* Added preliminary keyboard support back in (probably doesn't compile in linux)

* Fixed a deadlock in thread cancellation.
 * Muted some folder warnings when running pcsx2 for the first time.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1778 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-09-07 21:16:12 +00:00
parent fbae183dcc
commit 50446e6930
37 changed files with 2270 additions and 2061 deletions

View File

@ -1,223 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __PCSX2CONFIG_H__
#define __PCSX2CONFIG_H__
// Hack so that you can still use this file from C (not C++), or from a plugin without access to Paths.h.
// .. and removed in favor of a less hackish approach (air)
#ifndef g_MaxPath
#define g_MaxPath 255
#endif
/////////////////////////////////////////////////////////////////////////
// Session Configuration Override Flags
//
// a handful of flags that can override user configurations for the current application session
// only. This allows us to do things like force-disable recompilers if the memory allocations
// for them fail.
struct SessionOverrideFlags
{
bool ForceDisableEErec:1;
bool ForceDisableVU0rec:1;
bool ForceDisableVU1rec:1;
};
extern SessionOverrideFlags g_Session;
//////////////////////////////////////////////////////////////////////////
// Pcsx2 User Configuration Options!
#define PCSX2_EEREC 0x0010
#define PCSX2_VU0REC 0x0020
#define PCSX2_VU1REC 0x0040
#define PCSX2_FRAMELIMIT_MASK 0x0c00
#define PCSX2_FRAMELIMIT_NORMAL 0x0000
#define PCSX2_FRAMELIMIT_LIMIT 0x0400
#define PCSX2_FRAMELIMIT_SKIP 0x0800
#define PCSX2_MICROVU0 0x1000 // Use Micro VU0 recs instead of Zero VU0 Recs
#define PCSX2_MICROVU1 0x2000 // Use Micro VU1 recs instead of Zero VU1 Recs
#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK)
//------------ CPU Options!!! ---------------
#define CHECK_MICROVU0 (Config.Options&PCSX2_MICROVU0)
#define CHECK_MICROVU1 (Config.Options&PCSX2_MICROVU1)
#define CHECK_MACROVU0 // ifndef = Use sVU for VU macro, ifdef = Use mVU for VU macro
#define CHECK_EEREC (!g_Session.ForceDisableEErec && Config.Options&PCSX2_EEREC)
#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC)
#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC))
//------------ SPECIAL GAME FIXES!!! ---------------
#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x01) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
#define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x04) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
#define CHECK_VUCLIPFLAGHACK (Config.GameFixes & 0x02) // Special Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
#define CHECK_FPUMULHACK (Config.GameFixes & 0x08) // Special Fix for Tales of Destiny hangs.
#define CHECK_DMAEXECHACK (Config.GameFixes & 0x10) // Special Fix for Fatal Frame; breaks Gust and Tri-Ace games.
#define CHECK_XGKICKHACK (Config.GameFixes & 0x20) // Special Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics.
//------------ Advanced Options!!! ---------------
#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1)
#define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs
#define CHECK_VU_SIGN_OVERFLOW (Config.vuOptions & 0x4)
#define CHECK_VU_UNDERFLOW (Config.vuOptions & 0x8)
#define CHECK_VU_EXTRA_FLAGS 0 // Always disabled now // Sets correct flags in the VU recs
#define CHECK_FPU_OVERFLOW (Config.eeOptions & 0x1)
#define CHECK_FPU_EXTRA_OVERFLOW (Config.eeOptions & 0x2) // If enabled, Operands are checked for infinities before being used in the FPU recs
#define CHECK_FPU_EXTRA_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions
#define CHECK_FPU_FULL (Config.eeOptions & 0x4)
#define DEFAULT_eeOptions 0x01
#define DEFAULT_vuOptions 0x01
//------------ DEFAULT sseMXCSR VALUES!!! ---------------
#define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop"
#define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop"
//------------ Recompiler defines - Comment to disable a recompiler ---------------
// Yay! These work now! (air) ... almost (air)
#define SHIFT_RECOMPILE // Speed majorly reduced if disabled
#define BRANCH_RECOMPILE // Speed extremely reduced if disabled - more then shift
// Disabling all the recompilers in this block is interesting, as it still runs at a reasonable rate.
// It also adds a few glitches. Really reminds me of the old Linux 64-bit version. --arcum42
#define ARITHMETICIMM_RECOMPILE
#define ARITHMETIC_RECOMPILE
#define MULTDIV_RECOMPILE
#define JUMP_RECOMPILE
#define LOADSTORE_RECOMPILE
#define MOVE_RECOMPILE
#define MMI_RECOMPILE
#define MMI0_RECOMPILE
#define MMI1_RECOMPILE
#define MMI2_RECOMPILE
#define MMI3_RECOMPILE
#define FPU_RECOMPILE
#define CP0_RECOMPILE
#define CP2_RECOMPILE
// You can't recompile ARITHMETICIMM without ARITHMETIC.
#ifndef ARITHMETIC_RECOMPILE
#undef ARITHMETICIMM_RECOMPILE
#endif
#define EE_CONST_PROP // rec2 - enables constant propagation (faster)
// These are broken, so don't enable.
//#define PCSX2_CACHE_EMU_MEM
//#define ENABLECACHE
// Memory Card configuration, per slot.
struct McdConfig
{
// filename of the memory card for this slot.
// If the string is empty characters long then the default is used.
char Filename[g_MaxPath];
// Enables the memory card at the emulation level. When false, games will treat this
// slot as if the memory card has been physically removed from the PS2.
bool Enabled;
};
struct PluginNames
{
char GS[g_MaxPath];
char PAD1[g_MaxPath];
char PAD2[g_MaxPath];
char SPU2[g_MaxPath];
char CDVD[g_MaxPath];
char DEV9[g_MaxPath];
char USB[g_MaxPath];
char FW[g_MaxPath];
};
// This is intended to be where all the main paths for Pcsx2 are.
// This may end up being moved to Paths.h. It may also be converted to strings.
struct FilePaths
{
string Working;
char Plugins[g_MaxPath];
char Bios[g_MaxPath];
// These are mainly placeholders for later.
string Isos;
string Dumps;
// This is intended for the program to populate, and the plugins to read.
// Obviously can't be saved in the config file. :)
string Inis;
};
struct Hacks_t
{
int EECycleRate;
bool IOPCycleDouble;
//bool WaitCycleExt;
bool INTCSTATSlow;
bool IdleLoopFF;
int VUCycleSteal;
bool vuFlagHack;
bool vuMinMax;
bool ESCExits; // this is a hack!?
};
struct PcsxConfig
{
public:
// The Bios name isn't really a plugin name, so doesn't go with the Plugins.
char Bios[g_MaxPath];
PluginNames Plugins;
FilePaths Paths;
char Lang[g_MaxPath];
McdConfig Mcd[2];
bool McdEnableNTFS; // enables NTFS compression on cards and the mcd folder.
bool McdEnableEject; // enables auto-ejection of cards after loading savestates.
u32 Options; // PCSX2_X options
bool PsxOut;
bool Profiler; // Displays profiling info to console
bool cdvdPrint; // Prints cdvd reads to console
bool closeGSonEsc; // closes the GS (and saves its state) on escape automatically.
int PsxType;
int Patch;
int CustomFps;
Hacks_t Hacks;
int GameFixes;
int CustomFrameSkip;
int CustomConsecutiveFrames;
int CustomConsecutiveSkip;
u32 sseMXCSR;
u32 sseVUMXCSR;
u32 eeOptions;
u32 vuOptions;
int Blockdump;
};
extern PcsxConfig Config;
#endif // __PCSX2CONFIG_H__

View File

@ -72,9 +72,10 @@ namespace Threading
#if wxUSE_GUI
void WaitGui();
bool WaitGui( const wxTimeSpan& timeout );
#endif
void Wait();
void Wait( const wxTimeSpan& timeout );
bool Wait( const wxTimeSpan& timeout );
void WaitNoCancel();
int Count();
};
@ -125,6 +126,7 @@ namespace Threading
typedef int (*PlainJoeFP)();
pthread_t m_thread;
Semaphore m_sem_event; // general wait event that's needed by most threads.
Semaphore m_sem_finished; // used for canceling and closing threads in a deadlock-safe manner
sptr m_returncode; // value returned from the thread on close.
volatile long m_detached; // a boolean value which indicates if the m_thread handle is valid

