#include <bios.h>
#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char *errstr[]={ "General disk error", "Read error", "Invalid drive",
			   "Not a DRAGONDOS disk", "Invalid entry access",
			   "Required parameter missing" };
int err=0;

/*	note: dragon drives are numbered 1-4, so the initial working drive value
	of 0 indicates no valid drive */

int wdrv=0, wtrck=-1, whead=-1, notracks, nosecs, dread=0;
/*	enough buffer for one track (18 sectors) and directory track */
char tbuf[4608], dbuf[4608];

/*	get sector from track buffer or read new track - NULL on error */
char *getabs(int track, int sector) {
	int retry=2;

	if(wdrv<1) {
		err=2;
		return NULL;
	}
	if(dread && (track<0 || track>=notracks || sector<1 || sector>nosecs)) {
		err=1;
		return NULL;
	}
	if(track==20 && sector<19) {
		if(!dread) {
			do {
				if(!retry--) {
					err=1;
					return NULL;
				}
			} while(biosdisk(2, wdrv-1, 0, 20, 1, 18, dbuf));
			dread=1;
		}
		return &dbuf[--sector<<8];
	}
	if(track!=wtrck || whead!=(sector-1)/18) {
		do {
			if(!retry--) {
				wtrck=-1;
				err=1;
				return NULL;
			}
		} while(biosdisk(2, wdrv-1, (sector-1)/18, track, 1, 18, tbuf));
		wtrck=track;
		whead=(sector-1)/18;
	}
	return &tbuf[--sector<<8];
}

/*	set current working drive.  reads track 20 and gets number of tracks and
	sectors per track from sector 1 */
int setwdrv(int drive) {
	char *buf;

	/* error if drive out of range */
	if(drive<1 || drive>4) {
		err=2;
		return -1;
	}
	/* disk reset */
	biosdisk(0, drive-1, 0, 0, 0, 0, NULL);
	wdrv=drive;
	if((buf=getabs(20, 1))==NULL)
		return -1;
	notracks=buf[252];
	nosecs=buf[253];
	/*	check for dragondos disk */
	if((notracks+buf[254]+1)&0xff+(nosecs+buf[255]+1)&0xff) {
		err=3;
		return -1;
	}
	return 0;
}

int main(int argc, char *argv[]) {
	char far *dparm=MK_FP(0, 0x78);
	char *buf, *sstr="\x07\x0a\x0d";
	int r,c,dr=2;

	if(argc<3) {
		err=5;
		goto errexit;
	}

	dparm=MK_FP((dparm[3]<<8)|dparm[2], (dparm[1]<<8)|dparm[0]);
	dparm[3]=1;

	if(argc>3)
		dr=atoi(argv[argc-3]);

	setwdrv(dr);
	buf=getabs(atoi(argv[argc-2]), atoi(argv[argc-1]));
	for(r=0; r<16; r++) {
		for(c=0; c<8; c++)
			printf(" %02X", 0xff&buf[c]);
		printf("-");
		for(c=8; c<16; c++)
			printf("%02X ", 0xff&buf[c]);
		printf("  ");
		for(c=0; c<16; c++) {
			if(strchr(sstr, 0xff&buf[c])==NULL) {
				putch(0xff&buf[c]);
			} else {
				putch('.');
			}
		}
		buf+=16;
		puts("");
	}

	goto normex;
errexit:
	puts(errstr[err]);
	dparm[3]=2;
	exit(1);
normex:
	dparm[3]=2;
	return 0;
}
