Rev 1 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "bob_dom_cut.h"
#include "../common/indian.h"
static int g_i;
#define BOB_WRITE(fd, i) (g_i=be2le((unsigned int)i), write(fd, &g_i, sizeof(i)))
#define max(a, b) (a > b ? a : b)
//---------------------------------------------------------------------------------
bool bob_dom_name::toFile(bob_dom_otextfilestream& os)
{
if(m_text && *m_text!=0) {
int oldf=os.flags();
os << noSemicolons << "N " << autoSemicolons << m_text;
os.flags(oldf);
}
return os.good();
}
//---------------------------------------------------------------------------------
// STAT
#ifdef X2BC_USE_INI_FORMATS
bool bob_dom_stat::load(bob_dom_ibinaryfilestream& is, const Settings *settings)
{
is >> frameId;
m_format=settings->findStatFormat(frameId);
if(m_format==NULL){
error(s_error, e_format_noStatFormat, "Cannot find STAT format 0x%X", frameId);
setstate(bob_dom_stat::noFormat);
}
else{
int v;
for(Settings::StatFormat::const_iterator &it=m_format->tokens.begin(); it!=m_format->tokens.end(); ++it){
for(int i=0; i < it->count; i++){
is >> v;
push_back(v);
}
if(is.fail()){
error(s_error, e_format_notEnoughData, "Not enough data to match format 0x%X", frameId);
setstate(cannotMatchFormat);
break;
}
}
}
return rdstate()==formatted;
}
//---------------------------------------------------------------------------------
bool bob_dom_stat::toFile(bob_dom_obinaryfilestream& os)
{
os << frameId;
for(iterator &it=begin(); it!=end(); ++it){
os << *it;
}
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_stat::toFile(bob_dom_otextfilestream& os, const Settings *settings)
{
os << noSemicolons;
if(rdstate()!=formatted && settings->outputWarnings()){
os << "// Error: STAT frame id=" << hex << "0x" << frameId << dec;
if(rdstate()==noFormat)
os << ": cannot find frame format";
else
os << ": unable to match frame format";
}
else{
if(settings->statFormatWarnings() && settings->outputWarnings() && m_format->issueWarning)
os << "// Warning: Format 0x" << hex << m_format->id << " was used and it's marked with warning sign" << endl;
double val;
os << "{ ";
os << hex << "0x" << frameId << "; " << dec;
iterator &valit=begin();
for(Settings::StatFormat::const_iterator &it=m_format->tokens.begin(); it!=m_format->tokens.end(); ++it){
for(int i=0; i < it->count; i++){
val=*valit;
if(settings->convert())
val*=it->numFormat->multiplier;
if(settings->convert() && it->numFormat->outformat==Settings::NumberFormat::Float)
os << (float)val;
else
os << (int)val;
os << ';';
++valit;
}
if(it->data)
os << it->data;
}
os << noSemicolons << " }";
}
return os.good();
}
//---------------------------------------------------------------------------------
#endif // defined(X2BC_USE_INI_FORMATS)
// PATH
bool bob_dom_path::load(bob_dom_ibinaryfilestream& is, int version)
{
int hdr;
is >> hdr;
if(hdr!=hdr_begin){
error(e_badHeader);
return false;
}
is >> partIdx;
if(version < 6) {
int bid;
is >> bid;
m_bodyId=new char[20];
_itoa(bid, m_bodyId, 10);
}
else
is >> m_bodyId;
is >> cockpitIdx >> parentIdx >> bodyFlags;
if(peek(is)==bob_dom_name::hdr_begin){
if(name.load(is)==false){
for(ErrorIterator &it=name.errors.begin(); it!=name.errors.end(); ++it){
error(it->code, "name: %s", it->text);
}
return false;
}
}
if(peek(is)==bob_dom_constants::hdr_begin){
if(constants.load(is)==false){
for(ErrorIterator &it=name.errors.begin(); it!=name.errors.end(); ++it){
error(it->code, "constants: %s", it->text);
}
return false;
}
}
if(peek(is)==bob_dom_bob::hdr_begin){
bob=new bob_dom_bob(m_settings);
if(bob->load(is)==false){
for(ErrorIterator &it=bob->errors.begin(); it!=bob->errors.end(); ++it){
error(it->code, "bob->%s", it->text);
}
return false;
}
}
int noteLineCount;
is >> noteLineCount;
if(noteLineCount > 0){
if(m_notes.load(is, noteLineCount)==false){
for(ErrorIterator &it=m_notes.errors.begin(); it!=m_notes.errors.end(); ++it){
error(it->code, "notes->%s", it->text);
}
return false;
}
}
int statCount;
is >> statCount;
if(loadStatValues(is, statCount)==false) return false;
is >> hdr;
if(is.fail())
error(e_notEnoughData);
else if(hdr!=hdr_end)
error(e_badEndHeader);
/////////////////
//if(hdr==hdr_end) formatStats();
////////////////
return hdr==hdr_end && !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_path::loadStatValues(bob_dom_ibinaryfilestream& is, int count)
{
int hdr;
is >> hdr;
if(hdr!=hdr_stat_begin){
error(e_badHeader, "Expected STAT header.");
return false;
}
child_type *ch;
bool bRes;
for(int i=0; i < count; i++){
ch=createChild();
#ifdef X2BC_USE_INI_FORMATS
bRes=ch->load(is, m_settings);
#else
bRes=ch->load(is);
#endif
for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
error(it->severity, it->code, "stat->frame[%d]: %s", i, it->text);
}
if(bRes==false) break;
}
is >> hdr;
if(hdr!=hdr_stat_end){
error(s_error, e_moreData, "More data in STAT section than expected - skipping");
do{
is >> hdr;
}
while(hdr!=hdr_stat_end && is.good());
}
if(hdr!=hdr_stat_end)
error(e_notEnoughData);
return hdr==hdr_stat_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_path::toFile(bob_dom_obinaryfilestream& os, int cutVersion)
{
os << hdr_begin;
os << partIdx;
if(cutVersion >= 6)
os << bodyId();
else
os << atoi(bodyId());
os << cockpitIdx;
os << parentIdx;
os << bodyFlags;
os << name;
constants.toFile(os);
if(bob) bob->toFile(os);
os << (int)m_notes.size();
m_notes.toFile(os);
os << (int)size();
os << hdr_stat_begin;
for(iterator &it=begin(); it!=end(); ++it){
it->toFile(os);
}
os << hdr_stat_end << hdr_end;
return true;
}
//---------------------------------------------------------------------------------
bool bob_dom_path::toFile(bob_dom_otextfilestream& os, int idx)
{
os << noSemicolons << "P " << partIdx << "; B " << bodyId() << "; ";
if(parentIdx!=-1)
os << "F " << parentIdx << "; ";
if(cockpitIdx > 0)
os << "C " << cockpitIdx << "; ";
os << name;
constants.toFile(os);
/*
we've got old x2 flags and new x3 flags
these 2 can be mixed together
for example body || light
only the body (64) and scene (128) can be mixed with anything else imho
*/
if(bodyFlags!=0) {
if(bodyFlags & BodyFlags::fBody)
os << "b ";
if(bodyFlags & BodyFlags::fScene)
os << "j ";
int i=bodyFlags & 0x3F;
if(i)
os << (char) ('b' + i) << ' ';
}
os << "// idx " << idx << ", flags: " << bodyFlags << endl;
if(m_notes.size())
m_notes.toFile(os);
if(bob){
os << noSemicolons << "L { // beginning of embedded BOB" << endl;
os << *bob << "} // end of embedded BOB" << endl << endl;
}
int i=0;
for(iterator &it=begin(); it!=end(); ++it, ++i){
#ifdef X2BC_USE_INI_FORMATS
it->toFile(os, m_settings);
#else
it->toFile(os);
#endif
os << " // " << i << endl;
}
os << endl;
return os.good();
}
//---------------------------------------------------------------------------------
// CUT file
bool bob_dom_cut::load(bob_dom_ibinaryfilestream& is)
{
int hdr;
is >> hdr;
if(hdr!=hdr_begin){
error(e_badHeader);
return false;
}
if(peek(is)==bob_dom_info::hdr_begin){
if(!info.load(is)){
for(ErrorIterator &it=info.errors.begin(); it!=info.errors.end(); ++it){
error(it->code, "info: %s", it->text);
}
return false;
}
}
is >> version;
if(version!=supported_version)
error(s_warning, e_badVersion, "Unsupported CUT1 version, loading might fail");
is >> m_storedPathCount;
child_type *ch;
for(int i=0; i < m_storedPathCount; i++){
ch=createChild();
bool bRes=ch->load(is, version);
for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
error(it->code, "path[%d]->%s", i, it->text);
}
if(bRes==false) return false;
}
is >> hdr;
if(hdr!=hdr_end)
error(e_badEndHeader);
return hdr==hdr_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_cut::convert(bob_dom_ibinaryfilestream& is, bob_dom_otextfilestream& os)
{
int hdr;
is >> hdr;
if(hdr!=hdr_begin){
error(e_badHeader);
return false;
}
if(peek(is)==bob_dom_info::hdr_begin){
if(!info.load(is)){
for(ErrorIterator &it=info.errors.begin(); it!=info.errors.end(); ++it){
error(it->code, "info: %s", it->text);
}
return false;
}
}
is >> version;
os << info << endl << "VER: " << autoSemicolons << version << endl << endl;
is >> m_storedPathCount;
child_type *ch;
for(int i=0; i < m_storedPathCount; i++){
ch=new bob_dom_path(m_settings);
bool bRes=ch->load(is, version);
for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
error(it->code, "path[%d]->%s", i, it->text);
}
if(bRes)
ch->toFile(os, i);
delete ch;
if(bRes==false) return false;
}
is >> hdr;
if(hdr!=hdr_end)
error(e_badEndHeader);
return hdr==hdr_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_cut::toFile(bob_dom_obinaryfilestream& os)
{
os << hdr_begin << info << version << (int)size();
for(iterator &it=begin(); it!=end(); ++it){
it->toFile(os, version);
}
os << hdr_end;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_cut::toFile(bob_dom_otextfilestream& os)
{
os << noSemicolons << info << endl;
os << "VER: " << autoSemicolons << version << endl << endl;
int idx=0;
for(iterator &it=begin(); it!=end(); ++it){
it->toFile(os, idx++);
os << endl;
}
return os.good();
}
//---------------------------------------------------------------------------------
// NOTES - section NOTE
bool bob_dom_notes::load(bob_dom_ibinaryfilestream& is, int lineCount)
{
int hdr;
is >> hdr;
if(hdr!=hdr_begin){
error(e_badHeader);
return false;
}
child_type *ch;
for(int i=0; i < lineCount; i++){
ch=createChild();
if(ch->load(is)==false){
error(ch->errorCode, "line[%d]: %s", i, bob_traslate_error(ch->errorCode));
return false;
}
}
is >> hdr;
if(hdr!=hdr_end)
error(e_badEndHeader);
return hdr==hdr_end && !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_notes::toFile(bob_dom_obinaryfilestream& os)
{
if(size()==0) return true;
os << hdr_begin;
for(iterator &it=begin(); it!=end(); ++it){
it->toFile(os);
}
os << hdr_end;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_notes::toFile(bob_dom_otextfilestream& os)
{
os << noSemicolons << "T // Notes" << endl;
for(iterator &it=begin(); it!=end(); ++it){
it->toFile(os);
os << endl;
}
os << -1 << " // end of Notes" << endl;
return os.good();
}
//---------------------------------------------------------------------------------
// NOTE - object
bool bob_note::load(bob_dom_ibinaryfilestream& is)
{
is >> value;
is >> text;
if(is.fail())
errorCode=e_notEnoughData;
return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_note::toFile(bob_dom_obinaryfilestream& os)
{
os << value << text;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_note::toFile(bob_dom_otextfilestream& os)
{
os << autoSemicolons << value << text;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::load(bob_dom_ibinaryfilestream& is)
{
int hdr, count;
is >> hdr;
if(hdr!=hdr_begin){
error(e_badHeader);
return false;
}
is >> count;
constant c;
for(int i=0; i < count; i++){
c.load(is);
values.push_back(c);
}
is >> hdr;
if(hdr!=hdr_end){
error(e_badEndHeader);
return false;
}
return is.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::toFile(bob_dom_obinaryfilestream& os)
{
if(values.size()==0) return true;
os << hdr_begin << (int)values.size();
for(iterator &it=values.begin(); it!=values.end(); ++it){
(*it).toFile(os);
}
os << hdr_end;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::toFile(bob_dom_otextfilestream& os)
{
if(values.size()==0) return true;
os << noSemicolons << "K " << autoSemicolons << (int)values.size();
for(iterator &it=values.begin(); it!=values.end(); ++it){
(*it).toFile(os);
}
os << noSemicolons;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::constant::load(bob_dom_ibinaryfilestream& is)
{
is >> a >> b;
return is.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::constant::toFile(bob_dom_obinaryfilestream& os)
{
os << a << b;
return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::constant::toFile(bob_dom_otextfilestream& os)
{
os << a << b;
return os.good();
}
//---------------------------------------------------------------------------------