Important information: this site is currently scheduled to go offline indefinitely by end of the year.

PS2 texture unswizzling (4-bit textures)

Get your graphics formats figures out here! Got details for others? Post here!
Post Reply
Nick W
ultra-n00b
Posts: 3
Joined: Mon May 25, 2009 3:04 pm
Been thanked: 1 time

PS2 texture unswizzling (4-bit textures)

Post by Nick W »

To make a long story short, I'm working on the SVR image format and I'm having trouble unswizzling 4-bit textures. I've already got 8-bit texture unswizzling working fine.

The image on the left is what it should look like, the image on the right is how it currently works with my unswizzle code.

http://img39.imageshack.us/img39/3479/accordcorrect.png
http://img39.imageshack.us/img39/4348/a ... orrect.png

I'm currently using Sparky's Swizzle Code for this, obviously modified so it unswizzles rather than swizzles again.

Here is the code I'm currently using (C#):

Code: Select all

        // Unswizzle a 4-bit PS2 texture
        public static void UnSwizzle4(byte[] Buf, int Width, int Height, int Where)
        {
            // Don't swizzle if size if width or height is less than 128
            if (Width < 128 || Height < 128)
                return;

            // Make a copy of the swizzled input and clear buffer
            byte[] Swizzled = new byte[Buf.Length - Where];
            Array.Copy(Buf, Where, Swizzled, 0, Swizzled.Length);

            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    // get the pen
                    int index = y * Width + x;
                    //byte uPen = (byte)(Swizzled[index >> 1] >> ((index & 1) * 4) & 0xF);

                    // swizzle
                    int pageX = x & (~0x7f);
                    int pageY = y & (~0x7f);

                    int pages_horz = (Width + 127) / 128;
                    int pages_vert = (Height + 127) / 128;

                    int page_number = (pageY / 128) * pages_horz + (pageX / 128);

                    int page32Y = (page_number / pages_vert) * 32;
                    int page32X = (page_number % pages_vert) * 64;

                    int page_location = page32Y * Height * 2 + page32X * 4;

                    int locX = x & 0x7f;
                    int locY = y & 0x7f;

                    int block_location = ((locX & (~0x1f)) >> 1) * Height + (locY & (~0xf)) * 2;
                    int swap_selector = (((y + 2) >> 2) & 0x1) * 4;
                    int posY = (((y & (~3)) >> 1) + (y & 1)) & 0x7;

                    int column_location = posY * Height * 2 + ((x + swap_selector) & 0x7) * 4;

                    int byte_num = (x >> 3) & 3;     // 0,1,2,3
                    int bits_set = (y >> 1) & 1;     // 0,1            (lower/upper 4 bits)

                    byte uPen = (byte)(Swizzled[page_location + block_location + column_location + byte_num] >> ((index & 1) * 4) & 0xF);
                    Buf[Where + (index >> 1)] = (byte)((Buf[Where + (index >> 1)] & -bits_set) | (uPen << (bits_set * 4)));
                }
            }
        }
Here's the SVR of that file, if it helps at all (CLUT starts at 0x20 and is ARGB8888, image data at 0x60):
http://www.puyonexus.net/files/misc/accord_dress.svr
brienj
VIP member
VIP member
Posts: 288
Joined: Mon May 02, 2005 1:48 pm
Location: Louisville, KY
Has thanked: 10 times
Been thanked: 70 times
Contact:

Re: PS2 texture unswizzling (4-bit textures)

Post by brienj »

I'm in the same exact boat, and every bit of source code I've found doesn't work, although the source code from Puyo Tools and Sparky's Swizzle Code (they are the same thing and not sure who is the original publisher of the code) has been the closest one so far.
ameneko
advanced
Posts: 41
Joined: Thu Sep 10, 2009 2:31 am
Been thanked: 9 times

Re: PS2 texture unswizzling (4-bit textures)

Post by ameneko »

Check this. It's sort of a mess but it for sure works. It's based on Puyo Tools. https://github.com/neko68k/rtftool/blob ... p6t_v2.cpp
User avatar
CarLuver69
advanced
Posts: 50
Joined: Thu Mar 08, 2012 6:17 pm
Location: California, USA
Has thanked: 7 times
Been thanked: 21 times
Contact:

Re: PS2 texture unswizzling (4-bit textures)

Post by CarLuver69 »

After 8 years of this originally being posted, I can finally provide a concrete answer to 4-bit PS2 texture unswizzling. I wrote it in C# and is based on Delphi code originally by Dageron. Full credit goes to him for being smart enough to know how this stuff works!

A permanent link to the code can be found here. If you use this in an open-source project, a link back to the gist would be appreciated. But do make sure you give full credit to Dageron, as he's the one who made this possible in the first place!

Happy unswizzling!
Sir Kane
veteran
Posts: 104
Joined: Mon Aug 06, 2012 4:14 am
Been thanked: 96 times

Re: PS2 texture unswizzling (4-bit textures)

Post by Sir Kane »

The
//if ((mw % 32) > 0)
// mw = ((mw / 32) * 32) + 32;
part is for alignment to multiples of 32.

Though the typical implementation would be:

Code: Select all

(value + align-1)/align*align
instead of having the remainder check.
Post Reply