ImageDisk project is canceled

Sean 'Captain Napalm' Conner spc at conman.org
Tue Dec 20 20:56:53 CST 2005


It was thus said that the Great Tony Duell once stated:
> 
> There are now presumably a number of disks archived in Imagedisk format 
> that cannot (legally) be read. Great!. This is no better than teledisk. 
> It has convinced me even more that the only tools I will use to archive 
> disks are open-source ones, because that's the only way I can be sure 
> that the author won't throw a hissy fit for whatever reason and make the 
> archives useless.

  Here you go Tony, and any other person that bitched about the Imagedisk
format being undocumented.  If Dave allows, I can include the actual format
from his documentation (he wrote the documentation, but said the format is
open---I suppose someone can write up the format, but I've already more time
on this than I cared to).

  -spc (Now maybe this will shut up the people that claim the format
	isn't documented ... )

/*********************************************************************
*
* Copyright 2001 by Sean Conner.  All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* Comments, questions and criticisms can be sent to: sean at conman.org
*
*********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/***********************************************************************/

typedef unsigned char t_byte;

enum
{
  TH_MODE,
  TH_CYLINDER,
  TH_HEAD,
  TH_SECTORS,
  TH_SECTORSIZE,
  TH_SIZE
};

typedef t_byte t_trackheader[5];

struct track
{
  int      mode;
  int      cylinder;
  int      head;
  int      sectors;
  int      sectorsize;
  t_byte  *sectormap;
  t_byte  *cylindermap;
  t_byte  *headmap;
  int     *validsector;
  t_byte **data;
};

/**********************************************************************/

static void	*my_malloc		(size_t);
static void	*my_realloc		(void *,size_t);
static void	 my_fread		(void *,size_t,FILE *,int);
static int	 my_feof		(FILE *);
static void	 imd_track_header_check	(t_trackheader,int,long);

char		*imd_header		(FILE *);
struct track	*imd_track		(FILE *,int);
void		 imd_track_free		(struct track *);

/**************************************************************************/

int main(int argc,char *argv[])
{
  int i;
  int j;
  FILE *fpin;
  char *header;
  struct track *track;
  
  static char *modes[] =
  {
    "500 kbps FM",
    "300 kbps FM",
    "250 kbps FM",
    "500 kbps MFM",
    "300 kbps MFM",
    "250 kbps MFM"
  };
  
  if (argc == 1)
  {
    fprintf(stderr,"usage: %s <imd files>\n",argv[0]);
    exit(EXIT_FAILURE);
  }
  
  for (i = 1 ; i < argc ; i++)
  {
    fpin = fopen(argv[i],"rb");
    if (fpin == NULL)
    {
      perror(argv[i]);
      continue;
    }
    
    header = imd_header(fpin);
    printf("HEADER:\n%s\n",header);
    free(header);
    
    for (j = 0 ; !my_feof(fpin) ; j++)
    {
      track = imd_track(fpin,j);
      printf(
        "Track: %d\n"
      	"\tMode: %s\n"
      	"\tCylinder: %d\n"
      	"\tHead: %d\n"
      	"\tSectors: %d\n"
      	"\tSector Size: %d\n"
      	"\tCylinder Map: %s\n"
      	"\tHead Map: %s\n",
	j,
      	modes[track->mode],
      	track->cylinder,
      	track->head,
      	track->sectors,
      	track->sectorsize,
      	(track->cylindermap == NULL) ? "no" : "yes",
      	(track->headmap     == NULL) ? "no" : "yes"
      );

      imd_track_free(track);
    }
    
    fclose(fpin);
  }
  
  return(EXIT_SUCCESS);
}

/*************************************************************************/

static void *my_malloc(size_t size)
{
  void *mem;

  assert(size > 0);
  
  mem = malloc(size);
  if (mem == NULL)
  {
    perror("out of memory");
    exit(EXIT_FAILURE);
  }
  
  return(mem);
}

/*************************************************************************/

static void *my_realloc(void *ptr,size_t size)
{
  void *mem;
  
  mem = realloc(ptr,size);
  if (mem == NULL)
  {
    perror("out of memory");
    exit(EXIT_FAILURE);
  }
  
  return(mem);
}

/************************************************************************/

static void my_fread(void *ptr,size_t size,FILE *fpin,int track)
{
  size_t r;
  
  r = fread(ptr,1,size,fpin);
  if (r != size)
  {
    fprintf(stderr,"corrupt track %04d - reading error\n",track);
    exit(EXIT_FAILURE);
  }
}

/***************************************************************************/

static int my_feof(FILE *fp)
{
  int c;
  
  c = fgetc(fp);
  if (c == EOF) return(1);
  ungetc(c,fp);
  return(0);
}

/***************************************************************************/

char *imd_header(FILE *fpin)
{
  char   *text = NULL;
  size_t  size = 0;
  size_t  i    = 0;
  int     c;
  
  assert(fpin != NULL);
  
  while(!feof(fpin))
  {
    c = fgetc(fpin);
    if (c == 0x1A) break;
    if (c == EOF)
    {
      fprintf(stderr,"unexpected end of input in header\n");
      exit(EXIT_FAILURE);
    }
    
    if (i == size)
    {
      size += 1024;
      text  = my_realloc(text,size);
    }
    text[i++] = c;
  }
  
  if (text) text[i] = '\0';
  return(text);
}

/************************************************************************/

static void imd_track_header_check(t_trackheader th,int track,long pos)
{
  if (th[TH_MODE] > 5)
  {
    fprintf(
    	stderr,
    	"corrupt track %04d - non-supported mode %d @ %08lX\n",
    	track,
    	th[TH_MODE],
	pos
    );
    exit(EXIT_FAILURE);
  }
  
  if ((th[TH_HEAD] & 0x3F) > 1)
  {
    fprintf(
    	stderr,
    	"corrupt track %04d - non-supported # heads %d @ %08lX\n",
    	track,
    	th[TH_HEAD],
	pos
    );
    exit(EXIT_FAILURE);
  }
  
  if (th[TH_SECTORSIZE] > 6)
  {
    fprintf(
    	stderr,
    	"corrupt track %04d - non-supported sector size %d @ %08lX\n",
    	track,
    	th[TH_SECTORSIZE],
	pos
    );
    exit(EXIT_FAILURE);
  }  
}

/*************************************************************************/

struct track *imd_track(FILE *fpin,int tr)
{
  struct track  *track;
  t_trackheader  thead;
  int            i;
  t_byte         sectype;
  t_byte         fill;
  
  assert(fpin  != NULL);
  assert(tr    >  -1);
  
  track = my_malloc(sizeof(struct track));
  memset(track,0,sizeof(struct track));
  
  my_fread(&thead,sizeof(t_trackheader),fpin,tr);
  imd_track_header_check(thead,tr,ftell(fpin));
  
  track->mode       = thead[TH_MODE];
  track->cylinder   = thead[TH_CYLINDER];
  track->head       = thead[TH_HEAD] & 0x3F;
  track->sectors    = thead[TH_SECTORS];
  track->sectorsize = 128 << (thead[TH_SECTORSIZE]);
  
  assert(
  	   (track->sectorsize ==  128)
  	|| (track->sectorsize ==  256)
  	|| (track->sectorsize ==  512)
  	|| (track->sectorsize == 1024)
  	|| (track->sectorsize == 2048)
  	|| (track->sectorsize == 4096)
  	|| (track->sectorsize == 8192)
  );
  
  track->sectormap = my_malloc(track->sectors);
  my_fread(track->sectormap,track->sectors,fpin,tr);
  
  if (thead[TH_HEAD] & 0x80)
  {
    track->cylindermap = my_malloc(track->sectors);
    my_fread(track->cylindermap,track->sectors,fpin,tr);
  }
  
  if (thead[TH_HEAD] & 0x40)
  {
    track->headmap = my_malloc(track->sectors);
    my_fread(track->headmap,track->sectors,fpin,tr);
  }
  
  track->validsector = my_malloc(track->sectors * sizeof(int));
  track->data        = my_malloc(track->sectors * sizeof(t_byte *));
  
  for (i = 0 ; i < track->sectors ; i++)
  {
    track->data[i] = my_malloc(track->sectorsize);
    
    my_fread(&sectype,1,fpin,tr);
    if (sectype == 0)
    {
      track->validsector[i] = 0;
      memset(track->data[i],0,track->sectorsize);
    }
    else if (sectype == 1)
    {
      track->validsector[i] = 1;
      my_fread(track->data[i],track->sectorsize,fpin,tr);
    }
    else if (sectype == 2)
    {
      my_fread(&fill,1,fpin,tr);
      memset(track->data[i],fill,track->sectorsize);
    }
  }
  
  return(track);
}

/************************************************************************/

void imd_track_free(struct track *track)
{
  int i;
  
  assert(track            != NULL);
  assert(track->sectormap != NULL);
  assert(track->data      != NULL);
  
  for (i = 0 ; i < track->sectors ; i++)
  {
    assert(track->data[i] != NULL);
    free(track->data[i]);
  }
  
  free(track->data);
  if (track->headmap)       free(track->headmap);
  if (track->cylindermap)   free(track->cylindermap);
  free(track->validsector);
  free(track->sectormap);
  free(track);
}

/**************************************************************************/



More information about the cctalk mailing list