mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-26 15:45:41 +00:00
1712 lines
49 KiB
C
1712 lines
49 KiB
C
|
/******************************************************************/
|
||
|
/* DirectX 9 Renderer */
|
||
|
/******************************************************************/
|
||
|
|
||
|
#include "model3.h"
|
||
|
#include <d3d9.h>
|
||
|
#include <d3dx9.h>
|
||
|
#include <dxerr9.h>
|
||
|
|
||
|
#define EXTERNAL_SHADERS 0
|
||
|
|
||
|
static float min_z;
|
||
|
static float max_z;
|
||
|
|
||
|
|
||
|
#if EXTERNAL_SHADERS
|
||
|
|
||
|
static LPCTSTR vs_filename = "vertex_shader.vs";
|
||
|
static LPCTSTR ps_filename = "pixel_shader.ps";
|
||
|
static LPCTSTR vs2d_filename = "vertex_shader_2d.vs";
|
||
|
static LPCTSTR ps2d_filename = "pixel_shader_2d.ps";
|
||
|
|
||
|
#else
|
||
|
|
||
|
#include "shaders.h"
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
D3DXMATRIX d3d_matrix_stack_get_top(void);
|
||
|
void d3d_matrix_stack_init(void);
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
float x;
|
||
|
float y;
|
||
|
float width;
|
||
|
float height;
|
||
|
} VIEWPORT_PARAMS;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
D3DXVECTOR4 sun_vector;
|
||
|
D3DXVECTOR4 sun_params;
|
||
|
} LIGHTING_PARAMS;
|
||
|
|
||
|
#define MAX_VIEWPORTS 32
|
||
|
#define MAX_LIGHTS 32
|
||
|
|
||
|
static int current_viewport;
|
||
|
static int current_light;
|
||
|
static int num_viewports;
|
||
|
static int num_lights;
|
||
|
|
||
|
static VIEWPORT_PARAMS viewport_params[MAX_VIEWPORTS];
|
||
|
static LIGHTING_PARAMS lighting_params[MAX_LIGHTS];
|
||
|
|
||
|
|
||
|
#define MESH_STATIC 0
|
||
|
#define MESH_DYNAMIC 1
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
D3DMATRIX transform;
|
||
|
D3DMATRIX normal;
|
||
|
|
||
|
int mesh_index;
|
||
|
int viewport;
|
||
|
int lighting;
|
||
|
} MESH;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int vb_index;
|
||
|
int num_vertices;
|
||
|
int vb_index_alpha;
|
||
|
int num_vertices_alpha;
|
||
|
} MESH_CACHE;
|
||
|
|
||
|
#define DYNAMIC_VB_SIZE 180000
|
||
|
#define STATIC_VB_SIZE 1000000
|
||
|
|
||
|
#define NUM_DYNAMIC_MESHES 2048
|
||
|
#define NUM_STATIC_MESHES 32768
|
||
|
|
||
|
#define DYNAMIC_MESH_BUFFER_SIZE 2048
|
||
|
#define STATIC_MESH_BUFFER_SIZE 65536
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
float x, y, z;
|
||
|
float u, v;
|
||
|
float nx, ny, nz;
|
||
|
float tx, ty, twidth, theight;
|
||
|
D3DCOLOR color, color2;
|
||
|
} VERTEX;
|
||
|
|
||
|
D3DVERTEXELEMENT9 vertex_decl[] =
|
||
|
{
|
||
|
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
|
||
|
{0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
|
||
|
{0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
|
||
|
{0, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
|
||
|
{0, 48, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
|
||
|
{0, 52, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
|
||
|
D3DDECL_END()
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
float x, y, z, w;
|
||
|
float u, v;
|
||
|
} VERTEX_2D;
|
||
|
|
||
|
const DWORD VERTEX2D_FVF = (D3DFVF_XYZRHW | D3DFVF_TEX1 );
|
||
|
|
||
|
D3DVERTEXELEMENT9 vertex_decl_2d[] =
|
||
|
{
|
||
|
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
|
||
|
{0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
|
||
|
D3DDECL_END()
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
static LPDIRECT3D9 d3d;
|
||
|
static LPDIRECT3DDEVICE9 device;
|
||
|
|
||
|
static D3DCAPS9 device_caps;
|
||
|
|
||
|
static LPDIRECT3DTEXTURE9 texture;
|
||
|
static LPDIRECT3DVERTEXBUFFER9 dynamic_vb;
|
||
|
static LPDIRECT3DVERTEXBUFFER9 static_vb;
|
||
|
static LPDIRECT3DVERTEXBUFFER9 dynamic_vb_alpha;
|
||
|
static LPDIRECT3DVERTEXBUFFER9 static_vb_alpha;
|
||
|
static LPDIRECT3DVERTEXSHADER9 vshader;
|
||
|
static LPDIRECT3DPIXELSHADER9 pshader;
|
||
|
static LPDIRECT3DVERTEXDECLARATION9 vertex_declaration;
|
||
|
|
||
|
static LPDIRECT3DTEXTURE9 texture_2d[4];
|
||
|
static LPDIRECT3DTEXTURE9 palette_2d;
|
||
|
static LPDIRECT3DTEXTURE9 priority_2d[4];
|
||
|
static LPDIRECT3DVERTEXBUFFER9 vb_2d;
|
||
|
static LPDIRECT3DVERTEXSHADER9 vshader_2d;
|
||
|
static LPDIRECT3DPIXELSHADER9 pshader_2d;
|
||
|
static LPDIRECT3DVERTEXDECLARATION9 vertex_declaration_2d;
|
||
|
|
||
|
static LPD3DXMATRIXSTACK matrix_stack;
|
||
|
|
||
|
static LPDIRECT3DTEXTURE9 lightgun_cursor;
|
||
|
|
||
|
static LPD3DXFONT font;
|
||
|
|
||
|
static D3DMATRIX world_matrix;
|
||
|
static D3DMATRIX view_matrix;
|
||
|
static D3DMATRIX projection_matrix;
|
||
|
|
||
|
static D3DVIEWPORT9 viewport;
|
||
|
|
||
|
static char num_bits[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
||
|
|
||
|
static HWND main_window;
|
||
|
static HFONT hfont;
|
||
|
|
||
|
static UINT32 matrix_start;
|
||
|
|
||
|
static MESH_CACHE *static_mesh_cache;
|
||
|
static MESH_CACHE *dynamic_mesh_cache;
|
||
|
|
||
|
static int static_mesh_cache_top = 0;
|
||
|
static int dynamic_mesh_cache_top = 0;
|
||
|
|
||
|
static int dynamic_mesh_cache_vertex_top = 0;
|
||
|
static int dynamic_mesh_cache_vertex_top_alpha = 0;
|
||
|
static int static_mesh_cache_vertex_top = 0;
|
||
|
static int static_mesh_cache_vertex_top_alpha = 0;
|
||
|
|
||
|
static MESH *static_mesh_buffer;
|
||
|
static int static_mesh_buffer_top = 0;
|
||
|
static MESH *dynamic_mesh_buffer;
|
||
|
static int dynamic_mesh_buffer_top = 0;
|
||
|
|
||
|
static int listdone = 0;
|
||
|
|
||
|
static D3DXVECTOR4 sun_vector;
|
||
|
static D3DXVECTOR4 sun_params;
|
||
|
|
||
|
static BOOL traverse_node(UINT32);
|
||
|
static BOOL traverse_list(UINT32);
|
||
|
static BOOL render_scene(void);
|
||
|
static UINT32* get_address(UINT32);
|
||
|
|
||
|
|
||
|
static UINT16 *static_mesh_index;
|
||
|
|
||
|
|
||
|
static void d3d_shutdown(void)
|
||
|
{
|
||
|
if(d3d) {
|
||
|
IDirect3D9_Release(d3d);
|
||
|
d3d = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL d3d_pre_init(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
D3DDISPLAYMODE d3ddm;
|
||
|
D3DADAPTER_IDENTIFIER9 adapter_identifier;
|
||
|
|
||
|
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||
|
if (!d3d)
|
||
|
{
|
||
|
message(0, "Direct3DCreate9 failed.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
hr = IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->GetAdapterDisplayMode failed.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
hr = IDirect3D9_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &device_caps);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->GetDeviceCaps failed.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &adapter_identifier);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->GetAdapterIdentifier failed.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
message(0, "Video card: %s", adapter_identifier.Description);
|
||
|
|
||
|
if (device_caps.VertexShaderVersion < D3DVS_VERSION(3,0))
|
||
|
{
|
||
|
message(0, "The video card doesn't support Vertex Shader 3.0\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (device_caps.PixelShaderVersion < D3DPS_VERSION(3,0))
|
||
|
{
|
||
|
message(0, "The video card doesn't support Pixel Shader 3.0\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL d3d_init(HWND main_window)
|
||
|
{
|
||
|
D3DPRESENT_PARAMETERS d3dpp;
|
||
|
LPD3DXBUFFER vsh, psh, errors;
|
||
|
HRESULT hr;
|
||
|
DWORD flags = 0;
|
||
|
int width, height;
|
||
|
int i;
|
||
|
|
||
|
if (m3_config.fullscreen)
|
||
|
{
|
||
|
width = m3_config.width;
|
||
|
height = m3_config.height;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
width = 496;
|
||
|
height = 384;
|
||
|
}
|
||
|
|
||
|
// Check if we have a valid display mode
|
||
|
if (width == 0 || height == 0)
|
||
|
return FALSE;
|
||
|
|
||
|
memset(&d3dpp, 0, sizeof(d3dpp));
|
||
|
d3dpp.Windowed = m3_config.fullscreen ? FALSE : TRUE;
|
||
|
d3dpp.SwapEffect = m3_config.stretch ? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_FLIP;
|
||
|
d3dpp.BackBufferWidth = width;
|
||
|
d3dpp.BackBufferHeight = height;
|
||
|
d3dpp.BackBufferCount = m3_config.stretch ? 1 : 2;
|
||
|
d3dpp.hDeviceWindow = main_window;
|
||
|
d3dpp.PresentationInterval = m3_config.fullscreen ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||
|
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||
|
d3dpp.EnableAutoDepthStencil = TRUE;
|
||
|
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||
|
|
||
|
if (device_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
|
||
|
{
|
||
|
flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
||
|
}
|
||
|
|
||
|
hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, main_window, flags, &d3dpp, &device);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create vertex buffers for dynamic vertex data
|
||
|
hr = IDirect3DDevice9_CreateVertexBuffer(device,
|
||
|
DYNAMIC_VB_SIZE * sizeof(VERTEX), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &dynamic_vb, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->CreateVertexBuffer failed\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
hr = IDirect3DDevice9_CreateVertexBuffer(device,
|
||
|
DYNAMIC_VB_SIZE * sizeof(VERTEX), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &dynamic_vb_alpha, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->CreateVertexBuffer failed\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create vertex buffers for static vertex data
|
||
|
hr = IDirect3DDevice9_CreateVertexBuffer(device,
|
||
|
STATIC_VB_SIZE * sizeof(VERTEX), 0, 0, D3DPOOL_MANAGED, &static_vb, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->CreateVertexBuffer failed\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
hr = IDirect3DDevice9_CreateVertexBuffer(device,
|
||
|
STATIC_VB_SIZE * sizeof(VERTEX), 0, 0, D3DPOOL_MANAGED, &static_vb_alpha, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->CreateVertexBuffer failed\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#if EXTERNAL_SHADERS
|
||
|
// create vertex shader
|
||
|
hr = D3DXAssembleShaderFromFile(vs_filename, NULL, NULL, 0, &vsh, &errors);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: %s", errors->lpVtbl->GetBufferPointer(errors));
|
||
|
return FALSE;
|
||
|
}
|
||
|
hr = IDirect3DDevice9_CreateVertexShader(device, (DWORD*)vsh->lpVtbl->GetBufferPointer(vsh), &vshader);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreateVertexShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create pixel shader
|
||
|
hr = D3DXAssembleShaderFromFile(ps_filename, NULL, NULL, 0, &psh, &errors);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: %s", errors->lpVtbl->GetBufferPointer(errors));
|
||
|
return FALSE;
|
||
|
}
|
||
|
hr = IDirect3DDevice9_CreatePixelShader(device, (DWORD*)psh->lpVtbl->GetBufferPointer(psh), &pshader);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreatePixelShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
#else
|
||
|
// create vertex shader
|
||
|
hr = IDirect3DDevice9_CreateVertexShader(device, (DWORD*)vertex_shader_source, &vshader);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreateVertexShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create pixel shader
|
||
|
hr = IDirect3DDevice9_CreatePixelShader(device, (DWORD*)pixel_shader_source, &pshader);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreatePixelShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// create vertex declarations
|
||
|
hr = IDirect3DDevice9_CreateVertexDeclaration(device, vertex_decl, &vertex_declaration);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "IDirect3DDevice9_CreateVertexDeclaration failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create textures
|
||
|
hr = IDirect3DDevice9_CreateTexture(device, 2048, 4096, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "IDirect3DDevice9_CreateTexture failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dynamic_mesh_buffer = (MESH*)malloc(sizeof(MESH) * DYNAMIC_MESH_BUFFER_SIZE);
|
||
|
static_mesh_buffer = (MESH*)malloc(sizeof(MESH) * STATIC_MESH_BUFFER_SIZE);
|
||
|
|
||
|
dynamic_mesh_cache = (MESH_CACHE*)malloc(sizeof(MESH_CACHE) * NUM_DYNAMIC_MESHES);
|
||
|
static_mesh_cache = (MESH_CACHE*)malloc(sizeof(MESH_CACHE) * NUM_STATIC_MESHES);
|
||
|
|
||
|
static_mesh_index = (UINT16*)malloc(sizeof(UINT16) * 16777216);
|
||
|
for (i=0; i < 16777216; i++)
|
||
|
{
|
||
|
static_mesh_index[i] = 0xffff;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
/////////////////////////////
|
||
|
// 2D layers //
|
||
|
/////////////////////////////
|
||
|
|
||
|
VERTEX_2D *vb;
|
||
|
|
||
|
// create vertex shader and pixel shader for 2D
|
||
|
#if EXTERNAL_SHADERS
|
||
|
// create vertex shader
|
||
|
hr = D3DXAssembleShaderFromFile(vs2d_filename, NULL, NULL, 0, &vsh, &errors);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: %s", errors->lpVtbl->GetBufferPointer(errors));
|
||
|
return FALSE;
|
||
|
}
|
||
|
hr = IDirect3DDevice9_CreateVertexShader(device, (DWORD*)vsh->lpVtbl->GetBufferPointer(vsh), &vshader_2d);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreateVertexShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create pixel shader
|
||
|
hr = D3DXAssembleShaderFromFile(ps2d_filename, NULL, NULL, 0, &psh, &errors);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: %s", errors->lpVtbl->GetBufferPointer(errors));
|
||
|
return FALSE;
|
||
|
}
|
||
|
hr = IDirect3DDevice9_CreatePixelShader(device, (DWORD*)psh->lpVtbl->GetBufferPointer(psh), &pshader_2d);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreatePixelShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
#else
|
||
|
// create vertex shader
|
||
|
hr = IDirect3DDevice9_CreateVertexShader(device, (DWORD*)vertex_shader_2d_source, &vshader_2d);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreateVertexShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create pixel shader
|
||
|
hr = IDirect3DDevice9_CreatePixelShader(device, (DWORD*)pixel_shader_2d_source, &pshader_2d);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: IDirect3DDevice9_CreatePixelShader failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// create vertex declarations
|
||
|
hr = IDirect3DDevice9_CreateVertexDeclaration(device, vertex_decl, &vertex_declaration_2d);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "IDirect3DDevice9_CreateVertexDeclaration failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// create textures for 2d layers
|
||
|
for (i=0; i < 4; i++)
|
||
|
{
|
||
|
hr = IDirect3DDevice9_CreateTexture(device,
|
||
|
512, 512, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8L8, D3DPOOL_DEFAULT, &texture_2d[i], NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "IDirect3DDevice9_CreateTexture failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// priority
|
||
|
hr = IDirect3DDevice9_CreateTexture(device,
|
||
|
1, 512, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &priority_2d[i], NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "IDirect3DDevice9_CreateTexture failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// create texture for palette
|
||
|
hr = IDirect3DDevice9_CreateTexture(device,
|
||
|
256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &palette_2d, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "IDirect3DDevice9_CreateTexture failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// create vertex buffer for 2d layers
|
||
|
hr = IDirect3DDevice9_CreateVertexBuffer(device, 4 * sizeof(VERTEX_2D), 0, 0, D3DPOOL_MANAGED, &vb_2d, NULL);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "d3d->CreateVertexBuffer failed\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// fill in the vertex data
|
||
|
IDirect3DVertexBuffer9_Lock(vb_2d, 0, 0, (void **)&vb, D3DLOCK_DISCARD);
|
||
|
|
||
|
vb[0].x = 0.0f; vb[0].y = 0.0f; vb[0].z = 1.0f; vb[0].w = 1.0f;
|
||
|
vb[0].u = 0.0f; vb[0].v = 0.0f;
|
||
|
vb[1].x = 512.0f; vb[1].y = 0.0f; vb[1].z = 1.0f; vb[1].w = 1.0f;
|
||
|
vb[1].u = 1.0f; vb[1].v = 0.0f;
|
||
|
vb[2].x = 512.0f; vb[2].y = 512.0f; vb[2].z = 1.0f; vb[2].w = 1.0f;
|
||
|
vb[2].u = 1.0f; vb[2].v = 1.0f;
|
||
|
vb[3].x = 0.0f; vb[3].y = 512.0f; vb[3].z = 1.0f; vb[3].w = 1.0f;
|
||
|
vb[3].u = 0.0f; vb[3].v = 1.0f;
|
||
|
|
||
|
IDirect3DVertexBuffer9_Unlock(vb_2d);
|
||
|
}
|
||
|
|
||
|
D3DXCreateMatrixStack(0, &matrix_stack);
|
||
|
d3d_matrix_stack_init();
|
||
|
|
||
|
|
||
|
// Create font for the on-screen display
|
||
|
hfont = CreateFont( 14, 0, // Width, Height
|
||
|
0, 0, // Escapement, Orientation
|
||
|
FW_BOLD, // Font weight
|
||
|
FALSE, FALSE, // Italic, underline
|
||
|
FALSE, // Strikeout
|
||
|
ANSI_CHARSET, // Charset
|
||
|
OUT_DEFAULT_PRECIS, // Precision
|
||
|
CLIP_DEFAULT_PRECIS, // Clip precision
|
||
|
DEFAULT_QUALITY, // Output quality
|
||
|
DEFAULT_PITCH | // Pitch and family
|
||
|
FF_DONTCARE,
|
||
|
"Terminal" );
|
||
|
if (hfont == NULL)
|
||
|
{
|
||
|
message(0, "Direct3D error: Couldn't create font.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Create D3D font
|
||
|
hr = D3DXCreateFont(device, 14, 0, FW_BOLD, 1, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
|
||
|
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Terminal", &font);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
message(0, "Direct3D error: D3DXCreateFont failed.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
atexit(d3d_shutdown);
|
||
|
|
||
|
// set minimum and maximum Z
|
||
|
if (m3_config.step == 0x10)
|
||
|
{
|
||
|
min_z = 10.0f;
|
||
|
max_z = 500000.0f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
min_z = 0.1f;
|
||
|
max_z = 100000.0f;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void set_viewport(int x, int y, int width, int height)
|
||
|
{
|
||
|
D3DVIEWPORT9 viewport;
|
||
|
|
||
|
memset(&viewport, 0, sizeof(D3DVIEWPORT9));
|
||
|
viewport.X = x;
|
||
|
viewport.Y = y;
|
||
|
viewport.Width = width;
|
||
|
viewport.Height = height;
|
||
|
viewport.MinZ = min_z;
|
||
|
viewport.MaxZ = max_z;
|
||
|
|
||
|
IDirect3DDevice9_SetViewport(device, &viewport);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_draw_layer(int layer, UINT32 color_offset, int x, int y, BOOL top)
|
||
|
{
|
||
|
int i;
|
||
|
D3DXVECTOR4 scroll_pos;
|
||
|
float co[4];
|
||
|
co[0] = 0.0f;
|
||
|
co[1] = (((float)((color_offset >> 16) & 0xff) / 255.0f) - 0.5f) * 2.0f;
|
||
|
co[2] = (((float)((color_offset >> 8) & 0xff) / 255.0f) - 0.5f) * 2.0f;
|
||
|
co[3] = (((float)((color_offset >> 0) & 0xff) / 255.0f) - 0.5f) * 2.0f;
|
||
|
|
||
|
scroll_pos.x = (float)(x) / 512.0f;
|
||
|
scroll_pos.y = (float)(y) / 512.0f;
|
||
|
scroll_pos.z = top ? 1.0f : 0.0f;
|
||
|
|
||
|
set_viewport(0, 0, 496, 384);
|
||
|
|
||
|
IDirect3DDevice9_BeginScene(device);
|
||
|
|
||
|
IDirect3DDevice9_SetStreamSourceFreq(device, 0, 1);
|
||
|
IDirect3DDevice9_SetStreamSource(device, 0, vb_2d, 0, sizeof(VERTEX_2D));
|
||
|
IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
|
||
|
IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, NULL);
|
||
|
|
||
|
IDirect3DDevice9_SetFVF(device, VERTEX2D_FVF);
|
||
|
// IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration_2d);
|
||
|
IDirect3DDevice9_SetVertexShader(device, vshader_2d);
|
||
|
IDirect3DDevice9_SetPixelShader(device, pshader_2d);
|
||
|
|
||
|
// set color offset
|
||
|
IDirect3DDevice9_SetPixelShaderConstantF(device, 8, (float *)co, 1);
|
||
|
IDirect3DDevice9_SetPixelShaderConstantF(device, 9, (float *)&scroll_pos, 1);
|
||
|
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_FILLMODE, D3DFILL_SOLID);
|
||
|
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, TRUE);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, (DWORD)0x00000000);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
||
|
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_MINFILTER, D3DTEXF_NONE);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_MINFILTER, D3DTEXF_NONE);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
|
|
||
|
IDirect3DDevice9_SetTexture(device, 0, texture_2d[layer]);
|
||
|
IDirect3DDevice9_SetTexture(device, 1, palette_2d);
|
||
|
IDirect3DDevice9_SetTexture(device, 2, priority_2d[layer]);
|
||
|
|
||
|
IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLEFAN, 0, 2);
|
||
|
|
||
|
IDirect3DDevice9_EndScene(device);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_blit(void)
|
||
|
{
|
||
|
if (m3_config.stretch)
|
||
|
{
|
||
|
RECT src_rect = {0, 0, 496, 384};
|
||
|
IDirect3DDevice9_Present(device, &src_rect, NULL, NULL, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void osd_renderer_clear(BOOL fbuf, BOOL zbuf)
|
||
|
{
|
||
|
int flags = 0;
|
||
|
|
||
|
set_viewport(0, 0, m3_config.width, m3_config.height);
|
||
|
|
||
|
if (fbuf)
|
||
|
{
|
||
|
flags |= D3DCLEAR_TARGET;
|
||
|
}
|
||
|
if (zbuf)
|
||
|
{
|
||
|
flags |= D3DCLEAR_ZBUFFER;
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_Clear(device, 0, NULL, flags, 0x00000000, 1.0f, 0);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_get_layer_buffer(int layer_num, UINT8 **buffer, int *pitch)
|
||
|
{
|
||
|
D3DLOCKED_RECT locked_rect;
|
||
|
HRESULT hr;
|
||
|
|
||
|
*buffer = NULL;
|
||
|
*pitch = 0;
|
||
|
|
||
|
hr = IDirect3DTexture9_LockRect(texture_2d[layer_num], 0, &locked_rect, NULL, D3DLOCK_DISCARD);
|
||
|
if (!FAILED(hr))
|
||
|
{
|
||
|
*buffer = (UINT8 *)locked_rect.pBits;
|
||
|
*pitch = locked_rect.Pitch / 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void osd_renderer_free_layer_buffer(UINT layer_num)
|
||
|
{
|
||
|
IDirect3DTexture9_UnlockRect(texture_2d[layer_num], 0);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_get_palette_buffer(UINT32 **buffer, int *width, int *pitch)
|
||
|
{
|
||
|
D3DLOCKED_RECT locked_rect;
|
||
|
HRESULT hr;
|
||
|
|
||
|
*buffer = NULL;
|
||
|
*pitch = 0;
|
||
|
*width = 0;
|
||
|
|
||
|
hr = IDirect3DTexture9_LockRect(palette_2d, 0, &locked_rect, NULL, D3DLOCK_DISCARD);
|
||
|
if (!FAILED(hr))
|
||
|
{
|
||
|
*buffer = (UINT32*)locked_rect.pBits;
|
||
|
*pitch = locked_rect.Pitch / 4;
|
||
|
*width = 256;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void osd_renderer_free_palette_buffer(void)
|
||
|
{
|
||
|
IDirect3DTexture9_UnlockRect(palette_2d, 0);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_get_priority_buffer(int layer_num, UINT8 **buffer, int *pitch)
|
||
|
{
|
||
|
D3DLOCKED_RECT locked_rect;
|
||
|
HRESULT hr;
|
||
|
|
||
|
*buffer = NULL;
|
||
|
*pitch = 0;
|
||
|
|
||
|
hr = IDirect3DTexture9_LockRect(priority_2d[layer_num], 0, &locked_rect, NULL, D3DLOCK_DISCARD);
|
||
|
if (!FAILED(hr))
|
||
|
{
|
||
|
*buffer = (UINT8*)locked_rect.pBits;
|
||
|
*pitch = locked_rect.Pitch;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void osd_renderer_free_priority_buffer(int layer_num)
|
||
|
{
|
||
|
IDirect3DTexture9_UnlockRect(priority_2d[layer_num], 0);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_draw_text(int x, int y, const char* string, DWORD color, BOOL shadow)
|
||
|
{
|
||
|
RECT rect = { x, y, 496-1, 384-1 };
|
||
|
RECT rect_s = { x+1, y+1, 496-1, 384-1 };
|
||
|
if (shadow)
|
||
|
{
|
||
|
font->lpVtbl->DrawText(font, NULL, string, -1, &rect_s, 0, 0xFF000000);
|
||
|
}
|
||
|
|
||
|
font->lpVtbl->DrawText(font, NULL, string, -1, &rect, 0, color);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* void osd_renderer_set_coordinate_system(const MATRIX m);
|
||
|
*
|
||
|
* Applies the coordinate system matrix and makes adjustments so that the
|
||
|
* Model 3 coordinate system is properly handled.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* m = Matrix.
|
||
|
*/
|
||
|
|
||
|
void osd_renderer_set_coordinate_system( const MATRIX m )
|
||
|
{
|
||
|
memcpy( &view_matrix, m, sizeof(MATRIX) );
|
||
|
view_matrix._22 = -view_matrix._22;
|
||
|
}
|
||
|
|
||
|
static void cache_model(VERTEX *vb, VERTEX *vb_alpha, UINT32 *src, UINT32 address, int *verts, int *verts_alpha)
|
||
|
{
|
||
|
float fixed_point_scale;
|
||
|
VERTEX vertex[4];
|
||
|
VERTEX prev_vertex[4];
|
||
|
int end, index, vb_index, vb_index_alpha;
|
||
|
int polygon_index = 0;
|
||
|
float uv_scale;
|
||
|
|
||
|
int polygon = 0;
|
||
|
|
||
|
int normal_num = 0;
|
||
|
|
||
|
*verts = 0;
|
||
|
*verts_alpha = 0;
|
||
|
|
||
|
//UINT32 *src = get_address( address );
|
||
|
|
||
|
if(src == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
if(m3_config.step == 0x10)
|
||
|
fixed_point_scale = 32768.0f;
|
||
|
else
|
||
|
fixed_point_scale = 524288.0f;
|
||
|
|
||
|
memset(prev_vertex, 0, sizeof(prev_vertex));
|
||
|
end = 0;
|
||
|
index = 0;
|
||
|
vb_index = 0;
|
||
|
vb_index_alpha = 0;
|
||
|
|
||
|
do {
|
||
|
UINT32 header[7];
|
||
|
UINT32 entry[16];
|
||
|
D3DCOLOR color, color2;
|
||
|
int transparency;
|
||
|
int i, num_vertices, num_old_vertices;
|
||
|
int v2, v;
|
||
|
int texture_format;
|
||
|
int texture_x, texture_y, tex_width, tex_height;
|
||
|
float nx, ny, nz;
|
||
|
float dot;
|
||
|
int polygon_id;
|
||
|
|
||
|
for( i=0; i<7; i++) {
|
||
|
header[i] = src[index];
|
||
|
index++;
|
||
|
}
|
||
|
|
||
|
uv_scale = (header[1] & 0x40) ? 1.0f : 8.0f;
|
||
|
|
||
|
polygon_id = (header[0] >> 10) & 0x3fff;
|
||
|
|
||
|
if (polygon == 0 && (header[0] & 0xf) != 0)
|
||
|
return FALSE;
|
||
|
|
||
|
if (header[6] == 0 /*|| header[0] & 0x300*/)
|
||
|
return FALSE;
|
||
|
|
||
|
if ((header[0] & 0x300) == 0x300)
|
||
|
{
|
||
|
//printf("Polygon = %08X %08X %08X %08X %08X %08X %08X (address = %08X)\n", header[0], header[1], header[2], header[3], header[4], header[5], header[6], address);
|
||
|
}
|
||
|
|
||
|
// Check if this is the last polygon
|
||
|
if(header[1] & 0x4)
|
||
|
end = 1;
|
||
|
|
||
|
transparency = ((header[6] >> 18) & 0x1F) << 3;
|
||
|
if (header[6] & 0x800000)
|
||
|
{
|
||
|
color = 0xFF000000 | ((header[4] >> 8) & 0xffffff);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
color = (transparency << 24) | ((header[4] >> 8) & 0xffffff);
|
||
|
}
|
||
|
|
||
|
if (header[6] & 0x10000)
|
||
|
{
|
||
|
color2 = 0xffff0000 | (((header[6] >> 11) & 0x1F) << 3) << 16;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
color2 = 0;
|
||
|
}
|
||
|
|
||
|
if (header[6] & 0x4000000)
|
||
|
{
|
||
|
// texture enable
|
||
|
color2 |= 0x0000ff00;
|
||
|
}
|
||
|
|
||
|
texture_x = 32 * (((header[4] & 0x1F) << 1) | ((header[5] >> 7) & 0x1));
|
||
|
texture_y = 32 * ((header[5] & 0x1F) | ((header[4] >> 1) & 0x20));
|
||
|
tex_width = 32 << ((header[3] >> 3) & 0x7);
|
||
|
tex_height = 32 << (header[3] & 0x7);
|
||
|
|
||
|
texture_format = ((header[6] >> 7) & 0x7) ? 0 : 1;
|
||
|
if (texture_format == 0) texture_y += 2048;
|
||
|
|
||
|
// Polygon normal
|
||
|
// Assuming 2.22 fixed-point. Is this correct ?
|
||
|
nx = (float)((int)header[1] >> 8) / 4194304.0f;
|
||
|
ny = (float)((int)header[2] >> 8) / 4194304.0f;
|
||
|
nz = (float)((int)header[3] >> 8) / 4194304.0f;
|
||
|
|
||
|
// If bit 0x40 set this is a quad, otherwise a triangle
|
||
|
if(header[0] & 0x40)
|
||
|
num_vertices = 4;
|
||
|
else
|
||
|
num_vertices = 3;
|
||
|
|
||
|
// How many vertices are reused
|
||
|
num_old_vertices = num_bits[header[0] & 0xF];
|
||
|
|
||
|
// Load reused vertices
|
||
|
v2 = 0;
|
||
|
for( v=0; v<4; v++) {
|
||
|
if( header[0] & (1 << v) ) {
|
||
|
memcpy( &vertex[v2], &prev_vertex[v], sizeof(VERTEX) );
|
||
|
//vertex[v2].nx = prev_vertex[v].nx;
|
||
|
//vertex[v2].ny = prev_vertex[v].ny;
|
||
|
//vertex[v2].nz = prev_vertex[v].nz;
|
||
|
vertex[v2].color = color;
|
||
|
vertex[v2].color2 = color2;
|
||
|
vertex[v2].tx = texture_x;
|
||
|
vertex[v2].ty = texture_y;
|
||
|
vertex[v2].twidth = tex_width;
|
||
|
vertex[v2].theight = tex_height;
|
||
|
v2++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Load vertex data
|
||
|
for( i=0; i<(num_vertices - num_old_vertices) * 4; i++) {
|
||
|
entry[i] = src[index];
|
||
|
index++;
|
||
|
}
|
||
|
|
||
|
// Load new vertices
|
||
|
for( v=0; v < (num_vertices - num_old_vertices); v++) {
|
||
|
int ix, iy, iz;
|
||
|
UINT16 tx,ty;
|
||
|
int xsize, ysize;
|
||
|
int v_index = v * 4;
|
||
|
|
||
|
ix = entry[v_index];
|
||
|
iy = entry[v_index + 1];
|
||
|
iz = entry[v_index + 2];
|
||
|
|
||
|
if ((ix & 0xf0000000) == 0x70000000 ||
|
||
|
(iy & 0xf0000000) == 0x70000000 ||
|
||
|
(iz & 0xf0000000) == 0x70000000)
|
||
|
return FALSE;
|
||
|
|
||
|
vertex[v2].x = (float)(ix) / fixed_point_scale;
|
||
|
vertex[v2].y = (float)(iy) / fixed_point_scale;
|
||
|
vertex[v2].z = (float)(iz) / fixed_point_scale;
|
||
|
|
||
|
tx = (UINT16)((entry[v_index + 3] >> 16) & 0xFFFF);
|
||
|
ty = (UINT16)(entry[v_index + 3] & 0xFFFF);
|
||
|
xsize = 32 << ((header[3] >> 3) & 0x7);
|
||
|
ysize = 32 << (header[3] & 0x7);
|
||
|
|
||
|
// Convert texture coordinates from 13.3 fixed-point to float
|
||
|
// Tex coords need to be divided by texture size because D3D wants them in
|
||
|
// range 0...1
|
||
|
vertex[v2].u = ((float)(tx) / uv_scale) / (float)xsize;
|
||
|
vertex[v2].v = ((float)(ty) / uv_scale) / (float)ysize;
|
||
|
vertex[v2].nx = nx;
|
||
|
vertex[v2].ny = ny;
|
||
|
vertex[v2].nz = nz;
|
||
|
vertex[v2].color = color;
|
||
|
vertex[v2].color2 = color2;
|
||
|
vertex[v2].tx = texture_x;
|
||
|
vertex[v2].ty = texture_y;
|
||
|
vertex[v2].twidth = tex_width;
|
||
|
vertex[v2].theight = tex_height;
|
||
|
v2++;
|
||
|
|
||
|
if (header[0] & 0x300)
|
||
|
{
|
||
|
//printf(" Vert: %08X %08X %08X %08X\n", entry[v_index+0], entry[v_index+1], entry[v_index+2], entry[v_index+3]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
D3DXVECTOR3 e1, e2, cross, n;
|
||
|
e1.x = vertex[1].x - vertex[0].x;
|
||
|
e1.y = vertex[1].y - vertex[0].y;
|
||
|
e1.z = vertex[1].z - vertex[0].z;
|
||
|
e2.x = vertex[2].x - vertex[0].x;
|
||
|
e2.y = vertex[2].y - vertex[0].y;
|
||
|
e2.z = vertex[2].z - vertex[0].z;
|
||
|
|
||
|
n.x = nx;
|
||
|
n.y = ny;
|
||
|
n.z = nz;
|
||
|
|
||
|
D3DXVec3Cross(&cross, &e2, &e1);
|
||
|
D3DXVec3Normalize(&cross, &cross);
|
||
|
dot = D3DXVec3Dot(&n, &cross);
|
||
|
}
|
||
|
|
||
|
// Transparent polygons
|
||
|
// Translucent texture (ARGB4444)
|
||
|
if((header[6] & 0x800000) == 0 || header[6] & 0x1 /* || header[6] & 0x80000000*/)
|
||
|
{
|
||
|
if (dot >= 0)
|
||
|
{
|
||
|
memcpy(&vb_alpha[vb_index_alpha+0], &vertex[0], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+1], &vertex[1], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+2], &vertex[2], sizeof(VERTEX));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(&vb_alpha[vb_index_alpha+0], &vertex[2], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+1], &vertex[1], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+2], &vertex[0], sizeof(VERTEX));
|
||
|
}
|
||
|
vb_index_alpha += 3;
|
||
|
|
||
|
if (num_vertices > 3)
|
||
|
{
|
||
|
if (dot >= 0)
|
||
|
{
|
||
|
memcpy(&vb_alpha[vb_index_alpha+0], &vertex[0], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+1], &vertex[2], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+2], &vertex[3], sizeof(VERTEX));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(&vb_alpha[vb_index_alpha+0], &vertex[3], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+1], &vertex[2], sizeof(VERTEX));
|
||
|
memcpy(&vb_alpha[vb_index_alpha+2], &vertex[0], sizeof(VERTEX));
|
||
|
}
|
||
|
vb_index_alpha += 3;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (dot >= 0)
|
||
|
{
|
||
|
memcpy(&vb[vb_index+0], &vertex[0], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+1], &vertex[1], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+2], &vertex[2], sizeof(VERTEX));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(&vb[vb_index+0], &vertex[2], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+1], &vertex[1], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+2], &vertex[0], sizeof(VERTEX));
|
||
|
}
|
||
|
vb_index += 3;
|
||
|
|
||
|
if (num_vertices > 3)
|
||
|
{
|
||
|
if (dot >= 0)
|
||
|
{
|
||
|
memcpy(&vb[vb_index+0], &vertex[0], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+1], &vertex[2], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+2], &vertex[3], sizeof(VERTEX));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(&vb[vb_index+0], &vertex[3], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+1], &vertex[2], sizeof(VERTEX));
|
||
|
memcpy(&vb[vb_index+2], &vertex[0], sizeof(VERTEX));
|
||
|
}
|
||
|
vb_index += 3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Copy current vertex as previous vertex
|
||
|
memcpy(prev_vertex, vertex, sizeof(VERTEX) * 4);
|
||
|
|
||
|
polygon++;
|
||
|
|
||
|
} while(end == 0);
|
||
|
|
||
|
*verts = vb_index / 3;
|
||
|
*verts_alpha = vb_index_alpha / 3;
|
||
|
}
|
||
|
|
||
|
void osd_renderer_draw_model(UINT32 *mem, UINT32 address, int dynamic)
|
||
|
{
|
||
|
int num_triangles, num_triangles_alpha;
|
||
|
VERTEX *vb, *vb_alpha;
|
||
|
D3DMATRIX world_view_proj, world_view;
|
||
|
D3DMATRIX matrix = d3d_matrix_stack_get_top();
|
||
|
|
||
|
// Make the world-view matrix
|
||
|
//D3DXMatrixMultiply(&world_view, &matrix, &view_matrix);
|
||
|
D3DXMatrixTranspose(&world_view, &matrix);
|
||
|
|
||
|
// Make the world-view-projection matrix
|
||
|
D3DXMatrixMultiply(&world_view_proj, &matrix, &view_matrix);
|
||
|
D3DXMatrixMultiply(&world_view_proj, &world_view_proj, &projection_matrix);
|
||
|
D3DXMatrixTranspose(&world_view_proj, &world_view_proj);
|
||
|
|
||
|
if (dynamic)
|
||
|
{
|
||
|
int vert_index = dynamic_mesh_cache_vertex_top;
|
||
|
int vert_index_alpha = dynamic_mesh_cache_vertex_top_alpha;
|
||
|
|
||
|
IDirect3DVertexBuffer9_Lock(dynamic_vb, 0, 0, (void **)&vb, D3DLOCK_DISCARD);
|
||
|
IDirect3DVertexBuffer9_Lock(dynamic_vb_alpha, 0, 0, (void **)&vb_alpha, D3DLOCK_DISCARD);
|
||
|
cache_model(&vb[vert_index], &vb_alpha[vert_index_alpha], mem, address, &num_triangles, &num_triangles_alpha);
|
||
|
IDirect3DVertexBuffer9_Unlock(dynamic_vb_alpha);
|
||
|
IDirect3DVertexBuffer9_Unlock(dynamic_vb);
|
||
|
|
||
|
dynamic_mesh_cache[dynamic_mesh_cache_top].vb_index = vert_index;
|
||
|
dynamic_mesh_cache[dynamic_mesh_cache_top].vb_index_alpha = vert_index_alpha;
|
||
|
dynamic_mesh_cache[dynamic_mesh_cache_top].num_vertices = num_triangles * 3;
|
||
|
dynamic_mesh_cache[dynamic_mesh_cache_top].num_vertices_alpha = num_triangles_alpha * 3;
|
||
|
|
||
|
dynamic_mesh_cache_vertex_top += num_triangles * 3;
|
||
|
dynamic_mesh_cache_vertex_top_alpha += num_triangles_alpha * 3;
|
||
|
|
||
|
memcpy(&dynamic_mesh_buffer[dynamic_mesh_buffer_top].normal, &world_view, sizeof(D3DMATRIX));
|
||
|
memcpy(&dynamic_mesh_buffer[dynamic_mesh_buffer_top].transform, &world_view_proj, sizeof(D3DMATRIX));
|
||
|
|
||
|
dynamic_mesh_buffer[dynamic_mesh_buffer_top].lighting = current_light;
|
||
|
dynamic_mesh_buffer[dynamic_mesh_buffer_top].viewport = current_viewport;
|
||
|
|
||
|
dynamic_mesh_buffer[dynamic_mesh_buffer_top].mesh_index = dynamic_mesh_cache_top;
|
||
|
|
||
|
dynamic_mesh_cache_top++;
|
||
|
if (dynamic_mesh_cache_top >= NUM_DYNAMIC_MESHES)
|
||
|
{
|
||
|
printf("dynamic mesh cache overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
dynamic_mesh_buffer_top++;
|
||
|
if (dynamic_mesh_buffer_top >= DYNAMIC_MESH_BUFFER_SIZE)
|
||
|
{
|
||
|
printf("dynamic mesh buffer overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (dynamic_mesh_cache_vertex_top >= DYNAMIC_VB_SIZE)
|
||
|
{
|
||
|
printf("dynamic vertex cache overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
if (dynamic_mesh_cache_vertex_top_alpha >= DYNAMIC_VB_SIZE)
|
||
|
{
|
||
|
printf("dynamic vertex cache alpha overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UINT16 mesh_index = static_mesh_index[address & 0xffffff];
|
||
|
|
||
|
if (mesh_index == 0xffff)
|
||
|
{
|
||
|
// cache new mesh
|
||
|
int vert_index = static_mesh_cache_vertex_top;
|
||
|
int vert_index_alpha = static_mesh_cache_vertex_top_alpha;
|
||
|
|
||
|
int voffset = vert_index * sizeof(VERTEX);
|
||
|
int voffset_alpha = vert_index_alpha * sizeof(VERTEX);
|
||
|
int vsize = 10000 * sizeof(VERTEX);
|
||
|
|
||
|
IDirect3DVertexBuffer9_Lock(static_vb, voffset, vsize, (void **)&vb, 0);
|
||
|
IDirect3DVertexBuffer9_Lock(static_vb_alpha, voffset_alpha, vsize, (void **)&vb_alpha, 0);
|
||
|
cache_model(&vb[0], &vb_alpha[0], mem, address, &num_triangles, &num_triangles_alpha);
|
||
|
IDirect3DVertexBuffer9_Unlock(static_vb_alpha);
|
||
|
IDirect3DVertexBuffer9_Unlock(static_vb);
|
||
|
|
||
|
static_mesh_cache[static_mesh_cache_top].vb_index = vert_index;
|
||
|
static_mesh_cache[static_mesh_cache_top].vb_index_alpha = vert_index_alpha;
|
||
|
static_mesh_cache[static_mesh_cache_top].num_vertices = num_triangles * 3;
|
||
|
static_mesh_cache[static_mesh_cache_top].num_vertices_alpha = num_triangles_alpha * 3;
|
||
|
|
||
|
static_mesh_cache_vertex_top += num_triangles * 3;
|
||
|
static_mesh_cache_vertex_top_alpha += num_triangles_alpha * 3;
|
||
|
|
||
|
static_mesh_index[address & 0xffffff] = static_mesh_cache_top;
|
||
|
mesh_index = static_mesh_cache_top;
|
||
|
|
||
|
static_mesh_cache_top++;
|
||
|
if (static_mesh_cache_top >= NUM_STATIC_MESHES)
|
||
|
{
|
||
|
printf("static mesh cache overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (static_mesh_cache_vertex_top >= STATIC_VB_SIZE)
|
||
|
{
|
||
|
printf("static vertex cache overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
if (static_mesh_cache_vertex_top_alpha >= STATIC_VB_SIZE)
|
||
|
{
|
||
|
printf("static vertex cache alpha overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memcpy(&static_mesh_buffer[static_mesh_buffer_top].normal, &world_view, sizeof(D3DMATRIX));
|
||
|
memcpy(&static_mesh_buffer[static_mesh_buffer_top].transform, &world_view_proj, sizeof(D3DMATRIX));
|
||
|
|
||
|
static_mesh_buffer[static_mesh_buffer_top].lighting = current_light;
|
||
|
static_mesh_buffer[static_mesh_buffer_top].viewport = current_viewport;
|
||
|
|
||
|
static_mesh_buffer[static_mesh_buffer_top].mesh_index = mesh_index;
|
||
|
|
||
|
static_mesh_buffer_top++;
|
||
|
if (static_mesh_buffer_top >= STATIC_MESH_BUFFER_SIZE)
|
||
|
{
|
||
|
printf("static mesh buffer overflow!\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void osd_renderer_begin_3d_scene(void)
|
||
|
{
|
||
|
dynamic_mesh_buffer_top = 0;
|
||
|
static_mesh_buffer_top = 0;
|
||
|
|
||
|
dynamic_mesh_cache_top = 0;
|
||
|
dynamic_mesh_cache_vertex_top = 0;
|
||
|
dynamic_mesh_cache_vertex_top_alpha = 0;
|
||
|
|
||
|
num_lights = 0;
|
||
|
num_viewports = 0;
|
||
|
}
|
||
|
|
||
|
void osd_renderer_end_3d_scene(void)
|
||
|
{
|
||
|
int i;
|
||
|
int end = 0;
|
||
|
int index = 0;
|
||
|
float mipmap_lod_bias;
|
||
|
|
||
|
int selected_viewport = -1;
|
||
|
int selected_lighting = -1;
|
||
|
|
||
|
IDirect3DDevice9_BeginScene(device);
|
||
|
|
||
|
IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
|
||
|
IDirect3DDevice9_SetVertexShader(device, vshader);
|
||
|
IDirect3DDevice9_SetPixelShader(device, pshader);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_FILLMODE, D3DFILL_SOLID);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_USEW);
|
||
|
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
|
||
|
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
|
||
|
// IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||
|
// IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
|
||
|
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||
|
IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
|
||
|
//IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
|
||
|
|
||
|
//mipmap_lod_bias = -4.0f;
|
||
|
//IDirect3DDevice9_SetSamplerState( device, 0, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)(&mipmap_lod_bias));
|
||
|
|
||
|
IDirect3DDevice9_SetTexture(device, 0, texture);
|
||
|
|
||
|
IDirect3DDevice9_SetStreamSourceFreq(device, 0, 1);
|
||
|
IDirect3DDevice9_SetStreamSource(device, 0, static_vb, 0, sizeof(VERTEX));
|
||
|
|
||
|
set_viewport(0, 0, 496, 384);
|
||
|
|
||
|
// render static meshes
|
||
|
for (i=0; i < static_mesh_buffer_top; i++)
|
||
|
{
|
||
|
D3DMATRIX *transform, *normal;
|
||
|
int num_triangles, vb_index;
|
||
|
|
||
|
int mesh_index = static_mesh_buffer[i].mesh_index;
|
||
|
vb_index = static_mesh_cache[mesh_index].vb_index;
|
||
|
num_triangles = static_mesh_cache[mesh_index].num_vertices / 3;
|
||
|
|
||
|
if (num_triangles > 0)
|
||
|
{
|
||
|
if (selected_viewport != static_mesh_buffer[i].viewport)
|
||
|
{
|
||
|
D3DVIEWPORT9 vp;
|
||
|
selected_viewport = static_mesh_buffer[i].viewport;
|
||
|
vp.X = viewport_params[selected_viewport].x;
|
||
|
vp.Y = viewport_params[selected_viewport].y;
|
||
|
vp.Width = viewport_params[selected_viewport].width;
|
||
|
vp.Height = viewport_params[selected_viewport].height;
|
||
|
vp.MinZ = min_z;
|
||
|
vp.MaxZ = max_z;
|
||
|
IDirect3DDevice9_SetViewport(device, &vp);
|
||
|
}
|
||
|
|
||
|
transform = &static_mesh_buffer[i].transform;
|
||
|
normal = &static_mesh_buffer[i].normal;
|
||
|
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 0, (float*)transform, 4);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 4, (float*)normal, 4);
|
||
|
|
||
|
if (selected_lighting != static_mesh_buffer[i].lighting)
|
||
|
{
|
||
|
selected_lighting = static_mesh_buffer[i].lighting;
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 16, (float*)&lighting_params[selected_lighting].sun_vector, 1);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 17, (float*)&lighting_params[selected_lighting].sun_params, 1);
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, vb_index, num_triangles);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_SetStreamSourceFreq(device, 0, 1);
|
||
|
IDirect3DDevice9_SetStreamSource(device, 0, dynamic_vb, 0, sizeof(VERTEX));
|
||
|
|
||
|
// render dynamic meshes
|
||
|
for (i=0; i < dynamic_mesh_buffer_top; i++)
|
||
|
{
|
||
|
D3DMATRIX *transform, *normal;
|
||
|
int num_triangles, vb_index;
|
||
|
|
||
|
int mesh_index = dynamic_mesh_buffer[i].mesh_index;
|
||
|
vb_index = dynamic_mesh_cache[mesh_index].vb_index;
|
||
|
num_triangles = dynamic_mesh_cache[mesh_index].num_vertices / 3;
|
||
|
|
||
|
if (num_triangles > 0)
|
||
|
{
|
||
|
|
||
|
if (selected_viewport != dynamic_mesh_buffer[i].viewport)
|
||
|
{
|
||
|
D3DVIEWPORT9 vp;
|
||
|
selected_viewport = dynamic_mesh_buffer[i].viewport;
|
||
|
vp.X = viewport_params[selected_viewport].x;
|
||
|
vp.Y = viewport_params[selected_viewport].y;
|
||
|
vp.Width = viewport_params[selected_viewport].width;
|
||
|
vp.Height = viewport_params[selected_viewport].height;
|
||
|
vp.MinZ = min_z;
|
||
|
vp.MaxZ = max_z;
|
||
|
IDirect3DDevice9_SetViewport(device, &vp);
|
||
|
}
|
||
|
|
||
|
transform = &dynamic_mesh_buffer[i].transform;
|
||
|
normal = &dynamic_mesh_buffer[i].normal;
|
||
|
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 0, (float*)transform, 4);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 4, (float*)normal, 4);
|
||
|
|
||
|
if (selected_lighting != dynamic_mesh_buffer[i].lighting)
|
||
|
{
|
||
|
selected_lighting = dynamic_mesh_buffer[i].lighting;
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 16, (float*)&lighting_params[selected_lighting].sun_vector, 1);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 17, (float*)&lighting_params[selected_lighting].sun_params, 1);
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, vb_index, num_triangles);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// render alpha polys
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||
|
IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
|
||
|
|
||
|
IDirect3DDevice9_SetStreamSourceFreq(device, 0, 1);
|
||
|
IDirect3DDevice9_SetStreamSource(device, 0, dynamic_vb_alpha, 0, sizeof(VERTEX));
|
||
|
|
||
|
// render dynamic meshes
|
||
|
//for (i=dynamic_mesh_buffer_top-1; i >= 0; i--)
|
||
|
for (i=0; i < dynamic_mesh_buffer_top; i++)
|
||
|
{
|
||
|
D3DMATRIX *transform, *normal;
|
||
|
int num_triangles, vb_index;
|
||
|
|
||
|
int mesh_index = dynamic_mesh_buffer[i].mesh_index;
|
||
|
vb_index = dynamic_mesh_cache[mesh_index].vb_index_alpha;
|
||
|
num_triangles = dynamic_mesh_cache[mesh_index].num_vertices_alpha / 3;
|
||
|
|
||
|
if (num_triangles > 0)
|
||
|
{
|
||
|
if (selected_viewport != dynamic_mesh_buffer[i].viewport)
|
||
|
{
|
||
|
D3DVIEWPORT9 vp;
|
||
|
selected_viewport = dynamic_mesh_buffer[i].viewport;
|
||
|
vp.X = viewport_params[selected_viewport].x;
|
||
|
vp.Y = viewport_params[selected_viewport].y;
|
||
|
vp.Width = viewport_params[selected_viewport].width;
|
||
|
vp.Height = viewport_params[selected_viewport].height;
|
||
|
vp.MinZ = min_z;
|
||
|
vp.MaxZ = max_z;
|
||
|
IDirect3DDevice9_SetViewport(device, &vp);
|
||
|
}
|
||
|
|
||
|
transform = &dynamic_mesh_buffer[i].transform;
|
||
|
normal = &dynamic_mesh_buffer[i].normal;
|
||
|
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 0, (float*)transform, 4);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 4, (float*)normal, 4);
|
||
|
|
||
|
if (selected_lighting != dynamic_mesh_buffer[i].lighting)
|
||
|
{
|
||
|
selected_lighting = dynamic_mesh_buffer[i].lighting;
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 16, (float*)&lighting_params[selected_lighting].sun_vector, 1);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 17, (float*)&lighting_params[selected_lighting].sun_params, 1);
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, vb_index, num_triangles);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_SetStreamSourceFreq(device, 0, 1);
|
||
|
IDirect3DDevice9_SetStreamSource(device, 0, static_vb_alpha, 0, sizeof(VERTEX));
|
||
|
|
||
|
// render static meshes
|
||
|
//for (i=static_mesh_buffer_top-1; i >= 0; i--)
|
||
|
for (i=0; i < static_mesh_buffer_top; i++)
|
||
|
{
|
||
|
D3DMATRIX *transform, *normal;
|
||
|
int num_triangles, vb_index;
|
||
|
|
||
|
int mesh_index = static_mesh_buffer[i].mesh_index;
|
||
|
vb_index = static_mesh_cache[mesh_index].vb_index_alpha;
|
||
|
num_triangles = static_mesh_cache[mesh_index].num_vertices_alpha / 3;
|
||
|
|
||
|
if (num_triangles > 0)
|
||
|
{
|
||
|
if (selected_viewport != static_mesh_buffer[i].viewport)
|
||
|
{
|
||
|
D3DVIEWPORT9 vp;
|
||
|
selected_viewport = static_mesh_buffer[i].viewport;
|
||
|
vp.X = viewport_params[selected_viewport].x;
|
||
|
vp.Y = viewport_params[selected_viewport].y;
|
||
|
vp.Width = viewport_params[selected_viewport].width;
|
||
|
vp.Height = viewport_params[selected_viewport].height;
|
||
|
vp.MinZ = min_z;
|
||
|
vp.MaxZ = max_z;
|
||
|
IDirect3DDevice9_SetViewport(device, &vp);
|
||
|
}
|
||
|
|
||
|
transform = &static_mesh_buffer[i].transform;
|
||
|
normal = &static_mesh_buffer[i].normal;
|
||
|
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 0, (float*)transform, 4);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 4, (float*)normal, 4);
|
||
|
|
||
|
if (selected_lighting != static_mesh_buffer[i].lighting)
|
||
|
{
|
||
|
selected_lighting = static_mesh_buffer[i].lighting;
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 16, (float*)&lighting_params[selected_lighting].sun_vector, 1);
|
||
|
IDirect3DDevice9_SetVertexShaderConstantF(device, 17, (float*)&lighting_params[selected_lighting].sun_params, 1);
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, vb_index, num_triangles);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IDirect3DDevice9_EndScene(device);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_set_light( int light_num, LIGHT* param )
|
||
|
{
|
||
|
switch(param->type)
|
||
|
{
|
||
|
case LIGHT_PARALLEL:
|
||
|
lighting_params[num_lights].sun_vector.x = -param->u * view_matrix._11;
|
||
|
lighting_params[num_lights].sun_vector.y = param->v * view_matrix._22;
|
||
|
lighting_params[num_lights].sun_vector.z = -param->w * view_matrix._33;
|
||
|
lighting_params[num_lights].sun_vector.w = 1.0f;
|
||
|
|
||
|
lighting_params[num_lights].sun_params.x = param->diffuse_intensity;
|
||
|
lighting_params[num_lights].sun_params.y = param->ambient_intensity;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
error("Direct3D error: Unsupported light type: %d",param->type);
|
||
|
}
|
||
|
|
||
|
current_light = num_lights;
|
||
|
|
||
|
num_lights++;
|
||
|
if (num_lights >= MAX_LIGHTS)
|
||
|
{
|
||
|
error("Too many lights!");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void osd_renderer_set_viewport(const VIEWPORT* vp)
|
||
|
{
|
||
|
float fov = D3DXToRadian( (float)(vp->up + vp->down) );
|
||
|
float aspect_ratio = (float)((float)vp->width / (float)vp->height);
|
||
|
|
||
|
float x = vp->x;
|
||
|
float y = vp->y;
|
||
|
float w = vp->width;
|
||
|
float h = vp->height;
|
||
|
|
||
|
viewport_params[num_viewports].x = x;
|
||
|
viewport_params[num_viewports].y = y;
|
||
|
viewport_params[num_viewports].width = w;
|
||
|
viewport_params[num_viewports].height = h;
|
||
|
|
||
|
current_viewport = num_viewports;
|
||
|
|
||
|
num_viewports++;
|
||
|
if (num_viewports >= MAX_VIEWPORTS)
|
||
|
{
|
||
|
error("Too many viewports!");
|
||
|
}
|
||
|
|
||
|
D3DXMatrixPerspectiveFovLH(&projection_matrix, fov, aspect_ratio, min_z, max_z);
|
||
|
}
|
||
|
|
||
|
////////////////////////
|
||
|
// Matrix Stack //
|
||
|
////////////////////////
|
||
|
|
||
|
static D3DMATRIX matrix_to_d3d( const MATRIX m )
|
||
|
{
|
||
|
D3DMATRIX c;
|
||
|
memcpy( &c, m, sizeof(MATRIX) );
|
||
|
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
static int stack_ptr = 0;
|
||
|
|
||
|
static void d3d_matrix_stack_init(void)
|
||
|
{
|
||
|
matrix_stack->lpVtbl->LoadIdentity(matrix_stack);
|
||
|
}
|
||
|
|
||
|
static D3DXMATRIX d3d_matrix_stack_get_top(void)
|
||
|
{
|
||
|
D3DXMATRIX *m = matrix_stack->lpVtbl->GetTop(matrix_stack);
|
||
|
return *m;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* void osd_renderer_push_matrix(void);
|
||
|
*
|
||
|
* Pushes a matrix on to the stack. The matrix pushed is the former top of the
|
||
|
* stack.
|
||
|
*/
|
||
|
|
||
|
void osd_renderer_push_matrix(void)
|
||
|
{
|
||
|
stack_ptr++;
|
||
|
matrix_stack->lpVtbl->Push(matrix_stack);
|
||
|
|
||
|
if (stack_ptr >= 256)
|
||
|
{
|
||
|
error("Matrix stack overflow\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* void osd_renderer_pop_matrix(void);
|
||
|
*
|
||
|
* Pops a matrix off the top of the stack.
|
||
|
*/
|
||
|
|
||
|
void osd_renderer_pop_matrix(void)
|
||
|
{
|
||
|
stack_ptr--;
|
||
|
if( stack_ptr >= 0)
|
||
|
matrix_stack->lpVtbl->Pop(matrix_stack);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* void osd_renderer_multiply_matrix(MATRIX m);
|
||
|
*
|
||
|
* Multiplies the top of the matrix stack by the specified matrix
|
||
|
*
|
||
|
* Parameters:
|
||
|
* m = Matrix to multiply.
|
||
|
*/
|
||
|
|
||
|
void osd_renderer_multiply_matrix( MATRIX m )
|
||
|
{
|
||
|
D3DMATRIX x = matrix_to_d3d( m );
|
||
|
matrix_stack->lpVtbl->MultMatrixLocal(matrix_stack, &x );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* void osd_renderer_translate_matrix(float x, float y, float z);
|
||
|
*
|
||
|
* Translates the top of the matrix stack.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* x = Translation along X axis.
|
||
|
* y = Y axis.
|
||
|
* z = Z axis.
|
||
|
*/
|
||
|
|
||
|
void osd_renderer_translate_matrix( float x, float y, float z )
|
||
|
{
|
||
|
//stack->lpVtbl->TranslateLocal(stack, x, y, z );
|
||
|
D3DMATRIX t;
|
||
|
t._11 = 1.0f; t._12 = 0.0f; t._13 = 0.0f; t._14 = 0.0f;
|
||
|
t._21 = 0.0f; t._22 = 1.0f; t._23 = 0.0f; t._24 = 0.0f;
|
||
|
t._31 = 0.0f; t._32 = 0.0f; t._33 = 1.0f; t._34 = 0.0f;
|
||
|
t._41 = x; t._42 = y; t._43 = z; t._44 = 1.0f;
|
||
|
matrix_stack->lpVtbl->MultMatrixLocal(matrix_stack,&t);
|
||
|
}
|
||
|
|
||
|
// Mipmap starting positions for each level
|
||
|
static const int mipmap_xpos[] =
|
||
|
{ 0, 1024, 1536, 1792, 1920, 1984, 2016, 2032, 2040, 2044, 2046, 2047 };
|
||
|
static const int mipmap_ypos[] =
|
||
|
{ 0, 512, 768, 896, 960, 992, 1008, 1016, 1020, 1022, 1023, 0 };
|
||
|
|
||
|
void renderer_upload_texture(int x, int y, int u, int v, int width, int height, void *data, int mip_level)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
int i, j;
|
||
|
D3DLOCKED_RECT rect;
|
||
|
UINT16 *s = (UINT16*)data;
|
||
|
UINT32 *d;
|
||
|
int pitch;
|
||
|
RECT texture_rect;
|
||
|
|
||
|
if (mip_level > 3)
|
||
|
return;
|
||
|
|
||
|
/*hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0);
|
||
|
d = (UINT32*)rect.pBits;
|
||
|
pitch = rect.Pitch / 4;
|
||
|
|
||
|
for (j=y; j < y+height; j++)
|
||
|
{
|
||
|
int index = j * pitch;
|
||
|
int u = x;
|
||
|
for (i=x; i < x+width; i++)
|
||
|
{
|
||
|
UINT16 c = s[(j * 2048) + u];
|
||
|
int r = ((c >> 10) & 0x1f) << 3;
|
||
|
int g = ((c >> 5) & 0x1f) << 3;
|
||
|
int b = ((c >> 0) & 0x1f) << 3;
|
||
|
d[index+i] = 0xff000000 | (r << 16) | (g << 8) | (b);
|
||
|
u++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (j=y; j < y+height; j++)
|
||
|
{
|
||
|
int index = (j+2048) * pitch;
|
||
|
int u = x;
|
||
|
for (i=x; i < x+width; i++)
|
||
|
{
|
||
|
UINT16 c = s[(j * 2048) + u];
|
||
|
int r = ((c >> 12) & 0xf) << 4;
|
||
|
int g = ((c >> 8) & 0xf) << 4;
|
||
|
int b = ((c >> 4) & 0xf) << 4;
|
||
|
int a = ((c >> 0) & 0xf) << 4;
|
||
|
d[index+i] = (a << 24) | (r << 16) | (g << 8) | (b);
|
||
|
u++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IDirect3DTexture9_UnlockRect(texture, 0);*/
|
||
|
|
||
|
u >>= mip_level;
|
||
|
v >>= mip_level;
|
||
|
width >>= mip_level;
|
||
|
height >>= mip_level;
|
||
|
|
||
|
texture_rect.left = u;
|
||
|
texture_rect.top = v;
|
||
|
texture_rect.right = u + width;
|
||
|
texture_rect.bottom = v + height;
|
||
|
|
||
|
hr = IDirect3DTexture9_LockRect(texture, mip_level, &rect, &texture_rect, 0);
|
||
|
if (!FAILED(hr))
|
||
|
{
|
||
|
d = (UINT32*)rect.pBits;
|
||
|
pitch = rect.Pitch / 4;
|
||
|
|
||
|
for (j=0; j < height; j++)
|
||
|
{
|
||
|
int index = j * pitch;
|
||
|
for (i=0; i < width; i++)
|
||
|
{
|
||
|
UINT16 c = s[((j+y) * 2048) + x + i];
|
||
|
int r = ((c >> 10) & 0x1f) << 3;
|
||
|
int g = ((c >> 5) & 0x1f) << 3;
|
||
|
int b = ((c >> 0) & 0x1f) << 3;
|
||
|
int a = (c & 0x8000) ? 0 : 0xff;
|
||
|
d[index+i] = (a << 24) | (r << 16) | (g << 8) | (b);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
IDirect3DTexture9_UnlockRect(texture, mip_level);
|
||
|
|
||
|
texture_rect.left = u;
|
||
|
texture_rect.top = v + (2048 >> mip_level);
|
||
|
texture_rect.right = u + width;
|
||
|
texture_rect.bottom = v + (2048 >> mip_level) + height;
|
||
|
|
||
|
hr = IDirect3DTexture9_LockRect(texture, mip_level, &rect, &texture_rect, 0);
|
||
|
if (!FAILED(hr))
|
||
|
{
|
||
|
d = (UINT32*)rect.pBits;
|
||
|
pitch = rect.Pitch / 4;
|
||
|
for (j=0; j < height; j++)
|
||
|
{
|
||
|
int index = j * pitch;
|
||
|
for (i=0; i < width; i++)
|
||
|
{
|
||
|
UINT16 c = s[((j+y) * 2048) + x + i];
|
||
|
int r = ((c >> 12) & 0xf) << 4;
|
||
|
int g = ((c >> 8) & 0xf) << 4;
|
||
|
int b = ((c >> 4) & 0xf) << 4;
|
||
|
int a = ((c >> 0) & 0xf) << 4;
|
||
|
d[index+i] = (a << 24) | (r << 16) | (g << 8) | (b);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
IDirect3DTexture9_UnlockRect(texture, mip_level);
|
||
|
}
|
||
|
|
||
|
void osd_renderer_invalidate_textures(UINT x, UINT y, int u, int v, UINT w, UINT h, UINT8 *texture_sheet, int miplevel)
|
||
|
{
|
||
|
renderer_upload_texture(x, y, u, v, w, h, texture_sheet, miplevel);
|
||
|
}
|