Index: decode_header.cc
===================================================================
--- decode_header.cc	(revision 2)
+++ decode_header.cc	(working copy)
@@ -12,7 +12,8 @@
 	byte_t byte;
 	string str;
 	time_t ts;
-	udword_t subfile_offset;
+	udword_t subfile_offset= 0xffffffff;
+	byte_t dir_start;
 	
 	dec->set_outfile("DSKIMG", "header");
 	dec->print("XOR byte 0x%02x", img->xorbyte);
@@ -32,15 +33,15 @@
 	dec->print("%u sectors?", img->get_uword());
 	dec->print("%u heads?", img->get_uword());
 
+	dec->print("%u cyls", img->get_uword());
 	dec->print("???", img->get_word());
-	dec->print("???", img->get_word());
 
 	dec->print("%s", img->get_string(25).c_str());
 
 	ts= img->get_date();
 	dec->print("Created %24.24s", ctime(&ts));
 
-	dec->print("???", img->get_byte());
+	dec->print("Dir start?", (dir_start = img->get_byte()));
 
 	dec->print("%s", img->get_string(7).c_str());
 
@@ -72,8 +73,10 @@
 	dec->print("%u start-cylinder?", img->get_byte());
 	dec->print("%u system-type?", img->get_byte());
 	dec->print("%u end-head?", img->get_byte());
-	dec->print("%u end-sector?", img->get_byte());
-	dec->print("%u end-cylinder?", img->get_byte());
+	int s = img->get_byte() & 0xff;
+	dec->print("%u end-sector?", s & 0x3f);
+	int c = img->get_byte() & 0xff;
+	dec->print("%u end-cylinder?", ((s << 2) & 0x300) + c);
 	dec->print("%u rel-sectors?", img->get_udword());
 	dec->print("%u num-sectors?", img->get_udword());
 	dec->print(NULL, img->get_string(48).c_str());
@@ -82,26 +85,33 @@
 
 	dec->rawprint("*\n");
 
-	img->seek(0x400);
+	img->seek(dir_start * 0x200);
 
-	dec->print("???", img->get_byte());
-	dec->print("???", img->get_string(11).c_str());
-	dec->print("First subfile offset: 0x%06lx", 
-		subfile_offset= img->get_udword());
-	dec->print("???", img->get_byte());
-	dec->print("", img->get_string(15).c_str());
+	byte= img->get_byte();
+	if ( ! byte) {
+		img->seek(0x1000);
+	} else {
+		dec->print("???", img->get_byte());
+		dec->print("???", img->get_string(11).c_str());
+		dec->print("First subfile offset: 0x%06lx", 
+			subfile_offset= img->get_udword());
+		dec->print("???", img->get_byte());
+		dec->print("", img->get_string(15).c_str());
 
-	dec->print("Sequence block start", img->get_uword());
-	dec->rawprint("*\n");
-	dec->print("Sequence block end (block %u)",
-		img->last_seq_block(0x600));
-	if ( img->tell() != 0x600 ) {
-		dec->print("Sequence block padding", img->get_uword());
+		dec->print("Sequence block start", img->get_uword());
 		dec->rawprint("*\n");
+
+		off_t end = (dir_start+1) * 0x200;	
+		dec->print("Sequence block end (block %u)",
+			img->last_seq_block(end));
+		if ( img->tell() != end ) {
+			dec->print("Sequence block padding", img->get_uword());
+			dec->rawprint("*\n");
+		}
+
+		img->seek(end);
 	}
 
-	img->seek(0x600);
-
 	dec->banner("Begin FAT");
 	while ( img->tell() < subfile_offset ) {
 		img_fat_block_t fblock;
@@ -146,6 +156,9 @@
 			img->seek(next_block);
 		}
 		fblock.offset= seq*img->block_size();
+
+		if ( ! fblock.offset ) valid= 0;
+
 		if ( ! part && valid ) {
 			class ImgFile *ifile;
 			class ImgSubfile *subfile;
@@ -154,6 +167,9 @@
 				fblock.offset);
 			img->fat.insert(make_pair(fblock.fullname, fblock));
 
+			if ( fblock.offset && fblock.offset < subfile_offset )
+				subfile_offset= fblock.offset;
+
 			ifile= img->file_find(fblock.filename);
 			if ( ifile == NULL ) {
 				ifile= new ImgFile(img, fblock.filename);
@@ -161,8 +177,8 @@
 					ifile));
 			}
 
-			ifile->subfile_add(fblock.extension, fblock.offset,
-				fblock.size);
+			(void) ifile->subfile_add(fblock.extension,
+				fblock.offset, fblock.size);
 		}
 		dec->rawprint("\n");
 	}
Index: decode_tre.cc
===================================================================
--- decode_tre.cc	(revision 2)
+++ decode_tre.cc	(working copy)
@@ -23,7 +23,7 @@
 {
 	udword_t length, offset;
 	uword_t rsize;
-	off_t soffset, eoffset;
+	off_t soffset, eoffset, hoffset;
 	class ImgLBL *lbl;
 
 	tre= tre_in;
@@ -32,9 +32,10 @@
 	ifile= tre->ifile;
 
 	soffset= tre->offset();
+	hoffset= tre->h_offset();
 //	lbl= (class ImgLBL *) ifile->subfile_find("LBL");
 
-	img->seek(soffset);
+	img->seek(hoffset);
 
 	dec->set_outfile("TRE", "header");
 	dec->banner("TRE: Header");
@@ -321,7 +322,9 @@
 				subdiv.next_level_idx= img->get_uword();
 				dec->print("Next level at subdiv %u",
 					subdiv.next_level_idx);
-				if ( next_level_at == scount )
+				if ( next_level_at == scount ||
+					next_level_at > subdiv.next_level_idx )
+
 					next_level_at= subdiv.next_level_idx;
 			} else {
 				subdiv.next_level_idx= 0;
@@ -357,19 +360,22 @@
 		dec->comment("%u subdivisions", tre->nsubdivisions);
 		dec->comment(NULL);
 
-		for (i= tre->nlevels-1; i>= 0; --i) {
+		int level_count = tre->nlevels-1;
+		for (i= 24; i >= 0 ; i--) {
 			map_level_t level;
 
-			recsz= ( i ) ? 16 : 14;
-			ifile->level_get(i, &level);
+			recsz= ( level_count ) ? 16 : 14;
+			if (ifile->level_get(i, &level) < 0)
+				continue;
 
+			level_count--; 
 			nsubdivisions= level.nsubdiv;
 
 			dec->comment("Map Level %u", i);
 			dec->comment(NULL);
 
 			for (n= 0; n< nsubdivisions; ++n) {
-				dec->comment("Subdivision %u", scount);
+				dec->comment("Subdivision %u/%u", scount, nsubdivisions);
 
 				if ( scount > 1 )
 					dec->comment("Rgn start 0x%06x",
@@ -441,8 +447,9 @@
 	if ( tre->locked ) {
 		dec->print("width %u (unshifted) units", width);
 	} else {
+		uword_t unshift_width = width;
 		width<<= shiftby;
-		dec->print("width  %10.5f", img->degrees(width));
+		dec->print("width  %10.5f (%u)", img->degrees(width), unshift_width);
 	}
 	if ( subdiv->last ) dec->comment("last subdiv in chain");
 
@@ -450,8 +457,9 @@
 	if ( tre->locked ) {
 		dec->print("height %u (unshifted) units", height);
 	} else {
+		uword_t unshift_height = height;
 		height<<= shiftby;
-		dec->print("height %10.5f", img->degrees(height));
+		dec->print("height %10.5f (%u)", img->degrees(height), unshift_height);
 	}
 
 	if ( ! tre->locked ) {
@@ -467,6 +475,8 @@
 	int nrecs= tre->polyline_info.length/tre->polyline_info.rsize;
 	int n;
 
+	if ( ! nrecs ) return;
+
 	img->seek(tre->polyline_info.offset);
 	dec->set_outfile("TRE", "polylines");
 	dec->banner("TRE: Polyline information");
@@ -481,7 +491,7 @@
 		dec->print("Type %u, %s", type,
 			img->elem_polyline_name(type).c_str());
 		dec->print("max level %u?", img->get_byte());
-		dec->print("???", img->get_byte());
+		//dec->print("???", img->get_byte());
 	}
 }
 
@@ -490,6 +500,8 @@
 	int nrecs= tre->polygon_info.length/tre->polygon_info.rsize;
 	int n;
 
+	if ( ! nrecs ) return;
+
 	img->seek(tre->polygon_info.offset);
 	dec->set_outfile("TRE", "polygons");
 	dec->banner("TRE: Polygon information");
@@ -504,7 +516,7 @@
 		dec->print("Type %u, %s", type,
 			img->elem_polygon_name(type).c_str());
 		dec->print("max level %u?", img->get_byte());
-		dec->print("???", img->get_byte());
+		//dec->print("???", img->get_byte());
 	}
 }
 
@@ -513,6 +525,8 @@
 	int nrecs= tre->point_info.length/tre->point_info.rsize;
 	int n;
 
+	if ( ! nrecs ) return;
+
 	img->seek(tre->point_info.offset);
 	dec->set_outfile("TRE", "points");
 	dec->banner("TRE: Point information");
@@ -536,6 +550,8 @@
 	int nrecs= tre->copyright_info.length/tre->copyright_info.rsize;
 	int n;
 
+	if ( ! nrecs ) return;
+
 	img->seek(tre->copyright_info.offset);
 	dec->set_outfile("TRE", "copyright");
 	dec->banner("TRE: Copyrights");
@@ -564,3 +580,4 @@
 
 	dec->print("???", img->get_string(tre->unknown2_info.length).c_str());
 }
+
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 2)
+++ Makefile.in	(working copy)
@@ -2,8 +2,8 @@
 CXX=@CXX@
 CFLAGS=-g
 OBJS=main.o garminimg.o imgfile.o subfile.o tre.o lbl.o rgn.o net.o nod.o \
-	decoder.o decode_header.o decode_tre.o decode_lbl.o decode_rgn.o \
-	decode_net.o decode_nod.o
+	gmp.o decoder.o decode_header.o decode_tre.o decode_lbl.o \
+	decode_rgn.o decode_net.o decode_nod.o decode_gmp.o
 
 .SUFFIXES: .cc .o
 
Index: decoder.h
===================================================================
--- decoder.h	(revision 2)
+++ decoder.h	(working copy)
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 #include <stdio.h>
 #include <string>
+#include <stdarg.h>
 
 using namespace std;
 
Index: lbl.cc
===================================================================
--- lbl.cc	(revision 2)
+++ lbl.cc	(working copy)
@@ -1,5 +1,7 @@
 #include <sys/types.h>
 #include <string>
+#include <stdio.h>
+#include <memory.h>
 #include "imgtypes.h"
 #include "garminimg.h"
 #include "lbl.h"
@@ -11,7 +13,9 @@
 	encoding6_spec= "`abcdefghijklmnopqrstuvwxyz~~~~~0123456789~~~~~~";
 
 	ifile= ifilein;
-	imgfile_offset= offset;
+	header_offset= imgfile_offset= offset;
+
+	memset(&poi_mask, 0, sizeof(poi_mask));
 }
 
 ImgLBL::~ImgLBL ()
@@ -19,6 +23,20 @@
 }
 
 //-------------------------------------------------------------------
+// POI properties 
+//-------------------------------------------------------------------
+
+byte_t ImgLBL::global_poi_flags ()
+{
+	return poi_flags;
+}
+
+byte_t ImgLBL::global_poi_flags (byte_t flags_in)
+{
+	return poi_flags= flags_in;
+}
+
+//-------------------------------------------------------------------
 // Label methods
 //-------------------------------------------------------------------
 
@@ -32,8 +50,13 @@
 	switch (encoding) {
 	case LBL_ENC_6BIT:
 		return label_parse_6bit (offset);
-		break;
+	case LBL_ENC_8BIT:
+		return label_parse_8bit(offset);
+	case LBL_ENC_10BIT:
+		return label_parse_8bit(offset);
 	}
+
+	return "(can't decode)";
 }
 
 //-------------------------------------------------------------------
@@ -132,6 +155,45 @@
 }
 
 //-------------------------------------------------------------------
+// 8-bit decoding methods
+//-------------------------------------------------------------------
+
+string ImgLBL::label_parse_8bit (off_t offset)
+{
+	bool lcont= false;
+	//int chset= SET_8_NORMAL;
+	unsigned char enc[3], data[4];
+	string label;
+
+	if ( offset > label_info.offset+label_info.length || 
+		offset < label_info.offset ) {
+
+		return "(invalid offset)";
+	}
+
+	if ( img->tell() != offset ) img->seek(offset);
+
+	for (;;) {
+		img->get_cstring(enc, 1);
+
+		if ( lcont ) img->sbuffer_append();
+		else img->sbuffer_set();
+
+		data[0]= enc[0];
+
+		if ( data[0] == 0 ) {
+			//img->sbuffer_rtrim(2);
+			//img->seek(-2, SEEK_CUR);
+			return label;
+		}
+
+		label.append((char*)data, 1);
+
+		lcont= true;
+	}
+}
+
+//-------------------------------------------------------------------
 // Locality methods
 //-------------------------------------------------------------------
 
Index: README
===================================================================
--- README	(revision 2)
+++ README	(working copy)
@@ -6,7 +6,17 @@
 About imgdecode
 ---------------
 
-This program is designed to aid in the decoding of Garmin IMG files.
+NOTE: This code has been designed to work on topo and road maps
+only.  No effort has been made towards parsing marine or aviation
+maps. 
+
+"NT" style maps do not decode past a few headers as this map file
+format is only partially understood.  City Navigator v8 files do
+not decode correctly, either, due to unknown changes in their data
+structures.  It is known to work correctly on City Navigator v7 and
+older map files, US TOPO files, and Metroguide maps (v7 and older).
+
+The program is designed to aid in the decoding of Garmin IMG files.
 It hexdumps the IMG file side-by-side with plain-text descriptions
 of what the particular bytes in the file represent.  Unknown
 data blocks are either unlabeled or labeled with a ???.  Files are
@@ -66,14 +76,5 @@
 What isn't working
 ------------------
 
-NOD section "unknown2" is not correct.  There are offsets into this
-file from NET and I know where they are, but don't understand the
-algorithm for getting to them, so parsing NOD is pretty much impossible
-for now.
+Much of NOD is still unknown.
 
-Much of NET is still unknown.
-
-This still blows up on some IMG files and I'm not sure why.  If you
-are running against a CityNav or City Select NA product, I can look into
-it if you send me the file name (and product version).
-
Index: garminimg.cc
===================================================================
--- garminimg.cc	(revision 2)
+++ garminimg.cc	(working copy)
@@ -12,6 +12,7 @@
 #include <algorithm>
 #include "garminimg.h"
 #include "elemdata.h"
+#include <memory.h>
 
 using namespace std;
 
Index: decode_lbl.cc
===================================================================
--- decode_lbl.cc	(revision 2)
+++ decode_lbl.cc	(working copy)
@@ -3,13 +3,14 @@
 #include "decoder.h"
 #include "decode_img.h"
 
-void decode_lbl_labels (off_t end);
+void decode_lbl_labels ();
 void decode_lbl_country_def ();
 void decode_lbl_region_def ();
 void decode_lbl_city_def ();
 void decode_lbl_zip ();
 void decode_lbl_poiprop ();
 void decode_lbl_hwy_def ();
+void decode_lbl_exit_svc ();
 
 static class GarminImg *img;
 static class ImgFile *ifile;
