From 8a7f7b201cd0a9536f6f64755d59fc27a05dbfc9 Mon Sep 17 00:00:00 2001 From: DJRobX Date: Wed, 7 Nov 2007 09:24:46 +0000 Subject: [PATCH] Direct3d fixes, disabling lockable backbuffers. Official 1.8 beta seems to have an incomplete direct3d implementation. You cannot select full screen modes without using DirectDraw. This is fixed in this buld --- trunk/src/win32/Direct3D.cpp | 1276 ++++++++++----------- trunk/src/win32/DirectInput.cpp | 1858 +++++++++++++++---------------- 2 files changed, 1573 insertions(+), 1561 deletions(-) diff --git a/trunk/src/win32/Direct3D.cpp b/trunk/src/win32/Direct3D.cpp index aba02150..81062b72 100644 --- a/trunk/src/win32/Direct3D.cpp +++ b/trunk/src/win32/Direct3D.cpp @@ -1,116 +1,117 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team -// Copyright (C) 2005-2006 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 "Display.h" - -#include "MainWnd.h" - -#include "../System.h" -#include "../GBA.h" -#include "../Globals.h" -#include "../Text.h" -#include "../Util.h" -#include "../gb/gbGlobals.h" - -// Direct3D -#define DIRECT3D_VERSION 0x0900 -#include // main include file -#include // required for font rednering -#include // contains debug functions - -extern int Init_2xSaI(u32); // initializes all pixel filters -extern int systemSpeed; - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#ifdef MMX -extern "C" bool cpu_mmx; -extern bool detectMMX(); -#endif - - -class Direct3DDisplay : public IDisplay { -private: - LPDIRECT3D9 pD3D; - LPDIRECT3DDEVICE9 pDevice; - D3DDISPLAYMODE mode; - D3DPRESENT_PARAMETERS dpp; - D3DFORMAT screenFormat; - LPDIRECT3DSURFACE9 emulatedImage; - D3DTEXTUREFILTERTYPE filter; - int width; - int height; - RECT destRect; - bool failed; - ID3DXFont *pFont; - - void createFont(); - void destroyFont(); - void createSurface(); - void destroySurface(); - void calculateDestRect(); - bool resetDevice(); - void setPresentationType(); - -public: - Direct3DDisplay(); - virtual ~Direct3DDisplay(); - virtual DISPLAY_TYPE getType() { return DIRECT_3D; }; - - virtual bool initialize(); - virtual void cleanup(); - virtual void clear(); - virtual void render(); - - virtual void renderMenu(); - virtual bool changeRenderSize( int w, int h ); - virtual void resize( int w, int h ); - virtual void setOption( const char *option, int value ); - virtual int selectFullScreenMode( GUID ** ); -}; - - -Direct3DDisplay::Direct3DDisplay() -{ - pD3D = NULL; - pDevice = NULL; - screenFormat = D3DFMT_X8R8G8B8; - width = 0; - height = 0; - failed = false; - pFont = NULL; - emulatedImage = NULL; - filter = D3DTEXF_POINT; -} - - -Direct3DDisplay::~Direct3DDisplay() -{ - cleanup(); -} - +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 "Display.h" + +#include "MainWnd.h" + +#include "../System.h" +#include "../GBA.h" +#include "../Globals.h" +#include "../Text.h" +#include "../Util.h" +#include "../gb/gbGlobals.h" + +// Direct3D +#define DIRECT3D_VERSION 0x0900 +#include // main include file +#include // required for font rednering +#include // contains debug functions + +extern int Init_2xSaI(u32); // initializes all pixel filters +extern int systemSpeed; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#ifdef MMX +extern "C" bool cpu_mmx; +extern bool detectMMX(); +#endif + +extern int winVideoModeSelect(CWnd *, GUID **); + +class Direct3DDisplay : public IDisplay { +private: + LPDIRECT3D9 pD3D; + LPDIRECT3DDEVICE9 pDevice; + D3DDISPLAYMODE mode; + D3DPRESENT_PARAMETERS dpp; + D3DFORMAT screenFormat; + LPDIRECT3DSURFACE9 emulatedImage; + D3DTEXTUREFILTERTYPE filter; + int width; + int height; + RECT destRect; + bool failed; + ID3DXFont *pFont; + + void createFont(); + void destroyFont(); + void createSurface(); + void destroySurface(); + void calculateDestRect(); + bool resetDevice(); + void setPresentationType(); + +public: + Direct3DDisplay(); + virtual ~Direct3DDisplay(); + virtual DISPLAY_TYPE getType() { return DIRECT_3D; }; + + virtual bool initialize(); + virtual void cleanup(); + virtual void clear(); + virtual void render(); + + virtual void renderMenu(); + virtual bool changeRenderSize( int w, int h ); + virtual void resize( int w, int h ); + virtual void setOption( const char *option, int value ); + virtual int selectFullScreenMode( GUID ** ); +}; + + +Direct3DDisplay::Direct3DDisplay() +{ + pD3D = NULL; + pDevice = NULL; + screenFormat = D3DFMT_X8R8G8B8; + width = 0; + height = 0; + failed = false; + pFont = NULL; + emulatedImage = NULL; + filter = D3DTEXF_POINT; +} + + +Direct3DDisplay::~Direct3DDisplay() +{ + cleanup(); +} + void Direct3DDisplay::setPresentationType() { // Change display mode @@ -134,523 +135,534 @@ void Direct3DDisplay::setPresentationType() else dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync } - - -void Direct3DDisplay::cleanup() -{ - destroyFont(); - destroySurface(); - - if( pDevice ) { - pDevice->Release(); - pDevice = NULL; - } - - if( pD3D ) { - pD3D->Release(); - pD3D = NULL; - } -} - - -bool Direct3DDisplay::initialize() -{ - switch(theApp.cartridgeType) - { - case IMAGE_GBA: - theApp.sizeX = 240; - theApp.sizeY = 160; - break; - case IMAGE_GB: - if (gbBorderOn) - { - theApp.sizeX = 256; - theApp.sizeY = 224; - } - else - { - theApp.sizeX = 160; - theApp.sizeY = 144; - } - break; - } - - - switch(theApp.videoOption) - { - case VIDEO_1X: - theApp.surfaceSizeX = theApp.sizeX; - theApp.surfaceSizeY = theApp.sizeY; - break; - case VIDEO_2X: - theApp.surfaceSizeX = theApp.sizeX * 2; - theApp.surfaceSizeY = theApp.sizeY * 2; - break; - case VIDEO_3X: - theApp.surfaceSizeX = theApp.sizeX * 3; - theApp.surfaceSizeY = theApp.sizeY * 3; - break; - case VIDEO_4X: - theApp.surfaceSizeX = theApp.sizeX * 4; - theApp.surfaceSizeY = theApp.sizeY * 4; - break; - case VIDEO_320x240: - case VIDEO_640x480: - case VIDEO_800x600: - case VIDEO_1024x768: - case VIDEO_1280x1024: - case VIDEO_OTHER: - float scaleX = ((float)theApp.fsWidth / theApp.sizeX); - float scaleY = ((float)theApp.fsHeight / theApp.sizeY); - float min = (scaleX < scaleY) ? scaleX : scaleY; - if(theApp.fullScreenStretch) { - theApp.surfaceSizeX = theApp.fsWidth; - theApp.surfaceSizeY = theApp.fsHeight; - } else { - theApp.surfaceSizeX = (int)(theApp.sizeX * min); - theApp.surfaceSizeY = (int)(theApp.sizeY * min); - } - break; - } - - theApp.rect.left = 0; - theApp.rect.top = 0; - theApp.rect.right = theApp.sizeX; - theApp.rect.bottom = theApp.sizeY; - - theApp.dest.left = 0; - theApp.dest.top = 0; - theApp.dest.right = theApp.surfaceSizeX; - theApp.dest.bottom = theApp.surfaceSizeY; - - - DWORD style = WS_POPUP | WS_VISIBLE; - DWORD styleEx = 0; - - if(theApp.videoOption <= VIDEO_4X) { - style |= WS_OVERLAPPEDWINDOW; - } else { - styleEx = 0; - } - - if(theApp.videoOption <= VIDEO_4X) { - AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx); - } else { - AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx); - } - - int winSizeX = theApp.dest.right-theApp.dest.left; - int winSizeY = theApp.dest.bottom-theApp.dest.top; - - if(theApp.videoOption > VIDEO_4X) { - winSizeX = theApp.fsWidth; - winSizeY = theApp.fsHeight; - } - - int x = 0, y = 0; - - if(theApp.videoOption <= VIDEO_4X) { - x = theApp.windowPositionX; - y = theApp.windowPositionY; - } - - - // Create a window - MainWnd *pWnd = new MainWnd; - theApp.m_pMainWnd = pWnd; - - pWnd->CreateEx(styleEx, - theApp.wndClass, - _T("VisualBoyAdvance"), - style, - x,y,winSizeX,winSizeY, - NULL, - 0); - - if (!(HWND)*pWnd) { - DXTRACE_ERR_MSGBOX( _T("Error creating window"), 0 ); - return FALSE; - } - pWnd->DragAcceptFiles(TRUE); - theApp.updateMenuBar(); - theApp.adjustDestRect(); - - - // load Direct3D v9 - pD3D = Direct3DCreate9( D3D_SDK_VERSION ); - - if(pD3D == NULL) { - DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D object"), 0 ); - return FALSE; - } - - theApp.mode320Available = FALSE; - theApp.mode640Available = FALSE; - theApp.mode800Available = FALSE; - theApp.mode1024Available = FALSE; - theApp.mode1280Available = FALSE; - - pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode); - screenFormat = mode.Format; - - switch(mode.Format) { - case D3DFMT_R8G8B8: - systemColorDepth = 24; - systemRedShift = 19; - systemGreenShift = 11; - systemBlueShift = 3; - break; - case D3DFMT_X8R8G8B8: - systemColorDepth = 32; - systemRedShift = 19; - systemGreenShift = 11; - systemBlueShift = 3; - Init_2xSaI(32); - break; - case D3DFMT_R5G6B5: - systemColorDepth = 16; - systemRedShift = 11; - systemGreenShift = 6; - systemBlueShift = 0; - Init_2xSaI(565); - break; - case D3DFMT_X1R5G5B5: - systemColorDepth = 16; - systemRedShift = 10; - systemGreenShift = 5; - systemBlueShift = 0; - Init_2xSaI(555); - break; - default: - DXTRACE_ERR_MSGBOX( _T("Unsupport D3D format"), 0 ); - return false; - } - theApp.fsColorDepth = systemColorDepth; - utilUpdateSystemColorMaps(); - - -#ifdef MMX - if(!theApp.disableMMX) { - cpu_mmx = theApp.detectMMX(); - } else { - cpu_mmx = 0; - } -#endif - - - theApp.updateFilter(); - theApp.updateIFB(); - - - // create device - setPresentationType(); - - HRESULT hret = pD3D->CreateDevice( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - pWnd->GetSafeHwnd(), - D3DCREATE_SOFTWARE_VERTEXPROCESSING, - &dpp, - &pDevice); - if( FAILED( hret ) ) { - DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D device"), hret ); - return false; - } - - createFont(); - createSurface(); - calculateDestRect(); - - setOption( _T("d3dFilter"), theApp.d3dFilter ); - - if(failed) return false; - - return TRUE; -} - - -void Direct3DDisplay::renderMenu() -{ - checkFullScreen(); - if(theApp.m_pMainWnd) { - theApp.m_pMainWnd->DrawMenuBar(); - } -} - - -void Direct3DDisplay::clear() -{ - if( pDevice ) { - pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00,0x00,0x00), 0.0f, 0 ); - } -} - - -void Direct3DDisplay::render() -{ - if( failed ) return; - if(!pDevice) return; - if( FAILED( pDevice->TestCooperativeLevel() ) ) return; - - clear(); - - pDevice->BeginScene(); - - // copy pix to emulatedImage and apply pixel filter if selected - HRESULT hr; - D3DLOCKED_RECT lr; - if( FAILED( hr = emulatedImage->LockRect( &lr, NULL, D3DLOCK_DISCARD ) ) ) { - DXTRACE_ERR_MSGBOX( _T("Can not lock back buffer"), hr ); - return; - } else { - if( !theApp.filterFunction ) { - copyImage( pix, lr.pBits, theApp.sizeX, theApp.sizeY, lr.Pitch, systemColorDepth ); - } else { - u32 pitch = theApp.filterWidth * (systemColorDepth>>3) + 4; - theApp.filterFunction( pix + pitch, - pitch, - (u8*)theApp.delta, - (u8*)lr.pBits, - lr.Pitch, - theApp.filterWidth, - theApp.filterHeight); - } - emulatedImage->UnlockRect(); - } - - // copy emulatedImage to pBackBuffer and scale with or without aspect ratio - LPDIRECT3DSURFACE9 pBackBuffer; - pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); - if( theApp.fullScreenStretch ) { - pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, NULL, filter ); - } else { - pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, &destRect, filter ); - } - pBackBuffer->Release(); - pBackBuffer = NULL; - - D3DCOLOR color; - RECT r; - r.left = 4; - r.right = dpp.BackBufferWidth - 4; - - if( theApp.screenMessage ) { - color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0xFF, 0x00, 0x00) : D3DCOLOR_ARGB(0xFF, 0xFF, 0x00, 0x00); - if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage && pFont ) { - r.top = dpp.BackBufferHeight - 20; - r.bottom = dpp.BackBufferHeight - 4; - pFont->DrawText( NULL, theApp.screenMessageBuffer, -1, &r, 0, color ); - } else { - theApp.screenMessage = false; - } - } - - if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) { - color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0x00, 0x00, 0xFF) : D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0xFF); - char buffer[30]; - if( theApp.showSpeed == 1 ) { - sprintf( buffer, "%3d%%", systemSpeed ); - } else { - sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames ); - } - - r.top = 4; - r.bottom = 20; - pFont->DrawText( NULL, buffer, -1, &r, 0, color ); - } - - pDevice->EndScene(); - - pDevice->Present( NULL, NULL, NULL, NULL ); - - return; -} - - -bool Direct3DDisplay::changeRenderSize( int w, int h ) -{ - if( (w != width) || (h != height) ) { - width = w; height = h; - if( pDevice ) { - destroySurface(); - createSurface(); - calculateDestRect(); - } - } - return true; -} - - -void Direct3DDisplay::resize( int w, int h ) -{ - if( (w != dpp.BackBufferWidth) || (h != dpp.BackBufferHeight) ) { - dpp.BackBufferWidth = (UINT)w; - dpp.BackBufferHeight = (UINT)h; - resetDevice(); - calculateDestRect(); - } -} - - -int Direct3DDisplay::selectFullScreenMode( GUID ** ) -{ - HRESULT hr; - D3DDISPLAYMODE dm; - if( FAILED( hr = pDevice->GetDisplayMode( 0, &dm ) ) ) { - DXTRACE_ERR_MSGBOX( _T("pDevice->GetDisplayMode failed"), hr ); - return false; - } - - UINT bitsPerPixel; - switch( dm.Format ) - { - case D3DFMT_A2R10G10B10: - case D3DFMT_X8R8G8B8: - bitsPerPixel = 32; - break; - case D3DFMT_X1R5G5B5: - case D3DFMT_R5G6B5: - bitsPerPixel = 16; - break; - } - - return (bitsPerPixel << 24) | (dm.Width << 12) | dm.Height; -} - - -void Direct3DDisplay::createFont() -{ - if( !pFont ) { - HRESULT hr = D3DXCreateFont( - pDevice, - 14, - 0, - FW_BOLD, - 1, - FALSE, - DEFAULT_CHARSET, - OUT_DEFAULT_PRECIS, - DEFAULT_QUALITY, - DEFAULT_PITCH || FF_DONTCARE, - _T("Arial"), - &pFont ); - if( FAILED( hr ) ) { - DXTRACE_ERR_MSGBOX( _T("createFont failed"), hr ); - } - } -} - - -void Direct3DDisplay::destroyFont() -{ - if( pFont ) { - pFont->Release(); - pFont = NULL; - } -} - - -void Direct3DDisplay::createSurface() -{ - if( !emulatedImage ) { - HRESULT hr = pDevice->CreateOffscreenPlainSurface( - width, height, - dpp.BackBufferFormat, - D3DPOOL_DEFAULT, - &emulatedImage, - NULL ); - if( FAILED( hr ) ) { - DXTRACE_ERR_MSGBOX( _T("createSurface failed"), hr ); - } - } -} - - -void Direct3DDisplay::destroySurface() -{ - if( emulatedImage ) { - emulatedImage->Release(); - emulatedImage = NULL; - } -} - - -void Direct3DDisplay::calculateDestRect() -{ - float scaleX = (float)dpp.BackBufferWidth / (float)width; - float scaleY = (float)dpp.BackBufferHeight / (float)height; - float min = (scaleX < scaleY) ? scaleX : scaleY; - if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) { - min = (float)theApp.fsMaxScale; - } - destRect.left = 0; - destRect.top = 0; - destRect.right = (LONG)(width * min); - destRect.bottom = (LONG)(height * min); - if( destRect.right != dpp.BackBufferWidth ) { - LONG diff = (dpp.BackBufferWidth - destRect.right) / 2; - destRect.left += diff; - destRect.right += diff; - } - if( destRect.bottom != dpp.BackBufferHeight ) { - LONG diff = (dpp.BackBufferHeight - destRect.bottom) / 2; - destRect.top += diff; - destRect.bottom += diff; - } -} - - -void Direct3DDisplay::setOption( const char *option, int value ) -{ - if( !_tcscmp( option, _T("vsync") ) ) { - theApp.vsync = true; - resetDevice(); - } - - if( !_tcscmp( option, _T("tripleBuffering") ) ) { - theApp.tripleBuffering = true; - resetDevice(); - } - - if( !_tcscmp( option, _T("d3dFilter") ) ) { - switch( value ) - { - case 0: //point - filter = D3DTEXF_POINT; - break; - case 1: //linear - filter = D3DTEXF_LINEAR; - break; - } - } - - if( !_tcscmp( option, _T("maxScale") ) ) { - calculateDestRect(); - } -} - - -bool Direct3DDisplay::resetDevice() -{ - if( !pDevice ) return false; - - HRESULT hr; - destroyFont(); - destroySurface(); + + +void Direct3DDisplay::cleanup() +{ + destroyFont(); + destroySurface(); + + if( pDevice ) { + pDevice->Release(); + pDevice = NULL; + } + + if( pD3D ) { + pD3D->Release(); + pD3D = NULL; + } +} + + +bool Direct3DDisplay::initialize() +{ + switch(theApp.cartridgeType) + { + case IMAGE_GBA: + theApp.sizeX = 240; + theApp.sizeY = 160; + break; + case IMAGE_GB: + if (gbBorderOn) + { + theApp.sizeX = 256; + theApp.sizeY = 224; + } + else + { + theApp.sizeX = 160; + theApp.sizeY = 144; + } + break; + } + + + switch(theApp.videoOption) + { + case VIDEO_1X: + theApp.surfaceSizeX = theApp.sizeX; + theApp.surfaceSizeY = theApp.sizeY; + break; + case VIDEO_2X: + theApp.surfaceSizeX = theApp.sizeX * 2; + theApp.surfaceSizeY = theApp.sizeY * 2; + break; + case VIDEO_3X: + theApp.surfaceSizeX = theApp.sizeX * 3; + theApp.surfaceSizeY = theApp.sizeY * 3; + break; + case VIDEO_4X: + theApp.surfaceSizeX = theApp.sizeX * 4; + theApp.surfaceSizeY = theApp.sizeY * 4; + break; + case VIDEO_320x240: + case VIDEO_640x480: + case VIDEO_800x600: + case VIDEO_1024x768: + case VIDEO_1280x1024: + case VIDEO_OTHER: + float scaleX = ((float)theApp.fsWidth / theApp.sizeX); + float scaleY = ((float)theApp.fsHeight / theApp.sizeY); + float min = (scaleX < scaleY) ? scaleX : scaleY; + if(theApp.fullScreenStretch) { + theApp.surfaceSizeX = theApp.fsWidth; + theApp.surfaceSizeY = theApp.fsHeight; + } else { + theApp.surfaceSizeX = (int)(theApp.sizeX * min); + theApp.surfaceSizeY = (int)(theApp.sizeY * min); + } + break; + } + + theApp.rect.left = 0; + theApp.rect.top = 0; + theApp.rect.right = theApp.sizeX; + theApp.rect.bottom = theApp.sizeY; + + theApp.dest.left = 0; + theApp.dest.top = 0; + theApp.dest.right = theApp.surfaceSizeX; + theApp.dest.bottom = theApp.surfaceSizeY; + + + DWORD style = WS_POPUP | WS_VISIBLE; + DWORD styleEx = 0; + + if(theApp.videoOption <= VIDEO_4X) { + style |= WS_OVERLAPPEDWINDOW; + } else { + styleEx = 0; + } + + if(theApp.videoOption <= VIDEO_4X) { + AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx); + } else { + AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx); + } + + int winSizeX = theApp.dest.right-theApp.dest.left; + int winSizeY = theApp.dest.bottom-theApp.dest.top; + + if(theApp.videoOption > VIDEO_4X) { + winSizeX = theApp.fsWidth; + winSizeY = theApp.fsHeight; + } + + int x = 0, y = 0; + + if(theApp.videoOption <= VIDEO_4X) { + x = theApp.windowPositionX; + y = theApp.windowPositionY; + } + + + // Create a window + MainWnd *pWnd = new MainWnd; + theApp.m_pMainWnd = pWnd; + + pWnd->CreateEx(styleEx, + theApp.wndClass, + _T("VisualBoyAdvance"), + style, + x,y,winSizeX,winSizeY, + NULL, + 0); + + if (!(HWND)*pWnd) { + DXTRACE_ERR_MSGBOX( _T("Error creating window"), 0 ); + return FALSE; + } + pWnd->DragAcceptFiles(TRUE); + theApp.updateMenuBar(); + theApp.adjustDestRect(); + + + // load Direct3D v9 + pD3D = Direct3DCreate9( D3D_SDK_VERSION ); + + if(pD3D == NULL) { + DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D object"), 0 ); + return FALSE; + } + pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode); + + theApp.mode320Available = FALSE; + theApp.mode640Available = FALSE; + theApp.mode800Available = FALSE; + theApp.mode1024Available = FALSE; + theApp.mode1280Available = FALSE; + + unsigned int nModes, i; + D3DDISPLAYMODE dm; + + nModes = pD3D->GetAdapterModeCount(theApp.fsAdapter, mode.Format); + for (i = 0; iEnumAdapterModes(theApp.fsAdapter, mode.Format, i, &dm) ) + { + if ( (dm.Width == 320) && (dm.Height == 240) ) + theApp.mode320Available = true; + if ( (dm.Width == 640) && (dm.Height == 480) ) + theApp.mode640Available = true; + if ( (dm.Width == 800) && (dm.Height == 600) ) + theApp.mode800Available = true; + if ( (dm.Width == 1024) && (dm.Height == 768) ) + theApp.mode1024Available = true; + if ( (dm.Width == 1280) && (dm.Height == 1024) ) + theApp.mode1280Available = true; + } + } + + + screenFormat = mode.Format; + + switch(mode.Format) { + case D3DFMT_R8G8B8: + systemColorDepth = 24; + systemRedShift = 19; + systemGreenShift = 11; + systemBlueShift = 3; + break; + case D3DFMT_X8R8G8B8: + systemColorDepth = 32; + systemRedShift = 19; + systemGreenShift = 11; + systemBlueShift = 3; + Init_2xSaI(32); + break; + case D3DFMT_R5G6B5: + systemColorDepth = 16; + systemRedShift = 11; + systemGreenShift = 6; + systemBlueShift = 0; + Init_2xSaI(565); + break; + case D3DFMT_X1R5G5B5: + systemColorDepth = 16; + systemRedShift = 10; + systemGreenShift = 5; + systemBlueShift = 0; + Init_2xSaI(555); + break; + default: + DXTRACE_ERR_MSGBOX( _T("Unsupport D3D format"), 0 ); + return false; + } + theApp.fsColorDepth = systemColorDepth; + utilUpdateSystemColorMaps(); + + +#ifdef MMX + if(!theApp.disableMMX) { + cpu_mmx = theApp.detectMMX(); + } else { + cpu_mmx = 0; + } +#endif + + + theApp.updateFilter(); + theApp.updateIFB(); + + + // create device setPresentationType(); - if( FAILED( hr = pDevice->Reset( &dpp ) ) ) { - //DXTRACE_ERR_MSGBOX( _T("pDevice->Reset failed"), hr ); - failed = true; - return false; - } - createFont(); - createSurface(); - failed = false; - return true; -} - - -IDisplay *newDirect3DDisplay() -{ - return new Direct3DDisplay(); -} + + HRESULT hret = pD3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pWnd->GetSafeHwnd(), + D3DCREATE_SOFTWARE_VERTEXPROCESSING, + &dpp, + &pDevice); + if( FAILED( hret ) ) { + DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D device"), hret ); + return false; + } + + createFont(); + createSurface(); + calculateDestRect(); + + setOption( _T("d3dFilter"), theApp.d3dFilter ); + + if(failed) return false; + + return TRUE; +} + + +void Direct3DDisplay::renderMenu() +{ + checkFullScreen(); + if(theApp.m_pMainWnd) { + theApp.m_pMainWnd->DrawMenuBar(); + } +} + + +void Direct3DDisplay::clear() +{ + if( pDevice ) { + pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00,0x00,0x00), 0.0f, 0 ); + } +} + + +void Direct3DDisplay::render() +{ + if( failed ) return; + if(!pDevice) return; + if( FAILED( pDevice->TestCooperativeLevel() ) ) return; + + clear(); + + pDevice->BeginScene(); + + // copy pix to emulatedImage and apply pixel filter if selected + HRESULT hr; + D3DLOCKED_RECT lr; + if( FAILED( hr = emulatedImage->LockRect( &lr, NULL, D3DLOCK_DISCARD ) ) ) { + DXTRACE_ERR_MSGBOX( _T("Can not lock back buffer"), hr ); + return; + } else { + if( !theApp.filterFunction ) { + copyImage( pix, lr.pBits, theApp.sizeX, theApp.sizeY, lr.Pitch, systemColorDepth ); + } else { + u32 pitch = theApp.filterWidth * (systemColorDepth>>3) + 4; + theApp.filterFunction( pix + pitch, + pitch, + (u8*)theApp.delta, + (u8*)lr.pBits, + lr.Pitch, + theApp.filterWidth, + theApp.filterHeight); + } + emulatedImage->UnlockRect(); + } + + // copy emulatedImage to pBackBuffer and scale with or without aspect ratio + LPDIRECT3DSURFACE9 pBackBuffer; + pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); + if( theApp.fullScreenStretch ) { + pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, NULL, filter ); + } else { + pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, &destRect, filter ); + } + pBackBuffer->Release(); + pBackBuffer = NULL; + + D3DCOLOR color; + RECT r; + r.left = 4; + r.right = dpp.BackBufferWidth - 4; + + if( theApp.screenMessage ) { + color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0xFF, 0x00, 0x00) : D3DCOLOR_ARGB(0xFF, 0xFF, 0x00, 0x00); + if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage && pFont ) { + r.top = dpp.BackBufferHeight - 20; + r.bottom = dpp.BackBufferHeight - 4; + pFont->DrawText( NULL, theApp.screenMessageBuffer, -1, &r, 0, color ); + } else { + theApp.screenMessage = false; + } + } + + if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) { + color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0x00, 0x00, 0xFF) : D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0xFF); + char buffer[30]; + if( theApp.showSpeed == 1 ) { + sprintf( buffer, "%3d%%", systemSpeed ); + } else { + sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames ); + } + + r.top = 4; + r.bottom = 20; + pFont->DrawText( NULL, buffer, -1, &r, 0, color ); + } + + pDevice->EndScene(); + + pDevice->Present( NULL, NULL, NULL, NULL ); + + return; +} + + +bool Direct3DDisplay::changeRenderSize( int w, int h ) +{ + if( (w != width) || (h != height) ) { + width = w; height = h; + if( pDevice ) { + destroySurface(); + createSurface(); + calculateDestRect(); + } + } + return true; +} + + +void Direct3DDisplay::resize( int w, int h ) +{ + if( (w != dpp.BackBufferWidth) || (h != dpp.BackBufferHeight) ) { + dpp.BackBufferWidth = (UINT)w; + dpp.BackBufferHeight = (UINT)h; + resetDevice(); + calculateDestRect(); + } + if(theApp.videoOption > VIDEO_4X) + resetDevice(); + +} + + +int Direct3DDisplay::selectFullScreenMode( GUID **pGUID ) +{ + return winVideoModeSelect(theApp.m_pMainWnd, pGUID); +} + + +void Direct3DDisplay::createFont() +{ + if( !pFont ) { + HRESULT hr = D3DXCreateFont( + pDevice, + 14, + 0, + FW_BOLD, + 1, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + DEFAULT_QUALITY, + DEFAULT_PITCH || FF_DONTCARE, + _T("Arial"), + &pFont ); + if( FAILED( hr ) ) { + DXTRACE_ERR_MSGBOX( _T("createFont failed"), hr ); + } + } +} + + +void Direct3DDisplay::destroyFont() +{ + if( pFont ) { + pFont->Release(); + pFont = NULL; + } +} + + +void Direct3DDisplay::createSurface() +{ + if( !emulatedImage ) { + HRESULT hr = pDevice->CreateOffscreenPlainSurface( + width, height, + dpp.BackBufferFormat, + D3DPOOL_DEFAULT, + &emulatedImage, + NULL ); + if( FAILED( hr ) ) { + DXTRACE_ERR_MSGBOX( _T("createSurface failed"), hr ); + } + } +} + + +void Direct3DDisplay::destroySurface() +{ + if( emulatedImage ) { + emulatedImage->Release(); + emulatedImage = NULL; + } +} + + +void Direct3DDisplay::calculateDestRect() +{ + float scaleX = (float)dpp.BackBufferWidth / (float)width; + float scaleY = (float)dpp.BackBufferHeight / (float)height; + float min = (scaleX < scaleY) ? scaleX : scaleY; + if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) { + min = (float)theApp.fsMaxScale; + } + destRect.left = 0; + destRect.top = 0; + destRect.right = (LONG)(width * min); + destRect.bottom = (LONG)(height * min); + if( destRect.right != dpp.BackBufferWidth ) { + LONG diff = (dpp.BackBufferWidth - destRect.right) / 2; + destRect.left += diff; + destRect.right += diff; + } + if( destRect.bottom != dpp.BackBufferHeight ) { + LONG diff = (dpp.BackBufferHeight - destRect.bottom) / 2; + destRect.top += diff; + destRect.bottom += diff; + } +} + + +void Direct3DDisplay::setOption( const char *option, int value ) +{ + if( !_tcscmp( option, _T("vsync") ) ) { + theApp.vsync = true; + resetDevice(); + } + + if( !_tcscmp( option, _T("tripleBuffering") ) ) { + theApp.tripleBuffering = true; + resetDevice(); + } + + if( !_tcscmp( option, _T("d3dFilter") ) ) { + switch( value ) + { + case 0: //point + filter = D3DTEXF_POINT; + break; + case 1: //linear + filter = D3DTEXF_LINEAR; + break; + } + } + + if( !_tcscmp( option, _T("maxScale") ) ) { + calculateDestRect(); + } +} + + +bool Direct3DDisplay::resetDevice() +{ + if( !pDevice ) return false; + + HRESULT hr; + destroyFont(); + destroySurface(); + setPresentationType(); + if (!theApp.menuToggle) + pDevice->SetDialogBoxMode( FALSE ); + + if( FAILED( hr = pDevice->Reset( &dpp ) ) ) { + //DXTRACE_ERR_MSGBOX( _T("pDevice->Reset failed"), hr ); + failed = true; + return false; + } + if (theApp.menuToggle) + pDevice->SetDialogBoxMode( TRUE ); + + createFont(); + createSurface(); + failed = false; + return true; +} + + +IDisplay *newDirect3DDisplay() +{ + return new Direct3DDisplay(); +} diff --git a/trunk/src/win32/DirectInput.cpp b/trunk/src/win32/DirectInput.cpp index 074559c2..109918de 100644 --- a/trunk/src/win32/DirectInput.cpp +++ b/trunk/src/win32/DirectInput.cpp @@ -1,598 +1,598 @@ - -/* VisualBoyAdvance S - GB & GBA emulator - Copyright (C) 2006 Spacy - - Original VBA Credits: - Copyright (C) 1999-2003 Forgotten - Copyright (C) 2004-2006 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "stdafx.h" -#include "VBA.h" -#include "Input.h" -#include "Reg.h" -#include "WinResUtil.h" - -#define DIRECTINPUT_VERSION 0x0800 -#include -#pragma comment(lib, "Dinput8") - - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -extern void directXMessage(const char *); -extern void winlog(const char *msg,...); - -#define POV_UP 1 -#define POV_DOWN 2 -#define POV_RIGHT 4 -#define POV_LEFT 8 - -class DirectInput : public Input { -public: - virtual void checkDevices(); - DirectInput(); - virtual ~DirectInput(); - - virtual bool initialize(); - virtual bool readDevices(); - virtual u32 readDevice(int which); - virtual CString getKeyName(LONG_PTR key); - virtual void checkKeys(); - virtual void checkMotionKeys(); - virtual void activate(); - virtual void loadSettings(); - virtual void saveSettings(); -}; - -struct deviceInfo { - LPDIRECTINPUTDEVICE8 device; - BOOL isPolled; - int nButtons; - int nAxes; - int nPovs; - BOOL first; - struct { - DWORD offset; - LONG center; - LONG negative; - LONG positive; - } axis[8]; - int needed; - union { - UCHAR data[256]; - DIJOYSTATE state; - }; -}; - -static deviceInfo *currentDevice = NULL; -static int numDevices = 1; -static deviceInfo *pDevices = NULL; -static LPDIRECTINPUT8 pDirectInput = NULL; -static int axisNumber = 0; - - - - -LONG_PTR defvalues[JOYPADS * KEYS_PER_PAD + MOTION_KEYS] = - { - DIK_LEFT, DIK_RIGHT, - DIK_UP, DIK_DOWN, - DIK_Z, DIK_X, - DIK_RETURN,DIK_BACK, - DIK_A, DIK_S, - DIK_SPACE, DIK_F12, - DIK_C, - 0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0, - DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2 -}; - - -void winReadKey(const char *name, KeyList& Keys) -{ - CString TxtKeyList = regQueryStringValue(name, ""); - int curPos= 0; - - CString resToken=TxtKeyList.Tokenize(",",curPos); - while (resToken != "") - { - Keys.AddTail(atoi(resToken)); - resToken= TxtKeyList.Tokenize(",",curPos); - }; -} - -void winReadKey(const char *name, int num, KeyList& Keys) -{ - char buffer[80]; - - sprintf(buffer, "Joy%d_%s", num, name); - winReadKey(buffer, Keys); -} - - -void winReadKeys() -{ - - for(int i = 0; i < JOYPADS; i++) { - winReadKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]); - winReadKey("Right", i, theApp.input->joypaddata[JOYPAD(i, KEY_RIGHT)]); - winReadKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]); - winReadKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]); - winReadKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]); - winReadKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]); - winReadKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]); - winReadKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]); - winReadKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]); - winReadKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]); - winReadKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]); - winReadKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]); - winReadKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]); - } - winReadKey("Motion_Left", theApp.input->joypaddata[MOTION(KEY_LEFT)]); - winReadKey("Motion_Right", theApp.input->joypaddata[MOTION(KEY_RIGHT)]); - winReadKey("Motion_Up", theApp.input->joypaddata[MOTION(KEY_UP)]); - winReadKey("Motion_Down", theApp.input->joypaddata[MOTION(KEY_DOWN)]); -} - -void winSaveKey(char *name, KeyList& value) -{ - CString txtKeys; - - POSITION p = value.GetHeadPosition(); - while(p!=NULL) - { - CString tmp; - tmp.Format("%d", value.GetNext(p)); - txtKeys+=tmp; - if (p!=NULL) - txtKeys+=","; - } - regSetStringValue(name, txtKeys); -} - -static void winSaveKey(char *name, int num, KeyList& value) -{ - char buffer[80]; - - sprintf(buffer, "Joy%d_%s", num, name); - winSaveKey(buffer, value); -} - -void winSaveKeys() -{ - for(int i = 0; i < JOYPADS; i++) { - winSaveKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]); - winSaveKey("Right", i, theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)]); - winSaveKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]); - winSaveKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]); - winSaveKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]); - winSaveKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]); - winSaveKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]); - winSaveKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]); - winSaveKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]); - winSaveKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]); - winSaveKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]); - winSaveKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]); - winSaveKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]); - } - regSetDwordValue("joyVersion", 1); - - winSaveKey("Motion_Left", - theApp.input->joypaddata[MOTION(KEY_LEFT)]); - winSaveKey("Motion_Right", - theApp.input->joypaddata[MOTION(KEY_RIGHT)]); - winSaveKey("Motion_Up", - theApp.input->joypaddata[MOTION(KEY_UP)]); - winSaveKey("Motion_Down", - theApp.input->joypaddata[MOTION(KEY_DOWN)]); -} - -static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, - VOID* pContext ) -{ - DIPROPRANGE diprg; - diprg.diph.dwSize = sizeof(DIPROPRANGE); - diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); - diprg.diph.dwHow = DIPH_BYOFFSET; - diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis - - diprg.lMin = -32768; - diprg.lMax = 32767; - // try to set the range - if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) { - // Get the range for the axis - if ( FAILED(currentDevice->device-> - GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) { - return DIENUM_STOP; - } - } - - DIPROPDWORD didz; - - didz.diph.dwSize = sizeof(didz); - didz.diph.dwHeaderSize = sizeof(DIPROPHEADER); - didz.diph.dwHow = DIPH_BYOFFSET; - didz.diph.dwObj = pdidoi->dwOfs; - - didz.dwData = 5000; - - currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph); - - LONG center = (diprg.lMin + diprg.lMax)/2; - LONG threshold = (diprg.lMax - center)/2; - - // only 8 axis supported - if (axisNumber < 8) { - currentDevice->axis[axisNumber].center = center; - currentDevice->axis[axisNumber].negative = center - threshold; - currentDevice->axis[axisNumber].positive = center + threshold; - currentDevice->axis[axisNumber].offset = pdidoi->dwOfs; - } - axisNumber++; - return DIENUM_CONTINUE; -} - -static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, - VOID* pContext ) -{ - return DIENUM_CONTINUE; -} - -static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst, - LPVOID lpvContext) -{ - ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo)); - - HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance, - &pDevices[numDevices].device, - NULL); - - if (hRet != DI_OK) - return DIENUM_STOP; - - DIDEVCAPS caps; - caps.dwSize=sizeof(DIDEVCAPS); - - hRet = pDevices[numDevices].device->GetCapabilities(&caps); - - if (hRet == DI_OK) { - if (caps.dwFlags & DIDC_POLLEDDATAFORMAT || - caps.dwFlags & DIDC_POLLEDDEVICE) - pDevices[numDevices].isPolled = TRUE; - - pDevices[numDevices].nButtons = caps.dwButtons; - pDevices[numDevices].nAxes = caps.dwAxes; - pDevices[numDevices].nPovs = caps.dwPOVs; - - for (int i = 0; i < 6; i++) { - pDevices[numDevices].axis[i].center = 0x8000; - pDevices[numDevices].axis[i].negative = 0x4000; - pDevices[numDevices].axis[i].positive = 0xc000; - } - } - - - numDevices++; - - - return DIENUM_CONTINUE; -} - -BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst, - LPVOID lpvContext) -{ - numDevices++; - - return DIENUM_CONTINUE; -} - -static int getPovState(DWORD value) -{ - int state = 0; - if (LOWORD(value) != 0xFFFF) { - if (value < 9000 || value > 27000) - state |= POV_UP; - if (value > 0 && value < 18000) - state |= POV_RIGHT; - if (value > 9000 && value < 27000) - state |= POV_DOWN; - if (value > 18000) - state |= POV_LEFT; - } - return state; -} - -static void checkKeys() -{ - LONG_PTR dev = 0; - int i; - - for(i = 0; i < (sizeof(theApp.input->joypaddata) / sizeof(theApp.input->joypaddata[0])); i++) - { - if (theApp.input->joypaddata[i].IsEmpty() && defvalues[i]) - theApp.input->joypaddata[i].AddTail(defvalues[i]); - POSITION p = theApp.input->joypaddata[i].GetHeadPosition(); - while(p!=NULL) - { - LONG_PTR k = theApp.input->joypaddata[i].GetNext(p); - if (k > 0 && DEVICEOF(k) < numDevices) - pDevices[DEVICEOF(k)].needed = true; - } - } -} - -#define KEYDOWN(buffer,key) (buffer[key] & 0x80) - -static bool readKeyboard() -{ - if (pDevices[0].needed) { - HRESULT hret = pDevices[0].device-> - GetDeviceState(256, - (LPVOID)pDevices[0].data); - - if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { - hret = pDevices[0].device->Acquire(); - if (hret != DI_OK) - return false; - hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data); - } - - return hret == DI_OK; - } - return true; -} - -static bool readJoystick(int joy) -{ - if (pDevices[joy].needed) { - if (pDevices[joy].isPolled) - ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); - - HRESULT hret = pDevices[joy].device-> - GetDeviceState(sizeof(DIJOYSTATE), - (LPVOID)&pDevices[joy].state); - - if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { - hret = pDevices[joy].device->Acquire(); - - if (hret == DI_OK) { - - if (pDevices[joy].isPolled) - ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); - - hret = pDevices[joy].device-> - GetDeviceState(sizeof(DIJOYSTATE), - (LPVOID)&pDevices[joy].state); - } - } - - return hret == DI_OK; - } - - return true; -} - -static void checkKeyboard() -{ - // mham fix. Patch #1378104 - UCHAR keystate[256]; - HRESULT hret = pDevices[0].device->Acquire(); - - if (pDevices[0].first) { - pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data); - pDevices[0].first = FALSE; - return; - } - - hret = pDevices[0].device-> - GetDeviceState(256, (LPVOID)keystate); - - if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { - return; - } - - if (hret == DI_OK) { - for (int i = 0; i < 256; i++) { - if (keystate[i] == pDevices[0].data[i]) continue; - if (KEYDOWN(keystate, i)) { - SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i); - break; - } - } - } - memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256); -} - -static void checkJoypads() -{ - DIDEVICEOBJECTINSTANCE di; - - ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); - - di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); - - int i =0; - - DIJOYSTATE joystick; - - for (i = 1; i < numDevices; i++) { - HRESULT hret = pDevices[i].device->Acquire(); - - - if (pDevices[i].isPolled) - ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll(); - - hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick); - - int j; - - if (pDevices[i].first) { - memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); - pDevices[i].first = FALSE; - continue; - } - - for (j = 0; j < pDevices[i].nButtons; j++) { - if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) - & joystick.rgbButtons[j]) & 0x80) { - HWND focus = GetFocus(); - - SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128); - } - } - - for (j = 0; j < pDevices[i].nAxes && j < 8; j++) { - LONG value = pDevices[i].axis[j].center; - LONG old = 0; - switch (pDevices[i].axis[j].offset) { - case DIJOFS_X: - value = joystick.lX; - old = pDevices[i].state.lX; - break; - case DIJOFS_Y: - value = joystick.lY; - old = pDevices[i].state.lY; - break; - case DIJOFS_Z: - value = joystick.lZ; - old = pDevices[i].state.lZ; - break; - case DIJOFS_RX: - value = joystick.lRx; - old = pDevices[i].state.lRx; - break; - case DIJOFS_RY: - value = joystick.lRy; - old = pDevices[i].state.lRy; - break; - case DIJOFS_RZ: - value = joystick.lRz; - old = pDevices[i].state.lRz; - break; - case DIJOFS_SLIDER(0): - value = joystick.rglSlider[0]; - old = pDevices[i].state.rglSlider[0]; - break; - case DIJOFS_SLIDER(1): - value = joystick.rglSlider[1]; - old = pDevices[i].state.rglSlider[1]; - break; - } - if (value != old) { - if (value < pDevices[i].axis[j].negative) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)); - else if (value > pDevices[i].axis[j].positive) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1); - } - } - - for (j = 0;j < 4 && j < pDevices[i].nPovs; j++) { - if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) { - int state = getPovState(joystick.rgdwPOV[j]); - - if (state & POV_UP) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20); - else if (state & POV_DOWN) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21); - else if (state & POV_RIGHT) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22); - else if (state & POV_LEFT) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23); - } - } - - memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); - } -} - -BOOL checkKey(LONG_PTR key) -{ - LONG_PTR dev = (key >> 8); - - LONG_PTR k = (key & 255); - - if (dev == 0) { - return KEYDOWN(pDevices[0].data,k); - } else { - if (k < 16) { - LONG_PTR axis = k >> 1; - LONG value = pDevices[dev].axis[axis].center; - switch (pDevices[dev].axis[axis].offset) { - case DIJOFS_X: - value = pDevices[dev].state.lX; - break; - case DIJOFS_Y: - value = pDevices[dev].state.lY; - break; - case DIJOFS_Z: - value = pDevices[dev].state.lZ; - break; - case DIJOFS_RX: - value = pDevices[dev].state.lRx; - break; - case DIJOFS_RY: - value = pDevices[dev].state.lRy; - break; - case DIJOFS_RZ: - value = pDevices[dev].state.lRz; - break; - case DIJOFS_SLIDER(0): - value = pDevices[dev].state.rglSlider[0]; - break; - case DIJOFS_SLIDER(1): - value = pDevices[dev].state.rglSlider[1]; - break; - } - - if (k & 1) - return value > pDevices[dev].axis[axis].positive; - return value < pDevices[dev].axis[axis].negative; - } else if (k < 48) { - LONG_PTR hat = (k >> 2) & 3; - int state = getPovState(pDevices[dev].state.rgdwPOV[hat]); - BOOL res = FALSE; - switch (k & 3) { - case 0: - res = state & POV_UP; - break; - case 1: - res = state & POV_DOWN; - break; - case 2: - res = state & POV_RIGHT; - break; - case 3: - res = state & POV_LEFT; - break; - } - return res; - } else if (k >= 128) { - return pDevices[dev].state.rgbButtons[k-128] & 0x80; - } - } - - return FALSE; -} + +/* VisualBoyAdvance S - GB & GBA emulator + Copyright (C) 2006 Spacy + + Original VBA Credits: + Copyright (C) 1999-2003 Forgotten + Copyright (C) 2004-2006 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "stdafx.h" +#include "VBA.h" +#include "Input.h" +#include "Reg.h" +#include "WinResUtil.h" + +#define DIRECTINPUT_VERSION 0x0800 +#include +#pragma comment(lib, "Dinput8") + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern void directXMessage(const char *); +extern void winlog(const char *msg,...); + +#define POV_UP 1 +#define POV_DOWN 2 +#define POV_RIGHT 4 +#define POV_LEFT 8 + +class DirectInput : public Input { +public: + virtual void checkDevices(); + DirectInput(); + virtual ~DirectInput(); + + virtual bool initialize(); + virtual bool readDevices(); + virtual u32 readDevice(int which); + virtual CString getKeyName(LONG_PTR key); + virtual void checkKeys(); + virtual void checkMotionKeys(); + virtual void activate(); + virtual void loadSettings(); + virtual void saveSettings(); +}; + +struct deviceInfo { + LPDIRECTINPUTDEVICE8 device; + BOOL isPolled; + int nButtons; + int nAxes; + int nPovs; + BOOL first; + struct { + DWORD offset; + LONG center; + LONG negative; + LONG positive; + } axis[8]; + int needed; + union { + UCHAR data[256]; + DIJOYSTATE state; + }; +}; + +static deviceInfo *currentDevice = NULL; +static int numDevices = 1; +static deviceInfo *pDevices = NULL; +static LPDIRECTINPUT8 pDirectInput = NULL; +static int axisNumber = 0; + + + + +LONG_PTR defvalues[JOYPADS * KEYS_PER_PAD + MOTION_KEYS] = + { + DIK_LEFT, DIK_RIGHT, + DIK_UP, DIK_DOWN, + DIK_Z, DIK_X, + DIK_RETURN,DIK_BACK, + DIK_A, DIK_S, + DIK_SPACE, DIK_F12, + DIK_C, + 0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0, + DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2 +}; + + +void winReadKey(const char *name, KeyList& Keys) +{ + CString TxtKeyList = regQueryStringValue(name, ""); + int curPos= 0; + + CString resToken=TxtKeyList.Tokenize(",",curPos); + while (resToken != "") + { + Keys.AddTail(atoi(resToken)); + resToken= TxtKeyList.Tokenize(",",curPos); + }; +} + +void winReadKey(const char *name, int num, KeyList& Keys) +{ + char buffer[80]; + + sprintf(buffer, "Joy%d_%s", num, name); + winReadKey(buffer, Keys); +} + + +void winReadKeys() +{ + + for(int i = 0; i < JOYPADS; i++) { + winReadKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]); + winReadKey("Right", i, theApp.input->joypaddata[JOYPAD(i, KEY_RIGHT)]); + winReadKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]); + winReadKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]); + winReadKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]); + winReadKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]); + winReadKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]); + winReadKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]); + winReadKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]); + winReadKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]); + winReadKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]); + winReadKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]); + winReadKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]); + } + winReadKey("Motion_Left", theApp.input->joypaddata[MOTION(KEY_LEFT)]); + winReadKey("Motion_Right", theApp.input->joypaddata[MOTION(KEY_RIGHT)]); + winReadKey("Motion_Up", theApp.input->joypaddata[MOTION(KEY_UP)]); + winReadKey("Motion_Down", theApp.input->joypaddata[MOTION(KEY_DOWN)]); +} + +void winSaveKey(char *name, KeyList& value) +{ + CString txtKeys; + + POSITION p = value.GetHeadPosition(); + while(p!=NULL) + { + CString tmp; + tmp.Format("%d", value.GetNext(p)); + txtKeys+=tmp; + if (p!=NULL) + txtKeys+=","; + } + regSetStringValue(name, txtKeys); +} + +static void winSaveKey(char *name, int num, KeyList& value) +{ + char buffer[80]; + + sprintf(buffer, "Joy%d_%s", num, name); + winSaveKey(buffer, value); +} + +void winSaveKeys() +{ + for(int i = 0; i < JOYPADS; i++) { + winSaveKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]); + winSaveKey("Right", i, theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)]); + winSaveKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]); + winSaveKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]); + winSaveKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]); + winSaveKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]); + winSaveKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]); + winSaveKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]); + winSaveKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]); + winSaveKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]); + winSaveKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]); + winSaveKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]); + winSaveKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]); + } + regSetDwordValue("joyVersion", 1); + + winSaveKey("Motion_Left", + theApp.input->joypaddata[MOTION(KEY_LEFT)]); + winSaveKey("Motion_Right", + theApp.input->joypaddata[MOTION(KEY_RIGHT)]); + winSaveKey("Motion_Up", + theApp.input->joypaddata[MOTION(KEY_UP)]); + winSaveKey("Motion_Down", + theApp.input->joypaddata[MOTION(KEY_DOWN)]); +} + +static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYOFFSET; + diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis + + diprg.lMin = -32768; + diprg.lMax = 32767; + // try to set the range + if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) { + // Get the range for the axis + if ( FAILED(currentDevice->device-> + GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) { + return DIENUM_STOP; + } + } + + DIPROPDWORD didz; + + didz.diph.dwSize = sizeof(didz); + didz.diph.dwHeaderSize = sizeof(DIPROPHEADER); + didz.diph.dwHow = DIPH_BYOFFSET; + didz.diph.dwObj = pdidoi->dwOfs; + + didz.dwData = 5000; + + currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph); + + LONG center = (diprg.lMin + diprg.lMax)/2; + LONG threshold = (diprg.lMax - center)/2; + + // only 8 axis supported + if (axisNumber < 8) { + currentDevice->axis[axisNumber].center = center; + currentDevice->axis[axisNumber].negative = center - threshold; + currentDevice->axis[axisNumber].positive = center + threshold; + currentDevice->axis[axisNumber].offset = pdidoi->dwOfs; + } + axisNumber++; + return DIENUM_CONTINUE; +} + +static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + return DIENUM_CONTINUE; +} + +static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst, + LPVOID lpvContext) +{ + ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo)); + + HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance, + &pDevices[numDevices].device, + NULL); + + if (hRet != DI_OK) + return DIENUM_STOP; + + DIDEVCAPS caps; + caps.dwSize=sizeof(DIDEVCAPS); + + hRet = pDevices[numDevices].device->GetCapabilities(&caps); + + if (hRet == DI_OK) { + if (caps.dwFlags & DIDC_POLLEDDATAFORMAT || + caps.dwFlags & DIDC_POLLEDDEVICE) + pDevices[numDevices].isPolled = TRUE; + + pDevices[numDevices].nButtons = caps.dwButtons; + pDevices[numDevices].nAxes = caps.dwAxes; + pDevices[numDevices].nPovs = caps.dwPOVs; + + for (int i = 0; i < 6; i++) { + pDevices[numDevices].axis[i].center = 0x8000; + pDevices[numDevices].axis[i].negative = 0x4000; + pDevices[numDevices].axis[i].positive = 0xc000; + } + } + + + numDevices++; + + + return DIENUM_CONTINUE; +} + +BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst, + LPVOID lpvContext) +{ + numDevices++; + + return DIENUM_CONTINUE; +} + +static int getPovState(DWORD value) +{ + int state = 0; + if (LOWORD(value) != 0xFFFF) { + if (value < 9000 || value > 27000) + state |= POV_UP; + if (value > 0 && value < 18000) + state |= POV_RIGHT; + if (value > 9000 && value < 27000) + state |= POV_DOWN; + if (value > 18000) + state |= POV_LEFT; + } + return state; +} + +static void checkKeys() +{ + LONG_PTR dev = 0; + int i; + + for(i = 0; i < (sizeof(theApp.input->joypaddata) / sizeof(theApp.input->joypaddata[0])); i++) + { + if (theApp.input->joypaddata[i].IsEmpty() && defvalues[i]) + theApp.input->joypaddata[i].AddTail(defvalues[i]); + POSITION p = theApp.input->joypaddata[i].GetHeadPosition(); + while(p!=NULL) + { + LONG_PTR k = theApp.input->joypaddata[i].GetNext(p); + if (k > 0 && DEVICEOF(k) < numDevices) + pDevices[DEVICEOF(k)].needed = true; + } + } +} + +#define KEYDOWN(buffer,key) (buffer[key] & 0x80) + +static bool readKeyboard() +{ + if (pDevices[0].needed) { + HRESULT hret = pDevices[0].device-> + GetDeviceState(256, + (LPVOID)pDevices[0].data); + + if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { + hret = pDevices[0].device->Acquire(); + if (hret != DI_OK) + return false; + hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data); + } + + return hret == DI_OK; + } + return true; +} + +static bool readJoystick(int joy) +{ + if (pDevices[joy].needed) { + if (pDevices[joy].isPolled) + ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); + + HRESULT hret = pDevices[joy].device-> + GetDeviceState(sizeof(DIJOYSTATE), + (LPVOID)&pDevices[joy].state); + + if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { + hret = pDevices[joy].device->Acquire(); + + if (hret == DI_OK) { + + if (pDevices[joy].isPolled) + ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); + + hret = pDevices[joy].device-> + GetDeviceState(sizeof(DIJOYSTATE), + (LPVOID)&pDevices[joy].state); + } + } + + return hret == DI_OK; + } + + return true; +} + +static void checkKeyboard() +{ + // mham fix. Patch #1378104 + UCHAR keystate[256]; + HRESULT hret = pDevices[0].device->Acquire(); + + if (pDevices[0].first) { + pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data); + pDevices[0].first = FALSE; + return; + } + + hret = pDevices[0].device-> + GetDeviceState(256, (LPVOID)keystate); + + if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { + return; + } + + if (hret == DI_OK) { + for (int i = 0; i < 256; i++) { + if (keystate[i] == pDevices[0].data[i]) continue; + if (KEYDOWN(keystate, i)) { + SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i); + break; + } + } + } + memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256); +} + +static void checkJoypads() +{ + DIDEVICEOBJECTINSTANCE di; + + ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); + + di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); + + int i =0; + + DIJOYSTATE joystick; + + for (i = 1; i < numDevices; i++) { + HRESULT hret = pDevices[i].device->Acquire(); + + + if (pDevices[i].isPolled) + ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll(); + + hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick); + + int j; + + if (pDevices[i].first) { + memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); + pDevices[i].first = FALSE; + continue; + } + + for (j = 0; j < pDevices[i].nButtons; j++) { + if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) + & joystick.rgbButtons[j]) & 0x80) { + HWND focus = GetFocus(); + + SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128); + } + } + + for (j = 0; j < pDevices[i].nAxes && j < 8; j++) { + LONG value = pDevices[i].axis[j].center; + LONG old = 0; + switch (pDevices[i].axis[j].offset) { + case DIJOFS_X: + value = joystick.lX; + old = pDevices[i].state.lX; + break; + case DIJOFS_Y: + value = joystick.lY; + old = pDevices[i].state.lY; + break; + case DIJOFS_Z: + value = joystick.lZ; + old = pDevices[i].state.lZ; + break; + case DIJOFS_RX: + value = joystick.lRx; + old = pDevices[i].state.lRx; + break; + case DIJOFS_RY: + value = joystick.lRy; + old = pDevices[i].state.lRy; + break; + case DIJOFS_RZ: + value = joystick.lRz; + old = pDevices[i].state.lRz; + break; + case DIJOFS_SLIDER(0): + value = joystick.rglSlider[0]; + old = pDevices[i].state.rglSlider[0]; + break; + case DIJOFS_SLIDER(1): + value = joystick.rglSlider[1]; + old = pDevices[i].state.rglSlider[1]; + break; + } + if (value != old) { + if (value < pDevices[i].axis[j].negative) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)); + else if (value > pDevices[i].axis[j].positive) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1); + } + } + + for (j = 0;j < 4 && j < pDevices[i].nPovs; j++) { + if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) { + int state = getPovState(joystick.rgdwPOV[j]); + + if (state & POV_UP) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20); + else if (state & POV_DOWN) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21); + else if (state & POV_RIGHT) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22); + else if (state & POV_LEFT) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23); + } + } + + memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); + } +} + +BOOL checkKey(LONG_PTR key) +{ + LONG_PTR dev = (key >> 8); + + LONG_PTR k = (key & 255); + + if (dev == 0) { + return KEYDOWN(pDevices[0].data,k); + } else { + if (k < 16) { + LONG_PTR axis = k >> 1; + LONG value = pDevices[dev].axis[axis].center; + switch (pDevices[dev].axis[axis].offset) { + case DIJOFS_X: + value = pDevices[dev].state.lX; + break; + case DIJOFS_Y: + value = pDevices[dev].state.lY; + break; + case DIJOFS_Z: + value = pDevices[dev].state.lZ; + break; + case DIJOFS_RX: + value = pDevices[dev].state.lRx; + break; + case DIJOFS_RY: + value = pDevices[dev].state.lRy; + break; + case DIJOFS_RZ: + value = pDevices[dev].state.lRz; + break; + case DIJOFS_SLIDER(0): + value = pDevices[dev].state.rglSlider[0]; + break; + case DIJOFS_SLIDER(1): + value = pDevices[dev].state.rglSlider[1]; + break; + } + + if (k & 1) + return value > pDevices[dev].axis[axis].positive; + return value < pDevices[dev].axis[axis].negative; + } else if (k < 48) { + LONG_PTR hat = (k >> 2) & 3; + int state = getPovState(pDevices[dev].state.rgdwPOV[hat]); + BOOL res = FALSE; + switch (k & 3) { + case 0: + res = state & POV_UP; + break; + case 1: + res = state & POV_DOWN; + break; + case 2: + res = state & POV_RIGHT; + break; + case 3: + res = state & POV_LEFT; + break; + } + return res; + } else if (k >= 128) { + return pDevices[dev].state.rgbButtons[k-128] & 0x80; + } + } + + return FALSE; +} BOOL checkKey(KeyList &k) { @@ -603,337 +603,337 @@ BOOL checkKey(KeyList &k) return TRUE; } return FALSE; -} - -DirectInput::DirectInput() -{} - -DirectInput::~DirectInput() -{ - saveSettings(); - if (pDirectInput != NULL) { - if (pDevices) { - for (int i = 0; i < numDevices ; i++) { - if (pDevices[i].device) { - pDevices[i].device->Unacquire(); - pDevices[i].device->Release(); - pDevices[i].device = NULL; - } - } - free(pDevices); - pDevices = NULL; - } - - pDirectInput->Release(); - pDirectInput = NULL; - } -} - - -bool DirectInput::initialize() -{ - - HRESULT hr; - - hr = DirectInput8Create( - AfxGetInstanceHandle(), - DIRECTINPUT_VERSION, - IID_IDirectInput8, - (LPVOID*)&pDirectInput, - NULL ); - - if ( hr != DI_OK ) { - return false; - } - - - - - hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, - DIEnumDevicesCallback2, - NULL, - DIEDFL_ATTACHEDONLY); - - - - pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo)); - - hr = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL); - pDevices[0].isPolled = false; - pDevices[0].needed = true; - pDevices[0].first = true; - - if (hr != DI_OK) { - return false; - } - - - numDevices = 1; - - hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, - DIEnumDevicesCallback, - NULL, - DIEDFL_ATTACHEDONLY); - - - if (hr != DI_OK) { - return false; - } - - hr = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard); - - if (hr != DI_OK) { - return false; - } - - int i; - for (i = 1; i < numDevices; i++) { - pDevices[i].device->SetDataFormat(&c_dfDIJoystick); - pDevices[i].needed = false; - pDevices[i].first = true; - currentDevice = &pDevices[i]; - axisNumber = 0; - currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS); - currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV); - - - currentDevice = NULL; - } - - for (i = 0; i < numDevices; i++) - pDevices[i].device->Acquire(); - - return true; -} - -bool DirectInput::readDevices() -{ - bool ok = true; - for (int i = 0; i < numDevices; i++) { - if (pDevices[i].needed) { - if (i) { - ok = readJoystick(i); - } else - ok = readKeyboard(); - } - } - return ok; -} - -u32 DirectInput::readDevice(int which) -{ - u32 res = 0; - int i = theApp.joypadDefault; - if(which >= 0 && which <= 3) - i = which; - - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)])) - res |= 1; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)])) - res |= 2; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)])) - res |= 4; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)])) - res |= 8; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)])) - res |= 16; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)])) - res |= 32; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_UP)])) - res |= 64; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)])) - res |= 128; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)])) - res |= 256; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)])) - res |= 512; - - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)])) - res |= 4096; - - if(theApp.autoFire) { - res &= (~theApp.autoFire); - if(theApp.autoFireToggle) - res |= theApp.autoFire; - theApp.autoFireToggle = !theApp.autoFireToggle; - } - - // disallow L+R or U+D of being pressed at the same time - if((res & 48) == 48) - res &= ~16; - if((res & 192) == 192) - res &= ~128; - - if(theApp.movieRecording) { - if(i == theApp.joypadDefault) { - if(res != theApp.movieLastJoypad) { - fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile); - fwrite(&res, 1, sizeof(res), theApp.movieFile); - theApp.movieLastJoypad = res; - } - } - } - if(theApp.moviePlaying) { - if(theApp.movieFrame == theApp.moviePlayFrame) { - theApp.movieLastJoypad = theApp.movieNextJoypad; - theApp.movieReadNext(); - } - res = theApp.movieLastJoypad; - } - // we don't record speed up or screen capture buttons - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]) || theApp.speedupToggle) - res |= 1024; - if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)])) - res |= 2048; - - return res; -} - -CString DirectInput::getKeyName(LONG_PTR key) -{ - LONG_PTR d = (key >> 8); - LONG_PTR k = key & 255; - - DIDEVICEOBJECTINSTANCE di; - - ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); - - di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); - - CString winBuffer = winResLoadString(IDS_ERROR); - - if (d == 0) { - pDevices[0].device->GetObjectInfo( &di, (DWORD)key, DIPH_BYOFFSET ); - winBuffer = di.tszName; - } else { - if (k < 16) { - if (k < 4) { - switch (k) { - case 0: - winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d); - break; - case 1: - winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d); - break; - case 2: - winBuffer.Format(winResLoadString(IDS_JOY_UP), d); - break; - case 3: - winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d); - break; - } - } else { - pDevices[d].device->GetObjectInfo(&di, - pDevices[d].axis[k>>1].offset, - DIPH_BYOFFSET); - if (k & 1) - winBuffer.Format("Joy %d %s +", d, di.tszName); - else - winBuffer.Format("Joy %d %s -", d, di.tszName); - } - } else if (k < 48) { - LONG_PTR hat = (k >> 2) & 3; - pDevices[d].device->GetObjectInfo(&di, - (DWORD)DIJOFS_POV(hat), - DIPH_BYOFFSET); - char *dir = "up"; - LONG_PTR dd = k & 3; - if (dd == 1) - dir = "down"; - else if (dd == 2) - dir = "right"; - else if (dd == 3) - dir = "left"; - winBuffer.Format("Joy %d %s %s", d, di.tszName, dir); - } else { - pDevices[d].device->GetObjectInfo(&di, - (DWORD)DIJOFS_BUTTON(k-128), - DIPH_BYOFFSET); - winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName); - } - } - - return winBuffer; -} - -void DirectInput::checkKeys() -{ - ::checkKeys(); -} - -void DirectInput::checkMotionKeys() -{ - if(checkKey(theApp.input->joypaddata[MOTION(KEY_LEFT)])) { - theApp.sensorX += 3; - if(theApp.sensorX > 2197) - theApp.sensorX = 2197; - if(theApp.sensorX < 2047) - theApp.sensorX = 2057; - } else if(checkKey(theApp.input->joypaddata[MOTION(KEY_RIGHT)])) { - theApp.sensorX -= 3; - if(theApp.sensorX < 1897) - theApp.sensorX = 1897; - if(theApp.sensorX > 2047) - theApp.sensorX = 2037; - } else if(theApp.sensorX > 2047) { - theApp.sensorX -= 2; - if(theApp.sensorX < 2047) - theApp.sensorX = 2047; - } else { - theApp.sensorX += 2; - if(theApp.sensorX > 2047) - theApp.sensorX = 2047; - } - - if(checkKey(theApp.input->joypaddata[MOTION(KEY_UP)])) { - theApp.sensorY += 3; - if(theApp.sensorY > 2197) - theApp.sensorY = 2197; - if(theApp.sensorY < 2047) - theApp.sensorY = 2057; - } else if(checkKey(theApp.input->joypaddata[MOTION(KEY_DOWN)])) { - theApp.sensorY -= 3; - if(theApp.sensorY < 1897) - theApp.sensorY = 1897; - if(theApp.sensorY > 2047) - theApp.sensorY = 2037; - } else if(theApp.sensorY > 2047) { - theApp.sensorY -= 2; - if(theApp.sensorY < 2047) - theApp.sensorY = 2047; - } else { - theApp.sensorY += 2; - if(theApp.sensorY > 2047) - theApp.sensorY = 2047; - } -} - -Input *newDirectInput() -{ - return new DirectInput; -} - - -void DirectInput::checkDevices() -{ - checkJoypads(); - checkKeyboard(); -} - -void DirectInput::activate() -{ - for (int i = 0; i < numDevices; i++) { - if (pDevices != NULL && pDevices[i].device != NULL) - pDevices[i].device->Acquire(); - } -} - -void DirectInput::loadSettings() -{ - winReadKeys(); -} - -void DirectInput::saveSettings() -{ - winSaveKeys(); -} +} + +DirectInput::DirectInput() +{} + +DirectInput::~DirectInput() +{ + saveSettings(); + if (pDirectInput != NULL) { + if (pDevices) { + for (int i = 0; i < numDevices ; i++) { + if (pDevices[i].device) { + pDevices[i].device->Unacquire(); + pDevices[i].device->Release(); + pDevices[i].device = NULL; + } + } + free(pDevices); + pDevices = NULL; + } + + pDirectInput->Release(); + pDirectInput = NULL; + } +} + + +bool DirectInput::initialize() +{ + + HRESULT hr; + + hr = DirectInput8Create( + AfxGetInstanceHandle(), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (LPVOID*)&pDirectInput, + NULL ); + + if ( hr != DI_OK ) { + return false; + } + + + + + hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, + DIEnumDevicesCallback2, + NULL, + DIEDFL_ATTACHEDONLY); + + + + pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo)); + + hr = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL); + pDevices[0].isPolled = false; + pDevices[0].needed = true; + pDevices[0].first = true; + + if (hr != DI_OK) { + return false; + } + + + numDevices = 1; + + hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, + DIEnumDevicesCallback, + NULL, + DIEDFL_ATTACHEDONLY); + + + if (hr != DI_OK) { + return false; + } + + hr = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard); + + if (hr != DI_OK) { + return false; + } + + int i; + for (i = 1; i < numDevices; i++) { + pDevices[i].device->SetDataFormat(&c_dfDIJoystick); + pDevices[i].needed = false; + pDevices[i].first = true; + currentDevice = &pDevices[i]; + axisNumber = 0; + currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS); + currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV); + + + currentDevice = NULL; + } + + for (i = 0; i < numDevices; i++) + pDevices[i].device->Acquire(); + + return true; +} + +bool DirectInput::readDevices() +{ + bool ok = true; + for (int i = 0; i < numDevices; i++) { + if (pDevices[i].needed) { + if (i) { + ok = readJoystick(i); + } else + ok = readKeyboard(); + } + } + return ok; +} + +u32 DirectInput::readDevice(int which) +{ + u32 res = 0; + int i = theApp.joypadDefault; + if(which >= 0 && which <= 3) + i = which; + + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)])) + res |= 1; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)])) + res |= 2; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)])) + res |= 4; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)])) + res |= 8; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)])) + res |= 16; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)])) + res |= 32; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_UP)])) + res |= 64; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)])) + res |= 128; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)])) + res |= 256; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)])) + res |= 512; + + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)])) + res |= 4096; + + if(theApp.autoFire) { + res &= (~theApp.autoFire); + if(theApp.autoFireToggle) + res |= theApp.autoFire; + theApp.autoFireToggle = !theApp.autoFireToggle; + } + + // disallow L+R or U+D of being pressed at the same time + if((res & 48) == 48) + res &= ~16; + if((res & 192) == 192) + res &= ~128; + + if(theApp.movieRecording) { + if(i == theApp.joypadDefault) { + if(res != theApp.movieLastJoypad) { + fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile); + fwrite(&res, 1, sizeof(res), theApp.movieFile); + theApp.movieLastJoypad = res; + } + } + } + if(theApp.moviePlaying) { + if(theApp.movieFrame == theApp.moviePlayFrame) { + theApp.movieLastJoypad = theApp.movieNextJoypad; + theApp.movieReadNext(); + } + res = theApp.movieLastJoypad; + } + // we don't record speed up or screen capture buttons + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]) || theApp.speedupToggle) + res |= 1024; + if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)])) + res |= 2048; + + return res; +} + +CString DirectInput::getKeyName(LONG_PTR key) +{ + LONG_PTR d = (key >> 8); + LONG_PTR k = key & 255; + + DIDEVICEOBJECTINSTANCE di; + + ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); + + di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); + + CString winBuffer = winResLoadString(IDS_ERROR); + + if (d == 0) { + pDevices[0].device->GetObjectInfo( &di, (DWORD)key, DIPH_BYOFFSET ); + winBuffer = di.tszName; + } else { + if (k < 16) { + if (k < 4) { + switch (k) { + case 0: + winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d); + break; + case 1: + winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d); + break; + case 2: + winBuffer.Format(winResLoadString(IDS_JOY_UP), d); + break; + case 3: + winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d); + break; + } + } else { + pDevices[d].device->GetObjectInfo(&di, + pDevices[d].axis[k>>1].offset, + DIPH_BYOFFSET); + if (k & 1) + winBuffer.Format("Joy %d %s +", d, di.tszName); + else + winBuffer.Format("Joy %d %s -", d, di.tszName); + } + } else if (k < 48) { + LONG_PTR hat = (k >> 2) & 3; + pDevices[d].device->GetObjectInfo(&di, + (DWORD)DIJOFS_POV(hat), + DIPH_BYOFFSET); + char *dir = "up"; + LONG_PTR dd = k & 3; + if (dd == 1) + dir = "down"; + else if (dd == 2) + dir = "right"; + else if (dd == 3) + dir = "left"; + winBuffer.Format("Joy %d %s %s", d, di.tszName, dir); + } else { + pDevices[d].device->GetObjectInfo(&di, + (DWORD)DIJOFS_BUTTON(k-128), + DIPH_BYOFFSET); + winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName); + } + } + + return winBuffer; +} + +void DirectInput::checkKeys() +{ + ::checkKeys(); +} + +void DirectInput::checkMotionKeys() +{ + if(checkKey(theApp.input->joypaddata[MOTION(KEY_LEFT)])) { + theApp.sensorX += 3; + if(theApp.sensorX > 2197) + theApp.sensorX = 2197; + if(theApp.sensorX < 2047) + theApp.sensorX = 2057; + } else if(checkKey(theApp.input->joypaddata[MOTION(KEY_RIGHT)])) { + theApp.sensorX -= 3; + if(theApp.sensorX < 1897) + theApp.sensorX = 1897; + if(theApp.sensorX > 2047) + theApp.sensorX = 2037; + } else if(theApp.sensorX > 2047) { + theApp.sensorX -= 2; + if(theApp.sensorX < 2047) + theApp.sensorX = 2047; + } else { + theApp.sensorX += 2; + if(theApp.sensorX > 2047) + theApp.sensorX = 2047; + } + + if(checkKey(theApp.input->joypaddata[MOTION(KEY_UP)])) { + theApp.sensorY += 3; + if(theApp.sensorY > 2197) + theApp.sensorY = 2197; + if(theApp.sensorY < 2047) + theApp.sensorY = 2057; + } else if(checkKey(theApp.input->joypaddata[MOTION(KEY_DOWN)])) { + theApp.sensorY -= 3; + if(theApp.sensorY < 1897) + theApp.sensorY = 1897; + if(theApp.sensorY > 2047) + theApp.sensorY = 2037; + } else if(theApp.sensorY > 2047) { + theApp.sensorY -= 2; + if(theApp.sensorY < 2047) + theApp.sensorY = 2047; + } else { + theApp.sensorY += 2; + if(theApp.sensorY > 2047) + theApp.sensorY = 2047; + } +} + +Input *newDirectInput() +{ + return new DirectInput; +} + + +void DirectInput::checkDevices() +{ + checkJoypads(); + checkKeyboard(); +} + +void DirectInput::activate() +{ + for (int i = 0; i < numDevices; i++) { + if (pDevices != NULL && pDevices[i].device != NULL) + pDevices[i].device->Acquire(); + } +} + +void DirectInput::loadSettings() +{ + winReadKeys(); +} + +void DirectInput::saveSettings() +{ + winSaveKeys(); +}