# HG changeset patch # User Robert McIntyre # Date 1330916810 21600 # Node ID 2efb971df51595f7e70eaa814d7ffe84ab360870 # Parent b970226568d2b1b9d00cd68282563a521d93930e bringing in SDL package diff -r b970226568d2 -r 2efb971df515 configure.ac --- a/configure.ac Sun Mar 04 20:32:31 2012 -0600 +++ b/configure.ac Sun Mar 04 21:06:50 2012 -0600 @@ -27,7 +27,8 @@ # Checks for header files. -AC_CHECK_HEADERS([arpa/inet.h limits.h locale.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/socket.h unistd.h]) +AC_FUNC_ALLOCA +AC_CHECK_HEADERS([arpa/inet.h limits.h locale.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/socket.h unistd.h libintl.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL @@ -52,9 +53,6 @@ AC_FUNC_STRCOLL AC_CHECK_FUNCS([floor ftruncate gethostbyname gethostname inet_ntoa localeconv memchr memset modf pow setlocale socket sqrt strcasecmp strchr strcspn strdup strerror strpbrk strrchr strstr strtoul]) - - - AC_CONFIG_FILES([Makefile src/Makefile src/lua/Makefile @@ -62,7 +60,8 @@ src/gba/Makefile src/common/Makefile src/SFMT/Makefile - src/filters/Makefile]) + src/filters/Makefile + src/sdl/Makefile]) diff -r b970226568d2 -r 2efb971df515 src/AutoBuild.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/AutoBuild.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,30 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 __AUTOBUILD_H__ +#define __AUTOBUILD_H__ +#include "version.h" +//change the FALSE to TRUE for autoincrement of build number +#define INCREMENT_VERSION FALSE +#define FILEVER 1,8,0,600 +#define PRODUCTVER 1,8,0,600 +#define STRFILEVER "1, 8, 0, 600\0" +#define STRPRODUCTVER "1, 8, 0, 600\0" +#endif //__AUTOBUILD_H__ + diff -r b970226568d2 -r 2efb971df515 src/Makefile.am --- a/src/Makefile.am Sun Mar 04 20:32:31 2012 -0600 +++ b/src/Makefile.am Sun Mar 04 21:06:50 2012 -0600 @@ -1,3 +1,3 @@ -SUBDIRS = SFMT lua gb gba common filters +SUBDIRS = SFMT lua gb gba common filters sdl -noinst_HEADERS = Port.h NLS.h +noinst_HEADERS = Port.h NLS.h AutoBuild.h diff -r b970226568d2 -r 2efb971df515 src/sdl/Array.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/Array.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2008 by Sindre Aam�s * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef ARRAY_H +#define ARRAY_H + +#include + +template +class Array { + T *a; + std::size_t sz; + + Array(const Array &ar); + +public: + Array(const std::size_t size = 0) : a(size ? new T[size] : 0), sz(size) {} + ~Array() { delete []a; } + void reset(const std::size_t size) { delete []a; a = size ? new T[size] : 0; sz = size; } + std::size_t size() const { return sz; } + operator T*() { return a; } + operator const T*() const { return a; } +}; + +#endif diff -r b970226568d2 -r 2efb971df515 src/sdl/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/Makefile Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,552 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# src/sdl/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 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. + + + + +pkgdatadir = $(datadir)/VisualBoyAdvance +pkglibdir = $(libdir)/VisualBoyAdvance +pkgincludedir = $(includedir)/VisualBoyAdvance +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +bin_PROGRAMS = VisualBoyAdvance$(EXEEXT) +noinst_PROGRAMS = TestEmu$(EXEEXT) +subdir = src/sdl +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +OBJDIR = $(top_srcdir)/src/obj +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am_TestEmu_OBJECTS = TestEmu.$(OBJEXT) debugger.$(OBJEXT) \ + expr-lex.$(OBJEXT) expr.$(OBJEXT) exprNode.$(OBJEXT) +TestEmu_OBJECTS = $(am_TestEmu_OBJECTS) +am_VisualBoyAdvance_OBJECTS = SDL.$(OBJEXT) debugger.$(OBJEXT) \ + expr-lex.$(OBJEXT) expr.$(OBJEXT) exprNode.$(OBJEXT) \ + getopt.$(OBJEXT) getopt1.$(OBJEXT) SoundSDL.$(OBJEXT) +VisualBoyAdvance_OBJECTS = $(patsubst %,$(OBJDIR)/%,$(am_VisualBoyAdvance_OBJECTS)) +DEFAULT_INCLUDES = -I. +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(TestEmu_SOURCES) $(VisualBoyAdvance_SOURCES) +DIST_SOURCES = $(TestEmu_SOURCES) $(VisualBoyAdvance_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /home/r/proj/vba/trunk/missing --run aclocal-1.10 +AMTAR = ${SHELL} /home/r/proj/vba/trunk/missing --run tar +AUTOCONF = ${SHELL} /home/r/proj/vba/trunk/missing --run autoconf +AUTOHEADER = ${SHELL} /home/r/proj/vba/trunk/missing --run autoheader +AUTOMAKE = ${SHELL} /home/r/proj/vba/trunk/missing --run automake-1.10 +AWK = gawk +CC = gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O2 +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -g -O2 -DC_CORE -DPROFILING -DDEV_VERSION +CYGPATH_W = echo +DEFS = -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"VisualBoyAdvance\" -DVERSION=\"1.7.2\" -DYYTEXT_POINTER=1 -DHAVE_LIBZ=1 -DHAVE_LIBPNG=1 -DHAVE_LIBPTHREAD=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_MALLOC_H=1 -DHAVE_STRINGS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_NETINET_IN_H=1 +DEPDIR = .deps +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +GETTEXT_PACKAGE = +GMSGFMT = +GREP = /bin/grep +GTKMM_CFLAGS = +GTKMM_CPPFLAGS = +GTKMM_LIBS = +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +INTLLIBS = +LDFLAGS = +LEX = flex +LEXLIB = -lfl +LEX_OUTPUT_ROOT = lex.yy +LIBICONV = +LIBINTL = +LIBOBJS = +LIBS = -lpthread -lpng -lz +LTLIBICONV = +LTLIBINTL = +LTLIBOBJS = +MAKEINFO = ${SHELL} /home/r/proj/vba/trunk/missing --run makeinfo +MKDIR_P = /bin/mkdir -p +MKINSTALLDIRS = +MSGFMT = +MSGMERGE = +NASM = /usr/bin/nasm +OBJEXT = o +PACKAGE = VisualBoyAdvance +PACKAGE_BUGREPORT = +PACKAGE_NAME = +PACKAGE_STRING = +PACKAGE_TARNAME = +PACKAGE_VERSION = +PATH_SEPARATOR = : +PKG_CONFIG = +POSUB = +RANLIB = ranlib +SDL_CFLAGS = -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT +SDL_CONFIG = /usr/bin/sdl-config +SDL_LIBS = -L/usr/lib -Wl,-rpath,/usr/lib -lSDL -lpthread +SET_MAKE = +SHELL = /bin/sh +STRIP = +USE_NLS = +VBA_EXTRA = +VBA_LIBS = ../gba/libgba.a ../gb/libgb.a ../common/libgbcom.a ../filters/libfilter.a ../lua/libgblua.a ../prof/libprof.a +VBA_SRC_EXTRA = lua prof sdl +VERSION = 1.7.2 +XGETTEXT = +XMKMF = +YACC = bison -y +YFLAGS = +abs_builddir = /home/r/proj/vba/trunk/src/sdl +abs_srcdir = /home/r/proj/vba/trunk/src/sdl +abs_top_builddir = /home/r/proj/vba/trunk +abs_top_srcdir = /home/r/proj/vba/trunk +ac_ct_CC = gcc +ac_ct_CXX = g++ +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = $(SHELL) /home/r/proj/vba/trunk/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = x86_64-unknown-linux-gnu +target_alias = +target_cpu = x86_64 +target_os = linux-gnu +target_vendor = unknown +top_builddir = ../.. +top_srcdir = ../.. +VisualBoyAdvance_SOURCES = \ + SDL.cpp \ + debugger.cpp \ + debugger.h \ + expr-lex.cpp \ + expr.cpp \ + expr.cpp.h \ + exprNode.cpp \ + exprNode.h \ + getopt.c \ + getopt.h \ + getopt1.c \ + ../AutoBuild.h \ + ../NLS.h \ + ../Port.h + +VisualBoyAdvance_LDADD = ../gba/libgba.a ../gb/libgb.a ../common/libgbcom.a ../filters/libfilter.a ../lua/libgblua.a ../prof/libprof.a -L/usr/lib -Wl,-rpath,/usr/lib -lSDL -lpthread +VisualBoyAdvance_DEPENDENCIES = ../gba/libgba.a ../gb/libgb.a ../common/libgbcom.a ../filters/libfilter.a ../lua/libgblua.a ../prof/libprof.a +TestEmu_SOURCES = \ + TestEmu.cpp \ + debugger.cpp \ + debugger.h \ + expr-lex.cpp \ + expr.cpp \ + expr.cpp.h \ + exprNode.cpp \ + exprNode.h \ + ../AutoBuild.h \ + ../NLS.h \ + ../Port.h + +TestEmu_LDADD = ../gba/libgba.a ../gb/libgb.a ../common/libgbcom.a ../filters/libfilter.a ../lua/libgblua.a ../prof/libprof.a -L/usr/lib -Wl,-rpath,/usr/lib -lSDL -lpthread +TestEmu_DEPENDENCIES = ../gba/libgba.a ../gb/libgb.a ../common/libgbcom.a ../filters/libfilter.a ../lua/libgblua.a ../prof/libprof.a +AM_CPPFLAGS = \ + -I$(top_srcdir)/src \ + -DSDL \ + -DSYSCONFDIR=\"$(sysconfdir)\" + +AM_CXXFLAGS = -fno-exceptions -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/sdl/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/sdl/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +TestEmu$(EXEEXT): $(TestEmu_OBJECTS) $(TestEmu_DEPENDENCIES) + @rm -f TestEmu$(EXEEXT) + $(CXXLINK) $(TestEmu_OBJECTS) $(TestEmu_LDADD) $(LIBS) + +OBJECTS_ = \ +2xSaImmx.o elf.o GBASound.o gbSound.o Mode2.o RTC.o \ +2xSaI.o gbCheats.o getopt1.o Mode3.o scanline.o expr.o \ +admame.o gbDis.o getopt.o Mode4.o SDL.o expr-lex.o \ +agbprint.o gbGfx.o hq2x.o Mode5.o simple2x.o exprNode.o \ +armdis.o Flash.o gbGlobals.o interframe.o motionblur.o Sram.o \ +bilinear.o GBACheats.o gbMemory.o lua-engine.o movie.o \ +bios.o GBAGfx.o GB.o memgzio.o pixel.o Text.o \ +GBAGlobals.o gbPrinter.o Mode0.o prof.o unzip.o debugger.o\ +EEprom.o GBA.o gbSGB.o Mode1.o remote.o Util.o \ +SoundSDL.o + +OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJECTS_)) + +$(top_srcdir)/src/VisualBoyAdvance$(EXEEXT): $(OBJECTS) $(top_srcdir)/src/lua/libgblua.a + @rm -f VisualBoyAdvance$(EXEEXT) + $(CXXLINK) $(OBJECTS) $(top_srcdir)/src/lua/libgblua.a -L/usr/lib -lSDL -lpthread -lpng -lz + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/SDL.Po +include ./$(DEPDIR)/TestEmu.Po +include ./$(DEPDIR)/debugger.Po +include ./$(DEPDIR)/expr-lex.Po +include ./$(DEPDIR)/expr.Po +include ./$(DEPDIR)/exprNode.Po +include ./$(DEPDIR)/getopt.Po +include ./$(DEPDIR)/getopt1.Po + +$(OBJDIR)/%.o: %.c + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c `$(CYGPATH_W) '$<'` + +$(OBJDIR)/%.o: %.cpp + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +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; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$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 + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(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 $(VisualBoyAdvance_OBJECTS) $(top_srcdir)/src/VisualBoyAdvance$(EXEEXT) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +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-binPROGRAMS clean-generic clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-noinstPROGRAMS ctags distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + +# 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 -r b970226568d2 -r 2efb971df515 src/sdl/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/Makefile.am Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,51 @@ +bin_PROGRAMS = VisualBoyAdvance + +#noinst_PROGRAMS = TestEmu + +VisualBoyAdvance_SOURCES = \ + SDL.cpp \ + debugger.cpp \ + debugger.h \ + expr-lex.cpp \ + expr.cpp \ + expr.cpp.h \ + exprNode.cpp \ + exprNode.h \ + getopt.c \ + getopt.h \ + getopt1.c \ + ../AutoBuild.h \ + ../NLS.h \ + ../Port.h + +VisualBoyAdvance_LDADD = \ + ../lua/libgblua.a \ + ../common/libgbcom.a \ + ../gb/libgb.a \ + ../gba/libgba.a \ + ../filters/lib386.a \ + ../filters/libfilter.a + +# TestEmu_SOURCES = \ +# TestEmu.cpp \ +# debugger.cpp \ +# debugger.h \ +# expr-lex.cpp \ +# expr.cpp \ +# expr.cpp.h \ +# exprNode.cpp \ +# exprNode.h \ +# ../AutoBuild.h \ +# ../NLS.h \ +# ../Port.h + +# TestEmu_LDADD = @VBA_LIBS@ @SDL_LIBS@ + +# TestEmu_DEPENDENCIES = @VBA_LIBS@ + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src \ + -DSDL \ + -DSYSCONFDIR=\"$(sysconfdir)\" + +AM_CXXFLAGS = -fno-exceptions diff -r b970226568d2 -r 2efb971df515 src/sdl/RingBuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/RingBuffer.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2008 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef RINGBUFFER_H +#define RINGBUFFER_H + +#include "Array.h" +#include +#include +#include + +template +class RingBuffer { + Array buf; + std::size_t sz; + std::size_t rpos; + std::size_t wpos; + +public: + RingBuffer(const std::size_t sz_in = 0) : sz(0), rpos(0), wpos(0) { reset(sz_in); } + + std::size_t avail() const { + return (wpos < rpos ? 0 : sz) + rpos - wpos - 1; + } + + void clear() { + wpos = rpos = 0; + } + + void fill(T value); + + void read(T *out, std::size_t num); + + void reset(std::size_t sz_in); + + std::size_t size() const { + return sz - 1; + } + + std::size_t used() const { + return (wpos < rpos ? sz : 0) + wpos - rpos; + } + + void write(const T *in, std::size_t num); +}; + +template +void RingBuffer::fill(const T value) { + std::fill(buf + 0, buf + sz, value); + rpos = 0; + wpos = sz - 1; +} + +template +void RingBuffer::read(T *out, std::size_t num) { + if (rpos + num > sz) { + const std::size_t n = sz - rpos; + + std::memcpy(out, buf + rpos, n * sizeof(T)); + + rpos = 0; + num -= n; + out += n; + } + + std::memcpy(out, buf + rpos, num * sizeof(T)); + + if ((rpos += num) == sz) + rpos = 0; +} + +template +void RingBuffer::reset(const std::size_t sz_in) { + sz = sz_in + 1; + rpos = wpos = 0; + buf.reset(sz_in ? sz : 0); +} + +template +void RingBuffer::write(const T *in, std::size_t num) { + if (wpos + num > sz) { + const std::size_t n = sz - wpos; + + std::memcpy(buf + wpos, in, n * sizeof(T)); + + wpos = 0; + num -= n; + in += n; + } + + std::memcpy(buf + wpos, in, num * sizeof(T)); + + if ((wpos += num) == sz) + wpos = 0; +} + +#endif diff -r b970226568d2 -r 2efb971df515 src/sdl/SDL.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/SDL.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,3623 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 +#include +#include +#include +#include +#include + +#include "AutoBuild.h" + +#include "Port.h" +#include "SDL.h" +#include "debugger.h" +#include "gba/GBA.h" +#include "gba/GBAGlobals.h" +#include "gba/agbprint.h" +#include "gba/Flash.h" +#include "gba/RTC.h" +#include "gba/GBASound.h" +#include "gb/GB.h" +#include "gb/gbGlobals.h" +#include "common/Text.h" +#include "common/unzip.h" +#include "common/Util.h" +#include "common/movie.h" +#include "common/System.h" +#include "common/inputGlobal.h" +#include "../common/vbalua.h" +#include "SoundSDL.h" + + +#define GBC_CAPABLE ((gbRom[0x143] & 0x80) != 0) +#define SGB_CAPABLE (gbRom[0x146] == 0x03) + +#ifndef WIN32 +# include +# define GETCWD getcwd +#else // WIN32 +# include +# define GETCWD _getcwd +#endif // WIN32 + +#ifndef __GNUC__ +# define HAVE_DECL_GETOPT 0 +# define __STDC__ 1 +# include "getopt.h" +#else // ! __GNUC__ +# define HAVE_DECL_GETOPT 1 +# include "getopt.h" +#endif // ! __GNUC__ + +#ifdef MMX +extern "C" bool cpu_mmx; +#endif +extern bool8 soundEcho; +extern bool8 soundLowPass; +extern bool8 soundReverse; +extern int Init_2xSaI(u32); +extern void _2xSaI(u8*,u32,u8*,u8*,u32,int,int); +extern void _2xSaI32(u8*,u32,u8*,u8*,u32,int,int); +extern void Super2xSaI(u8*,u32,u8*,u8*,u32,int,int); +extern void Super2xSaI32(u8*,u32,u8*,u8*,u32,int,int); +extern void SuperEagle(u8*,u32,u8*,u8*,u32,int,int); +extern void SuperEagle32(u8*,u32,u8*,u8*,u32,int,int); +extern void Pixelate2x16(u8*,u32,u8*,u8*,u32,int,int); +extern void Pixelate2x32(u8*,u32,u8*,u8*,u32,int,int); +extern void MotionBlur(u8*,u32,u8*,u8*,u32,int,int); +extern void MotionBlur32(u8*,u32,u8*,u8*,u32,int,int); +extern void AdMame2x(u8*,u32,u8*,u8*,u32,int,int); +extern void AdMame2x32(u8*,u32,u8*,u8*,u32,int,int); +extern void Simple2x16(u8*,u32,u8*,u8*,u32,int,int); +extern void Simple2x32(u8*,u32,u8*,u8*,u32,int,int); +extern void Bilinear(u8*,u32,u8*,u8*,u32,int,int); +extern void Bilinear32(u8*,u32,u8*,u8*,u32,int,int); +extern void BilinearPlus(u8*,u32,u8*,u8*,u32,int,int); +extern void BilinearPlus32(u8*,u32,u8*,u8*,u32,int,int); +extern void Scanlines(u8*,u32,u8*,u8*,u32,int,int); +extern void Scanlines32(u8*,u32,u8*,u8*,u32,int,int); +extern void ScanlinesTV(u8*,u32,u8*,u8*,u32,int,int); +extern void ScanlinesTV32(u8*,u32,u8*,u8*,u32,int,int); +extern void hq2x(u8*,u32,u8*,u8*,u32,int,int); +extern void hq2x32(u8*,u32,u8*,u8*,u32,int,int); +extern void lq2x(u8*,u32,u8*,u8*,u32,int,int); +extern void lq2x32(u8*,u32,u8*,u8*,u32,int,int); + +extern void SmartIB(u8*,u32,int,int); +extern void SmartIB32(u8*,u32,int,int); +extern void MotionBlurIB(u8*,u32,int,int); +extern void MotionBlurIB32(u8*,u32,int,int); + +void Init_Overlay(SDL_Surface *surface, int overlaytype); +void Quit_Overlay(void); +void Draw_Overlay(SDL_Surface *surface, int size); + +extern void remoteInit(); +extern void remoteCleanUp(); +extern void remoteStubMain(); +extern void remoteStubSignal(int,int); +extern void remoteOutput(char *, u32); +extern void remoteSetProtocol(int); +extern void remoteSetPort(int); +extern void debuggerOutput(char *, u32); + +extern void CPUUpdateRenderBuffers(bool); + +struct EmulatedSystem theEmulator = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + false, + 0 +}; + +SDL_Surface *surface = NULL; +SDL_Overlay *overlay = NULL; +SDL_Rect overlay_rect; + +int systemSpeed = 0; +int systemRedShift = 0; +int systemBlueShift = 0; +int systemGreenShift = 0; +int systemColorDepth = 0; +int systemDebug = 0; +int systemVerbose = 0; +int systemFrameSkip = 0; +int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + +int srcPitch = 0; +int srcWidth = 0; +int srcHeight = 0; +int destWidth = 0; +int destHeight = 0; + +int sensorX = 2047; +int sensorY = 2047; +bool sensorOn = false; + +int filter = 0; +u8 *delta = NULL; + +int sdlPrintUsage = 0; +int disableMMX = 0; + +int systemCartridgeType = 3; +int sizeOption = 0; +int captureFormat = 0; +int useMovie = 0; + +int pauseWhenInactive = 0; +int active = 1; +int emulating = 0; +int RGB_LOW_BITS_MASK=0x821; +u32 systemColorMap32[0x10000]; +u16 systemColorMap16[0x10000]; +u16 systemGbPalette[24]; +void (*filterFunction)(u8*,u32,u8*,u8*,u32,int,int) = NULL; +void (*ifbFunction)(u8*,u32,int,int) = NULL; +int ifbType = 0; +char filename[2048]; +char ipsname[2048]; +char biosFileName[2048]; +char movieFileName[2048]; +char captureDir[2048]; +char saveDir[2048]; +char batteryDir[2048]; + +static char *rewindMemory = NULL; +static int rewindPos = 0; +static int rewindTopPos = 0; +static int rewindCounter = 0; +static int rewindCount = 0; +static bool rewindSaveNeeded = false; +static int rewindTimer = 0; + +#define REWIND_SIZE 400000 + +#define _stricmp strcasecmp + +/*bool sdlButtons[4][12] = { + { false, false, false, false, false, false, + false, false, false, false, false, false }, + { false, false, false, false, false, false, + false, false, false, false, false, false }, + { false, false, false, false, false, false, + false, false, false, false, false, false }, + { false, false, false, false, false, false, + false, false, false, false, false, false } +};*/ +/* + I'm changing the way the SDL GUI handles the button + input to match the one in win32, this is needed in + order to be compatible with the format required by + common/movie.cpp + --Felipe +*/ + +u16 currentButtons[4] = {0, 0, 0, 0}; + +bool sdlMotionButtons[4] = { false, false, false, false }; +const int32 INITIAL_SENSOR_VALUE = 2047; + +int sdlNumDevices = 0; +SDL_Joystick **sdlDevices = NULL; + +bool wasPaused = false; +int autoFrameSkip = 0; +int frameskipadjust = 0; +int showRenderedFrames = 0; +int renderedFrames = 0; + +int throttle = 0; +u32 throttleLastTime = 0; +u32 autoFrameSkipLastTime = 0; + +int showSpeed = 1; +int showSpeedTransparent = 1; +bool disableStatusMessages = false; +bool paused = false; +bool pauseNextFrame = false; +bool debugger = false; +bool debuggerStub = false; +int fullscreen = 0; +bool systemSoundOn = false; +bool yuv = false; +int yuvType = 0; +bool removeIntros = false; +int sdlFlashSize = 0; +int sdlAutoIPS = 1; +int sdlRtcEnable = 0; +int sdlAgbPrint = 0; + +int sdlDefaultJoypad = 0; + +extern void debuggerSignal(int,int); + +void (*dbgMain)() = debuggerMain; +void (*dbgSignal)(int,int) = debuggerSignal; +void (*dbgOutput)(char *, u32) = debuggerOutput; + +int mouseCounter = 0; +int autoFire = 0; +bool autoFireToggle = false; + +bool screenMessage[8] = {false,false,false,false,false,false,false,false}; +char screenMessageBuffer[8][21]; +u32 screenMessageTime[8] = {0,0,0,0,0,0,0,0}; +u32 screenMessageDuration[8] = {0,0,0,0,0,0,0,0}; + +SDL_cond *cond = NULL; +SDL_mutex *mutex = NULL; +u8* sdlBuffer; +int sdlSoundLen = 0; +SoundSDL* soundDriver = NULL; + +char *arg0; + +#ifndef C_CORE +u8 sdlStretcher[16384]; +int sdlStretcherPos; +#else +void (*sdlStretcher)(u8 *, u8*) = NULL; +#endif + +u16 joypad[4][12] = { + { SDLK_LEFT, SDLK_RIGHT, + SDLK_UP, SDLK_DOWN, + SDLK_z, SDLK_x, + SDLK_RETURN,SDLK_BACKSPACE, + SDLK_a, SDLK_s, + SDLK_SPACE, SDLK_F12 + }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +u16 defaultJoypad[12] = { + SDLK_LEFT, SDLK_RIGHT, + SDLK_UP, SDLK_DOWN, + SDLK_z, SDLK_x, + SDLK_RETURN,SDLK_BACKSPACE, + SDLK_a, SDLK_s, + SDLK_SPACE, SDLK_F12 +}; + +u16 motion[4] = { + SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 +}; + +u16 defaultMotion[4] = { + SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 +}; + +struct option sdlOptions[] = { + { "agb-print", no_argument, &sdlAgbPrint, 1 }, + { "auto-frameskip", no_argument, &autoFrameSkip, 1 }, + { "bios", required_argument, 0, 'b' }, + { "config", required_argument, 0, 'c' }, + { "debug", no_argument, 0, 'd' }, + { "filter", required_argument, 0, 'f' }, + { "filter-normal", no_argument, &filter, 0 }, + { "filter-tv-mode", no_argument, &filter, 1 }, + { "filter-2xsai", no_argument, &filter, 2 }, + { "filter-super-2xsai", no_argument, &filter, 3 }, + { "filter-super-eagle", no_argument, &filter, 4 }, + { "filter-pixelate", no_argument, &filter, 5 }, + { "filter-motion-blur", no_argument, &filter, 6 }, + { "filter-advmame", no_argument, &filter, 7 }, + { "filter-simple2x", no_argument, &filter, 8 }, + { "filter-bilinear", no_argument, &filter, 9 }, + { "filter-bilinear+", no_argument, &filter, 10 }, + { "filter-scanlines", no_argument, &filter, 11 }, + { "filter-hq2x", no_argument, &filter, 12 }, + { "filter-lq2x", no_argument, &filter, 13 }, + { "flash-size", required_argument, 0, 'S' }, + { "flash-64k", no_argument, &sdlFlashSize, 0 }, + { "flash-128k", no_argument, &sdlFlashSize, 1 }, + { "frameskip", required_argument, 0, 's' }, + { "fullscreen", no_argument, &fullscreen, 1 }, + { "gdb", required_argument, 0, 'G' }, + { "help", no_argument, &sdlPrintUsage, 1 }, + { "ifb-none", no_argument, &ifbType, 0 }, + { "ifb-motion-blur", no_argument, &ifbType, 1 }, + { "ifb-smart", no_argument, &ifbType, 2 }, + { "ips", required_argument, 0, 'i' }, + { "no-agb-print", no_argument, &sdlAgbPrint, 0 }, + { "no-auto-frameskip", no_argument, &autoFrameSkip, 0 }, + { "no-debug", no_argument, 0, 'N' }, + { "no-ips", no_argument, &sdlAutoIPS, 0 }, + { "no-mmx", no_argument, &disableMMX, 1 }, + { "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 }, + { "no-rtc", no_argument, &sdlRtcEnable, 0 }, + { "no-show-speed", no_argument, &showSpeed, 0 }, + { "no-throttle", no_argument, &throttle, 0 }, + { "pause-when-inactive", no_argument, &pauseWhenInactive, 1 }, + { "profile", optional_argument, 0, 'P' }, + { "rtc", no_argument, &sdlRtcEnable, 1 }, + { "save-type", required_argument, 0, 't' }, + { "save-auto", no_argument, &cpuSaveType, 0 }, + { "save-eeprom", no_argument, &cpuSaveType, 1 }, + { "save-sram", no_argument, &cpuSaveType, 2 }, + { "save-flash", no_argument, &cpuSaveType, 3 }, + { "save-sensor", no_argument, &cpuSaveType, 4 }, + { "save-none", no_argument, &cpuSaveType, 5 }, + { "show-speed-normal", no_argument, &showSpeed, 1 }, + { "show-speed-detailed", no_argument, &showSpeed, 2 }, + { "throttle", required_argument, 0, 'T' }, + { "verbose", required_argument, 0, 'v' }, + { "video-1x", no_argument, &sizeOption, 0 }, + { "video-2x", no_argument, &sizeOption, 1 }, + { "video-3x", no_argument, &sizeOption, 2 }, + { "video-4x", no_argument, &sizeOption, 3 }, + { "yuv", required_argument, 0, 'Y' }, + { "recordmovie", required_argument, 0, 'r' }, + { "playmovie", required_argument, 0, 'p' }, + { "watchmovie", required_argument, 0, 'w' }, + { NULL, no_argument, NULL, 0 } +}; + +#ifndef C_CORE +#define SDL_LONG(val) \ + *((u32 *)&sdlStretcher[sdlStretcherPos]) = val;\ + sdlStretcherPos+=4; + +#define SDL_AND_EAX(val) \ + sdlStretcher[sdlStretcherPos++] = 0x25;\ + SDL_LONG(val); + +#define SDL_AND_EBX(val) \ + sdlStretcher[sdlStretcherPos++] = 0x81;\ + sdlStretcher[sdlStretcherPos++] = 0xe3;\ + SDL_LONG(val); + +#define SDL_OR_EAX_EBX \ + sdlStretcher[sdlStretcherPos++] = 0x09;\ + sdlStretcher[sdlStretcherPos++] = 0xd8; + +#define SDL_LOADL_EBX \ + sdlStretcher[sdlStretcherPos++] = 0x8b;\ + sdlStretcher[sdlStretcherPos++] = 0x1f; + +#define SDL_LOADW \ + sdlStretcher[sdlStretcherPos++] = 0x66;\ + sdlStretcher[sdlStretcherPos++] = 0x8b;\ + sdlStretcher[sdlStretcherPos++] = 0x06;\ + sdlStretcher[sdlStretcherPos++] = 0x83;\ + sdlStretcher[sdlStretcherPos++] = 0xc6;\ + sdlStretcher[sdlStretcherPos++] = 0x02; + +#define SDL_LOADL \ + sdlStretcher[sdlStretcherPos++] = 0x8b;\ + sdlStretcher[sdlStretcherPos++] = 0x06;\ + sdlStretcher[sdlStretcherPos++] = 0x83;\ + sdlStretcher[sdlStretcherPos++] = 0xc6;\ + sdlStretcher[sdlStretcherPos++] = 0x04; + +#define SDL_LOADL2 \ + sdlStretcher[sdlStretcherPos++] = 0x8b;\ + sdlStretcher[sdlStretcherPos++] = 0x06;\ + sdlStretcher[sdlStretcherPos++] = 0x83;\ + sdlStretcher[sdlStretcherPos++] = 0xc6;\ + sdlStretcher[sdlStretcherPos++] = 0x03; + +#define SDL_STOREW \ + sdlStretcher[sdlStretcherPos++] = 0x66;\ + sdlStretcher[sdlStretcherPos++] = 0x89;\ + sdlStretcher[sdlStretcherPos++] = 0x07;\ + sdlStretcher[sdlStretcherPos++] = 0x83;\ + sdlStretcher[sdlStretcherPos++] = 0xc7;\ + sdlStretcher[sdlStretcherPos++] = 0x02; + +#define SDL_STOREL \ + sdlStretcher[sdlStretcherPos++] = 0x89;\ + sdlStretcher[sdlStretcherPos++] = 0x07;\ + sdlStretcher[sdlStretcherPos++] = 0x83;\ + sdlStretcher[sdlStretcherPos++] = 0xc7;\ + sdlStretcher[sdlStretcherPos++] = 0x04; + +#define SDL_STOREL2 \ + sdlStretcher[sdlStretcherPos++] = 0x89;\ + sdlStretcher[sdlStretcherPos++] = 0x07;\ + sdlStretcher[sdlStretcherPos++] = 0x83;\ + sdlStretcher[sdlStretcherPos++] = 0xc7;\ + sdlStretcher[sdlStretcherPos++] = 0x03; + +#define SDL_RET \ + sdlStretcher[sdlStretcherPos++] = 0xc3; + +#define SDL_PUSH_EAX \ + sdlStretcher[sdlStretcherPos++] = 0x50; + +#define SDL_PUSH_ECX \ + sdlStretcher[sdlStretcherPos++] = 0x51; + +#define SDL_PUSH_EBX \ + sdlStretcher[sdlStretcherPos++] = 0x53; + +#define SDL_PUSH_ESI \ + sdlStretcher[sdlStretcherPos++] = 0x56; + +#define SDL_PUSH_EDI \ + sdlStretcher[sdlStretcherPos++] = 0x57; + +#define SDL_POP_EAX \ + sdlStretcher[sdlStretcherPos++] = 0x58; + +#define SDL_POP_ECX \ + sdlStretcher[sdlStretcherPos++] = 0x59; + +#define SDL_POP_EBX \ + sdlStretcher[sdlStretcherPos++] = 0x5b; + +#define SDL_POP_ESI \ + sdlStretcher[sdlStretcherPos++] = 0x5e; + +#define SDL_POP_EDI \ + sdlStretcher[sdlStretcherPos++] = 0x5f; + +#define SDL_MOV_ECX(val) \ + sdlStretcher[sdlStretcherPos++] = 0xb9;\ + SDL_LONG(val); + +#define SDL_REP_MOVSB \ + sdlStretcher[sdlStretcherPos++] = 0xf3;\ + sdlStretcher[sdlStretcherPos++] = 0xa4; + +#define SDL_REP_MOVSW \ + sdlStretcher[sdlStretcherPos++] = 0xf3;\ + sdlStretcher[sdlStretcherPos++] = 0x66;\ + sdlStretcher[sdlStretcherPos++] = 0xa5; + +#define SDL_REP_MOVSL \ + sdlStretcher[sdlStretcherPos++] = 0xf3;\ + sdlStretcher[sdlStretcherPos++] = 0xa5; + +void sdlMakeStretcher(int width) +{ + sdlStretcherPos = 0; + switch(systemColorDepth) { + case 16: + if(sizeOption) { + SDL_PUSH_EAX; + SDL_PUSH_ESI; + SDL_PUSH_EDI; + for(int i = 0; i < width; i++) { + SDL_LOADW; + SDL_STOREW; + SDL_STOREW; + if(sizeOption > 1) { + SDL_STOREW; + } + if(sizeOption > 2) { + SDL_STOREW; + } + } + SDL_POP_EDI; + SDL_POP_ESI; + SDL_POP_EAX; + SDL_RET; + } else { + SDL_PUSH_ESI; + SDL_PUSH_EDI; + SDL_PUSH_ECX; + SDL_MOV_ECX(width); + SDL_REP_MOVSW; + SDL_POP_ECX; + SDL_POP_EDI; + SDL_POP_ESI; + SDL_RET; + } + break; + case 24: + if(sizeOption) { + SDL_PUSH_EAX; + SDL_PUSH_ESI; + SDL_PUSH_EDI; + int w = width - 1; + for(int i = 0; i < w; i++) { + SDL_LOADL2; + SDL_STOREL2; + SDL_STOREL2; + if(sizeOption > 1) { + SDL_STOREL2; + } + if(sizeOption > 2) { + SDL_STOREL2; + } + } + // need to write the last one + SDL_LOADL2; + SDL_STOREL2; + if(sizeOption > 1) { + SDL_STOREL2; + } + if(sizeOption > 2) { + SDL_STOREL2; + } + SDL_AND_EAX(0x00ffffff); + SDL_PUSH_EBX; + SDL_LOADL_EBX; + SDL_AND_EBX(0xff000000); + SDL_OR_EAX_EBX; + SDL_POP_EBX; + SDL_STOREL2; + SDL_POP_EDI; + SDL_POP_ESI; + SDL_POP_EAX; + SDL_RET; + } else { + SDL_PUSH_ESI; + SDL_PUSH_EDI; + SDL_PUSH_ECX; + SDL_MOV_ECX(3*width); + SDL_REP_MOVSB; + SDL_POP_ECX; + SDL_POP_EDI; + SDL_POP_ESI; + SDL_RET; + } + break; + case 32: + if(sizeOption) { + SDL_PUSH_EAX; + SDL_PUSH_ESI; + SDL_PUSH_EDI; + for(int i = 0; i < width; i++) { + SDL_LOADL; + SDL_STOREL; + SDL_STOREL; + if(sizeOption > 1) { + SDL_STOREL; + } + if(sizeOption > 2) { + SDL_STOREL; + } + } + SDL_POP_EDI; + SDL_POP_ESI; + SDL_POP_EAX; + SDL_RET; + } else { + SDL_PUSH_ESI; + SDL_PUSH_EDI; + SDL_PUSH_ECX; + SDL_MOV_ECX(width); + SDL_REP_MOVSL; + SDL_POP_ECX; + SDL_POP_EDI; + SDL_POP_ESI; + SDL_RET; + } + break; + } +} + +#ifdef _MSC_VER +#define SDL_CALL_STRETCHER \ + {\ + __asm mov eax, stretcher\ + __asm mov edi, dest\ + __asm mov esi, src\ + __asm call eax\ + } +#else +#define SDL_CALL_STRETCHER \ + asm volatile("call *%%eax"::"a" (stretcher),"S" (src),"D" (dest)) +#endif +#else +#define SDL_CALL_STRETCHER \ + sdlStretcher(src, dest) + +void sdlStretch16x1(u8 *src, u8 *dest) +{ + u16 *s = (u16 *)src; + u16 *d = (u16 *)dest; + for(int i = 0; i < srcWidth; i++) + *d++ = *s++; +} + +void sdlStretch16x2(u8 *src, u8 *dest) +{ + u16 *s = (u16 *)src; + u16 *d = (u16 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *s++; + } +} + +void sdlStretch16x3(u8 *src, u8 *dest) +{ + u16 *s = (u16 *)src; + u16 *d = (u16 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *s; + *d++ = *s++; + } +} + +void sdlStretch16x4(u8 *src, u8 *dest) +{ + u16 *s = (u16 *)src; + u16 *d = (u16 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *s; + *d++ = *s; + *d++ = *s++; + } +} + +void (*sdlStretcher16[4])(u8 *, u8 *) = { + sdlStretch16x1, + sdlStretch16x2, + sdlStretch16x3, + sdlStretch16x4 +}; + +void sdlStretch32x1(u8 *src, u8 *dest) +{ + u32 *s = (u32 *)src; + u32 *d = (u32 *)dest; + for(int i = 0; i < srcWidth; i++) + *d++ = *s++; +} + +void sdlStretch32x2(u8 *src, u8 *dest) +{ + u32 *s = (u32 *)src; + u32 *d = (u32 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *s++; + } +} + +void sdlStretch32x3(u8 *src, u8 *dest) +{ + u32 *s = (u32 *)src; + u32 *d = (u32 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *s; + *d++ = *s++; + } +} + +void sdlStretch32x4(u8 *src, u8 *dest) +{ + u32 *s = (u32 *)src; + u32 *d = (u32 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *s; + *d++ = *s; + *d++ = *s++; + } +} + +void (*sdlStretcher32[4])(u8 *, u8 *) = { + sdlStretch32x1, + sdlStretch32x2, + sdlStretch32x3, + sdlStretch32x4 +}; + +void sdlStretch24x1(u8 *src, u8 *dest) +{ + u8 *s = src; + u8 *d = dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } +} + +void sdlStretch24x2(u8 *src, u8 *dest) +{ + u8 *s = (u8 *)src; + u8 *d = (u8 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + } +} + +void sdlStretch24x3(u8 *src, u8 *dest) +{ + u8 *s = (u8 *)src; + u8 *d = (u8 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + } +} + +void sdlStretch24x4(u8 *src, u8 *dest) +{ + u8 *s = (u8 *)src; + u8 *d = (u8 *)dest; + for(int i = 0; i < srcWidth; i++) { + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + *d++ = *s; + *d++ = *(s+1); + *d++ = *(s+2); + s += 3; + } +} + +void (*sdlStretcher24[4])(u8 *, u8 *) = { + sdlStretch24x1, + sdlStretch24x2, + sdlStretch24x3, + sdlStretch24x4 +}; + +#endif + +u32 sdlFromHex(char *s) +{ + u32 value; + sscanf(s, "%x", &value); + return value; +} + +#ifdef __MSC__ +#define stat _stat +#define S_IFDIR _S_IFDIR +#endif + +void sdlCheckDirectory(char *dir) +{ + struct stat buf; + + int len = strlen(dir); + + char *p = dir + len - 1; + + if(*p == '/' || + *p == '\\') + *p = 0; + + if(stat(dir, &buf) == 0) { + if(!(buf.st_mode & S_IFDIR)) { + fprintf(stderr, "Error: %s is not a directory\n", dir); + dir[0] = 0; + } + } else { + fprintf(stderr, "Error: %s does not exist\n", dir); + dir[0] = 0; + } +} + +char *sdlGetFilename(char *name) +{ + static char filebuffer[2048]; + + int len = strlen(name); + + char *p = name + len - 1; + + while(true) { + if(*p == '/' || + *p == '\\') { + p++; + break; + } + len--; + p--; + if(len == 0) + break; + } + + if(len == 0) + strcpy(filebuffer, name); + else + strcpy(filebuffer, p); + return filebuffer; +} + +FILE *sdlFindFile(const char *name) +{ + char buffer[4096]; + char path[2048]; + +#ifdef WIN32 +#define PATH_SEP ";" +#define FILE_SEP '\\' +#define EXE_NAME "VisualBoyAdvance-SDL.exe" +#else // ! WIN32 +#define PATH_SEP ":" +#define FILE_SEP '/' +#define EXE_NAME "VisualBoyAdvance" +#endif // ! WIN32 + + fprintf(stderr, "Searching for file %s\n", name); + + if(GETCWD(buffer, 2048)) { + fprintf(stderr, "Searching current directory: %s\n", buffer); + } + + FILE *f = fopen(name, "r"); + if(f != NULL) { + return f; + } + + char *home = getenv("HOME"); + + if(home != NULL) { + fprintf(stderr, "Searching home directory: %s\n", home); + sprintf(path, "%s%c%s", home, FILE_SEP, name); + f = fopen(path, "r"); + if(f != NULL) + return f; + } + +#ifdef WIN32 + home = getenv("USERPROFILE"); + if(home != NULL) { + fprintf(stderr, "Searching user profile directory: %s\n", home); + sprintf(path, "%s%c%s", home, FILE_SEP, name); + f = fopen(path, "r"); + if(f != NULL) + return f; + } +#else // ! WIN32 + fprintf(stderr, "Searching system config directory: %s\n", SYSCONFDIR); + sprintf(path, "%s%c%s", SYSCONFDIR, FILE_SEP, name); + f = fopen(path, "r"); + if(f != NULL) + return f; +#endif // ! WIN32 + + if(!strchr(arg0, '/') && + !strchr(arg0, '\\')) { + char *path = getenv("PATH"); + + if(path != NULL) { + fprintf(stderr, "Searching PATH\n"); + strncpy(buffer, path, 4096); + buffer[4095] = 0; + char *tok = strtok(buffer, PATH_SEP); + + while(tok) { + sprintf(path, "%s%c%s", tok, FILE_SEP, EXE_NAME); + f = fopen(path, "r"); + if(f != NULL) { + char path2[2048]; + fclose(f); + sprintf(path2, "%s%c%s", tok, FILE_SEP, name); + f = fopen(path2, "r"); + if(f != NULL) { + fprintf(stderr, "Found at %s\n", path2); + return f; + } + } + tok = strtok(NULL, PATH_SEP); + } + } + } else { + // executable is relative to some directory + fprintf(stderr, "Searching executable directory\n"); + strcpy(buffer, arg0); + char *p = strrchr(buffer, FILE_SEP); + if(p) { + *p = 0; + sprintf(path, "%s%c%s", buffer, FILE_SEP, name); + f = fopen(path, "r"); + if(f != NULL) + return f; + } + } + return NULL; +} + +void sdlReadPreferences(FILE *f) +{ + char buffer[2048]; + + while(1) { + char *s = fgets(buffer, 2048, f); + + if(s == NULL) + break; + + char *p = strchr(s, '#'); + + if(p) + *p = 0; + + char *token = strtok(s, " \t\n\r="); + + if(!token) + continue; + + if(strlen(token) == 0) + continue; + + char *key = token; + char *value = strtok(NULL, "\t\n\r"); + + if(value == NULL) { + fprintf(stderr, "Empty value for key %s\n", key); + continue; + } + + if(!strcmp(key,"Joy0_Left")) { + joypad[0][KEY_LEFT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Right")) { + joypad[0][KEY_RIGHT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Up")) { + joypad[0][KEY_UP] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Down")) { + joypad[0][KEY_DOWN] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_A")) { + joypad[0][KEY_BUTTON_A] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_B")) { + joypad[0][KEY_BUTTON_B] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_L")) { + joypad[0][KEY_BUTTON_L] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_R")) { + joypad[0][KEY_BUTTON_R] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Start")) { + joypad[0][KEY_BUTTON_START] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Select")) { + joypad[0][KEY_BUTTON_SELECT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Speed")) { + joypad[0][KEY_BUTTON_SPEED] = sdlFromHex(value); + } else if(!strcmp(key, "Joy0_Capture")) { + joypad[0][KEY_BUTTON_CAPTURE] = sdlFromHex(value); + } else if(!strcmp(key,"Joy1_Left")) { + joypad[1][KEY_LEFT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Right")) { + joypad[1][KEY_RIGHT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Up")) { + joypad[1][KEY_UP] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Down")) { + joypad[1][KEY_DOWN] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_A")) { + joypad[1][KEY_BUTTON_A] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_B")) { + joypad[1][KEY_BUTTON_B] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_L")) { + joypad[1][KEY_BUTTON_L] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_R")) { + joypad[1][KEY_BUTTON_R] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Start")) { + joypad[1][KEY_BUTTON_START] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Select")) { + joypad[1][KEY_BUTTON_SELECT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Speed")) { + joypad[1][KEY_BUTTON_SPEED] = sdlFromHex(value); + } else if(!strcmp(key, "Joy1_Capture")) { + joypad[1][KEY_BUTTON_CAPTURE] = sdlFromHex(value); + } else if(!strcmp(key,"Joy2_Left")) { + joypad[2][KEY_LEFT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Right")) { + joypad[2][KEY_RIGHT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Up")) { + joypad[2][KEY_UP] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Down")) { + joypad[2][KEY_DOWN] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_A")) { + joypad[2][KEY_BUTTON_A] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_B")) { + joypad[2][KEY_BUTTON_B] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_L")) { + joypad[2][KEY_BUTTON_L] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_R")) { + joypad[2][KEY_BUTTON_R] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Start")) { + joypad[2][KEY_BUTTON_START] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Select")) { + joypad[2][KEY_BUTTON_SELECT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Speed")) { + joypad[2][KEY_BUTTON_SPEED] = sdlFromHex(value); + } else if(!strcmp(key, "Joy2_Capture")) { + joypad[2][KEY_BUTTON_CAPTURE] = sdlFromHex(value); + } else if(!strcmp(key,"Joy4_Left")) { + joypad[4][KEY_LEFT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Right")) { + joypad[4][KEY_RIGHT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Up")) { + joypad[4][KEY_UP] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Down")) { + joypad[4][KEY_DOWN] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_A")) { + joypad[4][KEY_BUTTON_A] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_B")) { + joypad[4][KEY_BUTTON_B] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_L")) { + joypad[4][KEY_BUTTON_L] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_R")) { + joypad[4][KEY_BUTTON_R] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Start")) { + joypad[4][KEY_BUTTON_START] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Select")) { + joypad[4][KEY_BUTTON_SELECT] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Speed")) { + joypad[4][KEY_BUTTON_SPEED] = sdlFromHex(value); + } else if(!strcmp(key, "Joy4_Capture")) { + joypad[4][KEY_BUTTON_CAPTURE] = sdlFromHex(value); + } else if(!strcmp(key, "Motion_Left")) { + motion[KEY_LEFT] = sdlFromHex(value); + } else if(!strcmp(key, "Motion_Right")) { + motion[KEY_RIGHT] = sdlFromHex(value); + } else if(!strcmp(key, "Motion_Up")) { + motion[KEY_UP] = sdlFromHex(value); + } else if(!strcmp(key, "Motion_Down")) { + motion[KEY_DOWN] = sdlFromHex(value); + } else if(!strcmp(key, "frameSkip")) { + frameSkip = sdlFromHex(value); + if(frameSkip < 0 || frameSkip > 9) + frameSkip = 2; + } else if(!strcmp(key, "gbFrameSkip")) { + gbFrameSkip = sdlFromHex(value); + if(gbFrameSkip < 0 || gbFrameSkip > 9) + gbFrameSkip = 0; + } else if(!strcmp(key, "video")) { + sizeOption = sdlFromHex(value); + if(sizeOption < 0 || sizeOption > 3) + sizeOption = 1; + } else if(!strcmp(key, "fullScreen")) { + fullscreen = sdlFromHex(value) ? 1 : 0; + } else if(!strcmp(key, "useBios")) { + useBios = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "skipBios")) { + skipBios = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "biosFile")) { + strcpy(biosFileName, value); + } else if(!strcmp(key, "filter")) { + filter = sdlFromHex(value); + if(filter < 0 || filter > 13) + filter = 0; + } else if(!strcmp(key, "disableStatus")) { + disableStatusMessages = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "borderOn")) { + gbBorderOn = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "borderAutomatic")) { + gbBorderAutomatic = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "emulatorType")) { + gbEmulatorType = sdlFromHex(value); + if(gbEmulatorType < 0 || gbEmulatorType > 5) + gbEmulatorType = 1; + } else if(!strcmp(key, "colorOption")) { + gbColorOption = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "captureDir")) { + sdlCheckDirectory(value); + strcpy(captureDir, value); + } else if(!strcmp(key, "saveDir")) { + sdlCheckDirectory(value); + strcpy(saveDir, value); + } else if(!strcmp(key, "batteryDir")) { + sdlCheckDirectory(value); + strcpy(batteryDir, value); + } else if(!strcmp(key, "captureFormat")) { + captureFormat = sdlFromHex(value); + } else if(!strcmp(key, "soundQuality")) { + soundQuality = sdlFromHex(value); + switch(soundQuality) { + case 1: break; + default: + fprintf(stderr, "The rerecording version will run only sound at highest quality. Defaulting to 44.1 KHz\n"); + soundQuality = 1; + break; + } + } else if(!strcmp(key, "soundOff")) { + soundOffFlag = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "soundEnable")) { + int res = sdlFromHex(value) & 0x30f; + soundEnableChannels(res); + soundDisableChannels(~res); + } else if(!strcmp(key, "soundEcho")) { + soundEcho = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "soundLowPass")) { + soundLowPass = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "soundReverse")) { + soundReverse = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "soundVolume")) { + soundVolume = sdlFromHex(value); + if(soundVolume < 0 || soundVolume > 3) + soundVolume = 0; + } else if(!strcmp(key, "removeIntros")) { + removeIntros = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "saveType")) { + cpuSaveType = sdlFromHex(value); + if(cpuSaveType < 0 || cpuSaveType > 5) + cpuSaveType = 0; + } else if(!strcmp(key, "flashSize")) { + sdlFlashSize = sdlFromHex(value); + if(sdlFlashSize != 0 && sdlFlashSize != 1) + sdlFlashSize = 0; + } else if(!strcmp(key, "ifbType")) { + ifbType = sdlFromHex(value); + if(ifbType < 0 || ifbType > 2) + ifbType = 0; + } else if(!strcmp(key, "showSpeed")) { + showSpeed = sdlFromHex(value); + if(showSpeed < 0 || showSpeed > 2) + showSpeed = 1; + } else if(!strcmp(key, "showSpeedTransparent")) { + showSpeedTransparent = sdlFromHex(value); + } else if(!strcmp(key, "autoFrameSkip")) { + autoFrameSkip = sdlFromHex(value); + } else if(!strcmp(key, "throttle")) { + throttle = sdlFromHex(value); + if(throttle != 0 && (throttle < 5 || throttle > 1000)) + throttle = 0; + } else if(!strcmp(key, "disableMMX")) { +#ifdef MMX + cpu_mmx = sdlFromHex(value) ? false : true; +#endif + } else if(!strcmp(key, "pauseWhenInactive")) { + pauseWhenInactive = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "agbPrint")) { + sdlAgbPrint = sdlFromHex(value); + } else if(!strcmp(key, "rtcEnabled")) { + sdlRtcEnable = sdlFromHex(value); + } else if(!strcmp(key, "rewindTimer")) { + rewindTimer = sdlFromHex(value); + if(rewindTimer < 0 || rewindTimer > 600) + rewindTimer = 0; + rewindTimer *= 6; // convert value to 10 frames multiple + } else if(!strcmp(key, "enhancedDetection")) { + cpuEnhancedDetection = sdlFromHex(value) ? true : false; + } else { + fprintf(stderr, "Unknown configuration key %s\n", key); + } + } +} + +void sdlReadPreferences() +{ + FILE *f = sdlFindFile("VisualBoyAdvance.cfg"); + + if(f == NULL) { + fprintf(stderr, "Configuration file NOT FOUND (using defaults)\n"); + return; + } else + fprintf(stderr, "Reading configuration file.\n"); + + sdlReadPreferences(f); + + fclose(f); +} + +static void sdlApplyPerImagePreferences() +{ + FILE *f = sdlFindFile("vba-over.ini"); + if(!f) { + fprintf(stderr, "vba-over.ini NOT FOUND (using emulator settings)\n"); + return; + } else + fprintf(stderr, "Reading vba-over.ini\n"); + + char buffer[7]; + buffer[0] = '['; + buffer[1] = rom[0xac]; + buffer[2] = rom[0xad]; + buffer[3] = rom[0xae]; + buffer[4] = rom[0xaf]; + buffer[5] = ']'; + buffer[6] = 0; + + char readBuffer[2048]; + + bool found = false; + + while(1) { + char *s = fgets(readBuffer, 2048, f); + + if(s == NULL) + break; + + char *p = strchr(s, ';'); + + if(p) + *p = 0; + + char *token = strtok(s, " \t\n\r="); + + if(!token) + continue; + if(strlen(token) == 0) + continue; + + if(!strcmp(token, buffer)) { + found = true; + break; + } + } + + if(found) { + while(1) { + char *s = fgets(readBuffer, 2048, f); + + if(s == NULL) + break; + + char *p = strchr(s, ';'); + if(p) + *p = 0; + + char *token = strtok(s, " \t\n\r="); + if(!token) + continue; + if(strlen(token) == 0) + continue; + + if(token[0] == '[') // starting another image settings + break; + char *value = strtok(NULL, "\t\n\r="); + if(value == NULL) + continue; + + if(!strcmp(token, "rtcEnabled")) + rtcEnable(atoi(value) == 0 ? false : true); + else if(!strcmp(token, "flashSize")) { + int size = atoi(value); + if(size == 0x10000 || size == 0x20000) + flashSetSize(size); + } else if(!strcmp(token, "saveType")) { + int save = atoi(value); + if(save >= 0 && save <= 5) + cpuSaveType = save; + } + } + } + fclose(f); +} + +static int sdlCalculateShift(u32 mask) +{ + int m = 0; + + while(mask) { + m++; + mask >>= 1; + } + + return m-5; +} + +static int sdlCalculateMaskWidth(u32 mask) +{ + int m = 0; + int mask2 = mask; + + while(mask2) { + m++; + mask2 >>= 1; + } + + int m2 = 0; + mask2 = mask; + while(!(mask2 & 1)) { + m2++; + mask2 >>= 1; + } + + return m - m2; +} + +void sdlWriteState(int num) +{ + char stateName[2048]; + + if(saveDir[0]) + sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), + num+1); + else + sprintf(stateName,"%s%d.sgm", filename, num+1); + if(theEmulator.emuWriteState) + theEmulator.emuWriteState(stateName); + sprintf(stateName, "Wrote state %d", num+1); + systemScreenMessage(stateName); +} + +void sdlReadState(int num) +{ + char stateName[2048]; + + if(saveDir[0]) + sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), + num+1); + else + sprintf(stateName,"%s%d.sgm", filename, num+1); + + if(theEmulator.emuReadState) + theEmulator.emuReadState(stateName); + + sprintf(stateName, "Loaded state %d", num+1); + systemScreenMessage(stateName); +} + +void sdlWriteBattery() +{ + char buffer[1048]; + + if(batteryDir[0]) + sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); + else + sprintf(buffer, "%s.sav", filename); + + theEmulator.emuWriteBattery(buffer); + + systemScreenMessage("Wrote battery"); +} + +void sdlReadBattery() +{ + char buffer[1048]; + + if(batteryDir[0]) + sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); + else + sprintf(buffer, "%s.sav", filename); + + bool res = false; + + res = theEmulator.emuReadBattery(buffer); + + if(res) + systemScreenMessage("Loaded battery"); +} + +#define MOD_KEYS (KMOD_CTRL|KMOD_SHIFT|KMOD_ALT|KMOD_META) +#define MOD_NOCTRL (KMOD_SHIFT|KMOD_ALT|KMOD_META) +#define MOD_NOALT (KMOD_CTRL|KMOD_SHIFT|KMOD_META) +#define MOD_NOSHIFT (KMOD_CTRL|KMOD_ALT|KMOD_META) + +void sdlUpdateKey(int key, bool down) +{ + int i; + for(int j = 0; j < 4; j++) { + for(i = 0 ; i < 12; i++) { + if((joypad[j][i] & 0xf000) == 0) { + if(key == joypad[j][i]) + if (down) currentButtons[j] |= 1<> 12); + int b = joypad[j][i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (b >= 128) && (b == (button+128))) { + if (pressed) currentButtons[j] |= 1<> 12); + int b = motion[i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (b >= 128) && (b == (button+128))) { + sdlMotionButtons[i] = pressed; + } + } + } +} + +void sdlUpdateJoyHat(int which, + int hat, + int value) +{ + int i; + for(int j = 0; j < 4; j++) { + for(i = 0; i < 12; i++) { + int dev = (joypad[j][i] >> 12); + int a = joypad[j][i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (a>=32) && (a < 48) && (((a&15)>>2) == hat)) { + int dir = a & 3; + int v = 0; + switch(dir) { + case 0: + v = value & SDL_HAT_UP; + break; + case 1: + v = value & SDL_HAT_DOWN; + break; + case 2: + v = value & SDL_HAT_RIGHT; + break; + case 3: + v = value & SDL_HAT_LEFT; + break; + } + if (v) currentButtons[j] |= 1<> 12); + int a = motion[i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (a>=32) && (a < 48) && (((a&15)>>2) == hat)) { + int dir = a & 3; + int v = 0; + switch(dir) { + case 0: + v = value & SDL_HAT_UP; + break; + case 1: + v = value & SDL_HAT_DOWN; + break; + case 2: + v = value & SDL_HAT_RIGHT; + break; + case 3: + v = value & SDL_HAT_LEFT; + break; + } + sdlMotionButtons[i] = (v ? true : false); + } + } + } +} + +void sdlUpdateJoyAxis(int which, + int axis, + int value) +{ + int i; + for(int j = 0; j < 4; j++) { + for(i = 0; i < 12; i++) { + int dev = (joypad[j][i] >> 12); + int a = joypad[j][i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (a < 32) && ((a>>1) == axis)) { + //I have no idea what this does, is this reimplementation correct? --Felipe + if (value>16384) { + if (a&1) currentButtons[j] |= 1<> 12); + int a = motion[i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (a < 32) && ((a>>1) == axis)) { + sdlMotionButtons[i] = (a & 1) ? (value > 16384) : (value < -16384); + } + } + } +} + +bool sdlCheckJoyKey(int key) +{ + int dev = (key >> 12) - 1; + int what = key & 0xfff; + + if(what >= 128) { + // joystick button + int button = what - 128; + + if(button >= SDL_JoystickNumButtons(sdlDevices[dev])) + return false; + } else if (what < 0x20) { + // joystick axis + what >>= 1; + if(what >= SDL_JoystickNumAxes(sdlDevices[dev])) + return false; + } else if (what < 0x30) { + // joystick hat + what = (what & 15); + what >>= 2; + if(what >= SDL_JoystickNumHats(sdlDevices[dev])) + return false; + } + + // no problem found + return true; +} + +void sdlCheckKeys() +{ + sdlNumDevices = SDL_NumJoysticks(); + + if(sdlNumDevices) + sdlDevices = (SDL_Joystick **)calloc(1,sdlNumDevices * + sizeof(SDL_Joystick **)); + int i; + + bool usesJoy = false; + + for(int j = 0; j < 4; j++) { + for(i = 0; i < 12; i++) { + int dev = joypad[j][i] >> 12; + if(dev) { + dev--; + bool ok = false; + + if(sdlDevices) { + if(dev < sdlNumDevices) { + if(sdlDevices[dev] == NULL) { + sdlDevices[dev] = SDL_JoystickOpen(dev); + } + + ok = sdlCheckJoyKey(joypad[j][i]); + } else + ok = false; + } + + if(!ok) + joypad[j][i] = defaultJoypad[i]; + else + usesJoy = true; + } + } + } + + for(i = 0; i < 4; i++) { + int dev = motion[i] >> 12; + if(dev) { + dev--; + bool ok = false; + + if(sdlDevices) { + if(dev < sdlNumDevices) { + if(sdlDevices[dev] == NULL) { + sdlDevices[dev] = SDL_JoystickOpen(dev); + } + + ok = sdlCheckJoyKey(motion[i]); + } else + ok = false; + } + + if(!ok) + motion[i] = defaultMotion[i]; + else + usesJoy = true; + } + } + + if(usesJoy) + SDL_JoystickEventState(SDL_ENABLE); +} + +void sdlPollEvents() +{ + SDL_Event event; + while(SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: + emulating = 0; + break; + case SDL_ACTIVEEVENT: + if(pauseWhenInactive && (event.active.state & SDL_APPINPUTFOCUS)) { + active = event.active.gain; + if(active) { + if(!paused) { + if(emulating) + soundResume(); + } + } else { + wasPaused = true; + if(pauseWhenInactive) { + if(emulating) + soundPause(); + } + + memset(delta,255,sizeof(delta)); + } + } + break; + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + if(fullscreen) { + SDL_ShowCursor(SDL_ENABLE); + mouseCounter = 120; + } + break; + case SDL_JOYHATMOTION: + sdlUpdateJoyHat(event.jhat.which, + event.jhat.hat, + event.jhat.value); + break; + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + sdlUpdateJoyButton(event.jbutton.which, + event.jbutton.button, + event.jbutton.state == SDL_PRESSED); + break; + case SDL_JOYAXISMOTION: + sdlUpdateJoyAxis(event.jaxis.which, + event.jaxis.axis, + event.jaxis.value); + break; + case SDL_KEYDOWN: + sdlUpdateKey(event.key.keysym.sym, true); + break; + case SDL_KEYUP: + switch(event.key.keysym.sym) { + case SDLK_r: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + if(emulating) { + theEmulator.emuReset(true); + + systemScreenMessage("Reset"); + } + } + break; + case SDLK_b: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + if(emulating && theEmulator.emuReadMemState && rewindMemory + && rewindCount) { + rewindPos = --rewindPos & 7; + theEmulator.emuReadMemState(&rewindMemory[REWIND_SIZE*rewindPos], + REWIND_SIZE); + rewindCount--; + rewindCounter = 0; + systemScreenMessage("Rewind"); + } + } + break; + case SDLK_p: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + paused = !paused; + SDL_PauseAudio(paused); + if(paused) + wasPaused = true; + } + break; + case SDLK_ESCAPE: + emulating = 0; + break; + case SDLK_f: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + int flags = 0; + fullscreen = !fullscreen; + if(fullscreen) + flags |= SDL_FULLSCREEN; + SDL_SetVideoMode(destWidth, destHeight, systemColorDepth, flags); + // if(SDL_WM_ToggleFullScreen(surface)) + // fullscreen = !fullscreen; + } + break; + case SDLK_F11: + if(dbgMain != debuggerMain) { + if(armState) { + armNextPC -= 4; + reg[15].I -= 4; + } else { + armNextPC -= 2; + reg[15].I -= 2; + } + } + debugger = true; + break; + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + case SDLK_F9: + case SDLK_F10: + if(!(event.key.keysym.mod & MOD_NOSHIFT) && + (event.key.keysym.mod & KMOD_SHIFT)) { + sdlWriteState(event.key.keysym.sym-SDLK_F1); + } else if(!(event.key.keysym.mod & MOD_KEYS)) { + sdlReadState(event.key.keysym.sym-SDLK_F1); + } + break; + case SDLK_1: + case SDLK_2: + case SDLK_3: + case SDLK_4: + if(!(event.key.keysym.mod & MOD_NOALT) && + (event.key.keysym.mod & KMOD_ALT)) { + char *disableMessages[4] = + { "autofire A disabled", + "autofire B disabled", + "autofire R disabled", + "autofire L disabled"}; + char *enableMessages[4] = + { "autofire A", + "autofire B", + "autofire R", + "autofire L"}; + int mask = 1 << (event.key.keysym.sym - SDLK_1); + if(event.key.keysym.sym > SDLK_2) + mask <<= 6; + if(autoFire & mask) { + autoFire &= ~mask; + systemScreenMessage(disableMessages[event.key.keysym.sym - SDLK_1]); + } else { + autoFire |= mask; + systemScreenMessage(enableMessages[event.key.keysym.sym - SDLK_1]); + } + } if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + int mask = 0x0100 << (event.key.keysym.sym - SDLK_1); + layerSettings ^= mask; + layerEnable = DISPCNT & layerSettings; + CPUUpdateRenderBuffers(false); + } + break; + case SDLK_5: + case SDLK_6: + case SDLK_7: + case SDLK_8: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + int mask = 0x0100 << (event.key.keysym.sym - SDLK_1); + layerSettings ^= mask; + layerEnable = DISPCNT & layerSettings; + } + break; + case SDLK_n: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + if(paused) + paused = false; + pauseNextFrame = true; + } + break; + default: + break; + } + sdlUpdateKey(event.key.keysym.sym, false); + break; + } + } +} + +void usage(char *cmd) +{ + printf("%s [option ...] file\n", cmd); + printf("\ +\n\ +Options:\n\ + -1, --video-1x 1x\n\ + -2, --video-2x 2x\n\ + -3, --video-3x 3x\n\ + -4, --video-4x 4x\n\ + -F, --fullscreen Full screen\n\ + -G, --gdb=PROTOCOL GNU Remote Stub mode:\n\ + tcp - use TCP at port 55555\n\ + tcp:PORT - use TCP at port PORT\n\ + pipe - use pipe transport\n\ + -N, --no-debug Don't parse debug information\n\ + -S, --flash-size=SIZE Set the Flash size\n\ + --flash-64k 0 - 64K Flash\n\ + --flash-128k 1 - 128K Flash\n\ + -T, --throttle=THROTTLE Set the desired throttle (5...1000)\n\ + -Y, --yuv=TYPE Use YUV overlay for drawing:\n\ + 0 - YV12\n\ + 1 - UYVY\n\ + 2 - YVYU\n\ + 3 - YUY2\n\ + 4 - IYUV\n\ + -b, --bios=BIOS Use given bios file\n\ + -c, --config=FILE Read the given configuration file\n\ + -d, --debug Enter debugger\n\ + -f, --filter=FILTER Select filter:\n\ + --filter-normal 0 - normal mode\n\ + --filter-tv-mode 1 - TV Mode\n\ + --filter-2xsai 2 - 2xSaI\n\ + --filter-super-2xsai 3 - Super 2xSaI\n\ + --filter-super-eagle 4 - Super Eagle\n\ + --filter-pixelate 5 - Pixelate\n\ + --filter-motion-blur 6 - Motion Blur\n\ + --filter-advmame 7 - AdvanceMAME Scale2x\n\ + --filter-simple2x 8 - Simple2x\n\ + --filter-bilinear 9 - Bilinear\n\ + --filter-bilinear+ 10 - Bilinear Plus\n\ + --filter-scanlines 11 - Scanlines\n\ + --filter-hq2x 12 - hq2x\n\ + --filter-lq2x 13 - lq2x\n\ + -h, --help Print this help\n\ + -i, --ips=PATCH Apply given IPS patch\n\ + -P, --profile=[HERTZ] Enable profiling\n\ + -s, --frameskip=FRAMESKIP Set frame skip (0...9)\n\ +"); + printf("\ + -t, --save-type=TYPE Set the available save type\n\ + --save-auto 0 - Automatic (EEPROM, SRAM, FLASH)\n\ + --save-eeprom 1 - EEPROM\n\ + --save-sram 2 - SRAM\n\ + --save-flash 3 - FLASH\n\ + --save-sensor 4 - EEPROM+Sensor\n\ + --save-none 5 - NONE\n\ + -v, --verbose=VERBOSE Set verbose logging (trace.log)\n\ + 1 - SWI\n\ + 2 - Unaligned memory access\n\ + 4 - Illegal memory write\n\ + 8 - Illegal memory read\n\ + 16 - DMA 0\n\ + 32 - DMA 1\n\ + 64 - DMA 2\n\ + 128 - DMA 3\n\ + 256 - Undefined instruction\n\ + 512 - AGBPrint messages\n\ +\n\ +Long options only:\n\ + --agb-print Enable AGBPrint support\n\ + --auto-frameskip Enable auto frameskipping\n\ + --ifb-none No interframe blending\n\ + --ifb-motion-blur Interframe motion blur\n\ + --ifb-smart Smart interframe blending\n\ + --no-agb-print Disable AGBPrint support\n\ + --no-auto-frameskip Disable auto frameskipping\n\ + --no-ips Do not apply IPS patch\n\ + --no-mmx Disable MMX support\n\ + --no-pause-when-inactive Don't pause when inactive\n\ + --no-rtc Disable RTC support\n\ + --no-show-speed Don't show emulation speed\n\ + --no-throttle Disable thrrotle\n\ + --pause-when-inactive Pause when inactive\n\ + --rtc Enable RTC support\n\ + --show-speed-normal Show emulation speed\n\ + --show-speed-detailed Show detailed speed data\n\ +"); + printf("\ + -r, --recordmovie=filename Start recording input movie\n\ + -p, --playmovie=filename Play input movie non-read-only\n\ + -w, --watchmovie=filename Play input movie in read-only mode\n\ +"); +} + +static char *szFile; + +void file_run() +{ + utilGetBaseName(szFile, filename); + char *p = strrchr(filename, '.'); + + if(p) + *p = 0; + + if(ipsname[0] == 0) + sprintf(ipsname, "%s.ips", filename); + + bool failed = false; + + IMAGE_TYPE type = utilFindType(szFile); + + if(type == IMAGE_UNKNOWN) { + systemMessage(0, "Unknown file type %s", szFile); + exit(-1); + } + systemCartridgeType = (int)type; + + if(type == IMAGE_GB) { + failed = !gbLoadRom(szFile); + if(!failed) { + systemCartridgeType = 1; + theEmulator = GBSystem; + if(sdlAutoIPS) { + int size = gbRomSize; + utilApplyIPS(ipsname, &gbRom, &size); + if(size != gbRomSize) { + extern bool gbUpdateSizes(); + gbUpdateSizes(); + gbReset(); + } + } + } + } else if(type == IMAGE_GBA) { + int size = CPULoadRom(szFile); + failed = (size == 0); + if(!failed) { + // if(cpuEnhancedDetection && cpuSaveType == 0) { + // utilGBAFindSave(rom, size); + // } + + sdlApplyPerImagePreferences(); + + systemCartridgeType = 0; + theEmulator = GBASystem; + + /* disabled due to problems + if(removeIntros && rom != NULL) { + WRITE32LE(&rom[0], 0xea00002e); + } + */ + + //CPUInit(biosFileName, useBios); + CPUInit(); + CPUReset(); + if(sdlAutoIPS) { + int size = 0x2000000; + utilApplyIPS(ipsname, &rom, &size); + if(size != 0x2000000) { + CPUReset(); + } + } + } + } + + if(failed) { + systemMessage(0, "Failed to load file %s", szFile); + exit(-1); + } + + emulating = 1; + renderedFrames = 0; + } + +int main(int argc, char **argv) +{ + fprintf(stderr, "VisualBoyAdvance version %s [SDL]\n", VERSION); + + arg0 = argv[0]; + + captureDir[0] = 0; + saveDir[0] = 0; + batteryDir[0] = 0; + ipsname[0] = 0; + + int op = -1; + + frameSkip = 2; + gbBorderOn = 0; + + parseDebug = true; + + sdlReadPreferences(); + + sdlPrintUsage = 0; + + while((op = getopt_long(argc, + argv, + "FNT:Y:G:D:b:c:df:hi:p::s:t:v:1234", + sdlOptions, + NULL)) != -1) { + switch(op) { + case 0: + // long option already processed by getopt_long + break; + case 'b': + useBios = true; + if(optarg == NULL) { + fprintf(stderr, "Missing BIOS file name\n"); + exit(-1); + } + strcpy(biosFileName, optarg); + break; + case 'c': + { + if(optarg == NULL) { + fprintf(stderr, "Missing config file name\n"); + exit(-1); + } + FILE *f = fopen(optarg, "r"); + if(f == NULL) { + fprintf(stderr, "File not found %s\n", optarg); + exit(-1); + } + sdlReadPreferences(f); + fclose(f); + } + break; + case 'd': + debugger = true; + break; + case 'h': + sdlPrintUsage = 1; + break; + case 'i': + if(optarg == NULL) { + fprintf(stderr, "Missing IPS name\n"); + exit(-1); + strcpy(ipsname, optarg); + } + break; + case 'Y': + yuv = true; + if(optarg) { + yuvType = atoi(optarg); + switch(yuvType) { + case 0: + yuvType = SDL_YV12_OVERLAY; + break; + case 1: + yuvType = SDL_UYVY_OVERLAY; + break; + case 2: + yuvType = SDL_YVYU_OVERLAY; + break; + case 3: + yuvType = SDL_YUY2_OVERLAY; + break; + case 4: + yuvType = SDL_IYUV_OVERLAY; + break; + default: + yuvType = SDL_YV12_OVERLAY; + } + } else + yuvType = SDL_YV12_OVERLAY; + break; + case 'G': + dbgMain = remoteStubMain; + dbgSignal = remoteStubSignal; + dbgOutput = remoteOutput; + debugger = true; + debuggerStub = true; + if(optarg) { + char *s = optarg; + if(strncmp(s,"tcp:", 4) == 0) { + s+=4; + int port = atoi(s); + remoteSetProtocol(0); + remoteSetPort(port); + } else if(strcmp(s,"tcp") == 0) { + remoteSetProtocol(0); + } else if(strcmp(s, "pipe") == 0) { + remoteSetProtocol(1); + } else { + fprintf(stderr, "Unknown protocol %s\n", s); + exit(-1); + } + } else { + remoteSetProtocol(0); + } + break; + case 'N': + parseDebug = false; + break; + case 'D': + if(optarg) { + systemDebug = atoi(optarg); + } else { + systemDebug = 1; + } + break; + case 'F': + fullscreen = 1; + mouseCounter = 120; + break; + case 'f': + if(optarg) { + filter = atoi(optarg); + } else { + filter = 0; + } + break; + + case 'r': + if(optarg == NULL) { + fprintf(stderr, "ERROR: --recordMovie ('r') needs movie filename as option\n"); + exit(-1); + } + strcpy(movieFileName, optarg); + useMovie = 1; + break; + case 'p': // play without read-only (editable) + fprintf (stderr, "-p got called!\n"); + if(optarg == NULL) { + fprintf(stderr, "ERROR: --playMovie ('p') needs movie filename as option\n"); + exit(-1); + } + strcpy(movieFileName, optarg); + useMovie = 2; + break; + case 'w': // play with read-only + fprintf (stderr, "-w got called!\n"); + if(optarg == NULL) { + fprintf(stderr, "ERROR: --watchMovie ('w') needs movie filename as option\n"); + exit(-1); + } + strcpy(movieFileName, optarg); + useMovie = 3; + break; + + case 'P': +#ifdef PROFILING + if(optarg) { + cpuEnableProfiling(atoi(optarg)); + } else + cpuEnableProfiling(100); +#endif + break; + case 'S': + sdlFlashSize = atoi(optarg); + if(sdlFlashSize < 0 || sdlFlashSize > 1) + sdlFlashSize = 0; + break; + case 's': + if(optarg) { + int a = atoi(optarg); + if(a >= 0 && a <= 9) { + gbFrameSkip = a; + frameSkip = a; + } + } else { + frameSkip = 2; + gbFrameSkip = 0; + } + break; + case 't': + if(optarg) { + int a = atoi(optarg); + if(a < 0 || a > 5) + a = 0; + cpuSaveType = a; + } + break; + case 'T': + if(optarg) { + int t = atoi(optarg); + throttle = t; + } + break; + case 'v': + if(optarg) { + systemVerbose = atoi(optarg); + } else + systemVerbose = 0; + break; + case '1': + sizeOption = 0; + break; + case '2': + sizeOption = 1; + break; + case '3': + sizeOption = 2; + break; + case '4': + sizeOption = 3; + break; + case '?': + sdlPrintUsage = 1; + break; + } + } + + if(sdlPrintUsage) { + usage(argv[0]); + exit(-1); + } + +#ifdef MMX + if(disableMMX) + cpu_mmx = 0; +#endif + + if(rewindTimer) + rewindMemory = (char *)malloc(8*REWIND_SIZE); + + if(sdlFlashSize == 0) + flashSetSize(0x10000); + else + flashSetSize(0x20000); + + rtcEnable(sdlRtcEnable ? true : false); + agbPrintEnable(sdlAgbPrint ? true : false); + + if(!debuggerStub) { + if(optind >= argc) { + systemMessage(0,"Missing image name"); + usage(argv[0]); + exit(-1); + } + } + + if(filter) { + sizeOption = 1; + } + + for(int i = 0; i < 24;) { + systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10); + systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10); + systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10); + systemGbPalette[i++] = 0; + } + + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + + if(optind < argc) + { + szFile = argv[optind]; + file_run(); + } + else + { + systemCartridgeType = 0; + strcpy(filename, "gnu_stub"); + rom = (u8 *)malloc(0x2000000); + workRAM = (u8 *)calloc(1, 0x40000); + bios = (u8 *)calloc(1,0x4000); + internalRAM = (u8 *)calloc(1,0x8000); + paletteRAM = (u8 *)calloc(1,0x400); + vram = (u8 *)calloc(1, 0x20000); + oam = (u8 *)calloc(1, 0x400); + pix = (u8 *)calloc(1, 4 * 240 * 160); + ioMem = (u8 *)calloc(1, 0x400); + + theEmulator = GBASystem; + + //CPUInit(biosFileName, useBios); + CPUInit(); + CPUReset(); + } + + if(debuggerStub) + remoteInit(); + + int flags = SDL_INIT_VIDEO|SDL_INIT_AUDIO| + SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE; + + if(soundOffFlag) + flags ^= SDL_INIT_AUDIO; + + if(SDL_Init(flags)) { + systemMessage(0, "Failed to init SDL: %s", SDL_GetError()); + exit(-1); + } + + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK)) { + systemMessage(0, "Failed to init joystick support: %s", SDL_GetError()); + } + + sdlCheckKeys(); + + if(systemCartridgeType == 0) { + srcWidth = 240; + srcHeight = 160; + systemFrameSkip = frameSkip; + } else if (systemCartridgeType == 1) { + if(gbBorderOn) { + srcWidth = 256; + srcHeight = 224; + gbBorderLineSkip = 256; + gbBorderColumnSkip = 48; + gbBorderRowSkip = 40; + } else { + srcWidth = 160; + srcHeight = 144; + gbBorderLineSkip = 160; + gbBorderColumnSkip = 0; + gbBorderRowSkip = 0; + } + systemFrameSkip = gbFrameSkip; + } else { + srcWidth = 320; + srcHeight = 240; + } + + destWidth = (sizeOption+1)*srcWidth; + destHeight = (sizeOption+1)*srcHeight; + + surface = SDL_SetVideoMode(destWidth, destHeight, 16, + SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF| + (fullscreen ? SDL_FULLSCREEN : 0)); + + if(surface == NULL) { + systemMessage(0, "Failed to set video mode"); + SDL_Quit(); + exit(-1); + } + + systemRedShift = sdlCalculateShift(surface->format->Rmask); + systemGreenShift = sdlCalculateShift(surface->format->Gmask); + systemBlueShift = sdlCalculateShift(surface->format->Bmask); + + systemColorDepth = surface->format->BitsPerPixel; + if(systemColorDepth == 15) + systemColorDepth = 16; + + if(yuv) { + Init_Overlay(surface, yuvType); + systemColorDepth = 32; + systemRedShift = 3; + systemGreenShift = 11; + systemBlueShift = 19; + } + + if(systemColorDepth != 16 && systemColorDepth != 24 && + systemColorDepth != 32) { + fprintf(stderr,"Unsupported color depth '%d'.\nOnly 16, 24 and 32 bit color depths are supported\n", systemColorDepth); + exit(-1); + } + +#ifndef C_CORE + sdlMakeStretcher(srcWidth); +#else + switch(systemColorDepth) { + case 16: + sdlStretcher = sdlStretcher16[sizeOption]; + break; + case 24: + sdlStretcher = sdlStretcher24[sizeOption]; + break; + case 32: + sdlStretcher = sdlStretcher32[sizeOption]; + break; + default: + fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth); + exit(-1); + } +#endif + + fprintf(stderr,"Color depth: %d\n", systemColorDepth); + + if(systemColorDepth == 16) { + if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) { + Init_2xSaI(565); + RGB_LOW_BITS_MASK = 0x821; + } else { + Init_2xSaI(555); + RGB_LOW_BITS_MASK = 0x421; + } + if(systemCartridgeType == 2) { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) | + (((i & 0x7c0) >> 6) << systemGreenShift) | + (((i & 0xf800) >> 11) << systemRedShift); + } + } else { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + } + srcPitch = srcWidth * 2+4; + } else { + if(systemColorDepth != 32) + filterFunction = NULL; + RGB_LOW_BITS_MASK = 0x010101; + if(systemColorDepth == 32) { + Init_2xSaI(32); + } + for(int i = 0; i < 0x10000; i++) { + systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + if(systemColorDepth == 32) + srcPitch = srcWidth*4 + 4; + else + srcPitch = srcWidth*3; + } + + if(systemColorDepth != 32) { + switch(filter) { + case 0: + filterFunction = NULL; + break; + case 1: + filterFunction = ScanlinesTV; + break; + case 2: + filterFunction = _2xSaI; + break; + case 3: + filterFunction = Super2xSaI; + break; + case 4: + filterFunction = SuperEagle; + break; + case 5: + filterFunction = Pixelate2x16; + break; + case 6: + filterFunction = MotionBlur; + break; + case 7: + filterFunction = AdMame2x; + break; + case 8: + filterFunction = Simple2x16; + break; + case 9: + filterFunction = Bilinear; + break; + case 10: + filterFunction = BilinearPlus; + break; + case 11: + filterFunction = Scanlines; + break; + case 12: + filterFunction = hq2x; + break; + case 13: + filterFunction = lq2x; + break; + default: + filterFunction = NULL; + break; + } + } else { + switch(filter) { + case 0: + filterFunction = NULL; + break; + case 1: + filterFunction = ScanlinesTV32; + break; + case 2: + filterFunction = _2xSaI32; + break; + case 3: + filterFunction = Super2xSaI32; + break; + case 4: + filterFunction = SuperEagle32; + break; + case 5: + filterFunction = Pixelate2x32; + break; + case 6: + filterFunction = MotionBlur32; + break; + case 7: + filterFunction = AdMame2x32; + break; + case 8: + filterFunction = Simple2x32; + break; + case 9: + filterFunction = Bilinear32; + break; + case 10: + filterFunction = BilinearPlus32; + break; + case 11: + filterFunction = Scanlines32; + break; + case 12: + filterFunction = hq2x32; + break; + case 13: + filterFunction = lq2x32; + break; + default: + filterFunction = NULL; + break; + } + } + + if(systemColorDepth == 16) { + switch(ifbType) { + case 0: + default: + ifbFunction = NULL; + break; + case 1: + ifbFunction = MotionBlurIB; + break; + case 2: + ifbFunction = SmartIB; + break; + } + } else if(systemColorDepth == 32) { + switch(ifbType) { + case 0: + default: + ifbFunction = NULL; + break; + case 1: + ifbFunction = MotionBlurIB32; + break; + case 2: + ifbFunction = SmartIB32; + break; + } + } else + ifbFunction = NULL; + + if(delta == NULL) { + delta = (u8*)malloc(322*242*4); + memset(delta, 255, 322*242*4); + } + + if(!soundOffFlag) + soundInit(); + + autoFrameSkipLastTime = throttleLastTime = systemGetClock(); + + switch(useMovie) + { + case 1: // --recordMovie + VBAMovieCreate(movieFileName, + /*authorInfo*/"", + /*startFlags*/0, + /*controllerFlags*/MOVIE_CONTROLLER(0), + /*typeFlags*/(systemCartridgeType==IMAGE_GBA)?(MOVIE_TYPE_GBA):(GBC_CAPABLE?MOVIE_TYPE_GBC:MOVIE_TYPE_SGB)); + break; + case 2: // --playMovie + VBAMovieOpen(movieFileName, false); + break; + case 3: // --watchMovie + VBAMovieOpen(movieFileName, true); + break; + default: + sdlReadBattery(); + break; + } + SDL_WM_SetCaption("VisualBoyAdvance", NULL); + + char *moviefile = getenv("AUTODEMO"); +// fprintf (stderr, "Checking for AUTODEMO...\n"); + if (moviefile) + { +// fprintf (stderr, "I got a filename OMG!\nCalling VBAMovieOpen...\n"); + VBAMovieOpen(moviefile, true); + } + + while(emulating) { + if(!paused && active) { + if(debugger && theEmulator.emuHasDebugger) + dbgMain(); + else { + theEmulator.emuMain(theEmulator.emuCount); + if(rewindSaveNeeded && rewindMemory && theEmulator.emuWriteMemState) { + rewindCount++; + if(rewindCount > 8) + rewindCount = 8; + if(theEmulator.emuWriteMemState && + theEmulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE], + REWIND_SIZE)) { + rewindPos = ++rewindPos & 7; + if(rewindCount == 8) + rewindTopPos = ++rewindTopPos & 7; + } + } + + rewindSaveNeeded = false; + } + } else { + SDL_Delay(500); + } + sdlPollEvents(); + if(mouseCounter) { + mouseCounter--; + if(mouseCounter == 0) + SDL_ShowCursor(SDL_DISABLE); + } + } + + emulating = 0; + fprintf(stderr,"Shutting down\n"); + remoteCleanUp(); + soundShutdown(); + + if(gbRom != NULL || rom != NULL) { + sdlWriteBattery(); + theEmulator.emuCleanUp(); + } + + if(delta) { + free(delta); + delta = NULL; + } + + SDL_Quit(); + return 0; +} + +void systemMessage(int num, const char *msg, ...) +{ + char buffer[2048]; + va_list valist; + + va_start(valist, msg); + vsprintf(buffer, msg, valist); + + fprintf(stderr, "%s\n", buffer); + va_end(valist); +} + +//On WIN32, this function messages requesting +//the window to be redrawn. Can this be ignored here? +void systemRefreshScreen(){} + +void systemRenderFrame() +{ + renderedFrames++; + VBAUpdateFrameCountDisplay(); + VBAUpdateButtonPressDisplay(); + + if(yuv) { + Draw_Overlay(surface, sizeOption+1); + return; + } + + SDL_LockSurface(surface); + + for(int slot = 0 ; slot < 8 ; slot++) + { + if(screenMessage[slot]) { + if(systemCartridgeType == 1 && gbBorderOn) { + gbSgbRenderBorder(); + } + if(((systemGetClock() - screenMessageTime[slot]) < screenMessageDuration[slot]) && + !disableStatusMessages) { + drawText(pix, srcPitch, 10, srcHeight - 20*(slot+1), + screenMessageBuffer[slot]); + } else { + screenMessage[slot] = false; + } + } + } + + if(ifbFunction) { + if(systemColorDepth == 16) + ifbFunction(pix+destWidth+4, destWidth+4, srcWidth, srcHeight); + else + ifbFunction(pix+destWidth*2+4, destWidth*2+4, srcWidth, srcHeight); + } + + if(filterFunction) { + if(systemColorDepth == 16) + filterFunction(pix+destWidth+4,destWidth+4, delta, + (u8*)surface->pixels,surface->pitch, + srcWidth, + srcHeight); + else + filterFunction(pix+destWidth*2+4, + destWidth*2+4, + delta, + (u8*)surface->pixels, + surface->pitch, + srcWidth, + srcHeight); + } else { + int destPitch = surface->pitch; + u8 *src = pix; + u8 *dest = (u8*)surface->pixels; + int i; + u32 *stretcher = (u32 *)sdlStretcher; + if(systemColorDepth == 16) + src += srcPitch; + int option = sizeOption; + if(yuv) + option = 0; + switch(sizeOption) { + case 0: + for(i = 0; i < srcHeight; i++) { + SDL_CALL_STRETCHER; + src += srcPitch; + dest += destPitch; + } + break; + case 1: + for(i = 0; i < srcHeight; i++) { + SDL_CALL_STRETCHER; + dest += destPitch; + SDL_CALL_STRETCHER; + src += srcPitch; + dest += destPitch; + } + break; + case 2: + for(i = 0; i < srcHeight; i++) { + SDL_CALL_STRETCHER; + dest += destPitch; + SDL_CALL_STRETCHER; + dest += destPitch; + SDL_CALL_STRETCHER; + src += srcPitch; + dest += destPitch; + } + break; + case 3: + for(i = 0; i < srcHeight; i++) { + SDL_CALL_STRETCHER; + dest += destPitch; + SDL_CALL_STRETCHER; + dest += destPitch; + SDL_CALL_STRETCHER; + dest += destPitch; + SDL_CALL_STRETCHER; + src += srcPitch; + dest += destPitch; + } + break; + } + } + + if(showSpeed && fullscreen) { + char buffer[50]; + if(showSpeed == 1) + sprintf(buffer, "%d%%", systemSpeed); + else + sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed, + systemFrameSkip, + showRenderedFrames); + if(showSpeedTransparent) + drawTextTransp((u8*)surface->pixels, + surface->pitch, + 10, + surface->h-20, + buffer); + else + drawText((u8*)surface->pixels, + surface->pitch, + 10, + surface->h-20, + buffer); + } + + SDL_UnlockSurface(surface); + // SDL_UpdateRect(surface, 0, 0, destWidth, destHeight); + SDL_Flip(surface); +} + +bool systemReadJoypads() +{ + return true; +} + +// Kludge to make Lua call the right function. +u32 systemGetOriginalJoypad(int which, bool sensor){ + return systemGetJoypad(which,sensor); +} + +u32 systemGetJoypad(int which, bool sensor) +{ + sensorOn = sensor; + if(which < 0 || which > 3) + which = sdlDefaultJoypad; + + //VBAMovieUpdate(which); + //VBAMovieUpdateState(); + u32 res = 0; + + //----------------------------// + if (VBAMoviePlaying()){ + // VBAMovieRead() overwrites currentButtons[i] + VBAMovieRead(which, sensor); + res = currentButtons[which]; + return res; + } + //---------------------------// + //Temporary implementation, not sure if it's correct --Felipe + + /* + if(sdlButtons[which][KEY_BUTTON_A]) + res |= BUTTON_MASK_A; + if(sdlButtons[which][KEY_BUTTON_B]) + res |= BUTTON_MASK_B; + if(sdlButtons[which][KEY_BUTTON_SELECT]) + res |= BUTTON_MASK_SELECT; + if(sdlButtons[which][KEY_BUTTON_START]) + res |= BUTTON_MASK_START; + if(sdlButtons[which][KEY_RIGHT]) + res |= BUTTON_MASK_RIGHT; + if(sdlButtons[which][KEY_LEFT]) + res |= BUTTON_MASK_LEFT; + if(sdlButtons[which][KEY_UP]) + res |= BUTTON_MASK_UP; + if(sdlButtons[which][KEY_DOWN]) + res |= BUTTON_MASK_DOWN; + if(sdlButtons[which][KEY_BUTTON_R]) + res |= BUTTON_MASK_R; + if(sdlButtons[which][KEY_BUTTON_L]) + res |= BUTTON_MASK_L; + */ +/* + // disallow L+R or U+D of being pressed at the same time + if((res & 48) == 48) + res &= ~16; + if((res & 192) == 192) + res &= ~128; +*/ +/* + if(sdlbuttons[which][KEY_BUTTON_SPEED]) + res |= 1024; + if(sdlButtons[which][KEY_BUTTON_CAPTURE]) + res |= 2048; +*/ + res = currentButtons[which]; + + if(autoFire) { + res &= (~autoFire); + if(autoFireToggle) + res |= autoFire; + autoFireToggle = !autoFireToggle; + } + + //if (res) fprintf(stdout,"%x\n",res); + + return res; +} + +void systemSetJoypad(int which, u32 buttons) +{ + if(which < 0 || which > 3) + which = sdlDefaultJoypad; +/* + sdlButtons[which][KEY_BUTTON_A] = (buttons & 1) != 0; + sdlButtons[which][KEY_BUTTON_B] = (buttons & 2) != 0; + sdlButtons[which][KEY_BUTTON_SELECT] = (buttons & 4) != 0; + sdlButtons[which][KEY_BUTTON_START] = (buttons & 8) != 0; + sdlButtons[which][KEY_RIGHT] = (buttons & 16) != 0; + sdlButtons[which][KEY_LEFT] = (buttons & 32) != 0; + sdlButtons[which][KEY_UP] = (buttons & 64) != 0; + sdlButtons[which][KEY_DOWN] = (buttons & 128) != 0; + sdlButtons[which][KEY_BUTTON_R] = (buttons & 256) != 0; + sdlButtons[which][KEY_BUTTON_L] = (buttons & 512) != 0; +*/ + currentButtons[which]= buttons & 0x3ff; +} + +void systemClearJoypads() +{ + for (int i = 0; i < 4; ++i) + currentButtons[i] = 0; + + //lastKeys = 0; +} + +void systemSetTitle(const char *title) +{ + SDL_WM_SetCaption(title, NULL); +} + +void systemShowSpeed(int speed) +{ + systemSpeed = speed; + + showRenderedFrames = renderedFrames; + renderedFrames = 0; + + if(!fullscreen && showSpeed) { + char buffer[80]; + if(showSpeed == 1) + sprintf(buffer, "VisualBoyAdvance-%3d%%", systemSpeed); + else + sprintf(buffer, "VisualBoyAdvance-%3d%%(%d, %d fps)", systemSpeed, + systemFrameSkip, + showRenderedFrames); + + systemSetTitle(buffer); + } +} + +// FIXME: the timing +void systemFrame(/*int rate*/) //Looking at System.cpp, it looks like rate should be 600 +{ + u32 time = systemGetClock(); + if(!wasPaused && autoFrameSkip && !throttle) { + u32 diff = time - autoFrameSkipLastTime; + int speed = 100; + + if(diff) + speed = (1000000/600)/diff; + + if(speed >= 98) { + frameskipadjust++; + + if(frameskipadjust >= 3) { + frameskipadjust=0; + if(systemFrameSkip > 0) + systemFrameSkip--; + } + } else { + if(speed < 80) + frameskipadjust -= (90 - speed)/5; + else if(systemFrameSkip < 9) + frameskipadjust--; + + if(frameskipadjust <= -2) { + frameskipadjust += 2; + if(systemFrameSkip < 9) + systemFrameSkip++; + } + } + } + if(!wasPaused && throttle) { + /*if(!speedup) { + u32 diff = time - throttleLastTime; + + int target = (1000000.0/(600*throttle)); + int d = (target - diff); + + if(d > 0) { + SDL_Delay(d); + } + } + throttleLastTime = systemGetClock(); + */ + } + if(rewindMemory) { + if(++rewindCounter >= rewindTimer) { + rewindSaveNeeded = true; + rewindCounter = 0; + } + } + + if(systemSaveUpdateCounter) { + if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) { + sdlWriteBattery(); + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + } + } + + wasPaused = false; + autoFrameSkipLastTime = time; +} + +int systemFramesToSkip(){ + return systemFrameSkip; +} + +int systemScreenCapture(int a) +{ + char buffer[2048]; + + if(captureFormat) { + if(captureDir[0]) + sprintf(buffer, "%s/%s%02d.bmp", captureDir, sdlGetFilename(filename), a); + else + sprintf(buffer, "%s%02d.bmp", filename, a); + + theEmulator.emuWriteBMP(buffer); + } else { + if(captureDir[0]) + sprintf(buffer, "%s/%s%02d.png", captureDir, sdlGetFilename(filename), a); + else + sprintf(buffer, "%s%02d.png", filename, a); + theEmulator.emuWritePNG(buffer); + } + + systemScreenMessage("Screen capture"); + return a; +} + +void soundCallback(void *,u8 *stream,int len){} + +void systemSoundWriteToBuffer(){ + soundDriver->write(soundFinalWave, soundBufferLen); +} + +void systemSoundClearBuffer() +{ + SDL_mutexP(mutex); + memset(sdlBuffer,0,soundBufferTotalLen); + sdlSoundLen=0; + printf("Hi\n"); + SDL_mutexV(mutex); +} + +bool systemSoundInit(){ + systemSoundShutdown(); + soundDriver = new SoundSDL(); + if ( !soundDriver ) + return false; + + if (!soundDriver->init()) //<-- sound sample rate + return false; + + if (!(soundDriver->setThrottle(throttle))){ + fprintf(stderr,"Failed to set desired throttle, defaulting to 100 %%.\n"); + if (!soundDriver->setThrottle(100)) return false; + } + soundPaused = true; + systemSoundOn = true; + return true; +} + +void systemSoundShutdown(){ + if (soundDriver) + { + delete soundDriver; + soundDriver = 0; + } +} + +void systemSoundPause() +{ + SDL_PauseAudio(1); +} + +void systemSoundResume() +{ + SDL_PauseAudio(0); +} + +void systemSoundReset() +{ +} + +u32 systemGetClock() +{ + return SDL_GetTicks(); +} + +void systemUpdateMotionSensor() +{ + if(sdlMotionButtons[KEY_LEFT]) { + sensorX += 3; + if(sensorX > 2197) + sensorX = 2197; + if(sensorX < 2047) + sensorX = 2057; + } else if(sdlMotionButtons[KEY_RIGHT]) { + sensorX -= 3; + if(sensorX < 1897) + sensorX = 1897; + if(sensorX > 2047) + sensorX = 2037; + } else if(sensorX > 2047) { + sensorX -= 2; + if(sensorX < 2047) + sensorX = 2047; + } else { + sensorX += 2; + if(sensorX > 2047) + sensorX = 2047; + } + + if(sdlMotionButtons[KEY_UP]) { + sensorY += 3; + if(sensorY > 2197) + sensorY = 2197; + if(sensorY < 2047) + sensorY = 2057; + } else if(sdlMotionButtons[KEY_DOWN]) { + sensorY -= 3; + if(sensorY < 1897) + sensorY = 1897; + if(sensorY > 2047) + sensorY = 2037; + } else if(sensorY > 2047) { + sensorY -= 2; + if(sensorY < 2047) + sensorY = 2047; + } else { + sensorY += 2; + if(sensorY > 2047) + sensorY = 2047; + } +} + +void systemResetSensor() +{ + sensorX = sensorY = INITIAL_SENSOR_VALUE; +} + +int systemGetSensorX() +{ + return sensorX; +} + +int systemGetSensorY() +{ + return sensorY; +} + +void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast) +{ +} + +void systemScreenMessage(const char *msg, int slot, int duration, const char *colorList) +{ + screenMessage[slot] = true; + screenMessageTime[slot] = systemGetClock(); + screenMessageDuration[slot] = duration; + if(strlen(msg) > 20) { + strncpy(screenMessageBuffer[slot], msg, 20); + screenMessageBuffer[slot][20] = 0; + } else + strcpy(screenMessageBuffer[slot], msg); +} + +bool systemSoundCanChangeQuality() +{ + return false; +} + +bool systemSoundSetQuality(int quality) +{ + if (systemCartridgeType == 0) + soundSetQuality(quality); + else + gbSoundSetQuality(quality); + + return true; +} + +bool systemPauseOnFrame() +{ + if(pauseNextFrame) { + paused = true; + pauseNextFrame = false; + return true; + } + return false; +} + +// Code donated by Niels Wagenaar (BoycottAdvance) + +// GBA screensize. +#define GBA_WIDTH 240 +#define GBA_HEIGHT 160 + +void Init_Overlay(SDL_Surface *gbascreen, int overlaytype) +{ + + overlay = SDL_CreateYUVOverlay( GBA_WIDTH, + GBA_HEIGHT, + overlaytype, gbascreen); + fprintf(stderr, "Created %dx%dx%d %s %s overlay\n", + overlay->w,overlay->h,overlay->planes, + overlay->hw_overlay?"hardware":"software", + overlay->format==SDL_YV12_OVERLAY?"YV12": + overlay->format==SDL_IYUV_OVERLAY?"IYUV": + overlay->format==SDL_YUY2_OVERLAY?"YUY2": + overlay->format==SDL_UYVY_OVERLAY?"UYVY": + overlay->format==SDL_YVYU_OVERLAY?"YVYU": + "Unknown"); +} + +void Quit_Overlay(void) +{ + + SDL_FreeYUVOverlay(overlay); +} + +/* NOTE: These RGB conversion functions are not intended for speed, + only as examples. +*/ +inline void RGBtoYUV(Uint8 *rgb, int *yuv) +{ + yuv[0] = (int)((0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16); + yuv[1] = (int)(128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2])); + yuv[2] = (int)(128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2])); +} + +inline void ConvertRGBtoYV12(SDL_Overlay *o) +{ + int x,y; + int yuv[3]; + Uint8 *p,*op[3]; + + SDL_LockYUVOverlay(o); + + /* Black initialization */ + /* + memset(o->pixels[0],0,o->pitches[0]*o->h); + memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2)); + memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2)); + */ + + /* Convert */ + for(y=0; y<160 && yh; y++) { + p=(Uint8 *)pix+srcPitch*y; + op[0]=o->pixels[0]+o->pitches[0]*y; + op[1]=o->pixels[1]+o->pitches[1]*(y/2); + op[2]=o->pixels[2]+o->pitches[2]*(y/2); + for(x=0; x<240 && xw; x++) { + RGBtoYUV(p,yuv); + *(op[0]++)=yuv[0]; + if(x%2==0 && y%2==0) { + *(op[1]++)=yuv[2]; + *(op[2]++)=yuv[1]; + } + p+=4;//s->format->BytesPerPixel; + } + } + + SDL_UnlockYUVOverlay(o); +} + +inline void ConvertRGBtoIYUV(SDL_Overlay *o) +{ + int x,y; + int yuv[3]; + Uint8 *p,*op[3]; + + SDL_LockYUVOverlay(o); + + /* Black initialization */ + /* + memset(o->pixels[0],0,o->pitches[0]*o->h); + memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2)); + memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2)); + */ + + /* Convert */ + for(y=0; y<160 && yh; y++) { + p=(Uint8 *)pix+srcPitch*y; + op[0]=o->pixels[0]+o->pitches[0]*y; + op[1]=o->pixels[1]+o->pitches[1]*(y/2); + op[2]=o->pixels[2]+o->pitches[2]*(y/2); + for(x=0; x<240 && xw; x++) { + RGBtoYUV(p,yuv); + *(op[0]++)=yuv[0]; + if(x%2==0 && y%2==0) { + *(op[1]++)=yuv[1]; + *(op[2]++)=yuv[2]; + } + p+=4; //s->format->BytesPerPixel; + } + } + + SDL_UnlockYUVOverlay(o); +} + +inline void ConvertRGBtoUYVY(SDL_Overlay *o) +{ + int x,y; + int yuv[3]; + Uint8 *p,*op; + + SDL_LockYUVOverlay(o); + + for(y=0; y<160 && yh; y++) { + p=(Uint8 *)pix+srcPitch*y; + op=o->pixels[0]+o->pitches[0]*y; + for(x=0; x<240 && xw; x++) { + RGBtoYUV(p,yuv); + if(x%2==0) { + *(op++)=yuv[1]; + *(op++)=yuv[0]; + *(op++)=yuv[2]; + } else + *(op++)=yuv[0]; + + p+=4; //s->format->BytesPerPixel; + } + } + + SDL_UnlockYUVOverlay(o); +} + +inline void ConvertRGBtoYVYU(SDL_Overlay *o) +{ + int x,y; + int yuv[3]; + Uint8 *p,*op; + + SDL_LockYUVOverlay(o); + + for(y=0; y<160 && yh; y++) { + p=(Uint8 *)pix+srcPitch*y; + op=o->pixels[0]+o->pitches[0]*y; + for(x=0; x<240 && xw; x++) { + RGBtoYUV(p,yuv); + if(x%2==0) { + *(op++)=yuv[0]; + *(op++)=yuv[2]; + op[1]=yuv[1]; + } else { + *op=yuv[0]; + op+=2; + } + + p+=4; //s->format->BytesPerPixel; + } + } + + SDL_UnlockYUVOverlay(o); +} + +inline void ConvertRGBtoYUY2(SDL_Overlay *o) +{ + int x,y; + int yuv[3]; + Uint8 *p,*op; + + SDL_LockYUVOverlay(o); + + for(y=0; y<160 && yh; y++) { + p=(Uint8 *)pix+srcPitch*y; + op=o->pixels[0]+o->pitches[0]*y; + for(x=0; x<240 && xw; x++) { + RGBtoYUV(p,yuv); + if(x%2==0) { + *(op++)=yuv[0]; + *(op++)=yuv[1]; + op[1]=yuv[2]; + } else { + *op=yuv[0]; + op+=2; + } + + p+=4; //s->format->BytesPerPixel; + } + } + + SDL_UnlockYUVOverlay(o); +} + +inline void Convert32bit(SDL_Surface *display) +{ + switch(overlay->format) { + case SDL_YV12_OVERLAY: + ConvertRGBtoYV12(overlay); + break; + case SDL_UYVY_OVERLAY: + ConvertRGBtoUYVY(overlay); + break; + case SDL_YVYU_OVERLAY: + ConvertRGBtoYVYU(overlay); + break; + case SDL_YUY2_OVERLAY: + ConvertRGBtoYUY2(overlay); + break; + case SDL_IYUV_OVERLAY: + ConvertRGBtoIYUV(overlay); + break; + default: + fprintf(stderr, "cannot convert RGB picture to obtained YUV format!\n"); + exit(1); + break; + } + +} + + +inline void Draw_Overlay(SDL_Surface *display, int size) +{ + SDL_LockYUVOverlay(overlay); + + Convert32bit(display); + + overlay_rect.x = 0; + overlay_rect.y = 0; + overlay_rect.w = GBA_WIDTH * size; + overlay_rect.h = GBA_HEIGHT * size; + + SDL_DisplayYUVOverlay(overlay, &overlay_rect); + SDL_UnlockYUVOverlay(overlay); +} + +bool systemIsEmulating() +{ + return emulating != 0; +} + +void systemGbBorderOn() +{ + srcWidth = 256; + srcHeight = 224; + gbBorderLineSkip = 256; + gbBorderColumnSkip = 48; + gbBorderRowSkip = 40; + + destWidth = (sizeOption+1)*srcWidth; + destHeight = (sizeOption+1)*srcHeight; + + surface = SDL_SetVideoMode(destWidth, destHeight, 16, + SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF| + (fullscreen ? SDL_FULLSCREEN : 0)); +#ifndef C_CORE + sdlMakeStretcher(srcWidth); +#else + switch(systemColorDepth) { + case 16: + sdlStretcher = sdlStretcher16[sizeOption]; + break; + case 24: + sdlStretcher = sdlStretcher24[sizeOption]; + break; + case 32: + sdlStretcher = sdlStretcher32[sizeOption]; + break; + default: + fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth); + exit(-1); + } +#endif + + if(systemColorDepth == 16) { + if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) { + Init_2xSaI(565); + RGB_LOW_BITS_MASK = 0x821; + } else { + Init_2xSaI(555); + RGB_LOW_BITS_MASK = 0x421; + } + if(systemCartridgeType == 2) { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) | + (((i & 0x7c0) >> 6) << systemGreenShift) | + (((i & 0xf800) >> 11) << systemRedShift); + } + } else { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + } + srcPitch = srcWidth * 2+4; + } else { + if(systemColorDepth != 32) + filterFunction = NULL; + RGB_LOW_BITS_MASK = 0x010101; + if(systemColorDepth == 32) { + Init_2xSaI(32); + } + for(int i = 0; i < 0x10000; i++) { + systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + if(systemColorDepth == 32) + srcPitch = srcWidth*4 + 4; + else + srcPitch = srcWidth*3; + } +} + +bool systemIsRunningGBA() +{ + return (rom != NULL); +} + +int systemGetDefaultJoypad() +{ + return sdlDefaultJoypad; +} + +bool systemIsPaused() +{ + return paused; +} + +void systemSetPause(bool pause) +{ + paused = pause; + if (pause) + systemSoundPause(); + else + systemSoundResume(); +} + +u16 checksumBIOS() +{ + bool hasBIOS = false; + u8 * tempBIOS; + if(useBios) + { + tempBIOS = (u8 *)malloc(0x4000); + int size = 0x4000; + if(utilLoad(biosFileName, + utilIsGBABios, + tempBIOS, + size)) { + if(size == 0x4000) + hasBIOS = true; + } + } + + u16 biosCheck = 0; + if(hasBIOS) { + for(int i = 0; i < 0x4000; i += 4) + biosCheck += *((u32 *)&tempBIOS[i]); + free(tempBIOS); + } + + return biosCheck; +} + +EmulatedSystemCounters systemCounters = { + 0, //framecount + 0, //lagcount + 0, //extracount + true, //lagged + true //laggedLast +}; + +void VBAOnEnteringFrameBoundary() +{ + CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION); + + if (VBALuaRunning()) + { + VBALuaFrameBoundary(); + } + + VBAMovieUpdateState(); +} + +void VBAOnExitingFrameBoundary() +{ + ; +} + + diff -r b970226568d2 -r 2efb971df515 src/sdl/SoundDriver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/SoundDriver.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,65 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 2008 VBA-M development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 __VBA_SOUND_DRIVER_H__ +#define __VBA_SOUND_DRIVER_H__ + +#include "Types.h" + +/** + * Sound driver abstract interface for the core to use to output sound. + * Subclass this to implement a new sound driver. + */ +class SoundDriver +{ +public: + + /** + * Destructor. Free the resources allocated by the sound driver. + */ + virtual ~SoundDriver() { }; + + /** + * Initialize the sound driver. + * @param sampleRate In Hertz + */ + virtual bool init() = 0; + + /** + * Tell the driver that the sound stream has paused + */ + virtual void pause() = 0; + + /** + * Reset the sound driver + */ + virtual void reset() = 0; + + /** + * Tell the driver that the sound stream has resumed + */ + virtual void resume() = 0; + + /** + * Write length bytes of data from the finalWave buffer to the driver output buffer. + */ + virtual void write(u16 * finalWave, int length) = 0; + + virtual bool setThrottle(unsigned short throttle) = 0; +}; + +#endif // __VBA_SOUND_DRIVER_H__ diff -r b970226568d2 -r 2efb971df515 src/sdl/SoundSDL.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/SoundSDL.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,178 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 2008 VBA-M development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 "SoundSDL.h" + +extern int emulating; +extern bool speedup; + +// Hold up to 100 ms of data in the ring buffer +const float SoundSDL::_delay = 0.1f; + +SoundSDL::SoundSDL(): + _rbuf(0), + _initialized(false) +{ + +} + +void SoundSDL::soundCallback(void *data, u8 *stream, int len) +{ + reinterpret_cast(data)->read(reinterpret_cast(stream), len); +} + +void SoundSDL::read(u16 * stream, int length) +{ + if (!_initialized || length <= 0 || !emulating) + return; + + SDL_mutexP(_mutex); + _rbuf.read(stream, std::min(static_cast(length) / 2, _rbuf.used())); + + SDL_CondSignal(_cond); + SDL_mutexV(_mutex); +} + +void SoundSDL::write(u16 * finalWave, int length) +{ + if (!_initialized) + return; + + if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) + SDL_PauseAudio(0); + + SDL_mutexP(_mutex); + + unsigned int samples = length / 4; + + std::size_t avail; + while ((avail = _rbuf.avail() / 2) < samples) + { + _rbuf.write(finalWave, avail * 2); + + finalWave += avail * 2; + samples -= avail; + + // If emulating and not in speed up mode, synchronize to audio + // by waiting till there is enough room in the buffer + if (emulating && !speedup) + { + SDL_CondWait(_cond,_mutex); + } + else + { + // Drop the remaining of the audio data + SDL_mutexV(_mutex); + return; + } + } + + _rbuf.write(finalWave, samples * 2); + + SDL_mutexV(_mutex); +} + + +bool SoundSDL::init() +{ + SDL_AudioSpec audio; + audio.freq = SDL_SAMPLE_RATE; + audio.format = AUDIO_S16SYS; + audio.channels = 2; + audio.samples = 1024; + audio.callback = soundCallback; + audio.userdata = this; + + if(SDL_OpenAudio(&audio, NULL)) + { + fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError()); + return false; + } + + _rbuf.reset(_delay * SDL_SAMPLE_RATE * 2); + + _cond = SDL_CreateCond(); + _mutex = SDL_CreateMutex(); + _initialized = true; + + return true; +} + +SoundSDL::~SoundSDL() +{ + if (!_initialized) + return; + + SDL_mutexP(_mutex); + int iSave = emulating; + emulating = 0; + SDL_CondSignal(_cond); + SDL_mutexV(_mutex); + + SDL_DestroyCond(_cond); + _cond = NULL; + + SDL_DestroyMutex(_mutex); + _mutex = NULL; + + SDL_CloseAudio(); + + emulating = iSave; +} + +void SoundSDL::pause() +{ + if (!_initialized) + return; + + SDL_PauseAudio(1); +} + +void SoundSDL::resume() +{ + if (!_initialized) + return; + + SDL_PauseAudio(0); +} + +void SoundSDL::reset() +{ +} + +bool SoundSDL::setThrottle(unsigned short throttle){ + switch(throttle){ + case 25: + case 50: + case 100: + case 200: + case 400: + break; + default: + return false; + } + SDL_CloseAudio(); + SDL_AudioSpec audio; + audio.freq = SDL_SAMPLE_RATE*throttle/100; + audio.format = AUDIO_S16SYS; + audio.channels = 2; + audio.samples = 1024; + audio.callback = soundCallback; + audio.userdata = this; + _rbuf.reset((_delay * SDL_SAMPLE_RATE * throttle * 2)/100); + return !SDL_OpenAudio(&audio,NULL); +} diff -r b970226568d2 -r 2efb971df515 src/sdl/SoundSDL.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/SoundSDL.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,56 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 2008 VBA-M development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 __VBA_SOUND_SDL_H__ +#define __VBA_SOUND_SDL_H__ + +#include "SoundDriver.h" +#include "RingBuffer.h" + +#include + +const int SDL_SAMPLE_RATE = 44100; + +class SoundSDL: public SoundDriver +{ +public: + SoundSDL(); + virtual ~SoundSDL(); + + virtual bool init(); + virtual void pause(); + virtual void reset(); + virtual void resume(); + virtual void write(u16 * finalWave, int length); + virtual bool setThrottle(unsigned short throttle); + +//private: + RingBuffer _rbuf; + + SDL_cond * _cond; + SDL_mutex * _mutex; + + bool _initialized; + + // Defines what delay in seconds we keep in the sound buffer + static const float _delay; + + static void soundCallback(void *data, u8 *stream, int length); + virtual void read(u16 * stream, int length); +}; + +#endif // __VBA_SOUND_SDL_H__ diff -r b970226568d2 -r 2efb971df515 src/sdl/TestEmu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/TestEmu.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,501 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 +#include +#include +#include +#include +#include + +#include "AutoBuild.h" + +#include "SDL.h" +#include "debugger.h" +#include "common/System.h" +#include "common/unzip.h" +#include "common/Util.h" +#include "gba/GBA.h" +#include "gba/GBAGlobals.h" +#include "gba/GBASound.h" +#include "gb/GB.h" +#include "gb/gbGlobals.h" + +#ifndef WIN32 +# include +# define GETCWD getcwd +#else // WIN32 +# include +# define GETCWD _getcwd +#endif // WIN32 + +#ifdef MMX +extern "C" bool cpu_mmx; +#endif +extern bool8 soundEcho; +extern bool8 soundLowPass; +extern bool8 soundReverse; + +extern void remoteInit(); +extern void remoteCleanUp(); +extern void remoteStubMain(); +extern void remoteStubSignal(int,int); +extern void remoteOutput(char *, u32); +extern void remoteSetProtocol(int); +extern void remoteSetPort(int); +extern void debuggerOutput(char *, u32); + +struct EmulatedSystem emulator; + +int systemRedShift = 0; +int systemBlueShift = 16; +int systemGreenShift = 8; +int systemColorDepth = 32; +int systemDebug = 0; +int systemVerbose = 0; +int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + +int sensorX = 2047; +int sensorY = 2047; +bool sensorOn = false; + +int cartridgeType = 3; +int captureFormat = 0; + +int emulating = 0; +int RGB_LOW_BITS_MASK=0x821; +int systemFrameSkip = 0; +u32 systemColorMap32[0x10000]; +u16 systemColorMap16[0x10000]; +u16 systemGbPalette[24]; +char filename[2048]; +char biosFileName[2048]; +char captureDir[2048]; +char saveDir[2048]; +char batteryDir[2048]; + +int throttle = 0; + +bool paused = false; +bool debugger = true; +bool debuggerStub = false; +bool systemSoundOn = false; +bool removeIntros = false; +int sdlFlashSize = 0; +int sdlAutoIPS = 1; +int sdlRtcEnable = 0; +int sdlAgbPrint = 0; + +int sdlDefaultJoypad = 0; + +u16 motion[4] = { + SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 +}; + +extern void debuggerSignal(int,int); + +void (*dbgMain)() = debuggerMain; +void (*dbgSignal)(int,int) = debuggerSignal; +void (*dbgOutput)(char *, u32) = debuggerOutput; + +char *sdlGetFilename(char *name) +{ + static char filebuffer[2048]; + + int len = strlen(name); + + char *p = name + len - 1; + + while(true) { + if(*p == '/' || + *p == '\\') { + p++; + break; + } + len--; + p--; + if(len == 0) + break; + } + + if(len == 0) + strcpy(filebuffer, name); + else + strcpy(filebuffer, p); + return filebuffer; +} + +void usage(char *cmd) +{ + printf("%s file-name\n",cmd); +} + +int main(int argc, char **argv) +{ + fprintf(stderr,"VisualBoyAdvance-Test version %s\n", VERSION); + + captureDir[0] = 0; + saveDir[0] = 0; + batteryDir[0] = 0; + + char buffer[1024]; + + systemFrameSkip = frameSkip = 2; + gbBorderOn = 0; + + parseDebug = true; + + if(!debuggerStub) { + if(argc <= 1) { + systemMessage(0,"Missing image name"); + usage(argv[0]); + exit(-1); + } + } + + for(int i = 0; i < 24;) { + systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10); + systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10); + systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10); + systemGbPalette[i++] = 0; + } + + if(argc == 2) { + char *szFile = argv[optind]; + bool failed = false; + if(utilIsZipFile(szFile)) { + unzFile unz = unzOpen(szFile); + + if(unz == NULL) { + systemMessage(0, "Cannot open file %s", szFile); + exit(-1); + } + int r = unzGoToFirstFile(unz); + + if(r != UNZ_OK) { + unzClose(unz); + systemMessage(0, "Bad ZIP file %s", szFile); + exit(-1); + } + + bool found = false; + + unz_file_info info; + + while(true) { + r = unzGetCurrentFileInfo(unz, + &info, + buffer, + sizeof(buffer), + NULL, + 0, + NULL, + 0); + + if(r != UNZ_OK) { + unzClose(unz); + systemMessage(0,"Bad ZIP file %s", szFile); + exit(-1); + } + + if(utilIsGBImage(buffer)) { + found = true; + cartridgeType = 1; + break; + } + if(utilIsGBAImage(buffer)) { + found = true; + cartridgeType = 0; + break; + } + + r = unzGoToNextFile(unz); + + if(r != UNZ_OK) + break; + } + + if(!found) { + unzClose(unz); + systemMessage(0, "No image found on ZIP file %s", szFile); + exit(-1); + } + + unzClose(unz); + } + + if(utilIsGBImage(szFile) || cartridgeType == 1) { + failed = !gbLoadRom(szFile); + cartridgeType = 1; + emulator = GBSystem; + } else if(utilIsGBAImage(szFile) || cartridgeType == 0) { + failed = !CPULoadRom(szFile); + cartridgeType = 0; + emulator = GBASystem; + + //CPUInit(biosFileName, useBios); + CPUInit(); + CPUReset(); + } else { + systemMessage(0, "Unknown file type %s", szFile); + exit(-1); + } + + if(failed) { + systemMessage(0, "Failed to load file %s", szFile); + exit(-1); + } + strcpy(filename, szFile); + char *p = strrchr(filename, '.'); + + if(p) + *p = 0; + } else { + cartridgeType = 0; + strcpy(filename, "gnu_stub"); + rom = (u8 *)malloc(0x2000000); + workRAM = (u8 *)calloc(1, 0x40000); + bios = (u8 *)calloc(1,0x4000); + internalRAM = (u8 *)calloc(1,0x8000); + paletteRAM = (u8 *)calloc(1,0x400); + vram = (u8 *)calloc(1, 0x20000); + oam = (u8 *)calloc(1, 0x400); + pix = (u8 *)calloc(1, 4 * 240 * 160); + ioMem = (u8 *)calloc(1, 0x400); + + emulator = GBASystem; + + //CPUInit(biosFileName, useBios); + CPUInit(); + CPUReset(); + } + + if(debuggerStub) + remoteInit(); + + if(cartridgeType == 0) { + } else if (cartridgeType == 1) { + if(gbBorderOn) { + gbBorderLineSkip = 256; + gbBorderColumnSkip = 48; + gbBorderRowSkip = 40; + } else { + gbBorderLineSkip = 160; + gbBorderColumnSkip = 0; + gbBorderRowSkip = 0; + } + } else { + } + + for(int i = 0; i < 0x10000; i++) { + systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + + emulating = 1; + soundInit(); + + while(emulating) { + if(!paused) { + if(debugger && emulator.emuHasDebugger) + dbgMain(); + else + emulator.emuMain(emulator.emuCount); + } + } + emulating = 0; + fprintf(stderr,"Shutting down\n"); + remoteCleanUp(); + soundShutdown(); + + if(gbRom != NULL || rom != NULL) { + emulator.emuCleanUp(); + } + + return 0; +} + +void systemMessage(int num, const char *msg, ...) +{ + char buffer[2048]; + va_list valist; + + va_start(valist, msg); + vsprintf(buffer, msg, valist); + + fprintf(stderr, "%s\n", buffer); + va_end(valist); +} + +void systemDrawScreen() +{ +} + +bool systemReadJoypads() +{ + return true; +} + +u32 systemReadJoypad(int,bool) +{ + return 0; +} + +void systemShowSpeed(int speed) +{ +} + +void system10Frames(int rate) +{ +} + +void systemFrame(int) +{ +} + +void systemSetTitle(const char *title) +{ +} + +int systemScreenCapture(int a) +{ + char buffer[2048]; + + if(captureFormat) { + if(captureDir[0]) + sprintf(buffer, "%s/%s%02d.bmp", captureDir, sdlGetFilename(filename), a); + else + sprintf(buffer, "%s%02d.bmp", filename, a); + + emulator.emuWriteBMP(buffer); + } else { + if(captureDir[0]) + sprintf(buffer, "%s/%s%02d.png", captureDir, sdlGetFilename(filename), a); + else + sprintf(buffer, "%s%02d.png", filename, a); + emulator.emuWritePNG(buffer); + } + + systemScreenMessage("Screen capture"); +} + +u32 systemReadJoypadExtended() +{ + return 0; +} + +void systemWriteDataToSoundBuffer() +{ +} + +bool systemSoundInit() +{ + return true; +} + +void systemSoundShutdown() +{ +} + +void systemSoundPause() +{ +} + +void systemSoundResume() +{ +} + +void systemSoundReset() +{ +} + +static int ticks = 0; + +u32 systemGetClock() +{ + return ticks++; +} + +void systemUpdateMotionSensor() +{ +} + +int systemGetSensorX() +{ + return 0; +} + +int systemGetSensorY() +{ + return 0; +} + +void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast) +{ +} + +void systemScreenMessage(const char *msg, int slot, int duration, const char *colorList) +{ +} + +bool systemCanChangeSoundQuality() +{ + return false; +} + +bool systemPauseOnFrame() +{ + return false; +} + +void systemGbBorderOn() +{ +} + +bool sdlCheckJoyKey(int) +{ + return true; +} + +u16 checksumBIOS() +{ + bool hasBIOS = false; + u8 * tempBIOS; + if(useBios) + { + tempBIOS = (u8 *)malloc(0x4000); + int size = 0x4000; + if(utilLoad(biosFileName, + utilIsGBABios, + tempBIOS, + size)) { + if(size == 0x4000) + hasBIOS = true; + } + } + + u16 biosCheck = 0; + if(hasBIOS) { + for(int i = 0; i < 0x4000; i += 4) + biosCheck += *((u32 *)&tempBIOS[i]); + free(tempBIOS); + } + + return biosCheck; +} diff -r b970226568d2 -r 2efb971df515 src/sdl/Types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/Types.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,33 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 2008 VBA-M development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 __VBA_TYPES_H__ +#define __VBA_TYPES_H__ + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +#endif // __VBA_TYPES_H__ diff -r b970226568d2 -r 2efb971df515 src/sdl/debugger.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/debugger.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,1460 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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. + +extern "C" { +#include +#include +} // FIXME: should use c++ headers instead + +#include + +#include "Port.h" +#include "gba/GBA.h" +#include "gba/GBAGlobals.h" +#include "gba/GBACheats.h" +#include "gba/armdis.h" +#include "gba/elf.h" +#include "common/System.h" +#include "exprNode.h" + +extern bool debugger; +extern int emulating; + +extern struct EmulatedSystem theEmulator; + +#define debuggerReadMemory(addr) \ + READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +#define debuggerReadHalfWord(addr) \ + READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +#define debuggerReadByte(addr) \ + map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] + +#define debuggerWriteMemory(addr, value) \ + WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value) + +#define debuggerWriteHalfWord(addr, value) \ + WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value) + +#define debuggerWriteByte(addr, value) \ + map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value) + +struct breakpointInfo { + u32 address; + u32 value; + int size; +}; + +struct DebuggerCommand { + const char *name; + void (*function)(int,char **); + const char *help; + const char *syntax; +}; + +void debuggerContinueAfterBreakpoint(); + +void debuggerHelp(int,char **); +void debuggerNext(int,char **); +void debuggerContinue(int, char **); +void debuggerRegisters(int, char **); +void debuggerBreak(int, char **); +void debuggerBreakDelete(int, char **); +void debuggerBreakList(int, char **); +void debuggerBreakArm(int, char **); +void debuggerBreakWriteClear(int, char **); +void debuggerBreakThumb(int, char **); +void debuggerBreakWrite(int, char **); +void debuggerDebug(int, char **); +void debuggerDisassemble(int, char **); +void debuggerDisassembleArm(int, char **); +void debuggerDisassembleThumb(int, char **); +void debuggerEditByte(int, char **); +void debuggerEditHalfWord(int, char **); +void debuggerEdit(int, char **); +void debuggerIo(int, char **); +void debuggerLocals(int, char **); +void debuggerMemoryByte(int, char **); +void debuggerMemoryHalfWord(int, char **); +void debuggerMemory(int, char **); +void debuggerPrint(int, char **); +void debuggerQuit(int, char **); +void debuggerSetRadix(int, char **); +void debuggerSymbols(int, char **); +void debuggerVerbose(int, char **); +void debuggerWhere(int, char **); + +DebuggerCommand debuggerCommands[] = { + { "?", debuggerHelp, "Shows this help information. Type ? for command help", "[]" }, + { "ba", debuggerBreakArm, "Adds an ARM breakpoint", "
" }, + { "bd", debuggerBreakDelete,"Deletes a breakpoint", "" }, + { "bl", debuggerBreakList, "Lists breakpoints" }, + { "bpw", debuggerBreakWrite, "Break on write", "
" }, + { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL }, + { "break", debuggerBreak, "Adds a breakpoint on the given function", "||" }, + { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "
" }, + { "c", debuggerContinue, "Continues execution" , NULL }, + { "d", debuggerDisassemble, "Disassembles instructions", "[
[]]" }, + { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[
[]]" }, + { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[
[]]" }, + { "eb", debuggerEditByte, "Modify memory location (byte)", "
" }, + { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","
" }, + { "ew", debuggerEdit, "Modify memory location (word)", "
for command help", "[]" }, + { "io", debuggerIo, "Show I/O registers status", "[video|video2|dma|timer|misc]" }, + { "locals", debuggerLocals, "Shows local variables", NULL }, + { "mb", debuggerMemoryByte, "Shows memory contents (bytes)", "
" }, + { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "
"}, + { "mw", debuggerMemory, "Shows memory contents (words)", "
" }, + { "n", debuggerNext, "Executes the next instruction", "[]" }, + { "print", debuggerPrint, "Print the value of a expression (if known)", "[/x|/o|/d] " }, + { "q", debuggerQuit, "Quits the emulator", NULL }, + { "r", debuggerRegisters, "Shows ARM registers", NULL }, + { "radix", debuggerSetRadix, "Sets the print radix", "" }, + { "symbols", debuggerSymbols, "List symbols", "[]" }, +#ifndef FINAL_VERSION + { "trace", debuggerDebug, "Sets the trace level", "" }, +#endif +#ifdef DEV_VERSION + { "verbose", debuggerVerbose, "Change verbose setting", "" }, +#endif + { "where", debuggerWhere, "Shows call chain", NULL }, + { NULL, NULL, NULL, NULL} // end marker +}; + +breakpointInfo debuggerBreakpointList[100]; + +int debuggerNumOfBreakpoints = 0; +bool debuggerAtBreakpoint = false; +int debuggerBreakpointNumber = 0; +int debuggerRadix = 0; + +void debuggerApplyBreakpoint(u32 address, int num, int size) +{ + if(size) + debuggerWriteMemory(address, (u32)(0xe1200070 | + (num & 0xf) | + ((num<<4)&0xf0))); + else + debuggerWriteHalfWord(address, + (u16)(0xbe00 | num)); +} + +void debuggerDisableBreakpoints() +{ + for(int i = 0; i < debuggerNumOfBreakpoints; i++) { + if(debuggerBreakpointList[i].size) + debuggerWriteMemory(debuggerBreakpointList[i].address, + debuggerBreakpointList[i].value); + else + debuggerWriteHalfWord(debuggerBreakpointList[i].address, + debuggerBreakpointList[i].value); + } +} + +void debuggerEnableBreakpoints(bool skipPC) +{ + for(int i = 0; i < debuggerNumOfBreakpoints; i++) { + if(debuggerBreakpointList[i].address == armNextPC && skipPC) + continue; + + debuggerApplyBreakpoint(debuggerBreakpointList[i].address, + i, + debuggerBreakpointList[i].size); + } +} + +void debuggerUsage(const char *cmd) +{ + for(int i = 0; ; i++) { + if(debuggerCommands[i].name) { + if(!strcmp(debuggerCommands[i].name, cmd)) { + printf("%s %s\t%s\n", + debuggerCommands[i].name, + debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "", + debuggerCommands[i].help); + break; + } + } else { + printf("Unrecognized command '%s'.", cmd); + break; + } + } +} + +void debuggerPrintBaseType(Type *t, u32 value, u32 location, + LocationType type, + int bitSize, int bitOffset) +{ + if(bitSize) { + if(bitOffset) + value >>= ((t->size*8)-bitOffset-bitSize); + value &= (1 << bitSize)-1; + } else { + if(t->size == 2) + value &= 0xFFFF; + else if(t->size == 1) + value &= 0xFF; + } + + if(t->size == 8) { + u64 value = 0; + if(type == LOCATION_memory) { + value = debuggerReadMemory(location) | + ((u64)debuggerReadMemory(location+4)<<32); + } else if(type == LOCATION_register) { + value = reg[location].I | ((u64)reg[location+1].I << 32); + } + switch(t->encoding) { + case DW_ATE_signed: + switch(debuggerRadix) { + case 0: + printf("%lld", value); + break; + case 1: + printf("0x%llx", value); + break; + case 2: + printf("0%llo", value); + break; + } + break; + case DW_ATE_unsigned: + switch(debuggerRadix) { + case 0: + printf("%llu", value); + break; + case 1: + printf("0x%llx", value); + break; + case 2: + printf("0%llo", value); + break; + } + break; + default: + printf("Unknowing 64-bit encoding\n"); + } + return; + } + + switch(t->encoding) { + case DW_ATE_boolean: + if(value) + printf("true"); + else + printf("false"); + break; + case DW_ATE_signed: + switch(debuggerRadix) { + case 0: + printf("%d", value); + break; + case 1: + printf("0x%x", value); + break; + case 2: + printf("0%o", value); + break; + } + break; + case DW_ATE_unsigned: + case DW_ATE_unsigned_char: + switch(debuggerRadix) { + case 0: + printf("%u", value); + break; + case 1: + printf("0x%x", value); + break; + case 2: + printf("0%o", value); + break; + } + break; + default: + printf("UNKNOWN BASE %d %08x", t->encoding, value); + } +} + +char *debuggerPrintType(Type *t) +{ + char buffer[1024]; + static char buffer2[1024]; + + if(t->type == TYPE_pointer) { + if(t->pointer) + strcpy(buffer, debuggerPrintType(t->pointer)); + else + strcpy(buffer, "void"); + sprintf(buffer2, "%s *", buffer); + return buffer2; + } else if(t->type == TYPE_reference) { + strcpy(buffer, debuggerPrintType(t->pointer)); + sprintf(buffer2, "%s &", buffer); + return buffer2; + } + return t->name; +} + +void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32); +void debuggerPrintValueInternal(Function *f, Type *t, + int bitSize, int bitOffset, + u32 objLocation, LocationType type); + +u32 debuggerGetValue(u32 location, LocationType type) +{ + switch(type) { + case LOCATION_memory: + return debuggerReadMemory(location); + case LOCATION_register: + return reg[location].I; + case LOCATION_value: + return location; + } + return 0; +} + +void debuggerPrintPointer(Type *t, u32 value) +{ + printf("(%s)0x%08x", debuggerPrintType(t), value); +} + +void debuggerPrintReference(Type *t, u32 value) +{ + printf("(%s)0x%08x", debuggerPrintType(t), value); +} + +void debuggerPrintFunction(Type *t, u32 value) +{ + printf("(%s)0x%08x", debuggerPrintType(t), value); +} + +void debuggerPrintArray(Type *t, u32 value) +{ + // todo + printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value); +} + +void debuggerPrintMember(Function *f, + Member *m, + u32 objLocation, + u32 location) +{ + int bitSize = m->bitSize; + if(bitSize) { + u32 value = 0; + int off = m->bitOffset; + int size = m->byteSize; + u32 v = 0; + if(size == 1) + v = debuggerReadByte(location); + else if(size == 2) + v = debuggerReadHalfWord(location); + else if(size == 4) + v = debuggerReadMemory(location); + + while(bitSize) { + int top = size*8 - off; + int bot = top - bitSize; + top--; + if(bot >= 0) { + value = (v >> (size*8 - bitSize - off)) & ((1 << bitSize)-1); + bitSize = 0; + } else { + value |= (v & ((1 << top)-1)) << (bitSize - top); + bitSize -= (top+1); + location -= size; + off = 0; + if(size == 1) + v = debuggerReadByte(location); + else if(size == 2) + v = debuggerReadHalfWord(location); + else + v = debuggerReadMemory(location); + } + } + debuggerPrintBaseType(m->type, value, location, LOCATION_memory, + bitSize, 0); + } else { + debuggerPrintValueInternal(f, m->type, m->location, m->bitSize, + m->bitOffset, objLocation); + } +} + +void debuggerPrintStructure(Function *f, Type *t, u32 objLocation) +{ + printf("{"); + int count = t->structure->memberCount; + int i = 0; + while(i < count) { + Member *m = &t->structure->members[i]; + printf("%s=", m->name); + LocationType type; + u32 location = elfDecodeLocation(f, m->location, &type, objLocation); + debuggerPrintMember(f, m, objLocation, location); + i++; + if(i < count) + printf(","); + } + printf("}"); +} + +void debuggerPrintUnion(Function *f, Type *t, u32 objLocation) +{ + // todo + printf("{"); + int count = t->structure->memberCount; + int i = 0; + while(i < count) { + Member *m = &t->structure->members[i]; + printf("%s=", m->name); + debuggerPrintMember(f, m, objLocation, 0); + i++; + if(i < count) + printf(","); + } + printf("}"); +} + +void debuggerPrintEnum(Type *t, u32 value) +{ + int i; + for(i = 0; i < t->enumeration->count; i++) { + EnumMember *m = (EnumMember *)&t->enumeration->members[i]; + if(value == m->value) { + puts(m->name); + return; + } + } + printf("(UNKNOWN VALUE) %d", value); +} + +void debuggerPrintValueInternal(Function *f, Type *t, + int bitSize, int bitOffset, + u32 objLocation, LocationType type) +{ + u32 value = debuggerGetValue(objLocation, type); + if(!t) { + printf("void"); + return; + } + switch(t->type) { + case TYPE_base: + debuggerPrintBaseType(t, value, objLocation, type, bitSize, bitOffset); + break; + case TYPE_pointer: + debuggerPrintPointer(t, value); + break; + case TYPE_reference: + debuggerPrintReference(t, value); + break; + case TYPE_function: + debuggerPrintFunction(t, value); + break; + case TYPE_array: + debuggerPrintArray(t, objLocation); + break; + case TYPE_struct: + debuggerPrintStructure(f, t, objLocation); + break; + case TYPE_union: + debuggerPrintUnion(f, t, objLocation); + break; + case TYPE_enum: + debuggerPrintEnum(t, value); + break; + default: + printf("%08x", value); + break; + } +} + +void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc, + int bitSize, int bitOffset, u32 objLocation) +{ + LocationType type; + u32 location; + if(loc) { + if(objLocation) + location = elfDecodeLocation(f, loc, &type, objLocation); + else + location = elfDecodeLocation(f, loc,&type); + } else { + location = objLocation; + type = LOCATION_memory; + } + + debuggerPrintValueInternal(f, t, bitSize, bitOffset, location, type); +} + +void debuggerPrintValue(Function *f, Object *o) +{ + debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0); + + printf("\n"); +} + +void debuggerSymbols(int argc, char **argv) +{ + int i = 0; + u32 value; + u32 size; + int type; + bool match = false; + int matchSize = 0; + char *matchStr = NULL; + + if(argc == 2) { + match = true; + matchSize = strlen(argv[1]); + matchStr = argv[1]; + } + printf("Symbol Value Size Type \n"); + printf("-------------------- ------- -------- -------\n"); + char *s = NULL; + while((s = elfGetSymbol(i, &value, &size, &type))) { + if(*s) { + if(match) { + if(strncmp(s, matchStr, matchSize) != 0) { + i++; + continue; + } + } + const char *ts = "?"; + switch(type) { + case 2: + ts = "ARM"; + break; + case 0x0d: + ts = "THUMB"; + break; + case 1: + ts = "DATA"; + break; + } + printf("%-20s %08x %08x %-7s\n", + s, value, size, ts); + } + i++; + } +} + +void debuggerSetRadix(int argc, char **argv) +{ + if(argc != 2) + debuggerUsage(argv[0]); + else { + int r = atoi(argv[1]); + + bool error = false; + switch(r) { + case 10: + debuggerRadix = 0; + break; + case 8: + debuggerRadix = 2; + break; + case 16: + debuggerRadix = 1; + break; + default: + error = true; + printf("Unknown radix %d. Valid values are 8, 10 and 16.\n", r); + break; + } + if(!error) + printf("Radix set to %d\n", r); + } +} + +void debuggerPrint(int argc, char **argv) +{ + if(argc != 2 && argc != 3) { + debuggerUsage(argv[0]); + } else { + u32 pc = armNextPC; + Function *f = NULL; + CompileUnit *u = NULL; + + elfGetCurrentFunction(pc, + &f, &u); + + int oldRadix = debuggerRadix; + if(argc == 3) { + if(argv[1][0] == '/') { + if(argv[1][1] == 'x') + debuggerRadix = 1; + else if(argv[1][1] == 'o') + debuggerRadix = 2; + else if(argv[1][1] == 'd') + debuggerRadix = 0; + else { + printf("Unknown format %c\n", argv[1][1]); + return; + } + } else { + printf("Unknown option %s\n", argv[1]); + return; + } + } + + char *s = argc == 2 ? argv[1] : argv[2]; + + extern char *exprString; + extern int exprCol; + extern int yyparse(); + exprString = s; + exprCol = 0; + if(!yyparse()) { + extern Node *result; + if(result->resolve(result, f, u)) { + if(result->member) + debuggerPrintMember(f, + result->member, + result->objLocation, + result->location); + else + debuggerPrintValueInternal(f, result->type, 0, 0, + result->location, + result->locType); + printf("\n"); + } else { + printf("Error resolving expression\n"); + } + } else { + printf("Error parsing expression:\n"); + printf("%s\n", s); + exprCol--; + for(int i = 0; i < exprCol; i++) + printf(" "); + printf("^\n"); + } + extern void exprCleanBuffer(); + exprCleanBuffer(); + exprNodeCleanUp(); + debuggerRadix = oldRadix; + } +} + +void debuggerHelp(int n, char **args) +{ + if(n == 2) { + debuggerUsage(args[1]); + } else { + for(int i = 0; ; i++) { + if(debuggerCommands[i].name) { + printf("%s\t%s\n", debuggerCommands[i].name, debuggerCommands[i].help); + } else + break; + } + } +} + +void debuggerDebug(int n, char **args) +{ + if(n == 2) { + int v = 0; + sscanf(args[1], "%d", &v); + systemDebug = v; + printf("Debug level set to %d\n", systemDebug); + } else + debuggerUsage("trace"); +} + +void debuggerVerbose(int n, char **args) +{ + if(n == 2) { + int v = 0; + sscanf(args[1], "%d", &v); + systemVerbose = v; + printf("Verbose level set to %d\n", systemVerbose); + } else + debuggerUsage("verbose"); +} + +void debuggerWhere(int n, char **args) +{ + void elfPrintCallChain(u32); + elfPrintCallChain(armNextPC); +} + +void debuggerLocals(int n, char **args) +{ + Function *f = NULL; + CompileUnit *u = NULL; + u32 pc = armNextPC; + if(elfGetCurrentFunction(pc, + &f, &u)) { + Object *o = f->parameters; + while(o) { + printf("%s=", o->name); + debuggerPrintValue(f, o); + o = o->next; + } + + o = f->variables; + while(o) { + bool visible = o->startScope ? pc>=o->startScope : true; + if(visible) + visible = o->endScope ? pc < o->endScope : true; + if(visible) { + printf("%s=", o->name); + debuggerPrintValue(f, o); + } + o = o->next; + } + } else { + printf("No information for current address\n"); + } +} + +void debuggerNext(int n, char **args) +{ + int count = 1; + if(n == 2) { + sscanf(args[1], "%d", &count); + } + for(int i = 0; i < count; i++) { + if(debuggerAtBreakpoint) { + debuggerContinueAfterBreakpoint(); + debuggerEnableBreakpoints(false); + } else + theEmulator.emuMain(1); + } + debuggerDisableBreakpoints(); + Function *f = NULL; + CompileUnit *u = NULL; + u32 a = armNextPC; + if(elfGetCurrentFunction(a, &f, &u)) { + char *file; + int line = elfFindLine(u, f, a, &file); + + printf("File %s, function %s, line %d\n", file, f->name, + line); + } + debuggerRegisters(0, NULL); +} + +void debuggerContinue(int n, char **args) +{ + if(debuggerAtBreakpoint) + debuggerContinueAfterBreakpoint(); + debuggerEnableBreakpoints(false); + debugger = false; +} + +void debuggerSignal(int sig,int number) +{ + switch(sig) { + case 4: + { + printf("Illegal instruction at %08x\n", armNextPC); + debugger = true; + } + break; + case 5: + { + printf("Breakpoint %d reached\n", number); + debugger = true; + debuggerAtBreakpoint = true; + debuggerBreakpointNumber = number; + debuggerDisableBreakpoints(); + + Function *f = NULL; + CompileUnit *u = NULL; + + if(elfGetCurrentFunction(armNextPC, &f, &u)) { + char *file; + int line = elfFindLine(u,f,armNextPC,&file); + printf("File %s, function %s, line %d\n", file, f->name, + line); + } + } + break; + default: + printf("Unknown signal %d\n", sig); + break; + } +} + +void debuggerBreakList(int, char **) +{ + printf("Num Address Type Symbol\n"); + printf("--- -------- ----- ------\n"); + for(int i = 0; i < debuggerNumOfBreakpoints; i++) { + printf("%3d %08x %s %s\n",i, debuggerBreakpointList[i].address, + debuggerBreakpointList[i].size ? "ARM" : "THUMB", + elfGetAddressSymbol(debuggerBreakpointList[i].address)); + } +} + +void debuggerBreakDelete(int n, char **args) +{ + if(n == 2) { + int n = 0; + sscanf(args[1], "%d", &n); + printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints); + if(n >= 0 && n < debuggerNumOfBreakpoints) { + n++; + if(n < debuggerNumOfBreakpoints) { + for(int i = n; i < debuggerNumOfBreakpoints; i++) { + debuggerBreakpointList[i-1].address = + debuggerBreakpointList[i].address; + debuggerBreakpointList[i-1].value = + debuggerBreakpointList[i].value; + debuggerBreakpointList[i-1].size = + debuggerBreakpointList[i].size; + } + } + debuggerNumOfBreakpoints--; + } + } else + debuggerUsage("bd"); +} + +void debuggerBreak(int n, char **args) +{ + if(n == 2) { + u32 address = 0; + u32 value = 0; + int type = 0; + char *s = args[1]; + char c = *s; + if(strchr(s, ':')) { + char *name = s; + char *l = strchr(s, ':'); + *l++ = 0; + int line = atoi(l); + + u32 addr; + Function *f; + CompileUnit *u; + + if(elfFindLineInModule(&addr, name, line)) { + if(elfGetCurrentFunction(addr, &f, &u)) { + u32 addr2; + if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) { + address = addr; + } else { + printf("Unable to get function symbol data\n"); + return; + } + } else { + printf("Unable to find function for address\n"); + return; + } + } else { + printf("Unable to find module or line\n"); + return; + } + } else if(c >= '0' && c <= '9') { + int line = atoi(s); + Function *f; + CompileUnit *u; + u32 addr; + + if(elfGetCurrentFunction(armNextPC, &f, &u)) { + if(elfFindLineInUnit(&addr, u, line)) { + if(elfGetCurrentFunction(addr, &f, &u)) { + u32 addr2; + if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) { + address = addr; + } else { + printf("Unable to get function symbol data\n"); + return; + } + } else { + printf("Unable to find function for address\n"); + return; + } + } else { + printf("Unable to find line\n"); + return; + } + } else { + printf("Cannot find current function\n"); + return; + } + } else { + if(!elfGetSymbolAddress(s, &address, &value, &type)) { + printf("Function %s not found\n", args[1]); + return; + } + } + if(type == 0x02 || type == 0x0d) { + int i = debuggerNumOfBreakpoints; + int size = 0; + if(type == 2) + size = 1; + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = type == 0x02 ? + debuggerReadMemory(address) : debuggerReadHalfWord(address); + debuggerBreakpointList[i].size = size; + // debuggerApplyBreakpoint(address, i, size); + debuggerNumOfBreakpoints++; + if(size) + printf("Added ARM breakpoint at %08x\n", address); + else + printf("Added THUMB breakpoint at %08x\n", address); + } else { + printf("%s is not a function symbol\n", args[1]); + } + } else + debuggerUsage("break"); +} + +void debuggerBreakThumb(int n, char **args) +{ + if(n == 2) { + u32 address = 0; + sscanf(args[1],"%x", &address); + int i = debuggerNumOfBreakpoints; + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = debuggerReadHalfWord(address); + debuggerBreakpointList[i].size = 0; + // debuggerApplyBreakpoint(address, i, 0); + debuggerNumOfBreakpoints++; + printf("Added THUMB breakpoint at %08x\n", address); + } else + debuggerUsage("bt"); +} + +void debuggerBreakArm(int n, char **args) +{ + if(n == 2) { + u32 address = 0; + sscanf(args[1],"%x", &address); + int i = debuggerNumOfBreakpoints; + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = debuggerReadMemory(address); + debuggerBreakpointList[i].size = 1; + // debuggerApplyBreakpoint(address, i, 1); + debuggerNumOfBreakpoints++; + printf("Added ARM breakpoint at %08x\n", address); + } else + debuggerUsage("ba"); +} + +void debuggerBreakOnWrite(u32 *mem, u32 oldvalue, u32 value, int size) +{ + u32 address = 0; + if(mem >= (u32*)&workRAM[0] && mem <= (u32*)&workRAM[0x3ffff]) + address = 0x2000000 + ((u64)mem - (u64)&workRAM[0]); + else + address = 0x3000000 + ((u64)mem - (u64)&internalRAM[0]); + + if(size == 2) + printf("Breakpoint (on write) address %08x old:%08x new:%08x\n", + address, oldvalue, value); + else if(size == 1) + printf("Breakpoint (on write) address %08x old:%04x new:%04x\n", + address, (u16)oldvalue,(u16)value); + else + printf("Breakpoint (on write) address %08x old:%02x new:%02x\n", + address, (u8)oldvalue, (u8)value); + debugger = true; +} + +void debuggerBreakWriteClear(int n, char **args) +{ + memset(freezeWorkRAM, false, 0x40000); + memset(freezeInternalRAM, false, 0x8000); + printf("Cleared all break on write\n"); +} + +void debuggerBreakWrite(int n, char **args) +{ + if(n == 3) { + if(cheatsNumber != 0) { + printf("Cheats are enabled. Cannot continue.\n"); + return; + } + u32 address = 0; + sscanf(args[1], "%x", &address); + int n = 0; + sscanf(args[2], "%d", &n); + + if(address < 0x2000000 || address > 0x3007fff) { + printf("Invalid address: %08x\n", address); + return; + } + + if(address > 0x203ffff && address < 0x3000000) { + printf("Invalid address: %08x\n", address); + return; + } + + u32 final = address + n; + + if(address < 0x2040000 && final > 0x2040000) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x3008000 && final > 0x3008000) { + printf("Invalid byte count: %d\n", n); + return; + } + printf("Added break on write at %08x for %d bytes\n", address, n); + for(int i = 0; i < n; i++) { + if((address >> 24) == 2) + freezeWorkRAM[address & 0x3ffff] = true; + else + freezeInternalRAM[address & 0x7fff] = true; + address++; + } + } else + debuggerUsage("bpw"); +} + +void debuggerDisassembleArm(int n, char **args) +{ + char buffer[80]; + u32 pc = reg[15].I; + pc -= 4; + int count = 20; + if(n >= 2) { + sscanf(args[1], "%x", &pc); + } + if(pc & 3) { + printf("Misaligned address %08x\n", pc); + pc &= 0xfffffffc; + } + if(n >= 3) { + sscanf(args[2], "%d", &count); + } + int i = 0; + int len = 0; + char format[30]; + for(i = 0; i < count; i++) { + int l = strlen(elfGetAddressSymbol(pc+4*i)); + if(l > len) + len = l; + } + sprintf(format, "%%08x %%-%ds %%s\n", len); + for(i = 0; i < count; i++) { + u32 addr = pc; + pc += disArm(pc, buffer, 2); + printf(format, addr, elfGetAddressSymbol(addr), buffer); + } +} + +void debuggerDisassembleThumb(int n, char **args) +{ + char buffer[80]; + u32 pc = reg[15].I; + pc -= 2; + int count = 20; + if(n >= 2) { + sscanf(args[1], "%x", &pc); + } + if(pc & 1) { + printf("Misaligned address %08x\n", pc); + pc &= 0xfffffffe; + } + if(n >= 3) { + sscanf(args[2], "%d", &count); + } + + int i = 0; + int len = 0; + char format[30]; + for(i = 0; i < count; i++) { + int l = strlen(elfGetAddressSymbol(pc+2*i)); + if(l > len) + len = l; + } + sprintf(format, "%%08x %%-%ds %%s\n", len); + + for(i = 0; i < count; i++) { + u32 addr = pc; + pc += disThumb(pc, buffer, 2); + printf(format, addr, elfGetAddressSymbol(addr), buffer); + } +} + +void debuggerDisassemble(int n, char **args) +{ + if(armState) + debuggerDisassembleArm(n, args); + else + debuggerDisassembleThumb(n, args); +} + +void debuggerContinueAfterBreakpoint() +{ + printf("Continuing after breakpoint\n"); + debuggerEnableBreakpoints(true); + theEmulator.emuMain(1); + debuggerAtBreakpoint = false; +} + +void debuggerRegisters(int, char **) +{ + char *command[3]; + char buffer[10]; + + printf("R00=%08x R04=%08x R08=%08x R12=%08x\n", + reg[0].I, reg[4].I, reg[8].I, reg[12].I); + printf("R01=%08x R05=%08x R09=%08x R13=%08x\n", + reg[1].I, reg[5].I, reg[9].I, reg[13].I); + printf("R02=%08x R06=%08x R10=%08x R14=%08x\n", + reg[2].I, reg[6].I, reg[10].I, reg[14].I); + printf("R03=%08x R07=%08x R11=%08x R15=%08x\n", + reg[3].I, reg[7].I, reg[11].I, reg[15].I); + printf("CPSR=%08x (%c%c%c%c%c%c%c Mode: %02x)\n", + reg[16].I, + (N_FLAG ? 'N' : '.'), + (Z_FLAG ? 'Z' : '.'), + (C_FLAG ? 'C' : '.'), + (V_FLAG ? 'V' : '.'), + (armIrqEnable ? '.' : 'I'), + ((!(reg[16].I & 0x40)) ? '.' : 'F'), + (armState ? '.' : 'T'), + armMode); + sprintf(buffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 2); + command[0]=const_cast("m"); + command[1]=buffer; + command[2]=const_cast("1"); + debuggerDisassemble(3, command); +} + +void debuggerIoVideo() +{ + printf("DISPCNT = %04x\n", DISPCNT); + printf("DISPSTAT = %04x\n", DISPSTAT); + printf("VCOUNT = %04x\n", VCOUNT); + printf("BG0CNT = %04x\n", BG0CNT); + printf("BG1CNT = %04x\n", BG1CNT); + printf("BG2CNT = %04x\n", BG2CNT); + printf("BG3CNT = %04x\n", BG3CNT); + printf("WIN0H = %04x\n", WIN0H); + printf("WIN0V = %04x\n", WIN0V); + printf("WIN1H = %04x\n", WIN1H); + printf("WIN1V = %04x\n", WIN1V); + printf("WININ = %04x\n", WININ); + printf("WINOUT = %04x\n", WINOUT); + printf("MOSAIC = %04x\n", MOSAIC); + printf("BLDMOD = %04x\n", BLDMOD); + printf("COLEV = %04x\n", COLEV); + printf("COLY = %04x\n", COLY); +} + +void debuggerIoVideo2() +{ + printf("BG0HOFS = %04x\n", BG0HOFS); + printf("BG0VOFS = %04x\n", BG0VOFS); + printf("BG1HOFS = %04x\n", BG1HOFS); + printf("BG1VOFS = %04x\n", BG1VOFS); + printf("BG2HOFS = %04x\n", BG2HOFS); + printf("BG2VOFS = %04x\n", BG2VOFS); + printf("BG3HOFS = %04x\n", BG3HOFS); + printf("BG3VOFS = %04x\n", BG3VOFS); + printf("BG2PA = %04x\n", BG2PA); + printf("BG2PB = %04x\n", BG2PB); + printf("BG2PC = %04x\n", BG2PC); + printf("BG2PD = %04x\n", BG2PD); + printf("BG2X = %08x\n", (BG2X_H<<16)|BG2X_L); + printf("BG2Y = %08x\n", (BG2Y_H<<16)|BG2Y_L); + printf("BG3PA = %04x\n", BG3PA); + printf("BG3PB = %04x\n", BG3PB); + printf("BG3PC = %04x\n", BG3PC); + printf("BG3PD = %04x\n", BG3PD); + printf("BG3X = %08x\n", (BG3X_H<<16)|BG3X_L); + printf("BG3Y = %08x\n", (BG3Y_H<<16)|BG3Y_L); +} + +void debuggerIoDMA() +{ + printf("DM0SAD = %08x\n", (DM0SAD_H<<16)|DM0SAD_L); + printf("DM0DAD = %08x\n", (DM0DAD_H<<16)|DM0DAD_L); + printf("DM0CNT = %08x\n", (DM0CNT_H<<16)|DM0CNT_L); + printf("DM1SAD = %08x\n", (DM1SAD_H<<16)|DM1SAD_L); + printf("DM1DAD = %08x\n", (DM1DAD_H<<16)|DM1DAD_L); + printf("DM1CNT = %08x\n", (DM1CNT_H<<16)|DM1CNT_L); + printf("DM2SAD = %08x\n", (DM2SAD_H<<16)|DM2SAD_L); + printf("DM2DAD = %08x\n", (DM2DAD_H<<16)|DM2DAD_L); + printf("DM2CNT = %08x\n", (DM2CNT_H<<16)|DM2CNT_L); + printf("DM3SAD = %08x\n", (DM3SAD_H<<16)|DM3SAD_L); + printf("DM3DAD = %08x\n", (DM3DAD_H<<16)|DM3DAD_L); + printf("DM3CNT = %08x\n", (DM3CNT_H<<16)|DM3CNT_L); +} + +void debuggerIoTimer() +{ + printf("TM0D = %04x\n", TM0D); + printf("TM0CNT = %04x\n", TM0CNT); + printf("TM1D = %04x\n", TM1D); + printf("TM1CNT = %04x\n", TM1CNT); + printf("TM2D = %04x\n", TM2D); + printf("TM2CNT = %04x\n", TM2CNT); + printf("TM3D = %04x\n", TM3D); + printf("TM3CNT = %04x\n", TM3CNT); +} + +void debuggerIoMisc() +{ + printf("P1 = %04x\n", P1); + printf("IE = %04x\n", IE); + printf("IF = %04x\n", IF); + printf("IME = %04x\n", IME); +} + +void debuggerIo(int n, char **args) +{ + if(n == 1) { + debuggerIoVideo(); + return; + } + if(!strcmp(args[1], "video")) + debuggerIoVideo(); + else if(!strcmp(args[1], "video2")) + debuggerIoVideo2(); + else if(!strcmp(args[1], "dma")) + debuggerIoDMA(); + else if(!strcmp(args[1], "timer")) + debuggerIoTimer(); + else if(!strcmp(args[1], "misc")) + debuggerIoMisc(); + else printf("Unrecognized option %s\n", args[1]); +} + +void debuggerEditByte(int n, char **args) +{ + if(n == 3) { + u32 address; + u32 byte; + sscanf(args[1], "%x", &address); + sscanf(args[2], "%x", &byte); + debuggerWriteByte(address, (u8)byte); + } else + debuggerUsage("eb"); +} + +void debuggerEditHalfWord(int n, char **args) +{ + if(n == 3) { + u32 address; + u32 byte; + sscanf(args[1], "%x", &address); + if(address & 1) { + printf("Error: address must be half-word aligned\n"); + return; + } + sscanf(args[2], "%x", &byte); + debuggerWriteHalfWord(address, (u16)byte); + } else + debuggerUsage("eh"); +} + +void debuggerEdit(int n, char **args) +{ + if(n == 3) { + u32 address; + u32 byte; + sscanf(args[1], "%x", &address); + if(address & 3) { + printf("Error: address must be word aligned\n"); + return; + } + sscanf(args[2], "%x", &byte); + debuggerWriteMemory(address, (u32)byte); + } else + debuggerUsage("ew"); +} + + +#define ASCII(c) (c) < 32 ? '.' : (c) > 127 ? '.' : (c) + +void debuggerMemoryByte(int n, char **args) +{ + if(n == 2) { + u32 addr = 0; + sscanf(args[1], "%x", &addr); + for(int ii = 0; ii < 16; ii++) { + int a = debuggerReadByte(addr); + int b = debuggerReadByte(addr+1); + int c = debuggerReadByte(addr+2); + int d = debuggerReadByte(addr+3); + int e = debuggerReadByte(addr+4); + int f = debuggerReadByte(addr+5); + int g = debuggerReadByte(addr+6); + int h = debuggerReadByte(addr+7); + int i = debuggerReadByte(addr+8); + int j = debuggerReadByte(addr+9); + int k = debuggerReadByte(addr+10); + int l = debuggerReadByte(addr+11); + int m = debuggerReadByte(addr+12); + int n = debuggerReadByte(addr+13); + int o = debuggerReadByte(addr+14); + int p = debuggerReadByte(addr+15); + + printf("%08x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + addr,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, + ASCII(a),ASCII(b),ASCII(c),ASCII(d), + ASCII(e),ASCII(f),ASCII(g),ASCII(h), + ASCII(i),ASCII(j),ASCII(k),ASCII(l), + ASCII(m),ASCII(n),ASCII(o),ASCII(p)); + addr += 16; + } + } else + debuggerUsage("mb"); +} + +void debuggerMemoryHalfWord(int n, char **args) +{ + if(n == 2) { + u32 addr = 0; + sscanf(args[1], "%x", &addr); + addr = addr & 0xfffffffe; + for(int ii = 0; ii < 16; ii++) { + int a = debuggerReadByte(addr); + int b = debuggerReadByte(addr+1); + int c = debuggerReadByte(addr+2); + int d = debuggerReadByte(addr+3); + int e = debuggerReadByte(addr+4); + int f = debuggerReadByte(addr+5); + int g = debuggerReadByte(addr+6); + int h = debuggerReadByte(addr+7); + int i = debuggerReadByte(addr+8); + int j = debuggerReadByte(addr+9); + int k = debuggerReadByte(addr+10); + int l = debuggerReadByte(addr+11); + int m = debuggerReadByte(addr+12); + int n = debuggerReadByte(addr+13); + int o = debuggerReadByte(addr+14); + int p = debuggerReadByte(addr+15); + + printf("%08x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + addr,b,a,d,c,f,e,h,g,j,i,l,k,n,m,p,o, + ASCII(a),ASCII(b),ASCII(c),ASCII(d), + ASCII(e),ASCII(f),ASCII(g),ASCII(h), + ASCII(i),ASCII(j),ASCII(k),ASCII(l), + ASCII(m),ASCII(n),ASCII(o),ASCII(p)); + addr += 16; + } + } else + debuggerUsage("mh"); +} + +void debuggerMemory(int n, char **args) +{ + if(n == 2) { + u32 addr = 0; + sscanf(args[1], "%x", &addr); + addr = addr & 0xfffffffc; + for(int ii = 0; ii < 16; ii++) { + int a = debuggerReadByte(addr); + int b = debuggerReadByte(addr+1); + int c = debuggerReadByte(addr+2); + int d = debuggerReadByte(addr+3); + + int e = debuggerReadByte(addr+4); + int f = debuggerReadByte(addr+5); + int g = debuggerReadByte(addr+6); + int h = debuggerReadByte(addr+7); + + int i = debuggerReadByte(addr+8); + int j = debuggerReadByte(addr+9); + int k = debuggerReadByte(addr+10); + int l = debuggerReadByte(addr+11); + + int m = debuggerReadByte(addr+12); + int n = debuggerReadByte(addr+13); + int o = debuggerReadByte(addr+14); + int p = debuggerReadByte(addr+15); + + printf("%08x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + addr,d,c,b,a,h,g,f,e,l,k,j,i,p,o,n,m, + ASCII(a),ASCII(b),ASCII(c),ASCII(d), + ASCII(e),ASCII(f),ASCII(g),ASCII(h), + ASCII(i),ASCII(j),ASCII(k),ASCII(l), + ASCII(m),ASCII(n),ASCII(o),ASCII(p)); + addr += 16; + } + } else + debuggerUsage("mw"); +} + +void debuggerQuit(int, char **) +{ + char buffer[10]; + printf("Are you sure you want to quit (y/n)? "); + fgets(buffer, 1024, stdin); + + if(buffer[0] == 'y' || buffer[0] == 'Y') { + debugger = false; + emulating = false; + } +} + +void debuggerOutput(char *s, u32 addr) +{ + if(s) + puts(s); + else { + char c; + + c = debuggerReadByte(addr); + addr++; + while(c) { + putchar(c); + c = debuggerReadByte(addr); + addr++; + } + } +} + +void debuggerMain() +{ + char buffer[1024]; + char *commands[10]; + int commandCount = 0; + + if(theEmulator.emuUpdateCPSR) + theEmulator.emuUpdateCPSR(); + debuggerRegisters(0, NULL); + + while(debugger) { + systemSoundPause(); + printf("debugger> "); + commandCount = 0; + char *s = fgets(buffer, 1024, stdin); + + commands[0] = strtok(s, " \t\n"); + if(commands[0] == NULL) + continue; + commandCount++; + while((s = strtok(NULL, " \t\n"))) { + commands[commandCount++] = s; + if(commandCount == 10) + break; + } + + for(int j = 0; ; j++) { + if(debuggerCommands[j].name == NULL) { + printf("Unrecognized command %s. Type h for help.\n", commands[0]); + break; + } + if(!strcmp(commands[0], debuggerCommands[j].name)) { + debuggerCommands[j].function(commandCount, commands); + break; + } + } + } +} diff -r b970226568d2 -r 2efb971df515 src/sdl/debugger.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/debugger.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,20 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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. + +extern void debuggerMain(); diff -r b970226568d2 -r 2efb971df515 src/sdl/expr-lex.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/expr-lex.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,1590 @@ +#line 2 "expr-lex.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvsroot/vba/VisualBoyAdvance/src/expr-lex.cpp,v 1.2 2003/06/06 14:17:21 forgotten Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include +#ifdef __GNUC__ +#include +#endif + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 10 +#define YY_END_OF_BUFFER 11 +static yyconst short int yy_accept[24] = + { 0, + 0, 0, 11, 9, 8, 8, 6, 7, 9, 4, + 3, 2, 2, 8, 5, 3, 2, 2, 2, 2, + 2, 1, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 4, 1, 1, + 1, 5, 1, 1, 6, 7, 1, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, + 1, 9, 1, 1, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 1, 1, 1, 1, 10, 1, 10, 10, 10, 10, + + 11, 12, 10, 10, 13, 10, 10, 10, 10, 10, + 14, 10, 10, 10, 15, 10, 10, 10, 10, 10, + 10, 16, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[17] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, + 2, 2, 2, 2, 2, 2 + } ; + +static yyconst short int yy_base[25] = + { 0, + 0, 0, 32, 33, 15, 17, 33, 33, 22, 33, + 22, 0, 16, 19, 33, 20, 0, 11, 15, 11, + 12, 0, 33, 21 + } ; + +static yyconst short int yy_def[25] = + { 0, + 23, 1, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 24, 24, 23, 23, 23, 24, 24, 24, 24, + 24, 24, 0, 23 + } ; + +static yyconst short int yy_nxt[50] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 4, 12, + 12, 12, 12, 12, 13, 12, 14, 14, 14, 14, + 14, 14, 17, 22, 21, 20, 19, 16, 18, 16, + 15, 23, 3, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23 + } ; + +static yyconst short int yy_chk[50] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 5, 5, 6, 6, + 14, 14, 24, 21, 20, 19, 18, 16, 13, 11, + 9, 3, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "expr.l" +#define INITIAL 0 +#line 2 "expr.l" +#include "expr.cpp.h" + +#ifndef __GNUC__ +#include +#define isatty _isatty +#endif + +char *exprString; +int exprCol; + +#define YY_INPUT(buf,result,max_size) \ + { \ + int c = *exprString++; \ + exprCol++;\ + result = (c == 0) ? YY_NULL : (buf[0] = c, 1); \ + } +#define YY_MAIN 0 +#line 400 "expr-lex.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp = NULL, *yy_bp = NULL; + register int yy_act; + +#line 31 "expr.l" + + +#line 554 "expr-lex.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 24 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 33 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 33 "expr.l" +{ + return TOKEN_SIZEOF; +} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 37 "expr.l" +{ + return TOKEN_IDENTIFIER; +} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 41 "expr.l" +{ + return TOKEN_NUMBER; +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 45 "expr.l" +{ + return TOKEN_DOT; +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 49 "expr.l" +{ + return TOKEN_ARROW; +} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 53 "expr.l" +{ + return TOKEN_ADDR; +} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 57 "expr.l" +{ + return TOKEN_STAR; +} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 61 "expr.l" + + YY_BREAK +case 9: +YY_RULE_SETUP +#line 63 "expr.l" +return *yytext; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 65 "expr.l" +ECHO; + YY_BREAK +#line 701 "expr-lex.cpp" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 24 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 24 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 23); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 65 "expr.l" + + +void exprCleanBuffer() +{ + yy_delete_buffer(yy_current_buffer); + yy_init = 1; +} diff -r b970226568d2 -r 2efb971df515 src/sdl/expr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/expr.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,998 @@ + +/* A Bison parser, made from expr.y + by GNU Bison version 1.28 */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define TOKEN_IDENTIFIER 257 +#define TOKEN_DOT 258 +#define TOKEN_STAR 259 +#define TOKEN_ARROW 260 +#define TOKEN_ADDR 261 +#define TOKEN_SIZEOF 262 +#define TOKEN_NUMBER 263 + +#line 1 "expr.y" + +namespace std { +#include +#include +#include +#include +} + +using namespace std; + +#include "../common/System.h" +#include "../gba/elf.h" +#include "exprNode.h" + +extern int yyerror(char *); +extern int yylex(); +extern char *yytext; + + +//#define YYERROR_VERBOSE 1 +//#define YYDEBUG 1 + + Node *result = NULL; +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 26 +#define YYFLAG -32768 +#define YYNTBASE 14 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 263 ? yytranslate[x] : 19) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, + 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 10, 2, 13, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 4, 8, 12, 16, 21, 23, 26, 29, + 34, 36 +}; + +static const short yyrhs[] = { 15, + 0, 16, 0, 11, 15, 12, 0, 15, 4, 18, + 0, 15, 6, 18, 0, 15, 10, 17, 13, 0, + 18, 0, 5, 15, 0, 7, 15, 0, 8, 11, + 15, 12, 0, 9, 0, 3, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 32, 35, 36, 37, 38, 39, 42, 43, 44, 45, + 49, 53 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","TOKEN_IDENTIFIER", +"TOKEN_DOT","TOKEN_STAR","TOKEN_ARROW","TOKEN_ADDR","TOKEN_SIZEOF","TOKEN_NUMBER", +"'['","'('","')'","']'","final","expression","simple_expression","number","ident", NULL +}; +#endif + +static const short yyr1[] = { 0, + 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, + 17, 18 +}; + +static const short yyr2[] = { 0, + 1, 1, 3, 3, 3, 4, 1, 2, 2, 4, + 1, 1 +}; + +static const short yydefact[] = { 0, + 12, 0, 0, 0, 0, 1, 2, 7, 8, 9, + 0, 0, 0, 0, 0, 0, 3, 4, 5, 11, + 0, 10, 6, 0, 0, 0 +}; + +static const short yydefgoto[] = { 24, + 6, 7, 21, 8 +}; + +static const short yypact[] = { -1, +-32768, -1, -1, -6, -1, 17,-32768,-32768, 17, 17, + -1, 7, 5, 5, 13, 8,-32768,-32768,-32768,-32768, + 11,-32768,-32768, 25, 26,-32768 +}; + +static const short yypgoto[] = {-32768, + -2,-32768,-32768, 2 +}; + + +#define YYLAST 27 + + +static const short yytable[] = { 9, + 10, 1, 12, 2, 11, 3, 4, 1, 16, 5, + 13, 13, 14, 14, 18, 19, 15, 15, 17, 22, + 13, 20, 14, 23, 25, 26, 15 +}; + +static const short yycheck[] = { 2, + 3, 3, 5, 5, 11, 7, 8, 3, 11, 11, + 4, 4, 6, 6, 13, 14, 10, 10, 12, 12, + 4, 9, 6, 13, 0, 0, 10 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/lib/bison.simple" +/* This file comes from bison-1.28. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + 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, 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. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ + register char *t = to; + register char *f = from; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 217 "/usr/lib/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 32 "expr.y" +{ result = yyvsp[0]; ; + break;} +case 2: +#line 36 "expr.y" +{ yyval = yyvsp[0]; ; + break;} +case 3: +#line 37 "expr.y" +{ yyval = yyvsp[-1]; ; + break;} +case 4: +#line 38 "expr.y" +{ yyval = exprNodeDot(yyvsp[-2], yyvsp[0]); ; + break;} +case 5: +#line 39 "expr.y" +{ yyval = exprNodeArrow(yyvsp[-2], yyvsp[0]); ; + break;} +case 6: +#line 40 "expr.y" +{ yyval = exprNodeArray(yyvsp[-3], yyvsp[-1]); ; + break;} +case 7: +#line 43 "expr.y" +{ yyval = yyvsp[0]; ; + break;} +case 8: +#line 44 "expr.y" +{ yyval = exprNodeStar(yyvsp[0]); ; + break;} +case 9: +#line 45 "expr.y" +{ yyval = exprNodeAddr(yyvsp[0]); ; + break;} +case 10: +#line 46 "expr.y" +{ yyval = exprNodeSizeof(yyvsp[-1]); ; + break;} +case 11: +#line 50 "expr.y" +{ yyval = exprNodeNumber(); ; + break;} +case 12: +#line 54 "expr.y" +{yyval = exprNodeIdentifier(); ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/lib/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; + + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 1; +} +#line 57 "expr.y" + + +int yyerror(char *s) +{ + return 0; +} + +#ifndef SDL +extern FILE *yyin; +int main(int argc, char **argv) +{ + // yydebug = 1; + ++argv, --argc; + if(argc > 0) + yyin = fopen(argv[0], "r"); + else + yyin = stdin; + if(!yyparse()) + result->print(); +} +#endif diff -r b970226568d2 -r 2efb971df515 src/sdl/expr.cpp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/expr.cpp.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,13 @@ +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#define TOKEN_IDENTIFIER 257 +#define TOKEN_DOT 258 +#define TOKEN_STAR 259 +#define TOKEN_ARROW 260 +#define TOKEN_ADDR 261 +#define TOKEN_SIZEOF 262 +#define TOKEN_NUMBER 263 + + +extern YYSTYPE yylval; diff -r b970226568d2 -r 2efb971df515 src/sdl/expr.l --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/expr.l Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,71 @@ +%{ +#include "expr.cpp.h" + +#ifndef __GNUC__ +#include +#define isatty _isatty +#endif + +char *exprString; +int exprCol; + +#define YY_INPUT(buf,result,max_size) \ + { \ + int c = *exprString++; \ + exprCol++;\ + result = (c == 0) ? YY_NULL : (buf[0] = c, 1); \ + } +%} + +%option nomain +%option noyywrap + +SIZEOF "sizeof" +ID [a-zA-Z_][a-zA-Z0-9_]* +NUM [0-9]+ +DOT "." +ARROW "->" +STAR "*" +ADDR "&" + +%% + +{SIZEOF} { + return TOKEN_SIZEOF; +} + +{ID} { + return TOKEN_IDENTIFIER; +} + +{NUM} { + return TOKEN_NUMBER; +} + +{DOT} { + return TOKEN_DOT; +} + +{ARROW} { + return TOKEN_ARROW; +} + +{ADDR} { + return TOKEN_ADDR; +} + +{STAR} { + return TOKEN_STAR; +} + +[ \t\n]+ + +. return *yytext; + +%% + +void exprCleanBuffer() +{ + yy_delete_buffer(yy_current_buffer); + yy_init = 1; +} diff -r b970226568d2 -r 2efb971df515 src/sdl/expr.y --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/expr.y Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,77 @@ +%{ +namespace std { +#include +#include +#include +#include +} + +using namespace std; + +#include "System.h" +#include "elf.h" +#include "exprNode.h" + +extern int yyerror(char *); +extern int yylex(); +extern char *yytext; + + +//#define YYERROR_VERBOSE 1 +//#define YYDEBUG 1 + + Node *result = NULL; +%} + +%token TOKEN_IDENTIFIER TOKEN_DOT TOKEN_STAR TOKEN_ARROW TOKEN_ADDR +%token TOKEN_SIZEOF TOKEN_NUMBER +%left TOKEN_DOT TOKEN_ARROW '[' +%expect 6 +%% + +final: expression { result = $1; } +; + +expression: + simple_expression { $$ = $1; } | + '(' expression ')' { $$ = $2; } | + expression TOKEN_DOT ident { $$ = exprNodeDot($1, $3); } | + expression TOKEN_ARROW ident { $$ = exprNodeArrow($1, $3); } | + expression '[' number ']' { $$ = exprNodeArray($1, $3); } +; +simple_expression: + ident { $$ = $1; } | + TOKEN_STAR expression { $$ = exprNodeStar($2); } | + TOKEN_ADDR expression { $$ = exprNodeAddr($2); } | + TOKEN_SIZEOF '(' expression ')' { $$ = exprNodeSizeof($3); } +; + +number: + TOKEN_NUMBER { $$ = exprNodeNumber(); } +; + +ident: + TOKEN_IDENTIFIER {$$ = exprNodeIdentifier(); } +; + +%% + +int yyerror(char *s) +{ + return 0; +} + +#ifndef SDL +extern FILE *yyin; +int main(int argc, char **argv) +{ + // yydebug = 1; + ++argv, --argc; + if(argc > 0) + yyin = fopen(argv[0], "r"); + else + yyin = stdin; + if(!yyparse()) + result->print(); +} +#endif diff -r b970226568d2 -r 2efb971df515 src/sdl/exprNode.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/exprNode.cpp Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,411 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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 +#include +#include + +#include "Port.h" +#include "gba/GBAGlobals.h" +#include "gba/elf.h" +#include "exprNode.h" + +extern char *yytext; + +#define debuggerReadMemory(addr) \ + READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +void *exprNodeCleanUpList[100]; +int exprNodeCleanUpCount = 0; +Type exprNodeType = { 0, TYPE_base, "int", DW_ATE_signed, 4, 0, {0}, 0 }; + +void exprNodeClean(void *m) +{ + exprNodeCleanUpList[exprNodeCleanUpCount++] = m; +} + +void exprNodeCleanUp() +{ + for(int i = 0; i < exprNodeCleanUpCount; i++) { + free(exprNodeCleanUpList[i]); + } + exprNodeCleanUpCount = 0; +} + +Node *exprNodeIdentifier() +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + n->name = strdup(yytext); + + exprNodeClean(n->name); + exprNodeClean(n); + + n->print = exprNodeIdentifierPrint; + n->resolve = exprNodeIdentifierResolve; + return n; +} + +bool exprNodeIdentifierResolve(Node *n, Function *f, CompileUnit *u) +{ + Object *o; + if(elfGetObject(n->name, f, u, &o)) { + n->type = o->type; + n->location = elfDecodeLocation(f, o->location, &n->locType); + return true; + } else { + printf("Object %s not found\n", n->name); + } + return false; +} + +void exprNodeIdentifierPrint(Node *n) +{ + printf("%s", n->name); +} + +Node *exprNodeNumber() +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + + exprNodeClean(n); + n->location = atoi(yytext); + n->type = &exprNodeType; + n->locType = LOCATION_value; + n->print = exprNodeNumberPrint; + n->resolve = exprNodeNumberResolve; + return n; +} + +bool exprNodeNumberResolve(Node *n, Function *f, CompileUnit *u) +{ + return true; +} + +void exprNodeNumberPrint(Node *n) +{ + printf("%d", n->location); +} + +Node *exprNodeStar(Node *exp) +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + exprNodeClean(n); + + n->expression = exp; + + n->print = exprNodeStarPrint; + n->resolve = exprNodeStarResolve; + return n; +} + +bool exprNodeStarResolve(Node *n, Function *f, CompileUnit *u) +{ + if(n->expression->resolve(n->expression, f, u)) { + if(n->expression->type->type == TYPE_pointer) { + n->location = n->expression->location; + if(n->expression->locType == LOCATION_memory) { + n->location = debuggerReadMemory(n->location); + } else if(n->expression->locType == LOCATION_register) { + n->location = reg[n->expression->location].I; + } else { + n->location = n->expression->location; + } + n->type = n->expression->type->pointer; + n->locType = LOCATION_memory; + return true; + } else { + printf("Object is not of pointer type\n"); + } + } + return false; +} + +void exprNodeStarPrint(Node *n) +{ + printf("*"); + n->expression->print(n->expression); +} + +Node *exprNodeDot(Node *exp, Node *ident) +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + exprNodeClean(n); + + n->expression = exp; + n->name = ident->name; + + n->print = exprNodeDotPrint; + n->resolve = exprNodeDotResolve; + return n; +} + +bool exprNodeDotResolve(Node *n, Function *f, CompileUnit *u) +{ + if(n->expression->resolve(n->expression, f, u)) { + TypeEnum tt = n->expression->type->type; + + if(tt == TYPE_struct || + tt == TYPE_union) { + u32 loc = n->expression->location; + Type *t = n->expression->type; + int count = t->structure->memberCount; + int i = 0; + while(i < count) { + Member *m = &t->structure->members[i]; + if(strcmp(m->name, n->name) == 0) { + // found member + n->type = m->type; + if(tt == TYPE_struct) { + n->location = elfDecodeLocation(f, m->location, &n->locType, + loc); + n->objLocation = loc; + } else { + n->location = loc; + n->locType = n->expression->locType; + n->objLocation = loc; + } + n->member = m; + return true; + } + i++; + } + printf("Member %s not found\n", n->name); + } else { + printf("Object is not of structure type\n"); + } + } + return false; +} + +void exprNodeDotPrint(Node *n) +{ + n->expression->print(n->expression); + printf(".%s", n->name); +} + +Node *exprNodeArrow(Node *exp, Node *ident) +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + exprNodeClean(n); + + n->expression = exp; + n->name = ident->name; + + n->print = exprNodeArrowPrint; + n->resolve = exprNodeArrowResolve; + return n; +} + +bool exprNodeArrowResolve(Node *n, Function *f, CompileUnit *u) +{ + if(n->expression->resolve(n->expression, f, u)) { + TypeEnum tt = n->expression->type->type; + if(tt != TYPE_pointer) { + printf("Object not of pointer type\n"); + return false; + } + tt = n->expression->type->pointer->type; + + if(tt == TYPE_struct || + tt == TYPE_union) { + u32 loc = debuggerReadMemory(n->expression->location); + Type *t = n->expression->type->pointer; + int count = t->structure->memberCount; + int i = 0; + while(i < count) { + Member *m = &t->structure->members[i]; + if(strcmp(m->name, n->name) == 0) { + // found member + n->type = m->type; + if(tt == TYPE_struct) { + n->location = elfDecodeLocation(f, m->location, &n->locType, + loc); + n->objLocation = loc; + } else { + n->location = loc; + n->objLocation = loc; + } + n->locType = LOCATION_memory; + n->member = m; + return true; + } + i++; + } + printf("Member %s not found\n", n->name); + } else { + printf("Object is not of structure type\n"); + } + } + return false; +} + +void exprNodeArrowPrint(Node *n) +{ + n->expression->print(n->expression); + printf("->%s", n->name); +} + +Node *exprNodeAddr(Node *exp) +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + exprNodeClean(n); + + n->expression = exp; + + n->print = exprNodeAddrPrint; + n->resolve = exprNodeAddrResolve; + return n; +} + +bool exprNodeAddrResolve(Node *n, Function *f, CompileUnit *u) +{ + if(n->expression->resolve(n->expression, f, u)) { + if(n->expression->locType == LOCATION_memory) { + n->location = n->expression->location; + n->locType = LOCATION_value; + n->type = &exprNodeType; + } else if(n->expression->locType == LOCATION_register) { + printf("Value is in register %d\n", n->expression->location); + } else { + printf("Direct value is %d\n", n->location); + } + return true; + } + return false; +} + +void exprNodeAddrPrint(Node *n) +{ + printf("*"); + n->expression->print(n->expression); +} + +Node *exprNodeSizeof(Node *exp) +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + exprNodeClean(n); + + n->expression = exp; + + n->print = exprNodeSizeofPrint; + n->resolve = exprNodeSizeofResolve; + return n; +} + +bool exprNodeSizeofResolve(Node *n, Function *f, CompileUnit *u) +{ + if(n->expression->resolve(n->expression, f, u)) { + n->location = n->expression->type->size; + n->locType = LOCATION_value; + n->type = &exprNodeType; + return true; + } + return false; +} + +void exprNodeSizeofPrint(Node *n) +{ + printf("sizeof("); + n->expression->print(n->expression); + printf(")"); +} + +Node *exprNodeArray(Node *exp, Node *number) +{ + Node *n = (Node *)calloc(1, sizeof(Node)); + exprNodeClean(n); + + n->expression = exp; + n->value = number->location; + + n->print = exprNodeArrayPrint; + n->resolve = exprNodeArrayResolve; + return n; +} + +int exprNodeGetSize(Array *a, int index) +{ + index++; + if(index == a->maxBounds) { + return a->type->size; + } else { + int size = a->bounds[a->maxBounds-1] * a->type->size; + + for(int i = index; i < a->maxBounds-1; i++) { + size *= a->bounds[i]; + } + return size; + } +} + +bool exprNodeArrayResolve(Node *n, Function *f, CompileUnit *u) +{ + if(n->expression->resolve(n->expression, f, u)) { + TypeEnum tt = n->expression->type->type; + if(tt != TYPE_array && + tt != TYPE_pointer) { + printf("Object not of array or pointer type\n"); + return false; + } + + if(tt == TYPE_array) { + Array *a = n->expression->type->array; + + u32 loc = n->expression->location; + Type *t = a->type; + if(a->maxBounds > 1) { + int index = n->expression->index; + + if(index == a->maxBounds) { + printf("Too many indices for array\n"); + return false; + } + + if((index+1) < a->maxBounds) { + n->type = n->expression->type; + n->index = index+1; + n->locType = LOCATION_memory; + n->location = n->expression->location + + n->value * exprNodeGetSize(a, index); + return true; + } + } + n->type = t; + n->location = loc + n->value * t->size; + n->locType = LOCATION_memory; + } else { + Type *t = n->expression->type->pointer; + u32 loc = n->expression->location; + if(n->expression->locType == LOCATION_register) + loc = reg[loc].I; + else + loc = debuggerReadMemory(loc); + n->type = t; + n->location = loc + n->value * t->size; + n->locType = LOCATION_memory; + } + return true; + } + return false; +} + +void exprNodeArrayPrint(Node *n) +{ + n->expression->print(n->expression); + printf("[%d]", n->value); +} diff -r b970226568d2 -r 2efb971df515 src/sdl/exprNode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/exprNode.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,68 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, 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. + +struct Node { + Type *type; + u32 location; + u32 objLocation; + LocationType locType; + int value; + int index; + char *name; + Node *expression; + Member *member; + void (*print)(Node *); + bool (*resolve)(Node *, Function *f, CompileUnit *u); +}; + +extern void exprNodeCleanUp(); + +extern Node *exprNodeIdentifier(); +extern void exprNodeIdentifierPrint(Node *); +extern bool exprNodeIdentifierResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeNumber(); +extern void exprNodeNumberPrint(Node *); +extern bool exprNodeNumberResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeStar(Node *); +extern void exprNodeStarPrint(Node *); +extern bool exprNodeStarResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeDot(Node *, Node *); +extern void exprNodeDotPrint(Node *); +extern bool exprNodeDotResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeArrow(Node *, Node *); +extern void exprNodeArrowPrint(Node *); +extern bool exprNodeArrowResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeAddr(Node *); +extern void exprNodeAddrPrint(Node *); +extern bool exprNodeAddrResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeSizeof(Node *); +extern void exprNodeSizeofPrint(Node *); +extern bool exprNodeSizeofResolve(Node *, Function *, CompileUnit *); + +extern Node *exprNodeArray(Node *, Node *); +extern void exprNodeArrayPrint(Node *); +extern bool exprNodeArrayResolve(Node *, Function *, CompileUnit *); + +#define YYSTYPE struct Node * diff -r b970226568d2 -r 2efb971df515 src/sdl/getopt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/getopt.c Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,1060 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 + Free Software Foundation, Inc. + + NOTE: This source is derived from an old version taken from the GNU C + Library (glibc). + + 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, 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. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#ifdef VMS +# include +# if HAVE_STRING_H - 0 +# include +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif +#endif + +#ifdef _MSC_VER +#include +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include +# define my_index strchr +#else + +# if HAVE_STRING_H +# include +# else +# if HAVE_STRINGS_H +# include +# endif +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +# ifdef text_set_element +text_set_element (__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff -r b970226568d2 -r 2efb971df515 src/sdl/getopt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/getopt.h Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,141 @@ +/* Declarations for getopt. + Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 2000 + Free Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + 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, 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 _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +/* HAVE_DECL_* is a three-state macro: undefined, 0 or 1. If it is + undefined, we haven't run the autoconf check so provide the + declaration without arguments. If it is 0, we checked and failed + to find the declaration so provide a fully prototyped one. If it + is 1, we found it so don't provide any declaration at all. */ +#if defined (__GNU_LIBRARY__) || (defined (HAVE_DECL_GETOPT) && !HAVE_DECL_GETOPT) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +# if !defined (HAVE_DECL_GETOPT) +extern int getopt (); +# endif +#endif /* __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* getopt.h */ diff -r b970226568d2 -r 2efb971df515 src/sdl/getopt1.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sdl/getopt1.c Sun Mar 04 21:06:50 2012 -0600 @@ -0,0 +1,190 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Free Software Foundation, Inc. + + NOTE: This source is derived from an old version taken from the GNU C + Library (glibc). + + 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, 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "getopt.h" + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */