Files
2015-09-03 01:20:11 -07:00

1243 lines
41 KiB
C

/*
PokeMini - Pokémon-Mini Emulator
Copyright (C) 2009-2015 JustBurn
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <math.h>
#include <unistd.h>
#include "SDL.h"
#include "PokeMini.h"
#include "PokeMini_Debug.h"
#include "Hardware_Debug.h"
#include "CPUWindow.h"
#include "MemWindow.h"
#include "SymbWindow.h"
#include "PokeMiniIcon_96x128.h"
#include "InstructionProc.h"
#include "InstructionInfo.h"
#include <gtk/gtk.h>
#include "GtkXDialogs.h"
#include "SGtkXDrawingView.h"
static int SymbWindow_InConfigs = 0;
GtkWindow *SymbWindow;
static int SymbWindow_minimized;
static GtkItemFactory *ItemFactory;
static GtkAccelGroup *AccelGroup;
static GtkBox *VBox1;
static GtkMenuBar *MenuBar;
static GtkLabel *LabelRunFull;
static GtkNotebook *ViewNB;
static SGtkXDrawingView CodeView;
static SGtkXDrawingView DataView;
static GtkLabel *PMSymbFile;
static int SymbsModified = 0;
static SymbItem *FirstCode = NULL;
static SymbItem *FirstData = NULL;
static char pmsymbfile[PMTMPV];
static GtkXCustomDialog SymbView_NewValue_CD[] = {
{GTKXCD_LABEL, "Set new value for $XXXX:"},
{GTKXCD_ENTRY, ""},
{GTKXCD_LABEL, "Prefix \"$\" for hexadecimal numbers"},
{GTKXCD_CHECK, "Watchpoint Read access", 1},
{GTKXCD_CHECK, "Watchpoint Write access", 1},
{GTKXCD_LABEL, "Warning: Watchpoints are only triggered at\nthe end of the instruction causing it."},
{GTKXCD_EOL, ""}
};
static GtkXCustomDialog SymbView_AddSetCode_CD[] = {
{GTKXCD_LABEL, "Symbol name:"},
{GTKXCD_ENTRY, ""},
{GTKXCD_LABEL, "Address:"},
{GTKXCD_NUMIN, "", 0, 6, 1, 0, 2097151},
{GTKXCD_LABEL, "NOTE: If symbol already exists\nit will be overwritten."},
{GTKXCD_EOL, ""}
};
static GtkXCustomDialog SymbView_AddSetData_CD[] = {
{GTKXCD_LABEL, "Symbol name:"},
{GTKXCD_ENTRY, ""},
{GTKXCD_LABEL, "Address:"},
{GTKXCD_NUMIN, "", 0, 6, 1, 0, 2097151},
{GTKXCD_RADIO, "8-Bits", 1},
{GTKXCD_RADIO, "16-Bits", 0},
{GTKXCD_RADIO, "24-Bits", 0},
{GTKXCD_RADIO, "32-Bits", 0},
{GTKXCD_HSEP, ""},
{GTKXCD_RADIO2, "Hide number", 0},
{GTKXCD_RADIO2, "Hexadecimal", 1},
{GTKXCD_RADIO2, "Signed number", 0},
{GTKXCD_RADIO2, "Unsigned number", 0},
{GTKXCD_LABEL, "NOTE: If symbol already exists\nit will be overwritten."},
{GTKXCD_EOL, ""}
};
static GtkXCustomDialog SymbView_ManageCode_CD[] = {
{GTKXCD_RADIO2, "Modify symbol", 1},
{GTKXCD_LABEL, "Symbol name:"},
{GTKXCD_ENTRY, ""},
{GTKXCD_LABEL, "Address:"},
{GTKXCD_NUMIN, "", 0, 6, 1, 0, 2097151},
{GTKXCD_LABEL, "NOTE: If symbol already exists\nit will be overwritten."},
{GTKXCD_HSEP, ""},
{GTKXCD_HSEP, ""},
{GTKXCD_RADIO2, "Delete symbol", 0},
{GTKXCD_EOL, ""}
};
static GtkXCustomDialog SymbView_ManageData_CD[] = {
{GTKXCD_RADIO2, "Modify symbol", 1},
{GTKXCD_LABEL, "Symbol name:"},
{GTKXCD_ENTRY, ""},
{GTKXCD_LABEL, "Address:"},
{GTKXCD_NUMIN, "", 0, 6, 1, 0, 2097151},
{GTKXCD_RADIO, "8-Bits", 1},
{GTKXCD_RADIO, "16-Bits", 0},
{GTKXCD_RADIO, "24-Bits", 0},
{GTKXCD_RADIO, "32-Bits", 0},
{GTKXCD_HSEP, ""},
{GTKXCD_RADIO3, "Hide number", 0},
{GTKXCD_RADIO3, "Hexadecimal", 1},
{GTKXCD_RADIO3, "Signed number", 0},
{GTKXCD_RADIO3, "Unsigned number", 0},
{GTKXCD_LABEL, "NOTE: If symbol already exists\nit will be overwritten."},
{GTKXCD_HSEP, ""},
{GTKXCD_HSEP, ""},
{GTKXCD_RADIO2, "Delete symbol", 0},
{GTKXCD_EOL, ""}
};
// -------------------
// Symb items handlers
// -------------------
void SymbItemsClearAll(SymbItem **list)
{
SymbItem *next, *item = *list;
while (item != NULL) {
next = item->next;
free(item);
item = next;
}
*list = NULL;
}
SymbItem *SymbItemsGetIndex(SymbItem **list, int index)
{
SymbItem *item = *list;
if (index < 0) return NULL;
while (item != NULL) {
if (index-- == 0) return item;
item = item->next;
}
return NULL;
}
SymbItem *SymbItemsGet(SymbItem **list, char *symbname)
{
SymbItem *item = *list;
while (item != NULL) {
if (!strcmp(item->name, symbname)) return item;
item = item->next;
}
return NULL;
}
void SymbItemsSet(SymbItem **list, SymbItem *setitem, int updateex)
{
SymbItem *item, *pitem, *newitem;
item = SymbItemsGet(list, setitem->name);
if (item != NULL) {
item->addr = setitem->addr;
if (updateex) {
item->size = setitem->size;
item->ctrl = setitem->ctrl;
}
return;
}
newitem = (SymbItem *)malloc(sizeof(SymbItem));
memcpy(newitem, setitem, sizeof(SymbItem));
if (*list == NULL) {
*list = newitem;
newitem->prev = NULL;
newitem->next = NULL;
return;
}
pitem = NULL;
item = *list;
while (item != NULL) {
if (strcmp(item->name, newitem->name) < 0) {
pitem = item;
item = item->next;
} else break;
}
newitem->prev = pitem;
newitem->next = item;
if (pitem) {
pitem->next = newitem;
} else {
*list = newitem;
}
if (item) item->prev = newitem;
}
void SymbItemsDelete(SymbItem **list, SymbItem *item)
{
if (!item) return;
if (item->prev) {
item->prev->next = item->next;
} else {
*list = item->next;
}
if (item->next) item->next->prev = item->prev;
free(item);
}
int SymbItemsLength(SymbItem **list)
{
int count = 0;
SymbItem *item = *list;
while (item != NULL) {
count++;
item = item->next;
}
return count;
}
int SymbItemsSetFromFile(char *filename)
{
FILE *fi;
char tmp[PMTMPV];
char stype[PMTMPV];
char sval[PMTMPV];
char ssize[PMTMPV];
char ssymb[PMTMPV];
uint32_t value;
int32_t size;
SymbItem item;
fi = fopen(filename, "r");
if (!fi) return 0;
while (fgets(tmp, PMTMPV, fi) != NULL) {
if (sscanf(tmp, "%s %s %s %s", stype, sval, ssize, ssymb) == 4) {
// Some future PMAS version
value = atoi_Ex(sval, 0);
size = atoi_Ex(ssize, -1);
if (!strcasecmp(stype, "LAB")) {
// Code
strcpy(item.name, ssymb);
item.addr = value;
SymbItemsSet(&FirstCode, &item, 0);
} else if (!strcasecmp(stype, "RAM")) {
// Data
strcpy(item.name, ssymb);
item.addr = value;
item.size = 0;
if (size == 2) item.size = 1;
else if (size == 3) item.size = 2;
else if (size == 4) item.size = 3;
item.ctrl = 1;
SymbItemsSet(&FirstData, &item, 0);
}
} else if (sscanf(tmp, "%s %s %s", stype, sval, ssymb) == 3) {
// PMAS == v0.20 Symbols
value = atoi_Ex(sval, 0);
if (!strcasecmp(stype, "LAB")) {
// Code
strcpy(item.name, ssymb);
item.addr = value;
SymbItemsSet(&FirstCode, &item, 0);
} else if (!strcasecmp(stype, "RAM")) {
// Data
strcpy(item.name, ssymb);
item.addr = value;
item.size = 0;
item.ctrl = 1;
SymbItemsSet(&FirstData, &item, 0);
}
} else if (sscanf(tmp, "%s %s", sval, ssymb) == 2) {
// PMAS <= 0.19 Symbols
// Code and Data
value = atoi_Ex(sval, 0);
strcpy(item.name, ssymb);
item.addr = value;
item.size = 0;
item.ctrl = 1;
SymbItemsSet(&FirstCode, &item, 0);
SymbItemsSet(&FirstData, &item, 0);
}
}
fclose(fi);
return 1;
}
int SymbItemsLoadFromFile(char *filename)
{
char tmp[PMTMPV], *txt;
char par[PMTMPV];
char tok;
SymbItem item;
FILE *fi;
SymbItemsClearAll(&FirstCode);
SymbItemsClearAll(&FirstData);
fi = fopen(filename, "r");
if (!fi) return 0;
while (fgets(tmp, PMTMPV, fi) != NULL) {
RemoveComments(tmp);
txt = TrimStr(tmp);
txt = UpToToken(par, txt, " \t\n", &tok);
if (tok == '\n') continue;
if (!strcasecmp(par, "CODE1")) {
txt = UpToToken(par, txt, " \t\n", &tok);
if (tok == '\n') continue;
item.addr = atoi_Ex(par, 0);
txt = UpToToken(item.name, txt, " \t\n", &tok);
SymbItemsSet(&FirstCode, &item, 1);
} else if (!strcasecmp(par, "DATA1")) {
txt = UpToToken(par, txt, " \t\n", &tok);
if (tok == '\n') continue;
item.addr = atoi_Ex(par, 0);
txt = UpToToken(par, txt, " \t\n", &tok);
if (tok == '\n') continue;
item.size = atoi_Ex(par, 0);
if ((item.size < 0) || (item.size > 3)) item.size = 0;
txt = UpToToken(par, txt, " \t\n", &tok);
if (tok == '\n') continue;
item.ctrl = atoi_Ex(par, 0);
txt = UpToToken(item.name, txt, " \t\n", &tok);
SymbItemsSet(&FirstData, &item, 1);
}
}
return 1;
}
int SymbItemsSaveToFile(char *filename)
{
SymbItem *item;
FILE *fo;
fo = fopen(filename, "w");
if (!fo) return 0;
// Write header
fprintf(fo, "# Symbols list generated by PokeMini %s\n", PokeMini_Version);
fprintf(fo, "# Min file: %s\n", GetFilename(CommandLine.min_file));
// Write code
item = FirstCode;
while (item != NULL) {
fprintf(fo, "CODE1 $%06X %s\n", item->addr, item->name);
item = item->next;
}
// Write data
item = FirstData;
while (item != NULL) {
fprintf(fo, "DATA1 $%06X %i %i %s\n", item->addr, item->size, item->ctrl, item->name);
item = item->next;
}
fclose(fo);
return 1;
}
void SymbWindow_Reload(void)
{
char tmp[PMTMPV];
if (!strlen(pmsymbfile)) SymbsModified = 0;
sprintf(tmp, "%c%s", (SymbsModified) ? '*' : ' ', pmsymbfile);
gtk_label_set_text(PMSymbFile, tmp);
sgtkx_drawing_view_sbminmax(&CodeView, 0, SymbItemsLength(&FirstCode));
sgtkx_drawing_view_sbminmax(&DataView, 0, SymbItemsLength(&FirstData));
SymbWindow_Refresh(1);
}
static void SymbWindow_AddSetCode()
{
SymbItem item;
int result;
SymbView_AddSetCode_CD[3].number = PhysicalPC();
sprintf(SymbView_AddSetCode_CD[1].text, "L%06X", SymbView_AddSetCode_CD[3].number);
result = CustomDialog(SymbWindow, "Add/set code symbol", SymbView_AddSetCode_CD);
if (result == 1) {
if (strlen(SymbView_AddSetCode_CD[1].text)) {
strcpy(item.name, SymbView_AddSetCode_CD[1].text);
item.addr = SymbView_AddSetCode_CD[3].number;
SymbItemsSet(&FirstCode, &item, 1);
SymbsModified = 1;
SymbWindow_Reload();
} else {
MessageDialog(SymbWindow, "Missing symbol name", "Add/set code symbol", GTK_MESSAGE_ERROR, NULL);
}
} else if (result == -1) {
MessageDialog(SymbWindow, "Invalid number", "Add/set code symbol", GTK_MESSAGE_ERROR, NULL);
}
}
static void SymbWindow_AddSetData()
{
SymbItem item;
int result;
SymbView_AddSetData_CD[3].number = 0x1000;
SymbView_AddSetData_CD[1].text[0] = 0;
result = CustomDialog(SymbWindow, "Add/set data symbol", SymbView_AddSetData_CD);
if (result == 1) {
if (strlen(SymbView_AddSetData_CD[1].text)) {
strcpy(item.name, SymbView_AddSetData_CD[1].text);
item.addr = SymbView_AddSetData_CD[3].number;
item.size = 0;
if (SymbView_AddSetData_CD[5].number) item.size = 1;
if (SymbView_AddSetData_CD[6].number) item.size = 2;
if (SymbView_AddSetData_CD[7].number) item.size = 3;
item.ctrl = 1;
if (SymbView_AddSetData_CD[9].number) item.ctrl = 0;
if (SymbView_AddSetData_CD[11].number) item.ctrl = 2;
if (SymbView_AddSetData_CD[12].number) item.ctrl = 3;
SymbItemsSet(&FirstData, &item, 1);
SymbsModified = 1;
SymbWindow_Reload();
} else {
MessageDialog(SymbWindow, "Missing symbol name", "Add/set data symbol", GTK_MESSAGE_ERROR, NULL);
}
} else if (result == -1) {
MessageDialog(SymbWindow, "Invalid number", "Add/set data symbol", GTK_MESSAGE_ERROR, NULL);
}
}
// -------
// Viewers
// -------
// Code view exposure event
static int CodeView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
int y, pp;
int yc, ys = -1;
SymbItem *item;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
ys = (widg->mousey - 12) / 12;
}
// Draw content
pp = widg->sboffset;
item = SymbItemsGetIndex(&FirstCode, pp);
for (y=1; y<yc+1; y++) {
if (emumode != EMUMODE_RUNFULL) {
if ((y-1) == ys) {
if (pp & 1) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (pp & 1) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (pp & 1) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
if (item == NULL) {
pp++;
continue;
}
// Draw trap
if (PMD_TrapPoints[item->addr & PM_ROM_Mask] & TRAPPOINT_BREAK) {
sgtkx_drawing_view_drawfrect(widg, 2, y * 12, 72, 12, 0xFF2000);
}
// Draw symbol
if (item->addr >= 0x01000000) sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x4C3000, "$%08X", item->addr);
else sgtkx_drawing_view_drawtext(widg, 20, y * 12, 0x4C3000, "$%06X", item->addr);
sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "-----------");
sgtkx_drawing_view_drawtext(widg, 180, y * 12, 0x402090, "%s", item->name);
// Next item
item = item->next;
pp++;
}
// Draw top bar
if (emumode != EMUMODE_RUNFULL) {
sgtkx_drawing_view_drawfrect(widg, 0, 0, widg->width, 12, 0xD8D8CC);
} else {
sgtkx_drawing_view_drawfrect(widg, 0, 0, widg->width, 12, 0x68685C);
}
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "Left click => Go to address -:- Right click => Manage symbol(s) -:- Middle click => Toggle breakpoint");
return 1;
}
// Code view button press
static int CodeView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int result, pp, ys = -1;
SymbItem *item;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
ys = (widg->mousey - 12) / 12;
pp = widg->sboffset + ys;
item = SymbItemsGetIndex(&FirstCode, pp);
if ((item == NULL) || (item->addr >= PM_ROM_Size)) {
if (button == SGTKXDV_BRIGHT) {
set_emumode(EMUMODE_STOP, 1);
SymbWindow_AddSetCode();
set_emumode(EMUMODE_RESTORE, 1);
}
return 1;
}
set_emumode(EMUMODE_STOP, 1);
if (button == SGTKXDV_BLEFT) {
// Go to address
ProgramView_GotoAddr(item->addr, 1);
refresh_debug(1);
} else if (button == SGTKXDV_BMIDDLE) {
// Toggle breakpoint
PMD_TrapPoints[item->addr & PM_ROM_Mask] ^= TRAPPOINT_BREAK;
refresh_debug(1);
} else if (button == SGTKXDV_BRIGHT) {
// Manage symbol
SymbView_ManageCode_CD[0].number = 1;
SymbView_ManageCode_CD[8].number = 0;
SymbView_ManageCode_CD[4].number = item->addr;
strcpy(SymbView_ManageCode_CD[2].text, item->name);
result = CustomDialog(SymbWindow, "Manage code symbol", SymbView_ManageCode_CD);
if (result == 1) {
if (strlen(SymbView_ManageCode_CD[2].text)) {
if (SymbView_ManageCode_CD[0].number) {
// Modify symbol
if (strcmp(item->name, SymbView_ManageCode_CD[2].text) && SymbItemsGet(&FirstCode, SymbView_ManageCode_CD[2].text)) {
MessageDialog(SymbWindow, "Symbol already exists", "Manage code symbol", GTK_MESSAGE_ERROR, NULL);
} else {
strcpy(item->name, SymbView_ManageCode_CD[2].text);
item->addr = SymbView_ManageCode_CD[4].number;
SymbsModified = 1;
SymbWindow_Reload();
}
} else {
// Delele symbol
SymbItemsDelete(&FirstCode, item);
SymbsModified = 1;
SymbWindow_Reload();
}
} else {
MessageDialog(SymbWindow, "Missing symbol name", "Manage code symbol", GTK_MESSAGE_ERROR, NULL);
}
} else if (result == -1) {
MessageDialog(SymbWindow, "Invalid number", "Manage code symbol", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// Data view exposure event
static int DataView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color, val;
int y, pp, watch;
int yc, ys = -1;
SymbItem *item;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
ys = (widg->mousey - 12) / 12;
}
// Draw content
pp = widg->sboffset;
item = SymbItemsGetIndex(&FirstData, pp);
for (y=1; y<yc+1; y++) {
if (emumode != EMUMODE_RUNFULL) {
if ((y-1) == ys) {
if (pp & 1) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (pp & 1) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (pp & 1) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
if (item == NULL) {
pp++;
continue;
}
// Draw trap
watch = PMD_TrapPoints[item->addr & PM_ROM_Mask] & TRAPPOINT_WATCH;
if (watch) {
sgtkx_drawing_view_drawfrect(widg, 82, y * 12, 72, 12, AnyView_TrapColor[watch]);
}
// Draw symbol
if (item->addr >= 0x01000000) sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x4C3000, "$%08X", item->addr);
else sgtkx_drawing_view_drawtext(widg, 20, y * 12, 0x4C3000, "$%06X", item->addr);
if (item->size == 0) {
val = MinxCPU_OnRead(0, item->addr);
switch (item->ctrl & 3) {
case 1: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "$%02X", val); break;
case 2: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%i", (int)((int8_t)val)); break;
case 3: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%u", (unsigned int)val); break;
}
} else if (item->size == 1) {
val = MinxCPU_OnRead(0, item->addr) +
(MinxCPU_OnRead(0, item->addr+1) << 8);
switch (item->ctrl & 3) {
case 1: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "$%04X", val); break;
case 2: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%i", (int)((int16_t)val)); break;
case 3: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%u", (unsigned int)val); break;
}
} else if (item->size == 2) {
val = MinxCPU_OnRead(0, item->addr) +
(MinxCPU_OnRead(0, item->addr+1) << 8) +
(MinxCPU_OnRead(0, item->addr+2) << 16);
switch (item->ctrl & 3) {
case 1: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "$%06X", val); break;
case 2: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%i", (int)((int32_t)(val << 8)) >> 8); break;
case 3: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%u", (unsigned int)val); break;
}
} else if (item->size == 3) {
val = MinxCPU_OnRead(0, item->addr) +
(MinxCPU_OnRead(0, item->addr+1) << 8) +
(MinxCPU_OnRead(0, item->addr+2) << 16) +
(MinxCPU_OnRead(0, item->addr+3) << 24);
switch (item->ctrl & 3) {
case 1: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "$%08X", val); break;
case 2: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%i", (int)val); break;
case 3: sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605080, "%u", (unsigned int)val); break;
}
}
sgtkx_drawing_view_drawtext(widg, 180, y * 12, 0x402090, "%s", item->name);
// Next item
item = item->next;
pp++;
}
// Draw top bar
if (emumode != EMUMODE_RUNFULL) {
sgtkx_drawing_view_drawfrect(widg, 0, 0, widg->width, 12, 0xD8D8CC);
} else {
sgtkx_drawing_view_drawfrect(widg, 0, 0, widg->width, 12, 0x68685C);
}
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "Left click => Edit value -:- Right click => Manage symbol(s) -:- Middle click => Toggle watchpoints");
return 1;
}
// Data view button press
static int DataView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int result, pp, ys = -1;
SymbItem *item;
uint32_t val;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
ys = (widg->mousey - 12) / 12;
pp = widg->sboffset + ys;
item = SymbItemsGetIndex(&FirstData, pp);
if ((item == NULL) || (item->addr >= PM_ROM_Size)) {
if (button == SGTKXDV_BRIGHT) {
set_emumode(EMUMODE_STOP, 1);
SymbWindow_AddSetData();
set_emumode(EMUMODE_RESTORE, 1);
}
return 1;
}
set_emumode(EMUMODE_STOP, 1);
if (button == SGTKXDV_BLEFT) {
// Edit value
val = (uint32_t)MinxCPU_OnRead(0, item->addr);
if (item->size >= 1) val += (uint32_t)MinxCPU_OnRead(0, item->addr+1) << 8;
if (item->size >= 2) val += (uint32_t)MinxCPU_OnRead(0, item->addr+2) << 16;
if (item->size >= 3) val += (uint32_t)MinxCPU_OnRead(0, item->addr+3) << 24;
if ((item->ctrl & 3) == 1) {
sprintf(SymbView_NewValue_CD[1].text, "$%02X", val);
if (item->size == 1) sprintf(SymbView_NewValue_CD[1].text, "$%04X", val);
if (item->size == 2) sprintf(SymbView_NewValue_CD[1].text, "$%06X", val);
if (item->size == 3) sprintf(SymbView_NewValue_CD[1].text, "$%08X", val);
} else {
sprintf(SymbView_NewValue_CD[1].text, "%i", val);
}
SymbView_NewValue_CD[3].number = PMD_TrapPoints[item->addr] & TRAPPOINT_WATCHREAD;
SymbView_NewValue_CD[4].number = PMD_TrapPoints[item->addr] & TRAPPOINT_WATCHWRITE;
sprintf(SymbView_NewValue_CD[0].text, "Set new value for $%04X (%s):", item->addr, item->name);
result = CustomDialog(SymbWindow, "Change memory", SymbView_NewValue_CD);
if (result == 1) {
val = atoi_Ex(SymbView_NewValue_CD[1].text, 0);
WriteToPMMem(item->addr, val);
PMD_TrapPoints[item->addr] &= ~TRAPPOINT_WATCH;
if (SymbView_NewValue_CD[3].number) PMD_TrapPoints[item->addr] |= TRAPPOINT_WATCHREAD;
if (SymbView_NewValue_CD[4].number) PMD_TrapPoints[item->addr] |= TRAPPOINT_WATCHWRITE;
if (item->size >= 1) {
WriteToPMMem(item->addr+1, val >> 8);
PMD_TrapPoints[item->addr+1] &= ~TRAPPOINT_WATCH;
if (SymbView_NewValue_CD[3].number) PMD_TrapPoints[item->addr+1] |= TRAPPOINT_WATCHREAD;
if (SymbView_NewValue_CD[4].number) PMD_TrapPoints[item->addr+1] |= TRAPPOINT_WATCHWRITE;
}
if (item->size >= 2) {
WriteToPMMem(item->addr+2, val >> 16);
PMD_TrapPoints[item->addr+2] &= ~TRAPPOINT_WATCH;
if (SymbView_NewValue_CD[3].number) PMD_TrapPoints[item->addr+2] |= TRAPPOINT_WATCHREAD;
if (SymbView_NewValue_CD[4].number) PMD_TrapPoints[item->addr+2] |= TRAPPOINT_WATCHWRITE;
}
if (item->size >= 3) {
WriteToPMMem(item->addr+3, val >> 24);
PMD_TrapPoints[item->addr+3] &= ~TRAPPOINT_WATCH;
if (SymbView_NewValue_CD[3].number) PMD_TrapPoints[item->addr+3] |= TRAPPOINT_WATCHREAD;
if (SymbView_NewValue_CD[4].number) PMD_TrapPoints[item->addr+3] |= TRAPPOINT_WATCHWRITE;
}
refresh_debug(1);
} else if (result == -1) {
MessageDialog(SymbWindow, "Invalid number", "Change memory", GTK_MESSAGE_ERROR, NULL);
}
} else if (button == SGTKXDV_BMIDDLE) {
val = PMD_TrapPoints[item->addr];
switch (val & TRAPPOINT_WATCH) {
case 0: val = TRAPPOINT_WATCHREAD | TRAPPOINT_WATCHWRITE; break;
case TRAPPOINT_WATCHREAD | TRAPPOINT_WATCHWRITE: val = TRAPPOINT_WATCHREAD; break;
case TRAPPOINT_WATCHREAD: val = TRAPPOINT_WATCHWRITE; break;
case TRAPPOINT_WATCHWRITE: val = 0; break;
}
PMD_TrapPoints[item->addr] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[item->addr] |= val;
if (item->size >= 1) {
PMD_TrapPoints[item->addr+1] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[item->addr+1] |= val;
}
if (item->size >= 2) {
PMD_TrapPoints[item->addr+2] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[item->addr+2] |= val;
}
if (item->size >= 3) {
PMD_TrapPoints[item->addr+3] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[item->addr+3] |= val;
}
refresh_debug(1);
} else if (button == SGTKXDV_BRIGHT) {
// Manage symbol
SymbView_ManageData_CD[0].number = 1;
SymbView_ManageData_CD[17].number = 0;
SymbView_ManageData_CD[4].number = item->addr;
SymbView_ManageData_CD[5].number = (item->size == 0) ? 1 : 0;
SymbView_ManageData_CD[6].number = (item->size == 1) ? 1 : 0;
SymbView_ManageData_CD[7].number = (item->size == 2) ? 1 : 0;
SymbView_ManageData_CD[8].number = (item->size == 3) ? 1 : 0;
SymbView_ManageData_CD[10].number = (item->ctrl == 0) ? 1 : 0;
SymbView_ManageData_CD[11].number = (item->ctrl == 1) ? 1 : 0;
SymbView_ManageData_CD[12].number = (item->ctrl == 2) ? 1 : 0;
SymbView_ManageData_CD[13].number = (item->ctrl == 3) ? 1 : 0;
strcpy(SymbView_ManageData_CD[2].text, item->name);
result = CustomDialog(SymbWindow, "Manage data symbol", SymbView_ManageData_CD);
if (result == 1) {
if (strlen(SymbView_ManageData_CD[2].text)) {
if (SymbView_ManageData_CD[0].number) {
// Modify symbol
if (strcmp(item->name, SymbView_ManageData_CD[2].text) && SymbItemsGet(&FirstData, SymbView_ManageData_CD[2].text)) {
MessageDialog(SymbWindow, "Symbol already exists", "Manage data symbol", GTK_MESSAGE_ERROR, NULL);
} else {
strcpy(item->name, SymbView_ManageData_CD[2].text);
item->addr = SymbView_ManageData_CD[4].number;
item->size = 0;
if (SymbView_ManageData_CD[6].number) item->size = 1;
if (SymbView_ManageData_CD[7].number) item->size = 2;
if (SymbView_ManageData_CD[8].number) item->size = 3;
item->ctrl = 1;
if (SymbView_ManageData_CD[10].number) item->ctrl = 0;
if (SymbView_ManageData_CD[12].number) item->ctrl = 2;
if (SymbView_ManageData_CD[13].number) item->ctrl = 3;
SymbsModified = 1;
SymbWindow_Reload();
}
} else {
// Delele symbol
SymbItemsDelete(&FirstData, item);
SymbsModified = 1;
SymbWindow_Reload();
}
} else {
MessageDialog(SymbWindow, "Missing symbol name", "Manage data symbol", GTK_MESSAGE_ERROR, NULL);
}
} else if (result == -1) {
MessageDialog(SymbWindow, "Invalid number", "Manage data symbol", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// --------------
// Menu callbacks
// --------------
static void SymbW_ImportSym(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
strcpy(tmp, CommandLine.min_file);
RemoveExtension(tmp);
strcat(tmp, ".sym");
if (OpenFileDialogEx(SymbWindow, "Import SYM", tmp, tmp, "PMAS symbols (*.sym)\0*.sym\0All (*.*)\0*.*\0", 0)) {
if (!SymbItemsSetFromFile(tmp)) {
MessageDialog(SymbWindow, "Error loading PMAS symbols list from ROM", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
} else SymbsModified = 1;
SymbWindow_Reload();
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void SymbW_LoadPMSymbols(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
strcpy(tmp, CommandLine.min_file);
RemoveExtension(tmp);
strcat(tmp, ".pmsymbols");
if (SymbsModified && !YesNoDialog(MainWindow, "Changes not saved\nLoad anyway?", "Load pmsymbols", GTK_MESSAGE_QUESTION, NULL)) {
set_emumode(EMUMODE_RESTORE, 1);
return;
}
if (OpenFileDialogEx(SymbWindow, "Load PokeMini Symbols", tmp, tmp, "PokeMini Symbols (*.pmsymbols)\0*.pmsymbols\0All (*.*)\0*.*\0", 0)) {
if (!SymbItemsLoadFromFile(tmp)) {
MessageDialog(SymbWindow, "Error loading PokeMini symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
} else {
strcpy(pmsymbfile, tmp);
SymbsModified = 0;
}
SymbWindow_Reload();
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void SymbW_SavePMSymbols(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 1);
if (strlen(pmsymbfile)) {
if (!SymbItemsSaveToFile(pmsymbfile)) {
MessageDialog(SymbWindow, "Error saving PokeMini symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
}
}
SymbsModified = 0;
SymbWindow_Reload();
set_emumode(EMUMODE_RESTORE, 1);
}
static void SymbW_SaveAsPMSymbols(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
strcpy(tmp, CommandLine.min_file);
RemoveExtension(tmp);
strcat(tmp, ".pmsymbols");
if (SaveFileDialogEx(SymbWindow, "Save PokeMini Symbols", tmp, tmp, "PokeMini Symbols (*.pmsymbols)\0*.pmsymbols\0All (*.*)\0*.*\0", 0)) {
if (!SymbItemsSaveToFile(tmp)) {
MessageDialog(SymbWindow, "Error saving PokeMini symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void SymbW_AutoReadSym(GtkWidget *widget, gpointer data)
{
if (SymbWindow_InConfigs) return;
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/File/Auto read .sym");
dclc_autoread_minsym = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void SymbW_AutoRWPMSym(GtkWidget *widget, gpointer data)
{
if (SymbWindow_InConfigs) return;
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/File/Auto rw .pmsymbols");
dclc_autorw_emusym = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void SymbW_AddSetCode(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 1);
SymbWindow_AddSetCode();
set_emumode(EMUMODE_RESTORE, 1);
}
static void SymbW_AddSetData(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 1);
SymbWindow_AddSetData();
set_emumode(EMUMODE_RESTORE, 1);
}
static void SymbW_ClrAllCode(GtkWidget *widget, gpointer data)
{
if (SymbItemsLength(&FirstCode)) {
SymbItemsClearAll(&FirstCode);
SymbsModified = 1;
SymbWindow_Reload();
}
}
static void SymbW_ClrAllData(GtkWidget *widget, gpointer data)
{
if (SymbItemsLength(&FirstData)) {
SymbItemsClearAll(&FirstData);
SymbsModified = 1;
SymbWindow_Reload();
}
}
static void SymbW_ClrAll(GtkWidget *widget, gpointer data)
{
if (SymbItemsLength(&FirstCode) || SymbItemsLength(&FirstData)) {
SymbItemsClearAll(&FirstCode);
SymbItemsClearAll(&FirstData);
SymbsModified = 1;
SymbWindow_Reload();
}
}
static void SymbW_RefreshNow(GtkWidget *widget, gpointer data)
{
refresh_debug(1);
}
static void SymbW_Refresh(GtkWidget *widget, gpointer data)
{
int val, index = (int)data;
static int lastrefrindex = -2;
if (lastrefrindex == index) return;
lastrefrindex = index;
if (SymbWindow_InConfigs) return;
if (index >= 0) {
dclc_symbwin_refresh = index;
} else {
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(SymbWindow, "Custom refresh rate", "Frames skip per refresh:", &val, dclc_symbwin_refresh, 4, 0, 0, 1000)) {
dclc_symbwin_refresh = val;
}
set_emumode(EMUMODE_RESTORE, 1);
}
}
static gint SymbWindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_widget_hide(GTK_WIDGET(SymbWindow));
return TRUE;
}
static gboolean SymbWindow_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
{
if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) SymbWindow_minimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
return TRUE;
}
static GtkItemFactoryEntry SymbWindow_MenuItems[] = {
{ "/_File", NULL, NULL, 0, "<Branch>" },
{ "/File/_Import sym...", "<CTRL>I", SymbW_ImportSym, 0, "<Item>" },
{ "/File/_Load pmsymbols...", "<CTRL>L", SymbW_LoadPMSymbols, 0, "<Item>" },
{ "/File/_Save pmsymbols", "<CTRL>S", SymbW_SavePMSymbols, 0, "<Item>" },
{ "/File/S_ave pmsymbols as...", "<CTRL><ALT>S", SymbW_SaveAsPMSymbols, 0, "<Item>" },
{ "/File/sep1", NULL, NULL, 0, "<Separator>" },
{ "/File/Auto read .sym", NULL, SymbW_AutoReadSym, 0, "<CheckItem>" },
{ "/File/Auto rw .pmsymbols", NULL, SymbW_AutoRWPMSym, 0, "<CheckItem>" },
{ "/_Symbols", NULL, NULL, 0, "<Branch>" },
{ "/Symbols/Add code symbol...", "<CTRL>C", SymbW_AddSetCode, 0, "<Item>" },
{ "/Symbols/Add data symbol...", "<CTRL>D", SymbW_AddSetData, 0, "<Item>" },
{ "/Symbols/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Symbols/Clear all", NULL, NULL, 0, "<Branch>" },
{ "/Symbols/Clear all/Code symbols", NULL, SymbW_ClrAllCode, 0, "<Item>" },
{ "/Symbols/Clear all/Data symbols", NULL, SymbW_ClrAllData, 0, "<Item>" },
{ "/Symbols/Clear all/Code and data", NULL, SymbW_ClrAll, 0, "<Item>" },
{ "/_Debugger", NULL, NULL, 0, "<Branch>" },
{ "/Debugger/Run full speed", "F5", Menu_Debug_RunFull, 0, "<Item>" },
{ "/Debugger/Run debug frames (Sound)", "<SHIFT>F5", Menu_Debug_RunDFrameSnd, 0, "<Item>" },
{ "/Debugger/Run debug frames", "<CTRL>F5", Menu_Debug_RunDFrame, 0, "<Item>" },
{ "/Debugger/Run debug steps", "<CTRL>F3", Menu_Debug_RunDStep, 0, "<Item>" },
{ "/Debugger/Single frame", "F4", Menu_Debug_SingleFrame, 0, "<Item>" },
{ "/Debugger/Single step", "F3", Menu_Debug_SingleStep, 0, "<Item>" },
{ "/Debugger/Step skip", "<SHIFT>F3", Menu_Debug_StepSkip, 0, "<Item>" },
{ "/Debugger/Stop", "F2", Menu_Debug_Stop, 0, "<Item>" },
{ "/_Refresh", NULL, NULL, 0, "<Branch>" },
{ "/Refresh/Now!", NULL, SymbW_RefreshNow, 0, "<Item>" },
{ "/Refresh/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Refresh/100% 72fps", NULL, SymbW_Refresh, 0, "<RadioItem>" },
{ "/Refresh/ 50% 36fps", NULL, SymbW_Refresh, 1, "/Refresh/100% 72fps" },
{ "/Refresh/ 33% 24fps", NULL, SymbW_Refresh, 2, "/Refresh/100% 72fps" },
{ "/Refresh/ 25% 18fps", NULL, SymbW_Refresh, 3, "/Refresh/100% 72fps" },
{ "/Refresh/ 17% 12fps", NULL, SymbW_Refresh, 5, "/Refresh/100% 72fps" },
{ "/Refresh/ 12% 9fps", NULL, SymbW_Refresh, 7, "/Refresh/100% 72fps" },
{ "/Refresh/ 8% 6fps", NULL, SymbW_Refresh, 11, "/Refresh/100% 72fps" },
{ "/Refresh/ 3% 2fps", NULL, SymbW_Refresh, 35, "/Refresh/100% 72fps" },
{ "/Refresh/ 1% 1fps", NULL, SymbW_Refresh, 71, "/Refresh/100% 72fps" },
{ "/Refresh/Custom...", NULL, SymbW_Refresh, -1, "/Refresh/100% 72fps" },
};
static gint SymbWindow_MenuItemsNum = sizeof(SymbWindow_MenuItems) / sizeof(*SymbWindow_MenuItems);
// -----------
// Symb Window
// -----------
int SymbWindow_Create(void)
{
// Window
SymbWindow = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
gtk_window_set_title(GTK_WINDOW(SymbWindow), "Symbols List View");
gtk_widget_set_size_request(GTK_WIDGET(SymbWindow), 200, 100);
gtk_window_set_default_size(SymbWindow, 420, 200);
g_signal_connect(SymbWindow, "delete_event", G_CALLBACK(SymbWindow_delete_event), NULL);
g_signal_connect(SymbWindow, "window-state-event", G_CALLBACK(SymbWindow_state_event), NULL);
VBox1 = GTK_BOX(gtk_vbox_new(FALSE, 0));
gtk_container_add(GTK_CONTAINER(SymbWindow), GTK_WIDGET(VBox1));
gtk_widget_show(GTK_WIDGET(VBox1));
// Menu bar
AccelGroup = gtk_accel_group_new();
ItemFactory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", AccelGroup);
gtk_item_factory_create_items(ItemFactory, SymbWindow_MenuItemsNum, SymbWindow_MenuItems, NULL);
gtk_window_add_accel_group(SymbWindow, AccelGroup);
MenuBar = GTK_MENU_BAR(gtk_item_factory_get_widget(ItemFactory, "<main>"));
gtk_box_pack_start(VBox1, GTK_WIDGET(MenuBar), FALSE, TRUE, 0);
gtk_widget_show(GTK_WIDGET(MenuBar));
// Label that warn when running full speed
LabelRunFull = GTK_LABEL(gtk_label_new("To view content you must stop emulation or run in debug frames/steps."));
gtk_box_pack_start(VBox1, GTK_WIDGET(LabelRunFull), FALSE, TRUE, 0);
// Code View
CodeView.on_exposure = SGtkXDVCB(CodeView_exposure);
CodeView.on_scroll = SGtkXDVCB(AnyView_scroll);
CodeView.on_resize = SGtkXDVCB(AnyView_resize);
CodeView.on_motion = SGtkXDVCB(AnyView_motion);
CodeView.on_buttonpress = SGtkXDVCB(CodeView_buttonpress);
CodeView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&CodeView, 1);
sgtkx_drawing_view_sbminmax(&CodeView, 0, 255);
gtk_widget_set_size_request(GTK_WIDGET(CodeView.box), 64, 64);
gtk_widget_show(GTK_WIDGET(CodeView.box));
// Data View
DataView.on_exposure = SGtkXDVCB(DataView_exposure);
DataView.on_scroll = SGtkXDVCB(AnyView_scroll);
DataView.on_resize = SGtkXDVCB(AnyView_resize);
DataView.on_motion = SGtkXDVCB(AnyView_motion);
DataView.on_buttonpress = SGtkXDVCB(DataView_buttonpress);
DataView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&DataView, 1);
sgtkx_drawing_view_sbminmax(&DataView, 0, 255);
gtk_widget_set_size_request(GTK_WIDGET(DataView.box), 64, 64);
gtk_widget_show(GTK_WIDGET(DataView.box));
// View Notebook
ViewNB = GTK_NOTEBOOK(gtk_notebook_new());
gtk_box_pack_start(VBox1, GTK_WIDGET(ViewNB), TRUE, TRUE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(ViewNB), GTK_WIDGET(CodeView.box), gtk_label_new("Code / Labels"));
gtk_notebook_append_page(GTK_NOTEBOOK(ViewNB), GTK_WIDGET(DataView.box), gtk_label_new("Data / RAM"));
gtk_widget_show(GTK_WIDGET(ViewNB));
// Write file
pmsymbfile[0] = 0;
PMSymbFile = GTK_LABEL(gtk_label_new(pmsymbfile));
gtk_misc_set_alignment(GTK_MISC(PMSymbFile), 0.5, 0.0);
gtk_label_set_justify(PMSymbFile, GTK_JUSTIFY_CENTER);
gtk_box_pack_start(VBox1, GTK_WIDGET(PMSymbFile), FALSE, TRUE, 0);
gtk_widget_show(GTK_WIDGET(PMSymbFile));
return 1;
}
void SymbWindow_Destroy(void)
{
int x, y, width, height;
if (SymbsModified) {
if (strlen(pmsymbfile) && (SymbItemsLength(&FirstCode) || SymbItemsLength(&FirstData))) {
if (!SymbItemsSaveToFile(pmsymbfile)) {
MessageDialog(SymbWindow, "Error saving PokeMini symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
}
}
}
if (gtk_widget_get_realized(GTK_WIDGET(SymbWindow))) {
gtk_widget_show(GTK_WIDGET(SymbWindow));
gtk_window_deiconify(SymbWindow);
gtk_window_get_position(SymbWindow, &x, &y);
gtk_window_get_size(SymbWindow, &width, &height);
dclc_symbwin_winx = x;
dclc_symbwin_winy = y;
dclc_symbwin_winw = width;
dclc_symbwin_winh = height;
}
}
void SymbWindow_Activate(void)
{
gtk_widget_realize(GTK_WIDGET(SymbWindow));
if ((dclc_symbwin_winx > -15) && (dclc_symbwin_winy > -16)) {
gtk_window_move(SymbWindow, dclc_symbwin_winx, dclc_symbwin_winy);
}
if ((dclc_symbwin_winw > 0) && (dclc_symbwin_winh > 0)) {
gtk_window_resize(SymbWindow, dclc_symbwin_winw, dclc_symbwin_winh);
}
gtk_widget_show(GTK_WIDGET(SymbWindow));
gtk_window_present(SymbWindow);
}
void SymbWindow_UpdateConfigs(void)
{
GtkWidget *widg;
SymbWindow_InConfigs = 1;
widg = gtk_item_factory_get_item(ItemFactory, "/File/Auto read .sym");
if (dclc_autoread_minsym) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/File/Auto rw .pmsymbols");
if (dclc_autorw_emusym) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
switch (dclc_symbwin_refresh) {
case 0: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/100% 72fps")), 1);
break;
case 1: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 50% 36fps")), 1);
break;
case 2: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 33% 24fps")), 1);
break;
case 3: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 25% 18fps")), 1);
break;
case 5: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 17% 12fps")), 1);
break;
case 7: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 12% 9fps")), 1);
break;
case 11: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 8% 6fps")), 1);
break;
case 19: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/ 6% 3fps")), 1);
break;
default: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(ItemFactory, "/Refresh/Custom...")), 1);
break;
}
SymbWindow_InConfigs = 0;
}
void SymbWindow_ROMLoaded(const char *filename)
{
char tmp[PMTMPV];
if (dclc_autorw_emusym) {
if (SymbsModified) {
if (strlen(pmsymbfile) && (SymbItemsLength(&FirstCode) || SymbItemsLength(&FirstData))) {
if (!SymbItemsSaveToFile(pmsymbfile)) {
MessageDialog(SymbWindow, "Error saving PokeMini symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
}
}
}
SymbItemsClearAll(&FirstCode);
SymbItemsClearAll(&FirstData);
strcpy(tmp, filename);
RemoveExtension(tmp);
strcat(tmp, ".pmsymbols");
strcpy(pmsymbfile, tmp);
if (FileExist(tmp)) {
if (!SymbItemsLoadFromFile(tmp)) {
MessageDialog(SymbWindow, "Error loading PokeMini symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
}
}
} else pmsymbfile[0] = 0;
if (dclc_autoread_minsym) {
strcpy(tmp, filename);
RemoveExtension(tmp);
strcat(tmp, ".sym");
if (FileExist(tmp)) {
if (!SymbItemsSetFromFile(tmp)) {
MessageDialog(SymbWindow, "Error loading PMAS symbols list", "Symbols List Error", GTK_MESSAGE_ERROR, NULL);
}
}
}
SymbsModified = 0;
SymbWindow_Reload();
}
void SymbWindow_Sensitive(int enabled)
{
if (enabled) {
gtk_widget_hide(GTK_WIDGET(LabelRunFull));
gtk_widget_show(GTK_WIDGET(ViewNB));
gtk_widget_show(GTK_WIDGET(PMSymbFile));
} else {
gtk_widget_show(GTK_WIDGET(LabelRunFull));
gtk_widget_hide(GTK_WIDGET(ViewNB));
gtk_widget_hide(GTK_WIDGET(PMSymbFile));
}
}
void SymbWindow_Refresh(int now)
{
static int refreshcnt = 0;
if ((refreshcnt <= 0) || (now)) {
refreshcnt = dclc_symbwin_refresh;
if (!now) {
if (!gtk_widget_get_visible(GTK_WIDGET(SymbWindow)) || SymbWindow_minimized) return;
}
sgtkx_drawing_view_refresh(&CodeView);
sgtkx_drawing_view_refresh(&DataView);
} else refreshcnt--;
}