Esempio n. 1
0
            public virtual void read()
            {
                int entryOffset = outerInstance.tell();

                type = outerInstance.read8();
                id   = outerInstance.read8();
                outerInstance.skip16();
                labelOffset     = outerInstance.read32();
                eHeadSize       = outerInstance.read32();
                entrySize       = outerInstance.read32();
                numSubEntries   = outerInstance.read32();
                nextEntryOffset = outerInstance.read32();
                prevEntryOffset = outerInstance.read32();
                parentTblOffset = outerInstance.read32();
                outerInstance.skip32();
                outerInstance.skip32();

                outerInstance.entries[entryOffset] = this;

                if (parentTblOffset != 0)
                {
                    parent = outerInstance.entries[entryOffset - parentTblOffset];
                }

                if (labelOffset != RCO_NULL_PTR)
                {
                    label = outerInstance.readLabel(labelOffset);
                }

                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("RCO entry at offset 0x{0:X}: {1}", entryOffset, ToString()));
                }

                switch (id)
                {
                case RCO_TABLE_MAIN:
                    if (type != 1)
                    {
                        Console.WriteLine(string.Format("Unknown RCO entry type 0x{0:X} at offset 0x{1:X}", type, entryOffset));
                    }
                    break;

                case RCO_TABLE_VSMX:
                    if (type == 1)
                    {
                        int offsetVSMX = outerInstance.read32();
                        int lengthVSMX = outerInstance.read32();
                        outerInstance.skip(offsetVSMX);
                        data = outerInstance.readBytes(lengthVSMX);
                        // 4-bytes alignment
                        outerInstance.skip(Utilities.alignUp(lengthVSMX, 3) - lengthVSMX);
                    }
                    else
                    {
                        Console.WriteLine(string.Format("Unknown RCO entry type 0x{0:X} at offset 0x{1:X}", type, entryOffset));
                    }
                    break;

                case RCO_TABLE_IMG:
                case RCO_TABLE_MODEL:
                    if (type == 1)
                    {
                        int format      = outerInstance.read16();
                        int compression = outerInstance.read16();
                        int sizePacked  = outerInstance.read32();
                        int offset      = outerInstance.read32();
                        int sizeUnpacked;                                 // this value doesn't exist if entry isn't compressed
                        if (compression != RCO_DATA_COMPRESSION_NONE)
                        {
                            sizeUnpacked = outerInstance.read32();
                        }
                        else
                        {
                            sizeUnpacked = sizePacked;
                        }

                        if (id == RCO_TABLE_IMG)
                        {
                            System.Drawing.Bitmap image = outerInstance.readImage(offset, sizePacked);
                            if (image != null)
                            {
                                obj = new ImageObject(image);
                                outerInstance.images[entryOffset] = image;
                            }
                        }

                        //if (log.DebugEnabled)
                        {
                            Console.WriteLine(string.Format("RCO entry {0}: format={1:D}, compression={2:D}, sizePacked=0x{3:X}, offset=0x{4:X}, sizeUnpacked=0x{5:X}", id == RCO_TABLE_IMG ? "IMG" : "MODEL", format, compression, sizePacked, offset, sizeUnpacked));
                        }
                    }
                    else if (type != 0)
                    {
                        Console.WriteLine(string.Format("Unknown RCO entry type 0x{0:X} at offset 0x{1:X}", type, entryOffset));
                    }
                    break;

                case RCO_TABLE_SOUND:
                    if (type == 1)
                    {
                        int   format        = outerInstance.read16();                        // 0x01 = VAG
                        int   channels      = outerInstance.read16();                        // 1 or 2 channels
                        int   sizeTotal     = outerInstance.read32();
                        int   offset        = outerInstance.read32();
                        int[] channelSize   = new int[channels];
                        int[] channelOffset = new int[channels];
                        // now pairs of size/offset for each channel
                        //if (log.DebugEnabled)
                        {
                            Console.WriteLine(string.Format("RCO entry SOUND: format={0:D}, channels={1:D}, sizeTotal=0x{2:X}, offset=0x{3:X}", format, channels, sizeTotal, offset));
                        }
                        for (int channel = 0; channel < channels; channel++)
                        {
                            channelSize[channel]   = outerInstance.read32();
                            channelOffset[channel] = outerInstance.read32();
                            //if (log.DebugEnabled)
                            {
                                Console.WriteLine(string.Format("Channel {0:D}: size=0x{1:X}, offset=0x{2:X}", channel, channelSize[channel], channelOffset[channel]));
                            }
                        }

                        obj = SoundFactory.newSound(format, channels, channelSize, channelOffset);

                        // there _must_ be two channels defined (no clear indication of size otherwise)
                        if (channels < 2)
                        {
                            for (int i = channels; i < 2; i++)
                            {
                                int dummyChannelSize   = outerInstance.read32();
                                int dummyChannelOffset = outerInstance.read32();
                                if (log.TraceEnabled)
                                {
                                    log.trace(string.Format("Dummy channel {0:D}: size=0x{1:X}, offset=0x{2:X}", i, dummyChannelSize, dummyChannelOffset));
                                }
                            }
                        }
                    }
                    else if (type != 0)
                    {
                        Console.WriteLine(string.Format("Unknown RCO entry type 0x{0:X} at offset 0x{1:X}", type, entryOffset));
                    }
                    break;

                case RCO_TABLE_OBJ:
                    if (type > 0)
                    {
                        obj = ObjectFactory.newObject(type);

                        if (obj != null && entrySize == 0)
                        {
                            entrySize = obj.size() + RCO_ENTRY_SIZE;
                        }

                        if (entrySize > RCO_ENTRY_SIZE)
                        {
                            int dataLength = entrySize - RCO_ENTRY_SIZE;
                            data = outerInstance.readBytes(dataLength);
                            if (log.TraceEnabled)
                            {
                                log.trace(string.Format("OBJ data at 0x{0:X}: {1}", entryOffset + RCO_ENTRY_SIZE, Utilities.getMemoryDump(data, 0, dataLength)));
                            }

                            if (obj != null)
                            {
                                RCOContext context = new RCOContext(data, 0, outerInstance.events, outerInstance.images, outerInstance.objects);
                                obj.read(context);
                                if (context.offset != dataLength)
                                {
                                    Console.WriteLine(string.Format("Incorrect Length data for ANIM"));
                                }

                                outerInstance.objects[entryOffset] = obj;

                                //if (log.DebugEnabled)
                                {
                                    Console.WriteLine(string.Format("OBJ: {0}", obj));
                                }
                            }
                        }
                    }
                    break;

                case RCO_TABLE_ANIM:
                    if (type > 0)
                    {
                        obj = AnimFactory.newAnim(type);

                        if (obj != null && entrySize == 0)
                        {
                            entrySize = obj.size() + RCO_ENTRY_SIZE;
                        }

                        if (entrySize > RCO_ENTRY_SIZE)
                        {
                            int dataLength = entrySize - RCO_ENTRY_SIZE;
                            data = outerInstance.readBytes(dataLength);
                            if (log.TraceEnabled)
                            {
                                log.trace(string.Format("ANIM data at 0x{0:X}: {1}", entryOffset + RCO_ENTRY_SIZE, Utilities.getMemoryDump(data, 0, dataLength)));
                            }

                            if (obj != null)
                            {
                                RCOContext context = new RCOContext(data, 0, outerInstance.events, outerInstance.images, outerInstance.objects);
                                obj.read(context);
                                if (context.offset != dataLength)
                                {
                                    Console.WriteLine(string.Format("Incorrect Length data for ANIM"));
                                }

                                outerInstance.objects[entryOffset] = obj;

                                //if (log.DebugEnabled)
                                {
                                    Console.WriteLine(string.Format("ANIM: {0}", obj));
                                }
                            }
                        }
                    }
                    break;

                case RCO_TABLE_FONT:
                    if (type == 1)
                    {
                        int format      = outerInstance.read16();
                        int compression = outerInstance.read16();
                        int unknown1    = outerInstance.read32();
                        int unknown2    = outerInstance.read32();
                        //if (log.DebugEnabled)
                        {
                            Console.WriteLine(string.Format("RCO entry FONT: format={0:D}, compression={1:D}, unknown1=0x{2:X}, unknown2=0x{3:X}", format, compression, unknown1, unknown2));
                        }
                    }
                    else if (type != 0)
                    {
                        Console.WriteLine(string.Format("Unknown RCO FONT entry type 0x{0:X} at offset 0x{1:X}", type, entryOffset));
                    }
                    break;

                case RCO_TABLE_TEXT:
                    if (type == 1)
                    {
                        int lang       = outerInstance.read16();
                        int format     = outerInstance.read16();
                        int numIndexes = outerInstance.read32();
                        //if (log.DebugEnabled)
                        {
                            Console.WriteLine(string.Format("RCO entry TEXT: lang={0:D}, format={1:D}, numIndexes=0x{2:X}", lang, format, numIndexes));
                        }
                        texts = new string[numIndexes];
                        for (int i = 0; i < numIndexes; i++)
                        {
                            int labelOffset = outerInstance.read32();
                            int Length      = outerInstance.read32();
                            int offset      = outerInstance.read32();
                            texts[i] = outerInstance.readText(lang, offset, Length);
                            //if (log.DebugEnabled)
                            {
                                Console.WriteLine(string.Format("RCO entry TEXT Index#{0:D}: labelOffset={1:D}, Length={2:D}, offset=0x{3:X}; '{4}'", i, labelOffset, Length, offset, texts[i]));
                            }
                        }
                    }
                    else if (type != 0)
                    {
                        Console.WriteLine(string.Format("Unknown RCO TEXT entry type 0x{0:X} at offset 0x{1:X}", type, entryOffset));
                    }
                    break;

                default:
                    Console.WriteLine(string.Format("Unknown RCO entry id 0x{0:X} at offset 0x{1:X}", id, entryOffset));
                    break;
                }

                if (numSubEntries > 0)
                {
                    subEntries = new RCOEntry[numSubEntries];
                    for (int i = 0; i < numSubEntries; i++)
                    {
                        subEntries[i] = new RCOEntry(outerInstance);
                        subEntries[i].read();
                    }
                }
            }