Пример #1
0
		public virtual void read(RCOContext context)
		{
			FieldInfo[] fields = SortedFields;
			foreach (FieldInfo FieldInfo in fields)
			{
                if (FieldInfo.ReflectedType.IsAssignableFrom(typeof(BaseType)))
				{
					try
					{
						BaseType baseType = (BaseType) FieldInfo;
						if (baseType == null)
						{
							baseType = (BaseType) FieldInfo.Type.newInstance();
							FieldInfo = baseType;
						}
						baseType.read(context);
					}
					catch (InstantiationException)
					{
						// Ignore error
					}
					catch (IllegalAccessException)
					{
						// Ignore error
					}
				}
			}
		}
Пример #2
0
        public override void init(RCOContext context)
        {
            switch (referenceType)
            {
            case REFERENCE_TYPE_NONE:
                break;

            case REFERENCE_TYPE_EVENT:
                @event = context.events[value];
                break;

            case REFERENCE_TYPE_OBJECT:
            case REFERENCE_TYPE_POSITION_OBJECT:
            case REFERENCE_TYPE_ANIM:
                @object = context.objects[value];
                break;

            case REFERENCE_TYPE_IMAGE:
                image = context.images[value];
                break;

            default:
                Console.WriteLine(string.Format("BaseReferenceType: unknown referenceType 0x{0:X}({1})", referenceType, getReferenceTypeString(referenceType)));
                break;
            }
            base.init(context);
        }
Пример #3
0
        public override void read(RCOContext context)
        {
            referenceType = read16(context);
            unknownShort  = read16(context);

            base.read(context);
        }
Пример #4
0
		public virtual void init(RCOContext context)
		{
			FieldInfo[] fields = Fields;
			foreach (FieldInfo FieldInfo in fields)
			{
				if (FieldInfo.Type.IsAssignableFrom(typeof(BaseType)))
				{
					try
					{
						BaseType baseType = (BaseType) FieldInfo.get(this);
						if (baseType != null)
						{
							baseType.init(context);
						}
					}
					catch (IllegalAccessException)
					{
						// Ignore error
					}
				}
			}
		}
Пример #5
0
 public virtual void init(RCOContext context)
 {
 }
Пример #6
0
 public virtual void read(RCOContext context)
 {
     value = read32(context);
 }
Пример #7
0
 protected internal virtual int read32(RCOContext context)
 {
     return(read16(context) | (read16(context) << 16));
 }
Пример #8
0
 protected internal virtual int read16(RCOContext context)
 {
     return(read8(context) | (read8(context) << 8));
 }
Пример #9
0
 protected internal virtual int read8(RCOContext context)
 {
     return(context.buffer[context.offset++] & 0xFF);
 }
