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

3489 lines
136 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 "ExportBMP.h"
#include "ExportWAV.h"
#include "PokeMiniIcon_96x128.h"
#include "InstructionProc.h"
#include "InstructionInfo.h"
#include "HelpSupport.h"
#include "FileAssociation.h"
#include "CPUWindow.h"
#include "InputWindow.h"
#include "PalEditWindow.h"
#include "MemWindow.h"
#include "PRCTilesWindow.h"
#include "PRCMapWindow.h"
#include "PRCSprWindow.h"
#include "TimersWindow.h"
#include "HardIOWindow.h"
#include "IRQWindow.h"
#include "MiscWindow.h"
#include "SymbWindow.h"
#include "TraceWindow.h"
#include "ExternalWindow.h"
#include <gtk/gtk.h>
#include "GtkXDialogs.h"
#include "SGtkXDrawingView.h"
const char *AboutTxt = "PokeMini " PokeMini_Version " Debugger"
"\n\n"
"Coded by JustBurn\n"
"Thanks to p0p, Dave|X,\n"
"Onori, goldmono, Agilo,\n"
"DarkFader, asterick,\n"
"MrBlinky, Wa, Lupin and\n"
"everyone in #pmdev on\n"
"IRC EFNET!\n\n"
"Please check readme.txt\n\n"
"For latest version visit:\n"
"http://pokemini.sourceforge.net/\n\n"
"Special thanks to:\n"
"Museum of Electronic Games & Art\n"
"http://m-e-g-a.org\n"
"MEGA supports preservation\n"
"projects of digital art & culture\n";
const char *WebsiteTxt = "http://pokemini.sourceforge.net/";
// Loaded color info file
char ColorInfoFile[PMTMPV] = {0};
static int CPUWindow_InConfigs = 0;
GtkWindow *MainWindow;
static int MainWindow_minimized;
static GtkItemFactory *ItemFactory;
static GtkAccelGroup *AccelGroup;
static GtkBox *VBox1;
static GtkMenuBar *MenuBar;
static GtkTable *MTable;
static SGtkXDrawingView ProgramView;
static SGtkXDrawingView RegistersView;
static SGtkXDrawingView StackView;
static GtkNotebook *BottomNB;
static SGtkXDrawingView RAMView;
static SGtkXDrawingView EEPROMView;
static SGtkXDrawingView IOView;
static GtkScrolledWindow *EditInfoMsgSW;
static GtkTextView *EditInfoMsg;
static GtkTextBuffer *EditInfoMsgBuf;
static GtkScrolledWindow *EditInfoDebugSW;
static GtkTextView *EditInfoDebug;
static GtkTextBuffer *EditInfoDebugBuf;
static GtkFrame *StatusFrame;
static GtkLabel *StatusLabel;
static const char *CartridgeIRQVectStr[27] = {
"Reset Location",
"PRC Frame Copy IRQ",
"PRC Render IRQ",
"Timer 2 Underflow (upper) IRQ",
"Timer 2 Underflow (lower) IRQ",
"Timer 1 Underflow (upper) IRQ",
"Timer 1 Underflow (lower) IRQ",
"Timer 3 Underflow (upper) IRQ",
"Timer 3 Comparator IRQ",
"32hz Timer (256hz linked) IRQ",
"8hz Timer (256hz linked) IRQ",
"2hz Timer (256hz linked) IRQ",
"1hz Timer (256hz linked) IRQ",
"IR Receiver IRQ",
"Shake Sensor IRQ",
"Power Key IRQ",
"Right Key IRQ",
"Left Key IRQ",
"Down Key IRQ",
"Up Key IRQ",
"C Key IRQ",
"B Key IRQ",
"A Key IRQ",
"Unknown 1 IRQ",
"Unknown 2 IRQ",
"Unknown 3 IRQ",
"Cartridge IRQ",
};
static uint32_t CartridgeIRQVectAddr[27] = {
0x2102, 0x2108, 0x210E, 0x2114,
0x211A, 0x2120, 0x2126, 0x212C,
0x2132, 0x2138, 0x213E, 0x2144,
0x214A, 0x2150, 0x2156, 0x215C,
0x2162, 0x2168, 0x216E, 0x2174,
0x217A, 0x2180, 0x2186, 0x218C,
0x2192, 0x2198, 0x219E
};
void Set_StatusLabel(const char *format, ...)
{
char txt[4096];
va_list args;
va_start (args, format);
vsprintf (txt, format, args);
gtk_label_set_text(StatusLabel, txt);
va_end (args);
}
void Add_InfoMessage(const char *format, ...)
{
GtkTextIter textiter;
char txt[4096];
int si;
va_list args;
va_start (args, format);
vsprintf (txt, format, args);
gtk_text_buffer_get_end_iter(EditInfoMsgBuf, &textiter);
gtk_text_buffer_insert(EditInfoMsgBuf, &textiter, txt, -1);
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(EditInfoMsgSW);
gtk_adjustment_set_value(adj, adj->upper);
va_end (args);
si = strlen(txt);
if (txt[si-1] == '\n') txt[si-1] = 0;
gtk_label_set_text(StatusLabel, txt);
}
char *DebugOutBuff = NULL;
int DebugOutBuffMode = 0; // 0 = Disabled, 1 = Add, 2 = Clear & Add
int DebugOutBuffSize = 0;
int DebugOutBuffAlloc = 0;
static void Print_DebugOutput(const char *txt, int size)
{
GtkTextIter textiter;
if (!DebugOutBuffMode) {
// Directly
gtk_text_buffer_get_end_iter(EditInfoDebugBuf, &textiter);
gtk_text_buffer_insert(EditInfoDebugBuf, &textiter, txt, size);
if ((dclc_autodebugout) && (gtk_notebook_get_current_page(BottomNB) != 4)) {
gtk_notebook_set_current_page(BottomNB, 4);
}
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(EditInfoDebugSW);
gtk_adjustment_set_value(adj, adj->upper-1);
} else {
// Buffered
if ((DebugOutBuffSize + size) >= 1048576) return;
if (DebugOutBuffAlloc <= (DebugOutBuffSize + size + 1)) {
DebugOutBuffAlloc += (size < 1024) ? 1024 : size;
DebugOutBuff = (char *)realloc(DebugOutBuff, DebugOutBuffAlloc);
}
memcpy((char *)DebugOutBuff + DebugOutBuffSize, txt, size);
DebugOutBuffSize += size;
DebugOutBuff[DebugOutBuffSize] = 0;
}
}
void Cmd_DebugOutput(int ctrl)
{
GtkTextIter startiter, enditer;
if (ctrl < 0) {
// Initialize
DebugOutBuffMode = 0;
DebugOutBuffAlloc = 0;
DebugOutBuffSize = 0;
if (DebugOutBuff) {
free(DebugOutBuff);
DebugOutBuff = NULL;
}
if (ctrl <= -2) {
gtk_text_buffer_get_start_iter(EditInfoDebugBuf, &startiter);
gtk_text_buffer_get_end_iter(EditInfoDebugBuf, &enditer);
gtk_text_buffer_delete(EditInfoDebugBuf, &startiter, &enditer);
}
} else if (ctrl == 'C') {
// Clear debug output
if (DebugOutBuffMode) {
DebugOutBuffMode = 2;
DebugOutBuffSize = 0;
} else {
gtk_text_buffer_get_start_iter(EditInfoDebugBuf, &startiter);
gtk_text_buffer_get_end_iter(EditInfoDebugBuf, &enditer);
gtk_text_buffer_delete(EditInfoDebugBuf, &startiter, &enditer);
}
} else if (ctrl == 'L') {
// Lock (Buffer)
if (DebugOutBuffMode) return;
if (!DebugOutBuff) {
DebugOutBuffAlloc = 1024;
DebugOutBuff = (char *)malloc(DebugOutBuffAlloc);
}
if (DebugOutBuff) {
DebugOutBuffMode = 1;
DebugOutBuffSize = 0;
}
} else if (ctrl == 'U') {
// Unlock (Unbuffer)
if (!DebugOutBuffMode) return;
if (DebugOutBuffMode == 2) {
gtk_text_buffer_get_start_iter(EditInfoDebugBuf, &startiter);
gtk_text_buffer_get_end_iter(EditInfoDebugBuf, &enditer);
gtk_text_buffer_delete(EditInfoDebugBuf, &startiter, &enditer);
}
gtk_text_buffer_get_end_iter(EditInfoDebugBuf, &enditer);
gtk_text_buffer_insert(EditInfoDebugBuf, &enditer, DebugOutBuff, DebugOutBuffSize);
if ((dclc_autodebugout) && (gtk_notebook_get_current_page(BottomNB) != 4)) {
gtk_notebook_set_current_page(BottomNB, 4);
}
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(EditInfoDebugSW);
gtk_adjustment_set_value(adj, adj->upper-1);
DebugOutBuffMode = 0;
DebugOutBuffSize = 0;
}
}
void Add_DebugOutputChar(unsigned char ch)
{
char txt[2] = {ch, 0};
if ((ch < 0x20) && (ch != 0x0A)) return; // Disallow controls except new lines
Print_DebugOutput(txt, 1);
}
void Add_DebugOutputNumber8(unsigned char num, int reg)
{
char txt[16];
if (reg == 1) sprintf(txt, "%02X", num);
else if (reg == 2) sprintf(txt, "%i", num);
else {
if (num & 0x80) sprintf(txt, "%i", -256 + num);
else sprintf(txt, "%i", num);
}
Print_DebugOutput(txt, strlen(txt));
}
void Add_DebugOutputNumber16(unsigned char num, int reg)
{
static unsigned char numlow = 0x00;
char txt[16];
if (reg & 1) {
if (reg & 2) {
if (num & 0x80) sprintf(txt, "%i", -65536 + (numlow + num * 256));
else sprintf(txt, "%i", (numlow + num * 256));
} else sprintf(txt, "%i", numlow + num * 256);
Print_DebugOutput(txt, strlen(txt));
} else {
numlow = num;
}
}
void Add_DebugOutputFixed8_8(unsigned char num, int reg)
{
static unsigned char numlow = 0x00;
char txt[64];
float f;
if (reg & 1) {
if (num & 0x80) {
f = (float)numlow / 256.0f + (float)(-256 + num);
sprintf(txt, "%.2f", f);
} else {
f = (float)numlow / 256.0f + (float)num;
sprintf(txt, "%.2f", f);
}
Print_DebugOutput(txt, strlen(txt));
} else {
numlow = num;
}
}
// ------
// DisAsm
// ------
static char *ColDCPUInstructions_Operand[] = {
"",
"\e234%j", "\e234%J", "\e234%i", "\e234%u", "\e234%U", "\e234%s", "\e234%S",
"\e240A", "\e240B", "\e234%u", "\e203[HL]",
"\e203[N+\e234%u\e203]", "\e203[\e234%U\e203]", "\e203[X]", "\e203[Y]",
"\e240L", "\e240H", "\e240N", "\e240SP",
"\e240BA", "\e240HL", "\e240X", "\e240Y",
"\e240F", "\e240I", "\e240XI", "\e240YI",
"\e203[X+\e234%s\e203]", "\e203[Y+\e234%s\e203]", "\e203[X+L]", "\e203[Y+L]",
"\e240U", "\e240V", "\e240XI", "\e240YI",
"\e203[SP+\e234%s\e203]", "\e240PC", "\e234%h",
NULL
};
// Disassembler with color codes
TSOpcDec CDisAsm_SOpcDec = {
DefaultOperandNumberDec, // Operand number decode
DefaultOperandNumberEnc, // Operand number encode
DebugCPUInstructions_Opcode, // Opcode dictionary
ColDCPUInstructions_Operand, // Operand dictionary
"\e024", // Opcode pre-text
" ", // Opcode post-text
"\e024, " // Operand separator
};
// -------
// Viewers
// -------
static uint32_t *ProgramView_Table = NULL;
// Get physical address of program view top
uint32_t ProgramView_GetTop(void)
{
int pp = ProgramView.sboffset;
if (!dclc_fullrange) {
if (pp >= 0x8000) {
pp = (MinxCPU.PC.B.I << 15) | (pp & 0x7FFF);
}
}
return pp;
}
// Recalculate program view table
uint32_t ProgramView_Recalc(uint32_t addr)
{
int y, size;
for (y=0; y<ProgramView.total_lines; y++) {
GetInstructionInfo(MinxCPU_OnRead, 1, addr, NULL, &size);
ProgramView_Table[y] = addr;
addr += size;
}
return addr;
}
// Syncronize program view
int ProgramView_Sync(void)
{
int pp;
// Check if the calculated begin/end match the real location
pp = ProgramView_GetTop();
if (pp != ProgramView.first_addr) {
ProgramView.first_addr = pp;
ProgramView.last_addr = ProgramView_Recalc(pp);
return 1;
}
return 0;
}
// Program view go to addr
void ProgramView_GotoAddr(uint32_t addr, int highlight)
{
int offset, laddr = addr;
if (addr >= 0x8000) laddr = 0x8000 | (addr & 0x7FFF);
// Sync program viewI should had them separate
ProgramView_Sync();
// Highlight address
if (highlight) {
ProgramView.highlight_addr = addr;
ProgramView.highlight_rem = 16;
}
// Try to point at the center
if ((addr < ProgramView.first_addr) || (addr >= ProgramView.last_addr)) {
// Not exactly in the center, but oh well
offset = ProgramView.total_lines >> 1;
if (dclc_fullrange) {
sgtkx_drawing_view_sbvalue(&ProgramView, addr - offset);
} else {
sgtkx_drawing_view_sbvalue(&ProgramView, laddr - offset);
}
}
}
// Program view go to SP
void StackView_GotoSP(void)
{
int val, begin, end;
begin = ProgramView.sboffset;
end = begin + StackView.total_lines;
val = MinxCPU.SP.W.L - 1;
if ((val < begin) || (val >= end)) {
sgtkx_drawing_view_sbvalue(&StackView, (val - 0x1000) - (StackView.total_lines >> 1));
}
}
static const char *ProgramView_CurType[4] = { "", "!", "->", "!>" };
// Program view resize event
static int ProgramView_resize(SGtkXDrawingView *widg, int width, int height, int _c)
{
int newsize;
newsize = height / 12;
if (newsize != widg->total_lines) {
widg->total_lines = newsize;
sgtkx_drawing_view_sbpage(widg, widg->total_lines - 1, widg->total_lines - 2);
// Resize table
ProgramView_Table = (uint32_t *)realloc(ProgramView_Table, ProgramView.total_lines * sizeof(uint32_t));
ProgramView_Sync();
}
return (emumode == EMUMODE_STOP);
}
// Program view exposure event
static int ProgramView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
int stripe, spp, pp, lastpp, lp, pPC;
InstructionInfo *opcode;
uint8_t data[4];
char opcodename[PMTMPV];
int size, onCur;
int y, yc, ys = -1;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) ys = (widg->mousey - 12) / 12;
// Get physical cursor location and PC
lp = pp = spp = widg->sboffset;
if (!dclc_fullrange) {
if (lp >= 0x8000) {
pp = (MinxCPU.PC.B.I << 15) | (lp & 0x7FFF);
}
}
pPC = PhysicalPC();
// Decrement highlighting remain timer
if (ProgramView.highlight_rem) {
ProgramView.highlight_rem--;
sgtkx_drawing_view_repaint_after(&ProgramView, 250);
}
// Draw content
widg->first_addr = stripe = pp;
lastpp = pp - 1;
for (y=1; y<yc+1; y++) {
// Recalculate physical address on logical mode
if (!dclc_fullrange) {
if (lp >= 0x8000) {
pp = (MinxCPU.PC.B.I << 15) | (lp & 0x7FFF);
}
}
// Bar color
onCur = 0;
if (emumode != EMUMODE_RUNFULL) {
if (ProgramView.highlight_rem && ((ProgramView.highlight_addr > lastpp) & (ProgramView.highlight_addr <= pp))) {
lastpp = pp = ProgramView.highlight_addr;
color = 0xFFE060;
} else if ((pPC > lastpp) & (pPC <= pp)) {
lastpp = pp = pPC;
if (!dclc_fullrange) {
if (lp >= 0x8000) {
pp = (MinxCPU.PC.B.I << 15) | (lp & 0x7FFF);
}
}
if (PMD_TrapPoints[pp & PM_ROM_Mask] & TRAPPOINT_BREAK) {
color = 0xFF8000;
onCur = 3;
} else {
color = 0xFFCC98;
onCur = 2;
}
} else if (PMD_TrapPoints[pp & PM_ROM_Mask] & TRAPPOINT_BREAK) {
color = 0xFF2000;
onCur = 1;
} else if ((y-1) == ys) {
if (stripe & 1) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (stripe & 1) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (stripe & 1) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
stripe++;
// Decode instruction
ProgramView_Table[y-1] = lastpp;
if (pp >= PM_ROM_Size) continue;
if (!dclc_fullrange && (lp >= 65536)) continue;
opcode = GetInstructionInfo(MinxCPU_OnRead, 1, pp, data, &size);
DisasmSingleOpcode(opcode, pp, data, opcodename, &CDisAsm_SOpcDec);
ProgramView_Table[y-1] = pp;
// Draw instruction
if (onCur) sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x603000, "%s", ProgramView_CurType[onCur]);
if (dclc_fullrange) {
sgtkx_drawing_view_drawtext(widg, 20, y * 12, 0x4C3000, "$%06X", pp);
} else {
sgtkx_drawing_view_drawtext(widg, 20, y * 12, 0x406080, "%02X\e320@%04X", (int)MinxCPU.PC.B.I, lp);
}
if (size >= 1) sgtkx_drawing_view_drawtext(widg, 84, y * 12, 0x605020, "%02X", data[0]);
if (size >= 2) sgtkx_drawing_view_drawtext(widg, 100, y * 12, 0x605040, "%02X", data[1]);
if (size >= 3) sgtkx_drawing_view_drawtext(widg, 116, y * 12, 0x605060, "%02X", data[2]);
if (size >= 4) sgtkx_drawing_view_drawtext(widg, 132, y * 12, 0x605080, "%02X", data[3]);
sgtkx_drawing_view_drawtext(widg, 156, y * 12, 0x4C3000, "%s", opcodename);
// Next one...
lastpp = pp;
pp += size; lp += size;
}
widg->last_addr = 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);
}
if (ys >= 0) {
lp = pp = ProgramView_Table[ys];
if (pp >= 0x8000) lp = 0x8000 | (pp & 0x7FFF);
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "Program Viewer - \e345%02X\e320$%04X / $%06X", (int)MinxCPU.PC.B.I, (int)lp, pp);
} else {
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "Program Viewer");
}
return 1;
}
static GtkXCustomDialog ProgramView_leftbpress[] = {
{GTKXCD_CHECK, "Change Opcode:", 1},
{GTKXCD_ENTRY, ""},
{GTKXCD_CHECK, "Enable breakpoint", 1},
{GTKXCD_EOL, ""}
};
// Program view button press
static int ProgramView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
InstructionInfo *opcode;
uint8_t data[16];
char opcodename[PMTMPV], errfail[PMTMPV];
int size, pp, ys;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
ys = (widg->mousey - 12) / 12;
set_emumode(EMUMODE_STOP, 1);
// Process selected item
pp = ProgramView_Table[ys];
opcode = GetInstructionInfo(MinxCPU_OnRead, 1, pp, data, &size);
DisasmSingleOpcode(opcode, pp, data, opcodename, &DefaultSOpcDec);
strcpy(ProgramView_leftbpress[1].text, opcodename);
ProgramView_leftbpress[2].number = PMD_TrapPoints[pp & PM_ROM_Mask] & TRAPPOINT_BREAK;
if (button == SGTKXDV_BLEFT) {
if (CustomDialog(MainWindow, "Modify opcode", ProgramView_leftbpress)) {
if (ProgramView_leftbpress[0].number) {
// Change opcode
opcode = AsmSingleOpcode(ProgramView_leftbpress[1].text, pp, data, &DefaultSOpcDec, errfail);
if (opcode) {
if (opcode->size != size) {
if (!YesNoDialog(MainWindow, "Opcode size doesn't match\nChange anyway?", "Change opcode", GTK_MESSAGE_QUESTION, NULL)) pp = -1;
}
if (pp == -1) {
// Do nothing...
} else if (pp < 0x1000) {
memset(&PM_BIOS[pp], 0xFF, size); // NOP extra space
memcpy(&PM_BIOS[pp], data, opcode->size);
} else if (pp < 0x2000) {
memset(&PM_RAM[pp-0x1000], 0xFF, size); // NOP extra space
memcpy(&PM_RAM[pp-0x1000], data, opcode->size);
} else if (pp < 0x2100) {
MessageDialog(MainWindow, "Cannot assembly hardware I/O!", "Modify opcode", GTK_MESSAGE_ERROR, NULL);
} else {
memset(&PM_ROM[pp & PM_ROM_Mask], 0xFF, size); // NOP extra space
memcpy(&PM_ROM[pp & PM_ROM_Mask], data, opcode->size);
}
} else {
MessageDialog(MainWindow, errfail, "Modify opcode", GTK_MESSAGE_ERROR, NULL);
}
}
// Change breakpoint
PMD_TrapPoints[pp & PM_ROM_Mask] &= ~TRAPPOINT_BREAK;
if (ProgramView_leftbpress[2].number) PMD_TrapPoints[pp & PM_ROM_Mask] |= TRAPPOINT_BREAK;
refresh_debug(1);
}
} else if ((button == SGTKXDV_BMIDDLE) || (button == SGTKXDV_BRIGHT)) {
// Toggle breakpoint
PMD_TrapPoints[pp & PM_ROM_Mask] ^= TRAPPOINT_BREAK;
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// CPU status string
static const char *CPUStatusStr[4] = {
"Normal",
"Halt",
"Stop",
"IRQ"
};
// Registers view exposure event
static int RegistersView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
int y, yc, ys = -1;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
ys = (widg->mousey - 12) / 12;
}
// Draw background
for (y=1; y<yc; y++) {
if (emumode != EMUMODE_RUNFULL) {
if ((y-1) == ys) {
if (y & 1) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (y & 1) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (y & 1) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
}
// 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, "Registers Viewer");
// Draw registers
y = 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "BA = $%04X,%i", (int)MinxCPU.BA.W.L, (int)MinxCPU.BA.W.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "HL = $\e345%02X\e003%04X,%i", (int)MinxCPU.HL.B.I, (int)MinxCPU.HL.W.L, (int)MinxCPU.HL.W.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " X = $\e345%02X\e003%04X,%i", (int)MinxCPU.X.B.I, (int)MinxCPU.X.W.L, (int)MinxCPU.X.W.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " Y = $\e345%02X\e003%04X,%i", (int)MinxCPU.Y.B.I, (int)MinxCPU.Y.W.L, (int)MinxCPU.Y.W.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "SP = $%04X,%i", (int)MinxCPU.SP.W.L, (int)MinxCPU.SP.W.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "PC = \e345%02X\e003$%04X,%i", (int)MinxCPU.PC.B.I, (int)MinxCPU.PC.W.L, (int)MinxCPU.PC.W.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " U = $%02X->$%02X (%i)", (int)MinxCPU.U1, (int)MinxCPU.U2, (int)MinxCPU.Shift_U);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " V = $%02X,%i", (int)MinxCPU.PC.B.I, (int)MinxCPU.PC.B.I);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " N = $%02X,%i", (int)MinxCPU.N.B.H, (int)MinxCPU.N.B.H);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " I = $%02X,%i", (int)MinxCPU.HL.B.I, (int)MinxCPU.HL.B.I);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "XI = $%02X,%i", (int)MinxCPU.X.B.I, (int)MinxCPU.X.B.I);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "YI = $%02X,%i", (int)MinxCPU.Y.B.I, (int)MinxCPU.Y.B.I);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " A = $%02X,%i", (int)MinxCPU.BA.B.L, (int)MinxCPU.BA.B.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " B = $%02X,%i", (int)MinxCPU.BA.B.H, (int)MinxCPU.BA.B.H);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " L = $%02X,%i", (int)MinxCPU.HL.B.L, (int)MinxCPU.HL.B.L);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " H = $%02X,%i", (int)MinxCPU.HL.B.H, (int)MinxCPU.HL.B.H);
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, " F = $%02X,%i", (int)MinxCPU.F, (int)MinxCPU.F);
y += 12;
if (emumode != EMUMODE_RUNFULL) {
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "\e%sI.D. \e%sI.F. \e%sNib. \e%sBCD",
(MinxCPU.F & 0x80) ? "003" : "766",
(MinxCPU.F & 0x40) ? "003" : "766",
(MinxCPU.F & 0x20) ? "003" : "766",
(MinxCPU.F & 0x10) ? "003" : "766");
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "\e%sSign \e%sOvFl \e%sCar. \e%sZe.",
(MinxCPU.F & 0x08) ? "003" : "766",
(MinxCPU.F & 0x04) ? "003" : "766",
(MinxCPU.F & 0x02) ? "003" : "766",
(MinxCPU.F & 0x01) ? "003" : "766");
y += 12;
} else {
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "\e%sI.D. \e%sI.F. \e%sNib. \e%sBCD",
(MinxCPU.F & 0x80) ? "003" : "433",
(MinxCPU.F & 0x40) ? "003" : "433",
(MinxCPU.F & 0x20) ? "003" : "433",
(MinxCPU.F & 0x10) ? "003" : "433");
y += 12;
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "\e%sSign \e%sOvFl \e%sCar. \e%sZe.",
(MinxCPU.F & 0x08) ? "003" : "433",
(MinxCPU.F & 0x04) ? "003" : "433",
(MinxCPU.F & 0x02) ? "003" : "433",
(MinxCPU.F & 0x01) ? "003" : "433");
y += 12;
}
if (MinxCPU.Status == MINX_STATUS_IRQ) {
sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "CPU Status: %s $%02X", CPUStatusStr[MinxCPU.Status], MinxCPU.IRQ_Vector);
} else sgtkx_drawing_view_drawtext(widg, 4, y, 0x00004C, "CPU Status: %s", CPUStatusStr[MinxCPU.Status]);
return 1;
}
static GtkXCustomDialog RegistersView_Uregister[] = {
{GTKXCD_LABEL, "Set U (Latch 1):"},
{GTKXCD_NUMIN, "", 0, 2, 1, -255, 255},
{GTKXCD_LABEL, "Set U (Latch 2):"},
{GTKXCD_NUMIN, "", 0, 2, 1, -255, 255},
{GTKXCD_LABEL, "Shift U ammount:"},
{GTKXCD_NUMIN, "", 0, 2, 0, 0, 3},
{GTKXCD_EOL, ""}
};
static GtkXCustomDialog RegistersView_CPUStatus[] = {
{GTKXCD_RADIO, "Normal", 1},
{GTKXCD_RADIO, "Halt", 0},
{GTKXCD_RADIO, "Stop", 0},
{GTKXCD_RADIO, "IRQ", 0},
{GTKXCD_LABEL, "IRQ Vector:"},
{GTKXCD_NUMIN, "", 0, 2, 0, 0, 127},
{GTKXCD_EOL, ""}
};
// Registers view button press
static int RegistersView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int result = 0, val;
int ys = -1, xs = -1;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
ys = (widg->mousey - 12) / 12;
xs = widg->mousex / 40;
set_emumode(EMUMODE_STOP, 1);
if (button == SGTKXDV_BLEFT) {
switch (ys) {
case 0: result = EnterNumberDialog(MainWindow, "Change register", "Set BA value:", &val, (int)MinxCPU.BA.W.L, 4, 1, -65535, 65535);
break;
case 1: result = EnterNumberDialog(MainWindow, "Change register", "Set HL value:", &val, (int)MinxCPU.HL.W.L, 4, 1, -65535, 65535);
break;
case 2: result = EnterNumberDialog(MainWindow, "Change register", "Set X value:", &val, (int)MinxCPU.X.W.L, 4, 1, -65535, 65535);
break;
case 3: result = EnterNumberDialog(MainWindow, "Change register", "Set Y value:", &val, (int)MinxCPU.Y.W.L, 4, 1, -65535, 65535);
break;
case 4: result = EnterNumberDialog(MainWindow, "Change register", "Set SP value:", &val, (int)MinxCPU.SP.W.L, 4, 1, -65535, 65535);
break;
case 5: result = EnterNumberDialog(MainWindow, "Change register", "Set PC value:", &val, (int)MinxCPU.PC.W.L, 4, 1, -65535, 65535);
break;
case 6: RegistersView_Uregister[1].number = (int)MinxCPU.U1;
RegistersView_Uregister[3].number = (int)MinxCPU.U2;
RegistersView_Uregister[5].number = (int)MinxCPU.Shift_U;
result = CustomDialog(MainWindow, "Change register", RegistersView_Uregister);
break;
case 7: result = EnterNumberDialog(MainWindow, "Change register", "Set V value:", &val, (int)MinxCPU.PC.B.I, 2, 1, -255, 255);
break;
case 8: result = EnterNumberDialog(MainWindow, "Change register", "Set N value:", &val, (int)MinxCPU.N.B.H, 2, 1, -255, 255);
break;
case 9: result = EnterNumberDialog(MainWindow, "Change register", "Set I value:", &val, (int)MinxCPU.HL.B.I, 2, 1, -255, 255);
break;
case 10:result = EnterNumberDialog(MainWindow, "Change register", "Set XI value:", &val, (int)MinxCPU.X.B.I, 2, 1, -255, 255);
break;
case 11:result = EnterNumberDialog(MainWindow, "Change register", "Set YI value:", &val, (int)MinxCPU.Y.B.I, 2, 1, -255, 255);
break;
case 12:result = EnterNumberDialog(MainWindow, "Change register", "Set A value:", &val, (int)MinxCPU.BA.B.L, 2, 1, -255, 255);
break;
case 13:result = EnterNumberDialog(MainWindow, "Change register", "Set B value:", &val, (int)MinxCPU.BA.B.H, 2, 1, -255, 255);
break;
case 14:result = EnterNumberDialog(MainWindow, "Change register", "Set L value:", &val, (int)MinxCPU.HL.B.L, 2, 1, -255, 255);
break;
case 15:result = EnterNumberDialog(MainWindow, "Change register", "Set H value:", &val, (int)MinxCPU.HL.B.H, 2, 1, -255, 255);
break;
case 16:result = EnterNumberDialog(MainWindow, "Change register", "Set F value:", &val, (int)MinxCPU.F, 2, 1, -255, 255);
break;
case 17:if (xs == 0) MinxCPU.F ^= 0x80;
if (xs == 1) MinxCPU.F ^= 0x40;
if (xs == 2) MinxCPU.F ^= 0x20;
if (xs == 3) MinxCPU.F ^= 0x10;
break;
case 18:if (xs == 0) MinxCPU.F ^= 0x08;
if (xs == 1) MinxCPU.F ^= 0x04;
if (xs == 2) MinxCPU.F ^= 0x02;
if (xs == 3) MinxCPU.F ^= 0x01;
break;
case 19:RegistersView_CPUStatus[0].number = (MinxCPU.Status == MINX_STATUS_NORMAL);
RegistersView_CPUStatus[1].number = (MinxCPU.Status == MINX_STATUS_HALT);
RegistersView_CPUStatus[2].number = (MinxCPU.Status == MINX_STATUS_STOP);
RegistersView_CPUStatus[3].number = (MinxCPU.Status == MINX_STATUS_IRQ);
RegistersView_CPUStatus[5].number = MinxCPU.IRQ_Vector >> 1;
result = CustomDialog(MainWindow, "Change register", RegistersView_CPUStatus);
break;
}
if (result == 1) {
switch (ys) {
case 0: MinxCPU.BA.W.L = val;
break;
case 1: MinxCPU.HL.W.L = val;
break;
case 2: MinxCPU.X.W.L = val;
break;
case 3: MinxCPU.Y.W.L = val;
break;
case 4: MinxCPU.SP.W.L = val;
break;
case 5: MinxCPU.PC.W.L = val;
break;
case 6: MinxCPU.U1 = RegistersView_Uregister[1].number;
MinxCPU.U2 = RegistersView_Uregister[3].number = (int)MinxCPU.U2;
MinxCPU.Shift_U = RegistersView_Uregister[5].number & 3;
break;
case 7: MinxCPU.PC.B.I = val;
break;
case 8: MinxCPU.N.B.H = val;
break;
case 9: MinxCPU.HL.B.I = val;
break;
case 10:MinxCPU.X.B.I = val;
break;
case 11:MinxCPU.Y.B.I = val;
break;
case 12:MinxCPU.BA.B.L = val;
break;
case 13:MinxCPU.BA.B.H = val;
break;
case 14:MinxCPU.HL.B.L = val;
break;
case 15:MinxCPU.HL.B.H = val;
break;
case 16:MinxCPU.F = val;
break;
case 19: // Status
if (RegistersView_CPUStatus[0].number) MinxCPU.Status = MINX_STATUS_NORMAL;
if (RegistersView_CPUStatus[1].number) MinxCPU.Status = MINX_STATUS_HALT;
if (RegistersView_CPUStatus[2].number) MinxCPU.Status = MINX_STATUS_STOP;
if (RegistersView_CPUStatus[3].number) MinxCPU.Status = MINX_STATUS_IRQ;
MinxCPU.IRQ_Vector = RegistersView_CPUStatus[5].number << 1;
break;
}
} else if (result == -1) {
MessageDialog(MainWindow, "Invalid number", "Change register", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// Stack view exposure event
static int StackView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
uint8_t dat, watch;
int pp, y, yc, ys = -1;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
ys = (widg->mousey - 12) / 12;
}
// Draw content
pp = widg->sboffset + 0x1000;
for (y=1; y<yc+1; y++) {
if (emumode != EMUMODE_RUNFULL) {
watch = PMD_TrapPoints[pp & PM_ROM_Mask] & TRAPPOINT_WATCH;
if ((MinxCPU.SP.W.L - 1) == pp) {
if (watch) {
color = AnyView_TrapColor[watch + 1];
} else {
color = 0xFFCC98;
}
} else if (watch) {
color = AnyView_TrapColor[watch];
} else {
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 (pp >= 0x2000) continue;
dat = PM_RAM[pp & 4095];
sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x4C3000, "$%04X: $%02X,%d", pp, (int)dat, (int)dat);
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, "Stack Viewer");
return 1;
}
// Stack view button press
static int StackView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int pp, ys = -1;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
ys = (widg->mousey - 12) / 12;
set_emumode(EMUMODE_STOP, 1);
// Process selected item
pp = widg->sboffset + 0x1000 + ys;
if (button == SGTKXDV_BLEFT) {
if (pp < 0x2000) {
AnyView_NewValue_CD[1].number = (int)PM_RAM[pp & 4095];
AnyView_NewValue_CD[3].number = PMD_TrapPoints[pp] & TRAPPOINT_WATCHREAD;
AnyView_NewValue_CD[4].number = PMD_TrapPoints[pp] & TRAPPOINT_WATCHWRITE;
sprintf(AnyView_NewValue_CD[0].text, "Set new value for $%04X:", pp);
if (CustomDialog(MainWindow, "Change stack", AnyView_NewValue_CD)) {
PM_RAM[pp & 4095] = AnyView_NewValue_CD[1].number;
PMD_TrapPoints[pp] &= ~TRAPPOINT_WATCH;
if (AnyView_NewValue_CD[3].number) PMD_TrapPoints[pp] |= TRAPPOINT_WATCHREAD;
if (AnyView_NewValue_CD[4].number) PMD_TrapPoints[pp] |= TRAPPOINT_WATCHWRITE;
refresh_debug(1);
}
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// RAM view go to addr
void RAMView_GotoAddr(uint32_t addr, int highlight)
{
int set_line = (addr - 0x1000) >> 4;
// Don't do anything if it's outside range
if ((addr < 0x1000) || (addr > 0x1FFF)) return;
// Highlight address
if (highlight) {
RAMView.highlight_addr = addr;
RAMView.highlight_rem = 16;
}
// Try to point at the top
if ((set_line < RAMView.sboffset) || (set_line >= (RAMView.sboffset + RAMView.total_lines - 1))) {
sgtkx_drawing_view_sbvalue(&RAMView, set_line - (RAMView.total_lines >> 1));
}
}
// RAM view exposure event
static int RAMView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
uint8_t dat, sdat, watch;
int x, y, pp, spp;
int yc, xs = -1, ys = -1;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
if ((widg->mousex >= 56) && (widg->mousex < 376)) {
xs = (widg->mousex - 56) / 20;
ys = (widg->mousey - 12) / 12;
} else if ((widg->mousex >= 376) && (widg->mousex < 504)) {
xs = (widg->mousex - 376) / 8;
ys = (widg->mousey - 12) / 12;
}
}
// Decrement highlighting remain timer
if (RAMView.highlight_rem) {
RAMView.highlight_rem--;
sgtkx_drawing_view_repaint_after(&RAMView, 250);
}
// Draw content
pp = spp = widg->sboffset * 16 + 0x1000;
for (y=1; y<yc+1; y++) {
if (emumode != EMUMODE_RUNFULL) {
if ((y-1) == ys) {
if (pp & 16) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (pp & 16) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (pp & 16) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
if (RAMView.highlight_rem && ((RAMView.highlight_addr & ~15) == pp)) {
dat = RAMView.highlight_addr & 15;
sgtkx_drawing_view_drawfrect(widg, 56+dat*20, y * 12, 16, 12, 0xFFE060);
sgtkx_drawing_view_drawfrect(widg, 376+dat*8, y * 12, 8, 12, 0xFFE060);
}
if (((y-1) == ys) && (xs >= 0)) {
sgtkx_drawing_view_drawfrect(widg, 56+xs*20, y * 12, 16, 12, color - 0x181818);
sgtkx_drawing_view_drawfrect(widg, 376+xs*8, y * 12, 8, 12, color - 0x181818);
}
if (pp >= 0x2000) continue;
sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x4C3000, "$%04X:", pp);
for (x=0; x<16; x++) {
dat = PM_RAM[pp & 4095];
sdat = (dat < 0x01) ? '.' : dat;
watch = PMD_TrapPoints[pp & PM_ROM_Mask] & TRAPPOINT_WATCH;
if (watch) {
sgtkx_drawing_view_drawfrect(widg, 56 + x * 20, y * 12, 16, 12, AnyView_TrapColor[watch]);
}
sgtkx_drawing_view_drawtext(widg, 56 + x * 20, y * 12, 0x4C4C00, "%02X", (int)dat);
sgtkx_drawing_view_drawchar(widg, 376 + x * 8, y * 12, 0x304C00, sdat);
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);
}
pp = spp + ys * 16 + xs;
if ((ys >= 0) && (pp < 0x2000)) {
dat = PM_RAM[pp & 4095];
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "RAM Content [ $%04X => $%02X, %i ]", pp, dat, dat);
} else {
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "RAM Content");
}
return 1;
}
// RAM view button press
static int RAMView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int pp, xs = -1, ys = -1;
uint8_t val;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
if ((widg->mousex >= 56) && (widg->mousex < 376)) {
xs = (widg->mousex - 56) / 20;
ys = (widg->mousey - 12) / 12;
} else if ((widg->mousex >= 376) && (widg->mousex < 504)) {
xs = (widg->mousex - 376) / 8;
ys = (widg->mousey - 12) / 12;
} else return 0;
set_emumode(EMUMODE_STOP, 1);
// Process selected item
pp = widg->sboffset * 16 + 0x1000 + ys * 16 + xs;
if (button == SGTKXDV_BLEFT) {
if (pp < 0x2000) {
AnyView_NewValue_CD[1].number = (int)PM_RAM[pp & 4095];
AnyView_NewValue_CD[3].number = PMD_TrapPoints[pp] & TRAPPOINT_WATCHREAD;
AnyView_NewValue_CD[4].number = PMD_TrapPoints[pp] & TRAPPOINT_WATCHWRITE;
sprintf(AnyView_NewValue_CD[0].text, "Set new value for $%04X:", pp);
if (CustomDialog(MainWindow, "Change RAM", AnyView_NewValue_CD)) {
PM_RAM[pp & 4095] = AnyView_NewValue_CD[1].number;
PMD_TrapPoints[pp] &= ~TRAPPOINT_WATCH;
if (AnyView_NewValue_CD[3].number) PMD_TrapPoints[pp] |= TRAPPOINT_WATCHREAD;
if (AnyView_NewValue_CD[4].number) PMD_TrapPoints[pp] |= TRAPPOINT_WATCHWRITE;
refresh_debug(1);
}
}
} else if (button == SGTKXDV_BMIDDLE) {
if (pp < 0x2000) {
val = PMD_TrapPoints[pp];
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[pp] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[pp] |= val;
refresh_debug(1);
}
} else if (button == SGTKXDV_BRIGHT) {
if (pp < 0x2000) {
val = PMD_TrapPoints[pp];
switch (val & TRAPPOINT_WATCH) {
case TRAPPOINT_WATCHREAD | TRAPPOINT_WATCHWRITE: val = 0; break;
case TRAPPOINT_WATCHREAD: val = TRAPPOINT_WATCHREAD | TRAPPOINT_WATCHWRITE; break;
case TRAPPOINT_WATCHWRITE: val = TRAPPOINT_WATCHREAD; break;
case 0: val = TRAPPOINT_WATCHWRITE; break;
}
PMD_TrapPoints[pp] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[pp] |= val;
refresh_debug(1);
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// Hardware IO exposure event
static int IOView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
uint8_t dat, sdat, watch;
int x, y, pp, spp;
int yc, xs = -1, ys = -1;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
if ((widg->mousex >= 56) && (widg->mousex < 376)) {
xs = (widg->mousex - 56) / 20;
ys = (widg->mousey - 12) / 12;
} else if ((widg->mousex >= 376) && (widg->mousex < 504)) {
xs = (widg->mousex - 376) / 8;
ys = (widg->mousey - 12) / 12;
}
}
// Draw content
pp = spp = widg->sboffset * 16 + 0x2000;
for (y=1; y<yc+1; y++) {
if (emumode != EMUMODE_RUNFULL) {
if ((y-1) == ys) {
if (pp & 16) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (pp & 16) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (pp & 16) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
if (((y-1) == ys) && (xs >= 0)) {
sgtkx_drawing_view_drawfrect(widg, 56+xs*20, y * 12, 16, 12, color - 0x181818);
sgtkx_drawing_view_drawfrect(widg, 376+xs*8, y * 12, 8, 12, color - 0x181818);
}
if (pp >= 0x2100) continue;
sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x4C3000, "$%04X:", pp);
for (x=0; x<16; x++) {
dat = MinxCPU_OnRead(0, pp);
sdat = (dat < 0x01) ? '.' : dat;
watch = PMD_TrapPoints[pp & PM_ROM_Mask] & TRAPPOINT_WATCH;
if (watch) {
sgtkx_drawing_view_drawfrect(widg, 56 + x * 20, y * 12, 16, 12, AnyView_TrapColor[watch]);
}
sgtkx_drawing_view_drawtext(widg, 56 + x * 20, y * 12, 0x4C4C00, "%02X", (int)dat);
sgtkx_drawing_view_drawchar(widg, 376 + x * 8, y * 12, 0x304C00, sdat);
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);
}
pp = spp + ys * 16 + xs;
if ((ys >= 0) && (pp < 0x2100)) {
dat = MinxCPU_OnRead(0, pp);
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "Hardware I/O [ $%04X => $%02X, %i ]", pp, dat, dat);
} else {
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "Hardware I/O");
}
return 1;
}
// Hardware IO view button press
static int IOView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int pp, xs = -1, ys = -1;
uint8_t val;
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
if ((widg->mousex >= 56) && (widg->mousex < 376)) {
xs = (widg->mousex - 56) / 20;
ys = (widg->mousey - 12) / 12;
} else if ((widg->mousex >= 376) && (widg->mousex < 504)) {
xs = (widg->mousex - 376) / 8;
ys = (widg->mousey - 12) / 12;
} else return 0;
set_emumode(EMUMODE_STOP, 1);
// Process selected item
pp = widg->sboffset * 16 + 0x2000 + ys * 16 + xs;
if (button == SGTKXDV_BLEFT) {
if (pp < 0x2100) {
AnyView_NewValue_CD[1].number = (int)MinxCPU_OnRead(0, pp);
AnyView_NewValue_CD[3].number = PMD_TrapPoints[pp] & TRAPPOINT_WATCHREAD;
AnyView_NewValue_CD[4].number = PMD_TrapPoints[pp] & TRAPPOINT_WATCHWRITE;
sprintf(AnyView_NewValue_CD[0].text, "Set new value for $%04X:", pp);
if (CustomDialog(MainWindow, "Change Hardware IO", AnyView_NewValue_CD)) {
MinxCPU_OnWrite(0, pp, AnyView_NewValue_CD[1].number);
PMD_TrapPoints[pp] &= ~TRAPPOINT_WATCH;
if (AnyView_NewValue_CD[3].number) PMD_TrapPoints[pp] |= TRAPPOINT_WATCHREAD;
if (AnyView_NewValue_CD[4].number) PMD_TrapPoints[pp] |= TRAPPOINT_WATCHWRITE;
refresh_debug(1);
}
}
} else if (button == SGTKXDV_BMIDDLE) {
if (pp < 0x2100) {
val = PMD_TrapPoints[pp];
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[pp] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[pp] |= val;
refresh_debug(1);
}
} else if (button == SGTKXDV_BRIGHT) {
if (pp < 0x2100) {
val = PMD_TrapPoints[pp];
switch (val & TRAPPOINT_WATCH) {
case TRAPPOINT_WATCHREAD | TRAPPOINT_WATCHWRITE: val = 0; break;
case TRAPPOINT_WATCHREAD: val = TRAPPOINT_WATCHREAD | TRAPPOINT_WATCHWRITE; break;
case TRAPPOINT_WATCHWRITE: val = TRAPPOINT_WATCHREAD; break;
case 0: val = TRAPPOINT_WATCHWRITE; break;
}
PMD_TrapPoints[pp] &= ~TRAPPOINT_WATCH;
PMD_TrapPoints[pp] |= val;
refresh_debug(1);
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
// EEPROM view exposure event
static int EEPROMView_exposure(SGtkXDrawingView *widg, int width, int height, int pitch)
{
uint32_t color;
uint8_t dat, sdat;
int x, y, pp, spp;
int yc, xs = -1, ys = -1;
// Calculate height and selected item
yc = height / 12;
if ((widg->mouseinside) && (widg->mousey >= 12)) {
if ((widg->mousex >= 56) && (widg->mousex < 376)) {
xs = (widg->mousex - 56) / 20;
ys = (widg->mousey - 12) / 12;
} else if ((widg->mousex >= 376) && (widg->mousex < 504)) {
xs = (widg->mousex - 376) / 8;
ys = (widg->mousey - 12) / 12;
}
}
// Draw content
pp = spp = widg->sboffset * 16;
for (y=1; y<yc+1; y++) {
if (emumode != EMUMODE_RUNFULL) {
if ((y-1) == ys) {
if (pp & 16) color = 0xF8F8DC;
else color = 0xF8F8F8;
} else {
if (pp & 16) color = 0xFFFFE4;
else color = 0xFFFFFF;
}
} else {
if (pp & 16) color = 0x808064;
else color = 0x808080;
}
sgtkx_drawing_view_drawfrect(widg, 0, y * 12, widg->width, 12, color);
if (((y-1) == ys) && (xs >= 0)) {
sgtkx_drawing_view_drawfrect(widg, 56+xs*20, y * 12, 16, 12, color - 0x181818);
sgtkx_drawing_view_drawfrect(widg, 376+xs*8, y * 12, 8, 12, color - 0x181818);
}
if (pp >= 0x2000) continue;
sgtkx_drawing_view_drawtext(widg, 4, y * 12, 0x4C3000, "$%04X:", pp);
for (x=0; x<16; x++) {
dat = EEPROM[pp & 8191];
sdat = (dat < 0x01) ? '.' : dat;
sgtkx_drawing_view_drawtext(widg, 56 + x * 20, y * 12, 0x4C4C00, "%02X", (int)dat);
sgtkx_drawing_view_drawchar(widg, 376 + x * 8, y * 12, 0x304C00, sdat);
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);
}
pp = spp + ys * 16 + xs;
if (ys >= 0) {
dat = EEPROM[pp & 8191];
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "EEPROM Content [ $%04X => $%02X, %i ]", pp, dat, dat);
} else {
sgtkx_drawing_view_drawtext(widg, 4, 0, 0x00004C, "EEPROM Content");
}
return 1;
}
// EEPROM view button press
static int EEPROMView_buttonpress(SGtkXDrawingView *widg, int button, int press, int _c)
{
int pp, val;
int xs = -1, ys = -1;
char tmp[64];
// Calculate selected item
if (emumode == EMUMODE_RUNFULL) return 0;
if ((!widg->mouseinside) || (widg->mousey < 12)) return 0;
if ((widg->mousex >= 56) && (widg->mousex < 376)) {
xs = (widg->mousex - 56) / 20;
ys = (widg->mousey - 12) / 12;
} else if ((widg->mousex >= 376) && (widg->mousex < 504)) {
xs = (widg->mousex - 376) / 8;
ys = (widg->mousey - 12) / 12;
} else return 0;
set_emumode(EMUMODE_STOP, 1);
// Process selected item
pp = widg->sboffset * 16 + ys * 16 + xs;
if (button == SGTKXDV_BLEFT) {
if (pp < 0x2000) {
sprintf(tmp, "Set new value for $%04X:", pp);
if (EnterNumberDialog(MainWindow, "Change EEPROM", tmp, &val, (int)EEPROM[pp & 8191], 2, 1, -255, 255)) {
EEPROM[pp & 8191] = val;
refresh_debug(1);
}
}
}
set_emumode(EMUMODE_RESTORE, 1);
return 1;
}
void AnyView_DrawBackground(SGtkXDrawingView *widg, int width, int height, int zoom)
{
uint32_t *scanptr;
int x, y, xp, yp;
// Sane size
if ((width <= 0) || (width >= widg->width)) width = widg->width;
if ((height <= 0) || (height >= widg->height)) height = widg->height;
// Draw pattern
for (y=0; y<widg->height; y++) {
yp = y / zoom;
scanptr = &widg->imgptr[y * widg->pitch];
for (x=0; x<widg->width; x++) {
xp = x / zoom;
scanptr[x] = ((yp ^ xp) & 1) ? 0x808080 : 0x404040;
}
}
}
void AnyView_DrawDisableMask(SGtkXDrawingView *widg)
{
uint32_t *scanptr;
int x, y;
// Draw mask
for (y=0; y<widg->height; y++) {
scanptr = &widg->imgptr[y * widg->pitch];
for (x=0; x<widg->width; x++) {
if ((y ^ x) & 1) scanptr[x] = 0x808080;
}
}
}
uint32_t AnyView_TrapColor[8] = {
0x000000, // No Watch
0x000000, // No Watch (trace over)
0xE02000, // Watch Read
0xFF8040, // Watch Read (trace over)
0x20E000, // Watch Write
0x80FF40, // Watch Write (trace over)
0xE0D000, // Watch RW
0xFFE040, // Watch RW (trace over)
};
GtkXCustomDialog AnyView_NewValue_CD[] = {
{GTKXCD_LABEL, "Set new value for $XXXX:"},
{GTKXCD_NUMIN, "", 0, 2, 1, -255, 255},
{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, ""}
};
GtkXCustomDialog AnyView_AddWPAt_CD[] = {
{GTKXCD_LABEL, "Watchpoint address:"},
{GTKXCD_NUMIN, "", 0, 6, 1, 0, 2097151},
{GTKXCD_LABEL, "Watchpoint size:"},
{GTKXCD_NUMIN, "", 1, 2, 0, 0, 2097151},
{GTKXCD_LABEL, "Prefix \"$\" for hexadecimal numbers"},
{GTKXCD_CHECK, "Read access", 1},
{GTKXCD_CHECK, "Write access", 1},
{GTKXCD_LABEL, "Warning: Watchpoints are only triggered at\nthe end of the instruction causing it."},
{GTKXCD_EOL, ""}
};
static GtkXCustomDialog CPUWindow_GotoCartIRQ_CD[] = {
{GTKXCD_LABEL, "Go to cartridge IRQ:"},
{GTKXCD_COMBO, "", 0, 27, 0, 0, 0, CartridgeIRQVectStr},
{GTKXCD_CHECK, "Decode address from IRQ code", 1},
{GTKXCD_EOL, ""}
};
int AnyView_scroll(SGtkXDrawingView *widg, int value, int min, int max)
{
return (emumode == EMUMODE_STOP);
}
int AnyView_resize(SGtkXDrawingView *widg, int width, int height, int _c)
{
widg->total_lines = height / 12;
sgtkx_drawing_view_sbpage(widg, widg->total_lines - 1, widg->total_lines - 2);
return (emumode == EMUMODE_STOP);
}
int AnyView_enterleave(SGtkXDrawingView *widg, int inside, int _b, int _c)
{
return (emumode == EMUMODE_STOP);
}
int AnyView_motion(SGtkXDrawingView *widg, int x, int y, int _c)
{
return (emumode == EMUMODE_STOP);
}
// --------------
// Menu callbacks
// --------------
void CPUWindow_AddMinOnRecent(const char *filename)
{
int i, x;
for (x=0; x<9; x++) {
if (!strcmp(filename, dclc_recent[x])) break;
}
if (x == 10) {
// Not found, shift down
for (i=8; i>=0; i--) {
strcpy(dclc_recent[i+1], dclc_recent[i]);
}
} else if (x == 0) {
// Last loaded, do nothing
return;
} else {
// Found at x, shift middle
for (i=x-1; i>=0; i--) {
strcpy(dclc_recent[i+1], dclc_recent[i]);
}
}
strcpy(dclc_recent[0], filename);
}
static void CPUWindow_CheckDirtyROM(void)
{
char tmp[PMTMPV];
if (clc_fullscreen) return; // Dialog + Fullscreen = Hazard
if (PM_MM_Dirty) {
if (YesNoDialog(MainWindow, "ROM has been changed by Flash I/O, save MIN?", "ROM changed", GTK_MESSAGE_QUESTION, NULL)) {
if (SaveFileDialogEx(MainWindow, "Save MIN", tmp, CommandLine.min_file, "MIN Rom (*.min)\0*.min\0All (*.*)\0*.*\0", 0)) {
if (ExtensionCheck(tmp, ".zip")) {
RemoveExtension(tmp);
strcat(tmp, ".min");
}
if (!PokeMini_SaveMINFile(tmp)) {
MessageDialog(MainWindow, "Error saving ROM", "MIN save error", GTK_MESSAGE_ERROR, NULL);
}
PM_MM_Dirty = 0;
}
}
}
}
static void Menu_File_OpenMIN(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
if (OpenFileDialogEx(MainWindow, "Open MIN", tmp, CommandLine.min_file, "ZIP Package or MIN Rom (*.zip;*.min)\0*.zip;*.min\0ZIP Package (*.zip)\0*.zip\0MIN Rom (*.min)\0*.min\0All (*.*)\0*.*\0", 0)) {
if (!ExtensionCheck(tmp, ".zip") && !ExtensionCheck(tmp, ".min") && !ExtensionCheck(tmp, ".minc")) {
if (!YesNoDialog(MainWindow, "File extension should be .zip or .min, continue?", "File Extension", GTK_MESSAGE_QUESTION, NULL)) {
set_emumode(EMUMODE_RESTORE, 1);
return;
}
}
CPUWindow_CheckDirtyROM();
if (!PokeMini_LoadROM(tmp)) {
MessageDialog(MainWindow, "Error loading ROM", "MIN load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
strcpy(CommandLine.rom_dir, PokeMini_CurrDir);
CPUWindow_AddMinOnRecent(CommandLine.min_file);
ExtractPath(tmp, 0);
PokeMini_SetCurrentDir(tmp);
CPUWindow_UpdateConfigs();
PokeMini_ApplyChanges();
set_emumode(EMUMODE_RESTORE, 1);
switch (clc_autorun) {
case 1: set_emumode(EMUMODE_RUNFULL, 0); break;
case 2: set_emumode(EMUMODE_RUNDEBFRAMESND, 0); break;
case 3: set_emumode(EMUMODE_RUNDEBFRAME, 0); break;
}
} else set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_OpenBIOS(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
if (OpenFileDialogEx(MainWindow, "Open BIOS", tmp, CommandLine.bios_file, "MIN Rom (*.min)\0*.min\0All (*.*)\0*.*\0", 0)) {
if (!ExtensionCheck(tmp, ".min")) {
if (!YesNoDialog(MainWindow, "File extension should be .min, continue?", "File Extension", GTK_MESSAGE_QUESTION, NULL)) {
set_emumode(EMUMODE_RESTORE, 1);
return;
}
}
if (YesNoDialog(MainWindow, "Loading new BIOS will reset emulation\nContinue?", "Open BIOS", GTK_MESSAGE_QUESTION, NULL)) {
if (!PokeMini_LoadBIOSFile(tmp)) {
MessageDialog(MainWindow, "Error loading BIOS\nReverting to FreeBIOS", "BIOS load error", GTK_MESSAGE_ERROR, NULL);
PokeMini_LoadFreeBIOS();
return;
}
strcpy(CommandLine.bios_file, tmp);
PokeMini_Reset(0);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_ReloadMIN(GtkWidget *widget, gpointer data)
{
if (clc_fullscreen) return; // Dialog + Fullscreen = Hazard
set_emumode(EMUMODE_STOP, 1);
if (!StringIsSet(CommandLine.min_file)) {
Menu_File_OpenMIN(widget, data);
} else {
CPUWindow_CheckDirtyROM();
if (!PokeMini_LoadROM(CommandLine.min_file)) {
MessageDialog(MainWindow, "Error loading ROM", "MIN load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
}
CPUWindow_AddMinOnRecent(CommandLine.min_file);
CPUWindow_UpdateConfigs();
PokeMini_ApplyChanges();
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_FreeBIOS(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 1);
if (YesNoDialog(MainWindow, "Loading FreeBIOS will reset emulation\nContinue?", "FreeBIOS", GTK_MESSAGE_QUESTION, NULL)) {
PokeMini_LoadFreeBIOS();
CommandLine.bios_file[0] = 0;
PokeMini_Reset(0);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_Autorun(GtkWidget *widget, gpointer data)
{
int index = (int)data;
clc_autorun = index;
}
static void Menu_File_OpenColor(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
sprintf(tmp, "%sc", CommandLine.min_file);
if (OpenFileDialogEx(MainWindow, "Open Color Info", tmp, tmp, "Color Info (*.minc)\0*.minc\0All (*.*)\0*.*\0", 0)) {
if (!ExtensionCheck(tmp, ".minc")) {
if (!YesNoDialog(MainWindow, "File extension should be .minc, continue?", "File Extension", GTK_MESSAGE_QUESTION, NULL)) {
set_emumode(EMUMODE_RESTORE, 1);
return;
}
}
if (!PokeMini_LoadColorFile(tmp)) {
MessageDialog(MainWindow, "Error loading color info", "Color Info load error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_ReloadColor(GtkWidget *widget, gpointer data)
{
if (clc_fullscreen) return; // Dialog + Fullscreen = Hazard
set_emumode(EMUMODE_STOP, 1);
if (ExtensionCheck(ColorInfoFile, ".zip")) {
MessageDialog(MainWindow, "Cannot reload color file from a ZIP package", "Color Info load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
if (!StringIsSet(ColorInfoFile)) {
MessageDialog(MainWindow, "Error loading color info", "Color Info load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
if (!PokeMini_LoadColorFile(ColorInfoFile)) {
MessageDialog(MainWindow, "Error reloading color info", "Color Info load error", GTK_MESSAGE_ERROR, NULL);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Capt_Snapshot1x(GtkWidget *widget, gpointer data)
{
char filename[PMTMPV];
cairo_surface_t *surface;
uint32_t *imgptr = NULL;
cairo_status_t cairerr;
FILE *capf;
int y;
set_emumode(EMUMODE_STOP, 1);
if (SaveFileDialogEx(MainWindow, "Save snapshot (1x preview)", filename, "snapshot.png", "PNG (*.png)\0*.png\0BMP (*.bmp)\0*.bmp\0", 0)) {
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 96, 64);
imgptr = (uint32_t *)cairo_image_surface_get_data(surface);
PokeMini_VideoPreview_32(imgptr, 96, PokeMini_LCDMode);
if (ExtensionCheck(filename, ".png")) {
cairerr = cairo_surface_write_to_png(surface, filename);
if (cairerr == CAIRO_STATUS_SUCCESS) {
Add_InfoMessage("[Info] Snapshot saved to '%s'\n", filename);
} else if (cairerr == CAIRO_STATUS_NO_MEMORY) {
MessageDialog(MainWindow, "No enough memory!", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
} else if (cairerr == CAIRO_STATUS_SURFACE_TYPE_MISMATCH) {
MessageDialog(MainWindow, "Surface mismatch", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
} else if (cairerr == CAIRO_STATUS_WRITE_ERROR) {
MessageDialog(MainWindow, "Write I/O error", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
}
} else if (ExtensionCheck(filename, ".bmp")) {
capf = Open_ExportBMP(filename, 96, 64);
if (!capf) {
MessageDialog(MainWindow, "Open failed", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
for (y=0; y<64; y++) {
WriteArray_ExportBMP(capf, (uint32_t *)&imgptr[(63-y) * 96], 96);
}
Close_ExportBMP(capf);
Add_InfoMessage("[Info] Snapshot saved to '%s'\n", filename);
} else {
MessageDialog(MainWindow, "Unsupported extension", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
}
cairo_surface_destroy(surface);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Capt_SnapshotLCD(GtkWidget *widget, gpointer data)
{
char filename[PMTMPV];
cairo_surface_t *surface;
uint32_t *imgptr = NULL;
cairo_status_t cairerr;
FILE *capf;
int w, h, y;
w = 96 * PMZoom;
h = 64 * PMZoom;
set_emumode(EMUMODE_STOP, 1);
if (SaveFileDialogEx(MainWindow, "Save snapshot (from LCD)", filename, "snapshot.png", "PNG (*.png)\0*.png\0BMP (*.bmp)\0*.bmp\0", 0)) {
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
imgptr = (uint32_t *)cairo_image_surface_get_data(surface);
PokeMini_VideoBlit32(imgptr, w);
if (ExtensionCheck(filename, ".png")) {
cairerr = cairo_surface_write_to_png(surface, filename);
if (cairerr == CAIRO_STATUS_SUCCESS) {
Add_InfoMessage("[Info] Snapshot saved to '%s'\n", filename);
} else if (cairerr == CAIRO_STATUS_NO_MEMORY) {
MessageDialog(MainWindow, "No enough memory!", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
} else if (cairerr == CAIRO_STATUS_SURFACE_TYPE_MISMATCH) {
MessageDialog(MainWindow, "Surface mismatch", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
} else if (cairerr == CAIRO_STATUS_WRITE_ERROR) {
MessageDialog(MainWindow, "Write I/O error", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
}
} else if (ExtensionCheck(filename, ".bmp")) {
capf = Open_ExportBMP(filename, w, h);
if (!capf) {
MessageDialog(MainWindow, "Open failed", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
for (y=0; y<h; y++) {
WriteArray_ExportBMP(capf, (uint32_t *)&imgptr[((h-1)-y) * w], w);
}
Close_ExportBMP(capf);
Add_InfoMessage("[Info] Snapshot saved to '%s'\n", filename);
} else {
MessageDialog(MainWindow, "Unsupported extension", "Save snapshot error", GTK_MESSAGE_ERROR, NULL);
}
cairo_surface_destroy(surface);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Capt_Sound(GtkWidget *widget, gpointer data)
{
char filename[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
if (sdump) {
// Stop recording
Close_ExportWAV(sdump);
sdump = NULL;
Add_InfoMessage("[Info] Sound recording stoped\n", filename);
gtk_frame_set_label(StatusFrame, NULL);
} else {
// Start recording
if (SaveFileDialogEx(MainWindow, "Save sound", filename, "sound.wav", "16-Bits Mono WAV (*.wav)\0*.wav\0", 0)) {
sdump = Open_ExportWAV(filename, EXPORTWAV_44KHZ | EXPORTWAV_MONO | EXPORTWAV_16BITS);
if (!sdump) {
MessageDialog(MainWindow, "Error opening sound export file", "Save sound error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
Add_InfoMessage("[Info] Sound recording to '%s' started\n", filename);
sdumptime = 0.0;
gtk_frame_set_label(StatusFrame, "Recording audio: 0.00 sec(s)");
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Recent_Run(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
int index = (int)data;
if (strlen(dclc_recent[index]) == 0) return;
strcpy(tmp, dclc_recent[index]);
set_emumode(EMUMODE_STOP, 1);
CPUWindow_CheckDirtyROM();
if (!PokeMini_LoadROM(tmp)) {
MessageDialog(MainWindow, "Error loading ROM", "MIN load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
ExtractPath(tmp, 0);
PokeMini_SetCurrentDir(tmp);
CPUWindow_UpdateConfigs();
PokeMini_ApplyChanges();
set_emumode(EMUMODE_RESTORE, 1);
switch (clc_autorun) {
case 1: set_emumode(EMUMODE_RUNFULL, 0); break;
case 2: set_emumode(EMUMODE_RUNDEBFRAMESND, 0); break;
case 3: set_emumode(EMUMODE_RUNDEBFRAME, 0); break;
}
}
static void Menu_Recent_Clear(GtkWidget *widget, gpointer data)
{
int i;
for (i=0; i<10; i++) dclc_recent[i][0] = 0;
}
static void Menu_File_LoadState(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV], romfile[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
sprintf(tmp, "%s.sta", CommandLine.min_file);
if (OpenFileDialogEx(MainWindow, "Load state", tmp, tmp, "State (*.sta)\0*.sta\0All (*.*)\0*.*\0", 0)) {
if (!PokeMini_CheckSSFile(tmp, romfile)) {
MessageDialog(MainWindow, "Invalid state file", "Load state error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
if (strcmp(romfile, CommandLine.min_file)) {
if (!YesNoDialog(MainWindow, "Assigned ROM does not match, continue?", "Load state", GTK_MESSAGE_QUESTION, NULL)) {
if (YesNoDialog(MainWindow, "Want to load with the assigned ROM?", "Load state", GTK_MESSAGE_QUESTION, NULL)) {
CPUWindow_CheckDirtyROM();
if (!PokeMini_LoadROM(romfile)) {
MessageDialog(MainWindow, "Error loading ROM", "MIN load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
ExtractPath(romfile, 0);
PokeMini_SetCurrentDir(romfile);
if (!PokeMini_LoadSSFile(tmp)) {
MessageDialog(MainWindow, "Error loading state", "Load state error", GTK_MESSAGE_ERROR, NULL);
}
CPUWindow_UpdateConfigs();
PokeMini_ApplyChanges();
}
set_emumode(EMUMODE_RESTORE, 1);
return;
}
}
if (!PokeMini_LoadSSFile(tmp)) {
MessageDialog(MainWindow, "Error loading state", "Load state error", GTK_MESSAGE_ERROR, NULL);
}
PokeMini_ApplyChanges();
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_SaveState(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
sprintf(tmp, "%s.sta", CommandLine.min_file);
if (SaveFileDialogEx(MainWindow, "Save state", tmp, tmp, "State (*.sta)\0*.sta\0All (*.*)\0*.*\0", 0)) {
if (!PokeMini_SaveSSFile(tmp, CommandLine.min_file)) {
MessageDialog(MainWindow, "Error saving state", "Save state error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_SaveMIN(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
if (SaveFileDialogEx(MainWindow, "Save MIN", tmp, CommandLine.min_file, "MIN Rom (*.min)\0*.min\0All (*.*)\0*.*\0", 0)) {
if (ExtensionCheck(tmp, ".zip")) {
RemoveExtension(tmp);
strcat(tmp, ".min");
}
if (!PokeMini_SaveMINFile(tmp)) {
MessageDialog(MainWindow, "Error saving ROM", "MIN save error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_SaveBIOS(GtkWidget *widget, gpointer data)
{
char tmp[PMTMPV];
set_emumode(EMUMODE_STOP, 1);
if (SaveFileDialogEx(MainWindow, "Save BIOS", tmp, CommandLine.bios_file, "MIN Rom (*.min)\0*.min\0All (*.*)\0*.*\0", 0)) {
if (!PokeMini_SaveBIOSFile(tmp)) {
MessageDialog(MainWindow, "Error saving BIOS", "BIOS save error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_File_Quit(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 0);
emurunning = 0;
}
static void Menu_Options_Zoom(GtkWidget *widget, gpointer data)
{
int index = (int)data;
if (clc_zoom != index) {
clc_zoom = index;
setup_screen();
}
}
static void Menu_Options_BPP(GtkWidget *widget, gpointer data)
{
int index = (int)data;
if (clc_bpp != index) {
clc_bpp = index;
setup_screen();
}
}
static void Menu_Options_Palette(GtkWidget *widget, gpointer data)
{
int index = (int)data;
if (CommandLine.palette != index) {
CommandLine.palette = index;
PokeMini_VideoPalette_Index(CommandLine.palette, CommandLine.custompal, CommandLine.lcdcontrast, CommandLine.lcdbright);
}
}
static void Menu_Options_LCDMode(GtkWidget *widget, gpointer data)
{
int index = (int)data;
GtkWidget *widg;
if (CommandLine.lcdmode != index) {
CommandLine.lcdmode = index;
if ((CommandLine.lcdmode == 3) && !PRCColorMap) {
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Mode/Analog");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
CommandLine.lcdmode = 0;
}
PokeMini_ApplyChanges();
}
}
static void Menu_Options_LCDFilt(GtkWidget *widget, gpointer data)
{
int index = (int)data;
if (CommandLine.lcdfilter != index) {
CommandLine.lcdfilter = index;
PokeMini_ApplyChanges();
}
}
static void Menu_Options_LCDContrast(GtkWidget *widget, gpointer data)
{
int index = (int)data;
GtkWidget *widg;
if (CommandLine.lcdcontrast != index) {
if (index == -1) {
index = CommandLine.lcdcontrast;
set_emumode(EMUMODE_STOP, 1);
if (!EnterNumberDialog(MainWindow, "LCD Contrast...", "Set percentage of contrast boost:", &index, index, 2, 0, 0, 100)) {
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/Default");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
index = 64;
}
set_emumode(EMUMODE_RESTORE, 1);
}
CommandLine.lcdcontrast = index;
PokeMini_VideoPalette_Index(CommandLine.palette, CommandLine.custompal, CommandLine.lcdcontrast, CommandLine.lcdbright);
PokeMini_ApplyChanges();
}
}
static void Menu_Options_LCDBright(GtkWidget *widget, gpointer data)
{
int index = (int)data;
GtkWidget *widg;
if (CommandLine.lcdbright != index) {
if (index == -200) {
index = CommandLine.lcdbright;
set_emumode(EMUMODE_STOP, 1);
if (!EnterNumberDialog(MainWindow, "LCD Bright...", "Set percentage of bright offset:", &index, index, 2, 0, -100, 100)) {
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Bright/Default");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
index = 0;
}
set_emumode(EMUMODE_RESTORE, 1);
}
CommandLine.lcdbright = index;
PokeMini_VideoPalette_Index(CommandLine.palette, CommandLine.custompal, CommandLine.lcdcontrast, CommandLine.lcdbright);
PokeMini_ApplyChanges();
}
}
static void Menu_Options_RumbleLvl(GtkWidget *widget, gpointer data)
{
int index = (int)data;
if (CommandLine.rumblelvl != index) {
CommandLine.rumblelvl = index;
PokeMini_ApplyChanges();
}
}
static void Menu_Options_Sound(GtkWidget *widget, gpointer data)
{
int index = (int)data;
CommandLine.sound = index;
if (emumode & EMUMODE_SOUND) enablesound(CommandLine.sound);
}
static void Menu_Options_PiezoFilter(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Options/Piezo Filter");
CommandLine.piezofilter = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PokeMini_ApplyChanges();
}
static void Menu_Options_SyncCyc(GtkWidget *widget, gpointer data)
{
int index = (int)data;
CommandLine.synccycles = index;
}
static void Menu_Options_LowBatt(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Options/Low Battery");
CommandLine.low_battery = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PokeMini_ApplyChanges();
}
static void Menu_Options_RTC(GtkWidget *widget, gpointer data)
{
if (CPUWindow_InConfigs) return;
CommandLine.updatertc = (int)data;
}
static void Menu_Options_ShareEEP(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Options/Share EEPROM");
CommandLine.eeprom_share = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PokeMini_ApplyChanges();
}
static void Menu_Options_Multicart(GtkWidget *widget, gpointer data)
{
int index = (int)data;
if (CPUWindow_InConfigs) return;
if (CommandLine.multicart != index) {
CommandLine.multicart = index;
MessageDialog(MainWindow, "Changing multicart require a reset or reload\nCheck Multicart Internals under Misc. Window", "Multicart", GTK_MESSAGE_WARNING, NULL);
}
}
static void Menu_Options_FreeBIOS(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Options/Force FreeBIOS");
CommandLine.forcefreebios = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PokeMini_ApplyChanges();
}
static void Menu_FileAss_Reg(GtkWidget *widget, gpointer data)
{
int ret;
set_emumode(EMUMODE_STOP, 1);
if (YesNoDialog(MainWindow, "Are you sure you want to add\n.min and .minc associations?", "Question", GTK_MESSAGE_QUESTION, NULL)) {
ret = FileAssociation_DoRegister();
if (ret == 2) {
MessageDialog(MainWindow, ".min and .minc have been successfuly registered", "Success", GTK_MESSAGE_INFO, NULL);
} else if (ret == 1) {
MessageDialog(MainWindow, ".min and .minc are still associated with other program", "Note", GTK_MESSAGE_INFO, NULL);
} else if (ret == 0) {
MessageDialog(MainWindow, "Error while trying to associate extensions", "Error", GTK_MESSAGE_ERROR, NULL);
} else if (ret == -1) {
MessageDialog(MainWindow, "Unsupported for this platform", "Error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_FileAss_Unreg(GtkWidget *widget, gpointer data)
{
int ret;
set_emumode(EMUMODE_STOP, 1);
if (YesNoDialog(MainWindow, "Are you sure you want to remove\n.min and .minc associations?", "Question", GTK_MESSAGE_QUESTION, NULL)) {
ret = FileAssociation_DoUnregister();
if (ret == 2) {
MessageDialog(MainWindow, ".min and .minc have been successfuly unregistered", "Success", GTK_MESSAGE_INFO, NULL);
} else if (ret == 1) {
MessageDialog(MainWindow, ".min and .minc are still associated with other program", "Note", GTK_MESSAGE_INFO, NULL);
} else if (ret == 0) {
MessageDialog(MainWindow, "Error while trying to remove association", "Error", GTK_MESSAGE_ERROR, NULL);
} else if (ret == -1) {
MessageDialog(MainWindow, "Unsupported for this platform", "Error", GTK_MESSAGE_ERROR, NULL);
}
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Options_PalEdit(GtkWidget *widget, gpointer data)
{
PalEditWindow_Activate();
}
static void Menu_Options_DefKeyboard(GtkWidget *widget, gpointer data)
{
InputWindow_Activate(0);
}
static void Menu_Options_DefJoystick(GtkWidget *widget, gpointer data)
{
InputWindow_Activate(1);
}
static void Menu_Options_UpdEEPROM(GtkWidget *widget, gpointer data)
{
PokeMini_SaveFromCommandLines(1);
Add_InfoMessage("[Info] EEPROM Updated\n");
}
static void Menu_Debug_FullRange(GtkWidget *widget, gpointer data)
{
int val;
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/Physical range");
dclc_fullrange = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
val = ProgramView.sboffset;
if (dclc_fullrange) {
if (val >= 0x8000) val = (MinxCPU.PC.B.I << 15) | (val & 0x7FFF);
sgtkx_drawing_view_sbminmax(&ProgramView, 0, PM_ROM_Size-1);
sgtkx_drawing_view_sbvalue(&ProgramView, val);
} else {
if (val >= 0x8000) val = 0x8000 | (val & 0x7FFF);
if (PM_ROM_Size <= 65535) sgtkx_drawing_view_sbminmax(&ProgramView, 0, PM_ROM_Size-1);
else sgtkx_drawing_view_sbminmax(&ProgramView, 0, 65535);
sgtkx_drawing_view_sbvalue(&ProgramView, val);
}
refresh_debug(1);
}
static void Menu_Debug_FollowPC(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/Follow PC");
dclc_followPC = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Debug_FollowSP(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/Follow SP");
dclc_followSP = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Debug_GotoProgAddr(GtkWidget *widget, gpointer data)
{
int addr = PhysicalPC();
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Go to program address...", "Go to program address:", &addr, addr, 6, 1, 0, PM_ROM_Size-1)) {
ProgramView_GotoAddr(addr, 1);
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Debug_GotoRAMAddr(GtkWidget *widget, gpointer data)
{
int addr = 0x1000 + (RAMView.sboffset * 16);
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Go to RAM address...", "Go to RAM address:", &addr, addr, 4, 1, 0x1000, 0x1FFF)) {
RAMView_GotoAddr(addr, 1);
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Debug_GotoBIOSIRQ(GtkWidget *widget, gpointer data)
{
uint32_t addr;
int irq;
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Go to IRQ...", "Go to IRQ:", &irq, 0, 2, 0, 0, 127)) {
addr = (PM_BIOS[irq*2+1] << 8) | PM_BIOS[irq*2];
ProgramView_GotoAddr(addr, 1);
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Debug_GotoCartIRQ(GtkWidget *widget, gpointer data)
{
uint32_t addr;
uint16_t laddr;
uint8_t dat, haddr;
int result, aoff;
set_emumode(EMUMODE_STOP, 1);
result = CustomDialog(MainWindow, "Go to cartridge IRQ", CPUWindow_GotoCartIRQ_CD);
if (result == 1) {
if (CPUWindow_GotoCartIRQ_CD[2].number) {
// Decode
haddr = 0;
laddr = 0;
addr = CartridgeIRQVectAddr[CPUWindow_GotoCartIRQ_CD[1].number];
// Try to decode a few instructions
for (aoff = 0; aoff < 6; ) {
dat = MinxCPU_OnRead(0, addr + aoff);
if (aoff++ == 6) break;
if (dat == 0xCE) {
// EXPAND
dat = MinxCPU_OnRead(0, addr + aoff);
if (aoff++ == 6) break;
if (dat == 0xC4) {
// MOV U, #nn
haddr = MinxCPU_OnRead(0, addr + aoff);
if (aoff++ == 6) break;
}
} else if (dat == 0xF1) {
// JMPb @nn
laddr = MinxCPU_OnRead(0, addr + aoff);
if (aoff++ == 6) break;
if (laddr & 0x80) laddr |= 0xFF00;
laddr = addr + aoff + laddr - 1;
addr = (haddr << 16) | laddr;
break;
} else if (dat == 0xF3) {
// JMPw @nnnn
laddr = MinxCPU_OnRead(0, addr + aoff);
if (aoff++ == 6) break;
laddr |= MinxCPU_OnRead(0, addr + aoff) << 8;
if (aoff++ == 6) break;
laddr = addr + aoff + laddr - 1;
addr = (haddr << 16) | laddr;
break;
} else {
// RETI
break;
}
}
ProgramView_GotoAddr(addr, 1);
refresh_debug(1);
} else {
// Don't decode
addr = CartridgeIRQVectAddr[CPUWindow_GotoCartIRQ_CD[1].number];
ProgramView_GotoAddr(addr, 1);
refresh_debug(1);
}
} else if (result == -1) {
MessageDialog(MainWindow, "Invalid number", "Manage data symbol", GTK_MESSAGE_ERROR, NULL);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Debug_GotoPC(GtkWidget *widget, gpointer data)
{
ProgramView_GotoAddr(PhysicalPC(), 0);
}
static void Menu_Debug_GotoSP(GtkWidget *widget, gpointer data)
{
StackView_GotoSP();
}
static void Menu_DebPRC_ShowBG(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/PRC/Show Background");
dclc_PRC_bg = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PRCRenderBD = !dclc_PRC_bg;
PRCRenderBG = dclc_PRC_bg;
}
static void Menu_DebPRC_ShowSpr(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/PRC/Show Sprites");
dclc_PRC_spr = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PRCRenderSpr = dclc_PRC_spr;
}
static void Menu_DebPRC_StallCPU(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/PRC/Stall CPU");
dclc_PRC_stallcpu = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
PRCAllowStall = dclc_PRC_stallcpu;
}
static void Menu_DebPRC_StallCycles(GtkWidget *widget, gpointer data)
{
int val;
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Stall Idle Cycles", "Number of idle cycles on stall:", &val, StallCycles, 2, 0, 8, 64)) {
StallCycles = val;
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Debug_IRQCall(GtkWidget *widget, gpointer data)
{
int val;
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "IRQ Call...", "IRQ call vector:", &val, (int)0, 2, 1, 0, 127)) {
MinxCPU.Status = MINX_STATUS_IRQ;
MinxCPU.IRQ_Vector = (val & 0x7F) << 1;
}
set_emumode(EMUMODE_RESTORE, 1);
}
void Menu_Debug_RunFull(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_RUNFULL, 0);
}
void Menu_Debug_RunDFrameSnd(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_RUNDEBFRAMESND, 0);
}
void Menu_Debug_RunDFrame(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_RUNDEBFRAME, 0);
}
void Menu_Debug_RunDStep(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_RUNDEBSTEP, 0);
}
void Menu_Debug_SingleFrame(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_FRAME, 0);
}
void Menu_Debug_SingleStep(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STEP, 0);
}
void Menu_Debug_StepSkip(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STEPSKIP, 0);
}
void Menu_Debug_Stop(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 0);
}
static void Menu_Debug_ResetHard(GtkWidget *widget, gpointer data)
{
Add_InfoMessage("[Info] Emulator has been hard reset (Full)\n");
PokeMini_Reset(1);
refresh_debug(1);
}
static void Menu_Debug_ResetSoft(GtkWidget *widget, gpointer data)
{
Add_InfoMessage("[Info] Emulator has been soft reset (Partial)\n");
PokeMini_Reset(0);
refresh_debug(1);
}
static void Menu_Break_EnableBP(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable breakpoints");
PMD_EnableBreakpoints = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Break_AddBPAt(GtkWidget *widget, gpointer data)
{
int addr = PhysicalPC();
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Add breakpoint at...", "Breakpoint address:", &addr, addr, 6, 1, 0, PM_ROM_Size-1)) {
if ((addr < 0) || (addr >= PM_ROM_Size)) {
MessageDialog(MainWindow, "Address out of range", "Add breakpoint at...", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
PMD_TrapPoints[addr] |= TRAPPOINT_BREAK;
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Break_DelBPAt(GtkWidget *widget, gpointer data)
{
int addr = PhysicalPC();
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Delete breakpoint at...", "Breakpoint address:", &addr, addr, 6, 1, 0, PM_ROM_Size-1)) {
PMD_TrapPoints[addr] &= ~TRAPPOINT_BREAK;
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Break_DelAllBP(GtkWidget *widget, gpointer data)
{
int i;
for (i=0; i<PM_ROM_Size; i++) PMD_TrapPoints[i] &= ~TRAPPOINT_BREAK;
refresh_debug(1);
}
static void Menu_Break_EnableWP(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable watchpoints");
PMD_EnableWatchpoints = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Break_AddWPAt(GtkWidget *widget, gpointer data)
{
int i, num;
set_emumode(EMUMODE_STOP, 1);
AnyView_AddWPAt_CD[1].number = 0x1000;
AnyView_AddWPAt_CD[3].number = 1;
AnyView_AddWPAt_CD[5].number = 1;
AnyView_AddWPAt_CD[6].number = 1;
if (CustomDialog(MainWindow, "Add watchpoing at...", AnyView_AddWPAt_CD)) {
for (i=0; i<AnyView_AddWPAt_CD[3].number; i++) {
num = AnyView_AddWPAt_CD[1].number + i;
if ((num < 0) || (num >= PM_ROM_Size)) {
MessageDialog(MainWindow, "Address out of range", "Add watchpoint at...", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
PMD_TrapPoints[num] &= ~TRAPPOINT_WATCH;
if (AnyView_AddWPAt_CD[5].number) PMD_TrapPoints[num] |= TRAPPOINT_WATCHREAD;
if (AnyView_AddWPAt_CD[6].number) PMD_TrapPoints[num] |= TRAPPOINT_WATCHWRITE;
}
refresh_debug(1);
}
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Break_DelAllWP(GtkWidget *widget, gpointer data)
{
int i;
for (i=0; i<PM_ROM_Size; i++) PMD_TrapPoints[i] &= ~TRAPPOINT_WATCH;
refresh_debug(1);
}
static void Menu_Break_EnableEx(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable exceptions");
PMD_EnableExceptions = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Break_EnableHalt(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable HALT break");
PMD_EnableHalt = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Break_EnableStop(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable STOP break");
PMD_EnableStop = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_View_Memory(GtkWidget *widget, gpointer data)
{
MemWindow_Activate();
}
static void Menu_View_PRCTiles(GtkWidget *widget, gpointer data)
{
PRCTilesWindow_Activate();
}
static void Menu_View_PRCMap(GtkWidget *widget, gpointer data)
{
PRCMapWindow_Activate();
}
static void Menu_View_PRCSpr(GtkWidget *widget, gpointer data)
{
PRCSprWindow_Activate();
}
static void Menu_View_HardIO(GtkWidget *widget, gpointer data)
{
HardIOWindow_Activate();
}
static void Menu_View_IRQ(GtkWidget *widget, gpointer data)
{
IRQWindow_Activate();
}
static void Menu_View_Timers(GtkWidget *widget, gpointer data)
{
TimersWindow_Activate();
}
static void Menu_View_Misc(GtkWidget *widget, gpointer data)
{
MiscWindow_Activate();
}
static void Menu_View_Symb(GtkWidget *widget, gpointer data)
{
SymbWindow_Activate();
}
static void Menu_View_Trace(GtkWidget *widget, gpointer data)
{
TraceWindow_Activate();
}
static void Menu_External_Run(GtkWidget *widget, gpointer data)
{
int index = (int)data;
int ret = ExternalWindow_Launch(dclc_extapp_exec[index], dclc_extapp_atcurrdir[index]);
if (ret == 0) {
MessageDialog(MainWindow, "File not found, no assoc. or fork error", "Launch failed", GTK_MESSAGE_ERROR, NULL);
} else if (ret == -1) {
MessageDialog(MainWindow, "Command requires ROM to be loaded", "Launch failed", GTK_MESSAGE_ERROR, NULL);
}
}
static void Menu_External_Conf(GtkWidget *widget, gpointer data)
{
ExternalWindow_Activate(ItemFactory);
}
static void Menu_Messages_BPMsg(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/Breakpoints");
PMD_MessageBreakpoints = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_WPMsg(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/Watchpoints");
PMD_MessageWatchpoints = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_ExMsg(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/Exceptions");
PMD_MessageExceptions = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_HaltMsg(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/HALT break");
PMD_MessageHalt = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_StopMsg(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/STOP break");
PMD_MessageStop = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_EnableDbgOut(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable debug output");
dclc_debugout = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_AutoDbgOut(GtkWidget *widget, gpointer data)
{
GtkWidget *widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Auto-open debug output");
dclc_autodebugout = (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widg)) == TRUE);
}
static void Menu_Messages_ClearMsgs(GtkWidget *widget, gpointer data)
{
GtkTextIter startiter, enditer;
gtk_text_buffer_get_start_iter(EditInfoMsgBuf, &startiter);
gtk_text_buffer_get_end_iter(EditInfoMsgBuf, &enditer);
gtk_text_buffer_delete(EditInfoMsgBuf, &startiter, &enditer);
}
static void Menu_Messages_ClearDebugOut(GtkWidget *widget, gpointer data)
{
Cmd_DebugOutput(-2);
}
static void Menu_Refresh_Now(GtkWidget *widget, gpointer data)
{
refresh_debug(1);
}
static void Menu_Refresh(GtkWidget *widget, gpointer data)
{
int val, index = (int)data;
static int lastrefrindex = -2;
if (lastrefrindex == index) return;
lastrefrindex = index;
if (CPUWindow_InConfigs) return;
if (index >= 0) {
dclc_cpuwin_refresh = index;
} else {
set_emumode(EMUMODE_STOP, 1);
if (EnterNumberDialog(MainWindow, "Custom refresh rate", "Frames skip per refresh:", &val, dclc_cpuwin_refresh, 4, 0, 0, 1000)) {
dclc_cpuwin_refresh = val;
}
set_emumode(EMUMODE_RESTORE, 1);
}
}
static void Menu_Help_CommandLine(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 1);
display_commandline();
set_emumode(EMUMODE_RESTORE, 1);
}
static void Menu_Help_Documentation(GtkWidget *widget, gpointer data)
{
HelpLaunchDoc("index");
}
static void Menu_Help_VisitWebsite(GtkWidget *widget, gpointer data)
{
HelpLaunchURL(WebsiteTxt);
}
static void Menu_Help_About(GtkWidget *widget, gpointer data)
{
set_emumode(EMUMODE_STOP, 1);
MessageDialog(MainWindow, AboutTxt, "About...", GTK_MESSAGE_INFO, PokeMiniIcon_96x128);
set_emumode(EMUMODE_RESTORE, 1);
}
static gint MainWindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
set_emumode(EMUMODE_STOP, 0);
emurunning = 0;
return TRUE;
}
static gboolean MainWindow_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
{
if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) MainWindow_minimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
return TRUE;
}
static void MainWindow_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint time, gpointer data)
{
char tmp[PMTMPV], *ptr = NULL;
gchar **urilist;
// Must contain data
if((selection_data == NULL) || (selection_data->length < 0)) {
gtk_drag_finish(context, FALSE, FALSE, time);
return;
}
// Get URI convert to filename
urilist = gtk_selection_data_get_uris(selection_data);
if (urilist[0]) {
ptr = g_filename_from_uri(urilist[0], NULL, NULL);
}
g_strfreev(urilist);
if (!ptr) {
gtk_drag_finish(context, FALSE, FALSE, time);
return;
}
strncpy(tmp, ptr, PMTMPV);
tmp[PMTMPV-1] = 0;
g_free(ptr);
gtk_drag_finish(context, TRUE, FALSE, time);
set_emumode(EMUMODE_STOP, 1);
if (!ExtensionCheck(tmp, ".zip") && !ExtensionCheck(tmp, ".min") && !ExtensionCheck(tmp, ".minc")) {
if (!YesNoDialog(MainWindow, "File extension should be .zip or .min, continue?", "File Extension", GTK_MESSAGE_QUESTION, NULL)) {
set_emumode(EMUMODE_RESTORE, 1);
return;
}
}
CPUWindow_CheckDirtyROM();
if (!PokeMini_LoadROM(tmp)) {
MessageDialog(MainWindow, "Error loading ROM", "MIN load error", GTK_MESSAGE_ERROR, NULL);
set_emumode(EMUMODE_RESTORE, 1);
return;
}
CPUWindow_AddMinOnRecent(CommandLine.min_file);
ExtractPath(tmp, 0);
PokeMini_SetCurrentDir(tmp);
CPUWindow_UpdateConfigs();
PokeMini_ApplyChanges();
set_emumode(EMUMODE_RESTORE, 1);
switch (clc_autorun) {
case 1: set_emumode(EMUMODE_RUNFULL, 0); break;
case 2: set_emumode(EMUMODE_RUNDEBFRAMESND, 0); break;
case 3: set_emumode(EMUMODE_RUNDEBFRAME, 0); break;
}
}
// Mod: 0 = None, 1 = Ctrl, 2 = Shift, 4 = Alt
TMenu_items_accel Menu_item_accel[] = {
{ SDLK_o, 5, Menu_File_ReloadMIN },
{ SDLK_c, 5, Menu_File_ReloadColor },
{ SDLK_q, 1, Menu_File_Quit },
{ SDLK_F5, 0, Menu_Debug_RunFull },
{ SDLK_F5, 2, Menu_Debug_RunDFrameSnd },
{ SDLK_F5, 1, Menu_Debug_RunDFrame },
{ SDLK_F3, 1, Menu_Debug_RunDStep },
{ SDLK_F4, 0, Menu_Debug_SingleFrame },
{ SDLK_F3, 0, Menu_Debug_SingleStep },
{ SDLK_F3, 2, Menu_Debug_StepSkip },
{ SDLK_F2, 0, Menu_Debug_Stop },
{ SDLK_r, 1, Menu_Debug_ResetHard },
{ SDLK_r, 2, Menu_Debug_ResetSoft },
{ 0, 0, NULL }
};
static GtkItemFactoryEntry CPUWindow_MenuItems[] = {
{ "/_File", NULL, NULL, 0, "<Branch>" },
{ "/File/Open _Min...", "<CTRL>O", Menu_File_OpenMIN, 0, "<Item>" },
{ "/File/Open _BIOS...", "<CTRL>B", Menu_File_OpenBIOS, 0, "<Item>" },
{ "/File/_Reload Min", "<CTRL><ALT>O", Menu_File_ReloadMIN, 0, "<Item>" },
{ "/File/Use internal _FreeBIOS", NULL, Menu_File_FreeBIOS, 0, "<Item>" },
{ "/File/Autorun/Disabled", NULL, Menu_File_Autorun, 0, "<RadioItem>" },
{ "/File/Autorun/Run full speed", NULL, Menu_File_Autorun, 1, "/File/Autorun/Disabled" },
{ "/File/Autorun/Debug frames (Sound)", NULL, Menu_File_Autorun, 2, "/File/Autorun/Disabled" },
{ "/File/Autorun/Debug frames", NULL, Menu_File_Autorun, 3, "/File/Autorun/Disabled" },
{ "/File/sep0", NULL, NULL, 0, "<Separator>" },
{ "/File/_Recent", NULL, NULL, 0, "<Branch>" },
{ "/File/Recent/ROM0", "<CTRL><SHIFT>1",Menu_Recent_Run, 0, "<Item>" },
{ "/File/Recent/ROM1", "<CTRL><SHIFT>2",Menu_Recent_Run, 1, "<Item>" },
{ "/File/Recent/ROM2", "<CTRL><SHIFT>3",Menu_Recent_Run, 2, "<Item>" },
{ "/File/Recent/ROM3", "<CTRL><SHIFT>4",Menu_Recent_Run, 3, "<Item>" },
{ "/File/Recent/ROM4", "<CTRL><SHIFT>5",Menu_Recent_Run, 4, "<Item>" },
{ "/File/Recent/ROM5", "<CTRL><SHIFT>6",Menu_Recent_Run, 5, "<Item>" },
{ "/File/Recent/ROM6", "<CTRL><SHIFT>7",Menu_Recent_Run, 6, "<Item>" },
{ "/File/Recent/ROM7", "<CTRL><SHIFT>8",Menu_Recent_Run, 7, "<Item>" },
{ "/File/Recent/ROM8", "<CTRL><SHIFT>9",Menu_Recent_Run, 8, "<Item>" },
{ "/File/Recent/ROM9", "<CTRL><SHIFT>0",Menu_Recent_Run, 9, "<Item>" },
{ "/File/Recent/sep1", NULL, NULL, 0, "<Separator>" },
{ "/File/Recent/Clear List", NULL, Menu_Recent_Clear, 0, "<Item>" },
{ "/File/sep1", NULL, NULL, 0, "<Separator>" },
{ "/File/_Load state...", NULL, Menu_File_LoadState, 0, "<Item>" },
{ "/File/_Save state...", NULL, Menu_File_SaveState, 0, "<Item>" },
{ "/File/sep2", NULL, NULL, 0, "<Separator>" },
{ "/File/Open _Color Info...", "<CTRL><ALT>C",Menu_File_OpenColor, 0, "<Item>" },
{ "/File/Reload _Color Info", "<CTRL><SHIFT>C",Menu_File_ReloadColor, 0, "<Item>" },
{ "/File/sep3", NULL, NULL, 0, "<Separator>" },
{ "/File/_Capture", NULL, NULL, 0, "<Branch>" },
{ "/File/Capture/Snapshot 1x preview", NULL, Menu_Capt_Snapshot1x, 0, "<Item>" },
{ "/File/Capture/Snapshot from LCD", NULL, Menu_Capt_SnapshotLCD, 0, "<Item>" },
{ "/File/Capture/Sound (Start & Stop)", NULL, Menu_Capt_Sound, 0, "<Item>" },
{ "/File/Save _Min...", "<CTRL>S", Menu_File_SaveMIN, 0, "<Item>" },
{ "/File/Save _BIOS...", NULL, Menu_File_SaveBIOS, 0, "<Item>" },
{ "/File/sep4", NULL, NULL, 0, "<Separator>" },
{ "/File/_Quit", "<CTRL>Q", Menu_File_Quit, 0, "<Item>" },
{ "/_Options", NULL, NULL, 0, "<Branch>" },
{ "/Options/_Zoom", NULL, NULL, 0, "<Branch>" },
{ "/Options/Zoom/1x (96x64)", NULL, Menu_Options_Zoom, 1, "<RadioItem>" },
{ "/Options/Zoom/2x (192x128)", NULL, Menu_Options_Zoom, 2, "/Options/Zoom/1x (96x64)" },
{ "/Options/Zoom/3x (288x192)", NULL, Menu_Options_Zoom, 3, "/Options/Zoom/1x (96x64)" },
{ "/Options/Zoom/4x (384x256)", NULL, Menu_Options_Zoom, 4, "/Options/Zoom/1x (96x64)" },
{ "/Options/Zoom/5x (480x320)", NULL, Menu_Options_Zoom, 5, "/Options/Zoom/1x (96x64)" },
{ "/Options/Zoom/6x (576x384)", NULL, Menu_Options_Zoom, 6, "/Options/Zoom/1x (96x64)" },
{ "/Options/_Bits-Per-Pixel", NULL, NULL, 0, "<Branch>" },
{ "/Options/Bits-Per-Pixel/16 bpp", NULL, Menu_Options_BPP, 16, "<RadioItem>" },
{ "/Options/Bits-Per-Pixel/32 bpp", NULL, Menu_Options_BPP, 32, "/Options/Bits-Per-Pixel/16 bpp" },
{ "/Options/_Palette", NULL, NULL, 0, "<Branch>" },
{ "/Options/Palette/Default", NULL, Menu_Options_Palette, 0, "<RadioItem>" },
{ "/Options/Palette/Old", NULL, Menu_Options_Palette, 1, "/Options/Palette/Default" },
{ "/Options/Palette/Black & White", NULL, Menu_Options_Palette, 2, "/Options/Palette/Default" },
{ "/Options/Palette/Green Palette", NULL, Menu_Options_Palette, 3, "/Options/Palette/Default" },
{ "/Options/Palette/Green Vector", NULL, Menu_Options_Palette, 4, "/Options/Palette/Default" },
{ "/Options/Palette/Red Palette", NULL, Menu_Options_Palette, 5, "/Options/Palette/Default" },
{ "/Options/Palette/Red Vector", NULL, Menu_Options_Palette, 6, "/Options/Palette/Default" },
{ "/Options/Palette/Blue LCD", NULL, Menu_Options_Palette, 7, "/Options/Palette/Default" },
{ "/Options/Palette/LED Backlight", NULL, Menu_Options_Palette, 8, "/Options/Palette/Default" },
{ "/Options/Palette/Girl Power", NULL, Menu_Options_Palette, 9, "/Options/Palette/Default" },
{ "/Options/Palette/Blue Palette", NULL, Menu_Options_Palette, 10, "/Options/Palette/Default" },
{ "/Options/Palette/Blue Vector", NULL, Menu_Options_Palette, 11, "/Options/Palette/Default" },
{ "/Options/Palette/Sepia", NULL, Menu_Options_Palette, 12, "/Options/Palette/Default" },
{ "/Options/Palette/Inverted B&W", NULL, Menu_Options_Palette, 13, "/Options/Palette/Default" },
{ "/Options/Palette/Custom 1", NULL, Menu_Options_Palette, 14, "/Options/Palette/Default" },
{ "/Options/Palette/Custom 2", NULL, Menu_Options_Palette, 15, "/Options/Palette/Default" },
{ "/Options/_LCD Mode", NULL, NULL, 0, "<Branch>" },
{ "/Options/LCD Mode/Analog", NULL, Menu_Options_LCDMode, 0, "<RadioItem>" },
{ "/Options/LCD Mode/3-Shades", NULL, Menu_Options_LCDMode, 1, "/Options/LCD Mode/Analog" },
{ "/Options/LCD Mode/2-Shades", NULL, Menu_Options_LCDMode, 2, "/Options/LCD Mode/Analog" },
{ "/Options/LCD Mode/Colors*", NULL, Menu_Options_LCDMode, 3, "/Options/LCD Mode/Analog" },
{ "/Options/LCD _Filter", NULL, NULL, 0, "<Branch>" },
{ "/Options/LCD Filter/None", NULL, Menu_Options_LCDFilt, 0, "<RadioItem>" },
{ "/Options/LCD Filter/Dot-Matrix", NULL, Menu_Options_LCDFilt, 1, "/Options/LCD Filter/None" },
{ "/Options/LCD Filter/50% Scanline", NULL, Menu_Options_LCDFilt, 2, "/Options/LCD Filter/None" },
{ "/Options/LCD _Contrast", NULL, NULL, 0, "<Branch>" },
{ "/Options/LCD Contrast/Default", NULL, Menu_Options_LCDContrast, 64, "<RadioItem>" },
{ "/Options/LCD Contrast/Lowest", NULL, Menu_Options_LCDContrast, 0, "/Options/LCD Contrast/Default" },
{ "/Options/LCD Contrast/Low", NULL, Menu_Options_LCDContrast, 25, "/Options/LCD Contrast/Default" },
{ "/Options/LCD Contrast/Medium", NULL, Menu_Options_LCDContrast, 50, "/Options/LCD Contrast/Default" },
{ "/Options/LCD Contrast/High", NULL, Menu_Options_LCDContrast, 75, "/Options/LCD Contrast/Default" },
{ "/Options/LCD Contrast/Highest", NULL, Menu_Options_LCDContrast, 100, "/Options/LCD Contrast/Default" },
{ "/Options/LCD Contrast/Custom...", NULL, Menu_Options_LCDContrast, -1, "<Item>" },
{ "/Options/LCD _Brightness", NULL, NULL, 0, "<Branch>" },
{ "/Options/LCD Brightness/Default", NULL, Menu_Options_LCDBright, 0, "<RadioItem>" },
{ "/Options/LCD Brightness/Lighter", NULL, Menu_Options_LCDBright, 24, "/Options/LCD Brightness/Default" },
{ "/Options/LCD Brightness/Light", NULL, Menu_Options_LCDBright, 12, "/Options/LCD Brightness/Default" },
{ "/Options/LCD Brightness/Dark", NULL, Menu_Options_LCDBright, -12, "/Options/LCD Brightness/Default" },
{ "/Options/LCD Brightness/Darker", NULL, Menu_Options_LCDBright, -24, "/Options/LCD Brightness/Default" },
{ "/Options/LCD Brightness/Custom...", NULL, Menu_Options_LCDBright, -200, "<Item>" },
{ "/Options/_Rumble Level", NULL, NULL, 0, "<Branch>" },
{ "/Options/Rumble Level/None", NULL, Menu_Options_RumbleLvl, 0, "<RadioItem>" },
{ "/Options/Rumble Level/Weak", NULL, Menu_Options_RumbleLvl, 1, "/Options/Rumble Level/None" },
{ "/Options/Rumble Level/Medium", NULL, Menu_Options_RumbleLvl, 2, "/Options/Rumble Level/None" },
{ "/Options/Rumble Level/Strong", NULL, Menu_Options_RumbleLvl, 3, "/Options/Rumble Level/None" },
{ "/Options/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Options/_Sound", NULL, NULL, 0, "<Branch>" },
{ "/Options/Sound/Disabled", NULL, Menu_Options_Sound, 0, "<RadioItem>" },
{ "/Options/Sound/Generated", NULL, Menu_Options_Sound, 1, "/Options/Sound/Disabled" },
{ "/Options/Sound/Direct", NULL, Menu_Options_Sound, 2, "/Options/Sound/Disabled" },
{ "/Options/Sound/Emulated", NULL, Menu_Options_Sound, 3, "/Options/Sound/Disabled" },
{ "/Options/Sound/Direct PWM", NULL, Menu_Options_Sound, 4, "/Options/Sound/Disabled" },
{ "/Options/Pie_zo Filter", NULL, Menu_Options_PiezoFilter, 0, "<CheckItem>" },
{ "/Options/sep2", NULL, NULL, 0, "<Separator>" },
{ "/Options/_Sync Cycles", NULL, NULL, 0, "<Branch>" },
{ "/Options/Sync Cycles/ 8 (Accurancy)", NULL, Menu_Options_SyncCyc, 8, "<RadioItem>" },
{ "/Options/Sync Cycles/ 16", NULL, Menu_Options_SyncCyc, 16, "/Options/Sync Cycles/ 8 (Accurancy)" },
{ "/Options/Sync Cycles/ 32", NULL, Menu_Options_SyncCyc, 32, "/Options/Sync Cycles/ 8 (Accurancy)" },
{ "/Options/Sync Cycles/ 64 (Performance)", NULL, Menu_Options_SyncCyc, 64, "/Options/Sync Cycles/ 8 (Accurancy)" },
{ "/Options/sep3", NULL, NULL, 0, "<Separator>" },
{ "/Options/_Low Battery", NULL, Menu_Options_LowBatt, 0, "<CheckItem>" },
{ "/Options/_RTC", NULL, NULL, 0, "<Branch>" },
{ "/Options/RTC/No RTC", NULL, Menu_Options_RTC, 0, "<RadioItem>" },
{ "/Options/RTC/State time difference", NULL, Menu_Options_RTC, 1, "/Options/RTC/No RTC" },
{ "/Options/RTC/RTC from Host", NULL, Menu_Options_RTC, 2, "/Options/RTC/No RTC" },
{ "/Options/Share _EEPROM", NULL, Menu_Options_ShareEEP, 0, "<CheckItem>" },
{ "/Options/_Multicart", NULL, NULL, 0, "<Branch>" },
{ "/Options/Multicart/Disabled", NULL, Menu_Options_Multicart, 0, "<RadioItem>" },
{ "/Options/Multicart/Flash 512KB (AM29LV040B)",NULL, Menu_Options_Multicart, 1, "/Options/Multicart/Disabled" },
{ "/Options/Multicart/Lupin 512KB (AM29LV040B)",NULL, Menu_Options_Multicart, 2, "/Options/Multicart/Disabled" },
{ "/Options/Force Free_BIOS", NULL, Menu_Options_FreeBIOS, 0, "<CheckItem>" },
{ "/Options/sep3", NULL, NULL, 0, "<Separator>" },
{ "/Options/File association", NULL, NULL, 0, "<Branch>" },
{ "/Options/File association/Register", NULL, Menu_FileAss_Reg, 0, "<Item>" },
{ "/Options/File association/Unregister", NULL, Menu_FileAss_Unreg, 0, "<Item>" },
{ "/Options/sep4", NULL, NULL, 0, "<Separator>" },
{ "/Options/_Custom Palette Edit...", NULL, Menu_Options_PalEdit, 0, "<Item>" },
{ "/Options/Define _Keyboard...", NULL, Menu_Options_DefKeyboard, 0, "<Item>" },
{ "/Options/Define _Joystick...", NULL, Menu_Options_DefJoystick, 0, "<Item>" },
{ "/Options/_Update EEPROM", NULL, Menu_Options_UpdEEPROM, 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 s_kip", "<SHIFT>F3", Menu_Debug_StepSkip, 0, "<Item>" },
{ "/Debugger/_Stop", "F2", Menu_Debug_Stop, 0, "<Item>" },
{ "/Debugger/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Debugger/_Physical range", "<CTRL>P", Menu_Debug_FullRange, 0, "<CheckItem>" },
{ "/Debugger/_Follow PC", "<CTRL>F", Menu_Debug_FollowPC, 0, "<CheckItem>" },
{ "/Debugger/_Follow SP", "<CTRL><ALT>F", Menu_Debug_FollowSP, 0, "<CheckItem>" },
{ "/Debugger/_Go to program address...", "<CTRL>G", Menu_Debug_GotoProgAddr, 0, "<Item>" },
{ "/Debugger/_Go to RAM address...", "<SHIFT>G", Menu_Debug_GotoRAMAddr, 0, "<Item>" },
{ "/Debugger/_Go to BIOS IRQ...", NULL, Menu_Debug_GotoBIOSIRQ, 0, "<Item>" },
{ "/Debugger/_Go to cartridge IRQ...", "<CTRL><ALT>G", Menu_Debug_GotoCartIRQ, 0, "<Item>" },
{ "/Debugger/Go to _PC", "<SHIFT>P", Menu_Debug_GotoPC, 0, "<Item>" },
{ "/Debugger/Go to _SP", "<SHIFT>S", Menu_Debug_GotoSP, 0, "<Item>" },
{ "/Debugger/sep2", NULL, NULL, 0, "<Separator>" },
{ "/Debugger/_PRC", NULL, NULL, 0, "<Branch>" },
{ "/Debugger/PRC/Show _Background", NULL, Menu_DebPRC_ShowBG, 0, "<CheckItem>" },
{ "/Debugger/PRC/Show _Sprites", NULL, Menu_DebPRC_ShowSpr, 0, "<CheckItem>" },
{ "/Debugger/PRC/Stall _CPU", NULL, Menu_DebPRC_StallCPU, 0, "<CheckItem>" },
{ "/Debugger/PRC/Stall _Cycles...", NULL, Menu_DebPRC_StallCycles, 0, "<Item>" },
{ "/Debugger/_IRQ call...", NULL, Menu_Debug_IRQCall, 0, "<Item>" },
{ "/Debugger/_Reset", NULL, NULL, 0, "<Branch>" },
{ "/Debugger/Reset/_Soft (Partial)", "<SHIFT>R", Menu_Debug_ResetSoft, 0, "<Item>" },
{ "/Debugger/Reset/_Hard (Full)", "<CTRL>R", Menu_Debug_ResetHard, 0, "<Item>" },
{ "/_Break", NULL, NULL, 0, "<Branch>" },
{ "/Break/_Enable breakpoints", "<ALT><SHIFT>B",Menu_Break_EnableBP, 0, "<CheckItem>" },
{ "/Break/_Add breakpoint at...", "<SHIFT>B", Menu_Break_AddBPAt, 0, "<Item>" },
{ "/Break/_Delete breakpoint at...", "<CTRL><SHIFT>B",Menu_Break_DelBPAt, 0, "<Item>" },
{ "/Break/_Delete all breakpoints", NULL, Menu_Break_DelAllBP, 0, "<Item>" },
{ "/Break/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Break/_Enable watchpoints", "<ALT><SHIFT>W",Menu_Break_EnableWP, 0, "<CheckItem>" },
{ "/Break/_Add Watchpoint at...", "<SHIFT>W", Menu_Break_AddWPAt, 0, "<Item>" },
{ "/Break/_Delete all watchpoints", NULL, Menu_Break_DelAllWP, 0, "<Item>" },
{ "/Break/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Break/_Enable exceptions", NULL, Menu_Break_EnableEx, 0, "<CheckItem>" },
{ "/Break/_Enable HALT break", NULL, Menu_Break_EnableHalt, 0, "<CheckItem>" },
{ "/Break/_Enable STOP break", NULL, Menu_Break_EnableStop, 0, "<CheckItem>" },
{ "/_Viewers", NULL, NULL, 0, "<Branch>" },
{ "/Viewers/_Memory View", "<CTRL>1", Menu_View_Memory, 0, "<Item>" },
{ "/Viewers/_PRC Tiles View", "<CTRL>2", Menu_View_PRCTiles, 0, "<Item>" },
{ "/Viewers/_PRC Map View", "<CTRL>3", Menu_View_PRCMap, 0, "<Item>" },
{ "/Viewers/_PRC Sprites View", "<CTRL>4", Menu_View_PRCSpr, 0, "<Item>" },
{ "/Viewers/_Timers View", "<CTRL>5", Menu_View_Timers, 0, "<Item>" },
{ "/Viewers/_Hardware IO View", "<CTRL>6", Menu_View_HardIO, 0, "<Item>" },
{ "/Viewers/_IRQ View", "<CTRL>7", Menu_View_IRQ, 0, "<Item>" },
{ "/Viewers/_Misc. View", "<CTRL>8", Menu_View_Misc, 0, "<Item>" },
{ "/Viewers/_Symbols List View", "<CTRL>9", Menu_View_Symb, 0, "<Item>" },
{ "/Viewers/_Run Trace View", "<CTRL>0", Menu_View_Trace, 0, "<Item>" },
{ "/_External", NULL, NULL, 0, "<Branch>" },
{ "/External/App1", "<CTRL><ALT>1", Menu_External_Run, 0, "<Item>" },
{ "/External/App2", "<CTRL><ALT>2", Menu_External_Run, 1, "<Item>" },
{ "/External/App3", "<CTRL><ALT>3", Menu_External_Run, 2, "<Item>" },
{ "/External/App4", "<CTRL><ALT>4", Menu_External_Run, 3, "<Item>" },
{ "/External/App5", "<CTRL><ALT>5", Menu_External_Run, 4, "<Item>" },
{ "/External/App6", "<CTRL><ALT>6", Menu_External_Run, 5, "<Item>" },
{ "/External/App7", "<CTRL><ALT>7", Menu_External_Run, 6, "<Item>" },
{ "/External/App8", "<CTRL><ALT>8", Menu_External_Run, 7, "<Item>" },
{ "/External/App9", "<CTRL><ALT>9", Menu_External_Run, 8, "<Item>" },
{ "/External/App10", "<CTRL><ALT>0", Menu_External_Run, 9, "<Item>" },
{ "/External/sep1", NULL, NULL, 0, "<Separator>" },
{ "/External/Configure...", NULL, Menu_External_Conf, 0, "<Item>" },
{ "/Messages/Enable _messages", NULL, NULL, 0, "<Branch>" },
{ "/Messages/Enable messages/Breakpoints",NULL, Menu_Messages_BPMsg, 0, "<CheckItem>" },
{ "/Messages/Enable messages/Watchpoints",NULL, Menu_Messages_WPMsg, 0, "<CheckItem>" },
{ "/Messages/Enable messages/Exceptions", NULL, Menu_Messages_ExMsg, 0, "<CheckItem>" },
{ "/Messages/Enable messages/HALT break", NULL, Menu_Messages_HaltMsg, 0, "<CheckItem>" },
{ "/Messages/Enable messages/STOP break", NULL, Menu_Messages_StopMsg, 0, "<CheckItem>" },
{ "/Messages/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Messages/_Enable debug output", NULL, Menu_Messages_EnableDbgOut, 0, "<CheckItem>" },
{ "/Messages/_Auto-open debug output", NULL, Menu_Messages_AutoDbgOut, 0, "<CheckItem>" },
{ "/Messages/sep2", NULL, NULL, 0, "<Separator>" },
{ "/Messages/Clear _messages", NULL, Menu_Messages_ClearMsgs, 0, "<Item>" },
{ "/Messages/Clear debug _output", NULL, Menu_Messages_ClearDebugOut, 0, "<Item>" },
{ "/_Refresh", NULL, NULL, 0, "<Branch>" },
{ "/Refresh/Now!", NULL, Menu_Refresh_Now, 0, "<Item>" },
{ "/Refresh/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Refresh/100% 72fps", NULL, Menu_Refresh, 0, "<RadioItem>" },
{ "/Refresh/ 50% 36fps", NULL, Menu_Refresh, 1, "/Refresh/100% 72fps" },
{ "/Refresh/ 33% 24fps", NULL, Menu_Refresh, 2, "/Refresh/100% 72fps" },
{ "/Refresh/ 25% 18fps", NULL, Menu_Refresh, 3, "/Refresh/100% 72fps" },
{ "/Refresh/ 17% 12fps", NULL, Menu_Refresh, 5, "/Refresh/100% 72fps" },
{ "/Refresh/ 12% 9fps", NULL, Menu_Refresh, 7, "/Refresh/100% 72fps" },
{ "/Refresh/ 8% 6fps", NULL, Menu_Refresh, 11, "/Refresh/100% 72fps" },
{ "/Refresh/ 3% 2fps", NULL, Menu_Refresh, 35, "/Refresh/100% 72fps" },
{ "/Refresh/ 1% 1fps", NULL, Menu_Refresh, 71, "/Refresh/100% 72fps" },
{ "/Refresh/Custom...", NULL, Menu_Refresh, -1, "/Refresh/100% 72fps" },
{ "/_Help", NULL, NULL, 0, "<Branch>" },
{ "/Help/_Documentation", "F1", Menu_Help_Documentation, 0, "<Item>" },
{ "/Help/_Visit website", NULL, Menu_Help_VisitWebsite, 0, "<Item>" },
{ "/Help/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Help/_Command-line switches...", NULL, Menu_Help_CommandLine, 0, "<Item>" },
{ "/Help/_About...", NULL, Menu_Help_About, 0, "<Item>" },
};
static gint CPUWindow_MenuItemsNum = sizeof(CPUWindow_MenuItems) / sizeof(*CPUWindow_MenuItems);
// Process menu item accelerator, execute callback and return if match
int ProcessMenuItemAccel(int key, int modifier, TMenu_items_accel *list)
{
if (!list) return 0;
while (list->callback) {
if ((list->key == key) && (list->modifier == modifier)) {
list->callback(NULL, NULL);
return 1;
}
list++;
}
return 0;
}
// ----------
// CPU Window
// ----------
static GtkTargetEntry drag_target_list[] = {
{ "text/uri-list", 0, 0 }
};
int CPUWindow_Create(void)
{
// Window
MainWindow = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
gtk_window_set_title(GTK_WINDOW(MainWindow), AppName);
gtk_widget_set_size_request(GTK_WIDGET(MainWindow), 500, 500);
gtk_window_set_default_size(MainWindow, 500, 500);
g_signal_connect(MainWindow, "delete_event", G_CALLBACK(MainWindow_delete_event), NULL);
g_signal_connect(MainWindow, "window-state-event", G_CALLBACK(MainWindow_state_event), NULL);
VBox1 = GTK_BOX(gtk_vbox_new(FALSE, 0));
gtk_container_add(GTK_CONTAINER(MainWindow), GTK_WIDGET(VBox1));
gtk_widget_show(GTK_WIDGET(VBox1));
gtk_drag_dest_set(GTK_WIDGET(MainWindow), GTK_DEST_DEFAULT_ALL, drag_target_list, 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
g_signal_connect(MainWindow, "drag-data-received", G_CALLBACK(MainWindow_drag_data_received), NULL);
// Menu bar
AccelGroup = gtk_accel_group_new();
ItemFactory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", AccelGroup);
gtk_item_factory_create_items(ItemFactory, CPUWindow_MenuItemsNum, CPUWindow_MenuItems, NULL);
gtk_window_add_accel_group(MainWindow, 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));
// Table on middle
MTable = GTK_TABLE(gtk_table_new(3, 2, FALSE));
gtk_box_pack_start(VBox1, GTK_WIDGET(MTable), TRUE, TRUE, 0);
gtk_widget_show(GTK_WIDGET(MTable));
// Program View
ProgramView.on_exposure = SGtkXDVCB(ProgramView_exposure);
ProgramView.on_scroll = SGtkXDVCB(AnyView_scroll);
ProgramView.on_resize = SGtkXDVCB(ProgramView_resize);
ProgramView.on_motion = SGtkXDVCB(AnyView_motion);
ProgramView.on_buttonpress = SGtkXDVCB(ProgramView_buttonpress);
ProgramView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
ProgramView.total_lines = ProgramView.height / 12;
ProgramView_Table = (uint32_t *)malloc(ProgramView.total_lines * sizeof(uint32_t));
sgtkx_drawing_view_new(&ProgramView, 1);
sgtkx_drawing_view_sbminmax(&ProgramView, 0, 0x001FFF); // $0000 to $1FFF
gtk_table_attach(MTable, GTK_WIDGET(ProgramView.box), 0, 1, 0, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
gtk_widget_show(GTK_WIDGET(ProgramView.box));
// Registers View
RegistersView.on_exposure = SGtkXDVCB(RegistersView_exposure);
RegistersView.on_scroll = SGtkXDVCB(AnyView_scroll);
RegistersView.on_resize = SGtkXDVCB(AnyView_resize);
RegistersView.on_motion = SGtkXDVCB(AnyView_motion);
RegistersView.on_buttonpress = SGtkXDVCB(RegistersView_buttonpress);
RegistersView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&RegistersView, 0);
gtk_widget_set_size_request(GTK_WIDGET(RegistersView.box), 160, 252);
gtk_table_attach(MTable, GTK_WIDGET(RegistersView.box), 1, 2, 0, 1, GTK_FILL, GTK_FILL, 2, 2);
gtk_widget_show(GTK_WIDGET(RegistersView.box));
// Stack View
StackView.on_exposure = SGtkXDVCB(StackView_exposure);
StackView.on_scroll = SGtkXDVCB(AnyView_scroll);
StackView.on_resize = SGtkXDVCB(AnyView_resize);
StackView.on_motion = SGtkXDVCB(AnyView_motion);
StackView.on_buttonpress = SGtkXDVCB(StackView_buttonpress);
StackView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&StackView, 1);
sgtkx_drawing_view_sbminmax(&StackView, 0, 0xFFF); // $1000 to $FFF
gtk_widget_set_size_request(GTK_WIDGET(StackView.box), 160, 48);
gtk_table_attach(MTable, GTK_WIDGET(StackView.box), 1, 2, 1, 2, GTK_FILL, GTK_FILL | GTK_EXPAND, 2, 2);
gtk_widget_show(GTK_WIDGET(StackView.box));
// RAM View
RAMView.on_exposure = SGtkXDVCB(RAMView_exposure);
RAMView.on_scroll = SGtkXDVCB(AnyView_scroll);
RAMView.on_resize = SGtkXDVCB(AnyView_resize);
RAMView.on_motion = SGtkXDVCB(AnyView_motion);
RAMView.on_buttonpress = SGtkXDVCB(RAMView_buttonpress);
RAMView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&RAMView, 1);
sgtkx_drawing_view_sbminmax(&RAMView, 0, 255); // $1000 to $1FFF
gtk_widget_set_size_request(GTK_WIDGET(RAMView.box), 192, 108);
gtk_widget_show(GTK_WIDGET(RAMView.box));
// IO View
IOView.on_exposure = SGtkXDVCB(IOView_exposure);
IOView.on_scroll = SGtkXDVCB(AnyView_scroll);
IOView.on_resize = SGtkXDVCB(AnyView_resize);
IOView.on_motion = SGtkXDVCB(AnyView_motion);
IOView.on_buttonpress = SGtkXDVCB(IOView_buttonpress);
IOView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&IOView, 1);
sgtkx_drawing_view_sbminmax(&IOView, 0, 15); // $2100 to $21FF
gtk_widget_set_size_request(GTK_WIDGET(IOView.box), 192, 108);
gtk_widget_show(GTK_WIDGET(IOView.box));
// EEPROM View
EEPROMView.on_exposure = SGtkXDVCB(EEPROMView_exposure);
EEPROMView.on_scroll = SGtkXDVCB(AnyView_scroll);
EEPROMView.on_resize = SGtkXDVCB(AnyView_resize);
EEPROMView.on_motion = SGtkXDVCB(AnyView_motion);
EEPROMView.on_buttonpress = SGtkXDVCB(EEPROMView_buttonpress);
EEPROMView.on_enterleave = SGtkXDVCB(AnyView_enterleave);
sgtkx_drawing_view_new(&EEPROMView, 1);
sgtkx_drawing_view_sbminmax(&EEPROMView, 0, 511); // $0000 to $1FFF
gtk_widget_set_size_request(GTK_WIDGET(EEPROMView.box), 192, 108);
gtk_widget_show(GTK_WIDGET(EEPROMView.box));
// Info Messages Text
EditInfoMsgBuf = GTK_TEXT_BUFFER(gtk_text_buffer_new(NULL));
EditInfoMsg = GTK_TEXT_VIEW(gtk_text_view_new_with_buffer(EditInfoMsgBuf));
gtk_text_view_set_editable(EditInfoMsg, FALSE);
gtk_text_view_set_cursor_visible(EditInfoMsg, FALSE);
gtk_widget_show(GTK_WIDGET(EditInfoMsg));
EditInfoMsgSW = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
gtk_scrolled_window_set_policy(EditInfoMsgSW, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(EditInfoMsgSW), GTK_WIDGET(EditInfoMsg));
gtk_widget_show(GTK_WIDGET(EditInfoMsgSW));
// Info Debug Text
EditInfoDebugBuf = GTK_TEXT_BUFFER(gtk_text_buffer_new(NULL));
EditInfoDebug = GTK_TEXT_VIEW(gtk_text_view_new_with_buffer(EditInfoDebugBuf));
gtk_widget_show(GTK_WIDGET(EditInfoDebug));
EditInfoDebugSW = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
gtk_scrolled_window_set_policy(EditInfoDebugSW, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(EditInfoDebugSW), GTK_WIDGET(EditInfoDebug));
gtk_widget_show(GTK_WIDGET(EditInfoDebugSW));
// Bottom Notebook
BottomNB = GTK_NOTEBOOK(gtk_notebook_new());
gtk_table_attach(MTable, GTK_WIDGET(BottomNB), 0, 2, 2, 3, GTK_FILL | GTK_SHRINK, GTK_FILL, 2, 2);
gtk_notebook_append_page(GTK_NOTEBOOK(BottomNB), GTK_WIDGET(RAMView.box), gtk_label_new("RAM"));
gtk_notebook_append_page(GTK_NOTEBOOK(BottomNB), GTK_WIDGET(IOView.box), gtk_label_new("Hard. I/O"));
gtk_notebook_append_page(GTK_NOTEBOOK(BottomNB), GTK_WIDGET(EEPROMView.box), gtk_label_new("EEPROM"));
gtk_notebook_append_page(GTK_NOTEBOOK(BottomNB), GTK_WIDGET(EditInfoMsgSW), gtk_label_new("Messages"));
gtk_notebook_append_page(GTK_NOTEBOOK(BottomNB), GTK_WIDGET(EditInfoDebugSW), gtk_label_new("Debug output"));
gtk_widget_show(GTK_WIDGET(BottomNB));
// Status bar on the bottom
StatusFrame = GTK_FRAME(gtk_frame_new(NULL));
gtk_frame_set_label_align(StatusFrame, 1.0f, 0.5f);
gtk_box_pack_start(VBox1, GTK_WIDGET(StatusFrame), FALSE, FALSE, 0);
gtk_widget_show(GTK_WIDGET(StatusFrame));
StatusLabel = GTK_LABEL(gtk_label_new(""));
gtk_label_set_justify(StatusLabel, GTK_JUSTIFY_LEFT);
gtk_label_set_ellipsize(StatusLabel, PANGO_ELLIPSIZE_END);
gtk_container_add(GTK_CONTAINER(StatusFrame), GTK_WIDGET(StatusLabel));
gtk_widget_show(GTK_WIDGET(StatusLabel));
return 1;
}
void CPUWindow_Destroy(void)
{
int x, y, width, height;
gtk_window_deiconify(MainWindow);
gtk_window_get_position(MainWindow, &x, &y);
gtk_window_get_size(MainWindow, &width, &height);
dclc_cpuwin_winx = x;
dclc_cpuwin_winy = y;
dclc_cpuwin_winw = width;
dclc_cpuwin_winh = height;
CPUWindow_CheckDirtyROM();
}
void CPUWindow_Activate(void)
{
gtk_widget_realize(GTK_WIDGET(MainWindow));
if ((dclc_cpuwin_winx > -15) && (dclc_cpuwin_winy > -16)) {
gtk_window_move(MainWindow, dclc_cpuwin_winx, dclc_cpuwin_winy);
}
if ((dclc_cpuwin_winw > 0) && (dclc_cpuwin_winh > 0)) {
gtk_window_resize(MainWindow, dclc_cpuwin_winw, dclc_cpuwin_winh);
}
gtk_widget_show(GTK_WIDGET(MainWindow));
CPUWindow_Refresh(1);
if (dclc_followPC) ProgramView_GotoAddr(PhysicalPC(), 0);
if (dclc_followSP) StackView_GotoSP();
}
void CPUWindow_UpdateConfigs(void)
{
char tmp[PMTMPV];
GtkWidget *widg;
int i, j;
CPUWindow_InConfigs = 1;
// Refresh recent list
for (i=0; i<10; i++) {
sprintf(tmp, "/File/Recent/ROM%i", i);
if (strlen(dclc_recent[i]) > 0) {
for (j=(int)strlen(dclc_recent[i])-1; j>=0; j--) if ((dclc_recent[i][j] == '/') || (dclc_recent[i][j] == '\\')) { j++; break; }
widg = gtk_item_factory_get_item(ItemFactory, tmp);
gtk_menu_item_set_label(GTK_MENU_ITEM(widg), &dclc_recent[i][j]);
} else {
widg = gtk_item_factory_get_item(ItemFactory, tmp);
gtk_menu_item_set_label(GTK_MENU_ITEM(widg), "---");
}
}
// Apply all options
widg = gtk_item_factory_get_item(ItemFactory, "/File/Autorun/Disabled");
if (clc_autorun == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/File/Autorun/Run full speed");
if (clc_autorun == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/File/Autorun/Debug frames (Sound)");
if (clc_autorun == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/File/Autorun/Debug frames");
if (clc_autorun == 3) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Zoom/1x (96x64)");
if (clc_zoom == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Zoom/2x (192x128)");
if (clc_zoom == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Zoom/3x (288x192)");
if (clc_zoom == 3) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Zoom/4x (384x256)");
if (clc_zoom == 4) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Zoom/5x (480x320)");
if (clc_zoom == 5) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Zoom/6x (576x384)");
if (clc_zoom == 6) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Bits-Per-Pixel/16 bpp");
if (clc_bpp == 16) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Bits-Per-Pixel/32 bpp");
if (clc_bpp == 32) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Default");
if (CommandLine.palette == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Old");
if (CommandLine.palette == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Black & White");
if (CommandLine.palette == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Green Palette");
if (CommandLine.palette == 3) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Green Vector");
if (CommandLine.palette == 4) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Red Palette");
if (CommandLine.palette == 5) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Red Vector");
if (CommandLine.palette == 6) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Blue LCD");
if (CommandLine.palette == 7) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/LED Backlight");
if (CommandLine.palette == 8) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Girl Power");
if (CommandLine.palette == 9) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Blue Palette");
if (CommandLine.palette == 10) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Blue Vector");
if (CommandLine.palette == 11) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Sepia");
if (CommandLine.palette == 12) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Inverted B&W");
if (CommandLine.palette == 13) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Custom 1");
if (CommandLine.palette == 14) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Palette/Custom 2");
if (CommandLine.palette == 15) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Mode/Analog");
if (CommandLine.lcdmode == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Mode/3-Shades");
if (CommandLine.lcdmode == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Mode/2-Shades");
if (CommandLine.lcdmode == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Mode/Colors*");
if (CommandLine.lcdmode == 3) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Filter/None");
if (CommandLine.lcdfilter == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Filter/Dot-Matrix");
if (CommandLine.lcdfilter == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Filter/50% Scanline");
if (CommandLine.lcdfilter == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/Default");
if (CommandLine.lcdcontrast == 64) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/Lowest");
if (CommandLine.lcdcontrast == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/Low");
if (CommandLine.lcdcontrast == 25) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/Medium");
if (CommandLine.lcdcontrast == 50) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/High");
if (CommandLine.lcdcontrast == 75) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Contrast/Highest");
if (CommandLine.lcdcontrast == 100) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Brightness/Default");
if (CommandLine.lcdbright == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Brightness/Lighter");
if (CommandLine.lcdbright == 24) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Brightness/Light");
if (CommandLine.lcdbright == 12) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Brightness/Dark");
if (CommandLine.lcdbright == -12) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/LCD Brightness/Darker");
if (CommandLine.lcdbright == -24) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Rumble Level/None");
if (CommandLine.rumblelvl == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Rumble Level/Weak");
if (CommandLine.rumblelvl == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Rumble Level/Medium");
if (CommandLine.rumblelvl == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Rumble Level/Strong");
if (CommandLine.rumblelvl == 3) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sound/Disabled");
if (CommandLine.sound == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sound/Generated");
if (CommandLine.sound == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sound/Direct");
if (CommandLine.sound == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sound/Emulated");
if (CommandLine.sound == 3) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sound/Direct PWM");
if (CommandLine.sound == 4) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sync Cycles/ 8 (Accurancy)");
if (CommandLine.synccycles == 8) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sync Cycles/ 16");
if (CommandLine.synccycles == 16) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sync Cycles/ 32");
if (CommandLine.synccycles == 32) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Sync Cycles/ 64 (Performance)");
if (CommandLine.synccycles == 64) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Piezo Filter");
if (CommandLine.piezofilter) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Low Battery");
if (CommandLine.low_battery) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/RTC/No RTC");
if (CommandLine.updatertc == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/RTC/State time difference");
if (CommandLine.updatertc == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/RTC/RTC from Host");
if (CommandLine.updatertc == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Share EEPROM");
if (CommandLine.eeprom_share) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Multicart/Disabled");
if (CommandLine.multicart == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Multicart/Flash 512KB (AM29LV040B)");
if (CommandLine.multicart == 1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Multicart/Lupin 512KB (AM29LV040B)");
if (CommandLine.multicart == 2) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Options/Force Free BIOS");
if (CommandLine.forcefreebios) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/Physical range");
if (dclc_fullrange) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/Follow PC");
if (dclc_followPC) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/Follow SP");
if (dclc_followSP) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/PRC/Show Background");
if (dclc_PRC_bg) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/PRC/Show Sprites");
if (dclc_PRC_spr) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Debugger/PRC/Stall CPU");
if (dclc_PRC_stallcpu) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
PRCRenderBD = !dclc_PRC_bg;
PRCRenderBG = dclc_PRC_bg;
PRCRenderSpr = dclc_PRC_spr;
PRCAllowStall = dclc_PRC_stallcpu;
widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable breakpoints");
if (PMD_EnableBreakpoints) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable watchpoints");
if (PMD_EnableWatchpoints) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable exceptions");
if (PMD_EnableExceptions) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable HALT break");
if (PMD_EnableHalt) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Break/Enable STOP break");
if (PMD_EnableStop) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/Breakpoints");
if (PMD_MessageBreakpoints) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/Watchpoints");
if (PMD_MessageWatchpoints) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/Exceptions");
if (PMD_MessageExceptions) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/HALT break");
if (PMD_MessageHalt) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable messages/STOP break");
if (PMD_MessageStop) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Enable debug output");
if (dclc_debugout) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
widg = gtk_item_factory_get_item(ItemFactory, "/Messages/Auto-open debug output");
if (dclc_autodebugout) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widg), 1);
// Update external items
ExternalWindow_UpdateMenu(ItemFactory);
switch (dclc_cpuwin_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;
}
CPUWindow_InConfigs = 0;
}
void CPUWindow_ROMResized(void)
{
if (dclc_fullrange) {
sgtkx_drawing_view_sbminmax(&ProgramView, 0, PM_ROM_Size-1);
} else {
if (PM_ROM_Size <= 65535) sgtkx_drawing_view_sbminmax(&ProgramView, 0, PM_ROM_Size-1);
sgtkx_drawing_view_sbminmax(&ProgramView, 0, 65535);
}
if (!PMHD_MINLoaded()) {
MessageDialog(MainWindow, "Memory allocation error!", "Allocation error", GTK_MESSAGE_ERROR, NULL);
}
}
void CPUWindow_EmumodeChanged(void)
{
if (dclc_followPC) ProgramView_GotoAddr(PhysicalPC(), 0);
if (dclc_followSP) StackView_GotoSP();
}
void CPUWindow_Refresh(int now)
{
static int refreshcnt = 0;
if ((refreshcnt <= 0) || (now)) {
refreshcnt = dclc_cpuwin_refresh;
if (!now) {
if (!gtk_widget_get_visible(GTK_WIDGET(MainWindow)) || MainWindow_minimized) return;
}
if (emumode != EMUMODE_STOP) {
if (dclc_followPC) ProgramView_GotoAddr(PhysicalPC(), 0);
if (dclc_followSP) StackView_GotoSP();
}
sgtkx_drawing_view_refresh(&ProgramView);
sgtkx_drawing_view_refresh(&RegistersView);
sgtkx_drawing_view_refresh(&StackView);
sgtkx_drawing_view_refresh(&RAMView);
sgtkx_drawing_view_refresh(&IOView);
sgtkx_drawing_view_refresh(&EEPROMView);
} else refreshcnt--;
}
void CPUWindow_FrameRendered(void)
{
char tmp[128];
if (sdump) {
sprintf(tmp, "Recording audio: %.2f sec(s)", sdumptime);
gtk_frame_set_label(StatusFrame, tmp);
}
}