home *** CD-ROM | disk | FTP | other *** search
- /*
- This is FastFlop, which speeds up your Atari ST's floppy disks
- Copyright (C) 1989 by Robert Fischer
-
- This program costs no money; you can redistribute it and/or modify it
- under the terms of the Lynxware General License as published by Robert
- Fischer; either version 1, 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
- Lynxware General License for more details.
-
- You should have received a copy of the Lynxware General License
- along with this program; if not, write to the author.
-
- To contact the author, call or write:
- Robert Fischer
- 80 Killdeer Road
- Hamden, CT 06517
- (203) 288-9599
- E-mail: fischer-robert@cs.yale.edu
- */
- /* FastFlop version 3.2 */
- #define VERSION "3.2"
- long _stksize = 400L;
-
- #include "stddef.h"
- #include <basepage.h>
- /* ================= Stuff from Include Files =============== */
- extern long bios();
- extern long xbios();
- extern long gemdos();
-
- #define HDV_BPB *( (func **)0x472L )
- #define HDV_RW *( (func **)0x476L )
- #define HDV_BOOT *( (func **)0x47AL )
- #define HDV_MEDIACH *( (func **)0x47EL )
-
- typedef struct os_header {
- unsigned bra; /* (0x0) branch to reset handler */
- unsigned version; /* (0x2) TOS version number */
- char *reset_handler; /* (0x4) pointer to reset handler */
- struct os_header *sysbase;/* (0x8) pointer to this block */
- char *osram_end; /* (0xc) pointer to end of os ram */
- long junk1; /* (0x10) (unused) */
- char *magic; /* (0x14) pointer to GEM mem usage block */
- long build_date; /* (0x18) system build date */
- unsigned os_config; /* (0x1c) OS configuration bits */
- unsigned tos_date; /* (0x1e) TOS system build date */
- char *root; /* (0x20) pointer to OS pool */
- unsigned *kbshift; /* (0x24) pointer to keyboard shift word */
- BASEPAGE **run; /* (0x28) pointer to current process ptr */
- } OS_HEADER;
- #define SYSBASE (*( (OS_HEADER **)0x4F2L ))
-
- #define Pterm0() gemdos(0x0)
- #define Cconout(a) gemdos(0x2,a)
- #define Cconws(a) gemdos(0x9,a)
- #define Super(a) gemdos(0x20,(LONG)(a))
- #define Ptermres(a,b) gemdos(0x31,(LONG)(a),b)
- #define Malloc(a) (char *)gemdos(0x48,(LONG)a)
-
- #define Bconin(a) bios(2,a)
-
- #define Floprd(a,b,c,d,e,f,g) (int) xbios(8,(LONG)(a),(LONG)(b),c,d,e,f,g)
- #define Flopwr(a,b,c,d,e,f,g) (int) xbios(9,(LONG)(a),(LONG)(b),c,d,e,f,g)
-
- /* ========================================================== */
- /* Constants */
-
- #define COPYRIGHT 0xbd /* circle-C copyright character */
-
- #define READ 0
- #define WRITE 1
-
- #define RW_OFFSET 2 /* # sectors passed while switching tracks */
- #define VER_OFFSET 3
-
- #define MAXSPT 10 /* physical # sectors that will fit on a track */
-
- #define CRITICAL_RETRY 0x00010000L
- #define OK 0
- #define ERROR (-1)
- #define DRIVE_NOT_READY (-2)
- #define UNKNOWN_CMD (-3)
- #define CRC_ERROR (-4)
- #define BAD_REQUEST (-5)
- #define SEEK_ERROR (-6)
- #define UNKNOWN_MEDIA (-7)
- #define SECTOR_NOT_FOUND (-8)
- #define NO_PAPER (-9)
- #define WRITE_FAULT (-10)
- #define READ_FAULT (-11)
- #define GENERAL_MISHAP (-12)
- #define WRITE_PROTECT (-13)
- #define MEDIA_CHANGE (-14)
- #define UNKNOWN_DEVICE (-15)
- #define BAD_SECTORS (-16)
- #define INSERT_DISK (-17)
- #define WRONG_DISK_DUMMY (-18)
-
- #define SAFE 0
- #define UNSURE 1
- #define CHANGED 2
-
- /* ---------------------------------------------------------- */
- typedef struct {
- LONG version; /* The composite version # for this record */
- LONG base_adr; /* Base address for this version of TOS */
- unsigned length; /* Length of floppy code */
-
- int floprd; /* Location of floprd() */
- int flopwr; /* Location of flopwr() */
- int flopver; /* Location of flopver() */
- int patch_place;/* Place to patch in jmp... */
-
- int ctrack; /* Place to find CTRACK.w */
- int flop_cmds_offbase; /* Base address for computing flop_cmds() */
- int criterr_patch; /* Place to patch the jmp to the critical error handler */
- } offset_rec;
- lfunc *flopwr_vec, *floprd_vec; /* flop + offsets->flopw, flop + offsets->floprd */
- /* ---------------------------------------------------------- */
- /* Stuff about magic ROM locations */
- #define NUM_ROMS 4 /* The # of ROM versions supported, i.e. length of loc[] */
-
- offset_rec loc[] = {
- /* Here are offsets for the first ROMs (TOS 1.0, 11-20-85) */
- 0x01000B74L, 0xfc1556L, 0x7D8 /* estimate */,
- /* 0xfc159e, 0xfc167c, 0xfc18ce, 0xfc1b90, 0xfc1b88, 0xfc1ba4, 0xfc1cd4 */
- 0x48, 0x126, 0x378, 0x63a, 0x632, 0x64e, 0x77e,
-
- /* With the introduction of the Mega ROMs, the floppy code changed to
- incorporate twisted formatting (and maybe other things, too.) The
- following offsets are for the floppy code in TOS 1.2 (Mega ROMs) and
- TOS 1.4 in RAM. The bases of the floppy code for those TOSs are:
-
- 1.2 ( 4-22-87) : FC173A
- 1.4 RAM ( 8- 8-88) : 00B95C
-
- The addresses in parentheses are the absolute positions of these
- offsets in TOS 1.4, RAM. */
-
- 0x01020E96L, 0xFC173AL, 0x7D8,
- 0x048 /* 0xB9A4 */, 0x11e /* 0xBA7A */, 0x3a8 /* 0xBD04 */,
- 0x656 /* 0xBFB2 */, 0x64e /* 0xBFAA */, 0x658 /* 0xBFB4 */,
- 0x782 /* 0xC0De */, /* This is only a guess, based on TOS 1.4 RAM */
- /* I haven't verified it. */
-
- 0x01041108L, 0xB95CL, 0x7D8,
- 0x048 /* 0xB9A4 */, 0x11e /* 0xBA7A */, 0x3a8 /* 0xBD04 */,
- 0x656 /* 0xBFB2 */, 0x64e /* 0xBFAA */, 0x658 /* 0xBFB4 */,
- 0x782 /* 0xC0De */,
-
- /* The floppy code changes with TOS 1.4, ROM. Without getting
- specific, I think that some of the mediach and error handling was
- improved. Here are the offsets for the code in TOS 1.4 in ROM, with
- the addresses again being absolute addresses for TOS 1.4, ROM. So
- far, only one version of TOS has these offsets, and here is its base
- address:
-
- 1.4, ROM (4-6-89) : FC0EF0
- */
-
- 0x01041286L, 0xFC0EF0L, 0x850 /* probably 0x842 */,
-
- /* FLOPRD_C */ 0x048, /* FC0F38 */
- /* FLOPWR_C */ 0x11A, /* FC100A */
- /* FLOPVER_C */ 0x396, /* FC1286 */
- /* PATCH_PLACE_C */ 0x628, /* FC1518 */
-
- /* CTRACK_C */ 0x620, /* FC1510 */
- /* FLOP_CMDS_OFFBASE_C */ 0x63C, /* FC152C */
- /* Critical error patch */ 0x766 /* FC1656 */
- };
-
- /* ---------------------------------------------------------- */
- extern BYTE go2tr_patch[]; /* Our patch to the OS */
- extern BYTE change_patch[]; /* Second patch to OS */
- extern BYTE cpatch_jmp[]; /* jmp command in change_patch to relocate */
- BYTE *flop; /* Buffer for floppy code */
- offset_rec *offsets; /* The offsets to use */
- /* ---------------------------------------------------------- */
- struct bpb {
- WORD recsiz,
- clsiz,
- clsizb,
- rdlen,
- fsiz,
- fatrec,
- datrec,
- numcl,
- bflags;
- };
-
-
- struct dsb{
- struct bpb b;
- WORD dntracks,
- dnsides,
- dspc,
- dspt,
- dhidden;
- char dserial[3];
- } *dsbtabp[2] = {NULL, NULL};
-
- /* ---------------------------------------------------------- */
- /* Global variables */
-
- static WORD startsect[] = {1, 1}; /* Sector to start track operation at */
- char diskbuf[1024]; /* buffer for verify and odd address calls */
- LONG (*orwabs_p)(); /* Old rwabs chain */
- LONG (*oxbios_p)(); /* Old Xbios chain */
-
- /* External variables */
-
- #define xbios_vec *( (func **)0xB8L ) /* Xbios vector */
- #define hdv_rw (* ( LONG (**)() ) 0x476L) /* rwabs chain pointer */
- #define fverify (* (WORD *) 0x444L) /* verify flag */
- #define romversion *((WORD *)(SYSBASE + 2))
- #define romdate *((WORD *)(SYSBASE + 0x1e))
- /* ---------------------------------------------------------- */
- /* Functions */
-
- extern LONG critic();
- extern VOID fastcpy();
-
- #define orwabs (*orwabs_p)
- #define mediach(a) bios(9, a)
- #define getbpb(a) bios(7, a)
- #define low8bits(x) ((x)&0xff)
-
- /* ---------------------------------------------------------- */
- LONG rwabs(rw, buf, count, recno, dev)
- WORD rw;
- LONG buf;
- WORD count, recno, dev;
- {
- register WORD dv;
- LONG ret;
-
- LONG floprw();
-
- dv = dev;
- if (dv >= 2 || buf == 0) /* let old rwabs handle */
- return orwabs(rw, buf, count, recno, dev);
-
- ret = orwabs(rw, buf, 0, 0, dev); /* try a practice read */
- if (ret != OK) return ret; /* give up if things not okay */
- if (rw > 1) rw -= 2; /* prepare for the real thing */
- return floprw(rw, buf, recno, dv, count); /* do it */
- }
- /* ------------------------------------------------------ */
- LONG floprw(rw, buf, recno, dev, count)
- WORD rw;
- LONG buf;
- WORD recno, dev, count;
- {
- int u2i();
- register struct dsb *p;
- register LONG ret;
-
- WORD track, side;
- WORD sect, cnt;
- WORD end;
- WORD sect1, cnt1;
- WORD sect2, cnt2;
- WORD ss;
- LONG bf, bf1, bf2;
- WORD oddflag;
-
- p = dsbtabp[dev];
- if (p == NULL) { /* Read the BPB if we haven't initted it yet */
- p = dsbtabp[dev] = (struct dsb *) getbpb(dev);
- }
-
- oddflag = ((buf & 1) == 1);
- if (!p->dspc)
- p->dspt = p->dspc = 9;
-
- while (count)
- {
- bf = oddflag ? (LONG) diskbuf : buf;
- track = recno / p->dspc;
- sect = recno % p->dspc;
- if (sect < p->dspt)
- side = 0;
- else
- {
- side = 1;
- sect -= p->dspt;
- }
- if (oddflag) cnt = 1;
- else if ((p->dspt - sect) < count)
- cnt = p->dspt - sect;
- else cnt = count;
-
- ++sect;
-
- /* try to write track in two pieces for efficiency */
-
- end = sect + cnt;
- ss = startsect[dev] + RW_OFFSET;
- if (ss > MAXSPT) ss -= MAXSPT;
- if (end <= ss || sect >= ss) {
- sect1 = sect; /* single piece */
- cnt1 = cnt;
- cnt2 = 0;
- bf1 = bf;
- startsect[dev] = end;
- }
- else { /* split into two pieces */
- sect1 = ss;
- cnt1 = end - sect1;
- sect2 = sect;
- cnt2 = sect1 - sect2;
- bf1 = bf + ((long)cnt2 << 9);
- bf2 = bf;
- startsect[dev] = ss;
- }
-
- do {
- if (rw)
- {
- if (bf != buf) fastcpy (buf, bf);
- ret = (*flopwr_vec)(bf1, 0L, dev, sect1, track, side, cnt1);
- if (!ret && cnt2 > 0) {
- ret = (*flopwr_vec)(bf2, 0L, dev, sect2, track, side, cnt2);
- }
-
- if ((!ret) && (fverify))
-
- { /* resplit for verify */
-
- end = sect + cnt;
- ss = startsect[dev] + VER_OFFSET;
- if (ss > MAXSPT) ss -= MAXSPT;
- if (end <= ss || sect >= ss) {
- sect1 = sect; /* single piece */
- cnt1 = cnt;
- cnt2 = 0;
- startsect[dev] = end;
- }
- else { /* split into two pieces */
- sect1 = ss;
- cnt1 = end - sect1;
- sect2 = sect;
- cnt2 = sect1 - sect2;
- startsect[dev] = ss;
- }
-
- ret = (*(lfunc *)(flop + offsets->flopver))(diskbuf, 0L, dev, sect1, track, side, cnt1);
- if (!ret && !u2i(diskbuf) && cnt2 > 0) {
- ret =
- (*(lfunc *)(flop + offsets->flopver))(diskbuf, 0L, dev, sect2, track, side, cnt2);
- }
- if (!ret && u2i(diskbuf))
- ret = BAD_SECTORS;
- }
- }
- else
- {
- ret = (*floprd_vec)(bf1, 0L, dev, sect1, track, side, cnt1);
- if (!ret && cnt2 > 0) {
- ret = (*floprd_vec)(bf2, 0L, dev, sect2, track, side, cnt2);
- }
- if (bf != buf) fastcpy(bf, buf);
- }
-
- if (ret != 0)
- ret = critic((WORD)ret, dev);
- } while (ret == CRITICAL_RETRY);
- if (ret != 0) return ret;
-
- buf += ((long)cnt << 9);
- recno += cnt;
- count -= cnt;
- }
- return OK;
- }
-
-
- /* Byte-swap the integer */
- int u2i(loc)
- char *loc;
- {
- return (low8bits(*(loc+1)) << 8) | low8bits(*loc);
- }
-
- /* ---------------------------------------------------------- */
- /* Install fast rwabs into system */
- main()
- {
- LONG flop_cmds; /* Absolute address of FLOP_CMDS inside of flop[] */
- WORD ctrack; /* Value of flop[CTRACK] */
- LONG usp;
- LONG version; /* The ROM version plus date */
- int i;
- extern LONG nxbios();
-
- static char address[] = "\
- 80 Killdeer Road\r\n\
- Hamden, CT 06517 USA\r\n\
- (203) 288-9599\r\n";
-
- Cconws("FastFlop " VERSION " Copyright \275 1989 by Robert Fischer\r\n");
- Cconws(address);
- Cconws("FastFlop comes with ABSOLUTELY NO WARRANTY.\r\n"
- "This program is Lynxware and is subject to the terms of the Lynxware\r\n"
- "General License; either version 1, or (at your option) any later version.\r\n\n"
-
- "You should have received a copy of the Lynxware General License\r\n"
- "along with this program; if not, write to the the author\r\n"
- );
-
- /* Copy the ROMs */
- usp = Super(0);
- version = SYSBASE->version;
- version <<= 16;
- version |= SYSBASE->tos_date;
- Super(usp);
-
- i = 0;
- for (; ;) {
- if (i == NUM_ROMS) {
- Cconws("\007*** FastFlop " VERSION " won't work with this ROM\r\n");
- Cconws("For help, please write or call:\r\n");
- Cconws(address);
- Cconws("DO NOT CALL ATARI!!\r\n");
- Cconws("Press any key to continue....\r\n");
- Bconin(2);
- Pterm0();
- }
- if (loc[i].version == version) {
- offsets = &loc[i];
- break;
- }
- i++;
- }
-
- flop = Malloc((LONG)offsets->length);
- if (flop == NULL) {
- Cconws("\007*** Insufficient memory\r\n");
- Cconws("Press any key to continue....\r\n");
- Bconin(2);
- Pterm0();
- }
-
- /* Patch the ROM */
- memcpy(flop, offsets->base_adr, offsets->length);
-
- /* Pull out the magic locations */
- ctrack = *(WORD *)(flop + offsets->ctrack);
- flop_cmds = (LONG)&flop[offsets->flop_cmds_offbase + flop[offsets->flop_cmds_offbase-1]];
-
-
- /* ^^^^^^^^^^^^^^^^^ First patch */
- /* Patch our go2track code */
- *((WORD *)(go2tr_patch + 0x2)) = ctrack;
- *((WORD *)(go2tr_patch + 0x1c)) = ctrack;
- *((LONG *)(go2tr_patch + 0x12)) = flop_cmds;
-
- /* Patch in a jmp to our code */
- *((WORD *)(flop + offsets->patch_place)) = 0x4EF9; /* jmp */
- *((BYTE **)(flop + offsets->patch_place + 2)) = go2tr_patch;
-
- /* Patch in jump to the critical error handler */
- *((WORD *)(flop + offsets->criterr_patch)) = 0x4EF9; /* jmp op-code */
- *((BYTE **)(flop + offsets->criterr_patch + 2)) = change_patch;
-
- /* Patch cpatch_jmp code to jump back */
- *((BYTE **)(cpatch_jmp + 2)) = (flop + offsets->criterr_patch + 10); /* 0x770, TOS 1.4 ROM */
-
- /* Set up the new vectors */
- flopwr_vec = (lfunc *)(flop + offsets->flopwr);
- floprd_vec = (lfunc *)(flop + offsets->floprd);
-
- /* Install the driver, exit */
- usp = Super(0);
- oxbios_p = xbios_vec;
- /* xbios_vec = nxbios; /* This doesn't work!!!!! */
- orwabs_p = hdv_rw;
- hdv_rw = rwabs;
- Super(usp);
-
- Ptermres(BP->p_hitpa - BP->p_lowtpa, 0); /* term & stay resident */
- }
-