Page 2 of 2

Re: Corpse Party PSP image.bin file

Posted: Sat Dec 03, 2011 6:16 pm
by brainfog
Thank you, good sir! Extractor works nicely.
Wouldn't you mind to share recompression alg code?
Don't have much patience to wait fully functioning tool (:

Re: Corpse Party PSP image.bin file

Posted: Sat Dec 03, 2011 9:40 pm
by cozy
The contents of this post was deleted because of possible forum rules violation.

Re: Corpse Party PSP image.bin file

Posted: Sat Dec 03, 2011 10:54 pm
by SkyBladeCloud
This is the complete code I'm using to decompress and recompress; it is a pretty standard implementation, with a top of 16 byte os compressed strings:

Code: Select all

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace LZSS
{
    unsafe static class LZSS
    {
        const int N = 4096;
        const int F = 16;
        const int THRESHOLD = 2;

        const int NIL = N;

        static int textsize = 0, codesize = 0;

        static byte* text_buf = (byte*)Marshal.AllocHGlobal(N + F - 1);

        static int match_position, match_length;
        static int[] lson = new int[N + 1], rson = new int[N + 257], dad = new int[N + 1];

        static Stream infile, outfile;

        private static void InitTree()
        {
            int i;

            for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
            for (i = 0; i < N; i++) dad[i] = NIL;
        }

        private static void InsertNode(int r)
        {
            int i, p, cmp;
            byte* key;

            cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
            rson[r] = lson[r] = NIL; match_length = 0;
            for (; ; )
            {
                if (cmp >= 0)
                {
                    if (rson[p] != NIL) p = rson[p];
                    else { rson[p] = r; dad[r] = p; return; }
                }
                else
                {
                    if (lson[p] != NIL) p = lson[p];
                    else { lson[p] = r; dad[r] = p; return; }
                }
                for (i = 1; i < F; i++)
                    if ((cmp = key[i] - text_buf[p + i]) != 0) break;
                if (i > match_length)
                {
                    match_position = p;
                    if ((match_length = i) >= F) break;
                }
            }
            dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
            dad[lson[p]] = r; dad[rson[p]] = r;
            if (rson[dad[p]] == p) rson[dad[p]] = r;
            else lson[dad[p]] = r;
            dad[p] = NIL;
        }

        private static void DeleteNode(int p)
        {
            int q;

            if (dad[p] == NIL) return;
            if (rson[p] == NIL) q = lson[p];
            else if (lson[p] == NIL) q = rson[p];
            else
            {
                q = lson[p];
                if (rson[q] != NIL)
                {
                    do { q = rson[q]; } while (rson[q] != NIL);
                    rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
                    lson[q] = lson[p]; dad[lson[p]] = q;
                }
                rson[q] = rson[p]; dad[rson[p]] = q;
            }
            dad[q] = dad[p];
            if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
            dad[p] = NIL;
        }

        private static void Encode()
        {
            int i, c, len, r, s, last_match_length, code_buf_ptr;
            byte[] code_buf = new byte[17];
            byte mask;

            InitTree();
            code_buf[0] = 0;
            code_buf_ptr = mask = 1;
            s = 0; r = N - F;
            for (i = s; i < r; i++) text_buf[i] = 0x00;
            for (len = 0; len < F && infile.Position != infile.Length; len++)
            {
                c = infile.ReadByte();
                text_buf[r + len] = (byte)c;
            }
            if ((textsize = len) == 0) return;
            for (i = 1; i <= F; i++) InsertNode(r - i);
            InsertNode(r);
            do
            {
                if (match_length > len) match_length = len;
                if (match_length <= THRESHOLD)
                {
                    match_length = 1;
                    code_buf[0] |= mask;
                    code_buf[code_buf_ptr++] = text_buf[r];
                }
                else
                {
                    code_buf[code_buf_ptr++] = (byte)match_position;
                    code_buf[code_buf_ptr++] = (byte)
                            (((match_position >> 4) & 0xf0)
                      | (match_length - (THRESHOLD + 1)));
                }
                if ((mask <<= 1) == 0)
                {
                    for (i = 0; i < code_buf_ptr; i++)
                        outfile.WriteByte(code_buf[i]);
                    codesize += code_buf_ptr;
                    code_buf[0] = 0; code_buf_ptr = mask = 1;
                }
                last_match_length = match_length;
                for (i = 0; i < last_match_length && infile.Position != infile.Length; i++)
                {
                    c = infile.ReadByte();
                    DeleteNode(s);
                    text_buf[s] = (byte)c;
                    if (s < F - 1) text_buf[s + N] = (byte)c;
                    s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);

                    InsertNode(r);
                }
                while (i++ < last_match_length)
                {
                    DeleteNode(s);
                    s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
                    if (--len != 0) InsertNode(r);
                }
            } while (len > 0);
            if (code_buf_ptr > 1)
            {
                for (i = 0; i < code_buf_ptr; i++) outfile.WriteByte(code_buf[i]);
                codesize += code_buf_ptr;
            }
        }

        private static void Decode()
        {
            int i, j, k, r, c, flags;

            for (i = 0; i < N - F; i++) text_buf[i] = 0x00;
            r = N - F; flags = 0;
            for (; ; )
            {
                if (((flags >>= 1) & 256) == 0)
                {
                    if (infile.Position == infile.Length) break;
                    c = infile.ReadByte();
                    flags = c | 0xff00;
                }
                if ((flags & 1) != 0)
                {
                    if (infile.Position == infile.Length) break;
                    c = infile.ReadByte();
                    outfile.WriteByte((byte)(c)); text_buf[r++] = (byte)(c); r &= (N - 1);
                }
                else
                {
                    if (infile.Position == infile.Length) break;
                    i = infile.ReadByte();
                    if (infile.Position == infile.Length) break;
                    j = infile.ReadByte();
                    i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD;
                    for (k = 0; k <= j; k++)
                    {
                        c = text_buf[(i + k) & (N - 1)];
                        outfile.WriteByte((byte)(c)); text_buf[r++] = (byte)(c); r &= (N - 1);
                    }
                }
            }
        }

        public static byte[] Decompress(byte[] inBuffer)
        {
            MemoryStream inStream = new MemoryStream(inBuffer);
            BinaryReader reader = new BinaryReader(inStream);
            reader.BaseStream.Seek(0x04, SeekOrigin.Begin);
            int decSize = reader.ReadInt32();
            infile = new MemoryStream(reader.ReadBytes(inBuffer.Length - 0x08));
            outfile = new MemoryStream();
            Decode();
            if (outfile.Length == decSize)
                return (outfile as MemoryStream).ToArray();
            else throw new InvalidDataException("Decompression Error");
        }

        public static byte[] Compress(byte[] inBuffer)
        {
            int decSize = inBuffer.Length;
            infile = new MemoryStream(inBuffer);
            outfile = new MemoryStream();
            Encode();
            MemoryStream outStream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(outStream);
            writer.Write(0x53535a4c);
            writer.Write(decSize);
            writer.Write((outfile as MemoryStream).ToArray());
            return outStream.ToArray();
        }

        public static void Decompress(String inFile, String outFile)
        {
            infile = new FileStream(inFile, FileMode.Open, FileAccess.Read);
            outfile = new FileStream(outFile, FileMode.Create, FileAccess.Write);
            Decode();
        }

        public static void Compress(String inFile, String outFile)
        {
            infile = new FileStream(inFile, FileMode.Open, FileAccess.Read);
            outfile = new FileStream(outFile, FileMode.Create, FileAccess.Write);
            Encode();
        }

        public static void Decompress(Stream inFileStream, Stream outFileStream)
        {
            infile = inFileStream;
            outfile = outFileStream;
            Decode();
        }

        public static void Compress(Stream inFileStream, Stream outFileStream)
        {
            infile = inFileStream;
            outfile = outFileStream;
            Encode();
        }
    }
}
Regards:

