<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Fri, 02 Jun 2000 12:35:24 +0100
From   : Tom Lees <tal26@...>
Subject: Re: Wave level tape encoding & adfs disk format

On Fri, Jun 02, 2000 at 04:02:27AM -0700, Thomas Harte wrote:
> The next targets for my emulator are to properly support tape files and
> possibly loading over the soundcard, and to finish the dfs2adfs (it actually
> does more than that, but no matter) converter such that all the bodged
> 'Electron' games on the 'net are loadable.
[...]

> As for the ADFS, I have checked every file on the BBC Documentation source
> which says 'disk' or 'dfs' anywhere in the title, but to no avail. The
> regulr DFS and Watford DFS62 formats are documented in a file principly
> about the Watford DFS62, but that is all I have found. Does anyone happen to
> know of a less obviously titled document, possibly on another topic, which
> happens to mention the format? I'm talking about at the level of what the
> Electron or BBC sees, I'm not so interested in the low level disk formatting
> and so on. Which is a shame because I have that information!
> 
> Thanks in advance, and apologies if I am asking too much.

I can't help for tape, but here's a short C program I wrote to extract files
from an ADFS image. I got the structures from the Electron Plus 3 UG (which
is at home at the moment), but you should be able to find the appropriate
info from here:

/*
 * Utility to extract stuff from ADFS images
 */

#include <stdio.h>
#include <string.h>

typedef unsigned char byte;
typedef unsigned int dword;

int map;

#pragma pack(1)
struct threebyte
{
       byte lo, mid, hi;
};

#define DECODE_3B(x) (x.lo | (x.mid << 8) | (x.hi << 16))

struct fsmap
{
       struct threebyte addr[82];
       byte reserved[6];
       struct threebyte total_sect;
       byte checksum_sect0;
       
       struct threebyte length[82];
       byte reserved_1[5];
       byte discid[2];
       byte bootopt;
       byte end_fslist;
       byte checksum_sect1;
};

struct adfs_dir
{
       byte msn;
       byte hugo[4];
       struct entry
       {
               byte name_access[10];
               dword load;
               dword exec;
               dword len;
               struct threebyte start_sect;
               byte sequence;
       } entries[47];
       byte zero;
       byte filename[10];
       struct threebyte parent_ptr;
       byte dirtitle[19];
       byte reserved[14];
       byte msn_copy;
       byte hugo_2[4];
       byte zero_2;
};
#pragma pack()

FILE *f;
struct fsmap fsm;

void read_sectors (void *ptr, int nsectors, int first)
{
       int trk;
       int i;
       int sect;
       int lsect;
       
       if (map)
       {
               for (i = 0; i < nsectors; i++)
               {
                       trk = (first+i)/10;
                       sect = (first+i)%10;
                       if (trk & 1)
                               lsect = ((80+(trk>>1))*10)+sect;
                       else
                               lsect = ((trk>>1)*10)+sect;
                       printf ("trk%d sect%d --> lsect%d\n", trk, sect, lsect);
                       fseek (f, lsect*256, SEEK_SET);
                       fread (ptr + (i*256), 256, 1, f);
               }
       }
       else
       {
               fseek (f, first*256, SEEK_SET);
               fread (ptr, nsectors, 256, f);
       }
}

void do_dir (int sector)
{
       struct adfs_dir dir;
       char namebuf[20], namebuf2[20];
       int i, j;
       
       read_sectors (&dir, 5, sector);
       
       if (strncmp (dir.hugo, "Hugo", 4))
               printf ("Warning: first hugo mismatch\n");
       if (strncmp (dir.hugo_2, "Hugo", 4))
               printf ("Warning: second hugo mismatch\n");
       
       for (i = 0; i < 10; i++)
       {
               namebuf[i] = dir.filename[i] & 0x7f;
               if (namebuf[i] == 0xd)
                       namebuf[i] = 0;
       }
       for (i = 0; i < 19; i++)
       {
               namebuf2[i] = dir.dirtitle[i] & 0x7f;
               if (namebuf2[i] == 0xd)
                       namebuf2[i] = 0;
       }
       namebuf[19] = 0;
       
       printf ("\n%s '%s' (%d %d)\n", namebuf, namebuf2,
               dir.msn, dir.msn_copy);
       
       for (i = 0; i < 47; i++)
       {
               if (dir.entries[i].name_access[0] == 0)
                       break;
               for (j = 0; j < 10; j++)
               {
                       namebuf[j] = dir.entries[i].name_access[j] & 0x7f;
                       if (namebuf[j] == 0xd)
                               namebuf[j] = 0;
               }
               namebuf[10] = 0;
               printf ("%.10s             %c %c %c %c     %08x %08x %d\n",
                       namebuf,
                       dir.entries[i].name_access[0] & 0x80 ? 'R' : 'r',
                       dir.entries[i].name_access[1] & 0x80 ? 'W' : 'w',
                       dir.entries[i].name_access[2] & 0x80 ? 'L' : 'l',
                       dir.entries[i].name_access[3] & 0x80 ? 'D' : 'd',
                       dir.entries[i].load,
                       dir.entries[i].exec,
                       dir.entries[i].len);
               if (dir.entries[i].name_access[3] & 0x80)
                       do_dir (DECODE_3B (dir.entries[i].start_sect));
       }
       printf ("\n");
}

int main(int argc, char *argv[])
{
       printf ("%d %d\n", sizeof (struct fsmap),
               sizeof (struct adfs_dir));
       
       if (argc >= 3)
               map = 1;
       else
               map = 0;
       
       f = fopen (argv[1], "r");
       fread (&fsm, sizeof (fsm), 1, f);
       
       do_dir (2);
}

/* End of file. */

-- 
Tom Lees <tal26@...      > <tom@...             > <tom@...       >
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>