1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-18 02:41:29 +02:00

#15 RNC texture format support (TR1 PSX title images)

This commit is contained in:
XProger
2017-12-14 02:25:44 +03:00
parent 9d68df5b7a
commit eb501ccb65
4 changed files with 193 additions and 48 deletions

View File

@@ -671,51 +671,36 @@ namespace TR {
const char* getGameScreen(Version version, LevelID id) { const char* getGameScreen(Version version, LevelID id) {
if (useEasyStart) { if (useEasyStart) {
if (version == VER_TR1_PC) switch (id) {
switch (id) { case LVL_TR1_TITLE :
case LVL_TR1_TITLE : if (Stream::existsContent("TITLEH.png")) return "TITLEH.png";
if (Stream::existsContent("DATA/TITLEH.PCX")) return "DATA/TITLEH.PCX"; if (Stream::existsContent("DATA/TITLEH.PCX")) return "DATA/TITLEH.PCX";
if (Stream::existsContent("TITLEH.png")) return "TITLEH.png"; if (Stream::existsContent("DELDATA/AMERTIT.RAW")) return "DELDATA/AMERTIT.RAW";
break; break;
default : ;
}
if (version == VER_TR2_PC) case LVL_TR2_TITLE :
switch (id) { if (Stream::existsContent("TITLE.png")) return "TITLE.png";
case LVL_TR2_TITLE : if (Stream::existsContent("data/TITLE.PCX")) return "data/TITLE.PCX";
if (Stream::existsContent("data/TITLE.PCX")) return "data/TITLE.PCX"; if (Stream::existsContent("pix/title.pcx")) return "pix/title.pcx";
if (Stream::existsContent("pix/title.pcx")) return "pix/title.pcx"; break;
if (Stream::existsContent("TITLE.png")) return "TITLE.png";
break;
default : ;
}
if (version == VER_TR3_PC) case LVL_TR3_TITLE :
switch (id) { if (Stream::existsContent("pix/TITLEUK.BMP")) return "pix/TITLEUK.BMP";
case LVL_TR3_TITLE : break;
if (Stream::existsContent("pix/TITLEUK.BMP")) return "pix/TITLEUK.BMP";
break; default : ;
default : ; }
}
} else { } else {
if (version & VER_TR1) switch (id) {
switch (id) { case LVL_TR1_TITLE : return "level/1/TITLEH.PCX";
case LVL_TR1_TITLE : return "level/1/TITLEH.PCX";
default : ;
}
if (version & VER_TR2) case LVL_TR2_TITLE : return "level/2/TITLE.PCX";
switch (id) {
case LVL_TR2_TITLE : return "level/2/TITLE.PCX";
default : ;
}
if (version & VER_TR3) case LVL_TR3_TITLE : return "level/3/TITLEUK.BMP";
switch (id) {
case LVL_TR3_TITLE : return "level/3/TITLEUK.BMP"; default : ;
default : ; }
}
} }
return NULL; return NULL;

View File

@@ -1021,11 +1021,11 @@ struct Inventory {
} else { } else {
game->setShader(Core::passFilter, Shader::DEFAULT, false, false); game->setShader(Core::passFilter, Shader::DEFAULT, false, false);
float aspectSrc = float(640.0f) / float(480.0f); float aspectSrc = float(background[0]->origWidth) / float(background[0]->origHeight);
float aspectDst = float(Core::width) / float(Core::height); float aspectDst = float(Core::width) / float(Core::height);
float aspectImg = aspectDst / aspectSrc; float aspectImg = aspectDst / aspectSrc;
float ax = 640.0f / float(background[0]->width); float ax = background[0]->origWidth / float(background[0]->width);
float ay = 480.0f / float(background[0]->height); float ay = background[0]->origHeight / float(background[0]->height);
Core::active.shader->setParam(uParam, vec4(ax * aspectImg, -ay, (0.5f - aspectImg * 0.5f) * ax, ay)); Core::active.shader->setParam(uParam, vec4(ax * aspectImg, -ay, (0.5f - aspectImg * 0.5f) * ax, ay));
} }

View File

@@ -7,7 +7,7 @@ struct Texture {
enum Format : uint32 { LUMINANCE, RGBA, RGB16, RGBA16, RGBA_FLOAT, RGBA_HALF, DEPTH, DEPTH_STENCIL, SHADOW, MAX }; enum Format : uint32 { LUMINANCE, RGBA, RGB16, RGBA16, RGBA_FLOAT, RGBA_HALF, DEPTH, DEPTH_STENCIL, SHADOW, MAX };
GLuint ID; GLuint ID;
int width, height; int width, height, origWidth, origHeight;
Format format; Format format;
bool cube; bool cube;
bool filter; bool filter;
@@ -17,8 +17,8 @@ struct Texture {
width = nextPow2(width); width = nextPow2(width);
height = nextPow2(height); height = nextPow2(height);
} }
this->width = width; this->width = origWidth = width;
this->height = height; this->height = origHeight = height;
glGenTextures(1, &ID); glGenTextures(1, &ID);
bind(0); bind(0);
@@ -236,6 +236,8 @@ struct Texture {
} }
Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data); Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data);
tex->origWidth = pcx.width;
tex->origHeight = pcx.height;
delete[] buffer; delete[] buffer;
return tex; return tex;
@@ -275,6 +277,8 @@ struct Texture {
} }
Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data32); Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data32);
tex->origWidth = width;
tex->origHeight = height;
delete[] data24; delete[] data24;
delete[] data32; delete[] data32;
@@ -475,13 +479,13 @@ struct Texture {
for (uint32 i = 0; i < dw; i++) for (uint32 i = 0; i < dw; i++)
*dst++ = (i < width && j < height) ? *src++ : 0xFF000000; *dst++ = (i < width && j < height) ? *src++ : 0xFF000000;
width = dw;
height = dh;
delete[] data32; delete[] data32;
data32 = dataPOT; data32 = dataPOT;
} }
Texture *tex = new Texture(width, height, Texture::RGBA, false, data32); Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data32);
tex->origWidth = width;
tex->origHeight = height;
delete[] data32; delete[] data32;
delete[] data; delete[] data;
@@ -490,6 +494,119 @@ struct Texture {
} }
#endif #endif
static void rncGetOffset(BitStream &bs, uint16 &offset) {
offset = 0;
if (bs.readBit()) {
offset = bs.readBit();
if (bs.readBit()) {
offset = ((offset << 1) | bs.readBit()) | 4;
if (!bs.readBit())
offset = (offset << 1) | bs.readBit();
} else if (!offset)
offset = bs.readBit() + 2;
}
offset = ((offset << 8) | bs.readByte()) + 1;
}
static Texture* LoadRNC(Stream &stream) { // https://github.com/lab313ru/rnc_propack_source
stream.seek(4); // skip MAGIC
uint32 size = swap32(stream.read(size));
uint32 csize = swap32(stream.read(csize));
stream.seek(4); // skip CRC
uint8 chunks, fkey;
stream.read(fkey);
stream.read(chunks);
uint16 key = fkey;
uint8 *data = new uint8[size];
uint8 *cdata = new uint8[csize];
stream.raw(cdata, csize);
BitStream bs(cdata, csize);
uint8 *dst = data;
uint8 *end = data + size;
uint32 length = 0;
uint16 offset = 0;
bs.readBits(2);
while (dst < end) {
if (!bs.readBit()) {
*dst++ = bs.readByte();
} else {
if (bs.readBit()) {
if (bs.readBit()) {
if (bs.readBit()) {
length = bs.readByte() + 8;
if (length == 8) {
bs.readBit();
continue;
}
} else
length = 3;
rncGetOffset(bs, offset);
} else {
length = 2;
offset = bs.readByte() + 1;
}
while (length--)
*dst++ = dst[-offset];
} else {
length = bs.readBit() + 4;
if (bs.readBit())
length = ((length - 1) << 1) + bs.readBit();
if (length != 9) {
rncGetOffset(bs, offset);
while (length--)
*dst++ = dst[-offset];
} else {
length = (bs.readBits(4) << 2) + 12;
while (length--)
*dst++ = bs.readByte();
}
}
}
}
delete[] cdata;
int width = 384;
int height = 256;
int dw = Core::support.texNPOT ? width : nextPow2(width);
int dh = Core::support.texNPOT ? height : nextPow2(height);
uint32 *data32 = new uint32[dw * dh];
{
uint32 *dst = data32;
uint16 *src = (uint16*)data;
for (int j = 0; j < dh; j++)
for (int i = 0; i < dw; i++) {
if (i < width && j < height) {
uint16 c = *src++;
*dst++ = ((c & 0x001F) << 3) | ((c & 0x03E0) << 6) | (((c & 0x7C00) << 9)) | 0xFF000000;
} else
*dst++ = 0xFF000000;
}
delete[] data;
}
Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data32);
tex->origWidth = width;
tex->origHeight = height;
delete[] data32;
return tex;
}
static Texture* Load(Stream &stream) { static Texture* Load(Stream &stream) {
uint32 magic; uint32 magic;
stream.read(magic); stream.read(magic);
@@ -498,6 +615,8 @@ struct Texture {
if (magic == 0x474E5089) if (magic == 0x474E5089)
return LoadPNG(stream); return LoadPNG(stream);
#endif #endif
if (magic == FOURCC("RNC\002"))
return LoadRNC(stream);
if ((magic & 0xFFFF) == 0x4D42) if ((magic & 0xFFFF) == 0x4D42)
return LoadBMP(stream); return LoadBMP(stream);
return LoadPCX(stream); return LoadPCX(stream);

View File

@@ -1128,6 +1128,47 @@ struct Stream {
} }
}; };
struct BitStream {
uint8 *data;
uint8 *end;
uint8 index;
uint8 value;
BitStream(uint8 *data, int size) : data(data), end(data + size), index(0), value(0) {}
uint8 readBits(int count) {
uint32 bits = 0;
while (count--) {
if (!index) {
ASSERT(data < end);
value = *data++;
index = 8;
}
bits <<= 1;
if (value & 0x80)
bits |= 1;
value <<= 1;
index--;
}
return bits;
}
uint8 readBit() {
return readBits(1);
}
uint8 readByte() {
return *data++;
}
};
namespace String { namespace String {
void toLower(char *str) { void toLower(char *str) {