diff options
Diffstat (limited to 'plugins/sid/sidplay-libs/libsidplay/src')
59 files changed, 18129 insertions, 0 deletions
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/Makefile.am new file mode 100644 index 00000000..8c586b8b --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/Makefile.am @@ -0,0 +1,31 @@ + +SUBDIRS = c64 mos6510 mos6526 mos656x xsid sid6526 sidtune +EXTRA_DIST = psiddrv.bin kernal.bin poweron.bin + + +# The library. + +lib_LTLIBRARIES = libsidplay2.la + +libsidplay2_la_SOURCES = config.cpp event.cpp \ +player.cpp player.h \ +psiddrv.cpp mixer.cpp \ +reloc65.c sidplay2.cpp \ +nullsid.h psiddrv.a65 + +libsidplay2_la_LIBADD = \ +./mos6510/libmos6510.la ./mos6526/libmos6526.la \ +./mos656x/libmos656x.la ./xsid/libxsid.la \ +./sidtune/libsidtune.la ./sid6526/libsid6526.la + +# We substitute the libtool-specific library version in configure.in. +libsidplay2_la_LDFLAGS = -version-info $(LIBVERSION) + +# Remove bad default includes +DEFAULT_INCLUDES= + +SUFFIXES = .a65 + +%.bin : %.a65 + xa -R -G $< -o $(srcdir)/$*.o65 + od -v -An -w8 -tx1 $(srcdir)/$*.o65 | sed 's/\w\w/0x&,/g' > $(srcdir)/$@ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/Makefile.in new file mode 100644 index 00000000..5475c200 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/Makefile.in @@ -0,0 +1,607 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +SUBDIRS = c64 mos6510 mos6526 mos656x xsid sid6526 sidtune +EXTRA_DIST = psiddrv.bin kernal.bin poweron.bin + + +# The library. +lib_LTLIBRARIES = libsidplay2.la + +libsidplay2_la_SOURCES = config.cpp event.cpp \ +player.cpp player.h \ +psiddrv.cpp mixer.cpp \ +reloc65.c sidplay2.cpp \ +nullsid.h psiddrv.a65 + + +libsidplay2_la_LIBADD = \ +./mos6510/libmos6510.la ./mos6526/libmos6526.la \ +./mos656x/libmos656x.la ./xsid/libxsid.la \ +./sidtune/libsidtune.la ./sid6526/libsid6526.la + + +# We substitute the libtool-specific library version in configure.in. +libsidplay2_la_LDFLAGS = -version-info $(LIBVERSION) + +# Remove bad default includes +DEFAULT_INCLUDES = + +SUFFIXES = .a65 +subdir = src +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) + +libsidplay2_la_DEPENDENCIES = ./mos6510/libmos6510.la \ + ./mos6526/libmos6526.la ./mos656x/libmos656x.la \ + ./xsid/libxsid.la ./sidtune/libsidtune.la \ + ./sid6526/libsid6526.la +am_libsidplay2_la_OBJECTS = config.lo event.lo player.lo psiddrv.lo \ + mixer.lo reloc65.lo sidplay2.lo +libsidplay2_la_OBJECTS = $(am_libsidplay2_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/config.Plo ./$(DEPDIR)/event.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/mixer.Plo ./$(DEPDIR)/player.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/psiddrv.Plo ./$(DEPDIR)/reloc65.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/sidplay2.Plo +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libsidplay2_la_SOURCES) + +RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ + ps-recursive install-info-recursive uninstall-info-recursive \ + all-recursive install-data-recursive install-exec-recursive \ + installdirs-recursive install-recursive uninstall-recursive \ + check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +SOURCES = $(libsidplay2_la_SOURCES) + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .a65 .c .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +libLTLIBRARIES_INSTALL = $(INSTALL) +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsidplay2.la: $(libsidplay2_la_OBJECTS) $(libsidplay2_la_DEPENDENCIES) + $(CXXLINK) -rpath $(libdir) $(libsidplay2_la_LDFLAGS) $(libsidplay2_la_OBJECTS) $(libsidplay2_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psiddrv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reloc65.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sidplay2.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(libdir) + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-recursive ctags ctags-recursive distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-recursive distclean-tags distdir \ + dvi dvi-am dvi-recursive info info-am info-recursive install \ + install-am install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive \ + install-libLTLIBRARIES install-man install-recursive \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am installdirs-recursive maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ + ps-recursive tags tags-recursive uninstall uninstall-am \ + uninstall-info-am uninstall-info-recursive \ + uninstall-libLTLIBRARIES uninstall-recursive + + +%.bin : %.a65 + xa -R -G $< -o $(srcdir)/$*.o65 + od -v -An -w8 -tx1 $(srcdir)/$*.o65 | sed 's/\w\w/0x&,/g' > $(srcdir)/$@ +# 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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/c64/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/c64/Makefile.am new file mode 100644 index 00000000..94d8e182 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/c64/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = c64cia.h \ +c64vic.h \ +c64xsid.h diff --git a/plugins/sid/sidplay-libs/libsidplay/src/c64/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/c64/Makefile.in new file mode 100644 index 00000000..a9a93154 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/c64/Makefile.in @@ -0,0 +1,286 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +EXTRA_DIST = c64cia.h \ +c64vic.h \ +c64xsid.h + +subdir = src/c64 +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/c64/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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 mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/c64/c64cia.h b/plugins/sid/sidplay-libs/libsidplay/src/c64/c64cia.h new file mode 100644 index 00000000..b9626405 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/c64/c64cia.h @@ -0,0 +1,70 @@ +/*************************************************************************** + c64cia.h - C64 CIAs + ------------------- + begin : Fri Apr 4 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _c64cia_h_ +#define _c64cia_h_ + +// The CIA emulations are very generic and here we need to effectively +// wire them into the computer (like adding a chip to a PCB). + +#include "c64env.h" +#include "../mos6526/mos6526.h" + +/* CIA 1 specifics: + Generates IRQs +*/ +class c64cia1: public MOS6526 +{ +private: + c64env &m_env; + +protected: + void interrupt (bool state) + { + m_env.interruptIRQ (state); + } + +public: + c64cia1 (c64env *env) + :MOS6526(&(env->context ())), + m_env(*env) {} + const char *error (void) {return "";} +}; + +/* CIA 2 specifics: + Generates NMIs +*/ +class c64cia2: public MOS6526 +{ +private: + c64env &m_env; + +protected: + void interrupt (bool state) + { + if (state) + m_env.interruptNMI (); + } + +public: + c64cia2 (c64env *env) + :MOS6526(&(env->context ())), + m_env(*env) {} + const char *error (void) {return "";} +}; + +#endif // _c64cia_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/c64/c64vic.h b/plugins/sid/sidplay-libs/libsidplay/src/c64/c64vic.h new file mode 100644 index 00000000..d9b2f934 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/c64/c64vic.h @@ -0,0 +1,54 @@ +/*************************************************************************** + c64vic.h - C64 VIC + ------------------- + begin : Fri Apr 4 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _c64vic_h_ +#define _c64vic_h_ + +// The VIC emulation is very generic and here we need to effectively +// wire it into the computer (like adding a chip to a PCB). +#include "c64env.h" +#include "../mos656x/mos656x.h" + +class c64vic: public MOS656X +{ +private: + c64env &m_env; + +protected: + void interrupt (bool state) + { + m_env.interruptIRQ (state); + } + + void busaccess (bool state) + { + m_env.signalBA (state); + } + + void addrctrl (bool state) + { + m_env.signalAEC (state); + } + +public: + c64vic (c64env *env) + :MOS656X(&(env->context ())), + m_env(*env) {} + const char *error (void) {return "";} +}; + +#endif // _c64vic_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/c64/c64xsid.h b/plugins/sid/sidplay-libs/libsidplay/src/c64/c64xsid.h new file mode 100644 index 00000000..e8385adb --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/c64/c64xsid.h @@ -0,0 +1,96 @@ +/*************************************************************************** + c64sid.h - ReSid Wrapper + ------------------- + begin : Fri Apr 4 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 file could be a specialisation of a sid implementation. + * However since the sid emulation is not part of this project + * we are actually creating a wrapper instead. + */ + +#include "c64env.h" +#include "sidbuilder.h" +#include "../xsid/xsid.h" + +class c64xsid: public XSID +{ +private: + c64env &m_env; + sidemu *m_sid; + int_least32_t m_gain; + +private: + uint8_t readMemByte (uint_least16_t addr) + {return m_env.readMemRamByte (addr);} + void writeMemByte (uint8_t data) + {m_sid->write (0x18, data);} + +public: + c64xsid (c64env *env, sidemu *sid) + :XSID(&env->context ()), + m_env(*env), m_sid(sid), m_gain(100) + {;} + + // Standard component interface + const char *error (void) {return "";} + void reset () { sidemu::reset (); } + void reset (uint8_t volume) + { + XSID::reset (volume); + m_sid->reset (volume); + } + + uint8_t read (uint_least8_t addr) + { return m_sid->read (addr); } + + void write (uint_least8_t addr, uint8_t data) + { + if (addr == 0x18) + XSID::storeSidData0x18 (data); + else + m_sid->write (addr, data); + } + + void write16 (uint_least16_t addr, uint8_t data) + { + XSID::write (addr, data); + } + + // Standard SID interface + int_least32_t output (uint_least8_t bits) + { return m_sid->output (bits) + (XSID::output (bits) * m_gain / 100); } + + void voice (uint_least8_t num, uint_least8_t vol, + bool mute) + { + if (num == 3) + XSID::mute (mute); + else + m_sid->voice (num, vol, mute); + } + + void gain (int_least8_t percent) + { + // 0 to 99 is loss, 101 - 200 is gain + m_gain = percent; + m_gain += 100; + if (m_gain > 200) + m_gain = 200; + } + + // Xsid specific + void emulation (sidemu *sid) {m_sid = sid;} + sidemu *emulation (void) { return m_sid; } +}; diff --git a/plugins/sid/sidplay-libs/libsidplay/src/config.cpp b/plugins/sid/sidplay-libs/libsidplay/src/config.cpp new file mode 100644 index 00000000..0b4a71da --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/config.cpp @@ -0,0 +1,616 @@ +/*************************************************************************** + config.cpp - Library Configuration Code + ------------------- + begin : Fri Jul 27 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: config.cpp,v $ + * Revision 1.29 2002/10/15 18:14:02 s_a_white + * Removed upper limit frequency limit check to allow for oversampling. + * + * Revision 1.28 2002/10/02 19:46:36 s_a_white + * RSID support & fix sid model forced operation. + * + * Revision 1.27 2002/09/09 18:09:06 s_a_white + * Added error message for psid specific flag set in strict real C64 mode. + * + * Revision 1.26 2002/08/10 22:35:56 s_a_white + * Small clock speed fix for when both clockSpeed and clockDefault are set + * to SID2_CLOCK_CORRECT. + * + * Revision 1.25 2002/07/17 19:25:28 s_a_white + * Temp fix to allow SID model to change for current builder. + * + * Revision 1.24 2002/04/14 21:46:50 s_a_white + * PlaySID reads fixed to come from RAM only. + * + * Revision 1.23 2002/03/11 18:01:30 s_a_white + * Prevent lockup if config call fails with existing and old configurations. + * + * Revision 1.22 2002/03/04 19:05:49 s_a_white + * Fix C++ use of nothrow. + * + * Revision 1.21 2002/03/03 22:01:58 s_a_white + * New clock speed & sid model interface. + * + * Revision 1.20 2002/02/18 21:59:10 s_a_white + * Added two new clock modes (FIXED). Seems to be a requirement for + * HVSC/sidplayw. + * + * Revision 1.19 2002/02/04 22:08:14 s_a_white + * Fixed main voice/sample gains. + * + * Revision 1.18 2002/01/29 21:50:33 s_a_white + * Auto switching to a better emulation mode. m_tuneInfo reloaded after a + * config. Initial code added to support more than two sids. + * + * Revision 1.17 2002/01/16 19:11:38 s_a_white + * Always release sid emulations now on a call to sidCreate until a better + * method is implemented for hardware emulations with locked sids. + * + * Revision 1.16 2002/01/16 08:23:45 s_a_white + * Force a clock speed when unknown. + * + * Revision 1.15 2002/01/15 19:12:54 s_a_white + * PSID2NG update. + * + * Revision 1.14 2002/01/14 23:18:56 s_a_white + * Make sure xsid releases the old sid emulation when there are errors gaining + * a new one. + * + * Revision 1.13 2001/12/20 20:15:23 s_a_white + * Fixed bad environment initialisation when switching to legacy modes. + * + * Revision 1.12 2001/12/13 08:28:08 s_a_white + * Added namespace support to fix problems with xsidplay. + * + * Revision 1.11 2001/12/11 19:24:15 s_a_white + * More GCC3 Fixes. + * + * Revision 1.10 2001/11/23 22:59:59 s_a_white + * Added new header + * + * Revision 1.9 2001/10/02 18:27:55 s_a_white + * Updated to use new sidbuilder classes. + * + * Revision 1.8 2001/09/20 20:33:54 s_a_white + * sid2 now gets correctly set to nullsid for a bad create call. + * + * Revision 1.7 2001/09/20 19:34:11 s_a_white + * Error checking added for the builder create calls. + * + * Revision 1.6 2001/09/17 19:02:38 s_a_white + * Now uses fixed point maths for sample output and rtc. + * + * Revision 1.5 2001/09/01 11:13:56 s_a_white + * Fixes sidplay1 environment modes. + * + * Revision 1.4 2001/08/20 18:24:50 s_a_white + * tuneInfo in the info structure now correctly has the sid revision setup. + * + * Revision 1.3 2001/08/12 18:22:45 s_a_white + * Fixed bug in Player::sidEmulation call. + * + * Revision 1.2 2001/07/27 12:51:40 s_a_white + * Removed warning. + * + * Revision 1.1 2001/07/27 12:12:23 s_a_white + * Initial release. + * + ***************************************************************************/ + +#include "sid2types.h" +#include "player.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif + +SIDPLAY2_NAMESPACE_START + +// An instance of this structure is used to transport emulator settings +// to and from the interface class. + +int Player::config (const sid2_config_t &cfg) +{ + if (m_running) + { + m_errorString = ERR_CONF_WHILST_ACTIVE; + goto Player_configure_error; + } + + // Check for base sampling frequency + if (cfg.frequency < 4000) + { // Rev 1.6 (saw) - Added descriptive error + m_errorString = ERR_UNSUPPORTED_FREQ; + goto Player_configure_error; + } + + // Check for legal precision + switch (cfg.precision) + { + case 8: + case 16: + case 24: + if (cfg.precision > SID2_MAX_PRECISION) + { // Rev 1.6 (saw) - Added descriptive error + m_errorString = ERR_UNSUPPORTED_PRECISION; + goto Player_configure_error; + } + break; + + default: + // Rev 1.6 (saw) - Added descriptive error + m_errorString = ERR_UNSUPPORTED_PRECISION; + goto Player_configure_error; + } + + // Only do these if we have a loaded tune + if (m_tune) + { + float64_t cpuFreq; + // Reset tune info + m_tune->getInfo(m_tuneInfo); + + // External Setups + if (sidCreate (cfg.sidEmulation, cfg.sidModel, cfg.sidDefault) < 0) + { + m_errorString = cfg.sidEmulation->error (); + m_cfg.sidEmulation = NULL; + goto Player_configure_restore; + } + // Must be this order: + // Determine clock speed + cpuFreq = clockSpeed (cfg.clockSpeed, cfg.clockDefault, + cfg.clockForced); + // Fixed point conversion 16.16 + m_samplePeriod = (event_clock_t) (cpuFreq / + (float64_t) cfg.frequency * + (1 << 16) * m_fastForwardFactor); + // Setup fake cia + sid6526.clock ((uint_least16_t)(cpuFreq / VIC_FREQ_PAL + 0.5)); + if (m_tuneInfo.songSpeed == SIDTUNE_SPEED_CIA_1A || + m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_NTSC) + { + sid6526.clock ((uint_least16_t)(cpuFreq / VIC_FREQ_NTSC + 0.5)); + } + // Configure, setup and install C64 environment/events + if (environment (cfg.environment) < 0) + goto Player_configure_restore; + // Start the real time clock event + rtc.clock (cpuFreq); + } + sidSamples (cfg.sidSamples); + + // All parameters check out, so configure player. + m_info.channels = 1; + if (cfg.playback == sid2_stereo) + m_info.channels++; + + m_sidAddress[0] = m_tuneInfo.sidChipBase1; + m_sidAddress[1] = m_tuneInfo.sidChipBase2; + + // Only force dual sids if second wasn't detected + if (!m_sidAddress[1] && cfg.forceDualSids) + m_sidAddress[1] = 0xd500; // Assumed + + m_leftVolume = cfg.leftVolume; + m_rightVolume = cfg.rightVolume; + + if (cfg.playback != sid2_mono) + { // Try Spliting channels across 2 sids + if (!m_sidAddress[1]) + { + m_sidAddress[1] = m_sidAddress[0]; + + // Mute Voices + sid[0]->voice (0, 0, true); + sid[0]->voice (2, 0, true); + sid[1]->voice (1, 0, true); + // 2 Voices scaled to unity from 4 (was !SID_VOL) + // m_leftVolume *= 2; + // m_rightVolume *= 2; + // 2 Voices scaled to unity from 3 (was SID_VOL) + // m_leftVolume *= 3; + // m_leftVolume /= 2; + // m_rightVolume *= 3; + // m_rightVolume /= 2; + } + + if (cfg.playback == sid2_left) + xsid.mute (true); + } + + // Setup the audio side, depending on the audio hardware + // and the information returned by sidtune + switch (cfg.precision) + { + case 8: + if (!m_sidAddress[1]) + { + if (cfg.playback == sid2_stereo) + output = &Player::stereoOut8MonoIn; + else + output = &Player::monoOut8MonoIn; + } + else + { + switch (cfg.playback) + { + case sid2_stereo: // Stereo Hardware + output = &Player::stereoOut8StereoIn; + break; + + case sid2_right: // Mono Hardware, + output = &Player::monoOut8StereoRIn; + break; + + case sid2_left: + output = &Player::monoOut8MonoIn; + break; + + case sid2_mono: + output = &Player::monoOut8StereoIn; + break; + } + } + break; + + case 16: + if (!m_sidAddress[1]) + { + if (cfg.playback == sid2_stereo) + output = &Player::stereoOut16MonoIn; + else + output = &Player::monoOut16MonoIn; + } + else + { + switch (cfg.playback) + { + case sid2_stereo: // Stereo Hardware + output = &Player::stereoOut16StereoIn; + break; + + case sid2_right: // Mono Hardware, + output = &Player::monoOut16StereoRIn; + break; + + case sid2_left: + output = &Player::monoOut16MonoIn; + break; + + case sid2_mono: + output = &Player::monoOut16StereoIn; + break; + } + } + } + + // Update Configuration + m_cfg = cfg; + + if (m_cfg.optimisation > SID2_MAX_OPTIMISATION) + m_cfg.optimisation = SID2_MAX_OPTIMISATION; +return 0; + +Player_configure_restore: + // Try restoring old configuration + if (&m_cfg != &cfg) + config (m_cfg); +Player_configure_error: + return -1; +} + +// Clock speed changes due to loading a new song +float64_t Player::clockSpeed (sid2_clock_t userClock, sid2_clock_t defaultClock, + bool forced) +{ + float64_t cpuFreq = CLOCK_FREQ_PAL; + + // Detect the Correct Song Speed + // Determine song speed when unknown + if (m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_UNKNOWN) + { + switch (defaultClock) + { + case SID2_CLOCK_PAL: + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_PAL; + break; + case SID2_CLOCK_NTSC: + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_NTSC; + break; + case SID2_CLOCK_CORRECT: + // No default so base it on emulation clock + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_ANY; + } + } + + // Since song will run correct at any clock speed + // set tune speed to the current emulation + if (m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_ANY) + { + if (userClock == SID2_CLOCK_CORRECT) + userClock = defaultClock; + + switch (userClock) + { + case SID2_CLOCK_NTSC: + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_NTSC; + break; + case SID2_CLOCK_PAL: + default: + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_PAL; + break; + } + } + + if (userClock == SID2_CLOCK_CORRECT) + { + switch (m_tuneInfo.clockSpeed) + { + case SIDTUNE_CLOCK_NTSC: + userClock = SID2_CLOCK_NTSC; + break; + case SIDTUNE_CLOCK_PAL: + userClock = SID2_CLOCK_PAL; + break; + } + } + + if (forced) + { + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_PAL; + if (userClock == SID2_CLOCK_NTSC) + m_tuneInfo.clockSpeed = SIDTUNE_CLOCK_NTSC; + } + + if (m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_PAL) + vic.chip (MOS6569); + else // if (tuneInfo.clockSpeed == SIDTUNE_CLOCK_NTSC) + vic.chip (MOS6567R8); + + if (userClock == SID2_CLOCK_PAL) + { + cpuFreq = CLOCK_FREQ_PAL; + m_tuneInfo.speedString = TXT_PAL_VBI; + if (m_tuneInfo.songSpeed == SIDTUNE_SPEED_CIA_1A) + m_tuneInfo.speedString = TXT_PAL_CIA; + else if (m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_NTSC) + m_tuneInfo.speedString = TXT_PAL_VBI_FIXED; + } + else // if (userClock == SID2_CLOCK_NTSC) + { + cpuFreq = CLOCK_FREQ_NTSC; + m_tuneInfo.speedString = TXT_NTSC_VBI; + if (m_tuneInfo.songSpeed == SIDTUNE_SPEED_CIA_1A) + m_tuneInfo.speedString = TXT_NTSC_CIA; + else if (m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_PAL) + m_tuneInfo.speedString = TXT_NTSC_VBI_FIXED; + } + return cpuFreq; +} + +int Player::environment (sid2_env_t env) +{ + switch (m_tuneInfo.compatibility) + { + case SIDTUNE_COMPATIBILITY_R64: + env = sid2_envR; + break; + case SIDTUNE_COMPATIBILITY_PSID: + if (env == sid2_envR) + env = sid2_envBS; + } + + // Environment already set? + if (!(m_ram && (m_info.environment == env))) + { // Setup new player environment + m_info.environment = env; + if (m_ram) + { + if (m_ram == m_rom) + delete [] m_ram; + else + { + delete [] m_rom; + delete [] m_ram; + } + } + +#ifdef HAVE_EXCEPTIONS + m_ram = new(std::nothrow) uint8_t[0x10000]; +#else + m_ram = new uint8_t[0x10000]; +#endif + + // Setup the access functions to the environment + // and the properties the memory has. + if (m_info.environment == sid2_envPS) + { // Playsid has no roms and SID exists in ram space + m_rom = m_ram; + m_readMemByte = &Player::readMemByte_player; + m_writeMemByte = &Player::writeMemByte_playsid; + m_readMemDataByte = &Player::readMemByte_plain; + } + else + { +#ifdef HAVE_EXCEPTIONS + m_rom = new(std::nothrow) uint8_t[0x10000]; +#else + m_rom = new uint8_t[0x10000]; +#endif + + switch (m_info.environment) + { + case sid2_envTP: + m_readMemByte = &Player::readMemByte_player; + m_writeMemByte = &Player::writeMemByte_sidplay; + m_readMemDataByte = &Player::readMemByte_sidplaytp; + break; + + //case sid2_envTR: + case sid2_envBS: + m_readMemByte = &Player::readMemByte_player; + m_writeMemByte = &Player::writeMemByte_sidplay; + m_readMemDataByte = &Player::readMemByte_sidplaybs; + break; + + case sid2_envR: + default: // <-- Just to please compiler + m_readMemByte = &Player::readMemByte_player; + m_writeMemByte = &Player::writeMemByte_sidplay; + m_readMemDataByte = &Player::readMemByte_sidplaybs; + break; + } + } + } + + { // Have to reload the song into memory as + // everything has changed + int ret; + sid2_env_t old = m_info.environment; + m_info.environment = env; + ret = initialise (); + m_info.environment = old; + return ret; + } +} + +// Integrate SID emulation from the builder class into +// libsidplay2 +int Player::sidCreate (sidbuilder *builder, sid2_model_t userModel, + sid2_model_t defaultModel) +{ + sid[0] = xsid.emulation (); + /* @FIXME@ Removed as prevents SID + * Model being updated + **************************************** + // If we are already using the emulation + // then don't change + if (builder == sid[0]->builder ()) + { + sid[0] = &xsid; + return 0; + } + ****************************************/ + + // Make xsid forget it's emulation + xsid.emulation (&nullsid); + + { // Release old sids + for (int i = 0; i < SID2_MAX_SIDS; i++) + { + sidbuilder *b; + b = sid[i]->builder (); + if (b) + b->unlock (sid[i]); + } + } + + if (!builder) + { // No sid + for (int i = 0; i < SID2_MAX_SIDS; i++) + sid[i] = &nullsid; + } + else + { // Detect the Correct SID model + // Determine model when unknown + if (m_tuneInfo.sidModel == SIDTUNE_SIDMODEL_UNKNOWN) + { + switch (defaultModel) + { + case SID2_MOS6581: + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_6581; + break; + case SID2_MOS8580: + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_8580; + break; + case SID2_MODEL_CORRECT: + // No default so base it on emulation clock + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_ANY; + } + } + + // Since song will run correct on any sid model + // set it to the current emulation + if (m_tuneInfo.sidModel == SIDTUNE_SIDMODEL_ANY) + { + if (userModel == SID2_MODEL_CORRECT) + userModel = defaultModel; + + switch (userModel) + { + case SID2_MOS8580: + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_8580; + break; + case SID2_MOS6581: + default: + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_6581; + break; + } + } + + switch (userModel) + { + case SID2_MODEL_CORRECT: + switch (m_tuneInfo.sidModel) + { + case SIDTUNE_SIDMODEL_8580: + userModel = SID2_MOS8580; + break; + case SIDTUNE_SIDMODEL_6581: + userModel = SID2_MOS6581; + break; + } + break; + // Fixup tune information if model is forced + case SID2_MOS6581: + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_6581; + break; + case SID2_MOS8580: + m_tuneInfo.sidModel = SIDTUNE_SIDMODEL_8580; + break; + } + + for (int i = 0; i < SID2_MAX_SIDS; i++) + { // Get first SID emulation + sid[i] = builder->lock (this, userModel); + if (!sid[i]) + sid[i] = &nullsid; + if ((i == 0) && !*builder) + return -1; + } + } + xsid.emulation (sid[0]); + sid[0] = &xsid; + return 0; +} + +void Player::sidSamples (bool enable) +{ + int_least8_t gain = 0; + xsid.sidSamples (enable); + + // Now balance voices + if (!enable) + gain = -25; + + xsid.gain (-100 - gain); + sid[0] = xsid.emulation (); + for (int i = 0; i < SID2_MAX_SIDS; i++) + sid[i]->gain (gain); + sid[0] = &xsid; +} + +SIDPLAY2_NAMESPACE_STOP diff --git a/plugins/sid/sidplay-libs/libsidplay/src/event.cpp b/plugins/sid/sidplay-libs/libsidplay/src/event.cpp new file mode 100644 index 00000000..ced11c38 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/event.cpp @@ -0,0 +1,121 @@ +/*************************************************************************** + event.cpp - Event schdeduler (based on alarm + from Vice) + ------------------- + begin : Wed May 9 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: event.cpp,v $ + * Revision 1.7 2002/11/21 19:55:38 s_a_white + * We now jump to next event directly instead on clocking by a number of + * cycles. + * + * Revision 1.6 2002/07/17 19:20:03 s_a_white + * More efficient event handling code. + * + * Revision 1.5 2001/10/02 18:24:09 s_a_white + * Updated to support safe scheduler interface. + * + * Revision 1.4 2001/09/17 19:00:28 s_a_white + * Constructor moved out of line. + * + * Revision 1.3 2001/09/15 13:03:50 s_a_white + * timeWarp now zeros m_eventClk instead of m_pendingEventClk which + * fixes a inifinite loop problem when driving libsidplay1. + * + ***************************************************************************/ + +#include <string.h> +#include "event.h" + +#define EVENT_TIMEWARP_COUNT 0x0FFFFF + + +EventScheduler::EventScheduler (const char * const name) +:m_name(name), + m_pendingEventCount(0), + m_timeWarp(this) +{ + memset (&m_pendingEvents, 0, sizeof (Event)); + m_pendingEvents.m_next = &m_pendingEvents; + m_pendingEvents.m_prev = &m_pendingEvents; + reset (); +} + +// Usefull to prevent clock overflowing +void EventScheduler::timeWarp () +{ + Event *e = &m_pendingEvents; + uint count = m_pendingEventCount; + while (count--) + { // Reduce all event clocks and clip them + // so none go negative + event_clock_t clk; + e = e->m_next; + clk = e->m_clk; + e->m_clk = 0; + if (clk >= m_eventClk) + e->m_clk = clk - m_eventClk; + } + m_eventClk = 0; + // Re-schedule the next timeWarp + schedule (&m_timeWarp, EVENT_TIMEWARP_COUNT); +} + +void EventScheduler::reset (void) +{ // Remove all events + Event *e = &m_pendingEvents; + uint count = m_pendingEventCount; + while (count--) + { + e = e->m_next; + e->m_pending = false; + } + m_pendingEvents.m_next = &m_pendingEvents; + m_pendingEvents.m_prev = &m_pendingEvents; + m_pendingEventClk = m_eventClk = m_schedClk = 0; + m_pendingEventCount = 0; + timeWarp (); +} + +// Add event to ordered pending queue +void EventScheduler::schedule (Event *event, event_clock_t cycles) +{ + uint clk = m_eventClk + cycles; + if (event->m_pending) + cancelPending (*event); + event->m_pending = true; + event->m_clk = clk; + + { // Now put in the correct place so we don't need to keep + // searching the list later. + Event *e = m_pendingEvents.m_next; + uint count = m_pendingEventCount; + while (count-- && (e->m_clk <= clk)) + e = e->m_next; + event->m_next = e; + event->m_prev = e->m_prev; + e->m_prev->m_next = event; + e->m_prev = event; + m_pendingEventClk = m_pendingEvents.m_next->m_clk; + m_pendingEventCount++; + } +} + +// Cancel a pending event +void EventScheduler::cancel (Event *event) +{ + if (event->m_pending) + cancelPending (*event); +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/kernal.bin b/plugins/sid/sidplay-libs/libsidplay/src/kernal.bin new file mode 100644 index 00000000..301badb1 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/kernal.bin @@ -0,0 +1,1024 @@ + 0x85, 0x56, 0x20, 0x0f, 0xbc, 0xa5, 0x61, 0xc9, + 0x88, 0x90, 0x03, 0x20, 0xd4, 0xba, 0x20, 0xcc, + 0xbc, 0xa5, 0x07, 0x18, 0x69, 0x81, 0xf0, 0xf3, + 0x38, 0xe9, 0x01, 0x48, 0xa2, 0x05, 0xb5, 0x69, + 0xb4, 0x61, 0x95, 0x61, 0x94, 0x69, 0xca, 0x10, + 0xf5, 0xa5, 0x56, 0x85, 0x70, 0x20, 0x53, 0xb8, + 0x20, 0xb4, 0xbf, 0xa9, 0xc4, 0xa0, 0xbf, 0x20, + 0x59, 0xe0, 0xa9, 0x00, 0x85, 0x6f, 0x68, 0x20, + 0xb9, 0xba, 0x60, 0x85, 0x71, 0x84, 0x72, 0x20, + 0xca, 0xbb, 0xa9, 0x57, 0x20, 0x28, 0xba, 0x20, + 0x5d, 0xe0, 0xa9, 0x57, 0xa0, 0x00, 0x4c, 0x28, + 0xba, 0x85, 0x71, 0x84, 0x72, 0x20, 0xc7, 0xbb, + 0xb1, 0x71, 0x85, 0x67, 0xa4, 0x71, 0xc8, 0x98, + 0xd0, 0x02, 0xe6, 0x72, 0x85, 0x71, 0xa4, 0x72, + 0x20, 0x28, 0xba, 0xa5, 0x71, 0xa4, 0x72, 0x18, + 0x69, 0x05, 0x90, 0x01, 0xc8, 0x85, 0x71, 0x84, + 0x72, 0x20, 0x67, 0xb8, 0xa9, 0x5c, 0xa0, 0x00, + 0xc6, 0x67, 0xd0, 0xe4, 0x60, 0x98, 0x35, 0x44, + 0x7a, 0x00, 0x68, 0x28, 0xb1, 0x46, 0x00, 0x20, + 0x2b, 0xbc, 0x30, 0x37, 0xd0, 0x20, 0x20, 0xf3, + 0xff, 0x86, 0x22, 0x84, 0x23, 0xa0, 0x04, 0xb1, + 0x22, 0x85, 0x62, 0xc8, 0xb1, 0x22, 0x85, 0x64, + 0xa0, 0x08, 0xb1, 0x22, 0x85, 0x63, 0xc8, 0xb1, + 0x22, 0x85, 0x65, 0x4c, 0xe3, 0xe0, 0xa9, 0x8b, + 0xa0, 0x00, 0x20, 0xa2, 0xbb, 0xa9, 0x8d, 0xa0, + 0xe0, 0x20, 0x28, 0xba, 0xa9, 0x92, 0xa0, 0xe0, + 0x20, 0x67, 0xb8, 0xa6, 0x65, 0xa5, 0x62, 0x85, + 0x65, 0x86, 0x62, 0xa6, 0x63, 0xa5, 0x64, 0x85, + 0x63, 0x86, 0x64, 0xa9, 0x00, 0x85, 0x66, 0xa5, + 0x61, 0x85, 0x70, 0xa9, 0x80, 0x85, 0x61, 0x20, + 0xd7, 0xb8, 0xa2, 0x8b, 0xa0, 0x00, 0x4c, 0xd4, + 0xbb, 0xc9, 0xf0, 0xd0, 0x07, 0x84, 0x38, 0x86, + 0x37, 0x4c, 0x63, 0xa6, 0xaa, 0xd0, 0x02, 0xa2, + 0x1e, 0x4c, 0x37, 0xa4, 0x20, 0xd2, 0xff, 0xb0, + 0xe8, 0x60, 0x20, 0xcf, 0xff, 0xb0, 0xe2, 0x60, + 0x20, 0xad, 0xe4, 0xb0, 0xdc, 0x60, 0x20, 0xc6, + 0xff, 0xb0, 0xd6, 0x60, 0x20, 0xe4, 0xff, 0xb0, + 0xd0, 0x60, 0x20, 0x8a, 0xad, 0x20, 0xf7, 0xb7, + 0xa9, 0xe1, 0x48, 0xa9, 0x46, 0x48, 0xad, 0x0f, + 0x03, 0x48, 0xad, 0x0c, 0x03, 0xae, 0x0d, 0x03, + 0xac, 0x0e, 0x03, 0x28, 0x6c, 0x14, 0x00, 0x08, + 0x8d, 0x0c, 0x03, 0x8e, 0x0d, 0x03, 0x8c, 0x0e, + 0x03, 0x68, 0x8d, 0x0f, 0x03, 0x60, 0x20, 0xd4, + 0xe1, 0xa6, 0x2d, 0xa4, 0x2e, 0xa9, 0x2b, 0x20, + 0xd8, 0xff, 0xb0, 0x95, 0x60, 0xa9, 0x01, 0x2c, + 0xa9, 0x00, 0x85, 0x0a, 0x20, 0xd4, 0xe1, 0xa5, + 0x0a, 0xa6, 0x2b, 0xa4, 0x2c, 0x20, 0xd5, 0xff, + 0xb0, 0x57, 0xa5, 0x0a, 0xf0, 0x17, 0xa2, 0x1c, + 0x20, 0xb7, 0xff, 0x29, 0x10, 0xd0, 0x17, 0xa5, + 0x7a, 0xc9, 0x02, 0xf0, 0x07, 0xa9, 0x64, 0xa0, + 0xa3, 0x4c, 0x1e, 0xab, 0x60, 0x20, 0xb7, 0xff, + 0x29, 0xbf, 0xf0, 0x05, 0xa2, 0x1d, 0x4c, 0x37, + 0xa4, 0xa5, 0x7b, 0xc9, 0x02, 0xd0, 0x0e, 0x86, + 0x2d, 0x84, 0x2e, 0xa9, 0x76, 0xa0, 0xa3, 0x20, + 0x1e, 0xab, 0x4c, 0x2a, 0xa5, 0x20, 0x8e, 0xa6, + 0x20, 0x33, 0xa5, 0x4c, 0x77, 0xa6, 0x20, 0x19, + 0xe2, 0x20, 0xc0, 0xff, 0xb0, 0x0b, 0x60, 0x20, + 0x19, 0xe2, 0xa5, 0x49, 0x20, 0xc3, 0xff, 0x90, + 0xc3, 0x4c, 0xf9, 0xe0, 0xa9, 0x00, 0x20, 0xbd, + 0xff, 0xa2, 0x01, 0xa0, 0x00, 0x20, 0xba, 0xff, + 0x20, 0x06, 0xe2, 0x20, 0x57, 0xe2, 0x20, 0x06, + 0xe2, 0x20, 0x00, 0xe2, 0xa0, 0x00, 0x86, 0x49, + 0x20, 0xba, 0xff, 0x20, 0x06, 0xe2, 0x20, 0x00, + 0xe2, 0x8a, 0xa8, 0xa6, 0x49, 0x4c, 0xba, 0xff, + 0x20, 0x0e, 0xe2, 0x4c, 0x9e, 0xb7, 0x20, 0x79, + 0x00, 0xd0, 0x02, 0x68, 0x68, 0x60, 0x20, 0xfd, + 0xae, 0x20, 0x79, 0x00, 0xd0, 0xf7, 0x4c, 0x08, + 0xaf, 0xa9, 0x00, 0x20, 0xbd, 0xff, 0x20, 0x11, + 0xe2, 0x20, 0x9e, 0xb7, 0x86, 0x49, 0x8a, 0xa2, + 0x01, 0xa0, 0x00, 0x20, 0xba, 0xff, 0x20, 0x06, + 0xe2, 0x20, 0x00, 0xe2, 0x86, 0x4a, 0xa0, 0x00, + 0xa5, 0x49, 0xe0, 0x03, 0x90, 0x01, 0x88, 0x20, + 0xba, 0xff, 0x20, 0x06, 0xe2, 0x20, 0x00, 0xe2, + 0x8a, 0xa8, 0xa6, 0x4a, 0xa5, 0x49, 0x20, 0xba, + 0xff, 0x20, 0x06, 0xe2, 0x20, 0x0e, 0xe2, 0x20, + 0x9e, 0xad, 0x20, 0xa3, 0xb6, 0xa6, 0x22, 0xa4, + 0x23, 0x4c, 0xbd, 0xff, 0xa9, 0xe0, 0xa0, 0xe2, + 0x20, 0x67, 0xb8, 0x20, 0x0c, 0xbc, 0xa9, 0xe5, + 0xa0, 0xe2, 0xa6, 0x6e, 0x20, 0x07, 0xbb, 0x20, + 0x0c, 0xbc, 0x20, 0xcc, 0xbc, 0xa9, 0x00, 0x85, + 0x6f, 0x20, 0x53, 0xb8, 0xa9, 0xea, 0xa0, 0xe2, + 0x20, 0x50, 0xb8, 0xa5, 0x66, 0x48, 0x10, 0x0d, + 0x20, 0x49, 0xb8, 0xa5, 0x66, 0x30, 0x09, 0xa5, + 0x12, 0x49, 0xff, 0x85, 0x12, 0x20, 0xb4, 0xbf, + 0xa9, 0xea, 0xa0, 0xe2, 0x20, 0x67, 0xb8, 0x68, + 0x10, 0x03, 0x20, 0xb4, 0xbf, 0xa9, 0xef, 0xa0, + 0xe2, 0x4c, 0x43, 0xe0, 0x20, 0xca, 0xbb, 0xa9, + 0x00, 0x85, 0x12, 0x20, 0x6b, 0xe2, 0xa2, 0x4e, + 0xa0, 0x00, 0x20, 0xf6, 0xe0, 0xa9, 0x57, 0xa0, + 0x00, 0x20, 0xa2, 0xbb, 0xa9, 0x00, 0x85, 0x66, + 0xa5, 0x12, 0x20, 0xdc, 0xe2, 0xa9, 0x4e, 0xa0, + 0x00, 0x4c, 0x0f, 0xbb, 0x48, 0x4c, 0x9d, 0xe2, + 0x81, 0x49, 0x0f, 0xda, 0xa2, 0x83, 0x49, 0x0f, + 0xda, 0xa2, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x84, 0xe6, 0x1a, 0x2d, 0x1b, 0x86, 0x28, 0x07, + 0xfb, 0xf8, 0x87, 0x99, 0x68, 0x89, 0x01, 0x87, + 0x23, 0x35, 0xdf, 0xe1, 0x86, 0xa5, 0x5d, 0xe7, + 0x28, 0x83, 0x49, 0x0f, 0xda, 0xa2, 0xa5, 0x66, + 0x48, 0x10, 0x03, 0x20, 0xb4, 0xbf, 0xa5, 0x61, + 0x48, 0xc9, 0x81, 0x90, 0x07, 0xa9, 0xbc, 0xa0, + 0xb9, 0x20, 0x0f, 0xbb, 0xa9, 0x3e, 0xa0, 0xe3, + 0x20, 0x43, 0xe0, 0x68, 0xc9, 0x81, 0x90, 0x07, + 0xa9, 0xe0, 0xa0, 0xe2, 0x20, 0x50, 0xb8, 0x68, + 0x10, 0x03, 0x4c, 0xb4, 0xbf, 0x60, 0x0b, 0x76, + 0xb3, 0x83, 0xbd, 0xd3, 0x79, 0x1e, 0xf4, 0xa6, + 0xf5, 0x7b, 0x83, 0xfc, 0xb0, 0x10, 0x7c, 0x0c, + 0x1f, 0x67, 0xca, 0x7c, 0xde, 0x53, 0xcb, 0xc1, + 0x7d, 0x14, 0x64, 0x70, 0x4c, 0x7d, 0xb7, 0xea, + 0x51, 0x7a, 0x7d, 0x63, 0x30, 0x88, 0x7e, 0x7e, + 0x92, 0x44, 0x99, 0x3a, 0x7e, 0x4c, 0xcc, 0x91, + 0xc7, 0x7f, 0xaa, 0xaa, 0xaa, 0x13, 0x81, 0x00, + 0x00, 0x00, 0x00, 0x20, 0xcc, 0xff, 0xa9, 0x00, + 0x85, 0x13, 0x20, 0x7a, 0xa6, 0x58, 0xa2, 0x80, + 0x6c, 0x00, 0x03, 0x8a, 0x30, 0x03, 0x4c, 0x3a, + 0xa4, 0x4c, 0x74, 0xa4, 0x20, 0x53, 0xe4, 0x20, + 0xbf, 0xe3, 0x20, 0x22, 0xe4, 0xa2, 0xfb, 0x9a, + 0xd0, 0xe4, 0xe6, 0x7a, 0xd0, 0x02, 0xe6, 0x7b, + 0xad, 0x60, 0xea, 0xc9, 0x3a, 0xb0, 0x0a, 0xc9, + 0x20, 0xf0, 0xef, 0x38, 0xe9, 0x30, 0x38, 0xe9, + 0xd0, 0x60, 0x80, 0x4f, 0xc7, 0x52, 0x58, 0xa9, + 0x4c, 0x85, 0x54, 0x8d, 0x10, 0x03, 0xa9, 0x48, + 0xa0, 0xb2, 0x8d, 0x11, 0x03, 0x8c, 0x12, 0x03, + 0xa9, 0x91, 0xa0, 0xb3, 0x85, 0x05, 0x84, 0x06, + 0xa9, 0xaa, 0xa0, 0xb1, 0x85, 0x03, 0x84, 0x04, + 0xa2, 0x1c, 0xbd, 0xa2, 0xe3, 0x95, 0x73, 0xca, + 0x10, 0xf8, 0xa9, 0x03, 0x85, 0x53, 0xa9, 0x00, + 0x85, 0x68, 0x85, 0x13, 0x85, 0x18, 0xa2, 0x01, + 0x8e, 0xfd, 0x01, 0x8e, 0xfc, 0x01, 0xa2, 0x19, + 0x86, 0x16, 0x38, 0x20, 0x9c, 0xff, 0x86, 0x2b, + 0x84, 0x2c, 0x38, 0x20, 0x99, 0xff, 0x86, 0x37, + 0x84, 0x38, 0x86, 0x33, 0x84, 0x34, 0xa0, 0x00, + 0x98, 0x91, 0x2b, 0xe6, 0x2b, 0xd0, 0x02, 0xe6, + 0x2c, 0x60, 0xa5, 0x2b, 0xa4, 0x2c, 0x20, 0x08, + 0xa4, 0xa9, 0x73, 0xa0, 0xe4, 0x20, 0x1e, 0xab, + 0xa5, 0x37, 0x38, 0xe5, 0x2b, 0xaa, 0xa5, 0x38, + 0xe5, 0x2c, 0x20, 0xcd, 0xbd, 0xa9, 0x60, 0xa0, + 0xe4, 0x20, 0x1e, 0xab, 0x4c, 0x44, 0xa6, 0x8b, + 0xe3, 0x83, 0xa4, 0x7c, 0xa5, 0x1a, 0xa7, 0xe4, + 0xa7, 0x86, 0xae, 0xa2, 0x0b, 0xbd, 0x47, 0xe4, + 0x9d, 0x00, 0x03, 0xca, 0x10, 0xf7, 0x60, 0x00, + 0x20, 0x42, 0x41, 0x53, 0x49, 0x43, 0x20, 0x42, + 0x59, 0x54, 0x45, 0x53, 0x20, 0x46, 0x52, 0x45, + 0x45, 0x0d, 0x00, 0x93, 0x0d, 0x20, 0x20, 0x20, + 0x20, 0x2a, 0x2a, 0x2a, 0x2a, 0x20, 0x43, 0x4f, + 0x4d, 0x4d, 0x4f, 0x44, 0x4f, 0x52, 0x45, 0x20, + 0x36, 0x34, 0x20, 0x42, 0x41, 0x53, 0x49, 0x43, + 0x20, 0x56, 0x32, 0x20, 0x2a, 0x2a, 0x2a, 0x2a, + 0x0d, 0x0d, 0x20, 0x36, 0x34, 0x4b, 0x20, 0x52, + 0x41, 0x4d, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, + 0x4d, 0x20, 0x20, 0x00, 0x81, 0x48, 0x20, 0xc9, + 0xff, 0xaa, 0x68, 0x90, 0x01, 0x8a, 0x60, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0x85, 0xa9, 0xa9, 0x01, 0x85, + 0xab, 0x60, 0xad, 0x86, 0x02, 0x91, 0xf3, 0x60, + 0x69, 0x02, 0xa4, 0x91, 0xc8, 0xd0, 0x04, 0xc5, + 0xa1, 0xd0, 0xf7, 0x60, 0x19, 0x26, 0x44, 0x19, + 0x1a, 0x11, 0xe8, 0x0d, 0x70, 0x0c, 0x06, 0x06, + 0xd1, 0x02, 0x37, 0x01, 0xae, 0x00, 0x69, 0x00, + 0xa2, 0x00, 0xa0, 0xdc, 0x60, 0xa2, 0x28, 0xa0, + 0x19, 0x60, 0xb0, 0x07, 0x86, 0xd6, 0x84, 0xd3, + 0x20, 0x6c, 0xe5, 0xa6, 0xd6, 0xa4, 0xd3, 0x60, + 0x20, 0xa0, 0xe5, 0xa9, 0x00, 0x8d, 0x91, 0x02, + 0x85, 0xcf, 0xa9, 0x48, 0x8d, 0x8f, 0x02, 0xa9, + 0xeb, 0x8d, 0x90, 0x02, 0xa9, 0x0a, 0x8d, 0x89, + 0x02, 0x8d, 0x8c, 0x02, 0xa9, 0x0e, 0x8d, 0x86, + 0x02, 0xa9, 0x04, 0x8d, 0x8b, 0x02, 0xa9, 0x0c, + 0x85, 0xcd, 0x85, 0xcc, 0xad, 0x88, 0x02, 0x09, + 0x80, 0xa8, 0xa9, 0x00, 0xaa, 0x94, 0xd9, 0x18, + 0x69, 0x28, 0x90, 0x01, 0xc8, 0xe8, 0xe0, 0x1a, + 0xd0, 0xf3, 0xa9, 0xff, 0x95, 0xd9, 0xa2, 0x18, + 0x20, 0xff, 0xe9, 0xca, 0x10, 0xfa, 0xa0, 0x00, + 0x84, 0xd3, 0x84, 0xd6, 0xa6, 0xd6, 0xa5, 0xd3, + 0xb4, 0xd9, 0x30, 0x08, 0x18, 0x69, 0x28, 0x85, + 0xd3, 0xca, 0x10, 0xf4, 0x20, 0xf0, 0xe9, 0xa9, + 0x27, 0xe8, 0xb4, 0xd9, 0x30, 0x06, 0x18, 0x69, + 0x28, 0xe8, 0x10, 0xf6, 0x85, 0xd5, 0x4c, 0x24, + 0xea, 0xe4, 0xc9, 0xf0, 0x03, 0x4c, 0xed, 0xe6, + 0x60, 0xea, 0x20, 0xa0, 0xe5, 0x4c, 0x66, 0xe5, + 0xa9, 0x03, 0x85, 0x9a, 0xa9, 0x00, 0x85, 0x99, + 0xa2, 0x2f, 0xbd, 0xb8, 0xec, 0x9d, 0xff, 0xcf, + 0xca, 0xd0, 0xf7, 0x60, 0xac, 0x77, 0x02, 0xa2, + 0x00, 0xbd, 0x78, 0x02, 0x9d, 0x77, 0x02, 0xe8, + 0xe4, 0xc6, 0xd0, 0xf5, 0xc6, 0xc6, 0x98, 0x58, + 0x18, 0x60, 0x20, 0x16, 0xe7, 0xa5, 0xc6, 0x85, + 0xcc, 0x8d, 0x92, 0x02, 0xf0, 0xf7, 0x78, 0xa5, + 0xcf, 0xf0, 0x0c, 0xa5, 0xce, 0xae, 0x87, 0x02, + 0xa0, 0x00, 0x84, 0xcf, 0x20, 0x13, 0xea, 0x20, + 0xb4, 0xe5, 0xc9, 0x83, 0xd0, 0x10, 0xa2, 0x09, + 0x78, 0x86, 0xc6, 0xbd, 0xe6, 0xec, 0x9d, 0x76, + 0x02, 0xca, 0xd0, 0xf7, 0xf0, 0xcf, 0xc9, 0x0d, + 0xd0, 0xc8, 0xa4, 0xd5, 0x84, 0xd0, 0xb1, 0xd1, + 0xc9, 0x20, 0xd0, 0x03, 0x88, 0xd0, 0xf7, 0xc8, + 0x84, 0xc8, 0xa0, 0x00, 0x8c, 0x92, 0x02, 0x84, + 0xd3, 0x84, 0xd4, 0xa5, 0xc9, 0x30, 0x1b, 0xa6, + 0xd6, 0x20, 0x91, 0xe5, 0xe4, 0xc9, 0xd0, 0x12, + 0xa5, 0xca, 0x85, 0xd3, 0xc5, 0xc8, 0x90, 0x0a, + 0xb0, 0x2b, 0x98, 0x48, 0x8a, 0x48, 0xa5, 0xd0, + 0xf0, 0x93, 0xa4, 0xd3, 0xb1, 0xd1, 0x85, 0xd7, + 0x29, 0x3f, 0x06, 0xd7, 0x24, 0xd7, 0x10, 0x02, + 0x09, 0x80, 0x90, 0x04, 0xa6, 0xd4, 0xd0, 0x04, + 0x70, 0x02, 0x09, 0x40, 0xe6, 0xd3, 0x20, 0x84, + 0xe6, 0xc4, 0xc8, 0xd0, 0x17, 0xa9, 0x00, 0x85, + 0xd0, 0xa9, 0x0d, 0xa6, 0x99, 0xe0, 0x03, 0xf0, + 0x06, 0xa6, 0x9a, 0xe0, 0x03, 0xf0, 0x03, 0x20, + 0x16, 0xe7, 0xa9, 0x0d, 0x85, 0xd7, 0x68, 0xaa, + 0x68, 0xa8, 0xa5, 0xd7, 0xc9, 0xde, 0xd0, 0x02, + 0xa9, 0xff, 0x18, 0x60, 0xc9, 0x22, 0xd0, 0x08, + 0xa5, 0xd4, 0x49, 0x01, 0x85, 0xd4, 0xa9, 0x22, + 0x60, 0x09, 0x40, 0xa6, 0xc7, 0xf0, 0x02, 0x09, + 0x80, 0xa6, 0xd8, 0xf0, 0x02, 0xc6, 0xd8, 0xae, + 0x86, 0x02, 0x20, 0x13, 0xea, 0x20, 0xb6, 0xe6, + 0x68, 0xa8, 0xa5, 0xd8, 0xf0, 0x02, 0x46, 0xd4, + 0x68, 0xaa, 0x68, 0x18, 0x58, 0x60, 0x20, 0xb3, + 0xe8, 0xe6, 0xd3, 0xa5, 0xd5, 0xc5, 0xd3, 0xb0, + 0x3f, 0xc9, 0x4f, 0xf0, 0x32, 0xad, 0x92, 0x02, + 0xf0, 0x03, 0x4c, 0x67, 0xe9, 0xa6, 0xd6, 0xe0, + 0x19, 0x90, 0x07, 0x20, 0xea, 0xe8, 0xc6, 0xd6, + 0xa6, 0xd6, 0x16, 0xd9, 0x56, 0xd9, 0xe8, 0xb5, + 0xd9, 0x09, 0x80, 0x95, 0xd9, 0xca, 0xa5, 0xd5, + 0x18, 0x69, 0x28, 0x85, 0xd5, 0xb5, 0xd9, 0x30, + 0x03, 0xca, 0xd0, 0xf9, 0x4c, 0xf0, 0xe9, 0xc6, + 0xd6, 0x20, 0x7c, 0xe8, 0xa9, 0x00, 0x85, 0xd3, + 0x60, 0xa6, 0xd6, 0xd0, 0x06, 0x86, 0xd3, 0x68, + 0x68, 0xd0, 0x9d, 0xca, 0x86, 0xd6, 0x20, 0x6c, + 0xe5, 0xa4, 0xd5, 0x84, 0xd3, 0x60, 0x48, 0x85, + 0xd7, 0x8a, 0x48, 0x98, 0x48, 0xa9, 0x00, 0x85, + 0xd0, 0xa4, 0xd3, 0xa5, 0xd7, 0x10, 0x03, 0x4c, + 0xd4, 0xe7, 0xc9, 0x0d, 0xd0, 0x03, 0x4c, 0x91, + 0xe8, 0xc9, 0x20, 0x90, 0x10, 0xc9, 0x60, 0x90, + 0x04, 0x29, 0xdf, 0xd0, 0x02, 0x29, 0x3f, 0x20, + 0x84, 0xe6, 0x4c, 0x93, 0xe6, 0xa6, 0xd8, 0xf0, + 0x03, 0x4c, 0x97, 0xe6, 0xc9, 0x14, 0xd0, 0x2e, + 0x98, 0xd0, 0x06, 0x20, 0x01, 0xe7, 0x4c, 0x73, + 0xe7, 0x20, 0xa1, 0xe8, 0x88, 0x84, 0xd3, 0x20, + 0x24, 0xea, 0xc8, 0xb1, 0xd1, 0x88, 0x91, 0xd1, + 0xc8, 0xb1, 0xf3, 0x88, 0x91, 0xf3, 0xc8, 0xc4, + 0xd5, 0xd0, 0xef, 0xa9, 0x20, 0x91, 0xd1, 0xad, + 0x86, 0x02, 0x91, 0xf3, 0x10, 0x4d, 0xa6, 0xd4, + 0xf0, 0x03, 0x4c, 0x97, 0xe6, 0xc9, 0x12, 0xd0, + 0x02, 0x85, 0xc7, 0xc9, 0x13, 0xd0, 0x03, 0x20, + 0x66, 0xe5, 0xc9, 0x1d, 0xd0, 0x17, 0xc8, 0x20, + 0xb3, 0xe8, 0x84, 0xd3, 0x88, 0xc4, 0xd5, 0x90, + 0x09, 0xc6, 0xd6, 0x20, 0x7c, 0xe8, 0xa0, 0x00, + 0x84, 0xd3, 0x4c, 0xa8, 0xe6, 0xc9, 0x11, 0xd0, + 0x1d, 0x18, 0x98, 0x69, 0x28, 0xa8, 0xe6, 0xd6, + 0xc5, 0xd5, 0x90, 0xec, 0xf0, 0xea, 0xc6, 0xd6, + 0xe9, 0x28, 0x90, 0x04, 0x85, 0xd3, 0xd0, 0xf8, + 0x20, 0x7c, 0xe8, 0x4c, 0xa8, 0xe6, 0x20, 0xcb, + 0xe8, 0x4c, 0x44, 0xec, 0x29, 0x7f, 0xc9, 0x7f, + 0xd0, 0x02, 0xa9, 0x5e, 0xc9, 0x20, 0x90, 0x03, + 0x4c, 0x91, 0xe6, 0xc9, 0x0d, 0xd0, 0x03, 0x4c, + 0x91, 0xe8, 0xa6, 0xd4, 0xd0, 0x3f, 0xc9, 0x14, + 0xd0, 0x37, 0xa4, 0xd5, 0xb1, 0xd1, 0xc9, 0x20, + 0xd0, 0x04, 0xc4, 0xd3, 0xd0, 0x07, 0xc0, 0x4f, + 0xf0, 0x24, 0x20, 0x65, 0xe9, 0xa4, 0xd5, 0x20, + 0x24, 0xea, 0x88, 0xb1, 0xd1, 0xc8, 0x91, 0xd1, + 0x88, 0xb1, 0xf3, 0xc8, 0x91, 0xf3, 0x88, 0xc4, + 0xd3, 0xd0, 0xef, 0xa9, 0x20, 0x91, 0xd1, 0xad, + 0x86, 0x02, 0x91, 0xf3, 0xe6, 0xd8, 0x4c, 0xa8, + 0xe6, 0xa6, 0xd8, 0xf0, 0x05, 0x09, 0x40, 0x4c, + 0x97, 0xe6, 0xc9, 0x11, 0xd0, 0x16, 0xa6, 0xd6, + 0xf0, 0x37, 0xc6, 0xd6, 0xa5, 0xd3, 0x38, 0xe9, + 0x28, 0x90, 0x04, 0x85, 0xd3, 0x10, 0x2a, 0x20, + 0x6c, 0xe5, 0xd0, 0x25, 0xc9, 0x12, 0xd0, 0x04, + 0xa9, 0x00, 0x85, 0xc7, 0xc9, 0x1d, 0xd0, 0x12, + 0x98, 0xf0, 0x09, 0x20, 0xa1, 0xe8, 0x88, 0x84, + 0xd3, 0x4c, 0xa8, 0xe6, 0x20, 0x01, 0xe7, 0x4c, + 0xa8, 0xe6, 0xc9, 0x13, 0xd0, 0x06, 0x20, 0x44, + 0xe5, 0x4c, 0xa8, 0xe6, 0x09, 0x80, 0x20, 0xcb, + 0xe8, 0x4c, 0x4f, 0xec, 0x46, 0xc9, 0xa6, 0xd6, + 0xe8, 0xe0, 0x19, 0xd0, 0x03, 0x20, 0xea, 0xe8, + 0xb5, 0xd9, 0x10, 0xf4, 0x86, 0xd6, 0x4c, 0x6c, + 0xe5, 0xa2, 0x00, 0x86, 0xd8, 0x86, 0xc7, 0x86, + 0xd4, 0x86, 0xd3, 0x20, 0x7c, 0xe8, 0x4c, 0xa8, + 0xe6, 0xa2, 0x02, 0xa9, 0x00, 0xc5, 0xd3, 0xf0, + 0x07, 0x18, 0x69, 0x28, 0xca, 0xd0, 0xf6, 0x60, + 0xc6, 0xd6, 0x60, 0xa2, 0x02, 0xa9, 0x27, 0xc5, + 0xd3, 0xf0, 0x07, 0x18, 0x69, 0x28, 0xca, 0xd0, + 0xf6, 0x60, 0xa6, 0xd6, 0xe0, 0x19, 0xf0, 0x02, + 0xe6, 0xd6, 0x60, 0xa2, 0x0f, 0xdd, 0xda, 0xe8, + 0xf0, 0x04, 0xca, 0x10, 0xf8, 0x60, 0x8e, 0x86, + 0x02, 0x60, 0x90, 0x05, 0x1c, 0x9f, 0x9c, 0x1e, + 0x1f, 0x9e, 0x81, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9a, 0x9b, 0xa5, 0xac, 0x48, 0xa5, 0xad, 0x48, + 0xa5, 0xae, 0x48, 0xa5, 0xaf, 0x48, 0xa2, 0xff, + 0xc6, 0xd6, 0xc6, 0xc9, 0xce, 0xa5, 0x02, 0xe8, + 0x20, 0xf0, 0xe9, 0xe0, 0x18, 0xb0, 0x0c, 0xbd, + 0xf1, 0xec, 0x85, 0xac, 0xb5, 0xda, 0x20, 0xc8, + 0xe9, 0x30, 0xec, 0x20, 0xff, 0xe9, 0xa2, 0x00, + 0xb5, 0xd9, 0x29, 0x7f, 0xb4, 0xda, 0x10, 0x02, + 0x09, 0x80, 0x95, 0xd9, 0xe8, 0xe0, 0x18, 0xd0, + 0xef, 0xa5, 0xf1, 0x09, 0x80, 0x85, 0xf1, 0xa5, + 0xd9, 0x10, 0xc3, 0xe6, 0xd6, 0xee, 0xa5, 0x02, + 0xa9, 0x7f, 0x8d, 0x00, 0xdc, 0xad, 0x01, 0xdc, + 0xc9, 0xfb, 0x08, 0xa9, 0x7f, 0x8d, 0x00, 0xdc, + 0x28, 0xd0, 0x0b, 0xa0, 0x00, 0xea, 0xca, 0xd0, + 0xfc, 0x88, 0xd0, 0xf9, 0x84, 0xc6, 0xa6, 0xd6, + 0x68, 0x85, 0xaf, 0x68, 0x85, 0xae, 0x68, 0x85, + 0xad, 0x68, 0x85, 0xac, 0x60, 0xa6, 0xd6, 0xe8, + 0xb5, 0xd9, 0x10, 0xfb, 0x8e, 0xa5, 0x02, 0xe0, + 0x18, 0xf0, 0x0e, 0x90, 0x0c, 0x20, 0xea, 0xe8, + 0xae, 0xa5, 0x02, 0xca, 0xc6, 0xd6, 0x4c, 0xda, + 0xe6, 0xa5, 0xac, 0x48, 0xa5, 0xad, 0x48, 0xa5, + 0xae, 0x48, 0xa5, 0xaf, 0x48, 0xa2, 0x19, 0xca, + 0x20, 0xf0, 0xe9, 0xec, 0xa5, 0x02, 0x90, 0x0e, + 0xf0, 0x0c, 0xbd, 0xef, 0xec, 0x85, 0xac, 0xb5, + 0xd8, 0x20, 0xc8, 0xe9, 0x30, 0xe9, 0x20, 0xff, + 0xe9, 0xa2, 0x17, 0xec, 0xa5, 0x02, 0x90, 0x0f, + 0xb5, 0xda, 0x29, 0x7f, 0xb4, 0xd9, 0x10, 0x02, + 0x09, 0x80, 0x95, 0xda, 0xca, 0xd0, 0xec, 0xae, + 0xa5, 0x02, 0x20, 0xda, 0xe6, 0x4c, 0x58, 0xe9, + 0x29, 0x03, 0x0d, 0x88, 0x02, 0x85, 0xad, 0x20, + 0xe0, 0xe9, 0xa0, 0x27, 0xb1, 0xac, 0x91, 0xd1, + 0xb1, 0xae, 0x91, 0xf3, 0x88, 0x10, 0xf5, 0x60, + 0x20, 0x24, 0xea, 0xa5, 0xac, 0x85, 0xae, 0xa5, + 0xad, 0x29, 0x03, 0x09, 0xd8, 0x85, 0xaf, 0x60, + 0xbd, 0xf0, 0xec, 0x85, 0xd1, 0xb5, 0xd9, 0x29, + 0x03, 0x0d, 0x88, 0x02, 0x85, 0xd2, 0x60, 0xa0, + 0x27, 0x20, 0xf0, 0xe9, 0x20, 0x24, 0xea, 0x20, + 0xda, 0xe4, 0xa9, 0x20, 0x91, 0xd1, 0x88, 0x10, + 0xf6, 0x60, 0xea, 0xa8, 0xa9, 0x02, 0x85, 0xcd, + 0x20, 0x24, 0xea, 0x98, 0xa4, 0xd3, 0x91, 0xd1, + 0x8a, 0x91, 0xf3, 0x60, 0xa5, 0xd1, 0x85, 0xf3, + 0xa5, 0xd2, 0x29, 0x03, 0x09, 0xd8, 0x85, 0xf4, + 0x60, 0x20, 0xea, 0xff, 0xa5, 0xcc, 0xd0, 0x29, + 0xc6, 0xcd, 0xd0, 0x25, 0xa9, 0x14, 0x85, 0xcd, + 0xa4, 0xd3, 0x46, 0xcf, 0xae, 0x87, 0x02, 0xb1, + 0xd1, 0xb0, 0x11, 0xe6, 0xcf, 0x85, 0xce, 0x20, + 0x24, 0xea, 0xb1, 0xf3, 0x8d, 0x87, 0x02, 0xae, + 0x86, 0x02, 0xa5, 0xce, 0x49, 0x80, 0x20, 0x1c, + 0xea, 0xa5, 0x01, 0x29, 0x10, 0xf0, 0x0a, 0xa0, + 0x00, 0x84, 0xc0, 0xa5, 0x01, 0x09, 0x20, 0xd0, + 0x08, 0xa5, 0xc0, 0xd0, 0x06, 0xa5, 0x01, 0x29, + 0x1f, 0x85, 0x01, 0x20, 0x87, 0xea, 0xad, 0x0d, + 0xdc, 0x68, 0xa8, 0x68, 0xaa, 0x68, 0x40, 0xa9, + 0x00, 0x8d, 0x8d, 0x02, 0xa0, 0x40, 0x84, 0xcb, + 0x8d, 0x00, 0xdc, 0xae, 0x01, 0xdc, 0xe0, 0xff, + 0xf0, 0x61, 0xa8, 0xa9, 0x81, 0x85, 0xf5, 0xa9, + 0xeb, 0x85, 0xf6, 0xa9, 0xfe, 0x8d, 0x00, 0xdc, + 0xa2, 0x08, 0x48, 0xad, 0x01, 0xdc, 0xcd, 0x01, + 0xdc, 0xd0, 0xf8, 0x4a, 0xb0, 0x16, 0x48, 0xb1, + 0xf5, 0xc9, 0x05, 0xb0, 0x0c, 0xc9, 0x03, 0xf0, + 0x08, 0x0d, 0x8d, 0x02, 0x8d, 0x8d, 0x02, 0x10, + 0x02, 0x84, 0xcb, 0x68, 0xc8, 0xc0, 0x41, 0xb0, + 0x0b, 0xca, 0xd0, 0xdf, 0x38, 0x68, 0x2a, 0x8d, + 0x00, 0xdc, 0xd0, 0xcc, 0x68, 0x6c, 0x8f, 0x02, + 0xa4, 0xcb, 0xb1, 0xf5, 0xaa, 0xc4, 0xc5, 0xf0, + 0x07, 0xa0, 0x10, 0x8c, 0x8c, 0x02, 0xd0, 0x36, + 0x29, 0x7f, 0x2c, 0x8a, 0x02, 0x30, 0x16, 0x70, + 0x49, 0xc9, 0x7f, 0xf0, 0x29, 0xc9, 0x14, 0xf0, + 0x0c, 0xc9, 0x20, 0xf0, 0x08, 0xc9, 0x1d, 0xf0, + 0x04, 0xc9, 0x11, 0xd0, 0x35, 0xac, 0x8c, 0x02, + 0xf0, 0x05, 0xce, 0x8c, 0x02, 0xd0, 0x2b, 0xce, + 0x8b, 0x02, 0xd0, 0x26, 0xa0, 0x04, 0x8c, 0x8b, + 0x02, 0xa4, 0xc6, 0x88, 0x10, 0x1c, 0xa4, 0xcb, + 0x84, 0xc5, 0xac, 0x8d, 0x02, 0x8c, 0x8e, 0x02, + 0xe0, 0xff, 0xf0, 0x0e, 0x8a, 0xa6, 0xc6, 0xec, + 0x89, 0x02, 0xb0, 0x06, 0x9d, 0x77, 0x02, 0xe8, + 0x86, 0xc6, 0xa9, 0x7f, 0x8d, 0x00, 0xdc, 0x60, + 0xad, 0x8d, 0x02, 0xc9, 0x03, 0xd0, 0x15, 0xcd, + 0x8e, 0x02, 0xf0, 0xee, 0xad, 0x91, 0x02, 0x30, + 0x1d, 0xad, 0x18, 0xd0, 0x49, 0x02, 0x8d, 0x18, + 0xd0, 0x4c, 0x76, 0xeb, 0x0a, 0xc9, 0x08, 0x90, + 0x02, 0xa9, 0x06, 0xaa, 0xbd, 0x79, 0xeb, 0x85, + 0xf5, 0xbd, 0x7a, 0xeb, 0x85, 0xf6, 0x4c, 0xe0, + 0xea, 0x81, 0xeb, 0xc2, 0xeb, 0x03, 0xec, 0x78, + 0xec, 0x14, 0x0d, 0x1d, 0x88, 0x85, 0x86, 0x87, + 0x11, 0x33, 0x57, 0x41, 0x34, 0x5a, 0x53, 0x45, + 0x01, 0x35, 0x52, 0x44, 0x36, 0x43, 0x46, 0x54, + 0x58, 0x37, 0x59, 0x47, 0x38, 0x42, 0x48, 0x55, + 0x56, 0x39, 0x49, 0x4a, 0x30, 0x4d, 0x4b, 0x4f, + 0x4e, 0x2b, 0x50, 0x4c, 0x2d, 0x2e, 0x3a, 0x40, + 0x2c, 0x5c, 0x2a, 0x3b, 0x13, 0x01, 0x3d, 0x5e, + 0x2f, 0x31, 0x5f, 0x04, 0x32, 0x20, 0x02, 0x51, + 0x03, 0xff, 0x94, 0x8d, 0x9d, 0x8c, 0x89, 0x8a, + 0x8b, 0x91, 0x23, 0xd7, 0xc1, 0x24, 0xda, 0xd3, + 0xc5, 0x01, 0x25, 0xd2, 0xc4, 0x26, 0xc3, 0xc6, + 0xd4, 0xd8, 0x27, 0xd9, 0xc7, 0x28, 0xc2, 0xc8, + 0xd5, 0xd6, 0x29, 0xc9, 0xca, 0x30, 0xcd, 0xcb, + 0xcf, 0xce, 0xdb, 0xd0, 0xcc, 0xdd, 0x3e, 0x5b, + 0xba, 0x3c, 0xa9, 0xc0, 0x5d, 0x93, 0x01, 0x3d, + 0xde, 0x3f, 0x21, 0x5f, 0x04, 0x22, 0xa0, 0x02, + 0xd1, 0x83, 0xff, 0x94, 0x8d, 0x9d, 0x8c, 0x89, + 0x8a, 0x8b, 0x91, 0x96, 0xb3, 0xb0, 0x97, 0xad, + 0xae, 0xb1, 0x01, 0x98, 0xb2, 0xac, 0x99, 0xbc, + 0xbb, 0xa3, 0xbd, 0x9a, 0xb7, 0xa5, 0x9b, 0xbf, + 0xb4, 0xb8, 0xbe, 0x29, 0xa2, 0xb5, 0x30, 0xa7, + 0xa1, 0xb9, 0xaa, 0xa6, 0xaf, 0xb6, 0xdc, 0x3e, + 0x5b, 0xa4, 0x3c, 0xa8, 0xdf, 0x5d, 0x93, 0x01, + 0x3d, 0xde, 0x3f, 0x81, 0x5f, 0x04, 0x95, 0xa0, + 0x02, 0xab, 0x83, 0xff, 0xc9, 0x0e, 0xd0, 0x07, + 0xad, 0x18, 0xd0, 0x09, 0x02, 0xd0, 0x09, 0xc9, + 0x8e, 0xd0, 0x0b, 0xad, 0x18, 0xd0, 0x29, 0xfd, + 0x8d, 0x18, 0xd0, 0x4c, 0xa8, 0xe6, 0xc9, 0x08, + 0xd0, 0x07, 0xa9, 0x80, 0x0d, 0x91, 0x02, 0x30, + 0x09, 0xc9, 0x09, 0xd0, 0xee, 0xa9, 0x7f, 0x2d, + 0x91, 0x02, 0x8d, 0x91, 0x02, 0x4c, 0xa8, 0xe6, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1c, 0x17, 0x01, 0x9f, 0x1a, 0x13, 0x05, 0xff, + 0x9c, 0x12, 0x04, 0x1e, 0x03, 0x06, 0x14, 0x18, + 0x1f, 0x19, 0x07, 0x9e, 0x02, 0x08, 0x15, 0x16, + 0x12, 0x09, 0x0a, 0x92, 0x0d, 0x0b, 0x0f, 0x0e, + 0xff, 0x10, 0x0c, 0xff, 0xff, 0x1b, 0x00, 0xff, + 0x1c, 0xff, 0x1d, 0xff, 0xff, 0x1f, 0x1e, 0xff, + 0x90, 0x06, 0xff, 0x05, 0xff, 0xff, 0x11, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x9b, 0x37, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x14, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x06, 0x01, 0x02, 0x03, 0x04, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x4c, + 0x4f, 0x41, 0x44, 0x0d, 0x52, 0x55, 0x4e, 0x0d, + 0x00, 0x28, 0x50, 0x78, 0xa0, 0xc8, 0xf0, 0x18, + 0x40, 0x68, 0x90, 0xb8, 0xe0, 0x08, 0x30, 0x58, + 0x80, 0xa8, 0xd0, 0xf8, 0x20, 0x48, 0x70, 0x98, + 0xc0, 0x09, 0x40, 0x2c, 0x09, 0x20, 0x20, 0xa4, + 0xf0, 0x48, 0x24, 0x94, 0x10, 0x0a, 0x38, 0x66, + 0xa3, 0x20, 0x40, 0xed, 0x46, 0x94, 0x46, 0xa3, + 0x68, 0x85, 0x95, 0x78, 0x20, 0x97, 0xee, 0xc9, + 0x3f, 0xd0, 0x03, 0x20, 0x85, 0xee, 0xad, 0x00, + 0xdd, 0x09, 0x08, 0x8d, 0x00, 0xdd, 0x78, 0x20, + 0x8e, 0xee, 0x20, 0x97, 0xee, 0x20, 0xb3, 0xee, + 0x78, 0x20, 0x97, 0xee, 0x20, 0xa9, 0xee, 0xb0, + 0x64, 0x20, 0x85, 0xee, 0x24, 0xa3, 0x10, 0x0a, + 0x20, 0xa9, 0xee, 0x90, 0xfb, 0x20, 0xa9, 0xee, + 0xb0, 0xfb, 0x20, 0xa9, 0xee, 0x90, 0xfb, 0x20, + 0x8e, 0xee, 0xa9, 0x08, 0x85, 0xa5, 0xad, 0x00, + 0xdd, 0xcd, 0x00, 0xdd, 0xd0, 0xf8, 0x0a, 0x90, + 0x3f, 0x66, 0x95, 0xb0, 0x05, 0x20, 0xa0, 0xee, + 0xd0, 0x03, 0x20, 0x97, 0xee, 0x20, 0x85, 0xee, + 0xea, 0xea, 0xea, 0xea, 0xad, 0x00, 0xdd, 0x29, + 0xdf, 0x09, 0x10, 0x8d, 0x00, 0xdd, 0xc6, 0xa5, + 0xd0, 0xd4, 0xa9, 0x04, 0x8d, 0x07, 0xdc, 0xa9, + 0x19, 0x8d, 0x0f, 0xdc, 0xad, 0x0d, 0xdc, 0xad, + 0x0d, 0xdc, 0x29, 0x02, 0xd0, 0x0a, 0x20, 0xa9, + 0xee, 0xb0, 0xf4, 0x58, 0x60, 0xa9, 0x80, 0x2c, + 0xa9, 0x03, 0x20, 0x1c, 0xfe, 0x58, 0x18, 0x90, + 0x4a, 0x85, 0x95, 0x20, 0x36, 0xed, 0xad, 0x00, + 0xdd, 0x29, 0xf7, 0x8d, 0x00, 0xdd, 0x60, 0x85, + 0x95, 0x20, 0x36, 0xed, 0x78, 0x20, 0xa0, 0xee, + 0x20, 0xbe, 0xed, 0x20, 0x85, 0xee, 0x20, 0xa9, + 0xee, 0x30, 0xfb, 0x58, 0x60, 0x24, 0x94, 0x30, + 0x05, 0x38, 0x66, 0x94, 0xd0, 0x05, 0x48, 0x20, + 0x40, 0xed, 0x68, 0x85, 0x95, 0x18, 0x60, 0x78, + 0x20, 0x8e, 0xee, 0xad, 0x00, 0xdd, 0x09, 0x08, + 0x8d, 0x00, 0xdd, 0xa9, 0x5f, 0x2c, 0xa9, 0x3f, + 0x20, 0x11, 0xed, 0x20, 0xbe, 0xed, 0x8a, 0xa2, + 0x0a, 0xca, 0xd0, 0xfd, 0xaa, 0x20, 0x85, 0xee, + 0x4c, 0x97, 0xee, 0x78, 0xa9, 0x00, 0x85, 0xa5, + 0x20, 0x85, 0xee, 0x20, 0xa9, 0xee, 0x10, 0xfb, + 0xa9, 0x01, 0x8d, 0x07, 0xdc, 0xa9, 0x19, 0x8d, + 0x0f, 0xdc, 0x20, 0x97, 0xee, 0xad, 0x0d, 0xdc, + 0xad, 0x0d, 0xdc, 0x29, 0x02, 0xd0, 0x07, 0x20, + 0xa9, 0xee, 0x30, 0xf4, 0x10, 0x18, 0xa5, 0xa5, + 0xf0, 0x05, 0xa9, 0x02, 0x4c, 0xb2, 0xed, 0x20, + 0xa0, 0xee, 0x20, 0x85, 0xee, 0xa9, 0x40, 0x20, + 0x1c, 0xfe, 0xe6, 0xa5, 0xd0, 0xca, 0xa9, 0x08, + 0x85, 0xa5, 0xad, 0x00, 0xdd, 0xcd, 0x00, 0xdd, + 0xd0, 0xf8, 0x0a, 0x10, 0xf5, 0x66, 0xa4, 0xad, + 0x00, 0xdd, 0xcd, 0x00, 0xdd, 0xd0, 0xf8, 0x0a, + 0x30, 0xf5, 0xc6, 0xa5, 0xd0, 0xe4, 0x20, 0xa0, + 0xee, 0x24, 0x90, 0x50, 0x03, 0x20, 0x06, 0xee, + 0xa5, 0xa4, 0x58, 0x18, 0x60, 0xad, 0x00, 0xdd, + 0x29, 0xef, 0x8d, 0x00, 0xdd, 0x60, 0xad, 0x00, + 0xdd, 0x09, 0x10, 0x8d, 0x00, 0xdd, 0x60, 0xad, + 0x00, 0xdd, 0x29, 0xdf, 0x8d, 0x00, 0xdd, 0x60, + 0xad, 0x00, 0xdd, 0x09, 0x20, 0x8d, 0x00, 0xdd, + 0x60, 0xad, 0x00, 0xdd, 0xcd, 0x00, 0xdd, 0xd0, + 0xf8, 0x0a, 0x60, 0x8a, 0xa2, 0xb8, 0xca, 0xd0, + 0xfd, 0xaa, 0x60, 0xa5, 0xb4, 0xf0, 0x47, 0x30, + 0x3f, 0x46, 0xb6, 0xa2, 0x00, 0x90, 0x01, 0xca, + 0x8a, 0x45, 0xbd, 0x85, 0xbd, 0xc6, 0xb4, 0xf0, + 0x06, 0x8a, 0x29, 0x04, 0x85, 0xb5, 0x60, 0xa9, + 0x20, 0x2c, 0x94, 0x02, 0xf0, 0x14, 0x30, 0x1c, + 0x70, 0x14, 0xa5, 0xbd, 0xd0, 0x01, 0xca, 0xc6, + 0xb4, 0xad, 0x93, 0x02, 0x10, 0xe3, 0xc6, 0xb4, + 0xd0, 0xdf, 0xe6, 0xb4, 0xd0, 0xf0, 0xa5, 0xbd, + 0xf0, 0xed, 0xd0, 0xea, 0x70, 0xe9, 0x50, 0xe6, + 0xe6, 0xb4, 0xa2, 0xff, 0xd0, 0xcb, 0xad, 0x94, + 0x02, 0x4a, 0x90, 0x07, 0x2c, 0x01, 0xdd, 0x10, + 0x1d, 0x50, 0x1e, 0xa9, 0x00, 0x85, 0xbd, 0x85, + 0xb5, 0xae, 0x98, 0x02, 0x86, 0xb4, 0xac, 0x9d, + 0x02, 0xcc, 0x9e, 0x02, 0xf0, 0x13, 0xb1, 0xf9, + 0x85, 0xb6, 0xee, 0x9d, 0x02, 0x60, 0xa9, 0x40, + 0x2c, 0xa9, 0x10, 0x0d, 0x97, 0x02, 0x8d, 0x97, + 0x02, 0xa9, 0x01, 0x8d, 0x0d, 0xdd, 0x4d, 0xa1, + 0x02, 0x09, 0x80, 0x8d, 0xa1, 0x02, 0x8d, 0x0d, + 0xdd, 0x60, 0xa2, 0x09, 0xa9, 0x20, 0x2c, 0x93, + 0x02, 0xf0, 0x01, 0xca, 0x50, 0x02, 0xca, 0xca, + 0x60, 0xa6, 0xa9, 0xd0, 0x33, 0xc6, 0xa8, 0xf0, + 0x36, 0x30, 0x0d, 0xa5, 0xa7, 0x45, 0xab, 0x85, + 0xab, 0x46, 0xa7, 0x66, 0xaa, 0x60, 0xc6, 0xa8, + 0xa5, 0xa7, 0xf0, 0x67, 0xad, 0x93, 0x02, 0x0a, + 0xa9, 0x01, 0x65, 0xa8, 0xd0, 0xef, 0xa9, 0x90, + 0x8d, 0x0d, 0xdd, 0x0d, 0xa1, 0x02, 0x8d, 0xa1, + 0x02, 0x85, 0xa9, 0xa9, 0x02, 0x4c, 0x3b, 0xef, + 0xa5, 0xa7, 0xd0, 0xea, 0x4c, 0xd3, 0xe4, 0xac, + 0x9b, 0x02, 0xc8, 0xcc, 0x9c, 0x02, 0xf0, 0x2a, + 0x8c, 0x9b, 0x02, 0x88, 0xa5, 0xaa, 0xae, 0x98, + 0x02, 0xe0, 0x09, 0xf0, 0x04, 0x4a, 0xe8, 0xd0, + 0xf8, 0x91, 0xf7, 0xa9, 0x20, 0x2c, 0x94, 0x02, + 0xf0, 0xb4, 0x30, 0xb1, 0xa5, 0xa7, 0x45, 0xab, + 0xf0, 0x03, 0x70, 0xa9, 0x2c, 0x50, 0xa6, 0xa9, + 0x01, 0x2c, 0xa9, 0x04, 0x2c, 0xa9, 0x80, 0x2c, + 0xa9, 0x02, 0x0d, 0x97, 0x02, 0x8d, 0x97, 0x02, + 0x4c, 0x7e, 0xef, 0xa5, 0xaa, 0xd0, 0xf1, 0xf0, + 0xec, 0x85, 0x9a, 0xad, 0x94, 0x02, 0x4a, 0x90, + 0x29, 0xa9, 0x02, 0x2c, 0x01, 0xdd, 0x10, 0x1d, + 0xd0, 0x20, 0xad, 0xa1, 0x02, 0x29, 0x02, 0xd0, + 0xf9, 0x2c, 0x01, 0xdd, 0x70, 0xfb, 0xad, 0x01, + 0xdd, 0x09, 0x02, 0x8d, 0x01, 0xdd, 0x2c, 0x01, + 0xdd, 0x70, 0x07, 0x30, 0xf9, 0xa9, 0x40, 0x8d, + 0x97, 0x02, 0x18, 0x60, 0x20, 0x28, 0xf0, 0xac, + 0x9e, 0x02, 0xc8, 0xcc, 0x9d, 0x02, 0xf0, 0xf4, + 0x8c, 0x9e, 0x02, 0x88, 0xa5, 0x9e, 0x91, 0xf9, + 0xad, 0xa1, 0x02, 0x4a, 0xb0, 0x1e, 0xa9, 0x10, + 0x8d, 0x0e, 0xdd, 0xad, 0x99, 0x02, 0x8d, 0x04, + 0xdd, 0xad, 0x9a, 0x02, 0x8d, 0x05, 0xdd, 0xa9, + 0x81, 0x20, 0x3b, 0xef, 0x20, 0x06, 0xef, 0xa9, + 0x11, 0x8d, 0x0e, 0xdd, 0x60, 0x85, 0x99, 0xad, + 0x94, 0x02, 0x4a, 0x90, 0x28, 0x29, 0x08, 0xf0, + 0x24, 0xa9, 0x02, 0x2c, 0x01, 0xdd, 0x10, 0xad, + 0xf0, 0x22, 0xad, 0xa1, 0x02, 0x4a, 0xb0, 0xfa, + 0xad, 0x01, 0xdd, 0x29, 0xfd, 0x8d, 0x01, 0xdd, + 0xad, 0x01, 0xdd, 0x29, 0x04, 0xf0, 0xf9, 0xa9, + 0x90, 0x18, 0x4c, 0x3b, 0xef, 0xad, 0xa1, 0x02, + 0x29, 0x12, 0xf0, 0xf3, 0x18, 0x60, 0xad, 0x97, + 0x02, 0xac, 0x9c, 0x02, 0xcc, 0x9b, 0x02, 0xf0, + 0x0b, 0x29, 0xf7, 0x8d, 0x97, 0x02, 0xb1, 0xf7, + 0xee, 0x9c, 0x02, 0x60, 0x09, 0x08, 0x8d, 0x97, + 0x02, 0xa9, 0x00, 0x60, 0x48, 0xad, 0xa1, 0x02, + 0xf0, 0x11, 0xad, 0xa1, 0x02, 0x29, 0x03, 0xd0, + 0xf9, 0xa9, 0x10, 0x8d, 0x0d, 0xdd, 0xa9, 0x00, + 0x8d, 0xa1, 0x02, 0x68, 0x60, 0x0d, 0x49, 0x2f, + 0x4f, 0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x20, + 0xa3, 0x0d, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, + 0x49, 0x4e, 0x47, 0xa0, 0x46, 0x4f, 0x52, 0xa0, + 0x0d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x50, + 0x4c, 0x41, 0x59, 0x20, 0x4f, 0x4e, 0x20, 0x54, + 0x41, 0x50, 0xc5, 0x50, 0x52, 0x45, 0x53, 0x53, + 0x20, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x20, + 0x26, 0x20, 0x50, 0x4c, 0x41, 0x59, 0x20, 0x4f, + 0x4e, 0x20, 0x54, 0x41, 0x50, 0xc5, 0x0d, 0x4c, + 0x4f, 0x41, 0x44, 0x49, 0x4e, 0xc7, 0x0d, 0x53, + 0x41, 0x56, 0x49, 0x4e, 0x47, 0xa0, 0x0d, 0x56, + 0x45, 0x52, 0x49, 0x46, 0x59, 0x49, 0x4e, 0xc7, + 0x0d, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0xa0, 0x0d, + 0x4f, 0x4b, 0x8d, 0x24, 0x9d, 0x10, 0x0d, 0xb9, + 0xbd, 0xf0, 0x08, 0x29, 0x7f, 0x20, 0xd2, 0xff, + 0xc8, 0x28, 0x10, 0xf3, 0x18, 0x60, 0xa5, 0x99, + 0xd0, 0x08, 0xa5, 0xc6, 0xf0, 0x0f, 0x78, 0x4c, + 0xb4, 0xe5, 0xc9, 0x02, 0xd0, 0x18, 0x84, 0x97, + 0x20, 0x86, 0xf0, 0xa4, 0x97, 0x18, 0x60, 0xa5, + 0x99, 0xd0, 0x0b, 0xa5, 0xd3, 0x85, 0xca, 0xa5, + 0xd6, 0x85, 0xc9, 0x4c, 0x32, 0xe6, 0xc9, 0x03, + 0xd0, 0x09, 0x85, 0xd0, 0xa5, 0xd5, 0x85, 0xc8, + 0x4c, 0x32, 0xe6, 0xb0, 0x38, 0xc9, 0x02, 0xf0, + 0x3f, 0x86, 0x97, 0x20, 0x99, 0xf1, 0xb0, 0x16, + 0x48, 0x20, 0x99, 0xf1, 0xb0, 0x0d, 0xd0, 0x05, + 0xa9, 0x40, 0x20, 0x1c, 0xfe, 0xc6, 0xa6, 0xa6, + 0x97, 0x68, 0x60, 0xaa, 0x68, 0x8a, 0xa6, 0x97, + 0x60, 0x20, 0x0d, 0xf8, 0xd0, 0x0b, 0x20, 0x41, + 0xf8, 0xb0, 0x11, 0xa9, 0x00, 0x85, 0xa6, 0xf0, + 0xf0, 0xb1, 0xb2, 0x18, 0x60, 0xa5, 0x90, 0xf0, + 0x04, 0xa9, 0x0d, 0x18, 0x60, 0x4c, 0x13, 0xee, + 0x20, 0x4e, 0xf1, 0xb0, 0xf7, 0xc9, 0x00, 0xd0, + 0xf2, 0xad, 0x97, 0x02, 0x29, 0x60, 0xd0, 0xe9, + 0xf0, 0xee, 0x48, 0xa5, 0x9a, 0xc9, 0x03, 0xd0, + 0x04, 0x68, 0x4c, 0x16, 0xe7, 0x90, 0x04, 0x68, + 0x4c, 0xdd, 0xed, 0x4a, 0x68, 0x85, 0x9e, 0x8a, + 0x48, 0x98, 0x48, 0x90, 0x23, 0x20, 0x0d, 0xf8, + 0xd0, 0x0e, 0x20, 0x64, 0xf8, 0xb0, 0x0e, 0xa9, + 0x02, 0xa0, 0x00, 0x91, 0xb2, 0xc8, 0x84, 0xa6, + 0xa5, 0x9e, 0x91, 0xb2, 0x18, 0x68, 0xa8, 0x68, + 0xaa, 0xa5, 0x9e, 0x90, 0x02, 0xa9, 0x00, 0x60, + 0x20, 0x17, 0xf0, 0x4c, 0xfc, 0xf1, 0x20, 0x0f, + 0xf3, 0xf0, 0x03, 0x4c, 0x01, 0xf7, 0x20, 0x1f, + 0xf3, 0xa5, 0xba, 0xf0, 0x16, 0xc9, 0x03, 0xf0, + 0x12, 0xb0, 0x14, 0xc9, 0x02, 0xd0, 0x03, 0x4c, + 0x4d, 0xf0, 0xa6, 0xb9, 0xe0, 0x60, 0xf0, 0x03, + 0x4c, 0x0a, 0xf7, 0x85, 0x99, 0x18, 0x60, 0xaa, + 0x20, 0x09, 0xed, 0xa5, 0xb9, 0x10, 0x06, 0x20, + 0xcc, 0xed, 0x4c, 0x48, 0xf2, 0x20, 0xc7, 0xed, + 0x8a, 0x24, 0x90, 0x10, 0xe6, 0x4c, 0x07, 0xf7, + 0x20, 0x0f, 0xf3, 0xf0, 0x03, 0x4c, 0x01, 0xf7, + 0x20, 0x1f, 0xf3, 0xa5, 0xba, 0xd0, 0x03, 0x4c, + 0x0d, 0xf7, 0xc9, 0x03, 0xf0, 0x0f, 0xb0, 0x11, + 0xc9, 0x02, 0xd0, 0x03, 0x4c, 0xe1, 0xef, 0xa6, + 0xb9, 0xe0, 0x60, 0xf0, 0xea, 0x85, 0x9a, 0x18, + 0x60, 0xaa, 0x20, 0x0c, 0xed, 0xa5, 0xb9, 0x10, + 0x05, 0x20, 0xbe, 0xed, 0xd0, 0x03, 0x20, 0xb9, + 0xed, 0x8a, 0x24, 0x90, 0x10, 0xe7, 0x4c, 0x07, + 0xf7, 0x20, 0x14, 0xf3, 0xf0, 0x02, 0x18, 0x60, + 0x20, 0x1f, 0xf3, 0x8a, 0x48, 0xa5, 0xba, 0xf0, + 0x50, 0xc9, 0x03, 0xf0, 0x4c, 0xb0, 0x47, 0xc9, + 0x02, 0xd0, 0x1d, 0x68, 0x20, 0xf2, 0xf2, 0x20, + 0x83, 0xf4, 0x20, 0x27, 0xfe, 0xa5, 0xf8, 0xf0, + 0x01, 0xc8, 0xa5, 0xfa, 0xf0, 0x01, 0xc8, 0xa9, + 0x00, 0x85, 0xf8, 0x85, 0xfa, 0x4c, 0x7d, 0xf4, + 0xa5, 0xb9, 0x29, 0x0f, 0xf0, 0x23, 0x20, 0xd0, + 0xf7, 0xa9, 0x00, 0x38, 0x20, 0xdd, 0xf1, 0x20, + 0x64, 0xf8, 0x90, 0x04, 0x68, 0xa9, 0x00, 0x60, + 0xa5, 0xb9, 0xc9, 0x62, 0xd0, 0x0b, 0xa9, 0x05, + 0x20, 0x6a, 0xf7, 0x4c, 0xf1, 0xf2, 0x20, 0x42, + 0xf6, 0x68, 0xaa, 0xc6, 0x98, 0xe4, 0x98, 0xf0, + 0x14, 0xa4, 0x98, 0xb9, 0x59, 0x02, 0x9d, 0x59, + 0x02, 0xb9, 0x63, 0x02, 0x9d, 0x63, 0x02, 0xb9, + 0x6d, 0x02, 0x9d, 0x6d, 0x02, 0x18, 0x60, 0xa9, + 0x00, 0x85, 0x90, 0x8a, 0xa6, 0x98, 0xca, 0x30, + 0x15, 0xdd, 0x59, 0x02, 0xd0, 0xf8, 0x60, 0xbd, + 0x59, 0x02, 0x85, 0xb8, 0xbd, 0x63, 0x02, 0x85, + 0xba, 0xbd, 0x6d, 0x02, 0x85, 0xb9, 0x60, 0xa9, + 0x00, 0x85, 0x98, 0xa2, 0x03, 0xe4, 0x9a, 0xb0, + 0x03, 0x20, 0xfe, 0xed, 0xe4, 0x99, 0xb0, 0x03, + 0x20, 0xef, 0xed, 0x86, 0x9a, 0xa9, 0x00, 0x85, + 0x99, 0x60, 0xa6, 0xb8, 0xd0, 0x03, 0x4c, 0x0a, + 0xf7, 0x20, 0x0f, 0xf3, 0xd0, 0x03, 0x4c, 0xfe, + 0xf6, 0xa6, 0x98, 0xe0, 0x0a, 0x90, 0x03, 0x4c, + 0xfb, 0xf6, 0xe6, 0x98, 0xa5, 0xb8, 0x9d, 0x59, + 0x02, 0xa5, 0xb9, 0x09, 0x60, 0x85, 0xb9, 0x9d, + 0x6d, 0x02, 0xa5, 0xba, 0x9d, 0x63, 0x02, 0xf0, + 0x5a, 0xc9, 0x03, 0xf0, 0x56, 0x90, 0x05, 0x20, + 0xd5, 0xf3, 0x90, 0x4f, 0xc9, 0x02, 0xd0, 0x03, + 0x4c, 0x09, 0xf4, 0x20, 0xd0, 0xf7, 0xb0, 0x03, + 0x4c, 0x13, 0xf7, 0xa5, 0xb9, 0x29, 0x0f, 0xd0, + 0x1f, 0x20, 0x17, 0xf8, 0xb0, 0x36, 0x20, 0xaf, + 0xf5, 0xa5, 0xb7, 0xf0, 0x0a, 0x20, 0xea, 0xf7, + 0x90, 0x18, 0xf0, 0x28, 0x4c, 0x04, 0xf7, 0x20, + 0x2c, 0xf7, 0xf0, 0x20, 0x90, 0x0c, 0xb0, 0xf4, + 0x20, 0x38, 0xf8, 0xb0, 0x17, 0xa9, 0x04, 0x20, + 0x6a, 0xf7, 0xa9, 0xbf, 0xa4, 0xb9, 0xc0, 0x60, + 0xf0, 0x07, 0xa0, 0x00, 0xa9, 0x02, 0x91, 0xb2, + 0x98, 0x85, 0xa6, 0x18, 0x60, 0xa5, 0xb9, 0x30, + 0xfa, 0xa4, 0xb7, 0xf0, 0xf6, 0xa9, 0x00, 0x85, + 0x90, 0xa5, 0xba, 0x20, 0x0c, 0xed, 0xa5, 0xb9, + 0x09, 0xf0, 0x20, 0xb9, 0xed, 0xa5, 0x90, 0x10, + 0x05, 0x68, 0x68, 0x4c, 0x07, 0xf7, 0xa5, 0xb7, + 0xf0, 0x0c, 0xa0, 0x00, 0xb1, 0xbb, 0x20, 0xdd, + 0xed, 0xc8, 0xc4, 0xb7, 0xd0, 0xf6, 0x4c, 0x54, + 0xf6, 0x20, 0x83, 0xf4, 0x8c, 0x97, 0x02, 0xc4, + 0xb7, 0xf0, 0x0a, 0xb1, 0xbb, 0x99, 0x93, 0x02, + 0xc8, 0xc0, 0x04, 0xd0, 0xf2, 0x20, 0x4a, 0xef, + 0x8e, 0x98, 0x02, 0xad, 0x93, 0x02, 0x29, 0x0f, + 0xf0, 0x1c, 0x0a, 0xaa, 0xad, 0xa6, 0x02, 0xd0, + 0x09, 0xbc, 0xc1, 0xfe, 0xbd, 0xc0, 0xfe, 0x4c, + 0x40, 0xf4, 0xbc, 0xeb, 0xe4, 0xbd, 0xea, 0xe4, + 0x8c, 0x96, 0x02, 0x8d, 0x95, 0x02, 0xad, 0x95, + 0x02, 0x0a, 0x20, 0x2e, 0xff, 0xad, 0x94, 0x02, + 0x4a, 0x90, 0x09, 0xad, 0x01, 0xdd, 0x0a, 0xb0, + 0x03, 0x20, 0x0d, 0xf0, 0xad, 0x9b, 0x02, 0x8d, + 0x9c, 0x02, 0xad, 0x9e, 0x02, 0x8d, 0x9d, 0x02, + 0x20, 0x27, 0xfe, 0xa5, 0xf8, 0xd0, 0x05, 0x88, + 0x84, 0xf8, 0x86, 0xf7, 0xa5, 0xfa, 0xd0, 0x05, + 0x88, 0x84, 0xfa, 0x86, 0xf9, 0x38, 0xa9, 0xf0, + 0x4c, 0x2d, 0xfe, 0xa9, 0x7f, 0x8d, 0x0d, 0xdd, + 0xa9, 0x06, 0x8d, 0x03, 0xdd, 0x8d, 0x01, 0xdd, + 0xa9, 0x04, 0x0d, 0x00, 0xdd, 0x8d, 0x00, 0xdd, + 0xa0, 0x00, 0x8c, 0xa1, 0x02, 0x60, 0x86, 0xc3, + 0x84, 0xc4, 0x6c, 0x30, 0x03, 0x85, 0x93, 0xa9, + 0x00, 0x85, 0x90, 0xa5, 0xba, 0xd0, 0x03, 0x4c, + 0x13, 0xf7, 0xc9, 0x03, 0xf0, 0xf9, 0x90, 0x7b, + 0xa4, 0xb7, 0xd0, 0x03, 0x4c, 0x10, 0xf7, 0xa6, + 0xb9, 0x20, 0xaf, 0xf5, 0xa9, 0x60, 0x85, 0xb9, + 0x20, 0xd5, 0xf3, 0xa5, 0xba, 0x20, 0x09, 0xed, + 0xa5, 0xb9, 0x20, 0xc7, 0xed, 0x20, 0x13, 0xee, + 0x85, 0xae, 0xa5, 0x90, 0x4a, 0x4a, 0xb0, 0x50, + 0x20, 0x13, 0xee, 0x85, 0xaf, 0x8a, 0xd0, 0x08, + 0xa5, 0xc3, 0x85, 0xae, 0xa5, 0xc4, 0x85, 0xaf, + 0x20, 0xd2, 0xf5, 0xa9, 0xfd, 0x25, 0x90, 0x85, + 0x90, 0x20, 0xe1, 0xff, 0xd0, 0x03, 0x4c, 0x33, + 0xf6, 0x20, 0x13, 0xee, 0xaa, 0xa5, 0x90, 0x4a, + 0x4a, 0xb0, 0xe8, 0x8a, 0xa4, 0x93, 0xf0, 0x0c, + 0xa0, 0x00, 0xd1, 0xae, 0xf0, 0x08, 0xa9, 0x10, + 0x20, 0x1c, 0xfe, 0x2c, 0x91, 0xae, 0xe6, 0xae, + 0xd0, 0x02, 0xe6, 0xaf, 0x24, 0x90, 0x50, 0xcb, + 0x20, 0xef, 0xed, 0x20, 0x42, 0xf6, 0x90, 0x79, + 0x4c, 0x04, 0xf7, 0x4a, 0xb0, 0x03, 0x4c, 0x13, + 0xf7, 0x20, 0xd0, 0xf7, 0xb0, 0x03, 0x4c, 0x13, + 0xf7, 0x20, 0x17, 0xf8, 0xb0, 0x68, 0x20, 0xaf, + 0xf5, 0xa5, 0xb7, 0xf0, 0x09, 0x20, 0xea, 0xf7, + 0x90, 0x0b, 0xf0, 0x5a, 0xb0, 0xda, 0x20, 0x2c, + 0xf7, 0xf0, 0x53, 0xb0, 0xd3, 0xa5, 0x90, 0x29, + 0x10, 0x38, 0xd0, 0x4a, 0xe0, 0x01, 0xf0, 0x11, + 0xe0, 0x03, 0xd0, 0xdd, 0xa0, 0x01, 0xb1, 0xb2, + 0x85, 0xc3, 0xc8, 0xb1, 0xb2, 0x85, 0xc4, 0xb0, + 0x04, 0xa5, 0xb9, 0xd0, 0xef, 0xa0, 0x03, 0xb1, + 0xb2, 0xa0, 0x01, 0xf1, 0xb2, 0xaa, 0xa0, 0x04, + 0xb1, 0xb2, 0xa0, 0x02, 0xf1, 0xb2, 0xa8, 0x18, + 0x8a, 0x65, 0xc3, 0x85, 0xae, 0x98, 0x65, 0xc4, + 0x85, 0xaf, 0xa5, 0xc3, 0x85, 0xc1, 0xa5, 0xc4, + 0x85, 0xc2, 0x20, 0xd2, 0xf5, 0x20, 0x4a, 0xf8, + 0x24, 0x18, 0xa6, 0xae, 0xa4, 0xaf, 0x60, 0xa5, + 0x9d, 0x10, 0x1e, 0xa0, 0x0c, 0x20, 0x2f, 0xf1, + 0xa5, 0xb7, 0xf0, 0x15, 0xa0, 0x17, 0x20, 0x2f, + 0xf1, 0xa4, 0xb7, 0xf0, 0x0c, 0xa0, 0x00, 0xb1, + 0xbb, 0x20, 0xd2, 0xff, 0xc8, 0xc4, 0xb7, 0xd0, + 0xf6, 0x60, 0xa0, 0x49, 0xa5, 0x93, 0xf0, 0x02, + 0xa0, 0x59, 0x4c, 0x2b, 0xf1, 0x86, 0xae, 0x84, + 0xaf, 0xaa, 0xb5, 0x00, 0x85, 0xc1, 0xb5, 0x01, + 0x85, 0xc2, 0x6c, 0x32, 0x03, 0xa5, 0xba, 0xd0, + 0x03, 0x4c, 0x13, 0xf7, 0xc9, 0x03, 0xf0, 0xf9, + 0x90, 0x5f, 0xa9, 0x61, 0x85, 0xb9, 0xa4, 0xb7, + 0xd0, 0x03, 0x4c, 0x10, 0xf7, 0x20, 0xd5, 0xf3, + 0x20, 0x8f, 0xf6, 0xa5, 0xba, 0x20, 0x0c, 0xed, + 0xa5, 0xb9, 0x20, 0xb9, 0xed, 0xa0, 0x00, 0x20, + 0x8e, 0xfb, 0xa5, 0xac, 0x20, 0xdd, 0xed, 0xa5, + 0xad, 0x20, 0xdd, 0xed, 0x20, 0xd1, 0xfc, 0xb0, + 0x16, 0xb1, 0xac, 0x20, 0xdd, 0xed, 0x20, 0xe1, + 0xff, 0xd0, 0x07, 0x20, 0x42, 0xf6, 0xa9, 0x00, + 0x38, 0x60, 0x20, 0xdb, 0xfc, 0xd0, 0xe5, 0x20, + 0xfe, 0xed, 0x24, 0xb9, 0x30, 0x11, 0xa5, 0xba, + 0x20, 0x0c, 0xed, 0xa5, 0xb9, 0x29, 0xef, 0x09, + 0xe0, 0x20, 0xb9, 0xed, 0x20, 0xfe, 0xed, 0x18, + 0x60, 0x4a, 0xb0, 0x03, 0x4c, 0x13, 0xf7, 0x20, + 0xd0, 0xf7, 0x90, 0x8d, 0x20, 0x38, 0xf8, 0xb0, + 0x25, 0x20, 0x8f, 0xf6, 0xa2, 0x03, 0xa5, 0xb9, + 0x29, 0x01, 0xd0, 0x02, 0xa2, 0x01, 0x8a, 0x20, + 0x6a, 0xf7, 0xb0, 0x12, 0x20, 0x67, 0xf8, 0xb0, + 0x0d, 0xa5, 0xb9, 0x29, 0x02, 0xf0, 0x06, 0xa9, + 0x05, 0x20, 0x6a, 0xf7, 0x24, 0x18, 0x60, 0xa5, + 0x9d, 0x10, 0xfb, 0xa0, 0x51, 0x20, 0x2f, 0xf1, + 0x4c, 0xc1, 0xf5, 0xa2, 0x00, 0xe6, 0xa2, 0xd0, + 0x06, 0xe6, 0xa1, 0xd0, 0x02, 0xe6, 0xa0, 0x38, + 0xa5, 0xa2, 0xe9, 0x01, 0xa5, 0xa1, 0xe9, 0x1a, + 0xa5, 0xa0, 0xe9, 0x4f, 0x90, 0x06, 0x86, 0xa0, + 0x86, 0xa1, 0x86, 0xa2, 0xad, 0x01, 0xdc, 0xcd, + 0x01, 0xdc, 0xd0, 0xf8, 0xaa, 0x30, 0x13, 0xa2, + 0xbd, 0x8e, 0x00, 0xdc, 0xae, 0x01, 0xdc, 0xec, + 0x01, 0xdc, 0xd0, 0xf8, 0x8d, 0x00, 0xdc, 0xe8, + 0xd0, 0x02, 0x85, 0x91, 0x60, 0x78, 0xa5, 0xa2, + 0xa6, 0xa1, 0xa4, 0xa0, 0x78, 0x85, 0xa2, 0x86, + 0xa1, 0x84, 0xa0, 0x58, 0x60, 0xa5, 0x91, 0xc9, + 0x7f, 0xd0, 0x07, 0x08, 0x20, 0xcc, 0xff, 0x85, + 0xc6, 0x28, 0x60, 0xa9, 0x01, 0x2c, 0xa9, 0x02, + 0x2c, 0xa9, 0x03, 0x2c, 0xa9, 0x04, 0x2c, 0xa9, + 0x05, 0x2c, 0xa9, 0x06, 0x2c, 0xa9, 0x07, 0x2c, + 0xa9, 0x08, 0x2c, 0xa9, 0x09, 0x48, 0x20, 0xcc, + 0xff, 0xa0, 0x00, 0x24, 0x9d, 0x50, 0x0a, 0x20, + 0x2f, 0xf1, 0x68, 0x48, 0x09, 0x30, 0x20, 0xd2, + 0xff, 0x68, 0x38, 0x60, 0xa5, 0x93, 0x48, 0x20, + 0x41, 0xf8, 0x68, 0x85, 0x93, 0xb0, 0x32, 0xa0, + 0x00, 0xb1, 0xb2, 0xc9, 0x05, 0xf0, 0x2a, 0xc9, + 0x01, 0xf0, 0x08, 0xc9, 0x03, 0xf0, 0x04, 0xc9, + 0x04, 0xd0, 0xe1, 0xaa, 0x24, 0x9d, 0x10, 0x17, + 0xa0, 0x63, 0x20, 0x2f, 0xf1, 0xa0, 0x05, 0xb1, + 0xb2, 0x20, 0xd2, 0xff, 0xc8, 0xc0, 0x15, 0xd0, + 0xf6, 0xa5, 0xa1, 0x20, 0xe0, 0xe4, 0xea, 0x18, + 0x88, 0x60, 0x85, 0x9e, 0x20, 0xd0, 0xf7, 0x90, + 0x5e, 0xa5, 0xc2, 0x48, 0xa5, 0xc1, 0x48, 0xa5, + 0xaf, 0x48, 0xa5, 0xae, 0x48, 0xa0, 0xbf, 0xa9, + 0x20, 0x91, 0xb2, 0x88, 0xd0, 0xfb, 0xa5, 0x9e, + 0x91, 0xb2, 0xc8, 0xa5, 0xc1, 0x91, 0xb2, 0xc8, + 0xa5, 0xc2, 0x91, 0xb2, 0xc8, 0xa5, 0xae, 0x91, + 0xb2, 0xc8, 0xa5, 0xaf, 0x91, 0xb2, 0xc8, 0x84, + 0x9f, 0xa0, 0x00, 0x84, 0x9e, 0xa4, 0x9e, 0xc4, + 0xb7, 0xf0, 0x0c, 0xb1, 0xbb, 0xa4, 0x9f, 0x91, + 0xb2, 0xe6, 0x9e, 0xe6, 0x9f, 0xd0, 0xee, 0x20, + 0xd7, 0xf7, 0xa9, 0x69, 0x85, 0xab, 0x20, 0x6b, + 0xf8, 0xa8, 0x68, 0x85, 0xae, 0x68, 0x85, 0xaf, + 0x68, 0x85, 0xc1, 0x68, 0x85, 0xc2, 0x98, 0x60, + 0xa6, 0xb2, 0xa4, 0xb3, 0xc0, 0x02, 0x60, 0x20, + 0xd0, 0xf7, 0x8a, 0x85, 0xc1, 0x18, 0x69, 0xc0, + 0x85, 0xae, 0x98, 0x85, 0xc2, 0x69, 0x00, 0x85, + 0xaf, 0x60, 0x20, 0x2c, 0xf7, 0xb0, 0x1d, 0xa0, + 0x05, 0x84, 0x9f, 0xa0, 0x00, 0x84, 0x9e, 0xc4, + 0xb7, 0xf0, 0x10, 0xb1, 0xbb, 0xa4, 0x9f, 0xd1, + 0xb2, 0xd0, 0xe7, 0xe6, 0x9e, 0xe6, 0x9f, 0xa4, + 0x9e, 0xd0, 0xec, 0x18, 0x60, 0x20, 0xd0, 0xf7, + 0xe6, 0xa6, 0xa4, 0xa6, 0xc0, 0xc0, 0x60, 0x20, + 0x2e, 0xf8, 0xf0, 0x1a, 0xa0, 0x1b, 0x20, 0x2f, + 0xf1, 0x20, 0xd0, 0xf8, 0x20, 0x2e, 0xf8, 0xd0, + 0xf8, 0xa0, 0x6a, 0x4c, 0x2f, 0xf1, 0xa9, 0x10, + 0x24, 0x01, 0xd0, 0x02, 0x24, 0x01, 0x18, 0x60, + 0x20, 0x2e, 0xf8, 0xf0, 0xf9, 0xa0, 0x2e, 0xd0, + 0xdd, 0xa9, 0x00, 0x85, 0x90, 0x85, 0x93, 0x20, + 0xd7, 0xf7, 0x20, 0x17, 0xf8, 0xb0, 0x1f, 0x78, + 0xa9, 0x00, 0x85, 0xaa, 0x85, 0xb4, 0x85, 0xb0, + 0x85, 0x9e, 0x85, 0x9f, 0x85, 0x9c, 0xa9, 0x90, + 0xa2, 0x0e, 0xd0, 0x11, 0x20, 0xd7, 0xf7, 0xa9, + 0x14, 0x85, 0xab, 0x20, 0x38, 0xf8, 0xb0, 0x6c, + 0x78, 0xa9, 0x82, 0xa2, 0x08, 0xa0, 0x7f, 0x8c, + 0x0d, 0xdc, 0x8d, 0x0d, 0xdc, 0xad, 0x0e, 0xdc, + 0x09, 0x19, 0x8d, 0x0f, 0xdc, 0x29, 0x91, 0x8d, + 0xa2, 0x02, 0x20, 0xa4, 0xf0, 0xad, 0x11, 0xd0, + 0x29, 0xef, 0x8d, 0x11, 0xd0, 0xad, 0x14, 0x03, + 0x8d, 0x9f, 0x02, 0xad, 0x15, 0x03, 0x8d, 0xa0, + 0x02, 0x20, 0xbd, 0xfc, 0xa9, 0x02, 0x85, 0xbe, + 0x20, 0x97, 0xfb, 0xa5, 0x01, 0x29, 0x1f, 0x85, + 0x01, 0x85, 0xc0, 0xa2, 0xff, 0xa0, 0xff, 0x88, + 0xd0, 0xfd, 0xca, 0xd0, 0xf8, 0x58, 0xad, 0xa0, + 0x02, 0xcd, 0x15, 0x03, 0x18, 0xf0, 0x15, 0x20, + 0xd0, 0xf8, 0x20, 0xbc, 0xf6, 0x4c, 0xbe, 0xf8, + 0x20, 0xe1, 0xff, 0x18, 0xd0, 0x0b, 0x20, 0x93, + 0xfc, 0x38, 0x68, 0x68, 0xa9, 0x00, 0x8d, 0xa0, + 0x02, 0x60, 0x86, 0xb1, 0xa5, 0xb0, 0x0a, 0x0a, + 0x18, 0x65, 0xb0, 0x18, 0x65, 0xb1, 0x85, 0xb1, + 0xa9, 0x00, 0x24, 0xb0, 0x30, 0x01, 0x2a, 0x06, + 0xb1, 0x2a, 0x06, 0xb1, 0x2a, 0xaa, 0xad, 0x06, + 0xdc, 0xc9, 0x16, 0x90, 0xf9, 0x65, 0xb1, 0x8d, + 0x04, 0xdc, 0x8a, 0x6d, 0x07, 0xdc, 0x8d, 0x05, + 0xdc, 0xad, 0xa2, 0x02, 0x8d, 0x0e, 0xdc, 0x8d, + 0xa4, 0x02, 0xad, 0x0d, 0xdc, 0x29, 0x10, 0xf0, + 0x09, 0xa9, 0xf9, 0x48, 0xa9, 0x2a, 0x48, 0x4c, + 0x43, 0xff, 0x58, 0x60, 0xae, 0x07, 0xdc, 0xa0, + 0xff, 0x98, 0xed, 0x06, 0xdc, 0xec, 0x07, 0xdc, + 0xd0, 0xf2, 0x86, 0xb1, 0xaa, 0x8c, 0x06, 0xdc, + 0x8c, 0x07, 0xdc, 0xa9, 0x19, 0x8d, 0x0f, 0xdc, + 0xad, 0x0d, 0xdc, 0x8d, 0xa3, 0x02, 0x98, 0xe5, + 0xb1, 0x86, 0xb1, 0x4a, 0x66, 0xb1, 0x4a, 0x66, + 0xb1, 0xa5, 0xb0, 0x18, 0x69, 0x3c, 0xc5, 0xb1, + 0xb0, 0x4a, 0xa6, 0x9c, 0xf0, 0x03, 0x4c, 0x60, + 0xfa, 0xa6, 0xa3, 0x30, 0x1b, 0xa2, 0x00, 0x69, + 0x30, 0x65, 0xb0, 0xc5, 0xb1, 0xb0, 0x1c, 0xe8, + 0x69, 0x26, 0x65, 0xb0, 0xc5, 0xb1, 0xb0, 0x17, + 0x69, 0x2c, 0x65, 0xb0, 0xc5, 0xb1, 0x90, 0x03, + 0x4c, 0x10, 0xfa, 0xa5, 0xb4, 0xf0, 0x1d, 0x85, + 0xa8, 0xd0, 0x19, 0xe6, 0xa9, 0xb0, 0x02, 0xc6, + 0xa9, 0x38, 0xe9, 0x13, 0xe5, 0xb1, 0x65, 0x92, + 0x85, 0x92, 0xa5, 0xa4, 0x49, 0x01, 0x85, 0xa4, + 0xf0, 0x2b, 0x86, 0xd7, 0xa5, 0xb4, 0xf0, 0x22, + 0xad, 0xa3, 0x02, 0x29, 0x01, 0xd0, 0x05, 0xad, + 0xa4, 0x02, 0xd0, 0x16, 0xa9, 0x00, 0x85, 0xa4, + 0x8d, 0xa4, 0x02, 0xa5, 0xa3, 0x10, 0x30, 0x30, + 0xbf, 0xa2, 0xa6, 0x20, 0xe2, 0xf8, 0xa5, 0x9b, + 0xd0, 0xb9, 0x4c, 0xbc, 0xfe, 0xa5, 0x92, 0xf0, + 0x07, 0x30, 0x03, 0xc6, 0xb0, 0x2c, 0xe6, 0xb0, + 0xa9, 0x00, 0x85, 0x92, 0xe4, 0xd7, 0xd0, 0x0f, + 0x8a, 0xd0, 0xa0, 0xa5, 0xa9, 0x30, 0xbd, 0xc9, + 0x10, 0x90, 0xb9, 0x85, 0x96, 0xb0, 0xb5, 0x8a, + 0x45, 0x9b, 0x85, 0x9b, 0xa5, 0xb4, 0xf0, 0xd2, + 0xc6, 0xa3, 0x30, 0xc5, 0x46, 0xd7, 0x66, 0xbf, + 0xa2, 0xda, 0x20, 0xe2, 0xf8, 0x4c, 0xbc, 0xfe, + 0xa5, 0x96, 0xf0, 0x04, 0xa5, 0xb4, 0xf0, 0x07, + 0xa5, 0xa3, 0x30, 0x03, 0x4c, 0x97, 0xf9, 0x46, + 0xb1, 0xa9, 0x93, 0x38, 0xe5, 0xb1, 0x65, 0xb0, + 0x0a, 0xaa, 0x20, 0xe2, 0xf8, 0xe6, 0x9c, 0xa5, + 0xb4, 0xd0, 0x11, 0xa5, 0x96, 0xf0, 0x26, 0x85, + 0xa8, 0xa9, 0x00, 0x85, 0x96, 0xa9, 0x81, 0x8d, + 0x0d, 0xdc, 0x85, 0xb4, 0xa5, 0x96, 0x85, 0xb5, + 0xf0, 0x09, 0xa9, 0x00, 0x85, 0xb4, 0xa9, 0x01, + 0x8d, 0x0d, 0xdc, 0xa5, 0xbf, 0x85, 0xbd, 0xa5, + 0xa8, 0x05, 0xa9, 0x85, 0xb6, 0x4c, 0xbc, 0xfe, + 0x20, 0x97, 0xfb, 0x85, 0x9c, 0xa2, 0xda, 0x20, + 0xe2, 0xf8, 0xa5, 0xbe, 0xf0, 0x02, 0x85, 0xa7, + 0xa9, 0x0f, 0x24, 0xaa, 0x10, 0x17, 0xa5, 0xb5, + 0xd0, 0x0c, 0xa6, 0xbe, 0xca, 0xd0, 0x0b, 0xa9, + 0x08, 0x20, 0x1c, 0xfe, 0xd0, 0x04, 0xa9, 0x00, + 0x85, 0xaa, 0x4c, 0xbc, 0xfe, 0x70, 0x31, 0xd0, + 0x18, 0xa5, 0xb5, 0xd0, 0xf5, 0xa5, 0xb6, 0xd0, + 0xf1, 0xa5, 0xa7, 0x4a, 0xa5, 0xbd, 0x30, 0x03, + 0x90, 0x18, 0x18, 0xb0, 0x15, 0x29, 0x0f, 0x85, + 0xaa, 0xc6, 0xaa, 0xd0, 0xdd, 0xa9, 0x40, 0x85, + 0xaa, 0x20, 0x8e, 0xfb, 0xa9, 0x00, 0x85, 0xab, + 0xf0, 0xd0, 0xa9, 0x80, 0x85, 0xaa, 0xd0, 0xca, + 0xa5, 0xb5, 0xf0, 0x0a, 0xa9, 0x04, 0x20, 0x1c, + 0xfe, 0xa9, 0x00, 0x4c, 0x4a, 0xfb, 0x20, 0xd1, + 0xfc, 0x90, 0x03, 0x4c, 0x48, 0xfb, 0xa6, 0xa7, + 0xca, 0xf0, 0x2d, 0xa5, 0x93, 0xf0, 0x0c, 0xa0, + 0x00, 0xa5, 0xbd, 0xd1, 0xac, 0xf0, 0x04, 0xa9, + 0x01, 0x85, 0xb6, 0xa5, 0xb6, 0xf0, 0x4b, 0xa2, + 0x3d, 0xe4, 0x9e, 0x90, 0x3e, 0xa6, 0x9e, 0xa5, + 0xad, 0x9d, 0x01, 0x01, 0xa5, 0xac, 0x9d, 0x00, + 0x01, 0xe8, 0xe8, 0x86, 0x9e, 0x4c, 0x3a, 0xfb, + 0xa6, 0x9f, 0xe4, 0x9e, 0xf0, 0x35, 0xa5, 0xac, + 0xdd, 0x00, 0x01, 0xd0, 0x2e, 0xa5, 0xad, 0xdd, + 0x01, 0x01, 0xd0, 0x27, 0xe6, 0x9f, 0xe6, 0x9f, + 0xa5, 0x93, 0xf0, 0x0b, 0xa5, 0xbd, 0xa0, 0x00, + 0xd1, 0xac, 0xf0, 0x17, 0xc8, 0x84, 0xb6, 0xa5, + 0xb6, 0xf0, 0x07, 0xa9, 0x10, 0x20, 0x1c, 0xfe, + 0xd0, 0x09, 0xa5, 0x93, 0xd0, 0x05, 0xa8, 0xa5, + 0xbd, 0x91, 0xac, 0x20, 0xdb, 0xfc, 0xd0, 0x43, + 0xa9, 0x80, 0x85, 0xaa, 0x78, 0xa2, 0x01, 0x8e, + 0x0d, 0xdc, 0xae, 0x0d, 0xdc, 0xa6, 0xbe, 0xca, + 0x30, 0x02, 0x86, 0xbe, 0xc6, 0xa7, 0xf0, 0x08, + 0xa5, 0x9e, 0xd0, 0x27, 0x85, 0xbe, 0xf0, 0x23, + 0x20, 0x93, 0xfc, 0x20, 0x8e, 0xfb, 0xa0, 0x00, + 0x84, 0xab, 0xb1, 0xac, 0x45, 0xab, 0x85, 0xab, + 0x20, 0xdb, 0xfc, 0x20, 0xd1, 0xfc, 0x90, 0xf2, + 0xa5, 0xab, 0x45, 0xbd, 0xf0, 0x05, 0xa9, 0x20, + 0x20, 0x1c, 0xfe, 0x4c, 0xbc, 0xfe, 0xa5, 0xc2, + 0x85, 0xad, 0xa5, 0xc1, 0x85, 0xac, 0x60, 0xa9, + 0x08, 0x85, 0xa3, 0xa9, 0x00, 0x85, 0xa4, 0x85, + 0xa8, 0x85, 0x9b, 0x85, 0xa9, 0x60, 0xa5, 0xbd, + 0x4a, 0xa9, 0x60, 0x90, 0x02, 0xa9, 0xb0, 0xa2, + 0x00, 0x8d, 0x06, 0xdc, 0x8e, 0x07, 0xdc, 0xad, + 0x0d, 0xdc, 0xa9, 0x19, 0x8d, 0x0f, 0xdc, 0xa5, + 0x01, 0x49, 0x08, 0x85, 0x01, 0x29, 0x08, 0x60, + 0x38, 0x66, 0xb6, 0x30, 0x3c, 0xa5, 0xa8, 0xd0, + 0x12, 0xa9, 0x10, 0xa2, 0x01, 0x20, 0xb1, 0xfb, + 0xd0, 0x2f, 0xe6, 0xa8, 0xa5, 0xb6, 0x10, 0x29, + 0x4c, 0x57, 0xfc, 0xa5, 0xa9, 0xd0, 0x09, 0x20, + 0xad, 0xfb, 0xd0, 0x1d, 0xe6, 0xa9, 0xd0, 0x19, + 0x20, 0xa6, 0xfb, 0xd0, 0x14, 0xa5, 0xa4, 0x49, + 0x01, 0x85, 0xa4, 0xf0, 0x0f, 0xa5, 0xbd, 0x49, + 0x01, 0x85, 0xbd, 0x29, 0x01, 0x45, 0x9b, 0x85, + 0x9b, 0x4c, 0xbc, 0xfe, 0x46, 0xbd, 0xc6, 0xa3, + 0xa5, 0xa3, 0xf0, 0x3a, 0x10, 0xf3, 0x20, 0x97, + 0xfb, 0x58, 0xa5, 0xa5, 0xf0, 0x12, 0xa2, 0x00, + 0x86, 0xd7, 0xc6, 0xa5, 0xa6, 0xbe, 0xe0, 0x02, + 0xd0, 0x02, 0x09, 0x80, 0x85, 0xbd, 0xd0, 0xd9, + 0x20, 0xd1, 0xfc, 0x90, 0x0a, 0xd0, 0x91, 0xe6, + 0xad, 0xa5, 0xd7, 0x85, 0xbd, 0xb0, 0xca, 0xa0, + 0x00, 0xb1, 0xac, 0x85, 0xbd, 0x45, 0xd7, 0x85, + 0xd7, 0x20, 0xdb, 0xfc, 0xd0, 0xbb, 0xa5, 0x9b, + 0x49, 0x01, 0x85, 0xbd, 0x4c, 0xbc, 0xfe, 0xc6, + 0xbe, 0xd0, 0x03, 0x20, 0xca, 0xfc, 0xa9, 0x50, + 0x85, 0xa7, 0xa2, 0x08, 0x78, 0x20, 0xbd, 0xfc, + 0xd0, 0xea, 0xa9, 0x78, 0x20, 0xaf, 0xfb, 0xd0, + 0xe3, 0xc6, 0xa7, 0xd0, 0xdf, 0x20, 0x97, 0xfb, + 0xc6, 0xab, 0x10, 0xd8, 0xa2, 0x0a, 0x20, 0xbd, + 0xfc, 0x58, 0xe6, 0xab, 0xa5, 0xbe, 0xf0, 0x30, + 0x20, 0x8e, 0xfb, 0xa2, 0x09, 0x86, 0xa5, 0x86, + 0xb6, 0xd0, 0x83, 0x08, 0x78, 0xad, 0x11, 0xd0, + 0x09, 0x10, 0x8d, 0x11, 0xd0, 0x20, 0xca, 0xfc, + 0xa9, 0x7f, 0x8d, 0x0d, 0xdc, 0x20, 0xdd, 0xfd, + 0xad, 0xa0, 0x02, 0xf0, 0x09, 0x8d, 0x15, 0x03, + 0xad, 0x9f, 0x02, 0x8d, 0x14, 0x03, 0x28, 0x60, + 0x20, 0x93, 0xfc, 0xf0, 0x97, 0xbd, 0x93, 0xfd, + 0x8d, 0x14, 0x03, 0xbd, 0x94, 0xfd, 0x8d, 0x15, + 0x03, 0x60, 0xa5, 0x01, 0x09, 0x20, 0x85, 0x01, + 0x60, 0x38, 0xa5, 0xac, 0xe5, 0xae, 0xa5, 0xad, + 0xe5, 0xaf, 0x60, 0xe6, 0xac, 0xd0, 0x02, 0xe6, + 0xad, 0x60, 0xa2, 0xff, 0x78, 0x9a, 0xd8, 0x20, + 0x02, 0xfd, 0xd0, 0x03, 0x6c, 0x00, 0x80, 0x8e, + 0x16, 0xd0, 0x20, 0xa3, 0xfd, 0x20, 0x50, 0xfd, + 0x20, 0x15, 0xfd, 0x20, 0x5b, 0xff, 0x58, 0x6c, + 0x00, 0xa0, 0xa2, 0x05, 0xbd, 0x0f, 0xfd, 0xdd, + 0x03, 0x80, 0xd0, 0x03, 0xca, 0xd0, 0xf5, 0x60, + 0xc3, 0xc2, 0xcd, 0x38, 0x30, 0xa2, 0x30, 0xa0, + 0xfd, 0x18, 0x86, 0xc3, 0x84, 0xc4, 0xa0, 0x1f, + 0xb9, 0x14, 0x03, 0xb0, 0x02, 0xb1, 0xc3, 0x91, + 0xc3, 0x99, 0x14, 0x03, 0x88, 0x10, 0xf1, 0x60, + 0x31, 0xea, 0x66, 0xfe, 0x47, 0xfe, 0x4a, 0xf3, + 0x91, 0xf2, 0x0e, 0xf2, 0x50, 0xf2, 0x33, 0xf3, + 0x57, 0xf1, 0xca, 0xf1, 0xed, 0xf6, 0x3e, 0xf1, + 0x2f, 0xf3, 0x66, 0xfe, 0xa5, 0xf4, 0xed, 0xf5, + 0xa9, 0x00, 0xa8, 0x99, 0x02, 0x00, 0x99, 0x00, + 0x02, 0x99, 0x00, 0x03, 0xc8, 0xd0, 0xf4, 0xa2, + 0x3c, 0xa0, 0x03, 0x86, 0xb2, 0x84, 0xb3, 0xa8, + 0xa9, 0x03, 0x85, 0xc2, 0xe6, 0xc2, 0xb1, 0xc1, + 0xaa, 0xa9, 0x55, 0x91, 0xc1, 0xd1, 0xc1, 0xd0, + 0x0f, 0x2a, 0x91, 0xc1, 0xd1, 0xc1, 0xd0, 0x08, + 0x8a, 0x91, 0xc1, 0xc8, 0xd0, 0xe8, 0xf0, 0xe4, + 0x98, 0xaa, 0xa4, 0xc2, 0x18, 0x20, 0x2d, 0xfe, + 0xa9, 0x08, 0x8d, 0x82, 0x02, 0xa9, 0x04, 0x8d, + 0x88, 0x02, 0x60, 0x6a, 0xfc, 0xcd, 0xfb, 0x31, + 0xea, 0x2c, 0xf9, 0xa9, 0x7f, 0x8d, 0x0d, 0xdc, + 0x8d, 0x0d, 0xdd, 0x8d, 0x00, 0xdc, 0xa9, 0x08, + 0x8d, 0x0e, 0xdc, 0x8d, 0x0e, 0xdd, 0x8d, 0x0f, + 0xdc, 0x8d, 0x0f, 0xdd, 0xa2, 0x00, 0x8e, 0x03, + 0xdc, 0x8e, 0x03, 0xdd, 0x8e, 0x18, 0xd4, 0xca, + 0x8e, 0x02, 0xdc, 0xa9, 0x07, 0x8d, 0x00, 0xdd, + 0xa9, 0x3f, 0x8d, 0x02, 0xdd, 0xa9, 0xe7, 0x85, + 0x01, 0xa9, 0x2f, 0x85, 0x00, 0xad, 0xa6, 0x02, + 0xf0, 0x0a, 0xa9, 0x25, 0x8d, 0x04, 0xdc, 0xa9, + 0x40, 0x4c, 0xf3, 0xfd, 0xa9, 0x95, 0x8d, 0x04, + 0xdc, 0xa9, 0x42, 0x8d, 0x05, 0xdc, 0x4c, 0x6e, + 0xff, 0x85, 0xb7, 0x86, 0xbb, 0x84, 0xbc, 0x60, + 0x85, 0xb8, 0x86, 0xba, 0x84, 0xb9, 0x60, 0xa5, + 0xba, 0xc9, 0x02, 0xd0, 0x0d, 0xad, 0x97, 0x02, + 0x48, 0xa9, 0x00, 0x8d, 0x97, 0x02, 0x68, 0x60, + 0x85, 0x9d, 0xa5, 0x90, 0x05, 0x90, 0x85, 0x90, + 0x60, 0x8d, 0x85, 0x02, 0x60, 0x90, 0x06, 0xae, + 0x83, 0x02, 0xac, 0x84, 0x02, 0x8e, 0x83, 0x02, + 0x8c, 0x84, 0x02, 0x60, 0x90, 0x06, 0xae, 0x81, + 0x02, 0xac, 0x82, 0x02, 0x8e, 0x81, 0x02, 0x8c, + 0x82, 0x02, 0x60, 0x78, 0x6c, 0x18, 0x03, 0x48, + 0x8a, 0x48, 0x98, 0x48, 0xa9, 0x7f, 0x8d, 0x0d, + 0xdd, 0xac, 0x0d, 0xdd, 0x30, 0x1c, 0x20, 0x02, + 0xfd, 0xd0, 0x03, 0x6c, 0x02, 0x80, 0x20, 0xbc, + 0xf6, 0x20, 0xe1, 0xff, 0xd0, 0x0c, 0x20, 0x15, + 0xfd, 0x20, 0xa3, 0xfd, 0x20, 0x18, 0xe5, 0x6c, + 0x02, 0xa0, 0x98, 0x2d, 0xa1, 0x02, 0xaa, 0x29, + 0x01, 0xf0, 0x28, 0xad, 0x00, 0xdd, 0x29, 0xfb, + 0x05, 0xb5, 0x8d, 0x00, 0xdd, 0xad, 0xa1, 0x02, + 0x8d, 0x0d, 0xdd, 0x8a, 0x29, 0x12, 0xf0, 0x0d, + 0x29, 0x02, 0xf0, 0x06, 0x20, 0xd6, 0xfe, 0x4c, + 0x9d, 0xfe, 0x20, 0x07, 0xff, 0x20, 0xbb, 0xee, + 0x4c, 0xb6, 0xfe, 0x8a, 0x29, 0x02, 0xf0, 0x06, + 0x20, 0xd6, 0xfe, 0x4c, 0xb6, 0xfe, 0x8a, 0x29, + 0x10, 0xf0, 0x03, 0x20, 0x07, 0xff, 0xad, 0xa1, + 0x02, 0x8d, 0x0d, 0xdd, 0x68, 0xa8, 0x68, 0xaa, + 0x68, 0x40, 0xc1, 0x27, 0x3e, 0x1a, 0xc5, 0x11, + 0x74, 0x0e, 0xed, 0x0c, 0x45, 0x06, 0xf0, 0x02, + 0x46, 0x01, 0xb8, 0x00, 0x71, 0x00, 0xad, 0x01, + 0xdd, 0x29, 0x01, 0x85, 0xa7, 0xad, 0x06, 0xdd, + 0xe9, 0x1c, 0x6d, 0x99, 0x02, 0x8d, 0x06, 0xdd, + 0xad, 0x07, 0xdd, 0x6d, 0x9a, 0x02, 0x8d, 0x07, + 0xdd, 0xa9, 0x11, 0x8d, 0x0f, 0xdd, 0xad, 0xa1, + 0x02, 0x8d, 0x0d, 0xdd, 0xa9, 0xff, 0x8d, 0x06, + 0xdd, 0x8d, 0x07, 0xdd, 0x4c, 0x59, 0xef, 0xad, + 0x95, 0x02, 0x8d, 0x06, 0xdd, 0xad, 0x96, 0x02, + 0x8d, 0x07, 0xdd, 0xa9, 0x11, 0x8d, 0x0f, 0xdd, + 0xa9, 0x12, 0x4d, 0xa1, 0x02, 0x8d, 0xa1, 0x02, + 0xa9, 0xff, 0x8d, 0x06, 0xdd, 0x8d, 0x07, 0xdd, + 0xae, 0x98, 0x02, 0x86, 0xa8, 0x60, 0xaa, 0xad, + 0x96, 0x02, 0x2a, 0xa8, 0x8a, 0x69, 0xc8, 0x8d, + 0x99, 0x02, 0x98, 0x69, 0x00, 0x8d, 0x9a, 0x02, + 0x60, 0xea, 0xea, 0x08, 0x68, 0x29, 0xef, 0x48, + 0x48, 0x8a, 0x48, 0x98, 0x48, 0xba, 0xbd, 0x04, + 0x01, 0x29, 0x10, 0xf0, 0x03, 0x6c, 0x16, 0x03, + 0x6c, 0x14, 0x03, 0x20, 0x18, 0xe5, 0xad, 0x12, + 0xd0, 0xd0, 0xfb, 0xad, 0x19, 0xd0, 0x29, 0x01, + 0x8d, 0xa6, 0x02, 0x4c, 0xdd, 0xfd, 0xa9, 0x81, + 0x8d, 0x0d, 0xdc, 0xad, 0x0e, 0xdc, 0x29, 0x80, + 0x09, 0x11, 0x8d, 0x0e, 0xdc, 0x4c, 0x8e, 0xee, + 0x03, 0x4c, 0x5b, 0xff, 0x4c, 0xa3, 0xfd, 0x4c, + 0x50, 0xfd, 0x4c, 0x15, 0xfd, 0x4c, 0x1a, 0xfd, + 0x4c, 0x18, 0xfe, 0x4c, 0xb9, 0xed, 0x4c, 0xc7, + 0xed, 0x4c, 0x25, 0xfe, 0x4c, 0x34, 0xfe, 0x4c, + 0x87, 0xea, 0x4c, 0x21, 0xfe, 0x4c, 0x13, 0xee, + 0x4c, 0xdd, 0xed, 0x4c, 0xef, 0xed, 0x4c, 0xfe, + 0xed, 0x4c, 0x0c, 0xed, 0x4c, 0x09, 0xed, 0x4c, + 0x07, 0xfe, 0x4c, 0x00, 0xfe, 0x4c, 0xf9, 0xfd, + 0x6c, 0x1a, 0x03, 0x6c, 0x1c, 0x03, 0x6c, 0x1e, + 0x03, 0x6c, 0x20, 0x03, 0x6c, 0x22, 0x03, 0x6c, + 0x24, 0x03, 0x6c, 0x26, 0x03, 0x4c, 0x9e, 0xf4, + 0x4c, 0xdd, 0xf5, 0x4c, 0xe4, 0xf6, 0x4c, 0xdd, + 0xf6, 0x6c, 0x28, 0x03, 0x6c, 0x2a, 0x03, 0x6c, + 0x2c, 0x03, 0x4c, 0x9b, 0xf6, 0x4c, 0x05, 0xe5, + 0x4c, 0x0a, 0xe5, 0x4c, 0x00, 0xe5, 0x52, 0x52, + 0x42, 0x59, 0x43, 0xfe, 0xe2, 0xfc, 0x48, 0xff, diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mixer.cpp b/plugins/sid/sidplay-libs/libsidplay/src/mixer.cpp new file mode 100644 index 00000000..c7703dc1 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mixer.cpp @@ -0,0 +1,180 @@ +/*************************************************************************** + mixer.cpp - Sids Mixer Routines + ------------------- + begin : Sun Jul 9 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mixer.cpp,v $ + * Revision 1.10 2002/01/29 21:50:33 s_a_white + * Auto switching to a better emulation mode. m_tuneInfo reloaded after a + * config. Initial code added to support more than two sids. + * + * Revision 1.9 2001/12/13 08:28:08 s_a_white + * Added namespace support to fix problems with xsidplay. + * + * Revision 1.8 2001/11/16 19:25:33 s_a_white + * Removed m_context as where getting mixed with parent class. + * + * Revision 1.7 2001/10/02 18:29:32 s_a_white + * Corrected fixed point maths overflow caused by fastforwarding. + * + * Revision 1.6 2001/09/17 19:02:38 s_a_white + * Now uses fixed point maths for sample output and rtc. + * + * Revision 1.5 2001/07/25 17:02:37 s_a_white + * Support for new configuration interface. + * + * Revision 1.4 2001/07/14 12:47:39 s_a_white + * Mixer routines simplified. Added new and more efficient method of + * determining when an output samples is required. + * + * Revision 1.3 2001/03/01 23:46:37 s_a_white + * Support for sample mode to be selected at runtime. + * + * Revision 1.2 2000/12/12 22:50:15 s_a_white + * Bug Fix #122033. + * + ***************************************************************************/ + +#include "player.h" +#include "sidendian.h" + +const int_least32_t VOLUME_MAX = 255; + +SIDPLAY2_NAMESPACE_START + +void Player::mixerReset (void) +{ // Fixed point 16.16 + m_sampleClock = m_samplePeriod & 0x0FFFF; + // Schedule next sample event + (context ()).schedule (&mixerEvent, + m_samplePeriod >> 24); +} + +void Player::mixer (void) +{ // Fixed point 16.16 + event_clock_t cycles; + char *buf = m_sampleBuffer + m_sampleIndex; + m_sampleClock += m_samplePeriod; + cycles = m_sampleClock >> 16; + m_sampleClock &= 0x0FFFF; + m_sampleIndex += (this->*output) (buf); + + // Schedule next sample event + (context ()).schedule (&mixerEvent, cycles); + + // Filled buffer + if (m_sampleIndex >= m_sampleCount) + m_running = false; +} + + +//------------------------------------------------------------------------- +// Generic sound output generation routines +//------------------------------------------------------------------------- +inline +int_least32_t Player::monoOutGenericLeftIn (uint_least8_t bits) +{ + return sid[0]->output (bits) * m_leftVolume / VOLUME_MAX; +} + +inline +int_least32_t Player::monoOutGenericStereoIn (uint_least8_t bits) +{ + // Convert to mono + return ((sid[0]->output (bits) * m_leftVolume) + + (sid[1]->output (bits) * m_rightVolume)) / (VOLUME_MAX * 2); +} + +inline +int_least32_t Player::monoOutGenericRightIn (uint_least8_t bits) +{ + return sid[1]->output (bits) * m_rightVolume / VOLUME_MAX; +} + + +//------------------------------------------------------------------------- +// 8 bit sound output generation routines +//------------------------------------------------------------------------- +uint_least32_t Player::monoOut8MonoIn (char *buffer) +{ + *buffer = (char) monoOutGenericLeftIn (8) ^ '\x80'; + return sizeof (char); +} + +uint_least32_t Player::monoOut8StereoIn (char *buffer) +{ + *buffer = (char) monoOutGenericStereoIn (8) ^ '\x80'; + return sizeof (char); +} + +uint_least32_t Player::monoOut8StereoRIn (char *buffer) +{ + *buffer = (char) monoOutGenericRightIn (8) ^ '\x80'; + return sizeof (char); +} + +uint_least32_t Player::stereoOut8MonoIn (char *buffer) +{ + char sample = (char) monoOutGenericLeftIn (8) ^ '\x80'; + buffer[0] = sample; + buffer[1] = sample; + return (2 * sizeof (char)); +} + +uint_least32_t Player::stereoOut8StereoIn (char *buffer) +{ + buffer[0] = (char) monoOutGenericLeftIn (8) ^ '\x80'; + buffer[1] = (char) monoOutGenericRightIn (8) ^ '\x80'; + return (2 * sizeof (char)); +} + +//------------------------------------------------------------------------- +// 16 bit sound output generation routines +//------------------------------------------------------------------------- +uint_least32_t Player::monoOut16MonoIn (char *buffer) +{ + endian_16 (buffer, (uint_least16_t) monoOutGenericLeftIn (16)); + return sizeof (uint_least16_t); +} + +uint_least32_t Player::monoOut16StereoIn (char *buffer) +{ + endian_16 (buffer, (uint_least16_t) monoOutGenericStereoIn (16)); + return sizeof (uint_least16_t); +} + +uint_least32_t Player::monoOut16StereoRIn (char *buffer) +{ + endian_16 (buffer, (uint_least16_t) monoOutGenericRightIn (16)); + return sizeof (uint_least16_t); +} + +uint_least32_t Player::stereoOut16MonoIn (char *buffer) +{ + uint_least16_t sample = (uint_least16_t) monoOutGenericLeftIn (16); + endian_16 (buffer, sample); + endian_16 (buffer + sizeof(uint_least16_t), sample); + return (2 * sizeof (uint_least16_t)); +} + +uint_least32_t Player::stereoOut16StereoIn (char *buffer) +{ + endian_16 (buffer, (uint_least16_t) monoOutGenericLeftIn (16)); + endian_16 (buffer + sizeof(uint_least16_t), + (uint_least16_t) monoOutGenericRightIn (16)); + return (2 * sizeof (uint_least16_t)); +} + +SIDPLAY2_NAMESPACE_STOP diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am new file mode 100644 index 00000000..27acc569 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am @@ -0,0 +1,9 @@ + +EXTRA_DIST = cycle_based + +noinst_LTLIBRARIES = libmos6510.la + +libmos6510_la_SOURCES = mos6510.cpp mos6510.h conf6510.h opcodes.h + +# Remove bad default includes +DEFAULT_INCLUDES= diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in new file mode 100644 index 00000000..9af93a74 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in @@ -0,0 +1,426 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +EXTRA_DIST = cycle_based + +noinst_LTLIBRARIES = libmos6510.la + +libmos6510_la_SOURCES = mos6510.cpp mos6510.h conf6510.h opcodes.h + +# Remove bad default includes +DEFAULT_INCLUDES = +subdir = src/mos6510 +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libmos6510_la_LDFLAGS = +libmos6510_la_LIBADD = +am_libmos6510_la_OBJECTS = mos6510.lo +libmos6510_la_OBJECTS = $(am_libmos6510_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/mos6510.Plo +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libmos6510_la_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libmos6510_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/mos6510/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libmos6510.la: $(libmos6510_la_OBJECTS) $(libmos6510_la_DEPENDENCIES) + $(CXXLINK) $(libmos6510_la_LDFLAGS) $(libmos6510_la_OBJECTS) $(libmos6510_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mos6510.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 $(LTLIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +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: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man 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 uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h new file mode 100644 index 00000000..6a1ea0bd --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h @@ -0,0 +1,45 @@ +/*************************************************************************** + config.h - description + ------------------- + begin : Thu May 11 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: conf6510.h,v $ + * Revision 1.3 2001/03/19 23:41:51 s_a_white + * Better support for global debug. + * + * Revision 1.2 2000/12/11 19:03:16 s_a_white + * AC99 Update. + * + ***************************************************************************/ + +#ifndef _conf6510_h_ +#define _conf6510_h_ + +#include "sidconfig.h" + +#define MOS6510_CYCLE_BASED +#define MOS6510_ACCURATE_CYCLES +#define MOS6510_SIDPLAY +//#define MOS6510_STATE_6510 +//#define MOS6510_DEBUG 1 + +// Support global debug option +#ifdef DEBUG +# ifndef MOS6510_DEBUG +# define MOS6510_DEBUG DEBUG +# endif +#endif + +#endif // _conf6510_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h new file mode 100644 index 00000000..9a046d2e --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h @@ -0,0 +1,311 @@ +/*************************************************************************** + mos6510c.h - Cycle Accurate 6510 Emulation + ------------------- + begin : Thu May 11 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mos6510c.h,v $ + * Revision 1.15 2002/11/28 20:35:06 s_a_white + * Reduced number of thrown exceptions when dma occurs. + * + * Revision 1.14 2002/11/25 20:10:55 s_a_white + * A bus access failure should stop the CPU dead like the cycle never started. + * This is currently simulated using throw (execption handling) for now. + * + * Revision 1.13 2002/11/21 19:52:48 s_a_white + * CPU upgraded to be like other components. Theres nolonger a clock call, + * instead events are registered to occur at a specific time. + * + * Revision 1.12 2002/11/19 22:57:33 s_a_white + * Initial support for external DMA to steal cycles away from the CPU. + * + * Revision 1.11 2002/11/01 17:35:27 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.10 2001/08/05 15:46:02 s_a_white + * No longer need to check on which cycle an instruction ends or when to print + * debug information. + * + * Revision 1.9 2001/07/14 16:48:03 s_a_white + * cycleCount and related must roject.Syn + * + * Revision 1.8 2001/07/14 13:15:30 s_a_white + * Accumulator is now unsigned, which improves code readability. Emulation + * tested with testsuite 2.15. Various instructions required modification. + * + * Revision 1.7 2001/03/28 21:17:34 s_a_white + * Added support for proper RMW instructions. + * + * Revision 1.6 2001/03/24 18:09:17 s_a_white + * On entry to interrupt routine the first instruction in the handler is now always + * executed before pending interrupts are re-checked. + * + * Revision 1.5 2001/03/19 23:48:21 s_a_white + * Interrupts made virtual to allow for redefintion for Sidplay1 compatible + * interrupts. + * + * Revision 1.4 2001/03/09 22:28:03 s_a_white + * Speed optimisation update. + * + * Revision 1.3 2001/02/13 21:03:33 s_a_white + * Changed inlines to non-inlines due to function bodies not being in header. + * + * Revision 1.2 2000/12/11 19:04:32 s_a_white + * AC99 Update. + * + ***************************************************************************/ + +#ifndef _mos6510c_h_ +#define _mos6510c_h_ + +#include "sidtypes.h" +#include "sidendian.h" + + +class MOS6510: public C64Environment, public Event +{ +private: + // External signals + bool aec; /* Address Controller, blocks all */ + bool rdy; /* Bus Access, blocks reads */ + bool m_blocked; + +protected: + bool dodump; + EventContext &eventContext; + + // Declare processor operations + struct ProcessorOperations + { + void (MOS6510::**cycle)(void); + uint cycles; + uint_least8_t opcode; + }; + + void (MOS6510::*fetchCycle[1]) (void); + struct ProcessorOperations instrTable[0x100]; + struct ProcessorOperations interruptTable[3]; + struct ProcessorOperations *instrCurrent; + + uint_least16_t instrStartPC; + uint_least8_t instrOpcode; + void (MOS6510::**procCycle) (void); + int_least8_t lastAddrCycle; + int_least8_t cycleCount; + + // Pointers to the current instruction cycle + uint_least16_t Cycle_EffectiveAddress; + uint8_t Cycle_Data; + uint_least16_t Cycle_Pointer; + + uint8_t Register_Accumulator; + uint8_t Register_X; + uint8_t Register_Y; + uint_least32_t Register_ProgramCounter; + uint8_t Register_Status; + uint_least8_t Register_c_Flag; + uint_least8_t Register_n_Flag; + uint_least8_t Register_v_Flag; + uint_least8_t Register_z_Flag; + uint_least16_t Register_StackPointer; + uint_least16_t Instr_Operand; + + // Interrupts + struct + { + uint_least8_t pending; + uint_least8_t irqs; + event_clock_t nmiClock; + event_clock_t irqClock; + event_clock_t delay; + bool irqRequest; + bool irqLatch; + } interrupts; + + uint8_t Debug_Data; + uint_least16_t Debug_EffectiveAddress; + uint_least8_t Debug_Opcode; + uint_least16_t Debug_Operand; + uint_least16_t Debug_ProgramCounter; + +protected: + void clock (void); + void event (void); + void Initialise (void); + // Declare Interrupt Routines + inline void RSTRequest (void); + inline void RST1Request (void); + inline void NMIRequest (void); + inline void NMI1Request (void); + inline void IRQRequest (void); + inline void IRQ1Request (void); + inline void IRQ2Request (void); + bool interruptPending (void); + + // Declare Instruction Routines + virtual void FetchOpcode (void); + void NextInstr (void); + inline void FetchDataByte (void); + inline void FetchLowAddr (void); + inline void FetchLowAddrX (void); + inline void FetchLowAddrY (void); + inline void FetchHighAddr (void); + inline void FetchHighAddrX (void); + inline void FetchHighAddrX2 (void); + inline void FetchHighAddrY (void); + inline void FetchHighAddrY2 (void); + inline void FetchLowEffAddr (void); + inline void FetchHighEffAddr (void); + inline void FetchHighEffAddrY (void); + inline void FetchHighEffAddrY2 (void); + inline void FetchLowPointer (void); + inline void FetchLowPointerX (void); + inline void FetchHighPointer (void); + inline void FetchEffAddrDataByte (void); + inline void PutEffAddrDataByte (void); + inline void FetchPutEffAddrDataByte (void); + inline void PushLowPC (void); + inline void PushHighPC (void); + inline void PushSR (bool b_flag); + inline void PushSR (void); + inline void PopLowPC (void); + inline void PopHighPC (void); + inline void PopSR (void); + inline void WasteCycle (void); + inline void DebugCycle (void); + + // Delcare Instruction Operation Routines + inline void adc_instr (void); + inline void alr_instr (void); + inline void anc_instr (void); + inline void and_instr (void); + inline void ane_instr (void); + inline void arr_instr (void); + inline void asl_instr (void); + inline void asla_instr (void); + inline void aso_instr (void); + inline void axa_instr (void); + inline void axs_instr (void); + inline void bcc_instr (void); + inline void bcs_instr (void); + inline void beq_instr (void); + inline void bit_instr (void); + inline void bmi_instr (void); + inline void bne_instr (void); + inline void branch_instr (bool condition); + inline void bpl_instr (void); + inline void brk_instr (void); + inline void bvc_instr (void); + inline void bvs_instr (void); + inline void clc_instr (void); + inline void cld_instr (void); + inline void cli_instr (void); + inline void clv_instr (void); + inline void cmp_instr (void); + inline void cpx_instr (void); + inline void cpy_instr (void); + inline void dcm_instr (void); + inline void dec_instr (void); + inline void dex_instr (void); + inline void dey_instr (void); + inline void eor_instr (void); + inline void inc_instr (void); + inline void ins_instr (void); + inline void inx_instr (void); + inline void iny_instr (void); + inline void jmp_instr (void); + inline void jsr_instr (void); + inline void las_instr (void); + inline void lax_instr (void); + inline void lda_instr (void); + inline void ldx_instr (void); + inline void ldy_instr (void); + inline void lse_instr (void); + inline void lsr_instr (void); + inline void lsra_instr (void); + inline void oal_instr (void); + inline void ora_instr (void); + inline void pha_instr (void); + inline void pla_instr (void); + inline void rla_instr (void); + inline void rol_instr (void); + inline void rola_instr (void); + inline void ror_instr (void); + inline void rora_instr (void); + inline void rra_instr (void); + inline void rti_instr (void); + inline void rts_instr (void); + inline void sbx_instr (void); + inline void say_instr (void); + inline void sbc_instr (void); + inline void sec_instr (void); + inline void sed_instr (void); + inline void sei_instr (void); + inline void shs_instr (void); + inline void sta_instr (void); + inline void stx_instr (void); + inline void sty_instr (void); + inline void tas_instr (void); + inline void tax_instr (void); + inline void tay_instr (void); + inline void tsx_instr (void); + inline void txa_instr (void); + inline void txs_instr (void); + inline void tya_instr (void); + inline void xas_instr (void); + void illegal_instr (void); + + // Declare Arithmatic Operations + inline void Perform_ADC (void); + inline void Perform_SBC (void); + +public: + MOS6510 (EventContext *context); + virtual ~MOS6510 (); + virtual void reset (void); + virtual void credits (char *str); + virtual void DumpState (void); + void debug (bool enable) {dodump = enable;} + void aecSignal (bool state); + void rdySignal (bool state); + + // Non-standard functions + virtual void triggerRST (void); + virtual void triggerNMI (void); + virtual void triggerIRQ (void); + void clearIRQ (void); +}; + + +//-------------------------------------------------------------------------// +// Emulate One Complete Cycle // +inline void MOS6510::clock (void) +{ + int_least8_t i = cycleCount++; + try { + (this->*procCycle[i]) (); + } catch (int_least8_t delta) { + cycleCount += delta; + m_blocked = true; + eventContext.cancel (this); + } +} + +inline void MOS6510::event (void) +{ + eventContext.schedule (this, 1); + clock (); +} + +#endif // _mos6510c_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i new file mode 100644 index 00000000..78d57ba6 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i @@ -0,0 +1,2562 @@ +/*************************************************************************** + mos6510.i - Cycle Accurate 6510 emulation + ------------------- + begin : Thu May 11 06:22:40 BST 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mos6510c.i,v $ + * Revision 1.30 2002/12/16 08:42:58 s_a_white + * Fixed use of nothrow to be namespaced with std::. + * + * Revision 1.29 2002/11/28 20:35:06 s_a_white + * Reduced number of thrown exceptions when dma occurs. + * + * Revision 1.28 2002/11/25 20:10:55 s_a_white + * A bus access failure should stop the CPU dead like the cycle never started. + * This is currently simulated using throw (execption handling) for now. + * + * Revision 1.27 2002/11/21 19:52:48 s_a_white + * CPU upgraded to be like other components. Theres nolonger a clock call, + * instead events are registered to occur at a specific time. + * + * Revision 1.26 2002/11/19 22:57:33 s_a_white + * Initial support for external DMA to steal cycles away from the CPU. + * + * Revision 1.25 2002/11/01 19:22:36 s_a_white + * Removed debug printf. + * + * Revision 1.24 2002/11/01 17:35:27 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.23 2002/03/12 18:48:03 s_a_white + * Tidied illegal instruction debug print out. + * + * Revision 1.22 2001/12/11 19:24:15 s_a_white + * More GCC3 Fixes. + * + * Revision 1.21 2001/11/16 19:21:03 s_a_white + * Sign fixes. + * + * Revision 1.20 2001/10/28 21:31:26 s_a_white + * Removed kernel debuging code. + * + * Revision 1.19 2001/09/03 22:21:52 s_a_white + * When initialising the status register and therefore unmasking the irqs, + * check the irq line to see if any are pending. + * + * Revision 1.18 2001/08/10 20:05:50 s_a_white + * Fixed RMW instructions which broke due to the optimisation. + * + * Revision 1.17 2001/08/05 15:46:02 s_a_white + * No longer need to check on which cycle an instruction ends or when to print + * debug information. + * + * Revision 1.16 2001/07/14 13:15:30 s_a_white + * Accumulator is now unsigned, which improves code readability. Emulation + * tested with testsuite 2.15. Various instructions required modification. + * + * Revision 1.15 2001/04/20 22:23:11 s_a_white + * Handling of page boundary crossing now correct for branch instructions. + * + * Revision 1.14 2001/03/28 22:59:59 s_a_white + * Converted some bad envReadMemByte's to + * envReadMemDataByte + * + * Revision 1.13 2001/03/28 21:17:34 s_a_white + * Added support for proper RMW instructions. + * + * Revision 1.12 2001/03/24 18:09:17 s_a_white + * On entry to interrupt routine the first instruction in the handler is now always + * executed before pending interrupts are re-checked. + * + * Revision 1.11 2001/03/22 22:40:43 s_a_white + * Added new header for definition of nothrow. + * + * Revision 1.10 2001/03/21 22:27:18 s_a_white + * Change to IRQ error message. + * + * Revision 1.9 2001/03/19 23:46:35 s_a_white + * NMI no longer sets I flag. RTI and store instructions are no longer + * overlapped. + * + * Revision 1.8 2001/03/09 22:28:51 s_a_white + * Speed optimisation update and fix for interrupt flag in PushSR call. + * + * Revision 1.7 2001/02/22 08:28:57 s_a_white + * Interrupt masking fixed. + * + * Revision 1.6 2001/02/13 23:01:44 s_a_white + * envReadMemDataByte now used for some memory accesses. + * + * Revision 1.5 2000/12/24 00:45:38 s_a_white + * HAVE_EXCEPTIONS update + * + * Revision 1.4 2000/12/14 23:55:07 s_a_white + * PushSR optimisation and PopSR code cleanup. + * + ***************************************************************************/ +/* +const char _sidtune_CHRtab[256] = // CHR$ conversion table (0x01 = no output) +{ + 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x20,0x21, 0x1,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x24,0x5d,0x20,0x20, + // alternative: CHR$(92=0x5c) => ISO Latin-1(0xa3) + 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f, + 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c, + // 0x80-0xFF + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d, + 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23, + 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f, + 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c, + 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d, + 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23 +}; +*/ + +#include "config.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif + +// Microsoft Visual C++ Version Number to work around compiler bug +// Currently both Visual C++ Versions 5, 6 are broken. +#define _MSC_VER_BAD_NEW 1200 /* Defines VC6 and below */ +//char filetmp[0x100]; +//int filepos = 0; + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Status Register Routines // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Use macros to access flags. Allows compatiblity with other versions +// of this emulation +// Set N and Z flags according to byte +#define setFlagsNZ(x) (Register_z_Flag = (Register_n_Flag = (uint_least8_t) (x))) +#define setFlagN(x) (Register_n_Flag = (uint_least8_t) (x)) +#define setFlagV(x) (Register_v_Flag = (uint_least8_t) (x)) +#define setFlagD(x) (Register_Status = (Register_Status & ~(1 << SR_DECIMAL)) \ + | (((x) != 0) << SR_DECIMAL)) +#define setFlagI(x) (Register_Status = (Register_Status & ~(1 << SR_INTERRUPT)) \ + | (((x) != 0) << SR_INTERRUPT)) +#define setFlagZ(x) (Register_z_Flag = (uint_least8_t) (x)) +#define setFlagC(x) (Register_c_Flag = (uint_least8_t) (x)) + + +#define getFlagN() ((Register_n_Flag & (1 << SR_NEGATIVE)) != 0) +#define getFlagV() (Register_v_Flag != 0) +#define getFlagD() ((Register_Status & (1 << SR_DECIMAL)) != 0) +#define getFlagI() ((Register_Status & (1 << SR_INTERRUPT)) != 0) +#define getFlagZ() (Register_z_Flag == 0) +#define getFlagC() (Register_c_Flag != 0) + +#define stealCycle() \ + interrupts.delay++; \ + throw((int_least8_t) -1); + + +// Handle bus access signals +void MOS6510::aecSignal (bool state) +{ // If the cpu blocked waiting for the bus + // the schedule a retry. + aec = state; + if (state && m_blocked) + { + m_blocked = false; + eventContext.schedule (this, 1); + } +} + +void MOS6510::rdySignal (bool state) +{ // If the cpu blocked waiting for the bus + // the schedule a retry. + rdy = state; + if (state && m_blocked) + { + m_blocked = false; + eventContext.schedule (this, 1); + } +} + +// Push P on stack, decrement S +void MOS6510::PushSR (bool b_flag) +{ + if (aec) + { + uint_least16_t addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + /* Rev 1.04 - Corrected flag mask */ + Register_Status &= ((1 << SR_NOTUSED) | (1 << SR_INTERRUPT) | + (1 << SR_DECIMAL) | (1 << SR_BREAK)); + Register_Status |= (getFlagN () << SR_NEGATIVE); + Register_Status |= (getFlagV () << SR_OVERFLOW); + Register_Status |= (getFlagZ () << SR_ZERO); + Register_Status |= (getFlagC () << SR_CARRY); + envWriteMemByte (addr, Register_Status & ~((!b_flag) << SR_BREAK)); + Register_StackPointer--; + } + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::PushSR (void) +{ + PushSR (true); +} + +// increment S, Pop P off stack +void MOS6510::PopSR (void) +{ + if (rdy && aec) + { + bool newFlagI, oldFlagI; + oldFlagI = getFlagI (); + + // Get status register off stack + Register_StackPointer++; + { + uint_least16_t addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + Register_Status = envReadMemByte (addr); + } + Register_Status |= ((1 << SR_NOTUSED) | (1 << SR_BREAK)); + setFlagN (Register_Status); + setFlagV (Register_Status & (1 << SR_OVERFLOW)); + setFlagZ (!(Register_Status & (1 << SR_ZERO))); + setFlagC (Register_Status & (1 << SR_CARRY)); + + // I flag change is delayed by 1 instruction + newFlagI = getFlagI (); + interrupts.irqLatch = oldFlagI ^ newFlagI; + // Check to see if interrupts got re-enabled + if (!newFlagI && interrupts.irqs) + interrupts.irqRequest = true; + } + else + { // Address bus not ready + stealCycle(); + } +} + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Interrupt Routines // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +#define iIRQSMAX 3 +enum +{ + oNONE = -1, + oRST, + oNMI, + oIRQ +}; + +enum +{ + iNONE = 0, + iRST = 1 << oRST, + iNMI = 1 << oNMI, + iIRQ = 1 << oIRQ +}; + +void MOS6510::triggerRST (void) +{ + interrupts.pending |= iRST; +} + +void MOS6510::triggerNMI (void) +{ + interrupts.pending |= iNMI; + interrupts.nmiClock = eventContext.getTime (); +} + +// Level triggered interrupt +void MOS6510::triggerIRQ (void) +{ // IRQ Suppressed + if (!getFlagI ()) + interrupts.irqRequest = true; + if (!interrupts.irqs++) + interrupts.irqClock = eventContext.getTime (); + + if (interrupts.irqs > iIRQSMAX) + { + printf ("\nMOS6510 ERROR: An external component is not clearing down it's IRQs.\n\n"); + exit (-1); + } +} + +void MOS6510::clearIRQ (void) +{ + if (interrupts.irqs > 0) + { + if (!(--interrupts.irqs)) + { // Clear off the interrupts + interrupts.irqRequest = false; + } + } +} + +bool MOS6510::interruptPending (void) +{ + int_least8_t offset, pending; + static const int_least8_t offTable[] = {oNONE, oRST, oNMI, oRST, + oIRQ, oRST, oNMI, oRST}; + // Update IRQ pending + if (!interrupts.irqLatch) + { + interrupts.pending &= ~iIRQ; + if (interrupts.irqRequest) + interrupts.pending |= iIRQ; + } + + pending = interrupts.pending; +MOS6510_interruptPending_check: + // Service the highest priority interrupt + offset = offTable[pending]; + switch (offset) + { + case oNONE: + return false; + + case oNMI: + { + // Try to determine if we should be processing the NMI yet + event_clock_t cycles = eventContext.getTime (interrupts.nmiClock); + if (cycles >= interrupts.delay) + { + interrupts.pending &= ~iNMI; + break; + } + + // NMI delayed so check for other interrupts + pending &= ~iNMI; + goto MOS6510_interruptPending_check; + } + + case oIRQ: + { + // Try to determine if we should be processing the IRQ yet + event_clock_t cycles = eventContext.getTime (interrupts.irqClock); + if (cycles >= interrupts.delay) + break; + + // NMI delayed so check for other interrupts + pending &= ~iIRQ; + goto MOS6510_interruptPending_check; + } + + case oRST: + break; + } + +#ifdef MOS6510_DEBUG + if (dodump) + { + printf ("****************************************************\n"); + switch (offset) + { + case oIRQ: + printf (" IRQ Routine\n"); + break; + case oNMI: + printf (" NMI Routine\n"); + break; + case oRST: + printf (" RST Routine\n"); + break; + } + printf ("****************************************************\n"); + } +#endif + + // Start the interrupt + instrCurrent = &interruptTable[offset]; + procCycle = instrCurrent->cycle; + cycleCount = 0; + return true; +} + +void MOS6510::RSTRequest (void) +{ + envReset (); +} + +void MOS6510::NMIRequest (void) +{ + if (rdy && aec) + endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFA)); + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::NMI1Request (void) +{ + if (rdy && aec) + { + endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFB)); + endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress); + } + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::IRQRequest (void) +{ + PushSR (false); + setFlagI (true); + interrupts.irqRequest = false; +} + +void MOS6510::IRQ1Request (void) +{ + if (rdy && aec) + endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFE)); + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::IRQ2Request (void) +{ + if (rdy && aec) + { + endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFF)); + endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress); + } + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::NextInstr (void) +{ + if (!interruptPending ()) + FetchOpcode (); +} + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Common Instruction Addressing Routines // +// Addressing operations as described in 64doc by John West and // +// Marko Makela // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +// Fetch opcode, increment PC +// Addressing Modes: All +void MOS6510::FetchOpcode (void) +{ + if (rdy && aec) + { // On new instruction all interrupt delays are reset + interrupts.delay = MOS6510_INTERRUPT_DELAY; + interrupts.irqLatch = false; + + instrStartPC = endian_32lo16 (Register_ProgramCounter++); + instrOpcode = envReadMemByte (instrStartPC); + // Convert opcode to pointer in instruction table + instrCurrent = &instrTable[instrOpcode]; + Instr_Operand = 0; + procCycle = instrCurrent->cycle; + cycleCount = 0; + clock (); + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Fetch value, increment PC +/* Addressing Modes: Immediate + Relative +*/ +void MOS6510::FetchDataByte (void) +{ // Get data byte from memory + Cycle_Data = envReadMemByte (endian_32lo16 (Register_ProgramCounter)); + Register_ProgramCounter++; + + // Nextline used for Debug + Instr_Operand = (uint_least16_t) Cycle_Data; +} + +// Fetch low address byte, increment PC +/* Addressing Modes: Stack Manipulation + Absolute + Zero Page + Zerp Page Indexed + Absolute Indexed + Absolute Indirect +*/ +void MOS6510::FetchLowAddr (void) +{ + if (rdy && aec) + { + Cycle_EffectiveAddress = envReadMemByte (endian_32lo16 (Register_ProgramCounter)); + Register_ProgramCounter++; + + // Nextline used for Debug + Instr_Operand = Cycle_EffectiveAddress; + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Read from address, add index register X to it +// Addressing Modes: Zero Page Indexed +void MOS6510::FetchLowAddrX (void) +{ + FetchLowAddr (); + Cycle_EffectiveAddress = (Cycle_EffectiveAddress + Register_X) & 0xFF; +} + +// Read from address, add index register Y to it +// Addressing Modes: Zero Page Indexed +void MOS6510::FetchLowAddrY (void) +{ + FetchLowAddr (); + Cycle_EffectiveAddress = (Cycle_EffectiveAddress + Register_Y) & 0xFF; +} + +// Fetch high address byte, increment PC (Absoulte Addressing) +// Low byte must have been obtained first! +// Addressing Modes: Absolute +void MOS6510::FetchHighAddr (void) +{ + if (rdy && aec) + { // Get the high byte of an address from memory + endian_16hi8 (Cycle_EffectiveAddress, envReadMemByte (endian_32lo16 (Register_ProgramCounter))); + Register_ProgramCounter++; + + // Nextline used for Debug + endian_16hi8 (Instr_Operand, endian_16hi8 (Cycle_EffectiveAddress)); + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Fetch high byte of address, add index register X to low address byte, +// increment PC +// Addressing Modes: Absolute Indexed +void MOS6510::FetchHighAddrX (void) +{ + uint8_t page; + // Rev 1.05 (saw) - Call base Function + FetchHighAddr (); + page = endian_16hi8 (Cycle_EffectiveAddress); + Cycle_EffectiveAddress += Register_X; + +#ifdef MOS6510_ACCURATE_CYCLES + // Handle page boundary crossing + if (endian_16hi8 (Cycle_EffectiveAddress) == page) + cycleCount++; +#endif +} + +// Same as above except dosen't worry about page crossing +void MOS6510::FetchHighAddrX2 (void) +{ + FetchHighAddr (); + Cycle_EffectiveAddress += Register_X; +} + +// Fetch high byte of address, add index register Y to low address byte, +// increment PC +// Addressing Modes: Absolute Indexed +void MOS6510::FetchHighAddrY (void) +{ + uint8_t page; + // Rev 1.05 (saw) - Call base Function + FetchHighAddr (); + page = endian_16hi8 (Cycle_EffectiveAddress); + Cycle_EffectiveAddress += Register_Y; + +#ifdef MOS6510_ACCURATE_CYCLES + // Handle page boundary crossing + if (endian_16hi8 (Cycle_EffectiveAddress) == page) + cycleCount++; +#endif +} + +// Same as above except dosen't worry about page crossing +void MOS6510::FetchHighAddrY2 (void) +{ + FetchHighAddr (); + Cycle_EffectiveAddress += Register_Y; +} + +// Fetch pointer address low, increment PC +/* Addressing Modes: Absolute Indirect + Indirect indexed (post Y) +*/ +void MOS6510::FetchLowPointer (void) +{ + if (rdy && aec) + { + Cycle_Pointer = envReadMemByte (endian_32lo16 (Register_ProgramCounter)); + Register_ProgramCounter++; + // Nextline used for Debug + Instr_Operand = Cycle_Pointer; + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Read pointer from the address and add X to it +// Addressing Modes: Indexed Indirect (pre X) +void MOS6510::FetchLowPointerX (void) +{ + if (rdy && aec) + { + endian_16hi8 (Cycle_Pointer, envReadMemDataByte (Cycle_Pointer)); + // Page boundary crossing is not handled + Cycle_Pointer = (Cycle_Pointer + Register_X) & 0xFF; + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Fetch pointer address high, increment PC +// Addressing Modes: Absolute Indirect +void MOS6510::FetchHighPointer (void) +{ + if (rdy && aec) + { + endian_16hi8 (Cycle_Pointer, envReadMemByte (endian_32lo16 (Register_ProgramCounter))); + Register_ProgramCounter++; + + // Nextline used for Debug + endian_16hi8 (Instr_Operand, endian_16hi8 (Cycle_Pointer)); + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Fetch effective address low +/* Addressing Modes: Indirect + Indexed Indirect (pre X) + Indirect indexed (post Y) +*/ +void MOS6510::FetchLowEffAddr (void) +{ + if (rdy && aec) + Cycle_EffectiveAddress = envReadMemDataByte (Cycle_Pointer); + else + { // Address bus not ready + stealCycle(); + } +} + +// Fetch effective address high +/* Addressing Modes: Indirect + Indexed Indirect (pre X) +*/ +void MOS6510::FetchHighEffAddr (void) +{ + if (rdy && aec) + { // Rev 1.03 (Mike) - Extra +1 removed + endian_16lo8 (Cycle_Pointer, (Cycle_Pointer + 1) & 0xff); + endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (Cycle_Pointer)); + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Fetch effective address high, add Y to low byte of effective address +// Addressing Modes: Indirect indexed (post Y) +void MOS6510::FetchHighEffAddrY (void) +{ + uint8_t page; + // Rev 1.05 (saw) - Call base Function + FetchHighEffAddr (); + page = endian_16hi8 (Cycle_EffectiveAddress); + Cycle_EffectiveAddress += Register_Y; + +#ifdef MOS6510_ACCURATE_CYCLES + // Handle page boundary crossing + if (endian_16hi8 (Cycle_EffectiveAddress) == page) + cycleCount++; +#endif +} + +// Same as above except dosen't worry about page crossing +void MOS6510::FetchHighEffAddrY2 (void) +{ + FetchHighEffAddr (); + Cycle_EffectiveAddress += Register_Y; +} + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Common Data Accessing Routines // +// Data Accessing operations as described in 64doc by John West and // +// Marko Makela // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +void MOS6510::FetchEffAddrDataByte (void) +{ + if (rdy && aec) + Cycle_Data = envReadMemDataByte (Cycle_EffectiveAddress); + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::PutEffAddrDataByte (void) +{ + if (aec) + envWriteMemByte (Cycle_EffectiveAddress, Cycle_Data); + else + { // Address bus not ready + stealCycle(); + } +} + +// Used for Read Modify Write (RMW) instructions +void MOS6510::FetchPutEffAddrDataByte (void) +{ + FetchEffAddrDataByte (); + PutEffAddrDataByte (); +} + +// Push Program Counter Low Byte on stack, decrement S +void MOS6510::PushLowPC (void) +{ + if (aec) + { + uint_least16_t addr; + addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + envWriteMemByte (addr, endian_32lo8 (Register_ProgramCounter)); + Register_StackPointer--; + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Push Program Counter High Byte on stack, decrement S +void MOS6510::PushHighPC (void) +{ + if (aec) + { + uint_least16_t addr; + addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + envWriteMemByte (addr, endian_32hi8 (Register_ProgramCounter)); + Register_StackPointer--; + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Increment stack and pull program counter low byte from stack, +void MOS6510::PopLowPC (void) +{ + if (rdy && aec) + { + uint_least16_t addr; + Register_StackPointer++; + addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (addr)); + } + else + { // Address bus not ready + stealCycle(); + } +} + +// Increment stack and pull program counter high byte from stack, +void MOS6510::PopHighPC (void) +{ + if (rdy && aec) + { + uint_least16_t addr; + Register_StackPointer++; + addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (addr)); + } + else + { // Address bus not ready + stealCycle(); + } +} + +void MOS6510::WasteCycle (void) +{ +} + +void MOS6510::DebugCycle (void) +{ + if (dodump) + DumpState (); + clock (); +} + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Common Instruction Opcodes // +// See and 6510 Assembly Book for more information on these instructions // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +void MOS6510::brk_instr (void) +{ + PushSR (); + setFlagI (true); + interrupts.irqRequest = false; + + // Check for an NMI, and switch over if pending + if (interrupts.pending & iNMI) + { + event_clock_t cycles = eventContext.getTime (interrupts.nmiClock); + if (cycles >= interrupts.delay) + { + interrupts.pending &= ~iNMI; + instrCurrent = &interruptTable[oNMI]; + procCycle = &instrCurrent->cycle[cycleCount]; + } + } +} + +void MOS6510::cld_instr (void) +{ + setFlagD (false); +} + +void MOS6510::cli_instr (void) +{ + bool oldFlagI = getFlagI (); + setFlagI (false); + // I flag change is delayed by 1 instruction + interrupts.irqLatch = oldFlagI ^ getFlagI (); + // Check to see if interrupts got re-enabled + if (interrupts.irqs) + interrupts.irqRequest = true; +} + +void MOS6510::jmp_instr (void) +{ + endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress); +} + +void MOS6510::jsr_instr (void) +{ // JSR uses absolute addressing in this emulation, + // hence the -1. The real SID does not use this addressing + // mode. + Register_ProgramCounter--; + PushHighPC (); +} + +void MOS6510::pha_instr (void) +{ + if (aec) + { + uint_least16_t addr; + addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + envWriteMemByte (addr, Register_Accumulator); + Register_StackPointer--; + } + else + { // Address bus not ready + cycleCount--; + return; + } +} + +/* RTI does not delay the IRQ I flag change as it is set 3 cycles before + * the end of the opcode, and thus the 6510 has enough time to call the + * interrupt routine as soon as the opcode ends, if necessary. */ +void MOS6510::rti_instr (void) +{ +#ifdef MOS6510_DEBUG + if (dodump) + printf ("****************************************************\n\n"); +#endif + + endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress); + interrupts.irqLatch = false; +} + +void MOS6510::rts_instr (void) +{ +/* + // Hack - Output character to screen + if (Register_ProgramCounter == 0xffd3) + { + char ch = _sidtune_CHRtab[Register_Accumulator]; + switch (ch) + { + case 0: + break; + case 1: + printf (" "); + fprintf (stderr, " "); + case 0xd: + printf ("\n"); + fprintf (stderr, "\n"); + filepos = 0; + break; + default: + filetmp[filepos++] = ch; + printf ("%c", ch); + fprintf (stderr, "%c", ch); + } + } + + if (Register_ProgramCounter == 0xe170) + { + filetmp[filepos] = '\0'; + envLoadFile (filetmp); + } +*/ + endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress); + Register_ProgramCounter++; +} + +void MOS6510::sed_instr (void) +{ + setFlagD (true); +} + +void MOS6510::sei_instr (void) +{ + bool oldFlagI = getFlagI (); + setFlagI (true); + // I flag change is delayed by 1 instruction + interrupts.irqLatch = oldFlagI ^ getFlagI (); + interrupts.irqRequest = false; +} + +void MOS6510::sta_instr (void) +{ + Cycle_Data = Register_Accumulator; + PutEffAddrDataByte (); +} + +void MOS6510::stx_instr (void) +{ + Cycle_Data = Register_X; + PutEffAddrDataByte (); +} + +void MOS6510::sty_instr (void) +{ + Cycle_Data = Register_Y; + PutEffAddrDataByte (); +} + + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Common Instruction Undocumented Opcodes // +// See documented 6502-nmo.opc by Adam Vardy for more details // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +// Undocumented - This opcode stores the result of A AND X AND the high +// byte of the target address of the operand +1 in memory. +void MOS6510::axa_instr (void) +{ + Cycle_Data = Register_X & Register_Accumulator & (endian_16hi8 (Cycle_EffectiveAddress) + 1); + PutEffAddrDataByte (); +} + +// Undocumented - AXS ANDs the contents of the A and X registers (without changing the +// contents of either register) and stores the result in memory. +// AXS does not affect any flags in the processor status register. +void MOS6510::axs_instr (void) +{ + Cycle_Data = Register_Accumulator & Register_X; +} + +/* Not required - Operation performed By another method +// Undocumented - HLT crashes the microprocessor. When this opcode is executed, program +// execution ceases. No hardware interrupts will execute either. The author +// has characterized this instruction as a halt instruction since this is the +// most straightforward explanation for this opcode's behaviour. Only a reset +// will restart execution. This opcode leaves no trace of any operation +// performed! No registers affected. +void MOS6510::hlt_instr (void) +{ +} +*/ + +/* Not required - Operation performed By another method +void MOS6510::nop_instr (void) +{ +} +*/ + +/* Not required - Operation performed By another method +void MOS6510::php_instr (void) +{ +} +*/ + +// Undocumented - This opcode ANDs the contents of the Y register with <ab+1> and stores the +// result in memory. +void MOS6510::say_instr (void) +{ + Cycle_Data = Register_Y & (endian_16hi8 (Cycle_EffectiveAddress) + 1); +} + +/* Not required - Operation performed By another method +// Undocumented - skip next byte. +void MOS6510::skb_instr (void) +{ + Register_ProgramCounter++; +} +*/ + +/* Not required - Operation performed By another method +// Undocumented - skip next word. +void MOS6510::skw_instr (void) +{ + Register_ProgramCounter += 2; +} +*/ + +// Undocumented - This opcode ANDs the contents of the X register with <ab+1> and stores the +// result in memory. +void MOS6510::xas_instr (void) +{ + Cycle_Data = Register_X & (endian_16hi8 (Cycle_EffectiveAddress) + 1); +} + + +#ifdef X86 +#include "MOS6510\CYCLE_~1\X86.CPP" +//#include "MOS6510\CYCLE_BASED\X86.CPP" +#else + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Generic Binary Coded Decimal Correction // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +void MOS6510::Perform_ADC (void) +{ + uint C = getFlagC (); + uint A = Register_Accumulator; + uint s = Cycle_Data; + uint regAC2 = A + s + C; + + if (getFlagD ()) + { // BCD mode + uint lo = (A & 0x0f) + (s & 0x0f) + C; + uint hi = (A & 0xf0) + (s & 0xf0); + if (lo > 0x09) lo += 0x06; + if (lo > 0x0f) hi += 0x10; + + setFlagZ (regAC2); + setFlagN (hi); + setFlagV (((hi ^ A) & 0x80) && !((A ^ s) & 0x80)); + if (hi > 0x90) hi += 0x60; + + setFlagC (hi > 0xff); + Register_Accumulator = (hi | (lo & 0x0f)); + } + else + { // Binary mode + setFlagC (regAC2 > 0xff); + setFlagV (((regAC2 ^ A) & 0x80) && !((A ^ s) & 0x80)); + setFlagsNZ (Register_Accumulator = regAC2 & 0xff); + } +} + +void MOS6510::Perform_SBC (void) +{ + uint C = !getFlagC (); + uint A = Register_Accumulator; + uint s = Cycle_Data; + uint regAC2 = A - s - C; + + setFlagC (regAC2 < 0x100); + setFlagV (((regAC2 ^ A) & 0x80) && ((A ^ s) & 0x80)); + setFlagsNZ (regAC2); + + if (getFlagD ()) + { // BCD mode + uint lo = (A & 0x0f) - (s & 0x0f) - C; + uint hi = (A & 0xf0) - (s & 0xf0); + if (lo & 0x10) + { + lo -= 0x06; + hi -= 0x10; + } + if (hi & 0x100) hi -= 0x60; + Register_Accumulator = (hi | (lo & 0x0f)); + } + else + { // Binary mode + Register_Accumulator = regAC2 & 0xff; + } +} + + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Generic Instruction Addressing Routines // +//-------------------------------------------------------------------------/ + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Generic Instruction Opcodes // +// See and 6510 Assembly Book for more information on these instructions // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +void MOS6510::adc_instr (void) +{ + Perform_ADC (); +} + +void MOS6510::and_instr (void) +{ + setFlagsNZ (Register_Accumulator &= Cycle_Data); +} + +void MOS6510::ane_instr (void) +{ + setFlagsNZ (Register_Accumulator = (Register_Accumulator | 0xee) & Register_X & Cycle_Data); +} + +void MOS6510::asl_instr (void) +{ + setFlagC (Cycle_Data & 0x80); + setFlagsNZ (Cycle_Data <<= 1); +} + +void MOS6510::asla_instr (void) +{ + setFlagC (Register_Accumulator & 0x80); + setFlagsNZ (Register_Accumulator <<= 1); +} + +void MOS6510::branch_instr (bool condition) +{ + if (condition) +#ifdef MOS6510_ACCURATE_CYCLES + { + uint8_t page; + page = endian_32hi8 (Register_ProgramCounter); + Register_ProgramCounter += (int8_t) Cycle_Data; + + // Handle page boundary crossing + if (endian_32hi8 (Register_ProgramCounter) == page) + { + cycleCount++; + interrupts.delay++; + } + } + else + { + cycleCount += 2; + } +#else + Register_ProgramCounter += (int8_t) Cycle_Data; +#endif +} + +void MOS6510::bcc_instr (void) +{ + branch_instr (!getFlagC ()); +} + +void MOS6510::bcs_instr (void) +{ + branch_instr (getFlagC ()); +} + +void MOS6510::beq_instr (void) +{ + branch_instr (getFlagZ ()); +} + +void MOS6510::bit_instr (void) +{ + setFlagZ (Register_Accumulator & Cycle_Data); + setFlagN (Cycle_Data); + setFlagV (Cycle_Data & 0x40); +} + +void MOS6510::bmi_instr (void) +{ + branch_instr (getFlagN ()); +} + +void MOS6510::bne_instr (void) +{ + branch_instr (!getFlagZ ()); +} + +void MOS6510::bpl_instr(void) +{ + branch_instr (!getFlagN ()); +} + +void MOS6510::bvc_instr (void) +{ + branch_instr (!getFlagV ()); +} + +void MOS6510::bvs_instr (void) +{ + branch_instr (getFlagV ()); +} + +void MOS6510::clc_instr (void) +{ + setFlagC (false); +} + +void MOS6510::clv_instr (void) +{ + setFlagV (false); +} + +void MOS6510::cmp_instr (void) +{ + uint_least16_t tmp = (uint_least16_t) Register_Accumulator - Cycle_Data; + setFlagsNZ (tmp); + setFlagC (tmp < 0x100); +} + +void MOS6510::cpx_instr (void) +{ + uint_least16_t tmp = (uint_least16_t) Register_X - Cycle_Data; + setFlagsNZ (tmp); + setFlagC (tmp < 0x100); +} + +void MOS6510::cpy_instr (void) +{ + uint_least16_t tmp = (uint_least16_t) Register_Y - Cycle_Data; + setFlagsNZ (tmp); + setFlagC (tmp < 0x100); +} + +void MOS6510::dec_instr (void) +{ + setFlagsNZ (--Cycle_Data); +} + +void MOS6510::dex_instr (void) +{ + setFlagsNZ (--Register_X); +} + +void MOS6510::dey_instr (void) +{ + setFlagsNZ (--Register_Y); +} + +void MOS6510::eor_instr (void) +{ + setFlagsNZ (Register_Accumulator^= Cycle_Data); +} + +void MOS6510::inc_instr (void) +{ + setFlagsNZ (++Cycle_Data); +} + +void MOS6510::inx_instr (void) +{ + setFlagsNZ (++Register_X); +} + +void MOS6510::iny_instr (void) +{ + setFlagsNZ (++Register_Y); +} + +void MOS6510::lda_instr (void) +{ + setFlagsNZ (Register_Accumulator = Cycle_Data); +} + +void MOS6510::ldx_instr (void) +{ + setFlagsNZ (Register_X = Cycle_Data); +} + +void MOS6510::ldy_instr (void) +{ + setFlagsNZ (Register_Y = Cycle_Data); +} + +void MOS6510::lsr_instr (void) +{ + setFlagC (Cycle_Data & 0x01); + setFlagsNZ (Cycle_Data >>= 1); +} + +void MOS6510::lsra_instr (void) +{ + setFlagC (Register_Accumulator & 0x01); + setFlagsNZ (Register_Accumulator >>= 1); +} + +void MOS6510::ora_instr (void) +{ + setFlagsNZ (Register_Accumulator |= Cycle_Data); +} + +void MOS6510::pla_instr (void) +{ + if (rdy && aec) + { + uint_least16_t addr; + Register_StackPointer++; + addr = Register_StackPointer; + endian_16hi8 (addr, SP_PAGE); + setFlagsNZ (Register_Accumulator = envReadMemByte (addr)); + } + else + { // Address bus not ready + cycleCount--; + return; + } +} + +void MOS6510::rol_instr (void) +{ + uint8_t tmp = Cycle_Data & 0x80; + Cycle_Data <<= 1; + if (getFlagC ()) Cycle_Data |= 0x01; + setFlagsNZ (Cycle_Data); + setFlagC (tmp); +} + +void MOS6510::rola_instr (void) +{ + uint8_t tmp = Register_Accumulator & 0x80; + Register_Accumulator <<= 1; + if (getFlagC ()) Register_Accumulator |= 0x01; + setFlagsNZ (Register_Accumulator); + setFlagC (tmp); +} + +void MOS6510::ror_instr (void) +{ + uint8_t tmp = Cycle_Data & 0x01; + Cycle_Data >>= 1; + if (getFlagC ()) Cycle_Data |= 0x80; + setFlagsNZ (Cycle_Data); + setFlagC (tmp); +} + +void MOS6510::rora_instr (void) +{ + uint8_t tmp = Register_Accumulator & 0x01; + Register_Accumulator >>= 1; + if (getFlagC ()) Register_Accumulator |= 0x80; + setFlagsNZ (Register_Accumulator); + setFlagC (tmp); +} + +void MOS6510::sbx_instr (void) +{ + uint tmp = (Register_X & Register_Accumulator) - Cycle_Data; + setFlagsNZ (Register_X = tmp & 0xff); + setFlagC (tmp < 0x100); +} + +void MOS6510::sbc_instr (void) +{ + Perform_SBC (); +} + +void MOS6510::sec_instr (void) +{ + setFlagC (true); +} + +void MOS6510::shs_instr (void) +{ + endian_16lo8 (Register_StackPointer, (Register_Accumulator & Register_X)); + Cycle_Data = (endian_16hi8 (Cycle_EffectiveAddress) + 1) & Register_StackPointer; +} + +void MOS6510::tax_instr (void) +{ + setFlagsNZ (Register_X = Register_Accumulator); +} + +void MOS6510::tay_instr (void) +{ + setFlagsNZ (Register_Y = Register_Accumulator); +} + +void MOS6510::tsx_instr (void) +{ // Rev 1.03 (saw) - Got these tsx and txs reversed + setFlagsNZ (Register_X = endian_16lo8 (Register_StackPointer)); +} + +void MOS6510::txa_instr (void) +{ + setFlagsNZ (Register_Accumulator = Register_X); +} + +void MOS6510::txs_instr (void) +{ // Rev 1.03 (saw) - Got these tsx and txs reversed + endian_16lo8 (Register_StackPointer, Register_X); +} + +void MOS6510::tya_instr (void) +{ + setFlagsNZ (Register_Accumulator = Register_Y); +} + +void MOS6510::illegal_instr (void) +{ + printf ("\n\nILLEGAL INSTRUCTION, resetting emulation. **************\n"); + DumpState (); + printf ("********************************************************\n"); + // Perform Environment Reset + envReset (); +} + + +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// +// Generic Instruction Undocuemented Opcodes // +// See documented 6502-nmo.opc by Adam Vardy for more details // +//-------------------------------------------------------------------------// +//-------------------------------------------------------------------------// + +// Undocumented - This opcode ANDs the contents of the A register with an immediate value and +// then LSRs the result. +void MOS6510::alr_instr (void) +{ + Register_Accumulator &= Cycle_Data; + setFlagC (Register_Accumulator & 0x01); + setFlagsNZ (Register_Accumulator >>= 1); +} + +// Undcouemented - ANC ANDs the contents of the A register with an immediate value and then +// moves bit 7 of A into the Carry flag. This opcode works basically +// identically to AND #immed. except that the Carry flag is set to the same +// state that the Negative flag is set to. +void MOS6510::anc_instr (void) +{ + setFlagsNZ (Register_Accumulator &= Cycle_Data); + setFlagC (getFlagN ()); +} + +// Undocumented - This opcode ANDs the contents of the A register with an immediate value and +// then RORs the result (Implementation based on that of Frodo C64 Emulator) +void MOS6510::arr_instr (void) +{ + uint8_t data = Cycle_Data & Register_Accumulator; + Register_Accumulator = data >> 1; + if (getFlagC ()) Register_Accumulator |= 0x80; + + if (getFlagD ()) + { + setFlagN (0); + if (getFlagC ()) setFlagN (1 << SR_NEGATIVE); + setFlagZ (Register_Accumulator); + setFlagV ((data ^ Register_Accumulator) & 0x40); + + if ((data & 0x0f) + (data & 0x01) > 5) + Register_Accumulator = Register_Accumulator & 0xf0 | (Register_Accumulator + 6) & 0x0f; + setFlagC (((data + (data & 0x10)) & 0x1f0) > 0x50); + if (getFlagC ()) + Register_Accumulator += 0x60; + } + else + { + setFlagsNZ (Register_Accumulator); + setFlagC (Register_Accumulator & 0x40); + setFlagV ((Register_Accumulator & 0x40) ^ ((Register_Accumulator & 0x20) << 1)); + } +} + +// Undocumented - This opcode ASLs the contents of a memory location and then ORs the result +// with the accumulator. +void MOS6510::aso_instr (void) +{ + setFlagC (Cycle_Data & 0x80); + Cycle_Data <<= 1; + setFlagsNZ (Register_Accumulator |= Cycle_Data); +} + +// Undocumented - This opcode DECs the contents of a memory location and then CMPs the result +// with the A register. +void MOS6510::dcm_instr (void) +{ + uint_least16_t tmp; + Cycle_Data--; + tmp = (uint_least16_t) Register_Accumulator - Cycle_Data; + setFlagsNZ (tmp); + setFlagC (tmp < 0x100); +} + +// Undocumented - This opcode INCs the contents of a memory location and then SBCs the result +// from the A register. +void MOS6510::ins_instr (void) +{ + Cycle_Data++; + Perform_SBC (); +} + +// Undocumented - This opcode ANDs the contents of a memory location with the contents of the +// stack pointer register and stores the result in the accumulator, the X +// register, and the stack pointer. Affected flags: N Z. +void MOS6510::las_instr (void) +{ + setFlagsNZ (Cycle_Data &= endian_16lo8 (Register_StackPointer)); + Register_Accumulator = Cycle_Data; + Register_X = Cycle_Data; + Register_StackPointer = Cycle_Data; +} + +// Undocumented - This opcode loads both the accumulator and the X register with the contents +// of a memory location. +void MOS6510::lax_instr (void) +{ + setFlagsNZ (Register_Accumulator = Register_X = Cycle_Data); +} + +// Undocumented - LSE LSRs the contents of a memory location and then EORs the result with +// the accumulator. +void MOS6510::lse_instr (void) +{ + setFlagC (Cycle_Data & 0x01); + Cycle_Data >>= 1; + setFlagsNZ (Register_Accumulator ^= Cycle_Data); +} + +// Undocumented - This opcode ORs the A register with #xx, ANDs the result with an immediate +// value, and then stores the result in both A and X. +// xx may be EE,EF,FE, OR FF, but most emulators seem to use EE +void MOS6510::oal_instr (void) +{ + setFlagsNZ (Register_X = (Register_Accumulator = (Cycle_Data & (Register_Accumulator | 0xee)))); +} + +// Undocumented - RLA ROLs the contents of a memory location and then ANDs the result with +// the accumulator. +void MOS6510::rla_instr (void) +{ + uint8_t tmp = Cycle_Data & 0x80; + Cycle_Data = Cycle_Data << 1; + if (getFlagC ()) Cycle_Data |= 0x01; + setFlagC (tmp); + setFlagsNZ (Register_Accumulator &= Cycle_Data); +} + +// Undocumented - RRA RORs the contents of a memory location and then ADCs the result with +// the accumulator. +void MOS6510::rra_instr (void) +{ + uint8_t tmp = Cycle_Data & 0x01; + Cycle_Data >>= 1; + if (getFlagC ()) Cycle_Data |= 0x80; + setFlagC (tmp); + Perform_ADC (); +} + +// Undocumented - This opcode ANDs the contents of the A and X registers (without changing +// the contents of either register) and transfers the result to the stack +// pointer. It then ANDs that result with the contents of the high byte of +// the target address of the operand +1 and stores that final result in +// memory. +void MOS6510::tas_instr (void) +{ + endian_16lo8 (Register_StackPointer, Register_Accumulator & Register_X); + uint_least16_t tmp = Register_StackPointer & (Cycle_EffectiveAddress + 1); + Cycle_Data = (signed) endian_16lo8 (tmp); +} + +#endif // X86 + + +//-------------------------------------------------------------------------// +// Initialise and create CPU Chip // + +//MOS6510::MOS6510 (model_t _model, const char *id) +MOS6510::MOS6510 (EventContext *context) +:eventContext(*context), + Event("CPU") +{ + struct ProcessorOperations *instr; + uint8_t legalMode = true; + uint8_t legalInstr = true; + uint i, pass; + + //---------------------------------------------------------------------- + // Build up the processor instruction table + for (i = 0; i < 0x100; i++) + { +#if MOS6510_DEBUG > 1 + printf ("Building Command %d[%02x]..", i, i); +#endif + + // Pass 1 allocates the memory, Pass 2 builds the instruction + instr = &instrTable[i]; + instr->cycle = NULL; + + for (pass = 0; pass < 2; pass++) + { + enum {WRITE = 0, RMW = 1, READ = 2}; + int access = WRITE; + cycleCount = -1; + legalMode = true; + legalInstr = true; + if (pass) procCycle = instr->cycle; + + switch (i) + { + // Accumulator or Implied addressing + case ASLn: case CLCn: case CLDn: case CLIn: case CLVn: case DEXn: + case DEYn: case INXn: case INYn: case LSRn: case NOPn_: case PHAn: + case PHPn: case PLAn: case PLPn: case ROLn: case RORn: case RTIn: + case RTSn: case SECn: case SEDn: case SEIn: case TAXn: case TAYn: + case TSXn: case TXAn: case TXSn: case TYAn: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + // Immediate and Relative Addressing Mode Handler + case ADCb: case ANDb: case ANCb_: case ANEb: case ASRb: case ARRb: + case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr: + case BRKn: case BVCr: case BVSr: case CMPb: case CPXb: case CPYb: + case EORb: case LDAb: case LDXb: case LDYb: case LXAb: case NOPb_: + case ORAb: case SBCb_: case SBXb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchDataByte; + break; + + // Zero Page Addressing Mode Handler - Read & RMW + case ADCz: case ANDz: case BITz: case CMPz: case CPXz: case CPYz: + case EORz: case LAXz: case LDAz: case LDXz: case LDYz: case ORAz: + case NOPz_: case SBCz: + access++; + case ASLz: case DCPz: case DECz: case INCz: case ISBz: case LSRz: + case ROLz: case RORz: case SREz: case SLOz: case RLAz: case RRAz: + access++; + case SAXz: case STAz: case STXz: case STYz: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr; + if (access == READ) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + } else if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + // Zero Page with X Offset Addressing Mode Handler + case ADCzx: case ANDzx: case CMPzx: case EORzx: case LDAzx: case LDYzx: + case NOPzx_: case ORAzx: case SBCzx: + access++; + case ASLzx: case DCPzx: case DECzx: case INCzx: case ISBzx: case LSRzx: + case RLAzx: case ROLzx: case RORzx: case RRAzx: case SLOzx: case SREzx: + access++; + case STAzx: case STYzx: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddrX; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + if (access == READ) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + } else if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + // Zero Page with Y Offset Addressing Mode Handler + case LDXzy: case LAXzy: + access = READ; + case STXzy: case SAXzy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddrY; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + if (access == READ) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + } + break; + + // Absolute Addressing Mode Handler + case ADCa: case ANDa: case BITa: case CMPa: case CPXa: case CPYa: + case EORa: case LAXa: case LDAa: case LDXa: case LDYa: case NOPa: + case ORAa: case SBCa: + access++; + case ASLa: case DCPa: case DECa: case INCa: case ISBa: case LSRa: + case ROLa: case RORa: case SLOa: case SREa: case RLAa: case RRAa: + access++; + case JMPw: case JSRw: case SAXa: case STAa: case STXa: case STYa: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddr; + if (access == READ) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + } else if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + // Absolute With X Offset Addressing Mode Handler (Read) + case ADCax: case ANDax: case CMPax: case EORax: case LDAax: + case LDYax: case NOPax_: case ORAax: case SBCax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrX; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + break; + + // Absolute X (No page crossing handled) + case ASLax: case DCPax: case DECax: case INCax: case ISBax: + case LSRax: case RLAax: case ROLax: case RORax: case RRAax: + case SLOax: case SREax: + access = RMW; + case SHYax: case STAax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrX2; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + // Absolute With Y Offset Addresing Mode Handler (Read) + case ADCay: case ANDay: case CMPay: case EORay: case LASay: + case LAXay: case LDAay: case LDXay: case ORAay: case SBCay: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrY; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + break; + + // Absolute Y (No page crossing handled) + case DCPay: case ISBay: case RLAay: case RRAay: case SLOay: + case SREay: + access = RMW; + case SHAay: case SHSay: case SHXay: case STAay: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrY2; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + // Absolute Indirect Addressing Mode Handler + case JMPi: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighPointer; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddr; + break; + + // Indexed with X Preinc Addressing Mode Handler + case ADCix: case ANDix: case CMPix: case EORix: case LAXix: case LDAix: + case ORAix: case SBCix: + access++; + case DCPix: case ISBix: case SLOix: case SREix: case RLAix: case RRAix: + access++; + case SAXix: case STAix: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointerX; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddr; + if (access == READ) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + } else if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + // Indexed with Y Postinc Addressing Mode Handler (Read) + case ADCiy: case ANDiy: case CMPiy: case EORiy: case LAXiy: + case LDAiy: case ORAiy: case SBCiy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddrY; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte; + break; + + // Indexed Y (No page crossing handled) + case DCPiy: case ISBiy: case RLAiy: case RRAiy: case SLOiy: + case SREiy: + access = RMW; + case SHAiy: case STAiy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddrY2; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + if (access == RMW) { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte; + } + break; + + default: + legalMode = false; + break; + } + +#ifdef MOS6510_DEBUG + if (legalMode) + { + cycleCount++; + if (pass) procCycle[cycleCount] = &MOS6510::DebugCycle; + } +#endif // MOS6510_DEBUG + + //--------------------------------------------------------------------------------------- + // Addressing Modes Finished, other cycles are instruction dependent + switch(i) + { + case ADCz: case ADCzx: case ADCa: case ADCax: case ADCay: case ADCix: + case ADCiy: case ADCb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::adc_instr; + break; + + case ANCb_: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::anc_instr; + break; + + case ANDz: case ANDzx: case ANDa: case ANDax: case ANDay: case ANDix: + case ANDiy: case ANDb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::and_instr; + break; + + case ANEb: // Also known as XAA + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ane_instr; + break; + + case ARRb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::arr_instr; + break; + + case ASLn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::asla_instr; + break; + + case ASLz: case ASLzx: case ASLa: case ASLax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::asl_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case ASRb: // Also known as ALR + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::alr_instr; + break; + + case BCCr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bcc_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BCSr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bcs_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BEQr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::beq_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BITz: case BITa: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bit_instr; + break; + + case BMIr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bmi_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BNEr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bne_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BPLr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bpl_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BRKn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushHighPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::brk_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ1Request; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ2Request; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode; + break; + + case BVCr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bvc_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case BVSr: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bvs_instr; +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + break; + + case CLCn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::clc_instr; + break; + + case CLDn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cld_instr; + break; + + case CLIn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cli_instr; + break; + + case CLVn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::clv_instr; + break; + + case CMPz: case CMPzx: case CMPa: case CMPax: case CMPay: case CMPix: + case CMPiy: case CMPb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cmp_instr; + break; + + case CPXz: case CPXa: case CPXb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cpx_instr; + break; + + case CPYz: case CPYa: case CPYb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cpy_instr; + break; + + case DCPz: case DCPzx: case DCPa: case DCPax: case DCPay: case DCPix: + case DCPiy: // Also known as DCM + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dcm_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case DECz: case DECzx: case DECa: case DECax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dec_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case DEXn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dex_instr; + break; + + case DEYn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dey_instr; + break; + + case EORz: case EORzx: case EORa: case EORax: case EORay: case EORix: + case EORiy: case EORb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::eor_instr; + break; + +/* HLT // Also known as JAM + case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: + case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2: + case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: + case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2: + cycleCount++; if (pass) procCycle[cycleCount] = hlt_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; +*/ + + case INCz: case INCzx: case INCa: case INCax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::inc_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case INXn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::inx_instr; + break; + + case INYn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::iny_instr; + break; + + case ISBz: case ISBzx: case ISBa: case ISBax: case ISBay: case ISBix: + case ISBiy: // Also known as INS + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ins_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case JMPw: case JMPi: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::jmp_instr; + break; + + case JSRw: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::jsr_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::jmp_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case LASay: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::las_instr; + break; + + case LAXz: case LAXzy: case LAXa: case LAXay: case LAXix: case LAXiy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lax_instr; + break; + + case LDAz: case LDAzx: case LDAa: case LDAax: case LDAay: case LDAix: + case LDAiy: case LDAb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lda_instr; + break; + + case LDXz: case LDXzy: case LDXa: case LDXay: case LDXb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ldx_instr; + break; + + case LDYz: case LDYzx: case LDYa: case LDYax: case LDYb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ldy_instr; + break; + + case LSRn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lsra_instr; + break; + + case LSRz: case LSRzx: case LSRa: case LSRax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lsr_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case NOPn_: case NOPb_: + // Should not be required! + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case NOPz_: case NOPzx_: case NOPa: case NOPax_: + // NOPb NOPz NOPzx - Also known as SKBn + // NOPa NOPax - Also known as SKWn + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case LXAb: // Also known as OAL + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::oal_instr; + break; + + case ORAz: case ORAzx: case ORAa: case ORAax: case ORAay: case ORAix: + case ORAiy: case ORAb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ora_instr; + break; + + case PHAn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::pha_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case PHPn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushSR; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case PLAn: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::pla_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case PLPn: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopSR; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case RLAz: case RLAzx: case RLAix: case RLAa: case RLAax: case RLAay: + case RLAiy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rla_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case ROLn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rola_instr; + break; + + case ROLz: case ROLzx: case ROLa: case ROLax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rol_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case RORn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rora_instr; + break; + + case RORz: case RORzx: case RORa: case RORax: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ror_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case RRAa: case RRAax: case RRAay: case RRAz: case RRAzx: case RRAix: + case RRAiy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rra_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case RTIn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopSR; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopLowPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopHighPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rti_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case RTSn: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopLowPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopHighPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rts_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case SAXz: case SAXzy: case SAXa: case SAXix: // Also known as AXS + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::axs_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + break; + + case SBCz: case SBCzx: case SBCa: case SBCax: case SBCay: case SBCix: + case SBCiy: case SBCb_: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sbc_instr; + break; + + case SBXb: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sbx_instr; + break; + + case SECn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sec_instr; + break; + + case SEDn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sed_instr; + break; + + case SEIn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sei_instr; + break; + + case SHAay: case SHAiy: // Also known as AXA + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::axa_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case SHSay: // Also known as TAS + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::shs_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + break; + + case SHXay: // Also known as XAS + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::xas_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + break; + + case SHYax: // Also known as SAY + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::say_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + break; + + case SLOz: case SLOzx: case SLOa: case SLOax: case SLOay: case SLOix: + case SLOiy: // Also known as ASO + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::aso_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case SREz: case SREzx: case SREa: case SREax: case SREay: case SREix: + case SREiy: // Also known as LSE + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lse_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case STAz: case STAzx: case STAa: case STAax: case STAay: case STAix: + case STAiy: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sta_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case STXz: case STXzy: case STXa: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::stx_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case STYz: case STYzx: case STYa: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sty_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + break; + + case TAXn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tax_instr; + break; + + case TAYn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tay_instr; + break; + + case TSXn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tsx_instr; + break; + + case TXAn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::txa_instr; + break; + + case TXSn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::txs_instr; + break; + + case TYAn: + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tya_instr; + break; + + default: + legalInstr = false; + break; + } + + if (!(legalMode || legalInstr)) + { + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::illegal_instr; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + } + else if (!(legalMode && legalInstr)) + { + printf ("\nInstruction 0x%x: Not built correctly.\n\n", i); + exit(1); + } + + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::NextInstr; + cycleCount++; + if (!pass) + { // Pass 1 - Allocate Memory + if (cycleCount) + { +#if defined(_MSC_VER) && (_MSC_VER <= _MSC_VER_BAD_NEW) + typedef void (MOS6510::*ptr2cycle) (void); + instr->cycle = (ptr2cycle*) new char[sizeof (ptr2cycle) *cycleCount]; +#else +# ifdef HAVE_EXCEPTIONS + instr->cycle = new(std::nothrow) (void (MOS6510::*[cycleCount]) (void)); +# else + instr->cycle = new (void (MOS6510::*[cycleCount]) (void)); +# endif +#endif // _MSC_VER + if (!instr->cycle) + goto MOS6510_MemAllocFailed; + } + } + else + instr->opcode = i; + +#if MOS6510_DEBUG > 1 + printf ("."); +#endif + } + + instr->cycles = cycleCount; +#if MOS6510_DEBUG > 1 + printf ("Done [%d Cycles]\n", cycleCount); +#endif + } + + //---------------------------------------------------------------------- + // Build interrupts + for (i = 0; i < 3; i++) + { +#if MOS6510_DEBUG > 1 + printf ("Building Interrupt %d[%02x]..", i, i); +#endif + + // Pass 1 allocates the memory, Pass 2 builds the interrupt + instr = &interruptTable[i]; + instr->cycle = NULL; + instr->opcode = 0; + + for (int pass = 0; pass < 2; pass++) + { + cycleCount = -1; + if (pass) procCycle = instr->cycle; + + switch (i) + { + case oRST: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::RSTRequest; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode; + break; + + case oNMI: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushHighPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQRequest; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::NMIRequest; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::NMI1Request; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode; + break; + + case oIRQ: +#ifdef MOS6510_ACCURATE_CYCLES + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle; +#endif + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushHighPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQRequest; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ1Request; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ2Request; + cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode; + break; + } + + cycleCount++; + if (!pass) + { // Pass 1 - Allocate Memory + if (cycleCount) + { +#if defined(_MSC_VER) && (_MSC_VER <= _MSC_VER_BAD_NEW) + typedef void (MOS6510::*ptr2cycle) (void); + instr->cycle = (ptr2cycle*) new char[sizeof (ptr2cycle) *cycleCount]; +#else +# ifdef HAVE_EXCEPTIONS + instr->cycle = new(std::nothrow) (void (MOS6510::*[cycleCount]) (void)); +# else + instr->cycle = new (void (MOS6510::*[cycleCount]) (void)); +# endif +#endif // _MSC_VER + if (!instr->cycle) + goto MOS6510_MemAllocFailed; + } + } + +#if MOS6510_DEBUG > 1 + printf ("."); +#endif + } + + instr->cycles = cycleCount; +#if MOS6510_DEBUG > 1 + printf ("Done [%d Cycles]\n", cycleCount); +#endif + } + + // Intialise Processor Registers + Register_Accumulator = 0; + Register_X = 0; + Register_Y = 0; + + Cycle_EffectiveAddress = 0; + Cycle_Data = 0; + fetchCycle[0] = &MOS6510::NextInstr; + + dodump = false; + Initialise (); +return; + +MOS6510_MemAllocFailed: + printf ("Unable to allocate enough memory.\n\n"); +exit (-1); +} + +MOS6510::~MOS6510 () +{ + struct ProcessorOperations *instr; + uint i; + + // Remove Opcodes + for (i = 0; i < 0x100; i++) + { + instr = &instrTable[i]; + if (instr->cycle != NULL) delete [] instr->cycle; + } + + // Remove Interrupts + for (i = 0; i < 3; i++) + { + instr = &interruptTable[i]; + if (instr->cycle != NULL) delete [] instr->cycle; + } +} + + +//-------------------------------------------------------------------------// +// Initialise CPU Emulation (Registers) // +void MOS6510::Initialise (void) +{ + // Reset stack + Register_StackPointer = endian_16 (SP_PAGE, 0xFF); + + // Reset Cycle Count + cycleCount = 0; + procCycle = fetchCycle; + + // Reset Status Register + Register_Status = (1 << SR_NOTUSED) | (1 << SR_BREAK); + // FLAGS are set from data directly and do not require + // being calculated first before setting. E.g. if you used + // SetFlags (0), N flag would = 0, and Z flag would = 1. + setFlagsNZ (1); + setFlagC (false); + setFlagV (false); + + // Set PC to some value + Register_ProgramCounter = 0; + // IRQs pending check + interrupts.irqLatch = false; + interrupts.irqRequest = false; + if (interrupts.irqs) + interrupts.irqRequest = true; + + // Signals + aec = true; + rdy = true; + + m_blocked = false; + eventContext.schedule (this, 1); +} + +//-------------------------------------------------------------------------// +// Reset CPU Emulation // +void MOS6510::reset (void) +{ + // Reset Interrupts + interrupts.pending = false; + interrupts.irqs = 0; + interrupts.delay = MOS6510_INTERRUPT_DELAY; + + // Internal Stuff + Initialise (); + + // Requires External Bits + // Read from reset vector for program entry point + endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFC)); + endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFD)); + Register_ProgramCounter = Cycle_EffectiveAddress; +// filepos = 0; +} + +//-------------------------------------------------------------------------// +// Module Credits // +void MOS6510::credits (char *sbuffer) +{ // Copy credits to buffer + sprintf (sbuffer, "%sModule : MOS6510 Cycle Exact Emulation\n", sbuffer); + sprintf (sbuffer, "%sWritten By : %s\n", sbuffer, MOS6510_AUTHOR); + sprintf (sbuffer, "%sVersion : %s\n", sbuffer, MOS6510_VERSION); + sprintf (sbuffer, "%sReleased : %s\n", sbuffer, MOS6510_DATE); + sprintf (sbuffer, "%sEmail : %s\n", sbuffer, MOS6510_EMAIL); +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h new file mode 100644 index 00000000..49d96dd6 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h @@ -0,0 +1,118 @@ +/*************************************************************************** + sid6510c.h - Special MOS6510 to be fully + compatible with sidplay + ------------------- + begin : Thu May 11 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: sid6510c.h,v $ + * Revision 1.16 2002/11/25 21:07:32 s_a_white + * Allow setting of program counter on reset. + * + * Revision 1.15 2002/11/21 19:52:48 s_a_white + * CPU upgraded to be like other components. Theres nolonger a clock call, + * instead events are registered to occur at a specific time. + * + * Revision 1.14 2002/11/19 22:56:25 s_a_white + * Sidplay1 modes modified to make them nolonger require the psid driver. + * + * Revision 1.13 2002/11/01 17:35:27 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.12 2002/03/12 18:47:13 s_a_white + * Made IRQ in sidplay1 compatibility modes behaves like JSR. This fixes tunes + * that have kernel switched out. + * + * Revision 1.11 2002/02/07 18:02:10 s_a_white + * Real C64 compatibility fixes. Debug of BRK works again. Fixed illegal + * instructions to work like sidplay1. + * + * Revision 1.10 2002/02/04 23:53:23 s_a_white + * Improved compatibilty of older sidplay1 modes. Fixed BRK to work like sidplay1 + * only when stack is 0xff in real mode for better compatibility with C64. + * + * Revision 1.9 2001/09/01 11:08:06 s_a_white + * Fixes for sidplay1 environment modes. + * + * Revision 1.8 2001/07/14 13:18:15 s_a_white + * Stack & PC invalid tests now only performed on a BRK. + * + * Revision 1.7 2001/03/24 18:09:17 s_a_white + * On entry to interrupt routine the first instruction in the handler is now always + * executed before pending interrupts are re-checked. + * + * Revision 1.6 2001/03/22 22:40:07 s_a_white + * Replaced tabs characters. + * + * Revision 1.5 2001/03/21 22:26:13 s_a_white + * Fake interrupts now been moved into here from player.cpp. At anytime it's + * now possible to ditch this compatibility class and use the real thing. + * + * Revision 1.4 2001/03/09 22:28:03 s_a_white + * Speed optimisation update. + * + * Revision 1.3 2001/02/13 21:02:25 s_a_white + * Small tidy up and possibly a small performace increase. + * + * Revision 1.2 2000/12/11 19:04:32 s_a_white + * AC99 Update. + * + ***************************************************************************/ + +#ifndef _sid6510c_h_ +#define _sid6510c_h_ + +#include "mos6510c.h" +#include "sid2types.h" + +class SID6510: public MOS6510 +{ +private: + // Sidplay Specials + bool m_sleeping; + sid2_env_t m_mode; + event_clock_t m_delayClk, m_delayCycles; + bool m_framelock; + +public: + SID6510 (EventContext *context); + + // Standard Functions + void reset (void); + void reset (uint_least16_t pc, uint8_t a, uint8_t x, uint8_t y); + void clock (void); + + void environment (sid2_env_t mode) { m_mode = mode; } + void triggerRST (void); + void triggerNMI (void); + void triggerIRQ (void); + void sleep (void); + +protected: + void FetchOpcode (void); + +private: + void (MOS6510::*delayCycle[1]) (void); + + inline void sid_illegal (void); + inline void sid_delay (void); + inline void sid_brk (void); + inline void sid_jmp (void); + inline void sid_rts (void); + inline void sid_cli (void); + inline void sid_rti (void); + inline void sid_irq (void); +}; + +#endif // _sid6510c_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i new file mode 100644 index 00000000..bc573d3b --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i @@ -0,0 +1,409 @@ +/*************************************************************************** + sid6510c.i - Sidplay Specific 6510 emulation + ------------------- + begin : Thu May 11 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: sid6510c.i,v $ + * Revision 1.28 2002/12/03 23:24:52 s_a_white + * Let environment know when cpu sleeps in real c64 mode. + * + * Revision 1.27 2002/12/02 22:19:43 s_a_white + * sid_brk fix to prevent it running some of the real brk cycles in old emulation + * modes. + * + * Revision 1.26 2002/11/25 21:07:34 s_a_white + * Allow setting of program counter on reset. + * + * Revision 1.25 2002/11/21 19:52:48 s_a_white + * CPU upgraded to be like other components. Theres nolonger a clock call, + * instead events are registered to occur at a specific time. + * + * Revision 1.24 2002/11/19 22:56:25 s_a_white + * Sidplay1 modes modified to make them nolonger require the psid driver. + * + * Revision 1.23 2002/11/01 17:35:27 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.22 2002/10/15 23:52:14 s_a_white + * Fix sidplay2 cpu sleep optimisation and NMIs. + * + * Revision 1.21 2002/09/23 22:50:55 s_a_white + * Reverted update 1.20 as was incorrect. Only need to + * change MOS6510 to SID6510 for compliancy. + * + * Revision 1.20 2002/09/23 19:42:14 s_a_white + * Newer compilers don't allow pointers to be taken directly + * from base class member functions. + * + * Revision 1.19 2002/03/12 18:47:13 s_a_white + * Made IRQ in sidplay1 compatibility modes behaves like JSR. This fixes tunes + * that have kernel switched out. + * + * Revision 1.18 2002/02/07 18:02:10 s_a_white + * Real C64 compatibility fixes. Debug of BRK works again. Fixed illegal + * instructions to work like sidplay1. + * + * Revision 1.17 2002/02/06 17:49:12 s_a_white + * Fixed sign comparison warning. + * + * Revision 1.16 2002/02/04 23:53:23 s_a_white + * Improved compatibilty of older sidplay1 modes. Fixed BRK to work like sidplay1 + * only when stack is 0xff in real mode for better compatibility with C64. + * + * Revision 1.15 2002/01/28 19:32:16 s_a_white + * PSID sample improvements. + * + * Revision 1.14 2001/10/02 18:00:37 s_a_white + * Removed un-necessary cli. + * + * Revision 1.13 2001/09/18 07:51:39 jpaana + * Small fix to rti-processing. + * + * Revision 1.12 2001/09/03 22:23:06 s_a_white + * Fixed faked IRQ trigger on BRK for sidplay1 environment modes. + * + * Revision 1.11 2001/09/01 11:08:06 s_a_white + * Fixes for sidplay1 environment modes. + * + * Revision 1.10 2001/08/05 15:46:02 s_a_white + * No longer need to check on which cycle an instruction ends or when to print + * debug information. + * + * Revision 1.9 2001/07/14 13:17:40 s_a_white + * Sidplay1 optimisations moved to here. Stack & PC invalid tests now only + * performed on a BRK. + * + * Revision 1.8 2001/03/24 18:09:17 s_a_white + * On entry to interrupt routine the first instruction in the handler is now always + * executed before pending interrupts are re-checked. + * + * Revision 1.7 2001/03/22 22:40:07 s_a_white + * Replaced tabs characters. + * + * Revision 1.6 2001/03/21 22:26:24 s_a_white + * Fake interrupts now been moved into here from player.cpp. At anytime it's + * now possible to ditch this compatibility class and use the real thing. + * + * Revision 1.5 2001/03/09 22:28:03 s_a_white + * Speed optimisation update. + * + * Revision 1.4 2001/02/13 21:02:16 s_a_white + * Small tidy up and possibly a small performace increase. + * + * Revision 1.3 2000/12/11 19:04:32 s_a_white + * AC99 Update. + * + ***************************************************************************/ + +#include "sid6510c.h" + + +SID6510::SID6510 (EventContext *context) +:MOS6510(context), + m_mode(sid2_envR), + m_framelock(false) +{ // Ok start all the hacks for sidplay. This prevents + // execution of code in roms. For real c64 emulation + // create object from base class! Also stops code + // rom execution when bad code switches roms in over + // itself. + for (uint i = 0; i < OPCODE_MAX; i++) + { + procCycle = instrTable[i].cycle; + if (procCycle == NULL) continue; + + for (uint n = 0; n < instrTable[i].cycles; n++) + { + if (procCycle[n] == &SID6510::illegal_instr) + { // Rev 1.2 (saw) - Changed nasty union to reinterpret_cast + procCycle[n] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_illegal); + } + else if (procCycle[n] == &SID6510::jmp_instr) + { // Stop jumps into rom code + procCycle[n] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_jmp); + } + else if (procCycle[n] == &SID6510::cli_instr) + { // No overlapping IRQs allowed + procCycle[n] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_cli); + } + } + } + + { // Since no real IRQs, all RTIs mapped to RTS + // Required for fix bad tunes in old modes + uint n; + procCycle = instrTable[RTIn].cycle; + for (n = 0; n < instrTable[RTIn].cycles; n++) + { + if (procCycle[n] == &SID6510::PopSR) + { + procCycle[n] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_rti); + break; + } + } + + procCycle = interruptTable[oIRQ].cycle; + for (n = 0; n < interruptTable[oIRQ].cycles; n++) + { + if (procCycle[n] == &SID6510::IRQRequest) + { + procCycle[n] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_irq); + break; + } + } + } + + { // Support of sidplays BRK functionality + procCycle = instrTable[BRKn].cycle; + for (uint n = 0; n < instrTable[BRKn].cycles; n++) + { + if (procCycle[n] == &SID6510::PushHighPC) + { + procCycle[n] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_brk); + break; + } + } + } + + // Used to insert busy delays into the CPU emulation + delayCycle[0] = reinterpret_cast <void (MOS6510::*)()> + (&SID6510::sid_delay); +} + +void SID6510::reset (uint_least16_t pc, uint8_t a, uint8_t x, uint8_t y) +{ // Reset the processor + reset (); + + // Registers not touched by a reset + Register_Accumulator = a; + Register_X = x; + Register_Y = y; + Register_ProgramCounter = pc; +} + +void SID6510::reset () +{ + m_sleeping = false; + // Call inherited reset + MOS6510::reset (); +} + +// Send CPU is about to sleep. Only a reset or +// interrupt will wake up the processor +void SID6510::sleep () +{ // Simulate a delay for JMPw + m_delayClk = eventContext.getTime (); + m_sleeping = true; + procCycle = delayCycle; + cycleCount = 0; + eventContext.cancel (this); + envSleep (); + + // Check for outstanding interrupts + if (interrupts.irqs) + { + interrupts.irqs--; + triggerIRQ (); + } + else if (interrupts.pending) + { + m_sleeping = false; + eventContext.schedule (this, 1); + } +} + +void SID6510::FetchOpcode (void) +{ + if (m_mode == sid2_envR) + { + MOS6510::FetchOpcode (); + return; + } + + // Sid tunes end by wrapping the stack. For compatibilty it + // has to be handled. + m_sleeping |= (endian_16hi8 (Register_StackPointer) != SP_PAGE); + m_sleeping |= (endian_32hi16 (Register_ProgramCounter) != 0); + if (!m_sleeping) + MOS6510::FetchOpcode (); + + if (m_framelock == false) + { + m_framelock = true; + // Simulate sidplay1 frame based execution + while (!m_sleeping) + MOS6510::clock (); + sleep (); + m_framelock = false; + } +} + + +//************************************************************************************** +// For sidplay compatibility implement those instructions which don't behave properly. +//************************************************************************************** +void SID6510::sid_brk (void) +{ + if (m_mode == sid2_envR) + { + MOS6510::PushHighPC (); + return; + } + + sei_instr (); +#if !defined(NO_RTS_UPON_BRK) + sid_rts (); +#endif + FetchOpcode (); +} + +void SID6510::sid_jmp (void) +{ // For sidplay compatibility, inherited from environment + if (m_mode == sid2_envR) + { // If a busy loop then just sleep + if (Cycle_EffectiveAddress != instrStartPC) + jmp_instr (); + else + { + Register_ProgramCounter = Cycle_EffectiveAddress; + sleep (); + } + return; + } + + if (envCheckBankJump (Cycle_EffectiveAddress)) + jmp_instr (); + else + sid_rts (); +} + +// Will do a full rts in 1 cycle, to +// destroy current function and quit +void SID6510::sid_rts (void) +{ + PopLowPC(); + PopHighPC(); + rts_instr(); +} + +void SID6510::sid_cli (void) +{ + if (m_mode == sid2_envR) + cli_instr (); +} + +void SID6510::sid_rti (void) +{ + if (m_mode == sid2_envR) + { + PopSR (); + return; + } + + // Fake RTS + sid_rts (); + FetchOpcode (); +} + +void SID6510::sid_irq (void) +{ + MOS6510::IRQRequest (); + if (m_mode != sid2_envR) + { // RTI behaves like RTI in sidplay1 modes + Register_StackPointer++; + } +} + +// Sidplay Suppresses Illegal Instructions +void SID6510::sid_illegal (void) +{ + if (m_mode == sid2_envR) + { + MOS6510::illegal_instr (); + return; + } +#ifdef MOS6510_DEBUG + DumpState (); +#endif +} + +void SID6510::sid_delay (void) +{ + cycleCount = 0; + if (++m_delayCycles >= 3) + { + (void) interruptPending (); + m_delayCycles = 0; + } +} + + +//************************************************************************************** +// Sidplay compatibility interrupts. Basically wakes CPU if it is m_sleeping +//************************************************************************************** +void SID6510::triggerRST (void) +{ // All modes + MOS6510::triggerRST (); + if (m_sleeping) + { + m_sleeping = false; + eventContext.schedule (this, 1); + } +} + +void SID6510::triggerNMI (void) +{ // Only in Real C64 mode + if (m_mode == sid2_envR) + { + MOS6510::triggerNMI (); + if (m_sleeping) + { + m_delayCycles = eventContext.getTime (m_delayClk) % 3; + m_sleeping = false; + eventContext.schedule (this, 1); + } + } +} + +void SID6510::triggerIRQ (void) +{ + switch (m_mode) + { + default: +#ifdef MOS6510_DEBUG + if (dodump) + { + printf ("****************************************************\n"); + printf (" Fake IRQ Routine\n"); + printf ("****************************************************\n"); + } +#endif + return; + case sid2_envR: + MOS6510::triggerIRQ (); + if (m_sleeping) + { // Simulate busy loop + m_delayCycles = eventContext.getTime (m_delayClk) % 3; + m_sleeping = false; + eventContext.schedule (this, 1); + } + } +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp new file mode 100644 index 00000000..74b09c95 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp @@ -0,0 +1,534 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Thu May 11 06:22:40 BST 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mos6510.cpp,v $ + * Revision 1.8 2001/08/05 15:46:38 s_a_white + * No longer need to check on which cycle to print debug information. + * + * Revision 1.7 2001/07/14 13:04:34 s_a_white + * Accumulator is now unsigned, which improves code readability. + * + * Revision 1.6 2001/03/09 22:27:46 s_a_white + * Speed optimisation update. + * + * Revision 1.5 2001/02/13 23:01:10 s_a_white + * envReadMemDataByte now used for debugging. + * + * Revision 1.4 2000/12/11 19:03:16 s_a_white + * AC99 Update. + * + ***************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include "sidtypes.h" +#include "sidendian.h" +#include "sidenv.h" +#include "conf6510.h" +#include "opcodes.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif + +#ifdef MOS6510_STATE_6510 +# include "state6510.h" +# include "state6510.cpp" +#else + +#include "mos6510.h" + +// Check to see what type of emulation is required +#ifdef MOS6510_CYCLE_BASED +# include "cycle_based/mos6510c.i" + +# ifdef MOS6510_SIDPLAY + // Compile in sidplay code +# include "cycle_based/sid6510c.i" +# endif // MOS6510_SIDPLAY +#else + // Line based emulation code has not been provided +#endif // MOS6510_CYCLE_BASED + +void MOS6510::DumpState (void) +{ + uint8_t opcode, data; + uint_least16_t operand, address; + + printf(" PC I A X Y SP DR PR NV-BDIZC Instruction\n"); + printf("%04x ", instrStartPC); + printf("%u ", interrupts.irqs); + printf("%02x ", Register_Accumulator); + printf("%02x ", Register_X); + printf("%02x ", Register_Y); + printf("01%02x ", endian_16lo8 (Register_StackPointer)); + printf("%02x ", envReadMemDataByte (0)); + printf("%02x ", envReadMemDataByte (1)); + + if (getFlagN()) printf ("1"); else printf ("0"); + if (getFlagV()) printf ("1"); else printf ("0"); + if (Register_Status & (1 << SR_NOTUSED)) printf ("1"); else printf ("0"); + if (Register_Status & (1 << SR_BREAK)) printf ("1"); else printf ("0"); + if (getFlagD()) printf ("1"); else printf ("0"); + if (getFlagI()) printf ("1"); else printf ("0"); + if (getFlagZ()) printf ("1"); else printf ("0"); + if (getFlagC()) printf ("1"); else printf ("0"); + + opcode = instrOpcode; + operand = Instr_Operand; + data = Cycle_Data; + + switch (opcode) + { + case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr: + case BVCr: case BVSr: + address = (uint_least16_t) (Register_ProgramCounter + (int8_t) operand); + break; + + default: + address = Cycle_EffectiveAddress; + break; + } + + printf(" %02x ", opcode); + + switch(opcode) + { + //Accumulator or Implied addressing + case ASLn: case LSRn: case ROLn: case RORn: + printf(" "); + break; + //Zero Page Addressing Mode Handler + case ADCz: case ANDz: case ASLz: case BITz: case CMPz: case CPXz: + case CPYz: case DCPz: case DECz: case EORz: case INCz: case ISBz: + case LAXz: case LDAz: case LDXz: case LDYz: case LSRz: case NOPz_: + case ORAz: case ROLz: case RORz: case SAXz: case SBCz: case SREz: + case STAz: case STXz: case STYz: case SLOz: case RLAz: case RRAz: + //ASOz AXSz DCMz INSz LSEz - Optional Opcode Names + printf("%02x ", (uint8_t) operand); + break; + //Zero Page with X Offset Addressing Mode Handler + case ADCzx: case ANDzx: case ASLzx: case CMPzx: case DCPzx: case DECzx: + case EORzx: case INCzx: case ISBzx: case LDAzx: case LDYzx: case LSRzx: + case NOPzx_: case ORAzx: case RLAzx: case ROLzx: case RORzx: case RRAzx: + case SBCzx: case SLOzx: case SREzx: case STAzx: case STYzx: + //ASOzx DCMzx INSzx LSEzx - Optional Opcode Names + printf("%02x ", (uint8_t) operand); + break; + //Zero Page with Y Offset Addressing Mode Handler + case LDXzy: case STXzy: case SAXzy: case LAXzy: + //AXSzx - Optional Opcode Names + printf("%02x ", endian_16lo8 (operand)); + break; + //Absolute Addressing Mode Handler + case ADCa: case ANDa: case ASLa: case BITa: case CMPa: case CPXa: + case CPYa: case DCPa: case DECa: case EORa: case INCa: case ISBa: + case JMPw: case JSRw: case LAXa: case LDAa: case LDXa: case LDYa: + case LSRa: case NOPa: case ORAa: case ROLa: case RORa: case SAXa: + case SBCa: case SLOa: case SREa: case STAa: case STXa: case STYa: + case RLAa: case RRAa: + //ASOa AXSa DCMa INSa LSEa - Optional Opcode Names + printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand)); + break; + //Absolute With X Offset Addresing Mode Handler + case ADCax: case ANDax: case ASLax: case CMPax: case DCPax: case DECax: + case EORax: case INCax: case ISBax: case LDAax: case LDYax: case LSRax: + case NOPax_: case ORAax: case RLAax: case ROLax: case RORax: case RRAax: + case SBCax: case SHYax: case SLOax: case SREax: case STAax: + //ASOax DCMax INSax LSEax SAYax - Optional Opcode Names + printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand)); + break; + //Absolute With Y Offset Addresing Mode Handler + case ADCay: case ANDay: case CMPay: case DCPay: case EORay: case ISBay: + case LASay: case LAXay: case LDAay: case LDXay: case ORAay: case RLAay: + case RRAay: case SBCay: case SHAay: case SHSay: case SHXay: case SLOay: + case SREay: case STAay: + //ASOay AXAay DCMay INSax LSEay TASay XASay - Optional Opcode Names + printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand)); + break; + //Immediate and Relative Addressing Mode Handler + case ADCb: case ANDb: case ANCb_: case ANEb: case ASRb: case ARRb: + + case CMPb: case CPXb: case CPYb: case EORb: case LDAb: case LDXb: + case LDYb: case LXAb: case NOPb_: case ORAb: case SBCb_: case SBXb: + //OALb ALRb XAAb - Optional Opcode Names + printf("%02x ", endian_16lo8 (operand)); + break; + case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr: + case BVCr: case BVSr: + printf("%02x ", endian_16lo8 (operand)); + break; + //Indirect Addressing Mode Handler + case JMPi: + printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand)); + break; + //Indexed with X Preinc Addressing Mode Handler + case ADCix: case ANDix: case CMPix: case DCPix: case EORix: case ISBix: + case LAXix: case LDAix: case ORAix: case SAXix: case SBCix: case SLOix: + case SREix: case STAix: case RLAix: case RRAix: + //ASOix AXSix DCMix INSix LSEix - Optional Opcode Names + printf("%02x ", endian_16lo8 (operand)); + break; + //Indexed with Y Postinc Addressing Mode Handler + case ADCiy: case ANDiy: case CMPiy: case DCPiy: case EORiy: case ISBiy: + case LAXiy: case LDAiy: case ORAiy: case RLAiy: case RRAiy: case SBCiy: + case SHAiy: case SLOiy: case SREiy: case STAiy: + //AXAiy ASOiy LSEiy DCMiy INSiy - Optional Opcode Names + printf("%02x ", endian_16lo8 (operand)); + break; + default: + printf(" "); + break; + } + + switch(opcode) + { + case ADCb: case ADCz: case ADCzx: case ADCa: case ADCax: case ADCay: + case ADCix: case ADCiy: + printf(" ADC"); break; + case ANCb_: + printf("*ANC"); break; + case ANDb: case ANDz: case ANDzx: case ANDa: case ANDax: case ANDay: + case ANDix: case ANDiy: + printf(" AND"); break; + case ANEb: //Also known as XAA + printf("*ANE"); break; + case ARRb: + printf("*ARR"); break; + case ASLn: case ASLz: case ASLzx: case ASLa: case ASLax: + printf(" ASL"); break; + case ASRb: //Also known as ALR + printf("*ASR"); break; + case BCCr: + printf(" BCC"); break; + case BCSr: + printf(" BCS"); break; + case BEQr: + printf(" BEQ"); break; + case BITz: case BITa: + printf(" BIT"); break; + case BMIr: + printf(" BMI"); break; + case BNEr: + printf(" BNE"); break; + case BPLr: + printf(" BPL"); break; + case BRKn: + printf(" BRK"); break; + case BVCr: + printf(" BVC"); break; + case BVSr: + printf(" BVS"); break; + case CLCn: + printf(" CLC"); break; + case CLDn: + printf(" CLD"); break; + case CLIn: + printf(" CLI"); break; + case CLVn: + printf(" CLV"); break; + case CMPb: case CMPz: case CMPzx: case CMPa: case CMPax: case CMPay: + case CMPix: case CMPiy: + printf(" CMP"); break; + case CPXb: case CPXz: case CPXa: + printf(" CPX"); break; + case CPYb: case CPYz: case CPYa: + printf(" CPY"); break; + case DCPz: case DCPzx: case DCPa: case DCPax: case DCPay: case DCPix: + case DCPiy: //Also known as DCM + printf("*DCP"); break; + case DECz: case DECzx: case DECa: case DECax: + printf(" DEC"); break; + case DEXn: + printf(" DEX"); break; + case DEYn: + printf(" DEY"); break; + case EORb: case EORz: case EORzx: case EORa: case EORax: case EORay: + case EORix: case EORiy: + printf(" EOR"); break; + case INCz: case INCzx: case INCa: case INCax: + printf(" INC"); break; + case INXn: + printf(" INX"); break; + case INYn: + printf(" INY"); break; + case ISBz: case ISBzx: case ISBa: case ISBax: case ISBay: case ISBix: + case ISBiy: //Also known as INS + printf("*ISB"); break; + case JMPw: case JMPi: + printf(" JMP"); break; + case JSRw: + printf(" JSR"); break; + case LASay: + printf("*LAS"); break; + case LAXz: case LAXzy: case LAXa: case LAXay: case LAXix: case LAXiy: + printf("*LAX"); break; + case LDAb: case LDAz: case LDAzx: case LDAa: case LDAax: case LDAay: + case LDAix: case LDAiy: + printf(" LDA"); break; + case LDXb: case LDXz: case LDXzy: case LDXa: case LDXay: + printf(" LDX"); break; + case LDYb: case LDYz: case LDYzx: case LDYa: case LDYax: + printf(" LDY"); break; + case LSRz: case LSRzx: case LSRa: case LSRax: case LSRn: + printf(" LSR"); break; + case NOPn_: case NOPb_: case NOPz_: case NOPzx_: case NOPa: case NOPax_: + if(opcode != NOPn) printf("*"); + else printf(" "); + printf("NOP"); break; + case LXAb: //Also known as OAL + printf("*LXA"); break; + case ORAb: case ORAz: case ORAzx: case ORAa: case ORAax: case ORAay: + case ORAix: case ORAiy: + printf(" ORA"); break; + case PHAn: + printf(" PHA"); break; + case PHPn: + printf(" PHP"); break; + case PLAn: + printf(" PLA"); break; + case PLPn: + printf(" PLP"); break; + case RLAz: case RLAzx: case RLAix: case RLAa: case RLAax: case RLAay: + case RLAiy: + printf("*RLA"); break; + case ROLz: case ROLzx: case ROLa: case ROLax: case ROLn: + printf(" ROL"); break; + case RORz: case RORzx: case RORa: case RORax: case RORn: + printf(" ROR"); break; + case RRAa: case RRAax: case RRAay: case RRAz: case RRAzx: case RRAix: + case RRAiy: + printf("*RRA"); break; + case RTIn: + printf(" RTI"); break; + case RTSn: + printf(" RTS"); break; + case SAXz: case SAXzy: case SAXa: case SAXix: //Also known as AXS + printf("*SAX"); break; + case SBCb_: + if(opcode != SBCb) printf("*"); + else printf(" "); + printf ("SBC"); break; + case SBCz: case SBCzx: case SBCa: case SBCax: case SBCay: case SBCix: + case SBCiy: + printf(" SBC"); break; + case SBXb: + printf("*SBX"); break; + case SECn: + printf(" SEC"); break; + case SEDn: + printf(" SED"); break; + case SEIn: + printf(" SEI"); break; + case SHAay: case SHAiy: //Also known as AXA + printf("*SHA"); break; + case SHSay: //Also known as TAS + printf("*SHS"); break; + case SHXay: //Also known as XAS + printf("*SHX"); break; + case SHYax: //Also known as SAY + printf("*SHY"); break; + case SLOz: case SLOzx: case SLOa: case SLOax: case SLOay: case SLOix: + case SLOiy: //Also known as ASO + printf("*SLO"); break; + case SREz: case SREzx: case SREa: case SREax: case SREay: case SREix: + case SREiy: //Also known as LSE + printf("*SRE"); break; + case STAz: case STAzx: case STAa: case STAax: case STAay: case STAix: + case STAiy: + printf(" STA"); break; + case STXz: case STXzy: case STXa: + printf(" STX"); break; + case STYz: case STYzx: case STYa: + printf(" STY"); break; + case TAXn: + printf(" TAX"); break; + case TAYn: + printf(" TAY"); break; + case TSXn: + printf(" TSX"); break; + case TXAn: + printf(" TXA"); break; + case TXSn: + printf(" TXS"); break; + case TYAn: + printf(" TYA"); break; + default: + printf("*HLT"); break; + } + + switch(opcode) + { + //Accumulator or Implied addressing + case ASLn: case LSRn: case ROLn: case RORn: + printf("n A"); + break; + + //Zero Page Addressing Mode Handler + case ADCz: case ANDz: case ASLz: case BITz: case CMPz: case CPXz: + case CPYz: case DCPz: case DECz: case EORz: case INCz: case ISBz: + case LAXz: case LDAz: case LDXz: case LDYz: case LSRz: case ORAz: + + case ROLz: case RORz: case SBCz: case SREz: case SLOz: case RLAz: + case RRAz: + //ASOz AXSz DCMz INSz LSEz - Optional Opcode Names + printf("z %02x {%02x}", (uint8_t) operand, data); + break; + case SAXz: case STAz: case STXz: case STYz: +#ifdef MOS6510_DEBUG + case NOPz_: +#endif + printf("z %02x", endian_16lo8 (operand)); + break; + + //Zero Page with X Offset Addressing Mode Handler + case ADCzx: case ANDzx: case ASLzx: case CMPzx: case DCPzx: case DECzx: + case EORzx: case INCzx: case ISBzx: case LDAzx: case LDYzx: case LSRzx: + case ORAzx: case RLAzx: case ROLzx: case RORzx: case RRAzx: case SBCzx: + case SLOzx: case SREzx: + //ASOzx DCMzx INSzx LSEzx - Optional Opcode Names + printf("zx %02x,X", endian_16lo8 (operand)); + printf(" [%04x]{%02x}", address, data); + break; + case STAzx: case STYzx: +#ifdef MOS6510_DEBUG + case NOPzx_: +#endif + printf("zx %02x,X", endian_16lo8 (operand)); + printf(" [%04x]", address); + break; + + //Zero Page with Y Offset Addressing Mode Handler + case LAXzy: case LDXzy: + //AXSzx - Optional Opcode Names + printf("zy %02x,Y", endian_16lo8 (operand)); + printf(" [%04x]{%02x}", address, data); + break; + case STXzy: case SAXzy: + printf("zy %02x,Y", endian_16lo8 (operand)); + printf(" [%04x]", address); + break; + + //Absolute Addressing Mode Handler + case ADCa: case ANDa: case ASLa: case BITa: case CMPa: case CPXa: + case CPYa: case DCPa: case DECa: case EORa: case INCa: case ISBa: + case LAXa: case LDAa: case LDXa: case LDYa: case LSRa: case ORAa: + case ROLa: case RORa: case SBCa: case SLOa: case SREa: case RLAa: + case RRAa: + //ASOa AXSa DCMa INSa LSEa - Optional Opcode Names + printf("a %04x {%02x}", operand, data); + break; + case SAXa: case STAa: case STXa: case STYa: +#ifdef MOS6510_DEBUG + case NOPa: +#endif + printf("a %04x", operand); + break; + case JMPw: case JSRw: + printf("w %04x", operand); + break; + + //Absolute With X Offset Addresing Mode Handler + case ADCax: case ANDax: case ASLax: case CMPax: case DCPax: case DECax: + case EORax: case INCax: case ISBax: case LDAax: case LDYax: case LSRax: + case ORAax: case RLAax: case ROLax: case RORax: case RRAax: case SBCax: + case SLOax: case SREax: + //ASOax DCMax INSax LSEax SAYax - Optional Opcode Names + printf("ax %04x,X", operand); + printf(" [%04x]{%02x}", address, data); + break; + case SHYax: case STAax: +#ifdef MOS6510_DEBUG + case NOPax_: +#endif + printf("ax %04x,X", operand); + printf(" [%04x]", address); + break; + + //Absolute With Y Offset Addresing Mode Handler + case ADCay: case ANDay: case CMPay: case DCPay: case EORay: case ISBay: + case LASay: case LAXay: case LDAay: case LDXay: case ORAay: case RLAay: + case RRAay: case SBCay: case SHSay: case SLOay: case SREay: + //ASOay AXAay DCMay INSax LSEay TASay XASay - Optional Opcode Names + printf("ay %04x,Y", operand); + printf(" [%04x]{%02x}", address, data); + break; + case SHAay: case SHXay: case STAay: + printf("ay %04x,Y", operand); + printf(" [%04x]", address); + break; + + //Immediate Addressing Mode Handler + case ADCb: case ANDb: case ANCb_: case ANEb: case ASRb: case ARRb: + case CMPb: case CPXb: case CPYb: case EORb: case LDAb: case LDXb: + case LDYb: case LXAb: case ORAb: case SBCb_: case SBXb: + //OALb ALRb XAAb - Optional Opcode Names +#ifdef MOS6510_DEBUG + case NOPb_: +#endif + printf("b #%02x", endian_16lo8 (operand)); + break; + + //Relative Addressing Mode Handler + case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr: + case BVCr: case BVSr: + printf("r #%02x", endian_16lo8 (operand)); + printf(" [%04x]", address); + break; + + //Indirect Addressing Mode Handler + case JMPi: + printf("i (%04x)", operand); + printf(" [%04x]", address); + break; + + //Indexed with X Preinc Addressing Mode Handler + case ADCix: case ANDix: case CMPix: case DCPix: case EORix: case ISBix: + case LAXix: case LDAix: case ORAix: case SBCix: case SLOix: case SREix: + case RLAix: case RRAix: + //ASOix AXSix DCMix INSix LSEix - Optional Opcode Names + printf("ix (%02x,X)", endian_16lo8 (operand)); + printf(" [%04x]{%02x}", address, data); + break; + case SAXix: case STAix: + printf("ix (%02x,X)", endian_16lo8 (operand)); + printf(" [%04x]", address); + break; + + //Indexed with Y Postinc Addressing Mode Handler + case ADCiy: case ANDiy: case CMPiy: case DCPiy: case EORiy: case ISBiy: + case LAXiy: case LDAiy: case ORAiy: case RLAiy: case RRAiy: case SBCiy: + case SLOiy: case SREiy: + //AXAiy ASOiy LSEiy DCMiy INSiy - Optional Opcode Names + printf("iy (%02x),Y", endian_16lo8 (operand)); + printf(" [%04x]{%02x}", address, data); + break; + case SHAiy: case STAiy: + printf("iy (%02x),Y", endian_16lo8 (operand)); + printf(" [%04x]", address); + break; + + default: + break; + } + + printf ("\n\n"); + fflush (stdout); +} + +#endif // MOS6510_STATE_6510 + diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h new file mode 100644 index 00000000..e7ad1a3f --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h @@ -0,0 +1,75 @@ +/*************************************************************************** + mos6510.h - description + ------------------- + begin : Thu May 11 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mos6510.h,v $ + * Revision 1.5 2001/07/14 16:47:21 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.4 2001/07/14 13:04:34 s_a_white + * Accumulator is now unsigned, which improves code readability. + * + * Revision 1.3 2000/12/11 19:03:16 s_a_white + * AC99 Update. + * + ***************************************************************************/ + +#ifndef _mos6510_h_ +#define _mos6510_h_ + +#include "config.h" +#include "component.h" +#include "sidenv.h" +#include "event.h" + +#undef MOS6510_VERSION +#undef MOS6510_DATE +#undef MOS6510_AUTHOR +#undef MOS6510_EMAIL +#define MOS6510_VERSION "1.08" +#define MOS6510_DATE "23th May 2000" +#define MOS6510_AUTHOR "Simon White" +#define MOS6510_EMAIL "s_a_white@email.com" +#define MOS6510_INTERRUPT_DELAY 2 + +#include "opcodes.h" +#include "conf6510.h" + +// Status Register flag definistions +#define SR_NEGATIVE 7 +#define SR_OVERFLOW 6 +#define SR_NOTUSED 5 +#define SR_BREAK 4 +#define SR_DECIMAL 3 +#define SR_INTERRUPT 2 +#define SR_ZERO 1 +#define SR_CARRY 0 + +#define SP_PAGE 0x01 + +// Check to see what type of emulation is required +#ifdef MOS6510_CYCLE_BASED +# ifdef MOS6510_SIDPLAY +# include "cycle_based/sid6510c.h" +# else +# include "cycle_based/mos6510c.h" +# endif // MOS6510_SIDPLAY +#else + // Line based emulation code has not been provided +#endif // MOS6510_CYCLE_BASED + +#endif // _mos6510_h_ + diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h new file mode 100644 index 00000000..e4d44acd --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h @@ -0,0 +1,331 @@ +/*************************************************************************** + opcodes.h - description + ------------------- + begin : Thu May 11 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _opcodes_h_ +#define _opcodes_h_ + +#define OPCODE_MAX 0x100 + +/* HLT + case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: + case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2: + case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: + case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2: +*/ + +#define BRKn 0x00 +#define JSRw 0x20 +#define RTIn 0x40 +#define RTSn 0x60 +#define NOPb 0x80 +#define NOPb_ NOPb: case 0x82: case 0xC2: case 0xE2: case 0x89 +#define LDYb 0xA0 +#define CPYb 0xC0 +#define CPXb 0xE0 + +#define ORAix 0x01 +#define ANDix 0x21 +#define EORix 0x41 +#define ADCix 0x61 +#define STAix 0x81 +#define LDAix 0xA1 +#define CMPix 0xC1 +#define SBCix 0xE1 + +#define LDXb 0xA2 + +#define SLOix 0x03 +#define RLAix 0x23 +#define SREix 0x43 +#define RRAix 0x63 +#define SAXix 0x83 +#define LAXix 0xA3 +#define DCPix 0xC3 +#define ISBix 0xE3 + +#define NOPz 0x04 +#define NOPz_ NOPz: case 0x44: case 0x64 +#define BITz 0x24 +#define STYz 0x84 +#define LDYz 0xA4 +#define CPYz 0xC4 +#define CPXz 0xE4 + +#define ORAz 0x05 +#define ANDz 0x25 +#define EORz 0x45 +#define ADCz 0x65 +#define STAz 0x85 +#define LDAz 0xA5 +#define CMPz 0xC5 +#define SBCz 0xE5 + +#define ASLz 0x06 +#define ROLz 0x26 +#define LSRz 0x46 +#define RORz 0x66 +#define STXz 0x86 +#define LDXz 0xA6 +#define DECz 0xC6 +#define INCz 0xE6 + +#define SLOz 0x07 +#define RLAz 0x27 +#define SREz 0x47 +#define RRAz 0x67 +#define SAXz 0x87 +#define LAXz 0xA7 +#define DCPz 0xC7 +#define ISBz 0xE7 + +#define PHPn 0x08 +#define PLPn 0x28 +#define PHAn 0x48 +#define PLAn 0x68 +#define DEYn 0x88 +#define TAYn 0xA8 +#define INYn 0xC8 +#define INXn 0xE8 + +#define ORAb 0x09 +#define ANDb 0x29 +#define EORb 0x49 +#define ADCb 0x69 +#define LDAb 0xA9 +#define CMPb 0xC9 +#define SBCb 0xE9 +#define SBCb_ SBCb: case 0XEB + +#define ASLn 0x0A +#define ROLn 0x2A +#define LSRn 0x4A +#define RORn 0x6A +#define TXAn 0x8A +#define TAXn 0xAA +#define DEXn 0xCA +#define NOPn 0xEA +#define NOPn_ NOPn: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA + +#define ANCb 0x0B +#define ANCb_ ANCb: case 0x2B +#define ASRb 0x4B +#define ARRb 0x6B +#define ANEb 0x8B +#define XAAb 0x8B +#define LXAb 0xAB +#define SBXb 0xCB + +#define NOPa 0x0C +#define BITa 0x2C +#define JMPw 0x4C +#define JMPi 0x6C +#define STYa 0x8C +#define LDYa 0xAC +#define CPYa 0xCC +#define CPXa 0xEC + +#define ORAa 0x0D +#define ANDa 0x2D +#define EORa 0x4D +#define ADCa 0x6D +#define STAa 0x8D +#define LDAa 0xAD +#define CMPa 0xCD +#define SBCa 0xED + +#define ASLa 0x0E +#define ROLa 0x2E +#define LSRa 0x4E +#define RORa 0x6E +#define STXa 0x8E +#define LDXa 0xAE +#define DECa 0xCE +#define INCa 0xEE + +#define SLOa 0x0F +#define RLAa 0x2F +#define SREa 0x4F +#define RRAa 0x6F +#define SAXa 0x8F +#define LAXa 0xAF +#define DCPa 0xCF +#define ISBa 0xEF + +#define BPLr 0x10 +#define BMIr 0x30 +#define BVCr 0x50 +#define BVSr 0x70 +#define BCCr 0x90 +#define BCSr 0xB0 +#define BNEr 0xD0 +#define BEQr 0xF0 + +#define ORAiy 0x11 +#define ANDiy 0x31 +#define EORiy 0x51 +#define ADCiy 0x71 +#define STAiy 0x91 +#define LDAiy 0xB1 +#define CMPiy 0xD1 +#define SBCiy 0xF1 + +#define SLOiy 0x13 +#define RLAiy 0x33 +#define SREiy 0x53 +#define RRAiy 0x73 +#define SHAiy 0x93 +#define LAXiy 0xB3 +#define DCPiy 0xD3 +#define ISBiy 0xF3 + +#define NOPzx 0x14 +#define NOPzx_ NOPzx: case 0x34: case 0x54: case 0x74: case 0xD4: case 0xF4 +#define STYzx 0x94 +#define LDYzx 0xB4 + +#define ORAzx 0x15 +#define ANDzx 0x35 +#define EORzx 0x55 +#define ADCzx 0x75 +#define STAzx 0x95 +#define LDAzx 0xB5 +#define CMPzx 0xD5 +#define SBCzx 0xF5 + +#define ASLzx 0x16 +#define ROLzx 0x36 +#define LSRzx 0x56 +#define RORzx 0x76 +#define STXzy 0x96 +#define LDXzy 0xB6 +#define DECzx 0xD6 +#define INCzx 0xF6 + +#define SLOzx 0x17 +#define RLAzx 0x37 +#define SREzx 0x57 +#define RRAzx 0x77 +#define SAXzy 0x97 +#define LAXzy 0xB7 +#define DCPzx 0xD7 +#define ISBzx 0xF7 + +#define CLCn 0x18 +#define SECn 0x38 +#define CLIn 0x58 +#define SEIn 0x78 +#define TYAn 0x98 +#define CLVn 0xB8 +#define CLDn 0xD8 +#define SEDn 0xF8 + +#define ORAay 0x19 +#define ANDay 0x39 +#define EORay 0x59 +#define ADCay 0x79 +#define STAay 0x99 +#define LDAay 0xB9 +#define CMPay 0xD9 +#define SBCay 0xF9 + +#define TXSn 0x9A +#define TSXn 0xBA + +#define SLOay 0x1B +#define RLAay 0x3B +#define SREay 0x5B +#define RRAay 0x7B +#define SHSay 0x9B +#define TASay 0x9B +#define LASay 0xBB +#define DCPay 0xDB +#define ISBay 0xFB + +#define NOPax 0x1C +#define NOPax_ NOPax: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC +#define SHYax 0x9C +#define LDYax 0xBC + +#define ORAax 0x1D +#define ANDax 0x3D +#define EORax 0x5D +#define ADCax 0x7D +#define STAax 0x9D +#define LDAax 0xBD +#define CMPax 0xDD +#define SBCax 0xFD + +#define ASLax 0x1E +#define ROLax 0x3E +#define LSRax 0x5E +#define RORax 0x7E +#define SHXay 0x9E +#define LDXay 0xBE +#define DECax 0xDE +#define INCax 0xFE + +#define SLOax 0x1F +#define RLAax 0x3F +#define SREax 0x5F +#define RRAax 0x7F +#define SHAay 0x9F +#define LAXay 0xBF +#define DCPax 0xDF +#define ISBax 0xFF + +// Instruction Aliases +#define ASOix SLOix +#define LSEix SREix +#define AXSix SAXix +#define DCMix DCPix +#define INSix ISBix +#define ASOz SLOz +#define LSEz SREz +#define AXSz SAXz +#define DCMz DCPz +#define INSz ISBz +#define ALRb ASRb +#define OALb LXAb +#define ASOa SLOa +#define LSEa SREa +#define AXSa SAXa +#define DCMa DCPa +#define INSa ISBa +#define ASOiy SLOiy +#define LSEiy SREiy +#define AXAiy SHAiy +#define DCMiy DCPiy +#define INSiy ISBiy +#define ASOzx SLOzx +#define LSEzx SREzx +#define AXSzy SAXzy +#define DCMzx DCPzx +#define INSzx ISBzx +#define ASOay SLOay +#define LSEay SREay +#define DCMay DCPay +#define INSay ISBay +#define SAYax SHYax +#define XASay SHXay +#define ASOax SLOax +#define LSEax SREax +#define AXAay SHAay +#define DCMax DCPax +#define INSax ISBax +#define SKBn NOPb +#define SKWn NOPa + +#endif // _opcodes_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6526/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/Makefile.am new file mode 100644 index 00000000..e5029df5 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/Makefile.am @@ -0,0 +1,7 @@ + +noinst_LTLIBRARIES = libmos6526.la + +libmos6526_la_SOURCES = mos6526.cpp mos6526.h + +# Remove bad default includes +DEFAULT_INCLUDES= diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6526/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/Makefile.in new file mode 100644 index 00000000..8f1667ec --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/Makefile.in @@ -0,0 +1,424 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +noinst_LTLIBRARIES = libmos6526.la + +libmos6526_la_SOURCES = mos6526.cpp mos6526.h + +# Remove bad default includes +DEFAULT_INCLUDES = +subdir = src/mos6526 +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libmos6526_la_LDFLAGS = +libmos6526_la_LIBADD = +am_libmos6526_la_OBJECTS = mos6526.lo +libmos6526_la_OBJECTS = $(am_libmos6526_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/mos6526.Plo +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libmos6526_la_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libmos6526_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/mos6526/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libmos6526.la: $(libmos6526_la_OBJECTS) $(libmos6526_la_DEPENDENCIES) + $(CXXLINK) $(libmos6526_la_LDFLAGS) $(libmos6526_la_OBJECTS) $(libmos6526_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mos6526.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 $(LTLIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +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: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man 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 uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6526/mos6526.cpp b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/mos6526.cpp new file mode 100644 index 00000000..32b6f1f2 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/mos6526.cpp @@ -0,0 +1,322 @@ +/*************************************************************************** + mos6526.cpp - CIA Timer + ------------------- + begin : Wed Jun 7 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mos6526.cpp,v $ + * Revision 1.10 2002/12/16 22:12:24 s_a_white + * Simulate serial input from data port A to prevent kernel lockups. + * + * Revision 1.9 2002/11/20 22:50:27 s_a_white + * Reload count when timers are stopped + * + * Revision 1.8 2002/10/02 19:49:21 s_a_white + * Revert previous change as was incorrect. + * + * Revision 1.7 2002/09/11 22:30:47 s_a_white + * Counter interval writes now go to a new register call prescaler. This is + * copied to the timer latch/counter as appropriate. + * + * Revision 1.6 2002/09/09 22:49:06 s_a_white + * Proper idr clear if interrupt was only internally pending. + * + * Revision 1.5 2002/07/20 08:34:52 s_a_white + * Remove unnecessary and pointless conts. + * + * Revision 1.4 2002/03/03 22:04:08 s_a_white + * Tidy. + * + * Revision 1.3 2001/07/14 13:03:33 s_a_white + * Now uses new component classes and event generation. + * + * Revision 1.2 2001/03/23 23:21:38 s_a_white + * Removed redundant reset funtion. Timer b now gets initialised properly. + * Switch case now allows write/read from timer b. + * + * Revision 1.1 2001/03/21 22:41:45 s_a_white + * Non faked CIA emulation with NMI support. Removal of Hacked VIC support + * off CIA timer. + * + * Revision 1.8 2001/03/09 23:44:30 s_a_white + * Integrated more 6526 features. All timer modes and interrupts correctly + * supported. + * + * Revision 1.7 2001/02/21 22:07:10 s_a_white + * Prevent re-triggering of interrupt if it's already active. + * + * Revision 1.6 2001/02/13 21:00:01 s_a_white + * Support for real interrupts. + * + * Revision 1.4 2000/12/11 18:52:12 s_a_white + * Conversion to AC99 + * + ***************************************************************************/ + +#include "sidendian.h" +#include "mos6526.h" + +enum +{ + INTERRUPT_TA = 1 << 0, + INTERRUPT_TB = 1 << 1, + INTERRUPT_ALARM = 1 << 2, + INTERRUPT_SP = 1 << 3, + INTERRUPT_FLAG = 1 << 4, + INTERRUPT_REQUEST = 1 << 7 +}; + +const char *MOS6526::credit = +{ // Optional information + "*MOS6526 (CIA) Emulation:\0" + "\tCopyright (C) 2001 Simon White <sidplay2@email.com>\0" +}; + + +MOS6526::MOS6526 (EventContext *context) +:idr(0), + event_context(*context), + event_ta(this), + event_tb(this) +{ + reset (); +} + +void MOS6526::reset (void) +{ + ta = ta_latch = 0xffff; + tb = tb_latch = 0xffff; + cra = crb = 0; + // Clear off any IRQs + trigger (0); + cnt_high = true; + icr = idr = 0; + m_accessClk = 0; + dpa = 0xf0; +} + +uint8_t MOS6526::read (uint_least8_t addr) +{ + event_clock_t cycles; + if (addr > 0x0f) return 0; + + cycles = event_context.getTime (m_accessClk); + m_accessClk += cycles; + + // Sync up timers + if ((cra & 0x21) == 0x01) + ta -= cycles; + if ((crb & 0x61) == 0x01) + tb -= cycles; + + switch (addr) + { + case 0x0: // Simulate a serial port + dpa = ((dpa << 1) | (dpa >> 7)) & 0xff; + if (dpa & 0x80) + return 0xc0; + return 0; + case 0x4: return endian_16lo8 (ta); + case 0x5: return endian_16hi8 (ta); + case 0x6: return endian_16lo8 (tb); + case 0x7: return endian_16hi8 (tb); + + case 0xd: + { // Clear IRQs, and return interrupt + // data register + uint8_t ret = idr; + trigger (0); + return ret; + } + + case 0x0e: return cra; + case 0x0f: return crb; + default: return regs[addr]; + } +} + +void MOS6526::write (uint_least8_t addr, uint8_t data) +{ + event_clock_t cycles; + if (addr > 0x0f) return; + + regs[addr] = data; + cycles = event_context.getTime (m_accessClk); + m_accessClk += cycles; + + // Sync up timers + if ((cra & 0x21) == 0x01) + ta -= cycles; + if ((crb & 0x61) == 0x01) + tb -= cycles; + + switch (addr) + { + case 0x4: endian_16lo8 (ta_latch, data); break; + case 0x5: + endian_16hi8 (ta_latch, data); + if (!(cra & 0x01)) // Reload timer if stopped + ta = ta_latch; + break; + + case 0x6: endian_16lo8 (tb_latch, data); break; + case 0x7: + endian_16hi8 (tb_latch, data); + if (!(crb & 0x01)) // Reload timer if stopped + tb = tb_latch; + break; + + case 0xd: + if (data & 0x80) + icr |= data & 0x1f; + else + icr &= ~data; + trigger (idr); + break; + + case 0x0e: + // Check for forced load + cra = data; + if (data & 0x10) + { + cra &= (~0x10); + ta = ta_latch; + } + + if ((data & 0x21) == 0x01) + { // Active + event_context.schedule (&event_ta, (event_clock_t) ta + 1); + } else + { // Inactive + ta = ta_latch; + event_context.cancel (&event_ta); + } + break; + + case 0x0f: + // Check for forced load + crb = data; + if (data & 0x10) + { + crb &= (~0x10); + tb = tb_latch; + } + + if ((data & 0x61) == 0x01) + { // Active + event_context.schedule (&event_tb, (event_clock_t) tb + 1); + } else + { // Inactive + tb = tb_latch; + event_context.cancel (&event_tb); + } + break; + + default: + break; + } +} + +void MOS6526::trigger (int irq) +{ + if (!irq) + { // Clear any requested IRQs + if (idr & INTERRUPT_REQUEST) + interrupt (false); + idr = 0; + return; + } + + idr |= irq; + if (icr & idr) + { + if (!(idr & INTERRUPT_REQUEST)) + { + idr |= INTERRUPT_REQUEST; + interrupt (true); + } + } +} + +void MOS6526::ta_event (void) +{ // Timer Modes + event_clock_t cycles; + uint8_t mode = cra & 0x21; + + if (mode == 0x21) + { + if (ta--) + return; + } + + cycles = event_context.getTime (m_accessClk); + m_accessClk += cycles; + + ta = ta_latch; + if (cra & 0x08) + { // one shot, stop timer A + cra &= (~0x01); + } else if (mode == 0x01) + { // Reset event + event_context.schedule (&event_ta, (event_clock_t) ta + 1); + } + trigger (INTERRUPT_TA); + + switch (crb & 0x61) + { + case 0x01: tb -= cycles; break; + case 0x41: + case 0x61: + tb_event (); + break; + } +} + +void MOS6526::tb_event (void) +{ // Timer Modes + uint8_t mode = crb & 0x61; + switch (mode) + { + case 0x01: + break; + + case 0x21: + case 0x41: + if (tb--) + return; + break; + + case 0x61: + if (cnt_high) + { + if (tb--) + return; + } + break; + + default: + return; + } + + m_accessClk = event_context.getTime (); + tb = tb_latch; + if (crb & 0x08) + { // one shot, stop timer A + crb &= (~0x01); + } else if (mode == 0x01) + { // Reset event + event_context.schedule (&event_tb, (event_clock_t) tb + 1); + } + trigger (INTERRUPT_TB); +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6526/mos6526.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/mos6526.h new file mode 100644 index 00000000..5fa11bcf --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6526/mos6526.h @@ -0,0 +1,156 @@ +/*************************************************************************** + mos6526.h - CIA timer to produce interrupts + ------------------- + begin : Wed Jun 7 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: mos6526.h,v $ + * Revision 1.11 2002/12/16 22:12:27 s_a_white + * Simulate serial input from data port A to prevent kernel lockups. + * + * Revision 1.10 2002/10/02 19:49:22 s_a_white + * Revert previous change as was incorrect. + * + * Revision 1.9 2002/09/11 22:30:47 s_a_white + * Counter interval writes now go to a new register call prescaler. This is + * copied to the timer latch/counter as appropriate. + * + * Revision 1.8 2002/07/20 08:34:52 s_a_white + * Remove unnecessary and pointless conts. + * + * Revision 1.7 2001/10/18 22:35:45 s_a_white + * GCC3 fixes. + * + * Revision 1.6 2001/07/14 16:46:59 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.5 2001/07/14 13:03:33 s_a_white + * Now uses new component classes and event generation. + * + * Revision 1.4 2001/03/25 19:50:16 s_a_white + * Timer B counts timer Aer a underflows correc + * + * Revision 1.3 2001/03/23 23:20:29 s_a_white + * Removed redundant reset prototype. + * + * Revision 1.2 2001/03/22 22:41:45 s_a_white + * Replaced tab characters + * + * Revision 1.1 2001/03/21 22:41:45 s_a_white + * Non faked CIA emulation with NMI support. Removal of Hacked VIC support + * off CIA timer. + * + * Revision 1.7 2001/03/09 23:44:30 s_a_white + * Integrated more 6526 features. All timer modes and interrupts correctly + * supported. + * + * Revision 1.6 2001/02/21 22:07:10 s_a_white + * Prevent re-triggering of interrupt if it's already active. + * + * Revision 1.5 2001/02/13 21:00:01 s_a_white + * Support for real interrupts. + * + * Revision 1.3 2000/12/11 18:52:12 s_a_white + * Conversion to AC99 + * + ***************************************************************************/ + +#ifndef _mos6526_h_ +#define _mos6526_h_ + +#include "component.h" +#include "event.h" + +class MOS6526: public component +{ +private: + static const char *credit; + +protected: + uint8_t regs[0x10]; + bool cnt_high; + + // Timer A + uint8_t cra, cra_latch, dpa; + uint_least16_t ta, ta_latch; + int ta_state; + + // Timer B + uint8_t crb; + uint_least16_t tb, tb_latch; + + uint8_t icr, idr; // Interrupt Control Register + event_clock_t m_accessClk; + EventContext &event_context; + + class EventTa: public Event + { + private: + MOS6526 &m_cia; + void event (void) {m_cia.ta_event ();} + + public: + EventTa (MOS6526 *cia) + :Event("CIA Timer A"), + m_cia(*cia) {} + } event_ta; + + /* + class EventStateMachineA: public Event + { + private: + MOS6526 &m_cia; + void event (void) {m_cia.cra_event ();} + + public: + EventStateMachineA (MOS6526 *cia) + :Event("CIA Timer A (State Machine)"), + m_cia(*cia) {} + } event_stateMachineA; +*/ + class EventTb: public Event + { + private: + MOS6526 &m_cia; + void event (void) {m_cia.tb_event ();} + + public: + EventTb (MOS6526 *cia) + :Event("CIA Timer B"), + m_cia(*cia) {} + } event_tb; + + friend class EventTa; +// friend class EventStateMachineA; + friend class EventTb; + +protected: + MOS6526 (EventContext *context); + void ta_event (void); + void tb_event (void); + void trigger (int irq); +// void stateMachineA_event (void); + + // Environment Interface + virtual void interrupt (bool state) = 0; + +public: + // Component Standard Calls + void reset (void); + uint8_t read (uint_least8_t addr); + void write (uint_least8_t addr, uint8_t data); + const char *credits (void) {return credit;} +}; + +#endif // _mos6526_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos656x/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/Makefile.am new file mode 100644 index 00000000..7a228bca --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/Makefile.am @@ -0,0 +1,7 @@ + +noinst_LTLIBRARIES = libmos656x.la + +libmos656x_la_SOURCES = mos656x.cpp mos656x.h + +# Remove bad default includes +DEFAULT_INCLUDES= diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos656x/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/Makefile.in new file mode 100644 index 00000000..eeeea606 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/Makefile.in @@ -0,0 +1,424 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +noinst_LTLIBRARIES = libmos656x.la + +libmos656x_la_SOURCES = mos656x.cpp mos656x.h + +# Remove bad default includes +DEFAULT_INCLUDES = +subdir = src/mos656x +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libmos656x_la_LDFLAGS = +libmos656x_la_LIBADD = +am_libmos656x_la_OBJECTS = mos656x.lo +libmos656x_la_OBJECTS = $(am_libmos656x_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/mos656x.Plo +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libmos656x_la_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libmos656x_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/mos656x/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libmos656x.la: $(libmos656x_la_OBJECTS) $(libmos656x_la_DEPENDENCIES) + $(CXXLINK) $(libmos656x_la_LDFLAGS) $(libmos656x_la_OBJECTS) $(libmos656x_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mos656x.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 $(LTLIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +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: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man 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 uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos656x/mos656x.cpp b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/mos656x.cpp new file mode 100644 index 00000000..a7e03642 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/mos656x.cpp @@ -0,0 +1,256 @@ +/*************************************************************************** + + mos656x.cpp - Minimal VIC emulation + ------------------- + begin : Wed May 21 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "sidendian.h" +#include "mos656x.h" + +#define MOS6567R56A_FIRST_DMA_LINE 0x30 +#define MOS6567R56A_LAST_DMA_LINE 0xf7 + +#define MOS6567R8_FIRST_DMA_LINE 0x30 +#define MOS6567R8_LAST_DMA_LINE 0xf7 + +#define MOS6569_FIRST_DMA_LINE 0x30 +#define MOS6569_LAST_DMA_LINE 0xff + +const char *MOS656X::credit = +{ // Optional information + "*MOS656X (VICII) Emulation:\0" + "\tCopyright (C) 2001 Simon White <sidplay2@email.com>\0" +}; + + +MOS656X::MOS656X (EventContext *context) +:Event("VIC Raster"), + event_context(*context) +{ + chip (MOS6569); +} + +void MOS656X::reset () +{ + icr = idr = ctrl1 = 0; + raster_irq = 0; + y_scroll = 0; + raster_y = yrasters - 1; + raster_x = xrasters - 1; + bad_lines_enabled = false; + event_context.schedule (this, 1); + m_accessClk = 0; +} + +void MOS656X::chip (mos656x_model_t model) +{ + switch (model) + { + // Seems to be an older NTSC chip + case MOS6567R56A: + yrasters = 262; + xrasters = 64; + first_dma_line = MOS6567R56A_FIRST_DMA_LINE; + last_dma_line = MOS6567R56A_LAST_DMA_LINE; + break; + + // NTSC Chip + case MOS6567R8: + yrasters = 263; + xrasters = 65; + first_dma_line = MOS6567R8_FIRST_DMA_LINE; + last_dma_line = MOS6567R8_LAST_DMA_LINE; + break; + + // PAL Chip + case MOS6569: + yrasters = 312; + xrasters = 63; + first_dma_line = MOS6569_FIRST_DMA_LINE; + last_dma_line = MOS6569_LAST_DMA_LINE; + break; + } + + reset (); +} + +uint8_t MOS656X::read (uint_least8_t addr) +{ + if (addr > 0x3f) return 0; + if (addr > 0x2e) return 0xff; + + switch (addr) + { + case 0x11: // Control register 1 + return (raster_y & 0x100) >> 1; + case 0x12: // Raster counter + return raster_y & 0xFF; + case 0x19: // IRQ flags + return idr; + case 0x1a: // IRQ mask + return icr | 0xf0; + default: return regs[addr]; + } +} + +void MOS656X::write (uint_least8_t addr, uint8_t data) +{ + if (addr > 0x3f) return; + + regs[addr] = data; + + switch (addr) + { + case 0x11: // Control register 1 + endian_16hi8 (raster_irq, data >> 7); + ctrl1 = data; + y_scroll = data & 7; + + if (raster_x < 11) + break; + + // In line $30, the DEN bit controls if Bad Lines can occur + if (raster_y == 0x30 && data & 0x10) + bad_lines_enabled = true; + + // Bad Line condition? + bad_line = (raster_y >= first_dma_line) && + (raster_y <= last_dma_line) && + ((raster_y & 7) == y_scroll) && + bad_lines_enabled; + + // Start DMA + if (bad_line && (raster_x < 54)) + { + busaccess(false); + if (raster_x < 52) + event_context.schedule (this, 3); + } + break; + + case 0x12: // Raster counter + endian_16lo8 (raster_irq, data); + break; + + case 0x19: // IRQ flags + idr &= ((~data & 0x0f) | 0x80); + if (idr == 0x80) + trigger (0); + break; + + case 0x1a: // IRQ mask + icr = data & 0x0f; + trigger (icr & idr); + break; + } +} + + +void MOS656X::trigger (int irq) +{ + if (!irq) + { // Clear any requested IRQs + if (idr & MOS656X_INTERRUPT_REQUEST) + interrupt (false); + idr = 0; + return; + } + + idr |= irq; + if (icr & idr) + { + if (!(idr & MOS656X_INTERRUPT_REQUEST)) + { + idr |= MOS656X_INTERRUPT_REQUEST; + interrupt (true); + } + } +} + +void MOS656X::event (void) +{ + event_clock_t delay = 1; + + switch (raster_x) + { + case 0: // IRQ occurred (xraster != 0) + if (raster_y != yrasters - 1) + { + raster_y++; + // Trigger raster IRQ if IRQ line reached + if (raster_y == raster_irq) + trigger (MOS656X_INTERRUPT_RST); + delay = 11; + } + break; + case 1: // Vertical blank (line 0) + // Trigger raster IRQ if IRQ in line 0 + raster_y = 0; + if (raster_y == raster_irq) + trigger (MOS656X_INTERRUPT_RST); + delay = 10; + break; + + case 11: // Start bad line + { // In line $30, the DEN bit controls if Bad Lines can occur + if (raster_y == first_dma_line) + bad_lines_enabled = (ctrl1 & 0x10) != 0; + + // Test for bad line condition + bad_line = (raster_y >= first_dma_line) && + (raster_y <= last_dma_line) && + ((raster_y & 7) == y_scroll) && + bad_lines_enabled; + + delay = xrasters - 11; + if (bad_line) + { + delay = 3; + busaccess (false); + } + break; + } + + case 14: // Start DMA + addrctrl (false); + delay = 40; + break; + case 54: // End DMA + busaccess (true); + addrctrl (true); + delay = xrasters - 54; + break; + + case 12: + case 13: + break; + + default: + if (bad_line && (raster_x < 54)) + { + addrctrl (false); + delay = 54 - raster_x; + } + else + { // Skip to the end of raster + busaccess (true); + delay = xrasters - raster_x; + } + } + + raster_x += delay; + raster_x %= xrasters; + event_context.schedule (this, delay); +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos656x/mos656x.h b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/mos656x.h new file mode 100644 index 00000000..7cf9867e --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/mos656x/mos656x.h @@ -0,0 +1,79 @@ +/*************************************************************************** + mos656x.h - Minimal VIC emulation + ------------------- + begin : Wed May 21 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _mos656x_h_ +#define _mos656x_h_ + +#include "component.h" +#include "event.h" + +typedef enum +{ + MOS6567R56A, /* OLD NTSC CHIP */ + MOS6567R8, /* NTSC */ + MOS6569 /* PAL */ +} mos656x_model_t; + + +class MOS656X: public component, public Event +{ +private: + static const char *credit; + +protected: + uint8_t regs[0x40]; + uint8_t icr, idr, ctrl1; + uint_least16_t yrasters, xrasters, raster_irq; + uint_least16_t raster_x, raster_y; + uint_least16_t first_dma_line, last_dma_line, y_scroll; + bool bad_lines_enabled, bad_line; + + event_clock_t m_accessClk; + EventContext &event_context; + +protected: + MOS656X (EventContext *context); + void event (void); + void trigger (int irq); + + // Environment Interface + virtual void interrupt (bool state) = 0; + virtual void busaccess (bool state) = 0; + virtual void addrctrl (bool state) = 0; + +public: + void chip (mos656x_model_t model); + + // Component Standard Calls + void reset (void); + uint8_t read (uint_least8_t addr); + void write (uint_least8_t addr, uint8_t data); + const char *credits (void) {return credit;} +}; + + +/*************************************************************************** + * Inline functions + **************************************************************************/ + +enum +{ + MOS656X_INTERRUPT_RST = 1 << 0, + MOS656X_INTERRUPT_REQUEST = 1 << 7 +}; + +#endif // _mos656x_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/nullsid.h b/plugins/sid/sidplay-libs/libsidplay/src/nullsid.h new file mode 100644 index 00000000..7865d9e9 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/nullsid.h @@ -0,0 +1,43 @@ +/*************************************************************************** + nullsid.h - Null SID Emulation + ------------------- + begin : Thurs Sep 20 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _nullsid_h_ +#define _nullsid_h_ + +#include "sidbuilder.h" + +class NullSID: public sidemu +{ +public: + NullSID () : sidemu (NULL) {;} + + // Standard component functions + void reset () { ; } + void reset (uint8_t) { ; } + uint8_t read (uint_least8_t) { return 0; } + void write (uint_least8_t, uint8_t) { ; } + const char *credits (void) { return ""; } + const char *error (void) { return ""; } + + // Standard SID functions + int_least32_t output (uint_least8_t) { return 0; } + void voice (uint_least8_t, uint_least8_t, + bool) { ; } + void gain (int_least8_t) { ; } +}; + +#endif // _nullsid_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/player.cpp b/plugins/sid/sidplay-libs/libsidplay/src/player.cpp new file mode 100644 index 00000000..38b612c0 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/player.cpp @@ -0,0 +1,945 @@ +/*************************************************************************** + player.cpp - Main Library Code + ------------------- + begin : Fri Jun 9 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: player.cpp,v $ + * Revision 1.57 2002/12/14 10:10:30 s_a_white + * Kernal Mod: Bypass screen clear as we don't have a screen. Fix setting + * of PAL/NTSC flag for real c64 mode. + * + * Revision 1.56 2002/12/13 22:01:54 s_a_white + * Kernel mods: Memory now bypassed by upping the start address so the + * end or ram is found instantly. Basic cold/warm start address points to a + * busy loop to prevent undersiable side effects (this may change later). + * + * Revision 1.55 2002/11/27 00:16:51 s_a_white + * Make sure driver info gets reset and exported properly. + * + * Revision 1.54 2002/11/25 21:09:41 s_a_white + * Reset address for old sidplay1 modes now directly passed to the CPU. This + * prevents tune corruption and banking issues for the different modes. + * + * Revision 1.53 2002/11/21 19:53:58 s_a_white + * CPU nolonger a special case. It now uses the event scheduler like all the + * other components. + * + * Revision 1.52 2002/11/20 21:44:03 s_a_white + * Fix fake IRQ to properly obtain next address. + * + * Revision 1.51 2002/11/19 22:55:18 s_a_white + * Sidplay1 modes modified to make them nolonger require the psid driver. + * Full c64 kernal supported in real c64 mode. + * + * Revision 1.50 2002/11/01 17:36:01 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.49 2002/10/20 08:58:36 s_a_white + * Modify IO map so psiddrv can detect special cases. + * + * Revision 1.48 2002/10/15 18:20:54 s_a_white + * Make all addresses from ea31 to ea7d valid IRQ exit points. This + * approximates the functionality of a real C64. + * + * Revision 1.47 2002/10/02 19:43:47 s_a_white + * RSID support. + * + * Revision 1.46 2002/09/17 17:02:41 s_a_white + * Fixed location of kernel IRQ exit code. + * + * Revision 1.45 2002/09/12 21:01:30 s_a_white + * Added support for simulating the random delay before the user loads a + * program on a real C64. + * + * Revision 1.44 2002/09/09 18:01:30 s_a_white + * Prevent m_info driver details getting modified when C64 crashes. + * + * Revision 1.43 2002/08/20 23:21:41 s_a_white + * Setup default sample format. + * + * Revision 1.42 2002/04/14 21:46:50 s_a_white + * PlaySID reads fixed to come from RAM only. + * + * Revision 1.41 2002/03/12 18:43:59 s_a_white + * Tidy up handling of envReset on illegal CPU instructions. + * + * Revision 1.40 2002/03/11 18:01:30 s_a_white + * Prevent lockup if config call fails with existing and old configurations. + * + * Revision 1.39 2002/03/03 22:01:58 s_a_white + * New clock speed & sid model interface. + * + * Revision 1.38 2002/02/17 16:33:02 s_a_white + * New reset interface for sidbuilders. + * + * Revision 1.37 2002/02/17 12:42:45 s_a_white + * envReset now sets playerStopped indicators. This means the player + * nolonger locks up when a HLT instruction is encountered. + * + * Revision 1.36 2002/02/06 20:12:03 s_a_white + * Added sidplay1 random extension for vic reads. + * + * Revision 1.35 2002/01/29 21:50:33 s_a_white + * Auto switching to a better emulation mode. m_tuneInfo reloaded after a + * config. Initial code added to support more than two sids. + * + * Revision 1.34 2002/01/14 23:16:27 s_a_white + * Prevent multiple initialisations if already stopped. + * + * Revision 1.33 2001/12/13 08:28:08 s_a_white + * Added namespace support to fix problems with xsidplay. + * + * Revision 1.32 2001/11/16 19:25:33 s_a_white + * Removed m_context as where getting mixed with parent class. + * + * Revision 1.31 2001/10/18 22:33:40 s_a_white + * Initialisation order fixes. + * + * Revision 1.30 2001/10/02 18:26:36 s_a_white + * Removed ReSID support and updated for new scheduler. + * + * Revision 1.29 2001/09/17 19:02:38 s_a_white + * Now uses fixed point maths for sample output and rtc. + * + * Revision 1.28 2001/09/04 18:50:57 s_a_white + * Fake CIA address now masked. + * + * Revision 1.27 2001/09/01 11:15:46 s_a_white + * Fixes sidplay1 environment modes. + * + * Revision 1.26 2001/08/10 20:04:46 s_a_white + * Initialise requires rtc reset for correct use with stop operation. + * + * Revision 1.25 2001/07/27 12:51:55 s_a_white + * Removed warning. + * + * Revision 1.24 2001/07/25 17:01:13 s_a_white + * Support for new configuration interface. + * + * Revision 1.23 2001/07/14 16:46:16 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.22 2001/07/14 12:56:15 s_a_white + * SID caching no longer needed. IC components now run using event + * generation (based on VICE). Handling of IRQs now more effecient. All + * sidplay1 hacks either removed or moved to sid6510. Fixed PAL/NTSC + * speeding fixing. Now uses new component and sidbuilder classes. + * + * Revision 1.21 2001/04/23 17:09:56 s_a_white + * Fixed video speed selection using unforced/forced and NTSC clockSpeeds. + * + * Revision 1.20 2001/03/26 21:46:43 s_a_white + * Removed unused #include. + * + * Revision 1.19 2001/03/25 19:48:13 s_a_white + * xsid.reset added. + * + * Revision 1.18 2001/03/22 22:45:20 s_a_white + * Re-ordered initialisations to match defintions. + * + * Revision 1.17 2001/03/21 22:32:34 s_a_white + * Filter redefinition support. VIC & NMI support added. Moved fake interrupts + * to sid6510 class. + * + * Revision 1.16 2001/03/09 22:26:36 s_a_white + * Support for updated C64 player. + * + * Revision 1.15 2001/03/08 22:46:42 s_a_white + * playAddr = 0xffff now better supported. + * + * Revision 1.14 2001/03/01 23:46:37 s_a_white + * Support for sample mode to be selected at runtime. + * + * Revision 1.13 2001/02/28 18:55:27 s_a_white + * Removed initBank* related stuff. IRQ terminating ROM jumps at 0xea31, + * 0xea7e and 0xea81 now handled. + * + * Revision 1.12 2001/02/21 21:43:10 s_a_white + * Now use VSID code and this handles interrupts much better! The whole + * initialise sequence has been modified to support this. + * + * Revision 1.11 2001/02/13 21:01:14 s_a_white + * Support for real interrupts. C64 Initialisation routine now run from Player::play + * instead of Player::initialise. Prevents lockups if init routine does not return. + * + * Revision 1.10 2001/02/08 17:21:14 s_a_white + * Initial SID volumes not being stored in cache. Fixes Dulcedo Cogitationis. + * + * Revision 1.9 2001/02/07 20:56:46 s_a_white + * Samples now delayed until end of simulated frame. + * + * Revision 1.8 2001/01/23 21:26:28 s_a_white + * Only way to load a tune now is by passing in a sidtune object. This is + * required for songlength database support. + * + * Revision 1.7 2001/01/07 15:13:39 s_a_white + * Hardsid update to mute sids when program exits. + * + * Revision 1.6 2000/12/21 22:48:27 s_a_white + * Re-order voices for mono to stereo conversion to match sidplay1. + * + * Revision 1.5 2000/12/14 23:53:36 s_a_white + * Small optimisation update, and comment revision. + * + * Revision 1.4 2000/12/13 17:56:24 s_a_white + * Interrupt vector address changed from 0x315 to 0x314. + * + * Revision 1.3 2000/12/13 12:00:25 mschwendt + * Corrected order of members in member initializer-list. + * + * Revision 1.2 2000/12/12 22:50:15 s_a_white + * Bug Fix #122033. + * + ***************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "config.h" +#include "sidendian.h" +#include "player.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif + +static const uint8_t kernal[] = { +#include "kernal.bin" +}; + +SIDPLAY2_NAMESPACE_START + +const double Player::CLOCK_FREQ_NTSC = 1022727.14; +const double Player::CLOCK_FREQ_PAL = 985248.4; +const double Player::VIC_FREQ_PAL = 50.0; +const double Player::VIC_FREQ_NTSC = 60.0; + +// These texts are used to override the sidtune settings. +const char *Player::TXT_PAL_VBI = "50 Hz VBI (PAL)"; +const char *Player::TXT_PAL_VBI_FIXED = "60 Hz VBI (PAL FIXED)"; +const char *Player::TXT_PAL_CIA = "CIA (PAL)"; +const char *Player::TXT_PAL_UNKNOWN = "UNKNOWN (PAL)"; +const char *Player::TXT_NTSC_VBI = "60 Hz VBI (NTSC)"; +const char *Player::TXT_NTSC_VBI_FIXED = "50 Hz VBI (NTSC FIXED)"; +const char *Player::TXT_NTSC_CIA = "CIA (NTSC)"; +const char *Player::TXT_NTSC_UNKNOWN = "UNKNOWN (NTSC)"; +const char *Player::TXT_NA = "NA"; + +// Error Strings +const char *Player::ERR_CONF_WHILST_ACTIVE = "SIDPLAYER ERROR: Trying to configure player whilst active."; +const char *Player::ERR_UNSUPPORTED_FREQ = "SIDPLAYER ERROR: Unsupported sampling frequency."; +const char *Player::ERR_UNSUPPORTED_PRECISION = "SIDPLAYER ERROR: Unsupported sample precision."; +const char *Player::ERR_MEM_ALLOC = "SIDPLAYER ERROR: Memory Allocation Failure."; +const char *Player::ERR_UNSUPPORTED_MODE = "SIDPLAYER ERROR: Unsupported Environment Mode (Coming Soon)."; + +const char *Player::credit[]; + + +// Set the ICs environment variable to point to +// this player +Player::Player (void) +// Set default settings for system +:c64env (&m_scheduler), + m_scheduler ("SIDPlay 2"), + sid6510 (&m_scheduler), + mos6510 (&m_scheduler), + cpu (&sid6510), + xsid (this, &nullsid), + cia (this), + cia2 (this), + sid6526 (this), + vic (this), + mixerEvent (this), + rtc (&m_scheduler), + m_tune (NULL), + m_ram (NULL), + m_rom (NULL), + m_errorString (TXT_NA), + m_fastForwardFactor (1.0), + m_mileage (0), + m_playerState (sid2_stopped), + m_running (false), + m_sampleCount (0) +{ + srand ((uint) ::time(NULL)); + m_rand = (uint_least32_t) rand (); + + // Set the ICs to use this environment + sid6510.setEnvironment (this); + mos6510.setEnvironment (this); + + // SID Initialise + for (int i = 0; i < SID2_MAX_SIDS; i++) + sid[i] = &nullsid; + xsid.emulation(sid[0]); + sid[0] = &xsid; + + // Setup exported info + m_info.credits = credit; + m_info.channels = 1; + m_info.driverAddr = 0; + m_info.driverLength = 0; + m_info.name = PACKAGE; + m_info.tuneInfo = NULL; + m_info.version = VERSION; + m_info.eventContext = &context(); + // Number of SIDs support by this library + m_info.maxsids = SID2_MAX_SIDS; + m_info.environment = sid2_envR; + + // Configure default settings + m_cfg.clockDefault = SID2_CLOCK_CORRECT; + m_cfg.clockForced = false; + m_cfg.clockSpeed = SID2_CLOCK_CORRECT; + m_cfg.environment = m_info.environment; + m_cfg.forceDualSids = false; + m_cfg.frequency = SID2_DEFAULT_SAMPLING_FREQ; + m_cfg.optimisation = SID2_DEFAULT_OPTIMISATION; + m_cfg.playback = sid2_mono; + m_cfg.precision = SID2_DEFAULT_PRECISION; + m_cfg.sidDefault = SID2_MODEL_CORRECT; + m_cfg.sidEmulation = NULL; + m_cfg.sidModel = SID2_MODEL_CORRECT; + m_cfg.sidSamples = true; + m_cfg.leftVolume = 255; + m_cfg.rightVolume = 255; + m_cfg.sampleFormat = SID2_LITTLE_SIGNED; + + // Configured by default for Sound Blaster (compatibles) + if (SID2_DEFAULT_PRECISION == 8) + m_cfg.sampleFormat = SID2_LITTLE_UNSIGNED; + config (m_cfg); + + // Get component credits + credit[0] = PACKAGE " V" VERSION " Engine:\0\tCopyright (C) 2000 Simon White <sidplay2@email.com>\0"; + credit[1] = xsid.credits (); + credit[2] = "*MOS6510 (CPU) Emulation:\0\tCopyright (C) 2000 Simon White <sidplay2@email.com>\0"; + credit[3] = cia.credits (); + credit[4] = vic.credits (); + credit[5] = NULL; +} + +// Makes the next sequence of notes available. For sidplay compatibility +// this function should be called from interrupt event +void Player::fakeIRQ (void) +{ // Check to see if the play address has been provided or whether + // we should pick it up from an IRQ vector + uint_least16_t playAddr = m_tuneInfo.playAddr; + + // We have to reload the new play address + if (playAddr) + evalBankSelect (m_playBank); + else + { + if (isKernal) + { // Setup the entry point from hardware IRQ + playAddr = endian_little16 (&m_ram[0x0314]); + } + else + { // Setup the entry point from software IRQ + playAddr = endian_little16 (&m_ram[0xFFFF]); + } + } + + // Setup the entry point and restart the cpu + cpu->triggerIRQ (); + sid6510.reset (playAddr, 0, 0, 0); +} + +int Player::fastForward (uint percent) +{ + if (percent > 3200) + { + m_errorString = "SIDPLAYER ERROR: Percentage value out of range"; + return -1; + } + { + float64_t fastForwardFactor; + fastForwardFactor = (float64_t) percent / 100.0; + // Conversion to fixed point 8.24 + m_samplePeriod = (event_clock_t) ((float64_t) m_samplePeriod / + m_fastForwardFactor * fastForwardFactor); + m_fastForwardFactor = fastForwardFactor; + } + return 0; +} + +int Player::initialise () +{ // Fix the mileage counter if just finished another song. + mileageCorrect (); + m_mileage += time (); + + reset (); + if (psidDrvInstall (m_tuneInfo, m_info) < 0) + return -1; + + // The Basic ROM sets these values on loading a file. + { // Program start address + uint_least16_t addr = m_tuneInfo.loadAddr; + endian_little16 (&m_ram[0x2b], addr); + // Program end address + 1 + addr += m_tuneInfo.c64dataLen; + endian_little16 (&m_ram[0x2d], addr); + } + + if (!m_tune->placeSidTuneInC64mem (m_ram)) + { // Rev 1.6 (saw) - Allow loop through errors + m_errorString = m_tuneInfo.statusString; + return -1; + } + + rtc.reset (); + envReset (false); + return 0; +} + +int Player::load (SidTune *tune) +{ + m_tune = tune; + if (!tune) + { // Unload tune + m_info.tuneInfo = NULL; + return 0; + } + m_info.tuneInfo = &m_tuneInfo; + + // Un-mute all voices + xsid.mute (false); + + for (int i = 0; i < SID2_MAX_SIDS; i++) + { + uint_least8_t v = 3; + while (v--) + sid[i]->voice (v, 0, false); + } + + { // Must re-configure on fly for stereo support! + int ret = config (m_cfg); + // Failed configuration with new tune, reject it + if (ret < 0) + { + m_tune = NULL; + return -1; + } + } + return 0; +} + +void Player::mileageCorrect (void) +{ // If just finished a song, round samples to correct mileage + if (m_sampleCount >= (m_cfg.frequency / 2)) + m_mileage++; + m_sampleCount = 0; +} + +void Player::pause (void) +{ + if (m_running) + { + m_playerState = sid2_paused; + m_running = false; + } +} + +uint_least32_t Player::play (void *buffer, uint_least32_t length) +{ + // Make sure a _tune is loaded + if (!m_tune) + return 0; + + // Setup Sample Information + m_sampleIndex = 0; + m_sampleCount = length; + m_sampleBuffer = (char *) buffer; + + // Start the player loop + m_playerState = sid2_playing; + m_running = true; + + while (m_running) + m_scheduler.clock (); + + if (m_playerState == sid2_stopped) + initialise (); + return m_sampleIndex; +} + +void Player::stop (void) +{ // Re-start song + if (m_tune && (m_playerState != sid2_stopped)) + { + if (!m_running) + initialise (); + else + { + m_playerState = sid2_stopped; + m_running = false; + } + } +} + + +//------------------------------------------------------------------------- +// Temporary hack till real bank switching code added + +// Input: A 16-bit effective address +// Output: A default bank-select value for $01. +uint8_t Player::iomap (uint_least16_t addr) +{ + if (m_info.environment != sid2_envPS) + { // Force Real C64 Compatibility + if (m_tuneInfo.compatibility == SIDTUNE_COMPATIBILITY_R64) + return 0; // Special case, converted to 0x37 later + + if (addr == 0) + return 0; // Special case, converted to 0x37 later + if (addr < 0xa000) + return 0x37; // Basic-ROM, Kernal-ROM, I/O + if (addr < 0xd000) + return 0x36; // Kernal-ROM, I/O + if (addr >= 0xe000) + return 0x35; // I/O only + } + return 0x34; // RAM only (special I/O in PlaySID mode) +} + +void Player::evalBankSelect (uint8_t data) +{ // Determine new memory configuration. + isBasic = ((data & 3) == 3); + isIO = ((data & 7) > 4); + isKernal = ((data & 2) != 0); + m_bankReg = data; +} + +uint8_t Player::readMemByte_player (uint_least16_t addr) +{ + if (m_info.environment == sid2_envR) + return readMemByte_sidplaybs (addr); + return readMemByte_plain (addr); +} + +uint8_t Player::readMemByte_plain (uint_least16_t addr) +{ // Bank Select Register Value DOES NOT get to ram + if (addr == 0x0001) + return m_bankReg; + return m_ram[addr]; +} + +uint8_t Player::readMemByte_io (uint_least16_t addr) +{ + uint_least16_t tempAddr = (addr & 0xfc1f); + + // Not SID ? + if (( tempAddr & 0xff00 ) != 0xd400 ) + { + if (m_info.environment == sid2_envR) + { + switch (endian_16hi8 (addr)) + { + case 0: + return readMemByte_plain (addr); + case 0xdc: + return cia.read (addr&0x0f); + case 0xdd: + return cia2.read (addr&0x0f); + case 0xd0: + return vic.read (addr&0x3f); + default: + return m_rom[addr]; + } + } + else + { + switch (endian_16hi8 (addr)) + { + case 0: + return readMemByte_plain (addr); + // Sidplay1 Random Extension CIA + case 0xdc: + return sid6526.read (addr&0x0f); + // Sidplay1 Random Extension VIC + case 0xd0: + switch (addr & 0x3f) + { + case 0x11: + case 0x12: + return sid6526.read ((addr-13)&0x0f); + } + // Deliberate run on + default: + return m_rom[addr]; + } + } + } + + // Read real sid for these + if ((addr & 0xff00) == m_sidAddress[1]) + return sid[1]->read ((uint8_t) addr); + return sid[0]->read ((uint8_t) tempAddr); +} + +uint8_t Player::readMemByte_sidplaytp(uint_least16_t addr) +{ + if (addr < 0xD000) + return readMemByte_plain (addr); + else + { + // Get high-nibble of address. + switch (addr >> 12) + { + case 0xd: + if (isIO) + return readMemByte_io (addr); + else + return m_ram[addr]; + break; + case 0xe: + case 0xf: + default: // <-- just to please the compiler + return m_ram[addr]; + } + } +} + +uint8_t Player::readMemByte_sidplaybs (uint_least16_t addr) +{ + if (addr < 0xA000) + return readMemByte_plain (addr); + else + { + // Get high-nibble of address. + switch (addr >> 12) + { + case 0xa: + case 0xb: + if (isBasic) + return m_rom[addr]; + else + return m_ram[addr]; + break; + case 0xc: + return m_ram[addr]; + break; + case 0xd: + if (isIO) + return readMemByte_io (addr); + else + return m_ram[addr]; + break; + case 0xe: + case 0xf: + default: // <-- just to please the compiler + if (isKernal) + return m_rom[addr]; + else + return m_ram[addr]; + } + } +} + +void Player::writeMemByte_plain (uint_least16_t addr, uint8_t data) +{ + if (addr == 0x0001) + { // Determine new memory configuration. + evalBankSelect (data); + return; + } + m_ram[addr] = data; +} + +void Player::writeMemByte_playsid (uint_least16_t addr, uint8_t data) +{ + uint_least16_t tempAddr = (addr & 0xfc1f); + + // Not SID ? + if (( tempAddr & 0xff00 ) != 0xd400 ) + { + if (m_info.environment == sid2_envR) + { + switch (endian_16hi8 (addr)) + { + case 0: + writeMemByte_plain (addr, data); + return; + case 0xdc: + cia.write (addr&0x0f, data); + return; + case 0xdd: + cia2.write (addr&0x0f, data); + return; + case 0xd0: + vic.write (addr&0x3f, data); + return; + default: + m_rom[addr] = data; + return; + } + } + else + { + switch (endian_16hi8 (addr)) + { + case 0: + writeMemByte_plain (addr, data); + return; + case 0xdc: // Sidplay1 CIA + sid6526.write (addr&0x0f, data); + return; + default: + m_rom[addr] = data; + return; + } + } + } + + // $D41D/1E/1F, $D43D/3E/3F, ... + // Map to real address to support PlaySID + // Extended SID Chip Registers. + if (( tempAddr & 0x00ff ) >= 0x001d ) + xsid.write16 (addr & 0x01ff, data); + else // Mirrored SID. + { // SID. + // Convert address to that acceptable by resid + // Support dual sid + if ((addr & 0xff00) == m_sidAddress[1]) + { + sid[1]->write (addr & 0xff, data); + // Prevent sid write accessing other sid + // if not doing mono to stereo conversion. + if (m_sidAddress[1] != m_sidAddress[0]) + return; + } + sid[0]->write (tempAddr & 0xff, data); + } +} + +void Player::writeMemByte_sidplay (uint_least16_t addr, uint8_t data) +{ + if (addr < 0xA000) + writeMemByte_plain (addr, data); + else + { + // Get high-nibble of address. + switch (addr >> 12) + { + case 0xa: + case 0xb: + case 0xc: + m_ram[addr] = data; + break; + case 0xd: + if (isIO) + writeMemByte_playsid (addr, data); + else + m_ram[addr] = data; + break; + case 0xe: + case 0xf: + default: // <-- just to please the compiler + m_ram[addr] = data; + } + } +} + +// -------------------------------------------------- +// These must be available for use: +void Player::reset (void) +{ + int i; + + m_playerState = sid2_stopped; + m_running = false; + + // Select Sidplay1 compatible CPU or real thing + cpu = &sid6510; + sid6510.environment (m_info.environment); + + m_scheduler.reset (); + for (i = 0; i < SID2_MAX_SIDS; i++) + sid[i]->reset (0x0f); + + if (m_info.environment == sid2_envR) + { + cia.reset (); + cia2.reset (); + vic.reset (); + } + else + { + sid6526.reset (); + sid6526.write (0x0e, 1); // Start timer + if (m_tuneInfo.songSpeed == SIDTUNE_SPEED_VBI) + sid6526.lock (); + } + + // Initalise Memory + memset (m_ram, 0, 0x10000); + memset (m_rom, 0, 0x10000); + if (m_info.environment != sid2_envPS) + memset (m_rom + 0xA000, RTSn, 0x2000); + + if (m_info.environment == sid2_envR) + { + memcpy (&m_rom[0xe000], kernal, sizeof (kernal)); + // Since we don't yet run the kernal power up + // routines, set somethings here. + endian_little16 (&m_ram[0x028f], 0xEB48); // keyboard poll + m_rom[0xfd69] = 0x9f; // Bypass memory check + m_rom[0xe55f] = 0x00; // Bypass screen clear + endian_little16 (&m_rom[0xa000], 0xA004); + endian_little16 (&m_rom[0xa002], 0xA004); + m_rom[0xa004] = JMPw; + endian_little16 (&m_rom[0xa005], 0xA004); + } + else // !sid2_envR + { + memset (m_rom + 0xE000, RTSn, 0x2000); + // fake VBI-interrupts that do $D019, BMI ... + m_rom[0x0d019] = 0xff; + if (m_info.environment == sid2_envPS) + { + m_ram[0xff48] = JMPi; + endian_little16 (&m_ram[0xff49], 0x0314); + } + + // Software vectors + endian_little16 (&m_ram[0x0314], 0xEA31); // IRQ + endian_little16 (&m_ram[0x0316], 0xFE66); // BRK + endian_little16 (&m_ram[0x0318], 0xFE47); // NMI + // Hardware vectors + if (m_info.environment == sid2_envPS) + endian_little16 (&m_rom[0xfffa], 0xFFFA); // NMI + else + endian_little16 (&m_rom[0xfffa], 0xFE43); // NMI + endian_little16 (&m_rom[0xfffc], 0xFCE2); // RESET + endian_little16 (&m_rom[0xfffe], 0xFF48); // IRQ + memcpy (&m_ram[0xfffa], &m_rom[0xfffa], 6); + } + + // Will get done later if can't now + if (m_tuneInfo.clockSpeed == SIDTUNE_CLOCK_PAL) + m_ram[0x02a6] = 1; + else // SIDTUNE_CLOCK_NTSC + m_ram[0x02a6] = 0; +} + +// This resets the cpu once the program is loaded to begin +// running. Also called when the emulation crashes +void Player::envReset (bool safe) +{ + if (safe) + { // Emulation crashed so run in safe mode + uint8_t prg[] = {LDAb, 0x7f, STAa, 0x0d, 0xdc, RTSn}; + sid2_info_t info; + SidTuneInfo tuneInfo; + // Install driver + tuneInfo.relocStartPage = 0x09; + tuneInfo.relocPages = 0x20; + tuneInfo.initAddr = 0x0800; + tuneInfo.songSpeed = SIDTUNE_SPEED_CIA_1A; + info.environment = m_info.environment; + psidDrvInstall (tuneInfo, info); + // Install prg + memcpy (&m_ram[0x0800], prg, sizeof (prg)); + + // Make sids silent + for (int i = 0; i < SID2_MAX_SIDS; i++) + sid[i]->reset (0); + } + + m_ram[0] = 0x2F; + evalBankSelect (0x37); + // defaults: Basic-ROM on, Kernal-ROM on, I/O on + if (m_info.environment != sid2_envR) + { + uint8_t song = m_tuneInfo.currentSong - 1; + uint8_t bank = iomap (m_tuneInfo.initAddr); + if (bank == 0) + bank = 0x37; + evalBankSelect (bank); + m_playBank = iomap (m_tuneInfo.playAddr); + if (m_info.environment != sid2_envPS) + sid6510.reset (m_tuneInfo.initAddr, song, 0, 0); + else + sid6510.reset (m_tuneInfo.initAddr, song, song, song); + } + else + cpu->reset (); + + mixerReset (); + xsid.suppress (true); +} + +uint8_t Player::envReadMemByte (uint_least16_t addr) +{ // Read from plain only to prevent execution of rom code + return (this->*(m_readMemByte)) (addr); +} + +void Player::envWriteMemByte (uint_least16_t addr, uint8_t data) +{ // Writes must be passed to env version. + (this->*(m_writeMemByte)) (addr, data); +} + +uint8_t Player::envReadMemDataByte (uint_least16_t addr) +{ // Read from plain only to prevent execution of rom code + return (this->*(m_readMemDataByte)) (addr); +} + +bool Player::envCheckBankJump (uint_least16_t addr) +{ + switch (m_info.environment) + { + case sid2_envBS: + if (addr >= 0xA000) + { + // Get high-nibble of address. + switch (addr >> 12) + { + case 0xa: + case 0xb: + if (isBasic) + return false; + break; + + case 0xc: + break; + + case 0xd: + if (isIO) + return false; + break; + + case 0xe: + case 0xf: + default: // <-- just to please the compiler + if (isKernal) + return false; + break; + } + } + break; + + case sid2_envTP: + if ((addr >= 0xd000) && isKernal) + return false; + break; + + default: + break; + } + + return true; +} + +SIDPLAY2_NAMESPACE_STOP diff --git a/plugins/sid/sidplay-libs/libsidplay/src/player.h b/plugins/sid/sidplay-libs/libsidplay/src/player.h new file mode 100644 index 00000000..7c0a024c --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/player.h @@ -0,0 +1,434 @@ + /*************************************************************************** + player.h - description + ------------------- + begin : Fri Jun 9 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: player.h,v $ + * Revision 1.39 2002/12/03 23:25:53 s_a_white + * Prevent PSID digis from playing in real C64 mode. + * + * Revision 1.38 2002/11/27 00:16:51 s_a_white + * Make sure driver info gets reset and exported properly. + * + * Revision 1.37 2002/11/20 21:44:34 s_a_white + * Initial support for external DMA to steal cycles away from the CPU. + * + * Revision 1.36 2002/11/19 22:55:50 s_a_white + * PSIDv2NG/RSID changes to deal with spec updates for recommended + * implementation. + * + * Revision 1.35 2002/11/01 17:36:01 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.34 2002/10/02 19:45:23 s_a_white + * RSID support. + * + * Revision 1.33 2002/09/12 21:01:31 s_a_white + * Added support for simulating the random delay before the user loads a + * program on a real C64. + * + * Revision 1.32 2002/09/09 18:01:30 s_a_white + * Prevent m_info driver details getting modified when C64 crashes. + * + * Revision 1.31 2002/07/21 19:39:41 s_a_white + * Proper error handling of reloc info overlapping load image. + * + * Revision 1.30 2002/07/20 08:34:52 s_a_white + * Remove unnecessary and pointless conts. + * + * Revision 1.29 2002/07/17 21:48:10 s_a_white + * PSIDv2NG reloc exclude region extension. + * + * Revision 1.28 2002/04/14 21:46:50 s_a_white + * PlaySID reads fixed to come from RAM only. + * + * Revision 1.27 2002/03/12 18:43:59 s_a_white + * Tidy up handling of envReset on illegal CPU instructions. + * + * Revision 1.26 2002/03/03 22:01:58 s_a_white + * New clock speed & sid model interface. + * + * Revision 1.25 2002/01/29 21:50:33 s_a_white + * Auto switching to a better emulation mode. m_tuneInfo reloaded after a + * config. Initial code added to support more than two sids. + * + * Revision 1.24 2002/01/28 19:32:01 s_a_white + * PSID sample improvements. + * + * Revision 1.23 2001/12/13 08:28:08 s_a_white + * Added namespace support to fix problems with xsidplay. + * + * Revision 1.22 2001/10/18 22:34:04 s_a_white + * GCC3 fixes. + * + * Revision 1.21 2001/10/02 18:26:36 s_a_white + * Removed ReSID support and updated for new scheduler. + * + * Revision 1.20 2001/09/20 19:32:39 s_a_white + * Support for a null sid emulation to use when a builder create call fails. + * + * Revision 1.19 2001/09/17 19:02:38 s_a_white + * Now uses fixed point maths for sample output and rtc. + * + * Revision 1.18 2001/09/01 11:15:46 s_a_white + * Fixes sidplay1 environment modes. + * + * Revision 1.17 2001/08/10 21:01:06 s_a_white + * Fixed RTC initialisation order warning. + * + * Revision 1.16 2001/08/10 20:03:19 s_a_white + * Added RTC reset. + * + * Revision 1.15 2001/07/25 17:01:13 s_a_white + * Support for new configuration interface. + * + * Revision 1.14 2001/07/14 16:46:16 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.13 2001/07/14 12:50:58 s_a_white + * Support for credits and debuging. External filter selection removed. RTC + * and samples obtained in a more efficient way. Support for component + * and sidbuilder classes. + * + * Revision 1.12 2001/04/23 17:09:56 s_a_white + * Fixed video speed selection using unforced/forced and NTSC clockSpeeds. + * + * Revision 1.11 2001/03/22 22:45:20 s_a_white + * Re-ordered initialisations to match defintions. + * + * Revision 1.10 2001/03/21 23:28:12 s_a_white + * Support new component names. + * + * Revision 1.9 2001/03/21 22:32:55 s_a_white + * Filter redefinition support. VIC & NMI support added. + * + * Revision 1.8 2001/03/08 22:48:33 s_a_white + * Sid reset on player destruction removed. Now handled locally by the sids. + * + * Revision 1.7 2001/03/01 23:46:37 s_a_white + * Support for sample mode to be selected at runtime. + * + * Revision 1.6 2001/02/28 18:52:55 s_a_white + * Removed initBank* related stuff. + * + * Revision 1.5 2001/02/21 21:41:51 s_a_white + * Added seperate ram bank to hold C64 player. + * + * Revision 1.4 2001/02/07 20:56:46 s_a_white + * Samples now delayed until end of simulated frame. + * + * Revision 1.3 2001/01/23 21:26:28 s_a_white + * Only way to load a tune now is by passing in a sidtune object. This is + * required for songlength database support. + * + * Revision 1.2 2001/01/07 15:58:37 s_a_white + * SID2_LIB_API now becomes a core define (SID_API). + * + * Revision 1.1 2000/12/12 19:15:40 s_a_white + * Renamed from sidplayer + * + ***************************************************************************/ + +#ifndef _player_h_ +#define _player_h_ + +#include <string.h> + +#include "config.h" +#include "sidplay2.h" +#include "sidenv.h" +#include "c64env.h" +#include "c64/c64xsid.h" +#include "c64/c64cia.h" +#include "c64/c64vic.h" + +#include "mos6510/mos6510.h" +#include "sid6526/sid6526.h" +#include "nullsid.h" +#define SID2_MAX_SIDS 2 + +SIDPLAY2_NAMESPACE_START + +class Player: private C64Environment, c64env +{ +private: + static const double CLOCK_FREQ_NTSC; + static const double CLOCK_FREQ_PAL; + static const double VIC_FREQ_PAL; + static const double VIC_FREQ_NTSC; + + static const char *TXT_PAL_VBI; + static const char *TXT_PAL_VBI_FIXED; + static const char *TXT_PAL_CIA; + static const char *TXT_PAL_UNKNOWN; + static const char *TXT_NTSC_VBI; + static const char *TXT_NTSC_VBI_FIXED; + static const char *TXT_NTSC_CIA; + static const char *TXT_NTSC_UNKNOWN; + static const char *TXT_NA; + + static const char *ERR_CONF_WHILST_ACTIVE; + static const char *ERR_UNSUPPORTED_FREQ; + static const char *ERR_UNSUPPORTED_PRECISION; + static const char *ERR_MEM_ALLOC; + static const char *ERR_UNSUPPORTED_MODE; + static const char *credit[10]; // 10 credits max + + static const char *ERR_PSIDDRV_NO_SPACE; + static const char *ERR_PSIDDRV_RELOC; + + EventScheduler m_scheduler; + + //SID6510 cpu(6510, "Main CPU"); + SID6510 sid6510; + MOS6510 mos6510; + MOS6510 *cpu; + // Sid objects to use. + NullSID nullsid; + c64xsid xsid; + c64cia1 cia; + c64cia2 cia2; + SID6526 sid6526; + c64vic vic; + sidemu *sid[SID2_MAX_SIDS]; + + class EventMixer: public Event + { + private: + Player &m_player; + void event (void) { m_player.mixer (); } + + public: + EventMixer (Player *player) + :Event("Mixer"), + m_player(*player) {} + } mixerEvent; + friend class EventMixer; + + class EventRTC: public Event + { + private: + EventContext &m_eventContext; + event_clock_t m_seconds; + event_clock_t m_period; + event_clock_t m_clk; + + void event (void) + { // Fixed point 25.7 (approx 2 dp) + event_clock_t cycles; + m_clk += m_period; + cycles = m_clk >> 7; + m_clk &= 0x7F; + m_seconds++; + m_eventContext.schedule (this, cycles); + } + + public: + EventRTC (EventContext *context) + :Event("RTC"), + m_eventContext(*context), + m_seconds(0) + {;} + + event_clock_t getTime () const {return m_seconds;} + + void reset (void) + { // Fixed point 25.7 + m_seconds = 0; + m_clk = m_period & 0x7F; + m_eventContext.schedule (this, m_period >> 7); + } + + void clock (float64_t period) + { // Fixed point 25.7 + m_period = (event_clock_t) (period / 10.0 * (float64_t) (1 << 7)); + reset (); + } + } rtc; + + // User Configuration Settings + SidTuneInfo m_tuneInfo; + SidTune *m_tune; + uint8_t *m_ram, *m_rom; + sid2_info_t m_info; + sid2_config_t m_cfg; + + const char *m_errorString; + float64_t m_fastForwardFactor; + uint_least32_t m_mileage; + int_least32_t m_leftVolume; + int_least32_t m_rightVolume; + volatile sid2_player_t m_playerState; + volatile bool m_running; + int m_rand; + + // Mixer settings + event_clock_t m_sampleClock; + event_clock_t m_samplePeriod; + uint_least32_t m_sampleCount; + uint_least32_t m_sampleIndex; + char *m_sampleBuffer; + + // C64 environment settings + uint8_t m_bankReg; + uint8_t m_playBank; + uint_least16_t m_sidAddress[2]; + + // temp stuff ------------- + bool isKernal; + bool isBasic; + bool isIO; + inline void evalBankSelect (uint8_t data); + void c64_initialise (void); + // ------------------------ + +private: + float64_t clockSpeed (sid2_clock_t clock, sid2_clock_t defaultClock, + bool forced); + int environment (sid2_env_t env); + void fakeIRQ (void); + int initialise (void); + void nextSequence (void); + void mixer (void); + void mixerReset (void); + void mileageCorrect (void); + int sidCreate (sidbuilder *builder, sid2_model_t model, + sid2_model_t defaultModel); + void sidSamples (bool enable); + void reset (); + uint8_t iomap (uint_least16_t addr); + + uint8_t readMemByte_player (uint_least16_t addr); + uint8_t readMemByte_plain (uint_least16_t addr); + uint8_t readMemByte_io (uint_least16_t addr); + uint8_t readMemByte_sidplaytp (uint_least16_t addr); + uint8_t readMemByte_sidplaybs (uint_least16_t addr); + void writeMemByte_plain (uint_least16_t addr, uint8_t data); + void writeMemByte_playsid (uint_least16_t addr, uint8_t data); + void writeMemByte_sidplay (uint_least16_t addr, uint8_t data); + + // Use pointers to please requirements of all the provided + // environments. + uint8_t (Player::*m_readMemByte) (uint_least16_t); + void (Player::*m_writeMemByte) (uint_least16_t, uint8_t); + uint8_t (Player::*m_readMemDataByte)(uint_least16_t); + + uint8_t readMemRamByte (uint_least16_t addr) + { return m_ram[addr]; } + + // Environment Function entry Points + void envReset (bool safe); + inline void envReset (void) { envReset (true); } + uint8_t envReadMemByte (uint_least16_t addr); + inline void envWriteMemByte (uint_least16_t addr, uint8_t data); + inline bool envCheckBankJump (uint_least16_t addr); + inline uint8_t envReadMemDataByte (uint_least16_t addr); + inline void envSleep (void); + + void envLoadFile (char *file) + { + char name[0x100] = "e:/emulators/c64/games/prgs/"; + strcat (name, file); + strcat (name, ".sid"); + m_tune->load (name); + stop (); + } + + // Rev 2.0.3 Added - New Mixer Routines + uint_least32_t (Player::*output) (char *buffer); + + // Rev 2.0.4 (saw) - Added to reduce code size + int_least32_t monoOutGenericLeftIn (uint_least8_t bits); + int_least32_t monoOutGenericStereoIn (uint_least8_t bits); + int_least32_t monoOutGenericRightIn (uint_least8_t bits); + + // 8 bit output + uint_least32_t monoOut8MonoIn (char *buffer); + uint_least32_t monoOut8StereoIn (char *buffer); + uint_least32_t monoOut8StereoRIn (char *buffer); + uint_least32_t stereoOut8MonoIn (char *buffer); + uint_least32_t stereoOut8StereoIn (char *buffer); + + // Rev 2.0.4 (jp) - Added 16 bit support + uint_least32_t monoOut16MonoIn (char *buffer); + uint_least32_t monoOut16StereoIn (char *buffer); + uint_least32_t monoOut16StereoRIn (char *buffer); + uint_least32_t stereoOut16MonoIn (char *buffer); + uint_least32_t stereoOut16StereoIn (char *buffer); + + void interruptIRQ (bool state); + void interruptNMI (void); + void interruptRST (void); + void signalBA (bool state) { cpu->rdySignal (state); } + void signalAEC (bool state) { cpu->aecSignal (state); } + + // PSID driver + int psidDrvInstall (SidTuneInfo &tuneInfo, sid2_info_t &info); + void psidRelocAddr (SidTuneInfo &tuneInfo, int startp, int endp); + +public: + Player (); + + const sid2_config_t &config (void) const { return m_cfg; } + const sid2_info_t &info (void) const { return m_info; } + + int config (const sid2_config_t &cfg); + int fastForward (uint percent); + int load (SidTune *tune); + uint_least8_t mileage (void) const { return m_mileage + time(); } + void pause (void); + uint_least32_t play (void *buffer, uint_least32_t length); + sid2_player_t state (void) const { return m_playerState; } + void stop (void); + uint_least32_t time (void) const {return rtc.getTime (); } + void debug (bool enable) { cpu->debug (enable); } + const char *error (void) const { return m_errorString; } +}; + +inline void Player::envSleep (void) +{ + if (m_info.environment != sid2_envR) + { // Start the sample sequence + xsid.suppress (false); + xsid.suppress (true); + } +} + +inline void Player::interruptIRQ (bool state) +{ + if (state) + { + if (m_info.environment == sid2_envR) + cpu->triggerIRQ (); + else + fakeIRQ (); + } + else + cpu->clearIRQ (); +} + +inline void Player::interruptNMI () +{ + cpu->triggerNMI (); +} + +inline void Player::interruptRST () +{ + stop (); +} + +SIDPLAY2_NAMESPACE_STOP + +#endif // _player_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/poweron.bin b/plugins/sid/sidplay-libs/libsidplay/src/poweron.bin new file mode 100644 index 00000000..b5850151 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/poweron.bin @@ -0,0 +1,79 @@ +0x9a, 0x03,
+0x18, 0x3c,
+0x01, 0x03,
+0x0f, 0xa0,
+0x01, 0x30,
+0x01, 0xfd,
+0x08, 0x0c,
+0x01, 0x0c,
+0x05, 0x04,
+0x03, 0x27,
+0x04, 0x84,
+0x01, 0x84,
+0x01, 0x84,
+0x01, 0x84,
+0x01, 0x84,
+0x01, 0x84,
+0x01, 0x84,
+0x01, 0x85,
+0x01, 0x85,
+0x01, 0x85,
+0x01, 0x85,
+0x01, 0x85,
+0x01, 0x85,
+0x01, 0x86,
+0x01, 0x86,
+0x01, 0x86,
+0x01, 0x86,
+0x01, 0x86,
+0x01, 0x86,
+0x01, 0x86,
+0x01, 0x87,
+0x01, 0x87,
+0x01, 0x87,
+0x01, 0x87,
+0x01, 0x87,
+0x01, 0x87,
+0x02, 0xd8,
+0xff, 0x00,
+0x8f, 0x08,
+0x02, 0xa0,
+0x02, 0x0e,
+0x02, 0x04,
+0x01, 0x0a,
+0x02, 0x04,
+0x01, 0x0a,
+0x03, 0x48,
+0x01, 0xeb,
+0x84, 0x31,
+0x01, 0xea,
+0x01, 0x66,
+0x01, 0xfe,
+0x01, 0x47,
+0x01, 0xfe,
+0x01, 0x4a,
+0x01, 0xf3,
+0x01, 0x91,
+0x01, 0xf2,
+0x01, 0x0e,
+0x01, 0xf2,
+0x01, 0x50,
+0x01, 0xf2,
+0x01, 0x33,
+0x01, 0xf3,
+0x01, 0x57,
+0x01, 0xf1,
+0x01, 0xca,
+0x01, 0xf1,
+0x01, 0xed,
+0x01, 0xf6,
+0x01, 0x3e,
+0x01, 0xf1,
+0x01, 0x2f,
+0x01, 0xf3,
+0x01, 0x66,
+0x01, 0xfe,
+0x01, 0xa5,
+0x01, 0xf4,
+0x01, 0xed,
+0x01, 0xf5,
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.a65 b/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.a65 new file mode 100644 index 00000000..8d269662 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.a65 @@ -0,0 +1,210 @@ +/*************************************************************************** + psiddrv.a65 - C64 Sid Player + ------------------- + begin : + copyright : (C) 2000 by Dag Lem + email : resid@nimrod.no + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * Modified by Simon White <sidplay2@email.com> for use in the sidplayer + * SIDPlay2. + * + * Build with: + * xa -R -G psiddrv.a65 -o psiddrv.o65 + * od -v -An -w8 -tx1 psiddrv.o65 | sed 's/\w\w/0x&,/g' > psiddrv.bin + ***************************************************************************/ +/*************************************************************************** + * $Log: psiddrv.a65,v $ + * Revision 1.16 2002/12/13 22:04:54 s_a_white + * Nolonger CLI after returning from INIT for RSID tunes. Since the tunes are + * more complicated rely on the init to do the right thing. + * + * Revision 1.15 2002/11/20 21:43:08 s_a_white + * Enable the VIC screen and therefore DMA. + * + * Revision 1.14 2002/11/19 22:53:23 s_a_white + * Sidplay1 modes modified to make them nolonger require the psid driver. + * + * Revision 1.13 2002/11/01 17:36:01 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.12 2002/10/20 08:59:14 s_a_white + * Prevent some PSID tunes being handled like RSID ones. + * + * Revision 1.11 2002/10/02 19:42:59 s_a_white + * RSID support. + * + * Revision 1.10 2002/09/21 22:32:18 s_a_white + * Prevent some of the real c64 only tunes abusing play != 0. Some busy + * looping ones may still get away with it... + * + * Revision 1.9 2002/09/12 20:39:47 s_a_white + * Added support for simulating the random delay before the user loads a + * program on a real C64. + * + * Revision 1.8 2002/03/12 18:45:37 s_a_white + * Added PHP to push stack as sidplay1 compatibility IRQ now behaves like + * JSR. + * + * Revision 1.7 2002/02/17 12:35:35 s_a_white + * BRK handler clean up and better sidplay2 optimisation usage. + * + * Revision 1.6 2002/02/05 08:48:58 s_a_white + * Small fix for psid specific rips and real irq handlers (A reg now zeroed). + * + * Revision 1.5 2002/02/04 23:50:48 s_a_white + * Improved compatibilty with older sidplay1 modes. + * + * Revision 1.4 2001/12/17 23:43:29 s_a_white + * Fix for real C64 tunes where BRK handler is run. + * + * Revision 1.3 2001/10/02 18:05:27 s_a_white + * Fix for real C64 tunes which correctly handle BRK. + * + * Revision 1.2 2001/09/01 11:12:22 s_a_white + * Fixes sidplay1 environment modes. + * + * Revision 1.1 2001/07/27 12:12:23 s_a_white + * Initial release. + * + ***************************************************************************/ + + ; entry address +coldvec .word cold + ; redirect basic restart vector + ; to finish the init sequence +finitvec .word setiomap + + ; initial user interrupt vectors +retusr .word irqret + .byte 0 +irqusr .word irqret +brkusr .word brkjob +nmiusr .word nmijob + +playnum .byte 0 +speed .byte 0 +initvec .word 0 +playvec .word 0 +rndwait .word 0 +initiomap .byte 0 +playiomap .byte 0 + + ; init/play PSID +play jmp (playvec) +init jmp (initvec) + + ; cold start +cold sei + + ; set CIA Timer A to 60Hz + lda $02a6 + beq ntsc +pal lda #$25 + ldx #$40 + bne timer +ntsc lda #$95 + ldx #$42 +timer sta $dc04 + stx $dc05 + + ; enable the VICs screen + lda $d011 + ora #$10 + sta $d011 + + ; 0 indicates VIC timing, else it's from CIA + ldx #$81 + lda speed + bne ciainit + + ; enable VICII raster interrupt + stx $d01a + beq doinit + + ; enable CIA 1 timer A interrupt +ciainit stx $dc0d + + ; always enable timer A for random numbers +doinit lda #$01 + sta $dc0e + + ; If play address, override default irq vector so + ; we reach are routine to handle play routine + lda playiomap + beq noplay + lda #<irqjob + sta $0314 + + ; set I/O map and call song init routine +noplay lda initiomap + bne setbank + ; Only release interrupt mask for real + ; C64 tunes (initiomap = 0) thus + ; providing a more realistic environment + lda #$37 + ; cli dosen't come into effect until + ; after the sta! + cli +setbank sta $01 + + ; simulate time before user loads tune +random tya + ldx rndwait + ldy rndwait+1 + inx + iny +wait dex + bne wait + dey + bne wait + tay + + ; get song number +getsong ldx playnum + dex + txa + ldx #0 + ldy #0 + jsr init +setiomap lda initiomap + beq idle + lda playiomap + beq run + lda #$37 + sta $01 + bne run + +brkjob ldx #$ff + txs +run cli +idle jmp idle + +irqjob lda $01 + pha + lda playiomap + sta $01 + lda #0 + jsr play + pla + sta $01 + inc $d019 + + ; IRQ Exit (code from Kernel ROM) +irqret lda $dc0d + pla + tay + pla + tax + pla +nmijob rti + +.end diff --git a/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.bin b/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.bin new file mode 100644 index 00000000..a7e8ae05 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.bin @@ -0,0 +1,32 @@ + 0x01, 0x00, 0x6f, 0x36, 0x35, 0x00, 0x00, 0x00, + 0x00, 0x10, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1d, 0x10, 0x7f, 0x10, 0xa9, + 0x10, 0x00, 0xa9, 0x10, 0x8f, 0x10, 0xb1, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6c, 0x11, 0x10, 0x6c, 0x0f, 0x10, + 0x78, 0xad, 0xa6, 0x02, 0xf0, 0x06, 0xa9, 0x25, + 0xa2, 0x40, 0xd0, 0x04, 0xa9, 0x95, 0xa2, 0x42, + 0x8d, 0x04, 0xdc, 0x8e, 0x05, 0xdc, 0xad, 0x11, + 0xd0, 0x09, 0x10, 0x8d, 0x11, 0xd0, 0xa2, 0x81, + 0xad, 0x0e, 0x10, 0xd0, 0x05, 0x8e, 0x1a, 0xd0, + 0xf0, 0x03, 0x8e, 0x0d, 0xdc, 0xa9, 0x01, 0x8d, + 0x0e, 0xdc, 0xad, 0x16, 0x10, 0xf0, 0x05, 0xa9, + 0x96, 0x8d, 0x14, 0x03, 0xad, 0x15, 0x10, 0xd0, + 0x03, 0xa9, 0x37, 0x58, 0x85, 0x01, 0x98, 0xae, + 0x13, 0x10, 0xac, 0x14, 0x10, 0xe8, 0xc8, 0xca, + 0xd0, 0xfd, 0x88, 0xd0, 0xfa, 0xa8, 0xae, 0x0d, + 0x10, 0xca, 0x8a, 0xa2, 0x00, 0xa0, 0x00, 0x20, + 0x1a, 0x10, 0xad, 0x15, 0x10, 0xf0, 0x0f, 0xad, + 0x16, 0x10, 0xf0, 0x09, 0xa9, 0x37, 0x85, 0x01, + 0xd0, 0x03, 0xa2, 0xff, 0x9a, 0x58, 0x4c, 0x93, + 0x10, 0xa5, 0x01, 0x48, 0xad, 0x16, 0x10, 0x85, + 0x01, 0xa9, 0x00, 0x20, 0x17, 0x10, 0x68, 0x85, + 0x01, 0xee, 0x19, 0xd0, 0xad, 0x0d, 0xdc, 0x68, + 0xa8, 0x68, 0xaa, 0x68, 0x40, 0x00, 0x00, 0x01, + 0x82, 0x02, 0x82, 0x02, 0x82, 0x03, 0x82, 0x02, + 0x82, 0x02, 0x82, 0x0d, 0x82, 0x03, 0x82, 0x23, + 0x82, 0x12, 0x82, 0x05, 0x22, 0x05, 0x82, 0x0b, + 0x82, 0x03, 0x82, 0x0c, 0x82, 0x09, 0x82, 0x03, + 0x82, 0x05, 0x82, 0x0f, 0x82, 0x06, 0x82, 0x07, + 0x82, 0x00, 0x00, 0x00, 0x00, diff --git a/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.cpp b/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.cpp new file mode 100644 index 00000000..5a8cf894 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/psiddrv.cpp @@ -0,0 +1,266 @@ +/*************************************************************************** + psiddrv.cpp - PSID Driver Installtion + ------------------- + begin : Fri Jul 27 2001 + copyright : (C) 2001 by Simon White + email : s_a_white@email.com + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: psiddrv.cpp,v $ + * Revision 1.25 2002/12/13 22:07:29 s_a_white + * C64 code fixed so a theres no decrement before checking the random value. + * + * Revision 1.24 2002/11/27 00:16:51 s_a_white + * Make sure driver info gets reset and exported properly. + * + * Revision 1.23 2002/11/25 21:09:42 s_a_white + * Reset address for old sidplay1 modes now directly passed to the CPU. This + * prevents tune corruption and banking issues for the different modes. + * + * Revision 1.22 2002/11/19 22:53:23 s_a_white + * Sidplay1 modes modified to make them nolonger require the psid driver. + * + * Revision 1.21 2002/11/01 19:11:21 s_a_white + * Export random delay used in song. + * + * Revision 1.20 2002/11/01 17:36:02 s_a_white + * Frame based support for old sidplay1 modes. + * + * Revision 1.19 2002/10/02 19:42:59 s_a_white + * RSID support. + * + * Revision 1.18 2002/09/12 21:01:32 s_a_white + * Added support for simulating the random delay before the user loads a + * program on a real C64. + * + * Revision 1.17 2002/09/09 18:01:30 s_a_white + * Prevent m_info driver details getting modified when C64 crashes. + * + * Revision 1.16 2002/07/21 19:39:40 s_a_white + * Proper error handling of reloc info overlapping load image. + * + * Revision 1.15 2002/07/18 18:37:42 s_a_white + * Buffer overflow fixes for tunes providing bad reloc information. + * + * Revision 1.14 2002/07/17 21:48:10 s_a_white + * PSIDv2NG reloc exclude region extension. + * + * Revision 1.13 2002/03/12 18:43:59 s_a_white + * Tidy up handling of envReset on illegal CPU instructions. + * + * Revision 1.12 2002/03/03 22:02:36 s_a_white + * Sidplay2 PSID driver length now exported. + * + * Revision 1.11 2002/02/17 12:41:18 s_a_white + * Fixed to not so easily break when C64 code is modified. + * + * Revision 1.10 2002/02/04 23:50:48 s_a_white + * Improved compatibilty with older sidplay1 modes. + * + * Revision 1.9 2002/01/29 21:50:33 s_a_white + * Auto switching to a better emulation mode. tuneInfo reloaded after a + * config. Initial code added to support more than two sids. + * + * Revision 1.8 2001/12/21 21:54:14 s_a_white + * Improved compatibility if Sidplay1 bankswitching mode. + * + * Revision 1.7 2001/12/13 08:28:08 s_a_white + * Added namespace support to fix problems with xsidplay. + * + * Revision 1.6 2001/11/16 19:23:18 s_a_white + * Fixed sign of buf for reloc65 call. + * + * Revision 1.5 2001/10/28 21:28:35 s_a_white + * For none real mode if play != 0 we now always jump to irqjob instead of + * playAddr. + * + * Revision 1.4 2001/10/02 18:31:24 s_a_white + * No longer dies if relocStartPages != 0 byr relocPages == 0. For none real + * evironment modes, play is always followed even if interrupt handlers are + * installed. + * + * Revision 1.3 2001/09/01 11:13:18 s_a_white + * Fixes sidplay1 environment modes. + * + * Revision 1.2 2001/07/27 12:52:12 s_a_white + * Removed warning. + * + * Revision 1.1 2001/07/27 12:12:23 s_a_white + * Initial release. + * + ***************************************************************************/ + +// -------------------------------------------------------- +// The code here is use to support the PSID Version 2NG +// (proposal B) file format for player relocation support. +// -------------------------------------------------------- +#include "sidendian.h" +#include "player.h" + +#define PSIDDRV_MAX_PAGE 0xff + +SIDPLAY2_NAMESPACE_START + +const char *Player::ERR_PSIDDRV_NO_SPACE = "ERROR: No space to install psid driver in C64 ram"; +const char *Player::ERR_PSIDDRV_RELOC = "ERROR: Failed whilst relocating psid driver"; + +extern "C" int reloc65(unsigned char** buf, int* fsize, int addr); + +int Player::psidDrvInstall (SidTuneInfo &tuneInfo, sid2_info_t &info) +{ + uint_least16_t relocAddr; + int startlp = tuneInfo.loadAddr >> 8; + int endlp = (tuneInfo.loadAddr + (tuneInfo.c64dataLen - 1)) >> 8; + + if (info.environment != sid2_envR) + { // Sidplay1 modes require no psid driver + info.driverAddr = 0; + info.driverLength = 0; + info.rnddelay = 0; + return 0; + } + + // Check for free space in tune + if (tuneInfo.relocStartPage == PSIDDRV_MAX_PAGE) + tuneInfo.relocPages = 0; + // Check if we need to find the reloc addr + else if (tuneInfo.relocStartPage == 0) + { // Tune is clean so find some free ram around the + // load image + psidRelocAddr (tuneInfo, startlp, endlp); + } + else + { // Check reloc information mode + int startrp = tuneInfo.relocStartPage; + int endrp = startrp + (tuneInfo.relocPages - 1); + + // New relocation implementation (exclude region) + // to complement existing method rejected as being + // unnecessary. From tests in most cases this + // method increases memory availibility. + /************************************************* + if ((startrp <= startlp) && (endrp >= endlp)) + { // Is describing used space so find some free + // ram outside this range + psidRelocAddr (tuneInfo, startrp, endrp); + } + *************************************************/ + } + + if (tuneInfo.relocPages < 1) + { + m_errorString = ERR_PSIDDRV_NO_SPACE; + return -1; + } + + relocAddr = tuneInfo.relocStartPage << 8; + + { // Place psid driver into ram + uint8_t psid_driver[] = { +# include "psiddrv.bin" + }; + uint8_t *reloc_driver = psid_driver; + int reloc_size = sizeof (psid_driver); + + if (!reloc65 (&reloc_driver, &reloc_size, relocAddr - 13)) + { + m_errorString = ERR_PSIDDRV_RELOC; + return -1; + } + + // Adjust size to not included initialisation data. + reloc_size -= 13; + info.driverAddr = relocAddr; + info.driverLength = (uint_least16_t) reloc_size; + // Round length to end of page + info.driverLength += 0xff; + info.driverLength &= 0xff00; + + m_ram[0x310] = JMPw; + memcpy (&m_ram[0x0311], &reloc_driver[4], 9); + memcpy (&m_rom[0xfffc], &reloc_driver[0], 2); /* RESET */ + + { // Experimental exit to basic support + uint_least16_t addr; + addr = endian_little16(&reloc_driver[2]); + m_rom[0xa7ae] = JMPw; + endian_little16 (&m_rom[0xa7af], 0xffe1); + endian_little16 (&m_ram[0x0328], addr); + } + memcpy (&m_ram[relocAddr], &reloc_driver[13], reloc_size); + } + + { // Setup the Initial entry point + uint_least16_t playAddr = tuneInfo.playAddr; + uint_least16_t addr = relocAddr; + + // Tell C64 about song + m_ram[addr++] = (uint8_t) tuneInfo.currentSong; + if (tuneInfo.songSpeed == SIDTUNE_SPEED_VBI) + m_ram[addr] = 0; + else // SIDTUNE_SPEED_CIA_1A + m_ram[addr] = 1; + + addr++; + endian_little16 (&m_ram[addr], tuneInfo.initAddr); + addr += 2; + endian_little16 (&m_ram[addr], playAddr); + addr += 2; + // Below we limit the delay to something sensible. + info.rnddelay = (uint_least16_t) (m_rand >> 3) & 0x0FFF; + endian_little16 (&m_ram[addr], m_info.rnddelay); + addr += 2; + m_rand = m_rand * 13 + 1; + m_ram[addr++] = iomap (m_tuneInfo.initAddr); + m_ram[addr++] = iomap (m_tuneInfo.playAddr); + } + return 0; +} + + +void Player::psidRelocAddr (SidTuneInfo &tuneInfo, int startp, int endp) +{ // Used memory ranges. + bool pages[256]; + int used[] = {0x00, 0x03, + 0xa0, 0xbf, + 0xd0, 0xff, + startp, endp}; + + // Mark used pages in table. + memset(pages, false, sizeof(pages)); + for (size_t i = 0; i < sizeof(used)/sizeof(*used); i += 2) + { + for (int page = used[i]; page <= used[i + 1]; page++) + pages[page] = true; + } + + { // Find largest free range. + int relocPages, lastPage = 0; + tuneInfo.relocPages = 0; + for (size_t page = 0; page < sizeof(pages)/sizeof(*pages); page++) + { + if (pages[page] == false) + continue; + relocPages = page - lastPage; + if (relocPages > tuneInfo.relocPages) + { + tuneInfo.relocStartPage = lastPage; + tuneInfo.relocPages = relocPages; + } + lastPage = page + 1; + } + } + + if (tuneInfo.relocPages == 0) + tuneInfo.relocStartPage = PSIDDRV_MAX_PAGE; +} + +SIDPLAY2_NAMESPACE_STOP diff --git a/plugins/sid/sidplay-libs/libsidplay/src/reloc65.c b/plugins/sid/sidplay-libs/libsidplay/src/reloc65.c new file mode 100644 index 00000000..3c732a39 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/reloc65.c @@ -0,0 +1,232 @@ +/* + xa65 - 6502 cross assembler and utility suite + reloc65 - relocates 'o65' files + Copyright (C) 1997 André Fachat (a.fachat@physik.tu-chemnitz.de) + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Modified by Dag Lem <resid@nimrod.no> + Relocate and extract text segment from memory buffer instead of file. + For use with VICE VSID. +*/ + +#include <stdio.h> +#include <string.h> + +#define BUF (9*2+8) /* 16 bit header */ + +typedef struct { + char *fname; + size_t fsize; + unsigned char *buf; + int tbase, tlen, dbase, dlen, bbase, blen, zbase, zlen; + int tdiff, ddiff, bdiff, zdiff; + unsigned char *segt; + unsigned char *segd; + unsigned char *utab; + unsigned char *rttab; + unsigned char *rdtab; + unsigned char *extab; +} file65; + + +int read_options(unsigned char *f); +int read_undef(unsigned char *f); +unsigned char *reloc_seg(unsigned char *f, int len, unsigned char *rtab, file65 *fp); +unsigned char *reloc_globals(unsigned char *, file65 *fp); + +file65 file; +unsigned char cmp[] = { 1, 0, 'o', '6', '5' }; + +int reloc65(unsigned char** buf, int* fsize, int addr) +{ + int mode, hlen; + + int tflag=0, dflag=0, bflag=0, zflag=0; + int tbase=0, dbase=0, bbase=0, zbase=0; + int extract = 0; + + file.buf = *buf; + file.fsize = *fsize; + tflag= 1; + tbase = addr; + extract = 1; + + if (memcmp(file.buf, cmp, 5) != 0) { + return 0; + } + + mode=file.buf[7]*256+file.buf[6]; + if(mode & 0x2000) { + return 0; + } else if(mode & 0x4000) { + return 0; + } + + hlen = BUF+read_options(file.buf+BUF); + + file.tbase = file.buf[ 9]*256+file.buf[ 8]; + file.tlen = file.buf[11]*256+file.buf[10]; + file.tdiff = tflag? tbase - file.tbase : 0; + file.dbase = file.buf[13]*256+file.buf[12]; + file.dlen = file.buf[15]*256+file.buf[14]; + file.ddiff = dflag? dbase - file.dbase : 0; + file.bbase = file.buf[17]*256+file.buf[16]; + file.blen = file.buf[19]*256+file.buf[18]; + file.bdiff = bflag? bbase - file.bbase : 0; + file.zbase = file.buf[21]*256+file.buf[20]; + file.zlen = file.buf[23]*256+file.buf[21]; + file.zdiff = zflag? zbase - file.zbase : 0; + + file.segt = file.buf + hlen; + file.segd = file.segt + file.tlen; + file.utab = file.segd + file.dlen; + + file.rttab = file.utab + read_undef(file.utab); + + file.rdtab = reloc_seg(file.segt, file.tlen, file.rttab, &file); + file.extab = reloc_seg(file.segd, file.dlen, file.rdtab, &file); + + reloc_globals(file.extab, &file); + + if(tflag) { + file.buf[ 9]= (tbase>>8)&255; + file.buf[ 8]= tbase & 255; + } + if(dflag) { + file.buf[13]= (dbase>>8)&255; + file.buf[12]= dbase & 255; + } + if(bflag) { + file.buf[17]= (bbase>>8)&255; + file.buf[16]= bbase & 255; + } + if(zflag) { + file.buf[21]= (zbase>>8)&255; + file.buf[20]= zbase & 255; + } + + switch(extract) { + case 0: /* whole file */ + return 1; + case 1: /* text segment */ + *buf = file.segt; + *fsize = file.tlen; + return 1; + case 2: + *buf = file.segd; + *fsize = file.dlen; + return 1; + default: + return 0; + } +} + + +int read_options(unsigned char *buf) { + int c, l=0; + + c=buf[0]; + while(c && c!=EOF) { + c&=255; + l+=c; + c=buf[l]; + } + return ++l; +} + +int read_undef(unsigned char *buf) { + int n, l = 2; + + n = buf[0] + 256*buf[1]; + while(n){ + n--; + while(!buf[l++]); + } + return l; +} + +#define reldiff(s) (((s)==2)?fp->tdiff:(((s)==3)?fp->ddiff:(((s)==4)?fp->bdiff:(((s)==5)?fp->zdiff:0)))) + +unsigned char *reloc_seg(unsigned char *buf, int len, unsigned char *rtab, file65 *fp) { + int adr = -1; + int type, seg, old, new; +/*printf("tdiff=%04x, ddiff=%04x, bdiff=%04x, zdiff=%04x\n", + fp->tdiff, fp->ddiff, fp->bdiff, fp->zdiff);*/ + while(*rtab) { + if((*rtab & 255) == 255) { + adr += 254; + rtab++; + } else { + adr += *rtab & 255; + rtab++; + type = *rtab & 0xe0; + seg = *rtab & 0x07; +/*printf("reloc entry @ rtab=%p (offset=%d), adr=%04x, type=%02x, seg=%d\n",rtab-1, *(rtab-1), adr, type, seg);*/ + rtab++; + switch(type) { + case 0x80: + old = buf[adr] + 256*buf[adr+1]; + new = old + reldiff(seg); + buf[adr] = new & 255; + buf[adr+1] = (new>>8)&255; + break; + case 0x40: + old = buf[adr]*256 + *rtab; + new = old + reldiff(seg); + buf[adr] = (new>>8)&255; + *rtab = new & 255; + rtab++; + break; + case 0x20: + old = buf[adr]; + new = old + reldiff(seg); + buf[adr] = new & 255; + break; + } + if(seg==0) rtab+=2; + } + } + if(adr > len) { +/* + fprintf(stderr,"reloc65: %s: Warning: relocation table entries past segment end!\n", + fp->fname); +*/ + } + return ++rtab; +} + +unsigned char *reloc_globals(unsigned char *buf, file65 *fp) { + int n, old, new, seg; + + n = buf[0] + 256*buf[1]; + buf +=2; + + while(n) { +/*printf("relocating %s, ", buf);*/ + while(*(buf++)); + seg = *buf; + old = buf[1] + 256*buf[2]; + new = old + reldiff(seg); +/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/ + buf[1] = new & 255; + buf[2] = (new>>8) & 255; + buf +=3; + n--; + } + return buf; +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sid6526/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/Makefile.am new file mode 100644 index 00000000..8b282820 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/Makefile.am @@ -0,0 +1,7 @@ + +noinst_LTLIBRARIES = libsid6526.la + +libsid6526_la_SOURCES = sid6526.cpp sid6526.h + +# Remove bad default includes +DEFAULT_INCLUDES= diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sid6526/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/Makefile.in new file mode 100644 index 00000000..ef5bdb03 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/Makefile.in @@ -0,0 +1,424 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +noinst_LTLIBRARIES = libsid6526.la + +libsid6526_la_SOURCES = sid6526.cpp sid6526.h + +# Remove bad default includes +DEFAULT_INCLUDES = +subdir = src/sid6526 +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libsid6526_la_LDFLAGS = +libsid6526_la_LIBADD = +am_libsid6526_la_OBJECTS = sid6526.lo +libsid6526_la_OBJECTS = $(am_libsid6526_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/sid6526.Plo +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libsid6526_la_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libsid6526_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/sid6526/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsid6526.la: $(libsid6526_la_OBJECTS) $(libsid6526_la_DEPENDENCIES) + $(CXXLINK) $(libsid6526_la_LDFLAGS) $(libsid6526_la_OBJECTS) $(libsid6526_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sid6526.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 $(LTLIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +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: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man 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 uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sid6526/sid6526.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/sid6526.cpp new file mode 100644 index 00000000..8737f7f0 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/sid6526.cpp @@ -0,0 +1,135 @@ +/*************************************************************************** + sid6526.cpp - description + ------------------- + begin : Wed Jun 7 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: sid6526.cpp,v $ + * Revision 1.7 2002/10/02 19:48:15 s_a_white + * Make CIA control register reflect that the timer cannot be disabled. + * + * Revision 1.6 2002/03/11 18:00:29 s_a_white + * Better mirror sidplay1s handling of random numbers. + * + * Revision 1.5 2002/03/03 22:03:49 s_a_white + * Tidy. + * + * Revision 1.4 2001/10/02 18:01:36 s_a_white + * Support for cleaned c64env. + * + * Revision 1.3 2001/09/18 02:22:37 jpaana + * Fixed include filename to lowercase + * + * Revision 1.2 2001/09/03 22:24:09 s_a_white + * New counts for timer A are correctly formed. + * + * Revision 1.1 2001/09/01 11:11:19 s_a_white + * This is the old fake6526 code required for sidplay1 environment modes. + * + ***************************************************************************/ + +#include <time.h> +#include "sidendian.h" +#include "sid6526.h" + +const char * const SID6526::credit = +{ // Optional information + "*SID6526 (SIDPlay1 Fake CIA) Emulation:\0" + "\tCopyright (C) 2001 Simon White <sidplay2@email.com>\0" +}; + +SID6526::SID6526 (c64env *env) +:m_env(*env), + m_eventContext(m_env.context ()), + rnd(0), + m_taEvent(*this) +{ + clock (0xffff); + reset (); +} + +void SID6526::reset (void) +{ + locked = false; + ta = ta_latch = m_count; + cra = 0; + rnd += time(NULL) & 0xff; + m_accessClk = 0; +} + +uint8_t SID6526::read (uint_least8_t addr) +{ + if (addr > 0x0f) + return 0; + + switch (addr) + { + case 0x04: + case 0x05: + case 0x11: + case 0x12: + rnd = rnd * 13 + 1; + return (uint8_t) (rnd >> 3); + break; + default: + return regs[addr]; + } +} + +void SID6526::write (uint_least8_t addr, uint8_t data) +{ + if (addr > 0x0f) + return; + + regs[addr] = data; + + if (locked) + return; // Stop program changing time interval + + { // Sync up timer + event_clock_t cycles; + cycles = m_eventContext.getTime (m_accessClk); + m_accessClk += cycles; + ta -= cycles; + } + + switch (addr) + { + case 0x4: endian_16lo8 (ta_latch, data); break; + case 0x5: + endian_16hi8 (ta_latch, data); + if (!(cra & 0x01)) // Reload timer if stopped + ta = ta_latch; + break; + case 0x0e: + cra = data | 0x01; + if (data & 0x10) + { + cra &= (~0x10); + ta = ta_latch; + } + m_eventContext.schedule (&m_taEvent, (event_clock_t) ta + 1); + break; + default: + break; + } +} + +void SID6526::event (void) +{ // Timer Modes + m_accessClk = m_eventContext.getTime (); + ta = ta_latch; + m_eventContext.schedule (&m_taEvent, (event_clock_t) ta + 1); + m_env.interruptIRQ (true); +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sid6526/sid6526.h b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/sid6526.h new file mode 100644 index 00000000..d92c230c --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sid6526/sid6526.h @@ -0,0 +1,84 @@ +/*************************************************************************** + sid6526.h - fake CIA timer for sidplay1 + environment modes + ------------------- + begin : Wed Jun 7 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: sid6526.h,v $ + * Revision 1.3 2002/07/20 08:34:52 s_a_white + * Remove unnecessary and pointless conts. + * + * Revision 1.2 2002/03/11 18:00:29 s_a_white + * Better mirror sidplay1s handling of random numbers. + * + * Revision 1.1 2001/09/01 11:11:19 s_a_white + * This is the old fake6526 code required for sidplay1 environment modes. + * + ***************************************************************************/ + +#ifndef _sid6526_h_ +#define _sid6526_h_ + +#include "component.h" +#include "event.h" +#include "c64env.h" + +class SID6526: public component +{ +private: + + static const char * const credit; + + c64env &m_env; + EventContext &m_eventContext; + event_clock_t m_accessClk; + + uint8_t regs[0x10]; + uint8_t cra; // Timer A Control Register + uint_least16_t ta_latch; + uint_least16_t ta; // Current count (reduces to zero) + uint_least32_t rnd; + uint_least16_t m_count; + bool locked; // Prevent code changing CIA. + + class TaEvent: public Event + { + private: + SID6526 &m_cia; + void event (void) {m_cia.event ();} + + public: + TaEvent (SID6526 &cia) + :Event("CIA Timer A"), + m_cia(cia) {} + } m_taEvent; + +public: + SID6526 (c64env *env); + + //Common: + void reset (void); + uint8_t read (uint_least8_t addr); + void write (uint_least8_t addr, uint8_t data); + const char *credits (void) {return credit;} + const char *error (void) {return "";} + + // Specific: + void event (void); + void clock (uint_least16_t count) { m_count = count; } + void lock () { locked = true; } +}; + +#endif // _sid6526_h_ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidplay2.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidplay2.cpp new file mode 100644 index 00000000..e3535ddb --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidplay2.cpp @@ -0,0 +1,131 @@ +/*************************************************************************** + sidplayer.cpp - Wrapper to hide private + header files (see below) + ------------------- + begin : Fri Jun 9 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: sidplay2.cpp,v $ + * Revision 1.15 2002/03/04 19:05:49 s_a_white + * Fix C++ use of nothrow. + * + * Revision 1.14 2001/12/13 08:28:08 s_a_white + * Added namespace support to fix problems with xsidplay. + * + * Revision 1.13 2001/12/11 19:24:15 s_a_white + * More GCC3 Fixes. + * + * Revision 1.12 2001/09/17 19:03:58 s_a_white + * 2.1.0 interface stabalisation. + * + * Revision 1.11 2001/09/01 11:16:12 s_a_white + * Renamed configure to config. + * + * Revision 1.10 2001/07/25 17:01:13 s_a_white + * Support for new configuration interface. + * + * Revision 1.9 2001/07/14 16:46:16 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.8 2001/07/14 12:57:38 s_a_white + * Added credits and debug functions. Removed external filter. + * + * Revision 1.7 2001/03/21 22:31:22 s_a_white + * Filter redefinition support. + * + * Revision 1.6 2001/03/01 23:46:37 s_a_white + * Support for sample mode to be selected at runtime. + * + * Revision 1.5 2001/02/21 21:49:21 s_a_white + * Now uses new player::getErrorString function. + * + * Revision 1.4 2001/02/13 21:32:35 s_a_white + * Windows DLL export fix. + * + * Revision 1.3 2001/02/07 20:57:08 s_a_white + * New SID_EXPORT define. Supports SidTune now. + * + * Revision 1.2 2001/01/23 21:26:28 s_a_white + * Only way to load a tune now is by passing in a sidtune object. This is + * required for songlength database support. + * + * Revision 1.1 2000/12/12 19:14:44 s_a_white + * Library wrapper. + * + ***************************************************************************/ + +//--------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------- +// Redirection to private version of sidplayer (This method is called Cheshire Cat) +// [ms: which is J. Carolan's name for a degenerate 'bridge'] +// This interface can be directly replaced with a libsidplay1 or C interface wrapper. +//--------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------- + +#include "config.h" +#include "player.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif + +sidplay2::sidplay2 () +#ifdef HAVE_EXCEPTIONS +: sidplayer (*(new(std::nothrow) SIDPLAY2_NAMESPACE::Player)) +#else +: sidplayer (*(new SIDPLAY2_NAMESPACE::Player)) +#endif +{ +} + +sidplay2::~sidplay2 () +{ if (&sidplayer) delete &sidplayer; } + +int sidplay2::config (const sid2_config_t &cfg) +{ return sidplayer.config (cfg); } + +const sid2_config_t &sidplay2::config (void) const +{ return sidplayer.config (); } + +void sidplay2::stop (void) +{ sidplayer.stop (); } + +void sidplay2::pause (void) +{ sidplayer.pause (); } + +uint_least32_t sidplay2::play (void *buffer, uint_least32_t length) +{ return sidplayer.play (buffer, length); } + +int sidplay2::load (SidTune *tune) +{ return sidplayer.load (tune); } + +const sid2_info_t &sidplay2::info () const +{ return sidplayer.info (); } + +uint_least32_t sidplay2::time (void) const +{ return sidplayer.time (); } + +uint_least32_t sidplay2::mileage (void) const +{ return sidplayer.mileage (); } + +const char *sidplay2::error (void) const +{ return sidplayer.error (); } + +int sidplay2::fastForward (uint percent) +{ return sidplayer.fastForward (percent); } + +void sidplay2::debug (bool enable) +{ sidplayer.debug (enable); } + +sid2_player_t sidplay2::state (void) const +{ return sidplayer.state (); } diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/IconInfo.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/IconInfo.cpp new file mode 100644 index 00000000..30df20b4 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/IconInfo.cpp @@ -0,0 +1,468 @@ +/* + * /home/ms/files/source/libsidtune/RCS/IconInfo.cpp,v + * + * Amiga icon tooltype PlaySID file format (.info) support. + * + * This is a derived work, courtesy of Peter Kunath, who has + * provided an examplary source code to examine an Amiga icon file. + * + * It has been ported and heavily modified to suit certain + * requirements. This replaces the old code, which was simply + * scanning input data for a first, presumedly constant, Id string. + * This code does not require the default tool to serve as a + * constant Id by containing "SID:PlaySID". + * + * 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 "config.h" +#include "SidTune.h" +#include "SmartPtr.h" +#include "SidTuneTools.h" +#include "sidendian.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif +#include <string.h> +#include <sstream> + +// Amiga Workbench specific structures. + +struct Border +{ + uint8_t LeftEdge[2]; // uint_least16_t; initial offsets from the origin + uint8_t TopEdge[2]; // uint_least16_t + uint8_t FrontPen, BackPen; // pens numbers for rendering + uint8_t DrawMode; // mode for rendering + uint8_t Count; // number of XY pairs + uint8_t pXY[4]; // int_least16_t *XY; vector coordinate pairs rel to LeftTop + uint8_t pNextBorder[4]; // Border *NextBorder; pointer to any other Border too +}; + +struct Image +{ + uint8_t LeftEdge[2]; // uint_least16_t; starting offset relative to some origin + uint8_t TopEdge[2]; // uint_least16_t; starting offsets relative to some origin + uint8_t Width[2]; // uint_least16_t; pixel size (though data is word-aligned) + uint8_t Height[2]; // uint_least16_t + uint8_t Depth[2]; // uint_least16_t; >= 0, for images you create + uint8_t pImageData[4]; // uint_least16_t *ImageData; pointer to the actual word-aligned bits + uint8_t PlanePick, PlaneOnOff; + uint8_t pNextImage[4]; // Image *NextImage; +}; + +struct Gadget +{ + uint8_t pNextGadget[4]; // Gadget *NextGadget; next gadget in the list + uint8_t LeftEdge[2]; // uint_least16_t; "hit box" of gadget + uint8_t TopEdge[2]; // uint_least16_t + uint8_t Width[2]; // uint_least16_t; "hit box" of gadget + uint8_t Height[2]; // uint_least16_t + uint8_t Flags[2]; // uint_least16_t; see below for list of defines + uint8_t Activation[2]; // uint_least16_t + uint8_t GadgetType[2]; // uint_least16_t; see below for defines + uint8_t pGadgetRender[4]; // Image *GadgetRender; + uint8_t pSelectRender[4]; // Image *SelectRender; + uint8_t pGadgetText[4]; // void *GadgetText; + uint8_t MutualExclude[4]; // udword + uint8_t pSpecialInfo[4]; // void *SpecialInfo; + uint8_t GadgetID[2]; // uint_least16_t + uint8_t UserData[4]; // udword; ptr to general purpose User data +}; + +struct DiskObject +{ + uint8_t Magic[2]; // uint_least16_t; a magic num at the start of the file + uint8_t Version[2]; // uint_least16_t; a version number, so we can change it + struct Gadget Gadget; // a copy of in core gadget + uint8_t Type; + uint8_t PAD_BYTE; // Pad it out to the next word boundry + uint8_t pDefaultTool[4]; // char *DefaultTool; + uint8_t ppToolTypes[4]; // char **ToolTypes; + uint8_t CurrentX[4]; // udword + uint8_t CurrentY[4]; // udword + uint8_t pDrawerData[4]; // char *DrawerData; + uint8_t pToolWindow[4]; // char *ToolWindow; only applies to tools + uint8_t StackSize[4]; // udword; only applies to tools +}; + + +// A magic number, not easily impersonated. +#define WB_DISKMAGIC 0xE310 +// Our current version number. +#define WB_DISKVERSION 1 +// Our current revision number. +#define WB_DISKREVISION 1 +// I only use the lower 8 bits of Gadget.UserData for the revision #. +#define WB_DISKREVISIONMASK 0xFF + +// The Workbench object types. +#define WB_DISK 1 +#define WB_DRAWER 2 +#define WB_TOOL 3 +#define WB_PROJECT 4 +#define WB_GARBAGE 5 +#define WB_DEVICE 6 +#define WB_KICK 7 +#define WB_APPICON 8 + +// --- Gadget.Flags values --- +// Combinations in these bits describe the highlight technique to be used. +#define GFLG_GADGHIGHBITS 0x0003 +// Complement the select box. +#define GFLG_GADGHCOMP 0x0000 +// Draw a box around the image. +#define GFLG_GADGHBOX 0x0001 +// Blast in this alternate image. +#define GFLG_GADGHIMAGE 0x0002 +// Don't highlight. +#define GFLG_GADGHNONE 0x0003 +// Set if GadgetRender and SelectRender point to an Image structure, +// clear if they point to Border structures. +#define GFLG_GADGIMAGE 0x0004 + +const char _sidtune_txt_format[] = "Raw plus PlaySID icon tooltype file (INFO)"; + +const char _sidtune_keyword_id[] = "SID:PLAYSID"; +const char _sidtune_keyword_address[] = "ADDRESS="; +const char _sidtune_keyword_songs[] = "SONGS="; +const char _sidtune_keyword_speed[] = "SPEED="; +const char _sidtune_keyword_name[] = "NAME="; +const char _sidtune_keyword_author[] = "AUTHOR="; +const char _sidtune_keyword_copyright[] = "COPYRIGHT="; +const char _sidtune_keyword_musPlayer[] = "SIDSONG=YES"; + +const char _sidtune_txt_noMemError[] = "ERROR: Not enough free memory"; +const char _sidtune_txt_corruptError[] = "ERROR: Info file is incomplete or corrupt"; +const char _sidtune_txt_noStringsError[] = "ERROR: Info file does not contain required strings"; +const char _sidtune_txt_dataCorruptError[] = "ERROR: C64 data file is corrupt"; +#if defined(SIDTUNE_REJECT_UNKNOWN_FIELDS) +const char _sidtune_txt_chunkError[] = "ERROR: Invalid tooltype information in icon file"; +#endif + +const uint_least16_t safeBufferSize = 64; // for string comparison, stream parsing + + +bool SidTune::INFO_fileSupport(const void* dataBuffer, uint_least32_t dataLength, + const void* infoBuffer, uint_least32_t infoLength) +{ + // Require a first minimum safety size. + uint_least32_t minSize = 1+sizeof(struct DiskObject); + if (infoLength < minSize) + return( false ); + + const DiskObject *dobject = (const DiskObject *)infoBuffer; + + // Require Magic_Id in the first two bytes of the file. + if ( endian_16(dobject->Magic[0],dobject->Magic[1]) != WB_DISKMAGIC ) + return false; + + // Only version 1.x supported. + if ( endian_16(dobject->Version[0],dobject->Version[1]) != WB_DISKVERSION ) + return false; + + // A PlaySID icon must be of type project. + if ( dobject->Type != WB_PROJECT ) + return false; + + uint i; // general purpose index variable + + // We want to skip a possible Gadget Image item. + const char *icon = (const char*)infoBuffer + sizeof(DiskObject); + + if ( (endian_16(dobject->Gadget.Flags[0],dobject->Gadget.Flags[1]) & GFLG_GADGIMAGE) == 0) + { + // Calculate size of gadget borders (vector image). + + if (dobject->Gadget.pGadgetRender[0] | + dobject->Gadget.pGadgetRender[1] | + dobject->Gadget.pGadgetRender[2] | + dobject->Gadget.pGadgetRender[3]) // border present? + { + // Require another minimum safety size. + minSize += sizeof(struct Border); + if (infoLength < minSize) + return( false ); + + const Border *brd = (const Border *)icon; + icon += sizeof(Border); + icon += brd->Count * (2+2); // pair of uint_least16_t + } + + if (dobject->Gadget.pSelectRender[0] | + dobject->Gadget.pSelectRender[1] | + dobject->Gadget.pSelectRender[2] | + dobject->Gadget.pSelectRender[3]) // alternate border present? + { + // Require another minimum safety size. + minSize += sizeof(Border); + if (infoLength < minSize) + return( false ); + + const Border *brd = (const Border *)icon; + icon += sizeof(Border); + icon += brd->Count * (2+2); // pair of uint_least16_t + } + } + else + { + // Calculate size of gadget images (bitmap image). + + if (dobject->Gadget.pGadgetRender[0] | + dobject->Gadget.pGadgetRender[1] | + dobject->Gadget.pGadgetRender[2] | + dobject->Gadget.pGadgetRender[3]) // image present? + { + // Require another minimum safety size. + minSize += sizeof(Image); + if (infoLength < minSize) + return( false ); + + const Image *img = (const Image *)icon; + icon += sizeof(Image); + + uint_least32_t imgsize = 0; + for(i=0;i<endian_16(img->Depth[0],img->Depth[1]);i++) + { + if ( (img->PlanePick & (1<<i)) != 0) + { + // NOTE: Intuition relies on PlanePick to know how many planes + // of data are found in ImageData. There should be no more + // '1'-bits in PlanePick than there are planes in ImageData. + imgsize++; + } + } + + imgsize *= ((endian_16(img->Width[0],img->Width[1])+15)/16)*2; // bytes per line + imgsize *= endian_16(img->Height[0],img->Height[1]); // bytes per plane + + icon += imgsize; + } + + if (dobject->Gadget.pSelectRender[0] | + dobject->Gadget.pSelectRender[1] | + dobject->Gadget.pSelectRender[2] | + dobject->Gadget.pSelectRender[3]) // alternate image present? + { + // Require another minimum safety size. + minSize += sizeof(Image); + if (infoLength < minSize) + return( false ); + + const Image *img = (const Image *)icon; + icon += sizeof(Image); + + uint_least32_t imgsize = 0; + for(i=0;i<endian_16(img->Depth[0],img->Depth[1]);i++) + { + if ( (img->PlanePick & (1<<i)) != 0) + { + // NOTE: Intuition relies on PlanePick to know how many planes + // of data are found in ImageData. There should be no more + // '1'-bits in PlanePick than there are planes in ImageData. + imgsize++; + } + } + + imgsize *= ((endian_16(img->Width[0],img->Width[1])+15)/16)*2; // bytes per line + imgsize *= endian_16(img->Height[0],img->Height[1]); // bytes per plane + icon += imgsize; + } + } + + // Here use a smart pointer to prevent access violation errors. + SmartPtr_sidtt<const char> spTool((const char*)icon,infoLength-(uint_least32_t)(icon-(const char*)infoBuffer)); + if ( !spTool ) + { + info.formatString = _sidtune_txt_corruptError; + return false; + } + + // A separate safe buffer is used for each tooltype string. +#ifdef HAVE_EXCEPTIONS + SmartPtr_sidtt<char> spCmpBuf(new(std::nothrow) char[safeBufferSize],safeBufferSize,true); +#else + SmartPtr_sidtt<char> spCmpBuf(new char[safeBufferSize],safeBufferSize,true); +#endif + if ( !spCmpBuf ) + { + info.formatString = _sidtune_txt_noMemError; + return false; + } + +#ifndef SID_HAVE_BAD_COMPILER + char* cmpBuf = spCmpBuf.tellBegin(); +#else + // This should not be necessary, but for some reason + // Microsoft Visual C++ says spCmpBuf is const... + char* cmpBuf = (char*) spCmpBuf.tellBegin(); +#endif + + // Skip default tool. + spTool += endian_32(spTool[0],spTool[1],spTool[2],spTool[3]) + 4; + + // Defaults. + fileOffset = 0; // no header in separate data file + info.sidChipBase1 = 0xd400; + info.sidChipBase2 = 0; + info.musPlayer = false; + info.numberOfInfoStrings = 0; + uint_least32_t oldStyleSpeed = 0; + + // Flags for required entries. + bool hasAddress = false, + hasName = false, + hasAuthor = false, + hasCopyright = false, + hasSongs = false, + hasSpeed = false, + hasUnknownChunk = false; + + // Calculate number of tooltype strings. + i = (endian_32(spTool[0],spTool[1],spTool[2],spTool[3])/4) - 1; + spTool += 4; // skip size info + + while( i-- > 0 ) + { + // Get length of this tool. + uint_least32_t toolLen = endian_32(spTool[0],spTool[1],spTool[2],spTool[3]); + spTool += 4; // skip tool length + // Copy item to safe buffer. + for ( uint ci = 0; ci < toolLen; ci++ ) + { +#ifndef SID_HAVE_BAD_COMPILER + spCmpBuf[ci] = spTool[ci]; +#else + // This should not be necessary, but for some reason + // Microsoft Visual C++ says spCmpBuf is const... + (*((char*) (&spCmpBuf[ci]))) = (char) spTool[ci]; +#endif + } + if ( !(spTool&&spCmpBuf) ) + { + return false; + } + + // Now check all possible keywords. + if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_address) == 0 ) + { + std::string s (cmpBuf + strlen(_sidtune_keyword_address), toolLen - strlen(_sidtune_keyword_address)); + std::istringstream addrIn(s); + info.loadAddr = (uint_least16_t)SidTuneTools::readHex( addrIn ); + info.initAddr = (uint_least16_t)SidTuneTools::readHex( addrIn ); + info.playAddr = (uint_least16_t)SidTuneTools::readHex( addrIn ); + if ( !addrIn ) + { + return false; + } + hasAddress = true; + } + else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_songs) == 0 ) + { + std::string s ( cmpBuf + strlen(_sidtune_keyword_songs), toolLen - strlen(_sidtune_keyword_songs)); + std::istringstream numIn(s); + if ( !numIn ) + { + return false; + } + info.songs = (uint_least16_t)SidTuneTools::readDec( numIn ); + info.startSong = (uint_least16_t)SidTuneTools::readDec( numIn ); + hasSongs = true; + } + else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_speed) == 0 ) + { + std::string s (cmpBuf + strlen(_sidtune_keyword_speed), toolLen - strlen(_sidtune_keyword_speed)); + std::istringstream speedIn (s); + if ( !speedIn ) + { + return false; + } + oldStyleSpeed = SidTuneTools::readHex(speedIn); + hasSpeed = true; + } + else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_name) == 0 ) + { + strncpy( &infoString[0][0], cmpBuf + strlen(_sidtune_keyword_name), 31 ); + info.infoString[0] = &infoString[0][0]; + hasName = true; + } + else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_author) == 0 ) + { + strncpy( &infoString[1][0], cmpBuf + strlen(_sidtune_keyword_author), 31 ); + info.infoString[1] = &infoString[1][0]; + hasAuthor = true; + } + else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_copyright) == 0 ) + { + strncpy( &infoString[2][0], cmpBuf + strlen(_sidtune_keyword_copyright), 31 ); + info.infoString[2] = &infoString[2][0]; + hasCopyright = true; + } + else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_musPlayer) == 0 ) + { + info.musPlayer = true; + } + else + { + hasUnknownChunk = true; +#if defined(SIDTUNE_REJECT_UNKNOWN_FIELDS) + info.formatString = _sidtune_txt_chunkError; + return false; +#endif + } + // Skip to next tool. + spTool += toolLen; + } + + // Collected ``required'' information complete ? + if ( hasAddress && hasName && hasAuthor && hasCopyright && hasSongs && hasSpeed ) + { + // Create the speed/clock setting table. + convertOldStyleSpeedToTables(oldStyleSpeed); + if (( info.loadAddr == 0 ) && ( dataLength != 0 )) + { + SmartPtr_sidtt<const uint_least8_t> spDataBuf((const uint_least8_t*)dataBuffer,dataLength); + spDataBuf += fileOffset; + info.loadAddr = endian_16(spDataBuf[1],spDataBuf[0]); + if ( !spDataBuf ) + { + info.formatString = _sidtune_txt_dataCorruptError; + return false; + } + fileOffset += 2; + } + if ( info.initAddr == 0 ) + { + info.initAddr = info.loadAddr; + } + info.numberOfInfoStrings = 3; + // We finally accept the input data. + info.formatString = _sidtune_txt_format; + return true; + } + else if ( hasAddress || hasName || hasAuthor || hasCopyright || hasSongs || hasSpeed ) + { + // Something is missing (or damaged?). + info.formatString = _sidtune_txt_corruptError; + return false; + } + else + { + // No PlaySID conform info strings. + info.formatString = _sidtune_txt_noStringsError; + return false; + } +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/InfoFile.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/InfoFile.cpp new file mode 100644 index 00000000..0c03b23c --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/InfoFile.cpp @@ -0,0 +1,398 @@ +/* + * /home/ms/files/source/libsidtune/RCS/InfoFile.cpp,v + * + * SIDPLAY INFOFILE format support. + * + * 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 "config.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif +#include <iostream> +#include <iomanip> +#include <sstream> +#include <ctype.h> +#include <string.h> + +#include "SidTune.h" +#include "SidTuneTools.h" +#include "sidendian.h" + + +const char text_format[] = "Raw plus SIDPLAY ASCII text file (SID)"; + +const char text_truncatedError[] = "ERROR: SID file is truncated"; +const char text_noMemError[] = "ERROR: Not enough free memory"; + +const char keyword_id[] = "SIDPLAY INFOFILE"; + +const char keyword_name[] = "NAME="; // No white-space characters +const char keyword_author[] = "AUTHOR="; // in these keywords, because +const char keyword_copyright[] = "COPYRIGHT="; // we want to use a white-space +const char keyword_released[] = "RELEASED="; // we want to use a white-space +const char keyword_address[] = "ADDRESS="; // eating string stream to +const char keyword_songs[] = "SONGS="; // parse most of the header. +const char keyword_speed[] = "SPEED="; +const char keyword_musPlayer[] = "SIDSONG=YES"; +const char keyword_reloc[] = "RELOC="; +const char keyword_clock[] = "CLOCK="; +const char keyword_sidModel[] = "SIDMODEL="; +const char keyword_compatibility[] = "COMPATIBILITY="; + +const uint_least16_t sidMinFileSize = 1+sizeof(keyword_id); // Just to avoid a first segm.fault. +const uint_least16_t parseChunkLen = 80; // Enough for all keywords incl. their values. + + +bool SidTune::SID_fileSupport(const void* dataBuffer, uint_least32_t dataBufLen, + const void* sidBuffer, uint_least32_t sidBufLen) +{ + // Make sure SID buffer pointer is not zero. + // Check for a minimum file size. If it is smaller, we will not proceed. + if ((sidBuffer==0) || (sidBufLen<sidMinFileSize)) + { + return false; + } + + const char* pParseBuf = (const char*)sidBuffer; + // First line has to contain the exact identification string. + if ( SidTuneTools::myStrNcaseCmp( pParseBuf, keyword_id ) != 0 ) + { + return false; + } + else + { + // At least the ID was found, so set a default error message. + info.formatString = text_truncatedError; + + // Defaults. + fileOffset = 0; // no header in separate data file + info.sidChipBase1 = 0xd400; + info.sidChipBase2 = 0; + info.musPlayer = false; + info.numberOfInfoStrings = 0; + uint_least32_t oldStyleSpeed = 0; + + // Flags for required entries. + bool hasAddress = false, + hasName = false, + hasAuthor = false, + hasReleased = false, + hasSongs = false, + hasSpeed = false; + + // Using a temporary instance of an input string chunk. +#ifdef HAVE_EXCEPTIONS + char* pParseChunk = new(std::nothrow) char[parseChunkLen+1]; +#else + char* pParseChunk = new char[parseChunkLen+1]; +#endif + if ( pParseChunk == 0 ) + { + info.formatString = text_noMemError; + return false; + } + + // Parse as long we have not collected all ``required'' entries. + //while ( !hasAddress || !hasName || !hasAuthor || !hasCopyright + // || !hasSongs || !hasSpeed ) + + // Above implementation is wrong, we need to get all known + // fields and then check if all ``required'' ones were found. + for (;;) + { + // Skip to next line. Leave loop, if none. + if (( pParseBuf = SidTuneTools::returnNextLine( pParseBuf )) == 0 ) + { + break; + } + // And get a second pointer to the following line. + const char* pNextLine = SidTuneTools::returnNextLine( pParseBuf ); + uint_least32_t restLen; + if ( pNextLine != 0 ) + { + // Calculate number of chars between current pos and next line. + restLen = (uint_least32_t)(pNextLine - pParseBuf); + } + else + { + // Calculate number of chars between current pos and end of buf. + restLen = sidBufLen - (uint_least32_t)(pParseBuf - (char*)sidBuffer); + } + // Create whitespace eating (!) input string stream. + + std::string s (pParseBuf, restLen); + + std::istringstream parseStream (s); + // A second one just for copying. + std::istringstream parseCopyStream (s); + if ( !parseStream || !parseCopyStream ) + { + break; + } + // Now copy the next X characters except white-spaces. + for ( uint_least16_t i = 0; i < parseChunkLen; i++ ) + { + char c; + parseCopyStream >> c; + pParseChunk[i] = c; + } + pParseChunk[parseChunkLen]=0; + // Now check for the possible keywords. + // ADDRESS + if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_address ) == 0 ) + { + SidTuneTools::skipToEqu( parseStream ); + info.loadAddr = (uint_least16_t)SidTuneTools::readHex( parseStream ); + if ( !parseStream ) + break; + info.initAddr = (uint_least16_t)SidTuneTools::readHex( parseStream ); + if ( !parseStream ) + break; + info.playAddr = (uint_least16_t)SidTuneTools::readHex( parseStream ); + hasAddress = true; + } + // NAME + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_name ) == 0 ) + { + SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[0][0],SIDTUNE_MAX_CREDIT_STRLEN); + info.infoString[0] = &infoString[0][0]; + hasName = true; + } + // AUTHOR + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_author ) == 0 ) + { + SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[1][0],SIDTUNE_MAX_CREDIT_STRLEN); + info.infoString[1] = &infoString[1][0]; + hasAuthor = true; + } + // COPYRIGHT + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_copyright ) == 0 ) + { + SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[2][0],SIDTUNE_MAX_CREDIT_STRLEN); + info.infoString[2] = &infoString[2][0]; + hasReleased = true; + } + // RELEASED + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_released ) == 0 ) + { + SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[2][0],SIDTUNE_MAX_CREDIT_STRLEN); + info.infoString[2] = &infoString[2][0]; + hasReleased = true; + } + // SONGS + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_songs ) == 0 ) + { + SidTuneTools::skipToEqu( parseStream ); + info.songs = (uint_least16_t)SidTuneTools::readDec( parseStream ); + info.startSong = (uint_least16_t)SidTuneTools::readDec( parseStream ); + hasSongs = true; + } + // SPEED + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_speed ) == 0 ) + { + SidTuneTools::skipToEqu( parseStream ); + oldStyleSpeed = SidTuneTools::readHex(parseStream); + hasSpeed = true; + } + // SIDSONG + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_musPlayer ) == 0 ) + { + info.musPlayer = true; + } + // RELOC + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_reloc ) == 0 ) + { + info.relocStartPage = (uint_least8_t)SidTuneTools::readHex( parseStream ); + if ( !parseStream ) + break; + info.relocPages = (uint_least8_t)SidTuneTools::readHex( parseStream ); + } + // CLOCK + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_clock ) == 0 ) + { + char clock[8]; + SidTuneTools::copyStringValueToEOL(pParseBuf,clock,sizeof(clock)); + if ( SidTuneTools::myStrNcaseCmp( clock, "UNKNOWN" ) == 0 ) + info.clockSpeed = SIDTUNE_CLOCK_UNKNOWN; + else if ( SidTuneTools::myStrNcaseCmp( clock, "PAL" ) == 0 ) + info.clockSpeed = SIDTUNE_CLOCK_PAL; + else if ( SidTuneTools::myStrNcaseCmp( clock, "NTSC" ) == 0 ) + info.clockSpeed = SIDTUNE_CLOCK_NTSC; + else if ( SidTuneTools::myStrNcaseCmp( clock, "ANY" ) == 0 ) + info.clockSpeed = SIDTUNE_CLOCK_ANY; + } + // SIDMODEL + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_sidModel ) == 0 ) + { + char model[8]; + SidTuneTools::copyStringValueToEOL(pParseBuf,model,sizeof(model)); + if ( SidTuneTools::myStrNcaseCmp( model, "UNKNOWN" ) == 0 ) + info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN; + else if ( SidTuneTools::myStrNcaseCmp( model, "6581" ) == 0 ) + info.sidModel = SIDTUNE_SIDMODEL_6581; + else if ( SidTuneTools::myStrNcaseCmp( model, "8580" ) == 0 ) + info.sidModel = SIDTUNE_SIDMODEL_8580; + else if ( SidTuneTools::myStrNcaseCmp( model, "ANY" ) == 0 ) + info.sidModel = SIDTUNE_SIDMODEL_ANY; + } + // COMPATIBILITY + else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_compatibility ) == 0 ) + { + char comp[5]; + SidTuneTools::copyStringValueToEOL(pParseBuf,comp,sizeof(comp)); + if ( SidTuneTools::myStrNcaseCmp( comp, "C64" ) == 0 ) + info.compatibility = SIDTUNE_COMPATIBILITY_C64; + else if ( SidTuneTools::myStrNcaseCmp( comp, "PSID" ) == 0 ) + info.compatibility = SIDTUNE_COMPATIBILITY_PSID; + else if ( SidTuneTools::myStrNcaseCmp( comp, "R64" ) == 0 ) + info.compatibility = SIDTUNE_COMPATIBILITY_R64; + } + }; + + delete[] pParseChunk; + + // Again check for the ``required'' values. + if ( hasAddress || hasName || hasAuthor || hasReleased || hasSongs || hasSpeed ) + { + // Check reserved fields to force real c64 compliance + if (info.compatibility == SIDTUNE_COMPATIBILITY_R64) + { + if (checkRealC64Info (oldStyleSpeed) == false) + return false; + } + // Create the speed/clock setting table. + convertOldStyleSpeedToTables(oldStyleSpeed, info.clockSpeed); + // loadAddr = 0 means, the address is stored in front of the C64 data. + // We cannot verify whether the dataBuffer contains valid data. + // All we want to know is whether the SID buffer is valid. + // If data is present, we access it (here to get the C64 load address). + if (info.loadAddr==0 && (dataBufLen>=(fileOffset+2)) && dataBuffer!=0) + { + const uint8_t* pDataBufCp = (const uint8_t*)dataBuffer + fileOffset; + info.loadAddr = endian_16( *(pDataBufCp + 1), *pDataBufCp ); + fileOffset += 2; // begin of data + } + // Keep compatibility to PSID/SID. + if ( info.initAddr == 0 ) + { + info.initAddr = info.loadAddr; + } + info.numberOfInfoStrings = 3; + // We finally accept the input data. + info.formatString = text_format; + return true; + } + else + { + // Something is missing (or damaged ?). + // Error string set above. + return false; + } + } +} + + +bool SidTune::SID_fileSupportSave( std::ofstream& toFile ) +{ + toFile << keyword_id << std::endl + << keyword_address << std::hex << std::setw(4) + << std::setfill('0') << 0 << ',' + << std::hex << std::setw(4) << info.initAddr << "," + << std::hex << std::setw(4) << info.playAddr << std::endl + << keyword_songs << std::dec << (int)info.songs << "," + << (int)info.startSong << std::endl; + + uint_least32_t oldStyleSpeed = 0; + int maxBugSongs = ((info.songs <= 32) ? info.songs : 32); + for (int s = 0; s < maxBugSongs; s++) + { + if (songSpeed[s] == SIDTUNE_SPEED_CIA_1A) + { + oldStyleSpeed |= (1<<s); + } + } + + toFile + << keyword_speed << std::hex << std::setw(8) + << oldStyleSpeed << std::endl + << keyword_name << info.infoString[0] << std::endl + << keyword_author << info.infoString[1] << std::endl + << keyword_released << info.infoString[2] << std::endl; + if ( info.musPlayer ) + { + toFile << keyword_musPlayer << std::endl; + } + if ( info.relocStartPage ) + { + toFile + << keyword_reloc << std::setfill('0') + << std::hex << std::setw(2) << (int) info.relocStartPage << "," + << std::hex << std::setw(2) << (int) info.relocPages << std::endl; + } + if ( info.clockSpeed != SIDTUNE_CLOCK_UNKNOWN ) + { + toFile << keyword_clock; + switch (info.clockSpeed) + { + case SIDTUNE_CLOCK_PAL: + toFile << "PAL"; + break; + case SIDTUNE_CLOCK_NTSC: + toFile << "NTSC"; + break; + case SIDTUNE_CLOCK_ANY: + toFile << "ANY"; + break; + } + toFile << std::endl; + } + if ( info.sidModel != SIDTUNE_SIDMODEL_UNKNOWN ) + { + toFile << keyword_sidModel; + switch (info.sidModel) + { + case SIDTUNE_SIDMODEL_6581: + toFile << "6581"; + break; + case SIDTUNE_SIDMODEL_8580: + toFile << "8580"; + break; + case SIDTUNE_SIDMODEL_ANY: + toFile << "ANY"; + break; + } + toFile << std::endl; + } + if ( info.compatibility == SIDTUNE_COMPATIBILITY_PSID ) + { + toFile << keyword_compatibility << "C64" << std::endl; + } + else if ( info.compatibility == SIDTUNE_COMPATIBILITY_R64 ) + { + toFile << keyword_compatibility << "R64" << std::endl; + } + + if ( !toFile ) + { + return false; + } + else + { + return true; + } +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/MUS.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/MUS.cpp new file mode 100644 index 00000000..16ea8fe9 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/MUS.cpp @@ -0,0 +1,681 @@ +/* + * /home/ms/files/source/libsidtune/RCS/MUS.cpp,v + * + * Sidplayer and Stereo Sidplayer format support. + * + * 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 <string.h> + +#include "config.h" +#include "SidTuneCfg.h" +#include "SidTune.h" +#include "sidendian.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif + +static const char _sidtune_txt_format_mus[] = "C64 Sidplayer format (MUS)"; +static const char _sidtune_txt_format_str[] = "C64 Stereo Sidplayer format (MUS+STR)"; +static const char _sidtune_txt_notEnoughMemory[] = "ERROR: Not enough free memory"; +static const char _sidtune_txt_sizeExceeded[] = "ERROR: Total file size too large"; + +static const uint_least16_t SIDTUNE_MUS_HLT_CMD = 0x14F; + +static const uint_least16_t SIDTUNE_MUS_DATA_ADDR = 0x0900; +static const uint_least16_t SIDTUNE_SID1_BASE_ADDR = 0xd400; +static const uint_least16_t SIDTUNE_SID2_BASE_ADDR = 0xd500; + +bool SidTune::MUS_fileSupport(Buffer_sidtt<const uint8_t>& musBuf, + Buffer_sidtt<const uint8_t>& strBuf) +{ + // Clear info strings. + for (int i = 0; i < SIDTUNE_MAX_CREDIT_STRINGS; i++) + infoString[i][0] = 0; + + uint_least32_t voice3Index; + if ( !MUS_detect(musBuf.get(),musBuf.len(),voice3Index) ) + return false; + + // Voice3Index now is offset to text lines (uppercase Pet-strings). + SmartPtr_sidtt<const uint8_t> spPet(musBuf.get(),musBuf.len()); + spPet += voice3Index; + { + for ( int line = 0; line < 5; line++ ) + { + MUS_decodePetLine(spPet,infoString[line]); + info.infoString[line] = infoString[line]; + } + } + info.numberOfInfoStrings = 5; + + info.loadAddr = SIDTUNE_MUS_DATA_ADDR; + info.sidChipBase1 = SIDTUNE_SID1_BASE_ADDR; + info.songs = (info.startSong = 1); + info.musPlayer = true; + + songSpeed[0] = SIDTUNE_SPEED_CIA_1A; +#ifdef SIDTUNE_PSID2NG + clockSpeed[0] = SIDTUNE_CLOCK_ANY; +#endif + fileOffset = 2; // data after load address + + if ( !strBuf.isEmpty() ) + { + if ( !MUS_detect(strBuf.get(),strBuf.len(),voice3Index) ) + return false; + + // Voice3Index now is offset to text lines (uppercase Pet-strings). + SmartPtr_sidtt<const uint8_t> spPet(strBuf.get(),strBuf.len()); + spPet += voice3Index; + for ( int line = 5; line < 10; line++ ) + { + MUS_decodePetLine(spPet,infoString[line]); + info.infoString[line] = infoString[line]; + } + info.numberOfInfoStrings += 5; + + info.sidChipBase2 = SIDTUNE_SID2_BASE_ADDR; + info.formatString = _sidtune_txt_format_str; + } + else + { + info.sidChipBase2 = 0; + info.formatString = _sidtune_txt_format_mus; + } + MUS_setPlayerAddress(); + + // Remove trailing empty lines. + const int lines = info.numberOfInfoStrings; + { + for ( int line = lines-1; line >= 0; line-- ) + { + if (strlen(info.infoString[line]) == 0) + --info.numberOfInfoStrings; + else + break; + } + } + + return true; +} + +bool SidTune::MUS_detect(const void* buffer, const uint_least32_t bufLen, + uint_least32_t& voice3Index) +{ + SmartPtr_sidtt<const uint8_t> spMus((const uint8_t*)buffer,bufLen); + // Skip load address and 3x length entry. + uint_least32_t voice1Index = (2+3*2); + // Add length of voice 1 data. + voice1Index += endian_16(spMus[3],spMus[2]); + // Add length of voice 2 data. + uint_least32_t voice2Index = voice1Index + endian_16(spMus[5],spMus[4]); + // Add length of voice 3 data. + voice3Index = voice2Index + endian_16(spMus[7],spMus[6]); + return ((endian_16(spMus[voice1Index-2],spMus[voice1Index+1-2]) == SIDTUNE_MUS_HLT_CMD) + && (endian_16(spMus[voice2Index-2],spMus[voice2Index+1-2]) == SIDTUNE_MUS_HLT_CMD) + && (endian_16(spMus[voice3Index-2],spMus[voice3Index+1-2]) == SIDTUNE_MUS_HLT_CMD) + && spMus); +} + +void SidTune::MUS_setPlayerAddress() +{ + if (info.sidChipBase2 == 0) + { + // Player #1. + info.initAddr = 0xec60; + info.playAddr = 0xec80; + } + else + { + // Player #1 + #2. + info.initAddr = 0xfc90; + info.playAddr = 0xfc96; + } +} + +static const char _sidtune_CHRtab[256] = // CHR$ conversion table (0x01 = no output) +{ + 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x20,0x21, 0x1,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x24,0x5d,0x20,0x20, + // alternative: CHR$(92=0x5c) => ISO Latin-1(0xa3) + 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f, + 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c, + // 0x80-0xFF + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d, + 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23, + 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f, + 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c, + 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d, + 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23 +}; + +int SidTune::MUS_decodePetLine(SmartPtr_sidtt<const uint8_t>& spPet, char* dest) +{ + int count = 0; + char c; + do + { + c = _sidtune_CHRtab[*spPet]; // ASCII CHR$ conversion + if ((c>=0x20) && (count<=31)) + { + dest[count++] = c; // copy to info string + } + // If character is 0x9d (left arrow key) then move back. + if ((*spPet==0x9d) && (count>=0)) + { + count--; + } + spPet++; + } + while ( !((c==0x0D)||(c==0x00)||spPet.fail()) ); + return count; +} + +static const uint8_t _sidtune_sidplayer1[] = +{ + 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x61, 0xe1, 0x60, 0x01, 0x02, 0x04, 0x00, 0x07, 0x0e, 0x02, 0x02, 0xfe, 0x02, 0x02, 0xfe, + 0xfe, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x1e, 0x18, 0x8b, 0x7e, + 0xfa, 0x06, 0xac, 0xf3, 0xe6, 0x8f, 0xf8, 0x2e, 0x86, 0x8e, 0x96, 0x9f, 0xa8, 0xb3, 0xbd, 0xc8, + 0xd4, 0xe1, 0xee, 0xfd, 0x8c, 0x78, 0x64, 0x50, 0x3c, 0x28, 0x14, 0x00, 0x00, 0x02, 0x03, 0x05, + 0x07, 0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x11, 0x12, 0x00, 0xe0, 0x00, 0x05, 0x0a, 0x0f, 0xf9, 0x00, + 0xf5, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xa0, + 0x00, 0xa9, 0x00, 0x8d, 0x00, 0xe0, 0xa2, 0x95, 0xa0, 0x42, 0xad, 0xa6, 0x02, 0xf0, 0x04, 0xa2, + 0x25, 0xa0, 0x40, 0x8e, 0x5b, 0xe1, 0x8c, 0x5c, 0xe1, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, + 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, + 0xea, 0x60, 0xa9, 0x00, 0x8d, 0x00, 0xe0, 0x86, 0x61, 0x84, 0x62, 0xa0, 0xbc, 0x99, 0x00, 0xe0, + 0x88, 0xd0, 0xfa, 0xa0, 0x72, 0x99, 0xbc, 0xe0, 0x88, 0xd0, 0xfa, 0x8d, 0x15, 0xd4, 0x8d, 0x16, + 0xd4, 0xa9, 0x08, 0x8d, 0x25, 0xe0, 0x8d, 0x17, 0xd4, 0x8d, 0x26, 0xe0, 0x8d, 0x18, 0xd4, 0xa9, + 0x90, 0x8d, 0x27, 0xe0, 0xa9, 0x60, 0x8d, 0x28, 0xe0, 0xa9, 0x0c, 0x8d, 0x29, 0xe0, 0xad, 0x5b, + 0xe1, 0x8d, 0x2d, 0xe0, 0xad, 0x5c, 0xe1, 0x8d, 0x2e, 0xe0, 0xa9, 0xff, 0x8d, 0xcc, 0xe0, 0xa9, + 0xd4, 0x85, 0x64, 0xa2, 0x02, 0xa9, 0xff, 0x9d, 0x0b, 0xe0, 0xa9, 0x01, 0x9d, 0x30, 0xe0, 0x9d, + 0x2a, 0xe0, 0x8a, 0x9d, 0x33, 0xe0, 0x9d, 0xae, 0xe0, 0xa9, 0x04, 0x9d, 0x39, 0xe0, 0xbd, 0xa8, + 0xe1, 0x9d, 0xba, 0xe0, 0xa9, 0x5b, 0x9d, 0x7e, 0xe0, 0xbd, 0x65, 0xe1, 0x85, 0x63, 0xa9, 0x00, + 0xa8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x08, 0x9d, 0x17, 0xe0, 0x9d, 0x9c, + 0xe0, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x40, 0x9d, 0x1a, 0xe0, 0x91, 0x63, 0xa9, 0x20, + 0x9d, 0x1d, 0xe0, 0xc8, 0x91, 0x63, 0xa9, 0xf5, 0x9d, 0x20, 0xe0, 0xc8, 0x91, 0x63, 0xca, 0x10, + 0xa4, 0x8a, 0xa2, 0x17, 0x9d, 0x3e, 0xe1, 0xca, 0x10, 0xfa, 0xa5, 0x61, 0x18, 0x69, 0x06, 0x85, + 0x63, 0xa9, 0x00, 0xaa, 0xa8, 0x65, 0x62, 0x85, 0x64, 0x9d, 0xab, 0xe0, 0x9d, 0xb4, 0xe0, 0xa5, + 0x63, 0x9d, 0xa8, 0xe0, 0x9d, 0xb1, 0xe0, 0x18, 0x71, 0x61, 0x85, 0x63, 0xa5, 0x64, 0xc8, 0x71, + 0x61, 0xc8, 0xe8, 0xe0, 0x03, 0xd0, 0xe0, 0xa6, 0x63, 0xa8, 0x60, 0xa9, 0x00, 0x8d, 0x04, 0xd4, + 0x8d, 0x0b, 0xd4, 0x8d, 0x12, 0xd4, 0x8d, 0x01, 0xd4, 0x8d, 0x08, 0xd4, 0x8d, 0x0f, 0xd4, 0xa9, + 0x08, 0x8d, 0x17, 0xd4, 0xad, 0x5b, 0xe1, 0x8d, 0x04, 0xdc, 0xad, 0x5c, 0xe1, 0x8d, 0x05, 0xdc, + 0x60, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x60, + 0xa9, 0x08, 0x8d, 0x00, 0xe0, 0x6c, 0x5d, 0xe1, 0xea, 0xea, 0xea, 0xad, 0x00, 0xe0, 0x30, 0xf0, + 0x09, 0x80, 0xa8, 0x29, 0x07, 0xf0, 0xee, 0xd8, 0x8c, 0x00, 0xe0, 0xea, 0xa5, 0xfb, 0x8d, 0x56, + 0xe1, 0xa5, 0xfc, 0x8d, 0x57, 0xe1, 0xa5, 0xfd, 0x8d, 0x58, 0xe1, 0xa5, 0xfe, 0x8d, 0x59, 0xe1, + 0xa5, 0xff, 0x8d, 0x5a, 0xe1, 0xad, 0x23, 0xe0, 0x18, 0x6d, 0xd9, 0xe0, 0x48, 0x29, 0x07, 0xa8, + 0xad, 0xdc, 0xe0, 0x69, 0x00, 0x85, 0xff, 0x68, 0x46, 0xff, 0x6a, 0x46, 0xff, 0x6a, 0x46, 0xff, + 0x6a, 0x18, 0x6d, 0x24, 0xe0, 0x8c, 0x15, 0xd4, 0x8d, 0x16, 0xd4, 0xad, 0x25, 0xe0, 0x8d, 0x17, + 0xd4, 0xad, 0x26, 0xe0, 0x8d, 0x18, 0xd4, 0xa9, 0xd4, 0x85, 0xfc, 0xa2, 0x00, 0xad, 0x00, 0xe0, + 0x3d, 0x62, 0xe1, 0xf0, 0x51, 0xbd, 0x65, 0xe1, 0x85, 0xfb, 0xbd, 0x0e, 0xe0, 0x18, 0x7d, 0x51, + 0xe0, 0xa8, 0xbd, 0x11, 0xe0, 0x7d, 0x54, 0xe0, 0x48, 0x98, 0x18, 0x7d, 0xcd, 0xe0, 0xa0, 0x00, + 0x91, 0xfb, 0x68, 0x7d, 0xd0, 0xe0, 0xc8, 0x91, 0xfb, 0xbd, 0x14, 0xe0, 0x18, 0x7d, 0x69, 0xe0, + 0x85, 0xff, 0xbd, 0x17, 0xe0, 0x7d, 0x6c, 0xe0, 0x48, 0xa5, 0xff, 0x18, 0x7d, 0xd3, 0xe0, 0xc8, + 0x91, 0xfb, 0x68, 0x7d, 0xd6, 0xe0, 0xc8, 0x91, 0xfb, 0xbd, 0x1d, 0xe0, 0xc8, 0xc8, 0x91, 0xfb, + 0xbd, 0x20, 0xe0, 0xc8, 0x91, 0xfb, 0xe8, 0xe0, 0x03, 0xd0, 0xa2, 0xac, 0x1a, 0xe0, 0xae, 0x1b, + 0xe0, 0xad, 0x1c, 0xe0, 0x8c, 0x04, 0xd4, 0x8e, 0x0b, 0xd4, 0x8d, 0x12, 0xd4, 0xae, 0x2d, 0xe0, + 0xac, 0x2e, 0xe0, 0x8e, 0x04, 0xdc, 0x8c, 0x05, 0xdc, 0xad, 0x1b, 0xd4, 0x8d, 0xbe, 0xe0, 0xad, + 0x1c, 0xd4, 0x8d, 0xbf, 0xe0, 0xa2, 0x00, 0xad, 0x00, 0xe0, 0x3d, 0x62, 0xe1, 0xf0, 0x10, 0x8e, + 0x2f, 0xe0, 0x20, 0x36, 0xe5, 0xad, 0x00, 0xe0, 0x29, 0x78, 0xf0, 0x03, 0x4c, 0x0c, 0xe5, 0xe8, + 0xe0, 0x03, 0xd0, 0xe3, 0xad, 0xc9, 0xe0, 0xd0, 0x52, 0xad, 0xca, 0xe0, 0x0d, 0xcb, 0xe0, 0xf0, + 0x78, 0xad, 0xdf, 0xe0, 0xd0, 0x28, 0xad, 0xca, 0xe0, 0xf0, 0x28, 0x18, 0x6d, 0xbd, 0xe0, 0xb0, + 0x07, 0xcd, 0xcc, 0xe0, 0x90, 0x60, 0xf0, 0x5e, 0xa9, 0x00, 0x8d, 0xdf, 0xe0, 0xad, 0xcb, 0xe0, + 0xf0, 0x54, 0xee, 0xdf, 0xe0, 0xad, 0xbd, 0xe0, 0xed, 0xcb, 0xe0, 0x4c, 0xb4, 0xe4, 0xad, 0xcb, + 0xe0, 0xf0, 0xd3, 0xad, 0xbd, 0xe0, 0x38, 0xed, 0xcb, 0xe0, 0xb0, 0x3a, 0xa9, 0x00, 0x8d, 0xdf, + 0xe0, 0xad, 0xca, 0xe0, 0xd0, 0x30, 0xee, 0xdf, 0xe0, 0xd0, 0x28, 0xce, 0xe0, 0xe0, 0xd0, 0x29, + 0xad, 0xdf, 0xe0, 0xd0, 0x11, 0xee, 0xdf, 0xe0, 0xad, 0xcb, 0xe0, 0xd0, 0x02, 0xa9, 0x20, 0x8d, + 0xe0, 0xe0, 0xa9, 0x00, 0xf0, 0x10, 0xce, 0xdf, 0xe0, 0xad, 0xca, 0xe0, 0xd0, 0x02, 0xa9, 0x20, + 0x8d, 0xe0, 0xe0, 0xad, 0xcc, 0xe0, 0x8d, 0xbd, 0xe0, 0xa2, 0x00, 0xbd, 0xc3, 0xe0, 0xf0, 0x44, + 0xa9, 0x00, 0x85, 0xff, 0xbc, 0xc0, 0xe0, 0xb9, 0xbd, 0xe0, 0xbc, 0xc6, 0xe0, 0xf0, 0x0e, 0x30, + 0x08, 0x0a, 0x26, 0xff, 0x88, 0xd0, 0xfa, 0xf0, 0x04, 0x4a, 0xc8, 0xd0, 0xfc, 0xbc, 0xc3, 0xe0, + 0x88, 0xd0, 0x0b, 0x9d, 0xcd, 0xe0, 0xa5, 0xff, 0x9d, 0xd0, 0xe0, 0x4c, 0x02, 0xe5, 0x88, 0xd0, + 0x0b, 0x9d, 0xd3, 0xe0, 0xa5, 0xff, 0x9d, 0xd6, 0xe0, 0x4c, 0x02, 0xe5, 0x8d, 0xd9, 0xe0, 0xa5, + 0xff, 0x8d, 0xdc, 0xe0, 0xe8, 0xe0, 0x03, 0xd0, 0xb2, 0xad, 0x00, 0xe0, 0x29, 0x7f, 0x8d, 0x00, + 0xe0, 0xad, 0x56, 0xe1, 0x85, 0xfb, 0xad, 0x57, 0xe1, 0x85, 0xfc, 0xad, 0x58, 0xe1, 0x85, 0xfd, + 0xad, 0x59, 0xe1, 0x85, 0xfe, 0xad, 0x5a, 0xe1, 0x85, 0xff, 0x6c, 0x5d, 0xe1, 0xbd, 0x60, 0xe0, + 0xd0, 0x03, 0x4c, 0x9f, 0xe6, 0x4c, 0xba, 0xe5, 0xde, 0x30, 0xe0, 0xd0, 0x03, 0x4c, 0xa0, 0xe6, + 0xbd, 0x36, 0xe0, 0x30, 0xe8, 0xd0, 0x1a, 0xbd, 0x3f, 0xe0, 0xf0, 0x05, 0xde, 0x3f, 0xe0, 0xd0, + 0x10, 0xbd, 0x39, 0xe0, 0xdd, 0x30, 0xe0, 0x90, 0x08, 0xbd, 0x1a, 0xe0, 0x29, 0xfe, 0x9d, 0x1a, + 0xe0, 0xbd, 0x42, 0xe0, 0xf0, 0x56, 0x0a, 0xbd, 0x0e, 0xe0, 0xb0, 0x1d, 0x7d, 0x45, 0xe0, 0x9d, + 0x0e, 0xe0, 0xa8, 0xbd, 0x11, 0xe0, 0x7d, 0x48, 0xe0, 0x9d, 0x11, 0xe0, 0x48, 0x98, 0xdd, 0x8d, + 0xe0, 0x68, 0xfd, 0x90, 0xe0, 0xb0, 0x1f, 0x90, 0x2e, 0xfd, 0x45, 0xe0, 0x9d, 0x0e, 0xe0, 0xbd, + 0x11, 0xe0, 0xfd, 0x48, 0xe0, 0x9d, 0x11, 0xe0, 0xbd, 0x8d, 0xe0, 0xdd, 0x0e, 0xe0, 0xbd, 0x90, + 0xe0, 0xfd, 0x11, 0xe0, 0x90, 0x11, 0xbd, 0x8d, 0xe0, 0x9d, 0x0e, 0xe0, 0xbd, 0x90, 0xe0, 0x9d, + 0x11, 0xe0, 0xa9, 0x00, 0x9d, 0x42, 0xe0, 0xbd, 0x60, 0xe0, 0xf0, 0x55, 0xbd, 0x4b, 0xe0, 0xf0, + 0x4b, 0xa0, 0x00, 0xde, 0x4e, 0xe0, 0xd0, 0x31, 0xbd, 0x51, 0xe0, 0x1d, 0x54, 0xe0, 0xd0, 0x1b, + 0xbd, 0x5d, 0xe0, 0x9d, 0x57, 0xe0, 0x9d, 0x4e, 0xe0, 0xbd, 0x4b, 0xe0, 0x0a, 0xbd, 0x5a, 0xe0, + 0x90, 0x04, 0x49, 0xff, 0x69, 0x00, 0x9d, 0x4b, 0xe0, 0xd0, 0x10, 0xbd, 0x57, 0xe0, 0x9d, 0x4e, + 0xe0, 0x98, 0x38, 0xfd, 0x4b, 0xe0, 0x9d, 0x4b, 0xe0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d, + 0x51, 0xe0, 0x9d, 0x51, 0xe0, 0x98, 0x7d, 0x54, 0xe0, 0x9d, 0x54, 0xe0, 0xbd, 0x36, 0xe0, 0x30, + 0x15, 0xbd, 0x93, 0xe0, 0xf0, 0x10, 0x18, 0x7d, 0x14, 0xe0, 0x9d, 0x14, 0xe0, 0xbd, 0x96, 0xe0, + 0x7d, 0x17, 0xe0, 0x9d, 0x17, 0xe0, 0xbd, 0x63, 0xe0, 0xf0, 0x4b, 0xa0, 0x00, 0xde, 0x66, 0xe0, + 0xd0, 0x31, 0xbd, 0x69, 0xe0, 0x1d, 0x6c, 0xe0, 0xd0, 0x1b, 0xbd, 0x72, 0xe0, 0x9d, 0x6f, 0xe0, + 0x9d, 0x66, 0xe0, 0xbd, 0x63, 0xe0, 0x0a, 0xbd, 0x75, 0xe0, 0x90, 0x04, 0x49, 0xff, 0x69, 0x00, + 0x9d, 0x63, 0xe0, 0xd0, 0x10, 0xbd, 0x6f, 0xe0, 0x9d, 0x66, 0xe0, 0x98, 0x38, 0xfd, 0x63, 0xe0, + 0x9d, 0x63, 0xe0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d, 0x69, 0xe0, 0x9d, 0x69, 0xe0, 0x98, + 0x7d, 0x6c, 0xe0, 0x9d, 0x6c, 0xe0, 0xbd, 0x36, 0xe0, 0x10, 0x03, 0x4c, 0x9f, 0xe6, 0xa0, 0x00, + 0xbd, 0xa2, 0xe0, 0xf0, 0x1c, 0x10, 0x01, 0xc8, 0x18, 0x6d, 0x23, 0xe0, 0x48, 0x29, 0x07, 0x8d, + 0x23, 0xe0, 0x68, 0x6a, 0x4a, 0x4a, 0x18, 0x79, 0xa6, 0xe1, 0x18, 0x6d, 0x24, 0xe0, 0x8d, 0x24, + 0xe0, 0x60, 0xbd, 0xa8, 0xe0, 0x85, 0xfd, 0xbd, 0xab, 0xe0, 0x85, 0xfe, 0xd0, 0x04, 0x60, 0x20, + 0x98, 0xe8, 0xad, 0x00, 0xe0, 0x3d, 0x62, 0xe1, 0xf0, 0xf4, 0xa0, 0x00, 0xb1, 0xfd, 0x85, 0xff, + 0xc8, 0xb1, 0xfd, 0xa8, 0xa5, 0xfd, 0x18, 0x69, 0x02, 0x85, 0xfd, 0x9d, 0xa8, 0xe0, 0xa5, 0xfe, + 0x69, 0x00, 0x85, 0xfe, 0x9d, 0xab, 0xe0, 0xa5, 0xff, 0x29, 0x03, 0xd0, 0xd2, 0xbd, 0x8d, 0xe0, + 0x9d, 0x0e, 0xe0, 0xbd, 0x90, 0xe0, 0x9d, 0x11, 0xe0, 0xa5, 0xff, 0x9d, 0x05, 0xe0, 0x98, 0x9d, + 0x02, 0xe0, 0x29, 0x07, 0xa8, 0xb9, 0x67, 0xe1, 0x8d, 0x6f, 0xe1, 0xbd, 0x02, 0xe0, 0x29, 0x38, + 0x4a, 0x4a, 0x4a, 0x7d, 0x81, 0xe0, 0x85, 0xfd, 0xbd, 0x02, 0xe0, 0x29, 0xc0, 0x0a, 0x2a, 0x2a, + 0xa8, 0xb9, 0x6f, 0xe1, 0x85, 0xfe, 0xbd, 0x02, 0xe0, 0x29, 0x07, 0xf0, 0x62, 0xa8, 0xb9, 0x72, + 0xe1, 0x65, 0xfe, 0x18, 0x7d, 0x84, 0xe0, 0x10, 0x05, 0x18, 0x69, 0x0c, 0xe6, 0xfd, 0xc9, 0x0c, + 0x90, 0x04, 0xe9, 0x0c, 0xc6, 0xfd, 0x85, 0xfe, 0xa8, 0xb9, 0x86, 0xe1, 0x85, 0xff, 0xb9, 0x7a, + 0xe1, 0xa4, 0xfd, 0x88, 0x30, 0x06, 0x46, 0xff, 0x6a, 0x88, 0x10, 0xfa, 0x18, 0x7d, 0x87, 0xe0, + 0x9d, 0x8d, 0xe0, 0xa5, 0xff, 0x7d, 0x8a, 0xe0, 0x9d, 0x90, 0xe0, 0xbd, 0x05, 0xe0, 0xd0, 0x03, + 0x4c, 0xa0, 0xe6, 0xbd, 0x45, 0xe0, 0x1d, 0x48, 0xe0, 0xf0, 0x16, 0xbd, 0x0e, 0xe0, 0xdd, 0x8d, + 0xe0, 0xbd, 0x11, 0xe0, 0xfd, 0x90, 0xe0, 0xa9, 0xfe, 0x6a, 0x9d, 0x42, 0xe0, 0x90, 0x11, 0xf0, + 0x4a, 0x9d, 0x42, 0xe0, 0xbd, 0x8d, 0xe0, 0x9d, 0x0e, 0xe0, 0xbd, 0x90, 0xe0, 0x9d, 0x11, 0xe0, + 0xbd, 0x36, 0xe0, 0x0a, 0xd0, 0x35, 0xbd, 0x93, 0xe0, 0xf0, 0x0c, 0xbd, 0x99, 0xe0, 0x9d, 0x14, + 0xe0, 0xbd, 0x9c, 0xe0, 0x9d, 0x17, 0xe0, 0xbd, 0x9f, 0xe0, 0xf0, 0x0f, 0xa4, 0xfd, 0x18, 0x79, + 0x92, 0xe1, 0xa4, 0xfe, 0x18, 0x79, 0x9a, 0xe1, 0x18, 0x90, 0x08, 0xbd, 0xa2, 0xe0, 0xf0, 0x0b, + 0xbd, 0xa5, 0xe0, 0x8d, 0x24, 0xe0, 0xa9, 0x00, 0x8d, 0x23, 0xe0, 0xbd, 0x3c, 0xe0, 0x9d, 0x3f, + 0xe0, 0xbd, 0x05, 0xe0, 0x29, 0x40, 0x9d, 0x36, 0xe0, 0xbd, 0x05, 0xe0, 0x4a, 0x4a, 0x29, 0x07, + 0xd0, 0x30, 0xbd, 0x05, 0xe0, 0x30, 0x14, 0xad, 0x27, 0xe0, 0x29, 0x3c, 0xd0, 0x1e, 0xad, 0x27, + 0xe0, 0x0a, 0x2a, 0x2a, 0xd0, 0x02, 0xa9, 0x04, 0x4c, 0x70, 0xe8, 0xad, 0x28, 0xe0, 0xf0, 0x0c, + 0x29, 0x3f, 0xd0, 0x08, 0xad, 0x28, 0xe0, 0x0a, 0x2a, 0x2a, 0xd0, 0x66, 0xa9, 0x10, 0x8d, 0x00, + 0xe0, 0x60, 0xc9, 0x01, 0xd0, 0x13, 0xbd, 0x05, 0xe0, 0x29, 0x20, 0xd0, 0x06, 0xad, 0x29, 0xe0, + 0x4c, 0x70, 0xe8, 0xbd, 0x2a, 0xe0, 0x4c, 0x70, 0xe8, 0xa8, 0xbd, 0x05, 0xe0, 0x29, 0xa0, 0xc9, + 0x80, 0xf0, 0x30, 0x85, 0xff, 0x18, 0xad, 0x27, 0xe0, 0xd0, 0x01, 0x38, 0x88, 0x88, 0xf0, 0x06, + 0x6a, 0xb0, 0x4e, 0x88, 0xd0, 0xfa, 0xa4, 0xff, 0x85, 0xff, 0xf0, 0x26, 0x46, 0xff, 0xb0, 0x41, + 0xf0, 0x42, 0x65, 0xff, 0xb0, 0x3e, 0xc8, 0x10, 0x19, 0x46, 0xff, 0xb0, 0x34, 0x65, 0xff, 0x90, + 0x11, 0xb0, 0x31, 0xad, 0x28, 0xe0, 0xf0, 0x29, 0x88, 0x88, 0xf0, 0x06, 0x4a, 0xb0, 0x22, 0x88, + 0xd0, 0xfa, 0x9d, 0x30, 0xe0, 0xbd, 0x1a, 0xe0, 0x29, 0xf6, 0x9d, 0x1a, 0xe0, 0x38, 0xbd, 0x02, + 0xe0, 0x29, 0x07, 0xd0, 0x03, 0x7e, 0x36, 0xe0, 0xbd, 0x1a, 0xe0, 0x69, 0x00, 0x9d, 0x1a, 0xe0, + 0x60, 0xa9, 0x10, 0x2c, 0xa9, 0x18, 0x8d, 0x00, 0xe0, 0x60, 0x98, 0x48, 0xa5, 0xff, 0x4a, 0x90, + 0x03, 0x4c, 0x42, 0xea, 0x4a, 0x4a, 0xb0, 0x1e, 0x4a, 0xb0, 0x0e, 0x9d, 0x9c, 0xe0, 0x9d, 0x17, + 0xe0, 0x68, 0x9d, 0x99, 0xe0, 0x9d, 0x14, 0xe0, 0x60, 0x4a, 0x90, 0x02, 0x09, 0xf8, 0x9d, 0x8a, + 0xe0, 0x68, 0x9d, 0x87, 0xe0, 0x60, 0x4a, 0xb0, 0x03, 0x4c, 0x4a, 0xe9, 0x4a, 0xb0, 0x61, 0x4a, + 0xb0, 0x0f, 0xd0, 0x08, 0x68, 0x9d, 0xa5, 0xe0, 0x8d, 0x24, 0xe0, 0x60, 0x68, 0x9d, 0x3c, 0xe0, + 0x60, 0xd0, 0x48, 0x68, 0x9d, 0x7e, 0xe0, 0xc9, 0x5b, 0xf0, 0x33, 0xa8, 0x4a, 0x4a, 0x4a, 0x38, + 0xe9, 0x0b, 0x18, 0x7d, 0x84, 0xe0, 0x30, 0x0c, 0xc9, 0x0c, 0x90, 0x11, 0xe9, 0x0c, 0xde, 0x81, + 0xe0, 0x4c, 0x0b, 0xe9, 0xc9, 0xf5, 0xb0, 0x05, 0x69, 0x0c, 0xfe, 0x81, 0xe0, 0x9d, 0x84, 0xe0, + 0x98, 0x29, 0x07, 0x38, 0xe9, 0x03, 0x18, 0x7d, 0x81, 0xe0, 0x9d, 0x81, 0xe0, 0x60, 0xbd, 0x78, + 0xe0, 0x9d, 0x81, 0xe0, 0xbd, 0x7b, 0xe0, 0x9d, 0x84, 0xe0, 0x60, 0x68, 0x9d, 0xc6, 0xe0, 0x60, + 0x4a, 0xb0, 0x08, 0x9d, 0x0b, 0xe0, 0x68, 0x9d, 0x08, 0xe0, 0x60, 0x4a, 0x6a, 0x6a, 0x6d, 0x5b, + 0xe1, 0x8d, 0x2d, 0xe0, 0x68, 0x6d, 0x5c, 0xe1, 0x8d, 0x2e, 0xe0, 0x60, 0x4a, 0x90, 0x03, 0x4c, + 0xd3, 0xe9, 0x4a, 0xb0, 0x40, 0x4a, 0xb0, 0x17, 0x4a, 0xb0, 0x0f, 0x68, 0x8d, 0x27, 0xe0, 0x4a, + 0x4a, 0x4a, 0xa8, 0xb9, 0xaf, 0xe1, 0x8d, 0x28, 0xe0, 0x60, 0x68, 0x9d, 0x5d, 0xe0, 0x60, 0x4a, + 0xb0, 0x05, 0x68, 0x8d, 0x01, 0xe0, 0x60, 0x68, 0xf0, 0x11, 0x9d, 0x75, 0xe0, 0xbc, 0x63, 0xe0, + 0xd0, 0x08, 0x9d, 0x63, 0xe0, 0xa9, 0x01, 0x9d, 0x66, 0xe0, 0x60, 0x9d, 0x63, 0xe0, 0x9d, 0x69, + 0xe0, 0x9d, 0x6c, 0xe0, 0x60, 0x4a, 0xb0, 0x30, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0x39, 0xe0, 0x60, + 0x68, 0xa0, 0x00, 0x4a, 0x90, 0x02, 0xc8, 0x18, 0x48, 0x29, 0x07, 0x79, 0xac, 0xe1, 0x9d, 0x78, + 0xe0, 0x9d, 0x81, 0xe0, 0x68, 0x4a, 0x4a, 0x4a, 0x18, 0x79, 0xad, 0xe1, 0x9d, 0x7b, 0xe0, 0x9d, + 0x84, 0xe0, 0xa9, 0x5b, 0x9d, 0x7e, 0xe0, 0x60, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0xa2, 0xe0, 0x60, + 0x68, 0x8d, 0xcc, 0xe0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x0d, 0x4a, 0xb0, 0x05, 0x68, 0x8d, + 0x29, 0xe0, 0x60, 0x68, 0x9d, 0x9f, 0xe0, 0x60, 0x4a, 0xb0, 0x0f, 0x68, 0x9d, 0x93, 0xe0, 0xa0, + 0x00, 0x0a, 0x90, 0x01, 0x88, 0x98, 0x9d, 0x96, 0xe0, 0x60, 0x68, 0x9d, 0x72, 0xe0, 0x60, 0x4a, + 0xb0, 0x1c, 0x4a, 0xb0, 0x15, 0x68, 0x9d, 0xb7, 0xe0, 0xa5, 0xfd, 0x9d, 0xb1, 0xe0, 0xa5, 0xfe, + 0x9d, 0xb4, 0xe0, 0xbd, 0x33, 0xe0, 0x9d, 0xae, 0xe0, 0x60, 0x68, 0x6c, 0x5f, 0xe1, 0x4a, 0xb0, + 0x1e, 0x68, 0xd0, 0x0a, 0x9d, 0x4b, 0xe0, 0x9d, 0x51, 0xe0, 0x9d, 0x54, 0xe0, 0x60, 0x9d, 0x5a, + 0xe0, 0xbc, 0x4b, 0xe0, 0xd0, 0x08, 0x9d, 0x4b, 0xe0, 0xa9, 0x01, 0x9d, 0x4e, 0xe0, 0x60, 0x68, + 0x9d, 0x2a, 0xe0, 0x60, 0x4a, 0x90, 0x08, 0x9d, 0x48, 0xe0, 0x68, 0x9d, 0x45, 0xe0, 0x60, 0x68, + 0x4a, 0xb0, 0x61, 0x4a, 0xb0, 0x25, 0x4a, 0xb0, 0x05, 0x4a, 0xa0, 0xf0, 0xd0, 0x06, 0x0a, 0x0a, + 0x0a, 0x0a, 0xa0, 0x0f, 0x85, 0xff, 0x98, 0xb0, 0x09, 0x3d, 0x1d, 0xe0, 0x05, 0xff, 0x9d, 0x1d, + 0xe0, 0x60, 0x3d, 0x20, 0xe0, 0x05, 0xff, 0x9d, 0x20, 0xe0, 0x60, 0x4a, 0xb0, 0x38, 0x4a, 0xb0, + 0x64, 0x85, 0xff, 0xbd, 0xba, 0xe0, 0xdd, 0xa9, 0xe1, 0xf0, 0x54, 0xfe, 0xba, 0xe0, 0xa8, 0xa5, + 0xfd, 0x99, 0xe1, 0xe0, 0xa5, 0xfe, 0x99, 0xf0, 0xe0, 0xbd, 0x33, 0xe0, 0x99, 0x2f, 0xe1, 0xa4, + 0xff, 0xb9, 0x17, 0xe1, 0xf0, 0x36, 0x85, 0xfe, 0xb9, 0xff, 0xe0, 0x85, 0xfd, 0xb9, 0x3e, 0xe1, + 0x9d, 0x33, 0xe0, 0x60, 0xb0, 0x4b, 0x4a, 0xb0, 0x3c, 0xa8, 0xa5, 0xfd, 0x99, 0xff, 0xe0, 0xa5, + 0xfe, 0x99, 0x17, 0xe1, 0xbd, 0x33, 0xe0, 0x99, 0x3e, 0xe1, 0xbd, 0xba, 0xe0, 0xdd, 0xa9, 0xe1, + 0xf0, 0x0d, 0xfe, 0xba, 0xe0, 0xa8, 0xa9, 0x00, 0x99, 0xf0, 0xe0, 0x60, 0xa9, 0x30, 0x2c, 0xa9, + 0x28, 0x8d, 0x00, 0xe0, 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x25, 0xe0, 0x29, 0xf0, 0x4d, 0x25, + 0xe0, 0x8d, 0x25, 0xe0, 0x60, 0x4d, 0x26, 0xe0, 0x29, 0x0f, 0x4d, 0x26, 0xe0, 0x8d, 0x26, 0xe0, + 0x60, 0x4a, 0xb0, 0x0b, 0x4a, 0xb0, 0x04, 0x8d, 0xca, 0xe0, 0x60, 0x8d, 0xcb, 0xe0, 0x60, 0x4a, + 0x90, 0x03, 0x4c, 0xa5, 0xeb, 0x4a, 0xa8, 0xf0, 0x21, 0x88, 0xf0, 0x34, 0x88, 0xf0, 0x42, 0x88, + 0xf0, 0x4a, 0x88, 0xf0, 0x52, 0x88, 0xf0, 0x5c, 0x88, 0xf0, 0x66, 0x88, 0xf0, 0x73, 0x29, 0x07, + 0x09, 0x10, 0xb0, 0x03, 0x4c, 0xb7, 0xea, 0x4c, 0x7f, 0xea, 0xac, 0x26, 0xe0, 0xb0, 0x07, 0xc8, + 0x98, 0x29, 0x0f, 0xd0, 0x07, 0x60, 0x98, 0x29, 0x0f, 0xf0, 0x04, 0x88, 0x8c, 0x26, 0xe0, 0x60, + 0xbd, 0x62, 0xe1, 0x49, 0xff, 0x2d, 0x25, 0xe0, 0x90, 0x03, 0x1d, 0x62, 0xe1, 0x8d, 0x25, 0xe0, + 0x60, 0xbd, 0x1a, 0xe0, 0x29, 0xfb, 0x90, 0x55, 0x09, 0x04, 0xb0, 0x51, 0xbd, 0x1a, 0xe0, 0x29, + 0xfd, 0x90, 0x4a, 0x09, 0x02, 0xb0, 0x46, 0xad, 0x25, 0xe0, 0x29, 0xf7, 0x90, 0x02, 0x09, 0x08, + 0x8d, 0x25, 0xe0, 0x60, 0xad, 0x26, 0xe0, 0x29, 0x7f, 0x90, 0x02, 0x09, 0x80, 0x8d, 0x26, 0xe0, + 0x60, 0x98, 0x8d, 0xbd, 0xe0, 0x8d, 0xdf, 0xe0, 0xc8, 0x8c, 0xe0, 0xe0, 0x2a, 0x8d, 0xc9, 0xe0, + 0x60, 0x98, 0x2a, 0x9d, 0x60, 0xe0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x14, 0xd0, 0x02, 0xa9, + 0x08, 0x0a, 0x0a, 0x0a, 0x0a, 0x5d, 0x1a, 0xe0, 0x29, 0xf0, 0x5d, 0x1a, 0xe0, 0x9d, 0x1a, 0xe0, + 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x26, 0xe0, 0x29, 0x70, 0x4d, 0x26, 0xe0, 0x8d, 0x26, 0xe0, + 0x60, 0x4a, 0x90, 0x04, 0x9d, 0xc0, 0xe0, 0x60, 0xa8, 0xf0, 0x20, 0x88, 0xf0, 0x40, 0x88, 0xf0, + 0x63, 0x29, 0x03, 0x9d, 0xc3, 0xe0, 0xa9, 0x00, 0x9d, 0xcd, 0xe0, 0x9d, 0xd0, 0xe0, 0x9d, 0xd3, + 0xe0, 0x9d, 0xd6, 0xe0, 0x8d, 0xd9, 0xe0, 0x8d, 0xdc, 0xe0, 0x60, 0xbd, 0xb7, 0xe0, 0xf0, 0x05, + 0xde, 0xb7, 0xe0, 0xf0, 0x12, 0xbd, 0x33, 0xe0, 0xdd, 0xae, 0xe0, 0xd0, 0x0b, 0xbd, 0xb1, 0xe0, + 0x85, 0xfd, 0xbd, 0xb4, 0xe0, 0x85, 0xfe, 0x60, 0xa9, 0x38, 0x8d, 0x00, 0xe0, 0x60, 0xbd, 0xba, + 0xe0, 0xdd, 0xa8, 0xe1, 0xf0, 0x18, 0xde, 0xba, 0xe0, 0xa8, 0x88, 0xb9, 0xf0, 0xe0, 0xf0, 0x0d, + 0x85, 0xfe, 0xb9, 0xe1, 0xe0, 0x85, 0xfd, 0xb9, 0x2f, 0xe1, 0x9d, 0x33, 0xe0, 0x60, 0xa9, 0x20, + 0x8d, 0x00, 0xe0, 0x60, 0xad, 0x00, 0xe0, 0x5d, 0x62, 0xe1, 0x8d, 0x00, 0xe0, 0xa9, 0x01, 0x9d, + 0x30, 0xe0, 0x60, 0xad, 0x00, 0xe0, 0x29, 0x07, 0x8d, 0x81, 0xec, 0xd0, 0x03, 0x20, 0xe9, 0xe2, + 0x60, 0x00, 0xa2, 0x51, 0xa0, 0xec, 0x8e, 0x5d, 0xe1, 0x8c, 0x5e, 0xe1, 0x20, 0xcf, 0xe1, 0xa2, + 0x00, 0xa0, 0x09, 0x20, 0x00, 0xe2, 0xa9, 0x07, 0x8d, 0x00, 0xe0, 0x8d, 0x81, 0xec, 0x60, 0x00, + 0x00, 0x00, 0xa9, 0x00, 0x29, 0xff, 0xf0, 0xf6, 0x4c, 0x29, 0xe3, 0xa9, 0x07, 0x8d, 0x00, 0xe0, + 0x60 +}; + +static const uint8_t _sidtune_sidplayer2[] = +{ + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x61, 0xf1, 0x60, 0x01, 0x02, 0x04, 0x00, 0x07, 0x0e, 0x02, 0x02, 0xfe, 0x02, 0x02, 0xfe, + 0xfe, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x1e, 0x18, 0x8b, 0x7e, + 0xfa, 0x06, 0xac, 0xf3, 0xe6, 0x8f, 0xf8, 0x2e, 0x86, 0x8e, 0x96, 0x9f, 0xa8, 0xb3, 0xbd, 0xc8, + 0xd4, 0xe1, 0xee, 0xfd, 0x8c, 0x78, 0x64, 0x50, 0x3c, 0x28, 0x14, 0x00, 0x00, 0x02, 0x03, 0x05, + 0x07, 0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x11, 0x12, 0x00, 0xe0, 0x00, 0x05, 0x0a, 0x0f, 0xf9, 0x00, + 0xf5, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xa0, + 0x00, 0xa9, 0x00, 0x8d, 0x00, 0xf0, 0xa2, 0x95, 0xa0, 0x42, 0xad, 0xa6, 0x02, 0xf0, 0x04, 0xa2, + 0x25, 0xa0, 0x40, 0x8e, 0x5b, 0xf1, 0x8c, 0x5c, 0xf1, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, + 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, + 0xea, 0x60, 0xa9, 0x00, 0x8d, 0x00, 0xf0, 0x86, 0x61, 0x84, 0x62, 0xa0, 0xbc, 0x99, 0x00, 0xf0, + 0x88, 0xd0, 0xfa, 0xa0, 0x72, 0x99, 0xbc, 0xf0, 0x88, 0xd0, 0xfa, 0x8d, 0x15, 0xd5, 0x8d, 0x16, + 0xd5, 0xa9, 0x08, 0x8d, 0x25, 0xf0, 0x8d, 0x17, 0xd5, 0x8d, 0x26, 0xf0, 0x8d, 0x18, 0xd5, 0xa9, + 0x90, 0x8d, 0x27, 0xf0, 0xa9, 0x60, 0x8d, 0x28, 0xf0, 0xa9, 0x0c, 0x8d, 0x29, 0xf0, 0xad, 0x5b, + 0xf1, 0x8d, 0x2d, 0xf0, 0xad, 0x5c, 0xf1, 0x8d, 0x2e, 0xf0, 0xa9, 0xff, 0x8d, 0xcc, 0xf0, 0xa9, + 0xd5, 0x85, 0x64, 0xa2, 0x02, 0xa9, 0xff, 0x9d, 0x0b, 0xf0, 0xa9, 0x01, 0x9d, 0x30, 0xf0, 0x9d, + 0x2a, 0xf0, 0x8a, 0x9d, 0x33, 0xf0, 0x9d, 0xae, 0xf0, 0xa9, 0x04, 0x9d, 0x39, 0xf0, 0xbd, 0xa8, + 0xf1, 0x9d, 0xba, 0xf0, 0xa9, 0x5b, 0x9d, 0x7e, 0xf0, 0xbd, 0x65, 0xf1, 0x85, 0x63, 0xa9, 0x00, + 0xa8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x08, 0x9d, 0x17, 0xf0, 0x9d, 0x9c, + 0xf0, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x40, 0x9d, 0x1a, 0xf0, 0x91, 0x63, 0xa9, 0x20, + 0x9d, 0x1d, 0xf0, 0xc8, 0x91, 0x63, 0xa9, 0xf5, 0x9d, 0x20, 0xf0, 0xc8, 0x91, 0x63, 0xca, 0x10, + 0xa4, 0x8a, 0xa2, 0x17, 0x9d, 0x3e, 0xf1, 0xca, 0x10, 0xfa, 0xa5, 0x61, 0x18, 0x69, 0x06, 0x85, + 0x63, 0xa9, 0x00, 0xaa, 0xa8, 0x65, 0x62, 0x85, 0x64, 0x9d, 0xab, 0xf0, 0x9d, 0xb4, 0xf0, 0xa5, + 0x63, 0x9d, 0xa8, 0xf0, 0x9d, 0xb1, 0xf0, 0x18, 0x71, 0x61, 0x85, 0x63, 0xa5, 0x64, 0xc8, 0x71, + 0x61, 0xc8, 0xe8, 0xe0, 0x03, 0xd0, 0xe0, 0xa6, 0x63, 0xa8, 0x60, 0xa9, 0x00, 0x8d, 0x04, 0xd5, + 0x8d, 0x0b, 0xd5, 0x8d, 0x12, 0xd5, 0x8d, 0x01, 0xd5, 0x8d, 0x08, 0xd5, 0x8d, 0x0f, 0xd5, 0xa9, + 0x08, 0x8d, 0x17, 0xd5, 0xad, 0x5b, 0xf1, 0x8d, 0x04, 0xdc, 0xad, 0x5c, 0xf1, 0x8d, 0x05, 0xdc, + 0x60, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x60, + 0xa9, 0x08, 0x8d, 0x00, 0xf0, 0x6c, 0x5d, 0xf1, 0xea, 0xea, 0xea, 0xad, 0x00, 0xf0, 0x30, 0xf0, + 0x09, 0x80, 0xa8, 0x29, 0x07, 0xf0, 0xee, 0xd8, 0x8c, 0x00, 0xf0, 0xea, 0xa5, 0xfb, 0x8d, 0x56, + 0xf1, 0xa5, 0xfc, 0x8d, 0x57, 0xf1, 0xa5, 0xfd, 0x8d, 0x58, 0xf1, 0xa5, 0xfe, 0x8d, 0x59, 0xf1, + 0xa5, 0xff, 0x8d, 0x5a, 0xf1, 0xad, 0x23, 0xf0, 0x18, 0x6d, 0xd9, 0xf0, 0x48, 0x29, 0x07, 0xa8, + 0xad, 0xdc, 0xf0, 0x69, 0x00, 0x85, 0xff, 0x68, 0x46, 0xff, 0x6a, 0x46, 0xff, 0x6a, 0x46, 0xff, + 0x6a, 0x18, 0x6d, 0x24, 0xf0, 0x8c, 0x15, 0xd5, 0x8d, 0x16, 0xd5, 0xad, 0x25, 0xf0, 0x8d, 0x17, + 0xd5, 0xad, 0x26, 0xf0, 0x8d, 0x18, 0xd5, 0xa9, 0xd5, 0x85, 0xfc, 0xa2, 0x00, 0xad, 0x00, 0xf0, + 0x3d, 0x62, 0xf1, 0xf0, 0x51, 0xbd, 0x65, 0xf1, 0x85, 0xfb, 0xbd, 0x0e, 0xf0, 0x18, 0x7d, 0x51, + 0xf0, 0xa8, 0xbd, 0x11, 0xf0, 0x7d, 0x54, 0xf0, 0x48, 0x98, 0x18, 0x7d, 0xcd, 0xf0, 0xa0, 0x00, + 0x91, 0xfb, 0x68, 0x7d, 0xd0, 0xf0, 0xc8, 0x91, 0xfb, 0xbd, 0x14, 0xf0, 0x18, 0x7d, 0x69, 0xf0, + 0x85, 0xff, 0xbd, 0x17, 0xf0, 0x7d, 0x6c, 0xf0, 0x48, 0xa5, 0xff, 0x18, 0x7d, 0xd3, 0xf0, 0xc8, + 0x91, 0xfb, 0x68, 0x7d, 0xd6, 0xf0, 0xc8, 0x91, 0xfb, 0xbd, 0x1d, 0xf0, 0xc8, 0xc8, 0x91, 0xfb, + 0xbd, 0x20, 0xf0, 0xc8, 0x91, 0xfb, 0xe8, 0xe0, 0x03, 0xd0, 0xa2, 0xac, 0x1a, 0xf0, 0xae, 0x1b, + 0xf0, 0xad, 0x1c, 0xf0, 0x8c, 0x04, 0xd5, 0x8e, 0x0b, 0xd5, 0x8d, 0x12, 0xd5, 0xae, 0x2d, 0xf0, + 0xac, 0x2e, 0xf0, 0x8e, 0x04, 0xdc, 0x8c, 0x05, 0xdc, 0xad, 0x1b, 0xd5, 0x8d, 0xbe, 0xf0, 0xad, + 0x1c, 0xd5, 0x8d, 0xbf, 0xf0, 0xa2, 0x00, 0xad, 0x00, 0xf0, 0x3d, 0x62, 0xf1, 0xf0, 0x10, 0x8e, + 0x2f, 0xf0, 0x20, 0x36, 0xf5, 0xad, 0x00, 0xf0, 0x29, 0x78, 0xf0, 0x03, 0x4c, 0x0c, 0xf5, 0xe8, + 0xe0, 0x03, 0xd0, 0xe3, 0xad, 0xc9, 0xf0, 0xd0, 0x52, 0xad, 0xca, 0xf0, 0x0d, 0xcb, 0xf0, 0xf0, + 0x78, 0xad, 0xdf, 0xf0, 0xd0, 0x28, 0xad, 0xca, 0xf0, 0xf0, 0x28, 0x18, 0x6d, 0xbd, 0xf0, 0xb0, + 0x07, 0xcd, 0xcc, 0xf0, 0x90, 0x60, 0xf0, 0x5e, 0xa9, 0x00, 0x8d, 0xdf, 0xf0, 0xad, 0xcb, 0xf0, + 0xf0, 0x54, 0xee, 0xdf, 0xf0, 0xad, 0xbd, 0xf0, 0xed, 0xcb, 0xf0, 0x4c, 0xb4, 0xf4, 0xad, 0xcb, + 0xf0, 0xf0, 0xd3, 0xad, 0xbd, 0xf0, 0x38, 0xed, 0xcb, 0xf0, 0xb0, 0x3a, 0xa9, 0x00, 0x8d, 0xdf, + 0xf0, 0xad, 0xca, 0xf0, 0xd0, 0x30, 0xee, 0xdf, 0xf0, 0xd0, 0x28, 0xce, 0xe0, 0xf0, 0xd0, 0x29, + 0xad, 0xdf, 0xf0, 0xd0, 0x11, 0xee, 0xdf, 0xf0, 0xad, 0xcb, 0xf0, 0xd0, 0x02, 0xa9, 0x20, 0x8d, + 0xe0, 0xf0, 0xa9, 0x00, 0xf0, 0x10, 0xce, 0xdf, 0xf0, 0xad, 0xca, 0xf0, 0xd0, 0x02, 0xa9, 0x20, + 0x8d, 0xe0, 0xf0, 0xad, 0xcc, 0xf0, 0x8d, 0xbd, 0xf0, 0xa2, 0x00, 0xbd, 0xc3, 0xf0, 0xf0, 0x44, + 0xa9, 0x00, 0x85, 0xff, 0xbc, 0xc0, 0xf0, 0xb9, 0xbd, 0xf0, 0xbc, 0xc6, 0xf0, 0xf0, 0x0e, 0x30, + 0x08, 0x0a, 0x26, 0xff, 0x88, 0xd0, 0xfa, 0xf0, 0x04, 0x4a, 0xc8, 0xd0, 0xfc, 0xbc, 0xc3, 0xf0, + 0x88, 0xd0, 0x0b, 0x9d, 0xcd, 0xf0, 0xa5, 0xff, 0x9d, 0xd0, 0xf0, 0x4c, 0x02, 0xf5, 0x88, 0xd0, + 0x0b, 0x9d, 0xd3, 0xf0, 0xa5, 0xff, 0x9d, 0xd6, 0xf0, 0x4c, 0x02, 0xf5, 0x8d, 0xd9, 0xf0, 0xa5, + 0xff, 0x8d, 0xdc, 0xf0, 0xe8, 0xe0, 0x03, 0xd0, 0xb2, 0xad, 0x00, 0xf0, 0x29, 0x7f, 0x8d, 0x00, + 0xf0, 0xad, 0x56, 0xf1, 0x85, 0xfb, 0xad, 0x57, 0xf1, 0x85, 0xfc, 0xad, 0x58, 0xf1, 0x85, 0xfd, + 0xad, 0x59, 0xf1, 0x85, 0xfe, 0xad, 0x5a, 0xf1, 0x85, 0xff, 0x6c, 0x5d, 0xf1, 0xbd, 0x60, 0xf0, + 0xd0, 0x03, 0x4c, 0x9f, 0xf6, 0x4c, 0xba, 0xf5, 0xde, 0x30, 0xf0, 0xd0, 0x03, 0x4c, 0xa0, 0xf6, + 0xbd, 0x36, 0xf0, 0x30, 0xe8, 0xd0, 0x1a, 0xbd, 0x3f, 0xf0, 0xf0, 0x05, 0xde, 0x3f, 0xf0, 0xd0, + 0x10, 0xbd, 0x39, 0xf0, 0xdd, 0x30, 0xf0, 0x90, 0x08, 0xbd, 0x1a, 0xf0, 0x29, 0xfe, 0x9d, 0x1a, + 0xf0, 0xbd, 0x42, 0xf0, 0xf0, 0x56, 0x0a, 0xbd, 0x0e, 0xf0, 0xb0, 0x1d, 0x7d, 0x45, 0xf0, 0x9d, + 0x0e, 0xf0, 0xa8, 0xbd, 0x11, 0xf0, 0x7d, 0x48, 0xf0, 0x9d, 0x11, 0xf0, 0x48, 0x98, 0xdd, 0x8d, + 0xf0, 0x68, 0xfd, 0x90, 0xf0, 0xb0, 0x1f, 0x90, 0x2e, 0xfd, 0x45, 0xf0, 0x9d, 0x0e, 0xf0, 0xbd, + 0x11, 0xf0, 0xfd, 0x48, 0xf0, 0x9d, 0x11, 0xf0, 0xbd, 0x8d, 0xf0, 0xdd, 0x0e, 0xf0, 0xbd, 0x90, + 0xf0, 0xfd, 0x11, 0xf0, 0x90, 0x11, 0xbd, 0x8d, 0xf0, 0x9d, 0x0e, 0xf0, 0xbd, 0x90, 0xf0, 0x9d, + 0x11, 0xf0, 0xa9, 0x00, 0x9d, 0x42, 0xf0, 0xbd, 0x60, 0xf0, 0xf0, 0x55, 0xbd, 0x4b, 0xf0, 0xf0, + 0x4b, 0xa0, 0x00, 0xde, 0x4e, 0xf0, 0xd0, 0x31, 0xbd, 0x51, 0xf0, 0x1d, 0x54, 0xf0, 0xd0, 0x1b, + 0xbd, 0x5d, 0xf0, 0x9d, 0x57, 0xf0, 0x9d, 0x4e, 0xf0, 0xbd, 0x4b, 0xf0, 0x0a, 0xbd, 0x5a, 0xf0, + 0x90, 0x04, 0x49, 0xff, 0x69, 0x00, 0x9d, 0x4b, 0xf0, 0xd0, 0x10, 0xbd, 0x57, 0xf0, 0x9d, 0x4e, + 0xf0, 0x98, 0x38, 0xfd, 0x4b, 0xf0, 0x9d, 0x4b, 0xf0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d, + 0x51, 0xf0, 0x9d, 0x51, 0xf0, 0x98, 0x7d, 0x54, 0xf0, 0x9d, 0x54, 0xf0, 0xbd, 0x36, 0xf0, 0x30, + 0x15, 0xbd, 0x93, 0xf0, 0xf0, 0x10, 0x18, 0x7d, 0x14, 0xf0, 0x9d, 0x14, 0xf0, 0xbd, 0x96, 0xf0, + 0x7d, 0x17, 0xf0, 0x9d, 0x17, 0xf0, 0xbd, 0x63, 0xf0, 0xf0, 0x4b, 0xa0, 0x00, 0xde, 0x66, 0xf0, + 0xd0, 0x31, 0xbd, 0x69, 0xf0, 0x1d, 0x6c, 0xf0, 0xd0, 0x1b, 0xbd, 0x72, 0xf0, 0x9d, 0x6f, 0xf0, + 0x9d, 0x66, 0xf0, 0xbd, 0x63, 0xf0, 0x0a, 0xbd, 0x75, 0xf0, 0x90, 0x04, 0x49, 0xff, 0x69, 0x00, + 0x9d, 0x63, 0xf0, 0xd0, 0x10, 0xbd, 0x6f, 0xf0, 0x9d, 0x66, 0xf0, 0x98, 0x38, 0xfd, 0x63, 0xf0, + 0x9d, 0x63, 0xf0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d, 0x69, 0xf0, 0x9d, 0x69, 0xf0, 0x98, + 0x7d, 0x6c, 0xf0, 0x9d, 0x6c, 0xf0, 0xbd, 0x36, 0xf0, 0x10, 0x03, 0x4c, 0x9f, 0xf6, 0xa0, 0x00, + 0xbd, 0xa2, 0xf0, 0xf0, 0x1c, 0x10, 0x01, 0xc8, 0x18, 0x6d, 0x23, 0xf0, 0x48, 0x29, 0x07, 0x8d, + 0x23, 0xf0, 0x68, 0x6a, 0x4a, 0x4a, 0x18, 0x79, 0xa6, 0xf1, 0x18, 0x6d, 0x24, 0xf0, 0x8d, 0x24, + 0xf0, 0x60, 0xbd, 0xa8, 0xf0, 0x85, 0xfd, 0xbd, 0xab, 0xf0, 0x85, 0xfe, 0xd0, 0x04, 0x60, 0x20, + 0x98, 0xf8, 0xad, 0x00, 0xf0, 0x3d, 0x62, 0xf1, 0xf0, 0xf4, 0xa0, 0x00, 0xb1, 0xfd, 0x85, 0xff, + 0xc8, 0xb1, 0xfd, 0xa8, 0xa5, 0xfd, 0x18, 0x69, 0x02, 0x85, 0xfd, 0x9d, 0xa8, 0xf0, 0xa5, 0xfe, + 0x69, 0x00, 0x85, 0xfe, 0x9d, 0xab, 0xf0, 0xa5, 0xff, 0x29, 0x03, 0xd0, 0xd2, 0xbd, 0x8d, 0xf0, + 0x9d, 0x0e, 0xf0, 0xbd, 0x90, 0xf0, 0x9d, 0x11, 0xf0, 0xa5, 0xff, 0x9d, 0x05, 0xf0, 0x98, 0x9d, + 0x02, 0xf0, 0x29, 0x07, 0xa8, 0xb9, 0x67, 0xf1, 0x8d, 0x6f, 0xf1, 0xbd, 0x02, 0xf0, 0x29, 0x38, + 0x4a, 0x4a, 0x4a, 0x7d, 0x81, 0xf0, 0x85, 0xfd, 0xbd, 0x02, 0xf0, 0x29, 0xc0, 0x0a, 0x2a, 0x2a, + 0xa8, 0xb9, 0x6f, 0xf1, 0x85, 0xfe, 0xbd, 0x02, 0xf0, 0x29, 0x07, 0xf0, 0x62, 0xa8, 0xb9, 0x72, + 0xf1, 0x65, 0xfe, 0x18, 0x7d, 0x84, 0xf0, 0x10, 0x05, 0x18, 0x69, 0x0c, 0xe6, 0xfd, 0xc9, 0x0c, + 0x90, 0x04, 0xe9, 0x0c, 0xc6, 0xfd, 0x85, 0xfe, 0xa8, 0xb9, 0x86, 0xf1, 0x85, 0xff, 0xb9, 0x7a, + 0xf1, 0xa4, 0xfd, 0x88, 0x30, 0x06, 0x46, 0xff, 0x6a, 0x88, 0x10, 0xfa, 0x18, 0x7d, 0x87, 0xf0, + 0x9d, 0x8d, 0xf0, 0xa5, 0xff, 0x7d, 0x8a, 0xf0, 0x9d, 0x90, 0xf0, 0xbd, 0x05, 0xf0, 0xd0, 0x03, + 0x4c, 0xa0, 0xf6, 0xbd, 0x45, 0xf0, 0x1d, 0x48, 0xf0, 0xf0, 0x16, 0xbd, 0x0e, 0xf0, 0xdd, 0x8d, + 0xf0, 0xbd, 0x11, 0xf0, 0xfd, 0x90, 0xf0, 0xa9, 0xfe, 0x6a, 0x9d, 0x42, 0xf0, 0x90, 0x11, 0xf0, + 0x4a, 0x9d, 0x42, 0xf0, 0xbd, 0x8d, 0xf0, 0x9d, 0x0e, 0xf0, 0xbd, 0x90, 0xf0, 0x9d, 0x11, 0xf0, + 0xbd, 0x36, 0xf0, 0x0a, 0xd0, 0x35, 0xbd, 0x93, 0xf0, 0xf0, 0x0c, 0xbd, 0x99, 0xf0, 0x9d, 0x14, + 0xf0, 0xbd, 0x9c, 0xf0, 0x9d, 0x17, 0xf0, 0xbd, 0x9f, 0xf0, 0xf0, 0x0f, 0xa4, 0xfd, 0x18, 0x79, + 0x92, 0xf1, 0xa4, 0xfe, 0x18, 0x79, 0x9a, 0xf1, 0x18, 0x90, 0x08, 0xbd, 0xa2, 0xf0, 0xf0, 0x0b, + 0xbd, 0xa5, 0xf0, 0x8d, 0x24, 0xf0, 0xa9, 0x00, 0x8d, 0x23, 0xf0, 0xbd, 0x3c, 0xf0, 0x9d, 0x3f, + 0xf0, 0xbd, 0x05, 0xf0, 0x29, 0x40, 0x9d, 0x36, 0xf0, 0xbd, 0x05, 0xf0, 0x4a, 0x4a, 0x29, 0x07, + 0xd0, 0x30, 0xbd, 0x05, 0xf0, 0x30, 0x14, 0xad, 0x27, 0xf0, 0x29, 0x3c, 0xd0, 0x1e, 0xad, 0x27, + 0xf0, 0x0a, 0x2a, 0x2a, 0xd0, 0x02, 0xa9, 0x04, 0x4c, 0x70, 0xf8, 0xad, 0x28, 0xf0, 0xf0, 0x0c, + 0x29, 0x3f, 0xd0, 0x08, 0xad, 0x28, 0xf0, 0x0a, 0x2a, 0x2a, 0xd0, 0x66, 0xa9, 0x10, 0x8d, 0x00, + 0xf0, 0x60, 0xc9, 0x01, 0xd0, 0x13, 0xbd, 0x05, 0xf0, 0x29, 0x20, 0xd0, 0x06, 0xad, 0x29, 0xf0, + 0x4c, 0x70, 0xf8, 0xbd, 0x2a, 0xf0, 0x4c, 0x70, 0xf8, 0xa8, 0xbd, 0x05, 0xf0, 0x29, 0xa0, 0xc9, + 0x80, 0xf0, 0x30, 0x85, 0xff, 0x18, 0xad, 0x27, 0xf0, 0xd0, 0x01, 0x38, 0x88, 0x88, 0xf0, 0x06, + 0x6a, 0xb0, 0x4e, 0x88, 0xd0, 0xfa, 0xa4, 0xff, 0x85, 0xff, 0xf0, 0x26, 0x46, 0xff, 0xb0, 0x41, + 0xf0, 0x42, 0x65, 0xff, 0xb0, 0x3e, 0xc8, 0x10, 0x19, 0x46, 0xff, 0xb0, 0x34, 0x65, 0xff, 0x90, + 0x11, 0xb0, 0x31, 0xad, 0x28, 0xf0, 0xf0, 0x29, 0x88, 0x88, 0xf0, 0x06, 0x4a, 0xb0, 0x22, 0x88, + 0xd0, 0xfa, 0x9d, 0x30, 0xf0, 0xbd, 0x1a, 0xf0, 0x29, 0xf6, 0x9d, 0x1a, 0xf0, 0x38, 0xbd, 0x02, + 0xf0, 0x29, 0x07, 0xd0, 0x03, 0x7e, 0x36, 0xf0, 0xbd, 0x1a, 0xf0, 0x69, 0x00, 0x9d, 0x1a, 0xf0, + 0x60, 0xa9, 0x10, 0x2c, 0xa9, 0x18, 0x8d, 0x00, 0xf0, 0x60, 0x98, 0x48, 0xa5, 0xff, 0x4a, 0x90, + 0x03, 0x4c, 0x42, 0xfa, 0x4a, 0x4a, 0xb0, 0x1e, 0x4a, 0xb0, 0x0e, 0x9d, 0x9c, 0xf0, 0x9d, 0x17, + 0xf0, 0x68, 0x9d, 0x99, 0xf0, 0x9d, 0x14, 0xf0, 0x60, 0x4a, 0x90, 0x02, 0x09, 0xf8, 0x9d, 0x8a, + 0xf0, 0x68, 0x9d, 0x87, 0xf0, 0x60, 0x4a, 0xb0, 0x03, 0x4c, 0x4a, 0xf9, 0x4a, 0xb0, 0x61, 0x4a, + 0xb0, 0x0f, 0xd0, 0x08, 0x68, 0x9d, 0xa5, 0xf0, 0x8d, 0x24, 0xf0, 0x60, 0x68, 0x9d, 0x3c, 0xf0, + 0x60, 0xd0, 0x48, 0x68, 0x9d, 0x7e, 0xf0, 0xc9, 0x5b, 0xf0, 0x33, 0xa8, 0x4a, 0x4a, 0x4a, 0x38, + 0xe9, 0x0b, 0x18, 0x7d, 0x84, 0xf0, 0x30, 0x0c, 0xc9, 0x0c, 0x90, 0x11, 0xe9, 0x0c, 0xde, 0x81, + 0xf0, 0x4c, 0x0b, 0xf9, 0xc9, 0xf5, 0xb0, 0x05, 0x69, 0x0c, 0xfe, 0x81, 0xf0, 0x9d, 0x84, 0xf0, + 0x98, 0x29, 0x07, 0x38, 0xe9, 0x03, 0x18, 0x7d, 0x81, 0xf0, 0x9d, 0x81, 0xf0, 0x60, 0xbd, 0x78, + 0xf0, 0x9d, 0x81, 0xf0, 0xbd, 0x7b, 0xf0, 0x9d, 0x84, 0xf0, 0x60, 0x68, 0x9d, 0xc6, 0xf0, 0x60, + 0x4a, 0xb0, 0x08, 0x9d, 0x0b, 0xf0, 0x68, 0x9d, 0x08, 0xf0, 0x60, 0x4a, 0x6a, 0x6a, 0x6d, 0x5b, + 0xf1, 0x8d, 0x2d, 0xf0, 0x68, 0x6d, 0x5c, 0xf1, 0x8d, 0x2e, 0xf0, 0x60, 0x4a, 0x90, 0x03, 0x4c, + 0xd3, 0xf9, 0x4a, 0xb0, 0x40, 0x4a, 0xb0, 0x17, 0x4a, 0xb0, 0x0f, 0x68, 0x8d, 0x27, 0xf0, 0x4a, + 0x4a, 0x4a, 0xa8, 0xb9, 0xaf, 0xf1, 0x8d, 0x28, 0xf0, 0x60, 0x68, 0x9d, 0x5d, 0xf0, 0x60, 0x4a, + 0xb0, 0x05, 0x68, 0x8d, 0x01, 0xf0, 0x60, 0x68, 0xf0, 0x11, 0x9d, 0x75, 0xf0, 0xbc, 0x63, 0xf0, + 0xd0, 0x08, 0x9d, 0x63, 0xf0, 0xa9, 0x01, 0x9d, 0x66, 0xf0, 0x60, 0x9d, 0x63, 0xf0, 0x9d, 0x69, + 0xf0, 0x9d, 0x6c, 0xf0, 0x60, 0x4a, 0xb0, 0x30, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0x39, 0xf0, 0x60, + 0x68, 0xa0, 0x00, 0x4a, 0x90, 0x02, 0xc8, 0x18, 0x48, 0x29, 0x07, 0x79, 0xac, 0xf1, 0x9d, 0x78, + 0xf0, 0x9d, 0x81, 0xf0, 0x68, 0x4a, 0x4a, 0x4a, 0x18, 0x79, 0xad, 0xf1, 0x9d, 0x7b, 0xf0, 0x9d, + 0x84, 0xf0, 0xa9, 0x5b, 0x9d, 0x7e, 0xf0, 0x60, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0xa2, 0xf0, 0x60, + 0x68, 0x8d, 0xcc, 0xf0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x0d, 0x4a, 0xb0, 0x05, 0x68, 0x8d, + 0x29, 0xf0, 0x60, 0x68, 0x9d, 0x9f, 0xf0, 0x60, 0x4a, 0xb0, 0x0f, 0x68, 0x9d, 0x93, 0xf0, 0xa0, + 0x00, 0x0a, 0x90, 0x01, 0x88, 0x98, 0x9d, 0x96, 0xf0, 0x60, 0x68, 0x9d, 0x72, 0xf0, 0x60, 0x4a, + 0xb0, 0x1c, 0x4a, 0xb0, 0x15, 0x68, 0x9d, 0xb7, 0xf0, 0xa5, 0xfd, 0x9d, 0xb1, 0xf0, 0xa5, 0xfe, + 0x9d, 0xb4, 0xf0, 0xbd, 0x33, 0xf0, 0x9d, 0xae, 0xf0, 0x60, 0x68, 0x6c, 0x5f, 0xf1, 0x4a, 0xb0, + 0x1e, 0x68, 0xd0, 0x0a, 0x9d, 0x4b, 0xf0, 0x9d, 0x51, 0xf0, 0x9d, 0x54, 0xf0, 0x60, 0x9d, 0x5a, + 0xf0, 0xbc, 0x4b, 0xf0, 0xd0, 0x08, 0x9d, 0x4b, 0xf0, 0xa9, 0x01, 0x9d, 0x4e, 0xf0, 0x60, 0x68, + 0x9d, 0x2a, 0xf0, 0x60, 0x4a, 0x90, 0x08, 0x9d, 0x48, 0xf0, 0x68, 0x9d, 0x45, 0xf0, 0x60, 0x68, + 0x4a, 0xb0, 0x61, 0x4a, 0xb0, 0x25, 0x4a, 0xb0, 0x05, 0x4a, 0xa0, 0xf0, 0xd0, 0x06, 0x0a, 0x0a, + 0x0a, 0x0a, 0xa0, 0x0f, 0x85, 0xff, 0x98, 0xb0, 0x09, 0x3d, 0x1d, 0xf0, 0x05, 0xff, 0x9d, 0x1d, + 0xf0, 0x60, 0x3d, 0x20, 0xf0, 0x05, 0xff, 0x9d, 0x20, 0xf0, 0x60, 0x4a, 0xb0, 0x38, 0x4a, 0xb0, + 0x64, 0x85, 0xff, 0xbd, 0xba, 0xf0, 0xdd, 0xa9, 0xf1, 0xf0, 0x54, 0xfe, 0xba, 0xf0, 0xa8, 0xa5, + 0xfd, 0x99, 0xe1, 0xf0, 0xa5, 0xfe, 0x99, 0xf0, 0xf0, 0xbd, 0x33, 0xf0, 0x99, 0x2f, 0xf1, 0xa4, + 0xff, 0xb9, 0x17, 0xf1, 0xf0, 0x36, 0x85, 0xfe, 0xb9, 0xff, 0xf0, 0x85, 0xfd, 0xb9, 0x3e, 0xf1, + 0x9d, 0x33, 0xf0, 0x60, 0xb0, 0x4b, 0x4a, 0xb0, 0x3c, 0xa8, 0xa5, 0xfd, 0x99, 0xff, 0xf0, 0xa5, + 0xfe, 0x99, 0x17, 0xf1, 0xbd, 0x33, 0xf0, 0x99, 0x3e, 0xf1, 0xbd, 0xba, 0xf0, 0xdd, 0xa9, 0xf1, + 0xf0, 0x0d, 0xfe, 0xba, 0xf0, 0xa8, 0xa9, 0x00, 0x99, 0xf0, 0xf0, 0x60, 0xa9, 0x30, 0x2c, 0xa9, + 0x28, 0x8d, 0x00, 0xf0, 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x25, 0xf0, 0x29, 0xf0, 0x4d, 0x25, + 0xf0, 0x8d, 0x25, 0xf0, 0x60, 0x4d, 0x26, 0xf0, 0x29, 0x0f, 0x4d, 0x26, 0xf0, 0x8d, 0x26, 0xf0, + 0x60, 0x4a, 0xb0, 0x0b, 0x4a, 0xb0, 0x04, 0x8d, 0xca, 0xf0, 0x60, 0x8d, 0xcb, 0xf0, 0x60, 0x4a, + 0x90, 0x03, 0x4c, 0xa5, 0xfb, 0x4a, 0xa8, 0xf0, 0x21, 0x88, 0xf0, 0x34, 0x88, 0xf0, 0x42, 0x88, + 0xf0, 0x4a, 0x88, 0xf0, 0x52, 0x88, 0xf0, 0x5c, 0x88, 0xf0, 0x66, 0x88, 0xf0, 0x73, 0x29, 0x07, + 0x09, 0x10, 0xb0, 0x03, 0x4c, 0xb7, 0xfa, 0x4c, 0x7f, 0xfa, 0xac, 0x26, 0xf0, 0xb0, 0x07, 0xc8, + 0x98, 0x29, 0x0f, 0xd0, 0x07, 0x60, 0x98, 0x29, 0x0f, 0xf0, 0x04, 0x88, 0x8c, 0x26, 0xf0, 0x60, + 0xbd, 0x62, 0xf1, 0x49, 0xff, 0x2d, 0x25, 0xf0, 0x90, 0x03, 0x1d, 0x62, 0xf1, 0x8d, 0x25, 0xf0, + 0x60, 0xbd, 0x1a, 0xf0, 0x29, 0xfb, 0x90, 0x55, 0x09, 0x04, 0xb0, 0x51, 0xbd, 0x1a, 0xf0, 0x29, + 0xfd, 0x90, 0x4a, 0x09, 0x02, 0xb0, 0x46, 0xad, 0x25, 0xf0, 0x29, 0xf7, 0x90, 0x02, 0x09, 0x08, + 0x8d, 0x25, 0xf0, 0x60, 0xad, 0x26, 0xf0, 0x29, 0x7f, 0x90, 0x02, 0x09, 0x80, 0x8d, 0x26, 0xf0, + 0x60, 0x98, 0x8d, 0xbd, 0xf0, 0x8d, 0xdf, 0xf0, 0xc8, 0x8c, 0xe0, 0xf0, 0x2a, 0x8d, 0xc9, 0xf0, + 0x60, 0x98, 0x2a, 0x9d, 0x60, 0xf0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x14, 0xd0, 0x02, 0xa9, + 0x08, 0x0a, 0x0a, 0x0a, 0x0a, 0x5d, 0x1a, 0xf0, 0x29, 0xf0, 0x5d, 0x1a, 0xf0, 0x9d, 0x1a, 0xf0, + 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x26, 0xf0, 0x29, 0x70, 0x4d, 0x26, 0xf0, 0x8d, 0x26, 0xf0, + 0x60, 0x4a, 0x90, 0x04, 0x9d, 0xc0, 0xf0, 0x60, 0xa8, 0xf0, 0x20, 0x88, 0xf0, 0x40, 0x88, 0xf0, + 0x63, 0x29, 0x03, 0x9d, 0xc3, 0xf0, 0xa9, 0x00, 0x9d, 0xcd, 0xf0, 0x9d, 0xd0, 0xf0, 0x9d, 0xd3, + 0xf0, 0x9d, 0xd6, 0xf0, 0x8d, 0xd9, 0xf0, 0x8d, 0xdc, 0xf0, 0x60, 0xbd, 0xb7, 0xf0, 0xf0, 0x05, + 0xde, 0xb7, 0xf0, 0xf0, 0x12, 0xbd, 0x33, 0xf0, 0xdd, 0xae, 0xf0, 0xd0, 0x0b, 0xbd, 0xb1, 0xf0, + 0x85, 0xfd, 0xbd, 0xb4, 0xf0, 0x85, 0xfe, 0x60, 0xa9, 0x38, 0x8d, 0x00, 0xf0, 0x60, 0xbd, 0xba, + 0xf0, 0xdd, 0xa8, 0xf1, 0xf0, 0x18, 0xde, 0xba, 0xf0, 0xa8, 0x88, 0xb9, 0xf0, 0xf0, 0xf0, 0x0d, + 0x85, 0xfe, 0xb9, 0xe1, 0xf0, 0x85, 0xfd, 0xb9, 0x2f, 0xf1, 0x9d, 0x33, 0xf0, 0x60, 0xa9, 0x20, + 0x8d, 0x00, 0xf0, 0x60, 0xad, 0x00, 0xf0, 0x5d, 0x62, 0xf1, 0x8d, 0x00, 0xf0, 0xa9, 0x01, 0x9d, + 0x30, 0xf0, 0x60, 0xad, 0x00, 0xf0, 0x29, 0x07, 0x8d, 0x81, 0xfc, 0xd0, 0x03, 0x20, 0xe9, 0xf2, + 0x60, 0x00, 0xa2, 0x51, 0xa0, 0xfc, 0x8e, 0x5d, 0xf1, 0x8c, 0x5e, 0xf1, 0x20, 0xcf, 0xf1, 0xa2, + 0x00, 0xa0, 0x09, 0x20, 0x00, 0xf2, 0xa9, 0x07, 0x8d, 0x00, 0xf0, 0x8d, 0x81, 0xfc, 0x60, 0x00, + 0x00, 0x00, 0xa9, 0x00, 0x29, 0xff, 0xf0, 0xf6, 0x4c, 0x29, 0xf3, 0xa9, 0x07, 0x8d, 0x00, 0xf0, + 0x60, 0x00, 0x20, 0x60, 0xec, 0x4c, 0x60, 0xfc, 0x20, 0x80, 0xec, 0x4c, 0x80, 0xfc +}; + +bool SidTune::MUS_mergeParts(Buffer_sidtt<const uint8_t>& musBuf, + Buffer_sidtt<const uint8_t>& strBuf) +{ + Buffer_sidtt<uint8_t> mergeBuf; + + uint_least32_t mergeLen = musBuf.len()+strBuf.len(); + + musDataLen = musBuf.len()-2; + + // Sanity check. I do not trust those MUS/STR files around. + uint_least32_t freeSpace = endian_16(_sidtune_sidplayer1[1],_sidtune_sidplayer1[0]) + - SIDTUNE_MUS_DATA_ADDR; + if ( (musBuf.len()+strBuf.len()-4) > freeSpace) + { + info.statusString = _sidtune_txt_sizeExceeded; + return false; + } + +#ifdef HAVE_EXCEPTIONS + if ( !mergeBuf.assign(new(std::nothrow) uint8_t[mergeLen],mergeLen) ) +#else + if ( !mergeBuf.assign(new uint8_t[mergeLen],mergeLen) ) +#endif + { + info.statusString = _sidtune_txt_notEnoughMemory; + return false; + } + + // Install MUS data #1 including load address. +#ifndef SID_HAVE_BAD_COMPILER + memcpy(mergeBuf.get(),musBuf.get(),musBuf.len()); +#else + memcpy((void*)mergeBuf.get(),musBuf.get(),musBuf.len()); +#endif + + if ( !strBuf.isEmpty() && info.sidChipBase2!=0 ) + { + // Install MUS data #2 _NOT_ including load address. +#ifndef SID_HAVE_BAD_COMPILER + memcpy(mergeBuf.get()+musBuf.len(),strBuf.get()+2,strBuf.len()-2); +#else + memcpy((void*)(mergeBuf.get()+musBuf.len()),strBuf.get()+2,strBuf.len()-2); +#endif + } + + musBuf.assign(mergeBuf.xferPtr(),mergeBuf.xferLen()); + strBuf.erase(); + + return true; +} + +void SidTune::MUS_installPlayer(uint8_t *c64buf) +{ + if (status && (c64buf != 0)) + { + // Install MUS player #1. + uint_least16_t dest = endian_16(_sidtune_sidplayer1[1], + _sidtune_sidplayer1[0]); + memcpy(c64buf+dest,_sidtune_sidplayer1+2,sizeof(_sidtune_sidplayer1)-2); + // Point player #1 to data #1. + c64buf[dest+0xc6e] = SIDTUNE_MUS_DATA_ADDR&0xFF; + c64buf[dest+0xc70] = SIDTUNE_MUS_DATA_ADDR>>8; + + if (info.sidChipBase2 != 0) + { + // Install MUS player #2. + dest = endian_16(_sidtune_sidplayer2[1], + _sidtune_sidplayer2[0]); + memcpy(c64buf+dest,_sidtune_sidplayer2+2,sizeof(_sidtune_sidplayer2)-2); + // Point player #2 to data #2. + c64buf[dest+0xc6e] = (SIDTUNE_MUS_DATA_ADDR+musDataLen)&0xFF; + c64buf[dest+0xc70] = (SIDTUNE_MUS_DATA_ADDR+musDataLen)>>8; + } + } +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/Makefile.am new file mode 100644 index 00000000..e1c06822 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/Makefile.am @@ -0,0 +1,17 @@ + +noinst_LTLIBRARIES = libsidtune.la + +libsidtune_la_SOURCES = IconInfo.cpp \ +InfoFile.cpp \ +MUS.cpp \ +PP20.cpp \ +PP20.h \ +PP20_Defs.h \ +PSID.cpp \ +SidTune.cpp \ +SidTuneCfg.h \ +SidTuneTools.cpp \ +SidTuneTools.h + +# Remove bad default includes +DEFAULT_INCLUDES= diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/Makefile.in new file mode 100644 index 00000000..bb5a7c27 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/Makefile.in @@ -0,0 +1,446 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +noinst_LTLIBRARIES = libsidtune.la + +libsidtune_la_SOURCES = IconInfo.cpp \ +InfoFile.cpp \ +MUS.cpp \ +PP20.cpp \ +PP20.h \ +PP20_Defs.h \ +PSID.cpp \ +SidTune.cpp \ +SidTuneCfg.h \ +SidTuneTools.cpp \ +SidTuneTools.h + + +# Remove bad default includes +DEFAULT_INCLUDES = +subdir = src/sidtune +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libsidtune_la_LDFLAGS = +libsidtune_la_LIBADD = +am_libsidtune_la_OBJECTS = IconInfo.lo InfoFile.lo MUS.lo PP20.lo \ + PSID.lo SidTune.lo SidTuneTools.lo +libsidtune_la_OBJECTS = $(am_libsidtune_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/IconInfo.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/InfoFile.Plo ./$(DEPDIR)/MUS.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/PP20.Plo ./$(DEPDIR)/PSID.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/SidTune.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/SidTuneTools.Plo +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libsidtune_la_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libsidtune_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/sidtune/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libsidtune.la: $(libsidtune_la_OBJECTS) $(libsidtune_la_DEPENDENCIES) + $(CXXLINK) $(libsidtune_la_LDFLAGS) $(libsidtune_la_OBJECTS) $(libsidtune_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IconInfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InfoFile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MUS.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PP20.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSID.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SidTune.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SidTuneTools.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 $(LTLIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +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: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man 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 uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20.cpp new file mode 100644 index 00000000..8bec5cfe --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20.cpp @@ -0,0 +1,289 @@ +/* + * /home/ms/files/source/libsidtune/RCS/PP20.cpp,v + * + * PowerPacker (AMIGA) "PP20" format decompressor. + * Copyright (C) Michael Schwendt <mschwendt@yahoo.com> + * + * 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 "PP20.h" + +#include <string.h> +#ifdef PP20_HAVE_EXCEPTIONS +#include <new> +#endif + +/* Read a big-endian 32-bit word from four bytes in memory. + No endian-specific optimizations applied. */ +inline udword_ppt readBEdword(const ubyte_ppt ptr[4]) +{ + return ( (((udword_ppt)ptr[0])<<24) + (((udword_ppt)ptr[1])<<16) + + (((udword_ppt)ptr[2])<<8) + ((udword_ppt)ptr[3]) ); +} + +const char _pp20_txt_packeddatacorrupt[] = "PowerPacker: Packed data is corrupt"; +const char _pp20_txt_unrecognized[] = "PowerPacker: Unrecognized compression method"; +const char _pp20_txt_uncompressed[] = "Not compressed with PowerPacker (PP20)"; +const char _pp20_txt_notenoughmemory[] = "Not enough free memory"; +const char _pp20_txt_fast[] = "PowerPacker: fast compression"; +const char _pp20_txt_mediocre[] = "PowerPacker: mediocre compression"; +const char _pp20_txt_good[] = "PowerPacker: good compression"; +const char _pp20_txt_verygood[] = "PowerPacker: very good compression"; +const char _pp20_txt_best[] = "PowerPacker: best compression"; +const char _pp20_txt_na[] = "N/A"; + +const char* PP20::PP_ID = "PP20"; + +PP20::PP20() +{ + statusString = _pp20_txt_uncompressed; +} + +bool PP20::isCompressed(const void* source, const udword_ppt size) +{ + // Check minimum input size, PP20 ID, and efficiency table. + if ( size<8 ) + { + return false; + } + // We hope that every file with a valid signature and a valid + // efficiency table is PP-compressed actually. + const char* idPtr = (const char*)source; + if ( strncmp(idPtr,PP_ID,4) != 0 ) + { + statusString = _pp20_txt_uncompressed; + return false; + } + return checkEfficiency(idPtr+4); +} + +bool PP20::checkEfficiency(const void* source) +{ + const udword_ppt PP_BITS_FAST = 0x09090909; + const udword_ppt PP_BITS_MEDIOCRE = 0x090a0a0a; + const udword_ppt PP_BITS_GOOD = 0x090a0b0b; + const udword_ppt PP_BITS_VERYGOOD = 0x090a0c0c; + const udword_ppt PP_BITS_BEST = 0x090a0c0d; + + // Copy efficiency table. + memcpy(efficiency,(const ubyte_ppt*)source,4); + udword_ppt eff = readBEdword(efficiency); + if (( eff != PP_BITS_FAST ) && + ( eff != PP_BITS_MEDIOCRE ) && + ( eff != PP_BITS_GOOD ) && + ( eff != PP_BITS_VERYGOOD ) && + ( eff != PP_BITS_BEST )) + { + statusString = _pp20_txt_unrecognized; + return false; + } + + // Define string describing compression encoding used. + switch ( eff) + { + case PP_BITS_FAST: + statusString = _pp20_txt_fast; + break; + case PP_BITS_MEDIOCRE: + statusString = _pp20_txt_mediocre; + break; + case PP_BITS_GOOD: + statusString = _pp20_txt_good; + break; + case PP_BITS_VERYGOOD: + statusString = _pp20_txt_verygood; + break; + case PP_BITS_BEST: + statusString = _pp20_txt_best; + break; + } + + return true; +} + +// Move four bytes to Motorola big-endian double-word. +inline void PP20::bytesTOdword() +{ + readPtr -= 4; + if ( readPtr < sourceBeg ) + { + statusString = _pp20_txt_packeddatacorrupt; + globalError = true; + } + else + { + current = readBEdword(readPtr); + } +} + +inline udword_ppt PP20::readBits(int count) +{ + udword_ppt data = 0; + // read 'count' bits of packed data + for (; count > 0; count--) + { + // equal to shift left + data += data; + // merge bit 0 + data |= (current&1); + current >>= 1; + if (--bits == 0) + { + bytesTOdword(); + bits = 32; + } + } + return data; +} + +inline void PP20::bytes() +{ + udword_ppt count, add; + count = (add = readBits(2)); + while (add == 3) + { + add = readBits(2); + count += add; + } + for ( ++count; count > 0 ; count--) + { + if (writePtr > destBeg) + { + *(--writePtr) = (ubyte_ppt)readBits(8); + } + else + { + statusString = _pp20_txt_packeddatacorrupt; + globalError = true; + } + } +} + +inline void PP20::sequence() +{ + udword_ppt offset, add; + udword_ppt length = readBits(2); // is length-2 + int offsetBitLen = (int)efficiency[length]; + length += 2; + if ( length != 5 ) + offset = readBits( offsetBitLen ); + else + { + if ( readBits(1) == 0 ) + offsetBitLen = 7; + offset = readBits( offsetBitLen ); + add = readBits(3); + length += add; + while ( add == 7 ) + { + add = readBits(3); + length += add; + } + } + for ( ; length > 0 ; length-- ) + { + if ( writePtr > destBeg ) + { + --writePtr; + *writePtr = *(writePtr+1+offset); + } + else + { + statusString = _pp20_txt_packeddatacorrupt; + globalError = true; + } + } +} + +udword_ppt PP20::decompress(const void* source, + udword_ppt size, + ubyte_ppt** destRef) +{ + globalError = false; // assume no error + + sourceBeg = (const ubyte_ppt*)source; + readPtr = sourceBeg; + + if ( !isCompressed(readPtr,size) ) + { + return 0; + } + + // Uncompressed size is stored at end of source file. + // Backwards decompression. + readPtr += (size-4); + + udword_ppt lastDword = readBEdword(readPtr); + // Uncompressed length in bits 31-8 of last dword. + udword_ppt outputLen = lastDword>>8; + + // Allocate memory for output data. + ubyte_ppt* dest; +#ifdef PP20_HAVE_EXCEPTIONS + if (( dest = new(std::nothrow) ubyte_ppt[outputLen]) == 0 ) +#else + if (( dest = new ubyte_ppt[outputLen]) == 0 ) +#endif + { + statusString = _pp20_txt_notenoughmemory; + return 0; + } + + // Lowest dest. address for range-checks. + destBeg = dest; + // Put destptr to end of uncompressed data. + writePtr = dest+outputLen; + + // Read number of unused bits in 1st data dword + // from lowest bits 7-0 of last dword. + bits = 32 - (lastDword&0xFF); + + // Main decompression loop. + bytesTOdword(); + if ( bits != 32 ) + current >>= (32-bits); + do + { + if ( readBits(1) == 0 ) + bytes(); + if ( writePtr > dest ) + sequence(); + if ( globalError ) + { + // statusString already set. + outputLen = 0; // unsuccessful decompression + break; + } + } while ( writePtr > dest ); + + // Finished. + + if (outputLen > 0) // successful + { + // Free any previously existing destination buffer. + if ( *destRef != 0 ) + { + delete[] *destRef; + } + *destRef = dest; + } + else + { + delete[] dest; + } + + return outputLen; +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20.h b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20.h new file mode 100644 index 00000000..74e7f5f7 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20.h @@ -0,0 +1,70 @@ +/* + * /home/ms/files/source/libsidtune/RCS/PP20.h,v + * + * PowerPacker (AMIGA) "PP20" format decompressor. + * Copyright (C) Michael Schwendt <mschwendt@yahoo.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PP_DECOMPRESSOR_H +#define PP_DECOMPRESSOR_H + +#include "PP20_Defs.h" + +class PP20 +{ + public: + + PP20(); + + bool isCompressed(const void* source, const udword_ppt size); + + // If successful, allocates a new buffer containing the + // uncompresse data and returns the uncompressed length. + // Else, returns 0. + udword_ppt decompress(const void* source, + udword_ppt size, + ubyte_ppt** destRef); + + const char* getStatusString() { return statusString; } + + private: + bool checkEfficiency(const void* source); + + void bytesTOdword(); + udword_ppt readBits(int count); + void bytes(); + void sequence(); + + static const char* PP_ID; + + ubyte_ppt efficiency[4]; + + const ubyte_ppt* sourceBeg; + const ubyte_ppt* readPtr; + + const ubyte_ppt* destBeg; + ubyte_ppt* writePtr; + + udword_ppt current; // compressed data longword + int bits; // number of bits in 'current' to evaluate + + bool globalError; // exception-free version of code + + const char* statusString; +}; + +#endif /* PP_DECOMPRESSOR_H */ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20_Defs.h b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20_Defs.h new file mode 100644 index 00000000..9e3b345b --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PP20_Defs.h @@ -0,0 +1,39 @@ +/* + * /home/ms/files/source/libsidtune/RCS/PP20_Defs.h,v + * + * PowerPacker (AMIGA) "PP20" format decompressor. + * Copyright (C) Michael Schwendt <mschwendt@yahoo.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PP_DECOMPRESSOR_DEFS_H +#define PP_DECOMPRESSOR_DEFS_H + +#include "sidtypes.h" + +#ifdef HAVE_EXCEPTIONS + #define PP20_HAVE_EXCEPTIONS +#else + #undef PP20_HAVE_EXCEPTIONS +#endif + +// Wanted: 8-bit unsigned. +typedef uint_least8_t ubyte_ppt; + +// Wanted: 32-bit unsigned. +typedef uint_least32_t udword_ppt; + +#endif /* PP_DECOMPRESSOR_DEFS_H */ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PSID.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PSID.cpp new file mode 100644 index 00000000..0cc96969 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/PSID.cpp @@ -0,0 +1,313 @@ +/* + * /home/ms/files/source/libsidtune/RCS/PSID.cpp,v + * + * PlaySID one-file format support. + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "SidTuneCfg.h" +#include "SidTune.h" +#include "sidendian.h" + +#define PSID_ID 0x50534944 +#define RSID_ID 0x52534944 + +// Header has been extended for 'RSID' format +// The following changes are present: +// id = 'RSID' +// version = 2 only +// play, load and speed reserved 0 +// psidspecific flag reserved 0 +// init cannot be under ROMS/IO +// load cannot be less than 0x0801 (start of basic) + +struct psidHeader // all values big-endian +{ + char id[4]; // 'PSID' (ASCII) + uint8_t version[2]; // 0x0001 or 0x0002 + uint8_t data[2]; // 16-bit offset to binary data in file + uint8_t load[2]; // 16-bit C64 address to load file to + uint8_t init[2]; // 16-bit C64 address of init subroutine + uint8_t play[2]; // 16-bit C64 address of play subroutine + uint8_t songs[2]; // number of songs + uint8_t start[2]; // start song out of [1..256] + uint8_t speed[4]; // 32-bit speed info + // bit: 0=50 Hz, 1=CIA 1 Timer A (default: 60 Hz) + char name[32]; // ASCII strings, 31 characters long and + char author[32]; // terminated by a trailing zero + char released[32]; // + uint8_t flags[2]; // only version 0x0002 + uint8_t relocStartPage; // only version 0x0002B + uint8_t relocPages; // only version 0x0002B + uint8_t reserved[2]; // only version 0x0002 +}; + +enum +{ + PSID_MUS = 1 << 0, + PSID_SPECIFIC = 1 << 1, + PSID_CLOCK = 3 << 2, + PSID_SIDMODEL = 3 << 4 +}; + +enum +{ + PSID_CLOCK_UNKNOWN = 0, + PSID_CLOCK_PAL = 1 << 2, + PSID_CLOCK_NTSC = 1 << 3, + PSID_CLOCK_ANY = PSID_CLOCK_PAL | PSID_CLOCK_NTSC +}; + +enum +{ + PSID_SIDMODEL_UNKNOWN = 0, + PSID_SIDMODEL_6581 = 1 << 4, + PSID_SIDMODEL_8580 = 1 << 5, + PSID_SIDMODEL_ANY = PSID_SIDMODEL_6581 | PSID_SIDMODEL_8580 +}; + +static const char _sidtune_format_psid[] = "PlaySID one-file format (PSID)"; +static const char _sidtune_format_rsid[] = "Real C64 one-file format (RSID)"; +static const char _sidtune_unknown_psid[] = "Unsupported PSID version"; +static const char _sidtune_unknown_rsid[] = "Unsupported RSID version"; +static const char _sidtune_truncated[] = "ERROR: File is most likely truncated"; +static const char _sidtune_invalid[] = "ERROR: File contains invalid data"; + +const int _sidtune_psid_maxStrLen = 31; + + +bool SidTune::PSID_fileSupport(const void* buffer, const uint_least32_t bufLen) +{ + int clock, compatibility; + uint_least32_t speed; +#ifdef SIDTUNE_PSID2NG + clock = SIDTUNE_CLOCK_UNKNOWN; +#else + clock = info.clockSpeed; +#endif + compatibility = SIDTUNE_COMPATIBILITY_C64; + + // Require minimum size to allow access to the first few bytes. + // Require a valid ID and version number. + const psidHeader* pHeader = (const psidHeader*)buffer; + + // File format check + if (bufLen<6) + return false; + if (endian_big32((const uint_least8_t*)pHeader->id)==PSID_ID) + { + if (endian_big16(pHeader->version) >= 3) + { + info.formatString = _sidtune_unknown_psid; + return false; + } + info.formatString = _sidtune_format_psid; + } + else if (endian_big32((const uint_least8_t*)pHeader->id)==RSID_ID) + { + if (endian_big16(pHeader->version) != 2) + { + info.formatString = _sidtune_unknown_rsid; + return false; + } + info.formatString = _sidtune_format_rsid; + compatibility = SIDTUNE_COMPATIBILITY_R64; + } + else + { + return false; + } + + // Due to security concerns, input must be at least as long as version 1 + // header plus 16-bit C64 load address. That is the area which will be + // accessed. + if ( bufLen < (sizeof(psidHeader)+2) ) + { + info.formatString = _sidtune_truncated; + return false; + } + + fileOffset = endian_big16(pHeader->data); + info.loadAddr = endian_big16(pHeader->load); + info.initAddr = endian_big16(pHeader->init); + info.playAddr = endian_big16(pHeader->play); + info.songs = endian_big16(pHeader->songs); + info.startSong = endian_big16(pHeader->start); + info.sidChipBase1 = 0xd400; + info.sidChipBase2 = 0; + info.compatibility = compatibility; + speed = endian_big32(pHeader->speed); + + if (info.songs > SIDTUNE_MAX_SONGS) + { + info.songs = SIDTUNE_MAX_SONGS; + } + + info.musPlayer = false; + info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN; + info.relocPages = 0; + info.relocStartPage = 0; + if ( endian_big16(pHeader->version) >= 2 ) + { + uint_least16_t flags = endian_big16(pHeader->flags); + if (flags & PSID_MUS) + { // MUS tunes run at any speed + clock = SIDTUNE_CLOCK_ANY; + info.musPlayer = true; + } + +#ifdef SIDTUNE_PSID2NG + if (flags & PSID_SPECIFIC) + info.compatibility = SIDTUNE_COMPATIBILITY_PSID; + + if (flags & PSID_CLOCK_PAL) + clock |= SIDTUNE_CLOCK_PAL; + if (flags & PSID_CLOCK_NTSC) + clock |= SIDTUNE_CLOCK_NTSC; + info.clockSpeed = clock; + + info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN; + if (flags & PSID_SIDMODEL_6581) + info.sidModel |= SIDTUNE_SIDMODEL_6581; + if (flags & PSID_SIDMODEL_8580) + info.sidModel |= SIDTUNE_SIDMODEL_8580; + + info.relocStartPage = pHeader->relocStartPage; + info.relocPages = pHeader->relocPages; +#endif // SIDTUNE_PSID2NG + } + + // Reserved meaning for possible future use + if ( info.playAddr == 0xffff ) + info.playAddr = 0; + + // Check reserved fields to force real c64 compliance + if (compatibility == SIDTUNE_COMPATIBILITY_R64) + { + if (checkRealC64Info (speed) == false) + { + info.formatString = _sidtune_invalid; + return false; + } + // Real C64 tunes appear as CIA + speed = ~0; + } + // Create the speed/clock setting table. + convertOldStyleSpeedToTables(speed, clock); + + if ( info.loadAddr == 0 ) + { + uint_least8_t* pData = (uint_least8_t*)buffer + fileOffset; + info.loadAddr = endian_16( *(pData+1), *pData ); + fileOffset += 2; + } + + info.c64dataLen = bufLen - fileOffset; + if ( resolveAddrs((uint_least8_t*)buffer + fileOffset) == false ) + return false; + + if ( checkRelocInfo() == false ) + return false; + + // Copy info strings, so they will not get lost. + info.numberOfInfoStrings = 3; + // Name + strncpy(&infoString[0][0],pHeader->name,_sidtune_psid_maxStrLen); + info.infoString[0] = &infoString[0][0]; + // Author + strncpy(&infoString[1][0],pHeader->author,_sidtune_psid_maxStrLen); + info.infoString[1] = &infoString[1][0]; + // Released + strncpy(&infoString[2][0],pHeader->released,_sidtune_psid_maxStrLen); + info.infoString[2] = &infoString[2][0]; + return true; +} + + +bool SidTune::PSID_fileSupportSave(std::ofstream& fMyOut, const uint_least8_t* dataBuffer) +{ + psidHeader myHeader; + endian_big32((uint_least8_t*)myHeader.id,PSID_ID); + endian_big16(myHeader.version,2); + endian_big16(myHeader.data,sizeof(psidHeader)); + endian_big16(myHeader.load,0); + endian_big16(myHeader.init,info.initAddr); + endian_big16(myHeader.play,info.playAddr); + endian_big16(myHeader.songs,info.songs); + endian_big16(myHeader.start,info.startSong); + + uint_least32_t speed = 0, check = 0; + uint_least32_t maxBugSongs = ((info.songs <= 32) ? info.songs : 32); + for (uint_least32_t s = 0; s < maxBugSongs; s++) + { + if (songSpeed[s] == SIDTUNE_SPEED_CIA_1A) + speed |= (1<<s); + check |= (1<<s); + } + endian_big32(myHeader.speed,speed); + + uint_least16_t tmpFlags = 0; + if ( info.musPlayer ) + tmpFlags |= PSID_MUS; + + if (info.compatibility == SIDTUNE_COMPATIBILITY_PSID) + tmpFlags |= PSID_SPECIFIC; + + tmpFlags |= (info.clockSpeed << 2); + tmpFlags |= (info.sidModel << 4); + endian_big16(myHeader.flags,tmpFlags); + endian_big16(myHeader.reserved,0); + myHeader.relocStartPage = info.relocStartPage; + myHeader.relocPages = info.relocPages; + + for ( uint i = 0; i < 32; i++ ) + { + myHeader.name[i] = 0; + myHeader.author[i] = 0; + myHeader.released[i] = 0; + } + strncpy( myHeader.name, info.infoString[0], _sidtune_psid_maxStrLen); + strncpy( myHeader.author, info.infoString[1], _sidtune_psid_maxStrLen); + strncpy( myHeader.released, info.infoString[2], _sidtune_psid_maxStrLen); + + if (info.compatibility == SIDTUNE_COMPATIBILITY_R64) + { + endian_big32((uint_least8_t*)myHeader.id,RSID_ID); + endian_big16(myHeader.play,0); + endian_big32(myHeader.speed,0); + } + + fMyOut.write( (char*)&myHeader, sizeof(psidHeader) ); + + // Save C64 lo/hi load address (little-endian). + uint_least8_t saveAddr[2]; + saveAddr[0] = info.loadAddr & 255; + saveAddr[1] = info.loadAddr >> 8; + fMyOut.write( (char*)saveAddr, 2 ); // !cast! + + // Data starts at: bufferaddr + fileoffset + // Data length: datafilelen - fileoffset + fMyOut.write( (const char*)dataBuffer + fileOffset, info.dataFileLen - fileOffset ); // !cast! + if ( !fMyOut ) + return false; + else + return true; +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTune.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTune.cpp new file mode 100644 index 00000000..29638775 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTune.cpp @@ -0,0 +1,1150 @@ +/* + * /home/ms/files/source/libsidtune/RCS/SidTune.cpp,v + * + * 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 _SidTune_cpp_ + +#include "config.h" +#include "SidTuneCfg.h" +#include "SidTune.h" +#include "SidTuneTools.h" +#include "sidendian.h" +#include "PP20.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif +#include <iostream> +#include <iomanip> +#include <string.h> +#include <limits.h> + +#if defined(HAVE_IOS_OPENMODE) + typedef std::ios::openmode openmode; +#else + typedef int openmode; +#endif + +// Used in address resolution procedure +#define SIDTUNE_BASIC_START 0x0801 + +const char* SidTune::txt_songNumberExceed = "SIDTUNE WARNING: Selected song number was too high"; +const char* SidTune::txt_empty = "SIDTUNE ERROR: No data to load"; +const char* SidTune::txt_unrecognizedFormat = "SIDTUNE ERROR: Could not determine file format"; +const char* SidTune::txt_noDataFile = "SIDTUNE ERROR: Did not find the corresponding data file"; +const char* SidTune::txt_notEnoughMemory = "SIDTUNE ERROR: Not enough free memory"; +const char* SidTune::txt_cantLoadFile = "SIDTUNE ERROR: Could not load input file"; +const char* SidTune::txt_cantOpenFile = "SIDTUNE ERROR: Could not open file for binary input"; +const char* SidTune::txt_fileTooLong = "SIDTUNE ERROR: Input data too long"; +const char* SidTune::txt_dataTooLong = "SIDTUNE ERROR: Size of music data exceeds C64 memory"; +const char* SidTune::txt_cantCreateFile = "SIDTUNE ERROR: Could not create output file"; +const char* SidTune::txt_fileIoError = "SIDTUNE ERROR: File I/O error"; +const char* SidTune::txt_VBI = "VBI"; +const char* SidTune::txt_CIA = "CIA 1 Timer A"; +const char* SidTune::txt_noErrors = "No errors"; +const char* SidTune::txt_na = "N/A"; +const char* SidTune::txt_badAddr = "SIDTUNE ERROR: Bad address data"; +const char* SidTune::txt_badReloc = "SIDTUNE ERROR: Bad reloc data"; + +// Default sidtune file name extensions. This selection can be overriden +// by specifying a custom list in the constructor. +const char* defaultFileNameExt[] = +{ + // Preferred default file extension for single-file sidtunes + // or sidtune description files in SIDPLAY INFOFILE format. + ".sid", + // Common file extension for single-file sidtunes due to SIDPLAY/DOS + // displaying files *.DAT in its file selector by default. + // Originally this was intended to be the extension of the raw data file + // of two-file sidtunes in SIDPLAY INFOFILE format. + ".dat", + // Extension of Amiga Workbench tooltype icon info files, which + // have been cut to MS-DOS file name length (8.3). + ".inf", + // No extension for the raw data file of two-file sidtunes in + // PlaySID Amiga Workbench tooltype icon info format. + "", + // Common upper-case file extensions from MS-DOS (unconverted). + ".DAT", ".SID", ".INF", + // File extensions used (and created) by various C64 emulators and + // related utilities. These extensions are recommended to be used as + // a replacement for ".dat" in conjunction with two-file sidtunes. + ".c64", ".prg", ".C64", ".PRG", + // Uncut extensions from Amiga. + ".info", ".INFO", ".data", ".DATA", + // Stereo Sidplayer (.mus/.MUS ought not be included because + // these must be loaded first; it sometimes contains the first + // credit lines of a MUS/STR pair). + ".str", ".STR", ".mus", ".MUS", + // End. + 0 +}; + +const char** SidTune::fileNameExtensions = defaultFileNameExt; + +inline void SidTune::setFileNameExtensions(const char **fileNameExt) +{ + fileNameExtensions = ((fileNameExt!=0)?fileNameExt:defaultFileNameExt); +} + +SidTune::SidTune(const char* fileName, const char **fileNameExt, + const bool separatorIsSlash) +{ + init(); + isSlashedFileName = separatorIsSlash; + setFileNameExtensions(fileNameExt); +#if !defined(SIDTUNE_NO_STDIN_LOADER) + // Filename ``-'' is used as a synonym for standard input. + if ( fileName!=0 && (strcmp(fileName,"-")==0) ) + { + getFromStdIn(); + } + else +#endif + if (fileName != 0) + { + getFromFiles(fileName); + } +} + +SidTune::SidTune(const uint_least8_t* data, const uint_least32_t dataLen) +{ + init(); + getFromBuffer(data,dataLen); +} + +SidTune::~SidTune() +{ + cleanup(); +} + +bool SidTune::load(const char* fileName, const bool separatorIsSlash) +{ + cleanup(); + init(); + isSlashedFileName = separatorIsSlash; + getFromFiles(fileName); + return status; +} + +bool SidTune::read(const uint_least8_t* data, uint_least32_t dataLen) +{ + cleanup(); + init(); + getFromBuffer(data,dataLen); + return status; +} + +const SidTuneInfo& SidTune::operator[](const uint_least16_t songNum) +{ + selectSong(songNum); + return info; +} + +void SidTune::getInfo(SidTuneInfo& outInfo) +{ + outInfo = info; // copy +} + +const SidTuneInfo& SidTune::getInfo() +{ + return info; +} + +// First check, whether a song is valid. Then copy any song-specific +// variable information such a speed/clock setting to the info structure. +uint_least16_t SidTune::selectSong(const uint_least16_t selectedSong) +{ + if ( !status ) + return 0; + else + info.statusString = SidTune::txt_noErrors; + + uint_least16_t song = selectedSong; + // Determine and set starting song number. + if (selectedSong == 0) + song = info.startSong; + if (selectedSong>info.songs || selectedSong>SIDTUNE_MAX_SONGS) + { + song = info.startSong; + info.statusString = SidTune::txt_songNumberExceed; + } + info.currentSong = song; + info.songLength = songLength[song-1]; + // Retrieve song speed definition. + info.songSpeed = songSpeed[song-1]; + info.clockSpeed = clockSpeed[song-1]; + // Assign song speed description string depending on clock speed. + // Final speed description is available only after song init. + if (info.songSpeed == SIDTUNE_SPEED_VBI) + info.speedString = txt_VBI; + else + info.speedString = txt_CIA; + return info.currentSong; +} + +void SidTune::fixLoadAddress(bool force, uint_least16_t init, uint_least16_t play) +{ + if (info.fixLoad || force) + { + info.fixLoad = false; + info.loadAddr += 2; + fileOffset += 2; + + if (force) + { + info.initAddr = init; + info.playAddr = play; + } + } +} + +// ------------------------------------------------- private member functions + +bool SidTune::placeSidTuneInC64mem(uint_least8_t* c64buf) +{ + if ( status && c64buf!=0 ) + { + uint_least32_t endPos = info.loadAddr + info.c64dataLen; + if (endPos <= SIDTUNE_MAX_MEMORY) + { + // Copy data from cache to the correct destination. + memcpy(c64buf+info.loadAddr,cache.get()+fileOffset,info.c64dataLen); + info.statusString = SidTune::txt_noErrors; + } + else + { + // Security - cut data which would exceed the end of the C64 + // memory. Memcpy could not detect this. + // + // NOTE: In libsidplay1 the rest gets wrapped to the beginning + // of the C64 memory. It is an undocumented hack most likely not + // used by any sidtune. Here we no longer do it like that, set + // an error message, and hope the modified behaviour will find + // a few badly ripped sids. + memcpy(c64buf+info.loadAddr,cache.get()+fileOffset,info.c64dataLen-(endPos-SIDTUNE_MAX_MEMORY)); + info.statusString = SidTune::txt_dataTooLong; + } + if (info.musPlayer) + { + MUS_installPlayer(c64buf); + } + } + return ( status && c64buf!=0 ); +} + +bool SidTune::loadFile(const char* fileName, Buffer_sidtt<const uint_least8_t>& bufferRef) +{ + Buffer_sidtt<uint_least8_t> fileBuf; + uint_least32_t fileLen = 0; + + // This sucks big time + //openmode createAtrr = std::ios::in; + std::_Ios_Openmode createAtrr = std::ios::in; +#ifdef HAVE_IOS_NOCREATE + createAtrr |= std::ios::nocreate; +#endif + // Open binary input file stream at end of file. +#if defined(HAVE_IOS_BIN) + createAtrr |= std::ios::bin; +#else + createAtrr |= std::ios::binary; +#endif + + std::fstream myIn(fileName,createAtrr); + // As a replacement for !is_open(), bad() and the NOT-operator don't seem + // to work on all systems. +#if defined(DONT_HAVE_IS_OPEN) + if ( !myIn ) +#else + if ( !myIn.is_open() ) +#endif + { + info.statusString = SidTune::txt_cantOpenFile; + return false; + } + else + { +#if defined(HAVE_SEEKG_OFFSET) + fileLen = (myIn.seekg(0,std::ios::end)).offset(); +#else + myIn.seekg(0,std::ios::end); + fileLen = (uint_least32_t)myIn.tellg(); +#endif +#ifdef HAVE_EXCEPTIONS + if ( !fileBuf.assign(new(std::nothrow) uint_least8_t[fileLen],fileLen) ) +#else + if ( !fileBuf.assign(new uint_least8_t[fileLen],fileLen) ) +#endif + { + info.statusString = SidTune::txt_notEnoughMemory; + return false; + } + myIn.seekg(0,std::ios::beg); + uint_least32_t restFileLen = fileLen; + // 16-bit compatible loading. Is this really necessary? + while ( restFileLen > INT_MAX ) + { + myIn.read((char*)fileBuf.get()+(fileLen-restFileLen),INT_MAX); // !cast! + restFileLen -= INT_MAX; + } + if ( restFileLen > 0 ) + { + myIn.read((char*)fileBuf.get()+(fileLen-restFileLen),restFileLen); // !cast! + } + if ( myIn.bad() ) + { + info.statusString = SidTune::txt_cantLoadFile; + return false; + } + else + { + info.statusString = SidTune::txt_noErrors; + } + } + myIn.close(); + if ( fileLen==0 ) + { + info.statusString = SidTune::txt_empty; + return false; + } + + // Check for PowerPacker compression: load and decompress, if PP20 file. + PP20 myPP; + if ( myPP.isCompressed(fileBuf.get(),fileBuf.len()) ) + { + uint_least8_t* destBufRef = 0; + if ( 0 == (fileLen = myPP.decompress(fileBuf.get(),fileBuf.len(), + &destBufRef)) ) + { + info.statusString = myPP.getStatusString(); + return false; + } + else + { + info.statusString = myPP.getStatusString(); + // Replace compressed buffer with uncompressed buffer. + fileBuf.assign(destBufRef,fileLen); + } + } + + bufferRef.assign(fileBuf.xferPtr(),fileBuf.xferLen()); + + return true; +} + +void SidTune::deleteFileNameCopies() +{ + // When will it be fully safe to call delete[](0) on every system? + if ( info.dataFileName != 0 ) + delete[] info.dataFileName; + if ( info.infoFileName != 0 ) + delete[] info.infoFileName; + if ( info.path != 0 ) + delete[] info.path; + info.dataFileName = 0; + info.infoFileName = 0; + info.path = 0; +} + +void SidTune::init() +{ + // Initialize the object with some safe defaults. + status = false; + + info.statusString = SidTune::txt_na; + info.path = info.infoFileName = info.dataFileName = 0; + info.dataFileLen = info.c64dataLen = 0; + info.formatString = SidTune::txt_na; + info.speedString = SidTune::txt_na; + info.loadAddr = ( info.initAddr = ( info.playAddr = 0 )); + info.songs = ( info.startSong = ( info.currentSong = 0 )); + info.sidChipBase1 = 0xd400; + info.sidChipBase2 = 0; + info.musPlayer = false; + info.fixLoad = false; + info.songSpeed = SIDTUNE_SPEED_VBI; +#ifdef SIDTUNE_PSID2NG + info.clockSpeed = SIDTUNE_CLOCK_UNKNOWN; + info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN; +#else + info.clockSpeed = SIDTUNE_CLOCK_PAL; + info.sidModel = SIDTUNE_SIDMODEL_6581; +#endif + info.compatibility = SIDTUNE_COMPATIBILITY_C64; + info.songLength = 0; + info.relocStartPage = 0; + info.relocPages = 0; + + for ( uint_least16_t si = 0; si < SIDTUNE_MAX_SONGS; si++ ) + { + songSpeed[si] = info.songSpeed; + clockSpeed[si] = info.clockSpeed; + songLength[si] = 0; + } + + fileOffset = 0; + musDataLen = 0; + + for ( uint_least16_t sNum = 0; sNum < SIDTUNE_MAX_CREDIT_STRINGS; sNum++ ) + { + for ( uint_least16_t sPos = 0; sPos < SIDTUNE_MAX_CREDIT_STRLEN; sPos++ ) + { + infoString[sNum][sPos] = 0; + } + } + info.numberOfInfoStrings = 0; + + // Not used!!! + info.numberOfCommentStrings = 1; +#ifdef HAVE_EXCEPTIONS + info.commentString = new(std::nothrow) char* [info.numberOfCommentStrings]; +#else + info.commentString = new char* [info.numberOfCommentStrings]; +#endif + if (info.commentString != 0) + info.commentString[0] = SidTuneTools::myStrDup("--- SAVED WITH SIDPLAY ---"); + else + info.commentString[0] = 0; +} + +void SidTune::cleanup() +{ + // Remove copy of comment field. + uint_least32_t strNum = 0; + // Check and remove every available line. + while (info.numberOfCommentStrings-- > 0) + { + if (info.commentString[strNum] != 0) + { + delete[] info.commentString[strNum]; + info.commentString[strNum] = 0; + } + strNum++; // next string + }; + delete[] info.commentString; // free the array pointer + + deleteFileNameCopies(); + + status = false; +} + +#if !defined(SIDTUNE_NO_STDIN_LOADER) + +void SidTune::getFromStdIn() +{ + // Assume a failure, so we can simply return. + status = false; + // Assume the memory allocation to fail. + info.statusString = SidTune::txt_notEnoughMemory; + uint_least8_t* fileBuf; +#ifdef HAVE_EXCEPTIONS + if ( 0 == (fileBuf = new(std::nothrow) uint_least8_t[SIDTUNE_MAX_FILELEN]) ) +#else + if ( 0 == (fileBuf = new uint_least8_t[SIDTUNE_MAX_FILELEN]) ) +#endif + { + return; + } + // We only read as much as fits in the buffer. + // This way we avoid choking on huge data. + uint_least32_t i = 0; + char datb; + while (std::cin.get(datb) && i<SIDTUNE_MAX_FILELEN) + fileBuf[i++] = (uint_least8_t) datb; + info.dataFileLen = i; + getFromBuffer(fileBuf,info.dataFileLen); + delete[] fileBuf; +} + +#endif + +void SidTune::getFromBuffer(const uint_least8_t* const buffer, const uint_least32_t bufferLen) +{ + // Assume a failure, so we can simply return. + status = false; + + if (buffer==0 || bufferLen==0) + { + info.statusString = SidTune::txt_empty; + return; + } + else if (bufferLen > SIDTUNE_MAX_FILELEN) + { + info.statusString = SidTune::txt_fileTooLong; + return; + } + + uint_least8_t* tmpBuf; +#ifdef HAVE_EXCEPTIONS + if ( 0 == (tmpBuf = new(std::nothrow) uint_least8_t[bufferLen]) ) +#else + if ( 0 == (tmpBuf = new uint_least8_t[bufferLen]) ) +#endif + { + info.statusString = SidTune::txt_notEnoughMemory; + return; + } + memcpy(tmpBuf,buffer,bufferLen); + + Buffer_sidtt<const uint_least8_t> buf1(tmpBuf,bufferLen); + Buffer_sidtt<const uint_least8_t> buf2; // empty + + bool foundFormat = false; + // Here test for the possible single file formats. -------------- + if ( PSID_fileSupport( buffer, bufferLen )) + { + foundFormat = true; + } + else if ( MUS_fileSupport(buf1,buf2) ) + { + foundFormat = MUS_mergeParts(buf1,buf2); + } + else + { + // No further single-file-formats available. + info.statusString = SidTune::txt_unrecognizedFormat; + } + if ( foundFormat ) + { + status = acceptSidTune("-","-",buf1); + } +} + +bool SidTune::acceptSidTune(const char* dataFileName, const char* infoFileName, + Buffer_sidtt<const uint_least8_t>& buf) +{ + deleteFileNameCopies(); + // Make a copy of the data file name and path, if available. + if ( dataFileName != 0 ) + { + info.path = SidTuneTools::myStrDup(dataFileName); + if (isSlashedFileName) + { + info.dataFileName = SidTuneTools::myStrDup(SidTuneTools::slashedFileNameWithoutPath(info.path)); + *SidTuneTools::slashedFileNameWithoutPath(info.path) = 0; // path only + } + else + { + info.dataFileName = SidTuneTools::myStrDup(SidTuneTools::fileNameWithoutPath(info.path)); + *SidTuneTools::fileNameWithoutPath(info.path) = 0; // path only + } + if ((info.path==0) || (info.dataFileName==0)) + { + info.statusString = SidTune::txt_notEnoughMemory; + return false; + } + } + else + { + // Provide empty strings. + info.path = SidTuneTools::myStrDup(""); + info.dataFileName = SidTuneTools::myStrDup(""); + } + // Make a copy of the info file name, if available. + if ( infoFileName != 0 ) + { + char* tmp = SidTuneTools::myStrDup(infoFileName); + if (isSlashedFileName) + info.infoFileName = SidTuneTools::myStrDup(SidTuneTools::slashedFileNameWithoutPath(tmp)); + else + info.infoFileName = SidTuneTools::myStrDup(SidTuneTools::fileNameWithoutPath(tmp)); + if ((tmp==0) || (info.infoFileName==0)) + { + info.statusString = SidTune::txt_notEnoughMemory; + return false; + } + delete[] tmp; + } + else + { + // Provide empty string. + info.infoFileName = SidTuneTools::myStrDup(""); + } + // Fix bad sidtune set up. + if (info.songs > SIDTUNE_MAX_SONGS) + info.songs = SIDTUNE_MAX_SONGS; + else if (info.songs == 0) + info.songs++; + if (info.startSong > info.songs) + info.startSong = 1; + else if (info.startSong == 0) + info.startSong++; + + if ( info.musPlayer ) + MUS_setPlayerAddress(); + + info.dataFileLen = buf.len(); + info.c64dataLen = buf.len() - fileOffset; + + if (info.dataFileLen >= 2) + { + // We only detect an offset of two. Some position independent + // sidtunes contain a load address of 0xE000, but are loaded + // to 0x0FFE and call player at 0x1000. + info.fixLoad = (endian_little16(buf.get()+fileOffset)==(info.loadAddr+2)); + } + + // Check the size of the data. + if ( info.c64dataLen > SIDTUNE_MAX_MEMORY ) + { + info.statusString = SidTune::txt_dataTooLong; + return false; + } + else if ( info.c64dataLen == 0 ) + { + info.statusString = SidTune::txt_empty; + return false; + } + + cache.assign(buf.xferPtr(),buf.xferLen()); + + info.statusString = SidTune::txt_noErrors; + return true; +} + +bool SidTune::createNewFileName(Buffer_sidtt<char>& destString, + const char* sourceName, + const char* sourceExt) +{ + Buffer_sidtt<char> newBuf; + uint_least32_t newLen = strlen(sourceName)+strlen(sourceExt)+1; + // Get enough memory, so we can appended the extension. +#ifdef HAVE_EXCEPTIONS + newBuf.assign(new(std::nothrow) char[newLen],newLen); +#else + newBuf.assign(new char[newLen],newLen); +#endif + if ( newBuf.isEmpty() ) + { + info.statusString = SidTune::txt_notEnoughMemory; + return (status = false); + } + strcpy(newBuf.get(),sourceName); + strcpy(SidTuneTools::fileExtOfPath(newBuf.get()),sourceExt); + destString.assign(newBuf.xferPtr(),newBuf.xferLen()); + return true; +} + +// Initializing the object based upon what we find in the specified file. + +void SidTune::getFromFiles(const char* fileName) +{ + // Assume a failure, so we can simply return. + status = false; + + Buffer_sidtt<const uint_least8_t> fileBuf1, fileBuf2; + Buffer_sidtt<char> fileName2; + + // Try to load the single specified file. + if ( loadFile(fileName,fileBuf1) ) + { + // File loaded. Now check if it is in a valid single-file-format. + if ( PSID_fileSupport(fileBuf1.get(),fileBuf1.len()) ) + { + status = acceptSidTune(fileName,0,fileBuf1); + return; + } + else if ( MUS_fileSupport(fileBuf1,fileBuf2) ) + { + // Try to find second file. + int n = 0; + while (fileNameExtensions[n] != 0) + { + if ( !createNewFileName(fileName2,fileName,fileNameExtensions[n]) ) + return; + // 1st data file was loaded into ``fileBuf1'', + // so we load the 2nd one into ``fileBuf2''. + // Do not load the first file again if names are equal. + if ( MYSTRICMP(fileName,fileName2.get())!=0 && + loadFile(fileName2.get(),fileBuf2) ) + { + if ( MUS_fileSupport(fileBuf1,fileBuf2) ) + { + if ( MUS_mergeParts(fileBuf1,fileBuf2) ) + { + status = acceptSidTune(fileName,fileName2.get(), + fileBuf1); + } + return; // in either case + } + } + n++; + }; + // No second file. + status = acceptSidTune(fileName,0,fileBuf1); + return; + } + +// -------------------------------------- Support for multiple-files formats. + else + { +// We cannot simply try to load additional files, if a description file was +// specified. It would work, but is error-prone. Imagine a filename mismatch +// or more than one description file (in another) format. Any other file +// with an appropriate file name can be the C64 data file. + +// First we see if ``fileName'' could be a raw data file. In that case we +// have to find the corresponding description file. + + // Right now we do not have a second file. Hence the (0, 0, ...) + // parameters are set for the data buffer. This will not hurt the + // file support procedures. + + // Make sure that ``fileBuf1'' does not contain a description file. + if ( !SID_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) && + !INFO_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) ) + { + // Assuming ``fileName'' to hold the name of the raw data file, + // we now create the name of a description file (=fileName2) by + // appending various filename extensions. + +// ------------------------------------------ Looking for a description file. + + int n = 0; + while (fileNameExtensions[n] != 0) + { + if ( !createNewFileName(fileName2,fileName,fileNameExtensions[n]) ) + return; + // 1st data file was loaded into ``fileBuf1'', + // so we load the 2nd one into ``fileBuf2''. + // Do not load the first file again if names are equal. + if ( MYSTRICMP(fileName,fileName2.get())!=0 && + loadFile(fileName2.get(),fileBuf2) ) + { + if ( SID_fileSupport(fileBuf1.get(),fileBuf1.len(), + fileBuf2.get(),fileBuf2.len()) + || INFO_fileSupport(fileBuf1.get(),fileBuf1.len(), + fileBuf2.get(),fileBuf2.len()) + ) + { + status = acceptSidTune(fileName,fileName2.get(), + fileBuf1); + return; + } + } + n++; + }; + +// --------------------------------------- Could not find a description file. + + info.statusString = SidTune::txt_unrecognizedFormat; + return; + } + +// ------------------------------------------------------------------------- +// Still unsuccessful ? Probably one put a description file name into +// ``fileName''. Assuming ``fileName'' to hold the name of a description +// file, we now create the name of the data file and swap both used memory +// buffers - fileBuf1 and fileBuf2 - when calling the format support. +// If it works, the second file is the data file ! If it is not, but does +// exist, we are out of luck, since we cannot detect data files. + + // Make sure ``fileBuf1'' contains a description file. + else if ( SID_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) || + INFO_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) ) + { + +// --------------------- Description file found. --- Looking for a data file. + + int n = 0; + while (fileNameExtensions[n] != 0) + { + if ( !createNewFileName(fileName2,fileName,fileNameExtensions[n]) ) + return; + // 1st info file was loaded into ``fileBuf'', + // so we load the 2nd one into ``fileBuf2''. + // Do not load the first file again if names are equal. + if ( MYSTRICMP(fileName,fileName2.get())!=0 && + + loadFile(fileName2.get(),fileBuf2) ) + { +// -------------- Some data file found, now identifying the description file. + + if ( SID_fileSupport(fileBuf2.get(),fileBuf2.len(), + fileBuf1.get(),fileBuf1.len()) + || INFO_fileSupport(fileBuf2.get(),fileBuf2.len(), + fileBuf1.get(),fileBuf1.len()) + ) + { + status = acceptSidTune(fileName2.get(),fileName, + fileBuf2); + return; + } + } + n++; + }; + +// ---------------------------------------- No corresponding data file found. + + info.statusString = SidTune::txt_noDataFile; + return; + } // end else if ( = is description file ) + +// --------------------------------- Neither description nor data file found. + + else + { + info.statusString = SidTune::txt_unrecognizedFormat; + return; + } + } // end else ( = is no singlefile ) + +// ---------------------------------------------------------- File I/O error. + + } // if loaddatafile + else + { + // returned fileLen was 0 = error. The info.statusString is + // already set then. + return; + } +} + +void SidTune::convertOldStyleSpeedToTables(uint_least32_t speed, int clock) +{ + // Create the speed/clock setting tables. + // + // This does not take into account the PlaySID bug upon evaluating the + // SPEED field. It would most likely break compatibility to lots of + // sidtunes, which have been converted from .SID format and vice versa. + // The .SID format does the bit-wise/song-wise evaluation of the SPEED + // value correctly, like it is described in the PlaySID documentation. + + int toDo = ((info.songs <= SIDTUNE_MAX_SONGS) ? info.songs : SIDTUNE_MAX_SONGS); + for (int s = 0; s < toDo; s++) + { + clockSpeed[s] = clock; + if (( (speed>>(s&31)) & 1 ) == 0 ) + songSpeed[s] = SIDTUNE_SPEED_VBI; + else + songSpeed[s] = SIDTUNE_SPEED_CIA_1A; + } +} + +// +// File format conversion --------------------------------------------------- +// + +bool SidTune::saveToOpenFile(std::ofstream& toFile, const uint_least8_t* buffer, + uint_least32_t bufLen ) +{ + uint_least32_t lenToWrite = bufLen; + while ( lenToWrite > INT_MAX ) + { + toFile.write((char*)buffer+(bufLen-lenToWrite),INT_MAX); + lenToWrite -= INT_MAX; + } + if ( lenToWrite > 0 ) + toFile.write((char*)buffer+(bufLen-lenToWrite),lenToWrite); + if ( toFile.bad() ) + { + info.statusString = SidTune::txt_fileIoError; + return false; + } + else + { + info.statusString = SidTune::txt_noErrors; + return true; + } +} + +bool SidTune::saveC64dataFile( const char* fileName, bool overWriteFlag ) +{ + bool success = false; // assume error + // This prevents saving from a bad object. + if ( status ) + { + // Open binary output file stream. + //openmode createAttr = std::ios::out; + std::_Ios_Openmode createAttr = std::ios::out; +#if defined(HAVE_IOS_BIN) + createAttr |= std::ios::bin; +#else + createAttr |= std::ios::binary; +#endif + if ( overWriteFlag ) + createAttr |= std::ios::trunc; + else + createAttr |= std::ios::app; + std::ofstream fMyOut( fileName, createAttr ); + if ( !fMyOut || fMyOut.tellp()>0 ) + { + info.statusString = SidTune::txt_cantCreateFile; + } + else + { + // Save c64 lo/hi load address. + uint_least8_t saveAddr[2]; + saveAddr[0] = info.loadAddr & 255; + saveAddr[1] = info.loadAddr >> 8; + fMyOut.write((char*)saveAddr,2); + // Data starts at: bufferaddr + fileOffset + // Data length: info.dataFileLen - fileOffset + if ( !saveToOpenFile( fMyOut,cache.get()+fileOffset, info.dataFileLen - fileOffset ) ) + { + info.statusString = SidTune::txt_fileIoError; + } + else + { + info.statusString = SidTune::txt_noErrors; + success = true; + } + fMyOut.close(); + } + } + return success; +} + +bool SidTune::saveSIDfile( const char* fileName, bool overWriteFlag ) +{ + bool success = false; // assume error + // This prevents saving from a bad object. + if ( status ) + { + // Open ASCII output file stream. +// openmode createAttr = std::ios::out; + std::_Ios_Openmode createAttr = std::ios::out; + if ( overWriteFlag ) + createAttr |= std::ios::trunc; + else + createAttr |= std::ios::app; + std::ofstream fMyOut( fileName, createAttr ); + if ( !fMyOut || fMyOut.tellp()>0 ) + { + info.statusString = SidTune::txt_cantCreateFile; + } + else + { + if ( !SID_fileSupportSave( fMyOut ) ) + { + info.statusString = SidTune::txt_fileIoError; + } + else + { + info.statusString = SidTune::txt_noErrors; + success = true; + } + fMyOut.close(); + } + } + return success; +} + +bool SidTune::savePSIDfile( const char* fileName, bool overWriteFlag ) +{ + bool success = false; // assume error + // This prevents saving from a bad object. + if ( status ) + { + // Open binary output file stream. + //openmode createAttr = std::ios::out; + std::_Ios_Openmode createAttr = std::ios::out; +#if defined(HAVE_IOS_BIN) + createAttr |= std::ios::bin; +#else + createAttr |= std::ios::binary; +#endif + if ( overWriteFlag ) + createAttr |= std::ios::trunc; + else + createAttr |= std::ios::app; + std::ofstream fMyOut( fileName, createAttr ); + if ( !fMyOut || fMyOut.tellp()>0 ) + { + info.statusString = SidTune::txt_cantCreateFile; + } + else + { + if ( !PSID_fileSupportSave( fMyOut,cache.get() ) ) + { + info.statusString = SidTune::txt_fileIoError; + } + else + { + info.statusString = SidTune::txt_noErrors; + success = true; + } + fMyOut.close(); + } + } + return success; +} + +bool SidTune::checkRealC64Info (uint_least32_t speed) +{ + if (info.loadAddr != 0) + return false; + if (info.playAddr != 0) + return false; + if (speed != 0) + return false; + if (info.compatibility == SIDTUNE_COMPATIBILITY_PSID) + return false; + return true; +} + +bool SidTune::checkRealC64Init (void) +{ + if (info.initAddr == 0) + info.initAddr = info.loadAddr; + + // Check valid init address + switch (info.initAddr >> 12) + { + case 0x0F: + case 0x0E: + case 0x0D: + case 0x0B: + case 0x0A: + return false; + default: + if ( (info.initAddr < info.loadAddr) || + (info.initAddr > (info.loadAddr + info.c64dataLen - 1)) ) + { + return false; + } + } + return true; +} + +bool SidTune::checkRelocInfo (void) +{ + uint_least8_t startp, endp; + + // Fix relocation information + if (info.relocStartPage == 0xFF) + { + info.relocPages = 0; + return true; + } + else if (info.relocPages == 0) + { + info.relocStartPage = 0; + return true; + } + + // Calculate start/end page + startp = info.relocStartPage; + endp = (startp + info.relocPages - 1) & 0xff; + if (endp < startp) + { + info.formatString = txt_badReloc; + return false; + } + + { // Check against load range + uint_least8_t startlp, endlp; + startlp = (uint_least8_t) (info.loadAddr >> 8); + endlp = startlp; + endlp += (uint_least8_t) ((info.c64dataLen - 1) >> 8); + + if ( ((startp <= startlp) && (endp >= startlp)) || + ((startp <= endlp) && (endp >= endlp)) ) + { + info.formatString = txt_badReloc; + return false; + } + } + + // Check that the relocation information does not use the following + // memory areas: 0x0000-0x03FF, 0xA000-0xBFFF and 0xD000-0xFFFF + if ((startp < 0x04) + || ((0xa0 <= startp) && (startp <= 0xbf)) + || (startp >= 0xd0) + || ((0xa0 <= endp) && (endp <= 0xbf)) + || (endp >= 0xd0)) + { + info.formatString = txt_badReloc; + return false; + } + return true; +} + +bool SidTune::resolveAddrs (const uint_least8_t* c64data) +{ + if ( info.compatibility == SIDTUNE_COMPATIBILITY_R64 ) + { + bool initAddrCheck = true; + + // Check tune is loadable on a real C64 + if ( info.loadAddr < SIDTUNE_R64_MIN_LOAD_ADDR ) + { + info.formatString = txt_badAddr; + return false; + } + + if ( (info.initAddr == 0) && (info.loadAddr == SIDTUNE_BASIC_START) ) + { // Scan basic for a sys call + const uint_least8_t* pData = c64data; + uint_least16_t addr = 0; + uint_least16_t next = endian_little16(pData); + uint_least16_t init = 0; + + while (next) + { // skip addr & line number + const uint_least8_t *p = &pData[addr + 4]; + +SidTune_resolveAddrs_basic: + // Check for SYS + if (*p++ != 0x9e) + { // Check for ':' instruction seperator before + // jumping to next basic line + while (*p != '\0') + { + if (*p++ == ':') + { // Skip spaces + while (*p == ' ') + p++; + // Make sure havent hit end of line + if (*p != '\0') + goto SidTune_resolveAddrs_basic; + } + } + // Not a sys so jump to next intruction + addr = next; + // Get addr of next line of basic + next = endian_little16(&pData[addr]); + continue; + } + // Skip spaces + while (*p == ' ') + p++; + // Found a sys, extract all numbers + while ( (*p >= '0') && (*p <= '9') ) + { + init *= 10; + init += *p++ - '0'; + } + info.initAddr = init; + // Assume address is legal otherwise + // a real c64 would crash + initAddrCheck = false; + break; + } + } + + if ( checkRealC64Init() == false ) + { + info.formatString = txt_badAddr; + return false; + } + } + else if ( info.initAddr == 0 ) + info.initAddr = info.loadAddr; + return true; +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneCfg.h b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneCfg.h new file mode 100644 index 00000000..088c906e --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneCfg.h @@ -0,0 +1,35 @@ +/* SidTuneCfg.h (template) */ + +#ifndef SIDTUNECFG_H +#define SIDTUNECFG_H + +#include "../../config.h" + +/* Define to add PSID2NG support */ +#define SIDTUNE_PSID2NG + +/* Minimum load address for real c64 only tunes */ +#define SIDTUNE_R64_MIN_LOAD_ADDR 0x07e8 + +/* -------------------------------------------------------------------------- + * Don't touch these! + * -------------------------------------------------------------------------- + */ +#undef SIDTUNE_NO_STDIN_LOADER +#undef SIDTUNE_REJECT_UNKNOWN_FIELDS + + +/* Define the file/path separator(s) that your filesystem uses: + SID_FS_IS_COLON_AND_BACKSLASH, SID_FS_IS_COLON_AND_SLASH, + SID_FS_IS_BACKSLASH, SID_FS_IS_COLON, SID_FS_IS_SLASH */ +#if defined(HAVE_MSWINDOWS) || defined(HAVE_MSDOS) || defined(HAVE_OS2) + #define SID_FS_IS_COLON_AND_BACKSLASH_AND_SLASH +#elif defined(HAVE_MACOS) + #define SID_FS_IS_COLON +#elif defined(HAVE_AMIGAOS) + #define SID_FS_IS_COLON_AND_SLASH +#else + #define SID_FS_IS_SLASH +#endif + +#endif /* SIDTUNECFG_H */ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneTools.cpp b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneTools.cpp new file mode 100644 index 00000000..450795b9 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneTools.cpp @@ -0,0 +1,215 @@ +/* + * /home/ms/files/source/libsidtune/RCS/SidTuneTools.cpp,v + * + * Copyright (C) Michael Schwendt <mschwendt@yahoo.com> + * + * 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 "SidTuneTools.h" + +#ifdef HAVE_EXCEPTIONS +# include <new> +#endif +#include <ctype.h> +#include <string.h> + +// Own version of strdup, which uses new instead of malloc. +char* SidTuneTools::myStrDup(const char *source) +{ + char *dest; +#ifdef HAVE_EXCEPTIONS + if ( (dest = new(std::nothrow) char[strlen(source)+1]) != 0) +#else + if ( (dest = new char[strlen(source)+1]) != 0) +#endif + { + strcpy(dest,source); + } + return dest; +} + +// Return pointer to file name position in complete path. +char* SidTuneTools::fileNameWithoutPath(char* s) +{ + int last_slash_pos = -1; + for ( uint_least32_t pos = 0; pos < strlen(s); pos++ ) + { +#if defined(SID_FS_IS_COLON_AND_BACKSLASH_AND_SLASH) + if ( s[pos] == ':' || s[pos] == '\\' || + s[pos] == '/' ) +#elif defined(SID_FS_IS_COLON_AND_SLASH) + if ( s[pos] == ':' || s[pos] == '/' ) +#elif defined(SID_FS_IS_SLASH) + if ( s[pos] == '/' ) +#elif defined(SID_FS_IS_BACKSLASH) + if ( s[pos] == '\\' ) +#elif defined(SID_FS_IS_COLON) + if ( s[pos] == ':' ) +#else +#error Missing file/path separator definition. +#endif + { + last_slash_pos = pos; + } + } + return( &s[last_slash_pos +1] ); +} + +// Return pointer to file name position in complete path. +// Special version: file separator = forward slash. +char* SidTuneTools::slashedFileNameWithoutPath(char* s) +{ + int last_slash_pos = -1; + for ( uint_least32_t pos = 0; pos < strlen(s); pos++ ) + { + if ( s[pos] == '/' ) + { + last_slash_pos = pos; + } + } + return( &s[last_slash_pos +1] ); +} + +// Return pointer to file name extension in path. +// The backwards-version. +char* SidTuneTools::fileExtOfPath(char* s) +{ + uint_least32_t last_dot_pos = strlen(s); // assume no dot and append + for ( int pos = last_dot_pos; pos >= 0; --pos ) + { + if ( s[pos] == '.' ) + { + last_dot_pos = pos; + break; + } + } + return( &s[last_dot_pos] ); +} + +// Parse input string stream. Read and convert a hexa-decimal number up +// to a ``,'' or ``:'' or ``\0'' or end of stream. +uint_least32_t SidTuneTools::readHex( std::istringstream& hexin ) +{ + uint_least32_t hexLong = 0; + char c; + do + { + hexin >> c; + if ( !hexin ) + break; + if (( c != ',') && ( c != ':' ) && ( c != 0 )) + { + // machine independed to_upper + c &= 0xdf; + ( c < 0x3a ) ? ( c &= 0x0f ) : ( c -= ( 0x41 - 0x0a )); + hexLong <<= 4; + hexLong |= (uint_least32_t)c; + } + else + { + if ( c == 0 ) + hexin.putback(c); + break; + } + } while ( hexin ); + return hexLong; +} + +// Parse input string stream. Read and convert a decimal number up +// to a ``,'' or ``:'' or ``\0'' or end of stream. +uint_least32_t SidTuneTools::readDec( std::istringstream& decin ) +{ + uint_least32_t hexLong = 0; + char c; + do + { + decin >> c; + if ( !decin ) + break; + if (( c != ',') && ( c != ':' ) && ( c != 0 )) + { + c &= 0x0f; + hexLong *= 10; + hexLong += (uint_least32_t)c; + } + else + { + if ( c == 0 ) + decin.putback(c); + break; + } + } while ( decin ); + return hexLong; +} + +// Search terminated string for next newline sequence. +// Skip it and return pointer to start of next line. +const char* SidTuneTools::returnNextLine(const char* s) +{ + // Unix: LF = 0x0A + // Windows, DOS: CR,LF = 0x0D,0x0A + // Mac: CR = 0x0D + char c; + while ((c = *s) != 0) + { + s++; // skip read character + if (c == 0x0A) + { + break; // LF found + } + else if (c == 0x0D) + { + if (*s == 0x0A) + { + s++; // CR,LF found, skip LF + } + break; // CR or CR,LF found + } + } + if (*s == 0) // end of string ? + { + return 0; // no next line available + } + return s; // next line available +} + +// Skip any characters in an input string stream up to '='. +void SidTuneTools::skipToEqu( std::istringstream& parseStream ) +{ + char c; + do + { + parseStream >> c; + } + while ( c != '=' ); +} + +void SidTuneTools::copyStringValueToEOL(const char* pSourceStr, char* pDestStr, int DestMaxLen ) +{ + // Start at first character behind '='. + while ( *pSourceStr != '=' ) + { + pSourceStr++; + } + pSourceStr++; // Skip '='. + while (( DestMaxLen > 0 ) && ( *pSourceStr != 0 ) + && ( *pSourceStr != '\n' ) && ( *pSourceStr != '\r' )) + { + *pDestStr++ = *pSourceStr++; + DestMaxLen--; + } + *pDestStr++ = 0; +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneTools.h b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneTools.h new file mode 100644 index 00000000..5a06046b --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/sidtune/SidTuneTools.h @@ -0,0 +1,86 @@ +/* + * /home/ms/files/source/libsidtune/RCS/SidTuneTools.h,v + * + * Copyright (C) Michael Schwendt <mschwendt@yahoo.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TOOLS_H +#define TOOLS_H + +#include "SidTuneCfg.h" +#include "sidtypes.h" + +#include <string.h> + +#include <sstream> + +#define MYSTRICMP stricmp +#if defined(HAVE_STRCASECMP) + #undef MYSTRICMP + #define MYSTRICMP strcasecmp +#endif + +#define MYSTRNICMP strnicmp +#if defined(HAVE_STRNCASECMP) + #undef MYSTRNICMP + #define MYSTRNICMP strncasecmp +#endif + +class SidTuneTools +{ + public: + + // Wrapper for ``strnicmp'' without third argument. + static int myStrNcaseCmp(const char* s1, const char* s2) + { + return MYSTRNICMP(s1,s2,strlen(s2)); + } + + // Own version of strdup, which uses new instead of malloc. + static char* myStrDup(const char *source); + + // Return pointer to file name position in complete path. + static char* fileNameWithoutPath(char* s); + + // Return pointer to file name position in complete path. + // Special version: file separator = forward slash. + static char* slashedFileNameWithoutPath(char* s); + + // Return pointer to file name extension in path. + // Searching backwards until first dot is found. + static char* fileExtOfPath(char* s); + + // Parse input string stream. Read and convert a hexa-decimal number up + // to a ``,'' or ``:'' or ``\0'' or end of stream. + static uint_least32_t readHex(std::istringstream& parseStream); + + // Parse input string stream. Read and convert a decimal number up + // to a ``,'' or ``:'' or ``\0'' or end of stream. + static uint_least32_t readDec(std::istringstream& parseStream); + + // Search terminated string for next newline sequence. + // Skip it and return pointer to start of next line. + static const char* returnNextLine(const char* pBuffer); + + // Skip any characters in an input string stream up to '='. + static void skipToEqu(std::istringstream& parseStream); + + // Start at first character behind '=' and copy rest of string. + static void copyStringValueToEOL(const char* pSourceStr, char* pDestStr, int destMaxLen); +}; + +#endif /* TOOLS_H */ diff --git a/plugins/sid/sidplay-libs/libsidplay/src/xsid/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/xsid/Makefile.am new file mode 100644 index 00000000..4c7caf6a --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/xsid/Makefile.am @@ -0,0 +1,7 @@ + +noinst_LTLIBRARIES = libxsid.la + +libxsid_la_SOURCES = xsid.cpp xsid.h + +# Remove bad default includes +DEFAULT_INCLUDES= diff --git a/plugins/sid/sidplay-libs/libsidplay/src/xsid/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/xsid/Makefile.in new file mode 100644 index 00000000..aafad807 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/xsid/Makefile.in @@ -0,0 +1,424 @@ +# Makefile.in generated by automake 1.7.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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 = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SID_HAVE_BOOL = @SID_HAVE_BOOL@ +SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@ +SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@ +SID_SIZEOF_INT = @SID_SIZEOF_INT@ +SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@ +SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@ +SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builders = @builders@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +noinst_LTLIBRARIES = libxsid.la + +libxsid_la_SOURCES = xsid.cpp xsid.h + +# Remove bad default includes +DEFAULT_INCLUDES = +subdir = src/xsid +mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/unix/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libxsid_la_LDFLAGS = +libxsid_la_LIBADD = +am_libxsid_la_OBJECTS = xsid.lo +libxsid_la_OBJECTS = $(am_libxsid_la_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/unix/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/xsid.Plo +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libxsid_la_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libxsid_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/xsid/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libxsid.la: $(libxsid_la_OBJECTS) $(libxsid_la_DEPENDENCIES) + $(CXXLINK) $(libxsid_la_LDFLAGS) $(libxsid_la_OBJECTS) $(libxsid_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsid.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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 $(LTLIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_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-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +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: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man 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 uninstall-info-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: diff --git a/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.cpp b/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.cpp new file mode 100644 index 00000000..29b5c909 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.cpp @@ -0,0 +1,598 @@ +/*************************************************************************** + xsid.cpp - Support for Playsids Extended + Registers + ------------------- + begin : Tue Jun 20 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: xsid.cpp,v $ + * Revision 1.20 2002/07/17 21:19:54 s_a_white + * Minor non sid sample mode fixes. + * + * Revision 1.19 2002/02/21 20:26:13 s_a_white + * Nolonger default to Galway Mode when Noise samples init incorrectly. Fixes + * VARIOUS/S-Z/Zyron/Bouncy_Balls.sid (HVSC). + * + * Revision 1.18 2002/02/17 16:34:39 s_a_white + * New reset interface + * + * Revision 1.17 2002/01/28 19:31:42 s_a_white + * PSID sample improvements. + * + * Revision 1.16 2001/10/02 18:03:03 s_a_white + * Support updated sidbuilder class interface. + * + * Revision 1.15 2001/09/17 18:36:41 s_a_white + * Changed object construction to prevent multiple resets. + * + * Revision 1.14 2001/07/14 12:59:53 s_a_white + * XSID effeciency increased. Now uses new component classes and event + * generation. + * + * Revision 1.13 2001/03/25 19:51:23 s_a_white + * Performance update. + * + * Revision 1.12 2001/03/19 23:40:19 s_a_white + * Removed repeat definition of state for debug mode. + * + * Revision 1.11 2001/03/09 22:27:13 s_a_white + * Speed optimisation update. + * + * Revision 1.10 2001/03/01 23:45:58 s_a_white + * Combined both through sid and non-through sid modes. Can be selected + * at runtime now. + * + * Revision 1.9 2001/02/21 21:46:34 s_a_white + * 0x1d = 0 now fixed. Limit checking on sid volume. This helps us determine + * even better what the sample offset should be (fixes Skate and Die). + * + * Revision 1.8 2001/02/07 21:02:30 s_a_white + * Supported for delaying samples for frame simulation. New alogarithm to + * better guess original tunes volume when playing samples. + * + * Revision 1.7 2000/12/12 22:51:01 s_a_white + * Bug Fix #122033. + * + ***************************************************************************/ + +#include <string.h> +#include <stdio.h> +#include "sidendian.h" +#include "xsid.h" + + +// Convert from 4 bit resolution to 8 bits +/* Rev 2.0.5 (saw) - Removed for a more non-linear equivalent + which better models the SIDS master volume register +const int8_t XSID::sampleConvertTable[16] = +{ + '\x80', '\x91', '\xa2', '\xb3', '\xc4', '\xd5', '\xe6', '\xf7', + '\x08', '\x19', '\x2a', '\x3b', '\x4c', '\x5d', '\x6e', '\x7f' +}; +*/ +const int8_t XSID::sampleConvertTable[16] = +{ + '\x80', '\x94', '\xa9', '\xbc', '\xce', '\xe1', '\xf2', '\x03', + '\x1b', '\x2a', '\x3b', '\x49', '\x58', '\x66', '\x73', '\x7f' +}; + +const char *XSID::credit = +{ + "xSID (Extended SID) Engine:\0" + "\tCopyright (C) 2000 Simon White <sidplay2@email.com>\0" +}; + + +channel::channel (const char * const name, EventContext *context, XSID *xsid) +:m_name(name), + m_context(*context), + m_xsid(*xsid), + sampleEvent(this), + galwayEvent(this) +{ + memset (reg, 0, sizeof (reg)); + active = true; + reset (); +} + +void channel::reset () +{ + galVolume = 0; // This is left to free run until reset + mode = FM_NONE; + free (); +} + +void channel::free () +{ + active = false; + cycleCount = 0; + sampleLimit = 0; + // Set XSID to stopped state + reg[convertAddr (0x1d)] = 0; + silence (); +} + +inline int8_t channel::output () +{ + outputs++; + return sample; +} + +void channel::checkForInit () +{ // Check to see mode of operation + // See xsid documentation + switch (reg[convertAddr (0x1d)]) + { + case 0xFF: + case 0xFE: + case 0xFC: + sampleInit (); + break; + case 0xFD: + if (!active) + return; + free (); // Stop + // Calculate the sample offset + m_xsid.sampleOffsetCalc (); + break; + case 0x00: + break; + default: + galwayInit (); + } +} + +void channel::sampleInit () +{ + uint8_t *r; + if (active && (mode == FM_GALWAY)) + return; + +#ifdef XSID_DEBUG + printf ("XSID [%s]: Sample Init\n", m_name); + if (active && (mode == FM_HUELS)) + printf ("XSID [%s]: Stopping Playing Sample\n", m_name); +#endif + + // Check all important parameters are legal + r = ®[convertAddr (0x1d)]; + volShift = (uint_least8_t) (0 - (int8_t) r[0]) >> 1; + r[0] = 0; + // Use endian_16 as can't g + r = ®[convertAddr (0x1e)]; + address = endian_16 (r[1], r[0]); + r = ®[convertAddr (0x3d)]; + samEndAddr = endian_16 (r[1], r[0]); + if (samEndAddr <= address) return; + samScale = reg[convertAddr (0x5f)]; + r = ®[convertAddr (0x5d)]; + samPeriod = endian_16 (r[1], r[0]) >> samScale; + if (!samPeriod) + { // Stop this channel + reg[convertAddr (0x1d)] = 0xfd; + checkForInit (); + return; + } + + // Load the other parameters + samNibble = 0; + samRepeat = reg[convertAddr (0x3f)]; + samOrder = reg[convertAddr (0x7d)]; + r = ®[convertAddr (0x7e)]; + samRepeatAddr = endian_16 (r[1], r[0]); + cycleCount = samPeriod; + + // Support Galway Samples, but that + // mode it setup only when as Galway + // Noise sequence begins + if (mode == FM_NONE) + mode = FM_HUELS; + + active = true; + cycles = 0; + outputs = 0; + + sampleLimit = 8 >> volShift; + sample = sampleCalculate (); + + // Calculate the sample offset + m_xsid.sampleOffsetCalc (); + +#ifdef XSID_DEBUG +# if XSID_DEBUG > 1 + printf ("XSID [%s]: Sample Start Address: 0x%04x\n", m_name, address); + printf ("XSID [%s]: Sample End Address: 0x%04x\n", m_name, samEndAddr); + printf ("XSID [%s]: Sample Repeat Address: 0x%04x\n", m_name, samRepeatAddr); + printf ("XSID [%s]: Sample Period: %u\n", m_name, samPeriod); + printf ("XSID [%s]: Sample Repeat: %u\n", m_name, samRepeat); + printf ("XSID [%s]: Sample Order: %u\n", m_name, samOrder); +# endif + printf ("XSID [%s]: Sample Start\n", m_name); +#endif // XSID_DEBUG + + // Schedule a sample update + m_context.schedule (&m_xsid, 0); + m_context.schedule (&sampleEvent, cycleCount); +} + +void channel::sampleClock () +{ + cycleCount = samPeriod; + if (address >= samEndAddr) + { + if (samRepeat != 0xFF) + { + if (samRepeat) + samRepeat--; + else + samRepeatAddr = address; + } + + address = samRepeatAddr; + if (address >= samEndAddr) + { // The sequence has completed + uint8_t &status = reg[convertAddr (0x1d)]; + if (!status) + status = 0xfd; + if (status != 0xfd) + active = false; +#ifdef XSID_DEBUG + printf ("XSID [%s]: Sample Stop (%lu Cycles, %lu Outputs)\n", + m_name, cycles, outputs); + if (status != 0xfd) + printf ("XSID [%s]: Starting Delayed Sequence\n", m_name); +#endif + checkForInit (); + return; + } + } + + // We have reached the required sample + // So now we need to extract the right nibble + sample = sampleCalculate (); + cycles += cycleCount; + // Schedule a sample update + m_context.schedule (&sampleEvent, cycleCount); + m_context.schedule (&m_xsid, 0); +} + +int8_t channel::sampleCalculate () +{ + uint_least8_t tempSample = m_xsid.readMemByte (address); + if (samOrder == SO_LOWHIGH) + { + if (samScale == 0) + { + if (samNibble != 0) + tempSample >>= 4; + } + // AND 15 further below. + } + else // if (samOrder == SO_HIGHLOW) + { + if (samScale == 0) + { + if (samNibble == 0) + tempSample >>= 4; + } + else // if (samScale != 0) + tempSample >>= 4; + // AND 15 further below. + } + + // Move to next address + address += samNibble; + samNibble ^= 1; + return (int8_t) ((tempSample & 0x0f) - 0x08) >> volShift; +} + +void channel::galwayInit() +{ + uint8_t *r; + if (active) + return; + +#ifdef XSID_DEBUG + printf ("XSID [%s]: Galway Init\n", m_name); +#endif + + // Check all important parameters are legal + r = ®[convertAddr (0x1d)]; + galTones = r[0]; + r[0] = 0; + galInitLength = reg[convertAddr (0x3d)]; + if (!galInitLength) return; + galLoopWait = reg[convertAddr (0x3f)]; + if (!galLoopWait) return; + galNullWait = reg[convertAddr (0x5d)]; + if (!galNullWait) return; + + // Load the other parameters + r = ®[convertAddr(0x1e)]; + address = endian_16 (r[1], r[0]); + volShift = reg[convertAddr (0x3e)] & 0x0f; + mode = FM_GALWAY; + active = true; + cycles = 0; + outputs = 0; + + sampleLimit = 8; + sample = (int8_t) galVolume - 8; + galwayTonePeriod (); + + // Calculate the sample offset + m_xsid.sampleOffsetCalc (); + +#ifdef XSID_DEBUG + printf ("XSID [%s]: Galway Start\n", m_name); +#endif + + // Schedule a sample update + m_context.schedule (&m_xsid, 0); + m_context.schedule (&galwayEvent, cycleCount); +} + +void channel::galwayClock () +{ + if (--galLength) + cycleCount = samPeriod; + else if (galTones == 0xff) + { // The sequence has completed + uint8_t &status = reg[convertAddr (0x1d)]; + if (!status) + status = 0xfd; + if (status != 0xfd) + active = false; +#ifdef XSID_DEBUG + printf ("XSID [%s]: Galway Stop (%lu Cycles, %lu Outputs)\n", + m_name, cycles, outputs); + if (status != 0xfd) + printf ("XSID [%s]: Starting Delayed Sequence\n", m_name); +#endif + checkForInit (); + return; + } + else + galwayTonePeriod (); + + // See Galway Example... + galVolume += volShift; + galVolume &= 0x0f; + sample = (int8_t) galVolume - 8; + cycles += cycleCount; + m_context.schedule (&galwayEvent, cycleCount); + m_context.schedule (&m_xsid, 0); +} + +void channel::galwayTonePeriod () +{ // Calculate the number of cycles over which sample should last + galLength = galInitLength; + samPeriod = m_xsid.readMemByte (address + galTones); + samPeriod *= galLoopWait; + samPeriod += galNullWait; + cycleCount = samPeriod; +#if XSID_DEBUG > 2 + printf ("XSID [%s]: Galway Settings\n", m_name); + printf ("XSID [%s]: Length %u, LoopWait %u, NullWait %u\n", + m_name, galLength, galLoopWait, galNullWait); + printf ("XSID [%s]: Tones %u, Data %u\n", + m_name, galTones, m_xsid.readMemByte (address + galTones)); +#endif + galTones--; +} + +void channel::silence () +{ + sample = 0; + m_context.cancel (&sampleEvent); + m_context.cancel (&galwayEvent); + m_context.schedule (&m_xsid, 0); +} + + +XSID::XSID (EventContext *context) +:sidemu(NULL), + Event("xSID"), + ch4("CH4", context, this), + ch5("CH5", context, this), + muted(false), + suppressed(false), + wasRunning(false) +{ + sidSamples (true); +} + +void XSID::reset (uint8_t) +{ + ch4.reset (); + ch5.reset (); + suppressed = false; + wasRunning = false; +} + +void XSID::event (void) +{ + if (ch4 || ch5) + { + setSidData0x18 (); + wasRunning = true; + } + else if (wasRunning) + { + recallSidData0x18 (); + wasRunning = false; + } +} + +// Use Suppress to delay the samples and start them later +// Effectivly allows running samples in a frame based mode. +void XSID::suppress (bool enable) +{ + // @FIXME@: Mute Temporary Hack + suppressed = enable; + if (!suppressed) + { // Get the channels running +#if XSID_DEBUG + printf ("XSID: Un-suppressing\n"); +#endif + ch4.checkForInit (); + ch5.checkForInit (); + } +#if XSID_DEBUG + else + printf ("XSID: Suppressing\n"); +#endif +} + +// By muting samples they will start and play the at the +// appropriate time but no sound is produced. Un-muting +// will cause sound output from the current play position. +void XSID::mute (bool enable) +{ + if (!muted && enable && wasRunning) + recallSidData0x18 (); + muted = enable; +} + +void XSID::write (uint_least16_t addr, uint8_t data) +{ + channel *ch; + uint8_t tempAddr; + + // Make sure address is legal + if ((addr & 0xfe8c) ^ 0x000c) + return; + + ch = &ch4; + if (addr & 0x0100) + ch = &ch5; + + tempAddr = (uint8_t) addr; + ch->write (tempAddr, data); +#if XSID_DEBUG > 1 + printf ("XSID: Addr 0x%02x, Data 0x%02x\n", tempAddr, data); +#endif + + if (tempAddr == 0x1d) + { + if (suppressed) + { +#if XSID_DEBUG + printf ("XSID: Initialise Suppressed\n"); +#endif + return; + } + ch->checkForInit (); + } +} + +int8_t XSID::sampleOutput (void) +{ + int8_t sample; + sample = ch4.output (); + sample += ch5.output (); + // Automatically compensated for by C64 code + //return (sample >> 1); + return sample; +} + +void XSID::setSidData0x18 (void) +{ + if (!_sidSamples || muted) + return; + + uint8_t data = (sidData0x18 & 0xf0); + data |= ((sampleOffset + sampleOutput ()) & 0x0f); + +#ifdef XSID_DEBUG + if ((sampleOffset + sampleOutput ()) > 0x0f) + { + printf ("XSID: Sample Wrapped [offset %u, sample %d]\n", + sampleOffset, sampleOutput ()); + } +# if XSID_DEBUG > 1 + printf ("XSID: Writing Sample to SID Volume [0x%02x]\n", data); +# endif +#endif // XSID_DEBUG + + writeMemByte (data); +} + +void XSID::recallSidData0x18 (void) +{ // Rev 2.0.5 (saw) - Changed to recall volume differently depending on mode + // Normally after samples volume should be restored to half volume, + // however, Galway Tunes sound horrible and seem to require setting back to + // the original volume. Setting back to the original volume for normal + // samples can have nasty pulsing effects + if (ch4.isGalway ()) + { + if (_sidSamples && !muted) + writeMemByte (sidData0x18); + } + else + setSidData0x18 (); +} + +void XSID::sampleOffsetCalc (void) +{ + // Try to determine a sensible offset between voice + // and sample volumes. + uint_least8_t lower = ch4.limit () + ch5.limit (); + uint_least8_t upper; + + // Both channels seem to be off. Keep current offset! + if (!lower) + return; + + sampleOffset = sidData0x18 & 0x0f; + + // Is possible to compensate for both channels + // set to 4 bits here, but should never happen. + if (lower > 8) + lower >>= 1; + upper = 0x0f - lower + 1; + + // Check against limits + if (sampleOffset < lower) + sampleOffset = lower; + else if (sampleOffset > upper) + sampleOffset = upper; + +#ifdef XSID_DEBUG + printf ("XSID: Sample Offset %d based on channel(s) ", sampleOffset); + if (ch4) + printf ("4 "); + if (ch5) + printf ("5"); + printf ("\n"); +#endif // XSID_DEBUG +} + +bool XSID::storeSidData0x18 (uint8_t data) +{ + sidData0x18 = data; + if (ch4 || ch5) + { // Force volume to be changed at next clock + sampleOffsetCalc (); + if (_sidSamples) + { +#if XSID_DEBUG + printf ("XSID: SID Volume Changed Externally (Corrected).\n"); +#endif + return true; + } + } + writeMemByte (sidData0x18); + return false; +} diff --git a/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h b/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h new file mode 100644 index 00000000..98171d73 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h @@ -0,0 +1,288 @@ +/*************************************************************************** + xsid.h - Support for Playsids Extended + Registers + ------------------- + begin : Tue Jun 20 2000 + copyright : (C) 2000 by Simon White + email : s_a_white@email.com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + * $Log: xsid.h,v $ + * Revision 1.21 2002/09/23 19:42:52 s_a_white + * Fixed intel compiler warnings. + * + * Revision 1.20 2002/07/17 19:18:17 s_a_white + * Changed bad #if to #ifdef + * + * Revision 1.19 2002/02/21 20:26:13 s_a_white + * Nolonger default to Galway Mode when Noise samples init incorrectly. Fixes + * VARIOUS/S-Z/Zyron/Bouncy_Balls.sid (HVSC). + * + * Revision 1.18 2002/02/17 16:34:39 s_a_white + * New reset interface + * + * Revision 1.17 2001/11/16 19:22:04 s_a_white + * Removed compiler warning for unused parameter. + * + * Revision 1.16 2001/10/18 22:36:16 s_a_white + * GCC3 fixes. + * + * Revision 1.15 2001/07/14 16:48:35 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.14 2001/07/14 12:59:39 s_a_white + * XSID effeciency increased. Now uses new component classes and event + * generation. + * + * Revision 1.13 2001/04/20 22:21:06 s_a_white + * inlined updateSidData0x18. + * + * Revision 1.12 2001/03/25 19:51:23 s_a_white + * Performance update. + * + * Revision 1.11 2001/03/19 23:40:46 s_a_white + * Better support for global debug. + * + * Revision 1.10 2001/03/09 22:27:13 s_a_white + * Speed optimisation update. + * + * Revision 1.9 2001/03/01 23:45:58 s_a_white + * Combined both through sid and non-through sid modes. Can be selected + * at runtime now. + * + * Revision 1.8 2001/02/21 21:46:34 s_a_white + * 0x1d = 0 now fixed. Limit checking on sid volume. This helps us determine + * even better what the sample offset should be (fixes Skate and Die). + * + * Revision 1.7 2001/02/07 21:02:30 s_a_white + * Supported for delaying samples for frame simulation. New alogarithm to + * better guess original tunes volume when playing samples. + * + * Revision 1.6 2000/12/12 22:51:01 s_a_white + * Bug Fix #122033. + * + ***************************************************************************/ + +/* +Effectively there is only 1 channel, which can either perform Galway Noise +or Sampling. However, to achieve all the effects on a C64, 2 sampling +channels are required. No divide by 2 is required and is compensated for +automatically in the C64 machine code. + +Confirmed by Warren Pilkington using the tune Turbo Outrun: +A new sample must interrupt an existing sample running on the same channel. + +Confirmed by Michael Schwendt and Antonia Vera using the tune Game Over: +A Galway Sample or Noise sequence cannot interrupt any other. However +the last of these new requested sequences will be played after the current +sequence ends. + +Lastly playing samples through the SIDs volume is not as clean as playing +them on their own channel. Playing through the SID will effect the volume +of the other channels and this will be most noticable at low frequencies. +These effects are however present in the original SID music. + +Some SIDs put values directly into the volume register. Others play samples +with respect to the current volume. We can't for definate know which the author +has chosen originally. We must just make a guess based on what the volume +is initially at the start of a sample sequence and from the details xSID has been +programmed with. +*/ + +#ifndef _xsid_h_ +#define _xsid_h_ + +#include "config.h" +#include "sidbuilder.h" +#include "event.h" + +// XSID configuration settings +//#define XSID_DEBUG 1 + +// Support global debug option +#ifdef DEBUG +# ifndef XSID_DEBUG +# define XSID_DEBUG DEBUG +# endif +#endif + +#ifdef XSID_DEBUG +# include <stdio.h> +#endif + +class XSID; +class channel +{ +private: + // General + const char * const m_name; + EventContext &m_context; + XSID &m_xsid; + friend class XSID; + + class SampleEvent: public Event + { + private: + channel &m_ch; + void event (void) { m_ch.sampleClock (); } + + public: + SampleEvent (channel *ch) + :Event("xSID Sample"), + m_ch(*ch) {} + } sampleEvent; + friend class SampleEvent; + + class GalwayEvent: public Event + { + private: + channel &m_ch; + void event (void) { m_ch.galwayClock (); } + + public: + GalwayEvent (channel *ch) + :Event("xSID Galway"), + m_ch(*ch) {} + } galwayEvent; + friend class GalwayEvent; + + uint8_t reg[0x10]; + enum {FM_NONE = 0, FM_HUELS, FM_GALWAY} mode; + bool active; + uint_least16_t address; + uint_least16_t cycleCount; // Counts to zero and triggers! + uint_least8_t volShift; + uint_least8_t sampleLimit; + int8_t sample; + + // Sample Section + uint_least8_t samRepeat; + uint_least8_t samScale; + enum {SO_LOWHIGH = 0, SO_HIGHLOW = 1}; + uint_least8_t samOrder; + uint_least8_t samNibble; + uint_least16_t samEndAddr; + uint_least16_t samRepeatAddr; + uint_least16_t samPeriod; + + // Galway Section + uint_least8_t galTones; + uint_least8_t galInitLength; + uint_least8_t galLength; + uint_least8_t galVolume; + uint_least8_t galLoopWait; + uint_least8_t galNullWait; + + // For Debugging + event_clock_t cycles; + event_clock_t outputs; + +private: + channel (const char * const name, EventContext *context, XSID *xsid); + void free (void); + void silence (void); + void sampleInit (void); + void sampleClock (void); + void galwayInit (void); + void galwayClock (void); + + // Compress address to not leave so many spaces + uint_least8_t convertAddr(uint_least8_t addr) + { return (((addr) & 0x3) | ((addr) >> 3) & 0x0c); } + + void reset (void); + uint8_t read (uint_least8_t addr) + { return reg[convertAddr (addr)]; } + void write (uint_least8_t addr, uint8_t data) + { reg[convertAddr (addr)] = data; } + int8_t output (void); + bool isGalway (void) + { return mode == FM_GALWAY; } + + uint_least8_t limit (void) + { return sampleLimit; } + + inline void checkForInit (void); + inline int8_t sampleCalculate (void); + inline void galwayTonePeriod (void); + + // Used to indicate if channel is running + operator bool() const { return (active); } +}; + + +class XSID: public sidemu, private Event +{ + friend class channel; + +private: + channel ch4; + channel ch5; + bool muted; + bool suppressed; + static const char *credit; + + uint8_t sidData0x18; + bool _sidSamples; + int8_t sampleOffset; + static const int8_t sampleConvertTable[16]; + bool wasRunning; + +private: + void event (void); + void checkForInit (channel *ch); + inline void setSidData0x18 (void); + inline void recallSidData0x18 (void); + int8_t sampleOutput (void); + void sampleOffsetCalc (void); + virtual uint8_t readMemByte (uint_least16_t addr) = 0; + virtual void writeMemByte (uint8_t data) = 0; + +public: + XSID (EventContext *context); + + // Standard calls + void reset () { sidemu::reset (); } + void reset (uint8_t); + uint8_t read (uint_least8_t) { return 0; } + void write (uint_least8_t, uint8_t) { ; } + const char *credits (void) {return credit;} + + // Specialist calls + uint8_t read (uint_least16_t) { return 0; } + void write (uint_least16_t addr, uint8_t data); + int_least32_t output (uint_least8_t bits = 16); + void mute (bool enable); + bool isMuted (void) { return muted; } + void suppress (bool enable); + + void sidSamples (bool enable) + { _sidSamples = enable; } + // Return whether we care it was changed. + bool storeSidData0x18 (uint8_t data); +}; + + +/*************************************************************************** + * Inline functions + **************************************************************************/ + +inline int_least32_t XSID::output (uint_least8_t bits) +{ + int_least32_t sample; + if (_sidSamples || muted) + return 0; + sample = sampleConvertTable[sampleOutput () + 8]; + return sample << (bits - 8); +} + +#endif // _xsid_h_ |