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

Final Fantasy XI .DAT (PC)

Post questions about game models here, or help out others!
Maphesdus
ultra-n00b
Posts: 6
Joined: Mon Jan 11, 2016 8:53 pm
Been thanked: 1 time

Re: Final Fantasy XI .DAT (PC)

Post by Maphesdus »

Okay, thanks. Sorry for my noobish questions, I'm just new to this whole thing.

Is there a way to export the animations for the spell effects? Cuz' as far as I can tell Noesis only loads the textures for spells, and not the actual spell animations.

By the way, MrAdults is Rich Whitehouse, I assume?
User avatar
shakotay2
MEGAVETERAN
MEGAVETERAN
Posts: 4284
Joined: Fri Apr 20, 2012 9:24 am
Location: Nexus, searching for Jim Kirk
Has thanked: 1146 times
Been thanked: 2242 times

Re: Final Fantasy XI .DAT (PC)

Post by shakotay2 »

Maphesdus wrote:By the way, MrAdults is Rich Whitehouse, I assume?
yep. Aliases of the "god of 3D model format analysing".

He's the One who's giving us the rules:
MrAdults wrote:There is a way to specify "up" in Noesis, that's why the models appear oriented correctly in Noesis. Noesis doesn't rotate the geometry itself, it changes what's considered "up" in the scene. This is The Right Thing To Do.
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
falconcool
veteran
Posts: 105
Joined: Tue Jun 16, 2009 4:41 am
Has thanked: 19 times
Been thanked: 11 times

Re: Final Fantasy XI .DAT (PC)

Post by falconcool »

hello,long time..not sure if anyone still digging this game.
About map/terrain data..it's encrypted.inside the mmb,mzb block.
Someone sent me the information how to decrypt it.
I only knew how to IO basic 3d models..so that information didn't help me much.
I decide to left the information here.
For some kind people wanna make blender/3dsmax script to import/export terrain/maps.

Code: Select all

static BYTE key_table[0x100] =
{
    0xE2, 0xE5, 0x06, 0xA9, 0xED, 0x26, 0xF4, 0x42, 0x15, 0xF4, 0x81, 0x7F, 0xDE, 0x9A, 0xDE, 0xD0,
    0x1A, 0x98, 0x20, 0x91, 0x39, 0x49, 0x48, 0xA4, 0x0A, 0x9F, 0x40, 0x69, 0xEC, 0xBD, 0x81, 0x81,
    0x8D, 0xAD, 0x10, 0xB8, 0xC1, 0x88, 0x15, 0x05, 0x11, 0xB1, 0xAA, 0xF0, 0x0F, 0x1E, 0x34, 0xE6,
    0x81, 0xAA, 0xCD, 0xAC, 0x02, 0x84, 0x33, 0x0A, 0x19, 0x38, 0x9E, 0xE6, 0x73, 0x4A, 0x11, 0x5D,
    0xBF, 0x85, 0x77, 0x08, 0xCD, 0xD9, 0x96, 0x0D, 0x79, 0x78, 0xCC, 0x35, 0x06, 0x8E, 0xF9, 0xFE,
    0x66, 0xB9, 0x21, 0x03, 0x20, 0x29, 0x1E, 0x27, 0xCA, 0x86, 0x82, 0xE6, 0x45, 0x07, 0xDD, 0xA9,
    0xB6, 0xD5, 0xA2, 0x03, 0xEC, 0xAD, 0x62, 0x45, 0x2D, 0xCE, 0x79, 0xBD, 0x8F, 0x2D, 0x10, 0x18,
    0xE6, 0x0A, 0x6F, 0xAA, 0x6F, 0x46, 0x84, 0x32, 0x9F, 0x29, 0x2C, 0xC2, 0xF0, 0xEB, 0x18, 0x6F,
    0xF2, 0x3A, 0xDC, 0xEA, 0x7B, 0x0C, 0x81, 0x2D, 0xCC, 0xEB, 0xA1, 0x51, 0x77, 0x2C, 0xFB, 0x49,
    0xE8, 0x90, 0xF7, 0x90, 0xCE, 0x5C, 0x01, 0xF3, 0x5C, 0xF4, 0x41, 0xAB, 0x04, 0xE7, 0x16, 0xCC,
    0x3A, 0x05, 0x54, 0x55, 0xDC, 0xED, 0xA4, 0xD6, 0xBF, 0x3F, 0x9E, 0x08, 0x93, 0xB5, 0x63, 0x38,
    0x90, 0xF7, 0x5A, 0xF0, 0xA2, 0x5F, 0x56, 0xC8, 0x08, 0x70, 0xCB, 0x24, 0x16, 0xDD, 0xD2, 0x74,
    0x95, 0x3A, 0x1A, 0x2A, 0x74, 0xC4, 0x9D, 0xEB, 0xAF, 0x69, 0xAA, 0x51, 0x39, 0x65, 0x94, 0xA2,
    0x4B, 0x1F, 0x1A, 0x60, 0x52, 0x39, 0xE8, 0x23, 0xEE, 0x58, 0x39, 0x06, 0x3D, 0x22, 0x6A, 0x2D,
    0xD2, 0x91, 0x25, 0xA5, 0x2E, 0x71, 0x62, 0xA5, 0x0B, 0xC1, 0xE5, 0x6E, 0x43, 0x49, 0x7C, 0x58,
    0x46, 0x19, 0x9F, 0x45, 0x49, 0xC6, 0x40, 0x09, 0xA2, 0x99, 0x5B, 0x7B, 0x98, 0x7F, 0xA0, 0xD0,
};

