read kega fusion plugins in the wxwidgets interface and also started some work on xbrz support in the interface, will complete that later though.

This commit is contained in:
wowzaman12 2015-04-05 13:32:12 +00:00
parent d00e850b7b
commit a051754bf4
7 changed files with 308 additions and 58 deletions

View File

@ -2000,6 +2000,13 @@ EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
{
int filt = gopts.filter;
if(filt == FF_PLUGIN ||
++gopts.filter == FF_PLUGIN && gopts.filter_plugin.empty())
{
gopts.filter = 0;
}
update_opts();
if(panel->panel) {
panel->panel->Delete();
panel->panel = NULL;

View File

@ -1438,6 +1438,145 @@ private:
wxArrayVideoModes vm;
};
// enable plugin-related iff filter choice is plugin
class PluginEnabler : public wxValidator
{
public:
PluginEnabler() : wxValidator() {}
PluginEnabler(const PluginEnabler &e) : wxValidator() {}
wxObject *Clone() const { return new PluginEnabler(*this); }
bool TransferFromWindow() { return true; }
bool Validate(wxWindow *p) { return true; }
bool TransferToWindow()
{
GetWindow()->Enable(gopts.filter == FF_PLUGIN);
return true;
}
};
// The same, but as an event handler
static class PluginEnable_t : public wxEvtHandler
{
public:
wxWindow *lab, *ch;
void ToggleChoice(wxCommandEvent &ev)
{
bool en = ev.GetSelection() == FF_PLUGIN;
lab->Enable(en);
ch->Enable(en);
}
} PluginEnableHandler;
// fill in plugin list
class PluginListFiller : public PluginEnabler
{
public:
PluginListFiller(wxDialog *parent, wxControl *lab, wxChoice *ch) :
PluginEnabler(), txt(lab), dlg(parent), plugins(), filtch(ch) {}
PluginListFiller(const PluginListFiller &e) :
PluginEnabler(), txt(e.txt), dlg(e.dlg), plugins(e.plugins),
filtch(e.filtch) {}
wxObject *Clone() const { return new PluginListFiller(*this); }
bool Validate(wxWindow *p) { return true; }
bool TransferToWindow()
{
PluginEnabler::TransferToWindow();
wxChoice *ch = wxStaticCast(GetWindow(), wxChoice);
ch->Clear();
ch->Append(_("None"));
plugins.clear();
const wxString &plpath = wxStandardPaths::Get().GetPluginsDir();
wxDir::GetAllFiles(plpath, &plugins, wxT("*.rpi"));
for(int i = 0; i < plugins.size(); i++) {
wxDynamicLibrary dl(plugins[i], wxDL_VERBATIM|wxDL_NOW);
RENDPLUG_GetInfo GetInfo;
const RENDER_PLUGIN_INFO *rpi;
if(dl.IsLoaded() &&
(GetInfo = (RENDPLUG_GetInfo)dl.GetSymbol(wxT("RenderPluginGetInfo"))) &&
// note that in actual kega fusion plugins, rpi->Output is
// unused (as is rpi->Handle)
dl.GetSymbol(wxT("RenderPluginOutput")) &&
(rpi = GetInfo()) &&
// FIXME: maybe this should be >= RPI_VERISON
(rpi->Flags & 0xff) == RPI_VERSION &&
// RPI_565_SUPP is not supported
// although it would be possible
// and it would make Cairo more efficient
(rpi->Flags & (RPI_555_SUPP|RPI_888_SUPP))) {
wxFileName fn(plugins[i]);
wxString s = fn.GetName();
s += wxT(": ");
s += wxString(rpi->Name, wxConvUTF8, sizeof(rpi->Name));
fn.MakeRelativeTo(plpath);
plugins[i] = fn.GetFullName();
ch->Append(s);
if(plugins[i] == gopts.filter_plugin)
ch->SetSelection(i + 1);
} else
plugins.RemoveAt(i--);
}
if(ch->GetCount() == 1) {
// this is probably the only place the user can find out where
// to put the plugins... it depends on where program was
// installed, and of course OS
wxString msg;
msg.Printf(_("No usable rpi plugins found in %s"), plpath.c_str());
systemScreenMessage(msg);
ch->Hide();
txt->Hide();
int cursel = filtch->GetSelection();
if(cursel == FF_PLUGIN)
cursel = 0;
if(filtch->GetCount() == FF_PLUGIN + 1) {
filtch->Delete(FF_PLUGIN);
// apparently wxgtk loses selection after this, even
// if selection was not FF_PLUGIN
filtch->SetSelection(cursel);
}
} else {
ch->Show();
txt->Show();
if(filtch->GetCount() < FF_PLUGIN + 1)
filtch->Append(_("Plugin"));
}
// FIXME: this isn't enough. It only resizes 2nd time around
dlg->Fit();
return true;
}
bool TransferFromWindow()
{
wxChoice *ch = wxStaticCast(GetWindow(), wxChoice);
if(ch->GetCount() == 1) {
gopts.filter_plugin = wxEmptyString;
// this happens if "Plugin" was selected and the entry was
// subsequently removed
if(ch->GetSelection() < 0)
ch->SetSelection(0);
if(gopts.filter < 0)
gopts.filter = 0;
} else {
int n = ch->GetSelection();
if(n > 0)
gopts.filter_plugin = plugins[n - 1];
else {
if(filtch->GetSelection() == FF_PLUGIN) {
wxMessageBox(_("Please select a plugin or a different filter"),
_("Plugin selection error"), wxOK|wxICON_ERROR);
return false;
}
gopts.filter_plugin = wxEmptyString;
}
}
return true;
}
private:
wxDialog *dlg;
wxControl *txt;
wxChoice *filtch;
wxArrayString plugins;
};
// this is the cmd table index for the accel tree ctrl
// one of the "benefits" of using TreeItemData is that we have to
// malloc them all, because treectrl destructor will free them all
@ -1459,15 +1598,15 @@ static bool treeid_to_name(int id, wxString &name, wxTreeCtrl *tc,
wxTreeItemIdValue cookie;
for(wxTreeItemId tid = tc->GetFirstChild(parent, cookie); tid.IsOk();
tid = tc->GetNextChild(parent, cookie)) {
const TreeInt *ti = static_cast<const TreeInt *>(tc->GetItemData(tid));
if(ti && ti->val == id) {
name = wxString(wxT(' '), 2 * lev) + tc->GetItemText(tid);
return true;
}
if(treeid_to_name(id, name, tc, tid, lev + 1)) {
name = wxString(wxT(' '), 2 * lev) + tc->GetItemText(tid) + wxT('\n') + name;
return true;
}
const TreeInt *ti = static_cast<const TreeInt *>(tc->GetItemData(tid));
if(ti && ti->val == id) {
name = wxString(wxT(' '), 2 * lev) + tc->GetItemText(tid);
return true;
}
if(treeid_to_name(id, name, tc, tid, lev + 1)) {
name = wxString(wxT(' '), 2 * lev) + tc->GetItemText(tid) + wxT('\n') + name;
return true;
}
}
return false;
}
@ -2650,57 +2789,69 @@ bool MainFrame::InitMore(void)
d=LoadXRCropertySheetDialog("DisplayConfig");
{
/// On-Screen Display
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "SpeedIndicator",wxGenericValidator(& gopts.osd_speed));
getcbb("NoStatusMsg", gopts.no_osd_status);
getcbb("Transparent", gopts.osd_transparent);
/// On-Screen Display
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "SpeedIndicator",wxGenericValidator(& gopts.osd_speed));
getcbb("NoStatusMsg", gopts.no_osd_status);
getcbb("Transparent", gopts.osd_transparent);
/// Zoom
// this was a choice, but I'd rather not have to make an off-by-one
// validator just for this, and spinctrl is good enough.
getsc("DefaultScale", gopts.video_scale);
getcbb("RetainAspect", gopts.retain_aspect);
getsc("MaxScale", gopts.max_scale);
// fs modes should be filled in at popup time
// since they may change based on what screen is current
SafeXRCCTRL<wxChoice>(d, "FullscreenMode");
getcbb("Fullscreen", gopts.fullscreen);
/// Zoom
// this was a choice, but I'd rather not have to make an off-by-one
// validator just for this, and spinctrl is good enough.
getsc("DefaultScale", gopts.video_scale);
getcbb("RetainAspect", gopts.retain_aspect);
getsc("MaxScale", gopts.max_scale);
// fs modes should be filled in at popup time
// since they may change based on what screen is current
SafeXRCCTRL<wxChoice>(d, "FullscreenMode");
getcbb("Fullscreen", gopts.fullscreen);
/// Advanced
getrbi("OutputSimple", gopts.render_method, RND_SIMPLE);
getrbi("OutputOpenGL", gopts.render_method, RND_OPENGL);
/// Advanced
getrbi("OutputSimple", gopts.render_method, RND_SIMPLE);
getrbi("OutputOpenGL", gopts.render_method, RND_OPENGL);
#ifdef NO_OGL
rb->Hide();
rb->Hide();
#endif
getrbi("OutputCairo", gopts.render_method, RND_CAIRO);
getrbi("OutputCairo", gopts.render_method, RND_CAIRO);
#ifdef NO_CAIRO
rb->Hide();
rb->Hide();
#endif
getrbi("OutputDirect3D", gopts.render_method, RND_DIRECT3D);
getrbi("OutputDirect3D", gopts.render_method, RND_DIRECT3D);
#if !defined(__WXMSW__) || defined(NO_D3D) || 1 // not implemented
rb->Hide();
rb->Hide();
#endif
getcbb("Bilinear", gopts.bilinear);
getcbb("VSync", gopts.vsync);
// FIXME: make cb disabled when not GL or d3d
int mthr = wxThread::GetCPUCount();
if(mthr > 8)
mthr = 8;
if(mthr < 0)
mthr = 2;
cb=SafeXRCCTRL<wxCheckBox>(d, "Multithread");
cb->SetValidator(wxBoolIntValidator(&gopts.max_threads, mthr));
if(mthr <= 1)
cb->Hide();
getcbb("Bilinear", gopts.bilinear);
getcbb("VSync", gopts.vsync);
// FIXME: make cb disabled when not GL or d3d
int mthr = wxThread::GetCPUCount();
if(mthr > 8)
mthr = 8;
if(mthr < 0)
mthr = 2;
cb=SafeXRCCTRL<wxCheckBox>(d, "Multithread");
cb->SetValidator(wxBoolIntValidator(&gopts.max_threads, mthr));
if(mthr <= 1)
cb->Hide();
#ifdef MMX
getcbb("MMX", cpu_mmx);
getcbb("MMX", cpu_mmx);
#else
cb=SafeXRCCTRL<wxCheckBox>(d, "MMX");
cb->Hide();
cb=SafeXRCCTRL<wxCheckBox>(d, "MMX");
cb->Hide();
#endif
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "Filter",wxGenericValidator(& gopts.filter));
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "IFB",wxGenericValidator(& gopts.ifb));
d->Fit();
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "Filter",wxGenericValidator(& gopts.filter));
// these two are filled and/or hidden at dialog load time
wxControl *pll;
wxChoice *pl;
pll=SafeXRCCTRL<wxControl>(d, "PluginLab");
pl=SafeXRCCTRL<wxChoice>(d, "Plugin");
pll->SetValidator(PluginEnabler());
pl->SetValidator(PluginListFiller(d, pll, ch));
PluginEnableHandler.lab = pll;
PluginEnableHandler.ch = pl;
ch->Connect(wxEVT_COMMAND_CHOICE_SELECTED,
wxCommandEventHandler(PluginEnable_t::ToggleChoice),
NULL, &PluginEnableHandler);
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "IFB",wxGenericValidator(& gopts.ifb));
d->Fit();
}
d=LoadXRCropertySheetDialog("SoundConfig");