~Sky

Re: Corpse Party PSP image.bin file

Posted: Sat Dec 03, 2011 11:36 pm
by brainfog
Thanx again :)

Re: Corpse Party PSP image.bin file

Posted: Mon Dec 05, 2011 12:04 am
by Toren
This is great. Thank you all for your help.

Re: Corpse Party PSP image.bin file

Posted: Thu Dec 08, 2011 8:31 pm
by Demoniiiik
I'm sorry. But you can do the opposite? That is archiving folder IMAGE in image.bin?
I want to replace some of the texture.

Re: Corpse Party PSP image.bin file

Posted: Wed Dec 21, 2011 9:09 pm
by magarcan
Thanks for the code and for the app, but I'm having a problem.

I've tested your app with the 10Mb file that other user has uploaded and I get an exception. CanĀ“t a partial file be used?

I'm interested in traslate game into my language, spanish, do aby of you know how can I get string??

Thanks!!

Re: Corpse Party PSP image.bin file

Posted: Thu Dec 22, 2011 2:19 am
by finale00
The 10 MB sample most likely won't work cause it's trying to decompress or go to some offset that may or may not exist.

Re: Corpse Party PSP image.bin file

Posted: Thu Dec 22, 2011 8:39 am
by magarcan
finale00 wrote:The 10 MB sample most likely won't work cause it's trying to decompress or go to some offset that may or may not exist.
You are right, I've tested it with full file and works O.K.

Any idea about were can I find text's files??

Re: Corpse Party PSP image.bin file

Posted: Mon Dec 26, 2011 9:27 pm
by cierpa
Any idea about were can I find text's files??
They're stored in SCRIPT folder. Check file SCRIPT_MAP5 (CHAP1) - these one have introduction of chapter 1.
As I checked they're seems compressed and contains bitmaps / voice acting/ avatars.