remove pce and sms libmednahawk sources
This commit is contained in:
parent
3b533893a8
commit
354e12f290
|
@ -1,7 +0,0 @@
|
|||
On virtual power/reset, don't reset event system(timestamps such as lastts and such; but recalculating events based on new emulated register settings caused by the
|
||||
power/reset is good).
|
||||
|
||||
All Reset()/Power() functions should be passed a timestamp(of the reset/power event).
|
||||
|
||||
All users of the event system should initialize internal timestamp(lastts) to 0 on initialization, and only reset to 0 when its EndFrame() or ResetTS() or similar
|
||||
function is called.
|
|
@ -1,12 +0,0 @@
|
|||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MATH_OPTIMIZER_FLAGS@
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir) -I$(top_srcdir)/src/hw_cpu -I$(top_srcdir)/src/hw_misc -I$(top_srcdir)/src/hw_sound -I$(top_srcdir)/src/hw_video
|
||||
|
||||
noinst_LIBRARIES = libpce.a
|
||||
mednafen_SOURCES = vce.cpp pce.cpp input.cpp huc.cpp hes.cpp tsushin.cpp subhw.cpp mcgenjin.cpp
|
||||
mednafen_SOURCES += input/gamepad.cpp input/tsushinkb.cpp input/mouse.cpp
|
||||
if WANT_DEBUGGER
|
||||
mednafen_SOURCES += debug.cpp
|
||||
endif
|
||||
|
||||
libpce_a_SOURCES = $(mednafen_SOURCES)
|
|
@ -1,638 +0,0 @@
|
|||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
@WANT_DEBUGGER_TRUE@am__append_1 = debug.cpp
|
||||
subdir = src/pce
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
|
||||
$(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \
|
||||
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \
|
||||
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \
|
||||
$(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \
|
||||
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \
|
||||
$(top_srcdir)/m4/inttypes-pri.m4 \
|
||||
$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
|
||||
$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
|
||||
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
|
||||
$(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \
|
||||
$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
|
||||
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
AM_V_AR = $(am__v_AR_$(V))
|
||||
am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_AR_0 = @echo " AR " $@;
|
||||
AM_V_at = $(am__v_at_$(V))
|
||||
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_at_0 = @
|
||||
libpce_a_AR = $(AR) $(ARFLAGS)
|
||||
libpce_a_LIBADD =
|
||||
am__libpce_a_SOURCES_DIST = vce.cpp pce.cpp input.cpp huc.cpp hes.cpp \
|
||||
tsushin.cpp subhw.cpp mcgenjin.cpp input/gamepad.cpp \
|
||||
input/tsushinkb.cpp input/mouse.cpp debug.cpp
|
||||
am__dirstamp = $(am__leading_dot)dirstamp
|
||||
@WANT_DEBUGGER_TRUE@am__objects_1 = debug.$(OBJEXT)
|
||||
am__objects_2 = vce.$(OBJEXT) pce.$(OBJEXT) input.$(OBJEXT) \
|
||||
huc.$(OBJEXT) hes.$(OBJEXT) tsushin.$(OBJEXT) subhw.$(OBJEXT) \
|
||||
mcgenjin.$(OBJEXT) input/gamepad.$(OBJEXT) \
|
||||
input/tsushinkb.$(OBJEXT) input/mouse.$(OBJEXT) \
|
||||
$(am__objects_1)
|
||||
am_libpce_a_OBJECTS = $(am__objects_2)
|
||||
libpce_a_OBJECTS = $(am_libpce_a_OBJECTS)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_lt = $(am__v_lt_$(V))
|
||||
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_lt_0 = --silent
|
||||
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_CXX = $(am__v_CXX_$(V))
|
||||
am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CXX_0 = @echo " CXX " $@;
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
|
||||
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CXXLD = $(am__v_CXXLD_$(V))
|
||||
am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CXXLD_0 = @echo " CXXLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_$(V))
|
||||
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libpce_a_SOURCES)
|
||||
DIST_SOURCES = $(am__libpce_a_SOURCES_DIST)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ALLOCA = @ALLOCA@
|
||||
ALSA_CFLAGS = @ALSA_CFLAGS@
|
||||
ALSA_LIBS = @ALSA_LIBS@
|
||||
AMTAR = @AMTAR@
|
||||
AM_CFLAGS = @AM_CFLAGS@
|
||||
AM_CXXFLAGS = @AM_CXXFLAGS@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
CC = @CC@
|
||||
CCAS = @CCAS@
|
||||
CCASDEPMODE = @CCASDEPMODE@
|
||||
CCASFLAGS = @CCASFLAGS@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DATADIRNAME = @DATADIRNAME@
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MATH_OPTIMIZER_FLAGS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GBA_EXTRA_FLAGS = @GBA_EXTRA_FLAGS@
|
||||
GENCAT = @GENCAT@
|
||||
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||
GLIBC2 = @GLIBC2@
|
||||
GLIBC21 = @GLIBC21@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GMSGFMT_015 = @GMSGFMT_015@
|
||||
GREP = @GREP@
|
||||
HAVE_ASPRINTF = @HAVE_ASPRINTF@
|
||||
HAVE_NEWLOCALE = @HAVE_NEWLOCALE@
|
||||
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
|
||||
HAVE_SNPRINTF = @HAVE_SNPRINTF@
|
||||
HAVE_VISIBILITY = @HAVE_VISIBILITY@
|
||||
HAVE_WPRINTF = @HAVE_WPRINTF@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
INTLBISON = @INTLBISON@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTLOBJS = @INTLOBJS@
|
||||
INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@
|
||||
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
|
||||
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||
JACK_CFLAGS = @JACK_CFLAGS@
|
||||
JACK_LIBS = @JACK_LIBS@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@
|
||||
LIBCDIO_LIBS = @LIBCDIO_LIBS@
|
||||
LIBICONV = @LIBICONV@
|
||||
LIBINTL = @LIBINTL@
|
||||
LIBMULTITHREAD = @LIBMULTITHREAD@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPTH = @LIBPTH@
|
||||
LIBPTH_PREFIX = @LIBPTH_PREFIX@
|
||||
LIBS = @LIBS@
|
||||
LIBTHREAD = @LIBTHREAD@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBC = @LTLIBC@
|
||||
LTLIBICONV = @LTLIBICONV@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBMULTITHREAD = @LTLIBMULTITHREAD@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LTLIBPTH = @LTLIBPTH@
|
||||
LTLIBTHREAD = @LTLIBTHREAD@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MATH_OPTIMIZER_FLAGS = @MATH_OPTIMIZER_FLAGS@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MMX_CFLAGS = @MMX_CFLAGS@
|
||||
MSGFMT = @MSGFMT@
|
||||
MSGFMT_015 = @MSGFMT_015@
|
||||
MSGMERGE = @MSGMERGE@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
POSUB = @POSUB@
|
||||
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SNDFILE_CFLAGS = @SNDFILE_CFLAGS@
|
||||
SNDFILE_LIBS = @SNDFILE_LIBS@
|
||||
SNES_EXTRA_CXXFLAGS = @SNES_EXTRA_CXXFLAGS@
|
||||
SNES_EXTRA_FLAGS = @SNES_EXTRA_FLAGS@
|
||||
SSE2_CFLAGS = @SSE2_CFLAGS@
|
||||
SSE3_CFLAGS = @SSE3_CFLAGS@
|
||||
SSE_CFLAGS = @SSE_CFLAGS@
|
||||
STRIP = @STRIP@
|
||||
TRIO_CFLAGS = @TRIO_CFLAGS@
|
||||
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
WARNING_FLAGS = @WARNING_FLAGS@
|
||||
WINDRES = @WINDRES@
|
||||
WOE32 = @WOE32@
|
||||
WOE32DLL = @WOE32DLL@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
XMKMF = @XMKMF@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir) -I$(top_srcdir)/src/hw_cpu -I$(top_srcdir)/src/hw_misc -I$(top_srcdir)/src/hw_sound -I$(top_srcdir)/src/hw_video
|
||||
noinst_LIBRARIES = libpce.a
|
||||
mednafen_SOURCES = vce.cpp pce.cpp input.cpp huc.cpp hes.cpp \
|
||||
tsushin.cpp subhw.cpp mcgenjin.cpp input/gamepad.cpp \
|
||||
input/tsushinkb.cpp input/mouse.cpp $(am__append_1)
|
||||
libpce_a_SOURCES = $(mednafen_SOURCES)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pce/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/pce/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
input/$(am__dirstamp):
|
||||
@$(MKDIR_P) input
|
||||
@: > input/$(am__dirstamp)
|
||||
input/$(DEPDIR)/$(am__dirstamp):
|
||||
@$(MKDIR_P) input/$(DEPDIR)
|
||||
@: > input/$(DEPDIR)/$(am__dirstamp)
|
||||
input/gamepad.$(OBJEXT): input/$(am__dirstamp) \
|
||||
input/$(DEPDIR)/$(am__dirstamp)
|
||||
input/tsushinkb.$(OBJEXT): input/$(am__dirstamp) \
|
||||
input/$(DEPDIR)/$(am__dirstamp)
|
||||
input/mouse.$(OBJEXT): input/$(am__dirstamp) \
|
||||
input/$(DEPDIR)/$(am__dirstamp)
|
||||
libpce.a: $(libpce_a_OBJECTS) $(libpce_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libpce.a
|
||||
$(AM_V_AR)$(libpce_a_AR) libpce.a $(libpce_a_OBJECTS) $(libpce_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libpce.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
-rm -f input/gamepad.$(OBJEXT)
|
||||
-rm -f input/mouse.$(OBJEXT)
|
||||
-rm -f input/tsushinkb.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hes.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcgenjin.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pce.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subhw.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsushin.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vce.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/gamepad.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/mouse.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/tsushinkb.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.cpp.lo:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
-rm -f input/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f input/$(am__dirstamp)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR) input/$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR) input/$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLIBRARIES ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -1,80 +0,0 @@
|
|||
PRELIMINARY, hypothetical, do not use as-is!
|
||||
|
||||
---- Subtitle text format ----
|
||||
|
||||
*** 0
|
||||
|
||||
> 0:13:13->0:13:19
|
||||
This is text. Blah Blah Blah blah blah.
|
||||
BLAH BLAH BLAH BLAH BLAH BLAH BLAH.
|
||||
|
||||
> 0:15:49->0:16:01
|
||||
This is more text lalalalalalalalalalaladelalala
|
||||
|
||||
> 0:15:55->0:16:09
|
||||
This is temporal-overlapping text lalalalala.
|
||||
|
||||
|
||||
|
||||
---- Subtitle binary format ----
|
||||
|
||||
*** NOTES ***
|
||||
|
||||
Big-endian for multi-byte sequences
|
||||
|
||||
Glyphs are rendered top-bottom, left-right.
|
||||
|
||||
*** END NOTES ***
|
||||
|
||||
Header:
|
||||
|
||||
4 bytes - Magic ID: GN1S
|
||||
4 bytes - Number of glyphs
|
||||
4 bytes - Number of sequences
|
||||
4 bytes - (PADDING)
|
||||
|
||||
Palette data(256 * 2 bytes):
|
||||
2 bytes - 16-bit ARGB(4 bits for each component; A = 0 is fully transparent, A = 0xF is max opacity)
|
||||
[...]
|
||||
|
||||
Glyph table:
|
||||
Entry:
|
||||
4 bytes - Offset(from start of file to glyph data)
|
||||
1 byte - Width
|
||||
1 byte - Height (all glyphs should typically have the same height, unless you're using separate fonts
|
||||
or are including "graphics" data).
|
||||
2 bytes - (PADDING)
|
||||
|
||||
Sequence table:
|
||||
4 bytes - Offset(from start of file to start of sequence)
|
||||
|
||||
Glyph data:
|
||||
(Width * Height + 7) & ~ 7 bytes - Pixel data, with padding of zeroes at the end of each glyph to 8 byte boundary.
|
||||
Pixel data should be stored top-bottom, left right.
|
||||
[...]
|
||||
|
||||
Sequence data(actual subtitles):
|
||||
|
||||
0x00-0x1F - Control codes.
|
||||
0x0X - Add 4-bit signed X to draw x coordinate(-8 to 7), can be used for kerning.
|
||||
0x10 - RTS(or end sequence; doesn't affect video output)
|
||||
0x11 - NOP
|
||||
0x12 - Flip video buffer.
|
||||
|
||||
0x14 XX - Set draw X coordinate(0-255).
|
||||
0x15 YY - Set draw Y coordinate(0-255).
|
||||
0x16 XX - Add XX to X coordinate.
|
||||
0x17 YY - Add YY to Y coordinate.
|
||||
|
||||
0x18 TT TT - Wait for 16-bit time TTTT(relative to the last wait; or in other words, relative
|
||||
to the current time in the case that script processing takes zero time)
|
||||
|
||||
0x1C NN NN NN NN - JSR to specified sequence.
|
||||
|
||||
0x1F OO CC [PP PP] [...] - Set palette data starting at offset OO, count CC, followed by 16-bit * CC palette
|
||||
data.
|
||||
|
||||
0x20-0x7F - Glyphs 0x00 through 0x5F
|
||||
0x80-0xFF - Glyphs 0x60 through 0xFFFFFFFF
|
||||
Load up lower 7 bits, shift left by 7, and read next byte. End after D7 of the byte read is cleared.
|
||||
(Note: Last byte can be 0x00-0x1F, and should not be interpreted as a control code)
|
|
@ -1,70 +0,0 @@
|
|||
68K at 10.74 MHz
|
||||
|
||||
256x256 centered image(equivalent to 5.37 MHz VCE pixel clock) overlayed on PCE video output
|
||||
|
||||
FB RAM should run at 10.74MHz. FB RAM back buffer is automatically cleared after page swap. FB RAM writes
|
||||
in CPU address space are bytewise-conditional(each byte in the unit written is only written to the corresponding address
|
||||
in FB RAM if the byte to be written is != 0).
|
||||
|
||||
Palette:
|
||||
256x16
|
||||
|
||||
Format:
|
||||
ORGB(4-bit opacity, 4-bit R, 4-bit G, 4-bit B).
|
||||
|
||||
|
||||
68K Memory Map:
|
||||
|
||||
0x000000-0x0FFFFF - (R/W) 1MiB RAM
|
||||
0x100000-0x10FFFF - (W) Back framebuffer RAM
|
||||
0x110000-0x11FFFF - (W) Back framebuffer RAM (A0-A7, A8-A15 swap)
|
||||
0x200000-0x2001FF - (W) Palette RAM (16-bit access only)
|
||||
|
||||
I/O(16-bit accesses only):
|
||||
0x400000 - (R/W) Comm port 0 (dual-ported)
|
||||
0x400002 - (R/W) Comm port 1 (dual-ported)
|
||||
0x400004 - (R/W) Comm port 2 (dual-ported)
|
||||
0x400006 - (R/W) Comm port 3 (dual-ported)
|
||||
0x400100 - (R) Status
|
||||
D15 - 1 = Pending framebuffer swap
|
||||
D14 - 1 = Auto clear in progress(starts at vsync page swap; FB access prohibited)
|
||||
D7-D0 - vsync counter(increments when vsync starts)
|
||||
|
||||
(W) Control
|
||||
D8 - Write with 1 set to acknowledge interrupt 1
|
||||
D1 - 0 = overlay disabled, 1 = overlay enabled (only controls visibility, hardware otherwise
|
||||
runs as normal even when disabled)
|
||||
D0 - When written with 1, set a pending flag, to swap display framebuffer at next vsync
|
||||
start.
|
||||
|
||||
***PROCEDURE***
|
||||
Draw your screen to the (back) FB. Wait until program's vsync counter(derived from D7-D0)
|
||||
>= frame event time - 1. Write 0x3 to Control. Wait until D15 and D14
|
||||
of status are both 0. REPEAT.
|
||||
|
||||
0x800000-0xFFFFFF - (Mirrors of 1MiB RAM)
|
||||
|
||||
|
||||
HuC6280 Memory map:
|
||||
|
||||
Page 0xFE: - (R/W) 8KiB RAM(last ~1KiB is mirror of 0x1C00-0x1FEF)
|
||||
Page 0xFF:
|
||||
0x1C00-0x1FEF - (R/W) Scratch & patch RAM.
|
||||
0x1FF0-0x1FF3 - (R/W) Comm port 0 through 3 (dual-ported)
|
||||
0x1FF4 - (W) 1MIB RAM write offset 4-11
|
||||
0x1FF5 - (W) 1MiB RAM write offset 12-19 (and latch the 20-bit address(lower 4 bits are 0)).
|
||||
0x1FF6 - (W) 1MiB RAM write port. (address autoincrement)
|
||||
0x1FF7 - (W) Control (Initialized as if 0x03 were written, on reset).
|
||||
D0 - Master the 1MiB RAM when 1, halting the 68K's execution. Access to the write port when this bit is
|
||||
cleared will be ignored. Probably should do a few NOPs when going from 0->1 and writing to the
|
||||
write port.
|
||||
|
||||
D1 - When written with 1 in this bit, reset the 68K.
|
||||
|
||||
D2 - When written with 1 in this bit, request 68K interrupt 1.
|
||||
|
||||
D7 - 0 = overlay disabled, 1 = overlay enabled. (Same underlying bit as Control on 68K side)
|
||||
|
||||
Write the byte sequence:
|
||||
0x47, 0x6E, 0x31, 0x14, 0xB3, 0xEB, 0xEC, 0x2B, to any address in 0x1C00-0x1FFF to enable subtitle
|
||||
hardware functionality.
|
File diff suppressed because it is too large
Load Diff
|
@ -1,48 +0,0 @@
|
|||
#ifndef _PCE_DEBUG_H
|
||||
#define _PCE_DEBUG_H
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
|
||||
#include "pce_psg/pce_psg.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
void PCEDBG_SetCPUCallback(void (*callb)(uint32 PC));
|
||||
void PCEDBG_SetBPCallback(void (*callb)(uint32 PC));
|
||||
|
||||
void PCEDBG_FlushBreakPoints(int type);
|
||||
void PCEDBG_AddBreakPoint(int type, unsigned int A1, unsigned int A2, bool logical);
|
||||
|
||||
uint32 PCEDBG_MemPeek(uint32 A, unsigned int bsize, bool hl, bool logical);
|
||||
void PCEDBG_IRQ(int level);
|
||||
uint32 PCEDBG_GetVector(int level);
|
||||
void PCEDBG_Disassemble(uint32 &a, uint32 SpecialA, char *);
|
||||
uint32 PCEDBG_GetRegister(const std::string &name, std::string *special);
|
||||
void PCEDBG_SetRegister(const std::string &name, uint32 value);
|
||||
|
||||
void PCEDBG_CheckBP(int type, uint32 address, unsigned int len);
|
||||
|
||||
void PCEDBG_GetAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint8 *Buffer);
|
||||
void PCEDBG_PutAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer);
|
||||
|
||||
|
||||
void PCEDBG_SetLogFunc(void (*func)(const char *, const char *));
|
||||
|
||||
void PCEDBG_DoLog(const char *type, const char *format, ...);
|
||||
char *PCEDBG_ShiftJIS_to_UTF8(const uint16 sjc);
|
||||
|
||||
void PCEDBG_EnableUsageMap(bool);
|
||||
|
||||
extern bool PCE_LoggingOn;
|
||||
extern bool PCE_UsageMapOn;
|
||||
|
||||
extern DebuggerInfoStruct PCEDBGInfo;
|
||||
|
||||
bool PCEDBG_Init(bool sgx, PCE_PSG *psg);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,297 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "hes.h"
|
||||
#include "huc.h"
|
||||
#include "../cdrom/pcecd.h"
|
||||
#include "../player.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
static uint8 mpr_start[8];
|
||||
static uint8 IBP[0x100];
|
||||
static uint8 *rom = NULL, *rom_backup = NULL;
|
||||
|
||||
static uint8 CurrentSong;
|
||||
static bool bootstrap;
|
||||
static bool ROMWriteWarningGiven;
|
||||
|
||||
uint8 ReadIBP(unsigned int A)
|
||||
{
|
||||
if(!(A & 0x100))
|
||||
return(IBP[A & 0xFF]);
|
||||
|
||||
if(bootstrap && !PCE_InDebug)
|
||||
{
|
||||
memcpy(rom + 0x1FF0, rom_backup + 0x1FF0, 16);
|
||||
bootstrap = false;
|
||||
return(CurrentSong);
|
||||
}
|
||||
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(HESROMWrite)
|
||||
{
|
||||
if(bootstrap)
|
||||
{
|
||||
puts("Write during bootstrap?");
|
||||
return;
|
||||
}
|
||||
|
||||
rom[A] = V;
|
||||
//printf("%08x: %02x\n", A, V);
|
||||
if(!ROMWriteWarningGiven)
|
||||
{
|
||||
MDFN_printf(_("Warning: HES is writing to physical address %08x. Future warnings of this nature are temporarily disabled for this HES file.\n"), A);
|
||||
ROMWriteWarningGiven = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8 BootROM[16] = { 0xA9, 0xFF, 0x53, 0x01, 0xEA, 0xEA, 0xEA, 0xEA,
|
||||
0xEA, 0xEA, 0xEA, 0x4C, 0x00, 0x1C, 0xF0, 0xFF };
|
||||
|
||||
static DECLFR(HESROMRead)
|
||||
{
|
||||
return(rom[A]);
|
||||
}
|
||||
|
||||
int PCE_HESLoad(const uint8 *buf, uint32 size)
|
||||
{
|
||||
uint32 LoadAddr, LoadSize;
|
||||
uint32 CurPos;
|
||||
uint16 InitAddr;
|
||||
uint8 StartingSong;
|
||||
int TotalSongs;
|
||||
|
||||
if(size < 0x10)
|
||||
{
|
||||
MDFN_PrintError(_("HES header is too small."));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(memcmp(buf, "HESM", 4))
|
||||
{
|
||||
MDFN_PrintError(_("HES header magic is invalid."));
|
||||
return(0);
|
||||
}
|
||||
|
||||
InitAddr = MDFN_de16lsb(&buf[0x6]);
|
||||
|
||||
CurPos = 0x10;
|
||||
|
||||
if(!(rom = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!(rom_backup = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
MDFN_printf(_("HES Information:\n"));
|
||||
MDFN_indent(1);
|
||||
|
||||
StartingSong = buf[5];
|
||||
|
||||
MDFN_printf(_("Init address: 0x%04x\n"), InitAddr);
|
||||
MDFN_printf(_("Starting song: %d\n"), StartingSong + 1);
|
||||
|
||||
for(int x = 0; x < 8; x++)
|
||||
{
|
||||
mpr_start[x] = buf[0x8 + x];
|
||||
MDFN_printf("MPR%d: %02x\n", x, mpr_start[x]);
|
||||
}
|
||||
|
||||
memset(rom, 0, 0x88 * 8192);
|
||||
memset(rom_backup, 0, 0x88 * 8192);
|
||||
|
||||
while(CurPos < (size - 0x10))
|
||||
{
|
||||
LoadSize = MDFN_de32lsb(&buf[CurPos + 0x4]);
|
||||
LoadAddr = MDFN_de32lsb(&buf[CurPos + 0x8]);
|
||||
|
||||
//printf("Size: %08x(%d), Addr: %08x, La: %02x\n", LoadSize, LoadSize, LoadAddr, LoadAddr / 8192);
|
||||
MDFN_printf(_("Chunk load:\n"));
|
||||
MDFN_indent(1);
|
||||
MDFN_printf(_("File offset: 0x%08x\n"), CurPos);
|
||||
MDFN_printf(_("Load size: 0x%08x\n"), LoadSize);
|
||||
MDFN_printf(_("Load target address: 0x%08x\n"), LoadAddr);
|
||||
|
||||
CurPos += 0x10;
|
||||
|
||||
if(((uint64)LoadSize + CurPos) > size)
|
||||
{
|
||||
uint32 NewLoadSize = size - CurPos;
|
||||
|
||||
MDFN_printf(_("Warning: HES is trying to load more data than is present in the file(%u attempted, %u left)!\n"), LoadSize, NewLoadSize);
|
||||
|
||||
LoadSize = NewLoadSize;
|
||||
}
|
||||
|
||||
// 0x88 * 8192 = 0x110000
|
||||
if(((uint64)LoadAddr + LoadSize) > 0x110000)
|
||||
{
|
||||
MDFN_printf(_("Warning: HES is trying to load data past boundary.\n"));
|
||||
|
||||
if(LoadAddr >= 0x110000)
|
||||
break;
|
||||
|
||||
LoadSize = 0x110000 - LoadAddr;
|
||||
}
|
||||
MDFN_indent(-1);
|
||||
memcpy(rom + LoadAddr, &buf[CurPos], LoadSize);
|
||||
CurPos += LoadSize;
|
||||
}
|
||||
|
||||
memcpy(rom_backup, rom, 0x88 * 8192);
|
||||
|
||||
CurrentSong = StartingSong;
|
||||
TotalSongs = 256;
|
||||
uint8 *IBP_WR = IBP;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
*IBP_WR++ = 0xA9; // LDA (immediate)
|
||||
*IBP_WR++ = mpr_start[i];
|
||||
*IBP_WR++ = 0x53; // TAM
|
||||
*IBP_WR++ = 1 << i;
|
||||
}
|
||||
|
||||
// Initialize VDC registers.
|
||||
{
|
||||
// uint8 vdc_init_rom[] = { 0xA2, 0x0A, 0xA9, 0xFF, 0x8E, 0x00, 0x00, 0x8D, 0x02, 0x00, 0x8D, 0x03, 0x00, 0xE8, 0xE0, 0x0F, 0xD0, 0xF2 };
|
||||
// uint8 vdc_init_rom[] = { 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEa, 0xEA };
|
||||
|
||||
static const uint8 vdc_init_rom[] = {
|
||||
0xA2, 0x1F, 0x8E, 0x00,
|
||||
0x00, 0x9C, 0x02, 0x00,
|
||||
0x9C, 0x03, 0x00, 0xCA,
|
||||
0x10, 0xF4, 0x03, 0x0A,
|
||||
0x13, 0x02, 0x23, 0x02,
|
||||
0x03, 0x0B, 0x13, 0x1F,
|
||||
0x23, 0x04, 0x03, 0x0C,
|
||||
0x13, 0x02, 0x23, 0x0D,
|
||||
0x03, 0x0D, 0x13, 0xEF,
|
||||
0x23, 0x00, 0x03, 0x0E,
|
||||
0x13, 0x04, 0xA9, 0x04,
|
||||
0x8D, 0x00, 0x04
|
||||
};
|
||||
|
||||
memcpy(IBP_WR, vdc_init_rom, sizeof(vdc_init_rom));
|
||||
IBP_WR += sizeof(vdc_init_rom);
|
||||
}
|
||||
|
||||
|
||||
*IBP_WR++ = 0xAD; // LDA(absolute)
|
||||
*IBP_WR++ = 0x00; //
|
||||
*IBP_WR++ = 0x1D; //
|
||||
*IBP_WR++ = 0x20; // JSR
|
||||
*IBP_WR++ = InitAddr; // JSR target LSB
|
||||
*IBP_WR++ = InitAddr >> 8; // JSR target MSB
|
||||
*IBP_WR++ = 0x58; // CLI
|
||||
*IBP_WR++ = 0xCB; // (Mednafen Special)
|
||||
*IBP_WR++ = 0x80; // BRA
|
||||
*IBP_WR++ = 0xFD; // -3
|
||||
|
||||
assert((unsigned int)(IBP_WR - IBP) <= sizeof(IBP));
|
||||
|
||||
Player_Init(TotalSongs, "", "", ""); //NULL, NULL, NULL, NULL); //UTF8 **snames);
|
||||
|
||||
for(int x = 0; x < 0x88; x++)
|
||||
{
|
||||
if(x)
|
||||
HuCPU->SetFastRead(x, rom + x * 8192);
|
||||
HuCPU->SetReadHandler(x, HESROMRead);
|
||||
HuCPU->SetWriteHandler(x, HESROMWrite);
|
||||
}
|
||||
|
||||
ROMWriteWarningGiven = FALSE;
|
||||
|
||||
MDFN_indent(-1);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void HES_Reset(void)
|
||||
{
|
||||
memcpy(rom, rom_backup, 0x88 * 8192);
|
||||
memcpy(rom + 0x1FF0, BootROM, 16);
|
||||
bootstrap = true;
|
||||
}
|
||||
|
||||
void HES_Update(EmulateSpecStruct *espec, uint16 jp_data)
|
||||
{
|
||||
static uint8 last = 0;
|
||||
bool needreload = 0;
|
||||
|
||||
if((jp_data & 0x20) && !(last & 0x20))
|
||||
{
|
||||
CurrentSong++;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if((jp_data & 0x80) && !(last & 0x80))
|
||||
{
|
||||
CurrentSong--;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if((jp_data & 0x8) && !(last & 0x8))
|
||||
needreload = 1;
|
||||
|
||||
if((jp_data & 0x10) && !(last & 0x10))
|
||||
{
|
||||
CurrentSong += 10;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if((jp_data & 0x40) && !(last & 0x40))
|
||||
{
|
||||
CurrentSong -= 10;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
last = jp_data;
|
||||
|
||||
if(needreload)
|
||||
PCE_Power();
|
||||
|
||||
if(!espec->skip)
|
||||
Player_Draw(espec->surface, &espec->DisplayRect, CurrentSong, espec->SoundBuf, espec->SoundBufSize);
|
||||
}
|
||||
|
||||
void HES_Close(void)
|
||||
{
|
||||
if(rom)
|
||||
{
|
||||
MDFN_free(rom);
|
||||
rom = NULL;
|
||||
}
|
||||
|
||||
if(rom_backup)
|
||||
{
|
||||
MDFN_free(rom_backup);
|
||||
rom_backup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef __MDFN_PCE_HES_H
|
||||
#define __MDFN_PCE_HES_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
uint8 ReadIBP(unsigned int A);
|
||||
int PCE_HESLoad(const uint8 *buf, uint32 size);
|
||||
void HES_Reset(void);
|
||||
void HES_Update(EmulateSpecStruct *espec, uint16 jp_data);
|
||||
void HES_Close(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,620 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "huc.h"
|
||||
#include "../cdrom/pcecd.h"
|
||||
#include "arcade_card/arcade_card.h"
|
||||
#include "../md5.h"
|
||||
#include "../file.h"
|
||||
#include "../cdrom/cdromif.h"
|
||||
#include "../mempatcher.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "mcgenjin.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
static const uint8 BRAM_Init_String[8] = { 'H', 'U', 'B', 'M', 0x00, 0x88, 0x10, 0x80 }; //"HUBM\x00\x88\x10\x80";
|
||||
static bool BRAM_Disabled; // Cached at game load, don't remove this caching behavior or save game loss may result(if we ever get a GUI).
|
||||
|
||||
ArcadeCard *arcade_card = NULL;
|
||||
|
||||
extern Blip_Buffer huc_sbuf;
|
||||
static MCGenjin *mcg = NULL;
|
||||
static uint8 *HuCROM = NULL;
|
||||
static uint8 *ROMMap[0x100] = { NULL };
|
||||
|
||||
static bool IsPopulous;
|
||||
bool IsTsushin;
|
||||
bool PCE_IsCD;
|
||||
|
||||
static uint8 *TsushinRAM = NULL; // 0x8000
|
||||
static uint8 *PopRAM = NULL; // 0x8000
|
||||
static uint8 SaveRAM[2048];
|
||||
static uint8 *CDRAM = NULL; //262144;
|
||||
|
||||
static uint8 *SysCardRAM = NULL;
|
||||
|
||||
static void Cleanup(void)
|
||||
{
|
||||
if(HuCROM)
|
||||
{
|
||||
MDFN_free(HuCROM);
|
||||
HuCROM = NULL;
|
||||
}
|
||||
|
||||
if(PopRAM)
|
||||
{
|
||||
MDFN_free(PopRAM);
|
||||
PopRAM = NULL;
|
||||
}
|
||||
|
||||
if(TsushinRAM)
|
||||
{
|
||||
MDFN_free(TsushinRAM);
|
||||
TsushinRAM = NULL;
|
||||
}
|
||||
|
||||
if(CDRAM)
|
||||
{
|
||||
MDFN_free(CDRAM);
|
||||
CDRAM = NULL;
|
||||
}
|
||||
|
||||
if(SysCardRAM)
|
||||
{
|
||||
MDFN_free(SysCardRAM);
|
||||
SysCardRAM = NULL;
|
||||
}
|
||||
|
||||
if(arcade_card)
|
||||
{
|
||||
delete arcade_card;
|
||||
arcade_card = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static DECLFR(AC_PhysRead)
|
||||
{
|
||||
return(arcade_card->PhysRead(A, PCE_InDebug));
|
||||
}
|
||||
|
||||
static DECLFW(AC_PhysWrite)
|
||||
{
|
||||
return(arcade_card->PhysWrite(A, V));
|
||||
}
|
||||
|
||||
static DECLFW(SysCardRAMWrite)
|
||||
{
|
||||
SysCardRAM[A - 0x68 * 8192] = V;
|
||||
}
|
||||
|
||||
static DECLFR(SysCardRAMRead)
|
||||
{
|
||||
return(SysCardRAM[A - 0x68 * 8192]);
|
||||
}
|
||||
|
||||
static DECLFW(CDRAMWrite)
|
||||
{
|
||||
CDRAM[A - 0x80 * 8192] = V;
|
||||
}
|
||||
|
||||
static DECLFR(CDRAMRead)
|
||||
{
|
||||
return(CDRAM[A - 0x80 * 8192]);
|
||||
}
|
||||
|
||||
static DECLFR(SaveRAMRead)
|
||||
{
|
||||
if(BRAM_Disabled)
|
||||
return(0xFF);
|
||||
|
||||
if((!PCE_IsCD || PCECD_IsBRAMEnabled()) && (A & 8191) < 2048)
|
||||
return(SaveRAM[A & 2047]);
|
||||
else
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(SaveRAMWrite)
|
||||
{
|
||||
if(BRAM_Disabled)
|
||||
return;
|
||||
|
||||
if((!PCE_IsCD || PCECD_IsBRAMEnabled()) && (A & 8191) < 2048)
|
||||
SaveRAM[A & 2047] = V;
|
||||
}
|
||||
|
||||
static DECLFR(HuCRead)
|
||||
{
|
||||
return(ROMMap[A >> 13][A]);
|
||||
}
|
||||
|
||||
static DECLFW(HuCRAMWrite)
|
||||
{
|
||||
ROMMap[A >> 13][A] = V;
|
||||
}
|
||||
|
||||
static uint8 HuCSF2Latch;
|
||||
static uint8 HuCSF2BankMask;
|
||||
|
||||
static DECLFR(HuCSF2ReadLow)
|
||||
{
|
||||
return(HuCROM[A]);
|
||||
}
|
||||
|
||||
static DECLFR(HuCSF2Read)
|
||||
{
|
||||
return(HuCROM[(A & 0x7FFFF) + 0x80000 + (HuCSF2Latch & HuCSF2BankMask) * 0x80000 ]);
|
||||
}
|
||||
|
||||
static DECLFW(HuCSF2Write)
|
||||
{
|
||||
if((A & 0x1FF0) == 0x1FF0)
|
||||
HuCSF2Latch = A & 0xF;
|
||||
}
|
||||
|
||||
static DECLFR(MCG_ReadHandler)
|
||||
{
|
||||
return mcg->Read(HuCPU->Timestamp(), A);
|
||||
}
|
||||
|
||||
static DECLFW(MCG_WriteHandler)
|
||||
{
|
||||
mcg->Write(HuCPU->Timestamp(), A, V);
|
||||
}
|
||||
|
||||
int HuCLoad(const uint8 *data, uint32 len, uint32 crc32, bool DisableBRAM, SysCardType syscard)
|
||||
{
|
||||
const uint32 sf2_threshold = 2048 * 1024;
|
||||
uint32 m_len = (len + 8191) &~ 8191;
|
||||
bool sf2_mapper = FALSE;
|
||||
bool mcg_mapper = FALSE;
|
||||
bool UseBRAM = FALSE;
|
||||
|
||||
if(len >= 8192 && !memcmp(data + 0x1FD0, "MCGENJIN", 8))
|
||||
mcg_mapper = TRUE;
|
||||
|
||||
if(!syscard && m_len >= sf2_threshold && !mcg_mapper)
|
||||
{
|
||||
sf2_mapper = TRUE;
|
||||
|
||||
// Only used the "extended" SF2 mapper if it's considerably larger than the normal SF2 mapper size.
|
||||
if(m_len < (512 * 1024 * 6))
|
||||
m_len = 512 * 1024 * 5;
|
||||
else
|
||||
m_len = round_up_pow2(m_len - 512 * 1024) + 512 * 1024;
|
||||
|
||||
if(m_len > 8912896)
|
||||
{
|
||||
MDFN_PrintError(_("ROM image is too large!"));
|
||||
m_len = 8912896;
|
||||
}
|
||||
|
||||
HuCSF2BankMask = ((m_len - 512 * 1024) / (512 * 1024)) - 1;
|
||||
|
||||
//printf("%d %d, %02x\n", len, m_len, HuCSF2BankMask);
|
||||
}
|
||||
|
||||
IsPopulous = 0;
|
||||
PCE_IsCD = 0;
|
||||
|
||||
if(syscard == SYSCARD_NONE)
|
||||
{
|
||||
md5_context md5;
|
||||
md5.starts();
|
||||
md5.update(data, len);
|
||||
md5.finish(MDFNGameInfo->MD5);
|
||||
|
||||
MDFN_printf(_("ROM: %dKiB\n"), (len + 1023) / 1024);
|
||||
MDFN_printf(_("ROM CRC32: 0x%08x\n"), crc32);
|
||||
MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||
}
|
||||
|
||||
if(syscard != SYSCARD_NONE)
|
||||
{
|
||||
if(!(CDRAM = (uint8 *)MDFN_calloc(1, 8 * 8192, _("CD RAM"))))
|
||||
{
|
||||
Cleanup();
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(int x = 0x80; x < 0x88; x++)
|
||||
{
|
||||
ROMMap[x] = &CDRAM[(x - 0x80) * 8192] - x * 8192;
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
|
||||
HuCPU->SetReadHandler(x, CDRAMRead);
|
||||
HuCPU->SetWriteHandler(x, CDRAMWrite);
|
||||
}
|
||||
MDFNMP_AddRAM(8 * 8192, 0x80 * 8192, CDRAM);
|
||||
|
||||
UseBRAM = TRUE;
|
||||
}
|
||||
|
||||
if(mcg_mapper)
|
||||
{
|
||||
mcg = new MCGenjin(&huc_sbuf, data, len);
|
||||
|
||||
for(unsigned i = 0; i < 128; i++)
|
||||
{
|
||||
HuCPU->SetFastRead(i, NULL);
|
||||
HuCPU->SetReadHandler(i, MCG_ReadHandler);
|
||||
HuCPU->SetWriteHandler(i, MCG_WriteHandler);
|
||||
}
|
||||
|
||||
goto BRAM_Init; // SO EVIL YES EVVIIIIIL(FIXME)
|
||||
}
|
||||
|
||||
if(!(HuCROM = (uint8 *)MDFN_malloc(m_len, _("HuCard ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(HuCROM, 0xFF, m_len);
|
||||
memcpy(HuCROM, data, (m_len < len) ? m_len : len);
|
||||
|
||||
if(m_len == 0x60000)
|
||||
{
|
||||
for(int x = 0; x < 128; x++)
|
||||
{
|
||||
ROMMap[x] = &HuCROM[(x & 0x1F) * 8192] - x * 8192;
|
||||
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
}
|
||||
|
||||
for(int x = 64; x < 128; x++)
|
||||
{
|
||||
ROMMap[x] = &HuCROM[((x & 0xF) + 32) * 8192] - x * 8192;
|
||||
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
}
|
||||
}
|
||||
else if(m_len == 0x80000)
|
||||
{
|
||||
for(int x = 0; x < 64; x++)
|
||||
{
|
||||
ROMMap[x] = &HuCROM[(x & 0x3F) * 8192] - x * 8192;
|
||||
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
}
|
||||
for(int x = 64; x < 128; x++)
|
||||
{
|
||||
ROMMap[x] = &HuCROM[((x & 0x1F) + 32) * 8192] - x * 8192;
|
||||
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int x = 0; x < 128; x++)
|
||||
{
|
||||
uint8 bank = x % (m_len / 8192);
|
||||
|
||||
ROMMap[x] = &HuCROM[bank * 8192] - x * 8192;
|
||||
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
}
|
||||
}
|
||||
|
||||
if(syscard)
|
||||
{
|
||||
if(syscard == SYSCARD_3 || syscard == SYSCARD_ARCADE)
|
||||
{
|
||||
if(!(SysCardRAM = (uint8 *)MDFN_calloc(1, 24 * 8192, _("System Card RAM"))))
|
||||
{
|
||||
Cleanup();
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(int x = 0x68; x < 0x80; x++)
|
||||
{
|
||||
ROMMap[x] = &SysCardRAM[(x - 0x68) * 8192] - x * 8192;
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
|
||||
HuCPU->SetReadHandler(x, SysCardRAMRead);
|
||||
HuCPU->SetWriteHandler(x, SysCardRAMWrite);
|
||||
}
|
||||
MDFNMP_AddRAM(24 * 8192, 0x68 * 8192, SysCardRAM);
|
||||
}
|
||||
|
||||
if(syscard == SYSCARD_ARCADE)
|
||||
{
|
||||
try
|
||||
{
|
||||
arcade_card = new ArcadeCard();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
MDFN_PrintError(_("Error creating %s object: %s"), "ArcadeCard", e.what());
|
||||
Cleanup();
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(int x = 0x40; x < 0x44; x++)
|
||||
{
|
||||
ROMMap[x] = NULL;
|
||||
HuCPU->SetFastRead(x, NULL);
|
||||
|
||||
HuCPU->SetReadHandler(x, AC_PhysRead);
|
||||
HuCPU->SetWriteHandler(x, AC_PhysWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!memcmp(HuCROM + 0x1F26, "POPULOUS", strlen("POPULOUS")))
|
||||
{
|
||||
gzFile fp;
|
||||
|
||||
if(!(PopRAM = (uint8 *)MDFN_malloc(32768, _("Populous RAM"))))
|
||||
{
|
||||
Cleanup();
|
||||
return(0);
|
||||
}
|
||||
memset(PopRAM, 0xFF, 32768);
|
||||
if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, PopRAM, 32768);
|
||||
gzclose(fp);
|
||||
}
|
||||
IsPopulous = 1;
|
||||
MDFN_printf("Populous\n");
|
||||
for(int x = 0x40; x < 0x44; x++)
|
||||
{
|
||||
ROMMap[x] = &PopRAM[(x & 3) * 8192] - x * 8192;
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
HuCPU->SetWriteHandler(x, HuCRAMWrite);
|
||||
}
|
||||
MDFNMP_AddRAM(32768, 0x40 * 8192, PopRAM);
|
||||
}
|
||||
else if(crc32 == 0x34dc65c4) // Tsushin Booster
|
||||
{
|
||||
gzFile fp;
|
||||
|
||||
if(!(TsushinRAM = (uint8*)MDFN_malloc(0x8000, _("Tsushin Booster RAM"))))
|
||||
{
|
||||
Cleanup();
|
||||
return(0);
|
||||
}
|
||||
memset(TsushinRAM, 0xFF, 0x8000);
|
||||
|
||||
if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, TsushinRAM, 32768);
|
||||
gzclose(fp);
|
||||
}
|
||||
IsTsushin = 1;
|
||||
MDFN_printf("Tsushin Booster\n");
|
||||
for(int x = 0x88; x < 0x8C; x++)
|
||||
{
|
||||
ROMMap[x] = &TsushinRAM[(x & 3) * 8192] - x * 8192;
|
||||
HuCPU->SetFastRead(x, ROMMap[x] + x * 8192);
|
||||
|
||||
HuCPU->SetReadHandler(x, HuCRead);
|
||||
HuCPU->SetWriteHandler(x, HuCRAMWrite);
|
||||
}
|
||||
MDFNMP_AddRAM(32768, 0x88 * 8192, TsushinRAM);
|
||||
}
|
||||
else
|
||||
UseBRAM = TRUE;
|
||||
|
||||
// 0x1A558
|
||||
if(sf2_mapper)
|
||||
{
|
||||
for(int x = 0x20; x < 0x40; x++)
|
||||
HuCPU->SetReadHandler(x, HuCSF2ReadLow);
|
||||
for(int x = 0x40; x < 0x80; x++)
|
||||
{
|
||||
HuCPU->SetFastRead(x, NULL); // Make sure our reads go through our read function, and not a table lookup
|
||||
HuCPU->SetReadHandler(x, HuCSF2Read);
|
||||
}
|
||||
HuCPU->SetWriteHandler(0, HuCSF2Write);
|
||||
|
||||
MDFN_printf("Street Fighter 2 Mapper\n");
|
||||
HuCSF2Latch = 0;
|
||||
}
|
||||
} // end else to if(syscard)
|
||||
|
||||
BRAM_Init:
|
||||
|
||||
BRAM_Disabled = DisableBRAM;
|
||||
if(BRAM_Disabled)
|
||||
UseBRAM = false;
|
||||
|
||||
if(UseBRAM)
|
||||
{
|
||||
gzFile fp;
|
||||
|
||||
memset(SaveRAM, 0x00, 2048);
|
||||
memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet
|
||||
// in the CD BIOS screen.
|
||||
if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, SaveRAM, 2048);
|
||||
gzclose(fp);
|
||||
}
|
||||
|
||||
HuCPU->SetWriteHandler(0xF7, SaveRAMWrite);
|
||||
HuCPU->SetReadHandler(0xF7, SaveRAMRead);
|
||||
MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
bool IsBRAMUsed(void)
|
||||
{
|
||||
if(BRAM_Disabled)
|
||||
return(false);
|
||||
|
||||
if(memcmp(SaveRAM, BRAM_Init_String, 8)) // HUBM string is modified/missing
|
||||
return(1);
|
||||
|
||||
for(int x = 8; x < 2048; x++)
|
||||
if(SaveRAM[x]) return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int HuC_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(PopRAM, IsPopulous ? 32768 : 0),
|
||||
SFARRAY(TsushinRAM, IsTsushin ? 32768 : 0),
|
||||
SFARRAY(SaveRAM, (IsPopulous || IsTsushin || BRAM_Disabled) ? 0 : 2048),
|
||||
SFARRAY(CDRAM, CDRAM ? (8192 * 8) : 0),
|
||||
SFARRAY(SysCardRAM, SysCardRAM ? (8192 * 24) : 0),
|
||||
SFVAR(HuCSF2Latch),
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "HuC");
|
||||
|
||||
if(load)
|
||||
HuCSF2Latch &= 0xF;
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
if(arcade_card)
|
||||
ret &= arcade_card->StateAction(sm, load, data_only);
|
||||
|
||||
ret &= PCECD_StateAction(sm, load, data_only);
|
||||
}
|
||||
|
||||
if(mcg)
|
||||
ret &= mcg->StateAction(sm, load, data_only);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void HuCClose(void)
|
||||
{
|
||||
if(mcg)
|
||||
{
|
||||
for(unsigned i = 0; i < mcg->GetNVPDC(); i++)
|
||||
{
|
||||
uint32 nvs = mcg->GetNVSize(i);
|
||||
|
||||
if(nvs)
|
||||
{
|
||||
char buf[32];
|
||||
std::vector<uint8> tmp_buf;
|
||||
|
||||
tmp_buf.resize(nvs);
|
||||
|
||||
mcg->ReadNV(i, &tmp_buf[0], 0, tmp_buf.size());
|
||||
|
||||
trio_snprintf(buf, sizeof(buf), "mg%d", i);
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, buf).c_str(), 6, &tmp_buf[0], tmp_buf.size());
|
||||
}
|
||||
}
|
||||
|
||||
delete mcg;
|
||||
mcg = NULL;
|
||||
}
|
||||
|
||||
if(IsPopulous)
|
||||
{
|
||||
if(PopRAM)
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, PopRAM, 32768);
|
||||
}
|
||||
}
|
||||
else if(IsTsushin)
|
||||
{
|
||||
if(TsushinRAM)
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, TsushinRAM, 32768);
|
||||
MDFN_free(TsushinRAM);
|
||||
TsushinRAM = NULL;
|
||||
}
|
||||
}
|
||||
else if(!BRAM_Disabled && IsBRAMUsed())
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, SaveRAM, 2048);
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void HuC_EndFrame(int32 timestamp)
|
||||
{
|
||||
if(mcg)
|
||||
mcg->EndFrame(timestamp);
|
||||
}
|
||||
|
||||
|
||||
void HuC_Power(void)
|
||||
{
|
||||
if(CDRAM)
|
||||
memset(CDRAM, 0x00, 8 * 8192);
|
||||
|
||||
if(SysCardRAM)
|
||||
memset(SysCardRAM, 0x00, 24 * 8192);
|
||||
|
||||
if(arcade_card)
|
||||
arcade_card->Power();
|
||||
|
||||
HuCSF2Latch = 0;
|
||||
|
||||
if(mcg)
|
||||
mcg->Power();
|
||||
}
|
||||
|
||||
|
||||
bool HuC_IsBRAMAvailable(void)
|
||||
{
|
||||
if(IsPopulous)
|
||||
return(false);
|
||||
|
||||
if(IsTsushin)
|
||||
return(false);
|
||||
|
||||
if(BRAM_Disabled)
|
||||
return(false);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
uint8 HuC_PeekBRAM(uint32 A)
|
||||
{
|
||||
assert(HuC_IsBRAMAvailable());
|
||||
|
||||
return(SaveRAM[A & 2047]);
|
||||
}
|
||||
|
||||
void HuC_PokeBRAM(uint32 A, uint8 V)
|
||||
{
|
||||
assert(HuC_IsBRAMAvailable());
|
||||
|
||||
SaveRAM[A & 2047] = V;
|
||||
}
|
||||
|
||||
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef __MDFN_PCE_HUC_H
|
||||
#define __MDFN_PCE_HUC_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SYSCARD_NONE = 0,
|
||||
SYSCARD_1,
|
||||
SYSCARD_2,
|
||||
SYSCARD_3,
|
||||
SYSCARD_ARCADE // 3.0 + extras
|
||||
} SysCardType;
|
||||
|
||||
int HuCLoad(const uint8 *data, uint32 len, uint32 crc32, bool DisableBRAM = false, SysCardType syscard = SYSCARD_NONE);
|
||||
|
||||
void HuC_EndFrame(int32 timestamp);
|
||||
|
||||
void HuCClose(void);
|
||||
int HuC_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void HuC_Power(void);
|
||||
|
||||
DECLFR(PCE_ACRead);
|
||||
DECLFW(PCE_ACWrite);
|
||||
|
||||
extern bool PCE_IsCD;
|
||||
extern bool IsTsushin;
|
||||
|
||||
// Debugger support functions.
|
||||
bool HuC_IsBRAMAvailable(void);
|
||||
uint8 HuC_PeekBRAM(uint32 A);
|
||||
void HuC_PokeBRAM(uint32 A, uint8 V);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,402 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "input.h"
|
||||
#include "huc.h"
|
||||
|
||||
#include "vce.h" // For debugging only(but not the debugger :b)
|
||||
|
||||
#include "input/gamepad.h"
|
||||
#include "input/mouse.h"
|
||||
#include "input/tsushinkb.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
PCEINPUT_NONE = 0,
|
||||
PCEINPUT_GAMEPAD = 1,
|
||||
PCEINPUT_MOUSE = 2,
|
||||
PCEINPUT_TSUSHINKB = 3,
|
||||
};
|
||||
|
||||
//PCE_Input_Device::PCE_Input_Device(int which)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
PCE_Input_Device::~PCE_Input_Device()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PCE_Input_Device::Power(int32 timestamp)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PCE_Input_Device::AdjustTS(int32 delta)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PCE_Input_Device::Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8 PCE_Input_Device::Read(int32 timestamp)
|
||||
{
|
||||
return(0xF);
|
||||
}
|
||||
|
||||
void PCE_Input_Device::Update(const void *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int PCE_Input_Device::StateAction(StateMem *sm, int load, int data_only, const char *section_name)
|
||||
{
|
||||
return(1);
|
||||
}
|
||||
|
||||
static PCE_Input_Device *devices[5] = { NULL };
|
||||
static bool MultiTapEnabled = TRUE;
|
||||
static int InputTypes[5] = { 0 };
|
||||
static uint8 *data_ptr[5];
|
||||
static bool SEL, CLR;
|
||||
static uint8 read_index = 0;
|
||||
|
||||
static void RemakeDevices(int which = -1)
|
||||
{
|
||||
int s = 0;
|
||||
int e = 5;
|
||||
|
||||
if(which != -1)
|
||||
{
|
||||
s = which;
|
||||
e = which + 1;
|
||||
}
|
||||
|
||||
for(int i = s; i < e; i++)
|
||||
{
|
||||
if(devices[i])
|
||||
delete devices[i];
|
||||
devices[i] = NULL;
|
||||
|
||||
switch(InputTypes[i])
|
||||
{
|
||||
default:
|
||||
case PCEINPUT_NONE: break;
|
||||
case PCEINPUT_GAMEPAD: devices[i] = PCEINPUT_MakeGamepad(i); break;
|
||||
case PCEINPUT_MOUSE: devices[i] = PCEINPUT_MakeMouse(); break;
|
||||
case PCEINPUT_TSUSHINKB: devices[i] = PCEINPUT_MakeTsushinKB(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SyncSettings(void);
|
||||
|
||||
void PCEINPUT_SettingChanged(const char *name)
|
||||
{
|
||||
SyncSettings();
|
||||
}
|
||||
|
||||
void PCEINPUT_Init(void)
|
||||
{
|
||||
SyncSettings();
|
||||
RemakeDevices();
|
||||
}
|
||||
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr)
|
||||
{
|
||||
assert(port < 5);
|
||||
|
||||
if(!strcasecmp(type, "gamepad"))
|
||||
InputTypes[port] = PCEINPUT_GAMEPAD;
|
||||
else if(!strcasecmp(type, "mouse"))
|
||||
InputTypes[port] = PCEINPUT_MOUSE;
|
||||
else if(!strcasecmp(type, "tsushinkb"))
|
||||
InputTypes[port] = PCEINPUT_TSUSHINKB;
|
||||
else
|
||||
InputTypes[port] = PCEINPUT_NONE;
|
||||
|
||||
data_ptr[port] = (uint8 *)ptr;
|
||||
|
||||
RemakeDevices(port);
|
||||
}
|
||||
|
||||
uint16 INPUT_HESHack(void)
|
||||
{
|
||||
uint16 ret = 0;
|
||||
|
||||
switch(InputTypes[0])
|
||||
{
|
||||
case PCEINPUT_GAMEPAD: ret = MDFN_de16lsb(data_ptr[0]);
|
||||
break;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void INPUT_Frame(void)
|
||||
{
|
||||
for(int i = 0; i < 5; i++)
|
||||
if(devices[i])
|
||||
devices[i]->Update(data_ptr[i]);
|
||||
}
|
||||
|
||||
void INPUT_FixTS(int32 timestamp)
|
||||
{
|
||||
for(int i = 0; i < 5; i++)
|
||||
if(devices[i])
|
||||
devices[i]->AdjustTS(-timestamp);
|
||||
}
|
||||
|
||||
static INLINE uint8 RealPortRead(int32 timestamp, int which)
|
||||
{
|
||||
uint8 ret = 0xF;
|
||||
|
||||
//printf("RealInputRead: %d %d\n", which, timestamp);
|
||||
if(devices[which])
|
||||
ret = devices[which]->Read(timestamp);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static INLINE void RealPortWrite(int32 timestamp, int which, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR)
|
||||
{
|
||||
if(devices[which])
|
||||
devices[which]->Write(timestamp, old_SEL, new_SEL, old_CLR, new_CLR);
|
||||
}
|
||||
|
||||
static INLINE uint8 MultiTapRead(int32 timestamp)
|
||||
{
|
||||
uint8 ret = 0xF;
|
||||
|
||||
if(read_index > 4)
|
||||
ret = 0;
|
||||
else
|
||||
ret = RealPortRead(timestamp, read_index);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static INLINE void MultiTapWrite(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR)
|
||||
{
|
||||
for(int i = 0; i < 5; i++)
|
||||
RealPortWrite(timestamp, i, old_SEL, new_SEL, old_CLR, new_CLR);
|
||||
|
||||
// SEL held high, CLR transitions from 0->1, reset counter.
|
||||
// Scratch that, only check if SEL is high on the write that changes CLR from 0 to 1, to fix "Strip Fighter".
|
||||
if(/*old_SEL &&*/ new_SEL && !old_CLR && new_CLR)
|
||||
{
|
||||
//puts("Reset read index");
|
||||
|
||||
read_index = 0;
|
||||
}
|
||||
// CLR held low, SEL transitions from 0->1, increment counter.
|
||||
else if(!old_CLR && !new_CLR && !old_SEL && new_SEL)
|
||||
{
|
||||
//puts("Increment read index");
|
||||
if(read_index < 255)
|
||||
read_index++;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 INPUT_Read(int32 timestamp, unsigned int A)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
//{
|
||||
// extern VCE *vce;
|
||||
// printf("Input Read: %04x, %d\n", A, vce->GetScanlineNo());
|
||||
//}
|
||||
|
||||
if(MultiTapEnabled && InputTypes[0] != PCEINPUT_TSUSHINKB)
|
||||
ret = MultiTapRead(timestamp);
|
||||
else
|
||||
ret = RealPortRead(timestamp, 0);
|
||||
|
||||
//printf("Input read: %04x, %02x\n",A,ret);
|
||||
|
||||
if(!PCE_IsCD)
|
||||
ret |= 0x80; // Set when CDROM is not attached
|
||||
|
||||
//ret |= 0x40; // PC Engine if set, TG16 if clear. Let's leave it clear, PC Engine games don't seem to mind if it's clear, but TG16 games barf if it's set.
|
||||
|
||||
ret |= 0x30; // Always-set?
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void INPUT_Write(int32 timestamp, unsigned int A, uint8 V)
|
||||
{
|
||||
//printf("Input Write: %04x, %02x\n", A, V);
|
||||
bool new_SEL = V & 0x1;
|
||||
bool new_CLR = V & 0x2;
|
||||
|
||||
if(MultiTapEnabled)
|
||||
MultiTapWrite(timestamp, SEL, new_SEL, CLR, new_CLR);
|
||||
else
|
||||
RealPortWrite(timestamp, 0, SEL, new_SEL, CLR, new_CLR);
|
||||
|
||||
SEL = new_SEL;
|
||||
CLR = new_CLR;
|
||||
}
|
||||
|
||||
void PCEINPUT_Power(int32 timestamp)
|
||||
{
|
||||
read_index = 0;
|
||||
SEL = 0;
|
||||
CLR = 0;
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
if(devices[i])
|
||||
devices[i]->Power(timestamp);
|
||||
}
|
||||
|
||||
int INPUT_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(SEL),
|
||||
SFVAR(CLR),
|
||||
SFVAR(read_index),
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "JOY");
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
if(devices[i])
|
||||
{
|
||||
char sn[8];
|
||||
snprintf(sn, 8, "INP%d", i);
|
||||
ret &= devices[i]->StateAction(sm, load, data_only, sn);
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// If we add more devices to these arrays before "gamepad", REMEMBER TO UPDATE the hackish array indexing in the SyncSettings() function
|
||||
// below.
|
||||
|
||||
static InputDeviceInfoStruct InputDeviceInfo[] =
|
||||
{
|
||||
// None
|
||||
{
|
||||
"none",
|
||||
"none",
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
|
||||
// Gamepad
|
||||
{
|
||||
"gamepad",
|
||||
"Gamepad",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(PCE_GamepadIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
PCE_GamepadIDII,
|
||||
},
|
||||
|
||||
// Mouse
|
||||
{
|
||||
"mouse",
|
||||
"Mouse",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(PCE_MouseIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
PCE_MouseIDII,
|
||||
},
|
||||
};
|
||||
|
||||
static InputDeviceInfoStruct InputDeviceInfoPort1[] =
|
||||
{
|
||||
// None
|
||||
{
|
||||
"none",
|
||||
"none",
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
|
||||
// Gamepad
|
||||
{
|
||||
"gamepad",
|
||||
"Gamepad",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(PCE_GamepadIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
PCE_GamepadIDII,
|
||||
},
|
||||
|
||||
// Mouse
|
||||
{
|
||||
"mouse",
|
||||
"Mouse",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(PCE_MouseIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
PCE_MouseIDII,
|
||||
},
|
||||
|
||||
// Tsushin Keyboard
|
||||
{
|
||||
"tsushinkb",
|
||||
"Tsushin Keyboard",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(PCE_TsushinKBIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
PCE_TsushinKBIDII,
|
||||
},
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct PortInfo[] =
|
||||
{
|
||||
{ "port1", "Port 1", sizeof(InputDeviceInfoPort1) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPort1, "gamepad" },
|
||||
{ "port2", "Port 2", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port3", "Port 3", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port4", "Port 4", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port5", "Port 5", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
};
|
||||
|
||||
InputInfoStruct PCEInputInfo =
|
||||
{
|
||||
sizeof(PortInfo) / sizeof(InputPortInfoStruct),
|
||||
PortInfo
|
||||
};
|
||||
|
||||
static void SyncSettings(void)
|
||||
{
|
||||
MDFNGameInfo->mouse_sensitivity = MDFN_GetSettingF("pce.mouse_sensitivity");
|
||||
InputDeviceInfo[1].IDII = MDFN_GetSettingB("pce.disable_softreset") ? PCE_GamepadIDII_DSR : PCE_GamepadIDII;
|
||||
MultiTapEnabled = MDFN_GetSettingB("pce.input.multitap");
|
||||
}
|
||||
|
||||
};
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef __PCE_INPUT_H
|
||||
#define __PCE_INPUT_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
class PCE_Input_Device
|
||||
{
|
||||
public:
|
||||
// PCE_Input_Device(int which); // "which" is advisory and only should be used in status messages.
|
||||
virtual ~PCE_Input_Device();
|
||||
virtual void AdjustTS(int32 delta);
|
||||
virtual void Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR);
|
||||
virtual uint8 Read(int32 timestamp);
|
||||
virtual void Power(int32 timestamp);
|
||||
virtual void Update(const void *data);
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *section_name);
|
||||
};
|
||||
|
||||
void PCEINPUT_Power(int32 timestamp);
|
||||
void PCEINPUT_Init(void);
|
||||
void PCEINPUT_SettingChanged(const char *name);
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr);
|
||||
uint8 INPUT_Read(int32 timestamp, unsigned int A);
|
||||
void INPUT_Write(int32 timestamp, unsigned int A, uint8 V);
|
||||
void INPUT_Frame(void);
|
||||
int INPUT_StateAction(StateMem *sm, int load, int data_only);
|
||||
extern InputInfoStruct PCEInputInfo;
|
||||
void INPUT_FixTS(int32 timestamp);
|
||||
|
||||
uint16 INPUT_HESHack(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,162 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../pce.h"
|
||||
#include "../input.h"
|
||||
#include "gamepad.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
class PCE_Input_Gamepad : public PCE_Input_Device
|
||||
{
|
||||
public:
|
||||
PCE_Input_Gamepad(int which);
|
||||
virtual void Power(int32 timestamp);
|
||||
virtual void Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR);
|
||||
virtual uint8 Read(int32 timestamp);
|
||||
virtual void Update(const void *data);
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *section_name);
|
||||
|
||||
|
||||
private:
|
||||
bool SEL, CLR;
|
||||
uint16 buttons;
|
||||
bool AVPad6Which;
|
||||
bool AVPad6Enabled;
|
||||
int which_this;
|
||||
};
|
||||
|
||||
PCE_Input_Gamepad::PCE_Input_Gamepad(int which)
|
||||
{
|
||||
which_this = which;
|
||||
Power(0); // FIXME?
|
||||
}
|
||||
|
||||
void PCE_Input_Gamepad::Power(int32 timestamp)
|
||||
{
|
||||
SEL = 0;
|
||||
CLR = 0;
|
||||
buttons = 0;
|
||||
AVPad6Which = 0;
|
||||
AVPad6Enabled = 0;
|
||||
}
|
||||
|
||||
void PCE_Input_Gamepad::Update(const void *data)
|
||||
{
|
||||
uint16 new_data = MDFN_de16lsb((uint8 *)data);
|
||||
|
||||
if((new_data & 0x1000) && !(buttons & 0x1000))
|
||||
{
|
||||
AVPad6Enabled = !AVPad6Enabled;
|
||||
MDFN_DispMessage("%d-button mode selected for pad %d", AVPad6Enabled ? 6 : 2, which_this + 1);
|
||||
}
|
||||
|
||||
buttons = new_data;
|
||||
}
|
||||
|
||||
uint8 PCE_Input_Gamepad::Read(int32 timestamp)
|
||||
{
|
||||
uint8 ret = 0xF;
|
||||
|
||||
if(AVPad6Which && AVPad6Enabled)
|
||||
{
|
||||
if(SEL)
|
||||
ret ^= 0xF;
|
||||
else
|
||||
ret ^= (buttons >> 8) & 0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(SEL)
|
||||
ret ^= (buttons >> 4) & 0x0F;
|
||||
else
|
||||
ret ^= buttons & 0x0F;
|
||||
}
|
||||
|
||||
//if(CLR)
|
||||
// ret = 0;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void PCE_Input_Gamepad::Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR)
|
||||
{
|
||||
SEL = new_SEL;
|
||||
CLR = new_CLR;
|
||||
|
||||
//if(old_SEL && new_SEL && old_CLR && !new_CLR)
|
||||
if(!old_SEL && new_SEL)
|
||||
AVPad6Which = !AVPad6Which;
|
||||
}
|
||||
|
||||
int PCE_Input_Gamepad::StateAction(StateMem *sm, int load, int data_only, const char *section_name)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(SEL),
|
||||
SFVAR(CLR),
|
||||
SFVAR(buttons),
|
||||
SFVAR(AVPad6Which),
|
||||
SFVAR(AVPad6Enabled),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// GamepadIDII and GamepadIDII_DSR must be EXACTLY the same except for the RUN+SELECT exclusion in the latter.
|
||||
const InputDeviceInputInfoStruct PCE_GamepadIDII[0xD] =
|
||||
{
|
||||
{ "i", "I", 12, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "ii", "II", 11, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, NULL },
|
||||
{ "run", "RUN", 5, IDIT_BUTTON, NULL },
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "iii", "III", 10, IDIT_BUTTON, NULL },
|
||||
{ "iv", "IV", 7, IDIT_BUTTON, NULL },
|
||||
{ "v", "V", 8, IDIT_BUTTON, NULL },
|
||||
{ "vi", "VI", 9, IDIT_BUTTON, NULL },
|
||||
{ "mode_select", "2/6 Mode Select", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
const InputDeviceInputInfoStruct PCE_GamepadIDII_DSR[0xD] =
|
||||
{
|
||||
{ "i", "I", 12, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "ii", "II", 11, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, "run" },
|
||||
{ "run", "RUN", 5, IDIT_BUTTON, "select" },
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "iii", "III", 10, IDIT_BUTTON, NULL },
|
||||
{ "iv", "IV", 7, IDIT_BUTTON, NULL },
|
||||
{ "v", "V", 8, IDIT_BUTTON, NULL },
|
||||
{ "vi", "VI", 9, IDIT_BUTTON, NULL },
|
||||
{ "mode_select", "2/6 Mode Select", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
PCE_Input_Device *PCEINPUT_MakeGamepad(int which)
|
||||
{
|
||||
return(new PCE_Input_Gamepad(which));
|
||||
}
|
||||
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef __PCE_INPUT_GAMEPAD_H
|
||||
#define __PCE_INPUT_GAMEPAD_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
extern const InputDeviceInputInfoStruct PCE_GamepadIDII[0xD];
|
||||
extern const InputDeviceInputInfoStruct PCE_GamepadIDII_DSR[0xD];
|
||||
|
||||
PCE_Input_Device *PCEINPUT_MakeGamepad(int which);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,171 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../pce.h"
|
||||
#include "../input.h"
|
||||
#include "mouse.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
class PCE_Input_Mouse : public PCE_Input_Device
|
||||
{
|
||||
public:
|
||||
PCE_Input_Mouse();
|
||||
virtual void Power(int32 timestamp);
|
||||
|
||||
virtual void AdjustTS(int32 delta);
|
||||
virtual void Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR);
|
||||
virtual uint8 Read(int32 timestamp);
|
||||
virtual void Update(const void *data);
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *section_name);
|
||||
|
||||
private:
|
||||
bool SEL, CLR;
|
||||
int64 mouse_last_meow;
|
||||
|
||||
int32 mouse_x, mouse_y;
|
||||
uint8 pce_mouse_button;
|
||||
uint8 mouse_index;
|
||||
|
||||
|
||||
uint16 mouse_shifter;
|
||||
};
|
||||
|
||||
void PCE_Input_Mouse::Power(int32 timestamp)
|
||||
{
|
||||
SEL = CLR = 0;
|
||||
mouse_last_meow = 0;
|
||||
mouse_x = mouse_y = 0;
|
||||
pce_mouse_button = 0;
|
||||
mouse_index = 0;
|
||||
mouse_shifter = 0;
|
||||
}
|
||||
|
||||
PCE_Input_Mouse::PCE_Input_Mouse()
|
||||
{
|
||||
Power(0);
|
||||
}
|
||||
|
||||
void PCE_Input_Mouse::Update(const void *data)
|
||||
{
|
||||
//puts("Frame");
|
||||
uint8 *data_ptr = (uint8 *)data;
|
||||
|
||||
mouse_x += (int32)MDFN_de32lsb(data_ptr + 0);
|
||||
mouse_y += (int32)MDFN_de32lsb(data_ptr + 4);
|
||||
pce_mouse_button = *(uint8 *)(data_ptr + 8);
|
||||
}
|
||||
|
||||
void PCE_Input_Mouse::AdjustTS(int32 delta)
|
||||
{
|
||||
//printf("Adjust: %d\n", delta);
|
||||
mouse_last_meow += delta;
|
||||
}
|
||||
|
||||
void PCE_Input_Mouse::Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR)
|
||||
{
|
||||
//printf("Write: %d old_SEL=%d, new_SEL=%d, old_CLR=%d, new_CLR=%d\n", timestamp, old_SEL, new_SEL, old_CLR, new_CLR);
|
||||
if(!old_CLR && new_CLR)
|
||||
{
|
||||
//printf("%lld\n", (int64)timestamp - mouse_last_meow);
|
||||
if(((int64)timestamp - mouse_last_meow) > 10000 * 3)
|
||||
{
|
||||
mouse_last_meow = timestamp;
|
||||
|
||||
int32 rel_x = (int32)((0-mouse_x));
|
||||
int32 rel_y = (int32)((0-mouse_y));
|
||||
|
||||
if(rel_x < -127) rel_x = -127;
|
||||
if(rel_x > 127) rel_x = 127;
|
||||
if(rel_y < -127) rel_y = -127;
|
||||
if(rel_y > 127) rel_y = 127;
|
||||
|
||||
mouse_shifter = ((rel_x & 0xF0) >> 4) | ((rel_x & 0x0F) << 4);
|
||||
mouse_shifter |= (((rel_y & 0xF0) >> 4) | ((rel_y & 0x0F) << 4)) << 8;
|
||||
|
||||
mouse_x += (int32)(rel_x);
|
||||
mouse_y += (int32)(rel_y);
|
||||
|
||||
//printf("Latch: %d %d, %04x\n", rel_x, rel_y, mouse_shifter);
|
||||
}
|
||||
else
|
||||
{
|
||||
//puts("Shift");
|
||||
mouse_shifter >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
SEL = new_SEL;
|
||||
CLR = new_CLR;
|
||||
}
|
||||
|
||||
uint8 PCE_Input_Mouse::Read(int32 timestamp)
|
||||
{
|
||||
uint8 ret = 0xF;
|
||||
|
||||
//printf("Read: %d\n", timestamp);
|
||||
|
||||
if(SEL)
|
||||
{
|
||||
ret = (mouse_shifter & 0xF);
|
||||
//printf("Read: %02x\n", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret ^= pce_mouse_button & 0xF;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int PCE_Input_Mouse::StateAction(StateMem *sm, int load, int data_only, const char *section_name)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(SEL),
|
||||
SFVAR(CLR),
|
||||
SFVAR(mouse_last_meow),
|
||||
SFVAR(mouse_x),
|
||||
SFVAR(mouse_y),
|
||||
SFVAR(pce_mouse_button),
|
||||
SFVAR(mouse_index),
|
||||
SFVAR(mouse_shifter),
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
const InputDeviceInputInfoStruct PCE_MouseIDII[0x6] =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS_REL },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL },
|
||||
{ "right", "Right Button", 3, IDIT_BUTTON, NULL },
|
||||
{ "left", "Left Button", 2, IDIT_BUTTON, NULL },
|
||||
{ "select", "SELECT", 0, IDIT_BUTTON, NULL },
|
||||
{ "run", "RUN", 1, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
PCE_Input_Device *PCEINPUT_MakeMouse(void)
|
||||
{
|
||||
return(new PCE_Input_Mouse());
|
||||
}
|
||||
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef __PCE_INPUT_MOUSE_H
|
||||
#define __PCE_INPUT_MOUSE_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
extern const InputDeviceInputInfoStruct PCE_MouseIDII[0x6];
|
||||
|
||||
PCE_Input_Device *PCEINPUT_MakeMouse(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,304 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../pce.h"
|
||||
#include "../input.h"
|
||||
#include "tsushinkb.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
class PCE_Input_TsushinKB : public PCE_Input_Device
|
||||
{
|
||||
public:
|
||||
|
||||
PCE_Input_TsushinKB();
|
||||
|
||||
virtual void Power(int32 timestamp);
|
||||
virtual void Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR);
|
||||
virtual uint8 Read(int32 timestamp);
|
||||
virtual void Update(const void *data);
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *section_name);
|
||||
|
||||
|
||||
private:
|
||||
bool SEL, CLR;
|
||||
uint8 TsuKBState[16];
|
||||
uint8 TsuKBLatch[16 + 2 + 1];
|
||||
uint32 TsuKBIndex;
|
||||
bool last_capslock;
|
||||
};
|
||||
|
||||
void PCE_Input_TsushinKB::Power(int32 timestamp)
|
||||
{
|
||||
SEL = CLR = 0;
|
||||
memset(TsuKBState, 0, sizeof(TsuKBState));
|
||||
memset(TsuKBLatch, 0, sizeof(TsuKBLatch));
|
||||
TsuKBIndex = 0;
|
||||
last_capslock = 0;
|
||||
}
|
||||
|
||||
PCE_Input_TsushinKB::PCE_Input_TsushinKB()
|
||||
{
|
||||
Power(0);
|
||||
}
|
||||
|
||||
void PCE_Input_TsushinKB::Update(const void *data)
|
||||
{
|
||||
uint8 *data_ptr = (uint8 *)data;
|
||||
bool capslock = TsuKBState[0xE] & 0x10;
|
||||
bool new_capslock = data_ptr[0xE] & 0x10;
|
||||
|
||||
if(!last_capslock && new_capslock)
|
||||
capslock ^= 1;
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
TsuKBState[i] = data_ptr[i];
|
||||
}
|
||||
|
||||
TsuKBState[0xE] = (TsuKBState[0xE] & ~0x10) | (capslock ? 0x10 : 0x00);
|
||||
|
||||
last_capslock = new_capslock;
|
||||
}
|
||||
|
||||
uint8 PCE_Input_TsushinKB::Read(int32 timestamp)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
ret = ((TsuKBLatch[TsuKBIndex] >> (SEL * 4)) & 0xF);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void PCE_Input_TsushinKB::Write(int32 timestamp, bool old_SEL, bool new_SEL, bool old_CLR, bool new_CLR)
|
||||
{
|
||||
SEL = new_SEL;
|
||||
CLR = new_CLR;
|
||||
|
||||
//printf("Write: %d %d %d %d\n", old_SEL, new_SEL, old_CLR, new_CLR);
|
||||
|
||||
if(!old_CLR && new_CLR)
|
||||
{
|
||||
TsuKBLatch[0] = 0x02;
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
TsuKBLatch[i + 1] = TsuKBState[i] ^ 0xFF;
|
||||
|
||||
TsuKBLatch[17] = 0x02;
|
||||
TsuKBIndex = 0;
|
||||
//puts("Latched");
|
||||
}
|
||||
else if(!old_SEL && new_SEL)
|
||||
{
|
||||
TsuKBIndex = (TsuKBIndex + 1) % 18;
|
||||
if(!TsuKBIndex)
|
||||
{
|
||||
for(int i = 0; i < 16; i++)
|
||||
TsuKBLatch[i + 1] = TsuKBState[i] ^ 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PCE_Input_TsushinKB::StateAction(StateMem *sm, int load, int data_only, const char *section_name)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(SEL),
|
||||
SFVAR(CLR),
|
||||
SFARRAY(TsuKBState, sizeof(TsuKBState)),
|
||||
SFARRAY(TsuKBLatch, sizeof(TsuKBLatch)),
|
||||
SFVAR(TsuKBIndex),
|
||||
SFVAR(last_capslock),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
const InputDeviceInputInfoStruct PCE_TsushinKBIDII[0x80] =
|
||||
{
|
||||
// 0 - DONE!
|
||||
{ "kp_0", "Keypad 0", 0, IDIT_BUTTON },
|
||||
{ "kp_1", "Keypad 1", 0, IDIT_BUTTON },
|
||||
{ "kp_2", "Keypad 2", 0, IDIT_BUTTON },
|
||||
{ "kp_3", "Keypad 3", 0, IDIT_BUTTON },
|
||||
{ "kp_4", "Keypad 4", 0, IDIT_BUTTON },
|
||||
{ "kp_5", "Keypad 5", 0, IDIT_BUTTON },
|
||||
{ "kp_6", "Keypad 6", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 1 - DONE!
|
||||
{ "kp_8", "Keypad 8", 0, IDIT_BUTTON },
|
||||
{ "kp_9", "Keypad 9", 0, IDIT_BUTTON },
|
||||
{ "kp_multiply", "Keypad *", 0, IDIT_BUTTON },
|
||||
{ "kp_plus", "Keypad +", 0, IDIT_BUTTON },
|
||||
{ "kp_equals", "Keypad =", 0, IDIT_BUTTON },
|
||||
{ "kp_comma", "Keypad ,", 0, IDIT_BUTTON },
|
||||
{ "kp_period", "Keypad .", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 2 - DONE!
|
||||
{ "at", "@", 0, IDIT_BUTTON },
|
||||
{ "a", "a", 0, IDIT_BUTTON },
|
||||
{ "b", "b", 0, IDIT_BUTTON },
|
||||
{ "c", "c", 0, IDIT_BUTTON },
|
||||
{ "d", "d", 0, IDIT_BUTTON },
|
||||
{ "e", "e", 0, IDIT_BUTTON },
|
||||
{ "f", "f", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 3 - DONE!
|
||||
{ "h", "h", 0, IDIT_BUTTON },
|
||||
{ "i", "i", 0, IDIT_BUTTON },
|
||||
{ "j", "j", 0, IDIT_BUTTON },
|
||||
{ "k", "k", 0, IDIT_BUTTON },
|
||||
{ "l", "l", 0, IDIT_BUTTON },
|
||||
{ "m", "m", 0, IDIT_BUTTON },
|
||||
{ "n", "n", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 4 - DONE!
|
||||
{ "p", "p", 0, IDIT_BUTTON },
|
||||
{ "q", "q", 0, IDIT_BUTTON },
|
||||
{ "r", "r", 0, IDIT_BUTTON },
|
||||
{ "s", "s", 0, IDIT_BUTTON },
|
||||
{ "t", "t", 0, IDIT_BUTTON },
|
||||
{ "u", "u", 0, IDIT_BUTTON },
|
||||
{ "v", "v", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 5 - DONE!
|
||||
{ "x", "x", 0, IDIT_BUTTON },
|
||||
{ "y", "y", 0, IDIT_BUTTON },
|
||||
{ "z", "z", 0, IDIT_BUTTON },
|
||||
{ "left_bracket", "[", 0, IDIT_BUTTON },
|
||||
{ "yen", "Yen", 0, IDIT_BUTTON },
|
||||
{ "right_bracket", "]", 0, IDIT_BUTTON },
|
||||
{ "caret", "^", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 6 - DONE!
|
||||
{ "0", "0", 0, IDIT_BUTTON },
|
||||
{ "1", "1", 0, IDIT_BUTTON },
|
||||
{ "2", "2", 0, IDIT_BUTTON },
|
||||
{ "3", "3", 0, IDIT_BUTTON },
|
||||
{ "4", "4", 0, IDIT_BUTTON },
|
||||
{ "5", "5", 0, IDIT_BUTTON },
|
||||
{ "6", "6", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 7 - DONE!
|
||||
{ "8", "8", 0, IDIT_BUTTON },
|
||||
{ "9", "9", 0, IDIT_BUTTON },
|
||||
{ "colon", ":", 0, IDIT_BUTTON },
|
||||
{ "semicolon", ";", 0, IDIT_BUTTON },
|
||||
{ "comma", ",", 0, IDIT_BUTTON },
|
||||
{ "period", ".", 0, IDIT_BUTTON },
|
||||
{ "slash", "/", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 8 - DONE enough
|
||||
{ "clear", "clear", 0, IDIT_BUTTON },
|
||||
{ "up", "up", 0, IDIT_BUTTON },
|
||||
{ "right", "right", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // Alternate backspace key on PC-88 keyboard??? { "unk80", "unknown", 0, IDIT_BUTTON },
|
||||
{ "grph", "GRPH", 0, IDIT_BUTTON },
|
||||
{ "kana", "カナ", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // Alternate shift key on PC-88 keyboard??? { "unk83", "unknown", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// 9 - DONE!
|
||||
{ "stop", "STOP", 0, IDIT_BUTTON }, // Break / STOP
|
||||
{ "f1", "F1", 0, IDIT_BUTTON },
|
||||
{ "f2", "F2", 0, IDIT_BUTTON },
|
||||
{ "f3", "F3", 0, IDIT_BUTTON },
|
||||
{ "f4", "F4", 0, IDIT_BUTTON },
|
||||
{ "f5", "F5", 0, IDIT_BUTTON },
|
||||
{ "space", "space", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// A - DONE!
|
||||
{ "tab", "Tab", 0, IDIT_BUTTON }, // Tab
|
||||
{ "down", "down", 0, IDIT_BUTTON },
|
||||
{ "left", "left", 0, IDIT_BUTTON },
|
||||
{ "help", "Help", 0, IDIT_BUTTON }, // -624
|
||||
{ "copy", "Copy", 0, IDIT_BUTTON }, // -623
|
||||
{ "kp_minus", "Keypad Minus", 0, IDIT_BUTTON },
|
||||
{ "kp_divide", "Keypad Divide", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// B - DONE(most likely)
|
||||
{ "roll_down", "ROLL DOWN", 0, IDIT_BUTTON },
|
||||
{ "roll_up", "ROLL UP", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownB2", "unknown", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownB3", "unknown", 0, IDIT_BUTTON },
|
||||
{ "o", "o", 0, IDIT_BUTTON },
|
||||
{ "underscore", "Underscore", 0, IDIT_BUTTON },
|
||||
{ "g", "g", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// C - DONE!
|
||||
{ "f6", "f6", 0, IDIT_BUTTON },
|
||||
{ "f7", "f7", 0, IDIT_BUTTON },
|
||||
{ "f8", "f8", 0, IDIT_BUTTON },
|
||||
{ "f9", "f9", 0, IDIT_BUTTON },
|
||||
{ "f10", "F10", 0, IDIT_BUTTON },
|
||||
{ "backspace", "backspace", 0, IDIT_BUTTON },
|
||||
{ "insert", "insert", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// D - DONE!
|
||||
{ "convert", "変換", 0, IDIT_BUTTON }, // (-620) Begin marking entered text, and disable marking after pressing the
|
||||
// end-of-block key.
|
||||
{ "nonconvert", "決定", 0, IDIT_BUTTON }, // (-619) End text marking block
|
||||
{ "pc", "PC", 0, IDIT_BUTTON }, // (-617) Selects between Rgana and Rkana. SHIFT+this key switches between
|
||||
// latin and kana/gana mode?
|
||||
{ "width", "変換", 0, IDIT_BUTTON }, // (-618) Chooses font width?
|
||||
{ "ctrl", "CTRL/Control", 0, IDIT_BUTTON }, // CTRL
|
||||
{ "kp_7", "Keypad 7", 0, IDIT_BUTTON },
|
||||
{ "w", "w", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// E - DONE!
|
||||
{ "return", "return", 0, IDIT_BUTTON }, // enter
|
||||
{ "kp_enter", "Keypad Enter", 0, IDIT_BUTTON }, // enter
|
||||
{ "left_shift", "Left Shift", 0, IDIT_BUTTON }, // Left Shift
|
||||
{ "right_shift", "Right Shift", 0, IDIT_BUTTON }, // Right Shift
|
||||
{ "caps_lock", "Caps Lock", 0, IDIT_BUTTON }, // Caps Lock(mechanically-locking...)
|
||||
{ "delete", "Delete", 0, IDIT_BUTTON },
|
||||
{ "escape", "Escape", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
|
||||
// F - DONE(most likely)
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownF0", "unknown", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownF1", "unknown", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownF2", "unknown", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownF3", "unknown", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON }, // { "unknownF4", "unknown", 0, IDIT_BUTTON },
|
||||
{ "minus", "Minus", 0, IDIT_BUTTON },
|
||||
{ "7", "7", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
};
|
||||
|
||||
PCE_Input_Device *PCEINPUT_MakeTsushinKB(void)
|
||||
{
|
||||
return(new PCE_Input_TsushinKB());
|
||||
}
|
||||
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef __PCE_INPUT_TSUSHINKB_H
|
||||
#define __PCE_INPUT_TSUSHINKB_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
extern const InputDeviceInputInfoStruct PCE_TsushinKBIDII[0x80];
|
||||
|
||||
PCE_Input_Device *PCEINPUT_MakeTsushinKB(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,260 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "mcgenjin.h"
|
||||
|
||||
MCGenjin_CS_Device::MCGenjin_CS_Device()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MCGenjin_CS_Device::~MCGenjin_CS_Device()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MCGenjin_CS_Device::Power(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MCGenjin_CS_Device::EndFrame(int32 timestamp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int MCGenjin_CS_Device::StateAction(StateMem *sm, int load, int data_only, const char *sname)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8 MCGenjin_CS_Device::Read(int32 timestamp, uint32 A)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void MCGenjin_CS_Device::Write(int32 timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32 MCGenjin_CS_Device::GetNVSize(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MCGenjin_CS_Device::ReadNV(uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
memset(buffer, 0, count);
|
||||
}
|
||||
|
||||
void MCGenjin_CS_Device::WriteNV(const uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class MCGenjin_CS_Device_RAM : public MCGenjin_CS_Device
|
||||
{
|
||||
public:
|
||||
|
||||
MCGenjin_CS_Device_RAM(uint32 size, bool nv)
|
||||
{
|
||||
assert(round_up_pow2(size) == size);
|
||||
|
||||
ram.resize(size);
|
||||
nonvolatile = nv;
|
||||
}
|
||||
|
||||
virtual ~MCGenjin_CS_Device_RAM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void Power(void)
|
||||
{
|
||||
if(!nonvolatile)
|
||||
ram.assign(ram.size(), 0xFF);
|
||||
|
||||
bank_select = 0;
|
||||
}
|
||||
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *sname)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(&ram[0], ram.size()),
|
||||
SFVAR(bank_select),
|
||||
SFEND
|
||||
};
|
||||
int ret = 1;
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, sname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
virtual uint8 Read(int32 timestamp, uint32 A)
|
||||
{
|
||||
return ram[(A | (bank_select << 18)) & (ram.size() - 1)];
|
||||
}
|
||||
|
||||
virtual void Write(int32 timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
if(!A)
|
||||
bank_select = V;
|
||||
|
||||
ram[(A | (bank_select << 18)) & (ram.size() - 1)] = V;
|
||||
}
|
||||
|
||||
virtual uint32 GetNVSize(void)
|
||||
{
|
||||
return nonvolatile ? ram.size() : 0;
|
||||
}
|
||||
|
||||
virtual void ReadNV(uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
while(count)
|
||||
{
|
||||
*buffer = ram[offset % ram.size()];
|
||||
buffer++;
|
||||
offset++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
while(count)
|
||||
{
|
||||
ram[offset % ram.size()] = *buffer;
|
||||
buffer++;
|
||||
offset++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint8> ram;
|
||||
bool nonvolatile;
|
||||
uint8 bank_select;
|
||||
};
|
||||
|
||||
#include "mcgenjin_ym2413.inc"
|
||||
|
||||
void MCGenjin::Power(void)
|
||||
{
|
||||
bank_select = 0;
|
||||
dlr = 0;
|
||||
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
cs[i]->Power();
|
||||
}
|
||||
|
||||
void MCGenjin::EndFrame(int32 timestamp)
|
||||
{
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
cs[i]->EndFrame(timestamp);
|
||||
}
|
||||
|
||||
uint32 MCGenjin::GetNVSize(const unsigned di)
|
||||
{
|
||||
return cs[di]->GetNVSize();
|
||||
}
|
||||
|
||||
|
||||
void MCGenjin::ReadNV(const unsigned di, uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
cs[di]->ReadNV(buffer, offset, count);
|
||||
}
|
||||
|
||||
void MCGenjin::WriteNV(const unsigned di, const uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
cs[di]->WriteNV(buffer, offset, count);
|
||||
}
|
||||
|
||||
MCGenjin::MCGenjin(Blip_Buffer *bb, const uint8 *rr, uint32 rr_size)
|
||||
{
|
||||
uint8 revision, num256_pages, region, cs_di[2];
|
||||
|
||||
if(rr_size < 8192)
|
||||
throw MDFN_Error(0, _("MCGenjin ROM size is too small!"));
|
||||
|
||||
if(memcmp(rr + 0x1FD0, "MCGENJIN", 8))
|
||||
throw MDFN_Error(0, _("MC Genjin header magic missing!"));
|
||||
|
||||
rom.resize(round_up_pow2(rr_size));
|
||||
|
||||
memcpy(&rom[0], rr, rr_size);
|
||||
|
||||
revision = rom[0x1FD8];
|
||||
num256_pages = rom[0x1FD9];
|
||||
region = rom[0x1FDA];
|
||||
cs_di[0] = rom[0x1FDB];
|
||||
cs_di[1] = rom[0x1FDC];
|
||||
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
switch(cs_di[i])
|
||||
{
|
||||
default:
|
||||
for(unsigned si = 0; si < i; si++) // FIXME: auto ptr to make this not necessary
|
||||
delete cs[si];
|
||||
|
||||
throw MDFN_Error(0, _("Unsupported MCGENJIN device on CS%d: 0x%02x"), i, cs_di[i]);
|
||||
break;
|
||||
|
||||
case 0x00:
|
||||
MDFN_printf(_("CS%d: Unused\n"), i);
|
||||
cs[i] = new MCGenjin_CS_Device();
|
||||
break;
|
||||
|
||||
case 0x10 ... 0x18:
|
||||
case 0x20 ... 0x28:
|
||||
MDFN_printf(_("CS%d: %uKiB %sRAM\n"), i, 8 << (cs_di[i] & 0xF), (cs_di[i] & 0x20) ? "Nonvolatile " : "");
|
||||
cs[i] = new MCGenjin_CS_Device_RAM(8192 << (cs_di[i] & 0xF), (bool)(cs_di[i] & 0x20));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MCGenjin::~MCGenjin()
|
||||
{
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
delete cs[i];
|
||||
}
|
||||
|
||||
int MCGenjin::StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(bank_select),
|
||||
SFVAR(dlr),
|
||||
SFEND
|
||||
};
|
||||
int ret = 1;
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "MCGENJIN");
|
||||
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, i ? "MCGENJIN_CS1" : "MCGENJIN_CS0");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_PCE_MCGENJIN_H
|
||||
#define __MDFN_PCE_MCGENJIN_H
|
||||
|
||||
#include <vector>
|
||||
#include <blip/Blip_Buffer.h>
|
||||
|
||||
class MCGenjin_CS_Device
|
||||
{
|
||||
public:
|
||||
|
||||
MCGenjin_CS_Device();
|
||||
virtual ~MCGenjin_CS_Device();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void EndFrame(int32 timestamp);
|
||||
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *sname);
|
||||
|
||||
virtual uint8 Read(int32 timestamp, uint32 A);
|
||||
virtual void Write(int32 timestamp, uint32 A, uint8 V);
|
||||
|
||||
virtual uint32 GetNVSize(void);
|
||||
virtual void ReadNV(uint8 *buffer, uint32 offset, uint32 count);
|
||||
virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 count);
|
||||
};
|
||||
|
||||
class MCGenjin
|
||||
{
|
||||
public:
|
||||
|
||||
MCGenjin(Blip_Buffer *bb, const uint8 *rr, uint32 rr_size);
|
||||
~MCGenjin();
|
||||
|
||||
void Power(void);
|
||||
void EndFrame(int32 timestamp);
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
INLINE unsigned GetNVPDC(void) { return 2; }
|
||||
uint32 GetNVSize(const unsigned di);
|
||||
void ReadNV(const unsigned di, uint8 *buffer, uint32 offset, uint32 count);
|
||||
void WriteNV(const unsigned di, const uint8 *buffer, uint32 offset, uint32 count);
|
||||
|
||||
INLINE uint8 combobble(uint8 v)
|
||||
{
|
||||
if(dlr)
|
||||
return ((((v * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL) >> 32);
|
||||
else
|
||||
return v;
|
||||
}
|
||||
|
||||
template<unsigned ar>
|
||||
INLINE uint8 ReadTP(int32 timestamp, uint32 A)
|
||||
{
|
||||
uint8 ret = 0xFF;
|
||||
|
||||
switch(ar)
|
||||
{
|
||||
case 0: ret = combobble(rom[A & 0x3FFFF & (rom.size() - 1)]);
|
||||
case 1: ret = combobble(rom[((A & 0x3FFFF) | (bank_select << 18)) & (rom.size() - 1)]);
|
||||
case 2: ret = cs[0]->Read(timestamp, A & 0x3FFFF);
|
||||
case 3: ret = cs[1]->Read(timestamp, A & 0x3FFFF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<unsigned ar>
|
||||
INLINE void WriteTP(int32 timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
switch(ar)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
if(A & 1)
|
||||
bank_select = V;
|
||||
else
|
||||
dlr = V & 0x01;
|
||||
break;
|
||||
|
||||
case 2: return cs[0]->Write(timestamp, A & 0x3FFFF, V);
|
||||
case 3: return cs[1]->Write(timestamp, A & 0x3FFFF, V);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE uint8 Read(int32 timestamp, uint32 A)
|
||||
{
|
||||
switch((A >> 18) & 0x3)
|
||||
{
|
||||
default: return 0xFF;
|
||||
case 0: return ReadTP<0>(timestamp, A);
|
||||
case 1: return ReadTP<1>(timestamp, A);
|
||||
case 2: return ReadTP<2>(timestamp, A);
|
||||
case 3: return ReadTP<3>(timestamp, A);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Write(int32 timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
switch((A >> 18) & 0x3)
|
||||
{
|
||||
case 0: WriteTP<0>(timestamp, A, V);
|
||||
case 1: WriteTP<1>(timestamp, A, V);
|
||||
case 2: WriteTP<2>(timestamp, A, V);
|
||||
case 3: WriteTP<3>(timestamp, A, V);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<uint8> rom;
|
||||
|
||||
MCGenjin_CS_Device *cs[2];
|
||||
|
||||
uint8 bank_select;
|
||||
uint8 dlr;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,97 +0,0 @@
|
|||
#include <mednafen/hw_sound/ym2413/emu2413.h>
|
||||
|
||||
class MCGenjin_CS_Device_YM2413 : public MCGenjin_CS_Device
|
||||
{
|
||||
public:
|
||||
|
||||
MCGenjin_CS_Device_YM2413(Blip_Buffer *bb)
|
||||
{
|
||||
zec = EMU2413_new(3579545);
|
||||
fm_last_value = 0;
|
||||
|
||||
sbuf = bb;
|
||||
}
|
||||
|
||||
virtual ~MCGenjin_CS_Device_YM2413()
|
||||
{
|
||||
EMU2413_delete(zec);
|
||||
}
|
||||
|
||||
virtual void Power(void)
|
||||
{
|
||||
EMU2413_reset(zec);
|
||||
last_ts = 0;
|
||||
fm_div = 0;
|
||||
}
|
||||
|
||||
virtual int StateAction(StateMem *sm, int load, int data_only, const char *sname)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFEND
|
||||
};
|
||||
int ret = 1;
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, sname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual uint8 Read(int32 timestamp, uint32 A)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
virtual void Write(int32 timestamp, uint32 A, uint8 V)
|
||||
{
|
||||
Update(timestamp / 3);
|
||||
EMU2413_writeIO(zec, A & 1, V);
|
||||
}
|
||||
|
||||
virtual void EndFrame(int32 timestamp)
|
||||
{
|
||||
Update(timestamp / 3);
|
||||
last_ts = 0;
|
||||
sbuf->set_modified();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void Update(int32 timestamp)
|
||||
{
|
||||
int32 cycles = timestamp - last_ts;
|
||||
|
||||
fm_div -= cycles;
|
||||
while(fm_div <= 0)
|
||||
{
|
||||
int32 new_value;
|
||||
|
||||
new_value = EMU2413_calc(zec) >> 1;
|
||||
|
||||
if(new_value > 32767)
|
||||
new_value = 32767;
|
||||
|
||||
if(new_value < -32768)
|
||||
new_value = -32768;
|
||||
|
||||
fmsynth.offset(timestamp + fm_div, new_value - fm_last_value, sbuf);
|
||||
|
||||
fm_last_value = new_value;
|
||||
fm_div += 72;
|
||||
}
|
||||
|
||||
last_ts = timestamp;
|
||||
}
|
||||
|
||||
EMU2413 *zec;
|
||||
Blip_Buffer *sbuf;
|
||||
|
||||
typedef Blip_Synth<blip_good_quality, 8192> FMSynth_t;
|
||||
FMSynth_t fmsynth;
|
||||
|
||||
int32 fm_div;
|
||||
int32 fm_last_value;
|
||||
|
||||
int32 last_ts;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,35 +0,0 @@
|
|||
#ifndef _PCE_H
|
||||
|
||||
#include "../mednafen.h"
|
||||
#include "../state.h"
|
||||
#include "../general.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
#define PCE_MASTER_CLOCK 21477272.727273
|
||||
|
||||
#define DECLFR(x) uint8 x (uint32 A)
|
||||
#define DECLFW(x) void x (uint32 A, uint8 V)
|
||||
|
||||
};
|
||||
|
||||
#include "huc6280/huc6280.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
extern HuC6280 *HuCPU;
|
||||
|
||||
extern uint32 PCE_InDebug;
|
||||
extern bool PCE_ACEnabled; // Arcade Card emulation enabled?
|
||||
void PCE_Power(void);
|
||||
|
||||
void PCE_MidSync(void);
|
||||
|
||||
uint8 PCE_PeekMainRAM(uint32 A);
|
||||
void PCE_PokeMainRAM(uint32 A, uint8 V);
|
||||
|
||||
};
|
||||
|
||||
#define _PCE_H
|
||||
#endif
|
|
@ -1,565 +0,0 @@
|
|||
#include "pce.h"
|
||||
#include "c68k/c68k.h"
|
||||
|
||||
static inline uint8 READ8_MSB(const uint8 *base, const unsigned int addr)
|
||||
{
|
||||
return(base[addr + 0]);
|
||||
}
|
||||
|
||||
static inline uint16 READ16_MSB(const uint8 *base, const unsigned int addr)
|
||||
{
|
||||
return((base[addr + 0] << 8) | (base[addr + 1] << 0));
|
||||
}
|
||||
|
||||
static inline void WRITE8_MSB(uint8 *base, const unsigned int addr, const uint8 value)
|
||||
{
|
||||
base[addr + 0] = value;
|
||||
}
|
||||
|
||||
static inline void WRITE16_MSB(uint8 *base, const unsigned int addr, const uint16 value)
|
||||
{
|
||||
base[addr + 0] = value >> 8;
|
||||
base[addr + 1] = value;
|
||||
}
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
static const uint8 VROM[8] = { 0x47, 0x6E, 0x31, 0x14, 0xB3, 0xEB, 0xEC, 0x2B };
|
||||
static uint8 VROM_Index;
|
||||
static bool HuVisible;
|
||||
|
||||
|
||||
static uint8 ExHuRAM[8192];
|
||||
static uint8 *BigRAM = NULL;
|
||||
static uint8 *FBRAM[2] = { NULL, NULL };
|
||||
static uint16 PalRAM[0x100];
|
||||
|
||||
static uint32 BigRAMWOTemp, BigRAMWO;
|
||||
|
||||
static uint8 CommPort[4];
|
||||
|
||||
static bool HuBigMaster;
|
||||
static bool M68KResetPending;
|
||||
//static bool M68KIntPending;
|
||||
static bool OverlayEnabled;
|
||||
|
||||
static bool CurDisplayFB;
|
||||
static bool FBSwapPending;
|
||||
static uint8 VSyncCounter;
|
||||
static uint32 DisplayScanline;
|
||||
|
||||
static uint32 AutoClearAddr;
|
||||
static int32 AutoClearCount;
|
||||
|
||||
static c68k_struc M68K;
|
||||
static uint8 M68K_ReadMemory8(uint32 A);
|
||||
static uint16 M68K_ReadMemory16(uint32 A);
|
||||
static void M68K_WriteMemory8(uint32 A, uint8 V);
|
||||
static void M68K_WriteMemory16(uint32 A, uint16 V);
|
||||
|
||||
static int32 lastts;
|
||||
static int32 M68K_cycle_counter;
|
||||
|
||||
static void AllocSubHWMem(void)
|
||||
{
|
||||
if(!BigRAM)
|
||||
BigRAM = (uint8 *)MDFN_calloc(1 << 20, 1, "BIG RAM RAM");
|
||||
|
||||
if(!FBRAM[0])
|
||||
FBRAM[0] = (uint8 *)MDFN_calloc(65536, 1, "FB RAM");
|
||||
|
||||
if(!FBRAM[1])
|
||||
FBRAM[1] = (uint8 *)MDFN_calloc(65536, 1, "FB RAM");
|
||||
|
||||
memset(FBRAM[0], 0xFF, 65536);
|
||||
memset(FBRAM[1], 0xFF, 65536);
|
||||
}
|
||||
|
||||
static void FreeSubHWMem(void)
|
||||
{
|
||||
if(BigRAM)
|
||||
{
|
||||
MDFN_free(BigRAM);
|
||||
BigRAM = NULL;
|
||||
}
|
||||
|
||||
if(FBRAM[0])
|
||||
{
|
||||
MDFN_free(FBRAM[0]);
|
||||
FBRAM[0] = NULL;
|
||||
}
|
||||
|
||||
if(FBRAM[1])
|
||||
{
|
||||
MDFN_free(FBRAM[1]);
|
||||
FBRAM[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
#include <desa68/desa68.h>
|
||||
|
||||
static uint16_t dis_callb(uint32_t A, void *private_data)
|
||||
{
|
||||
//printf("%04x\n", M68K_ReadMemory16(A & 0xFFFFFF));
|
||||
return(M68K_ReadMemory16(A & 0xFFFFFF));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void UpdateM68K(const int32 timestamp)
|
||||
{
|
||||
int32 hucycles = timestamp - lastts;
|
||||
lastts = timestamp;
|
||||
|
||||
if(HuBigMaster)
|
||||
return;
|
||||
|
||||
if(M68KResetPending)
|
||||
{
|
||||
M68KResetPending = false;
|
||||
C68k_Reset(&M68K);
|
||||
}
|
||||
|
||||
M68K_cycle_counter += hucycles;
|
||||
|
||||
while(M68K_cycle_counter > 0)
|
||||
{
|
||||
#if 0
|
||||
char TextBuf[256];
|
||||
DESA68parm_t d;
|
||||
strcpy(TextBuf, "Invalid");
|
||||
memset(&d, 0, sizeof(DESA68parm_t));
|
||||
|
||||
d.mem_callb = dis_callb;
|
||||
d.memmsk = 0xFFFFFF;
|
||||
d.pc = M68K.PC;
|
||||
d.str = TextBuf;
|
||||
d.strmax = 255; // FIXME, MDFN API change
|
||||
|
||||
desa68(&d);
|
||||
printf("%08x: %s\n", M68K.PC, TextBuf);
|
||||
#endif
|
||||
//M68K_cycle_counter -= C68k_Exec(&M68K) * 2;
|
||||
M68K.timestamp = 0;
|
||||
C68k_Exec(&M68K);
|
||||
M68K_cycle_counter -= M68K.timestamp * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void SubHW_EndFrame(const int32 timestamp)
|
||||
{
|
||||
UpdateM68K(timestamp);
|
||||
lastts = 0;
|
||||
}
|
||||
|
||||
|
||||
static int M68K_Int_Ack_Callback(int level)
|
||||
{
|
||||
return C68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
void SubHW_Init(void)
|
||||
{
|
||||
C68k_Init(&M68K, M68K_Int_Ack_Callback);
|
||||
|
||||
C68k_Set_ReadB(&M68K, M68K_ReadMemory8);
|
||||
C68k_Set_ReadW(&M68K, M68K_ReadMemory16);
|
||||
|
||||
C68k_Set_WriteB(&M68K, M68K_WriteMemory8);
|
||||
C68k_Set_WriteW(&M68K, M68K_WriteMemory16);
|
||||
}
|
||||
|
||||
void SubHW_Kill(void)
|
||||
{
|
||||
FreeSubHWMem();
|
||||
|
||||
if(BigRAM)
|
||||
{
|
||||
MDFN_free(BigRAM);
|
||||
BigRAM = NULL;
|
||||
}
|
||||
|
||||
if(FBRAM[0])
|
||||
{
|
||||
MDFN_free(FBRAM[0]);
|
||||
FBRAM[0] = NULL;
|
||||
}
|
||||
|
||||
if(FBRAM[1])
|
||||
{
|
||||
MDFN_free(FBRAM[1]);
|
||||
FBRAM[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE uint16 M68K_ReadIO(uint32 A)
|
||||
{
|
||||
if(A & 0x100)
|
||||
{
|
||||
uint16 ret = (FBSwapPending << 15) | ((AutoClearCount > 0) ? 0x4000 : 0) | VSyncCounter;
|
||||
|
||||
//printf("Moo: %04x\n", ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(CommPort[(A >> 1) & 0x3]);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void M68K_WriteIO(uint32 A, uint16 V)
|
||||
{
|
||||
if(A & 0x100)
|
||||
{
|
||||
if(V & 0x100)
|
||||
C68k_Set_IRQ(&M68K, 0);
|
||||
OverlayEnabled = (bool)(V & 0x2);
|
||||
FBSwapPending |= (bool)(V & 0x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommPort[(A >> 1) & 0x3] = V;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8 M68K_ReadMemory8(uint32 A)
|
||||
{
|
||||
switch((A >> 20) & 0xF)
|
||||
{
|
||||
default: return(0xFF);
|
||||
|
||||
case 0x0:
|
||||
return READ8_MSB(BigRAM, A & 0x7FFFF);
|
||||
|
||||
case 0x4:
|
||||
return M68K_ReadIO(A);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16 M68K_ReadMemory16(uint32 A)
|
||||
{
|
||||
//printf("Read16: %08x\n", A);
|
||||
switch((A >> 20) & 0xF)
|
||||
{
|
||||
default: return(0xFFFF);
|
||||
|
||||
case 0x0 ... 0x3:
|
||||
return READ16_MSB(BigRAM, A & 0x7FFFF);
|
||||
|
||||
case 0x4:
|
||||
return M68K_ReadIO(A);
|
||||
}
|
||||
}
|
||||
|
||||
static void M68K_WriteMemory8(uint32 A, uint8 V)
|
||||
{
|
||||
//printf("Write8 %08x %02x\n", A, V);
|
||||
switch((A >> 20) & 0xF)
|
||||
{
|
||||
default: break;
|
||||
|
||||
case 0x0:
|
||||
WRITE8_MSB(BigRAM, A & 0x7FFFF, V);
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
if(AutoClearCount > 0)
|
||||
{
|
||||
puts("Write during autoclear");
|
||||
return;
|
||||
}
|
||||
{
|
||||
uint16 fba = A & 0xFFFF;
|
||||
|
||||
if(A & 0x10000)
|
||||
fba = (fba << 8) | (fba >> 8);
|
||||
|
||||
if(V)
|
||||
FBRAM[CurDisplayFB ^ 1][fba] = V;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
M68K_WriteIO(A, V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void M68K_WriteMemory16(uint32 A, uint16 V)
|
||||
{
|
||||
//printf("Write16 %08x %02x\n", A, V);
|
||||
switch((A >> 20) & 0xF)
|
||||
{
|
||||
default: break;
|
||||
|
||||
case 0x0:
|
||||
WRITE16_MSB(BigRAM, A & 0x7FFFF, V);
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
if(AutoClearCount > 0)
|
||||
{
|
||||
puts("Write during autoclear");
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
uint16 fba = A & 0xFFFF;
|
||||
|
||||
if(A & 0x10000)
|
||||
fba = (fba << 8) | (fba >> 8);
|
||||
|
||||
if(V & 0xFF00)
|
||||
FBRAM[CurDisplayFB ^ 1][(fba + 0) & 0xFFFF] = V >> 8;
|
||||
if(V & 0x00FF)
|
||||
FBRAM[CurDisplayFB ^ 1][(fba + 1) & 0xFFFF] = V >> 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
PalRAM[(A >> 1) & 0xFF] = V;
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
M68K_WriteIO(A, V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SubHW_WriteIOPage(uint32 A, uint8 V)
|
||||
{
|
||||
if(!HuVisible)
|
||||
{
|
||||
if(VROM[VROM_Index] == V)
|
||||
VROM_Index++;
|
||||
else
|
||||
VROM_Index = 0;
|
||||
|
||||
if(VROM_Index == 8)
|
||||
{
|
||||
printf("Overlay hardware enabled.");
|
||||
MDFN_DispMessage("Overlay hardware enabled.");
|
||||
HuVisible = true;
|
||||
|
||||
AllocSubHWMem();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch(A & 0x1FFF)
|
||||
{
|
||||
case 0x1C00 ... 0x1FEF:
|
||||
ExHuRAM[A & 0x1FFF] = V;
|
||||
break;
|
||||
|
||||
case 0x1FF0 ... 0x1FF3:
|
||||
UpdateM68K(HuCPU->Timestamp());
|
||||
CommPort[A & 0x3] = V;
|
||||
break;
|
||||
|
||||
case 0x1FF4:
|
||||
BigRAMWOTemp &= 0xFF00;
|
||||
BigRAMWOTemp |= V;
|
||||
break;
|
||||
|
||||
case 0x1FF5:
|
||||
BigRAMWOTemp &= 0x00FF;
|
||||
BigRAMWOTemp |= V << 8;
|
||||
BigRAMWO = BigRAMWOTemp << 4;
|
||||
break;
|
||||
|
||||
case 0x1FF6:
|
||||
if(HuBigMaster)
|
||||
{
|
||||
//printf("BIG: %08x %02x\n", BigRAMWO, V);
|
||||
BigRAM[BigRAMWO] = V;
|
||||
BigRAMWO = (BigRAMWO + 1) & ((1 << 20) - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1FF7:
|
||||
UpdateM68K(HuCPU->Timestamp());
|
||||
HuBigMaster = V & 0x01;
|
||||
M68KResetPending |= (bool)(V & 0x02);
|
||||
C68k_Set_IRQ(&M68K, (bool)(V & 0x04));
|
||||
//M68KIntPending |= (bool)(V & 0x04);
|
||||
OverlayEnabled = (bool)(V & 0x80);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SubHW_ReadIOPage(uint32 A)
|
||||
{
|
||||
if(!HuVisible)
|
||||
return(0xFF);
|
||||
|
||||
switch(A & 0x1FFF)
|
||||
{
|
||||
case 0x1C00 ... 0x1FEF:
|
||||
return ExHuRAM[A & 0x1FFF];
|
||||
break;
|
||||
|
||||
case 0x1FF0 ... 0x1FF3:
|
||||
UpdateM68K(HuCPU->Timestamp());
|
||||
return CommPort[A & 0x3];
|
||||
break;
|
||||
}
|
||||
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
DECLFW(SubHW_WriteFEPage)
|
||||
{
|
||||
if(!HuVisible)
|
||||
return;
|
||||
|
||||
ExHuRAM[A & 0x1FFF] = V;
|
||||
}
|
||||
|
||||
DECLFR(SubHW_ReadFEPage)
|
||||
{
|
||||
if(!HuVisible)
|
||||
return(0xFF);
|
||||
|
||||
return(ExHuRAM[A & 0x1FFF]);
|
||||
}
|
||||
|
||||
void SubHW_CVSync(void)
|
||||
{
|
||||
if(!HuVisible)
|
||||
return;
|
||||
|
||||
UpdateM68K(HuCPU->Timestamp());
|
||||
|
||||
if(FBSwapPending)
|
||||
{
|
||||
FBSwapPending = false;
|
||||
CurDisplayFB = !CurDisplayFB;
|
||||
|
||||
AutoClearAddr = 0;
|
||||
AutoClearCount = 65536;
|
||||
}
|
||||
VSyncCounter++;
|
||||
DisplayScanline = 0;
|
||||
}
|
||||
|
||||
bool SubHW_DisplayLine(uint16 *out_buffer)
|
||||
{
|
||||
if(!HuVisible)
|
||||
return(false);
|
||||
|
||||
UpdateM68K(HuCPU->Timestamp());
|
||||
|
||||
if(OverlayEnabled)
|
||||
for(int x = 0; x < 256; x++)
|
||||
out_buffer[x] = PalRAM[FBRAM[CurDisplayFB][(((DisplayScanline - 17) & 0xFF) << 8) | x]];
|
||||
|
||||
DisplayScanline++;
|
||||
|
||||
for(int i = 0; i < 683; i++)
|
||||
{
|
||||
if(AutoClearCount <= 0)
|
||||
break;
|
||||
|
||||
FBRAM[CurDisplayFB ^ 1][AutoClearAddr++] = 0;
|
||||
AutoClearCount--;
|
||||
}
|
||||
|
||||
return(OverlayEnabled);
|
||||
}
|
||||
|
||||
void SubHW_Power(void)
|
||||
{
|
||||
memset(ExHuRAM, 0xFF, sizeof(ExHuRAM));
|
||||
|
||||
HuVisible = false;
|
||||
VROM_Index = 0;
|
||||
HuBigMaster = true;
|
||||
M68KResetPending = true;
|
||||
//M68KIntPending = false;
|
||||
C68k_Set_IRQ(&M68K, 0);
|
||||
|
||||
OverlayEnabled = false;
|
||||
|
||||
CurDisplayFB = 0;
|
||||
FBSwapPending = false;
|
||||
VSyncCounter = 0;
|
||||
|
||||
AutoClearAddr = 0;
|
||||
AutoClearCount = 0;
|
||||
|
||||
CommPort[0] = 0xFF;
|
||||
CommPort[1] = 0xFF;
|
||||
CommPort[2] = 0xFF;
|
||||
CommPort[3] = 0xFF;
|
||||
}
|
||||
|
||||
int SubHW_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
int ret;
|
||||
|
||||
SFORMAT VisibleStateRegs[] =
|
||||
{
|
||||
SFVAR(HuVisible),
|
||||
SFEND
|
||||
};
|
||||
|
||||
// Since "SubHWV" section is optional, we need to default to not being visible if the section isn't there.
|
||||
if(load)
|
||||
HuVisible = false;
|
||||
|
||||
ret = MDFNSS_StateAction(sm, load, data_only, VisibleStateRegs, "SubHWV", true);
|
||||
|
||||
if(HuVisible)
|
||||
{
|
||||
unsigned int c68k_state_len = C68k_Get_State_Max_Len();
|
||||
uint8 c68k_state[c68k_state_len];
|
||||
|
||||
C68k_Save_State(&M68K, c68k_state);
|
||||
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(VROM_Index),
|
||||
SFARRAY(ExHuRAM, 8192),
|
||||
SFARRAY(BigRAM, 1 << 20),
|
||||
SFARRAY(FBRAM[0], 65536),
|
||||
SFARRAY(FBRAM[1], 65536),
|
||||
SFARRAY16(PalRAM, 0x100),
|
||||
SFVAR(BigRAMWOTemp),
|
||||
SFVAR(BigRAMWO),
|
||||
SFARRAY(CommPort, 4),
|
||||
SFVAR(HuBigMaster),
|
||||
SFVAR(M68KResetPending),
|
||||
SFVAR(OverlayEnabled),
|
||||
SFVAR(CurDisplayFB),
|
||||
SFVAR(FBSwapPending),
|
||||
SFVAR(VSyncCounter),
|
||||
SFVAR(DisplayScanline),
|
||||
SFVAR(AutoClearAddr),
|
||||
SFVAR(AutoClearCount),
|
||||
|
||||
SFARRAY(c68k_state, c68k_state_len),
|
||||
SFEND
|
||||
};
|
||||
AllocSubHWMem();
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "SubHW");
|
||||
if(load)
|
||||
{
|
||||
C68k_Load_State(&M68K, c68k_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeSubHWMem();
|
||||
}
|
||||
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
void SubHW_Init(void);
|
||||
void SubHW_Kill(void);
|
||||
|
||||
void SubHW_WriteIOPage(uint32 A, uint8 V);
|
||||
uint8 SubHW_ReadIOPage(uint32 A);
|
||||
|
||||
DECLFW(SubHW_WriteFEPage);
|
||||
DECLFR(SubHW_ReadFEPage);
|
||||
|
||||
void SubHW_Power(void);
|
||||
|
||||
void SubHW_EndFrame(const int32 timestamp);
|
||||
void SubHW_CVSync(void);
|
||||
bool SubHW_DisplayLine(uint16 *out_buffer);
|
||||
|
||||
int SubHW_StateAction(StateMem *sm, int load, int data_only);
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "pce.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
/*
|
||||
Startup:
|
||||
0x80 -> $1830
|
||||
0x40 -> $1823
|
||||
0x50 -> $1823
|
||||
0x02 -> $1821
|
||||
0x40 -> $1823
|
||||
|
||||
Read from $1822 16 times, expecting (return value & 0xC0) == 0x80 each time
|
||||
|
||||
0x50 -> $1823
|
||||
0x01 -> $1821
|
||||
0x40 -> $1823
|
||||
0x04 -> $1822
|
||||
|
||||
*/
|
||||
|
||||
DECLFR(PCE_TsushinRead)
|
||||
{
|
||||
//printf("Read: %04x, %04x\n", A, HuCPU.PC);
|
||||
|
||||
return(0x80);
|
||||
}
|
||||
|
||||
DECLFW(PCE_TsushinWrite)
|
||||
{
|
||||
//printf("Write: %04x %02x, %04x\n", A, V, HuCPU.PC);
|
||||
}
|
||||
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __PCE_TSUSHIN_H
|
||||
#define __PCE_TSUSHIN_H
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
DECLFR(PCE_TsushinRead);
|
||||
DECLFW(PCE_TsushinWrite);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,843 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* VCE and VPC emulation */
|
||||
|
||||
/*
|
||||
<_Ki> So here is what I found today: the /Hblank signal is not affected (at all) by VCE's dot clock selection.
|
||||
It seems to be completely fixed; /HBlank-L-period = 237 x master clock cycles, and /HBlank-H-period = 1128, and
|
||||
that makes h-period = 1365 x master clock cycles as a whole.
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "huc.h"
|
||||
#include <math.h>
|
||||
#include "../video.h"
|
||||
#include "vce.h"
|
||||
#include "huc6270/vdc.h"
|
||||
#include "debug.h"
|
||||
#include "subhw.h"
|
||||
#include "../cdrom/pcecd.h"
|
||||
#include <trio/trio.h>
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
#define SUPERDUPERMODE 0
|
||||
|
||||
static const int vce_ratios[4] = { 4, 3, 2, 2 };
|
||||
|
||||
static void IRQChange_Hook(bool newstatus)
|
||||
{
|
||||
extern VCE *vce; //HORRIBLE
|
||||
vce->IRQChangeCheck();
|
||||
}
|
||||
|
||||
bool VCE::WS_Hook(int32 vdc_cycles)
|
||||
{
|
||||
bool ret = true;
|
||||
int32 to_steal;
|
||||
|
||||
if(vdc_cycles == -1) // Special event-based wait-stating
|
||||
to_steal = CalcNextEvent();
|
||||
else
|
||||
to_steal = ((vdc_cycles * dot_clock_ratio - clock_divider) + 2) / 3;
|
||||
|
||||
if(to_steal <= 0) // This should never happen. But in case it does...
|
||||
{
|
||||
printf("Bad steal: %d; Wanted VDC: %d; Dot clock ratio: %d; Clock divider: %d\n", to_steal, vdc_cycles, dot_clock_ratio, clock_divider);
|
||||
to_steal = 1;
|
||||
}
|
||||
|
||||
if((to_steal + ws_counter) > 455 * 64)
|
||||
{
|
||||
printf("WS Over: Wanted: %d, could: %d\n", to_steal, 455 * 64 - ws_counter);
|
||||
to_steal = 455 * 64 - ws_counter;
|
||||
|
||||
if(to_steal < 0)
|
||||
to_steal = 0;
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
if(to_steal > 0)
|
||||
{
|
||||
HuCPU->StealCycles(to_steal);
|
||||
ws_counter += to_steal;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static bool WS_Hook(int32 vdc_cycles)
|
||||
{
|
||||
extern VCE *vce;
|
||||
|
||||
return(vce->WS_Hook(vdc_cycles));
|
||||
}
|
||||
|
||||
void VCE::IRQChangeCheck(void)
|
||||
{
|
||||
bool irqtmp = 0;
|
||||
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
irqtmp |= vdc[chip]->PeekIRQ();
|
||||
|
||||
if(irqtmp)
|
||||
HuCPU->IRQBegin(HuC6280::IQIRQ1);
|
||||
else
|
||||
HuCPU->IRQEnd(HuC6280::IQIRQ1);
|
||||
}
|
||||
|
||||
void VCE::SetShowHorizOS(bool show)
|
||||
{
|
||||
ShowHorizOS = show;
|
||||
}
|
||||
|
||||
|
||||
VCE::VCE(bool want_sgfx, bool nospritelimit)
|
||||
{
|
||||
ShowHorizOS = false;
|
||||
|
||||
sgfx = want_sgfx;
|
||||
chip_count = sgfx ? 2 : 1;
|
||||
|
||||
cd_event = 1;
|
||||
|
||||
fb = NULL;
|
||||
pitch32 = 0;
|
||||
RunHook = NULL;
|
||||
HBlankHook = NULL;
|
||||
VBlankHook = NULL;
|
||||
|
||||
vdc[0] = vdc[1] = NULL;
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
{
|
||||
vdc[chip] = new VDC(nospritelimit, MDFN_GetSettingUI("pce.vramsize"));
|
||||
vdc[chip]->SetIRQHook(IRQChange_Hook);
|
||||
vdc[chip]->SetWSHook(MDFN_IEN_PCE::WS_Hook);
|
||||
}
|
||||
|
||||
CustomColorMap = NULL;
|
||||
CustomColorMapLen = 0;
|
||||
|
||||
memset(systemColorMap32, 0, sizeof(systemColorMap32));
|
||||
memset(bw_systemColorMap32, 0, sizeof(bw_systemColorMap32));
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
GfxDecode_Buf = NULL;
|
||||
GfxDecode_Line = -1;
|
||||
GfxDecode_Layer = 0;
|
||||
GfxDecode_Scroll = 0;
|
||||
GfxDecode_Pbn = 0;
|
||||
#endif
|
||||
|
||||
|
||||
SetShowHorizOS(false);
|
||||
}
|
||||
|
||||
VCE::~VCE()
|
||||
{
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
delete vdc[chip];
|
||||
}
|
||||
|
||||
void VCE::Reset(const int32 timestamp)
|
||||
{
|
||||
last_ts = 0;
|
||||
|
||||
pixel_offset = 0;
|
||||
dot_clock = 0;
|
||||
dot_clock_ratio = vce_ratios[dot_clock];
|
||||
clock_divider = 0;
|
||||
|
||||
ws_counter = 0;
|
||||
scanline = 0;
|
||||
scanline_out_ptr = NULL;
|
||||
CR = 0;
|
||||
lc263 = 0;
|
||||
bw = 0;
|
||||
|
||||
memset(color_table, 0, sizeof(color_table));
|
||||
memset(color_table_cache, 0, sizeof(color_table_cache));
|
||||
|
||||
ctaddress = 0;
|
||||
|
||||
hblank = 1;
|
||||
vblank = 1;
|
||||
|
||||
NeedSLReset = false;
|
||||
|
||||
hblank_counter = 237;
|
||||
vblank_counter = 4095 + 30;
|
||||
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
child_event[chip] = vdc[chip]->Reset();
|
||||
|
||||
// SuperGrafx VPC init
|
||||
priority[0] = 0x11;
|
||||
priority[1] = 0x11;
|
||||
winwidths[0] = 0;
|
||||
winwidths[1] = 0;
|
||||
st_mode = 0;
|
||||
window_counter[0] = 0x40;
|
||||
window_counter[1] = 0x40;
|
||||
|
||||
if(fb)
|
||||
scanline_out_ptr = &fb[scanline * pitch32];
|
||||
|
||||
///
|
||||
//
|
||||
//
|
||||
SubTValid = false;
|
||||
}
|
||||
|
||||
static MDFN_Rect *LW;
|
||||
|
||||
static bool skipframe;
|
||||
|
||||
/*
|
||||
Note: If we're skipping the frame, don't write to the data behind the pXBuf, DisplayRect, and LineWidths
|
||||
pointers at all. There's no need to, and HES playback depends on these structures being left alone; if they're not,
|
||||
there will be graphics distortion, and maybe memory corruption.
|
||||
*/
|
||||
|
||||
void VCE::StartFrame(MDFN_Surface *surface, MDFN_Rect *DisplayRect, MDFN_Rect *LineWidths, int skip)
|
||||
{
|
||||
uint32 *pXBuf = surface->pixels;
|
||||
|
||||
FrameDone = false;
|
||||
|
||||
//printf("Clock divider: %d\n", clock_divider);
|
||||
|
||||
color_table_cache[0x200] = color_table_cache[0x300] = surface->format.MakeColor(0x00, 0xFE, 0x00);
|
||||
|
||||
if(!skip)
|
||||
{
|
||||
DisplayRect->x = 0;
|
||||
DisplayRect->w = 1365;
|
||||
DisplayRect->y = 0 + 14;
|
||||
DisplayRect->h = 240; //263 - 14;
|
||||
|
||||
DisplayRect->y = 14 + MDFN_GetSettingUI("pce.slstart");
|
||||
DisplayRect->h = MDFN_GetSettingUI("pce.slend") - MDFN_GetSettingUI("pce.slstart") + 1;
|
||||
|
||||
for(int y = 0; y < 263; y++)
|
||||
LineWidths[y].w = 0;
|
||||
|
||||
pitch32 = surface->pitch32;
|
||||
fb = pXBuf;
|
||||
LW = LineWidths;
|
||||
scanline_out_ptr = &fb[scanline * pitch32];
|
||||
}
|
||||
else
|
||||
{
|
||||
pitch32 = 0;
|
||||
fb = NULL;
|
||||
LW = NULL;
|
||||
scanline_out_ptr = NULL;
|
||||
}
|
||||
|
||||
skipframe = skip;
|
||||
}
|
||||
|
||||
bool VCE::RunPartial(void)
|
||||
{
|
||||
HuCPU->SetEventHandler(this);
|
||||
|
||||
if(!PCE_IsCD)
|
||||
cd_event = 0x3FFFFFFF;
|
||||
|
||||
ws_counter = 0;
|
||||
HuCPU->Run();
|
||||
|
||||
if(!skipframe)
|
||||
{
|
||||
MDFN_Rect LW_Fix;
|
||||
|
||||
// Worst-case fallback
|
||||
LW_Fix.x = 0;
|
||||
LW_Fix.w = 256;
|
||||
LW_Fix.y = 0;
|
||||
LW_Fix.h = 0;
|
||||
|
||||
for(int y = 0; y < 263; y++)
|
||||
{
|
||||
if(LW[y].w)
|
||||
{
|
||||
LW_Fix = LW[y];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < 263; y++)
|
||||
{
|
||||
if(!LW[y].w)
|
||||
LW[y] = LW_Fix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(PCE_IsCD)
|
||||
SetCDEvent(PCECD_Run(HuCPU->Timestamp()));
|
||||
|
||||
HuCPU->SetEvent(Sync(HuCPU->Timestamp()));
|
||||
|
||||
last_ts = 0;
|
||||
|
||||
return(FrameDone);
|
||||
}
|
||||
|
||||
// If we ignore the return value of Sync(), we must do "HuCPU->SetEvent(CalcNextEvent());"
|
||||
// before the function(read/write functions) that called Sync() return!
|
||||
int32 VCE::Sync(const int32 timestamp)
|
||||
{
|
||||
int32 clocks = timestamp - last_ts;
|
||||
|
||||
cd_event -= clocks;
|
||||
if(cd_event <= 0)
|
||||
cd_event = PCECD_Run(timestamp);
|
||||
|
||||
|
||||
if(sgfx)
|
||||
{
|
||||
#define VCE_SGFX_MODE 1
|
||||
#include "vce_sync.inc"
|
||||
#undef VCE_SGFX_MODE
|
||||
}
|
||||
else
|
||||
{
|
||||
#include "vce_sync.inc"
|
||||
}
|
||||
|
||||
int32 ret = CalcNextEvent();
|
||||
|
||||
last_ts = timestamp;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void VCE::FixPCache(int entry)
|
||||
{
|
||||
uint32 *cm32 = bw ? bw_systemColorMap32 : systemColorMap32;
|
||||
|
||||
if(!(entry & 0xFF))
|
||||
{
|
||||
for(int x = 0; x < 16; x++)
|
||||
color_table_cache[(entry & 0x100) + (x << 4)] = cm32[color_table[entry & 0x100]];
|
||||
}
|
||||
if(!(entry & 0xF))
|
||||
return;
|
||||
|
||||
color_table_cache[entry] = cm32[color_table[entry]];
|
||||
}
|
||||
|
||||
void VCE::SetVCECR(uint8 V)
|
||||
{
|
||||
if(((V & 0x80) >> 7) != bw)
|
||||
{
|
||||
bw = V & 0x80;
|
||||
for(int x = 0; x < 512; x++)
|
||||
FixPCache(x);
|
||||
}
|
||||
|
||||
lc263 = (V & 0x04);
|
||||
|
||||
#if 0
|
||||
int new_dot_clock = V & 1;
|
||||
if(V & 2)
|
||||
new_dot_clock = 2;
|
||||
|
||||
dot_clock = new_dot_clock;
|
||||
#endif
|
||||
|
||||
dot_clock = V & 0x3;
|
||||
if(dot_clock == 3) // Remove this once we determine any relevant differences between 2 and 3.
|
||||
dot_clock = 2;
|
||||
|
||||
dot_clock_ratio = vce_ratios[dot_clock];
|
||||
|
||||
CR = V;
|
||||
}
|
||||
|
||||
void VCE::SetPixelFormat(const MDFN_PixelFormat &format)
|
||||
{
|
||||
for(int x = 0; x < 512; x++)
|
||||
{
|
||||
int r, g, b;
|
||||
int sc_r, sc_g, sc_b;
|
||||
|
||||
if(CustomColorMap)
|
||||
{
|
||||
r = CustomColorMap[x * 3 + 0];
|
||||
g = CustomColorMap[x * 3 + 1];
|
||||
b = CustomColorMap[x * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
b = 36 * (x & 0x007);
|
||||
r = 36 * ((x & 0x038) >> 3);
|
||||
g = 36 * ((x & 0x1c0) >> 6);
|
||||
}
|
||||
|
||||
if(CustomColorMap && CustomColorMapLen == 1024)
|
||||
{
|
||||
sc_r = CustomColorMap[(512 + x) * 3 + 0];
|
||||
sc_g = CustomColorMap[(512 + x) * 3 + 1];
|
||||
sc_b = CustomColorMap[(512 + x) * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
double y;
|
||||
|
||||
y = round(0.300 * r + 0.589 * g + 0.111 * b);
|
||||
|
||||
if(y < 0)
|
||||
y = 0;
|
||||
|
||||
if(y > 255)
|
||||
y = 255;
|
||||
|
||||
sc_r = sc_g = sc_b = y;
|
||||
}
|
||||
|
||||
systemColorMap32[x] = format.MakeColor(r, g, b);
|
||||
bw_systemColorMap32[x] = format.MakeColor(sc_r, sc_g, sc_b);
|
||||
}
|
||||
|
||||
// I know the temptation is there, but don't combine these two loops just
|
||||
// because they loop 512 times ;)
|
||||
for(int x = 0; x < 512; x++)
|
||||
FixPCache(x);
|
||||
|
||||
//
|
||||
// Make the subtitle overlay LUT
|
||||
//
|
||||
for(int n = 0; n < 4096; n++)
|
||||
{
|
||||
#if 0
|
||||
float y = (float)((n >> 8) & 0xF) / 15;
|
||||
float i = (float)((n >> 4) & 0xF) / 16;
|
||||
float q = (float)((n >> 0) & 0xF) / 16;
|
||||
int r, g, b;
|
||||
|
||||
i *= 1.1914;
|
||||
q *= 1.0452;
|
||||
|
||||
i -= 0.5957;
|
||||
q -= 0.5226;
|
||||
|
||||
r = 255 * (y + (0.9563 * i) + (0.6210 * q));
|
||||
g = 255 * (y + (-0.2721 * i) + (-0.6474 * q));
|
||||
b = 255 * (y + (-1.1070 * i) + (1.7046 * q));
|
||||
if(r < 0) r = 0; if(r > 255) r = 255;
|
||||
if(g < 0) g = 0; if(g > 255) g = 255;
|
||||
if(b < 0) b = 0; if(b > 255) b = 255;
|
||||
#else
|
||||
int r, g, b;
|
||||
|
||||
r = ((n >> 8) & 0xF) * 17;
|
||||
g = ((n >> 4) & 0xF) * 17;
|
||||
b = ((n >> 0) & 0xF) * 17;
|
||||
#endif
|
||||
SubTLUT[n] = format.MakeColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
bool VCE::SetCustomColorMap(const uint8 *triplets, const uint32 count)
|
||||
{
|
||||
assert(count == 512 || count == 1024);
|
||||
assert(triplets);
|
||||
|
||||
if(!(CustomColorMap = (uint8*)MDFN_malloc(count * 3, _("custom color map"))))
|
||||
return(FALSE);
|
||||
|
||||
CustomColorMapLen = count;
|
||||
|
||||
memcpy(CustomColorMap, triplets, 3 * count);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
uint8 VCE::Read(uint32 A)
|
||||
{
|
||||
uint8 ret = 0xFF;
|
||||
|
||||
if(!PCE_InDebug)
|
||||
Sync(HuCPU->Timestamp());
|
||||
|
||||
switch(A & 0x7)
|
||||
{
|
||||
case 4: ret = color_table[ctaddress & 0x1FF];
|
||||
break;
|
||||
|
||||
case 5: ret = color_table[ctaddress & 0x1FF] >> 8;
|
||||
ret &= 1;
|
||||
ret |= 0xFE;
|
||||
if(!PCE_InDebug)
|
||||
ctaddress++;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!PCE_InDebug)
|
||||
HuCPU->SetEvent(CalcNextEvent());
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void VCE::Write(uint32 A, uint8 V)
|
||||
{
|
||||
Sync(HuCPU->Timestamp());
|
||||
|
||||
//printf("VCE Write(vce scanline=%d, HuCPU.timestamp=%d): %04x %02x\n", scanline, HuCPU.timestamp, A, V);
|
||||
switch(A&0x7)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
int old_dot_clock = dot_clock;
|
||||
|
||||
SetVCECR(V);
|
||||
|
||||
if(old_dot_clock != dot_clock) // FIXME, this is wrong. A total fix will require changing the meaning
|
||||
// of clock_divider variable.
|
||||
{
|
||||
clock_divider = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: ctaddress &= 0x100; ctaddress |= V; break;
|
||||
case 3: ctaddress &= 0x0FF; ctaddress |= (V & 1) << 8; break;
|
||||
case 4: color_table[ctaddress & 0x1FF] &= 0x100;
|
||||
color_table[ctaddress & 0x1FF] |= V;
|
||||
FixPCache(ctaddress & 0x1FF);
|
||||
break;
|
||||
case 5: color_table[ctaddress & 0x1FF] &= 0xFF;
|
||||
color_table[ctaddress & 0x1FF] |= (V & 1) << 8;
|
||||
FixPCache(ctaddress & 0x1FF);
|
||||
ctaddress++;
|
||||
break;
|
||||
}
|
||||
|
||||
HuCPU->SetEvent(CalcNextEvent());
|
||||
}
|
||||
|
||||
uint8 VCE::ReadVDC(uint32 A)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
if(!PCE_InDebug)
|
||||
Sync(HuCPU->Timestamp());
|
||||
|
||||
if(!sgfx)
|
||||
{
|
||||
ret = vdc[0]->Read(A, child_event[0], PCE_InDebug);
|
||||
}
|
||||
else
|
||||
{
|
||||
int chip = 0;
|
||||
|
||||
A &= 0x1F;
|
||||
|
||||
if(A & 0x8)
|
||||
{
|
||||
ret = 0;
|
||||
|
||||
switch(A)
|
||||
{
|
||||
case 0x8: ret = priority[0]; break;
|
||||
case 0x9: ret = priority[1]; break;
|
||||
case 0xA: ret = winwidths[0]; break;
|
||||
case 0xB: ret = winwidths[0] >> 8; break;
|
||||
case 0xC: ret = winwidths[1]; break;
|
||||
case 0xD: ret = winwidths[1] >> 8; break;
|
||||
case 0xE: ret = 0; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chip = (A & 0x10) >> 4;
|
||||
ret = vdc[chip]->Read(A & 0x3, child_event[chip], PCE_InDebug);
|
||||
}
|
||||
}
|
||||
|
||||
if(!PCE_InDebug)
|
||||
HuCPU->SetEvent(CalcNextEvent());
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void VCE::WriteVDC(uint32 A, uint8 V)
|
||||
{
|
||||
Sync(HuCPU->Timestamp());
|
||||
|
||||
if(!sgfx)
|
||||
{
|
||||
vdc[0]->Write(A & 0x1FFF, V, child_event[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
int chip = 0;
|
||||
|
||||
// For ST0/ST1/ST2
|
||||
A |= ((A >> 31) & st_mode) << 4;
|
||||
|
||||
A &= 0x1F;
|
||||
|
||||
if(A & 0x8)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x8: priority[0] = V; break;
|
||||
case 0x9: priority[1] = V; break;
|
||||
case 0xA: winwidths[0] &= 0x300; winwidths[0] |= V; break;
|
||||
case 0xB: winwidths[0] &= 0x0FF; winwidths[0] |= (V & 3) << 8; break;
|
||||
case 0xC: winwidths[1] &= 0x300; winwidths[1] |= V; break;
|
||||
case 0xD: winwidths[1] &= 0x0FF; winwidths[1] |= (V & 3) << 8; break;
|
||||
case 0xE: st_mode = V & 1; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chip = (A & 0x10) >> 4;
|
||||
vdc[chip]->Write(A & 0x3, V, child_event[chip]);
|
||||
}
|
||||
}
|
||||
|
||||
HuCPU->SetEvent(CalcNextEvent());
|
||||
}
|
||||
|
||||
void VCE::WriteVDC_ST(uint32 A, uint8 V)
|
||||
{
|
||||
Sync(HuCPU->Timestamp());
|
||||
|
||||
if(!sgfx)
|
||||
{
|
||||
vdc[0]->Write(A, V, child_event[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
int chip = st_mode & 1;
|
||||
vdc[chip]->Write(A, V, child_event[chip]);
|
||||
}
|
||||
|
||||
HuCPU->SetEvent(CalcNextEvent());
|
||||
}
|
||||
|
||||
void VCE::SetLayerEnableMask(uint64 mask)
|
||||
{
|
||||
for(unsigned chip = 0; chip < (unsigned)chip_count; chip++)
|
||||
{
|
||||
vdc[chip]->SetLayerEnableMask((mask >> (chip * 2)) & 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
int VCE::StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT VCE_StateRegs[] =
|
||||
{
|
||||
SFVARN(CR, "VCECR"),
|
||||
|
||||
SFVAR(ws_counter),
|
||||
|
||||
SFVARN(ctaddress, "ctaddress"),
|
||||
SFARRAY16N(color_table, 0x200, "color_table"),
|
||||
|
||||
SFVARN(clock_divider, "clock_divider"),
|
||||
SFARRAY32N(child_event, 2, "child_event"),
|
||||
SFVARN(scanline, "scanline"),
|
||||
SFVARN(pixel_offset, "pixel_offset"),
|
||||
SFVARN(hblank_counter, "hblank_counter"),
|
||||
SFVARN(vblank_counter, "vblank_counter"),
|
||||
SFVAR(hblank),
|
||||
SFVAR(vblank),
|
||||
SFVAR(NeedSLReset),
|
||||
|
||||
SFVAR(last_ts),
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, VCE_StateRegs, "VCE");
|
||||
|
||||
if(sgfx)
|
||||
{
|
||||
SFORMAT VPC_StateRegs[] =
|
||||
{
|
||||
SFARRAYN(priority, 2, "priority"),
|
||||
SFARRAY16N(winwidths, 2, "winwidths"),
|
||||
SFVARN(st_mode, "st_mode"),
|
||||
SFARRAY32N(window_counter, 2, "window_counter"),
|
||||
SFEND
|
||||
};
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, VPC_StateRegs, "VPC");
|
||||
}
|
||||
|
||||
if(load)
|
||||
{
|
||||
// TODO/FIXME: Integrity checks to prevent buffer overflows.
|
||||
SetVCECR(CR);
|
||||
for(int x = 0; x < 512; x++)
|
||||
FixPCache(x);
|
||||
}
|
||||
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
ret &= vdc[chip]->StateAction(sm, load, data_only, chip ? "VDCB" : "VDC");
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
|
||||
uint32 VCE::GetRegister(const unsigned int id, char *special, const uint32 special_len)
|
||||
{
|
||||
uint32 value = 0xDEADBEEF;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case GSREG_CR:
|
||||
value = CR;
|
||||
if(special)
|
||||
{
|
||||
trio_snprintf(special, special_len, "Clock: %.2fMHz, %d lines/frame, Strip colorburst: %s",
|
||||
round(PCE_MASTER_CLOCK / 1e4 / vce_ratios[(value & 0x3) &~ ((value & 0x2) >> 1)]) / 100,
|
||||
(value & 0x04) ? 263 : 262,
|
||||
(value & 0x80) ? "On" : "Off");
|
||||
}
|
||||
break;
|
||||
|
||||
case GSREG_CTA:
|
||||
value = ctaddress;
|
||||
break;
|
||||
|
||||
case GSREG_SCANLINE:
|
||||
value = scanline;
|
||||
break;
|
||||
|
||||
// VPC:
|
||||
case GSREG_ST_MODE:
|
||||
value = st_mode;
|
||||
break;
|
||||
|
||||
case GSREG_WINDOW_WIDTH_0:
|
||||
case GSREG_WINDOW_WIDTH_1:
|
||||
value = winwidths[id - GSREG_WINDOW_WIDTH_0];
|
||||
if(special)
|
||||
{
|
||||
trio_snprintf(special, special_len, "Window width: %d%s", value - 0x40, (value <= 0x40) ? "(window disabled)" : "");
|
||||
}
|
||||
break;
|
||||
|
||||
case GSREG_PRIORITY_0:
|
||||
case GSREG_PRIORITY_1:
|
||||
value = priority[id - GSREG_PRIORITY_0];
|
||||
break;
|
||||
}
|
||||
return(value);
|
||||
}
|
||||
|
||||
void VCE::SetRegister(const unsigned int id, const uint32 value)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case GSREG_CR:
|
||||
SetVCECR(value);
|
||||
break;
|
||||
|
||||
case GSREG_CTA:
|
||||
ctaddress = value & 0x1FF;
|
||||
break;
|
||||
// VPC:
|
||||
case GSREG_ST_MODE:
|
||||
st_mode = (bool)value;
|
||||
break;
|
||||
|
||||
case GSREG_WINDOW_WIDTH_0:
|
||||
case GSREG_WINDOW_WIDTH_1:
|
||||
winwidths[id - GSREG_WINDOW_WIDTH_0] = value & 0x3FF;
|
||||
break;
|
||||
|
||||
case GSREG_PRIORITY_0:
|
||||
case GSREG_PRIORITY_1:
|
||||
priority[id - GSREG_PRIORITY_0] = value;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void VCE::SetGraphicsDecode(MDFN_Surface *surface, int line, int which, int xscroll, int yscroll, int pbn)
|
||||
{
|
||||
GfxDecode_Buf = surface;
|
||||
GfxDecode_Line = line;
|
||||
GfxDecode_Layer = which;
|
||||
GfxDecode_Scroll = yscroll;
|
||||
GfxDecode_Pbn = pbn;
|
||||
|
||||
if(GfxDecode_Buf && GfxDecode_Line == -1)
|
||||
DoGfxDecode();
|
||||
}
|
||||
|
||||
uint32 VCE::GetRegisterVDC(const unsigned int which_vdc, const unsigned int id, char *special, const uint32 special_len)
|
||||
{
|
||||
assert(which_vdc < (unsigned int)chip_count);
|
||||
|
||||
return(vdc[which_vdc]->GetRegister(id, special, special_len));
|
||||
}
|
||||
|
||||
void VCE::SetRegisterVDC(const unsigned int which_vdc, const unsigned int id, const uint32 value)
|
||||
{
|
||||
assert(which_vdc < (unsigned int)chip_count);
|
||||
|
||||
vdc[which_vdc]->SetRegister(id, value);
|
||||
}
|
||||
|
||||
|
||||
uint16 VCE::PeekPRAM(const uint16 Address)
|
||||
{
|
||||
return(color_table[Address & 0x1FF]);
|
||||
}
|
||||
|
||||
void VCE::PokePRAM(const uint16 Address, const uint16 Data)
|
||||
{
|
||||
color_table[Address & 0x1FF] = Data & 0x1FF;
|
||||
FixPCache(Address);
|
||||
}
|
||||
|
||||
|
||||
void VCE::DoGfxDecode(void)
|
||||
{
|
||||
const int which_vdc = (GfxDecode_Layer >> 1) & 1;
|
||||
const bool DecodeSprites = GfxDecode_Layer & 1;
|
||||
uint32 neo_palette[16];
|
||||
|
||||
assert(GfxDecode_Buf);
|
||||
|
||||
if(GfxDecode_Pbn == -1)
|
||||
{
|
||||
for(int x = 0; x < 16; x++)
|
||||
neo_palette[x] = GfxDecode_Buf->MakeColor(x * 17, x * 17, x * 17, 0xFF);
|
||||
}
|
||||
else
|
||||
for(int x = 0; x < 16; x++)
|
||||
neo_palette[x] = color_table_cache[x | (DecodeSprites ? 0x100 : 0x000) | ((GfxDecode_Pbn & 0xF) << 4)] | GfxDecode_Buf->MakeColor(0, 0, 0, 0xFF);
|
||||
|
||||
vdc[which_vdc]->DoGfxDecode(GfxDecode_Buf->pixels, neo_palette, GfxDecode_Buf->MakeColor(0, 0, 0, 0xFF), DecodeSprites, GfxDecode_Buf->w, GfxDecode_Buf->h, GfxDecode_Scroll);
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
|
@ -1,316 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __PCE_VCE_H
|
||||
#define __PCE_VCE_H
|
||||
|
||||
#include "huc6280/huc6280.h"
|
||||
#include "huc6270/vdc.h"
|
||||
|
||||
namespace MDFN_IEN_PCE
|
||||
{
|
||||
|
||||
//class VDC;
|
||||
//#include "vdc.h"
|
||||
|
||||
class VCE : public HuC6280_Support
|
||||
{
|
||||
public:
|
||||
|
||||
VCE(bool want_sgfx, bool nospritelimit);
|
||||
~VCE();
|
||||
|
||||
void SetShowHorizOS(bool show);
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void SetPixelFormat(const MDFN_PixelFormat &format);
|
||||
bool SetCustomColorMap(const uint8 *triplets, const uint32 count); // count = 512 or 1024
|
||||
|
||||
void StartFrame(MDFN_Surface *surface, MDFN_Rect *DisplayRect, MDFN_Rect *LineWidths, int skip);
|
||||
bool RunPartial(void);
|
||||
|
||||
inline int GetScanlineNo(void)
|
||||
{
|
||||
return(scanline);
|
||||
}
|
||||
|
||||
virtual int32 Sync(const int32 timestamp);
|
||||
|
||||
void Reset(const int32 timestamp);
|
||||
|
||||
void Write(uint32 A, uint8 V);
|
||||
uint8 Read(uint32 A);
|
||||
|
||||
uint8 ReadVDC(uint32 A);
|
||||
void WriteVDC(uint32 A, uint8 V);
|
||||
void WriteVDC_ST(uint32 A, uint8 V);
|
||||
|
||||
void SetLayerEnableMask(uint64 mask);
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
|
||||
uint16 PeekPRAM(const uint16 Address);
|
||||
void PokePRAM(const uint16 Address, const uint16 Data);
|
||||
|
||||
|
||||
// Peek(VRAM/SAT) and Poke(VRAM/SAT) work in 16-bit VRAM word units(Address and Length, both).
|
||||
INLINE uint16 PeekVDCVRAM(unsigned int which, uint16 Address)
|
||||
{
|
||||
assert(which < (unsigned int)chip_count);
|
||||
|
||||
return(vdc[which]->PeekVRAM(Address));
|
||||
}
|
||||
|
||||
INLINE uint16 PeekVDCSAT(unsigned int which, uint8 Address)
|
||||
{
|
||||
assert(which < (unsigned int)chip_count);
|
||||
|
||||
return(vdc[which]->PeekSAT(Address));
|
||||
}
|
||||
|
||||
INLINE void PokeVDCVRAM(const unsigned int which, const uint16 Address, const uint16 Data)
|
||||
{
|
||||
assert(which < (unsigned int)chip_count);
|
||||
|
||||
vdc[which]->PokeVRAM(Address, Data);
|
||||
}
|
||||
|
||||
INLINE void PokeVDCSAT(const unsigned int which, const uint8 Address, const uint16 Data)
|
||||
{
|
||||
assert(which < (unsigned int)chip_count);
|
||||
|
||||
vdc[which]->PokeSAT(Address, Data);
|
||||
}
|
||||
|
||||
void SetGraphicsDecode(MDFN_Surface *surface, int line, int which, int xscroll, int yscroll, int pbn);
|
||||
|
||||
enum
|
||||
{
|
||||
GSREG_CR = 0,
|
||||
GSREG_CTA,
|
||||
GSREG_SCANLINE,
|
||||
|
||||
// VPC:
|
||||
GSREG_PRIORITY_0,
|
||||
GSREG_PRIORITY_1,
|
||||
GSREG_WINDOW_WIDTH_0,
|
||||
GSREG_WINDOW_WIDTH_1,
|
||||
GSREG_ST_MODE
|
||||
};
|
||||
|
||||
uint32 GetRegister(const unsigned int id, char *special, const uint32 special_len);
|
||||
void SetRegister(const unsigned int id, const uint32 value);
|
||||
|
||||
|
||||
uint32 GetRegisterVDC(const unsigned int which_vdc, const unsigned int id, char *special, const uint32 special_len);
|
||||
void SetRegisterVDC(const unsigned int which_vdc, const unsigned int id, const uint32 value);
|
||||
|
||||
INLINE void ResetSimulateVDC(void)
|
||||
{
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
vdc[chip]->ResetSimulate();
|
||||
}
|
||||
|
||||
INLINE int SimulateReadVDC(uint32 A, VDC_SimulateResult *result)
|
||||
{
|
||||
if(!sgfx)
|
||||
{
|
||||
vdc[0]->SimulateRead(A, result);
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int chip = 0;
|
||||
|
||||
A &= 0x1F;
|
||||
|
||||
if(!(A & 0x8))
|
||||
{
|
||||
chip = (A & 0x10) >> 4;
|
||||
vdc[chip]->SimulateRead(A & 0x3, result);
|
||||
return(chip);
|
||||
}
|
||||
}
|
||||
|
||||
result->ReadCount = result->WriteCount = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
// If the simulated write is due to a ST0, ST1, or ST2 instruction, set the high bit of the passed address to 1.
|
||||
INLINE int SimulateWriteVDC(uint32 A, uint8 V, VDC_SimulateResult *result)
|
||||
{
|
||||
if(!sgfx)
|
||||
{
|
||||
vdc[0]->SimulateWrite(A, V, result);
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For ST0/ST1/ST2
|
||||
A |= ((A >> 31) & st_mode) << 4;
|
||||
|
||||
A &= 0x1F;
|
||||
|
||||
if(!(A & 0x8))
|
||||
{
|
||||
int chip = (A & 0x10) >> 4;
|
||||
vdc[chip]->SimulateWrite(A & 0x3, V, result);
|
||||
return(chip);
|
||||
}
|
||||
}
|
||||
|
||||
result->ReadCount = result->WriteCount = 0;
|
||||
result->ReadStart = result->WriteStart = 0;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void IRQChangeCheck(void);
|
||||
|
||||
bool WS_Hook(int32 vdc_cycles);
|
||||
|
||||
|
||||
// So wrong, but feels so...MUSHROOMY.
|
||||
// THIS IS BROKEN!
|
||||
// We need to put Sync() call before that, or bias
|
||||
// cd_event and the value to HuCPU->SetEvent by (HuCPU->timestamp - last_ts)
|
||||
INLINE void SetCDEvent(const int32 cycles)
|
||||
{
|
||||
const int32 time_behind = HuCPU->Timestamp() - last_ts;
|
||||
|
||||
assert(time_behind >= 0);
|
||||
|
||||
cd_event = cycles + time_behind;
|
||||
HuCPU->SetEvent(CalcNextEvent() - time_behind);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void FixPCache(int entry);
|
||||
void SetVCECR(uint8 V);
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
void DoGfxDecode(void);
|
||||
#endif
|
||||
|
||||
INLINE int32 CalcNextEvent(void)
|
||||
{
|
||||
int32 next_event = hblank_counter;
|
||||
|
||||
if(next_event > vblank_counter)
|
||||
next_event = vblank_counter;
|
||||
|
||||
if(next_event > cd_event)
|
||||
next_event = cd_event;
|
||||
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
{
|
||||
int fwoom = (child_event[chip] * dot_clock_ratio - clock_divider);
|
||||
|
||||
if(fwoom < 1)
|
||||
fwoom = 1;
|
||||
|
||||
if(next_event > fwoom)
|
||||
next_event = fwoom;
|
||||
}
|
||||
|
||||
if(next_event < 1)
|
||||
next_event = 1;
|
||||
|
||||
return(next_event);
|
||||
}
|
||||
|
||||
int32 child_event[2];
|
||||
|
||||
int32 cd_event;
|
||||
|
||||
uint32 *fb; // Pointer to the framebuffer.
|
||||
uint32 pitch32; // Pitch(in 32-bit pixels)
|
||||
bool FrameDone;
|
||||
|
||||
void (*RunHook)(int32 clocks, uint16 *pixels);
|
||||
|
||||
// Called when the state changes, with the new state.
|
||||
void (*HBlankHook)(bool status);
|
||||
void (*VBlankHook)(bool status);
|
||||
|
||||
int32 clock_divider;
|
||||
|
||||
int32 scanline;
|
||||
uint32 *scanline_out_ptr; // Pointer into fb
|
||||
int32 pixel_offset;
|
||||
|
||||
int32 hblank_counter;
|
||||
int32 vblank_counter;
|
||||
|
||||
bool hblank; // TRUE if in HBLANK, FALSE if not.
|
||||
bool vblank; // TRUE if in vblank, FALSE if not
|
||||
|
||||
bool NeedSLReset;
|
||||
|
||||
|
||||
uint8 CR; // Control Register
|
||||
bool lc263; // CR->263 line count if set, 262 if not
|
||||
bool bw; // CR->Black and White
|
||||
uint8 dot_clock; // CR->Dot Clock(5, 7, or 10 MHz = 0, 1, 2/3)
|
||||
int32 dot_clock_ratio; // CR->Dot Clock ratio cache
|
||||
|
||||
int32 ws_counter;
|
||||
|
||||
uint16 color_table[0x200];
|
||||
uint32 color_table_cache[0x200 * 2]; // * 2 for user layer disabling stuff.
|
||||
uint16 ctaddress;
|
||||
|
||||
|
||||
uint8 *CustomColorMap; // 1024 * 3
|
||||
uint32 CustomColorMapLen; // 512 or 1024
|
||||
|
||||
uint32 systemColorMap32[512], bw_systemColorMap32[512];
|
||||
|
||||
int32 last_ts;
|
||||
|
||||
VDC *vdc[2];
|
||||
|
||||
// SuperGrafx stuff:
|
||||
bool sgfx;
|
||||
int chip_count; // = 1 when sgfx is FALSE, = 2 when sgfx is TRUE
|
||||
uint8 priority[2];
|
||||
uint16 winwidths[2];
|
||||
uint8 st_mode;
|
||||
int32 window_counter[2];
|
||||
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
MDFN_Surface *GfxDecode_Buf;// = NULL;
|
||||
int GfxDecode_Line;// = -1;
|
||||
int GfxDecode_Layer;// = 0;
|
||||
int GfxDecode_Scroll;// = 0;
|
||||
int GfxDecode_Pbn;// = 0;
|
||||
#endif
|
||||
|
||||
bool ShowHorizOS;
|
||||
|
||||
bool SubTValid;
|
||||
uint16 SubTBuffer[0x100];
|
||||
uint32 SubTLUT[4096];
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,272 +0,0 @@
|
|||
while(clocks > 0)
|
||||
{
|
||||
int32 div_clocks;
|
||||
int32 chunk_clocks = clocks;
|
||||
|
||||
if(chunk_clocks > hblank_counter)
|
||||
chunk_clocks = hblank_counter;
|
||||
|
||||
if(chunk_clocks > vblank_counter)
|
||||
chunk_clocks = vblank_counter;
|
||||
|
||||
#ifdef VCE_SGFX_MODE
|
||||
for(int chip = 0; chip < 2; chip++)
|
||||
{
|
||||
#else
|
||||
{
|
||||
const int chip = 0;
|
||||
#endif
|
||||
int fwoom = (child_event[chip] * dot_clock_ratio - clock_divider);
|
||||
|
||||
assert(fwoom >= 1);
|
||||
|
||||
if(chunk_clocks > fwoom)
|
||||
chunk_clocks = fwoom;
|
||||
}
|
||||
|
||||
clock_divider += chunk_clocks;
|
||||
div_clocks = clock_divider / dot_clock_ratio;
|
||||
clock_divider -= div_clocks * dot_clock_ratio;
|
||||
|
||||
child_event[0] -= div_clocks;
|
||||
#ifdef VCE_SGFX_MODE
|
||||
child_event[1] -= div_clocks;
|
||||
#endif
|
||||
|
||||
if(div_clocks > 0)
|
||||
{
|
||||
#ifdef VCE_SGFX_MODE
|
||||
uint16 pixels[2][div_clocks];
|
||||
#else
|
||||
uint16 pixels[1][div_clocks];
|
||||
#endif
|
||||
|
||||
child_event[0] = vdc[0]->Run(div_clocks, pixels[0], skipframe);
|
||||
#ifdef VCE_SGFX_MODE
|
||||
child_event[1] = vdc[1]->Run(div_clocks, pixels[1], skipframe);
|
||||
#endif
|
||||
|
||||
if(!skipframe)
|
||||
{
|
||||
#ifdef VCE_SGFX_MODE
|
||||
{
|
||||
for(int32 i = 0; i < div_clocks; i++) // * vce_ratios[dot_clock]; i++)
|
||||
{
|
||||
static const int prio_select[4] = { 1, 1, 0, 0 };
|
||||
static const int prio_shift[4] = { 4, 0, 4, 0 };
|
||||
uint32 pix;
|
||||
int in_window = 0;
|
||||
|
||||
if(window_counter[0] > 0x40)
|
||||
{
|
||||
in_window |= 1;
|
||||
window_counter[0]--;
|
||||
}
|
||||
|
||||
if(window_counter[1] > 0x40)
|
||||
{
|
||||
in_window |= 2;
|
||||
window_counter[1]--;
|
||||
}
|
||||
|
||||
uint8 pb = (priority[prio_select[in_window]] >> prio_shift[in_window]) & 0xF;
|
||||
uint32 vdc2_pixel, vdc1_pixel;
|
||||
|
||||
vdc2_pixel = vdc1_pixel = 0;
|
||||
|
||||
if(pb & 1)
|
||||
vdc1_pixel = pixels[0][i];
|
||||
if(pb & 2)
|
||||
vdc2_pixel = pixels[1][i];
|
||||
|
||||
/* Dai MakaiMura uses setting 1, and expects VDC #2 sprites in front of VDC #1 background, but
|
||||
behind VDC #1's sprites.
|
||||
*/
|
||||
switch(pb >> 2)
|
||||
{
|
||||
case 1:
|
||||
if((vdc2_pixel & 0x100) && !(vdc1_pixel & 0x100) && (vdc2_pixel & 0xF))
|
||||
vdc1_pixel = 0; //amask;
|
||||
break;
|
||||
case 2:
|
||||
if((vdc1_pixel & 0x100) && !(vdc2_pixel & 0x100) && (vdc2_pixel & 0xF))
|
||||
vdc1_pixel = 0; //|= amask;
|
||||
break;
|
||||
}
|
||||
pix = color_table_cache[((vdc1_pixel & 0xF) ? vdc1_pixel : vdc2_pixel) & 0x1FF];
|
||||
|
||||
#if SUPERDUPERMODE
|
||||
for(int32 s_i = 0; s_i < dot_clock_ratio; s_i++)
|
||||
#endif
|
||||
{
|
||||
scanline_out_ptr[pixel_offset] = pix;
|
||||
pixel_offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
#if SUPERDUPERMODE
|
||||
for(int32 i = 0; i < div_clocks; i++)
|
||||
{
|
||||
for(int32 si = 0; si < dot_clock_ratio; si++)
|
||||
{
|
||||
uint32 pix = color_table_cache[pixels[0][i] & 0x3FF];
|
||||
|
||||
scanline_out_ptr[pixel_offset] = pix;
|
||||
pixel_offset++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for(int32 i = 0; i < div_clocks; i++) // * vce_ratios[dot_clock]; i++)
|
||||
{
|
||||
uint32 pix = color_table_cache[pixels[0][i] & 0x3FF];
|
||||
scanline_out_ptr[pixel_offset] = pix;
|
||||
pixel_offset++;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//pixel_offset += div_clocks * dot_clock_ratio;
|
||||
}
|
||||
|
||||
clocks -= chunk_clocks;
|
||||
hblank_counter -= chunk_clocks;
|
||||
if(hblank_counter <= 0)
|
||||
{
|
||||
hblank ^= 1;
|
||||
|
||||
if(hblank)
|
||||
{
|
||||
// Clock gets stretched and "synchronized" at the beginning of the 237-master-cycle hsync period.
|
||||
//clock_divider = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 *prev_sop = scanline_out_ptr;
|
||||
|
||||
if(sgfx)
|
||||
{
|
||||
int add = 0;
|
||||
if(dot_clock & 2)
|
||||
add = 8 + 96;
|
||||
else
|
||||
add = 8 + (dot_clock ? 38 : 24);
|
||||
window_counter[0] = winwidths[0] + add;
|
||||
window_counter[1] = winwidths[1] + add;
|
||||
}
|
||||
|
||||
if(NeedSLReset)
|
||||
scanline = 0;
|
||||
else
|
||||
scanline++;
|
||||
|
||||
if(scanline == 14 + 240)
|
||||
FrameDone = true;
|
||||
|
||||
if((scanline == 14 + 240) || (scanline == 123))
|
||||
{
|
||||
HuCPU->Exit();
|
||||
}
|
||||
|
||||
#if 0 // Testing code
|
||||
HuCPU->Exit();
|
||||
#endif
|
||||
|
||||
//printf("VCE New scanline: %d\n", scanline);
|
||||
|
||||
scanline_out_ptr = &fb[scanline * pitch32];
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
if(GfxDecode_Buf && GfxDecode_Line == scanline)
|
||||
DoGfxDecode();
|
||||
#endif
|
||||
|
||||
pixel_offset = 0;
|
||||
NeedSLReset = FALSE;
|
||||
|
||||
if(!skipframe)
|
||||
{
|
||||
static const int x_offsets[2][4] = {
|
||||
{ 8 + 24, 8 + 38, 8 + 96, 8 + 96 },
|
||||
{ 8 + 24 - 12, 8 + 38 - 16, 8 + 96 - 24, 8 + 96 - 24 },
|
||||
};
|
||||
static const int w_cows[2][4] = {
|
||||
{ 256, 341, 512, 512 },
|
||||
{ 256 + 24, 341 + 32, 512 + 48, 512 + 48 },
|
||||
};
|
||||
|
||||
int rect_x, rect_w;
|
||||
|
||||
#if SUPERDUPERMODE
|
||||
{
|
||||
if(dot_clock >= 2)
|
||||
rect_x = 208;
|
||||
else if(dot_clock == 1)
|
||||
rect_x = 136;
|
||||
else
|
||||
rect_x = 128;
|
||||
rect_w = 1024;
|
||||
|
||||
if(ShowHorizOS)
|
||||
{
|
||||
rect_x -= 48;
|
||||
rect_w += 96;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
rect_x = x_offsets[ShowHorizOS][dot_clock];
|
||||
rect_w = w_cows[ShowHorizOS][dot_clock];
|
||||
}
|
||||
#endif
|
||||
|
||||
LW[scanline].x = rect_x;
|
||||
LW[scanline].w = rect_w;
|
||||
|
||||
if(SubTValid && prev_sop)
|
||||
{
|
||||
uint32 *slp = prev_sop + x_offsets[0][dot_clock];
|
||||
uint32 scale_factor = 256 * 65536 / w_cows[0][dot_clock];
|
||||
for(int x = 0; x < w_cows[0][dot_clock]; x++)
|
||||
{
|
||||
uint32 src_x = (x * scale_factor) >> 16;
|
||||
uint32 mul_front = (SubTBuffer[src_x] >> 12) & 0xF;
|
||||
uint32 mul_back = 16 - mul_front;
|
||||
uint32 front = SubTLUT[SubTBuffer[src_x] & 0xFFF];
|
||||
uint32 back = slp[x];
|
||||
|
||||
front = (((front & 0xF0F0F0F0) >> 4) * mul_front) + ((((front & 0x0F0F0F0F) * mul_front) >> 4) & 0x0F0F0F0F);
|
||||
back = (((back & 0xF0F0F0F0) >> 4) * mul_back) + ((((back & 0x0F0F0F0F) * mul_back) >> 4) & 0x0F0F0F0F);
|
||||
|
||||
slp[x] = front + back;
|
||||
}
|
||||
}
|
||||
}
|
||||
SubTValid = SubHW_DisplayLine(SubTBuffer);
|
||||
}
|
||||
hblank_counter = hblank ? 237 : 1128;
|
||||
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
child_event[chip] = vdc[chip]->HSync(hblank);
|
||||
}
|
||||
|
||||
vblank_counter -= chunk_clocks;
|
||||
if(vblank_counter <= 0)
|
||||
{
|
||||
vblank ^= 1;
|
||||
vblank_counter = vblank ? 4095 : ((lc263 ? 358995 : 357630) - 4095);
|
||||
|
||||
if(!vblank)
|
||||
{
|
||||
NeedSLReset = TRUE;
|
||||
}
|
||||
else
|
||||
SubHW_CVSync();
|
||||
|
||||
for(int chip = 0; chip < chip_count; chip++)
|
||||
child_event[chip] = vdc[chip]->VSync(vblank);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MATH_OPTIMIZER_FLAGS@
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir)/src/hw_misc -I$(top_srcdir)/src/hw_sound
|
||||
|
||||
noinst_LIBRARIES = libpce_fast.a
|
||||
mednafen_SOURCES = huc6280.cpp pce.cpp vdc.cpp input.cpp huc.cpp hes.cpp tsushin.cpp
|
||||
|
||||
libpce_fast_a_SOURCES = $(mednafen_SOURCES)
|
|
@ -1,605 +0,0 @@
|
|||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = src/pce_fast
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
|
||||
$(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \
|
||||
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \
|
||||
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \
|
||||
$(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \
|
||||
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \
|
||||
$(top_srcdir)/m4/inttypes-pri.m4 \
|
||||
$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
|
||||
$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
|
||||
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
|
||||
$(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \
|
||||
$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
|
||||
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
AM_V_AR = $(am__v_AR_$(V))
|
||||
am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_AR_0 = @echo " AR " $@;
|
||||
AM_V_at = $(am__v_at_$(V))
|
||||
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_at_0 = @
|
||||
libpce_fast_a_AR = $(AR) $(ARFLAGS)
|
||||
libpce_fast_a_LIBADD =
|
||||
am__objects_1 = huc6280.$(OBJEXT) pce.$(OBJEXT) vdc.$(OBJEXT) \
|
||||
input.$(OBJEXT) huc.$(OBJEXT) hes.$(OBJEXT) tsushin.$(OBJEXT)
|
||||
am_libpce_fast_a_OBJECTS = $(am__objects_1)
|
||||
libpce_fast_a_OBJECTS = $(am_libpce_fast_a_OBJECTS)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_lt = $(am__v_lt_$(V))
|
||||
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_lt_0 = --silent
|
||||
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_CXX = $(am__v_CXX_$(V))
|
||||
am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CXX_0 = @echo " CXX " $@;
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
|
||||
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CXXLD = $(am__v_CXXLD_$(V))
|
||||
am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CXXLD_0 = @echo " CXXLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_$(V))
|
||||
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libpce_fast_a_SOURCES)
|
||||
DIST_SOURCES = $(libpce_fast_a_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ALLOCA = @ALLOCA@
|
||||
ALSA_CFLAGS = @ALSA_CFLAGS@
|
||||
ALSA_LIBS = @ALSA_LIBS@
|
||||
AMTAR = @AMTAR@
|
||||
AM_CFLAGS = @AM_CFLAGS@
|
||||
AM_CXXFLAGS = @AM_CXXFLAGS@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
CC = @CC@
|
||||
CCAS = @CCAS@
|
||||
CCASDEPMODE = @CCASDEPMODE@
|
||||
CCASFLAGS = @CCASFLAGS@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DATADIRNAME = @DATADIRNAME@
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MATH_OPTIMIZER_FLAGS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GBA_EXTRA_FLAGS = @GBA_EXTRA_FLAGS@
|
||||
GENCAT = @GENCAT@
|
||||
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||
GLIBC2 = @GLIBC2@
|
||||
GLIBC21 = @GLIBC21@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GMSGFMT_015 = @GMSGFMT_015@
|
||||
GREP = @GREP@
|
||||
HAVE_ASPRINTF = @HAVE_ASPRINTF@
|
||||
HAVE_NEWLOCALE = @HAVE_NEWLOCALE@
|
||||
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
|
||||
HAVE_SNPRINTF = @HAVE_SNPRINTF@
|
||||
HAVE_VISIBILITY = @HAVE_VISIBILITY@
|
||||
HAVE_WPRINTF = @HAVE_WPRINTF@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
INTLBISON = @INTLBISON@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTLOBJS = @INTLOBJS@
|
||||
INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@
|
||||
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
|
||||
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||
JACK_CFLAGS = @JACK_CFLAGS@
|
||||
JACK_LIBS = @JACK_LIBS@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@
|
||||
LIBCDIO_LIBS = @LIBCDIO_LIBS@
|
||||
LIBICONV = @LIBICONV@
|
||||
LIBINTL = @LIBINTL@
|
||||
LIBMULTITHREAD = @LIBMULTITHREAD@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPTH = @LIBPTH@
|
||||
LIBPTH_PREFIX = @LIBPTH_PREFIX@
|
||||
LIBS = @LIBS@
|
||||
LIBTHREAD = @LIBTHREAD@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBC = @LTLIBC@
|
||||
LTLIBICONV = @LTLIBICONV@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBMULTITHREAD = @LTLIBMULTITHREAD@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LTLIBPTH = @LTLIBPTH@
|
||||
LTLIBTHREAD = @LTLIBTHREAD@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MATH_OPTIMIZER_FLAGS = @MATH_OPTIMIZER_FLAGS@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MMX_CFLAGS = @MMX_CFLAGS@
|
||||
MSGFMT = @MSGFMT@
|
||||
MSGFMT_015 = @MSGFMT_015@
|
||||
MSGMERGE = @MSGMERGE@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
POSUB = @POSUB@
|
||||
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SNDFILE_CFLAGS = @SNDFILE_CFLAGS@
|
||||
SNDFILE_LIBS = @SNDFILE_LIBS@
|
||||
SNES_EXTRA_CXXFLAGS = @SNES_EXTRA_CXXFLAGS@
|
||||
SNES_EXTRA_FLAGS = @SNES_EXTRA_FLAGS@
|
||||
SSE2_CFLAGS = @SSE2_CFLAGS@
|
||||
SSE3_CFLAGS = @SSE3_CFLAGS@
|
||||
SSE_CFLAGS = @SSE_CFLAGS@
|
||||
STRIP = @STRIP@
|
||||
TRIO_CFLAGS = @TRIO_CFLAGS@
|
||||
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
WARNING_FLAGS = @WARNING_FLAGS@
|
||||
WINDRES = @WINDRES@
|
||||
WOE32 = @WOE32@
|
||||
WOE32DLL = @WOE32DLL@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
XMKMF = @XMKMF@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir)/src/hw_misc -I$(top_srcdir)/src/hw_sound
|
||||
noinst_LIBRARIES = libpce_fast.a
|
||||
mednafen_SOURCES = huc6280.cpp pce.cpp vdc.cpp input.cpp huc.cpp hes.cpp tsushin.cpp
|
||||
libpce_fast_a_SOURCES = $(mednafen_SOURCES)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pce_fast/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/pce_fast/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libpce_fast.a: $(libpce_fast_a_OBJECTS) $(libpce_fast_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libpce_fast.a
|
||||
$(AM_V_AR)$(libpce_fast_a_AR) libpce_fast.a $(libpce_fast_a_OBJECTS) $(libpce_fast_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libpce_fast.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hes.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huc6280.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pce.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsushin.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vdc.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.cpp.lo:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLIBRARIES ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -1,249 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "hes.h"
|
||||
#include "huc.h"
|
||||
#include "../cdrom/pcecd.h"
|
||||
#include "../player.h"
|
||||
#include "../endian.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
|
||||
static uint8 mpr_start[8];
|
||||
static uint8 IBP_Bank[0x2000];
|
||||
static uint8 *rom = NULL, *rom_backup = NULL;
|
||||
|
||||
static uint8 CurrentSong;
|
||||
static bool bootstrap;
|
||||
static bool ROMWriteWarningGiven;
|
||||
|
||||
uint8 ReadIBP(unsigned int A)
|
||||
{
|
||||
if(!(A & 0x100))
|
||||
return(IBP_Bank[0x1C00 + (A & 0xF)]);
|
||||
|
||||
if(bootstrap)
|
||||
{
|
||||
memcpy(rom + 0x1FF0, rom_backup + 0x1FF0, 16);
|
||||
bootstrap = false;
|
||||
return(CurrentSong);
|
||||
}
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(HESROMWrite)
|
||||
{
|
||||
rom[A] = V;
|
||||
//printf("%08x: %02x\n", A, V);
|
||||
if(!ROMWriteWarningGiven)
|
||||
{
|
||||
MDFN_printf(_("Warning: HES is writing to physical address %08x. Future warnings of this nature are temporarily disabled for this HES file.\n"), A);
|
||||
ROMWriteWarningGiven = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(HESROMRead)
|
||||
{
|
||||
return(rom[A]);
|
||||
}
|
||||
|
||||
int PCE_HESLoad(const uint8 *buf, uint32 size)
|
||||
{
|
||||
uint32 LoadAddr, LoadSize;
|
||||
uint32 CurPos;
|
||||
uint16 InitAddr;
|
||||
uint8 StartingSong;
|
||||
int TotalSongs;
|
||||
|
||||
InitAddr = MDFN_de16lsb(&buf[0x6]);
|
||||
|
||||
CurPos = 0x10;
|
||||
|
||||
if(!(rom = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!(rom_backup = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(rom, 0, 0x88 * 8192);
|
||||
memset(rom_backup, 0, 0x88 * 8192);
|
||||
|
||||
while(CurPos < (size - 0x10))
|
||||
{
|
||||
LoadSize = MDFN_de32lsb(&buf[CurPos + 0x4]);
|
||||
LoadAddr = MDFN_de32lsb(&buf[CurPos + 0x8]);
|
||||
|
||||
//printf("Size: %08x(%d), Addr: %08x, La: %02x\n", LoadSize, LoadSize, LoadAddr, LoadAddr / 8192);
|
||||
|
||||
CurPos += 0x10;
|
||||
|
||||
if(((uint64)LoadSize + CurPos) > size)
|
||||
{
|
||||
uint32 NewLoadSize = size - CurPos;
|
||||
|
||||
MDFN_printf(_("Warning: HES is trying to load more data than is present in the file(%u attempted, %u left)!\n"), LoadSize, NewLoadSize);
|
||||
|
||||
LoadSize = NewLoadSize;
|
||||
}
|
||||
|
||||
// 0x88 * 8192 = 0x110000
|
||||
if(((uint64)LoadAddr + LoadSize) > 0x110000)
|
||||
{
|
||||
MDFN_printf(_("Warning: HES is trying to load data past boundary.\n"));
|
||||
|
||||
if(LoadAddr >= 0x110000)
|
||||
break;
|
||||
|
||||
LoadSize = 0x110000 - LoadAddr;
|
||||
}
|
||||
|
||||
memcpy(rom + LoadAddr, &buf[CurPos], LoadSize);
|
||||
CurPos += LoadSize;
|
||||
}
|
||||
|
||||
for(int x = 0; x < 8; x++)
|
||||
mpr_start[x] = buf[0x8 + x];
|
||||
|
||||
memcpy(rom_backup, rom, 0x88 * 8192);
|
||||
|
||||
CurrentSong = StartingSong = buf[5];
|
||||
TotalSongs = 256;
|
||||
|
||||
memset(IBP_Bank, 0, 0x2000);
|
||||
|
||||
uint8 *IBP_WR = IBP_Bank + 0x1C00;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
*IBP_WR++ = 0xA9; // LDA (immediate)
|
||||
*IBP_WR++ = mpr_start[i];
|
||||
*IBP_WR++ = 0x53; // TAM
|
||||
*IBP_WR++ = 1 << i;
|
||||
}
|
||||
|
||||
*IBP_WR++ = 0xAD; // LDA(absolute)
|
||||
*IBP_WR++ = 0x00; //
|
||||
*IBP_WR++ = 0x1D; //
|
||||
*IBP_WR++ = 0x20; // JSR
|
||||
*IBP_WR++ = InitAddr; // JSR target LSB
|
||||
*IBP_WR++ = InitAddr >> 8; // JSR target MSB
|
||||
*IBP_WR++ = 0x58; // CLI
|
||||
*IBP_WR++ = 0xFC; // (Mednafen Special)
|
||||
*IBP_WR++ = 0x80; // BRA
|
||||
*IBP_WR++ = 0xFD; // -3
|
||||
|
||||
Player_Init(TotalSongs, "", "", ""); //NULL, NULL, NULL, NULL); //UTF8 **snames);
|
||||
|
||||
for(int x = 0; x < 0x80; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = rom;
|
||||
PCERead[x] = HESROMRead;
|
||||
PCEWrite[x] = HESROMWrite;
|
||||
}
|
||||
|
||||
HuCPUFastMap[0xFF] = IBP_Bank - (0xFF * 8192);
|
||||
|
||||
// FIXME: If a HES rip tries to execute a SCSI command, the CD emulation code will probably crash. Obviously, a HES rip shouldn't do this,
|
||||
// but Mednafen shouldn't crash either. ;)
|
||||
PCE_IsCD = 1;
|
||||
PCE_InitCD();
|
||||
|
||||
ROMWriteWarningGiven = FALSE;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static const uint8 BootROM[16] = { 0xA9, 0xFF, 0x53, 0x01, 0xEA, 0xEA, 0xEA, 0xEA,
|
||||
0xEA, 0xEA, 0xEA, 0x4C, 0x00, 0x1C, 0xF0, 0xFF };
|
||||
void HES_Reset(void)
|
||||
{
|
||||
memcpy(rom, rom_backup, 0x88 * 8192);
|
||||
memcpy(rom + 0x1FF0, BootROM, 16);
|
||||
bootstrap = true;
|
||||
}
|
||||
|
||||
|
||||
void HES_Draw(MDFN_Surface *surface, MDFN_Rect *DisplayRect, int16 *SoundBuf, int32 SoundBufSize)
|
||||
{
|
||||
extern uint16 pce_jp_data[5];
|
||||
static uint8 last = 0;
|
||||
bool needreload = 0;
|
||||
uint8 newset = (pce_jp_data[0] ^ last) & pce_jp_data[0];
|
||||
|
||||
if(newset & 0x20)
|
||||
{
|
||||
CurrentSong++;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if(newset & 0x80)
|
||||
{
|
||||
CurrentSong--;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if(newset & 0x08)
|
||||
needreload = 1;
|
||||
|
||||
if(newset & 0x10)
|
||||
{
|
||||
CurrentSong += 10;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if(newset & 0x40)
|
||||
{
|
||||
CurrentSong -= 10;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
last = pce_jp_data[0];
|
||||
|
||||
if(needreload)
|
||||
PCE_Power();
|
||||
|
||||
Player_Draw(surface, DisplayRect, CurrentSong, SoundBuf, SoundBufSize);
|
||||
}
|
||||
|
||||
void HES_Close(void)
|
||||
{
|
||||
PCECD_Close();
|
||||
|
||||
if(rom)
|
||||
{
|
||||
MDFN_free(rom);
|
||||
rom = NULL;
|
||||
}
|
||||
|
||||
if(rom_backup)
|
||||
{
|
||||
MDFN_free(rom_backup);
|
||||
rom_backup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
uint8 ReadIBP(unsigned int A);
|
||||
int PCE_HESLoad(const uint8 *buf, uint32 size);
|
||||
void HES_Reset(void);
|
||||
void HES_Draw(MDFN_Surface *surface, MDFN_Rect *DisplayRect, int16 *samples, int32 sampcount);
|
||||
void HES_Close(void);
|
||||
|
||||
};
|
|
@ -1,447 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* Portions of this file Copyright (C) 2004 Ki
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include <errno.h>
|
||||
#include "../cdrom/pcecd.h"
|
||||
#include "arcade_card/arcade_card.h"
|
||||
#include "../md5.h"
|
||||
#include "../file.h"
|
||||
#include "../cdrom/cdromif.h"
|
||||
#include "../mempatcher.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
static const uint8 BRAM_Init_String[8] = { 'H', 'U', 'B', 'M', 0x00, 0x88, 0x10, 0x80 }; //"HUBM\x00\x88\x10\x80";
|
||||
|
||||
ArcadeCard *arcade_card = NULL;
|
||||
|
||||
static uint8 *HuCROM = NULL;
|
||||
|
||||
static bool IsPopulous;
|
||||
bool IsTsushin;
|
||||
bool PCE_IsCD;
|
||||
|
||||
static uint8 *TsushinRAM = NULL; // 0x8000
|
||||
static uint8 SaveRAM[2048];
|
||||
|
||||
static DECLFW(ACPhysWrite)
|
||||
{
|
||||
arcade_card->PhysWrite(A, V);
|
||||
}
|
||||
|
||||
static DECLFR(ACPhysRead)
|
||||
{
|
||||
return(arcade_card->PhysRead(A));
|
||||
}
|
||||
|
||||
static DECLFR(SaveRAMRead)
|
||||
{
|
||||
if((!PCE_IsCD || PCECD_IsBRAMEnabled()) && (A & 8191) < 2048)
|
||||
return(SaveRAM[A & 2047]);
|
||||
else
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(SaveRAMWrite)
|
||||
{
|
||||
if((!PCE_IsCD || PCECD_IsBRAMEnabled()) && (A & 8191) < 2048)
|
||||
SaveRAM[A & 2047] = V;
|
||||
}
|
||||
|
||||
static DECLFR(HuCRead)
|
||||
{
|
||||
return ROMSpace[A];
|
||||
}
|
||||
|
||||
static DECLFW(HuCRAMWrite)
|
||||
{
|
||||
ROMSpace[A] = V;
|
||||
}
|
||||
|
||||
static DECLFW(HuCRAMWriteCDSpecial) // Hyper Dyne Special hack
|
||||
{
|
||||
BaseRAM[0x2000 | (A & 0x1FFF)] = V;
|
||||
ROMSpace[A] = V;
|
||||
}
|
||||
|
||||
static uint8 HuCSF2Latch = 0;
|
||||
|
||||
static DECLFR(HuCSF2Read)
|
||||
{
|
||||
return(HuCROM[(A & 0x7FFFF) + 0x80000 + HuCSF2Latch * 0x80000 ]); // | (HuCSF2Latch << 19) ]);
|
||||
}
|
||||
|
||||
static DECLFW(HuCSF2Write)
|
||||
{
|
||||
if((A & 0x1FFC) == 0x1FF0)
|
||||
{
|
||||
HuCSF2Latch = (A & 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
int HuCLoad(const uint8 *data, uint32 len, uint32 crc32)
|
||||
{
|
||||
uint32 sf2_threshold = 2048 * 1024;
|
||||
uint32 sf2_required_size = 2048 * 1024 + 512 * 1024;
|
||||
uint32 m_len = (len + 8191)&~8191;
|
||||
bool sf2_mapper = FALSE;
|
||||
|
||||
if(m_len >= sf2_threshold)
|
||||
{
|
||||
sf2_mapper = TRUE;
|
||||
|
||||
if(m_len != sf2_required_size)
|
||||
m_len = sf2_required_size;
|
||||
}
|
||||
|
||||
IsPopulous = 0;
|
||||
PCE_IsCD = 0;
|
||||
|
||||
md5_context md5;
|
||||
md5.starts();
|
||||
md5.update(data, len);
|
||||
md5.finish(MDFNGameInfo->MD5);
|
||||
|
||||
MDFN_printf(_("ROM: %dKiB\n"), (len + 1023) / 1024);
|
||||
MDFN_printf(_("ROM CRC32: 0x%04x\n"), crc32);
|
||||
MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||
|
||||
if(!(HuCROM = (uint8 *)MDFN_malloc(m_len, _("HuCard ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(HuCROM, 0xFF, m_len);
|
||||
memcpy(HuCROM, data, len);
|
||||
|
||||
memset(ROMSpace, 0xFF, 0x88 * 8192 + 8192);
|
||||
|
||||
if(m_len == 0x60000)
|
||||
{
|
||||
memcpy(ROMSpace + 0x00 * 8192, HuCROM, 0x20 * 8192);
|
||||
memcpy(ROMSpace + 0x20 * 8192, HuCROM, 0x20 * 8192);
|
||||
memcpy(ROMSpace + 0x40 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
memcpy(ROMSpace + 0x50 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
memcpy(ROMSpace + 0x60 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
memcpy(ROMSpace + 0x70 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
}
|
||||
else if(m_len == 0x80000)
|
||||
{
|
||||
memcpy(ROMSpace + 0x00 * 8192, HuCROM, 0x40 * 8192);
|
||||
memcpy(ROMSpace + 0x40 * 8192, HuCROM + 0x20 * 8192, 0x20 * 8192);
|
||||
memcpy(ROMSpace + 0x60 * 8192, HuCROM + 0x20 * 8192, 0x20 * 8192);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ROMSpace + 0x00 * 8192, HuCROM, (m_len < 1024 * 1024) ? m_len : 1024 * 1024);
|
||||
}
|
||||
|
||||
for(int x = 0x00; x < 0x80; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = ROMSpace;
|
||||
PCERead[x] = HuCRead;
|
||||
}
|
||||
|
||||
if(!memcmp(HuCROM + 0x1F26, "POPULOUS", strlen("POPULOUS")))
|
||||
{
|
||||
uint8 *PopRAM = ROMSpace + 0x40 * 8192;
|
||||
gzFile fp;
|
||||
|
||||
memset(PopRAM, 0xFF, 32768);
|
||||
if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, PopRAM, 32768);
|
||||
gzclose(fp);
|
||||
}
|
||||
|
||||
IsPopulous = 1;
|
||||
|
||||
MDFN_printf("Populous\n");
|
||||
|
||||
for(int x = 0x40; x < 0x44; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = &PopRAM[(x & 3) * 8192] - x * 8192;
|
||||
PCERead[x] = HuCRead;
|
||||
PCEWrite[x] = HuCRAMWrite;
|
||||
}
|
||||
MDFNMP_AddRAM(32768, 0x40 * 8192, PopRAM);
|
||||
}
|
||||
else if(crc32 == 0x34dc65c4) // Tsushin Booster
|
||||
{
|
||||
gzFile fp;
|
||||
|
||||
if(!(TsushinRAM = (uint8*)MDFN_calloc(1, 0x8000 + 8192, _("Tsushin Booster RAM")))) // + 8192 for PC-as-ptr safety padding
|
||||
{
|
||||
MDFN_free(HuCROM);
|
||||
return(0);
|
||||
}
|
||||
memset(TsushinRAM, 0xFF, 0x8000);
|
||||
|
||||
if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, TsushinRAM, 32768);
|
||||
gzclose(fp);
|
||||
}
|
||||
IsTsushin = 1;
|
||||
MDFN_printf("Tsushin Booster\n");
|
||||
for(int x = 0x88; x < 0x8C; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = &TsushinRAM[(x & 3) * 8192] - x * 8192;
|
||||
PCERead[x] = HuCRead;
|
||||
PCEWrite[x] = HuCRAMWrite;
|
||||
}
|
||||
MDFNMP_AddRAM(32768, 0x88 * 8192, TsushinRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
gzFile fp;
|
||||
|
||||
memset(SaveRAM, 0x00, 2048);
|
||||
memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet
|
||||
// in the CD BIOS screen.
|
||||
if((fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, SaveRAM, 2048);
|
||||
gzclose(fp);
|
||||
}
|
||||
PCEWrite[0xF7] = SaveRAMWrite;
|
||||
PCERead[0xF7] = SaveRAMRead;
|
||||
MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
|
||||
}
|
||||
|
||||
// 0x1A558
|
||||
//if(len >= 0x20000 && !memcmp(HuCROM + 0x1A558, "STREET FIGHTER#", strlen("STREET FIGHTER#")))
|
||||
if(sf2_mapper)
|
||||
{
|
||||
for(int x = 0x40; x < 0x80; x++)
|
||||
{
|
||||
// FIXME: PCE_FAST
|
||||
HuCPUFastMap[x] = NULL; // Make sure our reads go through our read function, and not a table lookup
|
||||
PCERead[x] = HuCSF2Read;
|
||||
}
|
||||
PCEWrite[0] = HuCSF2Write;
|
||||
MDFN_printf("Street Fighter 2 Mapper\n");
|
||||
HuCSF2Latch = 0;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
bool IsBRAMUsed(void)
|
||||
{
|
||||
if(memcmp(SaveRAM, BRAM_Init_String, 8)) // HUBM string is modified/missing
|
||||
return(1);
|
||||
|
||||
for(int x = 8; x < 2048; x++)
|
||||
if(SaveRAM[x]) return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int HuCLoadCD(const char *bios_path)
|
||||
{
|
||||
static const FileExtensionSpecStruct KnownBIOSExtensions[] =
|
||||
{
|
||||
{ ".pce", gettext_noop("PC Engine ROM Image") },
|
||||
{ ".bin", gettext_noop("PC Engine ROM Image") },
|
||||
{ ".bios", gettext_noop("BIOS Image") },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
MDFNFILE fp;
|
||||
|
||||
if(!fp.Open(bios_path, KnownBIOSExtensions, _("CD BIOS")))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(ROMSpace, 0xFF, 262144);
|
||||
|
||||
memcpy(ROMSpace, fp.Data() + (fp.Size() & 512), ((fp.Size() & ~512) > 262144) ? 262144 : (fp.Size() &~ 512) );
|
||||
|
||||
fp.Close();
|
||||
|
||||
PCE_IsCD = 1;
|
||||
PCE_InitCD();
|
||||
|
||||
md5_context md5;
|
||||
md5.starts();
|
||||
// md5_update(&md5, HuCROM, 262144);
|
||||
|
||||
#if 0
|
||||
int32 track = CDIF_GetFirstTrack();
|
||||
int32 last_track = CDIF_GetLastTrack();
|
||||
bool DTFound = 0;
|
||||
for(; track <= last_track; track++)
|
||||
{
|
||||
CDIF_Track_Format format;
|
||||
|
||||
if(CDIF_GetTrackFormat(track, format) && format == CDIF_FORMAT_MODE1)
|
||||
{
|
||||
DTFound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(DTFound) // Only add the MD5 hash if we were able to find a data track.
|
||||
{
|
||||
uint32 start_sector = CDIF_GetTrackStartPositionLBA(track);
|
||||
uint8 sector_buffer[2048];
|
||||
|
||||
for(int x = 0; x < 128; x++)
|
||||
{
|
||||
memset(sector_buffer, 0, 2048);
|
||||
CDIF_ReadSector(sector_buffer, NULL, start_sector + x, 1);
|
||||
md5.update(sector_buffer, 2048);
|
||||
}
|
||||
}
|
||||
md5.finish(MDFNGameInfo->MD5);
|
||||
MDFN_printf(_("CD MD5(first 256KiB): 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||
#endif
|
||||
|
||||
MDFN_printf(_("Arcade Card Emulation: %s\n"), PCE_ACEnabled ? _("Enabled") : _("Disabled"));
|
||||
for(int x = 0; x < 0x40; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = ROMSpace;
|
||||
PCERead[x] = HuCRead;
|
||||
}
|
||||
|
||||
for(int x = 0x68; x < 0x88; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = ROMSpace;
|
||||
PCERead[x] = HuCRead;
|
||||
PCEWrite[x] = HuCRAMWrite;
|
||||
}
|
||||
PCEWrite[0x80] = HuCRAMWriteCDSpecial; // Hyper Dyne Special hack
|
||||
MDFNMP_AddRAM(262144, 0x68 * 8192, ROMSpace + 0x68 * 8192);
|
||||
|
||||
if(PCE_ACEnabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
arcade_card = new ArcadeCard();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
MDFN_PrintError(_("Error creating %s object: %s"), "ArcadeCard", e.what());
|
||||
//Cleanup(); // TODO
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(int x = 0x40; x < 0x44; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = NULL;
|
||||
PCERead[x] = ACPhysRead;
|
||||
PCEWrite[x] = ACPhysWrite;
|
||||
}
|
||||
}
|
||||
|
||||
gzFile srp;
|
||||
|
||||
memset(SaveRAM, 0x00, 2048);
|
||||
memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet
|
||||
// in the CD BIOS screen.
|
||||
|
||||
if((srp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(srp, SaveRAM, 2048);
|
||||
gzclose(srp);
|
||||
}
|
||||
PCEWrite[0xF7] = SaveRAMWrite;
|
||||
PCERead[0xF7] = SaveRAMRead;
|
||||
MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int HuC_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(ROMSpace + 0x40 * 8192, IsPopulous ? 32768 : 0),
|
||||
SFARRAY(TsushinRAM, IsTsushin ? 32768 : 0),
|
||||
SFARRAY(SaveRAM, (IsPopulous || IsTsushin) ? 0 : 2048),
|
||||
SFARRAY(ROMSpace + 0x68 * 8192, PCE_IsCD ? 262144 : 0),
|
||||
SFVAR(HuCSF2Latch),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "HuC");
|
||||
|
||||
if(load)
|
||||
HuCSF2Latch &= 0x3;
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
ret &= PCECD_StateAction(sm, load, data_only);
|
||||
|
||||
if(arcade_card)
|
||||
ret &= arcade_card->StateAction(sm, load, data_only);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void HuCClose(void)
|
||||
{
|
||||
if(IsPopulous)
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, ROMSpace + 0x40 * 8192, 32768);
|
||||
}
|
||||
else if(IsTsushin)
|
||||
{
|
||||
if(TsushinRAM)
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, TsushinRAM, 32768);
|
||||
MDFN_free(TsushinRAM);
|
||||
TsushinRAM = NULL;
|
||||
}
|
||||
}
|
||||
else if(IsBRAMUsed())
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, SaveRAM, 2048);
|
||||
}
|
||||
|
||||
if(arcade_card)
|
||||
{
|
||||
delete arcade_card;
|
||||
arcade_card = NULL;
|
||||
}
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
PCECD_Close();
|
||||
}
|
||||
|
||||
if(HuCROM)
|
||||
{
|
||||
MDFN_free(HuCROM);
|
||||
HuCROM = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HuC_Power(void)
|
||||
{
|
||||
if(PCE_IsCD)
|
||||
memset(ROMSpace + 0x68 * 8192, 0x00, 262144);
|
||||
|
||||
if(arcade_card)
|
||||
arcade_card->Power();
|
||||
}
|
||||
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
int HuCLoad(const uint8 *data, uint32 len, uint32 crc32);
|
||||
int HuCLoadCD(const char *bios_path);
|
||||
void HuCClose(void);
|
||||
int HuC_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void HuC_Power(void);
|
||||
|
||||
DECLFR(PCE_ACRead);
|
||||
DECLFW(PCE_ACWrite);
|
||||
|
||||
extern bool PCE_IsCD;
|
||||
extern bool IsTsushin;
|
||||
|
||||
};
|
|
@ -1,784 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "vdc.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
HuC6280 HuCPU;
|
||||
uint8 *HuCPUFastMap[0x100];
|
||||
|
||||
#define HU_PC PC_local //HuCPU.PC
|
||||
#define HU_PC_base HuCPU.PC_base
|
||||
#define HU_A HuCPU.A
|
||||
#define HU_X X_local //HuCPU.X
|
||||
#define HU_Y Y_local //HuCPU.Y
|
||||
#define HU_S HuCPU.S
|
||||
#define HU_P P_local //HuCPU.P
|
||||
#define HU_PI HuCPU.mooPI
|
||||
#define HU_IRQlow HuCPU.IRQlow
|
||||
#define HU_Page1 Page1_local
|
||||
//HuCPU.Page1
|
||||
//Page1_local //HuCPU.Page1
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
#define HU_ZNFlags HuCPU.ZNFlags
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define LOAD_LOCALS_PC() register uint8 *PC_local = HuCPU.PC;
|
||||
#else
|
||||
#define LOAD_LOCALS_PC() register uint32 PC_local /*asm ("edi")*/ = HuCPU.PC; // asm ("edi") = HuCPU.PC;
|
||||
#endif
|
||||
|
||||
#define LOAD_LOCALS() \
|
||||
LOAD_LOCALS_PC(); \
|
||||
uint8 X_local = HuCPU.X; \
|
||||
uint8 Y_local = HuCPU.Y; \
|
||||
uint8 P_local = HuCPU.P; \
|
||||
uint8 *Page1_local = HuCPU.Page1;
|
||||
|
||||
#define SAVE_LOCALS() HuCPU.PC = PC_local; \
|
||||
HuCPU.X = X_local; \
|
||||
HuCPU.Y = Y_local; \
|
||||
HuCPU.P = P_local; \
|
||||
HuCPU.Page1 = Page1_local;
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
#define COMPRESS_FLAGS() HU_P &= ~(N_FLAG | Z_FLAG); HU_P |= ((HU_ZNFlags >> 24) & 0x80) | ((HU_ZNFlags & 0xFF) ? 0 : Z_FLAG);
|
||||
//((((HU_ZNFlags & 0xFF) - 1) >> 8) & Z_FLAG);
|
||||
#define EXPAND_FLAGS() HU_ZNFlags = (HU_P << 24) | ((HU_P & Z_FLAG) ^ Z_FLAG);
|
||||
#else
|
||||
#define COMPRESS_FLAGS()
|
||||
#define EXPAND_FLAGS()
|
||||
#endif
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define GetRealPC() ((unsigned int)(HU_PC - HU_PC_base))
|
||||
#define GetRealPC_EXTERNAL() ((unsigned int)(HuCPU.PC - HuCPU.PC_base))
|
||||
#else
|
||||
#define GetRealPC() (HU_PC)
|
||||
#define GetRealPC_EXTERNAL() (HuCPU.PC)
|
||||
#endif
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define SetPC(value) { unsigned int tempmoo = value; HU_PC = &HuCPU.FastPageR[tempmoo >> 13][tempmoo]; \
|
||||
HU_PC_base = HU_PC - tempmoo; }
|
||||
#define SetPC_EXTERNAL(value) { unsigned int tempmoo = value; \
|
||||
HuCPU.PC = &HuCPU.FastPageR[tempmoo >> 13][tempmoo]; HuCPU.PC_base = HuCPU.PC - tempmoo; }
|
||||
#else
|
||||
#define SetPC(value) { HU_PC = (value); }
|
||||
#define SetPC_EXTERNAL(value) { HuCPU.PC = (value); }
|
||||
#endif
|
||||
|
||||
// Page change PC, GET IT?!
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define FixPC_PC() SetPC(GetRealPC());
|
||||
#else
|
||||
#define FixPC_PC()
|
||||
#endif
|
||||
|
||||
//#define IncPC() { HU_PC++; if(!(GetRealPC() & 0x1FFF)) printf("Bank crossing: %04x\n", GetRealPC()); }
|
||||
//#define IncPC() HU_PC++;
|
||||
#if 0
|
||||
#define IncPC() { HU_PC++; if(!(GetRealPC() & 0x1FFF) && \
|
||||
HuCPU.MPR[(GetRealPC() - 1) >> 13] != (HuCPU.MPR[(GetRealPC()) >> 13] - 1)) \
|
||||
printf("Bank crossing: %04x, %02x, %02x\n", GetRealPC(), HuCPU.MPR[(GetRealPC() - 1) >> 13], \
|
||||
HuCPU.MPR[GetRealPC() >> 13]); }
|
||||
#else
|
||||
#define IncPC() HU_PC++;
|
||||
#endif
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define RdAtPC() (*HU_PC)
|
||||
//#define RdAtAndIncPC_16() (HU_PC += 2, *(uint16 *)(HU_PC - 2))
|
||||
#else
|
||||
#define RdAtPC() RdOp(HU_PC)
|
||||
//#define RdAtAndIncPC_16() (RdOp(HU_PC++) | ((RdOp(HU_PC++) << 8)))
|
||||
#endif
|
||||
|
||||
// If we change this definition, we'll need to also fix HuC6280_StealCycle() in huc6280.h
|
||||
#define ADDCYC(x) { HuCPU.timestamp += x; }
|
||||
|
||||
static uint8 dummy_bank[8192 + 8192]; // + 8192 for PC-as-ptr safety padding
|
||||
|
||||
#define SET_MPR(arg_i, arg_v) \
|
||||
{ \
|
||||
const unsigned int wmpr = arg_i, wbank = arg_v; \
|
||||
if(wmpr == 1) \
|
||||
{ \
|
||||
if(wbank != 0xF8 || !HuCPUFastMap[wbank]) \
|
||||
printf("Crazy page 1: %02x\n", wbank); \
|
||||
HU_Page1 = HuCPUFastMap[wbank] ? HuCPUFastMap[wbank] + wbank * 8192 : dummy_bank; \
|
||||
} \
|
||||
HuCPU.MPR[wmpr] = wbank; \
|
||||
HuCPU.FastPageR[wmpr] = HuCPUFastMap[wbank] ? (HuCPUFastMap[wbank] + wbank * 8192) - wmpr * 8192 : (dummy_bank - wmpr * 8192); \
|
||||
}
|
||||
|
||||
void HuC6280_SetMPR(int i, int v)
|
||||
{
|
||||
uint8 *Page1_local = HuCPU.Page1;
|
||||
|
||||
SET_MPR(i, v);
|
||||
|
||||
HuCPU.Page1 = Page1_local;
|
||||
}
|
||||
|
||||
|
||||
static void HuC6280_FlushMPRCache(void)
|
||||
{
|
||||
for(int x = 0; x < 9; x++)
|
||||
HuC6280_SetMPR(x, HuCPU.MPR[x & 0x7]);
|
||||
}
|
||||
|
||||
static INLINE uint8 RdMem(unsigned int A)
|
||||
{
|
||||
uint8 wmpr = HuCPU.MPR[A >> 13];
|
||||
return(PCERead[wmpr]((wmpr << 13) | (A & 0x1FFF)));
|
||||
}
|
||||
|
||||
static INLINE uint16 RdMem16(unsigned int A)
|
||||
{
|
||||
return(RdMem(A) | (RdMem(A + 1) << 8));
|
||||
}
|
||||
|
||||
static INLINE void WrMem(unsigned int A, uint8 V)
|
||||
{
|
||||
uint8 wmpr = HuCPU.MPR[A >> 13];
|
||||
PCEWrite[wmpr]((wmpr << 13) | (A & 0x1FFF), V);
|
||||
}
|
||||
|
||||
static INLINE uint8 RdOp(unsigned int A)
|
||||
{
|
||||
return(HuCPU.FastPageR[A >> 13][A]);
|
||||
}
|
||||
|
||||
#define PUSH(V) \
|
||||
{ \
|
||||
HU_Page1[0x100 + HU_S] = V; \
|
||||
HU_S--; \
|
||||
}
|
||||
|
||||
#define PUSH_PC() \
|
||||
{ \
|
||||
unsigned int real_pc = GetRealPC(); \
|
||||
PUSH(real_pc >> 8); \
|
||||
PUSH(real_pc); \
|
||||
}
|
||||
|
||||
#define POP() HU_Page1[0x100 + ++HU_S]
|
||||
|
||||
#define POP_PC() \
|
||||
{ \
|
||||
unsigned int npc; \
|
||||
npc = POP(); \
|
||||
npc |= POP() << 8; \
|
||||
SetPC(npc); \
|
||||
}
|
||||
|
||||
// Hopefully we never RTS to 0x0000. ;)
|
||||
#define POP_PC_AP() \
|
||||
{ \
|
||||
uint32 npc; \
|
||||
npc = POP(); \
|
||||
npc |= POP() << 8; \
|
||||
npc++; \
|
||||
SetPC(npc); \
|
||||
}
|
||||
|
||||
/* Some of these operations will only make sense if you know what the flag
|
||||
constants are. */
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
#define X_ZN(zort) { HU_ZNFlags = (int32)(int8)(uint8)(zort); }
|
||||
#define X_ZN_BIT(opres, argie) { HU_ZNFlags = (opres) | ((argie) << 24); }
|
||||
#else
|
||||
static uint8 ZNTable[256];
|
||||
#define X_ZN(zort) HU_P&=~(Z_FLAG|N_FLAG);HU_P|=ZNTable[zort]
|
||||
#define X_ZN_BIT(opres, argie) { HU_P &= ~(Z_FLAG | N_FLAG); HU_P |= ZNTable[opres] & Z_FLAG; HU_P |= argie & N_FLAG; }
|
||||
#endif
|
||||
|
||||
#define JR(cond) \
|
||||
{ \
|
||||
if(cond) \
|
||||
{ \
|
||||
int32 disp; \
|
||||
disp = 1 + (int8)RdAtPC(); \
|
||||
ADDCYC(2); \
|
||||
HU_PC+=disp; \
|
||||
} \
|
||||
else IncPC(); \
|
||||
}
|
||||
|
||||
#define BRA \
|
||||
{ \
|
||||
int32 disp; \
|
||||
disp = 1 + (int8)RdAtPC(); \
|
||||
HU_PC+=disp; \
|
||||
}
|
||||
|
||||
#define BBRi(bitto) JR(!(x & (1 << bitto)))
|
||||
#define BBSi(bitto) JR(x & (1 << bitto))
|
||||
|
||||
#define ST0 VDC_Write_ST(0, x)
|
||||
#define ST1 VDC_Write_ST(2, x)
|
||||
#define ST2 VDC_Write_ST(3, x)
|
||||
|
||||
#define LDA HU_A=x;X_ZN(HU_A)
|
||||
#define LDX HU_X=x;X_ZN(HU_X)
|
||||
#define LDY HU_Y=x;X_ZN(HU_Y)
|
||||
|
||||
/* All of the freaky arithmetic operations. */
|
||||
#define AND HU_A&=x;X_ZN(HU_A);
|
||||
|
||||
// FIXME:
|
||||
#define BIT HU_P&=~V_FLAG; X_ZN_BIT(x & HU_A, x); HU_P |= x & V_FLAG;
|
||||
#define EOR HU_A^=x;X_ZN(HU_A);
|
||||
#define ORA HU_A|=x;X_ZN(HU_A);
|
||||
|
||||
#define ADC { \
|
||||
if(HU_P & D_FLAG) \
|
||||
{ \
|
||||
uint32 low = (HU_A & 0x0F) + (x & 0x0F) + (HU_P & 1); \
|
||||
uint32 high = (HU_A & 0xF0) + (x & 0xF0); \
|
||||
HU_P &= ~C_FLAG; \
|
||||
if(low > 0x09) { high += 0x10; low += 0x06; } \
|
||||
if(high > 0x90) { high += 0x60; } \
|
||||
HU_P |= (high >> 8) & C_FLAG; \
|
||||
HU_A = (low & 0x0F) | (high & 0xF0); \
|
||||
X_ZN(HU_A); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
uint32 l=HU_A+x+(HU_P&1); \
|
||||
HU_P&=~(C_FLAG|V_FLAG); \
|
||||
HU_P|=((((HU_A^x)&0x80)^0x80) & ((HU_A^l)&0x80))>>1; \
|
||||
HU_P|=(l>>8)&C_FLAG; \
|
||||
HU_A=l; \
|
||||
X_ZN(HU_A); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SBC if(HU_P & D_FLAG) \
|
||||
{ \
|
||||
uint32 c = (HU_P & 1) ^ 1; \
|
||||
uint32 l = HU_A - x - c; \
|
||||
uint32 low = (HU_A & 0x0f) - (x & 0x0f) - c; \
|
||||
uint32 high = (HU_A & 0xf0) - (x & 0xf0); \
|
||||
HU_P &= ~(C_FLAG); \
|
||||
if(low & 0xf0) low -= 0x06; \
|
||||
if(low & 0x80) high -= 0x10; \
|
||||
if(high & 0x0f00) high -= 0x60; \
|
||||
HU_P |= ((l >> 8) & C_FLAG) ^ C_FLAG; \
|
||||
HU_A = (low & 0x0F) | (high & 0xf0); \
|
||||
X_ZN(HU_A); \
|
||||
} else { \
|
||||
uint32 l=HU_A-x-((HU_P&1)^1); \
|
||||
HU_P&=~(C_FLAG|V_FLAG); \
|
||||
HU_P|=((HU_A^l)&(HU_A^x)&0x80)>>1; \
|
||||
HU_P|=((l>>8)&C_FLAG)^C_FLAG; \
|
||||
HU_A=l; \
|
||||
X_ZN(HU_A); \
|
||||
}
|
||||
|
||||
#define CMPL(a1,a2) { \
|
||||
uint32 t=a1-a2; \
|
||||
X_ZN(t&0xFF); \
|
||||
HU_P&=~C_FLAG; \
|
||||
HU_P|=((t>>8)&C_FLAG)^C_FLAG; \
|
||||
}
|
||||
|
||||
#define TAM for(int i = 0; i < 8; i ++) { \
|
||||
if(x & (1 << i)) \
|
||||
{ \
|
||||
SET_MPR(i, HU_A); \
|
||||
} \
|
||||
} SET_MPR(8, HuCPU.MPR[0]);
|
||||
|
||||
#define TMA for(int i = 0; i < 8; i ++) { \
|
||||
if(x & (1 << i)) \
|
||||
HU_A = HuCPU.MPR[i]; \
|
||||
}
|
||||
|
||||
#define CSL
|
||||
#define CSH
|
||||
|
||||
#define RMB(bitto) x &= ~(1 << (bitto & 7))
|
||||
#define SMB(bitto) x |= 1 << (bitto & 7)
|
||||
|
||||
// FIXME
|
||||
#define TSB { HU_P &= ~V_FLAG; X_ZN_BIT(x | HU_A, x); HU_P |= x & V_FLAG; x |= HU_A; }
|
||||
#define TRB { HU_P &= ~V_FLAG; X_ZN_BIT(x & ~HU_A, x); HU_P |= x & V_FLAG; x &= ~HU_A; }
|
||||
#define TST { HU_P &= ~V_FLAG; X_ZN_BIT(x & zoomhack, x); HU_P |= x & V_FLAG; }
|
||||
|
||||
#define CMP CMPL(HU_A,x)
|
||||
#define CPX CMPL(HU_X,x)
|
||||
#define CPY CMPL(HU_Y,x)
|
||||
|
||||
/* The following operations modify the byte being worked on. */
|
||||
#define DEC x--;X_ZN(x)
|
||||
#define INC x++;X_ZN(x)
|
||||
|
||||
#define ASL HU_P&=~C_FLAG;HU_P|=x>>7;x<<=1;X_ZN(x)
|
||||
#define LSR HU_P&=~C_FLAG;HU_P|=x&1;x>>=1;X_ZN(x)
|
||||
|
||||
#define ROL { \
|
||||
uint8 l=x>>7; \
|
||||
x<<=1; \
|
||||
x|=HU_P&C_FLAG; \
|
||||
HU_P&=~C_FLAG; \
|
||||
HU_P|=l; \
|
||||
X_ZN(x); \
|
||||
}
|
||||
#define ROR { \
|
||||
uint8 l=x&1; \
|
||||
x>>=1; \
|
||||
x|=(HU_P&C_FLAG)<<7; \
|
||||
HU_P&=~C_FLAG; \
|
||||
HU_P|=l; \
|
||||
X_ZN(x); \
|
||||
}
|
||||
|
||||
/* Absolute */
|
||||
#define GetAB(target) \
|
||||
{ \
|
||||
target=RdAtPC(); \
|
||||
IncPC(); \
|
||||
target|=RdAtPC()<<8; \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Absolute Indexed(for reads) */
|
||||
#define GetABI(target, i) \
|
||||
{ \
|
||||
unsigned int tmp; \
|
||||
GetAB(tmp); \
|
||||
target=tmp; \
|
||||
target+=i; \
|
||||
}
|
||||
|
||||
/* Zero Page */
|
||||
#define GetZP(target) \
|
||||
{ \
|
||||
target=RdAtPC(); \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Zero Page Indexed */
|
||||
#define GetZPI(target,i) \
|
||||
{ \
|
||||
target=i+RdAtPC(); \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Indirect */
|
||||
#define GetIND(target) \
|
||||
{ \
|
||||
uint8 tmp; \
|
||||
tmp=RdAtPC(); \
|
||||
IncPC(); \
|
||||
target=HU_Page1[tmp]; \
|
||||
tmp++; \
|
||||
target|=HU_Page1[tmp]<<8; \
|
||||
}
|
||||
|
||||
|
||||
/* Indexed Indirect */
|
||||
#define GetIX(target) \
|
||||
{ \
|
||||
uint8 tmp; \
|
||||
tmp=RdAtPC(); \
|
||||
IncPC(); \
|
||||
tmp+=HU_X; \
|
||||
target=HU_Page1[tmp]; \
|
||||
tmp++; \
|
||||
target|=HU_Page1[tmp] <<8; \
|
||||
}
|
||||
|
||||
/* Indirect Indexed(for reads) */
|
||||
#define GetIY(target) \
|
||||
{ \
|
||||
unsigned int rt; \
|
||||
uint8 tmp; \
|
||||
tmp=RdAtPC(); \
|
||||
rt=HU_Page1[tmp]; \
|
||||
tmp++; \
|
||||
rt|=HU_Page1[tmp]<<8; \
|
||||
target = (rt + HU_Y); \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Now come the macros to wrap up all of the above stuff addressing mode functions
|
||||
and operation macros. Note that operation macros will always operate(redundant
|
||||
redundant) on the variable "x".
|
||||
*/
|
||||
|
||||
#define RMW_A(op) {uint8 x=HU_A; op; HU_A=x; break; } /* Meh... */
|
||||
#define RMW_AB(op) {unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_ABI(reg,op) {unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_ABX(op) RMW_ABI(HU_X,op)
|
||||
#define RMW_ABY(op) RMW_ABI(HU_Y,op)
|
||||
#define RMW_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x = RdMem(EA); op; WrMem(EA, x); break; }
|
||||
#define RMW_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break; }
|
||||
#define RMW_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break;}
|
||||
|
||||
#define LD_IM(op) { uint8 x; x=RdAtPC(); IncPC(); op; break; }
|
||||
#define LD_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; break; }
|
||||
#define LD_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; break; }
|
||||
#define LD_ZPY(op) { uint8 EA; uint8 x; GetZPI(EA,HU_Y); x=HU_Page1[EA]; op; break; }
|
||||
#define LD_AB(op) { unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; break; }
|
||||
#define LD_ABI(reg,op) { unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; break; }
|
||||
#define LD_ABX(op) LD_ABI(HU_X,op)
|
||||
#define LD_ABY(op) LD_ABI(HU_Y,op)
|
||||
|
||||
#define LD_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x=RdMem(EA); op; break; }
|
||||
#define LD_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; break; }
|
||||
#define LD_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; break; }
|
||||
|
||||
#define BMT_PREHONK(pork) HuCPU.in_block_move = IBM_##pork;
|
||||
#define BMT_HONKHONK(pork) if(HuCPU.timestamp >= next_user_event) goto GetOutBMT; continue_the_##pork:
|
||||
|
||||
#define BMT_TDD BMT_PREHONK(TDD); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src--; HuCPU.bmt_dest--; BMT_HONKHONK(TDD); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
|
||||
#define BMT_TAI BMT_PREHONK(TAI); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src + HuCPU.bmt_alternate)); HuCPU.bmt_dest++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TAI); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
|
||||
#define BMT_TIA BMT_PREHONK(TIA); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest + HuCPU.bmt_alternate, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TIA); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
|
||||
#define BMT_TII BMT_PREHONK(TII); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_dest++; BMT_HONKHONK(TII); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
|
||||
#define BMT_TIN BMT_PREHONK(TIN); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; BMT_HONKHONK(TIN); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
|
||||
|
||||
// Block memory transfer load
|
||||
#define LD_BMT(op) { PUSH(HU_Y); PUSH(HU_A); PUSH(HU_X); GetAB(HuCPU.bmt_src); GetAB(HuCPU.bmt_dest); GetAB(HuCPU.bmt_length); op; HuCPU.in_block_move = 0; HU_X = POP(); HU_A = POP(); HU_Y = POP(); break; }
|
||||
|
||||
#define ST_ZP(r) {uint8 EA; GetZP(EA); HU_Page1[EA] = r; break;}
|
||||
#define ST_ZPX(r) {uint8 EA; GetZPI(EA,HU_X); HU_Page1[EA] = r; break;}
|
||||
#define ST_ZPY(r) {uint8 EA; GetZPI(EA,HU_Y); HU_Page1[EA] = r; break;}
|
||||
#define ST_AB(r) {unsigned int EA; GetAB(EA); WrMem(EA, r); break;}
|
||||
#define ST_ABI(reg,r) {unsigned int EA; GetABI(EA,reg); WrMem(EA,r); break; }
|
||||
#define ST_ABX(r) ST_ABI(HU_X,r)
|
||||
#define ST_ABY(r) ST_ABI(HU_Y,r)
|
||||
|
||||
#define ST_IND(r) {unsigned int EA; GetIND(EA); WrMem(EA,r); break; }
|
||||
#define ST_IX(r) {unsigned int EA; GetIX(EA); WrMem(EA,r); break; }
|
||||
#define ST_IY(r) {unsigned int EA; GetIY(EA); WrMem(EA,r); break; }
|
||||
|
||||
static const uint8 CycTable[256] =
|
||||
{
|
||||
/*0x00*/ 8, 7, 3, 4, 6, 4, 6, 7, 3, 2, 2, 2, 7, 5, 7, 6,
|
||||
/*0x10*/ 2, 7, 7, 4, 6, 4, 6, 7, 2, 5, 2, 2, 7, 5, 7, 6,
|
||||
/*0x20*/ 7, 7, 3, 4, 4, 4, 6, 7, 4, 2, 2, 2, 5, 5, 7, 6,
|
||||
/*0x30*/ 2, 7, 7, 2, 4, 4, 6, 7, 2, 5, 2, 2, 5, 5, 7, 6,
|
||||
/*0x40*/ 7, 7, 3, 4, 8, 4, 6, 7, 3, 2, 2, 2, 4, 5, 7, 6,
|
||||
/*0x50*/ 2, 7, 7, 5, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
|
||||
/*0x60*/ 7, 7, 2, 2, 4, 4, 6, 7, 4, 2, 2, 2, 7, 5, 7, 6,
|
||||
/*0x70*/ 2, 7, 7, 17, 4, 4, 6, 7, 2, 5, 4, 2, 7, 5, 7, 6,
|
||||
|
||||
/*0x80*/ 4, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
|
||||
/*0x90*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
|
||||
/*0xA0*/ 2, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
|
||||
/*0xB0*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
|
||||
/*0xC0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
|
||||
/*0xD0*/ 2, 7, 7, 17, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
|
||||
/*0xE0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
|
||||
/*0xF0*/ 2, 7, 7, 17, 2, 4, 6, 7, 2, 5, 4, 2, 2, 5, 7, 6,
|
||||
};
|
||||
#if 0
|
||||
static bool WillIRQOccur(void) NO_INLINE;
|
||||
static bool WillIRQOccur(void)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if(HU_IRQlow)
|
||||
{
|
||||
if(!(HU_PI&I_FLAG))
|
||||
{
|
||||
if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
|
||||
ret = true;
|
||||
else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
|
||||
ret = true;
|
||||
else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
void HuC6280_IRQBegin(int w)
|
||||
{
|
||||
HU_IRQlow|=w;
|
||||
}
|
||||
|
||||
void HuC6280_IRQEnd(int w)
|
||||
{
|
||||
HU_IRQlow&=~w;
|
||||
}
|
||||
|
||||
void HuC6280_Reset(void)
|
||||
{
|
||||
HuCPU.timer_next_timestamp = HuCPU.timestamp + 1024;
|
||||
|
||||
HuCPU.timer_load = 0;
|
||||
HuCPU.timer_value = 0;
|
||||
HuCPU.timer_status = 0;
|
||||
HuCPU.in_block_move = 0;
|
||||
|
||||
unsigned int npc;
|
||||
|
||||
HuCPU.IRQMask = HuCPU.IRQMaskDelay = 7;
|
||||
|
||||
HuC6280_SetMPR(0, 0xFF);
|
||||
HuC6280_SetMPR(1, 0xF8);
|
||||
|
||||
for(int i = 2; i < 8; i++)
|
||||
HuC6280_SetMPR(i, 0);
|
||||
|
||||
npc = RdMem16(0xFFFE);
|
||||
|
||||
#define PC_local HuCPU.PC
|
||||
SetPC(npc);
|
||||
#undef PC_local
|
||||
|
||||
HuCPU.mooPI = I_FLAG;
|
||||
HuCPU.P = I_FLAG;
|
||||
|
||||
HU_IRQlow = 0;
|
||||
}
|
||||
|
||||
void HuC6280_Init(void)
|
||||
{
|
||||
memset((void *)&HuCPU,0,sizeof(HuCPU));
|
||||
memset(dummy_bank, 0, sizeof(dummy_bank));
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
|
||||
#else
|
||||
for(int x=0; x < 256; x++)
|
||||
if(!x) ZNTable[x]=Z_FLAG;
|
||||
else if (x&0x80) ZNTable[x]=N_FLAG;
|
||||
else ZNTable[x]=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HuC6280_Power(void)
|
||||
{
|
||||
HuCPU.IRQlow = 0;
|
||||
|
||||
HuCPU.A = 0;
|
||||
HuCPU.X = 0;
|
||||
HuCPU.Y = 0;
|
||||
HuCPU.S = 0;
|
||||
HuCPU.P = 0;
|
||||
HuCPU.mooPI = 0;
|
||||
|
||||
#if 0
|
||||
HU_PC = HU_PC_base = NULL;
|
||||
#else
|
||||
HuCPU.PC = 0;
|
||||
#endif
|
||||
|
||||
HuCPU.timestamp = 0;
|
||||
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
HuCPU.MPR[i] = 0;
|
||||
HuCPU.FastPageR[i] = NULL;
|
||||
}
|
||||
HuC6280_Reset();
|
||||
}
|
||||
|
||||
void HuC6280_Run(int32 cycles)
|
||||
{
|
||||
const int32 next_user_event = HuCPU.previous_next_user_event + cycles * pce_overclocked;
|
||||
|
||||
HuCPU.previous_next_user_event = next_user_event;
|
||||
|
||||
LOAD_LOCALS();
|
||||
|
||||
if(HuCPU.timestamp >= next_user_event)
|
||||
return;
|
||||
|
||||
int32 next_event;
|
||||
|
||||
if(HuCPU.in_block_move)
|
||||
{
|
||||
next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
|
||||
|
||||
switch(HuCPU.in_block_move)
|
||||
{
|
||||
case IBM_TIA: goto continue_the_TIA;
|
||||
case IBM_TAI: goto continue_the_TAI;
|
||||
case IBM_TDD: goto continue_the_TDD;
|
||||
case IBM_TII: goto continue_the_TII;
|
||||
case IBM_TIN: goto continue_the_TIN;
|
||||
}
|
||||
}
|
||||
|
||||
while(HuCPU.timestamp < next_user_event)
|
||||
{
|
||||
next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
|
||||
|
||||
while(HuCPU.timestamp < next_event)
|
||||
{
|
||||
uint8 b1;
|
||||
|
||||
if(HU_IRQlow)
|
||||
{
|
||||
if(!(HU_PI&I_FLAG))
|
||||
{
|
||||
uint32 tmpa = 0;
|
||||
|
||||
if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
|
||||
tmpa = 0xFFFA;
|
||||
else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
|
||||
tmpa = 0xFFF8;
|
||||
else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
|
||||
tmpa = 0xFFF6;
|
||||
|
||||
if(tmpa)
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
ADDCYC(8);
|
||||
PUSH_PC();
|
||||
|
||||
COMPRESS_FLAGS();
|
||||
PUSH((HU_P&~B_FLAG));
|
||||
HU_P |= I_FLAG;
|
||||
HU_P &= ~(T_FLAG | D_FLAG);
|
||||
HU_PI = HU_P;
|
||||
|
||||
npc = RdMem16(tmpa);
|
||||
SetPC(npc);
|
||||
|
||||
if(tmpa == 0xFFF8)
|
||||
HU_IRQlow &= ~0x200;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} // end if(HU_IRQlow)
|
||||
|
||||
//printf("%04x\n", GetRealPC());
|
||||
HU_PI = HU_P;
|
||||
HuCPU.IRQMaskDelay = HuCPU.IRQMask;
|
||||
|
||||
b1 = RdAtPC();
|
||||
|
||||
ADDCYC(CycTable[b1]);
|
||||
|
||||
IncPC();
|
||||
|
||||
switch(b1)
|
||||
{
|
||||
#include "huc6280_ops.inc"
|
||||
}
|
||||
|
||||
#ifndef HUC6280_EXTRA_CRAZY
|
||||
FixPC_PC();
|
||||
#endif
|
||||
} // end while(HuCPU.timestamp < next_event)
|
||||
|
||||
while(HuCPU.timestamp >= HuCPU.timer_next_timestamp)
|
||||
{
|
||||
HuCPU.timer_next_timestamp += 1024 * pce_overclocked;
|
||||
|
||||
if(HuCPU.timer_status)
|
||||
{
|
||||
HuCPU.timer_value --;
|
||||
if(HuCPU.timer_value < 0)
|
||||
{
|
||||
HuCPU.timer_value = HuCPU.timer_load;
|
||||
HuC6280_IRQBegin(MDFN_IQTIMER);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end while(HuCPU.timestamp < next_user_event)
|
||||
|
||||
GetOutBMT:
|
||||
|
||||
SAVE_LOCALS();
|
||||
}
|
||||
|
||||
void HuC6280_ResetTS(void)
|
||||
{
|
||||
HuCPU.timer_next_timestamp -= HuCPU.timestamp;
|
||||
HuCPU.previous_next_user_event -= HuCPU.timestamp;
|
||||
HuCPU.timestamp = 0;
|
||||
}
|
||||
|
||||
int HuC6280_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
uint16 tmp_PC = GetRealPC_EXTERNAL();
|
||||
|
||||
#define P_local HuCPU.P
|
||||
COMPRESS_FLAGS();
|
||||
|
||||
SFORMAT SFCPU[]=
|
||||
{
|
||||
SFVARN(tmp_PC, "PC"),
|
||||
SFVARN(HuCPU.A, "A"),
|
||||
SFVARN(HuCPU.P, "P"),
|
||||
SFVARN(HuCPU.X, "X"),
|
||||
SFVARN(HuCPU.Y, "Y"),
|
||||
SFVARN(HuCPU.S, "S"),
|
||||
SFVARN(HuCPU.mooPI, "PI"),
|
||||
|
||||
SFVARN(HuCPU.IRQMask, "IRQMask"),
|
||||
SFVARN(HuCPU.IRQMaskDelay, "IRQMaskDelay"),
|
||||
SFARRAYN(HuCPU.MPR, 8, "MPR"),
|
||||
SFVARN(HuCPU.timer_status, "timer_status"),
|
||||
SFVARN(HuCPU.timer_value, "timer_value"),
|
||||
SFVARN(HuCPU.timer_load, "timer_load"),
|
||||
|
||||
|
||||
SFVARN(HuCPU.IRQlow, "IRQlow"),
|
||||
SFVARN(HuCPU.in_block_move, "IBM"),
|
||||
SFVARN(HuCPU.bmt_src, "IBM_SRC"),
|
||||
SFVARN(HuCPU.bmt_dest, "IBM_DEST"),
|
||||
SFVARN(HuCPU.bmt_length, "IBM_LENGTH"),
|
||||
SFVARN(HuCPU.bmt_alternate, "IBM_ALTERNATE"),
|
||||
|
||||
SFVARN(HuCPU.timestamp, "timestamp"),
|
||||
SFVARN(HuCPU.timer_next_timestamp, "timer_next_timestamp"),
|
||||
SFVARN(HuCPU.previous_next_user_event, "previous_next_user_event"),
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, SFCPU, "CPU");
|
||||
|
||||
if(load)
|
||||
{
|
||||
// Update MPR cache
|
||||
HuC6280_FlushMPRCache();
|
||||
|
||||
// This must be after the MPR cache is updated:
|
||||
SetPC_EXTERNAL(tmp_PC);
|
||||
}
|
||||
|
||||
EXPAND_FLAGS();
|
||||
#undef P_local
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
};
|
|
@ -1,156 +0,0 @@
|
|||
#ifndef _HuC6280H
|
||||
|
||||
#define HUC6280_CRAZY_VERSION
|
||||
//#define HUC6280_EXTRA_CRAZY
|
||||
|
||||
#define HUC6280_LAZY_FLAGS
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
|
||||
typedef struct __HuC6280
|
||||
{
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
uint8 *PC, *PC_base;
|
||||
#else
|
||||
uint16 PC;
|
||||
#endif
|
||||
|
||||
uint8 A,X,Y,S,P,mooPI;
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
uint32 ZNFlags;
|
||||
#endif
|
||||
uint8 MPR[9]; // 8, + 1 for PC overflow from $ffff to $10000
|
||||
uint8 *FastPageR[9];
|
||||
uint8 *Page1;
|
||||
//uint8 *PAGE1_W;
|
||||
//const uint8 *PAGE1_R;
|
||||
|
||||
uint32 IRQlow; /* Simulated IRQ pin held low(or is it high?).
|
||||
And other junk hooked on for speed reasons.*/
|
||||
int32 timestamp;
|
||||
|
||||
uint8 IRQMask, IRQMaskDelay;
|
||||
uint8 timer_status;
|
||||
int32 timer_value, timer_load;
|
||||
int32 timer_next_timestamp;
|
||||
|
||||
uint32 in_block_move;
|
||||
uint16 bmt_src, bmt_dest, bmt_length;
|
||||
uint32 bmt_alternate;
|
||||
#define IBM_TIA 1
|
||||
#define IBM_TAI 2
|
||||
#define IBM_TDD 3
|
||||
#define IBM_TII 4
|
||||
#define IBM_TIN 5
|
||||
|
||||
int32 previous_next_user_event;
|
||||
} HuC6280;
|
||||
|
||||
void HuC6280_Run(int32 cycles);
|
||||
void HuC6280_ResetTS(void);
|
||||
|
||||
extern HuC6280 HuCPU;
|
||||
extern uint8 *HuCPUFastMap[0x100];
|
||||
|
||||
#define N_FLAG 0x80
|
||||
#define V_FLAG 0x40
|
||||
#define T_FLAG 0x20
|
||||
#define B_FLAG 0x10
|
||||
#define D_FLAG 0x08
|
||||
#define I_FLAG 0x04
|
||||
#define Z_FLAG 0x02
|
||||
#define C_FLAG 0x01
|
||||
|
||||
#define NTSC_CPU 1789772.7272727272727272
|
||||
#define PAL_CPU 1662607.125
|
||||
|
||||
#define MDFN_IQIRQ1 0x002
|
||||
#define MDFN_IQIRQ2 0x001
|
||||
#define MDFN_IQTIMER 0x004
|
||||
#define MDFN_IQRESET 0x020
|
||||
|
||||
void HuC6280_Init(void);
|
||||
void HuC6280_Reset(void);
|
||||
void HuC6280_Power(void);
|
||||
|
||||
void HuC6280_IRQBegin(int w);
|
||||
void HuC6280_IRQEnd(int w);
|
||||
|
||||
int HuC6280_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
static INLINE void HuC6280_StealCycle(void)
|
||||
{
|
||||
HuCPU.timestamp++;
|
||||
}
|
||||
|
||||
static INLINE uint8 HuC6280_TimerRead(unsigned int A)
|
||||
{
|
||||
#if 0
|
||||
return(HuCPU.timer_value | (PCEIODataBuffer & 0x80));
|
||||
#endif
|
||||
|
||||
uint8 tvr = HuCPU.timer_value;
|
||||
|
||||
if(HuCPU.timer_next_timestamp == HuCPU.timestamp)
|
||||
tvr = (tvr - 1) & 0x7F;
|
||||
|
||||
return(tvr | (PCEIODataBuffer & 0x80));
|
||||
}
|
||||
|
||||
static INLINE void HuC6280_TimerWrite(unsigned int A, uint8 V)
|
||||
{
|
||||
switch(A & 1)
|
||||
{
|
||||
case 0: HuCPU.timer_load = (V & 0x7F); break;
|
||||
case 1: if(V & 1) // Enable counter
|
||||
{
|
||||
if(HuCPU.timer_status == 0)
|
||||
{
|
||||
HuCPU.timer_next_timestamp = HuCPU.timestamp + 1024;
|
||||
HuCPU.timer_value = HuCPU.timer_load;
|
||||
}
|
||||
}
|
||||
HuCPU.timer_status = V & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE uint8 HuC6280_IRQStatusRead(unsigned int A)
|
||||
{
|
||||
if(!(A & 2))
|
||||
return(PCEIODataBuffer);
|
||||
|
||||
switch(A & 1)
|
||||
{
|
||||
case 0:
|
||||
HuC6280_IRQEnd(MDFN_IQTIMER);
|
||||
return(HuCPU.IRQMask ^ 0x7);
|
||||
case 1:
|
||||
{
|
||||
int status = 0;
|
||||
if(HuCPU.IRQlow & MDFN_IQIRQ1) status |= 2;
|
||||
if(HuCPU.IRQlow & MDFN_IQIRQ2) status |= 1;
|
||||
if(HuCPU.IRQlow & MDFN_IQTIMER) status |= 4;
|
||||
return(status | (PCEIODataBuffer & ~(1 | 2 | 4)));
|
||||
}
|
||||
}
|
||||
return(PCEIODataBuffer);
|
||||
}
|
||||
|
||||
static INLINE void HuC6280_IRQStatusWrite(unsigned int A, uint8 V)
|
||||
{
|
||||
if(!(A & 2)) return;
|
||||
switch(A & 1)
|
||||
{
|
||||
case 0: HuCPU.IRQMask = (V & 0x7) ^ 0x7; break;
|
||||
case 1: HuC6280_IRQEnd(MDFN_IQTIMER); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#define _HuC6280H
|
||||
#endif
|
|
@ -1,635 +0,0 @@
|
|||
/* Mednafen - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define TEST_WEIRD_TFLAG(n) { if(HU_P & T_FLAG) puts("RAWR" n); }
|
||||
|
||||
case 0x00: /* BRK */
|
||||
IncPC();
|
||||
HU_P &= ~T_FLAG;
|
||||
PUSH_PC();
|
||||
|
||||
COMPRESS_FLAGS();
|
||||
PUSH(HU_P|B_FLAG);
|
||||
HU_P|=I_FLAG;
|
||||
HU_P &= ~D_FLAG;
|
||||
HU_PI|=I_FLAG;
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
npc=RdOp(0xFFF6);
|
||||
npc|=RdOp(0xFFF7)<<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x40: /* RTI */
|
||||
HU_P = POP();
|
||||
EXPAND_FLAGS();
|
||||
/* HU_PI=HU_P; This is probably incorrect, so it's commented out. */
|
||||
HU_PI = HU_P;
|
||||
POP_PC();
|
||||
|
||||
// T-flag handling here:
|
||||
TEST_WEIRD_TFLAG("RTI");
|
||||
break;
|
||||
|
||||
case 0x60: /* RTS */
|
||||
POP_PC_AP();
|
||||
break;
|
||||
|
||||
case 0x48: /* PHA */
|
||||
PUSH(HU_A);
|
||||
break;
|
||||
|
||||
case 0x08: /* PHP */
|
||||
HU_P &= ~T_FLAG;
|
||||
COMPRESS_FLAGS();
|
||||
PUSH(HU_P|B_FLAG);
|
||||
break;
|
||||
|
||||
case 0xDA: // PHX 65C02
|
||||
PUSH(HU_X);
|
||||
break;
|
||||
|
||||
case 0x5A: // PHY 65C02
|
||||
PUSH(HU_Y);
|
||||
break;
|
||||
|
||||
case 0x68: /* PLA */
|
||||
HU_A = POP();
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0xFA: // PLX 65C02
|
||||
HU_X = POP();
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
|
||||
case 0x7A: // PLY 65C02
|
||||
HU_Y = POP();
|
||||
X_ZN(HU_Y);
|
||||
break;
|
||||
|
||||
case 0x28: /* PLP */
|
||||
HU_P = POP();
|
||||
EXPAND_FLAGS();
|
||||
|
||||
// T-flag handling here:
|
||||
TEST_WEIRD_TFLAG("PLP");
|
||||
break;
|
||||
|
||||
case 0x4C:
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
npc = RdAtPC();
|
||||
IncPC();
|
||||
npc|=RdAtPC() << 8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break; /* JMP ABSOLUTE */
|
||||
|
||||
case 0x6C: /* JMP Indirect */
|
||||
{
|
||||
uint32 tmp;
|
||||
unsigned int npc;
|
||||
|
||||
GetAB(tmp);
|
||||
|
||||
npc=RdMem(tmp);
|
||||
npc|=RdMem(tmp + 1)<<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7C: // JMP Indirect X - 65C02
|
||||
{
|
||||
uint32 tmp;
|
||||
unsigned int npc;
|
||||
|
||||
GetAB(tmp);
|
||||
tmp += HU_X;
|
||||
|
||||
npc=RdMem(tmp);
|
||||
npc|=RdMem(tmp + 1)<<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x20: /* JSR */
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
npc = RdAtPC();
|
||||
|
||||
IncPC();
|
||||
PUSH_PC();
|
||||
|
||||
npc |= RdAtPC() <<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAA: /* TAX */
|
||||
HU_X=HU_A;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0x8A: /* TXA */
|
||||
HU_A=HU_X;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0xA8: /* TAY */
|
||||
HU_Y=HU_A;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
case 0x98: /* TYA */
|
||||
HU_A=HU_Y;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0xBA: /* TSX */
|
||||
HU_X=HU_S;
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
case 0x9A: /* TXS */
|
||||
HU_S=HU_X;
|
||||
break;
|
||||
|
||||
case 0xCA: /* DEX */
|
||||
HU_X--;
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
case 0x88: /* DEY */
|
||||
HU_Y--;
|
||||
X_ZN(HU_Y);
|
||||
break;
|
||||
|
||||
case 0xE8: /* INX */
|
||||
HU_X++;
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
case 0xC8: /* INY */
|
||||
HU_Y++;
|
||||
X_ZN(HU_Y);
|
||||
break;
|
||||
|
||||
case 0x54: CSL; break;
|
||||
case 0xD4: CSH; break;
|
||||
|
||||
case 0x62: HU_A = 0; break; // CLA
|
||||
case 0x82: HU_X = 0; break; // CLX
|
||||
case 0xC2: HU_Y = 0; break; // CLY
|
||||
|
||||
case 0x18: /* CLC */
|
||||
HU_P&=~C_FLAG;
|
||||
break;
|
||||
|
||||
case 0xD8: /* CLD */
|
||||
HU_P&=~D_FLAG;
|
||||
break;
|
||||
|
||||
case 0x58: /* CLI */
|
||||
if((HU_P & I_FLAG) && (HU_IRQlow & MDFN_IQIRQ1))
|
||||
{
|
||||
uint8 moo_op = RdAtPC();
|
||||
if((moo_op == 0xAC || moo_op == 0xAD || moo_op == 0xAE) &&
|
||||
((RdOp(GetRealPC() + 1) & 0x3) == 0) && ((RdOp(GetRealPC() + 2) & 0xFC) == 0))
|
||||
{
|
||||
HU_IRQlow |= 0x200;
|
||||
//puts("CLI/LDA madness!");
|
||||
}
|
||||
}
|
||||
HU_P&=~I_FLAG;
|
||||
break;
|
||||
|
||||
case 0xB8: /* CLV */
|
||||
HU_P&=~V_FLAG;
|
||||
break;
|
||||
|
||||
case 0x38: /* SEC */
|
||||
HU_P|=C_FLAG;
|
||||
break;
|
||||
|
||||
case 0xF8: /* SED */
|
||||
HU_P|=D_FLAG;
|
||||
break;
|
||||
|
||||
case 0x78: /* SEI */
|
||||
HU_P|=I_FLAG;
|
||||
break;
|
||||
|
||||
case 0xEA: /* NOP */
|
||||
break;
|
||||
|
||||
case 0x0A: RMW_A(ASL);
|
||||
case 0x06: RMW_ZP(ASL);
|
||||
case 0x16: RMW_ZPX(ASL);
|
||||
case 0x0E: RMW_AB(ASL);
|
||||
case 0x1E: RMW_ABX(ASL);
|
||||
|
||||
case 0x3A: RMW_A(DEC);
|
||||
case 0xC6: RMW_ZP(DEC);
|
||||
case 0xD6: RMW_ZPX(DEC);
|
||||
case 0xCE: RMW_AB(DEC);
|
||||
case 0xDE: RMW_ABX(DEC);
|
||||
|
||||
case 0x1A: RMW_A(INC); // 65C02
|
||||
case 0xE6: RMW_ZP(INC);
|
||||
case 0xF6: RMW_ZPX(INC);
|
||||
case 0xEE: RMW_AB(INC);
|
||||
case 0xFE: RMW_ABX(INC);
|
||||
|
||||
case 0x4A: RMW_A(LSR);
|
||||
case 0x46: RMW_ZP(LSR);
|
||||
case 0x56: RMW_ZPX(LSR);
|
||||
case 0x4E: RMW_AB(LSR);
|
||||
case 0x5E: RMW_ABX(LSR);
|
||||
|
||||
case 0x2A: RMW_A(ROL);
|
||||
case 0x26: RMW_ZP(ROL);
|
||||
case 0x36: RMW_ZPX(ROL);
|
||||
case 0x2E: RMW_AB(ROL);
|
||||
case 0x3E: RMW_ABX(ROL);
|
||||
|
||||
case 0x6A: RMW_A(ROR);
|
||||
case 0x66: RMW_ZP(ROR);
|
||||
case 0x76: RMW_ZPX(ROR);
|
||||
case 0x6E: RMW_AB(ROR);
|
||||
case 0x7E: RMW_ABX(ROR);
|
||||
|
||||
case 0x69: LD_IM(ADC);
|
||||
case 0x65: LD_ZP(ADC);
|
||||
case 0x75: LD_ZPX(ADC);
|
||||
case 0x6D: LD_AB(ADC);
|
||||
case 0x7D: LD_ABX(ADC);
|
||||
case 0x79: LD_ABY(ADC);
|
||||
case 0x72: LD_IND(ADC);
|
||||
case 0x61: LD_IX(ADC);
|
||||
case 0x71: LD_IY(ADC);
|
||||
|
||||
case 0x29: LD_IM(AND);
|
||||
case 0x25: LD_ZP(AND);
|
||||
case 0x35: LD_ZPX(AND);
|
||||
case 0x2D: LD_AB(AND);
|
||||
case 0x3D: LD_ABX(AND);
|
||||
case 0x39: LD_ABY(AND);
|
||||
case 0x32: LD_IND(AND);
|
||||
case 0x21: LD_IX(AND);
|
||||
case 0x31: LD_IY(AND);
|
||||
|
||||
case 0x89: LD_IM(BIT);
|
||||
case 0x24: LD_ZP(BIT);
|
||||
case 0x34: LD_ZPX(BIT);
|
||||
case 0x2C: LD_AB(BIT);
|
||||
case 0x3C: LD_ABX(BIT);
|
||||
|
||||
case 0xC9: LD_IM(CMP);
|
||||
case 0xC5: LD_ZP(CMP);
|
||||
case 0xD5: LD_ZPX(CMP);
|
||||
case 0xCD: LD_AB(CMP);
|
||||
case 0xDD: LD_ABX(CMP);
|
||||
case 0xD9: LD_ABY(CMP);
|
||||
case 0xD2: LD_IND(CMP);
|
||||
case 0xC1: LD_IX(CMP);
|
||||
case 0xD1: LD_IY(CMP);
|
||||
|
||||
case 0xE0: LD_IM(CPX);
|
||||
case 0xE4: LD_ZP(CPX);
|
||||
case 0xEC: LD_AB(CPX);
|
||||
|
||||
case 0xC0: LD_IM(CPY);
|
||||
case 0xC4: LD_ZP(CPY);
|
||||
case 0xCC: LD_AB(CPY);
|
||||
|
||||
case 0x49: LD_IM(EOR);
|
||||
case 0x45: LD_ZP(EOR);
|
||||
case 0x55: LD_ZPX(EOR);
|
||||
case 0x4D: LD_AB(EOR);
|
||||
case 0x5D: LD_ABX(EOR);
|
||||
case 0x59: LD_ABY(EOR);
|
||||
case 0x52: LD_IND(EOR);
|
||||
case 0x41: LD_IX(EOR);
|
||||
case 0x51: LD_IY(EOR);
|
||||
|
||||
case 0xA9: LD_IM(LDA);
|
||||
case 0xA5: LD_ZP(LDA);
|
||||
case 0xB5: LD_ZPX(LDA);
|
||||
case 0xAD: LD_AB(LDA);
|
||||
case 0xBD: LD_ABX(LDA);
|
||||
case 0xB9: LD_ABY(LDA);
|
||||
case 0xB2: LD_IND(LDA);
|
||||
case 0xA1: LD_IX(LDA);
|
||||
case 0xB1: LD_IY(LDA);
|
||||
|
||||
case 0xA2: LD_IM(LDX);
|
||||
case 0xA6: LD_ZP(LDX);
|
||||
case 0xB6: LD_ZPY(LDX);
|
||||
case 0xAE: LD_AB(LDX);
|
||||
case 0xBE: LD_ABY(LDX);
|
||||
|
||||
case 0xA0: LD_IM(LDY);
|
||||
case 0xA4: LD_ZP(LDY);
|
||||
case 0xB4: LD_ZPX(LDY);
|
||||
case 0xAC: LD_AB(LDY);
|
||||
case 0xBC: LD_ABX(LDY);
|
||||
|
||||
case 0x09: LD_IM(ORA);
|
||||
case 0x05: LD_ZP(ORA);
|
||||
case 0x15: LD_ZPX(ORA);
|
||||
case 0x0D: LD_AB(ORA);
|
||||
case 0x1D: LD_ABX(ORA);
|
||||
case 0x19: LD_ABY(ORA);
|
||||
case 0x12: LD_IND(ORA);
|
||||
case 0x01: LD_IX(ORA);
|
||||
case 0x11: LD_IY(ORA);
|
||||
|
||||
case 0xE9: LD_IM(SBC);
|
||||
case 0xE5: LD_ZP(SBC);
|
||||
case 0xF5: LD_ZPX(SBC);
|
||||
case 0xED: LD_AB(SBC);
|
||||
case 0xFD: LD_ABX(SBC);
|
||||
case 0xF9: LD_ABY(SBC);
|
||||
case 0xF2: LD_IND(SBC);
|
||||
case 0xE1: LD_IX(SBC);
|
||||
case 0xF1: LD_IY(SBC);
|
||||
|
||||
case 0x85: ST_ZP(HU_A);
|
||||
case 0x95: ST_ZPX(HU_A);
|
||||
case 0x8D: ST_AB(HU_A);
|
||||
case 0x9D: ST_ABX(HU_A);
|
||||
case 0x99: ST_ABY(HU_A);
|
||||
case 0x92: ST_IND(HU_A);
|
||||
case 0x81: ST_IX(HU_A);
|
||||
case 0x91: ST_IY(HU_A);
|
||||
|
||||
case 0x86: ST_ZP(HU_X);
|
||||
case 0x96: ST_ZPY(HU_X);
|
||||
case 0x8E: ST_AB(HU_X);
|
||||
|
||||
case 0x84: ST_ZP(HU_Y);
|
||||
case 0x94: ST_ZPX(HU_Y);
|
||||
case 0x8C: ST_AB(HU_Y);
|
||||
|
||||
/* BBRi */
|
||||
case 0x0F: LD_ZP(BBRi(0));
|
||||
case 0x1F: LD_ZP(BBRi(1));
|
||||
case 0x2F: LD_ZP(BBRi(2));
|
||||
case 0x3F: LD_ZP(BBRi(3));
|
||||
case 0x4F: LD_ZP(BBRi(4));
|
||||
case 0x5F: LD_ZP(BBRi(5));
|
||||
case 0x6F: LD_ZP(BBRi(6));
|
||||
case 0x7F: LD_ZP(BBRi(7));
|
||||
|
||||
/* BBSi */
|
||||
case 0x8F: LD_ZP(BBSi(0));
|
||||
case 0x9F: LD_ZP(BBSi(1));
|
||||
case 0xAF: LD_ZP(BBSi(2));
|
||||
case 0xBF: LD_ZP(BBSi(3));
|
||||
case 0xCF: LD_ZP(BBSi(4));
|
||||
case 0xDF: LD_ZP(BBSi(5));
|
||||
case 0xEF: LD_ZP(BBSi(6));
|
||||
case 0xFF: LD_ZP(BBSi(7));
|
||||
|
||||
/* BRA */
|
||||
case 0x80: BRA; break;
|
||||
|
||||
/* BSR */
|
||||
case 0x44:
|
||||
{
|
||||
PUSH_PC();
|
||||
BRA;
|
||||
}
|
||||
break;
|
||||
|
||||
/* BCC */
|
||||
case 0x90: JR(!(HU_P&C_FLAG)); break;
|
||||
|
||||
/* BCS */
|
||||
case 0xB0: JR(HU_P&C_FLAG); break;
|
||||
|
||||
/* BVC */
|
||||
case 0x50: JR(!(HU_P&V_FLAG)); break;
|
||||
|
||||
/* BVS */
|
||||
case 0x70: JR(HU_P&V_FLAG); break;
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
|
||||
/* BEQ */
|
||||
case 0xF0: JR(!(HU_ZNFlags & 0xFF)); break;
|
||||
|
||||
/* BNE */
|
||||
case 0xD0: JR((HU_ZNFlags & 0xFF)); break;
|
||||
|
||||
/* BMI */
|
||||
case 0x30: JR((HU_ZNFlags & 0x80000000)); break;
|
||||
|
||||
/* BPL */
|
||||
case 0x10: JR(!(HU_ZNFlags & 0x80000000)); break;
|
||||
|
||||
#else
|
||||
|
||||
/* BEQ */
|
||||
case 0xF0: JR(HU_P&Z_FLAG); break;
|
||||
|
||||
/* BNE */
|
||||
case 0xD0: JR(!(HU_P&Z_FLAG)); break;
|
||||
|
||||
/* BMI */
|
||||
case 0x30: JR(HU_P&N_FLAG); break;
|
||||
|
||||
/* BPL */
|
||||
case 0x10: JR(!(HU_P&N_FLAG)); break;
|
||||
|
||||
#endif
|
||||
|
||||
// RMB 65SC02
|
||||
case 0x07: RMW_ZP(RMB(0));
|
||||
case 0x17: RMW_ZP(RMB(1));
|
||||
case 0x27: RMW_ZP(RMB(2));
|
||||
case 0x37: RMW_ZP(RMB(3));
|
||||
case 0x47: RMW_ZP(RMB(4));
|
||||
case 0x57: RMW_ZP(RMB(5));
|
||||
case 0x67: RMW_ZP(RMB(6));
|
||||
case 0x77: RMW_ZP(RMB(7));
|
||||
|
||||
// SMB 65SC02
|
||||
case 0x87: RMW_ZP(SMB(0));
|
||||
case 0x97: RMW_ZP(SMB(1));
|
||||
case 0xa7: RMW_ZP(SMB(2));
|
||||
case 0xb7: RMW_ZP(SMB(3));
|
||||
case 0xc7: RMW_ZP(SMB(4));
|
||||
case 0xd7: RMW_ZP(SMB(5));
|
||||
case 0xe7: RMW_ZP(SMB(6));
|
||||
case 0xf7: RMW_ZP(SMB(7));
|
||||
|
||||
// STZ 65C02
|
||||
case 0x64: ST_ZP(0);
|
||||
case 0x74: ST_ZPX(0);
|
||||
case 0x9C: ST_AB(0);
|
||||
case 0x9E: ST_ABX(0);
|
||||
|
||||
// TRB 65SC02
|
||||
case 0x14: RMW_ZP(TRB);
|
||||
case 0x1C: RMW_AB(TRB);
|
||||
|
||||
// TSB 65SC02
|
||||
case 0x04: RMW_ZP(TSB);
|
||||
case 0x0C: RMW_AB(TSB);
|
||||
|
||||
// TST
|
||||
case 0x83: { uint8 zoomhack=RdAtPC(); IncPC(); LD_ZP(TST); }
|
||||
case 0xA3: { uint8 zoomhack=RdAtPC(); IncPC(); LD_ZPX(TST); }
|
||||
case 0x93: { uint8 zoomhack=RdAtPC(); IncPC(); LD_AB(TST); }
|
||||
case 0xB3: { uint8 zoomhack=RdAtPC(); IncPC(); LD_ABX(TST); }
|
||||
|
||||
case 0x22: // SAX(amaphone!)
|
||||
{
|
||||
uint8 tmp = HU_X;
|
||||
HU_X = HU_A;
|
||||
HU_A = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x42: // SAY(what?)
|
||||
{
|
||||
uint8 tmp = HU_Y;
|
||||
HU_Y = HU_A;
|
||||
HU_A = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02: // SXY
|
||||
{
|
||||
uint8 tmp = HU_X;
|
||||
HU_X = HU_Y;
|
||||
HU_Y = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x73: // TII
|
||||
LD_BMT(BMT_TII);
|
||||
|
||||
case 0xC3: // TDD
|
||||
LD_BMT(BMT_TDD);
|
||||
|
||||
case 0xD3: // TIN
|
||||
LD_BMT(BMT_TIN);
|
||||
|
||||
case 0xE3: // TIA
|
||||
LD_BMT(BMT_TIA);
|
||||
|
||||
case 0xF3: // TAI
|
||||
LD_BMT(BMT_TAI);
|
||||
|
||||
case 0x43: // TMAi
|
||||
LD_IM(TMA);
|
||||
|
||||
case 0x53: // TAMi
|
||||
LD_IM(TAM);
|
||||
|
||||
case 0x03: // ST0
|
||||
LD_IM(ST0);
|
||||
|
||||
case 0x13: // ST1
|
||||
LD_IM(ST1);
|
||||
|
||||
case 0x23: // ST2
|
||||
LD_IM(ST2);
|
||||
|
||||
|
||||
case 0xF4: /* SET */
|
||||
{
|
||||
// AND, EOR, ORA, ADC
|
||||
uint8 Abackup = HU_A;
|
||||
|
||||
ADDCYC(3);
|
||||
HU_A = HU_Page1[HU_X]; //PAGE1_R[HU_X];
|
||||
|
||||
switch(RdAtPC())
|
||||
{
|
||||
default: //puts("Bad SET");
|
||||
break;
|
||||
|
||||
case 0x69: IncPC(); LD_IM(ADC);
|
||||
case 0x65: IncPC(); LD_ZP(ADC);
|
||||
case 0x75: IncPC(); LD_ZPX(ADC);
|
||||
case 0x6D: IncPC(); LD_AB(ADC);
|
||||
case 0x7D: IncPC(); LD_ABX(ADC);
|
||||
case 0x79: IncPC(); LD_ABY(ADC);
|
||||
case 0x72: IncPC(); LD_IND(ADC);
|
||||
case 0x61: IncPC(); LD_IX(ADC);
|
||||
case 0x71: IncPC(); LD_IY(ADC);
|
||||
|
||||
case 0x29: IncPC(); LD_IM(AND);
|
||||
case 0x25: IncPC(); LD_ZP(AND);
|
||||
case 0x35: IncPC(); LD_ZPX(AND);
|
||||
case 0x2D: IncPC(); LD_AB(AND);
|
||||
case 0x3D: IncPC(); LD_ABX(AND);
|
||||
case 0x39: IncPC(); LD_ABY(AND);
|
||||
case 0x32: IncPC(); LD_IND(AND);
|
||||
case 0x21: IncPC(); LD_IX(AND);
|
||||
case 0x31: IncPC(); LD_IY(AND);
|
||||
|
||||
case 0x49: IncPC(); LD_IM(EOR);
|
||||
case 0x45: IncPC(); LD_ZP(EOR);
|
||||
case 0x55: IncPC(); LD_ZPX(EOR);
|
||||
case 0x4D: IncPC(); LD_AB(EOR);
|
||||
case 0x5D: IncPC(); LD_ABX(EOR);
|
||||
case 0x59: IncPC(); LD_ABY(EOR);
|
||||
case 0x52: IncPC(); LD_IND(EOR);
|
||||
case 0x41: IncPC(); LD_IX(EOR);
|
||||
case 0x51: IncPC(); LD_IY(EOR);
|
||||
|
||||
case 0x09: IncPC(); LD_IM(ORA);
|
||||
case 0x05: IncPC(); LD_ZP(ORA);
|
||||
case 0x15: IncPC(); LD_ZPX(ORA);
|
||||
case 0x0D: IncPC(); LD_AB(ORA);
|
||||
case 0x1D: IncPC(); LD_ABX(ORA);
|
||||
case 0x19: IncPC(); LD_ABY(ORA);
|
||||
case 0x12: IncPC(); LD_IND(ORA);
|
||||
case 0x01: IncPC(); LD_IX(ORA);
|
||||
case 0x11: IncPC(); LD_IY(ORA);
|
||||
}
|
||||
HU_Page1[HU_X] /*PAGE1_W[HU_X]*/ = HU_A;
|
||||
HU_A = Abackup;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFC:
|
||||
{
|
||||
int32 ec_tmp;
|
||||
ec_tmp = next_event - HuCPU.timestamp;
|
||||
if(ec_tmp > 0)
|
||||
{
|
||||
ADDCYC(ec_tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: MDFN_printf("Bad %02x at $%04x\n", b1, GetRealPC());
|
||||
break;
|
|
@ -1,338 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "input.h"
|
||||
#include "huc.h"
|
||||
#include "../movie.h"
|
||||
#include "../endian.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
static int InputTypes[5];
|
||||
static uint8 *data_ptr[5];
|
||||
|
||||
static bool AVPad6Which[5]; // Lower(8 buttons) or higher(4 buttons).
|
||||
static bool AVPad6Enabled[5];
|
||||
|
||||
uint16 pce_jp_data[5];
|
||||
|
||||
static int64 mouse_last_meow[5];
|
||||
|
||||
static int32 mouse_x[5], mouse_y[5];
|
||||
static uint16 mouse_rel[5];
|
||||
|
||||
uint8 pce_mouse_button[5];
|
||||
uint8 mouse_index[5];
|
||||
|
||||
static uint8 sel;
|
||||
static uint8 read_index = 0;
|
||||
|
||||
static void SyncSettings(void);
|
||||
|
||||
void PCEINPUT_SettingChanged(const char *name)
|
||||
{
|
||||
SyncSettings();
|
||||
}
|
||||
|
||||
void PCEINPUT_Init(void)
|
||||
{
|
||||
SyncSettings();
|
||||
}
|
||||
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr)
|
||||
{
|
||||
assert(port < 5);
|
||||
|
||||
if(!strcasecmp(type, "gamepad"))
|
||||
InputTypes[port] = 1;
|
||||
else if(!strcasecmp(type, "mouse"))
|
||||
InputTypes[port] = 2;
|
||||
else
|
||||
InputTypes[port] = 0;
|
||||
data_ptr[port] = (uint8 *)ptr;
|
||||
}
|
||||
|
||||
void INPUT_Frame(void)
|
||||
{
|
||||
for(int x = 0; x < 5; x++)
|
||||
{
|
||||
if(InputTypes[x] == 1)
|
||||
{
|
||||
uint16 new_data = data_ptr[x][0] | (data_ptr[x][1] << 8);
|
||||
|
||||
if((new_data & 0x1000) && !(pce_jp_data[x] & 0x1000))
|
||||
{
|
||||
AVPad6Enabled[x] = !AVPad6Enabled[x];
|
||||
MDFN_DispMessage("%d-button mode selected for pad %d", AVPad6Enabled[x] ? 6 : 2, x + 1);
|
||||
}
|
||||
|
||||
pce_jp_data[x] = new_data;
|
||||
}
|
||||
else if(InputTypes[x] == 2)
|
||||
{
|
||||
mouse_x[x] += (int32)MDFN_de32lsb(data_ptr[x] + 0);
|
||||
mouse_y[x] += (int32)MDFN_de32lsb(data_ptr[x] + 4);
|
||||
pce_mouse_button[x] = *(uint8 *)(data_ptr[x] + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INPUT_FixTS(void)
|
||||
{
|
||||
for(int x = 0; x < 5; x++)
|
||||
{
|
||||
if(InputTypes[x] == 2)
|
||||
mouse_last_meow[x] -= HuCPU.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE bool CheckLM(int n)
|
||||
{
|
||||
if((int64)HuCPU.timestamp - mouse_last_meow[n] > 10000)
|
||||
{
|
||||
mouse_last_meow[n] = HuCPU.timestamp;
|
||||
|
||||
int32 rel_x = (int32)((0-mouse_x[n]));
|
||||
int32 rel_y = (int32)((0-mouse_y[n]));
|
||||
|
||||
if(rel_x < -127) rel_x = -127;
|
||||
if(rel_x > 127) rel_x = 127;
|
||||
if(rel_y < -127) rel_y = -127;
|
||||
if(rel_y > 127) rel_y = 127;
|
||||
|
||||
mouse_rel[n] = ((rel_x & 0xF0) >> 4) | ((rel_x & 0x0F) << 4);
|
||||
mouse_rel[n] |= (((rel_y & 0xF0) >> 4) | ((rel_y & 0x0F) << 4)) << 8;
|
||||
|
||||
mouse_x[n] += (int32)(rel_x);
|
||||
mouse_y[n] += (int32)(rel_y);
|
||||
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint8 INPUT_Read(unsigned int A)
|
||||
{
|
||||
uint8 ret = 0xF;
|
||||
int tmp_ri = read_index;
|
||||
|
||||
if(tmp_ri > 4)
|
||||
ret ^= 0xF;
|
||||
else
|
||||
{
|
||||
if(!InputTypes[tmp_ri])
|
||||
ret ^= 0xF;
|
||||
else if(InputTypes[tmp_ri] == 2) // Mouse
|
||||
{
|
||||
if(sel & 1)
|
||||
{
|
||||
CheckLM(tmp_ri);
|
||||
ret ^= 0xF;
|
||||
ret ^= mouse_rel[tmp_ri] & 0xF;
|
||||
|
||||
mouse_rel[tmp_ri] >>= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pce_mouse_button[tmp_ri] & 1)
|
||||
ret ^= 0x3; //pce_mouse_button[tmp_ri];
|
||||
|
||||
if(pce_mouse_button[tmp_ri] & 0x2)
|
||||
ret ^= 0x8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(InputTypes[tmp_ri] == 1) // Gamepad
|
||||
{
|
||||
if(AVPad6Which[tmp_ri] && AVPad6Enabled[tmp_ri])
|
||||
{
|
||||
if(sel & 1)
|
||||
ret ^= 0x0F;
|
||||
else
|
||||
ret ^= (pce_jp_data[tmp_ri] >> 8) & 0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sel & 1)
|
||||
ret ^= (pce_jp_data[tmp_ri] >> 4) & 0x0F;
|
||||
else
|
||||
ret ^= pce_jp_data[tmp_ri] & 0x0F;
|
||||
}
|
||||
if(!(sel & 1))
|
||||
AVPad6Which[tmp_ri] = !AVPad6Which[tmp_ri];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!PCE_IsCD)
|
||||
ret |= 0x80; // Set when CDROM is not attached
|
||||
|
||||
//ret |= 0x40; // PC Engine if set, TG16 if clear. Let's leave it clear, PC Engine games don't seem to mind if it's clear, but TG16 games barf if it's set.
|
||||
|
||||
ret |= 0x30; // Always-set?
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void INPUT_Write(unsigned int A, uint8 V)
|
||||
{
|
||||
if((V & 1) && !(sel & 2) && (V & 2))
|
||||
{
|
||||
read_index = 0;
|
||||
}
|
||||
else if((V & 1) && !(sel & 1))
|
||||
{
|
||||
if(read_index < 255)
|
||||
read_index++;
|
||||
}
|
||||
sel = V & 3;
|
||||
}
|
||||
|
||||
int INPUT_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
// 0.8.A fix:
|
||||
SFARRAYB(AVPad6Enabled, 5),
|
||||
SFARRAYB(AVPad6Which, 5),
|
||||
|
||||
SFVARN(mouse_last_meow[0], "mlm_0"),
|
||||
SFVARN(mouse_last_meow[1], "mlm_1"),
|
||||
SFVARN(mouse_last_meow[2], "mlm_2"),
|
||||
SFVARN(mouse_last_meow[3], "mlm_3"),
|
||||
SFVARN(mouse_last_meow[4], "mlm_4"),
|
||||
|
||||
SFARRAY32(mouse_x, 5),
|
||||
SFARRAY32(mouse_y, 5),
|
||||
SFARRAY16(mouse_rel, 5),
|
||||
SFARRAY(pce_mouse_button, 5),
|
||||
SFARRAY(mouse_index, 5),
|
||||
// end 0.8.A fix
|
||||
|
||||
SFARRAY16(pce_jp_data, 5),
|
||||
SFVAR(sel),
|
||||
SFVAR(read_index),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "JOY");
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// GamepadIDII and GamepadIDII_DSR must be EXACTLY the same except for the RUN+SELECT exclusion in the latter.
|
||||
static const InputDeviceInputInfoStruct GamepadIDII[] =
|
||||
{
|
||||
{ "i", "I", 12, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "ii", "II", 11, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, NULL },
|
||||
{ "run", "RUN", 5, IDIT_BUTTON, NULL },
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "iii", "III", 10, IDIT_BUTTON, NULL },
|
||||
{ "iv", "IV", 7, IDIT_BUTTON, NULL },
|
||||
{ "v", "V", 8, IDIT_BUTTON, NULL },
|
||||
{ "vi", "VI", 9, IDIT_BUTTON, NULL },
|
||||
{ "mode_select", "2/6 Mode Select", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
static const InputDeviceInputInfoStruct GamepadIDII_DSR[] =
|
||||
{
|
||||
{ "i", "I", 12, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "ii", "II", 11, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, "run" },
|
||||
{ "run", "RUN", 5, IDIT_BUTTON, "select" },
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "iii", "III", 10, IDIT_BUTTON, NULL },
|
||||
{ "iv", "IV", 7, IDIT_BUTTON, NULL },
|
||||
{ "v", "V", 8, IDIT_BUTTON, NULL },
|
||||
{ "vi", "VI", 9, IDIT_BUTTON, NULL },
|
||||
{ "mode_select", "2/6 Mode Select", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
static const InputDeviceInputInfoStruct MouseIDII[] =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS_REL },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL },
|
||||
{ "left", "Left Button", 0, IDIT_BUTTON, NULL },
|
||||
{ "right", "Right Button", 1, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
// If we add more devices to this array, REMEMBER TO UPDATE the hackish array indexing in the SyncSettings() function
|
||||
// below.
|
||||
static InputDeviceInfoStruct InputDeviceInfo[] =
|
||||
{
|
||||
// None
|
||||
{
|
||||
"none",
|
||||
"none",
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
|
||||
// Gamepad
|
||||
{
|
||||
"gamepad",
|
||||
"Gamepad",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GamepadIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
GamepadIDII,
|
||||
},
|
||||
|
||||
// Mouse
|
||||
{
|
||||
"mouse",
|
||||
"Mouse",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(MouseIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
MouseIDII,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct PortInfo[] =
|
||||
{
|
||||
{ "port1", "Port 1", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port2", "Port 2", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port3", "Port 3", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port4", "Port 4", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port5", "Port 5", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
};
|
||||
|
||||
InputInfoStruct PCEInputInfo =
|
||||
{
|
||||
sizeof(PortInfo) / sizeof(InputPortInfoStruct),
|
||||
PortInfo
|
||||
};
|
||||
|
||||
static void SyncSettings(void)
|
||||
{
|
||||
MDFNGameInfo->mouse_sensitivity = MDFN_GetSettingF("pce_fast.mouse_sensitivity");
|
||||
InputDeviceInfo[1].IDII = MDFN_GetSettingB("pce_fast.disable_softreset") ? GamepadIDII_DSR : GamepadIDII;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __PCE_INPUT_H
|
||||
#define __PCE_INPUT_H
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
void PCEINPUT_Init(void);
|
||||
void PCEINPUT_SettingChanged(const char *name);
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr);
|
||||
uint8 INPUT_Read(unsigned int A);
|
||||
void INPUT_Write(unsigned int A, uint8 V);
|
||||
void INPUT_Frame(void);
|
||||
int INPUT_StateAction(StateMem *sm, int load, int data_only);
|
||||
extern InputInfoStruct PCEInputInfo;
|
||||
void INPUT_FixTS(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,119 +0,0 @@
|
|||
const void * const IOReadHandlers[0x20] =
|
||||
{
|
||||
&&VDC_00, &&VDC_01, &&VDC_02, &&VDC_03,
|
||||
&&VCE_00, &&VCE_01, &&VCE_02, &&VCE_03,
|
||||
&&PSG, &&PSG, &&PSG, &&PSG,
|
||||
&&TIMER_00, &&TIMER_01, &&TIMER_02, &&TIMER_03,
|
||||
&&INPUT_00, &&INPUT_01, &&INPUT_02, &&INPUT_03,
|
||||
&&IRQ_00, &&IRQ_01, &&IRQ_02, &&IRQ_03,
|
||||
&&CDROM, &&CDROM, &&CDROM, &&CDROM,
|
||||
&&EXP, &&EXP, &&EXP, &&EXP
|
||||
};
|
||||
|
||||
A &= 0x1FFF;
|
||||
|
||||
goto *IOReadHandlers[((A & 0x1C00) >> 8) | (A & 0x3)];
|
||||
|
||||
#if IOREAD_SGX==1
|
||||
VDC_00:
|
||||
VDC_01:
|
||||
VDC_02:
|
||||
VDC_03: HuC6280_StealCycle();
|
||||
return(VDC_Read(A&0x1F, TRUE));
|
||||
#else
|
||||
|
||||
VDC_00:
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(0, FALSE));
|
||||
|
||||
VDC_01:
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(1, FALSE));
|
||||
|
||||
VDC_02:
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(2, FALSE));
|
||||
|
||||
VDC_03:
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(3, FALSE));
|
||||
#endif
|
||||
|
||||
VCE_00:
|
||||
VCE_01:
|
||||
VCE_02:
|
||||
VCE_03:
|
||||
HuC6280_StealCycle();
|
||||
return(VCE_Read(A));
|
||||
|
||||
PSG:
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
return(PCEIODataBuffer);
|
||||
|
||||
|
||||
TIMER_00:
|
||||
TIMER_01:
|
||||
TIMER_02:
|
||||
TIMER_03:
|
||||
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
{
|
||||
uint8 ret = HuC6280_TimerRead(A);
|
||||
PCEIODataBuffer = ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
INPUT_00:
|
||||
INPUT_01:
|
||||
INPUT_02:
|
||||
INPUT_03:
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
{
|
||||
uint8 ret = INPUT_Read(A);
|
||||
PCEIODataBuffer = ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
IRQ_00:
|
||||
IRQ_01:
|
||||
IRQ_02:
|
||||
IRQ_03:
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
{
|
||||
uint8 ret = HuC6280_IRQStatusRead(A);
|
||||
PCEIODataBuffer = ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
CDROM:
|
||||
if(IsTsushin)
|
||||
return(PCE_TsushinRead(A));
|
||||
|
||||
if(!PCE_IsCD)
|
||||
return(0xFF);
|
||||
|
||||
if((A & 0x1E00) == 0x1A00)
|
||||
{
|
||||
if(arcade_card)
|
||||
return(arcade_card->Read(A & 0x1FFF));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 next_cd_event;
|
||||
|
||||
return(PCECD_Read(HuCPU.timestamp * 3, A, next_cd_event));
|
||||
}
|
||||
|
||||
|
||||
EXP:
|
||||
if(IsHES)
|
||||
return(ReadIBP(A));
|
||||
|
||||
//printf("Meow: %08x, %02x:%04x\n", A, A >> 13, A & 0x1FFF);
|
||||
return(0xFF);
|
|
@ -1,676 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include <zlib.h>
|
||||
#include "vdc.h"
|
||||
#include "pce_psg/pce_psg.h"
|
||||
#include "input.h"
|
||||
#include "huc.h"
|
||||
#include "../cdrom/pcecd.h"
|
||||
#include "../cdrom/scsicd.h"
|
||||
#include "hes.h"
|
||||
#include "tsushin.h"
|
||||
#include "arcade_card/arcade_card.h"
|
||||
#include "../mempatcher.h"
|
||||
#include "../cdrom/cdromif.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
static PCE_PSG *psg = NULL;
|
||||
extern ArcadeCard *arcade_card; // Bah, lousy globals.
|
||||
|
||||
static Blip_Buffer sbuf[2];
|
||||
|
||||
bool PCE_ACEnabled;
|
||||
|
||||
static bool IsSGX;
|
||||
static bool IsHES;
|
||||
int pce_overclocked;
|
||||
|
||||
// Statically allocated for speed...or something.
|
||||
uint8 ROMSpace[0x88 * 8192 + 8192]; // + 8192 for PC-as-pointer safety padding
|
||||
|
||||
uint8 BaseRAM[32768 + 8192]; // 8KB for PCE, 32KB for Super Grafx // + 8192 for PC-as-pointer safety padding
|
||||
|
||||
uint8 PCEIODataBuffer;
|
||||
readfunc PCERead[0x100];
|
||||
writefunc PCEWrite[0x100];
|
||||
|
||||
static DECLFR(PCEBusRead)
|
||||
{
|
||||
//printf("BUS Read: %02x %04x\n", A >> 13, A);
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(PCENullWrite)
|
||||
{
|
||||
//printf("Null Write: %02x, %08x %02x\n", A >> 13, A, V);
|
||||
}
|
||||
|
||||
static DECLFR(BaseRAMReadSGX)
|
||||
{
|
||||
return((BaseRAM - (0xF8 * 8192))[A]);
|
||||
}
|
||||
|
||||
static DECLFW(BaseRAMWriteSGX)
|
||||
{
|
||||
(BaseRAM - (0xF8 * 8192))[A] = V;
|
||||
}
|
||||
|
||||
static DECLFR(BaseRAMRead)
|
||||
{
|
||||
return((BaseRAM - (0xF8 * 8192))[A]);
|
||||
}
|
||||
|
||||
static DECLFR(BaseRAMRead_Mirrored)
|
||||
{
|
||||
return(BaseRAM[A & 0x1FFF]);
|
||||
}
|
||||
|
||||
static DECLFW(BaseRAMWrite)
|
||||
{
|
||||
(BaseRAM - (0xF8 * 8192))[A] = V;
|
||||
}
|
||||
|
||||
static DECLFW(BaseRAMWrite_Mirrored)
|
||||
{
|
||||
BaseRAM[A & 0x1FFF] = V;
|
||||
}
|
||||
|
||||
static DECLFR(IORead)
|
||||
{
|
||||
#define IOREAD_SGX 0
|
||||
#include "ioread.inc"
|
||||
#undef IOREAD_SGX
|
||||
}
|
||||
|
||||
static DECLFR(IOReadSGX)
|
||||
{
|
||||
#define IOREAD_SGX 1
|
||||
#include "ioread.inc"
|
||||
#undef IOREAD_SGX
|
||||
}
|
||||
|
||||
static DECLFW(IOWrite)
|
||||
{
|
||||
A &= 0x1FFF;
|
||||
|
||||
switch(A & 0x1c00)
|
||||
{
|
||||
case 0x0000: HuC6280_StealCycle();
|
||||
VDC_Write(A, V);
|
||||
break;
|
||||
case 0x0400: HuC6280_StealCycle();
|
||||
VCE_Write(A, V);
|
||||
break;
|
||||
|
||||
case 0x0800: PCEIODataBuffer = V;
|
||||
psg->Write(HuCPU.timestamp / pce_overclocked, A, V);
|
||||
break;
|
||||
|
||||
case 0x0c00: PCEIODataBuffer = V;
|
||||
HuC6280_TimerWrite(A, V);
|
||||
break;
|
||||
|
||||
case 0x1000: PCEIODataBuffer = V; INPUT_Write(A, V); break;
|
||||
case 0x1400: PCEIODataBuffer = V; HuC6280_IRQStatusWrite(A, V); break;
|
||||
case 0x1800: if(IsTsushin)
|
||||
PCE_TsushinWrite(A, V);
|
||||
|
||||
if(!PCE_IsCD)
|
||||
break;
|
||||
|
||||
if((A & 0x1E00) == 0x1A00)
|
||||
{
|
||||
if(arcade_card)
|
||||
arcade_card->Write(A & 0x1FFF, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 dummy_ne;
|
||||
|
||||
dummy_ne = PCECD_Write(HuCPU.timestamp * 3, A, V);
|
||||
}
|
||||
break;
|
||||
//case 0x1C00: break; // Expansion
|
||||
//default: printf("Eep: %04x\n", A); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void PCECDIRQCB(bool asserted)
|
||||
{
|
||||
if(asserted)
|
||||
HuC6280_IRQBegin(MDFN_IQIRQ2);
|
||||
else
|
||||
HuC6280_IRQEnd(MDFN_IQIRQ2);
|
||||
}
|
||||
|
||||
bool PCE_InitCD(void)
|
||||
{
|
||||
PCECD_Settings cd_settings;
|
||||
memset(&cd_settings, 0, sizeof(PCECD_Settings));
|
||||
|
||||
cd_settings.CDDA_Volume = (double)MDFN_GetSettingUI("pce_fast.cddavolume") / 100;
|
||||
cd_settings.CD_Speed = MDFN_GetSettingUI("pce_fast.cdspeed");
|
||||
|
||||
cd_settings.ADPCM_Volume = (double)MDFN_GetSettingUI("pce_fast.adpcmvolume") / 100;
|
||||
cd_settings.ADPCM_LPF = MDFN_GetSettingB("pce_fast.adpcmlp");
|
||||
|
||||
if(cd_settings.CDDA_Volume != 1.0)
|
||||
MDFN_printf(_("CD-DA Volume: %d%%\n"), (int)(100 * cd_settings.CDDA_Volume));
|
||||
|
||||
if(cd_settings.ADPCM_Volume != 1.0)
|
||||
MDFN_printf(_("ADPCM Volume: %d%%\n"), (int)(100 * cd_settings.ADPCM_Volume));
|
||||
|
||||
return(PCECD_Init(&cd_settings, PCECDIRQCB, PCE_MASTER_CLOCK, pce_overclocked, &sbuf[0], &sbuf[1]));
|
||||
}
|
||||
|
||||
|
||||
static int LoadCommon(void);
|
||||
static void LoadCommonPre(void);
|
||||
|
||||
static bool TestMagic(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
if(memcmp(fp->data, "HESM", 4) && strcasecmp(fp->ext, "pce") && strcasecmp(fp->ext, "sgx"))
|
||||
return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static int Load(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
uint32 headerlen = 0;
|
||||
uint32 r_size;
|
||||
|
||||
IsHES = 0;
|
||||
IsSGX = 0;
|
||||
|
||||
if(!memcmp(fp->data, "HESM", 4))
|
||||
IsHES = 1;
|
||||
|
||||
LoadCommonPre();
|
||||
|
||||
if(!IsHES)
|
||||
{
|
||||
if(fp->size & 0x200) // 512 byte header!
|
||||
headerlen = 512;
|
||||
}
|
||||
|
||||
r_size = fp->size - headerlen;
|
||||
if(r_size > 4096 * 1024) r_size = 4096 * 1024;
|
||||
|
||||
for(int x = 0; x < 0x100; x++)
|
||||
{
|
||||
PCERead[x] = PCEBusRead;
|
||||
PCEWrite[x] = PCENullWrite;
|
||||
}
|
||||
|
||||
uint32 crc = crc32(0, fp->data + headerlen, fp->size - headerlen);
|
||||
|
||||
|
||||
if(IsHES)
|
||||
{
|
||||
if(!PCE_HESLoad(fp->data, fp->size))
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
HuCLoad(fp->data + headerlen, fp->size - headerlen, crc);
|
||||
|
||||
if(!strcasecmp(fp->ext, "sgx"))
|
||||
IsSGX = TRUE;
|
||||
|
||||
if(fp->size >= 8192 && !memcmp(fp->data + headerlen, "DARIUS Version 1.11b", strlen("DARIUS VERSION 1.11b")))
|
||||
{
|
||||
MDFN_printf("SuperGfx: Darius Plus\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
|
||||
if(crc == 0x4c2126b0)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Aldynes\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
|
||||
if(crc == 0x8c4588e2)
|
||||
{
|
||||
MDFN_printf("SuperGfx: 1941 - Counter Attack\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
if(crc == 0x1f041166)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Madouou Granzort\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
if(crc == 0xb486a8ed)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Daimakaimura\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
if(crc == 0x3b13af61)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Battle Ace\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
|
||||
return(LoadCommon());
|
||||
}
|
||||
|
||||
static void LoadCommonPre(void)
|
||||
{
|
||||
// FIXME: Make these globals less global!
|
||||
pce_overclocked = MDFN_GetSettingUI("pce_fast.ocmultiplier");
|
||||
PCE_ACEnabled = MDFN_GetSettingB("pce_fast.arcadecard");
|
||||
|
||||
if(pce_overclocked > 1)
|
||||
MDFN_printf(_("CPU overclock: %dx\n"), pce_overclocked);
|
||||
|
||||
if(MDFN_GetSettingUI("pce_fast.cdspeed") > 1)
|
||||
MDFN_printf(_("CD-ROM speed: %ux\n"), (unsigned int)MDFN_GetSettingUI("pce_fast.cdspeed"));
|
||||
|
||||
memset(HuCPUFastMap, 0, sizeof(HuCPUFastMap));
|
||||
for(int x = 0; x < 0x100; x++)
|
||||
{
|
||||
PCERead[x] = PCEBusRead;
|
||||
PCEWrite[x] = PCENullWrite;
|
||||
}
|
||||
|
||||
MDFNMP_Init(1024, (1 << 21) / 1024);
|
||||
}
|
||||
|
||||
static int LoadCommon(void)
|
||||
{
|
||||
IsSGX |= MDFN_GetSettingB("pce_fast.forcesgx") ? 1 : 0;
|
||||
|
||||
if(IsHES)
|
||||
IsSGX = 1;
|
||||
// Don't modify IsSGX past this point.
|
||||
|
||||
VDC_Init(IsSGX);
|
||||
|
||||
if(IsSGX)
|
||||
{
|
||||
MDFN_printf("SuperGrafx Emulation Enabled.\n");
|
||||
PCERead[0xF8] = PCERead[0xF9] = PCERead[0xFA] = PCERead[0xFB] = BaseRAMReadSGX;
|
||||
PCEWrite[0xF8] = PCEWrite[0xF9] = PCEWrite[0xFA] = PCEWrite[0xFB] = BaseRAMWriteSGX;
|
||||
|
||||
for(int x = 0xf8; x < 0xfb; x++)
|
||||
HuCPUFastMap[x] = BaseRAM - 0xf8 * 8192;
|
||||
|
||||
PCERead[0xFF] = IOReadSGX;
|
||||
}
|
||||
else
|
||||
{
|
||||
PCERead[0xF8] = BaseRAMRead;
|
||||
PCERead[0xF9] = PCERead[0xFA] = PCERead[0xFB] = BaseRAMRead_Mirrored;
|
||||
|
||||
PCEWrite[0xF8] = BaseRAMWrite;
|
||||
PCEWrite[0xF9] = PCEWrite[0xFA] = PCEWrite[0xFB] = BaseRAMWrite_Mirrored;
|
||||
|
||||
for(int x = 0xf8; x < 0xfb; x++)
|
||||
HuCPUFastMap[x] = BaseRAM - x * 8192;
|
||||
|
||||
PCERead[0xFF] = IORead;
|
||||
}
|
||||
|
||||
MDFNMP_AddRAM(IsSGX ? 32768 : 8192, 0xf8 * 8192, BaseRAM);
|
||||
|
||||
PCEWrite[0xFF] = IOWrite;
|
||||
|
||||
HuC6280_Init();
|
||||
|
||||
psg = new PCE_PSG(&sbuf[0], &sbuf[1], PCE_PSG::REVISION_ENHANCED); //HUC6280A);
|
||||
|
||||
psg->SetVolume(1.0);
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
unsigned int cdpsgvolume = MDFN_GetSettingUI("pce_fast.cdpsgvolume");
|
||||
|
||||
if(cdpsgvolume != 100)
|
||||
{
|
||||
MDFN_printf(_("CD PSG Volume: %d%%\n"), cdpsgvolume);
|
||||
}
|
||||
|
||||
psg->SetVolume(0.678 * cdpsgvolume / 100);
|
||||
|
||||
}
|
||||
|
||||
PCEINPUT_Init();
|
||||
|
||||
PCE_Power();
|
||||
|
||||
MDFNGameInfo->LayerNames = IsSGX ? "BG0\0SPR0\0BG1\0SPR1\0" : "Background\0Sprites\0";
|
||||
MDFNGameInfo->fps = (uint32)((double)7159090.90909090 / 455 / 263 * 65536 * 256);
|
||||
|
||||
// Clean this up:
|
||||
if(!MDFN_GetSettingB("pce_fast.correct_aspect"))
|
||||
MDFNGameInfo->fb_width = 682;
|
||||
|
||||
if(!IsHES)
|
||||
{
|
||||
MDFNGameInfo->nominal_width = MDFN_GetSettingB("pce_fast.correct_aspect") ? 320 : 341;
|
||||
MDFNGameInfo->nominal_height = MDFN_GetSettingUI("pce_fast.slend") - MDFN_GetSettingUI("pce_fast.slstart") + 1;
|
||||
|
||||
MDFNGameInfo->lcm_width = MDFN_GetSettingB("pce_fast.correct_aspect") ? 1024 : 341;
|
||||
MDFNGameInfo->lcm_height = MDFNGameInfo->nominal_height;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static bool TestMagicCD(std::vector<CDIF *> *CDInterfaces)
|
||||
{
|
||||
static const uint8 magic_test[0x20] = { 0x82, 0xB1, 0x82, 0xCC, 0x83, 0x76, 0x83, 0x8D, 0x83, 0x4F, 0x83, 0x89, 0x83, 0x80, 0x82, 0xCC,
|
||||
0x92, 0x98, 0x8D, 0xEC, 0x8C, 0xA0, 0x82, 0xCD, 0x8A, 0x94, 0x8E, 0xAE, 0x89, 0xEF, 0x8E, 0xD0
|
||||
};
|
||||
uint8 sector_buffer[2048];
|
||||
CDIF *cdiface = (*CDInterfaces)[0];
|
||||
CDUtility::TOC toc;
|
||||
bool ret = FALSE;
|
||||
|
||||
memset(sector_buffer, 0, sizeof(sector_buffer));
|
||||
|
||||
cdiface->ReadTOC(&toc);
|
||||
|
||||
for(int32 track = toc.first_track; track <= toc.last_track; track++)
|
||||
{
|
||||
if(toc.tracks[track].control & 0x4)
|
||||
{
|
||||
cdiface->ReadSector(sector_buffer, toc.tracks[track].lba, 1);
|
||||
|
||||
if(!memcmp((char*)sector_buffer, (char *)magic_test, 0x20))
|
||||
ret = TRUE;
|
||||
|
||||
// PCE CD BIOS apparently only looks at the first data track.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If it's a PC-FX CD(Battle Heat), return false.
|
||||
// This is very kludgy.
|
||||
for(int32 track = toc.first_track; track <= toc.last_track; track++)
|
||||
{
|
||||
if(toc.tracks[track].control & 0x4)
|
||||
{
|
||||
cdiface->ReadSector(sector_buffer, toc.tracks[track].lba, 1);
|
||||
if(!strncmp("PC-FX:Hu_CD-ROM", (char*)sector_buffer, strlen("PC-FX:Hu_CD-ROM")))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now, test for the Games Express CD games. The GE BIOS seems to always look at sector 0x10, but only if the first track is a
|
||||
// data track.
|
||||
if(toc.first_track == 1 && (toc.tracks[1].control & 0x4))
|
||||
{
|
||||
if(cdiface->ReadSector(sector_buffer, 0x10, 1))
|
||||
{
|
||||
if(!memcmp((char *)sector_buffer + 0x8, "HACKER CD ROM SYSTEM", 0x14))
|
||||
{
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int LoadCD(std::vector<CDIF *> *CDInterfaces)
|
||||
{
|
||||
std::string bios_path = MDFN_MakeFName(MDFNMKF_FIRMWARE, 0, MDFN_GetSettingS("pce_fast.cdbios").c_str() );
|
||||
|
||||
IsHES = 0;
|
||||
IsSGX = 0;
|
||||
|
||||
LoadCommonPre();
|
||||
|
||||
if(!HuCLoadCD(bios_path.c_str()))
|
||||
return(0);
|
||||
|
||||
SCSICD_SetDisc(true, NULL, true);
|
||||
SCSICD_SetDisc(false, (*CDInterfaces)[0], true);
|
||||
|
||||
return(LoadCommon());
|
||||
}
|
||||
|
||||
|
||||
static void CloseGame(void)
|
||||
{
|
||||
if(IsHES)
|
||||
HES_Close();
|
||||
else
|
||||
{
|
||||
HuCClose();
|
||||
}
|
||||
VDC_Close();
|
||||
if(psg)
|
||||
{
|
||||
delete psg;
|
||||
psg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void Emulate(EmulateSpecStruct *espec)
|
||||
{
|
||||
INPUT_Frame();
|
||||
|
||||
MDFNMP_ApplyPeriodicCheats();
|
||||
|
||||
if(espec->VideoFormatChanged)
|
||||
VDC_SetPixelFormat(espec->surface->format); //.Rshift, espec->surface->format.Gshift, espec->surface->format.Bshift);
|
||||
|
||||
if(espec->SoundFormatChanged)
|
||||
{
|
||||
for(int y = 0; y < 2; y++)
|
||||
{
|
||||
sbuf[y].set_sample_rate(espec->SoundRate ? espec->SoundRate : 44100, 50);
|
||||
sbuf[y].clock_rate((long)(PCE_MASTER_CLOCK / 3));
|
||||
sbuf[y].bass_freq(20);
|
||||
}
|
||||
}
|
||||
VDC_RunFrame(espec->surface, &espec->DisplayRect, espec->LineWidths, IsHES ? 1 : espec->skip);
|
||||
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
int32 dummy_ne;
|
||||
|
||||
dummy_ne = PCECD_Run(HuCPU.timestamp * 3);
|
||||
}
|
||||
|
||||
psg->EndFrame(HuCPU.timestamp / pce_overclocked);
|
||||
|
||||
if(espec->SoundBuf)
|
||||
{
|
||||
for(int y = 0; y < 2; y++)
|
||||
{
|
||||
sbuf[y].end_frame(HuCPU.timestamp / pce_overclocked);
|
||||
espec->SoundBufSize = sbuf[y].read_samples(espec->SoundBuf + y, espec->SoundBufMaxSize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
espec->MasterCycles = HuCPU.timestamp * 3;
|
||||
|
||||
INPUT_FixTS();
|
||||
|
||||
HuC6280_ResetTS();
|
||||
|
||||
if(PCE_IsCD)
|
||||
PCECD_ResetTS();
|
||||
|
||||
if(IsHES && !espec->skip)
|
||||
HES_Draw(espec->surface, &espec->DisplayRect, espec->SoundBuf, espec->SoundBufSize);
|
||||
}
|
||||
|
||||
static int StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(BaseRAM, IsSGX? 32768 : 8192),
|
||||
SFVAR(PCEIODataBuffer),
|
||||
SFEND
|
||||
};
|
||||
|
||||
//for(int i = 8192; i < 32768; i++)
|
||||
// if(BaseRAM[i] != 0xFF)
|
||||
// printf("%d %02x\n", i, BaseRAM[i]);
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN");
|
||||
|
||||
ret &= HuC6280_StateAction(sm, load, data_only);
|
||||
ret &= VDC_StateAction(sm, load, data_only);
|
||||
ret &= psg->StateAction(sm, load, data_only);
|
||||
ret &= INPUT_StateAction(sm, load, data_only);
|
||||
ret &= HuC_StateAction(sm, load, data_only);
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void PCE_Power(void)
|
||||
{
|
||||
memset(BaseRAM, 0x00, sizeof(BaseRAM));
|
||||
|
||||
if(!IsSGX)
|
||||
for(int i = 8192; i < 32768; i++)
|
||||
BaseRAM[i] = 0xFF;
|
||||
|
||||
PCEIODataBuffer = 0xFF;
|
||||
|
||||
if(IsHES)
|
||||
HES_Reset();
|
||||
|
||||
HuC6280_Power();
|
||||
VDC_Power();
|
||||
psg->Power(HuCPU.timestamp / pce_overclocked);
|
||||
HuC_Power();
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
int32 dummy_ne;
|
||||
|
||||
dummy_ne = PCECD_Power(HuCPU.timestamp * 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoSimpleCommand(int cmd)
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case MDFN_MSC_RESET: PCE_Power(); break;
|
||||
case MDFN_MSC_POWER: PCE_Power(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static MDFNSetting PCESettings[] =
|
||||
{
|
||||
/*
|
||||
{ "pce_fast.input.port1", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Input device for input port 1."), NULL, MDFNST_STRING, "gamepad", NULL, NULL },
|
||||
{ "pce_fast.input.port2", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Input device for input port 2."), NULL, MDFNST_STRING, "gamepad", NULL, NULL },
|
||||
{ "pce_fast.input.port3", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Input device for input port 3."), NULL, MDFNST_STRING, "gamepad", NULL, NULL },
|
||||
{ "pce_fast.input.port4", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Input device for input port 4."), NULL, MDFNST_STRING, "gamepad", NULL, NULL },
|
||||
{ "pce_fast.input.port5", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Input device for input port 5."), NULL, MDFNST_STRING, "gamepad", NULL, NULL },
|
||||
*/
|
||||
|
||||
{ "pce_fast.correct_aspect", MDFNSF_CAT_VIDEO, gettext_noop("Correct the aspect ratio."), NULL, MDFNST_BOOL, "1" },
|
||||
{ "pce_fast.slstart", MDFNSF_NOFLAGS, gettext_noop("First rendered scanline."), NULL, MDFNST_UINT, "4", "0", "239" },
|
||||
{ "pce_fast.slend", MDFNSF_NOFLAGS, gettext_noop("Last rendered scanline."), NULL, MDFNST_UINT, "235", "0", "239" },
|
||||
{ "pce_fast.mouse_sensitivity", MDFNSF_NOFLAGS, gettext_noop("Mouse sensitivity."), NULL, MDFNST_FLOAT, "0.50", NULL, NULL, NULL, PCEINPUT_SettingChanged },
|
||||
{ "pce_fast.disable_softreset", MDFNSF_NOFLAGS, gettext_noop("If set, when RUN+SEL are pressed simultaneously, disable both buttons temporarily."), NULL, MDFNST_BOOL, "0", NULL, NULL, NULL, PCEINPUT_SettingChanged },
|
||||
{ "pce_fast.forcesgx", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Force SuperGrafx emulation."), NULL, MDFNST_BOOL, "0" },
|
||||
{ "pce_fast.arcadecard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Enable Arcade Card emulation."), NULL, MDFNST_BOOL, "1" },
|
||||
{ "pce_fast.ocmultiplier", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("CPU overclock multiplier."), NULL, MDFNST_UINT, "1", "1", "100"},
|
||||
{ "pce_fast.cdspeed", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("CD-ROM data transfer speed multiplier."), NULL, MDFNST_UINT, "1", "1", "100" },
|
||||
{ "pce_fast.nospritelimit", MDFNSF_NOFLAGS, gettext_noop("Remove 16-sprites-per-scanline hardware limit."), NULL, MDFNST_BOOL, "0" },
|
||||
|
||||
{ "pce_fast.cdbios", MDFNSF_EMU_STATE, gettext_noop("Path to the CD BIOS"), NULL, MDFNST_STRING, "syscard3.pce" },
|
||||
{ "pce_fast.adpcmlp", MDFNSF_NOFLAGS, gettext_noop("Enable lowpass filter dependent on playback-frequency."), NULL, MDFNST_BOOL, "0" },
|
||||
{ "pce_fast.cdpsgvolume", MDFNSF_NOFLAGS, gettext_noop("PSG volume when playing a CD game."), NULL, MDFNST_UINT, "100", "0", "200" },
|
||||
{ "pce_fast.cddavolume", MDFNSF_NOFLAGS, gettext_noop("CD-DA volume."), NULL, MDFNST_UINT, "100", "0", "200" },
|
||||
{ "pce_fast.adpcmvolume", MDFNSF_NOFLAGS, gettext_noop("ADPCM volume."), NULL, MDFNST_UINT, "100", "0", "200" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static uint8 MemRead(uint32 addr)
|
||||
{
|
||||
return(PCERead[(addr / 8192) & 0xFF](addr));
|
||||
}
|
||||
|
||||
static const FileExtensionSpecStruct KnownExtensions[] =
|
||||
{
|
||||
{ ".pce", gettext_noop("PC Engine ROM Image") },
|
||||
{ ".hes", gettext_noop("PC Engine Music Rip") },
|
||||
{ ".sgx", gettext_noop("SuperGrafx ROM Image") },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
MDFNGI EmulatedPCE_Fast =
|
||||
{
|
||||
"pce_fast",
|
||||
"PC Engine (CD)/TurboGrafx 16 (CD)/SuperGrafx",
|
||||
KnownExtensions,
|
||||
MODPRIO_INTERNAL_LOW,
|
||||
NULL,
|
||||
&PCEInputInfo,
|
||||
Load,
|
||||
TestMagic,
|
||||
LoadCD,
|
||||
TestMagicCD,
|
||||
CloseGame,
|
||||
VDC_SetLayerEnableMask,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
MemRead,
|
||||
false,
|
||||
StateAction,
|
||||
Emulate,
|
||||
PCEINPUT_SetInput,
|
||||
DoSimpleCommand,
|
||||
PCESettings,
|
||||
MDFN_MASTERCLOCK_FIXED(PCE_MASTER_CLOCK),
|
||||
0,
|
||||
|
||||
true, // Multires possible?
|
||||
|
||||
0, // lcm_width
|
||||
0, // lcm_height
|
||||
NULL, // Dummy
|
||||
|
||||
320, // Nominal width
|
||||
232, // Nominal height
|
||||
|
||||
512, // Framebuffer width
|
||||
242, // Framebuffer height
|
||||
|
||||
2, // Number of output sound channels
|
||||
};
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
#ifndef _PCE_H
|
||||
|
||||
#include "../types.h"
|
||||
#include "../mednafen.h"
|
||||
#include "../state.h"
|
||||
#include "../general.h"
|
||||
#include "../memory.h"
|
||||
|
||||
#define PCE_MASTER_CLOCK 21477272.727273
|
||||
|
||||
#define DECLFR(x) uint8 MDFN_FASTCALL x (uint32 A)
|
||||
#define DECLFW(x) void MDFN_FASTCALL x (uint32 A, uint8 V)
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
extern uint8 ROMSpace[0x88 * 8192 + 8192];
|
||||
|
||||
typedef void (MDFN_FASTCALL *writefunc)(uint32 A, uint8 V);
|
||||
typedef uint8 (MDFN_FASTCALL *readfunc)(uint32 A);
|
||||
|
||||
extern uint8 PCEIODataBuffer;
|
||||
|
||||
bool PCE_InitCD(void);
|
||||
|
||||
};
|
||||
|
||||
#include "huc6280.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
extern bool PCE_ACEnabled; // Arcade Card emulation enabled?
|
||||
void PCE_Power(void);
|
||||
|
||||
extern readfunc PCERead[0x100];
|
||||
extern writefunc PCEWrite[0x100];
|
||||
extern int pce_overclocked;
|
||||
|
||||
extern uint8 BaseRAM[32768 + 8192];
|
||||
|
||||
};
|
||||
|
||||
using namespace PCE_Fast;
|
||||
|
||||
#define _PCE_H
|
||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "pce.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
/*
|
||||
Startup:
|
||||
0x80 -> $1830
|
||||
0x40 -> $1823
|
||||
0x50 -> $1823
|
||||
0x02 -> $1821
|
||||
0x40 -> $1823
|
||||
|
||||
Read from $1822 16 times, expecting (return value & 0xC0) == 0x80 each time
|
||||
|
||||
0x50 -> $1823
|
||||
0x01 -> $1821
|
||||
0x40 -> $1823
|
||||
0x04 -> $1822
|
||||
|
||||
*/
|
||||
|
||||
DECLFR(PCE_TsushinRead)
|
||||
{
|
||||
printf("Read: %04x\n", A);
|
||||
|
||||
return(0x80);
|
||||
}
|
||||
|
||||
DECLFW(PCE_TsushinWrite)
|
||||
{
|
||||
printf("Write: %04x %02x\n", A, V);
|
||||
}
|
||||
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __PCE_TSUSHIN_H
|
||||
#define __PCE_TSUSHIN_H
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
DECLFR(PCE_TsushinRead);
|
||||
DECLFW(PCE_TsushinWrite);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,211 +0,0 @@
|
|||
#ifndef _PCE_VDC_H
|
||||
#define _PCE_VDC_H
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
#define REGSETP(_reg, _data, _msb) { _reg &= 0xFF << ((_msb) ? 0 : 8); _reg |= (_data) << ((_msb) ? 8 : 0); }
|
||||
#define REGGETP(_reg, _msb) ((_reg >> ((_msb) ? 8 : 0)) & 0xFF)
|
||||
|
||||
#define VDC_DEBUG(x)
|
||||
//printf("%s: %d\n", x, vdc->display_counter);
|
||||
#define VDC_UNDEFINED(x) { }
|
||||
//{ printf("%s: %d\n", x, vdc->display_counter); }
|
||||
|
||||
static const unsigned int vram_inc_tab[4] = { 1, 32, 64, 128 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 priority[2];
|
||||
uint16 winwidths[2];
|
||||
uint8 st_mode;
|
||||
} vpc_t;
|
||||
|
||||
extern vpc_t vpc;
|
||||
|
||||
static const int VRAM_Size = 0x8000;
|
||||
static const int VRAM_SizeMask = VRAM_Size - 1; //0x7FFF;
|
||||
static const int VRAM_BGTileNoMask = VRAM_SizeMask / 16; //0x7FF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 CR;
|
||||
|
||||
bool lc263; // 263 line count if set, 262 if not
|
||||
bool bw; // Black and White
|
||||
uint8 dot_clock; // Dot Clock(5, 7, or 10 MHz = 0, 1, 2)
|
||||
uint16 color_table[0x200];
|
||||
uint32 color_table_cache[0x200];
|
||||
uint16 ctaddress;
|
||||
} vce_t;
|
||||
|
||||
extern vce_t vce;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16 y;
|
||||
uint16 height;
|
||||
uint16 x;
|
||||
uint16 no;
|
||||
uint16 flags;
|
||||
bool cgmode;
|
||||
} SAT_Cache_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 display_counter;
|
||||
|
||||
int32 sat_dma_slcounter;
|
||||
|
||||
uint8 select;
|
||||
uint16 MAWR; // Memory Address Write Register
|
||||
uint16 MARR; // Memory Address Read Register
|
||||
|
||||
uint16 CR; // Control Register
|
||||
uint16 RCR; // Raster Compare Register
|
||||
uint16 BXR; // Background X-Scroll Register
|
||||
uint16 BYR; // Background Y-Scroll Register
|
||||
uint16 MWR; // Memory Width Register
|
||||
|
||||
uint16 HSR; // Horizontal Sync Register
|
||||
uint16 HDR; // Horizontal Display Register
|
||||
uint16 VSR;
|
||||
uint16 VDR;
|
||||
|
||||
uint16 VCR;
|
||||
uint16 DCR;
|
||||
uint16 SOUR;
|
||||
uint16 DESR;
|
||||
uint16 LENR;
|
||||
uint16 SATB;
|
||||
|
||||
uint32 RCRCount;
|
||||
|
||||
uint16 read_buffer;
|
||||
uint8 write_latch;
|
||||
uint8 status;
|
||||
|
||||
uint16 DMAReadBuffer;
|
||||
bool DMAReadWrite;
|
||||
bool DMARunning;
|
||||
bool SATBPending;
|
||||
bool burst_mode;
|
||||
|
||||
uint32 BG_YOffset;
|
||||
uint32 BG_XOffset;
|
||||
|
||||
|
||||
|
||||
int SAT_Cache_Valid; // 64 through 128, depending on the number of 32-pixel-wide sprites.
|
||||
SAT_Cache_t SAT_Cache[128]; //64];
|
||||
|
||||
uint16 SAT[0x100];
|
||||
|
||||
uint16 VRAM[65536]; //VRAM_Size];
|
||||
uint64 bg_tile_cache[65536][8]; // Tile, y, x
|
||||
uint8 spr_tile_cache[1024][16][16]; // Tile, y, x
|
||||
uint8 spr_tile_clean[1024]; //VRAM_Size / 64];
|
||||
} vdc_t;
|
||||
|
||||
extern vdc_t *vdc_chips[2];
|
||||
extern int VDC_TotalChips;
|
||||
|
||||
|
||||
void VDC_SetPixelFormat(const MDFN_PixelFormat &format);
|
||||
void VDC_RunFrame(MDFN_Surface *surface, MDFN_Rect *DisplayRect, MDFN_Rect *LineWidths, int skip);
|
||||
void VDC_SetLayerEnableMask(uint64 mask);
|
||||
|
||||
DECLFW(VDC_Write);
|
||||
DECLFW(VDC_Write_ST);
|
||||
|
||||
DECLFR(VCE_Read);
|
||||
|
||||
static INLINE uint8 VDC_Read(unsigned int A, bool SGX)
|
||||
{
|
||||
uint8 ret = 0;
|
||||
int msb = A & 1;
|
||||
int chip = 0;
|
||||
vdc_t *vdc;
|
||||
|
||||
if(SGX)
|
||||
{
|
||||
A &= 0x1F;
|
||||
switch(A)
|
||||
{
|
||||
case 0x8: return(vpc.priority[0]);
|
||||
case 0x9: return(vpc.priority[1]);
|
||||
case 0xA: return(vpc.winwidths[0]);
|
||||
case 0xB: return(vpc.winwidths[0] >> 8);
|
||||
case 0xC: return(vpc.winwidths[1]);
|
||||
case 0xD: return(vpc.winwidths[1] >> 8);
|
||||
case 0xE: return(0);
|
||||
}
|
||||
if(A & 0x8) return(0);
|
||||
chip = (A & 0x10) >> 4;
|
||||
vdc = vdc_chips[chip];
|
||||
A &= 0x3;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdc = vdc_chips[0];
|
||||
A &= 0x3;
|
||||
}
|
||||
|
||||
switch(A)
|
||||
{
|
||||
case 0x0: ret = vdc->status;
|
||||
|
||||
vdc->status &= ~0x3F;
|
||||
|
||||
if(SGX)
|
||||
{
|
||||
if(!(vdc_chips[0]->status & 0x3F) && !(vdc_chips[1]->status & 0x3F))
|
||||
HuC6280_IRQEnd(MDFN_IQIRQ1);
|
||||
}
|
||||
else
|
||||
HuC6280_IRQEnd(MDFN_IQIRQ1); // Clear VDC IRQ line
|
||||
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
ret = REGGETP(vdc->read_buffer, msb);
|
||||
if(vdc->select == 0x2) // VRR - VRAM Read Register
|
||||
{
|
||||
if(msb)
|
||||
{
|
||||
vdc->MARR += vram_inc_tab[(vdc->CR >> 11) & 0x3];
|
||||
|
||||
if(vdc->MARR >= VRAM_Size)
|
||||
VDC_UNDEFINED("Unmapped VRAM VRR read");
|
||||
|
||||
vdc->read_buffer = vdc->VRAM[vdc->MARR & VRAM_SizeMask];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//if(HuCPU.isopread && (A == 1 || A == 3)) //(A == 2 || A == 3)) // && A == 1)
|
||||
if(A == 1)
|
||||
{
|
||||
//if(vdc->display_counter >= (VDS + VSW) && vdc->display_counter < (VDS + VSW + VDW + 1) && vce.dot_clock > 0)
|
||||
if(vce.dot_clock > 0)
|
||||
ret = 0x40;
|
||||
//printf("%d %d %02x\n", vdc->display_counter, vce.dot_clock, ret);
|
||||
//ret = 0x40;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
DECLFW(VCE_Write);
|
||||
|
||||
void VDC_Init(int sgx);
|
||||
void VDC_Close(void);
|
||||
void VDC_Reset(void);
|
||||
void VDC_Power(void);
|
||||
|
||||
int VDC_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
|
||||
uint32 vdc2_pixel, vdc1_pixel;
|
||||
|
||||
vdc2_pixel = vdc1_pixel = vce.color_table_cache[0];
|
||||
|
||||
if(pb & 1)
|
||||
vdc1_pixel = lb0[x];
|
||||
|
||||
if(pb & 2)
|
||||
vdc2_pixel = lb1[x];
|
||||
|
||||
/* Dai MakaiMura uses setting 1, and expects VDC #2 sprites in front of VDC #1 background, but
|
||||
behind VDC #1's sprites.
|
||||
*/
|
||||
switch(pb >> 2)
|
||||
{
|
||||
case 1:
|
||||
//if((vdc2_pixel & (amask << 2)) && !(vdc1_pixel & (amask << 2)))
|
||||
// vdc1_pixel |= amask;
|
||||
vdc1_pixel |= (((vdc2_pixel ^ vdc1_pixel) & vdc2_pixel) >> 2) & amask;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//if((vdc1_pixel & (amask << 2)) && !(vdc2_pixel & (amask << 2)) && !(vdc2_pixel & amask))
|
||||
// vdc1_pixel |= amask;
|
||||
puts("MOO");
|
||||
// TODO: Verify that this is correct logic.
|
||||
{
|
||||
const uint32 intermediate = ((vdc1_pixel ^ vdc2_pixel) & vdc1_pixel) >> 2;
|
||||
vdc1_pixel |= (intermediate ^ vdc2_pixel) & intermediate & amask;
|
||||
}
|
||||
break;
|
||||
}
|
||||
target[x] = (vdc1_pixel & amask) ? vdc2_pixel : vdc1_pixel;
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MATH_OPTIMIZER_FLAGS@
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir)/src/hw_cpu -I$(top_srcdir)/src/hw_sound
|
||||
|
||||
noinst_LIBRARIES = libsms.a
|
||||
|
||||
sms_SOURCES = cart.cpp memz80.cpp pio.cpp render.cpp romdb.cpp sms.cpp sound.cpp system.cpp tms.cpp vdp.cpp
|
||||
|
||||
libsms_a_SOURCES = $(sms_SOURCES)
|
||||
|
|
@ -1,609 +0,0 @@
|
|||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = src/sms
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
|
||||
$(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \
|
||||
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \
|
||||
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \
|
||||
$(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \
|
||||
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \
|
||||
$(top_srcdir)/m4/inttypes-pri.m4 \
|
||||
$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
|
||||
$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
|
||||
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
|
||||
$(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \
|
||||
$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
|
||||
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
AM_V_AR = $(am__v_AR_$(V))
|
||||
am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_AR_0 = @echo " AR " $@;
|
||||
AM_V_at = $(am__v_at_$(V))
|
||||
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_at_0 = @
|
||||
libsms_a_AR = $(AR) $(ARFLAGS)
|
||||
libsms_a_LIBADD =
|
||||
am__objects_1 = cart.$(OBJEXT) memz80.$(OBJEXT) pio.$(OBJEXT) \
|
||||
render.$(OBJEXT) romdb.$(OBJEXT) sms.$(OBJEXT) sound.$(OBJEXT) \
|
||||
system.$(OBJEXT) tms.$(OBJEXT) vdp.$(OBJEXT)
|
||||
am_libsms_a_OBJECTS = $(am__objects_1)
|
||||
libsms_a_OBJECTS = $(am_libsms_a_OBJECTS)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_lt = $(am__v_lt_$(V))
|
||||
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_lt_0 = --silent
|
||||
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_CXX = $(am__v_CXX_$(V))
|
||||
am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CXX_0 = @echo " CXX " $@;
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
|
||||
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CXXLD = $(am__v_CXXLD_$(V))
|
||||
am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CXXLD_0 = @echo " CXXLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_$(V))
|
||||
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libsms_a_SOURCES)
|
||||
DIST_SOURCES = $(libsms_a_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ALLOCA = @ALLOCA@
|
||||
ALSA_CFLAGS = @ALSA_CFLAGS@
|
||||
ALSA_LIBS = @ALSA_LIBS@
|
||||
AMTAR = @AMTAR@
|
||||
AM_CFLAGS = @AM_CFLAGS@
|
||||
AM_CXXFLAGS = @AM_CXXFLAGS@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
CC = @CC@
|
||||
CCAS = @CCAS@
|
||||
CCASDEPMODE = @CCASDEPMODE@
|
||||
CCASFLAGS = @CCASFLAGS@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DATADIRNAME = @DATADIRNAME@
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MATH_OPTIMIZER_FLAGS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GBA_EXTRA_FLAGS = @GBA_EXTRA_FLAGS@
|
||||
GENCAT = @GENCAT@
|
||||
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||
GLIBC2 = @GLIBC2@
|
||||
GLIBC21 = @GLIBC21@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GMSGFMT_015 = @GMSGFMT_015@
|
||||
GREP = @GREP@
|
||||
HAVE_ASPRINTF = @HAVE_ASPRINTF@
|
||||
HAVE_NEWLOCALE = @HAVE_NEWLOCALE@
|
||||
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
|
||||
HAVE_SNPRINTF = @HAVE_SNPRINTF@
|
||||
HAVE_VISIBILITY = @HAVE_VISIBILITY@
|
||||
HAVE_WPRINTF = @HAVE_WPRINTF@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
INTLBISON = @INTLBISON@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTLOBJS = @INTLOBJS@
|
||||
INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@
|
||||
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
|
||||
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||
JACK_CFLAGS = @JACK_CFLAGS@
|
||||
JACK_LIBS = @JACK_LIBS@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@
|
||||
LIBCDIO_LIBS = @LIBCDIO_LIBS@
|
||||
LIBICONV = @LIBICONV@
|
||||
LIBINTL = @LIBINTL@
|
||||
LIBMULTITHREAD = @LIBMULTITHREAD@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPTH = @LIBPTH@
|
||||
LIBPTH_PREFIX = @LIBPTH_PREFIX@
|
||||
LIBS = @LIBS@
|
||||
LIBTHREAD = @LIBTHREAD@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBC = @LTLIBC@
|
||||
LTLIBICONV = @LTLIBICONV@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBMULTITHREAD = @LTLIBMULTITHREAD@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LTLIBPTH = @LTLIBPTH@
|
||||
LTLIBTHREAD = @LTLIBTHREAD@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MATH_OPTIMIZER_FLAGS = @MATH_OPTIMIZER_FLAGS@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MMX_CFLAGS = @MMX_CFLAGS@
|
||||
MSGFMT = @MSGFMT@
|
||||
MSGFMT_015 = @MSGFMT_015@
|
||||
MSGMERGE = @MSGMERGE@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
POSUB = @POSUB@
|
||||
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
|
||||
RANLIB = @RANLIB@
|
||||
SDL_CFLAGS = @SDL_CFLAGS@
|
||||
SDL_CONFIG = @SDL_CONFIG@
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SNDFILE_CFLAGS = @SNDFILE_CFLAGS@
|
||||
SNDFILE_LIBS = @SNDFILE_LIBS@
|
||||
SNES_EXTRA_CXXFLAGS = @SNES_EXTRA_CXXFLAGS@
|
||||
SNES_EXTRA_FLAGS = @SNES_EXTRA_FLAGS@
|
||||
SSE2_CFLAGS = @SSE2_CFLAGS@
|
||||
SSE3_CFLAGS = @SSE3_CFLAGS@
|
||||
SSE_CFLAGS = @SSE_CFLAGS@
|
||||
STRIP = @STRIP@
|
||||
TRIO_CFLAGS = @TRIO_CFLAGS@
|
||||
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
WARNING_FLAGS = @WARNING_FLAGS@
|
||||
WINDRES = @WINDRES@
|
||||
WOE32 = @WOE32@
|
||||
WOE32DLL = @WOE32DLL@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
XMKMF = @XMKMF@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir)/src/hw_cpu -I$(top_srcdir)/src/hw_sound
|
||||
noinst_LIBRARIES = libsms.a
|
||||
sms_SOURCES = cart.cpp memz80.cpp pio.cpp render.cpp romdb.cpp sms.cpp sound.cpp system.cpp tms.cpp vdp.cpp
|
||||
libsms_a_SOURCES = $(sms_SOURCES)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/sms/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/sms/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libsms.a: $(libsms_a_OBJECTS) $(libsms_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libsms.a
|
||||
$(AM_V_AR)$(libsms_a_AR) libsms.a $(libsms_a_OBJECTS) $(libsms_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libsms.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cart.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memz80.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/romdb.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sms.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sound.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tms.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vdp.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.cpp.lo:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLIBRARIES ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1998-2004 Charles MacDonald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
#include "romdb.h"
|
||||
#include "cart.h"
|
||||
#include "../general.h"
|
||||
#include "../md5.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
static uint8 *rom = NULL;
|
||||
static uint8 pages;
|
||||
static uint32 page_mask8;
|
||||
static uint32 page_mask16;
|
||||
static uint32 rom_mask;
|
||||
static uint32 crc;
|
||||
static int mapper;
|
||||
static uint8 *sram = NULL;
|
||||
|
||||
static uint8 fcr[4];
|
||||
static uint8 BankAdd;
|
||||
|
||||
static uint8 CodeMasters_Bank[3];
|
||||
|
||||
static uint8 *CastleRAM = NULL;
|
||||
|
||||
static void writemem_mapper_sega(uint16 A, uint8 V)
|
||||
{
|
||||
if(A >= 0xFFFC)
|
||||
{
|
||||
fcr[A & 0x3] = V;
|
||||
if(A >= 0xFFFD)
|
||||
{
|
||||
static const int BankAddoo[4] = { 0x00, 0x18, 0x10, 0x08 };
|
||||
BankAdd = BankAddoo[fcr[0] & 0x3];
|
||||
}
|
||||
}
|
||||
if(fcr[0] & 0x3)
|
||||
printf("%02x\n", fcr[0] & 0x3);
|
||||
}
|
||||
|
||||
static void writemem_mapper_codies(uint16 A, uint8 V)
|
||||
{
|
||||
if(A < 0xC000)
|
||||
{
|
||||
if((CodeMasters_Bank[1] & 0x80) && (A >= 0xA000))
|
||||
sram[A & 0x1FFF] = V;
|
||||
else
|
||||
CodeMasters_Bank[A >> 14] = V;
|
||||
}
|
||||
}
|
||||
|
||||
void SMS_CartReset(void)
|
||||
{
|
||||
CodeMasters_Bank[0] = 0;
|
||||
CodeMasters_Bank[1] = 0;
|
||||
CodeMasters_Bank[2] = 0;
|
||||
|
||||
fcr[0] = 0x00;
|
||||
fcr[1] = 0x00;
|
||||
fcr[2] = 0x01;
|
||||
fcr[3] = 0x02;
|
||||
|
||||
BankAdd = 0x00;
|
||||
}
|
||||
|
||||
static const char *sms_mapper_string_table[] =
|
||||
{
|
||||
"None",
|
||||
"Sega",
|
||||
"CodeMasters",
|
||||
"32KiB ROM + 8KiB RAM",
|
||||
};
|
||||
|
||||
bool SMS_CartInit(const uint8 *data, uint32 size)
|
||||
{
|
||||
if(!(rom = (uint8*) MDFN_malloc(size, _("Cart ROM"))))
|
||||
return(0);
|
||||
|
||||
pages = size / 0x2000;
|
||||
page_mask8 = round_up_pow2(pages) - 1;
|
||||
page_mask16 = page_mask8 >> 1;
|
||||
rom_mask = (round_up_pow2(pages) * 8192) - 1;
|
||||
|
||||
crc = crc32(0, data, size);
|
||||
|
||||
md5_context md5;
|
||||
md5.starts();
|
||||
md5.update(data, size);
|
||||
md5.finish(MDFNGameInfo->MD5);
|
||||
|
||||
memcpy(rom, data, size);
|
||||
|
||||
if(size <= 40960)
|
||||
mapper = MAPPER_NONE;
|
||||
else
|
||||
mapper = MAPPER_SEGA;
|
||||
|
||||
const rominfo_t *romi;
|
||||
|
||||
if((romi = find_rom_in_db(crc)))
|
||||
{
|
||||
mapper = romi->mapper;
|
||||
sms.display = romi->display;
|
||||
sms.territory = romi->territory;
|
||||
if(romi->system != -1)
|
||||
sms.console = romi->system;
|
||||
}
|
||||
|
||||
if(mapper == MAPPER_CASTLE)
|
||||
{
|
||||
CastleRAM = (uint8 *)calloc(1, 8192);
|
||||
}
|
||||
sram = (uint8 *)calloc(1, 0x8000);
|
||||
|
||||
MDFN_printf(_("ROM: %dKiB\n"), (size + 1023) / 1024);
|
||||
MDFN_printf(_("ROM CRC32: 0x%08x\n"), crc);
|
||||
MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||
MDFN_printf(_("Mapper: %s\n"), sms_mapper_string_table[mapper]);
|
||||
MDFN_printf(_("Territory: %s\n"), (sms.territory == TERRITORY_DOMESTIC) ? _("Domestic") : _("Export"));
|
||||
|
||||
// Load battery-backed RAM, if any.
|
||||
if(sram)
|
||||
{
|
||||
gzFile savegame_fp;
|
||||
|
||||
savegame_fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb");
|
||||
if(savegame_fp)
|
||||
{
|
||||
gzread(savegame_fp, sram, 0x8000);
|
||||
gzclose(savegame_fp);
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
void SMS_CartClose(void)
|
||||
{
|
||||
if(sram)
|
||||
{
|
||||
for(int i = 0; i < 0x8000; i++)
|
||||
{
|
||||
if(sram[i] != 0x00)
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, sram, 0x8000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(rom)
|
||||
{
|
||||
free(rom);
|
||||
rom = NULL;
|
||||
}
|
||||
|
||||
if(CastleRAM)
|
||||
{
|
||||
free(CastleRAM);
|
||||
CastleRAM = NULL;
|
||||
}
|
||||
|
||||
if(sram)
|
||||
{
|
||||
free(sram);
|
||||
sram = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SMS_CartWrite(uint16 A, uint8 V)
|
||||
{
|
||||
if(mapper == MAPPER_CODIES)
|
||||
writemem_mapper_codies(A, V);
|
||||
else if(mapper == MAPPER_SEGA)
|
||||
{
|
||||
if(A >= 0x8000 && A < 0xC000)
|
||||
{
|
||||
if(fcr[0] & 0x8)
|
||||
sram[((fcr[0] & 0x4) ? 0x4000 : 0x0000) + (A & 0x3FFF)] = V;
|
||||
}
|
||||
else
|
||||
writemem_mapper_sega(A, V);
|
||||
}
|
||||
else if(mapper == MAPPER_CASTLE)
|
||||
{
|
||||
if(A >= 0x8000 && A <= 0xBFFF)
|
||||
CastleRAM[A & 0x1FFF] = V;
|
||||
}
|
||||
else if(A < 0xc000)
|
||||
printf("Bah: %04x %02x\n", A, V);
|
||||
}
|
||||
|
||||
uint8 SMS_CartRead(uint16 A)
|
||||
{
|
||||
if(mapper == MAPPER_CODIES)
|
||||
{
|
||||
if(A < 0x4000) // 0 - 0x3fff
|
||||
{
|
||||
return(rom[(A & 0x3FFF) + ((CodeMasters_Bank[0] & page_mask16) << 14)]);
|
||||
}
|
||||
else if(A < 0x8000) // 0x4000 - 0x7FFF
|
||||
{
|
||||
return(rom[(A & 0x3FFF) + ((CodeMasters_Bank[1] & page_mask16) << 14)]);
|
||||
}
|
||||
else if(A < 0xC000) // 0x8000 - 0xBFFF
|
||||
{
|
||||
if((CodeMasters_Bank[1] & 0x80) && (A >= 0xA000))
|
||||
return(sram[A & 0x1FFF]);
|
||||
|
||||
return(rom[(A & 0x3FFF) + ((CodeMasters_Bank[2] & page_mask16) << 14)]);
|
||||
}
|
||||
}
|
||||
else if(mapper == MAPPER_SEGA)
|
||||
{
|
||||
if(A < 0x4000)
|
||||
{
|
||||
if(A < 0x0400)
|
||||
return(rom[A]);
|
||||
else
|
||||
return(rom[(A & 0x3FFF) + (((fcr[1] + BankAdd) & page_mask16) << 14) ]);
|
||||
}
|
||||
else if(A < 0x8000)
|
||||
{
|
||||
return(rom[(A & 0x3FFF) + (((fcr[2] + BankAdd) & page_mask16) << 14) ]);
|
||||
}
|
||||
else if(A < 0xC000)
|
||||
{
|
||||
if(fcr[0] & 0x8)
|
||||
return(sram[((fcr[0] & 0x4) ? 0x4000 : 0x0000) + (A & 0x3FFF)]);
|
||||
else
|
||||
return(rom[(A & 0x3FFF) + (((fcr[3] + BankAdd) & page_mask16) << 14) ]);
|
||||
}
|
||||
}
|
||||
else if(mapper == MAPPER_CASTLE)
|
||||
{
|
||||
if(A >= 0x8000 && A <= 0xBFFF)
|
||||
return(CastleRAM[A & 0x1FFF]);
|
||||
else
|
||||
return(rom[A & rom_mask]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(rom[A & rom_mask]);
|
||||
}
|
||||
return((((A >> 8) | data_bus_pullup) & ~data_bus_pulldown));
|
||||
}
|
||||
|
||||
int SMS_CartStateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(sram, 0x8000),
|
||||
SFARRAY(fcr, 4),
|
||||
SFVAR(BankAdd),
|
||||
SFARRAY(CodeMasters_Bank, 3),
|
||||
SFARRAY(CastleRAM, CastleRAM ? 8192 : 0),
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = 1;
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "CART");
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef __SMS_CART_H
|
||||
#define __SMS_CART_H
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
bool SMS_CartInit(const uint8 *data, uint32 size);
|
||||
|
||||
void SMS_CartWrite(uint16 A, uint8 V);
|
||||
uint8 SMS_CartRead(uint16 A);
|
||||
void SMS_CartReset(void);
|
||||
void SMS_CartClose(void);
|
||||
int SMS_CartStateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
}
|
||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||
|
||||
Change log
|
||||
|
||||
[1.2]
|
||||
|
||||
- Fixed smptab allocation error.
|
||||
- Various source code cleanups.
|
||||
- Minor tweaks to sync with Mac source changes.
|
||||
- New sound update code from Richard Bannister.
|
||||
- Added more support for PAL hardware.
|
||||
- Added partial support for Codemasters games.
|
||||
- Fixed some aspects of ROM loading.
|
||||
- Fixed SRAM restore bug in save states.
|
||||
- Fixed viewport size check when going from extended to normal mode, which
|
||||
fixes Fantastic Dizzy opening screen and V counter test program.
|
||||
- Split up VDP emulation into SMS/GG/MD specific parts.
|
||||
- Added support for different port I/O port memory maps.
|
||||
- Fixed mapper restore bug in save states.
|
||||
- Fixed UI key management in dos/main.c
|
||||
- Improved HV counter emulation.
|
||||
- Added dump VRAM keyboard shortcut. (Alt+V)
|
||||
- Split up DOS code into different modules.
|
||||
- Fixed EXT connector and related I/O port 2 behavior.
|
||||
- Added GG I/O register emulation.
|
||||
- Changed SRAM management.
|
||||
- Modified use of reset/poweron/poweroff functions.
|
||||
- Added configuration via CRC for some Codemasters games.
|
||||
- Fixed implementation of GG input port.
|
||||
- Added cycle counter feature to Z80 emulator.
|
||||
- Added shutdown functions to other modules.
|
||||
- Mapped 2nd player inputs to keyboard numeric pad in dos/main.c
|
||||
- Fixed reset button handling in dos/main.c
|
||||
- Moved Z80 port handlers to memz80.c
|
||||
- Fixed console type assign in loadrom.c (removed TYPE_* defines)
|
||||
- Added support for I/O chip disable control.
|
||||
- Rewrote I/O chip emulation.
|
||||
- Fixed pixel LUT to handle sprite collision behind high priority BG tiles.
|
||||
- Added emulation of sprite overflow status flag.
|
||||
- Added 'granularity' member to bitmap struct and fixed DOS blur code.
|
||||
- Fixed FM sound restore on state load / FM emulator change.
|
||||
- Corrected screen blanking width.
|
||||
- Removed sprite limit disable feature.
|
||||
- Added support for extended display modes.
|
||||
- Added partial support for PAL display timing.
|
||||
- Removed BMP_* macros, replaced with bitmap.viewport.* variables.
|
||||
- Removed Y's (J) rendering hack that was problematic in other games.
|
||||
- Added error logging routines.
|
||||
- Removed Game Gear specific rendering speedups.
|
||||
- Replaced cart.type with sms.console, replaced access with IS_GG macro.
|
||||
- Renamed INPUT_SOFT_RESET to INPUT_RESET. Use for SMS games only.
|
||||
- Removed INPUT_HARD_RESET, use system_reset() instead.
|
||||
- Modified vdp_ctrl_w() to update address register LSB during leading write.
|
||||
- Changed path length in wram/state/snap routines to PATH_MAX in DOS code.
|
||||
- Added define to specify message length in DOS code.
|
||||
- Added r/w handlers for FM detection latch access, renamed fm* -> fmunit*
|
||||
- Added territory/console members to struct sms (removed sms.country).
|
||||
Removed TYPE_* and replaced with TERRITORY_* enums.
|
||||
- Fixed FM register restore during state load when sound is disabled.
|
||||
- Updated memory system to support 1K pages.
|
||||
- Updated zlib to 1.2.1 and unzip.c to 1.0
|
||||
- Moved sound management out of system.c into sound/sound.c,fmintf.c
|
||||
- Moved state management out of system.c into state.c
|
||||
- Rearranged header file include order in system.h
|
||||
- Added support for MAME YM2413 emulator
|
||||
- Abstracted FM sound chip interface to support both YM2413 emulators
|
||||
- Updated timeline in dos/main.c and system.c
|
||||
- Removed SSL logging
|
||||
- Fixed path length in loadrom.c to MAX_PATH from limits.h
|
||||
- Added library version display option to dos/main.c
|
||||
- Moved file I/O code to fileio.c
|
||||
- Fixed loadrom.c to support 16K ROM images
|
||||
- Updated documentation and porting instructions
|
||||
- Modified EMU2413 to have update function for 2-channel output
|
||||
- Modified dos\config.c to ensure parameters are left during option parsing
|
||||
- Modified YM2413 emulator to check for NULL pointer during shutdown
|
||||
- Cleaned up variable names in snd struct
|
||||
- Added default mixer callback
|
||||
- Made sound_shutdown() free memory
|
||||
- Modified sound_init() to allow re-initialization
|
||||
- Cleaned up system.h, sms.h, vdp.h
|
||||
- Optimized color expansion for paletteized 8-bit format in render.c
|
||||
- Added Maxim's SN76489 emulator, removed the old one
|
||||
- Added YM2413 context management
|
||||
- Fixed PSG/FM state save/load behavior
|
||||
|
||||
[0.9.4b]
|
||||
|
||||
- Removed calls to text_mode() and changed textprintf() to textprintf_ex().
|
||||
for compatability with Allegro v4.1.11 (WIP).
|
||||
- Removed VERSION from shared.h and add APP_NAME, APP_VERSION to system.h.
|
||||
- Changed TYPE_OVERSEAS to TYPE_EXPORT in sms.h.
|
||||
- Renamed dos.c/dos.h to main.c/main.h.
|
||||
- Fixed FPS meter state display.
|
||||
- Moved 1P buttons from ALT/LCTRL keys to S/A keys.
|
||||
- Added work RAM dump feature (Alt+W).
|
||||
- Added mostly complete HV counter tables to hvc.h.
|
||||
- Rewrote VDP frame and line interrupt handling.
|
||||
- Added ID and version number to state files.
|
||||
- Removed vdp_run(), renamed sms_run() to system_run() in system.c.
|
||||
- Merged cpu_reset() with sms_reset().
|
||||
- Consolidated parts of the ROM file loading routines.
|
||||
- Increased resolution of GG palette (Mean Bean Machine intro).
|
||||
- Fixed GG palette write handling (RoboCop 3 intro).
|
||||
- Rewrote and optimized tile caching routines.
|
||||
- Made SMS/GG palette brighter.
|
||||
- Fixed leftmost column drawing in SMS mode.
|
||||
- Upgraded Z80 CPU emulator from V2.7 to V3.3.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
Cool Spot
|
||||
|
||||
Menu area has gap after the screen blanking part.
|
||||
Caused by new interrupt handling code.
|
||||
|
||||
F16 Fighting Falcon, Rozetta no Shouzou
|
||||
|
||||
Uses TMS9918 display modes which are not supported yet.
|
||||
|
||||
Y's (J)
|
||||
|
||||
Uses specific features of SMS 1 VDP.
|
||||
|
|
@ -1,340 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -1,454 +0,0 @@
|
|||
|
||||
When you release a port, please include YOUR contact information for users
|
||||
to report bugs and other problems.
|
||||
|
||||
I get a ton of e-mails about a color problem in the Nokia P900 port of SMS
|
||||
Plus because the author apparently included my e-mail address (please link
|
||||
to my webpage instead) and listed NO contact information for him/herself.
|
||||
|
||||
Also, let me know when you release a port, so I can forward these types
|
||||
of e-mails appropriately.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
What's changed for SMS Plus v1.2
|
||||
|
||||
I haven't finished up the porting notes so some things aren't covered yet;
|
||||
look at the DOS source for an example.
|
||||
|
||||
After calling system_init(), use the following functions:
|
||||
|
||||
system_poweron() - Call once, can run game afterwards
|
||||
system_reset() - Can call during gameplay if user wants a hard reset
|
||||
system_poweroff() - Call once when done with a game.
|
||||
|
||||
When loading multiple ROMs in a single session, you'd call poweroff() when
|
||||
done with a game, then poweron() after the next one was loaded.
|
||||
|
||||
SRAM is loaded when poweron() or reset() is called.
|
||||
SRAM is saved when poweroff() is called.
|
||||
|
||||
The SRAM management function has changed:
|
||||
|
||||
void system_manage_sram(uint8 *sram, int slot, int mode);
|
||||
|
||||
'mode' is either SRAM_SAVE or SRAM_LOAD.
|
||||
The slot parameter is ignored for now.
|
||||
If there was SRAM to load, set sms.save = 1;
|
||||
Otherwise, clear SRAM to zero.
|
||||
See the DOS code for an implementation of this function.
|
||||
|
||||
Sound emulation
|
||||
|
||||
The following structure holds sound related information:
|
||||
|
||||
struct {
|
||||
|
||||
/* Input parameters */
|
||||
int sample_rate;
|
||||
int fps;
|
||||
uint32 psg_clock;
|
||||
uint32 fm_clock;
|
||||
int fm_which;
|
||||
void (*mixer_callback)(int16 **stream, int16 **output, int length);
|
||||
|
||||
/* Working data */
|
||||
int16 *stream[STREAM_MAX];
|
||||
int16 *output[2];
|
||||
|
||||
/* Outputs */
|
||||
int enabled;
|
||||
int buffer_size;
|
||||
int sample_count;
|
||||
} snd;
|
||||
|
||||
Normally you would set up this structure before calling system_init().
|
||||
You can change the input parameters and call sound_init() again to change
|
||||
them. Here are how the parameters should be used:
|
||||
|
||||
snd.sample_rate Set to the desired sample rate, e.g. 22050, 44100.
|
||||
Set to 0 to disable sound emulation.
|
||||
|
||||
snd.fps Set to 50 (PAL) or 60 (NTSC) to specify the emulated
|
||||
sound replay rate. PAL consoles are not completely
|
||||
supported yet, I would advise leaving this at 60.
|
||||
|
||||
snd.psg_clock Set to the SN76489 clock speed.
|
||||
Normally this is 3579545. (3.58 MHz)
|
||||
|
||||
snd.fm_clock Set to the YM2413 clock speed.
|
||||
Normally this is 3579545. (3.58 MHz)
|
||||
|
||||
snd.fm_which Set to SND_EMU2413 or SND_YM2413 depending on the FM
|
||||
sound chip emulator you want to use. You can change
|
||||
this and call sound_init() again for realtime switching.
|
||||
|
||||
snd.mixer_callback Set to NULL to use the default stream mixing routine,
|
||||
or point it to your own.
|
||||
|
||||
Calling sound_init() will return 0 if sound emulation was disabled or an
|
||||
error occured, or 1 if initialization was successful. The following
|
||||
variables will be valid for use afterwards:
|
||||
|
||||
snd.enabled Set to 1 if sound emulation is enabled, 0 if disabled.
|
||||
|
||||
snd.buffer_size Size of sample buffer in bytes.
|
||||
|
||||
snd.sample_count Length of sample buffer in samples.
|
||||
|
||||
snd.stream Sound streams for the built-in mixer function or a user
|
||||
supplied one to use.
|
||||
|
||||
snd.output Mixed audio generated by the built-in mixer function
|
||||
that can be output to a sound device. Updated after each
|
||||
call to system_frame().
|
||||
|
||||
An example of setup and use is as follows:
|
||||
|
||||
// Init code
|
||||
snd.sample_rate = 44100;
|
||||
snd.fps = 60;
|
||||
snd.psg_clock = 3579545;
|
||||
snd.fm_clock = 3579545;
|
||||
snd.fm_which = SND_EMU2413;
|
||||
snd.mixer_callback = NULL;
|
||||
system_init();
|
||||
|
||||
// Change some parameter later on
|
||||
snd.fm_which = SND_YM2413;
|
||||
sound_init();
|
||||
|
||||
// Update code
|
||||
system_frame();
|
||||
osd_play_stream_stereo( snd.output, snd.buffer_size );
|
||||
|
||||
Custom mixing
|
||||
|
||||
You can provide your own mixing routine to combine audio streams. Some
|
||||
uses might include:
|
||||
|
||||
- Per-stream volume adjustment, filtering, effects.
|
||||
- Stereo output of YM2413 sound.
|
||||
- Bass-boost on YM2413 rhythm output.
|
||||
- Can take advantage of in-hardware playback/mixing (console ports, etc.)
|
||||
|
||||
There are four sound streams available:
|
||||
|
||||
STREAM_PSG_L SN76489 left channel output
|
||||
STREAM_PSG_R SN76489 right channel output
|
||||
STREAM_FM_MO YM2413 melody channel output
|
||||
STREAM_FM_RO YM2413 rhythm channel output
|
||||
|
||||
The two YM2413 outputs are mixed together, along with the PSG output, for
|
||||
a single monoaural channel in all versions of the SMS and related hardware
|
||||
that support FM sound.
|
||||
|
||||
Synopsis of audio features by console:
|
||||
|
||||
FM sound Stereo PSG Output
|
||||
Mark III No No Mono
|
||||
Mark III+FM Yes No Mono
|
||||
SMS 1 No No Mono
|
||||
SMS 2 No No Mono
|
||||
SMS 1 (J) Yes No Mono
|
||||
Game Gear No Yes Stereo (headphone jack) Mono (speaker)
|
||||
|
||||
Audio from the YM2413 emulator has a lower volume than EMU2413 and will
|
||||
need to be adjusted.
|
||||
|
||||
See the default mixer routine in 'sound.c' for an example.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Porting notes for earlier 0.9.x versions
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
You can check out the DOS specific code to get an idea of
|
||||
how to port SMS Plus.
|
||||
|
||||
0.) Machine dependant issues
|
||||
----------------------------
|
||||
|
||||
Everything should compile fine for big-endian platforms, however
|
||||
I'm not sure the 8-bit pixel to 16-bit pixel conversion function
|
||||
in 'render.c' is endian safe.
|
||||
|
||||
You need to either define or not define 'LSB_FIRST' in your makefile,
|
||||
depending on your needs.
|
||||
|
||||
1.) Graphics
|
||||
------------
|
||||
|
||||
The emulated display can be shown in either 8-bit or 16-bit color.
|
||||
The following structure is used by the rendering routines to
|
||||
draw the display, and you need to set it up prior to running the
|
||||
emulation.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 *data;
|
||||
int width;
|
||||
int height;
|
||||
int pitch;
|
||||
int depth;
|
||||
struct
|
||||
{
|
||||
uint8 color[PALETTE_MAX][3];
|
||||
uint8 dirty[PALETTE_MAX];
|
||||
uint8 update;
|
||||
}pal;
|
||||
}t_bitmap;
|
||||
|
||||
'data' - Pointer to a linear chunk of memory. This should be at least
|
||||
256x192 pixels in size. You can modify this pointer between
|
||||
frames for double buffering (if it's pointed into memory mapped
|
||||
video RAM), or point it to system memory so further changes
|
||||
can be made. (like special effects, or for converting the
|
||||
graphics data to 24 or 32-bit format)
|
||||
'width' - Width of the bitmap, in pixels.
|
||||
'height' - Height of the bitmap, in pixels.
|
||||
'pitch' - Width of the bitmap, in *bytes*.
|
||||
'depth' - Color depth. Must be 8 or 16.
|
||||
'color' - An array of 32 RGB values, each scaled up to eight bits.
|
||||
'dirty' - Each entry is nonzero if the color has been modified.
|
||||
'update' - Nonzero if one or more colors have been modified.
|
||||
|
||||
If you are using 8-bit color, please note that each pixel drawn to
|
||||
the bitmap uses some extra unused bits during the rendering process.
|
||||
You can either mask out these bits using the PIXEL_MASK constant
|
||||
from 'system.h', or set palette ranges 20-3F, 40-5F to the same
|
||||
values as 00-1F.
|
||||
|
||||
If you are using 16-bit color, you can ignore the members of the 'pal'
|
||||
structure. Remember to adjust the MAKE_PIXEL macro in 'render.h' to
|
||||
whatever format your display uses. By default it will make a 16-bit
|
||||
pixel in RGB 5:6:5 format.
|
||||
|
||||
The macros BMP_X_OFFSET, BMP_Y_OFFSET, give the offset into the
|
||||
bitmap. This is because the SMS display takes up the entire bitmap,
|
||||
while the GG display is centered in the middle. These macros provide
|
||||
a convenient way to get the right offset.
|
||||
|
||||
The PALETTE_MAX constant returns the size of the palette.
|
||||
This is currently set to 32 entries.
|
||||
|
||||
2.) Sound
|
||||
---------
|
||||
|
||||
Sound emulation is handled through the following structure:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fps; /* Set to 50 or 60 FPS for PAL or NTSC games */
|
||||
int sample_rate; /* Set between 8000 and 48000 */
|
||||
int enabled; /* 1= Init OK, 0= Sound disabled or error */
|
||||
int sample_count; /* Length of buffer in samples */
|
||||
int buffer_size; /* Size of buffer in bytes */
|
||||
int16 *output[2]; /* Left and right channels */
|
||||
} snd_t;
|
||||
|
||||
You must call 'system_init()' and pass the desired sample rate as an
|
||||
parameter to enable sound emulation. You can set the sample rate to
|
||||
zero if you do not want sound emulation. Remember that 'snd.enabled'
|
||||
will be set afterwards to indicate if any errors occured.
|
||||
|
||||
You also must call 'system_shutdown()' when you are done running
|
||||
the virtual console emulation, so some memory used by the sound
|
||||
emulation code can be freed.
|
||||
|
||||
3.) Input
|
||||
---------
|
||||
|
||||
Input is handled through the following structure:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int pad[2];
|
||||
int system;
|
||||
}t_input;
|
||||
|
||||
'pad[]' - Corresponds to joystick one and joystick two.
|
||||
'system' - System buttons, specifically pause, start, and reset.
|
||||
|
||||
During each frame, you should clear members of this structure to zero,
|
||||
then update each one using the INPUT_* constants in 'system.h'.
|
||||
|
||||
4.) Game Images
|
||||
---------------
|
||||
|
||||
Game images are handled through the following structure:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 *rom;
|
||||
uint8 pages;
|
||||
uint8 type;
|
||||
}t_cart;
|
||||
|
||||
'rom' - Pointer to the ROM image.
|
||||
'pages' - ROM size divided by 16k.
|
||||
'type' - Set to either TYPE_SMS or TYPE_GG.
|
||||
|
||||
Games can be identified by their extension, which is usually '.sms'
|
||||
or '.gg'. Some games have an optional 512-byte header which you must
|
||||
remove. Remember to adjust the file size accordingly.
|
||||
|
||||
5.) Battery backed RAM
|
||||
----------------------
|
||||
|
||||
Some game cartridges can have up to 32k of battery backed RAM present.
|
||||
There are two variables relating to this:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 sram[0x8000];
|
||||
uint8 save;
|
||||
}t_sms;
|
||||
|
||||
'sram' - This is the data that should be saved and loaded.
|
||||
'save' - This is nonzero if the contents of sram[] should be saved.
|
||||
|
||||
It's impossible to know if a game will use battery backed RAM, so the
|
||||
emulation code waits until a game tries to read or write it, and then
|
||||
sets the 'save' flag meaning the data needs to be saved.
|
||||
|
||||
The basic way to deal with this is:
|
||||
|
||||
1. Load a game file
|
||||
2. If a file with the same name, and the extension .sav exists,
|
||||
then load that data into 'sram' and set the 'save' flag.
|
||||
3. When exiting, check if the 'save' flag is nonzero, and if so,
|
||||
write the contents of sram[] to a file with the extension .sav
|
||||
and the same filename as the game file loaded.
|
||||
|
||||
Note that when system_reset() is called, the function 'system_load_sram'
|
||||
which has a prototype in 'system.h' will be called. You *must* implement
|
||||
this function. All it has to do is see if any saved battery backed RAM
|
||||
is present, and update the save/sram[] members accordingly.
|
||||
|
||||
6.) Miscellaneous
|
||||
-----------------
|
||||
|
||||
Before running the virtual console emulation, you can set up
|
||||
these two variables:
|
||||
|
||||
sms.use_fm : 0= No YM2413 sound, 1= YM2413 sound
|
||||
sms.country : Set to TYPE_DOMESTIC (Japan), TYPE_OVERSEAS
|
||||
|
||||
Some games will display different text depending on the country
|
||||
setting. The default value is TYPE_OVERSEAS. This is suitable for every
|
||||
country but Japan.
|
||||
|
||||
Some games have different music if the YM2413 sound chip is present.
|
||||
If the 'fm_enable' value is set to one, then games can detect it.
|
||||
|
||||
If you want to use FM sound, you must ensure that 'use_fm' is nonzero
|
||||
before loading a game, since this variable controls if games can detect
|
||||
the YM2413 chip as well as actual YM2413 output.
|
||||
|
||||
Some games will only enable YM2413 sound if the country type is
|
||||
also set to TYPE_DOMESTIC. One such example is Wonderboy 3.
|
||||
|
||||
Both of these variables are preserved when system_reset() is called.
|
||||
|
||||
You can call load_state/save_state to save and restore the current state
|
||||
of the virtual console emulation. You need to pass a file handle as
|
||||
a parameter to these functions. Therefore, you are responsible for ensuring
|
||||
the file exists, and the file name. The naming convention is that all
|
||||
state files are named '.st0' up to '.st9'.
|
||||
|
||||
7.) Function reference
|
||||
----------------------
|
||||
|
||||
void system_init(int sound_rate);
|
||||
|
||||
You must set up the 'bitmap' and 'cart' structures prior to calling this
|
||||
function. If you want sound emulation, pass the desired sample rate
|
||||
(8000..44100). Afterwards, check the members of the 'snd' structure to see
|
||||
if you can use sound emulation. You can now call system_frame() and the like.
|
||||
|
||||
void system_shutdown(void);
|
||||
|
||||
Call this when you're done with the emulation. Not terribly important
|
||||
as it only frees some memory allocated by the sound emulation routines...
|
||||
|
||||
void system_reset(void)
|
||||
|
||||
Reset the virtual console emulation. This is called internally when
|
||||
the INPUT_HARD_RESET flag for 'input.system' is set.
|
||||
|
||||
void system_load_sram(void);
|
||||
|
||||
Refresh the 'sms.sram[]' and 'sms.save' variables.
|
||||
You must impelement this function yourself.
|
||||
|
||||
void system_frame(int skip);
|
||||
|
||||
You need to call this function 60 times a second. Pass zero as the
|
||||
parameter to draw the current frame, otherwise pass one to omit
|
||||
the drawing process. (ideal for frame skipping) Afterwards,
|
||||
the 'bitmap' and 'snd' structures will be updated with the current
|
||||
graphics and sound data. You should set up the 'input' structure
|
||||
before calling this function.
|
||||
|
||||
8.) Example
|
||||
-----------
|
||||
|
||||
Here's a brief overview of how to use all this:
|
||||
|
||||
- do machine dependant initialization (audio, video, init input, etc.)
|
||||
- set up bitmap structure
|
||||
- set up cart structure (load game)
|
||||
- call system_init()
|
||||
- if snd.enabled is set, we can use sound
|
||||
- load sram data if it exists for the game
|
||||
in a loop:
|
||||
- update input structure based on gamepad/keyboard
|
||||
- call system_frame()
|
||||
- play sound using 'snd.buffer'
|
||||
- copy 'bitmap.data' to the video display
|
||||
- quit if needed
|
||||
- save sram data if the game used it
|
||||
- call system_shutdown()
|
||||
|
||||
9.) Other notes on porting
|
||||
--------------------------
|
||||
|
||||
- Please read the license first.
|
||||
|
||||
- You must release the source code to your port in accordance with the GPL.
|
||||
|
||||
If you have made *no* changes to the main source code, meaning everything
|
||||
in the root directory, and the cpu and dos directories, then you
|
||||
do not have to include those files. No point in wasting space.
|
||||
|
||||
Otherwise, you must include those files with the changes clearly stated.
|
||||
If the changes are the kind that could benefit other ports (like a bug
|
||||
fix), then just let me know so I can update the main distribution, and
|
||||
don't bother releasing those files. But let me know before you release
|
||||
your port, however.
|
||||
|
||||
If you are using some commercial libraries to take care of items like
|
||||
audio output, or if you have developed some routines which you do not want
|
||||
made public (i.e. an assembly optimized blitter, or some custom joypad
|
||||
polling functions), then you do not have to include those files.
|
||||
|
||||
I prefer it where anybody can download a port of SMS Plus and compile it
|
||||
themselves, but I realize this isn't always possible.
|
||||
|
||||
It would be nice, and is not required, that you could organize the
|
||||
source in the same way I have it set up. For instance, maintaining the
|
||||
same directory structure, but adding an '/myport' directory with your
|
||||
specific files, and an appropriate makefile.
|
||||
|
||||
- You must clearly state in the executable that you are the porter,
|
||||
and that I wrote the program. Include YOUR contact information (e-mail
|
||||
address, website URL). This is so users will not ask me questions on how
|
||||
to use a specific port, which I know nothing about.
|
||||
|
||||
- You need to provide documentation. Please remember to mention
|
||||
the licensing stuff pertaining to SMS Plus and the MAME code that's
|
||||
mentioned (for example) in the original 'readme' I wrote. Or just
|
||||
include my documentation and make some additions.
|
||||
|
||||
Please link to my website in the documentation, so people will know
|
||||
where to get the original source code.
|
|
@ -1,310 +0,0 @@
|
|||
----------------------------------------------------------------------------
|
||||
SMS Plus
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
A free, open-source Sega Master System and Game Gear emulator.
|
||||
|
||||
Version 1.2
|
||||
by Charles MacDonald
|
||||
|
||||
What's New
|
||||
----------
|
||||
|
||||
[Version 1.2]
|
||||
|
||||
- Fixed smptab allocation error.
|
||||
- Various source code cleanups.
|
||||
- Minor tweaks to sync with Mac source changes.
|
||||
- Added more support for PAL hardware.
|
||||
- Added partial support for Codemasters games.
|
||||
- Fixed some aspects of ROM loading.
|
||||
- Fixed SRAM restore bug in save states.
|
||||
- Fixed viewport size check when going from extended to normal mode, which
|
||||
fixes Fantastic Dizzy opening screen and V counter test program.
|
||||
- Split up VDP emulation into SMS/GG/MD specific parts.
|
||||
- Added support for different port I/O port memory maps.
|
||||
- Fixed mapper restore bug in save states.
|
||||
- Fixed UI key management in dos/main.c
|
||||
- Improved HV counter emulation.
|
||||
- Added dump VRAM keyboard shortcut. (Alt+V)
|
||||
- Split up DOS code into different modules.
|
||||
- Fixed EXT connector and related I/O port 2 behavior.
|
||||
- Added GG I/O register emulation.
|
||||
- Changed SRAM management.
|
||||
- Modified use of reset/poweron/poweroff functions.
|
||||
- Added configuration via CRC for some Codemasters games.
|
||||
- Fixed implementation of GG input port.
|
||||
- Added cycle counter feature to Z80 emulator.
|
||||
- Added shutdown functions to other modules.
|
||||
- Mapped 2nd player inputs to keyboard numeric pad in dos/main.c
|
||||
- Fixed reset button handling in dos/main.c
|
||||
- Moved Z80 port handlers to memz80.c
|
||||
- Fixed console type assign in loadrom.c (removed TYPE_* defines)
|
||||
- Added support for I/O chip disable control.
|
||||
- Rewrote I/O chip emulation.
|
||||
- Fixed pixel LUT to handle sprite collision behind high priority BG tiles.
|
||||
- Added emulation of sprite overflow status flag.
|
||||
- Added 'granularity' member to bitmap struct and fixed DOS blur code.
|
||||
- Fixed FM sound restore on state load / FM emulator change.
|
||||
- Corrected screen blanking width.
|
||||
- Removed sprite limit disable feature.
|
||||
- Added support for extended display modes.
|
||||
- Added partial support for PAL display timing.
|
||||
- Removed BMP_* macros, replaced with bitmap.viewport.* variables.
|
||||
- Removed Y's (J) rendering hack that was problematic in other games.
|
||||
- Added error logging routines.
|
||||
- Removed Game Gear specific rendering speedups.
|
||||
- Replaced cart.type with sms.console, replaced access with IS_GG macro.
|
||||
- Renamed INPUT_SOFT_RESET to INPUT_RESET. Use for SMS games only.
|
||||
- Removed INPUT_HARD_RESET, use system_reset() instead.
|
||||
- Modified vdp_ctrl_w() to update address register LSB during leading write.
|
||||
- Changed path length in wram/state/snap routines to PATH_MAX in DOS code.
|
||||
- Added define to specify message length in DOS code.
|
||||
- Added r/w handlers for FM detection latch access, renamed fm* -> fmunit*
|
||||
- Added territory/console members to struct sms (removed sms.country).
|
||||
Removed TYPE_* and replaced with TERRITORY_* enums.
|
||||
- Fixed FM register restore during state load when sound is disabled.
|
||||
- Updated memory system to support 1K pages.
|
||||
- Updated zlib to 1.2.1 and unzip.c to 1.0
|
||||
- Moved sound management out of system.c into sound/sound.c,fmintf.c
|
||||
- Moved state management out of system.c into state.c
|
||||
- Rearranged header file include order in system.h
|
||||
- Added support for MAME YM2413 emulator
|
||||
- Abstracted FM sound chip interface to support both YM2413 emulators
|
||||
- Updated timeline in dos/main.c and system.c
|
||||
- Removed SSL logging
|
||||
- Fixed path length in loadrom.c to MAX_PATH from limits.h
|
||||
- Added library version display option to dos/main.c
|
||||
- Moved file I/O code to fileio.c
|
||||
- Fixed loadrom.c to support 16K ROM images
|
||||
- Updated documentation and porting instructions
|
||||
- Modified EMU2413 to have update function for 2-channel output
|
||||
- Modified dos\config.c to ensure parameters are left during option parsing
|
||||
- Modified YM2413 emulator to check for NULL pointer during shutdown
|
||||
- Cleaned up variable names in snd struct
|
||||
- Added default mixer callback
|
||||
- Made sound_shutdown() free memory
|
||||
- Modified sound_init() to allow re-initialization
|
||||
- Cleaned up system.h, sms.h, vdp.h
|
||||
- Optimized color expansion for paletteized 8-bit format in render.c
|
||||
- Added Maxim's SN76489 emulator, removed the old one
|
||||
- Added YM2413 context management
|
||||
- Fixed PSG/FM state save/load behavior
|
||||
|
||||
* Save state format has changed in this release, and will probably change
|
||||
in future updates. Old states from version 0.9.x are not interchangable
|
||||
with the new version 1.x states.
|
||||
|
||||
[Version 0.9.4b]
|
||||
|
||||
- Made a few minor changes to the source code.
|
||||
- Added keyboard shortcut to dump work RAM.
|
||||
- Fixed FPS state display.
|
||||
- Fixed GG palette handling.
|
||||
- Improved tile caching.
|
||||
- Made SMS/GG palette brighter.
|
||||
- Updated Z80 CPU emulator.
|
||||
|
||||
[Version 0.9.4a]
|
||||
|
||||
- A few cleanups so SMS Plus compiles with no errors or warnings.
|
||||
- Use of MMX code is now automatic but can still be disabled manually.
|
||||
- Replaced FM sound emulation with Mitsutaka Okazaki's EMU2413 library.
|
||||
- Fixed parts of the VDP emulation.
|
||||
- Removed support for PSX port.
|
||||
|
||||
[Version 0.9.3]
|
||||
|
||||
- Stereo Game Gear sound.
|
||||
- Save states, 10 per game.
|
||||
- Sound logging, output is .GYM compatible.
|
||||
- Optimized memory access for improved speed.
|
||||
- Screen snapshots in PCX format.
|
||||
- Stereo swap option for left and right speakers.
|
||||
- Added FPS meter.
|
||||
- Added some option toggle keys for in-game configuration.
|
||||
- Definable video driver.
|
||||
- Tweaked display modes for full-screen gameplay.
|
||||
- More of the usual internal changes and bug fixes.
|
||||
|
||||
[Version 0.9.2]
|
||||
|
||||
- Digital YM2413 FM sound emulation. Drums sound real good, too.
|
||||
- System territory switch, default is overseas (Europe / USA)
|
||||
- Made some internal changes and clean-ups to the source code.
|
||||
- Revised document on porting to be actually useful.
|
||||
- Adjusted version number to stay in sync with the Macintosh port.
|
||||
- Support for ZIPped game images and games with 512-byte headers.
|
||||
- Screen expansion now works for 16-bit displays.
|
||||
- Fixed some centering problems with screen expansion on GG games.
|
||||
- Sound output using SEAL should be a bit clearer.
|
||||
- Configuration file support.
|
||||
|
||||
[Version 0.9]
|
||||
|
||||
Everything has been rewritten from scratch. The emulation is much more
|
||||
accurate, as a result compatability has improved greatly.
|
||||
|
||||
The DOS port has a lot of nice features added, including 16-bit color,
|
||||
display blurring, digital sound emulation, and scanlines, which were the
|
||||
most requested items.
|
||||
|
||||
Also new is a Sony Playstation port, though it's highly experimental
|
||||
and has some serious performance issues.
|
||||
|
||||
SMS Plus is now free software; the source code is available for anyone
|
||||
to use as they see fit, and is distributed under the terms of the GNU
|
||||
General Public License.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
(DOS)
|
||||
|
||||
You'll need at least a Pentium 133, a VGA compatible display card,
|
||||
and optionally a joystick and sound card.
|
||||
|
||||
Controls are as follows:
|
||||
|
||||
Arrow Keys - Directional pad
|
||||
a - Button II
|
||||
s - Button I
|
||||
Enter - Start (GG) / PAUSE (SMS)
|
||||
Tab - Soft reset (SMS) / Hard reset (GG)
|
||||
Delete - Hard reset
|
||||
Esc/End - Exit program
|
||||
0-9 - Select save state slot
|
||||
Alt+W - Dump work RAM
|
||||
~ - Switch between EMU2413 and YM2413 FM sound chip emulators.
|
||||
|
||||
F1-F4 - Set frameskip level (F1 = no skip ... F4 = skip 3 frames)
|
||||
F5 - Save state file from current slot
|
||||
F6 - Cycle through state slots (0-9)
|
||||
F7 - Save state file to current slot
|
||||
F8 - Make PCX screen snapshot
|
||||
F9 - Toggle VSync
|
||||
F10 - Toggle speed throttling
|
||||
F11 - Toggle FPS meter
|
||||
|
||||
You can only support a second player if you are using a joystick driver
|
||||
that supports more than one joystick. (e.g. Sidewinder, dual pads, etc.)
|
||||
|
||||
Type 'sp -help' on the command line for a list of useful options.
|
||||
|
||||
-res <x> <y> set the display resolution.
|
||||
-vdriver <n> specify video driver.
|
||||
-depth <n> specify color depth. (8, 16)
|
||||
-blur blur display. (16-bit color only)
|
||||
-scanlines use scanlines effect.
|
||||
-tweak force tweaked 256x192 or 160x144 8-bit display.
|
||||
-scale scale display to full resolution. (slow)
|
||||
-expand force 512x384 or 400x300 zoomed display.
|
||||
-nommx disable use of MMX instructions.
|
||||
-novga disable use of VGA vertical scaling with '-expand'.
|
||||
-vsync wait for vertical sync before blitting.
|
||||
-throttle limit updates to 60 frames per second.
|
||||
-fps show FPS meter.
|
||||
-sound enable sound. (force speed throttling)
|
||||
-sndrate <n> specify sound rate. (8000, 11025, 22050, 44100)
|
||||
-sndcard <n> specify sound card. (0-7)
|
||||
-swap swap left and right stereo output.
|
||||
-joy <s> specify joystick type.
|
||||
-jp use Japanese console type.
|
||||
-fm required to enable YM2413 sound.
|
||||
-info show library versions.
|
||||
-codies force Codemasters mapper
|
||||
|
||||
Here is a list of all the video drivers you can pass as a parameter
|
||||
to the '-vdriver' option:
|
||||
|
||||
auto, safe, vga, modex, vesa2l, vesa3, vbeaf
|
||||
|
||||
Here is a list of all the joystick drivers you can pass as a parameter
|
||||
to the '-joy' option:
|
||||
|
||||
auto, none, standard, 2pads, 4button, 6button, 8button, fspro, wingex,
|
||||
sidewinder, gamepadpro, grip, grip4, sneslpt1, sneslpt2, sneslpt3,
|
||||
psxlpt1, psxlpt2, psxlpt3, n64lpt1, n64lpt2, n64lpt3, db9lpt1, db9lpt2,
|
||||
db9lpt3, tglpt1, tglpt2, tglpt3, wingwar, segaisa, segapci, segapci2
|
||||
|
||||
If you use the expand option without scanlines, and the display looks
|
||||
squashed vertically, then also use the '-novga' switch.
|
||||
|
||||
You can disable MMX use with the '-nommx' switch.
|
||||
|
||||
You can put any commandline option into a plain text file which should
|
||||
be called "sp.cfg". Put one option per line, please. Command line options
|
||||
will override anything in the configuration file.
|
||||
|
||||
Battery back-up RAM and save states are saved to the same directory as the
|
||||
game you loaded. This means running games off write-only media will not
|
||||
work. These files are named after the name of the image itself, not the
|
||||
name of the zipfile archive in the case of zip loading.
|
||||
|
||||
Currently the zip loading code can manage a zipfile where the game
|
||||
image is the first thing in it. If you try to open a huge archive of
|
||||
games, only the first will be played.
|
||||
|
||||
Credits and Acknowledgments
|
||||
---------------------------
|
||||
|
||||
Dedicated to Chris MacDonald.
|
||||
|
||||
Thanks to:
|
||||
|
||||
All Allegro contributors, Bero, Carlos Hasan, Dave, Eric Quinn,
|
||||
Frank Hughes, Flavio Morsoletto, Gilles Volant, Hiromitsu Shioya, Jon,
|
||||
Jean-loup Gailly, James McKay, Jarek Burczynski, Kreed, Mark Adler,
|
||||
Micheal Cunanan, Marcel de Kogel, Marat Fayzullin, Mitsutaka Okazaki,
|
||||
Maxim, Nyef, Nick Jacobson, Omar Cornut, Paul Leaman, Ricardo Bittencourt,
|
||||
Richard Mitton, Richard Talbot-Watkins, Sean Young, Tatsuyuki Satoh,
|
||||
the MAME team, and the S8-DEV forum members.
|
||||
|
||||
Richard Bannister for the Macintosh port. (www.bannister.org)
|
||||
Richard Teather for the Win32 port. (smsplus.vintagegaming.com)
|
||||
Caz Jones for the BeOS port. (http://www.infernal.currantbun.com)
|
||||
Cyx for the SDL port. (http://membres.lycos.fr/cyxdown/smssdl/)
|
||||
Ulrich Hecht for the Linux port. (http://www.emulinks.de/emus/)
|
||||
ss_teven for the Sega Dreamcast port. (no homepage URL)
|
||||
Dagolar for the Sega Saturn port. (http://phemusat.tripod.com/)
|
||||
Aj0 for the GP32 port. (http://ajo.thinknerd.com/gp32/sms32/files/)
|
||||
? for the X-Box port. (http://xport.xb-power.com/smsplus.html)
|
||||
? for the Sony Playstation 2 port. (http://nik.napalm-x.com/)
|
||||
|
||||
All of those responsible for many console, mobile phone, and PDA ports
|
||||
of SMS Plus.
|
||||
|
||||
The artists who worked on Red Zone and Sub Terrania for the cool font
|
||||
used in previous DOS ports.
|
||||
|
||||
I'd also like to thank everybody who contributed information, bug reports,
|
||||
and gave their comments and ideas.
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
Charles MacDonald
|
||||
E-mail: cgfm2 at hotmail dot com
|
||||
WWW: http://cgfm2.emuviews.com
|
||||
|
||||
Legal
|
||||
-----
|
||||
|
||||
SMS Plus is Copyright (C) 1998-2004 Charles MacDonald
|
||||
|
||||
The source code is distributed under the terms of the GNU General Public
|
||||
License.
|
||||
|
||||
The SN76489 emulator is written by Maxim.
|
||||
(http://mwos.cjb.net)
|
||||
|
||||
The EMU2413 emulator is written by Mitsutaka Okazaki.
|
||||
(http://www.angel.ne.jp/~okazaki/ym2413/)
|
||||
|
||||
The Z80 CPU and YM2413 emulator, and SEAL interface code are taken from the
|
||||
MAME project, and terms of their use are covered under the MAME license.
|
||||
(http://www.mame.net)
|
||||
|
||||
The blur code is based on the 'CTV' sources from Dave's DGen emulator.
|
||||
(http://www.dtmnt.com)
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
#ifndef _HVC_H_
|
||||
#define _HVC_H_
|
||||
|
||||
uint8 vc_ntsc_192[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
|
||||
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
uint8 vc_ntsc_224[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
|
||||
0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
uint8 vc_ntsc_256[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
|
||||
};
|
||||
|
||||
uint8 vc_pal_192[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2,
|
||||
0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
uint8 vc_pal_224[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02,
|
||||
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
uint8 vc_pal_256[] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
};
|
||||
|
||||
uint8 *vc_table[2][4] =
|
||||
{
|
||||
{
|
||||
vc_ntsc_192,
|
||||
vc_ntsc_224,
|
||||
vc_ntsc_256,
|
||||
vc_ntsc_192,
|
||||
},
|
||||
{
|
||||
vc_pal_192,
|
||||
vc_pal_224,
|
||||
vc_pal_256,
|
||||
vc_pal_192,
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _HVC_H_ */
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
/*
|
||||
memz80.c --
|
||||
Z80 port handlers.
|
||||
*/
|
||||
#include "shared.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/* Pull-up resistors on data bus */
|
||||
uint8 data_bus_pullup = 0x00;
|
||||
uint8 data_bus_pulldown = 0x00;
|
||||
|
||||
/* Read unmapped memory */
|
||||
uint8 z80_read_unmapped(void)
|
||||
{
|
||||
int pc = z80_getpc();
|
||||
uint8 data;
|
||||
pc = (pc - 1) & 0xFFFF;
|
||||
data = sms_readbyte(pc);
|
||||
|
||||
return ((data | data_bus_pullup) & ~data_bus_pulldown);
|
||||
}
|
||||
|
||||
void memctrl_w(uint8 data)
|
||||
{
|
||||
sms.memctrl = data;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Sega Master System port handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void sms_port_w(uint16 port, uint8 data)
|
||||
{
|
||||
switch(port & 0xC1)
|
||||
{
|
||||
case 0x00:
|
||||
memctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x01:
|
||||
ioctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
vdp_write(port, data);
|
||||
return;
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 sms_port_r(uint16 port)
|
||||
{
|
||||
switch(port & 0xC0)
|
||||
{
|
||||
case 0x00:
|
||||
return z80_read_unmapped();
|
||||
|
||||
case 0x40:
|
||||
return vdp_counter_r(port);
|
||||
|
||||
case 0x80:
|
||||
return vdp_read(port);
|
||||
|
||||
case 0xC0:
|
||||
return input_r(port);
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Sega Master System (J) port handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void smsj_port_w(uint16 port, uint8 data)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if(port >= 0xF0)
|
||||
{
|
||||
switch(port)
|
||||
{
|
||||
case 0xF0:
|
||||
fmunit_write(0, data);
|
||||
return;
|
||||
|
||||
case 0xF1:
|
||||
fmunit_write(1, data);
|
||||
return;
|
||||
|
||||
case 0xF2:
|
||||
fmunit_detect_w(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(port & 0xC1)
|
||||
{
|
||||
case 0x00:
|
||||
memctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x01:
|
||||
ioctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
vdp_write(port, data);
|
||||
return;
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 smsj_port_r(uint16 port)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if(port == 0xF2) // && !(sms.memctrl & 4))
|
||||
return fmunit_detect_r();
|
||||
|
||||
switch(port & 0xC0)
|
||||
{
|
||||
case 0x00:
|
||||
return z80_read_unmapped();
|
||||
|
||||
case 0x40:
|
||||
return vdp_counter_r(port);
|
||||
|
||||
case 0x80:
|
||||
return vdp_read(port);
|
||||
|
||||
case 0xC0:
|
||||
return input_r(port);
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Game Gear port handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void gg_port_w(uint16 port, uint8 data)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if(port <= 0x06) {
|
||||
sio_w(port, data);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(port & 0xC1)
|
||||
{
|
||||
case 0x00:
|
||||
memctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x01:
|
||||
ioctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
gg_vdp_write(port, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8 gg_port_r(uint16 port)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
if(port <= 0x06)
|
||||
return sio_r(port);
|
||||
|
||||
switch(port & 0xC0)
|
||||
{
|
||||
case 0x00:
|
||||
return z80_read_unmapped();
|
||||
|
||||
case 0x40:
|
||||
return vdp_counter_r(port);
|
||||
|
||||
case 0x80:
|
||||
return vdp_read(port);
|
||||
|
||||
case 0xC0:
|
||||
switch(port)
|
||||
{
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
return input_r(port);
|
||||
}
|
||||
return z80_read_unmapped();
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Game Gear (MS) port handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void ggms_port_w(uint16 port, uint8 data)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
switch(port & 0xC1)
|
||||
{
|
||||
case 0x00:
|
||||
memctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x01:
|
||||
ioctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
vdp_write(port, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 ggms_port_r(uint16 port)
|
||||
{
|
||||
port &= 0xFF;
|
||||
|
||||
switch(port & 0xC0)
|
||||
{
|
||||
case 0x00:
|
||||
return z80_read_unmapped();
|
||||
|
||||
case 0x40:
|
||||
return vdp_counter_r(port);
|
||||
|
||||
case 0x80:
|
||||
return vdp_read(port);
|
||||
|
||||
case 0xC0:
|
||||
switch(port)
|
||||
{
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
return input_r(port);
|
||||
}
|
||||
return z80_read_unmapped();
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MegaDrive / Genesis port handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void md_port_w(uint16 port, uint8 data)
|
||||
{
|
||||
switch(port & 0xC1)
|
||||
{
|
||||
case 0x00:
|
||||
/* No memory control register */
|
||||
return;
|
||||
|
||||
case 0x01:
|
||||
ioctrl_w(data);
|
||||
return;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
psg_write(data);
|
||||
return;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
md_vdp_write(port, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8 md_port_r(uint16 port)
|
||||
{
|
||||
switch(port & 0xC0)
|
||||
{
|
||||
case 0x00:
|
||||
return z80_read_unmapped();
|
||||
|
||||
case 0x40:
|
||||
return vdp_counter_r(port);
|
||||
|
||||
case 0x80:
|
||||
return vdp_read(port);
|
||||
|
||||
case 0xC0:
|
||||
switch(port)
|
||||
{
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
return input_r(port);
|
||||
}
|
||||
return z80_read_unmapped();
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
#ifndef _MEMZ80_H_
|
||||
#define _MEMZ80_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/* Global data */
|
||||
extern uint8 data_bus_pullup;
|
||||
extern uint8 data_bus_pulldown;
|
||||
|
||||
/* Function prototypes */
|
||||
uint8 z80_read_unmapped(void);
|
||||
void gg_port_w(uint16 port, uint8 data);
|
||||
uint8 gg_port_r(uint16 port);
|
||||
void ggms_port_w(uint16 port, uint8 data);
|
||||
uint8 ggms_port_r(uint16 port);
|
||||
void sms_port_w(uint16 port, uint8 data);
|
||||
uint8 sms_port_r(uint16 port);
|
||||
void smsj_port_w(uint16 port, uint8 data);
|
||||
uint8 smsj_port_r(uint16 port);
|
||||
void md_port_w(uint16 port, uint8 data);
|
||||
uint8 md_port_r(uint16 port);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _MEMZ80_H_ */
|
|
@ -1,289 +0,0 @@
|
|||
/*
|
||||
pio.c --
|
||||
I/O chip and peripheral emulation.
|
||||
*/
|
||||
#include "shared.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
static io_state io_lut[2][256];
|
||||
static const io_state *io_current;
|
||||
|
||||
void pio_init(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* Make pin state LUT */
|
||||
for(j = 0; j < 2; j++)
|
||||
{
|
||||
for(i = 0; i < 0x100; i++)
|
||||
{
|
||||
/* Common control: pin direction */
|
||||
io_lut[j][i].tr_dir[0] = (i & 0x01) ? PIN_DIR_IN : PIN_DIR_OUT;
|
||||
io_lut[j][i].th_dir[0] = (i & 0x02) ? PIN_DIR_IN : PIN_DIR_OUT;
|
||||
io_lut[j][i].tr_dir[1] = (i & 0x04) ? PIN_DIR_IN : PIN_DIR_OUT;
|
||||
io_lut[j][i].th_dir[1] = (i & 0x08) ? PIN_DIR_IN : PIN_DIR_OUT;
|
||||
|
||||
if(j == 1)
|
||||
{
|
||||
/* Programmable output state (Export machines only) */
|
||||
io_lut[j][i].tr_level[0] = (i & 0x01) ? PIN_LVL_HI : (i & 0x10) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
io_lut[j][i].th_level[0] = (i & 0x02) ? PIN_LVL_HI : (i & 0x20) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
io_lut[j][i].tr_level[1] = (i & 0x04) ? PIN_LVL_HI : (i & 0x40) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
io_lut[j][i].th_level[1] = (i & 0x08) ? PIN_LVL_HI : (i & 0x80) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fixed output state (Domestic machines only) */
|
||||
io_lut[j][i].tr_level[0] = (i & 0x01) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
io_lut[j][i].th_level[0] = (i & 0x02) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
io_lut[j][i].tr_level[1] = (i & 0x04) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
io_lut[j][i].th_level[1] = (i & 0x08) ? PIN_LVL_HI : PIN_LVL_LO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hack dos code doesn't call system_reset
|
||||
pio_reset();
|
||||
}
|
||||
|
||||
|
||||
void pio_reset(void)
|
||||
{
|
||||
/* GG SIO power-on defaults */
|
||||
sms.sio.pdr = 0x7F;
|
||||
sms.sio.ddr = 0xFF;
|
||||
sms.sio.txdata = 0x00;
|
||||
sms.sio.rxdata = 0xFF;
|
||||
sms.sio.sctrl = 0x00;
|
||||
|
||||
/* SMS I/O power-on defaults */
|
||||
ioctrl_w(0xFF);
|
||||
}
|
||||
|
||||
|
||||
void pio_shutdown(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
|
||||
void system_assign_device(int port, int type)
|
||||
{
|
||||
sms.device[port].type = type;
|
||||
}
|
||||
|
||||
void ioctrl_w(uint8 data)
|
||||
{
|
||||
sms.ioctrl = data;
|
||||
io_current = &io_lut[sms.territory][data];
|
||||
}
|
||||
|
||||
uint8 device_r(int offset)
|
||||
{
|
||||
uint8 temp = 0x7F;
|
||||
|
||||
switch(sms.device[offset].type)
|
||||
{
|
||||
case DEVICE_NONE:
|
||||
break;
|
||||
case DEVICE_PAD2B:
|
||||
break;
|
||||
case DEVICE_PADDLE:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint8 input_r(int offset)
|
||||
{
|
||||
uint8 temp = 0xFF;
|
||||
|
||||
/*
|
||||
If I/O chip is disabled, reads return last byte of instruction that
|
||||
read the I/O port.
|
||||
*/
|
||||
if(sms.memctrl & 0x04)
|
||||
return z80_read_unmapped();
|
||||
|
||||
offset &= 1;
|
||||
if(offset == 0)
|
||||
{
|
||||
/* Input port #0 */
|
||||
|
||||
if(input.pad[0] & INPUT_UP) temp &= ~0x01; /* D0 */
|
||||
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02; /* D1 */
|
||||
if(input.pad[0] & INPUT_LEFT) temp &= ~0x04; /* D2 */
|
||||
if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08; /* D3 */
|
||||
if(input.pad[0] & INPUT_BUTTON2) temp &= ~0x10; /* TL */
|
||||
if(input.pad[0] & INPUT_BUTTON1) temp &= ~0x20; /* TR */
|
||||
|
||||
if(sms.console == CONSOLE_GG)
|
||||
{
|
||||
uint8 state = sio_r(0x01);
|
||||
temp = (temp & 0x3F) | (state & 0x03) << 6; /* Insert D1,D0 */
|
||||
}
|
||||
else
|
||||
{
|
||||
if(input.pad[1] & INPUT_UP) temp &= ~0x40; /* D0 */
|
||||
if(input.pad[1] & INPUT_DOWN) temp &= ~0x80; /* D1 */
|
||||
}
|
||||
|
||||
/* Adjust TR state if it is an output */
|
||||
if(io_current->tr_dir[0] == PIN_DIR_OUT) {
|
||||
temp &= ~0x20;
|
||||
temp |= (io_current->tr_level[0] == PIN_LVL_HI) ? 0x20 : 0x00;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Input port #1 */
|
||||
if(sms.console == CONSOLE_GG)
|
||||
{
|
||||
uint8 state = sio_r(0x01);
|
||||
temp = (temp & 0xF0) | ((state & 0x3C) >> 2); /* Insert TR,TL,D3,D2 */
|
||||
temp = (temp & 0x7F) | ((state & 0x40) << 1); /* Insert TH */
|
||||
}
|
||||
else
|
||||
{
|
||||
if(input.pad[1] & INPUT_LEFT) temp &= ~0x01; /* D2 */
|
||||
if(input.pad[1] & INPUT_RIGHT) temp &= ~0x02; /* D3 */
|
||||
if(input.pad[1] & INPUT_BUTTON2) temp &= ~0x04; /* TL */
|
||||
if(input.pad[1] & INPUT_BUTTON1) temp &= ~0x08; /* TR */
|
||||
|
||||
/* Adjust TR state if it is an output */
|
||||
if(io_current->tr_dir[1] == PIN_DIR_OUT) {
|
||||
temp &= ~0x08;
|
||||
temp |= (io_current->tr_level[1] == PIN_LVL_HI) ? 0x08 : 0x00;
|
||||
}
|
||||
|
||||
/* Adjust TH state if it is an output */
|
||||
if(io_current->th_dir[1] == PIN_DIR_OUT) {
|
||||
temp &= ~0x80;
|
||||
temp |= (io_current->th_level[1] == PIN_LVL_HI) ? 0x80 : 0x00;
|
||||
}
|
||||
|
||||
if(input.system & INPUT_RESET) temp &= ~0x10;
|
||||
}
|
||||
|
||||
/* /CONT fixed at '1' for SMS/SMS2/GG */
|
||||
/* /CONT fixed at '0' for GEN/MD */
|
||||
if(IS_MD) temp &= ~0x20;
|
||||
|
||||
/* Adjust TH state if it is an output */
|
||||
if(io_current->th_dir[0] == PIN_DIR_OUT) {
|
||||
temp &= ~0x40;
|
||||
temp |= (io_current->th_level[0] == PIN_LVL_HI) ? 0x40 : 0x00;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint8 sio_r(int offset)
|
||||
{
|
||||
uint8 temp;
|
||||
|
||||
switch(offset & 0xFF)
|
||||
{
|
||||
case 0: /* Input port #2 */
|
||||
temp = 0xE0;
|
||||
if(input.system & INPUT_START) temp &= ~0x80;
|
||||
if(sms.territory == TERRITORY_DOMESTIC) temp &= ~0x40;
|
||||
if(sms.display == DISPLAY_NTSC) temp &= ~0x20;
|
||||
return temp;
|
||||
|
||||
case 1: /* Parallel data register */
|
||||
temp = 0x00;
|
||||
temp |= (sms.sio.ddr & 0x01) ? 0x01 : (sms.sio.pdr & 0x01);
|
||||
temp |= (sms.sio.ddr & 0x02) ? 0x02 : (sms.sio.pdr & 0x02);
|
||||
temp |= (sms.sio.ddr & 0x04) ? 0x04 : (sms.sio.pdr & 0x04);
|
||||
temp |= (sms.sio.ddr & 0x08) ? 0x08 : (sms.sio.pdr & 0x08);
|
||||
temp |= (sms.sio.ddr & 0x10) ? 0x10 : (sms.sio.pdr & 0x10);
|
||||
temp |= (sms.sio.ddr & 0x20) ? 0x20 : (sms.sio.pdr & 0x20);
|
||||
temp |= (sms.sio.ddr & 0x40) ? 0x40 : (sms.sio.pdr & 0x40);
|
||||
temp |= (sms.sio.pdr & 0x80);
|
||||
return temp;
|
||||
|
||||
case 2: /* Data direction register and NMI enable */
|
||||
return sms.sio.ddr;
|
||||
|
||||
case 3: /* Transmit data buffer */
|
||||
return sms.sio.txdata;
|
||||
|
||||
case 4: /* Receive data buffer */
|
||||
return sms.sio.rxdata;
|
||||
|
||||
case 5: /* Serial control */
|
||||
return sms.sio.sctrl;
|
||||
|
||||
case 6: /* Stereo sound control */
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/* Just to please compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
void sio_w(int offset, int data)
|
||||
{
|
||||
switch(offset & 0xFF)
|
||||
{
|
||||
case 0: /* Input port #2 (read-only) */
|
||||
return;
|
||||
|
||||
case 1: /* Parallel data register */
|
||||
sms.sio.pdr = data;
|
||||
return;
|
||||
|
||||
case 2: /* Data direction register and NMI enable */
|
||||
sms.sio.ddr = data;
|
||||
return;
|
||||
|
||||
case 3: /* Transmit data buffer */
|
||||
sms.sio.txdata = data;
|
||||
return;
|
||||
|
||||
case 4: /* Receive data buffer */
|
||||
return;
|
||||
|
||||
case 5: /* Serial control */
|
||||
sms.sio.sctrl = data & 0xF8;
|
||||
return;
|
||||
|
||||
case 6: /* Stereo output control */
|
||||
psg_stereo_w(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int SMS_PIOStateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(sms.sio.pdr),
|
||||
SFVAR(sms.sio.ddr),
|
||||
SFVAR(sms.sio.txdata),
|
||||
SFVAR(sms.sio.rxdata),
|
||||
SFVAR(sms.sio.sctrl),
|
||||
SFVAR(sms.ioctrl),
|
||||
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
|
||||
int ret;
|
||||
|
||||
ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "PIO");
|
||||
|
||||
if(load)
|
||||
{
|
||||
io_current = &io_lut[sms.territory][sms.ioctrl];
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
#ifndef _PIO_H_
|
||||
#define _PIO_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
#define SIO_TXFL (1 << 0) /* 1= Transmit buffer full */
|
||||
#define SIO_RXRD (1 << 1) /* 1= Receive buffer full */
|
||||
#define SIO_FRER (1 << 2) /* 1= Framing error occured */
|
||||
|
||||
#define MAX_DEVICE 2
|
||||
#define DEVICE_D0 (1 << 0)
|
||||
#define DEVICE_D1 (1 << 1)
|
||||
#define DEVICE_D2 (1 << 2)
|
||||
#define DEVICE_D3 (1 << 3)
|
||||
#define DEVICE_TL (1 << 4)
|
||||
#define DEVICE_TR (1 << 5)
|
||||
#define DEVICE_TH (1 << 6)
|
||||
#define DEVICE_ALL (DEVICE_D0 | DEVICE_D1 | DEVICE_D2 | DEVICE_D3 | DEVICE_TL | DEVICE_TR | DEVICE_TH)
|
||||
|
||||
#define PIN_LVL_LO 0 /* Pin outputs 0V */
|
||||
#define PIN_LVL_HI 1 /* Pin outputs +5V */
|
||||
#define PIN_DIR_OUT 0 /* Pin is is an active driving output */
|
||||
#define PIN_DIR_IN 1 /* Pin is in active-low input mode */
|
||||
|
||||
enum {
|
||||
PORT_A = 0, /* I/O port A */
|
||||
PORT_B = 1 /* I/O port B */
|
||||
};
|
||||
|
||||
enum {
|
||||
DEVICE_NONE = 0, /* No peripheral */
|
||||
DEVICE_PAD2B = 1, /* Standard 2-button digital joystick/gamepad */
|
||||
DEVICE_PADDLE = 2 /* Paddle controller; rotary dial with fire button */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8 tr_level[2]; /* TR pin output level */
|
||||
uint8 th_level[2]; /* TH pin output level */
|
||||
uint8 tr_dir[2]; /* TR pin direction */
|
||||
uint8 th_dir[2]; /* TH pin direction */
|
||||
} io_state;
|
||||
|
||||
/* Function prototypes */
|
||||
void pio_init(void);
|
||||
void pio_reset(void);
|
||||
void pio_shutdown(void);
|
||||
void system_assign_device(int port, int type);
|
||||
|
||||
int SMS_PIOStateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void io_lut_init(void);
|
||||
void ioctrl_w(uint8 data);
|
||||
uint8 input_r(int offset);
|
||||
void sio_w(int offset, int data);
|
||||
uint8 sio_r(int offset);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _PIO_H_ */
|
|
@ -1,569 +0,0 @@
|
|||
/*
|
||||
render.c --
|
||||
Display rendering.
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
static const uint8 tms_crom[] =
|
||||
{
|
||||
0x00, 0x00, 0x08, 0x0C,
|
||||
0x10, 0x30, 0x01, 0x3C,
|
||||
0x02, 0x03, 0x05, 0x0F,
|
||||
0x04, 0x33, 0x15, 0x3F
|
||||
};
|
||||
|
||||
static void remap_8_to_32(int line);
|
||||
|
||||
/* Background drawing function */
|
||||
void (*render_bg)(int line) = NULL;
|
||||
void (*render_obj)(int line) = NULL;
|
||||
|
||||
/* Pointer to output buffer */
|
||||
uint8 *linebuf;
|
||||
|
||||
/* Internal buffer for drawing non 8-bit displays */
|
||||
uint8 internal_buffer[0x100];
|
||||
|
||||
/* Precalculated pixel table */
|
||||
uint32 pixel[PALETTE_SIZE];
|
||||
|
||||
/* Dirty pattern info */
|
||||
uint8 bg_name_dirty[0x200]; /* 1= This pattern is dirty */
|
||||
uint16 bg_name_list[0x200]; /* List of modified pattern indices */
|
||||
uint16 bg_list_index; /* # of modified patterns in list */
|
||||
uint8 bg_pattern_cache[0x20000];/* Cached and flipped patterns */
|
||||
|
||||
/* Pixel look-up table */
|
||||
uint8 lut[0x10000];
|
||||
|
||||
/* Bitplane to packed pixel LUT */
|
||||
uint32 bp_lut[0x10000];
|
||||
|
||||
|
||||
void render_shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Initialize the rendering data */
|
||||
void render_init(void)
|
||||
{
|
||||
int i, j;
|
||||
int bx, sx, b, s, bp, bf, sf, c;
|
||||
|
||||
make_tms_tables();
|
||||
|
||||
/* Generate 64k of data for the look up table */
|
||||
for(bx = 0; bx < 0x100; bx++)
|
||||
{
|
||||
for(sx = 0; sx < 0x100; sx++)
|
||||
{
|
||||
/* Background pixel */
|
||||
b = (bx & 0x0F);
|
||||
|
||||
/* Background priority */
|
||||
bp = (bx & 0x20) ? 1 : 0;
|
||||
|
||||
/* Full background pixel + priority + sprite marker */
|
||||
bf = (bx & 0x7F);
|
||||
|
||||
/* Sprite pixel */
|
||||
s = (sx & 0x0F);
|
||||
|
||||
/* Full sprite pixel, w/ palette and marker bits added */
|
||||
sf = (sx & 0x0F) | 0x10 | 0x40;
|
||||
|
||||
/* Overwriting a sprite pixel ? */
|
||||
if(bx & 0x40)
|
||||
{
|
||||
/* Return the input */
|
||||
c = bf;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Work out priority and transparency for both pixels */
|
||||
if(bp)
|
||||
{
|
||||
/* Underlying pixel is high priority */
|
||||
if(b)
|
||||
{
|
||||
c = bf | 0x40;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if(s)
|
||||
{
|
||||
c = sf;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = bf;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Underlying pixel is low priority */
|
||||
if(s)
|
||||
{
|
||||
c = sf;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = bf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store result */
|
||||
lut[(bx << 8) | (sx)] = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make bitplane to pixel lookup table */
|
||||
for(i = 0; i < 0x100; i++)
|
||||
for(j = 0; j < 0x100; j++)
|
||||
{
|
||||
int x;
|
||||
uint32 out = 0;
|
||||
for(x = 0; x < 8; x++)
|
||||
{
|
||||
out |= (j & (0x80 >> x)) ? (uint32)(8 << (x << 2)) : 0;
|
||||
out |= (i & (0x80 >> x)) ? (uint32)(4 << (x << 2)) : 0;
|
||||
}
|
||||
#if LSB_FIRST
|
||||
bp_lut[(j << 8) | (i)] = out;
|
||||
#else
|
||||
bp_lut[(i << 8) | (j)] = out;
|
||||
#endif
|
||||
}
|
||||
|
||||
render_reset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Reset the rendering data */
|
||||
void render_reset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Clear palette */
|
||||
for(i = 0; i < PALETTE_SIZE; i++)
|
||||
{
|
||||
palette_sync(i, 1);
|
||||
}
|
||||
|
||||
/* Invalidate pattern cache */
|
||||
memset(bg_name_dirty, 0, sizeof(bg_name_dirty));
|
||||
memset(bg_name_list, 0, sizeof(bg_name_list));
|
||||
bg_list_index = 0;
|
||||
memset(bg_pattern_cache, 0, sizeof(bg_pattern_cache));
|
||||
|
||||
/* Pick render routine */
|
||||
render_bg = render_bg_sms;
|
||||
render_obj = render_obj_sms;
|
||||
}
|
||||
|
||||
|
||||
/* Draw a line of the display */
|
||||
void render_line(int line, int skip)
|
||||
{
|
||||
int meow_line = 0xFFFF;
|
||||
// printf("%02x\n", vdp.extended);
|
||||
switch(vdp.extended)
|
||||
{
|
||||
case 0: if(line < (192 + 24))
|
||||
meow_line = 24 + line;
|
||||
else if(line >= (vdp.lines_per_frame - 24))
|
||||
meow_line = line - (vdp.lines_per_frame - 24);
|
||||
break;
|
||||
|
||||
case 1: if(line < (224 + 8))
|
||||
meow_line = 8 + line;
|
||||
else if(line >= (vdp.lines_per_frame - 8))
|
||||
meow_line = line - (vdp.lines_per_frame - 8);
|
||||
|
||||
break;
|
||||
case 2: if(line < 240)
|
||||
meow_line = line;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure we're within the viewport range */
|
||||
if(line >= vdp.height)
|
||||
{
|
||||
if(meow_line < 240)
|
||||
{
|
||||
memset(linebuf, BACKDROP_COLOR, 256);
|
||||
remap_8_to_32(meow_line);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Point to current line in output buffer */
|
||||
linebuf = internal_buffer;
|
||||
|
||||
/* Update pattern cache */
|
||||
update_bg_pattern_cache();
|
||||
|
||||
/* Blank line (full width) */
|
||||
if(!(vdp.reg[1] & 0x40))
|
||||
{
|
||||
memset(linebuf, BACKDROP_COLOR, 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Draw background */
|
||||
if(render_bg != NULL)
|
||||
render_bg(line);
|
||||
|
||||
/* Draw sprites */
|
||||
if(render_obj != NULL)
|
||||
render_obj(line);
|
||||
|
||||
/* Blank leftmost column of display */
|
||||
if(vdp.reg[0] & 0x20)
|
||||
{
|
||||
memset(linebuf, BACKDROP_COLOR, 8);
|
||||
}
|
||||
}
|
||||
|
||||
remap_8_to_32(meow_line);
|
||||
}
|
||||
|
||||
|
||||
/* Draw the Master System background */
|
||||
void render_bg_sms(int line)
|
||||
{
|
||||
int locked = 0;
|
||||
int yscroll_mask = (vdp.extended) ? 256 : 224;
|
||||
int v_line = (line + vdp.reg[9]) % yscroll_mask;
|
||||
int v_row = (v_line & 7) << 3;
|
||||
int hscroll = ((vdp.reg[0] & 0x40) && (line < 0x10)) ? 0 : (0x100 - vdp.reg[8]);
|
||||
int column = 0;
|
||||
uint16 attr;
|
||||
uint8 *nt = &vdp.vram[vdp.ntab + (((v_line >> 3) << 6) & ((((vdp.reg[2] & 1) | vdp.quirk_disabled) << 10) | (~0U ^ (1 << 10)) ) )];
|
||||
int nt_scroll = (hscroll >> 3);
|
||||
int shift = (hscroll & 7);
|
||||
uint8 atex_mask;
|
||||
|
||||
uint8 *cache_ptr;
|
||||
uint8 *linebuf_ptr = &linebuf[0 - shift];
|
||||
|
||||
/* Draw first column (clipped) */
|
||||
if(shift)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x = shift; x < 8; x++)
|
||||
linebuf[(0 - shift) + (x)] = 0;
|
||||
|
||||
column++;
|
||||
}
|
||||
|
||||
/* Draw a line of the background */
|
||||
for(; column < 32; column++)
|
||||
{
|
||||
/* Stop vertical scrolling for leftmost eight columns */
|
||||
if((vdp.reg[0] & 0x80) && (!locked) && (column >= 24))
|
||||
{
|
||||
locked = 1;
|
||||
v_row = (line & 7) << 3;
|
||||
nt = &vdp.vram[((vdp.reg[2] << 10) & 0x3800) + ((line >> 3) << 6)];
|
||||
}
|
||||
|
||||
/* Get name table attribute word */
|
||||
attr = nt[(((column + nt_scroll) & 0x1F) << 1) | 0] | (nt[(((column + nt_scroll) & 0x1F) << 1) | 1] << 8);
|
||||
|
||||
/* Expand priority and palette bits */
|
||||
atex_mask = (attr >> 7) & 0x30;
|
||||
|
||||
/* Point to a line of pattern data in cache */
|
||||
cache_ptr = &bg_pattern_cache[((attr & 0x7FF) << 6) | (v_row)];
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
linebuf_ptr[column * 8 + i] = cache_ptr[i] | atex_mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw last column (clipped) */
|
||||
if(shift)
|
||||
{
|
||||
int x, c, a;
|
||||
|
||||
uint8 *p = &linebuf[(0 - shift)+(column << 3)];
|
||||
|
||||
attr = nt[(((column + nt_scroll) & 0x1F) << 1) | 0] | (nt[(((column + nt_scroll) & 0x1F) << 1) | 1] << 8);
|
||||
|
||||
a = (attr >> 7) & 0x30;
|
||||
|
||||
for(x = 0; x < shift; x++)
|
||||
{
|
||||
c = bg_pattern_cache[((attr & 0x7FF) << 6) | (v_row) | (x)];
|
||||
p[x] = ((c) | (a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Draw sprites */
|
||||
void render_obj_sms(int line)
|
||||
{
|
||||
int i;
|
||||
uint8 collision_buffer = 0;
|
||||
|
||||
/* Sprite count for current line (8 max.) */
|
||||
int count = 0;
|
||||
|
||||
/* Sprite dimensions */
|
||||
int width = 8;
|
||||
int height = (vdp.reg[1] & 0x02) ? 16 : 8;
|
||||
|
||||
/* Pointer to sprite attribute table */
|
||||
uint8 *st = (uint8 *)&vdp.vram[vdp.satb];
|
||||
|
||||
/* Adjust dimensions for double size sprites */
|
||||
if(vdp.reg[1] & 0x01)
|
||||
{
|
||||
width *= 2;
|
||||
height *= 2;
|
||||
}
|
||||
|
||||
/* Draw sprites in front-to-back order */
|
||||
for(i = 0; i < 64; i++)
|
||||
{
|
||||
/* Sprite Y position */
|
||||
int yp = st[i];
|
||||
|
||||
/* Found end of sprite list marker for non-extended modes? */
|
||||
if(vdp.extended == 0 && yp == 208)
|
||||
goto end;
|
||||
|
||||
/* Actual Y position is +1 */
|
||||
yp++;
|
||||
|
||||
/* Wrap Y coordinate for sprites > 240 */
|
||||
if(yp > 240) yp -= 256;
|
||||
|
||||
/* Check if sprite falls on current line */
|
||||
if((line >= yp) && (line < (yp + height)))
|
||||
{
|
||||
uint8 *linebuf_ptr;
|
||||
|
||||
/* Width of sprite */
|
||||
int start = 0;
|
||||
int end = width;
|
||||
|
||||
/* Sprite X position */
|
||||
int xp = st[0x80 + (i << 1)];
|
||||
|
||||
/* Pattern name */
|
||||
int n = st[0x81 + (i << 1)];
|
||||
|
||||
/* Bump sprite count */
|
||||
count++;
|
||||
|
||||
/* Too many sprites on this line ? */
|
||||
if(count == 9)
|
||||
{
|
||||
vdp.status |= 0x40;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* X position shift */
|
||||
if(vdp.reg[0] & 0x08) xp -= 8;
|
||||
|
||||
/* Add MSB of pattern name */
|
||||
if(vdp.reg[6] & 0x04) n |= 0x0100;
|
||||
|
||||
/* Mask LSB for 8x16 sprites */
|
||||
if(vdp.reg[1] & 0x02) n &= 0x01FE;
|
||||
|
||||
/* Point to offset in line buffer */
|
||||
linebuf_ptr = (uint8 *)&linebuf[xp];
|
||||
|
||||
/* Clip sprites on left edge */
|
||||
if(xp < 0)
|
||||
{
|
||||
start = (0 - xp);
|
||||
}
|
||||
|
||||
/* Clip sprites on right edge */
|
||||
if((xp + width) > 256)
|
||||
{
|
||||
end = (256 - xp);
|
||||
}
|
||||
|
||||
/* Draw double size sprite */
|
||||
if(vdp.reg[1] & 0x01)
|
||||
{
|
||||
int x;
|
||||
uint8 *cache_ptr = (uint8 *)&bg_pattern_cache[(n << 6) | (((line - yp) >> 1) << 3)];
|
||||
|
||||
/* Draw sprite line */
|
||||
for(x = start; x < end; x++)
|
||||
{
|
||||
/* Source pixel from cache */
|
||||
uint8 sp = cache_ptr[(x >> 1)];
|
||||
|
||||
/* Only draw opaque sprite pixels */
|
||||
if(sp)
|
||||
{
|
||||
/* Background pixel from line buffer */
|
||||
uint8 bg = linebuf_ptr[x];
|
||||
|
||||
/* Look up result */
|
||||
linebuf_ptr[x] = lut[(bg << 8) | (sp)];
|
||||
|
||||
/* Update collision buffer */
|
||||
collision_buffer |= bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Regular size sprite (8x8 / 8x16) */
|
||||
{
|
||||
int x;
|
||||
uint8 *cache_ptr = (uint8 *)&bg_pattern_cache[(n << 6) | ((line - yp) << 3)];
|
||||
|
||||
/* Draw sprite line */
|
||||
for(x = start; x < end; x++)
|
||||
{
|
||||
/* Source pixel from cache */
|
||||
uint8 sp = cache_ptr[x];
|
||||
|
||||
/* Only draw opaque sprite pixels */
|
||||
if(sp)
|
||||
{
|
||||
/* Background pixel from line buffer */
|
||||
uint8 bg = linebuf_ptr[x];
|
||||
|
||||
/* Look up result */
|
||||
linebuf_ptr[x] = lut[(bg << 8) | (sp)];
|
||||
|
||||
/* Update collision buffer */
|
||||
collision_buffer |= bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
/* Set sprite collision flag */
|
||||
if(collision_buffer & 0x40)
|
||||
vdp.status |= 0x20;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void update_bg_pattern_cache(void)
|
||||
{
|
||||
int i;
|
||||
uint8 x, y;
|
||||
uint16 name;
|
||||
|
||||
if(!bg_list_index) return;
|
||||
|
||||
for(i = 0; i < bg_list_index; i++)
|
||||
{
|
||||
name = bg_name_list[i];
|
||||
bg_name_list[i] = 0;
|
||||
|
||||
for(y = 0; y < 8; y++)
|
||||
{
|
||||
if(bg_name_dirty[name] & (1 << y))
|
||||
{
|
||||
uint8 *dst = &bg_pattern_cache[name << 6];
|
||||
|
||||
uint16 bp01 = vdp.vram16[(name << 4) | (y << 1) | (0)];
|
||||
uint16 bp23 = vdp.vram16[(name << 4) | (y << 1) | (1)];
|
||||
uint32 temp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]);
|
||||
|
||||
for(x = 0; x < 8; x++)
|
||||
{
|
||||
uint8 c = (temp >> (x << 2)) & 0x0F;
|
||||
dst[0x00000 | (y << 3) | (x)] = (c);
|
||||
dst[0x08000 | (y << 3) | (x ^ 7)] = (c);
|
||||
dst[0x10000 | ((y ^ 7) << 3) | (x)] = (c);
|
||||
dst[0x18000 | ((y ^ 7) << 3) | (x ^ 7)] = (c);
|
||||
}
|
||||
}
|
||||
}
|
||||
bg_name_dirty[name] = 0;
|
||||
}
|
||||
bg_list_index = 0;
|
||||
}
|
||||
|
||||
static uint32 SystemColorMap[4096];
|
||||
|
||||
/* Update a palette entry */
|
||||
void palette_sync(int index, int force)
|
||||
{
|
||||
uint32 color;
|
||||
|
||||
if(IS_GG)
|
||||
color = SystemColorMap[(vdp.cram[(index << 1) | 0] | (vdp.cram[(index << 1) | 1] << 8)) & 4095];
|
||||
else
|
||||
{
|
||||
if(!(vdp.reg[0] & 0x4))
|
||||
{
|
||||
color = SystemColorMap[tms_crom[index & 0x0F] & 0x3F];
|
||||
}
|
||||
else
|
||||
color = SystemColorMap[vdp.cram[index] & 0x3F];
|
||||
}
|
||||
pixel[index] = color;
|
||||
}
|
||||
|
||||
static void remap_8_to_32(int line)
|
||||
{
|
||||
int i;
|
||||
uint32 *p = (uint32 *)&bitmap.data[(line * bitmap.pitch)];
|
||||
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
p[i] = pixel[ internal_buffer[i] & PIXEL_MASK ];
|
||||
}
|
||||
}
|
||||
|
||||
void SMS_VDPSetPixelFormat(const MDFN_PixelFormat &format)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
if(IS_GG)
|
||||
{
|
||||
for(int i = 0; i < 4096; i++)
|
||||
{
|
||||
/* ----BBBBGGGGRRRR */
|
||||
r = (i & 0xF) * 17;
|
||||
g = ((i >> 4) & 0xF) * 17;
|
||||
b = ((i >> 8) & 0xF) * 17;
|
||||
|
||||
SystemColorMap[i] = format.MakeColor(r, g, b);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < 64; i++)
|
||||
{
|
||||
/* --BBGGRR */
|
||||
r = (i & 0x3) * 85;
|
||||
g = ((i >> 2) & 0x3) * 85;
|
||||
b = ((i >> 4) & 0x3) * 85;
|
||||
|
||||
SystemColorMap[i] = format.MakeColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < PALETTE_SIZE; i++)
|
||||
palette_sync(i, 1);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
#ifndef _RENDER_H_
|
||||
#define _RENDER_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/* Used for blanking a line in whole or in part */
|
||||
#define BACKDROP_COLOR (0x10 | (vdp.reg[7] & 0x0F))
|
||||
|
||||
extern void (*render_bg)(int line);
|
||||
extern void (*render_obj)(int line);
|
||||
extern uint8 *linebuf;
|
||||
extern uint8 internal_buffer[0x100];
|
||||
extern uint32 pixel[];
|
||||
extern uint8 bg_name_dirty[0x200];
|
||||
extern uint16 bg_name_list[0x200];
|
||||
extern uint16 bg_list_index;
|
||||
extern uint8 bg_pattern_cache[0x20000];
|
||||
extern uint8 tms_lookup[16][256][2];
|
||||
extern uint8 mc_lookup[16][256][8];
|
||||
extern uint8 txt_lookup[256][2];
|
||||
extern uint8 bp_expand[256][8];
|
||||
extern uint8 lut[0x10000];
|
||||
extern uint32 bp_lut[0x10000];
|
||||
|
||||
void render_shutdown(void);
|
||||
void render_init(void);
|
||||
void render_reset(void);
|
||||
void render_line(int line, int skip);
|
||||
void render_bg_sms(int line);
|
||||
void render_obj_sms(int line);
|
||||
void update_bg_pattern_cache(void);
|
||||
void palette_sync(int index, int force);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _RENDER_H_ */
|
|
@ -1,41 +0,0 @@
|
|||
#include "shared.h"
|
||||
#include "romdb.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
static const rominfo_t game_list[] = {
|
||||
{ 0x29822980, MAPPER_CODIES, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Cosmic Spacehead" },
|
||||
{ 0xB9664AE1, MAPPER_CODIES, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Fantastic Dizzy" },
|
||||
{ 0xA577CE46, MAPPER_CODIES, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Micro Machines" },
|
||||
{ 0x8813514B, MAPPER_CODIES, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Excellent Dizzy (Proto)" },
|
||||
{ 0xAA140C9C, MAPPER_CODIES, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Excellent Dizzy (Proto - GG)" },
|
||||
{ 0xea5c3a6f, MAPPER_CODIES, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Dinobasher Starring Bignose the Caveman (Proto)" },
|
||||
{ 0xa109a6fe, MAPPER_SEGA, DISPLAY_PAL, TERRITORY_EXPORT, -1, "Power Strike II" },
|
||||
|
||||
// Game Gear
|
||||
{0xd9a7f170, MAPPER_CODIES, DISPLAY_NTSC, TERRITORY_EXPORT, -1, "S.S. Lucifer" },
|
||||
|
||||
{0x5e53c7f7, MAPPER_CODIES, DISPLAY_NTSC, TERRITORY_EXPORT, -1, "Ernie Els Golf" },
|
||||
{0xc888222b, MAPPER_CODIES, DISPLAY_NTSC, TERRITORY_EXPORT, CONSOLE_SMS, "Fantastic Dizzy" },
|
||||
/* Not working?*/ {0x152f0dcc, MAPPER_CODIES, DISPLAY_NTSC, TERRITORY_EXPORT, -1, "Drop Zone" },
|
||||
/* Not working?*/ {0x8813514b, MAPPER_CODIES, DISPLAY_NTSC, TERRITORY_EXPORT, -1, "Excellent Dizzy Collection" },
|
||||
|
||||
// SG-1000
|
||||
{ 0x092f29d6, MAPPER_CASTLE, DISPLAY_NTSC, TERRITORY_DOMESTIC, -1, "The Castle" },
|
||||
{ (uint32)-1, -1 , -1 , -1 , -1, NULL},
|
||||
};
|
||||
|
||||
const rominfo_t *find_rom_in_db(uint32 crc)
|
||||
{
|
||||
/* Look up mapper in game list */
|
||||
for(int i = 0; game_list[i].name != NULL; i++)
|
||||
{
|
||||
if(crc == game_list[i].crc)
|
||||
return(&game_list[i]);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef __ROMDB_H
|
||||
#define __ROMDB_H
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
typedef struct {
|
||||
uint32 crc;
|
||||
int mapper;
|
||||
int display;
|
||||
int territory;
|
||||
int system;
|
||||
const char *name;
|
||||
} rominfo_t;
|
||||
|
||||
const rominfo_t *find_rom_in_db(uint32 crc);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef _SHARED_H_
|
||||
#define _SHARED_H_
|
||||
|
||||
#include "../mednafen.h"
|
||||
#include "z80-fuse/z80.h"
|
||||
#include "sms.h"
|
||||
#include "pio.h"
|
||||
#include "memz80.h"
|
||||
#include "vdp.h"
|
||||
#include "render.h"
|
||||
#include "sound.h"
|
||||
#include "system.h"
|
||||
#include "tms.h"
|
||||
#include "cart.h"
|
||||
|
||||
using namespace MDFN_IEN_SMS;
|
||||
|
||||
#endif /* _SHARED_H_ */
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
sms.c --
|
||||
Sega Master System console emulation.
|
||||
*/
|
||||
#include "shared.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/* SMS context */
|
||||
sms_t sms;
|
||||
|
||||
void sms_writebyte(uint16 A, uint8 V)
|
||||
{
|
||||
if(A >= 0xC000)
|
||||
sms.wram[A & 0x1FFF] = V;
|
||||
|
||||
SMS_CartWrite(A, V);
|
||||
}
|
||||
|
||||
uint8 sms_readbyte(uint16 A)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
if(A >= 0xC000)
|
||||
ret = sms.wram[A & 0x1FFF];
|
||||
else
|
||||
ret = SMS_CartRead(A);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void sms_init(void)
|
||||
{
|
||||
z80_init();
|
||||
|
||||
/* Default: open bus */
|
||||
data_bus_pullup = 0x00;
|
||||
data_bus_pulldown = 0x00;
|
||||
|
||||
z80_writebyte = sms_writebyte;
|
||||
z80_readbyte = sms_readbyte;
|
||||
|
||||
/* Force SMS (J) console type if FM sound enabled */
|
||||
if(sms.use_fm)
|
||||
{
|
||||
sms.console = CONSOLE_SMSJ;
|
||||
sms.territory = TERRITORY_DOMESTIC;
|
||||
sms.display = DISPLAY_NTSC;
|
||||
}
|
||||
|
||||
/* Initialize selected console emulation */
|
||||
switch(sms.console)
|
||||
{
|
||||
case CONSOLE_SMS:
|
||||
z80_writeport = sms_port_w;
|
||||
z80_readport = sms_port_r;
|
||||
break;
|
||||
|
||||
case CONSOLE_SMSJ:
|
||||
z80_writeport = smsj_port_w;
|
||||
z80_readport = smsj_port_r;
|
||||
break;
|
||||
|
||||
case CONSOLE_SMS2:
|
||||
z80_writeport = sms_port_w;
|
||||
z80_readport = sms_port_r;
|
||||
data_bus_pullup = 0xFF;
|
||||
break;
|
||||
|
||||
case CONSOLE_GG:
|
||||
z80_writeport = gg_port_w;
|
||||
z80_readport = gg_port_r;
|
||||
data_bus_pullup = 0xFF;
|
||||
break;
|
||||
|
||||
case CONSOLE_GGMS:
|
||||
z80_writeport = ggms_port_w;
|
||||
z80_readport = ggms_port_r;
|
||||
data_bus_pullup = 0xFF;
|
||||
break;
|
||||
|
||||
case CONSOLE_GEN:
|
||||
case CONSOLE_MD:
|
||||
z80_writeport = md_port_w;
|
||||
z80_readport = md_port_r;
|
||||
break;
|
||||
|
||||
case CONSOLE_GENPBC:
|
||||
case CONSOLE_MDPBC:
|
||||
z80_writeport = md_port_w;
|
||||
z80_readport = md_port_r;
|
||||
data_bus_pullup = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sms_shutdown(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
void sms_reset(void)
|
||||
{
|
||||
z80_reset();
|
||||
|
||||
/* Clear SMS context */
|
||||
memset(sms.wram, 0, sizeof(sms.wram));
|
||||
|
||||
sms.paused = 0x00;
|
||||
sms.save = 0x00;
|
||||
sms.fm_detect = 0x00;
|
||||
sms.memctrl = 0xAB;
|
||||
sms.ioctrl = 0xFF;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
|
||||
#ifndef _SMS_H_
|
||||
#define _SMS_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
enum {
|
||||
SLOT_BIOS = 0,
|
||||
SLOT_CARD = 1,
|
||||
SLOT_CART = 2,
|
||||
SLOT_EXP = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
MAPPER_NONE = 0,
|
||||
MAPPER_SEGA = 1,
|
||||
MAPPER_CODIES = 2,
|
||||
MAPPER_CASTLE = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
DISPLAY_NTSC = 0,
|
||||
DISPLAY_PAL = 1
|
||||
};
|
||||
|
||||
enum {
|
||||
CLOCK_NTSC = 3579545,
|
||||
CLOCK_PAL = 3546893
|
||||
};
|
||||
|
||||
enum {
|
||||
CONSOLE_SMS = 0x20,
|
||||
CONSOLE_SMSJ = 0x21,
|
||||
CONSOLE_SMS2 = 0x22,
|
||||
|
||||
CONSOLE_GG = 0x40,
|
||||
CONSOLE_GGMS = 0x41,
|
||||
|
||||
CONSOLE_MD = 0x80,
|
||||
CONSOLE_MDPBC = 0x81,
|
||||
CONSOLE_GEN = 0x82,
|
||||
CONSOLE_GENPBC = 0x83
|
||||
};
|
||||
|
||||
#define HWTYPE_SMS CONSOLE_SMS
|
||||
#define HWTYPE_GG CONSOLE_GG
|
||||
#define HWTYPE_MD CONSOLE_MD
|
||||
|
||||
#define IS_SMS (sms.console & HWTYPE_SMS)
|
||||
#define IS_GG (sms.console & HWTYPE_GG)
|
||||
#define IS_MD (sms.console & HWTYPE_MD)
|
||||
|
||||
enum {
|
||||
TERRITORY_DOMESTIC = 0,
|
||||
TERRITORY_EXPORT = 1
|
||||
};
|
||||
|
||||
/* SMS context */
|
||||
typedef struct
|
||||
{
|
||||
uint8 wram[0x2000];
|
||||
uint8 paused;
|
||||
uint8 save;
|
||||
uint8 territory;
|
||||
uint8 console;
|
||||
uint8 display;
|
||||
uint8 fm_detect;
|
||||
uint8 use_fm;
|
||||
uint8 memctrl;
|
||||
uint8 ioctrl;
|
||||
struct {
|
||||
uint8 pdr; /* Parallel data register */
|
||||
uint8 ddr; /* Data direction register */
|
||||
uint8 txdata; /* Transmit data buffer */
|
||||
uint8 rxdata; /* Receive data buffer */
|
||||
uint8 sctrl; /* Serial mode control and status */
|
||||
} sio;
|
||||
struct {
|
||||
int type;
|
||||
} device[2];
|
||||
|
||||
uint32 timestamp;
|
||||
int32 cycle_counter;
|
||||
} sms_t;
|
||||
|
||||
/* Global data */
|
||||
extern sms_t sms;
|
||||
|
||||
/* Function prototypes */
|
||||
uint8 sms_readbyte(uint16 A);
|
||||
void sms_init(void);
|
||||
void sms_reset(void);
|
||||
void sms_shutdown(void);
|
||||
void sms_mapper_w(int address, int data);
|
||||
int sms_irq_callback(int param);
|
||||
|
||||
}
|
||||
#endif /* _SMS_H_ */
|
|
@ -1,213 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1998-2004 Charles MacDonald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
#include <blip/Blip_Buffer.h>
|
||||
#include <blip/Stereo_Buffer.h>
|
||||
|
||||
#include "sms_apu/Sms_Apu.h"
|
||||
#include "ym2413/emu2413.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
static Sms_Apu apu;
|
||||
static Stereo_Buffer zebuf;
|
||||
typedef Blip_Synth<blip_good_quality, 1> FMSynth_t;
|
||||
static FMSynth_t fmsynth;
|
||||
static EMU2413 *FMThing = NULL;
|
||||
static uint32 SoundClock;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Sound chip access handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void psg_stereo_w(int data)
|
||||
{
|
||||
apu.write_ggstereo(sms.timestamp, data);
|
||||
}
|
||||
|
||||
void psg_write(int data)
|
||||
{
|
||||
//printf("Write: %d, %02x\n", sms.timestamp, data);
|
||||
apu.write_data(sms.timestamp, data);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Mark III FM Unit / Master System (J) built-in FM handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int fmunit_detect_r(void)
|
||||
{
|
||||
//printf("Detect_r: %02x\n", sms.fm_detect);
|
||||
return sms.fm_detect;
|
||||
}
|
||||
|
||||
void fmunit_detect_w(int data)
|
||||
{
|
||||
//printf("Detect_w: %02x\n", data);
|
||||
sms.fm_detect = data;
|
||||
}
|
||||
|
||||
static int16 fm_last_value;
|
||||
static int32 fm_last_timestamp;
|
||||
static int32 fm_div;
|
||||
|
||||
static void UpdateFM(void)
|
||||
{
|
||||
int32 cycles = sms.timestamp - fm_last_timestamp;
|
||||
|
||||
fm_div -= cycles;
|
||||
while(fm_div <= 0)
|
||||
{
|
||||
int32 new_value;
|
||||
|
||||
new_value = EMU2413_calc(FMThing);
|
||||
|
||||
//if(new_value > 32767) { printf("MOO0: %d\n", new_value); new_value = 32767; }
|
||||
//else if(new_value < -32768) { printf("MOO1: %d\n", new_value); new_value = -32768; }
|
||||
|
||||
//if(abs(new_value) > 95)
|
||||
//{
|
||||
// printf("new=%d, last=%d\n", new_value, fm_last_value);
|
||||
// if(new_value < -) new_value = -95;
|
||||
// else new_value = 95;
|
||||
//}
|
||||
|
||||
fmsynth.offset(sms.timestamp + fm_div, new_value - fm_last_value, zebuf.left());
|
||||
fmsynth.offset(sms.timestamp + fm_div, new_value - fm_last_value, zebuf.right());
|
||||
fm_last_value = new_value;
|
||||
fm_div += 72;
|
||||
}
|
||||
|
||||
fm_last_timestamp = sms.timestamp;
|
||||
}
|
||||
|
||||
void fmunit_write(int offset, int data)
|
||||
{
|
||||
//printf("FM Write: %d %d\n", offset, data);
|
||||
if(FMThing)
|
||||
{
|
||||
UpdateFM();
|
||||
EMU2413_writeIO(FMThing, offset, data);
|
||||
}
|
||||
}
|
||||
|
||||
void SMS_SoundReset(void)
|
||||
{
|
||||
apu.reset();
|
||||
if(FMThing)
|
||||
EMU2413_reset(FMThing);
|
||||
}
|
||||
|
||||
|
||||
int32 SMS_SoundFlush(int16 *SoundBuf, int32 MaxSoundFrames)
|
||||
{
|
||||
int32 FrameCount = 0;
|
||||
|
||||
if(FMThing)
|
||||
UpdateFM();
|
||||
|
||||
apu.end_frame(sms.timestamp);
|
||||
|
||||
zebuf.end_frame(sms.timestamp);
|
||||
|
||||
if(SoundBuf)
|
||||
FrameCount = zebuf.read_samples(SoundBuf, MaxSoundFrames * 2) / 2;
|
||||
else
|
||||
zebuf.clear();
|
||||
|
||||
fm_last_timestamp = 0;
|
||||
|
||||
return(FrameCount);
|
||||
}
|
||||
|
||||
static void RedoVolume(void)
|
||||
{
|
||||
apu.output(zebuf.center(), zebuf.left(), zebuf.right());
|
||||
apu.volume(0.50);
|
||||
fmsynth.volume(1.0 / 16384); //32768); //1.0 / 256); // / 65536); //0.15 / 8192);
|
||||
}
|
||||
|
||||
void SMS_SoundInit(uint32 clock, bool WantFM)
|
||||
{
|
||||
SoundClock = clock;
|
||||
|
||||
SMS_SetSoundRate(0);
|
||||
zebuf.clock_rate((long)(SoundClock));
|
||||
|
||||
RedoVolume();
|
||||
zebuf.bass_freq(20);
|
||||
|
||||
if(WantFM)
|
||||
FMThing = EMU2413_new(3579545);
|
||||
}
|
||||
|
||||
void SMS_SoundClose(void)
|
||||
{
|
||||
if(FMThing)
|
||||
{
|
||||
EMU2413_delete(FMThing);
|
||||
FMThing = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool SMS_SetSoundRate(uint32 rate)
|
||||
{
|
||||
zebuf.set_sample_rate(rate ? rate : 44100, 60);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
int SMS_SoundStateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
Sms_ApuState sn_state;
|
||||
int ret = 1;
|
||||
|
||||
memset(&sn_state, 0, sizeof(Sms_ApuState));
|
||||
|
||||
if(!load)
|
||||
{
|
||||
apu.save_state(&sn_state);
|
||||
}
|
||||
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY32N(sn_state.volume, 4, "Volume"),
|
||||
SFARRAY32N(sn_state.sq_period, 3, "SQPeriod"),
|
||||
SFARRAY32N(sn_state.sq_phase, 3, "SQPhase"),
|
||||
SFVARN(sn_state.noise_period, "NPeriod"),
|
||||
SFVARN(sn_state.noise_shifter, "NShifter"),
|
||||
SFVARN(sn_state.noise_feedback, "NFeedback"),
|
||||
SFVARN(sn_state.latch, "Latch"),
|
||||
SFVARN(sn_state.ggstereo, "GGStereo"),
|
||||
SFEND
|
||||
};
|
||||
|
||||
if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, "PSG"))
|
||||
ret = 0;
|
||||
else if(load)
|
||||
{
|
||||
apu.load_state(&sn_state);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef __SMS_SOUND_H
|
||||
#define __SMS_SOUND_H
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/* Function prototypes */
|
||||
void psg_write(int data);
|
||||
void psg_stereo_w(int data);
|
||||
int fmunit_detect_r(void);
|
||||
void fmunit_detect_w(int data);
|
||||
void fmunit_write(int offset, int data);
|
||||
|
||||
void SMS_SoundClose(void);
|
||||
int32 SMS_SoundFlush(int16 *SoundBuf, int32 MaxSoundFrames);
|
||||
void SMS_SoundReset(void);
|
||||
bool SMS_SetSoundRate(uint32 rate);
|
||||
int SMS_SoundStateAction(StateMem *sm, int load, int data_only);
|
||||
void SMS_SoundInit(uint32 clock, bool WantFM);
|
||||
|
||||
}
|
||||
#endif
|
|
@ -1,496 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1998-2004 Charles MacDonald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
#include "../mempatcher.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
bitmap_t bitmap;
|
||||
input_t input;
|
||||
static int32 SoftResetCount;
|
||||
|
||||
/* Run the virtual console emulation for one frame */
|
||||
void system_frame(int skip_render)
|
||||
{
|
||||
/* Debounce pause key */
|
||||
if(input.system & INPUT_PAUSE)
|
||||
{
|
||||
if(!sms.paused)
|
||||
{
|
||||
sms.paused = 1;
|
||||
|
||||
z80_nmi();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sms.paused = 0;
|
||||
}
|
||||
|
||||
if(SoftResetCount)
|
||||
{
|
||||
SoftResetCount--;
|
||||
if(!SoftResetCount)
|
||||
input.system &= ~INPUT_RESET;
|
||||
}
|
||||
SMS_VDPRunFrame(skip_render);
|
||||
}
|
||||
|
||||
|
||||
void system_reset(void)
|
||||
{
|
||||
SoftResetCount = 0;
|
||||
|
||||
SMS_CartReset();
|
||||
|
||||
sms_reset();
|
||||
pio_reset();
|
||||
vdp_reset();
|
||||
render_reset();
|
||||
SMS_SoundReset();
|
||||
}
|
||||
|
||||
static int StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(SoftResetCount),
|
||||
SFVAR(sms.cycle_counter),
|
||||
SFARRAYN(sms.wram, 0x2000, "RAM"),
|
||||
|
||||
SFVAR(sms.paused),
|
||||
|
||||
SFVAR(input.pad[0]),
|
||||
SFVAR(input.pad[1]),
|
||||
|
||||
SFVAR(input.analog[0]),
|
||||
SFVAR(input.analog[1]),
|
||||
|
||||
SFVAR(input.system),
|
||||
|
||||
SFVAR(sms.fm_detect),
|
||||
SFVAR(sms.memctrl),
|
||||
|
||||
//SFVAR(z80_runtime),
|
||||
//SFARRAY(CPUExRAM, 16384),
|
||||
//SFVAR(FlashStatusEnable),
|
||||
SFEND
|
||||
};
|
||||
int ret = 1;
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN");
|
||||
ret &= z80_state_action(sm, load, data_only, "Z80");
|
||||
ret &= SMS_CartStateAction(sm, load, data_only);
|
||||
ret &= SMS_PIOStateAction(sm, load, data_only);
|
||||
ret &= SMS_SoundStateAction(sm, load, data_only);
|
||||
ret &= SMS_VDPStateAction(sm, load, data_only);
|
||||
|
||||
if(load)
|
||||
{
|
||||
if(sms.cycle_counter > 1000)
|
||||
{
|
||||
sms.cycle_counter = 1000;
|
||||
puts("sms.cycle_counter sanity failed");
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static uint8 *InputPtrs[2];
|
||||
|
||||
static void SetInput(int port, const char *type, void *ptr)
|
||||
{
|
||||
InputPtrs[port] = (uint8 *)ptr;
|
||||
}
|
||||
|
||||
static void Emulate(EmulateSpecStruct *espec)
|
||||
{
|
||||
if(espec->VideoFormatChanged)
|
||||
SMS_VDPSetPixelFormat(espec->surface->format);
|
||||
|
||||
if(espec->SoundFormatChanged)
|
||||
SMS_SetSoundRate(espec->SoundRate);
|
||||
|
||||
|
||||
sms.timestamp = 0;
|
||||
|
||||
input.pad[0] = *InputPtrs[0] & 0x3F;
|
||||
|
||||
if(IS_SMS)
|
||||
{
|
||||
input.pad[1] = *InputPtrs[1] & 0x3F;
|
||||
|
||||
if((*InputPtrs[0] | *InputPtrs[1]) & 0x40)
|
||||
input.system |= INPUT_PAUSE;
|
||||
else
|
||||
input.system &= ~INPUT_PAUSE;
|
||||
}
|
||||
else // GG:
|
||||
{
|
||||
if(*InputPtrs[0] & 0x40)
|
||||
{
|
||||
input.system |= INPUT_START;
|
||||
}
|
||||
else
|
||||
input.system &= ~INPUT_START;
|
||||
}
|
||||
|
||||
//NGPJoyLatch = *chee;
|
||||
|
||||
MDFNMP_ApplyPeriodicCheats();
|
||||
|
||||
if(sms.console == CONSOLE_GG)
|
||||
{
|
||||
espec->DisplayRect.x = 48;
|
||||
espec->DisplayRect.y = 48;
|
||||
espec->DisplayRect.w = 160;
|
||||
espec->DisplayRect.h = 144;
|
||||
}
|
||||
else
|
||||
{
|
||||
espec->DisplayRect.x = 0;
|
||||
espec->DisplayRect.y = 0;
|
||||
espec->DisplayRect.w = 256;
|
||||
espec->DisplayRect.h = 240;
|
||||
}
|
||||
|
||||
bitmap.data = (uint8*)espec->surface->pixels;
|
||||
bitmap.width = 256;
|
||||
bitmap.height = 240;
|
||||
bitmap.pitch = 256 * sizeof(uint32);
|
||||
|
||||
system_frame(espec->skip);
|
||||
|
||||
espec->MasterCycles = sms.timestamp;
|
||||
espec->SoundBufSize = SMS_SoundFlush(espec->SoundBuf, espec->SoundBufMaxSize);
|
||||
}
|
||||
|
||||
static void CloseGame(void)
|
||||
{
|
||||
SMS_CartClose();
|
||||
|
||||
sms_shutdown();
|
||||
pio_shutdown();
|
||||
vdp_shutdown();
|
||||
render_shutdown();
|
||||
SMS_SoundClose();
|
||||
}
|
||||
|
||||
static int LoadCommon(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
int32 size = fp->size;
|
||||
const uint8 *data_ptr = fp->data;
|
||||
|
||||
if(size & 512)
|
||||
{
|
||||
size -= 512;
|
||||
data_ptr += 512;
|
||||
}
|
||||
|
||||
/* Assign default settings (US NTSC machine) */
|
||||
sms.display = DISPLAY_NTSC;
|
||||
|
||||
sms.territory = MDFN_GetSettingI("sms.territory");
|
||||
sms.use_fm = FALSE;
|
||||
|
||||
|
||||
if(!SMS_CartInit(data_ptr, size))
|
||||
return(0);
|
||||
|
||||
if(IS_SMS && sms.territory == TERRITORY_DOMESTIC)
|
||||
sms.use_fm = MDFN_GetSettingB("sms.fm");
|
||||
|
||||
MDFNMP_Init(1024, 65536 / 1024);
|
||||
|
||||
system_assign_device(PORT_A, DEVICE_PAD2B);
|
||||
system_assign_device(PORT_B, DEVICE_PAD2B);
|
||||
|
||||
MDFNMP_AddRAM(8192, 0xC000, sms.wram);
|
||||
|
||||
sms_init();
|
||||
pio_init();
|
||||
vdp_init(IS_SMS && sms.territory == TERRITORY_DOMESTIC);
|
||||
render_init();
|
||||
|
||||
MDFNGameInfo->GameSetMD5Valid = FALSE;
|
||||
|
||||
uint32 sndclk;
|
||||
|
||||
if(sms.display == DISPLAY_PAL)
|
||||
{
|
||||
sndclk = 3546893;
|
||||
MDFNGameInfo->fps = (uint32)((uint64)65536 * 256 * sndclk / 313 / 228); //6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198
|
||||
}
|
||||
else
|
||||
{
|
||||
sndclk = 3579545;
|
||||
MDFNGameInfo->fps = (uint32)((uint64)65536 * 256 * sndclk / 262 / 228); //6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198
|
||||
}
|
||||
|
||||
MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(sndclk);
|
||||
|
||||
SMS_SoundInit(sndclk, sms.use_fm);
|
||||
|
||||
sms.save = 0;
|
||||
|
||||
|
||||
system_reset();
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static bool TestMagicSMS(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
if(strcasecmp(fp->ext, "sms") && strcasecmp(fp->ext, "sg") && strcasecmp(fp->ext, "sc"))
|
||||
return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static bool TestMagicGG(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
if(strcasecmp(fp->ext, "gg"))
|
||||
return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
static int LoadSMS(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
sms.console = CONSOLE_SMS;
|
||||
|
||||
return(LoadCommon(name, fp));
|
||||
}
|
||||
|
||||
static int LoadGG(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
sms.console = CONSOLE_GG;
|
||||
|
||||
return(LoadCommon(name, fp));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const InputDeviceInputInfoStruct GGGamepadIDII[] =
|
||||
{
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "button1", "Button 1", 4, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "button2", "Button 2", 5, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "Start", "Start", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
static const InputDeviceInputInfoStruct SMSGamepadIDII[] =
|
||||
{
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "fire1", "Fire 1/Start", 4, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "fire2", "Fire 2", 5, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "pause", "Pause", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
static InputDeviceInfoStruct GGInputDeviceInfo[] =
|
||||
{
|
||||
{
|
||||
"gamepad",
|
||||
"Gamepad",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GGGamepadIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
GGGamepadIDII,
|
||||
}
|
||||
};
|
||||
|
||||
static InputDeviceInfoStruct SMSInputDeviceInfo[] =
|
||||
{
|
||||
{
|
||||
"gamepad",
|
||||
"Gamepad",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(SMSGamepadIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
SMSGamepadIDII,
|
||||
}
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct GGPortInfo[] =
|
||||
{
|
||||
{ "builtin", "Built-In", sizeof(GGInputDeviceInfo) / sizeof(InputDeviceInfoStruct), GGInputDeviceInfo, "gamepad" },
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct SMSPortInfo[] =
|
||||
{
|
||||
{ "port1", "Port 1", sizeof(SMSInputDeviceInfo) / sizeof(InputDeviceInfoStruct), SMSInputDeviceInfo, "gamepad" },
|
||||
{ "port2", "Port 2", sizeof(SMSInputDeviceInfo) / sizeof(InputDeviceInfoStruct), SMSInputDeviceInfo, "gamepad" }
|
||||
};
|
||||
|
||||
static InputInfoStruct GGInputInfo =
|
||||
{
|
||||
sizeof(GGPortInfo) / sizeof(InputPortInfoStruct),
|
||||
GGPortInfo
|
||||
};
|
||||
|
||||
static InputInfoStruct SMSInputInfo =
|
||||
{
|
||||
sizeof(SMSPortInfo) / sizeof(InputPortInfoStruct),
|
||||
SMSPortInfo
|
||||
};
|
||||
|
||||
static void DoSimpleCommand(int cmd)
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case MDFN_MSC_POWER: system_reset(); break;
|
||||
case MDFN_MSC_RESET: if(IS_SMS)
|
||||
{
|
||||
input.system |= INPUT_RESET;
|
||||
SoftResetCount = 20;
|
||||
}
|
||||
else
|
||||
system_reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static MDFNSetting_EnumList Territory_List[] =
|
||||
{
|
||||
{ "domestic", TERRITORY_DOMESTIC, gettext_noop("Domestic(Japanese)") },
|
||||
{ "export", TERRITORY_EXPORT, gettext_noop("Export(World)") },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static MDFNSetting SMSSettings[] =
|
||||
{
|
||||
{ "sms.territory", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("System territory/region."), NULL, MDFNST_ENUM, "export", NULL, NULL, NULL, NULL, Territory_List },
|
||||
{ "sms.fm", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Enable FM sound emulation when playing domestic/Japan-region games."), NULL, MDFNST_BOOL, "1" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static MDFNSetting GGSettings[] =
|
||||
{
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
static const FileExtensionSpecStruct SMSKnownExtensions[] =
|
||||
{
|
||||
{ ".sms", gettext_noop("Sega Master System ROM Image") },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const FileExtensionSpecStruct GGKnownExtensions[] =
|
||||
{
|
||||
{ ".gg", gettext_noop("Game Gear ROM Image") },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
MDFNGI EmulatedSMS =
|
||||
{
|
||||
"sms",
|
||||
"Sega Master System",
|
||||
SMSKnownExtensions,
|
||||
MODPRIO_INTERNAL_HIGH,
|
||||
NULL,
|
||||
&SMSInputInfo,
|
||||
LoadSMS,
|
||||
TestMagicSMS,
|
||||
NULL,
|
||||
NULL,
|
||||
CloseGame,
|
||||
NULL, //ToggleLayer,
|
||||
NULL, //"Hi\0Ho\0Mo\0", //"Background Scroll\0Foreground Scroll\0Sprites\0",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
StateAction,
|
||||
Emulate,
|
||||
SetInput,
|
||||
DoSimpleCommand,
|
||||
SMSSettings,
|
||||
0,
|
||||
0,
|
||||
FALSE, // Multires possible?
|
||||
|
||||
256, // lcm_width
|
||||
240, // lcm_height
|
||||
NULL, // Dummy
|
||||
|
||||
256, // Nominal width
|
||||
240, // Nominal height
|
||||
|
||||
256, // Framebuffer width
|
||||
256, // Framebuffer height
|
||||
|
||||
2, // Number of output sound channels
|
||||
};
|
||||
|
||||
MDFNGI EmulatedGG =
|
||||
{
|
||||
"gg",
|
||||
"Sega Game Gear",
|
||||
GGKnownExtensions,
|
||||
MODPRIO_INTERNAL_HIGH,
|
||||
NULL,
|
||||
&GGInputInfo,
|
||||
LoadGG,
|
||||
TestMagicGG,
|
||||
NULL,
|
||||
NULL,
|
||||
CloseGame,
|
||||
NULL, //ToggleLayer,
|
||||
NULL, //"Hi\0Ho\0Mo\0", //"Background Scroll\0Foreground Scroll\0Sprites\0",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
StateAction,
|
||||
Emulate,
|
||||
SetInput,
|
||||
DoSimpleCommand,
|
||||
GGSettings,
|
||||
0,
|
||||
0,
|
||||
FALSE, // Multires possible?
|
||||
|
||||
160, // lcm_width
|
||||
144, // lcm_height
|
||||
NULL, // Dummy
|
||||
|
||||
|
||||
160, // nominal width
|
||||
144, // nominal height
|
||||
|
||||
256, // Framebuffer width
|
||||
256, // Framebuffer height
|
||||
|
||||
2, // Number of output sound channels
|
||||
};
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
|
||||
#ifndef _SYSTEM_H_
|
||||
#define _SYSTEM_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
#define APP_NAME "SMS Plus"
|
||||
#define APP_VERSION "1.2"
|
||||
|
||||
#define PALETTE_SIZE 0x20
|
||||
|
||||
/* Mask for removing unused pixel data */
|
||||
#define PIXEL_MASK 0x1F
|
||||
|
||||
/* These can be used for 'input.pad[]' */
|
||||
#define INPUT_UP 0x00000001
|
||||
#define INPUT_DOWN 0x00000002
|
||||
#define INPUT_LEFT 0x00000004
|
||||
#define INPUT_RIGHT 0x00000008
|
||||
#define INPUT_BUTTON2 0x00000010
|
||||
#define INPUT_BUTTON1 0x00000020
|
||||
|
||||
/* These can be used for 'input.system' */
|
||||
#define INPUT_START 0x00000001 /* Game Gear only */
|
||||
#define INPUT_PAUSE 0x00000002 /* Master System only */
|
||||
#define INPUT_RESET 0x00000004 /* Master System only */
|
||||
|
||||
enum {
|
||||
SRAM_SAVE = 0,
|
||||
SRAM_LOAD = 1
|
||||
};
|
||||
|
||||
|
||||
/* User input structure */
|
||||
typedef struct
|
||||
{
|
||||
uint32 pad[2];
|
||||
uint8 analog[2];
|
||||
uint32 system;
|
||||
} input_t;
|
||||
|
||||
/* Bitmap structure */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *data;
|
||||
int width;
|
||||
int height;
|
||||
int pitch;
|
||||
} bitmap_t;
|
||||
|
||||
/* Global variables */
|
||||
extern bitmap_t bitmap; /* Display bitmap */
|
||||
extern input_t input; /* Controller input */
|
||||
|
||||
/* Function prototypes */
|
||||
void system_frame(int skip_render);
|
||||
void system_init(void);
|
||||
void system_reset(void);
|
||||
void system_manage_sram(uint8 *sram, int slot, int mode);
|
||||
void system_poweron(void);
|
||||
void system_poweroff(void);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _SYSTEM_H_ */
|
||||
|
||||
|
|
@ -1,521 +0,0 @@
|
|||
/*
|
||||
tms.c --
|
||||
TMS9918 and legacy video mode support.
|
||||
*/
|
||||
#include "shared.h"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
int text_counter; /* Text offset counter */
|
||||
uint8 tms_lookup[16][256][2]; /* Expand BD, PG data into 8-bit pixels (G1,G2) */
|
||||
uint8 mc_lookup[16][256][8]; /* Expand BD, PG data into 8-bit pixels (MC) */
|
||||
uint8 txt_lookup[256][2]; /* Expand BD, PG data into 8-bit pixels (TX) */
|
||||
uint8 bp_expand[256][8]; /* Expand PG data into 8-bit pixels */
|
||||
uint8 tms_obj_lut[16*256]; /* Look up priority between SG and display pixels */
|
||||
|
||||
static const uint8 diff_mask[] = {0x07, 0x07, 0x0F, 0x0F};
|
||||
static const uint8 name_mask[] = {0xFF, 0xFF, 0xFC, 0xFC};
|
||||
static const uint8 diff_shift[] = {0, 1, 0, 1};
|
||||
static const uint8 size_tab[] = {8, 16, 16, 32};
|
||||
|
||||
/* Internally latched sprite data in the VDP */
|
||||
typedef struct {
|
||||
int xpos;
|
||||
uint8 attr;
|
||||
uint8 sg[2];
|
||||
} tms_sprite;
|
||||
|
||||
tms_sprite sprites[4];
|
||||
int sprites_found;
|
||||
|
||||
void parse_line(int line)
|
||||
{
|
||||
int yp, i;
|
||||
int mode = vdp.reg[1] & 3;
|
||||
int size = size_tab[mode];
|
||||
int diff, name;
|
||||
uint8 *sa, *sg;
|
||||
tms_sprite *p;
|
||||
|
||||
/* Reset # of sprites found */
|
||||
sprites_found = 0;
|
||||
|
||||
/* Parse sprites */
|
||||
for(i = 0; i < 32; i++)
|
||||
{
|
||||
/* Point to current sprite in SA and our current sprite record */
|
||||
p = &sprites[sprites_found];
|
||||
sa = &vdp.vram[vdp.sa + (i << 2)];
|
||||
|
||||
/* Fetch Y coordinate */
|
||||
yp = sa[0];
|
||||
|
||||
/* Check for end marker */
|
||||
if(yp == 0xD0)
|
||||
goto parse_end;
|
||||
|
||||
/* Wrap Y position */
|
||||
if(yp > 0xE0)
|
||||
yp -= 256;
|
||||
|
||||
/* Check if sprite falls on following line */
|
||||
if(line >= yp && line < (yp + size))
|
||||
{
|
||||
/* Sprite overflow on this line */
|
||||
if(sprites_found == 4)
|
||||
{
|
||||
/* Set 5S and abort parsing */
|
||||
vdp.status |= 0x40;
|
||||
goto parse_end;
|
||||
}
|
||||
|
||||
/* Fetch X position */
|
||||
p->xpos = sa[1];
|
||||
|
||||
/* Fetch name */
|
||||
name = sa[2] & name_mask[mode];
|
||||
|
||||
/* Load attribute into attribute storage */
|
||||
p->attr = sa[3];
|
||||
|
||||
/* Apply early clock bit */
|
||||
if(p->attr & 0x80)
|
||||
p->xpos -= 32;
|
||||
|
||||
/* Calculate offset in pattern */
|
||||
diff = ((line - yp) >> diff_shift[mode]) & diff_mask[mode];
|
||||
|
||||
/* Insert additional name bit for 16-pixel tall sprites */
|
||||
if(diff & 8)
|
||||
name |= 1;
|
||||
|
||||
/* Fetch SG data */
|
||||
sg = &vdp.vram[vdp.sg | (name << 3) | (diff & 7)];
|
||||
p->sg[0] = sg[0x00];
|
||||
p->sg[1] = sg[0x10];
|
||||
|
||||
/* Bump found sprite count */
|
||||
++sprites_found;
|
||||
}
|
||||
}
|
||||
parse_end:
|
||||
|
||||
/* Insert number of last sprite entry processed */
|
||||
vdp.status = (vdp.status & 0xE0) | (i & 0x1F);
|
||||
}
|
||||
|
||||
void render_obj_tms(int line)
|
||||
{
|
||||
int i, x = 0;
|
||||
int size, start, end, mode;
|
||||
uint8 *lb, *obj_lut, *ex[2];
|
||||
tms_sprite *p;
|
||||
|
||||
mode = vdp.reg[1] & 3;
|
||||
size = size_tab[mode];
|
||||
|
||||
/* Render sprites */
|
||||
for(i = 0; i < sprites_found; i++)
|
||||
{
|
||||
p = &sprites[i];
|
||||
lb = &linebuf[p->xpos];
|
||||
obj_lut = &tms_obj_lut[(p->attr & 0x0F) << 8];
|
||||
|
||||
/* Point to expanded PG data */
|
||||
ex[0] = bp_expand[p->sg[0]];
|
||||
ex[1] = bp_expand[p->sg[1]];
|
||||
|
||||
/* Clip left edge */
|
||||
if(p->xpos < 0)
|
||||
start = 0 - p->xpos;
|
||||
else
|
||||
start = 0;
|
||||
|
||||
/* Clip right edge */
|
||||
if(p->xpos > 256 - size)
|
||||
end = 256 - p->xpos;
|
||||
else
|
||||
end = size;
|
||||
|
||||
/* Render sprite line */
|
||||
switch(mode)
|
||||
{
|
||||
case 0: /* 8x8 */
|
||||
for(x = start; x < end; x++) {
|
||||
if(ex[0][x])
|
||||
lb[x] = obj_lut[lb[x]];
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* 8x8 zoomed */
|
||||
for(x = start; x < end; x++) {
|
||||
if(ex[0][x >> 1])
|
||||
lb[x] = obj_lut[lb[x]];
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* 16x16 */
|
||||
for(x = start; x < end; x++) {
|
||||
if(ex[(x >> 3) & 1][x & 7])
|
||||
lb[x] = obj_lut[lb[x]];
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* 16x16 zoomed */
|
||||
for(x = start; x < end; x++) {
|
||||
if(ex[(x >> 4) & 1][(x >> 1) & 7])
|
||||
lb[x] = obj_lut[lb[x]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****
|
||||
1.) NOTE: xpos can be negative, but the 'start' value that is added
|
||||
to xpos will ensure it is positive.
|
||||
|
||||
For an EC sprite that is offscreen, 'start' will be larger
|
||||
than 'end' and the for-loop used for rendering will abort
|
||||
on the first pass.
|
||||
***/
|
||||
|
||||
|
||||
#define RENDER_TX_LINE \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ];
|
||||
|
||||
#define RENDER_TX_BORDER \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0]; \
|
||||
*lb++ = 0x10 | clut[0];
|
||||
|
||||
#define RENDER_GR_LINE \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ]; \
|
||||
*lb++ = 0x10 | clut[ *bpex++ ];
|
||||
|
||||
#define RENDER_MC_LINE \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++; \
|
||||
*lb++ = 0x10 | *mcex++;
|
||||
|
||||
void make_tms_tables(void)
|
||||
{
|
||||
int i, j, x;
|
||||
int bd, pg, ct;
|
||||
int sx, bx;
|
||||
|
||||
for(sx = 0; sx < 16; sx++)
|
||||
{
|
||||
for(bx = 0; bx < 256; bx++)
|
||||
{
|
||||
// uint8 bd = (bx & 0x0F);
|
||||
uint8 bs = (bx & 0x40);
|
||||
// uint8 bt = (bd == 0) ? 1 : 0;
|
||||
uint8 sd = (sx & 0x0F);
|
||||
// uint8 st = (sd == 0) ? 1 : 0;
|
||||
|
||||
// opaque sprite pixel, choose 2nd pal and set sprite marker
|
||||
if(sd && !bs)
|
||||
{
|
||||
tms_obj_lut[(sx<<8)|(bx)] = sd | 0x10 | 0x40;
|
||||
}
|
||||
else
|
||||
if(sd && bs)
|
||||
{
|
||||
// writing over a sprite
|
||||
tms_obj_lut[(sx<<8)|(bx)] = bx;
|
||||
}
|
||||
else
|
||||
{
|
||||
tms_obj_lut[(sx<<8)|(bx)] = bx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Text lookup table */
|
||||
for(bd = 0; bd < 256; bd++)
|
||||
{
|
||||
uint8 bg = (bd >> 0) & 0x0F;
|
||||
uint8 fg = (bd >> 4) & 0x0F;
|
||||
|
||||
/* If foreground is transparent, use background color */
|
||||
if(fg == 0) fg = bg;
|
||||
|
||||
txt_lookup[bd][0] = bg;
|
||||
txt_lookup[bd][1] = fg;
|
||||
}
|
||||
|
||||
/* Multicolor lookup table */
|
||||
for(bd = 0; bd < 16; bd++)
|
||||
{
|
||||
for(pg = 0; pg < 256; pg++)
|
||||
{
|
||||
int l = (pg >> 4) & 0x0F;
|
||||
int r = (pg >> 0) & 0x0F;
|
||||
|
||||
/* If foreground is transparent, use background color */
|
||||
if(l == 0) l = bd;
|
||||
if(r == 0) r = bd;
|
||||
|
||||
/* Unpack 2 nibbles across eight pixels */
|
||||
for(x = 0; x < 8; x++)
|
||||
{
|
||||
int c = (x & 4) ? r : l;
|
||||
|
||||
mc_lookup[bd][pg][x] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make bitmap data expansion table */
|
||||
memset(bp_expand, 0, sizeof(bp_expand));
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
for(j = 0; j < 8; j++)
|
||||
{
|
||||
int c = (i >> (j ^ 7)) & 1;
|
||||
bp_expand[i][j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* Graphics I/II lookup table */
|
||||
for(bd = 0; bd < 0x10; bd++)
|
||||
{
|
||||
for(ct = 0; ct < 0x100; ct++)
|
||||
{
|
||||
int backdrop = (bd & 0x0F);
|
||||
int background = (ct >> 0) & 0x0F;
|
||||
int foreground = (ct >> 4) & 0x0F;
|
||||
|
||||
/* If foreground is transparent, use background color */
|
||||
if(background == 0) background = backdrop;
|
||||
if(foreground == 0) foreground = backdrop;
|
||||
|
||||
tms_lookup[bd][ct][0] = background;
|
||||
tms_lookup[bd][ct][1] = foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void render_bg_tms(int line)
|
||||
{
|
||||
switch(vdp.mode & 7)
|
||||
{
|
||||
case 0: /* Graphics I */
|
||||
render_bg_m0(line);
|
||||
break;
|
||||
|
||||
case 1: /* Text */
|
||||
render_bg_m1(line);
|
||||
break;
|
||||
|
||||
case 2: /* Graphics II */
|
||||
render_bg_m2(line);
|
||||
break;
|
||||
|
||||
case 3: /* Text (Extended PG) */
|
||||
render_bg_m1x(line);
|
||||
break;
|
||||
|
||||
case 4: /* Multicolor */
|
||||
render_bg_m3(line);
|
||||
break;
|
||||
|
||||
case 5: /* Invalid (1+3) */
|
||||
render_bg_inv(line);
|
||||
break;
|
||||
|
||||
case 6: /* Multicolor (Extended PG) */
|
||||
render_bg_m3x(line);
|
||||
break;
|
||||
|
||||
case 7: /* Invalid (1+2+3) */
|
||||
render_bg_inv(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Graphics I */
|
||||
void render_bg_m0(int line)
|
||||
{
|
||||
int v_row = (line & 7);
|
||||
int column;
|
||||
int name;
|
||||
|
||||
uint8 *clut;
|
||||
uint8 *bpex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) << 5)];
|
||||
uint8 *ct = &vdp.vram[vdp.ct];
|
||||
uint8 *pg = &vdp.vram[vdp.pg | (v_row)];
|
||||
|
||||
for(column = 0; column < 32; column++)
|
||||
{
|
||||
name = pn[column];
|
||||
clut = &tms_lookup[vdp.bd][ct[name >> 3]][0];
|
||||
bpex = &bp_expand[pg[name << 3]][0];
|
||||
RENDER_GR_LINE
|
||||
}
|
||||
}
|
||||
|
||||
/* Text */
|
||||
void render_bg_m1(int line)
|
||||
{
|
||||
int v_row = (line & 7);
|
||||
int column;
|
||||
|
||||
uint8 *clut;
|
||||
uint8 *bpex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
// uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) * 40)];
|
||||
|
||||
uint8 *pn = &vdp.vram[vdp.pn + text_counter];
|
||||
|
||||
uint8 *pg = &vdp.vram[vdp.pg | (v_row)];
|
||||
uint8 bk = vdp.reg[7];
|
||||
|
||||
clut = &txt_lookup[bk][0];
|
||||
|
||||
for(column = 0; column < 40; column++)
|
||||
{
|
||||
bpex = &bp_expand[pg[pn[column] << 3]][0];
|
||||
RENDER_TX_LINE
|
||||
}
|
||||
|
||||
/* V3 */
|
||||
if((vdp.line & 7) == 7)
|
||||
text_counter += 40;
|
||||
|
||||
RENDER_TX_BORDER
|
||||
}
|
||||
|
||||
/* Text + extended PG */
|
||||
void render_bg_m1x(int line)
|
||||
{
|
||||
int v_row = (line & 7);
|
||||
int column;
|
||||
|
||||
uint8 *clut;
|
||||
uint8 *bpex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) * 40)];
|
||||
uint8 *pg = &vdp.vram[vdp.pg + (v_row) + ((line & 0xC0) << 5)];
|
||||
uint8 bk = vdp.reg[7];
|
||||
|
||||
clut = &tms_lookup[0][bk][0];
|
||||
|
||||
for(column = 0; column < 40; column++)
|
||||
{
|
||||
bpex = &bp_expand[pg[pn[column] << 3]][0];
|
||||
RENDER_TX_LINE
|
||||
}
|
||||
RENDER_TX_BORDER
|
||||
}
|
||||
|
||||
/* Invalid (2+3/1+2+3) */
|
||||
void render_bg_inv(int line)
|
||||
{
|
||||
int column;
|
||||
uint8 *clut;
|
||||
uint8 *bpex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
uint8 bk = vdp.reg[7];
|
||||
|
||||
clut = &txt_lookup[bk][0];
|
||||
|
||||
for(column = 0; column < 40; column++)
|
||||
{
|
||||
bpex = &bp_expand[0xF0][0];
|
||||
RENDER_TX_LINE
|
||||
}
|
||||
}
|
||||
|
||||
/* Multicolor */
|
||||
void render_bg_m3(int line)
|
||||
{
|
||||
int column;
|
||||
uint8 *mcex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
|
||||
uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) << 5)];
|
||||
uint8 *pg = &vdp.vram[vdp.pg + ((line >> 2) & 7)];
|
||||
|
||||
for(column = 0; column < 32; column++)
|
||||
{
|
||||
mcex = &mc_lookup[vdp.bd][pg[pn[column]<<3]][0];
|
||||
RENDER_MC_LINE
|
||||
}
|
||||
}
|
||||
|
||||
/* Multicolor + extended PG */
|
||||
void render_bg_m3x(int line)
|
||||
{
|
||||
int column;
|
||||
uint8 *mcex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) << 5)];
|
||||
uint8 *pg = &vdp.vram[vdp.pg + ((line >> 2) & 7) + ((line & 0xC0) << 5)];
|
||||
|
||||
for(column = 0; column < 32; column++)
|
||||
{
|
||||
mcex = &mc_lookup[vdp.bd][pg[pn[column]<<3]][0];
|
||||
RENDER_MC_LINE
|
||||
}
|
||||
}
|
||||
|
||||
/* Graphics II */
|
||||
void render_bg_m2(int line)
|
||||
{
|
||||
int v_row = (line & 7);
|
||||
int column;
|
||||
int name;
|
||||
|
||||
uint8 *clut;
|
||||
uint8 *bpex;
|
||||
uint8 *lb = &linebuf[0];
|
||||
uint8 *pn = &vdp.vram[vdp.pn | ((line & 0xF8) << 2)];
|
||||
uint8 *ct = &vdp.vram[(vdp.ct & 0x2000) | (v_row) | ((line & 0xC0) << 5)];
|
||||
uint8 *pg = &vdp.vram[(vdp.pg & 0x2000) | (v_row) | ((line & 0xC0) << 5)];
|
||||
|
||||
for(column = 0; column < 32; column++)
|
||||
{
|
||||
name = pn[column] << 3;
|
||||
clut = &tms_lookup[vdp.bd][ct[name]][0];
|
||||
bpex = &bp_expand[pg[name]][0];
|
||||
RENDER_GR_LINE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef _TMS_H_
|
||||
#define _TMS_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
extern int text_counter;
|
||||
|
||||
|
||||
void make_tms_tables(void);
|
||||
void render_bg_tms(int line);
|
||||
void render_bg_m0(int line);
|
||||
void render_bg_m1(int line);
|
||||
void render_bg_m1x(int line);
|
||||
void render_bg_inv(int line);
|
||||
void render_bg_m3(int line);
|
||||
void render_bg_m3x(int line);
|
||||
void render_bg_m2(int line);
|
||||
void render_obj_tms(int line);
|
||||
void parse_line(int line);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _TMS_H_ */
|
|
@ -1,656 +0,0 @@
|
|||
/*
|
||||
vdp.c --
|
||||
Video Display Processor (VDP) emulation.
|
||||
*/
|
||||
#include "shared.h"
|
||||
#include "hvc.inc"
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/* Mark a pattern as dirty */
|
||||
#define MARK_BG_DIRTY(addr) \
|
||||
{ \
|
||||
int name = (addr >> 5) & 0x1FF; \
|
||||
if(bg_name_dirty[name] == 0) \
|
||||
{ \
|
||||
bg_name_list[bg_list_index] = name; \
|
||||
bg_list_index++; \
|
||||
} \
|
||||
bg_name_dirty[name] |= (1 << ((addr >> 2) & 7)); \
|
||||
}
|
||||
|
||||
|
||||
/* VDP context */
|
||||
vdp_t vdp;
|
||||
|
||||
|
||||
/* Initialize VDP emulation */
|
||||
void vdp_init(bool want_quirk)
|
||||
{
|
||||
memset(&vdp, 0, sizeof(vdp_t));
|
||||
|
||||
vdp.lines_per_frame = (sms.display == DISPLAY_NTSC) ? 262 : 313;
|
||||
vdp.quirk_disabled = !want_quirk;
|
||||
|
||||
vdp_reset();
|
||||
}
|
||||
|
||||
void vdp_shutdown(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
|
||||
/* Reset VDP emulation */
|
||||
void vdp_reset(void)
|
||||
{
|
||||
memset(vdp.vram, 0, sizeof(vdp.vram));
|
||||
memset(vdp.cram, 0, sizeof(vdp.cram));
|
||||
memset(vdp.reg, 0, sizeof(vdp.reg));
|
||||
vdp.status = 0;
|
||||
vdp.latch = 0;
|
||||
vdp.pending = 0;
|
||||
vdp.buffer = 0;
|
||||
vdp.code = 0;
|
||||
vdp.addr = 0;
|
||||
|
||||
vdp.pn = 0;
|
||||
vdp.ct = 0;
|
||||
vdp.pg = 0;
|
||||
vdp.sa = 0;
|
||||
vdp.sg = 0;
|
||||
vdp.ntab = 0;
|
||||
vdp.satb = 0;
|
||||
vdp.line = 0;
|
||||
vdp.left = 0;
|
||||
vdp.height = 192;
|
||||
vdp.extended = 0;
|
||||
vdp.mode = 0;
|
||||
vdp.vint_pending = 0;
|
||||
vdp.hint_pending = 0;
|
||||
vdp.hc_latch = 0;
|
||||
vdp.cram_latch = 0;
|
||||
vdp.bd = 0;
|
||||
}
|
||||
|
||||
void vdp_hclatch(void)
|
||||
{
|
||||
unsigned int pixel_pos = ((sms.timestamp % CYCLES_PER_LINE) * 3) >> 1;
|
||||
|
||||
if(pixel_pos >= 0x128)
|
||||
pixel_pos += 0xAA;
|
||||
|
||||
vdp.hc_latch = pixel_pos >> 1;
|
||||
}
|
||||
|
||||
void viewport_check(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
int m1 = (vdp.reg[1] >> 4) & 1;
|
||||
int m3 = (vdp.reg[1] >> 3) & 1;
|
||||
int m2 = (vdp.reg[0] >> 1) & 1;
|
||||
int m4 = (vdp.reg[0] >> 2) & 1;
|
||||
|
||||
vdp.mode = (m4 << 3 | m3 << 2 | m2 << 1 | m1 << 0);
|
||||
|
||||
// check if this is switching out of tms
|
||||
if(!IS_GG)
|
||||
{
|
||||
for(i = 0; i < PALETTE_SIZE; i++)
|
||||
palette_sync(i, 1);
|
||||
}
|
||||
|
||||
/* Check for extended modes when M4 and M2 are set */
|
||||
if((vdp.reg[0] & 0x06) == 0x06)
|
||||
{
|
||||
/* Examine M1 and M3 to determine selected mode */
|
||||
switch(vdp.reg[1] & 0x18)
|
||||
{
|
||||
case 0x00: /* 192 */
|
||||
case 0x18: /* 192 */
|
||||
vdp.height = 192;
|
||||
vdp.extended = 0;
|
||||
vdp.ntab = (vdp.reg[2] << 10) & 0x3800;
|
||||
break;
|
||||
|
||||
case 0x08: /* 240 */
|
||||
vdp.height = 240;
|
||||
vdp.extended = 2;
|
||||
vdp.ntab = ((vdp.reg[2] << 10) & 0x3000) | 0x0700;
|
||||
break;
|
||||
|
||||
case 0x10: /* 224 */
|
||||
vdp.height = 224;
|
||||
vdp.extended = 1;
|
||||
vdp.ntab = ((vdp.reg[2] << 10) & 0x3000) | 0x0700;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vdp.height = 192;
|
||||
vdp.extended = 0;
|
||||
vdp.ntab = (vdp.reg[2] << 10) & 0x3800;
|
||||
}
|
||||
|
||||
vdp.pn = (vdp.reg[2] << 10) & 0x3C00;
|
||||
vdp.ct = (vdp.reg[3] << 6) & 0x3FC0;
|
||||
vdp.pg = (vdp.reg[4] << 11) & 0x3800;
|
||||
vdp.sa = (vdp.reg[5] << 7) & 0x3F80;
|
||||
vdp.sg = (vdp.reg[6] << 11) & 0x3800;
|
||||
|
||||
render_bg = (vdp.mode & 8) ? render_bg_sms : render_bg_tms;
|
||||
render_obj = (vdp.mode & 8) ? render_obj_sms : render_obj_tms;
|
||||
}
|
||||
|
||||
|
||||
void vdp_reg_w(uint8 r, uint8 d)
|
||||
{
|
||||
/* Store register data */
|
||||
vdp.reg[r] = d;
|
||||
|
||||
switch(r)
|
||||
{
|
||||
case 0x00: /* Mode Control No. 1 */
|
||||
if(vdp.hint_pending)
|
||||
{
|
||||
if(d & 0x10)
|
||||
z80_set_interrupt(TRUE);
|
||||
else
|
||||
z80_set_interrupt(FALSE);
|
||||
}
|
||||
viewport_check();
|
||||
break;
|
||||
|
||||
case 0x01: /* Mode Control No. 2 */
|
||||
if(vdp.vint_pending)
|
||||
{
|
||||
if(d & 0x20)
|
||||
z80_set_interrupt(TRUE);
|
||||
else
|
||||
z80_set_interrupt(FALSE);
|
||||
}
|
||||
viewport_check();
|
||||
break;
|
||||
|
||||
case 0x02: /* Name Table A Base Address */
|
||||
vdp.ntab = (vdp.reg[2] << 10) & 0x3800;
|
||||
vdp.pn = (vdp.reg[2] << 10) & 0x3C00;
|
||||
viewport_check();
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
vdp.ct = (vdp.reg[3] << 6) & 0x3FC0;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
vdp.pg = (vdp.reg[4] << 11) & 0x3800;
|
||||
break;
|
||||
|
||||
case 0x05: /* Sprite Attribute Table Base Address */
|
||||
vdp.satb = (vdp.reg[5] << 7) & 0x3F00;
|
||||
vdp.sa = (vdp.reg[5] << 7) & 0x3F80;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
vdp.sg = (vdp.reg[6] << 11) & 0x3800;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
vdp.bd = (vdp.reg[7] & 0x0F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void vdp_write(int offset, uint8 data)
|
||||
{
|
||||
int index;
|
||||
|
||||
switch(offset & 1)
|
||||
{
|
||||
case 0: /* Data port */
|
||||
|
||||
vdp.pending = 0;
|
||||
|
||||
switch(vdp.code)
|
||||
{
|
||||
case 0: /* VRAM write */
|
||||
case 1: /* VRAM write */
|
||||
case 2: /* VRAM write */
|
||||
index = (vdp.addr & 0x3FFF);
|
||||
if(data != vdp.vram[index])
|
||||
{
|
||||
vdp.vram[index] = data;
|
||||
MARK_BG_DIRTY(vdp.addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* CRAM write */
|
||||
index = (vdp.addr & 0x1F);
|
||||
if(data != vdp.cram[index])
|
||||
{
|
||||
vdp.cram[index] = data;
|
||||
palette_sync(index, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
return;
|
||||
|
||||
case 1: /* Control port */
|
||||
if(vdp.pending == 0)
|
||||
{
|
||||
vdp.addr = (vdp.addr & 0x3F00) | (data & 0xFF);
|
||||
vdp.latch = data;
|
||||
vdp.pending = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdp.pending = 0;
|
||||
vdp.code = (data >> 6) & 3;
|
||||
vdp.addr = (data << 8 | vdp.latch) & 0x3FFF;
|
||||
|
||||
if(vdp.code == 0)
|
||||
{
|
||||
vdp.buffer = vdp.vram[vdp.addr & 0x3FFF];
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
}
|
||||
|
||||
if(vdp.code == 2)
|
||||
{
|
||||
int r = (data & 0x0F);
|
||||
int d = vdp.latch;
|
||||
vdp_reg_w(r, d);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 vdp_read(int offset)
|
||||
{
|
||||
uint8 temp;
|
||||
|
||||
switch(offset & 1)
|
||||
{
|
||||
case 0: /* CPU <-> VDP data buffer */
|
||||
vdp.pending = 0;
|
||||
temp = vdp.buffer;
|
||||
vdp.buffer = vdp.vram[vdp.addr & 0x3FFF];
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
return temp;
|
||||
|
||||
case 1: /* Status flags */
|
||||
temp = vdp.status;
|
||||
vdp.pending = 0;
|
||||
vdp.status = 0;
|
||||
vdp.vint_pending = 0;
|
||||
vdp.hint_pending = 0;
|
||||
z80_set_interrupt(FALSE);
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8 vdp_counter_r(int offset)
|
||||
{
|
||||
switch(offset & 1)
|
||||
{
|
||||
case 0: /* V Counter */
|
||||
return vc_table[sms.display][vdp.extended][vdp.line & 0x1FF];
|
||||
|
||||
case 1: /* H Counter */
|
||||
vdp_hclatch(); // FIXME, call from pio.cpp under right conditions instead.
|
||||
return vdp.hc_latch;
|
||||
}
|
||||
|
||||
/* Just to please the compiler */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Game Gear VDP handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void gg_vdp_write(int offset, uint8 data)
|
||||
{
|
||||
int index;
|
||||
|
||||
switch(offset & 1)
|
||||
{
|
||||
case 0: /* Data port */
|
||||
vdp.pending = 0;
|
||||
switch(vdp.code)
|
||||
{
|
||||
case 0: /* VRAM write */
|
||||
case 1: /* VRAM write */
|
||||
case 2: /* VRAM write */
|
||||
index = (vdp.addr & 0x3FFF);
|
||||
if(data != vdp.vram[index])
|
||||
{
|
||||
vdp.vram[index] = data;
|
||||
MARK_BG_DIRTY(vdp.addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* CRAM write */
|
||||
if(vdp.addr & 1)
|
||||
{
|
||||
vdp.cram_latch = (vdp.cram_latch & 0x00FF) | ((data & 0xFF) << 8);
|
||||
vdp.cram[(vdp.addr & 0x3E) | (0)] = (vdp.cram_latch >> 0) & 0xFF;
|
||||
vdp.cram[(vdp.addr & 0x3E) | (1)] = (vdp.cram_latch >> 8) & 0xFF;
|
||||
palette_sync((vdp.addr >> 1) & 0x1F, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vdp.cram_latch = (vdp.cram_latch & 0xFF00) | ((data & 0xFF) << 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
return;
|
||||
|
||||
case 1: /* Control port */
|
||||
if(vdp.pending == 0)
|
||||
{
|
||||
vdp.addr = (vdp.addr & 0x3F00) | (data & 0xFF);
|
||||
vdp.latch = data;
|
||||
vdp.pending = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdp.pending = 0;
|
||||
vdp.code = (data >> 6) & 3;
|
||||
vdp.addr = (data << 8 | vdp.latch) & 0x3FFF;
|
||||
|
||||
if(vdp.code == 0)
|
||||
{
|
||||
vdp.buffer = vdp.vram[vdp.addr & 0x3FFF];
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
}
|
||||
|
||||
if(vdp.code == 2)
|
||||
{
|
||||
int r = (data & 0x0F);
|
||||
int d = vdp.latch;
|
||||
vdp_reg_w(r, d);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MegaDrive / Genesis VDP handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void md_vdp_write(int offset, uint8 data)
|
||||
{
|
||||
int index;
|
||||
|
||||
switch(offset & 1)
|
||||
{
|
||||
case 0: /* Data port */
|
||||
|
||||
vdp.pending = 0;
|
||||
|
||||
switch(vdp.code)
|
||||
{
|
||||
case 0: /* VRAM write */
|
||||
case 1: /* VRAM write */
|
||||
index = (vdp.addr & 0x3FFF);
|
||||
if(data != vdp.vram[index])
|
||||
{
|
||||
vdp.vram[index] = data;
|
||||
MARK_BG_DIRTY(vdp.addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* CRAM write */
|
||||
case 3: /* CRAM write */
|
||||
index = (vdp.addr & 0x1F);
|
||||
if(data != vdp.cram[index])
|
||||
{
|
||||
vdp.cram[index] = data;
|
||||
palette_sync(index, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
return;
|
||||
|
||||
case 1: /* Control port */
|
||||
if(vdp.pending == 0)
|
||||
{
|
||||
vdp.latch = data;
|
||||
vdp.pending = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdp.pending = 0;
|
||||
vdp.code = (data >> 6) & 3;
|
||||
vdp.addr = (data << 8 | vdp.latch) & 0x3FFF;
|
||||
|
||||
if(vdp.code == 0)
|
||||
{
|
||||
vdp.buffer = vdp.vram[vdp.addr & 0x3FFF];
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
}
|
||||
|
||||
if(vdp.code == 2)
|
||||
{
|
||||
int r = (data & 0x0F);
|
||||
int d = vdp.latch;
|
||||
vdp_reg_w(r, d);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* TMS9918 VDP handlers */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void tms_write(int offset, int data)
|
||||
{
|
||||
int index;
|
||||
|
||||
switch(offset & 1)
|
||||
{
|
||||
case 0: /* Data port */
|
||||
|
||||
vdp.pending = 0;
|
||||
|
||||
switch(vdp.code)
|
||||
{
|
||||
case 0: /* VRAM write */
|
||||
case 1: /* VRAM write */
|
||||
case 2: /* VRAM write */
|
||||
case 3: /* VRAM write */
|
||||
index = (vdp.addr & 0x3FFF);
|
||||
if(data != vdp.vram[index])
|
||||
{
|
||||
vdp.vram[index] = data;
|
||||
MARK_BG_DIRTY(vdp.addr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
return;
|
||||
|
||||
case 1: /* Control port */
|
||||
if(vdp.pending == 0)
|
||||
{
|
||||
vdp.latch = data;
|
||||
vdp.pending = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdp.pending = 0;
|
||||
vdp.code = (data >> 6) & 3;
|
||||
vdp.addr = (data << 8 | vdp.latch) & 0x3FFF;
|
||||
|
||||
if(vdp.code == 0)
|
||||
{
|
||||
vdp.buffer = vdp.vram[vdp.addr & 0x3FFF];
|
||||
vdp.addr = (vdp.addr + 1) & 0x3FFF;
|
||||
}
|
||||
|
||||
if(vdp.code == 2)
|
||||
{
|
||||
int r = (data & 0x07);
|
||||
int d = vdp.latch;
|
||||
vdp_reg_w(r, d);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void ExecuteCycles(int32 count)
|
||||
{
|
||||
sms.cycle_counter += count;
|
||||
|
||||
while(sms.cycle_counter > 0)
|
||||
{
|
||||
//printf("PC: %04x\n", z80_getpc());
|
||||
|
||||
int32 temp = z80_do_opcode();
|
||||
sms.timestamp += temp;
|
||||
sms.cycle_counter -= temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SMS_VDPRunFrame(int skip_render)
|
||||
{
|
||||
static const int iline_table[] = {0xC0, 0xE0, 0xF0};
|
||||
int iline;
|
||||
|
||||
text_counter = 0;
|
||||
|
||||
/* End of frame, parse sprites for line 0 on line 261 (VCount=$FF) */
|
||||
if(vdp.mode <= 7)
|
||||
parse_line(0);
|
||||
|
||||
for(vdp.line = 0; vdp.line < vdp.lines_per_frame;)
|
||||
{
|
||||
int moohack = CYCLES_PER_LINE;
|
||||
|
||||
ExecuteCycles(228 - 32);
|
||||
moohack -= 228 - 32;
|
||||
|
||||
iline = iline_table[vdp.extended];
|
||||
|
||||
render_line(vdp.line, skip_render);
|
||||
|
||||
if(vdp.line <= iline)
|
||||
{
|
||||
vdp.left -= 1;
|
||||
if(vdp.left == -1)
|
||||
{
|
||||
vdp.left = vdp.reg[0x0A];
|
||||
vdp.hint_pending = 1;
|
||||
|
||||
ExecuteCycles(16);
|
||||
moohack -= 16;
|
||||
|
||||
if(vdp.reg[0x00] & 0x10)
|
||||
{
|
||||
z80_set_interrupt(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ vdp.left = vdp.reg[0x0A];
|
||||
}
|
||||
|
||||
if(vdp.line == iline)
|
||||
{
|
||||
vdp.status |= 0x80;
|
||||
vdp.vint_pending = 1;
|
||||
|
||||
ExecuteCycles(16);
|
||||
moohack -= 16;
|
||||
if(vdp.reg[0x01] & 0x20)
|
||||
{
|
||||
z80_set_interrupt(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if(moohack)
|
||||
ExecuteCycles(moohack);
|
||||
|
||||
++vdp.line;
|
||||
|
||||
if(vdp.mode <= 7)
|
||||
parse_line(vdp.line);
|
||||
}
|
||||
}
|
||||
|
||||
int SMS_VDPStateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAYN(vdp.vram, 0x4000, "vram"),
|
||||
SFARRAYN(vdp.cram, 0x40, "cram"),
|
||||
SFARRAYN(vdp.reg, 0x10, "reg"),
|
||||
|
||||
SFVARN(vdp.status, "status"),
|
||||
SFVARN(vdp.latch, "latch"),
|
||||
SFVARN(vdp.pending, "pending"),
|
||||
SFVARN(vdp.buffer, "buffer"),
|
||||
SFVARN(vdp.code, "code"),
|
||||
SFVARN(vdp.addr, "addr"),
|
||||
|
||||
SFVARN(vdp.pn, "pn"),
|
||||
SFVARN(vdp.ct, "ct"),
|
||||
SFVARN(vdp.pg, "pg"),
|
||||
SFVARN(vdp.sa, "sa"),
|
||||
SFVARN(vdp.sg, "sg"),
|
||||
SFVARN(vdp.ntab, "ntab"),
|
||||
SFVARN(vdp.satb, "satb"),
|
||||
SFVARN(vdp.line, "line"),
|
||||
SFVARN(vdp.left, "left"),
|
||||
SFVARN(vdp.height, "height"),
|
||||
SFVARN(vdp.extended, "extended"),
|
||||
SFVARN(vdp.mode, "mode"),
|
||||
SFVARN(vdp.vint_pending, "vint_pending"),
|
||||
SFVARN(vdp.hint_pending, "hint_pending"),
|
||||
SFVARN(vdp.hc_latch, "hc_latch"),
|
||||
SFVARN(vdp.cram_latch, "cram_latch"),
|
||||
SFVARN(vdp.bd, "bd"),
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "VDP");
|
||||
|
||||
if(load)
|
||||
{
|
||||
/* Force full pattern cache update */
|
||||
bg_list_index = 0x200;
|
||||
for(int i = 0; i < 0x200; i++)
|
||||
{
|
||||
bg_name_list[i] = i;
|
||||
bg_name_dirty[i] = -1;
|
||||
}
|
||||
|
||||
/* Restore palette */
|
||||
for(int i = 0; i < PALETTE_SIZE; i++)
|
||||
palette_sync(i, 1);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
|
||||
#ifndef _VDP_H_
|
||||
#define _VDP_H_
|
||||
|
||||
namespace MDFN_IEN_SMS
|
||||
{
|
||||
|
||||
/*
|
||||
vdp1
|
||||
|
||||
mode 4 when m4 set and m1 reset
|
||||
|
||||
vdp2
|
||||
|
||||
mode 4 when m4 set and m2,m1 != 1,0
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* Display timing (NTSC) */
|
||||
|
||||
#define MASTER_CLOCK 3579545
|
||||
#define LINES_PER_FRAME 262
|
||||
#define CYCLES_PER_LINE 228
|
||||
|
||||
/* VDP context */
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint8 vram[0x4000];
|
||||
uint16 vram16[0x2000];
|
||||
};
|
||||
|
||||
uint8 cram[0x40];
|
||||
uint8 reg[0x10];
|
||||
uint8 status;
|
||||
uint8 latch;
|
||||
uint8 pending;
|
||||
uint8 buffer;
|
||||
uint8 code;
|
||||
uint16 addr;
|
||||
int pn, ct, pg, sa, sg;
|
||||
int ntab;
|
||||
int satb;
|
||||
int line;
|
||||
int left;
|
||||
uint8 height;
|
||||
uint8 extended;
|
||||
uint8 mode;
|
||||
uint8 vint_pending;
|
||||
uint8 hint_pending;
|
||||
uint8 hc_latch;
|
||||
uint16 cram_latch;
|
||||
uint8 bd;
|
||||
|
||||
int lines_per_frame;
|
||||
int rshift, gshift, bshift;
|
||||
bool quirk_disabled;
|
||||
} vdp_t;
|
||||
|
||||
/* Global data */
|
||||
extern vdp_t vdp;
|
||||
|
||||
/* Function prototypes */
|
||||
void vdp_init(bool want_quirk);
|
||||
void vdp_shutdown(void);
|
||||
void vdp_reset(void);
|
||||
uint8 vdp_counter_r(int offset);
|
||||
uint8 vdp_read(int offset);
|
||||
void vdp_write(int offset, uint8 data);
|
||||
void gg_vdp_write(int offset, uint8 data);
|
||||
void md_vdp_write(int offset, uint8 data);
|
||||
void tms_write(int offset, int data);
|
||||
void vdp_hclatch(void);
|
||||
|
||||
|
||||
void SMS_VDPRunFrame(int skip_render);
|
||||
void SMS_VDPSetPixelFormat(const MDFN_PixelFormat &format);
|
||||
int SMS_VDPStateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _VDP_H_ */
|
||||
|
Loading…
Reference in New Issue