@@ -21,8 +22,7 @@
 {
 	udword_t length;
 	uword_t rsize;
-	off_t offset;
-	off_t soffset;
+	off_t offset, soffset, hoffset;
 
 	lbl= lbl_in;
 	dec= dec_in;
@@ -30,13 +30,16 @@
 	ifile= lbl->ifile;
 
 	soffset= lbl->offset();
+	hoffset= lbl->h_offset();
 
-	img->seek(soffset);
+	img->seek(hoffset);
 	dec->set_outfile("LBL", "header");
 	dec->banner("LBL: Header");
 
 	decode_common_header(dec, lbl);
 
+	// LBL section 1
+
 	offset= img->get_udword()+soffset;
 	dec->print("Data offset 0x%06lx", offset);
 	dec->print("Data length %lu bytes", length= img->get_udword());
@@ -48,6 +51,8 @@
 	lbl->label_info.length= length;
 	lbl->label_info.offset= offset;
 
+	// LBL section 2
+
 	offset= img->get_udword()+soffset;
 	dec->print("Country definitions at 0x%06lx", offset);
 	dec->print("Country definition length %lu bytes", 
@@ -60,6 +65,8 @@
 
 	dec->print("", img->get_udword());
 
+	// LBL section 3
+
 	offset= img->get_udword()+soffset;
 	dec->print("Region definitions at 0x%06lx", offset);
 	dec->print("Region definition length %lu bytes", 
@@ -72,6 +79,8 @@
 
 	dec->print("", img->get_udword());
 
+	// LBL section 4
+
 	offset= img->get_udword()+soffset;
 	dec->print("City definitions at 0x%06lx", offset);
 	dec->print("City definition length %lu bytes",
@@ -84,56 +93,91 @@
 
 	dec->print("", img->get_udword());
 
+	// LBL section 5
+
 	offset= img->get_udword()+soffset;
 	dec->print("Unknown1 section at 0x%06lx", offset);
 	dec->print("Unknown1 section length %lu bytes",
 		length= img->get_udword());
 	dec->print("Unknown1 record size %u bytes", rsize= img->get_uword());
 	if (length) ifile->offset_add(offset, LBL_UNKN1);
-	lbl->unkn1_info.length= length;
-	lbl->unkn1_info.offset= offset;
-	lbl->unkn1_info.offset= rsize;
 
 	dec->print("", img->get_udword());
 
+	// LBL section 6
+
 	offset= img->get_udword()+soffset;
 	dec->print("POI properties at 0x%06lx", offset);
 	dec->print("POI properties length %lu bytes",
 		length= img->get_udword());
-	dec->print("Zip bit is phone if no phone bit: %c", (lbl->zipisphone= img->get_byte()) ?
-		'Y' : 'N');
-	lbl->poiflags= img->get_byte();
-	if ( lbl->poiflags ) {
+	dec->print("???", img->get_byte());
+	lbl->global_poi_flags(img->get_byte());
+	if ( lbl->global_poi_flags() ) {
 		string s_flags;
 		bool has_street, has_street_num, has_city,
-			has_zip, has_phone, has_extra, has_u1, has_u2;
+			has_zip, has_phone, has_hwyexit, has_tides,
+			has_unkn;
+		char mask= 0x1;
 
-		has_street_num=	lbl->poiflags & 0x1;
-		has_street=	lbl->poiflags & 0x2;
-		has_city=	lbl->poiflags & 0x4;
-		has_zip=	lbl->poiflags & 0x8;
-		has_phone=	lbl->poiflags & 0x10;
-		has_extra=	lbl->poiflags & 0x20;
-		has_u1=		lbl->poiflags & 0x40;
-		has_u2=		lbl->poiflags & 0x80;
+		has_street_num=	lbl->global_poi_flags() & 0x1;
+		has_street=	lbl->global_poi_flags() & 0x2;
+		has_city=	lbl->global_poi_flags() & 0x4;
+		has_zip=	lbl->global_poi_flags() & 0x8;
+		has_phone=	lbl->global_poi_flags() & 0x10;
+		has_hwyexit=	lbl->global_poi_flags() & 0x20;
+		has_tides=	lbl->global_poi_flags() & 0x40;
+		has_unkn=	lbl->global_poi_flags() & 0x80;
 
-		if ( lbl->zipisphone && has_zip && ! has_phone ) {
-			has_zip= 0;
-			has_phone= 1;
+		if ( has_street_num ) {
+			s_flags+= "street_num,";
+			lbl->poi_mask.street_num= mask;
+			mask*= 2;
 		}
 
-		if ( has_street_num ) s_flags+= "street_num,";
-		if ( has_street ) s_flags+= "street,";
-		if ( has_city ) s_flags+= "city,";
-		if ( has_zip ) s_flags+= "zip,";
-		if ( has_phone ) s_flags+= "phone,";
-		if ( has_extra ) s_flags+= "xtra,";
-		if ( has_u1 ) s_flags+= "unkn1,";
-		if ( has_u2 ) s_flags+= "unkn2,";
+		if ( has_street ) {
+			s_flags+= "street,";
+			lbl->poi_mask.street= mask;
+			mask*= 2;
+		}
 
+		if ( has_city ) {
+			s_flags+= "city,";
+			lbl->poi_mask.city= mask;
+			mask*= 2;
+		}
+
+		if ( has_zip ) {
+			s_flags+= "zip,";
+			lbl->poi_mask.zip= mask;
+			mask*= 2;
+		}
+
+		if ( has_phone ) {
+			s_flags+= "phone,";
+			lbl->poi_mask.phone= mask;
+			mask*= 2;
+		}
+
+		if ( has_hwyexit ) {
+			s_flags+= "exit,";
+			lbl->poi_mask.hwyexit= mask;
+			mask*= 2;
+		}
+
+		if ( has_tides ) {
+			s_flags+= "tides,";
+			lbl->poi_mask.tides= mask;
+			mask*= 2;
+		}
+
+		if ( has_unkn ) {
+			s_flags+= "unkn,";
+		}
+
 		s_flags.erase(s_flags.size()-1);
-		dec->print("%s POIs: %s", img->base(lbl->poiflags,
-			2, 8).c_str(), s_flags.c_str());
+		dec->print("%s POIs: %s",
+			img->base(lbl->global_poi_flags(), 2, 8).c_str(),
+			s_flags.c_str());
 	} else dec->print("No global POI properties");
 	if (length) ifile->offset_add(offset, LBL_POI_PROP);
 	lbl->poiprop_info.length= length;
@@ -142,6 +186,8 @@
 	dec->print("", img->get_uword());
 	dec->print("", img->get_byte());
 
+	// LBL section 7
+
 	offset= img->get_udword()+soffset;
 	dec->print("Unknown2 section at 0x%06lx", offset);
 	dec->print("Unknown2 section length %lu bytes",
@@ -151,6 +197,8 @@
 
 	dec->print("", img->get_udword());
 
+	// LBL section 8
+
 	offset= img->get_udword()+soffset;
 	dec->print("Zip definitions at 0x%06lx", offset);
 	dec->print("Zip definition length %lu bytes",
@@ -163,6 +211,8 @@
 
 	dec->print("", img->get_udword());
 
+	// LBL section 9
+
 	offset= img->get_udword()+soffset;
 	dec->print("Highway definitions at 0x%06lx", offset);
 	dec->print("Highway definition length %lu bytes",
@@ -175,36 +225,52 @@
 
 	dec->print("", img->get_udword());
 
+	// LBL section 10
+
 	offset= img->get_udword()+soffset;
-	dec->print("Exit definitions at 0x%06lx", offset);
-	dec->print("Exit definition length %lu bytes",
+	dec->print("Exit services at 0x%06lx", offset);
+	dec->print("Exit services length %lu bytes",
 		length= img->get_udword());
-	dec->print("Exit record size %u bytes", rsize= img->get_uword());
-	if (length) ifile->offset_add(offset, LBL_EXIT_DEF);
+	dec->print("Exit services record size %u bytes",
+		rsize= img->get_uword());
+	if (length) ifile->offset_add(offset, LBL_EXIT_SVC);
+	lbl->exitsvc_info.length= length;
+	lbl->exitsvc_info.offset= offset;
+	lbl->exitsvc_info.rsize= rsize;
 
 	dec->print("", img->get_udword());
 
+	// LBL section 11
+
 	offset= img->get_udword()+soffset;
-	dec->print("Highway data definitions at 0x%06lx", offset);
-	dec->print("Highway data definition length %lu bytes",
+	dec->print("Exit list at 0x%06lx", offset);
+	dec->print("Exit list length %lu bytes",
 		length= img->get_udword());
-	dec->print("Highway data record size %u bytes",
+	dec->print("Exit list record size %u bytes",
 		rsize= img->get_uword());
-	if (length) ifile->offset_add(offset, LBL_HWY_DATA);
+	if (length) ifile->offset_add(offset, LBL_EXIT_LST);
+	lbl->exitlist_info.length= length;
+	lbl->exitlist_info.offset= offset;
+	lbl->exitlist_info.rsize= rsize;
 
-	dec->print("", img->get_udword());
+	// LBL section 12?
 
-	dec->print("Code page?", img->get_uword());
-
 	dec->print("???", img->get_udword());
+	dec->print("???", img->get_uword());
+	dec->print("???", img->get_udword());
 
+	// LBL section 13
+
 	offset= img->get_udword()+soffset;
 	dec->print("Sort descriptor at 0x%06lx", offset);
 	dec->print("Sort descriptor length %lu bytes", 
 		length= img->get_udword());
 	if (length) ifile->offset_add(offset, LBL_SORT_DESC);
-	lbl->sortlen= length;
+	lbl->sort_info.length= length;
+	lbl->sort_info.offset= offset;
 
+	// LBL section 14
+
 	offset= img->get_udword()+soffset;
 	dec->print("Unknown3 section at 0x%06lx", offset);
 	dec->print("Unknown3 section length %lu bytes",
@@ -214,6 +280,8 @@
 
 	dec->print("", img->get_uword());
 
+	// LBL section 15
+
 	offset= img->get_udword()+soffset;
 	dec->print("Unknown4 section at 0x%06lx", offset);
 	dec->print("Unknown4 section length %lu bytes",
@@ -238,104 +306,56 @@
 	off_t noffset;
 	unsigned int type;
 
-	// Parse the data segments in offset order.
+	// Parse the data segments in a sensible order.  Labels
+	// come first, followed by indexed sections (cities, zips,
+	// etc.)  POI properties go last, since they depend on all
+	// or many of the other fields.
 
-	img->seek(soffset);
-	type= ifile->offset_find(img->tell());
-	if ( type == 0 ) {
-		noffset= ifile->offset_next(img->tell());
-		if ( noffset > eoffset ) noffset= eoffset;
-		dec->print("???", img->get_string(noffset -
-			img->tell()).c_str());
-	}
+	decode_lbl_labels();
 
-	while ( img->tell() < eoffset ) {
-		type= ifile->offset_find(img->tell());
+	// Countries, regions, cities, zips in that order.
 
-		noffset= ifile->offset_next(img->tell());
+	decode_lbl_country_def();
 
-		switch (type) {
-		case LBL_LABELS:
-			dec->set_outfile("LBL", "labels");
-			dec->banner("LBL: Labels");
-			decode_lbl_labels(img->tell()+lbl->label_info.length);
-			break;
-		case LBL_COUNTRY_DEF:
-			dec->set_outfile("LBL", "countries");
-			dec->banner("LBL: Country definitions");
-			decode_lbl_country_def();
-			break;
-		case LBL_REGION_DEF:
-			dec->set_outfile("LBL", "regions");
-			dec->banner("LBL: Region definitions");
-			decode_lbl_region_def();
-			break;
-		case LBL_CITY_DEF:
-			dec->set_outfile("LBL", "cities");
-			dec->banner("LBL: City definitions");
-			decode_lbl_city_def();
-			break;
-		case LBL_UNKN1:
-			dec->set_outfile("LBL", "unknown1");
-			dec->banner("LBL: Unknown 1");
-			break;
-		case LBL_POI_PROP:
-			dec->set_outfile("LBL", "poi_properties");
-			dec->banner("LBL: POI Properties");
-			decode_lbl_poiprop();
-			break;
-		case LBL_UNKN2:
-			dec->set_outfile("LBL", "unknown2");
-			dec->banner("LBL: Unknown 2");
-			break;
-		case LBL_ZIP_DEF:
-			dec->set_outfile("LBL", "zipcodes");
-			dec->banner("LBL: Zip/Postal codes");
-			decode_lbl_zip();
-			break;
-		case LBL_HWY_DEF:
-			dec->set_outfile("LBL", "highways");
-			dec->banner("LBL: Highways");
-			decode_lbl_hwy_def();
-			break;
-		case LBL_EXIT_DEF:
-			dec->set_outfile("LBL", "exits");
-			dec->banner("LBL: Exit services");
-			break;
-		case LBL_HWY_DATA:
-			dec->set_outfile("LBL", "hwydata");
-			dec->banner("LBL: Highway data");
-			break;
-		case LBL_SORT_DESC:
-			dec->set_outfile("LBL", "sort");
-			dec->banner("LBL: Sort descriptor");
-			dec->print("%s", img->get_string(lbl->sortlen).c_str());
-			break;
-		case LBL_UNKN3:
-			dec->set_outfile("LBL", "unknown3");
-			dec->banner("LBL: Unknown 3");
-			break;
-		case LBL_UNKN4:
-			dec->set_outfile("LBL", "unknown4");
-			dec->banner("LBL: Unknown 4");
-			break;
-		}
+	decode_lbl_region_def();
 
-		if ( noffset > eoffset || noffset == 0 ) noffset= eoffset;
-		if ( img->tell() < noffset ) {
-			dec->print("???", img->get_string(noffset
-				- img->tell()).c_str());
+	decode_lbl_city_def();
 
-		}
-	}
+	decode_lbl_zip();
+
+	decode_lbl_hwy_def();
+
+	decode_lbl_exit_svc();
+
+	// POI properties depend on the above
+
+	decode_lbl_poiprop();
+
+	// The sort descriptor.  Just do it here.
+
+	img->seek(lbl->sort_info.offset);
+	dec->set_outfile("LBL", "sort");
+	dec->banner("LBL: Sort descriptor");
+	dec->print("%s", img->get_string(lbl->sort_info.length).c_str());
 }
 
-void decode_lbl_labels (off_t end)
+void decode_lbl_labels ()
 {
-	off_t offset;
+	off_t offset, end;
 	string label;
 
-	offset= img->tell();
+	offset= lbl->label_info.offset;
+	end= offset+lbl->label_info.length;
+	img->seek(offset);
+
+	dec->set_outfile("LBL", "labels");
+	dec->banner("LBL: Labels");
+
+	//if ( lbl->encoding != LBL_ENC_6BIT ) {
+	//	dec->rawprint("Encoding unknown\n");
+	//	return;
+	//}
+
 	while ( offset < end ) {
 		int n;
 		off_t lbloffset;
@@ -371,6 +391,11 @@
 	int nrecs= lbl->country_info.length / lbl->country_info.rsize;
 	int n;
 
+	img->seek(lbl->country_info.offset);
+
+	dec->set_outfile("LBL", "countries");
+	dec->banner("LBL: Country definitions");
+
 	for (n= 1; n<= nrecs; ++n) {
 		off_t loffset;
 		string country;
@@ -382,7 +407,6 @@
 		dec->comment("%s", country.c_str());
 //		img->country(n, &label);
 
-		++n;
 	}
 	dec->comment(NULL);
 }
@@ -393,6 +417,11 @@
 	int nrecs= lbl->region_info.length / lbl->region_info.rsize;
 	int n;
 
+	img->seek(lbl->region_info.offset);
+
+	dec->set_outfile("LBL", "regions");
+	dec->banner("LBL: Region definitions");
+
 	for (n= 1; n<= nrecs; ++n) {
 		uword_t cidx;
 		udword_t loffset;
@@ -416,6 +445,11 @@
 	int nrecs= lbl->city_info.length / lbl->city_info.rsize;
 	int n;
 
+	img->seek(lbl->city_info.offset);
+
+	dec->set_outfile("LBL", "cities");
+	dec->banner("LBL: City definitions");
+
 	for (n= 1; n<= nrecs; ++n) {
 		udword_t cdata;
 		uword_t cinfo, ridx;
@@ -431,9 +465,11 @@
 		ridx= (cinfo & 0x3FFF);
 		pref= (cinfo & 0x8000);
 		
-		if ( pref ) dec->print("City %u is IdxPoint %u in subdiv %u",
-			n, cdata>>16, cdata&0xFFFF);
-		else {
+		if ( pref ) {
+			dec->print("City %u is IdxPoint %u in subdiv %u",
+				n, cdata&0xff, (cdata>>8)&0xFFFF);
+			ifile->city_inc();
+		} else {
 			udword_t loffset= (udword_t) cdata;
 
 			dec->print("City %u label at 0x%06x", n, loffset);
@@ -454,6 +490,11 @@
 	int nrecs= lbl->zip_info.length / lbl->zip_info.rsize;
 	int n;
 
+	img->seek(lbl->zip_info.offset);
+
+	dec->set_outfile("LBL", "zipcodes");
+	dec->banner("LBL: Zip/Postal codes");
+
 	for (n= 1; n<= nrecs; ++n) {
 		udword_t offset= img->get_uint24();
 		string label;
@@ -466,15 +507,21 @@
 
 void decode_lbl_poiprop ()
 {
-	off_t soffset= img->tell();
-	off_t eos= img->tell() + lbl->poiprop_info.length;
-	udword_t poi_data, lbloffset;
+	off_t soffset= lbl->poiprop_info.offset;
+	off_t eos= soffset + lbl->poiprop_info.length;
+	udword_t poi_data, lbloffset, lblinfo;
 	bool override;
 
+	img->seek(soffset);
+
+	dec->set_outfile("LBL", "poi_properties");
+	dec->banner("LBL: POI Properties");
+
 	while ( img->tell() < eos ) {
 		byte_t flags;
 		bool has_street, has_street_num, has_city,
-			has_zip, has_phone, has_extra, has_u1, has_u2;
+			has_zip, has_phone, has_hwyexit, has_tides,
+			has_unkn;
 
 		poi_data= img->get_uint24();
 		lbloffset= (poi_data & 0x3FFFFF);
@@ -487,40 +534,40 @@
 			dec->print("%s override flags",
 				img->base(flags, 2, 8).c_str());
 
-		} else flags= lbl->poiflags;
+			has_street_num= flags & lbl->poi_mask.street_num;
+			has_street=	flags & lbl->poi_mask.street;
+			has_city=	flags & lbl->poi_mask.city;
+			has_zip=	flags & lbl->poi_mask.zip;
+			has_phone=	flags & lbl->poi_mask.phone;
+			has_hwyexit=	flags & lbl->poi_mask.hwyexit;
+			has_tides=	flags & lbl->poi_mask.tides;
 
-		has_street_num=	flags & 0x1;
-		has_street=	flags & 0x2;
-		has_city=	flags & 0x4;
-		has_zip=	flags & 0x8;
-		has_phone=	flags & 0x10;
-		has_extra=	flags & 0x20;
-		has_u1=		flags & 0x40;
-		has_u2=		flags & 0x80;
+		} else {
+			flags= lbl->global_poi_flags();
 
-/*
-		if ( lbl->zipisphone && has_zip && ! has_phone ) {
-			has_zip= 0;
-			has_phone= 1;
+			has_street_num=	flags & 0x1;
+			has_street=	flags & 0x2;
+			has_city=	flags & 0x4;
+			has_zip=	flags & 0x8;
+			has_phone=	flags & 0x10;
+			has_hwyexit=	flags & 0x20;
+			has_tides=	flags & 0x40;
+			has_unkn=	flags & 0x80;
 		}
-*/
 
-		if ( override ) {
-			string s_flags;
+		string s_flags;
 
-			if ( has_street_num ) s_flags+= "street_num,";
-			if ( has_street ) s_flags+= "street,";
-			if ( has_city ) s_flags+= "city,";
-			if ( has_zip ) s_flags+= "zip,";
-			if ( has_phone ) s_flags+= "phone,";
-			if ( has_extra ) s_flags+= "xtra,";
-			if ( has_u1 ) s_flags+= "unkn1,";
-			if ( has_u2 ) s_flags+= "unkn2,";
+		if ( has_street_num ) s_flags+= "street_num,";
+		if ( has_street ) s_flags+= "street,";
+		if ( has_city ) s_flags+= "city,";
+		if ( has_zip ) s_flags+= "zip,";
+		if ( has_phone ) s_flags+= "phone,";
+		if ( has_hwyexit ) s_flags+= "hwyexit,";
+		if ( has_tides ) s_flags+= "tides,";
 
-			if ( s_flags.size() )
-				s_flags.erase(s_flags.size()-1);
-			dec->print("Has %s", s_flags.c_str());
-		}
+		if ( s_flags.size() )
+			s_flags.erase(s_flags.size()-1);
+		dec->comment("Has %s", s_flags.c_str());
 
 		if ( has_street_num ) {
 			string snum= img->get_base11str('-');
@@ -571,13 +618,45 @@
 
 		if ( has_phone ) {
 			string phn= img->get_base11str('-');
-			if ( phn.size() )
-				dec->print("Ph num %s", phn.c_str());
+			if ( phn.empty() ) {
+				udword_t mpoffset;
+				string::size_type idx;
+
+				dec->print("phone num is label");
+				mpoffset= img->get_byte()<<16;
+				img->sbuffer_set();
+				mpoffset|= img->get_uword();
+				img->sbuffer_append();
+				img->sbuffer_recall();
+				dec->print("label at 0x%06x", mpoffset);
+				phn= ifile->label_get(mpoffset);
+				dec->comment("Phone %s", phn.c_str());
+			} else
+				dec->print("Phone num %s", phn.c_str());
 		}
 
-		if ( has_extra ) {
-			img->get_byte();
-			dec->print("xtra");
+		if ( has_hwyexit ) {
+			bool has_eidx, has_onpark;
+			string ehas;
+
+			lblinfo= img->get_uint24();
+			lbloffset= lblinfo & 0x3FFFF;
+			has_onpark= (lblinfo & 0x400000);
+			has_eidx= (lblinfo & 0x800000);
+
+			if ( has_onpark ) ehas+= " overnight-parking";
+			if ( has_eidx ) ehas+= " indexed";
+
+			dec->print("Exit label at 0x%06x", lbloffset);
+			dec->comment("%s", ifile->label_get(lbloffset).c_str());
+			if ( ehas.size() ) dec->comment("%s", ehas.c_str());
+			dec->print("Highway idx %u", img->get_byte());
+
+			if ( has_eidx ) 
+				dec->print("Exit svc idx %u",
+					( lbl->nexitsvcs > 255 ) ?
+					img->get_uword() :
+					img->get_byte() );
 		}
 
 		while ( (img->tell()-soffset) % lbl->omult &&
@@ -595,8 +674,151 @@
 	int nrecs= lbl->hwy_info.length / lbl->hwy_info.rsize;
 	int n;
 
+	img->seek(lbl->hwy_info.offset);
+
+	dec->set_outfile("LBL", "highways");
+	dec->banner("LBL: Highways");
+
+	lbl->nhwys= nrecs;
+
 	for (n= 1; n<= nrecs; ++n) {
-		dec->print("???", img->get_string(lbl->region_info.rsize).c_str());
+		udword_t loffset= img->get_uint24();
+		dec->print("Label at offset 0x%06x", loffset);
+		dec->comment("%s", ifile->label_get(loffset).c_str());
+		dec->print("Exit list at 0x%06x", img->get_uint24());
 	}
 }
 
+void decode_lbl_exit_svc ()
+{
+	int nrecs= lbl->exitsvc_info.length / lbl->exitsvc_info.rsize;
+	int n, c;
+
+	lbl->nexitsvcs= nrecs;
+
+	img->seek(lbl->exitsvc_info.offset);
+
+	dec->set_outfile("LBL", "exit_services");
+	dec->banner("LBL: Exit Services");
+
+	c= 1;
+	dec->comment("Exit 1");
+	dec->comment(NULL);
+	for (n= 1; n<= nrecs; ++n) {
+		udword_t loffset, lblinfo;
+		byte_t fac, dir, type, data;
+		string sdir, stype, sfac;
+
+		lblinfo= img->get_uint24();
+		loffset= lblinfo&0x3FFFFF;
+		if ( lblinfo & 0x800000 ) {
+			dec->comment("Exit %u", ++c);
+			dec->comment(NULL);
+		}
+
+		dec->print("Label at offset 0x%06x", loffset);
+		dec->comment("%s", ifile->label_get(loffset).c_str());
+
+		data= img->get_byte();
+		dir= (data&0xF0)>>4;
+		type= data&0xF;
+
+		switch (type) {
+		case 0x0:
+			stype= "diesel w/restaurant";
+			break;
+		case 0x1:
+			stype= "diesel w/clearance";
+			break;
+		case 0x2:
+			stype= "fuel";
+			break;
+		case 0x3:
+			stype= "restaurant";
+			break;
+		case 0x4:
+			stype= "lodging";
+			break;
+		case 0x5:
+			stype= "car service";
+			break;
+		case 0x6:
+			stype= "diesel service";
+			break;
+		case 0x7:
+			stype= "comm car wash";
+			break;
+		case 0x8:
+			stype= "campground";
+			break;
+		case 0x9:
+			stype= "medical";
+			break;
+		case 0xa:
+			stype= "ATM";
+			break;
+		case 0xb:
+			stype= "recreation";
+			break;
+		case 0xc:
+			stype= "attractions";
+			break;
+		case 0xd:
+			stype= "fast food";
+			break;
+		case 0xe:
+		case 0xf:
+			stype= "none";
+		}
+
+		switch (dir) {
+		case 0x0:
+		case 0x1:
+			sdir= "north";
+			break;
+		case 0x2:
+		case 0x3:
+			sdir= "south";
+			break;
+		case 0x4:
+		case 0x5:
+			sdir= "east";
+			break;
+		case 0x6:
+		case 0x7:
+			sdir= "west";
+			break;
+		case 0x8:
+		case 0x9:
+			sdir= "inner";
+			break;
+		case 0xa:
+		case 0xb:
+			sdir= "outer";
+			break;
+		case 0xc:
+		case 0xd:
+			sdir= "both";
+			break;
+		case 0xe:
+		case 0xf:
+			sdir= "none";
+		}
+
+		dec->print("%s / %s", sdir.c_str(), stype.c_str());
+
+		fac= img->get_byte();
+		if ( fac & 0x01 ) sfac+= "truck/RV parking,";
+		if ( fac & 0x02 ) sfac+= "conven store,";
+		if ( fac & 0x04 ) sfac+= "diesel fuel,";
+		if ( fac & 0x08 ) sfac+= "car wash,";
+		if ( fac & 0x10 ) sfac+= "liq propane,";
+		if ( fac & 0x20 ) sfac+= "truck scale,";
+		if ( fac & 0x40 ) sfac+= "open 24h,";
+
+		if ( sfac.length() ) sfac.erase(sfac.size()-1);
+
+		dec->print("Facilities: %s", sfac.c_str());
+		dec->comment(NULL);
+	}
+}
Index: garminimg.h
===================================================================
--- garminimg.h	(revision 2)
+++ garminimg.h	(working copy)
@@ -14,6 +14,8 @@
 class ImgSubfile;
 class ImgTRE;
 class ImgLBL;
+class ImgRGN;
+class ImgGMP;
 
 struct img_fat_block_struct {
 	string filename;
@@ -166,6 +168,7 @@
 	zip_cache_t zips;
 	levels_t levels;
 	subdivisions_t subdivisions;
+	int indexed_cities;
 
 public:
 	class GarminImg *img;
@@ -176,7 +179,8 @@
 
 	// Subfile methods
 
-	void subfile_add (string type, off_t offset, udword_t size);
+	class ImgSubfile *subfile_add (string type, off_t offset,
+		udword_t size);
 	class ImgSubfile *subfile_find (string type);
 	off_t subfile_offset (string type);
 
@@ -203,6 +207,7 @@
 	vector<string> region_get_ar (uword_t idx);
 
 	void city_add (uword_t idx, string name, uword_t ridx);
+	void city_inc (void);
 	string city_get (uword_t idx);
 	vector<string> city_get_ar (uword_t idx);
 	uword_t ncities ();
@@ -231,14 +236,19 @@
 };
 
 class ImgSubfile {
+	friend class ImgGMP;
 	friend class ImgTRE;
 	friend class ImgLBL;
 	friend class ImgRGN;
 	friend class ImgNET;
 	friend class ImgNOD;
 
-	off_t imgfile_offset;
+	off_t imgfile_offset;	 // Offset of the subfile
 
+	off_t header_offset;	// Offset of the header in the subfile
+				// This is imgfile_offset for "old" style
+				// IMG files but differs for "NT" style
+
 public:
 	class ImgFile *ifile;
 	class GarminImg *img;
@@ -251,7 +261,10 @@
 
 	// Offset methods
 
+	void set_header_offset (off_t offset_new);
+	void set_size (udword_t size_new);
 	off_t offset ();
+	off_t h_offset ();
 };
 
 // Subfile data structures
@@ -269,6 +282,14 @@
 
 // Subfile class defintions
 
+class ImgGMP : public ImgSubfile {
+public:
+	int omult;
+
+	ImgGMP (class ImgFile *ifilein, off_t offset);
+	~ImgGMP ();
+};
+
 class ImgNOD : public ImgSubfile {
 public:
 	struct sec_info_struct unknown1_info, unknown2_info, unknown3_info;
@@ -280,8 +301,8 @@
 
 class ImgNET : public ImgSubfile {
 public:
-	struct sec_info_struct roads_info, unknown1_info, unknown2_info;
-	int omult;
+	struct sec_info_struct roads_info, unknown1_info, sorted_info;
+	int omult1, omult2;
 
 	ImgNET (class ImgFile *ifilein, off_t offset);
 	~ImgNET ();
@@ -317,25 +338,43 @@
 #define LBL_ENC_6BIT	6
 #define LBL_ENC_8BIT	9	// Yes, that's correct
 #define LBL_ENC_10BIT	10
+#define LBL_ENC_NT	11
 
 class ImgLBL : public ImgSubfile {
 	const char *encoding6, *encoding6_shift, *encoding6_spec;
+	byte_t poi_flags;
 
 	// Private 6 bit label methods
 
 	string char_6bit (byte_t byte, int *chset);
 	string label_parse_6bit (off_t offset);
+	string label_parse_8bit (off_t offset);
 
 public:
 	struct sec_info_struct country_info, region_info, city_info,
-		poiprop_info, zip_info, unkn1_info, label_info,
-		hwy_info;
-	int omult, poiflags, ncities, nzips, encoding, sortlen;
-	bool zipisphone;
+		poiprop_info, zip_info, label_info, hwy_info,
+		sort_info, exitlist_info, exitsvc_info;
 
+	int omult, ncities, nzips, encoding, nhwys, nexitsvcs;
+
+	struct poi_mask_struct {
+		char street_num;
+		char street;
+		char city;
+		char zip;
+		char phone;
+		char hwyexit;
+		char tides;
+	} poi_mask;
+
 	ImgLBL (class ImgFile *ifilein, off_t offset);
 	~ImgLBL ();
 
+	// POI properties functions
+
+	byte_t global_poi_flags ();
+	byte_t global_poi_flags (byte_t flags_in);
+
 	// Locality functions
 
 	void country_def_parse (off_t offset);
@@ -369,8 +408,8 @@
 #define	LBL_UNKN2       0x1007
 #define	LBL_ZIP_DEF     0x1008
 #define	LBL_HWY_DEF     0x1009
-#define	LBL_EXIT_DEF    0x100A
-#define	LBL_HWY_DATA    0x100B
+#define	LBL_EXIT_SVC    0x100A
+#define	LBL_EXIT_LST    0x100B
 #define	LBL_SORT_DESC   0x100C
 #define	LBL_UNKN3       0x100D
 #define	LBL_UNKN4       0x100E
@@ -378,7 +417,7 @@
 #define NET_ROAD_DEF	0x2001
 #define NET_ROAD_REC	0x2002
 #define NET_UNKN1	0x2003
-#define NET_UNKN2	0x2004
+#define NET_SORTED	0x2004
 
 #define NOD_UNKN1	0x3001
 #define NOD_UNKN2	0x3002
Index: imgfile.cc
===================================================================
--- imgfile.cc	(revision 2)
+++ imgfile.cc	(working copy)
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include "garminimg.h"
 
 using namespace std;
@@ -20,12 +21,16 @@
 // Subfile methods
 //----------------------------------------------------------------------
 
-void ImgFile::subfile_add (string type, off_t offset, udword_t sz)
+class ImgSubfile *ImgFile::subfile_add (string type, off_t offset, udword_t sz)
 {
 	class ImgSubfile *subfile= NULL;
 
+	if ( ! offset ) return NULL;
+
 	if ( type == "TRE" ) {
 		subfile= new ImgTRE (this, offset);
+	} else if ( type == "GMP" ) {
+		subfile= new ImgGMP (this, offset);
 	} else if ( type == "LBL" ) {
 		subfile= new ImgLBL (this, offset);
 	} else if ( type == "RGN" ) {
@@ -36,18 +41,28 @@
 		subfile= new ImgNOD (this, offset);
 	} else {
 		fprintf(stderr, "Unknown subfile %s\n", type.c_str());
-		return;
+		return NULL;
 	}
 
 	subfile->size= sz;
 	subfile->img= img;
 	subfiles.insert(make_pair(type, subfile));
+
+	return subfile;
 }
 
 class ImgSubfile *ImgFile::subfile_find (string type)
 {
 	subfile_list_t::iterator sfpos= subfiles.find(type);
 
+/*
+	for (sfpos= subfiles.begin(); sfpos != subfiles.end();
+	++sfpos) {
+		printf(">> Type= %s (%08x)\n", sfpos->first.c_str(),
+			sfpos->second);
+	}
+*/
+
 	if ( sfpos == subfiles.end() ) return NULL;
 
 	return sfpos->second;
@@ -206,6 +221,11 @@
 	cities.insert(make_pair(idx, city));
 }
 
+void ImgFile::city_inc(void)
+{
+	ImgFile::indexed_cities++;
+}
+
 string ImgFile::city_get (uword_t idx)
 {
 	locality_cache_t::iterator cpos;
@@ -237,7 +257,7 @@
 
 uword_t ImgFile::ncities ()
 {
-	return cities.size();
+	return ImgFile::indexed_cities + cities.size();
 }
 
 void ImgFile::zip_add (uword_t idx, string zip)
Index: nod.cc
===================================================================
--- nod.cc	(revision 2)
+++ nod.cc	(working copy)
@@ -6,7 +6,7 @@
 ImgNOD::ImgNOD (class ImgFile *ifilein, off_t offset)
 {
 	ifile= ifilein;
-	imgfile_offset= offset;
+	header_offset= imgfile_offset= offset;
 }
 
 ImgNOD::~ImgNOD ()
Index: decode_img.h
===================================================================
--- decode_img.h	(revision 2)
+++ decode_img.h	(working copy)
@@ -7,6 +7,8 @@
 
 void decode_common_header (class Decoder *dec, class ImgSubfile *sub);
 
+void decode_gmp_header (class Decoder *dec, class ImgGMP *sub);
+
 void decode_tre_header (class Decoder *dec, class ImgTRE *sub);
 void decode_tre_body ();
 
Index: decode_nod.cc
===================================================================
--- decode_nod.cc	(revision 2)
+++ decode_nod.cc	(working copy)
@@ -16,7 +16,7 @@
 {
 	udword_t length, offset;
 	uword_t rsize;
-	off_t soffset, eoffset;
+	off_t soffset, eoffset, hoffset;
 
 	nod= nod_in;
 	dec= dec_in;
@@ -24,8 +24,9 @@
 	ifile= nod->ifile;
 
 	soffset= nod->offset();
+	hoffset= nod->h_offset();
 
-	img->seek(soffset);
+	img->seek(hoffset);
 
 	dec->set_outfile("NOD", "header");
 	dec->banner("NOD: Header");
@@ -83,8 +84,8 @@
 
 	img->seek(soffset);
 
-	dec->set_outfile("NOD", "unknown1");
-	dec->banner("NOD: Unknown section 1");
+	dec->set_outfile("NOD", "section1");
+	dec->banner("NOD: Section 1");
 
 	dec->print("???", img->get_string(eoffset-soffset).c_str());
 }
@@ -93,15 +94,30 @@
 {
 	off_t soffset= nod->unknown2_info.offset;
 	off_t eoffset= nod->unknown2_info.offset+nod->unknown2_info.length;
+	off_t noffset= eoffset;
 
+	return; // XXX sr fix up this routine
 	img->seek(soffset);
 
-	dec->set_outfile("NOD", "unknown2");
-	dec->banner("NOD: Unknown section 2");
+	dec->set_outfile("NOD", "section2");
+	dec->banner("NOD: Section 2");
 
 	while (img->tell() < eoffset) {
+		byte_t data, rclass, sclass;
+
+		noffset= ifile->offset_next(img->tell());
+		if ( noffset > eoffset || noffset == 0 ) noffset= eoffset;
+
 		dec->comment("Offset 0x%06x", img->tell()-soffset);
-		dec->print("???", img->get_string(7).c_str());
+		data= img->get_byte();
+		rclass= (data&0xF0)>>4;
+		sclass= data&0xF;
+		dec->print("Road class 0x%x", rclass);
+		dec->comment("Speed class 0x%x", sclass);
+		dec->print("NOD1 offset 0x%06x?", img->get_uint24());
+
+		dec->print("???", img->get_string(noffset-img->tell()).c_str());
+		dec->comment(NULL);
 	}
 }
 
@@ -113,13 +129,14 @@
 
 	img->seek(soffset);
 
-	dec->set_outfile("NOD", "unknown3");
-	dec->banner("NOD: Unknown section 3");
+	dec->set_outfile("NOD", "boundary_nodes");
+	dec->banner("NOD: Boundary nodes");
 
 	for (n= 1; n<= nrecs; ++n) {
 		dec->comment("Record %u", n);
-		dec->print("???",
-			img->get_string(nod->unknown3_info.rsize).c_str());
+		dec->print("%.6f E", img->degrees(img->get_int24()));
+		dec->print("%.6f N", img->degrees(img->get_int24()));
+		dec->print("???", img->get_uint24());
 		dec->comment(NULL);
 	}
 }
Index: main.cc
===================================================================
--- main.cc	(revision 2)
+++ main.cc	(working copy)
@@ -2,6 +2,7 @@
 #include "garminimg.h"
 #include "decoder.h"
 #include "decode_img.h"
+#include <stdlib.h>
 
 void usage ();
 
@@ -21,8 +22,12 @@
 
 	img->set_fileent();
 	while ( (ifile= img->get_fileent()) != NULL ) {
-		class ImgSubfile *sub= ifile->subfile_find("TRE");
+		class ImgSubfile *sub= NULL;
+		
+		sub= ifile->subfile_find("GMP");
+		if ( sub != NULL ) decode_gmp_header(&dec, (ImgGMP *) sub);
 
+		sub= ifile->subfile_find("TRE");
 		if ( sub != NULL ) {
 			class ImgTRE *tre= (ImgTRE *) sub;
 			class ImgLBL *lbl;
@@ -60,7 +65,7 @@
 			if ( net ) decode_net_body();
 			if ( nod ) decode_nod_body();
 		} else {
-			fprintf(stderr, "TRE not found in\n");
+			fprintf(stderr, "TRE not found\n");
 			return -1;
 		}
 	}
Index: net.cc
===================================================================
--- net.cc	(revision 2)
+++ net.cc	(working copy)
@@ -6,7 +6,7 @@
 ImgNET::ImgNET (class ImgFile *ifilein, off_t offset)
 {
 	ifile= ifilein;
-	imgfile_offset= offset;
+	header_offset= imgfile_offset= offset;
 }
 
 ImgNET::~ImgNET ()
Index: rgn.cc
===================================================================
--- rgn.cc	(revision 2)
+++ rgn.cc	(working copy)
@@ -3,7 +3,7 @@
 ImgRGN::ImgRGN (class ImgFile *ifilein, off_t offset)
 {
 	ifile= ifilein;
-	imgfile_offset= offset;
+	header_offset= imgfile_offset= offset;
 }
 
 ImgRGN::~ImgRGN ()
Index: decode_net.cc
===================================================================
--- decode_net.cc	(revision 2)
+++ decode_net.cc	(working copy)
@@ -1,4 +1,5 @@
 #include <math.h>
+#include <stdlib.h>
 #include "imgtypes.h"
 #include "garminimg.h"
 #include "decoder.h"
@@ -7,25 +8,28 @@
 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_unkn2 ();
+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;
+	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(soffset);
+	img->seek(hoffset);
 
 	dec->set_outfile("NET", "header");
 	dec->banner("NET: Header");
@@ -40,13 +44,15 @@
 	net->roads_info.length= length;
 
 	dec->print("Road record offsets are x%u",
-		net->omult= int(pow(2.0,img->get_byte())));
+		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(NULL, img->get_byte());
+	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;
@@ -58,9 +64,9 @@
 	dec->print("Unknown2 record size %u bytes", 
 		rsize= img->get_uword());
 	ifile->offset_add(offset, NET_UNKN1);
-	net->unknown2_info.offset= offset;
-	net->unknown2_info.length= length;
-	net->unknown2_info.rsize= rsize;
+	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());
@@ -74,13 +80,14 @@
 
 void decode_net_body ()
 {
+	// Sorted road list
+
+	decode_net_sorted ();
+
 	// Parse road information first.
 
 	decode_net_roads ();
 
-	// Unknow section 2.  I think these may be intersections.
-
-	decode_net_unkn2 ();
 }
 
 void decode_net_roads ()
@@ -98,12 +105,14 @@
 
 	while ( img->tell() < eoffset ) {
 		udword_t lbloffset, roadinfo;
-		byte_t data;
+		double roadlen;
+		byte_t data, flags;
 		bool repeat;
 		off_t noffset;
-		int i, n;
+		int i, n, lcount;
 		unsigned int otype;
-		string stream;
+		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 ) {
@@ -115,36 +124,160 @@
 		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);
+			}
 		}
 
-		data= img->get_byte();
-		dec->print("Road data/flags %s?",
-			img->base(data, 2, 8).c_str());
-		dec->print("???", img->get_byte());
-		dec->print("???", img->get_uword());
+		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= 0;
+		n= lcount= 0;
 		while ( repeat ) {
+			int cnt;
+
 			data= img->get_byte();
 			repeat= !(data&0x80);
-			++n;
-			dec->print("unknown, for idx %d?", n);
+			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?",
+			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;
 
@@ -153,21 +286,31 @@
 	}
 }
 
-void decode_net_unkn2 ()
+void decode_net_sorted ()
 {
-	off_t soffset= net->unknown2_info.offset;
-	off_t eoffset= soffset+net->unknown2_info.length;
-	uword_t nrecs= net->unknown2_info.length/net->unknown2_info.rsize;
+	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->unknown2_info.offset);
-	dec->set_outfile("NET", "unknown2");
-	dec->banner("NET: Unknown Section 2 (Intersections?)");
+	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);
 
-		dec->print("Offset 0x%06x ?", (img->get_uint24()&0x3FFFFF));
+		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);
 	}
 }
Index: decode_rgn.cc
===================================================================
--- decode_rgn.cc	(revision 2)
+++ decode_rgn.cc	(working copy)
@@ -15,7 +15,7 @@
 
 void decode_rgn_header (class Decoder *dec_in, class ImgRGN *rgn_in)
 {
-	off_t soffset;
+	off_t soffset, hoffset;
 	rgn= rgn_in;
 	dec= dec_in;
 	img= dec->img;
@@ -24,8 +24,9 @@
 	net= (class ImgNET *) ifile->subfile_find("NET");
 
 	soffset= rgn->offset();
+	hoffset= rgn->h_offset();
 
-	img->seek(soffset);
+	img->seek(hoffset);
 
 	dec->set_outfile("RGN", "header");
 	dec->banner("RGN: Header");
@@ -150,9 +151,9 @@
 		word_t dx, dy;
 		string sinfo;
 
-		if ( indexed ) dec->comment("Point #%u", idx++);
+		dec->comment("Point #%u", idx++);
 		type= img->get_byte();
-		if ( has_subtype ) dec->print("Primary type %u", type);
+		dec->print("Primary type %u", type);
 
 		point_info= img->get_uint24();
 		has_subtype= (point_info & 0x800000);
@@ -230,10 +231,10 @@
 			lbl_in_net= lbl_info & 0x800000;
 			if ( lbl_in_net ) {
 				off_t netoff= net->roads_info.offset+
-					net->omult*lbloffset;
+					net->omult1*lbloffset;
 				ifile->offset_add(netoff, NET_ROAD_REC);
 				dec->print("Label at NET offset 0x%06x",
-					net->omult*lbloffset);
+					net->omult1*lbloffset);
 			} else {
 				dec->print("Label at LBL offset 0x%06x",
 					lbloffset);
Index: subfile.cc
===================================================================
--- subfile.cc	(revision 2)
+++ subfile.cc	(working copy)
@@ -10,8 +10,23 @@
 {
 }
 
+void ImgSubfile::set_header_offset (off_t offset_in)
+{
+	header_offset= offset_in;
+}
+
+void ImgSubfile::set_size (udword_t size_new)
+{
+	size= size_new;
+}
+
 off_t ImgSubfile::offset ()
 {
 	return imgfile_offset;
 }
 
+off_t ImgSubfile::h_offset ()
+{
+	return header_offset;
+}
+
Index: tre.cc
===================================================================
--- tre.cc	(revision 2)
+++ tre.cc	(working copy)
@@ -3,7 +3,7 @@
 ImgTRE::ImgTRE (class ImgFile *ifilein, off_t offset)
 {
 	ifile= ifilein;
-	imgfile_offset= offset;
+	header_offset= imgfile_offset= offset;
 	nsubdivisions= 0;
 	nlevels= 0;
 }
