Important information: this site is currently scheduled to go offline indefinitely by end of the year.
GTA IV LZX compression on resource data
-
- ultra-n00b
- Posts: 5
- Joined: Fri Oct 24, 2008 4:52 am
- Been thanked: 2 times
Re: GTA IV LZX compression on resource data
Post removed due to legal reasons
Last edited by AnthonyFiveSixTwo on Thu Jun 25, 2009 6:31 pm, edited 1 time in total.
-
- ultra-n00b
- Posts: 8
- Joined: Fri Apr 03, 2009 12:27 pm
- Location: Germany
- Been thanked: 1 time
- Contact:
Re: GTA IV LZX compression on resource data
Well, but whats about the LZX thing ?
Are they using a custom Compression layout ?
About the Textures:
I guess they use the normal 360 Swizzling like in Halo 3 or Dead or Alive Xtreme 2.
Did you allready check the XEX for something like a security check or something ?
Are they using a custom Compression layout ?
About the Textures:
I guess they use the normal 360 Swizzling like in Halo 3 or Dead or Alive Xtreme 2.
Did you allready check the XEX for something like a security check or something ?
-
- advanced
- Posts: 56
- Joined: Mon May 25, 2009 8:22 am
- Has thanked: 11 times
- Been thanked: 58 times
Re: GTA IV LZX compression on resource data
All progress is very nice, espesially if uncompression process is now known. Special thanks to AnthonyFiveSixTwo)
Yeah, the DLL is from x360 Development SDK, but anyway it is great because of LZX was large roadblock.
The rest of unpacked .xtd is now known, it is not totally differs from PC .wtd. Main difference is swizzling method - as far as I know, it is usual for x360 (some guys are already researched .xtd format - gtaforums.com staff and PC GTA IV tool developers, but keept everything in secret because of "legality" of their actions).
It means that structure of .xtd header and texturetable is not as imporntant, as texture data. IIVEnnEII (or somerbody else), can you post some code to deal with x360 swizzling?
Yeah, the DLL is from x360 Development SDK, but anyway it is great because of LZX was large roadblock.
The rest of unpacked .xtd is now known, it is not totally differs from PC .wtd. Main difference is swizzling method - as far as I know, it is usual for x360 (some guys are already researched .xtd format - gtaforums.com staff and PC GTA IV tool developers, but keept everything in secret because of "legality" of their actions).
It means that structure of .xtd header and texturetable is not as imporntant, as texture data. IIVEnnEII (or somerbody else), can you post some code to deal with x360 swizzling?
-
- ultra-n00b
- Posts: 8
- Joined: Fri Apr 03, 2009 12:27 pm
- Location: Germany
- Been thanked: 1 time
- Contact:
Re: GTA IV LZX compression on resource data
I allready talked to Anthony about that.
Well, I think they are using the "normal" swizzling method.
I got some code, maybe you have to adjust the code a bit:
Well, you need a EndianWriter.
I got a library for all that Xbox 360 stuff, but its not created by me.
Maybe Anthony can provide a DLL for "Free to use" purposes
Well, I think they are using the "normal" swizzling method.
I got some code, maybe you have to adjust the code a bit:
Code: Select all
public static byte[] Deswizzle(byte[] raw, int width, int height)
{
MemoryStream ms = new MemoryStream();
core.IO.EndianIO.EndianWriter ew = new core.IO.EndianIO.EndianWriter(ms, core.IO.EndianType.LittleEndian);
ew.BaseStream.Position = 0;
int realsize = width * height * 4;
int lines = realsize / 16;
int templine = 0;
int rowcount = 0;
int offsetby = 0;
int i = 0;
int sections = width / 32;
for (int x = 0; x < lines; x++)
{
if (rowcount % 32 == 0 && rowcount != 0)
{
templine = (i+1)*((width * 32) /4);
i++;
}
if (rowcount % 8 == 0 && rowcount != 0)
{
if (offsetby == 0)
{
offsetby = 8 * 16;
}
else
{
offsetby = 0;
}
}
if (rowcount == height) break;
///get row 1 - 224 pixels(one row) = 7 * 32
for (int y = 0; y < sections; y++)
{
//get 32 pixels
for (int z = 0; z < 8; z++)
{
if (z < 4)
{
int offset = (templine * 16) + ((y * 256) * 16) + ((z * 2) * 16) + offsetby;
int oi1 = BitConverter.ToInt32(raw, offset + 0);
int oi2 = BitConverter.ToInt32(raw, offset + 4);
int oi3 = BitConverter.ToInt32(raw, offset + 8);
int oi4 = BitConverter.ToInt32(raw, offset + 12);
ew.Write(oi1);
ew.Write(oi2);
ew.Write(oi3);
ew.Write(oi4);
}
else
{
int offset = (templine * 16) + ((y * 256) * 16) + ((z * 2) * 16) - offsetby;
int oi1 = BitConverter.ToInt32(raw, offset + 0);
int oi2 = BitConverter.ToInt32(raw, offset + 4);
int oi3 = BitConverter.ToInt32(raw, offset + 8);
int oi4 = BitConverter.ToInt32(raw, offset + 12);
ew.Write(oi1);
ew.Write(oi2);
ew.Write(oi3);
ew.Write(oi4);
}
}
}
rowcount++;
if (rowcount == height) break;
///get row 2
for (int y = 0; y < sections; y++)
{
//get 32 pixels
for (int z = 0; z < 8; z++)
{
if (offsetby != 0)
{
}
if (z < 4)
{
int offset = (templine * 16) + 16 + ((y * 256) * 16) + ((z * 2) * 16) + offsetby;
int oi1 = BitConverter.ToInt32(raw, offset + 0);
int oi2 = BitConverter.ToInt32(raw, offset + 4);
int oi3 = BitConverter.ToInt32(raw, offset + 8);
int oi4 = BitConverter.ToInt32(raw, offset + 12);
ew.Write(oi1);
ew.Write(oi2);
ew.Write(oi3);
ew.Write(oi4);
}
else
{
int offset = (templine * 16) + 16 + ((y * 256) * 16) + ((z * 2) * 16) - offsetby;
int oi1 = BitConverter.ToInt32(raw, offset + 0);
int oi2 = BitConverter.ToInt32(raw, offset + 4);
int oi3 = BitConverter.ToInt32(raw, offset + 8);
int oi4 = BitConverter.ToInt32(raw, offset + 12);
ew.Write(oi1);
ew.Write(oi2);
ew.Write(oi3);
ew.Write(oi4);
}
}
}
rowcount++;
templine += 16;
}
return ms.ToArray();
}
All credit goes to pokecancerpokecancer wrote:I figured I would release my deswizzle method for A8R8G8B8 so people can do more research on bitmaps. This applies to not only H3 but most game's resources for Xbox 360 and could probably be easily adjusted to deal with different argb formats by changing some of the math in my code. BTW this is using my own modified BinaryReader class so you will have to change that if you want to use this code. also keep in mind the data is in big endian format and need to 32 bit swapped in order to be in a format the pc can understand.
Well, you need a EndianWriter.
I got a library for all that Xbox 360 stuff, but its not created by me.
Maybe Anthony can provide a DLL for "Free to use" purposes
-
- mega-veteran
- Posts: 183
- Joined: Thu Oct 08, 2009 7:51 pm
- Has thanked: 6 times
- Been thanked: 10 times
Re: GTA IV LZX compression on resource data
So the xbox360 gets the files with x at begin.
Like .xft, xwd and such.
How are these textures inside?
Are they .dds or .xds?
I still havent found a way how to view or convert .xds textures.
Like .xft, xwd and such.
How are these textures inside?
Are they .dds or .xds?
I still havent found a way how to view or convert .xds textures.
Re: GTA IV LZX compression on resource data
Files into .xtd are the same what you can find in .wtd PC version of GTA4.bigBear wrote:So the xbox360 gets the files with x at begin.
Like .xft, xwd and such.
How are these textures inside?
Are they .dds or .xds?
I still havent found a way how to view or convert .xds textures.
Simply:
.xtd -> .dds
.wtd -> .dds
Look this:
Sorry for big image.
Anyone find method to extract this .xtd files ?
Re: GTA IV LZX compression on resource data
What has AnthonyFiveSixTwo said, that it has been removed?
Anyway I got the TBoGT and TLAD files, and can give you guys every file you want.
Maybe you can compare the freeway.xft and freeway.wft (from original IV) with a HEX editor?
Or luis.xdd and luis.wdd (from original IV)? Same story for texture files...
Anyway I got the TBoGT and TLAD files, and can give you guys every file you want.
Maybe you can compare the freeway.xft and freeway.wft (from original IV) with a HEX editor?
Or luis.xdd and luis.wdd (from original IV)? Same story for texture files...
Re: GTA IV LZX compression on resource data
No.. modders from france use this "compare" method and they find nothing usefull.
-
- veteran
- Posts: 87
- Joined: Sat Mar 13, 2010 3:59 pm
- Has thanked: 44 times
- Been thanked: 2 times
Re: GTA IV LZX compression on resource data
Hello, I know that this post is ancient, if I break some norm, erase it.
Have some time looking for the library or "something" to be able to open these files but I have not been lucky.
Those who have obtained it, looking for help for the forums, (in these forums also) now do not give information.
Probably someone could give me information or to help myself.
Post dates back: I have sent some private messages but it do not belong(do not perform,am not) if I have done it well. I it sit Post it dates 2: EFLC, will work out very prompt for PC and PS3 so I do not believe that there is no problem in which someone helps me.
Thank you
Hallo weiß ich, dass dieser Posten(Post) alt ist, wenn ich eine Norm breche(durchbreche), es ausradiere.
Haben Sie eine Zeit, die nach der Bibliothek oder "etwas" sucht, um imstande zu sein, diese Dateien zu öffnen, aber ich habe Glück nicht gehabt.
Diejenigen, die es erlangt haben, nach Hilfe für die Foren, (in diesen Foren auch) jetzt suchend, geben Information nicht.
Ich habe Interesse, Gewebe von GTA der IVTH IN XBOX 360 für ausschließlich privaten Gebrauch zu öffnen.
Wahrscheinlich konnte jemand mir Information geben oder mir zu helfen.
Posten(Post) reicht zurück: Ich habe einige private Nachrichten gesandt, aber es gehört nicht (führen Sie nicht aus, sind nicht) wenn ich es gut getan habe. Ich es sitzt Posten(Post), es datiere 2: EFLC, wird sehr pünktlich für PC und PS3 ausarbeiten, so dass ich nicht glaube, dass es kein Problem gibt, in dem jemand mir hilft.
Dank Sie
Have some time looking for the library or "something" to be able to open these files but I have not been lucky.
Those who have obtained it, looking for help for the forums, (in these forums also) now do not give information.
I have interest to open GTA's textures the IVth in XBOX 360 for exclusively private use.Dageron wrote:No future... If you could help me with decompressor writing it will be more than good, for all people who interested in X360 GTAIV.
Probably someone could give me information or to help myself.
Post dates back: I have sent some private messages but it do not belong(do not perform,am not) if I have done it well. I it sit Post it dates 2: EFLC, will work out very prompt for PC and PS3 so I do not believe that there is no problem in which someone helps me.
Thank you
Hallo weiß ich, dass dieser Posten(Post) alt ist, wenn ich eine Norm breche(durchbreche), es ausradiere.
Haben Sie eine Zeit, die nach der Bibliothek oder "etwas" sucht, um imstande zu sein, diese Dateien zu öffnen, aber ich habe Glück nicht gehabt.
Diejenigen, die es erlangt haben, nach Hilfe für die Foren, (in diesen Foren auch) jetzt suchend, geben Information nicht.
Ich habe Interesse, Gewebe von GTA der IVTH IN XBOX 360 für ausschließlich privaten Gebrauch zu öffnen.
Wahrscheinlich konnte jemand mir Information geben oder mir zu helfen.
Posten(Post) reicht zurück: Ich habe einige private Nachrichten gesandt, aber es gehört nicht (führen Sie nicht aus, sind nicht) wenn ich es gut getan habe. Ich es sitzt Posten(Post), es datiere 2: EFLC, wird sehr pünktlich für PC und PS3 ausarbeiten, so dass ich nicht glaube, dass es kein Problem gibt, in dem jemand mir hilft.
Dank Sie
Last edited by lUIGUIPIETRO on Tue Mar 23, 2010 4:57 pm, edited 1 time in total.
-
- Site Admin
- Posts: 4073
- Joined: Wed Jan 15, 2003 6:45 pm
- Location: Dungeons of Doom
- Has thanked: 450 times
- Been thanked: 682 times
- Contact:
Re: GTA IV LZX compression on resource data
So nobody here will help you? Is that what you are saying? Is the information here not enough?
-
- veteran
- Posts: 87
- Joined: Sat Mar 13, 2010 3:59 pm
- Has thanked: 44 times
- Been thanked: 2 times
Re: GTA IV LZX compression on resource data
Sorry old post,...
Well, searching carefully in my things, I have found some (enough) codes that are almost exact to others exposed in the previous page.
Might they use me as something? That is to say, on this topic I deal little (nothing) but I am trying(mean) it to forced marches.
And
and
Sorry for very long post.
Another thing, all the textures of PC have a heading RSC and some of xbox, the most common but others have heading .CSI.
Is it important?
Thank you for reading myself.
Well, searching carefully in my things, I have found some (enough) codes that are almost exact to others exposed in the previous page.
Might they use me as something? That is to say, on this topic I deal little (nothing) but I am trying(mean) it to forced marches.
Code: Select all
using System.IO;
namespace RageLib.Common.Resources
{
internal class ResourceHeader
{
private const uint MagicBigEndian = 0x52534305;
public const uint MagicValue = 0x05435352;
public uint Magic { get; set; }
public ResourceType Type { get; set; }
public uint Flags { get; set; }
public CompressionType CompressCodec { get; set; }
public int GetSystemMemSize()
{
return (int)(Flags & 0x7FF) << (int)(((Flags >> 11) & 0xF) + 8);
}
public int GetGraphicsMemSize()
{
return (int)((Flags >> 15) & 0x7FF) << (int)(((Flags >> 26) & 0xF) + 8);
}
public void SetMemSizes(int systemMemSize, int graphicsMemSize)
{
// gfx = a << (b + 8)
// minimum representable is block of 0x100 bytes
const int maxA = 0x3F;
int sysA = systemMemSize >> 8;
int sysB = 0;
while(sysA > maxA)
{
if ((sysA & 1) != 0)
{
sysA += 2;
}
sysA >>= 1;
sysB++;
}
int gfxA = graphicsMemSize >> 8;
int gfxB = 0;
while (gfxA > maxA)
{
if ((gfxA & 1) != 0)
{
gfxA += 2;
}
gfxA >>= 1;
gfxB++;
}
Flags = (Flags & 0xC0000000) | (uint)(sysA | (sysB << 11) | (gfxA << 15) | (gfxB << 26));
}
public void Read(BinaryReader br)
{
Magic = br.ReadUInt32();
Type = (ResourceType) br.ReadUInt32();
Flags = br.ReadUInt32();
CompressCodec = (CompressionType)br.ReadUInt16();
if (Magic == MagicBigEndian)
{
Magic = DataUtil.SwapEndian(Magic);
Type = (ResourceType)DataUtil.SwapEndian((uint)Type);
Flags = DataUtil.SwapEndian(Flags);
}
}
public void Write(BinaryWriter bw)
{
bw.Write( MagicValue );
bw.Write( (uint)Type );
bw.Write( Flags );
bw.Write( (ushort)CompressCodec );
}
}
}
Code: Select all
using System.Reflection;
namespace RageLib.Common.Resources
{
[Obfuscation(StripAfterObfuscation = true, ApplyToMembers = true, Exclude = true)]
public enum ResourceType
{
TextureXBOX = 0x7, // xtd
ModelXBOX = 0x6D, // xdr
Generic = 0x01, // xhm / xad (Generic files as rsc?)
Bounds = 0x20, // xbd, wbd
Particles = 0x24, // xpfl
Particles2 = 0x1B, // xpfl
Texture = 0x8, // wtd
Model = 0x6E, // wdr
ModelFrag = 0x70, //wft
}
}
Code: Select all
// Uncomment the following line to get this Decoder to work for XBOX360 DXT Encoded files
// Note that the data has to be untiled before running the decoder on it
//#define XBOX360
using System;
namespace RageLib.Textures.Decoder
{
internal static class DXTDecoder
{
internal static byte[] DecodeDXT1(byte[] data, int width, int height)
{
byte[] pixData = new byte[width * height * 4];
int xBlocks = width / 4;
int yBlocks = height / 4;
for (int y = 0; y < yBlocks; y++)
{
for (int x = 0; x < xBlocks; x++)
{
int blockDataStart = ((y * xBlocks) + x) * 8;
#if XBOX360
uint color0 = ((uint)data[blockDataStart + 0] << 8) + data[blockDataStart + 1];
uint color1 = ((uint)data[blockDataStart + 2] << 8) + data[blockDataStart + 3];
#else
uint color0 = BitConverter.ToUInt16(data, blockDataStart);
uint color1 = BitConverter.ToUInt16(data, blockDataStart + 2);
#endif
uint code = BitConverter.ToUInt32(data, blockDataStart + 4);
ushort r0 = 0, g0 = 0, b0 = 0, r1 = 0, g1 = 0, b1 = 0;
r0 = (ushort)(8 * (color0 & 31));
g0 = (ushort)(4 * ((color0 >> 5) & 63));
b0 = (ushort)(8 * ((color0 >> 11) & 31));
r1 = (ushort)(8 * (color1 & 31));
g1 = (ushort)(4 * ((color1 >> 5) & 63));
b1 = (ushort)(8 * ((color1 >> 11) & 31));
for (int k = 0; k < 4; k++)
{
#if XBOX360
int j = k ^ 1;
#else
int j = k;
#endif
for (int i = 0; i < 4; i++)
{
int pixDataStart = (width * (y * 4 + j) * 4) + ((x * 4 + i) * 4);
uint codeDec = code & 0x3;
switch (codeDec)
{
case 0:
pixData[pixDataStart + 0] = (byte)r0;
pixData[pixDataStart + 1] = (byte)g0;
pixData[pixDataStart + 2] = (byte)b0;
pixData[pixDataStart + 3] = 255;
break;
case 1:
pixData[pixDataStart + 0] = (byte)r1;
pixData[pixDataStart + 1] = (byte)g1;
pixData[pixDataStart + 2] = (byte)b1;
pixData[pixDataStart + 3] = 255;
break;
case 2:
pixData[pixDataStart + 3] = 255;
if (color0 > color1)
{
pixData[pixDataStart + 0] = (byte)((2 * r0 + r1) / 3);
pixData[pixDataStart + 1] = (byte)((2 * g0 + g1) / 3);
pixData[pixDataStart + 2] = (byte)((2 * b0 + b1) / 3);
}
else
{
pixData[pixDataStart + 0] = (byte)((r0 + r1) / 2);
pixData[pixDataStart + 1] = (byte)((g0 + g1) / 2);
pixData[pixDataStart + 2] = (byte)((b0 + b1) / 2);
}
break;
case 3:
if (color0 > color1)
{
pixData[pixDataStart + 0] = (byte)((r0 + 2 * r1) / 3);
pixData[pixDataStart + 1] = (byte)((g0 + 2 * g1) / 3);
pixData[pixDataStart + 2] = (byte)((b0 + 2 * b1) / 3);
pixData[pixDataStart + 3] = 255;
}
else
{
pixData[pixDataStart + 0] = 0;
pixData[pixDataStart + 1] = 0;
pixData[pixDataStart + 2] = 0;
pixData[pixDataStart + 3] = 0;
}
break;
}
code >>= 2;
}
}
}
}
return pixData;
}
internal static byte[] DecodeDXT3(byte[] data, int width, int height)
{
byte[] pixData = new byte[width * height * 4];
int xBlocks = width / 4;
int yBlocks = height / 4;
for (int y = 0; y < yBlocks; y++)
{
for (int x = 0; x < xBlocks; x++)
{
int blockDataStart = ((y * xBlocks) + x) * 16;
ushort[] alphaData = new ushort[4];
#if XBOX360
alphaData[0] = (ushort)((data[blockDataStart + 0] << 8) + data[blockDataStart + 1]);
alphaData[1] = (ushort)((data[blockDataStart + 2] << 8) + data[blockDataStart + 3]);
alphaData[2] = (ushort)((data[blockDataStart + 4] << 8) + data[blockDataStart + 5]);
alphaData[3] = (ushort)((data[blockDataStart + 6] << 8) + data[blockDataStart + 7]);
#else
alphaData[0] = BitConverter.ToUInt16(data, blockDataStart + 0);
alphaData[1] = BitConverter.ToUInt16(data, blockDataStart + 2);
alphaData[2] = BitConverter.ToUInt16(data, blockDataStart + 4);
alphaData[3] = BitConverter.ToUInt16(data, blockDataStart + 6);
#endif
byte[,] alpha = new byte[4, 4];
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 4; i++)
{
alpha[i, j] = (byte)((alphaData[j] & 0xF) * 16);
alphaData[j] >>= 4;
}
}
#if XBOX360
ushort color0 = (ushort)((data[blockDataStart + 8] << 8) + data[blockDataStart + 9]);
ushort color1 = (ushort)((data[blockDataStart + 10] << 8) + data[blockDataStart + 11]);
#else
ushort color0 = BitConverter.ToUInt16(data, blockDataStart + 8);
ushort color1 = BitConverter.ToUInt16(data, blockDataStart + 8 + 2);
#endif
uint code = BitConverter.ToUInt32(data, blockDataStart + 8 + 4);
ushort r0 = 0, g0 = 0, b0 = 0, r1 = 0, g1 = 0, b1 = 0;
r0 = (ushort)(8 * (color0 & 31));
g0 = (ushort)(4 * ((color0 >> 5) & 63));
b0 = (ushort)(8 * ((color0 >> 11) & 31));
r1 = (ushort)(8 * (color1 & 31));
g1 = (ushort)(4 * ((color1 >> 5) & 63));
b1 = (ushort)(8 * ((color1 >> 11) & 31));
for (int k = 0; k < 4; k++)
{
#if XBOX360
int j = k ^ 1;
#else
int j = k;
#endif
for (int i = 0; i < 4; i++)
{
int pixDataStart = (width * (y * 4 + j) * 4) + ((x * 4 + i) * 4);
uint codeDec = code & 0x3;
pixData[pixDataStart + 3] = alpha[i, j];
switch (codeDec)
{
case 0:
pixData[pixDataStart + 0] = (byte)r0;
pixData[pixDataStart + 1] = (byte)g0;
pixData[pixDataStart + 2] = (byte)b0;
break;
case 1:
pixData[pixDataStart + 0] = (byte)r1;
pixData[pixDataStart + 1] = (byte)g1;
pixData[pixDataStart + 2] = (byte)b1;
break;
case 2:
if (color0 > color1)
{
pixData[pixDataStart + 0] = (byte)((2 * r0 + r1) / 3);
pixData[pixDataStart + 1] = (byte)((2 * g0 + g1) / 3);
pixData[pixDataStart + 2] = (byte)((2 * b0 + b1) / 3);
}
else
{
pixData[pixDataStart + 0] = (byte)((r0 + r1) / 2);
pixData[pixDataStart + 1] = (byte)((g0 + g1) / 2);
pixData[pixDataStart + 2] = (byte)((b0 + b1) / 2);
}
break;
case 3:
if (color0 > color1)
{
pixData[pixDataStart + 0] = (byte)((r0 + 2 * r1) / 3);
pixData[pixDataStart + 1] = (byte)((g0 + 2 * g1) / 3);
pixData[pixDataStart + 2] = (byte)((b0 + 2 * b1) / 3);
}
else
{
pixData[pixDataStart + 0] = 0;
pixData[pixDataStart + 1] = 0;
pixData[pixDataStart + 2] = 0;
}
break;
}
code >>= 2;
}
}
}
}
return pixData;
}
internal static byte[] DecodeDXT5(byte[] data, int width, int height)
{
byte[] pixData = new byte[width * height * 4];
int xBlocks = width / 4;
int yBlocks = height / 4;
for (int y = 0; y < yBlocks; y++)
{
for (int x = 0; x < xBlocks; x++)
{
int blockDataStart = ((y * xBlocks) + x) * 16;
uint[] alphas = new uint[8];
ulong alphaMask = 0;
#if XBOX360
alphas[0] = data[blockDataStart + 1];
alphas[1] = data[blockDataStart + 0];
alphaMask |= data[blockDataStart + 6];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 7];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 4];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 5];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 2];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 3];
#else
alphas[0] = data[blockDataStart + 0];
alphas[1] = data[blockDataStart + 1];
alphaMask |= data[blockDataStart + 7];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 6];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 5];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 4];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 3];
alphaMask <<= 8;
alphaMask |= data[blockDataStart + 2];
#endif
// 8-alpha or 6-alpha block
if (alphas[0] > alphas[1])
{
// 8-alpha block: derive the other 6
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
alphas[2] = (byte)((6 * alphas[0] + 1 * alphas[1] + 3) / 7); // bit code 010
alphas[3] = (byte)((5 * alphas[0] + 2 * alphas[1] + 3) / 7); // bit code 011
alphas[4] = (byte)((4 * alphas[0] + 3 * alphas[1] + 3) / 7); // bit code 100
alphas[5] = (byte)((3 * alphas[0] + 4 * alphas[1] + 3) / 7); // bit code 101
alphas[6] = (byte)((2 * alphas[0] + 5 * alphas[1] + 3) / 7); // bit code 110
alphas[7] = (byte)((1 * alphas[0] + 6 * alphas[1] + 3) / 7); // bit code 111
}
else
{
// 6-alpha block.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
alphas[2] = (byte)((4 * alphas[0] + 1 * alphas[1] + 2) / 5); // Bit code 010
alphas[3] = (byte)((3 * alphas[0] + 2 * alphas[1] + 2) / 5); // Bit code 011
alphas[4] = (byte)((2 * alphas[0] + 3 * alphas[1] + 2) / 5); // Bit code 100
alphas[5] = (byte)((1 * alphas[0] + 4 * alphas[1] + 2) / 5); // Bit code 101
alphas[6] = 0x00; // Bit code 110
alphas[7] = 0xFF; // Bit code 111
}
byte[,] alpha = new byte[4, 4];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
alpha[j, i] = (byte)alphas[alphaMask & 7];
alphaMask >>= 3;
}
}
#if XBOX360
ushort color0 = (ushort)((data[blockDataStart + 8] << 8) + data[blockDataStart + 9]);
ushort color1 = (ushort)((data[blockDataStart + 10] << 8) + data[blockDataStart + 11]);
#else
ushort color0 = BitConverter.ToUInt16(data, blockDataStart + 8);
ushort color1 = BitConverter.ToUInt16(data, blockDataStart + 8 + 2);
#endif
uint code = BitConverter.ToUInt32(data, blockDataStart + 8 + 4);
ushort r0 = 0, g0 = 0, b0 = 0, r1 = 0, g1 = 0, b1 = 0;
r0 = (ushort)(8 * (color0 & 31));
g0 = (ushort)(4 * ((color0 >> 5) & 63));
b0 = (ushort)(8 * ((color0 >> 11) & 31));
r1 = (ushort)(8 * (color1 & 31));
g1 = (ushort)(4 * ((color1 >> 5) & 63));
b1 = (ushort)(8 * ((color1 >> 11) & 31));
for (int k = 0; k < 4; k++)
{
#if XBOX360
int j = k ^ 1;
#else
int j = k;
#endif
for (int i = 0; i < 4; i++)
{
int pixDataStart = (width * (y * 4 + j) * 4) + ((x * 4 + i) * 4);
uint codeDec = code & 0x3;
pixData[pixDataStart + 3] = alpha[i, j];
switch (codeDec)
{
case 0:
pixData[pixDataStart + 0] = (byte)r0;
pixData[pixDataStart + 1] = (byte)g0;
pixData[pixDataStart + 2] = (byte)b0;
break;
case 1:
pixData[pixDataStart + 0] = (byte)r1;
pixData[pixDataStart + 1] = (byte)g1;
pixData[pixDataStart + 2] = (byte)b1;
break;
case 2:
if (color0 > color1)
{
pixData[pixDataStart + 0] = (byte)((2 * r0 + r1) / 3);
pixData[pixDataStart + 1] = (byte)((2 * g0 + g1) / 3);
pixData[pixDataStart + 2] = (byte)((2 * b0 + b1) / 3);
}
else
{
pixData[pixDataStart + 0] = (byte)((r0 + r1) / 2);
pixData[pixDataStart + 1] = (byte)((g0 + g1) / 2);
pixData[pixDataStart + 2] = (byte)((b0 + b1) / 2);
}
break;
case 3:
if (color0 > color1)
{
pixData[pixDataStart + 0] = (byte)((r0 + 2 * r1) / 3);
pixData[pixDataStart + 1] = (byte)((g0 + 2 * g1) / 3);
pixData[pixDataStart + 2] = (byte)((b0 + 2 * b1) / 3);
}
else
{
pixData[pixDataStart + 0] = 0;
pixData[pixDataStart + 1] = 0;
pixData[pixDataStart + 2] = 0;
}
break;
}
code >>= 2;
}
}
}
}
return pixData;
}
}
}
Another thing, all the textures of PC have a heading RSC and some of xbox, the most common but others have heading .CSI.
Is it important?
Thank you for reading myself.
-
- mega-veteran
- Posts: 190
- Joined: Sat Jan 09, 2010 9:37 pm
- Has thanked: 8 times
- Been thanked: 64 times
Re: GTA IV LZX compression on resource data
So does anyone here have a way to decompress the files with the RSC header? The program "quickbms" supports XBOXMEM compression, but I can not figure out how to implement a quickbms script that works. Quickbms either crashes or produces an output file of size 0.
I accept ALL requests. Let me know your requests.