View File

@ -31,6 +31,8 @@ using namespace Threading;
namespace Threading
{
static const timespec ts_msec_200 = { 0, 200 * 1000000 };
static void _pt_callback_cleanup( void* handle )
{
((PersistentThread*)handle)->DoThreadCleanup();
@ -39,6 +41,7 @@ namespace Threading
PersistentThread::PersistentThread() :
m_thread()
, m_sem_event()
, m_sem_finished()
, m_returncode( 0 )
, m_detached( false )
, m_running( false )
@ -58,7 +61,11 @@ namespace Threading
if( !_InterlockedExchange( &m_detached, true ) )
{
pthread_join( m_thread, (void**)&m_returncode );
#if wxUSE_GUI
m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) );
#else
m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) );
#endif
m_running = false;
}
}
@ -109,7 +116,13 @@ namespace Threading
pthread_cancel( m_thread );
if( isBlocking )
pthread_join( m_thread, (void**)&m_returncode );
{
#if wxUSE_GUI
m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) );
#else
m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) );
#endif
}
else
pthread_detach( m_thread );
@ -137,7 +150,12 @@ namespace Threading
else
{
DevAssert( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." );
pthread_join( m_thread, (void**)&m_returncode );
#if wxUSE_GUI
m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) );
#else
m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) );
#endif
return m_returncode;
}
}
@ -260,11 +278,34 @@ namespace Threading
// In order to avoid deadlock we need to make sure we cut some time
// to handle messages. I choose 200ms:
static const timespec fail = { 0, 200 * 1000000 };
do {
wxTheApp->ProcessPendingEvents();
} while( sem_timedwait( &sema, &fail ) == ETIMEDOUT );
} while( sem_timedwait( &sema, &ts_msec_200 ) == ETIMEDOUT );
}
}
bool Semaphore::WaitGui( const wxTimeSpan& timeout )
{
if( !wxThread::IsMain() || (wxTheApp == NULL) )
{
return Wait( timeout );
}
else
{
wxTimeSpan countdown( (timeout) );
// In order to avoid deadlock we need to make sure we cut some time
// to handle messages. I choose 200ms:
static const wxTimeSpan pass( 0, 0, 0, 200 );
do {
wxTheApp->ProcessPendingEvents();
if( sem_timedwait( &sema, &ts_msec_200 ) != ETIMEDOUT )
break;
countdown -= pass;
} while( countdown.GetMilliseconds() > 0 );
return countdown.GetMilliseconds() > 0;
}
}
#endif
@ -274,10 +315,10 @@ namespace Threading
sem_wait( &sema );
}
void Semaphore::Wait( const wxTimeSpan& timeout )
bool Semaphore::Wait( const wxTimeSpan& timeout )
{
const timespec fail = { timeout.GetSeconds().GetLo(), 0 };
sem_timedwait( &sema, &fail );
return sem_timedwait( &sema, &fail ) != ETIMEDOUT;
}
// Performs an uncancellable wait on a semaphore; restoring the thread's previous cancel state

View File

@ -247,9 +247,6 @@ public:
// when enabled performs bios stub execution, skipping full sony bios + splash screens
SkipBiosSplash:1,
// Closes the GS/Video port on escape (good for fullscreen activity)
closeGSonEsc:1,
// enables simulated ejection of memory cards when loading savestates
McdEnableEjection:1;
}; };

View File

@ -634,6 +634,7 @@ struct GSStatePacket
};
// runs the GS
// (this should really be part of the AppGui)
void RunGSState( gzLoadingState& f )
{
u32 newfield;
@ -679,7 +680,9 @@ void RunGSState( gzLoadingState& f )
*(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield;
GSvsync(newfield);
SysUpdate();
// fixme : Process pending app messages here.
//SysUpdate();
if( g_SaveGSStream != 3 )
return;

View File

@ -368,5 +368,5 @@ extern gzSavingState* g_fGSSave;
#endif
void RunGSState(gzLoadingState& f);
extern void RunGSState(gzLoadingState& f);

View File

@ -85,10 +85,6 @@ extern bool States_isSlotUsed(int num);
// as keyboard events, menu/status updates, and cpu execution invocation.
namespace HostGui
{
// Signals the gui with a keystroke. Handle or discard or dispatch, or enjoy its
// pleasant flavor.
extern void __fastcall KeyEvent( keyEvent* ev );
// For issuing notices to both the status bar and the console at the same time.
// Single-line text only please! Multi-line msgs should be directed to the
// console directly, thanks.

278
pcsx2/Linux/LnxKeyCodes.cpp Normal file
View File

@ -0,0 +1,278 @@
#include "../PrecompiledHeader.h"
#include <wx/gtk/private.h>
#include <wx/gtk/win_gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkx.h>
// Returns a WXK_* keycode, given osome kinda GKT input mess!
u32 TranslateGDKtoWXK( u32 keysym )
{
u32 key_code;
switch ( keysym )
{
// Shift, Control and Alt don't generate the CHAR events at all
case GDK_Shift_L:
case GDK_Shift_R:
key_code = WXK_SHIFT;
break;
case GDK_Control_L:
case GDK_Control_R:
key_code = WXK_CONTROL;
break;
case GDK_Meta_L:
case GDK_Meta_R:
case GDK_Alt_L:
case GDK_Alt_R:
case GDK_Super_L:
case GDK_Super_R:
key_code = WXK_ALT;
break;
// neither do the toggle modifies
case GDK_Scroll_Lock:
key_code = WXK_SCROLL;
break;
case GDK_Caps_Lock:
key_code = WXK_CAPITAL;
break;
case GDK_Num_Lock:
key_code = WXK_NUMLOCK;
break;
// various other special keys
case GDK_Menu:
key_code = WXK_MENU;
break;
case GDK_Help:
key_code = WXK_HELP;
break;
case GDK_BackSpace:
key_code = WXK_BACK;
break;
case GDK_ISO_Left_Tab:
case GDK_Tab:
key_code = WXK_TAB;
break;
case GDK_Linefeed:
case GDK_Return:
key_code = WXK_RETURN;
break;
case GDK_Clear:
key_code = WXK_CLEAR;
break;
case GDK_Pause:
key_code = WXK_PAUSE;
break;
case GDK_Select:
key_code = WXK_SELECT;
break;
case GDK_Print:
key_code = WXK_PRINT;
break;
case GDK_Execute:
key_code = WXK_EXECUTE;
break;
case GDK_Escape:
key_code = WXK_ESCAPE;
break;
// cursor and other extended keyboard keys
case GDK_Delete:
key_code = WXK_DELETE;
break;
case GDK_Home:
key_code = WXK_HOME;
break;
case GDK_Left:
key_code = WXK_LEFT;
break;
case GDK_Up:
key_code = WXK_UP;
break;
case GDK_Right:
key_code = WXK_RIGHT;
break;
case GDK_Down:
key_code = WXK_DOWN;
break;
case GDK_Prior: // == GDK_Page_Up
key_code = WXK_PAGEUP;
break;
case GDK_Next: // == GDK_Page_Down
key_code = WXK_PAGEDOWN;
break;
case GDK_End:
key_code = WXK_END;
break;
case GDK_Begin:
key_code = WXK_HOME;
break;
case GDK_Insert:
key_code = WXK_INSERT;
break;
// numpad keys
case GDK_KP_0:
case GDK_KP_1:
case GDK_KP_2:
case GDK_KP_3:
case GDK_KP_4:
case GDK_KP_5:
case GDK_KP_6:
case GDK_KP_7:
case GDK_KP_8:
case GDK_KP_9:
key_code = (isChar ? '0' : WXK_NUMPAD0) + keysym - GDK_KP_0;
break;
case GDK_KP_Space:
key_code = isChar ? ' ' : WXK_NUMPAD_SPACE;
break;
case GDK_KP_Tab:
key_code = isChar ? WXK_TAB : WXK_NUMPAD_TAB;
break;
case GDK_KP_Enter:
key_code = isChar ? WXK_RETURN : WXK_NUMPAD_ENTER;
break;
case GDK_KP_F1:
key_code = isChar ? WXK_F1 : WXK_NUMPAD_F1;
break;
case GDK_KP_F2:
key_code = isChar ? WXK_F2 : WXK_NUMPAD_F2;
break;
case GDK_KP_F3:
key_code = isChar ? WXK_F3 : WXK_NUMPAD_F3;
break;
case GDK_KP_F4:
key_code = isChar ? WXK_F4 : WXK_NUMPAD_F4;
break;
case GDK_KP_Home:
key_code = isChar ? WXK_HOME : WXK_NUMPAD_HOME;
break;
case GDK_KP_Left:
key_code = isChar ? WXK_LEFT : WXK_NUMPAD_LEFT;
break;
case GDK_KP_Up:
key_code = isChar ? WXK_UP : WXK_NUMPAD_UP;
break;
case GDK_KP_Right:
key_code = isChar ? WXK_RIGHT : WXK_NUMPAD_RIGHT;
break;
case GDK_KP_Down:
key_code = isChar ? WXK_DOWN : WXK_NUMPAD_DOWN;
break;
case GDK_KP_Prior: // == GDK_KP_Page_Up
key_code = isChar ? WXK_PAGEUP : WXK_NUMPAD_PAGEUP;
break;
case GDK_KP_Next: // == GDK_KP_Page_Down
key_code = isChar ? WXK_PAGEDOWN : WXK_NUMPAD_PAGEDOWN;
break;
case GDK_KP_End:
key_code = isChar ? WXK_END : WXK_NUMPAD_END;
break;
case GDK_KP_Begin:
key_code = isChar ? WXK_HOME : WXK_NUMPAD_BEGIN;
break;
case GDK_KP_Insert:
key_code = isChar ? WXK_INSERT : WXK_NUMPAD_INSERT;
break;
case GDK_KP_Delete:
key_code = isChar ? WXK_DELETE : WXK_NUMPAD_DELETE;
break;
case GDK_KP_Equal:
key_code = isChar ? '=' : WXK_NUMPAD_EQUAL;
break;
case GDK_KP_Multiply:
key_code = isChar ? '*' : WXK_NUMPAD_MULTIPLY;
break;
case GDK_KP_Add:
key_code = isChar ? '+' : WXK_NUMPAD_ADD;
break;
case GDK_KP_Separator:
// FIXME: what is this?
key_code = isChar ? '.' : WXK_NUMPAD_SEPARATOR;
break;
case GDK_KP_Subtract:
key_code = isChar ? '-' : WXK_NUMPAD_SUBTRACT;
break;
case GDK_KP_Decimal:
key_code = isChar ? '.' : WXK_NUMPAD_DECIMAL;
break;
case GDK_KP_Divide:
key_code = isChar ? '/' : WXK_NUMPAD_DIVIDE;
break;
// function keys
case GDK_F1:
case GDK_F2:
case GDK_F3:
case GDK_F4:
case GDK_F5:
case GDK_F6:
case GDK_F7:
case GDK_F8:
case GDK_F9:
case GDK_F10:
case GDK_F11:
case GDK_F12:
key_code = WXK_F1 + keysym - GDK_F1;
break;
default:
key_code = 0;
}
return key_code;
}

View File

@ -224,7 +224,6 @@ mtgsThreadObject::~mtgsThreadObject()
void mtgsThreadObject::Cancel()
{
Console::WriteLn( "MTGS > Closing GS thread..." );
SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 );
SetEvent();
m_sem_Quitter.Wait( wxTimeSpan( 0, 0, 5, 0 ) );
@ -241,7 +240,7 @@ void mtgsThreadObject::Reset()
AtomicExchange( m_RingPos, m_WritePos );
MTGS_LOG( "MTGS > Sending Reset...\n" );
MTGS_LOG( "MTGS: Sending Reset..." );
SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
SendSimplePacket( GS_RINGTYPE_FRAMESKIP, 0, 0, 0 );
@ -501,15 +500,13 @@ struct PacketTagType
sptr mtgsThreadObject::ExecuteTask()
{
Console::WriteLn("MTGS > Thread Started, Opening GS Plugin...");
memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(PS2MEM_GS) );
GSsetBaseMem( m_gsMem );
GSirqCallback( NULL );
GetPluginManager().Open( PluginId_GS );
Console::WriteLn( "MTGS > GSopen Finished, return code: 0x%x", params m_returncode );
DbgCon::WriteLn( "MTGS: GSopen Finished, return code: 0x%x", params m_returncode );
GSCSRr = 0x551B4000; // 0x55190000
m_sem_InitDone.Post();
@ -642,14 +639,14 @@ sptr mtgsThreadObject::ExecuteTask()
}
case GS_RINGTYPE_RESET:
MTGS_LOG( "MTGS > Receiving Reset...\n" );
MTGS_LOG( "MTGS: Receiving Reset..." );
if( GSreset != NULL ) GSreset();
break;
case GS_RINGTYPE_SOFTRESET:
{
int mask = tag.data[0];
MTGS_LOG( "MTGS > Receiving GIF Soft Reset (mask: %d)\n", mask );
MTGS_LOG( "MTGS: Receiving GIF Soft Reset (mask: %d)", mask );
GSgifSoftReset( mask );
break;
}
@ -1115,7 +1112,7 @@ void mtgsThreadObject::GIFSoftReset( int mask )
if( GSgifSoftReset == NULL ) return;
MTGS_LOG( "MTGS > Sending GIF Soft Reset (mask: %d)\n", mask );
MTGS_LOG( "MTGS: Sending GIF Soft Reset (mask: %d)", mask );
mtgsThread->SendSimplePacket( GS_RINGTYPE_SOFTRESET, mask, 0, 0 );
}

View File

@ -43,30 +43,6 @@ static bool IsPathSeparator( wxChar src )
#endif
}
bool Exists( const wxString& path )
{
wxStructStat sbuf;
return wxStat( path.c_str(), &sbuf ) == 0;
}
// This function returns false if the path does not exist, or if the path exists and
// is a file.
bool IsDirectory( const wxString& path )
{
wxStructStat sbuf;
if( wxStat( path.c_str(), &sbuf ) == -1 ) return false;
return !!(sbuf.st_mode & _S_IFDIR);
}
// This function returns false if the path does not exist, or if the path exists and
// is a directory.
bool IsFile( const wxString& path )
{
wxStructStat sbuf;
if( wxStat( path.c_str(), &sbuf ) == -1 ) return false;
return !!(sbuf.st_mode & _S_IFREG);
}
// Returns the length of the file.
// returns -1 if the file is not found.
int GetFileSize( const wxString& path )

View File

@ -133,9 +133,6 @@ public:
namespace Path
{
extern bool IsRooted( const wxString& path );
extern bool IsDirectory( const wxString& path );
extern bool IsFile( const wxString& path );
extern bool Exists( const wxString& path );
extern int GetFileSize( const wxString& path );
extern wxString Combine( const wxString& srcPath, const wxString& srcFile );

View File

@ -155,7 +155,6 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
IniBitBool( CdvdDumpBlocks );
IniBitBool( EnablePatches );
IniBitBool( closeGSonEsc );
IniBitBool( McdEnableEjection );
// Process various sub-components:

View File

@ -220,6 +220,8 @@ static const LegacyApi_CommonMethod s_MethMessCommon[] =
{ "close", NULL },
{ "shutdown", NULL },
{ "keyEvent", (vMeth*)fallback_keyEvent },
{ "freeze", (vMeth*)fallback_freeze },
{ "test", (vMeth*)fallback_test },
{ "configure", fallback_configure },
@ -948,6 +950,19 @@ void PluginManager::Freeze( SaveState& state )
Freeze( pi->id, state );
}
bool PluginManager::KeyEvent( const keyEvent& evt )
{
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
{
if( pi->id != PluginId_PAD )
m_info[pi->id].CommonBindings.KeyEvent( const_cast<keyEvent*>(&evt) );
}
return false;
}
void PluginManager::Configure( PluginsEnum_t pid )
{
m_info[pid].CommonBindings.Configure();

View File

@ -118,6 +118,7 @@ struct LegacyPluginAPI_Common
void (CALLBACK* Close)();
void (CALLBACK* Shutdown)();
void (CALLBACK* KeyEvent)( keyEvent* evt );
s32 (CALLBACK* Freeze)(int mode, freezeData *data);
s32 (CALLBACK* Test)();
void (CALLBACK* Configure)();
@ -167,6 +168,7 @@ public:
virtual void Freeze( PluginsEnum_t pid, SaveState& state ) { wxASSERT_MSG( false, L"Null PluginManager!" ); }
virtual void Freeze( SaveState& state ) { wxASSERT_MSG( false, L"Null PluginManager!" ); }
virtual bool KeyEvent( const keyEvent& evt ) { return false; }
};
//////////////////////////////////////////////////////////////////////////////////////////
@ -213,6 +215,7 @@ public:
void Freeze( PluginsEnum_t pid, SaveState& state );
void Freeze( SaveState& state );
bool KeyEvent( const keyEvent& evt );
void Configure( PluginsEnum_t pid );
friend PluginManager* PluginManager_Create( const wxString (&folders)[PluginId_Count] );

