TIP: Click on subject to list as thread! ANSI
echo: aust_c_here
to: Frank Adam
from: Paul Edwards
date: 1996-10-18 05:56:12
subject: Fat

PE> No, I'll beat you to getting Tobruk working on the Amiga 
PE> though (with messagebase capabilities).
FA> Most likely:) 
FA> I don't even know what Tobruk does, is, 

It's a mailprocessor.  Just like squish.  Remember I was recommending
Binkley/Squish/Msged?  Well I use Binkley/Tobruk/Msged.

FA> and why it's called Tobruk ??
FA> Didn't we lose a battle there once ? :)

Not unless you're German.  First time in WWII the Germans were unable to
take a place.

PE> A simple "Released to the Public Domain" is all you need, 
FA> Yes boss, i'll do so in future, it just seems a bit strange for a simple
FA> thing like that.

Several hours of work is not something simple.  It's something worth $160
at standard contract rates ($40/hour).  If I can get a $160 
program for free, I am happy.

FA> I really hate that,i should've declared it "void ShowMedia( void )" 
FA> I always thought void func() would assume void for parameters, but it 
FA> keeps happening of late so i guess not.

Actually void func() is sort of equivalent to void func(...), ie a variable
number (possibly 0) of parameters, of unknown type. You definitely don't
want that!

FA> I will repost it on the weekend or early next week as a reader/saver 

I'll post the one I've currently got ready to go in OZPD...

/* 
   ** 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.
   ** Compile in large memory model.
 */

#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;
    int i;
    
    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 (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(void)                /* 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)

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™.