mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
eecc085e42
commit
012cdd4b14
|
@ -65,6 +65,6 @@ clean:
|
|||
-@$(call delete,*.manifest)
|
||||
|
||||
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:;
|
||||
|
|
|
@ -2,19 +2,16 @@
|
|||
#define NALL_PUBLIC_CAST_HPP
|
||||
|
||||
//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
|
||||
//from the global scope, regardless of inheritance and/or friendship privileges.
|
||||
//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.
|
||||
|
||||
//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8:
|
||||
//"access checking rules do not apply to names in explicit instantiations."
|
||||
//usage example:
|
||||
|
||||
//struct N { typedef void (Class::*)(); };
|
||||
//template class public_cast<N, &Class::Function>;
|
||||
//(class.*public_cast<N>::value)();
|
||||
//template class public_cast<N, &Class::Reference>;
|
||||
//(class.*public_cast<N>::value);
|
||||
|
||||
//Class::Reference may be public, protected or private
|
||||
//Class::Reference may be a function, object or variable
|
||||
|
||||
namespace nall {
|
||||
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 P> struct public_cast<T, P> : public_cast<T> {
|
||||
struct ref_t {
|
||||
ref_t() { public_cast<T>::value = P; }
|
||||
};
|
||||
static ref_t ref;
|
||||
static typename T::type value;
|
||||
};
|
||||
|
||||
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
|
||||
|
|
|
@ -116,7 +116,7 @@ HexEditor::HexEditor() {
|
|||
//internal
|
||||
|
||||
bool HexEditor::keyPress(unsigned scancode) {
|
||||
if(!onRead && !onWrite) return false;
|
||||
if(!onRead || !onWrite) return false;
|
||||
|
||||
unsigned position = cursorPosition();
|
||||
unsigned lineWidth = 10 + (hexEditor->columns * 3) + 1 + (hexEditor->columns) + 1;
|
||||
|
|
|
@ -30,6 +30,10 @@ void EditBox::setText(const string &text) {
|
|||
object->locked = false;
|
||||
}
|
||||
|
||||
void EditBox::setCursorPosition(unsigned position) {
|
||||
Edit_SetSel(widget->window, position, position);
|
||||
}
|
||||
|
||||
void EditBox::setEditable(bool editable) {
|
||||
SendMessage(widget->window, EM_SETREADONLY, editable == false, (LPARAM)0);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
struct HexEditor::Data {
|
||||
LRESULT CALLBACK (*windowProc)(HWND, UINT, LPARAM, WPARAM);
|
||||
unsigned size;
|
||||
unsigned offset;
|
||||
unsigned columns;
|
||||
unsigned rows;
|
||||
};
|
||||
|
||||
struct HorizontalSlider::Data {
|
||||
unsigned position;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <commctrl.h>
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
|
@ -19,6 +20,7 @@ namespace phoenix {
|
|||
#include "checkbox.cpp"
|
||||
#include "combobox.cpp"
|
||||
#include "editbox.cpp"
|
||||
#include "hexeditor.cpp"
|
||||
#include "horizontalslider.cpp"
|
||||
#include "label.cpp"
|
||||
#include "listbox.cpp"
|
||||
|
@ -45,7 +47,7 @@ void OS::initialize() {
|
|||
|
||||
os = new OS::Data;
|
||||
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;
|
||||
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 = "");
|
||||
nall::string getText();
|
||||
void setText(const nall::string &text);
|
||||
void setCursorPosition(unsigned position);
|
||||
void setEditable(bool editable = true);
|
||||
void setWordWrap(bool wordWrap = true);
|
||||
EditBox();
|
||||
|
@ -171,6 +172,23 @@ struct EditBox : Widget {
|
|||
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 {
|
||||
nall::function<void ()> onChange;
|
||||
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, unsigned length);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "075.01";
|
||||
static const char Version[] = "075.02";
|
||||
static const unsigned SerializerVersion = 18;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue