static void ExtractBg(string bgPath, string basePath = null) { if (basePath == null) { basePath = Path.ChangeExtension(bgPath, null); } else { basePath = Path.Combine(basePath, Path.GetFileNameWithoutExtension(bgPath)); } DatReader dat = new DatReader(Utils.CheckDecompress(File.OpenRead(bgPath))); using ObjConverter converter = new ObjConverter(dat); string mtlPath = basePath + ".mtl"; string mtlName = Path.GetFileName(mtlPath); for (int i = 0; i < 3; ++i) { using MemoryStream ms = new MemoryStream(dat.GetData(i)); DatReader innerDat = new DatReader(ms); for (int j = 0; j < innerDat.EntriesCount; ++j) { using BinaryReader br = new BinaryReader(new MemoryStream(innerDat.GetData(j))); Tdb tdb = new Tdb(); tdb.Read(br); // Remap textures (only known for Windows version, PS2 todo when files obtained) if (i == 0) { tdb.Textures[0].DatIndex = 4; tdb.Textures[1].DatIndex = 3; } else { tdb.Textures[0].DatIndex = 5; } using StreamWriter sw = File.CreateText($"{basePath}.{i}_{j}.obj"); sw.WriteLine($"mtllib {mtlName}"); sw.WriteLine(); converter.ConvertObj(tdb, sw); } } using (StreamWriter sw = File.CreateText(mtlPath)) { converter.ExportTextures(sw, basePath + ".", true); } }
TxmHeader CreateTexture(Tdb tdb, int index, out ulong textureId) { var tdbTexture = tdb.Textures[index]; textureId = ((ulong)tdbTexture.DatIndex << 32) | ((ulong)tdbTexture.ImageBufferBase << 16) | tdbTexture.ClutBufferBase; if (!textureCache.ContainsKey(textureId)) { TxmHeader txm = new TxmHeader(); txm.ImageBufferBase = tdbTexture.ImageBufferBase; txm.ClutBufferBase = tdbTexture.ClutBufferBase; textureCache.Add(textureId, txm); return(txm); } return(null); }
/// <summary> /// Returns stacks by select command. /// </summary> /// <param name="selectcommand">Select command.</param> public MochaArray <MochaStack> GetStacks(string selectcommand) { var regex = new Regex(selectcommand); return(new MochaArray <MochaStack>(Tdb.GetStacks(x => regex.IsMatch(x.Name)))); }
/// <summary> /// Returns table by use command. /// </summary> /// <param name="usecommand">Use command.</param> public MochaTableResult GetTable(string usecommand, bool from) { MochaColumn GetColumn(string cmd, IList <MochaColumn> cols) { string decomposeBrackets(string value) { int dex; if ((dex = value.IndexOf('(')) != -1) { return(value.Substring(dex + 1, value.Length - dex - 2)); } return(value); } string name = Mhql_AS.GetAS(ref cmd); if (Mhql_GRAMMAR.UseFunctions.MatchKey(cmd)) { MochaColumn column = new MochaColumn(); column.MHQLAsText = name; column.Tag = Mhql_GRAMMAR.UseFunctions.GetValueByMatchKey(cmd); if (column.Tag != "COUNT") { column.Description = Mhql_GRAMMAR.GetIndexOfColumn(decomposeBrackets(cmd), cols, from).ToString(); } return(column); } else { string colname = cmd.StartsWith("$") ? cmd.Substring(1).Trim() : cmd; IEnumerable <MochaColumn> result = cols.Where(x => x.Name == colname); if (!result.Any()) { throw new Exception($"Could not find a column with the name '{cmd}'!"); } MochaColumn column = result.First(); column.Tag = colname != cmd ? "$" : null; column.MHQLAsText = name; return(column); } } List <MochaColumn> columns = new List <MochaColumn>(); MochaTableResult resulttable = new MochaTableResult(); if (from) { int dex = Mhql_FROM.GetIndex(ref usecommand); string tablename = usecommand.Substring(dex + 5).Trim(); List <string> parts = Mhql_LEXER.SplitUseParameters(usecommand.Substring(0, dex)); List <MochaColumn> _columns = Tdb.GetColumns(tablename); if (parts.Count == 1 && parts[0].Trim() == "*") { columns.AddRange(_columns); } else { if (parts[0].TrimStart().StartsWith("$") && parts[0].TrimStart().Substring(1).TrimStart().StartsWith($"{Mhql_LEXER.LBRACE}")) { throw new InvalidOperationException("Cannot be used with subquery FROM keyword!"); } for (int index = 0; index < parts.Count; ++index) { columns.Add(GetColumn(parts[index].Trim(), _columns)); } } } else { List <string> parts = Mhql_LEXER.SplitUseParameters(usecommand); for (int index = 0; index < parts.Count; ++index) { string callcmd = parts[index].Trim(); if (callcmd == "*") { List <MochaTable> tables = Tdb.GetTables(); for (int tindex = 0; tindex < tables.Count; ++tindex) { columns.AddRange(tables[tindex].Columns); } continue; } int obrace = callcmd.IndexOf(Mhql_LEXER.LBRACE); if (obrace != -1) { IList <MochaColumn> _cols = (new MochaDbCommand(Tdb).ExecuteScalar(Mhql_LEXER.RangeSubqueryBrace( callcmd.Substring(obrace).Trim()))).Columns; string mode = callcmd.Substring(0, obrace).TrimStart().StartsWith("$") ? "$" : string.Empty; for (int cindex = 0; cindex < _cols.Count; ++cindex) { columns.Add(GetColumn($"{mode}{_cols[cindex].Name}", _cols)); } continue; } if (callcmd.StartsWith("$")) { callcmd = callcmd.Substring(1).Trim(); List <MochaColumn> _cols = Tdb.GetColumns(callcmd); for (int cindex = 0; cindex < _cols.Count; ++cindex) { columns.Add(GetColumn($"${_cols[cindex].Name}", _cols)); } continue; } string[] callparts = Mhql_LEXER.SplitSubCalls(callcmd); if (callparts.Length > 2) { throw new InvalidOperationException($"'{callcmd}' command is cannot processed!"); } for (byte partindex = 0; partindex < callparts.Length; ++partindex) { callparts[partindex] = callparts[partindex].Trim(); } List <MochaColumn> _columns = Tdb.GetColumns(callparts[0]); if (callparts.Length == 1) { columns.AddRange(_columns); } else { columns.Add(GetColumn(callparts[1], _columns)); } } } resulttable.Columns = columns.ToArray(); resulttable.SetRowsByDatas(); return(resulttable); }
public void ConvertObj(Tdb tdb, StreamWriter sw) { WriteObj(tdb, sw, 1); }
int WriteObj(Tdb tdb, StreamWriter sw, int startVert) { for (int i = 0; i < tdb.Mesh.Elements.Count; ++i) { var elem = tdb.Mesh.Elements[i]; sw.WriteLine($"g elem_{i}"); TxmHeader txm = CreateTexture(tdb, elem.TextureIndex, out var textureId); sw.WriteLine($"usemtl tex_{textureId:x12}"); if (txm != null) { FillTxm(elem, txm); } // Write vertices foreach (var vert in elem.Vertices) { sw.WriteLine($"v {(double)vert.X} {(double)vert.Y} {(double)vert.Z}"); } foreach (var norm in elem.VertexNormals) { sw.WriteLine($"vn {norm.Item1} {norm.Item2} {norm.Item3}"); } foreach (var uv in elem.STCoordinates) { sw.WriteLine($"vt {uv.Item1} {1 - uv.Item2}"); } // Write faces int[] initVerts = new int[2]; bool clockwise = true; if (elem.GifTagIndex == 3) // Triangle fans { int initVertPos = 0; for (int j = 0; j < elem.Vertices.Count; ++j) { if ((elem.Vertices[j].W.Packed & 0x00008000) != 0) { initVerts[initVertPos++] = startVert + j; } else { int currVert = startVert + j; if (clockwise) { sw.WriteLine($"f {initVerts[0]}/{initVerts[0]}/{initVerts[0]} {initVerts[1]}/{initVerts[1]}/{initVerts[1]} {currVert}/{currVert}/{currVert}"); } else { sw.WriteLine($"f {currVert}/{currVert}/{currVert} {initVerts[1]}/{initVerts[1]}/{initVerts[1]} {initVerts[0]}/{initVerts[0]}/{initVerts[0]}"); } initVerts[1] = currVert; initVertPos = 0; } clockwise = !clockwise; } } else if (elem.GifTagIndex == 4) // Triangle strips { for (int j = 0; j < elem.Vertices.Count; ++j) { int currVert = startVert + j; if ((elem.Vertices[j].W.Packed & 0x00008000) == 0) { if (clockwise) { sw.WriteLine($"f {initVerts[0]}/{initVerts[0]}/{initVerts[0]} {initVerts[1]}/{initVerts[1]}/{initVerts[1]} {currVert}/{currVert}/{currVert}"); } else { sw.WriteLine($"f {currVert}/{currVert}/{currVert} {initVerts[1]}/{initVerts[1]}/{initVerts[1]} {initVerts[0]}/{initVerts[0]}/{initVerts[0]}"); } } initVerts[0] = initVerts[1]; initVerts[1] = currVert; clockwise = !clockwise; } } else { throw new NotSupportedException("Unknown face construction type"); } startVert += elem.Vertices.Count; sw.WriteLine(); } return(startVert); }
/// <summary> /// Returns table by use command. /// </summary> /// <param name="usecommand">Use command.</param> public MochaTableResult GetTable(string usecommand, bool from) { var columns = new List <MochaColumn>(); var resulttable = new MochaTableResult(); if (from) { var dex = usecommand.IndexOf("FROM", StringComparison.OrdinalIgnoreCase); var tablename = usecommand.Substring(dex + 4).TrimStart().TrimEnd(); var parts = usecommand.Substring(0, dex).Split(','); var table = Tdb.GetTable(tablename); if (parts.Length == 1 && parts[0].Trim() == "*") { columns.AddRange(table.Columns); } else { for (var index = 0; index < parts.Length; index++) { var callcmd = parts[index].Trim(); var name = Mhql_AS.GetAS(ref callcmd); var column = table.Columns[callcmd]; column.Name = name; columns.Add(column); } } } else { var parts = usecommand.Split(','); for (var index = 0; index < parts.Length; index++) { var callcmd = parts[index].Trim(); if (callcmd == "*") { var tables = Tdb.GetTables(); for (int tindex = 0; tindex < tables.Count; tindex++) { columns.AddRange(tables[tindex].Columns); } continue; } var callparts = callcmd.Split('.'); if (callparts.Length > 2) { throw new MochaException($"'{callcmd}' command is cannot processed!"); } for (byte partindex = 0; partindex < callparts.Length; partindex++) { callparts[partindex] = callparts[partindex].Trim(); } var table = Tdb.GetTable(callparts[0]); if (callparts.Length == 1) { columns.AddRange(table.Columns); } else { var callp1 = callparts[1]; var name = Mhql_AS.GetAS(ref callp1); var column = table.Columns[callp1]; column.Name = name; columns.Add(column); } } } resulttable.Columns = columns.ToArray(); resulttable.SetRowsByDatas(); return(resulttable); }
/// <summary> /// Returns sector table by use command. /// </summary> /// <param name="usecommand">Use command.</param> public MochaTableResult GetSector(string usecommand, bool from) { if (from) { throw new MochaException("FROM keyword is cannot used with @SECTORS marked commands!"); } var resulttable = new MochaTableResult { Columns = new[] { new MochaColumn("Name"), new MochaColumn("Description"), new MochaColumn("Data") } }; var rows = new List <MochaRow>(); var parts = usecommand.Split(','); for (var index = 0; index < parts.Length; index++) { var callcmd = parts[index].TrimStart().TrimEnd(); if (callcmd == "*") { var sectors = Tdb.GetSectors(); for (int sindex = 0; sindex < sectors.Count; sindex++) { var currentsector = sectors.ElementAt(sindex); rows.Add(new MochaRow( new MochaData { data = currentsector.Name, dataType = MochaDataType.String }, new MochaData { data = currentsector.Description, dataType = MochaDataType.String }, new MochaData { data = currentsector.Data, dataType = MochaDataType.String } )); } } else { var sector = Tdb.GetSector(callcmd); rows.Add(new MochaRow( new MochaData { data = sector.Name, dataType = MochaDataType.String }, new MochaData { data = sector.Description, dataType = MochaDataType.String }, new MochaData { data = sector.Data, dataType = MochaDataType.String } )); } } resulttable.Rows = rows.ToArray(); return(resulttable); }