#include <stdio.h>
#include <dos.h>
#include <bios.h>
#include <limits.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <malloc.h>

#include "layout.h"

void * allocate_layout( unsigned size ) {
        void    *x ;

	if( ( x = calloc( 1, size ) ) == NULL ) {
        printf( "Core pool depleted !" ) ;
        exit( 3 ) ;
	}
	*(unsigned *)x = size ;
	return( x ) ;
}

void * load_layout( FILE *in ) {
	int     len ;
	void    *layout ;

	len = getw( in ) ;
	if( feof( in ) )
        return( NULL ) ;
	if( ( layout = malloc( len ) ) == NULL ){
        printf( "Core pool depleted !" ) ;
        exit( 3 ) ;
	}
	*(unsigned *)layout = len ;
	if( fread( (char *)layout + sizeof( int ), len - sizeof( int ), 1, in ) != 1 ){
        printf( "Input file damaged !" ) ;
        exit( 3 ) ;
	}
	return( layout ) ;
}

int main( int argc, char *argv[] )
{
	FILE            *in ;
	FILE            *out ;
	TRACK_LAYOUT    *track ;
	SECTOR_LAYOUT   *sector ;
	void            *p;
	int             i;

	if( argc != 3 ){
		printf( "Usage is : display infile outfile" ) ;
        return 3 ;
	}
	if( ( in = fopen( argv[ 1 ], "rb" ) ) == NULL ){
        perror( argv[ 1 ] ) ;
        return 3 ;
	}
	if( ( out = fopen( argv[ 2 ], "wt" ) ) == NULL ){
        perror( argv[ 2 ] ) ;
        return 3 ;
	}
	while( ( p = load_layout( in ) ) != NULL )
		switch (((unsigned *)p)[1]) {
			case SECTOR_ID : sector=p;
				fprintf(out,
					"Tag length : %u bytes\n"
					"Tag ID : 0x%X ( SECTOR )\n"
					"Data Length : %u bytes\n"
					"Data Type : %u ( %s )\n",
					sector->length,
					sector->id,
					sector->data_length,
					sector->deleted,((sector->deleted)?"Deleted":"Normal"));
				switch((sector->data_code)&DATA_CODE_MASK) {
					case ORDINARY_DATA : p="Ordinary Data"; break;
					case SHORT_DATA : p="Short Data"; break;
					case BAD_CRC : p="Bad CRC Data"; break;
					case GAP_DATA : p="GAP Data"; break;
					case HIDDEN_DATA : p="Hidden Data"; break;
					case SLOCK_MARK : p="Superlock Mark"; break;
					case NO_DATA : p="No Data"; break;
				}
				fprintf(out,
					"Data Code : %u ( %s%s)\n"
					"Weak Count : %u\n"
					"Data Offset : %lu\n"
					"Weak Data :",
					sector->data_code, p,
					((sector->data_code&DATA_ON_IAM)?" /on IAM ":" "),
					sector->weak_cnt,
					ftell(in)-sector->length+12L);
				for(i=0;i<sector->weak_cnt;i++)
					fprintf(out," 0x%04X",
						((unsigned *)(sector->data+sector->data_length))[i]);
				fprintf(out,"\n\n");
				free(sector);
				break;
			case TRACK_ID : track=p;
				fprintf(out,
					"Tag length : %u bytes\n"
					"Tag ID : 0x%X ( TRACK )\n"
					"Version : %u\n"
					"Track : %u\n"
					"Head : %u\n"
					"Data rate : %u %s\n"
					"Sector Count : %u\n",
					track->length,
					track->id,
					track->version,
					track->cyl,
					track->head,
					((track->rate&0x7F)?
						(((track->rate&0x7F)-1)?
							(((track->rate&0x7F)-2)?
								(((track->rate&0x7F)-3)?0
								:125)
							:250)
						:300)
					:500),
					((track->rate&0x80)?"FM":"MFM"),
					track->count);
				switch(track->treatment) {
					case ORDINARY_TREATMENT : p="Ordinary Format"; break;
					case SPECIAL_FORMAT : p="Special Format"; break;
					case SPECIAL_WRITE : p="Special Write"; break;
				}
				fprintf(out,
					"Format Mode : %u ( %s )\n"
					"Disk revolution time : %lu ( reserved for Ver 1.x )\n"
					"Sectors info : ******************************************\n",
					track->treatment,p,
					track->revolution_time);
				for(i=0;i<track->count;i++) {
					switch(track->sectors[i].hidden_ID) {
						case no_hidden :      p="     No Hidden"; break;
						case hidden_address : p="Hidden Address"; break;
						case Super_Lock :     p="     Superlock"; break;
						default :             p="              "; break;
					}
					fprintf(out," * %2u:    (%02X/%02X/%02X/%02X) Ofs %-10lu   %s *\n",
						i+1,
						(track->sectors[i].c),
						(track->sectors[i].h),
						(track->sectors[i].r),
						(track->sectors[i].n),
						track->sectors[i].time_diff,
						p);
				}
				fprintf(out," ********************************************************\n\n");
				free(track);
				break;
			default : track=p;
				fprintf(out,
					"Tag length : %u bytes\n"
					"Tag ID : 0x%X ( UNKNOWN )\n\n",
					track->length,
					track->id);
				break;
		}
	return 0 ;
	fclose(in);
	fclose(out);
}
