public static int Play(Stream Stream, Stream OutStream) { var strt = Stream.ReadString(3); Stream.Position = 0; ushort bztmp = 0; if (strt == "ea3") { //we get ea3 header Console.WriteLine("ea3 header\n"); Stream.Position = 0x6; var tmp = Stream.ReadBytes(4); int skipbytes = 0; for (int a0 = 0; a0 < 4; a0++) { skipbytes <<= 7; skipbytes += tmp[a0] & 0x7F; } Stream.Skip(skipbytes); } if (strt == "RIF") //RIFF { //we get RIFF header Console.WriteLine("RIFF header\n"); Stream.Position = 0x10; var fmt_size = Stream.ReadStruct<int>(); var fmt = Stream.ReadStruct<ushort>(); if (fmt != 0xFFFE) { Console.WriteLine("RIFF File fmt error\n"); return -1; } Stream.Skip(0x28); bztmp = Stream.ReadStruct<ushort_be>(); Stream.Skip(fmt_size - 0x2c); //search the data chunk for (int a0 = 0; a0 < 0x100; a0++) { if (Stream.ReadString(4) == "atad") break; } int tmpr = Stream.ReadStruct<int>(); } else { //EA3 block that contains at3+ stream Console.WriteLine("EA3 header"); Stream.Skip(0x22); Console.WriteLine("{0:X}", Stream.Position); bztmp = (ushort)Stream.ReadStruct<ushort_be>(); Stream.Skip(0x3c); } int blocksz = bztmp & 0x3FF; var buf0 = new byte[0x3000]; fixed (byte* buf0_ptr = buf0) { //calculate the frame block size here int block_size = blocksz * 8 + 8; Console.WriteLine("frame_block_size 0x{0:X}\n", block_size); //Console.ReadKey(); //so we make a new at3+ frame decoder MaiAT3PlusFrameDecoder d2 = new MaiAT3PlusFrameDecoder(); Stream.Read(buf0, 0, block_size); int chns = 0; short[] p_buf; int rs; //decode the first frame and get channel num //for (int n = 0; n < block_size; n++) Console.Write(buf0[n]); if ((rs = d2.decodeFrame(buf0_ptr, block_size, out chns, out p_buf)) != 0) Console.WriteLine("decode error {0}", rs); Console.WriteLine("channels: {0}\n", chns); if (chns > 2) Console.WriteLine("warning: waveout doesn't support {0} chns\n", chns); //just waveout //MaiWaveOutI *mwo0 = new MaiWaveOutI(chns, 44100, 16); //mwo0.play(); while (!Stream.Eof()) { Stream.Read(buf0, 0, block_size); //decode frame and get sample data if ((rs = d2.decodeFrame(buf0_ptr, block_size, out chns, out p_buf)) != 0) Console.WriteLine("decode error {0}", rs); //play it OutStream.WriteStructVector(p_buf, 0x800 * chns); //mwo0.enqueue((Mai_I8*)p_buf, 0x800 * chns * 2); } //while (mwo0.getRemainBufSize()) Mai_Sleep(1); return 0; } }
/// <summary> /// ReadMld0. /// </summary> private static NsbmdModel[] ReadMdl0(Stream stream, int blockoffset) { var reader = new EndianBinaryReader(stream, Endianness.LittleEndian); int blocksize; int blockptr; int blocklimit; byte num; uint r; List<NsbmdModel> model = new List<NsbmdModel>(); //////////////////////////////////////////////// // model blockptr = blockoffset + 4; // already read the ID, skip 4 bytes blocksize = reader.ReadInt32(); // block size blocklimit = blocksize + blockoffset; stream.Skip(1); // skip dummy '0' num = reader.ReadByte(); // no of model if (num <= 0) throw new Exception(); for (var i = 0; i < num; ++i) model.Add(new NsbmdModel()); var modelOffset = new UInt32[num]; stream.Skip(10 + 4 + (num * 4)); // skip [char xyz], useless, go straight to model data offset blockptr += 10 + 4; //////////////////////////////////////////////// // copy model dataoffset for (var i = 0; i < num; i++) modelOffset[i] = (uint)(reader.ReadUInt32() + blockoffset); //////////////////////////////////////////////// // copy model names for (var i = 0; i < num; i++) model[i].Name = Utils.ReadNSBMDString(reader); //////////////////////////////////////////////// // parse model data uint totalsize_base = reader.ReadUInt32(); uint codeoffset_base = reader.ReadUInt32(); uint texpaloffset_base = reader.ReadUInt32(); uint polyoffset_base = reader.ReadUInt32(); uint polyend_base = reader.ReadUInt32(); stream.Skip(4); uint matnum = reader.ReadByte(); // no. of material uint polynum = reader.ReadByte(); // no. of polygon byte laststack = reader.ReadByte(); byte unknown1m = reader.ReadByte(); float modelscale = (float)reader.ReadInt32() / 4096f; float boundscale = (float)reader.ReadInt32();// / 4096f; int vertexcount = reader.ReadInt16(); int surfacecount = reader.ReadInt16(); int trianglecount = reader.ReadInt16(); int quadcount = reader.ReadInt16(); model[0].laststackid = laststack; model[0].modelScale = modelscale; model[0].boundScale = boundscale; model[0].boundXmin = (float)NsbmdGlRenderer.sign(reader.ReadInt16(), 16) / 4096f; model[0].boundYmin = (float)NsbmdGlRenderer.sign(reader.ReadInt16(), 16) / 4096f; model[0].boundZmin = (float)NsbmdGlRenderer.sign(reader.ReadInt16(), 16) / 4096f; model[0].boundXmax = (float)NsbmdGlRenderer.sign(reader.ReadInt16(), 16) / 4096f; model[0].boundYmax = (float)NsbmdGlRenderer.sign(reader.ReadInt16(), 16) / 4096f; model[0].boundZmax = (float)NsbmdGlRenderer.sign(reader.ReadInt16(), 16) / 4096f; var polyOffsets = new UInt32[polynum]; var polyDataSize = new UInt32[polynum]; for (var i = 0; i < 1; i++) { var mod = model[i]; stream.Seek(modelOffset[i], SeekOrigin.Begin); // the following variables are all offset values long totalsize; uint codeoffset; UInt32 texpaloffset; UInt32 polyoffset; long polyend; long texoffset; long paloffset; uint modoffset = modelOffset[i]; totalsize = totalsize_base + modoffset; codeoffset = codeoffset_base + modoffset; // additional model data, bone definition etc., just follow NsbmdObject section texpaloffset = texpaloffset_base + modoffset; polyoffset = polyoffset_base + modoffset; polyend = polyend_base + modoffset; stream.Skip(5 * 4 + 4 + 2 + 38); // go straight to NsbmdObject //////////////////////////////////////////////// // NsbmdObject section UInt32 objnum; int objdatabase; UInt32[] objdataoffset; UInt32[] objdatasize; objdatabase = (int)stream.Position; stream.Skip(1); // skip dummy '0' objnum = reader.ReadByte(); // no of NsbmdObject stream.Skip(14 + (objnum * 4)); // skip bytes, go striaght to NsbmdObject data offset for (i = 0; i < objnum; ++i) mod.Objects.Add(new NsbmdObject()); objdataoffset = new UInt32[objnum]; objdatasize = new UInt32[objnum]; for (var j = 0; j < objnum; j++) objdataoffset[j] = (UInt32)(reader.ReadUInt32() + objdatabase); for (var j = 0; j < objnum - 1; j++) objdatasize[j] = objdataoffset[j + 1] - objdataoffset[j]; objdatasize[objnum - 1] = (UInt32)(codeoffset - objdataoffset[objnum - 1]); //////////////////////////////////////////////// // copy NsbmdObject names for (var j = 0; j < objnum; j++) { mod.Objects[j].Name = Utils.ReadNSBMDString(reader); // TO DEBUG Console.WriteLine(mod.Objects[j].Name); } //////////////////////////////////////////////// // parse NsbmdObject information for (var j = 0; j < objnum; j++) { if (objdatasize[j] <= 4) continue; stream.Seek(objdataoffset[j], SeekOrigin.Begin); ParseNsbmdObject(reader, mod.Objects[j], modelscale); } //////////////////////////////////////////////// // material section stream.Seek(texpaloffset, SeekOrigin.Begin); // now get the texture and palette offset texoffset = reader.ReadUInt16() + texpaloffset; paloffset = reader.ReadUInt16() + texpaloffset; // allocate memory for material for (var j = 0; j <= matnum; j++)//i <= matnum; ++i) mod.Materials.Add(new NsbmdMaterial()); //////////////////////////////////////////////// // parse material definition // defines RotA material by pairing texture and palette stream.Seek(16 + (matnum * 4), SeekOrigin.Current); // go straight to material data offset for (var j = 0; j < matnum; j++) // TODO: BAD! { mod.Materials[j] = new NsbmdMaterial(); blockptr = (int)stream.Position; r = reader.ReadUInt32() + texpaloffset/* + 4 + 12*/;// skip 18 bytes (+ 2 bytes for texoffset, 2 bytes for paloffset) stream.Seek(r, SeekOrigin.Begin); //mod.Materials[j].repeat = reader.ReadByte(); //reader.BaseStream.Position -= 1; int dummy = reader.ReadInt16(); int sectionSize = reader.ReadInt16(); int unknown1 = reader.ReadInt32();//DifAmbColors int unknown2 = reader.ReadInt32();//SpeEmiColors int unknown3 = reader.ReadInt32();//PolyAttrib int constant2 = reader.ReadInt32();//PolyAttrib Mask int texVramOffset = reader.ReadInt16(); int texImageParam = reader.ReadInt16(); int constant3 = reader.ReadInt32();//texImageParam Mask int constant4 = reader.ReadInt32(); int matWidth = reader.ReadInt16(); int matHeight = reader.ReadInt16(); int unknown4 = reader.ReadInt16(); int unknown5 = reader.ReadInt16(); int unknown6 = reader.ReadInt32(); //int unknown7 = reader.ReadInt32();//if srt S Scale //int unknown8 = reader.ReadInt32();//if srt T Scale //int unknown9 = reader.ReadInt16();//if srt & 60 Rot //int unknownA = reader.ReadInt16();//if srt & 60 S Trans //int unknownB = reader.ReadInt16();//if srt & 60 T Trans //uint polyParam = reader.ReadUInt32(); //reader.ReadInt16(); //ushort texImageParam = reader.ReadUInt16(); mod.Materials[j].repeatS = texImageParam & 1; mod.Materials[j].repeatT = texImageParam >> 1 & 1; mod.Materials[j].flipS = texImageParam >> 2 & 1; mod.Materials[j].flipT = texImageParam >> 3 & 1; /*if ((texImageParam >> 14 & 0x03) == 1) { mod.Materials[j].scaleS = /*1 << /(texImageParam >> 12 & 2) + 1; mod.Materials[j].scaleT = /*1 << /(texImageParam >> 14 & 2) + 1; } else { mod.Materials[j].scaleS = 1; mod.Materials[j].scaleT = 1; }*/ switch (texImageParam >> 14 & 0x03) { case 0: mod.Materials[j].scaleS = 1; mod.Materials[j].scaleT = 1; mod.Materials[j].transS = 0; mod.Materials[j].transT = 0; break; case 1: { int sscale = (int)reader.ReadInt32();// >> 0 & 0xFFFFFFFF; sscale = NsbmdGlRenderer.sign(sscale, 32); int tscale = (int)reader.ReadInt32();// >> 0 & 0xFFFFFFFF; tscale = NsbmdGlRenderer.sign(tscale, 32); //int strans = (int)unknown2 >> 0 & 0xFFFF; //int ttrans = (int)unknown2 >> 16 & 0xFFFF; mod.Materials[j].scaleS = (float)sscale / 4096f; mod.Materials[j].scaleT = (float)tscale / 4096f; if (sectionSize >= 60) { mod.Materials[j].rot = (float)reader.ReadInt16() / 4096f; mod.Materials[j].transS = (float)reader.ReadInt16() / 4096f; mod.Materials[j].transT = (float)reader.ReadInt16() / 4096f; } else { } break; } case 2: case 3: mod.Materials[j].mtx = new float[16]; for (int k = 0; k < 16; k++) { mod.Materials[j].mtx[k] = reader.ReadInt32(); } break; default: break; // throw new Exception(String.Format("BMD: unsupported texture coord transform mode {0}", matgroup.m_TexParams >> 30)); } mod.Materials[j].width = matWidth; mod.Materials[j].height = matHeight; int width = 8 << (texImageParam >> 4 & 7); int height = 8 << (texImageParam >> 7 & 7); //int m_DifAmbColors = reader.ReadInt32(); //int m_SpeEmiColors = reader.ReadInt32(); mod.Materials[j].DiffuseColor = SM64DSe.Helper.BGR15ToColor((ushort)(unknown1 & 0x7FFF)); mod.Materials[j].AmbientColor = SM64DSe.Helper.BGR15ToColor((ushort)(unknown1 >> 16 & 0x7FFF)); mod.Materials[j].SpecularColor = SM64DSe.Helper.BGR15ToColor((ushort)(unknown2 & 0x7FFF)); mod.Materials[j].EmissionColor = SM64DSe.Helper.BGR15ToColor((ushort)(unknown2 >> 16 & 0x7FFF)); int a = (int)((unknown3 >> 16) & 31); mod.Materials[j].Alpha = a;//a * 2 + 1;//a * 2 + (a + 31) / 32; mod.Materials[j].PolyAttrib = (uint)unknown3; mod.Materials[j].diffuseColor = (unknown1 >> 15 & 1) == 1; mod.Materials[j].shine = (unknown2 >> 15 & 1) == 1; stream.Seek(blockptr + 4, SeekOrigin.Begin); } for (var j = 0; j < matnum; j++) { mod.Materials[j].MaterialName = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // now go to read the texture definition stream.Seek(texoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' int texnum = reader.ReadByte(); Debug.Assert(texnum <= matnum); Console.WriteLine(String.Format("texnum: {0}", texnum)); if (texnum > 0) { stream.Seek(14 + (texnum * 4), SeekOrigin.Current); // go straight to data offsets for (var j = 0; j < texnum; j++) { Int32 flags = reader.ReadInt32(); int numPairs = flags >> 16 & 0xf; int dummy = flags >> 24 & 0xf; blockptr = (int)stream.Position; stream.Seek((flags & 0xffff) + texpaloffset, SeekOrigin.Begin); NSBMDTexture t = new NSBMDTexture(); for (int k = 0; k < numPairs; k++) { uint texmatid = reader.ReadByte(); mod.tex_mat.Add((int)texmatid); mod.Materials[j].texmatid.Add(texmatid); t.texmatid.Add(texmatid); } mod.Textures.Add(t); stream.Seek(blockptr, SeekOrigin.Begin); } for (var j = 0; j < texnum; j++) // copy texture names { NsbmdMaterial mat = mod.Materials[j]; mat.texname = Utils.ReadNSBMDString(reader); reader.BaseStream.Position -= 16; mod.Textures[j].texname = Utils.ReadNSBMDString(reader); Console.WriteLine("tex (matid={0}): {1}", mat.texmatid, mat.texname); } } //////////////////////////////////////////////// // now go to read the palette definition stream.Seek(paloffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' int palnum = reader.ReadByte(); // no of palette definition Debug.Assert(palnum <= matnum); // may not always hold? Console.WriteLine("DEBUG: palnum = {0}", palnum); if (palnum > 0) { stream.Seek(14 + (palnum * 4), SeekOrigin.Current); // go straight to data offsets for (var j = 0; j < palnum; j++) // matching palette with material { Int32 flags = reader.ReadInt32(); int numPairs = flags >> 16 & 0xf; int dummy = flags >> 24 & 0xf; blockptr = (int)stream.Position; stream.Seek((flags & 0xffff) + texpaloffset, SeekOrigin.Begin); NSBMDPalette t = new NSBMDPalette(); for (int k = 0; k < numPairs; k++) { uint texmatid = reader.ReadByte(); mod.tex_mat.Add((int)texmatid); mod.Materials[j].texmatid.Add(texmatid); t.palmatid.Add(texmatid); } mod.Palettes.Add(t); stream.Seek(blockptr, SeekOrigin.Begin); } for (var j = 0; j < palnum; j++) // copy palette names { int palmatid = (int)mod.Materials[j].palmatid; mod.Materials[palmatid].palname = Utils.ReadNSBMDString(reader); reader.BaseStream.Position -= 16; mod.Palettes[j].palname = Utils.ReadNSBMDString(reader); // TO DEBUG Console.WriteLine("pal (matid={0}): {1}", palmatid, mod.Materials[palmatid].palname); } } //////////////////////////////////////////////// // Polygon stream.Seek(polyoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' r = reader.ReadByte(); // no of polygon Console.WriteLine("DEBUG: polynum = {0}", polynum); for (var j = 0; j <= polynum; j++) { mod.Polygons.Add(new NsbmdPolygon()); } stream.Skip(14 + (polynum * 4)); // skip bytes, go straight to data offset for (var j = 0; j < polynum; j++) polyOffsets[j] = reader.ReadUInt32() + polyoffset; try { for (var j = 0; j < polynum; j++) // copy polygon names { mod.Polygons[j].Name = Utils.ReadNSBMDString(reader); Console.WriteLine(mod.Polygons[j].Name); } } catch { } //////////////////////////////////////////////// // now go to the polygon data, there is RotA 16-byte-header before geometry commands for (var j = 0; j < polynum; j++) { var poly = mod.Polygons[j]; ////////////////////////////////////////////////////////// poly.MatId = -1; // DEFAULT: indicate no associated material ////////////////////////////////////////////////////////// //stream.Seek(polyOffsets[j] + 8, SeekOrigin.Begin); // skip 8 unknown bytes short dummy = reader.ReadInt16(); short headerSize = reader.ReadInt16(); int unknown2 = reader.ReadInt32(); polyOffsets[j] += reader.ReadUInt32(); polyDataSize[j] = reader.ReadUInt32(); //printf( "poly %2d '%-16s': dataoffset: %08x datasize %08x\n", j, poly->polyname, poly->dataoffset, poly->datasize ); } //} //////////////////////////////////////////////// // read the polygon data into memory for (var j = 0; j < polynum; j++) { var poly = mod.Polygons[j]; stream.Seek(polyOffsets[j], SeekOrigin.Begin); poly.PolyData = reader.ReadBytes((int)polyDataSize[j]); } //} //////////////////////////////////////////////// // decode the additional model data DecodeCode(stream, codeoffset, texpaloffset, mod, laststack); } //modelnum = num; return model.ToArray(); }
/// <summary> /// ID3v2.3/2.4 タグから画像データの Stream を取り出します /// </summary> private Stream _ReadPictureInFrameHeaders(Stream file) { var count = 1; while (true) { // Frame Name var frameName = file.ReadAsAsciiString(4); // 有効な Frame Name であるかどうかを示す var validName = Regex.IsMatch(frameName, "^[A-Z0-9]+$"); // 無効な Frame Name であれば、ループ終了 if (!validName) { break; } Debug.WriteLine($"frameName = {frameName}"); var frameSize = file.ReadAsUInt(); // フラグ読み飛ばし file.Skip(2); // APIC Frame の判定 if (frameName == "APIC") { var removeCount = 0; file.Skip(1); removeCount += 1; while (file.ReadAsByte() != 0x00U) { removeCount++; } file.Skip(1); removeCount += 1; while (file.ReadAsByte() != 0x00U) { removeCount++; } var imageSource = file.ReadAsByteList((int)frameSize - removeCount); return(new MemoryStream(imageSource.ToArray())); } // PIC Frame でないため、フレーム自体を読み飛ばす file.Skip((int)frameSize); if (count > 74) { throw new InvalidDataException("フレーム数が正常な範囲を超えました"); } count++; } return(null); }
/// <summary> /// Load materials in stream. /// </summary> /// <param name="stream">Stream to use.</param> /// <returns>Material definitions.</returns> public static IEnumerable <NsbmdMaterial> ReadTex0(Stream stream, int blockoffset, out int ptexnum, out int ppalnum, out List <NSBMDTexture> texs, out List <NSBMDPalette> pals) { EndianBinaryReader reader = new EndianBinaryReader(stream, Endianness.LittleEndian); UInt32 blocksize, blockptr, blocklimit; int texnum; UInt32 texdataoffset; int texdatasize; UInt32 sptexoffset; // for 4x4 compressed texels only int sptexsize; // for 4x4 compressed texels only UInt32 spdataoffset; // for 4x4 compressed texels only int palnum; UInt32 paldefoffset; UInt32 paldataoffset; int paldatasize; NsbmdMaterial[] material = null; int i, j; texs = new List <NSBMDTexture>(); pals = new List <NSBMDPalette>(); blockptr = (uint)(blockoffset + 4); // already read the block ID, so skip 4 bytes blocksize = reader.ReadUInt32(); // block size blocklimit = (uint)(blocksize + blockoffset); Console.WriteLine("DEBUG: blockoffset = {0}, blocksize = {1}", blockoffset, blocksize); stream.Skip(4); // skip 4 padding 0s texdatasize = reader.ReadUInt16() << 3; // total texture data size div8 stream.Skip(6); // skip 6 bytes texdataoffset = (uint)(reader.ReadUInt32() + blockoffset); stream.Skip(4); // skip 4 padding 0s sptexsize = reader.ReadUInt16() << 3; // for format 5 4x4-texel, data size div8 stream.Skip(6); // skip 6 bytesmhm sptexoffset = (uint)(reader.ReadUInt32() + blockoffset); // for format 5 4x4-texel, data offset spdataoffset = (uint)(reader.ReadUInt32() + blockoffset); // for format 5 4x4-texel, palette info stream.Skip(4); // skip 4 bytes paldatasize = reader.ReadUInt16() << 3; // total palette data size div8 stream.Skip(2); // skip 2 bytes paldefoffset = (uint)(reader.ReadUInt32() + blockoffset); paldataoffset = (uint)(reader.ReadUInt32() + blockoffset); // printf( "texdataoffset = %08x texdatasize = %08x\n", texdataoffset, texdatasize ); // printf( "sptexoffset = %08x sptexsize = %08x spdataoffset = %08x\n", sptexoffset, sptexsize, spdataoffset ); // printf( "paldataoffset = %08x paldatasize = %08x\n", paldataoffset, paldatasize ); //////////////////////////////////////////////// // texture definition stream.Skip(1); // skip dummy '0' texnum = reader.ReadByte(); // no of texture blockptr = (uint)stream.Position; stream.Seek(paldefoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' palnum = reader.ReadByte(); // no of palette stream.Seek(blockptr, SeekOrigin.Begin); Console.WriteLine("texnum = {0}, palnum = {1}", texnum, palnum); // allocate memory for material, great enough to hold all texture and palette material = new NsbmdMaterial[(texnum > palnum ? texnum : palnum)]; for (i = 0; i < material.Length; i++) { material[i] = new NsbmdMaterial(); } stream.Skip(14 + (texnum * 4)); // go straight to texture info for (i = 0; i < texnum; i++) { UInt32 offset; int param; int format; int width; int height; var mat = material[i]; offset = (uint)(reader.ReadUInt16() << 3); param = reader.ReadUInt16(); // texture parameter stream.Skip(4); // skip 4 bytes format = (param >> 10) & 7; // format 0..7, see DSTek width = 8 << ((param >> 4) & 7); height = 8 << ((param >> 7) & 7); mat.color0 = (param >> 13) & 1; if (format == 5) { mat.texoffset = offset + sptexoffset; // 4x4-Texel Compressed Texture } else { mat.texoffset = offset + texdataoffset; } mat.format = format; mat.width = width; mat.height = height; NSBMDTexture t = new NSBMDTexture(); t.format = format; t.width = width; t.height = height; t.color0 = (param >> 13) & 1; texs.Add(t); } //////////////////////////////////////////// // copy texture names for (i = 0; i < texnum; i++) { material[i].texname = Utils.ReadNSBMDString(reader); reader.BaseStream.Position -= 16; texs[i].texname = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // calculate each texture's size for (i = 0; i < texnum; i++) { int[] bpp = { 0, 8, 2, 4, 8, 2, 8, 16 }; var mat = material[i]; mat.texsize = (uint)(mat.width * mat.height * bpp[mat.format] / 8); Console.WriteLine("tex {0} '{1}': offset = {2} size = {3} [W,H] = [{4}, {5}]", i, mat.texname, mat.texoffset, mat.texsize, mat.width, mat.height); texs[i].texsize = (uint)(mat.width * mat.height * bpp[mat.format] / 8); } //////////////////////////////////////////////// // palette definition stream.Seek(paldefoffset + 2, SeekOrigin.Begin); // skip palnum, already read stream.Seek(14 + (palnum * 4), SeekOrigin.Current); // go straight to palette info for (i = 0; i < palnum; i++) { uint curOffset = (uint)((reader.ReadUInt16() << 3) + paldataoffset); stream.Seek(2, SeekOrigin.Current); // skip 2 bytes material[i].paloffset = curOffset; NSBMDPalette t = new NSBMDPalette(); t.paloffset = curOffset; pals.Add(t); } //////////////////////////////////////////////// // copy palette names for (i = 0; i < palnum; i++) { var mat = material[i]; mat.palname = Utils.ReadNSBMDString(reader); reader.BaseStream.Position -= 16; pals[i].palname = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // calculate each palette's size // assume the palettes are stored sequentially /*for (i = 0; i < palnum - 1; i++) * { * int r; * var mat = material[i]; * r = i; * try { while (material[r].paloffset == mat.paloffset) r++; } * catch { } * // below is RotA stupid way to calculate the size of palette: next's offset - current's offset * // it works most of the time * if (r != palnum) * { * mat.palsize = material[r].paloffset - mat.paloffset; * pals[i].palsize = material[r].paloffset - mat.paloffset; * } * else * { * mat.palsize = blocklimit - mat.paloffset; * pals[i].palsize = blocklimit - mat.paloffset; * } * //printf("pal '%s' size = %d\n", mat->palname, mat->palsize); * } * material[i].palsize = blocklimit - material[i].paloffset; * pals[i].palsize = blocklimit - material[i].paloffset;*/ List <int> offsets = new List <int>(); for (int k = 0; k < pals.Count; k++) { if (!offsets.Contains((int)pals[k].paloffset)) { offsets.Add((int)pals[k].paloffset); } } offsets.Add((int)blocklimit); offsets.Sort(); for (int k = 0; k < pals.Count; k++) { int pallength; int l = -1; do { l++; }while (offsets[l] - pals[k].paloffset <= 0);//nsbtx.PalInfo.infoBlock.PalInfo[i + j].Palette_Offset - nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset == 0) pallength = offsets[l] - (int)pals[k].paloffset; //RGBA[] c_ = pals[k].paldata; //List<RGBA> c = new List<RGBA>(); //c.AddRange(pals[k].paldata.Take(pallength / 2)); //pals[k].paldata = c.ToArray(); pals[k].palsize = (uint)pallength; material[k].palsize = (uint)pallength; } //////////////////////////////////////////////// // traverse each texture for (i = 0; i < texnum; i++) { var mat = material[i]; stream.Seek(mat.texoffset, SeekOrigin.Begin); //////////////////////////////////////////////// // read texture into memory byte[] by = reader.ReadBytes((int)mat.texsize); mat.texdata = by; texs[i].texdata = by; Console.WriteLine("DEBUG: texoffset = {0}, texsize = {1}", mat.texoffset, mat.texsize); //////////////////////////////////////////////// // additional data for format 5 4x4 compressed texels if (mat.format == 5) { UInt32 r = mat.texsize / 2;//>> 1; stream.Seek(spdataoffset + (mat.texoffset - sptexoffset) / 2, SeekOrigin.Begin); by = reader.ReadBytes((int)r); mat.spdata = by; texs[i].spdata = by; Console.WriteLine("DEBUG: 4x4-texel spdataoffset = {0}, spdatasize = {1}", spdataoffset, r); //spdataoffset += r; } } //////////////////////////////////////////////// // traverse each palette for (i = 0; i < palnum; i++) { try { NsbmdMaterial mat = material[i]; var palentry = mat.palsize >> 1; RGBA[] rgbq = new RGBA[palentry]; Console.WriteLine("DEBUG: converting pal '{0}', palentry = {1}", mat.palname, palentry); stream.Seek(mat.paloffset, SeekOrigin.Begin); for (j = 0; j < palentry; j++) { UInt16 p = reader.ReadUInt16(); rgbq[j].R = (byte)(((p >> 0) & 0x1f) << 3); // red rgbq[j].G = (byte)(((p >> 5) & 0x1f) << 3); // green rgbq[j].B = (byte)(((p >> 10) & 0x1f) << 3); // blue //rgbq[j].RotA = (p&0x8000) ? 0xff : 0; rgbq[j].A = (p & 0x8000) == 0 ? (byte)0xff : (byte)0; //0xff; // alpha } mat.paldata = rgbq; pals[i].paldata = rgbq; } catch { } } ptexnum = texnum; ppalnum = palnum; return(material); }
public static Stream SkipStringUnicode(this Stream stream) { stream.Skip(stream.ReadInt32() * -2); return(stream); }
/// <summary> /// Skips <paramref name="count"/> number of bytes in the stream. /// </summary> /// <param name="stream">The stream to skip through.</param> /// <param name="count">The number of bytes to skip.</param> /// <returns>The number of bytes, actually skipped.</returns> /// /// <remarks> /// This method utilizes <see cref="Stream.Seek(long, SeekOrigin)"/> if it's <see cref="Stream.CanSeek"/> is /// true. Otherwise it reads bytes to a buffer of size 4096 until <paramref name="count"/> is reached. /// </remarks> /// /// <exception cref="ArgumentNullException"> /// <paramref name="stream"/> is null. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="count"/> is negative. /// </exception> /// <exception cref="IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="NotSupportedException"> /// The stream does not support seeking or reading. /// </exception> /// <exception cref="ObjectDisposedException"> /// The stream is closed. /// </exception> public static int Skip(this Stream stream, int count) { return(stream.Skip(count, 4096)); }
private static bool Whitespace(Stream data) { return(data.Skip(" \t\r\n") > 0); }
public override void Write(Stream output, IDirectory inputDirectory) { const uint xorMask1 = 0x41441043; const uint xorMask2 = 0x11C22050; const uint xorMask3 = 0xD05608C3; const uint xorMask4 = 0x532C7319; const int headerSize = 32; int shift = (Flags & 0x800) > 0 ? 12 : 10; int alignment = 1 << shift; BinaryWriter writer = new BinaryWriter(output, Encoding.Default, true); long headerPosition = output.Position; output.Skip(headerSize); long tableOffset = output.Position; output.Skip(8 * Entries.Count); //long unknownTableOffset = output.Position; //output.Skip(16 * UnknownEntries.Count); output.AlignWrite(alignment, 0x00); long dataOffset = output.Position; ulong[] sections = new ulong[Entries.Count]; for (int i = 0; i < Entries.Count; i++) { QarEntry entry = Entries[i]; entry.CalculateHash(); ulong section = (ulong) (output.Position >> shift) << 40 | (entry.Hash & 0xFF) << 32 | entry.Hash >> 32 & 0xFFFFFFFFFF; sections[i] = section; entry.Write(output, inputDirectory); output.AlignWrite(alignment, 0x00); } long endPosition = output.Position; uint endPositionHead = (uint) (endPosition >> shift); output.Position = headerPosition; writer.Write(QarMagicNumber); // SQAR writer.Write(Flags ^ xorMask1); writer.Write((uint)Entries.Count ^ xorMask2); writer.Write(xorMask3); // unknown count (not saved in the xml and output directory) writer.Write(endPositionHead ^ xorMask4); writer.Write((uint)dataOffset ^ xorMask1); writer.Write(1 ^ xorMask1); writer.Write(0 ^ xorMask2); output.Position = tableOffset; byte[] encryptedSectionsData = EncryptSections(sections); writer.Write(encryptedSectionsData); output.Position = endPosition; }
static void ParseFileList(Stream decompressedStream, long dataStreamLength) { var binaryReader = new BinaryReader(decompressedStream); var fileNumber = binaryReader.ReadUInt16(); filesInfos = new List <FileInfo>(); decompressedStream.Skip(2); // Unknown. Maybe fileNumber is 4 bytes? Bio.Cout("\n" + fileNumber + " files in installer\n"); installerVersion = GetInstallerVersion(decompressedStream, binaryReader, fileNumber, dataStreamLength); Func <Stream, BinaryReader, FileInfo> parsingFunction = TryParse30; if (installerVersion >= 40) { parsingFunction = TryParse40; } else if (installerVersion >= 35) { parsingFunction = TryParse35; } else if (installerVersion >= 30) { parsingFunction = TryParse30; } else if (installerVersion >= 20) { parsingFunction = TryParse20; } else { Bio.Error($"Unsupported installer version {installerVersion}. Please send a bug report if you want the file to be supported in a future version.", Bio.EXITCODE.NOT_SUPPORTED); } Bio.Cout($"\nStarting extraction as installer version {installerVersion}\n"); for (var i = 0; i < fileNumber; i++) { var fileInfo = parsingFunction(decompressedStream, binaryReader); Bio.Debug(string.Format("Node {0} at offset {1}, size: {2}, end: {3}", i, fileInfo.nodeStart, fileInfo.nodeSize, fileInfo.nodeEnd)); if (!fileInfo.IsValid(dataStreamLength)) { Bio.Error($"The file could not be extracted as installer version {installerVersion}. Please try to manually set the correct version using the command line switch -v.", Bio.EXITCODE.RUNTIME_ERROR); } #if DEBUG if (dumpBlocks) { using (var ms = new MemoryStream((int)fileInfo.nodeSize)) { decompressedStream.Position = fileInfo.nodeStart; decompressedStream.Copy(ms, (int)fileInfo.nodeSize); decompressedStream.Position = fileInfo.nodeEnd; SaveToFile(ms, "FileMeta" + i + ".bin"); } } #endif if (fileInfo.type != 0) { decompressedStream.Position = fileInfo.nodeEnd; continue; } filesInfos.Add(fileInfo); Bio.Debug(fileInfo); } }
private static OperatorType Operator(Stream data) { OperatorType result = OperatorType.None; char c = data.Peek(); if (c != '=' && c != '*' && c != '/' && c != '+' && c != '-' && c != '!' && c != '?' && c != '<' && c != '>' && c != '|' && c != ':' && c != '~' && c != '%' && c != '&' && c != '^') { return(result); } long streamPos = data.Position; data.Get(); long last = data.Skip("=+-*/&|^<>"); if (last > 2) { last = 2; } last++; data.Position = streamPos; string streamBuff = data.Read(last); switch (c) { case ':': { result = OperatorType.AlternateOperator; break; } case '!': // != if (last > 1 && streamBuff == "!=") { result = OperatorType.NEqual; break; } // ! else { result = OperatorType.Not; break; } case '=': if (last > 1 && streamBuff == "==") { result = OperatorType.Equal; } break; case '*': { result = OperatorType.Mult; break; } case '/': { result = OperatorType.Div; break; } case '+': // ++ if (last > 1 && streamBuff == "++") { result = OperatorType.Increment; break; } // + else { result = OperatorType.Add; break; } case '-': // -- if (last > 1 && streamBuff == "--") { result = OperatorType.Decrement; break; } // - else { result = OperatorType.Sub; break; } case '%': { result = OperatorType.Mod; break; } case '&': // && if (last > 1 && streamBuff == "&&") { result = OperatorType.LogicalAnd; break; } // & else { result = OperatorType.BitAnd; break; } case '|': // || if (last > 1 && streamBuff == "||") { result = OperatorType.LogicalInclusiveOr; break; } // | else { result = OperatorType.BitInclusiveOr; break; } case '^': // ^^ if (last > 1 && streamBuff == "^^") { result = OperatorType.LogicalExclusiveOr; break; } // ^ else { result = OperatorType.BitExclusiveOr; break; } case '<': // << if (last > 1 && streamBuff == "<<") { result = OperatorType.LBitShift; break; } // <= else if (last > 1 && streamBuff == "<=") { result = OperatorType.LeftRelationEqual; break; } // < else { result = OperatorType.LeftRelation; break; } case '>': // >> if (last > 1 && streamBuff == ">>") { result = OperatorType.RBitShift; break; } // >= else if (last > 1 && streamBuff == ">=") { result = OperatorType.RightRelationEqual; break; } // > else { result = OperatorType.RightRelation; break; } case '~': { // ~ result = OperatorType.ReverseOperator; break; } case '?': { // ? result = OperatorType.SelectOperator; break; } } data.Position = streamPos; return(result); }
public static bool SimpleWhitespace(Stream data) { return(data.Skip(" \t\r\n") > 0); }
/// <summary> /// Load materials in stream. /// </summary> /// <param name="stream">Stream to use.</param> /// <returns>Material definitions.</returns> public static IEnumerable<NsbmdMaterial> ReadTex0(Stream stream, int blockoffset, out int ptexnum, out int ppalnum) { BinaryReader reader = new BinaryReader(stream); UInt32 blocksize, blockptr, blocklimit; int texnum; UInt32 texdataoffset; int texdatasize; UInt32 sptexoffset; // for 4x4 compressed texels only int sptexsize; // for 4x4 compressed texels only UInt32 spdataoffset; // for 4x4 compressed texels only int palnum; UInt32 paldefoffset; UInt32 paldataoffset; int paldatasize; NsbmdMaterial[] material = null; int i, j; blockptr = (uint) (blockoffset + 4); // already read the block ID, so skip 4 bytes blocksize = reader.ReadUInt32(); // block size blocklimit = (uint) (blocksize + blockoffset); Console.WriteLine("DEBUG: blockoffset = {0}, blocksize = {1}", blockoffset, blocksize); stream.Skip(4); // skip 4 padding 0s texdatasize = reader.ReadUInt16() << 3; // total texture data size div8 stream.Skip(6); // skip 6 bytes texdataoffset = (uint) (reader.ReadUInt32() + blockoffset); stream.Skip(4); // skip 4 padding 0s sptexsize = reader.ReadUInt16() << 3; // for format 5 4x4-texel, data size div8 stream.Skip(6); // skip 6 bytesmhm sptexoffset = (uint) (reader.ReadUInt32() + blockoffset); // for format 5 4x4-texel, data offset spdataoffset = (uint) (reader.ReadUInt32() + blockoffset); // for format 5 4x4-texel, palette info stream.Skip(4); // skip 4 bytes paldatasize = reader.ReadUInt16() << 3; // total palette data size div8 stream.Skip(2); // skip 2 bytes paldefoffset = (uint) (reader.ReadUInt32() + blockoffset); paldataoffset = (uint) (reader.ReadUInt32() + blockoffset); // printf( "texdataoffset = %08x texdatasize = %08x\n", texdataoffset, texdatasize ); // printf( "sptexoffset = %08x sptexsize = %08x spdataoffset = %08x\n", sptexoffset, sptexsize, spdataoffset ); // printf( "paldataoffset = %08x paldatasize = %08x\n", paldataoffset, paldatasize ); //////////////////////////////////////////////// // texture definition stream.Skip(1); // skip dummy '0' texnum = reader.ReadByte(); // no of texture blockptr = (uint) stream.Position; stream.Seek(paldefoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' palnum = reader.ReadByte(); // no of palette stream.Seek(blockptr, SeekOrigin.Begin); Console.WriteLine("texnum = {0}, palnum = {1}", texnum, palnum); // allocate memory for material, great enough to hold all texture and palette material = new NsbmdMaterial[(texnum > palnum ? texnum : palnum)]; for (i = 0; i < material.Length; ++i) material[i] = new NsbmdMaterial(); stream.Skip(14 + (texnum*4)); // go straight to texture info for (i = 0; i < texnum; i++) { UInt32 offset; int param; int format; int width; int height; var mat = material[i]; offset = (uint) (reader.ReadUInt16() << 3); param = reader.ReadUInt16(); // texture parameter stream.Skip(4); // skip 4 bytes format = (param >> 10) & 7; // format 0..7, see DSTek width = 8 << ((param >> 4) & 7); height = 8 << ((param >> 7) & 7); mat.color0 = (param >> 13) & 1; if (format == 5) mat.texoffset = offset + sptexoffset; // 4x4-Texel Compressed Texture else mat.texoffset = offset + texdataoffset; mat.format = format; mat.width = width; mat.height = height; } //////////////////////////////////////////// // copy texture names for (i = 0; i < texnum; i++) { material[i].texname = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // calculate each texture's size for (i = 0; i < texnum; i++) { int[] bpp = {0, 8, 2, 4, 8, 2, 8, 16}; var mat = material[i]; mat.texsize = (uint) (mat.width*mat.height*bpp[mat.format]/8); Console.WriteLine("tex {0} '{1}': offset = {2} size = {3} [W,H] = [{4}, {5}]", i, mat.texname, mat.texoffset, mat.texsize, mat.width, mat.height); } //////////////////////////////////////////////// // palette definition stream.Seek(paldefoffset + 2, SeekOrigin.Begin); // skip palnum, already read stream.Seek(14 + (palnum*4), SeekOrigin.Current); // go straight to palette info for (i = 0; i < palnum; i++) { uint curOffset = (uint) ((reader.ReadUInt16() << 3) + paldataoffset); stream.Seek(2, SeekOrigin.Current); // skip 2 bytes material[i].paloffset = curOffset; } //////////////////////////////////////////////// // copy palette names for (i = 0; i < palnum; i++) { var mat = material[i]; mat.palname = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // calculate each palette's size // assume the palettes are stored sequentially for (i = 0; i < palnum - 1; i++) { var mat = material[i]; var r = i + 1; while (material[r].paloffset == mat.paloffset) r++; // below is RotA stupid way to calculate the size of palette: next's offset - current's offset // it works most of the time if (r != palnum) mat.palsize = material[r].paloffset - mat.paloffset; else mat.palsize = blocklimit - mat.paloffset; //printf("pal '%s' size = %d\n", mat->palname, mat->palsize); } material[i].palsize = blocklimit - material[i].paloffset; //////////////////////////////////////////////// // traverse each texture for (i = 0; i < texnum; i++) { var mat = material[i]; stream.Seek(mat.texoffset, SeekOrigin.Begin); //////////////////////////////////////////////// // read texture into memory mat.texdata = reader.ReadBytes((int) mat.texsize); Console.WriteLine("DEBUG: texoffset = {0}, texsize = {1}", mat.texoffset, mat.texsize); //////////////////////////////////////////////// // additional data for format 5 4x4 compressed texels if (true) //(mat.format == 5) { UInt32 r = mat.texsize >> 1; stream.Seek(spdataoffset, SeekOrigin.Begin); mat.spdata = reader.ReadBytes((int) r); Console.WriteLine("DEBUG: 4x4-texel spdataoffset = {0}, spdatasize = {1}", spdataoffset, r); spdataoffset += r; } } //////////////////////////////////////////////// // traverse each palette for (i = 0; i < palnum; i++) { try { NsbmdMaterial mat = material[i]; var palentry = mat.palsize >> 1; RGBA[] rgbq = new RGBA[palentry]; Console.WriteLine("DEBUG: converting pal '{0}', palentry = {1}", mat.palname, palentry); stream.Seek(mat.paloffset, SeekOrigin.Begin); for (j = 0; j < palentry; j++) { UInt16 p = reader.ReadUInt16(); rgbq[j].R = (byte) (((p >> 0) & 0x1f) << 3); // red rgbq[j].G = (byte) (((p >> 5) & 0x1f) << 3); // green rgbq[j].B = (byte) (((p >> 10) & 0x1f) << 3); // blue //rgbq[j].RotA = (p&0x8000) ? 0xff : 0; rgbq[j].A = 0xff; // alpha } mat.paldata = rgbq; } catch { } } ptexnum = texnum; ppalnum = palnum; return material; }
public static Stream SkipStringASCII(this Stream stream) { stream.Skip(stream.ReadInt32()); return(stream); }
/** * Reads the LM file header * * @param stream the data stream of the LM file * @throws java.io.IOException */ private void ReadHeader(Stream stream) { var headerLength = ReadInt(stream, _bigEndian); if ((headerLength != DarpaTgHeader.Length + 1) && (headerLength != DarpaQgHeader.Length + 1) && (headerLength != DarpaNgHeader.Length - 1)) { // not big-endian headerLength = Utilities.SwapInteger(headerLength); if (headerLength == (DarpaTgHeader.Length + 1) || headerLength == (DarpaQgHeader.Length + 1) || headerLength == (DarpaNgHeader.Length - 1)) { _bigEndian = false; // System.out.println("Little-endian"); } else { throw new Exception("Bad binary LM file magic number: " + headerLength + ", not an LM dumpfile?"); } } else { // System.out.println("Big-endian"); } // read and verify standard header string var header = ReadString(stream, headerLength - 1); stream.ReadByte(); // read the '\0' _bytesRead++; if (!header.Equals(DarpaTgHeader) & !header.Equals(DarpaQgHeader) /*& !Pattern.matches(DARPA_NG_HEADER, header)*/) { throw new Exception("Bad binary LM file header: " + header); } else { if (header.Equals(DarpaTgHeader)) { MaxDepth = 3; } else if (header.Equals(DarpaQgHeader)) { MaxDepth = 4; } else { var p = Pattern.Compile("\\d"); var m = p.Matcher(header); //Match m = Regex.Match(header, "\\d"); MaxDepth = Convert.ToInt32(m.Group(0), CultureInfo.InvariantCulture.NumberFormat); } } // read LM filename string size and string var fileNameLength = ReadInt(stream, _bigEndian); SkipStreamBytes(stream, fileNameLength); _numberNGrams = new int[MaxDepth]; _nGramOffset = new long[MaxDepth]; _nGramProbTable = new float[MaxDepth][]; _nGramBackoffTable = new float[MaxDepth][]; _nGramSegmentTable = new int[MaxDepth][]; _numberNGrams[0] = 0; LogBigramSegmentSize = Log2NgramSegmentSize; // read version number, if present. it must be <= 0. var version = ReadInt(stream, _bigEndian); // System.out.println("Version: " + version); BytesPerField = 2; if (version <= 0) // yes, its the version number { ReadInt(stream, _bigEndian); // read and skip timestamp // Means we are going 32 bits. if (version <= -3) { BytesPerField = 4; } // read and skip format description int formatLength; for (; ;) { if ((formatLength = ReadInt(stream, _bigEndian)) == 0) { break; } _bytesRead += stream.Skip(formatLength); } // read log NGram segment size if present // only for 16 bits version 2 LM if (version == -2) { LogBigramSegmentSize = ReadInt(stream, _bigEndian); if (LogBigramSegmentSize < 1 || LogBigramSegmentSize > 15) { throw new Exception("log2(bg_seg_sz) outside range 1..15"); } } _numberNGrams[0] = ReadInt(stream, _bigEndian); } else { _numberNGrams[0] = version; } if (_numberNGrams[0] <= 0) { throw new Exception("Bad number of unigrams: " + _numberNGrams[0] + ", must be > 0."); } for (var i = 1; i < MaxDepth; i++) { if ((_numberNGrams[i] = ReadInt(stream, _bigEndian)) < 0) { throw new Exception("Bad number of " + i + "-grams: " + _numberNGrams[i]); } } }
/// <summary> /// Read a list of attributes /// </summary> private void ReadAttributes(ConstantPool cp, IModifiableAttributeProvider provider) { var count = stream.ReadU2(); for (var i = 0; i < count; i++) { var nameIndex = stream.ReadU2(); var name = cp.GetEntry <ConstantPoolUtf8>(nameIndex).Value; var length = stream.ReadU4(); Attribute attr; int tmp; switch (name) { case CodeAttribute.AttributeName: attr = ReadCodeAttribute((MethodDefinition)provider, cp); break; case ConstantValueAttribute.AttributeName: tmp = stream.ReadU2(); attr = new ConstantValueAttribute(((IConstantPoolValue)cp[tmp]).Value); break; case ExceptionsAttribute.AttributeName: attr = ReadExceptionsAttribute(cp); break; case InnerClassesAttribute.AttributeName: attr = ReadInnerClassesAttribute(cp); break; case SyntheticAttribute.AttributeName: attr = new SyntheticAttribute(); break; case SourceFileAttribute.AttributeName: tmp = stream.ReadU2(); attr = new SourceFileAttribute(cp.GetEntry <ConstantPoolUtf8>(tmp).Value); break; case LineNumberTableAttribute.AttributeName: attr = ReadLineNumberTableAttribute(); break; case LocalVariableTableAttribute.AttributeName: attr = ReadLocalVariableTableAttribute(cp); break; case DeprecatedAttribute.AttributeName: attr = new DeprecatedAttribute(); break; case OverrideAttribute.AttributeName: attr = new OverrideAttribute(); break; case SignatureAttribute.AttributeName: tmp = stream.ReadU2(); attr = new SignatureAttribute(cp.GetEntry <ConstantPoolUtf8>(tmp).Value); break; case RuntimeVisibleAnnotationsAttribute.AttributeName: attr = new RuntimeVisibleAnnotationsAttribute(ReadAnnotationsAttribute(cp)); break; case RuntimeInvisibleAnnotationsAttribute.AttributeName: attr = new RuntimeInvisibleAnnotationsAttribute(ReadAnnotationsAttribute(cp)); break; // The format of these is different from Runtime[In]]VisibleAnnotationsAttribute, // see 4.7.19. Since the parameter attributes are not used in the // code, we skip loading them for now. //case RuntimeVisibleParameterAnnotationsAttribute.AttributeName: // attr = new RuntimeVisibleParameterAnnotationsAttribute(ReadParameterAnnotationsAttribute(cp)); // break; //case RuntimeInvisibleParameterAnnotationsAttribute.AttributeName: // attr = new RuntimeInvisibleParameterAnnotationsAttribute(ReadParameterAnnotationsAttribute(cp)); // break; case AnnotationDefaultAttribute.AttributeName: attr = new AnnotationDefaultAttribute(ReadElementValue(cp)); break; default: stream.Skip(length); attr = new UnknownAttribute(name); break; } provider.Add(attr); } provider.AttributesLoaded(); }
/// <summary> /// Load materials in stream. /// </summary> /// <param name="stream">Stream to use.</param> /// <returns>Material definitions.</returns> public static IEnumerable<NsbmdMaterial> ReadTex0(Stream stream, int blockoffset, out int ptexnum, out int ppalnum, out List<NSBMDTexture> texs, out List<NSBMDPalette> pals) { EndianBinaryReader reader = new EndianBinaryReader(stream, Endianness.LittleEndian); UInt32 blocksize, blockptr, blocklimit; int texnum; UInt32 texdataoffset; int texdatasize; UInt32 sptexoffset; // for 4x4 compressed texels only int sptexsize; // for 4x4 compressed texels only UInt32 spdataoffset; // for 4x4 compressed texels only int palnum; UInt32 paldefoffset; UInt32 paldataoffset; int paldatasize; NsbmdMaterial[] material = null; int i, j; texs = new List<NSBMDTexture>(); pals = new List<NSBMDPalette>(); blockptr = (uint)(blockoffset + 4); // already read the block ID, so skip 4 bytes blocksize = reader.ReadUInt32(); // block size blocklimit = (uint)(blocksize + blockoffset); Console.WriteLine("DEBUG: blockoffset = {0}, blocksize = {1}", blockoffset, blocksize); stream.Skip(4); // skip 4 padding 0s texdatasize = reader.ReadUInt16() << 3; // total texture data size div8 stream.Skip(6); // skip 6 bytes texdataoffset = (uint)(reader.ReadUInt32() + blockoffset); stream.Skip(4); // skip 4 padding 0s sptexsize = reader.ReadUInt16() << 3; // for format 5 4x4-texel, data size div8 stream.Skip(6); // skip 6 bytesmhm sptexoffset = (uint)(reader.ReadUInt32() + blockoffset); // for format 5 4x4-texel, data offset spdataoffset = (uint)(reader.ReadUInt32() + blockoffset); // for format 5 4x4-texel, palette info stream.Skip(4); // skip 4 bytes paldatasize = reader.ReadUInt16() << 3; // total palette data size div8 stream.Skip(2); // skip 2 bytes paldefoffset = (uint)(reader.ReadUInt32() + blockoffset); paldataoffset = (uint)(reader.ReadUInt32() + blockoffset); // printf( "texdataoffset = %08x texdatasize = %08x\n", texdataoffset, texdatasize ); // printf( "sptexoffset = %08x sptexsize = %08x spdataoffset = %08x\n", sptexoffset, sptexsize, spdataoffset ); // printf( "paldataoffset = %08x paldatasize = %08x\n", paldataoffset, paldatasize ); //////////////////////////////////////////////// // texture definition stream.Skip(1); // skip dummy '0' texnum = reader.ReadByte(); // no of texture blockptr = (uint)stream.Position; stream.Seek(paldefoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' palnum = reader.ReadByte(); // no of palette stream.Seek(blockptr, SeekOrigin.Begin); Console.WriteLine("texnum = {0}, palnum = {1}", texnum, palnum); // allocate memory for material, great enough to hold all texture and palette material = new NsbmdMaterial[(texnum > palnum ? texnum : palnum)]; for (i = 0; i < material.Length; i++) material[i] = new NsbmdMaterial(); stream.Skip(14 + (texnum * 4)); // go straight to texture info for (i = 0; i < texnum; i++) { UInt32 offset; int param; int format; int width; int height; var mat = material[i]; offset = (uint)(reader.ReadUInt16() << 3); param = reader.ReadUInt16(); // texture parameter stream.Skip(4); // skip 4 bytes format = (param >> 10) & 7; // format 0..7, see DSTek width = 8 << ((param >> 4) & 7); height = 8 << ((param >> 7) & 7); mat.color0 = (param >> 13) & 1; if (format == 5) mat.texoffset = offset + sptexoffset; // 4x4-Texel Compressed Texture else mat.texoffset = offset + texdataoffset; mat.format = format; mat.width = width; mat.height = height; NSBMDTexture t = new NSBMDTexture(); t.format = format; t.width = width; t.height = height; t.color0 = (param >> 13) & 1; texs.Add(t); } //////////////////////////////////////////// // copy texture names for (i = 0; i < texnum; i++) { material[i].texname = Utils.ReadNSBMDString(reader); reader.BaseStream.Position -= 16; texs[i].texname = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // calculate each texture's size for (i = 0; i < texnum; i++) { int[] bpp = { 0, 8, 2, 4, 8, 2, 8, 16 }; var mat = material[i]; mat.texsize = (uint)(mat.width * mat.height * bpp[mat.format] / 8); Console.WriteLine("tex {0} '{1}': offset = {2} size = {3} [W,H] = [{4}, {5}]", i, mat.texname, mat.texoffset, mat.texsize, mat.width, mat.height); texs[i].texsize = (uint)(mat.width * mat.height * bpp[mat.format] / 8); } //////////////////////////////////////////////// // palette definition stream.Seek(paldefoffset + 2, SeekOrigin.Begin); // skip palnum, already read stream.Seek(14 + (palnum * 4), SeekOrigin.Current); // go straight to palette info for (i = 0; i < palnum; i++) { uint curOffset = (uint)((reader.ReadUInt16() << 3) + paldataoffset); stream.Seek(2, SeekOrigin.Current); // skip 2 bytes material[i].paloffset = curOffset; NSBMDPalette t = new NSBMDPalette(); t.paloffset = curOffset; pals.Add(t); } //////////////////////////////////////////////// // copy palette names for (i = 0; i < palnum; i++) { var mat = material[i]; mat.palname = Utils.ReadNSBMDString(reader); reader.BaseStream.Position -= 16; pals[i].palname = Utils.ReadNSBMDString(reader); } //////////////////////////////////////////////// // calculate each palette's size // assume the palettes are stored sequentially /*for (i = 0; i < palnum - 1; i++) { int r; var mat = material[i]; r = i; try { while (material[r].paloffset == mat.paloffset) r++; } catch { } // below is RotA stupid way to calculate the size of palette: next's offset - current's offset // it works most of the time if (r != palnum) { mat.palsize = material[r].paloffset - mat.paloffset; pals[i].palsize = material[r].paloffset - mat.paloffset; } else { mat.palsize = blocklimit - mat.paloffset; pals[i].palsize = blocklimit - mat.paloffset; } //printf("pal '%s' size = %d\n", mat->palname, mat->palsize); } material[i].palsize = blocklimit - material[i].paloffset; pals[i].palsize = blocklimit - material[i].paloffset;*/ List<int> offsets = new List<int>(); for (int k = 0; k < pals.Count; k++) { if (!offsets.Contains((int)pals[k].paloffset)) { offsets.Add((int)pals[k].paloffset); } } offsets.Add((int)blocklimit); offsets.Sort(); for (int k = 0; k < pals.Count; k++) { int pallength; int l = -1; do { l++; } while (offsets[l] - pals[k].paloffset <= 0);//nsbtx.PalInfo.infoBlock.PalInfo[i + j].Palette_Offset - nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset == 0) pallength = offsets[l] - (int)pals[k].paloffset; //RGBA[] c_ = pals[k].paldata; //List<RGBA> c = new List<RGBA>(); //c.AddRange(pals[k].paldata.Take(pallength / 2)); //pals[k].paldata = c.ToArray(); pals[k].palsize = (uint)pallength; material[k].palsize = (uint)pallength; } //////////////////////////////////////////////// // traverse each texture for (i = 0; i < texnum; i++) { var mat = material[i]; stream.Seek(mat.texoffset, SeekOrigin.Begin); //////////////////////////////////////////////// // read texture into memory byte[] by = reader.ReadBytes((int)mat.texsize); mat.texdata = by; texs[i].texdata = by; Console.WriteLine("DEBUG: texoffset = {0}, texsize = {1}", mat.texoffset, mat.texsize); //////////////////////////////////////////////// // additional data for format 5 4x4 compressed texels if (mat.format == 5) { UInt32 r = mat.texsize / 2;//>> 1; stream.Seek(spdataoffset + (mat.texoffset - sptexoffset) / 2, SeekOrigin.Begin); by = reader.ReadBytes((int)r); mat.spdata = by; texs[i].spdata = by; Console.WriteLine("DEBUG: 4x4-texel spdataoffset = {0}, spdatasize = {1}", spdataoffset, r); //spdataoffset += r; } } //////////////////////////////////////////////// // traverse each palette for (i = 0; i < palnum; i++) { try { NsbmdMaterial mat = material[i]; var palentry = mat.palsize >> 1; RGBA[] rgbq = new RGBA[palentry]; Console.WriteLine("DEBUG: converting pal '{0}', palentry = {1}", mat.palname, palentry); stream.Seek(mat.paloffset, SeekOrigin.Begin); for (j = 0; j < palentry; j++) { UInt16 p = reader.ReadUInt16(); rgbq[j].R = (byte)(((p >> 0) & 0x1f) << 3); // red rgbq[j].G = (byte)(((p >> 5) & 0x1f) << 3); // green rgbq[j].B = (byte)(((p >> 10) & 0x1f) << 3); // blue //rgbq[j].RotA = (p&0x8000) ? 0xff : 0; rgbq[j].A = (p & 0x8000) == 0 ? (byte)0xff : (byte)0;//0xff; // alpha } mat.paldata = rgbq; pals[i].paldata = rgbq; } catch { } } ptexnum = texnum; ppalnum = palnum; return material; }
/// <summary> /// ReadMld0. /// </summary> private static NsbmdModel[] ReadMdl0(Stream stream, int blockoffset) { var reader = new BinaryReader(stream); int blocksize; int blockptr; int blocklimit; byte num; uint r; List<NsbmdModel> model = new List<NsbmdModel>(); //////////////////////////////////////////////// // model blockptr = blockoffset + 4; // already read the ID, skip 4 bytes blocksize = reader.ReadInt32(); // block size blocklimit = blocksize + blockoffset; stream.Skip(1); // skip dummy '0' num = reader.ReadByte(); // no of model if (num <= 0) throw new Exception(); for (var i = 0; i < num; ++i) model.Add(new NsbmdModel()); var modelOffset = new UInt32[num]; stream.Skip(10 + 4 + (num*4)); // skip [char xyz], useless, go straight to model data offset blockptr += 10 + 4; //////////////////////////////////////////////// // copy model dataoffset for (var i = 0; i < num; i++) modelOffset[i] = (uint) (reader.ReadUInt32() + blockoffset); //////////////////////////////////////////////// // copy model names for (var i = 0; i < num; i++) model[i].Name = Utils.ReadNSBMDString(reader); //////////////////////////////////////////////// // parse model data uint totalsize_base = reader.ReadUInt32(); uint codeoffset_base = reader.ReadUInt32(); uint texpaloffset_base = reader.ReadUInt32(); uint polyoffset_base = reader.ReadUInt32(); uint polyend_base = reader.ReadUInt32(); stream.Skip(4); uint matnum = reader.ReadByte(); // no. of material uint polynum = reader.ReadByte(); // no. of polygon var polyOffsets = new UInt32[polynum]; var polyDataSize = new UInt32[polynum]; for (var i = 0; i < num; i++) { var mod = model[i]; stream.Seek(modelOffset[i], SeekOrigin.Begin); // the following variables are all offset values long totalsize; uint codeoffset; UInt32 texpaloffset; UInt32 polyoffset; long polyend; long texoffset; long paloffset; uint modoffset = modelOffset[i]; totalsize = totalsize_base + modoffset; codeoffset = codeoffset_base + modoffset; // additional model data, bone definition etc., just follow NsbmdObject section texpaloffset = texpaloffset_base + modoffset; polyoffset = polyoffset_base + modoffset; polyend = polyend_base + modoffset; stream.Skip(5*4 + 4 + 2 + 38); // go straight to NsbmdObject //////////////////////////////////////////////// // NsbmdObject section UInt32 objnum; int objdatabase; UInt32[] objdataoffset; UInt32[] objdatasize; objdatabase = (int) stream.Position; stream.Skip(1); // skip dummy '0' objnum = reader.ReadByte(); // no of NsbmdObject stream.Skip(14 + (objnum*4)); // skip bytes, go striaght to NsbmdObject data offset for (i = 0; i < objnum; ++i) mod.Objects.Add(new NsbmdObject()); objdataoffset = new UInt32[objnum]; objdatasize = new UInt32[objnum]; for (var j = 0; j < objnum; j++) objdataoffset[j] = (UInt32) (reader.ReadUInt32() + objdatabase); for (var j = 0; j < objnum - 1; j++) objdatasize[j] = objdataoffset[j + 1] - objdataoffset[j]; objdatasize[objnum - 1] = (UInt32) (codeoffset - objdataoffset[objnum - 1]); //////////////////////////////////////////////// // copy NsbmdObject names for (var j = 0; j < objnum; j++) { mod.Objects[j].Name = Utils.ReadNSBMDString(reader); // TO DEBUG Console.WriteLine(mod.Objects[j].Name); } //////////////////////////////////////////////// // parse NsbmdObject information for (var j = 0; j < objnum; j++) { if (objdatasize[j] <= 4) continue; stream.Seek(objdataoffset[j], SeekOrigin.Begin); ParseNsbmdObject(reader, mod.Objects[j]); } //////////////////////////////////////////////// // material section stream.Seek(texpaloffset, SeekOrigin.Begin); // now get the texture and palette offset texoffset = reader.ReadUInt16() + texpaloffset; paloffset = reader.ReadUInt16() + texpaloffset; // allocate memory for material for (var j = 0; i <= matnum; ++i) mod.Materials.Add(new NsbmdMaterial()); //////////////////////////////////////////////// // parse material definition // defines RotA material by pairing texture and palette stream.Seek(16 + (matnum*4), SeekOrigin.Current); // go straight to material data offset for (var j = 0; j < matnum; j++) // TODO: BAD! { mod.Materials[j] = new NsbmdMaterial(); blockptr = (int) stream.Position; r = reader.ReadUInt32() + texpaloffset + 4 + 18; // skip 18 bytes (+ 2 bytes for texoffset, 2 bytes for paloffset) stream.Seek(r, SeekOrigin.Begin); mod.Materials[j].repeat = reader.ReadByte(); stream.Seek(blockptr + 4, SeekOrigin.Begin); } //////////////////////////////////////////////// // now go to read the texture definition stream.Seek(texoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' int texnum = reader.ReadByte(); Debug.Assert(texnum <= matnum); Console.WriteLine(String.Format("texnum: {0}", texnum)); if (texnum > 0) { stream.Seek(14 + (texnum*4), SeekOrigin.Current); // go straight to data offsets for (var j = 0; j < texnum; j++) { UInt32 texmatid = ((reader.ReadUInt32() & 0xffff) + texpaloffset); blockptr = (int) stream.Position; stream.Seek(texmatid, SeekOrigin.Begin); texmatid = reader.ReadByte(); mod.Materials[j].texmatid = texmatid; stream.Seek(blockptr, SeekOrigin.Begin); } for (var j = 0; j < texnum; j++) // copy texture names { NsbmdMaterial mat = mod.Materials[j]; mat.texname = Utils.ReadNSBMDString(reader); Console.WriteLine("tex (matid={0}): {1}", mat.texmatid, mat.texname); } //////////////////////////////////////////////// // now go to read the palette definition stream.Seek(paloffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' int palnum = reader.ReadByte(); // no of palette definition Debug.Assert(palnum <= matnum); // may not always hold? Console.WriteLine("DEBUG: palnum = {0}", palnum); if (palnum > 0) { stream.Seek(14 + (palnum*4), SeekOrigin.Current); // go straight to data offsets for (var j = 0; j < palnum; j++) // matching palette with material { var palmatid = (reader.ReadUInt32() & 0xffff) + texpaloffset; blockptr = (int) stream.Position; stream.Seek(palmatid, SeekOrigin.Begin); palmatid = reader.ReadByte(); var mat = mod.Materials[j]; mat.palmatid = palmatid; stream.Seek(blockptr, SeekOrigin.Begin); } for (var j = 0; j < palnum; j++) // copy palette names { int palmatid = (int) mod.Materials[j].palmatid; mod.Materials[palmatid].palname = Utils.ReadNSBMDString(reader); // TO DEBUG Console.WriteLine("pal (matid={0}): {1}", palmatid, mod.Materials[palmatid].palname); } //////////////////////////////////////////////// // Polygon stream.Seek(polyoffset, SeekOrigin.Begin); stream.Skip(1); // skip dummy '0' r = reader.ReadByte(); // no of polygon Console.WriteLine("DEBUG: polynum = {0}", polynum); for (var j = 0; j <= polynum; ++j) mod.Polygons.Add(new NsbmdPolygon()); stream.Skip(14 + (polynum*4)); // skip bytes, go straight to data offset for (var j = 0; j < polynum; j++) polyOffsets[j] = reader.ReadUInt32() + polyoffset; for (var j = 0; j < polynum; j++) // copy polygon names { mod.Polygons[j].Name = Utils.ReadNSBMDString(reader); Console.WriteLine(mod.Polygons[j].Name); } //////////////////////////////////////////////// // now go to the polygon data, there is RotA 16-byte-header before geometry commands for (var j = 0; j < polynum; j++) { var poly = mod.Polygons[j]; ////////////////////////////////////////////////////////// poly.MatId = -1; // DEFAULT: indicate no associated material ////////////////////////////////////////////////////////// stream.Seek(polyOffsets[j] + 8, SeekOrigin.Begin); // skip 8 unknown bytes polyOffsets[j] += reader.ReadUInt32(); polyDataSize[j] = reader.ReadUInt32(); //printf( "poly %2d '%-16s': dataoffset: %08x datasize %08x\n", j, poly->polyname, poly->dataoffset, poly->datasize ); } } //////////////////////////////////////////////// // read the polygon data into memory for (var j = 0; j < polynum; j++) { var poly = mod.Polygons[j]; stream.Seek(polyOffsets[j], SeekOrigin.Begin); poly.PolyData = reader.ReadBytes((int) polyDataSize[j]); } } //////////////////////////////////////////////// // decode the additional model data DecodeCode(stream, codeoffset, texpaloffset, mod); } //modelnum = num; return model.ToArray(); }
internal void SkipParams(Stream reader) { switch (this.flags & OpcodeFlags.OperandType) { case OpcodeFlags.NoOperand: break; case OpcodeFlags.OperandSize1: reader.Skip (1); break; case OpcodeFlags.OperandSize2: reader.Skip (2); break; case OpcodeFlags.OperandSize4: reader.Skip (4); break; case OpcodeFlags.OperandSize8: reader.Skip (8); break; case OpcodeFlags.OperandSwitch: //FIXME implement me throw new Exception ("not supported"); default: throw new Exception ("invalid opcode type " + this.flags); } }
public void Skip_zero_delta_does_nothing() { MoveTo(1); _stream.Skip(0); Assert.That(_stream.Position, Is.EqualTo(1)); }