static BYTE key_table2[0x100] =
{
    0xB8, 0xC5, 0xF7, 0x84, 0xE4, 0x5A, 0x23, 0x7B, 0xC8, 0x90, 0x1D, 0xF6, 0x5D, 0x09, 0x51, 0xC1,
    0x07, 0x24, 0xEF, 0x5B, 0x1D, 0x73, 0x90, 0x08, 0xA5, 0x70, 0x1C, 0x22, 0x5F, 0x6B, 0xEB, 0xB0,
    0x06, 0xC7, 0x2A, 0x3A, 0xD2, 0x66, 0x81, 0xDB, 0x41, 0x62, 0xF2, 0x97, 0x17, 0xFE, 0x05, 0xEF,
    0xA3, 0xDC, 0x22, 0xB3, 0x45, 0x70, 0x3E, 0x18, 0x2D, 0xB4, 0xBA, 0x0A, 0x65, 0x1D, 0x87, 0xC3,
    0x12, 0xCE, 0x8F, 0x9D, 0xF7, 0x0D, 0x50, 0x24, 0x3A, 0xF3, 0xCA, 0x70, 0x6B, 0x67, 0x9C, 0xB2,
    0xC2, 0x4D, 0x6A, 0x0C, 0xA8, 0xFA, 0x81, 0xA6, 0x79, 0xEB, 0xBE, 0xFE, 0x89, 0xB7, 0xAC, 0x7F,
    0x65, 0x43, 0xEC, 0x56, 0x5B, 0x35, 0xDA, 0x81, 0x3C, 0xAB, 0x6D, 0x28, 0x60, 0x2C, 0x5F, 0x31,
    0xEB, 0xDF, 0x8E, 0x0F, 0x4F, 0xFA, 0xA3, 0xDA, 0x12, 0x7E, 0xF1, 0xA5, 0xD2, 0x22, 0xA0, 0x0C,
    0x86, 0x8C, 0x0A, 0x0C, 0x06, 0xC7, 0x65, 0x18, 0xCE, 0xF2, 0xA3, 0x68, 0xFE, 0x35, 0x96, 0x95,
    0xA6, 0xFA, 0x58, 0x63, 0x41, 0x59, 0xEA, 0xDD, 0x7F, 0xD3, 0x1B, 0xA8, 0x48, 0x44, 0xAB, 0x91,
    0xFD, 0x13, 0xB1, 0x68, 0x01, 0xAC, 0x3A, 0x11, 0x78, 0x30, 0x33, 0xD8, 0x4E, 0x6A, 0x89, 0x05,
    0x7B, 0x06, 0x8E, 0xB0, 0x86, 0xFD, 0x9F, 0xD7, 0x48, 0x54, 0x04, 0xAE, 0xF3, 0x06, 0x17, 0x36,
    0x53, 0x3F, 0xA8, 0x11, 0x53, 0xCA, 0xA1, 0x95, 0xC2, 0xCD, 0xE6, 0x1F, 0x57, 0xB4, 0x7F, 0xAA,
    0xF3, 0x6B, 0xF9, 0xA0, 0x27, 0xD0, 0x09, 0xEF, 0xF6, 0x68, 0x73, 0x60, 0xDC, 0x50, 0x2A, 0x25,
    0x0F, 0x77, 0xB9, 0xB0, 0x04, 0x0B, 0xE1, 0xCC, 0x35, 0x31, 0x84, 0xE6, 0x22, 0xF9, 0xC2, 0xAB,
    0x95, 0x91, 0x61, 0xD9, 0x2B, 0xB9, 0x72, 0x4E, 0x10, 0x76, 0x31, 0x66, 0x0A, 0x0B, 0x2E, 0x83,
};

