From e57de37f3fdeb3ee06d92e2e5f503e17a05a919d Mon Sep 17 00:00:00 2001 From: DJRobX Date: Thu, 1 Nov 2007 10:28:09 +0000 Subject: [PATCH] Updated Direct3D to Spacy's 1.8 beta build Added new code to disable backbuffer locking to enable proper Vsync Enabled triple buffering for Direct3D Removed some unneeded binary VS.NET files git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@13 a31d4220-a93d-0410-bf67-fe4944624d44 --- VBA.suo | Bin 53248 -> 0 bytes VBA.vcproj | 4 + res/VBA.APS | Bin 280832 -> 0 bytes res/VBA.rc | 67 +- src/win32/Direct3D.cpp | 793 ++++++++------- src/win32/Input.h | 120 +-- src/win32/Joypad.cpp | 2 + src/win32/MainWndFile.cpp | 1777 +++++++++++++++++----------------- src/win32/MainWndOptions.cpp | 2 + 9 files changed, 1429 insertions(+), 1336 deletions(-) delete mode 100644 VBA.suo delete mode 100644 res/VBA.APS diff --git a/VBA.suo b/VBA.suo deleted file mode 100644 index f8fa64e903c1fb2fa0eb52865c37511c5f8642db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53248 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

&Lz*Q?u5xJaAam}qK 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π%Sd_Q`v%XxMxRhU*C_yJDu16l6B3l!iP)%6= z`D31Mz5hVM^Ut@IF$U)yM0ozW!kvI$e+c3E=Y|-wf9f!UqcS`p4>Iod`r!tjnt?M; zZR@cHpO%3$p6EBn8N5CNe+d0QbhN>zXW)!cc=1GobH$C@$2IKwF$Twv6r4W!Q^y&6 bW(H2*(B~m2l|EVD5beBSXBzyxO#c4|jQOlh diff --git a/res/VBA.rc b/res/VBA.rc index 15e19512..913ac89f 100644 --- a/res/VBA.rc +++ b/res/VBA.rc @@ -71,8 +71,8 @@ END // Dialog // -IDD_LINKTAB DIALOG DISCARDABLE 0, 0, 225, 162 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_LINKTAB DIALOG 0, 0, 225, 162 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Link Options" FONT 8, "MS Sans Serif" BEGIN @@ -81,72 +81,59 @@ BEGIN PUSHBUTTON "Cancel",ID_CANCEL,114,140,57,15 END -IDD_LINKTAB1 DIALOG DISCARDABLE 0, 0, 210, 130 -STYLE WS_CHILD | WS_VISIBLE +IDD_LINKTAB1 DIALOG 0, 0, 210, 130 +STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE FONT 8, "MS Sans Serif" BEGIN LTEXT "Link timeout (in milliseconds)",IDC_STATIC,17,12,92,16 EDITTEXT IDC_LINKTIMEOUT,116,10,53,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Single Computer",IDC_LINK_SINGLE,"Button", - BS_AUTORADIOBUTTON,17,27,71,16 - CONTROL "Network",IDC_LINK_LAN,"Button",BS_AUTORADIOBUTTON,17,43, - 70,16 + CONTROL "Single Computer",IDC_LINK_SINGLE,"Button",BS_AUTORADIOBUTTON,17,27,71,16 + CONTROL "Network",IDC_LINK_LAN,"Button",BS_AUTORADIOBUTTON,17,43,70,16 END -IDD_LINKTAB2 DIALOG DISCARDABLE 0, 0, 210, 113 -STYLE WS_CHILD +IDD_LINKTAB2 DIALOG 0, 0, 210, 113 +STYLE DS_SETFONT | WS_CHILD FONT 8, "MS Sans Serif" BEGIN - CONTROL "2",IDC_LINK2P,"Button",BS_AUTORADIOBUTTON | WS_GROUP,46, - 16,21,13 + CONTROL "2",IDC_LINK2P,"Button",BS_AUTORADIOBUTTON | WS_GROUP,46,16,21,13 CONTROL "3",IDC_LINK3P,"Button",BS_AUTORADIOBUTTON,94,16,21,13 CONTROL "4",IDC_LINK4P,"Button",BS_AUTORADIOBUTTON,142,16,21,13 - CONTROL "TCP/IP",IDC_LINKTCP,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,54,47,42,14 - CONTROL "UDP",IDC_LINKUDP,"Button",BS_AUTORADIOBUTTON | - WS_DISABLED,121,47,33,14 + CONTROL "TCP/IP",IDC_LINKTCP,"Button",BS_AUTORADIOBUTTON | WS_GROUP,54,47,42,14 + CONTROL "UDP",IDC_LINKUDP,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,121,47,33,14 PUSHBUTTON "Start!",IDC_SERVERSTART,79,89,50,17 LTEXT "Select number of players:",IDC_STATIC,60,7,89,10 LTEXT "Select protocol:",IDC_STATIC,78,33,53,11 - CONTROL "Speed hacks",IDC_SSPEED,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,76,70,57,12 + CONTROL "Speed hacks",IDC_SSPEED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,76,70,57,12 END -IDD_LINKTAB3 DIALOG DISCARDABLE 0, 0, 210, 108 -STYLE WS_CHILD +IDD_LINKTAB3 DIALOG 0, 0, 210, 108 +STYLE DS_SETFONT | WS_CHILD FONT 8, "MS Sans Serif" BEGIN - CONTROL "TCP/IP",IDC_CLINKTCP,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,58,20,39,12 - CONTROL "UDP",IDC_CLINKUDP,"Button",BS_AUTORADIOBUTTON | - WS_DISABLED,118,20,32,12 + CONTROL "TCP/IP",IDC_CLINKTCP,"Button",BS_AUTORADIOBUTTON | WS_GROUP,58,20,39,12 + CONTROL "UDP",IDC_CLINKUDP,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,118,20,32,12 EDITTEXT IDC_SERVERIP,84,39,79,12,ES_AUTOHSCROLL | WS_GROUP PUSHBUTTON "Connect",IDC_LINKCONNECT,75,81,59,16 LTEXT "Select protocol:",IDC_STATIC,78,7,53,9 LTEXT "Server IP address or hostname:",IDC_STATIC,7,37,62,18 LTEXT "Speed hacks:",IDC_STATIC,7,64,47,10 - CONTROL "Off (accurate)",IDC_SPEEDOFF,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,60,63,57,12 - CONTROL "On (fast)",IDC_SPEEDON,"Button",BS_AUTORADIOBUTTON,128, - 63,48,12 + CONTROL "Off (accurate)",IDC_SPEEDOFF,"Button",BS_AUTORADIOBUTTON | WS_GROUP,60,63,57,12 + CONTROL "On (fast)",IDC_SPEEDON,"Button",BS_AUTORADIOBUTTON,128,63,48,12 END -IDD_SERVERWAIT DIALOG DISCARDABLE 0, 0, 186, 90 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +IDD_SERVERWAIT DIALOG 0, 0, 186, 90 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Waiting for players" FONT 8, "MS Sans Serif" BEGIN PUSHBUTTON "Cancel",IDCANCEL,63,69,50,14 - CONTROL "Progress1",IDC_SERVERWAIT,"msctls_progress32",WS_BORDER, - 33,50,120,13 + CONTROL "Progress1",IDC_SERVERWAIT,"msctls_progress32",WS_BORDER,33,50,120,13 LTEXT "",IDC_STATIC1,7,7,154,8 LTEXT "",IDC_STATIC2,7,17,105,8 LTEXT "",IDC_STATIC3,7,25,105,8 LTEXT "",IDC_STATIC4,7,33,105,8 END - - IDD_OPENDLG DIALOG 36, 24, 202, 117 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Open" @@ -1563,7 +1550,6 @@ BEGIN MENUITEM "Direct&Draw", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW MENUITEM " Emulation only", ID_OPTIONS_VIDEO_DDRAWEMULATIONONLY MENUITEM " Use &Video Memory", ID_OPTIONS_VIDEO_DDRAWUSEVIDEOMEMORY - MENUITEM " Triple Buffering", ID_OPTIONS_VIDEO_TRIPLEBUFFERING MENUITEM SEPARATOR MENUITEM "Direct&3D", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D MENUITEM " Filter: Nearest", ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DNOFILTER @@ -1576,6 +1562,7 @@ BEGIN MENUITEM " Vertex: Quads", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS MENUITEM SEPARATOR MENUITEM "&VSync", ID_OPTIONS_VIDEO_VSYNC + MENUITEM "Triple Buffering", ID_OPTIONS_VIDEO_TRIPLEBUFFERING END MENUITEM SEPARATOR POPUP "Windowed" @@ -1809,7 +1796,7 @@ BEGIN MENUITEM "&Real Colors", ID_OPTIONS_GAMEBOY_REALCOLORS MENUITEM "G&ameboy Colors", ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS MENUITEM "LCD colors", ID_OPTIONS_FILTER_LCDCOLORS - MENUITEM SEPARATOR + MENUITEM SEPARATOR MENUITEM "&Colors...", ID_OPTIONS_GAMEBOY_COLORS END POPUP "&Language" @@ -1821,7 +1808,6 @@ BEGIN POPUP "Li&nk" BEGIN MENUITEM "&Wireless Adapter", ID_OPTIONS_LINK_WIRELESSADAPTER - MENUITEM "&Log", ID_OPTIONS_LINK_LOG MENUITEM "&Options...", ID_OPTIONS_LINK_OPTIONS END @@ -1960,13 +1946,6 @@ BEGIN END -///////////////////////////////////////////////////////////////////////////// -// -// RT_MANIFEST -// - -1 RT_MANIFEST "VBA.manifest" - ///////////////////////////////////////////////////////////////////////////// // // Version diff --git a/src/win32/Direct3D.cpp b/src/win32/Direct3D.cpp index 9878b605..315412fd 100644 --- a/src/win32/Direct3D.cpp +++ b/src/win32/Direct3D.cpp @@ -17,20 +17,27 @@ // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" -#include -#include -#include "vba.h" +#include +#include "VBA.H" #include "MainWnd.h" #include "UniVideoModeDlg.h" #include "../Util.h" #include "../Globals.h" #include "../Util.h" #include "../gb/gbGlobals.h" +// Link with Direct3D9 +#pragma comment(lib, "D3d9.lib") +#pragma comment(lib, "D3dx9.lib") +#define DIRECT3D_VERSION 0x0900 +#include +#include #include "../gbafilter.h" #ifdef _DEBUG #define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; #endif #ifdef MMX @@ -43,134 +50,155 @@ extern void winlog(const char *,...); extern int systemSpeed; -// Textured Vertex -typedef struct _D3DTLVERTEX { - float sx; /* Screen coordinates */ - float sy; - float sz; - float rhw; /* Reciprocal of homogeneous w */ - D3DCOLOR color; /* Vertex color */ - float tu; /* Texture coordinates */ - float tv; - _D3DTLVERTEX() { } - _D3DTLVERTEX( - const D3DVECTOR& v, - float _rhw, - D3DCOLOR _color, - float _tu, float _tv) - { sx = v.x; sy = v.y; sz = v.z; - rhw = _rhw; - color = _color; - tu = _tu; tv = _tv; } -} D3DTLVERTEX, *LPD3DTLVERTEX; -#define D3DFVF_TLVERTEX D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1 - - -// Simple Vertex -struct D3DVERTEX_SIMPLE -{ +// Vertex format declarations +const DWORD D3DFVF_TEXTBOXVERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE; +struct TEXTBOXVERTEX { FLOAT x, y, z, rhw; D3DCOLOR color; }; -#define D3DFVF_SIMPLE D3DFVF_XYZRHW | D3DFVF_DIFFUSE +const DWORD D3DFVF_IMAGEVERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1; +struct IMAGEVERTEX { + FLOAT x, y, z; + D3DCOLOR color; + FLOAT u, v; +}; + class Direct3DDisplay : public IDisplay { -private: - HINSTANCE d3dDLL; - LPDIRECT3D9 pD3D; - LPDIRECT3DDEVICE9 pDevice; - LPDIRECT3DTEXTURE9 pTexture; - D3DPRESENT_PARAMETERS dpp; - D3DFORMAT screenFormat; - int width, height; // Size of the source image to display - bool filterDisabled; - ID3DXFont *pFont; - bool failed; - D3DTLVERTEX verts[4]; // The coordinates for our texture - D3DVERTEX_SIMPLE msgBox[4]; - int textureWidth; // Size of the texture, - int textureHeight; // where the source image is copied to - int SelectedFreq, SelectedAdapter; - bool fullscreen; - - void restoreDeviceObjects(); - void invalidateDeviceObjects(); - bool initializeOffscreen(unsigned int w, unsigned int h); - void updateFiltering(int); - void updateVSync(void); - -public: +public: // Class Direct3DDisplay(); virtual ~Direct3DDisplay(); + +public: // Interface virtual bool initialize(); virtual void cleanup(); virtual void render(); - virtual void checkFullScreen(); virtual void renderMenu(); virtual void clear(); virtual bool changeRenderSize(int w, int h); virtual void resize(int w, int h); virtual DISPLAY_TYPE getType() { return DIRECT_3D; }; virtual void setOption(const char *, int); - virtual int selectFullScreenMode(GUID **); + virtual int selectFullScreenMode(GUID **); virtual int selectFullScreenMode2(); + + +private: // Functions + void restoreDeviceObjects(void); + void invalidateDeviceObjects(); + void setPresentationType(); + bool initializeOffscreen(unsigned int w, unsigned int h); + void updateFiltering(int); + bool resetDevice(); + void initializeMatrices(); + + +private: // Variables + int SelectedFreq, SelectedAdapter; + bool initSucessful; + bool doNotRender; + bool filterDisabled; + bool lockableBuffer; + LPDIRECT3D9 pD3D; + LPDIRECT3DDEVICE9 pDevice; + LPDIRECT3DTEXTURE9 pTexture; + LPD3DXFONT pFont; + D3DPRESENT_PARAMETERS dpp; + D3DFORMAT screenFormat; + D3DDISPLAYMODE mode; + + bool fullscreen; + int width, height; // Size of the source image to display + IMAGEVERTEX verts[4]; // The coordinates for our image texture + TEXTBOXVERTEX msgBox[4]; + int textureWidth; // Size of the texture, + int textureHeight; // where the source image is copied to + bool keepAspectRatio; }; Direct3DDisplay::Direct3DDisplay() { - d3dDLL = NULL; - pD3D = NULL; - pDevice = NULL; - pTexture = NULL; - pFont = NULL; - screenFormat = D3DFMT_R5G6B5; - width = 0; - height = 0; - filterDisabled = false; - failed = false; + initSucessful = false; + doNotRender = true; + pD3D = NULL; + pDevice = NULL; + pTexture = NULL; + pFont = NULL; + screenFormat = D3DFMT_UNKNOWN; + width = 0; + height = 0; + filterDisabled = false; + keepAspectRatio = true; // theApp.d3dKeepAspectRatio; + lockableBuffer = false; } Direct3DDisplay::~Direct3DDisplay() { - cleanup(); + cleanup(); +} + +void Direct3DDisplay::setPresentationType() +{ + // Change display mode + memset(&dpp, 0, sizeof(dpp)); + dpp.Windowed = !fullscreen; + if (fullscreen) + dpp.BackBufferFormat = + (theApp.fsColorDepth == 32) ? D3DFMT_X8R8G8B8 : D3DFMT_R5G6B5; + else + dpp.BackBufferFormat = mode.Format; + dpp.BackBufferCount = 3; + dpp.MultiSampleType = D3DMULTISAMPLE_NONE; + dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + dpp.BackBufferWidth = fullscreen ? theApp.fsWidth : theApp.surfaceSizeX; + dpp.BackBufferHeight = fullscreen ? theApp.fsHeight : theApp.surfaceSizeY; + dpp.hDeviceWindow = theApp.m_pMainWnd->GetSafeHwnd(); + dpp.FullScreen_RefreshRateInHz = fullscreen ? theApp.fsFrequency : 0; +// dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + dpp.Flags = theApp.menuToggle ? D3DPRESENTFLAG_LOCKABLE_BACKBUFFER : 0; + if (theApp.vsync) + dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync + else + dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync } void Direct3DDisplay::cleanup() -{ - if(pD3D != NULL) { - if(pFont) { - pFont->Release(); - pFont = NULL; - } - - if(pTexture) +{ // interface funtion + if(pD3D != NULL) { + if(pFont) { + pFont->Release(); + pFont = NULL; + } + + if(pTexture) { pTexture->Release(); pTexture = NULL; } if(pDevice) { - pDevice->Release(); - pDevice = NULL; - } - - pD3D->Release(); - pD3D = NULL; + pDevice->Release(); + pDevice = NULL; + } - if(d3dDLL != NULL) { - FreeLibrary(d3dDLL); - d3dDLL = NULL; - } - } + pD3D->Release(); + pD3D = NULL; + } + + initSucessful = false; + doNotRender = true; } bool Direct3DDisplay::initialize() -{ +{ // interface function + initSucessful = false; + doNotRender = true; + // Get emulated image's dimensions - switch (theApp.cartridgeType) + switch(theApp.cartridgeType) { case IMAGE_GBA: theApp.sizeX = 240; @@ -189,11 +217,11 @@ bool Direct3DDisplay::initialize() } break; } - - theApp.rect.left = 0; - theApp.rect.top = 0; - theApp.rect.right = theApp.sizeX; - theApp.rect.bottom = theApp.sizeY; + + theApp.rect.left = 0; + theApp.rect.top = 0; + theApp.rect.right = theApp.sizeX; + theApp.rect.bottom = theApp.sizeY; switch(theApp.videoOption) @@ -302,28 +330,8 @@ bool Direct3DDisplay::initialize() theApp.adjustDestRect(); - // Load DirectX DLL - d3dDLL = LoadLibrary("D3D9.DLL"); - LPDIRECT3D9 (WINAPI *D3DCreate)(UINT); - if(d3dDLL != NULL) - { - D3DCreate = (LPDIRECT3D9 (WINAPI *)(UINT)) - GetProcAddress(d3dDLL, "Direct3DCreate9"); - - if(D3DCreate == NULL) - { - theApp.directXMessage("Direct3DCreate9"); - return FALSE; - } - } - else - { - theApp.directXMessage("D3D9.DLL"); - return FALSE; - } - - pD3D = D3DCreate(D3D_SDK_VERSION); - + // Create an IDirect3D9 object + pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(pD3D == NULL) { winlog("Error creating Direct3D object\n"); @@ -334,7 +342,6 @@ bool Direct3DDisplay::initialize() // Display resolution - D3DDISPLAYMODE mode; pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode); switch(mode.Format) { @@ -343,6 +350,7 @@ bool Direct3DDisplay::initialize() systemRedShift = 19; systemGreenShift = 11; systemBlueShift = 3; + Init_2xSaI(32); break; case D3DFMT_X8R8G8B8: systemColorDepth = 32; @@ -371,7 +379,7 @@ bool Direct3DDisplay::initialize() } theApp.fsColorDepth = systemColorDepth; - // Check the available fullscreen modes and enable menu items + // Check the available pre-defined fullscreen modes and enable menu items unsigned int nModes, i; D3DDISPLAYMODE dm; @@ -381,10 +389,10 @@ bool Direct3DDisplay::initialize() theApp.mode1024Available = false; theApp.mode1280Available = false; - nModes = pD3D->GetAdapterModeCount(theApp.fsAdapter, D3DFMT_R5G6B5); + nModes = pD3D->GetAdapterModeCount(theApp.fsAdapter, mode.Format); for (i = 0; iEnumAdapterModes(theApp.fsAdapter, D3DFMT_R5G6B5, i, &dm) ) + if (D3D_OK == pD3D->EnumAdapterModes(theApp.fsAdapter, mode.Format, i, &dm) ) { if ( (dm.Width == 320) && (dm.Height == 240) ) theApp.mode320Available = true; @@ -396,13 +404,12 @@ bool Direct3DDisplay::initialize() theApp.mode1024Available = true; if ( (dm.Width == 1280) && (dm.Height == 1024) ) theApp.mode1280Available = true; - } } #ifdef MMX - if(!theApp.disableMMX) + if (!theApp.disableMMX) cpu_mmx = theApp.detectMMX(); else cpu_mmx = 0; @@ -410,42 +417,55 @@ bool Direct3DDisplay::initialize() screenFormat = mode.Format; - // Change display mode - ZeroMemory(&dpp, sizeof(dpp)); - dpp.Windowed = !fullscreen; - if (fullscreen) - dpp.BackBufferFormat = - (theApp.fsColorDepth == 32) ? D3DFMT_X8R8G8B8 : D3DFMT_R5G6B5; - else - dpp.BackBufferFormat = mode.Format; - dpp.BackBufferCount = 1; - dpp.MultiSampleType = D3DMULTISAMPLE_NONE; - dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - dpp.BackBufferWidth = fullscreen ? theApp.fsWidth : theApp.surfaceSizeX; - dpp.BackBufferHeight = fullscreen ? theApp.fsHeight : theApp.surfaceSizeY; - dpp.hDeviceWindow = pWnd->GetSafeHwnd(); - dpp.FullScreen_RefreshRateInHz = fullscreen ? theApp.fsFrequency : 0; - dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; - if (theApp.vsync) - dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync - else - dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync + setPresentationType(); - HRESULT hret = pD3D->CreateDevice(theApp.fsAdapter, - D3DDEVTYPE_HAL, - pWnd->GetSafeHwnd(), - D3DCREATE_SOFTWARE_VERTEXPROCESSING, - &dpp, - &pDevice); - if(hret != D3D_OK) - { - winlog("Error creating Direct3DDevice %08x\n", hret); + + DWORD BehaviorFlags; + D3DCAPS9 caps; + if (D3D_OK == pD3D->GetDeviceCaps(theApp.fsAdapter, D3DDEVTYPE_HAL, &caps)) { + if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { + BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; + } else { + BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + } + if (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) { + BehaviorFlags |= D3DCREATE_PUREDEVICE; + } + } else { + winlog("Error retrieving device's D3D capabilities\n"); return false; } - pDevice->SetDialogBoxMode(TRUE); // !!! Enable menu and windows !!! - restoreDeviceObjects(); + HRESULT hret = pD3D->CreateDevice(theApp.fsAdapter, + caps.DeviceType, + pWnd->GetSafeHwnd(), + BehaviorFlags, + &dpp, + &pDevice); +#ifdef _DEBUG + switch(hret) + { + case D3DERR_DEVICELOST: + winlog("Error creating Direct3DDevice (D3DERR_DEVICELOST)\n"); + return false; + break; + case D3DERR_INVALIDCALL: + winlog("Error creating Direct3DDevice (D3DERR_INVALIDCALL)\n"); + return false; + break; + case D3DERR_NOTAVAILABLE: + winlog("Error creating Direct3DDevice (D3DERR_NOTAVAILABLE)\n"); + return false; + break; + case D3DERR_OUTOFVIDEOMEMORY: + winlog("Error creating Direct3DDevice (D3DERR_OUTOFVIDEOMEMORY)\n"); + return false; + break; + } +#endif + + restoreDeviceObjects(); // Set the status message's background vertex information, that does not need to be changed in realtime msgBox[0].z = 0.5f; @@ -460,22 +480,36 @@ bool Direct3DDisplay::initialize() msgBox[3].z = 0.5f; msgBox[3].rhw = 1.0f; msgBox[3].color = 0x7f7f7f7f; + + // Set up the vertices of the texture + verts[0].z = verts[1].z = verts[2].z = verts[3].z = 1.0f; + verts[0].color = verts[1].color = verts[2].color = verts[3].color = D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff); + verts[1].u = verts[2].u = 1.0f; + verts[0].u = verts[3].u = 0.0f; + verts[0].v = verts[1].v = 0.0f; + verts[2].v = verts[3].v = 1.0f; + verts[0].x = verts[3].x = 0.0f; + verts[1].x = verts[2].x = 1.0f; + verts[0].y = verts[1].y = 0.0f; + verts[2].y = verts[3].y = 1.0f; + + utilUpdateSystemColorMaps(theApp.filterLCD ); theApp.updateFilter(); theApp.updateIFB(); - if(failed) - return false; - pWnd->DragAcceptFiles(TRUE); + initSucessful = true; + doNotRender = false; return TRUE; } bool Direct3DDisplay::initializeOffscreen(unsigned int w, unsigned int h) { D3DFORMAT format = screenFormat; + unsigned int correctedWidth=w, correctedHeight=h; // This function corrects the texture size automaticly @@ -505,10 +539,10 @@ bool Direct3DDisplay::initializeOffscreen(unsigned int w, unsigned int h) pDevice, correctedWidth, correctedHeight, - D3DX_DEFAULT, - 0, + 1, + D3DUSAGE_DYNAMIC, format, - D3DPOOL_MANAGED, + D3DPOOL_DEFAULT, &pTexture) ) { width = w; @@ -524,26 +558,53 @@ bool Direct3DDisplay::initializeOffscreen(unsigned int w, unsigned int h) void Direct3DDisplay::updateFiltering(int filter) -{ - switch(filter) { - default: - case 0: - // point filtering - pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); - pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); - pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT ); - break; - case 1: - // bilinear - pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); - pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); - pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT ); - break; - } +{ //TODO: use GetSampletState before changing + if(!pDevice) { + return; + } + + HRESULT res; + + switch(filter) + { + default: + case 0: + // point filtering + res = pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); + if (res != D3D_OK) { + systemMessage(0, "Could not set point filtering mode: %d", res); + return; + } + res = pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); + if (res != D3D_OK) { + systemMessage(0, "Could not set point filtering mode: %d", res); + return; + } + break; + case 1: + // bilinear + res = pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + if (res != D3D_OK) { + systemMessage(0, "Could not set bilinear filtering mode: %d", res); + return; + } + res = pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + if (res != D3D_OK) { + systemMessage(0, "Could not set bilinear filtering mode: %d", res); + return; + } + // Don't wrap textures .. otherwise bottom blurs top to bottom + pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + break; + } + return; } void Direct3DDisplay::clear() -{ +{ // interface function + if(!initSucessful) return; + if (pDevice) pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, #ifdef _DEBUG @@ -555,70 +616,43 @@ void Direct3DDisplay::clear() } void Direct3DDisplay::renderMenu() -{ - checkFullScreen(); - if(theApp.m_pMainWnd) - theApp.m_pMainWnd->DrawMenuBar(); -} +{ // interface function + if(!initSucessful) return; -void Direct3DDisplay::checkFullScreen() -{ - //if(tripleBuffering) - //pDirect3D->FlipToGDISurface(); + if(theApp.m_pMainWnd) + theApp.m_pMainWnd->DrawMenuBar(); } void Direct3DDisplay::render() -{ - unsigned int nBytesPerPixel = systemColorDepth / 8; //This is the byte count of a Pixel - unsigned int pitch = (theApp.filterWidth * nBytesPerPixel) + 4; - HRESULT hr; - +{ // interface function if(!pDevice) return; + if(!initSucessful) return; + if(doNotRender) return; + + unsigned int nBytesPerPixel = systemColorDepth >> 3; // This is the byte count of a Pixel + unsigned int pitch = (theApp.filterWidth * nBytesPerPixel) + 4; // The size of a scanline in bytes - // Test the cooperative level to see if it's okay to render + HRESULT hr; hr = pDevice->TestCooperativeLevel(); - if(hr != D3D_OK) + switch(hr) { - switch (hr) - { - case D3DERR_DEVICELOST: - break; - case D3DERR_DEVICENOTRESET: - invalidateDeviceObjects(); - hr = pDevice->Reset(&dpp); - if( hr == D3D_OK ) - { - restoreDeviceObjects(); - } -#ifdef _DEBUG - else - switch (hr) - { - case D3DERR_DEVICELOST: - winlog("Render_DeviceLost: D3DERR_DEVICELOST\n"); - break; - case D3DERR_DRIVERINTERNALERROR: - winlog("Render_DeviceLost: D3DERR_DRIVERINTERNALERROR\n"); - break; - case D3DERR_INVALIDCALL: - winlog("Render_DeviceLost: D3DERR_INVALIDCALL\n"); - break; - case D3DERR_OUTOFVIDEOMEMORY: - winlog("Render_DeviceLost: D3DERR_OUTOFVIDEOMEMORY\n"); - break; - case E_OUTOFMEMORY: - winlog("Render_DeviceLost: E_OUTOFMEMORY\n"); - break; - } -#endif - break; - case D3DERR_DRIVERINTERNALERROR: - winlog("Render: D3DERR_DRIVERINTERNALERROR\n"); - theApp.ExitInstance(); - break; - } + case D3DERR_DEVICENOTRESET: + resetDevice(); + break; + case D3DERR_DEVICELOST: + winlog("Render: D3DERR_DEVICELOST\n"); return; + break; + case D3DERR_DRIVERINTERNALERROR: + winlog("Render: D3DERR_DRIVERINTERNALERROR\n"); + cleanup(); + if(initialize()) { + return; + } else { // reinitialize device failed + AfxPostQuitMessage(D3DERR_DRIVERINTERNALERROR); + } + break; } // Clear the screen @@ -635,7 +669,7 @@ void Direct3DDisplay::render() if(SUCCEEDED(pDevice->BeginScene())) { D3DLOCKED_RECT locked; - + if( D3D_OK == pTexture->LockRect(0, &locked, NULL, D3DLOCK_DISCARD) ) { if(theApp.filterFunction) @@ -703,9 +737,9 @@ gbaLoop24bit: gbaLoopEnd: } - // C Version of the code above - //int x,y,i; - //int srcPitch = (theApp.sizeX+1) * nBytesPerPixel; + //C Version of the code above + //unsigned int i; + //int x, y, srcPitch = (theApp.sizeX+1) * nBytesPerPixel; //unsigned char * src = ((unsigned char*)pix)+srcPitch; //unsigned char * dst = (unsigned char*)locked.pBits; //for (y=0;yUnlockRect(0); - // Set the edges of the texture - POINT p1, p2; - p1.x = theApp.dest.left; - p1.y = theApp.dest.top; - p2.x = theApp.dest.right; - p2.y = theApp.dest.bottom; - theApp.m_pMainWnd->ScreenToClient(&p1); - theApp.m_pMainWnd->ScreenToClient(&p2); - - FLOAT left, right, top, bottom; - left = (FLOAT)(p1.x); - top = (FLOAT)(p1.y); - right = (FLOAT)(p2.x); - bottom = (FLOAT)(p2.y); - - right *= (FLOAT)textureWidth/theApp.rect.right; - bottom *= (FLOAT)textureHeight/theApp.rect.bottom; - - - verts[0] = D3DTLVERTEX(D3DXVECTOR3( left, top, 0.0f), 1.0f, 0xffffffff, 0.0f, 0.0f ); - verts[1] = D3DTLVERTEX(D3DXVECTOR3( right, top, 0.0f), 1.0f, 0xffffffff, 1.0f, 0.0f ); - verts[2] = D3DTLVERTEX(D3DXVECTOR3( right, bottom, 0.0f), 1.0f, 0xffffffff, 1.0f, 1.0f ); - verts[3] = D3DTLVERTEX(D3DXVECTOR3( left, bottom, 0.0f), 1.0f, 0xffffffff, 0.0f, 1.0f ); - - pDevice->SetFVF( D3DFVF_TLVERTEX ); + pDevice->SetFVF( D3DFVF_IMAGEVERTEX ); pDevice->SetTexture( 0, pTexture ); - pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, verts, sizeof(D3DTLVERTEX) ); - pTexture->UnlockRect(0); + pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, verts, sizeof( IMAGEVERTEX ) ); + } // SUCCEEDED(pTexture->LockRect... else { @@ -772,9 +781,9 @@ gbaLoopEnd: msgBox[3].x = (FLOAT)msgRect.left; msgBox[3].y = (FLOAT)msgRect.bottom; - pDevice->SetFVF( D3DFVF_SIMPLE ); + pDevice->SetFVF( D3DFVF_TEXTBOXVERTEX ); pDevice->SetTexture( 0, NULL ); - pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, msgBox, sizeof(D3DVERTEX_SIMPLE)); + pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, msgBox, sizeof(TEXTBOXVERTEX)); pFont->DrawText(NULL, theApp.screenMessageBuffer, -1, msgRect, DT_CENTER | DT_VCENTER, 0x7fff0000); } @@ -816,102 +825,117 @@ gbaLoopEnd: void Direct3DDisplay::invalidateDeviceObjects() { - if(pFont) - pFont->Release(); - pFont = NULL; + + if(pFont) { + pFont->Release(); + pFont = NULL; + } } void Direct3DDisplay::restoreDeviceObjects() { + // Create the font + D3DXCreateFont( pDevice, 24, 0, FW_BOLD, 1, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, "Arial", &pFont ); + + // Set texture filter updateFiltering(theApp.d3dFilter); - // Enable transparent vectors + // Set device settings pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); - pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + if (theApp.menuToggle) + pDevice->SetDialogBoxMode( TRUE ); + pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); - - // Create the font - D3DXCreateFont( pDevice, 24, 0, FW_BOLD, 1, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, "Arial", &pFont ); + // Set matrices + initializeMatrices(); } void Direct3DDisplay::resize(int w, int h) -{ - if(pDevice) - { - dpp.BackBufferWidth = w; - dpp.BackBufferHeight = h; - invalidateDeviceObjects(); - HRESULT hr = pDevice->Reset(&dpp); - if( hr == D3D_OK ) - restoreDeviceObjects(); - else - systemMessage(0, "Failed device reset %08x", hr); +{ // interface function + if(!initSucessful) return; + + if ( (w>0) && (h>0) ) { + if(pDevice) + { + dpp.BackBufferWidth = w; + dpp.BackBufferHeight = h; + setPresentationType(); + if (resetDevice()) { + doNotRender = false; + } + } + } else { + doNotRender = true; } + } bool Direct3DDisplay::changeRenderSize(int w, int h) -{ - // w and h is the size of the filtered image (So this could be 3xGBASize) - if(w != width || h != height) +{ // interface function + if(!initSucessful) return false; + + // w and h is the size of the filtered image (So this could be 3xGBASize) + if(w != width || h != height) { - if(pTexture) - { - pTexture->Release(); - pTexture = NULL; + if(pTexture) { + pTexture->Release(); + pTexture = NULL; } - if(!initializeOffscreen(w, h)) { - failed = true; - return false; - } - } + if(!initializeOffscreen(w, h)) { + return false; + } + } + + if(filterDisabled && theApp.filterFunction) + theApp.filterFunction = NULL; + + // Set up 2D matrices + initializeMatrices(); - if(filterDisabled && theApp.filterFunction) - theApp.filterFunction = NULL; - - return true; + return true; } void Direct3DDisplay::setOption(const char *option, int value) -{ - if(!strcmp(option, "d3dFilter")) - updateFiltering(value); +{ // interface function + if(!initSucessful) return; - if(!strcmp(option, "d3dVSync")) - updateVSync(); + if(!strcmp(option, "d3dFilter")) + updateFiltering(theApp.d3dFilter); + + if(!strcmp(option, "vsync")) + { + if (pDevice) + { + if (theApp.vsync) + dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync + else + dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync + resetDevice(); + } + } + + if(!strcmp(option, "triplebuffering")) + { + if (theApp.tripleBuffering) + dpp.BackBufferCount = 3; + else + dpp.BackBufferCount = 2; + resetDevice(); + } + + if(!strcmp(option, "d3dKeepAspectRatio")) + keepAspectRatio = true; //theApp.d3dKeepAspectRatio; } int Direct3DDisplay::selectFullScreenMode(GUID **) -{ - //int newScreenWidth, newScreenHeight; - //int newScreenBitsPerPixel; - - //D3DDISPLAYMODE dm; - //pDevice->GetDisplayMode( 0, &dm ); - - //newScreenWidth = dm.Width; - //newScreenHeight = dm.Height; - - //switch (dm.Format) - //{ - //case D3DFMT_A2R10G10B10: - //case D3DFMT_A8R8G8B8: - //case D3DFMT_X8R8G8B8: - // newScreenBitsPerPixel = 32; - // break; - //case D3DFMT_A1R5G5B5: - //case D3DFMT_X1R5G5B5: - //case D3DFMT_R5G6B5: - // newScreenBitsPerPixel = 16; - // break; - //} - // - //return (newScreenBitsPerPixel << 24) | (newScreenWidth << 12) | newScreenHeight; +{ // interface function int w, h, b; UniVideoModeDlg dlg(0, &w, &h, &b, &SelectedFreq, &SelectedAdapter); @@ -926,29 +950,108 @@ int Direct3DDisplay::selectFullScreenMode(GUID **) } } - int Direct3DDisplay::selectFullScreenMode2() { return (SelectedAdapter<<16) + SelectedFreq; } - -void Direct3DDisplay::updateVSync(void) +// Reset Device and Resources +bool Direct3DDisplay::resetDevice() { - if (pDevice) - { - if (theApp.vsync) - dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync - else - dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync - - invalidateDeviceObjects(); - HRESULT hr = pDevice->Reset(&dpp); - if (hr == D3D_OK) - restoreDeviceObjects(); - else - systemMessage(0, "Failed to change VSync option %08x", hr); + invalidateDeviceObjects(); + if(pTexture) { + pDevice->SetTexture( 0, NULL); + pTexture->Release(); + pTexture = NULL; } + if (!theApp.menuToggle) + pDevice->SetDialogBoxMode( FALSE ); + + HRESULT hr = pDevice->Reset(&dpp); + if (hr == D3D_OK) + { + restoreDeviceObjects(); + if(!initializeOffscreen(width, height)) + return false; + + return true; + } + else + { + switch(hr) + { + case D3DERR_DEVICELOST: + winlog("Render_DeviceLost: D3DERR_DEVICELOST\n"); + break; + case D3DERR_DRIVERINTERNALERROR: + winlog("Render_DeviceLost: D3DERR_DRIVERINTERNALERROR\n"); + break; + case D3DERR_INVALIDCALL: + winlog("Render_DeviceLost: D3DERR_INVALIDCALL\n"); + break; + case D3DERR_OUTOFVIDEOMEMORY: + winlog("Render_DeviceLost: D3DERR_OUTOFVIDEOMEMORY\n"); + break; + case E_OUTOFMEMORY: + winlog("Render_DeviceLost: E_OUTOFMEMORY\n"); + break; + } + winlog("Failed to reset device: %08x\n", hr); + return false; + } +} + +void Direct3DDisplay::initializeMatrices() +{ // Configure matrices to use standard orthogonal projection (2D) + D3DXMATRIX Ortho2D; + D3DXMATRIX Identity; + D3DXMATRIX temp1, temp2; + + // Initialize an orthographic matrix which automaticly compensates the difference between image size and texture size + if (!keepAspectRatio) { + D3DXMatrixOrthoOffCenterLH( + &Ortho2D, + 0.0f, // left + 1.0f * (FLOAT)width / (FLOAT)textureWidth, // right + 1.0f * (FLOAT)height / (FLOAT)textureHeight, // bottom + 0.0f, // top + 0.0f, 1.0f); // z + } else { + FLOAT l=0.0f, r=0.0f, b=0.0f, t=0.0f; + FLOAT srcAspectRatio = (FLOAT)theApp.sizeX / (FLOAT)theApp.sizeY; + FLOAT aspectRatio = (FLOAT)dpp.BackBufferWidth / (FLOAT)dpp.BackBufferHeight; + FLOAT textureImageDiffX = (FLOAT)width / (FLOAT)textureWidth; + FLOAT textureImageDiffY = (FLOAT)height / (FLOAT)textureHeight; + aspectRatio /= srcAspectRatio; + + if(aspectRatio > 1.0f) { + r = 1.0f * textureImageDiffX * aspectRatio; + b = 1.0f * textureImageDiffY; + } else { + r = 1.0f * textureImageDiffX; + b = 1.0f * textureImageDiffY * (1.0f / aspectRatio); + } + + D3DXMatrixOrthoOffCenterLH( + &temp1, + l, + r, + b, + t, + 0.0f, 1.0f); // z + D3DXMatrixTranslation( // translate matrix > move image + &temp2, + (aspectRatio>1.0)?( (aspectRatio - 1.0f) * 0.5f * textureImageDiffX ):0.0f, + (aspectRatio<1.0)?( ((1.0f/aspectRatio) - 1.0f) * 0.5f * textureImageDiffY ):0.0f, + 0.0f); + D3DXMatrixMultiply(&Ortho2D, &temp2, &temp1); + } + + D3DXMatrixIdentity(&Identity); // Identity = Do not change anything + + pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); + pDevice->SetTransform(D3DTS_WORLD, &Identity); + pDevice->SetTransform(D3DTS_VIEW, &Identity); } IDisplay *newDirect3DDisplay() diff --git a/src/win32/Input.h b/src/win32/Input.h index 7efaf18b..5349abca 100644 --- a/src/win32/Input.h +++ b/src/win32/Input.h @@ -1,28 +1,28 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef VBA_WIN32_INPUT_H -#define VBA_WIN32_INPUT_H -#include "../System.h" - -#define JOYCONFIG_MESSAGE (WM_USER + 1000) - +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_WIN32_INPUT_H +#define VBA_WIN32_INPUT_H +#include "../System.h" + +#define JOYCONFIG_MESSAGE (WM_USER + 1000) + typedef CList KeyList; #define JOYPADS 4 @@ -32,38 +32,38 @@ typedef CList KeyList; #define JOYPAD(i,j) ((i*KEYS_PER_PAD)+j) #define DEVICEOF(key) (key >> 8) -#define KEYOF(key) (key & 255) - -enum { - KEY_LEFT, KEY_RIGHT, - KEY_UP, KEY_DOWN, - KEY_BUTTON_A, KEY_BUTTON_B, - KEY_BUTTON_START, KEY_BUTTON_SELECT, - KEY_BUTTON_L, KEY_BUTTON_R, - KEY_BUTTON_SPEED, KEY_BUTTON_CAPTURE, - KEY_BUTTON_GS -}; - -class Input { - public: - KeyList joypaddata[JOYPADS * KEYS_PER_PAD + MOTION_KEYS]; - - Input() {}; - virtual ~Input() {}; - - virtual bool initialize() = 0; - - virtual bool readDevices() = 0; - virtual u32 readDevice(int which) = 0; - virtual CString getKeyName(int key) = 0; - virtual void checkKeys() = 0; - virtual void checkMotionKeys() = 0; - virtual void checkDevices() = 0; - virtual void activate() = 0; - virtual void loadSettings() = 0; - virtual void saveSettings() = 0; -}; - -#define joypad theApp.input->joypaddata - -#endif +#define KEYOF(key) (key & 255) + +enum { + KEY_LEFT, KEY_RIGHT, + KEY_UP, KEY_DOWN, + KEY_BUTTON_A, KEY_BUTTON_B, + KEY_BUTTON_START, KEY_BUTTON_SELECT, + KEY_BUTTON_L, KEY_BUTTON_R, + KEY_BUTTON_SPEED, KEY_BUTTON_CAPTURE, + KEY_BUTTON_GS +}; + +class Input { + public: + KeyList joypaddata[JOYPADS * KEYS_PER_PAD + MOTION_KEYS]; + + Input() {}; + virtual ~Input() {}; + + virtual bool initialize() = 0; + + virtual bool readDevices() = 0; + virtual u32 readDevice(int which) = 0; + virtual CString getKeyName(int key) = 0; + virtual void checkKeys() = 0; + virtual void checkMotionKeys() = 0; + virtual void checkDevices() = 0; + virtual void activate() = 0; + virtual void loadSettings() = 0; + virtual void saveSettings() = 0; +}; + +#define joypad theApp.input->joypaddata + +#endif diff --git a/src/win32/Joypad.cpp b/src/win32/Joypad.cpp index 36f9a7c5..bc6f30af 100644 --- a/src/win32/Joypad.cpp +++ b/src/win32/Joypad.cpp @@ -32,6 +32,8 @@ static char THIS_FILE[] = __FILE__; #endif // Todo: Expand UI to allow user to enter multiple keys here. +// these are temporary quick hacks to make the new lists +// work with the old code. int TempReadFirst(KeyList &Key) { diff --git a/src/win32/MainWndFile.cpp b/src/win32/MainWndFile.cpp index f6e55c4e..1322ee5b 100644 --- a/src/win32/MainWndFile.cpp +++ b/src/win32/MainWndFile.cpp @@ -1,734 +1,737 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "stdafx.h" -#include "MainWnd.h" - -#include "ExportGSASnapshot.h" -#include "FileDlg.h" -#include "GSACodeSelect.h" -#include "RomInfo.h" -#include "Reg.h" -#include "WinResUtil.h" - -#include "../GBA.h" -#include "../Globals.h" -#include "../NLS.h" -#include "../Sound.h" -#include "../gb/GB.h" -#include "../gb/gbCheats.h" -#include "../gb/gbGlobals.h" -#include "../Link.h" - -extern int emulating; - -extern void remoteCleanUp(); - -void MainWnd::OnFileOpen() -{ - theApp.winCheckFullscreen(); - if(fileOpenSelect()) { - FileRun(); - } -} - -void MainWnd::OnFilePause() -{ - theApp.paused = !theApp.paused; - if(emulating) { - if(theApp.paused) { - theApp.wasPaused = true; - soundPause(); - } else { - soundResume(); - } - } -} - -void MainWnd::OnUpdateFilePause(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(theApp.paused); -} - -void MainWnd::OnFileReset() -{ - if(emulating) { - theApp.emulator.emuReset(); - systemScreenMessage(winResLoadString(IDS_RESET)); - } -} - -void MainWnd::OnUpdateFileReset(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnUpdateFileRecentFreeze(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(theApp.recentFreeze); - - if(pCmdUI->m_pMenu == NULL) - return; - - CMenu *pMenu = pCmdUI->m_pMenu; - - int i; - for(i = 0; i < 10; i++) { - if(!pMenu->RemoveMenu(ID_FILE_MRU_FILE1+i, MF_BYCOMMAND)) - break; - } - - for(i = 0; i < 10; i++) { - CString p = theApp.recentFiles[i]; - if(p.GetLength() == 0) - break; - int index = p.ReverseFind('\\'); - - if(index != -1) - p = p.Right(p.GetLength()-index-1); - - pMenu->AppendMenu(MF_STRING, ID_FILE_MRU_FILE1+i, p); - } - theApp.winAccelMgr.UpdateMenu((HMENU)*pMenu); -} - -BOOL MainWnd::OnFileRecentFile(UINT nID) -{ - if(theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1].GetLength()) { - theApp.szFile = theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1]; - if(FileRun()) - emulating = true; - else { - emulating = false; - soundPause(); - } - } - return TRUE; -} - -void MainWnd::OnFileRecentReset() -{ - int i = 0; - for(i = 0; i < 10; i++) - theApp.recentFiles[i] = ""; -} - -void MainWnd::OnFileRecentFreeze() -{ - theApp.recentFreeze = !theApp.recentFreeze; -} - -void MainWnd::OnFileExit() -{ - SendMessage(WM_CLOSE); -} - -void MainWnd::OnFileClose() -{ - // save battery file before we change the filename... - if(rom != NULL || gbRom != NULL) { - if(theApp.autoSaveLoadCheatList) - winSaveCheatListDefault(); - writeBatteryFile(); - soundPause(); - theApp.emulator.emuCleanUp(); - remoteCleanUp(); - } - emulating = 0; - RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); - systemSetTitle("VisualBoyAdvance"); -} - -void MainWnd::OnUpdateFileClose(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileOpengameboy() -{ - theApp.winCheckFullscreen(); - theApp.dir = ""; - CString initialDir = regQueryStringValue("gbromdir","."); - if(!initialDir.IsEmpty()) - theApp.dir = initialDir; - - theApp.szFile = ""; - - LPCTSTR exts[] = { "" }; - CString filter = winLoadFilter(IDS_FILTER_GBROM); - CString title = winResLoadString(IDS_SELECT_ROM); - - FileDlg dlg(this, "", filter, 0, "", exts, initialDir, title, false); - - if(dlg.DoModal() == IDOK) { - theApp.szFile = dlg.GetPathName(); - theApp.dir = theApp.szFile.Left(dlg.m_ofn.nFileOffset); - if(theApp.dir.GetLength() > 3 && theApp.dir[theApp.dir.GetLength()-1] == '\\') - theApp.dir = theApp.dir.Left(theApp.dir.GetLength()-1); - regSetStringValue("gbromdir", theApp.dir); - FileRun(); - } -} - -void MainWnd::OnFileLoad() -{ - theApp.winCheckFullscreen(); - CString buffer; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - buffer = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(isDriveRoot(saveDir)) - filename.Format("%s%s.sgm", saveDir, buffer); - else - filename.Format("%s\\%s.sgm", saveDir, buffer); - - LPCTSTR exts[] = { ".sgm" }; - CString filter = winLoadFilter(IDS_FILTER_SGM); - CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME); - - FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, false); - - if(dlg.DoModal() == IDOK) { - bool res = loadSaveGame(dlg.GetPathName()); - - theApp.rewindCount = 0; - theApp.rewindCounter = 0; - theApp.rewindSaveNeeded = false; - - if(res) - systemScreenMessage(winResLoadString(IDS_LOADED_STATE)); - } -} - -void MainWnd::OnUpdateFileLoad(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -BOOL MainWnd::OnFileLoadSlot(UINT nID) -{ - nID = nID + 1 - ID_FILE_LOADGAME_SLOT1; - - CString buffer; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - buffer = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(isDriveRoot(saveDir)) - filename.Format("%s%s%d.sgm", saveDir, buffer, nID); - else - filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID); - - bool res = loadSaveGame(filename); - - theApp.rewindCount = 0; - theApp.rewindCounter = 0; - theApp.rewindSaveNeeded = false; - - CString format = winResLoadString(IDS_LOADED_STATE_N); - buffer.Format(format, nID); - - systemScreenMessage(buffer); - - return res; -} - -void MainWnd::OnFileSave() -{ - theApp.winCheckFullscreen(); - CString buffer; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - buffer = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(isDriveRoot(saveDir)) - filename.Format("%s%s.sgm", saveDir, buffer); - else - filename.Format("%s\\%s.sgm", saveDir, buffer); - - LPCTSTR exts[] = { ".sgm" }; - CString filter = winLoadFilter(IDS_FILTER_SGM); - CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME); - - FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, true); - - if(dlg.DoModal() == IDOK) { - bool res = writeSaveGame(dlg.GetPathName()); - if(res) - systemScreenMessage(winResLoadString(IDS_WROTE_STATE)); - } -} - -void MainWnd::OnUpdateFileSave(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -BOOL MainWnd::OnFileSaveSlot(UINT nID) -{ - nID = nID + 1 - ID_FILE_SAVEGAME_SLOT1; - - CString buffer; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - buffer = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(isDriveRoot(saveDir)) - filename.Format("%s%s%d.sgm", saveDir, buffer, nID); - else - filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID); - - bool res = writeSaveGame(filename); - - CString format = winResLoadString(IDS_WROTE_STATE_N); - buffer.Format(format, nID); - - systemScreenMessage(buffer); - - return res; -} - -void MainWnd::OnFileImportBatteryfile() -{ - theApp.winCheckFullscreen(); - LPCTSTR exts[] = { ".sav" }; - CString filter = winLoadFilter(IDS_FILTER_SAV); - CString title = winResLoadString(IDS_SELECT_BATTERY_FILE); - - CString saveDir = regQueryStringValue("batteryDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - FileDlg dlg(this, "", filter, 0, "", exts, saveDir, title, false); - - if(dlg.DoModal() == IDCANCEL) - return; - - CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST); - CString str2 = winResLoadString(IDS_CONFIRM_ACTION); - - if(MessageBox(str1, - str2, - MB_OKCANCEL) == IDCANCEL) - return; - - bool res = false; - - res = theApp.emulator.emuReadBattery(dlg.GetPathName()); - - if(!res) - systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", dlg.GetPathName()); - else { - theApp.emulator.emuReset(); - } -} - -void MainWnd::OnUpdateFileImportBatteryfile(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileImportGamesharkcodefile() -{ - theApp.winCheckFullscreen(); - LPCTSTR exts[] = { "" }; - CString filter = theApp.cartridgeType == 0 ? winLoadFilter(IDS_FILTER_SPC) : winLoadFilter(IDS_FILTER_GCF); - CString title = winResLoadString(IDS_SELECT_CODE_FILE); - - FileDlg dlg(this, "", filter, 0, "", exts, "", title, false); - - if(dlg.DoModal() == IDCANCEL) - return; - - CString str1 = winResLoadString(IDS_CODES_WILL_BE_LOST); - CString str2 = winResLoadString(IDS_CONFIRM_ACTION); - - if(MessageBox(str1, - str2, - MB_OKCANCEL) == IDCANCEL) - return; - - bool res = false; - CString file = dlg.GetPathName(); - if(theApp.cartridgeType == 1) - res = gbCheatReadGSCodeFile(file); - else { - res = fileImportGSACodeFile(file); - } -} - -void MainWnd::OnUpdateFileImportGamesharkcodefile(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileImportGamesharksnapshot() -{ - theApp.winCheckFullscreen(); - LPCTSTR exts[] = { "" }; - CString filter = theApp.cartridgeType == 1 ? winLoadFilter(IDS_FILTER_GBS) : winLoadFilter(IDS_FILTER_SPS); - CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE); - - FileDlg dlg(this, "", filter, 0, "", exts, "", title, false); - - if(dlg.DoModal() == IDCANCEL) - return; - - CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST); - CString str2 = winResLoadString(IDS_CONFIRM_ACTION); - - if(MessageBox(str1, - str2, - MB_OKCANCEL) == IDCANCEL) - return; - - if(theApp.cartridgeType == 1) - gbReadGSASnapshot(dlg.GetPathName()); - else - CPUReadGSASnapshot(dlg.GetPathName()); -} - -void MainWnd::OnUpdateFileImportGamesharksnapshot(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileExportBatteryfile() -{ - theApp.winCheckFullscreen(); - CString name; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - name = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - name = theApp.filename; - - LPCTSTR exts[] = {".sav", ".dat" }; - - CString filter = winLoadFilter(IDS_FILTER_SAV); - CString title = winResLoadString(IDS_SELECT_BATTERY_FILE); - - CString saveDir = regQueryStringValue("batteryDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - FileDlg dlg(this, - name, - filter, - 1, - "SAV", - exts, - saveDir, - title, - true); - - if(dlg.DoModal() == IDCANCEL) { - return; - } - - bool result = false; - - if(theApp.cartridgeType == 1) { - result = gbWriteBatteryFile(dlg.GetPathName(), false); - } else - result = theApp.emulator.emuWriteBattery(dlg.GetPathName()); - - if(!result) - systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", - dlg.GetPathName()); -} - -void MainWnd::OnUpdateFileExportBatteryfile(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileExportGamesharksnapshot() -{ - theApp.winCheckFullscreen(); - if(eepromInUse) { - systemMessage(IDS_EEPROM_NOT_SUPPORTED, "EEPROM saves cannot be exported"); - return; - } - - CString name; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - name = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - name = theApp.filename; - - LPCTSTR exts[] = {".sps" }; - - CString filter = winLoadFilter(IDS_FILTER_SPS); - CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE); - - FileDlg dlg(this, - name, - filter, - 1, - "SPS", - exts, - "", - title, - true); - - if(dlg.DoModal() == IDCANCEL) - return; - - char buffer[16]; - strncpy(buffer, (const char *)&rom[0xa0], 12); - buffer[12] = 0; - - ExportGSASnapshot dlg2(dlg.GetPathName(), buffer, this); - dlg2.DoModal(); -} - -void MainWnd::OnUpdateFileExportGamesharksnapshot(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating && theApp.cartridgeType == 0); -} - -void MainWnd::OnFileScreencapture() -{ - theApp.winCheckFullscreen(); - CString name; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - name = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - name = theApp.filename; - - CString capdir = regQueryStringValue("captureDir", ""); - if(capdir.IsEmpty()) - capdir = getDirFromFile(name); - - CString ext = "png"; - - if(theApp.captureFormat != 0) - ext = "bmp"; - - if(isDriveRoot(capdir)) - filename.Format("%s%s.%s", capdir, name, ext); - else - filename.Format("%s\\%s.%s", capdir, name, ext); - - LPCTSTR exts[] = {".png", ".bmp" }; - - CString filter = winLoadFilter(IDS_FILTER_PNG); - CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); - - FileDlg dlg(this, - filename, - filter, - theApp.captureFormat ? 2 : 1, - theApp.captureFormat ? "BMP" : "PNG", - exts, - capdir, - title, - true); - - if(dlg.DoModal() == IDCANCEL) - return; - - if(dlg.getFilterIndex() == 2) - theApp.emulator.emuWriteBMP(dlg.GetPathName()); - else - theApp.emulator.emuWritePNG(dlg.GetPathName()); - - systemScreenMessage(winResLoadString(IDS_SCREEN_CAPTURE)); -} - -void MainWnd::OnUpdateFileScreencapture(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileRominformation() -{ - theApp.winCheckFullscreen(); - if(theApp.cartridgeType == 0) { - RomInfoGBA dlg(rom); - dlg.DoModal(); - } else { - RomInfoGB dlg(gbRom); - dlg.DoModal(); - } -} - -void MainWnd::OnUpdateFileRominformation(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileTogglemenu() -{ - if(theApp.videoOption <= VIDEO_4X) - return; - - theApp.menuToggle = !theApp.menuToggle; - - if(theApp.menuToggle) { - theApp.updateMenuBar(); - if(theApp.tripleBuffering) { - if(theApp.display) - theApp.display->checkFullScreen(); - DrawMenuBar(); - } - } else { - SetMenu(NULL); - DestroyMenu(theApp.menu); - } - - theApp.adjustDestRect(); -} - -void MainWnd::OnUpdateFileTogglemenu(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(theApp.videoOption > VIDEO_4X); -} - -bool MainWnd::fileImportGSACodeFile(CString& fileName) -{ - FILE *f = fopen(fileName, "rb"); - - if(f == NULL) { - systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", fileName); - return false; - } - - u32 len; - fread(&len, 1, 4, f); - if(len != 14) { - fclose(f); - systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s", - fileName); - return false; - } - char buffer[16]; - fread(buffer, 1, 14, f); - buffer[14] = 0; - if(memcmp(buffer, "SharkPortCODES", 14)) { - fclose(f); - systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s", - fileName); - return false; - } - fseek(f, 0x1e, SEEK_SET); - fread(&len, 1, 4, f); - int game = 0; - if(len > 1) { - GSACodeSelect dlg(f); - game = dlg.DoModal(); - } - fclose(f); - - bool v3 = false; - - int index = fileName.ReverseFind('.'); - - if(index != -1) { - if(fileName.Right(3).CompareNoCase("XPC") == 0) - v3 = true; - } - - if(game != -1) { - return cheatsImportGSACodeFile(fileName, game, v3); - } - - return true; -} - -void MainWnd::OnFileSavegameOldestslot() -{ - if(!emulating) - return; - - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - filename = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(!isDriveRoot(saveDir)) - saveDir += "\\"; - - CString name; - CFileStatus status; - CString str; +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "stdafx.h" +#include "MainWnd.h" + +#include "ExportGSASnapshot.h" +#include "FileDlg.h" +#include "GSACodeSelect.h" +#include "RomInfo.h" +#include "Reg.h" +#include "WinResUtil.h" + +#include "../GBA.h" +#include "../Globals.h" +#include "../NLS.h" +#include "../Sound.h" +#include "../gb/GB.h" +#include "../gb/gbCheats.h" +#include "../gb/gbGlobals.h" +#include "../Link.h" + +extern int emulating; + +extern void remoteCleanUp(); + +void MainWnd::OnFileOpen() +{ + theApp.winCheckFullscreen(); + if(fileOpenSelect()) { + FileRun(); + } +} + +void MainWnd::OnFilePause() +{ + theApp.paused = !theApp.paused; + if(emulating) { + if(theApp.paused) { + theApp.wasPaused = true; + soundPause(); + } else { + soundResume(); + } + } +} + +void MainWnd::OnUpdateFilePause(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(theApp.paused); +} + +void MainWnd::OnFileReset() +{ + if(emulating) { + theApp.emulator.emuReset(); + systemScreenMessage(winResLoadString(IDS_RESET)); + } +} + +void MainWnd::OnUpdateFileReset(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnUpdateFileRecentFreeze(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(theApp.recentFreeze); + + if(pCmdUI->m_pMenu == NULL) + return; + + CMenu *pMenu = pCmdUI->m_pMenu; + + int i; + for(i = 0; i < 10; i++) { + if(!pMenu->RemoveMenu(ID_FILE_MRU_FILE1+i, MF_BYCOMMAND)) + break; + } + + for(i = 0; i < 10; i++) { + CString p = theApp.recentFiles[i]; + if(p.GetLength() == 0) + break; + int index = p.ReverseFind('\\'); + + if(index != -1) + p = p.Right(p.GetLength()-index-1); + + pMenu->AppendMenu(MF_STRING, ID_FILE_MRU_FILE1+i, p); + } + theApp.winAccelMgr.UpdateMenu((HMENU)*pMenu); +} + +BOOL MainWnd::OnFileRecentFile(UINT nID) +{ + if(theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1].GetLength()) { + theApp.szFile = theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1]; + if(FileRun()) + emulating = true; + else { + emulating = false; + soundPause(); + } + } + return TRUE; +} + +void MainWnd::OnFileRecentReset() +{ + int i = 0; + for(i = 0; i < 10; i++) + theApp.recentFiles[i] = ""; +} + +void MainWnd::OnFileRecentFreeze() +{ + theApp.recentFreeze = !theApp.recentFreeze; +} + +void MainWnd::OnFileExit() +{ + SendMessage(WM_CLOSE); +} + +void MainWnd::OnFileClose() +{ + // save battery file before we change the filename... + if(rom != NULL || gbRom != NULL) { + if(theApp.autoSaveLoadCheatList) + winSaveCheatListDefault(); + writeBatteryFile(); + soundPause(); + theApp.emulator.emuCleanUp(); + remoteCleanUp(); + } + emulating = 0; + RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); + systemSetTitle("VisualBoyAdvance"); +} + +void MainWnd::OnUpdateFileClose(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileOpengameboy() +{ + theApp.winCheckFullscreen(); + theApp.dir = ""; + CString initialDir = regQueryStringValue("gbromdir","."); + if(!initialDir.IsEmpty()) + theApp.dir = initialDir; + + theApp.szFile = ""; + + LPCTSTR exts[] = { "" }; + CString filter = winLoadFilter(IDS_FILTER_GBROM); + CString title = winResLoadString(IDS_SELECT_ROM); + + FileDlg dlg(this, "", filter, 0, "", exts, initialDir, title, false); + + if(dlg.DoModal() == IDOK) { + theApp.szFile = dlg.GetPathName(); + theApp.dir = theApp.szFile.Left(dlg.m_ofn.nFileOffset); + if(theApp.dir.GetLength() > 3 && theApp.dir[theApp.dir.GetLength()-1] == '\\') + theApp.dir = theApp.dir.Left(theApp.dir.GetLength()-1); + regSetStringValue("gbromdir", theApp.dir); + FileRun(); + } +} + +void MainWnd::OnFileLoad() +{ + theApp.winCheckFullscreen(); + CString buffer; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + buffer = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(isDriveRoot(saveDir)) + filename.Format("%s%s.sgm", saveDir, buffer); + else + filename.Format("%s\\%s.sgm", saveDir, buffer); + + LPCTSTR exts[] = { ".sgm" }; + CString filter = winLoadFilter(IDS_FILTER_SGM); + CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME); + + FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, false); + + if(dlg.DoModal() == IDOK) { + bool res = loadSaveGame(dlg.GetPathName()); + + theApp.rewindCount = 0; + theApp.rewindCounter = 0; + theApp.rewindSaveNeeded = false; + + if(res) + systemScreenMessage(winResLoadString(IDS_LOADED_STATE)); + } +} + +void MainWnd::OnUpdateFileLoad(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +BOOL MainWnd::OnFileLoadSlot(UINT nID) +{ + nID = nID + 1 - ID_FILE_LOADGAME_SLOT1; + + CString buffer; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + buffer = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(isDriveRoot(saveDir)) + filename.Format("%s%s%d.sgm", saveDir, buffer, nID); + else + filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID); + + bool res = loadSaveGame(filename); + + theApp.rewindCount = 0; + theApp.rewindCounter = 0; + theApp.rewindSaveNeeded = false; + + CString format = winResLoadString(IDS_LOADED_STATE_N); + buffer.Format(format, nID); + + systemScreenMessage(buffer); + + return res; +} + +void MainWnd::OnFileSave() +{ + theApp.winCheckFullscreen(); + CString buffer; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + buffer = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(isDriveRoot(saveDir)) + filename.Format("%s%s.sgm", saveDir, buffer); + else + filename.Format("%s\\%s.sgm", saveDir, buffer); + + LPCTSTR exts[] = { ".sgm" }; + CString filter = winLoadFilter(IDS_FILTER_SGM); + CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME); + + FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, true); + + if(dlg.DoModal() == IDOK) { + bool res = writeSaveGame(dlg.GetPathName()); + if(res) + systemScreenMessage(winResLoadString(IDS_WROTE_STATE)); + } +} + +void MainWnd::OnUpdateFileSave(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +BOOL MainWnd::OnFileSaveSlot(UINT nID) +{ + nID = nID + 1 - ID_FILE_SAVEGAME_SLOT1; + + CString buffer; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + buffer = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(isDriveRoot(saveDir)) + filename.Format("%s%s%d.sgm", saveDir, buffer, nID); + else + filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID); + + bool res = writeSaveGame(filename); + + CString format = winResLoadString(IDS_WROTE_STATE_N); + buffer.Format(format, nID); + + systemScreenMessage(buffer); + + return res; +} + +void MainWnd::OnFileImportBatteryfile() +{ + theApp.winCheckFullscreen(); + LPCTSTR exts[] = { ".sav" }; + CString filter = winLoadFilter(IDS_FILTER_SAV); + CString title = winResLoadString(IDS_SELECT_BATTERY_FILE); + + CString saveDir = regQueryStringValue("batteryDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + FileDlg dlg(this, "", filter, 0, "", exts, saveDir, title, false); + + if(dlg.DoModal() == IDCANCEL) + return; + + CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST); + CString str2 = winResLoadString(IDS_CONFIRM_ACTION); + + if(MessageBox(str1, + str2, + MB_OKCANCEL) == IDCANCEL) + return; + + bool res = false; + + res = theApp.emulator.emuReadBattery(dlg.GetPathName()); + + if(!res) + systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", dlg.GetPathName()); + else { + theApp.emulator.emuReset(); + } +} + +void MainWnd::OnUpdateFileImportBatteryfile(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileImportGamesharkcodefile() +{ + theApp.winCheckFullscreen(); + LPCTSTR exts[] = { "" }; + CString filter = theApp.cartridgeType == 0 ? winLoadFilter(IDS_FILTER_SPC) : winLoadFilter(IDS_FILTER_GCF); + CString title = winResLoadString(IDS_SELECT_CODE_FILE); + + FileDlg dlg(this, "", filter, 0, "", exts, "", title, false); + + if(dlg.DoModal() == IDCANCEL) + return; + + CString str1 = winResLoadString(IDS_CODES_WILL_BE_LOST); + CString str2 = winResLoadString(IDS_CONFIRM_ACTION); + + if(MessageBox(str1, + str2, + MB_OKCANCEL) == IDCANCEL) + return; + + bool res = false; + CString file = dlg.GetPathName(); + if(theApp.cartridgeType == 1) + res = gbCheatReadGSCodeFile(file); + else { + res = fileImportGSACodeFile(file); + } +} + +void MainWnd::OnUpdateFileImportGamesharkcodefile(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileImportGamesharksnapshot() +{ + theApp.winCheckFullscreen(); + LPCTSTR exts[] = { "" }; + CString filter = theApp.cartridgeType == 1 ? winLoadFilter(IDS_FILTER_GBS) : winLoadFilter(IDS_FILTER_SPS); + CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE); + + FileDlg dlg(this, "", filter, 0, "", exts, "", title, false); + + if(dlg.DoModal() == IDCANCEL) + return; + + CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST); + CString str2 = winResLoadString(IDS_CONFIRM_ACTION); + + if(MessageBox(str1, + str2, + MB_OKCANCEL) == IDCANCEL) + return; + + if(theApp.cartridgeType == 1) + gbReadGSASnapshot(dlg.GetPathName()); + else + CPUReadGSASnapshot(dlg.GetPathName()); +} + +void MainWnd::OnUpdateFileImportGamesharksnapshot(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileExportBatteryfile() +{ + theApp.winCheckFullscreen(); + CString name; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + name = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + name = theApp.filename; + + LPCTSTR exts[] = {".sav", ".dat" }; + + CString filter = winLoadFilter(IDS_FILTER_SAV); + CString title = winResLoadString(IDS_SELECT_BATTERY_FILE); + + CString saveDir = regQueryStringValue("batteryDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + FileDlg dlg(this, + name, + filter, + 1, + "SAV", + exts, + saveDir, + title, + true); + + if(dlg.DoModal() == IDCANCEL) { + return; + } + + bool result = false; + + if(theApp.cartridgeType == 1) { + result = gbWriteBatteryFile(dlg.GetPathName(), false); + } else + result = theApp.emulator.emuWriteBattery(dlg.GetPathName()); + + if(!result) + systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", + dlg.GetPathName()); +} + +void MainWnd::OnUpdateFileExportBatteryfile(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileExportGamesharksnapshot() +{ + theApp.winCheckFullscreen(); + if(eepromInUse) { + systemMessage(IDS_EEPROM_NOT_SUPPORTED, "EEPROM saves cannot be exported"); + return; + } + + CString name; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + name = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + name = theApp.filename; + + LPCTSTR exts[] = {".sps" }; + + CString filter = winLoadFilter(IDS_FILTER_SPS); + CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE); + + FileDlg dlg(this, + name, + filter, + 1, + "SPS", + exts, + "", + title, + true); + + if(dlg.DoModal() == IDCANCEL) + return; + + char buffer[16]; + strncpy(buffer, (const char *)&rom[0xa0], 12); + buffer[12] = 0; + + ExportGSASnapshot dlg2(dlg.GetPathName(), buffer, this); + dlg2.DoModal(); +} + +void MainWnd::OnUpdateFileExportGamesharksnapshot(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating && theApp.cartridgeType == 0); +} + +void MainWnd::OnFileScreencapture() +{ + theApp.winCheckFullscreen(); + CString name; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + name = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + name = theApp.filename; + + CString capdir = regQueryStringValue("captureDir", ""); + if(capdir.IsEmpty()) + capdir = getDirFromFile(name); + + CString ext = "png"; + + if(theApp.captureFormat != 0) + ext = "bmp"; + + if(isDriveRoot(capdir)) + filename.Format("%s%s.%s", capdir, name, ext); + else + filename.Format("%s\\%s.%s", capdir, name, ext); + + LPCTSTR exts[] = {".png", ".bmp" }; + + CString filter = winLoadFilter(IDS_FILTER_PNG); + CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); + + FileDlg dlg(this, + filename, + filter, + theApp.captureFormat ? 2 : 1, + theApp.captureFormat ? "BMP" : "PNG", + exts, + capdir, + title, + true); + + if(dlg.DoModal() == IDCANCEL) + return; + + if(dlg.getFilterIndex() == 2) + theApp.emulator.emuWriteBMP(dlg.GetPathName()); + else + theApp.emulator.emuWritePNG(dlg.GetPathName()); + + systemScreenMessage(winResLoadString(IDS_SCREEN_CAPTURE)); +} + +void MainWnd::OnUpdateFileScreencapture(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileRominformation() +{ + theApp.winCheckFullscreen(); + if(theApp.cartridgeType == 0) { + RomInfoGBA dlg(rom); + dlg.DoModal(); + } else { + RomInfoGB dlg(gbRom); + dlg.DoModal(); + } +} + +void MainWnd::OnUpdateFileRominformation(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileTogglemenu() +{ + if(theApp.videoOption <= VIDEO_4X) + return; + + theApp.menuToggle = !theApp.menuToggle; + + if(theApp.menuToggle) { + theApp.updateMenuBar(); + if(theApp.tripleBuffering) { + if(theApp.display) + theApp.display->checkFullScreen(); + DrawMenuBar(); + } + } else { + SetMenu(NULL); + DestroyMenu(theApp.menu); + } + + theApp.adjustDestRect(); + if(theApp.display) + theApp.display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top); + +} + +void MainWnd::OnUpdateFileTogglemenu(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(theApp.videoOption > VIDEO_4X); +} + +bool MainWnd::fileImportGSACodeFile(CString& fileName) +{ + FILE *f = fopen(fileName, "rb"); + + if(f == NULL) { + systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", fileName); + return false; + } + + u32 len; + fread(&len, 1, 4, f); + if(len != 14) { + fclose(f); + systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s", + fileName); + return false; + } + char buffer[16]; + fread(buffer, 1, 14, f); + buffer[14] = 0; + if(memcmp(buffer, "SharkPortCODES", 14)) { + fclose(f); + systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s", + fileName); + return false; + } + fseek(f, 0x1e, SEEK_SET); + fread(&len, 1, 4, f); + int game = 0; + if(len > 1) { + GSACodeSelect dlg(f); + game = dlg.DoModal(); + } + fclose(f); + + bool v3 = false; + + int index = fileName.ReverseFind('.'); + + if(index != -1) { + if(fileName.Right(3).CompareNoCase("XPC") == 0) + v3 = true; + } + + if(game != -1) { + return cheatsImportGSACodeFile(fileName, game, v3); + } + + return true; +} + +void MainWnd::OnFileSavegameOldestslot() +{ + if(!emulating) + return; + + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + filename = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(!isDriveRoot(saveDir)) + saveDir += "\\"; + + CString name; + CFileStatus status; + CString str; unsigned long time = (unsigned long)-1; int found = 0; @@ -737,161 +740,161 @@ void MainWnd::OnFileSavegameOldestslot() if(emulating && CFile::GetStatus(name, status)) { if((unsigned long)status.m_mtime.GetTime() < time) { - time = (time_t)status.m_mtime.GetTime(); - found = i; - } - } else { - found = i; - break; - } - } - OnFileSaveSlot(ID_FILE_SAVEGAME_SLOT1+found); -} - -void MainWnd::OnUpdateFileSavegameOldestslot(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); - if(pCmdUI->m_pSubMenu != NULL) { - CMenu *pMenu = pCmdUI->m_pSubMenu; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - filename = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(!isDriveRoot(saveDir)) - saveDir += "\\"; - - CString name; - CFileStatus status; - CString str; - - for(int i = 0; i < 10; i++) { - name.Format("%s%s%d.sgm", saveDir, filename, i+1); - - if(emulating && CFile::GetStatus(name, status)) { - CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S"); - str.Format("%d %s", i+1, timestamp); - } else { - str.Format("%d ----/--/-- --:--:--", i+1); - } - pMenu->ModifyMenu(ID_FILE_SAVEGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_SAVEGAME_SLOT1+i, str); - } - - theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu()); - } -} - -void MainWnd::OnFileLoadgameMostrecent() -{ - if(!emulating) - return; - - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - filename = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(!isDriveRoot(saveDir)) - saveDir += "\\"; - - CString name; - CFileStatus status; - CString str; + time = (time_t)status.m_mtime.GetTime(); + found = i; + } + } else { + found = i; + break; + } + } + OnFileSaveSlot(ID_FILE_SAVEGAME_SLOT1+found); +} + +void MainWnd::OnUpdateFileSavegameOldestslot(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); + if(pCmdUI->m_pSubMenu != NULL) { + CMenu *pMenu = pCmdUI->m_pSubMenu; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + filename = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(!isDriveRoot(saveDir)) + saveDir += "\\"; + + CString name; + CFileStatus status; + CString str; + + for(int i = 0; i < 10; i++) { + name.Format("%s%s%d.sgm", saveDir, filename, i+1); + + if(emulating && CFile::GetStatus(name, status)) { + CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S"); + str.Format("%d %s", i+1, timestamp); + } else { + str.Format("%d ----/--/-- --:--:--", i+1); + } + pMenu->ModifyMenu(ID_FILE_SAVEGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_SAVEGAME_SLOT1+i, str); + } + + theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu()); + } +} + +void MainWnd::OnFileLoadgameMostrecent() +{ + if(!emulating) + return; + + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + filename = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(!isDriveRoot(saveDir)) + saveDir += "\\"; + + CString name; + CFileStatus status; + CString str; unsigned long time = 0; - int found = -1; - - for(int i = 0; i < 10; i++) { - name.Format("%s%s%d.sgm", saveDir, filename, i+1); - - if(emulating && CFile::GetStatus(name, status)) { + int found = -1; + + for(int i = 0; i < 10; i++) { + name.Format("%s%s%d.sgm", saveDir, filename, i+1); + + if(emulating && CFile::GetStatus(name, status)) { if((unsigned long)status.m_mtime.GetTime() > time) { - time = (time_t)status.m_mtime.GetTime(); - found = i; - } - } - } - if(found != -1) { - OnFileLoadSlot(ID_FILE_LOADGAME_SLOT1+found); - } -} - -void MainWnd::OnUpdateFileLoadgameMostrecent(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(emulating); - - if(pCmdUI->m_pSubMenu != NULL) { - CMenu *pMenu = pCmdUI->m_pSubMenu; - CString filename; - - int index = theApp.filename.ReverseFind('\\'); - - if(index != -1) - filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); - else - filename = theApp.filename; - - CString saveDir = regQueryStringValue("saveDir", NULL); - - if(saveDir.IsEmpty()) - saveDir = getDirFromFile(theApp.filename); - - if(!isDriveRoot(saveDir)) - saveDir += "\\"; - - CString name; - CFileStatus status; - CString str; - - for(int i = 0; i < 10; i++) { - name.Format("%s%s%d.sgm", saveDir, filename, i+1); - - if(emulating && CFile::GetStatus(name, status)) { - CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S"); - str.Format("%d %s", i+1, timestamp); - } else { - str.Format("%d ----/--/-- --:--:--", i+1); - } - pMenu->ModifyMenu(ID_FILE_LOADGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_LOADGAME_SLOT1+i, str); - } - - theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu()); - } -} - -void MainWnd::OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnUpdateFileSaveGameSlot(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(emulating); -} - -void MainWnd::OnFileLoadgameAutoloadmostrecent() -{ - theApp.autoLoadMostRecent = !theApp.autoLoadMostRecent; -} - -void MainWnd::OnUpdateFileLoadgameAutoloadmostrecent(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(theApp.autoLoadMostRecent); -} + time = (time_t)status.m_mtime.GetTime(); + found = i; + } + } + } + if(found != -1) { + OnFileLoadSlot(ID_FILE_LOADGAME_SLOT1+found); + } +} + +void MainWnd::OnUpdateFileLoadgameMostrecent(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating); + + if(pCmdUI->m_pSubMenu != NULL) { + CMenu *pMenu = pCmdUI->m_pSubMenu; + CString filename; + + int index = theApp.filename.ReverseFind('\\'); + + if(index != -1) + filename = theApp.filename.Right(theApp.filename.GetLength()-index-1); + else + filename = theApp.filename; + + CString saveDir = regQueryStringValue("saveDir", NULL); + + if(saveDir.IsEmpty()) + saveDir = getDirFromFile(theApp.filename); + + if(!isDriveRoot(saveDir)) + saveDir += "\\"; + + CString name; + CFileStatus status; + CString str; + + for(int i = 0; i < 10; i++) { + name.Format("%s%s%d.sgm", saveDir, filename, i+1); + + if(emulating && CFile::GetStatus(name, status)) { + CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S"); + str.Format("%d %s", i+1, timestamp); + } else { + str.Format("%d ----/--/-- --:--:--", i+1); + } + pMenu->ModifyMenu(ID_FILE_LOADGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_LOADGAME_SLOT1+i, str); + } + + theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu()); + } +} + +void MainWnd::OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnUpdateFileSaveGameSlot(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(emulating); +} + +void MainWnd::OnFileLoadgameAutoloadmostrecent() +{ + theApp.autoLoadMostRecent = !theApp.autoLoadMostRecent; +} + +void MainWnd::OnUpdateFileLoadgameAutoloadmostrecent(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(theApp.autoLoadMostRecent); +} diff --git a/src/win32/MainWndOptions.cpp b/src/win32/MainWndOptions.cpp index 693372a9..75fe63d3 100644 --- a/src/win32/MainWndOptions.cpp +++ b/src/win32/MainWndOptions.cpp @@ -225,6 +225,7 @@ void MainWnd::OnUpdateOptionsVideoFrameskip9(CCmdUI* pCmdUI) void MainWnd::OnOptionsVideoVsync() { theApp.vsync = !theApp.vsync; + theApp.updateRenderMethod(true); } void MainWnd::OnUpdateOptionsVideoVsync(CCmdUI* pCmdUI) @@ -455,6 +456,7 @@ void MainWnd::OnUpdateOptionsVideoRendermethodOpengl(CCmdUI* pCmdUI) void MainWnd::OnOptionsVideoTriplebuffering() { theApp.tripleBuffering = !theApp.tripleBuffering; + theApp.updateRenderMethod(true); } void MainWnd::OnUpdateOptionsVideoTriplebuffering(CCmdUI* pCmdUI)