2010-09-25 15:46:12 +00:00
/***********************************************************************************
Snes9x - Portable Super Nintendo Entertainment System ( TM ) emulator .
( c ) Copyright 1996 - 2002 Gary Henderson ( gary . henderson @ ntlworld . com ) ,
Jerremy Koot ( jkoot @ snes9x . com )
( c ) Copyright 2002 - 2004 Matthew Kendora
( c ) Copyright 2002 - 2005 Peter Bortas ( peter @ bortas . org )
( c ) Copyright 2004 - 2005 Joel Yliluoma ( http : //iki.fi/bisqwit/)
( c ) Copyright 2001 - 2006 John Weidman ( jweidman @ slip . net )
( c ) Copyright 2002 - 2006 funkyass ( funkyass @ spam . shaw . ca ) ,
Kris Bleakley ( codeviolation @ hotmail . com )
( c ) Copyright 2002 - 2010 Brad Jorsch ( anomie @ users . sourceforge . net ) ,
Nach ( n - a - c - h @ users . sourceforge . net ) ,
2011-04-11 19:51:20 +00:00
( c ) Copyright 2002 - 2011 zones ( kasumitokoduck @ yahoo . com )
2010-09-25 15:46:12 +00:00
( c ) Copyright 2006 - 2007 nitsuja
2018-05-25 20:43:57 +00:00
( c ) Copyright 2009 - 2018 BearOso ,
2010-09-25 15:46:12 +00:00
OV2
2017-11-17 22:00:58 +00:00
( c ) Copyright 2017 qwertymodo
( c ) Copyright 2011 - 2017 Hans - Kristian Arntzen ,
2016-10-15 16:31:26 +00:00
Daniel De Matteis
( Under no circumstances will commercial rights be given )
2010-09-25 15:46:12 +00:00
BS - X C emulator code
( c ) Copyright 2005 - 2006 Dreamer Nom ,
zones
C4 x86 assembler and some C emulation code
( c ) Copyright 2000 - 2003 _Demo_ ( _demo_ @ zsnes . com ) ,
Nach ,
zsKnight ( zsknight @ zsnes . com )
C4 C + + code
( c ) Copyright 2003 - 2006 Brad Jorsch ,
Nach
DSP - 1 emulator code
( c ) Copyright 1998 - 2006 _Demo_ ,
Andreas Naive ( andreasnaive @ gmail . com ) ,
Gary Henderson ,
Ivar ( ivar @ snes9x . com ) ,
John Weidman ,
Kris Bleakley ,
Matthew Kendora ,
Nach ,
neviksti ( neviksti @ hotmail . com )
DSP - 2 emulator code
( c ) Copyright 2003 John Weidman ,
Kris Bleakley ,
Lord Nightmare ( lord_nightmare @ users . sourceforge . net ) ,
Matthew Kendora ,
neviksti
DSP - 3 emulator code
( c ) Copyright 2003 - 2006 John Weidman ,
Kris Bleakley ,
Lancer ,
z80 gaiden
DSP - 4 emulator code
( c ) Copyright 2004 - 2006 Dreamer Nom ,
John Weidman ,
Kris Bleakley ,
Nach ,
z80 gaiden
OBC1 emulator code
( c ) Copyright 2001 - 2004 zsKnight ,
pagefault ( pagefault @ zsnes . com ) ,
Kris Bleakley
Ported from x86 assembler to C by sanmaiwashi
SPC7110 and RTC C + + emulator code used in 1.39 - 1.51
( c ) Copyright 2002 Matthew Kendora with research by
zsKnight ,
John Weidman ,
Dark Force
SPC7110 and RTC C + + emulator code used in 1.52 +
( c ) Copyright 2009 byuu ,
neviksti
S - DD1 C emulator code
( c ) Copyright 2003 Brad Jorsch with research by
Andreas Naive ,
John Weidman
S - RTC C emulator code
( c ) Copyright 2001 - 2006 byuu ,
John Weidman
ST010 C + + emulator code
( c ) Copyright 2003 Feather ,
John Weidman ,
Kris Bleakley ,
Matthew Kendora
Super FX x86 assembler emulator code
( c ) Copyright 1998 - 2003 _Demo_ ,
pagefault ,
zsKnight
Super FX C emulator code
( c ) Copyright 1997 - 1999 Ivar ,
Gary Henderson ,
John Weidman
Sound emulator code used in 1.5 - 1.51
( c ) Copyright 1998 - 2003 Brad Martin
( c ) Copyright 1998 - 2006 Charles Bilyue '
Sound emulator code used in 1.52 +
( c ) Copyright 2004 - 2007 Shay Green ( gblargg @ gmail . com )
2016-10-07 17:47:07 +00:00
S - SMP emulator code used in 1.54 +
( c ) Copyright 2016 byuu
2010-09-25 15:46:12 +00:00
SH assembler code partly based on x86 assembler code
( c ) Copyright 2002 - 2004 Marcus Comstedt ( marcus @ mc . pp . se )
2 xSaI filter
( c ) Copyright 1999 - 2001 Derek Liauw Kie Fa
HQ2x , HQ3x , HQ4x filters
( c ) Copyright 2003 Maxim Stepin ( maxim @ hiend3d . com )
NTSC filter
( c ) Copyright 2006 - 2007 Shay Green
GTK + GUI code
2018-05-25 20:43:57 +00:00
( c ) Copyright 2004 - 2018 BearOso
2010-09-25 15:46:12 +00:00
Win32 GUI code
( c ) Copyright 2003 - 2006 blip ,
funkyass ,
Matthew Kendora ,
Nach ,
nitsuja
2018-05-25 20:43:57 +00:00
( c ) Copyright 2009 - 2018 OV2
2010-09-25 15:46:12 +00:00
Mac OS GUI code
( c ) Copyright 1998 - 2001 John Stiles
2011-04-11 19:51:20 +00:00
( c ) Copyright 2001 - 2011 zones
2010-09-25 15:46:12 +00:00
2016-10-15 16:31:26 +00:00
Libretro port
2017-11-17 22:00:58 +00:00
( c ) Copyright 2011 - 2017 Hans - Kristian Arntzen ,
2016-10-15 16:31:26 +00:00
Daniel De Matteis
( Under no circumstances will commercial rights be given )
2010-09-25 15:46:12 +00:00
Specific ports contains the works of other authors . See headers in
individual files .
Snes9x homepage : http : //www.snes9x.com/
Permission to use , copy , modify and / or distribute Snes9x in both binary
and source form , for non - commercial purposes , is hereby granted without
fee , providing that this license information and copyright notice appear
with all copies and any derived work .
This software is provided ' as - is ' , without any express or implied
warranty . In no event shall the authors be held liable for any damages
arising from the use of this software or it ' s derivatives .
Snes9x is freeware for PERSONAL USE only . Commercial users should
seek permission of the copyright holders first . Commercial use includes ,
but is not limited to , charging money for Snes9x or software derived from
Snes9x , including Snes9x or derivatives in commercial game bundles , and / or
using Snes9x as a promotion for your commercial product .
The copyright holders request that bug fixes and improvements to the code
should be forwarded to them so everyone can benefit from the modifications
in future versions .
Super NES and Super Nintendo Entertainment System are trademarks of
Nintendo Co . , Limited and its subsidiary companies .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# pragma comment( lib, "d3d9" )
# include "cdirect3d.h"
# include "win32_display.h"
2010-09-25 17:35:19 +00:00
# include "../snes9x.h"
2010-09-25 15:46:12 +00:00
# include "../gfx.h"
2010-09-25 17:35:19 +00:00
# include "../display.h"
2010-09-25 15:46:12 +00:00
# include "wsnes9x.h"
2018-08-06 23:16:41 +00:00
# include "dxerr.h"
2010-09-25 15:46:12 +00:00
# include <commctrl.h>
2012-10-18 13:44:42 +00:00
# include "CXML.h"
2010-09-25 15:46:12 +00:00
2016-10-07 21:00:26 +00:00
2010-09-25 15:46:12 +00:00
# include "../filter/hq2x.h"
# include "../filter/2xsai.h"
# ifndef max
# define max(a, b) (((a) > (b)) ? (a) : (b))
# endif
# ifndef min
# define min(a, b) (((a) < (b)) ? (a) : (b))
# endif
2011-12-10 14:21:37 +00:00
const D3DVERTEXELEMENT9 CDirect3D : : vertexElems [ 4 ] = {
{ 0 , 0 , D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_POSITION , 0 } ,
{ 0 , 12 , D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_TEXCOORD , 0 } ,
{ 0 , 20 , D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_TEXCOORD , 1 } ,
D3DDECL_END ( )
} ;
2010-09-25 15:46:12 +00:00
/* CDirect3D::CDirect3D()
sets default values for the variables
*/
CDirect3D : : CDirect3D ( )
{
init_done = false ;
pD3D = NULL ;
pDevice = NULL ;
drawSurface = NULL ;
vertexBuffer = NULL ;
afterRenderWidth = 0 ;
afterRenderHeight = 0 ;
quadTextureSize = 0 ;
fullscreen = false ;
2010-09-25 17:35:19 +00:00
filterScale = 1 ;
for ( int i = 0 ; i < MAX_SHADER_TEXTURES ; i + + ) {
rubyLUT [ i ] = NULL ;
}
2011-02-24 00:26:42 +00:00
shader_type = D3D_SHADER_NONE ;
2010-09-25 17:35:19 +00:00
shaderTimer = 1.0f ;
shaderTimeStart = 0 ;
shaderTimeElapsed = 0 ;
2011-05-11 19:39:06 +00:00
frameCount = 0 ;
2011-02-24 00:26:42 +00:00
cgContext = NULL ;
2011-03-20 22:21:12 +00:00
cgAvailable = false ;
2011-12-10 14:21:37 +00:00
cgShader = NULL ;
vertexDeclaration = NULL ;
2010-09-25 15:46:12 +00:00
}
/* CDirect3D::~CDirect3D()
releases allocated objects
*/
CDirect3D : : ~ CDirect3D ( )
{
DeInitialize ( ) ;
}
/* CDirect3D::Initialize
Initializes Direct3D ( always in window mode )
IN :
hWnd - the HWND of the window in which we render / the focus window for fullscreen
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : Initialize ( HWND hWnd )
{
if ( init_done )
return true ;
pD3D = Direct3DCreate9 ( D3D_SDK_VERSION ) ;
if ( pD3D = = NULL ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating initial D3D9 object " ) , 0 ) ;
2010-09-25 15:46:12 +00:00
return false ;
}
2012-01-23 17:12:47 +00:00
memset ( & dPresentParams , 0 , sizeof ( dPresentParams ) ) ;
2010-09-25 15:46:12 +00:00
dPresentParams . hDeviceWindow = hWnd ;
2010-09-25 17:35:19 +00:00
dPresentParams . Windowed = true ;
2010-09-25 15:46:12 +00:00
dPresentParams . BackBufferCount = GUI . DoubleBuffered ? 2 : 1 ;
dPresentParams . SwapEffect = D3DSWAPEFFECT_DISCARD ;
dPresentParams . BackBufferFormat = D3DFMT_UNKNOWN ;
HRESULT hr = pD3D - > CreateDevice ( D3DADAPTER_DEFAULT ,
D3DDEVTYPE_HAL ,
hWnd ,
D3DCREATE_MIXED_VERTEXPROCESSING ,
& dPresentParams ,
& pDevice ) ;
if ( FAILED ( hr ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating D3D9 device " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return false ;
}
2011-12-10 14:21:37 +00:00
hr = pDevice - > CreateVertexBuffer ( sizeof ( vertexStream ) , D3DUSAGE_WRITEONLY , 0 , D3DPOOL_MANAGED , & vertexBuffer , NULL ) ;
2010-09-25 15:46:12 +00:00
if ( FAILED ( hr ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating vertex buffer " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return false ;
}
2011-12-10 14:21:37 +00:00
hr = pDevice - > CreateVertexDeclaration ( vertexElems , & vertexDeclaration ) ;
if ( FAILED ( hr ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating vertex declaration " ) , hr ) ;
2011-12-10 14:21:37 +00:00
return false ;
}
2011-03-20 22:21:12 +00:00
cgAvailable = loadCgFunctions ( ) ;
if ( cgAvailable ) {
cgContext = cgCreateContext ( ) ;
hr = cgD3D9SetDevice ( pDevice ) ;
if ( FAILED ( hr ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error setting cg device " ) , hr ) ;
2011-03-20 22:21:12 +00:00
}
2011-12-10 14:21:37 +00:00
cgShader = new CD3DCG ( cgContext , pDevice ) ;
2011-02-24 00:26:42 +00:00
}
2011-03-05 23:48:54 +00:00
pDevice - > SetRenderState ( D3DRS_LIGHTING , FALSE ) ;
2011-12-10 14:21:37 +00:00
pDevice - > SetRenderState ( D3DRS_ZENABLE , FALSE ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_ADDRESSU , D3DTADDRESS_BORDER ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_ADDRESSV , D3DTADDRESS_BORDER ) ;
2011-03-05 23:48:54 +00:00
2010-09-25 15:46:12 +00:00
pDevice - > Clear ( 0 , NULL , D3DCLEAR_TARGET , D3DCOLOR_XRGB ( 0 , 0 , 0 ) , 1.0f , 0 ) ;
init_done = true ;
2010-09-25 17:35:19 +00:00
ApplyDisplayChanges ( ) ;
2010-09-25 15:46:12 +00:00
return true ;
}
void CDirect3D : : DeInitialize ( )
{
DestroyDrawSurface ( ) ;
2010-09-25 17:35:19 +00:00
SetShader ( NULL ) ;
2010-09-25 15:46:12 +00:00
2011-12-10 14:21:37 +00:00
if ( cgShader ) {
delete cgShader ;
cgShader = NULL ;
}
2011-04-10 14:06:24 +00:00
if ( cgContext ) {
cgDestroyContext ( cgContext ) ;
cgContext = NULL ;
}
if ( cgAvailable )
cgD3D9SetDevice ( NULL ) ;
2010-09-25 15:46:12 +00:00
if ( vertexBuffer ) {
vertexBuffer - > Release ( ) ;
vertexBuffer = NULL ;
}
2011-12-10 14:21:37 +00:00
if ( vertexDeclaration ) {
vertexDeclaration - > Release ( ) ;
vertexDeclaration = NULL ;
}
2010-09-25 15:46:12 +00:00
if ( pDevice ) {
pDevice - > Release ( ) ;
pDevice = NULL ;
}
if ( pD3D ) {
pD3D - > Release ( ) ;
pD3D = NULL ;
}
init_done = false ;
afterRenderWidth = 0 ;
afterRenderHeight = 0 ;
quadTextureSize = 0 ;
fullscreen = false ;
2010-09-25 17:35:19 +00:00
filterScale = 0 ;
2011-04-10 14:06:24 +00:00
if ( cgAvailable )
unloadCgLibrary ( ) ;
2011-03-20 22:21:12 +00:00
cgAvailable = false ;
2010-09-25 17:35:19 +00:00
}
bool CDirect3D : : SetShader ( const TCHAR * file )
2011-02-24 00:26:42 +00:00
{
SetShaderCG ( NULL ) ;
shader_type = D3D_SHADER_NONE ;
2011-12-10 14:21:37 +00:00
if ( file ! = NULL & &
( lstrlen ( file ) > 3 & & _tcsncicmp ( & file [ lstrlen ( file ) - 3 ] , TEXT ( " .cg " ) , 3 ) = = 0 ) | |
( lstrlen ( file ) > 4 & & _tcsncicmp ( & file [ lstrlen ( file ) - 4 ] , TEXT ( " .cgp " ) , 4 ) = = 0 ) ) {
2011-02-24 00:26:42 +00:00
return SetShaderCG ( file ) ;
}
2018-08-06 23:16:41 +00:00
return true ;
2011-02-24 00:26:42 +00:00
}
2011-03-04 01:11:36 +00:00
void CDirect3D : : checkForCgError ( const char * situation )
{
char buffer [ 4096 ] ;
CGerror error = cgGetError ( ) ;
const char * string = cgGetErrorString ( error ) ;
if ( error ! = CG_NO_ERROR ) {
sprintf ( buffer ,
" Situation: %s \n "
" Error: %s \n \n "
" Cg compiler output... \n " , situation , string ) ;
MessageBoxA ( 0 , buffer ,
" Cg error " , MB_OK | MB_ICONEXCLAMATION ) ;
if ( error = = CG_COMPILER_ERROR ) {
MessageBoxA ( 0 , cgGetLastListing ( cgContext ) ,
" Cg compilation error " , MB_OK | MB_ICONEXCLAMATION ) ;
}
}
}
2011-02-24 00:26:42 +00:00
bool CDirect3D : : SetShaderCG ( const TCHAR * file )
{
2011-03-20 22:21:12 +00:00
if ( ! cgAvailable ) {
2011-12-10 14:21:37 +00:00
if ( file )
MessageBox ( NULL , TEXT ( " The CG runtime is unavailable, CG shaders will not run. \n Consult the snes9x readme for information on how to obtain the runtime. " ) , TEXT ( " CG Error " ) ,
MB_OK | MB_ICONEXCLAMATION ) ;
2011-03-20 22:21:12 +00:00
return false ;
}
2011-12-10 14:21:37 +00:00
if ( ! cgShader - > LoadShader ( file ) )
2011-02-24 00:26:42 +00:00
return false ;
shader_type = D3D_SHADER_CG ;
return true ;
}
2010-09-25 15:46:12 +00:00
/* CDirect3D::Render
does the actual rendering , changes the draw surface if necessary and recalculates
the vertex information if filter output size changes
IN :
Src - the input surface
*/
void CDirect3D : : Render ( SSurface Src )
{
SSurface Dst ;
RECT dstRect ;
2010-09-25 17:35:19 +00:00
unsigned int newFilterScale ;
2010-09-25 15:46:12 +00:00
D3DLOCKED_RECT lr ;
D3DLOCKED_RECT lrConv ;
HRESULT hr ;
if ( ! init_done ) return ;
//create a new draw surface if the filter scale changes
//at least factor 2 so we can display unscaled hi-res images
2010-09-25 17:35:19 +00:00
newFilterScale = max ( 2 , max ( GetFilterScale ( GUI . ScaleHiRes ) , GetFilterScale ( GUI . Scale ) ) ) ;
if ( newFilterScale ! = filterScale ) {
ChangeDrawSurfaceSize ( newFilterScale ) ;
2010-09-25 15:46:12 +00:00
}
if ( FAILED ( hr = pDevice - > TestCooperativeLevel ( ) ) ) {
switch ( hr ) {
case D3DERR_DEVICELOST : //do no rendering until device is restored
return ;
case D3DERR_DEVICENOTRESET : //we can reset now
2017-06-04 20:17:58 +00:00
if ( ! IsIconic ( dPresentParams . hDeviceWindow ) )
ResetDevice ( ) ;
2010-09-25 15:46:12 +00:00
return ;
default :
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Internal driver error " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return ;
}
}
//BlankTexture(drawSurface);
if ( FAILED ( hr = drawSurface - > LockRect ( 0 , & lr , NULL , 0 ) ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Unable to lock texture " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return ;
} else {
Dst . Surface = ( unsigned char * ) lr . pBits ;
Dst . Height = quadTextureSize ;
Dst . Width = quadTextureSize ;
Dst . Pitch = lr . Pitch ;
RenderMethod ( Src , Dst , & dstRect ) ;
if ( ! Settings . AutoDisplayMessages ) {
2010-09-25 15:52:32 +00:00
WinSetCustomDisplaySurface ( ( void * ) Dst . Surface , Dst . Pitch / 2 , dstRect . right - dstRect . left , dstRect . bottom - dstRect . top , GetFilterScale ( CurrentScale ) ) ;
S9xDisplayMessages ( ( uint16 * ) Dst . Surface , Dst . Pitch / 2 , dstRect . right - dstRect . left , dstRect . bottom - dstRect . top , GetFilterScale ( CurrentScale ) ) ;
2010-09-25 15:46:12 +00:00
}
drawSurface - > UnlockRect ( 0 ) ;
}
2011-04-29 23:26:42 +00:00
if ( ! GUI . Stretch | | GUI . AspectRatio )
pDevice - > Clear ( 0 , NULL , D3DCLEAR_TARGET , D3DCOLOR_XRGB ( 0 , 0 , 0 ) , 1.0f , 0 ) ;
2011-03-05 23:48:54 +00:00
//if the output size of the render method changes we need to update the viewport
2010-09-25 15:46:12 +00:00
if ( afterRenderHeight ! = dstRect . bottom | | afterRenderWidth ! = dstRect . right ) {
afterRenderHeight = dstRect . bottom ;
afterRenderWidth = dstRect . right ;
2011-03-05 23:48:54 +00:00
SetViewport ( ) ;
2010-09-25 15:46:12 +00:00
}
pDevice - > SetTexture ( 0 , drawSurface ) ;
2011-12-10 14:21:37 +00:00
pDevice - > SetVertexDeclaration ( vertexDeclaration ) ;
2010-09-25 15:46:12 +00:00
pDevice - > SetStreamSource ( 0 , vertexBuffer , 0 , sizeof ( VERTEX ) ) ;
2010-09-25 17:35:19 +00:00
2018-08-06 23:16:41 +00:00
if ( shader_type = = D3D_SHADER_CG ) {
RECT displayRect ;
//Get maximum rect respecting AR setting
displayRect = CalculateDisplayRect ( dPresentParams . BackBufferWidth , dPresentParams . BackBufferHeight ,
dPresentParams . BackBufferWidth , dPresentParams . BackBufferHeight ) ;
cgShader - > Render ( drawSurface ,
XMFLOAT2 ( ( float ) quadTextureSize , ( float ) quadTextureSize ) ,
XMFLOAT2 ( ( float ) afterRenderWidth , ( float ) afterRenderHeight ) ,
XMFLOAT2 ( ( float ) ( displayRect . right - displayRect . left ) ,
( float ) ( displayRect . bottom - displayRect . top ) ) ,
XMFLOAT2 ( ( float ) dPresentParams . BackBufferWidth , ( float ) dPresentParams . BackBufferHeight ) ) ;
}
2011-12-10 14:21:37 +00:00
2018-08-06 23:16:41 +00:00
SetFiltering ( ) ;
2011-12-10 14:21:37 +00:00
2018-08-06 23:16:41 +00:00
pDevice - > SetVertexDeclaration ( vertexDeclaration ) ;
2011-12-10 14:21:37 +00:00
2018-08-06 23:16:41 +00:00
pDevice - > BeginScene ( ) ;
pDevice - > DrawPrimitive ( D3DPT_TRIANGLESTRIP , 0 , 2 ) ;
pDevice - > EndScene ( ) ;
2010-09-25 15:46:12 +00:00
pDevice - > Present ( NULL , NULL , NULL , NULL ) ;
2018-05-05 21:31:54 +00:00
if ( GUI . ReduceInputLag )
{
IDirect3DSurface9 * surface ;
2018-05-06 16:05:09 +00:00
RECT r = { 0 , 0 , 2 , 2 } ;
2018-05-05 21:31:54 +00:00
if ( pDevice - > GetBackBuffer ( 0 , 0 , D3DBACKBUFFER_TYPE_MONO , & surface ) = = D3D_OK )
{
2018-05-06 16:05:09 +00:00
if ( surface - > LockRect ( & lr , & r , D3DLOCK_READONLY ) = = D3D_OK )
2018-05-05 21:31:54 +00:00
{
surface - > UnlockRect ( ) ;
}
surface - > Release ( ) ;
}
}
2010-09-25 15:46:12 +00:00
return ;
}
/* CDirect3D::CreateDrawSurface
calculates the necessary texture size ( multiples of 2 )
and creates a new texture
*/
void CDirect3D : : CreateDrawSurface ( )
{
2010-09-25 17:35:19 +00:00
unsigned int neededSize ;
2010-09-25 15:46:12 +00:00
HRESULT hr ;
//we need at least 512 pixels (SNES_WIDTH * 2) so we can start with that value
quadTextureSize = 512 ;
2010-09-25 17:35:19 +00:00
neededSize = SNES_WIDTH * filterScale ;
2010-09-25 15:46:12 +00:00
while ( quadTextureSize < neededSize )
quadTextureSize * = 2 ;
if ( ! drawSurface ) {
hr = pDevice - > CreateTexture (
quadTextureSize , quadTextureSize ,
1 , // 1 level, no mipmaps
0 , // dynamic textures can be locked
D3DFMT_R5G6B5 ,
D3DPOOL_MANAGED ,
& drawSurface ,
NULL ) ;
if ( FAILED ( hr ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error while creating texture " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return ;
}
}
}
/* CDirect3D::DestroyDrawSurface
releases the old textures ( if allocated )
*/
void CDirect3D : : DestroyDrawSurface ( )
{
if ( drawSurface ) {
drawSurface - > Release ( ) ;
drawSurface = NULL ;
}
}
/* CDirect3D::BlankTexture
clears a texture ( fills it with zeroes )
IN :
texture - the texture to be blanked
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : BlankTexture ( LPDIRECT3DTEXTURE9 texture )
{
D3DLOCKED_RECT lr ;
HRESULT hr ;
if ( FAILED ( hr = texture - > LockRect ( 0 , & lr , NULL , 0 ) ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Unable to lock texture " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return false ;
} else {
memset ( lr . pBits , 0 , lr . Pitch * quadTextureSize ) ;
texture - > UnlockRect ( 0 ) ;
return true ;
}
}
/* CDirect3D::ChangeDrawSurfaceSize
changes the draw surface size : deletes the old textures , creates a new texture
and calculate new vertices
IN :
2010-09-25 17:35:19 +00:00
scale - the scale that has to fit into the textures
2010-09-25 15:46:12 +00:00
- - - - -
returns true if successful , false otherwise
*/
2010-09-25 17:35:19 +00:00
bool CDirect3D : : ChangeDrawSurfaceSize ( unsigned int scale )
2010-09-25 15:46:12 +00:00
{
2010-09-25 17:35:19 +00:00
filterScale = scale ;
2010-09-25 15:46:12 +00:00
if ( pDevice ) {
DestroyDrawSurface ( ) ;
CreateDrawSurface ( ) ;
SetupVertices ( ) ;
return true ;
}
return false ;
}
/* CDirect3D::SetupVertices
calculates the vertex coordinates
( respecting the stretch and aspect ratio settings )
*/
void CDirect3D : : SetupVertices ( )
{
void * pLockedVertexBuffer ;
float tX = ( float ) afterRenderWidth / ( float ) quadTextureSize ;
float tY = ( float ) afterRenderHeight / ( float ) quadTextureSize ;
2011-12-10 14:21:37 +00:00
vertexStream [ 0 ] = VERTEX ( 0.0f , 0.0f , 0.0f , 0.0f , tY , 0.0f , 0.0f ) ;
vertexStream [ 1 ] = VERTEX ( 0.0f , 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , 0.0f ) ;
vertexStream [ 2 ] = VERTEX ( 1.0f , 0.0f , 0.0f , tX , tY , 0.0f , 0.0f ) ;
vertexStream [ 3 ] = VERTEX ( 1.0f , 1.0f , 0.0f , tX , 0.0f , 0.0f , 0.0f ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
vertexStream [ i ] . x - = 0.5f / ( float ) dPresentParams . BackBufferWidth ;
vertexStream [ i ] . y + = 0.5f / ( float ) dPresentParams . BackBufferHeight ;
}
2010-09-25 15:46:12 +00:00
HRESULT hr = vertexBuffer - > Lock ( 0 , 0 , & pLockedVertexBuffer , NULL ) ;
2011-12-10 14:21:37 +00:00
memcpy ( pLockedVertexBuffer , vertexStream , sizeof ( vertexStream ) ) ;
2010-09-25 15:46:12 +00:00
vertexBuffer - > Unlock ( ) ;
}
2011-03-05 23:48:54 +00:00
void CDirect3D : : SetViewport ( )
{
2018-08-06 23:16:41 +00:00
XMMATRIX matIdentity ;
XMMATRIX matProjection ;
2011-03-05 23:48:54 +00:00
2018-08-06 23:16:41 +00:00
matProjection = XMMatrixOrthographicOffCenterLH ( 0.0f , 1.0f , 0.0f , 1.0f , 0.0f , 1.0f ) ;
matIdentity = XMMatrixIdentity ( ) ;
pDevice - > SetTransform ( D3DTS_WORLD , ( D3DMATRIX * ) & matIdentity ) ;
pDevice - > SetTransform ( D3DTS_VIEW , ( D3DMATRIX * ) & matIdentity ) ;
pDevice - > SetTransform ( D3DTS_PROJECTION , ( D3DMATRIX * ) & matProjection ) ;
2011-05-13 07:46:43 +00:00
2011-03-05 23:48:54 +00:00
RECT drawRect = CalculateDisplayRect ( afterRenderWidth , afterRenderHeight , dPresentParams . BackBufferWidth , dPresentParams . BackBufferHeight ) ;
D3DVIEWPORT9 viewport ;
viewport . X = drawRect . left ;
viewport . Y = drawRect . top ;
viewport . Height = drawRect . bottom - drawRect . top ;
viewport . Width = drawRect . right - drawRect . left ;
viewport . MinZ = 0.0f ;
viewport . MaxZ = 1.0f ;
HRESULT hr = pDevice - > SetViewport ( & viewport ) ;
SetupVertices ( ) ;
}
2010-09-25 15:46:12 +00:00
/* CDirect3D::ChangeRenderSize
determines if we need to reset the device ( if the size changed )
called with ( 0 , 0 ) whenever we want new settings to take effect
IN :
newWidth , newHeight - the new window size
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : ChangeRenderSize ( unsigned int newWidth , unsigned int newHeight )
{
if ( ! init_done )
return false ;
//if we already have the desired size no change is necessary
//during fullscreen no changes are allowed
2010-09-25 17:35:19 +00:00
if ( dPresentParams . BackBufferWidth = = newWidth & & dPresentParams . BackBufferHeight = = newHeight )
2010-09-25 15:46:12 +00:00
return true ;
if ( ! ResetDevice ( ) )
return false ;
2011-03-05 23:48:54 +00:00
2010-09-25 15:46:12 +00:00
return true ;
}
/* CDirect3D::ResetDevice
resets the device
called if surface was lost or the settings / display size require a device reset
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : ResetDevice ( )
{
2010-09-25 17:35:19 +00:00
if ( ! init_done ) return false ;
2010-09-25 15:46:12 +00:00
HRESULT hr ;
//release prior to reset
DestroyDrawSurface ( ) ;
2011-04-10 14:06:24 +00:00
if ( cgAvailable ) {
2011-12-10 14:21:37 +00:00
cgShader - > OnLostDevice ( ) ;
2011-04-10 14:06:24 +00:00
cgD3D9SetDevice ( NULL ) ;
}
2010-09-25 15:46:12 +00:00
//zero or unknown values result in the current window size/display settings
dPresentParams . BackBufferWidth = 0 ;
dPresentParams . BackBufferHeight = 0 ;
dPresentParams . BackBufferCount = GUI . DoubleBuffered ? 2 : 1 ;
dPresentParams . BackBufferFormat = D3DFMT_UNKNOWN ;
dPresentParams . FullScreen_RefreshRateInHz = 0 ;
dPresentParams . Windowed = true ;
dPresentParams . PresentationInterval = GUI . Vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE ;
2018-05-05 21:31:54 +00:00
dPresentParams . Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER ;
2010-09-25 15:46:12 +00:00
if ( fullscreen ) {
dPresentParams . BackBufferWidth = GUI . FullscreenMode . width ;
dPresentParams . BackBufferHeight = GUI . FullscreenMode . height ;
dPresentParams . BackBufferCount = GUI . DoubleBuffered ? 2 : 1 ;
dPresentParams . Windowed = false ;
if ( GUI . FullscreenMode . depth = = 32 )
dPresentParams . BackBufferFormat = D3DFMT_X8R8G8B8 ;
else
dPresentParams . BackBufferFormat = D3DFMT_R5G6B5 ;
dPresentParams . FullScreen_RefreshRateInHz = GUI . FullscreenMode . rate ;
}
if ( FAILED ( hr = pDevice - > Reset ( & dPresentParams ) ) ) {
2017-02-18 04:52:11 +00:00
DXTRACE_ERR ( TEXT ( " Unable to reset device " ) , hr ) ;
2010-09-25 15:46:12 +00:00
return false ;
}
2011-04-10 14:06:24 +00:00
if ( cgAvailable ) {
cgD3D9SetDevice ( pDevice ) ;
2011-12-10 14:21:37 +00:00
cgShader - > OnResetDevice ( ) ;
2010-09-25 15:46:12 +00:00
}
2011-03-05 23:48:54 +00:00
pDevice - > SetRenderState ( D3DRS_LIGHTING , FALSE ) ;
2010-09-25 15:46:12 +00:00
pDevice - > Clear ( 0 , NULL , D3DCLEAR_TARGET , D3DCOLOR_XRGB ( 0 , 0 , 0 ) , 1.0f , 0 ) ;
//recreate the surface
CreateDrawSurface ( ) ;
2011-04-29 23:26:42 +00:00
SetViewport ( ) ;
2010-09-25 15:46:12 +00:00
return true ;
}
/* CDirect3D::SetSnes9xColorFormat
sets the color format to 16 bit ( since the texture is always 16 bit )
no depth conversion is necessary ( done by D3D )
*/
void CDirect3D : : SetSnes9xColorFormat ( )
{
GUI . ScreenDepth = 16 ;
GUI . BlueShift = 0 ;
GUI . GreenShift = 6 ;
GUI . RedShift = 11 ;
S9xSetRenderPixelFormat ( RGB565 ) ;
S9xBlit2xSaIFilterInit ( ) ;
S9xBlitHQ2xFilterInit ( ) ;
GUI . NeedDepthConvert = FALSE ;
GUI . DepthConverted = TRUE ;
return ;
}
/* CDirect3D::SetFullscreen
enables / disables fullscreen mode
IN :
fullscreen - determines if fullscreen is enabled / disabled
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : SetFullscreen ( bool fullscreen )
{
if ( ! init_done )
return false ;
if ( this - > fullscreen = = fullscreen )
return true ;
this - > fullscreen = fullscreen ;
if ( ! ResetDevice ( ) )
return false ;
//present here to get a fullscreen blank even if no rendering is done
pDevice - > Present ( NULL , NULL , NULL , NULL ) ;
2011-04-29 23:26:42 +00:00
2010-09-25 15:46:12 +00:00
return true ;
}
/* CDirect3D::EnumModes
enumerates possible display modes ( only 16 and 32 bit ) and fills the vector
IN :
modeVector - pointer to the mode vector
*/
void CDirect3D : : EnumModes ( std : : vector < dMode > * modeVector )
{
D3DDISPLAYMODE d3dMode ;
int modeCount , index ;
dMode mode ;
if ( ! init_done )
return ;
//enumerate 32bit modes
modeCount = pD3D - > GetAdapterModeCount ( D3DADAPTER_DEFAULT , D3DFMT_X8R8G8B8 ) ;
for ( int i = 0 ; i < modeCount ; i + + ) {
if ( pD3D - > EnumAdapterModes ( D3DADAPTER_DEFAULT , D3DFMT_X8R8G8B8 , i , & d3dMode ) = = D3D_OK ) {
mode . width = d3dMode . Width ;
mode . height = d3dMode . Height ;
mode . rate = d3dMode . RefreshRate ;
mode . depth = 32 ;
modeVector - > push_back ( mode ) ;
}
}
//enumerate 16bit modes
modeCount = pD3D - > GetAdapterModeCount ( D3DADAPTER_DEFAULT , D3DFMT_R5G6B5 ) ;
for ( int i = 0 ; i < modeCount ; i + + ) {
if ( pD3D - > EnumAdapterModes ( D3DADAPTER_DEFAULT , D3DFMT_R5G6B5 , i , & d3dMode ) = = D3D_OK ) {
mode . width = d3dMode . Width ;
mode . height = d3dMode . Height ;
mode . rate = d3dMode . RefreshRate ;
mode . depth = 16 ;
modeVector - > push_back ( mode ) ;
}
}
}
/* CDirect3D::ApplyDisplayChanges
calls changerendersize to apply new display settings
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : ApplyDisplayChanges ( void )
{
2011-02-24 00:26:42 +00:00
if ( GUI . shaderEnabled & & GUI . D3DshaderFileName )
SetShader ( GUI . D3DshaderFileName ) ;
2010-09-25 17:35:19 +00:00
else
SetShader ( NULL ) ;
2010-09-25 15:46:12 +00:00
return ChangeRenderSize ( 0 , 0 ) ;
}
2011-12-10 14:21:37 +00:00
void CDirect3D : : SetFiltering ( )
{
2018-05-20 16:01:03 +00:00
if ( Settings . BilinearFilter ) {
2011-12-10 14:21:37 +00:00
pDevice - > SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR ) ;
} else {
pDevice - > SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_POINT ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_POINT ) ;
}
}