diff --git a/disk.c b/disk.c
index 053fa21..7f6cb46 100644
--- a/disk.c
+++ b/disk.c
@@ -1030,7 +1030,7 @@ trackgen( libspectrum_disk_t *d, buffer_t *buffer, int head, int track,
 
 /* close and destroy a disk structure and data */
 void
-disk_close( libspectrum_disk_t *d )
+libspectrum_disk_close( libspectrum_disk_t *d )
 {
   if( d->data != NULL ) {
     libspectrum_free( d->data );
@@ -1137,7 +1137,7 @@ alloc_uncompress_buffer( unsigned char **buffer, int length )
 }
 
 int
-disk_preformat( libspectrum_disk_t *d )
+libspectrum_disk_preformat( libspectrum_disk_t *d )
 {
   buffer_t buffer;
 
@@ -1781,7 +1781,7 @@ cpc_set_weak_range( libspectrum_disk_t *d, int idx, buffer_t *buffer, int n,
 static int
 open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
 {
-  int i, j, seclen, idlen, gap, preindex, sector_pad, idx;
+  int i, j, seclen, idlen, gap, preindex, idx;
   int bpt, max_bpt = 0, trlen;
   int fix[84], plus3_fix;
   unsigned char *hdrb;
@@ -1790,8 +1790,13 @@ open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
   d->sides = buff[0x31];
   d->cylinders = buff[0x30];			/* maximum number of tracks */
   GEOM_CHECK;
-  buffer->idx = 256;
 /* first scan for the longest track */
+  if( *buffer->data == 'M' ) { /* All track sizes in the standard disk image must be the same. */
+    trlen = buff[0x32] + 256 * buff[0x33];
+  } else {
+    trlen = -1;
+  }
+  buffer->idx = 256;
   for( i = 0; i < d->sides*d->cylinders; i++ ) {
     /* ignore Sector Offset block */
     if( buffavail( buffer ) >= 13 && !memcmp( buff, "Offset-Info\r\n", 13 ) ) {
@@ -1800,7 +1805,8 @@ open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
 
       /* sometimes in the header there are more track than in the file */
     if( buffavail( buffer ) == 0 ) {			/* no more data */
-      d->cylinders = i / d->sides + i % d->sides;	/* the real cylinder number */
+      if( d->flag & LIBSPECTRUM_DISK_FLAG_NOADD_MISSING )
+        d->cylinders = i / d->sides + i % d->sides;	/* the real cylinder number */
       break;
     }
     if( buffavail( buffer ) < 256 ||
@@ -1808,19 +1814,22 @@ open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
       return d->status = LIBSPECTRUM_DISK_OPEN;
 
     gap = (unsigned char)buff[0x16] == 0xff ? GAP_MINIMAL_FM : GAP_MINIMAL_MFM;
-    plus3_fix = trlen = 0;
+    plus3_fix = 0;
     while( i < buff[0x10] * d->sides + buff[0x11] ) {
       if( i < 84 ) fix[i] = 0;
       i++;
     }
-    if( i >= d->sides*d->cylinders ||
-        i != buff[0x10] * d->sides + buff[0x11] )	/* problem with track idx. */
+    if( i >= d->sides*d->cylinders )
       return d->status = LIBSPECTRUM_DISK_OPEN;
 
+    if( i != buff[0x10] * d->sides + buff[0x11] )	/* problem with track idx. */
+      fprintf( stderr, "Track/head info mismatch! (exp:%d got:%d /max:%d/)\n",
+                                i, buff[0x10] * d->sides, d->sides*d->cylinders );
+
     bpt = postindex_len( d, gap ) +
           ( preindex ? preindex_len( d, gap ) : 0 ) +
           ( gap == GAP_MINIMAL_MFM ? 6 : 3 );	/* gap4 */
-    sector_pad = 0;
+
     for( j = 0; j < buff[0x15]; j++ ) {			/* each sector */
       seclen = d->type == LIBSPECTRUM_DISK_ECPC ? buff[ 0x1e + 8 * j ] +
                                                   256 * buff[ 0x1f + 8 * j ]
@@ -1858,21 +1867,18 @@ open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
                  buff[ 0x1b + 8 * j ] != 2 - ( j & 1 ) )
           plus3_fix = CPC_ISSUE_NONE;
       }
-      trlen += seclen;
-      if( seclen % 0x100 )		/* every? 128/384/...byte length sector padded */
-        sector_pad++;
     }
     if( i < 84 ) {
       fix[i] = plus3_fix;
       if( fix[i] == CPC_ISSUE_4 )         bpt = 6500;/* Type 1 variant DD+ (e.g. Coin Op Hits) */
       else if( fix[i] != CPC_ISSUE_NONE ) bpt = 6250;/* we assume a standard DD track */
     }
-    buffer->idx += trlen + sector_pad * 128 + 256;
+/* extended DSK image uses track size table */
+    buffer->idx += ( trlen < 0 ? 256 * buffer->data[0x34 + i] : trlen );
     if( bpt > max_bpt )
       max_bpt = bpt;
   }
-  if( max_bpt == 0 )
-    return d->status = LIBSPECTRUM_DISK_GEOM;
+  if( max_bpt == 0 ) max_bpt = 6250;
 
   d->density = LIBSPECTRUM_DISK_DENS_AUTO;			/* disk_alloc use d->bpt */
   d->bpt = max_bpt;
@@ -1882,18 +1888,22 @@ open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
   DISK_SET_TRACK_IDX( d, 0 );
   buffer->idx = 256;				/* rewind to first track */
   for( i = 0; i < d->sides*d->cylinders; i++ ) {
+    int ii;					/* track number from Track Info */
+    int idx_save;
+
     hdrb = buff;
+    idx_save = buffer->idx;
     buffer->idx += 256;		/* skip to data */
     gap = (unsigned char)hdrb[0x16] == 0xff ? GAP_MINIMAL_FM : GAP_MINIMAL_MFM;
 
-    i = hdrb[0x10] * d->sides + hdrb[0x11];		/* adjust track No. */
+    ii = hdrb[0x10] * d->sides + hdrb[0x11];		/* adjust track No. */
+    if( ii > i ) i = ii;
     DISK_SET_TRACK_IDX( d, i );
     d->i = 0;
     if( preindex)
       preindex_add( d, gap );
     postindex_add( d, gap );
 
-    sector_pad = 0;
     for( j = 0; j < hdrb[0x15]; j++ ) {			/* each sector */
       seclen = d->type == LIBSPECTRUM_DISK_ECPC ? hdrb[ 0x1e + 8 * j ] +	/* data length in sector */
                               256 * hdrb[ 0x1f + 8 * j ]
@@ -1957,11 +1967,10 @@ open_cpc( buffer_t *buffer, libspectrum_disk_t *d )
                                         /* ( ( N * len ) / len - 1 ) * len */
         }
       }
-      if( seclen % 0x100 )		/* every? 128/384/...byte length sector padded */
-        sector_pad++;
     }
     gap4_add( d, gap );
-    buffer->idx += sector_pad * 0x80;
+/* extended DSK image uses track size table */
+    buffer->idx = idx_save + ( trlen < 0 ? 256 * buffer->data[0x34 + i] : trlen );
   }
   return d->status = LIBSPECTRUM_DISK_OK;
 }
@@ -2453,8 +2462,8 @@ libspectrum_disk_merge_sides( libspectrum_disk_t *d, libspectrum_disk_t *d1,
     d->track += d->tlen;
     d2->track += d2->tlen;
   }
-  disk_close( d1 );
-  disk_close( d2 );
+  libspectrum_disk_close( d1 );
+  libspectrum_disk_close( d2 );
   return d->status = LIBSPECTRUM_DISK_OK;
 }
 
@@ -2968,7 +2977,8 @@ write_log( buffer_t *b, libspectrum_disk_t *d )
       rev = k = 0;
       while( id_read( d, &h, &t, &s, &l ) ) {
         l = 0x80 << l;
-        if( datamark_read( d, &del, &fmf ) ) {
+	if( l > 16384 ) l = 16384; /* max HD track len is 12650 byte */
+	if( datamark_read( d, &del, &fmf ) ) {
           buffprintf( b, "  h:%d t:%d s:%d l:%d (%s/%sFM)\n", h, t, s, l,
                    del ? "deleted" : "normal", fmf ? "M" : "" );
         } else {
diff --git a/libspectrum.h.in b/libspectrum.h.in
index 5f76a76..a4a0887 100644
--- a/libspectrum.h.in
+++ b/libspectrum.h.in
@@ -1040,8 +1040,9 @@ typedef enum libspectrum_disk_flag_t {
   LIBSPECTRUM_DISK_FLAG_NONE = 0x00,
   LIBSPECTRUM_DISK_FLAG_PLUS3_CPC = 0x01,	/* try to fix some CPC issue */
   LIBSPECTRUM_DISK_FLAG_OPEN_DS = 0x02,		/* try to open the other side too */
-  LIBSPECTRUM_DISK_FLAG_PREIDX = 0x04,		/* generate preindex GAP for some format */
-  LIBSPECTRUM_DISK_FLAG_SAVE_UNCOMPR = 0x08,	/* save image as uncompressed (UDI) */
+  LIBSPECTRUM_DISK_FLAG_PREIDX = 0x04,		/* generate preindex GAP for some format  */
+  LIBSPECTRUM_DISK_FLAG_SAVE_UNCOMPR = 0x08,	/* save image as uncompressed (UDI)  */
+  LIBSPECTRUM_DISK_FLAG_NOADD_MISSING = 0x10,	/* not add missing tracks */
 } libspectrum_disk_flag_t;
 
 typedef enum libspectrum_disk_error_t {
