1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-14 00:54:05 +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) {
if (useEasyStart) {
if (version == VER_TR1_PC)
switch (id) {
case LVL_TR1_TITLE :
if (Stream::existsContent("DATA/TITLEH.PCX")) return "DATA/TITLEH.PCX";
if (Stream::existsContent("TITLEH.png")) return "TITLEH.png";
break;
default : ;
}
switch (id) {
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("DELDATA/AMERTIT.RAW")) return "DELDATA/AMERTIT.RAW";
break;
if (version == VER_TR2_PC)
switch (id) {
case LVL_TR2_TITLE :
if (Stream::existsContent("data/TITLE.PCX")) return "data/TITLE.PCX";
if (Stream::existsContent("pix/title.pcx")) return "pix/title.pcx";
if (Stream::existsContent("TITLE.png")) return "TITLE.png";
break;
default : ;
}
case LVL_TR2_TITLE :
if (Stream::existsContent("TITLE.png")) return "TITLE.png";
if (Stream::existsContent("data/TITLE.PCX")) return "data/TITLE.PCX";
if (Stream::existsContent("pix/title.pcx")) return "pix/title.pcx";
break;
if (version == VER_TR3_PC)
switch (id) {
case LVL_TR3_TITLE :
if (Stream::existsContent("pix/TITLEUK.BMP")) return "pix/TITLEUK.BMP";
break;
default : ;
}
case LVL_TR3_TITLE :
if (Stream::existsContent("pix/TITLEUK.BMP")) return "pix/TITLEUK.BMP";
break;
default : ;
}
} else {
if (version & VER_TR1)
switch (id) {
case LVL_TR1_TITLE : return "level/1/TITLEH.PCX";
default : ;
}
switch (id) {
case LVL_TR1_TITLE : return "level/1/TITLEH.PCX";
if (version & VER_TR2)
switch (id) {
case LVL_TR2_TITLE : return "level/2/TITLE.PCX";
default : ;
}
case LVL_TR2_TITLE : return "level/2/TITLE.PCX";
if (version & VER_TR3)
switch (id) {
case LVL_TR3_TITLE : return "level/3/TITLEUK.BMP";
default : ;
}
case LVL_TR3_TITLE : return "level/3/TITLEUK.BMP";
default : ;
}
}
return NULL;

View File

@@ -1021,11 +1021,11 @@ struct Inventory {
} else {
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 aspectImg = aspectDst / aspectSrc;
float ax = 640.0f / float(background[0]->width);
float ay = 480.0f / float(background[0]->height);
float ax = background[0]->origWidth / float(background[0]->width);
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));
}

View File

@@ -7,7 +7,7 @@ struct Texture {
enum Format : uint32 { LUMINANCE, RGBA, RGB16, RGBA16, RGBA_FLOAT, RGBA_HALF, DEPTH, DEPTH_STENCIL, SHADOW, MAX };
GLuint ID;
int width, height;
int width, height, origWidth, origHeight;
Format format;
bool cube;
bool filter;
@@ -17,8 +17,8 @@ struct Texture {
width = nextPow2(width);
height = nextPow2(height);
}
this->width = width;
this->height = height;
this->width = origWidth = width;
this->height = origHeight = height;
glGenTextures(1, &ID);
bind(0);
@@ -236,6 +236,8 @@ struct Texture {
}
Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data);
tex->origWidth = pcx.width;
tex->origHeight = pcx.height;
delete[] buffer;
return tex;
@@ -275,6 +277,8 @@ struct Texture {
}
Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data32);
tex->origWidth = width;
tex->origHeight = height;
delete[] data24;
delete[] data32;
@@ -475,13 +479,13 @@ struct Texture {
for (uint32 i = 0; i < dw; i++)
*dst++ = (i < width && j < height) ? *src++ : 0xFF000000;
width = dw;
height = dh;
delete[] data32;
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[] data;
@@ -490,6 +494,119 @@ struct Texture {
}
#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) {
uint32 magic;
stream.read(magic);
@@ -498,6 +615,8 @@ struct Texture {
if (magic == 0x474E5089)
return LoadPNG(stream);
#endif
if (magic == FOURCC("RNC\002"))
return LoadRNC(stream);
if ((magic & 0xFFFF) == 0x4D42)
return LoadBMP(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 {
void toLower(char *str) {