mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-23 08:49:47 +00:00
Update to Mednafen 0.9.26 - psx core
This commit is contained in:
parent
fcf2d96753
commit
d09d20f300
2
Makefile
2
Makefile
@ -140,7 +140,7 @@ WARNINGS := -Wall \
|
||||
-Wno-overflow
|
||||
|
||||
FLAGS += $(ENDIANNESS_DEFINES) -DSIZEOF_DOUBLE=8 $(WARNINGS) \
|
||||
-DMEDNAFEN_VERSION=\"0.9.25\" -DPACKAGE=\"mednafen\" -DMEDNAFEN_VERSION_NUMERIC=925 -DPSS_STYLE=1 -DMPC_FIXED_POINT -DARCH_X86 -DWANT_PSX_EMU -DSTDC_HEADERS -D__STDC_LIMIT_MACROS -D__LIBRETRO__ -DNDEBUG
|
||||
-DMEDNAFEN_VERSION=\"0.9.26\" -DPACKAGE=\"mednafen\" -DMEDNAFEN_VERSION_NUMERIC=926 -DPSS_STYLE=1 -DMPC_FIXED_POINT -DARCH_X86 -DWANT_PSX_EMU -DSTDC_HEADERS -D__STDC_LIMIT_MACROS -D__LIBRETRO__ -DNDEBUG
|
||||
|
||||
CXXFLAGS += $(FLAGS)
|
||||
CFLAGS += $(FLAGS) -std=gnu99
|
||||
|
@ -332,7 +332,7 @@ void retro_get_system_info(struct retro_system_info *info)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->library_name = "Mednafen PSX";
|
||||
info->library_version = "0.9.25";
|
||||
info->library_version = "0.9.26";
|
||||
info->need_fullpath = true;
|
||||
info->valid_extensions = "cue|CUE";
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
DEFS = @DEFS@ @CFLAG_VISIBILITY@
|
||||
|
||||
noinst_LIBRARIES = libmpcdec.a
|
||||
|
||||
libmpcdec_a_SOURCES = huffman.c mpc_decoder.c mpc_reader.c \
|
||||
requant.c streaminfo.c synth_filter.c mpc_bits_reader.c mpc_demux.c \
|
||||
mpc_bits_reader.h huffman.h decoder.h internal.h requant.h mpcdec_math.h \
|
||||
crc32.c huffman-bcl.c
|
||||
|
@ -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/mpcdec
|
||||
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
AUTHORS COPYING ChangeLog
|
||||
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 = @
|
||||
libmpcdec_a_AR = $(AR) $(ARFLAGS)
|
||||
libmpcdec_a_LIBADD =
|
||||
am_libmpcdec_a_OBJECTS = huffman.$(OBJEXT) mpc_decoder.$(OBJEXT) \
|
||||
mpc_reader.$(OBJEXT) requant.$(OBJEXT) streaminfo.$(OBJEXT) \
|
||||
synth_filter.$(OBJEXT) mpc_bits_reader.$(OBJEXT) \
|
||||
mpc_demux.$(OBJEXT) crc32.$(OBJEXT) huffman-bcl.$(OBJEXT)
|
||||
libmpcdec_a_OBJECTS = $(am_libmpcdec_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_lt = $(am__v_lt_$(V))
|
||||
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_lt_0 = --silent
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_$(V))
|
||||
am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_$(V))
|
||||
am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_$(V))
|
||||
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libmpcdec_a_SOURCES)
|
||||
DIST_SOURCES = $(libmpcdec_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 = @DEFS@ @CFLAG_VISIBILITY@
|
||||
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@
|
||||
noinst_LIBRARIES = libmpcdec.a
|
||||
libmpcdec_a_SOURCES = huffman.c mpc_decoder.c mpc_reader.c \
|
||||
requant.c streaminfo.c synth_filter.c mpc_bits_reader.c mpc_demux.c \
|
||||
mpc_bits_reader.h huffman.h decoder.h internal.h requant.h mpcdec_math.h \
|
||||
crc32.c huffman-bcl.c
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .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/mpcdec/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/mpcdec/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)
|
||||
libmpcdec.a: $(libmpcdec_a_OBJECTS) $(libmpcdec_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libmpcdec.a
|
||||
$(AM_V_AR)$(libmpcdec_a_AR) libmpcdec.a $(libmpcdec_a_OBJECTS) $(libmpcdec_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libmpcdec.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc32.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huffman-bcl.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huffman.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpc_bits_reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpc_decoder.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpc_demux.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpc_reader.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/requant.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streaminfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/synth_filter.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -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:
|
3
mednafen/psx-0925/NOTES
Normal file
3
mednafen/psx-0925/NOTES
Normal file
@ -0,0 +1,3 @@
|
||||
Capcom games(MMX4, MMX5, etc) - Sensitive about CD access and XA timing(XA playback problems).
|
||||
|
||||
Viewpoint - Extra-sensitive about GPU LL DMA timing? (It was generating exceptions for some timings...)
|
51
mednafen/psx-0925/PSX-TODO
Normal file
51
mednafen/psx-0925/PSX-TODO
Normal file
@ -0,0 +1,51 @@
|
||||
Soul Reaver - Legacy of Kain has CD load time pauses where it probably shouldn't.
|
||||
|
||||
Battle Arena Toshinden, Final Fantasy 7 have some kind of GPU timing issues.
|
||||
|
||||
Zero Divide runs too fast(related to CPU emulation speed?).
|
||||
|
||||
Chrono Cross has several-second freezes during some large special attack/magic sequences.
|
||||
|
||||
Tiny Toon Adventures - Plucky's Big Adventure is failing and BREAK'ing for some reason, maybe memcard related.
|
||||
|
||||
Shadow Master has broken startup images.
|
||||
|
||||
Crusaders of Might and Magic - The CD-XA buffering increase for ToD II is apparently exacerbating the early voice cutoff problem in this game.
|
||||
|
||||
Crash Team Racing - Noticed a game lockup once in the arcade mode stage select screen, having trouble reproducing it.
|
||||
|
||||
Misadventures of Trone Bonne - Voice problems, lockup, possibly due to excessively long seek delays?
|
||||
|
||||
Dance Dance Revolution - The music is...totally wonky.
|
||||
|
||||
Medal of Honor - Sound issues.
|
||||
|
||||
Fuuraiki - Hangs at black screen when trying to start a new game.
|
||||
|
||||
|
||||
Test time delta between GPU LL DMA end and GPU non-busy status for various primitive types in sequence on a PS1.
|
||||
|
||||
Test IRQ and COP0 latencies; PSX IRQ controller latency, software IRQ bit latency, latency of both relevant COP0 IRQ enable bits.
|
||||
|
||||
Test IRQ with LWC2.
|
||||
|
||||
Test IRQ with COP0 instructions(interrupted execution or not?).
|
||||
|
||||
Determine maximum quad height and width. See if drawing is an all-or-nothing thing, or if one triangle of the pair will still be drawn
|
||||
if it's not too large.
|
||||
|
||||
Test 0x0 and 1x1 polygon throughput for all triangle and quad drawing commands.
|
||||
|
||||
Fix line drawing algorithm to match test results on the real thing.
|
||||
|
||||
Instruction cache emulation(MAYBE).
|
||||
|
||||
|
||||
Test time between voice on and envelope reset; test time between voice on and first ADPCM block memory fetch.
|
||||
|
||||
The SPU in the PS1 might sometimes drop voice on events when playing an ADPCM block that loops to itself(and was also the first and only
|
||||
ADPCM block, at least in the test program I noticed the issue in); investigate further.
|
||||
|
||||
|
||||
|
||||
Make sure debugger COPn disassembly is correct(no typos or whatnot).
|
2
mednafen/psx-0925/README.NOW
Normal file
2
mednafen/psx-0925/README.NOW
Normal file
@ -0,0 +1,2 @@
|
||||
This PSX emulation code is horribly unfinished! Please don't take and use any pieces of it in any other project unless you have
|
||||
a very good reason to!
|
38
mednafen/psx-0925/SOURCES
Normal file
38
mednafen/psx-0925/SOURCES
Normal file
@ -0,0 +1,38 @@
|
||||
Sources of helpful information used in PS1 emulation(though some of it, especially older compiled information,
|
||||
is wrong to some degree or incomplete, but it's still useful):
|
||||
|
||||
PCSX(and derivatives/forks)
|
||||
MAME/MESS
|
||||
P.E.Op.S
|
||||
|
||||
Blade Lib
|
||||
psxsdk
|
||||
|
||||
doomed's PSX documents
|
||||
bITmASTER's document
|
||||
Neill Corlett's SPU documents
|
||||
T.Fujita's SIO documents
|
||||
ChrlyMac
|
||||
Exophase
|
||||
mizvekov
|
||||
notaz
|
||||
pSXAuthor
|
||||
smf(blog)
|
||||
shalma(forum posts, changelogs)
|
||||
drhell's site
|
||||
jac's CD-XA document
|
||||
"The PlayStation 1 Video (STR) Format" - M. Sabin
|
||||
Various PS1 emulator compatibility lists(for identifying problematic games)
|
||||
|
||||
|
||||
MIPS RISC Architecture - Gerry Kane (1st and 2nd editions)
|
||||
MIPS Programmer's Handbook, The
|
||||
|
||||
-----------
|
||||
General(non-PS1-specific) CD/CDROM information and code:
|
||||
|
||||
SCSI-3 Multimedia Commands Revision 10A
|
||||
ECMA-130
|
||||
|
||||
cdrdao
|
||||
dvdisaster
|
2107
mednafen/psx-0925/cdc.cpp
Normal file
2107
mednafen/psx-0925/cdc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
311
mednafen/psx-0925/cdc.h
Normal file
311
mednafen/psx-0925/cdc.h
Normal file
@ -0,0 +1,311 @@
|
||||
#ifndef __MDFN_PSX_CDC_H
|
||||
#define __MDFN_PSX_CDC_H
|
||||
|
||||
#include "../cdrom/cdromif.h"
|
||||
#include "../cdrom/SimpleFIFO.h"
|
||||
#include "../clamp.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
struct CD_Audio_Buffer
|
||||
{
|
||||
int16 Samples[2][0x1000]; // [0][...] = l, [1][...] = r
|
||||
int32 Size;
|
||||
uint32 Freq;
|
||||
};
|
||||
|
||||
class PS_CDC
|
||||
{
|
||||
public:
|
||||
|
||||
PS_CDC();
|
||||
~PS_CDC();
|
||||
|
||||
void SetDisc(bool tray_open, CDIF *cdif, const char disc_id[4]);
|
||||
|
||||
void Power(void);
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
void ResetTS(void);
|
||||
|
||||
int32 CalcNextEvent(void); // Returns in master cycles to next event.
|
||||
|
||||
pscpu_timestamp_t Update(const pscpu_timestamp_t timestamp);
|
||||
|
||||
void Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V);
|
||||
uint8 Read(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
bool DMACanRead(void);
|
||||
uint32 DMARead(void);
|
||||
|
||||
INLINE uint32 GetCDAudioFreq(void)
|
||||
{
|
||||
if(AudioBuffer_UsedCount && !AudioBuffer_InPrebuffer)
|
||||
{
|
||||
const unsigned wb = AudioBuffer_ReadPos >> 12;
|
||||
return AudioBuffer[wb].Freq;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void ApplyVolume(int32 samples[2])
|
||||
{
|
||||
int32 left_source = samples[0]; //(int16)MDFN_de16lsb(&buf[i * sizeof(int16) * 2 + 0]);
|
||||
int32 right_source = samples[1]; //(int16)MDFN_de16lsb(&buf[i * sizeof(int16) * 2 + 2]);
|
||||
int32 left_out = ((left_source * DecodeVolume[0][0]) >> 7) + ((right_source * DecodeVolume[1][0]) >> 7);
|
||||
int32 right_out = ((left_source * DecodeVolume[0][1]) >> 7) + ((right_source * DecodeVolume[1][1]) >> 7);
|
||||
|
||||
clamp(&left_out, -32768, 32767);
|
||||
clamp(&right_out, -32768, 32767);
|
||||
|
||||
if(Muted)
|
||||
{
|
||||
left_out = right_out = 0;
|
||||
}
|
||||
|
||||
samples[0] = left_out;
|
||||
samples[1] = right_out;
|
||||
}
|
||||
public:
|
||||
|
||||
INLINE void GetCDAudio(int32 &l, int32 &r)
|
||||
{
|
||||
if(AudioBuffer_UsedCount && !AudioBuffer_InPrebuffer)
|
||||
{
|
||||
const unsigned wb = AudioBuffer_ReadPos >> 12;
|
||||
int32 samples[2] = { AudioBuffer[wb].Samples[0][AudioBuffer_ReadPos & 0xFFF], AudioBuffer[wb].Samples[1][AudioBuffer_ReadPos & 0xFFF] };
|
||||
|
||||
ApplyVolume(samples);
|
||||
|
||||
l = samples[0];
|
||||
r = samples[1];
|
||||
|
||||
AudioBuffer_ReadPos = ((AudioBuffer_ReadPos + 1) & 0xFFF) | (AudioBuffer_ReadPos & ~0xFFF);
|
||||
|
||||
if((AudioBuffer_ReadPos & 0xFFF) == (AudioBuffer[wb].Size & 0xFFF))
|
||||
{
|
||||
//printf("RP == size; usedcount(predec)= %d, PSRCounter=%d\n", AudioBuffer_UsedCount, PSRCounter);
|
||||
AudioBuffer_ReadPos = ((((AudioBuffer_ReadPos >> 12) + 1) % AudioBuffer_Count) << 12);
|
||||
AudioBuffer_UsedCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void SoftReset(void);
|
||||
|
||||
CDIF *Cur_CDIF;
|
||||
bool DiscChanged;
|
||||
int32 DiscStartupDelay;
|
||||
|
||||
|
||||
enum { AudioBuffer_PreBufferCount = 2 };
|
||||
enum { AudioBuffer_Count = 4 };
|
||||
|
||||
CD_Audio_Buffer AudioBuffer[AudioBuffer_Count];
|
||||
uint32 AudioBuffer_ReadPos;
|
||||
uint32 AudioBuffer_WritePos;
|
||||
uint32 AudioBuffer_UsedCount;
|
||||
bool AudioBuffer_InPrebuffer;
|
||||
|
||||
uint8 Pending_DecodeVolume[2][2], DecodeVolume[2][2]; // [data_source][output_port]
|
||||
|
||||
void ClearAudioBuffers(void);
|
||||
|
||||
uint8 RegSelector;
|
||||
uint8 ArgsBuf[16];
|
||||
uint32 ArgsIn; // 5-bit(0 ... 31)
|
||||
|
||||
uint8 ResultsBuffer[16];
|
||||
uint8 ResultsIn; // 5-bit(0 ... 31)
|
||||
uint8 ResultsWP; // Write position, 4 bit(0 ... 15).
|
||||
uint8 ResultsRP; // Read position, 4 bit(0 ... 15).
|
||||
|
||||
SimpleFIFO<uint8> DMABuffer;
|
||||
uint8 SB[2340];
|
||||
uint32 SB_In;
|
||||
|
||||
|
||||
uint8 SubQBuf[0xC];
|
||||
uint8 SubQBuf_Safe[0xC];
|
||||
bool SubQChecksumOK;
|
||||
|
||||
bool HeaderBufValid;
|
||||
uint8 HeaderBuf[12];
|
||||
|
||||
void RecalcIRQ(void);
|
||||
enum
|
||||
{
|
||||
CDCIRQ_NONE = 0,
|
||||
CDCIRQ_DATA_READY = 1,
|
||||
CDCIRQ_COMPLETE = 2,
|
||||
CDCIRQ_ACKNOWLEDGE = 3,
|
||||
CDCIRQ_DATA_END = 4,
|
||||
CDCIRQ_DISC_ERROR = 5
|
||||
};
|
||||
|
||||
// Names are just guessed for these based on what conditions cause them:
|
||||
enum
|
||||
{
|
||||
ERRCODE_BAD_ARGVAL = 0x10,
|
||||
ERRCODE_BAD_NUMARGS = 0x20,
|
||||
ERRCODE_BAD_COMMAND = 0x40,
|
||||
ERRCODE_NOT_READY = 0x80, // 0x80 (happens with getlocl when drive isn't reading, pause when tray is open, and MAYBE when trying to run an async
|
||||
// command while another async command is currently in its asynch phase being executed[pause when in readtoc, todo test more])
|
||||
};
|
||||
|
||||
uint8 IRQBuffer;
|
||||
uint8 IRQOutTestMask;
|
||||
int32 CDCReadyReceiveCounter; // IRQBuffer being non-zero prevents new results and new IRQ from coming in and erasing the current results,
|
||||
// but apparently at least one CONFOUNDED game is clearing the IRQ state BEFORE reading the results, so we need to have a delay
|
||||
// between IRQBuffer being cleared to when we allow new results to come in. (The real thing should be like this too,
|
||||
// but the mechanism is probably more nuanced and complex and ugly and I like anchovy pizza)
|
||||
|
||||
void BeginResults(void);
|
||||
void WriteIRQ(uint8);
|
||||
void WriteResult(uint8);
|
||||
uint8 ReadResult(void);
|
||||
|
||||
uint8 FilterFile;
|
||||
uint8 FilterChan;
|
||||
|
||||
|
||||
uint8 PendingCommand;
|
||||
bool PendingCommandPhase;
|
||||
int32 PendingCommandCounter;
|
||||
|
||||
int32 SPUCounter;
|
||||
|
||||
enum { MODE_SPEED = 0x80 };
|
||||
enum { MODE_STRSND = 0x40 };
|
||||
enum { MODE_SIZE = 0x20 };
|
||||
enum { MODE_SIZE2 = 0x10 };
|
||||
enum { MODE_SF = 0x08 };
|
||||
enum { MODE_REPORT = 0x04 };
|
||||
enum { MODE_AUTOPAUSE = 0x02 };
|
||||
enum { MODE_CDDA = 0x01 };
|
||||
uint8 Mode;
|
||||
|
||||
enum
|
||||
{
|
||||
DS_STANDBY = -2,
|
||||
DS_PAUSED = -1,
|
||||
DS_STOPPED = 0,
|
||||
DS_SEEKING,
|
||||
DS_SEEKING_LOGICAL,
|
||||
DS_PLAY_SEEKING,
|
||||
DS_PLAYING,
|
||||
DS_READING,
|
||||
DS_RESETTING
|
||||
};
|
||||
int DriveStatus;
|
||||
int StatusAfterSeek;
|
||||
bool Forward;
|
||||
bool Backward;
|
||||
bool Muted;
|
||||
|
||||
int32 PlayTrackMatch;
|
||||
|
||||
int32 PSRCounter;
|
||||
|
||||
int32 CurSector;
|
||||
|
||||
unsigned AsyncIRQPending;
|
||||
uint8 AsyncResultsPending[16];
|
||||
uint8 AsyncResultsPendingCount;
|
||||
|
||||
int32 CalcSeekTime(int32 initial, int32 target, bool motor_on, bool paused);
|
||||
|
||||
void ClearAIP(void);
|
||||
void CheckAIP(void);
|
||||
void SetAIP(unsigned irq, unsigned result_count, uint8 *r);
|
||||
void SetAIP(unsigned irq, uint8 result0);
|
||||
void SetAIP(unsigned irq, uint8 result0, uint8 result1);
|
||||
|
||||
int32 SeekTarget;
|
||||
|
||||
pscpu_timestamp_t lastts;
|
||||
|
||||
CDUtility::TOC toc;
|
||||
bool IsPSXDisc;
|
||||
uint8 DiscID[4];
|
||||
|
||||
int32 CommandLoc;
|
||||
bool CommandLoc_Dirty;
|
||||
|
||||
uint8 MakeStatus(bool cmd_error = false);
|
||||
bool DecodeSubQ(uint8 *subpw);
|
||||
bool CommandCheckDiscPresent(void);
|
||||
|
||||
bool XA_Test(const uint8 *sdata);
|
||||
void XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab);
|
||||
int16 xa_previous[2][2];
|
||||
bool xa_cur_set;
|
||||
uint8 xa_cur_file;
|
||||
uint8 xa_cur_chan;
|
||||
|
||||
struct CDC_CTEntry
|
||||
{
|
||||
uint8 args_min;
|
||||
uint8 args_max;
|
||||
const char *name;
|
||||
int32 (PS_CDC::*func)(const int arg_count, const uint8 *args);
|
||||
int32 (PS_CDC::*func2)(void);
|
||||
};
|
||||
|
||||
void BeginSeek(uint32 target);
|
||||
void PreSeekHack(uint32 target);
|
||||
void ReadBase(void);
|
||||
|
||||
static CDC_CTEntry Commands[0x20];
|
||||
|
||||
int32 Command_Sync(const int arg_count, const uint8 *args);
|
||||
int32 Command_Nop(const int arg_count, const uint8 *args);
|
||||
int32 Command_Setloc(const int arg_count, const uint8 *args);
|
||||
int32 Command_Play(const int arg_count, const uint8 *args);
|
||||
int32 Command_Forward(const int arg_count, const uint8 *args);
|
||||
int32 Command_Backward(const int arg_count, const uint8 *args);
|
||||
int32 Command_ReadN(const int arg_count, const uint8 *args);
|
||||
int32 Command_Standby(const int arg_count, const uint8 *args);
|
||||
int32 Command_Standby_Part2(void);
|
||||
int32 Command_Stop(const int arg_count, const uint8 *args);
|
||||
int32 Command_Stop_Part2(void);
|
||||
int32 Command_Pause(const int arg_count, const uint8 *args);
|
||||
int32 Command_Pause_Part2(void);
|
||||
int32 Command_Reset(const int arg_count, const uint8 *args);
|
||||
int32 Command_Mute(const int arg_count, const uint8 *args);
|
||||
int32 Command_Demute(const int arg_count, const uint8 *args);
|
||||
int32 Command_Setfilter(const int arg_count, const uint8 *args);
|
||||
int32 Command_Setmode(const int arg_count, const uint8 *args);
|
||||
int32 Command_Getparam(const int arg_count, const uint8 *args);
|
||||
int32 Command_GetlocL(const int arg_count, const uint8 *args);
|
||||
int32 Command_GetlocP(const int arg_count, const uint8 *args);
|
||||
|
||||
int32 Command_ReadT(const int arg_count, const uint8 *args);
|
||||
int32 Command_ReadT_Part2(void);
|
||||
|
||||
int32 Command_GetTN(const int arg_count, const uint8 *args);
|
||||
int32 Command_GetTD(const int arg_count, const uint8 *args);
|
||||
int32 Command_SeekL(const int arg_count, const uint8 *args);
|
||||
int32 Command_SeekP(const int arg_count, const uint8 *args);
|
||||
int32 Command_Seek_PartN(void);
|
||||
|
||||
int32 Command_Test(const int arg_count, const uint8 *args);
|
||||
|
||||
int32 Command_ID(const int arg_count, const uint8 *args);
|
||||
int32 Command_ID_Part2(void);
|
||||
|
||||
int32 Command_ReadS(const int arg_count, const uint8 *args);
|
||||
int32 Command_Init(const int arg_count, const uint8 *args);
|
||||
|
||||
int32 Command_ReadTOC(const int arg_count, const uint8 *args);
|
||||
int32 Command_ReadTOC_Part2(void);
|
||||
|
||||
int32 Command_0x1d(const int arg_count, const uint8 *args);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
1942
mednafen/psx-0925/cpu.cpp
Normal file
1942
mednafen/psx-0925/cpu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
167
mednafen/psx-0925/cpu.h
Normal file
167
mednafen/psx-0925/cpu.h
Normal file
@ -0,0 +1,167 @@
|
||||
#ifndef __MDFN_PSX_CPU_H
|
||||
#define __MDFN_PSX_CPU_H
|
||||
|
||||
#include "gte.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class PS_CPU
|
||||
{
|
||||
public:
|
||||
|
||||
PS_CPU();
|
||||
~PS_CPU();
|
||||
|
||||
// FAST_MAP_* enums are in BYTES(8-bit), not in 32-bit units("words" in MIPS context), but the sizes
|
||||
// will always be multiples of 4.
|
||||
enum { FAST_MAP_SHIFT = 16 };
|
||||
enum { FAST_MAP_PSIZE = 1 << FAST_MAP_SHIFT };
|
||||
|
||||
void SetFastMap(void *region_mem, uint32 region_address, uint32 region_size);
|
||||
|
||||
INLINE void SetEventNT(const pscpu_timestamp_t next_event_ts_arg)
|
||||
{
|
||||
next_event_ts = next_event_ts_arg;
|
||||
}
|
||||
|
||||
pscpu_timestamp_t Run(pscpu_timestamp_t timestamp_in, bool ILHMode);
|
||||
|
||||
void Power(void);
|
||||
|
||||
// which ranges 0-5, inclusive
|
||||
void AssertIRQ(int which, bool asserted);
|
||||
|
||||
void SetHalt(bool status);
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
private:
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 GPR[32];
|
||||
uint32 GPR_dummy; // Used in load delay simulation(indexing past the end of GPR)
|
||||
};
|
||||
uint32 LO;
|
||||
uint32 HI;
|
||||
|
||||
|
||||
uint32 BACKED_PC;
|
||||
uint32 BACKED_new_PC;
|
||||
uint32 BACKED_new_PC_mask;
|
||||
|
||||
uint32 IPCache;
|
||||
void RecalcIPCache(void);
|
||||
bool Halted;
|
||||
|
||||
uint32 BACKED_LDWhich;
|
||||
uint32 BACKED_LDValue;
|
||||
|
||||
pscpu_timestamp_t next_event_ts;
|
||||
pscpu_timestamp_t gte_ts_done;
|
||||
|
||||
uint8 *FastMap[1 << (32 - FAST_MAP_SHIFT)];
|
||||
uint8 DummyPage[FAST_MAP_PSIZE];
|
||||
|
||||
enum
|
||||
{
|
||||
CP0REG_BPC = 3, // PC breakpoint address.
|
||||
CP0REG_BDA = 5, // Data load/store breakpoint address.
|
||||
CP0REG_TAR = 6, // Target address(???)
|
||||
CP0REG_DCIC = 7, // Cache control
|
||||
CP0REG_BDAM = 9, // Data load/store address mask.
|
||||
CP0REG_BPCM = 11, // PC breakpoint address mask.
|
||||
CP0REG_SR = 12,
|
||||
CP0REG_CAUSE = 13,
|
||||
CP0REG_EPC = 14,
|
||||
CP0REG_PRID = 15, // Product ID
|
||||
CP0REG_ERREG = 16
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32 Regs[32];
|
||||
struct
|
||||
{
|
||||
uint32 Unused00;
|
||||
uint32 Unused01;
|
||||
uint32 Unused02;
|
||||
uint32 BPC; // RW
|
||||
uint32 Unused04;
|
||||
uint32 BDA; // RW
|
||||
uint32 TAR;
|
||||
uint32 DCIC; // RW
|
||||
uint32 Unused08;
|
||||
uint32 BDAM; // R/W
|
||||
uint32 Unused0A;
|
||||
uint32 BPCM; // R/W
|
||||
uint32 SR; // R/W
|
||||
uint32 CAUSE; // R/W(partial)
|
||||
uint32 EPC; // R
|
||||
uint32 PRID; // R
|
||||
uint32 ERREG; // ?(may not exist, test)
|
||||
};
|
||||
};
|
||||
} CP0;
|
||||
|
||||
//PS_GTE GTE;
|
||||
|
||||
enum
|
||||
{
|
||||
EXCEPTION_INT = 0,
|
||||
EXCEPTION_MOD = 1,
|
||||
EXCEPTION_TLBL = 2,
|
||||
EXCEPTION_TLBS = 3,
|
||||
EXCEPTION_ADEL = 4, // Address error on load
|
||||
EXCEPTION_ADES = 5, // Address error on store
|
||||
EXCEPTION_IBE = 6, // Instruction bus error
|
||||
EXCEPTION_DBE = 7, // Data bus error
|
||||
EXCEPTION_SYSCALL = 8, // System call
|
||||
EXCEPTION_BP = 9, // Breakpoint
|
||||
EXCEPTION_RI = 10, // Reserved instruction
|
||||
EXCEPTION_COPU = 11, // Coprocessor unusable
|
||||
EXCEPTION_OV = 12 // Arithmetic overflow
|
||||
};
|
||||
|
||||
uint32 Exception(uint32 code, uint32 PC, const uint32 NPM) MDFN_WARN_UNUSED_RESULT;
|
||||
|
||||
template<bool DebugMode, bool ILHMode> pscpu_timestamp_t RunReal(pscpu_timestamp_t timestamp_in);
|
||||
|
||||
template<typename T> T ReadMemory(pscpu_timestamp_t ×tamp, uint32 address, bool DS24 = false);
|
||||
template<typename T> void WriteMemory(pscpu_timestamp_t ×tamp, uint32 address, uint32 value, bool DS24 = false);
|
||||
|
||||
|
||||
//
|
||||
// Mednafen debugger stuff follows:
|
||||
//
|
||||
public:
|
||||
void SetCPUHook(void (*cpuh)(uint32 pc), void (*addbt)(uint32 from, uint32 to, bool exception));
|
||||
void CheckBreakpoints(void (*callback)(bool write, uint32 address, unsigned int len), uint32 instr);
|
||||
|
||||
enum
|
||||
{
|
||||
GSREG_GPR = 0,
|
||||
GSREG_PC = 32,
|
||||
GSREG_PC_NEXT,
|
||||
GSREG_IN_BD_SLOT,
|
||||
GSREG_LO,
|
||||
GSREG_HI,
|
||||
GSREG_SR,
|
||||
GSREG_CAUSE,
|
||||
GSREG_EPC,
|
||||
};
|
||||
|
||||
uint32 GetRegister(unsigned int which, char *special, const uint32 special_len);
|
||||
void SetRegister(unsigned int which, uint32 value);
|
||||
|
||||
private:
|
||||
void (*CPUHook)(uint32 pc);
|
||||
void (*ADDBT)(uint32 from, uint32 to, bool exception);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
669
mednafen/psx-0925/debug.cpp
Normal file
669
mednafen/psx-0925/debug.cpp
Normal file
@ -0,0 +1,669 @@
|
||||
/* 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 "psx.h"
|
||||
#include "timer.h"
|
||||
#include "cdc.h"
|
||||
#include "spu.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
extern PS_GPU *GPU;
|
||||
extern PS_SPU *SPU;
|
||||
|
||||
static void (*CPUHook)(uint32) = NULL;
|
||||
static void (*BPCallB)(uint32 PC) = NULL;
|
||||
|
||||
struct PSX_BPOINT
|
||||
{
|
||||
uint32 A[2];
|
||||
int type;
|
||||
};
|
||||
|
||||
static std::vector<PSX_BPOINT> BreakPointsPC, BreakPointsRead, BreakPointsWrite;
|
||||
static bool FoundBPoint;
|
||||
|
||||
static int BTIndex = 0;
|
||||
|
||||
struct BTEntry
|
||||
{
|
||||
uint32 from;
|
||||
uint32 to;
|
||||
uint32 branch_count;
|
||||
bool exception;
|
||||
};
|
||||
|
||||
#define NUMBT 24
|
||||
static BTEntry BTEntries[NUMBT];
|
||||
|
||||
void DBG_Break(void)
|
||||
{
|
||||
FoundBPoint = true;
|
||||
}
|
||||
|
||||
static void AddBranchTrace(uint32 from, uint32 to, bool exception)
|
||||
{
|
||||
BTEntry *prevbt = &BTEntries[(BTIndex + NUMBT - 1) % NUMBT];
|
||||
|
||||
//if(BTEntries[(BTIndex - 1) & 0xF] == PC) return;
|
||||
|
||||
if(prevbt->from == from && prevbt->to == to && prevbt->exception == exception && prevbt->branch_count < 0xFFFFFFFF)
|
||||
prevbt->branch_count++;
|
||||
else
|
||||
{
|
||||
BTEntries[BTIndex].from = from;
|
||||
BTEntries[BTIndex].to = to;
|
||||
BTEntries[BTIndex].exception = exception;
|
||||
BTEntries[BTIndex].branch_count = 1;
|
||||
|
||||
BTIndex = (BTIndex + 1) % NUMBT;
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<BranchTraceResult> GetBranchTrace(void)
|
||||
{
|
||||
BranchTraceResult tmp;
|
||||
std::vector<BranchTraceResult> ret;
|
||||
|
||||
for(int x = 0; x < NUMBT; x++)
|
||||
{
|
||||
const BTEntry *bt = &BTEntries[(x + BTIndex) % NUMBT];
|
||||
|
||||
tmp.count = bt->branch_count;
|
||||
trio_snprintf(tmp.from, sizeof(tmp.from), "%08x", bt->from);
|
||||
trio_snprintf(tmp.to, sizeof(tmp.to), "%08x", bt->to);
|
||||
trio_snprintf(tmp.code, sizeof(tmp.code), "%s", bt->exception ? "e" : "");
|
||||
|
||||
ret.push_back(tmp);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void CheckCPUBPCallB(bool write, uint32 address, unsigned int len)
|
||||
{
|
||||
std::vector<PSX_BPOINT>::iterator bpit;
|
||||
std::vector<PSX_BPOINT>::iterator bpit_end;
|
||||
|
||||
if(write)
|
||||
{
|
||||
bpit = BreakPointsWrite.begin();
|
||||
bpit_end = BreakPointsWrite.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
bpit = BreakPointsRead.begin();
|
||||
bpit_end = BreakPointsRead.end();
|
||||
}
|
||||
|
||||
while(bpit != bpit_end)
|
||||
{
|
||||
if(address >= bpit->A[0] && address <= bpit->A[1])
|
||||
{
|
||||
FoundBPoint = true;
|
||||
break;
|
||||
}
|
||||
bpit++;
|
||||
}
|
||||
}
|
||||
|
||||
static void CPUHandler(uint32 PC)
|
||||
{
|
||||
std::vector<PSX_BPOINT>::iterator bpit;
|
||||
|
||||
if(PC == 0xB0 && CPU->GetRegister(PS_CPU::GSREG_GPR + 9, NULL, 0) == 0x3D)
|
||||
{
|
||||
putchar(CPU->GetRegister(PS_CPU::GSREG_GPR + 4, NULL, 0));
|
||||
//exit(1);
|
||||
//puts((const char *)&MainRAM[CPU->GetRegister(PS_CPU::GSREG_GPR + 4, NULL, 0) & 0x1FFFFF]);
|
||||
}
|
||||
|
||||
|
||||
// FIXME/TODO: Call ForceEventUpdates() somewhere
|
||||
|
||||
for(bpit = BreakPointsPC.begin(); bpit != BreakPointsPC.end(); bpit++)
|
||||
{
|
||||
if(PC >= bpit->A[0] && PC <= bpit->A[1])
|
||||
{
|
||||
FoundBPoint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CPU->CheckBreakpoints(CheckCPUBPCallB, PSX_MemPeek32(PC));
|
||||
|
||||
if(FoundBPoint)
|
||||
{
|
||||
BPCallB(PC);
|
||||
FoundBPoint = 0;
|
||||
}
|
||||
|
||||
if(CPUHook)
|
||||
CPUHook(PC);
|
||||
}
|
||||
|
||||
|
||||
static void RedoCPUHook(void)
|
||||
{
|
||||
const bool HappyTest = BreakPointsPC.size() || BreakPointsRead.size() || BreakPointsWrite.size();
|
||||
void (*cpuh)(uint32);
|
||||
|
||||
cpuh = HappyTest ? CPUHandler : CPUHook;
|
||||
|
||||
CPU->SetCPUHook(cpuh, cpuh ? AddBranchTrace : NULL);
|
||||
}
|
||||
|
||||
static void FlushBreakPoints(int type)
|
||||
{
|
||||
if(type == BPOINT_READ)
|
||||
BreakPointsRead.clear();
|
||||
else if(type == BPOINT_WRITE)
|
||||
BreakPointsWrite.clear();
|
||||
else if(type == BPOINT_PC)
|
||||
BreakPointsPC.clear();
|
||||
|
||||
RedoCPUHook();
|
||||
}
|
||||
|
||||
static void AddBreakPoint(int type, unsigned int A1, unsigned int A2, bool logical)
|
||||
{
|
||||
PSX_BPOINT tmp;
|
||||
|
||||
tmp.A[0] = A1;
|
||||
tmp.A[1] = A2;
|
||||
tmp.type = type;
|
||||
|
||||
if(type == BPOINT_READ)
|
||||
BreakPointsRead.push_back(tmp);
|
||||
else if(type == BPOINT_WRITE)
|
||||
BreakPointsWrite.push_back(tmp);
|
||||
else if(type == BPOINT_PC)
|
||||
BreakPointsPC.push_back(tmp);
|
||||
|
||||
RedoCPUHook();
|
||||
}
|
||||
|
||||
static void SetCPUCallback(void (*callb)(uint32 PC))
|
||||
{
|
||||
CPUHook = callb;
|
||||
RedoCPUHook();
|
||||
}
|
||||
|
||||
static void SetBPCallback(void (*callb)(uint32 PC))
|
||||
{
|
||||
BPCallB = callb;
|
||||
}
|
||||
|
||||
|
||||
static void GetAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint8 *Buffer)
|
||||
{
|
||||
if(!strcmp(name, "cpu"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0xFFFFFFFF;
|
||||
*Buffer = PSX_MemPeek8(Address);
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(name, "ram"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0x1FFFFF;
|
||||
*Buffer = PSX_MemPeek8(Address);
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(name, "spu"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0x7FFFF;
|
||||
*Buffer = SPU->PeekSPURAM(Address >> 1) >> ((Address & 1) * 8);
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(name, "gpu"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0xFFFFF;
|
||||
*Buffer = GPU->PeekRAM(Address >> 1) >> ((Address & 1) * 8);
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void PutAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer)
|
||||
{
|
||||
if(!strcmp(name, "cpu"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0xFFFFFFFF;
|
||||
|
||||
// TODO
|
||||
PSX_MemWrite8(0, Address, *Buffer);
|
||||
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(name, "gpu"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0xFFFFF;
|
||||
|
||||
uint16 peeko = GPU->PeekRAM(Address >> 1);
|
||||
|
||||
GPU->PokeRAM(Address >> 1, (*Buffer << ((Address & 1) * 8)) | (peeko & (0xFF00 >> ((Address & 1) * 8))) );
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(name, "spu"))
|
||||
{
|
||||
while(Length--)
|
||||
{
|
||||
Address &= 0x7FFFF;
|
||||
|
||||
uint16 peeko = SPU->PeekSPURAM(Address >> 1);
|
||||
|
||||
SPU->PokeSPURAM(Address >> 1, (*Buffer << ((Address & 1) * 8)) | (peeko & (0xFF00 >> ((Address & 1) * 8))) );
|
||||
Address++;
|
||||
Buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static uint32 MemPeek(uint32 A, unsigned int bsize, bool hl, bool logical)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
for(unsigned int i = 0; i < bsize; i++)
|
||||
ret |= PSX_MemPeek8(A + i) << (i * 8);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void Disassemble(uint32 &A, uint32 SpecialA, char *TextBuf)
|
||||
{
|
||||
assert(!(A & 0x3));
|
||||
|
||||
const uint32 instr = PSX_MemPeek32(A);
|
||||
|
||||
|
||||
strncpy(TextBuf, DisassembleMIPS(A, instr).c_str(), 256);
|
||||
TextBuf[255] = 0;
|
||||
|
||||
// trio_snprintf(TextBuf, 256, "0x%08x", instr);
|
||||
|
||||
A += 4;
|
||||
}
|
||||
|
||||
static MDFN_Surface *GfxDecode_Buf = NULL;
|
||||
static int GfxDecode_Line = -1;
|
||||
static int GfxDecode_Layer = 0;
|
||||
static int GfxDecode_Scroll = 0;
|
||||
static int GfxDecode_PBN = 0;
|
||||
|
||||
static void DoGfxDecode(void)
|
||||
{
|
||||
unsigned tp_w, tp_h;
|
||||
|
||||
tp_w = 256;
|
||||
tp_h = 256;
|
||||
|
||||
if(GfxDecode_Buf)
|
||||
{
|
||||
for(int sy = 0; sy < GfxDecode_Buf->h; sy++)
|
||||
{
|
||||
for(int sx = 0; sx < GfxDecode_Buf->w; sx++)
|
||||
{
|
||||
unsigned fb_x = ((sx % GfxDecode_Buf->w) + ((sy + GfxDecode_Scroll) / GfxDecode_Buf->w * GfxDecode_Buf->w)) & 1023;
|
||||
unsigned fb_y = (((sy + GfxDecode_Scroll) % GfxDecode_Buf->w) + ((((sx % GfxDecode_Buf->w) + ((sy + GfxDecode_Scroll) / GfxDecode_Buf->w * GfxDecode_Buf->w)) / 1024) * 256)) & 511;
|
||||
|
||||
uint16 pixel = GPU->PeekRAM(fb_y * 1024 + fb_x);
|
||||
|
||||
GfxDecode_Buf->pixels[(sy * GfxDecode_Buf->w * 3) + sx] = GfxDecode_Buf->MakeColor(((pixel >> 0) & 0x1F) * 255 / 31,
|
||||
((pixel >> 5) & 0x1F) * 255 / 31,
|
||||
((pixel >> 10) & 0x1F) * 255 / 31, 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DBG_GPUScanlineHook(unsigned scanline)
|
||||
{
|
||||
if((int)scanline == GfxDecode_Line)
|
||||
{
|
||||
DoGfxDecode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void 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();
|
||||
}
|
||||
|
||||
DebuggerInfoStruct PSX_DBGInfo =
|
||||
{
|
||||
"shift_jis",
|
||||
4, // Max instruction byte size
|
||||
4, // Instruction alignment(bytes)
|
||||
32, // Logical address bits
|
||||
32, // Physical address bits
|
||||
0x00000000, // Default watch addr
|
||||
~0U, // ZP addr
|
||||
|
||||
MemPeek,
|
||||
Disassemble,
|
||||
NULL,
|
||||
NULL, //ForceIRQ,
|
||||
NULL, //NESDBG_GetVector,
|
||||
FlushBreakPoints,
|
||||
AddBreakPoint,
|
||||
SetCPUCallback,
|
||||
SetBPCallback,
|
||||
GetBranchTrace,
|
||||
SetGraphicsDecode,
|
||||
NULL, //PCFXDBG_SetLogFunc,
|
||||
};
|
||||
|
||||
static RegType Regs_Misc[] =
|
||||
{
|
||||
{ TIMER_GSREG_COUNTER0, "COUNTER0", "Counter 0", 2 },
|
||||
{ TIMER_GSREG_MODE0, "MODE0", "Mode 0", 2 },
|
||||
{ TIMER_GSREG_TARGET0, "TARGET0", "Target 0", 2 },
|
||||
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
|
||||
|
||||
{ TIMER_GSREG_COUNTER1, "COUNTER1", "Counter 1", 2 },
|
||||
{ TIMER_GSREG_MODE1, "MODE1", "Mode 1", 2 },
|
||||
{ TIMER_GSREG_TARGET1, "TARGET1", "Target 1", 2 },
|
||||
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
|
||||
{ TIMER_GSREG_COUNTER2, "COUNTER2", "Counter 2", 2 },
|
||||
{ TIMER_GSREG_MODE2, "MODE2", "Mode 2", 2 },
|
||||
{ TIMER_GSREG_TARGET2, "TARGET2", "Target 2", 2 },
|
||||
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
|
||||
{ 0x10000 | IRQ_GSREG_ASSERTED, "ASSERTED", "IRQ Asserted", 2 },
|
||||
{ 0x10000 | IRQ_GSREG_STATUS, "STATUS", "IRQ Status", 2 },
|
||||
{ 0x10000 | IRQ_GSREG_MASK, "MASK", "IRQ Mask", 2 },
|
||||
|
||||
{ 0, "", "", 0 }
|
||||
};
|
||||
|
||||
|
||||
static uint32 GetRegister_Misc(const unsigned int id, char *special, const uint32 special_len)
|
||||
{
|
||||
if(id & 0x10000)
|
||||
return(IRQ_GetRegister(id & 0xFFFF, special, special_len));
|
||||
else
|
||||
return(TIMER_GetRegister(id & 0xFFFF, special, special_len));
|
||||
}
|
||||
|
||||
static void SetRegister_Misc(const unsigned int id, uint32 value)
|
||||
{
|
||||
if(id & 0x10000)
|
||||
IRQ_SetRegister(id & 0xFFFF, value);
|
||||
else
|
||||
TIMER_SetRegister(id & 0xFFFF, value);
|
||||
}
|
||||
|
||||
static RegGroupType MiscRegsGroup =
|
||||
{
|
||||
NULL,
|
||||
Regs_Misc,
|
||||
GetRegister_Misc,
|
||||
SetRegister_Misc
|
||||
};
|
||||
|
||||
static RegType Regs_SPU[] =
|
||||
{
|
||||
{ PS_SPU::GSREG_SPUCONTROL, "SPUCTRL", "SPU Control", 2 },
|
||||
|
||||
{ PS_SPU::GSREG_FM_ON, "FMOn", "FM Enable", 3 },
|
||||
{ PS_SPU::GSREG_NOISE_ON, "NoiseOn", "Noise Enable", 3 },
|
||||
{ PS_SPU::GSREG_REVERB_ON, "ReverbOn", "Reverb Enable", 3 },
|
||||
|
||||
{ PS_SPU::GSREG_CDVOL_L, "CDVolL", "CD Volume Left", 2 },
|
||||
{ PS_SPU::GSREG_CDVOL_R, "CDVolR", "CD Volume Right", 2 },
|
||||
|
||||
{ PS_SPU::GSREG_DRYVOL_CTRL_L, "DryVolCL", "Dry Volume Control Left", 2 },
|
||||
{ PS_SPU::GSREG_DRYVOL_CTRL_R, "DryVolCR", "Dry Volume Control Right", 2 },
|
||||
|
||||
{ PS_SPU::GSREG_DRYVOL_L, "DryVolL", "Dry Volume Left", 2 },
|
||||
{ PS_SPU::GSREG_DRYVOL_R, "DryVolR", "Dry Volume Right", 2 },
|
||||
|
||||
{ PS_SPU::GSREG_WETVOL_L, "WetVolL", "Wet Volume Left", 2 },
|
||||
{ PS_SPU::GSREG_WETVOL_R, "WetVolR", "Wet Volume Right", 2 },
|
||||
|
||||
{ PS_SPU::GSREG_RWADDR, "RWAddr", "SPURAM Read/Write Address", 3 },
|
||||
|
||||
{ PS_SPU::GSREG_IRQADDR, "IRQAddr", "IRQ Compare Address", 3 },
|
||||
|
||||
{ PS_SPU::GSREG_REVERBWA, "ReverbWA", "Reverb Work Area(Raw)", 2 },
|
||||
|
||||
{ PS_SPU::GSREG_VOICEON, "VoiceOn", "Voice On", 3 },
|
||||
{ PS_SPU::GSREG_VOICEOFF, "VoiceOff", "Voice Off", 3 },
|
||||
{ PS_SPU::GSREG_BLOCKEND, "BlockEnd", "Block End", 3 },
|
||||
|
||||
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
|
||||
{ PS_SPU::GSREG_FB_SRC_A, "FB_SRC_A", "", 2 },
|
||||
{ PS_SPU::GSREG_FB_SRC_B, "FB_SRC_B", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_ALPHA, "IIR_ALPHA", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_COEF_A, "ACC_COEF_A", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_COEF_B, "ACC_COEF_B", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_COEF_C, "ACC_COEF_C", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_COEF_D, "ACC_COEF_D", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_COEF, "IIR_COEF", "", 2 },
|
||||
{ PS_SPU::GSREG_FB_ALPHA, "FB_ALPHA", "", 2 },
|
||||
{ PS_SPU::GSREG_FB_X, "FB_X", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_DEST_A0, "IIR_DEST_A0", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_DEST_A1, "IIR_DEST_A1", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_A0, "ACC_SRC_A0", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_A1, "ACC_SRC_A1", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_B0, "ACC_SRC_B0", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_B1, "ACC_SRC_B1", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_SRC_A0, "IIR_SRC_A0", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_SRC_A1, "IIR_SRC_A1", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_DEST_B0, "IIR_DEST_B0", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_DEST_B1, "IIR_DEST_B1", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_C0, "ACC_SRC_C0", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_C1, "ACC_SRC_C1", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_D0, "ACC_SRC_D0", "", 2 },
|
||||
{ PS_SPU::GSREG_ACC_SRC_D1, "ACC_SRC_D1", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_SRC_B1, "IIR_SRC_B1", "", 2 },
|
||||
{ PS_SPU::GSREG_IIR_SRC_B0, "IIR_SRC_B0", "", 2 },
|
||||
{ PS_SPU::GSREG_MIX_DEST_A0, "MIX_DEST_A0", "", 2 },
|
||||
{ PS_SPU::GSREG_MIX_DEST_A1, "MIX_DEST_A1", "", 2 },
|
||||
{ PS_SPU::GSREG_MIX_DEST_B0, "MIX_DEST_B0", "", 2 },
|
||||
{ PS_SPU::GSREG_MIX_DEST_B1, "MIX_DEST_B1", "", 2 },
|
||||
{ PS_SPU::GSREG_IN_COEF_L, "IN_COEF_L", "", 2 },
|
||||
{ PS_SPU::GSREG_IN_COEF_R, "IN_COEF_R", "", 2 },
|
||||
|
||||
{ 0, "", "", 0 },
|
||||
};
|
||||
|
||||
#define VOICE_HELPER(v) \
|
||||
{ 0, "--V"#v"--", "", 0xFFFF }, \
|
||||
{ PS_SPU:: GSREG_V0_VOL_CTRL_L + v * 256, "VolCL", "Volume Control Left", 2 }, \
|
||||
{ PS_SPU:: GSREG_V0_VOL_CTRL_R + v * 256, "VolCR", "Volume Control Right", 2 }, \
|
||||
{ PS_SPU:: GSREG_V0_VOL_L + v * 256, "VolL", "Volume Left", 2 }, \
|
||||
{ PS_SPU:: GSREG_V0_VOL_R + v * 256, "VolR", "Volume Right", 2 }, \
|
||||
{ PS_SPU:: GSREG_V0_PITCH + v * 256, "Pitch", "Pitch", 2 }, \
|
||||
{ PS_SPU:: GSREG_V0_STARTADDR + v * 256, "SAddr", "Start Address", 3 }, \
|
||||
{ PS_SPU:: GSREG_V0_ADSR_CTRL + v * 256, "ADSRCTRL", "ADSR Control", 4 }, \
|
||||
{ PS_SPU:: GSREG_V0_ADSR_LEVEL + v * 256, "ADSRLev", "ADSR Level", 2 }, \
|
||||
{ PS_SPU:: GSREG_V0_LOOP_ADDR + v * 256, "LAddr", "Loop Address", 3 }, \
|
||||
{ PS_SPU:: GSREG_V0_READ_ADDR + v * 256, "RAddr", "Read Address", 3 }
|
||||
|
||||
|
||||
static RegType Regs_SPU_Voices[] =
|
||||
{
|
||||
#if 1
|
||||
VOICE_HELPER(0),
|
||||
VOICE_HELPER(1),
|
||||
VOICE_HELPER(2),
|
||||
VOICE_HELPER(3),
|
||||
#else
|
||||
VOICE_HELPER(20),
|
||||
VOICE_HELPER(21),
|
||||
VOICE_HELPER(22),
|
||||
VOICE_HELPER(23),
|
||||
#endif
|
||||
{ 0, "", "", 0 },
|
||||
};
|
||||
|
||||
|
||||
static uint32 GetRegister_SPU(const unsigned int id, char *special, const uint32 special_len)
|
||||
{
|
||||
return(SPU->GetRegister(id, special, special_len));
|
||||
}
|
||||
|
||||
static void SetRegister_SPU(const unsigned int id, uint32 value)
|
||||
{
|
||||
SPU->SetRegister(id, value);
|
||||
}
|
||||
|
||||
static RegGroupType SPURegsGroup =
|
||||
{
|
||||
NULL,
|
||||
Regs_SPU,
|
||||
GetRegister_SPU,
|
||||
SetRegister_SPU
|
||||
};
|
||||
|
||||
|
||||
static RegGroupType SPUVoicesRegsGroup =
|
||||
{
|
||||
NULL,
|
||||
Regs_SPU_Voices,
|
||||
GetRegister_SPU,
|
||||
SetRegister_SPU
|
||||
};
|
||||
|
||||
static RegType Regs_CPU[] =
|
||||
{
|
||||
{ PS_CPU::GSREG_PC, "PC", "PC", 4 },
|
||||
{ PS_CPU::GSREG_PC_NEXT, "NPC", "Next PC", 4 },
|
||||
{ PS_CPU::GSREG_IN_BD_SLOT, "INBD", "In Branch Delay Slot", 1 },
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
{ PS_CPU::GSREG_GPR + 1, "at", "Assembler Temporary", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 2, "v0", "Return Value 0", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 3, "v1", "Return Value 1", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 4, "a0", "Argument 0", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 5, "a1", "Argument 1", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 6, "a2", "Argument 2", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 7, "a3", "Argument 3", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 8, "t0", "Temporary 0", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 9, "t1", "Temporary 1", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 10, "t2", "Temporary 2", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 11, "t3", "Temporary 3", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 12, "t4", "Temporary 4", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 13, "t5", "Temporary 5", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 14, "t6", "Temporary 6", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 15, "t7", "Temporary 7", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 16, "s0", "Subroutine Reg Var 0", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 17, "s1", "Subroutine Reg Var 1", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 18, "s2", "Subroutine Reg Var 2", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 19, "s3", "Subroutine Reg Var 3", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 20, "s4", "Subroutine Reg Var 4", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 21, "s5", "Subroutine Reg Var 5", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 22, "s6", "Subroutine Reg Var 6", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 23, "s7", "Subroutine Reg Var 7", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 24, "t8", "Temporary 8", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 25, "t9", "Temporary 9", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 26, "k0", "Interrupt/Trap Handler Reg 0", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 27, "k1", "Interrupt/Trap Handler Reg 1", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 28, "gp", "Global Pointer", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 29, "sp", "Stack Pointer", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 30, "s8", "Subroutine Reg Var 8/Frame Pointer", 4 },
|
||||
{ PS_CPU::GSREG_GPR + 31, "ra", "Return Address", 4 },
|
||||
{ 0, "------", "", 0xFFFF },
|
||||
|
||||
{ PS_CPU::GSREG_SR, "SR", "Status Register", 4 },
|
||||
{ PS_CPU::GSREG_CAUSE, "CAU","Cause Register", 4 },
|
||||
{ PS_CPU::GSREG_EPC, "EPC", "EPC Register", 4 },
|
||||
{ 0, "", "", 0 }
|
||||
};
|
||||
|
||||
static uint32 GetRegister_CPU(const unsigned int id, char *special, const uint32 special_len)
|
||||
{
|
||||
return(CPU->GetRegister(id, special, special_len));
|
||||
}
|
||||
|
||||
static void SetRegister_CPU(const unsigned int id, uint32 value)
|
||||
{
|
||||
CPU->SetRegister(id, value);
|
||||
}
|
||||
|
||||
static RegGroupType CPURegsGroup =
|
||||
{
|
||||
NULL,
|
||||
Regs_CPU,
|
||||
GetRegister_CPU,
|
||||
SetRegister_CPU
|
||||
};
|
||||
|
||||
|
||||
bool DBG_Init(void)
|
||||
{
|
||||
CPUHook = NULL;
|
||||
BPCallB = NULL;
|
||||
FoundBPoint = false;
|
||||
|
||||
MDFNDBG_AddRegGroup(&CPURegsGroup);
|
||||
MDFNDBG_AddRegGroup(&MiscRegsGroup);
|
||||
MDFNDBG_AddRegGroup(&SPURegsGroup);
|
||||
MDFNDBG_AddRegGroup(&SPUVoicesRegsGroup);
|
||||
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "cpu", "CPU Physical", 32);
|
||||
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ram", "CPU Main Ram", 21);
|
||||
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "spu", "SPU RAM", 19);
|
||||
ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "gpu", "GPU RAM", 20);
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
21
mednafen/psx-0925/debug.h
Normal file
21
mednafen/psx-0925/debug.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __MDFN_PSX_DEBUG_H
|
||||
#define __MDFN_PSX_DEBUG_H
|
||||
|
||||
#ifdef WANT_DEBUGGER
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
extern DebuggerInfoStruct PSX_DBGInfo;
|
||||
|
||||
bool DBG_Init(void);
|
||||
|
||||
void DBG_Break(void);
|
||||
|
||||
void DBG_GPUScanlineHook(unsigned scanline);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
408
mednafen/psx-0925/dis.cpp
Normal file
408
mednafen/psx-0925/dis.cpp
Normal file
@ -0,0 +1,408 @@
|
||||
/* 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 "psx.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
struct OpEntry
|
||||
{
|
||||
uint32 mask;
|
||||
uint32 value;
|
||||
const char *mnemonic;
|
||||
const char *format;
|
||||
};
|
||||
|
||||
#define MASK_OP (0x3F << 26)
|
||||
#define MASK_FUNC (0x3F)
|
||||
#define MASK_RS (0x1F << 21)
|
||||
#define MASK_RT (0x1F << 16)
|
||||
#define MASK_RD (0x1F << 11)
|
||||
#define MASK_SA (0x1F << 6)
|
||||
|
||||
#define MK_OP(mnemonic, format, op, func, extra_mask) { MASK_OP | (op ? 0 : MASK_FUNC) | extra_mask, (op << 26) | func, mnemonic, format }
|
||||
|
||||
#define MK_OP_REGIMM(mnemonic, regop) { MASK_OP | MASK_RT, (0x01 << 26) | (regop << 16), mnemonic, "s, p" }
|
||||
|
||||
|
||||
#define MK_COPZ(z) { MASK_OP | (0x1 << 25), (0x1 << 25) | ((0x10 | z) << 26), "cop" #z, "F" }
|
||||
#define MK_COP0_FUNC(mnemonic, func) { MASK_OP | (0x1 << 25) | MASK_FUNC, (0x10 << 26) | (0x1 << 25) | func, mnemonic, "" }
|
||||
|
||||
#define MK_COPZ_XFER(z, mnemonic, format, xf) { MASK_OP | (0x1F << 21), ((0x10 | z) << 26) | (xf << 21), mnemonic, format }
|
||||
|
||||
#define MK_GTE(mnemonic, format, func) { MASK_OP | (0x1 << 25) | MASK_FUNC, (0x1 << 25) | (0x12 << 26) | func, mnemonic, format }
|
||||
|
||||
static OpEntry ops[] =
|
||||
{
|
||||
MK_OP("nop", "", 0, 0, MASK_RT | MASK_RD | MASK_SA),
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
MK_OP("sll", "d, t, a", 0, 0, 0),
|
||||
MK_OP("srl", "d, t, a", 0, 2, 0),
|
||||
MK_OP("sra", "d, t, a", 0, 3, 0),
|
||||
|
||||
MK_OP("sllv", "d, t, s", 0, 4, 0),
|
||||
MK_OP("srlv", "d, t, s", 0, 6, 0),
|
||||
MK_OP("srav", "d, t, s", 0, 7, 0),
|
||||
|
||||
MK_OP("jr", "s", 0, 8, 0),
|
||||
MK_OP("jalr", "d, s", 0, 9, 0),
|
||||
|
||||
MK_OP("syscall", "", 0, 12, 0), // TODO
|
||||
MK_OP("break", "", 0, 13, 0), // TODO
|
||||
|
||||
MK_OP("mfhi", "d", 0, 16, 0),
|
||||
MK_OP("mthi", "s", 0, 17, 0),
|
||||
MK_OP("mflo", "d", 0, 18, 0),
|
||||
MK_OP("mtlo", "s", 0, 19, 0),
|
||||
|
||||
MK_OP("mult", "s, t", 0, 24, 0),
|
||||
MK_OP("multu", "s, t", 0, 25, 0),
|
||||
MK_OP("div", "s, t", 0, 26, 0),
|
||||
MK_OP("divu", "s, t", 0, 27, 0),
|
||||
|
||||
MK_OP("add", "d, s, t", 0, 32, 0),
|
||||
MK_OP("addu", "d, s, t", 0, 33, 0),
|
||||
MK_OP("sub", "d, s, t", 0, 34, 0),
|
||||
MK_OP("subu", "d, s, t", 0, 35, 0),
|
||||
MK_OP("and", "d, s, t", 0, 36, 0),
|
||||
MK_OP("or", "d, s, t", 0, 37, 0),
|
||||
MK_OP("xor", "d, s, t", 0, 38, 0),
|
||||
MK_OP("nor", "d, s, t", 0, 39, 0),
|
||||
MK_OP("slt", "d, s, t", 0, 42, 0),
|
||||
MK_OP("sltu", "d, s, t", 0, 43, 0),
|
||||
|
||||
MK_OP_REGIMM("bgez", 0x01),
|
||||
MK_OP_REGIMM("bgezal", 0x11),
|
||||
MK_OP_REGIMM("bltz", 0x00),
|
||||
MK_OP_REGIMM("bltzal", 0x10),
|
||||
|
||||
|
||||
MK_OP("j", "P", 2, 0, 0),
|
||||
MK_OP("jal", "P", 3, 0, 0),
|
||||
|
||||
MK_OP("beq", "s, t, p", 4, 0, 0),
|
||||
MK_OP("bne", "s, t, p", 5, 0, 0),
|
||||
MK_OP("blez", "s, p", 6, 0, 0),
|
||||
MK_OP("bgtz", "s, p", 7, 0, 0),
|
||||
|
||||
MK_OP("addi", "t, s, i", 8, 0, 0),
|
||||
MK_OP("addiu", "t, s, i", 9, 0, 0),
|
||||
MK_OP("slti", "t, s, i", 10, 0, 0),
|
||||
MK_OP("sltiu", "t, s, i", 11, 0, 0),
|
||||
|
||||
MK_OP("andi", "t, s, z", 12, 0, 0),
|
||||
|
||||
MK_OP("ori", "t, s, z", 13, 0, 0),
|
||||
MK_OP("xori", "t, s, z", 14, 0, 0),
|
||||
MK_OP("lui", "t, z", 15, 0, 0),
|
||||
|
||||
MK_COPZ_XFER(0, "mfc0", "t, 0", 0x00),
|
||||
MK_COPZ_XFER(1, "mfc1", "t, ?", 0x00),
|
||||
MK_COPZ_XFER(2, "mfc2", "t, g", 0x00),
|
||||
MK_COPZ_XFER(3, "mfc3", "t, ?", 0x00),
|
||||
|
||||
MK_COPZ_XFER(0, "mtc0", "t, 0", 0x04),
|
||||
MK_COPZ_XFER(1, "mtc1", "t, ?", 0x04),
|
||||
MK_COPZ_XFER(2, "mtc2", "t, g", 0x04),
|
||||
MK_COPZ_XFER(3, "mtc3", "t, ?", 0x04),
|
||||
|
||||
MK_COPZ_XFER(0, "cfc0", "t, ?", 0x02),
|
||||
MK_COPZ_XFER(1, "cfc1", "t, ?", 0x02),
|
||||
MK_COPZ_XFER(2, "cfc2", "t, G", 0x02),
|
||||
MK_COPZ_XFER(3, "cfc3", "t, ?", 0x02),
|
||||
|
||||
MK_COPZ_XFER(0, "ctc0", "t, ?", 0x06),
|
||||
MK_COPZ_XFER(1, "ctc1", "t, ?", 0x06),
|
||||
MK_COPZ_XFER(2, "ctc2", "t, G", 0x06),
|
||||
MK_COPZ_XFER(3, "ctc3", "t, ?", 0x06),
|
||||
|
||||
// COP0 stuff here
|
||||
MK_COP0_FUNC("rfe", 0x10),
|
||||
|
||||
MK_OP("lwc0", "?, i(s)", 0x30, 0, 0),
|
||||
MK_OP("lwc1", "?, i(s)", 0x31, 0, 0),
|
||||
MK_OP("lwc2", "h, i(s)", 0x32, 0, 0),
|
||||
MK_OP("lwc3", "?, i(s)", 0x33, 0, 0),
|
||||
|
||||
MK_OP("swc0", "?, i(s)", 0x38, 0, 0),
|
||||
MK_OP("swc1", "?, i(s)", 0x39, 0, 0),
|
||||
MK_OP("swc2", "h, i(s)", 0x3A, 0, 0),
|
||||
MK_OP("swc3", "?, i(s)", 0x3B, 0, 0),
|
||||
|
||||
MK_OP("lb", "t, i(s)", 0x20, 0, 0),
|
||||
MK_OP("lh", "t, i(s)", 0x21, 0, 0),
|
||||
MK_OP("lwl", "t, i(s)", 0x22, 0, 0),
|
||||
MK_OP("lw", "t, i(s)", 0x23, 0, 0),
|
||||
MK_OP("lbu", "t, i(s)", 0x24, 0, 0),
|
||||
MK_OP("lhu", "t, i(s)", 0x25, 0, 0),
|
||||
MK_OP("lwr", "t, i(s)", 0x26, 0, 0),
|
||||
|
||||
MK_OP("sb", "t, i(s)", 0x28, 0, 0),
|
||||
MK_OP("sh", "t, i(s)", 0x29, 0, 0),
|
||||
MK_OP("swl", "t, i(s)", 0x2A, 0, 0),
|
||||
MK_OP("sw", "t, i(s)", 0x2B, 0, 0),
|
||||
MK_OP("swr", "t, i(s)", 0x2E, 0, 0),
|
||||
|
||||
//
|
||||
// GTE specific instructions
|
||||
//
|
||||
// sf mx v cv lm
|
||||
//
|
||||
MK_GTE("rtps", "#sf# #lm#", 0x00),
|
||||
MK_GTE("rtps", "#sf# #lm#", 0x01),
|
||||
MK_GTE("nclip", "", 0x06),
|
||||
MK_GTE("op", "#sf# #lm#", 0x0C),
|
||||
|
||||
MK_GTE("dpcs", "#sf# #lm#", 0x10),
|
||||
MK_GTE("intpl", "#sf# #lm#", 0x11),
|
||||
MK_GTE("mvmva", "#sf# #mx# #v# #cv# #lm#", 0x12),
|
||||
MK_GTE("ncds", "#sf# #lm#", 0x13),
|
||||
MK_GTE("cdp", "#sf# #lm#", 0x14),
|
||||
MK_GTE("ncdt", "#sf# #lm#", 0x16),
|
||||
MK_GTE("dcpl", "#sf# #lm#", 0x1A),
|
||||
MK_GTE("nccs", "#sf# #lm#", 0x1B),
|
||||
MK_GTE("cc", "#sf# #lm#", 0x1C),
|
||||
MK_GTE("ncs", "#sf# #lm#", 0x1E),
|
||||
MK_GTE("nct", "#sf# #lm#", 0x20),
|
||||
MK_GTE("sqr", "#sf# #lm#", 0x28),
|
||||
MK_GTE("dcpl", "#sf# #lm#", 0x29),
|
||||
MK_GTE("dpct", "#sf# #lm#", 0x2A),
|
||||
MK_GTE("avsz3", "", 0x2D),
|
||||
MK_GTE("avsz4", "", 0x2E),
|
||||
MK_GTE("rtpt", "#sf# #lm#", 0x30),
|
||||
MK_GTE("gpf", "#sf# #lm#", 0x3D),
|
||||
MK_GTE("gpl", "#sf# #lm#", 0x3E),
|
||||
MK_GTE("ncct", "#sf# #lm#", 0x3F),
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
MK_COPZ(0),
|
||||
MK_COPZ(1),
|
||||
MK_COPZ(2),
|
||||
MK_COPZ(3),
|
||||
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
std::string DisassembleMIPS(uint32 PC, uint32 instr)
|
||||
{
|
||||
std::string ret = "UNKNOWN";
|
||||
unsigned int rs = (instr >> 21) & 0x1F;
|
||||
unsigned int rt = (instr >> 16) & 0x1F;
|
||||
unsigned int rd = (instr >> 11) & 0x1F;
|
||||
unsigned int shamt = (instr >> 6) & 0x1F;
|
||||
unsigned int immediate = (int32)(int16)(instr & 0xFFFF);
|
||||
unsigned int immediate_ze = (instr & 0xFFFF);
|
||||
unsigned int jt = instr & ((1 << 26) - 1);
|
||||
|
||||
static const char *gpr_names[32] =
|
||||
{
|
||||
"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
|
||||
};
|
||||
|
||||
static const char *cop0_names[32] =
|
||||
{
|
||||
"CPR0", "CPR1", "CPR2", "BPC", "CPR4", "BDA", "TAR", "DCIC", "CPR8", "BDAM", "CPR10", "BPCM", "SR", "CAUSE", "EPC", "PRID",
|
||||
"ERREG", "CPR17", "CPR18", "CPR19", "CPR20", "CPR21", "CPR22", "CPR23", "CPR24", "CPR25", "CPR26", "CPR27", "CPR28", "CPR29", "CPR30", "CPR31"
|
||||
};
|
||||
|
||||
static const char *gte_cr_names[32] =
|
||||
{
|
||||
"R11R12", "R13R21", "R22R23", "R31R32", "R33", "TRX", "TRY", "TRZ", "L11L12", "L13L21", "L22L23", "L31L32", "L33", "RBK", "GBK", "BBK",
|
||||
"LR1LR2", "LR3LG1", "LG2LG3", "LB1LB2", "LB3", "RFC", "GFC", "BFC", "OFX", "OFY", "H", "DQA", "DQB", "ZSF3", "ZSF4", "FLAG"
|
||||
};
|
||||
|
||||
static const char *gte_dr_names[32] =
|
||||
{
|
||||
"VXY0", "VZ0", "VXY1", "VZ1", "VXY2", "VZ2", "RGB", "OTZ", "IR0", "IR1", "IR2", "IR3", "SXY0", "SXY1", "SXY2", "SXYP",
|
||||
"SZ0", "SZ1", "SZ2", "SZ3", "RGB0", "RGB1", "RGB2", "RES1", "MAC0", "MAC1", "MAC2", "MAC3", "IRGB", "ORGB", "LZCS", "LZCR"
|
||||
};
|
||||
|
||||
OpEntry *op = ops;
|
||||
|
||||
while(op->mnemonic)
|
||||
{
|
||||
if((instr & op->mask) == op->value)
|
||||
{
|
||||
// a = shift amount
|
||||
// s = rs
|
||||
// t = rt
|
||||
// d = rd
|
||||
// i = immediate
|
||||
// z = immediate, zero-extended
|
||||
// p = PC + 4 + immediate
|
||||
// P = ((PC + 4) & 0xF0000000) | (26bitval << 2)
|
||||
//
|
||||
// 0 = rd(cop0 registers)
|
||||
// c = rd(copz data registers)
|
||||
// C = rd(copz control registers)
|
||||
// g = rd(GTE data registers)
|
||||
// G = rd(GTE control registers)
|
||||
// h = rt(GTE data registers)
|
||||
|
||||
char s_a[16];
|
||||
char s_i[16];
|
||||
char s_z[16];
|
||||
char s_p[16];
|
||||
char s_P[16];
|
||||
char s_c[16];
|
||||
char s_C[16];
|
||||
|
||||
snprintf(s_a, sizeof(s_a), "%d", shamt);
|
||||
|
||||
if(immediate < 0)
|
||||
snprintf(s_i, sizeof(s_i), "%d", immediate);
|
||||
else
|
||||
snprintf(s_i, sizeof(s_i), "0x%04x", (uint32)immediate);
|
||||
|
||||
snprintf(s_z, sizeof(s_z), "0x%04x", immediate_ze);
|
||||
|
||||
snprintf(s_p, sizeof(s_p), "0x%08x", PC + 4 + (immediate << 2));
|
||||
|
||||
snprintf(s_P, sizeof(s_P), "0x%08x", ((PC + 4) & 0xF0000000) | (jt << 2));
|
||||
|
||||
snprintf(s_c, sizeof(s_c), "CPR%d", rd);
|
||||
snprintf(s_C, sizeof(s_C), "CCR%d", rd);
|
||||
|
||||
ret = std::string(op->mnemonic);
|
||||
ret.append(10 - ret.size(), ' ');
|
||||
|
||||
for(unsigned int i = 0; i < strlen(op->format); i++)
|
||||
{
|
||||
switch(op->format[i])
|
||||
{
|
||||
case '#':
|
||||
// sf mx v cv lm
|
||||
{
|
||||
char as[16];
|
||||
|
||||
as[0] = 0;
|
||||
if(!strncmp(&op->format[i], "#sf#", 4))
|
||||
{
|
||||
i += 3;
|
||||
snprintf(as, 16, "sf=%d", (int)(bool)(instr & (1 << 19)));
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#mx#", 4))
|
||||
{
|
||||
i += 3;
|
||||
snprintf(as, 16, "mx=%d", (instr >> 17) & 0x3);
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#v#", 3))
|
||||
{
|
||||
i += 2;
|
||||
snprintf(as, 16, "v=%d", (instr >> 15) & 0x3);
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#cv#", 4))
|
||||
{
|
||||
i += 3;
|
||||
snprintf(as, 16, "cv=%d", (instr >> 13) & 0x3);
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#lm#", 4))
|
||||
{
|
||||
i += 3;
|
||||
snprintf(as, 16, "lm=%d", (int)(bool)(instr & (1 << 10)));
|
||||
}
|
||||
ret.append(as);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
{
|
||||
char s_F[16];
|
||||
|
||||
snprintf(s_F, 16, "0x%07x", instr & 0x1FFFFFF);
|
||||
ret.append(s_F);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
ret.append(gte_dr_names[rt]);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
ret.append(gte_dr_names[rd]);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
ret.append(gte_cr_names[rd]);
|
||||
break;
|
||||
|
||||
case '0':
|
||||
ret.append(cop0_names[rd]);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
ret.append(s_c);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
ret.append(s_C);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
ret.append(s_a);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
ret.append(s_i);
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
ret.append(s_z);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
ret.append(s_p);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
ret.append(s_P);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
ret.append(gpr_names[rs]);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
ret.append(gpr_names[rt]);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
ret.append(gpr_names[rd]);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret.append(1, op->format[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
11
mednafen/psx-0925/dis.h
Normal file
11
mednafen/psx-0925/dis.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_DIS_H
|
||||
#define __MDFN_PSX_DIS_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
std::string DisassembleMIPS(uint32 PC, uint32 instr);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
638
mednafen/psx-0925/dma.cpp
Normal file
638
mednafen/psx-0925/dma.cpp
Normal file
@ -0,0 +1,638 @@
|
||||
/* 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 "psx.h"
|
||||
#include "mdec.h"
|
||||
#include "cdc.h"
|
||||
#include "spu.h"
|
||||
|
||||
// FIXME: 0-length block count?
|
||||
|
||||
|
||||
/* Notes:
|
||||
|
||||
Channel 4(SPU):
|
||||
Write:
|
||||
Doesn't seem to work properly with CHCR=0x01000001
|
||||
Hung when CHCR=0x11000601
|
||||
|
||||
Channel 6:
|
||||
DMA hangs if D28 of CHCR is 0?
|
||||
D1 did not have an apparent effect.
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
CH_MDEC_IN = 0,
|
||||
CH_MDEC_OUT = 1,
|
||||
CH_GPU = 2,
|
||||
CH_CDC = 3,
|
||||
CH_SPU = 4,
|
||||
CH_OT = 6,
|
||||
};
|
||||
|
||||
|
||||
// RunChannels(128 - whatevercounter);
|
||||
//
|
||||
// GPU next event, std::max<128, wait_time>, or something similar, for handling FIFO.
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
static int32 DMACycleCounter;
|
||||
|
||||
static uint32 DMAControl;
|
||||
static uint32 DMAIntControl;
|
||||
static uint8 DMAIntStatus;
|
||||
static bool IRQOut;
|
||||
|
||||
struct Channel
|
||||
{
|
||||
uint32 BaseAddr;
|
||||
uint32 BlockControl;
|
||||
uint32 ChanControl;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
uint32 CurAddr;
|
||||
uint32 NextAddr;
|
||||
|
||||
uint16 BlockCounter;
|
||||
uint16 WordCounter;
|
||||
|
||||
int32 ClockCounter;
|
||||
};
|
||||
|
||||
static Channel DMACH[7];
|
||||
static pscpu_timestamp_t lastts;
|
||||
|
||||
|
||||
static const char *PrettyChannelNames[7] = { "MDEC IN", "MDEC OUT", "GPU", "CDC", "SPU", "PIO", "OTC" };
|
||||
|
||||
void DMA_Init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DMA_Kill(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static INLINE void RecalcIRQOut(void)
|
||||
{
|
||||
bool irqo;
|
||||
|
||||
irqo = (bool)(DMAIntStatus & ((DMAIntControl >> 16) & 0x7F));
|
||||
irqo &= (DMAIntControl >> 23) & 1;
|
||||
|
||||
// I think it's logical OR, not XOR/invert. Still kind of weird, maybe it actually does something more complicated?
|
||||
//irqo ^= (DMAIntControl >> 15) & 1;
|
||||
irqo |= (DMAIntControl >> 15) & 1;
|
||||
|
||||
IRQOut = irqo;
|
||||
IRQ_Assert(IRQ_DMA, irqo);
|
||||
}
|
||||
|
||||
void DMA_ResetTS(void)
|
||||
{
|
||||
lastts = 0;
|
||||
}
|
||||
|
||||
void DMA_Power(void)
|
||||
{
|
||||
lastts = 0;
|
||||
|
||||
memset(DMACH, 0, sizeof(DMACH));
|
||||
|
||||
DMACycleCounter = 128;
|
||||
|
||||
DMAControl = 0;
|
||||
DMAIntControl = 0;
|
||||
DMAIntStatus = 0;
|
||||
RecalcIRQOut();
|
||||
}
|
||||
|
||||
static void RecalcHalt(void)
|
||||
{
|
||||
bool Halt = false;
|
||||
|
||||
if((DMACH[0].WordCounter || (DMACH[0].ChanControl & (1 << 24))) && (DMACH[0].ChanControl & 0x200) /*&& MDEC_DMACanWrite()*/)
|
||||
Halt = true;
|
||||
|
||||
if((DMACH[1].WordCounter || (DMACH[1].ChanControl & (1 << 24))) && (DMACH[1].ChanControl & 0x200) && (DMACH[1].WordCounter || MDEC_DMACanRead()))
|
||||
Halt = true;
|
||||
|
||||
if((DMACH[2].WordCounter || (DMACH[2].ChanControl & (1 << 24))) && (DMACH[2].ChanControl & 0x200) && ((DMACH[2].ChanControl & 0x1) && (DMACH[2].WordCounter || GPU->DMACanWrite())))
|
||||
Halt = true;
|
||||
|
||||
if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100))
|
||||
Halt = true;
|
||||
|
||||
if(DMACH[6].WordCounter || (DMACH[6].ChanControl & (1 << 24)))
|
||||
Halt = true;
|
||||
|
||||
//printf("Halt: %d\n", Halt);
|
||||
|
||||
CPU->SetHalt(Halt);
|
||||
}
|
||||
|
||||
template<int ch, bool write_mode>
|
||||
static INLINE bool ChCan(void)
|
||||
{
|
||||
#if 0
|
||||
if(ch != 3)
|
||||
{
|
||||
if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(ch)
|
||||
{
|
||||
case 0: return(true); // MDEC IN
|
||||
case 1: return(MDEC_DMACanRead()); // MDEC out
|
||||
case 2:
|
||||
if(write_mode)
|
||||
return(GPU->DMACanWrite());
|
||||
else
|
||||
return(true); // GPU
|
||||
case 3: return(true); // CDC
|
||||
case 4: return(true); // SPU
|
||||
case 5: return(true); // ??
|
||||
case 6: return(true); // OT
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
template<int ch, bool write_mode>
|
||||
static INLINE void ChRW(int32 timestamp, uint32 *V)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
|
||||
case CH_MDEC_IN:
|
||||
MDEC_DMAWrite(*V);
|
||||
break;
|
||||
|
||||
case CH_MDEC_OUT:
|
||||
*V = MDEC_DMARead();
|
||||
break;
|
||||
|
||||
case CH_GPU:
|
||||
if(write_mode)
|
||||
GPU->WriteDMA(*V);
|
||||
else
|
||||
*V = GPU->Read(timestamp, 0);
|
||||
break;
|
||||
|
||||
case CH_CDC:
|
||||
// 0x1f801018 affects CDC DMA timing.
|
||||
#if 0
|
||||
if(DMACH[ch].ChanControl & 0x100) // For CDC DMA(at least): When this bit is set, DMA controller doesn't appear to hog the (RAM?) bus.
|
||||
{
|
||||
if(DMACH[ch].ChanControl & 0x00400000) // For CDC DMA(at least): When this bit is set, DMA controller appears to get even less bus time(or has a lower priority??)
|
||||
{
|
||||
DMACH[ch].ClockCounter -= 44 * 20 / 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMACH[ch].ClockCounter -= 29 * 20 / 12;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DMACH[ch].ClockCounter -= 23 * 20 / 12; // (23 + 1) = 24. (Though closer to 24.5 or 24.4 on average per tests on a PS1)
|
||||
}
|
||||
#endif
|
||||
*V = CDC->DMARead();
|
||||
break;
|
||||
|
||||
case CH_SPU:
|
||||
// 0x1f801014 affects SPU DMA timing.
|
||||
// Wild conjecture about 0x1f801014:
|
||||
//
|
||||
// & 0x0000000F
|
||||
// & 0x000001E0 --- Used if (& 0x20000000) == 0?
|
||||
// & 0x00001000 --- Double total bus cycle time if value == 0?
|
||||
// & 0x0f000000 --- (value << 1) 33MHz cycles, bus cycle extension(added to 4?)?
|
||||
// & 0x20000000 ---
|
||||
//
|
||||
//
|
||||
// TODO?: SPU DMA will "complete" much faster if there's a mismatch between the CHCR read/write mode bit and the SPU control register DMA mode.
|
||||
//
|
||||
//
|
||||
// Investigate: SPU DMA doesn't seem to work right if the value written to 0x1F801DAA doesn't have the upper bit set to 1(0x8000) on a PS1.
|
||||
|
||||
DMACH[ch].ClockCounter -= 47; // Should be closer to 69, average, but actual timing is...complicated.
|
||||
if(write_mode)
|
||||
SPU->WriteDMA(*V);
|
||||
else
|
||||
*V = SPU->ReadDMA();
|
||||
break;
|
||||
|
||||
case CH_OT:
|
||||
if(DMACH[ch].WordCounter == 1)
|
||||
*V = 0xFFFFFF;
|
||||
else
|
||||
*V = (DMACH[ch].CurAddr - 4) & 0x1FFFFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<int ch, bool write_mode>
|
||||
static INLINE void RunChannelT(pscpu_timestamp_t timestamp, int32 clocks)
|
||||
{
|
||||
//const uint32 dc = (DMAControl >> (ch * 4)) & 0xF;
|
||||
|
||||
DMACH[ch].ClockCounter += clocks;
|
||||
|
||||
while(DMACH[ch].ClockCounter > 0)
|
||||
{
|
||||
if(!DMACH[ch].WordCounter)
|
||||
{
|
||||
if(!(DMACH[ch].ChanControl & (1 << 24)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(DMACH[ch].NextAddr & 0x800000)
|
||||
{
|
||||
//if(ch == 2)
|
||||
// PSX_WARNING("[DMA] LL Channel 2 ended normally: %d\n", GPU->GetScanlineNum());
|
||||
DMACH[ch].ChanControl &= ~(0x11 << 24);
|
||||
if(DMAIntControl & (1 << (16 + ch)))
|
||||
{
|
||||
DMAIntStatus |= 1 << ch;
|
||||
RecalcIRQOut();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!ChCan<ch, write_mode>())
|
||||
break;
|
||||
|
||||
if((DMACH[ch].ChanControl & (1 << 10)) && write_mode)
|
||||
{
|
||||
uint32 header;
|
||||
|
||||
DMACH[ch].CurAddr = DMACH[ch].NextAddr & 0x1FFFFC;
|
||||
header = MainRAM.ReadU32(DMACH[ch].CurAddr);
|
||||
DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0x1FFFFF;
|
||||
|
||||
DMACH[ch].WordCounter = header >> 24;
|
||||
DMACH[ch].NextAddr = header & 0xFFFFFF;
|
||||
|
||||
if(DMACH[ch].WordCounter > 0x10)
|
||||
printf("What the lala? 0x%02x @ 0x%08x\n", DMACH[ch].WordCounter, DMACH[ch].CurAddr - 4);
|
||||
|
||||
if(DMACH[ch].WordCounter)
|
||||
DMACH[ch].ClockCounter -= 15;
|
||||
else
|
||||
DMACH[ch].ClockCounter -= 10;
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMACH[ch].CurAddr = DMACH[ch].NextAddr & 0x1FFFFC;
|
||||
DMACH[ch].WordCounter = DMACH[ch].BlockControl & 0xFFFF;
|
||||
DMACH[ch].BlockCounter--;
|
||||
|
||||
if(!DMACH[ch].BlockCounter || ch == 6 || ch == 3)
|
||||
DMACH[ch].NextAddr = 0xFFFFFF;
|
||||
else
|
||||
DMACH[ch].NextAddr = (DMACH[ch].CurAddr + ((DMACH[ch].BlockControl & 0xFFFF) << 2)) & 0x1FFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
if(ch != 2 && ch != 1)
|
||||
{
|
||||
if(!ChCan<ch, write_mode>())
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
uint32 vtmp;
|
||||
|
||||
if(write_mode)
|
||||
vtmp = MainRAM.ReadU32(DMACH[ch].CurAddr);
|
||||
|
||||
ChRW<ch, write_mode>(timestamp, &vtmp);
|
||||
|
||||
if(!write_mode)
|
||||
MainRAM.WriteU32(DMACH[ch].CurAddr, vtmp);
|
||||
}
|
||||
|
||||
if(ch == 6)
|
||||
DMACH[ch].CurAddr = (DMACH[ch].CurAddr - 4) & 0x1FFFFF;
|
||||
else
|
||||
DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0x1FFFFF;
|
||||
|
||||
DMACH[ch].WordCounter--;
|
||||
DMACH[ch].ClockCounter--;
|
||||
}
|
||||
|
||||
|
||||
if(DMACH[ch].ClockCounter > 0)
|
||||
DMACH[ch].ClockCounter = 0;
|
||||
}
|
||||
|
||||
static INLINE void RunChannel(pscpu_timestamp_t timestamp, int32 clocks, int ch)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
default: abort();
|
||||
|
||||
case 0:
|
||||
RunChannelT<0, true>(timestamp, clocks);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
RunChannelT<1, false>(timestamp, clocks);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(DMACH[2].ChanControl & 0x1)
|
||||
RunChannelT<2, true>(timestamp, clocks);
|
||||
else
|
||||
RunChannelT<2, false>(timestamp, clocks);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
RunChannelT<3, false>(timestamp, clocks);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if(DMACH[4].ChanControl & 0x1)
|
||||
RunChannelT<4, true>(timestamp, clocks);
|
||||
else
|
||||
RunChannelT<4, false>(timestamp, clocks);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
RunChannelT<6, false>(timestamp, clocks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE int32 CalcNextEvent(int32 next_event)
|
||||
{
|
||||
if(DMACycleCounter < next_event)
|
||||
next_event = DMACycleCounter;
|
||||
|
||||
return(next_event);
|
||||
}
|
||||
|
||||
pscpu_timestamp_t DMA_Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
// uint32 dc = (DMAControl >> (ch * 4)) & 0xF;
|
||||
int32 clocks = timestamp - lastts;
|
||||
lastts = timestamp;
|
||||
|
||||
GPU->Update(timestamp);
|
||||
MDEC_Run(clocks);
|
||||
|
||||
RunChannel(timestamp, clocks, 0);
|
||||
RunChannel(timestamp, clocks, 1);
|
||||
RunChannel(timestamp, clocks, 2);
|
||||
RunChannel(timestamp, clocks, 3);
|
||||
RunChannel(timestamp, clocks, 4);
|
||||
RunChannel(timestamp, clocks, 6);
|
||||
|
||||
DMACycleCounter -= clocks;
|
||||
while(DMACycleCounter <= 0)
|
||||
DMACycleCounter += 128;
|
||||
|
||||
RecalcHalt();
|
||||
|
||||
return(timestamp + CalcNextEvent(0x10000000));
|
||||
}
|
||||
|
||||
void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
int ch = (A & 0x7F) >> 4;
|
||||
|
||||
//PSX_WARNING("[DMA] Write: %08x %08x, DMAIntStatus=%08x", A, V, DMAIntStatus);
|
||||
|
||||
// FIXME if we ever have "accurate" bus emulation
|
||||
V <<= (A & 3) * 8;
|
||||
|
||||
DMA_Update(timestamp);
|
||||
|
||||
if(ch == 7)
|
||||
{
|
||||
switch(A & 0xC)
|
||||
{
|
||||
case 0x0: //fprintf(stderr, "Global DMA control: 0x%08x\n", V);
|
||||
DMAControl = V;
|
||||
RecalcHalt();
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
//for(int x = 0; x < 7; x++)
|
||||
//{
|
||||
// if(DMACH[x].WordCounter || (DMACH[x].ChanControl & (1 << 24)))
|
||||
// {
|
||||
// fprintf(stderr, "Write DMAIntControl while channel %d active: 0x%08x\n", x, V);
|
||||
// }
|
||||
//}
|
||||
DMAIntControl = V & 0x00ff803f;
|
||||
DMAIntStatus &= ~(V >> 24);
|
||||
|
||||
//if(DMAIntStatus ^ (DMAIntStatus & (V >> 16)))
|
||||
// fprintf(stderr, "DMAINT Fudge: %02x\n", DMAIntStatus ^ (DMAIntStatus & (V >> 16)));
|
||||
DMAIntStatus &= (V >> 16); // THIS IS ALMOST CERTAINLY WRONG AND A HACK. Remove when CDC emulation is better.
|
||||
RecalcIRQOut();
|
||||
break;
|
||||
|
||||
default: PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch(A & 0xC)
|
||||
{
|
||||
case 0x0: DMACH[ch].BaseAddr = V & 0xFFFFFF;
|
||||
break;
|
||||
|
||||
case 0x4: DMACH[ch].BlockControl = V;
|
||||
break;
|
||||
|
||||
case 0xC:
|
||||
case 0x8:
|
||||
{
|
||||
uint32 OldCC = DMACH[ch].ChanControl;
|
||||
|
||||
//
|
||||
// Kludge for DMA timing granularity and other issues. Needs to occur before setting all bits of ChanControl to the new value, to accommodate the
|
||||
// case of a game cancelling DMA and changing the type of DMA(read/write, etc.) at the same time.
|
||||
//
|
||||
if((DMACH[ch].ChanControl & (1 << 24)) && !(V & (1 << 24)))
|
||||
{
|
||||
DMACH[ch].ChanControl &= ~(1 << 24); // Clear bit before RunChannel(), so it will only finish the block it's on at most.
|
||||
RunChannel(timestamp, 128 * 16, ch);
|
||||
DMACH[ch].BlockCounter = 0;
|
||||
DMACH[ch].WordCounter = 0;
|
||||
|
||||
#if 0 // TODO(maybe, need to work out worst-case performance for abnormally/brokenly large block sizes)
|
||||
DMACH[ch].ClockCounter = (1 << 30);
|
||||
RunChannel(timestamp, 1, ch);
|
||||
DMACH[ch].ClockCounter = 0;
|
||||
#endif
|
||||
|
||||
if(ch == 2)
|
||||
{
|
||||
GPU->AbortDMA();
|
||||
}
|
||||
|
||||
PSX_WARNING("[DMA] Forced stop for channel %d -- scanline=%d", ch, GPU->GetScanlineNum());
|
||||
//MDFN_DispMessage("[DMA] Forced stop for channel %d", ch);
|
||||
}
|
||||
|
||||
if(ch == 6)
|
||||
DMACH[ch].ChanControl = V & 0x51000002; // Not 100% sure, but close.
|
||||
else
|
||||
DMACH[ch].ChanControl = V & 0x71770703;
|
||||
|
||||
if(!(OldCC & (1 << 24)) && (V & (1 << 24)))
|
||||
{
|
||||
//if(ch == 2)
|
||||
//if(ch == 4)
|
||||
//PSX_WARNING("[DMA] Started DMA for channel=%d --- CHCR=0x%08x --- BCR=0x%08x --- scanline=%d", ch, DMACH[ch].ChanControl, DMACH[ch].BlockControl, GPU->GetScanlineNum());
|
||||
|
||||
DMACH[ch].ClockCounter = 0;
|
||||
DMACH[ch].NextAddr = DMACH[ch].BaseAddr & 0x1FFFFC;
|
||||
DMACH[ch].BlockCounter = DMACH[ch].BlockControl >> 16;
|
||||
|
||||
//
|
||||
// Viewpoint starts a short MEM->GPU LL DMA and apparently has race conditions that can cause a crash if it doesn't finish almost immediately(
|
||||
// or at least very quickly, which the current DMA granularity has issues with, so run the channel ahead a bit to take of this issue and potentially
|
||||
// games with similar issues).
|
||||
//
|
||||
// Though, Viewpoint isn't exactly a good game, so maybe we shouldn't bother? ;)
|
||||
//
|
||||
RunChannel(timestamp, 64, ch); //std::max<int>(128 - DMACycleCounter, 1)); //64); //1); //128 - DMACycleCounter);
|
||||
}
|
||||
|
||||
RecalcHalt();
|
||||
}
|
||||
break;
|
||||
}
|
||||
PSX_SetEventNT(PSX_EVENT_DMA, timestamp + CalcNextEvent(0x10000000));
|
||||
}
|
||||
|
||||
uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
int ch = (A & 0x7F) >> 4;
|
||||
uint32 ret = 0;
|
||||
|
||||
//assert(!(A & 3));
|
||||
|
||||
//if(ch == 2)
|
||||
// printf("DMA Read: %08x --- %d\n", A, GPU->GetScanlineNum());
|
||||
|
||||
if(ch == 7)
|
||||
{
|
||||
switch(A & 0xC)
|
||||
{
|
||||
default: PSX_WARNING("[DMA] Unknown read: %08x", A);
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case 0x0: ret = DMAControl;
|
||||
break;
|
||||
|
||||
case 0x4: ret = DMAIntControl | (DMAIntStatus << 24) | (IRQOut << 31);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else switch(A & 0xC)
|
||||
{
|
||||
case 0x0: ret = DMACH[ch].BaseAddr;
|
||||
break;
|
||||
|
||||
case 0x4: ret = DMACH[ch].BlockControl;
|
||||
break;
|
||||
|
||||
case 0xC:
|
||||
case 0x8: ret = DMACH[ch].ChanControl;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
ret >>= (A & 3) * 8;
|
||||
|
||||
//PSX_WARNING("[DMA] Read: %08x %08x", A, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int DMA_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(DMACycleCounter),
|
||||
SFVAR(DMAControl),
|
||||
SFVAR(DMAIntControl),
|
||||
SFVAR(DMAIntStatus),
|
||||
SFVAR(IRQOut),
|
||||
|
||||
#define SFDMACH(n) SFVARN(DMACH[n].BaseAddr, #n "BaseAddr"), \
|
||||
SFVARN(DMACH[n].BlockControl, #n "BlockControl"), \
|
||||
SFVARN(DMACH[n].ChanControl, #n "ChanControl"), \
|
||||
SFVARN(DMACH[n].CurAddr, #n "CurAddr"), \
|
||||
SFVARN(DMACH[n].NextAddr, #n "NextAddr"), \
|
||||
SFVARN(DMACH[n].BlockCounter, #n "BlockCounter"), \
|
||||
SFVARN(DMACH[n].WordCounter, #n "WordCounter"), \
|
||||
SFVARN(DMACH[n].ClockCounter, #n "ClockCounter")
|
||||
|
||||
SFDMACH(0),
|
||||
SFDMACH(1),
|
||||
SFDMACH(2),
|
||||
SFDMACH(3),
|
||||
SFDMACH(4),
|
||||
SFDMACH(5),
|
||||
SFDMACH(6),
|
||||
|
||||
#undef SFDMACH
|
||||
|
||||
SFVAR(lastts),
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "DMA");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
}
|
24
mednafen/psx-0925/dma.h
Normal file
24
mednafen/psx-0925/dma.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __MDFN_PSX_DMA_H
|
||||
#define __MDFN_PSX_DMA_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
bool DMA_GPUWriteActive(void);
|
||||
|
||||
pscpu_timestamp_t DMA_Update(const pscpu_timestamp_t timestamp);
|
||||
void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
void DMA_ResetTS(void);
|
||||
|
||||
void DMA_Power(void);
|
||||
|
||||
void DMA_Init(void);
|
||||
void DMA_Kill(void);
|
||||
|
||||
int DMA_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
906
mednafen/psx-0925/frontio.cpp
Normal file
906
mednafen/psx-0925/frontio.cpp
Normal file
@ -0,0 +1,906 @@
|
||||
/* 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 "psx.h"
|
||||
#include "frontio.h"
|
||||
#include "../FileWrapper.h"
|
||||
|
||||
#include "input/gamepad.h"
|
||||
#include "input/dualanalog.h"
|
||||
#include "input/dualshock.h"
|
||||
#include "input/mouse.h"
|
||||
#include "input/negcon.h"
|
||||
#include "input/guncon.h"
|
||||
#include "input/justifier.h"
|
||||
|
||||
#include "input/memcard.h"
|
||||
|
||||
#include "input/multitap.h"
|
||||
|
||||
#define PSX_FIODBGINFO(format, ...) { /* printf(format " -- timestamp=%d -- PAD temp\n", ## __VA_ARGS__, timestamp); */ }
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice::InputDevice()
|
||||
{
|
||||
}
|
||||
|
||||
InputDevice::~InputDevice()
|
||||
{
|
||||
}
|
||||
|
||||
void InputDevice::Power(void)
|
||||
{
|
||||
}
|
||||
|
||||
void InputDevice::Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice::ResetTS(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice::SetAMCT(bool)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice::SetCrosshairsColor(uint32 color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool InputDevice::RequireNoFrameskip(void)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
pscpu_timestamp_t InputDevice::GPULineHook(const pscpu_timestamp_t timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock)
|
||||
{
|
||||
return(PSX_EVENT_MAXTS);
|
||||
}
|
||||
|
||||
|
||||
void InputDevice::UpdateInput(const void *data)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InputDevice::SetDTR(bool new_dtr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool InputDevice::GetDSR(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
uint32 InputDevice::GetNVSize(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
void InputDevice::ReadNV(uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice::WriteNV(const uint8 *buffer, uint32 offset, uint32 count)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint64 InputDevice::GetNVDirtyCount(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
void InputDevice::ResetNVDirtyCount(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static INLINE unsigned EP_to_MP(unsigned ep)
|
||||
{
|
||||
#if 0
|
||||
return((bool)(ep & 0x4));
|
||||
#else
|
||||
return(ep == 1 || ep >= 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE unsigned EP_to_SP(unsigned ep)
|
||||
{
|
||||
#if 0
|
||||
return(ep & 0x3);
|
||||
#else
|
||||
if(ep < 2)
|
||||
return(0);
|
||||
else if(ep < 5)
|
||||
return(ep - 2 + 1);
|
||||
else
|
||||
return(ep - 5 + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FrontIO::MapDevicesToPorts(void)
|
||||
{
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
if(emulate_multitap[i])
|
||||
{
|
||||
Ports[i] = DevicesTap[i];
|
||||
MCPorts[i] = DummyDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ports[i] = Devices[i];
|
||||
MCPorts[i] = emulate_memcards[i] ? DevicesMC[i] : DummyDevice;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned mp = EP_to_MP(i);
|
||||
|
||||
if(emulate_multitap[mp])
|
||||
DevicesTap[mp]->SetSubDevice(EP_to_SP(i), Devices[i], emulate_memcards[i] ? DevicesMC[i] : DummyDevice);
|
||||
else
|
||||
DevicesTap[mp]->SetSubDevice(EP_to_SP(i), DummyDevice, DummyDevice);
|
||||
}
|
||||
}
|
||||
|
||||
FrontIO::FrontIO(bool emulate_memcards_[8], bool emulate_multitap_[2])
|
||||
{
|
||||
memcpy(emulate_memcards, emulate_memcards_, sizeof(emulate_memcards));
|
||||
memcpy(emulate_multitap, emulate_multitap_, sizeof(emulate_multitap));
|
||||
|
||||
DummyDevice = new InputDevice();
|
||||
|
||||
for(unsigned i = 0; i < 8; i++)
|
||||
{
|
||||
DeviceData[i] = NULL;
|
||||
Devices[i] = new InputDevice();
|
||||
DevicesMC[i] = Device_Memcard_Create();
|
||||
chair_colors[i] = 1 << 24;
|
||||
Devices[i]->SetCrosshairsColor(chair_colors[i]);
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
DevicesTap[i] = new InputDevice_Multitap();
|
||||
}
|
||||
|
||||
MapDevicesToPorts();
|
||||
}
|
||||
|
||||
void FrontIO::SetAMCT(bool enabled)
|
||||
{
|
||||
for(unsigned i = 0; i < 8; i++)
|
||||
{
|
||||
Devices[i]->SetAMCT(enabled);
|
||||
}
|
||||
amct_enabled = enabled;
|
||||
}
|
||||
|
||||
void FrontIO::SetCrosshairsColor(unsigned port, uint32 color)
|
||||
{
|
||||
assert(port >= 0 && port < 8);
|
||||
|
||||
chair_colors[port] = color;
|
||||
Devices[port]->SetCrosshairsColor(color);
|
||||
}
|
||||
|
||||
FrontIO::~FrontIO()
|
||||
{
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if(Devices[i])
|
||||
{
|
||||
delete Devices[i];
|
||||
Devices[i] = NULL;
|
||||
}
|
||||
if(DevicesMC[i])
|
||||
{
|
||||
delete DevicesMC[i];
|
||||
DevicesMC[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
if(DevicesTap[i])
|
||||
{
|
||||
delete DevicesTap[i];
|
||||
DevicesTap[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(DummyDevice)
|
||||
{
|
||||
delete DummyDevice;
|
||||
DummyDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pscpu_timestamp_t FrontIO::CalcNextEventTS(pscpu_timestamp_t timestamp, int32 next_event)
|
||||
{
|
||||
pscpu_timestamp_t ret;
|
||||
|
||||
if(ClockDivider > 0 && ClockDivider < next_event)
|
||||
next_event = ClockDivider;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
if(dsr_pulse_delay[i] > 0 && next_event > dsr_pulse_delay[i])
|
||||
next_event = dsr_pulse_delay[i];
|
||||
|
||||
ret = timestamp + next_event;
|
||||
|
||||
if(irq10_pulse_ts[0] < ret)
|
||||
ret = irq10_pulse_ts[0];
|
||||
|
||||
if(irq10_pulse_ts[1] < ret)
|
||||
ret = irq10_pulse_ts[1];
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void FrontIO::CheckStartStopPending(pscpu_timestamp_t timestamp, bool skip_event_set)
|
||||
{
|
||||
//const bool prior_ReceiveInProgress = ReceiveInProgress;
|
||||
//const bool prior_TransmitInProgress = TransmitInProgress;
|
||||
bool trigger_condition = false;
|
||||
|
||||
trigger_condition = (ReceivePending && (Control & 0x4)) || (TransmitPending && (Control & 0x1));
|
||||
|
||||
if(trigger_condition)
|
||||
{
|
||||
if(ReceivePending)
|
||||
{
|
||||
ReceivePending = false;
|
||||
ReceiveInProgress = true;
|
||||
ReceiveBufferAvail = false;
|
||||
ReceiveBuffer = 0;
|
||||
ReceiveBitCounter = 0;
|
||||
}
|
||||
|
||||
if(TransmitPending)
|
||||
{
|
||||
TransmitPending = false;
|
||||
TransmitInProgress = true;
|
||||
TransmitBitCounter = 0;
|
||||
}
|
||||
|
||||
ClockDivider = 0x44;
|
||||
}
|
||||
|
||||
if(!(Control & 0x5))
|
||||
{
|
||||
ReceiveInProgress = false;
|
||||
TransmitInProgress = false;
|
||||
}
|
||||
|
||||
if(!ReceiveInProgress && !TransmitInProgress)
|
||||
ClockDivider = 0;
|
||||
|
||||
if(!(skip_event_set))
|
||||
PSX_SetEventNT(PSX_EVENT_FIO, CalcNextEventTS(timestamp, 0x10000000));
|
||||
}
|
||||
|
||||
// DSR IRQ bit setting appears(from indirect tests on real PS1) to be level-sensitive, not edge-sensitive
|
||||
INLINE void FrontIO::DoDSRIRQ(void)
|
||||
{
|
||||
if(Control & 0x1000)
|
||||
{
|
||||
PSX_FIODBGINFO("[DSR] IRQ");
|
||||
istatus = true;
|
||||
IRQ_Assert(IRQ_SIO, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FrontIO::Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
assert(!(A & 0x1));
|
||||
|
||||
PSX_FIODBGINFO("[FIO] Write: %08x %08x", A, V);
|
||||
|
||||
Update(timestamp);
|
||||
|
||||
switch(A & 0xF)
|
||||
{
|
||||
case 0x0:
|
||||
TransmitBuffer = V;
|
||||
TransmitPending = true;
|
||||
TransmitInProgress = false;
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
Mode = V & 0x013F;
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
if(ClockDivider > 0 && ((V & 0x2000) != (Control & 0x2000)) && ((Control & 0x2) == (V & 0x2)) )
|
||||
fprintf(stderr, "FIO device selection changed during comm %04x->%04x", Control, V);
|
||||
|
||||
//printf("Control: %d, %04x\n", timestamp, V);
|
||||
Control = V & 0x3F2F;
|
||||
|
||||
if(V & 0x10)
|
||||
{
|
||||
istatus = false;
|
||||
IRQ_Assert(IRQ_SIO, false);
|
||||
}
|
||||
|
||||
if(V & 0x40) // Reset
|
||||
{
|
||||
istatus = false;
|
||||
IRQ_Assert(IRQ_SIO, false);
|
||||
|
||||
ClockDivider = 0;
|
||||
ReceivePending = false;
|
||||
TransmitPending = false;
|
||||
|
||||
ReceiveInProgress = false;
|
||||
TransmitInProgress = false;
|
||||
|
||||
ReceiveBufferAvail = false;
|
||||
|
||||
TransmitBuffer = 0;
|
||||
ReceiveBuffer = 0;
|
||||
|
||||
ReceiveBitCounter = 0;
|
||||
TransmitBitCounter = 0;
|
||||
|
||||
Mode = 0;
|
||||
Control = 0;
|
||||
Baudrate = 0;
|
||||
}
|
||||
|
||||
Ports[0]->SetDTR((Control & 0x2) && !(Control & 0x2000));
|
||||
MCPorts[0]->SetDTR((Control & 0x2) && !(Control & 0x2000));
|
||||
Ports[1]->SetDTR((Control & 0x2) && (Control & 0x2000));
|
||||
MCPorts[1]->SetDTR((Control & 0x2) && (Control & 0x2000));
|
||||
|
||||
#if 1
|
||||
if(!((Control & 0x2) && !(Control & 0x2000)))
|
||||
{
|
||||
dsr_pulse_delay[0] = 0;
|
||||
dsr_pulse_delay[2] = 0;
|
||||
dsr_active_until_ts[0] = -1;
|
||||
dsr_active_until_ts[2] = -1;
|
||||
}
|
||||
|
||||
if(!((Control & 0x2) && (Control & 0x2000)))
|
||||
{
|
||||
dsr_pulse_delay[1] = 0;
|
||||
dsr_pulse_delay[3] = 0;
|
||||
dsr_active_until_ts[1] = -1;
|
||||
dsr_active_until_ts[3] = -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
// TODO: Uncomment out in the future once our CPU emulation is a bit more accurate with timing, to prevent causing problems with games
|
||||
// that may clear the IRQ in an unsafe pattern that only works because its execution was slow enough to allow DSR to go inactive. (Whether or not
|
||||
// such games even exist though is unknown!)
|
||||
//if(timestamp < dsr_active_until_ts[0] || timestamp < dsr_active_until_ts[1] || timestamp < dsr_active_until_ts[2] || timestamp < dsr_active_until_ts[3])
|
||||
// DoDSRIRQ();
|
||||
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
Baudrate = V;
|
||||
//MDFN_DispMessage("%02x\n", V);
|
||||
break;
|
||||
}
|
||||
|
||||
CheckStartStopPending(timestamp, false);
|
||||
}
|
||||
|
||||
|
||||
uint32 FrontIO::Read(pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
assert(!(A & 0x1));
|
||||
|
||||
Update(timestamp);
|
||||
|
||||
switch(A & 0xF)
|
||||
{
|
||||
case 0x0:
|
||||
ret = ReceiveBuffer | (ReceiveBuffer << 8) | (ReceiveBuffer << 16) | (ReceiveBuffer << 24);
|
||||
ReceiveBufferAvail = false;
|
||||
ReceivePending = true;
|
||||
ReceiveInProgress = false;
|
||||
CheckStartStopPending(timestamp, false);
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
ret = 0;
|
||||
|
||||
if(!TransmitPending && !TransmitInProgress)
|
||||
ret |= 0x1;
|
||||
|
||||
if(ReceiveBufferAvail)
|
||||
ret |= 0x2;
|
||||
|
||||
if(timestamp < dsr_active_until_ts[0] || timestamp < dsr_active_until_ts[1] || timestamp < dsr_active_until_ts[2] || timestamp < dsr_active_until_ts[3])
|
||||
ret |= 0x80;
|
||||
|
||||
if(istatus)
|
||||
ret |= 0x200;
|
||||
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
ret = Mode;
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
ret = Control;
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
ret = Baudrate;
|
||||
break;
|
||||
}
|
||||
|
||||
if((A & 0xF) != 0x4)
|
||||
PSX_FIODBGINFO("[FIO] Read: %08x %08x", A, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
pscpu_timestamp_t FrontIO::Update(pscpu_timestamp_t timestamp)
|
||||
{
|
||||
int32 clocks = timestamp - lastts;
|
||||
bool need_start_stop_check = false;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
if(dsr_pulse_delay[i] > 0)
|
||||
{
|
||||
dsr_pulse_delay[i] -= clocks;
|
||||
if(dsr_pulse_delay[i] <= 0)
|
||||
{
|
||||
dsr_active_until_ts[i] = timestamp + 32 + dsr_pulse_delay[i];
|
||||
DoDSRIRQ();
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
if(timestamp >= irq10_pulse_ts[i])
|
||||
{
|
||||
//printf("Yay: %d %u\n", i, timestamp);
|
||||
irq10_pulse_ts[i] = PSX_EVENT_MAXTS;
|
||||
IRQ_Assert(IRQ_PIO, true);
|
||||
IRQ_Assert(IRQ_PIO, false);
|
||||
}
|
||||
}
|
||||
|
||||
if(ClockDivider > 0)
|
||||
{
|
||||
ClockDivider -= clocks;
|
||||
|
||||
while(ClockDivider <= 0)
|
||||
{
|
||||
if(ReceiveInProgress || TransmitInProgress)
|
||||
{
|
||||
bool rxd = 0, txd = 0;
|
||||
const uint32 BCMask = 0x07;
|
||||
|
||||
if(TransmitInProgress)
|
||||
{
|
||||
txd = (TransmitBuffer >> TransmitBitCounter) & 1;
|
||||
TransmitBitCounter = (TransmitBitCounter + 1) & BCMask;
|
||||
if(!TransmitBitCounter)
|
||||
{
|
||||
need_start_stop_check = true;
|
||||
PSX_FIODBGINFO("[FIO] Data transmitted: %08x", TransmitBuffer);
|
||||
TransmitInProgress = false;
|
||||
|
||||
if(Control & 0x400)
|
||||
{
|
||||
istatus = true;
|
||||
IRQ_Assert(IRQ_SIO, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rxd = Ports[0]->Clock(txd, dsr_pulse_delay[0]) & Ports[1]->Clock(txd, dsr_pulse_delay[1]) &
|
||||
MCPorts[0]->Clock(txd, dsr_pulse_delay[2]) & MCPorts[1]->Clock(txd, dsr_pulse_delay[3]);
|
||||
|
||||
if(ReceiveInProgress)
|
||||
{
|
||||
ReceiveBuffer &= ~(1 << ReceiveBitCounter);
|
||||
ReceiveBuffer |= rxd << ReceiveBitCounter;
|
||||
|
||||
ReceiveBitCounter = (ReceiveBitCounter + 1) & BCMask;
|
||||
|
||||
if(!ReceiveBitCounter)
|
||||
{
|
||||
need_start_stop_check = true;
|
||||
PSX_FIODBGINFO("[FIO] Data received: %08x", ReceiveBuffer);
|
||||
|
||||
ReceiveInProgress = false;
|
||||
ReceiveBufferAvail = true;
|
||||
|
||||
if(Control & 0x800)
|
||||
{
|
||||
istatus = true;
|
||||
IRQ_Assert(IRQ_SIO, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClockDivider += 0x44; //88; //99;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lastts = timestamp;
|
||||
|
||||
|
||||
if(need_start_stop_check)
|
||||
{
|
||||
CheckStartStopPending(timestamp, true);
|
||||
}
|
||||
|
||||
return(CalcNextEventTS(timestamp, 0x10000000));
|
||||
}
|
||||
|
||||
void FrontIO::ResetTS(void)
|
||||
{
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
Devices[i]->Update(lastts); // Maybe eventually call Update() from FrontIO::Update() and remove this(but would hurt speed)?
|
||||
Devices[i]->ResetTS();
|
||||
|
||||
DevicesMC[i]->Update(lastts); // Maybe eventually call Update() from FrontIO::Update() and remove this(but would hurt speed)?
|
||||
DevicesMC[i]->ResetTS();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
DevicesTap[i]->Update(lastts);
|
||||
DevicesTap[i]->ResetTS();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
if(irq10_pulse_ts[i] != PSX_EVENT_MAXTS)
|
||||
irq10_pulse_ts[i] -= lastts;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(dsr_active_until_ts[i] >= 0)
|
||||
{
|
||||
dsr_active_until_ts[i] -= lastts;
|
||||
//printf("SPOOONY: %d %d\n", i, dsr_active_until_ts[i]);
|
||||
}
|
||||
}
|
||||
lastts = 0;
|
||||
}
|
||||
|
||||
|
||||
void FrontIO::Power(void)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
dsr_pulse_delay[i] = 0;
|
||||
dsr_active_until_ts[i] = -1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
irq10_pulse_ts[i] = PSX_EVENT_MAXTS;
|
||||
}
|
||||
|
||||
lastts = 0;
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
ClockDivider = 0;
|
||||
|
||||
ReceivePending = false;
|
||||
TransmitPending = false;
|
||||
|
||||
ReceiveInProgress = false;
|
||||
TransmitInProgress = false;
|
||||
|
||||
ReceiveBufferAvail = false;
|
||||
|
||||
TransmitBuffer = 0;
|
||||
ReceiveBuffer = 0;
|
||||
|
||||
ReceiveBitCounter = 0;
|
||||
TransmitBitCounter = 0;
|
||||
|
||||
Mode = 0;
|
||||
Control = 0;
|
||||
Baudrate = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
Devices[i]->Power();
|
||||
DevicesMC[i]->Power();
|
||||
}
|
||||
|
||||
istatus = false;
|
||||
}
|
||||
|
||||
void FrontIO::UpdateInput(void)
|
||||
{
|
||||
for(int i = 0; i < 8; i++)
|
||||
Devices[i]->UpdateInput(DeviceData[i]);
|
||||
}
|
||||
|
||||
void FrontIO::SetInput(unsigned int port, const char *type, void *ptr)
|
||||
{
|
||||
delete Devices[port];
|
||||
Devices[port] = NULL;
|
||||
|
||||
if(port < 2)
|
||||
irq10_pulse_ts[port] = PSX_EVENT_MAXTS;
|
||||
|
||||
if(!strcmp(type, "gamepad"))
|
||||
Devices[port] = Device_Gamepad_Create();
|
||||
else if(!strcmp(type, "dualanalog"))
|
||||
Devices[port] = Device_DualAnalog_Create(false);
|
||||
else if(!strcmp(type, "analogjoy"))
|
||||
Devices[port] = Device_DualAnalog_Create(true);
|
||||
else if(!strcmp(type, "dualshock"))
|
||||
{
|
||||
char name[256];
|
||||
trio_snprintf(name, 256, _("DualShock on port %u"), port + 1);
|
||||
Devices[port] = Device_DualShock_Create(std::string(name));
|
||||
}
|
||||
else if(!strcmp(type, "mouse"))
|
||||
Devices[port] = Device_Mouse_Create();
|
||||
else if(!strcmp(type, "negcon"))
|
||||
Devices[port] = Device_neGcon_Create();
|
||||
else if(!strcmp(type, "guncon"))
|
||||
Devices[port] = Device_GunCon_Create();
|
||||
else if(!strcmp(type, "justifier"))
|
||||
Devices[port] = Device_Justifier_Create();
|
||||
else
|
||||
Devices[port] = new InputDevice();
|
||||
|
||||
Devices[port]->SetAMCT(amct_enabled);
|
||||
Devices[port]->SetCrosshairsColor(chair_colors[port]);
|
||||
DeviceData[port] = ptr;
|
||||
|
||||
MapDevicesToPorts();
|
||||
}
|
||||
|
||||
uint64 FrontIO::GetMemcardDirtyCount(unsigned int which)
|
||||
{
|
||||
assert(which < 8);
|
||||
|
||||
return(DevicesMC[which]->GetNVDirtyCount());
|
||||
}
|
||||
|
||||
void FrontIO::LoadMemcard(unsigned int which, const char *path)
|
||||
{
|
||||
assert(which < 8);
|
||||
|
||||
try
|
||||
{
|
||||
if(DevicesMC[which]->GetNVSize())
|
||||
{
|
||||
FileWrapper mf(path, FileWrapper::MODE_READ);
|
||||
std::vector<uint8> tmpbuf;
|
||||
|
||||
tmpbuf.resize(DevicesMC[which]->GetNVSize());
|
||||
|
||||
if(mf.size() != (int64)tmpbuf.size())
|
||||
throw(MDFN_Error(0, _("Memory card file \"%s\" is an incorrect size(%d bytes). The correct size is %d bytes."), path, (int)mf.size(), (int)tmpbuf.size()));
|
||||
|
||||
mf.read(&tmpbuf[0], tmpbuf.size());
|
||||
|
||||
DevicesMC[which]->WriteNV(&tmpbuf[0], 0, tmpbuf.size());
|
||||
DevicesMC[which]->ResetNVDirtyCount(); // There's no need to rewrite the file if it's the same data.
|
||||
}
|
||||
}
|
||||
catch(MDFN_Error &e)
|
||||
{
|
||||
if(e.GetErrno() != ENOENT)
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
|
||||
void FrontIO::SaveMemcard(unsigned int which, const char *path)
|
||||
{
|
||||
assert(which < 8);
|
||||
|
||||
if(DevicesMC[which]->GetNVSize() && DevicesMC[which]->GetNVDirtyCount())
|
||||
{
|
||||
FileWrapper mf(path, FileWrapper::MODE_WRITE); // TODO: MODE_WRITE_ATOMIC_OVERWRITE
|
||||
std::vector<uint8> tmpbuf;
|
||||
|
||||
tmpbuf.resize(DevicesMC[which]->GetNVSize());
|
||||
|
||||
DevicesMC[which]->ReadNV(&tmpbuf[0], 0, tmpbuf.size());
|
||||
mf.write(&tmpbuf[0], tmpbuf.size());
|
||||
|
||||
mf.close(); // Call before resetting the NV dirty count!
|
||||
|
||||
DevicesMC[which]->ResetNVDirtyCount();
|
||||
}
|
||||
}
|
||||
|
||||
bool FrontIO::RequireNoFrameskip(void)
|
||||
{
|
||||
for(unsigned i = 0; i < 8; i++)
|
||||
if(Devices[i]->RequireNoFrameskip())
|
||||
return(true);
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
void FrontIO::GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock)
|
||||
{
|
||||
Update(timestamp);
|
||||
|
||||
for(unsigned i = 0; i < 8; i++)
|
||||
{
|
||||
pscpu_timestamp_t plts = Devices[i]->GPULineHook(line_timestamp, vsync, pixels, format, width, pix_clock_offset, pix_clock);
|
||||
|
||||
if(i < 2)
|
||||
{
|
||||
irq10_pulse_ts[i] = plts;
|
||||
|
||||
if(irq10_pulse_ts[i] <= timestamp)
|
||||
{
|
||||
irq10_pulse_ts[i] = PSX_EVENT_MAXTS;
|
||||
IRQ_Assert(IRQ_PIO, true);
|
||||
IRQ_Assert(IRQ_PIO, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PSX_SetEventNT(PSX_EVENT_FIO, CalcNextEventTS(timestamp, 0x10000000));
|
||||
}
|
||||
|
||||
static InputDeviceInfoStruct InputDeviceInfoPSXPort[] =
|
||||
{
|
||||
// None
|
||||
{
|
||||
"none",
|
||||
"none",
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
|
||||
// Gamepad(SCPH-1080)
|
||||
{
|
||||
"gamepad",
|
||||
"Digital Gamepad",
|
||||
"PlayStation digital gamepad; SCPH-1080.",
|
||||
NULL,
|
||||
sizeof(Device_Gamepad_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_Gamepad_IDII,
|
||||
},
|
||||
|
||||
// Dual Shock Gamepad(SCPH-1200)
|
||||
{
|
||||
"dualshock",
|
||||
"DualShock",
|
||||
"DualShock gamepad; SCPH-1200. Emulation in Mednafen includes the analog mode toggle button.",
|
||||
NULL,
|
||||
sizeof(Device_DualShock_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_DualShock_IDII,
|
||||
},
|
||||
|
||||
// Dual Analog Gamepad(SCPH-1180), forced to analog mode.
|
||||
{
|
||||
"dualanalog",
|
||||
"Dual Analog",
|
||||
"Dual Analog gamepad; SCPH-1180. It is the predecessor/prototype to the more advanced DualShock. Emulated in Mednafen as forced to analog mode, and without rumble.",
|
||||
NULL,
|
||||
sizeof(Device_DualAnalog_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_DualAnalog_IDII,
|
||||
},
|
||||
|
||||
|
||||
// Analog joystick(SCPH-1110), forced to analog mode - emulated through a tweak to dual analog gamepad emulation.
|
||||
{
|
||||
"analogjoy",
|
||||
"Analog Joystick",
|
||||
"Flight-game-oriented dual-joystick controller; SCPH-1110. Emulated in Mednafen as forced to analog mode.",
|
||||
NULL,
|
||||
sizeof(Device_AnalogJoy_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_AnalogJoy_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"mouse",
|
||||
"Mouse",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(Device_Mouse_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_Mouse_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"negcon",
|
||||
"neGcon",
|
||||
"Namco's unconventional twisty racing-game-oriented gamepad; NPC-101.",
|
||||
NULL,
|
||||
sizeof(Device_neGcon_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_neGcon_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"guncon",
|
||||
"GunCon",
|
||||
"Namco's light gun; NPC-103.",
|
||||
NULL,
|
||||
sizeof(Device_GunCon_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_GunCon_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"justifier",
|
||||
"Konami Justifier",
|
||||
"Konami's light gun; SLUH-00017. Rumored to be wrought of the coagulated rage of all who tried to shoot The Dog. If the game you want to play supports the \"GunCon\", you should use that instead. NOTE: Currently does not work properly when on any of ports 1B-1D and 2B-2D.",
|
||||
NULL,
|
||||
sizeof(Device_Justifier_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_Justifier_IDII,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct PortInfo[] =
|
||||
{
|
||||
{ "port1", "Port 1/1A", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port2", "Port 2/2A", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port3", "Port 1B", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port4", "Port 1C", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port5", "Port 1D", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port6", "Port 2B", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port7", "Port 2C", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
{ "port8", "Port 2D", sizeof(InputDeviceInfoPSXPort) / sizeof(InputDeviceInfoStruct), InputDeviceInfoPSXPort, "gamepad" },
|
||||
};
|
||||
|
||||
InputInfoStruct FIO_InputInfo =
|
||||
{
|
||||
sizeof(PortInfo) / sizeof(InputPortInfoStruct),
|
||||
PortInfo
|
||||
};
|
||||
|
||||
|
||||
}
|
142
mednafen/psx-0925/frontio.h
Normal file
142
mednafen/psx-0925/frontio.h
Normal file
@ -0,0 +1,142 @@
|
||||
#ifndef __MDFN_PSX_FRONTIO_H
|
||||
#define __MDFN_PSX_FRONTIO_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_Multitap;
|
||||
|
||||
class InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice();
|
||||
virtual ~InputDevice();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
|
||||
virtual bool RequireNoFrameskip(void);
|
||||
virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock);
|
||||
|
||||
virtual void Update(const pscpu_timestamp_t timestamp); // Partially-implemented, don't rely on for timing any more fine-grained than a video frame for now.
|
||||
virtual void ResetTS(void);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetAMCT(bool enabled);
|
||||
virtual void SetCrosshairsColor(uint32 color);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void); // Currently unused.
|
||||
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
//
|
||||
//
|
||||
virtual uint32 GetNVSize(void);
|
||||
virtual void ReadNV(uint8 *buffer, uint32 offset, uint32 count);
|
||||
virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 count);
|
||||
|
||||
//
|
||||
// Dirty count should be incremented on each call to a method this class that causes at least 1 write to occur to the
|
||||
// nonvolatile memory(IE Clock() in the correct command phase, and WriteNV()).
|
||||
//
|
||||
virtual uint64 GetNVDirtyCount(void);
|
||||
virtual void ResetNVDirtyCount(void);
|
||||
};
|
||||
|
||||
class FrontIO
|
||||
{
|
||||
public:
|
||||
|
||||
FrontIO(bool emulate_memcards_[8], bool emulate_multitap_[2]);
|
||||
~FrontIO();
|
||||
|
||||
void Power(void);
|
||||
void Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
uint32 Read(pscpu_timestamp_t timestamp, uint32 A);
|
||||
pscpu_timestamp_t CalcNextEventTS(pscpu_timestamp_t timestamp, int32 next_event);
|
||||
pscpu_timestamp_t Update(pscpu_timestamp_t timestamp);
|
||||
void ResetTS(void);
|
||||
|
||||
bool RequireNoFrameskip(void);
|
||||
void GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock);
|
||||
|
||||
void UpdateInput(void);
|
||||
void SetInput(unsigned int port, const char *type, void *ptr);
|
||||
void SetAMCT(bool enabled);
|
||||
void SetCrosshairsColor(unsigned port, uint32 color);
|
||||
|
||||
uint64 GetMemcardDirtyCount(unsigned int which);
|
||||
void LoadMemcard(unsigned int which, const char *path);
|
||||
void SaveMemcard(unsigned int which, const char *path); //, bool force_save = false);
|
||||
|
||||
private:
|
||||
|
||||
void DoDSRIRQ(void);
|
||||
void CheckStartStopPending(pscpu_timestamp_t timestamp, bool skip_event_set = false);
|
||||
|
||||
void MapDevicesToPorts(void);
|
||||
|
||||
bool emulate_memcards[8];
|
||||
bool emulate_multitap[2];
|
||||
|
||||
InputDevice *Ports[2];
|
||||
InputDevice *MCPorts[2];
|
||||
|
||||
InputDevice *DummyDevice;
|
||||
InputDevice_Multitap *DevicesTap[2];
|
||||
|
||||
InputDevice *Devices[8];
|
||||
void *DeviceData[8];
|
||||
|
||||
InputDevice *DevicesMC[8];
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
int32 ClockDivider;
|
||||
|
||||
bool ReceivePending;
|
||||
bool TransmitPending;
|
||||
|
||||
bool ReceiveInProgress;
|
||||
bool TransmitInProgress;
|
||||
|
||||
bool ReceiveBufferAvail;
|
||||
|
||||
uint8 ReceiveBuffer;
|
||||
uint8 TransmitBuffer;
|
||||
|
||||
int32 ReceiveBitCounter;
|
||||
int32 TransmitBitCounter;
|
||||
|
||||
uint16 Mode;
|
||||
uint16 Control;
|
||||
uint16 Baudrate;
|
||||
|
||||
|
||||
bool istatus;
|
||||
//
|
||||
//
|
||||
pscpu_timestamp_t irq10_pulse_ts[2];
|
||||
|
||||
int32 dsr_pulse_delay[4];
|
||||
int32 dsr_active_until_ts[4];
|
||||
int32 lastts;
|
||||
//
|
||||
//
|
||||
bool amct_enabled;
|
||||
uint32 chair_colors[8];
|
||||
};
|
||||
|
||||
extern InputInfoStruct FIO_InputInfo;
|
||||
|
||||
}
|
||||
#endif
|
1365
mednafen/psx-0925/gpu.cpp
Normal file
1365
mednafen/psx-0925/gpu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
325
mednafen/psx-0925/gpu.h
Normal file
325
mednafen/psx-0925/gpu.h
Normal file
@ -0,0 +1,325 @@
|
||||
// WARNING WARNING WARNING: ONLY use CanRead() method of BlitterFIFO, and NOT CanWrite(), since the FIFO is larger than the actual PS1 GPU FIFO to accommodate
|
||||
// our lack of fancy superscalarish command sequencer.
|
||||
|
||||
#ifndef __MDFN_PSX_GPU_H
|
||||
#define __MDFN_PSX_GPU_H
|
||||
|
||||
#include "../cdrom/SimpleFIFO.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class PS_GPU;
|
||||
|
||||
struct CTEntry
|
||||
{
|
||||
uint8 len;
|
||||
uint8 fifo_fb_len;
|
||||
bool ss_cmd;
|
||||
const char *name;
|
||||
void (PS_GPU::*func[8])(const uint32 *cb);
|
||||
};
|
||||
|
||||
struct tri_vertex
|
||||
{
|
||||
int32 x, y;
|
||||
int32 u, v;
|
||||
int32 r, g, b;
|
||||
};
|
||||
|
||||
struct i_group;
|
||||
struct i_deltas;
|
||||
|
||||
struct line_point
|
||||
{
|
||||
int32 x, y;
|
||||
uint8 r, g, b;
|
||||
};
|
||||
|
||||
class PS_GPU
|
||||
{
|
||||
public:
|
||||
|
||||
PS_GPU(bool pal_clock_and_tv);
|
||||
~PS_GPU();
|
||||
|
||||
void Power(void);
|
||||
|
||||
void ResetTS(void);
|
||||
|
||||
void StartFrame(EmulateSpecStruct *espec);
|
||||
|
||||
pscpu_timestamp_t Update(const pscpu_timestamp_t timestamp);
|
||||
|
||||
void Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
|
||||
INLINE bool CalcFIFOReadyBit(void)
|
||||
{
|
||||
if(InCmd & (INCMD_PLINE | INCMD_QUAD))
|
||||
return(false);
|
||||
|
||||
if(BlitterFIFO.CanRead() == 0)
|
||||
return(true);
|
||||
|
||||
if(InCmd & (INCMD_FBREAD | INCMD_FBWRITE))
|
||||
return(false);
|
||||
|
||||
if(BlitterFIFO.CanRead() >= Commands[0][BlitterFIFO.ReadUnit(true) >> 24].fifo_fb_len)
|
||||
return(false);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
INLINE bool DMACanWrite(void)
|
||||
{
|
||||
return CalcFIFOReadyBit();
|
||||
}
|
||||
|
||||
INLINE void AbortDMA(void)
|
||||
{
|
||||
BlitterFIFO.Flush();
|
||||
InCmd = INCMD_NONE;
|
||||
}
|
||||
|
||||
void WriteDMA(uint32 V);
|
||||
|
||||
uint32 Read(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
inline int32 GetScanlineNum(void)
|
||||
{
|
||||
return(scanline);
|
||||
}
|
||||
|
||||
INLINE uint16 PeekRAM(uint32 A)
|
||||
{
|
||||
return(GPURAM[(A >> 10) & 0x1FF][A & 0x3FF]);
|
||||
}
|
||||
|
||||
INLINE void PokeRAM(uint32 A, uint16 V)
|
||||
{
|
||||
GPURAM[(A >> 10) & 0x1FF][A & 0x3FF] = V;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void ProcessFIFO(void);
|
||||
void WriteCB(uint32 data);
|
||||
void SoftReset(void);
|
||||
|
||||
// Y, X
|
||||
uint16 GPURAM[512][1024];
|
||||
|
||||
uint32 DMAControl;
|
||||
|
||||
//
|
||||
// Drawing stuff
|
||||
//
|
||||
//int32 TexPageX; // 0, 64, 128, 192, etc up to 960
|
||||
//int32 TexPageY; // 0 or 256
|
||||
//uint32 abr; // Semi-transparency mode(0~3)
|
||||
//bool dtd; // Dithering enable
|
||||
|
||||
int32 ClipX0;
|
||||
int32 ClipY0;
|
||||
int32 ClipX1;
|
||||
int32 ClipY1;
|
||||
|
||||
int32 OffsX;
|
||||
int32 OffsY;
|
||||
|
||||
bool dtd;
|
||||
bool dfe;
|
||||
|
||||
uint32 MaskSetOR;
|
||||
uint32 MaskEvalAND;
|
||||
|
||||
uint8 tww, twh, twx, twy;
|
||||
struct
|
||||
{
|
||||
uint8 TexWindowXLUT_Pre[16];
|
||||
uint8 TexWindowXLUT[256];
|
||||
uint8 TexWindowXLUT_Post[16];
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
uint8 TexWindowYLUT_Pre[16];
|
||||
uint8 TexWindowYLUT[256];
|
||||
uint8 TexWindowYLUT_Post[16];
|
||||
};
|
||||
void RecalcTexWindowLUT(void);
|
||||
|
||||
int32 TexPageX;
|
||||
int32 TexPageY;
|
||||
|
||||
uint32 SpriteFlip;
|
||||
|
||||
uint32 abr;
|
||||
uint32 TexMode;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8 RGB8SAT_Under[256];
|
||||
uint8 RGB8SAT[256];
|
||||
uint8 RGB8SAT_Over[256];
|
||||
};
|
||||
|
||||
uint8 DitherLUT[4][4][512]; // Y, X, 8-bit source value(256 extra for saturation)
|
||||
|
||||
bool LineSkipTest(unsigned y);
|
||||
|
||||
template<int BlendMode, bool MaskEval_TA, bool textured>
|
||||
void PlotPixel(int32 x, int32 y, uint16 pix);
|
||||
|
||||
template<uint32 TexMode_TA>
|
||||
uint16 GetTexel(uint32 clut_offset, int32 u, int32 v);
|
||||
|
||||
uint16 ModTexel(uint16 texel, int32 r, int32 g, int32 b, const int32 dither_x, const int32 dither_y);
|
||||
|
||||
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode, bool MaskEval_TA>
|
||||
void DrawSpan(int y, uint32 clut_offset, const int32 x_start, const int32 x_bound, const int32 bv_x, i_group ig, const i_deltas &idl);
|
||||
|
||||
template<bool shaded, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
void DrawTriangle(tri_vertex *vertices, uint32 clut);
|
||||
|
||||
template<int numvertices, bool shaded, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
void Command_DrawPolygon(const uint32 *cb);
|
||||
|
||||
template<bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA, bool FlipX, bool FlipY>
|
||||
void DrawSprite(int32 x_arg, int32 y_arg, int32 w, int32 h, uint8 u_arg, uint8 v_arg, uint32 color, uint32 clut_offset);
|
||||
|
||||
template<uint8 raw_size, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
void Command_DrawSprite(const uint32 *cb);
|
||||
|
||||
template<bool goraud, int BlendMode, bool MaskEval_TA>
|
||||
void DrawLine(line_point *vertices);
|
||||
|
||||
template<bool polyline, bool goraud, int BlendMode, bool MaskEval_TA>
|
||||
void Command_DrawLine(const uint32 *cb);
|
||||
|
||||
void Command_ClearCache(const uint32 *cb);
|
||||
|
||||
void Command_FBFill(const uint32 *cb);
|
||||
void Command_FBCopy(const uint32 *cb);
|
||||
void Command_FBWrite(const uint32 *cb);
|
||||
void Command_FBRead(const uint32 *cb);
|
||||
|
||||
void Command_DrawMode(const uint32 *cb);
|
||||
void Command_TexWindow(const uint32 *cb);
|
||||
void Command_Clip0(const uint32 *cb);
|
||||
void Command_Clip1(const uint32 *cb);
|
||||
void Command_DrawingOffset(const uint32 *cb);
|
||||
void Command_MaskSetting(const uint32 *cb);
|
||||
|
||||
static CTEntry Commands[4][256];
|
||||
|
||||
SimpleFIFO<uint32> BlitterFIFO;
|
||||
|
||||
uint32 DataReadBuffer;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// Powers of 2 for faster multiple equality testing(just for multi-testing; InCmd itself will only contain 0, or a power of 2).
|
||||
enum
|
||||
{
|
||||
INCMD_NONE = 0,
|
||||
INCMD_PLINE = (1 << 0),
|
||||
INCMD_QUAD = (1 << 1),
|
||||
INCMD_FBWRITE = (1 << 2),
|
||||
INCMD_FBREAD = (1 << 3)
|
||||
};
|
||||
uint8 InCmd;
|
||||
uint8 InCmd_CC;
|
||||
|
||||
tri_vertex InQuad_F3Vertices[3];
|
||||
uint32 InQuad_clut;
|
||||
|
||||
line_point InPLine_PrevPoint;
|
||||
|
||||
uint32 FBRW_X;
|
||||
uint32 FBRW_Y;
|
||||
uint32 FBRW_W;
|
||||
uint32 FBRW_H;
|
||||
uint32 FBRW_CurY;
|
||||
uint32 FBRW_CurX;
|
||||
|
||||
//
|
||||
// Display Parameters
|
||||
//
|
||||
uint32 DisplayMode;
|
||||
|
||||
bool DisplayOff;
|
||||
uint32 DisplayFB_XStart;
|
||||
uint32 DisplayFB_YStart;
|
||||
|
||||
uint32 HorizStart;
|
||||
uint32 HorizEnd;
|
||||
|
||||
uint32 VertStart;
|
||||
uint32 VertEnd;
|
||||
|
||||
//
|
||||
// Display work vars
|
||||
//
|
||||
/*
|
||||
uint32 DisplayMode_Latch;
|
||||
|
||||
bool DisplayOff_Latch;
|
||||
uint32 DisplayFB_XStart_Latch;
|
||||
uint32 DisplayFB_YStart_Latch;
|
||||
|
||||
uint32 HorizStart_Latch;
|
||||
uint32 HorizEnd_Latch;
|
||||
|
||||
uint32 VertStart_Latch;
|
||||
uint32 VertEnd_Latch;
|
||||
*/
|
||||
uint32 DisplayFB_CurYOffset;
|
||||
uint32 DisplayFB_CurLineYReadout;
|
||||
|
||||
uint32 DisplayHeightCounter;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
uint32 LinesPerField;
|
||||
uint32 VisibleStartLine;
|
||||
bool FrameInterlaced;
|
||||
bool PALMode;
|
||||
bool HeightMode;
|
||||
uint32 scanline;
|
||||
bool field;
|
||||
bool field_atvs;
|
||||
bool PhaseChange;
|
||||
|
||||
uint32 DotClockCounter;
|
||||
|
||||
uint64 GPUClockCounter;
|
||||
uint32 GPUClockRatio;
|
||||
int32 LineClockCounter;
|
||||
int32 LinePhase;
|
||||
|
||||
int32 DrawTimeAvail;
|
||||
|
||||
pscpu_timestamp_t lastts;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
EmulateSpecStruct *espec;
|
||||
MDFN_Surface *surface;
|
||||
MDFN_Rect *DisplayRect;
|
||||
MDFN_Rect *LineWidths;
|
||||
bool skip;
|
||||
bool HardwarePALType;
|
||||
|
||||
uint32 OutputLUT[32768];
|
||||
void ReorderRGB_Var(uint32 out_Rshift, uint32 out_Gshift, uint32 out_Bshift, bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x);
|
||||
|
||||
template<uint32 out_Rshift, uint32 out_Gshift, uint32 out_Bshift>
|
||||
void ReorderRGB(bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x) NO_INLINE;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
195
mednafen/psx-0925/gpu_command_table.inc
Normal file
195
mednafen/psx-0925/gpu_command_table.inc
Normal file
@ -0,0 +1,195 @@
|
||||
#define POLY_HELPER_SUB(cv, tm, mam) \
|
||||
&PS_GPU::Command_DrawPolygon<3 + ((cv & 0x8) >> 3), ((cv & 0x10) >> 4), ((cv & 0x4) >> 2), ((cv & 0x2) >> 1) ? BLENDMODE_MAC : -1, ((cv & 1) ^ 1) & ((cv & 0x4) >> 2), tm, mam >
|
||||
|
||||
#define POLY_HELPER(cv) { 1 + (3 /*+ ((cv & 0x8) >> 3)*/) * ( 1 + ((cv & 0x4) >> 2) + ((cv & 0x10) >> 4) ) - ((cv & 0x10) >> 4), \
|
||||
1, false, "Polygon", { POLY_HELPER_SUB(cv, ((cv & 0x4) ? 0 : 0), 0), POLY_HELPER_SUB(cv, ((cv & 0x4) ? 1 : 0), 0), \
|
||||
POLY_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 0), POLY_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 0), \
|
||||
POLY_HELPER_SUB(cv, ((cv & 0x4) ? 0 : 0), 1), POLY_HELPER_SUB(cv, ((cv & 0x4) ? 1 : 0), 1), \
|
||||
POLY_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 1), POLY_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 1), \
|
||||
} }
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
#define SPR_HELPER_SUB(cv, tm, mam) &PS_GPU::Command_DrawSprite<(cv >> 3) & 0x3, ((cv & 0x4) >> 2), ((cv & 0x2) >> 1) ? BLENDMODE_MAC : -1, ((cv & 1) ^ 1) & ((cv & 0x4) >> 2), tm, mam>
|
||||
|
||||
#define SPR_HELPER(cv) { 2 + ((cv & 0x4) >> 2) + ((cv & 0x18) ? 0 : 1), 2 | ((cv & 0x4) >> 2) | ((cv & 0x18) ? 0 : 1), false, "Sprite", { \
|
||||
SPR_HELPER_SUB(cv, ((cv & 0x4) ? 0 : 0), 0), SPR_HELPER_SUB(cv, ((cv & 0x4) ? 1 : 0), 0), \
|
||||
SPR_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 0), SPR_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 0), \
|
||||
SPR_HELPER_SUB(cv, ((cv & 0x4) ? 0 : 0), 1), SPR_HELPER_SUB(cv, ((cv & 0x4) ? 1 : 0), 1), \
|
||||
SPR_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 1), SPR_HELPER_SUB(cv, ((cv & 0x4) ? 2 : 0), 1), \
|
||||
} }
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
#define LINE_HELPER_SUB(cv, mam) &PS_GPU::Command_DrawLine<((cv & 0x08) >> 3), ((cv & 0x10) >> 4), ((cv & 0x2) >> 1) ? BLENDMODE_MAC : -1, mam>
|
||||
|
||||
#define LINE_HELPER(cv) { 3 + ((cv & 0x10) >> 4), 1, false, "Line", \
|
||||
{ LINE_HELPER_SUB(cv, 0), LINE_HELPER_SUB(cv, 0), LINE_HELPER_SUB(cv, 0), LINE_HELPER_SUB(cv, 0), \
|
||||
LINE_HELPER_SUB(cv, 1), LINE_HELPER_SUB(cv, 1), LINE_HELPER_SUB(cv, 1), LINE_HELPER_SUB(cv, 1), } }
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
#define OTHER_HELPER(arg_cs, arg_fbcs, arg_ss, arg_name, arg_ptr) { arg_cs, arg_fbcs, arg_ss, arg_name, { arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr } }
|
||||
|
||||
#define NULLCMD() { 1, 1, true, NULL, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }
|
||||
|
||||
|
||||
/* 0x00 */
|
||||
NULLCMD(),
|
||||
OTHER_HELPER(1, 2, false, "Clear Cache", &PS_GPU::Command_ClearCache),
|
||||
OTHER_HELPER(3, 3, false, "FB Fill", &PS_GPU::Command_FBFill),
|
||||
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0x10 */
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0x20 */
|
||||
POLY_HELPER(0x20),
|
||||
POLY_HELPER(0x21),
|
||||
POLY_HELPER(0x22),
|
||||
POLY_HELPER(0x23),
|
||||
POLY_HELPER(0x24),
|
||||
POLY_HELPER(0x25),
|
||||
POLY_HELPER(0x26),
|
||||
POLY_HELPER(0x27),
|
||||
POLY_HELPER(0x28),
|
||||
POLY_HELPER(0x29),
|
||||
POLY_HELPER(0x2a),
|
||||
POLY_HELPER(0x2b),
|
||||
POLY_HELPER(0x2c),
|
||||
POLY_HELPER(0x2d),
|
||||
POLY_HELPER(0x2e),
|
||||
POLY_HELPER(0x2f),
|
||||
POLY_HELPER(0x30),
|
||||
POLY_HELPER(0x31),
|
||||
POLY_HELPER(0x32),
|
||||
POLY_HELPER(0x33),
|
||||
POLY_HELPER(0x34),
|
||||
POLY_HELPER(0x35),
|
||||
POLY_HELPER(0x36),
|
||||
POLY_HELPER(0x37),
|
||||
POLY_HELPER(0x38),
|
||||
POLY_HELPER(0x39),
|
||||
POLY_HELPER(0x3a),
|
||||
POLY_HELPER(0x3b),
|
||||
POLY_HELPER(0x3c),
|
||||
POLY_HELPER(0x3d),
|
||||
POLY_HELPER(0x3e),
|
||||
POLY_HELPER(0x3f),
|
||||
|
||||
LINE_HELPER(0x40),
|
||||
LINE_HELPER(0x41),
|
||||
LINE_HELPER(0x42),
|
||||
LINE_HELPER(0x43),
|
||||
LINE_HELPER(0x44),
|
||||
LINE_HELPER(0x45),
|
||||
LINE_HELPER(0x46),
|
||||
LINE_HELPER(0x47),
|
||||
LINE_HELPER(0x48),
|
||||
LINE_HELPER(0x49),
|
||||
LINE_HELPER(0x4a),
|
||||
LINE_HELPER(0x4b),
|
||||
LINE_HELPER(0x4c),
|
||||
LINE_HELPER(0x4d),
|
||||
LINE_HELPER(0x4e),
|
||||
LINE_HELPER(0x4f),
|
||||
LINE_HELPER(0x50),
|
||||
LINE_HELPER(0x51),
|
||||
LINE_HELPER(0x52),
|
||||
LINE_HELPER(0x53),
|
||||
LINE_HELPER(0x54),
|
||||
LINE_HELPER(0x55),
|
||||
LINE_HELPER(0x56),
|
||||
LINE_HELPER(0x57),
|
||||
LINE_HELPER(0x58),
|
||||
LINE_HELPER(0x59),
|
||||
LINE_HELPER(0x5a),
|
||||
LINE_HELPER(0x5b),
|
||||
LINE_HELPER(0x5c),
|
||||
LINE_HELPER(0x5d),
|
||||
LINE_HELPER(0x5e),
|
||||
LINE_HELPER(0x5f),
|
||||
|
||||
SPR_HELPER(0x60),
|
||||
SPR_HELPER(0x61),
|
||||
SPR_HELPER(0x62),
|
||||
SPR_HELPER(0x63),
|
||||
SPR_HELPER(0x64),
|
||||
SPR_HELPER(0x65),
|
||||
SPR_HELPER(0x66),
|
||||
SPR_HELPER(0x67),
|
||||
SPR_HELPER(0x68),
|
||||
SPR_HELPER(0x69),
|
||||
SPR_HELPER(0x6a),
|
||||
SPR_HELPER(0x6b),
|
||||
SPR_HELPER(0x6c),
|
||||
SPR_HELPER(0x6d),
|
||||
SPR_HELPER(0x6e),
|
||||
SPR_HELPER(0x6f),
|
||||
SPR_HELPER(0x70),
|
||||
SPR_HELPER(0x71),
|
||||
SPR_HELPER(0x72),
|
||||
SPR_HELPER(0x73),
|
||||
SPR_HELPER(0x74),
|
||||
SPR_HELPER(0x75),
|
||||
SPR_HELPER(0x76),
|
||||
SPR_HELPER(0x77),
|
||||
SPR_HELPER(0x78),
|
||||
SPR_HELPER(0x79),
|
||||
SPR_HELPER(0x7a),
|
||||
SPR_HELPER(0x7b),
|
||||
SPR_HELPER(0x7c),
|
||||
SPR_HELPER(0x7d),
|
||||
SPR_HELPER(0x7e),
|
||||
SPR_HELPER(0x7f),
|
||||
|
||||
/* 0x80 */
|
||||
OTHER_HELPER(4, 2, false, "FB Copy", &PS_GPU::Command_FBCopy),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0x90 */
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0xA0 */
|
||||
OTHER_HELPER(3, 2, false, "FB Write", &PS_GPU::Command_FBWrite),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0xB0 */
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0xC0 */
|
||||
OTHER_HELPER(3, 2, false, "FB Read", &PS_GPU::Command_FBRead),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0xD0 */
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0xE0 */
|
||||
|
||||
NULLCMD(),
|
||||
OTHER_HELPER(1, 2, false, "Draw mode settings", &PS_GPU::Command_DrawMode),
|
||||
OTHER_HELPER(1, 2, false, "Texture window settings", &PS_GPU::Command_TexWindow),
|
||||
OTHER_HELPER(1, 1, true, "Drawing area top left", &PS_GPU::Command_Clip0),
|
||||
OTHER_HELPER(1, 1, true, "Drawing area bottom right", &PS_GPU::Command_Clip1),
|
||||
OTHER_HELPER(1, 1, true, "Drawing offset", &PS_GPU::Command_DrawingOffset),
|
||||
OTHER_HELPER(1, 2, false, "Mask settings", &PS_GPU::Command_MaskSetting),
|
||||
|
||||
NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
||||
/* 0xF0 */
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(),
|
||||
|
249
mednafen/psx-0925/gpu_line.inc
Normal file
249
mednafen/psx-0925/gpu_line.inc
Normal file
@ -0,0 +1,249 @@
|
||||
struct line_fxp_coord
|
||||
{
|
||||
int64 x, y;
|
||||
int32 r, g, b;
|
||||
};
|
||||
|
||||
struct line_fxp_step
|
||||
{
|
||||
int64 dx_dk, dy_dk;
|
||||
int32 dr_dk, dg_dk, db_dk;
|
||||
};
|
||||
|
||||
enum { Line_XY_FractBits = 32 };
|
||||
enum { Line_RGB_FractBits = 12 };
|
||||
|
||||
template<bool goraud>
|
||||
static INLINE void LinePointToFXPCoord(const line_point &point, const line_fxp_step &step, line_fxp_coord &coord)
|
||||
{
|
||||
coord.x = ((int64)point.x << Line_XY_FractBits) | (1LL << (Line_XY_FractBits - 1));
|
||||
coord.y = ((int64)point.y << Line_XY_FractBits) | (1LL << (Line_XY_FractBits - 1));
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
coord.r = (point.r << Line_RGB_FractBits) | (1 << (Line_RGB_FractBits - 1));
|
||||
coord.g = (point.g << Line_RGB_FractBits) | (1 << (Line_RGB_FractBits - 1));
|
||||
coord.b = (point.b << Line_RGB_FractBits) | (1 << (Line_RGB_FractBits - 1));
|
||||
}
|
||||
|
||||
// Not sure if this is correct or just roughly corresponds to behavior of real system(need more testing):
|
||||
if(step.dx_dk < 0)
|
||||
coord.x--;
|
||||
|
||||
if(step.dy_dk < 0)
|
||||
coord.y--;
|
||||
|
||||
if(step.dr_dk < 0)
|
||||
coord.r--;
|
||||
|
||||
if(step.dg_dk < 0)
|
||||
coord.g--;
|
||||
|
||||
if(step.db_dk < 0)
|
||||
coord.b--;
|
||||
}
|
||||
|
||||
template<typename T, unsigned bits>
|
||||
static INLINE T LineDivide(T delta, int32 dk)
|
||||
{
|
||||
delta <<= bits;
|
||||
|
||||
if(delta < 0)
|
||||
delta -= dk - 1;
|
||||
if(delta > 0)
|
||||
delta += dk - 1;
|
||||
|
||||
return(delta / dk);
|
||||
}
|
||||
|
||||
template<bool goraud>
|
||||
static INLINE void LinePointsToFXPStep(const line_point &point0, const line_point &point1, const int32 dk, line_fxp_step &step)
|
||||
{
|
||||
if(!dk)
|
||||
{
|
||||
step.dx_dk = 0;
|
||||
step.dy_dk = 0;
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
step.dr_dk = 0;
|
||||
step.dg_dk = 0;
|
||||
step.db_dk = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
step.dx_dk = LineDivide<int64, Line_XY_FractBits>(point1.x - point0.x, dk);
|
||||
step.dy_dk = LineDivide<int64, Line_XY_FractBits>(point1.y - point0.y, dk);
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
step.dr_dk = LineDivide<int32, Line_RGB_FractBits>(point1.r - point0.r, dk);
|
||||
step.dg_dk = LineDivide<int32, Line_RGB_FractBits>(point1.g - point0.g, dk);
|
||||
step.db_dk = LineDivide<int32, Line_RGB_FractBits>(point1.b - point0.b, dk);
|
||||
}
|
||||
}
|
||||
|
||||
template<bool goraud>
|
||||
static INLINE void AddLineStep(line_fxp_coord &point, const line_fxp_step &step, int32 count = 1)
|
||||
{
|
||||
point.x += step.dx_dk * count;
|
||||
point.y += step.dy_dk * count;
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
point.r += step.dr_dk * count;
|
||||
point.g += step.dg_dk * count;
|
||||
point.b += step.db_dk * count;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool goraud, int BlendMode, bool MaskEval_TA>
|
||||
void PS_GPU::DrawLine(line_point *points)
|
||||
{
|
||||
int32 i_dx;
|
||||
int32 i_dy;
|
||||
int32 k;
|
||||
line_fxp_coord cur_point;
|
||||
line_fxp_step step;
|
||||
|
||||
i_dx = abs(points[1].x - points[0].x);
|
||||
i_dy = abs(points[1].y - points[0].y);
|
||||
k = (i_dx > i_dy) ? i_dx : i_dy;
|
||||
|
||||
if(i_dx >= 1024)
|
||||
{
|
||||
//PSX_WARNING("[GPU] Line too long: i_dx=%d", i_dx);
|
||||
return;
|
||||
}
|
||||
|
||||
if(i_dy >= 512)
|
||||
{
|
||||
//PSX_WARNING("[GPU] Line too long: i_dy=%d", i_dy);
|
||||
return;
|
||||
}
|
||||
|
||||
// May not be correct(do tests for the case of k == i_dy on real thing.
|
||||
if(points[0].x > points[1].x)
|
||||
{
|
||||
line_point tmp = points[1];
|
||||
|
||||
points[1] = points[0];
|
||||
points[0] = tmp;
|
||||
}
|
||||
|
||||
DrawTimeAvail -= k * ((BlendMode >= 0) ? 2 : 1);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
LinePointsToFXPStep<goraud>(points[0], points[1], k, step);
|
||||
LinePointToFXPCoord<goraud>(points[0], step, cur_point);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
for(int32 i = 0; i <= k; i++) // <= is not a typo.
|
||||
{
|
||||
// Sign extension is not necessary here for x and y, due to the maximum values that ClipX1 and ClipY1 can contain.
|
||||
const int32 x = (cur_point.x >> Line_XY_FractBits) & 2047;
|
||||
const int32 y = (cur_point.y >> Line_XY_FractBits) & 2047;
|
||||
uint16 pix = 0x8000;
|
||||
|
||||
if(!LineSkipTest(y))
|
||||
{
|
||||
uint8 r, g, b;
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
r = cur_point.r >> Line_RGB_FractBits;
|
||||
g = cur_point.g >> Line_RGB_FractBits;
|
||||
b = cur_point.b >> Line_RGB_FractBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = points[0].r;
|
||||
g = points[0].g;
|
||||
b = points[0].b;
|
||||
}
|
||||
|
||||
if(goraud && dtd)
|
||||
{
|
||||
pix |= DitherLUT[y & 3][x & 3][r] << 0;
|
||||
pix |= DitherLUT[y & 3][x & 3][g] << 5;
|
||||
pix |= DitherLUT[y & 3][x & 3][b] << 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
pix |= (r >> 3) << 0;
|
||||
pix |= (g >> 3) << 5;
|
||||
pix |= (b >> 3) << 10;
|
||||
}
|
||||
|
||||
// FIXME: There has to be a faster way than checking for being inside the drawing area for each pixel.
|
||||
if(x >= ClipX0 && x <= ClipX1 && y >= ClipY0 && y <= ClipY1)
|
||||
PlotPixel<BlendMode, MaskEval_TA, false>(x, y, pix);
|
||||
}
|
||||
|
||||
AddLineStep<goraud>(cur_point, step);
|
||||
}
|
||||
}
|
||||
|
||||
template<bool polyline, bool goraud, int BlendMode, bool MaskEval_TA>
|
||||
void PS_GPU::Command_DrawLine(const uint32 *cb)
|
||||
{
|
||||
const uint8 cc = cb[0] >> 24; // For pline handling later.
|
||||
line_point points[2];
|
||||
|
||||
DrawTimeAvail -= 16; // FIXME, correct time.
|
||||
|
||||
if(polyline && InCmd == INCMD_PLINE)
|
||||
{
|
||||
//printf("PLINE N\n");
|
||||
points[0] = InPLine_PrevPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
points[0].r = (*cb >> 0) & 0xFF;
|
||||
points[0].g = (*cb >> 8) & 0xFF;
|
||||
points[0].b = (*cb >> 16) & 0xFF;
|
||||
cb++;
|
||||
|
||||
points[0].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF)) + OffsX;
|
||||
points[0].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF)) + OffsY;
|
||||
cb++;
|
||||
}
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
points[1].r = (*cb >> 0) & 0xFF;
|
||||
points[1].g = (*cb >> 8) & 0xFF;
|
||||
points[1].b = (*cb >> 16) & 0xFF;
|
||||
cb++;
|
||||
}
|
||||
else
|
||||
{
|
||||
points[1].r = points[0].r;
|
||||
points[1].g = points[0].g;
|
||||
points[1].b = points[0].b;
|
||||
}
|
||||
|
||||
points[1].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF)) + OffsX;
|
||||
points[1].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF)) + OffsY;
|
||||
cb++;
|
||||
|
||||
if(polyline)
|
||||
{
|
||||
InPLine_PrevPoint = points[1];
|
||||
|
||||
if(InCmd != INCMD_PLINE)
|
||||
{
|
||||
InCmd = INCMD_PLINE;
|
||||
InCmd_CC = cc;
|
||||
}
|
||||
}
|
||||
|
||||
DrawLine<goraud, BlendMode, MaskEval_TA>(points);
|
||||
}
|
||||
|
489
mednafen/psx-0925/gpu_polygon.inc
Normal file
489
mednafen/psx-0925/gpu_polygon.inc
Normal file
@ -0,0 +1,489 @@
|
||||
struct i_group
|
||||
{
|
||||
int32 u, v;
|
||||
int32 r, g, b;
|
||||
int32 dummy0[3];
|
||||
};
|
||||
|
||||
struct i_deltas
|
||||
{
|
||||
int32 du_dx, dv_dx;
|
||||
int32 dr_dx, dg_dx, db_dx;
|
||||
int32 dummy0[3];
|
||||
|
||||
int32 du_dy, dv_dy;
|
||||
int32 dr_dy, dg_dy, db_dy;
|
||||
int32 dummy1[3];
|
||||
};
|
||||
|
||||
static INLINE int64 MakePolyXFP(int32 x)
|
||||
{
|
||||
return ((int64)x << 32) + ((1LL << 32) - (1 << 11));
|
||||
}
|
||||
|
||||
static INLINE int64 MakePolyXFPStep(int32 dx, int32 dy)
|
||||
{
|
||||
int64 ret;
|
||||
int64 dx_ex = (int64)dx << 32;
|
||||
|
||||
if(dx_ex < 0)
|
||||
dx_ex -= dy - 1;
|
||||
|
||||
if(dx_ex > 0)
|
||||
dx_ex += dy - 1;
|
||||
|
||||
ret = dx_ex / dy;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static INLINE int32 GetPolyXFP_Int(int64 xfp)
|
||||
{
|
||||
return(xfp >> 32);
|
||||
}
|
||||
|
||||
//#define CALCIS(x,y) ( A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y) )
|
||||
#define CALCIS(x,y) (((B.x - A.x) * (C.y - B.y)) - ((C.x - B.x) * (B.y - A.y)))
|
||||
static INLINE bool CalcIDeltas(i_deltas &idl, const tri_vertex &A, const tri_vertex &B, const tri_vertex &C)
|
||||
{
|
||||
int64 num = ((int64)COORD_MF_INT(1)) << 32;
|
||||
int64 denom = CALCIS(x, y);
|
||||
int64 one_div;
|
||||
|
||||
if(!denom)
|
||||
return(false);
|
||||
|
||||
//num -= abs(denom) - 1;
|
||||
// num += abs(denom) >> 1;
|
||||
|
||||
one_div = num / denom;
|
||||
|
||||
idl.dr_dx = ((one_div * CALCIS(r, y)) + 0x00000000) >> 32;
|
||||
idl.dr_dy = ((one_div * CALCIS(x, r)) + 0x00000000) >> 32;
|
||||
|
||||
idl.dg_dx = ((one_div * CALCIS(g, y)) + 0x00000000) >> 32;
|
||||
idl.dg_dy = ((one_div * CALCIS(x, g)) + 0x00000000) >> 32;
|
||||
|
||||
idl.db_dx = ((one_div * CALCIS(b, y)) + 0x00000000) >> 32;
|
||||
idl.db_dy = ((one_div * CALCIS(x, b)) + 0x00000000) >> 32;
|
||||
|
||||
idl.du_dx = ((one_div * CALCIS(u, y)) + 0x00000000) >> 32;
|
||||
idl.du_dy = ((one_div * CALCIS(x, u)) + 0x00000000) >> 32;
|
||||
|
||||
idl.dv_dx = ((one_div * CALCIS(v, y)) + 0x00000000) >> 32;
|
||||
idl.dv_dy = ((one_div * CALCIS(x, v)) + 0x00000000) >> 32;
|
||||
|
||||
// printf(" du_dx=%08x, du_dy=%08x\n", idl.du_dx, idl.du_dy);
|
||||
|
||||
return(true);
|
||||
}
|
||||
#undef CALCIS
|
||||
|
||||
template<bool goraud, bool textured>
|
||||
static INLINE void AddIDeltas_DX(i_group &ig, const i_deltas &idl)
|
||||
{
|
||||
if(textured)
|
||||
{
|
||||
ig.u += idl.du_dx;
|
||||
ig.v += idl.dv_dx;
|
||||
}
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
ig.r += idl.dr_dx;
|
||||
ig.g += idl.dg_dx;
|
||||
ig.b += idl.db_dx;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool goraud, bool textured>
|
||||
static INLINE void AddIDeltas_DY(i_group &ig, const i_deltas &idl, int32 count = 1)
|
||||
{
|
||||
if(textured)
|
||||
{
|
||||
ig.u += idl.du_dy * count;
|
||||
ig.v += idl.dv_dy * count;
|
||||
}
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
ig.r += idl.dr_dy * count;
|
||||
ig.g += idl.dg_dy * count;
|
||||
ig.b += idl.db_dy * count;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
INLINE void PS_GPU::DrawSpan(int y, uint32 clut_offset, const int32 x_start, const int32 x_bound, const int32 bv_x, i_group ig, const i_deltas &idl)
|
||||
{
|
||||
int32 xs = x_start, xb = x_bound;
|
||||
|
||||
if(LineSkipTest(y))
|
||||
return;
|
||||
|
||||
if(xs < xb) // (xs != xb)
|
||||
{
|
||||
if(xs < ClipX0)
|
||||
xs = ClipX0;
|
||||
|
||||
if(xb > (ClipX1 + 1))
|
||||
xb = ClipX1 + 1;
|
||||
|
||||
if(xs < xb)
|
||||
{
|
||||
DrawTimeAvail -= (xb - xs);
|
||||
|
||||
if(goraud || textured)
|
||||
{
|
||||
DrawTimeAvail -= (xb - xs);
|
||||
}
|
||||
else if((BlendMode >= 0) || MaskEval_TA)
|
||||
{
|
||||
DrawTimeAvail -= (((xb + 1) & ~1) - (xs & ~1)) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(textured)
|
||||
{
|
||||
ig.u += (xs - bv_x) * idl.du_dx;
|
||||
ig.v += (xs - bv_x) * idl.dv_dx;
|
||||
}
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
ig.r += (xs - bv_x) * idl.dr_dx;
|
||||
ig.g += (xs - bv_x) * idl.dg_dx;
|
||||
ig.b += (xs - bv_x) * idl.db_dx;
|
||||
}
|
||||
|
||||
for(int32 x = xs; x < xb; x++)
|
||||
{
|
||||
uint32 r, g, b;
|
||||
|
||||
if(goraud)
|
||||
{
|
||||
r = RGB8SAT[COORD_GET_INT(ig.r)];
|
||||
g = RGB8SAT[COORD_GET_INT(ig.g)];
|
||||
b = RGB8SAT[COORD_GET_INT(ig.b)];
|
||||
}
|
||||
else
|
||||
{
|
||||
r = COORD_GET_INT(ig.r);
|
||||
g = COORD_GET_INT(ig.g);
|
||||
b = COORD_GET_INT(ig.b);
|
||||
}
|
||||
|
||||
if(textured)
|
||||
{
|
||||
uint16 fbw = GetTexel<TexMode_TA>(clut_offset, COORD_GET_INT(ig.u), COORD_GET_INT(ig.v));
|
||||
|
||||
if(fbw)
|
||||
{
|
||||
if(TexMult)
|
||||
{
|
||||
if(dtd)
|
||||
fbw = ModTexel(fbw, r, g, b, x & 3, y & 3);
|
||||
else
|
||||
fbw = ModTexel(fbw, r, g, b, 3, 2); //x & 3, y & 3);
|
||||
}
|
||||
PlotPixel<BlendMode, MaskEval_TA, true>(x, y, fbw);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 pix = 0x8000;
|
||||
|
||||
if(goraud && dtd)
|
||||
{
|
||||
pix |= DitherLUT[y & 3][x & 3][r] << 0;
|
||||
pix |= DitherLUT[y & 3][x & 3][g] << 5;
|
||||
pix |= DitherLUT[y & 3][x & 3][b] << 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
pix |= (r >> 3) << 0;
|
||||
pix |= (g >> 3) << 5;
|
||||
pix |= (b >> 3) << 10;
|
||||
}
|
||||
|
||||
PlotPixel<BlendMode, MaskEval_TA, false>(x, y, pix);
|
||||
}
|
||||
|
||||
AddIDeltas_DX<goraud, textured>(ig, idl);
|
||||
//AddStep<goraud, textured>(perp_coord, perp_step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
void PS_GPU::DrawTriangle(tri_vertex *vertices, uint32 clut)
|
||||
{
|
||||
i_deltas idl;
|
||||
|
||||
#if 0
|
||||
vertices[0].y = COORD_MF_INT(rand());
|
||||
vertices[1].y = COORD_MF_INT(rand());
|
||||
vertices[2].y = COORD_MF_INT(rand());
|
||||
|
||||
vertices[0].x = COORD_MF_INT(rand());
|
||||
vertices[1].x = COORD_MF_INT(rand());
|
||||
vertices[2].x = COORD_MF_INT(rand());
|
||||
#endif
|
||||
|
||||
if(vertices[2].y < vertices[1].y)
|
||||
{
|
||||
tri_vertex tmp = vertices[1];
|
||||
vertices[1] = vertices[2];
|
||||
vertices[2] = tmp;
|
||||
}
|
||||
|
||||
if(vertices[1].y < vertices[0].y)
|
||||
{
|
||||
tri_vertex tmp = vertices[0];
|
||||
vertices[0] = vertices[1];
|
||||
vertices[1] = tmp;
|
||||
}
|
||||
|
||||
if(vertices[2].y < vertices[1].y)
|
||||
{
|
||||
tri_vertex tmp = vertices[1];
|
||||
vertices[1] = vertices[2];
|
||||
vertices[2] = tmp;
|
||||
}
|
||||
|
||||
if(vertices[0].y == vertices[2].y)
|
||||
return;
|
||||
|
||||
if((vertices[2].y - vertices[0].y) >= 512)
|
||||
{
|
||||
//PSX_WARNING("[GPU] Triangle height too large: %d", (vertices[2].y - vertices[0].y));
|
||||
return;
|
||||
}
|
||||
|
||||
if(abs(vertices[2].x - vertices[0].x) >= 1024 ||
|
||||
abs(vertices[2].x - vertices[1].x) >= 1024 ||
|
||||
abs(vertices[1].x - vertices[0].x) >= 1024)
|
||||
{
|
||||
//PSX_WARNING("[GPU] Triangle width too large: %d %d %d", abs(vertices[2].x - vertices[0].x), abs(vertices[2].x - vertices[1].x), abs(vertices[1].x - vertices[0].x));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CalcIDeltas(idl, vertices[0], vertices[1], vertices[2]))
|
||||
return;
|
||||
|
||||
// [0] should be top vertex, [2] should be bottom vertex, [1] should be off to the side vertex.
|
||||
//
|
||||
//
|
||||
int32 y_start = vertices[0].y;
|
||||
int32 y_middle = vertices[1].y;
|
||||
int32 y_bound = vertices[2].y;
|
||||
|
||||
int64 base_coord;
|
||||
int64 base_step;
|
||||
|
||||
int64 bound_coord_ul;
|
||||
int64 bound_coord_us;
|
||||
|
||||
int64 bound_coord_ll;
|
||||
int64 bound_coord_ls;
|
||||
|
||||
bool right_facing;
|
||||
//bool bottom_up;
|
||||
i_group ig;
|
||||
|
||||
ig.u = COORD_MF_INT(vertices[0].u) + (1 << (COORD_FBS - 1));
|
||||
ig.v = COORD_MF_INT(vertices[0].v) + (1 << (COORD_FBS - 1));
|
||||
ig.r = COORD_MF_INT(vertices[0].r);
|
||||
ig.g = COORD_MF_INT(vertices[0].g);
|
||||
ig.b = COORD_MF_INT(vertices[0].b);
|
||||
|
||||
base_coord = MakePolyXFP(vertices[0].x); //COORD_MF_INT(vertices[0].x) + ((1 << COORD_FBS) - 1);
|
||||
base_step = MakePolyXFPStep((vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y)); //ROUND_HELPER(COORD_MF_INT(vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y));
|
||||
|
||||
bound_coord_ul = MakePolyXFP(vertices[0].x); // + ((1 << COORD_FBS) - 1);
|
||||
bound_coord_ll = MakePolyXFP(vertices[1].x); // + ((1 << COORD_FBS) - 1);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
if(vertices[1].y == vertices[0].y)
|
||||
{
|
||||
bound_coord_us = 0;
|
||||
right_facing = (bool)(vertices[1].x > vertices[0].x);
|
||||
}
|
||||
else
|
||||
{
|
||||
bound_coord_us = MakePolyXFPStep((vertices[1].x - vertices[0].x), (vertices[1].y - vertices[0].y));
|
||||
right_facing = (bool)(bound_coord_us > base_step);
|
||||
}
|
||||
|
||||
if(vertices[2].y == vertices[1].y)
|
||||
bound_coord_ls = 0;
|
||||
else
|
||||
bound_coord_ls = MakePolyXFPStep((vertices[2].x - vertices[1].x), (vertices[2].y - vertices[1].y));
|
||||
|
||||
if(y_start < ClipY0)
|
||||
{
|
||||
int32 count = ClipY0 - y_start;
|
||||
|
||||
y_start = ClipY0;
|
||||
base_coord += base_step * count;
|
||||
bound_coord_ul += bound_coord_us * count;
|
||||
|
||||
AddIDeltas_DY<goraud, textured>(ig, idl, count);
|
||||
|
||||
if(y_middle < ClipY0)
|
||||
{
|
||||
int32 count_ls = ClipY0 - y_middle;
|
||||
|
||||
y_middle = ClipY0;
|
||||
bound_coord_ll += bound_coord_ls * count_ls;
|
||||
}
|
||||
}
|
||||
|
||||
if(y_bound > (ClipY1 + 1))
|
||||
{
|
||||
y_bound = ClipY1 + 1;
|
||||
|
||||
if(y_middle > y_bound)
|
||||
y_middle = y_bound;
|
||||
}
|
||||
|
||||
if(right_facing)
|
||||
{
|
||||
for(int32 y = y_start; y < y_middle; y++)
|
||||
{
|
||||
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ul), vertices[0].x, ig, idl);
|
||||
base_coord += base_step;
|
||||
bound_coord_ul += bound_coord_us;
|
||||
AddIDeltas_DY<goraud, textured>(ig, idl);
|
||||
}
|
||||
|
||||
for(int32 y = y_middle; y < y_bound; y++)
|
||||
{
|
||||
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ll), vertices[0].x, ig, idl);
|
||||
base_coord += base_step;
|
||||
bound_coord_ll += bound_coord_ls;
|
||||
AddIDeltas_DY<goraud, textured>(ig, idl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int32 y = y_start; y < y_middle; y++)
|
||||
{
|
||||
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(bound_coord_ul), GetPolyXFP_Int(base_coord), vertices[0].x, ig, idl);
|
||||
base_coord += base_step;
|
||||
bound_coord_ul += bound_coord_us;
|
||||
AddIDeltas_DY<goraud, textured>(ig, idl);
|
||||
}
|
||||
|
||||
for(int32 y = y_middle; y < y_bound; y++)
|
||||
{
|
||||
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(bound_coord_ll), GetPolyXFP_Int(base_coord), vertices[0].x, ig, idl);
|
||||
base_coord += base_step;
|
||||
bound_coord_ll += bound_coord_ls;
|
||||
AddIDeltas_DY<goraud, textured>(ig, idl);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("[GPU] Vertices: %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d)\n\n\n", vertices[0].x, vertices[0].y,
|
||||
vertices[0].r, vertices[0].g, vertices[0].b,
|
||||
vertices[1].x, vertices[1].y,
|
||||
vertices[1].r, vertices[1].g, vertices[1].b,
|
||||
vertices[2].x, vertices[2].y,
|
||||
vertices[2].r, vertices[2].g, vertices[2].b);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<int numvertices, bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
void PS_GPU::Command_DrawPolygon(const uint32 *cb)
|
||||
{
|
||||
const unsigned cb0 = cb[0];
|
||||
tri_vertex vertices[3];
|
||||
uint32 clut = 0;
|
||||
unsigned sv = 0;
|
||||
//uint32 tpage = 0;
|
||||
|
||||
// Base timing is approximate, and could be improved.
|
||||
if(numvertices == 4 && InCmd == INCMD_QUAD)
|
||||
DrawTimeAvail -= (28 + 18);
|
||||
else
|
||||
DrawTimeAvail -= (64 + 18);
|
||||
|
||||
if(goraud && textured)
|
||||
DrawTimeAvail -= 150 * 3;
|
||||
else if(goraud)
|
||||
DrawTimeAvail -= 96 * 3;
|
||||
else if(textured)
|
||||
DrawTimeAvail -= 60 * 3;
|
||||
|
||||
if(numvertices == 4)
|
||||
{
|
||||
if(InCmd == INCMD_QUAD)
|
||||
{
|
||||
memcpy(&vertices[0], &InQuad_F3Vertices[1], 2 * sizeof(tri_vertex));
|
||||
clut = InQuad_clut;
|
||||
sv = 2;
|
||||
}
|
||||
}
|
||||
//else
|
||||
// memset(vertices, 0, sizeof(vertices));
|
||||
|
||||
for(unsigned v = sv; v < 3; v++)
|
||||
{
|
||||
if(v == 0 || goraud)
|
||||
{
|
||||
uint32 raw_color = (*cb & 0xFFFFFF);
|
||||
|
||||
vertices[v].r = raw_color & 0xFF;
|
||||
vertices[v].g = (raw_color >> 8) & 0xFF;
|
||||
vertices[v].b = (raw_color >> 16) & 0xFF;
|
||||
|
||||
cb++;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices[v].r = vertices[0].r;
|
||||
vertices[v].g = vertices[0].g;
|
||||
vertices[v].b = vertices[0].b;
|
||||
}
|
||||
|
||||
vertices[v].x = sign_x_to_s32(11, ((int16)(*cb & 0xFFFF))) + OffsX;
|
||||
vertices[v].y = sign_x_to_s32(11, ((int16)(*cb >> 16))) + OffsY;
|
||||
cb++;
|
||||
|
||||
if(textured)
|
||||
{
|
||||
vertices[v].u = (*cb & 0xFF);
|
||||
vertices[v].v = (*cb >> 8) & 0xFF;
|
||||
|
||||
if(v == 0)
|
||||
{
|
||||
clut = ((*cb >> 16) & 0xFFFF) << 4;
|
||||
}
|
||||
|
||||
cb++;
|
||||
}
|
||||
}
|
||||
|
||||
if(numvertices == 4)
|
||||
{
|
||||
if(InCmd == INCMD_QUAD)
|
||||
{
|
||||
InCmd = INCMD_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
InCmd = INCMD_QUAD;
|
||||
InCmd_CC = cb0 >> 24;
|
||||
memcpy(&InQuad_F3Vertices[0], &vertices[0], sizeof(tri_vertex) * 3);
|
||||
InQuad_clut = clut;
|
||||
}
|
||||
}
|
||||
|
||||
DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices, clut);
|
||||
}
|
||||
|
232
mednafen/psx-0925/gpu_sprite.inc
Normal file
232
mednafen/psx-0925/gpu_sprite.inc
Normal file
@ -0,0 +1,232 @@
|
||||
template<bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA, bool FlipX, bool FlipY>
|
||||
void PS_GPU::DrawSprite(int32 x_arg, int32 y_arg, int32 w, int32 h, uint8 u_arg, uint8 v_arg, uint32 color, uint32 clut_offset)
|
||||
{
|
||||
const int32 r = color & 0xFF;
|
||||
const int32 g = (color >> 8) & 0xFF;
|
||||
const int32 b = (color >> 16) & 0xFF;
|
||||
const uint16 fill_color = 0x8000 | ((r >> 3) << 0) | ((g >> 3) << 5) | ((b >> 3) << 10);
|
||||
|
||||
int32 x_start, x_bound;
|
||||
int32 y_start, y_bound;
|
||||
uint8 u, v;
|
||||
int v_inc = 1, u_inc = 1;
|
||||
|
||||
//printf("[GPU] Sprite: x=%d, y=%d, w=%d, h=%d\n", x_arg, y_arg, w, h);
|
||||
|
||||
x_start = x_arg;
|
||||
x_bound = x_arg + w;
|
||||
|
||||
y_start = y_arg;
|
||||
y_bound = y_arg + h;
|
||||
|
||||
if(textured)
|
||||
{
|
||||
u = u_arg;
|
||||
v = v_arg;
|
||||
|
||||
if(FlipX)
|
||||
{
|
||||
u_inc = -1;
|
||||
u |= 1;
|
||||
}
|
||||
// FIXME: Something weird happens when lower bit of u is set and we're not doing horizontal flip, but I'm not sure what it is exactly(needs testing)
|
||||
// It may only happen to the first pixel, so look for that case too during testing.
|
||||
//else
|
||||
// u = (u + 1) & ~1;
|
||||
|
||||
if(FlipY)
|
||||
{
|
||||
v_inc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(x_start < ClipX0)
|
||||
{
|
||||
if(textured)
|
||||
u += (ClipX0 - x_start) * u_inc;
|
||||
|
||||
x_start = ClipX0;
|
||||
}
|
||||
|
||||
if(y_start < ClipY0)
|
||||
{
|
||||
if(textured)
|
||||
v += (ClipY0 - y_start) * v_inc;
|
||||
|
||||
y_start = ClipY0;
|
||||
}
|
||||
|
||||
if(x_bound > (ClipX1 + 1))
|
||||
x_bound = ClipX1 + 1;
|
||||
|
||||
if(y_bound > (ClipY1 + 1))
|
||||
y_bound = ClipY1 + 1;
|
||||
|
||||
if(y_bound > y_start && x_bound > x_start)
|
||||
{
|
||||
//
|
||||
// Note(TODO): From tests on a PS1, even a 0-width sprite takes up time to "draw" proportional to its height.
|
||||
//
|
||||
int32 suck_time = (x_bound - x_start) * (y_bound - y_start);
|
||||
|
||||
// Disabled until we can get it to take into account texture windowing, which can cause large sprites to be drawn entirely from cache(and not suffer from a texturing
|
||||
// penalty); and disabled until we find a game that needs more accurate sprite draw timing. :b
|
||||
#if 0
|
||||
if(textured)
|
||||
{
|
||||
// Empirically-observed approximations of time(66MHz cycles) taken to draw large textured sprites in the various texture depths, when the texture data and CLUT data
|
||||
// was zero(non-zero takes longer to draw, TODO test that more):
|
||||
// 4bpp - area * 2
|
||||
// 8bpp - area * 3
|
||||
// 15/16bpp - area * 5
|
||||
// (other factors come into more importance for smaller sprites)
|
||||
static const int cw[4] = { 64, 32, 32, 32 };
|
||||
static const int ch[4] = { 64, 64, 32, 32 };
|
||||
static const int mm[4] = { 2 - 1, 3 - 1, 5 - 1, 5 - 1 };
|
||||
|
||||
// Parts of the first few(up to texture cache height) horizontal lines can be in cache, so assume they are.
|
||||
suck_time += mm[TexMode_TA] * std::max<int>(0, (x_bound - x_start) - cw[TexMode_TA]) * std::min<int>(ch[TexMode_TA], y_bound - y_start);
|
||||
|
||||
// The rest of the horizontal lines should not possibly have parts in the cache now.
|
||||
suck_time += mm[TexMode_TA] * (x_bound - x_start) * std::max<int>(0, (y_bound - y_start) - ch[TexMode_TA]);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if((BlendMode >= 0) || MaskEval_TA)
|
||||
{
|
||||
suck_time += ((((x_bound + 1) & ~1) - (x_start & ~1)) * (y_bound - y_start)) >> 1;
|
||||
}
|
||||
|
||||
DrawTimeAvail -= suck_time;
|
||||
}
|
||||
|
||||
|
||||
//HeightMode && !dfe && ((y & 1) == ((DisplayFB_YStart + !field_atvs) & 1)) && !DisplayOff
|
||||
//printf("%d:%d, %d, %d ---- heightmode=%d displayfb_ystart=%d field_atvs=%d displayoff=%d\n", w, h, scanline, dfe, HeightMode, DisplayFB_YStart, field_atvs, DisplayOff);
|
||||
|
||||
for(int32 y = y_start; y < y_bound; y++)
|
||||
{
|
||||
uint8 u_r;
|
||||
|
||||
if(textured)
|
||||
u_r = u;
|
||||
|
||||
if(!LineSkipTest(y))
|
||||
{
|
||||
for(int32 x = x_start; x < x_bound; x++)
|
||||
{
|
||||
if(textured)
|
||||
{
|
||||
uint16 fbw = GetTexel<TexMode_TA>(clut_offset, u_r, v);
|
||||
|
||||
if(fbw)
|
||||
{
|
||||
if(TexMult)
|
||||
{
|
||||
fbw = ModTexel(fbw, r, g, b, 3, 2);
|
||||
}
|
||||
PlotPixel<BlendMode, MaskEval_TA, true>(x, y, fbw);
|
||||
}
|
||||
}
|
||||
else
|
||||
PlotPixel<BlendMode, MaskEval_TA, false>(x, y, fill_color);
|
||||
|
||||
if(textured)
|
||||
u_r += u_inc;
|
||||
}
|
||||
}
|
||||
if(textured)
|
||||
v += v_inc;
|
||||
}
|
||||
}
|
||||
|
||||
template<uint8 raw_size, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
|
||||
void PS_GPU::Command_DrawSprite(const uint32 *cb)
|
||||
{
|
||||
int32 x, y;
|
||||
int32 w, h;
|
||||
uint8 u = 0, v = 0;
|
||||
uint32 color = 0;
|
||||
uint32 clut = 0;
|
||||
|
||||
DrawTimeAvail -= 16; // FIXME, correct time.
|
||||
|
||||
color = *cb & 0x00FFFFFF;
|
||||
cb++;
|
||||
|
||||
x = sign_x_to_s32(11, (*cb & 0xFFFF));
|
||||
y = sign_x_to_s32(11, (*cb >> 16));
|
||||
cb++;
|
||||
|
||||
if(textured)
|
||||
{
|
||||
u = *cb & 0xFF;
|
||||
v = (*cb >> 8) & 0xFF;
|
||||
clut = ((*cb >> 16) & 0xFFFF) << 4;
|
||||
cb++;
|
||||
}
|
||||
|
||||
switch(raw_size)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
w = (*cb & 0x3FF);
|
||||
h = (*cb >> 16) & 0x1FF;
|
||||
cb++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
w = 1;
|
||||
h = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
w = 8;
|
||||
h = 8;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
w = 16;
|
||||
h = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
//printf("SPRITE: %d %d %d -- %d %d\n", raw_size, x, y, w, h);
|
||||
|
||||
x = sign_x_to_s32(11, x + OffsX);
|
||||
y = sign_x_to_s32(11, y + OffsY);
|
||||
|
||||
switch(SpriteFlip & 0x3000)
|
||||
{
|
||||
case 0x0000:
|
||||
if(!TexMult || color == 0x808080)
|
||||
DrawSprite<textured, BlendMode, false, TexMode_TA, MaskEval_TA, false, false>(x, y, w, h, u, v, color, clut);
|
||||
else
|
||||
DrawSprite<textured, BlendMode, true, TexMode_TA, MaskEval_TA, false, false>(x, y, w, h, u, v, color, clut);
|
||||
break;
|
||||
|
||||
case 0x1000:
|
||||
if(!TexMult || color == 0x808080)
|
||||
DrawSprite<textured, BlendMode, false, TexMode_TA, MaskEval_TA, true, false>(x, y, w, h, u, v, color, clut);
|
||||
else
|
||||
DrawSprite<textured, BlendMode, true, TexMode_TA, MaskEval_TA, true, false>(x, y, w, h, u, v, color, clut);
|
||||
break;
|
||||
|
||||
case 0x2000:
|
||||
if(!TexMult || color == 0x808080)
|
||||
DrawSprite<textured, BlendMode, false, TexMode_TA, MaskEval_TA, false, true>(x, y, w, h, u, v, color, clut);
|
||||
else
|
||||
DrawSprite<textured, BlendMode, true, TexMode_TA, MaskEval_TA, false, true>(x, y, w, h, u, v, color, clut);
|
||||
break;
|
||||
|
||||
case 0x3000:
|
||||
if(!TexMult || color == 0x808080)
|
||||
DrawSprite<textured, BlendMode, false, TexMode_TA, MaskEval_TA, true, true>(x, y, w, h, u, v, color, clut);
|
||||
else
|
||||
DrawSprite<textured, BlendMode, true, TexMode_TA, MaskEval_TA, true, true>(x, y, w, h, u, v, color, clut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
1739
mednafen/psx-0925/gte.cpp
Normal file
1739
mednafen/psx-0925/gte.cpp
Normal file
File diff suppressed because it is too large
Load Diff
21
mednafen/psx-0925/gte.h
Normal file
21
mednafen/psx-0925/gte.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __MDFN_PSX_GTE_H
|
||||
#define __MDFN_PSX_GTE_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
void GTE_Power(void);
|
||||
int GTE_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
int32 GTE_Instruction(uint32 instr);
|
||||
|
||||
void GTE_WriteCR(unsigned int which, uint32 value);
|
||||
void GTE_WriteDR(unsigned int which, uint32 value);
|
||||
|
||||
uint32 GTE_ReadCR(unsigned int which);
|
||||
uint32 GTE_ReadDR(unsigned int which);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
32768
mednafen/psx-0925/gte_divrecip.inc
Normal file
32768
mednafen/psx-0925/gte_divrecip.inc
Normal file
File diff suppressed because it is too large
Load Diff
285
mednafen/psx-0925/input/dualanalog.cpp
Normal file
285
mednafen/psx-0925/input/dualanalog.cpp
Normal file
@ -0,0 +1,285 @@
|
||||
#include "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "dualanalog.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_DualAnalog : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_DualAnalog(bool joystick_mode_);
|
||||
virtual ~InputDevice_DualAnalog();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
bool joystick_mode;
|
||||
bool dtr;
|
||||
|
||||
uint8 buttons[2];
|
||||
uint8 axes[2][2];
|
||||
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
|
||||
uint8 transmit_buffer[8];
|
||||
uint32 transmit_pos;
|
||||
uint32 transmit_count;
|
||||
};
|
||||
|
||||
InputDevice_DualAnalog::InputDevice_DualAnalog(bool joystick_mode_) : joystick_mode(joystick_mode_)
|
||||
{
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_DualAnalog::~InputDevice_DualAnalog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_DualAnalog::Power(void)
|
||||
{
|
||||
dtr = 0;
|
||||
|
||||
buttons[0] = buttons[1] = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
memset(transmit_buffer, 0, sizeof(transmit_buffer));
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
|
||||
void InputDevice_DualAnalog::UpdateInput(const void *data)
|
||||
{
|
||||
uint8 *d8 = (uint8 *)data;
|
||||
|
||||
buttons[0] = d8[0];
|
||||
buttons[1] = d8[1];
|
||||
|
||||
for(int stick = 0; stick < 2; stick++)
|
||||
{
|
||||
for(int axis = 0; axis < 2; axis++)
|
||||
{
|
||||
int32 tmp;
|
||||
|
||||
tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767);
|
||||
tmp >>= 8;
|
||||
|
||||
axes[stick][axis] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void InputDevice_DualAnalog::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
//if(bitpos || transmit_count)
|
||||
// printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_DualAnalog::GetDSR(void)
|
||||
{
|
||||
if(!dtr)
|
||||
return(0);
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_DualAnalog::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer[transmit_pos] >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_pos++;
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x01)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
transmit_buffer[0] = joystick_mode ? 0x53 : 0x73;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
command_phase++;
|
||||
|
||||
transmit_buffer[0] = 0x5A;
|
||||
|
||||
//if(command != 0x42)
|
||||
// fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command);
|
||||
|
||||
if(command == 0x42)
|
||||
{
|
||||
transmit_buffer[1] = 0xFF ^ buttons[0];
|
||||
transmit_buffer[2] = 0xFF ^ buttons[1];
|
||||
transmit_buffer[3] = axes[0][0];
|
||||
transmit_buffer[4] = axes[0][1];
|
||||
transmit_buffer[5] = axes[1][0];
|
||||
transmit_buffer[6] = axes[1][1];
|
||||
transmit_pos = 0;
|
||||
transmit_count = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_phase = -1;
|
||||
transmit_buffer[1] = 0;
|
||||
transmit_buffer[2] = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
//if(receive_buffer)
|
||||
// printf("%d: %02x\n", 7 - transmit_count, receive_buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
dsr_pulse_delay = 0x40; //0x100;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
InputDevice *Device_DualAnalog_Create(bool joystick_mode)
|
||||
{
|
||||
return new InputDevice_DualAnalog(joystick_mode);
|
||||
}
|
||||
|
||||
|
||||
InputDeviceInputInfoStruct Device_DualAnalog_IDII[24] =
|
||||
{
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, NULL },
|
||||
{ "l3", "Left Stick, Button(L3)", 18, IDIT_BUTTON, NULL },
|
||||
{ "r3", "Right stick, Button(R3)", 23, IDIT_BUTTON, NULL },
|
||||
{ "start", "START", 5, IDIT_BUTTON, NULL },
|
||||
{ "up", "D-Pad UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "D-Pad RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "D-Pad DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "D-Pad LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
|
||||
{ "l2", "L2 (rear left shoulder)", 11, IDIT_BUTTON, NULL },
|
||||
{ "r2", "R2 (rear right shoulder)", 13, IDIT_BUTTON, NULL },
|
||||
{ "l1", "L1 (front left shoulder)", 10, IDIT_BUTTON, NULL },
|
||||
{ "r1", "R1 (front right shoulder)", 12, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "triangle", "△ (upper)", 6, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "circle", "○ (right)", 9, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "cross", "x (lower)", 7, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "square", "□ (left)", 8, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
|
||||
{ "rstick_right", "Right Stick RIGHT →", 22, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_left", "Right Stick LEFT ←", 21, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_down", "Right Stick DOWN ↓", 20, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_up", "Right Stick UP ↑", 19, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "lstick_right", "Left Stick RIGHT →", 17, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_left", "Left Stick LEFT ←", 16, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_down", "Left Stick DOWN ↓", 15, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_up", "Left Stick UP ↑", 14, IDIT_BUTTON_ANALOG },
|
||||
|
||||
};
|
||||
|
||||
// Not sure if all these buttons are named correctly!
|
||||
InputDeviceInputInfoStruct Device_AnalogJoy_IDII[24] =
|
||||
{
|
||||
{ "select", "SELECT", 8, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "start", "START", 9, IDIT_BUTTON, NULL },
|
||||
{ "up", "Thumbstick UP ↑", 14, IDIT_BUTTON, "down" },
|
||||
{ "right", "Thumbstick RIGHT →", 17, IDIT_BUTTON, "left" },
|
||||
{ "down", "Thumbstick DOWN ↓", 15, IDIT_BUTTON, "up" },
|
||||
{ "left", "Thumbstick LEFT ←", 16, IDIT_BUTTON, "right" },
|
||||
|
||||
{ "l2", "Left stick, Trigger", 2, IDIT_BUTTON, NULL },
|
||||
{ "r2", "Left stick, Pinky", 3, IDIT_BUTTON, NULL },
|
||||
{ "l1", "Left stick, L-thumb", 0, IDIT_BUTTON, NULL },
|
||||
{ "r1", "Left stick, R-thumb", 1, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "triangle", "Right stick, Pinky", 13, IDIT_BUTTON, NULL },
|
||||
{ "circle", "Right stick, R-thumb", 11, IDIT_BUTTON, NULL },
|
||||
{ "cross", "Right stick, L-thumb", 10, IDIT_BUTTON, NULL },
|
||||
{ "square", "Right stick, Trigger", 12, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "rstick_right", "Right Stick, RIGHT →", 21, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_left", "Right Stick, LEFT ←", 20, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_down", "Right Stick, BACK ↓", 19, IDIT_BUTTON_ANALOG },
|
||||
{ "rstick_up", "Right Stick, FORE ↑", 18, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "lstick_right", "Left Stick, RIGHT →", 7, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_left", "Left Stick, LEFT ←", 6, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_down", "Left Stick, BACK ↓", 5, IDIT_BUTTON_ANALOG },
|
||||
{ "lstick_up", "Left Stick, FORE ↑", 4, IDIT_BUTTON_ANALOG },
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
11
mednafen/psx-0925/input/dualanalog.h
Normal file
11
mednafen/psx-0925/input/dualanalog.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_DUALANALOG_H
|
||||
#define __MDFN_PSX_INPUT_DUALANALOG_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice *Device_DualAnalog_Create(bool joystick_mode);
|
||||
extern InputDeviceInputInfoStruct Device_DualAnalog_IDII[24];
|
||||
extern InputDeviceInputInfoStruct Device_AnalogJoy_IDII[24];
|
||||
}
|
||||
#endif
|
1025
mednafen/psx-0925/input/dualshock.cpp
Normal file
1025
mednafen/psx-0925/input/dualshock.cpp
Normal file
File diff suppressed because it is too large
Load Diff
11
mednafen/psx-0925/input/dualshock.h
Normal file
11
mednafen/psx-0925/input/dualshock.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_DUALSHOCK_H
|
||||
#define __MDFN_PSX_INPUT_DUALSHOCK_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
InputDevice *Device_DualShock_Create(const std::string &name);
|
||||
extern InputDeviceInputInfoStruct Device_DualShock_IDII[26];
|
||||
}
|
||||
#endif
|
216
mednafen/psx-0925/input/gamepad.cpp
Normal file
216
mednafen/psx-0925/input/gamepad.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
#include "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "gamepad.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_Gamepad : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_Gamepad();
|
||||
virtual ~InputDevice_Gamepad();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
bool dtr;
|
||||
|
||||
uint8 buttons[2];
|
||||
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
|
||||
uint8 transmit_buffer[3];
|
||||
uint32 transmit_pos;
|
||||
uint32 transmit_count;
|
||||
};
|
||||
|
||||
InputDevice_Gamepad::InputDevice_Gamepad()
|
||||
{
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_Gamepad::~InputDevice_Gamepad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_Gamepad::Power(void)
|
||||
{
|
||||
dtr = 0;
|
||||
|
||||
buttons[0] = buttons[1] = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
memset(transmit_buffer, 0, sizeof(transmit_buffer));
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
|
||||
void InputDevice_Gamepad::UpdateInput(const void *data)
|
||||
{
|
||||
uint8 *d8 = (uint8 *)data;
|
||||
|
||||
buttons[0] = d8[0];
|
||||
buttons[1] = d8[1];
|
||||
}
|
||||
|
||||
|
||||
void InputDevice_Gamepad::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
//if(bitpos || transmit_count)
|
||||
// printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_Gamepad::GetDSR(void)
|
||||
{
|
||||
if(!dtr)
|
||||
return(0);
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_Gamepad::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer[transmit_pos] >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_pos++;
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x01)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
transmit_buffer[0] = 0x41;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
command_phase++;
|
||||
|
||||
transmit_buffer[0] = 0x5A;
|
||||
|
||||
//if(command != 0x42)
|
||||
// fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command);
|
||||
//assert(command == 0x42);
|
||||
if(command == 0x42)
|
||||
{
|
||||
transmit_buffer[1] = 0xFF ^ buttons[0];
|
||||
transmit_buffer[2] = 0xFF ^ buttons[1];
|
||||
transmit_pos = 0;
|
||||
transmit_count = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_phase = -1;
|
||||
transmit_buffer[1] = 0;
|
||||
transmit_buffer[2] = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
dsr_pulse_delay = 0x40; //0x100;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
InputDevice *Device_Gamepad_Create(void)
|
||||
{
|
||||
return new InputDevice_Gamepad();
|
||||
}
|
||||
|
||||
|
||||
InputDeviceInputInfoStruct Device_Gamepad_IDII[16] =
|
||||
{
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "start", "START", 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" },
|
||||
|
||||
{ "l2", "L2 (rear left shoulder)", 11, IDIT_BUTTON, NULL },
|
||||
{ "r2", "R2 (rear right shoulder)", 13, IDIT_BUTTON, NULL },
|
||||
{ "l1", "L1 (front left shoulder)", 10, IDIT_BUTTON, NULL },
|
||||
{ "r1", "R1 (front right shoulder)", 12, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "triangle", "△ (upper)", 6, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "circle", "○ (right)", 9, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "cross", "x (lower)", 7, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "square", "□ (left)", 8, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
11
mednafen/psx-0925/input/gamepad.h
Normal file
11
mednafen/psx-0925/input/gamepad.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_GAMEPAD_H
|
||||
#define __MDFN_PSX_INPUT_GAMEPAD_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice *Device_Gamepad_Create(void);
|
||||
extern InputDeviceInputInfoStruct Device_Gamepad_IDII[16];
|
||||
|
||||
}
|
||||
#endif
|
396
mednafen/psx-0925/input/guncon.cpp
Normal file
396
mednafen/psx-0925/input/guncon.cpp
Normal file
@ -0,0 +1,396 @@
|
||||
/* 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 "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "guncon.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_GunCon : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_GunCon(void);
|
||||
virtual ~InputDevice_GunCon();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
virtual void SetCrosshairsColor(uint32 color);
|
||||
virtual bool RequireNoFrameskip(void);
|
||||
virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
bool dtr;
|
||||
|
||||
uint8 buttons;
|
||||
bool trigger_eff;
|
||||
bool trigger_noclear;
|
||||
uint16 hit_x, hit_y;
|
||||
|
||||
int32 nom_x, nom_y;
|
||||
int32 os_shot_counter;
|
||||
bool prev_oss;
|
||||
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
|
||||
uint8 transmit_buffer[16];
|
||||
uint32 transmit_pos;
|
||||
uint32 transmit_count;
|
||||
|
||||
//
|
||||
// Video timing stuff
|
||||
bool prev_vsync;
|
||||
int line_counter;
|
||||
|
||||
//
|
||||
unsigned chair_r, chair_g, chair_b;
|
||||
bool draw_chair;
|
||||
};
|
||||
|
||||
InputDevice_GunCon::InputDevice_GunCon(void) : chair_r(0), chair_g(0), chair_b(0), draw_chair(false)
|
||||
{
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_GunCon::~InputDevice_GunCon()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_GunCon::SetCrosshairsColor(uint32 color)
|
||||
{
|
||||
chair_r = (color >> 16) & 0xFF;
|
||||
chair_g = (color >> 8) & 0xFF;
|
||||
chair_b = (color >> 0) & 0xFF;
|
||||
|
||||
draw_chair = (color != (1 << 24));
|
||||
}
|
||||
|
||||
void InputDevice_GunCon::Power(void)
|
||||
{
|
||||
dtr = 0;
|
||||
|
||||
buttons = 0;
|
||||
trigger_eff = 0;
|
||||
trigger_noclear = 0;
|
||||
hit_x = 0;
|
||||
hit_y = 0;
|
||||
|
||||
nom_x = 0;
|
||||
nom_y = 0;
|
||||
|
||||
os_shot_counter = 0;
|
||||
prev_oss = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
memset(transmit_buffer, 0, sizeof(transmit_buffer));
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
|
||||
prev_vsync = 0;
|
||||
line_counter = 0;
|
||||
}
|
||||
|
||||
void InputDevice_GunCon::UpdateInput(const void *data)
|
||||
{
|
||||
uint8 *d8 = (uint8 *)data;
|
||||
|
||||
nom_x = MDFN_de32lsb(&d8[0]);
|
||||
nom_y = MDFN_de32lsb(&d8[4]);
|
||||
|
||||
trigger_noclear = (bool)(d8[8] & 0x1);
|
||||
trigger_eff |= trigger_noclear;
|
||||
|
||||
buttons = d8[8] >> 1;
|
||||
|
||||
if(os_shot_counter > 0) // FIXME if UpdateInput() is ever called more than once per video frame(at ~50 or ~60Hz).
|
||||
os_shot_counter--;
|
||||
|
||||
// Eeeeiiiiiight.
|
||||
if((d8[8] & 0x8) && !prev_oss && os_shot_counter == 0)
|
||||
os_shot_counter = 4;
|
||||
prev_oss = d8[8] & 0x8;
|
||||
|
||||
//MDFN_DispMessage("%08x %08x", nom_x, nom_y);
|
||||
}
|
||||
|
||||
bool InputDevice_GunCon::RequireNoFrameskip(void)
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
pscpu_timestamp_t InputDevice_GunCon::GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width,
|
||||
const unsigned pix_clock_offset, const unsigned pix_clock)
|
||||
{
|
||||
if(vsync && !prev_vsync)
|
||||
line_counter = 0;
|
||||
|
||||
if(pixels && pix_clock)
|
||||
{
|
||||
const int avs = 22; // Not 22 for PAL, fixme.
|
||||
int32 gx;
|
||||
int32 gy;
|
||||
|
||||
gx = ((int64)nom_x * width / MDFNGameInfo->nominal_width + 0x8000) >> 16;
|
||||
gy = (nom_y + 0x8000) >> 16;
|
||||
|
||||
for(int32 ix = gx; ix < (gx + (int32)(pix_clock / 762925)); ix++)
|
||||
{
|
||||
if(ix >= 0 && (unsigned)ix < width && line_counter >= (avs + gy) && line_counter < (avs + gy + 8))
|
||||
{
|
||||
int r, g, b, a;
|
||||
|
||||
format->DecodeColor(pixels[ix], r, g, b, a);
|
||||
|
||||
if((r + g + b) >= 0x40) // Wrong, but not COMPLETELY ABSOLUTELY wrong, at least. ;)
|
||||
{
|
||||
hit_x = (int64)(ix + pix_clock_offset) * 8000000 / pix_clock; // GunCon has what appears to be an 8.00MHz ceramic resonator in it.
|
||||
hit_y = line_counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_chair)
|
||||
{
|
||||
if(line_counter == (avs + gy))
|
||||
{
|
||||
const int ic = pix_clock / 762925;
|
||||
|
||||
for(int32 x = std::max<int32>(0, gx - ic); x < std::min<int32>(width, gx + ic); x++)
|
||||
{
|
||||
int r, g, b, a;
|
||||
int nr, ng, nb;
|
||||
|
||||
format->DecodeColor(pixels[x], r, g, b, a);
|
||||
|
||||
nr = (r + chair_r * 3) >> 2;
|
||||
ng = (g + chair_g * 3) >> 2;
|
||||
nb = (b + chair_b * 3) >> 2;
|
||||
|
||||
if(abs((r * 76 + g * 150 + b * 29) - (nr * 76 + ng * 150 + nb * 29)) < 16384)
|
||||
{
|
||||
nr >>= 1;
|
||||
ng >>= 1;
|
||||
nb >>= 1;
|
||||
}
|
||||
|
||||
pixels[x] = format->MakeColor(nr, ng, nb, a);
|
||||
}
|
||||
}
|
||||
else if(line_counter >= (avs + gy - 8) && line_counter <= (avs + gy + 8))
|
||||
{
|
||||
int r, g, b, a;
|
||||
int nr, ng, nb;
|
||||
|
||||
format->DecodeColor(pixels[gx], r, g, b, a);
|
||||
|
||||
nr = (r + chair_r * 3) >> 2;
|
||||
ng = (g + chair_g * 3) >> 2;
|
||||
nb = (b + chair_b * 3) >> 2;
|
||||
|
||||
if(abs((r * 76 + g * 150 + b * 29) - (nr * 76 + ng * 150 + nb * 29)) < 16384)
|
||||
{
|
||||
nr >>= 1;
|
||||
ng >>= 1;
|
||||
nb >>= 1;
|
||||
}
|
||||
|
||||
pixels[gx] = format->MakeColor(nr, ng, nb, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line_counter++;
|
||||
|
||||
return(PSX_EVENT_MAXTS);
|
||||
}
|
||||
|
||||
void InputDevice_GunCon::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
//if(bitpos || transmit_count)
|
||||
// printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_GunCon::GetDSR(void)
|
||||
{
|
||||
if(!dtr)
|
||||
return(0);
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_GunCon::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer[transmit_pos] >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_pos++;
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x01)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
transmit_buffer[0] = 0x63;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//if(receive_buffer)
|
||||
// printf("%02x\n", receive_buffer);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
command_phase++;
|
||||
|
||||
transmit_buffer[0] = 0x5A;
|
||||
|
||||
//puts("MOO");
|
||||
//if(command != 0x42)
|
||||
// fprintf(stderr, "GunCon unhandled command: 0x%02x\n", command);
|
||||
//assert(command == 0x42);
|
||||
if(command == 0x42)
|
||||
{
|
||||
transmit_buffer[1] = 0xFF ^ ((buttons & 0x01) << 3);
|
||||
transmit_buffer[2] = 0xFF ^ (trigger_eff << 5) ^ ((buttons & 0x02) << 5);
|
||||
|
||||
if(os_shot_counter > 0)
|
||||
{
|
||||
hit_x = 0x01;
|
||||
hit_y = 0x0A;
|
||||
transmit_buffer[2] |= (1 << 5);
|
||||
if(os_shot_counter == 2 || os_shot_counter == 3)
|
||||
{
|
||||
transmit_buffer[2] &= ~(1 << 5);
|
||||
}
|
||||
}
|
||||
|
||||
MDFN_en16lsb(&transmit_buffer[3], hit_x);
|
||||
MDFN_en16lsb(&transmit_buffer[5], hit_y);
|
||||
|
||||
hit_x = 0x01;
|
||||
hit_y = 0x0A;
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 7;
|
||||
|
||||
trigger_eff = trigger_noclear;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_phase = -1;
|
||||
transmit_buffer[1] = 0;
|
||||
transmit_buffer[2] = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
dsr_pulse_delay = 100; //0x80; //0x40;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
InputDevice *Device_GunCon_Create(void)
|
||||
{
|
||||
return new InputDevice_GunCon();
|
||||
}
|
||||
|
||||
|
||||
InputDeviceInputInfoStruct Device_GunCon_IDII[6] =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS },
|
||||
|
||||
{ "trigger", "Trigger", 0, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "a", "A", 1, IDIT_BUTTON, NULL },
|
||||
{ "b", "B", 2, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "offscreen_shot", "Offscreen Shot(Simulated)", 3, IDIT_BUTTON, NULL }, // Useful for "Judge Dredd", and probably not much else.
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
11
mednafen/psx-0925/input/guncon.h
Normal file
11
mednafen/psx-0925/input/guncon.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_GUNCON_H
|
||||
#define __MDFN_PSX_INPUT_GUNCON_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice *Device_GunCon_Create(void);
|
||||
extern InputDeviceInputInfoStruct Device_GunCon_IDII[6];
|
||||
|
||||
}
|
||||
#endif
|
393
mednafen/psx-0925/input/justifier.cpp
Normal file
393
mednafen/psx-0925/input/justifier.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
/* 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 "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "justifier.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_Justifier : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_Justifier(void);
|
||||
virtual ~InputDevice_Justifier();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
virtual void SetCrosshairsColor(uint32 color);
|
||||
virtual bool RequireNoFrameskip(void);
|
||||
virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
bool dtr;
|
||||
|
||||
uint8 buttons;
|
||||
bool trigger_eff;
|
||||
bool trigger_noclear;
|
||||
|
||||
bool need_hit_detect;
|
||||
|
||||
int32 nom_x, nom_y;
|
||||
int32 os_shot_counter;
|
||||
bool prev_oss;
|
||||
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
|
||||
uint8 transmit_buffer[16];
|
||||
uint32 transmit_pos;
|
||||
uint32 transmit_count;
|
||||
|
||||
//
|
||||
// Video timing stuff
|
||||
bool prev_vsync;
|
||||
int line_counter;
|
||||
|
||||
//
|
||||
unsigned chair_r, chair_g, chair_b;
|
||||
bool draw_chair;
|
||||
};
|
||||
|
||||
InputDevice_Justifier::InputDevice_Justifier(void) : chair_r(0), chair_g(0), chair_b(0), draw_chair(false)
|
||||
{
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_Justifier::~InputDevice_Justifier()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_Justifier::SetCrosshairsColor(uint32 color)
|
||||
{
|
||||
chair_r = (color >> 16) & 0xFF;
|
||||
chair_g = (color >> 8) & 0xFF;
|
||||
chair_b = (color >> 0) & 0xFF;
|
||||
|
||||
draw_chair = (color != (1 << 24));
|
||||
}
|
||||
|
||||
void InputDevice_Justifier::Power(void)
|
||||
{
|
||||
dtr = 0;
|
||||
|
||||
buttons = 0;
|
||||
trigger_eff = 0;
|
||||
trigger_noclear = 0;
|
||||
|
||||
need_hit_detect = false;
|
||||
|
||||
nom_x = 0;
|
||||
nom_y = 0;
|
||||
|
||||
os_shot_counter = 0;
|
||||
prev_oss = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
memset(transmit_buffer, 0, sizeof(transmit_buffer));
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
|
||||
prev_vsync = 0;
|
||||
line_counter = 0;
|
||||
}
|
||||
|
||||
void InputDevice_Justifier::UpdateInput(const void *data)
|
||||
{
|
||||
uint8 *d8 = (uint8 *)data;
|
||||
|
||||
nom_x = MDFN_de32lsb(&d8[0]);
|
||||
nom_y = MDFN_de32lsb(&d8[4]);
|
||||
|
||||
trigger_noclear = (bool)(d8[8] & 0x1);
|
||||
trigger_eff |= trigger_noclear;
|
||||
|
||||
buttons = (d8[8] >> 1) & 0x3;
|
||||
|
||||
if(os_shot_counter > 0) // FIXME if UpdateInput() is ever called more than once per video frame(at ~50 or ~60Hz).
|
||||
os_shot_counter--;
|
||||
|
||||
if((d8[8] & 0x8) && !prev_oss && os_shot_counter == 0)
|
||||
os_shot_counter = 10;
|
||||
prev_oss = d8[8] & 0x8;
|
||||
}
|
||||
|
||||
bool InputDevice_Justifier::RequireNoFrameskip(void)
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
pscpu_timestamp_t InputDevice_Justifier::GPULineHook(const pscpu_timestamp_t timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width,
|
||||
const unsigned pix_clock_offset, const unsigned pix_clock)
|
||||
{
|
||||
pscpu_timestamp_t ret = PSX_EVENT_MAXTS;
|
||||
|
||||
if(vsync && !prev_vsync)
|
||||
line_counter = 0;
|
||||
|
||||
if(pixels && pix_clock)
|
||||
{
|
||||
const int avs = 22; // Not 22 for PAL, fixme.
|
||||
int32 gx;
|
||||
int32 gy;
|
||||
int32 gxa;
|
||||
|
||||
gx = ((int64)nom_x * width / MDFNGameInfo->nominal_width + 0x8000) >> 16;
|
||||
gy = (nom_y + 0x8000) >> 16;
|
||||
gxa = gx; // - (pix_clock / 400000);
|
||||
//if(gxa < 0 && gx >= 0)
|
||||
// gxa = 0;
|
||||
|
||||
if(!os_shot_counter && need_hit_detect && gxa >= 0 && gxa < (int)width && line_counter >= (avs + gy - 1) && line_counter <= (avs + gy + 1))
|
||||
{
|
||||
int r, g, b, a;
|
||||
|
||||
format->DecodeColor(pixels[gxa], r, g, b, a);
|
||||
|
||||
if((r + g + b) >= 0x40) // Wrong, but not COMPLETELY ABSOLUTELY wrong, at least. ;)
|
||||
{
|
||||
ret = timestamp + (int64)(gxa + pix_clock_offset) * (44100 * 768) / pix_clock - 181;
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_chair)
|
||||
{
|
||||
if(line_counter == (avs + gy))
|
||||
{
|
||||
const int ic = pix_clock / 762925;
|
||||
|
||||
for(int32 x = std::max<int32>(0, gx - ic); x < std::min<int32>(width, gx + ic); x++)
|
||||
{
|
||||
int r, g, b, a;
|
||||
int nr, ng, nb;
|
||||
|
||||
format->DecodeColor(pixels[x], r, g, b, a);
|
||||
|
||||
nr = (r + chair_r * 3) >> 2;
|
||||
ng = (g + chair_g * 3) >> 2;
|
||||
nb = (b + chair_b * 3) >> 2;
|
||||
|
||||
if(abs((r * 76 + g * 150 + b * 29) - (nr * 76 + ng * 150 + nb * 29)) < 16384)
|
||||
{
|
||||
nr >>= 1;
|
||||
ng >>= 1;
|
||||
nb >>= 1;
|
||||
}
|
||||
|
||||
pixels[x] = format->MakeColor(nr, ng, nb, a);
|
||||
}
|
||||
}
|
||||
else if(line_counter >= (avs + gy - 8) && line_counter <= (avs + gy + 8))
|
||||
{
|
||||
int r, g, b, a;
|
||||
int nr, ng, nb;
|
||||
|
||||
format->DecodeColor(pixels[gx], r, g, b, a);
|
||||
|
||||
nr = (r + chair_r * 3) >> 2;
|
||||
ng = (g + chair_g * 3) >> 2;
|
||||
nb = (b + chair_b * 3) >> 2;
|
||||
|
||||
if(abs((r * 76 + g * 150 + b * 29) - (nr * 76 + ng * 150 + nb * 29)) < 16384)
|
||||
{
|
||||
nr >>= 1;
|
||||
ng >>= 1;
|
||||
nb >>= 1;
|
||||
}
|
||||
|
||||
pixels[gx] = format->MakeColor(nr, ng, nb, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line_counter++;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void InputDevice_Justifier::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
//if(bitpos || transmit_count)
|
||||
// printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_Justifier::GetDSR(void)
|
||||
{
|
||||
if(!dtr)
|
||||
return(0);
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_Justifier::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer[transmit_pos] >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_pos++;
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x01)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
transmit_buffer[0] = 0x31;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//if(receive_buffer)
|
||||
// printf("%02x\n", receive_buffer);
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
need_hit_detect = receive_buffer & 0x10; // TODO, see if it's (val&0x10) == 0x10, or some other mask value.
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
command_phase++;
|
||||
|
||||
transmit_buffer[0] = 0x5A;
|
||||
|
||||
//if(command != 0x42)
|
||||
// fprintf(stderr, "Justifier unhandled command: 0x%02x\n", command);
|
||||
//assert(command == 0x42);
|
||||
if(command == 0x42)
|
||||
{
|
||||
transmit_buffer[1] = 0xFF ^ ((buttons & 2) << 2);
|
||||
transmit_buffer[2] = 0xFF ^ (trigger_eff << 7) ^ ((buttons & 1) << 6);
|
||||
|
||||
if(os_shot_counter > 0)
|
||||
{
|
||||
transmit_buffer[2] |= (1 << 7);
|
||||
if(os_shot_counter == 6 || os_shot_counter == 5)
|
||||
{
|
||||
transmit_buffer[2] &= ~(1 << 7);
|
||||
}
|
||||
}
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 3;
|
||||
|
||||
trigger_eff = trigger_noclear;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_phase = -1;
|
||||
transmit_buffer[1] = 0;
|
||||
transmit_buffer[2] = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
dsr_pulse_delay = 200;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
InputDevice *Device_Justifier_Create(void)
|
||||
{
|
||||
return new InputDevice_Justifier();
|
||||
}
|
||||
|
||||
|
||||
InputDeviceInputInfoStruct Device_Justifier_IDII[6] =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS },
|
||||
|
||||
{ "trigger", "Trigger", 0, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "o", "O", 1, IDIT_BUTTON, NULL },
|
||||
{ "start", "Start", 2, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "offscreen_shot", "Offscreen Shot(Simulated)", 3, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
11
mednafen/psx-0925/input/justifier.h
Normal file
11
mednafen/psx-0925/input/justifier.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_JUSTIFIER_H
|
||||
#define __MDFN_PSX_INPUT_JUSTIFIER_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice *Device_Justifier_Create(void);
|
||||
extern InputDeviceInputInfoStruct Device_Justifier_IDII[6];
|
||||
|
||||
}
|
||||
#endif
|
448
mednafen/psx-0925/input/memcard.cpp
Normal file
448
mednafen/psx-0925/input/memcard.cpp
Normal file
@ -0,0 +1,448 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
// I could find no other commands than 'R', 'W', and 'S' (not sure what 'S' is for, however)
|
||||
|
||||
#include "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "memcard.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_Memcard : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_Memcard();
|
||||
virtual ~InputDevice_Memcard();
|
||||
|
||||
virtual void Power(void);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
//
|
||||
//
|
||||
virtual uint32 GetNVSize(void);
|
||||
virtual void ReadNV(uint8 *buffer, uint32 offset, uint32 size);
|
||||
virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 size);
|
||||
|
||||
virtual uint64 GetNVDirtyCount(void);
|
||||
virtual void ResetNVDirtyCount(void);
|
||||
|
||||
private:
|
||||
|
||||
bool presence_new;
|
||||
|
||||
uint8 card_data[1 << 17];
|
||||
uint8 rw_buffer[128];
|
||||
uint8 write_xor;
|
||||
|
||||
uint64 dirty_count;
|
||||
|
||||
bool dtr;
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
uint16 addr;
|
||||
uint8 calced_xor;
|
||||
|
||||
uint8 transmit_buffer;
|
||||
uint32 transmit_count;
|
||||
};
|
||||
|
||||
InputDevice_Memcard::InputDevice_Memcard()
|
||||
{
|
||||
Power();
|
||||
|
||||
dirty_count = 0;
|
||||
|
||||
// Init memcard as formatted.
|
||||
assert(sizeof(card_data) == (1 << 17));
|
||||
memset(card_data, 0x00, sizeof(card_data));
|
||||
|
||||
card_data[0x00] = 0x4D;
|
||||
card_data[0x01] = 0x43;
|
||||
card_data[0x7F] = 0x0E;
|
||||
|
||||
for(unsigned int A = 0x80; A < 0x800; A += 0x80)
|
||||
{
|
||||
card_data[A + 0x00] = 0xA0;
|
||||
card_data[A + 0x08] = 0xFF;
|
||||
card_data[A + 0x09] = 0xFF;
|
||||
card_data[A + 0x7F] = 0xA0;
|
||||
}
|
||||
|
||||
for(unsigned int A = 0x0800; A < 0x1200; A += 0x80)
|
||||
{
|
||||
card_data[A + 0x00] = 0xFF;
|
||||
card_data[A + 0x01] = 0xFF;
|
||||
card_data[A + 0x02] = 0xFF;
|
||||
card_data[A + 0x03] = 0xFF;
|
||||
card_data[A + 0x08] = 0xFF;
|
||||
card_data[A + 0x09] = 0xFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InputDevice_Memcard::~InputDevice_Memcard()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::Power(void)
|
||||
{
|
||||
dtr = 0;
|
||||
|
||||
//buttons[0] = buttons[1] = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
transmit_buffer = 0;
|
||||
|
||||
transmit_count = 0;
|
||||
|
||||
addr = 0;
|
||||
|
||||
presence_new = true;
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
if(command_phase > 0)
|
||||
PSX_WARNING("[MCR] Communication aborted???");
|
||||
}
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_Memcard::GetDSR(void)
|
||||
{
|
||||
if(!dtr)
|
||||
return(0);
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_Memcard::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//if(command_phase > 0 || transmit_count)
|
||||
// printf("[MCRDATA] Received_data=0x%02x, Sent_data=0x%02x\n", receive_buffer, transmit_buffer);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x81)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
//printf("[MCR] Device selected\n");
|
||||
transmit_buffer = presence_new ? 0x08 : 0x00;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
//printf("[MCR] Command received: %c\n", command);
|
||||
if(command == 'R' || command == 'W')
|
||||
{
|
||||
command_phase++;
|
||||
transmit_buffer = 0x5A;
|
||||
transmit_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(command == 'S')
|
||||
{
|
||||
PSX_WARNING("[MCR] Memcard S command unsupported.");
|
||||
}
|
||||
|
||||
command_phase = -1;
|
||||
transmit_buffer = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
transmit_buffer = 0x5D;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
transmit_buffer = 0x00;
|
||||
transmit_count = 1;
|
||||
if(command == 'R')
|
||||
command_phase = 1000;
|
||||
else if(command == 'W')
|
||||
command_phase = 2000;
|
||||
break;
|
||||
|
||||
//
|
||||
// Read
|
||||
//
|
||||
case 1000:
|
||||
addr = receive_buffer << 8;
|
||||
transmit_buffer = receive_buffer;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 1001:
|
||||
addr |= receive_buffer & 0xFF;
|
||||
transmit_buffer = '\\';
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 1002:
|
||||
//printf("[MCR] READ ADDR=0x%04x\n", addr);
|
||||
if(addr >= (sizeof(card_data) >> 7))
|
||||
addr = 0xFFFF;
|
||||
|
||||
calced_xor = 0;
|
||||
transmit_buffer = ']';
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
|
||||
// TODO: enable this code(or something like it) when CPU instruction timing is a bit better.
|
||||
//
|
||||
//dsr_pulse_delay = 32000;
|
||||
//goto SkipDPD;
|
||||
//
|
||||
|
||||
break;
|
||||
|
||||
case 1003:
|
||||
transmit_buffer = addr >> 8;
|
||||
calced_xor ^= transmit_buffer;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 1004:
|
||||
transmit_buffer = addr & 0xFF;
|
||||
calced_xor ^= transmit_buffer;
|
||||
|
||||
if(addr == 0xFFFF)
|
||||
{
|
||||
transmit_count = 1;
|
||||
command_phase = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
transmit_count = 1;
|
||||
command_phase = 1024;
|
||||
}
|
||||
break;
|
||||
|
||||
// Transmit actual 128 bytes data
|
||||
case (1024 + 0) ... (1024 + 128 - 1):
|
||||
transmit_buffer = card_data[(addr << 7) + (command_phase - 1024)];
|
||||
calced_xor ^= transmit_buffer;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
// XOR
|
||||
case (1024 + 128):
|
||||
transmit_buffer = calced_xor;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
// End flag
|
||||
case (1024 + 129):
|
||||
transmit_buffer = 'G';
|
||||
transmit_count = 1;
|
||||
command_phase = -1;
|
||||
break;
|
||||
|
||||
//
|
||||
// Write
|
||||
//
|
||||
case 2000:
|
||||
calced_xor = receive_buffer;
|
||||
addr = receive_buffer << 8;
|
||||
transmit_buffer = receive_buffer;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case 2001:
|
||||
calced_xor ^= receive_buffer;
|
||||
addr |= receive_buffer & 0xFF;
|
||||
//printf("[MCR] WRITE ADDR=0x%04x\n", addr);
|
||||
transmit_buffer = receive_buffer;
|
||||
transmit_count = 1;
|
||||
command_phase = 2048;
|
||||
break;
|
||||
|
||||
case (2048 + 0) ... (2048 + 128 - 1):
|
||||
calced_xor ^= receive_buffer;
|
||||
rw_buffer[command_phase - 2048] = receive_buffer;
|
||||
|
||||
transmit_buffer = receive_buffer;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case (2048 + 128): // XOR
|
||||
write_xor = receive_buffer;
|
||||
transmit_buffer = '\\';
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case (2048 + 129):
|
||||
transmit_buffer = ']';
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
break;
|
||||
|
||||
case (2048 + 130): // End flag
|
||||
//MDFN_DispMessage("%02x %02x", calced_xor, write_xor);
|
||||
//printf("[MCR] Write End. Actual_XOR=0x%02x, CW_XOR=0x%02x\n", calced_xor, write_xor);
|
||||
|
||||
if(calced_xor != write_xor)
|
||||
transmit_buffer = 'N';
|
||||
else if(addr >= (sizeof(card_data) >> 7))
|
||||
transmit_buffer = 0xFF;
|
||||
else
|
||||
{
|
||||
transmit_buffer = 'G';
|
||||
presence_new = false;
|
||||
|
||||
// If the current data is different from the data to be written, increment the dirty count.
|
||||
// memcpy()'ing over to card_data is also conditionalized here for a slight optimization.
|
||||
if(memcmp(&card_data[addr << 7], rw_buffer, 128))
|
||||
{
|
||||
memcpy(&card_data[addr << 7], rw_buffer, 128);
|
||||
dirty_count++;
|
||||
}
|
||||
}
|
||||
|
||||
transmit_count = 1;
|
||||
command_phase = -1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//if(command_phase != -1 || transmit_count)
|
||||
// printf("[MCR] Receive: 0x%02x, Send: 0x%02x -- %d\n", receive_buffer, transmit_buffer, command_phase);
|
||||
}
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
dsr_pulse_delay = 0x100;
|
||||
|
||||
//SkipDPD: ;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint32 InputDevice_Memcard::GetNVSize(void)
|
||||
{
|
||||
return(sizeof(card_data));
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::ReadNV(uint8 *buffer, uint32 offset, uint32 size)
|
||||
{
|
||||
while(size--)
|
||||
{
|
||||
*buffer = card_data[offset & (sizeof(card_data) - 1)];
|
||||
buffer++;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::WriteNV(const uint8 *buffer, uint32 offset, uint32 size)
|
||||
{
|
||||
if(size)
|
||||
dirty_count++;
|
||||
|
||||
while(size--)
|
||||
{
|
||||
card_data[offset & (sizeof(card_data) - 1)] = *buffer;
|
||||
buffer++;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 InputDevice_Memcard::GetNVDirtyCount(void)
|
||||
{
|
||||
return(dirty_count);
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::ResetNVDirtyCount(void)
|
||||
{
|
||||
dirty_count = 0;
|
||||
}
|
||||
|
||||
|
||||
InputDevice *Device_Memcard_Create(void)
|
||||
{
|
||||
return new InputDevice_Memcard();
|
||||
}
|
||||
|
||||
}
|
11
mednafen/psx-0925/input/memcard.h
Normal file
11
mednafen/psx-0925/input/memcard.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_MEMCARD_H
|
||||
#define __MDFN_PSX_INPUT_MEMCARD_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice *Device_Memcard_Create(void);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
252
mednafen/psx-0925/input/mouse.cpp
Normal file
252
mednafen/psx-0925/input/mouse.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
#include "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "mouse.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_Mouse : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_Mouse();
|
||||
virtual ~InputDevice_Mouse();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
|
||||
virtual void Update(const pscpu_timestamp_t timestamp);
|
||||
virtual void ResetTS(void);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
int32 lastts;
|
||||
int32 clear_timeout;
|
||||
|
||||
bool dtr;
|
||||
|
||||
uint8 button;
|
||||
uint8 button_post_mask;
|
||||
int32 accum_xdelta;
|
||||
int32 accum_ydelta;
|
||||
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
|
||||
uint8 transmit_buffer[5];
|
||||
uint32 transmit_pos;
|
||||
uint32 transmit_count;
|
||||
};
|
||||
|
||||
InputDevice_Mouse::InputDevice_Mouse()
|
||||
{
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_Mouse::~InputDevice_Mouse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_Mouse::Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
int32 cycles = timestamp - lastts;
|
||||
|
||||
clear_timeout += cycles;
|
||||
if(clear_timeout >= (33868800 / 4))
|
||||
{
|
||||
//puts("Mouse timeout\n");
|
||||
clear_timeout = 0;
|
||||
accum_xdelta = 0;
|
||||
accum_ydelta = 0;
|
||||
button &= button_post_mask;
|
||||
}
|
||||
|
||||
lastts = timestamp;
|
||||
}
|
||||
|
||||
void InputDevice_Mouse::ResetTS(void)
|
||||
{
|
||||
lastts = 0;
|
||||
}
|
||||
|
||||
void InputDevice_Mouse::Power(void)
|
||||
{
|
||||
lastts = 0;
|
||||
clear_timeout = 0;
|
||||
|
||||
dtr = 0;
|
||||
|
||||
button = 0;
|
||||
button_post_mask = 0;
|
||||
accum_xdelta = 0;
|
||||
accum_ydelta = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
memset(transmit_buffer, 0, sizeof(transmit_buffer));
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
|
||||
void InputDevice_Mouse::UpdateInput(const void *data)
|
||||
{
|
||||
accum_xdelta += (int32)MDFN_de32lsb((uint8*)data + 0);
|
||||
accum_ydelta += (int32)MDFN_de32lsb((uint8*)data + 4);
|
||||
|
||||
if(accum_xdelta > 30 * 127) accum_xdelta = 30 * 127;
|
||||
if(accum_xdelta < 30 * -128) accum_xdelta = 30 * -128;
|
||||
|
||||
if(accum_ydelta > 30 * 127) accum_ydelta = 30 * 127;
|
||||
if(accum_ydelta < 30 * -128) accum_ydelta = 30 * -128;
|
||||
|
||||
button |= *((uint8 *)data + 8);
|
||||
button_post_mask = *((uint8 *)data + 8);
|
||||
|
||||
//if(button)
|
||||
// MDFN_DispMessage("Button\n");
|
||||
//printf("%d %d\n", accum_xdelta, accum_ydelta);
|
||||
}
|
||||
|
||||
|
||||
void InputDevice_Mouse::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
//if(bitpos || transmit_count)
|
||||
// printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_Mouse::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer[transmit_pos] >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_pos++;
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x01)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
transmit_buffer[0] = 0x12;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
command_phase++;
|
||||
|
||||
transmit_buffer[0] = 0x5A;
|
||||
|
||||
if(command == 0x42)
|
||||
{
|
||||
int32 xdelta = accum_xdelta;
|
||||
int32 ydelta = accum_ydelta;
|
||||
|
||||
if(xdelta < -128) xdelta = -128;
|
||||
if(xdelta > 127) xdelta = 127;
|
||||
|
||||
if(ydelta < -128) ydelta = -128;
|
||||
if(ydelta > 127) ydelta = 127;
|
||||
|
||||
transmit_buffer[1] = 0xFF;
|
||||
transmit_buffer[2] = 0xFC ^ (button << 2);
|
||||
transmit_buffer[3] = xdelta;
|
||||
transmit_buffer[4] = ydelta;
|
||||
|
||||
accum_xdelta -= xdelta;
|
||||
accum_ydelta -= ydelta;
|
||||
|
||||
button &= button_post_mask;
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 5;
|
||||
|
||||
clear_timeout = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_phase = -1;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
dsr_pulse_delay = 0x40; //0x100;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
InputDevice *Device_Mouse_Create(void)
|
||||
{
|
||||
return new InputDevice_Mouse();
|
||||
}
|
||||
|
||||
|
||||
InputDeviceInputInfoStruct Device_Mouse_IDII[4] =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS_REL },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL },
|
||||
{ "right", "Right Button", 1, IDIT_BUTTON, NULL },
|
||||
{ "left", "Left Button", 0, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
11
mednafen/psx-0925/input/mouse.h
Normal file
11
mednafen/psx-0925/input/mouse.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __MDFN_PSX_INPUT_MOUSE_H
|
||||
#define __MDFN_PSX_INPUT_MOUSE_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice *Device_Mouse_Create(void);
|
||||
extern InputDeviceInputInfoStruct Device_Mouse_IDII[4];
|
||||
|
||||
}
|
||||
#endif
|
335
mednafen/psx-0925/input/multitap.cpp
Normal file
335
mednafen/psx-0925/input/multitap.cpp
Normal file
@ -0,0 +1,335 @@
|
||||
#include "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "multitap.h"
|
||||
|
||||
/*
|
||||
Notes from tests on real thing(not necessarily emulated the same way here):
|
||||
|
||||
Manual port selection read mode:
|
||||
Write 0x01-0x04 instead of 0x01 as first byte, selects port(1=A,2=B,3=C,4=D) to access.
|
||||
|
||||
Ports that don't exist(0x00, 0x05-0xFF) or don't have a device plugged in will not respond(no DSR pulse).
|
||||
|
||||
Full read mode:
|
||||
Bit0 of third byte(from-zero-index=0x02) should be set to 1 to enter full read mode, on subsequent reads.
|
||||
|
||||
Appears to require a controller to be plugged into the port specified by the first byte as per manual port selection read mode,
|
||||
to write the byte necessary to enter full-read mode; but once the third byte with the bit set has been written, no controller in
|
||||
that port is required for doing full reads(and the manual port selection is ignored when doing a full read).
|
||||
|
||||
However, if there are no controllers plugged in, or the first byte written in a full-mode communication has one or more bits in the upper
|
||||
nybble set to 1, the returned data will be short:
|
||||
% 0: 0xff
|
||||
% 1: 0x80
|
||||
% 2: 0x5a
|
||||
|
||||
Example full-read bytestream(with controllers plugged into port A, port B, and port C, with port D empty):
|
||||
% 0: 0xff
|
||||
% 1: 0x80
|
||||
% 2: 0x5a
|
||||
|
||||
% 3: 0x73 (Port A controller data start)
|
||||
% 4: 0x5a
|
||||
% 5: 0xff
|
||||
% 6: 0xff
|
||||
% 7: 0x80
|
||||
% 8: 0x8c
|
||||
% 9: 0x79
|
||||
% 10: 0x8f
|
||||
|
||||
% 11: 0x53 (Port B controller data start)
|
||||
% 12: 0x5a
|
||||
% 13: 0xff
|
||||
% 14: 0xff
|
||||
% 15: 0x80
|
||||
% 16: 0x80
|
||||
% 17: 0x75
|
||||
% 18: 0x8e
|
||||
|
||||
% 19: 0x41 (Port C controller data start)
|
||||
% 20: 0x5a
|
||||
% 21: 0xff
|
||||
% 22: 0xff
|
||||
% 23: 0xff
|
||||
% 24: 0xff
|
||||
% 25: 0xff
|
||||
% 26: 0xff
|
||||
|
||||
% 27: 0xff (Port D controller data start)
|
||||
% 28: 0xff
|
||||
% 29: 0xff
|
||||
% 30: 0xff
|
||||
% 31: 0xff
|
||||
% 32: 0xff
|
||||
% 33: 0xff
|
||||
% 34: 0xff
|
||||
|
||||
*/
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
InputDevice_Multitap::InputDevice_Multitap()
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
pad_devices[i] = NULL;
|
||||
mc_devices[i] = NULL;
|
||||
}
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_Multitap::~InputDevice_Multitap()
|
||||
{
|
||||
}
|
||||
|
||||
void InputDevice_Multitap::SetSubDevice(unsigned int sub_index, InputDevice *device, InputDevice *mc_device)
|
||||
{
|
||||
assert(sub_index < 4);
|
||||
|
||||
//printf("%d\n", sub_index);
|
||||
|
||||
pad_devices[sub_index] = device;
|
||||
mc_devices[sub_index] = mc_device;
|
||||
}
|
||||
|
||||
|
||||
void InputDevice_Multitap::Power(void)
|
||||
{
|
||||
selected_device = -1;
|
||||
bit_counter = 0;
|
||||
receive_buffer = 0;
|
||||
byte_counter = 0;
|
||||
|
||||
mc_mode = false;
|
||||
full_mode = false;
|
||||
full_mode_setting = false;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(pad_devices[i])
|
||||
pad_devices[i]->Power();
|
||||
|
||||
if(mc_devices[i])
|
||||
mc_devices[i]->Power();
|
||||
}
|
||||
}
|
||||
|
||||
void InputDevice_Multitap::SetDTR(bool new_dtr)
|
||||
{
|
||||
bool old_dtr = dtr;
|
||||
dtr = new_dtr;
|
||||
|
||||
if(!dtr)
|
||||
{
|
||||
bit_counter = 0;
|
||||
byte_counter = 0;
|
||||
receive_buffer = 0;
|
||||
selected_device = -1;
|
||||
mc_mode = false;
|
||||
full_mode = false;
|
||||
}
|
||||
|
||||
if(!old_dtr && dtr)
|
||||
{
|
||||
full_mode = full_mode_setting;
|
||||
//if(full_mode) {
|
||||
// printf("Full mode start\n"); }
|
||||
}
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
pad_devices[i]->SetDTR(dtr);
|
||||
mc_devices[i]->SetDTR(dtr);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputDevice_Multitap::GetDSR(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_Multitap::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
bool ret = 1;
|
||||
bool mangled_txd = TxD;
|
||||
int32 tmp_pulse_delay[2][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
|
||||
|
||||
//printf("Receive bit: %d\n", TxD);
|
||||
//printf("TxD %d\n", TxD);
|
||||
|
||||
receive_buffer &= ~ (1 << bit_counter);
|
||||
receive_buffer |= TxD << bit_counter;
|
||||
|
||||
if(1)
|
||||
{
|
||||
uint8 sub_clock = 0;
|
||||
uint8 sub_rxd_ignore = 0;
|
||||
|
||||
if(full_mode)
|
||||
{
|
||||
if(byte_counter == 0)
|
||||
{
|
||||
sub_clock = 0;
|
||||
sub_rxd_ignore = 0xF;
|
||||
}
|
||||
else if(byte_counter == 1)
|
||||
{
|
||||
ret = (0x80 >> bit_counter) & 1;
|
||||
sub_clock = false;
|
||||
sub_rxd_ignore = 0xF;
|
||||
}
|
||||
else if(byte_counter == 2)
|
||||
{
|
||||
ret = (0x5A >> bit_counter) & 1;
|
||||
sub_rxd_ignore = 0xF;
|
||||
|
||||
if(!mc_mode)
|
||||
{
|
||||
sub_clock = 0xF;
|
||||
mangled_txd = (0x01 >> bit_counter) & 1;
|
||||
}
|
||||
}
|
||||
else if(byte_counter == 0x03 || byte_counter == (0x03 + 0x08 * 1) || byte_counter == (0x03 + 0x08 * 2) || byte_counter == (0x03 + 0x08 * 3))
|
||||
{
|
||||
sub_clock = 1 << selected_device;
|
||||
sub_rxd_ignore = 0;
|
||||
mangled_txd = (command >> bit_counter) & 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sub_clock = 1 << selected_device;
|
||||
sub_rxd_ignore = 0;
|
||||
// Not sure about this, would need to test with rumble-capable device on real thing?
|
||||
//mangled_txd = (0x00 >> bit_counter) & 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(byte_counter == 0)
|
||||
{
|
||||
if(bit_counter < 4)
|
||||
mangled_txd = (0x01 >> bit_counter) & 1;
|
||||
|
||||
sub_clock = 0xF;
|
||||
sub_rxd_ignore = 0xF;
|
||||
}
|
||||
else if((unsigned)selected_device < 4)
|
||||
{
|
||||
sub_clock = 1 << selected_device;
|
||||
sub_rxd_ignore = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
if(sub_clock & (1 << i))
|
||||
{
|
||||
ret &= pad_devices[i]->Clock(mangled_txd, tmp_pulse_delay[0][i]) | ((sub_rxd_ignore >> i) & 1);
|
||||
ret &= mc_devices[i]->Clock(mangled_txd, tmp_pulse_delay[1][i]) | ((sub_rxd_ignore >> i) & 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
static uint8 sendy = 0;
|
||||
|
||||
sendy &= ~(1 << bit_counter);
|
||||
sendy |= ret << bit_counter;
|
||||
|
||||
if(bit_counter == 7)
|
||||
printf("Multitap to PSX: 0x%02x\n", sendy);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bit_counter = (bit_counter + 1) & 0x7;
|
||||
if(bit_counter == 0)
|
||||
{
|
||||
if(byte_counter == 0)
|
||||
{
|
||||
mc_mode = (bool)(receive_buffer & 0xF0);
|
||||
|
||||
//printf("Full mode: %d %d %d\n", full_mode, bit_counter, byte_counter);
|
||||
|
||||
if(full_mode)
|
||||
selected_device = 0;
|
||||
else
|
||||
{
|
||||
//printf("Device select: %02x\n", receive_buffer);
|
||||
selected_device = ((receive_buffer & 0xF) - 1) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if(byte_counter == 1)
|
||||
{
|
||||
command = receive_buffer;
|
||||
//printf("Multitap sub-command: %02x\n", command);
|
||||
}
|
||||
|
||||
if((!mc_mode || full_mode) && byte_counter == 2 && command == 0x42)
|
||||
{
|
||||
//printf("Full mode setting: %02x\n", receive_buffer);
|
||||
full_mode_setting = receive_buffer & 0x01;
|
||||
}
|
||||
|
||||
// Handle DSR stuff
|
||||
if(full_mode)
|
||||
{
|
||||
if(byte_counter == 0 || byte_counter == 1)
|
||||
dsr_pulse_delay = 0x40;
|
||||
else if(byte_counter == 2 || byte_counter == 3)
|
||||
{
|
||||
//int32 td = 0;
|
||||
//for(int i = 0; i < 4; i++)
|
||||
//{
|
||||
// td = std::max<int32>(td, tmp_pulse_delay[0][i]);
|
||||
// td = std::max<int32>(td, tmp_pulse_delay[1][i]);
|
||||
//}
|
||||
//dsr_pulse_delay = td;
|
||||
//printf("%d %d\n", byte_counter, dsr_pulse_delay);
|
||||
|
||||
// Just route the first port's DSR through here; at least one game relies on this(Formula One 2000), or else it freezes. Well, even when it doesn't
|
||||
// freeze, the game crashes(as of Jan 20, 2012), but that's not the multitap emulation's fault. :b
|
||||
dsr_pulse_delay = std::max<int32>(tmp_pulse_delay[0][0], tmp_pulse_delay[1][0]);
|
||||
}
|
||||
else if(byte_counter > 3 && byte_counter < 34)
|
||||
{
|
||||
dsr_pulse_delay = 0x80;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((unsigned)selected_device < 4)
|
||||
{
|
||||
dsr_pulse_delay = std::max<int32>(tmp_pulse_delay[0][selected_device], tmp_pulse_delay[1][selected_device]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
//printf("Byte Counter Increment\n");
|
||||
if(byte_counter < 255)
|
||||
byte_counter++;
|
||||
|
||||
if(full_mode && (byte_counter == (0x03 + 0x08 * 1) || byte_counter == (0x03 + 0x08 * 2) || byte_counter == (0x03 + 0x08 * 3)))
|
||||
{
|
||||
//printf("Device Select Increment\n");
|
||||
selected_device++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
45
mednafen/psx-0925/input/multitap.h
Normal file
45
mednafen/psx-0925/input/multitap.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef __MDFN_PSX_INPUT_MULTITAP_H
|
||||
#define __MDFN_PSX_INPUT_MULTITAP_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_Multitap : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_Multitap();
|
||||
virtual ~InputDevice_Multitap();
|
||||
virtual void Power(void);
|
||||
|
||||
void SetSubDevice(unsigned int sub_index, InputDevice *device, InputDevice *mc_device);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
InputDevice *pad_devices[4];
|
||||
InputDevice *mc_devices[4];
|
||||
|
||||
bool dtr;
|
||||
|
||||
int selected_device;
|
||||
bool full_mode_setting;
|
||||
|
||||
bool full_mode;
|
||||
bool mc_mode;
|
||||
|
||||
uint8 command;
|
||||
uint8 receive_buffer;
|
||||
uint8 bit_counter;
|
||||
uint8 byte_counter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
259
mednafen/psx-0925/input/negcon.cpp
Normal file
259
mednafen/psx-0925/input/negcon.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
/* 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 "../psx.h"
|
||||
#include "../frontio.h"
|
||||
#include "negcon.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
class InputDevice_neGcon : public InputDevice
|
||||
{
|
||||
public:
|
||||
|
||||
InputDevice_neGcon(void);
|
||||
virtual ~InputDevice_neGcon();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void SetDTR(bool new_dtr);
|
||||
virtual bool GetDSR(void);
|
||||
virtual bool Clock(bool TxD, int32 &dsr_pulse_delay);
|
||||
|
||||
private:
|
||||
|
||||
bool dtr;
|
||||
|
||||
uint8 buttons[2];
|
||||
uint8 twist;
|
||||
uint8 anabuttons[3];
|
||||
|
||||
int32 command_phase;
|
||||
uint32 bitpos;
|
||||
uint8 receive_buffer;
|
||||
|
||||
uint8 command;
|
||||
|
||||
uint8 transmit_buffer[8];
|
||||
uint32 transmit_pos;
|
||||
uint32 transmit_count;
|
||||
};
|
||||
|
||||
InputDevice_neGcon::InputDevice_neGcon(void)
|
||||
{
|
||||
Power();
|
||||
}
|
||||
|
||||
InputDevice_neGcon::~InputDevice_neGcon()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InputDevice_neGcon::Power(void)
|
||||
{
|
||||
dtr = 0;
|
||||
|
||||
buttons[0] = buttons[1] = 0;
|
||||
twist = 0;
|
||||
anabuttons[0] = 0;
|
||||
anabuttons[1] = 0;
|
||||
anabuttons[2] = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
|
||||
memset(transmit_buffer, 0, sizeof(transmit_buffer));
|
||||
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
|
||||
void InputDevice_neGcon::UpdateInput(const void *data)
|
||||
{
|
||||
uint8 *d8 = (uint8 *)data;
|
||||
|
||||
buttons[0] = d8[0];
|
||||
buttons[1] = d8[1];
|
||||
|
||||
twist = ((32768 + MDFN_de32lsb((const uint8 *)data + 4) - (((int32)MDFN_de32lsb((const uint8 *)data + 8) * 32768 + 16383) / 32767)) * 255 + 32767) / 65535;
|
||||
|
||||
anabuttons[0] = (MDFN_de32lsb((const uint8 *)data + 12) * 255 + 16383) / 32767;
|
||||
anabuttons[1] = (MDFN_de32lsb((const uint8 *)data + 16) * 255 + 16383) / 32767;
|
||||
anabuttons[2] = (MDFN_de32lsb((const uint8 *)data + 20) * 255 + 16383) / 32767;
|
||||
|
||||
//printf("%02x %02x %02x %02x\n", twist, anabuttons[0], anabuttons[1], anabuttons[2]);
|
||||
}
|
||||
|
||||
|
||||
void InputDevice_neGcon::SetDTR(bool new_dtr)
|
||||
{
|
||||
if(!dtr && new_dtr)
|
||||
{
|
||||
command_phase = 0;
|
||||
bitpos = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
else if(dtr && !new_dtr)
|
||||
{
|
||||
//if(bitpos || transmit_count)
|
||||
// printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
dtr = new_dtr;
|
||||
}
|
||||
|
||||
bool InputDevice_neGcon::GetDSR(void)
|
||||
{
|
||||
if(!dtr)
|
||||
return(0);
|
||||
|
||||
if(!bitpos && transmit_count)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool InputDevice_neGcon::Clock(bool TxD, int32 &dsr_pulse_delay)
|
||||
{
|
||||
bool ret = 1;
|
||||
|
||||
dsr_pulse_delay = 0;
|
||||
|
||||
if(!dtr)
|
||||
return(1);
|
||||
|
||||
if(transmit_count)
|
||||
ret = (transmit_buffer[transmit_pos] >> bitpos) & 1;
|
||||
|
||||
receive_buffer &= ~(1 << bitpos);
|
||||
receive_buffer |= TxD << bitpos;
|
||||
bitpos = (bitpos + 1) & 0x7;
|
||||
|
||||
if(!bitpos)
|
||||
{
|
||||
//printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase);
|
||||
|
||||
if(transmit_count)
|
||||
{
|
||||
transmit_pos++;
|
||||
transmit_count--;
|
||||
}
|
||||
|
||||
|
||||
switch(command_phase)
|
||||
{
|
||||
case 0:
|
||||
if(receive_buffer != 0x01)
|
||||
command_phase = -1;
|
||||
else
|
||||
{
|
||||
transmit_buffer[0] = 0x23;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 1;
|
||||
command_phase++;
|
||||
dsr_pulse_delay = 256;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
command = receive_buffer;
|
||||
command_phase++;
|
||||
|
||||
transmit_buffer[0] = 0x5A;
|
||||
|
||||
//if(command != 0x42)
|
||||
// fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command);
|
||||
|
||||
if(command == 0x42)
|
||||
{
|
||||
transmit_buffer[1] = 0xFF ^ buttons[0];
|
||||
transmit_buffer[2] = 0xFF ^ buttons[1];
|
||||
transmit_buffer[3] = twist; // Twist, 0x00 through 0xFF, 0x80 center.
|
||||
transmit_buffer[4] = anabuttons[0]; // Analog button I, 0x00 through 0xFF, 0x00 = no pressing, 0xFF = max.
|
||||
transmit_buffer[5] = anabuttons[1]; // Analog button II, ""
|
||||
transmit_buffer[6] = anabuttons[2]; // Left shoulder analog button, ""
|
||||
transmit_pos = 0;
|
||||
transmit_count = 7;
|
||||
dsr_pulse_delay = 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
command_phase = -1;
|
||||
transmit_buffer[1] = 0;
|
||||
transmit_buffer[2] = 0;
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(transmit_count > 0)
|
||||
dsr_pulse_delay = 128;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
InputDevice *Device_neGcon_Create(void)
|
||||
{
|
||||
return new InputDevice_neGcon();
|
||||
}
|
||||
|
||||
|
||||
InputDeviceInputInfoStruct Device_neGcon_IDII[21] =
|
||||
{
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ "start", "START", 4, IDIT_BUTTON, NULL },
|
||||
{ "up", "D-Pad UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "D-Pad RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "D-Pad DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "D-Pad LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ "r", "Right Shoulder", 12, IDIT_BUTTON },
|
||||
|
||||
{ "b", "B", 9, IDIT_BUTTON, NULL },
|
||||
{ "a", "A", 10, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", -1, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "twist_cwise", "Twist ↓|↑ (Analog, Turn Right)", 6, IDIT_BUTTON_ANALOG },
|
||||
{ "twist_ccwise", "Twist ↑|↓ (Analog, Turn Left)", 5, IDIT_BUTTON_ANALOG },
|
||||
{ "i", "I (Analog)", 8, IDIT_BUTTON_ANALOG },
|
||||
{ "ii", "II (Analog)", 7, IDIT_BUTTON_ANALOG },
|
||||
|
||||
{ "l", "Left Shoulder (Analog)", 11, IDIT_BUTTON_ANALOG },
|
||||
};
|
||||
|
||||
}
|
9
mednafen/psx-0925/input/negcon.h
Normal file
9
mednafen/psx-0925/input/negcon.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __MDFN_PSX_INPUT_NEGCON_H
|
||||
#define __MDFN_PSX_INPUT_NEGCON_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
InputDevice *Device_neGcon_Create(void);
|
||||
extern InputDeviceInputInfoStruct Device_neGcon_IDII[21];
|
||||
}
|
||||
#endif
|
174
mednafen/psx-0925/irq.cpp
Normal file
174
mednafen/psx-0925/irq.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/* 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 "psx.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
static uint16 Asserted;
|
||||
static uint16 Mask;
|
||||
static uint16 Status;
|
||||
|
||||
static INLINE void Recalc(void)
|
||||
{
|
||||
CPU->AssertIRQ(0, (bool)(Status & Mask));
|
||||
}
|
||||
|
||||
void IRQ_Power(void)
|
||||
{
|
||||
Asserted = 0;
|
||||
Status = 0;
|
||||
Mask = 0;
|
||||
|
||||
Recalc();
|
||||
}
|
||||
|
||||
int IRQ_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(Asserted),
|
||||
SFVAR(Mask),
|
||||
SFVAR(Status),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "IRQ");
|
||||
|
||||
if(load)
|
||||
{
|
||||
Recalc();
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void IRQ_Assert(int which, bool status)
|
||||
{
|
||||
uint32 old_Asserted = Asserted;
|
||||
//PSX_WARNING("[IRQ] Assert: %d %d", which, status);
|
||||
|
||||
//if(which == IRQ_SPU && status && (Asserted & (1 << which)))
|
||||
// MDFN_DispMessage("SPU IRQ glitch??");
|
||||
|
||||
Asserted &= ~(1 << which);
|
||||
|
||||
if(status)
|
||||
{
|
||||
Asserted |= 1 << which;
|
||||
//Status |= 1 << which;
|
||||
Status |= (old_Asserted ^ Asserted) & Asserted;
|
||||
}
|
||||
|
||||
Recalc();
|
||||
}
|
||||
|
||||
|
||||
void IRQ_Write(uint32 A, uint32 V)
|
||||
{
|
||||
// FIXME if we ever have "accurate" bus emulation
|
||||
V <<= (A & 3) * 8;
|
||||
|
||||
//printf("[IRQ] Write: 0x%08x 0x%08x --- PAD TEMP\n", A, V);
|
||||
|
||||
if(A & 4)
|
||||
Mask = V;
|
||||
else
|
||||
{
|
||||
Status &= V;
|
||||
//Status |= Asserted;
|
||||
}
|
||||
|
||||
Recalc();
|
||||
}
|
||||
|
||||
|
||||
uint32 IRQ_Read(uint32 A)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
if(A & 4)
|
||||
ret = Mask;
|
||||
else
|
||||
ret = Status;
|
||||
|
||||
// FIXME: Might want to move this out to psx.cpp eventually.
|
||||
ret |= 0x1F800000;
|
||||
ret >>= (A & 3) * 8;
|
||||
|
||||
|
||||
//printf("[IRQ] Read: 0x%08x 0x%08x --- PAD TEMP\n", A, ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void IRQ_Reset(void)
|
||||
{
|
||||
Asserted = 0;
|
||||
Status = 0;
|
||||
Mask = 0;
|
||||
|
||||
Recalc();
|
||||
}
|
||||
|
||||
|
||||
uint32 IRQ_GetRegister(unsigned int which, char *special, const uint32 special_len)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
switch(which)
|
||||
{
|
||||
case IRQ_GSREG_ASSERTED:
|
||||
ret = Asserted;
|
||||
break;
|
||||
|
||||
case IRQ_GSREG_STATUS:
|
||||
ret = Status;
|
||||
break;
|
||||
|
||||
case IRQ_GSREG_MASK:
|
||||
ret = Mask;
|
||||
break;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void IRQ_SetRegister(unsigned int which, uint32 value)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
case IRQ_GSREG_ASSERTED:
|
||||
Asserted = value;
|
||||
Recalc();
|
||||
break;
|
||||
|
||||
case IRQ_GSREG_STATUS:
|
||||
Status = value;
|
||||
Recalc();
|
||||
break;
|
||||
|
||||
case IRQ_GSREG_MASK:
|
||||
Mask = value;
|
||||
Recalc();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
43
mednafen/psx-0925/irq.h
Normal file
43
mednafen/psx-0925/irq.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef __MDFN_PSX_IRQ_H
|
||||
#define __MDFN_PSX_IRQ_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
IRQ_VSYNC = 0,
|
||||
IRQ_GPU = 1,
|
||||
IRQ_CD = 2,
|
||||
IRQ_DMA = 3, // Probably
|
||||
IRQ_TIMER_0 = 4,
|
||||
IRQ_TIMER_1 = 5,
|
||||
IRQ_TIMER_2 = 6,
|
||||
IRQ_SIO = 7,
|
||||
IRQ_SPU = 9,
|
||||
IRQ_PIO = 10, // Probably
|
||||
};
|
||||
|
||||
void IRQ_Power(void);
|
||||
void IRQ_Assert(int which, bool asserted);
|
||||
|
||||
void IRQ_Write(uint32 A, uint32 V);
|
||||
uint32 IRQ_Read(uint32 A);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
IRQ_GSREG_ASSERTED = 0,
|
||||
IRQ_GSREG_STATUS = 1,
|
||||
IRQ_GSREG_MASK = 2
|
||||
};
|
||||
|
||||
uint32 IRQ_GetRegister(unsigned int which, char *special, const uint32 special_len);
|
||||
void IRQ_SetRegister(unsigned int which, uint32 value);
|
||||
|
||||
int IRQ_StateAction(StateMem *sm, int load, int data_only);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
543
mednafen/psx-0925/mdec.cpp
Normal file
543
mednafen/psx-0925/mdec.cpp
Normal file
@ -0,0 +1,543 @@
|
||||
/* 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 "psx.h"
|
||||
#include "mdec.h"
|
||||
|
||||
#include "../cdrom/SimpleFIFO.h"
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__SSE2__)
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_POWERPC_ALTIVEC) && defined(HAVE_ALTIVEC_H)
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
|
||||
static bool block_ready;
|
||||
static int32 block_y[2][2][8][8];
|
||||
static int32 block_cb[8][8]; // [y >> 1][x >> 1]
|
||||
static int32 block_cr[8][8]; // [y >> 1][x >> 1]
|
||||
|
||||
static int32 run_time;
|
||||
static uint32 Command;
|
||||
|
||||
static uint8 QMatrix[2][64];
|
||||
static uint32 QMIndex;
|
||||
|
||||
static int16 IDCTMatrix[64] MDFN_ALIGN(16);
|
||||
static uint32 IDCTMIndex;
|
||||
|
||||
static uint8 QScale;
|
||||
|
||||
static int16 Coeff[6][64] MDFN_ALIGN(16);
|
||||
static uint32 CoeffIndex;
|
||||
static uint32 DecodeWB;
|
||||
|
||||
static SimpleFIFO<uint16> InputBuffer(65536);
|
||||
static SimpleFIFO<uint16> OutBuffer(384);
|
||||
|
||||
static uint32 InCounter;
|
||||
static bool BlockEnd;
|
||||
static bool DecodeEnd;
|
||||
|
||||
static const uint8 ZigZag[64] =
|
||||
{
|
||||
0x00, 0x01, 0x08, 0x10, 0x09, 0x02, 0x03, 0x0A,
|
||||
0x11, 0x18, 0x20, 0x19, 0x12, 0x0B, 0x04, 0x05,
|
||||
0x0C, 0x13, 0x1A, 0x21, 0x28, 0x30, 0x29, 0x22,
|
||||
0x1B, 0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1C,
|
||||
0x23, 0x2A, 0x31, 0x38, 0x39, 0x32, 0x2B, 0x24,
|
||||
0x1D, 0x16, 0x0F, 0x17, 0x1E, 0x25, 0x2C, 0x33,
|
||||
0x3A, 0x3B, 0x34, 0x2D, 0x26, 0x1F, 0x27, 0x2E,
|
||||
0x35, 0x3C, 0x3D, 0x36, 0x2F, 0x37, 0x3E, 0x3F
|
||||
};
|
||||
|
||||
void MDEC_Power(void)
|
||||
{
|
||||
run_time = 0;
|
||||
block_ready = false;
|
||||
|
||||
Command = 0;
|
||||
memset(QMatrix, 0, sizeof(QMatrix));
|
||||
QMIndex = 0;
|
||||
|
||||
memset(IDCTMatrix, 0, sizeof(IDCTMatrix));
|
||||
IDCTMIndex = 0;
|
||||
|
||||
QScale = 0;
|
||||
|
||||
memset(Coeff, 0, sizeof(Coeff));
|
||||
CoeffIndex = 0;
|
||||
DecodeWB = 0;
|
||||
|
||||
OutBuffer.Flush();
|
||||
|
||||
InCounter = 0;
|
||||
BlockEnd = 0;
|
||||
DecodeEnd = 0;
|
||||
}
|
||||
|
||||
int MDEC_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(block_ready),
|
||||
|
||||
SFARRAY32(&block_y[0][0][0][0], sizeof(block_y) / sizeof(block_y[0][0][0][0])),
|
||||
SFARRAY32(&block_cb[0][0], sizeof(block_cb) / sizeof(block_cb[0][0])),
|
||||
SFARRAY32(&block_cr[0][0], sizeof(block_cr) / sizeof(block_cr[0][0])),
|
||||
|
||||
SFVAR(run_time),
|
||||
SFVAR(Command),
|
||||
|
||||
SFARRAY(&QMatrix[0][0], sizeof(QMatrix) / sizeof(QMatrix[0][0])),
|
||||
SFVAR(QMIndex),
|
||||
|
||||
SFARRAY16(&IDCTMatrix[0], sizeof(IDCTMatrix) / sizeof(IDCTMatrix[0])),
|
||||
SFVAR(IDCTMIndex),
|
||||
|
||||
SFVAR(QScale),
|
||||
|
||||
SFARRAY16(&Coeff[0][0], sizeof(Coeff) / sizeof(Coeff[0][0])),
|
||||
SFVAR(CoeffIndex),
|
||||
SFVAR(DecodeWB),
|
||||
|
||||
#define SFFIFO16(fifoobj) SFARRAY16(&fifoobj.data[0], fifoobj.data.size()), \
|
||||
SFVAR(fifoobj.read_pos), \
|
||||
SFVAR(fifoobj.write_pos), \
|
||||
SFVAR(fifoobj.in_count)
|
||||
|
||||
SFFIFO16(InputBuffer),
|
||||
SFFIFO16(OutBuffer),
|
||||
#undef SFFIFO
|
||||
|
||||
SFVAR(InCounter),
|
||||
SFVAR(BlockEnd),
|
||||
SFVAR(DecodeEnd),
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MDEC");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void WriteQTab(uint8 V)
|
||||
{
|
||||
QMatrix[QMIndex >> 6][QMIndex & 0x3F] = V;
|
||||
QMIndex = (QMIndex + 1) & 0x7F;
|
||||
}
|
||||
|
||||
static void DecodeImage(void);
|
||||
static INLINE void WriteImageData(uint16 V)
|
||||
{
|
||||
const uint32 qmw = (bool)(DecodeWB < 2);
|
||||
|
||||
//printf("MDEC DMA SubWrite: %04x\n", V);
|
||||
|
||||
if(!CoeffIndex)
|
||||
{
|
||||
if(DecodeWB == 0 && V == 0xFE00)
|
||||
{
|
||||
InputBuffer.Flush();
|
||||
return;
|
||||
}
|
||||
QScale = V >> 10;
|
||||
Coeff[DecodeWB][ZigZag[0]] = sign_10_to_s16(V & 0x3FF) * QMatrix[qmw][0];
|
||||
CoeffIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(V == 0xFE00)
|
||||
{
|
||||
BlockEnd = true;
|
||||
while(CoeffIndex < 64)
|
||||
Coeff[DecodeWB][ZigZag[CoeffIndex++]] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 rlcount = V >> 10;
|
||||
|
||||
for(uint32 i = 0; i < rlcount && CoeffIndex < 64; i++)
|
||||
{
|
||||
Coeff[DecodeWB][ZigZag[CoeffIndex]] = 0;
|
||||
CoeffIndex++;
|
||||
}
|
||||
|
||||
if(CoeffIndex < 64)
|
||||
{
|
||||
Coeff[DecodeWB][ZigZag[CoeffIndex]] = (sign_10_to_s16(V & 0x3FF) * QScale * QMatrix[qmw][CoeffIndex]) >> 3; // Arithmetic right shift or division(negative differs)?
|
||||
CoeffIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(CoeffIndex == 64 && BlockEnd)
|
||||
{
|
||||
BlockEnd = false;
|
||||
CoeffIndex = 0;
|
||||
|
||||
//printf("Block %d finished\n", DecodeWB);
|
||||
|
||||
DecodeWB++;
|
||||
if(DecodeWB == 6)
|
||||
{
|
||||
DecodeWB = 0;
|
||||
|
||||
DecodeImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void IDCT(int16 *in_coeff, int32 *out_coeff)
|
||||
{
|
||||
#if defined(__SSE2__)
|
||||
for(int i = 0; i < 8 * 8; i++)
|
||||
{
|
||||
__m128i sum = _mm_set1_epi32(0);
|
||||
__m128i m0 = _mm_load_si128((__m128i *)&IDCTMatrix[((i & 7) * 8) + 0]);
|
||||
int32 tmp[4] MDFN_ALIGN(16);
|
||||
|
||||
for(int v = 0; v < 8; v++)
|
||||
{
|
||||
__m128i c = _mm_load_si128((__m128i *)&in_coeff[v * 8]);
|
||||
__m128i m1 = _mm_set1_epi16(IDCTMatrix[(i & ~7) + v]);
|
||||
__m128i m = _mm_mulhi_epi16(m0, m1);
|
||||
|
||||
sum = _mm_add_epi32(sum, _mm_madd_epi16(c, m));
|
||||
}
|
||||
|
||||
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6)));
|
||||
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (1 << 0) | (0 << 2)));
|
||||
sum = _mm_srai_epi32(sum, 16);
|
||||
|
||||
//_mm_store_ss((float *)(out_coeff + i), (__m128)sum);
|
||||
_mm_store_si128((__m128i*)tmp, sum);
|
||||
|
||||
out_coeff[i] = tmp[0]; //((tmp[0] + tmp[1]) + (tmp[2] + tmp[3])) >> 16;
|
||||
}
|
||||
#elif defined(ARCH_POWERPC_ALTIVEC)
|
||||
static const uint8 snail_cake[16] MDFN_ALIGN(16) = {
|
||||
0x00, 0x01, 0x10, 0x11,
|
||||
0x04, 0x05, 0x14, 0x15,
|
||||
0x08, 0x09, 0x18, 0x19,
|
||||
0x0C, 0x0D, 0x1C, 0x1D };
|
||||
vector unsigned char snail_pizza = vec_ld(0, snail_cake);
|
||||
|
||||
for(int i = 0; i < 8 * 8; i++)
|
||||
{
|
||||
vector signed int sum = vec_splat_s32(0);
|
||||
vector signed short m0 = vec_ld((((i & 7) * 8) + 0) * sizeof(signed short), IDCTMatrix);
|
||||
int32 tmp[4] MDFN_ALIGN(16);
|
||||
|
||||
for(int v = 0; v < 8; v++)
|
||||
{
|
||||
vector signed short c = vec_ld((v * 8) * sizeof(signed short), in_coeff);
|
||||
vector signed short m1 = vec_splats(IDCTMatrix[(i & ~7) + v]);
|
||||
#if 0
|
||||
vector signed short m = vec_madds(m0, m1, vec_splat_s16(0)); // Has incorrect behavior for what we need.
|
||||
#endif
|
||||
vector signed int te = vec_mule(m0, m1);
|
||||
vector signed int to = vec_mulo(m0, m1);
|
||||
vector signed short m = (vector signed short)vec_perm(te, to, snail_pizza);
|
||||
|
||||
sum = vec_msum(c, m, sum);
|
||||
}
|
||||
vec_st(sum, 0, tmp);
|
||||
out_coeff[i] = ((tmp[0] + tmp[1]) + (tmp[2] + tmp[3])) >> 16;
|
||||
}
|
||||
#else
|
||||
for(int y = 0; y < 8; y++)
|
||||
{
|
||||
for(int x = 0; x < 8; x++)
|
||||
{
|
||||
int32 sum = 0;
|
||||
|
||||
for(int v = 0; v < 8; v++)
|
||||
{
|
||||
int16 *c = &in_coeff[v * 8];
|
||||
int16 *m0 = &IDCTMatrix[(x * 8) + 0];
|
||||
int16 *m1 = &IDCTMatrix[(y * 8) + v];
|
||||
|
||||
for(int u = 0; u < 8; u++)
|
||||
{
|
||||
sum += c[u] * ((m0[u] * m1[0]) >> 16);
|
||||
}
|
||||
}
|
||||
out_coeff[y * 8 + x] = sum >> 16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void YCbCr_to_RGB(const int32 y, const int32 cb, const int32 cr, int &r, int &g, int &b)
|
||||
{
|
||||
r = (y + 128) + ((91881 * cr) >> 16);
|
||||
g = (y + 128) - ((22525 * cb) >> 16) - ((46812 * cr) >> 16);
|
||||
b = (y + 128) + ((116130 * cb) >> 16);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void DecodeImage(void)
|
||||
{
|
||||
//puts("DECODE");
|
||||
run_time -= 2048; //4096; //256; //1024; //2048; //8192; //1024; //4096;
|
||||
|
||||
IDCT(Coeff[0], &block_cr[0][0]);
|
||||
IDCT(Coeff[1], &block_cb[0][0]);
|
||||
IDCT(Coeff[2], &block_y[0][0][0][0]);
|
||||
IDCT(Coeff[3], &block_y[0][1][0][0]);
|
||||
IDCT(Coeff[4], &block_y[1][0][0][0]);
|
||||
IDCT(Coeff[5], &block_y[1][1][0][0]);
|
||||
|
||||
block_ready = true;
|
||||
}
|
||||
|
||||
static void EncodeImage(void)
|
||||
{
|
||||
//printf("ENCODE, %d\n", (Command & 0x08000000) ? 256 : 384);
|
||||
|
||||
block_ready = false;
|
||||
|
||||
if(!(Command & 0x08000000))
|
||||
{
|
||||
uint8 output[16][16][3]; // [y][x][cc]
|
||||
|
||||
for(int y = 0; y < 16; y++)
|
||||
{
|
||||
for(int x = 0; x < 16; x++)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
YCbCr_to_RGB(block_y[(y >> 3) & 1][(x >> 3) & 1][y & 7][x & 7], block_cb[y >> 1][x >> 1], block_cr[y >> 1][x >> 1], r, g, b);
|
||||
|
||||
//r = y * 15;
|
||||
//g = x * 15;
|
||||
//b = 0;
|
||||
|
||||
output[y][x][0] = r;
|
||||
output[y][x][1] = g;
|
||||
output[y][x][2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 384; i++)
|
||||
{
|
||||
if(OutBuffer.CanWrite())
|
||||
OutBuffer.WriteUnit((&output[0][0][0])[i * 2 + 0] | ((&output[0][0][0])[i * 2 + 1] << 8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 pixel_or = (Command & 0x02000000) ? 0x8000 : 0x0000;
|
||||
|
||||
for(int y = 0; y < 16; y++)
|
||||
{
|
||||
for(int x = 0; x < 16; x++)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
YCbCr_to_RGB(block_y[(y >> 3) & 1][(x >> 3) & 1][y & 7][x & 7], block_cb[y >> 1][x >> 1], block_cr[y >> 1][x >> 1], r, g, b);
|
||||
|
||||
if(OutBuffer.CanWrite())
|
||||
OutBuffer.WriteUnit(pixel_or | ((r >> 3) << 0) | ((g >> 3) << 5) | ((b >> 3) << 10));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MDEC_DMAWrite(uint32 V)
|
||||
{
|
||||
if(Command == 0x60000000)
|
||||
{
|
||||
for(unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
IDCTMatrix[((IDCTMIndex & 0x7) << 3) | ((IDCTMIndex >> 3) & 0x7)] = (int16)(V & 0xFFFF);
|
||||
IDCTMIndex = (IDCTMIndex + 1) & 0x3F;
|
||||
|
||||
V >>= 16;
|
||||
}
|
||||
}
|
||||
else if(Command == 0x40000001)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteQTab((uint8)V);
|
||||
V >>= 8;
|
||||
}
|
||||
}
|
||||
else if((Command & 0xF5FF0000) == 0x30000000)
|
||||
{
|
||||
if(InCounter > 0)
|
||||
{
|
||||
for(int vi = 0; vi < 2; vi++)
|
||||
{
|
||||
if(InputBuffer.CanWrite())
|
||||
InputBuffer.WriteUnit(V);
|
||||
|
||||
V >>= 16;
|
||||
}
|
||||
InCounter--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("MYSTERY1: %08x\n", V);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 MDEC_DMARead(void)
|
||||
{
|
||||
uint32 V = 0;
|
||||
|
||||
if((Command & 0xF5FF0000) == 0x30000000 && OutBuffer.CanRead() >= 2)
|
||||
{
|
||||
V = OutBuffer.ReadUnit() | (OutBuffer.ReadUnit() << 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("BONUS GNOMES");
|
||||
V = rand();
|
||||
}
|
||||
return(V);
|
||||
}
|
||||
|
||||
bool MDEC_DMACanRead(void)
|
||||
{
|
||||
return(OutBuffer.CanRead() >= 2); //(OutBuffer.CanRead() >= 2) || ((Command & 0xF5FF0000) != 0x30000000);
|
||||
}
|
||||
|
||||
void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
PSX_WARNING("[MDEC] Write: 0x%08x 0x%08x, %d", A, V, timestamp);
|
||||
if(A & 4)
|
||||
{
|
||||
if(V & 0x80000000) // Reset?
|
||||
{
|
||||
block_ready = false;
|
||||
run_time = 0;
|
||||
QMIndex = 0;
|
||||
IDCTMIndex = 0;
|
||||
|
||||
QScale = 0;
|
||||
|
||||
memset(Coeff, 0, sizeof(Coeff));
|
||||
CoeffIndex = 0;
|
||||
DecodeWB = 0;
|
||||
|
||||
InputBuffer.Flush();
|
||||
OutBuffer.Flush();
|
||||
|
||||
InCounter = 0;
|
||||
BlockEnd = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Command = V;
|
||||
|
||||
if((Command & 0xF5FF0000) == 0x30000000)
|
||||
{
|
||||
InputBuffer.Flush();
|
||||
OutBuffer.Flush();
|
||||
|
||||
block_ready = false;
|
||||
BlockEnd = false;
|
||||
CoeffIndex = 0;
|
||||
DecodeWB = 0;
|
||||
|
||||
InCounter = V & 0xFFFF;
|
||||
}
|
||||
else if(Command == 0x60000000)
|
||||
{
|
||||
IDCTMIndex = 0;
|
||||
}
|
||||
else if(Command == 0x40000001)
|
||||
{
|
||||
QMIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 MDEC_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
if(A & 4)
|
||||
{
|
||||
ret = 0;
|
||||
|
||||
if(InputBuffer.CanRead())
|
||||
ret |= 0x20000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Command;
|
||||
}
|
||||
|
||||
//PSX_WARNING("[MDEC] Read: 0x%08x 0x%08x -- %d %d", A, ret, InputBuffer.CanRead(), InCounter);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void MDEC_Run(int32 clocks)
|
||||
{
|
||||
run_time += clocks;
|
||||
|
||||
while(run_time > 0)
|
||||
{
|
||||
run_time--;
|
||||
|
||||
if(block_ready && !OutBuffer.CanRead())
|
||||
EncodeImage();
|
||||
|
||||
if(block_ready && OutBuffer.CanRead())
|
||||
break;
|
||||
|
||||
if(!InputBuffer.CanRead())
|
||||
break;
|
||||
|
||||
WriteImageData(InputBuffer.ReadUnit());
|
||||
}
|
||||
|
||||
if(run_time > 0)
|
||||
run_time = 0;
|
||||
}
|
||||
|
||||
}
|
23
mednafen/psx-0925/mdec.h
Normal file
23
mednafen/psx-0925/mdec.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef __MDFN_PSX_MDEC_H
|
||||
#define __MDFN_PSX_MDEC_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
void MDEC_DMAWrite(uint32 V);
|
||||
|
||||
uint32 MDEC_DMARead(void);
|
||||
|
||||
void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
uint32 MDEC_Read(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
|
||||
void MDEC_Power(void);
|
||||
|
||||
bool MDEC_DMACanRead(void);
|
||||
void MDEC_Run(int32 clocks);
|
||||
|
||||
int MDEC_StateAction(StateMem *sm, int load, int data_only);
|
||||
}
|
||||
|
||||
#endif
|
1878
mednafen/psx-0925/psx.cpp
Normal file
1878
mednafen/psx-0925/psx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
87
mednafen/psx-0925/psx.h
Normal file
87
mednafen/psx-0925/psx.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef __MDFN_PSX_PSX_H
|
||||
#define __MDFN_PSX_PSX_H
|
||||
|
||||
#include <mednafen/mednafen.h>
|
||||
#include <mednafen/masmem.h>
|
||||
#include <trio/trio.h>
|
||||
|
||||
#include "../cdrom/cdromif.h"
|
||||
#include "../general.h"
|
||||
#include "../FileWrapper.h"
|
||||
|
||||
//#define PSX_WARNING(format, ...) { printf(format "\n", ## __VA_ARGS__); }
|
||||
//#define PSX_DBGINFO(format, ...) { /*printf(format "\n", ## __VA_ARGS__);*/ }
|
||||
#define PSX_WARNING(format, ...)
|
||||
#define PSX_DBGINFO(format, ...)
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
typedef int32 pscpu_timestamp_t;
|
||||
|
||||
bool MDFN_FASTCALL PSX_EventHandler(const pscpu_timestamp_t timestamp);
|
||||
|
||||
void MDFN_FASTCALL PSX_MemWrite8(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
void MDFN_FASTCALL PSX_MemWrite16(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
void MDFN_FASTCALL PSX_MemWrite24(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
void MDFN_FASTCALL PSX_MemWrite32(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
|
||||
uint8 MDFN_FASTCALL PSX_MemRead8(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
uint16 MDFN_FASTCALL PSX_MemRead16(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
uint32 MDFN_FASTCALL PSX_MemRead24(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
uint32 MDFN_FASTCALL PSX_MemRead32(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
uint8 PSX_MemPeek8(uint32 A);
|
||||
uint16 PSX_MemPeek16(uint32 A);
|
||||
uint32 PSX_MemPeek32(uint32 A);
|
||||
|
||||
// Should write to WO-locations if possible
|
||||
#if 0
|
||||
void PSX_MemPoke8(uint32 A, uint8 V);
|
||||
void PSX_MemPoke16(uint32 A, uint16 V);
|
||||
void PSX_MemPoke32(uint32 A, uint32 V);
|
||||
#endif
|
||||
|
||||
void PSX_RequestMLExit(void);
|
||||
|
||||
enum
|
||||
{
|
||||
PSX_EVENT__SYNFIRST = 0,
|
||||
PSX_EVENT_GPU,
|
||||
PSX_EVENT_CDC,
|
||||
//PSX_EVENT_SPU,
|
||||
PSX_EVENT_TIMER,
|
||||
PSX_EVENT_DMA,
|
||||
PSX_EVENT_FIO,
|
||||
PSX_EVENT__SYNLAST,
|
||||
PSX_EVENT__COUNT,
|
||||
};
|
||||
|
||||
#define PSX_EVENT_MAXTS 0x20000000
|
||||
void PSX_SetEventNT(const int type, const pscpu_timestamp_t next_timestamp);
|
||||
|
||||
void PSX_GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock);
|
||||
};
|
||||
|
||||
|
||||
#include "dis.h"
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
#include "gpu.h"
|
||||
#include "dma.h"
|
||||
//#include "sio.h"
|
||||
#include "debug.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
class PS_CDC;
|
||||
class PS_SPU;
|
||||
|
||||
extern PS_CPU *CPU;
|
||||
extern PS_GPU *GPU;
|
||||
extern PS_CDC *CDC;
|
||||
extern PS_SPU *SPU;
|
||||
extern MultiAccessSizeMem<2048 * 1024, uint32, false> MainRAM;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
106
mednafen/psx-0925/sio.cpp
Normal file
106
mednafen/psx-0925/sio.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/* 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 "psx.h"
|
||||
#include "sio.h"
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
// Dummy implementation.
|
||||
|
||||
static uint16 Status;
|
||||
static uint16 Mode;
|
||||
static uint16 Control;
|
||||
static uint16 BaudRate;
|
||||
static uint32 DataBuffer;
|
||||
|
||||
void SIO_Power(void)
|
||||
{
|
||||
Status = 0;
|
||||
Mode = 0;
|
||||
Control = 0;
|
||||
BaudRate = 0;
|
||||
DataBuffer = 0;
|
||||
}
|
||||
|
||||
uint32 SIO_Read(pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
|
||||
switch(A & 0xE)
|
||||
{
|
||||
default:
|
||||
PSX_WARNING("[SIO] Unknown read: 0x%08x -- %d\n", A, timestamp);
|
||||
break;
|
||||
|
||||
case 0x0:
|
||||
//case 0x2:
|
||||
ret = DataBuffer >> ((A & 2) * 8);
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
ret = Status;
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
ret = Mode;
|
||||
break;
|
||||
|
||||
case 0xA:
|
||||
ret = Control;
|
||||
break;
|
||||
|
||||
case 0xE:
|
||||
ret = BaudRate;
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret >> ((A & 1) * 8));
|
||||
}
|
||||
|
||||
void SIO_Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
V <<= (A & 1) * 8;
|
||||
|
||||
switch(A & 0xE)
|
||||
{
|
||||
default:
|
||||
PSX_WARNING("[SIO] Unknown write: 0x%08x 0x%08x -- %d\n", A, V, timestamp);
|
||||
break;
|
||||
|
||||
case 0x0:
|
||||
//case 0x2:
|
||||
V <<= (A & 2) * 8;
|
||||
DataBuffer = V;
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
Mode = V;
|
||||
break;
|
||||
|
||||
case 0xA:
|
||||
Control = V;
|
||||
break;
|
||||
|
||||
case 0xE:
|
||||
BaudRate = V;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
13
mednafen/psx-0925/sio.h
Normal file
13
mednafen/psx-0925/sio.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __MDFN_PSX_SIO_H
|
||||
#define __MDFN_PSX_SIO_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
void SIO_Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
uint32 SIO_Read(pscpu_timestamp_t timestamp, uint32 A);
|
||||
void SIO_Power(void);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
1565
mednafen/psx-0925/spu.cpp
Normal file
1565
mednafen/psx-0925/spu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
338
mednafen/psx-0925/spu.h
Normal file
338
mednafen/psx-0925/spu.h
Normal file
@ -0,0 +1,338 @@
|
||||
#ifndef __MDFN_PSX_SPU_H
|
||||
#define __MDFN_PSX_SPU_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
ADSR_ATTACK = 0,
|
||||
ADSR_DECAY = 1,
|
||||
ADSR_SUSTAIN = 2,
|
||||
ADSR_RELEASE = 3
|
||||
};
|
||||
|
||||
struct SPU_ADSR
|
||||
{
|
||||
uint16 EnvLevel; // We typecast it to (int16) in several places, but keep it here as (uint16) to prevent signed overflow/underflow, which compilers
|
||||
// may not treat consistently.
|
||||
uint32 Divider;
|
||||
uint32 Phase;
|
||||
|
||||
bool AttackExp;
|
||||
bool SustainExp;
|
||||
bool SustainDec;
|
||||
bool ReleaseExp;
|
||||
|
||||
int32 AttackRate; // Ar
|
||||
int32 DecayRate; // Dr * 4
|
||||
int32 SustainRate; // Sr
|
||||
int32 ReleaseRate; // Rr * 4
|
||||
|
||||
int32 SustainLevel; // (Sl + 1) << 11
|
||||
};
|
||||
|
||||
class PS_SPU;
|
||||
class SPU_Sweep
|
||||
{
|
||||
friend class PS_SPU; // For save states - FIXME(remove in future?)
|
||||
|
||||
public:
|
||||
SPU_Sweep() { }
|
||||
~SPU_Sweep() { }
|
||||
|
||||
void Power(void);
|
||||
|
||||
void WriteControl(uint16 value);
|
||||
int16 ReadVolume(void);
|
||||
|
||||
void WriteVolume(int16 value);
|
||||
|
||||
void Clock(void);
|
||||
|
||||
private:
|
||||
uint16 Control;
|
||||
int16 Current;
|
||||
uint32 Divider;
|
||||
};
|
||||
|
||||
struct SPU_Voice
|
||||
{
|
||||
int32 DecodeBuffer[32 + 4]; // + 4 so we don't have to do & 0x1F in our MAC
|
||||
int32 DecodeWritePos;
|
||||
|
||||
uint8 DecodeFlags;
|
||||
|
||||
SPU_Sweep Sweep[2];
|
||||
|
||||
uint16 Pitch;
|
||||
uint32 CurPhase;
|
||||
int32 CurPhase_SD; // Offseted compared to CurPhase, used for triggering sample decode.
|
||||
|
||||
uint32 StartAddr;
|
||||
|
||||
uint32 CurAddr;
|
||||
|
||||
uint32 ADSRControl;
|
||||
|
||||
uint32 LoopAddr;
|
||||
|
||||
int32 PreLRSample; // After enveloping, but before L/R volume. Range of -32768 to 32767
|
||||
|
||||
SPU_ADSR ADSR;
|
||||
};
|
||||
|
||||
class PS_SPU
|
||||
{
|
||||
public:
|
||||
|
||||
PS_SPU();
|
||||
~PS_SPU();
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void Power(void);
|
||||
void Write(pscpu_timestamp_t timestamp, uint32 A, uint16 V);
|
||||
uint16 Read(pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
void WriteDMA(uint32 V);
|
||||
uint32 ReadDMA(void);
|
||||
|
||||
void StartFrame(double rate, uint32 quality);
|
||||
int32 EndFrame(int16 *SoundBuf);
|
||||
|
||||
int32 UpdateFromCDC(int32 clocks);
|
||||
//pscpu_timestamp_t Update(pscpu_timestamp_t timestamp);
|
||||
|
||||
|
||||
static void DecodeADPCM(const uint8 *input, int16 *output, const unsigned shift, const unsigned weight);
|
||||
|
||||
private:
|
||||
|
||||
void CheckIRQAddr(uint32 addr);
|
||||
void WriteSPURAM(uint32 addr, uint16 value);
|
||||
uint16 ReadSPURAM(uint32 addr);
|
||||
|
||||
void DecodeSamples(SPU_Voice *voice);
|
||||
|
||||
void CacheEnvelope(SPU_Voice *voice);
|
||||
void ResetEnvelope(SPU_Voice *voice);
|
||||
void ReleaseEnvelope(SPU_Voice *voice);
|
||||
void RunEnvelope(SPU_Voice *voice);
|
||||
|
||||
|
||||
void RunReverb(int32 in_l, int32 in_r, int32 &out_l, int32 &out_r);
|
||||
bool GetCDAudio(int32 &l, int32 &r);
|
||||
|
||||
SPU_Voice Voices[24];
|
||||
|
||||
uint32 NoiseCounter;
|
||||
uint16 LFSR;
|
||||
|
||||
uint32 FM_Mode;
|
||||
uint32 Noise_Mode;
|
||||
uint32 Reverb_Mode;
|
||||
|
||||
int32 ReverbWA;
|
||||
|
||||
SPU_Sweep GlobalSweep[2]; // Doesn't affect reverb volume!
|
||||
|
||||
int32 ReverbVol[2];
|
||||
|
||||
int32 CDVol[2];
|
||||
int32 ExternVol[2];
|
||||
|
||||
uint32 IRQAddr;
|
||||
|
||||
uint32 RWAddr;
|
||||
|
||||
uint16 SPUControl;
|
||||
|
||||
uint32 VoiceOn;
|
||||
uint32 VoiceOff;
|
||||
|
||||
uint32 BlockEnd;
|
||||
|
||||
uint32 CWA;
|
||||
|
||||
int32 CDXA_ResampBuffer[2][4];
|
||||
int32 CDXA_CurPhase;
|
||||
|
||||
union
|
||||
{
|
||||
uint16 Regs[0x100];
|
||||
struct
|
||||
{
|
||||
uint16 VoiceRegs[0xC0];
|
||||
union
|
||||
{
|
||||
uint16 GlobalRegs[0x20];
|
||||
struct
|
||||
{
|
||||
uint16 _Global0[0x17];
|
||||
uint16 SPUStatus;
|
||||
uint16 _Global1[0x08];
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
int16 ReverbRegs[0x20];
|
||||
|
||||
struct
|
||||
{
|
||||
int16 FB_SRC_A;
|
||||
int16 FB_SRC_B;
|
||||
int16 IIR_ALPHA;
|
||||
int16 ACC_COEF_A;
|
||||
int16 ACC_COEF_B;
|
||||
int16 ACC_COEF_C;
|
||||
int16 ACC_COEF_D;
|
||||
int16 IIR_COEF;
|
||||
int16 FB_ALPHA;
|
||||
int16 FB_X;
|
||||
int16 IIR_DEST_A0;
|
||||
int16 IIR_DEST_A1;
|
||||
int16 ACC_SRC_A0;
|
||||
int16 ACC_SRC_A1;
|
||||
int16 ACC_SRC_B0;
|
||||
int16 ACC_SRC_B1;
|
||||
int16 IIR_SRC_A0;
|
||||
int16 IIR_SRC_A1;
|
||||
int16 IIR_DEST_B0;
|
||||
int16 IIR_DEST_B1;
|
||||
int16 ACC_SRC_C0;
|
||||
int16 ACC_SRC_C1;
|
||||
int16 ACC_SRC_D0;
|
||||
int16 ACC_SRC_D1;
|
||||
int16 IIR_SRC_B1;
|
||||
int16 IIR_SRC_B0;
|
||||
int16 MIX_DEST_A0;
|
||||
int16 MIX_DEST_A1;
|
||||
int16 MIX_DEST_B0;
|
||||
int16 MIX_DEST_B1;
|
||||
int16 IN_COEF_L;
|
||||
int16 IN_COEF_R;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
uint16 AuxRegs[0x10];
|
||||
|
||||
int16 RDSB[2][128]; // [40]
|
||||
int32 RDSB_WP;
|
||||
|
||||
int16 RUSB[2][128];
|
||||
int32 RUSB_WP;
|
||||
|
||||
int32 ReverbCur;
|
||||
|
||||
int32 Get_Reverb_Offset(int32 offset);
|
||||
int32 RD_RVB(int16 raw_offs);
|
||||
void WR_RVB(int16 raw_offs, int32 sample, int32 extra_offs = 0);
|
||||
|
||||
bool IRQAsserted;
|
||||
|
||||
//pscpu_timestamp_t lastts;
|
||||
int32 clock_divider;
|
||||
|
||||
uint16 SPURAM[524288 / sizeof(uint16)];
|
||||
|
||||
int last_rate;
|
||||
uint32 last_quality;
|
||||
|
||||
// Buffers 44.1KHz samples, should have enough for one video frame(~735 frames NTSC, ~882 PAL) plus jitter plus enough for the resampler leftovers.
|
||||
// We'll just go with 4096 because powers of 2 are AWESOME and such.
|
||||
uint32 IntermediateBufferPos;
|
||||
int16 IntermediateBuffer[4096][2];
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
GSREG_SPUCONTROL = 0,
|
||||
|
||||
GSREG_FM_ON,
|
||||
GSREG_NOISE_ON,
|
||||
GSREG_REVERB_ON,
|
||||
|
||||
GSREG_CDVOL_L,
|
||||
GSREG_CDVOL_R,
|
||||
|
||||
GSREG_DRYVOL_CTRL_L,
|
||||
GSREG_DRYVOL_CTRL_R,
|
||||
|
||||
GSREG_DRYVOL_L,
|
||||
GSREG_DRYVOL_R,
|
||||
|
||||
GSREG_WETVOL_L,
|
||||
GSREG_WETVOL_R,
|
||||
|
||||
GSREG_RWADDR,
|
||||
|
||||
GSREG_IRQADDR,
|
||||
|
||||
GSREG_REVERBWA,
|
||||
|
||||
GSREG_VOICEON,
|
||||
GSREG_VOICEOFF,
|
||||
GSREG_BLOCKEND,
|
||||
|
||||
// Note: the order of these should match the reverb reg array
|
||||
GSREG_FB_SRC_A,
|
||||
GSREG_FB_SRC_B,
|
||||
GSREG_IIR_ALPHA,
|
||||
GSREG_ACC_COEF_A,
|
||||
GSREG_ACC_COEF_B,
|
||||
GSREG_ACC_COEF_C,
|
||||
GSREG_ACC_COEF_D,
|
||||
GSREG_IIR_COEF,
|
||||
GSREG_FB_ALPHA,
|
||||
GSREG_FB_X,
|
||||
GSREG_IIR_DEST_A0,
|
||||
GSREG_IIR_DEST_A1,
|
||||
GSREG_ACC_SRC_A0,
|
||||
GSREG_ACC_SRC_A1,
|
||||
GSREG_ACC_SRC_B0,
|
||||
GSREG_ACC_SRC_B1,
|
||||
GSREG_IIR_SRC_A0,
|
||||
GSREG_IIR_SRC_A1,
|
||||
GSREG_IIR_DEST_B0,
|
||||
GSREG_IIR_DEST_B1,
|
||||
GSREG_ACC_SRC_C0,
|
||||
GSREG_ACC_SRC_C1,
|
||||
GSREG_ACC_SRC_D0,
|
||||
GSREG_ACC_SRC_D1,
|
||||
GSREG_IIR_SRC_B1,
|
||||
GSREG_IIR_SRC_B0,
|
||||
GSREG_MIX_DEST_A0,
|
||||
GSREG_MIX_DEST_A1,
|
||||
GSREG_MIX_DEST_B0,
|
||||
GSREG_MIX_DEST_B1,
|
||||
GSREG_IN_COEF_L,
|
||||
GSREG_IN_COEF_R,
|
||||
|
||||
|
||||
// Multiply v * 256 for each extra voice
|
||||
GSREG_V0_VOL_CTRL_L = 0x8000,
|
||||
GSREG_V0_VOL_CTRL_R,
|
||||
GSREG_V0_VOL_L,
|
||||
GSREG_V0_VOL_R,
|
||||
GSREG_V0_PITCH,
|
||||
GSREG_V0_STARTADDR,
|
||||
GSREG_V0_ADSR_CTRL,
|
||||
GSREG_V0_ADSR_LEVEL,
|
||||
GSREG_V0_LOOP_ADDR,
|
||||
GSREG_V0_READ_ADDR
|
||||
};
|
||||
|
||||
uint32 GetRegister(unsigned int which, char *special, const uint32 special_len);
|
||||
void SetRegister(unsigned int which, uint32 value);
|
||||
|
||||
uint16 PeekSPURAM(uint32 address);
|
||||
void PokeSPURAM(uint32 address, uint16 value);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
256
mednafen/psx-0925/spu_fir_table.inc
Normal file
256
mednafen/psx-0925/spu_fir_table.inc
Normal file
@ -0,0 +1,256 @@
|
||||
{ (int16)0x12c7, (int16)0x59b3, (int16)0x1307, (int16)0xffff },
|
||||
{ (int16)0x1288, (int16)0x59b2, (int16)0x1347, (int16)0xffff },
|
||||
{ (int16)0x1249, (int16)0x59b0, (int16)0x1388, (int16)0xffff },
|
||||
{ (int16)0x120b, (int16)0x59ad, (int16)0x13c9, (int16)0xffff },
|
||||
{ (int16)0x11cd, (int16)0x59a9, (int16)0x140b, (int16)0xffff },
|
||||
{ (int16)0x118f, (int16)0x59a4, (int16)0x144d, (int16)0xffff },
|
||||
{ (int16)0x1153, (int16)0x599e, (int16)0x1490, (int16)0xffff },
|
||||
{ (int16)0x1116, (int16)0x5997, (int16)0x14d4, (int16)0xffff },
|
||||
{ (int16)0x10db, (int16)0x598f, (int16)0x1517, (int16)0xffff },
|
||||
{ (int16)0x109f, (int16)0x5986, (int16)0x155c, (int16)0xffff },
|
||||
{ (int16)0x1065, (int16)0x597c, (int16)0x15a0, (int16)0xffff },
|
||||
{ (int16)0x102a, (int16)0x5971, (int16)0x15e6, (int16)0xffff },
|
||||
{ (int16)0x0ff1, (int16)0x5965, (int16)0x162c, (int16)0xffff },
|
||||
{ (int16)0x0fb7, (int16)0x5958, (int16)0x1672, (int16)0xffff },
|
||||
{ (int16)0x0f7f, (int16)0x5949, (int16)0x16b9, (int16)0xffff },
|
||||
{ (int16)0x0f46, (int16)0x593a, (int16)0x1700, (int16)0xffff },
|
||||
{ (int16)0x0f0f, (int16)0x592a, (int16)0x1747, (int16)0x0000 },
|
||||
{ (int16)0x0ed7, (int16)0x5919, (int16)0x1790, (int16)0x0000 },
|
||||
{ (int16)0x0ea1, (int16)0x5907, (int16)0x17d8, (int16)0x0000 },
|
||||
{ (int16)0x0e6b, (int16)0x58f4, (int16)0x1821, (int16)0x0000 },
|
||||
{ (int16)0x0e35, (int16)0x58e0, (int16)0x186b, (int16)0x0000 },
|
||||
{ (int16)0x0e00, (int16)0x58cb, (int16)0x18b5, (int16)0x0000 },
|
||||
{ (int16)0x0dcb, (int16)0x58b5, (int16)0x1900, (int16)0x0000 },
|
||||
{ (int16)0x0d97, (int16)0x589e, (int16)0x194b, (int16)0x0001 },
|
||||
{ (int16)0x0d63, (int16)0x5886, (int16)0x1996, (int16)0x0001 },
|
||||
{ (int16)0x0d30, (int16)0x586d, (int16)0x19e2, (int16)0x0001 },
|
||||
{ (int16)0x0cfd, (int16)0x5853, (int16)0x1a2e, (int16)0x0001 },
|
||||
{ (int16)0x0ccb, (int16)0x5838, (int16)0x1a7b, (int16)0x0002 },
|
||||
{ (int16)0x0c99, (int16)0x581c, (int16)0x1ac8, (int16)0x0002 },
|
||||
{ (int16)0x0c68, (int16)0x57ff, (int16)0x1b16, (int16)0x0002 },
|
||||
{ (int16)0x0c38, (int16)0x57e2, (int16)0x1b64, (int16)0x0003 },
|
||||
{ (int16)0x0c07, (int16)0x57c3, (int16)0x1bb3, (int16)0x0003 },
|
||||
{ (int16)0x0bd8, (int16)0x57a3, (int16)0x1c02, (int16)0x0003 },
|
||||
{ (int16)0x0ba9, (int16)0x5782, (int16)0x1c51, (int16)0x0004 },
|
||||
{ (int16)0x0b7a, (int16)0x5761, (int16)0x1ca1, (int16)0x0004 },
|
||||
{ (int16)0x0b4c, (int16)0x573e, (int16)0x1cf1, (int16)0x0005 },
|
||||
{ (int16)0x0b1e, (int16)0x571b, (int16)0x1d42, (int16)0x0005 },
|
||||
{ (int16)0x0af1, (int16)0x56f6, (int16)0x1d93, (int16)0x0006 },
|
||||
{ (int16)0x0ac4, (int16)0x56d1, (int16)0x1de5, (int16)0x0007 },
|
||||
{ (int16)0x0a98, (int16)0x56ab, (int16)0x1e37, (int16)0x0007 },
|
||||
{ (int16)0x0a6c, (int16)0x5684, (int16)0x1e89, (int16)0x0008 },
|
||||
{ (int16)0x0a40, (int16)0x565b, (int16)0x1edc, (int16)0x0009 },
|
||||
{ (int16)0x0a16, (int16)0x5632, (int16)0x1f2f, (int16)0x0009 },
|
||||
{ (int16)0x09eb, (int16)0x5609, (int16)0x1f82, (int16)0x000a },
|
||||
{ (int16)0x09c1, (int16)0x55de, (int16)0x1fd6, (int16)0x000b },
|
||||
{ (int16)0x0998, (int16)0x55b2, (int16)0x202a, (int16)0x000c },
|
||||
{ (int16)0x096f, (int16)0x5585, (int16)0x207f, (int16)0x000d },
|
||||
{ (int16)0x0946, (int16)0x5558, (int16)0x20d4, (int16)0x000e },
|
||||
{ (int16)0x091e, (int16)0x5529, (int16)0x2129, (int16)0x000f },
|
||||
{ (int16)0x08f7, (int16)0x54fa, (int16)0x217f, (int16)0x0010 },
|
||||
{ (int16)0x08d0, (int16)0x54ca, (int16)0x21d5, (int16)0x0011 },
|
||||
{ (int16)0x08a9, (int16)0x5499, (int16)0x222c, (int16)0x0012 },
|
||||
{ (int16)0x0883, (int16)0x5467, (int16)0x2282, (int16)0x0013 },
|
||||
{ (int16)0x085d, (int16)0x5434, (int16)0x22da, (int16)0x0015 },
|
||||
{ (int16)0x0838, (int16)0x5401, (int16)0x2331, (int16)0x0016 },
|
||||
{ (int16)0x0813, (int16)0x53cc, (int16)0x2389, (int16)0x0018 },
|
||||
{ (int16)0x07ef, (int16)0x5397, (int16)0x23e1, (int16)0x0019 },
|
||||
{ (int16)0x07cb, (int16)0x5361, (int16)0x2439, (int16)0x001b },
|
||||
{ (int16)0x07a7, (int16)0x532a, (int16)0x2492, (int16)0x001c },
|
||||
{ (int16)0x0784, (int16)0x52f3, (int16)0x24eb, (int16)0x001e },
|
||||
{ (int16)0x0762, (int16)0x52ba, (int16)0x2545, (int16)0x0020 },
|
||||
{ (int16)0x0740, (int16)0x5281, (int16)0x259e, (int16)0x0021 },
|
||||
{ (int16)0x071e, (int16)0x5247, (int16)0x25f8, (int16)0x0023 },
|
||||
{ (int16)0x06fd, (int16)0x520c, (int16)0x2653, (int16)0x0025 },
|
||||
{ (int16)0x06dc, (int16)0x51d0, (int16)0x26ad, (int16)0x0027 },
|
||||
{ (int16)0x06bb, (int16)0x5194, (int16)0x2708, (int16)0x0029 },
|
||||
{ (int16)0x069b, (int16)0x5156, (int16)0x2763, (int16)0x002c },
|
||||
{ (int16)0x067c, (int16)0x5118, (int16)0x27be, (int16)0x002e },
|
||||
{ (int16)0x065c, (int16)0x50da, (int16)0x281a, (int16)0x0030 },
|
||||
{ (int16)0x063e, (int16)0x509a, (int16)0x2876, (int16)0x0033 },
|
||||
{ (int16)0x061f, (int16)0x505a, (int16)0x28d2, (int16)0x0035 },
|
||||
{ (int16)0x0601, (int16)0x5019, (int16)0x292e, (int16)0x0038 },
|
||||
{ (int16)0x05e4, (int16)0x4fd7, (int16)0x298b, (int16)0x003a },
|
||||
{ (int16)0x05c7, (int16)0x4f95, (int16)0x29e7, (int16)0x003d },
|
||||
{ (int16)0x05aa, (int16)0x4f52, (int16)0x2a44, (int16)0x0040 },
|
||||
{ (int16)0x058e, (int16)0x4f0e, (int16)0x2aa1, (int16)0x0043 },
|
||||
{ (int16)0x0572, (int16)0x4ec9, (int16)0x2aff, (int16)0x0046 },
|
||||
{ (int16)0x0556, (int16)0x4e84, (int16)0x2b5c, (int16)0x0049 },
|
||||
{ (int16)0x053b, (int16)0x4e3e, (int16)0x2bba, (int16)0x004d },
|
||||
{ (int16)0x0520, (int16)0x4df7, (int16)0x2c18, (int16)0x0050 },
|
||||
{ (int16)0x0506, (int16)0x4db0, (int16)0x2c76, (int16)0x0054 },
|
||||
{ (int16)0x04ec, (int16)0x4d68, (int16)0x2cd4, (int16)0x0057 },
|
||||
{ (int16)0x04d2, (int16)0x4d20, (int16)0x2d33, (int16)0x005b },
|
||||
{ (int16)0x04b9, (int16)0x4cd7, (int16)0x2d91, (int16)0x005f },
|
||||
{ (int16)0x04a0, (int16)0x4c8d, (int16)0x2df0, (int16)0x0063 },
|
||||
{ (int16)0x0488, (int16)0x4c42, (int16)0x2e4f, (int16)0x0067 },
|
||||
{ (int16)0x0470, (int16)0x4bf7, (int16)0x2eae, (int16)0x006b },
|
||||
{ (int16)0x0458, (int16)0x4bac, (int16)0x2f0d, (int16)0x006f },
|
||||
{ (int16)0x0441, (int16)0x4b5f, (int16)0x2f6c, (int16)0x0074 },
|
||||
{ (int16)0x042a, (int16)0x4b13, (int16)0x2fcc, (int16)0x0078 },
|
||||
{ (int16)0x0413, (int16)0x4ac5, (int16)0x302b, (int16)0x007d },
|
||||
{ (int16)0x03fc, (int16)0x4a77, (int16)0x308b, (int16)0x0082 },
|
||||
{ (int16)0x03e7, (int16)0x4a29, (int16)0x30ea, (int16)0x0087 },
|
||||
{ (int16)0x03d1, (int16)0x49d9, (int16)0x314a, (int16)0x008c },
|
||||
{ (int16)0x03bc, (int16)0x498a, (int16)0x31aa, (int16)0x0091 },
|
||||
{ (int16)0x03a7, (int16)0x493a, (int16)0x3209, (int16)0x0096 },
|
||||
{ (int16)0x0392, (int16)0x48e9, (int16)0x3269, (int16)0x009c },
|
||||
{ (int16)0x037e, (int16)0x4898, (int16)0x32c9, (int16)0x00a1 },
|
||||
{ (int16)0x036a, (int16)0x4846, (int16)0x3329, (int16)0x00a7 },
|
||||
{ (int16)0x0356, (int16)0x47f4, (int16)0x3389, (int16)0x00ad },
|
||||
{ (int16)0x0343, (int16)0x47a1, (int16)0x33e9, (int16)0x00b3 },
|
||||
{ (int16)0x0330, (int16)0x474e, (int16)0x3449, (int16)0x00ba },
|
||||
{ (int16)0x031d, (int16)0x46fa, (int16)0x34a9, (int16)0x00c0 },
|
||||
{ (int16)0x030b, (int16)0x46a6, (int16)0x3509, (int16)0x00c7 },
|
||||
{ (int16)0x02f9, (int16)0x4651, (int16)0x3569, (int16)0x00cd },
|
||||
{ (int16)0x02e7, (int16)0x45fc, (int16)0x35c9, (int16)0x00d4 },
|
||||
{ (int16)0x02d6, (int16)0x45a6, (int16)0x3629, (int16)0x00db },
|
||||
{ (int16)0x02c4, (int16)0x4550, (int16)0x3689, (int16)0x00e3 },
|
||||
{ (int16)0x02b4, (int16)0x44fa, (int16)0x36e8, (int16)0x00ea },
|
||||
{ (int16)0x02a3, (int16)0x44a3, (int16)0x3748, (int16)0x00f2 },
|
||||
{ (int16)0x0293, (int16)0x444c, (int16)0x37a8, (int16)0x00fa },
|
||||
{ (int16)0x0283, (int16)0x43f4, (int16)0x3807, (int16)0x0101 },
|
||||
{ (int16)0x0273, (int16)0x439c, (int16)0x3867, (int16)0x010a },
|
||||
{ (int16)0x0264, (int16)0x4344, (int16)0x38c6, (int16)0x0112 },
|
||||
{ (int16)0x0255, (int16)0x42eb, (int16)0x3926, (int16)0x011b },
|
||||
{ (int16)0x0246, (int16)0x4292, (int16)0x3985, (int16)0x0123 },
|
||||
{ (int16)0x0237, (int16)0x4239, (int16)0x39e4, (int16)0x012c },
|
||||
{ (int16)0x0229, (int16)0x41df, (int16)0x3a43, (int16)0x0135 },
|
||||
{ (int16)0x021b, (int16)0x4185, (int16)0x3aa2, (int16)0x013f },
|
||||
{ (int16)0x020d, (int16)0x412a, (int16)0x3b00, (int16)0x0148 },
|
||||
{ (int16)0x0200, (int16)0x40d0, (int16)0x3b5f, (int16)0x0152 },
|
||||
{ (int16)0x01f2, (int16)0x4074, (int16)0x3bbd, (int16)0x015c },
|
||||
{ (int16)0x01e5, (int16)0x4019, (int16)0x3c1b, (int16)0x0166 },
|
||||
{ (int16)0x01d9, (int16)0x3fbd, (int16)0x3c79, (int16)0x0171 },
|
||||
{ (int16)0x01cc, (int16)0x3f62, (int16)0x3cd7, (int16)0x017b },
|
||||
{ (int16)0x01c0, (int16)0x3f05, (int16)0x3d35, (int16)0x0186 },
|
||||
{ (int16)0x01b4, (int16)0x3ea9, (int16)0x3d92, (int16)0x0191 },
|
||||
{ (int16)0x01a8, (int16)0x3e4c, (int16)0x3def, (int16)0x019c },
|
||||
{ (int16)0x019c, (int16)0x3def, (int16)0x3e4c, (int16)0x01a8 },
|
||||
{ (int16)0x0191, (int16)0x3d92, (int16)0x3ea9, (int16)0x01b4 },
|
||||
{ (int16)0x0186, (int16)0x3d35, (int16)0x3f05, (int16)0x01c0 },
|
||||
{ (int16)0x017b, (int16)0x3cd7, (int16)0x3f62, (int16)0x01cc },
|
||||
{ (int16)0x0171, (int16)0x3c79, (int16)0x3fbd, (int16)0x01d9 },
|
||||
{ (int16)0x0166, (int16)0x3c1b, (int16)0x4019, (int16)0x01e5 },
|
||||
{ (int16)0x015c, (int16)0x3bbd, (int16)0x4074, (int16)0x01f2 },
|
||||
{ (int16)0x0152, (int16)0x3b5f, (int16)0x40d0, (int16)0x0200 },
|
||||
{ (int16)0x0148, (int16)0x3b00, (int16)0x412a, (int16)0x020d },
|
||||
{ (int16)0x013f, (int16)0x3aa2, (int16)0x4185, (int16)0x021b },
|
||||
{ (int16)0x0135, (int16)0x3a43, (int16)0x41df, (int16)0x0229 },
|
||||
{ (int16)0x012c, (int16)0x39e4, (int16)0x4239, (int16)0x0237 },
|
||||
{ (int16)0x0123, (int16)0x3985, (int16)0x4292, (int16)0x0246 },
|
||||
{ (int16)0x011b, (int16)0x3926, (int16)0x42eb, (int16)0x0255 },
|
||||
{ (int16)0x0112, (int16)0x38c6, (int16)0x4344, (int16)0x0264 },
|
||||
{ (int16)0x010a, (int16)0x3867, (int16)0x439c, (int16)0x0273 },
|
||||
{ (int16)0x0101, (int16)0x3807, (int16)0x43f4, (int16)0x0283 },
|
||||
{ (int16)0x00fa, (int16)0x37a8, (int16)0x444c, (int16)0x0293 },
|
||||
{ (int16)0x00f2, (int16)0x3748, (int16)0x44a3, (int16)0x02a3 },
|
||||
{ (int16)0x00ea, (int16)0x36e8, (int16)0x44fa, (int16)0x02b4 },
|
||||
{ (int16)0x00e3, (int16)0x3689, (int16)0x4550, (int16)0x02c4 },
|
||||
{ (int16)0x00db, (int16)0x3629, (int16)0x45a6, (int16)0x02d6 },
|
||||
{ (int16)0x00d4, (int16)0x35c9, (int16)0x45fc, (int16)0x02e7 },
|
||||
{ (int16)0x00cd, (int16)0x3569, (int16)0x4651, (int16)0x02f9 },
|
||||
{ (int16)0x00c7, (int16)0x3509, (int16)0x46a6, (int16)0x030b },
|
||||
{ (int16)0x00c0, (int16)0x34a9, (int16)0x46fa, (int16)0x031d },
|
||||
{ (int16)0x00ba, (int16)0x3449, (int16)0x474e, (int16)0x0330 },
|
||||
{ (int16)0x00b3, (int16)0x33e9, (int16)0x47a1, (int16)0x0343 },
|
||||
{ (int16)0x00ad, (int16)0x3389, (int16)0x47f4, (int16)0x0356 },
|
||||
{ (int16)0x00a7, (int16)0x3329, (int16)0x4846, (int16)0x036a },
|
||||
{ (int16)0x00a1, (int16)0x32c9, (int16)0x4898, (int16)0x037e },
|
||||
{ (int16)0x009c, (int16)0x3269, (int16)0x48e9, (int16)0x0392 },
|
||||
{ (int16)0x0096, (int16)0x3209, (int16)0x493a, (int16)0x03a7 },
|
||||
{ (int16)0x0091, (int16)0x31aa, (int16)0x498a, (int16)0x03bc },
|
||||
{ (int16)0x008c, (int16)0x314a, (int16)0x49d9, (int16)0x03d1 },
|
||||
{ (int16)0x0087, (int16)0x30ea, (int16)0x4a29, (int16)0x03e7 },
|
||||
{ (int16)0x0082, (int16)0x308b, (int16)0x4a77, (int16)0x03fc },
|
||||
{ (int16)0x007d, (int16)0x302b, (int16)0x4ac5, (int16)0x0413 },
|
||||
{ (int16)0x0078, (int16)0x2fcc, (int16)0x4b13, (int16)0x042a },
|
||||
{ (int16)0x0074, (int16)0x2f6c, (int16)0x4b5f, (int16)0x0441 },
|
||||
{ (int16)0x006f, (int16)0x2f0d, (int16)0x4bac, (int16)0x0458 },
|
||||
{ (int16)0x006b, (int16)0x2eae, (int16)0x4bf7, (int16)0x0470 },
|
||||
{ (int16)0x0067, (int16)0x2e4f, (int16)0x4c42, (int16)0x0488 },
|
||||
{ (int16)0x0063, (int16)0x2df0, (int16)0x4c8d, (int16)0x04a0 },
|
||||
{ (int16)0x005f, (int16)0x2d91, (int16)0x4cd7, (int16)0x04b9 },
|
||||
{ (int16)0x005b, (int16)0x2d33, (int16)0x4d20, (int16)0x04d2 },
|
||||
{ (int16)0x0057, (int16)0x2cd4, (int16)0x4d68, (int16)0x04ec },
|
||||
{ (int16)0x0054, (int16)0x2c76, (int16)0x4db0, (int16)0x0506 },
|
||||
{ (int16)0x0050, (int16)0x2c18, (int16)0x4df7, (int16)0x0520 },
|
||||
{ (int16)0x004d, (int16)0x2bba, (int16)0x4e3e, (int16)0x053b },
|
||||
{ (int16)0x0049, (int16)0x2b5c, (int16)0x4e84, (int16)0x0556 },
|
||||
{ (int16)0x0046, (int16)0x2aff, (int16)0x4ec9, (int16)0x0572 },
|
||||
{ (int16)0x0043, (int16)0x2aa1, (int16)0x4f0e, (int16)0x058e },
|
||||
{ (int16)0x0040, (int16)0x2a44, (int16)0x4f52, (int16)0x05aa },
|
||||
{ (int16)0x003d, (int16)0x29e7, (int16)0x4f95, (int16)0x05c7 },
|
||||
{ (int16)0x003a, (int16)0x298b, (int16)0x4fd7, (int16)0x05e4 },
|
||||
{ (int16)0x0038, (int16)0x292e, (int16)0x5019, (int16)0x0601 },
|
||||
{ (int16)0x0035, (int16)0x28d2, (int16)0x505a, (int16)0x061f },
|
||||
{ (int16)0x0033, (int16)0x2876, (int16)0x509a, (int16)0x063e },
|
||||
{ (int16)0x0030, (int16)0x281a, (int16)0x50da, (int16)0x065c },
|
||||
{ (int16)0x002e, (int16)0x27be, (int16)0x5118, (int16)0x067c },
|
||||
{ (int16)0x002c, (int16)0x2763, (int16)0x5156, (int16)0x069b },
|
||||
{ (int16)0x0029, (int16)0x2708, (int16)0x5194, (int16)0x06bb },
|
||||
{ (int16)0x0027, (int16)0x26ad, (int16)0x51d0, (int16)0x06dc },
|
||||
{ (int16)0x0025, (int16)0x2653, (int16)0x520c, (int16)0x06fd },
|
||||
{ (int16)0x0023, (int16)0x25f8, (int16)0x5247, (int16)0x071e },
|
||||
{ (int16)0x0021, (int16)0x259e, (int16)0x5281, (int16)0x0740 },
|
||||
{ (int16)0x0020, (int16)0x2545, (int16)0x52ba, (int16)0x0762 },
|
||||
{ (int16)0x001e, (int16)0x24eb, (int16)0x52f3, (int16)0x0784 },
|
||||
{ (int16)0x001c, (int16)0x2492, (int16)0x532a, (int16)0x07a7 },
|
||||
{ (int16)0x001b, (int16)0x2439, (int16)0x5361, (int16)0x07cb },
|
||||
{ (int16)0x0019, (int16)0x23e1, (int16)0x5397, (int16)0x07ef },
|
||||
{ (int16)0x0018, (int16)0x2389, (int16)0x53cc, (int16)0x0813 },
|
||||
{ (int16)0x0016, (int16)0x2331, (int16)0x5401, (int16)0x0838 },
|
||||
{ (int16)0x0015, (int16)0x22da, (int16)0x5434, (int16)0x085d },
|
||||
{ (int16)0x0013, (int16)0x2282, (int16)0x5467, (int16)0x0883 },
|
||||
{ (int16)0x0012, (int16)0x222c, (int16)0x5499, (int16)0x08a9 },
|
||||
{ (int16)0x0011, (int16)0x21d5, (int16)0x54ca, (int16)0x08d0 },
|
||||
{ (int16)0x0010, (int16)0x217f, (int16)0x54fa, (int16)0x08f7 },
|
||||
{ (int16)0x000f, (int16)0x2129, (int16)0x5529, (int16)0x091e },
|
||||
{ (int16)0x000e, (int16)0x20d4, (int16)0x5558, (int16)0x0946 },
|
||||
{ (int16)0x000d, (int16)0x207f, (int16)0x5585, (int16)0x096f },
|
||||
{ (int16)0x000c, (int16)0x202a, (int16)0x55b2, (int16)0x0998 },
|
||||
{ (int16)0x000b, (int16)0x1fd6, (int16)0x55de, (int16)0x09c1 },
|
||||
{ (int16)0x000a, (int16)0x1f82, (int16)0x5609, (int16)0x09eb },
|
||||
{ (int16)0x0009, (int16)0x1f2f, (int16)0x5632, (int16)0x0a16 },
|
||||
{ (int16)0x0009, (int16)0x1edc, (int16)0x565b, (int16)0x0a40 },
|
||||
{ (int16)0x0008, (int16)0x1e89, (int16)0x5684, (int16)0x0a6c },
|
||||
{ (int16)0x0007, (int16)0x1e37, (int16)0x56ab, (int16)0x0a98 },
|
||||
{ (int16)0x0007, (int16)0x1de5, (int16)0x56d1, (int16)0x0ac4 },
|
||||
{ (int16)0x0006, (int16)0x1d93, (int16)0x56f6, (int16)0x0af1 },
|
||||
{ (int16)0x0005, (int16)0x1d42, (int16)0x571b, (int16)0x0b1e },
|
||||
{ (int16)0x0005, (int16)0x1cf1, (int16)0x573e, (int16)0x0b4c },
|
||||
{ (int16)0x0004, (int16)0x1ca1, (int16)0x5761, (int16)0x0b7a },
|
||||
{ (int16)0x0004, (int16)0x1c51, (int16)0x5782, (int16)0x0ba9 },
|
||||
{ (int16)0x0003, (int16)0x1c02, (int16)0x57a3, (int16)0x0bd8 },
|
||||
{ (int16)0x0003, (int16)0x1bb3, (int16)0x57c3, (int16)0x0c07 },
|
||||
{ (int16)0x0003, (int16)0x1b64, (int16)0x57e2, (int16)0x0c38 },
|
||||
{ (int16)0x0002, (int16)0x1b16, (int16)0x57ff, (int16)0x0c68 },
|
||||
{ (int16)0x0002, (int16)0x1ac8, (int16)0x581c, (int16)0x0c99 },
|
||||
{ (int16)0x0002, (int16)0x1a7b, (int16)0x5838, (int16)0x0ccb },
|
||||
{ (int16)0x0001, (int16)0x1a2e, (int16)0x5853, (int16)0x0cfd },
|
||||
{ (int16)0x0001, (int16)0x19e2, (int16)0x586d, (int16)0x0d30 },
|
||||
{ (int16)0x0001, (int16)0x1996, (int16)0x5886, (int16)0x0d63 },
|
||||
{ (int16)0x0001, (int16)0x194b, (int16)0x589e, (int16)0x0d97 },
|
||||
{ (int16)0x0000, (int16)0x1900, (int16)0x58b5, (int16)0x0dcb },
|
||||
{ (int16)0x0000, (int16)0x18b5, (int16)0x58cb, (int16)0x0e00 },
|
||||
{ (int16)0x0000, (int16)0x186b, (int16)0x58e0, (int16)0x0e35 },
|
||||
{ (int16)0x0000, (int16)0x1821, (int16)0x58f4, (int16)0x0e6b },
|
||||
{ (int16)0x0000, (int16)0x17d8, (int16)0x5907, (int16)0x0ea1 },
|
||||
{ (int16)0x0000, (int16)0x1790, (int16)0x5919, (int16)0x0ed7 },
|
||||
{ (int16)0x0000, (int16)0x1747, (int16)0x592a, (int16)0x0f0f },
|
||||
{ (int16)0xffff, (int16)0x1700, (int16)0x593a, (int16)0x0f46 },
|
||||
{ (int16)0xffff, (int16)0x16b9, (int16)0x5949, (int16)0x0f7f },
|
||||
{ (int16)0xffff, (int16)0x1672, (int16)0x5958, (int16)0x0fb7 },
|
||||
{ (int16)0xffff, (int16)0x162c, (int16)0x5965, (int16)0x0ff1 },
|
||||
{ (int16)0xffff, (int16)0x15e6, (int16)0x5971, (int16)0x102a },
|
||||
{ (int16)0xffff, (int16)0x15a0, (int16)0x597c, (int16)0x1065 },
|
||||
{ (int16)0xffff, (int16)0x155c, (int16)0x5986, (int16)0x109f },
|
||||
{ (int16)0xffff, (int16)0x1517, (int16)0x598f, (int16)0x10db },
|
||||
{ (int16)0xffff, (int16)0x14d4, (int16)0x5997, (int16)0x1116 },
|
||||
{ (int16)0xffff, (int16)0x1490, (int16)0x599e, (int16)0x1153 },
|
||||
{ (int16)0xffff, (int16)0x144d, (int16)0x59a4, (int16)0x118f },
|
||||
{ (int16)0xffff, (int16)0x140b, (int16)0x59a9, (int16)0x11cd },
|
||||
{ (int16)0xffff, (int16)0x13c9, (int16)0x59ad, (int16)0x120b },
|
||||
{ (int16)0xffff, (int16)0x1388, (int16)0x59b0, (int16)0x1249 },
|
||||
{ (int16)0xffff, (int16)0x1347, (int16)0x59b2, (int16)0x1288 },
|
||||
{ (int16)0xffff, (int16)0x1307, (int16)0x59b3, (int16)0x12c7 },
|
64
mednafen/psx-0925/spu_nft.inc
Normal file
64
mednafen/psx-0925/spu_nft.inc
Normal file
@ -0,0 +1,64 @@
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000002,
|
||||
0x00000002,
|
||||
0x00000002,
|
||||
0x00000002,
|
||||
0x00000004,
|
||||
0x00000005,
|
||||
0x00000006,
|
||||
0x00000007,
|
||||
0x00000008,
|
||||
0x0000000a,
|
||||
0x0000000c,
|
||||
0x0000000e,
|
||||
0x00000010,
|
||||
0x00000014,
|
||||
0x00000018,
|
||||
0x0000001c,
|
||||
0x00000020,
|
||||
0x00000028,
|
||||
0x00000030,
|
||||
0x00000038,
|
||||
0x00000040,
|
||||
0x00000050,
|
||||
0x00000060,
|
||||
0x00000070,
|
||||
0x00000080,
|
||||
0x000000a0,
|
||||
0x000000c0,
|
||||
0x000000e0,
|
||||
0x00000100,
|
||||
0x00000140,
|
||||
0x00000180,
|
||||
0x000001c0,
|
||||
0x00000200,
|
||||
0x00000280,
|
||||
0x00000300,
|
||||
0x00000380,
|
||||
0x00000400,
|
||||
0x00000500,
|
||||
0x00000600,
|
||||
0x00000700,
|
||||
0x00000800,
|
||||
0x00000a00,
|
||||
0x00000c00,
|
||||
0x00000e00,
|
||||
0x00001000,
|
||||
0x00001400,
|
||||
0x00001800,
|
||||
0x00001c00,
|
||||
0x00002000,
|
||||
0x00002800,
|
||||
0x00003000,
|
||||
0x00003800,
|
||||
0x00004000,
|
||||
0x00005000,
|
||||
0x00006000,
|
||||
0x00007000,
|
||||
0x00008000,
|
||||
0x00008000,
|
||||
0x00008000,
|
||||
0x00008000,
|
237
mednafen/psx-0925/spu_reverb.inc
Normal file
237
mednafen/psx-0925/spu_reverb.inc
Normal file
@ -0,0 +1,237 @@
|
||||
static int16 ReverbSat(int32 samp) MDFN_WARN_UNUSED_RESULT;
|
||||
static INLINE int16 ReverbSat(int32 samp)
|
||||
{
|
||||
if(samp > 32767)
|
||||
samp = 32767;
|
||||
|
||||
if(samp < -32768)
|
||||
samp = -32768;
|
||||
|
||||
return(samp);
|
||||
}
|
||||
|
||||
|
||||
INLINE int32 PS_SPU::Get_Reverb_Offset(int32 in_offset)
|
||||
{
|
||||
int32 offset = in_offset & 0x3FFFF;
|
||||
int32 wa_size = 0x40000 - ReverbWA;
|
||||
|
||||
if(offset & 0x20000)
|
||||
{
|
||||
offset -= ReverbWA;
|
||||
|
||||
if(offset < 0)
|
||||
{
|
||||
offset = 0;
|
||||
//PSX_WARNING("[SPU] A reverb offset is broken(-).");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(offset >= wa_size)
|
||||
{
|
||||
offset = wa_size - 1;
|
||||
//PSX_WARNING("[SPU] A reverb offset is broken(+): WASize=0x%04x, 0x%04x.", wa_size >> 2, in_offset >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
offset += ReverbCur;
|
||||
|
||||
if(offset >= 0x40000)
|
||||
offset = (offset & 0x3FFFF) + ReverbWA;
|
||||
|
||||
assert(offset >= ReverbWA && offset < 0x40000);
|
||||
|
||||
return(offset);
|
||||
}
|
||||
|
||||
int32 PS_SPU::RD_RVB(int16 raw_offs)
|
||||
{
|
||||
//raw_offs = rand() & 0xFFFF;
|
||||
|
||||
return((int16)SPURAM[Get_Reverb_Offset(raw_offs << 2)]);
|
||||
}
|
||||
|
||||
void PS_SPU::WR_RVB(int16 raw_offs, int32 sample, int32 extra_offs)
|
||||
{
|
||||
//raw_offs = rand() & 0xFFFF;
|
||||
|
||||
SPURAM[Get_Reverb_Offset((raw_offs << 2) + extra_offs)] = ReverbSat(sample);
|
||||
}
|
||||
|
||||
static INLINE int32 Reverb4422(const int16 *src)
|
||||
{
|
||||
static const int16 ResampTable[40] =
|
||||
{
|
||||
(int16)0xffff,
|
||||
(int16)0x0000,
|
||||
(int16)0x0002,
|
||||
(int16)0x0000,
|
||||
(int16)0xfff6,
|
||||
(int16)0x0000,
|
||||
(int16)0x0023,
|
||||
(int16)0x0000,
|
||||
(int16)0xff99,
|
||||
(int16)0x0000,
|
||||
(int16)0x010a,
|
||||
(int16)0x0000,
|
||||
(int16)0xfd98,
|
||||
(int16)0x0000,
|
||||
(int16)0x0534,
|
||||
(int16)0x0000,
|
||||
(int16)0xf470,
|
||||
(int16)0x0000,
|
||||
(int16)0x2806,
|
||||
(int16)0x4000,
|
||||
(int16)0x2806,
|
||||
(int16)0x0000,
|
||||
(int16)0xf470,
|
||||
(int16)0x0000,
|
||||
(int16)0x0534,
|
||||
(int16)0x0000,
|
||||
(int16)0xfd98,
|
||||
(int16)0x0000,
|
||||
(int16)0x010a,
|
||||
(int16)0x0000,
|
||||
(int16)0xff99,
|
||||
(int16)0x0000,
|
||||
(int16)0x0023,
|
||||
(int16)0x0000,
|
||||
(int16)0xfff6,
|
||||
(int16)0x0000,
|
||||
(int16)0x0002,
|
||||
(int16)0x0000,
|
||||
(int16)0xffff,
|
||||
(int16)0x0000,
|
||||
};
|
||||
int32 out = 0; // 32-bits is adequate(it won't overflow)
|
||||
|
||||
for(int i = 0; i < 40; i += 2)
|
||||
out += ResampTable[i] * src[i];
|
||||
|
||||
// Middle non-zero
|
||||
out += 0x4000 * src[19];
|
||||
|
||||
out >>= 15;
|
||||
|
||||
if(out < -32768)
|
||||
out = -32768;
|
||||
|
||||
if(out > 32767)
|
||||
out = 32767;
|
||||
|
||||
return(out);
|
||||
}
|
||||
|
||||
void PS_SPU::RunReverb(int32 in_l, int32 in_r, int32 &out_l, int32 &out_r)
|
||||
{
|
||||
int32 upsampled[2] = { 0, 0 };
|
||||
|
||||
RDSB[0][RDSB_WP] = in_l;
|
||||
RDSB[1][RDSB_WP] = in_r;
|
||||
RDSB[0][RDSB_WP | 0x40] = in_l; // So we don't have to &/bounds check in our MAC loop
|
||||
RDSB[1][RDSB_WP | 0x40] = in_r;
|
||||
|
||||
RDSB_WP = (RDSB_WP + 1) & 0x3F;
|
||||
|
||||
if(!(RDSB_WP & 1))
|
||||
{
|
||||
int32 downsampled[2];
|
||||
|
||||
for(int lr = 0; lr < 2; lr++)
|
||||
downsampled[lr] = Reverb4422(&RDSB[lr][(RDSB_WP - 40) & 0x3F]);
|
||||
|
||||
//
|
||||
// Run algorithm
|
||||
///
|
||||
if(SPUControl & 0x80)
|
||||
{
|
||||
int32 IIR_INPUT_A0;
|
||||
int32 IIR_INPUT_A1;
|
||||
int32 IIR_INPUT_B0;
|
||||
int32 IIR_INPUT_B1;
|
||||
int32 IIR_A0, IIR_A1, IIR_B0, IIR_B1;
|
||||
int32 ACC0, ACC1;
|
||||
int32 FB_A0, FB_A1, FB_B0, FB_B1;
|
||||
|
||||
IIR_INPUT_A0 = ((RD_RVB(IIR_SRC_A0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15);
|
||||
IIR_INPUT_A1 = ((RD_RVB(IIR_SRC_A1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15);
|
||||
IIR_INPUT_B0 = ((RD_RVB(IIR_SRC_B0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15);
|
||||
IIR_INPUT_B1 = ((RD_RVB(IIR_SRC_B1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15);
|
||||
|
||||
|
||||
IIR_A0 = (((int64)IIR_INPUT_A0 * IIR_ALPHA) >> 15) + ((RD_RVB(IIR_DEST_A0) * (32768 - IIR_ALPHA)) >> 15);
|
||||
IIR_A1 = (((int64)IIR_INPUT_A1 * IIR_ALPHA) >> 15) + ((RD_RVB(IIR_DEST_A1) * (32768 - IIR_ALPHA)) >> 15);
|
||||
IIR_B0 = (((int64)IIR_INPUT_B0 * IIR_ALPHA) >> 15) + ((RD_RVB(IIR_DEST_B0) * (32768 - IIR_ALPHA)) >> 15);
|
||||
IIR_B1 = (((int64)IIR_INPUT_B1 * IIR_ALPHA) >> 15) + ((RD_RVB(IIR_DEST_B1) * (32768 - IIR_ALPHA)) >> 15);
|
||||
|
||||
WR_RVB(IIR_DEST_A0, IIR_A0, 1);
|
||||
WR_RVB(IIR_DEST_A1, IIR_A1, 1);
|
||||
WR_RVB(IIR_DEST_B0, IIR_B0, 1);
|
||||
WR_RVB(IIR_DEST_B1, IIR_B1, 1);
|
||||
|
||||
#if 0
|
||||
ACC0 = ((RD_RVB(ACC_SRC_A0) * ACC_COEF_A) >> 15) +
|
||||
((RD_RVB(ACC_SRC_B0) * ACC_COEF_B) >> 15) +
|
||||
((RD_RVB(ACC_SRC_C0) * ACC_COEF_C) >> 15) +
|
||||
((RD_RVB(ACC_SRC_D0) * ACC_COEF_D) >> 15);
|
||||
|
||||
ACC1 = ((RD_RVB(ACC_SRC_A1) * ACC_COEF_A) >> 15) +
|
||||
((RD_RVB(ACC_SRC_B1) * ACC_COEF_B) >> 15) +
|
||||
((RD_RVB(ACC_SRC_C1) * ACC_COEF_C) >> 15) +
|
||||
((RD_RVB(ACC_SRC_D1) * ACC_COEF_D) >> 15);
|
||||
#endif
|
||||
|
||||
ACC0 = ((int64)(RD_RVB(ACC_SRC_A0) * ACC_COEF_A) +
|
||||
(RD_RVB(ACC_SRC_B0) * ACC_COEF_B) +
|
||||
(RD_RVB(ACC_SRC_C0) * ACC_COEF_C) +
|
||||
(RD_RVB(ACC_SRC_D0) * ACC_COEF_D)) >> 15;
|
||||
|
||||
|
||||
ACC1 = ((int64)(RD_RVB(ACC_SRC_A1) * ACC_COEF_A) +
|
||||
(RD_RVB(ACC_SRC_B1) * ACC_COEF_B) +
|
||||
(RD_RVB(ACC_SRC_C1) * ACC_COEF_C) +
|
||||
(RD_RVB(ACC_SRC_D1) * ACC_COEF_D)) >> 15;
|
||||
|
||||
|
||||
FB_A0 = RD_RVB(MIX_DEST_A0 - FB_SRC_A);
|
||||
FB_A1 = RD_RVB(MIX_DEST_A1 - FB_SRC_A);
|
||||
FB_B0 = RD_RVB(MIX_DEST_B0 - FB_SRC_B);
|
||||
FB_B1 = RD_RVB(MIX_DEST_B1 - FB_SRC_B);
|
||||
|
||||
WR_RVB(MIX_DEST_A0, ACC0 - ((FB_A0 * FB_ALPHA) >> 15));
|
||||
WR_RVB(MIX_DEST_A1, ACC1 - ((FB_A1 * FB_ALPHA) >> 15));
|
||||
|
||||
WR_RVB(MIX_DEST_B0, (((int64)FB_ALPHA * ACC0) >> 15) - ((FB_A0 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B0 * FB_X) >> 15));
|
||||
WR_RVB(MIX_DEST_B1, (((int64)FB_ALPHA * ACC1) >> 15) - ((FB_A1 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B1 * FB_X) >> 15));
|
||||
}
|
||||
|
||||
//
|
||||
// Get output samples
|
||||
//
|
||||
// RUSB[0][RUSB_WP | 0x40] = RUSB[0][RUSB_WP] = (short)rand();
|
||||
// RUSB[1][RUSB_WP | 0x40] = RUSB[1][RUSB_WP] = (short)rand();
|
||||
RUSB[0][RUSB_WP | 0x40] = RUSB[0][RUSB_WP] = (RD_RVB(MIX_DEST_A0) + RD_RVB(MIX_DEST_B0)) >> 1;
|
||||
RUSB[1][RUSB_WP | 0x40] = RUSB[1][RUSB_WP] = (RD_RVB(MIX_DEST_A1) + RD_RVB(MIX_DEST_B1)) >> 1;
|
||||
|
||||
RUSB_WP = (RUSB_WP + 1) & 0x3F;
|
||||
|
||||
ReverbCur = (ReverbCur + 1) & 0x3FFFF;
|
||||
if(!ReverbCur)
|
||||
ReverbCur = ReverbWA;
|
||||
}
|
||||
else
|
||||
{
|
||||
RUSB[0][RUSB_WP | 0x40] = RUSB[0][RUSB_WP] = 0;
|
||||
RUSB[1][RUSB_WP | 0x40] = RUSB[1][RUSB_WP] = 0;
|
||||
|
||||
RUSB_WP = (RUSB_WP + 1) & 0x3F;
|
||||
}
|
||||
|
||||
for(int lr = 0; lr < 2; lr++)
|
||||
upsampled[lr] = Reverb4422(&RUSB[lr][(RUSB_WP - 40) & 0x3F]);
|
||||
|
||||
out_l = upsampled[0];
|
||||
out_r = upsampled[1];
|
||||
}
|
||||
|
512
mednafen/psx-0925/timer.cpp
Normal file
512
mednafen/psx-0925/timer.cpp
Normal file
@ -0,0 +1,512 @@
|
||||
/* 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 "psx.h"
|
||||
#include "timer.h"
|
||||
|
||||
/*
|
||||
Notes(some of it may be incomplete or wrong in subtle ways)
|
||||
|
||||
Control bits:
|
||||
Lower 3 bits of mode, for timer1:
|
||||
0x1 = don't count during vblank
|
||||
0x3 = vblank going inactive triggers timer reset
|
||||
0x5 = vblank going inactive triggers timer reset, and only count within vblank.
|
||||
0x7 = Wait until vblank goes active then inactive, then start counting?
|
||||
For timer2:
|
||||
0x1 = timer stopped(TODO: confirm on real system)
|
||||
|
||||
Target mode enabled 0x008
|
||||
IRQ enable 0x010
|
||||
--?Affects 0x400 status flag?-- 0x020
|
||||
IRQ evaluation auto-reset 0x040
|
||||
--unknown-- 0x080
|
||||
Clock selection 0x100
|
||||
Divide by 8(timer 2 only?) 0x200
|
||||
|
||||
Counter:
|
||||
Reset to 0 on writes to the mode/status register.
|
||||
|
||||
Status flags:
|
||||
Unknown flag 0x0400
|
||||
Compare flag 0x0800
|
||||
Cleared on mode/status read.
|
||||
Set when: //ever Counter == 0(proooobably, need to investigate lower 3 bits in relation to this).
|
||||
|
||||
|
||||
Overflow/Carry flag 0x1000
|
||||
Cleared on mode/status read.
|
||||
Set when counter overflows from 0xFFFF->0.
|
||||
|
||||
Hidden flags:
|
||||
IRQ done
|
||||
Cleared on writes to the mode/status register, on writes to the count register, and apparently automatically when the counter
|
||||
increments if (Mode & 0x40) [Note: If target mode is enabled, and target is 0, IRQ done flag won't be automatically reset]
|
||||
|
||||
There seems to be a brief period(edge condition?) where, if count to target is enabled, you can (sometimes?) read the target value in the count
|
||||
register before it's reset to 0. I doubt any games rely on this, but who knows. Maybe a PSX equivalent of the PC Engine "Battle Royale"? ;)
|
||||
|
||||
When the counter == 0, the compare flag is set. An IRQ will be generated if (Mode & 0x10), and the hidden IRQ done flag will be set.
|
||||
*/
|
||||
|
||||
/*
|
||||
Dec. 26, 2011 Note
|
||||
Due to problems I've had with my GPU timing test program, timer2 appears to be unreliable(clocks are skipped?) when target mode is enabled and the full
|
||||
33MHz clock is used(rather than 33MHz / 8). TODO: Investigate further and confirm(or not).
|
||||
*/
|
||||
|
||||
/*
|
||||
FIXME: Clock appropriately(and update events) when using SetRegister() via the debugger.
|
||||
*/
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
extern PS_GPU *GPU;
|
||||
|
||||
struct Timer
|
||||
{
|
||||
uint32 Mode;
|
||||
int32 Counter; // Only 16-bit, but 32-bit here for detecting counting past target.
|
||||
int32 Target;
|
||||
|
||||
int32 Div8Counter;
|
||||
|
||||
bool IRQDone;
|
||||
int32 DoZeCounting;
|
||||
};
|
||||
|
||||
static bool vblank;
|
||||
static bool hretrace;
|
||||
static Timer Timers[3];
|
||||
static pscpu_timestamp_t lastts;
|
||||
|
||||
static int32 CalcNextEvent(int32 next_event)
|
||||
{
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
int32 target;
|
||||
int32 count_delta;
|
||||
|
||||
if((i == 0 || i == 1) && (Timers[i].Mode & 0x100)) // If clocked by GPU, abort for this timer(will result in poor granularity for pixel-clock-derived timer IRQs, but whatever).
|
||||
continue;
|
||||
|
||||
if(!(Timers[i].Mode & 0x10)) // If IRQ is disabled, abort for this timer.
|
||||
continue;
|
||||
|
||||
if((Timers[i].Mode & 0x8) && (Timers[i].Counter == 0) && (Timers[i].Target == 0) && !Timers[i].IRQDone)
|
||||
{
|
||||
next_event = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
target = ((Timers[i].Mode & 0x8) && (Timers[i].Counter < Timers[i].Target)) ? Timers[i].Target : 0x10000;
|
||||
|
||||
count_delta = target - Timers[i].Counter;
|
||||
if(count_delta <= 0)
|
||||
{
|
||||
fprintf(stderr, "timer %d count_delta <= 0!!! %d %d\n", i, target, Timers[i].Counter);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
int32 tmp_clocks;
|
||||
|
||||
if(Timers[i].DoZeCounting <= 0)
|
||||
continue;
|
||||
|
||||
if((i == 0x2) && (Timers[i].Mode & 0x1))
|
||||
continue;
|
||||
|
||||
if((i == 0x2) && (Timers[i].Mode & 0x200))
|
||||
{
|
||||
assert(Timers[i].Div8Counter >= 0 && Timers[i].Div8Counter < 8);
|
||||
tmp_clocks = ((count_delta - 1) * 8) + (8 - Timers[i].Div8Counter);
|
||||
}
|
||||
else
|
||||
tmp_clocks = count_delta;
|
||||
|
||||
assert(tmp_clocks > 0);
|
||||
|
||||
if(next_event > tmp_clocks)
|
||||
next_event = tmp_clocks;
|
||||
}
|
||||
}
|
||||
|
||||
return(next_event);
|
||||
}
|
||||
|
||||
static void ClockTimer(int i, uint32 clocks)
|
||||
{
|
||||
int32 before = Timers[i].Counter;
|
||||
int32 target = 0x10000;
|
||||
bool zero_tm = false;
|
||||
|
||||
if(Timers[i].DoZeCounting <= 0)
|
||||
clocks = 0;
|
||||
|
||||
if(i == 0x2)
|
||||
{
|
||||
uint32 d8_clocks;
|
||||
|
||||
Timers[i].Div8Counter += clocks;
|
||||
d8_clocks = Timers[i].Div8Counter >> 3;
|
||||
Timers[i].Div8Counter -= d8_clocks << 3;
|
||||
|
||||
if(Timers[i].Mode & 0x200) // Divide by 8, at least for timer 0x2
|
||||
clocks = d8_clocks;
|
||||
|
||||
if(Timers[i].Mode & 1)
|
||||
clocks = 0;
|
||||
}
|
||||
|
||||
if(Timers[i].Mode & 0x008)
|
||||
target = Timers[i].Target;
|
||||
|
||||
if(target == 0 && Timers[i].Counter == 0)
|
||||
zero_tm = true;
|
||||
else
|
||||
Timers[i].Counter += clocks;
|
||||
|
||||
if(clocks && (Timers[i].Mode & 0x40))
|
||||
Timers[i].IRQDone = false;
|
||||
|
||||
if((before < target && Timers[i].Counter >= target) || zero_tm || Timers[i].Counter > 0xFFFF)
|
||||
{
|
||||
#if 1
|
||||
if(Timers[i].Mode & 0x10)
|
||||
{
|
||||
if((Timers[i].Counter - target) > 3)
|
||||
printf("Timer %d IRQ trigger error: %d\n", i, Timers[i].Counter - target);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Timers[i].Mode |= 0x0800;
|
||||
|
||||
if(Timers[i].Counter > 0xFFFF)
|
||||
{
|
||||
Timers[i].Counter -= 0x10000;
|
||||
|
||||
if(target == 0x10000)
|
||||
Timers[i].Mode |= 0x1000;
|
||||
|
||||
if(!target)
|
||||
Timers[i].Counter = 0;
|
||||
}
|
||||
|
||||
if(target)
|
||||
Timers[i].Counter -= (Timers[i].Counter / target) * target;
|
||||
|
||||
if((Timers[i].Mode & 0x10) && !Timers[i].IRQDone)
|
||||
{
|
||||
Timers[i].IRQDone = true;
|
||||
|
||||
IRQ_Assert(IRQ_TIMER_0 + i, true);
|
||||
IRQ_Assert(IRQ_TIMER_0 + i, false);
|
||||
}
|
||||
|
||||
if(Timers[i].Counter && (Timers[i].Mode & 0x40))
|
||||
Timers[i].IRQDone = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TIMER_SetVBlank(bool status)
|
||||
{
|
||||
switch(Timers[1].Mode & 0x7)
|
||||
{
|
||||
case 0x1:
|
||||
Timers[1].DoZeCounting = !status;
|
||||
break;
|
||||
|
||||
case 0x3:
|
||||
if(vblank && !status)
|
||||
Timers[1].Counter = 0;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
Timers[1].DoZeCounting = status;
|
||||
if(vblank && !status)
|
||||
Timers[1].Counter = 0;
|
||||
break;
|
||||
|
||||
case 0x7:
|
||||
if(Timers[1].DoZeCounting == -1)
|
||||
{
|
||||
if(!vblank && status)
|
||||
Timers[1].DoZeCounting = 0;
|
||||
}
|
||||
else if(Timers[1].DoZeCounting == 0)
|
||||
{
|
||||
if(vblank && !status)
|
||||
Timers[1].DoZeCounting = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
vblank = status;
|
||||
}
|
||||
|
||||
void TIMER_SetHRetrace(bool status)
|
||||
{
|
||||
if(hretrace && !status)
|
||||
{
|
||||
if((Timers[0].Mode & 0x7) == 0x3)
|
||||
Timers[0].Counter = 0;
|
||||
}
|
||||
|
||||
hretrace = status;
|
||||
}
|
||||
|
||||
void TIMER_AddDotClocks(uint32 count)
|
||||
{
|
||||
if(Timers[0].Mode & 0x100)
|
||||
ClockTimer(0, count);
|
||||
}
|
||||
|
||||
void TIMER_ClockHRetrace(void)
|
||||
{
|
||||
if(Timers[1].Mode & 0x100)
|
||||
ClockTimer(1, 1);
|
||||
}
|
||||
|
||||
pscpu_timestamp_t TIMER_Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
int32 cpu_clocks = timestamp - lastts;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
uint32 timer_clocks = cpu_clocks;
|
||||
|
||||
if(Timers[i].Mode & 0x100)
|
||||
continue;
|
||||
|
||||
ClockTimer(i, timer_clocks);
|
||||
}
|
||||
|
||||
lastts = timestamp;
|
||||
|
||||
return(timestamp + CalcNextEvent(1024));
|
||||
}
|
||||
|
||||
static void CalcCountingStart(unsigned which)
|
||||
{
|
||||
Timers[which].DoZeCounting = true;
|
||||
|
||||
switch(which)
|
||||
{
|
||||
case 1:
|
||||
switch(Timers[which].Mode & 0x07)
|
||||
{
|
||||
case 0x1:
|
||||
Timers[which].DoZeCounting = !vblank;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
Timers[which].DoZeCounting = vblank;
|
||||
break;
|
||||
|
||||
case 0x7:
|
||||
Timers[which].DoZeCounting = -1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V)
|
||||
{
|
||||
TIMER_Update(timestamp);
|
||||
|
||||
int which = (A >> 4) & 0x3;
|
||||
|
||||
assert(!(A & 3));
|
||||
|
||||
PSX_DBGINFO("[TIMER] Write: %08x %04x\n", A, V);
|
||||
|
||||
if(which >= 3)
|
||||
return;
|
||||
|
||||
// TODO: See if the "Timers[which].Counter" part of the IRQ if() statements below is what a real PSX does.
|
||||
switch(A & 0xC)
|
||||
{
|
||||
case 0x0: Timers[which].IRQDone = false;
|
||||
#if 1
|
||||
if(Timers[which].Counter && (V & 0xFFFF) == 0)
|
||||
{
|
||||
Timers[which].Mode |= 0x0800;
|
||||
if((Timers[which].Mode & 0x10) && !Timers[which].IRQDone)
|
||||
{
|
||||
Timers[which].IRQDone = true;
|
||||
IRQ_Assert(IRQ_TIMER_0 + which, true);
|
||||
IRQ_Assert(IRQ_TIMER_0 + which, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Timers[which].Counter = V & 0xFFFF;
|
||||
break;
|
||||
|
||||
case 0x4: Timers[which].Mode = (V & 0x3FF) | (Timers[which].Mode & 0x1C00);
|
||||
Timers[which].IRQDone = false;
|
||||
#if 1
|
||||
if(Timers[which].Counter)
|
||||
{
|
||||
Timers[which].Mode |= 0x0800;
|
||||
if((Timers[which].Mode & 0x10) && !Timers[which].IRQDone)
|
||||
{
|
||||
Timers[which].IRQDone = true;
|
||||
IRQ_Assert(IRQ_TIMER_0 + which, true);
|
||||
IRQ_Assert(IRQ_TIMER_0 + which, false);
|
||||
}
|
||||
}
|
||||
Timers[which].Counter = 0;
|
||||
#endif
|
||||
CalcCountingStart(which); // Call after setting .Mode
|
||||
break;
|
||||
|
||||
case 0x8: Timers[which].Target = V & 0xFFFF;
|
||||
break;
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
|
||||
// TIMER_Update(timestamp);
|
||||
|
||||
PSX_SetEventNT(PSX_EVENT_TIMER, timestamp + CalcNextEvent(1024));
|
||||
}
|
||||
|
||||
uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
uint16 ret = 0;
|
||||
int which = (A >> 4) & 0x3;
|
||||
|
||||
assert(!(A & 3));
|
||||
|
||||
if(which >= 3)
|
||||
assert(0);
|
||||
|
||||
TIMER_Update(timestamp);
|
||||
|
||||
switch(A & 0xC)
|
||||
{
|
||||
case 0x0: ret = Timers[which].Counter;
|
||||
break;
|
||||
|
||||
case 0x4: ret = Timers[which].Mode;
|
||||
Timers[which].Mode &= ~0x1800;
|
||||
break;
|
||||
|
||||
case 0x8: ret = Timers[which].Target;
|
||||
break;
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void TIMER_ResetTS(void)
|
||||
{
|
||||
lastts = 0;
|
||||
}
|
||||
|
||||
|
||||
void TIMER_Power(void)
|
||||
{
|
||||
lastts = 0;
|
||||
|
||||
hretrace = false;
|
||||
vblank = false;
|
||||
memset(Timers, 0, sizeof(Timers));
|
||||
}
|
||||
|
||||
int TIMER_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
#define SFTIMER(n) SFVARN(Timers[n].Mode, #n "Mode"), \
|
||||
SFVARN(Timers[n].Counter, #n "Counter"), \
|
||||
SFVARN(Timers[n].Target, #n "Target"), \
|
||||
SFVARN(Timers[n].Div8Counter, #n "Div8Counter"), \
|
||||
SFVARN(Timers[n].IRQDone, #n "IRQDone")
|
||||
SFTIMER(0),
|
||||
SFTIMER(1),
|
||||
SFTIMER(2),
|
||||
#undef SFTIMER
|
||||
SFVAR(lastts),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "TIMER");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint32 TIMER_GetRegister(unsigned int which, char *special, const uint32 special_len)
|
||||
{
|
||||
int tw = (which >> 4) & 0x3;
|
||||
uint32 ret = 0;
|
||||
|
||||
switch(which & 0xF)
|
||||
{
|
||||
case TIMER_GSREG_COUNTER0:
|
||||
ret = Timers[tw].Counter;
|
||||
break;
|
||||
|
||||
case TIMER_GSREG_MODE0:
|
||||
ret = Timers[tw].Mode;
|
||||
break;
|
||||
|
||||
case TIMER_GSREG_TARGET0:
|
||||
ret = Timers[tw].Target;
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void TIMER_SetRegister(unsigned int which, uint32 value)
|
||||
{
|
||||
int tw = (which >> 4) & 0x3;
|
||||
|
||||
switch(which & 0xF)
|
||||
{
|
||||
case TIMER_GSREG_COUNTER0:
|
||||
Timers[tw].Counter = value & 0xFFFF;
|
||||
break;
|
||||
|
||||
case TIMER_GSREG_MODE0:
|
||||
Timers[tw].Mode = value & 0xFFFF;
|
||||
break;
|
||||
|
||||
case TIMER_GSREG_TARGET0:
|
||||
Timers[tw].Target = value & 0xFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
42
mednafen/psx-0925/timer.h
Normal file
42
mednafen/psx-0925/timer.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef __MDFN_PSX_TIMER_H
|
||||
#define __MDFN_PSX_TIMER_H
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_GSREG_COUNTER0 = 0x00,
|
||||
TIMER_GSREG_MODE0,
|
||||
TIMER_GSREG_TARGET0,
|
||||
|
||||
TIMER_GSREG_COUNTER1 = 0x10,
|
||||
TIMER_GSREG_MODE1,
|
||||
TIMER_GSREG_TARGET1,
|
||||
|
||||
TIMER_GSREG_COUNTER2 = 0x20,
|
||||
TIMER_GSREG_MODE2,
|
||||
TIMER_GSREG_TARGET2,
|
||||
};
|
||||
|
||||
uint32 TIMER_GetRegister(unsigned int which, char *special, const uint32 special_len);
|
||||
void TIMER_SetRegister(unsigned int which, uint32 value);
|
||||
|
||||
|
||||
void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V);
|
||||
uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
||||
void TIMER_AddDotClocks(uint32 count);
|
||||
void TIMER_ClockHRetrace(void);
|
||||
void TIMER_SetHRetrace(bool status);
|
||||
void TIMER_SetVBlank(bool status);
|
||||
|
||||
pscpu_timestamp_t TIMER_Update(const pscpu_timestamp_t);
|
||||
void TIMER_ResetTS(void);
|
||||
|
||||
void TIMER_Power(void);
|
||||
int TIMER_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -5,22 +5,17 @@ Battle Arena Toshinden, Final Fantasy 7 have some kind of GPU timing issues.
|
||||
Zero Divide runs too fast(related to CPU emulation speed?).
|
||||
|
||||
Chrono Cross has several-second freezes during some large special attack/magic sequences.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Tiny Toon Adventures - Plucky's Big Adventure is failing and BREAK'ing for some reason, maybe memcard related.
|
||||
|
||||
Shadow Master has broken startup images.
|
||||
Shadow Master might have broken startup images.
|
||||
|
||||
Crusaders of Might and Magic - The CD-XA buffering increase for ToD II is apparently exacerbating the early voice cutoff problem in this game.
|
||||
|
||||
Crash Team Racing - Noticed a game lockup once in the arcade mode stage select screen, having trouble reproducing it.
|
||||
|
||||
Misadventures of Trone Bonne - Voice problems, lockup, possibly due to excessively long seek delays?
|
||||
|
||||
Dance Dance Revolution - The music is...totally wonky.
|
||||
|
||||
Medal of Honor - Sound issues.
|
||||
|
||||
Fuuraiki - Hangs at black screen when trying to start a new game.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Test time delta between GPU LL DMA end and GPU non-busy status for various primitive types in sequence on a PS1.
|
||||
|
@ -554,8 +554,8 @@ void PS_CDC::XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab)
|
||||
uint8 ibuffer[28];
|
||||
int16 obuffer[2 + 28];
|
||||
|
||||
//if(param != param_copy)
|
||||
// printf("%d %02x %02x\n", unit, param, param_copy);
|
||||
if(param != param_copy)
|
||||
printf("%d %02x %02x\n", unit, param, param_copy);
|
||||
|
||||
for(unsigned i = 0; i < 28; i++)
|
||||
{
|
||||
@ -775,8 +775,8 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
{
|
||||
if(XA_Test(buf))
|
||||
{
|
||||
//if(AudioBuffer_ReadPos & 0xFFF)
|
||||
//printf("readpos=%04x(rabl=%04x) writepos=%04x\n", AudioBuffer_ReadPos, AudioBuffer[AudioBuffer_ReadPos >> 12].Size, AudioBuffer_WritePos);
|
||||
if(AudioBuffer_ReadPos & 0xFFF)
|
||||
printf("readpos=%04x(rabl=%04x) writepos=%04x\n", AudioBuffer_ReadPos, AudioBuffer[AudioBuffer_ReadPos >> 12].Size, AudioBuffer_WritePos);
|
||||
|
||||
//if(AudioBuffer_UsedCount == 0)
|
||||
// AudioBuffer_InPrebuffer = true;
|
||||
@ -986,7 +986,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
||||
const CDC_CTEntry *command = &Commands[PendingCommand];
|
||||
//PSX_WARNING("[CDC] Command: %s --- %d", command->name, Results.CanRead());
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
printf("[CDC] Command: %s --- ", command->name);
|
||||
for(unsigned int i = 0; i < ArgsIn; i++)
|
||||
printf(" 0x%02x", ArgsBuf[i]);
|
||||
@ -1327,7 +1327,7 @@ int32 PS_CDC::CalcSeekTime(int32 initial, int32 target, bool motor_on, bool paus
|
||||
}
|
||||
}
|
||||
|
||||
//printf("%d\n", ret);
|
||||
printf("%d\n", ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ void PS_CPU::SetFastMap(void *region_mem, uint32 region_address, uint32 region_s
|
||||
// FAST_MAP_SHIFT
|
||||
// FAST_MAP_PSIZE
|
||||
|
||||
for(uint64 A = region_address; A < region_address + region_size; A += FAST_MAP_PSIZE)
|
||||
for(uint64 A = region_address; A < (uint64)region_address + region_size; A += FAST_MAP_PSIZE)
|
||||
{
|
||||
FastMap[A >> FAST_MAP_SHIFT] = ((uint8 *)region_mem - region_address);
|
||||
}
|
||||
|
@ -546,10 +546,15 @@ static RegType Regs_SPU_Voices[] =
|
||||
VOICE_HELPER(2),
|
||||
VOICE_HELPER(3),
|
||||
#else
|
||||
VOICE_HELPER(20),
|
||||
VOICE_HELPER(21),
|
||||
VOICE_HELPER(9),
|
||||
VOICE_HELPER(12),
|
||||
VOICE_HELPER(17),
|
||||
VOICE_HELPER(22),
|
||||
VOICE_HELPER(23),
|
||||
|
||||
//VOICE_HELPER(20),
|
||||
//VOICE_HELPER(21),
|
||||
//VOICE_HELPER(22),
|
||||
//VOICE_HELPER(23),
|
||||
#endif
|
||||
{ 0, "", "", 0 },
|
||||
};
|
||||
|
@ -28,24 +28,24 @@ struct OpEntry
|
||||
const char *format;
|
||||
};
|
||||
|
||||
#define MASK_OP (0x3F << 26)
|
||||
#define MASK_FUNC (0x3F)
|
||||
#define MASK_RS (0x1F << 21)
|
||||
#define MASK_RT (0x1F << 16)
|
||||
#define MASK_RD (0x1F << 11)
|
||||
#define MASK_SA (0x1F << 6)
|
||||
#define MASK_OP (0x3FU << 26)
|
||||
#define MASK_FUNC (0x3FU)
|
||||
#define MASK_RS (0x1FU << 21)
|
||||
#define MASK_RT (0x1FU << 16)
|
||||
#define MASK_RD (0x1FU << 11)
|
||||
#define MASK_SA (0x1FU << 6)
|
||||
|
||||
#define MK_OP(mnemonic, format, op, func, extra_mask) { MASK_OP | (op ? 0 : MASK_FUNC) | extra_mask, (op << 26) | func, mnemonic, format }
|
||||
#define MK_OP(mnemonic, format, op, func, extra_mask) { MASK_OP | (op ? 0 : MASK_FUNC) | extra_mask, ((unsigned)op << 26) | func, mnemonic, format }
|
||||
|
||||
#define MK_OP_REGIMM(mnemonic, regop) { MASK_OP | MASK_RT, (0x01 << 26) | (regop << 16), mnemonic, "s, p" }
|
||||
#define MK_OP_REGIMM(mnemonic, regop) { MASK_OP | MASK_RT, (0x01U << 26) | (regop << 16), mnemonic, "s, p" }
|
||||
|
||||
|
||||
#define MK_COPZ(z) { MASK_OP | (0x1 << 25), (0x1 << 25) | ((0x10 | z) << 26), "cop" #z, "F" }
|
||||
#define MK_COP0_FUNC(mnemonic, func) { MASK_OP | (0x1 << 25) | MASK_FUNC, (0x10 << 26) | (0x1 << 25) | func, mnemonic, "" }
|
||||
#define MK_COPZ(z) { MASK_OP | (0x1U << 25), (0x1U << 25) | ((0x10U | z) << 26), "cop" #z, "F" }
|
||||
#define MK_COP0_FUNC(mnemonic, func) { MASK_OP | (0x1U << 25) | MASK_FUNC, (0x10U << 26) | (0x1U << 25) | func, mnemonic, "" }
|
||||
|
||||
#define MK_COPZ_XFER(z, mnemonic, format, xf) { MASK_OP | (0x1F << 21), ((0x10 | z) << 26) | (xf << 21), mnemonic, format }
|
||||
#define MK_COPZ_XFER(z, mnemonic, format, xf) { MASK_OP | (0x1FU << 21), ((0x10U | z) << 26) | (xf << 21), mnemonic, format }
|
||||
|
||||
#define MK_GTE(mnemonic, format, func) { MASK_OP | (0x1 << 25) | MASK_FUNC, (0x1 << 25) | (0x12 << 26) | func, mnemonic, format }
|
||||
#define MK_GTE(mnemonic, format, func) { MASK_OP | (0x1U << 25) | MASK_FUNC, (0x1U << 25) | (0x12U << 26) | func, mnemonic, format }
|
||||
|
||||
static OpEntry ops[] =
|
||||
{
|
||||
|
@ -434,6 +434,7 @@ void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
int ch = (A & 0x7F) >> 4;
|
||||
|
||||
//if(ch == 2 || ch == 7)
|
||||
//PSX_WARNING("[DMA] Write: %08x %08x, DMAIntStatus=%08x", A, V, DMAIntStatus);
|
||||
|
||||
// FIXME if we ever have "accurate" bus emulation
|
||||
@ -548,11 +549,6 @@ uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
{
|
||||
int ch = (A & 0x7F) >> 4;
|
||||
uint32 ret = 0;
|
||||
|
||||
//assert(!(A & 3));
|
||||
|
||||
//if(ch == 2)
|
||||
// printf("DMA Read: %08x --- %d\n", A, GPU->GetScanlineNum());
|
||||
|
||||
if(ch == 7)
|
||||
{
|
||||
|
@ -674,7 +674,7 @@ void FrontIO::SetInput(unsigned int port, const char *type, void *ptr)
|
||||
if(port < 2)
|
||||
irq10_pulse_ts[port] = PSX_EVENT_MAXTS;
|
||||
|
||||
if(!strcmp(type, "gamepad"))
|
||||
if(!strcmp(type, "gamepad") || !strcmp(type, "dancepad"))
|
||||
Devices[port] = Device_Gamepad_Create();
|
||||
else if(!strcmp(type, "dualanalog"))
|
||||
Devices[port] = Device_DualAnalog_Create(false);
|
||||
@ -882,6 +882,15 @@ static InputDeviceInfoStruct InputDeviceInfoPSXPort[] =
|
||||
Device_Justifier_IDII,
|
||||
},
|
||||
|
||||
{
|
||||
"dancepad",
|
||||
"Dance Pad",
|
||||
"Dingo Dingo Rodeo!",
|
||||
NULL,
|
||||
sizeof(Device_Dancepad_IDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
Device_Dancepad_IDII,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct PortInfo[] =
|
||||
|
@ -787,6 +787,8 @@ INLINE void PS_GPU::WriteCB(uint32 InData)
|
||||
|
||||
void PS_GPU::Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
||||
{
|
||||
V <<= (A & 3) * 8;
|
||||
|
||||
if(A & 4) // GP1 ("Control")
|
||||
{
|
||||
uint32 command = V >> 24;
|
||||
@ -965,7 +967,7 @@ uint32 PS_GPU::Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
//PSX_WARNING("[GPU READ WHEN (DMACONTROL&2)] 0x%08x - ret=0x%08x, scanline=%d", A, ret, scanline);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return(ret >> ((A & 3) * 8));
|
||||
}
|
||||
|
||||
INLINE void PS_GPU::ReorderRGB_Var(uint32 out_Rshift, uint32 out_Gshift, uint32 out_Bshift, bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x)
|
||||
@ -1155,11 +1157,7 @@ pscpu_timestamp_t PS_GPU::Update(const pscpu_timestamp_t sys_timestamp)
|
||||
}
|
||||
char buffer[256];
|
||||
|
||||
trio_snprintf(buffer, sizeof(buffer), _("VIDEO STANDARD MISMATCH"));
|
||||
#ifndef __LIBRETRO__
|
||||
DrawTextTrans(surface->pixels + ((DisplayRect->h / 2) - (13 / 2)) * surface->pitch32, surface->pitch32 << 2, DisplayRect->w, (UTF8*)buffer,
|
||||
surface->MakeColor(0x00, 0xFF, 0x00), true, MDFN_FONT_6x13_12x13);
|
||||
#endif
|
||||
/* trio_snprintf(buffer, sizeof(buffer), _("VIDEO STANDARD MISMATCH")); */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -211,6 +211,28 @@ InputDeviceInputInfoStruct Device_Gamepad_IDII[16] =
|
||||
{ "square", "□ (left)", 8, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
};
|
||||
|
||||
InputDeviceInputInfoStruct Device_Dancepad_IDII[16] =
|
||||
{
|
||||
{ "select", "SELECT", 0, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON },
|
||||
{ "start", "START", 1, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "up", "UP ↑", 3, IDIT_BUTTON, NULL },
|
||||
{ "right", "RIGHT →", 6, IDIT_BUTTON, NULL },
|
||||
{ "down", "DOWN ↓", 8, IDIT_BUTTON, NULL },
|
||||
{ "left", "LEFT ←", 5, IDIT_BUTTON, NULL },
|
||||
|
||||
{ NULL, "empty", 0, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON, NULL },
|
||||
{ NULL, "empty", 0, IDIT_BUTTON, NULL },
|
||||
|
||||
{ "triangle", "△ (lower left)", 7, IDIT_BUTTON, NULL },
|
||||
{ "circle", "○ (upper right)", 4, IDIT_BUTTON, NULL },
|
||||
{ "cross", "x (upper left)", 2, IDIT_BUTTON, NULL },
|
||||
{ "square", "□ (lower right)", 9, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace MDFN_IEN_PSX
|
||||
|
||||
InputDevice *Device_Gamepad_Create(void);
|
||||
extern InputDeviceInputInfoStruct Device_Gamepad_IDII[16];
|
||||
extern InputDeviceInputInfoStruct Device_Dancepad_IDII[16];
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -15,10 +15,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO__
|
||||
#define HAVE_PSF 1
|
||||
#endif
|
||||
|
||||
#include "psx.h"
|
||||
#include "mdec.h"
|
||||
#include "frontio.h"
|
||||
@ -26,13 +22,7 @@
|
||||
#include "sio.h"
|
||||
#include "cdc.h"
|
||||
#include "spu.h"
|
||||
#include "../mednafen-endian.h"
|
||||
#include "../mempatcher.h"
|
||||
#ifdef HAVE_PSF
|
||||
#include "../PSFLoader.h"
|
||||
#include "../player.h"
|
||||
#endif
|
||||
|
||||
#include "../cputest/cputest.h"
|
||||
|
||||
extern MDFNGI EmulatedPSX;
|
||||
@ -40,20 +30,6 @@ extern MDFNGI EmulatedPSX;
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
#ifdef HAVE_PSF
|
||||
class PSF1Loader : public PSFLoader
|
||||
{
|
||||
public:
|
||||
|
||||
PSF1Loader(MDFNFILE *fp);
|
||||
virtual ~PSF1Loader();
|
||||
|
||||
virtual void HandleEXE(const uint8 *data, uint32 len, bool ignore_pcsp = false);
|
||||
|
||||
PSFTags tags;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
REGION_JP = 0,
|
||||
@ -67,10 +43,6 @@ static uint32 ReadCounter = 0;
|
||||
static uint32 WriteCounter = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSF
|
||||
static PSF1Loader *psf_loader = NULL;
|
||||
#endif
|
||||
|
||||
static std::vector<CDIF*> *cdifs = NULL;
|
||||
static std::vector<const char *> cdifs_scex_ids;
|
||||
static bool CD_TrayOpen;
|
||||
@ -587,7 +559,7 @@ template<typename T, bool IsWrite, bool Access24, bool Peek> static INLINE void
|
||||
return;
|
||||
}
|
||||
|
||||
if(A >= 0x1F801100 && A <= 0x1F80112F) // Root counters
|
||||
if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters
|
||||
{
|
||||
if(IsWrite)
|
||||
TIMER_Write(timestamp, A, V);
|
||||
@ -777,15 +749,11 @@ static void Emulate(EmulateSpecStruct *espec)
|
||||
{
|
||||
pscpu_timestamp_t timestamp = 0;
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
espec->skip = false;
|
||||
#else
|
||||
if(FIO->RequireNoFrameskip())
|
||||
{
|
||||
//puts("MEOW");
|
||||
espec->skip = false; //TODO: Save here, and restore at end of Emulate() ?
|
||||
}
|
||||
#endif
|
||||
|
||||
MDFNGameInfo->mouse_sensitivity = MDFN_GetSettingF("psx.input.mouse_sensitivity");
|
||||
|
||||
@ -796,19 +764,11 @@ static void Emulate(EmulateSpecStruct *espec)
|
||||
espec->SoundBufSize = 0;
|
||||
|
||||
FIO->UpdateInput();
|
||||
#ifdef HAVE_PSF
|
||||
GPU->StartFrame(psf_loader ? NULL : espec);
|
||||
#else
|
||||
GPU->StartFrame(espec);
|
||||
#endif
|
||||
SPU->StartFrame(espec->SoundRate, MDFN_GetSettingUI("psx.spu.resamp_quality"));
|
||||
|
||||
Running = -1;
|
||||
#ifdef HAVE_PSF
|
||||
timestamp = CPU->Run(timestamp, psf_loader != NULL);
|
||||
#else
|
||||
timestamp = CPU->Run(timestamp, false);
|
||||
#endif
|
||||
|
||||
assert(timestamp);
|
||||
|
||||
@ -830,17 +790,6 @@ static void Emulate(EmulateSpecStruct *espec)
|
||||
|
||||
espec->MasterCycles = timestamp;
|
||||
|
||||
#ifdef HAVE_PSF
|
||||
if(psf_loader)
|
||||
{
|
||||
if(!espec->skip)
|
||||
{
|
||||
espec->LineWidths[0].w = ~0;
|
||||
Player_Draw(espec->surface, &espec->DisplayRect, 0, espec->SoundBuf, espec->SoundBufSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Save memcards if dirty.
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
@ -857,7 +806,7 @@ static void Emulate(EmulateSpecStruct *espec)
|
||||
Memcard_SaveDelay[i] += timestamp;
|
||||
if(Memcard_SaveDelay[i] >= (33868800 * 2)) // Wait until about 2 seconds of no new writes.
|
||||
{
|
||||
//fprintf(stderr, "Saving memcard %d...\n", i);
|
||||
fprintf(stderr, "Saving memcard %d...\n", i);
|
||||
try
|
||||
{
|
||||
char ext[64];
|
||||
@ -893,11 +842,6 @@ static void Emulate(EmulateSpecStruct *espec)
|
||||
|
||||
static bool TestMagic(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
#ifdef HAVE_PSF
|
||||
if(PSFLoader::TestMagic(0x01, fp))
|
||||
return(true);
|
||||
#endif
|
||||
|
||||
if(fp->size < 0x800)
|
||||
return(false);
|
||||
|
||||
@ -1461,31 +1405,10 @@ static void LoadEXE(const uint8 *data, const uint32 size, bool ignore_pcsp = fal
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_PSF
|
||||
PSF1Loader::PSF1Loader(MDFNFILE *fp)
|
||||
{
|
||||
tags = Load(0x01, 2033664, fp);
|
||||
}
|
||||
|
||||
PSF1Loader::~PSF1Loader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PSF1Loader::HandleEXE(const uint8 *data, uint32 size, bool ignore_pcsp)
|
||||
{
|
||||
LoadEXE(data, size, ignore_pcsp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void Cleanup(void);
|
||||
static int Load(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
#ifdef HAVE_PSF
|
||||
const bool IsPSF = PSFLoader::TestMagic(0x01, fp);
|
||||
#else
|
||||
const bool IsPSF = false;
|
||||
#endif
|
||||
const bool IsPSF = false;
|
||||
|
||||
if(!TestMagic(name, fp))
|
||||
{
|
||||
@ -1514,19 +1437,6 @@ static int Load(const char *name, MDFNFILE *fp)
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef HAVE_PSF
|
||||
if(IsPSF)
|
||||
{
|
||||
psf_loader = new PSF1Loader(fp);
|
||||
|
||||
std::vector<std::string> SongNames;
|
||||
|
||||
SongNames.push_back(psf_loader->tags.GetTag("title"));
|
||||
|
||||
Player_Init(1, psf_loader->tags.GetTag("game"), psf_loader->tags.GetTag("artist"), psf_loader->tags.GetTag("copyright"), SongNames);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
LoadEXE(fp->data, fp->size);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
@ -1544,8 +1454,8 @@ static int LoadCD(std::vector<CDIF *> *CDInterfaces)
|
||||
int ret = InitCommon(CDInterfaces);
|
||||
|
||||
// TODO: fastboot setting
|
||||
if(MDFN_GetSettingB("psx.fastboot"))
|
||||
BIOSROM->WriteU32(0x6990, 0);
|
||||
//if(MDFN_GetSettingB("psx.fastboot"))
|
||||
// BIOSROM->WriteU32(0x6990, 0);
|
||||
|
||||
MDFNGameInfo->GameType = GMT_CDROM;
|
||||
|
||||
@ -1556,14 +1466,6 @@ static void Cleanup(void)
|
||||
{
|
||||
TextMem.resize(0);
|
||||
|
||||
#ifdef HAVE_PSF
|
||||
if(psf_loader)
|
||||
{
|
||||
delete psf_loader;
|
||||
psf_loader = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(CDC)
|
||||
{
|
||||
delete CDC;
|
||||
@ -1613,9 +1515,6 @@ static void Cleanup(void)
|
||||
|
||||
static void CloseGame(void)
|
||||
{
|
||||
#ifdef HAVE_PSF
|
||||
if(!psf_loader)
|
||||
#endif
|
||||
{
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
@ -1641,11 +1540,6 @@ static void CloseGame(void)
|
||||
|
||||
static void SetInput(int port, const char *type, void *ptr)
|
||||
{
|
||||
#ifdef HAVE_PSF
|
||||
if(psf_loader)
|
||||
FIO->SetInput(port, "none", NULL);
|
||||
else
|
||||
#endif
|
||||
FIO->SetInput(port, type, ptr);
|
||||
}
|
||||
|
||||
@ -1761,10 +1655,8 @@ static void DoSimpleCommand(int cmd)
|
||||
|
||||
static const FileExtensionSpecStruct KnownExtensions[] =
|
||||
{
|
||||
#ifdef HAVE_PSF
|
||||
{ ".psf", gettext_noop("PSF1 Rip") },
|
||||
{ ".minipsf", gettext_noop("MiniPSF1 Rip") },
|
||||
#endif
|
||||
{ ".psx", gettext_noop("PS-X Executable") },
|
||||
{ ".exe", gettext_noop("PS-X Executable") },
|
||||
{ NULL, NULL }
|
||||
@ -1806,7 +1698,7 @@ static MDFNSetting PSXSettings[] =
|
||||
{ "psx.input.port7.gun_chairs", MDFNSF_NOFLAGS, gettext_noop("Crosshairs color for lightgun on port 2C."), gettext_noop("A value of 0x1000000 disables crosshair drawing."), MDFNST_UINT, "0x0080FF", "0x000000", "0x1000000" },
|
||||
{ "psx.input.port8.gun_chairs", MDFNSF_NOFLAGS, gettext_noop("Crosshairs color for lightgun on port 2D."), gettext_noop("A value of 0x1000000 disables crosshair drawing."), MDFNST_UINT, "0x8000FF", "0x000000", "0x1000000" },
|
||||
|
||||
{ "psx.fastboot", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Skip BIOS intro sequence."), gettext_noop("MAY BREAK GAMES."), MDFNST_BOOL, "0" },
|
||||
//{ "psx.fastboot", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Skip BIOS intro sequence."), gettext_noop("MAY BREAK GAMES."), MDFNST_BOOL, "0" },
|
||||
{ "psx.region_autodetect", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Attempt to auto-detect region of game."), NULL, MDFNST_BOOL, "1" },
|
||||
{ "psx.region_default", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Default region to use."), gettext_noop("Used if region autodetection fails or is disabled."), MDFNST_ENUM, "jp", NULL, NULL, NULL, NULL, Region_List },
|
||||
|
||||
|
@ -9,10 +9,8 @@
|
||||
#include "../general.h"
|
||||
#include "../FileWrapper.h"
|
||||
|
||||
//#define PSX_WARNING(format, ...) { printf(format "\n", ## __VA_ARGS__); }
|
||||
//#define PSX_DBGINFO(format, ...) { /*printf(format "\n", ## __VA_ARGS__);*/ }
|
||||
#define PSX_WARNING(format, ...)
|
||||
#define PSX_DBGINFO(format, ...)
|
||||
#define PSX_WARNING(format, ...) { printf(format "\n", ## __VA_ARGS__); }
|
||||
#define PSX_DBGINFO(format, ...) { /*printf(format "\n", ## __VA_ARGS__);*/ }
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
@ -770,7 +770,7 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
voice->CurPhase_SD += phase_inc;
|
||||
}
|
||||
|
||||
if(!(SPUControl & 0x8000) || (VoiceOff & (1 << voice_num)))
|
||||
if(VoiceOff & (1 << voice_num))
|
||||
{
|
||||
if(voice->ADSR.Phase != ADSR_RELEASE)
|
||||
{
|
||||
@ -778,7 +778,7 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
}
|
||||
}
|
||||
|
||||
if((SPUControl & 0x8000) && (VoiceOn & (1 << voice_num)))
|
||||
if(VoiceOn & (1 << voice_num))
|
||||
{
|
||||
ResetEnvelope(voice);
|
||||
|
||||
@ -796,6 +796,12 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
|
||||
|
||||
voice->CurAddr = voice->StartAddr & ~0x7;
|
||||
}
|
||||
|
||||
if(!(SPUControl & 0x8000))
|
||||
{
|
||||
voice->ADSR.Phase = ADSR_RELEASE;
|
||||
voice->ADSR.EnvLevel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VoiceOff = 0;
|
||||
@ -1173,6 +1179,7 @@ void PS_SPU::StartFrame(double rate, uint32 quality)
|
||||
{
|
||||
if((int)rate != last_rate || quality != last_quality)
|
||||
{
|
||||
//double ratio = (double)44100 / (rate ? rate : 44100);
|
||||
int err = 0;
|
||||
|
||||
last_rate = (int)rate;
|
||||
|
@ -71,13 +71,13 @@
|
||||
|
||||
/*
|
||||
FIXME: Clock appropriately(and update events) when using SetRegister() via the debugger.
|
||||
|
||||
TODO: If we ever return randomish values to "simulate" open bus, remember to change the return type and such of the TIMER_Read() function to full 32-bit too.
|
||||
*/
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
extern PS_GPU *GPU;
|
||||
|
||||
struct Timer
|
||||
{
|
||||
uint32 Mode;
|
||||
@ -337,7 +337,7 @@ void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V)
|
||||
|
||||
int which = (A >> 4) & 0x3;
|
||||
|
||||
assert(!(A & 3));
|
||||
V <<= (A & 3) * 8;
|
||||
|
||||
PSX_DBGINFO("[TIMER] Write: %08x %04x\n", A, V);
|
||||
|
||||
@ -384,7 +384,8 @@ void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V)
|
||||
case 0x8: Timers[which].Target = V & 0xFFFF;
|
||||
break;
|
||||
|
||||
default: assert(0);
|
||||
case 0xC: // Open bus
|
||||
break;
|
||||
}
|
||||
|
||||
// TIMER_Update(timestamp);
|
||||
@ -397,10 +398,12 @@ uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
uint16 ret = 0;
|
||||
int which = (A >> 4) & 0x3;
|
||||
|
||||
assert(!(A & 3));
|
||||
|
||||
if(which >= 3)
|
||||
assert(0);
|
||||
{
|
||||
PSX_WARNING("[TIMER] Open Bus Read: 0x%08x", A);
|
||||
|
||||
return(ret >> ((A & 3) * 8));
|
||||
}
|
||||
|
||||
TIMER_Update(timestamp);
|
||||
|
||||
@ -416,10 +419,11 @@ uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
||||
case 0x8: ret = Timers[which].Target;
|
||||
break;
|
||||
|
||||
default: assert(0);
|
||||
case 0xC: PSX_WARNING("[TIMER] Open Bus Read: 0x%08x", A);
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return(ret >> ((A & 3) * 8));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
DEFS = @DEFS@ @CFLAG_VISIBILITY@
|
||||
INCLUDES = -I./
|
||||
|
||||
noinst_LIBRARIES = libvorbisidec.a
|
||||
|
||||
libvorbisidec_a_SOURCES = mdct.c block.c window.c \
|
||||
synthesis.c info.c \
|
||||
floor1.c floor0.c vorbisfile.c \
|
||||
res012.c mapping0.c registry.c codebook.c \
|
||||
sharedbook.c framing.c bitwise.c \
|
||||
codebook.h misc.h mdct_lookup.h\
|
||||
os.h mdct.h block.h ivorbisfile.h lsp_lookup.h\
|
||||
registry.h window.h window_lookup.h\
|
||||
codec_internal.h backends.h ogg.h \
|
||||
asm_arm.h ivorbiscodec.h
|
@ -1,623 +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/tremor
|
||||
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
COPYING
|
||||
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 = @
|
||||
libvorbisidec_a_AR = $(AR) $(ARFLAGS)
|
||||
libvorbisidec_a_LIBADD =
|
||||
am_libvorbisidec_a_OBJECTS = mdct.$(OBJEXT) block.$(OBJEXT) \
|
||||
window.$(OBJEXT) synthesis.$(OBJEXT) info.$(OBJEXT) \
|
||||
floor1.$(OBJEXT) floor0.$(OBJEXT) vorbisfile.$(OBJEXT) \
|
||||
res012.$(OBJEXT) mapping0.$(OBJEXT) registry.$(OBJEXT) \
|
||||
codebook.$(OBJEXT) sharedbook.$(OBJEXT) framing.$(OBJEXT) \
|
||||
bitwise.$(OBJEXT)
|
||||
libvorbisidec_a_OBJECTS = $(am_libvorbisidec_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_lt = $(am__v_lt_$(V))
|
||||
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_lt_0 = --silent
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_$(V))
|
||||
am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_$(V))
|
||||
am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_$(V))
|
||||
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libvorbisidec_a_SOURCES)
|
||||
DIST_SOURCES = $(libvorbisidec_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 = @DEFS@ @CFLAG_VISIBILITY@
|
||||
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@
|
||||
INCLUDES = -I./
|
||||
noinst_LIBRARIES = libvorbisidec.a
|
||||
libvorbisidec_a_SOURCES = mdct.c block.c window.c \
|
||||
synthesis.c info.c \
|
||||
floor1.c floor0.c vorbisfile.c \
|
||||
res012.c mapping0.c registry.c codebook.c \
|
||||
sharedbook.c framing.c bitwise.c \
|
||||
codebook.h misc.h mdct_lookup.h\
|
||||
os.h mdct.h block.h ivorbisfile.h lsp_lookup.h\
|
||||
registry.h window.h window_lookup.h\
|
||||
codec_internal.h backends.h ogg.h \
|
||||
asm_arm.h ivorbiscodec.h
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .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/tremor/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/tremor/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)
|
||||
libvorbisidec.a: $(libvorbisidec_a_OBJECTS) $(libvorbisidec_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libvorbisidec.a
|
||||
$(AM_V_AR)$(libvorbisidec_a_AR) libvorbisidec.a $(libvorbisidec_a_OBJECTS) $(libvorbisidec_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libvorbisidec.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitwise.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/block.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codebook.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/floor0.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/floor1.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/framing.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapping0.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdct.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/res012.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sharedbook.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/synthesis.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vorbisfile.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLIBRARIES ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
@ -1,785 +0,0 @@
|
||||
CHANGES -- trio
|
||||
|
||||
|
||||
The changes listed without a name attributed to them were most likely done by
|
||||
Bjorn Reese and/or Daniel Stenberg.
|
||||
|
||||
Version 1.14 - 2010/01/26
|
||||
-------------------------
|
||||
* David Byron
|
||||
Added trio_xstring_append_max.
|
||||
|
||||
* Fixed compilation problem on Cygwin due to lack of long double math
|
||||
(reported by Matthias Andree).
|
||||
|
||||
* David Boyce
|
||||
Added #undef of standard stdio function names before assigning trio functions
|
||||
to them.
|
||||
|
||||
* Matthias Andree
|
||||
Upgraded configure.in to use new macros instead of obsoleted macros.
|
||||
|
||||
* Matthias Andree
|
||||
Added VPATH to Makefile.in
|
||||
|
||||
* Tom Honermann
|
||||
Fixed problem with subnormal numbers which caused an infinite loop outputting
|
||||
leading spaces.
|
||||
|
||||
* Adam McLaurin
|
||||
Improved parsing performance by avoiding memset() and memcpy() on character
|
||||
arrays.
|
||||
|
||||
* Gideon Smeding
|
||||
Fixed %u scanning of signed numbers.
|
||||
|
||||
* Gideon Smeding
|
||||
Fixed group scanning for non-matching input.
|
||||
|
||||
* Fixed missing undo of look-ahead reading for scanf functions. This does only
|
||||
work for the scanf* and fscanf* functions, not dscanf* and cscanf* functions
|
||||
(reported by Gideon Smeding).
|
||||
|
||||
* If the format string is empty, scanf does not attempt to read any input.
|
||||
|
||||
* Ralf Junker
|
||||
Fixed Borland compilation for user-defined specifiers.
|
||||
|
||||
|
||||
Version 1.13 - 2008/11/09
|
||||
-------------------------
|
||||
* Ives Aerts
|
||||
Added the $<format|skip> format for user-defined specifiers, which is
|
||||
compatible with compiler warnings about mismatches between specifiers and
|
||||
arguments.
|
||||
|
||||
* Added TRIO_DEPRECATED flag (reported by David Boyce)
|
||||
|
||||
* Fixed rounding adjustment for long double (reported as bug item #2136686).
|
||||
|
||||
* Added Makefile dependency for test target (reported as bug item #2136636).
|
||||
|
||||
* David Boyce
|
||||
Fixed long long support for MSVC.
|
||||
|
||||
* Fixed potential problem with read after buffer end for non-zero terminated
|
||||
strings (reported as bug item #1828465).
|
||||
|
||||
* Andreas Stricker
|
||||
Added WinCE support.
|
||||
|
||||
* Fixed number of significant digits for %g.
|
||||
|
||||
|
||||
Version 1.12 - 2006/10/22
|
||||
-------------------------
|
||||
* Fixed scanning of floats (reported by Bernd Ahlers).
|
||||
|
||||
* Fixed configure.in for GCC on Tru64 and MIPSpro on IRIX (reported by Andreas
|
||||
Maus).
|
||||
|
||||
* Olli Savia
|
||||
Added support for LynxOS.
|
||||
|
||||
|
||||
Version 1.11 - 2006/04/08
|
||||
-------------------------
|
||||
* Mark Pickelmann
|
||||
Fixed trio_unregister. If the first element was removed, the remaining
|
||||
list would be removed as well.
|
||||
|
||||
* Fixed unintended formatting of %e that would result in non-zero numbers
|
||||
starting with zero (reported by Mark Pickelmann and Gisli Ottarsson).
|
||||
|
||||
* Fixed compilation with Sun Workshop 6 (reported by Matthias Andree).
|
||||
|
||||
* Fixed accuracy for denormalized numbers (bug item #758327).
|
||||
|
||||
* Glen Davidson
|
||||
Fixed scanning of floating-point numbers without a decimal-point (bug item
|
||||
#1370427).
|
||||
|
||||
* David Byron
|
||||
Fixed more compiler warnings.
|
||||
|
||||
* Fixed compilation of trio_to_long_double and TRIO_FEATURE_FLOAT (reported by
|
||||
David Byron).
|
||||
|
||||
* Fixed precision of large floating-point numbers (bug item #1314524).
|
||||
|
||||
* Karl Bochert
|
||||
Fixed trio_fpclassify_and_signbit to only restore the floating-point
|
||||
precision.
|
||||
|
||||
* Fixed detection of need for ieee option on FreeBSD/Alpha.
|
||||
|
||||
* Added TRIO_SNPRINTF_ONLY compilation.
|
||||
|
||||
* Fixed trio_to_double by not using strtod() on Tru64/DECC because it does not
|
||||
support hex-floats.
|
||||
|
||||
* Fixed crash on 64 bits machines related to a previous workaround in version
|
||||
1.9 for uninitialized va_list (reported by Nicolai Tufar, suggestion by
|
||||
Douglas Gwyn).
|
||||
|
||||
* Patrick Jessee
|
||||
Fixed width calculation for %g.
|
||||
|
||||
* Added macros for internal features.
|
||||
|
||||
* Jon Foster
|
||||
Added macros for conditional compilation of many features. Documented all
|
||||
the features.
|
||||
|
||||
* Karl Bochert
|
||||
Fixed problem with Borland C++, which changes the floating-point precision
|
||||
for certain math functions (log10() and _fpclass()).
|
||||
|
||||
* Karl Bochert
|
||||
Fixed compilation warnings on Borland C++.
|
||||
|
||||
* Removed any occurrence of #elif because Borland C++ reports wrong line
|
||||
numbers when they are present (reported by Karl Bochert).
|
||||
|
||||
* David Byron
|
||||
Added trio_asprintfv.
|
||||
|
||||
* Brian Chapman
|
||||
Fixed Mac OS X compilation.
|
||||
|
||||
* David Byron
|
||||
Fixed several compiler warnings.
|
||||
|
||||
* Fixed printing of out-of-range arguments for %hhd and %hd. These arguments
|
||||
can be out of range because of default integer promotion.
|
||||
|
||||
* Bob Friesenhahn
|
||||
Fixed installation of header files.
|
||||
|
||||
* Joe Orton
|
||||
Added SHELL to Makefile.in to avoid problems with CShells.
|
||||
|
||||
* Shaun Tancheff
|
||||
Fixed regresion tests for MSVC.
|
||||
|
||||
* Craig Berry
|
||||
Fixed the VMS C99 workaround.
|
||||
|
||||
|
||||
Version 1.10 - 2003/03/06
|
||||
-------------------------
|
||||
* Rearranged some include files to accommodate large file support (reported by
|
||||
Albert Chin-A-Young).
|
||||
|
||||
* Added support for SunOS 4.1.x lack of strerror, tolower, and toupper
|
||||
(reported by Peter McCluskey).
|
||||
|
||||
* Fixed pedantic compilation with TRIO_MINIMAL.
|
||||
|
||||
* Jose Kahan
|
||||
Moved <limits.h> to avoid redefinition problems.
|
||||
|
||||
* Fixed hex-float exponents (reported by Matthias Clasen).
|
||||
|
||||
* Fixed handling of negative width and precision via paramters (reported by
|
||||
Jacob Navia).
|
||||
|
||||
* Nigel Hall
|
||||
Fixed TRIO_VA_START for VMS.
|
||||
|
||||
* Rune Enggaard Lausen
|
||||
Fixed compilation for Borland C++ Builder.
|
||||
|
||||
* Fixed precision of hex-float numbers (reported by James Antill).
|
||||
|
||||
* Fixed plus sign only to be added for signed numbers.
|
||||
|
||||
* Fixed printing of integers with value and precision of zero (reported by
|
||||
James Antill).
|
||||
|
||||
* Fixed %#.o to only print one zero if the value is zero (reported by James
|
||||
Antill).
|
||||
|
||||
* Rewrote check for IEEE compilation option to remove dependency on additional
|
||||
scripts.
|
||||
|
||||
* Mehdi Lavasani
|
||||
Makefile install target fixed to work with older install programs.
|
||||
|
||||
* Collapsed the DECC, MSVC, HP-UX, and AIX code for trio_fpclassify_and_sign()
|
||||
with further preprocessing.
|
||||
|
||||
|
||||
Version 1.9 - 2002/10/13
|
||||
------------------------
|
||||
* Fixed trio_fpclassify_and_signbit on AIX 3.2
|
||||
|
||||
* Added configure check for -ieee/-mieee compilation option for Alpha machines.
|
||||
|
||||
* Craig Berry
|
||||
Fixed compilation on VMS.
|
||||
|
||||
* Albert Chin-A-Young
|
||||
Fixed incorrect conditional expression in trio_isinf.
|
||||
|
||||
* Fixed the warnings about uninitialized va_list in the printfv and scanfv
|
||||
family without the use of compiler specific pragmas (suggested by Ian
|
||||
Pilcher).
|
||||
|
||||
* Fixed space flag for floating-point numbers (reported by Ian Main).
|
||||
|
||||
|
||||
Version 1.8 - 2002/07/10
|
||||
------------------------
|
||||
* Fixed infinite loop in multibyte handling (reported by Gisli Ottarsson).
|
||||
|
||||
* Added the customizable cprintf/cscanf family which enables to user to specify
|
||||
input and output stream functions (suggested by Florian Schulze).
|
||||
|
||||
* Fixed trio_isinf by removing the HP-UX workaround, and instead making sure
|
||||
that the C99 macro will adhere to the trio return values (reported by Luke
|
||||
Dunstan).
|
||||
|
||||
* Alexander Lukyanov
|
||||
Fixed boundary case for scanning and EOF.
|
||||
|
||||
* Jacob Navia
|
||||
Enabled the L modifier for formatting.
|
||||
|
||||
* Added TRIO_MINIMAL to build trio without the string functions.
|
||||
|
||||
* Added the R modifier to print rounded floating-point numbers.
|
||||
|
||||
* Added trio_to_long_double and long double scanning (the L modifier).
|
||||
|
||||
* Added trio_locale_decimal_point, trio_locale_thousand_separator,
|
||||
trio_locale_grouping to overwrite locale settings.
|
||||
|
||||
* Rewrote TrioWriteDouble to avoid temporary buffers and thus the danger of
|
||||
buffer overflows (for instance %.5000f).
|
||||
|
||||
* Improved floating-point formatting accuracy.
|
||||
|
||||
* Fixed formatting of non-decimal exponents.
|
||||
|
||||
* Fixed thousand separator checking.
|
||||
|
||||
* Fixed %f scanning to get a float and %lf to get a double.
|
||||
|
||||
* Fixed WIN32 compilation (reported by Emmanuel Mogenet)
|
||||
|
||||
* Fixed regression test cases to exclude disabled features.
|
||||
|
||||
|
||||
Version 1.7 - 2002/05/07
|
||||
------------------------
|
||||
* Fixed trio_to_double to handle hex-floats properly.
|
||||
|
||||
* Fixed printing of %a-format to be like %e, not like %g.
|
||||
|
||||
* Fixed floating-point printing of values beyond the machine accuracy.
|
||||
|
||||
* Fixed %f for printing with large precision.
|
||||
|
||||
* Fixed the usage of C99 nan(), which caused a crash on OSF/1 (reported by
|
||||
Georg Bolz)
|
||||
|
||||
* Joe Orton
|
||||
Fixed %p on 64-bit platforms.
|
||||
|
||||
* Made trio compile with K&R compilers.
|
||||
|
||||
* Emmanuel Mogenet
|
||||
Fixed bug in trio_asprintf.
|
||||
|
||||
* Emmanuel Mogenet
|
||||
Various WIN32 fixes.
|
||||
|
||||
* Joe Orton
|
||||
Fixed trio_isinf() on HP-UX, and added test cases.
|
||||
|
||||
* Joe Orton
|
||||
Fixed non-portable use of $^ in Makefile.
|
||||
|
||||
* Joe Orton
|
||||
Added autoconf.
|
||||
|
||||
* Alexander Lukyanov
|
||||
Fixed a number of bugs in the scanning of EOF and the count specifier.
|
||||
|
||||
* Richard Jinks
|
||||
Added trio_nzero
|
||||
|
||||
* Fixed incorrect handling of return code from TrioReadChar (reported by
|
||||
Henrik Löf)
|
||||
|
||||
* Fixed parsing of character class expressions.
|
||||
|
||||
* Fixed trio_to_double which did not work with long fractions.
|
||||
|
||||
* Fixed %f for printing of large numbers.
|
||||
|
||||
* Fixed %#s to handle whitespaces as non-printable characters.
|
||||
|
||||
* Added trio_isfinite, trio_signbit, and trio_fpclassify.
|
||||
|
||||
* Added new test cases.
|
||||
|
||||
|
||||
Version 1.6 - 2002/01/13
|
||||
------------------------
|
||||
* Added dynamic string functions.
|
||||
|
||||
* Rewrote and extended documentation in JavaDoc (using Doxygen).
|
||||
|
||||
* Moved and renamed strio functions to triostr.
|
||||
|
||||
* Robert Collins
|
||||
Added definition for Cygwin.
|
||||
|
||||
* Markus Henke
|
||||
Added long double workaround for the HP C/iX compiler.
|
||||
|
||||
* Marc Verwerft
|
||||
Improved error handling for dynamically allocated strings.
|
||||
|
||||
* John Fotheringham
|
||||
Made trionan compile on OpenVMS.
|
||||
|
||||
* Added 'd' and 'D' as exponent letters when using TRIO_MICROSOFT.
|
||||
|
||||
* Fixed uninitial memory read for the parameter modifiers.
|
||||
|
||||
|
||||
Version 1.5 - 2001/09/08
|
||||
------------------------
|
||||
* Merged with libxml changes.
|
||||
|
||||
* Moved NaN and Inf handling to separate file to enable reuse in other
|
||||
projects.
|
||||
|
||||
* Igor Zlatkovic
|
||||
Fixed TrioGenerateNan for MSVC.
|
||||
|
||||
* Fixed lots of preprocessor macros and internal data structure names.
|
||||
|
||||
|
||||
Version 1.4 - 2001/06/03
|
||||
------------------------
|
||||
* Added hex-float (%a and %A) for scanning.
|
||||
|
||||
* Added wide character arguments (%ls, %ws, %S, %lc, %wc, and %C) for both
|
||||
printf and scanf.
|
||||
|
||||
* Added mutex callbacks for user-specified specifiers to enable applications to
|
||||
add thread-safety. These are registered with trio_register, where the
|
||||
namespace is set to either ":enter" to lock a mutex, or ":leave" to unlock a
|
||||
mutex.
|
||||
|
||||
* Added equivalence class expressions for scanning. For example, %[[=a=]] scans
|
||||
for all letters in the same equivalence class as the letter 'a' as defined
|
||||
by the locale.
|
||||
|
||||
* Changed character class expressions for scanning. The expressions must now
|
||||
be embedded withing an extra set of brackets, e.g. %[[:alpha:]]. This was
|
||||
done to adhere to the syntax of UNIX98 regular expressions.
|
||||
|
||||
* Added the possibility to specify standard support (TRIO_C99 etc.) as compiler
|
||||
options.
|
||||
|
||||
* Fixed conversion of hex-float in StrToDouble.
|
||||
|
||||
* Fixed formatting of hex-float numbers.
|
||||
|
||||
* Stan Boehm
|
||||
Fixed crash on QNX, which happend because some buffers on the stack were too
|
||||
big.
|
||||
|
||||
* Fixed default precision for %f and %g (reported by Jose Ortiz)
|
||||
|
||||
* Howard Kapustein
|
||||
Added the I8, I16, I32, and I64 modifiers.
|
||||
|
||||
* Jose Ortiz
|
||||
Fixed rounding problem for %e.
|
||||
|
||||
* Jose Ortiz
|
||||
Fixed various problems with the xlC and Sun C++ compilers.
|
||||
|
||||
|
||||
Version 1.3 - 2001/05/16
|
||||
------------------------
|
||||
* trio's treatment of the field width when the %e code was used was not
|
||||
correct (reported by Gisli Ottarsson). It turns out the fraction part should
|
||||
be zero-padded by default and the exponent part should be zero-prefixed if
|
||||
it is only one digit. At least that's how the GNU and Sun libc's work. The
|
||||
trio floating point output looks identical to them now.
|
||||
|
||||
* Fixed group scanning with modifiers.
|
||||
|
||||
* Fixed compilation for 64-bit Digital Unix.
|
||||
|
||||
* Igor Zlatkovic
|
||||
Fixed compilation of dprintf, which uses read/write, for MSVC.
|
||||
|
||||
* Fixed various compilation problems on Digital Unix (mainly associated with
|
||||
va_list).
|
||||
|
||||
|
||||
Version 1.2 - 2001/04/11
|
||||
------------------------
|
||||
* Added autoconf integration. If compiled with HAVE_CONFIG_H the following
|
||||
happens. Firstly, <config.h> is included. Secondly, trio will only be
|
||||
compiled if WITH_TRIO is defined herein. Thirdly, if TRIO_REPLACE_STDIO is
|
||||
defined, only stdio functions that have not been detected by autoconf, i.e.
|
||||
those not defined by HAVE_PRINTF or similar, will be replaced by trio
|
||||
functions (suggested by Daniel Veillard).
|
||||
|
||||
* Fixed '%m.nf' output. Previously trio did not treat the width properly
|
||||
in all cases (reported by Gisli Ottarsson).
|
||||
|
||||
* Added explicit promotion for the scanfv family.
|
||||
|
||||
* Fixed more C++ compilation warnings.
|
||||
|
||||
|
||||
Version 1.1 - 2001/02/25
|
||||
------------------------
|
||||
* Added explicit promotion for the printfv familiy. A float must be specified
|
||||
by %hf.
|
||||
|
||||
* Fixed positionals for printfv (reported by Gisli Ottarsson).
|
||||
|
||||
* Fixed an integer to pointer conversion problem on the SGI MIPS C compiler
|
||||
(reported by Gisli Ottarsson).
|
||||
|
||||
* Fixed ANSI C++ warnings (type casting, and namespace is a reserved keyword).
|
||||
|
||||
* Added \n to all examples in the documentation to prevent confusion.
|
||||
|
||||
* Fixed StrSubstringMax
|
||||
|
||||
|
||||
Version 1.0 - 2000/12/10
|
||||
------------------------
|
||||
* Bumped Version number.
|
||||
|
||||
|
||||
Version 0.25 - 2000/12/09
|
||||
-------------------------
|
||||
* Wrote more documentation.
|
||||
|
||||
* Improved NaN support and added NaN to regression test.
|
||||
|
||||
* Fixed C99 support.
|
||||
|
||||
* Added missing getter/setter functions.
|
||||
|
||||
|
||||
Version 0.24 - 2000/12/02
|
||||
-------------------------
|
||||
* Added callback functionality for the user-defined specifier (<>). All
|
||||
the necessary functions are defined in triop.h header file. See the
|
||||
documentation for trio_register for further detail.
|
||||
|
||||
* Wrote initial documentation on the callback functionality.
|
||||
|
||||
* Added the printfv and scanfv family of functions, which takes a pointer
|
||||
array rather than variadic arguments. Each pointer in the array must point
|
||||
to the associated data (requested by Bruce Korb).
|
||||
|
||||
* As indicated in version 0.21 the extension modifiers (<>) have now been
|
||||
completely removed.
|
||||
|
||||
* Added skipping of thousand-separators in floating-point number scanning.
|
||||
|
||||
|
||||
Version 0.23 - 2000/10/21
|
||||
-------------------------
|
||||
* Added width to scanning of floating-point numbers.
|
||||
|
||||
* Wrote more documentation on trio_printf.
|
||||
|
||||
* Fixed problem with trailing zeroes after decimal-point.
|
||||
|
||||
|
||||
Version 0.22 - 2000/08/06
|
||||
-------------------------
|
||||
* Added LC_CTYPE locale dependent character class expressions to scan lists.
|
||||
Included are [:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:],
|
||||
[:lower:], [:print:], [:punct:], [:space:], [:upper:], [:xdigit:]
|
||||
|
||||
* Added C escapes to alternative string formatting and scanning.
|
||||
|
||||
* Added StrSubstringMax.
|
||||
|
||||
* Wrote a little more documentation.
|
||||
|
||||
* Fixed scanf return values.
|
||||
|
||||
* Fixed a sign error for non-ascii characters.
|
||||
|
||||
|
||||
Version 0.21 - 2000/07/19
|
||||
-------------------------
|
||||
* Converted the documentation to TeX. With latex2man the documentation can
|
||||
automatically be converted into man pages.
|
||||
|
||||
* Added trio_scanf, trio_vscanf, trio_fscanf, and trio_vfscanf.
|
||||
|
||||
* Added trio_dprintf, trio_vdprintf, trio_dscanf, and trio_vdscanf. These
|
||||
functions can be used to write and read directly to pipes and sockets (the
|
||||
assume blocking sockets). Stdio buffering is surpassed, so the functions are
|
||||
async-safe. However, reading from stdin (STDIN_FILENO) or writing to stdout
|
||||
(STDOUT_FILENO) reintroduces the buffering.
|
||||
|
||||
* Paul Janzen
|
||||
Added trio_asprintf and trio_vasprintf, which are compatible with the GNU
|
||||
and BSD interfaces.
|
||||
|
||||
* Added scanlist ranges for group scanning (%[]).
|
||||
|
||||
* Added width for scanning (missing for floating-point numbers though).
|
||||
|
||||
* Added variable size modifier (&) to handle system defined types of unknown
|
||||
size. This modifier makes certain assumptions about the integer sizes, which
|
||||
may not be valid on any machine. Consequently, the modifier will remain
|
||||
undocumented, as it may be removed later.
|
||||
|
||||
* Added \777 and \xFF to alternative string scanning (%#s)
|
||||
|
||||
* Added the TRIO_REPLACE_STDIO check in the header.
|
||||
|
||||
* Improved performance of the multibyte character parsing.
|
||||
|
||||
* Fixed positionals (%n$) which had stopped working.
|
||||
|
||||
* Fixed hh and ll modifiers to allow exactly two letters and no more.
|
||||
|
||||
* Fixed ANSI C++ warnings. Also fixed the compiler warning about casting
|
||||
between integer and pointer (this has been annoying me for ages).
|
||||
|
||||
* Fixed snprintf and vsnprintf with zero buffer size.
|
||||
|
||||
* Fixed NAN problems (reported by Keith Briggs).
|
||||
|
||||
* Fixed parsing of multibyte characters. The format string was not correctly
|
||||
advanced in case of a multibyte character.
|
||||
|
||||
* Renamed many of the internal functions to have more consistant names.
|
||||
|
||||
* Removed the <quote=c> and <fill=c> modifiers. They are not really worth
|
||||
including. The other <> modifiers may disappear as well.
|
||||
|
||||
|
||||
Version 0.20 - 2000/06/05
|
||||
-------------------------
|
||||
* Added intmax_t and ptrdiff_t support.
|
||||
|
||||
* Added support for LC_NUMERIC grouping.
|
||||
|
||||
* Added double-dot notation for the conversion base. The style is now
|
||||
%width.precision.base, where any argument can be a number, an asterix
|
||||
indicating a parameter, or be omitted entirely. For example, %*..2i is
|
||||
to specify binary numbers without precision, and with width as a parameter
|
||||
on the va_list.
|
||||
|
||||
* Added sticky modifier (!), which makes subsequent specifiers of the same
|
||||
type reuse the current modifiers. Inspired by a suggestion from Gary Porter.
|
||||
|
||||
* Added group scanning (%[]). Scanlist ranges and multibyte sequences are not
|
||||
supported yet.
|
||||
|
||||
* Added count scanning (%n).
|
||||
|
||||
* Changed the number scanning to accept thousand separators and any base.
|
||||
|
||||
* Fixed positional for parameters. It is possible to write something like
|
||||
%3$*1$.*2$d (which happens to be the same as %*.*d).
|
||||
|
||||
* Fixed precision of integers.
|
||||
|
||||
* Fixed parameter flags. Before trio could only handle one parameter flag per
|
||||
specifier, although two (three with double-dot base) were possible.
|
||||
|
||||
* Fixed isinf() for those platforms where it is unimplemented.
|
||||
|
||||
|
||||
Version 0.18 - 2000/05/27
|
||||
-------------------------
|
||||
* Rewrote the entire floating-point formatting function (Danny Dulai had
|
||||
reported several errors and even supplied some patches, which unfortunately
|
||||
were lost due to the refactoring).
|
||||
|
||||
* Removed the use of strlen() in the declaration of a stack array. This
|
||||
caused problems on some compilers (besides it isn't really ANSI C compliant
|
||||
anyways). Using some arbitrarily chosen maximum value; should examine if
|
||||
some standard defines an upper limit on the length of decimal-point and
|
||||
thousands-separator (sizeof(wchar_t) perhaps?)
|
||||
|
||||
* Changed the parsing of the format string to be multibyte aware.
|
||||
|
||||
|
||||
Version 0.17 - 2000/05/19
|
||||
-------------------------
|
||||
* Added INF, -INF, and NAN for floating-point numbers.
|
||||
|
||||
* Fixed %#.9g -- alternative with precision.
|
||||
|
||||
* Ken Gibson
|
||||
Fixed printing of negative hex numbers
|
||||
|
||||
* Joerg (last name unknown)
|
||||
Fixed convertion of non-ASCII characters
|
||||
|
||||
|
||||
Version 0.16 - 1999/08/06
|
||||
-------------------------
|
||||
* Changed the constness of the second argument of StrFloat and StrDouble. The
|
||||
lack of parameter overloading in C is the reason for the strange use of
|
||||
constness in strtof and strtod.
|
||||
|
||||
* Cleaned up constness.
|
||||
|
||||
|
||||
Version 0.15 - 1999/07/23
|
||||
-------------------------
|
||||
* Fixed the internal representation of numbers from signed to unsigned. Signed
|
||||
numbers posed a problem for large unsigned numbers (reported by Tero)
|
||||
|
||||
* Fixed a tiny bug in trio_vsprintfcat
|
||||
|
||||
* Changed the meaning of the max argument of StrAppendMax to be consistant
|
||||
with StrFormatAppendMax. Now it is the maximal size of the entire target
|
||||
buffer, not just the appended size. This makes it easier to avoid buffer
|
||||
overflows (requested by Tero)
|
||||
|
||||
|
||||
Version 0.14 - 1999/05/16
|
||||
-------------------------
|
||||
* Added size_t support (just waiting for a C99 compliant compiler to add
|
||||
ptrdiff_t and intmax_t)
|
||||
|
||||
* Rewrote TrioOutStreamDouble so it does not use the libc sprintf to emulate
|
||||
floating-point anylonger.
|
||||
|
||||
* Fixed width, precision, and adjustment for numbers and doubles.
|
||||
|
||||
|
||||
Version 0.13 - 1999/05/06
|
||||
-------------------------
|
||||
* Fixed zero padding for %d. Now %d will only zero pad if explicitly requested
|
||||
to do so with the 0 flag (reported by Tero).
|
||||
|
||||
* Fixed an incorrect while() condition in TrioGetString (reported by Tero).
|
||||
|
||||
|
||||
Version 0.12 - 1999/04/19
|
||||
-------------------------
|
||||
* Fixed incorrect zero padding of pointers
|
||||
|
||||
* Added StrHash with STRIO_HASH_PLAIN
|
||||
|
||||
* Added StrFormatDateMax
|
||||
|
||||
|
||||
Version 0.11 - 1999/03/25
|
||||
-------------------------
|
||||
* Made it compile under cygwin
|
||||
|
||||
* Fixed a bug were TrioPreprocess would return an error if no formatting chars
|
||||
were found (reported by Tero).
|
||||
|
||||
|
||||
Version - 1999/03/19
|
||||
--------------------
|
||||
* Added trio_strerror and TRIO_ERROR_NAME.
|
||||
|
||||
* Changed the error codes to be positive (as errno)
|
||||
|
||||
* Fixed two reads of uninitialized memory reported by Purify
|
||||
|
||||
* Added binary specifiers 'b' and 'B' (like SCO.) ThousandSeparator can be
|
||||
used to separate nibbles (4 bit)
|
||||
|
||||
* Renamed all Internal* functions to Trio*, which seems like a better
|
||||
namespace (even though it is of no practical interest because these
|
||||
functions are not visible beyond the scope of this file.)
|
||||
|
||||
|
||||
Version - 1999/03/12
|
||||
--------------------
|
||||
* Added hex-float format for StrToDouble
|
||||
|
||||
* Double references and gaps in the arguments are not allowed (for the %n$
|
||||
format) and in both cases an error code is returned.
|
||||
|
||||
* Added StrToDouble (and StrToFloat)
|
||||
|
||||
|
||||
Version - 1999/03/08
|
||||
--------------------
|
||||
* Added InStream and OutStream to the trio_T structure.
|
||||
|
||||
* Started work on TrioScan.
|
||||
|
||||
* Return values for errors changed. Two macros to unpack the error code has
|
||||
been added to the header.
|
||||
|
||||
* Shortshort (hh) flag added.
|
||||
|
||||
* %#s also quotes the quote-char now.
|
||||
|
||||
* Removed the 'errorInFormat' boolean, which isn't used anymore after the
|
||||
functions bail out with an error instead.
|
||||
|
||||
|
||||
Version - 1999/03/04
|
||||
--------------------
|
||||
* More than MAX_PARAMETERS parametes will now cause the TrioPreprocess()
|
||||
function to return error.
|
||||
|
||||
* Unknown flags and/or specifiers cause errors too.
|
||||
|
||||
* Added trio_snprintfcat and trio_vsnprintfcat and the defined name
|
||||
StrFormatAppendMax. They append a formatted string to the end of a string.
|
||||
|
||||
* Define MAX_PARAMETERS to 128 at all times instead of using NL_ARGMAX when
|
||||
that exists.
|
||||
|
||||
* Added platform fixes for Amiga as suggested by Tero Jänkä <tesaja@utu.fi>
|
||||
|
||||
|
||||
Version - 1999/01/31
|
||||
--------------------
|
||||
* vaprintf did add a zero byte even when it had failed.
|
||||
|
||||
* Cleaned up the code for locale handling and thousand separator
|
||||
|
||||
* Added trio_aprintf() and trio_vaprintf(). They return an allocated string.
|
||||
|
||||
* Added thousands separator for numbers
|
||||
|
||||
* Added floating point support for *printf
|
||||
|
||||
|
||||
Version - 1998/10/20
|
||||
--------------------
|
||||
* StrMatchCase() called StrMatch() instead of itself recursively
|
||||
|
||||
* Rewrote the implementation of *printf and *scanf and put all the code in
|
||||
this file. Extended qualifiers and qualifiers from other standards were
|
||||
added.
|
||||
|
||||
* Added StrSpanFunction, StrToLong, and StrToUnsignedLong
|
||||
|
||||
|
||||
Version - 1998/05/23
|
||||
--------------------
|
||||
* Made the StrEqual* functions resistant to NULL pointers
|
||||
|
||||
* Turns out strdup() is no standard at all, and some platforms (I seem to
|
||||
recall HP-UX) has problems with it. Made our own StrDuplicate() instead.
|
||||
|
||||
* Added StrFormat() and StrFormatMax() to serve as sprintf() and snprintf()
|
||||
respectively.
|
@ -1,6 +0,0 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @TRIO_CFLAGS@
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl
|
||||
|
||||
noinst_LIBRARIES = libtrio.a
|
||||
libtrio_a_SOURCES = trio.c trionan.c triostr.c
|
@ -1,599 +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/trio
|
||||
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 = @
|
||||
libtrio_a_AR = $(AR) $(ARFLAGS)
|
||||
libtrio_a_LIBADD =
|
||||
am_libtrio_a_OBJECTS = trio.$(OBJEXT) trionan.$(OBJEXT) \
|
||||
triostr.$(OBJEXT)
|
||||
libtrio_a_OBJECTS = $(am_libtrio_a_OBJECTS)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_lt = $(am__v_lt_$(V))
|
||||
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_lt_0 = --silent
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_$(V))
|
||||
am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_$(V))
|
||||
am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_$(V))
|
||||
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libtrio_a_SOURCES)
|
||||
DIST_SOURCES = $(libtrio_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@ @TRIO_CFLAGS@
|
||||
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
|
||||
noinst_LIBRARIES = libtrio.a
|
||||
libtrio_a_SOURCES = trio.c trionan.c triostr.c
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .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/trio/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/trio/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)
|
||||
libtrio.a: $(libtrio_a_OBJECTS) $(libtrio_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libtrio.a
|
||||
$(AM_V_AR)$(libtrio_a_AR) libtrio.a $(libtrio_a_OBJECTS) $(libtrio_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libtrio.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trio.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trionan.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/triostr.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -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:
|
@ -4,6 +4,5 @@
|
||||
#include "video.h"
|
||||
|
||||
void MDFND_DispMessage(UTF8 *text);
|
||||
void MDFNI_SaveSnapshot(const MDFN_Surface *src, const MDFN_Rect *rect, const MDFN_Rect *LineWidths);
|
||||
|
||||
#endif
|
||||
|
@ -160,14 +160,6 @@ class MDFN_PixelFormat
|
||||
|
||||
}; // MDFN_PixelFormat;
|
||||
|
||||
struct MDFN_PaletteEntry
|
||||
{
|
||||
uint8 r, g, b;
|
||||
};
|
||||
|
||||
#include <vector>
|
||||
typedef std::vector<MDFN_PaletteEntry> MDFN_Palette;
|
||||
|
||||
// Supports 32-bit RGBA
|
||||
// 16-bit is WIP
|
||||
class MDFN_Surface //typedef struct
|
||||
|
Loading…
Reference in New Issue
Block a user