diff --git a/VBA.suo b/VBA.suo deleted file mode 100644 index f8fa64e9..00000000 Binary files a/VBA.suo and /dev/null differ diff --git a/VBA.vcproj b/VBA.vcproj index 0b1a8470..d8954eff 100644 --- a/VBA.vcproj +++ b/VBA.vcproj @@ -1642,6 +1642,10 @@ > + + -#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)