remove pce and sms libmednahawk sources

This commit is contained in:
zeromus 2012-11-05 01:10:48 +00:00
parent 3b533893a8
commit 354e12f290
79 changed files with 0 additions and 20081 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;
}
}
};

View File

@ -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

View File

@ -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;
}
};

View File

@ -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

View File

@ -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");
}
};

View File

@ -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

View File

@ -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));
}
};

View File

@ -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

View File

@ -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());
}
};

View File

@ -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

View File

@ -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());
}
};

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
};

View File

@ -1,12 +0,0 @@
#ifndef __PCE_TSUSHIN_H
#define __PCE_TSUSHIN_H
namespace MDFN_IEN_PCE
{
DECLFR(PCE_TsushinRead);
DECLFW(PCE_TsushinWrite);
};
#endif

View File

@ -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
};

View File

@ -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

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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:

View File

@ -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;
}
}
};

View File

@ -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);
};

View File

@ -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();
}
};

View File

@ -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;
};

View File

@ -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);
}
};

View File

@ -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

View File

@ -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;

View File

@ -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;
}
};

View File

@ -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

View File

@ -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);

View File

@ -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
};

View File

@ -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

View File

@ -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);
}
};

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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)

View File

@ -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_ */

View File

@ -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;
}
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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

View File

@ -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_ */

View File

@ -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;
}
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
};

View File

@ -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_ */

View File

@ -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
}
}
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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_ */