1
0
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:
XProger
2020-10-14 06:32:13 +04:00
parent 7a3c15d29c
commit f0bc71af6d
29 changed files with 2462 additions and 50 deletions

View File

@@ -1523,7 +1523,7 @@ struct DummyController : Controller {
DummyController(IGame *game, int entity) : Controller(game, entity) {}
virtual void update() override {};
virtual void update() {}
};

View File

@@ -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 &params) {
#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);
}

View File

@@ -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();
}

View File

@@ -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
View 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 &params) {
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

View File

@@ -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

View File

@@ -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" \

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);

View 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

View 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
View 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, &params);
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);
}

Binary file not shown.

View File

@@ -28,7 +28,6 @@ struct Shader : GAPI::Shader {
setParam(uLightProj, Core::mLightProj);
setParam(uViewPos, Core::viewPos);
setParam(uParam, Core::params);
setParam(uFogParams, Core::fogParams);
}
};

View 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

View 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
View 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

View 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

View 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

View 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

View 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

View 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

View 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
View 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
View 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

View 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

View File

@@ -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

View File

@@ -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; };
};