View File

@ -136,7 +136,8 @@ opt_desc opts[] = {
ENUMOPT("Display/Filter", wxTRANSLATE("Full-screen filter to apply"), gopts.filter,
wxTRANSLATE("none|2xsai|super2xsai|supereagle|pixelate|advmame|"
"bilinear|bilinearplus|scanlines|tvmode|hq2x|lq2x|"
"simple2x|simple3x|hq3x|simple4x|hq4x")),
"simple2x|simple3x|hq3x|simple4x|hq4x|xbrz|plugin")),
STROPT ("Display/FilterPlugin", wxTRANSLATE("Filter plugin library"), gopts.filter_plugin),
BOOLOPT("Display/Fullscreen", wxTRANSLATE("Enter fullscreen mode at startup"), gopts.fullscreen),
INTOPT ("Display/FullscreenDepth", wxTRANSLATE("Fullscreen mode color depth (0 = any)"), gopts.fs_mode.bpp, 0, 999),
INTOPT ("Display/FullscreenFreq", wxTRANSLATE("Fullscreen mode frequency (0 = any)"), gopts.fs_mode.refresh, 0, 999),

View File

@ -15,6 +15,7 @@ extern struct opts_t {
bool cpu_mmx;
bool no_osd_status;
int filter;
wxString filter_plugin;
int ifb;
bool fullscreen;
wxVideoMode fs_mode;

View File

@ -988,9 +988,47 @@ DrawingPanel::DrawingPanel(int _width, int _height) :
pixbuf1(0), pixbuf2(0), rpi(0), nthreads(0)
{
memset(delta, 0xff, sizeof(delta));
scale = builtin_ff_scale(gopts.filter);
if(gopts.filter == FF_PLUGIN) {
do { // do { } while(0) so break; exits entire block
// could've also just used goto & a label, I guess
gopts.filter = FF_NONE; // preemptive in case of errors
systemColorDepth = 32;
if(gopts.filter_plugin.empty())
break;
wxFileName fpn(gopts.filter_plugin);
fpn.MakeAbsolute(wxStandardPaths::Get().GetPluginsDir());
if(!filt_plugin.Load(fpn.GetFullPath(), wxDL_VERBATIM|wxDL_NOW))
break;
RENDPLUG_GetInfo gi = (RENDPLUG_GetInfo)filt_plugin.GetSymbol(wxT("RenderPluginGetInfo"));
if(!gi)
break;
// need to be able to write to _rpi to set Output() and Flags
RENDER_PLUGIN_INFO *_rpi = gi();
// FIXME: maybe < RPI_VERSION, assuming future vers. back compat?
if(!_rpi || (_rpi->Flags & 0xff) != RPI_VERSION ||
!(_rpi->Flags & (RPI_555_SUPP|RPI_888_SUPP)))
break;
_rpi->Flags &= ~RPI_565_SUPP;
if(_rpi->Flags & RPI_888_SUPP) {
_rpi->Flags &= ~RPI_555_SUPP;
// FIXME: should this be 32 or 24? No docs or sample source
systemColorDepth = 32;
} else
systemColorDepth = 16;
if(!_rpi->Output)
// note that in actual kega fusion plugins, rpi->Output is
// unused (as is rpi->Handle)
_rpi->Output = (RENDPLUG_Output)filt_plugin.GetSymbol(wxT("RenderPluginOutput"));
scale = (_rpi->Flags & RPI_OUT_SCLMSK) >> RPI_OUT_SCLSH;
rpi = _rpi;
gopts.filter = FF_PLUGIN; // now that there is a valid plugin
} while(0);
else {
scale = builtin_ff_scale(gopts.filter);
#define out_16 (systemColorDepth == 16)
#endif
systemColorDepth = 32;
}
systemColorDepth = 32;
// Intialize color tables
#if wxBYTE_ORDER == wxLITTLE_ENDIAN
@ -1149,9 +1187,6 @@ public:
case FF_TV:
ScanlinesTV32(src, instride, delta, dst, outstride, width, height);
break;
case FF_HQ2X:
hq2x32(src, instride, delta, dst, outstride, width, height);
break;
case FF_LQ2X:
lq2x32(src, instride, delta, dst, outstride, width, height);
break;
@ -1161,15 +1196,52 @@ public:
case FF_SIMPLE3X:
Simple3x32(src, instride, delta, dst, outstride, width, height);
break;
case FF_HQ3X:
hq3x32(src, instride, delta, dst, outstride, width, height);
break;
case FF_SIMPLE4X:
Simple4x32(src, instride, delta, dst, outstride, width, height);
break;
case FF_HQ2X:
hq2x32(src, instride, delta, dst, outstride, width, height);
break;
case FF_HQ3X:
hq3x32(src, instride, delta, dst, outstride, width, height);
break;
case FF_HQ4X:
hq4x32(src, instride, delta, dst, outstride, width, height);
break;
/* Placeholder for xbrz support
case FF_XBRZ2X:
break;
case FF_XBRZ3X:
break;
case FF_XBRZ4X:
break;
case FF_XBRZ5X:
break;
*/
case FF_PLUGIN:
// MFC interface did not do plugins in parallel
// Probably because it's almost certain they carry state or do
// other non-thread-safe things
// But the user can always turn mt off of it's not working..
RENDER_PLUGIN_OUTP outdesc;
outdesc.Size = sizeof(outdesc);
outdesc.Flags = rpi->Flags;
outdesc.SrcPtr = src;
outdesc.SrcPitch = instride;
outdesc.SrcW = width;
// FIXME: win32 code adds to H, saying that frame isn't fully
// rendered otherwise
// I need to verify that statement before I go adding stuff that
// may make it crash.
outdesc.SrcH = height; // + scale / 2
outdesc.DstPtr = dst;
outdesc.DstPitch = outstride;
outdesc.DstW = width * scale;
// on the other hand, there is at least 1 line below, so I'll add
// that to dest in case safety checks in plugin use < instead of <=
outdesc.DstH = height * scale + 1; // + scale * (scale / 2)
rpi->Output(&outdesc);
break;
default:
break;
}

View File

@ -508,6 +508,7 @@ protected:
FilterThread *threads;
int nthreads;
wxSemaphore filt_done;
wxDynamicLibrary filt_plugin;
const RENDER_PLUGIN_INFO *rpi; // also flag indicating plugin loaded
// largest buffer required is 32-bit * (max width + 1) * (max height + 2)
u8 delta[257 * 4 * 226];

View File

@ -2663,8 +2663,25 @@
<item>HQ 3x</item>
<item>Simple 4x</item>
<item>HQ 4x</item>
<item>XBR 2x (note: Not available yet)</item>
<item>XBR 3x (note: Not available yet)</item>
<item>XBR 4x (note: Not available yet)</item>
<item>XBR 5x (note: Not available yet)</item>
<item>Plugin</item>
</content>
</object>
<flag>wxALL|wxEXPAND</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxStaticText" name="PluginLab">
<label>Plugin :</label>
</object>
<flag>wxALL|wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxChoice" name="Plugin"/>
<flag>wxALL|wxEXPAND</flag>
<border>5</border>
</object>