- // render.cpp 
-   
- // thanks ChaotikMind for optimizing the engine a bit :) 
-   
- #include "common.h" 
-   
-   
- // note: DirectX requires a C++ compiler. 
- #include "DirectX9/Include/d3d9.h" 
- #include "DirectX9/Include/d3dx9.h" 
-   
- // include the Direct3D library files 
- #pragma comment (lib, "DirectX9/Lib/x86/d3d9.lib") 
- #pragma comment (lib, "DirectX9/Lib/x86/d3dx9.lib") 
-   
-   
- // define this to display framerate 
- #define WANT_FRAMERATE 
-   
-   
- // handy macro to print a chatter channel reply 
- #define PRINT_CCREPLY(ccreply) \ 
- { \ 
-    Render_wprintf (rect.right, initial_height - combined_height, initial_width - rect.right, ALIGN_LEFT, ALIGN_TOP, ALIGN_LEFT, \ 
-                    chat_fontindex, (ccreply)->color, &rect, \ 
-                    L"["); \ 
-    Render_wprintf (rect.right, initial_height - combined_height, initial_width - rect.right, ALIGN_LEFT, ALIGN_TOP, ALIGN_LEFT, \ 
-                    chat_fontindex, RGBA_TO_RGBACOLOR (159, 159, 159, RGBACOLOR_ALPHA ((ccreply)->color)), &rect, \ 
-                    (ccreply)->channelname); \ 
-    Render_wprintf (rect.right, initial_height - combined_height, initial_width - rect.right, ALIGN_LEFT, ALIGN_TOP, ALIGN_LEFT, \ 
-                    chat_fontindex, (ccreply)->color, &rect, \ 
-                    L"] "); /* closing bracket + non-breakable space */ \ 
-    Render_wprintf (rect.right, initial_height - combined_height, initial_width - rect.right, ALIGN_LEFT, ALIGN_TOP, ALIGN_LEFT, \ 
-                    chat_fontindex, RGBA_TO_RGBACOLOR (159, 159, 159, RGBACOLOR_ALPHA ((ccreply)->color)), &rect, \ 
-                    (ccreply)->nickname); \ 
-    Render_wprintf (rect.right, initial_height - combined_height, initial_width - rect.right, ALIGN_LEFT, ALIGN_TOP, ALIGN_LEFT, \ 
-                    chat_fontindex, (ccreply)->color, &rect, \ 
-                    L": "); /* colon + non-breakable space */ \ 
-    if ((ccreply)->text != NULL) \ 
-       Render_wprintf (rect.right, initial_height - combined_height, initial_width - rect.right, ALIGN_LEFT, ALIGN_TOP, ALIGN_LEFT, \ 
-                       chat_fontindex, (ccreply)->color, &rect, \ 
-                       (ccreply)->text); \ 
- } 
-   
-   
- // handy macro to draw a GUI button 
- #define DRAW_BUTTON_IF_NEEDED(button) \ 
- { \ 
-    if ((button).state != 0) \ 
-       Render_DrawSprite (&sprites[(button).sprite_index], (button).left, (button).top, (button).width, (button).height, ((button).state == 2 ? 0xFF : 0x7F)); \ 
- } 
-   
-   
- // handy macro to draw a GUI text 
- #define DRAW_TEXT_IF_NEEDED(text) \ 
- { \ 
-    if ((text).is_displayed) \ 
-    { \ 
-       Render_wprintf ((int) ((text).xpos_percent * (float) initial_width) / 100, (int) ((text).ypos_percent * (float) initial_height) / 100, \ 
-                       (int) ((text).maxwidth_percent * (float) initial_width) / 100, (text).horizontal_align, (text).vertical_align, (text).text_align, (text).font_index, \ 
-                       ((text).want_fade ? \ 
-                        RGBACOLOR_SETALPHA ((text).color, \ 
-                                            (((text).appear_time + (text).disappear_time) * 0.5f > current_time ? \ 
-                                            /* fading in  */ (int) FadeFloat (0, RGBACOLOR_ALPHA ((text).color), (text).appear_time, (text).appear_time + 0.5f) : \ 
-                                            /* fading out */ (int) FadeFloat (RGBACOLOR_ALPHA ((text).color), 0, (text).disappear_time - 3.0f, (text).disappear_time))) : \ 
-                        (text).color), \ 
-                       NULL, (text).buffer); \ 
-       if ((text).disappear_time < current_time) \ 
-          (text).is_displayed = false; \ 
-    } \ 
- } 
-   
-   
- #pragma pack(push,1) 
-   
- // definition for a vector 
- typedef struct vector_s 
- { 
-    float x; // X component 
-    float y; // Y component 
-    float z; // Z component 
- } vector_t; 
-   
-   
- // definition for a texture coordinates pair 
- typedef struct texcoord_s 
- { 
-    float u; // X coordinate of the texture point this vertex corresponds to 
-    float v; // Y coordinate of the texture point this vertex corresponds to 
- } texcoord_t; 
-   
-   
- // definition for a vertex (must be in that order for Direct3D) 
- typedef struct vertex_s 
- { 
-    vector_t position; // position in space 
-    vector_t normal; // coordinates of the unary normal vector of the plane this vertex is on (for illumination) 
-    texcoord_t texcoord; // coordinates of the texture point this vertex corresponds to 
- } vertex_t; 
-   
- #pragma pack(pop) 
-   
-   
- // definition for a reflected object (qsort array element to sort reflections by distance) 
- typedef struct reflectedobject_s 
- { 
-    sceneobject_t *object; // pointer to the scene object 
-    float distance; // distance to viewer camera 
- } reflectedobject_t; 
-   
-   
- // definition for a material (light reflection type) 
- typedef struct material_s 
- { 
-    wchar_t name[32]; // material name 
-    float ambient; // ambient reflection value ranging from 0 to 1 
-    float diffuse; // diffuse reflection value ranging from 0 to 1 
-    float emissive; // emissive reflection value ranging from 0 to 1 
-    float specular; // specular reflection value ranging from 0 to 1 
-    float shininess; // shininess (specular factor) 
-    float transparency; // transparency value ranging from 0 (fully transparent) to 1 (opaque) 
- } material_t; 
-   
-   
- // definition for a mesh 
- typedef struct mesh_s 
- { 
-    unsigned long hash; // basic content hash, to avoid duplicates 
-    unsigned long vertex_format; 
-    IDirect3DVertexBuffer9 *d3dvertices; // handled opaquely by Direct3D 
-    int vertice_size; 
-    int vertice_count; 
-    bool is_indexed; // set to TRUE if this mesh has an index buffer 
-    IDirect3DIndexBuffer9 *d3dindices; // handled opaquely by Direct3D 
-    int indice_size; 
-    int indice_count; 
- } mesh_t; 
-   
-   
- // definition for a texture 
- typedef struct texture_s 
- { 
-    unsigned long hash; // basic content hash, to avoid duplicates 
-    int width; 
-    int height; 
-    IDirect3DTexture9 *texture; 
- } texture_t; 
-   
-   
- // definition for a font 
- typedef struct font_s 
- { 
-    unsigned long pathname_hash; 
-    ID3DXFont *font; 
- } font_t; 
-   
-   
- // definition for a sprite 
- typedef struct sprite_s 
- { 
-    unsigned long hash; // basic content hash, to avoid duplicates 
-    ID3DXSprite *sprite; 
-    int texture_index; 
- } sprite_t; 
-   
-   
- // global variables used in this module only 
- static IDirect3D9 *d3d = NULL; // our Direct3D interface 
- static IDirect3DDevice9 *d3ddev = NULL; // the device class 
-   
- static material_t *materials = NULL; 
- static int material_count = 0; 
- static texture_t *textures = NULL; 
- static int texture_count = 0; 
- static mesh_t *meshes = NULL; 
- static int mesh_count = 0; 
- static font_t *fonts = NULL; 
- static int font_count = 0; 
- static sprite_t *sprites = NULL; 
- static int sprite_count = 0; 
- static const float fov_value = 45.0f; // field of view width, in degrees 
- static const float viewdist_near = 1.0f; // nearest view plane distance 
- static const float viewdist_far = 200.0f; // farthest view plane distance 
- static int initial_width = 0; // initial width of the render surface, in pixels (typically equal to the max displayable size) 
- static int initial_height = 0; // initial height of the render surface, in pixels (typically equal to the max displayable size) 
- static float current_width = 0.0f; // current width of the client area on which the render surface is rendered, in pixels 
- static float current_height = 0.0f; // current height of the client area on which the render surface is rendered, in pixels 
- static D3DCOLOR ambient_light; 
- static vector_t camera_position; 
- static const vector_t scene_center = { 0.0f, 0.0f, 0.0f }; 
- static const vector_t upwards_direction = { 0.0f, 0.0f, 1.0f }; 
- static int best_supported_filter; 
- static bool is_fsaa_supported = false; 
-   
- static wchar_t printf_buffer[0xffff]; 
-   
-   
- // prototypes of functions used in this module only 
- static bool Render_LoadMesh_X (mesh_t *mesh, const wchar_t *xfile_pathname); 
- static bool Render_LoadMesh_Obj (mesh_t *mesh, const wchar_t *objfile_pathname); 
- static void Render_DrawSceneObjectReflection (sceneobject_t *sceneobject); 
- static void Render_DrawSceneObject (sceneobject_t *sceneobject); 
- static void Render_DrawSceneTile (sceneobject_t *sceneobject); 
- static void Render_DrawSprite (sprite_t *sprite, float x_percent, float y_percent, float width_percent, float height_percent, int alpha); 
- static void Render_GetTextBoundaries (int max_width, int font_id, wchar_t *text, RECT *rect); 
- static void Render_wprintf (int x, int y, int max_width, int horiz_align, int vert_align, int text_align, int font_id, unsigned long color_rgba, RECT *out_rect, const wchar_t *fmt, ...); 
- static float DistanceToCamera (float x, float y, float z); 
- static float FadeFloat (float from, float to, float start_time, float end_time); 
- static unsigned long HashString (const wchar_t *string_buffer); 
- static unsigned long HashFile (const wchar_t *file_pathname); 
- static void ResolveWildcard (wchar_t *file_pathname, wchar_t *extensions_separated_by_bars); 
- static int SortReflectedObjects (const void *object1, const void *object2); 
-   
-   
- bool Render_Init (void) 
- { 
-    // this function sets up and initializes Direct3D 
-   
-    static wchar_t *default_materialname = L"default"; 
-   
-    D3DCAPS9 device_capabilities; 
-    unsigned long behaviour_flags; 
-    unsigned long multisample_quality_count; 
-    D3DPRESENT_PARAMETERS d3dpp; 
-    wchar_t errorfile_path[MAX_PATH]; 
-    wchar_t line_buffer[256]; 
-    material_t material; 
-    HRESULT ret; 
-    RECT rect; 
-    RECT viewport_rect; 
-    FILE *fp; 
-   
-    // create the Direct3D interface 
-    d3d = Direct3DCreate9 (D3D_SDK_VERSION); 
-   
-    // get hardware capabilities 
-    if (FAILED (d3d->GetDeviceCaps (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &device_capabilities))) 
-    { 
-       MessageBox (NULL, LOCALIZE (L"Error_CouldNotCreateD3DDevGetDeviceCapsFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-       return (false); 
-    } 
-   
-    // grab info from that and adjust our D3D settings 
-    best_supported_filter = (device_capabilities.RasterCaps & D3DPRASTERCAPS_ANISOTROPY ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR); 
-    behaviour_flags = (device_capabilities.VertexProcessingCaps != 0 ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING); 
-   
-    // see if simple (non-maskable) full-scene antialiasing is supported and in how many quality flavors 
-    if (SUCCEEDED (d3d->CheckDeviceMultiSampleType (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, false, D3DMULTISAMPLE_NONMASKABLE, &multisample_quality_count))) 
-       is_fsaa_supported = true; // remember FSAA is supported 
-   
-    memset (&d3dpp, 0, sizeof (d3dpp)); // clear out the struct for use 
-    d3dpp.Windowed = true; // always windowed (because we can't display dialog boxes in fullscreen mode) 
-    d3dpp.BackBufferCount = 1; 
-    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames 
-    d3dpp.hDeviceWindow = hMainWnd; // set the window to be used by Direct3D 
-    d3dpp.EnableAutoDepthStencil = true; // enable Z-buffer and stencil buffer 
-    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; // D3DFMT_D15S1 15 bits should be enough to store each pixel's Z depth 
-    if (is_fsaa_supported) 
-    { 
-       d3dpp.MultiSampleType = D3DMULTISAMPLE_NONMASKABLE; // use multisampling (full scene antialiasing) if supported 
-       d3dpp.MultiSampleQuality = multisample_quality_count - 1; // use the best available multisample quality 
-    } 
-    else 
-    { 
-       d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; // do not use multisampling (full scene antialiasing) 
-       d3dpp.MultiSampleQuality = 0; 
-    } 
-   
-    // get main window's current rectangle and full screen size 
-    GetWindowRect (hMainWnd, &rect); 
-   
-    // create a device class using this information and the info from the d3dpp stuct. Resize the window to the max displayable 
-    // size before creating the DirectX device, so as to guarantee the viewport will never be upscaled in case of window resize. 
-    MoveWindow (hMainWnd, rect.left, rect.top, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), false); 
-    if (FAILED (ret = d3d->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hMainWnd, behaviour_flags, &d3dpp, &d3ddev))) 
-    { 
-       MessageBox (NULL, LOCALIZE (L"Error_CouldNotCreateD3DDevCreateDeviceFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-   
-       // on error, write a log file on the user's desktop 
-       errorfile_path[0] = 0; 
-       SHGetSpecialFolderPath (NULL, errorfile_path, CSIDL_DESKTOP, true); 
-       wcscat_s (errorfile_path, WCHAR_SIZEOF (errorfile_path), L"\\Chess Giants error.log"); 
-       _wfopen_s (&fp, errorfile_path, L"w, ccs=UNICODE"); 
-       if (fp != NULL) 
-       { 
-          fwprintf (fp, L"device_capabilities.DeviceType = %d\n", device_capabilities.DeviceType); 
-          fwprintf (fp, L"device_capabilities.AdapterOrdinal = %ul\n", device_capabilities.AdapterOrdinal); 
-          fwprintf (fp, L"device_capabilities.Caps = %ul\n", device_capabilities.Caps); 
-          fwprintf (fp, L"device_capabilities.Caps2 = %ul\n", device_capabilities.Caps2); 
-          fwprintf (fp, L"device_capabilities.Caps3 = %ul\n", device_capabilities.Caps3); 
-          fwprintf (fp, L"device_capabilities.PresentationIntervals = %ul\n", device_capabilities.PresentationIntervals); 
-          fwprintf (fp, L"device_capabilities.CursorCaps = %ul\n", device_capabilities.CursorCaps); 
-          fwprintf (fp, L"device_capabilities.DevCaps = %ul\n", device_capabilities.DevCaps); 
-          fwprintf (fp, L"device_capabilities.PrimitiveMiscCaps = %ul\n", device_capabilities.PrimitiveMiscCaps); 
-          fwprintf (fp, L"device_capabilities.RasterCaps = %ul\n", device_capabilities.RasterCaps); 
-          fwprintf (fp, L"device_capabilities.ZCmpCaps = %ul\n", device_capabilities.ZCmpCaps); 
-          fwprintf (fp, L"device_capabilities.SrcBlendCaps = %ul\n", device_capabilities.SrcBlendCaps); 
-          fwprintf (fp, L"device_capabilities.DestBlendCaps = %ul\n", device_capabilities.DestBlendCaps); 
-          fwprintf (fp, L"device_capabilities.AlphaCmpCaps = %ul\n", device_capabilities.AlphaCmpCaps); 
-          fwprintf (fp, L"device_capabilities.ShadeCaps = %ul\n", device_capabilities.ShadeCaps); 
-          fwprintf (fp, L"device_capabilities.TextureCaps = %ul\n", device_capabilities.TextureCaps); 
-          fwprintf (fp, L"device_capabilities.TextureFilterCaps = %ul\n", device_capabilities.TextureFilterCaps); 
-          fwprintf (fp, L"device_capabilities.CubeTextureFilterCaps = %ul\n", device_capabilities.CubeTextureFilterCaps); 
-          fwprintf (fp, L"device_capabilities.VolumeTextureFilterCaps = %ul\n", device_capabilities.VolumeTextureFilterCaps); 
-          fwprintf (fp, L"device_capabilities.TextureAddressCaps = %ul\n", device_capabilities.TextureAddressCaps); 
-          fwprintf (fp, L"device_capabilities.VolumeTextureAddressCaps = %ul\n", device_capabilities.VolumeTextureAddressCaps); 
-          fwprintf (fp, L"device_capabilities.LineCaps = %ul\n", device_capabilities.LineCaps); 
-          fwprintf (fp, L"device_capabilities.MaxTextureWidth = %ul\n", device_capabilities.MaxTextureWidth); 
-          fwprintf (fp, L"device_capabilities.MaxTextureHeight = %ul\n", device_capabilities.MaxTextureHeight); 
-          fwprintf (fp, L"device_capabilities.MaxVolumeExtent = %ul\n", device_capabilities.MaxVolumeExtent); 
-          fwprintf (fp, L"device_capabilities.MaxTextureRepeat = %ul\n", device_capabilities.MaxTextureRepeat); 
-          fwprintf (fp, L"device_capabilities.MaxTextureAspectRatio = %ul\n", device_capabilities.MaxTextureAspectRatio); 
-          fwprintf (fp, L"device_capabilities.MaxAnisotropy = %ul\n", device_capabilities.MaxAnisotropy); 
-          fwprintf (fp, L"device_capabilities.MaxVertexW = %f\n", device_capabilities.MaxVertexW); 
-          fwprintf (fp, L"device_capabilities.GuardBandLeft = %f\n", device_capabilities.GuardBandLeft); 
-          fwprintf (fp, L"device_capabilities.GuardBandTop = %f\n", device_capabilities.GuardBandTop); 
-          fwprintf (fp, L"device_capabilities.GuardBandRight = %f\n", device_capabilities.GuardBandRight); 
-          fwprintf (fp, L"device_capabilities.GuardBandBottom = %f\n", device_capabilities.GuardBandBottom); 
-          fwprintf (fp, L"device_capabilities.ExtentsAdjust = %f\n", device_capabilities.ExtentsAdjust); 
-          fwprintf (fp, L"device_capabilities.StencilCaps = %ul\n", device_capabilities.StencilCaps); 
-          fwprintf (fp, L"device_capabilities.FVFCaps = %ul\n", device_capabilities.FVFCaps); 
-          fwprintf (fp, L"device_capabilities.TextureOpCaps = %ul\n", device_capabilities.TextureOpCaps); 
-          fwprintf (fp, L"device_capabilities.MaxTextureBlendStages = %ul\n", device_capabilities.MaxTextureBlendStages); 
-          fwprintf (fp, L"device_capabilities.MaxSimultaneousTextures = %ul\n", device_capabilities.MaxSimultaneousTextures); 
-          fwprintf (fp, L"device_capabilities.VertexProcessingCaps = %ul\n", device_capabilities.VertexProcessingCaps); 
-          fwprintf (fp, L"device_capabilities.MaxActiveLights = %ul\n", device_capabilities.MaxActiveLights); 
-          fwprintf (fp, L"device_capabilities.MaxUserClipPlanes = %ul\n", device_capabilities.MaxUserClipPlanes); 
-          fwprintf (fp, L"device_capabilities.MaxVertexBlendMatrices = %ul\n", device_capabilities.MaxVertexBlendMatrices); 
-          fwprintf (fp, L"device_capabilities.MaxVertexBlendMatrixIndex = %ul\n", device_capabilities.MaxVertexBlendMatrixIndex); 
-          fwprintf (fp, L"device_capabilities.MaxPointSize = %f\n", device_capabilities.MaxPointSize); 
-          fwprintf (fp, L"device_capabilities.MaxPrimitiveCount = %ul\n", device_capabilities.MaxPrimitiveCount); 
-          fwprintf (fp, L"device_capabilities.MaxVertexIndex = %ul\n", device_capabilities.MaxVertexIndex); 
-          fwprintf (fp, L"device_capabilities.MaxStreams = %ul\n", device_capabilities.MaxStreams); 
-          fwprintf (fp, L"device_capabilities.MaxStreamStride = %ul\n", device_capabilities.MaxStreamStride); 
-          fwprintf (fp, L"device_capabilities.VertexShaderVersion = %ul\n", device_capabilities.VertexShaderVersion); 
-          fwprintf (fp, L"device_capabilities.MaxVertexShaderConst = %ul\n", device_capabilities.MaxVertexShaderConst); 
-          fwprintf (fp, L"device_capabilities.PixelShaderVersion = %ul\n", device_capabilities.PixelShaderVersion); 
-          fwprintf (fp, L"device_capabilities.PixelShader1xMaxValue = %f\n", device_capabilities.PixelShader1xMaxValue); 
-          fwprintf (fp, L"device_capabilities.DevCaps2 = %ul\n", device_capabilities.DevCaps2); 
-          fwprintf (fp, L"device_capabilities.MaxNpatchTessellationLevel = %f\n", device_capabilities.MaxNpatchTessellationLevel); 
-          fwprintf (fp, L"device_capabilities.Reserved5 = %ul\n", device_capabilities.Reserved5); 
-          fwprintf (fp, L"device_capabilities.MasterAdapterOrdinal = %ul\n", device_capabilities.MasterAdapterOrdinal); 
-          fwprintf (fp, L"device_capabilities.AdapterOrdinalInGroup = %ul\n", device_capabilities.AdapterOrdinalInGroup); 
-          fwprintf (fp, L"device_capabilities.NumberOfAdaptersInGroup = %ul\n", device_capabilities.NumberOfAdaptersInGroup); 
-          fwprintf (fp, L"device_capabilities.DeclTypes = %ul\n", device_capabilities.DeclTypes); 
-          fwprintf (fp, L"device_capabilities.NumSimultaneousRTs = %ul\n", device_capabilities.NumSimultaneousRTs); 
-          fwprintf (fp, L"device_capabilities.StretchRectFilterCaps = %ul\n", device_capabilities.StretchRectFilterCaps); 
-          fwprintf (fp, L"device_capabilities.VS20Caps.Caps = %ul\n", device_capabilities.VS20Caps.Caps); 
-          fwprintf (fp, L"device_capabilities.VS20Caps.DynamicFlowControlDepth = %d\n", device_capabilities.VS20Caps.DynamicFlowControlDepth); 
-          fwprintf (fp, L"device_capabilities.VS20Caps.NumTemps = %d\n", device_capabilities.VS20Caps.NumTemps); 
-          fwprintf (fp, L"device_capabilities.VS20Caps.StaticFlowControlDepth = %d\n", device_capabilities.VS20Caps.StaticFlowControlDepth); 
-          fwprintf (fp, L"device_capabilities.PS20Caps.Caps = %ul\n", device_capabilities.PS20Caps.Caps); 
-          fwprintf (fp, L"device_capabilities.PS20Caps.DynamicFlowControlDepth = %d\n", device_capabilities.PS20Caps.DynamicFlowControlDepth); 
-          fwprintf (fp, L"device_capabilities.PS20Caps.NumTemps = %d\n", device_capabilities.PS20Caps.NumTemps); 
-          fwprintf (fp, L"device_capabilities.PS20Caps.StaticFlowControlDepth = %d\n", device_capabilities.PS20Caps.StaticFlowControlDepth); 
-          fwprintf (fp, L"device_capabilities.PS20Caps.NumInstructionSlots = %d\n", device_capabilities.PS20Caps.NumInstructionSlots); 
-          fwprintf (fp, L"device_capabilities.VertexTextureFilterCaps = %ul\n", device_capabilities.VertexTextureFilterCaps); 
-          fwprintf (fp, L"device_capabilities.MaxVShaderInstructionsExecuted = %ul\n", device_capabilities.MaxVShaderInstructionsExecuted); 
-          fwprintf (fp, L"device_capabilities.MaxPShaderInstructionsExecuted = %ul\n", device_capabilities.MaxPShaderInstructionsExecuted); 
-          fwprintf (fp, L"device_capabilities.MaxVertexShader30InstructionSlots = %ul\n", device_capabilities.MaxVertexShader30InstructionSlots); 
-          fwprintf (fp, L"device_capabilities.MaxPixelShader30InstructionSlots = %ul\n", device_capabilities.MaxPixelShader30InstructionSlots); 
-          fwprintf (fp, L"========\n"); 
-          fwprintf (fp, L"(guessed) behaviour_flags = %ul\n", behaviour_flags); 
-          fwprintf (fp, L"========\n"); 
-          fwprintf (fp, L"d3dpp.MultiSampleType = %d\n", d3dpp.MultiSampleType); 
-          fwprintf (fp, L"d3dpp.MultiSampleQuality = %d\n", d3dpp.MultiSampleQuality); 
-          fwprintf (fp, L"========\n"); 
-          fwprintf (fp, L"d3d->CreateDevice() returned %d\n", (int) ret); 
-          fclose (fp); 
-   
-          MessageBox (NULL, LOCALIZE (L"Error_GameCouldNotStartPleaseSendLogToAuthor"), LOCALIZE (L"Information"), MB_ICONINFORMATION | MB_OK); 
-       } 
-       else 
-          MessageBox (NULL, LOCALIZE (L"Error_CouldNotWriteToLogFile"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-   
-       return (false); 
-    } 
-   
-    // save the viewport's width and height 
-    GetClientRect (hMainWnd, &viewport_rect); 
-    initial_width = viewport_rect.right; 
-    initial_height = viewport_rect.bottom; 
-   
-    // now resize the window to its original size 
-    MoveWindow (hMainWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, false); 
-   
-    // set the texture parameters 
-    d3ddev->SetSamplerState (0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); // wrap textures around their edges 
-    d3ddev->SetSamplerState (0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); 
-    d3ddev->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); // and modulate their alpha with the material's alpha 
-    d3ddev->SetTextureStageState (0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); 
-    d3ddev->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 
-   
-    // enable the Z buffer 
-    d3ddev->SetRenderState (D3DRS_ZENABLE, true); 
-   
-    // disable the stencil buffer 
-    d3ddev->SetRenderState (D3DRS_STENCILENABLE, false); 
-   
-    // normalize the face normals (if we don't, scaling will cause problems with lighting computations) 
-    d3ddev->SetRenderState (D3DRS_NORMALIZENORMALS, true); 
-   
-    // turn on alpha blending 
-    d3ddev->SetRenderState (D3DRS_ALPHABLENDENABLE, true); 
-    d3ddev->SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_ADD); 
-    d3ddev->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 
-    d3ddev->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
-   
-    // use all of the materials' light reflection properties 
-    d3ddev->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); 
-    d3ddev->SetRenderState (D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); 
-    d3ddev->SetRenderState (D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL); 
-    d3ddev->SetRenderState (D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); 
-    d3ddev->SetRenderState (D3DRS_COLORVERTEX, false); 
-   
-    // enable 3D lighting 
-    d3ddev->SetRenderState (D3DRS_LIGHTING, true); 
-   
-    // open and parse the materials file and build the materials list 
-    materials = NULL; 
-    material_count = 0; 
-    _wfopen_s (&fp, L"materials.cfg", L"r, ccs=UNICODE"); 
-    if (fp != NULL) 
-    { 
-       // read line per line... 
-       while (fgetws (line_buffer, WCHAR_SIZEOF (line_buffer), fp) != NULL) 
-       { 
-          // can we read a complete material line ? 
-          if (swscanf_s (line_buffer, L"\"%[^\"]\" %f %f %f %f %f %f", material.name, WCHAR_SIZEOF (material.name), &material.ambient, &material.diffuse, &material.emissive, &material.specular, &material.shininess, &material.transparency) == 7) 
-          { 
-             materials = (material_t *) SAFE_realloc (materials, material_count, material_count + 1, sizeof (material_t), false); 
-             memcpy (&materials[material_count], &material, sizeof (material_t)); 
-             material_count++; // if so, append this new material to the materials array 
-          } 
-       } 
-       fclose (fp); // finished, close the file 
-    } 
-    materials = (material_t *) SAFE_realloc (materials, material_count, material_count + 1, sizeof (material_t), false); 
-    wcscpy_s (materials[material_count].name, WCHAR_SIZEOF (materials[material_count].name), default_materialname); 
-    materials[material_count].ambient = 1.0f; 
-    materials[material_count].diffuse = 1.0f; 
-    materials[material_count].emissive = 0.0f; 
-    materials[material_count].specular = 0.0f; 
-    materials[material_count].shininess = 0.0f; 
-    materials[material_count].transparency = 1.0f; 
-    material_count++; // append a default material at the end of the array and we're all set 
-   
-    return (true); // finished 
- } 
-   
-   
- void Render_Shutdown (void) 
- { 
-    // this function shuts down the Direct3D interfaces and releases the Direct3D COM objects 
-   
-    int array_index; 
-   
-    // close and release font data 
-    SAFE_free ((void **) &fonts); 
-    font_count = 0; 
-   
-    // close and release sprite data 
-    SAFE_free ((void **) &sprites); 
-    sprite_count = 0; 
-   
-    // close and release meshes data 
-    if (meshes != NULL) 
-    { 
-       for (array_index = 0; array_index < mesh_count; array_index++) 
-       { 
-          if (meshes[array_index].d3dindices != NULL) 
-             meshes[array_index].d3dindices->Release (); 
-          meshes[array_index].d3dindices = NULL; 
-   
-          if (meshes[array_index].d3dvertices != NULL) 
-             meshes[array_index].d3dvertices->Release (); 
-          meshes[array_index].d3dvertices = NULL; 
-       } 
-    } 
-    meshes = NULL; 
-    mesh_count = 0; 
-   
-    // close and release texture data 
-    if (textures != NULL) 
-    { 
-       for (array_index = 0; array_index < texture_count; array_index++) 
-          if (textures[array_index].texture != NULL) 
-             textures[array_index].texture->Release (); 
-       SAFE_free ((void **) &textures); 
-    } 
-    texture_count = 0; 
-   
-    // close and release materials data 
-    SAFE_free ((void **) &materials); 
-    material_count = 0; 
-   
-    // close and release the 3D device 
-    if (d3ddev != NULL) 
-       d3ddev->Release (); 
-    d3ddev = NULL; 
-   
-    // close and release Direct3D 
-    if (d3d != NULL) 
-       d3d->Release (); 
-    d3d = NULL; 
-   
-    return; // finished 
- } 
-   
-   
- void Render_RenderFrame (scene_t *scene) 
- { 
-    // this is the function used to render a single frame 
-   
-    static int framerate_value = 0; 
-    static int framerate_count = 0; 
-    static float framerate_time = 0; 
-   
-    D3DXMATRIX scaling_matrix; 
-    D3DXMATRIX translation_matrix; 
-    D3DXMATRIX view_matrix; // the view transform matrix 
-    D3DXMATRIX projection_matrix; // the projection transform matrix 
-    D3DLIGHT9 dxlight; 
-    RECT rect; 
-    float angle; 
-    float sin_pitch; 
-    float sin_yaw; 
-    float cos_pitch; 
-    float cos_yaw; 
-    int light_index; 
-    int object_index; 
-    int cchistory_index; 
-    int cchistory_index2; 
-    int combined_width; 
-    int combined_height; 
-    light_t *light; 
-    ccreply_t *ccreply; 
-    sceneobject_t *sceneobject; 
-    reflectedobject_t *reflectedobjects; // mallocated 
-    int reflectedobject_count; 
-    reflectedobject_t *otherobjects; // mallocated 
-    int otherobject_count; 
-   
-    // get the device view port and save the actual width and height 
-    GetClientRect (hMainWnd, &rect); 
-    current_width = (float) rect.right; // they may differ from window width and window height 
-    current_height = (float) rect.bottom; // because of title bars, menus, borders, etc. 
-   
-    // clear the back buffer, the Z buffer and the stencil buffer 
-    d3ddev->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB (0, 0, 0), 1.0f, 0); 
-    d3ddev->BeginScene (); // begins the 3D scene 
-   
-    //////////////////////////////////////// 
-    // Setup scene lights 
-   
-    // There are three types of light : ambient, diffuse and specular. 
-    // Diffuse lights can be of type directional (sun), point (bulb) or spot (flashlight). 
-   
-    // The attenuation formula for point lights is : 
-    // Atten = 1 / (att0 + (att1 * d) + (att2 * d²)) 
-   
-    // In spot lights, Phi is the outer cone angle. Theta is the inner cone angle. 
-   
-    // set the default lighting color 
-    ambient_light = RGBACOLOR_TO_ARGBCOLOR (RGBACOLOR_FULLALPHA (theme->illum.ambient_light)); 
-    d3ddev->SetRenderState (D3DRS_AMBIENT, ambient_light); 
-   
-    // for each light... 
-    for (light_index = 0; light_index < theme->illum.light_count; light_index++) 
-    { 
-       light = &theme->illum.lights[light_index]; // quick access to light 
-   
-       memset (&dxlight, 0, sizeof (dxlight)); // clear out the dxlight struct for use 
-   
-       // set its type 
-       if (light->type == LIGHT_DIRECTIONAL) 
-          dxlight.Type = D3DLIGHT_DIRECTIONAL; // directional light (e.g, sun) 
-       else if (light->type == LIGHT_POINT) 
-          dxlight.Type = D3DLIGHT_POINT; // point light (e.g, light bulb) 
-       else if (light->type == LIGHT_SPOT) 
-          dxlight.Type = D3DLIGHT_SPOT; // spot light (e.g, flash light) 
-       else 
-       { 
-          d3ddev->LightEnable (light_index, false); // unknown light ; turn off light #index 
-          continue; // and proceed to the next one 
-       } 
-   
-       // set its parameters 
-       dxlight.Diffuse = D3DXCOLOR (RGBACOLOR_TO_ARGBCOLOR (RGBACOLOR_FULLALPHA (light->color))); 
-       dxlight.Specular = D3DXCOLOR (0xffffffff); 
-       dxlight.Position.x = light->pos_x; 
-       dxlight.Position.y = light->pos_y; 
-       dxlight.Position.z = light->pos_z; 
-       dxlight.Direction.x = light->direction_x; 
-       dxlight.Direction.y = light->direction_y; 
-       dxlight.Direction.z = light->direction_z; 
-       dxlight.Range = light->range; // light won't be computed after this distance 
-       dxlight.Attenuation0 = light->attenuation_constant; // constant attenuation, see formula 
-       dxlight.Attenuation1 = light->attenuation_proportional; // proportional attenuation, see formula 
-       dxlight.Attenuation2 = light->attenuation_square; // square attenuation, see formula 
-       dxlight.Phi = light->cone_outer * TO_RADIANS; // outer spot cone 
-       dxlight.Theta = light->cone_inner * TO_RADIANS; // inner spot cone 
-   
-       d3ddev->SetLight (light_index, &dxlight); // send the light struct properties to light #index 
-       d3ddev->LightEnable (light_index, true); // turn on light #index 
-    } 
-   
-    //////////////////////////////// 
-    // View transform 
-   
-    // compute the sine and cosine of the pitch component 
-    angle = current_pitch * TO_RADIANS; 
-    sin_pitch = sinf (angle); 
-    cos_pitch = cosf (angle); 
-   
-    // compute the sine and cosine of the yaw component 
-    angle = current_yaw * TO_RADIANS; 
-    sin_yaw = sinf (angle); 
-    cos_yaw = cosf (angle); 
-   
-    // build the camera position 
-    camera_position.x = (float) -(cos_pitch * cos_yaw) * current_distance; 
-    camera_position.y = (float) -(cos_pitch * sin_yaw) * current_distance; 
-    camera_position.z = (float) sin_pitch * current_distance; 
-   
-    // set up a view matrix 
-    D3DXMatrixLookAtLH (&view_matrix, 
-                        (D3DXVECTOR3 *) &camera_position, // camera position 
-                        (D3DXVECTOR3 *) &scene_center, // look-at position 
-                        (D3DXVECTOR3 *) &upwards_direction); // up direction 
-   
-    // tell Direct3D about our matrix 
-    d3ddev->SetTransform (D3DTS_VIEW, &view_matrix); 
-   
-    ///////////////////////////////////// 
-    // Projection transform 
-   
-    // set up a projection matrix 
-    D3DXMatrixPerspectiveFovLH (&projection_matrix, 
-                                fov_value * TO_RADIANS, // field of view width 
-                                current_width / current_height, // aspect ratio 
-                                viewdist_near, viewdist_far); // view plane distances 
-   
-    // tell Direct3D about our matrix 
-    d3ddev->SetTransform (D3DTS_PROJECTION, &projection_matrix); 
-   
-    ///////////////////////////////////// 
-    // End of the transforms 
-   
-    // if we want it, enable specular lighting 
-    d3ddev->SetRenderState (D3DRS_SPECULARENABLE, options.want_specularlighting); 
-   
-    // turn on texture filtering if needed 
-    if (options.want_filtering) 
-    { 
-       d3ddev->SetSamplerState (0, D3DSAMP_MINFILTER, best_supported_filter); 
-       d3ddev->SetSamplerState (0, D3DSAMP_MAGFILTER, best_supported_filter); 
-       d3ddev->SetSamplerState (0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); 
-   
-       // turn on fullscene antialiasing only if capable 
-       d3ddev->SetRenderState (D3DRS_MULTISAMPLEANTIALIAS, is_fsaa_supported); 
-    } 
-    else 
-    { 
-       d3ddev->SetSamplerState (0, D3DSAMP_MINFILTER, D3DTEXF_NONE); 
-       d3ddev->SetSamplerState (0, D3DSAMP_MAGFILTER, D3DTEXF_NONE); 
-       d3ddev->SetSamplerState (0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); 
-   
-       // turn off fullscene antialiasing 
-       d3ddev->SetRenderState (D3DRS_MULTISAMPLEANTIALIAS, false); 
-    } 
-   
-    ///////////////////////////////////////////////////////////// 
-    // draw the background elements. No need for a Z buffer here. 
-   
-    d3ddev->SetRenderState (D3DRS_ZENABLE, false); // disable depth testing 
-   
-    // draw the background sprite, if any 
-    if (scene->background_spriteindex >= 0) 
-       Render_DrawSprite (&sprites[scene->background_spriteindex], 0.0f, 0.0f, 100.0f, 100.0f, 0xFF); 
-   
-    // draw the table border 
-    Render_DrawSceneObject (&scene->objects[0]); 
-    Render_DrawSceneObject (&scene->objects[1]); 
-   
-    // draw the table and build the stencil buffer at the same time 
-    d3ddev->SetRenderState (D3DRS_STENCILENABLE, true); // enable the stencil buffer (i.e. the "frame" for drawing table reflections) 
-    d3ddev->SetRenderState (D3DRS_STENCILFUNC, D3DCMP_ALWAYS); // instruct how to fill it 
-    d3ddev->SetRenderState (D3DRS_STENCILPASS, D3DSTENCILOP_INCRSAT); // instruct how to fill it 
-    Render_DrawSceneObject (&scene->objects[2]); // draw the table squares in the stencil buffer 
-    d3ddev->SetRenderState (D3DRS_STENCILENABLE, false); // finished drawing the stencil buffer 
-   
-    d3ddev->SetRenderState (D3DRS_ZENABLE, true); // re-enable depth testing 
-   
-    //////////////////////////////////////////////////////////// 
-    // draw the scene objects and their reflections on the table 
-   
-    // start with the reflections if we want them, and if the table does it 
-    if (options.want_reflections && (theme->reflection_alpha > 0)) 
-    { 
-       // build an array of reflected objects with their distances 
-       reflectedobjects = NULL; 
-       reflectedobject_count = 0; 
-       otherobjects = NULL; 
-       otherobject_count = 0; 
-   
-       // cycle through all parts and see which ones need to be reflected 
-       for (object_index = 3; object_index < scene->object_count; object_index++) 
-       { 
-          sceneobject = &scene->objects[object_index]; // quick access to scene object 
-   
-          // is this object a mesh AND it's above the ground ? 
-          if ((sceneobject->mesh_index != -1) && (sceneobject->z > 0)) 
-          { 
-             // yes it is. It thus needs to be reflected, so add it to the list 
-             reflectedobjects = (reflectedobject_t *) SAFE_realloc (reflectedobjects, reflectedobject_count, reflectedobject_count + 1, sizeof (reflectedobject_t), false); 
-             reflectedobjects[reflectedobject_count].object = sceneobject; // save scene object 
-             reflectedobjects[reflectedobject_count].distance = DistanceToCamera (sceneobject->x, sceneobject->y, sceneobject->z); 
-             reflectedobject_count++; // we have now one object more to reflect 
-          } 
-          else 
-          { 
-             // no it's not. It doesn't need to be reflected, so add it to the other list 
-             otherobjects = (reflectedobject_t *) SAFE_realloc (otherobjects, otherobject_count, otherobject_count + 1, sizeof (reflectedobject_t), false); 
-             otherobjects[otherobject_count].object = sceneobject; // save scene object 
-             otherobjects[otherobject_count].distance = 0; 
-             otherobject_count++; // we have now one object more to reflect 
-          } 
-       } 
-   
-       // now sort them from farthest to closest and draw them in this order 
-       qsort (reflectedobjects, reflectedobject_count, sizeof (reflectedobject_t), SortReflectedObjects); 
-       for (object_index = 0; object_index < reflectedobject_count; object_index++) 
-          Render_DrawSceneObjectReflection (reflectedobjects[object_index].object); // draw the reflection 
-       for (object_index = 0; object_index < reflectedobject_count; object_index++) 
-          Render_DrawSceneObject (reflectedobjects[object_index].object); // and draw the objects afterwards 
-       for (object_index = 0; object_index < otherobject_count; object_index++) 
-          Render_DrawSceneObject (otherobjects[object_index].object); // finally, draw the non-reflected objects 
-   
-       SAFE_free ((void **) &reflectedobjects); // and free the reflected objects array 
-       SAFE_free ((void **) &otherobjects); // and the non-reflected objects array 
-    } 
-    else 
-       for (object_index = 3; object_index < scene->object_count; object_index++) 
-          Render_DrawSceneObject (&scene->objects[object_index]); // else if no reflections, draw the objects, the Z-buffer will sort them 
-   
-    // draw the overlay texture if required 
-    if (scene->overlay_spriteindex >= 0) 
-       Render_DrawSprite (&sprites[scene->overlay_spriteindex], 0.0f, 0.0f, 100.0f, 100.0f, 0x4F); 
-   
-    /////////////// 
-    // draw the GUI 
-   
-    // draw the arrows 
-    DRAW_BUTTON_IF_NEEDED (scene->gui.larrow); // left arrow 
-    DRAW_BUTTON_IF_NEEDED (scene->gui.rarrow); // right arrow 
-    DRAW_TEXT_IF_NEEDED (scene->gui.arrow_text); // arrow text 
-   
-    if (want_framerate) 
-       Render_wprintf (initial_width - 10, 10, 62, ALIGN_RIGHT, ALIGN_TOP, ALIGN_CENTER, arrow_fontindex, D3DCOLOR_RGBA (255, 255, 255, 255), NULL, 
-                       L"%d textures\n" 
-                       L"%d meshes\n" 
-                       L"%d fonts\n" 
-                       L"%d sprites\n" 
-                       L"%d fps", texture_count, mesh_count, font_count, sprite_count, framerate_value); 
-   
-    // draw the other GUI buttons 
-    DRAW_BUTTON_IF_NEEDED (scene->gui.chatbutton); // chat button 
-    DRAW_BUTTON_IF_NEEDED (scene->gui.gamesbutton); // games button 
-    DRAW_BUTTON_IF_NEEDED (scene->gui.peoplebutton); // people button 
-   
-    // does the parts pick line need to be displayed ? 
-    if (scene->gui.is_partspick_displayed) 
-    { 
- #define PARTSIZE_PCT (100.0f / 13.0f) 
-   
-       if (scene->gui.partspick_selectedpart == 'P')      Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  0.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'R') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  1.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'N') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  2.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'B') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  3.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'Q') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  4.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'K') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  5.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == ' ') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  6.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'k') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  7.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'q') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  8.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'b') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex],  9.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'n') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex], 10.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'r') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex], 11.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-       else if (scene->gui.partspick_selectedpart == 'p') Render_DrawSprite (&sprites[theme->lastmovetarget_spriteindex], 12.0f * PARTSIZE_PCT, 0.0f, PARTSIZE_PCT, 11.0f, 0xFF); 
-   
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_WHITE][PART_PAWN]],       0.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'P') || (scene->gui.partspick_selectedpart == 'P')) ? 0xFF : 0x7F)); // white pawn 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_WHITE][PART_ROOK]],       1.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'R') || (scene->gui.partspick_selectedpart == 'R')) ? 0xFF : 0x7F)); // white rook 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_WHITE][PART_KNIGHT]],     2.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'N') || (scene->gui.partspick_selectedpart == 'N')) ? 0xFF : 0x7F)); // white knight 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_WHITE][PART_BISHOP]],     3.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'B') || (scene->gui.partspick_selectedpart == 'B')) ? 0xFF : 0x7F)); // white bishop 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_WHITE][PART_QUEEN]],      4.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'Q') || (scene->gui.partspick_selectedpart == 'Q')) ? 0xFF : 0x7F)); // white queen 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_WHITE][PART_KING]],       5.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'K') || (scene->gui.partspick_selectedpart == 'K')) ? 0xFF : 0x7F)); // white king 
-       Render_DrawSprite (&sprites[theme->lastmovesource_spriteindex],         6.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == ' ') || (scene->gui.partspick_selectedpart == ' ')) ? 0xFF : 0x7F)); // erase mark 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_BLACK][PART_KING]],       7.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'k') || (scene->gui.partspick_selectedpart == 'k')) ? 0xFF : 0x7F)); // black king 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_BLACK][PART_QUEEN]],      8.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'q') || (scene->gui.partspick_selectedpart == 'q')) ? 0xFF : 0x7F)); // black queen 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_BLACK][PART_BISHOP]],     9.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'b') || (scene->gui.partspick_selectedpart == 'b')) ? 0xFF : 0x7F)); // black bishop 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_BLACK][PART_KNIGHT]],    10.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'n') || (scene->gui.partspick_selectedpart == 'n')) ? 0xFF : 0x7F)); // black knight 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_BLACK][PART_ROOK]],      11.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'r') || (scene->gui.partspick_selectedpart == 'r')) ? 0xFF : 0x7F)); // black rook 
-       Render_DrawSprite (&sprites[theme->flatsprites[COLOR_BLACK][PART_PAWN]],      12.0f * PARTSIZE_PCT, 0, PARTSIZE_PCT, 11.0f, (((scene->gui.partspick_hoveredpart == 'p') || (scene->gui.partspick_selectedpart == 'p')) ? 0xFF : 0x7F)); // black pawn 
-   
- #undef PARTSIZE_PCT 
-    } 
-   
-    // draw GUI texts 
-    DRAW_TEXT_IF_NEEDED (scene->gui.comment_text); // move comments 
-    DRAW_TEXT_IF_NEEDED (scene->gui.history_text); // game history 
-    DRAW_TEXT_IF_NEEDED (scene->gui.clock_text); // game clock 
-   
-    // draw the chatter channels text 
-    Render_GetTextBoundaries (-1, chat_fontindex, L"a", &rect); 
-    combined_height = rect.bottom; // get a string's height 
-   
-    // cycle through all the chat strings... 
-    ccreply = NULL; 
-    for (cchistory_index = 0; cchistory_index < scene->gui.cchistory_count; cchistory_index++) 
-    { 
-       ccreply = &scene->gui.cchistory[cchistory_index]; // quick access to CC reply 
-       if ((ccreply->text[0] != 0) && (ccreply->arrival_time + 60.0f > current_time)) 
-          break; // break at the first one that we should display 
-    } 
-   
-    // have we some to display ? 
-    if (cchistory_index < scene->gui.cchistory_count) 
-    { 
-       // first, get the remaining text's combined height 
-       for (cchistory_index2 = cchistory_index; cchistory_index2 < scene->gui.cchistory_count; cchistory_index2++) 
-       { 
-          ccreply = &scene->gui.cchistory[cchistory_index2]; // quick access to CC reply 
-   
-          combined_width = 10; 
-          Render_GetTextBoundaries (initial_width - combined_width, chat_fontindex, L"[] : ", &rect); 
-          combined_width += rect.right; 
-          Render_GetTextBoundaries (initial_width - combined_width, chat_fontindex, ccreply->channelname, &rect); 
-          combined_width += rect.right; 
-          Render_GetTextBoundaries (initial_width - combined_width, chat_fontindex, ccreply->nickname, &rect); 
-          combined_width += rect.right; 
-          Render_GetTextBoundaries (initial_width - combined_width, chat_fontindex, ccreply->text, &rect); 
-          combined_height += rect.bottom; // add this string's height  
-       } 
-   
-       // now for each string remaining... 
-       for (; cchistory_index < scene->gui.cchistory_count; cchistory_index++) 
-       { 
-          ccreply = &scene->gui.cchistory[cchistory_index]; // quick access to CC reply 
-          rect.right = 10; 
-          PRINT_CCREPLY (ccreply); // print CC reply on screen 
-          combined_height -= (rect.bottom - rect.top); // draw it from top of zone to bottom 
-       } 
-    } 
-   
-    // are we online ? 
-    if (Player_FindByType (PLAYER_INTERNET) != NULL) 
-    { 
-       ccreply = &scene->gui.entered_ccreply; 
-       if (!scene->gui.is_entering_text) 
-          ccreply->color = RGBACOLOR_SETALPHA (ccreply->color, RGBACOLOR_ALPHA (ccreply->color) / 6); // if there's no text being entered, fade CC reply a lot 
-   
-       rect.right = 10; 
-       PRINT_CCREPLY (ccreply); // print CC reply on screen 
-    } 
-   
-    // print GUI texts 
-    DRAW_TEXT_IF_NEEDED (scene->gui.turn_text); // player turn's text 
-    DRAW_TEXT_IF_NEEDED (scene->gui.central_text); // central notification zone text 
-   
-    // if needed, print the spinning wheel 
-    if (scene->gui.want_spinwheel) 
-       Render_DrawSprite (&sprites[spinner_spriteindex[(int) (10.0f * current_time) % 12]], 47.0f, 46.0f, 6.0f, 8.0f, 255); 
-   
-    // are we in demo mode ? if so, display the program name as a watermark 
- #ifdef DEMO 
-    Render_wprintf (initial_width / 2, initial_height * 2 / 3, -1, ALIGN_CENTER, ALIGN_CENTER, ALIGN_CENTER, chat_fontindex, 
-                    D3DCOLOR_RGBA (255, 255, 255, 191), 
-                    NULL, PROGRAM_NAME L" - " PROGRAM_URL L"\n- %d:%02d -", (int) (DEMO_TIMEOUT - current_time) / 60, (int) (DEMO_TIMEOUT - current_time) % 60); 
- #endif // DEMO 
-   
-    // end 3D rendering on the back buffer 
-    ////////////////////////////////////// 
-   
-    d3ddev->EndScene (); // ends the 3D scene 
-    d3ddev->Present (NULL, NULL, NULL, NULL); // displays the created frame on the screen 
-   
-    // update the frame rate 
-    if (framerate_time < current_time) 
-    { 
-       framerate_value = framerate_count; 
-       framerate_count = 0; 
-       framerate_time = current_time + 1.0f; 
-    } 
-    framerate_count++; // one frame more elapsed 
-   
-    return; // finished 
- } 
-   
-   
- int Render_LoadMesh (const wchar_t *fmt, ...) 
- { 
-    // this function appends a new mesh in the global meshes buffer and returns its index 
-   
-    static wchar_t meshfile_pathname[MAX_PATH]; 
-    unsigned long hash; 
-    mesh_t *mesh; 
-    int mesh_index; 
-    va_list argptr; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    wvsprintf (meshfile_pathname, fmt, argptr); 
-    va_end (argptr); 
-   
-    // resolve wildcards and get content hash 
-    ResolveWildcard (meshfile_pathname, L".obj"); 
-    hash = HashFile (meshfile_pathname); 
-     
-    // now cycle through all our loaded meshes and see if it's already loaded 
-    for (mesh_index = 0; mesh_index < mesh_count; mesh_index++) 
-       if (meshes[mesh_index].hash == hash) 
-          return (mesh_index); // if we can find it, return its index so as not to load it twice 
-   
-    // reallocate space to hold one mesh more 
-    meshes = (mesh_t *) SAFE_realloc (meshes, mesh_count, mesh_count + 1, sizeof (mesh_t), false); 
-    mesh = &meshes[mesh_count]; // quick access to the mesh we'll be working on 
-   
-    // load the mesh 
-    if (!Render_LoadMesh_Obj (mesh, meshfile_pathname)) 
-    { 
-       MessageBox (NULL, LOCALIZE (L"Error_UnableToAddMeshD3DXLoadMeshFromXFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-       return (-1); // bomb out on error 
-    } 
-   
-    mesh->hash = hash; // save the hash 
-    mesh_count++; // we know now one mesh more 
-    return (mesh_count - 1); // return its index 
- } 
-   
-   
- int Render_LoadTexture (const wchar_t *fmt, ...) 
- { 
-    // this function appends a new texture in the global textures buffer and returns its index 
-   
-    D3DSURFACE_DESC texture_description; 
-    wchar_t texturefile_pathname[MAX_PATH]; 
-    static wchar_t *filename; 
-    unsigned long hash; 
-    int texture_index; 
-    va_list argptr; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    wvsprintf (texturefile_pathname, fmt, argptr); 
-    va_end (argptr); 
-   
-    // resolve wildcards and get content hash 
-    ResolveWildcard (texturefile_pathname, L".dds|.jpg|.jpeg|.png|.tga|.bmp"); 
-    hash = HashFile (texturefile_pathname); 
-   
-    // now cycle through all our loaded textures and see if it's already loaded 
-    for (texture_index = 0; texture_index < texture_count; texture_index++) 
-       if (textures[texture_index].hash == hash) 
-          return (texture_index); // if we can find it, return its index so as not to load it twice 
-   
-    // reallocate space to hold one texture more 
-    textures = (texture_t *) SAFE_realloc (textures, texture_count, texture_count + 1, sizeof (texture_t), false); 
-   
-    // ask Direct3D to prepare texture data 
-    if (FAILED (D3DXCreateTextureFromFile (d3ddev, texturefile_pathname, &textures[texture_count].texture))) 
-    { 
-       MessageBox (NULL, LOCALIZE (L"Error_UnableToAddTextureD3DXCreateTextureFromFileFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-       return (-1); // bomb out on error 
-    } 
-   
-    // get info on the newly loaded texture such as size etc. 
-    textures[texture_count].texture->GetLevelDesc (0, &texture_description); 
-    textures[texture_count].width = texture_description.Width; // save texture width (as loaded) 
-    textures[texture_count].height = texture_description.Height; // save texture height (as loaded) 
-    textures[texture_count].hash = hash; // save its hash 
-    texture_count++; // we know now one texture more 
-    return (texture_count - 1); // return its index 
- } 
-   
-   
- int Render_LoadFont (const wchar_t *font_name, int font_size, bool is_bold, bool is_italic) 
- { 
-    // this function appends a new font in the global fonts buffer and returns its index 
-   
-    unsigned long pathname_hash; 
-    int font_index; 
-   
-    // first, get the hash of the requested pathname (include font size and weight parameters) 
-    pathname_hash = HashString (font_name); 
-    pathname_hash += 3 * (unsigned long) font_size + 2 * (unsigned long) is_bold + (unsigned long) is_italic; 
-   
-    // now cycle through all our loaded fonts and see if it's already loaded 
-    for (font_index = 0; font_index < font_count; font_index++) 
-       if (fonts[font_index].pathname_hash == pathname_hash) 
-          return (font_index); // if we can find it, return its index so as not to load it twice 
-   
-    // reallocate space to hold one font more 
-    fonts = (font_t *) SAFE_realloc (fonts, font_count, font_count + 1, sizeof (font_t), false); 
-   
-    // create a Direct3D font object and record font data 
-    if (FAILED (D3DXCreateFont (d3ddev, font_size, // font height 
-                                0, // font width 
-                                (is_bold ? FW_BOLD : FW_NORMAL), // font weight (bold, etc) 
-                                0, // miplevels 
-                                is_italic, // is italic 
-                                DEFAULT_CHARSET, // charset 
-                                OUT_DEFAULT_PRECIS, // precision 
-                                CLEARTYPE_QUALITY, // font quality (antialiased or not) 
-                                DEFAULT_PITCH | FF_DONTCARE, // font family 
-                                font_name, // font name 
-                                &fonts[font_count].font))) // and a pointer that will receive the font 
-    { 
-       MessageBox (NULL, LOCALIZE (L"Error_UnableToAddFontD3DXCreateFontFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-       return (-1); // bomb out on error 
-    } 
-   
-    fonts[font_count].pathname_hash = pathname_hash; // save its hash 
-    font_count++; // we know now one font more 
-    return (font_count - 1); // return its index 
- } 
-   
-   
- int Render_LoadSprite (const wchar_t *fmt, ...) 
- { 
-    // this function appends a new sprite in the global sprites buffer and returns its index 
-   
-    wchar_t spritefile_pathname[MAX_PATH]; 
-    unsigned long hash; 
-    int sprite_index; 
-    va_list argptr; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    wvsprintf (spritefile_pathname, fmt, argptr); 
-    va_end (argptr); 
-   
-    // resolve wildcards and get content hash 
-    ResolveWildcard (spritefile_pathname, L".dds|.jpg|.jpeg|.png|.tga|.bmp"); 
-    hash = HashFile (spritefile_pathname); 
-   
-    // now cycle through all our loaded sprites and see if it's already loaded 
-    for (sprite_index = 0; sprite_index < sprite_count; sprite_index++) 
-       if (sprites[sprite_index].hash == hash) 
-          return (sprite_index); // if we can find it, return its index so as not to load it twice 
-   
-    // reallocate space to hold one sprite more 
-    sprites = (sprite_t *) SAFE_realloc (sprites, sprite_count, sprite_count + 1, sizeof (sprite_t), false); 
-   
-    // ask Direct3D to prepare texture data 
-    if (FAILED (D3DXCreateSprite (d3ddev, &sprites[sprite_count].sprite))) 
-    { 
-       MessageBox (NULL, LOCALIZE (L"Error_UnableToAddSpriteD3DXCreateSpriteFailed"), LOCALIZE (L"FatalError"), MB_ICONERROR | MB_OK); 
-       return (-1); // bomb out on error 
-    } 
-    sprites[sprite_count].texture_index = Render_LoadTexture (spritefile_pathname); // register and save sprite texture 
-    sprites[sprite_count].hash = hash; // save its hash 
-   
-    sprite_count++; // we know now one sprite more 
-    return (sprite_count - 1); // return its index 
- } 
-   
-   
- int Render_MaterialIndexOf (const wchar_t *material_name) 
- { 
-    // this function returns the index of the material in the global materials array which has the specified name 
-   
-    int material_index; 
-   
-    // cycle through all materials and look whether one with the specified name exists 
-    for (material_index = 0; material_index < material_count; material_index++) 
-       if (_wcsicmp (materials[material_index].name, material_name) == 0) 
-          return (material_index); // if we find one, return its index 
-   
-    return (material_count - 1); // else return the index of the last material in list, which is the default material 
- } 
-   
-   
- void Render_MouseToFloor (short mouse_x, short mouse_y, float *floor_x, float *floor_y) 
- { 
-    // this function converts a mouse coordinates into floor coordinates by doing vector 
-    // projection on the floor plane from the eyepoint of the camera 
-   
-    static D3DXPLANE floor_plane; 
-    static bool is_planefound = false; 
-   
-    D3DXMATRIX projection_matrix; 
-    D3DXMATRIX view_matrix; 
-    D3DXMATRIX invertedview_matrix; 
-    float mouse_pitch; 
-    float mouse_yaw; 
-    vector_t v_lookat; 
-    vector_t v_intersection; 
-   
-    // find the floor plane (only do it once) 
-    if (!is_planefound) 
-    { 
-       D3DXPlaneFromPointNormal (&floor_plane, (D3DXVECTOR3 *) &scene_center, (D3DXVECTOR3 *) &upwards_direction); 
-       is_planefound = true; // once and for all, as this plane will never change 
-    } 
-   
-    // get the current projection and view matrices, and invert the view matrix 
-    d3ddev->GetTransform (D3DTS_PROJECTION, &projection_matrix); 
-    d3ddev->GetTransform (D3DTS_VIEW, &view_matrix); 
-    D3DXMatrixInverse (&invertedview_matrix, NULL, &view_matrix); 
-   
-    // convert the mouse coordinates to relative pitch and yaw 
-    mouse_pitch =  (((mouse_x * 2.0f) / current_width) - 1) / projection_matrix._11; 
-    mouse_yaw = -(((mouse_y * 2.0f) / current_height) - 1) / projection_matrix._22; 
-   
-    // now build a matrix that will describe the mouse direction vector, add it to the camera position, and make it 200 times longer 
-    v_lookat.x = camera_position.x + (mouse_pitch * invertedview_matrix._11 + mouse_yaw * invertedview_matrix._21 + invertedview_matrix._31) * 200.0f; 
-    v_lookat.y = camera_position.y + (mouse_pitch * invertedview_matrix._12 + mouse_yaw * invertedview_matrix._22 + invertedview_matrix._32) * 200.0f; 
-    v_lookat.z = camera_position.z + (mouse_pitch * invertedview_matrix._13 + mouse_yaw * invertedview_matrix._23 + invertedview_matrix._33) * 200.0f; 
-   
-    // and the intersection point with our ray 
-    D3DXPlaneIntersectLine ((D3DXVECTOR3 *) &v_intersection, &floor_plane, (D3DXVECTOR3 *) &camera_position, (D3DXVECTOR3 *) &v_lookat); 
-   
-    // now fill the return values 
-    *floor_x = v_intersection.x; 
-    *floor_y = v_intersection.y; 
-   
-    return; // finished 
- } 
-   
-   
- bool Render_IsMouseInBox (short mouse_x, short mouse_y, float x_percent, float y_percent, float width_percent, float height_percent) 
- { 
-    // helper function that returns whether the mouse coordinates are inside a given square 
-   
-    float mousex_percent; 
-    float mousey_percent; 
-   
-    // compute mouse coordinates in percents 
-    mousex_percent = (float) (mouse_x * 100) / current_width; 
-    mousey_percent = (float) (mouse_y * 100) / current_height; 
-   
-    return ((mousex_percent >= x_percent) && (mousex_percent <= x_percent + width_percent) 
-            && (mousey_percent >= y_percent) && (mousey_percent <= y_percent + height_percent)); 
- } 
-   
-   
- static bool Render_LoadMesh_Obj (mesh_t *mesh, const wchar_t *objfile_pathname) 
- { 
-    // this function loads a mesh from a Wavefront Object file (.obj) 
-   
-    #define OBJ_INCREASE_OR_RESIZE(count,maxcount,increment,arrayptr,type,erase) { \ 
-       (count)++; \ 
-       if ((count) == (maxcount)) \ 
-       { \ 
-          (arrayptr) = (type *) SAFE_realloc ((arrayptr), (maxcount), (maxcount) + (increment), sizeof (type), erase); \ 
-          (maxcount) += (increment); \ 
-       } \ 
-    } 
-    #define OBJ_CONVERT_INDEX(element,current_element_count) if ((element) < 0) (element) = (current_element_count) + (element); else (element)--; 
-    #define OBJ_GET_EXISTING_INDEX_OR_APPEND_VERTEX(uniquevertex) \ 
-    { \ 
-       hash = &hashtable[*((unsigned long *) &obj.vs[(uniquevertex).iv].x) & 0xFF]; \ 
-       for (vertex_index = 0; vertex_index < hash->count; vertex_index++) \ 
-          if ((memcmp (&vertices[hash->indices[vertex_index]].position, &obj.vs[(uniquevertex).iv], sizeof (vector_t)) == 0) \ 
-              && (memcmp (&vertices[hash->indices[vertex_index]].normal, &obj.ns[(uniquevertex).in], sizeof (vector_t)) == 0) \ 
-              && (memcmp (&vertices[hash->indices[vertex_index]].texcoord, &obj.tcs[(uniquevertex).itc], sizeof (texcoord_t)) == 0)) \ 
-             break; \ 
-       if (vertex_index == hash->count) \ 
-       { \ 
-          vertex_index = mesh->vertice_count; \ 
-          current_vertex = &vertices[vertex_index]; \ 
-          memset (current_vertex, 0, sizeof (vertex_t)); \ 
-          memcpy (¤t_vertex->position, &obj.vs[(uniquevertex).iv], sizeof (vector_t)); \ 
-          if ((uniquevertex).in > -1) \ 
-             memcpy (¤t_vertex->normal, &obj.ns[(uniquevertex).in], sizeof (vector_t)); \ 
-          if ((uniquevertex).itc > -1) \ 
-             memcpy (¤t_vertex->texcoord, &obj.tcs[(uniquevertex).itc], sizeof (texcoord_t)); \ 
-          hash = &hashtable[*((unsigned long *) ¤t_vertex->normal.x) & 0xFF]; \ 
-          hash->indices = (long *) SAFE_realloc (hash->indices, hash->count, hash->count + 1, sizeof (long), false); \ 
-          hash->indices[hash->count] = vertex_index; \ 
-          hash->count++; \ 
-          mesh->vertice_count++; \ 
-       } \ 
-       else \ 
-          vertex_index = hash->indices[vertex_index]; \ 
-    } 
-   
-    typedef struct obj_uniquevertex_s { long iv, in, itc; } obj_uniquevertex_t; 
-    typedef struct obj_face_s { obj_uniquevertex_t v1, v2, v3; } obj_face_t; 
-    typedef struct obj_hashbucket_s { int count; long *indices; /* mallocated */ } obj_hashbucket_t; 
-    typedef struct objfile_s 
-    { 
-       vector_t *vs; long v_count; long v_maxcount; // array mallocated to v_maxcount 
-       vector_t *ns; long n_count; long n_maxcount; // array mallocated to n_maxcount 
-       texcoord_t *tcs; long tc_count; long tc_maxcount; // array mallocated to tc_maxcount 
-       obj_face_t *fs; long f_count; long f_maxcount; // array mallocated to f_maxcount 
-    } objfile_t; 
-   
-    static obj_hashbucket_t hashtable[256]; 
-    objfile_t obj; 
-    obj_hashbucket_t *hash; 
-    obj_face_t *f; 
-    vertex_t *vertices; // mallocated 
-    unsigned long *indices; // mallocated 
-    vertex_t *current_vertex; 
-    struct _stat fileinfo; 
-    char *filedata; // mallocated 
-    char *fileptr; 
-    int vertex_index; 
-    int array_index; 
-    void *ptr_to; 
-    FILE *fp; 
-   
-    // open the mesh file and read it as a whole 
-    _wstat (objfile_pathname, &fileinfo); 
-    _wfopen_s (&fp, objfile_pathname, L"rb"); 
-    if (fp == NULL) 
-       return (false); // bomb out on error 
-    filedata = (char *) SAFE_malloc (fileinfo.st_size, sizeof (char), false); // mallocate space for data 
-    fread (filedata, fileinfo.st_size, 1, fp); // read file as a whole 
-    fclose (fp); // file is read, close it 
-   
-    // allocate space for an arbitrary amount of vertices, texture coordinates, normals and faces 
-    memset (&obj, 0, sizeof (obj)); 
-    obj.v_maxcount = 10000; obj.vs = (vector_t *) SAFE_malloc (obj.v_maxcount, sizeof (vector_t), false); 
-    obj.n_maxcount = 10000; obj.ns = (vector_t *) SAFE_malloc (obj.n_maxcount, sizeof (vector_t), false); 
-    obj.tc_maxcount = 10000; obj.tcs = (texcoord_t *) SAFE_malloc (obj.tc_maxcount, sizeof (texcoord_t), false); 
-    obj.f_maxcount = 5000; obj.fs = (obj_face_t *) SAFE_malloc (obj.f_maxcount, sizeof (obj_face_t), true); // zero out the faces array (IMPORTANT !) 
-   
-    // read file line per line... 
-    fileptr = filedata - 1; // start parsing line after line 
-    while (fileptr != NULL) 
-    { 
-       fileptr++; // skip the line feed (or reach the first character, if it's the first pass) 
-   
-       // is it a vertex-related line ? 
-       if (fileptr[0] == L'v') 
-       { 
-          // is it a vertex, a normal or a texture coordinate ? 
-          if ((fileptr[1] == L' ') && (sscanf_s (&fileptr[2], "%f %f %f", &obj.vs[obj.v_count].x, &obj.vs[obj.v_count].y, &obj.vs[obj.v_count].z) == 3)) 
-             OBJ_INCREASE_OR_RESIZE (obj.v_count, obj.v_maxcount, 10000, obj.vs, vector_t, false) // one vertex more has been read 
-          else if ((fileptr[1] == L'n') && (sscanf_s (&fileptr[3], "%f %f %f", &obj.ns[obj.n_count].x, &obj.ns[obj.n_count].y, &obj.ns[obj.n_count].z) == 3)) 
-             OBJ_INCREASE_OR_RESIZE (obj.n_count, obj.n_maxcount, 10000, obj.ns, vector_t, false) // one normal more has been read 
-          else if ((fileptr[1] == L't') && (sscanf_s (&fileptr[3], "%f %f", &obj.tcs[obj.tc_count].u, &obj.tcs[obj.tc_count].v) == 2)) 
-             OBJ_INCREASE_OR_RESIZE (obj.tc_count, obj.tc_maxcount, 10000, obj.tcs, texcoord_t, false) // one texture coordinate more has been read 
-       } 
-   
-       // else is it a face-related line ? 
-       else if (fileptr[0] == L'f') 
-       { 
-          // get a quick pointer to current face (note: it's been already blanked out by malloc()) 
-          f = &obj.fs[obj.f_count]; 
-   
-          // is it a face with normals, a face without normals or a face without normals and texture coordinates ? 
-          if ((sscanf_s (&fileptr[2], "%d/%d/%d %d/%d/%d %d/%d/%d", &f->v1.iv, &f->v1.itc, &f->v1.in, &f->v2.iv, &f->v2.itc, &f->v2.in, &f->v3.iv, &f->v3.itc, &f->v3.in) == 9) 
-              || (sscanf_s (&fileptr[2], "%d/%d %d/%d %d/%d", &f->v3.iv, &f->v3.itc, &f->v2.iv, &f->v2.itc, &f->v3.iv, &f->v3.itc) == 6) 
-              || (sscanf_s (&fileptr[2], "%d %d %d", &f->v3.iv, &f->v2.iv, &f->v3.iv) == 6)) 
-          { 
-             OBJ_CONVERT_INDEX (f->v1.iv, obj.v_count); 
-             OBJ_CONVERT_INDEX (f->v1.in, obj.n_count); // if no normal could be read, its index will be converted from 0 to -1 
-             OBJ_CONVERT_INDEX (f->v1.itc, obj.tc_count); // if no texcoord could be read, its index will be converted from 0 to -1 
-             OBJ_CONVERT_INDEX (f->v2.iv, obj.v_count); 
-             OBJ_CONVERT_INDEX (f->v2.in, obj.n_count); // if no normal could be read, its index will be converted from 0 to -1 
-             OBJ_CONVERT_INDEX (f->v2.itc, obj.tc_count); // if no texcoord could be read, its index will be converted from 0 to -1 
-             OBJ_CONVERT_INDEX (f->v3.iv, obj.v_count); 
-             OBJ_CONVERT_INDEX (f->v3.in, obj.n_count); // if no normal could be read, its index will be converted from 0 to -1 
-             OBJ_CONVERT_INDEX (f->v3.itc, obj.tc_count); // if no texcoord could be read, its index will be converted from 0 to -1 
-             OBJ_INCREASE_OR_RESIZE (obj.f_count, obj.f_maxcount, 5000, obj.fs, obj_face_t, true) // one face more has been read 
-          } 
-       } 
-   
-       fileptr = strchr (fileptr, '\n'); // proceed to next line 
-    } 
-   
-    // now build our final vertex and index list 
-    vertices = (vertex_t *) SAFE_malloc (3 * obj.f_count, sizeof (vertex_t), false); // mallocate for the max number of vertices we can have 
-    indices = (unsigned long *) SAFE_malloc (3 * obj.f_count, sizeof (unsigned long), false); // mallocate for the right amount of indices 
-   
-    // t3h mighty l00p ^^ (builds vertex and index buffers) 
-    memset (hashtable, 0, sizeof (hashtable)); // wipe out the hashtable 
-    mesh->vertice_count = 0; // start with an unoptimized list 
-    for (array_index = 0; array_index < obj.f_count; array_index++) 
-    { 
-       f = &obj.fs[array_index]; // quick access to current face 
-       OBJ_GET_EXISTING_INDEX_OR_APPEND_VERTEX (f->v1); 
-       indices[3 * array_index + 0] = vertex_index; 
-       OBJ_GET_EXISTING_INDEX_OR_APPEND_VERTEX (f->v2); 
-       indices[3 * array_index + 1] = vertex_index; 
-       OBJ_GET_EXISTING_INDEX_OR_APPEND_VERTEX (f->v3); 
-       indices[3 * array_index + 2] = vertex_index; 
-    } 
-   
-    // now create a correctly-sized DirectX vertex buffer and populate it 
-    mesh->vertex_format = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; 
-    mesh->vertice_size = sizeof (vertex_t); 
-    d3ddev->CreateVertexBuffer (mesh->vertice_count * mesh->vertice_size, // length 
-                                D3DUSAGE_DYNAMIC, // usage 
-                                mesh->vertex_format, // vertex format 
-                                D3DPOOL_DEFAULT, // pool type 
-                                &mesh->d3dvertices, // pointer to the vertex buffer pointer 
-                                NULL); // shared handle 
-    mesh->d3dvertices->Lock (0, mesh->vertice_count * mesh->vertice_size, &ptr_to, D3DLOCK_DISCARD); 
-    memcpy (ptr_to, vertices, mesh->vertice_count * mesh->vertice_size); 
-    mesh->d3dvertices->Unlock (); 
-   
-    // create a correctly-sized DirectX index buffer and populate it 
-    mesh->is_indexed = true; // remember that we're building an index buffer 
-    mesh->indice_count = obj.f_count * 3; 
-    mesh->indice_size = (mesh->indice_count <= (int) USHRT_MAX ? 2 : 4); 
-    d3ddev->CreateIndexBuffer (mesh->indice_count * mesh->indice_size, // length 
-                               D3DUSAGE_DYNAMIC, // usage 
-                               (mesh->indice_size == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32), // format (here, 16 or 32-bit) 
-                               D3DPOOL_DEFAULT, // pool type 
-                               &mesh->d3dindices, // pointer to the index buffer pointer 
-                               NULL); // shared handle 
-    mesh->d3dindices->Lock (0, mesh->indice_count * mesh->indice_size, &ptr_to, D3DLOCK_DISCARD); 
-    if (mesh->indice_size == 2) 
-       for (array_index = 0; array_index < mesh->indice_count; array_index++) 
-          ((unsigned short *) ptr_to)[array_index] = (unsigned short) indices[array_index]; 
-    else 
-       memcpy (ptr_to, indices, mesh->indice_count * mesh->indice_size); 
-    mesh->d3dindices->Unlock (); 
-   
-    // finished, free the temporary objects 
-    for (array_index = 0; array_index < sizeof (hashtable) / sizeof (obj_hashbucket_t); array_index++) 
-       SAFE_free ((void **) &hashtable[array_index].indices); 
-    SAFE_free ((void **) &indices); 
-    SAFE_free ((void **) &vertices); 
-    SAFE_free ((void **) &obj.vs); 
-    SAFE_free ((void **) &obj.ns); 
-    SAFE_free ((void **) &obj.tcs); 
-    SAFE_free ((void **) &obj.fs); 
-    SAFE_free ((void **) &filedata); 
-   
-    return (true); // Wavefront Object successfully loaded, return TRUE 
-   
-    #undef OBJ_GET_EXISTING_INDEX_OR_APPEND_VERTEX 
-    #undef OBJ_CONVERT_INDEX 
-    #undef OBJ_INCREASE_OR_RESIZE 
- } 
-   
-   
- static void Render_DrawSceneObjectReflection (sceneobject_t *sceneobject) 
- { 
-    // fast helper to draw a mesh at a specified location with certain pitch and yaw angles 
-   
-    D3DXMATRIX rotation_matrix; 
-    D3DXMATRIX translation_matrix; 
-    D3DXMATRIX reflect_matrix; 
-    D3DXMATRIX scaling_matrix; 
-    material_t *material; 
-    D3DMATERIAL9 d3dmaterial; 
-    D3DXPLANE plane; 
-    mesh_t *mesh; 
-    mesh_t *tile_mesh; 
-    float alpha; 
-   
-    // draw the reflection below this mesh 
-   
-    // quick access to meshes 
-    mesh = &meshes[sceneobject->mesh_index]; 
-    tile_mesh = &meshes[theme->tile_meshindex]; 
-   
-    // set the world transform at location 
-    D3DXPlaneFromPointNormal (&plane, (D3DXVECTOR3 *) &scene_center, (D3DXVECTOR3 *) &upwards_direction); 
-    D3DXMatrixReflect (&reflect_matrix, &plane); 
-    D3DXMatrixRotationYawPitchRoll (&rotation_matrix, -sceneobject->pitch * TO_RADIANS, 0.0f, -sceneobject->yaw * TO_RADIANS); 
-    D3DXMatrixTranslation (&translation_matrix, sceneobject->x, sceneobject->y, -sceneobject->z); 
-    D3DXMatrixScaling (&scaling_matrix, sceneobject->scale, sceneobject->scale, 1.0f); 
-   
-    // tell Direct3D about our matrix 
-    d3ddev->SetTransform (D3DTS_WORLD, &(reflect_matrix * scaling_matrix * rotation_matrix * translation_matrix)); 
-   
-    d3ddev->SetRenderState (D3DRS_STENCILENABLE, true); // enable the stencil buffer 
-    d3ddev->SetRenderState (D3DRS_STENCILFUNC, D3DCMP_LESS); // instruct how to fill the stencil buffer 
-    d3ddev->SetRenderState (D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); // instruct how to fill the stencil buffer 
-   
-    // set the texture for this mesh 
-    if (sceneobject->texture_index != -1) 
-       d3ddev->SetTexture (0, textures[sceneobject->texture_index].texture); 
-    else 
-       d3ddev->SetTexture (0, NULL); 
-   
-    // adjust the light reflection properties by setting the material 
-    if (sceneobject->material_index != -1) 
-       material = &materials[sceneobject->material_index]; // use the specified scene object material 
-    else 
-       material = &materials[material_count - 1]; // scene object material unspecified, use default material 
-    alpha = theme->reflection_alpha / 256.0f; 
-    d3dmaterial.Ambient = D3DXCOLOR (material->ambient, material->ambient, material->ambient, material->transparency * alpha); // Alpha value not used according to SDK 
-    d3dmaterial.Diffuse = D3DXCOLOR (material->diffuse, material->diffuse, material->diffuse, material->transparency * alpha); 
-    d3dmaterial.Emissive = D3DXCOLOR (material->emissive, material->emissive, material->emissive, material->transparency * alpha); // Alpha value not used according to SDK 
-    d3dmaterial.Specular = D3DXCOLOR (material->specular, material->specular, material->specular, material->transparency * alpha); // Alpha value not used according to SDK 
-    d3dmaterial.Power = material->shininess; 
-    d3ddev->SetMaterial (&d3dmaterial); 
-   
-    // draw the mesh subset 
-    d3ddev->SetStreamSource (0, mesh->d3dvertices, 0, sizeof (vertex_t)); 
-    d3ddev->SetFVF (mesh->vertex_format); 
-    d3ddev->SetRenderState (D3DRS_CULLMODE, D3DCULL_CW); // draw the faces backwards 
-    if (mesh->is_indexed) 
-    { 
-       d3ddev->SetIndices (mesh->d3dindices); 
-       d3ddev->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0, mesh->vertice_count, 0, mesh->indice_count / 3); 
-    } 
-    else 
-       d3ddev->DrawPrimitive (D3DPT_TRIANGLELIST, 0, mesh->vertice_count / 3); 
-   
-    d3ddev->SetRenderState (D3DRS_STENCILENABLE, false); // and disable the stencil buffer 
-   
-    // now draw the simple shadow below this mesh 
-   
-    // grab the tools we need in hand 
-    d3ddev->SetRenderState (D3DRS_ZENABLE, false); // disable the Z buffer 
-    d3ddev->SetRenderState (D3DRS_AMBIENT, D3DCOLOR_XRGB (255, 255, 255)); // raise ambient light 
-   
-    // position the simple shadow sprite 
-    D3DXMatrixScaling (&scaling_matrix, max (sceneobject->simpleshadow_size, sceneobject->z / 5.0f), max (sceneobject->simpleshadow_size, sceneobject->z / 5.0f), 0.0f); 
-    D3DXMatrixTranslation (&translation_matrix, sceneobject->x, sceneobject->y, 0.0f); 
-    d3ddev->SetTransform (D3DTS_WORLD, &(scaling_matrix * translation_matrix)); 
-   
-    // adjust the light reflection properties by setting the material 
-    material = &materials[material_count - 1]; // use the default material 
-    d3dmaterial.Ambient = D3DXCOLOR (material->ambient, material->ambient, material->ambient, material->transparency); 
-    d3dmaterial.Diffuse = D3DXCOLOR (material->diffuse, material->diffuse, material->diffuse, material->transparency); 
-    d3dmaterial.Emissive = D3DXCOLOR (material->emissive, material->emissive, material->emissive, material->transparency); 
-    d3dmaterial.Specular = D3DXCOLOR (material->specular, material->specular, material->specular, material->transparency); 
-    d3dmaterial.Power = material->shininess; 
-    d3ddev->SetMaterial (&d3dmaterial); 
-   
-    d3ddev->SetTexture (0, textures[theme->shadow_textureindex].texture); // select the texture we want 
-   
-    // and then draw it 
-    d3ddev->SetStreamSource (0, tile_mesh->d3dvertices, 0, sizeof (vertex_t)); // set stream source 
-    d3ddev->SetFVF (tile_mesh->vertex_format); // select which vertex format we are using 
-    d3ddev->SetRenderState (D3DRS_CULLMODE, D3DCULL_CW); // draw the faces backwards 
-    if (tile_mesh->is_indexed) 
-    { 
-       d3ddev->SetIndices (tile_mesh->d3dindices); 
-       d3ddev->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0, tile_mesh->vertice_count, 0, tile_mesh->indice_count / 3); 
-    } 
-    else 
-       d3ddev->DrawPrimitive (D3DPT_TRIANGLELIST, 0, tile_mesh->vertice_count / 3); 
-   
-    // finished, reset ambient light to its previous value and enable the Z buffer back 
-    d3ddev->SetRenderState (D3DRS_AMBIENT, ambient_light); 
-    d3ddev->SetRenderState (D3DRS_ZENABLE, true); 
-   
-    return; // finished 
- } 
-   
-   
- static void Render_DrawSceneObject (sceneobject_t *sceneobject) 
- { 
-    // fast helper to draw a mesh at a specified location with certain pitch and yaw angles 
-   
-    D3DXMATRIX rotation_matrix; 
-    D3DXMATRIX translation_matrix; 
-    D3DXMATRIX scaling_matrix; 
-    material_t *material; 
-    D3DMATERIAL9 d3dmaterial; 
-    mesh_t *mesh; 
-   
-    // is this object a tile (i.e, it has no mesh) ? 
-    if (sceneobject->mesh_index == -1) 
-    { 
-       Render_DrawSceneTile (sceneobject); // then draw it as a tile instead 
-       return; // and return 
-    } 
-   
-    // quick access to mesh 
-    mesh = &meshes[sceneobject->mesh_index]; 
-   
-    // set the world transform at location 
-    D3DXMatrixRotationYawPitchRoll (&rotation_matrix, sceneobject->pitch * TO_RADIANS, 0.0f, sceneobject->yaw * TO_RADIANS); 
-    D3DXMatrixTranslation (&translation_matrix, sceneobject->x, sceneobject->y, sceneobject->z); 
-    D3DXMatrixScaling (&scaling_matrix, sceneobject->scale, sceneobject->scale, 1.0f); 
-   
-    // tell Direct3D about our matrix 
-    d3ddev->SetTransform (D3DTS_WORLD, &(scaling_matrix * rotation_matrix * translation_matrix)); 
-   
-    // set the texture for this mesh 
-    if (sceneobject->texture_index != -1) 
-       d3ddev->SetTexture (0, textures[sceneobject->texture_index].texture); 
-    else 
-       d3ddev->SetTexture (0, NULL); 
-   
-    // adjust the light reflection properties by setting the material 
-    if (sceneobject->material_index != -1) 
-       material = &materials[sceneobject->material_index]; 
-    else 
-       material = &materials[material_count - 1]; 
-    d3dmaterial.Ambient = D3DXCOLOR (material->ambient, material->ambient, material->ambient, material->transparency); 
-    d3dmaterial.Diffuse = D3DXCOLOR (material->diffuse, material->diffuse, material->diffuse, material->transparency); 
-    d3dmaterial.Emissive = D3DXCOLOR (material->emissive, material->emissive, material->emissive, material->transparency); 
-    d3dmaterial.Specular = D3DXCOLOR (material->specular, material->specular, material->specular, material->transparency); 
-    d3dmaterial.Power = material->shininess; 
-    d3ddev->SetMaterial (&d3dmaterial); 
-   
-    // draw the mesh subset 
-    d3ddev->SetStreamSource (0, mesh->d3dvertices, 0, sizeof (vertex_t)); 
-    d3ddev->SetFVF (mesh->vertex_format); 
-   
-    // is there transparency on this mesh ? 
-    if (material->transparency < 1) 
-    { 
-       d3ddev->SetRenderState (D3DRS_CULLMODE, D3DCULL_CW); // draw the back faces 
-       if (mesh->is_indexed) 
-       { 
-          d3ddev->SetIndices (mesh->d3dindices); 
-          d3ddev->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0, mesh->vertice_count, 0, mesh->indice_count / 3); 
-       } 
-       else 
-          d3ddev->DrawPrimitive (D3DPT_TRIANGLELIST, 0, mesh->vertice_count / 3); 
-    } 
-   
-    // now draw the front faces 
-    d3ddev->SetRenderState (D3DRS_CULLMODE, D3DCULL_CCW); // draw the front faces 
-    if (mesh->is_indexed) 
-    { 
-       d3ddev->SetIndices (mesh->d3dindices); 
-       d3ddev->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0, mesh->vertice_count, 0, mesh->indice_count / 3); 
-    } 
-    else 
-       d3ddev->DrawPrimitive (D3DPT_TRIANGLELIST, 0, mesh->vertice_count / 3); 
-   
-    return; // finished 
- } 
-   
-   
- static void Render_DrawSceneTile (sceneobject_t *sceneobject) 
- { 
-    // fast helper to draw a tile (i.e, an object that doesn't have a mesh) at a specified location 
-   
-    D3DXMATRIX rotation_matrix; 
-    D3DXMATRIX translation_matrix; 
-    D3DXMATRIX scaling_matrix; 
-    material_t *material; 
-    D3DMATERIAL9 d3dmaterial; 
-    mesh_t *tile_mesh; 
-   
-    tile_mesh = &meshes[theme->tile_meshindex]; // quick access to tile mesh 
-   
-    // grab the tools we need in hand 
-    d3ddev->SetRenderState (D3DRS_AMBIENT, D3DCOLOR_RGBA (0xFF, 0xFF, 0xFF, 0xFF)); // raise light 
-   
-    // set the world transform at location 
-    D3DXMatrixRotationYawPitchRoll (&rotation_matrix, sceneobject->pitch * TO_RADIANS, 0.0f, sceneobject->yaw * TO_RADIANS); 
-    D3DXMatrixTranslation (&translation_matrix, sceneobject->x, sceneobject->y, sceneobject->z); 
-    D3DXMatrixScaling (&scaling_matrix, sceneobject->scale, sceneobject->scale, 1.0f); 
-   
-    // tell Direct3D about our matrix 
-    d3ddev->SetTransform (D3DTS_WORLD, &(scaling_matrix * rotation_matrix * translation_matrix)); 
-   
-    // adjust the light reflection properties by setting the material 
-    material = &materials[material_count - 1]; // use the default material for tiles 
-    d3dmaterial.Ambient = D3DXCOLOR (material->ambient, material->ambient, material->ambient, material->ambient); 
-    d3dmaterial.Diffuse = D3DXCOLOR (material->diffuse, material->diffuse, material->diffuse, material->diffuse); 
-    d3dmaterial.Emissive = D3DXCOLOR (material->emissive, material->emissive, material->emissive, material->emissive); 
-    d3dmaterial.Specular = D3DXCOLOR (material->specular, material->specular, material->specular, material->specular); 
-    d3dmaterial.Power = material->shininess; 
-    d3ddev->SetMaterial (&d3dmaterial); 
-   
-    // select the texture we want 
-    d3ddev->SetTexture (0, textures[sceneobject->texture_index].texture); 
-   
-    // and then draw it 
-    d3ddev->SetStreamSource (0, tile_mesh->d3dvertices, 0, sizeof (vertex_t)); // set stream source 
-    d3ddev->SetFVF (tile_mesh->vertex_format); // select which vertex format we are using 
-    d3ddev->SetRenderState (D3DRS_CULLMODE, D3DCULL_CW); // draw the back faces 
-    if (tile_mesh->is_indexed) 
-    { 
-       d3ddev->SetIndices (tile_mesh->d3dindices); 
-       d3ddev->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0, tile_mesh->vertice_count, 0, tile_mesh->indice_count / 3); 
-    } 
-    else 
-       d3ddev->DrawPrimitive (D3DPT_TRIANGLELIST, 0, tile_mesh->vertice_count / 3); 
-   
-    // finished, reset ambient light to its previous value 
-    d3ddev->SetRenderState (D3DRS_AMBIENT, ambient_light); 
-   
-    return; // finished 
- } 
-   
-   
- static void Render_DrawSprite (sprite_t *sprite, float x_percent, float y_percent, float width_percent, float height_percent, int alpha) 
- { 
-    // fast helper to draw a sprite at a specified location with certain parameters 
-   
-    D3DXMATRIX scaling_matrix; 
-    texture_t *texture; 
-    float scale_x; 
-    float scale_y; 
-   
-    texture = &textures[sprite->texture_index]; // quick access to sprite's texture 
-   
-    scale_x = (width_percent * (float) initial_width) / (float) (100 * texture->width); 
-    scale_y = (height_percent * (float) initial_height) / (float) (100 * texture->height); 
-   
-    // start rendering the sprite (an optimized version would draw all sprites in a row...) 
-    sprite->sprite->Begin (D3DXSPRITE_ALPHABLEND); 
-   
-    // scale and position the sprite 
-    D3DXMatrixTransformation2D (&scaling_matrix, // output matrix 
-                                NULL, // scaling center 
-                                0.0f, // scaling rotation 
-                                &D3DXVECTOR2 (scale_x, scale_y), // scaling ratio 
-                                &D3DXVECTOR2 (0, 0), // rotation center 
-                                0.0f, // rotation 
-                                &D3DXVECTOR2 (x_percent * (float) initial_width / 100.0f, y_percent * (float) initial_height / 100.0f)); // translation 
-    sprite->sprite->SetTransform (&scaling_matrix); // tell the sprite about the scaling and position transform 
-   
-    // now draw the sprite with the specified alpha and finish rendering 
-    sprite->sprite->Draw (texture->texture, NULL, NULL, NULL, D3DCOLOR_ARGB (alpha, 255, 255, 255)); 
-    sprite->sprite->End (); 
-   
-    return; // finished 
- } 
-   
-   
- static void Render_GetTextBoundaries (int max_width, int font_id, wchar_t *text, RECT *rect) 
- { 
-    // this function computes and returns the size of the rectangle the specified text will fit into. Note that text may be modified 
-    // to insert new lines if it doesn't fit in a single line. 
-   
-    int char_index; 
-    int length; 
-    int optimal_length; 
-    bool have_split; 
-   
-    // blank out the output rectangle 
-    memset (rect, 0, sizeof (RECT)); 
-   
-    // ask direct3D to compute the text size a first time 
-    fonts[font_id].font->DrawText (NULL, text, -1, rect, DT_CALCRECT, D3DCOLOR (0)); 
-   
-    // if max width is not set, set it to viewport width 
-    if (max_width < 0) 
-       max_width = initial_width; // then use it to compute the real max width 
-   
-    // do we need more than one line ? 
-    if (rect->right > max_width) 
-    { 
-       // see how many lines we need and compute the optimal length of one line 
-       length = wcslen (text); 
-       optimal_length = length / (1 + rect->right / (int) max_width); 
-       have_split = false; 
-       for (char_index = optimal_length; char_index < length; char_index++) 
-          if (iswspace (text[char_index])) 
-          { 
-             text[char_index] = L'\n'; // interpolate linefeeds into string 
-             have_split = true; // remember string has been split 
-             char_index += optimal_length; 
-          } 
-   
-       // and ask direct3D to compute the text size again 
-       fonts[font_id].font->DrawText (NULL, text, -1, rect, DT_CALCRECT, D3DCOLOR (0)); 
-    } 
-   
-    return; // finished 
- } 
-   
-   
- static void Render_wprintf (int x, int y, int max_width, int horiz_align, int vert_align, int text_align, int font_id, unsigned long color_rgba, RECT *out_rect, const wchar_t *fmt, ...) 
- { 
-    // this function displays text on the Direct3D interface according to the given parameters. X and Y are the base coordinates of 
-    // the text's bounding rectangle. Max_width is the maximum allowed width of this rectangle before wrapping words on a new line. 
-    // Horiz_align and vert_align are the alignment parameters of the RECTANGLE relatively to X and Y. Text_align is the alignment of 
-    // the TEXT inside this rectangle (meaning, you can have right-aligned text in a rectangle that is centered on a point). Font_id 
-    // and color.alphargb define the font and color of the text. Out_rect, if filled, will point to a RECT structure describing the text's 
-    // bounding rectangle, after any word wrapping corrections have been made. Fmt is a format string containing the text itself, 
-    // printf-style. 
-   
-    va_list argptr; 
-    RECT rect; 
-    int left; 
-    int top; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    wvsprintf (printf_buffer, fmt, argptr); 
-    va_end (argptr); 
-   
-    // get the text boundaries 
-    Render_GetTextBoundaries (max_width, font_id, printf_buffer, &rect); 
-   
-    // horizontal alignment 
-    if (horiz_align == ALIGN_LEFT) 
-       left = x; 
-    else if (horiz_align == ALIGN_RIGHT) 
-       left = x - rect.right; 
-    else 
-       left = x - rect.right / 2; 
-   
-    // vertical alignment 
-    if (vert_align == ALIGN_TOP) 
-       top = y; 
-    else if (vert_align == ALIGN_BOTTOM) 
-       top = y - rect.bottom; 
-    else 
-       top = y - rect.bottom / 2; 
-   
-    // now reposition our rectangle correctly acording to alignment 
-    OffsetRect (&rect, left, top); 
-   
-    // and draw the text 
-    if (text_align == ALIGN_LEFT) 
-       fonts[font_id].font->DrawText (NULL, printf_buffer, -1, &rect, DT_LEFT, RGBACOLOR_TO_ARGBCOLOR (color_rgba)); 
-    else if (horiz_align == ALIGN_RIGHT) 
-       fonts[font_id].font->DrawText (NULL, printf_buffer, -1, &rect, DT_RIGHT, RGBACOLOR_TO_ARGBCOLOR (color_rgba)); 
-    else 
-       fonts[font_id].font->DrawText (NULL, printf_buffer, -1, &rect, DT_CENTER, RGBACOLOR_TO_ARGBCOLOR (color_rgba)); 
-   
-    // do we want the output rectangle ? 
-    if (out_rect != NULL) 
-       memcpy (out_rect, &rect, sizeof (rect)); // if so, copy it in the given variable 
-   
-    return; // finished 
- } 
-   
-   
- static float DistanceToCamera (float x, float y, float z) 
- { 
-    // this function computes the distance of the point at coordinates x,y,z to the camera 
-   
-    vector_t displacement; 
-   
-    // compute displacement... 
-    displacement.x = x - camera_position.x; 
-    displacement.y = y - camera_position.y; 
-    displacement.z = z - camera_position.z; 
-   
-    // ...and then Pythagores in 3D 
-    return (sqrtf (displacement.x * displacement.x + displacement.y * displacement.y + displacement.z * displacement.z)); 
- } 
-   
-   
- static float FadeFloat (float from, float to, float start_time, float end_time) 
- { 
-    // helper function to return a progressive variation between from and to based on time 
-   
-    if (end_time < current_time) 
-       return (to); 
-   
-    //      base + (variation) * (               fraction of completion               ) 
-    return (from + (to - from) * (current_time - start_time) / (end_time - start_time)); 
- } 
-   
-   
- static unsigned long HashString (const wchar_t *string_buffer)  
- { 
-    // super fast string hash function, code courtesy of 
-    // http://www.azillionmonkeys.com/qed/hash.html 
-   
-    unsigned long length; 
-    unsigned long hash; 
-    unsigned long tmp; 
-    int remaining; 
-   
-    // first, get the string length and start with this as a hash value 
-    length = wcslen (string_buffer) * sizeof (wchar_t); 
-    hash = length; 
-   
-    // figure out how many bytes there will remain after 32-bit processing 
-    remaining = length & 3; 
-    length >>= 2; 
-   
-    // main loop, process 32-bit blocks 
-    for ( ; length > 0; length--) 
-    { 
-       hash += *((const unsigned short *) string_buffer); 
-       tmp = ((*((const unsigned short *) (string_buffer + 2))) << 11) ^ hash; 
-       hash = (hash << 16) ^ tmp; 
-       string_buffer += 2 * sizeof (unsigned short); 
-       hash += hash >> 11; 
-    } 
-   
-    // handle the remaining bytes 
-    if (remaining == 3) 
-    { 
-       hash += *((const unsigned short *) string_buffer); 
-       hash ^= hash << 16; 
-       hash ^= string_buffer[sizeof (unsigned short)] << 18; 
-       hash += hash >> 11; 
-    } 
-    else if (remaining == 2) 
-    { 
-       hash += *((const unsigned short *) string_buffer); 
-       hash ^= hash << 11; 
-       hash += hash >> 17; 
-    } 
-    else if (remaining == 1) 
-    { 
-       hash += *string_buffer; 
-       hash ^= hash << 10; 
-       hash += hash >> 1; 
-    } 
-   
-    // force "avalanching" of final 127 bits 
-    hash ^= hash << 3; 
-    hash += hash >> 5; 
-    hash ^= hash << 4; 
-    hash += hash >> 17; 
-    hash ^= hash << 25; 
-    hash += hash >> 6; 
-   
-    return (hash); // finished, return the hash value 
- } 
-   
-   
- static unsigned long HashFile (const wchar_t *file_pathname)  
- { 
-    // super fast file content pseudo-hash function 
-   
-    unsigned short value; 
-    struct _stat fileinfo; 
-    FILE *fp; 
-   
-    // first, get info about the file 
-    if (_wstat (file_pathname, &fileinfo) != 0) 
-       return ((unsigned long) time (NULL)); // if file can't be open, return a random number 
-   
-    // open the file 
-    _wfopen_s (&fp, file_pathname, L"rb"); 
-    if (fp == NULL) 
-       return ((unsigned long) time (NULL)); // if file can't be open, return a random number 
-   
-    // seek at 2/3 of file size (if file is small enough, return only its content) 
-    if (fileinfo.st_size >= 4) 
-    { 
-       fseek (fp, fileinfo.st_size * 2 / 3, SEEK_SET); // seek at 2/3 of file 
-       fread (&value, 2, 1, fp); // and read a word here 
-    } 
-    else if (fileinfo.st_size >= 2) 
-       fread (&value, 2, 1, fp); 
-    else if (fileinfo.st_size == 1) 
-       value = fgetc (fp); 
-    else 
-       value = 0; 
-   
-    // finished, close the file 
-    fclose (fp); 
-   
-    // and return a hash composed of the 16 lower bits of the file size and the value we read 
-    return ((unsigned long) (fileinfo.st_size << 16) | (unsigned long) value); 
- } 
-   
-   
- static void ResolveWildcard (wchar_t *file_pathname, wchar_t *extensions_separated_by_bars) 
- { 
-    // this function resolves a pathname ending with .* by testing with various possible 
-    // file extensions until one of the files formed that way is found to exist. 
-   
-    static wchar_t extension_list[256]; // needs to be modifiable for strtok() 
-    wchar_t *current_extension; 
-    wchar_t *wcstok_context; 
-    struct _stat fileinfo; 
-    int length; 
-   
-    wcscpy_s (extension_list, WCHAR_SIZEOF (extension_list), extensions_separated_by_bars); 
-    length = wcslen (file_pathname); // get pathname length 
-   
-    // does the pathname we want NOT end with a wildcard ? 
-    if ((length < 2) || (wcscmp (&file_pathname[length - 2], L".*") != 0)) 
-       return; // no need to resolve anything 
-   
-    // test each extension and see if a corresponding file exists 
-    current_extension = wcstok_s (extension_list, L"|", &wcstok_context); 
-    while (current_extension != NULL) 
-    { 
-       if (*current_extension == L'.') 
-          current_extension++; // if current extension starts with a dot, skip it 
-       wcscpy_s (&file_pathname[length - 1], wcslen (current_extension) + 1, current_extension); 
-       if (_wstat (file_pathname, &fileinfo) == 0) 
-          return; // found a file with this extension 
-       current_extension = wcstok_s (NULL, L"|", &wcstok_context); 
-    } 
-   
-    wcscpy_s (&file_pathname[length - 1], 2, L"*"); 
-    return; // if none of these extensions match, put the wildcard back and return 
- } 
-   
-   
- static int SortReflectedObjects (const void *object1, const void *object2) 
- { 
-    // callback function used by qsort() when sorting the reflected objects according to their distance to the viewer 
-   
-    return ((int) (1000.0f * (((reflectedobject_t *) object2)->distance - ((reflectedobject_t *) object1)->distance))); 
- } 
-