diff --git a/desmume/configure.ac b/desmume/configure.ac index 23a889983..0532548e6 100644 --- a/desmume/configure.ac +++ b/desmume/configure.ac @@ -160,6 +160,7 @@ AC_CONFIG_FILES([Makefile src/gtk-glade/Makefile src/gtk-glade/desmume-glade.desktop src/windows/Makefile + src/gdbstub/Makefile autopackage/default.apspec debian/rules debian/changelog diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index 478392f5e..82b4530bb 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = build.bat instruction_tabdef.inc thumb_tabdef.inc fs-linux.c fs-windows.c -DIST_SUBDIRS = . cli gtk gtk-glade windows -SUBDIRS = . $(UI_DIR) +DIST_SUBDIRS = . gdbstub cli gtk gtk-glade windows +SUBDIRS = . gdbstub $(UI_DIR) noinst_LIBRARIES = libdesmume.a libdesmume_a_SOURCES = \ armcpu.c armcpu.h ARM9.h \ @@ -19,6 +19,7 @@ libdesmume_a_SOURCES = \ render3D.c render3D.h \ saves.c saves.h \ SPU.c SPU.h \ + gdbstub.h \ matrix.c matrix.h \ opengl_collector_3Demu.c opengl_collector_3Demu.h \ thumb_instructions.c thumb_instructions.h types.h diff --git a/desmume/src/cli/Makefile.am b/desmume/src/cli/Makefile.am index b1b8241f2..1141030fd 100644 --- a/desmume/src/cli/Makefile.am +++ b/desmume/src/cli/Makefile.am @@ -1,4 +1,4 @@ bin_PROGRAMS = desmume-cli desmume_cli_SOURCES = main.c ../sndsdl.c ../ctrlssdl.h ../ctrlssdl.c -desmume_cli_LDADD = ../libdesmume.a $(SDL_LIBS) +desmume_cli_LDADD = ../libdesmume.a ../gdbstub/libgdbstub.a $(SDL_LIBS) desmume_cli_CFLAGS = $(SDL_CFLAGS) diff --git a/desmume/src/cli/main.c b/desmume/src/cli/main.c index 37f559711..654f7399f 100644 --- a/desmume/src/cli/main.c +++ b/desmume/src/cli/main.c @@ -19,6 +19,7 @@ * Boston, MA 02111-1307, USA. */ #include "SDL.h" +#include "SDL_thread.h" #include #include #include @@ -46,6 +47,7 @@ #include "../sndsdl.h" #include "../ctrlssdl.h" #include "../render3D.h" +#include "../gdbstub.h" volatile BOOL execute = FALSE; @@ -95,27 +97,35 @@ const u16 cli_kb_cfg[NB_KEYS] = SDLK_o // BOOST }; - - struct my_config { + u16 arm9_gdb_port; + u16 arm7_gdb_port; + int disable_sound; #ifdef INCLUDE_OPENGL_2D int opengl_2d; int soft_colour_convert; #endif + int disable_limiter; const char *nds_file; - - + const char *cflash_disk_image_file; }; static void init_config( struct my_config *config) { + config->arm9_gdb_port = 0; + config->arm7_gdb_port = 0; + config->disable_sound = 0; + config->disable_limiter = 0; + config->nds_file = NULL; + config->cflash_disk_image_file = NULL; + #ifdef INCLUDE_OPENGL_2D config->opengl_2d = 0; config->soft_colour_convert = 0; @@ -135,12 +145,20 @@ fill_config( struct my_config *config, printf( "USAGE: %s \n", argv[0]); printf( "OPTIONS:\n"); printf( " --disable-sound Disables the sound emulation\n"); + printf( " --disable-limiter Disables the 60 fps limiter\n"); #ifdef INCLUDE_OPENGL_2D printf( " --opengl-2d Enables using OpenGL for screen rendering\n"); printf( " --soft-convert Use software colour conversion during OpenGL\n"); printf( " screen rendering. May produce better or worse\n"); printf( " frame rates depending on hardware.\n"); #endif + printf( "\n"); + printf( " --arm9gdb=PORT_NUM Enable the ARM9 GDB stub on the given port\n"); + printf( " --arm7gdb=PORT_NUM Enable the ARM7 GDB stub on the given port\n"); + //printf( " --sticky Enable sticky keys and stylus\n"); + printf( "\n"); + printf( " --cflash=PATH_TO_DISK_IMAGE\n"); + printf( " Enable disk image GBAMP compact flash emulation\n"); printf( "\n"); printf( " --help Display this message\n"); good_args = 0; @@ -156,6 +174,43 @@ fill_config( struct my_config *config, config->soft_colour_convert = 1; } #endif + else if ( strcmp( argv[i], "--disable-limiter") == 0) { + config->disable_limiter = 1; + } + else if ( strncmp( argv[i], "--arm9gdb=", 10) == 0) { + char *end_char; + unsigned long port_num = strtoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm9_gdb_port = port_num; + } + else { + fprintf( stderr, "ARM9 GDB stub port must be in the range 1 to 65535\n"); + good_args = 0; + } + } + else if ( strncmp( argv[i], "--arm7gdb=", 10) == 0) { + char *end_char; + unsigned long port_num = strtoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm7_gdb_port = port_num; + } + else { + fprintf( stderr, "ARM7 GDB stub port must be in the range 1 to 65535\n"); + good_args = 0; + } + } + else if ( strncmp( argv[i], "--cflash=", 9) == 0) { + if ( config->cflash_disk_image_file == NULL) { + config->cflash_disk_image_file = &argv[i][9]; + } + else { + fprintf( stderr, "CFlash disk image file (\"%s\") already set\n", + config->cflash_disk_image_file); + good_args = 0; + } + } else { if ( config->nds_file == NULL) { config->nds_file = argv[i]; @@ -182,6 +237,26 @@ fill_config( struct my_config *config, } +/* + * The thread handling functions needed by the GDB stub code. + */ +void * +createThread_gdb( void (*thread_function)( void *data), + void *thread_data) { + SDL_Thread *new_thread = SDL_CreateThread( (int (*)(void *data))thread_function, + thread_data); + + return new_thread; +} + +void +joinThread_gdb( void *thread_handle) { + int ignore; + SDL_WaitThread( thread_handle, &ignore); +} + + + /** * A SDL timer callback function. Signals the supplied SDL semaphore * if its value is small. @@ -420,16 +495,25 @@ Draw( void) { if(rawImage == NULL) return; SDL_BlitSurface(rawImage, 0, surface, 0); + SDL_UpdateRect(surface, 0, 0, 0, 0); SDL_FreeSurface(rawImage); return; } + int main(int argc, char ** argv) { static unsigned short keypad = 0; struct my_config my_config; u32 last_cycle = 0; + gdbstub_handle_t arm9_gdb_stub; + gdbstub_handle_t arm7_gdb_stub; + struct armcpu_memory_iface *arm9_memio = &arm9_base_memory_iface; + struct armcpu_memory_iface *arm7_memio = &arm7_base_memory_iface; + struct armcpu_ctrl_iface *arm9_ctrl_iface; + struct armcpu_ctrl_iface *arm7_ctrl_iface; + int limiter_frame_counter = 0; SDL_sem *fps_limiter_semaphore; SDL_TimerID limiter_timer; @@ -454,20 +538,55 @@ int main(int argc, char ** argv) { exit(1); } + if ( my_config.arm9_gdb_port != 0) { + arm9_gdb_stub = createStub_gdb( my_config.arm9_gdb_port, + &arm9_memio, + &arm9_direct_memory_iface); + + if ( arm9_gdb_stub == NULL) { + fprintf( stderr, "Failed to create ARM9 gdbstub on port %d\n", + my_config.arm9_gdb_port); + exit( 1); + } + } + if ( my_config.arm7_gdb_port != 0) { + arm7_gdb_stub = createStub_gdb( my_config.arm7_gdb_port, + &arm7_memio, + &arm7_base_memory_iface); + + if ( arm7_gdb_stub == NULL) { + fprintf( stderr, "Failed to create ARM7 gdbstub on port %d\n", + my_config.arm7_gdb_port); + exit( 1); + } + } + #ifdef DEBUG LogStart(); #endif - NDS_Init(); + NDS_Init( arm9_memio, &arm9_ctrl_iface, + arm7_memio, &arm7_ctrl_iface); if ( !my_config.disable_sound) { SPU_ChangeSoundCore(SNDCORE_SDL, 735 * 4); } - if ( NDS_LoadROM( my_config.nds_file, MC_TYPE_AUTODETECT, 1) < 0) { + if (NDS_LoadROM( my_config.nds_file, MC_TYPE_AUTODETECT, 1, my_config.cflash_disk_image_file) < 0) { fprintf(stderr, "error while loading %s\n", my_config.nds_file); exit(-1); } + /* + * Activate the GDB stubs + * This has to come after the NDS_Init where the cpus are set up. + */ + if ( my_config.arm9_gdb_port != 0) { + activateStub_gdb( arm9_gdb_stub, arm9_ctrl_iface); + } + if ( my_config.arm7_gdb_port != 0) { + activateStub_gdb( arm7_gdb_stub, arm7_ctrl_iface); + } + /* // This has to get fixed yet strcpy(szRomPath, dirname(argv[1])); cflash_close(); @@ -555,16 +674,18 @@ int main(int argc, char ** argv) { /* Load our own keyboard configuration */ set_kb_keys(cli_kb_cfg); - /* create the semaphore used for fps limiting */ - fps_limiter_semaphore = SDL_CreateSemaphore( 1); + if ( !my_config.disable_limiter) { + /* create the semaphore used for fps limiting */ + fps_limiter_semaphore = SDL_CreateSemaphore( 1); - /* start a SDL timer for every FPS_LIMITER_FRAME_PERIOD frames to keep us at 60 fps */ - limiter_timer = SDL_AddTimer( 16 * FPS_LIMITER_FRAME_PERIOD, - fps_limiter_fn, fps_limiter_semaphore); - if ( limiter_timer == NULL) { - fprintf( stderr, "Error trying to start FPS limiter timer: %s\n", - SDL_GetError()); - return 1; + /* start a SDL timer for every FPS_LIMITER_FRAME_PERIOD frames to keep us at 60 fps */ + limiter_timer = SDL_AddTimer( 16 * FPS_LIMITER_FRAME_PERIOD, + fps_limiter_fn, fps_limiter_semaphore); + if ( limiter_timer == NULL) { + fprintf( stderr, "Error trying to start FPS limiter timer: %s\n", + SDL_GetError()); + return 1; + } } @@ -596,12 +717,14 @@ int main(int argc, char ** argv) { #endif Draw(); - limiter_frame_counter += 1; - if ( limiter_frame_counter >= FPS_LIMITER_FRAME_PERIOD) { - limiter_frame_counter = 0; + if ( !my_config.disable_limiter) { + limiter_frame_counter += 1; + if ( limiter_frame_counter >= FPS_LIMITER_FRAME_PERIOD) { + limiter_frame_counter = 0; - /* wait for the timer to expire */ - SDL_SemWait( fps_limiter_semaphore); + /* wait for the timer to expire */ + SDL_SemWait( fps_limiter_semaphore); + } } #ifdef DISPLAY_FPS @@ -620,22 +743,34 @@ int main(int argc, char ** argv) { fps_frame_counter = 0; fps_timing = 0; - sprintf( win_title, "%f Desmume", fps); + sprintf( win_title, "Desmume %f", fps); SDL_WM_SetCaption( win_title, NULL); } #endif } + + /* Unload joystick */ uninit_joy(); - /* tidy up the FPS limiter timer and semaphore */ - SDL_RemoveTimer( limiter_timer); - SDL_DestroySemaphore( fps_limiter_semaphore); + if ( !my_config.disable_limiter) { + /* tidy up the FPS limiter timer and semaphore */ + SDL_RemoveTimer( limiter_timer); + SDL_DestroySemaphore( fps_limiter_semaphore); + } SDL_Quit(); NDS_DeInit(); + + if ( my_config.arm9_gdb_port != 0) { + destroyStub_gdb( arm9_gdb_stub); + } + if ( my_config.arm7_gdb_port != 0) { + destroyStub_gdb( arm7_gdb_stub); + } + #ifdef DEBUG LogStop(); #endif diff --git a/desmume/src/gtk-glade/Makefile.am b/desmume/src/gtk-glade/Makefile.am index 57d8d535f..c137d22e7 100644 --- a/desmume/src/gtk-glade/Makefile.am +++ b/desmume/src/gtk-glade/Makefile.am @@ -17,7 +17,7 @@ desmume_glade_SOURCES = \ gladedir = $(datadir)/desmume/glade glade_DATA = glade/DeSmuMe_Dtools.glade glade/DeSmuMe.glade glade/DeSmuME.xpm -desmume_glade_LDADD = ../libdesmume.a $(SDL_LIBS) $(GTKGLEXT_LIBS) $(LIBGLADE_LIBS) $(GTHREAD_LIBS) +desmume_glade_LDADD = ../libdesmume.a ../gdbstub/libgdbstub.a $(SDL_LIBS) $(GTKGLEXT_LIBS) $(LIBGLADE_LIBS) $(GTHREAD_LIBS) desmume_glade_CFLAGS = $(SDL_CFLAGS) $(GTKGLEXT_CFLAGS) $(LIBGLADE_CFLAGS) $(GTHREAD_CFLAGS) -DDATADIR=\"$(gladedir)/\" desmume_glade_LDFLAGS = -rdynamic diff --git a/desmume/src/gtk-glade/desmume.c b/desmume/src/gtk-glade/desmume.c index 0fd382335..bbbd3de95 100755 --- a/desmume/src/gtk-glade/desmume.c +++ b/desmume/src/gtk-glade/desmume.c @@ -39,9 +39,13 @@ void desmume_mem_init(); u8 *desmume_rom_data = NULL; u32 desmume_last_cycle; -void desmume_init() +void desmume_init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface) { - NDS_Init(); + NDS_Init( arm9_mem_if, arm9_ctrl_iface, + arm7_mem_if, arm7_ctrl_iface); SPU_ChangeSoundCore(SNDCORE_SDL, 735 * 4); execute = FALSE; } @@ -57,7 +61,7 @@ int desmume_open(const char *filename) int i; noticed_3D=attempted_3D_op=FALSE; clear_savestates(); - i = NDS_LoadROM(filename, savetype, savesize); + i = NDS_LoadROM(filename, savetype, savesize, NULL); return i; } diff --git a/desmume/src/gtk-glade/desmume.h b/desmume/src/gtk-glade/desmume.h index 2133eb257..df5f3381a 100755 --- a/desmume/src/gtk-glade/desmume.h +++ b/desmume/src/gtk-glade/desmume.h @@ -22,22 +22,24 @@ #include "globals.h" - #define FPS_LIMITER_FRAME_PERIOD 5 extern SDL_sem *glade_fps_limiter_semaphore; extern int glade_fps_limiter_disabled; -extern void desmume_init(); -extern void desmume_free(); +extern void desmume_init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface); +extern void desmume_free( void); extern int desmume_open(const char *filename); extern void desmume_savetype(int type); -extern void desmume_pause(); -extern void desmume_resume(); -extern void desmume_reset(); -extern void desmume_toggle(); -extern BOOL desmume_running(); +extern void desmume_pause( void); +extern void desmume_resume( void); +extern void desmume_reset( void); +extern void desmume_toggle( void); +extern BOOL desmume_running( void); -extern void desmume_cycle(); +extern void desmume_cycle( void); #endif /*__DESMUME_H__*/ diff --git a/desmume/src/gtk-glade/main.c b/desmume/src/gtk-glade/main.c index feb3fe796..90c942162 100755 --- a/desmume/src/gtk-glade/main.c +++ b/desmume/src/gtk-glade/main.c @@ -24,6 +24,7 @@ #include "callbacks_IO.h" #include "dTools/callbacks_dtools.h" #include "globals.h" +#include "../gdbstub.h" #ifdef GTKGLEXT_AVAILABLE #include @@ -67,11 +68,18 @@ struct configured_features { int software_colour_convert; int disable_3d; int disable_limiter; + + u16 arm9_gdb_port; + u16 arm7_gdb_port; + const char *nds_file; }; static void init_configured_features( struct configured_features *config) { + config->arm9_gdb_port = 0; + config->arm7_gdb_port = 0; + config->software_colour_convert = 0; config->disable_3d = 0; @@ -102,6 +110,10 @@ fill_configured_features( struct configured_features *config, #endif g_print( " --disable-limiter Disables the 60 fps limiter\n"); g_print( "\n"); + g_print( " --arm9gdb=PORT_NUM Enable the ARM9 GDB stub on the given port\n"); + g_print( " --arm7gdb=PORT_NUM Enable the ARM7 GDB stub on the given port\n"); + //g_print( " --sticky Enable sticky keys and stylus\n"); + g_print( "\n"); g_print( " --help Display this message\n"); good_args = 0; } @@ -113,6 +125,30 @@ fill_configured_features( struct configured_features *config, config->disable_3d = 1; } #endif + else if ( strncmp( argv[i], "--arm9gdb=", 10) == 0) { + char *end_char; + unsigned long port_num = strtoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm9_gdb_port = port_num; + } + else { + g_print( "ARM9 GDB stub port must be in the range 1 to 65535\n"); + good_args = 0; + } + } + else if ( strncmp( argv[i], "--arm7gdb=", 10) == 0) { + char *end_char; + unsigned long port_num = strtoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm7_gdb_port = port_num; + } + else { + g_print( "ARM7 GDB stub port must be in the range 1 to 65535\n"); + good_args = 0; + } + } else if ( strcmp( argv[i], "--disable-limiter") == 0) { config->disable_limiter = 1; } @@ -314,6 +350,27 @@ void update_savestate(u8 num) } +/* + * The thread handling functions needed by the GDB stub code. + */ +void * +createThread_gdb( void (*thread_function)( void *data), + void *thread_data) { + GThread *new_thread = g_thread_create( (GThreadFunc)thread_function, + thread_data, + TRUE, + NULL); + + return new_thread; +} + +void +joinThread_gdb( void *thread_handle) { + g_thread_join( thread_handle); +} + + + /** * A SDL timer callback function. Signals the supplied SDL semaphore * if its value is small. @@ -340,7 +397,12 @@ glade_fps_limiter_fn( Uint32 interval, void *param) { static int common_gtk_glade_main( struct configured_features *my_config) { SDL_TimerID limiter_timer; - + gdbstub_handle_t arm9_gdb_stub; + gdbstub_handle_t arm7_gdb_stub; + struct armcpu_memory_iface *arm9_memio = &arm9_base_memory_iface; + struct armcpu_memory_iface *arm7_memio = &arm7_base_memory_iface; + struct armcpu_ctrl_iface *arm9_ctrl_iface; + struct armcpu_ctrl_iface *arm7_ctrl_iface; #ifdef GTKGLEXT_AVAILABLE // check if you have GTHREAD when running configure script @@ -353,6 +415,30 @@ common_gtk_glade_main( struct configured_features *my_config) { #endif init_keyvals(); + if ( my_config->arm9_gdb_port != 0) { + arm9_gdb_stub = createStub_gdb( my_config->arm9_gdb_port, + &arm9_memio, + &arm9_base_memory_iface); + + if ( arm9_gdb_stub == NULL) { + g_print( "Failed to create ARM9 gdbstub on port %d\n", + my_config->arm9_gdb_port); + return -1; + } + } + if ( my_config->arm7_gdb_port != 0) { + arm7_gdb_stub = createStub_gdb( my_config->arm7_gdb_port, + &arm7_memio, + &arm7_base_memory_iface); + + if ( arm7_gdb_stub == NULL) { + g_print( "Failed to create ARM7 gdbstub on port %d\n", + my_config->arm7_gdb_port); + return -1; + } + } + + if(SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO) == -1) { fprintf(stderr, "Error trying to initialize SDL: %s\n", @@ -360,8 +446,21 @@ common_gtk_glade_main( struct configured_features *my_config) { return 1; } + desmume_init( arm9_memio, &arm9_ctrl_iface, + arm7_memio, &arm7_ctrl_iface); + + /* + * Activate the GDB stubs + * This has to come after the NDS_Init (called in desmume_init) + * where the cpus are set up. + */ + if ( my_config->arm9_gdb_port != 0) { + activateStub_gdb( arm9_gdb_stub, arm9_ctrl_iface); + } + if ( my_config->arm7_gdb_port != 0) { + activateStub_gdb( arm7_gdb_stub, arm7_ctrl_iface); + } - desmume_init(); /* Initialize joysticks */ if(!init_joy()) return 1; @@ -475,7 +574,10 @@ int main(int argc, char *argv[]) { struct configured_features my_config; init_configured_features( &my_config); - + + if (!g_thread_supported()) + g_thread_init( NULL); + gtk_init(&argc, &argv); #ifdef GTKGLEXT_AVAILABLE diff --git a/desmume/src/gtk/Makefile.am b/desmume/src/gtk/Makefile.am index c645539c2..fc0fee42f 100644 --- a/desmume/src/gtk/Makefile.am +++ b/desmume/src/gtk/Makefile.am @@ -16,6 +16,7 @@ desmume_SOURCES = \ ../ctrlssdl.h ../ctrlssdl.c \ gdk_3Demu.c gdk_3Demu.h \ main.c -desmume_LDADD = ../libdesmume.a $(SDL_LIBS) $(GTK_LIBS) $(GTKGLEXT_LIBS) -desmume_CFLAGS = $(SDL_CFLAGS) $(GTK_CFLAGS) $(GTKGLEXT_CFLAGS) +desmume_LDADD = ../libdesmume.a ../gdbstub/libgdbstub.a \ + $(SDL_LIBS) $(GTK_LIBS) $(GTKGLEXT_LIBS) $(GTHREAD_LIBS) +desmume_CFLAGS = $(SDL_CFLAGS) $(GTK_CFLAGS) $(GTKGLEXT_CFLAGS) $(GTHREAD_CFLAGS) #desmume_LDFLAGS = -rdynamic diff --git a/desmume/src/gtk/desmume.c b/desmume/src/gtk/desmume.c index 8a62fc051..5977652b5 100644 --- a/desmume/src/gtk/desmume.c +++ b/desmume/src/gtk/desmume.c @@ -29,9 +29,14 @@ unsigned long glock = 0; u8 *desmume_rom_data = NULL; u32 desmume_last_cycle; -void desmume_init( int disable_sound) +void desmume_init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface, + int disable_sound) { - NDS_Init(); + NDS_Init( arm9_mem_if, arm9_ctrl_iface, + arm7_mem_if, arm7_ctrl_iface); if ( !disable_sound) { SPU_ChangeSoundCore(SNDCORE_SDL, 735 * 4); } diff --git a/desmume/src/gtk/desmume.h b/desmume/src/gtk/desmume.h index cd5fcca5d..e1076ae57 100644 --- a/desmume/src/gtk/desmume.h +++ b/desmume/src/gtk/desmume.h @@ -24,7 +24,11 @@ #include "globals.h" -extern void desmume_init( int disable_sound); +extern void desmume_init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface, + int disable_sound); extern void desmume_free( void); extern void desmume_pause( void); diff --git a/desmume/src/gtk/main.c b/desmume/src/gtk/main.c index 6e547c6fa..329b1f085 100644 --- a/desmume/src/gtk/main.c +++ b/desmume/src/gtk/main.c @@ -27,6 +27,8 @@ #include "globals.h" #include "../debug.h" +#include "../gdbstub.h" + #ifdef GTKGLEXT_AVAILABLE #include "../opengl_collector_3Demu.h" #include "gdk_3Demu.h" @@ -36,8 +38,23 @@ #define EMULOOP_PRIO (G_PRIORITY_HIGH_IDLE + 20) + +#define ENABLE_MEMORY_PROFILING 1 + +#ifdef ENABLE_MEMORY_PROFILING +#include + +void +print_memory_profiling( void); +#endif + +static const char *bad_glob_cflash_disk_image_file; + + #define FPS_LIMITER_FRAME_PERIOD 8 static SDL_sem *fps_limiter_semaphore; +static int gtk_fps_limiter_disabled = 0; + /************************ CONFIG FILE *****************************/ @@ -87,13 +104,23 @@ struct screen_render_config { struct configured_features { struct screen_render_config screen; + int disable_sound; int disable_3d; + int disable_limiter; + + u16 arm9_gdb_port; + u16 arm7_gdb_port; + const char *nds_file; + const char *cflash_disk_image_file; }; static void init_configured_features( struct configured_features *config) { + config->arm9_gdb_port = 0; + config->arm7_gdb_port = 0; + config->disable_sound = 0; config->screen.opengl = 0; @@ -101,7 +128,11 @@ init_configured_features( struct configured_features *config) { config->disable_3d = 0; + config->disable_limiter = 0; + config->nds_file = NULL; + + config->cflash_disk_image_file = NULL; } static int @@ -125,6 +156,14 @@ fill_configured_features( struct configured_features *config, printf( "\n"); #endif printf( " --disable-sound Disables the sound emulation\n"); + printf( " --disable-limiter Disables the 60 fps limiter\n"); + printf( "\n"); + printf( " --arm9gdb=PORT_NUM Enable the ARM9 GDB stub on the given port\n"); + printf( " --arm7gdb=PORT_NUM Enable the ARM7 GDB stub on the given port\n"); + //printf( " --sticky Enable sticky keys and stylus\n"); + printf( "\n"); + printf( " --cflash=PATH_TO_DISK_IMAGE\n"); + printf( " Enable disk image GBAMP compact flash emulation\n"); printf( "\n"); printf( " --help Display this message\n"); good_args = 0; @@ -143,6 +182,43 @@ fill_configured_features( struct configured_features *config, config->disable_3d = 1; } #endif + else if ( strcmp( argv[i], "--disable-limiter") == 0) { + config->disable_limiter = 1; + } + else if ( strncmp( argv[i], "--arm9gdb=", 10) == 0) { + char *end_char; + unsigned long port_num = strtoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm9_gdb_port = port_num; + } + else { + fprintf( stderr, "ARM9 GDB stub port must be in the range 1 to 65535\n"); + good_args = 0; + } + } + else if ( strncmp( argv[i], "--arm7gdb=", 10) == 0) { + char *end_char; + unsigned long port_num = strtoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm7_gdb_port = port_num; + } + else { + fprintf( stderr, "ARM7 GDB stub port must be in the range 1 to 65535\n"); + good_args = 0; + } + } + else if ( strncmp( argv[i], "--cflash=", 9) == 0) { + if ( config->cflash_disk_image_file == NULL) { + config->cflash_disk_image_file = &argv[i][9]; + } + else { + fprintf( stderr, "CFlash disk image file (\"%s\") already set\n", + config->cflash_disk_image_file); + good_args = 0; + } + } else { if ( config->nds_file == NULL) { config->nds_file = argv[i]; @@ -168,6 +244,29 @@ fill_configured_features( struct configured_features *config, return good_args; } + +/* + * The thread handling functions needed by the GDB stub code. + */ +void * +createThread_gdb( void (*thread_function)( void *data), + void *thread_data) { + GThread *new_thread = g_thread_create( (GThreadFunc)thread_function, + thread_data, + TRUE, + NULL); + + return new_thread; +} + +void +joinThread_gdb( void *thread_handle) { + g_thread_join( thread_handle); +} + + + + u16 Keypad_Temp[NB_KEYS]; int Write_ConfigFile() @@ -286,9 +385,10 @@ void About(GtkWidget* widget, gpointer data) g_object_unref(pixbuf); } -static int Open(const char *filename) +static int Open(const char *filename, const char *cflash_disk_image) { - int i = NDS_LoadROM(filename, MC_TYPE_AUTODETECT, 1); + int i = NDS_LoadROM( filename, MC_TYPE_AUTODETECT, 1, + cflash_disk_image); return i; } @@ -366,7 +466,7 @@ static void *Open_Select(GtkWidget* widget, gpointer data) case GTK_RESPONSE_OK: /* Recuperation du chemin */ sChemin = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection)); - if(Open((const char*)sChemin) < 0) + if(Open((const char*)sChemin, bad_glob_cflash_disk_image_file) < 0) { GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection), GTK_DIALOG_MODAL, @@ -865,6 +965,12 @@ static gint Key_Press(GtkWidget *w, GdkEventKey *e) u16 Key = lookup_key(e->keyval); ADD_KEY( Cur_Keypad, Key ); if(desmume_running()) update_keypad(Cur_Keypad); + +#ifdef ENABLE_MEMORY_PROFILING + if ( e->keyval == GDK_Tab) { + print_memory_profiling(); + } +#endif return 1; } @@ -1381,12 +1487,14 @@ gboolean EmuLoop(gpointer data) _updateDTools(); gtk_widget_queue_draw( nds_screen_widget); - limiter_frame_counter += 1; - if ( limiter_frame_counter >= FPS_LIMITER_FRAME_PERIOD) { - limiter_frame_counter = 0; + if ( !gtk_fps_limiter_disabled) { + limiter_frame_counter += 1; + if ( limiter_frame_counter >= FPS_LIMITER_FRAME_PERIOD) { + limiter_frame_counter = 0; - /* wait for the timer to expire */ - SDL_SemWait( fps_limiter_semaphore); + /* wait for the timer to expire */ + SDL_SemWait( fps_limiter_semaphore); + } } @@ -1438,11 +1546,43 @@ common_gtk_main( struct configured_features *my_config) { GdkGLConfig *glconfig; GdkGLContext *glcontext; #endif + gdbstub_handle_t arm9_gdb_stub; + gdbstub_handle_t arm7_gdb_stub; + struct armcpu_memory_iface *arm9_memio = &arm9_base_memory_iface; + struct armcpu_memory_iface *arm7_memio = &arm7_base_memory_iface; + struct armcpu_ctrl_iface *arm9_ctrl_iface; + struct armcpu_ctrl_iface *arm7_ctrl_iface; + + bad_glob_cflash_disk_image_file = my_config->cflash_disk_image_file; #ifdef DEBUG LogStart(); #endif + if ( my_config->arm9_gdb_port != 0) { + arm9_gdb_stub = createStub_gdb( my_config->arm9_gdb_port, + &arm9_memio, + &arm9_base_memory_iface); + + if ( arm9_gdb_stub == NULL) { + fprintf( stderr, "Failed to create ARM9 gdbstub on port %d\n", + my_config->arm9_gdb_port); + exit( -1); + } + } + if ( my_config->arm7_gdb_port != 0) { + arm7_gdb_stub = createStub_gdb( my_config->arm7_gdb_port, + &arm7_memio, + &arm7_base_memory_iface); + + if ( arm7_gdb_stub == NULL) { + fprintf( stderr, "Failed to create ARM7 gdbstub on port %d\n", + my_config->arm7_gdb_port); + exit( -1); + } + } + + #ifdef GTKGLEXT_AVAILABLE /* Try double-buffered visual */ glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB | @@ -1470,8 +1610,23 @@ common_gtk_main( struct configured_features *my_config) { SDL_GetError()); return 1; } + desmume_init( arm9_memio, &arm9_ctrl_iface, + arm7_memio, &arm7_ctrl_iface, + my_config->disable_sound); + + + /* + * Activate the GDB stubs + * This has to come after the NDS_Init (called in desmume_init) + * where the cpus are set up. + */ + if ( my_config->arm9_gdb_port != 0) { + activateStub_gdb( arm9_gdb_stub, arm9_ctrl_iface); + } + if ( my_config->arm7_gdb_port != 0) { + activateStub_gdb( arm7_gdb_stub, arm7_ctrl_iface); + } - desmume_init( my_config->disable_sound); /* Initialize joysticks */ if(!init_joy()) return 1; @@ -1789,15 +1944,18 @@ common_gtk_main( struct configured_features *my_config) { //LoadFirmware("fw.bin"); - /* create the semaphore used for fps limiting */ - fps_limiter_semaphore = SDL_CreateSemaphore( 1); + gtk_fps_limiter_disabled = my_config->disable_limiter; + if ( !gtk_fps_limiter_disabled) { + /* create the semaphore used for fps limiting */ + fps_limiter_semaphore = SDL_CreateSemaphore( 1); - /* start a SDL timer for every FPS_LIMITER_FRAME_PERIOD frames to keep us at 60 fps */ - limiter_timer = SDL_AddTimer( 16 * FPS_LIMITER_FRAME_PERIOD, fps_limiter_fn, fps_limiter_semaphore); - if ( limiter_timer == NULL) { - fprintf( stderr, "Error trying to start FPS limiter timer: %s\n", - SDL_GetError()); - return 1; + /* start a SDL timer for every FPS_LIMITER_FRAME_PERIOD frames to keep us at 60 fps */ + limiter_timer = SDL_AddTimer( 16 * FPS_LIMITER_FRAME_PERIOD, fps_limiter_fn, fps_limiter_semaphore); + if ( limiter_timer == NULL) { + fprintf( stderr, "Error trying to start FPS limiter timer: %s\n", + SDL_GetError()); + return 1; + } } /* @@ -1836,7 +1994,7 @@ common_gtk_main( struct configured_features *my_config) { /* Vérifie la ligne de commandes */ if( my_config->nds_file != NULL) { - if(Open( my_config->nds_file) >= 0) + if(Open( my_config->nds_file, bad_glob_cflash_disk_image_file) >= 0) { Launch(); } @@ -1861,9 +2019,11 @@ common_gtk_main( struct configured_features *my_config) { desmume_free(); - /* tidy up the FPS limiter timer and semaphore */ - SDL_RemoveTimer( limiter_timer); - SDL_DestroySemaphore( fps_limiter_semaphore); + if ( !gtk_fps_limiter_disabled) { + /* tidy up the FPS limiter timer and semaphore */ + SDL_RemoveTimer( limiter_timer); + SDL_DestroySemaphore( fps_limiter_semaphore); + } #ifdef DEBUG LogStop(); @@ -1872,8 +2032,15 @@ common_gtk_main( struct configured_features *my_config) { uninit_joy(); SDL_Quit(); - + Write_ConfigFile(); + + if ( my_config->arm9_gdb_port != 0) { + destroyStub_gdb( arm9_gdb_stub); + } + if ( my_config->arm7_gdb_port != 0) { + destroyStub_gdb( arm7_gdb_stub); + } return EXIT_SUCCESS; } @@ -1884,7 +2051,10 @@ main (int argc, char *argv[]) { struct configured_features my_config; init_configured_features( &my_config); - + + if (!g_thread_supported()) + g_thread_init( NULL); + gtk_init(&argc, &argv); #ifdef GTKGLEXT_AVAILABLE diff --git a/desmume/src/windows/main.c b/desmume/src/windows/main.c index c3bca524e..169fbd0e7 100644 --- a/desmume/src/windows/main.c +++ b/desmume/src/windows/main.c @@ -50,9 +50,14 @@ #include "FirmConfig.h" #include "OGLRender.h" #include "../render3D.h" +#include "../gdbstub.h" #include "snddx.h" +/* The compact flash disk image file */ +static const char *bad_glob_cflash_disk_image_file; +static char cflash_filename_buffer[512]; + /* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); @@ -112,7 +117,79 @@ static u32 backupmemorysize=1; LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - + +struct configured_features { + u16 arm9_gdb_port; + u16 arm7_gdb_port; + + const char *cflash_disk_image_file; +}; + +static void +init_configured_features( struct configured_features *config) { + config->arm9_gdb_port = 0; + config->arm7_gdb_port = 0; + + config->cflash_disk_image_file = NULL; +} + + +static int +fill_configured_features( struct configured_features *config, LPSTR lpszArgument) { + int good_args = 0; + LPTSTR cmd_line; + LPWSTR *argv; + int argc; + + argv = CommandLineToArgvW( GetCommandLineW(), &argc); + + if ( argv != NULL) { + int i; + good_args = 1; + for ( i = 1; i < argc && good_args; i++) { + if ( wcsncmp( argv[i], L"--arm9gdb=", 10) == 0) { + wchar_t *end_char; + unsigned long port_num = wcstoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm9_gdb_port = port_num; + } + else { + MessageBox(NULL,"ARM9 GDB stub port must be in the range 1 to 65535","Error",MB_OK); + good_args = 0; + } + } + else if ( wcsncmp( argv[i], L"--arm7gdb=", 10) == 0) { + wchar_t *end_char; + unsigned long port_num = wcstoul( &argv[i][10], &end_char, 10); + + if ( port_num > 0 && port_num < 65536) { + config->arm7_gdb_port = port_num; + } + else { + MessageBox(NULL,"ARM9 GDB stub port must be in the range 1 to 65535","Error",MB_OK); + good_args = 0; + } + } + else if ( wcsncmp( argv[i], L"--cflash=", 9) == 0) { + if ( config->cflash_disk_image_file == NULL) { + size_t convert_count = wcstombs( &cflash_filename_buffer[0], &argv[i][9], 512); + if ( convert_count > 0) { + config->cflash_disk_image_file = cflash_filename_buffer; + } + } + else { + MessageBox(NULL,"CFlash disk image file already set","Error",MB_OK); + good_args = 0; + } + } + } + LocalFree( argv); + } + + return good_args; +} + // Rotation definitions u8 GPU_screenrotated[4*256*192]; short GPU_rotation = 0; @@ -423,16 +500,34 @@ void StateLoadSlot(int num) NDS_UnPause(); } -BOOL LoadROM(char * filename) +BOOL LoadROM(char * filename, const char *cflash_disk_image) { NDS_Pause(); - if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize) > 0) + if (NDS_LoadROM(filename, backupmemorytype, backupmemorysize, cflash_disk_image) > 0) return TRUE; return FALSE; } +/* + * The thread handling functions needed by the GDB stub code. + */ +void * +createThread_gdb( void (*thread_function)( void *data), + void *thread_data) { + void *new_thread = CreateThread( NULL, 0, + (LPTHREAD_START_ROUTINE)thread_function, thread_data, + 0, NULL); + + return new_thread; +} + +void +joinThread_gdb( void *thread_handle) { +} + + void SetLanguage(int langid) { switch(langid) @@ -491,7 +586,15 @@ int WINAPI WinMain (HINSTANCE hThisInstance, int nFunsterStil) { - MSG messages; /* Here messages to the application are saved */ + gdbstub_handle_t arm9_gdb_stub; + gdbstub_handle_t arm7_gdb_stub; + struct armcpu_memory_iface *arm9_memio = &arm9_base_memory_iface; + struct armcpu_memory_iface *arm7_memio = &arm7_base_memory_iface; + struct armcpu_ctrl_iface *arm9_ctrl_iface; + struct armcpu_ctrl_iface *arm7_ctrl_iface; + struct configured_features my_config; + + MSG messages; /* Here messages to the application are saved */ char text[80]; cwindow_struct MainWindow; HACCEL hAccel; @@ -505,6 +608,13 @@ int WINAPI WinMain (HINSTANCE hThisInstance, sprintf(text, "DeSmuME v%s", VERSION); + init_configured_features( &my_config); + if ( !fill_configured_features( &my_config, lpszArgument)) { + MessageBox(NULL,"Unable to parse command line arguments","Error",MB_OK); + return 0; + } + bad_glob_cflash_disk_image_file = my_config.cflash_disk_image_file; + hAccel = LoadAccelerators(hAppInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL)); if (CWindow_Init(&MainWindow, hThisInstance, szClassName, text, @@ -535,6 +645,41 @@ int WINAPI WinMain (HINSTANCE hThisInstance, NDS_Init(); + if ( my_config.arm9_gdb_port != 0) { + arm9_gdb_stub = createStub_gdb( my_config.arm9_gdb_port, + &arm9_memio, &arm9_direct_memory_iface); + + if ( arm9_gdb_stub == NULL) { + MessageBox(hwnd,"Failed to create ARM9 gdbstub","Error",MB_OK); + return -1; + } + } + if ( my_config.arm7_gdb_port != 0) { + arm7_gdb_stub = createStub_gdb( my_config.arm7_gdb_port, + &arm7_memio, + &arm7_base_memory_iface); + + if ( arm7_gdb_stub == NULL) { + MessageBox(hwnd,"Failed to create ARM7 gdbstub","Error",MB_OK); + return -1; + } + } + + + NDS_Init( arm9_memio, &arm9_ctrl_iface, + arm7_memio, &arm7_ctrl_iface); + + /* + * Activate the GDB stubs + * This has to come after the NDS_Init where the cpus are set up. + */ + if ( my_config.arm9_gdb_port != 0) { + activateStub_gdb( arm9_gdb_stub, arm9_ctrl_iface); + } + if ( my_config.arm7_gdb_port != 0) { + activateStub_gdb( arm7_gdb_stub, arm7_ctrl_iface); + } + GetPrivateProfileString("General", "Language", "0", text, 80, IniName); CheckLanguage(IDC_LANGENGLISH+atoi(text)); @@ -581,7 +726,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (lpszArgument[0] == '\"') sscanf(lpszArgument, "\"%[^\"]\"", lpszArgument); - if(LoadROM(lpszArgument)) + if(LoadROM(lpszArgument, bad_glob_cflash_disk_image_file)) { EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); @@ -690,7 +835,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM char filename[MAX_PATH] = ""; DragQueryFile((HDROP)wParam,0,filename,MAX_PATH); DragFinish((HDROP)wParam); - if(LoadROM(filename)) + if(LoadROM(filename, bad_glob_cflash_disk_image_file)) { EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED); @@ -948,7 +1093,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM LOG("%s\r\n", filename); - if(LoadROM(filename)) + if(LoadROM(filename, bad_glob_cflash_disk_image_file)) { EnableMenuItem(menu, IDM_EXEC, MF_GRAYED); EnableMenuItem(menu, IDM_PAUSE, MF_ENABLED);