2013-03-15 13:11:33 +00:00
|
|
|
namespace phoenix {
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
static gint Window_close(GtkWidget* widget, GdkEvent* event, Window* window) {
|
2011-02-24 09:27:21 +00:00
|
|
|
if(window->onClose) window->onClose();
|
2013-03-15 13:11:33 +00:00
|
|
|
else window->setVisible(false);
|
|
|
|
if(window->state.modal && !window->visible()) window->setModal(false);
|
2011-02-24 09:27:21 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
static gboolean Window_expose(GtkWidget* widget, GdkEvent* event, Window* window) {
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
if(window->state.backgroundColorOverride == false) return false;
|
2013-05-02 11:25:45 +00:00
|
|
|
cairo_t* context = gdk_cairo_create(widget->window);
|
2011-08-08 12:01:09 +00:00
|
|
|
|
|
|
|
Color color = window->backgroundColor();
|
|
|
|
double red = (double)color.red / 255.0;
|
|
|
|
double green = (double)color.green / 255.0;
|
|
|
|
double blue = (double)color.blue / 255.0;
|
|
|
|
double alpha = (double)color.alpha / 255.0;
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
if(gdk_screen_is_composited(gdk_screen_get_default())
|
|
|
|
&& gdk_screen_get_rgba_colormap(gdk_screen_get_default())
|
|
|
|
) {
|
2011-08-08 12:01:09 +00:00
|
|
|
cairo_set_source_rgba(context, red, green, blue, alpha);
|
|
|
|
} else {
|
|
|
|
cairo_set_source_rgb(context, red, green, blue);
|
|
|
|
}
|
|
|
|
|
|
|
|
cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
|
|
|
|
cairo_paint(context);
|
|
|
|
cairo_destroy(context);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
static gboolean Window_configure(GtkWidget* widget, GdkEvent* event, Window* window) {
|
2011-02-24 09:27:21 +00:00
|
|
|
if(gtk_widget_get_realized(window->p.widget) == false) return false;
|
Update to higan v091r14 and ananke v00r03 releases.
byuu says:
higan changelog:
- generates title displayed in emulator window by asking the core
- core builds title solely from "information/title" ... if it's not
there, you don't get a title at all
- sub-system load menu is gone ... since there are multiple revisions of
the SGB, this never really worked well anyway
- to load an SGB, BS-X or ST cartridge, load the base cartridge first
- "File->Load Game" moved to "Load->Import Game" ... may cause a bit of
confusion to new users, but I don't like having a single-item menu,
we'll just have to explain it to new users
- browser window redone to look like ananke
- home button here goes to ~/Emulation rather than just ~ like ananke,
since this is the home of game folders
- game folder icon is now the executable icon for the Tango theme
(orange diamond), meant to represent a complete game rather than
a game file or archive
ananke changelog:
- outputs GBC games to "Game Boy Color/" instead of "Game Boy/"
- adds the file basename to "information/title"
Known issues:
- using ananke to load a GB game trips the Super Famicom SGB mode and
fails (need to make the full-path auto-detection ignore non-bootable
systems)
- need to dump and test some BS-X media before releasing
- ananke lacks BS-X Satellaview cartridge support
- v092 isn't going to let you retarget the ananke/higan game folder path
of ~/Emulation, you will have to wait for a future version if that
bothers you so greatly
[Later, after the v092 release, byuu posted this additional changelog:
- kill laevateinn
- add title()
- add bootable, remove load
- combine file, library
- combine [][][] paths
- fix SFC subtype handling XML->BML
- update file browser to use buttons
- update file browser keyboard handling
- update system XML->BML
- fix sufami turbo hashing
- remove Cartridge::manifest
]
2012-12-25 05:31:55 +00:00
|
|
|
if(window->visible() == false) return false;
|
2011-08-06 14:03:52 +00:00
|
|
|
GdkWindow *gdkWindow = gtk_widget_get_window(widget);
|
2011-02-24 09:27:21 +00:00
|
|
|
|
2011-08-06 14:03:52 +00:00
|
|
|
GdkRectangle border, client;
|
|
|
|
gdk_window_get_frame_extents(gdkWindow, &border);
|
2013-03-15 13:11:33 +00:00
|
|
|
gdk_window_get_geometry(gdkWindow, nullptr, nullptr, &client.width, &client.height, nullptr);
|
2011-08-06 14:03:52 +00:00
|
|
|
gdk_window_get_origin(gdkWindow, &client.x, &client.y);
|
|
|
|
|
2011-09-09 04:16:25 +00:00
|
|
|
if(window->state.fullScreen == false) {
|
|
|
|
//update geometry settings
|
2013-04-14 08:52:47 +00:00
|
|
|
settings->geometry.frameX = client.x - border.x;
|
|
|
|
settings->geometry.frameY = client.y - border.y;
|
|
|
|
settings->geometry.frameWidth = border.width - client.width;
|
|
|
|
settings->geometry.frameHeight = border.height - client.height;
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
if(window->state.backgroundColorOverride == false) {
|
|
|
|
GdkColor color = widget->style->bg[GTK_STATE_NORMAL];
|
2013-04-14 08:52:47 +00:00
|
|
|
settings->window.backgroundColor
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
= ((uint8_t)(color.red >> 8) << 16)
|
|
|
|
+ ((uint8_t)(color.green >> 8) << 8)
|
|
|
|
+ ((uint8_t)(color.blue >> 8) << 0);
|
|
|
|
}
|
Update to v084r01 release.
I rewrote the S-SMP processor core (implementation of the 256 opcodes),
utilizing my new 6502-like syntax. It matches what bass v05r01 uses.
Took 10 hours.
Due to being able to group the "mov reg,mem" opcodes together with
"adc/sbc/ora/and/eor/cmp" sets, the total code size was reduced from
55.7KB to 42.5KB for identical accuracy and speed.
I also dropped the trick I was using to pass register variables as
template arguments, and instead just use a switch table to pass them as
function arguments. Makes the table a lot easier to read.
Passes all of my S-SMP tests, and all of blargg's
arithmetic/cycle-timing S-SMP tests. Runs Zelda 3 great as well. Didn't
test further.
This does have the potential to cause some regressions if I've messed
anything up, and none of the above tests caught it, so as always,
testing would be appreciated.
Anyway, yeah. By writing the actual processor with this new mnemonic
set, it confirms the parallels I've made.
My guess is that Sony really did clone the 6502, but was worried about
legal implications or something and changed the mnemonics last-minute.
(Note to self: need to re-enable snes.random before v085 official.)
EDIT: oh yeah, I also commented out the ALSA snd_pcm_drain() inside
term(). Without it, there is a tiny pop when the driver is
re-initialized. But with it, the entire emulator would lock up for five
whole seconds waiting on that call to complete. I'll take the pop any
day over that.
2011-11-17 12:05:35 +00:00
|
|
|
settings->save();
|
2011-09-09 04:16:25 +00:00
|
|
|
}
|
2011-02-24 09:27:21 +00:00
|
|
|
|
2012-03-26 10:13:02 +00:00
|
|
|
Geometry geometry = {
|
|
|
|
client.x,
|
|
|
|
client.y + window->p.menuHeight(),
|
|
|
|
client.width,
|
|
|
|
client.height - window->p.menuHeight() - window->p.statusHeight()
|
|
|
|
};
|
|
|
|
|
2011-02-27 09:11:01 +00:00
|
|
|
//move
|
2012-03-26 10:13:02 +00:00
|
|
|
if(geometry.x != window->state.geometry.x || geometry.y != window->state.geometry.y) {
|
2011-08-06 14:03:52 +00:00
|
|
|
if(window->state.fullScreen == false) {
|
2012-03-26 10:13:02 +00:00
|
|
|
window->state.geometry.x = geometry.x;
|
|
|
|
window->state.geometry.y = geometry.y;
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
2011-08-06 14:03:52 +00:00
|
|
|
if(window->p.locked == false && window->onMove) window->onMove();
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2011-02-27 09:11:01 +00:00
|
|
|
//size
|
2012-03-26 10:13:02 +00:00
|
|
|
if(geometry.width != window->state.geometry.width || geometry.height != window->state.geometry.height) {
|
|
|
|
window->p.onSizePending = true;
|
2011-08-06 14:03:52 +00:00
|
|
|
}
|
2011-02-27 09:11:01 +00:00
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
static void Window_drop(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
|
2013-07-29 09:42:45 +00:00
|
|
|
GtkSelectionData* data, guint type, guint timestamp, Window* window) {
|
|
|
|
if(window->state.droppable == false) return;
|
|
|
|
lstring paths = DropPaths(data);
|
|
|
|
if(paths.empty()) return;
|
|
|
|
if(window->onDrop) window->onDrop(paths);
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
static gboolean Window_keyPress(GtkWidget* widget, GdkEventKey* event, Window* window) {
|
2012-01-15 08:29:57 +00:00
|
|
|
Keyboard::Keycode key = Keysym(event->keyval);
|
|
|
|
if(key != Keyboard::Keycode::None && window->onKeyPress) window->onKeyPress(key);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
static gboolean Window_keyRelease(GtkWidget* widget, GdkEventKey* event, Window* window) {
|
2012-01-15 08:29:57 +00:00
|
|
|
Keyboard::Keycode key = Keysym(event->keyval);
|
|
|
|
if(key != Keyboard::Keycode::None && window->onKeyRelease) window->onKeyRelease(key);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
static void Window_sizeAllocate(GtkWidget* widget, GtkAllocation* allocation, Window* window) {
|
2012-03-26 10:13:02 +00:00
|
|
|
//size-allocate sent from gtk_fixed_move(); detect if layout unchanged and return
|
|
|
|
if(allocation->width == window->p.lastAllocation.width
|
|
|
|
&& allocation->height == window->p.lastAllocation.height) return;
|
|
|
|
|
|
|
|
window->state.geometry.width = allocation->width;
|
|
|
|
window->state.geometry.height = allocation->height;
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
for(auto& layout : window->state.layout) {
|
2012-03-26 10:13:02 +00:00
|
|
|
Geometry geometry = window->geometry();
|
|
|
|
geometry.x = geometry.y = 0;
|
|
|
|
layout.setGeometry(geometry);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(window->p.onSizePending && window->p.locked == false && window->onSize) {
|
|
|
|
window->p.onSizePending = false;
|
|
|
|
window->onSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
window->p.lastAllocation = *allocation;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
static void Window_sizeRequest(GtkWidget* widget, GtkRequisition* requisition, Window* window) {
|
2012-03-26 10:13:02 +00:00
|
|
|
requisition->width = window->state.geometry.width;
|
|
|
|
requisition->height = window->state.geometry.height;
|
|
|
|
}
|
|
|
|
|
2012-08-07 13:28:00 +00:00
|
|
|
Window& pWindow::none() {
|
2013-05-02 11:25:45 +00:00
|
|
|
static Window* window = nullptr;
|
2012-08-07 13:28:00 +00:00
|
|
|
if(window == nullptr) window = new Window;
|
|
|
|
return *window;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pWindow::append(Layout& layout) {
|
2011-02-24 09:27:21 +00:00
|
|
|
Geometry geometry = this->geometry();
|
|
|
|
geometry.x = geometry.y = 0;
|
|
|
|
layout.setGeometry(geometry);
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pWindow::append(Menu& menu) {
|
2013-11-28 10:29:01 +00:00
|
|
|
if(window.state.menuFont) menu.p.setFont(window.state.menuFont);
|
|
|
|
else menu.p.setFont(Font::sans(8));
|
2011-09-05 03:48:23 +00:00
|
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(this->menu), menu.p.widget);
|
|
|
|
gtk_widget_show(menu.p.widget);
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pWindow::append(Widget& widget) {
|
2013-03-15 13:11:33 +00:00
|
|
|
if(widget.font().empty() && !window.state.widgetFont.empty()) {
|
|
|
|
widget.setFont(window.state.widgetFont);
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:32:53 +00:00
|
|
|
if(GetParentWidget(&widget)) {
|
2013-11-28 10:29:01 +00:00
|
|
|
widget.p.gtkParent = GetParentWidget(&widget)->p.container(widget);
|
|
|
|
} else {
|
|
|
|
widget.p.gtkParent = formContainer;
|
|
|
|
}
|
2011-02-24 09:27:21 +00:00
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
gtk_fixed_put(GTK_FIXED(widget.p.gtkParent), 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);
|
|
|
|
else widget.p.setFont(Font::sans(8));
|
|
|
|
widget.setVisible(widget.visible());
|
2011-08-06 14:03:52 +00:00
|
|
|
}
|
|
|
|
|
2011-02-27 09:05:10 +00:00
|
|
|
Geometry pWindow::frameMargin() {
|
2012-03-26 10:13:02 +00:00
|
|
|
if(window.state.fullScreen) return {
|
|
|
|
0,
|
|
|
|
menuHeight(),
|
|
|
|
0,
|
|
|
|
menuHeight() + statusHeight()
|
|
|
|
};
|
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
return {
|
2013-04-14 08:52:47 +00:00
|
|
|
settings->geometry.frameX,
|
|
|
|
settings->geometry.frameY + menuHeight(),
|
|
|
|
settings->geometry.frameWidth,
|
|
|
|
settings->geometry.frameHeight + menuHeight() + statusHeight()
|
2011-02-24 09:27:21 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
bool pWindow::focused() {
|
|
|
|
return gtk_window_is_active(GTK_WINDOW(widget));
|
|
|
|
}
|
|
|
|
|
|
|
|
Geometry pWindow::geometry() {
|
2014-01-05 09:59:17 +00:00
|
|
|
if(window.state.fullScreen) {
|
|
|
|
int x, y, width, height;
|
|
|
|
gtk_window_get_position(GTK_WINDOW(widget), &x, &y);
|
|
|
|
gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
|
|
|
|
return {x, y + menuHeight(), width, height - menuHeight() - statusHeight()};
|
|
|
|
}
|
2011-02-24 09:27:21 +00:00
|
|
|
return window.state.geometry;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pWindow::remove(Layout& layout) {
|
2011-09-05 03:48:23 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pWindow::remove(Menu& menu) {
|
2011-09-05 03:48:23 +00:00
|
|
|
menu.p.orphan();
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
void pWindow::remove(Widget& widget) {
|
2011-09-05 03:48:23 +00:00
|
|
|
widget.p.orphan();
|
|
|
|
}
|
|
|
|
|
2013-07-29 09:42:45 +00:00
|
|
|
void pWindow::setBackgroundColor(Color color) {
|
Update to v093r02 release.
byuu says:
Changelog:
- nall: fixed major memory leak in string class
- ruby: video shaders support #define-based settings now
- phoenix/GTK+: support > 256x256 icons for window / task bar / alt-tab
- sfc: remove random/ and config/, merge into system/
- ethos: delete higan.png (48x48), replace with higan512.png (512x512)
as new higan.png
- ethos: default gamma to 100% (no color adjustment)
- ethos: use "Video Shaders/Display Emulation/" instead of "Video
Shaders/Emulation/"
- use g++ instead of g++-4.7 (g++ -v must be >= 4.7)
- use -std=c++11 instead of -std=gnu++11
- applied a few patches from Debian upstream to make their packaging job
easier
So because colors are normalized in GLSL, I won't be able to offer video
shaders absolute color literals. We will have to perform basic color
conversion inside the core.
As such, the current plan is to create some sort of Emulator::Settings
interface. With that, I'll connect an option for color correction, which
will be on by default. For FC/SFC, that will mean gamma correction
(darker / stronger colors), and for GB/GBC/GBA, it will mean simulating
the weird brightness levels of the displays. I am undecided on whether
to use pea soup green for the GB or not. By not doing so, it'll be
easier for the display emulation shader to do it.
2013-11-09 11:45:54 +00:00
|
|
|
GdkColor gdkColor = CreateColor(color.red, color.green, color.blue);
|
2011-08-06 14:03:52 +00:00
|
|
|
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &gdkColor);
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-07-29 09:42:45 +00:00
|
|
|
void pWindow::setDroppable(bool droppable) {
|
|
|
|
gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY);
|
|
|
|
if(droppable) gtk_drag_dest_add_uri_targets(widget);
|
|
|
|
}
|
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
void pWindow::setFocused() {
|
|
|
|
gtk_window_present(GTK_WINDOW(widget));
|
|
|
|
}
|
|
|
|
|
|
|
|
void pWindow::setFullScreen(bool fullScreen) {
|
|
|
|
if(fullScreen == false) {
|
|
|
|
gtk_window_unfullscreen(GTK_WINDOW(widget));
|
|
|
|
} else {
|
|
|
|
gtk_window_fullscreen(GTK_WINDOW(widget));
|
2014-01-05 09:59:17 +00:00
|
|
|
/*unsigned monitor = gdk_screen_get_monitor_at_window(gdk_screen_get_default(), gtk_widget_get_window(widget));
|
|
|
|
GdkRectangle rectangle = {0};
|
|
|
|
gdk_screen_get_monitor_geometry(gdk_screen_get_default(), monitor, &rectangle);
|
|
|
|
gtk_window_set_decorated(GTK_WINDOW(widget), false);
|
|
|
|
gtk_window_move(GTK_WINDOW(widget), rectangle.x, rectangle.y);
|
|
|
|
gtk_window_resize(GTK_WINDOW(widget), rectangle.width, rectangle.height);
|
|
|
|
gtk_widget_set_size_request(formContainer, rectangle.width, rectangle.height);*/
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-29 09:42:45 +00:00
|
|
|
void pWindow::setGeometry(Geometry geometry) {
|
2011-02-27 09:05:10 +00:00
|
|
|
Geometry margin = frameMargin();
|
|
|
|
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
|
2011-09-09 04:16:25 +00:00
|
|
|
|
2012-03-26 10:13:02 +00:00
|
|
|
GdkGeometry geom;
|
|
|
|
geom.min_width = window.state.resizable ? 1 : window.state.geometry.width;
|
|
|
|
geom.min_height = window.state.resizable ? 1 : window.state.geometry.height;
|
|
|
|
gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE);
|
2011-09-09 04:16:25 +00:00
|
|
|
|
2012-03-26 10:13:02 +00:00
|
|
|
//gtk_window_set_policy(GTK_WINDOW(widget), true, true, false);
|
2011-02-24 09:27:21 +00:00
|
|
|
gtk_widget_set_size_request(formContainer, geometry.width, geometry.height);
|
2011-10-24 11:35:34 +00:00
|
|
|
gtk_window_resize(GTK_WINDOW(widget), geometry.width, geometry.height + menuHeight() + statusHeight());
|
2013-03-15 13:11:33 +00:00
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
for(auto& layout : window.state.layout) {
|
2013-03-15 13:11:33 +00:00
|
|
|
Geometry layoutGeometry = geometry;
|
|
|
|
layoutGeometry.x = layoutGeometry.y = 0;
|
|
|
|
layout.setGeometry(layoutGeometry);
|
|
|
|
}
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void pWindow::setMenuFont(string font) {
|
2013-05-02 11:25:45 +00:00
|
|
|
for(auto& item : window.state.menu) item.p.setFont(font);
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pWindow::setMenuVisible(bool visible) {
|
|
|
|
gtk_widget_set_visible(menu, visible);
|
|
|
|
}
|
|
|
|
|
Update to v088r11 release.
byuu says:
Changelog:
- phoenix has added Window::setModal(bool modal = true);
- file dialog is now modal. This allows emulation cores to request data
and get it immediately before continuing the loading process
- save data is hooked up for most systems, still need to handle
subsystem slot saves (Sufami Turbo, basically.)
- toggle fullscreen key binding added (Alt+Enter for now. I think F11 is
probably better though, Enter is often mapped to game start button.)
- video scaling is in (center, scale, stretch), works the same in
windowed and fullscreen mode (stretch hides resize window option), all
in the settings menu now
- enough structure to map all saved paths for the browser and to load
BS-X slotted carts, BS-X carts, single Sufami Turbo carts
Caveats / Missing:
- Super Game Boy input doesn't work yet (due to change in callback
binding)
- doesn't load secondary Sufami Turbo slot yet
- BS-X BIOS isn't show the data pack games to load for some reason (ugh,
I hate the shit out of debugging BS-X stuff ...)
- need mute audio, sync audio+video toggle, save/load state menu and
quick keys, XML mapping information window
- need cheat editor and cheat database
- need state manager
- need to sort subsystems below main systems in load menu (basically
just see if media.slot.size() > 0)
- need video shaders (will probably leave off filters for the time being
... due to that 24/30-bit thing)
- need video adjustments (contrast etc, overscan masks)
- need audio adjustments (frequency, latency, resampler, volume,
per-system frequency)
- need driver selection and input focus policy (driver crash detection
would be nice too)
- need NSS DIP switch settings (that one will be really fun)
- need to save and load window geometry settings
- need to hook up controller selection (won't be fun), create a map to
hide controllers with no inputs to reassign
2012-05-03 12:36:47 +00:00
|
|
|
void pWindow::setModal(bool modal) {
|
2013-03-15 13:11:33 +00:00
|
|
|
if(modal == true) {
|
|
|
|
gtk_window_set_modal(GTK_WINDOW(widget), true);
|
|
|
|
while(window.state.modal) {
|
|
|
|
Application::processEvents();
|
|
|
|
usleep(20 * 1000);
|
|
|
|
}
|
|
|
|
gtk_window_set_modal(GTK_WINDOW(widget), false);
|
|
|
|
}
|
Update to v088r11 release.
byuu says:
Changelog:
- phoenix has added Window::setModal(bool modal = true);
- file dialog is now modal. This allows emulation cores to request data
and get it immediately before continuing the loading process
- save data is hooked up for most systems, still need to handle
subsystem slot saves (Sufami Turbo, basically.)
- toggle fullscreen key binding added (Alt+Enter for now. I think F11 is
probably better though, Enter is often mapped to game start button.)
- video scaling is in (center, scale, stretch), works the same in
windowed and fullscreen mode (stretch hides resize window option), all
in the settings menu now
- enough structure to map all saved paths for the browser and to load
BS-X slotted carts, BS-X carts, single Sufami Turbo carts
Caveats / Missing:
- Super Game Boy input doesn't work yet (due to change in callback
binding)
- doesn't load secondary Sufami Turbo slot yet
- BS-X BIOS isn't show the data pack games to load for some reason (ugh,
I hate the shit out of debugging BS-X stuff ...)
- need mute audio, sync audio+video toggle, save/load state menu and
quick keys, XML mapping information window
- need cheat editor and cheat database
- need state manager
- need to sort subsystems below main systems in load menu (basically
just see if media.slot.size() > 0)
- need video shaders (will probably leave off filters for the time being
... due to that 24/30-bit thing)
- need video adjustments (contrast etc, overscan masks)
- need audio adjustments (frequency, latency, resampler, volume,
per-system frequency)
- need driver selection and input focus policy (driver crash detection
would be nice too)
- need NSS DIP switch settings (that one will be really fun)
- need to save and load window geometry settings
- need to hook up controller selection (won't be fun), create a map to
hide controllers with no inputs to reassign
2012-05-03 12:36:47 +00:00
|
|
|
}
|
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
void pWindow::setResizable(bool resizable) {
|
|
|
|
gtk_window_set_resizable(GTK_WINDOW(widget), resizable);
|
|
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(status), resizable);
|
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void pWindow::setStatusFont(string font) {
|
2011-09-05 03:48:23 +00:00
|
|
|
pFont::setFont(status, font);
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void pWindow::setStatusText(string text) {
|
2011-02-24 09:27:21 +00:00
|
|
|
gtk_statusbar_pop(GTK_STATUSBAR(status), 1);
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(status), 1, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pWindow::setStatusVisible(bool visible) {
|
|
|
|
gtk_widget_set_visible(status, visible);
|
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void pWindow::setTitle(string text) {
|
2011-02-24 09:27:21 +00:00
|
|
|
gtk_window_set_title(GTK_WINDOW(widget), text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pWindow::setVisible(bool visible) {
|
|
|
|
gtk_widget_set_visible(widget, visible);
|
2012-03-26 10:13:02 +00:00
|
|
|
if(visible) {
|
|
|
|
if(gtk_widget_get_visible(menu)) {
|
|
|
|
GtkAllocation allocation;
|
|
|
|
gtk_widget_get_allocation(menu, &allocation);
|
2013-04-14 08:52:47 +00:00
|
|
|
settings->geometry.menuHeight = allocation.height;
|
2012-03-26 10:13:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(gtk_widget_get_visible(status)) {
|
|
|
|
GtkAllocation allocation;
|
|
|
|
gtk_widget_get_allocation(status, &allocation);
|
2013-04-14 08:52:47 +00:00
|
|
|
settings->geometry.statusHeight = allocation.height;
|
2012-03-26 10:13:02 +00:00
|
|
|
}
|
|
|
|
}
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void pWindow::setWidgetFont(string font) {
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pWindow::constructor() {
|
2012-03-26 10:13:02 +00:00
|
|
|
lastAllocation.width = 0;
|
|
|
|
lastAllocation.height = 0;
|
|
|
|
onSizePending = false;
|
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
2011-08-08 12:01:09 +00:00
|
|
|
|
2013-01-05 09:19:04 +00:00
|
|
|
//if program was given a name, try and set the window taskbar icon from one of the pixmaps folders
|
2013-03-15 13:11:33 +00:00
|
|
|
if(applicationState.name.empty() == false) {
|
Update to v093r02 release.
byuu says:
Changelog:
- nall: fixed major memory leak in string class
- ruby: video shaders support #define-based settings now
- phoenix/GTK+: support > 256x256 icons for window / task bar / alt-tab
- sfc: remove random/ and config/, merge into system/
- ethos: delete higan.png (48x48), replace with higan512.png (512x512)
as new higan.png
- ethos: default gamma to 100% (no color adjustment)
- ethos: use "Video Shaders/Display Emulation/" instead of "Video
Shaders/Emulation/"
- use g++ instead of g++-4.7 (g++ -v must be >= 4.7)
- use -std=c++11 instead of -std=gnu++11
- applied a few patches from Debian upstream to make their packaging job
easier
So because colors are normalized in GLSL, I won't be able to offer video
shaders absolute color literals. We will have to perform basic color
conversion inside the core.
As such, the current plan is to create some sort of Emulator::Settings
interface. With that, I'll connect an option for color correction, which
will be on by default. For FC/SFC, that will mean gamma correction
(darker / stronger colors), and for GB/GBC/GBA, it will mean simulating
the weird brightness levels of the displays. I am undecided on whether
to use pea soup green for the GB or not. By not doing so, it'll be
easier for the display emulation shader to do it.
2013-11-09 11:45:54 +00:00
|
|
|
string filename = {"/usr/share/pixmaps/", applicationState.name, ".png"};
|
|
|
|
if(!file::exists(filename)) filename = {"/usr/local/share/pixmaps/", applicationState.name, ".png"};
|
|
|
|
if(file::exists(filename)) {
|
|
|
|
//maximum image size supported by GTK+ is 256x256; so we must scale larger images ourselves
|
|
|
|
nall::image icon(filename);
|
|
|
|
icon.scale(min(256u, icon.width), min(256u, icon.height), Interpolation::Hermite);
|
|
|
|
GdkPixbuf* pixbuf = CreatePixbuf(icon);
|
|
|
|
gtk_window_set_icon(GTK_WINDOW(widget), pixbuf);
|
|
|
|
g_object_unref(G_OBJECT(pixbuf));
|
2013-01-05 09:19:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
|
|
|
|
if(!colormap) colormap = gdk_screen_get_rgb_colormap(gdk_screen_get_default());
|
|
|
|
if(colormap) gtk_widget_set_colormap(widget, colormap);
|
2011-08-08 12:01:09 +00:00
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
gtk_window_set_resizable(GTK_WINDOW(widget), true);
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
#if GTK_MAJOR_VERSION >= 3
|
|
|
|
gtk_window_set_has_resize_grip(GTK_WINDOW(widget), false);
|
|
|
|
#endif
|
|
|
|
|
2011-02-24 09:27:21 +00:00
|
|
|
gtk_widget_set_app_paintable(widget, true);
|
|
|
|
gtk_widget_add_events(widget, GDK_CONFIGURE);
|
|
|
|
|
|
|
|
menuContainer = gtk_vbox_new(false, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(widget), menuContainer);
|
|
|
|
gtk_widget_show(menuContainer);
|
|
|
|
|
|
|
|
menu = gtk_menu_bar_new();
|
|
|
|
gtk_box_pack_start(GTK_BOX(menuContainer), menu, false, false, 0);
|
|
|
|
|
|
|
|
formContainer = gtk_fixed_new();
|
|
|
|
gtk_box_pack_start(GTK_BOX(menuContainer), formContainer, true, true, 0);
|
|
|
|
gtk_widget_show(formContainer);
|
|
|
|
|
|
|
|
statusContainer = gtk_event_box_new();
|
|
|
|
status = gtk_statusbar_new();
|
|
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(status), true);
|
|
|
|
gtk_container_add(GTK_CONTAINER(statusContainer), status);
|
|
|
|
gtk_box_pack_start(GTK_BOX(menuContainer), statusContainer, false, false, 0);
|
|
|
|
gtk_widget_show(statusContainer);
|
|
|
|
|
|
|
|
setTitle("");
|
2012-03-26 10:13:02 +00:00
|
|
|
setResizable(window.state.resizable);
|
2011-02-24 09:27:21 +00:00
|
|
|
setGeometry(window.state.geometry);
|
2013-11-28 10:29:01 +00:00
|
|
|
setMenuFont(Font::sans(8));
|
|
|
|
setStatusFont(Font::sans(8));
|
2011-02-24 09:27:21 +00:00
|
|
|
|
2011-08-06 14:03:52 +00:00
|
|
|
g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
|
2011-08-08 12:01:09 +00:00
|
|
|
g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window);
|
2011-08-06 14:03:52 +00:00
|
|
|
g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
|
2013-11-28 10:29:01 +00:00
|
|
|
g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(Window_drop), (gpointer)&window);
|
|
|
|
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPress), (gpointer)&window);
|
|
|
|
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPress), (gpointer)&window);
|
2012-03-26 10:13:02 +00:00
|
|
|
|
|
|
|
g_signal_connect(G_OBJECT(formContainer), "size-allocate", G_CALLBACK(Window_sizeAllocate), (gpointer)&window);
|
|
|
|
g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)&window);
|
2013-11-28 10:29:01 +00:00
|
|
|
|
|
|
|
window.state.backgroundColor = Color(
|
|
|
|
(uint8_t)(settings->window.backgroundColor >> 16),
|
|
|
|
(uint8_t)(settings->window.backgroundColor >> 8),
|
|
|
|
(uint8_t)(settings->window.backgroundColor >> 0)
|
|
|
|
);
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
|
|
|
|
2011-02-27 09:11:01 +00:00
|
|
|
unsigned pWindow::menuHeight() {
|
2013-04-14 08:52:47 +00:00
|
|
|
return window.state.menuVisible ? settings->geometry.menuHeight : 0;
|
2011-02-27 09:11:01 +00:00
|
|
|
}
|
2011-02-24 09:27:21 +00:00
|
|
|
|
2011-02-27 09:11:01 +00:00
|
|
|
unsigned pWindow::statusHeight() {
|
2013-04-14 08:52:47 +00:00
|
|
|
return window.state.statusVisible ? settings->geometry.statusHeight : 0;
|
2011-02-24 09:27:21 +00:00
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
|
|
|
|
}
|