Added AStyle 2.05.1 to the wx pre-build events and formatted the wx gui code.

Options used:
--style=allman --indent=tab=4 --align-pointer=type --align-reference=name --break-blocks --pad-oper --pad-header --unpad-paren --delete-empty-lines --break-closing-brackets --keep-one-line-blocks --keep-one-line-statements --convert-tabs --remove-comment-prefix --mode=c
This commit is contained in:
skidau 2015-05-15 02:16:18 +00:00
parent 3f0a5adf94
commit f2274347ae
32 changed files with 16351 additions and 13542 deletions

View File

@ -46,14 +46,14 @@
<GenerateManifest>true</GenerateManifest>
<OutDir>$(ProjectDir)$(Platform)\$(Configuration)\Binary\</OutDir>
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\Build\$(ProjectName)\</IntDir>
<IncludePath>..\..\..\dependencies\openal-soft\include\AL\;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
<IncludePath>..\..\..\dependencies\openal-soft\include\AL;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)$(Platform)\$(Configuration)\Binary\</OutDir>
<IntDir>$(ProjectDir)$(Platform)\$(Configuration)\Build\$(ProjectName)\</IntDir>
<GenerateManifest>true</GenerateManifest>
<IncludePath>..\..\..\dependencies\openal-soft\include\AL\;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
<IncludePath>..\..\..\dependencies\openal-soft\include\AL;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vc_mswud_x64\</OutDir>

File diff suppressed because it is too large Load Diff

View File

