elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


+  Foro de elhacker.net
|-+  Programación
| |-+  Ingeniería Inversa (Moderadores: karmany, .:UND3R:., MCKSys Argentina)
| | |-+  Ayuda para parsear este formato...
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Ayuda para parsear este formato...  (Leído 5,584 veces)
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.788



Ver Perfil
Ayuda para parsear este formato...
« en: 10 Diciembre 2016, 11:56 am »

Buenas!

Primero me gustaría aclarar que el propósito de esto es ético, y cualquier persona dispuesta a ayudarme a aclararme las ideas con esta duda que tengo, podría verse recompensada en un futuro próximo, ya que un grupo muy importante (y veterano) de Rom-Hacking está llevando a cabo la traducción al Español del videojuego Persona 3 para PS2, y yo he decidido prestarles ayuda en una pequeña cosa que necesitan, pero me encuentro atascado...

Este es el archivo con el que estoy trabajando:

El archivo se llama datBootsHelp.bmd y el formato del archivo, BMD, es un formato privativo el cual contiene 2 tablas,
necesito parsear una de esas tablas para traducir de forma programática los textos que contiene, y por textos me refiero a estas descripciones en Inglés:



En la siguiente imagen os muestro las especificaciones conocidas del formato BMD, y los valores que he obtenido analizando el archivo de ejemplo datBootsHelp.bmd el cual he compartido al principio del post.



Las filas marcadas con un signo verde son las que he conseguido localizar y parsear de forma programática sin problemas, las filas con un aspa roja son las que todavía no, y la fila con un signo de interrogación es el offset con el que tengo problemas y por ende me impide localizar los valores del aspa roja...

El problema que tengo es que no consigo determinar en que offset se delimita el final de la primera tabla, con el inicio de la segunda tabla, ni tampoco entiendo cual es la longitud exacta (contando los bytes ceros/nulos, se entiende) de los campos/textos de la segunda tabla, es decir, no consigo entender donde empieza el identificador de texto, cual es su longitud/capacidad, y donde empieza la descripción de texto y cual es su longitud/capacidad. Si analizo y comparo cada campo por individual para intentar averiguar la longitud, me da diferentes longitudes así que no me cuadra nada... pero eso solo significa que lo estoy analizando mal, por que deben tener una longitud máxima el identificador la descripción, vaya xD.

Supuestamente y a mi entender, la primera tabla termina en el offset 814 (0x32C) como se menciona en la imagen de arriba; en esta imagen de aquí abajo hago una selección empezando por ese offset hasta encontrar el inicio del primer identificador de texto ...y por medio hay 2 bytes (A4 1D) que no se lo que son:





Por último, comparto el código fuente que he desarrollado en el lenguaje VB.NET para leer los datos de la cabecera del formato y  la primera tabla:

Código
  1. ''' ----------------------------------------------------------------------------------------------------
  2. ''' <summary>
  3. ''' Represents the BMD File Format.
  4. ''' </summary>
  5. ''' ----------------------------------------------------------------------------------------------------
  6. ''' <remarks>
  7. ''' <see href="http://datacrystal.romhacking.net/wiki/Persona_3_and_4/BMD_%28File_Format%29"/>
  8. ''' </remarks>
  9. ''' ----------------------------------------------------------------------------------------------------
  10. Public NotInheritable Class BMDFormat
  11.  
  12. #Region " Private Fields "
  13.  
  14.    ''' <summary>
  15.    ''' Specifies the offset where the header begins.
  16.    ''' </summary>
  17.    Private ReadOnly HeaderOffset As Integer = &H0
  18.  
  19.    ''' <summary>
  20.    ''' Specifies the offset where the non-text table begins. This is the first table in the BMD file format.
  21.    ''' </summary>
  22.    Private ReadOnly TableNonTextOffset As Integer = &H24
  23.  
  24.    ''' <summary>
  25.    ''' Specifies the offset where the text table begins. This is the second table in the BMD file format.
  26.    ''' </summary>
  27.    Private TableTextOffset As Integer ' The value is determined later, at the end of the TableNonTextOffset table.
  28.  
  29.    ''' <summary>
  30.    ''' Contains the offset location and length of the BMD header offsets.
  31.    ''' </summary>
  32.    Private ReadOnly HeaderOffsets As New Dictionary(Of String, KeyValuePair(Of Integer, Integer))(StringComparer.Ordinal) From {
  33.        {"ChunkID", New KeyValuePair(Of Integer, Integer)(&H0, Nothing)},
  34.        {"Size", New KeyValuePair(Of Integer, Integer)(&H4, &H5)},
  35.        {"MagicIdentifier", New KeyValuePair(Of Integer, Integer)(&H8, &HB)},
  36.        {"EndOfTextTable", New KeyValuePair(Of Integer, Integer)(&H10, &H11)},
  37.        {"OffsetsAmount", New KeyValuePair(Of Integer, Integer)(&H14, &H15)},
  38.        {"EntriesAmount", New KeyValuePair(Of Integer, Integer)(&H18, &H19)}
  39.    } ' Friendly-Name, {Start-Offset, End-Offset}
  40.  
  41. #End Region
  42.  
  43. #Region " Properties "
  44.  
  45.    ''' <summary>
  46.    ''' Gets the raw byte-data of the BMD file.
  47.    ''' </summary>
  48.    Public ReadOnly Property RawData As Byte()
  49.        Get
  50.            Return Me.rawDataB
  51.        End Get
  52.    End Property
  53.    Private ReadOnly rawDataB As Byte()
  54.  
  55.    ''' <summary>
  56.    ''' Gets the Chunk ID of the file format.
  57.    ''' </summary>
  58.    Public ReadOnly Property ChunkID As Byte
  59.        Get
  60.            Return Me.chunkIDB
  61.        End Get
  62.    End Property
  63.    Private chunkIDB As Byte
  64.  
  65.    ''' <summary>
  66.    ''' Gets the size of the file.
  67.    ''' </summary>
  68.    Public ReadOnly Property Size As Short
  69.        Get
  70.            Return Me.sizeB
  71.        End Get
  72.    End Property
  73.    Private sizeB As Short
  74.  
  75.    ''' <summary>
  76.    ''' Gets the Magic Identifier of the file format.
  77.    ''' </summary>
  78.    Public ReadOnly Property MagicIdentifier As Byte()
  79.        Get
  80.            Return Me.magicIdentifierB
  81.        End Get
  82.    End Property
  83.    Private magicIdentifierB As Byte()
  84.  
  85.    ''' <summary>
  86.    ''' Gets the end of text table of the file format.
  87.    ''' </summary>
  88.    Public ReadOnly Property EndOfTextTable As Short
  89.        Get
  90.            Return Me.endOfTextTableB
  91.        End Get
  92.    End Property
  93.    Private endOfTextTableB As Short
  94.  
  95.    ''' <summary>
  96.    ''' Gets the amount of offsets in offset table of the file format.
  97.    ''' </summary>
  98.    Public ReadOnly Property OffsetsAmount As Short
  99.        Get
  100.            Return Me.offsetsAmountB
  101.        End Get
  102.    End Property
  103.    Private offsetsAmountB As Short
  104.  
  105.    ''' <summary>
  106.    ''' Gets the amount of entries of the file format.
  107.    ''' </summary>
  108.    Public ReadOnly Property EntriesAmount As Short
  109.        Get
  110.            Return Me.entriesAmountB
  111.        End Get
  112.    End Property
  113.    Private entriesAmountB As Short
  114.  
  115. #End Region
  116.  
  117. #Region " Constructors "
  118.  
  119.    Private Sub New()
  120.    End Sub
  121.  
  122.    Public Sub New(ByVal filepath As String)
  123.        Me.New(File.ReadAllBytes(filepath))
  124.    End Sub
  125.  
  126.    Public Sub New(ByVal file As FileInfo)
  127.        Me.New(file.FullName)
  128.    End Sub
  129.  
  130.    Public Sub New(ByVal raw As Byte())
  131.        Me.rawDataB = raw
  132.        Me.ReadHeader()
  133.    End Sub
  134.  
  135. #End Region
  136.  
  137. #Region " Private Methods "
  138.  
  139.    ''' <summary>
  140.    ''' Reads the BMD header.
  141.    ''' </summary>
  142.    Private Sub ReadHeader()
  143.  
  144.        Dim chunkID As KeyValuePair(Of Integer, Integer) = Me.HeaderOffsets("ChunkID")
  145.        Dim size As KeyValuePair(Of Integer, Integer) = Me.HeaderOffsets("Size")
  146.        Dim magicIdentifier As KeyValuePair(Of Integer, Integer) = Me.HeaderOffsets("MagicIdentifier")
  147.        Dim endOfTextTable As KeyValuePair(Of Integer, Integer) = Me.HeaderOffsets("EndOfTextTable")
  148.        Dim offsetsAmount As KeyValuePair(Of Integer, Integer) = Me.HeaderOffsets("OffsetsAmount")
  149.        Dim entriesAmount As KeyValuePair(Of Integer, Integer) = Me.HeaderOffsets("EntriesAmount")
  150.  
  151.        Me.magicIdentifierB = Me.GetBytes(Me.HeaderOffset, magicIdentifier.Key, magicIdentifier.Value)
  152.        Me.chunkIDB = Me.GetByte(Me.HeaderOffset, chunkID.Key)
  153.        Me.sizeB = BitConverter.ToInt16(Me.GetBytes(Me.HeaderOffset, size.Key, size.Value), 0)
  154.        Me.endOfTextTableB = BitConverter.ToInt16(Me.GetBytes(Me.HeaderOffset, endOfTextTable.Key, endOfTextTable.Value), 0)
  155.        Me.offsetsAmountB = BitConverter.ToInt16(Me.GetBytes(Me.HeaderOffset, offsetsAmount.Key, offsetsAmount.Value), 0)
  156.        Me.entriesAmountB = BitConverter.ToInt16(Me.GetBytes(Me.HeaderOffset, entriesAmount.Key, entriesAmount.Value), 0)
  157.  
  158.        Me.TableTextOffset = Me.TableNonTextOffset + (8 * (entriesAmountB - 1)) + 2
  159.  
  160.        Me.ReadNonTextTable()
  161.        Me.ReadTextTable()
  162.  
  163.    End Sub
  164.  
  165.    ''' <summary>
  166.    ''' Reads the non-text table of the BMD file format.
  167.    ''' <para></para>
  168.    ''' This table seems not useful.
  169.    ''' </summary>
  170.    Private Sub ReadNonTextTable()
  171.  
  172.        For x As Integer = 0 To (entriesAmountB - 1)
  173.  
  174.            Dim offset As Integer = Me.TableNonTextOffset + (8 * x)
  175.            Dim data As Byte() = Me.GetBytes(offset, 0, 1)
  176.            Dim value As Short = BitConverter.ToInt16(data, 0)
  177.  
  178. #If DEBUG Then
  179.            Debug.WriteLine(String.Format("Entry.Index.: {0}", (x + 1)))
  180.            Debug.WriteLine(String.Format("Start.Offset: DEC={0,-4} HEX=0x{1}", offset, offset.ToString("X")))
  181.            Debug.WriteLine(String.Format("Raw.Bytes...: {0}", String.Join(" ", From b As Byte In data Select b.ToString("X"))))
  182.            Debug.WriteLine(String.Format("Int16.Value.: {0}", value))
  183.            Debug.WriteLine(String.Empty)
  184. #End If
  185.  
  186.        Next
  187.  
  188.    End Sub
  189.  
  190.    ''' <summary>
  191.    ''' Reads the text table of the BMD file format.
  192.    ''' <para></para>
  193.    ''' This table contains the items identifiers and their descriptions for further translation.
  194.    ''' </summary>
  195.    Private Sub ReadTextTable()
  196.  
  197.        For x As Integer = 0 To ...
  198.            ' ...?
  199.        Next
  200.  
  201.    End Sub
  202.  
  203.    Private Function GetByte(ByVal start As Integer, ByVal offset As Integer) As Byte
  204.        Return Buffer.GetByte(array:=Me.RawData, index:=start + offset)
  205.    End Function
  206.  
  207.    Private Function GetBytes(ByVal start As Integer, ByVal from As Integer, ByVal [to] As Integer) As Byte()
  208.        Return Me.rawDataB.Skip(start + from).Take(([to] - from) + 1).ToArray()
  209.    End Function
  210.  
  211. #End Region
  212.  
  213. End Class

Saludos!
« Última modificación: 31 Diciembre 2016, 16:38 pm por Eleкtro » En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Ayuda para parsear este formato...
« Respuesta #1 en: 11 Diciembre 2016, 18:14 pm »

Obtengo estos datos:
Código:
boots_2000
boots_2001
boots_2002
boots_2003
boots_2004
boots_2005
boots_2006
boots_2007
boots_2008
boots_2009
boots_200A
boots_200B
boots_200C
boots_200D
boots_200E
boots_200F
boots_2010
boots_2011
boots_2012
boots_2013
boots_2014
boots_2015
boots_2016
boots_2017
boots_2018
boots_2019
boots_201A
boots_201B
boots_201C
boots_201D
boots_201E
boots_201F
boots_2020
boots_2021
boots_2022
boots_2023
boots_2024
boots_2025
boots_2026
boots_2027
boots_2028
boots_2029
boots_202A
boots_202B
boots_202C
boots_202D
boots_202E
boots_202F
boots_2030
boots_2031
boots_2032
boots_2033
boots_2034
boots_2035
boots_2036
boots_2037
boots_2038
boots_2039
boots_203A
boots_203B
boots_203C
boots_203D
boots_203E
boots_203F
boots_2040
boots_2041
boots_2042
boots_2043
boots_2044
boots_2045
boots_2046
boots_2047
boots_2048
boots_2049
boots_204A
boots_204B
boots_204C
boots_204D
boots_204E
boots_204F
boots_2050
boots_2051
boots_2052
boots_2053
boots_2054
boots_2055
boots_2056
boots_2057
boots_2058
boots_2059
boots_205A
boots_205B
boots_205C
boots_205D
boots_205E
boots_205F
boots_2060
boots_2061

Con este código en C++:
Código
  1. #include <fstream>
  2. #include <iostream>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. struct BMDHeader{
  8. uint8_t chunkId;
  9. uint8_t __pad0[3];
  10. uint16_t fileSize;
  11. uint8_t __pad1[1];
  12. uint32_t magicIdentifier ;
  13. uint32_t _null_ : 32;
  14. uint16_t textTableEnd;
  15. uint8_t __pad2[2];
  16. uint16_t offsetAmount;
  17. uint8_t __pad3[2];
  18. uint8_t entryAmount;
  19. uint8_t __pad4[3];
  20. uint32_t _20000_;
  21. };
  22.  
  23. int main(){
  24.    /// READ FILE
  25. fstream inFile("datBootsHelp.bmd", ios::binary | ios::in);
  26. if(!inFile){
  27. cout << "File error" << endl;
  28. return 1;
  29. }
  30.  
  31. inFile.seekg(0, ios::end);
  32. string file(inFile.tellg(), '\0');
  33. inFile.seekg(0);
  34.  
  35. inFile.read(const_cast<char*>(file.data()), file.size());
  36.    /// FILE READED
  37.  
  38.    /// GETTING HEADER
  39. BMDHeader header = *(BMDHeader*)file.data();
  40. if(header._20000_ != 0x20000 || header.fileSize != file.size()){
  41.        cout << "Header error" << endl;
  42.        return 2;
  43. }
  44.    /// HEADER OK
  45.  
  46. cout << (int)header.entryAmount << " entries" << '\n' << endl;
  47.  
  48.    /// READING VALUES
  49.    vector<string> entries(header.entryAmount);
  50.  
  51.    for(int i=0; i<header.entryAmount; i++){
  52.        uint16_t offset = *(uint16_t*)&file[0x24 + 8 * i];
  53.        entries[i] = string(&file[0x20 + offset]);
  54.    }
  55.  
  56.    for(string& str :  entries){
  57.        cout << str << '\n';
  58.    }
  59.  
  60.    cout << '\n' << "ENDED" << endl;
  61. }

Eso sí, ignoré gran parte de los campos del header. No sé si son necesarias.

Y ya podías decir al menos de qué trataba el formato eh? Que tuve que descubrirlo xD http://datacrystal.romhacking.net/wiki/Persona_3_and_4/BMD_(File_Format)


EDITO:
Un poco hardcodeado para obtener los datos que faltan (a parte del ID):

Código
  1. #include <fstream>
  2. #include <iostream>
  3. #include <map>
  4.  
  5. using namespace std;
  6.  
  7. struct BMDHeader{
  8. uint8_t chunkId;
  9. uint8_t __pad0[3];
  10. uint16_t fileSize;
  11. uint8_t __pad1[1];
  12. uint32_t magicIdentifier ;
  13. uint32_t _null_ : 32;
  14. uint16_t textTableEnd;
  15. uint8_t __pad2[2];
  16. uint16_t offsetAmount;
  17. uint8_t __pad3[2];
  18. uint8_t entryAmount;
  19. uint8_t __pad4[3];
  20. uint32_t _20000_;
  21. };
  22.  
  23. int main(){
  24.    /// READ FILE
  25. fstream inFile("datBootsHelp.bmd", ios::binary | ios::in);
  26. if(!inFile){
  27. cout << "File error" << endl;
  28. return 1;
  29. }
  30.  
  31. inFile.seekg(0, ios::end);
  32. string file(inFile.tellg(), '\0');
  33. inFile.seekg(0);
  34.  
  35. inFile.read(const_cast<char*>(file.data()), file.size());
  36.    /// FILE READED
  37.  
  38.    /// GETTING HEADER
  39. BMDHeader header = *(BMDHeader*)file.data();
  40. if(header._20000_ != 0x20000 || header.fileSize != file.size()){
  41.        cout << "Header error" << endl;
  42.        return 2;
  43. }
  44.    /// HEADER OK
  45.  
  46. cout << (int)header.entryAmount << " entries" << '\n' << endl;
  47.  
  48.    /// READING VALUES
  49.    map<string, string> entries;
  50.  
  51.    for(int i=0; i<header.entryAmount; i++){
  52.        uint16_t offset = *(uint16_t*)&file[0x24 + 8 * i];
  53.        string id = string(&file[0x20 + offset]);
  54.        entries[id] = string(&file[0x20 + offset + id.size() + 0x20]);
  55.    }
  56.  
  57.    for(auto& p :  entries){
  58.        cout << p.first << ":\n";
  59.        cout << p.second << "\n\n";
  60.    }
  61.  
  62.    cout << '\n' << "ENDED" << endl;
  63. }
Datos:
Código:
boots_2000:
Reserve


boots_2001:
Solidly made
work boots.


boots_2002:
An ordinary pair of
loafers.


boots_2003:
Long, black boots.


boots_2004:
Boots with a horizontal
line over the toes.


boots_2005:
Classic-model sneakers.


boots_2006:
Shoes for playing
indoor soccer.


boots_2007:
Low-heeled boots.


boots_2008:
Sandals that massage
your pressure points.


boots_2009:
Strong enough to take
any punishment.


boots_200A:
Boots with thick soles.


boots_200B:
Sandals with many
bumps.


boots_200C:
Boots made out of
leather.


boots_200D:
Shoes with a single
row of wheels.


boots_200E:
Geta made with the
latest technology.


boots_200F:
Boots from military
surplus.


boots_2010:
Greaves colored
a dark red.


boots_2011:
Sandals that boost
the wearer's magic.


boots_2012:
Shoes made with
modern technology.


boots_2013:
Sandals worn by
ninjas.


boots_2014:
Shoes with needles
on the soles.


boots_2015:
Boots with jet engines
attached.


boots_2016:
Exceptionally durable
greaves.


boots_2017:
Very light shoes.


boots_2018:
Sandals with dazzling
silver ornaments.


boots_2019:
0x2019


boots_201A:
0x201A


boots_201B:
Shoes with pentacle
symbols.


boots_201C:
Hitmen's favorite
shoes.


boots_201D:
Unbelievably light
pair of sandals.


boots_201E:
A war god's spirit
dwells in these boots.


boots_201F:
Boots that have been
blessed.


boots_2020:
Women's boots that
lend beauty.


boots_2021:
A famous ninja's
sandals.


boots_2022:
0x2022


boots_2023:
0x2022


boots_2024:
Men's boots embroidered
with dragons.


boots_2025:
Can supposedly be
remote-controlled...


boots_2026:
0x2026


boots_2027:
A manly pair of
geta, for men.


boots_2028:
Shoes with vicious-
looking spikes.


boots_2029:
0x2029


boots_202A:
Sandals with a lion
drawn on them.


boots_202B:
Men's greaves, worn
by a veteran warrior.


boots_202C:
0x202C


boots_202D:
0x202D


boots_202E:
Sandals with a fresh
grass scent.


boots_202F:
0x202F


boots_2030:
0x2030


boots_2031:
0x2031


boots_2032:
Savior's boots worn
only by men.


boots_2033:
0x2033


boots_2034:
Leopard-print leggings
for women.


boots_2035:
0x2035


boots_2036:
Lightweight pumps
for women.


boots_2037:
0x2037


boots_2038:
Heels that make women
supersexy.


boots_2039:
0x2039


boots_203A:
0x203A


boots_203B:
0x203B


boots_203C:
Women's boots that
last forever.


boots_203D:
The paw pads are very
soft to the touch.


boots_203E:
0x203E


boots_203F:
0x203F


boots_2040:
0x2040


boots_2041:
0x2041


boots_2042:
0x2042


boots_2043:
0x2043


boots_2044:
0x2044


boots_2045:
0x2045


boots_2046:
0x2046


boots_2047:
Ordinary leg parts for
Aigis.


boots_2048:
Leg parts for Aigis made
with strong fibers.


boots_2049:
Processed iron leg parts
for Aigis.


boots_204A:
Molecularly cohesive leg
parts for Aigis.


boots_204B:
Ceramic leg parts for
Aigis.


boots_204C:
Cobalt leg parts for
Aigis.


boots_204D:
Lightweight leg parts for
Aigis.


boots_204E:
Alloyed leg parts for
Aigis.


boots_204F:
Consolidated leg parts
for Aigis.


boots_2050:
Leg parts for Aigis from
the Beast God.


boots_2051:
2051


boots_2052:
2052


boots_2053:
Shining leg parts for
Metis.


boots_2054:
Leather-covered leg parts
for Metis.


boots_2055:
Resin leg parts for Metis.


boots_2056:
Light ceramic leg parts
for Metis.


boots_2057:
Light alloy leg parts for
Metis.


boots_2058:
Titanium leg parts for
Metis.


boots_2059:
Zirconium leg parts for
Metis.


boots_205A:
Imitation dancing shoes
for Metis.


boots_205B:
Magical leg parts for
Metis.


boots_205C:
Crimson leg parts for
Metis.


boots_205D:
Angelic leg parts for
Aigis.


boots_205E:
Mysterious glass leg
parts for Metis.


boots_205F:
The ultimate prototype
leg parts for Aigis.


boots_2060:
Supreme pitch-black leg
parts for Metis.


boots_2061:
ü·ü╩ü┘

Tengo que ver cómo obtener los datos, ya que no parece que hablen de ello en lo del formato.

EDITO:
Mejorado. Ahora capta bien el mensaje (salvo para el último, que no parece tener el mismo formato (o el formato está mal interpretado))

Y con respecto a lo que dices de cuándo acaba la primera tabla y cuándo empieza la segunda, yo me limité a lo que dice esa web y utilizar directamente el offset "Text offset relative from offset 20". Sumarlo, para saber la posición de la celda de texto, y listo. Iterar por cada elemento de la primera tabla, y se acabó.
« Última modificación: 11 Diciembre 2016, 18:52 pm por ivancea96 » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.788



Ver Perfil
Re: Ayuda para parsear este formato...
« Respuesta #2 en: 13 Diciembre 2016, 10:57 am »

@ivancea96
Joder, no me esperaba una ayuda tan gratificante, ¡muchísimas gracias!. Más tarde me pondré a analizar el código e intentar reproducirlo en VB.NET.

PD: No quise decir de que trataba el formato BMD por cuestiones éticas, para no dar motivo a que se cierre el post, de todas formas en el código que compartí, arriba en la cabecera habia una url a esa wiki... xD.

EDITO: Veo que la cantidad de identificadores de items (boots_*) que obtuviste son 98, y el valor "98" se puede obtener en la cabecera del formato, y además el 98 también hace referencia a la cantidad de valores que hay en la primera tabla, así que deduzco que esos 98 valores de la primera tabla deberán especificar la longitud de cada bloque de la segunda tabla, genial!
 
Saludos y gracias de nuevo por tu tiempo!
« Última modificación: 13 Diciembre 2016, 11:10 am por Eleкtro » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.788



Ver Perfil
Re: Ayuda para parsear este formato...
« Respuesta #3 en: 31 Diciembre 2016, 16:11 pm »

Hola. Dejé a un lado este proyecto por un tiempo y hoy he vuelto a ponerme. @ivancea96, estoy adaptando tu código, pero tengo una duda...

¿Cómo determinas la longitud del campo "id" (9 caracteres legibles en este caso, 42 de espacio en total creo) y del texto/descripción del item?.

En esta iteración no veo que determines la longitud de "id" ni tampoco de "entries[0]", ¿como es posible entonces?, no lo entiendo.

Código
  1.    for(int i=0; i<header.entryAmount; i++){
  2.        uint16_t offset = *(uint16_t*)&file[0x24 + 8 * i];
  3.        string id = string(&file[0x20 + offset]);
  4.        entries[id] = string(&file[0x20 + offset + id.size() + 0x20]);
  5.    }

En serio, ¿como determinas el tamaño que tiene "id" y cada elemento del array "entries"?.

EDITO: Estoy leyendo una referencia online de C++, no se si esto tiene algo que ver pero creo que cuando usas string file(inFile.tellg(), '\0'); devuelve la posición del caracter evaluado "\0" (¿está \escapado?, no me queda muy claro si eso es un "0", no se nada de c/c++).



Esta sería mi adaptación de tu iteración, INACABADA... por que desconozco la longitud de esos campos.
Código
  1. For x As Integer = 0 To (entryAmountB - 1)
  2.  
  3.    Dim offset As Integer = Me.TableNonTextOffset + (8 * x)
  4.    Dim value As Short = BitConverter.ToInt16(Me.GetBytes(offset, 0, 1), 0)
  5.  
  6.    Dim idOffset As Short = (&H20 + value)
  7.    Dim id As String = Encoding.UTF8.GetString(Me.GetBytes(idOffset, 0, LONGITUD_DE_ID))
  8.  
  9.    Dim textOffset As Short = (idOffset + id.Length() + &H20)
  10.    Dim text As String = Encoding.UTF8.GetString(Me.GetBytes(textOffset, 0, LONGITUD_DE_TEXTO))
  11.  
  12.    Debug.WriteLine(String.Format("Entry.Id...: {0}", id))  ' boots_nnnn
  13.    Debug.WriteLine(String.Format("Entry.Text.: {0}", text)) ' el texto/descripción del item
  14.  
  15. Next

Cada texto de "boots_nnnn" termina con una secuencia de bytes parecida a estas:
Código:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 FF FF 44 03 00 00 0F 00 00 00 F2 08 FF FF F1 3F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 FF FF 78 03 00 00 20 00 00 00 F2 08 FF FF F1 3F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 FF FF C4 05 00 00 2D 00 00 00 F2 08 FF FF F1 3F

Despues de esa secuencia comienza el texto/descripción del item, y ese texto siempre parece terminar con la secuencia de bytes 2E 0A.

Sabiendo eso, creo que puedo determinar facilmente la longitud de cada campo, pero me gustaría comprender como lo haces en tu código, por que pareces conocer la longitud de forma más simple y eficiente.

Saludos!
« Última modificación: 31 Diciembre 2016, 16:42 pm por Eleкtro » En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Ayuda para parsear este formato...
« Respuesta #4 en: 31 Diciembre 2016, 17:00 pm »

el constructor de la clase string en C++, si no le pasas un tamaño, coge hasta el próximo caracter nulo ('\0'). Si no recuerdo mal, ese campo es de tamaño variable, y el resto de la memoria, la no utilizada, está rellena con caracteres nulos.
Así que eso, dura ahsta el próximo caracter nulo.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Ayuda para ver un dvd que esta en formato .iso!!!
Multimedia
brank87 2 2,041 Último mensaje 14 Octubre 2005, 22:10 pm
por brank87
necesito ayuda para cambiar el formato!!
Multimedia
gaye 2 2,083 Último mensaje 7 Noviembre 2005, 18:20 pm
por ™Carlos.®
ayuda para cambiar formato de mpg a un avi
Multimedia
morbid 3 2,130 Último mensaje 27 Diciembre 2005, 18:27 pm
por Songoku
ayuda para convertir de .avi(Xdiv) a formato DVD
Multimedia
Commander 3 3,398 Último mensaje 10 Febrero 2008, 06:43 am
por sempus
Programa para quemar peliculas bajadas en formato divx y avi, a formato dvd
Multimedia
xoux 3 5,354 Último mensaje 28 Abril 2008, 08:37 am
por Aberroncho
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines