mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-26 18:30:26 +00:00
(Mednafen PCE) Update to 0.9.33.3
This commit is contained in:
parent
f23e446ff8
commit
c2adc1c619
28
Makefile
28
Makefile
@ -4,6 +4,7 @@ FRONTEND_SUPPORTS_RGB565 = 1
|
||||
MEDNAFEN_DIR := mednafen
|
||||
MEDNAFEN_LIBRETRO_DIR := mednafen-libretro
|
||||
NEED_TREMOR = 0
|
||||
LIBRETRO_SOURCES :=
|
||||
|
||||
ifeq ($(platform),)
|
||||
platform = unix
|
||||
@ -71,7 +72,8 @@ else ifeq ($(core), pce-fast)
|
||||
ifneq ($(platform), osx)
|
||||
PTHREAD_FLAGS = -pthread
|
||||
endif
|
||||
NEED_BPP = 32
|
||||
HAVE_HES = 0
|
||||
NEED_BPP = 16
|
||||
NEED_TREMOR = 1
|
||||
NEED_BLIP = 1
|
||||
NEED_CD = 1
|
||||
@ -79,15 +81,23 @@ endif
|
||||
NEED_SCSI_CD = 1
|
||||
NEED_THREADING = 1
|
||||
NEED_CRC32 = 1
|
||||
WANT_NEW_API = 1
|
||||
CORE_DEFINE := -DWANT_PCE_FAST_EMU
|
||||
CORE_DIR := $(MEDNAFEN_DIR)/pce_fast
|
||||
CORE_DIR := $(MEDNAFEN_DIR)/pce_fast-09333
|
||||
|
||||
CORE_SOURCES := $(CORE_DIR)/huc.cpp \
|
||||
CORE_SOURCES := \
|
||||
$(CORE_DIR)/huc.cpp \
|
||||
$(CORE_DIR)/huc6280.cpp \
|
||||
$(CORE_DIR)/input.cpp \
|
||||
$(CORE_DIR)/pce.cpp \
|
||||
$(CORE_DIR)/tsushin.cpp \
|
||||
$(CORE_DIR)/pcecd.cpp \
|
||||
$(CORE_DIR)/pcecd_drive.cpp \
|
||||
$(CORE_DIR)/psg.cpp \
|
||||
$(CORE_DIR)/vdc.cpp
|
||||
|
||||
ifeq ($(HAVE_HES),1)
|
||||
CORE_SOURCES += $(CORE_DIR)/hes.cpp
|
||||
endif
|
||||
TARGET_NAME := mednafen_pce_fast_libretro
|
||||
|
||||
arch = intel
|
||||
@ -484,6 +494,7 @@ endif
|
||||
|
||||
ifeq ($(NEED_CRC32), 1)
|
||||
FLAGS += -DWANT_CRC32
|
||||
LIBRETRO_SOURCES += scrc32.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(NEED_DEINTERLACER), 1)
|
||||
@ -538,7 +549,7 @@ MEDNAFEN_SOURCES := $(MEDNAFEN_DIR)/mednafen.cpp \
|
||||
$(MEDNAFEN_DIR)/md5.cpp
|
||||
|
||||
|
||||
LIBRETRO_SOURCES := libretro.cpp stubs.cpp $(THREAD_STUBS)
|
||||
LIBRETRO_SOURCES += libretro.cpp stubs.cpp $(THREAD_STUBS)
|
||||
|
||||
TRIO_SOURCES += $(MEDNAFEN_DIR)/trio/trio.c \
|
||||
$(MEDNAFEN_DIR)/trio/triostr.c
|
||||
@ -589,6 +600,10 @@ ifeq ($(CACHE_CD), 1)
|
||||
FLAGS += -D__LIBRETRO_CACHE_CD__
|
||||
endif
|
||||
|
||||
ifeq ($(NEED_BPP), 8)
|
||||
FLAGS += -DWANT_8BPP
|
||||
endif
|
||||
|
||||
ifeq ($(NEED_BPP), 16)
|
||||
FLAGS += -DWANT_16BPP
|
||||
endif
|
||||
@ -601,6 +616,9 @@ ifeq ($(NEED_BPP), 32)
|
||||
FLAGS += -DWANT_32BPP
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_NEW_API), 1)
|
||||
FLAGS += -DWANT_NEW_API
|
||||
endif
|
||||
|
||||
CXXFLAGS += $(FLAGS)
|
||||
CFLAGS += $(FLAGS)
|
||||
|
@ -92,7 +92,7 @@ static bool is_pal = false;
|
||||
#include "mednafen/cdrom/pcecd.h"
|
||||
#define MEDNAFEN_CORE_NAME_MODULE "pce_fast"
|
||||
#define MEDNAFEN_CORE_NAME "Mednafen PCE Fast"
|
||||
#define MEDNAFEN_CORE_VERSION "v0.9.28"
|
||||
#define MEDNAFEN_CORE_VERSION "v0.9.33.3"
|
||||
#define MEDNAFEN_CORE_EXTENSIONS "pce|sgx|cue"
|
||||
#define MEDNAFEN_CORE_TIMING_FPS 59.82
|
||||
#define MEDNAFEN_CORE_GEOMETRY_BASE_W (game->nominal_width)
|
||||
|
4
mednafen/cputest/cputest.h
Normal file
4
mednafen/cputest/cputest.h
Normal file
@ -0,0 +1,4 @@
|
||||
#ifndef _MEDNAFEN_CPUTEST_H
|
||||
#define _MEDNAFEN_CPUTEST_H
|
||||
|
||||
#endif
|
@ -104,6 +104,27 @@ typedef struct
|
||||
const InputPortInfoStruct *Types;
|
||||
} InputInfoStruct;
|
||||
|
||||
struct MemoryPatch;
|
||||
|
||||
struct CheatFormatStruct
|
||||
{
|
||||
const char *FullName; //"Game Genie", "GameShark", "Pro Action Catplay", etc.
|
||||
const char *Description; // Whatever?
|
||||
|
||||
bool (*DecodeCheat)(const std::string& cheat_string, MemoryPatch* patch); // *patch should be left as initialized by MemoryPatch::MemoryPatch(), unless this is the
|
||||
// second(or third or whatever) part of a multipart cheat.
|
||||
//
|
||||
// Will throw an std::exception(or derivative) on format error.
|
||||
//
|
||||
// Will return true if this is part of a multipart cheat.
|
||||
};
|
||||
|
||||
struct CheatFormatInfoStruct
|
||||
{
|
||||
unsigned NumFormats;
|
||||
|
||||
CheatFormatStruct *Formats;
|
||||
};
|
||||
|
||||
// Miscellaneous system/simple commands(power, reset, dip switch toggles, coin insert, etc.)
|
||||
// (for DoSimpleCommand() )
|
||||
@ -302,6 +323,10 @@ typedef struct
|
||||
void (*RemoveReadPatches)(void);
|
||||
uint8 (*MemRead)(uint32 addr);
|
||||
|
||||
#ifdef WANT_NEW_API
|
||||
CheatFormatInfoStruct *CheatFormatInfo;
|
||||
#endif
|
||||
|
||||
bool SaveStateAltersState; // true for bsnes and some libco-style emulators, false otherwise.
|
||||
// Main save state routine, called by the save state code in state.cpp.
|
||||
// When saving, load is set to 0. When loading, load is set to the version field of the save state being loaded.
|
||||
|
@ -28,6 +28,9 @@ void MDFN_DebugPrintReal(const char *file, const int line, const char *format, .
|
||||
void MDFN_LoadGameCheats(void *override);
|
||||
void MDFN_FlushGameCheats(int nosave);
|
||||
|
||||
void MDFN_MidSync(EmulateSpecStruct *espec);
|
||||
void MDFN_MidLineUpdate(EmulateSpecStruct *espec, int y);
|
||||
|
||||
#include "mednafen-driver.h"
|
||||
|
||||
#include "mednafen-endian.h"
|
||||
|
4
mednafen/movie.h
Normal file
4
mednafen/movie.h
Normal file
@ -0,0 +1,4 @@
|
||||
#ifndef _MEDNAFEN_MOVIE_H
|
||||
#define _MEDNAFEN_MOVIE_H
|
||||
|
||||
#endif
|
8
mednafen/pce_fast-09333/Makefile.am
Normal file
8
mednafen/pce_fast-09333/Makefile.am
Normal file
@ -0,0 +1,8 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir)/src/hw_misc -I$(top_srcdir)/src/hw_sound
|
||||
|
||||
noinst_LIBRARIES = libpce_fast.a
|
||||
mednafen_SOURCES = huc6280.cpp pce.cpp vdc.cpp input.cpp huc.cpp hes.cpp pcecd.cpp pcecd_drive.cpp psg.cpp
|
||||
|
||||
libpce_fast_a_SOURCES = $(mednafen_SOURCES)
|
634
mednafen/pce_fast-09333/Makefile.in
Normal file
634
mednafen/pce_fast-09333/Makefile.in
Normal file
@ -0,0 +1,634 @@
|
||||
# Makefile.in generated by automake 1.11.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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@
|
||||
am__make_dryrun = \
|
||||
{ \
|
||||
am__dry=no; \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
|
||||
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
|
||||
*) \
|
||||
for am__flg in $$MAKEFLAGS; do \
|
||||
case $$am__flg in \
|
||||
*=*|--*) ;; \
|
||||
*n*) am__dry=yes; break;; \
|
||||
esac; \
|
||||
done;; \
|
||||
esac; \
|
||||
test $$am__dry = yes; \
|
||||
}
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = src/pce_fast
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \
|
||||
$(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \
|
||||
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \
|
||||
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \
|
||||
$(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \
|
||||
$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \
|
||||
$(top_srcdir)/m4/inttypes-pri.m4 \
|
||||
$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
|
||||
$(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \
|
||||
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
|
||||
$(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \
|
||||
$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \
|
||||
$(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
AM_V_AR = $(am__v_AR_@AM_V@)
|
||||
am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
|
||||
am__v_AR_0 = @echo " AR " $@;
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
libpce_fast_a_AR = $(AR) $(ARFLAGS)
|
||||
libpce_fast_a_LIBADD =
|
||||
am__objects_1 = huc6280.$(OBJEXT) pce.$(OBJEXT) vdc.$(OBJEXT) \
|
||||
input.$(OBJEXT) huc.$(OBJEXT) hes.$(OBJEXT) pcecd.$(OBJEXT) \
|
||||
pcecd_drive.$(OBJEXT) psg.$(OBJEXT)
|
||||
am_libpce_fast_a_OBJECTS = $(am__objects_1)
|
||||
libpce_fast_a_OBJECTS = $(am_libpce_fast_a_OBJECTS)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
AM_V_CXX = $(am__v_CXX_@AM_V@)
|
||||
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
|
||||
am__v_CXX_0 = @echo " CXX " $@;
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
|
||||
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
|
||||
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
|
||||
am__v_CXXLD_0 = @echo " CXXLD " $@;
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
SOURCES = $(libpce_fast_a_SOURCES)
|
||||
DIST_SOURCES = $(libpce_fast_a_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
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@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
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@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
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@
|
||||
SNES_PERF_EXTRA_CXXFLAGS = @SNES_PERF_EXTRA_CXXFLAGS@
|
||||
SNES_PERF_EXTRA_FLAGS = @SNES_PERF_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@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
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@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_srcdir)/src/hw_misc -I$(top_srcdir)/src/hw_sound
|
||||
noinst_LIBRARIES = libpce_fast.a
|
||||
mednafen_SOURCES = huc6280.cpp pce.cpp vdc.cpp input.cpp huc.cpp hes.cpp pcecd.cpp pcecd_drive.cpp psg.cpp
|
||||
libpce_fast_a_SOURCES = $(mednafen_SOURCES)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pce_fast/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/pce_fast/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libpce_fast.a: $(libpce_fast_a_OBJECTS) $(libpce_fast_a_DEPENDENCIES) $(EXTRA_libpce_fast_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libpce_fast.a
|
||||
$(AM_V_AR)$(libpce_fast_a_AR) libpce_fast.a $(libpce_fast_a_OBJECTS) $(libpce_fast_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libpce_fast.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hes.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/huc6280.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pce.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcecd.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcecd_drive.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psg.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vdc.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.cpp.lo:
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
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:
|
249
mednafen/pce_fast-09333/hes.cpp
Normal file
249
mednafen/pce_fast-09333/hes.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "hes.h"
|
||||
#include "huc.h"
|
||||
#include "pcecd.h"
|
||||
#include "../player.h"
|
||||
#include "../endian.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
|
||||
static uint8 mpr_start[8];
|
||||
static uint8 IBP_Bank[0x2000];
|
||||
static uint8 *rom = NULL, *rom_backup = NULL;
|
||||
|
||||
static uint8 CurrentSong;
|
||||
static bool bootstrap;
|
||||
static bool ROMWriteWarningGiven;
|
||||
|
||||
uint8 ReadIBP(unsigned int A)
|
||||
{
|
||||
if(!(A & 0x100))
|
||||
return(IBP_Bank[0x1C00 + (A & 0xF)]);
|
||||
|
||||
if(bootstrap)
|
||||
{
|
||||
memcpy(rom + 0x1FF0, rom_backup + 0x1FF0, 16);
|
||||
bootstrap = false;
|
||||
return(CurrentSong);
|
||||
}
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(HESROMWrite)
|
||||
{
|
||||
rom[A] = V;
|
||||
//printf("%08x: %02x\n", A, V);
|
||||
if(!ROMWriteWarningGiven)
|
||||
{
|
||||
MDFN_printf(_("Warning: HES is writing to physical address %08x. Future warnings of this nature are temporarily disabled for this HES file.\n"), A);
|
||||
ROMWriteWarningGiven = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(HESROMRead)
|
||||
{
|
||||
return(rom[A]);
|
||||
}
|
||||
|
||||
int PCE_HESLoad(const uint8 *buf, uint32 size)
|
||||
{
|
||||
uint32 LoadAddr, LoadSize;
|
||||
uint32 CurPos;
|
||||
uint16 InitAddr;
|
||||
uint8 StartingSong;
|
||||
int TotalSongs;
|
||||
|
||||
InitAddr = MDFN_de16lsb(&buf[0x6]);
|
||||
|
||||
CurPos = 0x10;
|
||||
|
||||
if(!(rom = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!(rom_backup = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(rom, 0, 0x88 * 8192);
|
||||
memset(rom_backup, 0, 0x88 * 8192);
|
||||
|
||||
while(CurPos < (size - 0x10))
|
||||
{
|
||||
LoadSize = MDFN_de32lsb(&buf[CurPos + 0x4]);
|
||||
LoadAddr = MDFN_de32lsb(&buf[CurPos + 0x8]);
|
||||
|
||||
//printf("Size: %08x(%d), Addr: %08x, La: %02x\n", LoadSize, LoadSize, LoadAddr, LoadAddr / 8192);
|
||||
|
||||
CurPos += 0x10;
|
||||
|
||||
if(((uint64)LoadSize + CurPos) > size)
|
||||
{
|
||||
uint32 NewLoadSize = size - CurPos;
|
||||
|
||||
MDFN_printf(_("Warning: HES is trying to load more data than is present in the file(%u attempted, %u left)!\n"), LoadSize, NewLoadSize);
|
||||
|
||||
LoadSize = NewLoadSize;
|
||||
}
|
||||
|
||||
// 0x88 * 8192 = 0x110000
|
||||
if(((uint64)LoadAddr + LoadSize) > 0x110000)
|
||||
{
|
||||
MDFN_printf(_("Warning: HES is trying to load data past boundary.\n"));
|
||||
|
||||
if(LoadAddr >= 0x110000)
|
||||
break;
|
||||
|
||||
LoadSize = 0x110000 - LoadAddr;
|
||||
}
|
||||
|
||||
memcpy(rom + LoadAddr, &buf[CurPos], LoadSize);
|
||||
CurPos += LoadSize;
|
||||
}
|
||||
|
||||
for(int x = 0; x < 8; x++)
|
||||
mpr_start[x] = buf[0x8 + x];
|
||||
|
||||
memcpy(rom_backup, rom, 0x88 * 8192);
|
||||
|
||||
CurrentSong = StartingSong = buf[5];
|
||||
TotalSongs = 256;
|
||||
|
||||
memset(IBP_Bank, 0, 0x2000);
|
||||
|
||||
uint8 *IBP_WR = IBP_Bank + 0x1C00;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
*IBP_WR++ = 0xA9; // LDA (immediate)
|
||||
*IBP_WR++ = mpr_start[i];
|
||||
*IBP_WR++ = 0x53; // TAM
|
||||
*IBP_WR++ = 1 << i;
|
||||
}
|
||||
|
||||
*IBP_WR++ = 0xAD; // LDA(absolute)
|
||||
*IBP_WR++ = 0x00; //
|
||||
*IBP_WR++ = 0x1D; //
|
||||
*IBP_WR++ = 0x20; // JSR
|
||||
*IBP_WR++ = InitAddr; // JSR target LSB
|
||||
*IBP_WR++ = InitAddr >> 8; // JSR target MSB
|
||||
*IBP_WR++ = 0x58; // CLI
|
||||
*IBP_WR++ = 0xFC; // (Mednafen Special)
|
||||
*IBP_WR++ = 0x80; // BRA
|
||||
*IBP_WR++ = 0xFD; // -3
|
||||
|
||||
Player_Init(TotalSongs, "", "", ""); //NULL, NULL, NULL, NULL); //UTF8 **snames);
|
||||
|
||||
for(int x = 0; x < 0x80; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = rom;
|
||||
PCERead[x] = HESROMRead;
|
||||
PCEWrite[x] = HESROMWrite;
|
||||
}
|
||||
|
||||
HuCPUFastMap[0xFF] = IBP_Bank - (0xFF * 8192);
|
||||
|
||||
// FIXME: If a HES rip tries to execute a SCSI command, the CD emulation code will probably crash. Obviously, a HES rip shouldn't do this,
|
||||
// but Mednafen shouldn't crash either. ;)
|
||||
PCE_IsCD = 1;
|
||||
PCE_InitCD();
|
||||
|
||||
ROMWriteWarningGiven = FALSE;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static const uint8 BootROM[16] = { 0xA9, 0xFF, 0x53, 0x01, 0xEA, 0xEA, 0xEA, 0xEA,
|
||||
0xEA, 0xEA, 0xEA, 0x4C, 0x00, 0x1C, 0xF0, 0xFF };
|
||||
void HES_Reset(void)
|
||||
{
|
||||
memcpy(rom, rom_backup, 0x88 * 8192);
|
||||
memcpy(rom + 0x1FF0, BootROM, 16);
|
||||
bootstrap = true;
|
||||
}
|
||||
|
||||
|
||||
void HES_Draw(MDFN_Surface *surface, MDFN_Rect *DisplayRect, int16 *SoundBuf, int32 SoundBufSize)
|
||||
{
|
||||
extern uint16 pce_jp_data[5];
|
||||
static uint8 last = 0;
|
||||
bool needreload = 0;
|
||||
uint8 newset = (pce_jp_data[0] ^ last) & pce_jp_data[0];
|
||||
|
||||
if(newset & 0x20)
|
||||
{
|
||||
CurrentSong++;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if(newset & 0x80)
|
||||
{
|
||||
CurrentSong--;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if(newset & 0x08)
|
||||
needreload = 1;
|
||||
|
||||
if(newset & 0x10)
|
||||
{
|
||||
CurrentSong += 10;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
if(newset & 0x40)
|
||||
{
|
||||
CurrentSong -= 10;
|
||||
needreload = 1;
|
||||
}
|
||||
|
||||
last = pce_jp_data[0];
|
||||
|
||||
if(needreload)
|
||||
PCE_Power();
|
||||
|
||||
Player_Draw(surface, DisplayRect, CurrentSong, SoundBuf, SoundBufSize);
|
||||
}
|
||||
|
||||
void HES_Close(void)
|
||||
{
|
||||
PCECD_Close();
|
||||
|
||||
if(rom)
|
||||
{
|
||||
MDFN_free(rom);
|
||||
rom = NULL;
|
||||
}
|
||||
|
||||
if(rom_backup)
|
||||
{
|
||||
MDFN_free(rom_backup);
|
||||
rom_backup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
11
mednafen/pce_fast-09333/hes.h
Normal file
11
mednafen/pce_fast-09333/hes.h
Normal file
@ -0,0 +1,11 @@
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
uint8 ReadIBP(unsigned int A);
|
||||
void HES_Draw(MDFN_Surface *surface, MDFN_Rect *DisplayRect, int16 *samples, int32 sampcount);
|
||||
|
||||
int PCE_HESLoad(const uint8 *buf, uint32 size) MDFN_COLD;
|
||||
void HES_Reset(void) MDFN_COLD;
|
||||
void HES_Close(void) MDFN_COLD;
|
||||
|
||||
};
|
409
mednafen/pce_fast-09333/huc.cpp
Normal file
409
mednafen/pce_fast-09333/huc.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* Portions of this file Copyright (C) 2004 Ki
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include <errno.h>
|
||||
#include "pcecd.h"
|
||||
#include "arcade_card/arcade_card.h"
|
||||
#include "../md5.h"
|
||||
#include "../file.h"
|
||||
#include "../cdrom/cdromif.h"
|
||||
#include "../mempatcher.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
static const uint8 BRAM_Init_String[8] = { 'H', 'U', 'B', 'M', 0x00, 0x88, 0x10, 0x80 }; //"HUBM\x00\x88\x10\x80";
|
||||
|
||||
ArcadeCard *arcade_card = NULL;
|
||||
|
||||
static uint8 *HuCROM = NULL;
|
||||
|
||||
static bool IsPopulous;
|
||||
bool PCE_IsCD;
|
||||
|
||||
static uint8 SaveRAM[2048];
|
||||
|
||||
static DECLFW(ACPhysWrite)
|
||||
{
|
||||
arcade_card->PhysWrite(A, V);
|
||||
}
|
||||
|
||||
static DECLFR(ACPhysRead)
|
||||
{
|
||||
return(arcade_card->PhysRead(A));
|
||||
}
|
||||
|
||||
static DECLFR(SaveRAMRead)
|
||||
{
|
||||
if((!PCE_IsCD || PCECD_IsBRAMEnabled()) && (A & 8191) < 2048)
|
||||
return(SaveRAM[A & 2047]);
|
||||
else
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(SaveRAMWrite)
|
||||
{
|
||||
if((!PCE_IsCD || PCECD_IsBRAMEnabled()) && (A & 8191) < 2048)
|
||||
SaveRAM[A & 2047] = V;
|
||||
}
|
||||
|
||||
static DECLFR(HuCRead)
|
||||
{
|
||||
return ROMSpace[A];
|
||||
}
|
||||
|
||||
static DECLFW(HuCRAMWrite)
|
||||
{
|
||||
ROMSpace[A] = V;
|
||||
}
|
||||
|
||||
static DECLFW(HuCRAMWriteCDSpecial) // Hyper Dyne Special hack
|
||||
{
|
||||
BaseRAM[0x2000 | (A & 0x1FFF)] = V;
|
||||
ROMSpace[A] = V;
|
||||
}
|
||||
|
||||
static uint8 HuCSF2Latch = 0;
|
||||
|
||||
static DECLFR(HuCSF2Read)
|
||||
{
|
||||
return(HuCROM[(A & 0x7FFFF) + 0x80000 + HuCSF2Latch * 0x80000 ]); // | (HuCSF2Latch << 19) ]);
|
||||
}
|
||||
|
||||
static DECLFW(HuCSF2Write)
|
||||
{
|
||||
if((A & 0x1FFC) == 0x1FF0)
|
||||
{
|
||||
HuCSF2Latch = (A & 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
int HuCLoad(const uint8 *data, uint32 len, uint32 crc32)
|
||||
{
|
||||
uint32 sf2_threshold = 2048 * 1024;
|
||||
uint32 sf2_required_size = 2048 * 1024 + 512 * 1024;
|
||||
uint32 m_len = (len + 8191)&~8191;
|
||||
bool sf2_mapper = FALSE;
|
||||
|
||||
if(m_len >= sf2_threshold)
|
||||
{
|
||||
sf2_mapper = TRUE;
|
||||
|
||||
if(m_len != sf2_required_size)
|
||||
m_len = sf2_required_size;
|
||||
}
|
||||
|
||||
IsPopulous = 0;
|
||||
PCE_IsCD = 0;
|
||||
|
||||
md5_context md5;
|
||||
md5.starts();
|
||||
md5.update(data, len);
|
||||
md5.finish(MDFNGameInfo->MD5);
|
||||
|
||||
MDFN_printf(_("ROM: %dKiB\n"), (len + 1023) / 1024);
|
||||
MDFN_printf(_("ROM CRC32: 0x%04x\n"), crc32);
|
||||
MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||
|
||||
if(!(HuCROM = (uint8 *)MDFN_malloc(m_len, _("HuCard ROM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(HuCROM, 0xFF, m_len);
|
||||
memcpy(HuCROM, data, (m_len < len) ? m_len : len);
|
||||
|
||||
memset(ROMSpace, 0xFF, 0x88 * 8192 + 8192);
|
||||
|
||||
if(m_len == 0x60000)
|
||||
{
|
||||
memcpy(ROMSpace + 0x00 * 8192, HuCROM, 0x20 * 8192);
|
||||
memcpy(ROMSpace + 0x20 * 8192, HuCROM, 0x20 * 8192);
|
||||
memcpy(ROMSpace + 0x40 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
memcpy(ROMSpace + 0x50 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
memcpy(ROMSpace + 0x60 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
memcpy(ROMSpace + 0x70 * 8192, HuCROM + 0x20 * 8192, 0x10 * 8192);
|
||||
}
|
||||
else if(m_len == 0x80000)
|
||||
{
|
||||
memcpy(ROMSpace + 0x00 * 8192, HuCROM, 0x40 * 8192);
|
||||
memcpy(ROMSpace + 0x40 * 8192, HuCROM + 0x20 * 8192, 0x20 * 8192);
|
||||
memcpy(ROMSpace + 0x60 * 8192, HuCROM + 0x20 * 8192, 0x20 * 8192);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ROMSpace + 0x00 * 8192, HuCROM, (m_len < 1024 * 1024) ? m_len : 1024 * 1024);
|
||||
}
|
||||
|
||||
for(int x = 0x00; x < 0x80; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = ROMSpace;
|
||||
PCERead[x] = HuCRead;
|
||||
}
|
||||
|
||||
if(!memcmp(HuCROM + 0x1F26, "POPULOUS", strlen("POPULOUS")))
|
||||
{
|
||||
uint8 *PopRAM = ROMSpace + 0x40 * 8192;
|
||||
FILE *fp;
|
||||
|
||||
memset(PopRAM, 0xFF, 32768);
|
||||
if((fp = (FILE*)fopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, PopRAM, 32768);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
IsPopulous = 1;
|
||||
|
||||
MDFN_printf("Populous\n");
|
||||
|
||||
for(int x = 0x40; x < 0x44; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = &PopRAM[(x & 3) * 8192] - x * 8192;
|
||||
PCERead[x] = HuCRead;
|
||||
PCEWrite[x] = HuCRAMWrite;
|
||||
}
|
||||
MDFNMP_AddRAM(32768, 0x40 * 8192, PopRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
memset(SaveRAM, 0x00, 2048);
|
||||
memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet
|
||||
// in the CD BIOS screen.
|
||||
if((fp = (FILE*)fopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(fp, SaveRAM, 2048);
|
||||
fclose(fp);
|
||||
}
|
||||
PCEWrite[0xF7] = SaveRAMWrite;
|
||||
PCERead[0xF7] = SaveRAMRead;
|
||||
MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
|
||||
}
|
||||
|
||||
// 0x1A558
|
||||
//if(len >= 0x20000 && !memcmp(HuCROM + 0x1A558, "STREET FIGHTER#", strlen("STREET FIGHTER#")))
|
||||
if(sf2_mapper)
|
||||
{
|
||||
for(int x = 0x40; x < 0x80; x++)
|
||||
{
|
||||
// FIXME: PCE_FAST
|
||||
HuCPUFastMap[x] = NULL; // Make sure our reads go through our read function, and not a table lookup
|
||||
PCERead[x] = HuCSF2Read;
|
||||
}
|
||||
PCEWrite[0] = HuCSF2Write;
|
||||
MDFN_printf("Street Fighter 2 Mapper\n");
|
||||
HuCSF2Latch = 0;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
bool IsBRAMUsed(void)
|
||||
{
|
||||
if(memcmp(SaveRAM, BRAM_Init_String, 8)) // HUBM string is modified/missing
|
||||
return(1);
|
||||
|
||||
for(int x = 8; x < 2048; x++)
|
||||
if(SaveRAM[x]) return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int HuCLoadCD(const char *bios_path)
|
||||
{
|
||||
static const FileExtensionSpecStruct KnownBIOSExtensions[] =
|
||||
{
|
||||
{ ".pce", gettext_noop("PC Engine ROM Image") },
|
||||
{ ".bin", gettext_noop("PC Engine ROM Image") },
|
||||
{ ".bios", gettext_noop("BIOS Image") },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
MDFNFILE fp;
|
||||
|
||||
if(!fp.Open(bios_path, KnownBIOSExtensions, _("CD BIOS")))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(ROMSpace, 0xFF, 262144);
|
||||
|
||||
memcpy(ROMSpace, GET_FDATA(fp) + (GET_FSIZE(fp) & 512), ((GET_FSIZE(fp) & ~512) > 262144) ? 262144 : (GET_FSIZE(fp) &~ 512) );
|
||||
|
||||
fp.Close();
|
||||
|
||||
PCE_IsCD = 1;
|
||||
PCE_InitCD();
|
||||
|
||||
md5_context md5;
|
||||
md5.starts();
|
||||
// md5_update(&md5, HuCROM, 262144);
|
||||
|
||||
#if 0
|
||||
int32 track = CDIF_GetFirstTrack();
|
||||
int32 last_track = CDIF_GetLastTrack();
|
||||
bool DTFound = 0;
|
||||
for(; track <= last_track; track++)
|
||||
{
|
||||
CDIF_Track_Format format;
|
||||
|
||||
if(CDIF_GetTrackFormat(track, format) && format == CDIF_FORMAT_MODE1)
|
||||
{
|
||||
DTFound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(DTFound) // Only add the MD5 hash if we were able to find a data track.
|
||||
{
|
||||
uint32 start_sector = CDIF_GetTrackStartPositionLBA(track);
|
||||
uint8 sector_buffer[2048];
|
||||
|
||||
for(int x = 0; x < 128; x++)
|
||||
{
|
||||
memset(sector_buffer, 0, 2048);
|
||||
CDIF_ReadSector(sector_buffer, NULL, start_sector + x, 1);
|
||||
md5.update(sector_buffer, 2048);
|
||||
}
|
||||
}
|
||||
md5.finish(MDFNGameInfo->MD5);
|
||||
MDFN_printf(_("CD MD5(first 256KiB): 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());
|
||||
#endif
|
||||
|
||||
MDFN_printf(_("Arcade Card Emulation: %s\n"), PCE_ACEnabled ? _("Enabled") : _("Disabled"));
|
||||
for(int x = 0; x < 0x40; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = ROMSpace;
|
||||
PCERead[x] = HuCRead;
|
||||
}
|
||||
|
||||
for(int x = 0x68; x < 0x88; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = ROMSpace;
|
||||
PCERead[x] = HuCRead;
|
||||
PCEWrite[x] = HuCRAMWrite;
|
||||
}
|
||||
PCEWrite[0x80] = HuCRAMWriteCDSpecial; // Hyper Dyne Special hack
|
||||
MDFNMP_AddRAM(262144, 0x68 * 8192, ROMSpace + 0x68 * 8192);
|
||||
|
||||
if(PCE_ACEnabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
arcade_card = new ArcadeCard();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
MDFN_PrintError(_("Error creating %s object: %s"), "ArcadeCard", e.what());
|
||||
//Cleanup(); // TODO
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(int x = 0x40; x < 0x44; x++)
|
||||
{
|
||||
HuCPUFastMap[x] = NULL;
|
||||
PCERead[x] = ACPhysRead;
|
||||
PCEWrite[x] = ACPhysWrite;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *srp;
|
||||
|
||||
memset(SaveRAM, 0x00, 2048);
|
||||
memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet
|
||||
// in the CD BIOS screen.
|
||||
|
||||
if((srp = (FILE*)fopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb")))
|
||||
{
|
||||
gzread(srp, SaveRAM, 2048);
|
||||
fclose(srp);
|
||||
}
|
||||
PCEWrite[0xF7] = SaveRAMWrite;
|
||||
PCERead[0xF7] = SaveRAMRead;
|
||||
MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int HuC_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(ROMSpace + 0x40 * 8192, IsPopulous ? 32768 : 0),
|
||||
SFARRAY(SaveRAM, IsPopulous ? 0 : 2048),
|
||||
SFARRAY(ROMSpace + 0x68 * 8192, PCE_IsCD ? 262144 : 0),
|
||||
SFVAR(HuCSF2Latch),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "HuC");
|
||||
|
||||
if(load)
|
||||
HuCSF2Latch &= 0x3;
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
ret &= PCECD_StateAction(sm, load, data_only);
|
||||
|
||||
if(arcade_card)
|
||||
ret &= arcade_card->StateAction(sm, load, data_only);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void HuCClose(void)
|
||||
{
|
||||
if(IsPopulous)
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, ROMSpace + 0x40 * 8192, 32768);
|
||||
}
|
||||
else if(IsBRAMUsed())
|
||||
{
|
||||
MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 0, SaveRAM, 2048);
|
||||
}
|
||||
|
||||
if(arcade_card)
|
||||
{
|
||||
delete arcade_card;
|
||||
arcade_card = NULL;
|
||||
}
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
PCECD_Close();
|
||||
}
|
||||
|
||||
if(HuCROM)
|
||||
{
|
||||
MDFN_free(HuCROM);
|
||||
HuCROM = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HuC_Power(void)
|
||||
{
|
||||
if(PCE_IsCD)
|
||||
memset(ROMSpace + 0x68 * 8192, 0x00, 262144);
|
||||
|
||||
if(arcade_card)
|
||||
arcade_card->Power();
|
||||
}
|
||||
|
||||
};
|
16
mednafen/pce_fast-09333/huc.h
Normal file
16
mednafen/pce_fast-09333/huc.h
Normal file
@ -0,0 +1,16 @@
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
int HuCLoad(const uint8 *data, uint32 len, uint32 crc32) MDFN_COLD;
|
||||
int HuCLoadCD(const char *bios_path) MDFN_COLD;
|
||||
void HuCClose(void) MDFN_COLD;
|
||||
int HuC_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void HuC_Power(void) MDFN_COLD;
|
||||
|
||||
DECLFR(PCE_ACRead);
|
||||
DECLFW(PCE_ACWrite);
|
||||
|
||||
extern bool PCE_IsCD;
|
||||
|
||||
};
|
785
mednafen/pce_fast-09333/huc6280.cpp
Normal file
785
mednafen/pce_fast-09333/huc6280.cpp
Normal file
@ -0,0 +1,785 @@
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "vdc.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
HuC6280 HuCPU;
|
||||
uint8 *HuCPUFastMap[0x100];
|
||||
|
||||
#define HU_PC PC_local //HuCPU.PC
|
||||
#define HU_PC_base HuCPU.PC_base
|
||||
#define HU_A HuCPU.A
|
||||
#define HU_X X_local //HuCPU.X
|
||||
#define HU_Y Y_local //HuCPU.Y
|
||||
#define HU_S HuCPU.S
|
||||
#define HU_P P_local //HuCPU.P
|
||||
#define HU_PI HuCPU.mooPI
|
||||
#define HU_IRQlow HuCPU.IRQlow
|
||||
#define HU_Page1 Page1_local
|
||||
//HuCPU.Page1
|
||||
//Page1_local //HuCPU.Page1
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
#define HU_ZNFlags HuCPU.ZNFlags
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define LOAD_LOCALS_PC() register uint8 *PC_local = HuCPU.PC;
|
||||
#else
|
||||
#define LOAD_LOCALS_PC() register uint32 PC_local /*asm ("edi")*/ = HuCPU.PC; // asm ("edi") = HuCPU.PC;
|
||||
#endif
|
||||
|
||||
#define LOAD_LOCALS() \
|
||||
LOAD_LOCALS_PC(); \
|
||||
uint8 X_local = HuCPU.X; \
|
||||
uint8 Y_local = HuCPU.Y; \
|
||||
uint8 P_local = HuCPU.P; \
|
||||
uint8 *Page1_local = HuCPU.Page1;
|
||||
|
||||
#define SAVE_LOCALS() HuCPU.PC = PC_local; \
|
||||
HuCPU.X = X_local; \
|
||||
HuCPU.Y = Y_local; \
|
||||
HuCPU.P = P_local; \
|
||||
HuCPU.Page1 = Page1_local;
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
#define COMPRESS_FLAGS() HU_P &= ~(N_FLAG | Z_FLAG); HU_P |= ((HU_ZNFlags >> 24) & 0x80) | ((HU_ZNFlags & 0xFF) ? 0 : Z_FLAG);
|
||||
//((((HU_ZNFlags & 0xFF) - 1) >> 8) & Z_FLAG);
|
||||
#define EXPAND_FLAGS() HU_ZNFlags = (HU_P << 24) | ((HU_P & Z_FLAG) ^ Z_FLAG);
|
||||
#else
|
||||
#define COMPRESS_FLAGS()
|
||||
#define EXPAND_FLAGS()
|
||||
#endif
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define GetRealPC() ((unsigned int)(HU_PC - HU_PC_base))
|
||||
#define GetRealPC_EXTERNAL() ((unsigned int)(HuCPU.PC - HuCPU.PC_base))
|
||||
#else
|
||||
#define GetRealPC() (HU_PC)
|
||||
#define GetRealPC_EXTERNAL() (HuCPU.PC)
|
||||
#endif
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define SetPC(value) { unsigned int tempmoo = value; HU_PC = &HuCPU.FastPageR[tempmoo >> 13][tempmoo]; \
|
||||
HU_PC_base = HU_PC - tempmoo; }
|
||||
#define SetPC_EXTERNAL(value) { unsigned int tempmoo = value; \
|
||||
HuCPU.PC = &HuCPU.FastPageR[tempmoo >> 13][tempmoo]; HuCPU.PC_base = HuCPU.PC - tempmoo; }
|
||||
#else
|
||||
#define SetPC(value) { HU_PC = (value); }
|
||||
#define SetPC_EXTERNAL(value) { HuCPU.PC = (value); }
|
||||
#endif
|
||||
|
||||
// Page change PC, GET IT?!
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define FixPC_PC() SetPC(GetRealPC());
|
||||
#else
|
||||
#define FixPC_PC()
|
||||
#endif
|
||||
|
||||
//#define IncPC() { HU_PC++; if(!(GetRealPC() & 0x1FFF)) printf("Bank crossing: %04x\n", GetRealPC()); }
|
||||
//#define IncPC() HU_PC++;
|
||||
#if 0
|
||||
#define IncPC() { HU_PC++; if(!(GetRealPC() & 0x1FFF) && \
|
||||
HuCPU.MPR[(GetRealPC() - 1) >> 13] != (HuCPU.MPR[(GetRealPC()) >> 13] - 1)) \
|
||||
printf("Bank crossing: %04x, %02x, %02x\n", GetRealPC(), HuCPU.MPR[(GetRealPC() - 1) >> 13], \
|
||||
HuCPU.MPR[GetRealPC() >> 13]); }
|
||||
#else
|
||||
#define IncPC() HU_PC++;
|
||||
#endif
|
||||
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
#define RdAtPC() (*HU_PC)
|
||||
//#define RdAtAndIncPC_16() (HU_PC += 2, *(uint16 *)(HU_PC - 2))
|
||||
#else
|
||||
#define RdAtPC() RdOp(HU_PC)
|
||||
//#define RdAtAndIncPC_16() (RdOp(HU_PC++) | ((RdOp(HU_PC++) << 8)))
|
||||
#endif
|
||||
|
||||
// If we change this definition, we'll need to also fix HuC6280_StealCycle() in huc6280.h
|
||||
#define ADDCYC(x) { HuCPU.timestamp += x; }
|
||||
|
||||
static uint8 dummy_bank[8192 + 8192]; // + 8192 for PC-as-ptr safety padding
|
||||
|
||||
#define SET_MPR(arg_i, arg_v) \
|
||||
{ \
|
||||
const unsigned int wmpr = arg_i, wbank = arg_v; \
|
||||
if(wmpr == 1) \
|
||||
{ \
|
||||
if(wbank != 0xF8 || !HuCPUFastMap[wbank]) \
|
||||
printf("Crazy page 1: %02x\n", wbank); \
|
||||
HU_Page1 = HuCPUFastMap[wbank] ? HuCPUFastMap[wbank] + wbank * 8192 : dummy_bank; \
|
||||
} \
|
||||
HuCPU.MPR[wmpr] = wbank; \
|
||||
HuCPU.FastPageR[wmpr] = HuCPUFastMap[wbank] ? (HuCPUFastMap[wbank] + wbank * 8192) - wmpr * 8192 : (dummy_bank - wmpr * 8192); \
|
||||
}
|
||||
|
||||
void HuC6280_SetMPR(int i, int v)
|
||||
{
|
||||
uint8 *Page1_local = HuCPU.Page1;
|
||||
|
||||
SET_MPR(i, v);
|
||||
|
||||
HuCPU.Page1 = Page1_local;
|
||||
}
|
||||
|
||||
|
||||
static void HuC6280_FlushMPRCache(void)
|
||||
{
|
||||
for(int x = 0; x < 9; x++)
|
||||
HuC6280_SetMPR(x, HuCPU.MPR[x & 0x7]);
|
||||
}
|
||||
|
||||
static INLINE uint8 RdMem(unsigned int A)
|
||||
{
|
||||
uint8 wmpr = HuCPU.MPR[A >> 13];
|
||||
return(PCERead[wmpr]((wmpr << 13) | (A & 0x1FFF)));
|
||||
}
|
||||
|
||||
static INLINE uint16 RdMem16(unsigned int A)
|
||||
{
|
||||
return(RdMem(A) | (RdMem(A + 1) << 8));
|
||||
}
|
||||
|
||||
static INLINE void WrMem(unsigned int A, uint8 V)
|
||||
{
|
||||
uint8 wmpr = HuCPU.MPR[A >> 13];
|
||||
PCEWrite[wmpr]((wmpr << 13) | (A & 0x1FFF), V);
|
||||
}
|
||||
|
||||
static INLINE uint8 RdOp(unsigned int A)
|
||||
{
|
||||
return(HuCPU.FastPageR[A >> 13][A]);
|
||||
}
|
||||
|
||||
#define PUSH(V) \
|
||||
{ \
|
||||
HU_Page1[0x100 + HU_S] = V; \
|
||||
HU_S--; \
|
||||
}
|
||||
|
||||
#define PUSH_PC() \
|
||||
{ \
|
||||
unsigned int real_pc = GetRealPC(); \
|
||||
PUSH(real_pc >> 8); \
|
||||
PUSH(real_pc); \
|
||||
}
|
||||
|
||||
#define POP() HU_Page1[0x100 + ++HU_S]
|
||||
|
||||
#define POP_PC() \
|
||||
{ \
|
||||
unsigned int npc; \
|
||||
npc = POP(); \
|
||||
npc |= POP() << 8; \
|
||||
SetPC(npc); \
|
||||
}
|
||||
|
||||
// Hopefully we never RTS to 0x0000. ;)
|
||||
#define POP_PC_AP() \
|
||||
{ \
|
||||
uint32 npc; \
|
||||
npc = POP(); \
|
||||
npc |= POP() << 8; \
|
||||
npc++; \
|
||||
SetPC(npc); \
|
||||
}
|
||||
|
||||
/* Some of these operations will only make sense if you know what the flag
|
||||
constants are. */
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
#define X_ZN(zort) { HU_ZNFlags = (int32)(int8)(uint8)(zort); }
|
||||
#define X_ZN_BIT(opres, argie) { HU_ZNFlags = (opres) | ((argie) << 24); }
|
||||
#else
|
||||
static uint8 ZNTable[256];
|
||||
#define X_ZN(zort) HU_P&=~(Z_FLAG|N_FLAG);HU_P|=ZNTable[zort]
|
||||
#define X_ZN_BIT(opres, argie) { HU_P &= ~(Z_FLAG | N_FLAG); HU_P |= ZNTable[opres] & Z_FLAG; HU_P |= argie & N_FLAG; }
|
||||
#endif
|
||||
|
||||
#define JR(cond) \
|
||||
{ \
|
||||
if(cond) \
|
||||
{ \
|
||||
int32 disp; \
|
||||
disp = 1 + (int8)RdAtPC(); \
|
||||
ADDCYC(2); \
|
||||
HU_PC+=disp; \
|
||||
} \
|
||||
else IncPC(); \
|
||||
}
|
||||
|
||||
#define BRA \
|
||||
{ \
|
||||
int32 disp; \
|
||||
disp = 1 + (int8)RdAtPC(); \
|
||||
HU_PC+=disp; \
|
||||
}
|
||||
|
||||
#define BBRi(bitto) JR(!(x & (1 << bitto)))
|
||||
#define BBSi(bitto) JR(x & (1 << bitto))
|
||||
|
||||
#define ST0 VDC_Write_ST(0, x)
|
||||
#define ST1 VDC_Write_ST(2, x)
|
||||
#define ST2 VDC_Write_ST(3, x)
|
||||
|
||||
#define LDA HU_A=x;X_ZN(HU_A)
|
||||
#define LDX HU_X=x;X_ZN(HU_X)
|
||||
#define LDY HU_Y=x;X_ZN(HU_Y)
|
||||
|
||||
/* All of the freaky arithmetic operations. */
|
||||
#define AND HU_A&=x;X_ZN(HU_A);
|
||||
|
||||
// FIXME:
|
||||
#define BIT HU_P&=~V_FLAG; X_ZN_BIT(x & HU_A, x); HU_P |= x & V_FLAG;
|
||||
#define EOR HU_A^=x;X_ZN(HU_A);
|
||||
#define ORA HU_A|=x;X_ZN(HU_A);
|
||||
|
||||
#define ADC { \
|
||||
if(HU_P & D_FLAG) \
|
||||
{ \
|
||||
uint32 low = (HU_A & 0x0F) + (x & 0x0F) + (HU_P & 1); \
|
||||
uint32 high = (HU_A & 0xF0) + (x & 0xF0); \
|
||||
HU_P &= ~C_FLAG; \
|
||||
if(low > 0x09) { high += 0x10; low += 0x06; } \
|
||||
if(high > 0x90) { high += 0x60; } \
|
||||
HU_P |= (high >> 8) & C_FLAG; \
|
||||
HU_A = (low & 0x0F) | (high & 0xF0); \
|
||||
X_ZN(HU_A); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
uint32 l=HU_A+x+(HU_P&1); \
|
||||
HU_P&=~(C_FLAG|V_FLAG); \
|
||||
HU_P|=((((HU_A^x)&0x80)^0x80) & ((HU_A^l)&0x80))>>1; \
|
||||
HU_P|=(l>>8)&C_FLAG; \
|
||||
HU_A=l; \
|
||||
X_ZN(HU_A); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SBC if(HU_P & D_FLAG) \
|
||||
{ \
|
||||
uint32 c = (HU_P & 1) ^ 1; \
|
||||
uint32 l = HU_A - x - c; \
|
||||
uint32 low = (HU_A & 0x0f) - (x & 0x0f) - c; \
|
||||
uint32 high = (HU_A & 0xf0) - (x & 0xf0); \
|
||||
HU_P &= ~(C_FLAG); \
|
||||
if(low & 0xf0) low -= 0x06; \
|
||||
if(low & 0x80) high -= 0x10; \
|
||||
if(high & 0x0f00) high -= 0x60; \
|
||||
HU_P |= ((l >> 8) & C_FLAG) ^ C_FLAG; \
|
||||
HU_A = (low & 0x0F) | (high & 0xf0); \
|
||||
X_ZN(HU_A); \
|
||||
} else { \
|
||||
uint32 l=HU_A-x-((HU_P&1)^1); \
|
||||
HU_P&=~(C_FLAG|V_FLAG); \
|
||||
HU_P|=((HU_A^l)&(HU_A^x)&0x80)>>1; \
|
||||
HU_P|=((l>>8)&C_FLAG)^C_FLAG; \
|
||||
HU_A=l; \
|
||||
X_ZN(HU_A); \
|
||||
}
|
||||
|
||||
#define CMPL(a1,a2) { \
|
||||
uint32 t=a1-a2; \
|
||||
X_ZN(t&0xFF); \
|
||||
HU_P&=~C_FLAG; \
|
||||
HU_P|=((t>>8)&C_FLAG)^C_FLAG; \
|
||||
}
|
||||
|
||||
#define TAM for(int i = 0; i < 8; i ++) { \
|
||||
if(x & (1 << i)) \
|
||||
{ \
|
||||
SET_MPR(i, HU_A); \
|
||||
} \
|
||||
} SET_MPR(8, HuCPU.MPR[0]);
|
||||
|
||||
#define TMA for(int i = 0; i < 8; i ++) { \
|
||||
if(x & (1 << i)) \
|
||||
HU_A = HuCPU.MPR[i]; \
|
||||
}
|
||||
|
||||
#define CSL
|
||||
#define CSH
|
||||
|
||||
#define RMB(bitto) x &= ~(1 << (bitto & 7))
|
||||
#define SMB(bitto) x |= 1 << (bitto & 7)
|
||||
|
||||
// FIXME
|
||||
#define TSB { HU_P &= ~V_FLAG; X_ZN_BIT(x | HU_A, x); HU_P |= x & V_FLAG; x |= HU_A; }
|
||||
#define TRB { HU_P &= ~V_FLAG; X_ZN_BIT(x & ~HU_A, x); HU_P |= x & V_FLAG; x &= ~HU_A; }
|
||||
#define TST { HU_P &= ~V_FLAG; X_ZN_BIT(x & zoomhack, x); HU_P |= x & V_FLAG; }
|
||||
|
||||
#define CMP CMPL(HU_A,x)
|
||||
#define CPX CMPL(HU_X,x)
|
||||
#define CPY CMPL(HU_Y,x)
|
||||
|
||||
/* The following operations modify the byte being worked on. */
|
||||
#define DEC x--;X_ZN(x)
|
||||
#define INC x++;X_ZN(x)
|
||||
|
||||
#define ASL HU_P&=~C_FLAG;HU_P|=x>>7;x<<=1;X_ZN(x)
|
||||
#define LSR HU_P&=~C_FLAG;HU_P|=x&1;x>>=1;X_ZN(x)
|
||||
|
||||
#define ROL { \
|
||||
uint8 l=x>>7; \
|
||||
x<<=1; \
|
||||
x|=HU_P&C_FLAG; \
|
||||
HU_P&=~C_FLAG; \
|
||||
HU_P|=l; \
|
||||
X_ZN(x); \
|
||||
}
|
||||
#define ROR { \
|
||||
uint8 l=x&1; \
|
||||
x>>=1; \
|
||||
x|=(HU_P&C_FLAG)<<7; \
|
||||
HU_P&=~C_FLAG; \
|
||||
HU_P|=l; \
|
||||
X_ZN(x); \
|
||||
}
|
||||
|
||||
/* Absolute */
|
||||
#define GetAB(target) \
|
||||
{ \
|
||||
target=RdAtPC(); \
|
||||
IncPC(); \
|
||||
target|=RdAtPC()<<8; \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Absolute Indexed(for reads) */
|
||||
#define GetABI(target, i) \
|
||||
{ \
|
||||
unsigned int tmp; \
|
||||
GetAB(tmp); \
|
||||
target=tmp; \
|
||||
target+=i; \
|
||||
}
|
||||
|
||||
/* Zero Page */
|
||||
#define GetZP(target) \
|
||||
{ \
|
||||
target=RdAtPC(); \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Zero Page Indexed */
|
||||
#define GetZPI(target,i) \
|
||||
{ \
|
||||
target=i+RdAtPC(); \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Indirect */
|
||||
#define GetIND(target) \
|
||||
{ \
|
||||
uint8 tmp; \
|
||||
tmp=RdAtPC(); \
|
||||
IncPC(); \
|
||||
target=HU_Page1[tmp]; \
|
||||
tmp++; \
|
||||
target|=HU_Page1[tmp]<<8; \
|
||||
}
|
||||
|
||||
|
||||
/* Indexed Indirect */
|
||||
#define GetIX(target) \
|
||||
{ \
|
||||
uint8 tmp; \
|
||||
tmp=RdAtPC(); \
|
||||
IncPC(); \
|
||||
tmp+=HU_X; \
|
||||
target=HU_Page1[tmp]; \
|
||||
tmp++; \
|
||||
target|=HU_Page1[tmp] <<8; \
|
||||
}
|
||||
|
||||
/* Indirect Indexed(for reads) */
|
||||
#define GetIY(target) \
|
||||
{ \
|
||||
unsigned int rt; \
|
||||
uint8 tmp; \
|
||||
tmp=RdAtPC(); \
|
||||
rt=HU_Page1[tmp]; \
|
||||
tmp++; \
|
||||
rt|=HU_Page1[tmp]<<8; \
|
||||
target = (rt + HU_Y); \
|
||||
IncPC(); \
|
||||
}
|
||||
|
||||
/* Now come the macros to wrap up all of the above stuff addressing mode functions
|
||||
and operation macros. Note that operation macros will always operate(redundant
|
||||
redundant) on the variable "x".
|
||||
*/
|
||||
|
||||
#define RMW_A(op) {uint8 x=HU_A; op; HU_A=x; break; } /* Meh... */
|
||||
#define RMW_AB(op) {unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_ABI(reg,op) {unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_ABX(op) RMW_ABI(HU_X,op)
|
||||
#define RMW_ABY(op) RMW_ABI(HU_Y,op)
|
||||
#define RMW_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x = RdMem(EA); op; WrMem(EA, x); break; }
|
||||
#define RMW_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; WrMem(EA,x); break; }
|
||||
#define RMW_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break; }
|
||||
#define RMW_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; HU_Page1[EA] = x; break;}
|
||||
|
||||
#define LD_IM(op) { uint8 x; x=RdAtPC(); IncPC(); op; break; }
|
||||
#define LD_ZP(op) { uint8 EA; uint8 x; GetZP(EA); x=HU_Page1[EA]; op; break; }
|
||||
#define LD_ZPX(op) { uint8 EA; uint8 x; GetZPI(EA,HU_X); x=HU_Page1[EA]; op; break; }
|
||||
#define LD_ZPY(op) { uint8 EA; uint8 x; GetZPI(EA,HU_Y); x=HU_Page1[EA]; op; break; }
|
||||
#define LD_AB(op) { unsigned int EA; uint8 x; GetAB(EA); x=RdMem(EA); op; break; }
|
||||
#define LD_ABI(reg,op) { unsigned int EA; uint8 x; GetABI(EA,reg); x=RdMem(EA); op; break; }
|
||||
#define LD_ABX(op) LD_ABI(HU_X,op)
|
||||
#define LD_ABY(op) LD_ABI(HU_Y,op)
|
||||
|
||||
#define LD_IND(op) { unsigned int EA; uint8 x; GetIND(EA); x=RdMem(EA); op; break; }
|
||||
#define LD_IX(op) { unsigned int EA; uint8 x; GetIX(EA); x=RdMem(EA); op; break; }
|
||||
#define LD_IY(op) { unsigned int EA; uint8 x; GetIY(EA); x=RdMem(EA); op; break; }
|
||||
|
||||
#define BMT_PREHONK(pork) HuCPU.in_block_move = IBM_##pork;
|
||||
#define BMT_HONKHONK(pork) if(HuCPU.timestamp >= next_user_event) goto GetOutBMT; continue_the_##pork:
|
||||
|
||||
#define BMT_TDD BMT_PREHONK(TDD); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src--; HuCPU.bmt_dest--; BMT_HONKHONK(TDD); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
|
||||
#define BMT_TAI BMT_PREHONK(TAI); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src + HuCPU.bmt_alternate)); HuCPU.bmt_dest++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TAI); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
|
||||
#define BMT_TIA BMT_PREHONK(TIA); {HuCPU.bmt_alternate = 0; do { ADDCYC(6); WrMem(HuCPU.bmt_dest + HuCPU.bmt_alternate, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_alternate ^= 1; BMT_HONKHONK(TIA); HuCPU.bmt_length--; } while(HuCPU.bmt_length); }
|
||||
#define BMT_TII BMT_PREHONK(TII); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; HuCPU.bmt_dest++; BMT_HONKHONK(TII); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
|
||||
#define BMT_TIN BMT_PREHONK(TIN); do { ADDCYC(6); WrMem(HuCPU.bmt_dest, RdMem(HuCPU.bmt_src)); HuCPU.bmt_src++; BMT_HONKHONK(TIN); HuCPU.bmt_length--; } while(HuCPU.bmt_length);
|
||||
|
||||
// Block memory transfer load
|
||||
#define LD_BMT(op) { PUSH(HU_Y); PUSH(HU_A); PUSH(HU_X); GetAB(HuCPU.bmt_src); GetAB(HuCPU.bmt_dest); GetAB(HuCPU.bmt_length); op; HuCPU.in_block_move = 0; HU_X = POP(); HU_A = POP(); HU_Y = POP(); break; }
|
||||
|
||||
#define ST_ZP(r) {uint8 EA; GetZP(EA); HU_Page1[EA] = r; break;}
|
||||
#define ST_ZPX(r) {uint8 EA; GetZPI(EA,HU_X); HU_Page1[EA] = r; break;}
|
||||
#define ST_ZPY(r) {uint8 EA; GetZPI(EA,HU_Y); HU_Page1[EA] = r; break;}
|
||||
#define ST_AB(r) {unsigned int EA; GetAB(EA); WrMem(EA, r); break;}
|
||||
#define ST_ABI(reg,r) {unsigned int EA; GetABI(EA,reg); WrMem(EA,r); break; }
|
||||
#define ST_ABX(r) ST_ABI(HU_X,r)
|
||||
#define ST_ABY(r) ST_ABI(HU_Y,r)
|
||||
|
||||
#define ST_IND(r) {unsigned int EA; GetIND(EA); WrMem(EA,r); break; }
|
||||
#define ST_IX(r) {unsigned int EA; GetIX(EA); WrMem(EA,r); break; }
|
||||
#define ST_IY(r) {unsigned int EA; GetIY(EA); WrMem(EA,r); break; }
|
||||
|
||||
static const uint8 CycTable[256] =
|
||||
{
|
||||
/*0x00*/ 8, 7, 3, 4, 6, 4, 6, 7, 3, 2, 2, 2, 7, 5, 7, 6,
|
||||
/*0x10*/ 2, 7, 7, 4, 6, 4, 6, 7, 2, 5, 2, 2, 7, 5, 7, 6,
|
||||
/*0x20*/ 7, 7, 3, 4, 4, 4, 6, 7, 4, 2, 2, 2, 5, 5, 7, 6,
|
||||
/*0x30*/ 2, 7, 7, 2, 4, 4, 6, 7, 2, 5, 2, 2, 5, 5, 7, 6,
|
||||
/*0x40*/ 7, 7, 3, 4, 8, 4, 6, 7, 3, 2, 2, 2, 4, 5, 7, 6,
|
||||
/*0x50*/ 2, 7, 7, 5, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
|
||||
/*0x60*/ 7, 7, 2, 2, 4, 4, 6, 7, 4, 2, 2, 2, 7, 5, 7, 6,
|
||||
/*0x70*/ 2, 7, 7, 17, 4, 4, 6, 7, 2, 5, 4, 2, 7, 5, 7, 6,
|
||||
|
||||
/*0x80*/ 4, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
|
||||
/*0x90*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
|
||||
/*0xA0*/ 2, 7, 2, 7, 4, 4, 4, 7, 2, 2, 2, 2, 5, 5, 5, 6,
|
||||
/*0xB0*/ 2, 7, 7, 8, 4, 4, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6,
|
||||
/*0xC0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
|
||||
/*0xD0*/ 2, 7, 7, 17, 3, 4, 6, 7, 2, 5, 3, 2, 2, 5, 7, 6,
|
||||
/*0xE0*/ 2, 7, 2, 17, 4, 4, 6, 7, 2, 2, 2, 2, 5, 5, 7, 6,
|
||||
/*0xF0*/ 2, 7, 7, 17, 2, 4, 6, 7, 2, 5, 4, 2, 2, 5, 7, 6,
|
||||
};
|
||||
#if 0
|
||||
static bool WillIRQOccur(void) NO_INLINE;
|
||||
static bool WillIRQOccur(void)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if(HU_IRQlow)
|
||||
{
|
||||
if(!(HU_PI&I_FLAG))
|
||||
{
|
||||
if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
|
||||
ret = true;
|
||||
else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
|
||||
ret = true;
|
||||
else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
void HuC6280_IRQBegin(int w)
|
||||
{
|
||||
HU_IRQlow|=w;
|
||||
}
|
||||
|
||||
void HuC6280_IRQEnd(int w)
|
||||
{
|
||||
HU_IRQlow&=~w;
|
||||
}
|
||||
|
||||
void HuC6280_Reset(void)
|
||||
{
|
||||
HuCPU.timer_next_timestamp = HuCPU.timestamp + 1024;
|
||||
|
||||
HuCPU.timer_load = 0;
|
||||
HuCPU.timer_value = 0;
|
||||
HuCPU.timer_status = 0;
|
||||
HuCPU.in_block_move = 0;
|
||||
|
||||
unsigned int npc;
|
||||
|
||||
HuCPU.IRQMask = HuCPU.IRQMaskDelay = 7;
|
||||
|
||||
HuC6280_SetMPR(0, 0xFF);
|
||||
HuC6280_SetMPR(8, 0xFF);
|
||||
HuC6280_SetMPR(1, 0xF8);
|
||||
|
||||
for(int i = 2; i < 8; i++)
|
||||
HuC6280_SetMPR(i, 0);
|
||||
|
||||
npc = RdMem16(0xFFFE);
|
||||
|
||||
#define PC_local HuCPU.PC
|
||||
SetPC(npc);
|
||||
#undef PC_local
|
||||
|
||||
HuCPU.mooPI = I_FLAG;
|
||||
HuCPU.P = I_FLAG;
|
||||
|
||||
HU_IRQlow = 0;
|
||||
}
|
||||
|
||||
void HuC6280_Init(void)
|
||||
{
|
||||
memset((void *)&HuCPU,0,sizeof(HuCPU));
|
||||
memset(dummy_bank, 0, sizeof(dummy_bank));
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
|
||||
#else
|
||||
for(int x=0; x < 256; x++)
|
||||
if(!x) ZNTable[x]=Z_FLAG;
|
||||
else if (x&0x80) ZNTable[x]=N_FLAG;
|
||||
else ZNTable[x]=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HuC6280_Power(void)
|
||||
{
|
||||
HuCPU.IRQlow = 0;
|
||||
|
||||
HuCPU.A = 0;
|
||||
HuCPU.X = 0;
|
||||
HuCPU.Y = 0;
|
||||
HuCPU.S = 0;
|
||||
HuCPU.P = 0;
|
||||
HuCPU.mooPI = 0;
|
||||
|
||||
#if 0
|
||||
HU_PC = HU_PC_base = NULL;
|
||||
#else
|
||||
HuCPU.PC = 0;
|
||||
#endif
|
||||
|
||||
HuCPU.timestamp = 0;
|
||||
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
HuCPU.MPR[i] = 0;
|
||||
HuCPU.FastPageR[i] = NULL;
|
||||
}
|
||||
HuC6280_Reset();
|
||||
}
|
||||
|
||||
void HuC6280_Run(int32 cycles)
|
||||
{
|
||||
const int32 next_user_event = HuCPU.previous_next_user_event + cycles * pce_overclocked;
|
||||
|
||||
HuCPU.previous_next_user_event = next_user_event;
|
||||
|
||||
LOAD_LOCALS();
|
||||
|
||||
if(HuCPU.timestamp >= next_user_event)
|
||||
return;
|
||||
|
||||
int32 next_event;
|
||||
|
||||
if(HuCPU.in_block_move)
|
||||
{
|
||||
next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
|
||||
|
||||
switch(HuCPU.in_block_move)
|
||||
{
|
||||
case IBM_TIA: goto continue_the_TIA;
|
||||
case IBM_TAI: goto continue_the_TAI;
|
||||
case IBM_TDD: goto continue_the_TDD;
|
||||
case IBM_TII: goto continue_the_TII;
|
||||
case IBM_TIN: goto continue_the_TIN;
|
||||
}
|
||||
}
|
||||
|
||||
while(MDFN_LIKELY(HuCPU.timestamp < next_user_event))
|
||||
{
|
||||
next_event = (next_user_event < HuCPU.timer_next_timestamp) ? next_user_event : HuCPU.timer_next_timestamp;
|
||||
|
||||
while(MDFN_LIKELY(HuCPU.timestamp < next_event))
|
||||
{
|
||||
uint8 b1;
|
||||
|
||||
if(HU_IRQlow)
|
||||
{
|
||||
if(!(HU_PI&I_FLAG))
|
||||
{
|
||||
uint32 tmpa = 0;
|
||||
|
||||
if(HU_IRQlow & MDFN_IQTIMER & HuCPU.IRQMaskDelay)
|
||||
tmpa = 0xFFFA;
|
||||
else if((HU_IRQlow & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay) || ((HU_IRQlow >> 8) & MDFN_IQIRQ1 & HuCPU.IRQMaskDelay))
|
||||
tmpa = 0xFFF8;
|
||||
else if(HU_IRQlow & MDFN_IQIRQ2 & HuCPU.IRQMaskDelay)
|
||||
tmpa = 0xFFF6;
|
||||
|
||||
if(tmpa)
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
ADDCYC(8);
|
||||
PUSH_PC();
|
||||
|
||||
COMPRESS_FLAGS();
|
||||
PUSH((HU_P&~B_FLAG));
|
||||
HU_P |= I_FLAG;
|
||||
HU_P &= ~(T_FLAG | D_FLAG);
|
||||
HU_PI = HU_P;
|
||||
|
||||
npc = RdMem16(tmpa);
|
||||
SetPC(npc);
|
||||
|
||||
if(tmpa == 0xFFF8)
|
||||
HU_IRQlow &= ~0x200;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} // end if(HU_IRQlow)
|
||||
|
||||
//printf("%04x\n", GetRealPC());
|
||||
HU_PI = HU_P;
|
||||
HuCPU.IRQMaskDelay = HuCPU.IRQMask;
|
||||
|
||||
b1 = RdAtPC();
|
||||
|
||||
ADDCYC(CycTable[b1]);
|
||||
|
||||
IncPC();
|
||||
|
||||
switch(b1)
|
||||
{
|
||||
#include "huc6280_ops.inc"
|
||||
}
|
||||
|
||||
#ifndef HUC6280_EXTRA_CRAZY
|
||||
FixPC_PC();
|
||||
#endif
|
||||
} // end while(HuCPU.timestamp < next_event)
|
||||
|
||||
while(HuCPU.timestamp >= HuCPU.timer_next_timestamp)
|
||||
{
|
||||
HuCPU.timer_next_timestamp += 1024 * pce_overclocked;
|
||||
|
||||
if(HuCPU.timer_status)
|
||||
{
|
||||
HuCPU.timer_value --;
|
||||
if(HuCPU.timer_value < 0)
|
||||
{
|
||||
HuCPU.timer_value = HuCPU.timer_load;
|
||||
HuC6280_IRQBegin(MDFN_IQTIMER);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end while(HuCPU.timestamp < next_user_event)
|
||||
|
||||
GetOutBMT:
|
||||
|
||||
SAVE_LOCALS();
|
||||
}
|
||||
|
||||
void HuC6280_ResetTS(void)
|
||||
{
|
||||
HuCPU.timer_next_timestamp -= HuCPU.timestamp;
|
||||
HuCPU.previous_next_user_event -= HuCPU.timestamp;
|
||||
HuCPU.timestamp = 0;
|
||||
}
|
||||
|
||||
int HuC6280_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
uint16 tmp_PC = GetRealPC_EXTERNAL();
|
||||
|
||||
#define P_local HuCPU.P
|
||||
COMPRESS_FLAGS();
|
||||
|
||||
SFORMAT SFCPU[]=
|
||||
{
|
||||
SFVARN(tmp_PC, "PC"),
|
||||
SFVARN(HuCPU.A, "A"),
|
||||
SFVARN(HuCPU.P, "P"),
|
||||
SFVARN(HuCPU.X, "X"),
|
||||
SFVARN(HuCPU.Y, "Y"),
|
||||
SFVARN(HuCPU.S, "S"),
|
||||
SFVARN(HuCPU.mooPI, "PI"),
|
||||
|
||||
SFVARN(HuCPU.IRQMask, "IRQMask"),
|
||||
SFVARN(HuCPU.IRQMaskDelay, "IRQMaskDelay"),
|
||||
SFARRAYN(HuCPU.MPR, 8, "MPR"),
|
||||
SFVARN(HuCPU.timer_status, "timer_status"),
|
||||
SFVARN(HuCPU.timer_value, "timer_value"),
|
||||
SFVARN(HuCPU.timer_load, "timer_load"),
|
||||
|
||||
|
||||
SFVARN(HuCPU.IRQlow, "IRQlow"),
|
||||
SFVARN(HuCPU.in_block_move, "IBM"),
|
||||
SFVARN(HuCPU.bmt_src, "IBM_SRC"),
|
||||
SFVARN(HuCPU.bmt_dest, "IBM_DEST"),
|
||||
SFVARN(HuCPU.bmt_length, "IBM_LENGTH"),
|
||||
SFVARN(HuCPU.bmt_alternate, "IBM_ALTERNATE"),
|
||||
|
||||
SFVARN(HuCPU.timestamp, "timestamp"),
|
||||
SFVARN(HuCPU.timer_next_timestamp, "timer_next_timestamp"),
|
||||
SFVARN(HuCPU.previous_next_user_event, "previous_next_user_event"),
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, SFCPU, "CPU");
|
||||
|
||||
if(load)
|
||||
{
|
||||
// Update MPR cache
|
||||
HuC6280_FlushMPRCache();
|
||||
|
||||
// This must be after the MPR cache is updated:
|
||||
SetPC_EXTERNAL(tmp_PC);
|
||||
}
|
||||
|
||||
EXPAND_FLAGS();
|
||||
#undef P_local
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
};
|
156
mednafen/pce_fast-09333/huc6280.h
Normal file
156
mednafen/pce_fast-09333/huc6280.h
Normal file
@ -0,0 +1,156 @@
|
||||
#ifndef _HuC6280H
|
||||
|
||||
#define HUC6280_CRAZY_VERSION
|
||||
//#define HUC6280_EXTRA_CRAZY
|
||||
|
||||
#define HUC6280_LAZY_FLAGS
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
|
||||
typedef struct __HuC6280
|
||||
{
|
||||
#ifdef HUC6280_CRAZY_VERSION
|
||||
uint8 *PC, *PC_base;
|
||||
#else
|
||||
uint16 PC;
|
||||
#endif
|
||||
|
||||
uint8 A,X,Y,S,P,mooPI;
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
uint32 ZNFlags;
|
||||
#endif
|
||||
uint8 MPR[9]; // 8, + 1 for PC overflow from $ffff to $10000
|
||||
uint8 *FastPageR[9];
|
||||
uint8 *Page1;
|
||||
//uint8 *PAGE1_W;
|
||||
//const uint8 *PAGE1_R;
|
||||
|
||||
uint32 IRQlow; /* Simulated IRQ pin held low(or is it high?).
|
||||
And other junk hooked on for speed reasons.*/
|
||||
int32 timestamp;
|
||||
|
||||
uint8 IRQMask, IRQMaskDelay;
|
||||
uint8 timer_status;
|
||||
int32 timer_value, timer_load;
|
||||
int32 timer_next_timestamp;
|
||||
|
||||
uint32 in_block_move;
|
||||
uint16 bmt_src, bmt_dest, bmt_length;
|
||||
uint32 bmt_alternate;
|
||||
#define IBM_TIA 1
|
||||
#define IBM_TAI 2
|
||||
#define IBM_TDD 3
|
||||
#define IBM_TII 4
|
||||
#define IBM_TIN 5
|
||||
|
||||
int32 previous_next_user_event;
|
||||
} HuC6280;
|
||||
|
||||
void HuC6280_Run(int32 cycles);
|
||||
void HuC6280_ResetTS(void);
|
||||
|
||||
extern HuC6280 HuCPU;
|
||||
extern uint8 *HuCPUFastMap[0x100];
|
||||
|
||||
#define N_FLAG 0x80
|
||||
#define V_FLAG 0x40
|
||||
#define T_FLAG 0x20
|
||||
#define B_FLAG 0x10
|
||||
#define D_FLAG 0x08
|
||||
#define I_FLAG 0x04
|
||||
#define Z_FLAG 0x02
|
||||
#define C_FLAG 0x01
|
||||
|
||||
#define NTSC_CPU 1789772.7272727272727272
|
||||
#define PAL_CPU 1662607.125
|
||||
|
||||
#define MDFN_IQIRQ1 0x002
|
||||
#define MDFN_IQIRQ2 0x001
|
||||
#define MDFN_IQTIMER 0x004
|
||||
#define MDFN_IQRESET 0x020
|
||||
|
||||
void HuC6280_Init(void) MDFN_COLD;
|
||||
void HuC6280_Reset(void) MDFN_COLD;
|
||||
void HuC6280_Power(void) MDFN_COLD;
|
||||
|
||||
void HuC6280_IRQBegin(int w);
|
||||
void HuC6280_IRQEnd(int w);
|
||||
|
||||
int HuC6280_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
static INLINE void HuC6280_StealCycle(void)
|
||||
{
|
||||
HuCPU.timestamp++;
|
||||
}
|
||||
|
||||
static INLINE uint8 HuC6280_TimerRead(unsigned int A)
|
||||
{
|
||||
#if 0
|
||||
return(HuCPU.timer_value | (PCEIODataBuffer & 0x80));
|
||||
#endif
|
||||
|
||||
uint8 tvr = HuCPU.timer_value;
|
||||
|
||||
if(HuCPU.timer_next_timestamp == HuCPU.timestamp)
|
||||
tvr = (tvr - 1) & 0x7F;
|
||||
|
||||
return(tvr | (PCEIODataBuffer & 0x80));
|
||||
}
|
||||
|
||||
static INLINE void HuC6280_TimerWrite(unsigned int A, uint8 V)
|
||||
{
|
||||
switch(A & 1)
|
||||
{
|
||||
case 0: HuCPU.timer_load = (V & 0x7F); break;
|
||||
case 1: if(V & 1) // Enable counter
|
||||
{
|
||||
if(HuCPU.timer_status == 0)
|
||||
{
|
||||
HuCPU.timer_next_timestamp = HuCPU.timestamp + 1024;
|
||||
HuCPU.timer_value = HuCPU.timer_load;
|
||||
}
|
||||
}
|
||||
HuCPU.timer_status = V & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE uint8 HuC6280_IRQStatusRead(unsigned int A)
|
||||
{
|
||||
if(!(A & 2))
|
||||
return(PCEIODataBuffer);
|
||||
|
||||
switch(A & 1)
|
||||
{
|
||||
case 0:
|
||||
HuC6280_IRQEnd(MDFN_IQTIMER);
|
||||
return(HuCPU.IRQMask ^ 0x7);
|
||||
case 1:
|
||||
{
|
||||
int status = 0;
|
||||
if(HuCPU.IRQlow & MDFN_IQIRQ1) status |= 2;
|
||||
if(HuCPU.IRQlow & MDFN_IQIRQ2) status |= 1;
|
||||
if(HuCPU.IRQlow & MDFN_IQTIMER) status |= 4;
|
||||
return(status | (PCEIODataBuffer & ~(1 | 2 | 4)));
|
||||
}
|
||||
}
|
||||
return(PCEIODataBuffer);
|
||||
}
|
||||
|
||||
static INLINE void HuC6280_IRQStatusWrite(unsigned int A, uint8 V)
|
||||
{
|
||||
if(!(A & 2)) return;
|
||||
switch(A & 1)
|
||||
{
|
||||
case 0: HuCPU.IRQMask = (V & 0x7) ^ 0x7; break;
|
||||
case 1: HuC6280_IRQEnd(MDFN_IQTIMER); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#define _HuC6280H
|
||||
#endif
|
635
mednafen/pce_fast-09333/huc6280_ops.inc
Normal file
635
mednafen/pce_fast-09333/huc6280_ops.inc
Normal file
@ -0,0 +1,635 @@
|
||||
/* Mednafen - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define TEST_WEIRD_TFLAG(n) { if(HU_P & T_FLAG) puts("RAWR" n); }
|
||||
|
||||
case 0x00: /* BRK */
|
||||
IncPC();
|
||||
HU_P &= ~T_FLAG;
|
||||
PUSH_PC();
|
||||
|
||||
COMPRESS_FLAGS();
|
||||
PUSH(HU_P|B_FLAG);
|
||||
HU_P|=I_FLAG;
|
||||
HU_P &= ~D_FLAG;
|
||||
HU_PI|=I_FLAG;
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
npc=RdOp(0xFFF6);
|
||||
npc|=RdOp(0xFFF7)<<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x40: /* RTI */
|
||||
HU_P = POP();
|
||||
EXPAND_FLAGS();
|
||||
/* HU_PI=HU_P; This is probably incorrect, so it's commented out. */
|
||||
HU_PI = HU_P;
|
||||
POP_PC();
|
||||
|
||||
// T-flag handling here:
|
||||
TEST_WEIRD_TFLAG("RTI");
|
||||
break;
|
||||
|
||||
case 0x60: /* RTS */
|
||||
POP_PC_AP();
|
||||
break;
|
||||
|
||||
case 0x48: /* PHA */
|
||||
PUSH(HU_A);
|
||||
break;
|
||||
|
||||
case 0x08: /* PHP */
|
||||
HU_P &= ~T_FLAG;
|
||||
COMPRESS_FLAGS();
|
||||
PUSH(HU_P|B_FLAG);
|
||||
break;
|
||||
|
||||
case 0xDA: // PHX 65C02
|
||||
PUSH(HU_X);
|
||||
break;
|
||||
|
||||
case 0x5A: // PHY 65C02
|
||||
PUSH(HU_Y);
|
||||
break;
|
||||
|
||||
case 0x68: /* PLA */
|
||||
HU_A = POP();
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0xFA: // PLX 65C02
|
||||
HU_X = POP();
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
|
||||
case 0x7A: // PLY 65C02
|
||||
HU_Y = POP();
|
||||
X_ZN(HU_Y);
|
||||
break;
|
||||
|
||||
case 0x28: /* PLP */
|
||||
HU_P = POP();
|
||||
EXPAND_FLAGS();
|
||||
|
||||
// T-flag handling here:
|
||||
TEST_WEIRD_TFLAG("PLP");
|
||||
break;
|
||||
|
||||
case 0x4C:
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
npc = RdAtPC();
|
||||
IncPC();
|
||||
npc|=RdAtPC() << 8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break; /* JMP ABSOLUTE */
|
||||
|
||||
case 0x6C: /* JMP Indirect */
|
||||
{
|
||||
uint32 tmp;
|
||||
unsigned int npc;
|
||||
|
||||
GetAB(tmp);
|
||||
|
||||
npc=RdMem(tmp);
|
||||
npc|=RdMem(tmp + 1)<<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7C: // JMP Indirect X - 65C02
|
||||
{
|
||||
uint32 tmp;
|
||||
unsigned int npc;
|
||||
|
||||
GetAB(tmp);
|
||||
tmp += HU_X;
|
||||
|
||||
npc=RdMem(tmp);
|
||||
npc|=RdMem(tmp + 1)<<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x20: /* JSR */
|
||||
{
|
||||
unsigned int npc;
|
||||
|
||||
npc = RdAtPC();
|
||||
|
||||
IncPC();
|
||||
PUSH_PC();
|
||||
|
||||
npc |= RdAtPC() <<8;
|
||||
|
||||
SetPC(npc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAA: /* TAX */
|
||||
HU_X=HU_A;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0x8A: /* TXA */
|
||||
HU_A=HU_X;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0xA8: /* TAY */
|
||||
HU_Y=HU_A;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
case 0x98: /* TYA */
|
||||
HU_A=HU_Y;
|
||||
X_ZN(HU_A);
|
||||
break;
|
||||
|
||||
case 0xBA: /* TSX */
|
||||
HU_X=HU_S;
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
case 0x9A: /* TXS */
|
||||
HU_S=HU_X;
|
||||
break;
|
||||
|
||||
case 0xCA: /* DEX */
|
||||
HU_X--;
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
case 0x88: /* DEY */
|
||||
HU_Y--;
|
||||
X_ZN(HU_Y);
|
||||
break;
|
||||
|
||||
case 0xE8: /* INX */
|
||||
HU_X++;
|
||||
X_ZN(HU_X);
|
||||
break;
|
||||
case 0xC8: /* INY */
|
||||
HU_Y++;
|
||||
X_ZN(HU_Y);
|
||||
break;
|
||||
|
||||
case 0x54: CSL; break;
|
||||
case 0xD4: CSH; break;
|
||||
|
||||
case 0x62: HU_A = 0; break; // CLA
|
||||
case 0x82: HU_X = 0; break; // CLX
|
||||
case 0xC2: HU_Y = 0; break; // CLY
|
||||
|
||||
case 0x18: /* CLC */
|
||||
HU_P&=~C_FLAG;
|
||||
break;
|
||||
|
||||
case 0xD8: /* CLD */
|
||||
HU_P&=~D_FLAG;
|
||||
break;
|
||||
|
||||
case 0x58: /* CLI */
|
||||
if((HU_P & I_FLAG) && (HU_IRQlow & MDFN_IQIRQ1))
|
||||
{
|
||||
uint8 moo_op = RdAtPC();
|
||||
if((moo_op == 0xAC || moo_op == 0xAD || moo_op == 0xAE) &&
|
||||
((RdOp(GetRealPC() + 1) & 0x3) == 0) && ((RdOp(GetRealPC() + 2) & 0xFC) == 0))
|
||||
{
|
||||
HU_IRQlow |= 0x200;
|
||||
//puts("CLI/LDA madness!");
|
||||
}
|
||||
}
|
||||
HU_P&=~I_FLAG;
|
||||
break;
|
||||
|
||||
case 0xB8: /* CLV */
|
||||
HU_P&=~V_FLAG;
|
||||
break;
|
||||
|
||||
case 0x38: /* SEC */
|
||||
HU_P|=C_FLAG;
|
||||
break;
|
||||
|
||||
case 0xF8: /* SED */
|
||||
HU_P|=D_FLAG;
|
||||
break;
|
||||
|
||||
case 0x78: /* SEI */
|
||||
HU_P|=I_FLAG;
|
||||
break;
|
||||
|
||||
case 0xEA: /* NOP */
|
||||
break;
|
||||
|
||||
case 0x0A: RMW_A(ASL);
|
||||
case 0x06: RMW_ZP(ASL);
|
||||
case 0x16: RMW_ZPX(ASL);
|
||||
case 0x0E: RMW_AB(ASL);
|
||||
case 0x1E: RMW_ABX(ASL);
|
||||
|
||||
case 0x3A: RMW_A(DEC);
|
||||
case 0xC6: RMW_ZP(DEC);
|
||||
case 0xD6: RMW_ZPX(DEC);
|
||||
case 0xCE: RMW_AB(DEC);
|
||||
case 0xDE: RMW_ABX(DEC);
|
||||
|
||||
case 0x1A: RMW_A(INC); // 65C02
|
||||
case 0xE6: RMW_ZP(INC);
|
||||
case 0xF6: RMW_ZPX(INC);
|
||||
case 0xEE: RMW_AB(INC);
|
||||
case 0xFE: RMW_ABX(INC);
|
||||
|
||||
case 0x4A: RMW_A(LSR);
|
||||
case 0x46: RMW_ZP(LSR);
|
||||
case 0x56: RMW_ZPX(LSR);
|
||||
case 0x4E: RMW_AB(LSR);
|
||||
case 0x5E: RMW_ABX(LSR);
|
||||
|
||||
case 0x2A: RMW_A(ROL);
|
||||
case 0x26: RMW_ZP(ROL);
|
||||
case 0x36: RMW_ZPX(ROL);
|
||||
case 0x2E: RMW_AB(ROL);
|
||||
case 0x3E: RMW_ABX(ROL);
|
||||
|
||||
case 0x6A: RMW_A(ROR);
|
||||
case 0x66: RMW_ZP(ROR);
|
||||
case 0x76: RMW_ZPX(ROR);
|
||||
case 0x6E: RMW_AB(ROR);
|
||||
case 0x7E: RMW_ABX(ROR);
|
||||
|
||||
case 0x69: LD_IM(ADC);
|
||||
case 0x65: LD_ZP(ADC);
|
||||
case 0x75: LD_ZPX(ADC);
|
||||
case 0x6D: LD_AB(ADC);
|
||||
case 0x7D: LD_ABX(ADC);
|
||||
case 0x79: LD_ABY(ADC);
|
||||
case 0x72: LD_IND(ADC);
|
||||
case 0x61: LD_IX(ADC);
|
||||
case 0x71: LD_IY(ADC);
|
||||
|
||||
case 0x29: LD_IM(AND);
|
||||
case 0x25: LD_ZP(AND);
|
||||
case 0x35: LD_ZPX(AND);
|
||||
case 0x2D: LD_AB(AND);
|
||||
case 0x3D: LD_ABX(AND);
|
||||
case 0x39: LD_ABY(AND);
|
||||
case 0x32: LD_IND(AND);
|
||||
case 0x21: LD_IX(AND);
|
||||
case 0x31: LD_IY(AND);
|
||||
|
||||
case 0x89: LD_IM(BIT);
|
||||
case 0x24: LD_ZP(BIT);
|
||||
case 0x34: LD_ZPX(BIT);
|
||||
case 0x2C: LD_AB(BIT);
|
||||
case 0x3C: LD_ABX(BIT);
|
||||
|
||||
case 0xC9: LD_IM(CMP);
|
||||
case 0xC5: LD_ZP(CMP);
|
||||
case 0xD5: LD_ZPX(CMP);
|
||||
case 0xCD: LD_AB(CMP);
|
||||
case 0xDD: LD_ABX(CMP);
|
||||
case 0xD9: LD_ABY(CMP);
|
||||
case 0xD2: LD_IND(CMP);
|
||||
case 0xC1: LD_IX(CMP);
|
||||
case 0xD1: LD_IY(CMP);
|
||||
|
||||
case 0xE0: LD_IM(CPX);
|
||||
case 0xE4: LD_ZP(CPX);
|
||||
case 0xEC: LD_AB(CPX);
|
||||
|
||||
case 0xC0: LD_IM(CPY);
|
||||
case 0xC4: LD_ZP(CPY);
|
||||
case 0xCC: LD_AB(CPY);
|
||||
|
||||
case 0x49: LD_IM(EOR);
|
||||
case 0x45: LD_ZP(EOR);
|
||||
case 0x55: LD_ZPX(EOR);
|
||||
case 0x4D: LD_AB(EOR);
|
||||
case 0x5D: LD_ABX(EOR);
|
||||
case 0x59: LD_ABY(EOR);
|
||||
case 0x52: LD_IND(EOR);
|
||||
case 0x41: LD_IX(EOR);
|
||||
case 0x51: LD_IY(EOR);
|
||||
|
||||
case 0xA9: LD_IM(LDA);
|
||||
case 0xA5: LD_ZP(LDA);
|
||||
case 0xB5: LD_ZPX(LDA);
|
||||
case 0xAD: LD_AB(LDA);
|
||||
case 0xBD: LD_ABX(LDA);
|
||||
case 0xB9: LD_ABY(LDA);
|
||||
case 0xB2: LD_IND(LDA);
|
||||
case 0xA1: LD_IX(LDA);
|
||||
case 0xB1: LD_IY(LDA);
|
||||
|
||||
case 0xA2: LD_IM(LDX);
|
||||
case 0xA6: LD_ZP(LDX);
|
||||
case 0xB6: LD_ZPY(LDX);
|
||||
case 0xAE: LD_AB(LDX);
|
||||
case 0xBE: LD_ABY(LDX);
|
||||
|
||||
case 0xA0: LD_IM(LDY);
|
||||
case 0xA4: LD_ZP(LDY);
|
||||
case 0xB4: LD_ZPX(LDY);
|
||||
case 0xAC: LD_AB(LDY);
|
||||
case 0xBC: LD_ABX(LDY);
|
||||
|
||||
case 0x09: LD_IM(ORA);
|
||||
case 0x05: LD_ZP(ORA);
|
||||
case 0x15: LD_ZPX(ORA);
|
||||
case 0x0D: LD_AB(ORA);
|
||||
case 0x1D: LD_ABX(ORA);
|
||||
case 0x19: LD_ABY(ORA);
|
||||
case 0x12: LD_IND(ORA);
|
||||
case 0x01: LD_IX(ORA);
|
||||
case 0x11: LD_IY(ORA);
|
||||
|
||||
case 0xE9: LD_IM(SBC);
|
||||
case 0xE5: LD_ZP(SBC);
|
||||
case 0xF5: LD_ZPX(SBC);
|
||||
case 0xED: LD_AB(SBC);
|
||||
case 0xFD: LD_ABX(SBC);
|
||||
case 0xF9: LD_ABY(SBC);
|
||||
case 0xF2: LD_IND(SBC);
|
||||
case 0xE1: LD_IX(SBC);
|
||||
case 0xF1: LD_IY(SBC);
|
||||
|
||||
case 0x85: ST_ZP(HU_A);
|
||||
case 0x95: ST_ZPX(HU_A);
|
||||
case 0x8D: ST_AB(HU_A);
|
||||
case 0x9D: ST_ABX(HU_A);
|
||||
case 0x99: ST_ABY(HU_A);
|
||||
case 0x92: ST_IND(HU_A);
|
||||
case 0x81: ST_IX(HU_A);
|
||||
case 0x91: ST_IY(HU_A);
|
||||
|
||||
case 0x86: ST_ZP(HU_X);
|
||||
case 0x96: ST_ZPY(HU_X);
|
||||
case 0x8E: ST_AB(HU_X);
|
||||
|
||||
case 0x84: ST_ZP(HU_Y);
|
||||
case 0x94: ST_ZPX(HU_Y);
|
||||
case 0x8C: ST_AB(HU_Y);
|
||||
|
||||
/* BBRi */
|
||||
case 0x0F: LD_ZP(BBRi(0));
|
||||
case 0x1F: LD_ZP(BBRi(1));
|
||||
case 0x2F: LD_ZP(BBRi(2));
|
||||
case 0x3F: LD_ZP(BBRi(3));
|
||||
case 0x4F: LD_ZP(BBRi(4));
|
||||
case 0x5F: LD_ZP(BBRi(5));
|
||||
case 0x6F: LD_ZP(BBRi(6));
|
||||
case 0x7F: LD_ZP(BBRi(7));
|
||||
|
||||
/* BBSi */
|
||||
case 0x8F: LD_ZP(BBSi(0));
|
||||
case 0x9F: LD_ZP(BBSi(1));
|
||||
case 0xAF: LD_ZP(BBSi(2));
|
||||
case 0xBF: LD_ZP(BBSi(3));
|
||||
case 0xCF: LD_ZP(BBSi(4));
|
||||
case 0xDF: LD_ZP(BBSi(5));
|
||||
case 0xEF: LD_ZP(BBSi(6));
|
||||
case 0xFF: LD_ZP(BBSi(7));
|
||||
|
||||
/* BRA */
|
||||
case 0x80: BRA; break;
|
||||
|
||||
/* BSR */
|
||||
case 0x44:
|
||||
{
|
||||
PUSH_PC();
|
||||
BRA;
|
||||
}
|
||||
break;
|
||||
|
||||
/* BCC */
|
||||
case 0x90: JR(!(HU_P&C_FLAG)); break;
|
||||
|
||||
/* BCS */
|
||||
case 0xB0: JR(HU_P&C_FLAG); break;
|
||||
|
||||
/* BVC */
|
||||
case 0x50: JR(!(HU_P&V_FLAG)); break;
|
||||
|
||||
/* BVS */
|
||||
case 0x70: JR(HU_P&V_FLAG); break;
|
||||
|
||||
#ifdef HUC6280_LAZY_FLAGS
|
||||
|
||||
/* BEQ */
|
||||
case 0xF0: JR(!(HU_ZNFlags & 0xFF)); break;
|
||||
|
||||
/* BNE */
|
||||
case 0xD0: JR((HU_ZNFlags & 0xFF)); break;
|
||||
|
||||
/* BMI */
|
||||
case 0x30: JR((HU_ZNFlags & 0x80000000)); break;
|
||||
|
||||
/* BPL */
|
||||
case 0x10: JR(!(HU_ZNFlags & 0x80000000)); break;
|
||||
|
||||
#else
|
||||
|
||||
/* BEQ */
|
||||
case 0xF0: JR(HU_P&Z_FLAG); break;
|
||||
|
||||
/* BNE */
|
||||
case 0xD0: JR(!(HU_P&Z_FLAG)); break;
|
||||
|
||||
/* BMI */
|
||||
case 0x30: JR(HU_P&N_FLAG); break;
|
||||
|
||||
/* BPL */
|
||||
case 0x10: JR(!(HU_P&N_FLAG)); break;
|
||||
|
||||
#endif
|
||||
|
||||
// RMB 65SC02
|
||||
case 0x07: RMW_ZP(RMB(0));
|
||||
case 0x17: RMW_ZP(RMB(1));
|
||||
case 0x27: RMW_ZP(RMB(2));
|
||||
case 0x37: RMW_ZP(RMB(3));
|
||||
case 0x47: RMW_ZP(RMB(4));
|
||||
case 0x57: RMW_ZP(RMB(5));
|
||||
case 0x67: RMW_ZP(RMB(6));
|
||||
case 0x77: RMW_ZP(RMB(7));
|
||||
|
||||
// SMB 65SC02
|
||||
case 0x87: RMW_ZP(SMB(0));
|
||||
case 0x97: RMW_ZP(SMB(1));
|
||||
case 0xa7: RMW_ZP(SMB(2));
|
||||
case 0xb7: RMW_ZP(SMB(3));
|
||||
case 0xc7: RMW_ZP(SMB(4));
|
||||
case 0xd7: RMW_ZP(SMB(5));
|
||||
case 0xe7: RMW_ZP(SMB(6));
|
||||
case 0xf7: RMW_ZP(SMB(7));
|
||||
|
||||
// STZ 65C02
|
||||
case 0x64: ST_ZP(0);
|
||||
case 0x74: ST_ZPX(0);
|
||||
case 0x9C: ST_AB(0);
|
||||
case 0x9E: ST_ABX(0);
|
||||
|
||||
// TRB 65SC02
|
||||
case 0x14: RMW_ZP(TRB);
|
||||
case 0x1C: RMW_AB(TRB);
|
||||
|
||||
// TSB 65SC02
|
||||
case 0x04: RMW_ZP(TSB);
|
||||
case 0x0C: RMW_AB(TSB);
|
||||
|
||||
// TST
|
||||
case 0x83: { uint8 zoomhack=RdAtPC(); IncPC(); LD_ZP(TST); }
|
||||
case 0xA3: { uint8 zoomhack=RdAtPC(); IncPC(); LD_ZPX(TST); }
|
||||
case 0x93: { uint8 zoomhack=RdAtPC(); IncPC(); LD_AB(TST); }
|
||||
case 0xB3: { uint8 zoomhack=RdAtPC(); IncPC(); LD_ABX(TST); }
|
||||
|
||||
case 0x22: // SAX(amaphone!)
|
||||
{
|
||||
uint8 tmp = HU_X;
|
||||
HU_X = HU_A;
|
||||
HU_A = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x42: // SAY(what?)
|
||||
{
|
||||
uint8 tmp = HU_Y;
|
||||
HU_Y = HU_A;
|
||||
HU_A = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02: // SXY
|
||||
{
|
||||
uint8 tmp = HU_X;
|
||||
HU_X = HU_Y;
|
||||
HU_Y = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x73: // TII
|
||||
LD_BMT(BMT_TII);
|
||||
|
||||
case 0xC3: // TDD
|
||||
LD_BMT(BMT_TDD);
|
||||
|
||||
case 0xD3: // TIN
|
||||
LD_BMT(BMT_TIN);
|
||||
|
||||
case 0xE3: // TIA
|
||||
LD_BMT(BMT_TIA);
|
||||
|
||||
case 0xF3: // TAI
|
||||
LD_BMT(BMT_TAI);
|
||||
|
||||
case 0x43: // TMAi
|
||||
LD_IM(TMA);
|
||||
|
||||
case 0x53: // TAMi
|
||||
LD_IM(TAM);
|
||||
|
||||
case 0x03: // ST0
|
||||
LD_IM(ST0);
|
||||
|
||||
case 0x13: // ST1
|
||||
LD_IM(ST1);
|
||||
|
||||
case 0x23: // ST2
|
||||
LD_IM(ST2);
|
||||
|
||||
|
||||
case 0xF4: /* SET */
|
||||
{
|
||||
// AND, EOR, ORA, ADC
|
||||
uint8 Abackup = HU_A;
|
||||
|
||||
ADDCYC(3);
|
||||
HU_A = HU_Page1[HU_X]; //PAGE1_R[HU_X];
|
||||
|
||||
switch(RdAtPC())
|
||||
{
|
||||
default: //puts("Bad SET");
|
||||
break;
|
||||
|
||||
case 0x69: IncPC(); LD_IM(ADC);
|
||||
case 0x65: IncPC(); LD_ZP(ADC);
|
||||
case 0x75: IncPC(); LD_ZPX(ADC);
|
||||
case 0x6D: IncPC(); LD_AB(ADC);
|
||||
case 0x7D: IncPC(); LD_ABX(ADC);
|
||||
case 0x79: IncPC(); LD_ABY(ADC);
|
||||
case 0x72: IncPC(); LD_IND(ADC);
|
||||
case 0x61: IncPC(); LD_IX(ADC);
|
||||
case 0x71: IncPC(); LD_IY(ADC);
|
||||
|
||||
case 0x29: IncPC(); LD_IM(AND);
|
||||
case 0x25: IncPC(); LD_ZP(AND);
|
||||
case 0x35: IncPC(); LD_ZPX(AND);
|
||||
case 0x2D: IncPC(); LD_AB(AND);
|
||||
case 0x3D: IncPC(); LD_ABX(AND);
|
||||
case 0x39: IncPC(); LD_ABY(AND);
|
||||
case 0x32: IncPC(); LD_IND(AND);
|
||||
case 0x21: IncPC(); LD_IX(AND);
|
||||
case 0x31: IncPC(); LD_IY(AND);
|
||||
|
||||
case 0x49: IncPC(); LD_IM(EOR);
|
||||
case 0x45: IncPC(); LD_ZP(EOR);
|
||||
case 0x55: IncPC(); LD_ZPX(EOR);
|
||||
case 0x4D: IncPC(); LD_AB(EOR);
|
||||
case 0x5D: IncPC(); LD_ABX(EOR);
|
||||
case 0x59: IncPC(); LD_ABY(EOR);
|
||||
case 0x52: IncPC(); LD_IND(EOR);
|
||||
case 0x41: IncPC(); LD_IX(EOR);
|
||||
case 0x51: IncPC(); LD_IY(EOR);
|
||||
|
||||
case 0x09: IncPC(); LD_IM(ORA);
|
||||
case 0x05: IncPC(); LD_ZP(ORA);
|
||||
case 0x15: IncPC(); LD_ZPX(ORA);
|
||||
case 0x0D: IncPC(); LD_AB(ORA);
|
||||
case 0x1D: IncPC(); LD_ABX(ORA);
|
||||
case 0x19: IncPC(); LD_ABY(ORA);
|
||||
case 0x12: IncPC(); LD_IND(ORA);
|
||||
case 0x01: IncPC(); LD_IX(ORA);
|
||||
case 0x11: IncPC(); LD_IY(ORA);
|
||||
}
|
||||
HU_Page1[HU_X] /*PAGE1_W[HU_X]*/ = HU_A;
|
||||
HU_A = Abackup;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFC:
|
||||
{
|
||||
int32 ec_tmp;
|
||||
ec_tmp = next_event - HuCPU.timestamp;
|
||||
if(ec_tmp > 0)
|
||||
{
|
||||
ADDCYC(ec_tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: //MDFN_printf("Bad %02x at $%04x\n", b1, GetRealPC());
|
||||
break;
|
338
mednafen/pce_fast-09333/input.cpp
Normal file
338
mednafen/pce_fast-09333/input.cpp
Normal file
@ -0,0 +1,338 @@
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include "input.h"
|
||||
#include "huc.h"
|
||||
#include "../movie.h"
|
||||
#include "../mednafen-endian.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
static int InputTypes[5];
|
||||
static uint8 *data_ptr[5];
|
||||
|
||||
static bool AVPad6Which[5]; // Lower(8 buttons) or higher(4 buttons).
|
||||
static bool AVPad6Enabled[5];
|
||||
|
||||
uint16 pce_jp_data[5];
|
||||
|
||||
static int64 mouse_last_meow[5];
|
||||
|
||||
static int32 mouse_x[5], mouse_y[5];
|
||||
static uint16 mouse_rel[5];
|
||||
|
||||
uint8 pce_mouse_button[5];
|
||||
uint8 mouse_index[5];
|
||||
|
||||
static uint8 sel;
|
||||
static uint8 read_index = 0;
|
||||
|
||||
static void SyncSettings(void);
|
||||
|
||||
void PCEINPUT_SettingChanged(const char *name)
|
||||
{
|
||||
SyncSettings();
|
||||
}
|
||||
|
||||
void PCEINPUT_Init(void)
|
||||
{
|
||||
SyncSettings();
|
||||
}
|
||||
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr)
|
||||
{
|
||||
assert(port < 5);
|
||||
|
||||
if(!strcasecmp(type, "gamepad"))
|
||||
InputTypes[port] = 1;
|
||||
else if(!strcasecmp(type, "mouse"))
|
||||
InputTypes[port] = 2;
|
||||
else
|
||||
InputTypes[port] = 0;
|
||||
data_ptr[port] = (uint8 *)ptr;
|
||||
}
|
||||
|
||||
void INPUT_Frame(void)
|
||||
{
|
||||
for(int x = 0; x < 5; x++)
|
||||
{
|
||||
if(InputTypes[x] == 1)
|
||||
{
|
||||
uint16 new_data = data_ptr[x][0] | (data_ptr[x][1] << 8);
|
||||
|
||||
if((new_data & 0x1000) && !(pce_jp_data[x] & 0x1000))
|
||||
{
|
||||
AVPad6Enabled[x] = !AVPad6Enabled[x];
|
||||
MDFN_DispMessage("%d-button mode selected for pad %d", AVPad6Enabled[x] ? 6 : 2, x + 1);
|
||||
}
|
||||
|
||||
pce_jp_data[x] = new_data;
|
||||
}
|
||||
else if(InputTypes[x] == 2)
|
||||
{
|
||||
mouse_x[x] += (int32)MDFN_de32lsb(data_ptr[x] + 0);
|
||||
mouse_y[x] += (int32)MDFN_de32lsb(data_ptr[x] + 4);
|
||||
pce_mouse_button[x] = *(uint8 *)(data_ptr[x] + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void INPUT_FixTS(void)
|
||||
{
|
||||
for(int x = 0; x < 5; x++)
|
||||
{
|
||||
if(InputTypes[x] == 2)
|
||||
mouse_last_meow[x] -= HuCPU.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE bool CheckLM(int n)
|
||||
{
|
||||
if((int64)HuCPU.timestamp - mouse_last_meow[n] > 10000)
|
||||
{
|
||||
mouse_last_meow[n] = HuCPU.timestamp;
|
||||
|
||||
int32 rel_x = (int32)((0-mouse_x[n]));
|
||||
int32 rel_y = (int32)((0-mouse_y[n]));
|
||||
|
||||
if(rel_x < -127) rel_x = -127;
|
||||
if(rel_x > 127) rel_x = 127;
|
||||
if(rel_y < -127) rel_y = -127;
|
||||
if(rel_y > 127) rel_y = 127;
|
||||
|
||||
mouse_rel[n] = ((rel_x & 0xF0) >> 4) | ((rel_x & 0x0F) << 4);
|
||||
mouse_rel[n] |= (((rel_y & 0xF0) >> 4) | ((rel_y & 0x0F) << 4)) << 8;
|
||||
|
||||
mouse_x[n] += (int32)(rel_x);
|
||||
mouse_y[n] += (int32)(rel_y);
|
||||
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint8 INPUT_Read(unsigned int A)
|
||||
{
|
||||
uint8 ret = 0xF;
|
||||
int tmp_ri = read_index;
|
||||
|
||||
if(tmp_ri > 4)
|
||||
ret ^= 0xF;
|
||||
else
|
||||
{
|
||||
if(!InputTypes[tmp_ri])
|
||||
ret ^= 0xF;
|
||||
else if(InputTypes[tmp_ri] == 2) // Mouse
|
||||
{
|
||||
if(sel & 1)
|
||||
{
|
||||
CheckLM(tmp_ri);
|
||||
ret ^= 0xF;
|
||||
ret ^= mouse_rel[tmp_ri] & 0xF;
|
||||
|
||||
mouse_rel[tmp_ri] >>= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pce_mouse_button[tmp_ri] & 1)
|
||||
ret ^= 0x3; //pce_mouse_button[tmp_ri];
|
||||
|
||||
if(pce_mouse_button[tmp_ri] & 0x2)
|
||||
ret ^= 0x8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(InputTypes[tmp_ri] == 1) // Gamepad
|
||||
{
|
||||
if(AVPad6Which[tmp_ri] && AVPad6Enabled[tmp_ri])
|
||||
{
|
||||
if(sel & 1)
|
||||
ret ^= 0x0F;
|
||||
else
|
||||
ret ^= (pce_jp_data[tmp_ri] >> 8) & 0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sel & 1)
|
||||
ret ^= (pce_jp_data[tmp_ri] >> 4) & 0x0F;
|
||||
else
|
||||
ret ^= pce_jp_data[tmp_ri] & 0x0F;
|
||||
}
|
||||
if(!(sel & 1))
|
||||
AVPad6Which[tmp_ri] = !AVPad6Which[tmp_ri];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!PCE_IsCD)
|
||||
ret |= 0x80; // Set when CDROM is not attached
|
||||
|
||||
//ret |= 0x40; // PC Engine if set, TG16 if clear. Let's leave it clear, PC Engine games don't seem to mind if it's clear, but TG16 games barf if it's set.
|
||||
|
||||
ret |= 0x30; // Always-set?
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void INPUT_Write(unsigned int A, uint8 V)
|
||||
{
|
||||
if((V & 1) && !(sel & 2) && (V & 2))
|
||||
{
|
||||
read_index = 0;
|
||||
}
|
||||
else if((V & 1) && !(sel & 1))
|
||||
{
|
||||
if(read_index < 255)
|
||||
read_index++;
|
||||
}
|
||||
sel = V & 3;
|
||||
}
|
||||
|
||||
int INPUT_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
// 0.8.A fix:
|
||||
SFARRAYB(AVPad6Enabled, 5),
|
||||
SFARRAYB(AVPad6Which, 5),
|
||||
|
||||
SFVARN(mouse_last_meow[0], "mlm_0"),
|
||||
SFVARN(mouse_last_meow[1], "mlm_1"),
|
||||
SFVARN(mouse_last_meow[2], "mlm_2"),
|
||||
SFVARN(mouse_last_meow[3], "mlm_3"),
|
||||
SFVARN(mouse_last_meow[4], "mlm_4"),
|
||||
|
||||
SFARRAY32(mouse_x, 5),
|
||||
SFARRAY32(mouse_y, 5),
|
||||
SFARRAY16(mouse_rel, 5),
|
||||
SFARRAY(pce_mouse_button, 5),
|
||||
SFARRAY(mouse_index, 5),
|
||||
// end 0.8.A fix
|
||||
|
||||
SFARRAY16(pce_jp_data, 5),
|
||||
SFVAR(sel),
|
||||
SFVAR(read_index),
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "JOY");
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
// GamepadIDII and GamepadIDII_DSR must be EXACTLY the same except for the RUN+SELECT exclusion in the latter.
|
||||
static const InputDeviceInputInfoStruct GamepadIDII[] =
|
||||
{
|
||||
{ "i", "I", 12, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "ii", "II", 11, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, NULL },
|
||||
{ "run", "RUN", 5, IDIT_BUTTON, NULL },
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "iii", "III", 10, IDIT_BUTTON, NULL },
|
||||
{ "iv", "IV", 7, IDIT_BUTTON, NULL },
|
||||
{ "v", "V", 8, IDIT_BUTTON, NULL },
|
||||
{ "vi", "VI", 9, IDIT_BUTTON, NULL },
|
||||
{ "mode_select", "2/6 Mode Select", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
static const InputDeviceInputInfoStruct GamepadIDII_DSR[] =
|
||||
{
|
||||
{ "i", "I", 12, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "ii", "II", 11, IDIT_BUTTON_CAN_RAPID, NULL },
|
||||
{ "select", "SELECT", 4, IDIT_BUTTON, "run" },
|
||||
{ "run", "RUN", 5, IDIT_BUTTON, "select" },
|
||||
{ "up", "UP ↑", 0, IDIT_BUTTON, "down" },
|
||||
{ "right", "RIGHT →", 3, IDIT_BUTTON, "left" },
|
||||
{ "down", "DOWN ↓", 1, IDIT_BUTTON, "up" },
|
||||
{ "left", "LEFT ←", 2, IDIT_BUTTON, "right" },
|
||||
{ "iii", "III", 10, IDIT_BUTTON, NULL },
|
||||
{ "iv", "IV", 7, IDIT_BUTTON, NULL },
|
||||
{ "v", "V", 8, IDIT_BUTTON, NULL },
|
||||
{ "vi", "VI", 9, IDIT_BUTTON, NULL },
|
||||
{ "mode_select", "2/6 Mode Select", 6, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
static const InputDeviceInputInfoStruct MouseIDII[] =
|
||||
{
|
||||
{ "x_axis", "X Axis", -1, IDIT_X_AXIS_REL },
|
||||
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL },
|
||||
{ "left", "Left Button", 0, IDIT_BUTTON, NULL },
|
||||
{ "right", "Right Button", 1, IDIT_BUTTON, NULL },
|
||||
};
|
||||
|
||||
// If we add more devices to this array, REMEMBER TO UPDATE the hackish array indexing in the SyncSettings() function
|
||||
// below.
|
||||
static InputDeviceInfoStruct InputDeviceInfo[] =
|
||||
{
|
||||
// None
|
||||
{
|
||||
"none",
|
||||
"none",
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
|
||||
// Gamepad
|
||||
{
|
||||
"gamepad",
|
||||
"Gamepad",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(GamepadIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
GamepadIDII,
|
||||
},
|
||||
|
||||
// Mouse
|
||||
{
|
||||
"mouse",
|
||||
"Mouse",
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(MouseIDII) / sizeof(InputDeviceInputInfoStruct),
|
||||
MouseIDII,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const InputPortInfoStruct PortInfo[] =
|
||||
{
|
||||
{ "port1", "Port 1", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port2", "Port 2", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port3", "Port 3", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port4", "Port 4", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
{ "port5", "Port 5", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" },
|
||||
};
|
||||
|
||||
InputInfoStruct PCEInputInfo =
|
||||
{
|
||||
sizeof(PortInfo) / sizeof(InputPortInfoStruct),
|
||||
PortInfo
|
||||
};
|
||||
|
||||
static void SyncSettings(void)
|
||||
{
|
||||
MDFNGameInfo->mouse_sensitivity = MDFN_GetSettingF("pce_fast.mouse_sensitivity");
|
||||
InputDeviceInfo[1].IDII = MDFN_GetSettingB("pce_fast.disable_softreset") ? GamepadIDII_DSR : GamepadIDII;
|
||||
}
|
||||
|
||||
};
|
19
mednafen/pce_fast-09333/input.h
Normal file
19
mednafen/pce_fast-09333/input.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __PCE_INPUT_H
|
||||
#define __PCE_INPUT_H
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
void PCEINPUT_Init(void);
|
||||
void PCEINPUT_SettingChanged(const char *name);
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr);
|
||||
uint8 INPUT_Read(unsigned int A);
|
||||
void INPUT_Write(unsigned int A, uint8 V);
|
||||
void INPUT_Frame(void);
|
||||
int INPUT_StateAction(StateMem *sm, int load, int data_only);
|
||||
extern InputInfoStruct PCEInputInfo;
|
||||
void INPUT_FixTS(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
138
mednafen/pce_fast-09333/ioread.inc
Normal file
138
mednafen/pce_fast-09333/ioread.inc
Normal file
@ -0,0 +1,138 @@
|
||||
A &= 0x1FFF;
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER)
|
||||
const void * const IOReadHandlers[0x20] =
|
||||
{
|
||||
&&VDC_00, &&VDC_01, &&VDC_02, &&VDC_03,
|
||||
&&VCE_00, &&VCE_01, &&VCE_02, &&VCE_03,
|
||||
&&PSG_00, &&PSG_01, &&PSG_02, &&PSG_03,
|
||||
&&TIMER_00, &&TIMER_01, &&TIMER_02, &&TIMER_03,
|
||||
&&INPUT_00, &&INPUT_01, &&INPUT_02, &&INPUT_03,
|
||||
&&IRQ_00, &&IRQ_01, &&IRQ_02, &&IRQ_03,
|
||||
&&CDROM_00, &&CDROM_01, &&CDROM_02, &&CDROM_03,
|
||||
&&EXP_00, &&EXP_01, &&EXP_02, &&EXP_03
|
||||
};
|
||||
|
||||
goto *IOReadHandlers[((A & 0x1C00) >> 8) | (A & 0x3)];
|
||||
{
|
||||
#define PCEF_CASEL(label, caseval) label
|
||||
#else
|
||||
#define PCEF_CASEL(label, caseval) case (caseval)
|
||||
|
||||
switch(((A & 0x1C00) >> 8) | (A & 0x3))
|
||||
{
|
||||
#endif
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#if IOREAD_SGX==1
|
||||
PCEF_CASEL(VDC_00, 0x00):
|
||||
PCEF_CASEL(VDC_01, 0x01):
|
||||
PCEF_CASEL(VDC_02, 0x02):
|
||||
PCEF_CASEL(VDC_03, 0x03):
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(A & 0x1F, TRUE));
|
||||
#else
|
||||
|
||||
PCEF_CASEL(VDC_00, 0x00):
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(0, FALSE));
|
||||
|
||||
PCEF_CASEL(VDC_01, 0x01):
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(1, FALSE));
|
||||
|
||||
PCEF_CASEL(VDC_02, 0x02):
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(2, FALSE));
|
||||
|
||||
PCEF_CASEL(VDC_03, 0x03):
|
||||
HuC6280_StealCycle();
|
||||
return(VDC_Read(3, FALSE));
|
||||
#endif
|
||||
|
||||
PCEF_CASEL(VCE_00, 0x04):
|
||||
PCEF_CASEL(VCE_01, 0x05):
|
||||
PCEF_CASEL(VCE_02, 0x06):
|
||||
PCEF_CASEL(VCE_03, 0x07):
|
||||
HuC6280_StealCycle();
|
||||
return(VCE_Read(A));
|
||||
|
||||
PCEF_CASEL(PSG_00, 0x08):
|
||||
PCEF_CASEL(PSG_01, 0x09):
|
||||
PCEF_CASEL(PSG_02, 0x0A):
|
||||
PCEF_CASEL(PSG_03, 0x0B):
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
return(PCEIODataBuffer);
|
||||
|
||||
|
||||
PCEF_CASEL(TIMER_00, 0x0C):
|
||||
PCEF_CASEL(TIMER_01, 0x0D):
|
||||
PCEF_CASEL(TIMER_02, 0x0E):
|
||||
PCEF_CASEL(TIMER_03, 0x0F):
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
{
|
||||
uint8 ret = HuC6280_TimerRead(A);
|
||||
PCEIODataBuffer = ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
PCEF_CASEL(INPUT_00, 0x10):
|
||||
PCEF_CASEL(INPUT_01, 0x11):
|
||||
PCEF_CASEL(INPUT_02, 0x12):
|
||||
PCEF_CASEL(INPUT_03, 0x13):
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
{
|
||||
uint8 ret = INPUT_Read(A);
|
||||
PCEIODataBuffer = ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
PCEF_CASEL(IRQ_00, 0x14):
|
||||
PCEF_CASEL(IRQ_01, 0x15):
|
||||
PCEF_CASEL(IRQ_02, 0x16):
|
||||
PCEF_CASEL(IRQ_03, 0x17):
|
||||
if(HuCPU.in_block_move)
|
||||
return(0);
|
||||
{
|
||||
uint8 ret = HuC6280_IRQStatusRead(A);
|
||||
PCEIODataBuffer = ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
PCEF_CASEL(CDROM_00, 0x18):
|
||||
PCEF_CASEL(CDROM_01, 0x19):
|
||||
PCEF_CASEL(CDROM_02, 0x1A):
|
||||
PCEF_CASEL(CDROM_03, 0x1B):
|
||||
if(!PCE_IsCD)
|
||||
return(0xFF);
|
||||
|
||||
if((A & 0x1E00) == 0x1A00)
|
||||
{
|
||||
if(arcade_card)
|
||||
return(arcade_card->Read(A & 0x1FFF));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(PCECD_Read(HuCPU.timestamp * 3, A));
|
||||
}
|
||||
|
||||
PCEF_CASEL(EXP_00, 0x1C):
|
||||
PCEF_CASEL(EXP_01, 0x1D):
|
||||
PCEF_CASEL(EXP_02, 0x1E):
|
||||
PCEF_CASEL(EXP_03, 0x1F):
|
||||
#ifdef HAVE_HES
|
||||
if(IsHES)
|
||||
return(ReadIBP(A));
|
||||
#endif
|
||||
return(0xFF);
|
||||
|
||||
}
|
||||
#undef PCEF_CASEL
|
||||
//printf("Meow: %08x, %02x:%04x\n", A, A >> 13, A & 0x1FFF);
|
714
mednafen/pce_fast-09333/pce.cpp
Normal file
714
mednafen/pce_fast-09333/pce.cpp
Normal file
@ -0,0 +1,714 @@
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pce.h"
|
||||
#include <zlib.h>
|
||||
#include "vdc.h"
|
||||
#include "psg.h"
|
||||
#include "input.h"
|
||||
#include "huc.h"
|
||||
#include "pcecd.h"
|
||||
#include "pcecd_drive.h"
|
||||
#include "hes.h"
|
||||
#include "arcade_card/arcade_card.h"
|
||||
#include "../mempatcher.h"
|
||||
#include "../cdrom/cdromif.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
static PCEFast_PSG *psg = NULL;
|
||||
extern ArcadeCard *arcade_card; // Bah, lousy globals.
|
||||
|
||||
static Blip_Buffer sbuf[2];
|
||||
|
||||
bool PCE_ACEnabled;
|
||||
|
||||
static bool IsSGX;
|
||||
static bool IsHES;
|
||||
int pce_overclocked;
|
||||
|
||||
// Statically allocated for speed...or something.
|
||||
uint8 ROMSpace[0x88 * 8192 + 8192]; // + 8192 for PC-as-pointer safety padding
|
||||
|
||||
uint8 BaseRAM[32768 + 8192]; // 8KB for PCE, 32KB for Super Grafx // + 8192 for PC-as-pointer safety padding
|
||||
|
||||
uint8 PCEIODataBuffer;
|
||||
readfunc PCERead[0x100];
|
||||
writefunc PCEWrite[0x100];
|
||||
|
||||
static DECLFR(PCEBusRead)
|
||||
{
|
||||
//printf("BUS Read: %02x %04x\n", A >> 13, A);
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
static DECLFW(PCENullWrite)
|
||||
{
|
||||
//printf("Null Write: %02x, %08x %02x\n", A >> 13, A, V);
|
||||
}
|
||||
|
||||
static DECLFR(BaseRAMReadSGX)
|
||||
{
|
||||
return((BaseRAM - (0xF8 * 8192))[A]);
|
||||
}
|
||||
|
||||
static DECLFW(BaseRAMWriteSGX)
|
||||
{
|
||||
(BaseRAM - (0xF8 * 8192))[A] = V;
|
||||
}
|
||||
|
||||
static DECLFR(BaseRAMRead)
|
||||
{
|
||||
return((BaseRAM - (0xF8 * 8192))[A]);
|
||||
}
|
||||
|
||||
static DECLFR(BaseRAMRead_Mirrored)
|
||||
{
|
||||
return(BaseRAM[A & 0x1FFF]);
|
||||
}
|
||||
|
||||
static DECLFW(BaseRAMWrite)
|
||||
{
|
||||
(BaseRAM - (0xF8 * 8192))[A] = V;
|
||||
}
|
||||
|
||||
static DECLFW(BaseRAMWrite_Mirrored)
|
||||
{
|
||||
BaseRAM[A & 0x1FFF] = V;
|
||||
}
|
||||
|
||||
static DECLFR(IORead)
|
||||
{
|
||||
#define IOREAD_SGX 0
|
||||
#include "ioread.inc"
|
||||
#undef IOREAD_SGX
|
||||
}
|
||||
|
||||
static DECLFR(IOReadSGX)
|
||||
{
|
||||
#define IOREAD_SGX 1
|
||||
#include "ioread.inc"
|
||||
#undef IOREAD_SGX
|
||||
}
|
||||
|
||||
static DECLFW(IOWrite)
|
||||
{
|
||||
A &= 0x1FFF;
|
||||
|
||||
switch(A >> 10)
|
||||
{
|
||||
case 0: HuC6280_StealCycle();
|
||||
VDC_Write(A, V);
|
||||
break;
|
||||
|
||||
case 1: HuC6280_StealCycle();
|
||||
VCE_Write(A, V);
|
||||
break;
|
||||
|
||||
case 2: PCEIODataBuffer = V;
|
||||
psg->Write(HuCPU.timestamp / pce_overclocked, A, V);
|
||||
break;
|
||||
|
||||
case 3: PCEIODataBuffer = V;
|
||||
HuC6280_TimerWrite(A, V);
|
||||
break;
|
||||
|
||||
case 4: PCEIODataBuffer = V; INPUT_Write(A, V); break;
|
||||
case 5: PCEIODataBuffer = V; HuC6280_IRQStatusWrite(A, V); break;
|
||||
case 6:
|
||||
if(!PCE_IsCD)
|
||||
break;
|
||||
|
||||
if((A & 0x1E00) == 0x1A00)
|
||||
{
|
||||
if(arcade_card)
|
||||
arcade_card->Write(A & 0x1FFF, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
PCECD_Write(HuCPU.timestamp * 3, A, V);
|
||||
}
|
||||
break;
|
||||
|
||||
case 7: break; // Expansion.
|
||||
}
|
||||
}
|
||||
|
||||
static void PCECDIRQCB(bool asserted)
|
||||
{
|
||||
if(asserted)
|
||||
HuC6280_IRQBegin(MDFN_IQIRQ2);
|
||||
else
|
||||
HuC6280_IRQEnd(MDFN_IQIRQ2);
|
||||
}
|
||||
|
||||
bool PCE_InitCD(void)
|
||||
{
|
||||
PCECD_Settings cd_settings;
|
||||
memset(&cd_settings, 0, sizeof(PCECD_Settings));
|
||||
|
||||
cd_settings.CDDA_Volume = (double)MDFN_GetSettingUI("pce_fast.cddavolume") / 100;
|
||||
cd_settings.CD_Speed = MDFN_GetSettingUI("pce_fast.cdspeed");
|
||||
|
||||
cd_settings.ADPCM_Volume = (double)MDFN_GetSettingUI("pce_fast.adpcmvolume") / 100;
|
||||
cd_settings.ADPCM_LPF = MDFN_GetSettingB("pce_fast.adpcmlp");
|
||||
|
||||
if(cd_settings.CDDA_Volume != 1.0)
|
||||
MDFN_printf(_("CD-DA Volume: %d%%\n"), (int)(100 * cd_settings.CDDA_Volume));
|
||||
|
||||
if(cd_settings.ADPCM_Volume != 1.0)
|
||||
MDFN_printf(_("ADPCM Volume: %d%%\n"), (int)(100 * cd_settings.ADPCM_Volume));
|
||||
|
||||
return(PCECD_Init(&cd_settings, PCECDIRQCB, PCE_MASTER_CLOCK, pce_overclocked, &sbuf[0], &sbuf[1]));
|
||||
}
|
||||
|
||||
|
||||
static int LoadCommon(void);
|
||||
static void LoadCommonPre(void);
|
||||
|
||||
static bool TestMagic(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
if(memcmp(GET_FDATA_PTR(fp), "HESM", 4) && strcasecmp(GET_FEXTS_PTR(fp), "pce") && strcasecmp(GET_FEXTS_PTR(fp), "sgx"))
|
||||
return(FALSE);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static int Load(const char *name, MDFNFILE *fp)
|
||||
{
|
||||
uint32 headerlen = 0;
|
||||
uint32 r_size;
|
||||
|
||||
IsHES = 0;
|
||||
IsSGX = 0;
|
||||
|
||||
if(!memcmp(GET_FDATA_PTR(fp), "HESM", 4))
|
||||
IsHES = 1;
|
||||
|
||||
LoadCommonPre();
|
||||
|
||||
if(!IsHES)
|
||||
{
|
||||
if(GET_FSIZE_PTR(fp) & 0x200) // 512 byte header!
|
||||
headerlen = 512;
|
||||
}
|
||||
|
||||
r_size = GET_FSIZE_PTR(fp) - headerlen;
|
||||
if(r_size > 4096 * 1024) r_size = 4096 * 1024;
|
||||
|
||||
for(int x = 0; x < 0x100; x++)
|
||||
{
|
||||
PCERead[x] = PCEBusRead;
|
||||
PCEWrite[x] = PCENullWrite;
|
||||
}
|
||||
|
||||
uint32 crc = crc32(0, GET_FDATA_PTR(fp) + headerlen, GET_FSIZE_PTR(fp) - headerlen);
|
||||
|
||||
|
||||
#ifdef HAVE_HES
|
||||
if(IsHES)
|
||||
{
|
||||
if(!PCE_HESLoad(GET_FDATA_PTR(fp), GET_FSIZE_PTR(fp)))
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
HuCLoad(GET_FDATA_PTR(fp) + headerlen, GET_FSIZE_PTR(fp) - headerlen, crc);
|
||||
|
||||
if(!strcasecmp(GET_FEXTS_PTR(fp), "sgx"))
|
||||
IsSGX = TRUE;
|
||||
|
||||
if(GET_FSIZE_PTR(fp) >= 8192 && !memcmp(GET_FDATA_PTR(fp) + headerlen, "DARIUS Version 1.11b", strlen("DARIUS VERSION 1.11b")))
|
||||
{
|
||||
MDFN_printf("SuperGfx: Darius Plus\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
|
||||
if(crc == 0x4c2126b0)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Aldynes\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
|
||||
if(crc == 0x8c4588e2)
|
||||
{
|
||||
MDFN_printf("SuperGfx: 1941 - Counter Attack\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
if(crc == 0x1f041166)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Madouou Granzort\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
if(crc == 0xb486a8ed)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Daimakaimura\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
if(crc == 0x3b13af61)
|
||||
{
|
||||
MDFN_printf("SuperGfx: Battle Ace\n");
|
||||
IsSGX = 1;
|
||||
}
|
||||
|
||||
return(LoadCommon());
|
||||
}
|
||||
|
||||
static void LoadCommonPre(void)
|
||||
{
|
||||
// FIXME: Make these globals less global!
|
||||
pce_overclocked = MDFN_GetSettingUI("pce_fast.ocmultiplier");
|
||||
PCE_ACEnabled = MDFN_GetSettingB("pce_fast.arcadecard");
|
||||
|
||||
if(pce_overclocked > 1)
|
||||
MDFN_printf(_("CPU overclock: %dx\n"), pce_overclocked);
|
||||
|
||||
if(MDFN_GetSettingUI("pce_fast.cdspeed") > 1)
|
||||
MDFN_printf(_("CD-ROM speed: %ux\n"), (unsigned int)MDFN_GetSettingUI("pce_fast.cdspeed"));
|
||||
|
||||
memset(HuCPUFastMap, 0, sizeof(HuCPUFastMap));
|
||||
for(int x = 0; x < 0x100; x++)
|
||||
{
|
||||
PCERead[x] = PCEBusRead;
|
||||
PCEWrite[x] = PCENullWrite;
|
||||
}
|
||||
|
||||
MDFNMP_Init(1024, (1 << 21) / 1024);
|
||||
}
|
||||
|
||||
static int LoadCommon(void)
|
||||
{
|
||||
IsSGX |= MDFN_GetSettingB("pce_fast.forcesgx") ? 1 : 0;
|
||||
|
||||
if(IsHES)
|
||||
IsSGX = 1;
|
||||
// Don't modify IsSGX past this point.
|
||||
|
||||
VDC_Init(IsSGX);
|
||||
|
||||
if(IsSGX)
|
||||
{
|
||||
MDFN_printf("SuperGrafx Emulation Enabled.\n");
|
||||
PCERead[0xF8] = PCERead[0xF9] = PCERead[0xFA] = PCERead[0xFB] = BaseRAMReadSGX;
|
||||
PCEWrite[0xF8] = PCEWrite[0xF9] = PCEWrite[0xFA] = PCEWrite[0xFB] = BaseRAMWriteSGX;
|
||||
|
||||
for(int x = 0xf8; x < 0xfb; x++)
|
||||
HuCPUFastMap[x] = BaseRAM - 0xf8 * 8192;
|
||||
|
||||
PCERead[0xFF] = IOReadSGX;
|
||||
}
|
||||
else
|
||||
{
|
||||
PCERead[0xF8] = BaseRAMRead;
|
||||
PCERead[0xF9] = PCERead[0xFA] = PCERead[0xFB] = BaseRAMRead_Mirrored;
|
||||
|
||||
PCEWrite[0xF8] = BaseRAMWrite;
|
||||
PCEWrite[0xF9] = PCEWrite[0xFA] = PCEWrite[0xFB] = BaseRAMWrite_Mirrored;
|
||||
|
||||
for(int x = 0xf8; x < 0xfb; x++)
|
||||
HuCPUFastMap[x] = BaseRAM - x * 8192;
|
||||
|
||||
PCERead[0xFF] = IORead;
|
||||
}
|
||||
|
||||
MDFNMP_AddRAM(IsSGX ? 32768 : 8192, 0xf8 * 8192, BaseRAM);
|
||||
|
||||
PCEWrite[0xFF] = IOWrite;
|
||||
|
||||
HuC6280_Init();
|
||||
|
||||
psg = new PCEFast_PSG(&sbuf[0], &sbuf[1]);
|
||||
|
||||
psg->SetVolume(1.0);
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
unsigned int cdpsgvolume = MDFN_GetSettingUI("pce_fast.cdpsgvolume");
|
||||
|
||||
if(cdpsgvolume != 100)
|
||||
{
|
||||
MDFN_printf(_("CD PSG Volume: %d%%\n"), cdpsgvolume);
|
||||
}
|
||||
|
||||
psg->SetVolume(0.678 * cdpsgvolume / 100);
|
||||
|
||||
}
|
||||
|
||||
PCEINPUT_Init();
|
||||
|
||||
PCE_Power();
|
||||
|
||||
MDFNGameInfo->LayerNames = IsSGX ? "BG0\0SPR0\0BG1\0SPR1\0" : "Background\0Sprites\0";
|
||||
MDFNGameInfo->fps = (uint32)((double)7159090.90909090 / 455 / 263 * 65536 * 256);
|
||||
|
||||
// Clean this up:
|
||||
if(!MDFN_GetSettingB("pce_fast.correct_aspect"))
|
||||
MDFNGameInfo->fb_width = 682;
|
||||
|
||||
if(!IsHES)
|
||||
{
|
||||
MDFNGameInfo->nominal_width = MDFN_GetSettingB("pce_fast.correct_aspect") ? 288 : 341;
|
||||
MDFNGameInfo->nominal_height = MDFN_GetSettingUI("pce_fast.slend") - MDFN_GetSettingUI("pce_fast.slstart") + 1;
|
||||
|
||||
MDFNGameInfo->lcm_width = MDFN_GetSettingB("pce_fast.correct_aspect") ? 1024 : 341;
|
||||
MDFNGameInfo->lcm_height = MDFNGameInfo->nominal_height;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static bool TestMagicCD(std::vector<CDIF *> *CDInterfaces)
|
||||
{
|
||||
static const uint8 magic_test[0x20] = { 0x82, 0xB1, 0x82, 0xCC, 0x83, 0x76, 0x83, 0x8D, 0x83, 0x4F, 0x83, 0x89, 0x83, 0x80, 0x82, 0xCC,
|
||||
0x92, 0x98, 0x8D, 0xEC, 0x8C, 0xA0, 0x82, 0xCD, 0x8A, 0x94, 0x8E, 0xAE, 0x89, 0xEF, 0x8E, 0xD0
|
||||
};
|
||||
uint8 sector_buffer[2048];
|
||||
CDIF *cdiface = (*CDInterfaces)[0];
|
||||
CDUtility::TOC toc;
|
||||
bool ret = FALSE;
|
||||
|
||||
memset(sector_buffer, 0, sizeof(sector_buffer));
|
||||
|
||||
cdiface->ReadTOC(&toc);
|
||||
|
||||
for(int32 track = toc.first_track; track <= toc.last_track; track++)
|
||||
{
|
||||
if(toc.tracks[track].control & 0x4)
|
||||
{
|
||||
cdiface->ReadSector(sector_buffer, toc.tracks[track].lba, 1);
|
||||
|
||||
if(!memcmp((char*)sector_buffer, (char *)magic_test, 0x20))
|
||||
ret = TRUE;
|
||||
|
||||
// PCE CD BIOS apparently only looks at the first data track.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If it's a PC-FX CD(Battle Heat), return false.
|
||||
// This is very kludgy.
|
||||
for(int32 track = toc.first_track; track <= toc.last_track; track++)
|
||||
{
|
||||
if(toc.tracks[track].control & 0x4)
|
||||
{
|
||||
cdiface->ReadSector(sector_buffer, toc.tracks[track].lba, 1);
|
||||
if(!strncmp("PC-FX:Hu_CD-ROM", (char*)sector_buffer, strlen("PC-FX:Hu_CD-ROM")))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now, test for the Games Express CD games. The GE BIOS seems to always look at sector 0x10, but only if the first track is a
|
||||
// data track.
|
||||
if(toc.first_track == 1 && (toc.tracks[1].control & 0x4))
|
||||
{
|
||||
if(cdiface->ReadSector(sector_buffer, 0x10, 1))
|
||||
{
|
||||
if(!memcmp((char *)sector_buffer + 0x8, "HACKER CD ROM SYSTEM", 0x14))
|
||||
{
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int LoadCD(std::vector<CDIF *> *CDInterfaces)
|
||||
{
|
||||
std::string bios_path = MDFN_MakeFName(MDFNMKF_FIRMWARE, 0, MDFN_GetSettingS("pce_fast.cdbios").c_str() );
|
||||
|
||||
IsHES = 0;
|
||||
IsSGX = 0;
|
||||
|
||||
LoadCommonPre();
|
||||
|
||||
if(!HuCLoadCD(bios_path.c_str()))
|
||||
return(0);
|
||||
|
||||
PCECD_Drive_SetDisc(true, NULL, true);
|
||||
PCECD_Drive_SetDisc(false, (*CDInterfaces)[0], true);
|
||||
|
||||
return(LoadCommon());
|
||||
}
|
||||
|
||||
|
||||
static void CloseGame(void)
|
||||
{
|
||||
#ifdef HAVE_HES
|
||||
if(IsHES)
|
||||
HES_Close();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
HuCClose();
|
||||
}
|
||||
VDC_Close();
|
||||
if(psg)
|
||||
{
|
||||
delete psg;
|
||||
psg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void Emulate(EmulateSpecStruct *espec)
|
||||
{
|
||||
INPUT_Frame();
|
||||
|
||||
MDFNMP_ApplyPeriodicCheats();
|
||||
|
||||
#if 0
|
||||
{
|
||||
static bool firstcat = true;
|
||||
MDFN_PixelFormat nf;
|
||||
|
||||
nf.bpp = 16;
|
||||
nf.colorspace = MDFN_COLORSPACE_RGB;
|
||||
nf.Rshift = 11;
|
||||
nf.Gshift = 5;
|
||||
nf.Bshift = 0;
|
||||
nf.Ashift = 16;
|
||||
|
||||
nf.Rprec = 5;
|
||||
nf.Gprec = 6;
|
||||
nf.Bprec = 5;
|
||||
nf.Aprec = 8;
|
||||
|
||||
espec->surface->SetFormat(nf, false);
|
||||
espec->VideoFormatChanged = firstcat;
|
||||
firstcat = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static bool firstcat = true;
|
||||
|
||||
MDFN_PixelFormat tmp_pf;
|
||||
|
||||
tmp_pf.Rshift = 0;
|
||||
tmp_pf.Gshift = 0;
|
||||
tmp_pf.Bshift = 0;
|
||||
tmp_pf.Ashift = 8;
|
||||
|
||||
tmp_pf.Rprec = 0;
|
||||
tmp_pf.Gprec = 0;
|
||||
tmp_pf.Bprec = 0;
|
||||
tmp_pf.Aprec = 0;
|
||||
|
||||
tmp_pf.bpp = 8;
|
||||
tmp_pf.colorspace = MDFN_COLORSPACE_RGB;
|
||||
|
||||
espec->surface->SetFormat(tmp_pf, false);
|
||||
espec->VideoFormatChanged = firstcat;
|
||||
firstcat = false;
|
||||
#endif
|
||||
|
||||
if(espec->VideoFormatChanged)
|
||||
VDC_SetPixelFormat(espec->surface->format); //.Rshift, espec->surface->format.Gshift, espec->surface->format.Bshift);
|
||||
|
||||
if(espec->SoundFormatChanged)
|
||||
{
|
||||
for(int y = 0; y < 2; y++)
|
||||
{
|
||||
sbuf[y].set_sample_rate(espec->SoundRate ? espec->SoundRate : 44100, 50);
|
||||
sbuf[y].clock_rate((long)(PCE_MASTER_CLOCK / 3));
|
||||
sbuf[y].bass_freq(10);
|
||||
}
|
||||
}
|
||||
VDC_RunFrame(espec, IsHES);
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
PCECD_Run(HuCPU.timestamp * 3);
|
||||
}
|
||||
|
||||
psg->EndFrame(HuCPU.timestamp / pce_overclocked);
|
||||
|
||||
if(espec->SoundBuf)
|
||||
{
|
||||
for(int y = 0; y < 2; y++)
|
||||
{
|
||||
sbuf[y].end_frame(HuCPU.timestamp / pce_overclocked);
|
||||
espec->SoundBufSize = sbuf[y].read_samples(espec->SoundBuf + y, espec->SoundBufMaxSize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
espec->MasterCycles = HuCPU.timestamp * 3;
|
||||
|
||||
INPUT_FixTS();
|
||||
|
||||
HuC6280_ResetTS();
|
||||
|
||||
if(PCE_IsCD)
|
||||
PCECD_ResetTS();
|
||||
|
||||
#ifdef HAVE_HES
|
||||
if(IsHES && !espec->skip)
|
||||
HES_Draw(espec->surface, &espec->DisplayRect, espec->SoundBuf, espec->SoundBufSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(BaseRAM, IsSGX? 32768 : 8192),
|
||||
SFVAR(PCEIODataBuffer),
|
||||
SFEND
|
||||
};
|
||||
|
||||
//for(int i = 8192; i < 32768; i++)
|
||||
// if(BaseRAM[i] != 0xFF)
|
||||
// printf("%d %02x\n", i, BaseRAM[i]);
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN");
|
||||
|
||||
ret &= HuC6280_StateAction(sm, load, data_only);
|
||||
ret &= VDC_StateAction(sm, load, data_only);
|
||||
ret &= psg->StateAction(sm, load, data_only);
|
||||
ret &= INPUT_StateAction(sm, load, data_only);
|
||||
ret &= HuC_StateAction(sm, load, data_only);
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void PCE_Power(void)
|
||||
{
|
||||
memset(BaseRAM, 0x00, sizeof(BaseRAM));
|
||||
|
||||
if(!IsSGX)
|
||||
for(int i = 8192; i < 32768; i++)
|
||||
BaseRAM[i] = 0xFF;
|
||||
|
||||
PCEIODataBuffer = 0xFF;
|
||||
|
||||
#ifdef HAVE_HES
|
||||
if(IsHES)
|
||||
HES_Reset();
|
||||
#endif
|
||||
|
||||
HuC6280_Power();
|
||||
VDC_Power();
|
||||
psg->Power(HuCPU.timestamp / pce_overclocked);
|
||||
HuC_Power();
|
||||
|
||||
if(PCE_IsCD)
|
||||
{
|
||||
PCECD_Power(HuCPU.timestamp * 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoSimpleCommand(int cmd)
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case MDFN_MSC_RESET: PCE_Power(); break;
|
||||
case MDFN_MSC_POWER: PCE_Power(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static MDFNSetting PCESettings[] =
|
||||
{
|
||||
{ "pce_fast.correct_aspect", MDFNSF_CAT_VIDEO, gettext_noop("Correct the aspect ratio."), NULL, MDFNST_BOOL, "1" },
|
||||
{ "pce_fast.slstart", MDFNSF_NOFLAGS, gettext_noop("First rendered scanline."), NULL, MDFNST_UINT, "4", "0", "239" },
|
||||
{ "pce_fast.slend", MDFNSF_NOFLAGS, gettext_noop("Last rendered scanline."), NULL, MDFNST_UINT, "235", "0", "239" },
|
||||
{ "pce_fast.mouse_sensitivity", MDFNSF_NOFLAGS, gettext_noop("Mouse sensitivity."), NULL, MDFNST_FLOAT, "0.50", NULL, NULL, NULL, PCEINPUT_SettingChanged },
|
||||
{ "pce_fast.disable_softreset", MDFNSF_NOFLAGS, gettext_noop("If set, when RUN+SEL are pressed simultaneously, disable both buttons temporarily."), NULL, MDFNST_BOOL, "0", NULL, NULL, NULL, PCEINPUT_SettingChanged },
|
||||
{ "pce_fast.forcesgx", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Force SuperGrafx emulation."), NULL, MDFNST_BOOL, "0" },
|
||||
{ "pce_fast.arcadecard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("Enable Arcade Card emulation."), NULL, MDFNST_BOOL, "1" },
|
||||
{ "pce_fast.ocmultiplier", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("CPU overclock multiplier."), NULL, MDFNST_UINT, "1", "1", "100"},
|
||||
{ "pce_fast.cdspeed", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, gettext_noop("CD-ROM data transfer speed multiplier."), NULL, MDFNST_UINT, "1", "1", "100" },
|
||||
{ "pce_fast.nospritelimit", MDFNSF_NOFLAGS, gettext_noop("Remove 16-sprites-per-scanline hardware limit."), NULL, MDFNST_BOOL, "0" },
|
||||
|
||||
{ "pce_fast.cdbios", MDFNSF_EMU_STATE, gettext_noop("Path to the CD BIOS"), NULL, MDFNST_STRING, "syscard3.pce" },
|
||||
|
||||
{ "pce_fast.adpcmlp", MDFNSF_NOFLAGS, gettext_noop("Enable dynamic ADPCM lowpass filter."), NULL, MDFNST_BOOL, "0" },
|
||||
{ "pce_fast.cdpsgvolume", MDFNSF_NOFLAGS, gettext_noop("PSG volume when playing a CD game."), NULL, MDFNST_UINT, "100", "0", "200" },
|
||||
{ "pce_fast.cddavolume", MDFNSF_NOFLAGS, gettext_noop("CD-DA volume."), NULL, MDFNST_UINT, "100", "0", "200" },
|
||||
{ "pce_fast.adpcmvolume", MDFNSF_NOFLAGS, gettext_noop("ADPCM volume."), NULL, MDFNST_UINT, "100", "0", "200" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static uint8 MemRead(uint32 addr)
|
||||
{
|
||||
return(PCERead[(addr / 8192) & 0xFF](addr));
|
||||
}
|
||||
|
||||
static const FileExtensionSpecStruct KnownExtensions[] =
|
||||
{
|
||||
{ ".pce", gettext_noop("PC Engine ROM Image") },
|
||||
{ ".hes", gettext_noop("PC Engine Music Rip") },
|
||||
{ ".sgx", gettext_noop("SuperGrafx ROM Image") },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
MDFNGI EmulatedPCE_Fast =
|
||||
{
|
||||
"pce_fast",
|
||||
"PC Engine (CD)/TurboGrafx 16 (CD)/SuperGrafx",
|
||||
KnownExtensions,
|
||||
MODPRIO_INTERNAL_LOW,
|
||||
NULL,
|
||||
&PCEInputInfo,
|
||||
Load,
|
||||
TestMagic,
|
||||
LoadCD,
|
||||
TestMagicCD,
|
||||
CloseGame,
|
||||
VDC_SetLayerEnableMask,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
MemRead,
|
||||
NULL,
|
||||
false,
|
||||
StateAction,
|
||||
Emulate,
|
||||
PCEINPUT_SetInput,
|
||||
DoSimpleCommand,
|
||||
PCESettings,
|
||||
MDFN_MASTERCLOCK_FIXED(PCE_MASTER_CLOCK),
|
||||
0,
|
||||
|
||||
true, // Multires possible?
|
||||
|
||||
0, // lcm_width
|
||||
0, // lcm_height
|
||||
NULL, // Dummy
|
||||
|
||||
288, // Nominal width
|
||||
232, // Nominal height
|
||||
|
||||
512, // Framebuffer width
|
||||
242, // Framebuffer height
|
||||
|
||||
2, // Number of output sound channels
|
||||
};
|
||||
|
62
mednafen/pce_fast-09333/pce.h
Normal file
62
mednafen/pce_fast-09333/pce.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef _PCE_H
|
||||
#define _PCE_H
|
||||
|
||||
#include "../mednafen-types.h"
|
||||
#include "../mednafen.h"
|
||||
#include "../state.h"
|
||||
#include "../general.h"
|
||||
#include "../mednafen-memory.h"
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
#define GET_FDATA(fp) (fp.f_data)
|
||||
#define GET_FSIZE(fp) (fp.f_size)
|
||||
#define GET_FEXTS(fp) (fp.f_ext)
|
||||
#define GET_FDATA_PTR(fp) (fp->f_data)
|
||||
#define GET_FSIZE_PTR(fp) (fp->f_size)
|
||||
#define GET_FEXTS_PTR(fp) (fp->f_ext)
|
||||
#define gzread(a, b, c) fread(b, c, 1, a)
|
||||
#else
|
||||
#define GET_FDATA(fp) (fp.Data())
|
||||
#define GET_FSIZE(fp) (fp.Size())
|
||||
#define GET_FDATA_PTR(fp) (fp->data)
|
||||
#define GET_FSIZE_PTR(fp) (fp->size)
|
||||
#define GET_FEXTS_PTR(fp) (fp->ext)
|
||||
#define gzread(a, b, c) gzread(a, b, c)
|
||||
#endif
|
||||
|
||||
#define PCE_MASTER_CLOCK 21477272.727273
|
||||
|
||||
#define DECLFR(x) uint8 MDFN_FASTCALL x (uint32 A)
|
||||
#define DECLFW(x) void MDFN_FASTCALL x (uint32 A, uint8 V)
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
extern uint8 ROMSpace[0x88 * 8192 + 8192];
|
||||
|
||||
typedef void (MDFN_FASTCALL *writefunc)(uint32 A, uint8 V);
|
||||
typedef uint8 (MDFN_FASTCALL *readfunc)(uint32 A);
|
||||
|
||||
extern uint8 PCEIODataBuffer;
|
||||
|
||||
bool PCE_InitCD(void) MDFN_COLD;
|
||||
|
||||
};
|
||||
|
||||
#include "huc6280.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
extern bool PCE_ACEnabled; // Arcade Card emulation enabled?
|
||||
void PCE_Power(void) MDFN_COLD;
|
||||
|
||||
extern readfunc PCERead[0x100];
|
||||
extern writefunc PCEWrite[0x100];
|
||||
extern int pce_overclocked;
|
||||
|
||||
extern uint8 BaseRAM[32768 + 8192];
|
||||
|
||||
};
|
||||
|
||||
using namespace PCE_Fast;
|
||||
|
||||
#endif
|
984
mednafen/pce_fast-09333/pcecd.cpp
Normal file
984
mednafen/pce_fast-09333/pcecd.cpp
Normal file
@ -0,0 +1,984 @@
|
||||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2004 Ki
|
||||
* Copyright (C) 2007-2011 Mednafen Team
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
PCE_FAST(less accurate, faster, etc.) fork from PCE module "pcecd.cpp".
|
||||
*/
|
||||
|
||||
#include "../mednafen.h"
|
||||
#include "../cdrom/cdromif.h"
|
||||
#include "pcecd_drive.h"
|
||||
#include "../okiadpcm.h"
|
||||
|
||||
#include "pcecd.h"
|
||||
#include "../cdrom/SimpleFIFO.h"
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
//#define PCECD_DEBUG
|
||||
|
||||
static unsigned int OC_Multiplier;
|
||||
|
||||
static void (*IRQCB)(bool asserted);
|
||||
|
||||
static float CDDAVolumeSetting; // User setting!
|
||||
|
||||
static bool bBRAMEnabled;
|
||||
static uint8 _Port[15];
|
||||
static uint8 ACKStatus;
|
||||
|
||||
static SimpleFIFO<uint8> SubChannelFIFO(16);
|
||||
|
||||
static Blip_Buffer *sbuf[2];
|
||||
static int16 RawPCMVolumeCache[2];
|
||||
|
||||
static int32 ClearACKDelay;
|
||||
|
||||
static int32 lastts;
|
||||
static int32 pcecd_drive_ne = 0;
|
||||
|
||||
// ADPCM variables and whatnot
|
||||
#define ADPCM_DEBUG(x, ...) { /*printf("[Half=%d, End=%d, Playing=%d] "x, ADPCM.HalfReached, ADPCM.EndReached, ADPCM.Playing, ## __VA_ARGS__);*/ }
|
||||
|
||||
typedef Blip_Synth<blip_good_quality, 16384> ADSynth;
|
||||
static ADSynth ADPCMSynth;
|
||||
static OKIADPCM_Decoder<OKIADPCM_MSM5205> MSM5205;
|
||||
|
||||
static bool ADPCMLP;
|
||||
typedef struct
|
||||
{
|
||||
uint8 *RAM; // = NULL; //0x10000;
|
||||
uint16 Addr;
|
||||
uint16 ReadAddr;
|
||||
uint16 WriteAddr;
|
||||
uint16 LengthCount;
|
||||
|
||||
bool HalfReached;
|
||||
bool EndReached;
|
||||
bool Playing;
|
||||
|
||||
uint8 LastCmd;
|
||||
uint32 SampleFreq;
|
||||
uint32 LPF_SampleFreq;
|
||||
|
||||
uint8 PlayBuffer;
|
||||
uint8 ReadBuffer;
|
||||
int32 ReadPending;
|
||||
int32 WritePending;
|
||||
uint8 WritePendingValue;
|
||||
|
||||
uint32 PlayNibble;
|
||||
|
||||
|
||||
int64 bigdivacc;
|
||||
int64 bigdiv;
|
||||
int32 last_pcm;
|
||||
} ADPCM_t;
|
||||
|
||||
static ADPCM_t ADPCM;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 Command;
|
||||
int32 Volume;
|
||||
|
||||
int32 CycleCounter;
|
||||
uint32 CountValue; // What to reload CycleCounter with when it expires.
|
||||
bool Clocked;
|
||||
} FADE_t;
|
||||
|
||||
static FADE_t Fader;
|
||||
static int32 ADPCMFadeVolume, CDDAFadeVolume;
|
||||
|
||||
static INLINE void Fader_SyncWhich(void)
|
||||
{
|
||||
if(Fader.Command & 0x2) // ADPCM fade
|
||||
{
|
||||
ADPCMFadeVolume = Fader.Volume;
|
||||
CDDAFadeVolume = 65536;
|
||||
}
|
||||
else // CD-DA Fade
|
||||
{
|
||||
CDDAFadeVolume = Fader.Volume;
|
||||
ADPCMFadeVolume = 65536;
|
||||
}
|
||||
|
||||
ADPCMFadeVolume >>= 6;
|
||||
PCECD_Drive_SetCDDAVolume(0.50f * CDDAFadeVolume * CDDAVolumeSetting);
|
||||
}
|
||||
|
||||
|
||||
static void RedoLPF(int f)
|
||||
{
|
||||
if(sbuf[0] && sbuf[1])
|
||||
{
|
||||
if(ADPCMLP)
|
||||
{
|
||||
if(f >= 14)
|
||||
{
|
||||
int rolloff = (int)((((double)32087.5 / (16 - f)) / 2) * 0.70);
|
||||
ADPCMSynth.treble_eq( blip_eq_t(-1000, rolloff, sbuf[0]->sample_rate()));
|
||||
}
|
||||
else
|
||||
{
|
||||
int rolloff = (int)((((double)32087.5 / (16 - f)) / 2) * 0.80);
|
||||
ADPCMSynth.treble_eq( blip_eq_t(-1000, rolloff, sbuf[0]->sample_rate()));
|
||||
}
|
||||
}
|
||||
else
|
||||
ADPCMSynth.treble_eq(-8.0);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE int32 ADPCM_ClocksToNextEvent(void)
|
||||
{
|
||||
int32 ret = (ADPCM.bigdiv + 65535) >> 16;
|
||||
|
||||
if(ADPCM.WritePending && ret > ADPCM.WritePending)
|
||||
ret = ADPCM.WritePending;
|
||||
|
||||
if(ADPCM.ReadPending && ret > ADPCM.ReadPending)
|
||||
ret = ADPCM.ReadPending;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int32 CalcNextEvent(int32 base)
|
||||
{
|
||||
int32 next_event = base;
|
||||
int32 ADPCM_ctne = ADPCM_ClocksToNextEvent();
|
||||
|
||||
if(next_event > ADPCM_ctne)
|
||||
next_event = ADPCM_ctne;
|
||||
|
||||
if(ClearACKDelay > 0 && next_event > ClearACKDelay)
|
||||
next_event = ClearACKDelay;
|
||||
|
||||
if(next_event > pcecd_drive_ne)
|
||||
next_event = pcecd_drive_ne;
|
||||
|
||||
if(Fader.Clocked && next_event > Fader.CycleCounter)
|
||||
next_event = Fader.CycleCounter;
|
||||
|
||||
return(next_event);
|
||||
}
|
||||
|
||||
static void update_irq_state()
|
||||
{
|
||||
uint8 irq = _Port[2] & _Port[0x3] & (0x4|0x8|0x10|0x20|0x40);
|
||||
|
||||
IRQCB((bool)irq);
|
||||
}
|
||||
|
||||
static void StuffSubchannel(uint8 meow, int subindex)
|
||||
{
|
||||
uint8 tmp_data = meow & 0x7F;
|
||||
|
||||
if(subindex == -2)
|
||||
tmp_data = 0x00;
|
||||
else if(subindex == -1)
|
||||
tmp_data = 0x80;
|
||||
|
||||
if(SubChannelFIFO.CanWrite())
|
||||
SubChannelFIFO.Write(&tmp_data, 1);
|
||||
|
||||
_Port[0x3] |= 0x10;
|
||||
update_irq_state();
|
||||
}
|
||||
|
||||
static void CDIRQ(int type)
|
||||
{
|
||||
#ifdef PCECD_DEBUG
|
||||
if(type != 0x8000 || _Port[0x3] & 0x60)
|
||||
printf("CDIRQ: %d\n", type);
|
||||
#endif
|
||||
if(type & 0x8000)
|
||||
{
|
||||
type &= 0x7FFF;
|
||||
if(type == PCECD_Drive_IRQ_DATA_TRANSFER_DONE)
|
||||
_Port[0x3] &= ~0x20;
|
||||
else if(type == PCECD_Drive_IRQ_DATA_TRANSFER_READY)
|
||||
_Port[0x3] &= ~0x40;
|
||||
}
|
||||
else if(type == PCECD_Drive_IRQ_DATA_TRANSFER_DONE)
|
||||
{
|
||||
_Port[0x3] |= 0x20;
|
||||
}
|
||||
else if(type == PCECD_Drive_IRQ_DATA_TRANSFER_READY)
|
||||
{
|
||||
_Port[0x3] |= 0x40;
|
||||
}
|
||||
update_irq_state();
|
||||
}
|
||||
|
||||
static void UpdateADPCMIRQState(void)
|
||||
{
|
||||
_Port[0x3] &= ~0xC;
|
||||
|
||||
_Port[0x3] |= ADPCM.HalfReached ? 0x4 : 0x0;
|
||||
_Port[0x3] |= ADPCM.EndReached ? 0x8 : 0x0;
|
||||
|
||||
update_irq_state();
|
||||
}
|
||||
|
||||
static INLINE uint8 read_1808(int32 timestamp)
|
||||
{
|
||||
uint8 ret = PCECD_Drive_GetDB();
|
||||
|
||||
if(PCECD_Drive_GetREQ() && !PCECD_Drive_GetACK() && !PCECD_Drive_GetCD())
|
||||
{
|
||||
if(PCECD_Drive_GetIO())
|
||||
{
|
||||
PCECD_Drive_SetACK(TRUE);
|
||||
ACKStatus = TRUE;
|
||||
pcecd_drive_ne = PCECD_Drive_Run(timestamp);
|
||||
ClearACKDelay = 15 * 3;
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
bool PCECD_SetSettings(const PCECD_Settings *settings)
|
||||
{
|
||||
if(settings)
|
||||
{
|
||||
assert(settings->CDDA_Volume <= 2.0);
|
||||
assert(settings->ADPCM_Volume <= 2.0);
|
||||
}
|
||||
|
||||
CDDAVolumeSetting = settings ? settings->CDDA_Volume : 1.0;
|
||||
Fader_SyncWhich();
|
||||
|
||||
ADPCMSynth.volume(0.42735f * (settings ? settings->ADPCM_Volume : 1.0));
|
||||
ADPCMLP = settings ? settings->ADPCM_LPF : 0;
|
||||
|
||||
PCECD_Drive_SetTransferRate(126000 * (settings ? settings->CD_Speed : 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PCECD_Init(const PCECD_Settings *settings, void (*irqcb)(bool), double master_clock, unsigned int ocm, Blip_Buffer *soundbuf_l, Blip_Buffer *soundbuf_r)
|
||||
{
|
||||
lastts = 0;
|
||||
|
||||
OC_Multiplier = ocm;
|
||||
|
||||
IRQCB = irqcb;
|
||||
|
||||
sbuf[0] = soundbuf_l;
|
||||
sbuf[1] = soundbuf_r;
|
||||
|
||||
// Warning: magic number 126000 in PCECD_SetSettings() too
|
||||
PCECD_Drive_Init(3 * OC_Multiplier, sbuf[0], sbuf[1], 126000 * (settings ? settings->CD_Speed : 1), master_clock * OC_Multiplier, CDIRQ, StuffSubchannel);
|
||||
|
||||
if(!(ADPCM.RAM = (uint8 *)MDFN_malloc(0x10000, _("PCE ADPCM RAM"))))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
PCECD_SetSettings(settings);
|
||||
|
||||
ADPCM.bigdivacc = (int64)((double)master_clock * OC_Multiplier * 65536 / 32087.5);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
void PCECD_Close(void)
|
||||
{
|
||||
if(ADPCM.RAM)
|
||||
{
|
||||
MDFN_free(ADPCM.RAM);
|
||||
ADPCM.RAM = NULL;
|
||||
}
|
||||
PCECD_Drive_Close();
|
||||
}
|
||||
|
||||
|
||||
void PCECD_Power(uint32 timestamp)
|
||||
{
|
||||
if((int32)timestamp != lastts)
|
||||
(void)PCECD_Run(timestamp);
|
||||
|
||||
IRQCB(0);
|
||||
|
||||
PCECD_Drive_Power(timestamp);
|
||||
pcecd_drive_ne = 0x7fffffff;
|
||||
|
||||
bBRAMEnabled = FALSE;
|
||||
memset(_Port, 0, sizeof(_Port));
|
||||
ACKStatus = 0;
|
||||
ClearACKDelay = 0;
|
||||
|
||||
memset(ADPCM.RAM, 0x00, 65536);
|
||||
|
||||
ADPCM.ReadPending = ADPCM.WritePending = 0;
|
||||
ADPCM.ReadBuffer = 0;
|
||||
ADPCM.PlayBuffer = 0;
|
||||
|
||||
ADPCM.LastCmd = 0;
|
||||
MSM5205.SetSample(0x800);
|
||||
MSM5205.SetSSI(0);
|
||||
|
||||
ADPCM.SampleFreq = 0;
|
||||
ADPCM.LPF_SampleFreq = 0;
|
||||
ADPCM.bigdiv = ADPCM.bigdivacc * (16 - ADPCM.SampleFreq);
|
||||
RedoLPF(ADPCM.LPF_SampleFreq);
|
||||
|
||||
ADPCM.Addr = 0;
|
||||
ADPCM.ReadAddr = 0;
|
||||
ADPCM.WriteAddr = 0;
|
||||
ADPCM.LengthCount = 0;
|
||||
ADPCM.LastCmd = 0;
|
||||
|
||||
ADPCM.HalfReached = false;
|
||||
ADPCM.EndReached = false;
|
||||
ADPCM.Playing = false;
|
||||
ADPCM.PlayNibble = 0;
|
||||
|
||||
UpdateADPCMIRQState();
|
||||
|
||||
Fader.Command = 0x00;
|
||||
Fader.Volume = 0;
|
||||
Fader.CycleCounter = 0;
|
||||
Fader.CountValue = 0;
|
||||
Fader.Clocked = FALSE;
|
||||
}
|
||||
|
||||
bool PCECD_IsBRAMEnabled(void)
|
||||
{
|
||||
return bBRAMEnabled;
|
||||
}
|
||||
|
||||
uint8 PCECD_Read(uint32 timestamp, uint32 A)
|
||||
{
|
||||
uint8 ret = 0;
|
||||
|
||||
if((A & 0x18c0) == 0x18c0)
|
||||
{
|
||||
switch (A & 0x18cf)
|
||||
{
|
||||
case 0x18c1: ret = 0xaa; break;
|
||||
case 0x18c2: ret = 0x55; break;
|
||||
case 0x18c3: ret = 0x00; break;
|
||||
case 0x18c5: ret = 0xaa; break;
|
||||
case 0x18c6: ret = 0x55; break;
|
||||
case 0x18c7: ret = 0x03; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PCECD_Run(timestamp);
|
||||
|
||||
switch(A & 0xf)
|
||||
{
|
||||
case 0x0:
|
||||
ret = 0;
|
||||
ret |= PCECD_Drive_GetBSY() ? 0x80 : 0x00;
|
||||
ret |= PCECD_Drive_GetREQ() ? 0x40 : 0x00;
|
||||
ret |= PCECD_Drive_GetMSG() ? 0x20 : 0x00;
|
||||
ret |= PCECD_Drive_GetCD() ? 0x10 : 0x00;
|
||||
ret |= PCECD_Drive_GetIO() ? 0x08 : 0x00;
|
||||
break;
|
||||
|
||||
case 0x1: ret = PCECD_Drive_GetDB();
|
||||
break;
|
||||
|
||||
case 0x2: ret = _Port[2];
|
||||
break;
|
||||
|
||||
case 0x3: bBRAMEnabled = FALSE;
|
||||
|
||||
/* switch left/right of digitized cd playback */
|
||||
ret = _Port[0x3];
|
||||
_Port[0x3] ^= 2;
|
||||
break;
|
||||
|
||||
case 0x4: ret = _Port[4];
|
||||
break;
|
||||
|
||||
case 0x5: if(_Port[0x3] & 0x2)
|
||||
ret = RawPCMVolumeCache[1] & 0xff; // Right
|
||||
else
|
||||
ret = RawPCMVolumeCache[0] & 0xff; // Left
|
||||
break;
|
||||
|
||||
case 0x6: if(_Port[0x3] & 0x2)
|
||||
ret = ((uint16)RawPCMVolumeCache[1]) >> 8; // Right
|
||||
else
|
||||
ret = ((uint16)RawPCMVolumeCache[0]) >> 8; // Left
|
||||
break;
|
||||
|
||||
case 0x7:
|
||||
if(SubChannelFIFO.CanRead() > 0)
|
||||
ret = SubChannelFIFO.ReadByte();
|
||||
else
|
||||
ret = 0x00; // Not sure if it's 0, 0xFF, the last byte read, or something else.
|
||||
|
||||
if(SubChannelFIFO.CanRead() == 0)
|
||||
{
|
||||
_Port[0x3] &= ~0x10;
|
||||
update_irq_state();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
ret = read_1808(timestamp);
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
ADPCM_DEBUG("ReadBuffer\n");
|
||||
ADPCM.ReadPending = 19 * 3; //24 * 3;
|
||||
ret = ADPCM.ReadBuffer;
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
ret = _Port[0xb];
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
//printf("ADPCM Status Read: %d\n", timestamp);
|
||||
ret = 0x00;
|
||||
|
||||
ret |= (ADPCM.EndReached) ? 0x01 : 0x00;
|
||||
ret |= (ADPCM.Playing) ? 0x08 : 0x00;
|
||||
ret |= (ADPCM.WritePending > 0) ? 0x04 : 0x00;
|
||||
ret |= (ADPCM.ReadPending > 0) ? 0x80 : 0x00;
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
ret = ADPCM.LastCmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PCECD_DEBUG
|
||||
printf("Read: %04x %02x, %d\n", A, ret, timestamp);
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static INLINE void Fader_Run(const int32 clocks)
|
||||
{
|
||||
if(Fader.Clocked)
|
||||
{
|
||||
Fader.CycleCounter -= clocks;
|
||||
while(Fader.CycleCounter <= 0)
|
||||
{
|
||||
if(Fader.Volume)
|
||||
Fader.Volume--;
|
||||
|
||||
Fader_SyncWhich();
|
||||
|
||||
Fader.CycleCounter += Fader.CountValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PCECD_Write(uint32 timestamp, uint32 physAddr, uint8 data)
|
||||
{
|
||||
const uint8 V = data;
|
||||
|
||||
#ifdef PCECD_DEBUG
|
||||
printf("Write: (PC=%04x, t=%6d) %04x %02x; MSG: %d, REQ: %d, ACK: %d, CD: %d, IO: %d, BSY: %d, SEL: %d\n", HuCPU.PC, timestamp, physAddr, data, PCECD_Drive_GetMSG(), PCECD_Drive_GetREQ(), PCECD_Drive_GetACK(), PCECD_Drive_GetCD(), PCECD_Drive_GetIO(), PCECD_Drive_GetBSY(), PCECD_Drive_GetSEL());
|
||||
#endif
|
||||
|
||||
PCECD_Run(timestamp);
|
||||
|
||||
switch (physAddr & 0xf)
|
||||
{
|
||||
case 0x0:
|
||||
PCECD_Drive_SetSEL(1);
|
||||
PCECD_Drive_Run(timestamp);
|
||||
PCECD_Drive_SetSEL(0);
|
||||
pcecd_drive_ne = PCECD_Drive_Run(timestamp);
|
||||
|
||||
/* reset irq status */
|
||||
_Port[0x3] &= ~(0x20 | 0x40); // TODO: Confirm writing this register really reset these bits.
|
||||
update_irq_state();
|
||||
break;
|
||||
|
||||
case 0x1: // $1801
|
||||
_Port[1] = data;
|
||||
PCECD_Drive_SetDB(data);
|
||||
pcecd_drive_ne = PCECD_Drive_Run(timestamp);
|
||||
break;
|
||||
|
||||
case 0x2: // $1802
|
||||
#ifdef PCECD_DEBUG
|
||||
if(!(_Port[0x3] & _Port[2] & 0x40) && (_Port[0x3] & data & 0x40))
|
||||
puts("IRQ on waah 0x40");
|
||||
if(!(_Port[0x3] & _Port[2] & 0x20) && (_Port[0x3] & data & 0x20))
|
||||
puts("IRQ on waah 0x20");
|
||||
#endif
|
||||
|
||||
PCECD_Drive_SetACK(data & 0x80);
|
||||
pcecd_drive_ne = PCECD_Drive_Run(timestamp);
|
||||
_Port[2] = data;
|
||||
ACKStatus = (bool)(data & 0x80);
|
||||
update_irq_state();
|
||||
break;
|
||||
|
||||
case 0x3: // read only
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
PCECD_Drive_SetRST(data & 0x2);
|
||||
pcecd_drive_ne = PCECD_Drive_Run(timestamp);
|
||||
if(data & 0x2)
|
||||
{
|
||||
_Port[0x3] &= ~0x70;
|
||||
update_irq_state();
|
||||
}
|
||||
_Port[4] = data;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
{
|
||||
int16 left, right;
|
||||
PCECD_Drive_GetCDDAValues(left, right);
|
||||
RawPCMVolumeCache[0] = ((int64)abs(left) * CDDAFadeVolume) >> 16;
|
||||
RawPCMVolumeCache[1] = ((int64)abs(right) * CDDAFadeVolume) >> 16;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7: // $1807: D7=1 enables backup ram
|
||||
if (data & 0x80)
|
||||
{
|
||||
bBRAMEnabled = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8: // Set ADPCM address low
|
||||
if(ADPCM.LastCmd & 0x80)
|
||||
break;
|
||||
|
||||
ADPCM.Addr &= 0xFF00;
|
||||
ADPCM.Addr |= V;
|
||||
|
||||
ADPCM_DEBUG("SAL: %02x, %d\n", V, timestamp);
|
||||
|
||||
// Length appears to be constantly latched when D4 is set(tested on a real system)
|
||||
if(ADPCM.LastCmd & 0x10)
|
||||
{
|
||||
ADPCM_DEBUG("Set length(crazy way L): %04x\n", ADPCM.Addr);
|
||||
ADPCM.LengthCount = ADPCM.Addr;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x9: // Set ADPCM address high
|
||||
if(ADPCM.LastCmd & 0x80)
|
||||
break;
|
||||
|
||||
ADPCM.Addr &= 0x00FF;
|
||||
ADPCM.Addr |= V << 8;
|
||||
|
||||
ADPCM_DEBUG("SAH: %02x, %d\n", V, timestamp);
|
||||
|
||||
// Length appears to be constantly latched when D4 is set(tested on a real system)
|
||||
if(ADPCM.LastCmd & 0x10)
|
||||
{
|
||||
ADPCM_DEBUG("Set length(crazy way H): %04x\n", ADPCM.Addr);
|
||||
ADPCM.LengthCount = ADPCM.Addr;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
//ADPCM_DEBUG("Write: %02x, %d\n", V, timestamp);
|
||||
ADPCM.WritePending = 3 * 11;
|
||||
ADPCM.WritePendingValue = data;
|
||||
break;
|
||||
|
||||
case 0xb: // adpcm dma
|
||||
ADPCM_DEBUG("DMA: %02x\n", V);
|
||||
_Port[0xb] = data;
|
||||
break;
|
||||
|
||||
case 0xc: // read-only
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
ADPCM_DEBUG("Write180D: %02x\n", V);
|
||||
if(data & 0x80)
|
||||
{
|
||||
ADPCM.Addr = 0;
|
||||
ADPCM.ReadAddr = 0;
|
||||
ADPCM.WriteAddr = 0;
|
||||
ADPCM.LengthCount = 0;
|
||||
ADPCM.LastCmd = 0;
|
||||
|
||||
ADPCM.Playing = false;
|
||||
ADPCM.HalfReached = false;
|
||||
ADPCM.EndReached = false;
|
||||
|
||||
ADPCM.PlayNibble = 0;
|
||||
|
||||
UpdateADPCMIRQState();
|
||||
|
||||
MSM5205.SetSample(0x800);
|
||||
MSM5205.SetSSI(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if(ADPCM.Playing && !(data & 0x20))
|
||||
ADPCM.Playing = false;
|
||||
|
||||
if(!ADPCM.Playing && (data & 0x20))
|
||||
{
|
||||
ADPCM.bigdiv = ADPCM.bigdivacc * (16 - ADPCM.SampleFreq);
|
||||
ADPCM.Playing = true;
|
||||
ADPCM.HalfReached = false; // Not sure about this.
|
||||
ADPCM.PlayNibble = 0;
|
||||
MSM5205.SetSample(0x800);
|
||||
MSM5205.SetSSI(0);
|
||||
}
|
||||
|
||||
// Length appears to be constantly latched when D4 is set(tested on a real system)
|
||||
if(data & 0x10)
|
||||
{
|
||||
ADPCM_DEBUG("Set length: %04x\n", ADPCM.Addr);
|
||||
ADPCM.LengthCount = ADPCM.Addr;
|
||||
ADPCM.EndReached = false;
|
||||
}
|
||||
|
||||
// D2 and D3 control read address
|
||||
if(!(ADPCM.LastCmd & 0x8) && (data & 0x08))
|
||||
{
|
||||
if(data & 0x4)
|
||||
ADPCM.ReadAddr = ADPCM.Addr;
|
||||
else
|
||||
ADPCM.ReadAddr = (ADPCM.Addr - 1) & 0xFFFF;
|
||||
|
||||
ADPCM_DEBUG("Set ReadAddr: %04x, %06x\n", ADPCM.Addr, ADPCM.ReadAddr);
|
||||
}
|
||||
|
||||
// D0 and D1 control write address
|
||||
if(!(ADPCM.LastCmd & 0x2) && (data & 0x2))
|
||||
{
|
||||
ADPCM.WriteAddr = ADPCM.Addr;
|
||||
if(!(data & 0x1))
|
||||
ADPCM.WriteAddr = (ADPCM.WriteAddr - 1) & 0xFFFF;
|
||||
ADPCM_DEBUG("Set WriteAddr: %04x, %06x\n", ADPCM.Addr, ADPCM.WriteAddr);
|
||||
}
|
||||
ADPCM.LastCmd = data;
|
||||
UpdateADPCMIRQState();
|
||||
break;
|
||||
|
||||
case 0xe: // Set ADPCM playback rate
|
||||
{
|
||||
uint8 freq = V & 0x0F;
|
||||
|
||||
ADPCM.SampleFreq = freq;
|
||||
|
||||
ADPCM_DEBUG("Freq: %02x\n", freq);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xf:
|
||||
Fader.Command = V;
|
||||
|
||||
#ifdef PCECD_DEBUG
|
||||
printf("Fade: %02x\n", data);
|
||||
#endif
|
||||
|
||||
// Cancel fade
|
||||
if(!(V & 0x8))
|
||||
{
|
||||
Fader.Volume = 65536;
|
||||
Fader.CycleCounter = 0;
|
||||
Fader.CountValue = 0;
|
||||
Fader.Clocked = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fader.CountValue = OC_Multiplier * 3 * ((V & 0x4) ? 273 : 655); // 2.500s : 6.000s;
|
||||
|
||||
if(!Fader.Clocked)
|
||||
Fader.CycleCounter = Fader.CountValue;
|
||||
|
||||
Fader.Clocked = TRUE;
|
||||
}
|
||||
Fader_SyncWhich();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void ADPCM_PB_Run(int32 basetime, int32 run_time)
|
||||
{
|
||||
ADPCM.bigdiv -= run_time * 65536;
|
||||
|
||||
while(ADPCM.bigdiv <= 0)
|
||||
{
|
||||
ADPCM.bigdiv += ADPCM.bigdivacc * (16 - ADPCM.SampleFreq);
|
||||
|
||||
if(ADPCM.Playing && !ADPCM.PlayNibble) // Do playback sample buffer fetch.
|
||||
{
|
||||
ADPCM.HalfReached = (ADPCM.LengthCount < 32768);
|
||||
if(!ADPCM.LengthCount && !(ADPCM.LastCmd & 0x10))
|
||||
{
|
||||
if(ADPCM.EndReached)
|
||||
ADPCM.HalfReached = false;
|
||||
|
||||
ADPCM.EndReached = true;
|
||||
|
||||
if(ADPCM.LastCmd & 0x40)
|
||||
ADPCM.Playing = false;
|
||||
}
|
||||
|
||||
ADPCM.PlayBuffer = ADPCM.RAM[ADPCM.ReadAddr];
|
||||
ADPCM.ReadAddr = (ADPCM.ReadAddr + 1) & 0xFFFF;
|
||||
|
||||
if(ADPCM.LengthCount && !(ADPCM.LastCmd & 0x10))
|
||||
ADPCM.LengthCount--;
|
||||
}
|
||||
|
||||
if(ADPCM.Playing)
|
||||
{
|
||||
int32 pcm;
|
||||
uint8 nibble;
|
||||
|
||||
nibble = (ADPCM.PlayBuffer >> (ADPCM.PlayNibble ^ 4)) & 0x0F;
|
||||
pcm = MSM5205.Decode(nibble) - 2048;
|
||||
|
||||
ADPCM.PlayNibble ^= 4;
|
||||
|
||||
pcm = (pcm * ADPCMFadeVolume) >> 8;
|
||||
uint32 synthtime = ((basetime + (ADPCM.bigdiv >> 16))) / (3 * OC_Multiplier);
|
||||
|
||||
if(sbuf[0] && sbuf[1])
|
||||
{
|
||||
ADPCMSynth.offset(synthtime, pcm - ADPCM.last_pcm, sbuf[0]);
|
||||
ADPCMSynth.offset(synthtime, pcm - ADPCM.last_pcm, sbuf[1]);
|
||||
}
|
||||
ADPCM.last_pcm = pcm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void ADPCM_Run(const int32 clocks, const int32 timestamp)
|
||||
{
|
||||
//printf("ADPCM Run: %d\n", clocks);
|
||||
ADPCM_PB_Run(timestamp, clocks);
|
||||
|
||||
if(ADPCM.WritePending)
|
||||
{
|
||||
ADPCM.WritePending -= clocks;
|
||||
if(ADPCM.WritePending <= 0)
|
||||
{
|
||||
ADPCM.HalfReached = (ADPCM.LengthCount < 32768);
|
||||
if(!(ADPCM.LastCmd & 0x10) && ADPCM.LengthCount < 0xFFFF)
|
||||
ADPCM.LengthCount++;
|
||||
|
||||
ADPCM.RAM[ADPCM.WriteAddr++] = ADPCM.WritePendingValue;
|
||||
ADPCM.WritePending = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ADPCM.WritePending)
|
||||
{
|
||||
if(_Port[0xb] & 0x3)
|
||||
{
|
||||
// Run PCECD_Drive before we examine the signals.
|
||||
pcecd_drive_ne = PCECD_Drive_Run(timestamp);
|
||||
|
||||
if(!PCECD_Drive_GetCD() && PCECD_Drive_GetIO() && PCECD_Drive_GetREQ() && !PCECD_Drive_GetACK())
|
||||
{
|
||||
ADPCM.WritePendingValue = read_1808(timestamp);
|
||||
ADPCM.WritePending = 10 * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ADPCM.ReadPending)
|
||||
{
|
||||
ADPCM.ReadPending -= clocks;
|
||||
if(ADPCM.ReadPending <= 0)
|
||||
{
|
||||
ADPCM.ReadBuffer = ADPCM.RAM[ADPCM.ReadAddr];
|
||||
ADPCM.ReadAddr = (ADPCM.ReadAddr + 1) & 0xFFFF;
|
||||
ADPCM.ReadPending = 0;
|
||||
|
||||
ADPCM.HalfReached = (ADPCM.LengthCount < 32768);
|
||||
if(!(ADPCM.LastCmd & 0x10))
|
||||
{
|
||||
if(ADPCM.LengthCount)
|
||||
ADPCM.LengthCount--;
|
||||
else
|
||||
{
|
||||
ADPCM.EndReached = true;
|
||||
ADPCM.HalfReached = false;
|
||||
|
||||
if(ADPCM.LastCmd & 0x40)
|
||||
ADPCM.Playing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateADPCMIRQState();
|
||||
}
|
||||
|
||||
void PCECD_Run(uint32 in_timestamp)
|
||||
{
|
||||
int32 clocks = in_timestamp - lastts;
|
||||
int32 running_ts = lastts;
|
||||
|
||||
//printf("Run Begin: Clocks=%d(%d - %d), cl=%d\n", clocks, in_timestamp, lastts, CalcNextEvent);
|
||||
//fflush(stdout);
|
||||
|
||||
while(clocks > 0)
|
||||
{
|
||||
int32 chunk_clocks = CalcNextEvent(clocks);
|
||||
|
||||
running_ts += chunk_clocks;
|
||||
|
||||
if(ClearACKDelay > 0)
|
||||
{
|
||||
ClearACKDelay -= chunk_clocks;
|
||||
if(ClearACKDelay <= 0)
|
||||
{
|
||||
ACKStatus = FALSE;
|
||||
PCECD_Drive_SetACK(FALSE);
|
||||
PCECD_Drive_Run(running_ts);
|
||||
if(PCECD_Drive_GetCD())
|
||||
{
|
||||
_Port[0xb] &= ~1;
|
||||
#ifdef PCECD_DEBUG
|
||||
puts("DMA End");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fader_Run(chunk_clocks);
|
||||
|
||||
ADPCM_Run(chunk_clocks, running_ts);
|
||||
pcecd_drive_ne = PCECD_Drive_Run(running_ts);
|
||||
|
||||
clocks -= chunk_clocks;
|
||||
}
|
||||
|
||||
lastts = in_timestamp;
|
||||
}
|
||||
|
||||
void PCECD_ResetTS(void)
|
||||
{
|
||||
if(ADPCM.SampleFreq != ADPCM.LPF_SampleFreq)
|
||||
{
|
||||
ADPCM.LPF_SampleFreq = ADPCM.SampleFreq;
|
||||
RedoLPF(ADPCM.LPF_SampleFreq);
|
||||
}
|
||||
PCECD_Drive_ResetTS();
|
||||
lastts = 0;
|
||||
}
|
||||
|
||||
static int ADPCM_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
uint32 ad_sample = MSM5205.GetSample();
|
||||
int32 ad_ref_index = MSM5205.GetSSI();
|
||||
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY(ADPCM.RAM, 0x10000),
|
||||
|
||||
SFVAR(ADPCM.bigdiv),
|
||||
SFVAR(ADPCM.Addr),
|
||||
SFVAR(ADPCM.ReadAddr),
|
||||
SFVAR(ADPCM.WriteAddr),
|
||||
SFVAR(ADPCM.LengthCount),
|
||||
SFVAR(ADPCM.LastCmd),
|
||||
SFVAR(ADPCM.SampleFreq),
|
||||
|
||||
SFVAR(ADPCM.ReadPending),
|
||||
SFVAR(ADPCM.ReadBuffer),
|
||||
SFVAR(ADPCM.PlayBuffer),
|
||||
|
||||
SFVAR(ADPCM.WritePending),
|
||||
SFVAR(ADPCM.WritePendingValue),
|
||||
|
||||
SFVAR(ADPCM.HalfReached),
|
||||
SFVAR(ADPCM.EndReached),
|
||||
SFVAR(ADPCM.Playing),
|
||||
|
||||
SFVAR(ADPCM.PlayNibble),
|
||||
|
||||
SFVAR(ad_sample),
|
||||
SFVAR(ad_ref_index),
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "APCM");
|
||||
if(load)
|
||||
{
|
||||
MSM5205.SetSample(ad_sample);
|
||||
MSM5205.SetSSI(ad_ref_index);
|
||||
RedoLPF(ADPCM.SampleFreq);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int PCECD_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(bBRAMEnabled),
|
||||
SFVAR(ACKStatus),
|
||||
SFVAR(ClearACKDelay),
|
||||
SFARRAY16(RawPCMVolumeCache, 2),
|
||||
SFARRAY(_Port, sizeof(_Port)),
|
||||
|
||||
SFVAR(Fader.Command),
|
||||
SFVAR(Fader.Volume),
|
||||
SFVAR(Fader.CycleCounter),
|
||||
SFVAR(Fader.CountValue),
|
||||
SFVAR(Fader.Clocked),
|
||||
|
||||
SFARRAY(&SubChannelFIFO.data[0], SubChannelFIFO.data.size()),
|
||||
SFVAR(SubChannelFIFO.read_pos),
|
||||
SFVAR(SubChannelFIFO.write_pos),
|
||||
SFVAR(SubChannelFIFO.in_count),
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "PECD");
|
||||
ret &= PCECD_Drive_StateAction(sm, load, data_only, "CDRM");
|
||||
ret &= ADPCM_StateAction(sm, load, data_only);
|
||||
|
||||
if(load)
|
||||
{
|
||||
Fader_SyncWhich();
|
||||
//PCECD_Drive_SetDB(_Port[1]);
|
||||
PCECD_Drive_SetACK(ACKStatus);
|
||||
PCECD_Drive_SetRST(_Port[4] & 0x2);
|
||||
|
||||
SubChannelFIFO.read_pos %= SubChannelFIFO.size;
|
||||
SubChannelFIFO.write_pos %= SubChannelFIFO.size;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
37
mednafen/pce_fast-09333/pcecd.h
Normal file
37
mednafen/pce_fast-09333/pcecd.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef __PCE_CDROM_H
|
||||
#define __PCE_CDROM_H
|
||||
|
||||
#include <blip/Blip_Buffer.h>
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float CDDA_Volume; // Max 2.000...
|
||||
float ADPCM_Volume; // Max 2.000...
|
||||
|
||||
unsigned int CD_Speed;
|
||||
|
||||
bool ADPCM_LPF;
|
||||
} PCECD_Settings;
|
||||
|
||||
void PCECD_Run(uint32 in_timestamp);
|
||||
void PCECD_ResetTS(void);
|
||||
|
||||
bool PCECD_Init(const PCECD_Settings *settings, void (*irqcb)(bool), double master_clock, unsigned int ocm, Blip_Buffer *soundbuf_l, Blip_Buffer *soundbuf_r) MDFN_COLD;
|
||||
bool PCECD_SetSettings(const PCECD_Settings *settings) MDFN_COLD;
|
||||
void PCECD_Close(void) MDFN_COLD;
|
||||
void PCECD_Power(uint32 timestamp) MDFN_COLD;
|
||||
|
||||
|
||||
uint8 PCECD_Read(uint32 timestamp, uint32);
|
||||
void PCECD_Write(uint32 timestamp, uint32, uint8 data);
|
||||
|
||||
bool PCECD_IsBRAMEnabled(void);
|
||||
|
||||
int PCECD_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
1367
mednafen/pce_fast-09333/pcecd_drive.cpp
Normal file
1367
mednafen/pce_fast-09333/pcecd_drive.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
mednafen/pce_fast-09333/pcecd_drive.h
Normal file
89
mednafen/pce_fast-09333/pcecd_drive.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef __PCEFAST_PCECD_Drive_H
|
||||
#define __PCEFAST_PCECD_Drive_H
|
||||
|
||||
#include <blip/Blip_Buffer.h>
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
typedef int32 pcecd_drive_timestamp_t;
|
||||
|
||||
struct pcecd_drive_bus_t
|
||||
{
|
||||
// Data bus(FIXME: we should have a variable for the target and the initiator, and OR them together to be truly accurate).
|
||||
uint8 DB;
|
||||
|
||||
uint32 signals;
|
||||
};
|
||||
|
||||
extern pcecd_drive_bus_t cd_bus; // Don't access this structure directly by name outside of pcecd_drive.c, but use the macros below.
|
||||
|
||||
// Signals under our(the "target") control.
|
||||
#define PCECD_Drive_IO_mask 0x001
|
||||
#define PCECD_Drive_CD_mask 0x002
|
||||
#define PCECD_Drive_MSG_mask 0x004
|
||||
#define PCECD_Drive_REQ_mask 0x008
|
||||
#define PCECD_Drive_BSY_mask 0x010
|
||||
|
||||
// Signals under the control of the initiator(not us!)
|
||||
#define PCECD_Drive_kingRST_mask 0x020
|
||||
#define PCECD_Drive_kingACK_mask 0x040
|
||||
#define PCECD_Drive_kingSEL_mask 0x100
|
||||
|
||||
#define BSY_signal ((const bool)(cd_bus.signals & PCECD_Drive_BSY_mask))
|
||||
#define ACK_signal ((const bool)(cd_bus.signals & PCECD_Drive_kingACK_mask))
|
||||
#define RST_signal ((const bool)(cd_bus.signals & PCECD_Drive_kingRST_mask))
|
||||
#define MSG_signal ((const bool)(cd_bus.signals & PCECD_Drive_MSG_mask))
|
||||
#define SEL_signal ((const bool)(cd_bus.signals & PCECD_Drive_kingSEL_mask))
|
||||
#define REQ_signal ((const bool)(cd_bus.signals & PCECD_Drive_REQ_mask))
|
||||
#define IO_signal ((const bool)(cd_bus.signals & PCECD_Drive_IO_mask))
|
||||
#define CD_signal ((const bool)(cd_bus.signals & PCECD_Drive_CD_mask))
|
||||
|
||||
#define DB_signal ((const uint8)cd_bus.DB)
|
||||
|
||||
#define PCECD_Drive_GetDB() DB_signal
|
||||
#define PCECD_Drive_GetBSY() BSY_signal
|
||||
#define PCECD_Drive_GetIO() IO_signal
|
||||
#define PCECD_Drive_GetCD() CD_signal
|
||||
#define PCECD_Drive_GetMSG() MSG_signal
|
||||
#define PCECD_Drive_GetREQ() REQ_signal
|
||||
|
||||
// Should we phase out getting these initiator-driven signals like this(the initiator really should keep track of them itself)?
|
||||
#define PCECD_Drive_GetACK() ACK_signal
|
||||
#define PCECD_Drive_GetRST() RST_signal
|
||||
#define PCECD_Drive_GetSEL() SEL_signal
|
||||
|
||||
void PCECD_Drive_Power(pcecd_drive_timestamp_t system_timestamp);
|
||||
void PCECD_Drive_SetDB(uint8 data);
|
||||
|
||||
// These PCECD_Drive_Set* functions are kind of misnomers, at least in comparison to the PCECD_Drive_Get* functions...
|
||||
// They will set/clear the bits corresponding to the KING's side of the bus.
|
||||
void PCECD_Drive_SetACK(bool set);
|
||||
void PCECD_Drive_SetSEL(bool set);
|
||||
void PCECD_Drive_SetRST(bool set);
|
||||
|
||||
uint32 PCECD_Drive_Run(pcecd_drive_timestamp_t);
|
||||
void PCECD_Drive_ResetTS(void);
|
||||
|
||||
enum
|
||||
{
|
||||
PCECD_Drive_IRQ_DATA_TRANSFER_DONE = 1,
|
||||
PCECD_Drive_IRQ_DATA_TRANSFER_READY,
|
||||
PCECD_Drive_IRQ_MAGICAL_REQ,
|
||||
};
|
||||
|
||||
void PCECD_Drive_GetCDDAValues(int16 &left, int16 &right);
|
||||
|
||||
void PCECD_Drive_SetLog(void (*logfunc)(const char *, const char *, ...)) MDFN_COLD;
|
||||
void PCECD_Drive_Init(int CDDATimeDiv, Blip_Buffer *leftbuf, Blip_Buffer *rightbuf, uint32 TransferRate, uint32 SystemClock, void (*IRQFunc)(int), void (*SSCFunc)(uint8, int)) MDFN_COLD;
|
||||
void PCECD_Drive_Close(void) MDFN_COLD;
|
||||
|
||||
void PCECD_Drive_SetTransferRate(uint32 TransferRate);
|
||||
void PCECD_Drive_SetCDDAVolume(unsigned vol); // vol of 65536 = 1.0 = maximum.
|
||||
int PCECD_Drive_StateAction(StateMem *sm, int load, int data_only, const char *sname);
|
||||
|
||||
void PCECD_Drive_SetDisc(bool tray_open, CDIF *cdif, bool no_emu_side_effects = false) MDFN_COLD;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
677
mednafen/pce_fast-09333/psg.cpp
Normal file
677
mednafen/pce_fast-09333/psg.cpp
Normal file
@ -0,0 +1,677 @@
|
||||
/* 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 "../mednafen.h"
|
||||
#include "psg.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <trio/trio.h>
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
void PCEFast_PSG::SetVolume(double new_volume)
|
||||
{
|
||||
OutputVolume = new_volume;
|
||||
|
||||
Synth.volume(OutputVolume / 6);
|
||||
}
|
||||
|
||||
void PCEFast_PSG::UpdateOutput_Norm(const int32 timestamp, psg_channel *ch)
|
||||
{
|
||||
int32 samp[2];
|
||||
int sv = ch->dda;
|
||||
|
||||
samp[0] = dbtable[ch->vl[0]][sv];
|
||||
samp[1] = dbtable[ch->vl[1]][sv];
|
||||
|
||||
Synth.offset_inline(timestamp, samp[0] - ch->blip_prev_samp[0], sbuf[0]);
|
||||
Synth.offset_inline(timestamp, samp[1] - ch->blip_prev_samp[1], sbuf[1]);
|
||||
|
||||
ch->blip_prev_samp[0] = samp[0];
|
||||
ch->blip_prev_samp[1] = samp[1];
|
||||
}
|
||||
|
||||
void PCEFast_PSG::UpdateOutput_Noise(const int32 timestamp, psg_channel *ch)
|
||||
{
|
||||
int32 samp[2];
|
||||
int sv = ((ch->lfsr & 1) << 5) - (ch->lfsr & 1); //(ch->lfsr & 0x1) ? 0x1F : 0;
|
||||
|
||||
samp[0] = dbtable[ch->vl[0]][sv];
|
||||
samp[1] = dbtable[ch->vl[1]][sv];
|
||||
|
||||
Synth.offset_inline(timestamp, samp[0] - ch->blip_prev_samp[0], sbuf[0]);
|
||||
Synth.offset_inline(timestamp, samp[1] - ch->blip_prev_samp[1], sbuf[1]);
|
||||
|
||||
ch->blip_prev_samp[0] = samp[0];
|
||||
ch->blip_prev_samp[1] = samp[1];
|
||||
}
|
||||
|
||||
void PCEFast_PSG::UpdateOutput_Off(const int32 timestamp, psg_channel *ch)
|
||||
{
|
||||
int32 samp[2];
|
||||
|
||||
samp[0] = samp[1] = 0;
|
||||
|
||||
Synth.offset_inline(timestamp, samp[0] - ch->blip_prev_samp[0], sbuf[0]);
|
||||
Synth.offset_inline(timestamp, samp[1] - ch->blip_prev_samp[1], sbuf[1]);
|
||||
|
||||
ch->blip_prev_samp[0] = samp[0];
|
||||
ch->blip_prev_samp[1] = samp[1];
|
||||
}
|
||||
|
||||
|
||||
void PCEFast_PSG::UpdateOutput_Accum(const int32 timestamp, psg_channel *ch)
|
||||
{
|
||||
int32 samp[2];
|
||||
|
||||
samp[0] = ((int32)dbtable_volonly[ch->vl[0]] * ((int32)ch->samp_accum - 496)) >> (8 + 5);
|
||||
samp[1] = ((int32)dbtable_volonly[ch->vl[1]] * ((int32)ch->samp_accum - 496)) >> (8 + 5);
|
||||
|
||||
Synth.offset_inline(timestamp, samp[0] - ch->blip_prev_samp[0], sbuf[0]);
|
||||
Synth.offset_inline(timestamp, samp[1] - ch->blip_prev_samp[1], sbuf[1]);
|
||||
|
||||
ch->blip_prev_samp[0] = samp[0];
|
||||
ch->blip_prev_samp[1] = samp[1];
|
||||
}
|
||||
|
||||
// This function should always be called after RecalcFreqCache() (it's not called from RecalcFreqCache to avoid redundant code)
|
||||
void PCEFast_PSG::RecalcUOFunc(int chnum)
|
||||
{
|
||||
psg_channel *ch = &channel[chnum];
|
||||
|
||||
//printf("UO Update: %d, %02x\n", chnum, ch->control);
|
||||
|
||||
if(!(ch->control & 0xC0))
|
||||
ch->UpdateOutput = &PCEFast_PSG::UpdateOutput_Off;
|
||||
else if(ch->noisectrl & ch->control & 0x80)
|
||||
ch->UpdateOutput = &PCEFast_PSG::UpdateOutput_Noise;
|
||||
// If the control for the channel is in waveform play mode, and the (real) playback frequency is too high, and the channel is either not the LFO modulator channel or
|
||||
// if the LFO trigger bit(which halts the LFO modulator channel's waveform incrementing when set) is clear
|
||||
else if((ch->control & 0xC0) == 0x80 && ch->freq_cache <= 0xA && (chnum != 1 || !(lfoctrl & 0x80)) )
|
||||
ch->UpdateOutput = &PCEFast_PSG::UpdateOutput_Accum;
|
||||
else
|
||||
ch->UpdateOutput = &PCEFast_PSG::UpdateOutput_Norm;
|
||||
}
|
||||
|
||||
|
||||
void PCEFast_PSG::RecalcFreqCache(int chnum)
|
||||
{
|
||||
psg_channel *ch = &channel[chnum];
|
||||
|
||||
if(chnum == 0 && (lfoctrl & 0x03))
|
||||
{
|
||||
const uint32 shift = (((lfoctrl & 0x3) - 1) << 1);
|
||||
uint8 la = channel[1].dda;
|
||||
int32 tmp_freq = ((int32)ch->frequency + ((la - 0x10) << shift)) & 0xFFF;
|
||||
|
||||
ch->freq_cache = (tmp_freq ? tmp_freq : 4096) << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->freq_cache = (ch->frequency ? ch->frequency : 4096) << 1;
|
||||
|
||||
if(chnum == 1 && (lfoctrl & 0x03))
|
||||
ch->freq_cache *= lfofreq ? lfofreq : 256;
|
||||
}
|
||||
}
|
||||
|
||||
void PCEFast_PSG::RecalcNoiseFreqCache(int chnum)
|
||||
{
|
||||
psg_channel *ch = &channel[chnum];
|
||||
int32 freq = 0x1F - (ch->noisectrl & 0x1F);
|
||||
|
||||
if(!freq)
|
||||
freq = 0x20;
|
||||
else
|
||||
freq <<= 6;
|
||||
|
||||
freq <<= 1;
|
||||
|
||||
ch->noise_freq_cache = freq;
|
||||
}
|
||||
|
||||
PCEFast_PSG::PCEFast_PSG(Blip_Buffer *bb_l, Blip_Buffer *bb_r)
|
||||
{
|
||||
//printf("Test: %u, %u\n", sizeof(psg_channel), (uint8*)&channel[0].balance - (uint8*)&channel[0].waveform[0]);
|
||||
Synth.treble_eq(-2.0);
|
||||
|
||||
sbuf[0] = bb_l;
|
||||
sbuf[1] = bb_r;
|
||||
|
||||
lastts = 0;
|
||||
for(int ch = 0; ch < 6; ch++)
|
||||
{
|
||||
channel[ch].blip_prev_samp[0] = 0;
|
||||
channel[ch].blip_prev_samp[1] = 0;
|
||||
channel[ch].lastts = 0;
|
||||
}
|
||||
|
||||
SetVolume(1.0);
|
||||
|
||||
for(int vl = 0; vl < 32; vl++)
|
||||
{
|
||||
double flub = 1;
|
||||
|
||||
if(vl)
|
||||
flub /= pow(2, (double)1 / 4 * vl); // ~1.5dB reduction per increment of vl
|
||||
|
||||
if(vl == 0x1F)
|
||||
flub = 0;
|
||||
|
||||
for(int samp = 0; samp < 32; samp++)
|
||||
{
|
||||
int eff_samp = samp * 2 - 0x1F;
|
||||
|
||||
dbtable[vl][samp] = (int32)(flub * eff_samp * 128);
|
||||
dbtable_volonly[vl] = (int32)(flub * 65536);
|
||||
}
|
||||
}
|
||||
|
||||
Power(0);
|
||||
}
|
||||
|
||||
PCEFast_PSG::~PCEFast_PSG()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
int32 PCEFast_PSG::GetVL(const int chnum, const int lr)
|
||||
{
|
||||
// Note: Changing the 0x1F(not that there should be) would require changing the channel pseudo-off volume check logic later on.
|
||||
static const uint8 scale_tab[] =
|
||||
{
|
||||
0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
|
||||
0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F
|
||||
};
|
||||
|
||||
psg_channel *ch = &channel[chnum];
|
||||
|
||||
const int gbal = 0x1F - scale_tab[(globalbalance >> (lr ? 0 : 4)) & 0xF];
|
||||
const int bal = 0x1F - scale_tab[(ch->balance >> (lr ? 0 : 4)) & 0xF];
|
||||
const int al = 0x1F - (ch->control & 0x1F);
|
||||
int vol_reduction;
|
||||
|
||||
vol_reduction = gbal + bal + al;
|
||||
|
||||
if(vol_reduction > 0x1F)
|
||||
vol_reduction = 0x1F;
|
||||
|
||||
return(vol_reduction);
|
||||
}
|
||||
|
||||
void PCEFast_PSG::Write(int32 timestamp, uint8 A, uint8 V)
|
||||
{
|
||||
A &= 0x0F;
|
||||
|
||||
if(A == 0x00)
|
||||
{
|
||||
select = (V & 0x07);
|
||||
return;
|
||||
}
|
||||
|
||||
Update(timestamp);
|
||||
|
||||
psg_channel *ch = &channel[select];
|
||||
|
||||
//if(A == 0x01 || select == 5)
|
||||
// printf("Write Ch: %d %04x %02x, %d\n", select, A, V, timestamp);
|
||||
|
||||
switch(A)
|
||||
{
|
||||
default: break;
|
||||
|
||||
case 0x01: /* Global sound balance */
|
||||
globalbalance = V;
|
||||
vol_pending = true;
|
||||
break;
|
||||
|
||||
case 0x02: /* Channel frequency (LSB) */
|
||||
if(select > 5) return; // no more than 6 channels, silly game.
|
||||
|
||||
ch->frequency = (ch->frequency & 0x0F00) | V;
|
||||
RecalcFreqCache(select);
|
||||
RecalcUOFunc(select);
|
||||
break;
|
||||
|
||||
case 0x03: /* Channel frequency (MSB) */
|
||||
if(select > 5) return; // no more than 6 channels, silly game.
|
||||
|
||||
ch->frequency = (ch->frequency & 0x00FF) | ((V & 0x0F) << 8);
|
||||
RecalcFreqCache(select);
|
||||
RecalcUOFunc(select);
|
||||
break;
|
||||
|
||||
case 0x04: /* Channel enable, DDA, volume */
|
||||
if(select > 5) return; // no more than 6 channels, silly game.
|
||||
|
||||
if((ch->control & 0x40) && !(V & 0x40))
|
||||
{
|
||||
ch->waveform_index = 0;
|
||||
ch->dda = ch->waveform[ch->waveform_index];
|
||||
ch->counter = ch->freq_cache;
|
||||
}
|
||||
|
||||
if(!(ch->control & 0x80) && (V & 0x80))
|
||||
{
|
||||
if(!(V & 0x40))
|
||||
{
|
||||
ch->waveform_index = (ch->waveform_index + 1) & 0x1F;
|
||||
ch->dda = ch->waveform[ch->waveform_index];
|
||||
}
|
||||
}
|
||||
|
||||
ch->control = V;
|
||||
RecalcFreqCache(select);
|
||||
RecalcUOFunc(select);
|
||||
|
||||
vol_pending = true;
|
||||
break;
|
||||
|
||||
case 0x05: /* Channel balance */
|
||||
if(select > 5) return; // no more than 6 channels, silly game.
|
||||
ch->balance = V;
|
||||
|
||||
vol_pending = true;
|
||||
break;
|
||||
|
||||
case 0x06: /* Channel waveform data */
|
||||
if(select > 5) return; // no more than 6 channels, silly game.
|
||||
V &= 0x1F;
|
||||
|
||||
if(!(ch->control & 0x40))
|
||||
{
|
||||
ch->samp_accum -= ch->waveform[ch->waveform_index];
|
||||
ch->waveform[ch->waveform_index] = V;
|
||||
ch->samp_accum += ch->waveform[ch->waveform_index];
|
||||
}
|
||||
|
||||
if((ch->control & 0xC0) == 0x00)
|
||||
ch->waveform_index = ((ch->waveform_index + 1) & 0x1F);
|
||||
|
||||
if(ch->control & 0x80)
|
||||
{
|
||||
// According to my tests(on SuperGrafx), writing to this channel
|
||||
// will update the waveform value cache/latch regardless of DDA mode being enabled.
|
||||
ch->dda = V;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x07: /* Noise enable and frequency */
|
||||
if(select > 5) return; // no more than 6 channels, silly game.
|
||||
if(select >= 4)
|
||||
{
|
||||
ch->noisectrl = V;
|
||||
RecalcNoiseFreqCache(select);
|
||||
RecalcUOFunc(select);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08: /* LFO frequency */
|
||||
lfofreq = V & 0xFF;
|
||||
//printf("LFO Freq: %02x\n", V);
|
||||
break;
|
||||
|
||||
case 0x09: /* LFO trigger and control */
|
||||
//printf("LFO Ctrl: %02x\n", V);
|
||||
if(V & 0x80)
|
||||
{
|
||||
channel[1].waveform_index = 0;
|
||||
channel[1].dda = channel[1].waveform[channel[1].waveform_index];
|
||||
channel[1].counter = channel[1].freq_cache;
|
||||
}
|
||||
lfoctrl = V;
|
||||
RecalcFreqCache(0);
|
||||
RecalcUOFunc(0);
|
||||
RecalcFreqCache(1);
|
||||
RecalcUOFunc(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't use INLINE, which has always_inline in it, due to gcc's inability to cope with the type of recursion
|
||||
// used in this function.
|
||||
template<bool LFO_On>
|
||||
void PCEFast_PSG::RunChannel(int chc, int32 timestamp)
|
||||
{
|
||||
psg_channel *ch = &channel[chc];
|
||||
int32 running_timestamp = ch->lastts;
|
||||
int32 run_time = timestamp - ch->lastts;
|
||||
|
||||
ch->lastts = timestamp;
|
||||
|
||||
if(!run_time)
|
||||
return;
|
||||
|
||||
(this->*ch->UpdateOutput)(running_timestamp, ch);
|
||||
|
||||
if(chc >= 4)
|
||||
{
|
||||
int32 freq = ch->noise_freq_cache;
|
||||
|
||||
ch->noisecount -= run_time;
|
||||
|
||||
#define CLOCK_LFSR(lfsr) { unsigned int newbit = ((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 11) ^ (lfsr >> 12) ^ (lfsr >> 17)) & 1; lfsr = (lfsr >> 1) | (newbit << 17); }
|
||||
if(&PCEFast_PSG::UpdateOutput_Noise == ch->UpdateOutput)
|
||||
{
|
||||
while(ch->noisecount <= 0)
|
||||
{
|
||||
CLOCK_LFSR(ch->lfsr);
|
||||
UpdateOutput_Noise(timestamp + ch->noisecount, ch);
|
||||
ch->noisecount += freq;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(ch->noisecount <= 0)
|
||||
{
|
||||
CLOCK_LFSR(ch->lfsr);
|
||||
ch->noisecount += freq;
|
||||
}
|
||||
}
|
||||
#undef CLOCK_LFSR
|
||||
}
|
||||
|
||||
// D7 of control is 0, don't clock the counter at all.
|
||||
// D7 of lfocontrol is 1(and chc == 1), don't clock the counter at all(not sure about this)
|
||||
// In DDA mode, don't clock the counter.
|
||||
// (Noise being enabled isn't handled here since AFAIK it doesn't disable clocking of the waveform portion, its sound just overrides the sound from
|
||||
// the waveform portion when the noise enable bit is set, which is handled in our RecalcUOFunc).
|
||||
if(!(ch->control & 0x80) || (chc == 1 && (lfoctrl & 0x80)) || (ch->control & 0x40))
|
||||
return;
|
||||
|
||||
ch->counter -= run_time;
|
||||
|
||||
if(!LFO_On && ch->freq_cache <= 0xA)
|
||||
{
|
||||
if(ch->counter <= 0)
|
||||
{
|
||||
const int32 inc_count = ((0 - ch->counter) / ch->freq_cache) + 1;
|
||||
|
||||
ch->counter += inc_count * ch->freq_cache;
|
||||
|
||||
ch->waveform_index = (ch->waveform_index + inc_count) & 0x1F;
|
||||
ch->dda = ch->waveform[ch->waveform_index];
|
||||
}
|
||||
}
|
||||
|
||||
while(ch->counter <= 0)
|
||||
{
|
||||
ch->waveform_index = (ch->waveform_index + 1) & 0x1F;
|
||||
ch->dda = ch->waveform[ch->waveform_index];
|
||||
|
||||
(this->*ch->UpdateOutput)(timestamp + ch->counter, ch);
|
||||
|
||||
if(LFO_On)
|
||||
{
|
||||
RunChannel<false>(1, timestamp + ch->counter);
|
||||
RecalcFreqCache(0);
|
||||
RecalcUOFunc(0);
|
||||
|
||||
ch->counter += (ch->freq_cache <= 0xA) ? 0xA : ch->freq_cache; // Not particularly accurate, but faster.
|
||||
}
|
||||
else
|
||||
ch->counter += ch->freq_cache;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void PCEFast_PSG::UpdateSubLFO(int32 timestamp)
|
||||
{
|
||||
RunChannel<true>(0, timestamp);
|
||||
|
||||
for(int chc = 1; chc < 6; chc++)
|
||||
RunChannel<false>(chc, timestamp);
|
||||
}
|
||||
|
||||
INLINE void PCEFast_PSG::UpdateSubNonLFO(int32 timestamp)
|
||||
{
|
||||
for(int chc = 0; chc < 6; chc++)
|
||||
RunChannel<false>(chc, timestamp);
|
||||
}
|
||||
|
||||
//static int32 last_read;
|
||||
//static int32 last_apply;
|
||||
|
||||
void PCEFast_PSG::Update(int32 timestamp)
|
||||
{
|
||||
int32 run_time = timestamp - lastts;
|
||||
|
||||
if(vol_pending && !vol_update_counter && !vol_update_which)
|
||||
{
|
||||
vol_update_counter = 1;
|
||||
vol_pending = false;
|
||||
}
|
||||
|
||||
bool lfo_on = (bool)(lfoctrl & 0x03);
|
||||
|
||||
if(lfo_on)
|
||||
{
|
||||
if(!(channel[1].control & 0x80) || (lfoctrl & 0x80))
|
||||
{
|
||||
lfo_on = 0;
|
||||
RecalcFreqCache(0);
|
||||
RecalcUOFunc(0);
|
||||
}
|
||||
}
|
||||
|
||||
int32 clocks = run_time;
|
||||
int32 running_timestamp = lastts;
|
||||
|
||||
while(clocks > 0)
|
||||
{
|
||||
int32 chunk_clocks = clocks;
|
||||
|
||||
if(vol_update_counter > 0 && chunk_clocks > vol_update_counter)
|
||||
chunk_clocks = vol_update_counter;
|
||||
|
||||
running_timestamp += chunk_clocks;
|
||||
clocks -= chunk_clocks;
|
||||
|
||||
if(lfo_on)
|
||||
UpdateSubLFO(running_timestamp);
|
||||
else
|
||||
UpdateSubNonLFO(running_timestamp);
|
||||
|
||||
if(vol_update_counter > 0)
|
||||
{
|
||||
vol_update_counter -= chunk_clocks;
|
||||
if(!vol_update_counter)
|
||||
{
|
||||
const int phase = vol_update_which & 1;
|
||||
const int lr = ((vol_update_which >> 1) & 1) ^ 1;
|
||||
const int chnum = vol_update_which >> 2;
|
||||
|
||||
if(!phase)
|
||||
{
|
||||
//printf("Volume update(Read, %d since last): ch=%d, lr=%d, ts=%d\n", running_timestamp - last_read, chnum, lr, running_timestamp);
|
||||
|
||||
if(chnum < 6)
|
||||
{
|
||||
vol_update_vllatch = GetVL(chnum, lr);
|
||||
}
|
||||
//last_read = running_timestamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("Volume update(Apply): ch=%d, lr=%d, ts=%d\n", chnum, lr, running_timestamp);
|
||||
if(chnum < 6)
|
||||
{
|
||||
channel[chnum].vl[lr] = vol_update_vllatch;
|
||||
}
|
||||
//last_apply = running_timestamp;
|
||||
}
|
||||
vol_update_which = (vol_update_which + 1) & 0x1F;
|
||||
|
||||
if(vol_update_which)
|
||||
vol_update_counter = phase ? 1 : 255;
|
||||
else if(vol_pending)
|
||||
{
|
||||
vol_update_counter = phase ? 1 : 255;
|
||||
vol_pending = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastts = running_timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
void PCEFast_PSG::EndFrame(int32 timestamp)
|
||||
{
|
||||
Update(timestamp);
|
||||
lastts = 0;
|
||||
for(int chc = 0; chc < 6; chc++)
|
||||
channel[chc].lastts = 0;
|
||||
}
|
||||
|
||||
void PCEFast_PSG::Power(const int32 timestamp)
|
||||
{
|
||||
// Not sure about power-on values, these are mostly just intuitive guesses(with some laziness thrown in).
|
||||
if(timestamp != lastts)
|
||||
Update(timestamp);
|
||||
|
||||
memset(&channel, 0, sizeof(channel));
|
||||
|
||||
select = 0;
|
||||
globalbalance = 0;
|
||||
lfofreq = 0;
|
||||
lfoctrl = 0;
|
||||
|
||||
for(int ch = 0; ch < 6; ch++)
|
||||
{
|
||||
channel[ch].frequency = 0;
|
||||
channel[ch].control = 0x00;
|
||||
channel[ch].balance = 0;
|
||||
memset(channel[ch].waveform, 0, 32);
|
||||
channel[ch].samp_accum = 0;
|
||||
|
||||
channel[ch].waveform_index = 0;
|
||||
channel[ch].dda = 0x00;
|
||||
channel[ch].noisectrl = 0x00;
|
||||
|
||||
channel[ch].vl[0] = 0x1F;
|
||||
channel[ch].vl[1] = 0x1F;
|
||||
|
||||
channel[ch].samp_accum = 0;
|
||||
|
||||
RecalcFreqCache(ch);
|
||||
RecalcUOFunc(ch);
|
||||
|
||||
channel[ch].counter = channel[ch].freq_cache;
|
||||
|
||||
if(ch >= 4)
|
||||
{
|
||||
RecalcNoiseFreqCache(ch);
|
||||
channel[ch].noisecount = 1;
|
||||
channel[ch].lfsr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
vol_pending = false;
|
||||
vol_update_counter = 0;
|
||||
vol_update_which = 0;
|
||||
}
|
||||
|
||||
int PCEFast_PSG::StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
for(int ch = 0; ch < 6; ch++)
|
||||
{
|
||||
char tmpstr[5] = "SCHx";
|
||||
psg_channel *pt = &channel[ch];
|
||||
|
||||
SFORMAT CH_StateRegs[] =
|
||||
{
|
||||
SFVARN(pt->counter, "counter"),
|
||||
SFVARN(pt->frequency, "frequency"),
|
||||
SFVARN(pt->control, "control"),
|
||||
SFVARN(pt->balance, "balance"),
|
||||
SFARRAYN(pt->waveform, 32, "waveform"),
|
||||
SFVARN(pt->waveform_index, "waveform_index"),
|
||||
SFVARN(pt->dda, "dda"),
|
||||
SFVARN(pt->noisectrl, "noisectrl"),
|
||||
SFVARN(pt->noisecount, "noisecount"),
|
||||
SFVARN(pt->lfsr, "lfsr"),
|
||||
SFARRAY32N(pt->vl, 2, "vl"), // TODO
|
||||
SFEND
|
||||
};
|
||||
tmpstr[3] = '0' + ch;
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, CH_StateRegs, tmpstr);
|
||||
}
|
||||
|
||||
SFORMAT PSG_StateRegs[] =
|
||||
{
|
||||
SFVAR(select),
|
||||
SFVAR(globalbalance),
|
||||
SFVAR(lfofreq),
|
||||
SFVAR(lfoctrl),
|
||||
|
||||
SFVAR(vol_update_counter),
|
||||
SFVAR(vol_update_which),
|
||||
SFVAR(vol_pending),
|
||||
SFEND
|
||||
};
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, PSG_StateRegs, "PSG");
|
||||
|
||||
if(load)
|
||||
{
|
||||
vol_update_which &= 0x1F;
|
||||
|
||||
if(!channel[4].lfsr)
|
||||
channel[4].lfsr = 1;
|
||||
|
||||
if(!channel[5].lfsr)
|
||||
channel[5].lfsr = 1;
|
||||
|
||||
for(int ch = 0; ch < 6; ch++)
|
||||
{
|
||||
channel[ch].samp_accum = 0;
|
||||
for(int wi = 0; wi < 32; wi++)
|
||||
{
|
||||
channel[ch].waveform[wi] &= 0x1F;
|
||||
channel[ch].samp_accum += channel[ch].waveform[wi];
|
||||
}
|
||||
|
||||
for(int lr = 0; lr < 2; lr++)
|
||||
channel[ch].vl[lr] &= 0x1F;
|
||||
|
||||
if(!channel[ch].noisecount && ch >= 4)
|
||||
{
|
||||
printf("ch=%d, noisecount == 0\n", ch);
|
||||
channel[ch].noisecount = 1;
|
||||
}
|
||||
|
||||
if(channel[ch].counter <= 0)
|
||||
{
|
||||
printf("ch=%d, counter <= 0\n", ch);
|
||||
channel[ch].counter = 1;
|
||||
}
|
||||
|
||||
if(ch >= 4)
|
||||
RecalcNoiseFreqCache(ch);
|
||||
RecalcFreqCache(ch);
|
||||
RecalcUOFunc(ch);
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
99
mednafen/pce_fast-09333/psg.h
Normal file
99
mednafen/pce_fast-09333/psg.h
Normal file
@ -0,0 +1,99 @@
|
||||
#ifndef _PCEFast_PSG_H
|
||||
#define _PCEFast_PSG_H
|
||||
|
||||
#include <blip/Blip_Buffer.h>
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
class PCEFast_PSG;
|
||||
|
||||
struct psg_channel
|
||||
{
|
||||
uint8 waveform[32]; /* Waveform data */
|
||||
uint8 waveform_index; /* Waveform data index */
|
||||
uint8 dda;
|
||||
uint8 control; /* Channel enable, DDA, volume */
|
||||
uint8 noisectrl; /* Noise enable/ctrl (channels 4,5 only) */
|
||||
|
||||
int32 vl[2]; //vll, vlr;
|
||||
|
||||
int32 counter;
|
||||
|
||||
void (PCEFast_PSG::*UpdateOutput)(const int32 timestamp, psg_channel *ch);
|
||||
|
||||
uint32 freq_cache;
|
||||
uint32 noise_freq_cache; // Channel 4,5 only
|
||||
int32 noisecount;
|
||||
uint32 lfsr;
|
||||
|
||||
int32 samp_accum; // The result of adding up all the samples in the waveform buffer(part of an optimization for high-frequency playback).
|
||||
int32 blip_prev_samp[2];
|
||||
int32 lastts;
|
||||
|
||||
uint16 frequency; /* Channel frequency */
|
||||
uint8 balance; /* Channel balance */
|
||||
};
|
||||
|
||||
class PCEFast_PSG
|
||||
{
|
||||
public:
|
||||
|
||||
PCEFast_PSG(Blip_Buffer *bb_l, Blip_Buffer *bb_r) MDFN_COLD;
|
||||
~PCEFast_PSG() MDFN_COLD;
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only) MDFN_COLD;
|
||||
|
||||
void Power(const int32 timestamp) MDFN_COLD;
|
||||
void Write(int32 timestamp, uint8 A, uint8 V);
|
||||
|
||||
void SetVolume(double new_volume) MDFN_COLD;
|
||||
|
||||
void EndFrame(int32 timestamp);
|
||||
|
||||
private:
|
||||
|
||||
void Update(int32 timestamp);
|
||||
|
||||
void UpdateSubLFO(int32 timestamp);
|
||||
void UpdateSubNonLFO(int32 timestamp);
|
||||
|
||||
void RecalcUOFunc(int chnum);
|
||||
void UpdateOutput_Off(const int32 timestamp, psg_channel *ch);
|
||||
void UpdateOutput_Accum(const int32 timestamp, psg_channel *ch);
|
||||
void UpdateOutput_Norm(const int32 timestamp, psg_channel *ch);
|
||||
void UpdateOutput_Noise(const int32 timestamp, psg_channel *ch);
|
||||
|
||||
int32 GetVL(const int chnum, const int lr);
|
||||
|
||||
void RecalcFreqCache(int chnum);
|
||||
void RecalcNoiseFreqCache(int chnum);
|
||||
template<bool LFO_On>
|
||||
void RunChannel(int chc, int32 timestamp);
|
||||
double OutputVolume;
|
||||
|
||||
uint8 select; /* Selected channel (0-5) */
|
||||
uint8 globalbalance; /* Global sound balance */
|
||||
uint8 lfofreq; /* LFO frequency */
|
||||
uint8 lfoctrl; /* LFO control */
|
||||
|
||||
int32 vol_update_counter;
|
||||
int32 vol_update_which;
|
||||
int32 vol_update_vllatch;
|
||||
bool vol_pending;
|
||||
|
||||
psg_channel channel[6];
|
||||
|
||||
int32 lastts;
|
||||
|
||||
Blip_Buffer *sbuf[2];
|
||||
Blip_Synth<blip_good_quality, 8192> Synth;
|
||||
|
||||
int32 dbtable_volonly[32];
|
||||
|
||||
int32 dbtable[32][32];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
1976
mednafen/pce_fast-09333/vdc.cpp
Normal file
1976
mednafen/pce_fast-09333/vdc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
211
mednafen/pce_fast-09333/vdc.h
Normal file
211
mednafen/pce_fast-09333/vdc.h
Normal file
@ -0,0 +1,211 @@
|
||||
#ifndef _PCE_VDC_H
|
||||
#define _PCE_VDC_H
|
||||
|
||||
namespace PCE_Fast
|
||||
{
|
||||
|
||||
#define REGSETP(_reg, _data, _msb) { _reg &= 0xFF << ((_msb) ? 0 : 8); _reg |= (_data) << ((_msb) ? 8 : 0); }
|
||||
#define REGGETP(_reg, _msb) ((_reg >> ((_msb) ? 8 : 0)) & 0xFF)
|
||||
|
||||
#define VDC_DEBUG(x)
|
||||
//printf("%s: %d\n", x, vdc->display_counter);
|
||||
#define VDC_UNDEFINED(x) { }
|
||||
//{ printf("%s: %d\n", x, vdc->display_counter); }
|
||||
|
||||
static const uint8 vram_inc_tab[4] = { 1, 32, 64, 128 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 priority[2];
|
||||
uint16 winwidths[2];
|
||||
uint8 st_mode;
|
||||
} vpc_t;
|
||||
|
||||
extern vpc_t vpc;
|
||||
|
||||
static const int VRAM_Size = 0x8000;
|
||||
static const int VRAM_SizeMask = VRAM_Size - 1; //0x7FFF;
|
||||
static const int VRAM_BGTileNoMask = VRAM_SizeMask / 16; //0x7FF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 CR;
|
||||
|
||||
bool lc263; // 263 line count if set, 262 if not
|
||||
bool bw; // Black and White
|
||||
uint8 dot_clock; // Dot Clock(5, 7, or 10 MHz = 0, 1, 2)
|
||||
uint16 color_table[0x200];
|
||||
uint32 color_table_cache[0x200];
|
||||
uint16 ctaddress;
|
||||
} vce_t;
|
||||
|
||||
extern vce_t vce;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16 y;
|
||||
uint16 height;
|
||||
uint16 x;
|
||||
uint16 no;
|
||||
uint16 flags;
|
||||
bool cgmode;
|
||||
} SAT_Cache_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 display_counter;
|
||||
|
||||
int32 sat_dma_slcounter;
|
||||
|
||||
uint8 select;
|
||||
uint16 MAWR; // Memory Address Write Register
|
||||
uint16 MARR; // Memory Address Read Register
|
||||
|
||||
uint16 CR; // Control Register
|
||||
uint16 RCR; // Raster Compare Register
|
||||
uint16 BXR; // Background X-Scroll Register
|
||||
uint16 BYR; // Background Y-Scroll Register
|
||||
uint16 MWR; // Memory Width Register
|
||||
|
||||
uint16 HSR; // Horizontal Sync Register
|
||||
uint16 HDR; // Horizontal Display Register
|
||||
uint16 VSR;
|
||||
uint16 VDR;
|
||||
|
||||
uint16 VCR;
|
||||
uint16 DCR;
|
||||
uint16 SOUR;
|
||||
uint16 DESR;
|
||||
uint16 LENR;
|
||||
uint16 SATB;
|
||||
|
||||
uint32 RCRCount;
|
||||
|
||||
uint16 read_buffer;
|
||||
uint8 write_latch;
|
||||
uint8 status;
|
||||
|
||||
uint16 DMAReadBuffer;
|
||||
bool DMAReadWrite;
|
||||
bool DMARunning;
|
||||
bool SATBPending;
|
||||
bool burst_mode;
|
||||
|
||||
uint32 BG_YOffset;
|
||||
uint32 BG_XOffset;
|
||||
|
||||
|
||||
|
||||
int SAT_Cache_Valid; // 64 through 128, depending on the number of 32-pixel-wide sprites.
|
||||
SAT_Cache_t SAT_Cache[128]; //64];
|
||||
|
||||
uint16 SAT[0x100];
|
||||
|
||||
uint16 VRAM[65536]; //VRAM_Size];
|
||||
uint64 bg_tile_cache[65536][8]; // Tile, y, x
|
||||
uint8 spr_tile_cache[1024][16][16]; // Tile, y, x
|
||||
uint8 spr_tile_clean[1024]; //VRAM_Size / 64];
|
||||
} vdc_t;
|
||||
|
||||
extern vdc_t *vdc_chips[2];
|
||||
extern int VDC_TotalChips;
|
||||
|
||||
|
||||
void VDC_SetPixelFormat(const MDFN_PixelFormat &format) MDFN_COLD;
|
||||
void VDC_RunFrame(EmulateSpecStruct *espec, bool IsHES);
|
||||
void VDC_SetLayerEnableMask(uint64 mask);
|
||||
|
||||
DECLFW(VDC_Write);
|
||||
DECLFW(VDC_Write_ST);
|
||||
|
||||
DECLFR(VCE_Read);
|
||||
|
||||
static INLINE uint8 VDC_Read(unsigned int A, bool SGX)
|
||||
{
|
||||
uint8 ret = 0;
|
||||
int msb = A & 1;
|
||||
int chip = 0;
|
||||
vdc_t *vdc;
|
||||
|
||||
if(SGX)
|
||||
{
|
||||
A &= 0x1F;
|
||||
switch(A)
|
||||
{
|
||||
case 0x8: return(vpc.priority[0]);
|
||||
case 0x9: return(vpc.priority[1]);
|
||||
case 0xA: return(vpc.winwidths[0]);
|
||||
case 0xB: return(vpc.winwidths[0] >> 8);
|
||||
case 0xC: return(vpc.winwidths[1]);
|
||||
case 0xD: return(vpc.winwidths[1] >> 8);
|
||||
case 0xE: return(0);
|
||||
}
|
||||
if(A & 0x8) return(0);
|
||||
chip = (A & 0x10) >> 4;
|
||||
vdc = vdc_chips[chip];
|
||||
A &= 0x3;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdc = vdc_chips[0];
|
||||
A &= 0x3;
|
||||
}
|
||||
|
||||
switch(A)
|
||||
{
|
||||
case 0x0: ret = vdc->status;
|
||||
|
||||
vdc->status &= ~0x3F;
|
||||
|
||||
if(SGX)
|
||||
{
|
||||
if(!(vdc_chips[0]->status & 0x3F) && !(vdc_chips[1]->status & 0x3F))
|
||||
HuC6280_IRQEnd(MDFN_IQIRQ1);
|
||||
}
|
||||
else
|
||||
HuC6280_IRQEnd(MDFN_IQIRQ1); // Clear VDC IRQ line
|
||||
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
ret = REGGETP(vdc->read_buffer, msb);
|
||||
if(vdc->select == 0x2) // VRR - VRAM Read Register
|
||||
{
|
||||
if(msb)
|
||||
{
|
||||
vdc->MARR += vram_inc_tab[(vdc->CR >> 11) & 0x3];
|
||||
|
||||
if(vdc->MARR >= VRAM_Size)
|
||||
VDC_UNDEFINED("Unmapped VRAM VRR read");
|
||||
|
||||
vdc->read_buffer = vdc->VRAM[vdc->MARR & VRAM_SizeMask];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//if(HuCPU.isopread && (A == 1 || A == 3)) //(A == 2 || A == 3)) // && A == 1)
|
||||
if(A == 1)
|
||||
{
|
||||
//if(vdc->display_counter >= (VDS + VSW) && vdc->display_counter < (VDS + VSW + VDW + 1) && vce.dot_clock > 0)
|
||||
if(vce.dot_clock > 0)
|
||||
ret = 0x40;
|
||||
//printf("%d %d %02x\n", vdc->display_counter, vce.dot_clock, ret);
|
||||
//ret = 0x40;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
DECLFW(VCE_Write);
|
||||
|
||||
void VDC_Init(int sgx) MDFN_COLD;
|
||||
void VDC_Close(void) MDFN_COLD;
|
||||
void VDC_Reset(void) MDFN_COLD;
|
||||
void VDC_Power(void) MDFN_COLD;
|
||||
|
||||
int VDC_StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
35
mednafen/pce_fast-09333/vpc_mix_inner.inc
Normal file
35
mednafen/pce_fast-09333/vpc_mix_inner.inc
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
uint32 vdc2_pixel, vdc1_pixel;
|
||||
|
||||
vdc2_pixel = vdc1_pixel = vce.color_table_cache[0];
|
||||
|
||||
if(pb & 1)
|
||||
vdc1_pixel = lb0[x];
|
||||
|
||||
if(pb & 2)
|
||||
vdc2_pixel = lb1[x];
|
||||
|
||||
/* Dai MakaiMura uses setting 1, and expects VDC #2 sprites in front of VDC #1 background, but
|
||||
behind VDC #1's sprites.
|
||||
*/
|
||||
switch(pb >> 2)
|
||||
{
|
||||
case 1:
|
||||
//if((vdc2_pixel & (amask << 2)) && !(vdc1_pixel & (amask << 2)))
|
||||
// vdc1_pixel |= amask;
|
||||
vdc1_pixel |= (((vdc2_pixel ^ vdc1_pixel) & vdc2_pixel) >> 2) & amask;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//if((vdc1_pixel & (amask << 2)) && !(vdc2_pixel & (amask << 2)) && !(vdc2_pixel & amask))
|
||||
// vdc1_pixel |= amask;
|
||||
puts("MOO");
|
||||
// TODO: Verify that this is correct logic.
|
||||
{
|
||||
const uint32 intermediate = ((vdc1_pixel ^ vdc2_pixel) & vdc1_pixel) >> 2;
|
||||
vdc1_pixel |= (intermediate ^ vdc2_pixel) & intermediate & amask;
|
||||
}
|
||||
break;
|
||||
}
|
||||
target[x] = (vdc1_pixel & amask) ? vdc2_pixel : vdc1_pixel;
|
||||
|
@ -69,14 +69,26 @@ void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32
|
||||
|
||||
pixels16 = NULL;
|
||||
pixels = NULL;
|
||||
#if defined(WANT_8BPP)
|
||||
palette = NULL;
|
||||
#endif
|
||||
|
||||
if(!(rpix = calloc(1, p_pitchinpix * p_height * (nf.bpp / 8))))
|
||||
throw(1);
|
||||
|
||||
if(nf.bpp == 16)
|
||||
#if defined(WANT_8BPP)
|
||||
//if(nf.bpp == 8)
|
||||
{
|
||||
pixels8 = (uint8 *)rpix;
|
||||
palette = (MDFN_PaletteEntry*)calloc(sizeof(MDFN_PaletteEntry), 256);
|
||||
}
|
||||
#elif defined(WANT_16BPP)
|
||||
//if(nf.bpp == 16)
|
||||
pixels16 = (uint16 *)rpix;
|
||||
else
|
||||
#elif defined(WANT_32BPP)
|
||||
//else
|
||||
pixels = (uint32 *)rpix;
|
||||
#endif
|
||||
|
||||
w = p_width;
|
||||
h = p_height;
|
||||
@ -94,9 +106,17 @@ void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert)
|
||||
|
||||
MDFN_Surface::~MDFN_Surface()
|
||||
{
|
||||
if(pixels)
|
||||
free(pixels);
|
||||
#if defined(WANT_16BPP)
|
||||
if(pixels16)
|
||||
free(pixels16);
|
||||
#elif defined(WANT_32BPP)
|
||||
if(pixels)
|
||||
free(pixels);
|
||||
#elif defined(WANT_8BPP)
|
||||
pixels8 = NULL;
|
||||
if(palette)
|
||||
free(palette);
|
||||
palette = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,11 @@
|
||||
#define MAKECOLOR(r, g, b, a) (((r >> RED_EXPAND) << RED_SHIFT) | ((g >> GREEN_EXPAND) << GREEN_SHIFT) | ((b >> BLUE_EXPAND) << BLUE_SHIFT))
|
||||
#endif
|
||||
|
||||
struct MDFN_PaletteEntry
|
||||
{
|
||||
uint8 r, g, b;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 x, y, w, h;
|
||||
@ -126,6 +131,8 @@ class MDFN_Surface //typedef struct
|
||||
int32 pitchinpix; // New name, new code should use this.
|
||||
};
|
||||
|
||||
MDFN_PaletteEntry *palette;
|
||||
|
||||
MDFN_PixelFormat format;
|
||||
|
||||
void SetFormat(const MDFN_PixelFormat &new_format, bool convert);
|
||||
|
86
scrc32.cpp
86
scrc32.cpp
@ -0,0 +1,86 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef WANT_CRC32
|
||||
|
||||
static const unsigned long crc_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
#define DO1_CRC32(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
|
||||
#define DO2_CRC32(buf) DO1_CRC32(buf); DO1_CRC32(buf);
|
||||
#define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf);
|
||||
#define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf);
|
||||
|
||||
unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len)
|
||||
{
|
||||
if (buf == 0) return 0L;
|
||||
crc = crc ^ 0xffffffffL;
|
||||
while (len >= 8)
|
||||
{
|
||||
DO8_CRC32(buf);
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1_CRC32(buf);
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
79
scrc32.h
79
scrc32.h
@ -5,84 +5,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef WANT_CRC32
|
||||
|
||||
static const unsigned long crc_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
#define DO1_CRC32(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
|
||||
#define DO2_CRC32(buf) DO1_CRC32(buf); DO1_CRC32(buf);
|
||||
#define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf);
|
||||
#define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf);
|
||||
|
||||
static unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len)
|
||||
{
|
||||
if (buf == 0) return 0L;
|
||||
crc = crc ^ 0xffffffffL;
|
||||
while (len >= 8)
|
||||
{
|
||||
DO8_CRC32(buf);
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1_CRC32(buf);
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffL;
|
||||
}
|
||||
|
||||
#endif
|
||||
unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user