mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-18 19:01:45 +02:00
XBOX port WIP
This commit is contained in:
@@ -1523,7 +1523,7 @@ struct DummyController : Controller {
|
||||
|
||||
DummyController(IGame *game, int entity) : Controller(game, entity) {}
|
||||
|
||||
virtual void update() override {};
|
||||
virtual void update() {}
|
||||
};
|
||||
|
||||
|
||||
|
30
src/core.h
30
src/core.h
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define OS_FILEIO_CACHE
|
||||
#define OS_PTHREAD_MT
|
||||
@@ -129,6 +128,15 @@
|
||||
#define _GAPI_GL 1
|
||||
|
||||
#undef OS_PTHREAD_MT
|
||||
#elif _XBOX
|
||||
#define _OS_XBOX 1
|
||||
#define _GAPI_D3D8 1
|
||||
|
||||
#undef OS_PTHREAD_MT
|
||||
|
||||
#define NOMINMAX
|
||||
#include <xtl.h>
|
||||
#include <xgraphics.h>
|
||||
#endif
|
||||
|
||||
#ifndef _OS_PSP
|
||||
@@ -608,6 +616,7 @@ enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult, bmMAX };
|
||||
|
||||
namespace Core {
|
||||
float eye;
|
||||
float aspectFix = 1.0f;
|
||||
Texture *eyeTex[2];
|
||||
short4 viewport, viewportDef, scissor;
|
||||
mat4 mModel, mView, mProj, mViewProj, mViewInv;
|
||||
@@ -617,7 +626,6 @@ namespace Core {
|
||||
vec4 lightPos[MAX_LIGHTS];
|
||||
vec4 lightColor[MAX_LIGHTS];
|
||||
vec4 params;
|
||||
vec4 fogParams;
|
||||
vec4 contacts[MAX_CONTACTS];
|
||||
|
||||
struct LightStack {
|
||||
@@ -707,6 +715,8 @@ namespace Core {
|
||||
#include "gapi/sw.h"
|
||||
#elif _GAPI_GL
|
||||
#include "gapi/gl.h"
|
||||
#elif _GAPI_D3D8
|
||||
#include "gapi/d3d8.h"
|
||||
#elif _GAPI_D3D9
|
||||
#include "gapi/d3d9.h"
|
||||
#elif _GAPI_D3D11
|
||||
@@ -978,6 +988,13 @@ namespace Core {
|
||||
settings.audio.reverb = false;
|
||||
#endif
|
||||
|
||||
#ifdef _OS_XBOX
|
||||
settings.detail.setFilter (Core::Settings::HIGH);
|
||||
settings.detail.setLighting (Core::Settings::LOW);
|
||||
settings.detail.setShadows (Core::Settings::LOW);
|
||||
settings.detail.setWater (Core::Settings::LOW);
|
||||
#endif
|
||||
|
||||
memset(&active, 0, sizeof(active));
|
||||
renderState = 0;
|
||||
|
||||
@@ -1190,6 +1207,15 @@ namespace Core {
|
||||
Core::active.shader->setParam(uMaterial, Core::active.material);
|
||||
}
|
||||
|
||||
void setFog(const vec4 ¶ms) {
|
||||
#ifdef _XBOX
|
||||
GAPI::setFog(params);
|
||||
#else
|
||||
ASSERT(Core::active.shader);
|
||||
Core::active.shader->setParam(uFogParams, params);
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateLights() {
|
||||
GAPI::updateLights(lightPos, lightColor, MAX_LIGHTS);
|
||||
}
|
||||
|
12
src/format.h
12
src/format.h
@@ -3111,14 +3111,14 @@ namespace TR {
|
||||
int16 waterSplash;
|
||||
int16 glyphs;
|
||||
|
||||
struct {
|
||||
struct Weapon {
|
||||
int16 items[MAX_WEAPONS];
|
||||
int16& operator[] (Entity::Type type) {
|
||||
return items[getWeaponIndex(type)];
|
||||
};
|
||||
} weapons;
|
||||
|
||||
struct {
|
||||
struct Inventory {
|
||||
int16 passport;
|
||||
int16 passport_closed;
|
||||
int16 map;
|
||||
@@ -3131,14 +3131,14 @@ namespace TR {
|
||||
int16 gamma;
|
||||
int16 explosive;
|
||||
|
||||
struct {
|
||||
struct Weapon {
|
||||
int16 items[MAX_WEAPONS];
|
||||
int16& operator[] (Entity::Type type) {
|
||||
return items[getWeaponIndex(type)];
|
||||
};
|
||||
} weapons;
|
||||
|
||||
struct {
|
||||
struct Ammo {
|
||||
int16 items[MAX_WEAPONS];
|
||||
int16& operator[] (Entity::Type type) {
|
||||
return items[getWeaponIndex(type)];
|
||||
@@ -3910,7 +3910,7 @@ namespace TR {
|
||||
((uint64)((const char*)(str))[4] << 32) | ((uint64)((const char*)(str))[5] << 40) | ((uint64)((const char*)(str))[6] << 48) | ((uint64)((const char*)(str))[7] << 56))
|
||||
|
||||
void readSAT(Stream &stream) {
|
||||
#if !defined(_OS_PSP) && !defined(_OS_3DS)
|
||||
#if !defined(_OS_PSP) && !defined(_OS_3DS) && !defined(_OS_XBOX)
|
||||
Room *room = NULL;
|
||||
|
||||
while (stream.pos < stream.size) {
|
||||
@@ -6224,7 +6224,7 @@ namespace TR {
|
||||
|
||||
if (animTexBlockSize) {
|
||||
uint16 *animTexBlock = new uint16[animTexBlockSize];
|
||||
for (int i = 0; i < animTexBlockSize; i++) {
|
||||
for (uint32 i = 0; i < animTexBlockSize; i++) {
|
||||
animTexBlock[i] = stream.readLE16();
|
||||
}
|
||||
|
||||
|
@@ -1695,6 +1695,7 @@ namespace TR {
|
||||
}
|
||||
|
||||
#define FOG_DIST (1.0f / (18 * 1024))
|
||||
#define FOG_NONE vec4(0.0f, 0.0f, 0.0f, 0.0f)
|
||||
#define FOG_BLACK vec4(0.0f, 0.0f, 0.0f, FOG_DIST)
|
||||
#define FOG_SANDY vec4(0.2f, 0.1f, 0.0f, FOG_DIST)
|
||||
#define FOG_GREEN vec4(0.0f, 0.1f, 0.0f, FOG_DIST)
|
||||
|
866
src/gapi/d3d8.h
Normal file
866
src/gapi/d3d8.h
Normal file
@@ -0,0 +1,866 @@
|
||||
#ifndef H_GAPI_D3D8
|
||||
#define H_GAPI_D3D8
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define PROFILE_MARKER(title)
|
||||
#define PROFILE_LABEL(id, name, label)
|
||||
#define PROFILE_TIMING(time)
|
||||
|
||||
extern LPDIRECT3D8 D3D;
|
||||
extern LPDIRECT3DDEVICE8 device;
|
||||
extern D3DPRESENT_PARAMETERS d3dpp;
|
||||
|
||||
#ifdef _DEBUG
|
||||
void D3DCHECK(HRESULT res) {
|
||||
if (!FAILED(res)) return;
|
||||
|
||||
LOG("! ");
|
||||
switch (res) {
|
||||
case D3DERR_WRONGTEXTUREFORMAT : LOG("D3DERR_WRONGTEXTUREFORMAT"); break;
|
||||
case D3DERR_UNSUPPORTEDCOLOROPERATION : LOG("D3DERR_UNSUPPORTEDCOLOROPERATION"); break;
|
||||
case D3DERR_UNSUPPORTEDCOLORARG : LOG("D3DERR_UNSUPPORTEDCOLORARG"); break;
|
||||
case D3DERR_UNSUPPORTEDALPHAOPERATION : LOG("D3DERR_UNSUPPORTEDALPHAOPERATION"); break;
|
||||
case D3DERR_UNSUPPORTEDALPHAARG : LOG("D3DERR_UNSUPPORTEDALPHAARG"); break;
|
||||
case D3DERR_TOOMANYOPERATIONS : LOG("D3DERR_TOOMANYOPERATIONS"); break;
|
||||
case D3DERR_CONFLICTINGTEXTUREFILTER : LOG("D3DERR_CONFLICTINGTEXTUREFILTER"); break;
|
||||
case D3DERR_UNSUPPORTEDFACTORVALUE : LOG("D3DERR_UNSUPPORTEDFACTORVALUE"); break;
|
||||
case D3DERR_CONFLICTINGRENDERSTATE : LOG("D3DERR_CONFLICTINGRENDERSTATE"); break;
|
||||
case D3DERR_UNSUPPORTEDTEXTUREFILTER : LOG("D3DERR_UNSUPPORTEDTEXTUREFILTER"); break;
|
||||
case D3DERR_CONFLICTINGTEXTUREPALETTE : LOG("D3DERR_CONFLICTINGTEXTUREPALETTE"); break;
|
||||
case D3DERR_DRIVERINTERNALERROR : LOG("D3DERR_DRIVERINTERNALERROR"); break;
|
||||
case D3DERR_NOTFOUND : LOG("D3DERR_NOTFOUND"); break;
|
||||
case D3DERR_MOREDATA : LOG("D3DERR_MOREDATA"); break;
|
||||
case D3DERR_DEVICELOST : LOG("D3DERR_DEVICELOST"); break;
|
||||
case D3DERR_DEVICENOTRESET : LOG("D3DERR_DEVICENOTRESET"); break;
|
||||
case D3DERR_NOTAVAILABLE : LOG("D3DERR_NOTAVAILABLE"); break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY : LOG("D3DERR_OUTOFVIDEOMEMORY"); break;
|
||||
case D3DERR_INVALIDDEVICE : LOG("D3DERR_INVALIDDEVICE"); break;
|
||||
case D3DERR_INVALIDCALL : LOG("D3DERR_INVALIDCALL"); break;
|
||||
default : LOG("D3DERR_UNKNOWN"); break;
|
||||
}
|
||||
LOG("\n");
|
||||
ASSERT(false);
|
||||
}
|
||||
#else
|
||||
#define D3DCHECK(res) res
|
||||
#endif
|
||||
|
||||
namespace GAPI {
|
||||
using namespace Core;
|
||||
|
||||
typedef ::Vertex Vertex;
|
||||
|
||||
int cullMode, blendMode;
|
||||
uint32 clearColor;
|
||||
|
||||
LPDIRECT3DSURFACE8 defRT, defDS;
|
||||
|
||||
const DWORD vertexDecl[] =
|
||||
{
|
||||
D3DVSD_STREAM(0),
|
||||
D3DVSD_REG( aCoord, D3DVSDT_SHORT4 ),
|
||||
D3DVSD_REG( aNormal, D3DVSDT_NORMSHORT4 ),
|
||||
D3DVSD_REG( aTexCoord, D3DVSDT_NORMSHORT4 ),
|
||||
D3DVSD_REG( aColor, D3DVSDT_PBYTE4 ),
|
||||
D3DVSD_REG( aLight, D3DVSDT_PBYTE4 ),
|
||||
D3DVSD_END()
|
||||
};
|
||||
|
||||
struct Texture;
|
||||
struct Mesh;
|
||||
|
||||
struct Resource {
|
||||
Texture *texture;
|
||||
Mesh *mesh;
|
||||
} resList[256];
|
||||
int resCount;
|
||||
|
||||
void registerResource(Mesh *mesh) {
|
||||
resList[resCount].mesh = mesh;
|
||||
resList[resCount].texture = NULL;
|
||||
resCount++;
|
||||
}
|
||||
|
||||
void registerResource(Texture *texture) {
|
||||
resList[resCount].mesh = NULL;
|
||||
resList[resCount].texture = texture;
|
||||
resCount++;
|
||||
}
|
||||
|
||||
void unregisterResource(void *res) {
|
||||
for (int i = 0; i < resCount; i++)
|
||||
if (resList[i].mesh == res || resList[i].texture == res) {
|
||||
resList[i] = resList[--resCount];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Shader
|
||||
#include "shaders/d3d8/shaders.h"
|
||||
|
||||
enum {
|
||||
USAGE_VS,
|
||||
USAGE_PS,
|
||||
};
|
||||
|
||||
static const struct Binding {
|
||||
int reg;
|
||||
int usage;
|
||||
} bindings[uMAX] = {
|
||||
{ 0, USAGE_VS | USAGE_PS }, // uParam
|
||||
{ 1, USAGE_VS | USAGE_PS }, // uTexParam
|
||||
{ 2, USAGE_VS | USAGE_PS }, // uViewProj
|
||||
{ 6, USAGE_VS | USAGE_PS }, // uBasis
|
||||
{ 70, USAGE_VS | USAGE_PS }, // uLightProj
|
||||
{ 74, USAGE_VS | USAGE_PS }, // uMaterial
|
||||
{ 75, USAGE_VS | USAGE_PS }, // uAmbient
|
||||
{ 81, USAGE_VS | USAGE_PS }, // uFogParams
|
||||
{ 82, USAGE_VS | USAGE_PS }, // uViewPos
|
||||
{ 83, USAGE_VS | USAGE_PS }, // uLightPos
|
||||
{ 87, USAGE_VS | USAGE_PS }, // uLightColor
|
||||
{ 91, USAGE_VS | USAGE_PS }, // uRoomSize
|
||||
{ 92, USAGE_VS | USAGE_PS }, // uPosScale
|
||||
{ 98, USAGE_VS | USAGE_PS }, // uContacts
|
||||
};
|
||||
|
||||
struct Shader {
|
||||
DWORD VS;
|
||||
DWORD PS;
|
||||
|
||||
Shader() : VS(NULL), PS(NULL) {}
|
||||
|
||||
void init(Core::Pass pass, int type, int *def, int defCount) {
|
||||
bool underwater = false;
|
||||
|
||||
for (int i = 0; i < defCount; i++) {
|
||||
if (def[i] == SD_UNDERWATER) {
|
||||
underwater = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define SHADER(S,P) S##_##P
|
||||
#define SHADER_U(S,P) (underwater ? SHADER(S##_u,P) : SHADER(S,P))
|
||||
|
||||
const uint8 *vSrc, *fSrc;
|
||||
switch (pass) {
|
||||
case passCompose :
|
||||
switch (type) {
|
||||
case 0 : vSrc = SHADER_U ( compose_sprite, v ); fSrc = SHADER_U ( compose_sprite, f ); break;
|
||||
case 1 : vSrc = SHADER ( compose_flash, v ); fSrc = SHADER ( compose_flash, f ); break;
|
||||
case 2 : vSrc = SHADER_U ( compose_room, v ); fSrc = SHADER_U ( compose_room, f ); break;
|
||||
case 3 : vSrc = SHADER_U ( compose_entity, v ); fSrc = SHADER_U ( compose_entity, f ); break;
|
||||
case 4 : vSrc = SHADER ( compose_mirror, v ); fSrc = SHADER ( compose_mirror, f ); break;
|
||||
default : ASSERT(false);
|
||||
}
|
||||
break;
|
||||
case passShadow :
|
||||
switch (type) {
|
||||
case 3 :
|
||||
case 4 : vSrc = SHADER ( shadow_entity, v ); fSrc = SHADER ( shadow_entity, f ); break;
|
||||
default : ASSERT(false);
|
||||
}
|
||||
break;
|
||||
case passAmbient :
|
||||
switch (type) {
|
||||
case 0 : vSrc = SHADER ( ambient_sprite, v ); fSrc = SHADER ( ambient_sprite, f ); break;
|
||||
case 1 : vSrc = SHADER ( ambient_room, v ); fSrc = SHADER ( ambient_room, f ); break; // TYPE_FLASH (sky)
|
||||
case 2 : vSrc = SHADER ( ambient_room, v ); fSrc = SHADER ( ambient_room, f ); break;
|
||||
default : ASSERT(false);
|
||||
}
|
||||
break;
|
||||
case passSky : vSrc = SHADER ( gui, v ); fSrc = SHADER ( gui, f ); break; // TODO
|
||||
/*
|
||||
case passWater :
|
||||
switch (type) {
|
||||
case 0 : vSrc = SHADER ( water_drop, v ); fSrc = SHADER ( water_drop, f ); break;
|
||||
case 1 : vSrc = SHADER ( water_simulate, v ); fSrc = SHADER ( water_simulate, f ); break;
|
||||
case 2 : vSrc = SHADER ( water_caustics, v ); fSrc = SHADER ( water_caustics, f ); break;
|
||||
case 3 : vSrc = SHADER ( water_rays, v ); fSrc = SHADER ( water_rays, f ); break;
|
||||
case 4 : vSrc = SHADER ( water_mask, v ); fSrc = SHADER ( water_mask, f ); break;
|
||||
case 5 : vSrc = SHADER ( water_compose, v ); fSrc = SHADER ( water_compose, f ); break;
|
||||
default : ASSERT(false);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case passFilter :
|
||||
switch (type) {
|
||||
case 0 : vSrc = SHADER ( filter_upscale, v ); fSrc = SHADER ( filter_upscale, f ); break;
|
||||
case 1 : vSrc = SHADER ( filter_downsample, v ); fSrc = SHADER ( filter_downsample, f ); break;
|
||||
case 3 : vSrc = SHADER ( filter_grayscale, v ); fSrc = SHADER ( filter_grayscale, f ); break;
|
||||
case 4 : vSrc = SHADER ( filter_blur, v ); fSrc = SHADER ( filter_blur, f ); break;
|
||||
case 5 : vSrc = SHADER ( filter_blur, v ); fSrc = SHADER ( filter_blur, f ); break; // TODO anaglyph
|
||||
default : ASSERT(false);
|
||||
}
|
||||
break;
|
||||
case passGUI : vSrc = SHADER ( gui, v ); fSrc = SHADER ( gui, f ); break;
|
||||
default : ASSERT(false); LOG("! wrong pass id\n"); return;
|
||||
}
|
||||
|
||||
#undef SHADER
|
||||
#undef SHADER_U
|
||||
|
||||
device->CreateVertexShader(vertexDecl, (DWORD*)vSrc, &VS, 0);
|
||||
device->CreatePixelShader(&((D3DPIXELSHADERDEF_FILE*)fSrc)->Psd, &PS);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
device->SetVertexShader(0);
|
||||
device->SetPixelShader(0);
|
||||
if (VS) device->DeleteVertexShader(VS);
|
||||
if (PS) device->DeletePixelShader(PS);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
if (Core::active.shader != this) {
|
||||
Core::active.shader = this;
|
||||
device->SetVertexShader(VS);
|
||||
device->SetPixelShader(PS);
|
||||
}
|
||||
}
|
||||
|
||||
void setConstant(UniformType uType, const float *value, int vectors) {
|
||||
const Binding &b = bindings[uType];
|
||||
if (b.usage | USAGE_VS) device->SetVertexShaderConstant (b.reg, value, vectors);
|
||||
// if (b.usage | USAGE_PS) device->SetPixelShaderConstant (b.reg, value, vectors);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {
|
||||
setConstant(uType, (float*)&value, count);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {
|
||||
setConstant(uType, (float*)&value, count * 4);
|
||||
}
|
||||
};
|
||||
|
||||
// Texture
|
||||
struct Texture {
|
||||
LPDIRECT3DTEXTURE8 tex2D;
|
||||
LPDIRECT3DCUBETEXTURE8 texCube;
|
||||
|
||||
int width, height, depth, origWidth, origHeight, origDepth;
|
||||
TexFormat fmt;
|
||||
uint32 opt;
|
||||
D3DFORMAT d3dformat;
|
||||
|
||||
Texture(int width, int height, int depth, uint32 opt) : tex2D(NULL), texCube(NULL), width(width), height(height), depth(depth), origWidth(width), origHeight(height), origDepth(depth), fmt(FMT_RGBA), opt(opt) {}
|
||||
|
||||
void init(void *data) {
|
||||
ASSERT((opt & OPT_PROXY) == 0);
|
||||
|
||||
bool isDepth = fmt == FMT_DEPTH || fmt == FMT_SHADOW;
|
||||
bool mipmaps = (opt & OPT_MIPMAPS) != 0;
|
||||
bool cube = (opt & OPT_CUBEMAP) != 0;
|
||||
bool dynamic = (opt & OPT_DYNAMIC) != 0;
|
||||
bool isTarget = (opt & OPT_TARGET) != 0 && !isDepth;
|
||||
|
||||
static const struct FormatDesc {
|
||||
int bpp;
|
||||
D3DFORMAT format;
|
||||
} formats[FMT_MAX] = {
|
||||
{ 8, D3DFMT_L8 },
|
||||
{ 32, D3DFMT_A8R8G8B8 },
|
||||
{ 16, D3DFMT_R5G6B5 },
|
||||
{ 16, D3DFMT_A1R5G5B5 },
|
||||
{ 64, D3DFMT_A8R8G8B8 }, // TODO
|
||||
{ 32, D3DFMT_A8R8G8B8 }, // TODO
|
||||
{ 16, D3DFMT_LIN_D16 },
|
||||
{ 16, D3DFMT_LIN_D16 },
|
||||
};
|
||||
|
||||
FormatDesc desc = formats[fmt];
|
||||
|
||||
if (isTarget) {
|
||||
|
||||
}
|
||||
|
||||
uint32 usage = 0;
|
||||
if (isDepth) usage |= D3DUSAGE_DEPTHSTENCIL;
|
||||
if (isTarget) usage |= D3DUSAGE_RENDERTARGET;
|
||||
|
||||
D3DPOOL pool = (isTarget || isDepth) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
|
||||
|
||||
d3dformat = desc.format;
|
||||
|
||||
if (cube) {
|
||||
D3DCHECK(device->CreateCubeTexture(width, 1, usage, desc.format, pool, &texCube));
|
||||
} else {
|
||||
D3DCHECK(device->CreateTexture(width, height, mipmaps ? 4 : 1, usage, desc.format, pool, &tex2D));
|
||||
if (data && !isTarget) {
|
||||
update(data);
|
||||
}
|
||||
}
|
||||
|
||||
if (pool != D3DPOOL_MANAGED)
|
||||
registerResource(this);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
unregisterResource(this);
|
||||
if (tex2D) tex2D->Release();
|
||||
if (texCube) texCube->Release();
|
||||
}
|
||||
|
||||
VOID XBUtil_SwizzleTexture2D( D3DLOCKED_RECT* pLock, const D3DSURFACE_DESC* pDesc )
|
||||
{
|
||||
DWORD dwPixelSize = XGBytesPerPixelFromFormat( pDesc->Format );
|
||||
DWORD dwTextureSize = pDesc->Width * pDesc->Height * dwPixelSize;
|
||||
|
||||
BYTE* pSrcBits = new BYTE[ dwTextureSize ];
|
||||
memcpy( pSrcBits, pLock->pBits, dwTextureSize );
|
||||
|
||||
XGSwizzleRect( pSrcBits, 0, NULL, pLock->pBits,
|
||||
pDesc->Width, pDesc->Height,
|
||||
NULL, dwPixelSize );
|
||||
|
||||
delete[] pSrcBits;
|
||||
}
|
||||
|
||||
void updateLevel(int32 level, void *data) {
|
||||
int32 bpp;
|
||||
switch (fmt) {
|
||||
case FMT_LUMINANCE : bpp = 1; break;
|
||||
case FMT_RGBA : bpp = 4; break;
|
||||
default : ASSERT(false);
|
||||
}
|
||||
|
||||
int32 w = width >> level;
|
||||
int32 h = height >> level;
|
||||
int32 ow = origWidth >> level;
|
||||
int32 oh = origHeight >> level;
|
||||
|
||||
uint8 *buffer = new uint8[w * h * bpp];
|
||||
|
||||
if (fmt == FMT_RGBA) {
|
||||
uint8 *src = (uint8*)data;
|
||||
uint8 *dst = buffer;
|
||||
|
||||
for (int y = 0; y < oh; y++) {
|
||||
uint8 *ptr = dst;
|
||||
for (int x = 0; x < ow; x++) {
|
||||
ptr[0] = src[2];
|
||||
ptr[1] = src[1];
|
||||
ptr[2] = src[0];
|
||||
ptr[3] = src[3];
|
||||
ptr += 4;
|
||||
src += 4;
|
||||
}
|
||||
dst += w * 4;
|
||||
}
|
||||
} else {
|
||||
if (w == ow && h == oh) {
|
||||
memcpy(buffer, data, w * h * bpp);
|
||||
} else {
|
||||
uint8 *src = (uint8*)data;
|
||||
uint8 *dst = buffer;
|
||||
for (int y = 0; y < oh; y++) {
|
||||
memcpy(dst, src, ow * bpp);
|
||||
src += ow * bpp;
|
||||
dst += w * bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
D3DCHECK(tex2D->LockRect(level, &rect, NULL, 0));
|
||||
XGSwizzleRect(buffer, 0, NULL, rect.pBits, w, h, NULL, 4);
|
||||
D3DCHECK(tex2D->UnlockRect(level));
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
if ((opt & OPT_MIPMAPS) && (level < 3)) {
|
||||
ASSERT(fmt == FMT_RGBA);
|
||||
|
||||
uint8 *mip = new uint8[(ow >> 1) * (oh >> 1) * 4];
|
||||
uint8 *dst = mip;
|
||||
uint8 *src = (uint8*)data;
|
||||
|
||||
for (int32 y = 0; y < oh; y += 2) {
|
||||
for (int32 x = 0; x < ow; x += 2) {
|
||||
*dst++ = (src[0] + src[4] + src[ow * 4] + src[ow * 4 + 4]) >> 2; src++; // R
|
||||
*dst++ = (src[0] + src[4] + src[ow * 4] + src[ow * 4 + 4]) >> 2; src++; // G
|
||||
*dst++ = (src[0] + src[4] + src[ow * 4] + src[ow * 4 + 4]) >> 2; src++; // B
|
||||
*dst++ = (src[0] + src[4] + src[ow * 4] + src[ow * 4 + 4]) >> 2; src++; // A
|
||||
src += 4;
|
||||
}
|
||||
src += ow * 4;
|
||||
}
|
||||
|
||||
updateLevel(level + 1, mip);
|
||||
|
||||
delete[] mip;
|
||||
}
|
||||
}
|
||||
|
||||
void update(void *data) {
|
||||
updateLevel(0, data);
|
||||
}
|
||||
|
||||
void bind(int sampler) {
|
||||
if (sampler > 3) return; // TODO
|
||||
|
||||
if (opt & OPT_PROXY) return;
|
||||
ASSERT(tex2D || texCube);
|
||||
|
||||
if (Core::active.textures[sampler] != this) {
|
||||
Core::active.textures[sampler] = this;
|
||||
if (tex2D) {
|
||||
device->SetTexture(sampler, tex2D);
|
||||
/* TODO unsupported
|
||||
if (opt & OPT_VERTEX) {
|
||||
device->SetTexture(D3DVERTEXTEXTURESAMPLER0 + sampler, tex2D);
|
||||
}*/
|
||||
} else if (texCube) {
|
||||
device->SetTexture(sampler, texCube);
|
||||
}
|
||||
|
||||
bool filter = (Core::settings.detail.filter > Core::Settings::LOW) && !(opt & OPT_NEAREST);
|
||||
bool mipmaps = (Core::settings.detail.filter > Core::Settings::LOW) && (opt & OPT_MIPMAPS);
|
||||
bool aniso = (Core::settings.detail.filter > Core::Settings::MEDIUM) && mipmaps && (Core::support.maxAniso > 0);
|
||||
|
||||
device->SetTextureStageState(sampler, D3DTSS_ADDRESSU, (opt & OPT_REPEAT) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
|
||||
device->SetTextureStageState(sampler, D3DTSS_ADDRESSV, (opt & OPT_REPEAT) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
|
||||
|
||||
if (aniso) {
|
||||
device->SetTextureStageState(sampler, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetTextureStageState(sampler, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device->SetTextureStageState(sampler, D3DTSS_MIPFILTER, D3DTEXF_NONE);
|
||||
device->SetTextureStageState(sampler, D3DTSS_MAXANISOTROPY, support.maxAniso);
|
||||
} else {
|
||||
device->SetTextureStageState(sampler, D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
device->SetTextureStageState(sampler, D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
device->SetTextureStageState(sampler, D3DTSS_MIPFILTER, mipmaps ? (filter ? D3DTEXF_LINEAR : D3DTEXF_POINT) : D3DTEXF_NONE);
|
||||
device->SetTextureStageState(sampler, D3DTSS_MAXANISOTROPY, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unbind(int sampler) {
|
||||
if (Core::active.textures[sampler]) {
|
||||
Core::active.textures[sampler] = NULL;
|
||||
device->SetTexture(sampler, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void generateMipMap() {}
|
||||
|
||||
void setFilterQuality(int value) {}
|
||||
};
|
||||
|
||||
// Mesh
|
||||
struct Mesh {
|
||||
LPDIRECT3DINDEXBUFFER8 IB;
|
||||
LPDIRECT3DVERTEXBUFFER8 VB;
|
||||
|
||||
int iCount;
|
||||
int vCount;
|
||||
bool dynamic;
|
||||
|
||||
Mesh(bool dynamic) : IB(NULL), VB(NULL), dynamic(dynamic) {}
|
||||
|
||||
void init(Index *indices, int iCount, ::Vertex *vertices, int vCount, int aCount) {
|
||||
this->iCount = iCount;
|
||||
this->vCount = vCount;
|
||||
ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex));
|
||||
|
||||
uint32 usage = D3DUSAGE_WRITEONLY | (dynamic ? D3DUSAGE_DYNAMIC : 0);
|
||||
D3DPOOL pool = dynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
|
||||
|
||||
D3DCHECK(device->CreateIndexBuffer (iCount * sizeof(Index), usage, D3DFMT_INDEX16, pool, &IB));
|
||||
D3DCHECK(device->CreateVertexBuffer (vCount * sizeof(Vertex), usage, D3DFMT_UNKNOWN, pool, &VB));
|
||||
|
||||
update(indices, iCount, vertices, vCount);
|
||||
|
||||
if (pool != D3DPOOL_MANAGED)
|
||||
registerResource(this);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
unregisterResource(this);
|
||||
IB->Release();
|
||||
VB->Release();
|
||||
}
|
||||
|
||||
void update(Index *indices, int iCount, ::Vertex *vertices, int vCount) {
|
||||
ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex));
|
||||
|
||||
void* ptr;
|
||||
int size;
|
||||
|
||||
if (indices && iCount) {
|
||||
size = iCount * sizeof(indices[0]);
|
||||
D3DCHECK(IB->Lock(0, 0, (BYTE**)&ptr, 0));
|
||||
memcpy(ptr, indices, size);
|
||||
D3DCHECK(IB->Unlock());
|
||||
}
|
||||
|
||||
if (vertices && vCount) {
|
||||
size = vCount * sizeof(vertices[0]);
|
||||
D3DCHECK(VB->Lock(0, 0, (BYTE**)&ptr, 0));
|
||||
memcpy(ptr, vertices, size);
|
||||
D3DCHECK(VB->Unlock());
|
||||
}
|
||||
}
|
||||
|
||||
void bind(const MeshRange &range) const {
|
||||
device->SetIndices(IB, range.vStart);
|
||||
device->SetStreamSource(0, VB, sizeof(Vertex));
|
||||
}
|
||||
|
||||
void initNextRange(MeshRange &range, int &aIndex) const {
|
||||
range.aIndex = -1;
|
||||
}
|
||||
};
|
||||
|
||||
// GLuint FBO, defaultFBO;
|
||||
struct RenderTargetCache {
|
||||
int count;
|
||||
struct Item {
|
||||
LPDIRECT3DSURFACE8 surface;
|
||||
int width;
|
||||
int height;
|
||||
} items[MAX_RENDER_BUFFERS];
|
||||
} rtCache[2];
|
||||
|
||||
void init() {
|
||||
memset(rtCache, 0, sizeof(rtCache));
|
||||
|
||||
D3DADAPTER_IDENTIFIER8 adapterInfo;
|
||||
D3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapterInfo);
|
||||
LOG("Vendor : %s\n", adapterInfo.Description);
|
||||
LOG("Renderer : Direct3D 8\n");
|
||||
|
||||
support.maxAniso = 4;
|
||||
support.maxVectors = 16;
|
||||
support.shaderBinary = false;
|
||||
support.VAO = false; // SHADOW_COLOR
|
||||
support.depthTexture = false; // SHADOW_DEPTH
|
||||
support.shadowSampler = false;
|
||||
support.discardFrame = false;
|
||||
support.texNPOT = false;
|
||||
support.texRG = false;
|
||||
support.texBorder = false;
|
||||
support.colorFloat = false;
|
||||
support.colorHalf = false;
|
||||
support.texFloatLinear = false;
|
||||
support.texFloat = false;
|
||||
support.texHalfLinear = false;
|
||||
support.texHalf = false;
|
||||
|
||||
#ifdef PROFILE
|
||||
support.profMarker = false;
|
||||
support.profTiming = false;
|
||||
#endif
|
||||
|
||||
defRT = defDS = NULL;
|
||||
|
||||
const float factors[] = {
|
||||
0.0f, 0.5f, 1.0f, 2.0f,
|
||||
0.6f, 0.9f, 0.9f, 32767.0f
|
||||
};
|
||||
device->SetVertexShaderConstant(94, factors, 2);
|
||||
|
||||
device->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_EXP);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
if (defRT) defRT->Release();
|
||||
if (defDS) defDS->Release();
|
||||
}
|
||||
|
||||
void resetDevice() {
|
||||
// release dummy RTs
|
||||
for (int i = 0; i < 2; i++) {
|
||||
RenderTargetCache &cache = rtCache[i];
|
||||
for (int j = 0; j < cache.count; j++)
|
||||
cache.items[j].surface->Release();
|
||||
cache.count = 0;
|
||||
}
|
||||
|
||||
// release texture RTs
|
||||
int tmpCount = resCount;
|
||||
Resource tmpList[256];
|
||||
memcpy(tmpList, resList, sizeof(Resource) * tmpCount);
|
||||
|
||||
for (int i = 0; i < tmpCount; i++) {
|
||||
Resource &res = tmpList[i];
|
||||
if (res.mesh)
|
||||
res.mesh->deinit();
|
||||
else
|
||||
res.texture->deinit();
|
||||
}
|
||||
|
||||
if (defRT) defRT->Release();
|
||||
if (defDS) defDS->Release();
|
||||
|
||||
D3DCHECK(device->Reset(&d3dpp));
|
||||
device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &defRT);
|
||||
device->GetDepthStencilSurface(&defDS);
|
||||
|
||||
// reinit texture RTs
|
||||
for (int i = 0; i < tmpCount; i++) {
|
||||
Resource &res = tmpList[i];
|
||||
if (res.mesh)
|
||||
res.mesh->init(NULL, res.mesh->iCount, NULL, res.mesh->vCount, 0);
|
||||
else
|
||||
res.texture->init(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
inline mat4::ProjRange getProjRange() {
|
||||
return mat4::PROJ_ZERO_POS;
|
||||
}
|
||||
|
||||
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
|
||||
mat4 m;
|
||||
m.ortho(getProjRange(), l, r, b, t, znear, zfar);
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) {
|
||||
mat4 m;
|
||||
m.perspective(getProjRange(), fov, aspect, znear, zfar, eye);
|
||||
return m;
|
||||
}
|
||||
|
||||
bool beginFrame() {
|
||||
if (defRT == NULL) device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &defRT);
|
||||
if (defDS == NULL) device->GetDepthStencilSurface(&defDS);
|
||||
|
||||
device->BeginScene();
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {
|
||||
device->EndScene();
|
||||
}
|
||||
|
||||
void resetState() {
|
||||
device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
|
||||
device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
}
|
||||
|
||||
int cacheRenderTarget(bool depth, int width, int height) {
|
||||
RenderTargetCache &cache = rtCache[depth];
|
||||
|
||||
for (int i = 0; i < cache.count; i++)
|
||||
if (cache.items[i].width == width && cache.items[i].height == height)
|
||||
return i;
|
||||
|
||||
ASSERT(cache.count < MAX_RENDER_BUFFERS);
|
||||
|
||||
RenderTargetCache::Item &item = cache.items[cache.count];
|
||||
item.width = width;
|
||||
item.height = height;
|
||||
|
||||
if (depth)
|
||||
device->CreateDepthStencilSurface(width, height, D3DFMT_LIN_D16, D3DMULTISAMPLE_NONE, &item.surface);
|
||||
else
|
||||
device->CreateRenderTarget(width, height, D3DFMT_LIN_R5G6B5, D3DMULTISAMPLE_NONE, false, &item.surface);
|
||||
|
||||
return cache.count++;
|
||||
}
|
||||
|
||||
void bindTarget(Texture *target, int face) {
|
||||
if (!target) { // may be a null
|
||||
D3DCHECK(device->SetRenderTarget(defRT, defDS));
|
||||
} else {
|
||||
ASSERT(target->opt & OPT_TARGET);
|
||||
|
||||
LPDIRECT3DSURFACE8 surface;
|
||||
|
||||
bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW;
|
||||
|
||||
if (target->tex2D) {
|
||||
D3DCHECK(target->tex2D->GetSurfaceLevel(0, &surface));
|
||||
} else if (target->texCube) {
|
||||
D3DCHECK(target->texCube->GetCubeMapSurface(D3DCUBEMAP_FACES(D3DCUBEMAP_FACE_POSITIVE_X + face), 0, &surface));
|
||||
}
|
||||
|
||||
int rtIndex = cacheRenderTarget(!depth, target->width, target->height);
|
||||
|
||||
if (depth) {
|
||||
D3DCHECK(device->SetRenderTarget(rtCache[false].items[rtIndex].surface, surface));
|
||||
} else {
|
||||
D3DCHECK(device->SetRenderTarget(surface, rtCache[true].items[rtIndex].surface));
|
||||
}
|
||||
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
Core::active.viewport = short4(0, 0, 0, 0); // forcing viewport reset
|
||||
Core::active.scissor = short4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void discardTarget(bool color, bool depth) {}
|
||||
|
||||
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
|
||||
ASSERT(dst && dst->tex2D);
|
||||
|
||||
LPDIRECT3DSURFACE8 surface;
|
||||
dst->tex2D->GetSurfaceLevel(0, &surface);
|
||||
|
||||
RECT srcRect = { x, y, x + width, y + height },
|
||||
dstRect = { xOffset, yOffset, xOffset + width, yOffset + height };
|
||||
|
||||
//device->StretchRect(defRT, &srcRect, surface, &dstRect, D3DTEXF_POINT); TODO
|
||||
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
void setVSync(bool enable) {
|
||||
d3dpp.FullScreen_PresentationInterval = enable ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
GAPI::resetDevice();
|
||||
}
|
||||
|
||||
void waitVBlank() {}
|
||||
|
||||
void clear(bool color, bool depth) {
|
||||
uint32 flags = (color ? D3DCLEAR_TARGET : 0) | (depth ? (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) : 0);
|
||||
if (flags) {
|
||||
device->Clear(0, NULL, flags, clearColor, 1.0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void setClearColor(const vec4 &color) {
|
||||
clearColor = (int(color.x * 255) << 16) |
|
||||
(int(color.y * 255) << 8 ) |
|
||||
(int(color.z * 255) ) |
|
||||
(int(color.w * 255) << 24);
|
||||
}
|
||||
|
||||
void setViewport(const short4 &v) {
|
||||
D3DVIEWPORT8 viewport;
|
||||
viewport.X = v.x;
|
||||
viewport.Y = v.y;
|
||||
viewport.Width = v.z;
|
||||
viewport.Height = v.w;
|
||||
viewport.MinZ = 0.0f;
|
||||
viewport.MaxZ = 1.0f;
|
||||
|
||||
device->SetViewport(&viewport);
|
||||
}
|
||||
|
||||
void setScissor(const short4 &s) {
|
||||
D3DRECT scissor;
|
||||
scissor.x1 = s.x;
|
||||
scissor.y1 = active.viewport.w - (s.y + s.w);
|
||||
scissor.x2 = s.x + s.z;
|
||||
scissor.y2 = active.viewport.w - s.y;
|
||||
|
||||
device->SetScissors(1, FALSE, &scissor);
|
||||
}
|
||||
|
||||
void setDepthTest(bool enable) {
|
||||
device->SetRenderState(D3DRS_ZENABLE, enable ? D3DZB_TRUE : D3DZB_FALSE);
|
||||
}
|
||||
|
||||
void setDepthWrite(bool enable) {
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, enable ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void setColorWrite(bool r, bool g, bool b, bool a) {
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE,
|
||||
(r ? D3DCOLORWRITEENABLE_RED : 0) |
|
||||
(g ? D3DCOLORWRITEENABLE_GREEN : 0) |
|
||||
(b ? D3DCOLORWRITEENABLE_BLUE : 0) |
|
||||
(a ? D3DCOLORWRITEENABLE_ALPHA : 0));
|
||||
}
|
||||
|
||||
void setAlphaTest(bool enable) {
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAKILL, enable ? D3DTALPHAKILL_ENABLE : D3DTALPHAKILL_DISABLE);
|
||||
}
|
||||
|
||||
void setCullMode(int rsMask) {
|
||||
cullMode = rsMask;
|
||||
switch (rsMask) {
|
||||
case RS_CULL_BACK : device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); break;
|
||||
case RS_CULL_FRONT : device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); break;
|
||||
default : device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void setBlendMode(int rsMask) {
|
||||
blendMode = rsMask;
|
||||
switch (rsMask) {
|
||||
case RS_BLEND_ALPHA :
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
break;
|
||||
case RS_BLEND_ADD :
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
||||
break;
|
||||
case RS_BLEND_MULT :
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
|
||||
break;
|
||||
case RS_BLEND_PREMULT :
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
break;
|
||||
default :
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
return;
|
||||
}
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
}
|
||||
|
||||
void setViewProj(const mat4 &mView, const mat4 &mProj) {
|
||||
device->SetTransform(D3DTS_PROJECTION, (D3DXMATRIX*)&mProj);
|
||||
}
|
||||
|
||||
void updateLights(vec4 *lightPos, vec4 *lightColor, int count) {
|
||||
if (active.shader) {
|
||||
active.shader->setParam(uLightColor, lightColor[0], count);
|
||||
active.shader->setParam(uLightPos, lightPos[0], count);
|
||||
}
|
||||
}
|
||||
|
||||
void setFog(const vec4 ¶ms) {
|
||||
if (params.w > 0.0f) {
|
||||
device->SetRenderState(D3DRS_FOGENABLE, TRUE);
|
||||
|
||||
DWORD fogColor = 0xFF000000
|
||||
| (DWORD(clamp(params.z * 255.0f, 0.0f, 255.0f)) << 0)
|
||||
| (DWORD(clamp(params.y * 255.0f, 0.0f, 255.0f)) << 8)
|
||||
| (DWORD(clamp(params.x * 255.0f, 0.0f, 255.0f)) << 16);
|
||||
device->SetRenderState(D3DRS_FOGCOLOR, fogColor);
|
||||
|
||||
ASSERT(Core::active.shader);
|
||||
Core::active.shader->setParam(uFogParams, params); // color.rgb, factor
|
||||
} else {
|
||||
device->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void DIP(Mesh *mesh, const MeshRange &range) {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, mesh->vCount, range.iStart, range.iCount / 3);
|
||||
}
|
||||
|
||||
vec4 copyPixel(int x, int y) {
|
||||
GAPI::Texture *t = Core::active.target;
|
||||
ASSERT(t && t->tex2D);
|
||||
/*
|
||||
LPDIRECT3DSURFACE8 surface, texSurface;
|
||||
D3DCHECK(t->tex2D->GetSurfaceLevel(0, &texSurface));
|
||||
D3DCHECK(device->CreateOffscreenPlainSurface(t->width, t->height, t->d3dformat, D3DPOOL_SYSTEMMEM, &surface, NULL));
|
||||
D3DCHECK(device->GetRenderTargetData(texSurface, surface));
|
||||
|
||||
RECT r = { x, y, x + 1, y + 1 };
|
||||
D3DLOCKED_RECT rect;
|
||||
surface->LockRect(&rect, &r, D3DLOCK_READONLY);
|
||||
ubyte4 c = *((ubyte4*)rect.pBits);
|
||||
surface->UnlockRect();
|
||||
|
||||
texSurface->Release();
|
||||
surface->Release();
|
||||
|
||||
return vec4(float(c.z), float(c.y), float(c.x), float(c.w)) * (1.0f / 255.0f);
|
||||
*/
|
||||
return vec4(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -35,16 +35,16 @@ struct OptionItem {
|
||||
TYPE_KEY,
|
||||
} type;
|
||||
StringID title;
|
||||
intptr_t offset;
|
||||
int32 offset;
|
||||
uint32 color;
|
||||
uint32 icon;
|
||||
uint8 maxValue;
|
||||
bool bar;
|
||||
|
||||
OptionItem(Type type = TYPE_EMPTY, int title = STR_EMPTY, intptr_t offset = 0, uint32 color = 0xFFFFFFFF, int icon = 0, uint8 maxValue = 0, bool bar = false) : type(type), title(StringID(title)), offset(offset), color(color), icon(icon), maxValue(maxValue), bar(bar) {}
|
||||
OptionItem(Type type = TYPE_EMPTY, int title = STR_EMPTY, int32 offset = 0, uint32 color = 0xFFFFFFFF, int icon = 0, uint8 maxValue = 0, bool bar = false) : type(type), title(StringID(title)), offset(offset), color(color), icon(icon), maxValue(maxValue), bar(bar) {}
|
||||
|
||||
void setValue(uint8 value, Core::Settings *settings) const {
|
||||
*(uint8*)(intptr_t(settings) + offset) = value;
|
||||
*((uint8*)settings + offset) = value;
|
||||
}
|
||||
|
||||
bool checkValue(uint8 value) const {
|
||||
@@ -102,7 +102,7 @@ struct OptionItem {
|
||||
if (active)
|
||||
UI::renderBar(CTEX_OPTION, vec2(x, y - LINE_HEIGHT + 6), vec2(w, LINE_HEIGHT - 6), 1.0f, 0xFFD8377C, 0);
|
||||
|
||||
const uint8 &value = *(uint8*)(intptr_t(settings) + offset);
|
||||
const uint8 &value = *((uint8*)settings + offset);
|
||||
|
||||
switch (type) {
|
||||
case TYPE_TITLE :
|
||||
@@ -164,7 +164,7 @@ static const OptionItem optSound[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(_OS_PSP) || defined(_OS_PSV) || defined(_OS_3DS) || defined(_OS_GCW0) || defined(_OS_CLOVER) || defined(_OS_PSC)
|
||||
#if defined(_OS_PSP) || defined(_OS_PSV) || defined(_OS_3DS) || defined(_OS_GCW0) || defined(_OS_CLOVER) || defined(_OS_PSC) || defined(_OS_XBOX)
|
||||
#define INV_GAMEPAD_ONLY
|
||||
#endif
|
||||
|
||||
@@ -182,7 +182,7 @@ static const OptionItem optSound[] = {
|
||||
#define INV_CTRL_START_OPTION 2
|
||||
#endif
|
||||
|
||||
#if defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_RPI) || defined(_OS_GCW0)
|
||||
#if defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_RPI) || defined(_OS_GCW0) || defined(_OS_XBOX)
|
||||
#define INV_VIBRATION
|
||||
#endif
|
||||
|
||||
@@ -430,7 +430,7 @@ struct Inventory {
|
||||
case TR::Entity::INV_PASSPORT :
|
||||
if (value != 0) return NULL;
|
||||
optCount = optLoadSlots.length;
|
||||
return optLoadSlots;
|
||||
return optLoadSlots.items;
|
||||
case TR::Entity::INV_DETAIL :
|
||||
optCount = COUNT(optDetail);
|
||||
return optDetail;
|
||||
@@ -492,7 +492,7 @@ struct Inventory {
|
||||
|
||||
opt = opt + slot;
|
||||
|
||||
uint8 &value = *(uint8*)(intptr_t(settings) + opt->offset);
|
||||
uint8 &value = *((uint8*)settings + opt->offset);
|
||||
|
||||
switch (key) {
|
||||
case cAction : return (opt->type == OptionItem::TYPE_BUTTON || opt->type == OptionItem::TYPE_KEY) ? opt : NULL;
|
||||
@@ -818,7 +818,7 @@ struct Inventory {
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
for (int pos = 0; pos < itemsCount; pos++)
|
||||
for (; pos < itemsCount; pos++)
|
||||
if (items[pos]->type > type)
|
||||
break;
|
||||
|
||||
@@ -1407,7 +1407,7 @@ struct Inventory {
|
||||
|
||||
for (int i = 0; i < COUNT(background); i++) {
|
||||
if (!background[i]) {
|
||||
background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGBA, OPT_TARGET);
|
||||
background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGB16, OPT_TARGET);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1748,7 +1748,7 @@ struct Inventory {
|
||||
aspectSrc = ax = ay = 1.0f;
|
||||
}
|
||||
|
||||
float aspectDst = float(Core::width) / float(Core::height);
|
||||
float aspectDst = float(Core::width) / float(Core::height) * Core::aspectFix;
|
||||
float aspectImg = aspectSrc / aspectDst;
|
||||
|
||||
#ifdef FFP
|
||||
@@ -2090,7 +2090,7 @@ struct Inventory {
|
||||
const char *bSelect = STR[STR_KEY_FIRST + ikEnter];
|
||||
const char *bBack = STR[STR_KEY_FIRST + Core::settings.controls[playerIndex].keys[cInventory].key];
|
||||
|
||||
#if defined(_OS_SWITCH) || defined(_OS_3DS) || defined(_OS_GCW0)
|
||||
#if defined(_OS_SWITCH) || defined(_OS_3DS) || defined(_OS_GCW0) || defined(_OS_XBOX)
|
||||
bSelect = "A";
|
||||
bBack = "B";
|
||||
#endif
|
||||
|
@@ -252,6 +252,12 @@ enum StringID {
|
||||
, STR_MAX
|
||||
};
|
||||
|
||||
#ifdef _XBOX // TODO: illegal escape sequence
|
||||
#define STR_RUSSIAN "Russian"
|
||||
#else
|
||||
#define STR_RUSSIAN "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{<7B>"
|
||||
#endif
|
||||
|
||||
#define STR_LANGUAGES \
|
||||
"English" \
|
||||
, "Fran|cais" \
|
||||
@@ -260,7 +266,7 @@ enum StringID {
|
||||
, "Italiano" \
|
||||
, "Polski" \
|
||||
, "Portugu(es" \
|
||||
, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>{<7B>" \
|
||||
, STR_RUSSIAN \
|
||||
, "\x11\x02\x70\x01\x97\x01\xD6\xFF\xFF" \
|
||||
, "\x11\x01\x22\x01\x0F\x01\x0F\x01\x0E\x01\x06\x01\x04\x01\x0C\x01\x0B\xFF\xFF" \
|
||||
, "Suomi" \
|
||||
|
29
src/level.h
29
src/level.h
@@ -551,22 +551,24 @@ struct Level : IGame {
|
||||
#endif
|
||||
|
||||
vec4 material;
|
||||
|
||||
if (Core::pass == Core::passAmbient) {
|
||||
if (room.flags.water) {
|
||||
Core::fogParams = underwaterFogParams;
|
||||
material = vec4(underwaterColor, 1.0f);
|
||||
} else {
|
||||
Core::fogParams = levelFogParams;
|
||||
material = vec4(1.0f);
|
||||
}
|
||||
} else {
|
||||
Core::fogParams = levelFogParams;
|
||||
material = vec4(diffuse, ambient, specular, alpha);
|
||||
}
|
||||
|
||||
setShader(Core::pass, type, (Core::pass == Core::passAmbient) ? false : room.flags.water, alphaTest);
|
||||
|
||||
if (room.flags.water) {
|
||||
Core::setFog(underwaterFogParams);
|
||||
} else {
|
||||
Core::setFog(levelFogParams);
|
||||
}
|
||||
|
||||
#ifdef _GAPI_SW
|
||||
GAPI::setPalette(room.flags.water ? GAPI::swPaletteWater : GAPI::swPaletteColor);
|
||||
GAPI::setShading(true);
|
||||
@@ -2384,6 +2386,7 @@ struct Level : IGame {
|
||||
renderEntitiesTransp(transp);
|
||||
|
||||
#ifndef FFP
|
||||
Core::setFog(FOG_NONE);
|
||||
Core::whiteTex->bind(sDiffuse);
|
||||
Core::setBlendMode(bmMult);
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
@@ -2529,11 +2532,17 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void renderAdditive(RoomDesc *roomsList, int roomsCount) {
|
||||
vec4 oldFog = Core::fogParams;
|
||||
Core::fogParams = FOG_BLACK; // don't apply fog for additive
|
||||
// don't apply fog for additive geometry
|
||||
vec4 oldLevelFogParams = levelFogParams;
|
||||
vec4 oldUnderwaterFogParams = underwaterFogParams;
|
||||
levelFogParams = FOG_NONE;
|
||||
underwaterFogParams = FOG_NONE;
|
||||
|
||||
renderRooms(roomsList, roomsCount, 2);
|
||||
renderEntities(2);
|
||||
Core::fogParams = oldFog;
|
||||
|
||||
levelFogParams = oldLevelFogParams;
|
||||
underwaterFogParams = oldUnderwaterFogParams;
|
||||
}
|
||||
|
||||
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {
|
||||
@@ -2612,6 +2621,8 @@ struct Level : IGame {
|
||||
if (camera->isUnderwater())
|
||||
renderAdditive(roomsList, roomsCount);
|
||||
|
||||
Core::setFog(FOG_NONE);
|
||||
|
||||
Core::setBlendMode(bmNone);
|
||||
if (water && waterCache && waterCache->visible) {
|
||||
Core::Pass pass = Core::pass;
|
||||
@@ -2631,6 +2642,8 @@ struct Level : IGame {
|
||||
if (!camera->isUnderwater())
|
||||
renderAdditive(roomsList, roomsCount);
|
||||
|
||||
Core::setFog(FOG_NONE);
|
||||
|
||||
Core::setBlendMode(bmNone);
|
||||
|
||||
Core::Pass pass = Core::pass;
|
||||
@@ -3065,7 +3078,7 @@ struct Level : IGame {
|
||||
int vW = Core::width;
|
||||
int vH = Core::height;
|
||||
|
||||
float aspect = float(vW) / float(vH);
|
||||
float aspect = float(vW) / float(vH) * Core::aspectFix;
|
||||
|
||||
if (Core::defaultTarget) {
|
||||
vX = 0;
|
||||
|
@@ -1296,7 +1296,7 @@ static void compute_window(int n, float *window)
|
||||
rotate(c, s, s, c);
|
||||
|
||||
for (i=0; i < n2; ++i) {
|
||||
window[i] = sinf((float)(0.5 * M_PI * (y * y)));
|
||||
window[i] = (float)sin(0.5 * M_PI * (y * y));
|
||||
rotate(x, y, s, c);
|
||||
}
|
||||
}
|
||||
|
12
src/mesh.h
12
src/mesh.h
@@ -302,12 +302,12 @@ struct MeshBuilder {
|
||||
};
|
||||
|
||||
const short4 boxCoords[] = {
|
||||
{-1, -1, 1, 0}, { 1, -1, 1, 0}, { 1, 1, 1, 0}, {-1, 1, 1, 0},
|
||||
{ 1, 1, 1, 0}, { 1, 1, -1, 0}, { 1, -1, -1, 0}, { 1, -1, 1, 0},
|
||||
{-1, -1, -1, 0}, { 1, -1, -1, 0}, { 1, 1, -1, 0}, {-1, 1, -1, 0},
|
||||
{-1, -1, -1, 0}, {-1, -1, 1, 0}, {-1, 1, 1, 0}, {-1, 1, -1, 0},
|
||||
{ 1, 1, 1, 0}, {-1, 1, 1, 0}, {-1, 1, -1, 0}, { 1, 1, -1, 0},
|
||||
{-1, -1, -1, 0}, { 1, -1, -1, 0}, { 1, -1, 1, 0}, {-1, -1, 1, 0},
|
||||
short4(-1, -1, 1, 0), short4( 1, -1, 1, 0), short4( 1, 1, 1, 0), short4(-1, 1, 1, 0),
|
||||
short4( 1, 1, 1, 0), short4( 1, 1, -1, 0), short4( 1, -1, -1, 0), short4( 1, -1, 1, 0),
|
||||
short4(-1, -1, -1, 0), short4( 1, -1, -1, 0), short4( 1, 1, -1, 0), short4(-1, 1, -1, 0),
|
||||
short4(-1, -1, -1, 0), short4(-1, -1, 1, 0), short4(-1, 1, 1, 0), short4(-1, 1, -1, 0),
|
||||
short4( 1, 1, 1, 0), short4(-1, 1, 1, 0), short4(-1, 1, -1, 0), short4( 1, 1, -1, 0),
|
||||
short4(-1, -1, -1, 0), short4( 1, -1, -1, 0), short4( 1, -1, 1, 0), short4(-1, -1, 1, 0),
|
||||
};
|
||||
|
||||
iCount += COUNT(boxIndices);
|
||||
|
30
src/platform/xbox/OpenLara.sln
Normal file
30
src/platform/xbox/OpenLara.sln
Normal file
@@ -0,0 +1,30 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenLara", "OpenLara.vcproj", "{9DC80A4E-C379-4FB3-994E-62C358071007}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Profile = Profile
|
||||
Profile_FastCap = Profile_FastCap
|
||||
Release = Release
|
||||
Release_LTCG = Release_LTCG
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Debug.ActiveCfg = Debug|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Debug.Build.0 = Debug|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Profile.ActiveCfg = Profile|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Profile.Build.0 = Profile|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Release.ActiveCfg = Release|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Release.Build.0 = Release|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox
|
||||
{9DC80A4E-C379-4FB3-994E-62C358071007}.Release_LTCG.Build.0 = Release_LTCG|Xbox
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
473
src/platform/xbox/OpenLara.vcproj
Normal file
473
src/platform/xbox/OpenLara.vcproj
Normal file
@@ -0,0 +1,473 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="OpenLara"
|
||||
ProjectGUID="{9DC80A4E-C379-4FB3-994E-62C358071007}"
|
||||
Keyword="XboxProj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Xbox"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Xbox"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\..\libs;..\..\;"
|
||||
PreprocessorDefinitions="_XBOX"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xactengd.lib xsndtrkd.lib xvoiced.lib xonlined.lib xboxkrnl.lib xbdm.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeForWindows98="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="XboxDeploymentTool"
|
||||
RemotePath="xe:\$(SolutionName)\default.xbe"/>
|
||||
<Tool
|
||||
Name="XboxImageTool"
|
||||
FileName="$(TargetDir)default.xbe"
|
||||
StackSize="65536"
|
||||
IncludeDebugInfo="TRUE"
|
||||
NoLibWarn="TRUE"
|
||||
TitleID="0x14021968"
|
||||
TitleName="OpenLara"
|
||||
TitleImage="titleimage.xbx"
|
||||
XBEVersion="4096"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Xbox"
|
||||
OutputDirectory="Profile"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\..\libs;..\..\;"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;PROFILE"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="xapilib.lib d3d8i.lib d3dx8.lib xgraphics.lib dsound.lib dmusici.lib xactengi.lib xsndtrk.lib xvoice.lib xonlines.lib xboxkrnl.lib xbdm.lib xperf.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
OptimizeForWindows98="1"
|
||||
SetChecksum="TRUE"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="XboxDeploymentTool"
|
||||
RemotePath="xe:\$(SolutionName)\default.xbe"/>
|
||||
<Tool
|
||||
Name="XboxImageTool"
|
||||
FileName="$(TargetDir)default.xbe"
|
||||
StackSize="65536"
|
||||
IncludeDebugInfo="TRUE"
|
||||
NoLibWarn="TRUE"
|
||||
TitleName="OpenLara"
|
||||
XBEVersion="4096"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile_FastCap|Xbox"
|
||||
OutputDirectory="Profile_FastCap"
|
||||
IntermediateDirectory="Profile_FastCap"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\..\libs;..\..\;"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;PROFILE;FASTCAP"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"
|
||||
FastCAP="TRUE"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="xapilib.lib d3d8i.lib d3dx8.lib xgraphics.lib dsound.lib dmusici.lib xactengi.lib xsndtrk.lib xvoice.lib xonlines.lib xboxkrnl.lib xbdm.lib xperf.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
OptimizeForWindows98="1"
|
||||
SetChecksum="TRUE"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="XboxDeploymentTool"
|
||||
RemotePath="xe:\$(SolutionName)\default.xbe"/>
|
||||
<Tool
|
||||
Name="XboxImageTool"
|
||||
FileName="$(TargetDir)default.xbe"
|
||||
StackSize="65536"
|
||||
IncludeDebugInfo="TRUE"
|
||||
NoLibWarn="TRUE"
|
||||
TitleName="OpenLara"
|
||||
XBEVersion="4096"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Xbox"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\..\libs;..\..\;"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="xapilib.lib d3d8.lib d3dx8.lib xgraphics.lib dsound.lib dmusic.lib xacteng.lib xsndtrk.lib xvoice.lib xonlines.lib xboxkrnl.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
OptimizeForWindows98="1"
|
||||
SetChecksum="TRUE"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="XboxDeploymentTool"
|
||||
RemotePath="xe:\$(SolutionName)\default.xbe"/>
|
||||
<Tool
|
||||
Name="XboxImageTool"
|
||||
FileName="$(TargetDir)default.xbe"
|
||||
StackSize="65536"
|
||||
TitleName="OpenLara"
|
||||
XBEVersion="4096"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release_LTCG|Xbox"
|
||||
OutputDirectory="Release_LTCG"
|
||||
IntermediateDirectory="Release_LTCG"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\..\libs;..\..\;"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;LTCG"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="xapilib.lib d3d8ltcg.lib d3dx8.lib xgraphicsltcg.lib dsound.lib dmusicltcg.lib xactengltcg.lib xsndtrk.lib xvoice.lib xonlines.lib xboxkrnl.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
OptimizeForWindows98="1"
|
||||
SetChecksum="TRUE"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="XboxDeploymentTool"
|
||||
RemotePath="xe:\$(SolutionName)\default.xbe"/>
|
||||
<Tool
|
||||
Name="XboxImageTool"
|
||||
FileName="$(TargetDir)default.xbe"
|
||||
StackSize="65536"
|
||||
TitleName="OpenLara"
|
||||
XBEVersion="4096"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="lang"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\lang\cn.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\cz.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\de.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\en.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\es.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\fi.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\fr.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\glyph_cn.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\glyph_gr.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\glyph_ja.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\glyph_ru.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\gr.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\it.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\ja.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\pl.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\pt.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang\ru.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="gapi"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\gapi\d3d8.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="libs"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="tinf"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\libs\tinf\tinf.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\libs\tinf\tinflate.c">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="stb_vorbis"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\libs\stb_vorbis\stb_vorbis.c">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\animation.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\cache.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\camera.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\character.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\collision.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\controller.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\core.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\debug.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\enemy.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\extension.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\format.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\frustum.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\game.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gameflow.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gltf.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\input.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\inventory.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\json.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lang.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lara.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\level.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\mesh.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\napi_dummy.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\napi_socket.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\network.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\objects.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\savegame.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\shader.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sound.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sprite.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\texture.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\ui.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\utils.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\video.h">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
336
src/platform/xbox/main.cpp
Normal file
336
src/platform/xbox/main.cpp
Normal file
@@ -0,0 +1,336 @@
|
||||
#include "game.h"
|
||||
|
||||
LPDIRECT3D8 D3D;
|
||||
LPDIRECT3DDEVICE8 device;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
|
||||
// multi-threading
|
||||
void* osMutexInit() {
|
||||
CRITICAL_SECTION *CS = new CRITICAL_SECTION();
|
||||
InitializeCriticalSection(CS);
|
||||
return CS;
|
||||
}
|
||||
|
||||
void osMutexFree(void *obj) {
|
||||
DeleteCriticalSection((CRITICAL_SECTION*)obj);
|
||||
delete (CRITICAL_SECTION*)obj;
|
||||
}
|
||||
|
||||
void osMutexLock(void *obj) {
|
||||
EnterCriticalSection((CRITICAL_SECTION*)obj);
|
||||
}
|
||||
|
||||
void osMutexUnlock(void *obj) {
|
||||
LeaveCriticalSection((CRITICAL_SECTION*)obj);
|
||||
}
|
||||
|
||||
// timing
|
||||
LARGE_INTEGER timerFreq;
|
||||
LARGE_INTEGER timerStart;
|
||||
|
||||
int osGetTimeMS() {
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
return int32((time.QuadPart - timerStart.QuadPart) * 1000L / timerFreq.QuadPart);
|
||||
}
|
||||
|
||||
|
||||
// input
|
||||
struct JoyDevice {
|
||||
HANDLE handle;
|
||||
int time;
|
||||
float vL, vR;
|
||||
float oL, oR;
|
||||
XINPUT_FEEDBACK feedback;
|
||||
} joyDevice[INPUT_JOY_COUNT];
|
||||
|
||||
#define JOY_MIN_UPDATE_FX_TIME 50
|
||||
#define JOY_TRIGGER_THRESHOLD 30
|
||||
|
||||
void osJoyVibrate(int index, float L, float R) {
|
||||
joyDevice[index].vL = L;
|
||||
joyDevice[index].vR = R;
|
||||
}
|
||||
|
||||
void joyInit() {
|
||||
XInitDevices(0, NULL);
|
||||
}
|
||||
|
||||
float joyTrigger(int32 value) {
|
||||
return clamp(float(value - JOY_TRIGGER_THRESHOLD) / (255 - JOY_TRIGGER_THRESHOLD), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void joyUpdate() {
|
||||
static XINPUT_POLLING_PARAMETERS params = { TRUE, TRUE, 0, 8, 8, 0, };
|
||||
|
||||
DWORD dwInsertions, dwRemovals;
|
||||
XGetDeviceChanges(XDEVICE_TYPE_GAMEPAD, &dwInsertions, &dwRemovals);
|
||||
|
||||
for (DWORD i = 0; i < XGetPortCount(); i++) {
|
||||
JoyDevice &joy = joyDevice[i];
|
||||
|
||||
if (dwInsertions & (1 << i)) {
|
||||
memset(&joy, 0, sizeof(joy));
|
||||
joy.handle = XInputOpen(XDEVICE_TYPE_GAMEPAD, i, XDEVICE_NO_SLOT, ¶ms);
|
||||
LOG("joy insert: %d\n", i);
|
||||
}
|
||||
|
||||
if (dwRemovals & (1 << i)) {
|
||||
XInputClose(joy.handle);
|
||||
joy.handle = NULL;
|
||||
LOG("joy remove: %d\n", i);
|
||||
}
|
||||
|
||||
if (joy.handle) {
|
||||
XINPUT_STATE state;
|
||||
XInputGetState(joy.handle, &state);
|
||||
|
||||
Input::setJoyPos(i, jkL, vec2(state.Gamepad.sThumbLX + 0.5f, -(state.Gamepad.sThumbLY + 0.5f)) / 32767.5f);
|
||||
Input::setJoyPos(i, jkR, vec2(state.Gamepad.sThumbRX + 0.5f, -(state.Gamepad.sThumbRY + 0.5f)) / 32767.5f);
|
||||
Input::setJoyPos(i, jkLT, vec2(state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE], 0.0f));
|
||||
Input::setJoyPos(i, jkRT, vec2(state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK], 0.0f));
|
||||
|
||||
Input::setJoyDown(i, jkA, state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_A] > 0);
|
||||
Input::setJoyDown(i, jkB, state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_B] > 0);
|
||||
Input::setJoyDown(i, jkX, state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_X] > 0);
|
||||
Input::setJoyDown(i, jkY, state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] > 0);
|
||||
Input::setJoyDown(i, jkLB, joyTrigger(state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) > 0);
|
||||
Input::setJoyDown(i, jkRB, joyTrigger(state.Gamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) > 0);
|
||||
Input::setJoyDown(i, jkUp, (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) > 0);
|
||||
Input::setJoyDown(i, jkDown, (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) > 0);
|
||||
Input::setJoyDown(i, jkLeft, (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) > 0);
|
||||
Input::setJoyDown(i, jkRight, (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) > 0);
|
||||
Input::setJoyDown(i, jkStart, (state.Gamepad.wButtons & XINPUT_GAMEPAD_START) > 0);
|
||||
Input::setJoyDown(i, jkSelect, (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) > 0);
|
||||
Input::setJoyDown(i, jkL, (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) > 0);
|
||||
Input::setJoyDown(i, jkR, (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) > 0);
|
||||
|
||||
if ((joy.vL != joy.oL || joy.vR != joy.oR) && Core::getTime() >= joy.time) {
|
||||
if (joy.feedback.Header.dwStatus != ERROR_IO_PENDING) {
|
||||
joy.feedback.Rumble.wLeftMotorSpeed = WORD(joy.vL * 65535.0f);
|
||||
joy.feedback.Rumble.wRightMotorSpeed = WORD(joy.vR * 65535.0f);
|
||||
joy.oL = joy.vL;
|
||||
joy.oR = joy.vR;
|
||||
joy.time = Core::getTime() + JOY_MIN_UPDATE_FX_TIME;
|
||||
XInputSetState(joy.handle, &joy.feedback);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sound
|
||||
#define SND_PACKETS 2
|
||||
#define SND_SAMPLES 2352
|
||||
#define SND_SIZE (SND_SAMPLES * sizeof(int16) * 2)
|
||||
|
||||
LPDIRECTSOUND DSound;
|
||||
LPDIRECTSOUNDSTREAM sndStream;
|
||||
uint8* sndBuffer;
|
||||
|
||||
void CALLBACK sndFill(VOID* pStreamContext, VOID* pPacketContext, DWORD dwStatus) {
|
||||
if (Core::isQuit) return;
|
||||
|
||||
if (dwStatus != XMEDIAPACKET_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
int32 index = (int32)pPacketContext;
|
||||
|
||||
XMEDIAPACKET packet = {0};
|
||||
packet.dwMaxSize = SND_SIZE;
|
||||
packet.pvBuffer = sndBuffer + index * SND_SIZE;
|
||||
packet.pContext = pPacketContext;
|
||||
|
||||
Sound::fill((Sound::Frame*)packet.pvBuffer, SND_SIZE / 4);
|
||||
|
||||
sndStream->Process(&packet, NULL);
|
||||
}
|
||||
|
||||
void sndInit() {
|
||||
if (FAILED(DirectSoundCreate(NULL, &DSound, NULL)))
|
||||
return;
|
||||
|
||||
WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 2, 44100, 44100 * 4, 4, 16, sizeof(waveFmt) };
|
||||
|
||||
DSSTREAMDESC dssd = {0};
|
||||
dssd.dwMaxAttachedPackets = SND_PACKETS;
|
||||
dssd.lpwfxFormat = &waveFmt;
|
||||
dssd.lpfnCallback = sndFill;
|
||||
|
||||
sndBuffer = (uint8*)XPhysicalAlloc(SND_SIZE * SND_PACKETS, MAXULONG_PTR, 0, PAGE_READWRITE | PAGE_NOCACHE);
|
||||
if (!sndBuffer)
|
||||
return;
|
||||
memset(sndBuffer, 0, SND_SIZE * SND_PACKETS);
|
||||
|
||||
if (FAILED(DirectSoundCreateStream(&dssd, &sndStream)))
|
||||
return;
|
||||
|
||||
XMEDIAPACKET packet = {0};
|
||||
packet.dwMaxSize = SND_SIZE;
|
||||
for (int i = 0; i < SND_PACKETS; i++) {
|
||||
packet.pvBuffer = sndBuffer + i * SND_SIZE;
|
||||
packet.pContext = (VOID*)i;
|
||||
sndStream->Process(&packet, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void sndFree() {
|
||||
if (sndStream) {
|
||||
sndStream->Pause(DSSTREAMPAUSE_PAUSE);
|
||||
sndStream->Discontinuity();
|
||||
sndStream->Flush();
|
||||
sndStream->Release();
|
||||
}
|
||||
if (sndBuffer) {
|
||||
XPhysicalFree(sndBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void sndUpdate() {
|
||||
DirectSoundDoWork();
|
||||
}
|
||||
|
||||
|
||||
// context
|
||||
struct {
|
||||
int width;
|
||||
int height;
|
||||
bool prog;
|
||||
bool wide;
|
||||
|
||||
bool support(DWORD videoFlags) {
|
||||
if (wide && !(videoFlags & XC_VIDEO_FLAGS_WIDESCREEN))
|
||||
return false;
|
||||
if ((height == 480) && wide && !(videoFlags & XC_VIDEO_FLAGS_WIDESCREEN))
|
||||
return false;
|
||||
if ((height == 480) && prog && !(videoFlags & XC_VIDEO_FLAGS_HDTV_480p))
|
||||
return false;
|
||||
if ((height == 720) && !(videoFlags & XC_VIDEO_FLAGS_HDTV_720p))
|
||||
return false;
|
||||
if ((height == 1080) && !(videoFlags & XC_VIDEO_FLAGS_HDTV_1080i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
} displayModes[] = {
|
||||
{ 1920, 1080, false, true }, // 1920x1080 interlaced 16x9
|
||||
{ 1280, 720, true, true }, // 1280x720 progressive 16x9
|
||||
{ 720, 480, true, true }, // 720x480 progressive 16x9
|
||||
{ 720, 480, false, true }, // 720x480 interlaced 16x9
|
||||
{ 640, 480, true, true }, // 640x480 progressive 16x9
|
||||
{ 640, 480, false, true }, // 640x480 interlaced 16x9
|
||||
{ 720, 480, true, false }, // 720x480 progressive 4x3
|
||||
{ 720, 480, false, false }, // 720x480 interlaced 4x3
|
||||
{ 640, 480, true, false }, // 640x480 progressive 4x3
|
||||
{ 640, 480, false, false }, // 640x480 interlaced 4x3
|
||||
};
|
||||
|
||||
HRESULT ContextCreate() {
|
||||
D3D = Direct3DCreate8(D3D_SDK_VERSION);
|
||||
|
||||
if (!D3D) return E_FAIL;
|
||||
|
||||
memset(&d3dpp, 0, sizeof(d3dpp));
|
||||
d3dpp.BackBufferWidth = 640;
|
||||
d3dpp.BackBufferHeight = 480;
|
||||
|
||||
DWORD videoFlags = XGetVideoFlags();
|
||||
|
||||
for (int i = 0; i < COUNT(displayModes); i++) {
|
||||
if (displayModes[i].support(videoFlags)) {
|
||||
d3dpp.BackBufferWidth = displayModes[i].width;
|
||||
d3dpp.BackBufferHeight = displayModes[i].height;
|
||||
if (displayModes[i].wide) {
|
||||
d3dpp.Flags |= D3DPRESENTFLAG_WIDESCREEN;
|
||||
}
|
||||
if (displayModes[i].prog) {
|
||||
d3dpp.Flags |= D3DPRESENTFLAG_PROGRESSIVE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float f = float(d3dpp.BackBufferWidth) / float(d3dpp.BackBufferHeight);
|
||||
if (d3dpp.Flags & D3DPRESENTFLAG_WIDESCREEN) {
|
||||
Core::aspectFix = (16.0f / 9.0f) / f;
|
||||
} else {
|
||||
Core::aspectFix = (4.0f / 3.0f) / f;
|
||||
}
|
||||
|
||||
d3dpp.BackBufferFormat = D3DFMT_LIN_X8R8G8B8;
|
||||
d3dpp.BackBufferCount = 1;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE_OR_IMMEDIATE;
|
||||
|
||||
if (FAILED(D3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device)))
|
||||
return E_FAIL;
|
||||
|
||||
Core::width = d3dpp.BackBufferWidth;
|
||||
Core::height = d3dpp.BackBufferHeight;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void ContextSwap() {
|
||||
device->Present(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
int checkLanguage() {
|
||||
int str = STR_LANG_EN;
|
||||
switch (XGetLanguage()) {
|
||||
case XC_LANGUAGE_ENGLISH : str = STR_LANG_EN; break;
|
||||
case XC_LANGUAGE_FRENCH : str = STR_LANG_FR; break;
|
||||
case XC_LANGUAGE_GERMAN : str = STR_LANG_DE; break;
|
||||
case XC_LANGUAGE_SPANISH : str = STR_LANG_ES; break;
|
||||
case XC_LANGUAGE_ITALIAN : str = STR_LANG_IT; break;
|
||||
case XC_LANGUAGE_PORTUGUESE : str = STR_LANG_PT; break;
|
||||
case XC_LANGUAGE_JAPANESE : str = STR_LANG_JA; break;
|
||||
case XC_LANGUAGE_TCHINESE : str = STR_LANG_CN; break;
|
||||
}
|
||||
return str - STR_LANG_EN;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
strcpy(contentDir, "D:\\");
|
||||
|
||||
saveDir[0] = cacheDir[0] = 0;
|
||||
if (XCreateSaveGame("U:\\", L"OpenLara", OPEN_ALWAYS, 0, saveDir, 256) == ERROR_SUCCESS) {
|
||||
strcpy(cacheDir, saveDir);
|
||||
}
|
||||
|
||||
if (FAILED(ContextCreate()))
|
||||
return;
|
||||
|
||||
QueryPerformanceFrequency(&timerFreq);
|
||||
QueryPerformanceCounter(&timerStart);
|
||||
|
||||
Sound::channelsCount = 0;
|
||||
|
||||
joyInit();
|
||||
sndInit();
|
||||
|
||||
Core::defLang = checkLanguage();
|
||||
|
||||
Game::init("PSXDATA\\LEVEL1.PSX"); // (char*)NULL);
|
||||
|
||||
while (!Core::isQuit) {
|
||||
joyUpdate();
|
||||
sndUpdate();
|
||||
|
||||
if (Game::update()) {
|
||||
Game::render();
|
||||
ContextSwap();
|
||||
}
|
||||
};
|
||||
|
||||
sndFree();
|
||||
Game::deinit();
|
||||
|
||||
LD_LAUNCH_DASHBOARD LaunchData = { XLD_LAUNCH_DASHBOARD_MAIN_MENU };
|
||||
XLaunchNewImage(NULL, (LAUNCH_DATA*)&LaunchData);
|
||||
}
|
BIN
src/platform/xbox/titleimage.xbx
Normal file
BIN
src/platform/xbox/titleimage.xbx
Normal file
Binary file not shown.
@@ -28,7 +28,6 @@ struct Shader : GAPI::Shader {
|
||||
setParam(uLightProj, Core::mLightProj);
|
||||
setParam(uViewPos, Core::viewPos);
|
||||
setParam(uParam, Core::params);
|
||||
setParam(uFogParams, Core::fogParams);
|
||||
}
|
||||
};
|
||||
|
||||
|
72
src/shaders/ambient_room.asm
Normal file
72
src/shaders/ambient_room.asm
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define lv1 r1
|
||||
#define lv2 r2
|
||||
#define lv3 r3
|
||||
#define normal r4
|
||||
#define att r5
|
||||
#define light r6
|
||||
#define pos r7
|
||||
|
||||
; pos = mulQuatPos(uBasis[0], aCoord)
|
||||
mulQuatPos(pos, aCoord, 0)
|
||||
|
||||
; vFog = length((uViewPos - pos) * uFogParams.w)
|
||||
applyFog(vFog, pos)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; lighting
|
||||
; lv[1..3] = (uLightPos[1..3].xyz - pos) * uLightColor[1..3].w;
|
||||
add lv1.xyz, c[uLightPos + 1], -pos
|
||||
add lv2.xyz, c[uLightPos + 2], -pos
|
||||
add lv3.xyz, c[uLightPos + 3], -pos
|
||||
mul lv1.xyz, c[uLightColor + 1].w, lv1
|
||||
mul lv2.xyz, c[uLightColor + 2].w, lv2
|
||||
mul lv3.xyz, c[uLightColor + 3].w, lv3
|
||||
|
||||
; att[1..3] = dot(lv[1..3], lv[1..3])
|
||||
mov att.x, ONE
|
||||
dp3 att.y, lv1, lv1
|
||||
dp3 att.z, lv2, lv2
|
||||
dp3 att.w, lv3, lv3
|
||||
|
||||
; att = max(0, 1 - att) / sqrt(att)
|
||||
rsq tmp.y, att.y
|
||||
rsq tmp.z, att.z
|
||||
rsq tmp.w, att.w
|
||||
|
||||
add att, ONE, -att
|
||||
max att, ZERO, att
|
||||
mul att, tmp, att
|
||||
|
||||
; light = max(0, dot(aNormal, lv[1..3]))
|
||||
mov light.x, ZERO
|
||||
dp3 light.y, lv1, aNormal
|
||||
dp3 light.z, lv2, aNormal
|
||||
dp3 light.w, lv3, aNormal
|
||||
|
||||
; light = max(0, light) * att
|
||||
max light, ZERO, light
|
||||
mul light, light, att
|
||||
|
||||
; vColor = (aLight + light[1..3] * uLightColor[1..3]) * aColor * 2
|
||||
mov pos, aColor
|
||||
mov tmp, aLight
|
||||
mad tmp.xyz, light.y, c[uLightColor + 1], tmp
|
||||
mad tmp.xyz, light.z, c[uLightColor + 2], tmp
|
||||
mad tmp.xyz, light.w, c[uLightColor + 3], tmp
|
||||
mul tmp, pos, tmp
|
||||
applyUnderwater(tmp)
|
||||
add vColor, tmp, tmp
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
10
src/shaders/ambient_sprite.asm
Normal file
10
src/shaders/ambient_sprite.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
m4x4 oPos, aCoord, c[uViewProj]
|
||||
mov oD0, aLight
|
||||
mov oT0, aTexCoord
|
||||
#else
|
||||
tex t0
|
||||
mov r0, t0
|
||||
#endif
|
73
src/shaders/common.asm
Normal file
73
src/shaders/common.asm
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifdef VERTEX
|
||||
xvs.1.1
|
||||
|
||||
#define vPosition oPos
|
||||
#define vColor oD0
|
||||
#define vTexCoord oT0
|
||||
#define vFog oFog
|
||||
#else
|
||||
ps.1.0
|
||||
|
||||
#define vColor v0
|
||||
#endif
|
||||
|
||||
; attributes
|
||||
#define aCoord v0
|
||||
#define aNormal v1
|
||||
#define aTexCoord v2
|
||||
#define aColor v3
|
||||
#define aLight v4
|
||||
|
||||
; constants
|
||||
#define uParam 0
|
||||
#define uTexParam 1
|
||||
#define uViewProj 2
|
||||
#define uBasis 6
|
||||
#define uLightProj 70
|
||||
#define uMaterial 74
|
||||
#define uAmbient 75
|
||||
#define uFogParams 81
|
||||
#define uViewPos 82
|
||||
#define uLightPos 83
|
||||
#define uLightColor 87
|
||||
#define uRoomSize 91
|
||||
#define uPosScale 92
|
||||
|
||||
#define ZERO c94.xxxx
|
||||
#define HALF c94.yyyy
|
||||
#define ONE c94.zzzz
|
||||
#define TWO c94.wwww
|
||||
#define UW_COLOR c95.xyz
|
||||
#define MAX_SHORT c95.wwww
|
||||
|
||||
#define tmp r8
|
||||
|
||||
#define mulMat(dst, src, matrix) \
|
||||
mul tmp, c[matrix + 0], src.x \
|
||||
mad tmp, src.y, c[matrix + 1], tmp \
|
||||
mad tmp, src.z, c[matrix + 2], tmp \
|
||||
mad dst, src.w, c[matrix + 3], tmp
|
||||
|
||||
#define mulQuatPos(dst, src, joint) \
|
||||
mul dst.xyz, c[uBasis + joint], src.zxyw \
|
||||
mad dst.xyz, src, c[uBasis + joint].zxyw, -dst \
|
||||
mad dst.xyz, src.yzxw, c[uBasis + joint].w, dst \
|
||||
mul tmp.xyz, c[uBasis + joint].zxyw, dst \
|
||||
mad dst.xyz, dst.yzxw, c[uBasis + joint].yzxw, -tmp \
|
||||
mad dst.xyz, dst, TWO, src \
|
||||
add dst.xyz, c[uBasis + joint + 1], dst \
|
||||
mov dst.w, c[uBasis + joint + 1].w
|
||||
|
||||
#define applyFog(dst, src) \
|
||||
add tmp.xyz, c[uViewPos].xyz, -src.xyz \
|
||||
mul tmp.xyz, tmp.xyz, c[uFogParams].www \
|
||||
dp3 tmp.x, tmp.xyz, tmp.xyz \
|
||||
rsq tmp.x, tmp.x \
|
||||
rcp dst.x, tmp.x
|
||||
|
||||
#ifdef UNDERWATER
|
||||
#define applyUnderwater(dst) \
|
||||
mul dst.xyz, dst.xyz, UW_COLOR
|
||||
#else
|
||||
#define applyUnderwater(dst)
|
||||
#endif
|
44
src/shaders/compile_d3d8.bat
Normal file
44
src/shaders/compile_d3d8.bat
Normal file
@@ -0,0 +1,44 @@
|
||||
@echo off
|
||||
rd /S /Q d3d8
|
||||
mkdir d3d8
|
||||
|
||||
call :compile_u compose_sprite
|
||||
call :compile_u compose_room
|
||||
call :compile_u compose_entity
|
||||
call :compile compose_mirror
|
||||
call :compile compose_flash
|
||||
|
||||
call :compile shadow_entity
|
||||
call :compile ambient_room
|
||||
call :compile ambient_sprite
|
||||
|
||||
call :compile filter _upscale "/D UPSCALE"
|
||||
call :compile filter _downsample "/D DOWNSAMPLE"
|
||||
call :compile filter _grayscale "/D GRAYSCALE"
|
||||
call :compile filter _blur "/D BLUR"
|
||||
call :compile filter _anaglyph "/D ANAGLYPH"
|
||||
|
||||
call :compile gui
|
||||
|
||||
del tmp
|
||||
|
||||
EXIT /B %ERRORLEVEL%
|
||||
|
||||
:compile
|
||||
SETLOCAL
|
||||
echo compile d3d8/%~1%~2 %~3
|
||||
echo #include "%~1%~2_v.h" >> d3d8/shaders.h
|
||||
echo #include "%~1%~2_f.h" >> d3d8/shaders.h
|
||||
xsasm /D VERTEX /O2 %~3 %~1.asm tmp
|
||||
bin2c -n %~1%~2_v -o d3d8/%~1%~2_v.h tmp
|
||||
xsasm /D PIXEL /O2 %~3 %~1.asm tmp
|
||||
bin2c -n %~1%~2_f -o d3d8/%~1%~2_f.h tmp
|
||||
ENDLOCAL
|
||||
EXIT /B 0
|
||||
|
||||
:compile_u
|
||||
SETLOCAL
|
||||
call :compile %~1
|
||||
call :compile %~1 _u "/D UNDERWATER"
|
||||
ENDLOCAL
|
||||
EXIT /B 0
|
93
src/shaders/compose_entity.asm
Normal file
93
src/shaders/compose_entity.asm
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define lv0 r0
|
||||
#define lv1 r1
|
||||
#define lv2 r2
|
||||
#define lv3 r3
|
||||
#define normal r4
|
||||
#define att r5
|
||||
#define light r6
|
||||
#define pos r7
|
||||
|
||||
#define MAT_AMBIENT c[uMaterial].y
|
||||
#define MAT_ALPHA c[uMaterial].w
|
||||
|
||||
; joint = int(aCoord.w)
|
||||
mov a0.x, aCoord.w
|
||||
|
||||
; pos = mulQuatPos(uBasis[joint], aCoord)
|
||||
mulQuatPos(pos, aCoord, a0.x)
|
||||
|
||||
; vFog = length((uViewPos - pos) * uFogParams.w)
|
||||
applyFog(vFog, pos)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; lighting
|
||||
; lv[0..3] = (uLightPos[0..3].xyz - pos) * uLightColor[0..3].w;
|
||||
add lv0.xyz, c[uLightPos + 0], -pos
|
||||
add lv1.xyz, c[uLightPos + 1], -pos
|
||||
add lv2.xyz, c[uLightPos + 2], -pos
|
||||
add lv3.xyz, c[uLightPos + 3], -pos
|
||||
mul lv0.xyz, c[uLightColor + 0].w, lv0
|
||||
mul lv1.xyz, c[uLightColor + 1].w, lv1
|
||||
mul lv2.xyz, c[uLightColor + 2].w, lv2
|
||||
mul lv3.xyz, c[uLightColor + 3].w, lv3
|
||||
|
||||
; att[0..3] = dot(lv[0..3], lv[0..3])
|
||||
dp3 att.x, lv0, lv0
|
||||
dp3 att.y, lv1, lv1
|
||||
dp3 att.z, lv2, lv2
|
||||
dp3 att.w, lv3, lv3
|
||||
|
||||
; att = max(0, 1 - att) / sqrt(att)
|
||||
rsq tmp.x, att.x
|
||||
rsq tmp.y, att.y
|
||||
rsq tmp.z, att.z
|
||||
rsq tmp.w, att.w
|
||||
|
||||
add att, ONE, -att
|
||||
max att, ZERO, att
|
||||
mul att, tmp, att
|
||||
|
||||
; normal = mulQuat(uBasis[joint], aNormal)
|
||||
mul pos.xyz, c[uBasis + a0.x], aNormal.zxyw
|
||||
mad pos.xyz, aNormal, c[uBasis + a0.x].zxyw, -pos
|
||||
mad pos.xyz, aNormal.yzxw, c[uBasis + a0.x].w, pos
|
||||
mul tmp.xyz, c[uBasis + a0.x].zxyw, pos
|
||||
mad pos.xyz, pos.yzxw, c[uBasis + a0.x].yzxw, -tmp
|
||||
mad normal, pos, TWO, aNormal
|
||||
|
||||
; light = max(0, dot(normal, lv[0..3]))
|
||||
dp3 light.x, lv0, normal
|
||||
dp3 light.y, lv1, normal
|
||||
dp3 light.z, lv2, normal
|
||||
dp3 light.w, lv3, normal
|
||||
|
||||
; light = max(0, light) * att
|
||||
max light, ZERO, light
|
||||
mul light, light, att
|
||||
|
||||
; vColor = aColor * material.alpha * (material.ambient + light[0..3] * uLightColor[0..3]) * 2
|
||||
mov pos, aColor
|
||||
mul pos, MAT_ALPHA, pos
|
||||
mov tmp.xyz, MAT_AMBIENT
|
||||
mov tmp.w, ONE
|
||||
mad tmp.xyz, light.x, c[uLightColor + 0], tmp
|
||||
mad tmp.xyz, light.y, c[uLightColor + 1], tmp
|
||||
mad tmp.xyz, light.z, c[uLightColor + 2], tmp
|
||||
mad tmp.xyz, light.w, c[uLightColor + 3], tmp
|
||||
mul tmp, pos, tmp
|
||||
applyUnderwater(tmp)
|
||||
add vColor, tmp, tmp
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
37
src/shaders/compose_flash.asm
Normal file
37
src/shaders/compose_flash.asm
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define lv0 r0
|
||||
#define lv1 r1
|
||||
#define lv2 r2
|
||||
#define lv3 r3
|
||||
#define normal r4
|
||||
#define att r5
|
||||
#define light r6
|
||||
#define pos r7
|
||||
#define MAT_DIFFUSE c[uMaterial].x
|
||||
#define MAT_EMISSIVE c[uMaterial].w
|
||||
|
||||
; pos = mulQuatPos(uBasis[0], aCoord)
|
||||
mulQuatPos(pos, aCoord, 0)
|
||||
|
||||
; vFog = length((uViewPos - pos) * uFogParams.w)
|
||||
applyFog(vFog, pos)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; vColor = (material.diffuse * aColor.xyz * 2.0 + material.emissive, 1.0)
|
||||
mul tmp, MAT_DIFFUSE, aColor
|
||||
add tmp, tmp, tmp
|
||||
add vColor, tmp, MAT_EMISSIVE
|
||||
mov vColor.w, MAT_EMISSIVE
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
40
src/shaders/compose_mirror.asm
Normal file
40
src/shaders/compose_mirror.asm
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define lv0 r0
|
||||
#define lv1 r1
|
||||
#define lv2 r2
|
||||
#define lv3 r3
|
||||
#define normal r4
|
||||
#define att r5
|
||||
#define light r6
|
||||
#define pos r7
|
||||
|
||||
; joint = int(aCoord.w)
|
||||
mov a0.x, aCoord.w
|
||||
|
||||
; pos = mulQuatPos(uBasis[joint], aCoord)
|
||||
mulQuatPos(pos, aCoord, a0.x)
|
||||
|
||||
; vFog = length((uViewPos - pos) * uFogParams.w)
|
||||
applyFog(vFog, pos)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; vColor = uMaterial
|
||||
mov vColor, ONE ; TODO
|
||||
|
||||
; normal = mulQuat(uBasis, aNormal)
|
||||
mov normal, aNormal
|
||||
mul pos.xyz, c[uBasis + 0 + a0.x], normal.zxyw
|
||||
mad pos.xyz, normal, c[uBasis + 0 + a0.x].zxyw, -pos
|
||||
mad pos.xyz, normal.yzxw, c[uBasis + 0 + a0.x].w, pos
|
||||
mul tmp.xyz, c[uBasis + 0 + a0.x].zxyw, pos
|
||||
mad pos.xyz, pos.yzxw, c[uBasis + 0 + a0.x].yzxw, -tmp
|
||||
mad vTexCoord, pos, TWO, normal
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
72
src/shaders/compose_room.asm
Normal file
72
src/shaders/compose_room.asm
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define lv1 r1
|
||||
#define lv2 r2
|
||||
#define lv3 r3
|
||||
#define normal r4
|
||||
#define att r5
|
||||
#define light r6
|
||||
#define pos r7
|
||||
|
||||
; pos = mulQuatPos(uBasis[0], aCoord)
|
||||
mulQuatPos(pos, aCoord, 0)
|
||||
|
||||
; vFog = length((uViewPos - pos) * uFogParams.w)
|
||||
applyFog(vFog, pos)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; lighting
|
||||
; lv[1..3] = (uLightPos[1..3].xyz - pos) * uLightColor[1..3].w;
|
||||
add lv1.xyz, c[uLightPos + 1], -pos
|
||||
add lv2.xyz, c[uLightPos + 2], -pos
|
||||
add lv3.xyz, c[uLightPos + 3], -pos
|
||||
mul lv1.xyz, c[uLightColor + 1].w, lv1
|
||||
mul lv2.xyz, c[uLightColor + 2].w, lv2
|
||||
mul lv3.xyz, c[uLightColor + 3].w, lv3
|
||||
|
||||
; att[1..3] = dot(lv[1..3], lv[1..3])
|
||||
mov att.x, ONE
|
||||
dp3 att.y, lv1, lv1
|
||||
dp3 att.z, lv2, lv2
|
||||
dp3 att.w, lv3, lv3
|
||||
|
||||
; att = max(0, 1 - att) / sqrt(att)
|
||||
rsq tmp.y, att.y
|
||||
rsq tmp.z, att.z
|
||||
rsq tmp.w, att.w
|
||||
|
||||
add att, ONE, -att
|
||||
max att, ZERO, att
|
||||
mul att, tmp, att
|
||||
|
||||
; light = max(0, dot(aNormal, lv[1..3]))
|
||||
mov light.x, ZERO
|
||||
dp3 light.y, lv1, aNormal
|
||||
dp3 light.z, lv2, aNormal
|
||||
dp3 light.w, lv3, aNormal
|
||||
|
||||
; light = max(0, light) * att
|
||||
max light, ZERO, light
|
||||
mul light, light, att
|
||||
|
||||
; vColor = (aLight + light[1..3] * uLightColor[1..3]) * aColor * 2
|
||||
mov pos, aColor
|
||||
mov tmp, aLight
|
||||
mad tmp.xyz, light.y, c[uLightColor + 1], tmp
|
||||
mad tmp.xyz, light.z, c[uLightColor + 2], tmp
|
||||
mad tmp.xyz, light.w, c[uLightColor + 3], tmp
|
||||
mul tmp, pos, tmp
|
||||
applyUnderwater(tmp)
|
||||
add vColor, tmp, tmp
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
94
src/shaders/compose_sprite.asm
Normal file
94
src/shaders/compose_sprite.asm
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define lv0 r0
|
||||
#define lv1 r1
|
||||
#define lv2 r2
|
||||
#define lv3 r3
|
||||
#define normal r4
|
||||
#define att r5
|
||||
#define light r6
|
||||
#define pos r7
|
||||
#define size r4
|
||||
#define vv r6
|
||||
|
||||
#define MAT_AMBIENT c[uMaterial].y
|
||||
#define MAT_ALPHA c[uMaterial].w
|
||||
|
||||
; pos = (aTexCoord.zw * 32767, 0, 0)
|
||||
mov pos, ZERO
|
||||
mul pos.xy, aTexCoord.zw, MAX_SHORT
|
||||
|
||||
; size = mulQuatPos(uBasis[0], pos)
|
||||
mulQuatPos(size, pos, 0)
|
||||
|
||||
; pos = size + aCoord
|
||||
add pos, size, aCoord
|
||||
mov pos.w, ONE
|
||||
|
||||
; vFog = length((uViewPos - pos) * uFogParams.w)
|
||||
applyFog(vFog, pos)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; lighting
|
||||
; lv[1..3] = (uLightPos[1..3].xyz - pos) * uLightColor[1..3].w;
|
||||
add lv1.xyz, c[uLightPos + 1], -pos
|
||||
add lv2.xyz, c[uLightPos + 2], -pos
|
||||
add lv3.xyz, c[uLightPos + 3], -pos
|
||||
mul lv1.xyz, c[uLightColor + 1].w, lv1
|
||||
mul lv2.xyz, c[uLightColor + 2].w, lv2
|
||||
mul lv3.xyz, c[uLightColor + 3].w, lv3
|
||||
|
||||
; att[1..3] = dot(lv[1..3], lv[1..3])
|
||||
mov att.x, ONE
|
||||
dp3 att.y, lv1, lv1
|
||||
dp3 att.z, lv2, lv2
|
||||
dp3 att.w, lv3, lv3
|
||||
|
||||
; att = max(0, 1 - att) / sqrt(att)
|
||||
rsq tmp.y, att.y
|
||||
rsq tmp.z, att.z
|
||||
rsq tmp.w, att.w
|
||||
|
||||
add att, ONE, -att
|
||||
max att, ZERO, att
|
||||
mul att, tmp, att
|
||||
|
||||
; viewVec = uViewPos - pos
|
||||
add vv, c[uViewPos], -pos
|
||||
|
||||
; normal = normalize(viewVec)
|
||||
dp3 tmp.x, vv, vv
|
||||
rsq tmp.x, tmp.x
|
||||
mul normal, vv, tmp.x
|
||||
|
||||
; light = max(0, dot(normal, lv[1..3]))
|
||||
mov light.x, MAT_AMBIENT
|
||||
dp3 light.y, lv1, normal
|
||||
dp3 light.z, lv2, normal
|
||||
dp3 light.w, lv3, normal
|
||||
|
||||
; light = max(0, light) * att
|
||||
max light, ZERO, light
|
||||
mul light, light, att
|
||||
|
||||
; vColor = vec4(aLight.rgb * aLight.a, aLight.a) * 2
|
||||
mov tmp, aLight
|
||||
mad tmp.xyz, light.x, c[uLightColor + 0], tmp
|
||||
mad tmp.xyz, light.y, c[uLightColor + 1], tmp
|
||||
mad tmp.xyz, light.z, c[uLightColor + 2], tmp
|
||||
mad tmp.xyz, light.w, c[uLightColor + 3], tmp
|
||||
mul tmp.xyz, tmp, tmp.w
|
||||
applyUnderwater(tmp)
|
||||
add vColor, tmp, tmp
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
65
src/shaders/filter.asm
Normal file
65
src/shaders/filter.asm
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
mulMat(vPosition, aCoord, uViewProj)
|
||||
|
||||
|
||||
#ifdef GRAYSCALE
|
||||
mov vColor.xyz, c[uParam].xyz
|
||||
mov vColor.w, ONE
|
||||
#else
|
||||
mov vColor, aLight
|
||||
#endif
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
#ifdef UPSCALE
|
||||
mov vTexCoord, aTexCoord ; TODO + 0.5 * (1 / uParam.xy)
|
||||
#endif
|
||||
|
||||
#ifdef DOWNSAMPLE
|
||||
mov vTexCoord, aTexCoord
|
||||
#endif
|
||||
|
||||
#ifdef GRAYSCALE
|
||||
mov tmp, c[uParam].wwww
|
||||
mad vTexCoord, tmp, HALF, aTexCoord
|
||||
#endif
|
||||
|
||||
#ifdef BLUR
|
||||
mov tmp, c[uParam].wwww
|
||||
mad vTexCoord, tmp, HALF, aTexCoord
|
||||
#endif
|
||||
|
||||
#ifdef ANAGLYPH
|
||||
mov vTexCoord, aTexCoord
|
||||
#endif
|
||||
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
def c0, 0.299f, 0.587f, 0.114f, 0.0f
|
||||
|
||||
tex t0
|
||||
|
||||
#ifdef UPSCALE
|
||||
mul r0, t0, vColor
|
||||
#endif
|
||||
|
||||
#ifdef DOWNSAMPLE
|
||||
mul r0, t0, vColor
|
||||
#endif
|
||||
|
||||
#ifdef GRAYSCALE
|
||||
dp3 r1.rgb, t0, c0
|
||||
mov r0, vColor
|
||||
mul r0.rgb, r0.rgb, r1.rgb
|
||||
#endif
|
||||
|
||||
#ifdef BLUR ; TODO four tap blur
|
||||
mul r0, t0, vColor
|
||||
#endif
|
||||
|
||||
#ifdef ANAGLYPH
|
||||
mul r0, t0, vColor
|
||||
#endif
|
||||
|
||||
#endif
|
14
src/shaders/gui.asm
Normal file
14
src/shaders/gui.asm
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
mulMat(vPosition, aCoord, uViewProj)
|
||||
|
||||
mul vColor, aLight, c[uMaterial]
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1)
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
tex t0
|
||||
mul r0, t0, vColor
|
||||
#endif
|
22
src/shaders/shadow_entity.asm
Normal file
22
src/shaders/shadow_entity.asm
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "common.asm"
|
||||
|
||||
#ifdef VERTEX
|
||||
; variables
|
||||
#define pos r7
|
||||
|
||||
; joint = int(aCoord.w)
|
||||
mov a0.x, aCoord.w
|
||||
|
||||
; pos = mulQuatPos(uBasis[joint], aCoord)
|
||||
mulQuatPos(pos, aCoord, a0.x)
|
||||
|
||||
; vPosition = uViewProj * pos
|
||||
mulMat(vPosition, pos, uViewProj)
|
||||
|
||||
; vTecCoord = (aTexCoord.xyz, 1) TODO check AKILL
|
||||
mov vTexCoord, aTexCoord
|
||||
mov vTexCoord.w, ONE
|
||||
#else
|
||||
def c0, 0.0f, 0.0f, 0.0f, 1.0f
|
||||
mov r0, c0
|
||||
#endif
|
@@ -8,7 +8,7 @@
|
||||
|
||||
#define DECODE_OGG
|
||||
|
||||
#if !defined(_OS_PSP) && !defined(_OS_WEB) && !defined(_OS_PSV) && !defined(_OS_3DS)
|
||||
#if !defined(_OS_PSP) && !defined(_OS_WEB) && !defined(_OS_PSV) && !defined(_OS_3DS) && !defined(_OS_XBOX)
|
||||
#define DECODE_MP3
|
||||
#endif
|
||||
|
||||
|
48
src/utils.h
48
src/utils.h
@@ -20,7 +20,7 @@
|
||||
#define ASSERTV(expr) ASSERT(expr)
|
||||
|
||||
#ifndef _OS_ANDROID
|
||||
#define LOG(...) printf(__VA_ARGS__)
|
||||
#define LOG printf
|
||||
#endif
|
||||
|
||||
#else
|
||||
@@ -35,7 +35,7 @@
|
||||
#define LOG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define LOG(...) printf(__VA_ARGS__)
|
||||
#define LOG printf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -50,6 +50,21 @@
|
||||
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"OpenLara",__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef _OS_XBOX
|
||||
#define MAX_LOG_LENGTH 1024
|
||||
|
||||
#undef LOG
|
||||
void LOG(const char *format, ...) {
|
||||
char str[MAX_LOG_LENGTH];
|
||||
va_list arglist;
|
||||
va_start(arglist, format);
|
||||
_vsnprintf(str, MAX_LOG_LENGTH, format, arglist);
|
||||
va_end(arglist);
|
||||
OutputDebugStringA(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _OS_PSP
|
||||
extern "C" {
|
||||
// pspmath.h
|
||||
@@ -74,7 +89,7 @@
|
||||
#define DECL_STR(v) #v,
|
||||
|
||||
#define EPS FLT_EPSILON
|
||||
#define INF INFINITY
|
||||
#define INF FLT_MAX
|
||||
#define PI 3.14159265358979323846f
|
||||
#define PIH (PI * 0.5f)
|
||||
#define PI2 (PI * 2.0f)
|
||||
@@ -1585,14 +1600,15 @@ struct Stream {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
char path[256];
|
||||
path[0] = 0;
|
||||
if (contentDir[0] && (!cacheDir[0] || !strstr(name, cacheDir))) {
|
||||
char path[255];
|
||||
path[0] = 0;
|
||||
strcat(path, contentDir);
|
||||
strcat(path, name);
|
||||
f = fopen(path, "rb");
|
||||
} else
|
||||
f = fopen(name, "rb");
|
||||
}
|
||||
strcat(path, name);
|
||||
fixBackslash(path);
|
||||
|
||||
f = fopen(path, "rb");
|
||||
|
||||
if (!f) {
|
||||
#ifdef _OS_WEB
|
||||
@@ -1650,6 +1666,17 @@ struct Stream {
|
||||
osCacheWrite(stream);
|
||||
}
|
||||
|
||||
static void fixBackslash(char *str) {
|
||||
#ifdef _OS_XBOX
|
||||
int len = strlen(str);
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (str[i] == '/') {
|
||||
str[i] = '\\';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool exists(const char *name) {
|
||||
FILE *f = fopen(name, "rb");
|
||||
if (!f) return false;
|
||||
@@ -1661,6 +1688,7 @@ struct Stream {
|
||||
char fileName[1024];
|
||||
strcpy(fileName, contentDir);
|
||||
strcat(fileName, name);
|
||||
fixBackslash(fileName);
|
||||
return exists(fileName);
|
||||
}
|
||||
|
||||
@@ -2151,8 +2179,6 @@ struct Array {
|
||||
ASSERT(index >= 0 && index < length);
|
||||
return items[index];
|
||||
};
|
||||
|
||||
inline operator T*() const { return items; };
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user