From 3e665bc66a38e005823f48c3457c292044460af7 Mon Sep 17 00:00:00 2001 From: Nach Date: Wed, 14 Nov 2007 12:06:48 +0000 Subject: [PATCH] Can now build under Linux, although it crashes very early. --- trunk/Makefile | 57 + trunk/src/expr-lex.cpp | 1591 ++++++++++++++ trunk/src/expr.cpp | 998 +++++++++ trunk/src/expr.cpp.h | 13 + trunk/src/exprNode.cpp | 415 ++++ trunk/src/exprNode.h | 68 + trunk/src/libresample-0.1.3/Make | 7 + trunk/src/sdl/SDL.cpp | 3456 ++++++++++++++++++++++++++++++ trunk/src/sdl/debugger.cpp | 2663 +++++++++++++++++++++++ trunk/src/sdl/debugger.h | 20 + trunk/src/sdl/dummy.cpp | 46 + 11 files changed, 9334 insertions(+) create mode 100644 trunk/Makefile create mode 100644 trunk/src/expr-lex.cpp create mode 100644 trunk/src/expr.cpp create mode 100644 trunk/src/expr.cpp.h create mode 100644 trunk/src/exprNode.cpp create mode 100644 trunk/src/exprNode.h create mode 100644 trunk/src/libresample-0.1.3/Make create mode 100644 trunk/src/sdl/SDL.cpp create mode 100644 trunk/src/sdl/debugger.cpp create mode 100644 trunk/src/sdl/debugger.h create mode 100644 trunk/src/sdl/dummy.cpp diff --git a/trunk/Makefile b/trunk/Makefile new file mode 100644 index 00000000..6143a8f0 --- /dev/null +++ b/trunk/Makefile @@ -0,0 +1,57 @@ +CC=gcc +CPPC=g++ +CFLAGS=-W -Wall -Wno-unused -DHAVE_NETINET_IN_H -DHAVE_ARPA_INET_H -DFINAL_VERSION -DSDL -DSYSCONFDIR="home" +CXXFLAGS=${CFLAGS} +ASM=nasm +ASMFLAGS=-w-orphan-labels -f elf -DELF -O1 -Isrc/ +LFLAGS=-lz -lpng -s -lSDL + +MAINDIR=src +SDLDIR=src/sdl +DMGDIR=src/gb +RESAMPLEDIR=src/libresample-0.1.3 + +MAINOBJ=${MAINDIR}/2xSaI.o ${MAINDIR}/admame.o ${MAINDIR}/agbprint.o ${MAINDIR}/armdis.o \ +${MAINDIR}/bilinear.o ${MAINDIR}/bios.o ${MAINDIR}/Cheats.o ${MAINDIR}/CheatSearch.o \ +${MAINDIR}/EEprom.o ${MAINDIR}/elf.o ${MAINDIR}/Flash.o ${MAINDIR}/GBA.o \ +${MAINDIR}/gbafilter.o ${MAINDIR}/Gfx.o ${MAINDIR}/Globals.o ${MAINDIR}/hq2x.o \ +${MAINDIR}/hq3x32.o ${MAINDIR}/hq4x.o ${MAINDIR}/hq_shared32.o ${MAINDIR}/interframe.o \ +${MAINDIR}/lq3x.o ${MAINDIR}/lq4x.o ${MAINDIR}/Mode0.o \ +${MAINDIR}/Mode1.o ${MAINDIR}/Mode2.o ${MAINDIR}/Mode3.o ${MAINDIR}/Mode4.o \ +${MAINDIR}/Mode5.o ${MAINDIR}/motionblur.o ${MAINDIR}/pixel.o ${MAINDIR}/portable.o \ +${MAINDIR}/remote.o ${MAINDIR}/RTC.o ${MAINDIR}/scanline.o ${MAINDIR}/simpleFilter.o \ +${MAINDIR}/snd_interp.o ${MAINDIR}/Sound.o ${MAINDIR}/Sram.o ${MAINDIR}/Text.o \ +${MAINDIR}/unzip.o ${MAINDIR}/Util.o ${MAINDIR}/exprNode.o ${MAINDIR}/getopt.o \ +${MAINDIR}/getopt1.o ${MAINDIR}/memgzio.o ${MAINDIR}/hq3x_16.o ${MAINDIR}/hq3x_32.o \ +${MAINDIR}/hq4x_16.o ${MAINDIR}/hq4x_32.o ${MAINDIR}/expr-lex.o ${MAINDIR}/expr.o + +DMGOBJ=${DMGDIR}/GB.o ${DMGDIR}/gbCheats.o ${DMGDIR}/gbDis.o ${DMGDIR}/gbGfx.o \ +${DMGDIR}/gbGlobals.o ${DMGDIR}/gbMemory.o ${DMGDIR}/gbPrinter.o ${DMGDIR}/gbSGB.o \ +${DMGDIR}/gbSound.o + +SDLOBJ=${SDLDIR}/debugger.o ${SDLDIR}/SDL.o ${SDLDIR}/dummy.o + +OBJECTS=${MAINOBJ} ${DMGOBJ} ${SDLOBJ} +LIB=${RESAMPLEDIR}/libresample.a + +.SUFFIXES: .c .cpp + +%.o: %.c + ${CC} ${CFLAGS} -o $@ -c $< + +%.o: %.cpp + ${CPPC} ${CXXFLAGS} -o $@ -c $< + +%.o: %.asm + ${ASM} ${ASMFLAGS} -o $@ $< + +ALL: vba + +vba: ${OBJECTS} ${LIB} + $(CPPC) -o $@ ${OBJECTS} ${LIB} ${LFLAGS} + +${RESAMPLEDIR}/libresample.a: + make -C ${RESAMPLEDIR} -f Make + +clean: + rm -f vba ${OBJECTS} ${LIB} diff --git a/trunk/src/expr-lex.cpp b/trunk/src/expr-lex.cpp new file mode 100644 index 00000000..6bc20685 --- /dev/null +++ b/trunk/src/expr-lex.cpp @@ -0,0 +1,1591 @@ +#line 2 "expr-lex.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvsroot/vba/VisualBoyAdvance/src/expr-lex.cpp,v 1.4 2006/09/03 21:52:25 kxu 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 +#define fileno _fileno +#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 --git a/trunk/src/expr.cpp b/trunk/src/expr.cpp new file mode 100644 index 00000000..25c68f69 --- /dev/null +++ b/trunk/src/expr.cpp @@ -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 "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; +#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 --git a/trunk/src/expr.cpp.h b/trunk/src/expr.cpp.h new file mode 100644 index 00000000..9b3fdc30 --- /dev/null +++ b/trunk/src/expr.cpp.h @@ -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 --git a/trunk/src/exprNode.cpp b/trunk/src/exprNode.cpp new file mode 100644 index 00000000..cc38c2a2 --- /dev/null +++ b/trunk/src/exprNode.cpp @@ -0,0 +1,415 @@ +// 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 "GBA.h" +#include "Port.h" +#include "elf.h" +#include "exprNode.h" + +#ifndef __GNUC__ +#define strdup _strdup +#endif + +extern char *yytext; + +#define debuggerReadMemory(addr) \ + READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +const void *exprNodeCleanUpList[100]; +int exprNodeCleanUpCount = 0; +Type exprNodeType = { 0, TYPE_base, "int", DW_ATE_signed, 4, 0, {0}, 0 }; + +void exprNodeClean(const void *m) +{ + exprNodeCleanUpList[exprNodeCleanUpCount++] = m; +} + +void exprNodeCleanUp() +{ + for(int i = 0; i < exprNodeCleanUpCount; i++) { + free((void *)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 --git a/trunk/src/exprNode.h b/trunk/src/exprNode.h new file mode 100644 index 00000000..8295b486 --- /dev/null +++ b/trunk/src/exprNode.h @@ -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; + const 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 --git a/trunk/src/libresample-0.1.3/Make b/trunk/src/libresample-0.1.3/Make new file mode 100644 index 00000000..419614d3 --- /dev/null +++ b/trunk/src/libresample-0.1.3/Make @@ -0,0 +1,7 @@ +ALL: libresample.a + +Makefile: + ./configure + +libresample.a: Makefile + make diff --git a/trunk/src/sdl/SDL.cpp b/trunk/src/sdl/SDL.cpp new file mode 100644 index 00000000..a4ed4d8b --- /dev/null +++ b/trunk/src/sdl/SDL.cpp @@ -0,0 +1,3456 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005-2006 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 +#include "../GBA.h" +#include "../agbprint.h" +#include "../Flash.h" +#include "../Port.h" +#include "debugger.h" +#include "../RTC.h" +#include "../Sound.h" +#include "../Text.h" +#include "../unzip.h" +#include "../Util.h" +#include "../gb/gb.h" +#include "../gb/gbGlobals.h" + +#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 bool soundEcho; +extern bool soundLowPass; +extern bool 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 Pixelate(u8*,u32,u8*,u8*,u32,int,int); +extern void Pixelate32(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 Simple2x(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); +extern int gbHardware; + +struct EmulatedSystem emulator = { + 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; + +int filter = 0; +u8 *delta = NULL; + +int sdlPrintUsage = 0; +int disableMMX = 0; + +int cartridgeType = 3; +int sizeOption = 0; +int captureFormat = 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 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 SYSMSG_BUFFER_SIZE 1024 + +#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 } +}; + +bool sdlMotionButtons[4] = { false, false, false, false }; + +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 sdlMirroringEnable = 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 = false; +char screenMessageBuffer[21]; +u32 screenMessageTime = 0; + +// Patch #1382692 by deathpudding. +SDL_sem *sdlBufferLock = NULL; +SDL_sem *sdlBufferFull = NULL; +SDL_sem *sdlBufferEmpty = NULL; +u8 sdlBuffer[4096]; +int sdlSoundLen = 0; + +char *arg0; + +#ifndef C_CORE +u8 sdlStretcher[16384]; +int sdlStretcherPos; +#else +void (*sdlStretcher)(u8 *, u8*) = NULL; +#endif + +enum { + KEY_LEFT, KEY_RIGHT, + KEY_UP, KEY_DOWN, + KEY_BUTTON_A, KEY_BUTTON_B, + KEY_BUTTON_START, KEY_BUTTON_SELECT, + KEY_BUTTON_L, KEY_BUTTON_R, + KEY_BUTTON_SPEED, KEY_BUTTON_CAPTURE +}; + +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' }, + { NULL, no_argument, NULL, 0 } +}; + +extern bool CPUIsGBAImage(char *); +extern bool gbIsGameboyRom(char *); + +#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: + case 2: + case 4: + break; + default: + fprintf(stderr, "Unknown sound quality %d. Defaulting to 22Khz\n", + soundQuality); + soundQuality = 2; + break; + } + } else if(!strcmp(key, "soundOff")) { + soundOffFlag = sdlFromHex(value) ? true : false; + } else if(!strcmp(key, "soundEnable")) { + int res = sdlFromHex(value) & 0x30f; + soundEnable(res); + soundDisable(~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 { + 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; + } else if(!strcmp(token, "mirroringEnabled")) { + mirroringEnable = (atoi(value) == 0 ? false : true); + } + } + } + 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(emulator.emuWriteState) + emulator.emuWriteState(stateName); + + sprintf(stateName, "Wrote state %d", num+1); + systemScreenMessage(stateName); + + systemDrawScreen(); +} + +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(emulator.emuReadState) + emulator.emuReadState(stateName); + + sprintf(stateName, "Loaded state %d", num+1); + systemScreenMessage(stateName); + + systemDrawScreen(); +} + +void sdlWriteBattery() +{ + char buffer[1048]; + + if(batteryDir[0]) + sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); + else + sprintf(buffer, "%s.sav", filename); + + emulator.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 = emulator.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]) + sdlButtons[j][i] = down; + } + } + } + for(i = 0 ; i < 4; i++) { + if((motion[i] & 0xf000) == 0) { + if(key == motion[i]) + sdlMotionButtons[i] = down; + } + } +} + +void sdlUpdateJoyButton(int which, + int button, + bool pressed) +{ + int i; + for(int j = 0; j < 4; j++) { + for(i = 0; i < 12; i++) { + int dev = (joypad[j][i] >> 12); + int b = joypad[j][i] & 0xfff; + if(dev) { + dev--; + + if((dev == which) && (b >= 128) && (b == (button+128))) { + sdlButtons[j][i] = pressed; + } + } + } + } + for(i = 0; i < 4; i++) { + int dev = (motion[i] >> 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; + } + sdlButtons[j][i] = (v ? true : false); + } + } + } + } + for(i = 0; i < 4; i++) { + int dev = (motion[i] >> 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)) { + sdlButtons[j][i] = (a & 1) ? (value > 16384) : (value < -16384); + } + } + } + } + for(i = 0; i < 4; i++) { + int dev = (motion[i] >> 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) { + emulator.emuReset(); + + systemScreenMessage("Reset"); + } + } + break; + case SDLK_b: + if(!(event.key.keysym.mod & MOD_NOCTRL) && + (event.key.keysym.mod & KMOD_CTRL)) { + if(emulating && emulator.emuReadMemState && rewindMemory + && rewindCount) { + rewindPos = (rewindPos - 1) & 7; + emulator.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)) { + const char *disableMessages[4] = + { "autofire A disabled", + "autofire B disabled", + "autofire R disabled", + "autofire L disabled"}; + const 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\ +"); +} + +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 '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); + if(t < 5 || t > 1000) + t = 0; + 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) { + char *szFile = argv[optind]; + u32 len = strlen(szFile); + if (len > SYSMSG_BUFFER_SIZE) + { + fprintf(stderr,"%s :%s: File name too long\n",argv[0],szFile); + exit(-1); + } + + 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); + } + cartridgeType = (int)type; + + if(type == IMAGE_GB) { + failed = !gbLoadRom(szFile); + if(!failed) { + gbGetHardwareType(); + + // used for the handling of the gb Boot Rom + if (gbHardware & 5) + { + char tempName[0x800]; + strcpy(tempName, arg0); + char *p = strrchr(tempName, '\\'); + if(p) { *p = 0x00; } + strcat(tempName, "\\DMG_ROM.bin"); + fprintf(stderr, "%s\n", tempName); + gbCPUInit(tempName, useBios); + } + else useBios = false; + + gbReset(); + cartridgeType = IMAGE_GB; + emulator = 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) { + sdlApplyPerImagePreferences(); + + doMirroring(mirroringEnable); + + cartridgeType = 0; + emulator = GBASystem; + + /* disabled due to problems + if(removeIntros && rom != NULL) { + WRITE32LE(&rom[0], 0xea00002e); + } + */ + + CPUInit(biosFileName, useBios); + 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); + } + } 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 * 241 * 162); + ioMem = (u8 *)calloc(1, 0x400); + + emulator = GBASystem; + + CPUInit(biosFileName, useBios); + CPUReset(); + } + + sdlReadBattery(); + + 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(cartridgeType == 0) { + srcWidth = 240; + srcHeight = 160; + systemFrameSkip = frameSkip; + } else if (cartridgeType == 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); + } else { + Init_2xSaI(555); + } + srcPitch = srcWidth * 2+4; + } else { + if(systemColorDepth != 32) + filterFunction = NULL; + Init_2xSaI(32); + if(systemColorDepth == 32) + srcPitch = srcWidth*4 + 4; + else + srcPitch = srcWidth*3; + } + + utilUpdateSystemColorMaps(); + + 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 = Pixelate; + break; + case 6: + filterFunction = MotionBlur; + break; + case 7: + filterFunction = AdMame2x; + break; +// case 8: +// filterFunction = Simple2x; +// 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 = Pixelate32; + 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); + } + + emulating = 1; + renderedFrames = 0; + + if(!soundOffFlag) + soundInit(); + + autoFrameSkipLastTime = throttleLastTime = systemGetClock(); + + SDL_WM_SetCaption("VisualBoyAdvance", NULL); + + while(emulating) { + if(!paused && active) { + if(debugger && emulator.emuHasDebugger) + dbgMain(); + else { + emulator.emuMain(emulator.emuCount); + if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) { + rewindCount++; + if(rewindCount > 8) + rewindCount = 8; + if(emulator.emuWriteMemState && + emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE], + REWIND_SIZE)) { + rewindPos = (rewindPos + 1) & 7; + if(rewindCount == 8) + rewindTopPos = (rewindTopPos + 1) & 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(); + emulator.emuCleanUp(); + } + + if(delta) { + free(delta); + delta = NULL; + } + + SDL_Quit(); + return 0; +} + +void systemMessage(int num, const char *msg, ...) +{ + char buffer[SYSMSG_BUFFER_SIZE*2]; + va_list valist; + + va_start(valist, msg); + vsprintf(buffer, msg, valist); + + fprintf(stderr, "%s\n", buffer); + va_end(valist); +} + +void systemDrawScreen() +{ + renderedFrames++; + + if(yuv) { + Draw_Overlay(surface, sizeOption+1); + return; + } + + SDL_LockSurface(surface); + + if(screenMessage) { + if(cartridgeType == 1 && gbBorderOn) { + gbSgbRenderBorder(); + } + if(((systemGetClock() - screenMessageTime) < 3000) && + !disableStatusMessages) { + drawText(pix, srcPitch, 10, srcHeight - 20, + screenMessageBuffer); + } else { + screenMessage = 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; +} + +u32 systemReadJoypad(int which) +{ + if(which < 0 || which > 3) + which = sdlDefaultJoypad; + + u32 res = 0; + + if(sdlButtons[which][KEY_BUTTON_A]) + res |= 1; + if(sdlButtons[which][KEY_BUTTON_B]) + res |= 2; + if(sdlButtons[which][KEY_BUTTON_SELECT]) + res |= 4; + if(sdlButtons[which][KEY_BUTTON_START]) + res |= 8; + if(sdlButtons[which][KEY_RIGHT]) + res |= 16; + if(sdlButtons[which][KEY_LEFT]) + res |= 32; + if(sdlButtons[which][KEY_UP]) + res |= 64; + if(sdlButtons[which][KEY_DOWN]) + res |= 128; + if(sdlButtons[which][KEY_BUTTON_R]) + res |= 256; + if(sdlButtons[which][KEY_BUTTON_L]) + res |= 512; + + // 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; + + if(autoFire) { + res &= (~autoFire); + if(autoFireToggle) + res |= autoFire; + autoFireToggle = !autoFireToggle; + } + + return res; +} + +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); + } +} + +void systemFrame() +{ +} + +void system10Frames(int rate) +{ + u32 time = systemGetClock(); + if(!wasPaused && autoFrameSkip && !throttle) { + u32 diff = time - autoFrameSkipLastTime; + int speed = 100; + + if(diff) + speed = (1000000/rate)/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/(rate*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; +} + +void 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"); +} + +void soundCallback(void *,u8 *stream,int len) +{ + if (!emulating) + return; + + // Patch #1382692 by deathpudding. + /* since this is running in a different thread, speedup and + * throttle can change at any time; save the value so locks + * stay in sync */ + bool lock = (!speedup && !throttle) ? true : false; + + if (lock) + SDL_SemWait (sdlBufferFull); + + SDL_SemWait (sdlBufferLock); + memcpy (stream, sdlBuffer, len); + sdlSoundLen = 0; + SDL_SemPost (sdlBufferLock); + + if (lock) + SDL_SemPost (sdlBufferEmpty); +} + +void systemWriteDataToSoundBuffer() +{ + // Patch #1382692 by deathpudding. + if (SDL_GetAudioStatus () != SDL_AUDIO_PLAYING) + SDL_PauseAudio (0); + + if ((sdlSoundLen + soundBufferLen) >= 2048*2) { + bool lock = (!speedup && !throttle) ? true : false; + + if (lock) + SDL_SemWait (sdlBufferEmpty); + + SDL_SemWait (sdlBufferLock); + int copied = 2048*2 - sdlSoundLen; + memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, copied); + sdlSoundLen = 2048*2; + SDL_SemPost (sdlBufferLock); + + if (lock) { + SDL_SemPost (sdlBufferFull); + + /* wait for buffer to be dumped by soundCallback() */ + SDL_SemWait (sdlBufferEmpty); + SDL_SemPost (sdlBufferEmpty); + + SDL_SemWait (sdlBufferLock); + memcpy (sdlBuffer, ((u8 *)soundFinalWave) + copied, + soundBufferLen - copied); + sdlSoundLen = soundBufferLen - copied; + SDL_SemPost (sdlBufferLock); + } + else { + SDL_SemWait (sdlBufferLock); + memcpy (sdlBuffer, ((u8 *) soundFinalWave) + copied, soundBufferLen); + SDL_SemPost (sdlBufferLock); + } + } + else { + SDL_SemWait (sdlBufferLock); + memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, soundBufferLen); + sdlSoundLen += soundBufferLen; + SDL_SemPost (sdlBufferLock); + } +} + +bool systemSoundInit() +{ + SDL_AudioSpec audio; + + switch(soundQuality) { + case 1: + audio.freq = 44100; + soundBufferLen = 1470*2; + break; + case 2: + audio.freq = 22050; + soundBufferLen = 736*2; + break; + case 4: + audio.freq = 11025; + soundBufferLen = 368*2; + break; + } + audio.format=AUDIO_S16SYS; + audio.channels = 2; + audio.samples = 1024; + audio.callback = soundCallback; + audio.userdata = NULL; + if(SDL_OpenAudio(&audio, NULL)) { + fprintf(stderr,"Failed to open audio: %s\n", SDL_GetError()); + return false; + } + soundBufferTotalLen = soundBufferLen*10; + // Patch #1382692 by deathpudding. + sdlBufferLock = SDL_CreateSemaphore (1); + sdlBufferFull = SDL_CreateSemaphore (0); + sdlBufferEmpty = SDL_CreateSemaphore (1); + sdlSoundLen = 0; + systemSoundOn = true; + return true; +} + +void systemSoundShutdown() +{ + // Patch #1382692 by deathpudding. + SDL_CloseAudio (); //TODO: fix freeze + SDL_DestroySemaphore (sdlBufferLock); + SDL_DestroySemaphore (sdlBufferFull); + SDL_DestroySemaphore (sdlBufferEmpty); + sdlBufferLock = NULL; + sdlBufferFull = NULL; + sdlBufferEmpty = NULL; +} + +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; + } +} + +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) +{ + screenMessage = true; + screenMessageTime = systemGetClock(); + if(strlen(msg) > 20) { + strncpy(screenMessageBuffer, msg, 20); + screenMessageBuffer[20] = 0; + } else + strcpy(screenMessageBuffer, msg); +} + +bool systemCanChangeSoundQuality() +{ + return false; +} + +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); +} + +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(cartridgeType == 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; + } +} diff --git a/trunk/src/sdl/debugger.cpp b/trunk/src/sdl/debugger.cpp new file mode 100644 index 00000000..8d742449 --- /dev/null +++ b/trunk/src/sdl/debugger.cpp @@ -0,0 +1,2663 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 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. + +// Parts adapted from VBA-H (VBA for Hackers) by LabMaster + +#include +#include +#include +#include + +#include "../GBA.h" +#include "../Port.h" +#include "../armdis.h" +#include "../elf.h" +#include "../exprNode.h" + +extern bool debugger; +extern int emulating; +extern void sdlWriteState(int num); +extern void sdlReadState(int num); + +extern struct EmulatedSystem emulator; + +#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; + + u32 cond_address; + char cond_rel; + u32 cond_value; + int cond_size; + bool ia1; + bool ia2; +}; + +struct DebuggerCommand { + const char *name; + void (*function)(int,char **); + const char *help; + const char *syntax; +}; + +unsigned int SearchStart = 0xFFFFFFFF; +unsigned int SearchMaxMatches = 5; +u8 SearchData [64]; // It doesn't make much sense to search for more than 64 bytes +unsigned int SearchLength = 0; +unsigned int SearchResults; + +static void debuggerContinueAfterBreakpoint(); +void debuggerDoSearch(); +unsigned int AddressToGBA(u8* mem); + +static void debuggerHelp(int,char **); +static void debuggerNext(int,char **); +static void debuggerContinue(int, char **); +static void debuggerRegisters(int, char **); +static void debuggerBreak(int, char **); +static void debuggerBreakDelete(int, char **); +static void debuggerBreakList(int, char **); +static void debuggerBreakArm(int, char **); +static void debuggerBreakThumb(int, char **); +static void debuggerBreakChange(int, char **); +static void debuggerBreakChangeClear(int, char **); +static void debuggerBreakWriteClear(int, char **); +static void debuggerBreakWrite(int, char **); +static void debuggerDebug(int, char **); +static void debuggerDisassemble(int, char **); +static void debuggerDisassembleArm(int, char **); +static void debuggerDisassembleThumb(int, char **); +static void debuggerEditByte(int, char **); +static void debuggerEditHalfWord(int, char **); +static void debuggerEditRegister(int, char **); +static void debuggerEdit(int, char **); +static void debuggerFileDisassemble(int, char **); +static void debuggerFileDisassembleArm(int, char **); +static void debuggerFileDisassembleThumb(int, char **); +static void debuggerFindText(int, char **); +static void debuggerFindHex(int, char **); +static void debuggerFindResume(int, char **); +static void debuggerIo(int, char **); +static void debuggerLast(int, char **); +static void debuggerLocals(int, char **); +static void debuggerMemoryByte(int, char **); +static void debuggerMemoryHalfWord(int, char **); +static void debuggerMemory(int, char **); +static void debuggerPrint(int, char **); +static void debuggerQuit(int, char **); +static void debuggerSetRadix(int, char **); +static void debuggerSymbols(int, char **); +static void debuggerVerbose(int, char **); +static void debuggerWhere(int, char **); + +static void debuggerReadState(int, char **); +static void debuggerWriteState(int, char **); +static void debuggerDumpLoad(int, char**); +static void debuggerDumpSave(int, char**); +static void debuggerCondValidate(int n, char **args, int start); +static bool debuggerCondEvaluate(int num); +static void debuggerCondBreakThumb(int, char **); +static void debuggerCondBreakArm(int, char **); + +static DebuggerCommand debuggerCommands[] = { + { "?", debuggerHelp, "Show this help information. Type ? for command help", "[]" }, + { "ba", debuggerBreakArm, "Add an ARM breakpoint", "
" }, + { "bd", debuggerBreakDelete,"Delete a breakpoint", "" }, + { "bl", debuggerBreakList, "List breakpoints" }, + { "bpc", debuggerBreakChange, "Break on change", "
" }, + { "bpcc", debuggerBreakChangeClear, "Clear break on change", "[
]" }, + { "bpw", debuggerBreakWrite, "Break on write", "
" }, + { "bpwc", debuggerBreakWriteClear, "Clear break on write", "[
]" }, + { "break", debuggerBreak, "Add a breakpoint on the given function", "||" }, + { "bt", debuggerBreakThumb, "Add a THUMB breakpoint", "
" }, + { "c", debuggerContinue, "Continue execution" , NULL }, + { "cba", debuggerCondBreakArm, "Add a conditional ARM breakpoint", "
$
|R []\n either ==, !=, <, >, <=, >=\n either b, h, w" }, + { "cbt", debuggerCondBreakThumb, "Add a conditional THUMB breakpoint", "
$
|R []\n either ==, !=, <, >, <=, >=\n either b, h, w" }, + { "d", debuggerDisassemble, "Disassemble instructions", "[
[]]" }, + { "da", debuggerDisassembleArm, "Disassemble ARM instructions", "[
[]]" }, + { "dload",debuggerDumpLoad, "Load raw data dump from file","
"}, + { "dsave",debuggerDumpSave, "Dump raw data to file","
"}, + { "dt", debuggerDisassembleThumb, "Disassemble THUMB instructions", "[
[]]" }, + { "eb", debuggerEditByte, "Modify memory location (byte)", "
" }, + { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","
" }, + { "er", debuggerEditRegister, "Modify register", " " }, + { "ew", debuggerEdit, "Modify memory location (word)", "
" }, + { "fd", debuggerFileDisassemble, "Disassemble instructions to file", " [
[]]" }, + { "fda", debuggerFileDisassembleArm, "Disassemble ARM instructions to file", " [
[]]" }, + { "fdt", debuggerFileDisassembleThumb, "Disassemble THUMB instructions to file", " [
[]]" }, + { "ft", debuggerFindText, "Search memory for ASCII-string.", " [] " }, + { "fh", debuggerFindHex, "Search memory for hex-string.", " [] " }, + { "fr", debuggerFindResume, "Resume current search.", "[]" }, + { "h", debuggerHelp, "Show this help information. Type h for command help", "[]" }, + { "io", debuggerIo, "Show I/O registers status", "[video|video2|dma|timer|misc]" }, + { "last", debuggerLast, "Trigger the display of the last registers states", NULL }, + { "load", debuggerReadState, "Load a savegame", "" }, + { "locals", debuggerLocals, "Show local variables", NULL }, + { "mb", debuggerMemoryByte, "Show memory contents (bytes)", "
" }, + { "mh", debuggerMemoryHalfWord, "Show memory contents (half-words)", "
"}, + { "mw", debuggerMemory, "Show memory contents (words)", "
" }, + { "n", debuggerNext, "Execute the next instruction", "[]" }, + { "print", debuggerPrint, "Print the value of a expression (if known)", "[/x|/o|/d] " }, + { "q", debuggerQuit, "Quit the emulator", NULL }, + { "r", debuggerRegisters, "Show ARM registers", NULL }, + { "radix", debuggerSetRadix, "Set the print radix", "" }, + { "save", debuggerWriteState, "Create a savegame", "" }, + { "symbols", debuggerSymbols, "List symbols", "[]" }, +#ifndef FINAL_VERSION + { "trace", debuggerDebug, "Set the trace level", "" }, +#endif +#ifdef DEV_VERSION + { "verbose", debuggerVerbose, "Change verbose setting", "" }, +#endif + { "where", debuggerWhere, "Show the call chain (if available)", NULL }, + { NULL, NULL, NULL, NULL} // end marker +}; + +breakpointInfo debuggerBreakpointList[100]; + +int debuggerNumOfBreakpoints = 0; +bool debuggerAtBreakpoint = false; +int debuggerBreakpointNumber = 0; +int debuggerRadix = 0; + +extern u32 cpuPrefetch[2]; + +#define ARM_PREFETCH \ + {\ + cpuPrefetch[0] = debuggerReadMemory(armNextPC);\ + cpuPrefetch[1] = debuggerReadMemory(armNextPC+4);\ + } + +#define THUMB_PREFETCH \ + {\ + cpuPrefetch[0] = debuggerReadHalfWord(armNextPC);\ + cpuPrefetch[1] = debuggerReadHalfWord(armNextPC+2);\ + } + +static void debuggerPrefetch() +{ + if(armState) { + ARM_PREFETCH; + } else { + THUMB_PREFETCH; + } +} + +static 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)); +} + +static 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); + } +} + +static 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); + } +} + +static void debuggerUsage(const char *cmd) +{ + for(int i = 0; ; i++) { + if(debuggerCommands[i].name) { + if(!strcmp(debuggerCommands[i].name, cmd)) { + printf("%s %s\n\n%s\n", + debuggerCommands[i].name, + debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "", + debuggerCommands[i].help); + break; + } + } else { + printf("Unrecognized command '%s'.", cmd); + break; + } + } +} + +static 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); + } +} + +static const 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; +} + +static void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32); +static void debuggerPrintValueInternal(Function *f, Type *t, + int bitSize, int bitOffset, + u32 objLocation, LocationType type); + +static 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; +} + +static void debuggerPrintPointer(Type *t, u32 value) +{ + printf("(%s)0x%08x", debuggerPrintType(t), value); +} + +static void debuggerPrintReference(Type *t, u32 value) +{ + printf("(%s)0x%08x", debuggerPrintType(t), value); +} + +static void debuggerPrintFunction(Type *t, u32 value) +{ + printf("(%s)0x%08x", debuggerPrintType(t), value); +} + +static void debuggerPrintArray(Type *t, u32 value) +{ + // todo + printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value); +} + +static 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); + } +} + +static 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("}"); +} + +static 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("}"); +} + +static 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) { + printf(m->name); + return; + } + } + printf("(UNKNOWN VALUE) %d", value); +} + +static 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; + } +} + +static 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); +} + +static void debuggerPrintValue(Function *f, Object *o) +{ + debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0); + + printf("\n"); +} + +static void debuggerSymbols(int argc, char **argv) +{ + int i = 0; + u32 value; + u32 size; + int type; + bool match = false; + int matchSize = 0; + const char *matchStr = NULL; + + if(argc == 2) { + match = true; + matchSize = strlen(argv[1]); + matchStr = argv[1]; + } + printf("Symbol Value Size Type \n"); + printf("-------------------- ------- -------- -------\n"); + const 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++; + } +} + +static 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); + } +} + +static 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; + } + } + + const char *s = argc == 2 ? argv[1] : argv[2]; + + extern const 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; + } +} + +static 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; + } + } +} + +static 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"); +} + +static 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"); +} + +static void debuggerWhere(int n, char **args) +{ + void elfPrintCallChain(u32); + elfPrintCallChain(armNextPC); +} + +static 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"); + } +} + +static 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 { + debuggerPrefetch(); + emulator.emuMain(1); + } + } + debuggerDisableBreakpoints(); + Function *f = NULL; + CompileUnit *u = NULL; + u32 a = armNextPC; + if(elfGetCurrentFunction(a, &f, &u)) { + const char *file; + int line = elfFindLine(u, f, a, &file); + + printf("File %s, function %s, line %d\n", file, f->name, + line); + } + debuggerRegisters(0, NULL); +} + +static void debuggerContinue(int n, char **args) +{ + if(debuggerAtBreakpoint) + debuggerContinueAfterBreakpoint(); + debuggerEnableBreakpoints(false); + debugger = false; + debuggerPrefetch(); +} + +/*extern*/ void debuggerSignal(int sig,int number) +{ + switch(sig) { + case 4: + { + printf("Illegal instruction at %08x\n", armNextPC); + debugger = true; + } + break; + case 5: + { + bool cond = debuggerCondEvaluate(number & 255); + if(cond) { + printf("Breakpoint %d reached\n", number); + debugger = true; + } else { + debuggerDisableBreakpoints(); + debuggerPrefetch(); + emulator.emuMain(1); + debuggerEnableBreakpoints(false); + return; + } + debuggerAtBreakpoint = true; + debuggerBreakpointNumber = number; + debuggerDisableBreakpoints(); + + Function *f = NULL; + CompileUnit *u = NULL; + + if(elfGetCurrentFunction(armNextPC, &f, &u)) { + const 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; + } +} + +static 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)); + } +} + +static void debuggerBreakDelete(int n, char **args) +{ + if(n == 2) { + int n = 0; + sscanf(args[1], "%d", &n); + if(n >= 0 && n < debuggerNumOfBreakpoints) { + printf("Deleting breakpoint %d (%d)\n", 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 + printf("No breakpoints are set\n"); + } else + debuggerUsage("bd"); +} + +static void debuggerBreak(int n, char **args) +{ + if(n == 2) { + u32 address = 0; + u32 value = 0; + int type = 0; + const char *s = args[1]; + char c = *s; + if(strchr(s, ':')) { + const 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"); +} + +static 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"); +} + +static 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"); +} + +/*extern*/ void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value, + int size, int t) +{ + const char *type = "write"; + if(t == 2) + type = "change"; + + if(size == 2) + printf("Breakpoint (on %s) address %08x old:%08x new:%08x\n", + type, address, oldvalue, value); + else if(size == 1) + printf("Breakpoint (on %s) address %08x old:%04x new:%04x\n", + type, address, (u16)oldvalue,(u16)value); + else + printf("Breakpoint (on %s) address %08x old:%02x new:%02x\n", + type, address, (u8)oldvalue, (u8)value); + debugger = true; +} + +static void debuggerBreakWriteClear(int n, char **args) +{ + if(n == 3) { + u32 address = 0; + sscanf(args[1], "%x", &address); + int n = 0; + sscanf(args[2], "%d", &n); + + if (! ((address >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + printf("Invalid address: %08x\n", address); + return; + } + + u32 final = address + n; + switch(address >> 24) { + case 2: + { + address &= 0x3ffff; + final &= 0x3ffff; + for(u32 i = address; i < final; i++) + if(freezeWorkRAM[i] == 1) + freezeWorkRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x2000000+address, 0x2000000+final); + } + break; + case 3: + { + address &= 0x7fff; + final &= 0x7fff; + for(u32 i = address; i < final; i++) + if(freezeInternalRAM[i] == 1) + freezeInternalRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x3000000+address, 0x3000000+final); + } + break; + case 5: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezePRAM[i] == 1) + freezePRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x5000000+address, 0x5000000+final); + } + break; + case 6: + { + if (address > 0x6010000) { + address &= 0x17fff; + final &= 0x17fff; + } else { + address &= 0xffff; + final &= 0xffff; + } + + for (u32 i = address; i < final; i++) + if(freezeVRAM[i] == 1) + freezeVRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x06000000+address, 0x06000000+final); + } + break; + case 7: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezeOAM[i] == 1) + freezeOAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x7000000+address, 0x7000000+final); + } + break; + } + } else if(n == 1) { + int i; + for(i = 0; i < 0x40000; i++) + if(freezeWorkRAM[i] == 1) + freezeWorkRAM[i] = 0; + for(i = 0; i < 0x8000; i++) + if(freezeInternalRAM[i] == 1) + freezeInternalRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezePRAM[i] == 1) + freezePRAM[i] = 0; + for(i = 0; i< 0x18000; i++) + if(freezeVRAM[i] == 1) + freezeVRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezeOAM[i] == 1) + freezeOAM[i] = 0; + + printf("Cleared all break on write\n"); + } else + debuggerUsage("bpwc"); +} + +static 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 >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + 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; + } else if(address < 0x05000400 && final > 0x05000400) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x06018000 && final > 0x06018000) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x07000400 && final > 0x07000400) { + printf("Invalid byte count: %d\n", n); + return; + } + + printf("Added break on write at %08x for %d bytes\n", address, n); + + switch(address >> 24) { + case 2: + for (int i = 0; i < n; i++) + freezeWorkRAM[(address + i) & 0x3ffff] = 1; + break; + case 3: + for (int i = 0; i < n; i++) + freezeInternalRAM[(address + i) & 0x7fff] = 1; + break; + case 5: + for (int i = 0; i < n; i++) + freezePRAM[(address + i) & 0x3ff] = 1; + break; + case 6: + // address/range must be valid, so we can use a lazy mask + for (int i = 0; i < n; i++) + freezeVRAM[(address + i) & 0x1ffff] = 1; + break; + case 7: + for (int i = 0; i < n; i++) + freezeOAM[(address + i) & 0x3ff] = 1; + break; + } + + } else + debuggerUsage("bpw"); +} + +static void debuggerBreakChangeClear(int n, char **args) +{ + if(n == 3) { + u32 address = 0; + sscanf(args[1], "%x", &address); + int n = 0; + sscanf(args[2], "%d", &n); + + if (! ((address >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + printf("Invalid address: %08x\n", address); + return; + } + + u32 final = address + n; + switch(address >> 24) { + case 2: + { + address &= 0x3ffff; + final &= 0x3ffff; + for(u32 i = address; i < final; i++) + if(freezeWorkRAM[i] == 2) + freezeWorkRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x2000000+address, 0x2000000+final); + } + break; + case 3: + { + address &= 0x7fff; + final &= 0x7fff; + for(u32 i = address; i < final; i++) + if(freezeInternalRAM[i] == 2) + freezeInternalRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x3000000+address, 0x3000000+final); + } + break; + case 5: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezePRAM[i] == 2) + freezePRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x5000000+address, 0x5000000+final); + } + break; + case 6: + { + if (address > 0x6010000) { + address &= 0x17fff; + final &= 0x17fff; + } else { + address &= 0xffff; + final &= 0xffff; + } + for(u32 i = address; i < final; i++) + if(freezeVRAM[i] == 2) + freezeVRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x3000000+address, 0x3000000+final); + } + break; + case 7: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezeOAM[i] == 2) + freezeOAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x7000000+address, 0x7000000+final); + } + break; + } + } else if(n == 1) { + int i; + for(i = 0; i < 0x40000; i++) + if(freezeWorkRAM[i] == 2) + freezeWorkRAM[i] = 0; + for(i = 0; i < 0x8000; i++) + if(freezeInternalRAM[i] == 2) + freezeInternalRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezePRAM[i] == 2) + freezePRAM[i] = 0; + for(i = 0; i < 0x18000; i++) + if(freezeVRAM[i] == 2) + freezeVRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezeOAM[i] == 2) + freezeOAM[i] = 0; + + printf("Cleared all break on change\n"); + } else + debuggerUsage("bpcc"); +} + +static void debuggerBreakChange(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 >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + 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; + } else if(address < 0x6018000 && final > 0x6018000) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x7000400 && final > 0x7000400) { + printf("Invalid byte count: %d\n", n); + return; + } + printf("Added break on change at %08x for %d bytes\n", address, n); + + switch(address >> 24) { + case 2: + for (int i = 0; i < n; i++) + freezeWorkRAM[(address + i) & 0x3ffff] = 2; + break; + case 3: + for (int i = 0; i < n; i++) + freezeInternalRAM[(address + i) & 0x7fff] = 2; + break; + case 5: + for (int i = 0; i < n; i++) + freezePRAM[(address + i) & 0x3ff] = 2; + break; + case 6: + // address/range must be valid, so we can use a lazy mask + for (int i = 0; i < n; i++) + freezeVRAM[(address + i) & 0x1ffff] = 2; + break; + case 7: + for (int i = 0; i < n; i++) + freezeOAM[(address + i) & 0x3ff] = 2; + break; + } + + } else + debuggerUsage("bpc"); +} + +static void debuggerDisassembleArm(FILE *f, u32 pc, int count) +{ + char buffer[80]; + int i = 0; + u32 len = 0; + char format[30]; + for(i = 0; i < count; i++) { + size_t 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); + fprintf(f, format, addr, elfGetAddressSymbol(addr), buffer); + } +} + +static void debuggerDisassembleThumb(FILE *f, u32 pc, int count) +{ + char buffer[80]; + int i = 0; + u32 len = 0; + char format[30]; + for(i = 0; i < count; i++) { + size_t 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); + fprintf(f, format, addr, elfGetAddressSymbol(addr), buffer); + } +} + +static void debuggerDisassembleArm(int n, char **args) +{ + 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); + } + debuggerDisassembleArm(stdout, pc, count); +} + +static void debuggerDisassembleThumb(int n, char **args) +{ + 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); + } + debuggerDisassembleThumb(stdout, pc, count); +} + +static void debuggerDisassemble(int n, char **args) +{ + if(armState) + debuggerDisassembleArm(n, args); + else + debuggerDisassembleThumb(n, args); +} + +static void debuggerFileDisassembleArm(int n, char **args) +{ + u32 pc = reg[15].I; + pc -= 4; + int count = 20; + if(n < 2) { + debuggerUsage("fda"); + return; + } + FILE *f = fopen(args[1], "w+"); + if(!f) { + printf("Error: cannot open file %s\n", args[1]); + return; + } + if(n >= 3) { + sscanf(args[2], "%x", &pc); + } + if(pc & 3) { + printf("Misaligned address %08x\n", pc); + pc &= 0xfffffffc; + } + if(n >= 4) { + sscanf(args[3], "%d", &count); + } + debuggerDisassembleArm(f, pc, count); + fclose(f); +} + +static void debuggerFileDisassembleThumb(int n, char **args) +{ + u32 pc = reg[15].I; + pc -= 2; + int count = 20; + if(n < 2) { + debuggerUsage("fdt"); + return; + } + FILE *f = fopen(args[1], "w+"); + if(!f) { + printf("Error: cannot open file %s\n", args[1]); + return; + } + + if(n >= 3) { + sscanf(args[2], "%x", &pc); + } + if(pc & 1) { + printf("Misaligned address %08x\n", pc); + pc &= 0xfffffffe; + } + if(n >= 4) { + sscanf(args[3], "%d", &count); + } + debuggerDisassembleThumb(f, pc, count); + fclose(f); +} + +void debuggerFindText(int n, char **args) +{ + if ((n == 4) || (n == 3)) + { + SearchResults = 0; + sscanf(args[1], "%x", &SearchStart); + + if (n == 4) + { + sscanf(args[2], "%u", &SearchMaxMatches); + strncpy((char*) SearchData, args[3], 64); + SearchLength = strlen(args[3]); + } + else if (n == 3) + { + strncpy((char*) SearchData, args[2], 64); + SearchLength = strlen(args[2]); + }; + + if (SearchLength > 64) + { + printf ("Entered string (length: %d) is longer than 64 bytes and was cut.\n", SearchLength); + SearchLength = 64; + }; + + debuggerDoSearch (); + + } else + debuggerUsage("ft"); +}; + +void debuggerFindHex(int n, char **args) +{ + if ((n == 4) || (n == 3)) + { + SearchResults = 0; + sscanf(args[1], "%x", &SearchStart); + + char SearchHex [128]; + if (n == 4) + { + sscanf(args[2], "%u", &SearchMaxMatches); + strncpy(SearchHex, args[3], 128); + SearchLength = strlen(args[3]); + } + else if (n == 3) + { + strncpy(SearchHex, args[2], 128); + SearchLength = strlen(args[2]); + }; + + if (SearchLength & 1) + printf ("Unaligned bytecount: %d,5. Last digit (%c) cut.\n", SearchLength / 2, SearchHex [SearchLength - 1]); + + SearchLength /= 2; + + if (SearchLength > 64) + { + printf ("Entered string (length: %d) is longer than 64 bytes and was cut.\n", SearchLength); + SearchLength = 64; + }; + + for (unsigned int i = 0; i < SearchLength; i++) + { + unsigned int cbuf = 0; + sscanf (&SearchHex [i << 1], "%02x", &cbuf); + SearchData [i] = cbuf; + }; + + debuggerDoSearch (); + + } else + debuggerUsage("fh"); +}; + +void debuggerFindResume(int n, char **args) +{ + if ((n == 1) || (n == 2)) + { + if (SearchLength == 0) + { + printf("Error: No search in progress. Start a search with ft or fh.\n"); + debuggerUsage("fr"); + return; + }; + + if (n == 2) + sscanf(args[1], "%u", &SearchMaxMatches); + + debuggerDoSearch(); + + } else + debuggerUsage("fr"); +}; + +void debuggerDoSearch() +{ + int count = 0; + + while (true) + { + unsigned int final = SearchStart + SearchLength - 1; + u8* end; + u8* start; + + switch (SearchStart >> 24) + { + case 0: + if (final > 0x00003FFF) { SearchStart = 0x02000000; continue; } + else { start = bios + (SearchStart & 0x3FFF); end = bios + 0x3FFF; break; }; + case 2: + if (final > 0x0203FFFF) { SearchStart = 0x03000000; continue; } + else { start = workRAM + (SearchStart & 0x3FFFF); end = workRAM + 0x3FFFF; break; }; + case 3: + if (final > 0x03007FFF) { SearchStart = 0x04000000; continue; } + else { start = internalRAM + (SearchStart & 0x7FFF); end = internalRAM + 0x7FFF; break; }; + case 4: + if (final > 0x040003FF) { SearchStart = 0x05000000; continue; } + else { start = ioMem + (SearchStart & 0x3FF); end = ioMem + 0x3FF; break; }; + case 5: + if (final > 0x050003FF) { SearchStart = 0x06000000; continue; } + else { start = paletteRAM + (SearchStart & 0x3FF); end = paletteRAM + 0x3FF; break; }; + case 6: + if (final > 0x0601FFFF) { SearchStart = 0x07000000; continue; } + else { start = vram + (SearchStart & 0x1FFFF); end = vram + 0x1FFFF; break; }; + case 7: + if (final > 0x070003FF) { SearchStart = 0x08000000; continue; } + else { start = oam + (SearchStart & 0x3FF); end = oam + 0x3FF; break; }; + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + if (final <= 0x09FFFFFF) + { start = rom + (SearchStart & 0x01FFFFFF); end = rom + 0x01FFFFFF; break; }; + default: + printf ("Search completed.\n"); + SearchLength = 0; + return; + }; + + end -= SearchLength - 1; + u8 firstbyte = SearchData [0]; + while (start <= end) + { + while ((start <= end) && (*start != firstbyte)) + start++; + + if (start > end) + break; + + unsigned int p = 1; + while ((start [p] == SearchData [p]) && (p < SearchLength)) + p++; + + if (p == SearchLength) + { + printf ("Search result (%d): %08x\n", count + SearchResults, AddressToGBA (start)); + count++; + if (count == SearchMaxMatches) + { + SearchStart = AddressToGBA (start + p); + SearchResults += count; + return; + }; + + start += p; // assume areas don't overlap; alternative: start++; + } else + start++; + }; + + SearchStart = AddressToGBA (end + SearchLength - 1) + 1; + }; +}; + +unsigned int AddressToGBA(u8* mem) +{ + if(mem >= &bios[0] && mem <= &bios[0x3fff]) + return 0x00000000 + (mem - &bios[0]); + else if(mem >= &workRAM[0] && mem <= &workRAM[0x3ffff]) + return 0x02000000 + (mem - &workRAM[0]); + else if(mem >= &internalRAM[0] && mem <= &internalRAM[0x7fff]) + return 0x03000000 + (mem - &internalRAM[0]); + else if(mem >= &ioMem[0] && mem <= &ioMem[0x3ff]) + return 0x04000000 + (mem - &ioMem[0]); + else if(mem >= &paletteRAM[0] && mem <= &paletteRAM[0x3ff]) + return 0x05000000 + (mem - &paletteRAM[0]); + else if(mem >= &vram[0] && mem <= &vram[0x1ffff]) + return 0x06000000 + (mem - &vram[0]); + else if(mem >= &oam[0] && mem <= &oam[0x3ff]) + return 0x07000000 + (mem - &oam[0]); + else if(mem >= &rom[0] && mem <= &rom[0x1ffffff]) + return 0x08000000 + (mem - &rom[0]); + else + return 0xFFFFFFFF; +}; + +static void debuggerFileDisassemble(int n, char **args) +{ + if(n < 2) { + debuggerUsage("fd"); + } else { + if(armState) + debuggerFileDisassembleArm(n, args); + else + debuggerFileDisassembleThumb(n, args); + } +} + +static void debuggerContinueAfterBreakpoint() +{ + printf("Continuing after breakpoint\n"); + debuggerEnableBreakpoints(true); + debuggerPrefetch(); + emulator.emuMain(1); + debuggerAtBreakpoint = false; +} + +static void debuggerRegisters(int, char **) +{ + char m[] = { 'm', 0 }; + char one[] = { '1', 0 }; + + char *command[3] = { m , 0, one }; + char buffer[10]; + +#ifdef BKPT_SUPPORT + if (debugger_last) + { + printf("R00=%08x R04=%08x R08=%08x R12=%08x\n", + oldreg[0], oldreg[4], oldreg[8], oldreg[12]); + printf("R01=%08x R05=%08x R09=%08x R13=%08x\n", + oldreg[1], oldreg[5], oldreg[9], oldreg[13]); + printf("R02=%08x R06=%08x R10=%08x R14=%08x\n", + oldreg[2], oldreg[6], oldreg[10], oldreg[14]); + printf("R03=%08x R07=%08x R11=%08x R15=%08x\n", + oldreg[3], oldreg[7], oldreg[11], oldreg[15]); + command[1]=oldbuffer; + debuggerDisassemble(3, command); + printf("\n"); + } +#endif + + 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[1]=buffer; + debuggerDisassemble(3, command); +} + +static 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); +} + +static 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); +} + +static 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); +} + +static 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); +} + +static void debuggerIoMisc() +{ + printf("P1 = %04x\n", P1); + printf("IE = %04x\n", IE); + printf("IF = %04x\n", IF); + printf("IME = %04x\n", IME); +} + +static 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]); +} + +static void debuggerEditByte(int n, char **args) +{ + if(n == 3) { + u32 address = 0x10000; + u32 byte = 0; + sscanf(args[1], "%x", &address); + sscanf(args[2], "%x", &byte); + debuggerWriteByte(address, (u8)byte); + } else + debuggerUsage("eb"); +} + +static void debuggerEditHalfWord(int n, char **args) +{ + if(n == 3) { + u32 address = 0x10000; + u32 HalfWord = 0; + sscanf(args[1], "%x", &address); + if(address & 1) { + printf("Error: address must be half-word aligned\n"); + return; + } + sscanf(args[2], "%x", &HalfWord); + debuggerWriteHalfWord(address, (u16)HalfWord); + } else + debuggerUsage("eh"); +} + +static void debuggerEditRegister(int n, char **args) +{ + if(n == 3) { + int r = 15; + u32 val; + sscanf(args[1], "%d", &r); + if(r > 16 || r == 15) { + // don't allow PC to change + printf("Error: Register must be valid (0-14,16)\n"); + return; + } + sscanf(args[2], "%x", &val); + reg[r].I=val; + printf("Register changed.\n"); + } else + debuggerUsage("er"); +} + +static 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) + +static void debuggerMemoryByte(int n, char **args) +{ + if(n == 2) { + u32 addr = 0; + sscanf(args[1], "%x", &addr); + for(int _i = 0; _i < 16; _i++) { + 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"); +} + +static void debuggerMemoryHalfWord(int n, char **args) +{ + if(n == 2) { + u32 addr = 0; + sscanf(args[1], "%x", &addr); + addr = addr & 0xfffffffe; + for(int _i = 0; _i < 16; _i++) { + 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"); +} + +static void debuggerMemory(int n, char **args) +{ + if(n == 2) { + u32 addr = 0; + sscanf(args[1], "%x", &addr); + addr = addr & 0xfffffffc; + for(int _i = 0; _i < 16; _i++) { + 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"); +} + +static 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; + } +} + +static void debuggerWriteState(int n, char **args) +{ + int num = 12; + + if(n == 2) { + sscanf(args[1],"%d",&num); + if(num > 0 && num < 11) + sdlWriteState(num-1); + else + printf("Savestate number must be in the 1-10 range"); + } + else + debuggerUsage("save"); +} + +static void debuggerReadState(int n, char **args) +{ + int num = 12; + + if(n == 2) { + sscanf(args[1],"%d",&num); + if(num > 0 && num < 11) + sdlReadState(num-1); + else + printf("Savestate number must be in the 1-10 range"); + } + else + debuggerUsage("load"); +} + +static void debuggerDumpLoad(int n, char** args) +{ + u32 address = 0; + const char *file; + FILE *f; + int c; + + if(n==3) { + file=args[1]; + + sscanf(args[2],"%x",&address); + + f=fopen(file,"rb"); + if(!f) { + printf("Error opening file.\n"); + return; + } + + fseek(f,0,SEEK_END); + int size=ftell(f); + fseek(f,0,SEEK_SET); + + for(int i=0;i 4) { //conditional args handled separately + int i = debuggerNumOfBreakpoints; + + u32 address = 0; + sscanf(args[1],"%x", &address); + + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = debuggerReadHalfWord(address); + debuggerBreakpointList[i].size = 0; + + debuggerCondValidate(n, args,2); + } else + debuggerUsage("cbt"); + +} + +static void debuggerCondBreakArm(int n, char **args) +{ + if(n > 4) { //conditional args handled separately + + int i = debuggerNumOfBreakpoints; + u32 address = 0; + + sscanf(args[1],"%x", &address); + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = debuggerReadMemory(address); + debuggerBreakpointList[i].size = 1; + debuggerCondValidate(n, args,2); + } else + debuggerUsage("cba"); +} + +static void debuggerCondValidate(int n, char **args,int start) +{ + /* + 0: address/register + 1: op + 2: value + 3: size + */ + + int i=debuggerNumOfBreakpoints; + + char *address=args[start]; + const char *op=args[start+1]; + char *value=args[start+2]; + const char *tsize,*taddress,*tvalue; + + int rel=0; + + u32 value1=0; + u32 value2=0; + + char size=0; + int j=1; + + if(n==6) { + size = args[start+3][0]; + if(size != 'b' && size != 'h' && size != 'w') { + printf("Invalid size.\n"); + return; + } + + switch(size) { + case 'b': + debuggerBreakpointList[i].cond_size=1; + tsize="byte"; + break; + case 'h': + debuggerBreakpointList[i].cond_size=2; + tsize="halfword"; + break; + case 'w': + debuggerBreakpointList[i].cond_size=4; + tsize="word"; + break; + } + } + + switch(toupper(address[0])) { + case '$': //is address + while (address[j]) { + address[j-1]=address[j]; + j++; + } + address[j-1]=0; + + sscanf(address,"%x",&value1); + switch(size) { + case 'h': + if(value1 & 1) { + printf("Misaligned Conditional Address.\n"); + return; + } + break; + case 'w': + if(value1 & 3) { + printf("Misaligned Conditional Address.\n"); + return; + } + case 'b': + break; + default: + printf("Erroneous Condition\n"); + debuggerUsage((char *)((toupper(args[0][2])=='T') ? "cbt" : "cba")); + return; + } + debuggerBreakpointList[i].ia1=true; + taddress="$"; + break; + case 'R': //is register + while(address[j]) { + address[j-1]=address[j]; + j++; + } + address[j-1]=0; + sscanf(address,"%d",&value1); + + if(value1 > 16) { + printf("Invalid Register.\n"); + return; + } + if(size) + size=0; + debuggerBreakpointList[i].ia1=true; + taddress="r"; + break; + default: //immediate; + printf("First Comparison Parameter should not be Immediate\n"); + return; + } + + debuggerBreakpointList[i].cond_address = value1; + + // Check op + switch(op[0]) { + case '=': // 1 + if (op[1] == '=' && op[2]==0) + rel=1; + else + goto error; + break; + case '!': //2 + if (op[1]=='=' && op[2]==0) + rel=2; + else + goto error; + break; + case '<': //3 + if(op[1]=='=') + rel=5; + else if (op[1]==0) + rel=3; + else + goto error; + break; + case '>': //4 + if (op[1]=='=') + rel=6; + else if (op[1]==0) + rel=4; + else + goto error; + break; + default: + error: + printf("Invalid comparison operator.\n"); + return; + } + + if(op==0) { + printf("Invalid comparison operator.\n"); + return; + } + debuggerBreakpointList[i].cond_rel=rel; + + switch(toupper(value[0])) { + case '$': //is address + while(value[j]) { + value[j-1]=value[j]; + j++; + } + value[j-1]=0; + + sscanf(value,"%x",&value2); + debuggerBreakpointList[i].ia2=true; + tvalue="$"; + switch(size) { + case 'h': + if(value2 & 1) { + printf("Misaligned Conditional Address.\n"); + return; + } + break; + case 'w': + if(value2 & 3) { + printf("Misaligned Conditional Address.\n"); + return; + } + case 'b': + break; + default: + printf("Erroneous Condition\n"); + debuggerUsage((char *)((toupper(args[0][2])=='T') ? "cbt" : "cba")); + return; + } + break; + case 'R': //is register + while(value[j]) { + value[j-1]=value[j]; + j++; + } + value[j-1]=0; + sscanf(value,"%d",&value2); + + if(value2 > 16) { + printf("Invalid Register.\n"); + return; + } + debuggerBreakpointList[i].ia2=true; + tvalue="r"; + break; + default: //immediate; + sscanf(value, "%x",&value2); + debuggerBreakpointList[i].ia2=false; + tvalue="0x"; + + switch(size) { + case 'b': + value2 &=0xFF; + break; + case 'h': + value2 &=0xFFFF; + break; + default: + case 'w': + value2 &=0xFFFFFFFF; + break; + } + break; + } + + debuggerBreakpointList[i].cond_value = value2; + debuggerNumOfBreakpoints++; + + // At here, everything's set. Display message. + switch(size) { + case 0: + printf("Added breakpoint on %08X if R%02d %s %08X\n", + debuggerBreakpointList[i].address, + debuggerBreakpointList[i].cond_address, + op, + debuggerBreakpointList[i].cond_value); + break; + case 'b': + printf("Added breakpoint on %08X if %s%08X %s %s%02X\n", + debuggerBreakpointList[i].address, + taddress, + debuggerBreakpointList[i].cond_address, + op,tvalue, + debuggerBreakpointList[i].cond_value); + break; + case 'h': + printf("Added breakpoint on %08X if %s%08X %s %s%04X\n", + debuggerBreakpointList[i].address, + taddress, + debuggerBreakpointList[i].cond_address, + op, + tvalue, + debuggerBreakpointList[i].cond_value); + break; + case 'w': + printf("Added breakpoint on %08X if %s%08X %s %s%08X\n", + debuggerBreakpointList[i].address, + taddress, + debuggerBreakpointList[i].cond_address, + op,tvalue, + debuggerBreakpointList[i].cond_value); + break; + } +} + +static bool debuggerCondEvaluate(int num) +{ + // check if there is a condition + if(debuggerBreakpointList[num].cond_rel == 0) + return true; + + u32 address=debuggerBreakpointList[num].cond_address; + char size=debuggerBreakpointList[num].cond_size; + u32 value=debuggerBreakpointList[num].cond_value; + u32 value1=0; + u32 value2=0; + + if(address<17) + value1=reg[address].I; + else { + switch(size) { + case 1: + value1=debuggerReadByte(address); + break; + case 2: + value1=debuggerReadHalfWord(address); + break; + default: + value1=debuggerReadMemory(address); + break; + } + } + + //value2 + if(debuggerBreakpointList[num].ia2) { //is address or register + if(value<17) + value2=reg[address].I; + else { + switch(size) { + case 'b': + value2=debuggerReadByte(value); + break; + case 'h': + value2=debuggerReadHalfWord(value); + break; + default: + value2=debuggerReadMemory(value); + break; + } + } + } else + value2=value; + + switch(debuggerBreakpointList[num].cond_rel) { + case 1: // == + return (value1 == value2); + case 2: // != + return (value1 != value2); + case 3: // < + return (value1 < value2); + case 4: // > + return (value1 > value2); + case 5: // <= + return (value1 <= value2); + case 6: // >= + return (value1 >= value2); + default: + return false; //should never happen + } +} + +/*extern*/ void debuggerOutput(char *s, u32 addr) +{ + if(s) + printf(s); + else { + char c; + + c = debuggerReadByte(addr); + addr++; + while(c) { + putchar(c); + c = debuggerReadByte(addr); + addr++; + } + } +} + +char* strqtok (char* string, const char* ctrl) +{ // quoted tokens + static char* nexttoken = NULL; + char* str; + + if (string != NULL) + str = string; + else { + if (nexttoken == NULL) + return NULL; + str = nexttoken; + }; + + char deli [32]; + memset (deli, 0, 32 * sizeof (char)); + while (*ctrl) + { + deli [*ctrl >> 3] |= (1 << (*ctrl & 7)); + ctrl++; + }; + // can't allow to be set + deli ['"' >> 3] &= ~(1 << ('"' & 7)); + + // jump over leading delimiters + while ((deli [*str >> 3] & (1 << (*str & 7))) && *str) + str++; + + if (*str == '"') + { + string = ++str; + + // only break if another quote or end of string is found + while ((*str != '"') && *str) + str++; + } else { + string = str; + + // break on delimiter + while (!(deli [*str >> 3] & (1 << (*str & 7))) && *str) + str++; + }; + + if (string == str) + { + nexttoken = NULL; + return NULL; + } else { + if (*str) + { + *str = 0; + nexttoken = str + 1; + } else + nexttoken = NULL; + + return string; + }; +}; + +/*extern*/ void debuggerMain() +{ + char buffer[1024]; + char *commands[10]; + int commandCount = 0; + + if(emulator.emuUpdateCPSR) + emulator.emuUpdateCPSR(); + debuggerRegisters(0, NULL); + + while(debugger) { + systemSoundPause(); + debuggerDisableBreakpoints(); + printf("debugger> "); + commandCount = 0; + char *s = fgets(buffer, 1024, stdin); + + commands[0] = strqtok(s, " \t\n"); + if(commands[0] == NULL) + continue; + commandCount++; + while((s = strqtok(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; + } + } + } +} + +void debuggerLast(int n, char **args) +{ +debugger_last =!debugger_last; +if (debugger_last == true) +printf ("Last registers will be shown\n"); +else +printf ("Last registers wont be shown\n"); +} diff --git a/trunk/src/sdl/debugger.h b/trunk/src/sdl/debugger.h new file mode 100644 index 00000000..695ed217 --- /dev/null +++ b/trunk/src/sdl/debugger.h @@ -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 --git a/trunk/src/sdl/dummy.cpp b/trunk/src/sdl/dummy.cpp new file mode 100644 index 00000000..f41d6b4d --- /dev/null +++ b/trunk/src/sdl/dummy.cpp @@ -0,0 +1,46 @@ +#include + +//I hate hacks + +int realsystemRedShift = 0; +bool linkenable = false; +int lspeed = 0; + + + +void LinkSStop() +{ + const char *f = __func__; + printf("Stub Function: %s\n", f); +} + +void StartLink(unsigned short) +{ + const char *f = __func__; + printf("Stub Function: %s\n", f); +} + +void LinkSSend(unsigned short) +{ + const char *f = __func__; + printf("Stub Function: %s\n", f); +} + +void StartGPLink(unsigned short) +{ + const char *f = __func__; + printf("Stub Function: %s\n", f); +} + +void StartJOYLink(unsigned short) +{ + const char *f = __func__; + printf("Stub Function: %s\n", f); +} + +void LinkUpdate(int) +{ + const char *f = __func__; + printf("Stub Function: %s\n", f); +} +