@ -4,16 +4,16 @@
class BasicDrawingPanel : public DrawingPanel, public wxPanel
{
public:
BasicDrawingPanel(wxWindow *parent, int _width, int _height);
wxWindow *GetWindow() { return this; }
void Delete() { Destroy(); }
BasicDrawingPanel(wxWindow* parent, int _width, int _height);
wxWindow* GetWindow() { return this; }
void Delete() { Destroy(); }
protected:
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void DrawArea(wxWindowDC &dc);
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void DrawArea(wxWindowDC &dc);
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#ifndef NO_OGL
@ -22,25 +22,25 @@ protected:
class GLDrawingPanel : public DrawingPanel, public wxGLCanvas
{
public:
GLDrawingPanel(wxWindow *parent, int _width, int _height);
virtual ~GLDrawingPanel();
wxWindow *GetWindow() { return this; }
void Delete() { Destroy(); }
GLDrawingPanel(wxWindow* parent, int _width, int _height);
virtual ~GLDrawingPanel();
wxWindow* GetWindow() { return this; }
void Delete() { Destroy(); }
protected:
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void OnSize(wxSizeEvent &);
void DrawArea(wxWindowDC &dc);
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void OnSize(wxSizeEvent &);
void DrawArea(wxWindowDC &dc);
#if wxCHECK_VERSION(2,9,0) || !defined(__WXMAC__)
wxGLContext ctx;
wxGLContext ctx;
#endif
bool did_init;
void Init();
GLuint texid, vlist;
int texsize;
bool did_init;
void Init();
GLuint texid, vlist;
int texsize;
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#endif
@ -48,18 +48,18 @@ protected:
class DXDrawingPanel : public DrawingPanel, public wxPanel
{
public:
DXDrawingPanel(wxWindow *parent, int _width, int _height);
wxWindow *GetWindow() { return this; }
void Delete() { Destroy(); }
DXDrawingPanel(wxWindow* parent, int _width, int _height);
wxWindow* GetWindow() { return this; }
void Delete() { Destroy(); }
protected:
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void DrawArea(wxWindowDC&);
bool did_init;
void Init();
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void DrawArea(wxWindowDC &);
bool did_init;
void Init();
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#endif
@ -69,18 +69,18 @@ protected:
class CairoDrawingPanel : public DrawingPanel, public wxPanel
{
public:
CairoDrawingPanel(wxWindow *parent, int _width, int _height);
~CairoDrawingPanel();
wxWindow *GetWindow() { return this; }
void Delete() { Destroy(); }
CairoDrawingPanel(wxWindow* parent, int _width, int _height);
~CairoDrawingPanel();
wxWindow* GetWindow() { return this; }
void Delete() { Destroy(); }
protected:
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void DrawArea(wxWindowDC&);
cairo_surface_t *conv_surf;
void PaintEv2(wxPaintEvent &ev) { PaintEv(ev); }
void DrawArea(wxWindowDC &);
cairo_surface_t* conv_surf;
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
DECLARE_CLASS()
DECLARE_EVENT_TABLE()
};
#endif

View File

@ -24,7 +24,7 @@ private:
LPDIRECTSOUNDNOTIFY dsbNotify;
HANDLE dsbEvent;
WAVEFORMATEX wfx; // Primary buffer wave format
int soundBufferLen;
int soundBufferLen;
int soundBufferTotalLen;
unsigned int soundNextPosition;
@ -36,7 +36,7 @@ public:
void pause(); // pause the secondary sound buffer
void reset(); // stop and reset the secondary sound buffer
void resume(); // resume the secondary sound buffer
void write(u16 * finalWave, int length); // write the emulated sound to the secondary sound buffer
void write(u16* finalWave, int length); // write the emulated sound to the secondary sound buffer
};
@ -47,7 +47,6 @@ DirectSound::DirectSound()
dsbSecondary = NULL;
dsbNotify = NULL;
dsbEvent = NULL;
soundBufferTotalLen = 14700;
soundNextPosition = 0;
}
@ -55,23 +54,28 @@ DirectSound::DirectSound()
DirectSound::~DirectSound()
{
if(dsbNotify) {
if (dsbNotify)
{
dsbNotify->Release();
dsbNotify = NULL;
}
if(dsbEvent) {
if (dsbEvent)
{
CloseHandle(dsbEvent);
dsbEvent = NULL;
}
if(pDirectSound) {
if(dsbPrimary) {
if (pDirectSound)
{
if (dsbPrimary)
{
dsbPrimary->Release();
dsbPrimary = NULL;
}
if(dsbSecondary) {
if (dsbSecondary)
{
dsbSecondary->Release();
dsbSecondary = NULL;
}
@ -88,39 +92,47 @@ bool DirectSound::init(long sampleRate)
DWORD freq;
DSBUFFERDESC dsbdesc;
int i;
hr = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound8, (LPVOID*)&pDirectSound);
hr = CoCreateInstance( CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound8, (LPVOID *)&pDirectSound );
if( hr != S_OK ) {
if (hr != S_OK)
{
wxLogError(_("Cannot create DirectSound %08x"), hr);
return false;
}
GUID dev;
if(gopts.audio_dev.empty())
if (gopts.audio_dev.empty())
dev = DSDEVID_DefaultPlayback;
else
CLSIDFromString(const_cast<wxChar *>(gopts.audio_dev.wx_str()), &dev);
pDirectSound->Initialize( &dev );
if( hr != DS_OK ) {
CLSIDFromString(const_cast<wxChar*>(gopts.audio_dev.wx_str()), &dev);
pDirectSound->Initialize(&dev);
if (hr != DS_OK)
{
wxLogError(_("Cannot create DirectSound %08x"), hr);
return false;
}
if( FAILED( hr = pDirectSound->SetCooperativeLevel( (HWND)wxGetApp().frame->GetHandle(), DSSCL_EXCLUSIVE ) ) ) {
if (FAILED(hr = pDirectSound->SetCooperativeLevel((HWND)wxGetApp().frame->GetHandle(), DSSCL_EXCLUSIVE)))
{
wxLogError(_("Cannot SetCooperativeLevel %08x"), hr);
return false;
}
// Create primary sound buffer
ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
if( !gopts.dsound_hw_accel ) {
if (!gopts.dsound_hw_accel)
{
dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
}
if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbPrimary, NULL ) ) ) {
if (FAILED(hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbPrimary, NULL)))
{
wxLogError(_("Cannot CreateSoundBuffer %08x"), hr);
return false;
}
@ -128,11 +140,10 @@ bool DirectSound::init(long sampleRate)
freq = sampleRate;
// calculate the number of samples per frame first
// then multiply it with the size of a sample frame (16 bit * stereo)
soundBufferLen = ( freq / 60 ) * 4;
soundBufferLen = (freq / 60) * 4;
soundBufferTotalLen = soundBufferLen * 10;
soundNextPosition = 0;
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = freq;
@ -140,42 +151,50 @@ bool DirectSound::init(long sampleRate)
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
if( FAILED( hr = dsbPrimary->SetFormat( &wfx ) ) ) {
wxLogError( _("CreateSoundBuffer(primary) failed %08x"), hr );
if (FAILED(hr = dsbPrimary->SetFormat(&wfx)))
{
wxLogError(_("CreateSoundBuffer(primary) failed %08x"), hr);
return false;
}
// Create secondary sound buffer
ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS;
if( !gopts.dsound_hw_accel ) {
if (!gopts.dsound_hw_accel)
{
dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
}
dsbdesc.dwBufferBytes = soundBufferTotalLen;
dsbdesc.lpwfxFormat = &wfx;
if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbSecondary, NULL ) ) ) {
wxLogError(_("CreateSoundBuffer(secondary) failed %08x"), hr );
if (FAILED(hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL)))
{
wxLogError(_("CreateSoundBuffer(secondary) failed %08x"), hr);
return false;
}
if( FAILED( hr = dsbSecondary->SetCurrentPosition( 0 ) ) ) {
wxLogError(_("dsbSecondary->SetCurrentPosition failed %08x"), hr );
if (FAILED(hr = dsbSecondary->SetCurrentPosition(0)))
{
wxLogError(_("dsbSecondary->SetCurrentPosition failed %08x"), hr);
return false;
}
if( SUCCEEDED( hr = dsbSecondary->QueryInterface( IID_IDirectSoundNotify8, (LPVOID*)&dsbNotify ) ) ) {
dsbEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if (SUCCEEDED(hr = dsbSecondary->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*)&dsbNotify)))
{
dsbEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
DSBPOSITIONNOTIFY notify[10];
for( i = 0; i < 10; i++ ) {
for (i = 0; i < 10; i++)
{
notify[i].dwOffset = i * soundBufferLen;
notify[i].hEventNotify = dsbEvent;
}
if( FAILED( dsbNotify->SetNotificationPositions( 10, notify ) ) ) {
if (FAILED(dsbNotify->SetNotificationPositions(10, notify)))
{
dsbNotify->Release();
dsbNotify = NULL;
CloseHandle(dsbEvent);
@ -183,10 +202,10 @@ bool DirectSound::init(long sampleRate)
}
}
// Play primary buffer
if( FAILED( hr = dsbPrimary->Play( 0, 0, DSBPLAY_LOOPING ) ) ) {
wxLogError( _("Cannot Play primary %08x"), hr );
if (FAILED(hr = dsbPrimary->Play(0, 0, DSBPLAY_LOOPING)))
{
wxLogError(_("Cannot Play primary %08x"), hr);
return false;
}
@ -196,40 +215,36 @@ bool DirectSound::init(long sampleRate)
void DirectSound::pause()
{
if( dsbSecondary == NULL ) return;
if (dsbSecondary == NULL) return;
DWORD status;
dsbSecondary->GetStatus(&status);
dsbSecondary->GetStatus( &status );
if( status & DSBSTATUS_PLAYING ) dsbSecondary->Stop();
if (status & DSBSTATUS_PLAYING) dsbSecondary->Stop();
}
void DirectSound::reset()
{
if( dsbSecondary == NULL ) return;
if (dsbSecondary == NULL) return;
dsbSecondary->Stop();
dsbSecondary->SetCurrentPosition( 0 );
dsbSecondary->SetCurrentPosition(0);
soundNextPosition = 0;
}
void DirectSound::resume()
{
if( dsbSecondary == NULL ) return;
if (dsbSecondary == NULL) return;
dsbSecondary->Play( 0, 0, DSBPLAY_LOOPING );
dsbSecondary->Play(0, 0, DSBPLAY_LOOPING);
}
void DirectSound::write(u16 * finalWave, int length)
void DirectSound::write(u16* finalWave, int length)
{
if(!pDirectSound) return;
if (!pDirectSound) return;
HRESULT hr;
DWORD status = 0;
@ -239,88 +254,103 @@ void DirectSound::write(u16 * finalWave, int length)
LPVOID lpvPtr2;
DWORD dwBytes2 = 0;
if (!speedup && throttle && !gba_joybus_active) {
if (!speedup && throttle && !gba_joybus_active)
{
hr = dsbSecondary->GetStatus(&status);
if( status & DSBSTATUS_PLAYING ) {
if( !soundPaused ) {
while( true ) {
if (status & DSBSTATUS_PLAYING)
{
if (!soundPaused)
{
while (true)
{
dsbSecondary->GetCurrentPosition(&play, NULL);
int BufferLeft = ((soundNextPosition <= play) ?
play - soundNextPosition :
soundBufferTotalLen - soundNextPosition + play);
int BufferLeft = ((soundNextPosition <= play) ?
play - soundNextPosition :
soundBufferTotalLen - soundNextPosition + play);
if(BufferLeft > soundBufferLen)
{
if (BufferLeft > soundBufferTotalLen - (soundBufferLen * 3))
soundBufferLow = true;
break;
}
soundBufferLow = false;
if (BufferLeft > soundBufferLen)
{
if (BufferLeft > soundBufferTotalLen - (soundBufferLen * 3))
soundBufferLow = true;
if(dsbEvent) {
WaitForSingleObject(dsbEvent, 50);
}
}
break;
}
soundBufferLow = false;
if (dsbEvent)
{
WaitForSingleObject(dsbEvent, 50);
}
}
}
}/* else {
// TODO: remove?
setsoundPaused(true);
}*/
}
// TODO: remove?
setsoundPaused(true);
}*/
}
// Obtain memory address of write block.
// This will be in two parts if the block wraps around.
if( DSERR_BUFFERLOST == ( hr = dsbSecondary->Lock(
soundNextPosition,
soundBufferLen,
&lpvPtr1,
&dwBytes1,
&lpvPtr2,
&dwBytes2,
0 ) ) ) {
// If DSERR_BUFFERLOST is returned, restore and retry lock.
dsbSecondary->Restore();
hr = dsbSecondary->Lock(
soundNextPosition,
soundBufferLen,
&lpvPtr1,
&dwBytes1,
&lpvPtr2,
&dwBytes2,
0 );
if (DSERR_BUFFERLOST == (hr = dsbSecondary->Lock(
soundNextPosition,
soundBufferLen,
&lpvPtr1,
&dwBytes1,
&lpvPtr2,
&dwBytes2,
0)))
{
// If DSERR_BUFFERLOST is returned, restore and retry lock.
dsbSecondary->Restore();
hr = dsbSecondary->Lock(
soundNextPosition,
soundBufferLen,
&lpvPtr1,
&dwBytes1,
&lpvPtr2,
&dwBytes2,
0);
}
soundNextPosition += soundBufferLen;
soundNextPosition = soundNextPosition % soundBufferTotalLen;
if( SUCCEEDED( hr ) ) {
if (SUCCEEDED(hr))
{
// Write to pointers.
CopyMemory( lpvPtr1, finalWave, dwBytes1 );
if ( lpvPtr2 ) {
CopyMemory( lpvPtr2, finalWave + dwBytes1, dwBytes2 );
CopyMemory(lpvPtr1, finalWave, dwBytes1);
if (lpvPtr2)
{
CopyMemory(lpvPtr2, finalWave + dwBytes1, dwBytes2);
}
// Release the data back to DirectSound.
hr = dsbSecondary->Unlock( lpvPtr1, dwBytes1, lpvPtr2, dwBytes2 );
} else {
wxLogError(_("dsbSecondary->Lock() failed: %08x"), hr );
hr = dsbSecondary->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
}
else
{
wxLogError(_("dsbSecondary->Lock() failed: %08x"), hr);
return;
}
}
SoundDriver *newDirectSound()
SoundDriver* newDirectSound()
{
return new DirectSound();
}
struct devnames {
wxArrayString *names, *ids;
struct devnames
{
wxArrayString* names, *ids;
};
static BOOL CALLBACK DSEnumCB(LPGUID guid, LPCTSTR desc, LPCTSTR drvnam, LPVOID user)
{
devnames *dn = (devnames *)user;
devnames* dn = (devnames*)user;
dn->names->push_back(desc);
WCHAR buf[32 + 4 + 2 + 1]; // hex digits + "-" + "{}" + \0
StringFromGUID2(*guid, buf, sizeof(buf));

View File

@ -6,77 +6,77 @@
// most 16-bit filters require space in src rounded up to u32
// those that take delta take 1 src line of pixels, rounded up to u32 size
// initial value appears to be all-0xff
void Pixelate32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Pixelate(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void Pixelate32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Pixelate(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
// next 3*2 use Init_2xSaI(555|565) and do not take into account
int Init_2xSaI(u32 BitFormat);
// endianness or bit shift variables in init.
// next 4*2 may be MMX-accelerated
void _2xSaI32(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void _2xSaI(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void _2xSaI32(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
void _2xSaI(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
// void Scale_2xSaI(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Super2xSaI32(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void Super2xSaI(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void SuperEagle32(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void SuperEagle(u8 *src, u32 spitch, u8 *delta, u8 *dst, u32 dstp, int w, int h);
void AdMame2x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void AdMame2x(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Super2xSaI32(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
void Super2xSaI(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
void SuperEagle32(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
void SuperEagle(u8* src, u32 spitch, u8* delta, u8* dst, u32 dstp, int w, int h);
void AdMame2x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void AdMame2x(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// next 4 convert to rgb24 in internal buffers first, and then back again
void Bilinear32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Bilinear(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void BilinearPlus32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void BilinearPlus(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Scanlines32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Scanlines(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void ScanlinesTV32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Bilinear32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Bilinear(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void BilinearPlus32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void BilinearPlus(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Scanlines32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Scanlines(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void ScanlinesTV32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// "TV" here means each pixel is faded horizontally & vertically rather than
// inserting black scanlines
// this depends on RGB_LOW_BITS_MASK
extern int RGB_LOW_BITS_MASK;
void ScanlinesTV(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void ScanlinesTV(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// next 2 require calling hq2x_init first and whenever bpp changes
void hq2x_init(unsigned bpp);
void hq2x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq2x(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void lq2x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void lq2x(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq2x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void hq2x(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void lq2x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void lq2x(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// the simple ones could greatly benefit from correct usage of preprocessor..
// in any case, they are worthless, since all renderers do "simple" or
// better by default
void Simple2x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Simple2x(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Simple3x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Simple3x(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Simple4x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Simple4x(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void Simple2x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Simple2x(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Simple3x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Simple3x(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Simple4x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void Simple4x(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// note: 16-bit input for asm version only!
void hq3x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq3x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// this takes 32-bit input
// (by converting to 16-bit first in asm version)
void hq3x32_32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq3x16(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq3x32_32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void hq3x16(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// note: 16-bit input for asm version only!
void hq4x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq4x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// this takes 32-bit input
// (by converting to 16-bit first in asm version)
void hq4x32_32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq4x16(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void hq4x32_32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void hq4x16(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void xbrz2x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void xbrz3x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void xbrz4x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void xbrz5x32(u8 *src, u32 spitch, u8 *, u8 *dst, u32 dstp, int w, int h);
void xbrz2x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void xbrz3x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void xbrz4x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
void xbrz5x32(u8* src, u32 spitch, u8*, u8* dst, u32 dstp, int w, int h);
// call ifc to ignore previous frame / when starting new
void InterframeCleanup();
// all 4 are MMX-accelerated if enabled
void SmartIB(u8 *src, u32 spitch, int width, int height);
void SmartIB32(u8 *src, u32 spitch, int width, int height);
void MotionBlurIB(u8 *src, u32 spitch, int width, int height);
void MotionBlurIB32(u8 *src, u32 spitch, int width, int height);
void SmartIB(u8 *src, u32 spitch, int width, int starty, int height);
void SmartIB32(u8 *src, u32 spitch, int width, int starty, int height);
void MotionBlurIB(u8 *src, u32 spitch, int width, int starty, int height);
void MotionBlurIB32(u8 *src, u32 spitch, int width, int starty, int height);
void SmartIB(u8* src, u32 spitch, int width, int height);
void SmartIB32(u8* src, u32 spitch, int width, int height);
void MotionBlurIB(u8* src, u32 spitch, int width, int height);
void MotionBlurIB32(u8* src, u32 spitch, int width, int height);
void SmartIB(u8* src, u32 spitch, int width, int starty, int height);
void SmartIB32(u8* src, u32 spitch, int width, int starty, int height);
void MotionBlurIB(u8* src, u32 spitch, int width, int starty, int height);
void MotionBlurIB32(u8* src, u32 spitch, int width, int starty, int height);
#endif /* FILTERS_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -46,19 +46,19 @@ public:
void pause(); // pause the secondary sound buffer
void reset(); // stop and reset the secondary sound buffer
void resume(); // play/resume the secondary sound buffer
void write(u16 * finalWave, int length); // write the emulated sound to a sound buffer
void write(u16* finalWave, int length); // write the emulated sound to a sound buffer
private:
static OPENALFNTABLE ALFunction;
bool initialized;
bool buffersLoaded;
ALCdevice *device;
ALCcontext *context;
ALuint *buffer;
ALCdevice* device;
ALCcontext* context;
ALuint* buffer;
ALuint tempBuffer;
ALuint source;
int freq;
int soundBufferLen;
int soundBufferLen;
#ifdef LOGALL
void debugState();
@ -71,8 +71,8 @@ OpenAL::OpenAL()
buffersLoaded = false;
device = NULL;
context = NULL;
buffer = (ALuint*)malloc( gopts.audio_buffers * sizeof( ALuint ) );
memset( buffer, 0, gopts.audio_buffers * sizeof( ALuint ) );
buffer = (ALuint*)malloc(gopts.audio_buffers * sizeof(ALuint));
memset(buffer, 0, gopts.audio_buffers * sizeof(ALuint));
tempBuffer = 0;
source = 0;
}
@ -80,33 +80,26 @@ OpenAL::OpenAL()
OpenAL::~OpenAL()
{
if( !initialized ) return;
if (!initialized) return;
ALFunction.alSourceStop( source );
ALFunction.alSourceStop(source);
ASSERT_SUCCESS;
ALFunction.alSourcei( source, AL_BUFFER, 0 );
ALFunction.alSourcei(source, AL_BUFFER, 0);
ASSERT_SUCCESS;
ALFunction.alDeleteSources( 1, &source );
ALFunction.alDeleteSources(1, &source);
ASSERT_SUCCESS;
ALFunction.alDeleteBuffers( gopts.audio_buffers, buffer );
ALFunction.alDeleteBuffers(gopts.audio_buffers, buffer);
ASSERT_SUCCESS;
free( buffer );
ALFunction.alcMakeContextCurrent( NULL );
free(buffer);
ALFunction.alcMakeContextCurrent(NULL);
// Wine incorrectly returns ALC_INVALID_VALUE
// and then fails the rest of these functions as well
// so there will be a leak under Wine, but that's a bug in Wine, not
// this code
//ASSERT_SUCCESS;
ALFunction.alcDestroyContext( context );
ALFunction.alcDestroyContext(context);
//ASSERT_SUCCESS;
ALFunction.alcCloseDevice( device );
ALFunction.alcCloseDevice(device);
//ASSERT_SUCCESS;
ALFunction.alGetError(); // reset error state
}
@ -114,81 +107,79 @@ OpenAL::~OpenAL()
#ifdef LOGALL
void OpenAL::debugState()
{
ALint value = 0;
ALFunction.alGetSourcei( source, AL_SOURCE_STATE, &value );
ALFunction.alGetSourcei(source, AL_SOURCE_STATE, &value);
ASSERT_SUCCESS;
winlog(" soundPaused = %i\n", soundPaused);
winlog(" Source:\n");
winlog(" State: ");
winlog( " soundPaused = %i\n", soundPaused );
winlog( " Source:\n" );
winlog( " State: " );
switch( value )
switch (value)
{
case AL_INITIAL:
winlog( "AL_INITIAL\n" );
winlog("AL_INITIAL\n");
break;
case AL_PLAYING:
winlog( "AL_PLAYING\n" );
winlog("AL_PLAYING\n");
break;
case AL_PAUSED:
winlog( "AL_PAUSED\n" );
winlog("AL_PAUSED\n");
break;
case AL_STOPPED:
winlog( "AL_STOPPED\n" );
winlog("AL_STOPPED\n");
break;
default:
winlog( "!unknown!\n" );
winlog("!unknown!\n");
break;
}
ALFunction.alGetSourcei( source, AL_BUFFERS_QUEUED, &value );
ALFunction.alGetSourcei(source, AL_BUFFERS_QUEUED, &value);
ASSERT_SUCCESS;
winlog( " Buffers in queue: %i\n", value );
ALFunction.alGetSourcei( source, AL_BUFFERS_PROCESSED, &value );
winlog(" Buffers in queue: %i\n", value);
ALFunction.alGetSourcei(source, AL_BUFFERS_PROCESSED, &value);
ASSERT_SUCCESS;
winlog( " Buffers processed: %i\n", value );
winlog(" Buffers processed: %i\n", value);
}
#endif
bool OpenAL::init(long sampleRate)
{
winlog( "OpenAL::init\n" );
assert( initialized == false );
winlog("OpenAL::init\n");
assert(initialized == false);
if( !LoadOAL() ) {
wxLogError( _("OpenAL library could not be found on your system. Please install the runtime from http://openal.org") );
if (!LoadOAL())
{
wxLogError(_("OpenAL library could not be found on your system. Please install the runtime from http://openal.org"));
return false;
}
if( !gopts.audio_dev.empty() ) {
device = ALFunction.alcOpenDevice( gopts.audio_dev.mb_str() );
} else {
device = ALFunction.alcOpenDevice( NULL );
if (!gopts.audio_dev.empty())
{
device = ALFunction.alcOpenDevice(gopts.audio_dev.mb_str());
}
else
{
device = ALFunction.alcOpenDevice(NULL);
}
assert( device != NULL );
context = ALFunction.alcCreateContext( device, NULL );
assert( context != NULL );
ALCboolean retVal = ALFunction.alcMakeContextCurrent( context );
assert( ALC_TRUE == retVal );
ALFunction.alGenBuffers( gopts.audio_buffers, buffer );
assert(device != NULL);
context = ALFunction.alcCreateContext(device, NULL);
assert(context != NULL);
ALCboolean retVal = ALFunction.alcMakeContextCurrent(context);
assert(ALC_TRUE == retVal);
ALFunction.alGenBuffers(gopts.audio_buffers, buffer);
ASSERT_SUCCESS;
ALFunction.alGenSources( 1, &source );
ALFunction.alGenSources(1, &source);
ASSERT_SUCCESS;
freq = sampleRate;
// calculate the number of samples per frame first
// then multiply it with the size of a sample frame (16 bit * stereo)
soundBufferLen = ( freq / 60 ) * 4;
soundBufferLen = (freq / 60) * 4;
initialized = true;
return true;
}
@ -196,142 +187,164 @@ bool OpenAL::init(long sampleRate)
void OpenAL::resume()
{
if( !initialized ) return;
winlog( "OpenAL::resume\n" );
if( !buffersLoaded ) return;
if (!initialized) return;
winlog("OpenAL::resume\n");
if (!buffersLoaded) return;
debugState();
ALint sourceState = 0;
ALFunction.alGetSourcei( source, AL_SOURCE_STATE, &sourceState );
ALFunction.alGetSourcei(source, AL_SOURCE_STATE, &sourceState);
ASSERT_SUCCESS;
if( sourceState != AL_PLAYING ) {
ALFunction.alSourcePlay( source );
if (sourceState != AL_PLAYING)
{
ALFunction.alSourcePlay(source);
ASSERT_SUCCESS;
}
debugState();
}
void OpenAL::pause()
{
if( !initialized ) return;
winlog( "OpenAL::pause\n" );
if( !buffersLoaded ) return;
if (!initialized) return;
winlog("OpenAL::pause\n");
if (!buffersLoaded) return;
debugState();
ALint sourceState = 0;
ALFunction.alGetSourcei( source, AL_SOURCE_STATE, &sourceState );
ALFunction.alGetSourcei(source, AL_SOURCE_STATE, &sourceState);
ASSERT_SUCCESS;
if( sourceState == AL_PLAYING ) {
ALFunction.alSourcePause( source );
if (sourceState == AL_PLAYING)
{
ALFunction.alSourcePause(source);
ASSERT_SUCCESS;
}
debugState();
}
void OpenAL::reset()
{
if( !initialized ) return;
winlog( "OpenAL::reset\n" );
if( !buffersLoaded ) return;
debugState();
if (!initialized) return;
winlog("OpenAL::reset\n");
if (!buffersLoaded) return;
debugState();
ALint sourceState = 0;
ALFunction.alGetSourcei( source, AL_SOURCE_STATE, &sourceState );
ALFunction.alGetSourcei(source, AL_SOURCE_STATE, &sourceState);
ASSERT_SUCCESS;
if( sourceState != AL_STOPPED ) {
ALFunction.alSourceStop( source );
if (sourceState != AL_STOPPED)
{
ALFunction.alSourceStop(source);
ASSERT_SUCCESS;
}
debugState();
}
void OpenAL::write(u16 * finalWave, int length)
void OpenAL::write(u16* finalWave, int length)
{
if( !initialized ) return;
winlog( "OpenAL::write\n" );
if (!initialized) return;
winlog("OpenAL::write\n");
debugState();
ALint sourceState = 0;
ALint nBuffersProcessed = 0;
if( !buffersLoaded ) {
if (!buffersLoaded)
{
// ==initial buffer filling==
winlog( " initial buffer filling\n" );
for( int i = 0 ; i < gopts.audio_buffers ; i++ ) {
winlog(" initial buffer filling\n");
for (int i = 0 ; i < gopts.audio_buffers ; i++)
{
// Filling the buffers explicitly with silence would be cleaner,
// but the very first sample is usually silence anyway.
ALFunction.alBufferData( buffer[i], AL_FORMAT_STEREO16, finalWave, soundBufferLen, freq );
ALFunction.alBufferData(buffer[i], AL_FORMAT_STEREO16, finalWave, soundBufferLen, freq);
ASSERT_SUCCESS;
}
ALFunction.alSourceQueueBuffers( source, gopts.audio_buffers, buffer );
ALFunction.alSourceQueueBuffers(source, gopts.audio_buffers, buffer);
ASSERT_SUCCESS;
buffersLoaded = true;
} else {
}
else
{
// ==normal buffer refreshing==
nBuffersProcessed = 0;
ALFunction.alGetSourcei( source, AL_BUFFERS_PROCESSED, &nBuffersProcessed );
ALFunction.alGetSourcei(source, AL_BUFFERS_PROCESSED, &nBuffersProcessed);
ASSERT_SUCCESS;
if( nBuffersProcessed == gopts.audio_buffers ) {
if (nBuffersProcessed == gopts.audio_buffers)
{
// we only want to know about it when we are emulating at full speed or faster:
if( ( throttle >= 100 ) || ( throttle == 0 ) ) {
if( systemVerbose & VERBOSE_SOUNDOUTPUT ) {
if ((throttle >= 100) || (throttle == 0))
{
if (systemVerbose & VERBOSE_SOUNDOUTPUT)
{
static unsigned int i = 0;
log( "OpenAL: Buffers were not refilled fast enough (i=%i)\n", i++ );
log("OpenAL: Buffers were not refilled fast enough (i=%i)\n", i++);
}
}
}
if (!speedup && throttle && !gba_joybus_active) {
if (!speedup && throttle && !gba_joybus_active)
{
// wait until at least one buffer has finished
while( nBuffersProcessed == 0 ) {
winlog( " waiting...\n" );
while (nBuffersProcessed == 0)
{
winlog(" waiting...\n");
// wait for about half the time one buffer needs to finish
// unoptimized: ( sourceBufferLen * 1000 ) / ( freq * 2 * 2 ) * 1/2
wxMilliSleep( soundBufferLen / ( freq >> 7 ) );
ALFunction.alGetSourcei( source, AL_BUFFERS_PROCESSED, &nBuffersProcessed );
wxMilliSleep(soundBufferLen / (freq >> 7));
ALFunction.alGetSourcei(source, AL_BUFFERS_PROCESSED, &nBuffersProcessed);
ASSERT_SUCCESS;
}
} else {
if( nBuffersProcessed == 0 ) return;
}
else
{
if (nBuffersProcessed == 0) return;
}
assert( nBuffersProcessed > 0 );
assert(nBuffersProcessed > 0);
// unqueue buffer
tempBuffer = 0;
ALFunction.alSourceUnqueueBuffers( source, 1, &tempBuffer );
ALFunction.alSourceUnqueueBuffers(source, 1, &tempBuffer);
ASSERT_SUCCESS;
// refill buffer
ALFunction.alBufferData( tempBuffer, AL_FORMAT_STEREO16, finalWave, soundBufferLen, freq );
ALFunction.alBufferData(tempBuffer, AL_FORMAT_STEREO16, finalWave, soundBufferLen, freq);
ASSERT_SUCCESS;
// requeue buffer
ALFunction.alSourceQueueBuffers( source, 1, &tempBuffer );
ALFunction.alSourceQueueBuffers(source, 1, &tempBuffer);
ASSERT_SUCCESS;
}
// start playing the source if necessary
ALFunction.alGetSourcei( source, AL_SOURCE_STATE, &sourceState );
ALFunction.alGetSourcei(source, AL_SOURCE_STATE, &sourceState);
ASSERT_SUCCESS;
if( !soundPaused && ( sourceState != AL_PLAYING ) ) {
ALFunction.alSourcePlay( source );
if (!soundPaused && (sourceState != AL_PLAYING))
{
ALFunction.alSourcePlay(source);
ASSERT_SUCCESS;
}
}
SoundDriver *newOpenAL()
SoundDriver* newOpenAL()
{
winlog( "newOpenAL\n" );
winlog("newOpenAL\n");
return new OpenAL();
}
@ -348,23 +361,24 @@ wxDynamicLibrary OpenAL::Lib;
bool OpenAL::LoadOAL()
{
if(!Lib.IsLoaded() &&
if (!Lib.IsLoaded() &&
#ifdef __WXMSW__
// on win32, it's openal32.dll
!Lib.Load(wxT("openal32")) &&
// on win32, it's openal32.dll
!Lib.Load(wxT("openal32")) &&
#else
#ifdef __WXMAC__
// on macosx, it's just plain OpenAL
!Lib.Load(wxT("OpenAL"), wxDL_NOW|wxDL_VERBATIM) &&
// on macosx, it's just plain OpenAL
!Lib.Load(wxT("OpenAL"), wxDL_NOW | wxDL_VERBATIM) &&
#endif
#endif
// on linux, it's libopenal.so
// try standard name on all platforms
!Lib.Load(wxDynamicLibrary::CanonicalizeName(wxT("openal"))))
// on linux, it's libopenal.so
// try standard name on all platforms
!Lib.Load(wxDynamicLibrary::CanonicalizeName(wxT("openal"))))
return false;
#define loadfn(t, n) do { \
if(!(ALFunction.n = (t)Lib.GetSymbol(wxT(#n)))) \
return false; \
if(!(ALFunction.n = (t)Lib.GetSymbol(wxT(#n)))) \
return false; \
} while(0)
//loadfn(LPALENABLE, alEnable);
//loadfn(LPALDISABLE, alDisable);
@ -439,7 +453,6 @@ bool OpenAL::LoadOAL()
//loadfn(LPALDOPPLERVELOCITY, alDopplerVelocity);
//loadfn(LPALSPEEDOFSOUND, alSpeedOfSound);
//loadfn(LPALDISTANCEMODEL, alDistanceModel);
loadfn(LPALCCREATECONTEXT, alcCreateContext);
loadfn(LPALCMAKECONTEXTCURRENT, alcMakeContextCurrent);
//loadfn(LPALCPROCESSCONTEXT, alcProcessContext);
@ -470,18 +483,24 @@ bool GetOALDevices(wxArrayString &names, wxArrayString &ids)
bool OpenAL::GetDevices(wxArrayString &names, wxArrayString &ids)
{
if(!OpenAL::LoadOAL())
if (!OpenAL::LoadOAL())
return false;
#ifdef ALC_DEVICE_SPECIFIER
if(ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_FALSE)
if (ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_FALSE)
// this extension isn't critical to OpenAL operating
return true;
const char *devs = ALFunction.alcGetString(NULL, ALC_DEVICE_SPECIFIER);
while(*devs) {
const char* devs = ALFunction.alcGetString(NULL, ALC_DEVICE_SPECIFIER);
while (*devs)
{
names.push_back(wxString(devs, wxConvLibc));
ids.push_back(names[names.size() - 1]);
devs += strlen(devs) + 1;
}
#else
// should work anyway, but must always use default driver
return true;

View File

@ -15,17 +15,18 @@
// since the ALC typedefs are broken on Mac:
#ifdef __WXMAC__
typedef ALCcontext * (ALC_APIENTRY *LPALCCREATECONTEXT) (ALCdevice *device, const ALCint *attrlist);
typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)( ALCcontext *context );
typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)( ALCcontext *context );
typedef ALCdevice * (ALC_APIENTRY *LPALCOPENDEVICE)( const ALCchar *devicename );
typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)( ALCdevice *device );
typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)( ALCdevice *device, const ALCchar *extname );
typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)( ALCdevice *device, ALCenum param );
typedef ALCcontext* (ALC_APIENTRY* LPALCCREATECONTEXT)(ALCdevice* device, const ALCint* attrlist);
typedef ALCboolean(ALC_APIENTRY* LPALCMAKECONTEXTCURRENT)(ALCcontext* context);
typedef void (ALC_APIENTRY* LPALCDESTROYCONTEXT)(ALCcontext* context);
typedef ALCdevice* (ALC_APIENTRY* LPALCOPENDEVICE)(const ALCchar* devicename);
typedef ALCboolean(ALC_APIENTRY* LPALCCLOSEDEVICE)(ALCdevice* device);
typedef ALCboolean(ALC_APIENTRY* LPALCISEXTENSIONPRESENT)(ALCdevice* device, const ALCchar* extname);
typedef const ALCchar* (ALC_APIENTRY* LPALCGETSTRING)(ALCdevice* device, ALCenum param);
#endif
// no more use of copyrighted OpenAL code just to load the stupid library
struct OPENALFNTABLE {
struct OPENALFNTABLE
{
//LPALENABLE alEnable;
//LPALDISABLE alDisable;
//LPALISENABLED alIsEnabled;

File diff suppressed because it is too large Load Diff

View File

@ -2,94 +2,96 @@
#define WX_OPTS_H
#define NUM_KEYS 21
extern const char * const joynames[NUM_KEYS];
extern const char* const joynames[NUM_KEYS];
extern wxJoyKeyBinding defkeys[NUM_KEYS * 2]; // keyboard + joystick defaults
extern struct opts_t {
opts_t();
// while I would normally put large objects in front to reduce gaps,
// I instead organized this by opts.cpp table order
extern struct opts_t
{
opts_t();
// while I would normally put large objects in front to reduce gaps,
// I instead organized this by opts.cpp table order
/// Display
bool bilinear;
int filter;
wxString filter_plugin;
int ifb;
wxVideoMode fs_mode;
int max_threads;
int render_method;
int video_scale;
bool retain_aspect;
/// Display
bool bilinear;
int filter;
wxString filter_plugin;
int ifb;
wxVideoMode fs_mode;
int max_threads;
int render_method;
int video_scale;
bool retain_aspect;
/// GB
wxString gb_bios;
wxString gbc_bios;
// u16 systemGbPalette[8*3];
bool print_auto_page, print_screen_cap;
wxString gb_rom_dir;
/// GB
wxString gb_bios;
wxString gbc_bios;
// u16 systemGbPalette[8*3];
bool print_auto_page, print_screen_cap;
wxString gb_rom_dir;
wxString gbc_rom_dir;
/// GBA
wxString gba_bios;
int gba_link_type;
wxString link_host;
int link_proto;
bool link_auto;
wxString gba_rom_dir;
/// GBA
wxString gba_bios;
int gba_link_type;
wxString link_host;
int link_proto;
bool link_auto;
wxString gba_rom_dir;
/// General
bool autoload_state, autoload_cheats;
wxString battery_dir;
bool recent_freeze;
wxString recording_dir;
int rewind_interval;
wxString scrshot_dir;
wxString state_dir;
/// General
bool autoload_state, autoload_cheats;
wxString battery_dir;
bool recent_freeze;
wxString recording_dir;
int rewind_interval;
wxString scrshot_dir;
wxString state_dir;
/// Joypad
wxJoyKeyBinding_v joykey_bindings[4][NUM_KEYS];
int autofire_rate;
int default_stick;
/// Joypad
wxJoyKeyBinding_v joykey_bindings[4][NUM_KEYS];
int autofire_rate;
int default_stick;
/// Keyboard
wxAcceleratorEntry_v accels;
/// Keyboard
wxAcceleratorEntry_v accels;
/// Sound
int audio_api;
int audio_buffers;
wxString audio_dev;
int sound_en; // soundSetEnable()
int gba_sound_filter;
bool soundInterpolation;
bool gb_declick;
int gb_echo;
bool gb_effects_config_enabled;
bool dsound_hw_accel;
int gb_stereo;
bool gb_effects_config_surround;
int sound_qual; // soundSetSampleRate() / gbSoundSetSampleRate()
int sound_vol; // soundSetVolume()
bool upmix; // xa2 only
/// Sound
int audio_api;
int audio_buffers;
wxString audio_dev;
int sound_en; // soundSetEnable()
int gba_sound_filter;
bool soundInterpolation;
bool gb_declick;
int gb_echo;
bool gb_effects_config_enabled;
bool dsound_hw_accel;
int gb_stereo;
bool gb_effects_config_surround;
int sound_qual; // soundSetSampleRate() / gbSoundSetSampleRate()
int sound_vol; // soundSetVolume()
bool upmix; // xa2 only
/// Recent
wxFileHistory *recent;
/// Recent
wxFileHistory* recent;
/// wxWindows
// wxWidgets-generated options (opaque)
/// wxWindows
// wxWidgets-generated options (opaque)
} gopts;
extern struct opt_desc {
const wxChar *opt;
const char *cmd;
const wxChar *desc;
wxString *stropt;
int *intopt;
const wxChar *enumvals;
int min, max;
bool *boolopt;
// current configured value
wxString curstr;
int curint;
extern struct opt_desc
{
const wxChar* opt;
const char* cmd;
const wxChar* desc;
wxString* stropt;
int* intopt;
const wxChar* enumvals;
int min, max;
bool* boolopt;
// current configured value
wxString curstr;
int curint;
#define curbool curint
} opts[];
extern const int num_opts;
@ -105,6 +107,6 @@ void load_opts();
// will detect changes and write config if necessary
void update_opts();
// returns true if option name correct; prints error if val invalid
bool opt_set(const wxChar *name, const wxChar *val);
bool opt_set(const wxChar* name, const wxChar* val);
#endif /* WX_OPTS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
cd ..\..\src\wx
cmake.exe -P copy-events.cmake
..\..\..\dependencies\AStyle\bin\astyle --recursive --style=allman --indent=tab=4 --align-pointer=type --align-reference=name --break-blocks --pad-oper --pad-header --unpad-paren --delete-empty-lines --break-closing-brackets --keep-one-line-blocks --keep-one-line-statements --convert-tabs --remove-comment-prefix --mode=c *.cpp *.h
cmake -P copy-events.cmake
..\..\..\dependencies\wxrc xrc\*.xrc -o wxvbam.xrs
..\..\..\dependencies\bin2c wxvbam.xrs builtin-xrc.h builtin_xrs
..\..\..\dependencies\bin2c ../vba-over.ini builtin-over.h builtin_over

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,16 +5,17 @@
#include <wx/caret.h>
// avoid exporting too much stuff
namespace Viewers {
// common to all viewers:
// - track in MainFrame::popups
// - wxID_CLOSE button closes window
// - AutoUpdate checkbox toggles calling Update() every screen refresh
class Viewer : public wxDialog
{
public:
namespace Viewers
{
// common to all viewers:
// - track in MainFrame::popups
// - wxID_CLOSE button closes window
// - AutoUpdate checkbox toggles calling Update() every screen refresh
class Viewer : public wxDialog
{
public:
void CloseDlg(wxCloseEvent &ev);
Viewer(const wxChar *name);
Viewer(const wxChar* name);
virtual ~Viewer() {}
virtual void Update() = 0;
bool auto_update;
@ -26,25 +27,25 @@ namespace Viewers {
void ActiveCtrlScr(wxScrollEvent &ev) { ActiveCtrl(ev); }
void ActiveCtrlSpin(wxSpinEvent &ev) { ActiveCtrl(ev); }
protected:
const wxChar *dname;
protected:
const wxChar* dname;
void SetAutoUpdate(wxCommandEvent &ev) { auto_update = ev.IsChecked(); }
DECLARE_EVENT_TABLE()
};
};
// on errors, abort program
// on errors, abort program
#define baddialog() do { \
wxLogError(_("Unable to load dialog %s from resources"), dname); \
wxGetApp().frame->Close(true); \
return; \
} while(0)
// widgets to use with auto validator
// widgets to use with auto validator
#define getvfld(sv, n, t, v) do { \
t *_w = sv XRCCTRL(*this, n, t); \
if(!_w) \
baddialog(); \
baddialog(); \
_w->SetValidator(v); \
} while(0)
#define getradio(sv, n, var, val) \
@ -57,40 +58,40 @@ namespace Viewers {
#define LoadXRCViewer(t) do { \
wxDialog *d = new Viewers::t##Viewer; \
if(d) \
d->Show(); \
d->Show(); \
} while(0)
// a list box with no horizontal scrollbar and a funky vertical scrollbar:
// range = 1 - 500
// but/pagesz = # of lines shown/# of lines shown - 1
// 1-100 = normal
// 101-200 = 10x semi-stationary
// 201-300 = stationary @ center
// 301-400 = 10x semi-stationary
// 401-500 = normal
// a list box with no horizontal scrollbar and a funky vertical scrollbar:
// range = 1 - 500
// but/pagesz = # of lines shown/# of lines shown - 1
// 1-100 = normal
// 101-200 = 10x semi-stationary
// 201-300 = stationary @ center
// 301-400 = 10x semi-stationary
// 401-500 = normal
// note that since listboxes' size is impossible to control correctly (at
// least with wxGTK), this uses a textctrl to display the items.
// note that since listboxes' size is impossible to control correctly (at
// least with wxGTK), this uses a textctrl to display the items.
class DisList : public wxPanel
{
public:
class DisList : public wxPanel
{
public:
DisList();
// called after init to create subcontrols and size panel
void Refit(int cols);
void MoveSB();
void MoveView(wxScrollEvent &ev);
private:
private:
void RefillNeeded();
public:
public:
// called by parent's refill handler or any other time strings have
// changed
void Refill();
private:
private:
void Resize(wxSizeEvent &ev);
void SetSel();
public:
public:
// make addr visible and then select it
void SetSel(u32 addr);
void UnSel() { issel = false; }
@ -107,7 +108,7 @@ namespace Viewers {
u32 topaddr;
// max address for scrollbar
u32 maxaddr;
protected:
protected:
// assigned to textctrl to avoid mouse input
void MouseEvent(wxMouseEvent &ev) {}
// the subwidgets
@ -122,42 +123,42 @@ namespace Viewers {
bool issel;
DECLARE_DYNAMIC_CLASS() // for xrc
DECLARE_EVENT_TABLE()
};
DECLARE_EVENT_TABLE()
};
BEGIN_DECLARE_EVENT_TYPES()
// event generated when fewer lines available than needed
DECLARE_LOCAL_EVENT_TYPE(EVT_REFILL_NEEDED, 0)
END_DECLARE_EVENT_TYPES()
BEGIN_DECLARE_EVENT_TYPES()
// event generated when fewer lines available than needed
DECLARE_LOCAL_EVENT_TYPE(EVT_REFILL_NEEDED, 0)
END_DECLARE_EVENT_TYPES()
// a hex editor with a funky scrollbar like above
// a hex editor with a funky scrollbar like above
// since it's impossible to exercise this much control over a text
// control, it uses a panel into which text is drawn.
// Maybe some day the above will be changed to do that as well, since
// it allows better mouse control as well.
// since it's impossible to exercise this much control over a text
// control, it uses a panel into which text is drawn.
// Maybe some day the above will be changed to do that as well, since
// it allows better mouse control as well.
class MemView : public wxPanel
{
public:
class MemView : public wxPanel
{
public:
MemView();
// called after init to create subcontrols and size panel
void Refit();
void MoveSB();
void MoveView(wxScrollEvent &ev);
private:
private:
void RefillNeeded();
public:
public:
// called by parent's refill handler or any other time strings have
// changed
void Refill();
private:
private:
void Refill(wxDC &dc);
void RepaintEv(wxPaintEvent &ev);
void Repaint();
void Resize(wxSizeEvent &ev);
public:
public:
// make addr visible
void Show(u32 addr, bool force_update = false);
@ -176,8 +177,8 @@ namespace Viewers {
// after write, these contain write addr and val
u32 writeaddr, writeval;
// when selection is made, this widget is updated w/ addr
wxControl *addrlab;
protected:
wxControl* addrlab;
protected:
// easier than checking maxaddr
int addrlen;
@ -186,7 +187,7 @@ namespace Viewers {
// the subwidgets
wxPanel disp;
wxScrollBar sb;
wxCaret *caret;
wxCaret* caret;
// cached text size
int charheight, charwidth;
// need to know if tc/sb have been Create()d yet
@ -197,167 +198,168 @@ namespace Viewers {
void ShowCaret();
DECLARE_DYNAMIC_CLASS() // for xrc
DECLARE_EVENT_TABLE()
};
DECLARE_EVENT_TABLE()
};
BEGIN_DECLARE_EVENT_TYPES()
// event generated when write occurs
// check writeaddr/writeval/fmt
DECLARE_LOCAL_EVENT_TYPE(EVT_WRITEVAL, 0)
END_DECLARE_EVENT_TYPES()
BEGIN_DECLARE_EVENT_TYPES()
// event generated when write occurs
// check writeaddr/writeval/fmt
DECLARE_LOCAL_EVENT_TYPE(EVT_WRITEVAL, 0)
END_DECLARE_EVENT_TYPES()
// Display a color in a square, with the RGB value to its right.
// Display a color in a square, with the RGB value to its right.
// this is too hard to integrate into xrc (impossible to initialize
// correctly) so no accomodations are made for this
// this is too hard to integrate into xrc (impossible to initialize
// correctly) so no accomodations are made for this
class ColorView : public wxControl
{
public:
ColorView(wxWindow *parent, wxWindowID id);
class ColorView : public wxControl
{
public:
ColorView(wxWindow* parent, wxWindowID id);
void SetRGB(int r, int g, int b);
void GetRGB(int &_r, int &_g, int &_b) { _r = r; _g = g; _b = b; }
protected:
protected:
int r, g, b;
wxPanel *cp;
wxStaticText *rt, *gt, *bt;
};
wxPanel* cp;
wxStaticText* rt, *gt, *bt;
};
#define unkctrl(n, v) do { \
if(!wxXmlResource::Get()->AttachUnknownControl(wxT(n), v, this)) \
baddialog(); \
if(!wxXmlResource::Get()->AttachUnknownControl(wxT(n), v, this)) \
baddialog(); \
} while(0)
#define colorctrl(v, n) do { \
v = new ColorView(this, XRCID(n)); \
if(!v) \
baddialog(); \
baddialog(); \
unkctrl(n, v); \
} while(0)
// Display a small bitmap in jumbopixel style. If a pixel is selected, it
// is highlighted with a border. For wxvbam, no event is generated.
// Instead, a ColorView can be assigned to it, and on selection, that
// widget will be updated to the selected color.
// The whole class can also be derived to add more functionality to the
// button click.
// Display a small bitmap in jumbopixel style. If a pixel is selected, it
// is highlighted with a border. For wxvbam, no event is generated.
// Instead, a ColorView can be assigned to it, and on selection, that
// widget will be updated to the selected color.
// The whole class can also be derived to add more functionality to the
// button click.
// It must be intialized in 3 phases: 2-phase xrc-style (new + Create()),
// and then InitBMP()
// It must be intialized in 3 phases: 2-phase xrc-style (new + Create()),
// and then InitBMP()
class PixView : public wxPanel
{
public:
class PixView : public wxPanel
{
public:
PixView() : wxPanel(), bm(0) {}
bool InitBMP(int w = 8, int h = 8, ColorView *cv = NULL);
bool InitBMP(int w = 8, int h = 8, ColorView* cv = NULL);
// stride is in pixels
// format is rgb24 (aka wxImage format)
// x/y is added to data and returned coords
// if data == NULL, bitmap will be reset to default (all-black)
virtual void SetData(const unsigned char *data, int stride, int x = 0,
int y = 0);
virtual void SetData(const unsigned char* data, int stride, int x = 0,
int y = 0);
// desel if out of displayed range
void SetSel(int x, int y, bool dsel_cview_update = true);
// -1, -1 = no sel
void GetSel(int &x, int &y) {
x = selx < 0 ? -1 : ox + selx;
y = sely < 0 ? -1 : oy + sely;
void GetSel(int &x, int &y)
{
x = selx < 0 ? -1 : ox + selx;
y = sely < 0 ? -1 : oy + sely;
}
ColorView *cview;
protected:
ColorView* cview;
protected:
wxImage im;
wxBitmap *bm;
wxBitmap* bm;
void Redraw(wxPaintEvent &ev);
virtual void SelPoint(wxMouseEvent &ev);
int ox, oy, selx, sely;
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS()
};
};
#define pixview(v, n, w, h, cv) do { \
v = XRCCTRL(*this, n, PixView); \
if(!v) \
baddialog(); \
baddialog(); \
v->InitBMP(w, h, cv); \
} while(0)
// a graphics viewer panel; expected to be inside of a wxScrollWindow
class GfxPanel : public wxPanel
{
public:
// a graphics viewer panel; expected to be inside of a wxScrollWindow
class GfxPanel : public wxPanel
{
public:
GfxPanel() : wxPanel(), bm(0), selx(-1), sely(-1) {}
int bmw, bmh;
wxBitmap *bm;
wxImage *im;
PixView *pv;
wxBitmap* bm;
wxImage* im;
PixView* pv;
protected:
protected:
void DrawBitmap(wxPaintEvent &ev);
void Click(wxMouseEvent &ev);
void MouseMove(wxMouseEvent &ev);
void DoSel(wxMouseEvent &ev, bool force = false);
private:
private:
int selx, sely;
DECLARE_DYNAMIC_CLASS()
DECLARE_EVENT_TABLE()
};
};
BEGIN_DECLARE_EVENT_TYPES()
// event generated on mouse click
// generates wxMouseEvent with coords adjusted to original bitmap
// size regardless of scaling
DECLARE_LOCAL_EVENT_TYPE(EVT_COMMAND_GFX_CLICK, 0)
END_DECLARE_EVENT_TYPES()
BEGIN_DECLARE_EVENT_TYPES()
// event generated on mouse click
// generates wxMouseEvent with coords adjusted to original bitmap
// size regardless of scaling
DECLARE_LOCAL_EVENT_TYPE(EVT_COMMAND_GFX_CLICK, 0)
END_DECLARE_EVENT_TYPES()
#define EVT_GFX_CLICK(id, fun) \
DECLARE_EVENT_TABLE_ENTRY(EVT_COMMAND_GFX_CLICK, id, wxID_ANY, wxMouseEventHandler(fun), NULL),
// like Viewer, common stuff to all gfx viewers
// this is what actually manages the GfxPanel
class GfxViewer : public Viewer
{
public:
GfxViewer(const wxChar *dname, int maxw, int maxh);
// like Viewer, common stuff to all gfx viewers
// this is what actually manages the GfxPanel
class GfxViewer : public Viewer
{
public:
GfxViewer(const wxChar* dname, int maxw, int maxh);
void ChangeBMP();
void BMPSize(int w, int h);
protected:
protected:
void StretchTog(wxCommandEvent &ev);
void RefreshEv(wxCommandEvent &ev);
void SaveBMP(wxCommandEvent &ev);
wxImage image;
GfxPanel *gv;
private:
GfxPanel* gv;
private:
static wxString bmp_save_dir;
wxScrolledWindow *gvs;
wxCheckBox *str;
wxScrolledWindow* gvs;
wxCheckBox* str;
DECLARE_EVENT_TABLE()
};
};
// if the jumbopixel view is all there is, maybe send a GFX_CLICK..
class PixViewEvt : public PixView
{
// if the jumbopixel view is all there is, maybe send a GFX_CLICK..
class PixViewEvt : public PixView
{
// generates a GFX_CLICK if a point is selected
void SetData(const unsigned char *data, int stride, int x = 0,
int y = 0);
protected:
void SetData(const unsigned char* data, int stride, int x = 0,
int y = 0);
protected:
// always generates a GFX_CLICK
void SelPoint(wxMouseEvent &ev);
void click();
DECLARE_DYNAMIC_CLASS()
};
};
// a display-only checkbox which does not look like it's disabled
class DispCheckBox : public wxCheckBox
{
public:
// a display-only checkbox which does not look like it's disabled
class DispCheckBox : public wxCheckBox
{
public:
bool AcceptsFocus() { return false; }
void MouseEvent(wxMouseEvent &ev) {}
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS()
};
};
// standard widgets in graphical viewers
// standard widgets in graphical viewers
}
#endif /* WX_VIEWSUPT_H */

View File

@ -45,7 +45,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxCheckedListCtrl, wxListCtrl)
IMPLEMENT_CLASS(wxCheckedListCtrl, wxListCtrl)
#endif
BEGIN_EVENT_TABLE(wxCheckedListCtrl, wxListCtrl)
EVT_LEFT_DOWN(wxCheckedListCtrl::OnMouseEvent)
EVT_LEFT_DOWN(wxCheckedListCtrl::OnMouseEvent)
END_EVENT_TABLE()
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_CHECKED);
@ -57,86 +57,75 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_UNCHECKED);
// wxCHECKEDLISTCTRL
// ------------------
bool wxCheckedListCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint& pt,
const wxSize& sz, long style, const wxValidator& validator, const wxString& name)
bool wxCheckedListCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint &pt,
const wxSize &sz, long style, const wxValidator &validator, const wxString &name)
{
if (!wxListCtrl::Create(parent, id, pt, sz, style, validator, name))
return FALSE;
#if CLC_VBAM_USAGE
// support xrc by making init separate
return Init();
// support xrc by making init separate
return Init();
}
bool wxCheckedListCtrl::Init()
{
#if CLC_USE_SYSICONS
// use native size images instead of 16x16
wxCheckBox *cb = new wxCheckBox(GetParent(), wxID_ANY, wxEmptyString);
wxSize cbsz = cb->GetBestSize();
delete cb;
m_imageList.Create(cbsz.GetWidth(), cbsz.GetHeight(), TRUE);
// use native size images instead of 16x16
wxCheckBox* cb = new wxCheckBox(GetParent(), wxID_ANY, wxEmptyString);
wxSize cbsz = cb->GetBestSize();
delete cb;
m_imageList.Create(cbsz.GetWidth(), cbsz.GetHeight(), TRUE);
#else
m_imageList.Create(16, 16, TRUE);
m_imageList.Create(16, 16, TRUE);
#endif
#endif
SetImageList(&m_imageList, wxIMAGE_LIST_SMALL);
SetImageList(&m_imageList, wxIMAGE_LIST_SMALL);
#if CLC_VBAM_USAGE && CLC_USE_SYSICONS
// pasted from wxWiki
// but with native size instead of 16x16
// constructor only takes wxSize in 2.9+, apparently
wxBitmap unchecked_bmp(cbsz.GetWidth(), cbsz.GetHeight()),
checked_bmp(cbsz.GetWidth(), cbsz.GetHeight()),
unchecked_disabled_bmp(cbsz.GetWidth(), cbsz.GetHeight()),
checked_disabled_bmp(cbsz.GetWidth(), cbsz.GetHeight());
// Bitmaps must not be selected by a DC for addition to the image list but I don't see
// a way of diselecting them in wxMemoryDC so let's just use a code block to end the scope
{
wxMemoryDC renderer_dc;
// Unchecked
renderer_dc.SelectObject(unchecked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), 0);
// Checked
renderer_dc.SelectObject(checked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), wxCONTROL_CHECKED);
// Unchecked and Disabled
renderer_dc.SelectObject(unchecked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), 0 | wxCONTROL_DISABLED);
// Checked and Disabled
renderer_dc.SelectObject(checked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), wxCONTROL_CHECKED | wxCONTROL_DISABLED);
}
// the add order must respect the wxCLC_XXX_IMGIDX defines in the headers !
m_imageList.Add(unchecked_bmp);
m_imageList.Add(checked_bmp);
m_imageList.Add(unchecked_disabled_bmp);
m_imageList.Add(checked_disabled_bmp);
// pasted from wxWiki
// but with native size instead of 16x16
// constructor only takes wxSize in 2.9+, apparently
wxBitmap unchecked_bmp(cbsz.GetWidth(), cbsz.GetHeight()),
checked_bmp(cbsz.GetWidth(), cbsz.GetHeight()),
unchecked_disabled_bmp(cbsz.GetWidth(), cbsz.GetHeight()),
checked_disabled_bmp(cbsz.GetWidth(), cbsz.GetHeight());
// Bitmaps must not be selected by a DC for addition to the image list but I don't see
// a way of diselecting them in wxMemoryDC so let's just use a code block to end the scope
{
wxMemoryDC renderer_dc;
// Unchecked
renderer_dc.SelectObject(unchecked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), 0);
// Checked
renderer_dc.SelectObject(checked_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), wxCONTROL_CHECKED);
// Unchecked and Disabled
renderer_dc.SelectObject(unchecked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), 0 | wxCONTROL_DISABLED);
// Checked and Disabled
renderer_dc.SelectObject(checked_disabled_bmp);
renderer_dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID));
renderer_dc.Clear();
wxRendererNative::Get().DrawCheckBox(this, renderer_dc, wxRect(0, 0, 16, 16), wxCONTROL_CHECKED | wxCONTROL_DISABLED);
}
// the add order must respect the wxCLC_XXX_IMGIDX defines in the headers !
m_imageList.Add(unchecked_bmp);
m_imageList.Add(checked_bmp);
m_imageList.Add(unchecked_disabled_bmp);
m_imageList.Add(checked_disabled_bmp);
#else
// the add order must respect the wxCLC_XXX_IMGIDX defines in the headers !
m_imageList.Add(wxIcon(unchecked_xpm));
m_imageList.Add(wxIcon(checked_xpm));
m_imageList.Add(wxIcon(unchecked_dis_xpm));
m_imageList.Add(wxIcon(checked_dis_xpm));
m_imageList.Add(wxIcon(unchecked_xpm));
m_imageList.Add(wxIcon(checked_xpm));
m_imageList.Add(wxIcon(unchecked_dis_xpm));
m_imageList.Add(wxIcon(checked_dis_xpm));
#endif
return TRUE;
}
@ -152,16 +141,17 @@ int wxCheckedListCtrl::GetItemImageFromAdditionalState(int addstate)
return wxCLC_DISABLED_CHECKED_IMGIDX;
else if (!checked && enabled)
return wxCLC_UNCHECKED_IMGIDX;
wxASSERT(!checked && !enabled); // this is the last possibility
wxASSERT(!checked && !enabled); // this is the last possibility
return wxCLC_DISABLED_UNCHECKED_IMGIDX;
}
wxColour wxCheckedListCtrl::GetBgColourFromAdditionalState(int additionalstate)
{
if ((additionalstate & wxLIST_STATE_ENABLED) &&
this->IsEnabled())
this->IsEnabled())
return *wxWHITE;
#ifdef __WXMSW__
return wxColour(212, 208, 200);
#else
@ -170,9 +160,10 @@ wxColour wxCheckedListCtrl::GetBgColourFromAdditionalState(int additionalstate)
}
/* static */
int wxCheckedListCtrl::GetAndRemoveAdditionalState(long *state, int statemask)
int wxCheckedListCtrl::GetAndRemoveAdditionalState(long* state, int statemask)
{
int additionalstate = 0;
if (!state) return -1;
// extract the bits we are interested in
@ -181,6 +172,7 @@ int wxCheckedListCtrl::GetAndRemoveAdditionalState(long *state, int statemask)
// and set them in a different variable if they are included in the statemask
if (checked && (statemask & wxLIST_STATE_CHECKED)) additionalstate |= wxLIST_STATE_CHECKED;
if (enabled && (statemask & wxLIST_STATE_ENABLED)) additionalstate |= wxLIST_STATE_ENABLED;
// remove them from the original state var...
@ -189,20 +181,19 @@ int wxCheckedListCtrl::GetAndRemoveAdditionalState(long *state, int statemask)
return additionalstate;
}
bool wxCheckedListCtrl::GetItem(wxListItem& info) const
bool wxCheckedListCtrl::GetItem(wxListItem &info) const
{
// wx internal wxListCtrl::GetItem remove from the state mask the
// wxLIST_STATE_CHECKED & wxLIST_STATE_ENABLED bits since they
// are not part of wx standard flags... so we need to check those
// flags against the original wxListItem's statemask...
wxListItem original(info);
#ifdef __WXDEBUG__
// we always want to retrieve also the image state for checking purposes...
info.m_mask |= wxLIST_MASK_IMAGE;
#endif
if (!wxListCtrl::GetItem(info))
if (!wxListCtrl::GetItem(info))
return FALSE;
// these are our additional supported states: read them from m_stateList
@ -211,69 +202,73 @@ bool wxCheckedListCtrl::GetItem(wxListItem& info) const
// now intercept state requests about enable or check mode
if ((original.m_mask & wxLIST_MASK_STATE) &&
(original.m_stateMask & wxLIST_STATE_CHECKED)) {
(original.m_stateMask & wxLIST_STATE_CHECKED))
{
info.m_state |= (m_stateList[info.m_itemId] & wxLIST_STATE_CHECKED);
info.m_stateMask |= wxLIST_STATE_CHECKED;
info.m_mask |= wxLIST_MASK_STATE; // contains valid info !
info.m_mask |= wxLIST_MASK_STATE; // contains valid info !
}
if ((original.m_mask & wxLIST_MASK_STATE) &&
(original.m_stateMask & wxLIST_STATE_ENABLED)) {
(original.m_stateMask & wxLIST_STATE_ENABLED))
{
info.m_state |= (m_stateList[info.m_itemId] & wxLIST_STATE_ENABLED);
info.m_stateMask |= wxLIST_STATE_ENABLED;
info.m_mask |= wxLIST_MASK_STATE; // contains valid info !
info.m_mask |= wxLIST_MASK_STATE; // contains valid info !
}
// check that state & image are synch
#if CLC_VBAM_USAGE
if(info.GetColumn())
if (info.GetColumn())
return TRUE;
#endif
#ifdef __WXDEBUG__
wxASSERT_MSG((int)m_stateList.GetCount() == (int)GetItemCount(),
wxT("Something wrong ! See InsertItem()"));
wxT("Something wrong ! See InsertItem()"));
// read info by image index
bool imagecheck = (info.m_image == wxCLC_CHECKED_IMGIDX) ||
(info.m_image == wxCLC_DISABLED_CHECKED_IMGIDX);
(info.m_image == wxCLC_DISABLED_CHECKED_IMGIDX);
bool imageenabled = (info.m_image == wxCLC_CHECKED_IMGIDX) ||
(info.m_image == wxCLC_UNCHECKED_IMGIDX);
(info.m_image == wxCLC_UNCHECKED_IMGIDX);
wxASSERT_MSG((checked && imagecheck) || (!checked && !imagecheck),
wxT("This is item has checked state but it's shown as unchecked (or viceversa)"));
wxT("This is item has checked state but it's shown as unchecked (or viceversa)"));
wxASSERT_MSG((enabled && imageenabled) || (!enabled && !imageenabled),
wxT("This is item has enabled state but it's shown as disabled (or viceversa)"));
wxT("This is item has enabled state but it's shown as disabled (or viceversa)"));
#endif
return TRUE;
}
bool wxCheckedListCtrl::SetItem(wxListItem& info)
bool wxCheckedListCtrl::SetItem(wxListItem &info)
{
#if CLC_VBAM_USAGE
// only col 0 gets a checkbox
if(info.GetColumn())
if (info.GetColumn())
return wxListCtrl::SetItem(info);
#endif
// remove the checked & enabled states from the state flag:
// we'll store them in our separate array
int additionalstate = GetAndRemoveAdditionalState(&info.m_state, info.m_stateMask);
// set image index
// set image index
// we will ignore the info.m_image field since we need
// to overwrite it...
if (info.m_mask & wxLIST_MASK_STATE) {
if (info.m_mask & wxLIST_MASK_STATE)
{
// if some state is not included in the state mask, then get the state info
// from our internal state array
if (!(info.m_stateMask & wxLIST_STATE_ENABLED))
additionalstate |= (m_stateList[info.m_itemId] & wxLIST_STATE_ENABLED);
if (!(info.m_stateMask & wxLIST_STATE_CHECKED))
additionalstate |= (m_stateList[info.m_itemId] & wxLIST_STATE_CHECKED);
// state is valid: use it to determine the image to set...
info.m_mask |= wxLIST_MASK_IMAGE;
info.m_image = GetItemImageFromAdditionalState(additionalstate);
// since when changing the background color, also the foreground color
// and the font of the item are changed, we try to respect the user
// choices of such attributes
@ -282,14 +277,12 @@ bool wxCheckedListCtrl::SetItem(wxListItem& info)
// before wx 2.6.2 the wxListCtrl::SetItemFont function is missing
info.SetFont(this->GetItemFont(info.GetId()));
#endif
// change the background color to respect the enabled/disabled status...
info.SetBackgroundColour(GetBgColourFromAdditionalState(additionalstate));
m_stateList[info.m_itemId] = additionalstate;
} else {
}
else
{
// state is invalid; don't change image
info.m_mask &= ~wxLIST_MASK_IMAGE;
}
@ -301,9 +294,10 @@ bool wxCheckedListCtrl::SetItem(wxListItem& info)
long wxCheckedListCtrl::InsertItem(wxListItem &info)
{
int additionalstate = GetAndRemoveAdditionalState(&info.m_state, info.m_stateMask);
if (!(info.m_mask & wxLIST_MASK_STATE) ||
!(info.m_stateMask & wxLIST_STATE_ENABLED)) {
if (!(info.m_mask & wxLIST_MASK_STATE) ||
!(info.m_stateMask & wxLIST_STATE_ENABLED))
{
// if not specified, the default additional state is ENABLED
additionalstate = wxLIST_STATE_ENABLED;
}
@ -312,110 +306,111 @@ long wxCheckedListCtrl::InsertItem(wxListItem &info)
info.m_mask |= wxLIST_MASK_IMAGE;
info.m_image = GetItemImageFromAdditionalState(additionalstate);
info.SetBackgroundColour(GetBgColourFromAdditionalState(additionalstate));
int itemcount = GetItemCount();
wxASSERT_MSG(info.m_itemId <= itemcount, wxT("Invalid index !"));
wxASSERT_MSG((int)m_stateList.GetCount() == (int)GetItemCount(),
wxT("Something wrong !"));
if (info.m_itemId == itemcount) {
wxT("Something wrong !"));
if (info.m_itemId == itemcount)
{
// we are adding a new item at the end of the list
m_stateList.Add(additionalstate);
} else {
}
else
{
// we must shift all following items
m_stateList.Add(m_stateList[itemcount - 1]);
for (int i=itemcount - 1; i > info.m_itemId; i--)
m_stateList[i] = m_stateList[i-1];
for (int i = itemcount - 1; i > info.m_itemId; i--)
m_stateList[i] = m_stateList[i - 1];
m_stateList[info.m_itemId] = additionalstate;
}
return wxListCtrl::InsertItem(info);
}
bool wxCheckedListCtrl::SetItemState(long item, long state, long stateMask)
{
wxListItem li;
li.SetId(item);
li.SetMask(wxLIST_MASK_STATE);
li.SetState(state);
li.SetStateMask(stateMask);
// so we are sure to use wxCheckedListCtrl::SetItem
// (and not wxListCtrl::SetItem)
return SetItem(li);
}
int wxCheckedListCtrl::GetItemState(long item, long stateMask) const
{
wxListItem li;
li.SetId(item);
li.SetMask(wxLIST_MASK_STATE);
li.SetStateMask(stateMask);
// so we are sure to use wxCheckedListCtrl::GetItem
// (and not wxListCtrl::GetItem)
if (!GetItem(li))
return -1;
return li.GetState();
}
long wxCheckedListCtrl::SetItem(long index, int col, const wxString& label, int WXUNUSED(imageId))
{
wxListItem li;
li.SetId(index);
li.SetColumn(col);
li.SetText(label);
li.SetMask(wxLIST_MASK_TEXT);
wxListItem li;
li.SetId(item);
li.SetMask(wxLIST_MASK_STATE);
li.SetState(state);
li.SetStateMask(stateMask);
// so we are sure to use wxCheckedListCtrl::SetItem
// (and not wxListCtrl::SetItem)
return SetItem(li);
}
long wxCheckedListCtrl::InsertItem( long index, const wxString& label, int WXUNUSED(imageIndex) )
int wxCheckedListCtrl::GetItemState(long item, long stateMask) const
{
wxListItem info;
info.m_text = label;
info.m_mask = wxLIST_MASK_TEXT;
info.m_itemId = index;
return InsertItem(info);
wxListItem li;
li.SetId(item);
li.SetMask(wxLIST_MASK_STATE);
li.SetStateMask(stateMask);
// so we are sure to use wxCheckedListCtrl::GetItem
// (and not wxListCtrl::GetItem)
if (!GetItem(li))
return -1;
return li.GetState();
}
long wxCheckedListCtrl::SetItem(long index, int col, const wxString &label, int WXUNUSED(imageId))
{
wxListItem li;
li.SetId(index);
li.SetColumn(col);
li.SetText(label);
li.SetMask(wxLIST_MASK_TEXT);
// so we are sure to use wxCheckedListCtrl::SetItem
// (and not wxListCtrl::SetItem)
return SetItem(li);
}
long wxCheckedListCtrl::InsertItem(long index, const wxString &label, int WXUNUSED(imageIndex))
{
wxListItem info;
info.m_text = label;
info.m_mask = wxLIST_MASK_TEXT;
info.m_itemId = index;
return InsertItem(info);
}
void wxCheckedListCtrl::Check(long item, bool checked)
{
{
// NB: the "statemask" is not the "mask" of a list item;
// in the "mask" you use the wxLIST_MASK_XXXX defines;
// in the "statemask" you use the wxLIST_STATE_XXX defines
// to set a specific bit of the wxListInfo::m_state var
if (checked)
if (checked)
// the 2nd parameter says: activate the STATE bit relative to CHECK feature
// the 3rd parameter says: set only *that* bit
SetItemState(item, wxLIST_STATE_CHECKED, wxLIST_STATE_CHECKED);
// the 3rd parameter says: set only *that* bit
SetItemState(item, wxLIST_STATE_CHECKED, wxLIST_STATE_CHECKED);
else
SetItemState(item, 0, wxLIST_STATE_CHECKED);
SetItemState(item, 0, wxLIST_STATE_CHECKED);
}
void wxCheckedListCtrl::Enable(long item, bool enable)
{
if (enable)
{
if (enable)
// the 2nd parameter says: activate the STATE bit relative to ENABLE feature
// the 3rd parameter says: set only *that* bit
// the 3rd parameter says: set only *that* bit
SetItemState(item, wxLIST_STATE_ENABLED, wxLIST_STATE_ENABLED);
else
SetItemState(item, 0, wxLIST_STATE_ENABLED);
SetItemState(item, 0, wxLIST_STATE_ENABLED);
}
void wxCheckedListCtrl::EnableAll(bool enable)
{
for (int i=0; i < GetItemCount(); i++)
for (int i = 0; i < GetItemCount(); i++)
Enable(i, enable);
}
void wxCheckedListCtrl::CheckAll(bool check)
{
for (int i=0; i < GetItemCount(); i++)
for (int i = 0; i < GetItemCount(); i++)
Check(i, check);
}
@ -423,16 +418,16 @@ bool wxCheckedListCtrl::DeleteItem(long item)
{
// shift our additional state array
//for (int i=item,max=GetItemCount(); i < max-1; i++)
// m_stateList[i] = m_stateList[i+1];
// m_stateList[i] = m_stateList[i+1];
m_stateList.RemoveAt(item, 1);
return wxListCtrl::DeleteItem(item);
}
int wxCheckedListCtrl::GetCheckedItemCount() const
{
int res = 0;
for (int i=0; i<GetItemCount(); i++)
for (int i = 0; i < GetItemCount(); i++)
if (IsChecked(i))
res++;
@ -441,48 +436,50 @@ int wxCheckedListCtrl::GetCheckedItemCount() const
// event handlers
void wxCheckedListCtrl::OnMouseEvent(wxMouseEvent& event)
void wxCheckedListCtrl::OnMouseEvent(wxMouseEvent &event)
{
if (!event.LeftDown()) {
event.Skip();
if (!event.LeftDown())
{
event.Skip();
return;
}
int flags;
long item = HitTest(event.GetPosition(), flags);
if (item == wxNOT_FOUND || !IsEnabled(item)) {
if (item == wxNOT_FOUND || !IsEnabled(item))
{
// skip this item
event.Skip();
return;
event.Skip();
return;
}
// user clicked exactly on the checkbox or on the item row ?
bool processcheck = (flags & wxLIST_HITTEST_ONITEMICON) ||
((GetWindowStyle() & wxCLC_CHECK_WHEN_SELECTING) &&
(flags & wxLIST_HITTEST_ONITEM));
if (processcheck) {
bool processcheck = (flags & wxLIST_HITTEST_ONITEMICON) ||
((GetWindowStyle() & wxCLC_CHECK_WHEN_SELECTING) &&
(flags & wxLIST_HITTEST_ONITEM));
if (processcheck)
{
wxListEvent ev(wxEVT_NULL, GetId());
ev.m_itemIndex = item;
ev.m_itemIndex = item;
// send the check event
if (IsChecked(item)) {
if (IsChecked(item))
{
ev.SetEventType(wxEVT_COMMAND_LIST_ITEM_UNCHECKED);
Check(item, FALSE);
AddPendingEvent(ev);
} else {
}
else
{
ev.SetEventType(wxEVT_COMMAND_LIST_ITEM_CHECKED);
Check(item, TRUE);
AddPendingEvent(ev);
}
}
event.Skip();
event.Skip();
}
#endif // wxUSE_CHECKEDLISTCTRL
#endif // wxUSE_CHECKEDLISTCTRL

View File

@ -5,129 +5,170 @@
IMPLEMENT_DYNAMIC_CLASS(wxJoyKeyTextCtrl, wxKeyTextCtrl)
BEGIN_EVENT_TABLE(wxJoyKeyTextCtrl, wxKeyTextCtrl)
EVT_SDLJOY(wxJoyKeyTextCtrl::OnJoy)
EVT_SDLJOY(wxJoyKeyTextCtrl::OnJoy)
END_EVENT_TABLE()
int wxJoyKeyTextCtrl::DigitalButton(wxSDLJoyEvent &event)
{
int sdlval = event.GetControlValue();
int sdltype = event.GetControlType();
int sdlval = event.GetControlValue();
int sdltype = event.GetControlType();
switch (sdltype)
{
case WXSDLJOY_AXIS:
// for val = 0 return arbitrary direction; val means "off"
return sdlval > 0 ? WXJB_AXIS_PLUS : WXJB_AXIS_MINUS;
case WXSDLJOY_HAT:
/* URDL = 1248 */
switch (sdlval)
{
case 1:
return WXJB_HAT_N;
case 2:
return WXJB_HAT_E;
case 3:
return WXJB_HAT_NE;
case 4:
return WXJB_HAT_S;
case 6:
return WXJB_HAT_SE;
case 8:
return WXJB_HAT_W;
case 9:
return WXJB_HAT_NW;
case 12:
return WXJB_HAT_SW;
default:
return WXJB_HAT_N; // arbitrary direction; val = 0 means "off"
}
case WXSDLJOY_BUTTON:
return WXJB_BUTTON;
switch(sdltype) {
case WXSDLJOY_AXIS:
// for val = 0 return arbitrary direction; val means "off"
return sdlval > 0 ? WXJB_AXIS_PLUS : WXJB_AXIS_MINUS;
case WXSDLJOY_HAT:
/* URDL = 1248 */
switch(sdlval) {
case 1:
return WXJB_HAT_N;
case 2:
return WXJB_HAT_E;
case 3:
return WXJB_HAT_NE;
case 4:
return WXJB_HAT_S;
case 6:
return WXJB_HAT_SE;
case 8:
return WXJB_HAT_W;
case 9:
return WXJB_HAT_NW;
case 12:
return WXJB_HAT_SW;
default:
return WXJB_HAT_N; // arbitrary direction; val = 0 means "off"
// unknown ctrl type
return -1;
}
case WXSDLJOY_BUTTON:
return WXJB_BUTTON;
default:
// unknown ctrl type
return -1;
}
}
void wxJoyKeyTextCtrl::OnJoy(wxSDLJoyEvent &event)
{
short val = event.GetControlValue();
int mod = DigitalButton(event);
int key = event.GetControlIndex(), joy = event.GetJoy() + 1;
short val = event.GetControlValue();
int mod = DigitalButton(event);
int key = event.GetControlIndex(), joy = event.GetJoy() + 1;
if(!val || mod < 0)
return;
wxString nv = ToString(mod, key, joy);
if(nv.empty())
return;
if(multikey) {
wxString ov = GetValue();
if(!ov.empty())
nv = ov + multikey + nv;
}
SetValue(nv);
if(keyenter)
Navigate();
if (!val || mod < 0)
return;
wxString nv = ToString(mod, key, joy);
if (nv.empty())
return;
if (multikey)
{
wxString ov = GetValue();
if (!ov.empty())
nv = ov + multikey + nv;
}
SetValue(nv);
if (keyenter)
Navigate();
}
wxString wxJoyKeyTextCtrl::ToString(int mod, int key, int joy)
{
if(!joy)
return wxKeyTextCtrl::ToString(mod, key);
wxString s;
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
// So any strings added below must also be translated unconditionally
s.Printf(_("Joy%d-"), joy);
wxString mk;
switch(mod) {
case WXJB_AXIS_PLUS:
mk.Printf(_("Axis%d+"), key);
break;
case WXJB_AXIS_MINUS:
mk.Printf(_("Axis%d-"), key);
break;
case WXJB_BUTTON:
mk.Printf(_("Button%d"), key);
break;
case WXJB_HAT_N:
mk.Printf(_("Hat%dN"), key);
break;
case WXJB_HAT_S:
mk.Printf(_("Hat%dS"), key);
break;
case WXJB_HAT_W:
mk.Printf(_("Hat%dW"), key);
break;
case WXJB_HAT_E:
mk.Printf(_("Hat%dE"), key);
break;
case WXJB_HAT_NW:
mk.Printf(_("Hat%dNW"), key);
break;
case WXJB_HAT_NE:
mk.Printf(_("Hat%dNE"), key);
break;
case WXJB_HAT_SW:
mk.Printf(_("Hat%dSW"), key);
break;
case WXJB_HAT_SE:
mk.Printf(_("Hat%dSE"), key);
break;
}
s += mk;
return s;
if (!joy)
return wxKeyTextCtrl::ToString(mod, key);
wxString s;
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
// So any strings added below must also be translated unconditionally
s.Printf(_("Joy%d-"), joy);
wxString mk;
switch (mod)
{
case WXJB_AXIS_PLUS:
mk.Printf(_("Axis%d+"), key);
break;
case WXJB_AXIS_MINUS:
mk.Printf(_("Axis%d-"), key);
break;
case WXJB_BUTTON:
mk.Printf(_("Button%d"), key);
break;
case WXJB_HAT_N:
mk.Printf(_("Hat%dN"), key);
break;
case WXJB_HAT_S:
mk.Printf(_("Hat%dS"), key);
break;
case WXJB_HAT_W:
mk.Printf(_("Hat%dW"), key);
break;
case WXJB_HAT_E:
mk.Printf(_("Hat%dE"), key);
break;
case WXJB_HAT_NW:
mk.Printf(_("Hat%dNW"), key);
break;
case WXJB_HAT_NE:
mk.Printf(_("Hat%dNE"), key);
break;
case WXJB_HAT_SW:
mk.Printf(_("Hat%dSW"), key);
break;
case WXJB_HAT_SE:
mk.Printf(_("Hat%dSE"), key);
break;
}
s += mk;
return s;
}
wxString wxJoyKeyTextCtrl::ToString(wxJoyKeyBinding_v keys, wxChar sep)
{
wxString ret;
for(int i = 0; i < keys.size(); i++) {
if(i > 0)
ret += sep;
wxString key = ToString(keys[i].mod, keys[i].key, keys[i].joy);
if(key.empty())
return wxEmptyString;
ret += key;
}
return ret;
wxString ret;
for (int i = 0; i < keys.size(); i++)
{
if (i > 0)
ret += sep;
wxString key = ToString(keys[i].mod, keys[i].key, keys[i].joy);
if (key.empty())
return wxEmptyString;
ret += key;
}
return ret;
}
#include <wx/regex.h>
@ -136,137 +177,168 @@ wxString wxJoyKeyTextCtrl::ToString(wxJoyKeyBinding_v keys, wxChar sep)
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
// So any strings added below must also be translated unconditionally
// \1 is joy #
static wxRegEx joyre(_("^Joy([0-9]+)[-+]"), wxRE_EXTENDED|wxRE_ICASE);
static wxRegEx joyre(_("^Joy([0-9]+)[-+]"), wxRE_EXTENDED | wxRE_ICASE);
// \1 is axis# and \2 is + or -
static wxRegEx axre(_("Axis([0-9]+)([+-])"), wxRE_EXTENDED|wxRE_ICASE);
static wxRegEx axre(_("Axis([0-9]+)([+-])"), wxRE_EXTENDED | wxRE_ICASE);
// \1 is button#
static wxRegEx butre(_("Button([0-9]+)"), wxRE_EXTENDED|wxRE_ICASE);
static wxRegEx butre(_("Button([0-9]+)"), wxRE_EXTENDED | wxRE_ICASE);
// \1 is hat#, \3 is N, \4 is S, \5 is E, \6 is W, \7 is NE, \8 is SE,
// \9 is SW, \10 is NW
static wxRegEx hatre(_("Hat([0-9]+)((N|North|U|Up)|(S|South|D|Down)|"
"(E|East|R|Right)|(W|West|L|Left)|"
"(NE|NorthEast|UR|UpRight)|(SE|SouthEast|DR|DownRight)|"
"(SW|SouthWest|DL|DownLeft)|(NW|NorthWest|UL|UpLeft))"),
wxRE_EXTENDED|wxRE_ICASE);
"(E|East|R|Right)|(W|West|L|Left)|"
"(NE|NorthEast|UR|UpRight)|(SE|SouthEast|DR|DownRight)|"
"(SW|SouthWest|DL|DownLeft)|(NW|NorthWest|UL|UpLeft))"),
wxRE_EXTENDED | wxRE_ICASE);
// use of static wxRegeEx is not thread-safe
static wxCriticalSection recs;
// wx provides no atoi for wxChar
// this is not a universal function; assumes valid number
static int simple_atoi(const wxChar *s, int len)
static int simple_atoi(const wxChar* s, int len)
{
int ret = 0;
for(int i = 0; i < len; i++)
ret = ret * 10 + s[i] - wxT('0');
return ret;
int ret = 0;
for (int i = 0; i < len; i++)
ret = ret * 10 + s[i] - wxT('0');
return ret;
}
static bool ParseJoy(const wxChar *s, int len, int &mod, int &key, int &joy)
static bool ParseJoy(const wxChar* s, int len, int &mod, int &key, int &joy)
{
mod = key = joy = 0;
if(!len)
return false;
mod = key = joy = 0;
wxCriticalSectionLocker lk(recs);
size_t b, l;
if(!joyre.Matches(s) || !joyre.GetMatch(&b, &l) || b)
return false;
const wxChar *p = s + l;
int alen = len - l;
joyre.GetMatch(&b, &l, 1);
joy = simple_atoi(s + b, l);
if (!len)
return false;
wxCriticalSectionLocker lk(recs);
size_t b, l;
if (!joyre.Matches(s) || !joyre.GetMatch(&b, &l) || b)
return false;
const wxChar* p = s + l;
int alen = len - l;
joyre.GetMatch(&b, &l, 1);
joy = simple_atoi(s + b, l);
#define is_ctrl(re) re.Matches(p) && re.GetMatch(&b, &l) && l == alen && !b
if(is_ctrl(axre)) {
axre.GetMatch(&b, &l, 1);
key = simple_atoi(p + b, l);
axre.GetMatch(&b, &l, 2);
mod = p[b] == wxT('+') ? WXJB_AXIS_PLUS : WXJB_AXIS_MINUS;
} else if(is_ctrl(butre)) {
butre.GetMatch(&b, &l, 1);
key = simple_atoi(p + b, l);
mod = WXJB_BUTTON;
} else if(is_ctrl(hatre)) {
hatre.GetMatch(&b, &l, 1);
key = simple_atoi(p + b, l);
if (is_ctrl(axre))
{
axre.GetMatch(&b, &l, 1);
key = simple_atoi(p + b, l);
axre.GetMatch(&b, &l, 2);
mod = p[b] == wxT('+') ? WXJB_AXIS_PLUS : WXJB_AXIS_MINUS;
}
else if (is_ctrl(butre))
{
butre.GetMatch(&b, &l, 1);
key = simple_atoi(p + b, l);
mod = WXJB_BUTTON;
}
else if (is_ctrl(hatre))
{
hatre.GetMatch(&b, &l, 1);
key = simple_atoi(p + b, l);
#define check_dir(n, d) else if(hatre.GetMatch(&b, &l, n) && l > 0) mod = WXJB_HAT_##d
if(0);
check_dir(3, N);
check_dir(4, S);
check_dir(5, E);
check_dir(6, W);
check_dir(7, NE);
check_dir(8, SE);
check_dir(9, SW);
check_dir(10, NW);
} else {
joy = 0;
return false;
}
return true;
if (0);
check_dir(3, N);
check_dir(4, S);
check_dir(5, E);
check_dir(6, W);
check_dir(7, NE);
check_dir(8, SE);
check_dir(9, SW);
check_dir(10, NW);
}
else
{
joy = 0;
return false;
}
return true;
}
bool wxJoyKeyTextCtrl::ParseString(const wxChar *s, int len, int &mod, int &key, int &joy)
bool wxJoyKeyTextCtrl::ParseString(const wxChar* s, int len, int &mod, int &key, int &joy)
{
if(ParseJoy(s, len, mod, key, joy))
return true;
return wxKeyTextCtrl::ParseString(s, len, mod, key);
if (ParseJoy(s, len, mod, key, joy))
return true;
return wxKeyTextCtrl::ParseString(s, len, mod, key);
}
bool wxJoyKeyTextCtrl::FromString(const wxString &s, int &mod, int &key, int &joy)
{
return ParseString(s.c_str(), s.size(), mod, key, joy);
return ParseString(s.c_str(), s.size(), mod, key, joy);
}
wxJoyKeyBinding_v wxJoyKeyTextCtrl::FromString(const wxString &s, wxChar sep)
{
wxJoyKeyBinding_v ret, empty;
int mod, key, joy;
int len = s.size();
if(!len)
return empty;
wxJoyKeyBinding_v ret, empty;
int mod, key, joy;
int len = s.size();
for(int lastkey = len - 1; (lastkey = s.rfind(sep, lastkey)) != wxString::npos; lastkey--) {
if(lastkey == len - 1) {
// sep as accel
if(!lastkey)
break;
if(s[lastkey - 1] == wxT('-') || s[lastkey - 1] == wxT('+') ||
s[lastkey - 1] == sep)
continue;
if (!len)
return empty;
for (int lastkey = len - 1; (lastkey = s.rfind(sep, lastkey)) != wxString::npos; lastkey--)
{
if (lastkey == len - 1)
{
// sep as accel
if (!lastkey)
break;
if (s[lastkey - 1] == wxT('-') || s[lastkey - 1] == wxT('+') ||
s[lastkey - 1] == sep)
continue;
}
if (!ParseString(s.c_str() + lastkey + 1, len - lastkey - 1, mod, key, joy))
return empty;
wxJoyKeyBinding jb = { key, mod, joy };
ret.insert(ret.begin(), jb);
len = lastkey;
}
if(!ParseString(s.c_str() + lastkey + 1, len - lastkey - 1, mod, key, joy))
return empty;
if (!ParseString(s.c_str(), len, mod, key, joy))
return empty;
wxJoyKeyBinding jb = { key, mod, joy };
ret.insert(ret.begin(), jb);
len = lastkey;
}
if(!ParseString(s.c_str(), len, mod, key, joy))
return empty;
wxJoyKeyBinding jb = { key, mod, joy };
ret.insert(ret.begin(), jb);
return ret;
return ret;
}
IMPLEMENT_CLASS(wxJoyKeyValidator, wxValidator)
bool wxJoyKeyValidator::TransferToWindow()
{
if(!val)
return false;
wxJoyKeyTextCtrl *jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
if(!jk)
return false;
jk->SetValue(wxJoyKeyTextCtrl::ToString(*val));
return true;
if (!val)
return false;
wxJoyKeyTextCtrl* jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
if (!jk)
return false;
jk->SetValue(wxJoyKeyTextCtrl::ToString(*val));
return true;
}
bool wxJoyKeyValidator::TransferFromWindow()
{
if(!val)
return false;
wxJoyKeyTextCtrl *jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
if(!jk)
return false;
*val = wxJoyKeyTextCtrl::FromString(jk->GetValue());
return true;
if (!val)
return false;
wxJoyKeyTextCtrl* jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
if (!jk)
return false;
*val = wxJoyKeyTextCtrl::FromString(jk->GetValue());
return true;
}

View File

@ -3,226 +3,280 @@
IMPLEMENT_DYNAMIC_CLASS(wxKeyTextCtrl, wxTextCtrl)
BEGIN_EVENT_TABLE(wxKeyTextCtrl, wxTextCtrl)
EVT_KEY_DOWN(wxKeyTextCtrl::OnKeyDown)
EVT_KEY_UP(wxKeyTextCtrl::OnKeyUp)
EVT_KEY_DOWN(wxKeyTextCtrl::OnKeyDown)
EVT_KEY_UP(wxKeyTextCtrl::OnKeyUp)
END_EVENT_TABLE()
void wxKeyTextCtrl::OnKeyDown(wxKeyEvent &event)
{
lastmod = event.GetModifiers();
lastkey = event.GetKeyCode();
lastmod = event.GetModifiers();
lastkey = event.GetKeyCode();
}
void wxKeyTextCtrl::OnKeyUp(wxKeyEvent &event)
{
int mod = lastmod;
int key = lastkey;
lastmod = lastkey = 0;
// key is only 0 if we missed the keydown event
// or if we are being shipped pseudo keypress events
// either way, just ignore
if(!key)
return;
// use unmodified backspace to clear last key, if enabled
// if blank or backspace is modified, add normally instead
if(clearable && !mod && key == WXK_BACK && !GetValue().empty())
{
wxString val = GetValue();
int lastkey = val.rfind(multikey);
if(lastkey && lastkey != wxString::npos) {
// if this was actually a ,-accel, delete instead
if(lastkey == val.size() - 1) {
lastkey = val.rfind(multikey, lastkey-1);
if(lastkey == wxString::npos)
lastkey = 0;
}
val.resize(lastkey);
SetValue(val);
} else
Clear();
} else {
wxString nv = ToString(mod, key);
if(nv.empty())
return;
if(multikey) {
wxString ov = GetValue();
if(!ov.empty())
nv = ov + multikey + nv;
int mod = lastmod;
int key = lastkey;
lastmod = lastkey = 0;
// key is only 0 if we missed the keydown event
// or if we are being shipped pseudo keypress events
// either way, just ignore
if (!key)
return;
// use unmodified backspace to clear last key, if enabled
// if blank or backspace is modified, add normally instead
if (clearable && !mod && key == WXK_BACK && !GetValue().empty())
{
wxString val = GetValue();
int lastkey = val.rfind(multikey);
if (lastkey && lastkey != wxString::npos)
{
// if this was actually a ,-accel, delete instead
if (lastkey == val.size() - 1)
{
lastkey = val.rfind(multikey, lastkey - 1);
if (lastkey == wxString::npos)
lastkey = 0;
}
val.resize(lastkey);
SetValue(val);
}
else
Clear();
}
SetValue(nv);
}
if(keyenter)
Navigate();
else
{
wxString nv = ToString(mod, key);
if (nv.empty())
return;
if (multikey)
{
wxString ov = GetValue();
if (!ov.empty())
nv = ov + multikey + nv;
}
SetValue(nv);
}
if (keyenter)
Navigate();
}
wxString wxKeyTextCtrl::ToString(int mod, int key)
{
// wx ignores non-alnum printable chars
// actually, wx gives an assertion error, so it's best to filter out
// before passing to ToString()
bool char_override = key > 32 && key < WXK_START && !wxIsalnum(key);
// wx also ignores modifiers (and does not report meta at all)
bool mod_override = key == WXK_SHIFT || key == WXK_CONTROL || key == WXK_ALT;
wxAcceleratorEntry ae(mod, char_override || mod_override ? WXK_F1 : key);
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
// So any strings added below must also be translated unconditionally
wxString s = ae.ToString();
if(char_override || mod_override) {
int l = s.rfind(wxT('-'));
if(l == wxString::npos)
l = 0;
else l++;
s.erase(l);
switch(key) {
case WXK_SHIFT:
s.append(_("SHIFT"));
break;
case WXK_ALT:
s.append(_("ALT"));
break;
case WXK_CONTROL:
s.append(_("CTRL"));
break;
default:
s.append((wxChar)key);
}
}
// wx ignores non-alnum printable chars
// actually, wx gives an assertion error, so it's best to filter out
// before passing to ToString()
bool char_override = key > 32 && key < WXK_START && !wxIsalnum(key);
// wx also ignores modifiers (and does not report meta at all)
bool mod_override = key == WXK_SHIFT || key == WXK_CONTROL || key == WXK_ALT;
wxAcceleratorEntry ae(mod, char_override || mod_override ? WXK_F1 : key);
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
// So any strings added below must also be translated unconditionally
wxString s = ae.ToString();
// on Mac, ctrl/meta become xctrl/cmd
// on other, meta is ignored
if (char_override || mod_override)
{
int l = s.rfind(wxT('-'));
if (l == wxString::npos)
l = 0;
else l++;
s.erase(l);
switch (key)
{
case WXK_SHIFT:
s.append(_("SHIFT"));
break;
case WXK_ALT:
s.append(_("ALT"));
break;
case WXK_CONTROL:
s.append(_("CTRL"));
break;
default:
s.append((wxChar)key);
}
}
// on Mac, ctrl/meta become xctrl/cmd
// on other, meta is ignored
#ifndef __WXMAC__
if(mod & wxMOD_META) {
s.insert(0, _("Meta-"));
}
if (mod & wxMOD_META)
{
s.insert(0, _("Meta-"));
}
#endif
if(s.empty() || (key != wxT('-') && s[s.size()-1] == wxT('-')))
// bad key combo; probably also generates an assertion in wx
return wxEmptyString;
return s;
if (s.empty() || (key != wxT('-') && s[s.size() - 1] == wxT('-')))
// bad key combo; probably also generates an assertion in wx
return wxEmptyString;
return s;
}
wxString wxKeyTextCtrl::ToString(wxAcceleratorEntry_v keys, wxChar sep)
{
wxString ret;
for(int i = 0; i < keys.size(); i++) {
if(i > 0)
ret += sep;
wxString key = ToString(keys[i].GetFlags(), keys[i].GetKeyCode());
if(key.empty())
return wxEmptyString;
ret += key;
}
return ret;
wxString ret;
for (int i = 0; i < keys.size(); i++)
{
if (i > 0)
ret += sep;
wxString key = ToString(keys[i].GetFlags(), keys[i].GetKeyCode());
if (key.empty())
return wxEmptyString;
ret += key;
}
return ret;
}
bool wxKeyTextCtrl::ParseString(const wxChar *s, int len, int &mod, int &key)
bool wxKeyTextCtrl::ParseString(const wxChar* s, int len, int &mod, int &key)
{
mod = key = 0;
if(!s || !len)
return false;
wxString a = wxT('\t');
a.append(s, len);
wxAcceleratorEntry ae;
mod = key = 0;
if (!s || !len)
return false;
wxString a = wxT('\t');
a.append(s, len);
wxAcceleratorEntry ae;
#ifndef __WXMAC__
#define check_meta(str) do { \
wxString meta = str; \
for(int ml = 0; (ml = a.find(meta, ml)) != wxString::npos; ml++) { \
if(!ml || a[ml-1] == wxT('-') || a[ml-1] == wxT('+')) { \
mod |= wxMOD_META; \
a.erase(ml, meta.size()); \
ml = -1; \
} \
if(!ml || a[ml-1] == wxT('-') || a[ml-1] == wxT('+')) { \
mod |= wxMOD_META; \
a.erase(ml, meta.size()); \
ml = -1; \
} \
} \
} while(0)
check_meta(wxT("Meta-"));
check_meta(wxT("Meta+"));
check_meta(_("Meta-"));
check_meta(_("Meta+"));
check_meta(wxT("Meta-"));
check_meta(wxT("Meta+"));
check_meta(_("Meta-"));
check_meta(_("Meta+"));
#endif
// wx disallows standalone modifiers
// unlike ToString(), this generates a debug message rather than
// an assertion error, so it's easy to ignore and expensive to avoid
// beforehand. Instead, check for them on failure
if(!ae.FromString(a)) {
a.MakeUpper();
// wx disallows standalone modifiers
// unlike ToString(), this generates a debug message rather than
// an assertion error, so it's easy to ignore and expensive to avoid
// beforehand. Instead, check for them on failure
if (!ae.FromString(a))
{
a.MakeUpper();
#define chk_str(n, k) do { \
wxString t = n; \
if(a.size() > t.size() && a.substr(a.size() - t.size()) == t) { \
a.replace(a.size() - t.size(), t.size(), wxT("F1")); \
wxString ss(s); \
if(ae.FromString(a)) { \
mod |= ae.GetFlags(); \
key = k; \
return true; \
} \
a.replace(a.size() - 2, 2, n); \
a.replace(a.size() - t.size(), t.size(), wxT("F1")); \
wxString ss(s); \
if(ae.FromString(a)) { \
mod |= ae.GetFlags(); \
key = k; \
return true; \
} \
a.replace(a.size() - 2, 2, n); \
} \
} while(0)
chk_str(wxT("ALT"), WXK_ALT);
chk_str(wxT("SHIFT"), WXK_SHIFT);
chk_str(wxT("CTRL"), WXK_CONTROL);
chk_str(wxT("CONTROL"), WXK_CONTROL);
chk_str(_("ALT"), WXK_ALT);
chk_str(_("SHIFT"), WXK_SHIFT);
chk_str(_("CTRL"), WXK_CONTROL);
chk_str(_("CONTROL"), WXK_CONTROL);
return false;
}
mod |= ae.GetFlags();
key = ae.GetKeyCode();
// wx makes key lower-case, but key events return upper case
if(key < WXK_START && wxIslower(key))
key = wxToupper(key);
return true;
chk_str(wxT("ALT"), WXK_ALT);
chk_str(wxT("SHIFT"), WXK_SHIFT);
chk_str(wxT("CTRL"), WXK_CONTROL);
chk_str(wxT("CONTROL"), WXK_CONTROL);
chk_str(_("ALT"), WXK_ALT);
chk_str(_("SHIFT"), WXK_SHIFT);
chk_str(_("CTRL"), WXK_CONTROL);
chk_str(_("CONTROL"), WXK_CONTROL);
return false;
}
mod |= ae.GetFlags();
key = ae.GetKeyCode();
// wx makes key lower-case, but key events return upper case
if (key < WXK_START && wxIslower(key))
key = wxToupper(key);
return true;
}
bool wxKeyTextCtrl::FromString(const wxString &s, int &mod, int &key)
{
return ParseString(s.c_str(), s.size(), mod, key);
return ParseString(s.c_str(), s.size(), mod, key);
}
wxAcceleratorEntry_v wxKeyTextCtrl::FromString(const wxString &s, wxChar sep)
{
wxAcceleratorEntry_v ret, empty;
int mod, key;
int len = s.size();
wxAcceleratorEntry_v ret, empty;
int mod, key;
int len = s.size();
for(int lastkey = len - 1; (lastkey = s.rfind(sep, lastkey)) != wxString::npos; lastkey--) {
if(lastkey == len - 1) {
// sep as accel
if(!lastkey)
break;
if(s[lastkey - 1] == wxT('-') || s[lastkey - 1] == wxT('+') ||
s[lastkey - 1] == sep)
continue;
for (int lastkey = len - 1; (lastkey = s.rfind(sep, lastkey)) != wxString::npos; lastkey--)
{
if (lastkey == len - 1)
{
// sep as accel
if (!lastkey)
break;
if (s[lastkey - 1] == wxT('-') || s[lastkey - 1] == wxT('+') ||
s[lastkey - 1] == sep)
continue;
}
if (!ParseString(s.c_str() + lastkey + 1, len - lastkey - 1, mod, key))
return empty;
ret.insert(ret.begin(), wxAcceleratorEntry(mod, key));
len = lastkey;
}
if(!ParseString(s.c_str() + lastkey + 1, len - lastkey - 1, mod, key))
return empty;
if (!ParseString(s.c_str(), len, mod, key))
return empty;
ret.insert(ret.begin(), wxAcceleratorEntry(mod, key));
len = lastkey;
}
if(!ParseString(s.c_str(), len, mod, key))
return empty;
ret.insert(ret.begin(), wxAcceleratorEntry(mod, key));
return ret;
return ret;
}
IMPLEMENT_CLASS(wxKeyValidator, wxValidator)
bool wxKeyValidator::TransferToWindow()
{
wxKeyTextCtrl *k = wxDynamicCast(GetWindow(), wxKeyTextCtrl);
if(!k)
return false;
k->SetValue(wxKeyTextCtrl::ToString(*val));
return true;
wxKeyTextCtrl* k = wxDynamicCast(GetWindow(), wxKeyTextCtrl);
if (!k)
return false;
k->SetValue(wxKeyTextCtrl::ToString(*val));
return true;
}
bool wxKeyValidator::TransferFromWindow()
{
wxKeyTextCtrl *k = wxDynamicCast(GetWindow(), wxKeyTextCtrl);
if(!k)
return false;
*val = wxKeyTextCtrl::FromString(k->GetValue());
return true;
wxKeyTextCtrl* k = wxDynamicCast(GetWindow(), wxKeyTextCtrl);
if (!k)
return false;
*val = wxKeyTextCtrl::FromString(k->GetValue());
return true;
}

View File

@ -5,155 +5,196 @@
DEFINE_EVENT_TYPE(wxEVT_SDLJOY)
struct wxSDLJoyState {
SDL_Joystick *dev;
int nax, nhat, nbut;
short *curval;
~wxSDLJoyState() { if(dev) SDL_JoystickClose(dev); }
struct wxSDLJoyState
{
SDL_Joystick* dev;
int nax, nhat, nbut;
short* curval;
~wxSDLJoyState() { if (dev) SDL_JoystickClose(dev); }
};
wxSDLJoy::wxSDLJoy(bool analog) : wxTimer(), digital(!analog),
evthandler(0), joystate(0), nosticks(true)
evthandler(0), joystate(0), nosticks(true)
{
// Start up joystick if not already started
// FIXME: check for errors
SDL_Init(SDL_INIT_JOYSTICK);
// but we'll have to manage it manually
SDL_JoystickEventState(SDL_IGNORE);
// now query joystick config and open joysticks
// there is no way to reread this later (e.g. if joystick plugged in),
// since SDL won't
njoy = SDL_NumJoysticks();
if(!njoy)
return;
joystate = new wxSDLJoyState_t[njoy];
memset(joystate, 0, njoy * sizeof(*joystate));
for(int i = 0; i < njoy; i++) {
SDL_Joystick *dev = joystate[i].dev = SDL_JoystickOpen(i);
int nctrl = 0;
nctrl += joystate[i].nax = SDL_JoystickNumAxes(dev);
nctrl += joystate[i].nhat = SDL_JoystickNumHats(dev);
nctrl += joystate[i].nbut = SDL_JoystickNumButtons(dev);
joystate[i].curval = new short[nctrl];
memset(joystate[i].curval, 0, sizeof(short) * nctrl);
}
// Start up joystick if not already started
// FIXME: check for errors
SDL_Init(SDL_INIT_JOYSTICK);
// but we'll have to manage it manually
SDL_JoystickEventState(SDL_IGNORE);
// now query joystick config and open joysticks
// there is no way to reread this later (e.g. if joystick plugged in),
// since SDL won't
njoy = SDL_NumJoysticks();
if (!njoy)
return;
joystate = new wxSDLJoyState_t[njoy];
memset(joystate, 0, njoy * sizeof(*joystate));
for (int i = 0; i < njoy; i++)
{
SDL_Joystick* dev = joystate[i].dev = SDL_JoystickOpen(i);
int nctrl = 0;
nctrl += joystate[i].nax = SDL_JoystickNumAxes(dev);
nctrl += joystate[i].nhat = SDL_JoystickNumHats(dev);
nctrl += joystate[i].nbut = SDL_JoystickNumButtons(dev);
joystate[i].curval = new short[nctrl];
memset(joystate[i].curval, 0, sizeof(short) * nctrl);
}
}
wxSDLJoy::~wxSDLJoy()
{
delete[] joystate;
// SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
delete[] joystate;
// SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}
wxEvtHandler *wxSDLJoy::Attach(wxEvtHandler *handler)
wxEvtHandler* wxSDLJoy::Attach(wxEvtHandler* handler)
{
wxEvtHandler *prev = evthandler;
evthandler = handler;
return prev;
wxEvtHandler* prev = evthandler;
evthandler = handler;
return prev;
}
void wxSDLJoy::Add(int joy)
{
if(joy >= njoy || !njoy)
return;
if(joy < 0) {
for(int i = 0; i < njoy; i++)
Add(i);
return;
}
if(!joystate[joy].dev)
joystate[joy].dev = SDL_JoystickOpen(joy);
if(nosticks && joystate[joy].dev) {
Start(50);
nosticks = false;
}
if (joy >= njoy || !njoy)
return;
if (joy < 0)
{
for (int i = 0; i < njoy; i++)
Add(i);
return;
}
if (!joystate[joy].dev)
joystate[joy].dev = SDL_JoystickOpen(joy);
if (nosticks && joystate[joy].dev)
{
Start(50);
nosticks = false;
}
}
void wxSDLJoy::Remove(int joy)
{
if(joy >= njoy || !njoy)
return;
if(joy < 0) {
for(int i = 0; i < njoy; i++)
if(joystate[i].dev) {
SDL_JoystickClose(joystate[i].dev);
joystate[i].dev = NULL;
}
if (joy >= njoy || !njoy)
return;
if (joy < 0)
{
for (int i = 0; i < njoy; i++)
if (joystate[i].dev)
{
SDL_JoystickClose(joystate[i].dev);
joystate[i].dev = NULL;
}
Stop();
nosticks = true;
return;
}
if (!joystate[joy].dev)
return;
SDL_JoystickClose(joystate[joy].dev);
joystate[joy].dev = NULL;
for (int i = 0; i < njoy; i++)
if (joystate[i].dev)
return;
Stop();
nosticks = true;
return;
}
if(!joystate[joy].dev)
return;
SDL_JoystickClose(joystate[joy].dev);
joystate[joy].dev = NULL;
for(int i = 0; i < njoy; i++)
if(joystate[i].dev)
return;
Stop();
nosticks = true;
}
void wxSDLJoy::Notify()
{
if(nosticks)
return;
SDL_JoystickUpdate();
wxEvtHandler *handler = evthandler ? evthandler : wxWindow::FindFocus();
for(int i = 0; i < njoy; i++) {
SDL_Joystick *dev = joystate[i].dev;
if(dev) {
int nax = joystate[i].nax, nhat = joystate[i].nhat,
nbut = joystate[i].nbut;
int ctrl = 0;
short val;
for(int j = 0; j < nax; j++) {
val = SDL_JoystickGetAxis(dev, j);
if(digital) {
if(val > 0x3fff)
val = 0x7fff;
else if(val <= -0x3fff)
val = -0x7fff;
else
val = 0;
if (nosticks)
return;
SDL_JoystickUpdate();
wxEvtHandler* handler = evthandler ? evthandler : wxWindow::FindFocus();
for (int i = 0; i < njoy; i++)
{
SDL_Joystick* dev = joystate[i].dev;
if (dev)
{
int nax = joystate[i].nax, nhat = joystate[i].nhat,
nbut = joystate[i].nbut;
int ctrl = 0;
short val;
for (int j = 0; j < nax; j++)
{
val = SDL_JoystickGetAxis(dev, j);
if (digital)
{
if (val > 0x3fff)
val = 0x7fff;
else if (val <= -0x3fff)
val = -0x7fff;
else
val = 0;
}
if (handler && val != joystate[i].curval[j])
{
wxSDLJoyEvent ev(wxEVT_SDLJOY, GetId());
ev.joy = i;
ev.ctrl_type = WXSDLJOY_AXIS;
ev.ctrl_idx = j;
ev.ctrl_val = val;
ev.prev_val = joystate[i].curval[j];
handler->ProcessEvent(ev);
}
joystate[i].curval[j] = val;
}
for (int j = 0; j < nhat; j++)
{
val = SDL_JoystickGetHat(dev, j);
if (handler && val != joystate[i].curval[nax + j])
{
wxSDLJoyEvent ev(wxEVT_SDLJOY, GetId());
ev.joy = i;
ev.ctrl_type = WXSDLJOY_HAT;
ev.ctrl_idx = j;
ev.ctrl_val = val;
ev.prev_val = joystate[i].curval[nax + j];
handler->ProcessEvent(ev);
}
joystate[i].curval[nax + j] = val;
}
for (int j = 0; j < nbut; j++)
{
val = SDL_JoystickGetButton(dev, j);
if (handler && val != joystate[i].curval[nax + nhat + j])
{
wxSDLJoyEvent ev(wxEVT_SDLJOY, GetId());
ev.joy = i;
ev.ctrl_type = WXSDLJOY_BUTTON;
ev.ctrl_idx = j;
ev.ctrl_val = val;
ev.prev_val = joystate[i].curval[nax + nhat + j];
handler->ProcessEvent(ev);
}
joystate[i].curval[nax + nhat + j] = val;
}
}
if(handler && val != joystate[i].curval[j]) {
wxSDLJoyEvent ev(wxEVT_SDLJOY, GetId());
ev.joy = i;
ev.ctrl_type = WXSDLJOY_AXIS;
ev.ctrl_idx = j;
ev.ctrl_val = val;
ev.prev_val = joystate[i].curval[j];
handler->ProcessEvent(ev);
}
joystate[i].curval[j] = val;
}
for(int j = 0; j < nhat; j++) {
val = SDL_JoystickGetHat(dev, j);
if(handler && val != joystate[i].curval[nax + j]) {
wxSDLJoyEvent ev(wxEVT_SDLJOY, GetId());
ev.joy = i;
ev.ctrl_type = WXSDLJOY_HAT;
ev.ctrl_idx = j;
ev.ctrl_val = val;
ev.prev_val = joystate[i].curval[nax + j];
handler->ProcessEvent(ev);
}
joystate[i].curval[nax + j] = val;
}
for(int j = 0; j < nbut; j++) {
val = SDL_JoystickGetButton(dev, j);
if(handler && val != joystate[i].curval[nax + nhat + j]) {
wxSDLJoyEvent ev(wxEVT_SDLJOY, GetId());
ev.joy = i;
ev.ctrl_type = WXSDLJOY_BUTTON;
ev.ctrl_idx = j;
ev.ctrl_val = val;
ev.prev_val = joystate[i].curval[nax + nhat + j];
handler->ProcessEvent(ev);
}
joystate[i].curval[nax + nhat + j] = val;
}
}
}
}

View File

@ -14,25 +14,25 @@
#define _WX_CHECKEDLISTCTRL_H_
// wxWidgets headers
#include "wx/webupdatedef.h" // for the WXDLLIMPEXP_WEBUPDATE macro
#include "wx/webupdatedef.h" // for the WXDLLIMPEXP_WEBUPDATE macro
#include <wx/listctrl.h>
#include <wx/imaglist.h>
#if wxUSE_CHECKEDLISTCTRL
// image indexes (used internally by wxCheckedListCtrl)
#define wxCLC_UNCHECKED_IMGIDX 0 // unchecked & enabled
#define wxCLC_CHECKED_IMGIDX 1 // checked & enabled
#define wxCLC_DISABLED_UNCHECKED_IMGIDX 2 // unchecked & disabled
#define wxCLC_DISABLED_CHECKED_IMGIDX 3 // checked & disabled
#define wxCLC_UNCHECKED_IMGIDX 0 // unchecked & enabled
#define wxCLC_CHECKED_IMGIDX 1 // checked & enabled
#define wxCLC_DISABLED_UNCHECKED_IMGIDX 2 // unchecked & disabled
#define wxCLC_DISABLED_CHECKED_IMGIDX 3 // checked & disabled
// additional state flags (wx's defines should end at 0x0100; see listbase.h)
#define wxLIST_STATE_CHECKED 0x010000
#define wxLIST_STATE_ENABLED 0x100000
#define wxLIST_STATE_CHECKED 0x010000
#define wxLIST_STATE_ENABLED 0x100000
// additional wxCheckedListCtrl style flags
// (wx's defines should at 0x8000; see listbase.h)
#define wxCLC_CHECK_WHEN_SELECTING 0x10000
#define wxCLC_CHECK_WHEN_SELECTING 0x10000
// -------------------------
@ -63,7 +63,7 @@ DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_WEBUPDATE, wxEVT_COMMAND_LIST_ITEM_UNCHE
class WXDLLIMPEXP_WEBUPDATE wxCheckedListCtrl : public wxListCtrl
{
protected:
// we have to keep a different array to keep track of the additional
// states we support....
wxArrayInt m_stateList;
@ -79,25 +79,25 @@ public:
: wxListCtrl(), m_imageList(16, 16, TRUE) {}
#endif
wxCheckedListCtrl(wxWindow *parent, wxWindowID id = -1,
const wxPoint& pt = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
long style = wxCLC_CHECK_WHEN_SELECTING,
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxListCtrlNameStr)
wxCheckedListCtrl(wxWindow* parent, wxWindowID id = -1,
const wxPoint &pt = wxDefaultPosition,
const wxSize &sz = wxDefaultSize,
long style = wxCLC_CHECK_WHEN_SELECTING,
const wxValidator &validator = wxDefaultValidator,
const wxString &name = wxListCtrlNameStr)
#if CLC_VBAM_USAGE && CLC_USE_SYSICONS
: wxListCtrl(), m_imageList()
: wxListCtrl(), m_imageList()
#else
: wxListCtrl(), m_imageList(16, 16, TRUE)
: wxListCtrl(), m_imageList(16, 16, TRUE)
#endif
{ Create(parent, id, pt, sz, style, validator, name); }
bool Create(wxWindow *parent, wxWindowID id = -1,
const wxPoint& pt = wxDefaultPosition,
const wxSize& sz = wxDefaultSize,
long style = wxCLC_CHECK_WHEN_SELECTING,
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxListCtrlNameStr);
{ Create(parent, id, pt, sz, style, validator, name); }
bool Create(wxWindow* parent, wxWindowID id = -1,
const wxPoint &pt = wxDefaultPosition,
const wxSize &sz = wxDefaultSize,
long style = wxCLC_CHECK_WHEN_SELECTING,
const wxValidator &validator = wxDefaultValidator,
const wxString &name = wxListCtrlNameStr);
#ifdef CLC_VBAM_USAGE
// for xrc usage, a separate init function is needed.
@ -106,19 +106,19 @@ public:
virtual ~wxCheckedListCtrl() {}
public: // utilities
public: // utilities
// core overloads (i.e. the most generic overloads)
bool GetItem(wxListItem& info) const;
bool SetItem(wxListItem& info);
long InsertItem(wxListItem& info);
bool DeleteItem(long item);
bool GetItem(wxListItem &info) const;
bool SetItem(wxListItem &info);
long InsertItem(wxListItem &info);
bool DeleteItem(long item);
bool DeleteAllItems()
{ m_stateList.Clear(); return wxListCtrl::DeleteAllItems(); }
{ m_stateList.Clear(); return wxListCtrl::DeleteAllItems(); }
bool SortItems(wxListCtrlCompare, long)
{ wxASSERT_MSG(0, wxT("Not implemented yet ! sorry... ")); return FALSE; }
{ wxASSERT_MSG(0, wxT("Not implemented yet ! sorry... ")); return FALSE; }
// shortcuts to the SetItemState function
void Check(long item, bool checked);
void Enable(long item, bool enable);
@ -129,17 +129,17 @@ public: // utilities
// However you should use #EnableAll instead of this function if you want to get
// good graphics (try to understand)
virtual bool Enable(bool enable = true)
{ return wxListCtrl::Enable(enable); }
{ return wxListCtrl::Enable(enable); }
// shortcuts to the GetItemState function
bool IsChecked(long item) const
{ return GetItemState(item, wxLIST_STATE_CHECKED) != 0; }
{ return GetItemState(item, wxLIST_STATE_CHECKED) != 0; }
bool IsEnabled(long item) const
{ return GetItemState(item, wxLIST_STATE_ENABLED) != 0; }
{ return GetItemState(item, wxLIST_STATE_ENABLED) != 0; }
// this needs to be redeclared otherwise it's hidden by our other IsEnabled() function.
bool IsEnabled() const
{ return wxWindow::IsEnabled(); }
{ return wxWindow::IsEnabled(); }
//! Returns the number of checked items in the control.
int GetCheckedItemCount() const;
@ -148,22 +148,22 @@ public: // utilities
// #GetItem and #SetItem functions...
bool SetItemState(long item, long state, long stateMask);
int GetItemState(long item, long stateMask) const;
long InsertItem( long index, const wxString& label, int imageIndex = -1);
long SetItem(long index, int col, const wxString& label, int imageId = -1);
long InsertItem(long index, const wxString &label, int imageIndex = -1);
long SetItem(long index, int col, const wxString &label, int imageId = -1);
// the image associated with an element is already in used by wxCheckedListCtrl
// itself to show the checkbox and it cannot be handled by the user !
bool SetItemImage(long, int)
{ wxASSERT_MSG(0, wxT("This function cannot be used with wxCheckedListCtrl !")); return FALSE; }
{ wxASSERT_MSG(0, wxT("This function cannot be used with wxCheckedListCtrl !")); return FALSE; }
protected: // event handlers
protected: // event handlers
void OnMouseEvent(wxMouseEvent& event);
void OnMouseEvent(wxMouseEvent &event);
protected: // internal utilities
protected: // internal utilities
static int GetItemImageFromAdditionalState(int addstate);
static int GetAndRemoveAdditionalState(long *state, int statemask);
static int GetAndRemoveAdditionalState(long* state, int statemask);
wxColour GetBgColourFromAdditionalState(int additionalstate);
private:
@ -176,7 +176,7 @@ private:
};
#endif // wxUSE_CHECKEDLISTCTRL
#endif // wxUSE_CHECKEDLISTCTRL
#endif // _WX_CHECKEDLISTCTRL_H_
#endif // _WX_CHECKEDLISTCTRL_H_

View File

@ -8,68 +8,70 @@
#include "wx/keyedit.h"
#include "wx/sdljoy.h"
typedef struct wxJoyKeyBinding {
int key; // key code; listed first for easy static init
int mod; // modifier flags
int joy; // joystick # (starting at 1)
// if joy is non-0, key = control number, and mod = control type
typedef struct wxJoyKeyBinding
{
int key; // key code; listed first for easy static init
int mod; // modifier flags
int joy; // joystick # (starting at 1)
// if joy is non-0, key = control number, and mod = control type
} wxJoyKeyBinding;
typedef std::vector<wxJoyKeyBinding> wxJoyKeyBinding_v;
// joystick control types
// mod for joysticks
enum {
WXJB_AXIS_PLUS, WXJB_AXIS_MINUS, WXJB_BUTTON, WXJB_HAT_FIRST,
WXJB_HAT_N = WXJB_HAT_FIRST, WXJB_HAT_S, WXJB_HAT_W, WXJB_HAT_E, WXJB_HAT_NW,
WXJB_HAT_NE, WXJB_HAT_SW, WXJB_HAT_SE, WXJB_HAT_LAST = WXJB_HAT_SE
enum
{
WXJB_AXIS_PLUS, WXJB_AXIS_MINUS, WXJB_BUTTON, WXJB_HAT_FIRST,
WXJB_HAT_N = WXJB_HAT_FIRST, WXJB_HAT_S, WXJB_HAT_W, WXJB_HAT_E, WXJB_HAT_NW,
WXJB_HAT_NE, WXJB_HAT_SW, WXJB_HAT_SE, WXJB_HAT_LAST = WXJB_HAT_SE
};
class wxJoyKeyTextCtrl : public wxKeyTextCtrl
{
public:
// default constructor; required for use with xrc
// FIXME: clearable and keyenter should be style flags
wxJoyKeyTextCtrl() : wxKeyTextCtrl() {}
virtual ~wxJoyKeyTextCtrl() {};
// default constructor; required for use with xrc
// FIXME: clearable and keyenter should be style flags
wxJoyKeyTextCtrl() : wxKeyTextCtrl() {}
virtual ~wxJoyKeyTextCtrl() {};
// key is event.GetControlIndex(), and joy is event.GetJoy() + 1
// mod is derived from GetControlValue() and GetControlType():
// convert wxSDLJoyEvent's type+val into mod (WXJB_*)
static int DigitalButton(wxSDLJoyEvent &event);
// convert mod+key to accel string, separated by -
static wxString ToString(int mod, int key, int joy);
// convert multiple keys, separated by multikey
static wxString ToString(wxJoyKeyBinding_v keys, wxChar sep = wxT(','));
// parses single key string into mod+key
static bool FromString(const wxString &s, int &mod, int &key, int &joy);
// parse multi-key string into array
// returns empty array on parse errors
static wxJoyKeyBinding_v FromString(const wxString &s, wxChar sep = wxT(','));
// parse a single key in given wxChar array up to given len
static bool ParseString(const wxChar *s, int len, int &mod, int &key, int &joy);
// key is event.GetControlIndex(), and joy is event.GetJoy() + 1
// mod is derived from GetControlValue() and GetControlType():
// convert wxSDLJoyEvent's type+val into mod (WXJB_*)
static int DigitalButton(wxSDLJoyEvent &event);
// convert mod+key to accel string, separated by -
static wxString ToString(int mod, int key, int joy);
// convert multiple keys, separated by multikey
static wxString ToString(wxJoyKeyBinding_v keys, wxChar sep = wxT(','));
// parses single key string into mod+key
static bool FromString(const wxString &s, int &mod, int &key, int &joy);
// parse multi-key string into array
// returns empty array on parse errors
static wxJoyKeyBinding_v FromString(const wxString &s, wxChar sep = wxT(','));
// parse a single key in given wxChar array up to given len
static bool ParseString(const wxChar* s, int len, int &mod, int &key, int &joy);
protected:
void OnJoy(wxSDLJoyEvent &);
void OnJoy(wxSDLJoyEvent &);
DECLARE_DYNAMIC_CLASS();
DECLARE_EVENT_TABLE();
DECLARE_DYNAMIC_CLASS();
DECLARE_EVENT_TABLE();
};
// A simple copy-only validator
class wxJoyKeyValidator : public wxValidator
{
public:
wxJoyKeyValidator(wxJoyKeyBinding_v *v) : wxValidator(), val(v) {}
wxJoyKeyValidator(const wxJoyKeyValidator &v) : wxValidator(), val(v.val) {}
wxObject *Clone() const { return new wxJoyKeyValidator(val); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow *p) { return true; }
wxJoyKeyValidator(wxJoyKeyBinding_v* v) : wxValidator(), val(v) {}
wxJoyKeyValidator(const wxJoyKeyValidator &v) : wxValidator(), val(v.val) {}
wxObject* Clone() const { return new wxJoyKeyValidator(val); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow* p) { return true; }
protected:
wxJoyKeyBinding_v *val;
wxJoyKeyBinding_v* val;
DECLARE_CLASS(wxJoyKeyValidator)
DECLARE_CLASS(wxJoyKeyValidator)
};
#endif /* WX_JOYKEYTEXT_H */

View File

@ -14,62 +14,62 @@ typedef std::vector<wxAcceleratorEntry> wxAcceleratorEntry_v;
class wxKeyTextCtrl : public wxTextCtrl
{
public:
// default constructor; required for use with xrc
// FIXME: clearable and keyenter should be style flags
wxKeyTextCtrl() : wxTextCtrl(), clearable(true), multikey(wxT(',')),
keyenter(true), lastmod(0), lastkey(0) {};
virtual ~wxKeyTextCtrl() {};
// default constructor; required for use with xrc
// FIXME: clearable and keyenter should be style flags
wxKeyTextCtrl() : wxTextCtrl(), clearable(true), multikey(wxT(',')),
keyenter(true), lastmod(0), lastkey(0) {};
virtual ~wxKeyTextCtrl() {};
void SetClearable(bool set = true) { clearable = set; }
void SetMultikey(wxChar c = wxT(',')) { multikey = c; }
void SetKeyEnter(bool set = true) { keyenter = set; }
void SetClearable(bool set = true) { clearable = set; }
void SetMultikey(wxChar c = wxT(',')) { multikey = c; }
void SetKeyEnter(bool set = true) { keyenter = set; }
bool GetClearable() { return clearable; }
wxChar GetMultikey() { return multikey; }
bool GetKeyEnter() { return keyenter; }
bool GetClearable() { return clearable; }
wxChar GetMultikey() { return multikey; }
bool GetKeyEnter() { return keyenter; }
// convert mod+key to accel string, separated by -
static wxString ToString(int mod, int key);
// convert multiple keys, separated by multikey
static wxString ToString(wxAcceleratorEntry_v keys, wxChar sep = wxT(','));
// parses single key string into mod+key
static bool FromString(const wxString &s, int &mod, int &key);
// parse multi-key string into accelentry array
// note that meta flag may be set in accelentry array item even
// where not supported for accelerators (i.e. non-mac)
// returns empty array on parse errors
static wxAcceleratorEntry_v FromString(const wxString &s, wxChar sep = wxT(','));
// parse a single key in given wxChar array up to given len
static bool ParseString(const wxChar *s, int len, int &mod, int &key);
// convert mod+key to accel string, separated by -
static wxString ToString(int mod, int key);
// convert multiple keys, separated by multikey
static wxString ToString(wxAcceleratorEntry_v keys, wxChar sep = wxT(','));
// parses single key string into mod+key
static bool FromString(const wxString &s, int &mod, int &key);
// parse multi-key string into accelentry array
// note that meta flag may be set in accelentry array item even
// where not supported for accelerators (i.e. non-mac)
// returns empty array on parse errors
static wxAcceleratorEntry_v FromString(const wxString &s, wxChar sep = wxT(','));
// parse a single key in given wxChar array up to given len
static bool ParseString(const wxChar* s, int len, int &mod, int &key);
protected:
void OnKeyDown(wxKeyEvent &);
void OnKeyUp(wxKeyEvent &);
void OnKeyDown(wxKeyEvent &);
void OnKeyUp(wxKeyEvent &);
bool clearable;
wxChar multikey;
bool keyenter;
// the last keydown event received; this is processed on next keyup
int lastmod, lastkey;
bool clearable;
wxChar multikey;
bool keyenter;
// the last keydown event received; this is processed on next keyup
int lastmod, lastkey;
DECLARE_DYNAMIC_CLASS();
DECLARE_EVENT_TABLE();
DECLARE_DYNAMIC_CLASS();
DECLARE_EVENT_TABLE();
};
// A simple copy-only validator
class wxKeyValidator : public wxValidator
{
public:
wxKeyValidator(wxAcceleratorEntry_v *v) : wxValidator(), val(v) {}
wxKeyValidator(const wxKeyValidator &v) : wxValidator(), val(v.val) {}
wxObject *Clone() const { return new wxKeyValidator(val); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow *p) { return true; }
wxKeyValidator(wxAcceleratorEntry_v* v) : wxValidator(), val(v) {}
wxKeyValidator(const wxKeyValidator &v) : wxValidator(), val(v.val) {}
wxObject* Clone() const { return new wxKeyValidator(val); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow* p) { return true; }
protected:
wxAcceleratorEntry_v *val;
wxAcceleratorEntry_v* val;
DECLARE_CLASS(wxKeyValidator)
DECLARE_CLASS(wxKeyValidator)
};
#endif /* WX_KEYTEXT_H */

View File

@ -18,77 +18,78 @@ typedef struct wxSDLJoyState wxSDLJoyState_t;
class wxSDLJoy : public wxTimer
{
public:
// if analog, send events for all axis movement
// otherwise, only send events when values cross the 50% mark
// and max out values
wxSDLJoy(bool analog = false);
// but flag can be set later
void SetAnalog(bool analog = true) { digital = !analog; };
// send events to this handler
// If NULL (default), send to window with keyboard focus
wxEvtHandler *Attach(wxEvtHandler *);
// add another joystick to the list of polled sticks
// -1 == add all
// If joy > # of joysticks, it is ignored
// This will start polling if a valid joystick is selected
void Add(int joy = -1);
// remove a joystick from the polled sticks
// -1 == remove all
// If joy > # of joysticks, it is ignored
// This will stop polling if all joysticks are disabled
void Remove(int joy = -1);
// query if a stick is being polled
bool IsPolling(int joy);
// query # of joysticks
int GetNumJoysticks() { return njoy; }
// query # of axes on given joystick
// 0 is returned if joy is invalid
int GetNumAxes(int joy);
// query # of hats on given joystick
// 0 is returned if joy is invalid
int GetNumHats(int joy);
// query # of buttons on given joystick
// 0 is returned if joy is invalid
int GetNumButtons(int joy);
// if analog, send events for all axis movement
// otherwise, only send events when values cross the 50% mark
// and max out values
wxSDLJoy(bool analog = false);
// but flag can be set later
void SetAnalog(bool analog = true) { digital = !analog; };
// send events to this handler
// If NULL (default), send to window with keyboard focus
wxEvtHandler* Attach(wxEvtHandler*);
// add another joystick to the list of polled sticks
// -1 == add all
// If joy > # of joysticks, it is ignored
// This will start polling if a valid joystick is selected
void Add(int joy = -1);
// remove a joystick from the polled sticks
// -1 == remove all
// If joy > # of joysticks, it is ignored
// This will stop polling if all joysticks are disabled
void Remove(int joy = -1);
// query if a stick is being polled
bool IsPolling(int joy);
// query # of joysticks
int GetNumJoysticks() { return njoy; }
// query # of axes on given joystick
// 0 is returned if joy is invalid
int GetNumAxes(int joy);
// query # of hats on given joystick
// 0 is returned if joy is invalid
int GetNumHats(int joy);
// query # of buttons on given joystick
// 0 is returned if joy is invalid
int GetNumButtons(int joy);
virtual ~wxSDLJoy();
virtual ~wxSDLJoy();
protected:
bool digital;
int njoy;
wxSDLJoyState_t *joystate;
wxEvtHandler *evthandler;
bool nosticks;
void Notify();
bool digital;
int njoy;
wxSDLJoyState_t* joystate;
wxEvtHandler* evthandler;
bool nosticks;
void Notify();
};
enum {
// The types of supported controls
// values are signed-16 for axis, 0/1 for button
// hat is bitmask NESW/URDL
WXSDLJOY_AXIS, WXSDLJOY_HAT, WXSDLJOY_BUTTON
enum
{
// The types of supported controls
// values are signed-16 for axis, 0/1 for button
// hat is bitmask NESW/URDL
WXSDLJOY_AXIS, WXSDLJOY_HAT, WXSDLJOY_BUTTON
};
class wxSDLJoyEvent : public wxCommandEvent
{
friend class wxSDLJoy;
friend class wxSDLJoy;
public:
// Default constructor
wxSDLJoyEvent(wxEventType commandType = wxEVT_NULL, int id = 0) :
wxCommandEvent(commandType, id) {}
// accessors
unsigned short GetJoy() { return joy; }
unsigned short GetControlType() { return ctrl_type; }
unsigned short GetControlIndex() { return ctrl_idx; }
short GetControlValue() { return ctrl_val; }
short GetControlPrevValue() { return prev_val; }
// required for PostEvent, apparently
wxEvent *Clone();
// Default constructor
wxSDLJoyEvent(wxEventType commandType = wxEVT_NULL, int id = 0) :
wxCommandEvent(commandType, id) {}
// accessors
unsigned short GetJoy() { return joy; }
unsigned short GetControlType() { return ctrl_type; }
unsigned short GetControlIndex() { return ctrl_idx; }
short GetControlValue() { return ctrl_val; }
short GetControlPrevValue() { return prev_val; }
// required for PostEvent, apparently
wxEvent* Clone();
protected:
unsigned short joy;
unsigned short ctrl_type;
unsigned short ctrl_idx;
short ctrl_val;
short prev_val;
unsigned short joy;
unsigned short ctrl_type;
unsigned short ctrl_idx;
short ctrl_val;
short prev_val;
};
// Note: this means sdljoy can't be part of a library w/o extra work
@ -96,7 +97,7 @@ DECLARE_LOCAL_EVENT_TYPE(wxEVT_SDLJOY, -1)
typedef void (wxEvtHandler::*wxSDLJoyEventFunction)(wxSDLJoyEvent &);
#define EVT_SDLJOY(fn) \
DECLARE_EVENT_TABLE_ENTRY(wxEVT_SDLJOY, wxID_ANY, wxID_ANY, \
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) \
wxStaticCastEvent(wxSDLJoyEventFunction, &fn), (wxObject *)NULL), \
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) \
wxStaticCastEvent(wxSDLJoyEventFunction, &fn), (wxObject *)NULL), \
#endif /* JOYEVT_H */

View File

@ -7,21 +7,21 @@
class wxFarRadio : public wxCheckBox
{
public:
wxFarRadio();
virtual ~wxFarRadio();
void SetValue(bool val);
// join this group with widget(s) in grp
void SetGroup(class wxFarRadio *grp);
// turn into a singleton
void BreakGroup();
// iterate over members in group (ring)
wxFarRadio *GetNext();
wxFarRadio();
virtual ~wxFarRadio();
void SetValue(bool val);
// join this group with widget(s) in grp
void SetGroup(class wxFarRadio* grp);
// turn into a singleton
void BreakGroup();
// iterate over members in group (ring)
wxFarRadio* GetNext();
protected:
void UpdatedValue();
void UpdateEvt(wxCommandEvent &ev);
wxFarRadio *Next;
DECLARE_DYNAMIC_CLASS()
DECLARE_EVENT_TABLE()
void UpdatedValue();
void UpdateEvt(wxCommandEvent &ev);
wxFarRadio* Next;
DECLARE_DYNAMIC_CLASS()
DECLARE_EVENT_TABLE()
};
// boolean copy-only validator that uses a constant int
@ -29,16 +29,16 @@ protected:
class wxBoolIntValidator : public wxValidator
{
public:
wxBoolIntValidator(int *_vptr, int _val, int _mask = ~0) : wxValidator(),
vptr(_vptr), val(_val), mask(_mask) {}
wxBoolIntValidator(const wxBoolIntValidator &v) : wxValidator(),
vptr(v.vptr), val(v.val), mask(v.mask) {}
wxObject *Clone() const { return new wxBoolIntValidator(vptr, val, mask); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow *p) { return true; }
wxBoolIntValidator(int* _vptr, int _val, int _mask = ~0) : wxValidator(),
vptr(_vptr), val(_val), mask(_mask) {}
wxBoolIntValidator(const wxBoolIntValidator &v) : wxValidator(),
vptr(v.vptr), val(v.val), mask(v.mask) {}
wxObject* Clone() const { return new wxBoolIntValidator(vptr, val, mask); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow* p) { return true; }
protected:
int val, mask, *vptr;
int val, mask, *vptr;
};
// boolean copy-only validator with reversed value
@ -46,29 +46,29 @@ protected:
class wxBoolRevValidator : public wxValidator
{
public:
wxBoolRevValidator(bool *_vptr) : wxValidator(), vptr(_vptr) {}
wxBoolRevValidator(const wxBoolRevValidator &v) : wxValidator(), vptr(v.vptr) {}
wxObject *Clone() const { return new wxBoolRevValidator(vptr); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow *p) { return true; }
wxBoolRevValidator(bool* _vptr) : wxValidator(), vptr(_vptr) {}
wxBoolRevValidator(const wxBoolRevValidator &v) : wxValidator(), vptr(v.vptr) {}
wxObject* Clone() const { return new wxBoolRevValidator(vptr); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow* p) { return true; }
protected:
bool *vptr;
bool* vptr;
};
// wxFilePickerCtrl/wxDirPickerCtrl copy-only vvalidator
class wxFileDirPickerValidator : public wxValidator
{
public:
wxFileDirPickerValidator(wxString *_vptr) : wxValidator(), vptr(_vptr) {}
wxFileDirPickerValidator(const wxFileDirPickerValidator &v) : wxValidator(),
vptr(v.vptr) {}
wxObject *Clone() const { return new wxFileDirPickerValidator(vptr); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow *p) { return true; }
wxFileDirPickerValidator(wxString* _vptr) : wxValidator(), vptr(_vptr) {}
wxFileDirPickerValidator(const wxFileDirPickerValidator &v) : wxValidator(),
vptr(v.vptr) {}
wxObject* Clone() const { return new wxFileDirPickerValidator(vptr); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow* p) { return true; }
protected:
wxString *vptr;
wxString* vptr;
};
@ -81,17 +81,17 @@ protected:
class wxColorValidator : public wxValidator
{
public:
wxColorValidator(uint32_t *vptr) : wxValidator(), ptr32(vptr), ptr16(0) {}
wxColorValidator(uint16_t *vptr) : wxValidator(), ptr16(vptr), ptr32(0) {}
wxColorValidator(const wxColorValidator &v) : wxValidator(),
ptr32(v.ptr32), ptr16(v.ptr16) {}
wxObject *Clone() const { return new wxColorValidator(*this); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow *p) { return true; }
wxColorValidator(uint32_t* vptr) : wxValidator(), ptr32(vptr), ptr16(0) {}
wxColorValidator(uint16_t* vptr) : wxValidator(), ptr16(vptr), ptr32(0) {}
wxColorValidator(const wxColorValidator &v) : wxValidator(),
ptr32(v.ptr32), ptr16(v.ptr16) {}
wxObject* Clone() const { return new wxColorValidator(*this); }
bool TransferToWindow();
bool TransferFromWindow();
bool Validate(wxWindow* p) { return true; }
protected:
uint32_t *ptr32;
uint16_t *ptr16;
uint32_t* ptr32;
uint16_t* ptr16;
};
// Copy-only validators for checkboxes and radio buttons that enables a set
@ -103,62 +103,62 @@ protected:
// there's probably a standard wxWindowList or some such, but it's
// undocumented and I prefer arrays
typedef std::vector<wxWindow *>wxWindow_v;
typedef std::vector<wxWindow*>wxWindow_v;
class wxBoolEnValidator : public wxGenericValidator
{
public:
wxBoolEnValidator(bool *vptr) : wxGenericValidator(vptr) {}
wxBoolEnValidator(bool *vptr, wxWindow_v &cnt, std::vector<int>rev = std::vector<int>()) :
wxGenericValidator(vptr), controls(cnt), reverse(rev) {}
wxBoolEnValidator(const wxBoolEnValidator &v) : wxGenericValidator(v),
controls(v.controls), reverse(v.reverse) {}
wxObject *Clone() const { return new wxBoolEnValidator(*this); }
// set these after init, rather than in constructor
wxWindow_v controls;
// set reverse entries to true if disabled when checkbox checked
// controls past the end of the reverse array are not reversed
std::vector<int> reverse;
// inherit validate, xferfrom from parent
bool TransferToWindow();
wxBoolEnValidator(bool* vptr) : wxGenericValidator(vptr) {}
wxBoolEnValidator(bool* vptr, wxWindow_v &cnt, std::vector<int>rev = std::vector<int>()) :
wxGenericValidator(vptr), controls(cnt), reverse(rev) {}
wxBoolEnValidator(const wxBoolEnValidator &v) : wxGenericValidator(v),
controls(v.controls), reverse(v.reverse) {}
wxObject* Clone() const { return new wxBoolEnValidator(*this); }
// set these after init, rather than in constructor
wxWindow_v controls;
// set reverse entries to true if disabled when checkbox checked
// controls past the end of the reverse array are not reversed
std::vector<int> reverse;
// inherit validate, xferfrom from parent
bool TransferToWindow();
};
class wxBoolIntEnValidator : public wxBoolIntValidator
{
public:
wxBoolIntEnValidator(int *vptr, int val, int mask = ~0) :
wxBoolIntValidator(vptr, val, mask) {}
wxBoolIntEnValidator(int *vptr, int val, int mask, wxWindow_v &cnt,
std::vector<int>rev = std::vector<int>()) :
wxBoolIntValidator(vptr, val, mask), controls(cnt), reverse(rev) {}
wxBoolIntEnValidator(const wxBoolIntEnValidator &v) :
wxBoolIntValidator(v), controls(v.controls), reverse(v.reverse) {}
wxObject *Clone() const { return new wxBoolIntEnValidator(*this); }
// set these after init, rather than in constructor
wxWindow_v controls;
// set reverse entries to true if disabled when checkbox checked
// controls past the end of the reverse array are not reversed
std::vector<int> reverse;
// inherit validate, xferfrom from parent
bool TransferToWindow();
wxBoolIntEnValidator(int* vptr, int val, int mask = ~0) :
wxBoolIntValidator(vptr, val, mask) {}
wxBoolIntEnValidator(int* vptr, int val, int mask, wxWindow_v &cnt,
std::vector<int>rev = std::vector<int>()) :
wxBoolIntValidator(vptr, val, mask), controls(cnt), reverse(rev) {}
wxBoolIntEnValidator(const wxBoolIntEnValidator &v) :
wxBoolIntValidator(v), controls(v.controls), reverse(v.reverse) {}
wxObject* Clone() const { return new wxBoolIntEnValidator(*this); }
// set these after init, rather than in constructor
wxWindow_v controls;
// set reverse entries to true if disabled when checkbox checked
// controls past the end of the reverse array are not reversed
std::vector<int> reverse;
// inherit validate, xferfrom from parent
bool TransferToWindow();
};
class wxBoolRevEnValidator : public wxBoolRevValidator
{
public:
wxBoolRevEnValidator(bool *vptr) : wxBoolRevValidator(vptr) {}
wxBoolRevEnValidator(bool *vptr, wxWindow_v &cnt, std::vector<int>rev = std::vector<int>()) :
wxBoolRevValidator(vptr), controls(cnt), reverse(rev) {}
wxBoolRevEnValidator(const wxBoolRevEnValidator &v) : wxBoolRevValidator(v),
controls(v.controls), reverse(v.reverse) {}
wxObject *Clone() const { return new wxBoolRevEnValidator(*this); }
// set these after init, rather than in constructor
wxWindow_v controls;
// set reverse entries to true if disabled when checkbox checked
// controls past the end of the reverse array are not reversed
std::vector<int> reverse;
// inherit validate, xferfrom from parent
bool TransferToWindow();
wxBoolRevEnValidator(bool* vptr) : wxBoolRevValidator(vptr) {}
wxBoolRevEnValidator(bool* vptr, wxWindow_v &cnt, std::vector<int>rev = std::vector<int>()) :
wxBoolRevValidator(vptr), controls(cnt), reverse(rev) {}
wxBoolRevEnValidator(const wxBoolRevEnValidator &v) : wxBoolRevValidator(v),
controls(v.controls), reverse(v.reverse) {}
wxObject* Clone() const { return new wxBoolRevEnValidator(*this); }
// set these after init, rather than in constructor
wxWindow_v controls;
// set reverse entries to true if disabled when checkbox checked
// controls past the end of the reverse array are not reversed
std::vector<int> reverse;
// inherit validate, xferfrom from parent
bool TransferToWindow();
};
// and here's an event handler that can be attached to the widget or a parent
@ -168,23 +168,23 @@ public:
class wxBoolEnHandler : public wxEvtHandler
{
public:
wxWindow_v controls;
std::vector<int> reverse;
void ToggleCheck(wxCommandEvent &ev);
void Enable(wxCommandEvent &ev);
void Disable(wxCommandEvent &ev);
wxWindow_v controls;
std::vector<int> reverse;
void ToggleCheck(wxCommandEvent &ev);
void Enable(wxCommandEvent &ev);
void Disable(wxCommandEvent &ev);
};
// use this to connect to the handler of id in win to obj
#define wxCBBoolEnHandlerConnect(win, id, obj) \
(win)->Connect(id, wxEVT_COMMAND_CHECKBOX_CLICKED, \
wxCommandEventHandler(wxBoolEnHandler::ToggleCheck), NULL, \
&obj)
wxCommandEventHandler(wxBoolEnHandler::ToggleCheck), NULL, \
&obj)
#define wxRBBoolEnHandlerConnect(win, id, obj, f) \
(win)->Connect(id, wxEVT_COMMAND_RADIOBUTTON_SELECTED, \
wxCommandEventHandler(wxBoolEnHandler::f), NULL, \
&obj)
wxCommandEventHandler(wxBoolEnHandler::f), NULL, \
&obj)
#define wxRBEBoolEnHandlerConnect(win, id, obj) wxRBBoolEnHandlerConnect(win, id, obj, Enable)
#define wxRBDBoolEnHandlerConnect(win, id, obj) wxRBBoolEnHandlerConnect(win, id, obj, Disable)

View File

@ -3,254 +3,322 @@
#include "wx/wxmisc.h"
wxFarRadio::wxFarRadio()
: wxCheckBox()
: wxCheckBox()
{
Next = this;
Next = this;
}
wxFarRadio::~wxFarRadio()
{
BreakGroup();
BreakGroup();
}
void wxFarRadio::SetValue(bool val)
{
wxCheckBox::SetValue(val);
UpdatedValue();
wxCheckBox::SetValue(val);
UpdatedValue();
}
void wxFarRadio::SetGroup(class wxFarRadio *grp)
void wxFarRadio::SetGroup(class wxFarRadio* grp)
{
if(grp == this)
return;
wxFarRadio *checked = GetValue() ? this : NULL;
for(wxFarRadio *gp = Next; gp != this; gp = gp->Next) {
if(gp = grp)
return;
if(gp->GetValue())
checked = gp;
}
wxFarRadio *link = Next;
Next = grp;
bool clear_checked = false;
wxFarRadio *gp;
for(gp = grp; gp->Next != grp; gp = gp->Next) {
if(checked && GetValue())
clear_checked = true;
}
gp->Next = link;
if(checked && gp->GetValue())
clear_checked = true;
if(clear_checked)
checked->SetValue(false);
int l;
for(l = 1, gp = Next; gp != this; gp = gp->Next, l++);
if (grp == this)
return;
wxFarRadio* checked = GetValue() ? this : NULL;
for (wxFarRadio* gp = Next; gp != this; gp = gp->Next)
{
if (gp = grp)
return;
if (gp->GetValue())
checked = gp;
}
wxFarRadio* link = Next;
Next = grp;
bool clear_checked = false;
wxFarRadio* gp;
for (gp = grp; gp->Next != grp; gp = gp->Next)
{
if (checked && GetValue())
clear_checked = true;
}
gp->Next = link;
if (checked && gp->GetValue())
clear_checked = true;
if (clear_checked)
checked->SetValue(false);
int l;
for (l = 1, gp = Next; gp != this; gp = gp->Next, l++);
}
void wxFarRadio::BreakGroup() {
wxFarRadio **gp;
for(gp = &Next; *gp != this; gp = &(*gp)->Next);
*gp = Next;
Next = this;
}
wxFarRadio *wxFarRadio::GetNext()
void wxFarRadio::BreakGroup()
{
return Next;
wxFarRadio** gp;
for (gp = &Next; *gp != this; gp = &(*gp)->Next);
*gp = Next;
Next = this;
}
wxFarRadio* wxFarRadio::GetNext()
{
return Next;
}
void wxFarRadio::UpdatedValue()
{
if(!GetValue()) {
wxFarRadio *gp;
// just like system wx, ensure at least one always checked
for(gp = Next; gp != this; gp = gp->Next)
if(gp->GetValue())
break;
if(gp == this) {
SetValue(true);
return;
if (!GetValue())
{
wxFarRadio* gp;
// just like system wx, ensure at least one always checked
for (gp = Next; gp != this; gp = gp->Next)
if (gp->GetValue())
break;
if (gp == this)
{
SetValue(true);
return;
}
}
} else
for(wxFarRadio *gp = Next; gp != this; gp = gp->Next)
gp->SetValue(false);
else
for (wxFarRadio* gp = Next; gp != this; gp = gp->Next)
gp->SetValue(false);
}
void wxFarRadio::UpdateEvt(wxCommandEvent &ev)
{
UpdatedValue();
ev.Skip();
UpdatedValue();
ev.Skip();
}
IMPLEMENT_DYNAMIC_CLASS(wxFarRadio, wxCheckBox);
BEGIN_EVENT_TABLE(wxFarRadio, wxCheckBox)
EVT_CHECKBOX(wxID_ANY, wxFarRadio::UpdateEvt)
EVT_CHECKBOX(wxID_ANY, wxFarRadio::UpdateEvt)
END_EVENT_TABLE()
bool wxBoolIntValidator::TransferToWindow()
{
if(!vptr)
if (!vptr)
return false;
bool checked = (*vptr & mask) == val;
wxCheckBox* cb = wxDynamicCast(GetWindow(), wxCheckBox);
if (cb)
{
cb->SetValue(checked);
return true;
}
wxRadioButton* rb = wxDynamicCast(GetWindow(), wxRadioButton);
if (rb)
{
rb->SetValue(checked);
return true;
}
return false;
bool checked = (*vptr & mask) == val;
wxCheckBox *cb = wxDynamicCast(GetWindow(), wxCheckBox);
if(cb) {
cb->SetValue(checked);
return true;
}
wxRadioButton *rb = wxDynamicCast(GetWindow(), wxRadioButton);
if(rb) {
rb->SetValue(checked);
return true;
}
return false;
}
bool wxBoolIntValidator::TransferFromWindow()
{
if(!vptr)
return false;
bool nv = false;
wxCheckBox *cb = wxDynamicCast(GetWindow(), wxCheckBox);
if(cb)
nv = cb->GetValue();
else {
wxRadioButton *rb = wxDynamicCast(GetWindow(), wxRadioButton);
if(rb)
nv = rb->GetValue();
if (!vptr)
return false;
bool nv = false;
wxCheckBox* cb = wxDynamicCast(GetWindow(), wxCheckBox);
if (cb)
nv = cb->GetValue();
else
return false;
}
if(mask == ~0 && !nv && *vptr != val)
{
wxRadioButton* rb = wxDynamicCast(GetWindow(), wxRadioButton);
if (rb)
nv = rb->GetValue();
else
return false;
}
if (mask == ~0 && !nv && *vptr != val)
return true;
*vptr = (*vptr & ~mask) | (nv ? val : 0);
return true;
*vptr = (*vptr & ~mask) | (nv ? val : 0);
return true;
}
bool wxBoolRevValidator::TransferToWindow()
{
if(!vptr)
if (!vptr)
return false;
wxCheckBox* cb = wxDynamicCast(GetWindow(), wxCheckBox);
if (cb)
{
cb->SetValue(!*vptr);
return true;
}
wxRadioButton* rb = wxDynamicCast(GetWindow(), wxRadioButton);
if (rb)
{
rb->SetValue(!*vptr);
return true;
}
return false;
wxCheckBox *cb = wxDynamicCast(GetWindow(), wxCheckBox);
if(cb) {
cb->SetValue(!*vptr);
return true;
}
wxRadioButton *rb = wxDynamicCast(GetWindow(), wxRadioButton);
if(rb) {
rb->SetValue(!*vptr);
return true;
}
return false;
}
bool wxBoolRevValidator::TransferFromWindow()
{
if(!vptr)
return false;
wxCheckBox *cb = wxDynamicCast(GetWindow(), wxCheckBox);
if(cb)
*vptr = !cb->GetValue();
else {
wxRadioButton *rb = wxDynamicCast(GetWindow(), wxRadioButton);
if(rb)
*vptr = !rb->GetValue();
if (!vptr)
return false;
wxCheckBox* cb = wxDynamicCast(GetWindow(), wxCheckBox);
if (cb)
*vptr = !cb->GetValue();
else
return false;
}
return true;
{
wxRadioButton* rb = wxDynamicCast(GetWindow(), wxRadioButton);
if (rb)
*vptr = !rb->GetValue();
else
return false;
}
return true;
}
#include <wx/filepicker.h>
bool wxFileDirPickerValidator::TransferToWindow()
{
if(!vptr)
if (!vptr)
return false;
wxFilePickerCtrl* fp = wxDynamicCast(GetWindow(), wxFilePickerCtrl);
if (fp)
{
fp->SetPath(*vptr);
return true;
}
wxDirPickerCtrl* dp = wxDynamicCast(GetWindow(), wxDirPickerCtrl);
if (dp)
{
dp->SetPath(*vptr);
return true;
}
return false;
wxFilePickerCtrl *fp = wxDynamicCast(GetWindow(), wxFilePickerCtrl);
if(fp) {
fp->SetPath(*vptr);
return true;
}
wxDirPickerCtrl *dp = wxDynamicCast(GetWindow(), wxDirPickerCtrl);
if(dp) {
dp->SetPath(*vptr);
return true;
}
return false;
}
bool wxFileDirPickerValidator::TransferFromWindow()
{
if(!vptr)
if (!vptr)
return false;
wxFilePickerCtrl* fp = wxDynamicCast(GetWindow(), wxFilePickerCtrl);
if (fp)
{
*vptr = fp->GetPath();
return true;
}
wxDirPickerCtrl* dp = wxDynamicCast(GetWindow(), wxDirPickerCtrl);
if (dp)
{
*vptr = dp->GetPath();
return true;
}
return false;
wxFilePickerCtrl *fp = wxDynamicCast(GetWindow(), wxFilePickerCtrl);
if(fp) {
*vptr = fp->GetPath();
return true;
}
wxDirPickerCtrl *dp = wxDynamicCast(GetWindow(), wxDirPickerCtrl);
if(dp) {
*vptr = dp->GetPath();
return true;
}
return false;
}
#include <wx/clrpicker.h>
bool wxColorValidator::TransferToWindow()
{
if(!ptr32 && !ptr16)
return false;
wxColourPickerCtrl *cp = wxDynamicCast(GetWindow(), wxColourPickerCtrl);
if(!cp)
return false;
if(ptr32)
cp->SetColour(wxColor(((*ptr32 >> 16) & 0xff),
((*ptr32 >> 8) & 0xff),
((*ptr32) & 0xff)));
else
cp->SetColour(wxColor(((*ptr16 << 3) & 0xf8),
((*ptr16 >> 2) & 0xf8),
((*ptr16 >> 7) & 0xf8)));
return true;
if (!ptr32 && !ptr16)
return false;
wxColourPickerCtrl* cp = wxDynamicCast(GetWindow(), wxColourPickerCtrl);
if (!cp)
return false;
if (ptr32)
cp->SetColour(wxColor(((*ptr32 >> 16) & 0xff),
((*ptr32 >> 8) & 0xff),
((*ptr32) & 0xff)));
else
cp->SetColour(wxColor(((*ptr16 << 3) & 0xf8),
((*ptr16 >> 2) & 0xf8),
((*ptr16 >> 7) & 0xf8)));
return true;
}
bool wxColorValidator::TransferFromWindow()
{
if(!ptr32 && !ptr16)
return false;
wxColourPickerCtrl *cp = wxDynamicCast(GetWindow(), wxColourPickerCtrl);
if(!cp)
return false;
wxColor c = cp->GetColour();
if(ptr32)
*ptr32 = ((c.Red() & 0xff) << 16) +
((c.Green() & 0xff) << 8) +
((c.Blue() & 0xff));
else
*ptr16 = ((c.Red() & 0xf8) >> 3) +
((c.Green() & 0xf8) << 2) +
((c.Blue() & 0xf8) << 7);
return true;
if (!ptr32 && !ptr16)
return false;
wxColourPickerCtrl* cp = wxDynamicCast(GetWindow(), wxColourPickerCtrl);
if (!cp)
return false;
wxColor c = cp->GetColour();
if (ptr32)
*ptr32 = ((c.Red() & 0xff) << 16) +
((c.Green() & 0xff) << 8) +
((c.Blue() & 0xff));
else
*ptr16 = ((c.Red() & 0xf8) >> 3) +
((c.Green() & 0xf8) << 2) +
((c.Blue() & 0xf8) << 7);
return true;
}
static void enable(wxWindow_v controls, std::vector<int>reverse, bool en)
{
for(int i = 0; i < controls.size(); i++)
controls[i]->Enable(reverse.size() <= i || !reverse[i] ? en : !en);
for (int i = 0; i < controls.size(); i++)
controls[i]->Enable(reverse.size() <= i || !reverse[i] ? en : !en);
}
#define boolen(r) do { \
int en; \
wxCheckBox *cb = wxDynamicCast(GetWindow(), wxCheckBox); \
if(cb) \
en = cb->GetValue(); \
en = cb->GetValue(); \
else { \
wxRadioButton *rb = wxDynamicCast(GetWindow(), wxRadioButton); \
if(!rb) \
return false; \
en = rb->GetValue(); \
wxRadioButton *rb = wxDynamicCast(GetWindow(), wxRadioButton); \
if(!rb) \
return false; \
en = rb->GetValue(); \
} \
enable(controls, reverse, r ? !en : en); \
return true; \
@ -258,65 +326,71 @@ static void enable(wxWindow_v controls, std::vector<int>reverse, bool en)
bool wxBoolEnValidator::TransferToWindow()
{
if(!wxGenericValidator::TransferToWindow())
return false;
boolen(false);
if (!wxGenericValidator::TransferToWindow())
return false;
boolen(false);
}
bool wxBoolIntEnValidator::TransferToWindow()
{
if(!wxBoolIntValidator::TransferToWindow())
return false;
boolen(false);
if (!wxBoolIntValidator::TransferToWindow())
return false;
boolen(false);
}
bool wxBoolRevEnValidator::TransferToWindow()
{
if(!wxBoolRevValidator::TransferToWindow())
return false;
boolen(true);
if (!wxBoolRevValidator::TransferToWindow())
return false;
boolen(true);
}
void wxBoolEnHandler::ToggleCheck(wxCommandEvent &ev)
{
enable(controls, reverse, ev.IsChecked());
ev.Skip();
enable(controls, reverse, ev.IsChecked());
ev.Skip();
}
void wxBoolEnHandler::Enable(wxCommandEvent &ev)
{
enable(controls, reverse, true);
ev.Skip();
enable(controls, reverse, true);
ev.Skip();
}
void wxBoolEnHandler::Disable(wxCommandEvent &ev)
{
enable(controls, reverse, false);
ev.Skip();
enable(controls, reverse, false);
ev.Skip();
}
static const wxChar * /* const */ val_hexdigits_s[] = {
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"),
wxT("7"), wxT("8"), wxT("9"), wxT("A"), wxT("B"), wxT("C"), wxT("D"),
wxT("E"), wxT("F"), wxT("a"), wxT("b"), wxT("c"), wxT("d"), wxT("e"),
wxT("f")
static const wxChar* /* const */ val_hexdigits_s[] =
{
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"),
wxT("7"), wxT("8"), wxT("9"), wxT("A"), wxT("B"), wxT("C"), wxT("D"),
wxT("E"), wxT("F"), wxT("a"), wxT("b"), wxT("c"), wxT("d"), wxT("e"),
wxT("f")
};
const wxArrayString val_hexdigits(sizeof(val_hexdigits_s)/sizeof(val_hexdigits_s[0]),
val_hexdigits_s);
const wxArrayString val_hexdigits(sizeof(val_hexdigits_s) / sizeof(val_hexdigits_s[0]),
val_hexdigits_s);
static const wxChar * /* const */ val_sigdigits_s[] = {
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"),
wxT("7"), wxT("8"), wxT("9"), wxT("-"), wxT("+")
static const wxChar* /* const */ val_sigdigits_s[] =
{
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"),
wxT("7"), wxT("8"), wxT("9"), wxT("-"), wxT("+")
};
const wxArrayString val_sigdigits(sizeof(val_sigdigits_s)/sizeof(val_sigdigits_s[0]),
val_sigdigits_s);
const wxArrayString val_sigdigits(sizeof(val_sigdigits_s) / sizeof(val_sigdigits_s[0]),
val_sigdigits_s);
static const wxChar * /* const */ val_unsdigits_s[] = {
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"),
wxT("7"), wxT("8"), wxT("9")
static const wxChar* /* const */ val_unsdigits_s[] =
{
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"),
wxT("7"), wxT("8"), wxT("9")
};
const wxArrayString val_unsdigits(sizeof(val_unsdigits_s)/sizeof(val_unsdigits_s[0]),
val_unsdigits_s);
const wxArrayString val_unsdigits(sizeof(val_unsdigits_s) / sizeof(val_unsdigits_s[0]),
val_unsdigits_s);

View File

@ -3,15 +3,15 @@
// For compilers that support precompilation, includes <wx/wx.h>.
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include <wx/wx.h>
#include <wx/wx.h>
#endif
// The following are not pulled in by wx.h
@ -65,28 +65,36 @@
#include "wx/keyedit.h"
static inline void DoSetAccel(wxMenuItem *mi, wxAcceleratorEntry *acc)
static inline void DoSetAccel(wxMenuItem* mi, wxAcceleratorEntry* acc)
{
wxString lab = mi->GetItemLabel();
size_t tab = lab.find(wxT('\t'));
// following short circuit returns are to avoid UI update on no change
if(tab == wxString::npos && !acc)
return;
wxString accs;
if(acc)
// actually, use keyedit's ToString(), as it is more reliable
// and doesn't generate wx assertions
// accs = acc->ToString();
accs = wxKeyTextCtrl::ToString(acc->GetFlags(), acc->GetKeyCode());
if(tab != wxString::npos && accs == lab.substr(tab + 1))
return;
if(tab != wxString::npos)
lab.resize(tab);
if(acc) {
lab.append(wxT('\t'));
lab.append(accs);
}
mi->SetItemLabel(lab);
wxString lab = mi->GetItemLabel();
size_t tab = lab.find(wxT('\t'));
// following short circuit returns are to avoid UI update on no change
if (tab == wxString::npos && !acc)
return;
wxString accs;
if (acc)
// actually, use keyedit's ToString(), as it is more reliable
// and doesn't generate wx assertions
// accs = acc->ToString();
accs = wxKeyTextCtrl::ToString(acc->GetFlags(), acc->GetKeyCode());
if (tab != wxString::npos && accs == lab.substr(tab + 1))
return;
if (tab != wxString::npos)
lab.resize(tab);
if (acc)
{
lab.append(wxT('\t'));
lab.append(accs);
}
mi->SetItemLabel(lab);
}
// wxrc helpers (for dynamic strings instead of constant)

File diff suppressed because it is too large Load Diff

View File

@ -30,11 +30,11 @@
template <typename T>
void CheckPointer(T pointer)
{
if(pointer == NULL)
if (pointer == NULL)
{
std::string errormessage = "Pointer of type \"";
errormessage+=typeid(pointer).name();
errormessage+="\" was not correctly created.";
errormessage += typeid(pointer).name();
errormessage += "\" was not correctly created.";
throw std::runtime_error(errormessage);
}
}
@ -56,47 +56,48 @@ class MainFrame;
class wxvbamApp : public wxApp
{
public:
wxvbamApp() : wxApp(), pending_fullscreen(false) {}
virtual bool OnInit();
virtual void OnInitCmdLine(wxCmdLineParser &);
virtual bool OnCmdLineParsed(wxCmdLineParser &);
// name of a file to load at earliest opportunity
wxString pending_load;
// list of options to set after config file loaded
wxArrayString pending_optset;
// set fullscreen mode after init
bool pending_fullscreen;
wxvbamApp() : wxApp(), pending_fullscreen(false) {}
virtual bool OnInit();
virtual void OnInitCmdLine(wxCmdLineParser &);
virtual bool OnCmdLineParsed(wxCmdLineParser &);
// name of a file to load at earliest opportunity
wxString pending_load;
// list of options to set after config file loaded
wxArrayString pending_optset;
// set fullscreen mode after init
bool pending_fullscreen;
#if __WXMAC__
// I suppose making this work will require tweaking the bundle
void MacOpenFile(const wxString&f) { pending_load = f; };
// I suppose making this work will require tweaking the bundle
void MacOpenFile(const wxString &f) { pending_load = f; };
#endif
// without this, global accels don't always work
int FilterEvent(wxEvent &event);
wxAcceleratorEntry_v accels;
// without this, global accels don't always work
int FilterEvent(wxEvent &event);
wxAcceleratorEntry_v accels;
// the main configuration
wxFileConfig *cfg;
// vba-over.ini
wxFileConfig *overrides;
MainFrame *frame;
// use this to get ms since program lauch
wxStopWatch timer;
// append log messages to this for the log viewer
wxString log;
// there's no way to retrieve "current" locale, so this is public
wxLocale locale;
//Handle most exceptions
virtual bool OnExceptionInMainLoop()
{
// the main configuration
wxFileConfig* cfg;
// vba-over.ini
wxFileConfig* overrides;
MainFrame* frame;
// use this to get ms since program lauch
wxStopWatch timer;
// append log messages to this for the log viewer
wxString log;
// there's no way to retrieve "current" locale, so this is public
wxLocale locale;
//Handle most exceptions
virtual bool OnExceptionInMainLoop()
{
try {throw;}
catch(const std::exception& e){
catch (const std::exception &e)
{
std::cerr << "AN ERROR HAS OCCURRED: " << e.what() << std::endl;
return false;
}
}
}
private:
wxPathList config_path;
wxPathList config_path;
char* home;
};
@ -111,51 +112,53 @@ DECLARE_APP(wxvbamApp);
#define EVT_HANDLER_MASK(n, x, m) \
void MainFrame::On##n(wxCommandEvent& WXUNUSED(event)) \
{ \
if(!(cmd_enable & (m))) \
return; \
Do##n(); \
if(!(cmd_enable & (m))) \
return; \
Do##n(); \
} \
void MainFrame::Do##n() \
// here are those conditions
enum {
CMDEN_GB = (1<<0), // GB ROM loaded
CMDEN_GBA = (1<<1), // GBA ROM loaded
// the rest imply the above, unless:
// _ANY -> does not imply either
// _GBA -> only implies GBA
CMDEN_REWIND = (1<<2), // rewind states available
CMDEN_SREC = (1<<3), // sound recording in progress
CMDEN_NSREC = (1<<4), // no sound recording
CMDEN_VREC = (1<<5), // video recording
CMDEN_NVREC = (1<<6), // no video recording
CMDEN_GREC = (1<<7), // game recording
CMDEN_NGREC = (1<<8), // no game recording
CMDEN_GPLAY = (1<<9), // game playback
CMDEN_NGPLAY = (1<<10), // no game playback
CMDEN_SAVST = (1<<11), // any save states
CMDEN_GDB = (1<<12), // gdb connected
CMDEN_NGDB_GBA = (1<<13), // gdb not connected
CMDEN_NGDB_ANY = (1<<14), // gdb not connected
CMDEN_NREC_ANY = (1<<15), // not a/v recording
CMDEN_LINK_ANY = (1<<16), // link enabled
enum
{
CMDEN_GB = (1 << 0), // GB ROM loaded
CMDEN_GBA = (1 << 1), // GBA ROM loaded
// the rest imply the above, unless:
// _ANY -> does not imply either
// _GBA -> only implies GBA
CMDEN_REWIND = (1 << 2), // rewind states available
CMDEN_SREC = (1 << 3), // sound recording in progress
CMDEN_NSREC = (1 << 4), // no sound recording
CMDEN_VREC = (1 << 5), // video recording
CMDEN_NVREC = (1 << 6), // no video recording
CMDEN_GREC = (1 << 7), // game recording
CMDEN_NGREC = (1 << 8), // no game recording
CMDEN_GPLAY = (1 << 9), // game playback
CMDEN_NGPLAY = (1 << 10), // no game playback
CMDEN_SAVST = (1 << 11), // any save states
CMDEN_GDB = (1 << 12), // gdb connected
CMDEN_NGDB_GBA = (1 << 13), // gdb not connected
CMDEN_NGDB_ANY = (1 << 14), // gdb not connected
CMDEN_NREC_ANY = (1 << 15), // not a/v recording
CMDEN_LINK_ANY = (1 << 16), // link enabled
CMDEN_NEVER = (1<<31) // never (for NOOP)
CMDEN_NEVER = (1 << 31) // never (for NOOP)
};
#define ONLOAD_CMDEN (CMDEN_NSREC|CMDEN_NVREC|CMDEN_NGREC|CMDEN_NGPLAY)
#define UNLOAD_CMDEN_KEEP (CMDEN_NGDB_ANY|CMDEN_NREC_ANY|CMDEN_LINK_ANY)
struct checkable_mi_t {
int cmd;
wxMenuItem *mi;
bool *boolopt;
int *intopt, mask, val;
struct checkable_mi_t
{
int cmd;
wxMenuItem* mi;
bool* boolopt;
int* intopt, mask, val;
};
// wxArray is only for small types
typedef std::vector<checkable_mi_t> checkable_mi_array_t;
typedef std::list<wxDialog *> dialog_list_t;
typedef std::list<wxDialog*> dialog_list_t;
class GameArea;
@ -167,8 +170,8 @@ extern bool pause_next;
class MainFrame : public wxFrame
{
public:
MainFrame();
~MainFrame();
MainFrame();
~MainFrame();
bool BindControls();
void MenuOptionIntMask(const char* menuName, int &field, int mask);
@ -178,49 +181,49 @@ public:
void GetMenuOptionBool(const char* menuName, bool &field);
void SetMenuOption(const char* menuName, int value);
void SetJoystick();
void SetJoystick();
GameArea *GetPanel() { return panel; }
GameArea* GetPanel() { return panel; }
// wxMSW pauses the game for menu popups and modal dialogs, but wxGTK
// does not. It's probably desirable to pause the game. To do this for
// dialogs, use this function instead of dlg->ShowModal()
int ShowModal(wxDialog *dlg);
// and here are the wrapper functions for use when ShowModal() isn't
// possible
void StartModal();
void StopModal();
// however, adding a handler for open/close menu to do the same is unsafe.
// there is no guarantee every show will be matched by a hide.
void MenuPopped(wxMenuEvent &evt);
// wxMSW pauses the game for menu popups and modal dialogs, but wxGTK
// does not. It's probably desirable to pause the game. To do this for
// dialogs, use this function instead of dlg->ShowModal()
int ShowModal(wxDialog* dlg);
// and here are the wrapper functions for use when ShowModal() isn't
// possible
void StartModal();
void StopModal();
// however, adding a handler for open/close menu to do the same is unsafe.
// there is no guarantee every show will be matched by a hide.
void MenuPopped(wxMenuEvent &evt);
// flags for enabling commands
int cmd_enable;
// flags for enabling commands
int cmd_enable;
// adjust menus based on current cmd_enable
void enable_menus();
// adjust menus based on current cmd_enable
void enable_menus();
void EnableNetworkMenu();
// adjust menus based on available save game states
void update_state_ts(bool force = false);
// adjust menus based on available save game states
void update_state_ts(bool force = false);
// retrieve oldest/newest slot
// returns lowest-numbered slot on ties
int oldest_state_slot(); // or empty slot if available
int newest_state_slot(); // or 0 if none
// retrieve oldest/newest slot
// returns lowest-numbered slot on ties
int oldest_state_slot(); // or empty slot if available
int newest_state_slot(); // or 0 if none
// system-defined accelerators
wxAcceleratorEntry_v sys_accels;
// adjust recent menu with accelerators
void SetRecentAccels();
// merge sys accels with user-defined accels (user overrides sys)
wxAcceleratorEntry_v get_accels(wxAcceleratorEntry_v user_accels);
// update menu and global accelerator table with sys+user accel defs
// probably not the quickest way to add/remove individual accels
void set_global_accels();
// system-defined accelerators
wxAcceleratorEntry_v sys_accels;
// adjust recent menu with accelerators
void SetRecentAccels();
// merge sys accels with user-defined accels (user overrides sys)
wxAcceleratorEntry_v get_accels(wxAcceleratorEntry_v user_accels);
// update menu and global accelerator table with sys+user accel defs
// probably not the quickest way to add/remove individual accels
void set_global_accels();
// 2.8 has no HasFocus(), and FindFocus() doesn't work right
bool HasFocus() { return focused; }
// 2.8 has no HasFocus(), and FindFocus() doesn't work right
bool HasFocus() { return focused; }
// Returns the link mode to set according to the options
LinkMode GetConfiguredLinkMode();
@ -228,77 +231,77 @@ public:
// Start GDB listener
void GDBBreak();
// The various viewer popups; these can be popped up as often as
// desired
void Disassemble();
void IOViewer();
void MapViewer();
void MemViewer();
void OAMViewer();
void PaletteViewer();
void TileViewer();
// The various viewer popups; these can be popped up as often as
// desired
void Disassemble();
void IOViewer();
void MapViewer();
void MemViewer();
void OAMViewer();
void PaletteViewer();
void TileViewer();
// since they will all have to be destroyed on game unload:
dialog_list_t popups;
// since they will all have to be destroyed on game unload:
dialog_list_t popups;
// this won't actually be destroyed, but it needs to be tracked so only
// one is ever up and it needs to be pinged when new messages arrive
LogDialog *logdlg;
// this won't actually be destroyed, but it needs to be tracked so only
// one is ever up and it needs to be pinged when new messages arrive
LogDialog* logdlg;
// the cheat search dialog isn't destroyed or tracked, but it needs
// to be cleared between games
void ResetCheatSearch();
// call this to update the viewers once a frame:
void UpdateViewers();
// the cheat search dialog isn't destroyed or tracked, but it needs
// to be cleared between games
void ResetCheatSearch();
// required for building from xrc
DECLARE_DYNAMIC_CLASS();
// required for event handling
DECLARE_EVENT_TABLE();
// call this to update the viewers once a frame:
void UpdateViewers();
// required for building from xrc
DECLARE_DYNAMIC_CLASS();
// required for event handling
DECLARE_EVENT_TABLE();
private:
GameArea *panel;
GameArea* panel;
// the various reasons the game might be paused
bool paused;
int menus_opened, dialog_opened;
// the various reasons the game might be paused
bool paused;
int menus_opened, dialog_opened;
public:
bool IsPaused(bool incendental = false)
{
return (paused && !pause_next && !incendental) || menus_opened || dialog_opened;
}
bool IsPaused(bool incendental = false)
{
return (paused && !pause_next && !incendental) || menus_opened || dialog_opened;
}
private:
bool autoLoadMostRecent;
// copy of top-level menu bar as a context menu
wxMenu *ctx_menu;
// load/save states menu items
wxMenuItem *loadst_mi[10];
wxMenuItem *savest_mi[10];
wxDateTime state_ts[10];
// checkable menu items
checkable_mi_array_t checkable_mi;
// recent menu item accels
wxMenu *recent;
wxAcceleratorEntry recent_accel[10];
// joystick reader
wxSDLJoy joy;
bool autoLoadMostRecent;
// copy of top-level menu bar as a context menu
wxMenu* ctx_menu;
// load/save states menu items
wxMenuItem* loadst_mi[10];
wxMenuItem* savest_mi[10];
wxDateTime state_ts[10];
// checkable menu items
checkable_mi_array_t checkable_mi;
// recent menu item accels
wxMenu* recent;
wxAcceleratorEntry recent_accel[10];
// joystick reader
wxSDLJoy joy;
// helper function for adding menu to accel editor
void add_menu_accels(wxTreeCtrl *tc, wxTreeItemId &parent, wxMenu *menu);
// helper function for adding menu to accel editor
void add_menu_accels(wxTreeCtrl* tc, wxTreeItemId &parent, wxMenu* menu);
// for detecting window focus
void OnActivate(wxActivateEvent&);
// quicker & more accurate than FindFocus() != NULL
bool focused;
// may work, may not... if so, load dropped file
void OnDropFile(wxDropFilesEvent&);
// pop up menu in fullscreen mode
void OnMenu(wxContextMenuEvent &);
// Load a named wxDialog from the XRC file
wxDialog * LoadXRCDialog(const char * name);
// Load a named wxDialog from the XRC file
wxDialog * LoadXRCropertySheetDialog(const char * name);
// for detecting window focus
void OnActivate(wxActivateEvent &);
// quicker & more accurate than FindFocus() != NULL
bool focused;
// may work, may not... if so, load dropped file
void OnDropFile(wxDropFilesEvent &);
// pop up menu in fullscreen mode
void OnMenu(wxContextMenuEvent &);
// Load a named wxDialog from the XRC file
wxDialog* LoadXRCDialog(const char* name);
// Load a named wxDialog from the XRC file
wxDialog* LoadXRCropertySheetDialog(const char* name);
#include "cmdhandlers.h"
};
@ -306,41 +309,46 @@ private:
class ModalPause
{
public:
ModalPause() { wxGetApp().frame->StartModal(); }
~ModalPause() { wxGetApp().frame->StopModal(); }
ModalPause() { wxGetApp().frame->StartModal(); }
~ModalPause() { wxGetApp().frame->StopModal(); }
};
enum showspeed {
// this order must match order of option enum and selector widget
SS_NONE, SS_PERCENT, SS_DETAILED
enum showspeed
{
// this order must match order of option enum and selector widget
SS_NONE, SS_PERCENT, SS_DETAILED
};
enum filtfunc {
// this order must match order of option enum and selector widget
FF_NONE, FF_2XSAI, FF_SUPER2XSAI, FF_SUPEREAGLE, FF_PIXELATE,
FF_ADVMAME, FF_BILINEAR, FF_BILINEARPLUS, FF_SCANLINES, FF_TV,
FF_HQ2X, FF_LQ2X, FF_SIMPLE2X, FF_SIMPLE3X, FF_HQ3X, FF_SIMPLE4X,
enum filtfunc
{
// this order must match order of option enum and selector widget
FF_NONE, FF_2XSAI, FF_SUPER2XSAI, FF_SUPEREAGLE, FF_PIXELATE,
FF_ADVMAME, FF_BILINEAR, FF_BILINEARPLUS, FF_SCANLINES, FF_TV,
FF_HQ2X, FF_LQ2X, FF_SIMPLE2X, FF_SIMPLE3X, FF_HQ3X, FF_SIMPLE4X,
FF_HQ4X, FF_XBRZ2X, FF_XBRZ3X, FF_XBRZ4X, FF_XBRZ5X, FF_PLUGIN // plugin must always be last
};
#define builtin_ff_scale(x) \
((x == FF_XBRZ5X) ? 5 : \
((x == FF_XBRZ5X) ? 5 : \
(x == FF_XBRZ4X || x == FF_HQ4X || x == FF_SIMPLE4X) ? 4 : \
(x == FF_XBRZ3X || x == FF_HQ3X || x == FF_SIMPLE3X) ? 3 : \
x == FF_PLUGIN ? 0 : x == FF_NONE ? 1 : 2)
(x == FF_XBRZ3X || x == FF_HQ3X || x == FF_SIMPLE3X) ? 3 : \
x == FF_PLUGIN ? 0 : x == FF_NONE ? 1 : 2)
enum ifbfunc {
// this order must match order of option enum and selector widget
IFB_NONE, IFB_SMART, IFB_MOTION_BLUR
enum ifbfunc
{
// this order must match order of option enum and selector widget
IFB_NONE, IFB_SMART, IFB_MOTION_BLUR
};
// make sure and keep this in sync with opts.cpp!
enum renderer {
RND_SIMPLE, RND_OPENGL, RND_CAIRO, RND_DIRECT3D
enum renderer
{
RND_SIMPLE, RND_OPENGL, RND_CAIRO, RND_DIRECT3D
};
// likewise
enum audioapi {
AUD_SDL, AUD_OPENAL, AUD_DIRECTSOUND, AUD_XAUDIO2
enum audioapi
{
AUD_SDL, AUD_OPENAL, AUD_DIRECTSOUND, AUD_XAUDIO2
};
// an unfortunate legacy default; should have a non-digit preceding %d
@ -359,125 +367,125 @@ class DrawingPanel;
class GameArea : public wxPanel
{
public:
GameArea();
virtual ~GameArea();
GameArea();
virtual ~GameArea();
// set to game title + link info
void SetFrameTitle();
// set to game title + link info
void SetFrameTitle();
void LoadGame(const wxString &name);
void UnloadGame(bool destruct = false);
void LoadGame(const wxString &name);
void UnloadGame(bool destruct = false);
IMAGE_TYPE game_type() { return loaded; }
u32 game_size() { return rom_size; }
wxString game_dir() { return loaded_game.GetPath(); }
wxString game_name() { return loaded_game.GetFullName(); }
wxString bat_dir() { return batdir; }
wxString state_dir() { return statedir; }
void recompute_dirs();
IMAGE_TYPE game_type() { return loaded; }
u32 game_size() { return rom_size; }
wxString game_dir() { return loaded_game.GetPath(); }
wxString game_name() { return loaded_game.GetFullName(); }
wxString bat_dir() { return batdir; }
wxString state_dir() { return statedir; }
void recompute_dirs();
bool LoadState();
bool LoadState(int slot);
bool LoadState(const wxFileName &fname);
bool LoadState();
bool LoadState(int slot);
bool LoadState(const wxFileName &fname);
bool SaveState();
bool SaveState(int slot);
bool SaveState(const wxFileName &fname);
bool SaveState();
bool SaveState(int slot);
bool SaveState(const wxFileName &fname);
// save to default location
void SaveBattery(bool quiet = false);
// save to default location
void SaveBattery(bool quiet = false);
// true if file at default location may not match memory
bool cheats_dirty;
// true if file at default location may not match memory
bool cheats_dirty;
static const int GBWidth = 160, GBHeight = 144,
SGBWidth = 256, SGBHeight = 224,
GBAWidth = 240, GBAHeight = 160;
void AddBorder();
void DelBorder();
// Delete() & set to NULL to force reinit
DrawingPanel *panel;
struct EmulatedSystem *emusys;
static const int GBWidth = 160, GBHeight = 144,
SGBWidth = 256, SGBHeight = 224,
GBAWidth = 240, GBAHeight = 160;
void AddBorder();
void DelBorder();
// Delete() & set to NULL to force reinit
DrawingPanel* panel;
struct EmulatedSystem* emusys;
// pause game or signal a long operation, similar to pausing
void Pause();
void Resume();
// pause game or signal a long operation, similar to pausing
void Pause();
void Resume();
// true if paused since last reset of flag
bool was_paused;
// true if paused since last reset of flag
bool was_paused;
// osdstat is always displayed at top-left of screen
wxString osdstat;
// osdstat is always displayed at top-left of screen
wxString osdstat;
// osdtext is displayed for 3 seconds after osdtime, and then cleared
wxString osdtext;
u32 osdtime;
// osdtext is displayed for 3 seconds after osdtime, and then cleared
wxString osdtext;
u32 osdtime;
// Rewind: count down to 0 and rewind
u32 rewind_time;
// Rewind: flag to OnIdle to do a rewind
bool do_rewind;
// Rewind: rewind states
char *rewind_mem; // should be u8, really
int num_rewind_states;
int next_rewind_state;
// FIXME: size this properly
// Rewind: count down to 0 and rewind
u32 rewind_time;
// Rewind: flag to OnIdle to do a rewind
bool do_rewind;
// Rewind: rewind states
char* rewind_mem; // should be u8, really
int num_rewind_states;
int next_rewind_state;
// FIXME: size this properly
#define REWIND_SIZE 400000
// FIXME: make this a config option
// FIXME: make this a config option
#define NUM_REWINDS 8
void ShowFullScreen(bool full);
bool IsFullScreen() { return fullscreen; }
// set size of frame & panel to scaled screen size
void AdjustSize(bool force);
void ShowFullScreen(bool full);
bool IsFullScreen() { return fullscreen; }
// set size of frame & panel to scaled screen size
void AdjustSize(bool force);
#ifndef NO_FFMPEG
void StartSoundRecording(const wxString &fname);
void StopSoundRecording();
void StartVidRecording(const wxString &fname);
void StopVidRecording();
void AddFrame(const u8 *data); // video
void AddFrame(const u16 *data, int length); // audio
bool IsRecording() { return snd_rec.IsRecording() || vid_rec.IsRecording(); }
void StartSoundRecording(const wxString &fname);
void StopSoundRecording();
void StartVidRecording(const wxString &fname);
void StopVidRecording();
void AddFrame(const u8* data); // video
void AddFrame(const u16* data, int length); // audio
bool IsRecording() { return snd_rec.IsRecording() || vid_rec.IsRecording(); }
#endif
void StartGameRecording(const wxString &fname);
void StopGameRecording();
void StartGamePlayback(const wxString &fname);
void StopGamePlayback();
void StartGameRecording(const wxString &fname);
void StopGameRecording();
void StartGamePlayback(const wxString &fname);
void StopGamePlayback();
protected:
// set minsize of frame & panel to unscaled screen size
void LowerMinSize();
// set minsize of frame & panel to scaled screen size
void AdjustMinSize();
// set minsize of frame & panel to unscaled screen size
void LowerMinSize();
// set minsize of frame & panel to scaled screen size
void AdjustMinSize();
IMAGE_TYPE loaded;
u32 rom_size;
wxFileName loaded_game;
wxString batdir, statedir;
IMAGE_TYPE loaded;
u32 rom_size;
wxFileName loaded_game;
wxString batdir, statedir;
int basic_width, basic_height;
bool fullscreen;
int basic_width, basic_height;
bool fullscreen;
bool paused;
void OnIdle(wxIdleEvent &);
void OnKeyDown(wxKeyEvent &ev);
void OnKeyUp(wxKeyEvent &ev);
void OnSDLJoy(wxSDLJoyEvent &ev);
bool paused;
void OnIdle(wxIdleEvent &);
void OnKeyDown(wxKeyEvent &ev);
void OnKeyUp(wxKeyEvent &ev);
void OnSDLJoy(wxSDLJoyEvent &ev);
#ifndef NO_FFMPEG
MediaRecorder snd_rec, vid_rec;
MediaRecorder snd_rec, vid_rec;
#endif
public:
void ShowPointer();
void HidePointer();
void ShowPointer();
void HidePointer();
protected:
void MouseEvent(wxMouseEvent &) { ShowPointer(); }
bool pointer_blanked;
u32 mouse_active_time;
void MouseEvent(wxMouseEvent &) { ShowPointer(); }
bool pointer_blanked;
u32 mouse_active_time;
DECLARE_DYNAMIC_CLASS()
DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS()
DECLARE_EVENT_TABLE()
};
// wxString version of OSD message
@ -486,12 +494,13 @@ void systemScreenMessage(const wxString &msg);
// List of all commands with their descriptions
// sorted by cmd field for binary searching
// filled in by copy-events.cmake
extern struct cmditem {
const wxChar *cmd, *name;
int cmd_id;
int mask_flags; // if non-0, one of the flags must be turned on in win
// to enable this command
wxMenuItem *mi; // the menu item to invoke command, if present
extern struct cmditem
{
const wxChar* cmd, *name;
int cmd_id;
int mask_flags; // if non-0, one of the flags must be turned on in win
// to enable this command
wxMenuItem* mi; // the menu item to invoke command, if present
} cmdtab[];
extern const int ncmds;
// for binary search
@ -505,72 +514,72 @@ class FilterThread;
class DrawingPanel : public wxObject
{
public:
DrawingPanel(int _width, int _height);
~DrawingPanel();
void DrawArea(u8 **pixels);
// the following wouldn't be necessary with virtual inheritance
virtual wxWindow *GetWindow() = 0;
virtual void Delete() = 0;
DrawingPanel(int _width, int _height);
~DrawingPanel();
void DrawArea(u8** pixels);
// the following wouldn't be necessary with virtual inheritance
virtual wxWindow* GetWindow() = 0;
virtual void Delete() = 0;
protected:
virtual void DrawArea(wxWindowDC&) = 0;
virtual void DrawOSD(wxWindowDC&);
int width, height, scale;
u8 *todraw;
u8 *pixbuf1, *pixbuf2;
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];
virtual void DrawArea(wxWindowDC &) = 0;
virtual void DrawOSD(wxWindowDC &);
int width, height, scale;
u8* todraw;
u8* pixbuf1, *pixbuf2;
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];
// following can't work in 2.8 as intended
// inheriting from wxEvtHandler is required, but also breaks subclasses
// due to lack of virtual inheritance (2.9 drops wxEvtHandler req)
// so each child must have a paint event handler (not override of this,
// but it's not virtual anyway, so that won't happen) that calls this
void PaintEv(wxPaintEvent &ev);
// following can't work in 2.8 as intended
// inheriting from wxEvtHandler is required, but also breaks subclasses
// due to lack of virtual inheritance (2.9 drops wxEvtHandler req)
// so each child must have a paint event handler (not override of this,
// but it's not virtual anyway, so that won't happen) that calls this
void PaintEv(wxPaintEvent &ev);
DECLARE_ABSTRACT_CLASS()
DECLARE_ABSTRACT_CLASS()
};
class LogDialog : public wxDialog
{
public:
LogDialog();
void Update();
LogDialog();
void Update();
private:
wxTextCtrl *log;
void Save(wxCommandEvent &ev);
void Clear(wxCommandEvent &ev);
wxTextCtrl* log;
void Save(wxCommandEvent &ev);
void Clear(wxCommandEvent &ev);
DECLARE_EVENT_TABLE()
DECLARE_EVENT_TABLE()
};
#include "opts.h"
class SoundDriver;
extern SoundDriver *newOpenAL();
extern SoundDriver* newOpenAL();
// I should add this to SoundDriver, but wxArrayString is wx-specific
// I suppose I could make subclass wxSoundDriver. maybe later.
extern bool GetOALDevices(wxArrayString &names, wxArrayString &ids);
#ifdef __WXMSW__
extern SoundDriver *newDirectSound();
extern SoundDriver* newDirectSound();
extern bool GetDSDevices(wxArrayString &names, wxArrayString &ids);
extern SoundDriver *newXAudio2_Output();
extern SoundDriver* newXAudio2_Output();
extern bool GetXA2Devices(wxArrayString &names, wxArrayString &ids);
#endif
extern bool debugger;
extern void (*dbgMain)();
extern void (*dbgSignal)(int, int);
extern void (*dbgOutput)(const char *, u32);
extern void (*dbgOutput)(const char*, u32);
extern void remoteStubMain();
extern void remoteCleanUp();
extern void remoteStubSignal(int, int);
extern void remoteOutput(const char *, u32);
extern void remoteOutput(const char*, u32);
extern bool debugOpenPty();
extern const wxString &debugGetSlavePty();

View File

@ -20,57 +20,73 @@
#include "../System.h" // for systemMessage()
#include "../gba/Globals.h"
int GetXA2Devices(IXAudio2 *xa, wxArrayString *names, wxArrayString *ids,
const wxString *match)
int GetXA2Devices(IXAudio2* xa, wxArrayString* names, wxArrayString* ids,
const wxString* match)
{
HRESULT hr;
UINT32 dev_count = 0;
hr = xa->GetDeviceCount( &dev_count );
if( hr != S_OK ) {
hr = xa->GetDeviceCount(&dev_count);
if (hr != S_OK)
{
wxLogError(_("XAudio2: Enumerating devices failed!"));
return true;
} else {
}
else
{
XAUDIO2_DEVICE_DETAILS dd;
for( UINT32 i = 0; i < dev_count; i++ ) {
hr = xa->GetDeviceDetails( i, &dd );
if( hr != S_OK ) {
for (UINT32 i = 0; i < dev_count; i++)
{
hr = xa->GetDeviceDetails(i, &dd);
if (hr != S_OK)
{
continue;
} else {
if(ids) {
}
else
{
if (ids)
{
ids->push_back(dd.DeviceID);
names->push_back( dd.DisplayName );
} else if(*match == dd.DeviceID)
names->push_back(dd.DisplayName);
}
else if (*match == dd.DeviceID)
return i;
}
}
}
return -1;
}
bool GetXA2Devices(wxArrayString &names, wxArrayString &ids)
{
HRESULT hr;
IXAudio2 *xa = NULL;
IXAudio2* xa = NULL;
UINT32 flags = 0;
#ifdef _DEBUG
flags = XAUDIO2_DEBUG_ENGINE;
#endif
hr = XAudio2Create(&xa, flags);
hr = XAudio2Create( &xa, flags );
if( hr != S_OK ) {
wxLogError( _("The XAudio2 interface failed to initialize!") );
if (hr != S_OK)
{
wxLogError(_("The XAudio2 interface failed to initialize!"));
return false;
}
GetXA2Devices(xa, &names, &ids, NULL);
xa->Release();
return true;
}
static int XA2GetDev(IXAudio2 *xa)
static int XA2GetDev(IXAudio2* xa)
{
if(gopts.audio_dev.empty())
if (gopts.audio_dev.empty())
return 0;
else {
else
{
int ret = GetXA2Devices(xa, NULL, NULL, &gopts.audio_dev);
return ret < 0 ? 0 : ret;
}
@ -79,12 +95,12 @@ static int XA2GetDev(IXAudio2 *xa)
class XAudio2_Output;
static void xaudio2_device_changed( XAudio2_Output * );
static void xaudio2_device_changed(XAudio2_Output*);
class XAudio2_Device_Notifier : public IMMNotificationClient
{
volatile LONG registered;
IMMDeviceEnumerator *pEnumerator;
IMMDeviceEnumerator* pEnumerator;
std::wstring last_device;
@ -92,13 +108,13 @@ class XAudio2_Device_Notifier : public IMMNotificationClient
std::vector<XAudio2_Output*> instances;
public:
XAudio2_Device_Notifier() : registered( 0 )
XAudio2_Device_Notifier() : registered(0)
{
InitializeCriticalSection( &lock );
InitializeCriticalSection(&lock);
}
~XAudio2_Device_Notifier()
{
DeleteCriticalSection( &lock );
DeleteCriticalSection(&lock);
}
ULONG STDMETHODCALLTYPE AddRef()
@ -111,7 +127,7 @@ public:
return 1;
}
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, VOID **ppvInterface )
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface)
{
if (IID_IUnknown == riid)
{
@ -126,70 +142,75 @@ public:
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged( EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId )
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
{
if ( flow == eRender && last_device.compare( pwstrDeviceId ) != 0 )
if (flow == eRender && last_device.compare(pwstrDeviceId) != 0)
{
last_device = pwstrDeviceId;
EnterCriticalSection(&lock);
EnterCriticalSection( &lock );
for ( auto it = instances.begin(); it < instances.end(); ++it )
for (auto it = instances.begin(); it < instances.end(); ++it)
{
xaudio2_device_changed( *it );
xaudio2_device_changed(*it);
}
LeaveCriticalSection( &lock );
LeaveCriticalSection(&lock);
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceAdded( LPCWSTR pwstrDeviceId ) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceRemoved( LPCWSTR pwstrDeviceId ) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged( LPCWSTR pwstrDeviceId, DWORD dwNewState ) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged( LPCWSTR pwstrDeviceId, const PROPERTYKEY key ) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; }
void do_register(XAudio2_Output * p_instance)
void do_register(XAudio2_Output* p_instance)
{
if ( InterlockedIncrement( &registered ) == 1 )
if (InterlockedIncrement(&registered) == 1)
{
pEnumerator = NULL;
HRESULT hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL, CLSCTX_INPROC_SERVER, __uuidof( IMMDeviceEnumerator ), ( void** ) &pEnumerator );
if ( SUCCEEDED( hr ) )
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**) &pEnumerator);
if (SUCCEEDED(hr))
{
pEnumerator->RegisterEndpointNotificationCallback( this );
pEnumerator->RegisterEndpointNotificationCallback(this);
}
}
EnterCriticalSection( &lock );
instances.push_back( p_instance );
LeaveCriticalSection( &lock );
EnterCriticalSection(&lock);
instances.push_back(p_instance);
LeaveCriticalSection(&lock);
}
void do_unregister( XAudio2_Output * p_instance )
void do_unregister(XAudio2_Output* p_instance)
{
if ( InterlockedDecrement( &registered ) == 0 )
if (InterlockedDecrement(&registered) == 0)
{
if (pEnumerator)
{
pEnumerator->UnregisterEndpointNotificationCallback( this );
pEnumerator->UnregisterEndpointNotificationCallback(this);
pEnumerator->Release();
pEnumerator = NULL;
}
}
EnterCriticalSection( &lock );
for ( auto it = instances.begin(); it < instances.end(); ++it )
EnterCriticalSection(&lock);
for (auto it = instances.begin(); it < instances.end(); ++it)
{
if ( *it == p_instance )
if (*it == p_instance)
{
instances.erase( it );
instances.erase(it);
break;
}
}
LeaveCriticalSection( &lock );
LeaveCriticalSection(&lock);
}
} g_notifier;
@ -199,30 +220,33 @@ class XAudio2_BufferNotify : public IXAudio2VoiceCallback
public:
HANDLE hBufferEndEvent;
XAudio2_BufferNotify() {
XAudio2_BufferNotify()
{
hBufferEndEvent = NULL;
hBufferEndEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
assert( hBufferEndEvent != NULL );
hBufferEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
assert(hBufferEndEvent != NULL);
}
~XAudio2_BufferNotify() {
CloseHandle( hBufferEndEvent );
~XAudio2_BufferNotify()
{
CloseHandle(hBufferEndEvent);
hBufferEndEvent = NULL;
}
STDMETHOD_( void, OnBufferEnd ) ( void *pBufferContext ) {
assert( hBufferEndEvent != NULL );
SetEvent( hBufferEndEvent );
STDMETHOD_(void, OnBufferEnd)(void* pBufferContext)
{
assert(hBufferEndEvent != NULL);
SetEvent(hBufferEndEvent);
}
// dummies:
STDMETHOD_( void, OnVoiceProcessingPassStart ) ( UINT32 BytesRequired ) {}
STDMETHOD_( void, OnVoiceProcessingPassEnd ) () {}
STDMETHOD_( void, OnStreamEnd ) () {}
STDMETHOD_( void, OnBufferStart ) ( void *pBufferContext ) {}
STDMETHOD_( void, OnLoopEnd ) ( void *pBufferContext ) {}
STDMETHOD_( void, OnVoiceError ) ( void *pBufferContext, HRESULT Error ) {};
STDMETHOD_(void, OnVoiceProcessingPassStart)(UINT32 BytesRequired) {}
STDMETHOD_(void, OnVoiceProcessingPassEnd)() {}
STDMETHOD_(void, OnStreamEnd)() {}
STDMETHOD_(void, OnBufferStart)(void* pBufferContext) {}
STDMETHOD_(void, OnLoopEnd)(void* pBufferContext) {}
STDMETHOD_(void, OnVoiceError)(void* pBufferContext, HRESULT Error) {};
};
@ -238,7 +262,7 @@ public:
bool init(long sampleRate);
// Sound Data Feed
void write(u16 * finalWave, int length);
void write(u16* finalWave, int length);
// Play Control
void pause();
@ -248,7 +272,7 @@ public:
void device_change();
// Configuration Changes
void setThrottle( unsigned short throttle );
void setThrottle(unsigned short throttle);
private:
bool failed;
@ -256,15 +280,15 @@ private:
bool playing;
UINT32 freq;
UINT32 bufferCount;
BYTE *buffers;
BYTE* buffers;
int currentBuffer;
int soundBufferLen;
volatile bool device_changed;
IXAudio2 *xaud;
IXAudio2MasteringVoice *mVoice; // listener
IXAudio2SourceVoice *sVoice; // sound source
IXAudio2* xaud;
IXAudio2MasteringVoice* mVoice; // listener
IXAudio2SourceVoice* sVoice; // sound source
XAUDIO2_BUFFER buf;
XAUDIO2_VOICE_STATE vState;
XAudio2_BufferNotify notify; // buffer end notification
@ -282,20 +306,18 @@ XAudio2_Output::XAudio2_Output()
buffers = NULL;
currentBuffer = 0;
device_changed = false;
xaud = NULL;
mVoice = NULL;
sVoice = NULL;
ZeroMemory( &buf, sizeof( buf ) );
ZeroMemory( &vState, sizeof( vState ) );
g_notifier.do_register( this );
ZeroMemory(&buf, sizeof(buf));
ZeroMemory(&vState, sizeof(vState));
g_notifier.do_register(this);
}
XAudio2_Output::~XAudio2_Output()
{
g_notifier.do_unregister( this );
g_notifier.do_unregister(this);
close();
}
@ -303,26 +325,32 @@ void XAudio2_Output::close()
{
initialized = false;
if( sVoice ) {
if( playing ) {
HRESULT hr = sVoice->Stop( 0 );
assert( hr == S_OK );
if (sVoice)
{
if (playing)
{
HRESULT hr = sVoice->Stop(0);
assert(hr == S_OK);
}
sVoice->DestroyVoice();
sVoice = NULL;
}
if( buffers ) {
free( buffers );
if (buffers)
{
free(buffers);
buffers = NULL;
}
if( mVoice ) {
if (mVoice)
{
mVoice->DestroyVoice();
mVoice = NULL;
}
if( xaud ) {
if (xaud)
{
xaud->Release();
xaud = NULL;
}
@ -336,182 +364,200 @@ void XAudio2_Output::device_change()
bool XAudio2_Output::init(long sampleRate)
{
if( failed || initialized ) return false;
if (failed || initialized) return false;
HRESULT hr;
// Initialize XAudio2
UINT32 flags = 0;
//#ifdef _DEBUG
// flags = XAUDIO2_DEBUG_ENGINE;
//#endif
hr = XAudio2Create(&xaud, flags);
hr = XAudio2Create( &xaud, flags );
if( hr != S_OK ) {
wxLogError( _("The XAudio2 interface failed to initialize!") );
if (hr != S_OK)
{
wxLogError(_("The XAudio2 interface failed to initialize!"));
failed = true;
return false;
}
freq = sampleRate;
// calculate the number of samples per frame first
// then multiply it with the size of a sample frame (16 bit * stereo)
soundBufferLen = ( freq / 60 ) * 4;
soundBufferLen = (freq / 60) * 4;
// create own buffers to store sound data because it must not be
// manipulated while the voice plays from it
buffers = (BYTE *)malloc( ( bufferCount + 1 ) * soundBufferLen );
buffers = (BYTE*)malloc((bufferCount + 1) * soundBufferLen);
// + 1 because we need one temporary buffer when all others are in use
WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof( wfx ) );
ZeroMemory(&wfx, sizeof(wfx));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = freq;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.nChannels * ( wfx.wBitsPerSample / 8 );
wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
// create sound receiver
hr = xaud->CreateMasteringVoice(
&mVoice,
XAUDIO2_DEFAULT_CHANNELS,
XAUDIO2_DEFAULT_SAMPLERATE,
0,
XA2GetDev(xaud),
NULL );
if( hr != S_OK ) {
wxLogError( _("XAudio2: Creating mastering voice failed!") );
&mVoice,
XAUDIO2_DEFAULT_CHANNELS,
XAUDIO2_DEFAULT_SAMPLERATE,
0,
XA2GetDev(xaud),
NULL);
if (hr != S_OK)
{
wxLogError(_("XAudio2: Creating mastering voice failed!"));
failed = true;
return false;
}
// create sound emitter
hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, &notify );
if( hr != S_OK ) {
wxLogError( _("XAudio2: Creating source voice failed!") );
hr = xaud->CreateSourceVoice(&sVoice, &wfx, 0, 4.0f, &notify);
if (hr != S_OK)
{
wxLogError(_("XAudio2: Creating source voice failed!"));
failed = true;
return false;
}
if( gopts.upmix ) {
if (gopts.upmix)
{
// set up stereo upmixing
XAUDIO2_DEVICE_DETAILS dd;
ZeroMemory( &dd, sizeof( dd ) );
hr = xaud->GetDeviceDetails( 0, &dd );
assert( hr == S_OK );
float *matrix = NULL;
matrix = (float*)malloc( sizeof( float ) * 2 * dd.OutputFormat.Format.nChannels );
if( matrix == NULL ) return false;
ZeroMemory(&dd, sizeof(dd));
hr = xaud->GetDeviceDetails(0, &dd);
assert(hr == S_OK);
float* matrix = NULL;
matrix = (float*)malloc(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels);
if (matrix == NULL) return false;
bool matrixAvailable = true;
switch( dd.OutputFormat.Format.nChannels ) {
case 4: // 4.0
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Back L*/ matrix[4] = 1.0000f; matrix[5] = 0.0000f;
/*Back R*/ matrix[6] = 0.0000f; matrix[7] = 1.0000f;
break;
case 5: // 5.0
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*Side L*/ matrix[6] = 1.0000f; matrix[7] = 0.0000f;
/*Side R*/ matrix[8] = 0.0000f; matrix[9] = 1.0000f;
break;
case 6: // 5.1
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
break;
case 7: // 6.1
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
/*Back C*/ matrix[12] = 0.7071f; matrix[13] = 0.7071f;
break;
case 8: // 7.1
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Back L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Back R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
/*Side L*/ matrix[12] = 1.0000f; matrix[13] = 0.0000f;
/*Side R*/ matrix[14] = 0.0000f; matrix[15] = 1.0000f;
break;
default:
matrixAvailable = false;
break;
switch (dd.OutputFormat.Format.nChannels)
{
case 4: // 4.0
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Back L*/ matrix[4] = 1.0000f; matrix[5] = 0.0000f;
/*Back R*/ matrix[6] = 0.0000f; matrix[7] = 1.0000f;
break;
case 5: // 5.0
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*Side L*/ matrix[6] = 1.0000f; matrix[7] = 0.0000f;
/*Side R*/ matrix[8] = 0.0000f; matrix[9] = 1.0000f;
break;
case 6: // 5.1
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
break;
case 7: // 6.1
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
/*Back C*/ matrix[12] = 0.7071f; matrix[13] = 0.7071f;
break;
case 8: // 7.1
//Speaker \ Left Source Right Source
/*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f;
/*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f;
/*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f;
/*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f;
/*Back L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f;
/*Back R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f;
/*Side L*/ matrix[12] = 1.0000f; matrix[13] = 0.0000f;
/*Side R*/ matrix[14] = 0.0000f; matrix[15] = 1.0000f;
break;
default:
matrixAvailable = false;
break;
}
if( matrixAvailable ) {
hr = sVoice->SetOutputMatrix( NULL, 2, dd.OutputFormat.Format.nChannels, matrix );
assert( hr == S_OK );
if (matrixAvailable)
{
hr = sVoice->SetOutputMatrix(NULL, 2, dd.OutputFormat.Format.nChannels, matrix);
assert(hr == S_OK);
}
free( matrix );
free(matrix);
matrix = NULL;
}
hr = sVoice->Start( 0 );
assert( hr == S_OK );
hr = sVoice->Start(0);
assert(hr == S_OK);
playing = true;
currentBuffer = 0;
device_changed = false;
initialized = true;
return true;
}
void XAudio2_Output::write(u16 * finalWave, int length)
void XAudio2_Output::write(u16* finalWave, int length)
{
if( !initialized || failed ) return;
if (!initialized || failed) return;
while( true ) {
if ( device_changed ) {
while (true)
{
if (device_changed)
{
close();
if (!init(freq)) return;
}
sVoice->GetState( &vState );
sVoice->GetState(&vState);
assert(vState.BuffersQueued <= bufferCount);
assert( vState.BuffersQueued <= bufferCount );
if( vState.BuffersQueued < bufferCount ) {
if( vState.BuffersQueued == 0 ) {
if (vState.BuffersQueued < bufferCount)
{
if (vState.BuffersQueued == 0)
{
// buffers ran dry
if( systemVerbose & VERBOSE_SOUNDOUTPUT ) {
if (systemVerbose & VERBOSE_SOUNDOUTPUT)
{
static unsigned int i = 0;
log( "XAudio2: Buffers were not refilled fast enough (i=%i)\n", i++ );
log("XAudio2: Buffers were not refilled fast enough (i=%i)\n", i++);
}
}
// there is at least one free buffer
break;
} else {
}
else
{
// the maximum number of buffers is currently queued
if( !speedup && throttle && !gba_joybus_active ) {
if (!speedup && throttle && !gba_joybus_active)
{
// wait for one buffer to finish playing
if (WaitForSingleObject( notify.hBufferEndEvent, 10000 ) == WAIT_TIMEOUT) {
if (WaitForSingleObject(notify.hBufferEndEvent, 10000) == WAIT_TIMEOUT)
{
device_changed = true;
}
} else {
}
else
{
// drop current audio frame
return;
}
@ -519,26 +565,24 @@ void XAudio2_Output::write(u16 * finalWave, int length)
}
// copy & protect the audio data in own memory area while playing it
CopyMemory( &buffers[ currentBuffer * soundBufferLen ], finalWave, soundBufferLen );
CopyMemory(&buffers[ currentBuffer * soundBufferLen ], finalWave, soundBufferLen);
buf.AudioBytes = soundBufferLen;
buf.pAudioData = &buffers[ currentBuffer * soundBufferLen ];
currentBuffer++;
currentBuffer %= ( bufferCount + 1 ); // + 1 because we need one temporary buffer
HRESULT hr = sVoice->SubmitSourceBuffer( &buf ); // send buffer to queue
assert( hr == S_OK );
currentBuffer %= (bufferCount + 1); // + 1 because we need one temporary buffer
HRESULT hr = sVoice->SubmitSourceBuffer(&buf); // send buffer to queue
assert(hr == S_OK);
}
void XAudio2_Output::pause()
{
if( !initialized || failed ) return;
if (!initialized || failed) return;
if( playing ) {
HRESULT hr = sVoice->Stop( 0 );
assert( hr == S_OK );
if (playing)
{
HRESULT hr = sVoice->Stop(0);
assert(hr == S_OK);
playing = false;
}
}
@ -546,11 +590,12 @@ void XAudio2_Output::pause()
void XAudio2_Output::resume()
{
if( !initialized || failed ) return;
if (!initialized || failed) return;
if( !playing ) {
HRESULT hr = sVoice->Start( 0 );
assert( hr == S_OK );
if (!playing)
{
HRESULT hr = sVoice->Start(0);
assert(hr == S_OK);
playing = true;
}
}
@ -558,34 +603,36 @@ void XAudio2_Output::resume()
void XAudio2_Output::reset()
{
if( !initialized || failed ) return;
if (!initialized || failed) return;
if( playing ) {
HRESULT hr = sVoice->Stop( 0 );
assert( hr == S_OK );
if (playing)
{
HRESULT hr = sVoice->Stop(0);
assert(hr == S_OK);
}
sVoice->FlushSourceBuffers();
sVoice->Start( 0 );
sVoice->Start(0);
playing = true;
}
void XAudio2_Output::setThrottle( unsigned short throttle )
void XAudio2_Output::setThrottle(unsigned short throttle)
{
if( !initialized || failed ) return;
if (!initialized || failed) return;
if( throttle == 0 ) throttle = 100;
HRESULT hr = sVoice->SetFrequencyRatio( (float)throttle / 100.0f );
assert( hr == S_OK );
if (throttle == 0) throttle = 100;
HRESULT hr = sVoice->SetFrequencyRatio((float)throttle / 100.0f);
assert(hr == S_OK);
}
void xaudio2_device_changed( XAudio2_Output * instance )
void xaudio2_device_changed(XAudio2_Output* instance)
{
instance->device_change();
}
SoundDriver *newXAudio2_Output()
SoundDriver* newXAudio2_Output()
{
return new XAudio2_Output();
}