/*  psmain.c
 *    PSIOX standalone startup
 *    (c) 1994 Frank "Shaggy" Barrus 
 *    see psiox.c for interface details
 */


#include <stdio.h>
#include <stdlib.h>
#include "memtype.h"
#include "vdisk.h"
#include "psio.h"
#include "device.h"
#include "ados.h"
#include "argparse.h"


char errmsg[256];


int interactive = False;


#ifdef blah

void copy_disk_to_file(int drive, char *fname)
{
FILE *f;
byte buf[256];
int i, retry;
struct sio2pc_image_hdr hdr;
struct errormap *emap;
int nerr;
int nretry = 3;
	init_drive(drive);
	if((f = fopen(fname, "r"))) {
		fclose(f);
		printf("%s: disk image already exists\n", fname);
		exit(1);
	}
	f = fopen(fname, "w+");
	memset(&hdr, 0, sizeof(hdr));
	PUTWORD(hdr.code, SIO2PC_MAGIC);
	PUTLONG(hdr.size, disk[drive].nsec*(disk[drive].secsize/16));
	PUTWORD(hdr.secsize, disk[drive].secsize);
	fwrite(&hdr, sizeof(hdr), 1, f);
	emap = (struct errormap*)calloc(disk[drive].nsec,
				sizeof(struct errormap));
	nerr = 0;
	for(i=1; i<=disk[drive].nsec; i++) {
		printf("%04d\b\b\b\b", i);
		fflush(stdout);
		retry = nretry;
		while(retry-- && !read_sector(drive, i, buf)) {
			if(retry == nretry-1)
				printf("D%d: sector %5d: %s",
					drive+1, i, errmsg);
			else
				printf(", %s", errmsg);
			if(retry) {
				printf(" -- retry");
				fflush(stdout);
				if(i > disk[drive].nsec/2)
					read_sector(drive, 1, buf);
				else
					read_sector(drive,
						disk[drive].nsec, buf);
				sleep(1);
			} else {
				get_drive_status(drive);
				printf(" -- failed (%02X/%02X)",
					disk[drive].cstat, disk[drive].hstat);
				PUTWORD(emap[nerr].sec, i);
				emap[nerr].cstat = disk[drive].cstat;
				emap[nerr].hstat = disk[drive].hstat;
				nerr++;
			}
		}
		if(retry < nretry-1)
			printf("\n");
		fwrite(buf,disk[drive].secsize,1,f);
	}
	fwrite(emap, sizeof(*emap), nerr, f);
	free(emap);
	rewind(f);
	PUTWORD(hdr.errnum, nerr+1);
	fwrite(&hdr, sizeof(hdr), 1, f);
	fclose(f);
}


void show_stats(char *fname)
{
FILE *f;
struct errormap emap;
struct sio2pc_image_hdr hdr;
int i, secsize, nsec;
int nerr;
	f = fopen(fname, "r");
	fread(&hdr, sizeof(hdr), 1, f); 
	if(GETWORD(hdr.code) != SIO2PC_MAGIC) {
		printf("not an [E]SIO2PC file\n");
		return;
	}
	secsize = GETWORD(hdr.secsize);
	nsec = GETLONG(hdr.size)/(secsize/16);
	nerr = GETWORD(hdr.errnum);
	if(!nerr) 
		printf("%s: SIO2PC; %d sectors; %d bytes per sector\n",
			fname, nsec, secsize);
	else {
		printf("%s: ESIO2PC; %d sectors; %d bytes per sector; %d bad sectors\n", 
			fname, nsec, secsize, nerr-1);
		fseek(f, sizeof(hdr)+nsec*secsize, SEEK_SET);
		for(i=0; i<nerr-1; i++) {
			fread(&emap, sizeof(emap), 1, f);
			printf("%d:%02X/%02X  ", GETWORD(emap.sec),
				emap.cstat, emap.hstat);
		}
		printf("\n");
	}
	fclose(f);
}