Пример #10
0
        /// <summary>
        /// Read a RCO file.
        /// See description of an RCO file structure in
        /// https://github.com/kakaroto/RCOMage/blob/master/src/rcofile.h
        /// </summary>
        /// <returns> true  RCO file is valid
        ///         false RCO file is invalid </returns>
        private bool read()
        {
            int magic = endianSwap32(read32());

            if (magic != RCO_MAGIC)
            {
                Console.WriteLine(string.Format("Invalid RCO magic 0x{0:X8}", magic));
                return(false);
            }
            int version = read32();

            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("RCO version 0x{0:X}", version));
            }

            skip32();             // null
            int compression       = read32();
            int umdFlag           = compression & 0x0F;
            int headerCompression = (compression & 0xF0) >> 4;
            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("umdFlag=0x{0:X}, headerCompression=0x{1:X}", umdFlag, headerCompression));
            }

            int pMainTable = read32();

            pVSMXTable = read32();
            int pTextTable  = read32();
            int pSoundTable = read32();
            int pModelTable = read32();
            int pImgTable   = read32();

            skip32();             // pUnknown
            int pFontTable = read32();
            int pObjTable  = read32();
            int pAnimTable = read32();

            pTextData  = read32();
            lTextData  = read32();
            pLabelData = read32();
            lLabelData = read32();
            int pEventData = read32();
            int lEventData = read32();
            int pTextPtrs  = read32();
            int lTextPtrs  = read32();
            int pImgPtrs   = read32();
            int lImgPtrs   = read32();
            int pModelPtrs = read32();
            int lModelPtrs = read32();
            int pSoundPtrs = read32();
            int lSoundPtrs = read32();
            int pObjPtrs   = read32();
            int lObjPtrs   = read32();
            int pAnimPtrs  = read32();
            int lAnimPtrs  = read32();

            pImgData = read32();
            lImgData = read32();
            int pSoundData = read32();
            int lSoundData = read32();
            int pModelData = read32();
            int lModelData = read32();

            skip32();             // Always 0xFFFFFFFF
            skip32();             // Always 0xFFFFFFFF
            skip32();             // Always 0xFFFFFFFF

            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("pMainTable=0x{0:X}, pVSMXTable=0x{1:X}, pTextTable=0x{2:X}, pSoundTable=0x{3:X}, pModelTable=0x{4:X}, pImgTable=0x{5:X}, pFontTable=0x{6:X}, pObjTable=0x{7:X}, pAnimTable=0x{8:X}", pMainTable, pVSMXTable, pTextTable, pSoundTable, pModelTable, pImgTable, pFontTable, pObjTable, pAnimTable));
                Console.WriteLine(string.Format("TextData=0x{0:X}[0x{1:X}], LabelData=0x{2:X}[0x{3:X}], EventData=0x{4:X}[0x{5:X}]", pTextData, lTextData, pLabelData, lLabelData, pEventData, lEventData));
                Console.WriteLine(string.Format("TextPtrs=0x{0:X}[0x{1:X}], ImgPtrs=0x{2:X}[0x{3:X}], ModelPtrs=0x{4:X}[0x{5:X}], SoundPtrs=0x{6:X}[0x{7:X}], ObjPtrs=0x{8:X}[0x{9:X}], AnimPtrs=0x{10:X}[0x{11:X}]", pTextPtrs, lTextPtrs, pImgPtrs, lImgPtrs, pModelPtrs, lModelPtrs, pSoundPtrs, lSoundPtrs, pObjPtrs, lObjPtrs, pAnimPtrs, lAnimPtrs));
                Console.WriteLine(string.Format("ImgData=0x{0:X}[0x{1:X}], SoundData=0x{2:X}[0x{3:X}], ModelData=0x{4:X}[0x{5:X}]", pImgData, lImgData, pSoundData, lSoundData, pModelData, lModelData));
            }

            if (headerCompression != 0)
            {
                int     lenPacked      = read32();
                int     lenUnpacked    = read32();
                int     lenLongestText = read32();
                sbyte[] packedBuffer   = readBytes(lenPacked);
                sbyte[] unpackedBuffer = new sbyte[lenUnpacked];
                int     result;

                if (headerCompression == RCO_DATA_COMPRESSION_RLZ)
                {
                    result = LZR.decompress(unpackedBuffer, lenUnpacked, packedBuffer);
                }
                else
                {
                    Console.WriteLine(string.Format("Unimplemented compression {0:D}", headerCompression));
                    result = -1;
                }

                if (log.TraceEnabled)
                {
                    log.trace(string.Format("Unpack header longestText=0x{0:X}, result=0x{1:X}: {2}", lenLongestText, result, Utilities.getMemoryDump(unpackedBuffer, 0, lenUnpacked)));
                }

                if (pTextData != RCO_NULL_PTR && lTextData > 0)
                {
                    seek(pTextData);
                    int nextOffset;
                    do
                    {
                        int textLang = read16();
                        skip16();
                        nextOffset = read32();
                        int textLenPacked   = read32();
                        int textLenUnpacked = read32();

                        sbyte[] textPackedBuffer   = readBytes(textLenPacked);
                        sbyte[] textUnpackedBuffer = new sbyte[textLenUnpacked];

                        if (headerCompression == RCO_DATA_COMPRESSION_RLZ)
                        {
                            result = LZR.decompress(textUnpackedBuffer, textLenUnpacked, textPackedBuffer);
                        }
                        else
                        {
                            Console.WriteLine(string.Format("Unimplemented compression {0:D}", headerCompression));
                            result = -1;
                        }

                        if (log.TraceEnabled)
                        {
                            log.trace(string.Format("Unpack text lang={0:D}, result=0x{1:X}: {2}", textLang, result, Utilities.getMemoryDump(textUnpackedBuffer, 0, textLenUnpacked)));
                        }

                        if (result >= 0)
                        {
                            compressedTextDataOffset           = extend(compressedTextDataOffset, textLang + 1);
                            compressedTextDataOffset[textLang] = unpackedBuffer.Length + RCO_HEADER_SIZE;
                            unpackedBuffer = append(unpackedBuffer, textUnpackedBuffer);
                        }

                        if (nextOffset == 0)
                        {
                            break;
                        }
                        skip(nextOffset - 16 - textLenPacked);
                    } while (nextOffset != 0);
                }

                if (result >= 0)
                {
                    buffer = append(buffer, RCO_HEADER_SIZE, unpackedBuffer);
                }
            }

            events = new Dictionary <int, string>();
            if (pEventData != RCO_NULL_PTR && lEventData > 0)
            {
                seek(pEventData);
                while (tell() < pEventData + lEventData)
                {
                    int    index = tell() - pEventData;
                    string s     = readString();
                    if (!string.ReferenceEquals(s, null) && s.Length > 0)
                    {
                        events[index] = s;
                    }
                }
            }

            entries = new Dictionary <int, RCO.RCOEntry>();
            images  = new Dictionary <int, System.Drawing.Bitmap>();
            objects = new Dictionary <int, BaseObject>();

            mainTable = readRCOEntry(pMainTable);
            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("mainTable: {0}", mainTable));
            }

            if (pObjPtrs != RCO_NULL_PTR)
            {
                seek(pObjPtrs);
                for (int i = 0; i < lObjPtrs; i += 4)
                {
                    int objPtr = read32();
                    if (objPtr != 0 && !objects.ContainsKey(objPtr))
                    {
                        Console.WriteLine(string.Format("Object 0x{0:X} not read", objPtr));
                    }
                }
            }

            if (pImgPtrs != RCO_NULL_PTR)
            {
                seek(pImgPtrs);
                for (int i = 0; i < lImgPtrs; i += 4)
                {
                    int imgPtr = read32();
                    if (imgPtr != 0 && !images.ContainsKey(imgPtr))
                    {
                        Console.WriteLine(string.Format("Image 0x{0:X} not read", imgPtr));
                    }
                }
            }

            RCOContext context = new RCOContext(null, 0, events, images, objects);

            foreach (BaseObject @object in objects.Values)
            {
                @object.init(context);
            }
            return(true);
        }
Пример #11
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();
                    }
                }
            }