mirror of
https://github.com/visualboyadvance-m/visualboyadvance-m
synced 2025-10-06 16:12:51 +02:00
Compare commits
6 Commits
sfml-downg
...
video-refa
Author | SHA1 | Date | |
---|---|---|---|
|
c960fbc117 | ||
|
06313d9df1 | ||
|
ccd9847672 | ||
|
24cc810eb6 | ||
|
d5d01a8b68 | ||
|
2f5219ee8f |
@@ -25,8 +25,9 @@
|
||||
|
||||
extern int emulating;
|
||||
|
||||
// Hold up to 300 ms of data in the ring buffer
|
||||
const double SoundSDL::buftime = 0.300;
|
||||
// Hold up to 50 ms of data in the ring buffer
|
||||
// 3 frames
|
||||
const double SoundSDL::buftime = 0.050;
|
||||
|
||||
SoundSDL::SoundSDL():
|
||||
samples_buf(0),
|
||||
|
@@ -364,6 +364,10 @@ mirroringEnabled=1
|
||||
saveType=1
|
||||
mirroringEnabled=1
|
||||
|
||||
# Higurashi no Nakukoroni (Japan)
|
||||
[HGRS]
|
||||
saveType=2
|
||||
|
||||
# Koro Koro Puzzle - Happy Panechu! (Japan)
|
||||
[KHPJ]
|
||||
saveType=4
|
||||
@@ -494,4 +498,4 @@ flashSize=131072
|
||||
|
||||
# Pokemon - Edicion Rojo Fuego (Spain)
|
||||
[BPRS]
|
||||
flashSize=131072
|
||||
flashSize=131072
|
||||
|
@@ -22,6 +22,12 @@ include(VbamFunctions)
|
||||
|
||||
set(VBAM_LIBS ${VBAMCORE_LIBS})
|
||||
|
||||
option(ENABLE_THREAD_MAINLOOP "Enable separate thread for emulator main loop for WX port" OFF)
|
||||
|
||||
if(NOT ENABLE_THREAD_MAINLOOP)
|
||||
add_definitions(-DNO_THREAD_MAINLOOP)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# not yet implemented
|
||||
option(ENABLE_DIRECT3D "Enable Direct3D rendering for the wxWidgets port" OFF)
|
||||
|
@@ -2297,6 +2297,10 @@ EVT_HANDLER(GeneralConfigure, "General options...")
|
||||
if (ShowModal(dlg) == wxID_OK)
|
||||
update_opts();
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
|
||||
if (panel->game_type() != IMAGE_UNKNOWN)
|
||||
soundSetThrottle(throttle);
|
||||
|
||||
@@ -2598,6 +2602,10 @@ EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
|
||||
if (ShowModal(dlg) != wxID_OK)
|
||||
return;
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
|
||||
if (frameSkip >= 0)
|
||||
systemFrameSkip = frameSkip;
|
||||
|
||||
@@ -2609,16 +2617,16 @@ EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
|
||||
panel->ShowFullScreen(true);
|
||||
}
|
||||
|
||||
if (panel->panel) {
|
||||
panel->panel->Destroy();
|
||||
panel->panel = NULL;
|
||||
}
|
||||
panel->DestroyDrawingPanel();
|
||||
|
||||
update_opts();
|
||||
}
|
||||
|
||||
EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
int filt = gopts.filter;
|
||||
|
||||
if ((filt == FF_PLUGIN || ++gopts.filter == FF_PLUGIN) && gopts.filter_plugin.empty()) {
|
||||
@@ -2627,10 +2635,7 @@ EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
|
||||
|
||||
update_opts();
|
||||
|
||||
if (panel->panel) {
|
||||
panel->panel->Destroy();
|
||||
panel->panel = NULL;
|
||||
}
|
||||
panel->DestroyDrawingPanel();
|
||||
|
||||
wxString msg;
|
||||
msg.Printf(_("Using pixel filter #%d"), gopts.filter);
|
||||
@@ -2639,13 +2644,13 @@ EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
|
||||
|
||||
EVT_HANDLER_MASK(ChangeIFB, "Change Interframe Blending", CMDEN_NREC_ANY)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
gopts.ifb = (gopts.ifb + 1) % 3;
|
||||
update_opts();
|
||||
|
||||
if (panel->panel) {
|
||||
panel->panel->Destroy();
|
||||
panel->panel = NULL;
|
||||
}
|
||||
panel->DestroyDrawingPanel();
|
||||
|
||||
wxString msg;
|
||||
msg.Printf(_("Using interframe blending #%d"), gopts.ifb);
|
||||
@@ -2833,13 +2838,13 @@ EVT_HANDLER(Bilinear, "Use bilinear filter with 3d renderer")
|
||||
|
||||
EVT_HANDLER(RetainAspect, "Retain aspect ratio when resizing")
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
GetMenuOptionBool("RetainAspect", gopts.retain_aspect);
|
||||
|
||||
// Force new panel with new aspect ratio options.
|
||||
if (panel->panel) {
|
||||
panel->panel->Destroy();
|
||||
panel->panel = nullptr;
|
||||
}
|
||||
panel->DestroyDrawingPanel();
|
||||
|
||||
update_opts();
|
||||
}
|
||||
|
@@ -4028,5 +4028,8 @@ bool MainFrame::BindControls()
|
||||
panel->SetFrameTitle();
|
||||
// All OK; activate idle loop
|
||||
panel->SetExtraStyle(panel->GetExtraStyle() | wxWS_EX_PROCESS_IDLE);
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
panel->StartEmulationThread();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
377
src/wx/panel.cpp
377
src/wx/panel.cpp
@@ -28,35 +28,11 @@ static void clear_input_press();
|
||||
|
||||
int emulating;
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
|
||||
|
||||
GameArea::GameArea()
|
||||
: wxPanel()
|
||||
, panel(NULL)
|
||||
, emusys(NULL)
|
||||
, was_paused(false)
|
||||
, rewind_time(0)
|
||||
, do_rewind(false)
|
||||
, rewind_mem(0)
|
||||
, num_rewind_states(0)
|
||||
, loaded(IMAGE_UNKNOWN)
|
||||
, basic_width(GBAWidth)
|
||||
, basic_height(GBAHeight)
|
||||
, fullscreen(false)
|
||||
, paused(false)
|
||||
, pointer_blanked(false)
|
||||
, mouse_active_time(0)
|
||||
{
|
||||
SetSizer(new wxBoxSizer(wxVERTICAL));
|
||||
// all renderers prefer 32-bit
|
||||
// well, "simple" prefers 24-bit, but that's not available for filters
|
||||
systemColorDepth = 32;
|
||||
hq2x_init(32);
|
||||
Init_2xSaI(32);
|
||||
}
|
||||
|
||||
void GameArea::LoadGame(const wxString& name)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
rom_scene_rls = wxT("-");
|
||||
rom_scene_rls_name = wxT("-");
|
||||
rom_name = wxT("");
|
||||
@@ -553,10 +529,7 @@ void GameArea::UnloadGame(bool destruct)
|
||||
|
||||
// in destructor, panel should be auto-deleted by wx since all panels
|
||||
// are derived from a window attached as child to GameArea
|
||||
if (panel)
|
||||
panel->Destroy();
|
||||
|
||||
panel = NULL;
|
||||
DestroyDrawingPanel();
|
||||
|
||||
// close any game-related viewer windows
|
||||
// in destructor, viewer windows are in process of being deleted anyway
|
||||
@@ -595,6 +568,9 @@ bool GameArea::LoadState(int slot)
|
||||
|
||||
bool GameArea::LoadState(const wxFileName& fname)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
// FIXME: first save to backup state if not backup state
|
||||
bool ret = emusys->emuReadState(UTF8(fname.GetFullPath()));
|
||||
|
||||
@@ -642,6 +618,9 @@ bool GameArea::SaveState(int slot)
|
||||
|
||||
bool GameArea::SaveState(const wxFileName& fname)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
// FIXME: first copy to backup state if not backup state
|
||||
bool ret = emusys->emuWriteState(UTF8(fname.GetFullPath()));
|
||||
wxGetApp().frame->update_state_ts(true);
|
||||
@@ -681,6 +660,9 @@ void GameArea::SaveBattery()
|
||||
|
||||
void GameArea::AddBorder()
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
if (basic_width != GBWidth)
|
||||
return;
|
||||
|
||||
@@ -693,14 +675,14 @@ void GameArea::AddBorder()
|
||||
wxGetApp().frame->Fit();
|
||||
GetSizer()->Detach(panel->GetWindow());
|
||||
|
||||
if (panel)
|
||||
panel->Destroy();
|
||||
|
||||
panel = NULL;
|
||||
DestroyDrawingPanel();
|
||||
}
|
||||
|
||||
void GameArea::DelBorder()
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
if (basic_width != SGBWidth)
|
||||
return;
|
||||
|
||||
@@ -712,10 +694,7 @@ void GameArea::DelBorder()
|
||||
wxGetApp().frame->Fit();
|
||||
GetSizer()->Detach(panel->GetWindow());
|
||||
|
||||
if (panel)
|
||||
panel->Destroy();
|
||||
|
||||
panel = NULL;
|
||||
DestroyDrawingPanel();
|
||||
}
|
||||
|
||||
void GameArea::AdjustMinSize()
|
||||
@@ -751,6 +730,9 @@ void GameArea::LowerMinSize()
|
||||
|
||||
void GameArea::AdjustSize(bool force)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
AdjustMinSize();
|
||||
|
||||
if (fullscreen)
|
||||
@@ -774,6 +756,9 @@ void GameArea::AdjustSize(bool force)
|
||||
|
||||
void GameArea::ShowFullScreen(bool full)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
if (full == fullscreen) {
|
||||
// in case the tlw somehow lost its mind, force it to proper mode
|
||||
if (wxGetApp().frame->IsFullScreen() != fullscreen)
|
||||
@@ -791,10 +776,7 @@ void GameArea::ShowFullScreen(bool full)
|
||||
|
||||
// just in case screen mode is going to change, go ahead and preemptively
|
||||
// delete panel to be recreated immediately after resize
|
||||
if (panel) {
|
||||
panel->Destroy();
|
||||
panel = NULL;
|
||||
}
|
||||
DestroyDrawingPanel();
|
||||
|
||||
// Windows does not restore old window size/pos
|
||||
// at least under Wine
|
||||
@@ -939,6 +921,9 @@ void GameArea::OnKillFocus(wxFocusEvent& ev)
|
||||
|
||||
void GameArea::Pause()
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
if (paused)
|
||||
return;
|
||||
|
||||
@@ -961,6 +946,9 @@ void GameArea::Pause()
|
||||
|
||||
void GameArea::Resume()
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
if (!paused)
|
||||
return;
|
||||
|
||||
@@ -973,6 +961,307 @@ void GameArea::Resume()
|
||||
SetFocus();
|
||||
}
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
|
||||
|
||||
GameArea::GameArea()
|
||||
: wxPanel()
|
||||
, panel(NULL)
|
||||
, emusys(NULL)
|
||||
, was_paused(false)
|
||||
, rewind_time(0)
|
||||
, do_rewind(false)
|
||||
, rewind_mem(0)
|
||||
, num_rewind_states(0)
|
||||
, loaded(IMAGE_UNKNOWN)
|
||||
, basic_width(GBAWidth)
|
||||
, basic_height(GBAHeight)
|
||||
, fullscreen(false)
|
||||
, paused(false)
|
||||
, pointer_blanked(false)
|
||||
, mouse_active_time(0)
|
||||
{
|
||||
SetSizer(new wxBoxSizer(wxVERTICAL));
|
||||
// all renderers prefer 32-bit
|
||||
// well, "simple" prefers 24-bit, but that's not available for filters
|
||||
systemColorDepth = 32;
|
||||
hq2x_init(32);
|
||||
Init_2xSaI(32);
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
Bind(WX_THREAD_REQUEST_UPDATEDRAWPANEL, &GameArea::RequestUpdateDrawPanel, this);
|
||||
Bind(WX_THREAD_REQUEST_DRAWFRAME, &GameArea::RequestDrawFrame, this);
|
||||
Bind(WX_THREAD_REQUEST_UPDATESTATUSBAR, &GameArea::RequestUpdateStatusBar, this);
|
||||
Bind(WX_THREAD_REQUEST_GBPRINTER, &GameArea::ShowPrinter, this);
|
||||
Bind(WX_THREAD_REQUEST_UPDATELOG, &GameArea::RequestUpdateLog, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSection MainFrame::emulationCS;
|
||||
|
||||
void GameArea::RequestDraw()
|
||||
{
|
||||
wxQueueEvent(this, new wxThreadEvent(WX_THREAD_REQUEST_DRAWFRAME));
|
||||
}
|
||||
|
||||
void GameArea::RequestDrawFrame(wxThreadEvent& WXUNUSED(event))
|
||||
{
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
MainFrame* mf = wxGetApp().frame;
|
||||
mf->UpdateViewers();
|
||||
if (panel) {
|
||||
panel->DrawArea(&pix);
|
||||
}
|
||||
}
|
||||
|
||||
wxThread::ExitCode GameArea::Entry()
|
||||
{
|
||||
while (!GetThread()->TestDestroy()) {
|
||||
{
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
if (emusys) {
|
||||
wxGetApp().frame->PollJoysticks();
|
||||
if (!panel) {
|
||||
wxQueueEvent(this, new wxThreadEvent(WX_THREAD_REQUEST_UPDATEDRAWPANEL));
|
||||
}
|
||||
if (!paused && panel) {
|
||||
emusys->emuMain(emusys->emuCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
wxMilliSleep(1);
|
||||
}
|
||||
return (wxThread::ExitCode)0;
|
||||
}
|
||||
|
||||
void GameArea::StopEmulationThread()
|
||||
{
|
||||
if (GetThread() && GetThread()->IsRunning())
|
||||
GetThread()->Delete(); // it will exit after next `TestDestroy()`
|
||||
}
|
||||
|
||||
void GameArea::StartEmulationThread()
|
||||
{
|
||||
if (CreateThread(wxTHREAD_JOINABLE) != wxTHREAD_NO_ERROR)
|
||||
{
|
||||
wxLogError(_("Could not create emulation thread!"));
|
||||
return;
|
||||
}
|
||||
if (GetThread()->Run() != wxTHREAD_NO_ERROR)
|
||||
{
|
||||
wxLogError(_("Could not run emulation thread!"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GameArea::RequestUpdateDrawPanel(wxThreadEvent& WXUNUSED(event))
|
||||
{
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
if (!panel) {
|
||||
switch (gopts.render_method) {
|
||||
case RND_SIMPLE:
|
||||
panel = new BasicDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#ifdef __WXMAC__
|
||||
case RND_QUARTZ2D:
|
||||
panel = new Quartz2DDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_OGL
|
||||
case RND_OPENGL:
|
||||
panel = new GLDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#endif
|
||||
#if defined(__WXMSW__) && !defined(NO_D3D)
|
||||
case RND_DIRECT3D:
|
||||
panel = new DXDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
wxWindow* w = panel->GetWindow();
|
||||
|
||||
// set up event handlers
|
||||
w->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(GameArea::OnKeyDown), NULL, this);
|
||||
w->Connect(wxEVT_KEY_UP, wxKeyEventHandler(GameArea::OnKeyUp), NULL, this);
|
||||
w->Connect(wxEVT_PAINT, wxPaintEventHandler(GameArea::PaintEv), NULL, this);
|
||||
w->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(GameArea::EraseBackground), NULL, this);
|
||||
|
||||
// set userdata so we know it's the panel and not the frame being resized
|
||||
// the userdata is freed on disconnect/destruction
|
||||
this->Connect(wxEVT_SIZE, wxSizeEventHandler(GameArea::OnSize), NULL, this);
|
||||
|
||||
// We need to check if the buttons stayed pressed when focus the panel.
|
||||
w->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(GameArea::OnKillFocus), NULL, this);
|
||||
|
||||
// Update mouse last-used timers on mouse events etc..
|
||||
w->Connect(wxEVT_MOTION, wxMouseEventHandler(GameArea::MouseEvent), NULL, this);
|
||||
w->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(GameArea::MouseEvent), NULL, this);
|
||||
w->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(GameArea::MouseEvent), NULL, this);
|
||||
w->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(GameArea::MouseEvent), NULL, this);
|
||||
w->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(GameArea::MouseEvent), NULL, this);
|
||||
|
||||
w->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
|
||||
w->SetSize(wxSize(basic_width, basic_height));
|
||||
|
||||
if (maxScale)
|
||||
w->SetMaxSize(wxSize(basic_width * maxScale,
|
||||
basic_height * maxScale));
|
||||
|
||||
// if user changed Display/Scale config, this needs to run
|
||||
AdjustMinSize();
|
||||
AdjustSize(false);
|
||||
|
||||
unsigned frame_priority = gopts.retain_aspect ? 0 : 1;
|
||||
|
||||
GetSizer()->Clear();
|
||||
|
||||
// add spacers on top and bottom to center panel vertically
|
||||
// but not on 2.8 which does not handle this correctly
|
||||
if (gopts.retain_aspect)
|
||||
#if wxCHECK_VERSION(2, 9, 0)
|
||||
GetSizer()->Add(0, 0, wxEXPAND);
|
||||
#else
|
||||
frame_priority = 1;
|
||||
#endif
|
||||
|
||||
// this triggers an assertion dialog in <= 3.1.2 in debug mode
|
||||
GetSizer()->Add(w, frame_priority, gopts.retain_aspect ? (wxSHAPED | wxALIGN_CENTER | wxEXPAND) : wxEXPAND);
|
||||
|
||||
#if wxCHECK_VERSION(2, 9, 0)
|
||||
if (gopts.retain_aspect)
|
||||
GetSizer()->Add(0, 0, wxEXPAND);
|
||||
#endif
|
||||
|
||||
Layout();
|
||||
|
||||
#if wxCHECK_VERSION(2, 9, 0)
|
||||
SendSizeEvent();
|
||||
#endif
|
||||
|
||||
if (pointer_blanked)
|
||||
w->SetCursor(wxCursor(wxCURSOR_BLANK));
|
||||
|
||||
// set focus to panel
|
||||
w->SetFocus();
|
||||
|
||||
// generate system color maps (after output module init)
|
||||
if (loaded == IMAGE_GBA) utilUpdateSystemColorMaps(gbaLcdFilter);
|
||||
else if (loaded == IMAGE_GB) utilUpdateSystemColorMaps(gbLcdFilter);
|
||||
else utilUpdateSystemColorMaps(false);
|
||||
}
|
||||
}
|
||||
|
||||
void GameArea::RequestStatusBar(int speed, int frames)
|
||||
{
|
||||
wxThreadEvent *event = new wxThreadEvent(WX_THREAD_REQUEST_UPDATESTATUSBAR);
|
||||
event->SetPayload(speed);
|
||||
event->SetExtraLong(frames); // should probably use payload too
|
||||
wxQueueEvent(this, event);
|
||||
}
|
||||
|
||||
struct PrinterDataDialog {
|
||||
uint16_t* to_print;
|
||||
uint16_t** accum_prdata;
|
||||
int lines, feed;
|
||||
int *accum_prdata_len, *accum_prdata_size;
|
||||
};
|
||||
PrinterDataDialog printerDataDialog;
|
||||
|
||||
void GameArea::RequestGBPrinter(uint16_t* to_print, uint16_t** accum_prdata, int lines, int feed, int *accum_prdata_len, int *accum_prdata_size)
|
||||
{
|
||||
wxThreadEvent *event = new wxThreadEvent(WX_THREAD_REQUEST_GBPRINTER);
|
||||
printerDataDialog = {to_print, accum_prdata, lines, feed, accum_prdata_len, accum_prdata_size};
|
||||
event->SetPayload(&printerDataDialog);
|
||||
wxQueueEvent(this, event);
|
||||
}
|
||||
|
||||
void GameArea::ShowPrinter(wxThreadEvent& event)
|
||||
{
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
PrinterDataDialog *pdd = event.GetPayload<PrinterDataDialog*>();
|
||||
|
||||
uint16_t* to_print = pdd->to_print;
|
||||
uint16_t** accum_prdata = pdd->accum_prdata;
|
||||
int lines = pdd->lines;
|
||||
int feed = pdd->feed;
|
||||
int *accum_prdata_len = pdd->accum_prdata_len;
|
||||
int *accum_prdata_size = pdd->accum_prdata_size;
|
||||
|
||||
PrintDialog dlg(to_print, lines, !(feed & 15));
|
||||
int ret = dlg.ShowModal();
|
||||
|
||||
if (ret == wxID_OK) {
|
||||
*accum_prdata_len = (lines + 1) * 162;
|
||||
|
||||
if (to_print != *accum_prdata) {
|
||||
if (*accum_prdata_size < *accum_prdata_len) {
|
||||
if (!(*accum_prdata_size))
|
||||
*accum_prdata = (uint16_t*)calloc(*accum_prdata_len, 2);
|
||||
else
|
||||
*accum_prdata = (uint16_t*)realloc(*accum_prdata, *accum_prdata_len * 2);
|
||||
|
||||
*accum_prdata_size = *accum_prdata_len;
|
||||
}
|
||||
|
||||
memcpy(*accum_prdata, to_print, *accum_prdata_len * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameArea::RequestUpdateStatusBar(wxThreadEvent& event)
|
||||
{
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
MainFrame* f = wxGetApp().frame;
|
||||
int speed = event.GetPayload<int>();
|
||||
int frames = event.GetExtraLong(); // should probably use payload too
|
||||
wxString s;
|
||||
s.Printf(_("%d%%(%d, %d fps)"), speed, systemFrameSkip, frames * speed / 100);
|
||||
|
||||
switch (showSpeed) {
|
||||
case SS_NONE:
|
||||
f->GetPanel()->osdstat.clear();
|
||||
break;
|
||||
|
||||
case SS_PERCENT:
|
||||
f->GetPanel()->osdstat.Printf(_("%d%%"), speed);
|
||||
break;
|
||||
|
||||
case SS_DETAILED:
|
||||
f->GetPanel()->osdstat = s;
|
||||
break;
|
||||
}
|
||||
|
||||
wxGetApp().frame->SetStatusText(s, 1);
|
||||
}
|
||||
|
||||
void GameArea::UpdateLog()
|
||||
{
|
||||
wxQueueEvent(this, new wxThreadEvent(WX_THREAD_REQUEST_UPDATELOG));
|
||||
}
|
||||
|
||||
void GameArea::RequestUpdateLog(wxThreadEvent& WXUNUSED(event))
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
LogDialog* d = wxGetApp().frame->logdlg;
|
||||
|
||||
if (d && d->IsShown()) {
|
||||
d->Update();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NO_THREAD_MAINLOOP
|
||||
|
||||
void GameArea::DestroyDrawingPanel()
|
||||
{
|
||||
if (panel) {
|
||||
panel->Destroy();
|
||||
panel = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GameArea::OnIdle(wxIdleEvent& event)
|
||||
{
|
||||
wxString pl = wxGetApp().pending_load;
|
||||
@@ -1416,7 +1705,9 @@ void GameArea::OnSDLJoy(wxSDLJoyEvent& ev)
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(GameArea, wxPanel)
|
||||
#ifdef NO_THREAD_MAINLOOP
|
||||
EVT_IDLE(GameArea::OnIdle)
|
||||
#endif
|
||||
EVT_SDLJOY(GameArea::OnSDLJoy)
|
||||
// FIXME: wxGTK does not generate motion events in MainFrame (not sure
|
||||
// what to do about it)
|
||||
|
@@ -86,18 +86,22 @@ void systemDrawScreen()
|
||||
{
|
||||
frames++;
|
||||
MainFrame* mf = wxGetApp().frame;
|
||||
mf->UpdateViewers();
|
||||
// FIXME: Sm60FPS crap and sondBufferLow crap
|
||||
GameArea* ga = mf->GetPanel();
|
||||
#ifndef NO_FFMPEG
|
||||
|
||||
if (ga)
|
||||
ga->AddFrame(pix);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
if (ga && ga->panel) {
|
||||
ga->RequestDraw();
|
||||
}
|
||||
#else
|
||||
mf->UpdateViewers();
|
||||
if (ga && ga->panel)
|
||||
ga->panel->DrawArea(&pix);
|
||||
#endif
|
||||
}
|
||||
|
||||
// record a game "movie"
|
||||
@@ -337,6 +341,9 @@ uint32_t systemReadJoypad(int joy)
|
||||
void systemShowSpeed(int speed)
|
||||
{
|
||||
MainFrame* f = wxGetApp().frame;
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
f->GetPanel()->RequestStatusBar(speed, frames);
|
||||
#else
|
||||
wxString s;
|
||||
s.Printf(_("%d%%(%d, %d fps)"), speed, systemFrameSkip, frames * speed / 100);
|
||||
|
||||
@@ -355,6 +362,7 @@ void systemShowSpeed(int speed)
|
||||
}
|
||||
|
||||
wxGetApp().frame->SetStatusText(s, 1);
|
||||
#endif // NO_THREAD_MAINLOOP
|
||||
frames = 0;
|
||||
}
|
||||
|
||||
@@ -658,53 +666,6 @@ int systemGetSensorZ()
|
||||
return sensorz[gopts.default_stick - 1] / 10;
|
||||
}
|
||||
|
||||
class PrintDialog : public wxEvtHandler, public wxPrintout {
|
||||
public:
|
||||
PrintDialog(const uint16_t* data, int lines, bool cont);
|
||||
~PrintDialog();
|
||||
int ShowModal()
|
||||
{
|
||||
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
|
||||
|
||||
if (gopts.keep_on_top)
|
||||
dlg->SetWindowStyle(dlg->GetWindowStyle() | wxSTAY_ON_TOP);
|
||||
else
|
||||
dlg->SetWindowStyle(dlg->GetWindowStyle() & ~wxSTAY_ON_TOP);
|
||||
|
||||
CheckPointer(wxGetApp().frame);
|
||||
return wxGetApp().frame->ShowModal(dlg);
|
||||
}
|
||||
|
||||
private:
|
||||
void DoSave(wxCommandEvent&);
|
||||
void DoPrint(wxCommandEvent&);
|
||||
void ChangeMag(wxCommandEvent&);
|
||||
void ShowImg(wxPaintEvent&);
|
||||
bool OnPrintPage(int pno);
|
||||
void OnPreparePrinting();
|
||||
bool HasPage(int pno) { return pno <= npw * nph; }
|
||||
void GetPageInfo(int* minp, int* maxp, int* pfrom, int* pto)
|
||||
{
|
||||
*minp = 1;
|
||||
*maxp = npw * nph;
|
||||
*pfrom = 1;
|
||||
*pto = 1;
|
||||
}
|
||||
|
||||
wxDialog* dlg;
|
||||
wxPanel* p;
|
||||
wxImage img;
|
||||
wxBitmap* bmp;
|
||||
wxControlWithItems* mag;
|
||||
|
||||
static wxPrintData* printdata;
|
||||
static wxPageSetupDialogData* pagedata;
|
||||
wxRect margins;
|
||||
int npw, nph;
|
||||
|
||||
DECLARE_CLASS(PrintDialog)
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(PrintDialog, wxEvtHandler)
|
||||
|
||||
PrintDialog::PrintDialog(const uint16_t* data, int lines, bool cont):
|
||||
@@ -1016,6 +977,9 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
panel->RequestGBPrinter(to_print, &accum_prdata, lines, feed, &accum_prdata_len, &accum_prdata_size);
|
||||
#else
|
||||
PrintDialog dlg(to_print, lines, !(feed & 15));
|
||||
int ret = dlg.ShowModal();
|
||||
|
||||
@@ -1035,6 +999,7 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con
|
||||
memcpy(accum_prdata, to_print, accum_prdata_len * 2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void systemScreenMessage(const wxString& msg)
|
||||
@@ -1324,12 +1289,15 @@ void log(const char* defaultMsg, ...)
|
||||
wxGetApp().log.append(msg);
|
||||
|
||||
if (wxGetApp().IsMainLoopRunning()) {
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxGetApp().frame->GetPanel()->UpdateLog();
|
||||
#else
|
||||
LogDialog* d = wxGetApp().frame->logdlg;
|
||||
|
||||
if (d && d->IsShown()) {
|
||||
d->Update();
|
||||
}
|
||||
|
||||
systemScreenMessage(msg);
|
||||
#endif
|
||||
//systemScreenMessage(msg);
|
||||
}
|
||||
}
|
||||
|
@@ -726,6 +726,9 @@ MainFrame::MainFrame()
|
||||
|
||||
MainFrame::~MainFrame()
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
GetPanel()->StopEmulationThread();
|
||||
#endif
|
||||
#ifndef NO_LINK
|
||||
CloseLink();
|
||||
#endif
|
||||
@@ -772,6 +775,10 @@ void MainFrame::OnDropFile(wxDropFilesEvent& event)
|
||||
wxString* f = event.GetFiles();
|
||||
// ignore all but last
|
||||
wxGetApp().pending_load = f[event.GetNumberOfFiles() - 1];
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
GetPanel()->LoadGame(wxGetApp().pending_load);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainFrame::OnMenu(wxContextMenuEvent& event)
|
||||
@@ -845,6 +852,9 @@ void MainFrame::OnSize(wxSizeEvent& event)
|
||||
|
||||
int MainFrame::FilterEvent(wxEvent& event)
|
||||
{
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
wxCriticalSectionLocker lock(MainFrame::emulationCS);
|
||||
#endif
|
||||
if (event.GetEventType() == wxEVT_KEY_DOWN && !menus_opened && !dialog_opened)
|
||||
{
|
||||
wxKeyEvent& ke = (wxKeyEvent&)event;
|
||||
@@ -1081,7 +1091,7 @@ void MainFrame::MenuPopped(wxMenuEvent& evt)
|
||||
// On Windows nullptr is the system menu.
|
||||
if (evt.GetEventType() == wxEVT_MENU_CLOSE && (evt.GetMenu() == nullptr || evt.GetMenu()->GetMenuBar() == GetMenuBar()))
|
||||
SetMenusOpened(false);
|
||||
else
|
||||
else if (evt.GetEventType() == wxEVT_MENU_OPEN)
|
||||
SetMenusOpened(true);
|
||||
|
||||
evt.Skip();
|
||||
@@ -1101,17 +1111,17 @@ void MainFrame::MenuPopped(wxMenuEvent& evt)
|
||||
void MainFrame::SetMenusOpened(bool state)
|
||||
{
|
||||
if ((menus_opened = state)) {
|
||||
#ifdef __WXMSW__
|
||||
paused = true;
|
||||
panel->Pause();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef __WXMSW__
|
||||
paused = false;
|
||||
pause_next = false;
|
||||
panel->Resume();
|
||||
#endif
|
||||
//#ifdef __WXMSW__
|
||||
// paused = true;
|
||||
// panel->Pause();
|
||||
//#endif
|
||||
// }
|
||||
// else {
|
||||
//#ifdef __WXMSW__
|
||||
// paused = false;
|
||||
// pause_next = false;
|
||||
// panel->Resume();
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -214,6 +214,10 @@ public:
|
||||
MainFrame();
|
||||
~MainFrame();
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
static wxCriticalSection emulationCS;
|
||||
#endif
|
||||
|
||||
bool BindControls();
|
||||
void MenuOptionIntMask(const char* menuName, int& field, int mask);
|
||||
void MenuOptionIntRadioValue(const char* menuName, int& field, int mask);
|
||||
@@ -500,11 +504,42 @@ class DrawingPanelBase;
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
class GameArea : public wxPanel, public HiDPIAware {
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
#include <wx/thread.h>
|
||||
|
||||
wxDEFINE_EVENT(WX_THREAD_REQUEST_UPDATEDRAWPANEL, wxThreadEvent);
|
||||
wxDEFINE_EVENT(WX_THREAD_REQUEST_DRAWFRAME, wxThreadEvent);
|
||||
wxDEFINE_EVENT(WX_THREAD_REQUEST_UPDATESTATUSBAR, wxThreadEvent);
|
||||
wxDEFINE_EVENT(WX_THREAD_REQUEST_GBPRINTER, wxThreadEvent);
|
||||
wxDEFINE_EVENT(WX_THREAD_REQUEST_UPDATELOG, wxThreadEvent);
|
||||
#endif // NO_THREAD_MAINLOOP
|
||||
|
||||
class GameArea : public wxPanel, public HiDPIAware
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
, public wxThreadHelper
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
GameArea();
|
||||
virtual ~GameArea();
|
||||
|
||||
#ifndef NO_THREAD_MAINLOOP
|
||||
virtual wxThread::ExitCode Entry();
|
||||
void StartEmulationThread();
|
||||
void StopEmulationThread();
|
||||
void RequestUpdateDrawPanel(wxThreadEvent&);
|
||||
void RequestDrawFrame(wxThreadEvent&);
|
||||
void RequestUpdateStatusBar(wxThreadEvent&);
|
||||
void RequestDraw();
|
||||
void RequestStatusBar(int speed, int frames);
|
||||
void RequestGBPrinter(uint16_t*, uint16_t**, int, int, int*, int*);
|
||||
void ShowPrinter(wxThreadEvent&);
|
||||
void RequestUpdateLog(wxThreadEvent&);
|
||||
void UpdateLog();
|
||||
#endif
|
||||
|
||||
void DestroyDrawingPanel();
|
||||
|
||||
virtual void SetMainFrame(MainFrame* parent) { main_frame = parent; }
|
||||
|
||||
// set to game title + link info
|
||||
@@ -747,6 +782,53 @@ private:
|
||||
|
||||
#include "opts.h"
|
||||
|
||||
class PrintDialog : public wxEvtHandler, public wxPrintout {
|
||||
public:
|
||||
PrintDialog(const uint16_t* data, int lines, bool cont);
|
||||
~PrintDialog();
|
||||
int ShowModal()
|
||||
{
|
||||
dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER);
|
||||
|
||||
if (gopts.keep_on_top)
|
||||
dlg->SetWindowStyle(dlg->GetWindowStyle() | wxSTAY_ON_TOP);
|
||||
else
|
||||
dlg->SetWindowStyle(dlg->GetWindowStyle() & ~wxSTAY_ON_TOP);
|
||||
|
||||
CheckPointer(wxGetApp().frame);
|
||||
return wxGetApp().frame->ShowModal(dlg);
|
||||
}
|
||||
|
||||
private:
|
||||
void DoSave(wxCommandEvent&);
|
||||
void DoPrint(wxCommandEvent&);
|
||||
void ChangeMag(wxCommandEvent&);
|
||||
void ShowImg(wxPaintEvent&);
|
||||
bool OnPrintPage(int pno);
|
||||
void OnPreparePrinting();
|
||||
bool HasPage(int pno) { return pno <= npw * nph; }
|
||||
void GetPageInfo(int* minp, int* maxp, int* pfrom, int* pto)
|
||||
{
|
||||
*minp = 1;
|
||||
*maxp = npw * nph;
|
||||
*pfrom = 1;
|
||||
*pto = 1;
|
||||
}
|
||||
|
||||
wxDialog* dlg;
|
||||
wxPanel* p;
|
||||
wxImage img;
|
||||
wxBitmap* bmp;
|
||||
wxControlWithItems* mag;
|
||||
|
||||
static wxPrintData* printdata;
|
||||
static wxPageSetupDialogData* pagedata;
|
||||
wxRect margins;
|
||||
int npw, nph;
|
||||
|
||||
DECLARE_CLASS(PrintDialog)
|
||||
};
|
||||
|
||||
// I should add this to SoundDriver, but wxArrayString is wx-specific
|
||||
// I suppose I could make subclass wxSoundDriver. maybe later.
|
||||
|
||||
|
Reference in New Issue
Block a user