Update to v083r03 release.

byuu says:

Lots of phoenix issues fixed, especially for Windows and GTK+.
NES emulation passes all ten ppu_vbl_nmi tests from blargg.
Sprite timing is nowhere near accurate yet (always consumes four clocks
per sprite), but oh well.
This commit is contained in:
Tim Allen 2011-10-24 22:35:34 +11:00
parent db5e2107b4
commit 6b708de893
26 changed files with 138 additions and 60 deletions

View File

@ -176,6 +176,9 @@ namespace nall {
inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u);
inline string sha256(const uint8_t *data, unsigned size);
inline char* integer(char *result, intmax_t value);
inline char* decimal(char *result, uintmax_t value);
template<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value);
template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value);
template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value);

View File

@ -3,12 +3,25 @@
namespace nall {
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline const char* to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; }
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
template<> inline const char* to_string<intmax_t> (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; }
template<> inline const char* to_string<uintmax_t> (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; }
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
template<> inline const char* to_string<bool>(bool v) { return v ? "true" : "false"; }
template<> inline const char* to_string<char>(char v) { static char temp[256]; return integer(temp, v); }
template<> inline const char* to_string<signed char> (signed char v) { static char temp[256]; return integer(temp, v); }
template<> inline const char* to_string<signed short> (signed short v) { static char temp[256]; return integer(temp, v); }
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; return integer(temp, v); }
template<> inline const char* to_string<signed long> (signed long v) { static char temp[256]; return integer(temp, v); }
template<> inline const char* to_string<signed long long>(signed long long v) { static char temp[256]; return integer(temp, v); }
template<> inline const char* to_string<unsigned char> (unsigned char v) { static char temp[256]; return decimal(temp, v); }
template<> inline const char* to_string<unsigned short> (unsigned short v) { static char temp[256]; return decimal(temp, v); }
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; return decimal(temp, v); }
template<> inline const char* to_string<unsigned long> (unsigned long v) { static char temp[256]; return decimal(temp, v); }
template<> inline const char* to_string<unsigned long long>(unsigned long long v) { static char temp[256]; return decimal(temp, v); }
template<> inline const char* to_string<float> (float v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
template<> inline const char* to_string<long double>(long double v) { static char temp[256]; snprintf(temp, 255, "%Lf", v); return temp; }
template<> inline const char* to_string<char*> (char *v) { return v; }
template<> inline const char* to_string<const char*> (const char *v) { return v; }
template<> inline const char* to_string<string> (string v) { return v; }

View File

@ -68,11 +68,47 @@ string sha256(const uint8_t *data, unsigned size) {
return result;
}
/* arithmetic <> string */
/* cast.hpp arithmetic -> string */
char* integer(char *result, intmax_t value) {
bool negative = value < 0;
if(negative) value = -value;
char buffer[64];
unsigned size = 0;
do {
unsigned n = value % 10;
buffer[size++] = '0' + n;
value /= 10;
} while(value);
buffer[size++] = negative ? '-' : '+';
for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
result[size] = 0;
return result;
}
char* decimal(char *result, uintmax_t value) {
char buffer[64];
unsigned size = 0;
do {
unsigned n = value % 10;
buffer[size++] = '0' + n;
value /= 10;
} while(value);
for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
result[size] = 0;
return result;
}
/* general-purpose arithmetic -> string */
template<unsigned length_, char padding> string integer(intmax_t value) {
bool negative = value < 0;
if(negative) value = abs(value);
if(negative) value = -value;
char buffer[64];
unsigned size = 0;
@ -99,7 +135,7 @@ template<unsigned length_, char padding> string integer(intmax_t value) {
template<unsigned length_, char padding> string linteger(intmax_t value) {
bool negative = value < 0;
if(negative) value = abs(value);
if(negative) value = -value;
char buffer[64];
unsigned size = 0;

View File

@ -22,8 +22,12 @@ void PPU::main() {
void PPU::tick() {
if(status.ly == 240 && status.lx == 340) status.nmi_hold = 1;
if(status.ly == 241 && status.lx == 0) status.nmi_flag = status.nmi_hold;
if(status.ly == 241 && status.lx == 2) if(status.nmi_enable && status.nmi_flag) cpu.set_nmi_line(1);
if(status.ly == 261 && status.lx == 0) cpu.set_nmi_line(status.nmi_flag = 0);
if(status.ly == 241 && status.lx == 2) cpu.set_nmi_line(status.nmi_enable && status.nmi_flag);
if(status.ly == 260 && status.lx == 340) status.nmi_hold = 0;
if(status.ly == 261 && status.lx == 0) status.nmi_flag = status.nmi_hold;
if(status.ly == 261 && status.lx == 2) cpu.set_nmi_line(status.nmi_enable && status.nmi_flag);
if(status.ly == 261 && status.lx == 0) status.sprite_zero_hit = 0;
clock += 4;
@ -145,7 +149,7 @@ void PPU::write(uint16 addr, uint8 data) {
status.sprite_addr = (data & 0x08) ? 0x1000 : 0x0000;
status.vram_increment = (data & 0x04) ? 32 : 1;
status.taddr = (status.taddr & 0x73ff) | ((data & 0x03) << 10);
cpu.set_nmi_line(status.nmi_enable && status.nmi_flag);
cpu.set_nmi_line(status.nmi_enable && status.nmi_hold && status.nmi_flag);
return;
case 1: //PPUMASK
status.emphasis = data >> 5;
@ -467,9 +471,9 @@ void PPU::raster_scanline() {
//336-339
chr_load(0x2000 | (status.vaddr & 0x0fff));
tick();
bool skip = (raster_enable() && status.field == 1 && status.ly == 261);
tick();
bool skip = (raster_enable() && status.field == 1 && status.ly == 261);
chr_load(0x2000 | (status.vaddr & 0x0fff));
tick();
tick();

View File

@ -13,6 +13,7 @@
#include "../reference/platform.cpp"
#endif
static bool OS_quit = false;
Window Window::None;
//Font
@ -80,6 +81,7 @@ void OS::processEvents() {
}
void OS::quit() {
OS_quit = true;
return pOS::quit();
}
@ -159,7 +161,6 @@ void Window::append(Widget &widget) {
if(state.widget.append(widget)) {
((Sizable&)widget).state.window = this;
p.append(widget);
synchronizeLayout();
}
}
@ -282,6 +283,7 @@ void Window::setTitle(const string &text) {
void Window::setVisible(bool visible) {
state.visible = visible;
synchronizeLayout();
return p.setVisible(visible);
}
@ -295,7 +297,11 @@ string Window::statusText() {
}
void Window::synchronizeLayout() {
setGeometry(geometry());
if(visible() && OS_quit == false) setGeometry(geometry());
}
bool Window::visible() {
return state.visible;
}
Window::Window():
@ -524,8 +530,6 @@ void Layout::append(Sizable &sizable) {
Widget &widget = (Widget&)sizable;
if(sizable.window()) sizable.window()->append(widget);
}
if(window()) window()->synchronizeLayout();
}
void Layout::remove(Sizable &sizable) {
@ -536,8 +540,6 @@ void Layout::remove(Sizable &sizable) {
sizable.state.layout = 0;
sizable.state.window = 0;
if(window()) window()->synchronizeLayout();
}
Layout::Layout():

View File

@ -155,6 +155,7 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
void setWidgetFont(const nall::string &font);
nall::string statusText();
void synchronizeLayout();
bool visible();
Window();
~Window();

View File

@ -1,11 +1,13 @@
void FixedLayout::append(Sizable &sizable, const Geometry &geometry) {
children.append({ &sizable, geometry });
synchronizeLayout();
if(window()) window()->synchronizeLayout();
}
void FixedLayout::append(Sizable &sizable) {
for(auto &child : children) if(child.sizable == &sizable) return;
Layout::append(sizable);
if(window()) window()->synchronizeLayout();
}
bool FixedLayout::enabled() {
@ -27,6 +29,7 @@ void FixedLayout::remove(Sizable &sizable) {
if(children[n].sizable == &sizable) {
children.remove(n);
Layout::remove(sizable);
if(window()) window()->synchronizeLayout();
break;
}
}

View File

@ -23,5 +23,5 @@ struct FixedLayout : Layout {
Sizable *sizable;
Geometry geometry;
};
nall::linear_vector<Children> children;
nall::vector<Children> children;
};

View File

@ -2,6 +2,7 @@ void HorizontalLayout::append(Sizable &sizable, unsigned width, unsigned height,
for(auto &child : children) if(child.sizable == &sizable) return;
children.append({ &sizable, width, height, spacing });
synchronizeLayout();
if(window()) window()->synchronizeLayout();
}
void HorizontalLayout::append(Sizable &sizable) {
@ -47,6 +48,7 @@ void HorizontalLayout::remove(Sizable &sizable) {
}
children.remove(n);
Layout::remove(sizable);
if(window()) window()->synchronizeLayout();
break;
}
}

View File

@ -27,5 +27,5 @@ struct HorizontalLayout : public Layout {
Sizable *sizable;
unsigned width, height, spacing;
};
nall::linear_vector<Children> children;
nall::vector<Children> children;
};

View File

@ -2,6 +2,7 @@ void VerticalLayout::append(Sizable &sizable, unsigned width, unsigned height, u
for(auto &child : children) if(child.sizable == &sizable) return;
children.append({ &sizable, width, height, spacing });
synchronizeLayout();
if(window()) window()->synchronizeLayout();
}
void VerticalLayout::append(Sizable &sizable) {
@ -47,6 +48,7 @@ void VerticalLayout::remove(Sizable &sizable) {
}
children.remove(n);
Layout::remove(sizable);
if(window()) window()->synchronizeLayout();
break;
}
}

View File

@ -27,5 +27,5 @@ struct VerticalLayout : public Layout {
Sizable *sizable;
unsigned width, height, spacing;
};
nall::linear_vector<Children> children;
nall::vector<Children> children;
};

View File

@ -21,7 +21,7 @@ void pWidget::setFont(const string &font) {
}
void pWidget::setGeometry(const Geometry &geometry) {
if(sizable.state.window) gtk_fixed_move(GTK_FIXED(sizable.state.window->p.formContainer), gtkWidget, geometry.x, geometry.y);
if(sizable.window() && sizable.window()->visible()) gtk_fixed_move(GTK_FIXED(sizable.window()->p.formContainer), gtkWidget, geometry.x, geometry.y);
unsigned width = (signed)geometry.width <= 0 ? 1U : geometry.width;
unsigned height = (signed)geometry.height <= 0 ? 1U : geometry.height;
gtk_widget_set_size_request(gtkWidget, width, height);

View File

@ -91,6 +91,7 @@ void pWindow::append(Menu &menu) {
}
void pWindow::append(Widget &widget) {
((Sizable&)widget).state.window = &window;
gtk_fixed_put(GTK_FIXED(formContainer), widget.p.gtkWidget, 0, 0);
if(widget.state.font != "") widget.p.setFont(widget.state.font);
else if(window.state.widgetFont != "") widget.p.setFont(window.state.widgetFont);
@ -154,18 +155,16 @@ void pWindow::setFullScreen(bool fullScreen) {
gtk_window_unfullscreen(GTK_WINDOW(widget));
gtk_window_set_resizable(GTK_WINDOW(widget), window.state.resizable);
gtk_window_set_decorated(GTK_WINDOW(widget), true);
for(unsigned n = 0; n < 4; n++) {
setGeometry(window.state.geometry);
gtk_widget_set_size_request(widget, -1, -1);
OS::processEvents();
usleep(2000);
}
gtk_widget_set_size_request(widget, -1, -1);
gdk_display_sync(gtk_widget_get_display(widget));
setGeometry(window.state.geometry);
} else {
gtk_window_fullscreen(GTK_WINDOW(widget));
gtk_window_set_decorated(GTK_WINDOW(widget), false);
gtk_widget_set_size_request(widget, OS::desktopGeometry().width, OS::desktopGeometry().height);
gtk_window_set_resizable(GTK_WINDOW(widget), false);
}
gdk_display_sync(gtk_widget_get_display(widget));
}
void pWindow::setGeometry(const Geometry &geometry) {
@ -181,7 +180,7 @@ void pWindow::setGeometry(const Geometry &geometry) {
gtk_window_set_policy(GTK_WINDOW(widget), true, true, false);
gtk_widget_set_size_request(formContainer, geometry.width, geometry.height);
gtk_window_resize(GTK_WINDOW(widget), geometry.width + margin.width, geometry.height + margin.height);
gtk_window_resize(GTK_WINDOW(widget), geometry.width, geometry.height + menuHeight() + statusHeight());
for(auto &layout : window.state.layout) {
Geometry geometry = this->geometry();

View File

@ -120,6 +120,14 @@ void pOS::quit() {
qtApplication = 0;
}
void pOS::syncX() {
for(unsigned n = 0; n < 8; n++) {
QApplication::syncX();
OS::processEvents();
usleep(2000);
}
}
void pOS::initialize() {
settings = new Settings;
settings->load();

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp'
**
** Created: Tue Oct 11 18:59:15 2011
** Created: Sun Oct 23 22:41:00 2011
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
**
** WARNING! All changes made in this file will be lost!

View File

@ -45,6 +45,7 @@ struct pOS : public pObject {
static bool pendingEvents();
static void processEvents();
static void quit();
static void syncX();
static void initialize();
};

View File

@ -92,10 +92,12 @@ void pWindow::setFullScreen(bool fullScreen) {
void pWindow::setGeometry(const Geometry &geometry_) {
locked = true;
OS::processEvents();
QApplication::syncX();
Geometry geometry = geometry_, margin = frameMargin();
setResizable(window.state.resizable);
qtWindow->move(geometry.x, geometry.y);
qtWindow->move(geometry.x - frameMargin().x, geometry.y - frameMargin().y);
//qtWindow->adjustSize() fails if larger than 2/3rds screen size
qtWindow->resize(qtWindow->sizeHint());
qtWindow->setMinimumSize(1, 1);
@ -200,12 +202,7 @@ void pWindow::destructor() {
}
void pWindow::updateFrameGeometry() {
if(window.state.fullScreen == false) for(unsigned n = 0; n < 100; n++) {
if(qtWindow->geometry().x() > qtWindow->frameGeometry().x()) break;
usleep(100);
QApplication::processEvents();
}
pOS::syncX();
QRect border = qtWindow->frameGeometry();
QRect client = qtWindow->geometry();
@ -215,12 +212,12 @@ void pWindow::updateFrameGeometry() {
settings->frameGeometryHeight = border.height() - client.height();
if(window.state.menuVisible) {
for(unsigned n = 0; n < 10; n++) { usleep(100); QApplication::processEvents(); }
pOS::syncX();
settings->menuGeometryHeight = qtMenu->height();
}
if(window.state.statusVisible) {
for(unsigned n = 0; n < 10; n++) { usleep(100); QApplication::processEvents(); }
pOS::syncX();
settings->statusGeometryHeight = qtStatus->height();
}
}

View File

@ -53,7 +53,7 @@ static string pOS_fileDialog(bool save, Window &parent, const string &path, cons
for(auto &filterItem : filter) {
lstring part;
part.split("(", filterItem);
if(part.size() != 2) { print("--", filterItem, "\n"); continue; }
if(part.size() != 2) continue;
part[1].rtrim<1>(")");
part[1].replace(" ", "");
part[1].transform(",", ";");
@ -397,17 +397,16 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
if(listView.p.locked == false && listView.onTick) listView.onTick(nmlistview->iItem);
} else if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
listView.p.lostFocus = true;
} else {
if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) {
listView.state.selected = true;
listView.state.selection = listView.selection();
if(listView.p.locked == false && listView.onChange) listView.onChange();
} else if(listView.p.lostFocus == false && listView.selected() == false) {
listView.state.selected = true;
listView.state.selection = listView.selection();
if(listView.p.locked == false && listView.onChange) listView.onChange();
}
} else if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) {
listView.p.lostFocus = false;
listView.state.selected = true;
listView.state.selection = listView.selection();
if(listView.p.locked == false && listView.onChange) listView.onChange();
} else if(listView.p.lostFocus == false && listView.selected() == false) {
listView.p.lostFocus = false;
listView.state.selected = false;
listView.state.selection = 0;
if(listView.p.locked == false && listView.onChange) listView.onChange();
}
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
if(listView.onActivate) listView.onActivate();

View File

@ -90,6 +90,7 @@ void pListView::setHeaderVisible(bool visible) {
void pListView::setSelected(bool selected) {
locked = true;
lostFocus = false;
if(selected == false) {
ListView_SetItemState(hwnd, -1, 0, LVIS_FOCUSED | LVIS_SELECTED);
} else {
@ -100,6 +101,7 @@ void pListView::setSelected(bool selected) {
void pListView::setSelection(unsigned row) {
locked = true;
lostFocus = false;
ListView_SetItemState(hwnd, row, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
locked = false;
}

View File

@ -27,7 +27,7 @@ void Application::run() {
}
Application::Application(int argc, char **argv) {
title = "bsnes v083.02";
title = "bsnes v083.03";
application = this;
quit = false;

View File

@ -40,9 +40,9 @@ SettingsWindow::SettingsWindow() {
append(*inputSettings);
append(*advancedSettings);
panelList.onChange = [&] { setPanel(panelList.selection()); };
setPanel(2);
panelList.onChange = { &SettingsWindow::panelChanged, this };
panelList.setSelection(2);
panelChanged();
}
SettingsWindow::~SettingsWindow() {
@ -52,15 +52,13 @@ SettingsWindow::~SettingsWindow() {
delete videoSettings;
}
void SettingsWindow::setPanel(unsigned n) {
panelList.setSelection(n);
void SettingsWindow::panelChanged() {
videoSettings->setVisible(false);
audioSettings->setVisible(false);
inputSettings->setVisible(false);
advancedSettings->setVisible(false);
switch(n) {
if(panelList.selected()) switch(panelList.selection()) {
case 0: return videoSettings->setVisible();
case 1: return audioSettings->setVisible();
case 2: return inputSettings->setVisible();

View File

@ -15,7 +15,7 @@ struct SettingsWindow : Window {
HorizontalLayout layout;
ListView panelList;
void setPanel(unsigned);
void panelChanged();
SettingsWindow();
~SettingsWindow();

View File

@ -58,6 +58,12 @@ void StateManager::refresh() {
stateList.autoSizeColumns();
}
void StateManager::reset() {
for(unsigned n = 0; n < 32; n++) slot[n] = serializer();
synchronize();
refresh();
}
bool StateManager::load(const string &filename, unsigned revision) {
for(unsigned n = 0; n < 32; n++) slot[n] = serializer();
synchronize();

View File

@ -13,6 +13,7 @@ struct StateManager : Window {
void synchronize();
void refresh();
void reset();
bool load(const string &filename, unsigned revision);
bool save(const string &filename, unsigned revision);

View File

@ -13,6 +13,7 @@ void Utility::setMode(Interface::Mode mode) {
mainWindow->setTitle(application->title);
mainWindow->setStatusText("No cartridge loaded");
cheatEditor->reset();
stateManager->reset();
}
else if(mode == Interface::Mode::NES) {