koreth@ssyx.ucsc.edu (Steven Grimm) (07/15/88)
Submitted-by: uunet!mcvax!mirsa.inria.fr!colas (Colas Nahaboo)
Posting-number: Volume 1, Issue 62
Archive-name: flip27/part01
#--------------------------Cut Here--------------------------
#! /bin/sh
# This is a shell archive. Remove anything before the "#! /bin/sh" line,
# then unpack it by saving it in a file and typing "sh file."
#
# Wrapped by Steven Grimm (koreth) at ssyx on Fri Jul 15 09:32:22 1988
#
# unpacks with default permissions
#
# Contents : FLIP.C
#
if `test ! -s FLIP.C`
then
echo "x - FLIP.C"
cat > FLIP.C << '@\Rogue\Monster\'
/********************************************\
* *
* flip: Unprotected disk copier *
* By Colas NAHABOO (INRIA sophia-antipolis) *
* *
* Compile with MEGAMAX C v1.1 (in-line asm) *
* *
\********************************************/
#define VERSION "2.7"
#define DATE "Jun 25 88"
char *header =
"\33E\33e\33v\033p\
FLIP: disk copier by Colas Nahaboo v%-5s %-9s Free Ram:%4ldK\
\033q\n\n";
#include <osbind.h>
#include <stdio.h>
#define BLANK (0xE5E5) /* std sector format value */
#define MAGIC (0x87654321L) /* magic number value */
unsigned char *ROMS_YEAR = 0x00fc0018L + 3L; /* year of the roms */
#define MEMORY_LEFT 0 /* bytes not eaten by main buffer */
#define TRACK_RETRY 4 /* number of full track retrys */
#define NO_DISK 0 /* no disk in drive */
#define SOURCE_DISK 1 /* source disk in drive */
#define DEST_DISK 2 /* destination disk in drive */
/* list of fatal errors */
#define NORMAL 10
#define USER_ABORT 1
#define SYNTAX_ERROR 2
#define NO_DISK_IN_MEMORY 3
#define NO_OVERRIDE 4
#define NO_DRIVE_B 5
#define DOUBLE_ON_BACK 6
#define NO_FLIP_ON_DOUBLE 7
#define BAD_OPTION 8
#define NO_MEMORY 9
int bad_option = ' ';
/* twister interface */
extern twister(); /* adress of formatter */
char buffer_data[0x3FFF]; /* 16k of buffer */
extern long buffer; /* format track buffer */
extern int thedisk, /* A=0, B=1 */
dblsided, /* SS=0, DS= -1 */
sectoroffset, /* 0 = sectors 0 to 10, 1= 11 to 20 */
flipped, /* normal=0, back side=1 */
keypress, /* 1 if key aborted format */
starttrack, /* 0 or more */
endtrack; /* 80 or more */
extern int badflag; /* return code */
extern int new_roms; /* are we running with the new roms? */
/* flip's globals */
long buffer_size = 0L; /* max size of buffer */
jmp_buf start_dest; /* insert dest */
int drives_content[2];/* what is there in the drives ? */
int /* disk parameters read from boot sect */
drive, /* drive: 0=A, 1=B */
sides, /* 0=SS, 1=DS */
tracks, /* 80 normally */
st, /* sectors per track (9 or 10) */
bps; /* bytes per sector (512) */
int /* options */
verify_source, /* just verify the source */
read_source, /* read source */
zero_disk, /* prepares blank image in memory */
write_dest, /* write dest */
format, /* do format */
Verify, /* do verify formatting */
verify, /* do verify writing */
override, /* do not read boot sector */
single, /* Single Sided */
nine_sectors, /* 9 sect/track */
interactive, /* interactive */
play_it_again_sam, /* user hit "return" */
use_track_map; /* to use built-in track map */
int d1=0, d2=0, s1=0, s2=0; /* drive/side source/dest */
#define TRACK_MAP_SIZE 99
char track_map[TRACK_MAP_SIZE + 1];
char full_track_map[TRACK_MAP_SIZE + 1]; /* for multipasses */
int one_valid_copy_done = 0; /* used to allow "r" */
int multipass; /* when not enough mem */
int first_pass,
last_pass;
jmp_buf start;
char *buf = NULL;
char *malloc(), *index(), *get_drive();
unsigned is_non_executable();
extern char *help_text[];
int errno;
char rep[40], default_rep[40]; /* input buffer */
/*
* parse the command line and set options
* return 1 if error, 0 if OK
*/
int
parse_command()
{
printf("Command (? for help) (CR= %s ): ", default_rep);
fflush(stdout);
gets(rep);
/* parse main options */
verify_source = read_source = zero_disk = write_dest = format =
verify = Verify = use_track_map = override = nine_sectors = single =
interactive = d1 = d2 = s1 = s2 = play_it_again_sam = 0;
if (!rep[0]) { /* void rep ==> default */
strcpy(rep, default_rep);
play_it_again_sam = 1;
}
switch(rep[0]){
case '?': /* need help */
more(help_text);
longjmp(start, NORMAL);
case 'q': /* quit */
exit(0);
case 'v':
verify_source = 1;
get_options(get_drive(SOURCE_DISK, rep+1, 1), "os9ti");
return 0;
case 'r':
if (!one_valid_copy_done)
longjmp(start, NO_DISK_IN_MEMORY);
get_options(get_drive(DEST_DISK, rep+1,1), "fvVi");
write_dest = 1;
return 0;
case 'f':
override = 1;
get_options(get_drive(DEST_DISK, rep+1,1), "s9tvVfi");
zero_disk = 1;
write_dest = 1;
return 0;
case 'a': case 'b':
get_options(
get_drive(DEST_DISK,
get_drive(SOURCE_DISK, rep, 0),
1),
"os9tvVfi");
read_source = write_dest = 1;
return 0;
default :
longjmp(start, SYNTAX_ERROR);
}
}
char *
get_drive(drive, string, is_optional)
int drive;
char * string;
int is_optional;
{
char *ptr =string;
int side = 0, default_drive = 0;
if(!index("abAB", string[0]))
if(is_optional)
default_drive = 1; /* drive A is default */
else
longjmp(start, SYNTAX_ERROR);
if(!default_drive && (index("12", string[1]))) {
ptr ++;
side = (toupper(*ptr) == '2' ? 1 : 0);
}
if(drive == DEST_DISK){
d2 = (default_drive ? 0 : (toupper(*string) == 'B' ? 1 : 0));
s2 = side;
}else{
d1 = (default_drive ? 0 : (toupper(*string) == 'B' ? 1 : 0));
s1 = side;
}
return (default_drive ? string : ptr +1);
}
get_options(string, options)
char *string, *options;
{
while(*string){
if(!index(options, *string)) {
bad_option = *string;
longjmp(start, BAD_OPTION);
}
switch(*string){
case 'o': override = 1; break;
case 's': single = 1; break;
case '9': nine_sectors = 1; break;
case 't': use_track_map = 1; break;
case 'v': verify = 1; break;
case 'V': Verify = 1; break;
case 'f': format = 1; break;
case 'i': interactive = 1; break;
}
string++;
}
if(!override && (single || nine_sector))
longjmp(start, NO_OVERRIDE);
}
main()
{
buffer = (long) buffer_data;/* init twister */
sectoroffset = 0; /* mem alloc */
buffer_size = (long) Malloc(-1L) - MEMORY_LEFT;
buf = (char *) Malloc(buffer_size);
if(((unsigned) *ROMS_YEAR) > (unsigned) 0x86)
new_roms = 1;
else
new_roms = 0;
if(is_drive_B()) /* default command */
strcpy(default_rep, "bfv");
else
strcpy(default_rep, "afv");
printf(header, VERSION, DATE, buffer_size / 1024); /* resets screen */
switch(setjmp(start)){
case 0:case NORMAL: /* initial */
break;
case USER_ABORT: /* user abort */
printf("\007Ok, aborted...\n");
break;
case SYNTAX_ERROR: /* syntax error */
printf("\007SYNTAX ERROR!\n");
break;
case NO_DISK_IN_MEMORY:
printf("\007No disk in memory!\n");
break;
case NO_OVERRIDE:
printf("\007Options d and 9 requires option o\n");
break;
case NO_DRIVE_B:
printf("\007Sorry, no drive B present...\n");
break;
case DOUBLE_ON_BACK:
printf("\007A double sided disk on back? use override!\n");
break;
case NO_FLIP_ON_DOUBLE:
printf("\007You cannot flip double-sided disks!\n");
break;
case BAD_OPTION:
printf("\007bad option: %c\n", bad_option);
break;
case NO_MEMORY:
printf("\007Sorry, not enough memory...\n");
break;
}
while (1) {
/* we dont know what's in the drives */
drives_content[0] = drives_content[1] = NO_DISK;
/* prompts and parse command and options */
parse_command();
/* check for drive B */
if ((d1 || d2) && (!is_drive_B()))
longjmp(start, NO_DRIVE_B);
/* prompts for track_map */
if (use_track_map)
input_track_map();
/* examine source disk */
if(read_source || verify_source || zero_disk)
examine_disk(d1, s1);
/* check run time consistency */
if (sides == 2) {
if (s1 == 1)
longjmp(start, DOUBLE_ON_BACK);
if (s1 != s2)
longjmp(start, NO_FLIP_ON_DOUBLE);
}
strcpy(default_rep, rep); /* seems ok then take it as default */
/* copy disk */
if((d1 != d2) && /* suppose user had time to put dest */
(read_source || verify_source))
drives_content[d2] = DEST_DISK;
do_copy_disk();
printf("\007OK, done.\n");
}
}
/*
* do_copy_disk:
* do a one-pass or multipass copy
*/
do_copy_disk()
{
int track_number = 0, i, j, to_do;
multipass = 0;
if (read_source) {
for (i = 0; i < TRACK_MAP_SIZE; i++)
track_number += (int) track_map[i];
if(buffer_size < (sides * bps * st * (long) track_number))
multipass = 1;
one_valid_copy_done = !multipass; /* let previous value of
multipass inchanged if no read_source */
}
if(zero_disk) one_valid_copy_done = 0;
bcopy(track_map, full_track_map, TRACK_MAP_SIZE);
if(!multipass){
copy_disk();
}else{
for(j=0; j<TRACK_MAP_SIZE; j++)
track_map[j] = '\0';
track_number = buffer_size / (sides*bps*st);
i = to_do = 0;
first_pass = 1;
last_pass = 0;
while(i < TRACK_MAP_SIZE){
if(full_track_map[i]){
to_do++;
track_map[i] = '\001';
}
if(to_do == track_number){
copy_disk();
to_do = first_pass = 0;
for(j=0; j<TRACK_MAP_SIZE; j++)
track_map[j] = '\0';
}
i++;
}
first_pass = 0;
last_pass = 1;
copy_disk();
}
}
/*
* examine_disk: reads boot sector to determine type of disk.
*/
/* describe the BOOT sector by offsets in the boot sector */
#define b_bootbranch 0
#define b_oem 0x02
#define b_serial 0x08
#define b_bps 0x0B
#define b_spc 0x0D
#define b_res 0x0E
#define b_nfats 0x10
#define b_ndirs 0x11
#define b_nsects 0x13
#define b_media 0x15
#define b_spf 0x16
#define b_spt 0x18
#define b_nsides 0x1A
#define b_nhide 0x1C
#define b_boot 0x1E
#define b_checksum 0x01FE
/* 2 chars ==> 1 int */
#define canshort(x,y) (((unsigned)(x))|(((unsigned)(y))<<8))
unsigned char bb[512];
randomize_boot()
{
long serial;
unsigned non_exec = is_non_executable(buf);
if((!multipass || first_pass) && track_map[0]) {
serial = Random();
buf[b_serial] = (char) ((serial >> 16) & 255L);
buf[b_serial+1] = (char) ((serial >> 8) & 255L);
buf[b_serial+2] = (char) (serial & 255L);
update_checksum(buf, non_exec);
}
}
/*
* prepares a blank image:
* boot sector, & zero tracks 0&1 (if enough memory)
*/
do_zero_disk()
{
unsigned nsects;
if(buffer_size < (sides * bps * st * 2L)) longjmp(start, NO_MEMORY);
bfill(buf, '\0', (long) (sides * bps * st * 2L));
Protobt(buf, 0x02000000L, ((sides == 2) ? 3 : 2), 0);
buf[b_spt] = (char) (st & 0xFF);
nsects = (unsigned) (sides * st * (1 + max_track()));
buf[b_nsects] = (char) (nsects & 255);
buf[b_nsects+1] = (char) ((nsects >> 8) & 255);
update_checksum(buf, (unsigned) 1);
printf("Formatting %s sided disk, %d tracks and %d sectors.\n",
((sides == 1) ? "single" : "double"), 1+max_track(), st);
}
int
max_track()
{
int i;
for (i= TRACK_MAP_SIZE -1; i>=0; i--)
if(full_track_map[i]) return i;
return 0;
}
examine_disk(drive, side)
int drive, side;
{
int i;
if (override) {
sides = (single ? 1 : 2);
bps = 512;
st = (nine_sectors ? 9 : 10);
tracks = 80;
} else {
if (drives_content[drive] != SOURCE_DISK) {
prompt_for_disk(SOURCE_DISK, drive, side);
}
while (Floprd(&bb, 0L, drive, 1, 0, side, 1)) {
printf("\007Cannot read boot block! CR/SP=retry, other=abort: ");
fflush(stdout);
if (!index("\r\n ", (char) Cnecin()))
longjmp(start, USER_ABORT);
}
if(!is_non_executable(bb)) {
printf("\007EXECUTABLE BOOT! at $3A, %2x %2x %2x -- check for virus\n",
(int) bb[58], (int) bb[59], (int) bb[60]);
}
printf("Disk in drive %c:", 'A' + drive);
printf(" %d side", sides = (int) bb[b_nsides]);
printf("%s, %d tracks,", (sides == 2 ? "s" : ""),
tracks = ((canshort(bb[b_nsects], bb[b_nsects + 1]) /
(int) bb[b_spt]) /
(int) bb[b_nsides]));
printf(" %d sectors of", st = (int) bb[b_spt]);
printf(" %d bytes\n", bps =
canshort(bb[b_bps], bb[b_bps + 1]));
if ((bps != 512) || ((st != 10) && (st != 9)) || (tracks != 80)) {
printf("\007WARNING -- this is not a normal disk!\n");
}
if (sides < 1 || sides > 2 ||
bps != 512 ||
st > 11 || st < 9 ||
tracks < 1 || tracks > TRACK_MAP_SIZE) {
printf("***** Strange disk! ... copying normally ");
printf("(1 side, 80 tracks of 9 sectors)\n");
override = 1;
sides = 1;
bps = 512;
st = 9;
tracks = 80;
}
}
if (!use_track_map) {
for (i = 0; i < tracks; i++)
track_map[i] = '\001';
for (i = tracks; i < TRACK_MAP_SIZE; i++)
track_map[i] = '\0';
}
}
/*
* format disk using TWISTER
* returns 0 if OK, aborts and returns 1 on error.
*/
int
format_disk(f_drive, f_double, f_side)
int f_drive, f_double, f_side;
{
int i;
char *map;
if(multipass)
map = full_track_map;
else
map = track_map;
thedisk = f_drive;
dblsided = (f_double ? -1 : 0);
flipped = f_side;
redo:
i = 0;
while (i < TRACK_MAP_SIZE) {
if (map[i]) {
starttrack = i;
while (map[i++]);
endtrack = i - 1;
keypress = 0;
Supexec(twister);
if(keypress) {
longjmp(start, USER_ABORT);
}
if (badflag){
printf("\n\007FORMAT Error! CR/SP = retry whole formatting,");
printf(" other=abort\n");
printf("(disk might be WRITE_PROTECTED?)\n");
if (!index("\r\n ", (char) Cnecin()))
longjmp(start, USER_ABORT);
else
goto redo;
}
} else {
i++;
}
}
}
/*
* copy_disk: where the copy is really done
*/
copy_disk()
{
if((read_source || verify_source)
&& (drives_content[d1] != SOURCE_DISK))
prompt_for_disk(SOURCE_DISK, d1, s1);
if (read_source) { /* source */
read_disk(d1, s1); /* read */
next_line();
}
if (verify_source && (!multipass || first_pass)) {
verify_disk(d1, s1);
next_line();
}
setjmp(start_dest); /* destination */
if(zero_disk) do_zero_disk(); /* blank image */
if(!override) randomize_boot(); /* change serial */
if((format || Verify || write_dest || verify))
prompt_for_disk(DEST_DISK, d2, s2);
if (format && (!multipass || first_pass)) { /* format */
format_disk(d2, sides - 1, s2);
next_line();
}
if (Verify && (!multipass || first_pass)) { /* Verify */
verify_disk(d2, s2);
next_line();
}
if (write_dest) { /* write */
write_disk(d2, s2);
next_line();
}
if (verify && (!multipass || last_pass)) { /* verify */
verify_disk(d2, s2);
next_line();
}
}
/*
* return 1 if skip, 0 if no key, longjmps to start if abort
*/
abort_on_key(track,side)
int track,side;
{
if (Cconis()) {
if ((int) Cnecin() == 0x1b)
longjmp(start, USER_ABORT);
printf("\n\007KEY PRESSED! CR/SP = continue, ");
printf("i=interactive, %s other abort:\n",
(track == -1 ? "" : " S = skip,"));
switch ((int) Cnecin()) {
case ' ':
case '\n':
case '\r':
return 0;
case 'i':
case 'I':
interactive = 1;
return 0;
case 's':
case 'S':
if (track != -1) {
printf("Ok, skipping track %d, side %d (sects #%d - #%d)\n",
track + 1, side +1,
((track * sides) + side)* st,
((track * sides) + side + 1) * st);
return 1;
}
}
longjmp(start, USER_ABORT);
}
}
int
retry(s, t, side, restart)
char *s;
int t, side;
long *restart;
{
printf("\n\007** %s ERROR track %d ,side %d (s. #%d - #%d) ",
s, t + 1, side + 1,
(t * sides + side) * st,
(t * sides + side + 1) * st);
printf("CR/SP retry, S skip, %sother abort",
(restart ? "BS=OTHER disk " : ""));
fflush(stdout);
switch ((int) Cnecin()) {
case ' ':
case '\r':
case '\n':
return 1;
case 's':
case 'S':
printf("\n OK, skipping track %d, side %d\n", t + 1, side + 1);
return 0;
case '\010':
if (restart)
longjmp(restart, 1);
default:
longjmp(start, USER_ABORT);
}
}
/*
* sector_read
* reads one track into ptr, reading sector by sector
* returns: 0=ok, 1=bad, 2= skip.
*/
int
sector_read(ptr, foo, drive, sect1, track, side, n)
char *ptr, *foo;
int drive, sect1, track, side, n;
{
int i, result = 0, pass;
int pass_ok[4];
for (pass = 0; pass < 4; pass++) {
pass_ok[pass] = 1;
for (i = 0; i < n; i++) {
if (abort_on_key(track,i))
return 2;
switch (one_sector_read(
(pass ? buffer_data + (pass - 1) * 5120 : ptr) + (i * bps),
foo, drive, i + sect1, track, side)) {
case 1:
if (!result)
printf("\nTrack %d, side %d: sectors ",
track + 1, side + 1);
result = 1;
printf("%d (#%d) ", i + 1, (track * sides + side) * st + i);
fflush(stdout);
bfill(ptr + i * bps, '\0', (long) bps); /* fills bad sector with */
/* 0's */
case 2:
pass_ok[pass] = 0;
}
}
if (result) {
printf("are bad!\n");
fflush(stdout);
return result;
}
}
if (pass_ok[0])
return 0; /* if any pass is good, use it */
{
int i;
for (i = 1; i < 4; i++) {
if (pass_ok[i]) {
bcopy(buffer_data + 512 * (i - 1), ptr, 512 * n);
return 0;
}
}
}
if (check_random(track, side, n, ptr, buffer_data)) {
return 1; /* random read */
} else {
printf("\nTrack %d, side %d, (sects #%d - #%d) read sect by sect\n"
,track + 1, side + 1,
(track * sides + side) * st,
(track * sides + side + 1) * st);
return 1; /* no but don't trust! */
}
}
/*
* check_random:
* check tracks buffer to see if equal, return 1 if error
*/
int
check_random(track, side, n, buf0, buf1)
int track, side, n;
char *buf0, *buf1;
{
int sect, i, bad = 0;
char *p0, *p1, *p2, *p3;
for (sect = 1; sect <= n; sect++) {
p0 = buf0 + (sect - 1) * 512;
p1 = buf1 + (sect - 1) * 512;
p2 = buf1 + (sect - 1) * 512 + 5120;
p3 = buf1 + (sect - 1) * 512 + 10240;
for (i = 0; i < 512; i++, p0++, p1++, p2++, p3++) {
if ((*p0 != *p1) || (*p0 != *p2) || (*p0 != *p3)) {
if (!bad) {
printf("\n\007DIFFERENT READS ");
printf("on track %d, side %d, sects ",
track + 1, side + 1);
bad = 1;
}
printf("%d (#%d) ", sect,
(track * sides + side) * st + sect - 1);
break;
}
}
}
if(bad) {
printf("\n");
fflush(stdout);
}
return bad;
}
/*
* one_sector_read:
* reads a sector and the 2 outside it
* return 0 if ok, 1 if bad, 2 if forced to copy sector alone
*/
char *private_buffer[512 * 3];
int
one_sector_read(buf, foo, drive, sect, track, side)
char *buf, *foo;
int drive, sect, track, side;
{
if (Floprd(private_buffer + (sect == 1 ? 512 : 0), foo, drive,
(sect == 1 ? 1 : sect - 1), track, side,
((sect == 1) || (sect == st) ? 2 : 3))) {
if (Floprd(private_buffer + 512, foo, drive, sect, track, side, 1)){
return 1;
} else {
bcopy(private_buffer + 512, buf, 512);
return 2;
}
}
bcopy(private_buffer + 512, buf, 512);
return 0;
}
next_line()
{
Crawio((int) '\r');
Crawio((int) '\n');
}
bcopy(from, to, count)
register char *from, *to;
int count;
{
register char *last = from + count;
while (from != last)
*to++ = *from++;
}
bfill(from, octet, count)
register char *from, octet;
long count;
{
register char *last = from + count;
while (from != last)
*from++ = octet;
}
/*
* is_drive_B
* return 1 if drive B is there
*/
int
is_drive_B()
{
long usermode = Super(0L);
int result = *(int *) 0x4a6; /* _nflops */
Super(usermode);
return (result - 1);
}
/*
* retry_track
* retries plain track
*/
int
retry_track(track, side)
int track, side;
{
printf("\n\007** Track-read error track %d ,side %d \n", track + 1, side + 1);
printf("CR/SP retry, ESC aborts, other go to sector_read: ");
fflush(stdout);
switch ((char) Cnecin()) {
case ' ':
case '\r':
return 1;
case 0x1b:
longjmp(start, USER_ABORT);
default:
return 0;
}
}
verify_disk(drive, side)
int drive, side;
{
char *ptr, *map;
int t, n;
if(multipass)
map = full_track_map;
else
map = track_map;
ptr = buffer_data;
for (t = 0; t < TRACK_MAP_SIZE; t++) {
if (map[t]) {
for (n = side; n < (side + sides); n++) {
if (Floprd(ptr, 0L, drive, 1, t, n, st))
while (retry("Verify", t, n, start_dest) &&
Floprd(ptr, 0L, drive, 1, t, n, st));
abort_on_key(t,n);
}
Crawio((int) 'v');
}
}
}
write_disk(drive, side)
int drive, side;
{
char *ptr;
int t, n, last_track;
ptr = buf;
if(zero_disk){ /* formatting is a special case */
last_track = 2;
}else{
last_track = TRACK_MAP_SIZE;
}
for (t = 0; t < last_track; t++) {
if (track_map[t]) {
for (n = side; n < (side + sides); n++) {
if (Flopwr(ptr, 0L, drive, 1, t, n, st))
while (retry("Write", t, n, start_dest) &&
Flopwr(ptr, 0L, drive, 1, t, n, st));
ptr += (long) bps *st;
abort_on_key(-1,n);
}
Crawio((int) '.');
}
}
}
read_disk(drive, side)
int drive, side;
{
char *ptr = buf, c;
int t, n;
int full_track_retry;
/* we need at least room for 1 track! */
if(buffer_size < (sides * bps * st * 1L)) longjmp(start, NO_MEMORY);
for (t = 0; t < TRACK_MAP_SIZE; t++) {
if (track_map[t]) {
c = ',';
for (n = side; n < (side + sides); n++) {
if (Floprd(ptr, 0L, drive, 1, t, n, st)) {
c = ';';
full_track_retry = 1;
while(1) {
abort_on_key(-1,n);
if (!Floprd(ptr, 0L, drive, 1, t, n, st))
goto good_retry;
full_track_retry++;
if (full_track_retry >= TRACK_RETRY) {
if (interactive && retry_track(t, n)) {
full_track_retry = 1;
}else{
break;
}
}
}
/* 4 retries done */
if (1 == sector_read(ptr, 0L, drive, 1, t, n, st)) {
if (interactive) {
while (retry("Read", t, n, 0L) &&
(1 == sector_read(ptr, 0L, drive, 1, t, n, st)));
}
}
}
good_retry:
ptr += (long) (bps * st);
abort_on_key(-1,n);
}
Crawio((int) c);
}
}
}
input_track_map()
{
char text[10];
int i, strack, etrack;
if(play_it_again_sam) {
bcopy(full_track_map, track_map, TRACK_MAP_SIZE);
return;
}
for (i = 0; i < TRACK_MAP_SIZE; i++)
track_map[i] = '\0';
while ((printf("Enter start track (CR = done): "),
gets(text), (int) text[0])) {
strack = atoi(text) - 1;
printf("Enter end track (CR = %d): ", strack + 1);
gets(text);
if (!text[0])
etrack = strack;
else
etrack = atoi(text) - 1;
if ((etrack > TRACK_MAP_SIZE) ||
(strack > etrack) ||
(strack < 0)) {
printf("Sorry, not a valid entry: %d...%d\n",
strack + 1, etrack + 1);
} else {
for (i = strack; i <= etrack; i++)
track_map[i] = '\001';
printf("Ok, range %d...%d will be done\n",
strack + 1, etrack + 1);
}
}
}
/*
* prompt_for_disk:
* ask user to insert disk if we think it is not in drive
*/
prompt_for_disk(disk, drive, side)
int disk, drive,side;
{
if(drives_content[drive] != disk){
printf("\nInsert %s disk in drive %c (side %d),",
(disk == SOURCE_DISK ? "SOURCE" : "DESTINATION"),
(char)(drive + 'A'), side + 1);
printf("CR/SP = ok, other = abort\n");
if (!index("\r\n ", (char) Cnecin())){
if(disk == SOURCE_DISK)
one_valid_copy_done = 0;
longjmp(start, USER_ABORT);
}else{
drives_content[drive] = disk;
}
}
}
/*
* update_checksum:
* compute checksum of boot buffer and set it (last int of 256 ints)
*/
update_checksum(block, is_boot_non_executable)
unsigned block[];
unsigned is_boot_non_executable;
{
int i; unsigned sum = 0;
for(i=0; i<255; i++)
sum += block[i];
block[255] = (unsigned) 0x1234 - sum + is_boot_non_executable;
}
unsigned
is_non_executable(block)
unsigned block[];
{
int i; unsigned sum = 0;
for(i=0; i<=255; i++)
sum += block[i];
return (sum == (unsigned) 0x1234 ? (unsigned) 0 : (unsigned) 1);
}
@\Rogue\Monster\
else
echo "shar: Will not over write FLIP.C"
fi
echo "Finished archive 1 of 2"
# to concatenate archives, remove anything after this line
exit 0