Update to v072r06 release.

(there was no r05 release posted to the WIP thread)

byuu says:

Updated libsnes to use new file and function names.
Also added EditBox::setCursorPosition for GTK+ and Qt, only used by the
debugger so far so that when text is added, it auto-scrolls to the
bottom.
This commit is contained in:
Tim Allen 2010-11-01 22:26:20 +11:00
parent edac93b800
commit 7e8958b102
16 changed files with 217 additions and 28 deletions

View File

@ -47,3 +47,12 @@ void EditBox::setText(const string &text) {
gtk_text_buffer_set_text(object->textBuffer, text, -1);
object->locked = false;
}
void EditBox::setCursorPosition(unsigned position) {
GtkTextMark *mark = gtk_text_buffer_get_mark(object->textBuffer, "insert");
GtkTextIter iter;
gtk_text_buffer_get_end_iter(object->textBuffer, &iter);
gtk_text_iter_set_offset(&iter, min(position, gtk_text_iter_get_offset(&iter)));
gtk_text_buffer_place_cursor(object->textBuffer, &iter);
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(object->subWidget), mark);
}

View File

@ -157,6 +157,7 @@ struct EditBox : Widget {
void setWordWrap(bool wordWrap = true);
nall::string text();
void setText(const nall::string &text);
void setCursorPosition(unsigned position);
};
struct HexEditor : Widget {
@ -173,6 +174,9 @@ struct HexEditor : Widget {
struct Data;
Data *hexEditor;
bool keyPress(unsigned scancode);
void scroll(unsigned position);
void setScroll();
void updateScroll();
unsigned cursorPosition();
void setCursorPosition(unsigned position);
};

View File

@ -2,41 +2,71 @@ static bool HexEditor_keyPress(GtkWidget *widget, GdkEventKey *event, HexEditor
return self->keyPress(event->keyval);
}
static bool HexEditor_scroll(GtkRange *range, GtkScrollType scroll, gdouble value, HexEditor *self) {
self->scroll((unsigned)value);
return false;
}
void HexEditor::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
object->widget = gtk_scrolled_window_new(0, 0);
widget->parent = &parent;
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN);
hexEditor->size = 0;
hexEditor->offset = 0;
hexEditor->columns = 16;
hexEditor->rows = 16;
object->widget = gtk_hbox_new(false, 0);
gtk_widget_set_size_request(object->widget, width, height);
object->subWidget = gtk_text_view_new();
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(object->subWidget), GTK_WRAP_NONE);
gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget);
object->textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(object->subWidget));
hexEditor->container = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(hexEditor->container), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(hexEditor->container), GTK_SHADOW_ETCHED_IN);
hexEditor->widget = gtk_text_view_new();
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(hexEditor->widget), GTK_WRAP_NONE);
gtk_container_add(GTK_CONTAINER(hexEditor->container), hexEditor->widget);
g_signal_connect(G_OBJECT(hexEditor->widget), "key-press-event", G_CALLBACK(HexEditor_keyPress), (gpointer)this);
hexEditor->scroll = gtk_vscrollbar_new((GtkAdjustment*)0);
gtk_range_set_range(GTK_RANGE(hexEditor->scroll), 0, 256);
gtk_range_set_increments(GTK_RANGE(hexEditor->scroll), 1, 16);
gtk_widget_set_sensitive(hexEditor->scroll, false);
g_signal_connect(G_OBJECT(hexEditor->scroll), "change-value", G_CALLBACK(HexEditor_scroll), (gpointer)this);
gtk_box_pack_start(GTK_BOX(object->widget), hexEditor->container, true, true, 0);
gtk_box_pack_start(GTK_BOX(object->widget), hexEditor->scroll, false, false, 1);
object->textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(hexEditor->widget));
hexEditor->cursor = gtk_text_buffer_get_mark(object->textBuffer, "insert");
gtk_text_view_set_editable(GTK_TEXT_VIEW(object->subWidget), false);
g_signal_connect(G_OBJECT(object->subWidget), "key-press-event", G_CALLBACK(HexEditor_keyPress), (gpointer)this);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont);
gtk_fixed_put(GTK_FIXED(parent.object->formContainer), object->widget, x, y);
gtk_widget_show(object->subWidget);
if(parent.window->defaultFont) setFont(*parent.window->defaultFont);
gtk_widget_show(hexEditor->scroll);
gtk_widget_show(hexEditor->widget);
gtk_widget_show(hexEditor->container);
gtk_widget_show(object->widget);
}
void HexEditor::setSize(unsigned size) {
hexEditor->size = size;
setScroll();
}
void HexEditor::setOffset(unsigned offset) {
hexEditor->offset = offset;
setScroll();
updateScroll();
}
void HexEditor::setColumns(unsigned columns) {
hexEditor->columns = columns;
setScroll();
}
void HexEditor::setRows(unsigned rows) {
hexEditor->rows = rows;
setScroll();
}
void HexEditor::update() {
@ -189,7 +219,30 @@ bool HexEditor::keyPress(unsigned scancode) {
}
}
return false;
return true;
}
void HexEditor::scroll(unsigned position) {
unsigned rows = hexEditor->size / hexEditor->columns;
if(position >= rows) position = rows - 1;
setOffset(position * hexEditor->columns);
update();
}
void HexEditor::setScroll() {
unsigned rows = hexEditor->size / hexEditor->columns;
if(rows) rows--;
if(rows) {
gtk_range_set_range(GTK_RANGE(hexEditor->scroll), 0, rows);
gtk_widget_set_sensitive(hexEditor->scroll, true);
} else {
gtk_widget_set_sensitive(hexEditor->scroll, false);
}
}
void HexEditor::updateScroll() {
unsigned row = hexEditor->offset / hexEditor->columns;
gtk_range_set_value(GTK_RANGE(hexEditor->scroll), row);
}
unsigned HexEditor::cursorPosition() {

View File

@ -36,6 +36,10 @@ struct Canvas::Data {
};
struct HexEditor::Data {
GtkWidget *container;
GtkWidget *widget;
GtkWidget *scroll;
GtkTextMark *cursor;
unsigned size;
unsigned offset;

View File

@ -23,6 +23,13 @@ void EditBox::setText(const string &text) {
editBox->setPlainText(QString::fromUtf8(text));
}
void EditBox::setCursorPosition(unsigned position) {
QTextCursor cursor = editBox->textCursor();
unsigned lastchar = strlen(editBox->toPlainText().toUtf8().constData());
cursor.setPosition(min(position, lastchar));
editBox->setTextCursor(cursor);
}
EditBox::EditBox() {
editBox = new EditBox::Data(*this);
widget->widget = editBox;

View File

@ -199,6 +199,7 @@ struct EditBox : Widget {
void setWordWrap(bool wordWrap = true);
nall::string text();
void setText(const nall::string &text);
void setCursorPosition(unsigned position);
EditBox();
//private:
struct Data;

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'qt.moc.hpp'
**
** Created: Mon Oct 11 13:03:04 2010
** Created: Mon Nov 1 06:26:59 2010
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2)
**
** WARNING! All changes made in this file will be lost!

View File

@ -1,7 +1,7 @@
#include "libsnes.hpp"
#include <snes.hpp>
#include <nall/snes/info.hpp>
#include <nall/snes/cartridge.hpp>
using namespace nall;
struct Interface : public SNES::Interface {
@ -120,7 +120,7 @@ bool snes_load_cartridge_normal(
) {
snes_cheat_reset();
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : snes_information(rom_data, rom_size).xml_memory_map;
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { xmlrom });
SNES::system.power();
return true;
@ -132,9 +132,9 @@ bool snes_load_cartridge_bsx_slotted(
) {
snes_cheat_reset();
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : snes_information(rom_data, rom_size).xml_memory_map;
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
if(bsx_data) SNES::memory::bsxflash.copy(bsx_data, bsx_size);
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : snes_information(bsx_data, bsx_size).xml_memory_map;
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SNESCartridge(bsx_data, bsx_size).xmlMemoryMap;
SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, { xmlrom, xmlbsx });
SNES::system.power();
return true;
@ -146,9 +146,9 @@ bool snes_load_cartridge_bsx(
) {
snes_cheat_reset();
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : snes_information(rom_data, rom_size).xml_memory_map;
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
if(bsx_data) SNES::memory::bsxflash.copy(bsx_data, bsx_size);
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : snes_information(bsx_data, bsx_size).xml_memory_map;
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SNESCartridge(bsx_data, bsx_size).xmlMemoryMap;
SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, { xmlrom, xmlbsx });
SNES::system.power();
return true;
@ -161,11 +161,11 @@ bool snes_load_cartridge_sufami_turbo(
) {
snes_cheat_reset();
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : snes_information(rom_data, rom_size).xml_memory_map;
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
if(sta_data) SNES::memory::stArom.copy(sta_data, sta_size);
string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : snes_information(sta_data, sta_size).xml_memory_map;
string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : SNESCartridge(sta_data, sta_size).xmlMemoryMap;
if(stb_data) SNES::memory::stBrom.copy(stb_data, stb_size);
string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : snes_information(stb_data, stb_size).xml_memory_map;
string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : SNESCartridge(stb_data, stb_size).xmlMemoryMap;
SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, { xmlrom, xmlsta, xmlstb });
SNES::system.power();
return true;
@ -177,9 +177,9 @@ bool snes_load_cartridge_super_game_boy(
) {
snes_cheat_reset();
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : snes_information(rom_data, rom_size).xml_memory_map;
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
if(dmg_data) SNES::memory::gbrom.copy(dmg_data, dmg_size);
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : snes_information(dmg_data, dmg_size).xml_memory_map;
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : SNESCartridge(dmg_data, dmg_size).xmlMemoryMap;
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { xmlrom, xmldmg });
SNES::system.power();
return true;

View File

@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "072.04";
static const char Version[] = "072.06";
static const unsigned SerializerVersion = 14;
}
}

View File

@ -25,6 +25,22 @@ void Console::create() {
};
}
void Console::eventBreakpoint() {
if(traceToConsole.checked() == false) return;
unsigned n = SNES::debugger.breakpoint_hit;
string text = { "Breakpoint ", n + 1, " hit." };
buffer.append(string(buffer == "" ? "" : "\n", text));
output.setText(buffer);
output.setCursorPosition(~0);
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::CPUBus) {
eventTraceCPU();
} else if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::APURAM) {
eventTraceSMP();
}
}
void Console::eventTraceCPU() {
if(traceCPU.checked() == false) return;
if(traceToConsole.checked() == false) return;
@ -33,6 +49,7 @@ void Console::eventTraceCPU() {
SNES::cpu.disassemble_opcode(text, SNES::cpu.regs.pc);
buffer.append(string(buffer == "" ? "" : "\n", text));
output.setText(buffer);
output.setCursorPosition(~0);
}
void Console::eventTraceSMP() {
@ -43,4 +60,5 @@ void Console::eventTraceSMP() {
SNES::smp.disassemble_opcode(text, SNES::smp.regs.pc);
buffer.append(string(buffer == "" ? "" : "\n", text));
output.setText(buffer);
output.setCursorPosition(~0);
}

View File

@ -8,6 +8,7 @@ struct Console : TopLevelWindow {
string buffer;
void create();
void eventBreakpoint();
void eventTraceCPU();
void eventTraceSMP();
};

View File

@ -7,6 +7,7 @@
#include "console.cpp"
#include "cpu/debugger.cpp"
#include "smp/debugger.cpp"
#include "tools/breakpoint-editor.cpp"
#include "tools/memory-editor.cpp"
Debugger debugger;
@ -14,6 +15,7 @@ void Debugger::create() {
console.create();
cpuDebugger.create();
smpDebugger.create();
breakpointEditor.create();
memoryEditor.create();
Window::create(0, 0, 256, 256, "Debugger");
@ -24,12 +26,14 @@ void Debugger::create() {
showConsole.create(*this, x, y, 240, Style::CheckBoxHeight, "Console"); y += Style::CheckBoxHeight;
showCPUDebugger.create(*this, x, y, 240, Style::CheckBoxHeight, "CPU debugger"); y += Style::CheckBoxHeight;
showSMPDebugger.create(*this, x, y, 240, Style::CheckBoxHeight, "SMP debugger"); y += Style::CheckBoxHeight;
showBreakpointEditor.create(*this, x, y, 240, Style::CheckBoxHeight, "Breakpoint editor"); y += Style::CheckBoxHeight;
showMemoryEditor.create(*this, x, y, 240, Style::CheckBoxHeight, "Memory editor"); y += Style::CheckBoxHeight;
//windows shown by default
showConsole.setChecked();
showCPUDebugger.setChecked();
showSMPDebugger.setChecked();
showBreakpointEditor.setChecked();
setGeometry(0, 0, 250, y);
@ -49,6 +53,10 @@ void Debugger::create() {
smpDebugger.setVisible(debugger.showSMPDebugger.checked());
};
showBreakpointEditor.onTick = []() {
breakpointEditor.setVisible(debugger.showBreakpointEditor.checked());
};
showMemoryEditor.onTick = []() {
memoryEditor.setVisible(debugger.showMemoryEditor.checked());
};
@ -64,6 +72,7 @@ void Debugger::setVisible(bool visible) {
console.setVisible(showConsole.checked() & visible);
cpuDebugger.setVisible(showCPUDebugger.checked() & visible);
smpDebugger.setVisible(showSMPDebugger.checked() & visible);
breakpointEditor.setVisible(showBreakpointEditor.checked() & visible);
memoryEditor.setVisible(showMemoryEditor.checked() & visible);
}
@ -84,6 +93,14 @@ void Debugger::run() {
SNES::system.run();
if(debugMode == DebugMode::WaitForBreakpoint) {
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::BreakpointHit) {
debugMode = DebugMode::None;
console.eventBreakpoint();
breakpointEditor.eventBreakpoint();
}
}
if(debugMode == DebugMode::StepIntoCPU) {
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::CPUStep) {
debugMode = DebugMode::None;

View File

@ -1,11 +1,13 @@
#include "console.hpp"
#include "cpu/debugger.hpp"
#include "smp/debugger.hpp"
#include "tools/breakpoint-editor.hpp"
#include "tools/memory-editor.hpp"
struct Debugger : TopLevelWindow {
enum class DebugMode : unsigned {
None,
WaitForBreakpoint,
StepIntoCPU,
StepIntoSMP,
} debugMode;
@ -14,6 +16,7 @@ struct Debugger : TopLevelWindow {
CheckBox showConsole;
CheckBox showCPUDebugger;
CheckBox showSMPDebugger;
CheckBox showBreakpointEditor;
CheckBox showMemoryEditor;
void create();

View File

@ -0,0 +1,57 @@
BreakpointEditor breakpointEditor;
void BreakpointEditor::create() {
Window::create(0, 0, 256, 256, "Breakpoint Editor");
application.addWindow(this, "Debugger.BreakpointEditor", "192,192");
unsigned x = 5, y = 5;
runToBreakpoint.create(*this, x, y, 295, Style::CheckBoxHeight, "Run To Breakpoint");
y += Style::CheckBoxHeight + 5;
for(unsigned n = 0; n < Breakpoints; n++) {
enableBox[n].create(*this, x, y, 35, Style::EditBoxHeight, { n + 1 });
addressBox[n].create(*this, x + 35, y, 60, Style::EditBoxHeight);
valueBox[n].create(*this, x + 100, y, 30, Style::EditBoxHeight);
typeBox[n].create(*this, x + 135, y, 80, Style::EditBoxHeight, "Exec\nRead\nWrite");
sourceBox[n].create(*this, x + 220, y, 80, Style::EditBoxHeight, "CPU\nAPU\nVRAM\nOAM\nCGRAM");
y += Style::EditBoxHeight + 5;
enableBox[n].onTick = [n]() { breakpointEditor.toggleBreakpoint(n); };
}
setGeometry(0, 0, 305, y);
runToBreakpoint.onTick = []() {
if(breakpointEditor.runToBreakpoint.checked()) {
debugger.debugMode = Debugger::DebugMode::WaitForBreakpoint;
} else {
debugger.debugMode = Debugger::DebugMode::None;
}
};
}
void BreakpointEditor::toggleBreakpoint(unsigned n) {
bool enabled = enableBox[n].checked();
if(enabled == false) {
SNES::debugger.breakpoint[n].enabled = false;
} else {
SNES::debugger.breakpoint[n].enabled = true;
SNES::debugger.breakpoint[n].addr = strhex(addressBox[n].text());
SNES::debugger.breakpoint[n].data = strhex(valueBox[n].text());
if(valueBox[n].text() == "") SNES::debugger.breakpoint[n].data = -1; //break on any value
SNES::debugger.breakpoint[n].mode = (SNES::Debugger::Breakpoint::Mode)typeBox[n].selection();
SNES::debugger.breakpoint[n].source = (SNES::Debugger::Breakpoint::Source)sourceBox[n].selection();
SNES::debugger.breakpoint[n].counter = 0;
}
//do not allow values to be edited while breakpoint is enabled
addressBox[n].setEnabled(!enabled);
valueBox[n].setEnabled(!enabled);
typeBox[n].setEnabled(!enabled);
sourceBox[n].setEnabled(!enabled);
}
void BreakpointEditor::eventBreakpoint() {
runToBreakpoint.setChecked(false);
}

View File

@ -0,0 +1,15 @@
struct BreakpointEditor : TopLevelWindow {
enum : unsigned { Breakpoints = SNES::Debugger::Breakpoints };
CheckBox runToBreakpoint;
CheckBox enableBox[Breakpoints];
TextBox addressBox[Breakpoints];
TextBox valueBox[Breakpoints];
ComboBox typeBox[Breakpoints];
ComboBox sourceBox[Breakpoints];
void create();
void toggleBreakpoint(unsigned breakpoint);
void eventBreakpoint();
};
extern BreakpointEditor breakpointEditor;

View File

@ -5,7 +5,7 @@ void MemoryEditor::create() {
application.addWindow(this, "Debugger.MemoryEditor", "192,192");
unsigned x = 5, y = 5;
editor.create(*this, x, y, 455, 210); x += 455 + 5;
editor.create(*this, x, y, 470, 210); x += 470 + 5;
editor.setFont(application.monospaceFont);
editor.setColumns(16);
editor.setRows(16);
@ -21,7 +21,7 @@ void MemoryEditor::create() {
refreshButton.create(*this, x, y, 80, Style::ButtonHeight, "Refresh"); y += Style::ButtonHeight;
setGeometry(0, 0, 545, 220);
setGeometry(0, 0, 560, 220);
onClose = []() {
debugger.showMemoryEditor.setChecked(false);