2013-04-04 21:22:19 +00:00
/*
* Glide64 - Glide video plugin for Nintendo 64 emulators .
* Copyright ( c ) 2002 Dave2001
* Copyright ( c ) 2003 - 2009 Sergey ' Gonetz ' Lipski
*
* 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
* 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
*/
//****************************************************************
//
// Glide64 - Glide Plugin for Nintendo 64 emulators
// Project started on December 29th, 2001
//
// Authors:
// Dave2001, original author, founded the project in 2001, left it in 2002
// Gugaman, joined the project in 2002, left it in 2002
// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
//
//****************************************************************
//
// To modify Glide64:
// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
//
//****************************************************************
2013-04-20 02:14:46 +00:00
2016-01-28 20:00:13 +00:00
# include <string.h>
2015-12-04 21:26:58 +00:00
# include <Common/StdString.h>
2015-10-09 00:07:09 +00:00
# include "Gfx_1.3.h"
2015-02-17 09:56:34 +00:00
# include "Version.h"
2013-04-24 05:03:21 +00:00
# include <Settings/Settings.h>
2016-01-25 09:33:04 +00:00
# include <Common/CriticalSection.h>
2016-09-16 21:37:27 +00:00
# include <Common/DateTimeClass.h>
2016-01-25 11:00:45 +00:00
# include <Common/path.h>
2016-02-24 10:55:42 +00:00
# include <png/png.h>
2016-03-08 06:36:18 +00:00
# include <memory>
2016-10-09 09:44:31 +00:00
# include <Common/SmartPointer.h>
2013-04-24 05:03:21 +00:00
2016-01-25 11:00:45 +00:00
# include "Config.h"
2013-04-04 21:22:19 +00:00
# include "Util.h"
# include "3dmath.h"
# include "Debugger.h"
# include "Combine.h"
# include "TexCache.h"
# include "CRC.h"
# include "FBtoScreen.h"
# include "DepthBufferRender.h"
2016-02-01 08:56:25 +00:00
# include "trace.h"
2017-01-28 11:29:03 +00:00
# include "ScreenResolution.h"
2013-04-04 21:22:19 +00:00
2017-01-28 19:27:50 +00:00
# ifdef _WIN32
# include <commctrl.h>
# endif
2013-04-04 21:22:19 +00:00
# include <stdarg.h>
2017-02-08 19:08:06 +00:00
# ifdef ANDROID
uint32_t g_NativeWidth , g_NativeHeight ;
# endif
2013-04-04 21:22:19 +00:00
GFX_INFO gfx ;
int to_fullscreen = FALSE ;
2016-01-20 17:12:15 +00:00
int GfxInitDone = FALSE ;
2016-03-08 06:31:08 +00:00
bool g_romopen = false ;
2013-04-04 21:22:19 +00:00
GrContext_t gfx_context = 0 ;
int exception = FALSE ;
int evoodoo = 0 ;
int ev_fullscreen = 0 ;
2017-01-28 19:27:50 +00:00
extern int viewport_offset ;
2017-02-08 19:08:06 +00:00
extern int g_width , g_height ;
2017-01-28 19:27:50 +00:00
2016-01-25 11:00:45 +00:00
# ifdef _WIN32
2013-04-22 01:11:55 +00:00
HINSTANCE hinstDLL = NULL ;
2013-04-04 21:22:19 +00:00
# endif
# ifdef PERFORMANCE
int64 perf_cur ;
int64 perf_next ;
# endif
2016-01-20 06:14:48 +00:00
uint32_t region = 0 ;
2013-04-04 21:22:19 +00:00
unsigned int BMASK = 0x7FFFFF ;
// Reality display processor structure
RDP rdp ;
2017-01-23 06:50:29 +00:00
CSettings * g_settings = NULL ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
VOODOO voodoo = { 0 , 0 , 0 , 0 ,
2016-03-08 21:55:19 +00:00
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0
2016-01-20 06:29:27 +00:00
} ;
2013-04-04 21:22:19 +00:00
GrTexInfo fontTex ;
GrTexInfo cursorTex ;
2016-01-20 06:14:48 +00:00
uint32_t offset_font = 0 ;
uint32_t offset_cursor = 0 ;
uint32_t offset_textures = 0 ;
uint32_t offset_texbuf1 = 0 ;
2013-04-04 21:22:19 +00:00
int capture_screen = 0 ;
2016-01-25 11:00:45 +00:00
std : : string capture_path ;
2013-04-04 21:22:19 +00:00
2017-01-28 11:29:03 +00:00
# ifdef _WIN32
HWND g_hwnd_win = NULL ;
static RECT g_windowedRect = { 0 } ;
static HMENU g_windowedMenu = 0 ;
static unsigned long g_windowedExStyle , g_windowedStyle ;
bool g_fullscreen ;
# endif // _WIN32
2016-01-20 06:29:27 +00:00
void _ChangeSize ( )
2013-04-04 21:22:19 +00:00
{
2017-01-31 06:56:52 +00:00
rdp . scale_1024 = g_settings - > scr_res_x ( ) / 1024.0f ;
rdp . scale_768 = g_settings - > scr_res_y ( ) / 768.0f ;
2013-04-04 21:22:19 +00:00
2016-02-01 08:56:25 +00:00
// float res_scl_x = (float)g_settings->res_x / 320.0f;
2017-01-31 06:56:52 +00:00
float res_scl_y = ( float ) g_settings - > res_y ( ) / 240.0f ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
uint32_t scale_x = * gfx . VI_X_SCALE_REG & 0xFFF ;
if ( ! scale_x ) return ;
uint32_t scale_y = * gfx . VI_Y_SCALE_REG & 0xFFF ;
if ( ! scale_y ) return ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
float fscale_x = ( float ) scale_x / 1024.0f ;
float fscale_y = ( float ) scale_y / 2048.0f ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
uint32_t dwHStartReg = * gfx . VI_H_START_REG ;
uint32_t dwVStartReg = * gfx . VI_V_START_REG ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
uint32_t hstart = dwHStartReg > > 16 ;
uint32_t hend = dwHStartReg & 0xFFFF ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// dunno... but sometimes this happens
if ( hend = = hstart ) hend = ( int ) ( * gfx . VI_WIDTH_REG / fscale_x ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
uint32_t vstart = dwVStartReg > > 16 ;
uint32_t vend = dwVStartReg & 0xFFFF ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
rdp . vi_width = ( hend - hstart ) * fscale_x ;
rdp . vi_height = ( vend - vstart ) * fscale_y * 1.0126582f ;
2016-02-01 08:56:25 +00:00
float aspect = ( g_settings - > adjust_aspect & & ( fscale_y > fscale_x ) & & ( rdp . vi_width > rdp . vi_height ) ) ? fscale_x / fscale_y : 1.0f ;
2013-04-04 21:22:19 +00:00
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceResolution , TraceDebug , " hstart: %d, hend: %d, vstart: %d, vend: %d " , hstart , hend , vstart , vend ) ;
WriteTrace ( TraceResolution , TraceDebug , " size: %d x %d " , ( int ) rdp . vi_width , ( int ) rdp . vi_height ) ;
2013-04-04 21:22:19 +00:00
2017-01-31 06:56:52 +00:00
rdp . scale_x = ( float ) g_settings - > res_x ( ) / rdp . vi_width ;
2016-02-01 08:56:25 +00:00
if ( region > 0 & & g_settings - > pal230 )
2016-01-20 06:29:27 +00:00
{
// odd... but pal games seem to want 230 as height...
rdp . scale_y = res_scl_y * ( 230.0f / rdp . vi_height ) * aspect ;
}
else
{
2017-01-31 06:56:52 +00:00
rdp . scale_y = ( float ) g_settings - > res_y ( ) / rdp . vi_height * aspect ;
2016-01-20 06:29:27 +00:00
}
2016-02-01 08:56:25 +00:00
// rdp.offset_x = g_settings->offset_x * res_scl_x;
// rdp.offset_y = g_settings->offset_y * res_scl_y;
2016-01-20 06:29:27 +00:00
//rdp.offset_x = 0;
// rdp.offset_y = 0;
2017-01-31 06:56:52 +00:00
rdp . offset_y = ( ( float ) g_settings - > res_y ( ) - rdp . vi_height * rdp . scale_y ) * 0.5f ;
2016-01-20 06:29:27 +00:00
if ( ( ( uint32_t ) rdp . vi_width < = ( * gfx . VI_WIDTH_REG ) / 2 ) & & ( rdp . vi_width > rdp . vi_height ) )
rdp . scale_y * = 0.5f ;
rdp . scissor_o . ul_x = 0 ;
rdp . scissor_o . ul_y = 0 ;
rdp . scissor_o . lr_x = ( uint32_t ) rdp . vi_width ;
rdp . scissor_o . lr_y = ( uint32_t ) rdp . vi_height ;
rdp . update | = UPDATE_VIEWPORT | UPDATE_SCISSOR ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
void ChangeSize ( )
2013-04-04 21:22:19 +00:00
{
2017-01-31 06:56:52 +00:00
g_settings - > UpdateScreenSize ( ev_fullscreen ) ;
2016-01-20 06:29:27 +00:00
_ChangeSize ( ) ;
2017-01-31 06:56:52 +00:00
rdp . offset_x = ( g_settings - > scr_res_x ( ) - g_settings - > res_x ( ) ) / 2.0f ;
float offset_y = ( g_settings - > scr_res_y ( ) - g_settings - > res_y ( ) ) / 2.0f ;
2016-01-20 06:29:27 +00:00
rdp . offset_y + = offset_y ;
2017-01-29 06:47:28 +00:00
if ( g_settings - > aspectmode ( ) = = CSettings : : Aspect_Original )
2016-01-20 06:29:27 +00:00
{
rdp . scale_x = rdp . scale_y = 1.0f ;
2017-01-31 06:56:52 +00:00
rdp . offset_x = ( g_settings - > scr_res_x ( ) - rdp . vi_width ) / 2.0f ;
rdp . offset_y = ( g_settings - > scr_res_y ( ) - rdp . vi_height ) / 2.0f ;
2016-01-20 06:29:27 +00:00
}
2013-04-04 21:22:19 +00:00
}
void ConfigWrapper ( )
{
2017-01-28 11:29:03 +00:00
grConfigWrapperExt ( g_settings - > wrpVRAM * 1024 * 1024 , g_settings - > wrpFBO , g_settings - > wrpAnisotropic ) ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
void UseUnregisteredSetting ( int /*SettingID*/ )
2013-04-04 21:22:19 +00:00
{
2016-01-25 11:00:45 +00:00
# ifdef _WIN32
2016-01-20 06:29:27 +00:00
DebugBreak ( ) ;
2016-01-25 11:00:45 +00:00
# endif
2013-04-04 21:22:19 +00:00
}
2016-03-10 18:29:41 +00:00
extern int g_width , g_height ;
2013-04-04 21:22:19 +00:00
GRSTIPPLE grStippleModeExt = NULL ;
GRSTIPPLE grStipplePatternExt = NULL ;
2013-04-22 01:11:55 +00:00
int GetTexAddrUMA ( int /*tmu*/ , int texsize )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
int addr = voodoo . tex_min_addr [ 0 ] + voodoo . tmem_ptr [ 0 ] ;
voodoo . tmem_ptr [ 0 ] + = texsize ;
voodoo . tmem_ptr [ 1 ] = voodoo . tmem_ptr [ 0 ] ;
return addr ;
2013-04-04 21:22:19 +00:00
}
int GetTexAddrNonUMA ( int tmu , int texsize )
{
2016-01-20 06:29:27 +00:00
int addr = voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ;
voodoo . tmem_ptr [ tmu ] + = texsize ;
return addr ;
2013-04-04 21:22:19 +00:00
}
GETTEXADDR GetTexAddr = GetTexAddrNonUMA ;
// guLoadTextures - used to load the cursor and font textures
2016-01-20 06:29:27 +00:00
void guLoadTextures ( )
2013-04-04 21:22:19 +00:00
{
int tbuf_size = 0 ;
if ( voodoo . max_tex_size < = 256 )
{
2016-01-20 06:29:27 +00:00
grTextureBufferExt ( GR_TMU1 , voodoo . tex_min_addr [ GR_TMU1 ] , GR_LOD_LOG2_256 , GR_LOD_LOG2_256 ,
GR_ASPECT_LOG2_1x1 , GR_TEXFMT_RGB_565 , GR_MIPMAPLEVELMASK_BOTH ) ;
tbuf_size = 8 * grTexCalcMemRequired ( GR_LOD_LOG2_256 , GR_LOD_LOG2_256 ,
GR_ASPECT_LOG2_1x1 , GR_TEXFMT_RGB_565 ) ;
2013-04-04 21:22:19 +00:00
}
2017-01-31 06:56:52 +00:00
else if ( g_settings - > scr_res_x ( ) < = 1024 )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
grTextureBufferExt ( GR_TMU0 , voodoo . tex_min_addr [ GR_TMU0 ] , GR_LOD_LOG2_1024 , GR_LOD_LOG2_1024 ,
GR_ASPECT_LOG2_1x1 , GR_TEXFMT_RGB_565 , GR_MIPMAPLEVELMASK_BOTH ) ;
tbuf_size = grTexCalcMemRequired ( GR_LOD_LOG2_1024 , GR_LOD_LOG2_1024 ,
GR_ASPECT_LOG2_1x1 , GR_TEXFMT_RGB_565 ) ;
grRenderBuffer ( GR_BUFFER_TEXTUREBUFFER_EXT ) ;
grBufferClear ( 0 , 0 , 0xFFFF ) ;
grRenderBuffer ( GR_BUFFER_BACKBUFFER ) ;
2013-04-04 21:22:19 +00:00
}
else
{
2016-01-20 06:29:27 +00:00
grTextureBufferExt ( GR_TMU0 , voodoo . tex_min_addr [ GR_TMU0 ] , GR_LOD_LOG2_2048 , GR_LOD_LOG2_2048 ,
GR_ASPECT_LOG2_1x1 , GR_TEXFMT_RGB_565 , GR_MIPMAPLEVELMASK_BOTH ) ;
tbuf_size = grTexCalcMemRequired ( GR_LOD_LOG2_2048 , GR_LOD_LOG2_2048 ,
GR_ASPECT_LOG2_1x1 , GR_TEXFMT_RGB_565 ) ;
grRenderBuffer ( GR_BUFFER_TEXTUREBUFFER_EXT ) ;
grBufferClear ( 0 , 0 , 0xFFFF ) ;
grRenderBuffer ( GR_BUFFER_BACKBUFFER ) ;
2013-04-04 21:22:19 +00:00
}
rdp . texbufs [ 0 ] . tmu = GR_TMU0 ;
rdp . texbufs [ 0 ] . begin = voodoo . tex_min_addr [ GR_TMU0 ] ;
2016-01-20 06:29:27 +00:00
rdp . texbufs [ 0 ] . end = rdp . texbufs [ 0 ] . begin + tbuf_size ;
2013-04-04 21:22:19 +00:00
rdp . texbufs [ 0 ] . count = 0 ;
rdp . texbufs [ 0 ] . clear_allowed = TRUE ;
offset_font = tbuf_size ;
if ( voodoo . num_tmu > 1 )
{
2016-01-20 06:29:27 +00:00
rdp . texbufs [ 1 ] . tmu = GR_TMU1 ;
rdp . texbufs [ 1 ] . begin = voodoo . tex_UMA ? rdp . texbufs [ 0 ] . end : voodoo . tex_min_addr [ GR_TMU1 ] ;
rdp . texbufs [ 1 ] . end = rdp . texbufs [ 1 ] . begin + tbuf_size ;
rdp . texbufs [ 1 ] . count = 0 ;
rdp . texbufs [ 1 ] . clear_allowed = TRUE ;
if ( voodoo . tex_UMA )
offset_font + = tbuf_size ;
else
offset_texbuf1 = tbuf_size ;
2013-04-04 21:22:19 +00:00
}
# include "font.h"
2016-01-20 06:29:27 +00:00
uint32_t * data = ( uint32_t * ) font ;
uint32_t cur ;
// ** Font texture **
uint8_t * tex8 = ( uint8_t * ) malloc ( 256 * 64 ) ;
fontTex . smallLodLog2 = fontTex . largeLodLog2 = GR_LOD_LOG2_256 ;
fontTex . aspectRatioLog2 = GR_ASPECT_LOG2_4x1 ;
fontTex . format = GR_TEXFMT_ALPHA_8 ;
fontTex . data = tex8 ;
// Decompression: [1-bit inverse alpha --> 8-bit alpha]
uint32_t i , b ;
for ( i = 0 ; i < 0x200 ; i + + )
{
// cur = ~*(data++), byteswapped
2013-04-04 21:22:19 +00:00
# ifdef __VISUALC__
2016-01-20 06:29:27 +00:00
cur = _byteswap_ulong ( ~ * ( data + + ) ) ;
2013-04-04 21:22:19 +00:00
# else
2016-01-20 06:29:27 +00:00
cur = ~ * ( data + + ) ;
cur = ( ( cur & 0xFF ) < < 24 ) | ( ( ( cur > > 8 ) & 0xFF ) < < 16 ) | ( ( ( cur > > 16 ) & 0xFF ) < < 8 ) | ( ( cur > > 24 ) & 0xFF ) ;
2013-04-04 21:22:19 +00:00
# endif
2016-01-20 06:29:27 +00:00
for ( b = 0x80000000 ; b ! = 0 ; b > > = 1 )
{
if ( cur & b ) * tex8 = 0xFF ;
else * tex8 = 0x00 ;
tex8 + + ;
2016-02-24 07:07:50 +00:00
}
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
grTexDownloadMipMap ( GR_TMU0 ,
voodoo . tex_min_addr [ GR_TMU0 ] + offset_font ,
GR_MIPMAPLEVELMASK_BOTH ,
& fontTex ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
offset_cursor = offset_font + grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & fontTex ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
free ( fontTex . data ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// ** Cursor texture **
2013-04-04 21:22:19 +00:00
# include "cursor.h"
2016-01-20 06:29:27 +00:00
data = ( uint32_t * ) cursor ;
uint16_t * tex16 = ( uint16_t * ) malloc ( 32 * 32 * 2 ) ;
cursorTex . smallLodLog2 = cursorTex . largeLodLog2 = GR_LOD_LOG2_32 ;
cursorTex . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
cursorTex . format = GR_TEXFMT_ARGB_1555 ;
cursorTex . data = tex16 ;
// Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]
for ( i = 0 ; i < 0x200 ; i + + )
{
cur = * ( data + + ) ;
* ( tex16 + + ) = ( uint16_t ) ( ( ( cur & 0x000000FF ) < < 8 ) | ( ( cur & 0x0000FF00 ) > > 8 ) ) ;
* ( tex16 + + ) = ( uint16_t ) ( ( ( cur & 0x00FF0000 ) > > 8 ) | ( ( cur & 0xFF000000 ) > > 24 ) ) ;
}
grTexDownloadMipMap ( GR_TMU0 ,
voodoo . tex_min_addr [ GR_TMU0 ] + offset_cursor ,
GR_MIPMAPLEVELMASK_BOTH ,
& cursorTex ) ;
// Round to higher 16
offset_textures = ( ( offset_cursor + grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & cursorTex ) )
& 0xFFFFFFF0 ) + 16 ;
free ( cursorTex . data ) ;
2013-04-04 21:22:19 +00:00
}
void DisplayLoadProgress ( const wchar_t * format , . . . )
{
2016-01-20 06:29:27 +00:00
va_list args ;
wchar_t wbuf [ INFO_BUF ] ;
char buf [ INFO_BUF ] ;
// process input
va_start ( args , format ) ;
vswprintf ( wbuf , INFO_BUF , format , args ) ;
va_end ( args ) ;
// XXX: convert to multibyte
wcstombs ( buf , wbuf , INFO_BUF ) ;
2016-01-20 17:12:15 +00:00
float x ;
set_message_combiner ( ) ;
output ( 382 , 380 , 1 , " LOADING TEXTURES. PLEASE WAIT... " ) ;
2016-01-25 09:58:29 +00:00
int len = minval ( ( int ) strlen ( buf ) * 8 , 1024 ) ;
2016-01-20 17:12:15 +00:00
x = ( 1024 - len ) / 2.0f ;
output ( x , 360 , 1 , buf ) ;
grBufferSwap ( 0 ) ;
grColorMask ( FXTRUE , FXTRUE ) ;
grBufferClear ( 0 , 0 , 0xFFFF ) ;
2013-04-04 21:22:19 +00:00
}
2017-01-28 11:29:03 +00:00
# ifdef _WIN32
void SetWindowDisplaySize ( HWND hWnd )
{
if ( ( HWND ) hWnd = = NULL ) hWnd = GetActiveWindow ( ) ;
g_hwnd_win = ( HWND ) hWnd ;
2017-01-31 06:56:52 +00:00
if ( ev_fullscreen )
2017-01-28 11:29:03 +00:00
{
ZeroMemory ( & g_windowedRect , sizeof ( RECT ) ) ;
GetWindowRect ( hWnd , & g_windowedRect ) ;
g_windowedExStyle = GetWindowLong ( hWnd , GWL_EXSTYLE ) ;
g_windowedStyle = GetWindowLong ( hWnd , GWL_STYLE ) ;
// primary monitor only
2017-01-31 06:56:52 +00:00
if ( ! EnterFullScreen ( g_settings - > wrpResolution ) )
2017-01-28 11:29:03 +00:00
{
WriteTrace ( TraceGlitch , TraceWarning , " can't change to fullscreen mode " ) ;
}
g_windowedMenu = GetMenu ( hWnd ) ;
if ( g_windowedMenu ) SetMenu ( hWnd , NULL ) ;
HWND hStatusBar = FindWindowEx ( hWnd , NULL , " msctls_statusbar32 " , NULL ) ; // 1964
if ( hStatusBar ) ShowWindow ( hStatusBar , SW_HIDE ) ;
SetWindowLong ( hWnd , GWL_STYLE , 0 ) ;
SetWindowLong ( hWnd , GWL_EXSTYLE , WS_EX_APPWINDOW | WS_EX_TOPMOST ) ;
SetWindowPos ( hWnd , NULL , 0 , 0 , g_width , g_height , SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW ) ;
viewport_offset = 0 ;
g_fullscreen = true ;
}
2017-01-31 06:56:52 +00:00
else
{
RECT clientRect = { 0 } , toolbarRect = { 0 } , statusbarRect = { 0 } , windowedRect = { 0 } ;
HWND hToolBar = FindWindowEx ( hWnd , NULL , REBARCLASSNAME , NULL ) ;
HWND hStatusBar = FindWindowEx ( hWnd , NULL , STATUSCLASSNAME , NULL ) ;
if ( hStatusBar = = NULL )
{
hStatusBar = FindWindowEx ( hWnd , NULL , " msctls_statusbar32 " , NULL ) ;
}
if ( hToolBar ! = NULL )
{
GetWindowRect ( hToolBar , & toolbarRect ) ;
}
if ( hStatusBar ! = NULL )
{
GetWindowRect ( hStatusBar , & statusbarRect ) ;
}
viewport_offset = statusbarRect . bottom - statusbarRect . top ;
GetWindowRect ( hWnd , & g_windowedRect ) ;
GetClientRect ( hWnd , & clientRect ) ;
g_windowedRect . right + = ( g_width - ( clientRect . right - clientRect . left ) ) ;
g_windowedRect . bottom + = ( g_height + ( toolbarRect . bottom - toolbarRect . top ) + ( statusbarRect . bottom - statusbarRect . top ) - ( clientRect . bottom - clientRect . top ) ) ;
SetWindowPos ( hWnd , NULL , 0 , 0 , g_windowedRect . right - g_windowedRect . left , g_windowedRect . bottom - g_windowedRect . top , SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE ) ;
g_fullscreen = false ;
}
2017-01-28 11:29:03 +00:00
}
void ExitFullScreen ( void )
{
if ( g_fullscreen )
{
ChangeDisplaySettings ( NULL , 0 ) ;
SetWindowPos ( g_hwnd_win , NULL , g_windowedRect . left , g_windowedRect . top , 0 , 0 , SWP_NOZORDER | SWP_NOSIZE ) ;
SetWindowLong ( g_hwnd_win , GWL_STYLE , g_windowedStyle ) ;
SetWindowLong ( g_hwnd_win , GWL_EXSTYLE , g_windowedExStyle ) ;
if ( g_windowedMenu ) SetMenu ( g_hwnd_win , g_windowedMenu ) ;
g_fullscreen = false ;
}
}
# endif
2016-01-20 06:29:27 +00:00
int InitGfx ( )
2013-04-04 21:22:19 +00:00
{
2016-01-20 17:12:15 +00:00
if ( GfxInitDone )
{
2016-01-20 06:29:27 +00:00
ReleaseGfx ( ) ;
2016-01-20 17:12:15 +00:00
}
2016-01-20 06:29:27 +00:00
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2016-01-20 06:29:27 +00:00
rdp_reset ( ) ;
// Initialize Glide
grGlideInit ( ) ;
// Is mirroring allowed?
const char * extensions = grGetString ( GR_EXTENSION ) ;
2017-01-24 19:08:33 +00:00
// Check which SST we are using and initialize stuff
2016-01-20 06:29:27 +00:00
// Hiroshi Morii <koolsmoky@users.sourceforge.net>
enum {
GR_SSTTYPE_VOODOO = 0 ,
GR_SSTTYPE_SST96 = 1 ,
GR_SSTTYPE_AT3D = 2 ,
GR_SSTTYPE_Voodoo2 = 3 ,
GR_SSTTYPE_Banshee = 4 ,
GR_SSTTYPE_Voodoo3 = 5 ,
GR_SSTTYPE_Voodoo4 = 6 ,
GR_SSTTYPE_Voodoo5 = 7
} ;
const char * hardware = grGetString ( GR_HARDWARE ) ;
unsigned int SST_type = GR_SSTTYPE_VOODOO ;
if ( strstr ( hardware , " Rush " ) ) {
SST_type = GR_SSTTYPE_SST96 ;
}
else if ( strstr ( hardware , " Voodoo2 " ) ) {
SST_type = GR_SSTTYPE_Voodoo2 ;
}
else if ( strstr ( hardware , " Voodoo Banshee " ) ) {
SST_type = GR_SSTTYPE_Banshee ;
}
else if ( strstr ( hardware , " Voodoo3 " ) ) {
SST_type = GR_SSTTYPE_Voodoo3 ;
}
else if ( strstr ( hardware , " Voodoo4 " ) ) {
SST_type = GR_SSTTYPE_Voodoo4 ;
}
else if ( strstr ( hardware , " Voodoo5 " ) ) {
SST_type = GR_SSTTYPE_Voodoo5 ;
}
// 2Mb Texture boundary
voodoo . has_2mb_tex_boundary = ( SST_type < GR_SSTTYPE_Banshee ) & & ! evoodoo ;
// use UMA if available
voodoo . tex_UMA = FALSE ;
2017-02-08 19:08:06 +00:00
if ( strstr ( extensions , " TEXUMA " ) )
{
2016-01-20 06:29:27 +00:00
// we get better texture cache hits with UMA on
grEnable ( GR_TEXTURE_UMA_EXT ) ;
voodoo . tex_UMA = TRUE ;
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " Using TEXUMA extension " ) ;
2016-01-20 06:29:27 +00:00
}
2017-01-31 06:56:52 +00:00
g_settings - > UpdateScreenSize ( ev_fullscreen ) ;
2017-02-08 19:08:06 +00:00
# ifndef ANDROID
2017-01-28 11:29:03 +00:00
SetWindowDisplaySize ( gfx . hWnd ) ;
2017-02-08 19:08:06 +00:00
# endif
2017-01-28 19:27:50 +00:00
gfx_context = grSstWinOpen ( GR_COLORFORMAT_RGBA , GR_ORIGIN_UPPER_LEFT , 2 , 1 ) ;
2016-01-20 06:29:27 +00:00
if ( ! gfx_context )
{
2016-03-28 22:50:01 +00:00
# ifdef _WIN32
2016-01-25 11:00:45 +00:00
MessageBox ( gfx . hWnd , " Error setting display mode " , " Error " , MB_OK | MB_ICONEXCLAMATION ) ;
2016-03-28 22:50:01 +00:00
# else
fprintf ( stderr , " Error setting display mode \n " ) ;
# endif
2016-01-20 06:29:27 +00:00
grGlideShutdown ( ) ;
return FALSE ;
}
2013-04-04 21:22:19 +00:00
2016-01-20 17:12:15 +00:00
GfxInitDone = TRUE ;
2016-01-20 06:29:27 +00:00
to_fullscreen = FALSE ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// get the # of TMUs available
grGet ( GR_NUM_TMU , 4 , ( FxI32 * ) & voodoo . num_tmu ) ;
// get maximal texture size
grGet ( GR_MAX_TEXTURE_SIZE , 4 , ( FxI32 * ) & voodoo . max_tex_size ) ;
2017-01-29 06:26:41 +00:00
voodoo . sup_large_tex = ( voodoo . max_tex_size > 256 & & ! g_settings - > hacks ( CSettings : : hack_PPL ) ) ;
2016-01-20 06:29:27 +00:00
//num_tmu = 1;
if ( voodoo . tex_UMA )
{
GetTexAddr = GetTexAddrUMA ;
voodoo . tex_min_addr [ 0 ] = voodoo . tex_min_addr [ 1 ] = grTexMinAddress ( GR_TMU0 ) ;
voodoo . tex_max_addr [ 0 ] = voodoo . tex_max_addr [ 1 ] = grTexMaxAddress ( GR_TMU0 ) ;
}
else
{
GetTexAddr = GetTexAddrNonUMA ;
voodoo . tex_min_addr [ 0 ] = grTexMinAddress ( GR_TMU0 ) ;
voodoo . tex_min_addr [ 1 ] = grTexMinAddress ( GR_TMU1 ) ;
voodoo . tex_max_addr [ 0 ] = grTexMaxAddress ( GR_TMU0 ) ;
voodoo . tex_max_addr [ 1 ] = grTexMaxAddress ( GR_TMU1 ) ;
}
2013-04-04 21:22:19 +00:00
2017-01-29 06:26:41 +00:00
if ( strstr ( extensions , " TEXMIRROR " ) & & ! g_settings - > hacks ( CSettings : : hack_Zelda ) ) //zelda's trees suffer from hardware mirroring
2016-01-20 06:29:27 +00:00
voodoo . sup_mirroring = 1 ;
else
voodoo . sup_mirroring = 0 ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
if ( strstr ( extensions , " TEXFMT " ) ) //VSA100 texture format extension
voodoo . sup_32bit_tex = TRUE ;
else
voodoo . sup_32bit_tex = FALSE ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
voodoo . gamma_correction = 0 ;
if ( strstr ( extensions , " GETGAMMA " ) )
grGet ( GR_GAMMA_TABLE_ENTRIES , sizeof ( voodoo . gamma_table_size ) , & voodoo . gamma_table_size ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
grStippleModeExt = ( GRSTIPPLE ) grStippleMode ;
grStipplePatternExt = ( GRSTIPPLE ) grStipplePattern ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
if ( grStipplePatternExt )
2016-02-01 08:56:25 +00:00
grStipplePatternExt ( g_settings - > stipple_pattern ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
InitCombine ( ) ;
2013-04-04 21:22:19 +00:00
# ifdef SIMULATE_VOODOO1
2016-01-20 06:29:27 +00:00
voodoo . num_tmu = 1 ;
voodoo . sup_mirroring = 0 ;
2013-04-04 21:22:19 +00:00
# endif
# ifdef SIMULATE_BANSHEE
2016-01-20 06:29:27 +00:00
voodoo . num_tmu = 1 ;
voodoo . sup_mirroring = 1 ;
2013-04-04 21:22:19 +00:00
# endif
2016-01-20 06:29:27 +00:00
grCoordinateSpace ( GR_WINDOW_COORDS ) ;
grVertexLayout ( GR_PARAM_XY , offsetof ( VERTEX , x ) , GR_PARAM_ENABLE ) ;
grVertexLayout ( GR_PARAM_Q , offsetof ( VERTEX , q ) , GR_PARAM_ENABLE ) ;
grVertexLayout ( GR_PARAM_Z , offsetof ( VERTEX , z ) , GR_PARAM_ENABLE ) ;
grVertexLayout ( GR_PARAM_ST0 , offsetof ( VERTEX , coord [ 0 ] ) , GR_PARAM_ENABLE ) ;
grVertexLayout ( GR_PARAM_ST1 , offsetof ( VERTEX , coord [ 2 ] ) , GR_PARAM_ENABLE ) ;
grVertexLayout ( GR_PARAM_PARGB , offsetof ( VERTEX , b ) , GR_PARAM_ENABLE ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
grCullMode ( GR_CULL_NEGATIVE ) ;
2013-04-04 21:22:19 +00:00
2017-03-09 20:54:56 +00:00
if ( g_settings - > fog ( ) ) //"FOGCOORD" extension
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
if ( strstr ( extensions , " FOGCOORD " ) )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
GrFog_t fog_t [ 64 ] ;
guFogGenerateLinear ( fog_t , 0.0f , 255.0f ) ; //(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);
for ( int i = 63 ; i > 0 ; i - - )
{
if ( fog_t [ i ] - fog_t [ i - 1 ] > 63 )
{
fog_t [ i - 1 ] = fog_t [ i ] - 63 ;
}
}
fog_t [ 0 ] = 0 ;
// for (int f = 0; f < 64; f++)
// {
2016-02-11 09:58:42 +00:00
// WriteTrace(TraceRDP, TraceDebug, "fog[%d]=%d->%f", f, fog_t[f], guFogTableIndexToW(f));
2016-01-20 06:29:27 +00:00
// }
grFogTable ( fog_t ) ;
grVertexLayout ( GR_PARAM_FOG_EXT , offsetof ( VERTEX , f ) , GR_PARAM_ENABLE ) ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
else //not supported
2017-03-09 20:54:56 +00:00
{
g_settings - > SetFog ( FALSE ) ;
}
2016-01-20 06:29:27 +00:00
}
grDepthBufferMode ( GR_DEPTHBUFFER_ZBUFFER ) ;
grDepthBufferFunction ( GR_CMP_LESS ) ;
grDepthMask ( FXTRUE ) ;
ChangeSize ( ) ;
guLoadTextures ( ) ;
ClearCache ( ) ;
grCullMode ( GR_CULL_DISABLE ) ;
grDepthBufferMode ( GR_DEPTHBUFFER_ZBUFFER ) ;
grDepthBufferFunction ( GR_CMP_ALWAYS ) ;
grRenderBuffer ( GR_BUFFER_BACKBUFFER ) ;
grColorMask ( FXTRUE , FXTRUE ) ;
grDepthMask ( FXTRUE ) ;
grBufferClear ( 0 , 0 , 0xFFFF ) ;
grBufferSwap ( 0 ) ;
grBufferClear ( 0 , 0 , 0xFFFF ) ;
grDepthMask ( FXFALSE ) ;
grTexFilterMode ( 0 , GR_TEXTUREFILTER_BILINEAR , GR_TEXTUREFILTER_BILINEAR ) ;
grTexFilterMode ( 1 , GR_TEXTUREFILTER_BILINEAR , GR_TEXTUREFILTER_BILINEAR ) ;
grTexClampMode ( 0 , GR_TEXTURECLAMP_CLAMP , GR_TEXTURECLAMP_CLAMP ) ;
grTexClampMode ( 1 , GR_TEXTURECLAMP_CLAMP , GR_TEXTURECLAMP_CLAMP ) ;
2017-01-31 06:56:52 +00:00
grClipWindow ( 0 , 0 , g_settings - > scr_res_x ( ) , g_settings - > scr_res_y ( ) ) ;
2016-01-20 06:29:27 +00:00
rdp . update | = UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE ;
2013-04-04 21:22:19 +00:00
2016-02-01 08:56:25 +00:00
if ( ! g_settings - > ghq_use )
2013-04-04 21:22:19 +00:00
{
2017-03-09 21:37:26 +00:00
g_settings - > ghq_use = g_settings - > ghq_fltr ( ) ! = CSettings : : TextureFilter_None | | g_settings - > ghq_enht ( ) ! = CSettings : : TextureEnht_None | | g_settings - > ghq_hirs ( ) ! = CSettings : : HiResPackFormat_None ;
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_use )
2016-01-20 06:29:27 +00:00
{
/* Plugin path */
2017-03-09 21:37:26 +00:00
int options = g_settings - > ghq_fltr ( ) | g_settings - > ghq_enht ( ) | g_settings - > ghq_cmpr ( ) | g_settings - > ghq_hirs ( ) ;
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_enht_cmpr )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = COMPRESS_TEX ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_hirs_cmpr )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = COMPRESS_HIRESTEX ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_hirs_tile )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = TILE_HIRESTEX ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_enht_f16bpp )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = FORCE16BPP_TEX ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_hirs_f16bpp )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = FORCE16BPP_HIRESTEX ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_enht_gz )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = GZ_TEXCACHE ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_hirs_gz )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = GZ_HIRESTEXCACHE ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_cache_save )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = ( DUMP_TEXCACHE | DUMP_HIRESTEXCACHE ) ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_hirs_let_texartists_fly )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = LET_TEXARTISTS_FLY ;
2017-01-31 06:56:52 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_hirs_dump )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
options | = DUMP_TEX ;
2017-01-31 06:56:52 +00:00
}
2016-01-20 06:29:27 +00:00
2016-02-01 08:56:25 +00:00
g_settings - > ghq_use = ( int ) ext_ghq_init ( voodoo . max_tex_size , // max texture width supported by hardware
2016-01-20 06:29:27 +00:00
voodoo . max_tex_size , // max texture height supported by hardware
voodoo . sup_32bit_tex ? 32 : 16 , // max texture bpp supported by hardware
options ,
2016-02-01 08:56:25 +00:00
g_settings - > ghq_cache_size * 1024 * 1024 , // cache texture to system memory
2017-03-09 21:12:37 +00:00
g_settings - > texture_dir ( ) ,
2016-01-25 10:34:16 +00:00
rdp . RomName , // name of ROM. must be no longer than 256 characters
2016-01-20 06:29:27 +00:00
DisplayLoadProgress ) ;
}
}
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_use & & strstr ( extensions , " TEXMIRROR " ) )
2017-01-31 06:56:52 +00:00
{
2016-01-20 06:29:27 +00:00
voodoo . sup_mirroring = 1 ;
2017-01-31 06:56:52 +00:00
}
2016-01-20 06:29:27 +00:00
return TRUE ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
void ReleaseGfx ( )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// Restore gamma settings
if ( voodoo . gamma_correction )
{
if ( voodoo . gamma_table_r )
grLoadGammaTable ( voodoo . gamma_table_size , voodoo . gamma_table_r , voodoo . gamma_table_g , voodoo . gamma_table_b ) ;
else
guGammaCorrectionRGB ( 1.3f , 1.3f , 1.3f ) ; //1.3f is default 3dfx gamma for everything but desktop
voodoo . gamma_correction = 0 ;
}
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// Release graphics
grSstWinClose ( gfx_context ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// Shutdown glide
grGlideShutdown ( ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 17:12:15 +00:00
GfxInitDone = FALSE ;
2016-01-20 06:29:27 +00:00
rdp . window_changed = TRUE ;
2013-04-04 21:22:19 +00:00
}
2016-01-25 09:33:04 +00:00
# ifdef _WIN32
CriticalSection * g_ProcessDListCS = NULL ;
2013-04-09 12:02:27 +00:00
2016-01-25 11:00:45 +00:00
extern " C " int WINAPI DllMain ( HINSTANCE hinst , DWORD fdwReason , LPVOID /*lpReserved*/ )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
if ( fdwReason = = DLL_PROCESS_ATTACH )
{
hinstDLL = hinst ;
2016-01-25 09:33:04 +00:00
if ( g_ProcessDListCS = = NULL )
{
g_ProcessDListCS = new CriticalSection ( ) ;
}
2016-03-08 22:22:28 +00:00
ConfigInit ( hinst ) ;
2016-01-20 06:29:27 +00:00
}
else if ( fdwReason = = DLL_PROCESS_DETACH )
{
2016-01-25 09:33:04 +00:00
if ( g_ProcessDListCS )
{
delete g_ProcessDListCS ;
}
2016-03-08 22:22:28 +00:00
ConfigCleanup ( ) ;
2016-01-20 06:29:27 +00:00
}
return TRUE ;
2013-04-04 21:22:19 +00:00
}
# endif
void CALL ReadScreen ( void * * dest , int * width , int * height )
{
2017-01-31 06:56:52 +00:00
* width = g_settings - > res_x ( ) ;
* height = g_settings - > res_y ( ) ;
uint8_t * buff = ( uint8_t * ) malloc ( g_settings - > res_x ( ) * g_settings - > res_y ( ) * 3 ) ;
2016-01-20 06:29:27 +00:00
uint8_t * line = buff ;
* dest = ( void * ) buff ;
GrLfbInfo_t info ;
info . size = sizeof ( GrLfbInfo_t ) ;
if ( grLfbLock ( GR_LFB_READ_ONLY ,
GR_BUFFER_FRONTBUFFER ,
GR_LFBWRITEMODE_565 ,
GR_ORIGIN_UPPER_LEFT ,
FXFALSE ,
& info ) )
2013-04-04 21:22:19 +00:00
{
2017-01-31 06:56:52 +00:00
uint32_t offset_src = info . strideInBytes * ( g_settings - > scr_res_y ( ) - 1 ) ;
2016-01-20 06:29:27 +00:00
// Copy the screen
uint8_t r , g , b ;
if ( info . writeMode = = GR_LFBWRITEMODE_8888 )
{
uint32_t col ;
2017-01-31 06:56:52 +00:00
for ( uint32_t y = 0 ; y < g_settings - > res_y ( ) ; y + + )
2016-01-20 06:29:27 +00:00
{
uint32_t * ptr = ( uint32_t * ) ( ( uint8_t * ) info . lfbPtr + offset_src ) ;
2017-01-31 06:56:52 +00:00
for ( uint32_t x = 0 ; x < g_settings - > res_x ( ) ; x + + )
2016-01-20 06:29:27 +00:00
{
col = * ( ptr + + ) ;
r = ( uint8_t ) ( ( col > > 16 ) & 0xFF ) ;
g = ( uint8_t ) ( ( col > > 8 ) & 0xFF ) ;
b = ( uint8_t ) ( col & 0xFF ) ;
line [ x * 3 ] = b ;
line [ x * 3 + 1 ] = g ;
line [ x * 3 + 2 ] = r ;
}
2017-01-31 06:56:52 +00:00
line + = g_settings - > res_x ( ) * 3 ;
2016-01-20 06:29:27 +00:00
offset_src - = info . strideInBytes ;
}
}
else
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
uint16_t col ;
2017-01-31 06:56:52 +00:00
for ( uint32_t y = 0 ; y < g_settings - > res_y ( ) ; y + + )
2016-01-20 06:29:27 +00:00
{
uint16_t * ptr = ( uint16_t * ) ( ( uint8_t * ) info . lfbPtr + offset_src ) ;
2017-01-31 06:56:52 +00:00
for ( uint32_t x = 0 ; x < g_settings - > res_x ( ) ; x + + )
2016-01-20 06:29:27 +00:00
{
col = * ( ptr + + ) ;
r = ( uint8_t ) ( ( float ) ( col > > 11 ) / 31.0f * 255.0f ) ;
g = ( uint8_t ) ( ( float ) ( ( col > > 5 ) & 0x3F ) / 63.0f * 255.0f ) ;
b = ( uint8_t ) ( ( float ) ( col & 0x1F ) / 31.0f * 255.0f ) ;
line [ x * 3 ] = b ;
line [ x * 3 + 1 ] = g ;
line [ x * 3 + 2 ] = r ;
}
2017-01-31 06:56:52 +00:00
line + = g_settings - > res_x ( ) * 3 ;
2016-01-20 06:29:27 +00:00
offset_src - = info . strideInBytes ;
}
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
// Unlock the frontbuffer
grLfbUnlock ( GR_LFB_READ_ONLY , GR_BUFFER_FRONTBUFFER ) ;
}
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " Success " ) ;
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : CaptureScreen
Purpose : This function dumps the current frame to a file
input : pointer to the directory to save the file to
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
EXPORT void CALL CaptureScreen ( char * Directory )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
capture_screen = 1 ;
2016-01-25 11:00:45 +00:00
capture_path = Directory ;
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : ChangeWindow
Purpose : to change the window between fullscreen and window
mode . If the window was in fullscreen this should
change the screen to window mode and vice vesa .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
EXPORT void CALL ChangeWindow ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
if ( evoodoo )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
if ( ! ev_fullscreen )
{
to_fullscreen = TRUE ;
ev_fullscreen = TRUE ;
}
else
{
ev_fullscreen = FALSE ;
InitGfx ( ) ;
}
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
else
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
// Go to fullscreen at next dlist
// This is for compatibility with 1964, which reloads the plugin
// when switching to fullscreen
2016-01-20 17:12:15 +00:00
if ( ! GfxInitDone )
2016-01-20 06:29:27 +00:00
{
to_fullscreen = TRUE ;
}
else
{
ReleaseGfx ( ) ;
}
2013-04-04 21:22:19 +00:00
}
}
/******************************************************************
Function : CloseDLL
Purpose : This function is called when the emulator is closing
down allowing the dll to de - initialise .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL CloseDLL ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2013-04-04 21:22:19 +00:00
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_use )
2016-01-20 06:29:27 +00:00
{
ext_ghq_shutdown ( ) ;
2016-02-01 08:56:25 +00:00
g_settings - > ghq_use = 0 ;
2016-01-25 07:15:46 +00:00
}
2016-02-01 08:56:25 +00:00
if ( g_settings )
{
delete g_settings ;
g_settings = NULL ;
}
2016-01-20 17:12:15 +00:00
ReleaseGfx ( ) ;
2016-01-20 06:29:27 +00:00
ZLUT_release ( ) ;
ClearCache ( ) ;
delete [ ] voodoo . gamma_table_r ;
voodoo . gamma_table_r = 0 ;
delete [ ] voodoo . gamma_table_g ;
voodoo . gamma_table_g = 0 ;
delete [ ] voodoo . gamma_table_b ;
voodoo . gamma_table_b = 0 ;
2016-02-24 07:07:50 +00:00
}
2013-04-04 21:22:19 +00:00
/******************************************************************
Function : DllTest
Purpose : This function is optional function that is provided
to allow the user to test the dll
input : a handle to the window that calls this function
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL DllTest ( HWND /*hParent*/ )
2013-04-04 21:22:19 +00:00
{
}
/******************************************************************
Function : DrawScreen
Purpose : This function is called when the emulator receives a
WM_PAINT message . This allows the gfx to fit in when
it is being used in the desktop .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL DrawScreen ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : GetDllInfo
Purpose : This function allows the emulator to gather information
about the dll by filling in the PluginInfo structure .
input : a pointer to a PLUGIN_INFO stucture that needs to be
filled by the function . ( see def above )
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
PluginInfo - > Version = 0x0104 ; // Set to 0x0104
PluginInfo - > Type = PLUGIN_TYPE_GFX ; // Set to PLUGIN_TYPE_GFX
2013-04-22 01:11:55 +00:00
# ifdef _DEBUG
2016-01-20 06:29:27 +00:00
sprintf ( PluginInfo - > Name , " Glide64 For PJ64 (Debug): %s " , VER_FILE_VERSION_STR ) ;
2013-04-22 01:11:55 +00:00
# else
2016-01-20 06:29:27 +00:00
sprintf ( PluginInfo - > Name , " Glide64 For PJ64: %s " , VER_FILE_VERSION_STR ) ;
2013-04-22 01:11:55 +00:00
# endif
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// If DLL supports memory these memory options then set them to TRUE or FALSE
// if it does not support it
PluginInfo - > NormalMemory = FALSE ; // a normal uint8_t array
PluginInfo - > MemoryBswaped = TRUE ; // a normal uint8_t array where the memory has been pre
// bswap on a dword (32 bits) boundry
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : InitiateGFX
Purpose : This function is called when the DLL is started to give
information from the emulator that the n64 graphics
uses . This is not called from the emulation thread .
Input : Gfx_Info is passed to this function which is defined
above .
Output : TRUE on success
FALSE on failure to initialise
* * note on interrupts * * :
To generate an interrupt set the appropriate bit in MI_INTR_REG
and then call the function CheckInterrupts to tell the emulator
that there is a waiting interrupt .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
int CALL InitiateGFX ( GFX_INFO Gfx_Info )
2013-04-04 21:22:19 +00:00
{
2016-02-01 08:56:25 +00:00
WriteTrace ( TraceInterface , TraceDebug , " Start " ) ;
2016-01-20 06:29:27 +00:00
voodoo . num_tmu = 2 ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// Assume scale of 1 for debug purposes
rdp . scale_x = 1.0f ;
rdp . scale_y = 1.0f ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
char name [ 21 ] = " DEFAULT " ;
2017-01-24 19:08:33 +00:00
g_settings - > ReadGameSettings ( name ) ;
2017-01-23 18:28:13 +00:00
ZLUT_init ( ) ;
2017-01-23 18:19:46 +00:00
ConfigWrapper ( ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
gfx = Gfx_Info ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
util_init ( ) ;
math_init ( ) ;
TexCacheInit ( ) ;
CRC_BuildTable ( ) ;
CountCombine ( ) ;
2016-05-01 02:43:24 +00:00
ZLUT_init ( ) ;
2013-04-04 21:22:19 +00:00
2017-01-28 11:29:03 +00:00
grConfigWrapperExt ( g_settings - > wrpVRAM * 1024 * 1024 , g_settings - > wrpFBO , g_settings - > wrpAnisotropic ) ;
2016-01-20 06:29:27 +00:00
grGlideInit ( ) ;
const char * extensions = grGetString ( GR_EXTENSION ) ;
grGlideShutdown ( ) ;
if ( strstr ( extensions , " EVOODOO " ) )
{
evoodoo = 1 ;
voodoo . has_2mb_tex_boundary = 0 ;
}
2016-02-01 08:56:25 +00:00
else
{
2016-01-20 06:29:27 +00:00
evoodoo = 0 ;
voodoo . has_2mb_tex_boundary = 1 ;
}
return TRUE ;
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : MoveScreen
Purpose : This function is called in response to the emulator
receiving a WM_MOVE passing the xpos and ypos passed
from that message .
input : xpos - the x - coordinate of the upper - left corner of the
client area of the window .
ypos - y - coordinate of the upper - left corner of the
client area of the window .
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL MoveScreen ( int xpos , int ypos )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
xpos = xpos ;
ypos = ypos ;
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " xpos: %d ypos: %d " , xpos , ypos ) ;
2016-01-20 06:29:27 +00:00
rdp . window_changed = TRUE ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
void CALL PluginLoaded ( void )
2013-04-24 05:03:21 +00:00
{
2017-01-23 06:50:29 +00:00
if ( g_settings = = NULL )
{
g_settings = new CSettings ;
}
2016-02-10 07:10:12 +00:00
SetupTrace ( ) ;
2016-02-01 08:56:25 +00:00
WriteTrace ( TraceInterface , TraceDebug , " Start " ) ;
WriteTrace ( TraceInterface , TraceDebug , " Done " ) ;
2013-04-24 05:03:21 +00:00
}
2016-06-04 06:50:02 +00:00
# ifdef ANDROID
void vbo_disable ( void ) ;
# endif
2013-04-04 21:22:19 +00:00
/******************************************************************
Function : RomClosed
Purpose : This function is called when a rom is closed .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL RomClosed ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2016-01-20 06:29:27 +00:00
2016-06-04 06:50:02 +00:00
# ifdef ANDROID
vbo_disable ( ) ;
# endif
2016-01-20 06:29:27 +00:00
rdp . window_changed = TRUE ;
2016-03-08 06:31:08 +00:00
g_romopen = FALSE ;
2016-01-20 17:12:15 +00:00
if ( evoodoo )
2016-02-11 09:58:42 +00:00
{
2016-01-20 06:29:27 +00:00
ReleaseGfx ( ) ;
2016-02-11 09:58:42 +00:00
}
2013-04-04 21:22:19 +00:00
}
static void CheckDRAMSize ( )
{
2016-01-20 06:29:27 +00:00
uint32_t test ;
GLIDE64_TRY
{
test = gfx . RDRAM [ 0x007FFFFF ] + 1 ;
}
2016-02-24 07:07:50 +00:00
GLIDE64_CATCH
2016-01-20 06:29:27 +00:00
{
test = 0 ;
}
2016-02-24 07:07:50 +00:00
if ( test )
BMASK = 0x7FFFFF ;
else
BMASK = WMASK ;
2013-04-04 21:22:19 +00:00
# ifdef LOGGING
2016-02-11 09:58:42 +00:00
sprintf ( out_buf , " Detected RDRAM size: %08lx " , BMASK ) ;
2016-01-20 06:29:27 +00:00
LOG ( out_buf ) ;
2013-04-04 21:22:19 +00:00
# endif
2016-01-20 17:12:15 +00:00
}
2013-04-04 21:22:19 +00:00
/******************************************************************
Function : RomOpen
Purpose : This function is called when a rom is open . ( from the
emulation thread )
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL RomOpen ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2016-01-20 06:29:27 +00:00
no_dlist = true ;
2016-03-08 06:31:08 +00:00
g_romopen = TRUE ;
2017-01-30 17:34:36 +00:00
g_ucode_error_report = TRUE ; // allowed to report ucode errors
2016-01-20 06:29:27 +00:00
rdp_reset ( ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
// Get the country code & translate to NTSC(0) or PAL(1)
uint16_t code = ( ( uint16_t * ) gfx . HEADER ) [ 0x1F ^ 1 ] ;
if ( code = = 0x4400 ) region = 1 ; // Germany (PAL)
if ( code = = 0x4500 ) region = 0 ; // USA (NTSC)
if ( code = = 0x4A00 ) region = 0 ; // Japan (NTSC)
if ( code = = 0x5000 ) region = 1 ; // Europe (PAL)
if ( code = = 0x5500 ) region = 0 ; // Australia (NTSC)
// get the name of the ROM
2016-03-08 21:55:19 +00:00
char name [ 21 ] ;
2016-01-20 06:29:27 +00:00
for ( int i = 0 ; i < 20 ; i + + )
{
char ch ;
const char invalid_ch = ' ? ' ; /* Some Japanese games use wide chars. */
ch = ( char ) gfx . HEADER [ ( 32 + i ) ^ 3 ] ;
if ( ch = = ' \0 ' )
ch = ' ' ;
if ( ch < ' ' )
ch = invalid_ch ;
if ( ch > ' ~ ' )
ch = invalid_ch ;
name [ i ] = ch ;
}
name [ 20 ] = ' \0 ' ;
// remove all trailing spaces
while ( name [ strlen ( name ) - 1 ] = = ' ' )
2016-01-25 10:34:16 +00:00
{
2016-01-20 06:29:27 +00:00
name [ strlen ( name ) - 1 ] = 0 ;
2016-01-25 10:34:16 +00:00
}
2016-01-20 06:29:27 +00:00
2016-02-01 08:56:25 +00:00
if ( g_settings - > ghq_use & & strcmp ( rdp . RomName , name ) ! = 0 )
2016-01-20 06:29:27 +00:00
{
ext_ghq_shutdown ( ) ;
2016-02-01 08:56:25 +00:00
g_settings - > ghq_use = 0 ;
2016-01-20 06:29:27 +00:00
}
2016-01-25 10:34:16 +00:00
strcpy ( rdp . RomName , name ) ;
2017-01-24 19:08:33 +00:00
g_settings - > ReadGameSettings ( name ) ;
2016-01-20 06:29:27 +00:00
ClearCache ( ) ;
CheckDRAMSize ( ) ;
// ** EVOODOO EXTENSIONS **
2016-01-20 17:12:15 +00:00
if ( ! GfxInitDone )
2016-01-20 06:29:27 +00:00
{
grGlideInit ( ) ;
}
const char * extensions = grGetString ( GR_EXTENSION ) ;
2016-01-20 17:12:15 +00:00
grGlideShutdown ( ) ;
2016-01-20 06:29:27 +00:00
2016-01-20 17:12:15 +00:00
if ( strstr ( extensions , " EVOODOO " ) )
evoodoo = 1 ;
else
evoodoo = 0 ;
2016-01-20 06:29:27 +00:00
2016-01-20 17:12:15 +00:00
if ( evoodoo )
InitGfx ( ) ;
2016-01-20 06:29:27 +00:00
if ( strstr ( extensions , " ROMNAME " ) )
{
char strSetRomName [ ] = " grSetRomName " ;
void ( FX_CALL * grSetRomName ) ( char * ) ;
grSetRomName = ( void ( FX_CALL * ) ( char * ) ) grGetProcAddress ( strSetRomName ) ;
grSetRomName ( name ) ;
}
// **
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : ShowCFB
Purpose : Useally once Dlists are started being displayed , cfb is
ignored . This function tells the dll to start displaying
them again .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool no_dlist = true ;
2016-01-20 06:29:27 +00:00
void CALL ShowCFB ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " - " ) ;
2016-01-20 06:29:27 +00:00
no_dlist = true ;
2013-04-04 21:22:19 +00:00
}
void drawViRegBG ( )
{
2016-03-08 21:55:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " start " ) ;
2016-01-20 06:29:27 +00:00
const uint32_t VIwidth = * gfx . VI_WIDTH_REG ;
FB_TO_SCREEN_INFO fb_info ;
fb_info . width = VIwidth ;
fb_info . height = ( uint32_t ) rdp . vi_height ;
if ( fb_info . height = = 0 )
{
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " Image height = 0 - skipping " ) ;
2016-01-20 06:29:27 +00:00
return ;
}
fb_info . ul_x = 0 ;
fb_info . lr_x = VIwidth - 1 ;
// fb_info.lr_x = (uint32_t)rdp.vi_width - 1;
fb_info . ul_y = 0 ;
fb_info . lr_y = fb_info . height - 1 ;
fb_info . opaque = 1 ;
fb_info . addr = * gfx . VI_ORIGIN_REG ;
fb_info . size = * gfx . VI_STATUS_REG & 3 ;
rdp . last_bg = fb_info . addr ;
bool drawn = DrawFrameBufferToScreen ( fb_info ) ;
2017-01-29 06:26:41 +00:00
if ( g_settings - > hacks ( CSettings : : hack_Lego ) & & drawn )
2016-01-20 06:29:27 +00:00
{
rdp . updatescreen = 1 ;
newSwapBuffers ( ) ;
DrawFrameBufferToScreen ( fb_info ) ;
}
2016-03-08 21:55:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " done " ) ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
static void DrawFrameBuffer ( )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
if ( to_fullscreen )
GoToFullScreen ( ) ;
2016-01-20 17:12:15 +00:00
grDepthMask ( FXTRUE ) ;
grColorMask ( FXTRUE , FXTRUE ) ;
grBufferClear ( 0 , 0 , 0xFFFF ) ;
drawViRegBG ( ) ;
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : UpdateScreen
Purpose : This function is called in response to a vsync of the
screen were the VI bit in MI_INTR_REG has already been
set
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:14:48 +00:00
uint32_t update_screen_count = 0 ;
2016-01-20 06:29:27 +00:00
void CALL UpdateScreen ( void )
2013-04-04 21:22:19 +00:00
{
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " Origin: %08x, Old origin: %08x, width: %d " , * gfx . VI_ORIGIN_REG , rdp . vi_org_reg , * gfx . VI_WIDTH_REG ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
uint32_t width = ( * gfx . VI_WIDTH_REG ) < < 1 ;
2016-01-20 17:12:15 +00:00
if ( * gfx . VI_ORIGIN_REG > width )
{
2016-01-20 06:29:27 +00:00
update_screen_count + + ;
2016-01-20 17:12:15 +00:00
}
2017-01-29 06:26:41 +00:00
uint32_t limit = g_settings - > hacks ( CSettings : : hack_Lego ) ? 15 : 30 ;
2017-01-24 19:08:33 +00:00
if ( g_settings - > fb_cpu_write_hack_enabled ( ) & & ( update_screen_count > limit ) & & ( rdp . last_bg = = 0 ) )
2016-01-20 06:29:27 +00:00
{
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DirectCPUWrite hack! " ) ;
2016-01-20 06:29:27 +00:00
update_screen_count = 0 ;
no_dlist = true ;
ClearCache ( ) ;
UpdateScreen ( ) ;
return ;
}
if ( no_dlist )
2013-04-04 21:22:19 +00:00
{
2016-01-20 06:29:27 +00:00
if ( * gfx . VI_ORIGIN_REG > width )
{
ChangeSize ( ) ;
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " ChangeSize done " ) ;
2016-01-20 06:29:27 +00:00
DrawFrameBuffer ( ) ;
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawFrameBuffer done " ) ;
2016-01-20 06:29:27 +00:00
rdp . updatescreen = 1 ;
newSwapBuffers ( ) ;
}
return ;
}
2017-01-29 18:05:06 +00:00
if ( g_settings - > swapmode ( ) = = CSettings : : SwapMode_Old )
{
2016-01-20 06:29:27 +00:00
newSwapBuffers ( ) ;
2017-01-29 18:05:06 +00:00
}
2013-04-04 21:22:19 +00:00
}
static void DrawWholeFrameBufferToScreen ( )
{
2016-01-20 06:29:27 +00:00
static uint32_t toScreenCI = 0 ;
if ( rdp . ci_width < 200 )
2017-01-29 18:05:06 +00:00
{
2016-01-20 06:29:27 +00:00
return ;
2017-01-29 18:05:06 +00:00
}
2016-01-20 06:29:27 +00:00
if ( rdp . cimg = = toScreenCI )
2017-01-29 18:05:06 +00:00
{
2016-01-20 06:29:27 +00:00
return ;
2017-01-29 18:05:06 +00:00
}
2016-01-20 06:29:27 +00:00
toScreenCI = rdp . cimg ;
FB_TO_SCREEN_INFO fb_info ;
fb_info . addr = rdp . cimg ;
fb_info . size = rdp . ci_size ;
fb_info . width = rdp . ci_width ;
fb_info . height = rdp . ci_height ;
if ( fb_info . height = = 0 )
2017-01-29 18:05:06 +00:00
{
2016-01-20 06:29:27 +00:00
return ;
2017-01-29 18:05:06 +00:00
}
2016-01-20 06:29:27 +00:00
fb_info . ul_x = 0 ;
fb_info . lr_x = rdp . ci_width - 1 ;
fb_info . ul_y = 0 ;
fb_info . lr_y = rdp . ci_height - 1 ;
fb_info . opaque = 0 ;
DrawFrameBufferToScreen ( fb_info ) ;
2017-01-24 19:08:33 +00:00
if ( ! g_settings - > fb_ref_enabled ( ) )
{
2016-01-20 06:29:27 +00:00
memset ( gfx . RDRAM + rdp . cimg , 0 , ( rdp . ci_width * rdp . ci_height ) < < rdp . ci_size > > 1 ) ;
2017-01-24 19:08:33 +00:00
}
2013-04-04 21:22:19 +00:00
}
static void GetGammaTable ( )
{
2016-01-20 06:29:27 +00:00
char strGetGammaTableExt [ ] = " grGetGammaTableExt " ;
void ( FX_CALL * grGetGammaTableExt ) ( FxU32 , FxU32 * , FxU32 * , FxU32 * ) =
( void ( FX_CALL * ) ( FxU32 , FxU32 * , FxU32 * , FxU32 * ) ) grGetProcAddress ( strGetGammaTableExt ) ;
if ( grGetGammaTableExt )
{
voodoo . gamma_table_r = new FxU32 [ voodoo . gamma_table_size ] ;
voodoo . gamma_table_g = new FxU32 [ voodoo . gamma_table_size ] ;
voodoo . gamma_table_b = new FxU32 [ voodoo . gamma_table_size ] ;
grGetGammaTableExt ( voodoo . gamma_table_size , voodoo . gamma_table_r , voodoo . gamma_table_g , voodoo . gamma_table_b ) ;
}
2013-04-04 21:22:19 +00:00
}
2016-02-24 10:55:42 +00:00
void write_png_file ( const char * file_name , int width , int height , uint8_t * buffer )
{
/* create file */
FILE * fp = fopen ( file_name , " wb " ) ;
if ( ! fp )
{
WriteTrace ( TracePNG , TraceError , " File %s could not be opened for writing " , file_name ) ;
return ;
}
/* initialize stuff */
png_structp png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING , NULL , NULL , NULL ) ;
if ( png_ptr = = NULL )
{
WriteTrace ( TracePNG , TraceError , " png_create_write_struct failed " ) ;
fclose ( fp ) ;
return ;
}
png_infop info_ptr = png_create_info_struct ( png_ptr ) ;
if ( info_ptr = = NULL )
{
WriteTrace ( TracePNG , TraceError , " png_create_info_struct failed " ) ;
png_destroy_read_struct ( & png_ptr , NULL , NULL ) ;
fclose ( fp ) ;
return ;
}
if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
{
WriteTrace ( TracePNG , TraceError , " Error during init_io " ) ;
png_destroy_read_struct ( & png_ptr , & info_ptr , NULL ) ;
fclose ( fp ) ;
return ;
}
png_init_io ( png_ptr , fp ) ;
/* write header */
if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
{
WriteTrace ( TracePNG , TraceError , " Error during writing header " ) ;
png_destroy_read_struct ( & png_ptr , & info_ptr , NULL ) ;
fclose ( fp ) ;
return ;
}
png_byte bit_depth = 8 ;
png_byte color_type = PNG_COLOR_TYPE_RGB ;
png_set_IHDR ( png_ptr , info_ptr , width , height , bit_depth , color_type , PNG_INTERLACE_NONE , PNG_COMPRESSION_TYPE_BASE , PNG_FILTER_TYPE_BASE ) ;
png_write_info ( png_ptr , info_ptr ) ;
/* write bytes */
if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
{
WriteTrace ( TracePNG , TraceError , " Error during writing bytes " ) ;
png_destroy_read_struct ( & png_ptr , & info_ptr , NULL ) ;
fclose ( fp ) ;
return ;
}
int pixel_size = 3 ;
int p = 0 ;
2016-03-08 21:55:19 +00:00
png_bytep * row_pointers = ( png_bytep * ) malloc ( sizeof ( png_bytep ) * height ) ;
2016-02-24 10:55:42 +00:00
for ( int y = 0 ; y < height ; y + + )
{
row_pointers [ y ] = ( png_byte * ) malloc ( width * pixel_size ) ;
for ( int x = 0 ; x < width ; x + + )
{
row_pointers [ y ] [ x * pixel_size + 0 ] = buffer [ p + + ] ;
row_pointers [ y ] [ x * pixel_size + 1 ] = buffer [ p + + ] ;
row_pointers [ y ] [ x * pixel_size + 2 ] = buffer [ p + + ] ;
}
}
png_write_image ( png_ptr , row_pointers ) ;
// cleanup heap allocation
for ( int y = 0 ; y < height ; y + + )
{
free ( row_pointers [ y ] ) ;
}
free ( row_pointers ) ;
/* end write */
if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
{
WriteTrace ( TracePNG , TraceError , " Error during end of write " ) ;
png_destroy_read_struct ( & png_ptr , & info_ptr , NULL ) ;
fclose ( fp ) ;
return ;
}
png_write_end ( png_ptr , NULL ) ;
fclose ( fp ) ;
}
2016-01-20 06:14:48 +00:00
uint32_t curframe = 0 ;
2013-04-04 21:22:19 +00:00
void newSwapBuffers ( )
{
2016-01-20 06:29:27 +00:00
if ( ! rdp . updatescreen )
return ;
2013-04-04 21:22:19 +00:00
2016-01-20 06:29:27 +00:00
rdp . updatescreen = 0 ;
2013-04-04 21:22:19 +00:00
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " swapped " ) ;
2013-04-04 21:22:19 +00:00
2016-01-20 17:12:15 +00:00
rdp . update | = UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE ;
2017-01-31 06:56:52 +00:00
grClipWindow ( 0 , 0 , g_settings - > scr_res_x ( ) , g_settings - > scr_res_y ( ) ) ;
2016-01-20 17:12:15 +00:00
grDepthBufferFunction ( GR_CMP_ALWAYS ) ;
grDepthMask ( FXFALSE ) ;
grCullMode ( GR_CULL_DISABLE ) ;
2016-01-20 06:29:27 +00:00
if ( capture_screen )
2013-04-04 21:22:19 +00:00
{
2016-01-25 11:00:45 +00:00
CPath path ( capture_path ) ;
if ( ! path . DirectoryExists ( ) )
{
path . DirectoryCreate ( ) ;
}
stdstr romName = rdp . RomName ;
romName . Replace ( " " , " _ " ) ;
romName . Replace ( " : " , " ; " ) ;
2016-01-20 06:29:27 +00:00
for ( int i = 1 ; ; i + + )
2013-04-04 21:22:19 +00:00
{
2017-01-28 19:11:28 +00:00
stdstr_f filename ( " Glide64_%s_%s%d.png " , romName . c_str ( ) , i < 10 ? " 0 " : " " , i ) ;
2016-01-25 11:00:45 +00:00
path . SetNameExtension ( filename . c_str ( ) ) ;
if ( ! path . Exists ( ) )
{
2016-01-20 06:29:27 +00:00
break ;
2016-01-25 11:00:45 +00:00
}
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
const uint32_t offset_x = ( uint32_t ) rdp . offset_x ;
const uint32_t offset_y = ( uint32_t ) rdp . offset_y ;
2017-01-31 06:56:52 +00:00
const uint32_t image_width = g_settings - > scr_res_x ( ) - offset_x * 2 ;
const uint32_t image_height = g_settings - > scr_res_y ( ) - offset_y * 2 ;
2016-01-20 06:29:27 +00:00
GrLfbInfo_t info ;
info . size = sizeof ( GrLfbInfo_t ) ;
2016-01-25 11:00:45 +00:00
if ( grLfbLock ( GR_LFB_READ_ONLY , GR_BUFFER_BACKBUFFER , GR_LFBWRITEMODE_565 , GR_ORIGIN_UPPER_LEFT , FXFALSE , & info ) )
2013-04-04 21:22:19 +00:00
{
2016-10-09 09:44:31 +00:00
AUTO_PTR < uint8_t > ssimg_buffer ( new uint8_t [ image_width * image_height * 3 ] ) ;
2016-02-24 10:55:42 +00:00
uint8_t * ssimg = ssimg_buffer . get ( ) ;
2016-01-20 06:29:27 +00:00
int sspos = 0 ;
uint32_t offset_src = info . strideInBytes * offset_y ;
// Copy the screen
if ( info . writeMode = = GR_LFBWRITEMODE_8888 )
{
uint32_t col ;
for ( uint32_t y = 0 ; y < image_height ; y + + )
{
uint32_t * ptr = ( uint32_t * ) ( ( uint8_t * ) info . lfbPtr + offset_src ) ;
ptr + = offset_x ;
for ( uint32_t x = 0 ; x < image_width ; x + + )
{
col = * ( ptr + + ) ;
ssimg [ sspos + + ] = ( uint8_t ) ( ( col > > 16 ) & 0xFF ) ;
ssimg [ sspos + + ] = ( uint8_t ) ( ( col > > 8 ) & 0xFF ) ;
ssimg [ sspos + + ] = ( uint8_t ) ( col & 0xFF ) ;
}
offset_src + = info . strideInBytes ;
}
}
else
{
uint16_t col ;
for ( uint32_t y = 0 ; y < image_height ; y + + )
{
uint16_t * ptr = ( uint16_t * ) ( ( uint8_t * ) info . lfbPtr + offset_src ) ;
ptr + = offset_x ;
for ( uint32_t x = 0 ; x < image_width ; x + + )
{
col = * ( ptr + + ) ;
ssimg [ sspos + + ] = ( uint8_t ) ( ( float ) ( col > > 11 ) / 31.0f * 255.0f ) ;
ssimg [ sspos + + ] = ( uint8_t ) ( ( float ) ( ( col > > 5 ) & 0x3F ) / 63.0f * 255.0f ) ;
ssimg [ sspos + + ] = ( uint8_t ) ( ( float ) ( col & 0x1F ) / 31.0f * 255.0f ) ;
}
offset_src + = info . strideInBytes ;
}
}
// Unlock the backbuffer
grLfbUnlock ( GR_LFB_READ_ONLY , GR_BUFFER_BACKBUFFER ) ;
2017-01-28 19:11:28 +00:00
write_png_file ( path , image_width , image_height , ssimg ) ;
2016-01-20 06:29:27 +00:00
capture_screen = 0 ;
2013-04-04 21:22:19 +00:00
}
2016-01-20 06:29:27 +00:00
}
2013-04-04 21:22:19 +00:00
2017-01-24 19:08:33 +00:00
if ( g_settings - > fb_read_back_to_screen_enabled ( ) )
{
2016-01-20 06:29:27 +00:00
DrawWholeFrameBufferToScreen ( ) ;
2017-01-24 19:08:33 +00:00
}
2016-01-20 06:29:27 +00:00
2017-01-29 06:26:41 +00:00
if ( g_settings - > fb_hwfbe_enabled ( ) & & ! g_settings - > hacks ( CSettings : : hack_RE2 ) & & ! evoodoo )
2017-01-24 19:08:33 +00:00
{
2016-01-20 17:12:15 +00:00
grAuxBufferExt ( GR_BUFFER_AUXBUFFER ) ;
2017-01-24 19:08:33 +00:00
}
2016-02-04 10:22:19 +00:00
WriteTrace ( TraceGlide64 , TraceDebug , " BUFFER SWAPPED " ) ;
2017-03-09 07:13:25 +00:00
grBufferSwap ( g_settings - > vsync ( ) ) ;
2016-01-20 17:12:15 +00:00
if ( * gfx . VI_STATUS_REG & 0x08 ) //gamma correction is used
2013-04-04 21:22:19 +00:00
{
2016-01-20 17:12:15 +00:00
if ( ! voodoo . gamma_correction )
2016-01-20 06:29:27 +00:00
{
2016-01-20 17:12:15 +00:00
if ( voodoo . gamma_table_size & & ! voodoo . gamma_table_r )
GetGammaTable ( ) ; //save initial gamma tables
guGammaCorrectionRGB ( 2.0f , 2.0f , 2.0f ) ; //with gamma=2.0 gamma table is the same, as in N64
voodoo . gamma_correction = 1 ;
2016-01-20 06:29:27 +00:00
}
2016-01-20 17:12:15 +00:00
}
else
{
if ( voodoo . gamma_correction )
2016-01-20 06:29:27 +00:00
{
2016-01-20 17:12:15 +00:00
if ( voodoo . gamma_table_r )
grLoadGammaTable ( voodoo . gamma_table_size , voodoo . gamma_table_r , voodoo . gamma_table_g , voodoo . gamma_table_b ) ;
else
guGammaCorrectionRGB ( 1.3f , 1.3f , 1.3f ) ; //1.3f is default 3dfx gamma for everything but desktop
voodoo . gamma_correction = 0 ;
2016-01-20 06:29:27 +00:00
}
2013-04-04 21:22:19 +00:00
}
2017-03-09 21:06:58 +00:00
if ( g_settings - > wireframe | | g_settings - > buff_clear ( ) | | ( g_settings - > hacks ( CSettings : : hack_PPL ) & & g_settings - > ucode ( ) = = CSettings : : ucode_S2DEX ) )
2013-04-04 21:22:19 +00:00
{
2017-01-29 06:26:41 +00:00
grDepthMask ( ( g_settings - > hacks ( CSettings : : hack_RE2 ) & & g_settings - > fb_depth_render_enabled ( ) ) ? FXFALSE : FXTRUE ) ;
2016-01-20 17:12:15 +00:00
grBufferClear ( 0 , 0 , 0xFFFF ) ;
}
2013-04-04 21:22:19 +00:00
2017-01-24 19:08:33 +00:00
if ( g_settings - > fb_read_back_to_screen2_enabled ( ) )
2016-01-20 17:12:15 +00:00
{
2016-01-20 06:29:27 +00:00
DrawWholeFrameBufferToScreen ( ) ;
2016-01-20 17:12:15 +00:00
}
2016-01-20 06:29:27 +00:00
frame_count + + ;
2013-04-04 21:22:19 +00:00
}
/******************************************************************
Function : ViStatusChanged
Purpose : This function is called to notify the dll that the
ViStatus registers value has been changed .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL ViStatusChanged ( void )
2013-04-04 21:22:19 +00:00
{
}
/******************************************************************
Function : ViWidthChanged
Purpose : This function is called to notify the dll that the
ViWidth registers value has been changed .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-20 06:29:27 +00:00
void CALL ViWidthChanged ( void )
2013-04-04 21:22:19 +00:00
{
}
2016-03-10 18:29:41 +00:00
# ifdef ANDROID
/******************************************************************
Function : SurfaceCreated
Purpose : this function is called when the surface is created .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void CALL SurfaceCreated ( void )
{
}
/******************************************************************
Function : SurfaceChanged
Purpose : this function is called when the surface is has changed .
input : none
output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void CALL SurfaceChanged ( int width , int height )
{
2017-02-08 19:08:06 +00:00
g_NativeWidth = width ;
g_NativeHeight = height ;
2016-03-10 18:29:41 +00:00
}
void Android_JNI_SwapWindow ( )
{
gfx . SwapBuffers ( ) ;
}
2016-12-01 07:25:11 +00:00
# endif