TIP: Click on subject to list as thread! ANSI
echo: aust_c_here
to: Frank Adam
from: Paul Edwards
date: 1996-10-16 00:08:06
subject: Fat

FA> Hi Paul, why not write your own ??

Because I'm busy writing other things of my own, mostly that don't involve
machine-specific code!  :-)

FA> I've had this floating around for some time, and couldn't get it 
FA> working at that stage. I tried again now, must be improving :).
FA> If i get the time i'll finish and add the restore and boot read to it, 
FA> unless you want to beat me to it. ;-)

No, I'll beat you to getting Tobruk working on the Amiga though (with
messagebase capabilities).

FA> ** Fat saver.. PD by me to you or anyone who cares to use it.

A simple "Released to the Public Domain" is all you need, the
above is not straightforward.  I also ran it through indent, and then I
went to compile it with bcc 3.1...

Borland C++  Version 3.1 Copyright (c) 1992 Borland International
fat.c:
Warning fat.c 84: Suspicious pointer conversion in function GetDpb
Error fat.c 111: Expression syntax in function GetFat
Error fat.c 111: Undefined symbol 'i' in function GetFat
Error fat.c 111: Statement missing ; in function GetFat
Warning fat.c 127: 'p' is assigned a value that is never used in function GetFat
Warning fat.c 127: 'j' is declared but never used in function GetFat
Warning fat.c 127: 'startsector' is assigned a value that is never used in
function GetFat
Warning fat.c 127: Parameter 'drive' is never used in function GetFat
Warning fat.c 186: Call to function 'ShowMedia' with no prototype in function main
*** 3 errors in Compile ***

        Available memory 3788340


What did I do wrong?  BFN.  Paul.


/* 
   ** Fat saver.. Written by Frank Adam and released to the public domain.
   ** This will NOT work on an older compiler if you have a modern
   ** large drive because they (EG. TC2) seem to use the old INT25 absread()
   ** function, which can not read LBA drives. Compiled in BC4, but
   ** should port with little pain.
   ** Only one truely non portable part in this, absread(), there are 
   ** replacements for that out there, but i didn't really want to bother.
   ** Could replace it with INT25 AX=ffffh, i think.
 */

#include 
#include              /* for memcpy */
#include               /* for toupper */
#include 
#include 

#define BYTE char
#define WORD unsigned int
#define DWORD unsigned long

struct DriveParamBlock          /* from Ralph Brown's excellent Interrupt
                                   List */
{
    BYTE Driveno;               /* drive number (00h = A:, 01h = B:, etc) */
    BYTE DevUnit;               /* unit number within device driver */
    WORD Bpersec;               /* bytes per sector */
    BYTE Hysect;                /* highest sector number within a cluster */
    BYTE Shft;                  /* shift count to convert clusters into
                                   sectors */
    WORD ResSecs;               /* number of reserved sectors at beginning
                                   of drive */
    BYTE NumFats;               /* number of FATs */
    WORD NumRoot;               /* number of root directory entries */
    WORD UserFsc;               /* number of first sector containing user
                                   data */
    WORD MaxClust;              /* highest cluster number (number of data
                                   clusters + 1) */
    /* 16-bit FAT if greater than 0FF6h, else 12-bit FAT */
    WORD SecPerFat;             /* number of sectors per FAT */
    WORD DirStart;              /* sector number of first directory sector */
    DWORD DevHead;              /* address of device driver header */
    BYTE MediaId;               /* media ID byte (see #0669) */
    BYTE AccessB;               /* 00h if disk accessed, FFh if not */
    DWORD NextDbp;              /* pointer to next DPB */
    WORD NextClus;              /* cluster at which to start search for
                                   free space */
    /* when writing, usually the last cluster allocated */
    WORD FreeClus;              /* number of free clusters on drive, FFFFh
                                   = unknown */
};

struct BackupData               /* this could hold the "where to put it
                                   back" info */
{
    int drive;
    short fss;                  /* fat start sector. Always 1(i think) */
    int bps;                    /* bytes per sector 512 on my drives */
    int spf;                    /* sectors per fat 251-2 on my drives */
    short fats;                 /* number of fats  (normally 2, 0 here is
                                   not good at all:)) */
    /* the two fats are contigous and the same, so one is enough  /* to
       save, image.exe does the same.  */
}
bupdat;                         /* not yet in use */