int BitCount(BYTE x)
{
    int n = 0;
    n += ((x >> 7) & 1);
    n += ((x >> 6) & 1);
    n += ((x >> 5) & 1);
    n += ((x >> 4) & 1);
    n += ((x >> 3) & 1);
    n += ((x >> 2) & 1);
    n += ((x >> 1) & 1);
    n += ((x >> 0) & 1);
    return n;
}

void decode_mmb2(BYTE *p)
{
    if(p[6] == 0xFF && p[7] == 0xFF)    {
        int decode_length = (p[0] << 0) | (p[1] << 8) | (p[2] << 16);
        DWORD key1 = p[5] ^ 0xF0;
        DWORD key2 = key_table2[key1] ;
        int key_counter = 0;

        DWORD decode_count = ((decode_length - 8) & ~0xf) / 2;

        DWORD *data1 = (DWORD *)(p + 8 + 0);
        DWORD *data2 = (DWORD *)(p + 8 + decode_count);
        for(DWORD pos = 0; pos < decode_count; pos += 8)
        {
            if(key2 & 1)
            {
                DWORD tmp;

                tmp = data1[0];
                data1[0] = data2[0];
                data2[0] = tmp;

                tmp = data1[1];
                data1[1] = data2[1];
                data2[1] = tmp;
            }
            key1 += 9;
            key2 += key1;
            data1 += 2;
            data2 += 2;
        }
    }
}

void decode_mmb(BYTE*p)
{
    if(p[3] >= 5)
    {
        int decode_length = (p[0] << 0) | (p[1] << 8) | (p[2] << 16);
        DWORD key = key_table[p[5] ^ 0xF0];
        int key_counter = 0;

        for(int pos = 8; pos < decode_length; pos++)
        {
            DWORD x = ((key & 0xFF) << 8) | (key & 0xFF);
            key += ++key_counter;

            p[pos] ^= (x >> (key & 7));
            key += ++key_counter;
        }
    }
    decode_mmb2(p);
}

void decode_mzb(BYTE* p)
{
    if (p[3] >= 0x1B)
    {
        int decode_length = (p[0] << 0) | (p[1] << 8) | (p[2] << 16);
        DWORD key = key_table[p[7] ^ 0xFF];
        int key_counter = 0;

        for (int pos = 8; pos < decode_length; )
        {
            int xor_length = ((key >> 4) & 7) + 16;

            if ((key & 1) && (pos + xor_length < decode_length))
            {
                for (int i = 0; i < xor_length; i++)
                 {
                    p[pos+i] ^= 0xFF;
                }
            }
            key += ++key_counter;
            pos += xor_length;
        }
        int node_count = (p[4] << 0) | (p[5] << 8) | (p[6] << 16);
        OBJINFO *node = (OBJINFO *)(p+32);
        for(int i = 0; i < node_count; i++)
        {
            for(int i = 0; i < 16; i++)
            {
                node->id[i] ^= 0x55; // OBJINFO.id[16]; offset +0x00
            }
            node++;
        }
    }
}

Pray mr.adult can heal from the illness.
Post Reply