void fix_file(int drive, char *fname)
{
FILE *f;
byte buf[256];
int i, sec, retry;
struct sio2pc_image_hdr hdr;
struct errormap *emap, *oldmap;
int nerr, oldnerr;
int nretry = 6;
	init_drive(drive);
	f = fopen(fname, "r+");
	fread(&hdr, sizeof(hdr), 1, f);
	if(GETWORD(hdr.code) != SIO2PC_MAGIC) {
		printf("not an SIO2PC file\n");
		return;
	}
	if(GETLONG(hdr.size) != disk[drive].nsec*(disk[drive].secsize/16)
	   || GETWORD(hdr.secsize) != disk[drive].secsize) {
		printf("%s: SIO2PC header does not match drive parameters\n");
		return;
	}
	oldnerr = GETWORD(hdr.errnum)-1;
	if(oldnerr < 1) {
		printf("%s: no errors to fix\n");
		return;
	}
	oldmap = (struct errormap*)calloc(oldnerr,
				sizeof(struct errormap));
	emap = (struct errormap*)calloc(oldnerr,
				sizeof(struct errormap));
	fseek(f, disk[drive].nsec*disk[drive].secsize, SEEK_CUR);
	fread(oldmap, sizeof(*oldmap), oldnerr, f);
	nerr = 0;
	for(i=0; i<oldnerr; i++) {
		sec = GETWORD(oldmap[i].sec);
		printf("D%d: sector %5d: ", drive+1, sec);
		fflush(stdout);
		retry = nretry;
		while(retry-- && !read_sector(drive, sec, buf)) {
			printf("%s; ", errmsg);
			fflush(stdout);
			if(retry) {
				read_sector(drive, retry*disk[drive].nsec/6, buf);
				sleep(2);
			} else {
				get_drive_status(drive);
				printf("failed (%02X/%02X)",
					disk[drive].cstat, disk[drive].hstat);
				PUTWORD(emap[nerr].sec, sec);
				emap[nerr].cstat = disk[drive].cstat;
				emap[nerr].hstat = disk[drive].hstat;
				nerr++;
			}
		}
		if(retry < 0)
			printf("\n");
		else
			printf("ok\n");
		fseek(f, sizeof(hdr)+(sec-1)*disk[drive].secsize, SEEK_SET);
		fwrite(buf,disk[drive].secsize,1,f);
	}
	rewind(f);
	PUTWORD(hdr.errnum, nerr+1);
	fwrite(&hdr, sizeof(hdr), 1, f);
	fseek(f, disk[drive].nsec*disk[drive].secsize, SEEK_CUR);
	fwrite(emap, sizeof(*emap), nerr, f);
	free(emap);
	free(oldmap);
	fclose(f);
}

#endif


void print_error(char *str)
{
	fprintf(stderr, "%s%s\n", str, errmsg);
	exit(1);
}


int exec_options(int argc, char **argv)
{
	if((argc = psio_init(argc, argv)) < 0) 
		return False;
	if((argc = vdisk_init(argc, argv)) < 0) 
		return False;
	if((argc = dos_init(argc, argv)) < 0) 
		return False;
	if((argc = device_init(argc, argv)) < 0) 
		return False;
	while(argc--) {
		if(!strcmp(*argv, "-i"))
			interactive++;
		else if(!strcmp(*argv, "-h")) {
			printf("General options:\n");
			printf("\t-h\t\t\tlist options\n");
			printf("\t-i\t\t\tinteractive mode\n");
			printf("\t-v\t\t\tvirtual fileserver mode\n");
			return True;
		} else {
			sprintf(errmsg, "invalid option: %s", *argv);
			return False;
		}
	}
	return True;
}


int main(int argc, char **argv)
{
char str[256];
	printf("PSIOX: Parallel SIO Xfer program   v0.10 (August 3, 1994)\n");
	printf("Written by Frank Barrus.  (c) 1994 ShagWare.\n");
	argc--; argv++;
	if(!argc) {
		fprintf(stderr, "No options specified. (-h for help)\n"); 
		exit(1);
	}
	if(!exec_options(argc, argv)) {
		fprintf(stderr, "%s\n", errmsg);
		return 1;
	}
	while(interactive && printf(">") 
	      && fgets(str, sizeof(str), stdin)) 
		if(str[0] == '!')
			system(&str[1]);
		else if(!parse_options(str))
			fprintf(stderr, "%s\n", errmsg);
	printf("\n");
	vdisk_end();
	return 0;
}

