diff --git a/trunk/desmume/src/gtk/Makefile.am b/trunk/desmume/src/gtk/Makefile.am index 6a7d6d521..5cb537e33 100644 --- a/trunk/desmume/src/gtk/Makefile.am +++ b/trunk/desmume/src/gtk/Makefile.am @@ -1,4 +1,4 @@ bin_PROGRAMS = desmume -desmume_SOURCES = main.cpp desmume.cpp ini.cpp dToolsList.cpp tools/ioregsView.cpp +desmume_SOURCES = main.c desmume.c ini.c dToolsList.c tools/ioregsView.c desmume_LDADD = ../libdesmume.a $(GTK_LIBS) -desmume_CXXFLAGS = $(GTK_CFLAGS) +desmume_CFLAGS = $(GTK_CFLAGS) diff --git a/trunk/desmume/src/gtk/dToolsList.c b/trunk/desmume/src/gtk/dToolsList.c new file mode 100644 index 000000000..9ea10071a --- /dev/null +++ b/trunk/desmume/src/gtk/dToolsList.c @@ -0,0 +1,10 @@ +#include "dTool.h" +#include "tools/ioregsView.h" + +dTool_t *dTools_list[] = +{ + &dTool_ioregsView +}; + +int dTools_list_size = 1; + diff --git a/trunk/desmume/src/gtk/desmume.c b/trunk/desmume/src/gtk/desmume.c new file mode 100644 index 000000000..cefbf8246 --- /dev/null +++ b/trunk/desmume/src/gtk/desmume.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include + +#include "../MMU.h" +#include "../armcpu.h" +#include "../NDSSystem.h" +#include "../cflash.h" + +#include "desmume.h" + +BOOL execute = FALSE; +BOOL click = FALSE; +BOOL fini = FALSE; +unsigned long glock = 0; + +void desmume_mem_init(); + +u8 *desmume_rom_data = NULL; +u32 desmume_last_cycle; + +void desmume_init() +{ + NDSInit(); + execute = FALSE; +} + +void desmume_free() +{ + execute = FALSE; + desmume_free_rom(); + NDSDeInit(); +} + +void desmume_mem_init() +{ + //ARM7 EXCEPTION VECTORS + MMU_writeWord(1, 0x00, 0xE25EF002); + MMU_writeWord(1, 0x04, 0xEAFFFFFE); + MMU_writeWord(1, 0x18, 0xEA000000); + MMU_writeWord(1, 0x20, 0xE92D500F); + MMU_writeWord(1, 0x24, 0xE3A00301); + MMU_writeWord(1, 0x28, 0xE28FE000); + MMU_writeWord(1, 0x2C, 0xE510F004); + MMU_writeWord(1, 0x30, 0xE8BD500F); + MMU_writeWord(1, 0x34, 0xE25EF004); + + //ARM9 EXCEPTION VECTORS + MMU_writeWord(0, 0xFFF0018, 0xEA000000); + MMU_writeWord(0, 0xFFF0020, 0xE92D500F); + MMU_writeWord(0, 0xFFF0024, 0xEE190F11); + MMU_writeWord(0, 0xFFF0028, 0xE1A00620); + MMU_writeWord(0, 0xFFF002C, 0xE1A00600); + MMU_writeWord(0, 0xFFF0030, 0xE2800C40); + MMU_writeWord(0, 0xFFF0034, 0xE28FE000); + MMU_writeWord(0, 0xFFF0038, 0xE510F004); + MMU_writeWord(0, 0xFFF003C, 0xE8BD500F); + MMU_writeWord(0, 0xFFF0040, 0xE25EF004); +} + +#define DSGBA_EXTENSTION ".ds.gba" +#define DSGBA_LOADER_SIZE 512 +enum +{ + ROM_NDS = 0, + ROM_DSGBA +}; +int desmume_load_rom(const char *filename) +{ + int i; + uint type; + const char *p = filename; + FILE *file; + u32 size, mask; + u8 *data; + + type = ROM_NDS; + + p += strlen(p); + p -= strlen(DSGBA_EXTENSTION); + if(memcmp(p, DSGBA_EXTENSTION, strlen(DSGBA_EXTENSTION)) == 0) + { + type = ROM_DSGBA; + } + + file = fopen(filename, "rb"); + if(!file) { return -1; } + + fseek(file, 0, SEEK_END); + size = ftell(file); + fseek(file, 0, SEEK_SET); + + if(type == ROM_DSGBA) + { + fseek(file, DSGBA_LOADER_SIZE, SEEK_SET); + size -= DSGBA_LOADER_SIZE; + } + + mask = size; + mask |= (mask >>1); + mask |= (mask >>2); + mask |= (mask >>4); + mask |= (mask >>8); + mask |= (mask >>16); + + data = (u8*)malloc(mask + 1); + if(!data) { fclose(file); return -1; } + + i = fread(data, 1, size, file); + + fclose(file); + + MMU_unsetRom(); + NDS_loadROM(data, mask); + desmume_rom_data = data; + + strcpy(szRomPath, dirname((char *) filename)); + cflash_close(); + cflash_init(); + + return i; +} + +void desmume_free_rom() +{ + if(desmume_rom_data) + { + free(desmume_rom_data); + desmume_rom_data = NULL; + } +} + +void desmume_reset() +{ + execute = FALSE; + desmume_mem_init(); + desmume_last_cycle = 0; +} + +void desmume_pause() +{ + execute = FALSE; +} +void desmume_resume() +{ + execute = TRUE; +} +void desmume_toggle() +{ + execute = (execute) ? FALSE : TRUE; +} +BOOL desmume_running() +{ + return execute; +} + +void desmume_cycle() +{ + desmume_last_cycle = NDS_exec((560190 << 1) - desmume_last_cycle, FALSE); +} + +void desmume_touch(s16 x, s16 y) +{ + NDS_setTouchPos(x, y); +} +void desmume_touch_release() +{ + NDS_releasTouch(); +} + +void desmume_keypad(u16 k) +{ + unsigned short k_ext = (k >> 10) & 0x3; + unsigned short k_pad = k & 0x3FF; + ((unsigned short *)ARM9Mem.ARM9_REG)[0x130>>1] = ~k_pad; + ((unsigned short *)MMU.ARM7_REG)[0x130>>1] = ~k_ext; +} + diff --git a/trunk/desmume/src/gtk/main.c b/trunk/desmume/src/gtk/main.c new file mode 100644 index 000000000..a8cc2d628 --- /dev/null +++ b/trunk/desmume/src/gtk/main.c @@ -0,0 +1,1320 @@ +#include +#include +#include +#include + +#include +#include + +#include "../MMU.h" +#include "../armcpu.h" +#include "../NDSSystem.h" +#include "../debug.h" + +#include "desmume.h" +#include "ini.h" + +#include +#include + +#define EMULOOP_PRIO (G_PRIORITY_HIGH_IDLE + 20) + +/************************ CONFIG FILE *****************************/ + +// extern char FirmwareFile[256]; +// int LoadFirmware(const char *filename); + +static gint Keypad_Config[DESMUME_NB_KEYS]; + +const char *Ini_Keypad_Values[DESMUME_NB_KEYS] = +{ + "KEY_A", + "KEY_B", + "KEY_SELECT", + "KEY_START", + "KEY_RIGHT", + "KEY_LEFT", + "KEY_UP", + "KEY_DOWN", + "KEY_R", + "KEY_L", + "KEY_Y", + "KEY_X", + "KEY_DEBUG", +}; + +#define CONFIG_FILE "desmume.ini" + +ini_file_t *Config_INI; + +int Write_ConfigFile() +{ + int i; + char buffer[64]; + ini_file_t *ini; + + ini = ini_blank_new(); + + ini_add_section(ini, "KEYS"); + + for(i = 0; i < DESMUME_NB_KEYS; i++) + { + sprintf(buffer, "%d", Keypad_Config[i]); + ini_add_value(ini, "KEYS", Ini_Keypad_Values[i], buffer); + } + +// if(FirmwareFile[0]) +// { +// ini_add_section(ini, "FIRMWARE"); +// ini_add_value(ini, "FIRMWARE", "FILE", FirmwareFile); +// } + + ini_write(ini, CONFIG_FILE); + ini_free_file(ini); + + return 0; +} + +void Load_DefaultConfig(); +int Read_ConfigFile() +{ + int i; + ini_file_t *ini; + + Load_DefaultConfig(); + + ini = ini_parse(CONFIG_FILE); + + if(ini) + { + const char *c; + + for(i = 0; i < DESMUME_NB_KEYS; i++) + { + c = ini_req_value(ini, "KEYS", Ini_Keypad_Values[i]); + if(c && *c != '0' && *c != '\0') { Keypad_Config[i] = atoi(c); } + } + +// c = ini_req_value(ini, "FIRMWARE", "FILE"); +// if(c && *c != '0' && *c != '\0') LoadFirmware(c); + + ini_free_file(ini); + } + + return 0; +} + +const gint Default_Keypad_Config[DESMUME_NB_KEYS] = +{ + 97, // a + 98, // b + 65288, // backspace + 65293, // enter + 65363, // directional arrows + 65361, + 65362, + 65364, + 65454, // numeric . + 65456, // numeric 0 + 121, // y + 120, // x + 112 +}; + +void Load_DefaultConfig() +{ + memcpy(Keypad_Config, Default_Keypad_Config, sizeof(Keypad_Config)); +} + + +/************************ GTK *******************************/ + +uint Frameskip = 0; + +//const gint StaCounter[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + +static SDL_Surface *SDL_Screenbuf; +static GdkPixmap *pPixmap; + +static GtkWidget *pWindow; +static GtkWidget *pStatusBar; +static GtkWidget *pToolbar; +static GtkWidget *pDrawingArea; + +static BOOL regMainLoop = FALSE; + +static gint pStatusBar_Ctx; +#define pStatusBar_Change(t) gtk_statusbar_pop(GTK_STATUSBAR(pStatusBar), pStatusBar_Ctx); gtk_statusbar_push(GTK_STATUSBAR(pStatusBar), pStatusBar_Ctx, t); + +gboolean EmuLoop(gpointer data); + +void About(GtkWidget* widget, gpointer data) +{ + GtkWidget *pAbout; + + pAbout = gtk_message_dialog_new (GTK_WINDOW(data), + GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, +"Desmume v0.33 \n\ +------------------\n\ +Base Emulator by Yopyop\n\ +http://yopyop156.ifrance.com/index.htm\n\ +------------------\n\ +Open source project\n\ +http://desmume.sourceforge.net/\n\ +------------------\n\ +GTK interface by Thoduv\n\ +http://thoduv.drunkencoders.com/\n\ +------------------\n\ +Build date: " __DATE__ ", " __TIME__ "."); + + gtk_dialog_run(GTK_DIALOG(pAbout)); + + gtk_widget_destroy(pAbout); +} + +static int Open(const char *filename) +{ + int i = desmume_load_rom(filename); + desmume_reset(); + return i; +} + +static void Launch() +{ + desmume_resume(); + + if(!regMainLoop) + { + g_idle_add_full(EMULOOP_PRIO, &EmuLoop, pWindow, NULL); regMainLoop = TRUE; + } + + pStatusBar_Change("Running ..."); + +} + +static void Pause() +{ + desmume_pause(); + pStatusBar_Change("Paused"); +} + +/* Sélectionne un fichier puis le charge */ +static void *Open_Select(GtkWidget* widget, gpointer data) +{ + Pause(); + + GtkFileFilter *pFilter_nds, *pFilter_dsgba, *pFilter_any; + GtkWidget *pFileSelection; + GtkWidget *pParent; + gchar *sChemin; + + pParent = GTK_WIDGET(data); + + pFilter_nds = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_nds, "*.nds"); + gtk_file_filter_set_name(pFilter_nds, "Nds binary (.nds)"); + + pFilter_dsgba = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_dsgba, "*.ds.gba"); + gtk_file_filter_set_name(pFilter_dsgba, "Nds binary with loader (.ds.gba)"); + + pFilter_any = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_any, "*"); + gtk_file_filter_set_name(pFilter_any, "All files"); + + /* Creation de la fenetre de selection */ + pFileSelection = gtk_file_chooser_dialog_new("Open...", + GTK_WINDOW(pParent), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_OK, + NULL); + /* On limite les actions a cette fenetre */ + gtk_window_set_modal(GTK_WINDOW(pFileSelection), TRUE); + + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_nds); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_dsgba); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_any); + + /* Affichage fenetre */ + switch(gtk_dialog_run(GTK_DIALOG(pFileSelection))) + { + case GTK_RESPONSE_OK: + /* Recuperation du chemin */ + sChemin = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection)); + if(Open((const char*)sChemin) < 0) + { + GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "Unable to load :\n%s", sChemin); + gtk_dialog_run(GTK_DIALOG(pDialog)); + gtk_widget_destroy(pDialog); + } + + //Launch(NULL, pWindow); + + g_free(sChemin); + break; + default: + break; + } + gtk_widget_destroy(pFileSelection); + +} + +static void Close() +{ +} + +static void Reset() +{ + desmume_reset(); + desmume_resume(); + + pStatusBar_Change("Running ..."); +} + +static void Quit(GtkWidget* widget, gpointer data) +{ + gtk_main_quit(); +} + +int ScreenCoeff_Size; + +/////////////////////////////// DRAWING SCREEN ////////////////////////////////// + +/* Drawing callback */ +int gtkFloatExposeEvent (GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + + + SDL_PixelFormat screenPixFormat; + SDL_Surface *rawImage, *screenImage; + + rawImage = SDL_CreateRGBSurfaceFrom((void*)&GPU_screen, 256, 192*2, 16, 512, 0x001F, 0x03E0, 0x7C00, 0); + if(rawImage == NULL) return 1; + + memcpy(&screenPixFormat, rawImage->format, sizeof(SDL_PixelFormat)); + + //fprintf(stderr,"%p,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",screenPixFormat.palette,screenPixFormat. BitsPerPixel,screenPixFormat. BytesPerPixel,screenPixFormat. Rloss,screenPixFormat. Gloss,screenPixFormat. Bloss,screenPixFormat. Aloss,screenPixFormat. Rshift,screenPixFormat. Gshift,screenPixFormat. Bshift,screenPixFormat. Ashift,screenPixFormat. Rmask,screenPixFormat. Gmask,screenPixFormat. Bmask,screenPixFormat. Amask,screenPixFormat.colorkey,screenPixFormat. alpha); + + screenPixFormat.BitsPerPixel = 24; + screenPixFormat.BytesPerPixel = 3; + screenPixFormat.Rshift = 0; + screenPixFormat.Gshift = 8; + screenPixFormat.Bshift = 16; + screenPixFormat.Rmask = 0x0000FF; + screenPixFormat.Gmask = 0x00FF00; + screenPixFormat.Bmask = 0xFF0000; + + screenImage = SDL_ConvertSurface(rawImage, &screenPixFormat, 0); + //screenImage = rawImage; + + /*gdk_window_clear_area (widget->window, event->area.x, event->area.y, +event->area.width, event->area.height); + gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state], + &event->area);*/ + /*gdk_draw_rgb_32_image*/ + gdk_draw_rgb_image (widget->window, + widget->style->fg_gc[widget->state],0,0,screenImage->w, screenImage->h, + GDK_RGB_DITHER_NONE,(guchar*)screenImage->pixels,screenImage->pitch); + //gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state],NULL); + + SDL_FreeSurface(screenImage); + SDL_FreeSurface(rawImage); + return 1; +} + +static void Draw() +{ +} + +/////////////////////////////// KEYS AND STYLUS UPDATE /////////////////////////////////////// + +static gboolean Stylus_Move(GtkWidget *w, GdkEventMotion *e, gpointer data) +{ + GdkModifierType state; + gint x,y; + signed long EmuX, EmuY; + + + if(click) + { + if(e->is_hint) + gdk_window_get_pointer(w->window, &x, &y, &state); + else + { + x= (gint)e->x; + y= (gint)e->y; + state=(GdkModifierType)e->state; + } + + // fprintf(stderr,"X=%d, Y=%d, S&1=%d\n", x,y,state&GDK_BUTTON1_MASK); + + if(y >= 192 && (state & GDK_BUTTON1_MASK)) + { + EmuX = x; + EmuY = y - 192; + if(EmuX<0) EmuX = 0; else if(EmuX>255) EmuX = 255; + if(EmuY<0) EmuY = 0; else if(EmuY>192) EmuY = 192; + desmume_touch(EmuX, EmuY); + } + } + + return TRUE; +} +static gboolean Stylus_Press(GtkWidget *w, GdkEventButton *e, gpointer data) +{ + GdkModifierType state; + gint x,y; + signed long EmuX, EmuY; + + if(desmume_running()) + { + if(e->button == 1) + { + click = TRUE; + + gdk_window_get_pointer(w->window, &x, &y, &state); + if(y >= 192 && (state & GDK_BUTTON1_MASK)) + { + EmuX = x; + EmuY = y - 192; + if(EmuX<0) EmuX = 0; else if(EmuX>255) EmuX = 255; + if(EmuY<0) EmuY = 0; else if(EmuY>192) EmuY = 192; + desmume_touch(EmuX, EmuY); + } + } + } + + return TRUE; +} +static gboolean Stylus_Release(GtkWidget *w, GdkEventButton *e, gpointer data) +{ + if(click) desmume_touch_release(); + click = FALSE; + return TRUE; +} + +static unsigned short Cur_Keypad = 0; + +static gint Key_Press(GtkWidget *w, GdkEventKey *e) +{ + int i; + unsigned short Key = 0; + + for(i = 0; i < DESMUME_NB_KEYS; i++) + if(e->keyval == Keypad_Config[i]) break; + + if(i < DESMUME_NB_KEYS) + { + Key = DESMUME_KEYMASK_(i); + Cur_Keypad |= Key; + if(desmume_running()) desmume_keypad(Cur_Keypad); + } + + //fprintf(stderr,"P:%d(%d)->%X => [%X]\n", e->keyval, e->hardware_keycode, Key, Cur_Keypad); + return 1; +} +static gint Key_Release(GtkWidget *w, GdkEventKey *e) +{ + int i; + unsigned short Key = 0; + + for(i = 0; i < DESMUME_NB_KEYS; i++) + if(e->keyval == Keypad_Config[i]) break; + + if(i < DESMUME_NB_KEYS) + { + Key = DESMUME_KEYMASK_(i); + Cur_Keypad &= ~Key; + if(desmume_running()) desmume_keypad(Cur_Keypad); + } + + //fprintf(stderr,"R:%d(%d)->%X => [%X]\n", e->keyval, e->hardware_keycode, Key, Cur_Keypad); + return 1; +} + +/////////////////////////////// CONTROLS EDIT ////////////////////////////////////// + +const char *Keys_Name[DESMUME_NB_KEYS] = +{ + "A", + "B", + "Select", + "Start", + "Right", + "Left", + "Up", + "Down", + "R", + "L", + "Y", + "X", + "Debug" +}; + +GtkWidget *mkLabel; +gint Modify_Key_Chosen = 0; + +void Modify_Key_Press(GtkWidget *w, GdkEventKey *e) +{ + char YouPressed[128]; + Modify_Key_Chosen = e->keyval; + sprintf(YouPressed, "You pressed : %d\nClick OK to keep this key.", e->keyval); + gtk_label_set(GTK_LABEL(mkLabel), YouPressed); +} + +gint Keypad_Temp[DESMUME_NB_KEYS]; + +void Modify_Key(GtkWidget* widget, gpointer data) +{ + gint Key = (gint)data; + char Title[64]; + char Key_Label[64]; + + GtkWidget *mkDialog; + + sprintf(Title, "Press \"%s\" key ...\n", Keys_Name[Key]); + mkDialog = gtk_dialog_new_with_buttons(Title, + GTK_WINDOW(pWindow), + GTK_DIALOG_MODAL, + GTK_STOCK_OK,GTK_RESPONSE_OK, + GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, + NULL); + + g_signal_connect(G_OBJECT(mkDialog), "key_press_event", G_CALLBACK(Modify_Key_Press), NULL); + + mkLabel = gtk_label_new(Title); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(mkDialog)->vbox), mkLabel,TRUE, FALSE, 0); + + gtk_widget_show_all(GTK_DIALOG(mkDialog)->vbox); + + switch(gtk_dialog_run(GTK_DIALOG(mkDialog))) + { + case GTK_RESPONSE_OK: + + Keypad_Temp[Key] = Modify_Key_Chosen; + sprintf(Key_Label, "%s (%d)", Keys_Name[Key], Keypad_Temp[Key]); + gtk_button_set_label(GTK_BUTTON(widget), Key_Label); + + break; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_NONE: + Modify_Key_Chosen = 0; + break; + } + + gtk_widget_destroy(mkDialog); + +} + +void Edit_Controls(GtkWidget* widget, gpointer data) +{ + char Key_Label[64]; + int i; + GtkWidget *ecDialog; + GtkWidget *ecKey; + + memcpy(&Keypad_Temp, &Keypad_Config, sizeof(Keypad_Config)); + + ecDialog = gtk_dialog_new_with_buttons("Edit controls", + GTK_WINDOW(pWindow), + GTK_DIALOG_MODAL, + GTK_STOCK_OK,GTK_RESPONSE_OK, + GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, + NULL); + + + for(i = 0; i < DESMUME_NB_KEYS; i++) + { + sprintf(Key_Label, "%s (%d)", Keys_Name[i], Keypad_Temp[i]); + ecKey = gtk_button_new_with_label(Key_Label); + g_signal_connect(G_OBJECT(ecKey), "clicked", G_CALLBACK(Modify_Key), (gpointer*)i); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ecDialog)->vbox), ecKey,TRUE, FALSE, 0); + } + + gtk_widget_show_all(GTK_DIALOG(ecDialog)->vbox); + + switch (gtk_dialog_run(GTK_DIALOG(ecDialog))) + { + case GTK_RESPONSE_OK: + memcpy(&Keypad_Config, &Keypad_Temp, sizeof(Keypad_Config)); + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_NONE: + break; + } + gtk_widget_destroy(ecDialog); + +} + +///////////////////////////////// SCREEN SCALING ////////////////////////////// + +#define MAX_SCREENCOEFF 4 + +void Modify_ScreenCoeff(GtkWidget* widget, gpointer data) +{ + int Size = (int)data; + + gtk_drawing_area_size(GTK_DRAWING_AREA(pDrawingArea), 256 * Size, 384 * Size); + gtk_widget_set_usize (pDrawingArea, 256 * Size, 384 * Size); + + ScreenCoeff_Size = Size; + +} + +/////////////////////////////// LAYER HIDING ///////////////////////////////// + +void Modify_Layer(GtkWidget* widget, gpointer data) +{ + int i; + gchar *Layer = (gchar*)data; + + if(!desmume_running()) + { + return; + } + + if(memcmp(Layer, "Sub", 3) == 0) + { + if(memcmp(Layer, "Sub BG", 6) == 0) + { + i = atoi(Layer + strlen("Sub BG ")); + if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)) == TRUE) { + if(!SubScreen.gpu->dispBG[i]) GPU_addBack(SubScreen.gpu, i); + } else { + if(SubScreen.gpu->dispBG[i]) GPU_remove(SubScreen.gpu, i); } + } + else + { + /* TODO: Disable sprites */ + } + } + else + { + if(memcmp(Layer, "Main BG", 7) == 0) + { + i = atoi(Layer + strlen("Main BG ")); + if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)) == TRUE) { + if(!MainScreen.gpu->dispBG[i]) GPU_addBack(MainScreen.gpu, i); + } else { + if(MainScreen.gpu->dispBG[i]) GPU_remove(MainScreen.gpu, i); } + } + else + { + /* TODO: Disable sprites */ + } + } + //fprintf(stderr,"Changed %s to %d\n",Layer,gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); +} + +#include "DeSmuME.xpm" + +const char *Layers_Menu[10] = +{ + "Main BG 0", + "Main BG 1", + "Main BG 2", + "Main BG 3", + "Main OBJ", + "SUB BG 0", + "SUB BG 1", + "SUB BG 2", + "SUB BG 3", + "SUB OBJ", +}; + +/////////////////////////////// PRINTSCREEN ///////////////////////////////// +// TODO: improve (let choose filename, and use png) + +typedef struct +{ + unsigned long header_size; + long width; + long height; + unsigned short r1; + unsigned short depth; + unsigned long r2; + unsigned long size; + long r3,r4; + unsigned long r5,r6; +}BmpImageHeader; + +typedef struct +{ + unsigned short type; + unsigned long size; + unsigned short r1, r2; + unsigned long data_offset; +}BmpFileHeader; + + +int WriteBMP(const char *filename,u16 *bmp){ + BmpFileHeader fileheader; + BmpImageHeader imageheader; + fileheader.size = 14; + fileheader.type = 0x4D42; + fileheader.r1 = 0; + fileheader.r2=0; + fileheader.data_offset = 14+40; + + imageheader.header_size = 40; + imageheader.r1 = 1; + imageheader.depth = 24; + imageheader.r2 = 0; + imageheader.size = 256 * 192*2 * 3; + imageheader.r3 = 0; + imageheader.r4 = 0; + imageheader.r5 = 0; + imageheader.r6 = 0; + imageheader.width = 256; + imageheader.height = 192*2; + + FILE *fichier = fopen(filename,"wb"); + //fwrite(&fileheader, 1, 14, fichier); + + //fwrite(&imageheader, 1, 40, fichier); + fwrite( &fileheader.type, sizeof(fileheader.type), 1, fichier); + fwrite( &fileheader.size, sizeof(fileheader.size), 1, fichier); + fwrite( &fileheader.r1, sizeof(fileheader.r1), 1, fichier); + fwrite( &fileheader.r2, sizeof(fileheader.r2), 1, fichier); + fwrite( &fileheader.data_offset, sizeof(fileheader.data_offset), 1, fichier); + fwrite( &imageheader.header_size, sizeof(imageheader.header_size), 1, fichier); + fwrite( &imageheader.width, sizeof(imageheader.width), 1, fichier); + fwrite( &imageheader.height, sizeof(imageheader.height), 1, fichier); + fwrite( &imageheader.r1, sizeof(imageheader.r1), 1, fichier); + fwrite( &imageheader.depth, sizeof(imageheader.depth), 1, fichier); + fwrite( &imageheader.r2, sizeof(imageheader.r2), 1, fichier); + fwrite( &imageheader.size, sizeof(imageheader.size), 1, fichier); + fwrite( &imageheader.r3, sizeof(imageheader.r3), 1, fichier); + fwrite( &imageheader.r4, sizeof(imageheader.r4), 1, fichier); + fwrite( &imageheader.r5, sizeof(imageheader.r5), 1, fichier); + fwrite( &imageheader.r6, sizeof(imageheader.r6), 1, fichier); + int i,j,k; + for(j=0;j<192*2;j++)for(i=0;i<256;i++){ + unsigned char r,g,b; + u16 pixel = bmp[i+(192*2-j)*256]; + r = pixel>>10; + pixel-=r<<10; + g = pixel>>5; + pixel-=g<<5; + b = pixel; + r*=255/31; + g*=255/31; + b*=255/31; + fwrite(&r, 1, sizeof(char), fichier); + fwrite(&g, 1, sizeof(char), fichier); + fwrite(&b, 1, sizeof(char), fichier); +} + fclose(fichier); +return 1; +} + +static void Printscreen(GtkWidget* widget, gpointer data) +{ + WriteBMP("./test.bmp",GPU_screen); +} + +/////////////////////////////// DS CONFIGURATION ////////////////////////////////// + +#if 0 + +char FirmwareFile[256]; + +int LoadFirmware(const char *filename) +{ + int i; + u32 size; + FILE *f; + + strncpy(FirmwareFile, filename, 256); + + f = fopen(filename, "rb"); + if(!f) return -1; + + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + + if(size > MMU.spi7.fw.size) { fclose(f); return -1; } /* this must be a small file*/ + + i = fread(MMU.spi7.fw.data, size, 1, f); + + fclose(f); + + return i; +} + +int SelectFirmwareFile_Load(GtkWidget *w, gpointer data) +{ + GtkFileFilter *pFilter_nds, *pFilter_bin, *pFilter_any; + GtkWidget *pFileSelection; + GtkWidget *pParent; + gchar *sChemin; + + BOOL oldState = desmume_running(); + Pause(); + + pParent = GTK_WIDGET(data); + + pFilter_nds = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_nds, "*.nds"); + gtk_file_filter_set_name(pFilter_nds, "Nds binary (.nds)"); + + pFilter_bin = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_bin, "*.bin"); + gtk_file_filter_set_name(pFilter_bin, "Binary file (.bin)"); + + pFilter_any = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_any, "*"); + gtk_file_filter_set_name(pFilter_any, "All files"); + + /* Creation de la fenetre de selection */ + pFileSelection = gtk_file_chooser_dialog_new("Load firmware...", + GTK_WINDOW(pParent), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_OK, + NULL); + /* On limite les actions a cette fenetre */ + gtk_window_set_modal(GTK_WINDOW(pFileSelection), TRUE); + + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_nds); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_bin); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_any); + + if(FirmwareFile[0]) gtk_file_chooser_select_uri(GTK_FILE_CHOOSER(pFileSelection), FirmwareFile); + + /* Affichage fenetre */ + switch(gtk_dialog_run(GTK_DIALOG(pFileSelection))) + { + case GTK_RESPONSE_OK: + /* Recuperation du chemin */ + sChemin = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection)); + if(LoadFirmware((const char*)sChemin) < 0) + { + GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Unable to load :\n%s", sChemin); + gtk_dialog_run(GTK_DIALOG(pDialog)); + gtk_widget_destroy(pDialog); + } + else + { + GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Selected firmware :\n%s", sChemin); + gtk_dialog_run(GTK_DIALOG(pDialog)); + gtk_widget_destroy(pDialog); + } + + g_free(sChemin); + break; + default: + break; + } + gtk_widget_destroy(pFileSelection); + + if(oldState) Launch(); + +} + +int SelectFirmwareFile_Load(GtkWidget *w, gpointer data) +{ + GtkFileFilter *pFilter_nds, *pFilter_bin, *pFilter_any; + GtkWidget *pFileSelection; + GtkWidget *pParent; + gchar *sChemin; + + BOOL oldState = desmume_running(); + Pause(); + + pParent = GTK_WIDGET(data); + + pFilter_nds = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_nds, "*.nds"); + gtk_file_filter_set_name(pFilter_nds, "Nds binary (.nds)"); + + pFilter_bin = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_bin, "*.bin"); + gtk_file_filter_set_name(pFilter_bin, "Binary file (.bin)"); + + pFilter_any = gtk_file_filter_new(); + gtk_file_filter_add_pattern(pFilter_any, "*"); + gtk_file_filter_set_name(pFilter_any, "All files"); + + /* Creation de la fenetre de selection */ + pFileSelection = gtk_file_chooser_dialog_new("Save firmware...", + GTK_WINDOW(pParent), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_OK, + NULL); + /* On limite les actions a cette fenetre */ + gtk_window_set_modal(GTK_WINDOW(pFileSelection), TRUE); + + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_nds); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_bin); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_any); + + if(FirmwareFile[0]) gtk_file_chooser_select_uri(GTK_FILE_CHOOSER(pFileSelection), FirmwareFile); + + /* Affichage fenetre */ + switch(gtk_dialog_run(GTK_DIALOG(pFileSelection))) + { + case GTK_RESPONSE_OK: + /* Recuperation du chemin */ + sChemin = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection)); + if(LoadFirmware((const char*)sChemin) < 0) + { + GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Unable to load :\n%s", sChemin); + gtk_dialog_run(GTK_DIALOG(pDialog)); + gtk_widget_destroy(pDialog); + } + else + { + GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Selected firmware :\n%s", sChemin); + gtk_dialog_run(GTK_DIALOG(pDialog)); + gtk_widget_destroy(pDialog); + } + + g_free(sChemin); + break; + default: + break; + } + gtk_widget_destroy(pFileSelection); + + if(oldState) Launch(); + +} + +#endif + +/////////////////////////////// FRAMESKIP ///////////////////////////////// + +#define MAX_FRAMESKIP 10 + +void Modify_Frameskip(GtkWidget *widget, gpointer data) +{ + Frameskip = (int)data; +} + +/////////////////////////////// TOOLS MANAGEMENT /////////////////////////////// + +#include "dTool.h" + +extern const dTool_t *dTools_list[]; +extern const int dTools_list_size; + +BOOL *dTools_running; + +void Start_dTool(GtkWidget *widget, gpointer data) +{ + int tool = (int)data; + + if(dTools_running[tool]) return; + + dTools_list[tool]->open(tool); + dTools_running[tool] = TRUE; +} + +void dTool_CloseCallback(int tool) +{ + dTools_running[tool] = FALSE; +} + +/////////////////////////////// MAIN EMULATOR LOOP /////////////////////////////// + +static inline void _updateDTools() +{ + int i; + for(i = 0; i < dTools_list_size; i++) + { + if(dTools_running[i]) { dTools_list[i]->update(); } + } +} + +Uint32 fps, fps_SecStart, fps_FrameCount; + +gboolean EmuLoop(gpointer data) +{ + int i; + + if(desmume_running()) /* Si on est en train d'executer le programme ... */ + { + + fps_FrameCount += Frameskip + 1; + if(!fps_SecStart) fps_SecStart = SDL_GetTicks(); + if(SDL_GetTicks() - fps_SecStart >= 1000) + { + fps_SecStart = SDL_GetTicks(); + fps = fps_FrameCount; + fps_FrameCount = 0; + + char Title[32]; + sprintf(Title, "Desmume - %dfps", fps); + gtk_window_set_title(GTK_WINDOW(pWindow), Title); + } + + desmume_cycle(); /* Emule ! */ + for(i = 0; i < Frameskip; i++) desmume_cycle(); /* cycles supplémentaires pour le frameskip */ + + Draw(); + + _updateDTools(); + gtk_widget_queue_draw(pDrawingArea); + + return TRUE; + } + + regMainLoop = FALSE; + return FALSE; +} + + +/////////////////////////////// MAIN /////////////////////////////// + +#ifdef WIN32 +int WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) +{ + main(0,NULL); +} +#endif + +int main (int argc, char *argv[]) +{ + int i; + + const char *commandLine_File = NULL; + GtkWidget *pVBox; + GtkWidget *pMenuBar; + GtkWidget *pMenu, *pSubMenu; + GtkWidget *pMenuItem, *pSubMenuItem; + + pthread_t emu_thread; + + if(argc == 2) commandLine_File = argv[1]; + +#ifdef DEBUG + LogStart(); +#endif + + gtk_init(&argc, &argv); + SDL_Init(SDL_INIT_VIDEO); + desmume_init(); + + dTools_running = (BOOL*)malloc(sizeof(BOOL) * dTools_list_size); + for(i=0; i= 2) && (GTK_MINOR_VERSION >= 6)) + pMenuItem = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PLAY,NULL); +#else + pMenuItem = gtk_menu_item_new_with_label("Run"); +#endif + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(Launch), (GtkWidget*) pWindow); + gtk_menu_shell_append(GTK_MENU_SHELL(mEmulation), pMenuItem); + +#if ((GTK_MAJOR_VERSION >= 2) && (GTK_MINOR_VERSION >= 6)) + pMenuItem = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PAUSE,NULL); +#else + pMenuItem = gtk_menu_item_new_with_label("Pause"); +#endif + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(Pause), (GtkWidget*) pWindow); + gtk_menu_shell_append(GTK_MENU_SHELL(mEmulation), pMenuItem); + + pMenuItem = gtk_menu_item_new_with_label("Reset"); + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(Reset), (GtkWidget*) pWindow); + gtk_menu_shell_append(GTK_MENU_SHELL(mEmulation), pMenuItem); + + mFrameskip = gtk_menu_new(); + pMenuItem = gtk_menu_item_new_with_label("Frameskip"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), mFrameskip); + gtk_menu_shell_append(GTK_MENU_SHELL(mEmulation), pMenuItem); + + for(i = 0; i < MAX_FRAMESKIP; i++) { + char frameskipRadio_buf[16]; + sprintf(frameskipRadio_buf, "%d", i); + if(i>0) mFrameskip_Radio[i] = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(mFrameskip_Radio[i-1]), frameskipRadio_buf); + else mFrameskip_Radio[i] = gtk_radio_menu_item_new_with_label(NULL, frameskipRadio_buf); + g_signal_connect(G_OBJECT(mFrameskip_Radio[i]), "activate", G_CALLBACK(Modify_Frameskip), (gpointer)i); + gtk_menu_shell_append(GTK_MENU_SHELL(mFrameskip), mFrameskip_Radio[i]); + } + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mFrameskip_Radio[0]), TRUE); + + mGraphics = gtk_menu_new(); + pMenuItem = gtk_menu_item_new_with_label("Graphics"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), mGraphics); + gtk_menu_shell_append(GTK_MENU_SHELL(mEmulation), pMenuItem); + +// TODO: Un jour, peut être... >< + mSize = gtk_menu_new(); + pMenuItem = gtk_menu_item_new_with_label("Size"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), mSize); + gtk_menu_shell_append(GTK_MENU_SHELL(mGraphics), pMenuItem); + + for(i = 1; i < MAX_SCREENCOEFF; i++) { + char sizeRadio_buf[16]; + sprintf(sizeRadio_buf, "x%d", i); + if(i>1) mSize_Radio[i] = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(mSize_Radio[i-1]), sizeRadio_buf); + else mSize_Radio[i] = gtk_radio_menu_item_new_with_label(NULL, sizeRadio_buf); + g_signal_connect(G_OBJECT(mSize_Radio[i]), "activate", G_CALLBACK(Modify_ScreenCoeff), (gpointer)i); + gtk_menu_shell_append(GTK_MENU_SHELL(mSize), mSize_Radio[i]); + } + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mFrameskip_Radio[0]), TRUE); + + mLayers = gtk_menu_new(); + pMenuItem = gtk_menu_item_new_with_label("Layers"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), mLayers); + gtk_menu_shell_append(GTK_MENU_SHELL(mGraphics), pMenuItem); + + for(i = 0; i < 10; i++) { + mLayers_Radio[i] = gtk_check_menu_item_new_with_label(Layers_Menu[i]); + g_signal_connect(G_OBJECT(mLayers_Radio[i]), "activate", G_CALLBACK(Modify_Layer), (void*)Layers_Menu[i]); + gtk_menu_shell_append(GTK_MENU_SHELL(mLayers), mLayers_Radio[i]); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mLayers_Radio[i]), TRUE); + } + + + /** Menu "Options" **/ + GtkWidget *mConfig = gtk_menu_new(); + + pMenuItem = gtk_menu_item_new_with_label("Edit controls"); + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(Edit_Controls), (GtkWidget*) pWindow); + gtk_menu_shell_append(GTK_MENU_SHELL(mConfig), pMenuItem); + +#if 0 + + GtkWidget *mFirmware; + + mFirmware = gtk_menu_new(); + pMenuItem = gtk_menu_item_new_with_label("Firmware"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), mFirmware); + gtk_menu_shell_append(GTK_MENU_SHELL(mConfig), pMenuItem); + + pMenuItem = gtk_menu_item_new_with_label("Select..."); + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(SelectFirmwareFile), (gpointer)0); + gtk_menu_shell_append(GTK_MENU_SHELL(mFirmware), pMenuItem); + + pMenuItem = gtk_menu_item_new_with_label("Config"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), mConfig); + gtk_menu_shell_append(GTK_MENU_SHELL(pMenuBar), pMenuItem); + +#endif + + /** Menu "Outils" **/ + + pMenu = gtk_menu_new(); + + for(i = 0; i < dTools_list_size; i++) + { + pMenuItem = gtk_menu_item_new_with_label(dTools_list[i]->name); + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(Start_dTool), (gpointer)i); + gtk_menu_shell_append(GTK_MENU_SHELL(pMenu), pMenuItem); + } + + pMenuItem = gtk_menu_item_new_with_label("Tools"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), pMenu); + gtk_menu_shell_append(GTK_MENU_SHELL(pMenuBar), pMenuItem); + + /** Menu "?" **/ + + pMenu = gtk_menu_new(); + +#if ((GTK_MAJOR_VERSION >= 2) && (GTK_MINOR_VERSION >= 6)) + pMenuItem = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT,NULL); +#else + pMenuItem = gtk_menu_item_new_with_label("About"); +#endif + g_signal_connect(G_OBJECT(pMenuItem), "activate", G_CALLBACK(About), (GtkWidget*) pWindow); + gtk_menu_shell_append(GTK_MENU_SHELL(pMenu), pMenuItem); + + pMenuItem = gtk_menu_item_new_with_label("?"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(pMenuItem), pMenu); + gtk_menu_shell_append(GTK_MENU_SHELL(pMenuBar), pMenuItem); + + /* Ajout du menu a la fenetre */ + gtk_box_pack_start(GTK_BOX(pVBox), pMenuBar, FALSE, FALSE, 0); + + /* Création de la Toolbar */ + + pToolbar = gtk_toolbar_new(); + gtk_box_pack_start(GTK_BOX(pVBox), pToolbar, FALSE, FALSE, 0); + gtk_toolbar_insert_stock(GTK_TOOLBAR(pToolbar), + GTK_STOCK_OPEN, + "Open", + NULL, + G_CALLBACK(Open_Select), + NULL, + -1); + + gtk_toolbar_insert_stock(GTK_TOOLBAR(pToolbar), +#if ((GTK_MAJOR_VERSION >= 2) && (GTK_MINOR_VERSION >= 6)) + GTK_STOCK_MEDIA_PLAY, +#else + NULL +#endif + "Run", + NULL, + G_CALLBACK(Launch), + NULL, + -1); + gtk_toolbar_insert_stock(GTK_TOOLBAR(pToolbar), +#if ((GTK_MAJOR_VERSION >= 2) && (GTK_MINOR_VERSION >= 6)) + GTK_STOCK_MEDIA_PAUSE, +#else + NULL, +#endif + + "Pause", + NULL, + G_CALLBACK(Pause), + NULL, + -1); + gtk_toolbar_insert_stock(GTK_TOOLBAR(pToolbar), + GTK_STOCK_QUIT, + "Quit", + NULL, + G_CALLBACK(Quit), + NULL, + -1); + + /* Création de l'endroit pour l'affichage des écrans */ + + pDrawingArea= gtk_drawing_area_new(); + + gtk_drawing_area_size(GTK_DRAWING_AREA(pDrawingArea), 256, 384); + gtk_widget_set_usize (pDrawingArea, 256, 384); + + gtk_widget_set_events(pDrawingArea, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK ); + + g_signal_connect(G_OBJECT(pDrawingArea), "button_press_event", G_CALLBACK(Stylus_Press), NULL); + g_signal_connect(G_OBJECT(pDrawingArea), "button_release_event", G_CALLBACK(Stylus_Release), NULL); + g_signal_connect(G_OBJECT(pDrawingArea), "motion_notify_event", G_CALLBACK(Stylus_Move), NULL); + + + g_signal_connect( G_OBJECT(pDrawingArea), "realize", G_CALLBACK(Draw), NULL ) ; + g_signal_connect( G_OBJECT(pDrawingArea), "expose_event", G_CALLBACK(gtkFloatExposeEvent), NULL ) ; + + gtk_box_pack_start(GTK_BOX(pVBox), pDrawingArea, FALSE, FALSE, 0); + + /* Création de la barre d'état */ + + pStatusBar = gtk_statusbar_new(); + + pStatusBar_Ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(pStatusBar), "Global"); + + pStatusBar_Change("Desmume"); + + gtk_box_pack_end(GTK_BOX(pVBox), pStatusBar, FALSE, FALSE, 0); + + gtk_widget_show_all(pWindow); + + //LoadFirmware("fw.bin"); + + /* Vérifie la ligne de commandes */ + if(commandLine_File) + { + if(Open(commandLine_File) >= 0) + { + Launch(); + } + else + { + GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pWindow), + GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "Unable to load :\n%s", commandLine_File); + gtk_dialog_run(GTK_DIALOG(pDialog)); + gtk_widget_destroy(pDialog); + } + } + + /* Boucle principale */ + +// gtk_idle_add(&EmuLoop, pWindow); +// g_idle_add(&EmuLoop, pWindow); + + gtk_main(); + + desmume_free(); + +#ifdef DEBUG + LogStop(); +#endif + + SDL_Quit(); + + Write_ConfigFile(); + + return EXIT_SUCCESS; +} + + + + + diff --git a/trunk/desmume/src/gtk/tools/ioregsView.c b/trunk/desmume/src/gtk/tools/ioregsView.c new file mode 100644 index 000000000..d0888a565 --- /dev/null +++ b/trunk/desmume/src/gtk/tools/ioregsView.c @@ -0,0 +1,465 @@ +#include +#include "../dTool.h" + +#include "../MMU.h" +#include "../nds/system.h" +#include "../nds/serial.h" + +#define TOOL_NAME "IO regs view" + +BOOL CPUS [2] = {TRUE, TRUE}; + +static GtkWidget *mWin[2]; +static GtkWidget *mVbox0[2]; +static GtkWidget *mIoRegCombo[2]; +static GtkWidget *mRegInfos[2]; + +typedef void (*reg_dispFn)(int c); +typedef u32 (*reg_valFn)(int c); + +typedef struct +{ + char name[64]; + u32 adress; + int size; + reg_dispFn create; + reg_dispFn update; + reg_dispFn destroy; + reg_valFn value; +} reg_t; + +static reg_t *current_reg[2] = {NULL, NULL}; + +#define REGFN_BEGIN(reg) \ + GtkWidget **_wl_ = Widgets_##reg [c]; + +#define BIT_CHECK(w, n, s) { \ + char _bit_check_buf[64]; \ + sprintf(_bit_check_buf, "Bit %d: %s", n,s); \ + _wl_[w] = gtk_check_button_new_with_label(_bit_check_buf ); \ + gtk_box_pack_start(GTK_BOX(mVbox0[c]), _wl_[w], FALSE, FALSE, 0); } + +#define BIT_COMBO(w,n,s) { \ + _wl_[w] = gtk_hbox_new(FALSE, 0); \ + gtk_box_pack_start(GTK_BOX(mVbox0[c]), _wl_[w], FALSE, FALSE, 0); } \ + char _bit_combo_buf[64]; \ + sprintf(_bit_combo_buf, "Bits %s: %s", n,s); \ + GtkWidget *__combo_lbl_tmp = gtk_label_new(_bit_combo_buf); \ + GtkWidget *__combo_tmp = gtk_combo_box_new_text(); \ + +#define BIT_COMBO_ADD(w, s) { \ + gtk_combo_box_append_text(GTK_COMBO_BOX(__combo_tmp), s); } + +#define BIT_COMBO_GET(w) (GTK_WIDGET(g_list_first(gtk_container_get_children(GTK_CONTAINER(_wl_[w])))->data)) + +#define BIT_COMBO_END(w) \ + gtk_box_pack_start(GTK_BOX(_wl_[w]), __combo_tmp, FALSE, FALSE, 0); \ + gtk_box_pack_start(GTK_BOX(_wl_[w]), __combo_lbl_tmp, FALSE, FALSE, 0); + +#define CREA_END() \ + gtk_widget_show_all(mWin[c]); + +/////////////////////////////// REG_IME /////////////////////////////// +static GtkWidget *Widgets_REG_IME[2][1]; +static void crea_REG_IME(int c) +{ + REGFN_BEGIN(REG_IME); + BIT_CHECK(0, 0, "Master interrupt enable"); + CREA_END(); +} +static void updt_REG_IME(int c) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Widgets_REG_IME[c][0]), MMU.reg_IME[c] ? 1 : 0); } +static void dest_REG_IME(int c) { gtk_widget_destroy(Widgets_REG_IME[c][0]); } +static u32 val_REG_IME(int c) { return MMU.reg_IME[c]; } + +/////////////////////////////// REG_IE /////////////////////////////// + +static const char *interrupt_strings[25] = +{ + "LCD VBlank", // 0 + "LCD HBlank", // 1 + "LCD VCount", // 2 + "Timer0 overflow", // 3 + "Timer1 overflow", + "Timer2 overflow", + "Timer3 overflow", + "Serial communication (RTC)", // 7 + "DMA0", // 8 + "DMA1", + "DMA2", + "DMA3", + "Keypad", // 12 + "Game Pak (GBA slot)", // 13 + "", // 14 + "", // 15 + "IPC Sync", // 16 + "IPC Send FIFO empty", // 17 + "IPC Recv FIFO not empty", // 18 + "Card Data Transfer Completion (DS-card slot)", // 29 + "Card IREQ_MC (DS-card slot)", // 20 + "Geometry (3D) command FIFO", // 21 + "Screens unfolding", // 22 + "SPI bus", // 23 + "Wifi" // 24 +}; +#define INTERRUPT_SKIP(c) if(i == 14 || i == 15 || (c == 0 && (i == 7 || i == 22 || i == 23 || i == 24)) || (c == 1 && i == 21))continue; + +static GtkWidget *Widgets_REG_IE[2][32]; +static void crea_REG_IE(int c) +{ + REGFN_BEGIN(REG_IE); + int i; + for(i = 0; i < 24; i++) { INTERRUPT_SKIP(c); BIT_CHECK(i, i, interrupt_strings[i]); } + CREA_END(); +} +static void updt_REG_IE(int c) +{ + int i; + for(i = 0; i < 24; i++) { INTERRUPT_SKIP(c); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Widgets_REG_IE[c][i]), (MMU.reg_IE[c] & (1<>1]&(1<>1]; } + +/////////////////////////////// POWER_CR /////////////////////////////// +static const char *powercr9_strings[] = +{ + "Enable LCD", + "2D A engine", + "3D render engine", + "3D geometry engine (matrix)", + "", "", "", "", "", + "2D B engine", + "", "", "", "", "", + "Swap LCD" +}; +static const char *powercr7_strings[] = +{ + "Sound speakers", + "Wifi system" +}; +#define POWER_CR_SKIP(c) if(i==4||i==5||i==6||i==7||i==8||i==10||i==11|i==12|i==13||i==14)continue; +#define POWER_CR_SIZE(c) ((c==0)?16:2) + +static GtkWidget *Widgets_POWER_CR[2][16]; +static void crea_POWER_CR(int c) +{ + REGFN_BEGIN(POWER_CR); + int i; + for(i = 0; i < POWER_CR_SIZE(c); i++) { POWER_CR_SKIP(c); BIT_CHECK(i, i, (c==0?powercr9_strings:powercr7_strings)[i]); } + CREA_END(); +} +static void updt_POWER_CR(int c) +{ + int i; + for(i = 0; i < POWER_CR_SIZE(c); i++) { POWER_CR_SKIP(c); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Widgets_POWER_CR[c][i]), (((u16 *)(MMU.MMU_MEM[c][0x40]))[0x304>>1]&(1<>1]; } + +/////////////////////////////// REG_SPICNT /////////////////////////////// +static const char *spicnt_strings[16] = +{ + "Baudrate", + "","","","","","", + "Busy flag", + "Device", + "", + "Transfer size", + "Chipselect Hold", + "Unknown", + "Unknown", + "Interrupt request", + "Enable SPI bus", +}; + +// 0-1 Baudrate (0=4MHz/Firmware, 1=2MHz/Touchscr, 2=1MHz/Powerman., 3=512KHz) +// 2-6 Not used (Zero) +// 7 Busy Flag (0=Ready, 1=Busy) (presumably Read-only) +// 8-9 Device Select (0=Powerman., 1=Firmware, 2=Touchscr, 3=Reserved) +// 10 Transfer Size (0=8bit, 1=16bit) +// 11 Chipselect Hold (0=Deselect after transfer, 1=Keep selected) +// 12 Unknown (usually 0) (set equal to Bit11 when BIOS accesses firmware) +// 13 Unknown (usually 0) (set to 1 when BIOS accesses firmware) +// 14 Interrupt Request (0=Disable, 1=Enable) +// 15 SPI Bus Enable (0=Disable, 1=Enable) + + +#define REG_SPICNT_SKIP(c) if(i==1||i==2||i==3||i==4||i==5||i==6||i==9)continue; +#define REG_SPICNT_ISCHECK(c) (i==7||i==11||i==14||i==15||i==12||i==13) + +static GtkWidget *Widgets_REG_SPICNT[2][16]; +static void crea_REG_SPICNT(int c) +{ + REGFN_BEGIN(REG_SPICNT); + int i; + for(i = 0; i < 16; i++) { REG_SPICNT_SKIP(c); + if(REG_SPICNT_ISCHECK(c)) { BIT_CHECK(i, i, spicnt_strings[i]); } + else if(i == 0) { BIT_COMBO(i, "0-1", spicnt_strings[0]); + BIT_COMBO_ADD(i, "0= 4Mhz"); + BIT_COMBO_ADD(i, "1= 2Mhz"); + BIT_COMBO_ADD(i, "2= 1Mhz"); + BIT_COMBO_ADD(i, "3= 512Khz"); + BIT_COMBO_END(i); } + else if(i == 8) { BIT_COMBO(i, "8-9", spicnt_strings[8]); + BIT_COMBO_ADD(i, "0= Power management device"); + BIT_COMBO_ADD(i, "1= Firmware"); + BIT_COMBO_ADD(i, "2= Touchscreen/Microphone"); + BIT_COMBO_ADD(i, "3= Reserved/Prohibited"); + BIT_COMBO_END(i); } + else if(i == 10) { BIT_COMBO(i, "10", spicnt_strings[10]); + BIT_COMBO_ADD(i, "0= 8 bits"); + BIT_COMBO_ADD(i, "1= 16 bits"); + BIT_COMBO_END(i); } + } + CREA_END(); +} +static u32 val_REG_SPICNT(int c) { return ((u16 *)(MMU.MMU_MEM[c][0x40]))[0x1C0>>1]; } +static void updt_REG_SPICNT(int c) +{ + REGFN_BEGIN(REG_SPICNT); + u16 val = val_REG_SPICNT(c); + int i; + for(i = 0; i < 16; i++) { REG_SPICNT_SKIP(c); + if(REG_SPICNT_ISCHECK(c)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Widgets_REG_SPICNT[c][i]), (((u16 *)(MMU.MMU_MEM[c][0x40]))[0x1C0>>1]&(1<>8)&3); } + else if(i == 10) { gtk_combo_box_set_active(GTK_COMBO_BOX(BIT_COMBO_GET(i)) , (val>>10)&1); } + } +} +static void dest_REG_SPICNT(int c) +{ + int i; + for(i = 0; i < 16; i++) { REG_SPICNT_SKIP(c); gtk_widget_destroy(Widgets_REG_SPICNT[c][i]); } +} + +/////////////////////////////// LIST /////////////////////////////// +#define BITS_8 1 +#define BITS_16 2 +#define BITS_32 4 +static const char *bits_strings[5] = {"0", "8", "16", "24", "32"}; + +#define REG_STR(r, s) {#r, r, s, &crea_##r, &updt_##r, &dest_##r, &val_##r} +#define REG_FNS(r) &crea_##r, &updt_##r, &dest_##r, &val_##r +//////// ARM9 //////// +#define REG_LIST_SIZE_ARM9 5 +static const reg_t regs_list_9[] = +{ + {"REG_IME", REG_IME, BITS_16, REG_FNS(REG_IME)}, + {"REG_IE", REG_IE, BITS_32, REG_FNS(REG_IE)}, + {"REG_IF", REG_IF, BITS_32, REG_FNS(REG_IF)}, + {"REG_IPCFIFOCNT", 0x04000184, BITS_16, REG_FNS(REG_IPCFIFOCNT)}, + {"POWER_CR", POWER_CR, BITS_16, REG_FNS(POWER_CR)} +}; + +//////// ARM7 //////// +#define REG_LIST_SIZE_ARM7 6 +static const reg_t regs_list_7[] = +{ + {"REG_IME", REG_IME, BITS_16, REG_FNS(REG_IME)}, + {"REG_IE", REG_IE, BITS_32, REG_FNS(REG_IE)}, + {"REG_IF", REG_IF, BITS_32, REG_FNS(REG_IF)}, + {"REG_IPCFIFOCNT", 0x04000184, BITS_16, REG_FNS(REG_IPCFIFOCNT)}, + {"POWER_CR", POWER_CR, BITS_16, REG_FNS(POWER_CR)}, + {"REG_SPICNT", REG_SPICNT, BITS_16, REG_FNS(REG_SPICNT)} +}; + +#define GET_REG_LIST_SIZE(i) ((i==0)?REG_LIST_SIZE_ARM9:REG_LIST_SIZE_ARM7) +#define GET_REG_LIST(i) ((i==0)?regs_list_9:regs_list_7) + +static void _clearContainer(GtkWidget *widget, gpointer data) +{ + if(widget == mRegInfos[0] || widget == mRegInfos[1]) return; + if(widget == mIoRegCombo[0] || widget == mIoRegCombo[1]) return; + + gtk_container_remove(GTK_CONTAINER((GtkWidget*)data), widget); +// gtk_widget_destroy(widget); +// gtk_object_destroy(GTK_OBJECT(widget)); +} + +static void selected_reg(GtkWidget* widget, gpointer data) +{ + int c = (int)data; + + guint active = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + + if(current_reg[c]) current_reg[c]->destroy(c); + gtk_container_foreach(GTK_CONTAINER(mVbox0[c]), _clearContainer, (gpointer)mVbox0[c]); + + current_reg[c] = (reg_t*)&(GET_REG_LIST(c)[active]); + +// gtk_box_pack_start(GTK_BOX(mVbox0[c]), mIoRegCombo[c], FALSE, FALSE, 0); + + char regInfosBuffer[64]; + + if(current_reg[c]->size == BITS_8) + { + sprintf(regInfosBuffer, "0x%02X", current_reg[c]->value(c)); + } + else if(current_reg[c]->size == BITS_16) + { + sprintf(regInfosBuffer, "0x%04X", current_reg[c]->value(c)); + } + else + { + sprintf(regInfosBuffer, "0x%08X", current_reg[c]->value(c)); + } +// gtk_box_pack_start(GTK_BOX(mVbox0[c]), mRegInfos[c], FALSE, FALSE, 0); + gtk_label_set_label(GTK_LABEL(mRegInfos[c]), regInfosBuffer); + + current_reg[c]->create(c); + current_reg[c]->update(c); +} + +/////////////////////////////// TOOL /////////////////////////////// + +static int DTOOL_ID; + +static void close() +{ + DTOOL_LOG("Close\n"); + + dTool_CloseCallback(DTOOL_ID); +} + +static void _closeOne(GtkWidget *widget, gpointer data) +{ + int c = (int)data; + CPUS[c] = FALSE; + if(c == 0 && !CPUS[1]) close(); + if(c == 1 && !CPUS[0]) close(); + + gtk_widget_destroy(mRegInfos[c]); + gtk_widget_destroy(mIoRegCombo[c]); + gtk_widget_destroy(mVbox0[c]); +// gtk_widget_destroy(mWin[c]); +} + +static void update() +{ + int c; + + for(c = 0; c < 2; c++) + { + if(!CPUS[c]) continue; + current_reg[c]->update(c); + } +} + +static void open(int ID) +{ + int c, i; + + DTOOL_ID = ID; + + for(c = 0; c < 2; c++) + { + CPUS[c] = TRUE; + + mWin[c]= gtk_window_new(GTK_WINDOW_TOPLEVEL); + if(c == 0) gtk_window_set_title(GTK_WINDOW(mWin[c]), TOOL_NAME " : ARM9"); + else gtk_window_set_title(GTK_WINDOW(mWin[c]), TOOL_NAME " : ARM7"); + g_signal_connect(G_OBJECT(mWin[c]), "destroy", G_CALLBACK(&_closeOne), (gpointer)c); + + mVbox0[c] = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(mWin[c]), mVbox0[c]); + + mIoRegCombo[c] = gtk_combo_box_new_text(); + mRegInfos[c] = gtk_label_new(""); + + for(i = 0; i < GET_REG_LIST_SIZE(c); i++) + { + char reg_name_buffer[64]; + sprintf(reg_name_buffer, "0x%08X : %s (%s)", GET_REG_LIST(c)[i].adress, GET_REG_LIST(c)[i].name, bits_strings[GET_REG_LIST(c)[i].size]); + gtk_combo_box_append_text(GTK_COMBO_BOX(mIoRegCombo[c]), reg_name_buffer); + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(mIoRegCombo[c]), 0); + g_signal_connect(G_OBJECT(mIoRegCombo[c]), "changed", G_CALLBACK(selected_reg), (gpointer)c); + + gtk_box_pack_start(GTK_BOX(mVbox0[c]), mIoRegCombo[c], FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(mVbox0[c]), mRegInfos[c], FALSE, FALSE, 0); + selected_reg(mIoRegCombo[c], (gpointer)c); + + gtk_widget_show_all(mWin[c]); + } +} + +/////////////////////////////// TOOL DEFINITION /////////////////////////////// + +dTool_t dTool_ioregsView = +{ + TOOL_NAME, + &open, + &update, + &close +}; + + + +