View File

@ -280,11 +280,6 @@ void SysClearExecutionCache()
vuMicroCpuReset();
}
__forceinline void SysUpdate()
{
HostGui::KeyEvent( PADkeyEvent() );
}
bool EmulationInProgress()
{
return (g_EmuThread != NULL) && g_EmuThread->IsRunning();
@ -319,9 +314,6 @@ void SysExecute( CoreEmuThread* newThread )
// saving states). No assertions or exceptions.
void SysEndExecution()
{
if( EmuConfig.closeGSonEsc )
StateRecovery::MakeGsOnly();
safe_delete( g_EmuThread );
}
@ -338,17 +330,6 @@ void SysResume()
}
// Function provided to escape the emulation state, by shutting down plugins and saving
// the GS state. The execution state is effectively preserved, and can be resumed with a
// call to SysExecute.
/*void SysEndExecution()
{
if( EmuConfig.closeGSonEsc )
StateRecovery::MakeGsOnly();
ClosePlugins( EmuConfig.closeGSonEsc );
}*/
void SysRestorableReset()
{
if( !EmulationInProgress() ) return;

View File

@ -34,7 +34,6 @@ class CoreEmuThread;
extern bool SysInit();
extern void SysDetect(); // Detects cpu type and fills cpuInfo structs.
extern void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
extern void SysUpdate(); // Called on VBlank (to update i.e. pads)
extern void SysExecute( CoreEmuThread* newThread );
extern void SysExecute( CoreEmuThread* newThread, CDVD_SourceType cdvdsrc );

View File

@ -287,13 +287,15 @@ public:
protected:
void ReadUserModeSettings();
bool TryOpenConfigCwd();
void OnSemaphorePing( wxCommandEvent& evt );
void OnMessageBox( pxMessageBoxEvent& evt );
void CleanupMess();
void OpenWizardConsole();
void HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const;
void OnSemaphorePing( wxCommandEvent& evt );
void OnMessageBox( pxMessageBoxEvent& evt );
void OnKeyDown( wxKeyEvent& evt );
// ----------------------------------------------------------------------------
// Override wx default exception handling behavior
// ----------------------------------------------------------------------------
@ -313,11 +315,15 @@ protected:
//
class AppEmuThread : public CoreEmuThread
{
protected:
wxKeyEvent m_kevt;
public:
AppEmuThread( const wxString& elf_file=wxEmptyString );
virtual ~AppEmuThread() { }
virtual void Resume();
virtual void StateCheck();
protected:
sptr ExecuteTask();
@ -334,3 +340,5 @@ extern void OpenPlugins();
extern wxRect wxGetDisplayArea();
extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos );
extern void ProcessFKeys(int fkey, struct KeyModifiers *keymod);

View File

@ -333,6 +333,12 @@ void wxDirName::Rmdir()
bool wxDirName::Mkdir()
{
if( Exists() ) return true;
// Recursively create child directories as needed:
wxDirName recurse( *this );
recurse.RemoveLastDir();
if( !recurse.Mkdir() ) return false;
return wxFileName::Mkdir();
}
@ -361,6 +367,7 @@ AppConfig::AppConfig() :
, Toolbar_ShowLabels( true )
, McdEnableNTFS( true )
, CloseGSonEsc( true )
, CurrentIso()
, CdvdSource( CDVDsrc_Iso )

View File

@ -133,6 +133,9 @@ public:
// enables automatic ntfs compression of memory cards (Win32 only)
bool McdEnableNTFS;
// Closes the GS/Video port on escape (good for fullscreen activity)
bool CloseGSonEsc;
wxString CurrentIso;
CDVD_SourceType CdvdSource;

View File

@ -59,11 +59,13 @@ Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent ) :
void Dialogs::ImportSettingsDialog::OnImport_Click( __unused wxCommandEvent& evt )
{
AppConfig_ReloadGlobalSettings( false ); // ... and import existing settings
g_Conf->Folders.Bios.Mkdir();
EndModal( wxID_OK );
}
void Dialogs::ImportSettingsDialog::OnOverwrite_Click( __unused wxCommandEvent& evt )
{
AppConfig_ReloadGlobalSettings( true ); // ... and overwrite any existing settings
g_Conf->Folders.Bios.Mkdir();
EndModal( wxID_OK );
}

