Obtengo estos datos:
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++:
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
struct BMDHeader{
uint8_t chunkId;
uint8_t __pad0[3];
uint16_t fileSize;
uint8_t __pad1[1];
uint32_t magicIdentifier ;
uint32_t _null_ : 32;
uint16_t textTableEnd;
uint8_t __pad2[2];
uint16_t offsetAmount;
uint8_t __pad3[2];
uint8_t entryAmount;
uint8_t __pad4[3];
uint32_t _20000_;
};
int main(){
/// READ FILE
fstream inFile("datBootsHelp.bmd", ios::binary | ios::in);
if(!inFile){
cout << "File error" << endl;
return 1;
}
inFile.seekg(0, ios::end);
string file(inFile.tellg(), '\0');
inFile.seekg(0);
inFile.read(const_cast<char*>(file.data()), file.size());
/// FILE READED
/// GETTING HEADER
BMDHeader header = *(BMDHeader*)file.data();
if(header._20000_ != 0x20000 || header.fileSize != file.size()){
cout << "Header error" << endl;
return 2;
}
/// HEADER OK
cout << (int)header.entryAmount << " entries" << '\n' << endl;
/// READING VALUES
vector<string> entries(header.entryAmount);
for(int i=0; i<header.entryAmount; i++){
uint16_t offset = *(uint16_t*)&file[0x24 + 8 * i];
entries[i] = string(&file[0x20 + offset]);
}
for(string& str : entries){
cout << str << '\n';
}
cout << '\n' << "ENDED" << endl;
}
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):
#include <fstream>
#include <iostream>
#include <map>
using namespace std;
struct BMDHeader{
uint8_t chunkId;
uint8_t __pad0[3];
uint16_t fileSize;
uint8_t __pad1[1];
uint32_t magicIdentifier ;
uint32_t _null_ : 32;
uint16_t textTableEnd;
uint8_t __pad2[2];
uint16_t offsetAmount;
uint8_t __pad3[2];
uint8_t entryAmount;
uint8_t __pad4[3];
uint32_t _20000_;
};
int main(){
/// READ FILE
fstream inFile("datBootsHelp.bmd", ios::binary | ios::in);
if(!inFile){
cout << "File error" << endl;
return 1;
}
inFile.seekg(0, ios::end);
string file(inFile.tellg(), '\0');
inFile.seekg(0);
inFile.read(const_cast<char*>(file.data()), file.size());
/// FILE READED
/// GETTING HEADER
BMDHeader header = *(BMDHeader*)file.data();
if(header._20000_ != 0x20000 || header.fileSize != file.size()){
cout << "Header error" << endl;
return 2;
}
/// HEADER OK
cout << (int)header.entryAmount << " entries" << '\n' << endl;
/// READING VALUES
map<string, string> entries;
for(int i=0; i<header.entryAmount; i++){
uint16_t offset = *(uint16_t*)&file[0x24 + 8 * i];
string id = string(&file[0x20 + offset]);
entries[id] = string(&file[0x20 + offset + id.size() + 0x20]);
}
for(auto& p : entries){
cout << p.first << ":\n";
cout << p.second << "\n\n";
}
cout << '\n' << "ENDED" << endl;
}
Datos:
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ó.