Rev 288 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
#include <math.h>
#include <stdlib.h>
#include "imgtypes.h"
#include "garminimg.h"
#include "decoder.h"
#include "decode_img.h"
static class GarminImg *img;
static class ImgFile *ifile;
static class ImgNET *net;
static class ImgNOD *nod;
static class Decoder *dec;
void decode_net_roads ();
void decode_net_sorted ();
void decode_net_header (class Decoder *dec_in, class ImgNET *net_in)
{
udword_t length, offset;
uword_t rsize;
off_t soffset, eoffset, hoffset;
net= net_in;
dec= dec_in;
img= dec->img;
ifile= net->ifile;
nod= (ImgNOD *) ifile->subfile_find("NOD");
soffset= net->offset();
hoffset= net->h_offset();
img->seek(hoffset);
dec->set_outfile("NET", "header");
dec->banner("NET: Header");
decode_common_header(dec, net);
dec->print("Road defs at offset 0x%08x",
offset= img->get_udword()+soffset);
dec->print("Road defs length %ld bytes",
length= img->get_udword());
ifile->offset_add(offset, NET_ROAD_DEF);
net->roads_info.offset= offset;
net->roads_info.length= length;
dec->print("Road record offsets are x%u",
net->omult1= int(pow(2.0,img->get_byte())));
dec->print("Unknown1 at offset 0x%08x",
offset= img->get_udword()+soffset);
dec->print("Unknown1 length %ld bytes",
length= img->get_udword());
dec->print("Unknown1 offsets are x%u",
net->omult2= int(pow(2.0,img->get_byte())));
ifile->offset_add(offset, NET_UNKN1);
net->unknown1_info.offset= offset;
net->unknown1_info.length= length;
dec->print("Unknown2 at offset 0x%08x",
offset= img->get_udword()+soffset);
dec->print("Unknown2 length %ld bytes",
length= img->get_udword());
dec->print("Unknown2 record size %u bytes",
rsize= img->get_uword());
ifile->offset_add(offset, NET_UNKN1);
net->sorted_info.offset= offset;
net->sorted_info.length= length;
net->sorted_info.rsize= rsize;
dec->print("???", img->get_udword());
dec->print("???", img->get_byte());
dec->print("???", img->get_byte());
dec->print("???", img->get_udword());
dec->print("???", img->get_udword());
dec->print("???", img->get_udword());
dec->banner("NET: End Header");
}
void decode_net_body ()
{
// Sorted road list
decode_net_sorted ();
// Parse road information first.
decode_net_roads ();
}
void decode_net_roads ()
{
// These have variable-length records that have not been
// deciphered. So, use the offsets that we created when
// parsing RGN to determine the start of each record.
off_t soffset= net->roads_info.offset;
off_t eoffset= soffset+net->roads_info.length;
img->seek(net->roads_info.offset);
dec->set_outfile("NET", "roads");
dec->banner("NET: Road definitions?");
while ( img->tell() < eoffset ) {
udword_t lbloffset, roadinfo;
double roadlen;
byte_t data, flags;
bool repeat;
off_t noffset;
int i, n, lcount;
unsigned int otype;
string stream, shas;
bool has_addr, has_nod, has_dir;
otype= ifile->offset_find(img->tell());
if ( otype != NET_ROAD_REC && otype != NET_ROAD_DEF ) {
fprintf(stderr, "Not a known offset at 0x%08x",
img->tell());
exit(1);
}
dec->comment(NULL);
dec->comment("Road offset 0x%06x", img->tell()-soffset);
if ( img->tell() == soffset ) {
if ( img->get_byte() == 0x2f ) {
dec->print("NULL record?");
} else img->seek(-1, SEEK_CUR);
}
repeat= true;
while ( repeat ) {
bool net2ptr;
lbloffset= img->get_uint24();
repeat= !(lbloffset & 0x800000);
net2ptr= (lbloffset & 0x400000);
lbloffset&= 0x3FFFFF;
dec->print("Label 0x%06x: %s", lbloffset,
ifile->label_get(lbloffset).c_str());
if ( net2ptr ) {
udword_t n2offset= img->get_uint24();
dec->print("NET2 offset 0x%06x", n2offset);
}
}
flags= img->get_byte();
dec->print("Road flags %s",
img->base(flags, 2, 8).c_str());
shas.clear();
has_dir= flags&0x02;
has_addr= flags&0x10;
has_nod= flags&0x40;
if ( has_addr ) shas+= " addr";
if ( has_nod ) shas+= " nod";
if ( has_dir ) shas+= " direction";
if ( shas.size() ) dec->comment("has%s", shas.c_str());
roadlen= ((double) img->get_uint24()) * 7.8369461;
if ( roadlen < 528 )
dec->print("Road len %d ft", (int) roadlen);
else
dec->print("Road len %.2f mi", roadlen/5280.0);
repeat= true;
n= lcount= 0;
while ( repeat ) {
int cnt;
data= img->get_byte();
repeat= !(data&0x80);
cnt= (data&0x7F);
n+= cnt;
dec->print("%u indices in level %u", cnt, lcount);
++lcount;
}
for (i= 0; i< n; ++i) {
roadinfo= img->get_uint24();
dec->print("Index %u, subdiv %u",
(roadinfo&0xFF), (roadinfo&0xFFFF00)>>8);
}
if ( has_addr ) {
string sfields= "Fields 1-3:";
int fields[4];
dec->print("%u address blocks", img->get_byte());
data= img->get_byte();
for (i= 1; i<= 3; ++i) {
byte_t mask= 0x3<<(i*2);
byte_t val= (data&mask)>>(i*2);
switch (val) {
case 0x0:
// number field
sfields+= " nmbr";
break;
case 0x1:
// unknown
sfields+= " ???";
break;
case 0x2:
// LBL field
sfields+= " lbl";
break;
case 0x3:
// empty
sfields+= " empty";
break;
}
fields[i]= val;
}
dec->print("%s", sfields.c_str());
for (i= 1; i<= 3; ++i) {
string label;
byte_t val;
switch (fields[i]) {
case 0x0:
dec->print("field %u: %d bytes", i,
val= img->get_byte());
dec->print("???",
img->get_string(val).c_str());
break;
case 0x1:
dec->print("???", img->get_byte());
break;
case 0x2:
switch (i) {
case 1:
val= ( ifile->ncities()>255 ) ?
img->get_uword() :
img->get_byte();
dec->print("Zip idx %u", val);
break;
case 2:
val= ( ifile->nzips()>255 ) ?
img->get_uword() :
img->get_byte();
dec->print("City idx %u", val);
break;
case 3:
dec->print("???",
img->get_byte());
break;
}
break;
}
}
}
if ( has_nod ) {
data= img->get_byte();
off_t nodoff;
if ( data & 0x1 ) {
dec->print("Two-byte NOD offset");
nodoff= img->get_uword();
} else if ( data & 0x3 ) {
dec->print("Three-byte NOD offset");
nodoff= img->get_uint24();
}
dec->print("NOD offset 0x%06x", nodoff);
ifile->offset_add(nodoff+nod->unknown2_info.offset,
NOD_UNKN2);
}
if ( ifile->offset_find(img->tell()) ) continue;
noffset= ifile->offset_next(img->tell());
if ( noffset > eoffset || noffset == 0 ) noffset= eoffset;
stream= img->get_string(noffset-img->tell());
dec->print("%u byte stream", stream.length());
}
}
void decode_net_sorted ()
{
off_t soffset= net->sorted_info.offset;
off_t eoffset= soffset+net->sorted_info.length;
off_t rdoffset= net->roads_info.offset;
uword_t nrecs= net->sorted_info.length/net->sorted_info.rsize;
uword_t i;
img->seek(net->sorted_info.offset);
dec->set_outfile("NET", "sorted_roads");
dec->banner("NET: Sorted roads");
for (i= 1; i<= nrecs; ++i) {
udword_t lblinfo;
off_t offset;
int num;
dec->comment("Record %u", i);
lblinfo= img->get_uint24();
offset= lblinfo&0x3FFFFF;
num= ((lblinfo&0xC00000)>>22)+1;
dec->print("Label %u, offset 0x%06x", num, offset);
ifile->offset_add(rdoffset+offset, NET_ROAD_DEF);
dec->comment(NULL);
}
}