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 } } } }
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); }
public override void read(RCOContext context) { referenceType = read16(context); unknownShort = read16(context); base.read(context); }
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 } } } }
public virtual void init(RCOContext context) { }
public virtual void read(RCOContext context) { value = read32(context); }
protected internal virtual int read32(RCOContext context) { return(read16(context) | (read16(context) << 16)); }
protected internal virtual int read16(RCOContext context) { return(read8(context) | (read8(context) << 8)); }
protected internal virtual int read8(RCOContext context) { return(context.buffer[context.offset++] & 0xFF); }
/// <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); }
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(); } } }