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:
@@ -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;
|
||||
|
@@ -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));
|
||||
}
|
||||
|
131
src/texture.h
131
src/texture.h
@@ -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);
|
||||
|
41
src/utils.h
41
src/utils.h
@@ -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) {
|
||||
|
Reference in New Issue
Block a user