View File

@ -33,12 +33,6 @@ bool renderswitch = false;
namespace HostGui
{
static const int NUM_STATES = 10;
static int StatesC = 0;
static int g_Pcsx2Recording = 0; // true 1 if recording video and sound
// Sets the status bar message without mirroring the output to the console.
void SetStatusMsg( const wxString& text )
{
@ -51,24 +45,34 @@ namespace HostGui
Console::Status( text.c_str() );
SetStatusMsg( text );
}
}
static const int NUM_STATES = 10;
static int StatesC = 0;
static int g_Pcsx2Recording = 0; // true 1 if recording video and sound
static wxString GetGSStateFilename()
{
return Path::Combine( g_Conf->Folders.Savestates, wxsFormat( L"/%8.8X.%d.gs", ElfCRC, StatesC ) );
}
static void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
void Pcsx2App::OnKeyDown( wxKeyEvent& evt )
{
assert(fkey >= 1 && fkey <= 12 );
switch( evt.GetKeyCode() )
{
case WXK_ESCAPE:
if( g_Conf->CloseGSonEsc )
StateRecovery::MakeGsOnly();
switch(fkey)
{
case 1:
SysEndExecution();
break;
case WXK_F1:
States_Save( StatesC );
break;
case 2:
if( keymod->shift )
case WXK_F2:
if( evt.GetModifiers() & wxMOD_SHIFT )
StatesC = (StatesC+NUM_STATES-1) % NUM_STATES;
else
StatesC = (StatesC+1) % NUM_STATES;
@ -79,21 +83,21 @@ namespace HostGui
GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).mb_str());
break;
case 3:
case WXK_F3:
States_Load( StatesC );
break;
case 4:
case WXK_F4:
// FIXME : Reimplement framelimiting using new oolean system
//CycleFrameLimit(keymod->shift ? -1 : 1);
break;
// note: VK_F5-VK_F7 are reserved for GS
case 8:
case WXK_F8:
GSmakeSnapshot( g_Conf->Folders.Snapshots.ToAscii().data() );
break;
case 9: //gsdx "on the fly" renderer switching
case WXK_F9: //gsdx "on the fly" renderer switching
SysSuspend();
StateRecovery::MakeGsOnly();
@ -106,7 +110,7 @@ namespace HostGui
break;
#ifdef PCSX2_DEVBUILD
case 10:
case WXK_F10:
// There's likely a better way to implement this, but this seemed useful.
// I might add turning EE, VU0, and VU1 recs on and off by hotkey at some point, too.
// --arcum42
@ -119,7 +123,7 @@ namespace HostGui
break;
case 11:
case WXK_F11:
Console::Notice( "Cannot make gsstates in MTGS mode" );
// fixme : fix up gsstate mess and make it mtgs compatible -- air
@ -149,8 +153,8 @@ namespace HostGui
#endif
#endif
case 12:
if( keymod->shift )
case WXK_F12:
if( evt.GetModifiers() & wxMOD_SHIFT )
{
#ifdef PCSX2_DEVBUILD
iDumpRegisters(cpuRegs.pc, 0);
@ -167,8 +171,3 @@ namespace HostGui
break;
}
}
void __fastcall KeyEvent( keyEvent* ev )
{
}
}

View File

@ -102,6 +102,8 @@ protected:
void Menu_ShowConsole(wxCommandEvent &event);
void Menu_ShowAboutBox(wxCommandEvent &event);
bool _DoSelectIsoBrowser();
// ------------------------------------------------------------------------
// MainEmuFram Internal API for Populating Main Menu Contents
// ------------------------------------------------------------------------

View File