char fname[80];
struct DriveParamBlock dpb;

int GetDpb(int drive)
{
    union REGS inregs, outregs;
    struct SREGS sregs;
    char far *p;
    inregs.h.ah = 0x32;
    inregs.h.dl = drive;        /* 0 default drv,1 = A, 2 = B, etc.. */
    intdosx(&inregs, &outregs, &sregs);
    if (outregs.x.cflag)
        return 0;
    if (outregs.h.al)
        return 0;
    p = (char far *)MK_FP((unsigned)sregs.ds, (unsigned)outregs.x.bx);
    printf("\nDBP Address = %p\n", p);
    memcpy(&dpb, p, sizeof(struct DriveParamBlock));
    return 1;
};


int GetFat(int drive)
{
    char *fat;
    int startsector = 1, j, p = 0;
    FILE *out;
    sprintf(fname, "testfat%c.dat\0", (dpb.Driveno + 'A'));

    fat = (char *)calloc(dpb.Bpersec, sizeof(unsigned char));
    if (NULL == fat)
    {
        printf("\nNot enough memory");
        return 0;
    }

    out = fopen(fname, "wb");
    if (out == NULL)
    {
        perror("\nError opening file");
        return 0;
    }

    printf("\n\n");
    for (int i = 0; i < (dpb.SecPerFat); i++)
    {
        if (absread(drive, 1, i + startsector, fat) != 0)
        {
            perror("Disk read error");
            return 0;
        }
        printf("\rSector %02d Read OK....", i);
        for (j = 0; j < dpb.Bpersec; j++)
            p += fwrite(&fat[j], 1, 1, out);
        printf("Written %03d items OK", i, p);
        p = 0;
    }
    free(fat);
    fclose(out);
    return 1;                   /* phew */
};

void ShowMedia()                /* just a bit of show off :o) */
{
    printf("\n Drive %c media type = ", toupper(dpb.Driveno + 'A'));
    switch ((int)dpb.MediaId)
    {
    case 0xfff0:
        if (dpb.SecPerFat > 4 && dpb.SecPerFat < 10)
            printf("Probably 1.44M 3.5 floppy");
        else
            printf("Unrecognized device or CD-ROM drive.");
        break;
    case 0xfff8:
        printf("Hard drive");
        break;
    case 0xfff9:
        printf("DS 1.2M 5.25 floppy");
        break;
    case 0xfffa:
        printf("HP ROM device");
        break;
    case 0xfffc:
        printf("SS 9S/T 180K floppy");
        break;
    case 0xfffd:
        printf("DS 9S/T 360K floppy");
        break;
    case 0xfffe:
        printf("SS 8S/T 160K floppy");
        break;
    case 0xffff:
        printf("DS 8S/T 320K floppy");
        break;
    default:
        printf("Unrecognized device");
        break;
    }
    printf("\nSectors per fat  = %d", dpb.SecPerFat);
    printf("\nBytes per sector = %d", dpb.Bpersec);
    printf("\nNumber of fats   = %d", dpb.NumFats);
};
/* Note: i found, a 1.4M can return 0xfff9 if disk/x-copied from a 1.2M */


int main(void)
{
    int drive = 1;              /* 
                                   **   try 'A' first, but works fine here
                                   on all my drives  **   except the
                                   CD-ROM */
    if (GetDpb(drive))
        printf("DBP Operation OK..");
    else
    {
        printf("DBP Operation Failed ! ");
        return 0;
    }

    ShowMedia();                /* looking good if we got here */
    printf("\n\nProceed with reading FAT ?");
    if (toupper(fgetc(stdin)) == 'N')
        return 0;
    if (GetFat(drive - 1) != 0)
        printf("\nFat saved OK to %s.", fname);
    return 0;
}
@EOT:

---
* Origin: X (3:711/934.9)
SEEN-BY: 633/267 270
@PATH: 711/934 808 50/99 635/544 727 728 633/267

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.