mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-09 12:36:42 +02:00
Update to v075r02 release.
byuu says: Changelog: - added ui-libsnes directory back into source archive; make archive-all includes it now - added basic HexEditor widget to phoenix/Windows
This commit is contained in:
@@ -65,6 +65,6 @@ clean:
|
|||||||
-@$(call delete,*.manifest)
|
-@$(call delete,*.manifest)
|
||||||
|
|
||||||
archive-all:
|
archive-all:
|
||||||
tar -cjf bsnes.tar.bz2 data gameboy libco nall obj out phoenix ruby snes ui ui-gameboy Makefile cc.bat clean.bat sync.sh
|
tar -cjf bsnes.tar.bz2 data gameboy libco nall obj out phoenix ruby snes ui ui-gameboy ui-libsnes Makefile cc.bat clean.bat sync.sh
|
||||||
|
|
||||||
help:;
|
help:;
|
||||||
|
@@ -2,19 +2,16 @@
|
|||||||
#define NALL_PUBLIC_CAST_HPP
|
#define NALL_PUBLIC_CAST_HPP
|
||||||
|
|
||||||
//this is a proof-of-concept-*only* C++ access-privilege elevation exploit.
|
//this is a proof-of-concept-*only* C++ access-privilege elevation exploit.
|
||||||
//it allows full access to both protected and private member variables, objects and functions
|
//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8:
|
||||||
//from the global scope, regardless of inheritance and/or friendship privileges.
|
//"access checking rules do not apply to names in explicit instantiations."
|
||||||
//the code itself is 100% legal C++, per C++98 section 14.7.2 paragraph 8:
|
|
||||||
//"Access checking rules do not apply to names in explicit instantiations."
|
|
||||||
|
|
||||||
//C++0x variadic templates are used simply to allow public_cast name to be used
|
|
||||||
//on second derived class name for simplification, however the basic idea also
|
|
||||||
//works on C++98.
|
|
||||||
|
|
||||||
//usage example:
|
//usage example:
|
||||||
|
|
||||||
//struct N { typedef void (Class::*)(); };
|
//struct N { typedef void (Class::*)(); };
|
||||||
//template class public_cast<N, &Class::Function>;
|
//template class public_cast<N, &Class::Reference>;
|
||||||
//(class.*public_cast<N>::value)();
|
//(class.*public_cast<N>::value);
|
||||||
|
|
||||||
|
//Class::Reference may be public, protected or private
|
||||||
|
//Class::Reference may be a function, object or variable
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T, typename T::type... P> struct public_cast;
|
template<typename T, typename T::type... P> struct public_cast;
|
||||||
@@ -26,13 +23,10 @@ namespace nall {
|
|||||||
template<typename T> typename T::type public_cast<T>::value;
|
template<typename T> typename T::type public_cast<T>::value;
|
||||||
|
|
||||||
template<typename T, typename T::type P> struct public_cast<T, P> : public_cast<T> {
|
template<typename T, typename T::type P> struct public_cast<T, P> : public_cast<T> {
|
||||||
struct ref_t {
|
static typename T::type value;
|
||||||
ref_t() { public_cast<T>::value = P; }
|
|
||||||
};
|
|
||||||
static ref_t ref;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename T::type P> typename public_cast<T, P>::ref_t public_cast<T, P>::ref;
|
template<typename T, typename T::type P> typename T::type public_cast<T, P>::value = public_cast<T>::value = P;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -116,7 +116,7 @@ HexEditor::HexEditor() {
|
|||||||
//internal
|
//internal
|
||||||
|
|
||||||
bool HexEditor::keyPress(unsigned scancode) {
|
bool HexEditor::keyPress(unsigned scancode) {
|
||||||
if(!onRead && !onWrite) return false;
|
if(!onRead || !onWrite) return false;
|
||||||
|
|
||||||
unsigned position = cursorPosition();
|
unsigned position = cursorPosition();
|
||||||
unsigned lineWidth = 10 + (hexEditor->columns * 3) + 1 + (hexEditor->columns) + 1;
|
unsigned lineWidth = 10 + (hexEditor->columns * 3) + 1 + (hexEditor->columns) + 1;
|
||||||
|
@@ -30,6 +30,10 @@ void EditBox::setText(const string &text) {
|
|||||||
object->locked = false;
|
object->locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditBox::setCursorPosition(unsigned position) {
|
||||||
|
Edit_SetSel(widget->window, position, position);
|
||||||
|
}
|
||||||
|
|
||||||
void EditBox::setEditable(bool editable) {
|
void EditBox::setEditable(bool editable) {
|
||||||
SendMessage(widget->window, EM_SETREADONLY, editable == false, (LPARAM)0);
|
SendMessage(widget->window, EM_SETREADONLY, editable == false, (LPARAM)0);
|
||||||
}
|
}
|
||||||
|
149
bsnes/phoenix/windows/hexeditor.cpp
Executable file
149
bsnes/phoenix/windows/hexeditor.cpp
Executable file
@@ -0,0 +1,149 @@
|
|||||||
|
static LRESULT CALLBACK HexEditor_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
|
HexEditor &self = *(HexEditor*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
|
|
||||||
|
switch(msg) {
|
||||||
|
case WM_CHAR: {
|
||||||
|
if(self.keyPress(wparam)) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.hexEditor->windowProc(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
|
||||||
|
widget->window = CreateWindowEx(
|
||||||
|
WS_EX_CLIENTEDGE,
|
||||||
|
L"EDIT", L"",
|
||||||
|
WS_CHILD | WS_TABSTOP | WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_WANTRETURN,
|
||||||
|
x, y, width, height,
|
||||||
|
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
|
||||||
|
);
|
||||||
|
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
|
||||||
|
SendMessage(widget->window, WM_SETFONT, (WPARAM)(parent.window->defaultFont ? parent.window->defaultFont : OS::os->monospaceFont), 0);
|
||||||
|
|
||||||
|
hexEditor->windowProc = (LRESULT CALLBACK (*)(HWND, UINT, LPARAM, WPARAM))GetWindowLongPtr(widget->window, GWLP_WNDPROC);
|
||||||
|
SetWindowLongPtr(widget->window, GWLP_WNDPROC, (LONG_PTR)HexEditor_WindowProc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::setSize(unsigned size) {
|
||||||
|
hexEditor->size = size;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::setOffset(unsigned offset) {
|
||||||
|
hexEditor->offset = offset;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::setColumns(unsigned columns) {
|
||||||
|
hexEditor->columns = columns;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::setRows(unsigned rows) {
|
||||||
|
hexEditor->rows = rows;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HexEditor::update() {
|
||||||
|
if(!onRead) {
|
||||||
|
SetWindowText(widget->window, L"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//modifying text resets cursor position to zero, save position so we can restore it later
|
||||||
|
unsigned cursorPosition = Edit_GetSel(widget->window);
|
||||||
|
|
||||||
|
string output;
|
||||||
|
unsigned offset = hexEditor->offset;
|
||||||
|
for(unsigned row = 0; row < hexEditor->rows; row++) {
|
||||||
|
output.append(hex<8>(offset));
|
||||||
|
output.append(" ");
|
||||||
|
|
||||||
|
string hexdata;
|
||||||
|
string ansidata = " ";
|
||||||
|
for(unsigned column = 0; column < hexEditor->columns; column++) {
|
||||||
|
if(offset < hexEditor->size) {
|
||||||
|
uint8_t data = onRead(offset++);
|
||||||
|
hexdata.append(hex<2>(data));
|
||||||
|
hexdata.append(" ");
|
||||||
|
char buffer[2] = { data >= 0x20 && data <= 0x7e ? (char)data : '.', 0 };
|
||||||
|
ansidata.append(buffer);
|
||||||
|
} else {
|
||||||
|
hexdata.append(" ");
|
||||||
|
ansidata.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.append(hexdata);
|
||||||
|
output.append(ansidata);
|
||||||
|
if(offset >= hexEditor->size) break;
|
||||||
|
if(row != hexEditor->rows - 1) output.append("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowText(widget->window, utf16_t(output));
|
||||||
|
Edit_SetSel(widget->window, LOWORD(cursorPosition), HIWORD(cursorPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HexEditor::keyPress(unsigned scancode) {
|
||||||
|
if(!onRead || !onWrite) return false;
|
||||||
|
|
||||||
|
unsigned position = LOWORD(Edit_GetSel(widget->window));
|
||||||
|
unsigned lineWidth = 10 + (hexEditor->columns * 3) + 1 + (hexEditor->columns) + 2;
|
||||||
|
unsigned cursorY = position / lineWidth;
|
||||||
|
unsigned cursorX = position % lineWidth;
|
||||||
|
|
||||||
|
//convert scancode to hex nibble
|
||||||
|
if(scancode >= '0' && scancode <= '9') scancode = scancode - '0';
|
||||||
|
else if(scancode >= 'A' && scancode <= 'F') scancode = scancode - 'A' + 10;
|
||||||
|
else if(scancode >= 'a' && scancode <= 'f') scancode = scancode - 'a' + 10;
|
||||||
|
else return false;
|
||||||
|
|
||||||
|
if(cursorX >= 10) {
|
||||||
|
//not on an offset
|
||||||
|
cursorX -= 10;
|
||||||
|
if((cursorX % 3) != 2) {
|
||||||
|
//not on a space
|
||||||
|
bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low
|
||||||
|
cursorX /= 3;
|
||||||
|
if(cursorX < hexEditor->columns) {
|
||||||
|
//not in ANSI region
|
||||||
|
unsigned offset = hexEditor->offset + (cursorY * hexEditor->columns + cursorX);
|
||||||
|
|
||||||
|
if(offset >= hexEditor->size) return false; //do not edit past end of file
|
||||||
|
uint8_t data = onRead(offset);
|
||||||
|
|
||||||
|
//write modified value
|
||||||
|
if(cursorNibble == 1) {
|
||||||
|
data = (data & 0xf0) | (scancode << 0);
|
||||||
|
} else {
|
||||||
|
data = (data & 0x0f) | (scancode << 4);
|
||||||
|
}
|
||||||
|
onWrite(offset, data);
|
||||||
|
|
||||||
|
//auto-advance cursor to next nibble/byte
|
||||||
|
position++;
|
||||||
|
if(cursorNibble && cursorX != hexEditor->columns - 1) position++;
|
||||||
|
Edit_SetSel(widget->window, position, position);
|
||||||
|
|
||||||
|
//refresh output to reflect modified data
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HexEditor::HexEditor() {
|
||||||
|
hexEditor = new HexEditor::Data;
|
||||||
|
hexEditor->windowProc = 0;
|
||||||
|
hexEditor->size = 0;
|
||||||
|
hexEditor->offset = 0;
|
||||||
|
hexEditor->columns = 16;
|
||||||
|
hexEditor->rows = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
HexEditor::~HexEditor() {
|
||||||
|
delete[] hexEditor;
|
||||||
|
}
|
@@ -53,6 +53,14 @@ struct EditBox::Data {
|
|||||||
unsigned height;
|
unsigned height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HexEditor::Data {
|
||||||
|
LRESULT CALLBACK (*windowProc)(HWND, UINT, LPARAM, WPARAM);
|
||||||
|
unsigned size;
|
||||||
|
unsigned offset;
|
||||||
|
unsigned columns;
|
||||||
|
unsigned rows;
|
||||||
|
};
|
||||||
|
|
||||||
struct HorizontalSlider::Data {
|
struct HorizontalSlider::Data {
|
||||||
unsigned position;
|
unsigned position;
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
@@ -19,6 +20,7 @@ namespace phoenix {
|
|||||||
#include "checkbox.cpp"
|
#include "checkbox.cpp"
|
||||||
#include "combobox.cpp"
|
#include "combobox.cpp"
|
||||||
#include "editbox.cpp"
|
#include "editbox.cpp"
|
||||||
|
#include "hexeditor.cpp"
|
||||||
#include "horizontalslider.cpp"
|
#include "horizontalslider.cpp"
|
||||||
#include "label.cpp"
|
#include "label.cpp"
|
||||||
#include "listbox.cpp"
|
#include "listbox.cpp"
|
||||||
@@ -45,7 +47,7 @@ void OS::initialize() {
|
|||||||
|
|
||||||
os = new OS::Data;
|
os = new OS::Data;
|
||||||
os->proportionalFont = Font_createFont("Tahoma", 8, false, false);
|
os->proportionalFont = Font_createFont("Tahoma", 8, false, false);
|
||||||
os->monospaceFont = Font_createFont("Courier New", 8, false, false);
|
os->monospaceFont = Font_createFont("Lucida Console", 8, false, false);
|
||||||
|
|
||||||
WNDCLASS wc;
|
WNDCLASS wc;
|
||||||
wc.cbClsExtra = 0;
|
wc.cbClsExtra = 0;
|
||||||
|
@@ -163,6 +163,7 @@ struct EditBox : Widget {
|
|||||||
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
|
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
|
||||||
nall::string getText();
|
nall::string getText();
|
||||||
void setText(const nall::string &text);
|
void setText(const nall::string &text);
|
||||||
|
void setCursorPosition(unsigned position);
|
||||||
void setEditable(bool editable = true);
|
void setEditable(bool editable = true);
|
||||||
void setWordWrap(bool wordWrap = true);
|
void setWordWrap(bool wordWrap = true);
|
||||||
EditBox();
|
EditBox();
|
||||||
@@ -171,6 +172,23 @@ struct EditBox : Widget {
|
|||||||
Data *editBox;
|
Data *editBox;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HexEditor : Widget {
|
||||||
|
nall::function<uint8_t (unsigned)> onRead;
|
||||||
|
nall::function<void (unsigned, uint8_t)> onWrite;
|
||||||
|
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
|
||||||
|
void setSize(unsigned size);
|
||||||
|
void setOffset(unsigned offset);
|
||||||
|
void setColumns(unsigned columns);
|
||||||
|
void setRows(unsigned rows);
|
||||||
|
void update();
|
||||||
|
HexEditor();
|
||||||
|
~HexEditor();
|
||||||
|
//private:
|
||||||
|
struct Data;
|
||||||
|
Data *hexEditor;
|
||||||
|
bool keyPress(unsigned scancode);
|
||||||
|
};
|
||||||
|
|
||||||
struct HorizontalSlider : Widget {
|
struct HorizontalSlider : Widget {
|
||||||
nall::function<void ()> onChange;
|
nall::function<void ()> onChange;
|
||||||
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, unsigned length);
|
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, unsigned length);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "075.01";
|
static const char Version[] = "075.02";
|
||||||
static const unsigned SerializerVersion = 18;
|
static const unsigned SerializerVersion = 18;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user