@ -58,12 +58,46 @@ void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event )
wxGetApp().SaveSettings();
}
void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
// Returns FALSE if the user cancelled the action.
bool MainEmuFrame::_DoSelectIsoBrowser()
{
if( EmulationInProgress() )
static const wxChar* isoFilterTypes =
L"All Supported (.iso .mdf .nrg .bin .img .dump)|*.iso;*.mdf;*.nrg;*.bin;*.img;*.dump|"
L"Disc Images (.iso .mdf .nrg .bin .img)|*.iso;*.mdf;*.nrg;*.bin;*.img|"
L"Blockdumps (.dump)|*.dump|"
L"All Files (*.*)|*.*";
wxFileDialog ctrl( this, _("Select CDVD source iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString,
isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( ctrl.ShowModal() != wxID_CANCEL )
{
g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath();
g_Conf->CurrentIso = ctrl.GetPath();
wxGetApp().SaveSettings();
UpdateIsoSrcFile();
return true;
}
return false;
}
void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
{
SysSuspend();
if( !wxFileExists( g_Conf->CurrentIso ) )
{
if( !_DoSelectIsoBrowser() )
{
SysResume();
return;
}
}
if( EmulationInProgress() )
{
// [TODO] : Add one of 'dems checkboxes that read like "[x] don't show this stupid shit again, kthx."
bool result = Msgbox::OkCancel( pxE( ".Popup:ConfirmEmuReset", L"This will reset the emulator and your current emulation session will be lost. Are you sure?") );
@ -81,29 +115,10 @@ void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
SysExecute( new AppEmuThread(), g_Conf->CdvdSource );
}
static const wxChar* isoFilterTypes =
L"All Supported (.iso .mdf .nrg .bin .img .dump)|*.iso;*.mdf;*.nrg;*.bin;*.img;*.dump|"
L"Disc Images (.iso .mdf .nrg .bin .img)|*.iso;*.mdf;*.nrg;*.bin;*.img|"
L"Blockdumps (.dump)|*.dump|"
L"All Files (*.*)|*.*";
void MainEmuFrame::Menu_IsoBrowse_Click( wxCommandEvent &event )
{
SysSuspend();
wxFileDialog ctrl( this, _("Select CDVD source iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString,
isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( ctrl.ShowModal() != wxID_CANCEL )
{
g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath();
g_Conf->CurrentIso = ctrl.GetPath();
wxGetApp().SaveSettings();
UpdateIsoSrcFile();
}
_DoSelectIsoBrowser();
SysResume();
}
@ -111,10 +126,7 @@ void MainEmuFrame::Menu_RunIso_Click( wxCommandEvent &event )
{
SysSuspend();
wxFileDialog ctrl( this, _("Run PS2 Iso..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString,
isoFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( ctrl.ShowModal() == wxID_CANCEL )
if( !_DoSelectIsoBrowser() )
{
SysResume();
return;
@ -122,12 +134,6 @@ void MainEmuFrame::Menu_RunIso_Click( wxCommandEvent &event )
SysEndExecution();
g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath();
g_Conf->CurrentIso = ctrl.GetPath();
wxGetApp().SaveSettings();
UpdateIsoSrcFile();
wxString elf_file;
if( EmuConfig.SkipBiosSplash )
{

View File

@ -116,6 +116,9 @@ Panels::DirPickerPanel::DirPickerPanel( wxWindow* parent, FoldersEnum_t folderid
Connect( m_checkCtrl->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DirPickerPanel::UseDefaultPath_Click ) );
// wx warns when paths don't exist, but this is typically normal when the wizard
// creates its child controls. So let's ignore them.
wxDoNotLogInThisScope please;
Reset(); // forces default settings based on g_Conf
}

View File

@ -72,7 +72,7 @@ void States_Load(int num)
{
wxString file( SaveState::GetFilename( num ) );
if( !Path::IsFile( file ) )
if( !wxFileExists( file ) )
{
Console::Notice( "Savestate slot %d is empty.", params num );
return;

View File

@ -60,7 +60,8 @@ namespace Exception
}
AppEmuThread::AppEmuThread( const wxString& elf_file ) :
CoreEmuThread( elf_file )
m_kevt()
, CoreEmuThread( elf_file )
{
MemoryCard::Init();
}
@ -68,9 +69,61 @@ AppEmuThread::AppEmuThread( const wxString& elf_file ) :
void AppEmuThread::Resume()
{
if( wxGetApp().GetMainFrame().IsPaused() ) return;
// Clear the sticky key statuses, because hell knows what's changed while the PAD
// plugin was suspended.
m_kevt.m_shiftDown = false;
m_kevt.m_controlDown = false;
m_kevt.m_altDown = false;
CoreEmuThread::Resume();
}
// fixme: this ID should be the ID of our wx-managed GS window (which is not
// wx-managed yet, so let's just use some arbitrary value...)
static const int pxID_Window_GS = 8030;
void AppEmuThread::StateCheck()
{
CoreEmuThread::StateCheck();
const keyEvent* ev = PADkeyEvent();
if( ev == NULL || (ev->key == 0) ) return;
GetPluginManager().KeyEvent( *ev );
m_kevt.SetEventType( ( ev->evt == KEYPRESS ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP );
m_kevt.SetId( pxID_Window_GS );
const bool isDown = (ev->evt == KEYPRESS);
#ifdef __WXMSW__
const int vkey = wxCharCodeMSWToWX( ev->key );
#elif defined( __WXGTK__ )
const int vkey = TranslateGDKtoWXK( ev->key );
#else
# error Unsupported Target Platform.
#endif
switch (vkey)
{
case WXK_SHIFT: m_kevt.m_shiftDown = isDown; return;
case WXK_CONTROL: m_kevt.m_controlDown = isDown; return;
case WXK_MENU: m_kevt.m_altDown = isDown; return;
}
// fixme: when the GS is wx-controlled, we should send the message to the GS window
// instead.
if( isDown )
{
m_kevt.m_keyCode = vkey;
wxGetApp().AddPendingEvent( m_kevt );
}
}
sptr AppEmuThread::ExecuteTask()
{
try
@ -120,6 +173,7 @@ sptr AppEmuThread::ExecuteTask()
// ----------------------------------------------------------------------------
// [TODO] : Add exception handling here for debuggable PS2 exceptions that allows
// invocation of the PCSX2 debugger and such.
//
catch( Exception::BaseException& ex )
{
// Sent the exception back to the main gui thread?
@ -144,7 +198,7 @@ void Pcsx2App::OpenWizardConsole()
static bool m_ForceWizard = false;
// User mode settings can't be stores in the CWD for two reasons:
// User mode settings can't be stored in the CWD for two reasons:
// (a) the user may not have permission to do so (most obvious)
// (b) it would result in sloppy usermode.ini found all over a hard drive if people runs the
// exe from many locations (ugh).
@ -159,7 +213,10 @@ void Pcsx2App::ReadUserModeSettings()
wxDirName usrlocaldir( wxStandardPaths::Get().GetUserLocalDataDir() );
if( !usrlocaldir.Exists() )
{
Console::Status( L"Creating UserLocalData folder: " + usrlocaldir.ToString() );
usrlocaldir.Mkdir();
}
wxFileName usermodefile( FilenameDefs::GetUsermodeConfig() );
usermodefile.SetPath( usrlocaldir.ToString() );
@ -211,7 +268,7 @@ void Pcsx2App::ReadUserModeSettings()
void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
{
parser.SetLogo( L" >> Pcsx2 -- A Playstation2 Emulator for the PC\n");
parser.SetLogo( L" >> PCSX2 -- A Playstation2 Emulator for the PC\n");
parser.AddParam( L"CDVD/ELF", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL );
@ -269,6 +326,8 @@ bool Pcsx2App::OnInit()
Connect( pxEVT_CallStackBox, pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
Connect( pxEVT_SemaphorePing, wxCommandEventHandler( Pcsx2App::OnSemaphorePing ) );
Connect( pxID_Window_GS, wxEVT_KEY_DOWN, wxKeyEventHandler( Pcsx2App::OnKeyDown ) );
// User/Admin Mode Dual Setup:
// Pcsx2 now supports two fundamental modes of operation. The default is Classic mode,
// which uses the Current Working Directory (CWD) for all user data files, and requires
@ -282,8 +341,8 @@ bool Pcsx2App::OnInit()
try
{
ReadUserModeSettings();
delete wxLog::SetActiveTarget( new pxLogConsole() );
ReadUserModeSettings();
AppConfig_ReloadGlobalSettings();

View File

@ -567,38 +567,7 @@
</File>
</Filter>
<Filter
Name="Linux"
>
<File
RelativePath="..\..\Linux\HostGui.cpp"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<Filter
Name="asm"
Name="LinuxAsm"
>
<File
RelativePath="..\..\x86\aMicroVU.S"
@ -621,7 +590,6 @@
>
</File>
</Filter>
</Filter>
<Filter
Name="Utilities"
>
@ -2074,6 +2042,10 @@
RelativePath="..\..\gui\MainMenuClicks.cpp"
>
</File>
<File
RelativePath="..\..\gui\Plugins.cpp"
>
</File>
<File
RelativePath="..\..\gui\Saveslots.cpp"
>
@ -2573,12 +2545,8 @@
</File>
</Filter>
<Filter
Name="System"
Name="Win32"
>
<File
RelativePath="..\..\gui\Plugins.cpp"
>
</File>
<File
RelativePath="..\WinCompressNTFS.cpp"
>
@ -2588,6 +2556,38 @@
>
</File>
</Filter>
<Filter
Name="Linux"
>
<File
RelativePath="..\..\Linux\LnxKeyCodes.cpp"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
</Filter>
</Filter>
<File
RelativePath="..\..\gui\AppConfig.h"

View File

@ -86,7 +86,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Include", "Include", "{0FAD
common\include\afxresmw.h = common\include\afxresmw.h
common\include\intrin_x86.h = common\include\intrin_x86.h
common\include\Pcsx2Api.h = common\include\Pcsx2Api.h
common\include\Pcsx2Config.h = common\include\Pcsx2Config.h
common\include\Pcsx2Defs.h = common\include\Pcsx2Defs.h
common\include\Pcsx2Types.h = common\include\Pcsx2Types.h
common\include\PluginCallbacks.h = common\include\PluginCallbacks.h
@ -125,7 +124,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wx", "wx", "{62BF822E-6A12-
common\include\wx\scopedptr.h = common\include\wx\scopedptr.h
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin2cpp", "Tools\bin2cpp\bin2c.vcproj", "{677B7D11-D5E1-40B3-88B1-9A4DF83D2213}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin2cpp", "tools\bin2cpp\bin2c.vcproj", "{677B7D11-D5E1-40B3-88B1-9A4DF83D2213}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{2D6F0A62-A247-4CCF-947F-FCD54BE16103}"
EndProject

View File

@ -246,6 +246,66 @@
RelativePath="..\zeropad.cpp"
>
</File>
<Filter
Name="Linux"
>
<File
RelativePath="..\Linux\gui.cpp"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\Linux\linux.cpp"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
</Filter>
</Filter>
<Filter
Name="Header Files"