thug/Code/Gfx/XBox/NX/nx_init.cpp

473 lines
17 KiB
C++
Raw Permalink Normal View History

2016-02-13 21:39:12 +00:00
#include <xtl.h>
// Include the following two files for detailed timing data collection.
//#include <xbdm.h>
//#include <d3d8perf.h>
#include "sys/config/config.h"
#include "nx_init.h"
#include "anim.h"
#include "chars.h"
#include "scene.h"
#include "render.h"
#include "instance.h"
#include "gamma.h"
#include "grass.h"
namespace NxXbox
{
sEngineGlobals EngineGlobals;
/******************************************************************/
/* */
/* */
/******************************************************************/
void InitialiseRenderstates( void )
{
D3DDevice_SetRenderState( D3DRS_LOCALVIEWER, FALSE );
D3DDevice_SetRenderState( D3DRS_COLORVERTEX, FALSE );
EngineGlobals.lighting_enabled = false;
D3DDevice_SetRenderState( D3DRS_LIGHTING, FALSE );
EngineGlobals.specular_enabled = 0;
D3DDevice_SetRenderState( D3DRS_SPECULARENABLE, FALSE );
EngineGlobals.cull_mode = D3DCULL_CW;
D3DDevice_SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
EngineGlobals.allow_envmapping = true;
EngineGlobals.dither_enable = TRUE;
D3DDevice_SetRenderState( D3DRS_DITHERENABLE, TRUE );
EngineGlobals.z_test_enabled = TRUE;
D3DDevice_SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
EngineGlobals.z_write_enabled = TRUE;
D3DDevice_SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
EngineGlobals.alpha_blend_enable = 1;
D3DDevice_SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
EngineGlobals.alpha_test_enable = 1;
D3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
D3DDevice_SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
EngineGlobals.alpha_ref = 0;
D3DDevice_SetRenderState( D3DRS_ALPHAREF, 0x00 );
for( int stage = 0; stage < 4; ++stage )
{
EngineGlobals.uv_addressing[stage] = 0x00000000UL;
EngineGlobals.mip_map_lod_bias[stage] = 0x00000000UL;
EngineGlobals.p_texture[stage] = NULL;
EngineGlobals.min_mag_filter[stage] = 0x00010000UL;
EngineGlobals.color_sign[stage] = 0x00000000UL;
D3DDevice_SetTextureStageState( stage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
D3DDevice_SetTextureStageState( stage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
if( stage == 0 )
{
// If we are running in 720p or 1080i mode, need max pixel pushing power - avoid anisotropic filtering.
// MSM PERFCHANGE
if( EngineGlobals.backbuffer_height > 480 )
{
D3DDevice_SetTextureStageState( stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
}
else
{
D3DDevice_SetTextureStageState( stage, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC );
D3DDevice_SetTextureStageState( stage, D3DTSS_MAXANISOTROPY, 3 );
}
}
else
{
D3DDevice_SetTextureStageState( stage, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
}
D3DDevice_SetTextureStageState( stage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
D3DDevice_SetTextureStageState( stage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
}
// Set up material for specular properties for fixed function pipeline.
D3DMATERIAL8 test_mat;
ZeroMemory( &test_mat, sizeof( D3DMATERIAL8 ));
D3DDevice_SetMaterial( &test_mat );
D3DDevice_SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );
D3DDevice_SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL );
D3DDevice_SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1 );
D3DDevice_SetRenderState( D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL );
// Set these up so they will get reset first time through.
EngineGlobals.blend_mode_value = 0xDEADBABE;
EngineGlobals.blend_op = 0xDEADBABE;
EngineGlobals.src_blend = 0xDEADBABE;
EngineGlobals.dest_blend = 0xDEADBABE;
EngineGlobals.screenshot_name[0] = 0;
// Build the required vertex shaders.
CreateWeightedMeshVertexShaders();
// Build required pixel shaders.
create_pixel_shaders();
// Set pixel shader constants.
EngineGlobals.pixel_shader_constants[16] = 0.0f;
EngineGlobals.pixel_shader_constants[17] = 0.5f;
EngineGlobals.pixel_shader_constants[18] = 0.0f; // Fog denisty.
EngineGlobals.pixel_shader_constants[19] = 0.5f; // Constant 0.5
EngineGlobals.pixel_shader_override = 0;
EngineGlobals.pixel_shader_id = 0;
EngineGlobals.upload_pixel_shader_constants = false;
EngineGlobals.is_orthographic = false;
EngineGlobals.custom_pipeline_enabled = false;
EngineGlobals.vertex_shader_override = 0;
EngineGlobals.texture_stage_override = 0;
EngineGlobals.material_override = 0;
EngineGlobals.blend_mode_override = 0;
EngineGlobals.clear_color_buffer = true;
EngineGlobals.clear_color = 0x00506070;
EngineGlobals.letterbox_active = false;
// Set default directional lights
EngineGlobals.directional_light_color[0] = -0.5f; // Dir0
EngineGlobals.directional_light_color[1] = -0.8660254f;
EngineGlobals.directional_light_color[2] = 0.0f;
EngineGlobals.directional_light_color[3] = 0.0f;
EngineGlobals.directional_light_color[4] = 0.586f; // Col0
EngineGlobals.directional_light_color[5] = 0.586f;
EngineGlobals.directional_light_color[6] = 0.586f;
EngineGlobals.directional_light_color[7] = 1.0f;
EngineGlobals.directional_light_color[8] = 1.0f; // Dir1
EngineGlobals.directional_light_color[9] = 0.0f;
EngineGlobals.directional_light_color[10] = 0.0f;
EngineGlobals.directional_light_color[11] = 0.0f;
EngineGlobals.directional_light_color[12] = 0.0f; // Col1
EngineGlobals.directional_light_color[13] = 0.0f;
EngineGlobals.directional_light_color[14] = 0.0f;
EngineGlobals.directional_light_color[15] = 1.0f;
EngineGlobals.directional_light_color[16] = 1.0f; // Dir2
EngineGlobals.directional_light_color[17] = 0.0f;
EngineGlobals.directional_light_color[18] = 0.0f;
EngineGlobals.directional_light_color[19] = 0.0f;
EngineGlobals.directional_light_color[20] = 0.0f; // Col2
EngineGlobals.directional_light_color[21] = 0.0f;
EngineGlobals.directional_light_color[22] = 0.0f;
EngineGlobals.directional_light_color[23] = 1.0f;
// Set default ambient light.
EngineGlobals.ambient_light_color[0] = 0.5865f;
EngineGlobals.ambient_light_color[1] = 0.5865f;
EngineGlobals.ambient_light_color[2] = 0.5865f;
EngineGlobals.ambient_light_color[3] = 1.0f;
EngineGlobals.fog_enabled = false;
EngineGlobals.fog_color = 0x00000000UL;
EngineGlobals.fog_start = FEET_TO_INCHES( -20.0f );
EngineGlobals.fog_end = FEET_TO_INCHES( -2050.0f );
D3DDevice_SetRenderState( D3DRS_FOGENABLE, EngineGlobals.fog_enabled );
D3DDevice_SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_LINEAR );
// D3DDevice_SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_EXP );
// D3DDevice_SetRenderState( D3DRS_FOGSTART, *((DWORD*)( &EngineGlobals.fog_start )));
// D3DDevice_SetRenderState( D3DRS_FOGEND, *((DWORD*)( &EngineGlobals.fog_end )));
D3DDevice_SetRenderState( D3DRS_FOGCOLOR, EngineGlobals.fog_color );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void InitialiseEngine( void )
{
D3DPRESENT_PARAMETERS params;
DWORD video_flags = XGetVideoFlags();
EngineGlobals.loadingbar_timer_event = 0;
// Setup default values for the screen conversion macro.
EngineGlobals.screen_conv_x_multiplier = 640.0f / 640.0f;
EngineGlobals.screen_conv_y_multiplier = 480.0f / 480.0f;
EngineGlobals.screen_conv_x_offset = 0;
EngineGlobals.screen_conv_y_offset = 16;
ZeroMemory( &params, sizeof( D3DPRESENT_PARAMETERS ));
// This setting required for any multisample presentation.
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
// Let D3D create the depth-stencil buffer for us.
params.EnableAutoDepthStencil = TRUE;
// Select default refresh rate and presentation interval. Note: When we switch to the December SDK
// we can use the ONE_OR_IMMEDIATE value (if the tearing looks okay).
if(( Config::GetDisplayType() == Config::DISPLAY_TYPE_PAL ) && ( Config::FPS() == 60 ))
{
// PAL 60Hz has been selected - need to set this refresh rate explicitly.
params.FullScreen_RefreshRateInHz = 60;
}
else
{
params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
}
// params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE_OR_IMMEDIATE;
// params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// Set up the back buffer format.
params.BackBufferCount = 1;
params.BackBufferWidth = 640;
params.BackBufferHeight = 480;
params.BackBufferFormat = D3DFMT_LIN_X8R8G8B8;
// Set up the Z-stencil buffer format and multisample format.
params.AutoDepthStencilFormat = D3DFMT_D24S8;
// params.MultiSampleType = D3DMULTISAMPLE_NONE;
params.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR;
// params.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_QUINCUNX;
// params.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_LINEAR;
// Set flag for widescreen where appropriate.
if( video_flags & XC_VIDEO_FLAGS_WIDESCREEN )
{
params.Flags |= D3DPRESENTFLAG_WIDESCREEN;
// Optionally set up 720<32>480 back buffer.
// Set up 16:9 projection transform.
}
// Set flag for progrssive scan where appropriate.
if( video_flags & XC_VIDEO_FLAGS_HDTV_720p )
{
params.Flags |= D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN;
params.BackBufferWidth = 1280;
params.BackBufferHeight = 720;
// Turn off FSAA.
params.MultiSampleType = D3DMULTISAMPLE_NONE;
EngineGlobals.screen_conv_x_multiplier = 1280.0f / 704.0f;
EngineGlobals.screen_conv_y_multiplier = 720.0f / 480.0f;
EngineGlobals.screen_conv_x_offset = 32;
EngineGlobals.screen_conv_y_offset = 32;
}
else if( video_flags & XC_VIDEO_FLAGS_HDTV_480p )
{
params.Flags |= D3DPRESENTFLAG_PROGRESSIVE;
}
// else if( video_flags & XC_VIDEO_FLAGS_HDTV_1080i )
// {
// params.Flags |= D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN | D3DPRESENTFLAG_FIELD;
// params.BackBufferWidth = 1920;
// params.BackBufferHeight = 540;
// params.BackBufferFormat = D3DFMT_LIN_R5G6B5;
// params.AutoDepthStencilFormat = D3DFMT_D16;
// params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_TWO;
//
// // Turn off FSAA.
// params.MultiSampleType = D3DMULTISAMPLE_NONE;
//
// EngineGlobals.screen_conv_x_multiplier = 1920.0f / 704.0f;
// EngineGlobals.screen_conv_y_multiplier = 1080.0f / 480.0f;
// EngineGlobals.screen_conv_x_offset = 32;
// EngineGlobals.screen_conv_y_offset = 16;
// }
else
{
params.Flags |= D3DPRESENTFLAG_INTERLACED;
}
if( params.BackBufferWidth == 640 )
{
params.Flags |= D3DPRESENTFLAG_10X11PIXELASPECTRATIO;
}
// The default push buffer size is 512k. Double this to reduce stalls from filling the push buffer.
Direct3D_SetPushBufferSize( 2 * 512 * 1024, 32 * 1024 );
if( D3D_OK != Direct3D_CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
NULL,
D3DCREATE_HARDWARE_VERTEXPROCESSING, // Note: may want to consider adding the PUREDEVICE flag here also.
&params,
&EngineGlobals.p_Device ))
{
// Failed to start up engine. Bad!
exit( 0 );
}
// Also create the render surface we will use when doing screen blur. (Creating this at 32bit depth also, since still
// takes up less memory than 720p buffers).
if( params.BackBufferWidth <= 640 )
{
D3DDevice_CreateRenderTarget( 640, 480, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[0] );
D3DDevice_CreateRenderTarget( 320, 240, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[1] );
D3DDevice_CreateRenderTarget( 160, 120, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[2] );
D3DDevice_CreateRenderTarget( 80, 60, D3DFMT_LIN_X8R8G8B8, 0, 0, &EngineGlobals.p_BlurSurface[3] );
}
// Obtain pointers to the render and Z-stencil surfaces. Doing this increases their reference counts, so release
// them following the operation.
D3DDevice_GetRenderTarget( &EngineGlobals.p_RenderSurface );
D3DDevice_GetDepthStencilSurface( &EngineGlobals.p_ZStencilSurface );
LPDIRECT3DSURFACE8 pBackBuffer;
D3DDevice_GetBackBuffer( 0, 0, &pBackBuffer );
// Get back buffer information.
EngineGlobals.backbuffer_width = params.BackBufferWidth;
EngineGlobals.backbuffer_height = params.BackBufferHeight;
EngineGlobals.backbuffer_format = params.BackBufferFormat;
EngineGlobals.zstencil_depth = ( params.AutoDepthStencilFormat == D3DFMT_D16 ) ? 16 : 32;
// Get blur buffer information.
if( EngineGlobals.p_BlurSurface[0] )
{
D3DSURFACE_DESC blur_surface_desc;
EngineGlobals.p_BlurSurface[0]->GetDesc( &blur_surface_desc );
EngineGlobals.blurbuffer_format = blur_surface_desc.Format;
}
// Set our renderstate to a known state.
InitialiseRenderstates();
// Set default gamma values.
SetGammaNormalized( 0.14f, 0.13f, 0.12f );
// Initialise the memory resident font, used for fatal i/o error messages etc.
EngineGlobals.p_memory_resident_font = InitialiseMemoryResidentFont();
// Code to enable detailed timing. Need to link with d3d8i.lib.
// DmEnableGPUCounter( TRUE );
// D3DPERF_SetShowFrameRateInterval( 1000 );
// D3DPERF_GetStatistics()->m_dwDumpFPSInfoMask |= D3DPERF_DUMP_FPS_PERFPROFILE;
// Now that the D3DDevice is created, it's safe to install vsync handlers.
Tmr::InstallVSyncHandlers();
// Load up the bump textures.
// LoadBumpTextures();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void FatalFileError( uint32 error )
{
static char* p_error_message_english[2] = { "There's a problem with the disc you're using.",
"It may be dirty or damaged." };
static char* p_error_message_french[2] = { "Le disque utilis<69> pr<70>sente une anomalie.",
"Il est peut-<2D>tre sale ou endommag<61>." };
static char* p_error_message_german[2] = { "Bei der benutzten CD ist ein Problem aufgetreten.",
"M<EFBFBD>glicherweise ist sie verschmutzt oder besch<63>digt." };
// Turn off the loading bar if it is active.
if( EngineGlobals.loadingbar_timer_event != 0 )
{
timeKillEvent( EngineGlobals.loadingbar_timer_event );
EngineGlobals.loadingbar_timer_event = 0;
}
// Ensure the graphics device has been initialised at this point.
if( EngineGlobals.p_Device == NULL )
{
InitialiseEngine();
}
// Wait for any rendering to complete.
EngineGlobals.p_Device->BlockUntilIdle();
char* p_error_message[2];
switch( Config::GetLanguage())
{
case Config::LANGUAGE_FRENCH:
{
p_error_message[0] = p_error_message_french[0];
p_error_message[1] = p_error_message_french[1];
break;
}
case Config::LANGUAGE_GERMAN:
{
p_error_message[0] = p_error_message_german[0];
p_error_message[1] = p_error_message_german[1];
break;
}
default:
{
p_error_message[0] = p_error_message_english[0];
p_error_message[1] = p_error_message_english[1];
break;
}
}
// Set up the text string used for the error message.
SText error_text;
error_text.mp_font = (SFont*)EngineGlobals.p_memory_resident_font;
error_text.m_xpos = 48.0f;
error_text.m_ypos = 128.0f;
error_text.m_xscale = 0.8f;
error_text.m_yscale = 1.0f;
error_text.m_rgba = 0x80808080;
error_text.mp_next = NULL;
set_texture( 1, NULL );
set_texture( 2, NULL );
set_texture( 3, NULL );
// Want an infinite loop here.
while( true )
{
D3DDevice_Swap( D3DSWAP_DEFAULT );
// Now that the swap instruction has been pushed, clear the buffer for next frame.
D3DDevice_Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0 );
set_blend_mode( vBLEND_MODE_BLEND );
set_texture( 0, NULL );
set_render_state( RS_UVADDRESSMODE0, 0x00010001UL );
set_render_state( RS_ZBIAS, 0 );
set_render_state( RS_ALPHACUTOFF, 1 );
set_render_state( RS_ZWRITEENABLE, 0 );
D3DDevice_SetTextureStageState( 0, D3DTSS_COLORSIGN, D3DTSIGN_RUNSIGNED | D3DTSIGN_GUNSIGNED | D3DTSIGN_BUNSIGNED );
D3DDevice_SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
D3DDevice_SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | 0 );
error_text.mp_string = p_error_message[0];
error_text.m_ypos = error_text.m_ypos - 16.0f;
error_text.BeginDraw();
error_text.Draw();
error_text.EndDraw();
error_text.mp_string = p_error_message[1];
error_text.m_ypos = error_text.m_ypos + 16.0f;
error_text.BeginDraw();
error_text.Draw();
error_text.EndDraw();
}
}
} // namespace NxXbox