read kega fusion plugins in the wxwidgets interface and also started some work on xbrz support in the interface, will complete that later though.
git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@1301 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
parent
fccb69238b
commit
6497a54aad
|
@ -2000,6 +2000,13 @@ EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
|
||||||
|
|
||||||
EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", 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) {
|
if(panel->panel) {
|
||||||
panel->panel->Delete();
|
panel->panel->Delete();
|
||||||
panel->panel = NULL;
|
panel->panel = NULL;
|
||||||
|
|
|
@ -1438,6 +1438,145 @@ private:
|
||||||
wxArrayVideoModes vm;
|
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
|
// this is the cmd table index for the accel tree ctrl
|
||||||
// one of the "benefits" of using TreeItemData is that we have to
|
// one of the "benefits" of using TreeItemData is that we have to
|
||||||
// malloc them all, because treectrl destructor will free them all
|
// malloc them all, because treectrl destructor will free them all
|
||||||
|
@ -2699,6 +2838,18 @@ bool MainFrame::InitMore(void)
|
||||||
cb->Hide();
|
cb->Hide();
|
||||||
#endif
|
#endif
|
||||||
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "Filter",wxGenericValidator(& gopts.filter));
|
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));
|
ch=GetValidatedChild<wxChoice,wxGenericValidator>(d, "IFB",wxGenericValidator(& gopts.ifb));
|
||||||
d->Fit();
|
d->Fit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,8 @@ opt_desc opts[] = {
|
||||||
ENUMOPT("Display/Filter", wxTRANSLATE("Full-screen filter to apply"), gopts.filter,
|
ENUMOPT("Display/Filter", wxTRANSLATE("Full-screen filter to apply"), gopts.filter,
|
||||||
wxTRANSLATE("none|2xsai|super2xsai|supereagle|pixelate|advmame|"
|
wxTRANSLATE("none|2xsai|super2xsai|supereagle|pixelate|advmame|"
|
||||||
"bilinear|bilinearplus|scanlines|tvmode|hq2x|lq2x|"
|
"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),
|
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/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),
|
INTOPT ("Display/FullscreenFreq", wxTRANSLATE("Fullscreen mode frequency (0 = any)"), gopts.fs_mode.refresh, 0, 999),
|
||||||
|
|
|
@ -15,6 +15,7 @@ extern struct opts_t {
|
||||||
bool cpu_mmx;
|
bool cpu_mmx;
|
||||||
bool no_osd_status;
|
bool no_osd_status;
|
||||||
int filter;
|
int filter;
|
||||||
|
wxString filter_plugin;
|
||||||
int ifb;
|
int ifb;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
wxVideoMode fs_mode;
|
wxVideoMode fs_mode;
|
||||||
|
|
|
@ -988,9 +988,47 @@ DrawingPanel::DrawingPanel(int _width, int _height) :
|
||||||
pixbuf1(0), pixbuf2(0), rpi(0), nthreads(0)
|
pixbuf1(0), pixbuf2(0), rpi(0), nthreads(0)
|
||||||
{
|
{
|
||||||
memset(delta, 0xff, sizeof(delta));
|
memset(delta, 0xff, sizeof(delta));
|
||||||
|
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);
|
scale = builtin_ff_scale(gopts.filter);
|
||||||
#define out_16 (systemColorDepth == 16)
|
#define out_16 (systemColorDepth == 16)
|
||||||
|
#endif
|
||||||
|
systemColorDepth = 32;
|
||||||
|
}
|
||||||
systemColorDepth = 32;
|
systemColorDepth = 32;
|
||||||
// Intialize color tables
|
// Intialize color tables
|
||||||
#if wxBYTE_ORDER == wxLITTLE_ENDIAN
|
#if wxBYTE_ORDER == wxLITTLE_ENDIAN
|
||||||
|
@ -1149,9 +1187,6 @@ public:
|
||||||
case FF_TV:
|
case FF_TV:
|
||||||
ScanlinesTV32(src, instride, delta, dst, outstride, width, height);
|
ScanlinesTV32(src, instride, delta, dst, outstride, width, height);
|
||||||
break;
|
break;
|
||||||
case FF_HQ2X:
|
|
||||||
hq2x32(src, instride, delta, dst, outstride, width, height);
|
|
||||||
break;
|
|
||||||
case FF_LQ2X:
|
case FF_LQ2X:
|
||||||
lq2x32(src, instride, delta, dst, outstride, width, height);
|
lq2x32(src, instride, delta, dst, outstride, width, height);
|
||||||
break;
|
break;
|
||||||
|
@ -1161,15 +1196,52 @@ public:
|
||||||
case FF_SIMPLE3X:
|
case FF_SIMPLE3X:
|
||||||
Simple3x32(src, instride, delta, dst, outstride, width, height);
|
Simple3x32(src, instride, delta, dst, outstride, width, height);
|
||||||
break;
|
break;
|
||||||
case FF_HQ3X:
|
|
||||||
hq3x32(src, instride, delta, dst, outstride, width, height);
|
|
||||||
break;
|
|
||||||
case FF_SIMPLE4X:
|
case FF_SIMPLE4X:
|
||||||
Simple4x32(src, instride, delta, dst, outstride, width, height);
|
Simple4x32(src, instride, delta, dst, outstride, width, height);
|
||||||
break;
|
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:
|
case FF_HQ4X:
|
||||||
hq4x32(src, instride, delta, dst, outstride, width, height);
|
hq4x32(src, instride, delta, dst, outstride, width, height);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -508,6 +508,7 @@ protected:
|
||||||
FilterThread *threads;
|
FilterThread *threads;
|
||||||
int nthreads;
|
int nthreads;
|
||||||
wxSemaphore filt_done;
|
wxSemaphore filt_done;
|
||||||
|
wxDynamicLibrary filt_plugin;
|
||||||
const RENDER_PLUGIN_INFO *rpi; // also flag indicating plugin loaded
|
const RENDER_PLUGIN_INFO *rpi; // also flag indicating plugin loaded
|
||||||
// largest buffer required is 32-bit * (max width + 1) * (max height + 2)
|
// largest buffer required is 32-bit * (max width + 1) * (max height + 2)
|
||||||
u8 delta[257 * 4 * 226];
|
u8 delta[257 * 4 * 226];
|
||||||
|
|
|
@ -2663,10 +2663,27 @@
|
||||||
<item>HQ 3x</item>
|
<item>HQ 3x</item>
|
||||||
<item>Simple 4x</item>
|
<item>Simple 4x</item>
|
||||||
<item>HQ 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>
|
</content>
|
||||||
</object>
|
</object>
|
||||||
<flag>wxALL|wxEXPAND</flag>
|
<flag>wxALL|wxEXPAND</flag>
|
||||||
<border>5</border>
|
<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>
|
</object>
|
||||||
<object class="sizeritem">
|
<object class="sizeritem">
|
||||||
<object class="wxStaticText">
|
<object class="wxStaticText">
|
||||||
|
|
Loading…
Reference in New Issue