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

#include "sysboot.v"
#include "noboot.v"
#include "msdos.v"
#include "msdos16.v"
#include "skip.v"
#include "killhd.v"
#include "tarboot.v"
#include "minix.v"
#include "minixhd.v"
#include "mbr.v"

unsigned char buffer[1024];

#define FS_NONE	0	/* Bootsector is complete */
#define FS_DOS	1	/* Bootsector needs 'normal' DOS FS */
#define FS_ADOS	2	/* Bootsector likes any DOS FS */
#define FS_TAR	3	/* Bootsector needs GNU-tar volume label */
#define FS_STAT	4	/* Any bootsector is checked */
#define FS_ZERO 5	/* Boot sector must be already Zapped */
#define FS_MBR  6	/* Boot sector is an MBR */

#ifndef __MSDOS__
#define X_HAS_2M20
#endif

struct bblist {
   char * name;
   char * desc;
   char * data;
   int	  size;
   int  name_type;
   int	boot_name;
   int	fstype;
   int  fsmod;
} bblocks[] = {
{ "tar",  "Bootable GNU tar volume lable",
   	   tarboot_data, tarboot_size, 0, 0, 		FS_TAR},
{ "dos12","Boot file BOOTFILE.SYS from dos floppy",
           msdos_data, msdos_size,
	   1, msdos_boot_name-msdos_start,		FS_DOS, 12},
{ "dos16","Boot file BOOTFILE.SYS from FAT16 hard disk or floppy",
           msdos16_data, msdos16_size,
	   1, msdos16_boot_name-msdos16_start,		FS_DOS, 16},
{ "none", "No OS bootblock, just display message",  
           noboot_data, noboot_size, 
	   2, noboot_boot_message-noboot_start, 	FS_ADOS},
{ "skip", "Bypasses floppy boot with message",  
           skip_data, skip_size,  
	   2, skip_mesg-skip_start,			FS_ADOS},
{ "minix","Minix floppy FS booter",           
           minix_data, minix_size, 
	   2, minix_bootfile-minix_start,		FS_ZERO},
{ "hdmin","Minix Hard disk FS booter",    
           minixhd_data, minixhd_size, 
	   2, minixhd_bootfile-minixhd_start,		FS_ZERO},
{ "killhd", "Deletes MBR from hard disk when booted",  
           killhd_data, killhd_size,  
	   2, killhd_boot_message-killhd_start, 	FS_ADOS},
#if __STDC__
{ "mbr",  "Master boot record for HD"
#if defined(mbr_Banner) || mbr_diskman || mbr_linear || mbr_mbrkey || mbr_preboot
   ", Options:"
#ifdef mbr_Banner
   " Banner"
#endif
#if mbr_diskman
   " DiskMan"
#endif
#if mbr_linear
   " LBA"
#if !mbr_useCHS
   "-Only"
#endif
#endif
#if mbr_mbrkey
   " BootKeys"
#endif
#if mbr_preboot
   " PreBoot"
#endif
#endif
	   ,             
           mbr_data,mbr_size, 
#ifdef mbr_Banner
	   2, mbr_Banner-mbr_start, 			FS_MBR},
#else
           0, 0, 					FS_MBR},
#endif
#else
{ "mbr",  "Master boot record for HD",
	   mbr_data,mbr_size, 0, 0,                     FS_MBR},
#endif
{ "stat", "Display dosfs superblock",                          
           0, 0, 0, 0, 					FS_STAT},
{ "copy", "Copy boot block to makeboot.sav or named file",                   
           0, 0, 0, 0, 					FS_STAT},
{ "Zap",  "Clear boot block to NULs",                       
           0, 1024, 0, 0, 				FS_NONE},
   0
};

char * progname = "";

int disktype = 0;
FILE * diskfd;

int disk_sect = 63;	/* These are initilised to the maximums */
int disk_head = 256;	/* Set to the correct values when an MSDOS disk is */
int disk_trck = 256;	/* successfully identified */

int force = 0;
int write_zero = 1;	/* Write sector 0 */
int write_one = 0;	/* Write sector 1 */
int bs_offset = 0;	/* Offset of _real_ bootsector for 2m floppies */

char * boot_id = 0;

main(argc, argv)
int argc;
char ** argv;
{
   FILE * fd;
   struct bblist *ptr;
   int i;

   progname = argv[0];

   if( argc == 4 && strcmp(argv[1], "-f") == 0 )
   {
      argv++; argc--; force++;
   }
   if( argc != 3 ) Usage();

   boot_id = strchr(argv[1], '=');
   if( boot_id )
      *boot_id++ = '\0';

   if( (i=strlen(argv[1])) < 2 ) Usage();
   for(ptr = bblocks; ptr->name; ptr++)
      if( strncmp(argv[1], ptr->name, i) == 0 ) break;
   if( ptr->name == 0 ) Usage();

   open_disk(argv[2]);
   if( read_sector(0, buffer) != 0 )
      exit(1);
   read_sector(1, buffer+512);

   write_zero = (ptr->size >= 512);
   write_one =  (ptr->size >= 1024);

   switch(ptr->fstype)
   {
   case FS_NONE:	/* override */
   case FS_STAT:
   case FS_ADOS:
      break;
   case FS_DOS:
      check_msdos();
      if(ptr->fsmod) check_simpledos(ptr->fsmod);
      break;
   case FS_TAR:
      check_tar();
      break;
   case FS_ZERO:
      check_zapped();
      break;
   case FS_MBR:
      check_mbr();
      break;

   default:
      fprintf(stderr, "Program error, unknown filesystem requirement\n");
      exit(2);
   }

   switch(ptr->fstype)
   {
   case FS_STAT:
      if( strcmp(ptr->name, "copy") == 0 )
         save_super(buffer);
      else
         print_super(buffer);
      close_disk();
      exit(0);
   case FS_DOS:
   case FS_ADOS:
      for(i=0; i<sysboot_dosfs_stat; i++)
         buffer[i] = ptr->data[i];
      for(i=sysboot_codestart; i<512; i++)
         buffer[i] = ptr->data[i];
      break;

   case FS_TAR:
      copy_tarblock();
      break;

   case FS_MBR:
      copy_mbr(ptr->data);
      break;

   case FS_ZERO:
   case FS_NONE:
      if( ptr->data )
	 memcpy(buffer, ptr->data, ptr->size);
      else
      {
	 memset(buffer, '\0', 1024);
	 write_one = 1;
      }
      break;
   }

   if( boot_id ) switch(ptr->name_type)
   {
   case 1:
      set_dosname(ptr->boot_name);
      break;
   case 2:
      set_asciz(ptr->boot_name);
      break;
   default:
      fprintf(stderr, "Cannot specify boot name for this block\n");
      exit(1);
   }

   if( bs_offset )
   {
      if( write_zero ) do_2m_write();
      /* Don't write 1 ever! */
   }
   else
   {
      if( write_zero ) write_sector(0, buffer);
      if( write_one )  write_sector(1, buffer+512);
   }
   close_disk();
   exit(0);
}

Usage()
{
   struct bblist *ptr = bblocks;

   if( progname == 0 || *progname == 0 || progname[1] == 0 )
      progname = "makeboot";

#ifdef __MSDOS__
   fprintf(stderr, "Usage: %s [-f] bootblock[=bootname] a:\n\n", progname);
   fprintf(stderr, "The 'a:' can be any drive or file or @: for the MBR.\n");
#else
   fprintf(stderr, "Usage: %s [-f] bootblock[=bootname] /dev/fd0\n\n", progname);
#endif
   fprintf(stderr, "The bootname is a filename or message to use with the block,\n");
   fprintf(stderr, "the blocks are:\n");
   for(;ptr->name; ptr++)
       fprintf(stderr, "\t%s\t%s\n", ptr->name, ptr->desc);
   exit(1);
}

/**************************************************************************/

int
open_disk(diskname)
char * diskname;
{
#ifdef __MSDOS__
   /* Freedos fix */
   if( diskname[2] == '\r' ) diskname[2] = 0;

   if( diskname[2] == 0 && diskname[1] == ':' )
   {
      if (isalpha(diskname[0])) {
	 disktype = toupper(diskname[0])-'A'+1;
	 return 0;
      }
      if (diskname[0] =='@') {
	 disktype = 129;
	 return 0;
      }
   }
#endif
   disktype = 0;
   diskfd = fopen(diskname, "r+b");
   if( diskfd == 0 ) diskfd = fopen(diskname, "rb");
   if( diskfd == 0 && force ) diskfd = fopen(diskname, "w+b");
   if( diskfd == 0 )
   {
      fprintf(stderr, "Cannot open '%s'\n", diskname);
      exit(1);
   }
   return 0;
}

close_disk()
{
   if( diskfd && disktype == 0 ) fclose(diskfd);
   diskfd = 0;
   disktype = 0;
}

int
write_sector(sectno, loadaddr)
int sectno;
char * loadaddr;
{
#ifdef __MSDOS__
   if( disktype == 1 || disktype == 2 || disktype == 129 )
   {
      int tries, rv;
      int s,h,c;
      s = sectno%disk_sect + 1;
      h = sectno/disk_sect%disk_head;
      c = sectno/disk_sect/disk_head;

      for(tries=0; tries<6; tries++)
         if( (rv = bios_sect_write(disktype-1, c, h, s, loadaddr)) == 0 )
            break;
      if( rv )
      {
	 if (rv/256 == 3)
	    fprintf(stderr, "Write protect error writing sector %d\n", sectno);
	 else
	    fprintf(stderr, "Error writing sector %d, (%d)\n", sectno, rv/256);
	 return -1;
      }
      return 0;
   }
   if( disktype )
   {
      int tries, rv;

      for(tries=0; tries<6; tries++)
         if( (rv = dos_sect_write(disktype-1, sectno, loadaddr)) == 0 )
            break;
      if( rv )
      {
         fprintf(stderr, "Error writing sector %d, (0x%04d)\n", sectno, rv);
         memset(loadaddr, '\0', 512);
	 return -1;
      }
      return 0;
   }
#endif
   if( disktype )
   {
      fprintf(stderr, "Cannot write sector %d\n", sectno);
      return -1;
   }
   fseek(diskfd, (long)sectno*512, 0);
   if( fwrite(loadaddr, 512, 1, diskfd) != 1 )
   {
      fprintf(stderr, "Cannot write sector %d\n", sectno);
      return -1;
   }
   printf("Wrote sector %d\n", sectno);
   return 0;
}

int
read_sector(sectno, loadaddr)
int sectno;
char * loadaddr;
{
   int cc;
#ifdef __MSDOS__
   if( disktype == 1 || disktype == 2 || disktype == 129 )
   {
      int tries, rv;
      int s,h,c;
      s = sectno%disk_sect + 1;
      h = sectno/disk_sect%disk_head;
      c = sectno/disk_sect/disk_head;

      for(tries=0; tries<6; tries++)
         if( (rv = bios_sect_read(disktype-1, c, h, s, loadaddr)) == 0 )
            break;
      if( rv )
      {
         fprintf(stderr, "Error reading sector %d, (%d)\n", sectno, rv/256);
         memset(loadaddr, '\0', 512);
	 return -1;
      }
      return 0;
   }
   if( disktype )
   {
      int tries, rv;

      for(tries=0; tries<6; tries++)
         if( (rv = dos_sect_read(disktype-1, sectno, loadaddr)) == 0 )
            break;
      if( rv )
      {
         fprintf(stderr, "Error reading sector %d, (0x%04d)\n", sectno, rv);
         memset(loadaddr, '\0', 512);
	 return -1;
      }
      return 0;
   }
#endif
   if( disktype )
   {
      fprintf(stderr, "Cannot read sector %d\n", sectno);
      return -1;
   }
   fseek(diskfd, (long)sectno*512, 0);
   if( (cc=fread(loadaddr, 1, 512, diskfd)) != 512 )
   {
      fprintf(stderr, "Cannot read sector %d, clearing\n", sectno);
      if(cc<0) cc=0;
      memset(loadaddr+cc, '\0', 512-cc);
   }
   return 0;
}

/**************************************************************************/

#ifdef __MSDOS__
bios_sect_read(drv, track, head, sector, loadaddr)
{
#asm
  push	bp
  mov	bp,sp

  push	ds
  pop	es

  mov	dh,[bp+2+_bios_sect_read.head]
  mov	dl,[bp+2+_bios_sect_read.drv]
  mov	cl,[bp+2+_bios_sect_read.sector]
  mov	ch,[bp+2+_bios_sect_read.track]

  mov	bx,[bp+2+_bios_sect_read.loadaddr]

  mov	ax,#$0201
  int	$13
  jc	bios_read_err
  mov	ax,#0
bios_read_err:

  pop	bp
#endasm
}

bios_sect_write(drv, track, head, sector, loadaddr)
{
#asm
  push	bp
  mov	bp,sp

  push	ds
  pop	es

  mov	dh,[bp+2+_bios_sect_write.head]
  mov	dl,[bp+2+_bios_sect_write.drv]
  mov	cl,[bp+2+_bios_sect_write.sector]
  mov	ch,[bp+2+_bios_sect_write.track]

  mov	bx,[bp+2+_bios_sect_write.loadaddr]

  mov	ax,#$0301
  int	$13
  jc	bios_write_err
  mov	ax,#0
bios_write_err:

  pop	bp
#endasm
}
#endif

/**************************************************************************/

#ifdef __MSDOS__

/* All this mess just to read one sector!! */

struct disk_packet {
   long	sector;
   int	count;
   long	addr;
} disk_packet;

dos_sect_read(drv, sector, loadaddr)
{
#asm
  push	bp
  mov	bp,sp

  mov	al,[bp+2+_dos_sect_read.drv]
  mov	cx,#1
  mov	dx,[bp+2+_dos_sect_read.sector]
  mov	bx,[bp+2+_dos_sect_read.loadaddr]

  int	$25
  pop	bx
  jnc	dos_read_ok

  mov	bp,sp

  ! Fill the disk packet
  mov	ax,[bp+2+_dos_sect_read.sector]
  mov	[_disk_packet],ax
  xor	ax,ax
  mov	[_disk_packet+2],ax
  inc	ax
  mov	[_disk_packet+4],ax
  mov	ax,[bp+2+_dos_sect_read.loadaddr]
  mov	[_disk_packet+6],ax
  mov	ax,ds
  mov	[_disk_packet+8],ax

  mov	dl,[bp+2+_dos_sect_read.drv]
  inc	dl
  mov	bx,#_disk_packet
  mov	cx,#0xFFFF
  mov	si,#0
  mov	ax,#0x7305

  int	$21

  jc	dos_read_err
dos_read_ok:
  mov	ax,#0
dos_read_err:

  pop	bp
#endasm
}

dos_sect_write(drv, sector, loadaddr)
{
#asm
  push	bp
  mov	bp,sp

  mov	al,[bp+2+_dos_sect_write.drv]
  mov	cx,#1
  mov	dx,[bp+2+_dos_sect_write.sector]
  mov	bx,[bp+2+_dos_sect_write.loadaddr]

  int	$26
  pop	bx
  jnc	dos_write_ok

  mov	bp,sp

  ! Fill the disk packet
  mov	ax,[bp+2+_dos_sect_write.sector]
  mov	[_disk_packet],ax
  xor	ax,ax
  mov	[_disk_packet+2],ax
  inc	ax
  mov	[_disk_packet+4],ax
  mov	ax,[bp+2+_dos_sect_write.loadaddr]
  mov	[_disk_packet+6],ax
  mov	ax,ds
  mov	[_disk_packet+8],ax

  mov	dl,[bp+2+_dos_sect_write.drv]
  inc	dl
  mov	bx,#_disk_packet
  mov	cx,#0xFFFF
  mov	si,#1
  mov	ax,#0x7305

  int	$21

  jc	dos_write_err
dos_write_ok:
  mov	ax,#0
dos_write_err:

  pop	bp
#endasm
}
#endif
/**************************************************************************/

check_zapped()
{
   int i;
   for(i=0; i<512; i++)
      if( buffer[i] )
         break;

   if( i != 512 )
   {
      fprintf(stderr, "Boot block isn't empty, zap it first\n");
      if(!force) exit(1);
   }
}

/**************************************************************************/

struct tar_head {
   char name[100];
   char mode[8];
   char uid[8];
   char gid[8];
   char size[12];
   char mtime[12];
   char chksum[8];
   char linkflag;
   char linkname[100];
   char magic[8];
   char uname[32];
   char gname[32];
   char devmajor[8];
   char devminor[8];
   char padding[167];
} ;

#define buff_tar	(*(struct tar_head*) buffer)
#define boot_tar	(*(struct tar_head*) tarboot_data)

unsigned int oct(s)
char *s;
{
   unsigned int val = 0;
   int i;
   for(i=0; i<8; i++) if( s[i] >= '0' && s[i] <= '7' )
      val = (val<<3) + s[i] - '0';
   return val;
}

check_tar()
{
   char vbuf[100];
   unsigned char *p;
   unsigned int csum = 0;
   long osum = -1;

   for(p=buffer; p<buffer+512; p++)
      if( *p ) goto not_zapped;
   /* Block zapped, ok */
   return 0;
not_zapped:

   osum = oct(buff_tar.chksum);
   memset(buff_tar.chksum, ' ', sizeof(buff_tar.chksum));

   for(p=buffer; p<buffer+512; p++)
      csum += (*p & 0xFF);

   if( csum != osum )
   {
      fprintf(stderr, "TAR file checksum failed, this isn't a tar file.\n");
      if(!force) exit(9);

      write_one = 1;
      memset(buffer, '\0', 1024);
   }
   if( buff_tar.linkflag != 'V' )
   {
      fprintf(stderr, "Tar file doesn't start with a volume label\n");
      if(!force) exit(8);
   }

   strcpy(vbuf, boot_tar.name); strcat(vbuf, " Volume 1");
   if( strcmp(boot_tar.name, buff_tar.name) != 0 
    && strcmp(vbuf, buff_tar.name) != 0 )
   {
      fprintf(stderr, "WARNING: Volume is labeled as '%s' not '%s'\n",
                       buff_tar.name, boot_tar.name);
   }
   return 0;
}

copy_tarblock()
{
   char lbuf[20];
   unsigned char * p;
   unsigned int csum = 0;
   int i;

   struct tar_head temp;

   temp = boot_tar;

   /* Copy preserved fields
    */
   if( buff_tar.name[0] )
   {
      memcpy(temp.mtime, buff_tar.mtime, sizeof(temp.mtime));

      memset(temp.name, 0x90, 16);
      for(i=0; buff_tar.name[i] && buff_tar.name[i] != ' ' && i<14; i++)
      {
         int ch = buff_tar.name[i];
         if( islower(ch) ) ch = toupper(ch);
         if( strchr("/?@ABCDEFGHIJKLMNO", ch) == 0 )
            ch = '?';
         temp.name[i] = ch;
      }
      temp.name[i++] = 0;
      temp.name[i]   = 0xC0;
   }
   else
      sprintf(temp.mtime, "%11lo", time((void*)0));

   buff_tar = temp;

   /* Re-calculate the checksum */
   memset(buff_tar.chksum, ' ', sizeof(buff_tar.chksum));

   for(p=buffer; p<buffer+512; p++)
      csum += (*p & 0xFF);

   sprintf(buff_tar.chksum, "%7o", csum);

   printf("Boot block installed");
   if( ((struct tar_head*)buffer)[1].name[0] )
      printf(" to boot file '%s'\n",
         ((struct tar_head*)buffer)[1].name);
   else
      printf(", use 'tar -r' to add executable\n");
}

/**************************************************************************/

#define DOS_SYSID	0
#define DOS_SECT	1
#define DOS_CLUST	2
#define DOS_RESV	3
#define DOS_NFAT	4
#define DOS_NROOT	5
#define DOS_MAXSECT	6
#define DOS_MEDIA	7
#define DOS_FATLEN	8
#define DOS_SPT		9
#define DOS_HEADS	10
#define DOS_HIDDEN	11

#define DOS4_MAXSECT	12
#define DOS4_PHY_DRIVE	13
#define DOS4_SERIAL	14
#define DOS4_LABEL	15
#define DOS4_FATTYPE	16

#define DOS7_MAXSECT	17
#define DOS7_FAT32LEN	18
#define DOS7_FLAGS	19
#define DOS7_VERSION	20
#define DOS7_ROOT_CLUST	21
#define DOS7_INFO_SECT	22
#define DOS7_BOOT2	23

struct bootfields {
   int offset;
   int length;
   unsigned value;
   long lvalue;
}
   dosflds[] =
{
   { 0x03, 8, 0},
   { 0x0B, 2, 0},
   { 0x0D, 1, 0},
   { 0x0E, 2, 0},
   { 0x10, 1, 0},
   { 0x11, 2, 0},
   { 0x13, 2, 0},
   { 0x15, 1, 0},
   { 0x16, 2, 0},
   { 0x18, 2, 0},
   { 0x1A, 2, 0},
   { 0x1C, 4, 0},

   { 0x20, 4, 0},	/* DOS4+ */
   { 0x24, 1, 0},
   { 0x27, 4, 0},
   { 0x2B, 11, 0},
   { 0x36, 8, 0},

   { 0x20, 4, 0},	/* DOS7 FAT32 */
   { 0x24, 4, 0},
   { 0x28, 2, 0},
   { 0x2A, 2, 0},
   { 0x2C, 4, 0},
   { 0x30, 2, 0},
   { 0x32, 2, 0},

   { 0x40, 1, 0},
   { 0x43, 4, 0},
   { 0x47, 11, 0},
   { 0x52, 8, 0},

   { 0x3e8, 4, 0},
   { 0x3ec, 4, 0},

   { -1,0,0}
};

print_super(bootsect)
char * bootsect;
{
static char * fieldnames[] = {
   "System ID",
   "Sector size",
   "Cluster size",
   "Reserved sectors",
   "FAT count",
   "Root dir entries",
   "Sector count",
   "Media code",
   "FAT length",
   "Sect/Track",
   "Heads",
   "Hidden sectors (Partition offset)",

   "Large Filesystem sector count",
   "Phys drive",
   "Serial number",
   "Disk Label (DOS 4+)",
   "FAT type",

   "Large Filesystem sector count",
   "FAT32 FAT length",
   "FAT32 Flags",
   "FAT32 version",
   "FAT32 Root Cluster",
   "FAT32 Info Sector",
   "FAT32 Backup Boot",

   "FAT32 Phys Drive",
   "FAT32 Serial number",
   "FAT32 Disk Label",
   "FAT32 FAT Type",

   "FAT32 Free clusters",
   "FAT32 Next free cluster",

   0
};
   int i;
   long numclust = 0xFFFF;
   int fatbits = 0;
   int fat_len = -1;

   for(i=0; dosflds[i].offset >= 0; i++)
   {
      if( i>= DOS4_MAXSECT && (fat_len==0) != (i>=DOS7_MAXSECT) )
	 continue;

      if( dosflds[i].length <= 4 )
      {
         long v = 0; int j;
	 for(j=dosflds[i].length-1; j>=0; j--)
	 {
	    v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] ));
	 }

	 if( i==DOS_FATLEN )
	    fat_len = v;

	 if (v==0 && 
	  (i==DOS_FATLEN || i==DOS_MAXSECT || i==DOS4_MAXSECT || i==DOS_NROOT))
	    continue;

         printf("%-35s%ld\n", fieldnames[i], v);

	 if (i==DOS_SECT && v!=512 && v!=1024 && v!=2048)
	    break;
      }
      else
      {
         int ch, j;
         printf("%-35s", fieldnames[i]);
	 for(j=0; j<dosflds[i].length; j++)
	 {
	    ch = bootsect[dosflds[i].offset+j];
	    if( ch < ' ' || ch > '~' ) putchar('.');
	    else                       putchar(ch);
	 }
	 putchar('\n');
      }
   }
}

decode_super(bootsect)
char * bootsect;
{
   int i;

   for(i=0; dosflds[i].offset >= 0; i++)
   {
      if( i>= DOS4_MAXSECT && 
	    (dosflds[DOS_FATLEN].value==0) != (i>=DOS7_MAXSECT) )
      {
	 dosflds[i].lvalue = dosflds[i].value = 0;
	 continue;
      }

      if( dosflds[i].length <= 4 )
      {
         long v = 0; int j;
	 for(j=dosflds[i].length-1; j>=0; j--)
	 {
	    v = v*256 + (0xFF&( bootsect[dosflds[i].offset+j] ));
	 }
	 dosflds[i].value = v;
	 dosflds[i].lvalue = v;
      }
      else
	 dosflds[i].lvalue = dosflds[i].value = 0;
   }
}

save_super(bootsect)
char * bootsect;
{
   FILE * fd;
   char * fname = "makeboot.sav";
   if( boot_id ) fname = boot_id;

   printf("Copying boot block to '%s'\n", fname);
   fd = fopen(fname, "wb");
   fwrite(bootsect, 1024, 1, fd);
   fclose(fd);
}

/**************************************************************************/

check_msdos()
{
   decode_super(buffer);
   if( dosflds[DOS_CLUST].value == 0 )	/* MSDOS v1.0 */
      dosflds[DOS_CLUST].value = 1;

   if( dosflds[DOS_MEDIA].value < 0xF0 )
   {
      if (!force)
         fprintf(stderr, "Dos media descriptor is invalid\n");
   }
   else if( dosflds[DOS_MEDIA].value != (0xFF&buffer[512])
         && dosflds[DOS_RESV].value == 1 )
      fprintf(stderr, "Dos media descriptor check failed\n");
   else
   {
      disk_sect = dosflds[DOS_SPT].value;
      disk_head = dosflds[DOS_HEADS].value;
      if( disk_sect > 0 && disk_head > 0 )
         disk_trck = dosflds[DOS_MAXSECT].value/disk_head/disk_sect;

#ifndef __MSDOS__
      if( bs_offset == 0 &&
          memcmp(buffer+dosflds[DOS_SYSID].offset, "2M-STV0", 7) == 0)
      {
         printf("Floppy is in 2M format - reading 2nd boot block\n");
         bs_offset = dosflds[DOS_RESV].value + dosflds[DOS_FATLEN].value;
         if( read_sector(bs_offset, buffer) != 0 )
            exit(1);

         decode_super(buffer);
         if( dosflds[DOS_MEDIA].value < 0xF0 ||
                ( dosflds[DOS_MEDIA].value != (0xFF&buffer[512])
               && dosflds[DOS_RESV].value == 1 ) )
	 {
	    if( force )
	    {
               printf("Bad 2nd boot block - reloading first\n");
               if( read_sector(0, buffer) != 0 )
                  exit(1);
	    }
	    else
	    {
               printf("Bad 2nd boot block\n");
	       exit(1);
	    }
	 }
         check_msdos();
      }
#endif
      return;
   }
   if(!force) exit(2);
}

check_simpledos(bb_fatbits)
int bb_fatbits;
{
   long numclust = 0xFFFF;
   char * err = 0;
   int fatbits = 0;

   /* Work out how many real clusters there are */
   if( dosflds[DOS_MAXSECT].value + 2 > 2 )
      numclust = ( dosflds[DOS_MAXSECT].value
                   - dosflds[DOS_RESV].value
                   - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value
                   - ((dosflds[DOS_NROOT].value+15)/16)
                 ) / dosflds[DOS_CLUST].value + 2;
   else if( dosflds[DOS4_MAXSECT].value > 0 )
      numclust = ( dosflds[DOS4_MAXSECT].lvalue
                   - dosflds[DOS_RESV].value
                   - dosflds[DOS_NFAT].value * dosflds[DOS_FATLEN].value
                   - ((dosflds[DOS_NROOT].value+15)/16)
                 ) / dosflds[DOS_CLUST].value + 2;
   else
      numclust = ( dosflds[DOS7_MAXSECT].lvalue
                   - dosflds[DOS_RESV].value
                   - dosflds[DOS_NFAT].value * dosflds[DOS7_FAT32LEN].value
                 ) / dosflds[DOS_CLUST].value;

   if( memcmp(buffer+dosflds[DOS4_FATTYPE].offset, "FAT12", 5) == 0 )
      fatbits=12;
   else if( memcmp(buffer+dosflds[DOS4_FATTYPE].offset, "FAT16", 5) == 0 )
      fatbits=16;
   else
      fatbits=12+4*(numclust > 0xFF0) + 16*(numclust > 0xFFF0L);

   if( dosflds[DOS_NFAT].value > 2 )
      err = "Too many fat copies on disk";
   else if( dosflds[DOS_NROOT].value < 15 )
      err = "Root directory has unreasonable size.";
   else if( dosflds[DOS_SECT].value != 512 )
      err = "Drive sector size isn't 512 bytes sorry no-go.";
   else if( fatbits == 16 && numclust < 0xFF0 )
      err = "Weirdness, FAT16 but less than $FF0 clusters";
   else if( fatbits != bb_fatbits )
      err = "Filesystem has the wrong fat type for this bootblock.";
   else if( numclust * dosflds[DOS_CLUST].lvalue / 
	    dosflds[DOS_SPT].value > 65535 )
      err = "Boot sector untested with more than 65535 tracks";

   if( !err && bb_fatbits == 12 )
   {
      if( dosflds[DOS4_PHY_DRIVE].value != 0 )
         err = "This boot sector is only for floppies";
      else if( (0x7C00-msdos_start-512)/512 < dosflds[DOS_FATLEN].value )
         err = "The FAT is too large to load in the available space.";
      else if( dosflds[DOS_RESV].value + dosflds[DOS_FATLEN].value > 
               dosflds[DOS_SPT].value )
         err = "The bootblock needs all of fat1 on the first track.";
      else if( msdos_heads == 2 && dosflds[DOS_HEADS].value != 2 )
         err = "Drive doesn't have two heads, this is required.";
      else if( dosflds[DOS_HIDDEN].lvalue != 0 )
         err = "MSDOS floppies shouldn't have hidden sectors.";
   }
   
   if( err )
   {
      fprintf(stderr, "ERROR: %s\n\n", err);
      print_super(buffer);
      if(!force) exit(2);
   }
}

set_dosname(boot_name)
int boot_name;
{
   char dos_name[20];
   int i,j;

   strcpy(dos_name, "           ");

   for(i=0; boot_id[i] && boot_id[i] != '.' && i<16; i++)
      dos_name[i] = toupper(boot_id[i]);

   if( boot_id[i] == '.' )
   {
      for(j=8,i++; boot_id[i] && boot_id[i] != '.' && j<16; i++,j++)
         dos_name[j] = toupper(boot_id[i]);
   }

   printf("Bootfile set to '%11.11s'\n", dos_name);

   memcpy(buffer+boot_name, dos_name, 11);
}

set_asciz(boot_name)
int boot_name;
{
   int i, j;

   for(i=boot_name; buffer[i]; i++) ;
   for(           ; !buffer[i]; i++) ;
   i = i - boot_name -1;

   if( strlen(boot_id) > i )
   {
      fprintf(stderr, "Name '%s' is too long for bootblock\n");
      exit(1);
   }
   else
   {
      for(i=0,j=boot_name; boot_id[i]; i++)
      {
	 if( boot_id[i] == '\\' && boot_id[i+1] )
	 {
	    i++;
	    switch(boot_id[i])
	    {
	       case 'n': buffer[j++] = '\n'; break;
	       case 'r': buffer[j++] = '\r'; break;
	       case 'b': buffer[j++] = '\b'; break;
	       case 't': buffer[j++] = '\t'; break;
	       case 'a': buffer[j++] = '\007'; break;
	       case 'e': buffer[j++] = '\033'; break;
	       default:  buffer[j++] = boot_id[i]; break;
	    }
	 }
#ifdef __MSDOS__
	 else if(boot_id[i] == '_')   buffer[j++] = ' ';
	 else if(boot_id[i] == '^') { buffer[j++] = '\r'; buffer[j++] = '\n'; }
#endif
	 else buffer[j++] = boot_id[i];
      }
      buffer[j] = 0;
   }
}

check_mbr()
{
   int i = 0;

   if( buffer[510] == 0x55 && buffer[511] == 0xAA )
      i = 512;

   for(; i<512; i++)
      if( buffer[i] )
         break;

   /* Check for Disk Manager partition tables */
   if( buffer[252] == 0x55 && buffer[253] == 0xAA )
   {
      if( (unsigned char)mbr_data[252] != 0x55 || 
	  (unsigned char)mbr_data[253] != 0xAA )
	 i = 252;
   }

   if( i != 512 )
   {
      if(force)
         fprintf(stderr, "That doesn't look like a compatible MBR but ...\n");
      else
      {
         fprintf(stderr, "That doesn't look like a compatible MBR\n");
         exit(1);
      }
   }
}

copy_mbr(mbr_data)
char * mbr_data;
{
   if( buffer[252] != 0xAA || buffer[253] != 0x55 ||
       (unsigned char)mbr_data[252] != 0xAA || mbr_data[253] != 0x55 )
      memcpy(buffer, mbr_data, 446);
   else
      memcpy(buffer, mbr_data, 254);

   buffer[510] = 0x55;
   buffer[511] = 0xAA;
   write_zero = 1;
}

/**************************************************************************/

#ifdef HAS_2M20

char boot_sector_2m_23_82[] = {
0xe9,0x7d,0x00,0x32,0x4d,0x2d,0x53,0x54,0x56,0x30,0x34,0x00,0x02,0x01,0x01,0x00,
0x02,0xe0,0x00,0xbc,0x0e,0xfa,0x0b,0x00,0x17,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x45,0xb8,0x25,0x51,0x4e,0x4f,0x20,0x4e,0x41,
0x4d,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0x00,0x3f,
0x07,0x01,0x00,0x00,0x80,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x13,0x46,0x01,0x02,
0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,
0x13,0x40,0x03,0x07,0x81,0x04,0x04,0x8c,0x01,0x04,0x97,0x05,0x04,0xa2,0x02,0x04,
0xad,0x06,0x03,0xb3,0x03,0x04,0xbe,0x07,0x02,0x04,0x04,0x04,0x04,0x04,0x03,0x02,
0xfa,0x33,0xc0,0x8e,0xd0,0xbc,0x00,0x7c,0xb8,0xc0,0x07,0x50,0x05,0x20,0x00,0x50,
0x07,0x1f,0x33,0xf6,0x33,0xff,0xb9,0x00,0x01,0xfc,0xf3,0xa5,0x8b,0x1e,0x44,0x00,
0x8d,0x47,0x26,0x06,0x50,0xcb,0xfb,0xbe,0x1a,0x01,0xe8,0xd9,0x00,0xbb,0x78,0x00,
0x36,0xc5,0x37,0x1e,0x56,0x33,0xff,0x36,0x89,0x3f,0x36,0x8c,0x47,0x02,0xb9,0x0b,
0x00,0xf3,0xa4,0x06,0x1f,0xa0,0x18,0x00,0x88,0x45,0xf9,0x33,0xc0,0x8e,0xc0,0xbb,
0x00,0x7c,0x26,0x89,0x87,0xfe,0x01,0xb8,0x01,0x02,0x8b,0x0e,0x16,0x00,0x83,0xc1,
0x02,0x33,0xd2,0x83,0xf9,0x0a,0x72,0x1f,0x51,0xcd,0x13,0x59,0x36,0x8b,0x1e,0x13,
0x04,0x83,0xeb,0x05,0xb8,0x40,0x00,0xf7,0xe3,0x8e,0xc0,0x53,0x33,0xdb,0xb8,0x05,
0x02,0x41,0x33,0xd2,0xcd,0x13,0x5b,0x36,0x8f,0x06,0x78,0x00,0x36,0x8f,0x06,0x7a,
0x00,0x26,0x81,0x3e,0xfe,0x09,0x55,0xaa,0x75,0x60,0x36,0x89,0x1e,0x13,0x04,0x06,
0xb4,0x08,0xb3,0x00,0xb2,0x00,0xcd,0x13,0x8a,0xc3,0xb4,0x00,0x80,0xfa,0x02,0x72,
0x0c,0x50,0xb4,0x08,0xb3,0x00,0xb2,0x01,0xcd,0x13,0x58,0x8a,0xe3,0x07,0x26,0x8c,
0x06,0xfe,0x09,0x26,0xff,0x1e,0xfc,0x09,0xb8,0x01,0x02,0x33,0xd2,0x8e,0xc2,0xb9,
0x01,0x00,0xbb,0x00,0x80,0x50,0xcd,0x13,0x58,0xbb,0x00,0x7c,0x06,0x53,0x26,0x81,
0x7f,0x03,0x32,0x4d,0x75,0x04,0xb2,0x80,0xcd,0x13,0x26,0x81,0x3e,0xfe,0x7d,0x55,
0xaa,0x75,0x03,0x33,0xd2,0xcb,0x22,0xd2,0x74,0xec,0xbe,0x2f,0x01,0xe8,0x06,0x00,
0xb4,0x00,0xcd,0x16,0xcd,0x19,0x03,0x36,0x44,0x00,0xfc,0xac,0x22,0xc0,0x74,0x09,
0xb4,0x0e,0xbb,0x07,0x00,0xcd,0x10,0xeb,0xf1,0xc3,0x0d,0x0a,0x32,0x4d,0x20,0x53,
0x75,0x70,0x65,0x72,0x42,0x4f,0x4f,0x54,0x20,0x32,0x2e,0x30,0x0d,0x0a,0x00,0x0d,
0x0a,0xad,0x4e,0x6f,0x20,0x62,0x6f,0x74,0x61,0x62,0x6c,0x65,0x21,0x0d,0x0a,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x4d,0x61,0x64,0x65,0x20,0x69,0x6e,0x20,0x53,0x70,0x61,0x69,0x6e,0x00,0x55,0xaa
};

char boot_sector_2m_22_82[] = {
0xe9,0x6e,0x00,0x32,0x4d,0x2d,0x53,0x54,0x56,0x30,0x38,0x00,0x02,0x01,0x01,0x00,
0x02,0xe0,0x00,0x18,0x0e,0xfa,0x0b,0x00,0x16,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xcc,0x9b,0xe1,0xd4,0x4e,0x4f,0x20,0x4e,0x41,
0x4d,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0x00,0x04,
0x07,0x00,0x00,0x00,0x71,0x00,0x4c,0x00,0x61,0x00,0x66,0x00,0x13,0x46,0x01,0x02,
0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,
0x13,0x0b,0x28,0x03,0x01,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
0x03,0xfa,0x33,0xc0,0x8e,0xd0,0xbc,0x00,0x7c,0xb8,0xc0,0x07,0x50,0x05,0x20,0x00,
0x50,0x07,0x1f,0x33,0xf6,0x33,0xff,0xb9,0x00,0x01,0xfc,0xf3,0xa5,0x8b,0x1e,0x44,
0x00,0x8d,0x47,0x26,0x06,0x50,0xcb,0xfb,0xbe,0x1a,0x01,0xe8,0xd9,0x00,0xbb,0x78,
0x00,0x36,0xc5,0x37,0x1e,0x56,0x33,0xff,0x36,0x89,0x3f,0x36,0x8c,0x47,0x02,0xb9,
0x0b,0x00,0xf3,0xa4,0x06,0x1f,0xa0,0x18,0x00,0x88,0x45,0xf9,0x33,0xc0,0x8e,0xc0,
0xbb,0x00,0x7c,0x26,0x89,0x87,0xfe,0x01,0xb8,0x01,0x02,0x8b,0x0e,0x16,0x00,0x83,
0xc1,0x02,0x33,0xd2,0x83,0xf9,0x0a,0x72,0x1f,0x51,0xcd,0x13,0x59,0x36,0x8b,0x1e,
0x13,0x04,0x83,0xeb,0x05,0xb8,0x40,0x00,0xf7,0xe3,0x8e,0xc0,0x53,0x33,0xdb,0xb8,
0x05,0x02,0x41,0x33,0xd2,0xcd,0x13,0x5b,0x36,0x8f,0x06,0x78,0x00,0x36,0x8f,0x06,
0x7a,0x00,0x26,0x81,0x3e,0xfe,0x09,0x55,0xaa,0x75,0x60,0x36,0x89,0x1e,0x13,0x04,
0x06,0xb4,0x08,0xb3,0x00,0xb2,0x00,0xcd,0x13,0x8a,0xc3,0xb4,0x00,0x80,0xfa,0x02,
0x72,0x0c,0x50,0xb4,0x08,0xb3,0x00,0xb2,0x01,0xcd,0x13,0x58,0x8a,0xe3,0x07,0x26,
0x8c,0x06,0xfe,0x09,0x26,0xff,0x1e,0xfc,0x09,0xb8,0x01,0x02,0x33,0xd2,0x8e,0xc2,
0xb9,0x01,0x00,0xbb,0x00,0x80,0x50,0xcd,0x13,0x58,0xbb,0x00,0x7c,0x06,0x53,0x26,
0x81,0x7f,0x03,0x32,0x4d,0x75,0x04,0xb2,0x80,0xcd,0x13,0x26,0x81,0x3e,0xfe,0x7d,
0x55,0xaa,0x75,0x03,0x33,0xd2,0xcb,0x22,0xd2,0x74,0xec,0xbe,0x2f,0x01,0xe8,0x06,
0x00,0xb4,0x00,0xcd,0x16,0xcd,0x19,0x03,0x36,0x44,0x00,0xfc,0xac,0x22,0xc0,0x74,
0x09,0xb4,0x0e,0xbb,0x07,0x00,0xcd,0x10,0xeb,0xf1,0xc3,0x0d,0x0a,0x32,0x4d,0x20,
0x53,0x75,0x70,0x65,0x72,0x42,0x4f,0x4f,0x54,0x20,0x32,0x2e,0x30,0x0d,0x0a,0x00,
0x0d,0x0a,0xad,0x4e,0x6f,0x20,0x62,0x6f,0x74,0x61,0x62,0x6c,0x65,0x21,0x0d,0x0a,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x4d,0x61,0x64,0x65,0x20,0x69,0x6e,0x20,0x53,0x70,0x61,0x69,0x6e,0x00,0x55,0xaa
};


char program_2m_vsn_20[] = {
0x2b,0x00,0x43,0x00,0x32,0x30,0x32,0x4d,0x2d,0x53,0x54,0x56,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x4a,0x42,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfb,0xfc,0x9c,0x56,0x80,
0xfa,0x02,0x73,0x3d,0xe8,0x41,0x00,0x2e,0x80,0x3c,0x02,0x74,0x04,0x2e,0x80,0x3c,
0x04,0x72,0x2e,0x80,0xfc,0x02,0x72,0x29,0x80,0xfc,0x05,0x77,0x24,0x75,0x05,0xe8,
0x36,0x00,0xeb,0x1d,0xe8,0x85,0x00,0x73,0x09,0x5e,0x9d,0xf9,0xb8,0x00,0x06,0xca,
0x02,0x00,0x2e,0x80,0x7c,0x01,0x00,0x74,0x08,0x5e,0x9d,0xe8,0x3c,0x02,0xca,0x02,
0x00,0x5e,0x9d,0x2e,0xff,0x2e,0xfc,0x09,0x9c,0x53,0x8a,0xda,0xb7,0x00,0xd1,0xe3,
0x2e,0x8b,0xb7,0x00,0x00,0x5b,0x9d,0xc3,0x60,0xe8,0xec,0xff,0xb0,0x01,0x72,0x02,
0xb0,0x00,0x2e,0x88,0x44,0x01,0x61,0xc3,0x50,0xa0,0x12,0x00,0x0a,0x06,0x11,0x00,
0x58,0xc3,0x60,0x1e,0x6a,0x40,0x1f,0xb0,0x01,0x8a,0xca,0xd2,0xe0,0x84,0x06,0x3f,
0x00,0x75,0x04,0xf8,0xe8,0xef,0x05,0x8a,0xe2,0xc0,0xe4,0x04,0x0a,0xe0,0xc0,0xe0,
0x04,0x0c,0x0c,0x0a,0xc2,0xba,0xf2,0x03,0xfa,0x88,0x26,0x3f,0x00,0xee,0x83,0xc2,
0x05,0xeb,0x00,0xeb,0x00,0xec,0xfb,0xa8,0x80,0x1f,0x61,0xc3,0x60,0xe8,0x98,0xff,
0x2e,0x80,0x7c,0x02,0x01,0x2e,0xc6,0x44,0x02,0x00,0x74,0x08,0xe8,0xb3,0xff,0x75,
0x03,0x61,0xf8,0xc3,0xf8,0xe8,0x90,0xff,0x1e,0x06,0xbb,0x90,0x00,0x02,0xda,0x6a,
0x40,0x1f,0x80,0x27,0xef,0x0e,0x0e,0x1f,0x07,0x88,0x16,0x0c,0x00,0xf9,0xe8,0x29,
0x05,0xc6,0x06,0x11,0x00,0x01,0xc6,0x06,0x12,0x00,0x00,0xe8,0xa1,0x05,0xfe,0x0e,
0x11,0x00,0xe8,0x9a,0x05,0xf8,0xe8,0x7d,0x05,0xe8,0x76,0xff,0x74,0x07,0xc6,0x44,
0x02,0x01,0xf8,0xeb,0x68,0x1e,0x6a,0x40,0x1f,0xc6,0x06,0x41,0x00,0x06,0x1f,0xc6,
0x06,0x1b,0x00,0xff,0xc6,0x44,0x08,0x14,0xb9,0x03,0x00,0x51,0x83,0xf9,0x02,0xe8,
0xe8,0x04,0xc6,0x44,0x06,0x00,0xc6,0x06,0x11,0x00,0x00,0xc6,0x06,0x12,0x00,0x00,
0xc6,0x06,0x13,0x00,0x01,0xc6,0x06,0x16,0x00,0x00,0xc6,0x06,0x17,0x00,0x01,0xc6,
0x06,0x27,0x00,0x46,0x8b,0x3e,0x19,0x00,0xe8,0x7f,0x02,0x75,0x0b,0x59,0x8b,0x1e,
0x19,0x00,0xe8,0x1c,0x00,0xf8,0xeb,0x14,0x8a,0x44,0x06,0x40,0x3c,0x03,0x77,0x05,
0x88,0x44,0x06,0xeb,0xc1,0xc6,0x44,0x06,0x00,0x59,0xe2,0xaf,0xf9,0x07,0x1f,0x61,
0xc3,0x60,0xe8,0x88,0x00,0x72,0x5c,0x88,0x44,0x05,0x88,0x4c,0x03,0x8a,0x16,0x0c,
0x00,0xf9,0xe8,0xd3,0xfe,0x26,0x8a,0x47,0x16,0x88,0x44,0x17,0x26,0x8a,0x4f,0x41,
0x88,0x4c,0x04,0x26,0x8b,0x47,0x42,0x89,0x44,0x06,0x26,0x8a,0x47,0x18,0x88,0x44,
0x09,0x26,0x8b,0x7f,0x48,0x26,0x8a,0x41,0x01,0x8a,0xe0,0x22,0xc9,0x74,0x0a,0x80,
0xc4,0xbe,0xb0,0x0b,0xf6,0xe4,0x2d,0x3e,0x08,0xd0,0xe8,0x88,0x44,0x08,0xb9,0x0d,
0x00,0x26,0x8b,0x7f,0x4a,0x03,0xfb,0x8d,0x5c,0x0a,0x26,0x8a,0x05,0x88,0x07,0x43,
0x47,0xe2,0xf7,0x8a,0x44,0x06,0xc0,0xe0,0x06,0x0c,0x17,0x80,0x3c,0x02,0x77,0x0a,
0x24,0xf8,0x0c,0x05,0xa8,0x40,0x74,0x02,0x34,0x21,0x1e,0xbb,0x90,0x00,0x02,0x1e,
0x0c,0x00,0x6a,0x40,0x1f,0x80,0x27,0x08,0x08,0x07,0x1f,0x61,0xc3,0x56,0x57,0x8d,
0x7f,0x03,0xbe,0x06,0x00,0xb9,0x06,0x00,0xf3,0xa6,0xf9,0x75,0x19,0x33,0xc0,0x26,
0x8a,0x4f,0x40,0x80,0xf9,0x06,0x72,0x0d,0x26,0x8b,0x7f,0x44,0x4f,0x26,0x02,0x01,
0x83,0xff,0x3f,0x77,0xf7,0xf8,0x5f,0x5e,0xc3,0x50,0x73,0x37,0x80,0x3e,0x1f,0x00,
0x00,0x75,0x2f,0xa0,0x21,0x00,0xd0,0xe0,0xb4,0x04,0x72,0x22,0xc0,0xe0,0x02,0xb4,
0x10,0x72,0x1b,0xd0,0xe0,0xb4,0x08,0x72,0x15,0xc0,0xe0,0x02,0xb4,0x04,0x72,0x0e,
0xd0,0xe0,0xb4,0x03,0x72,0x08,0xd0,0xe0,0xb4,0x02,0x72,0x02,0xb4,0x20,0x08,0x26,
0x1f,0x00,0xf9,0x58,0xc3,0x9c,0x60,0x06,0x6a,0x40,0x07,0xbf,0x41,0x00,0xbe,0x1f,
0x00,0xb9,0x04,0x00,0xf3,0xa5,0x07,0x61,0x9d,0xc3,0x1e,0x60,0x0e,0x1f,0x88,0x16,
0x0c,0x00,0xe8,0xc3,0xfd,0x80,0x7c,0x05,0x00,0x74,0x08,0xc6,0x06,0x1f,0x00,0x40,
0xe9,0xbb,0x00,0x50,0xb4,0x00,0xa3,0x0d,0x00,0x8a,0xc5,0xd0,0xe0,0x8a,0xd6,0x80,
0xe6,0x7f,0x02,0xc6,0xf6,0x64,0x09,0x02,0xc1,0x80,0xd4,0x00,0x48,0xa3,0x0f,0x00,
0x8b,0xfb,0x5b,0x8a,0xdf,0xb7,0x00,0x8a,0x8f,0x26,0x00,0x88,0x0e,0x27,0x00,0xd0,
0xe2,0x72,0x73,0x23,0xc0,0x75,0x2c,0x80,0x7c,0x03,0x07,0x72,0x19,0x8a,0x44,0x17,
0x40,0xb9,0x01,0x00,0xe8,0x9b,0x00,0x75,0x6e,0xff,0x0e,0x0d,0x00,0xff,0x06,0x0f,
0x00,0xa1,0x0f,0x00,0xeb,0x0d,0x80,0x3e,0x27,0x00,0x4a,0x75,0x06,0x81,0xc7,0x00,
0x02,0xeb,0xe6,0x8a,0x4c,0x17,0xb5,0x00,0x3b,0xc1,0x77,0x0f,0xe8,0x5d,0x00,0xe8,
0x70,0x00,0x75,0x43,0x83,0x3e,0x0d,0x00,0x00,0x74,0x3c,0xa1,0x0f,0x00,0x8a,0x4c,
0x17,0xb5,0x00,0xd1,0xe1,0x3b,0xc1,0x77,0x1d,0xe8,0x40,0x00,0x80,0x3e,0x27,0x00,
0x4a,0x75,0x07,0xc1,0xe1,0x09,0x03,0xf9,0xeb,0x0c,0x8a,0x54,0x17,0xb6,0x00,0x2b,
0xc2,0xe8,0x3e,0x00,0x75,0x11,0x83,0x3e,0x0d,0x00,0x00,0x74,0x0a,0xa1,0x0f,0x00,
0x8b,0x0e,0x0d,0x00,0xe8,0x2b,0x00,0xf8,0xe8,0x2b,0x03,0xe8,0x17,0xff,0x61,0x8a,
0x26,0x1f,0x00,0x1f,0x22,0xe4,0x74,0x03,0xf9,0xb0,0x00,0xc3,0x2b,0xc8,0x41,0x3b,
0x0e,0x0d,0x00,0x76,0x04,0x8b,0x0e,0x0d,0x00,0x29,0x0e,0x0d,0x00,0x01,0x0e,0x0f,
0x00,0xc3,0x8b,0xd8,0x88,0x0e,0x17,0x00,0xf6,0x74,0x09,0xfe,0xc4,0x88,0x26,0x13,
0x00,0xd0,0xe8,0xa2,0x11,0x00,0xd0,0xd0,0x24,0x01,0xa2,0x12,0x00,0xa0,0x13,0x00,
0x02,0x06,0x17,0x00,0x72,0x06,0x48,0x3a,0x44,0x09,0x76,0x07,0xc6,0x06,0x1f,0x00,
0x04,0xeb,0x77,0x8a,0xc4,0x98,0xe8,0xbf,0xfc,0x74,0x18,0x8d,0x5c,0x09,0x48,0x43,
0xfe,0xc4,0x8a,0x0f,0x80,0xe9,0x02,0xb5,0x01,0xd2,0xe5,0x2a,0xc5,0x73,0xf0,0x02,
0xc5,0x86,0xe0,0xa2,0x13,0x00,0x88,0x26,0x16,0x00,0xe8,0xe8,0x01,0xb4,0x00,0x88,
0x26,0x15,0x00,0xe8,0x92,0xfc,0x75,0x09,0xa0,0x17,0x00,0x88,0x26,0x17,0x00,0xeb,
0x28,0x38,0x64,0x04,0x75,0x28,0x38,0x26,0x16,0x00,0x74,0x05,0xe8,0x31,0x00,0x72,
0x29,0x38,0x26,0x17,0x00,0x74,0x23,0xe8,0x9b,0x01,0x8a,0xc8,0xa0,0x17,0x00,0xf6,
0xf1,0x22,0xc0,0x74,0x09,0x88,0x26,0x17,0x00,0xe8,0x82,0x00,0x72,0x0c,0x80,0x3e,
0x17,0x00,0x00,0x74,0x05,0xe8,0x08,0x00,0x73,0xf4,0x80,0x3e,0x1f,0x00,0x00,0xc3,
0x50,0x80,0x3e,0x27,0x00,0x4a,0x74,0x16,0x80,0x3e,0x27,0x00,0x42,0x74,0x3b,0xe8,
0xbb,0x00,0x73,0x05,0xe8,0xdb,0x00,0x72,0x48,0xe8,0x6f,0x00,0xeb,0x43,0x80,0x3e,
0x16,0x00,0x00,0x75,0x09,0xe8,0x4d,0x01,0x38,0x06,0x17,0x00,0x73,0x14,0xe8,0x9c,
0x00,0x73,0x0f,0xc6,0x06,0x27,0x00,0x46,0xe8,0xb7,0x00,0xc6,0x06,0x27,0x00,0x4a,
0x72,0x1f,0xe8,0x46,0x00,0xe8,0xaa,0x00,0xeb,0x17,0x53,0x8a,0x1e,0x16,0x00,0xe8,
0x23,0x01,0xfe,0x0e,0x17,0x00,0x74,0x05,0x43,0x3a,0xd8,0x72,0xf5,0x5b,0xe8,0x91,
0x00,0x9c,0xfe,0x06,0x13,0x00,0xc6,0x06,0x16,0x00,0x00,0x9d,0x58,0xc3,0x50,0x22,
0xc0,0x74,0x16,0x8a,0x26,0x13,0x00,0x88,0x26,0x14,0x00,0x02,0xc4,0x48,0xa2,0x15,
0x00,0xfe,0xc0,0xe8,0x6c,0x00,0xa2,0x13,0x00,0x58,0xc3,0x50,0x53,0x51,0x56,0x8a,
0x1e,0x16,0x00,0xe8,0xdf,0x00,0x53,0xc1,0xe3,0x09,0x03,0x1e,0x19,0x00,0x8b,0xf3,
0xb9,0x00,0x01,0xe8,0x16,0x00,0xf3,0xa5,0xe8,0x11,0x00,0x5b,0xfe,0x0e,0x17,0x00,
0x74,0x05,0x43,0x3a,0xd8,0x72,0xdf,0x5e,0x59,0x5b,0x58,0xc3,0x2e,0x80,0x3e,0x27,
0x00,0x4a,0x74,0x02,0xf8,0xc3,0x87,0xf7,0x06,0x1e,0x07,0x1f,0xc3,0x50,0xa0,0x1b,
0x00,0x3a,0x06,0x0c,0x00,0x75,0x18,0xa0,0x11,0x00,0x8a,0x26,0x12,0x00,0x3b,0x06,
0x1c,0x00,0x75,0x0b,0xa0,0x1e,0x00,0x3a,0x06,0x13,0x00,0x75,0x02,0x58,0xc3,0xf9,
0x58,0xc3,0x50,0x53,0xe8,0x78,0x01,0x73,0x0f,0x80,0x3e,0x1f,0x00,0x00,0x75,0x05,
0x80,0x0e,0x1f,0x00,0x40,0xf9,0xeb,0x6a,0xe8,0x3d,0xfb,0xb0,0x02,0x74,0x0d,0x8d,
0x5c,0x0a,0x02,0x1e,0x13,0x00,0x80,0xd7,0x00,0x8a,0x47,0xff,0xa2,0x18,0x00,0x80,
0x3e,0x15,0x00,0x00,0x74,0x0b,0xe8,0x5c,0x02,0xc6,0x06,0x15,0x00,0x00,0x9c,0xeb,
0x3d,0x06,0x57,0x0e,0x07,0x8b,0x3e,0x19,0x00,0xa0,0x13,0x00,0xa2,0x14,0x00,0xa2,
0x15,0x00,0xe8,0x40,0x02,0xc6,0x06,0x15,0x00,0x00,0x5f,0x07,0x9c,0xb0,0xff,0x72,
0x0a,0x80,0x3e,0x27,0x00,0x42,0x74,0x16,0xa0,0x0c,0x00,0xa2,0x1b,0x00,0xa0,0x11,
0x00,0x8a,0x26,0x12,0x00,0xa3,0x1c,0x00,0xa0,0x13,0x00,0xa2,0x1e,0x00,0x9d,0xe8,
0x97,0xfc,0x5b,0x58,0xc3,0xe8,0xd0,0xfa,0xb0,0x01,0x74,0x18,0x53,0x51,0x8d,0x5c,
0x0a,0x02,0x1e,0x13,0x00,0x80,0xd7,0x00,0x8a,0x4f,0xff,0x80,0xe9,0x02,0xb0,0x01,
0xd2,0xe0,0x59,0x5b,0xc3,0x60,0x1e,0xbb,0x40,0x00,0x53,0x1f,0xb5,0xed,0xfa,0x2e,
0x8a,0x0e,0x0c,0x00,0xb0,0x01,0xd2,0xe0,0x84,0x47,0xff,0x74,0x04,0x38,0x2f,0x76,
0x33,0x08,0x47,0xff,0x80,0x67,0xff,0xcf,0x8a,0xc1,0xc0,0xe0,0x04,0x08,0x47,0xff,
0xc6,0x07,0xff,0xfb,0xba,0xf2,0x03,0x80,0xc1,0x04,0xb0,0x01,0xd2,0xe0,0x2e,0x0a,
0x06,0x0c,0x00,0x0c,0x0c,0xee,0xb8,0xfd,0x90,0xf8,0xcd,0x15,0x72,0x06,0xb8,0xe8,
0x03,0xe8,0x48,0x03,0x88,0x2f,0xfb,0x1f,0x61,0xc3,0x60,0xe8,0x68,0x00,0x8a,0x0e,
0x0c,0x00,0x8a,0xc1,0xc0,0xe0,0x02,0x0c,0x01,0xd2,0xe0,0x1e,0x6a,0x40,0x1f,0xfa,
0xa2,0x3f,0x00,0x80,0x26,0x3e,0x00,0x70,0x1f,0xc0,0xe0,0x04,0x0a,0xc1,0x0c,0x08,
0xba,0xf2,0x03,0xee,0xe8,0x08,0x03,0x0c,0x04,0xee,0xe8,0x1a,0x02,0xb0,0x08,0xe8,
0xc3,0x02,0xe8,0x82,0x02,0xe8,0x7f,0x02,0xe8,0x02,0x00,0x61,0xc3,0x50,0x1e,0x6a,
0x40,0x1f,0x8a,0x26,0x8b,0x00,0x1f,0xb0,0x03,0xe8,0xa9,0x02,0xb0,0xbf,0x80,0xe4,
0xc0,0x74,0x09,0xb0,0xaf,0x80,0xfc,0xc0,0x74,0x02,0xb0,0xdf,0xe8,0x96,0x02,0xb0,
0x02,0xe8,0x91,0x02,0x58,0xc3,0x60,0x1e,0xb0,0xff,0x72,0x0a,0x6a,0x00,0x1f,0xc5,
0x1e,0x78,0x00,0x8a,0x47,0x02,0x6a,0x40,0x1f,0xa2,0x40,0x00,0x1f,0x61,0xc3,0x60,
0xe8,0x87,0x00,0xe8,0xb7,0xff,0xb4,0x01,0x8a,0x0e,0x0c,0x00,0xd2,0xe4,0x1e,0x6a,
0x40,0x1f,0x84,0x26,0x3e,0x00,0x1f,0x75,0x05,0xe8,0xa6,0x00,0x72,0x69,0xbb,0x94,
0x00,0x02,0x1e,0x0c,0x00,0xa0,0x11,0x00,0x1e,0x6a,0x40,0x1f,0x08,0x26,0x3e,0x00,
0x8a,0x26,0x41,0x00,0x3a,0x07,0x88,0x07,0x1f,0x75,0x05,0x80,0xfc,0x40,0x75,0x44,
0xb0,0x0f,0xe8,0x30,0x02,0x72,0x40,0xa0,0x12,0x00,0xc0,0xe0,0x02,0x0a,0x06,0x0c,
0x00,0xe8,0x21,0x02,0xa0,0x11,0x00,0xe8,0x1b,0x02,0xe8,0x6a,0x01,0x72,0x28,0xb0,
0x08,0xe8,0x11,0x02,0x72,0x21,0xe8,0xce,0x01,0x72,0x1c,0x8a,0xe0,0xe8,0xc7,0x01,
0xf6,0xc4,0xc0,0x75,0x12,0xb0,0x0f,0x80,0x3e,0x27,0x00,0x4a,0x74,0x02,0xb0,0x01,
0x98,0xe8,0x38,0x02,0x61,0xf8,0xc3,0x61,0xf9,0xc3,0x60,0xe8,0x4a,0xf9,0x8b,0x44,
0x06,0x74,0x02,0x8a,0xc4,0x1e,0x6a,0x40,0x1f,0x8a,0x26,0x8b,0x00,0xc0,0xec,0x06,
0x3a,0xc4,0x74,0x10,0xba,0xf7,0x03,0xee,0xc0,0xe0,0x06,0x80,0x26,0x8b,0x00,0x3f,
0x08,0x06,0x8b,0x00,0x1f,0xbf,0x1f,0x00,0xb9,0x08,0x00,0x88,0x2d,0x47,0xe2,0xfb,
0x61,0xc3,0x60,0xbb,0x94,0x00,0x02,0x1e,0x0c,0x00,0x1e,0x6a,0x40,0x1f,0x88,0x3f,
0x1f,0xb9,0x02,0x00,0xb0,0x07,0xe8,0x9c,0x01,0x72,0x35,0xa0,0x12,0x00,0xc0,0xe0,
0x02,0x0a,0x06,0x0c,0x00,0xe8,0x8d,0x01,0x72,0x26,0xe8,0xda,0x00,0x72,0x21,0xb0,
0x08,0xe8,0x81,0x01,0x72,0x1a,0xe8,0x3e,0x01,0x72,0x15,0x8a,0xe0,0xe8,0x37,0x01,
0x80,0xf4,0x20,0xf6,0xc4,0xf0,0x75,0x08,0xb8,0x01,0x00,0xe8,0xae,0x01,0xeb,0x03,
0xe2,0xc2,0xf9,0x61,0xc3,0x50,0x53,0x51,0x52,0x8a,0x0e,0x18,0x00,0xb5,0x00,0xf9,
0xd2,0xd5,0xb1,0x00,0xa0,0x15,0x00,0x2a,0x06,0x14,0x00,0x40,0x98,0xf7,0xe1,0x8b,
0xd0,0x8b,0xc8,0x49,0x8c,0xc0,0xe8,0x72,0x00,0x72,0x6a,0xa0,0x27,0x00,0xe8,0xb7,
0x00,0x3c,0x4a,0xb0,0xc5,0x74,0x02,0xb0,0xe6,0xe8,0x29,0x01,0x72,0x57,0xa0,0x12,
0x00,0xc0,0xe0,0x02,0x0a,0x06,0x0c,0x00,0xe8,0x1a,0x01,0xa0,0x11,0x00,0xe8,0x14,
0x01,0xa0,0x12,0x00,0xe8,0x0e,0x01,0xa0,0x14,0x00,0xe8,0x08,0x01,0xa0,0x18,0x00,
0xe8,0x02,0x01,0xa0,0x15,0x00,0xe8,0xfc,0x00,0x8a,0x44,0x08,0xe8,0xf6,0x00,0xb0,
0x80,0xe8,0xf1,0x00,0xe8,0x40,0x00,0x9c,0xbb,0x20,0x00,0xb9,0x07,0x00,0xe8,0xa6,
0x00,0x88,0x07,0x43,0xe2,0xf8,0x9d,0x72,0x0c,0xf6,0x06,0x20,0x00,0xc0,0x75,0x05,
0x03,0xfa,0xf8,0xeb,0x01,0xf9,0x5a,0x59,0x5b,0x58,0xc3,0x52,0xbb,0x10,0x00,0xf7,
0xe3,0x03,0xc7,0x83,0xd2,0x00,0x8b,0xd8,0x8a,0xe2,0x8b,0xd1,0x03,0xd3,0x73,0x05,
0xc6,0x06,0x1f,0x00,0x09,0x5a,0xc3,0xfb,0x60,0x1e,0x6a,0x40,0x1f,0xb8,0x01,0x90,
0xf8,0xcd,0x15,0xba,0x80,0x02,0xbb,0x3e,0x00,0x72,0x0f,0x33,0xc9,0x84,0x17,0x75,
0x0f,0xe8,0xf6,0x00,0xe2,0xf7,0xfe,0xce,0x75,0xf1,0x2e,0x08,0x16,0x1f,0x00,0xf9,
0x9c,0x80,0x27,0x7f,0x9d,0x1f,0x61,0xc3,0x50,0xfa,0xe6,0x0b,0xb0,0x00,0xeb,0x00,
0xeb,0x00,0xe6,0x0c,0x8a,0xc3,0xeb,0x00,0xeb,0x00,0xe6,0x04,0x8a,0xc7,0xeb,0x00,
0xeb,0x00,0xe6,0x04,0xeb,0x00,0xeb,0x00,0x8a,0xc4,0xe6,0x81,0x8a,0xc1,0xeb,0x00,
0xeb,0x00,0xe6,0x05,0x8a,0xc5,0xeb,0x00,0xeb,0x00,0xe6,0x05,0xfb,0xb0,0x02,0xeb,
0x00,0xeb,0x00,0xe6,0x0a,0x58,0xc3,0x51,0x52,0x50,0xe8,0x72,0x00,0xba,0xf4,0x03,
0xb9,0x85,0x00,0xeb,0x00,0xeb,0x00,0xec,0x24,0xc0,0x3c,0xc0,0x74,0x1c,0xeb,0x00,
0xeb,0x00,0xe4,0x61,0x24,0x10,0x3a,0xc4,0x74,0xe9,0x8a,0xe0,0xe2,0xe5,0x58,0x5a,
0x59,0x80,0x0e,0x1f,0x00,0x80,0xb0,0x00,0xf9,0xc3,0x58,0x42,0xeb,0x00,0xeb,0x00,
0xec,0x5a,0x59,0xf8,0xc3,0x51,0x52,0x50,0xe8,0x34,0x00,0xba,0xf4,0x03,0xb9,0x85,
0x00,0xeb,0x00,0xeb,0x00,0xec,0xa8,0x80,0x75,0x1a,0xeb,0x00,0xeb,0x00,0xe4,0x61,
0x24,0x10,0x3a,0xc4,0x74,0xeb,0x8a,0xe0,0xe2,0xe7,0x58,0x5a,0x59,0x80,0x0e,0x1f,
0x00,0x80,0xf9,0xc3,0x42,0x58,0xeb,0x00,0xeb,0x00,0xee,0x5a,0x59,0xf8,0xc3,0x50,
0x51,0xb9,0x04,0x00,0xe8,0x23,0x00,0xe2,0xfb,0x59,0x58,0xc3,0x9c,0x60,0xba,0x4a,
0x42,0xf7,0xe2,0x8a,0xcc,0x8a,0xea,0x8a,0xd6,0xb6,0x00,0xe8,0x0c,0x00,0xe2,0xfb,
0x23,0xd2,0x74,0x03,0x4a,0xeb,0xf4,0x61,0x9d,0xc3,0xeb,0x00,0xeb,0x00,0xe4,0x61,
0x24,0x10,0x3a,0xc4,0x74,0xf4,0x8a,0xe0,0xc3,0x1e,0x16,0x1f,0x26,0xa2,0x2b,0x00,
0x26,0x88,0x26,0x43,0x00,0xbf,0xfc,0x09,0xbe,0x4c,0x00,0xfc,0xfa,0xa5,0xa5,0xc7,
0x44,0xfc,0x5b,0x00,0x8c,0x44,0xfe,0xfb,0x1f,0xcb,0x00,0x00,0xd9,0x09,0x55,0xaa
};
#endif

char program_2m_magic[] = {
0x2b,0x00,0x43,0x00,0x32,0x30,0x32,0x4d,0x2d,0x53,0x54,0x56,0x00,0x00,0x00,0x00
};

do_2m_write()
{
   int i;
   char * mbr;

   if( read_sector(bs_offset+1, buffer+512) != 0 )
      exit(1);

   if( memcmp(buffer+512, program_2m_magic, 16) == 0 )
   {
      /* Seems to be properly formatted already */

      write_sector(bs_offset, buffer);
      return;
   }
#ifdef HAS_2M20
   else if( disk_trck != 82 || disk_sect != 22 )
   {
      fprintf(stderr, "To be bootable a 2M disk must be 22 sectors 82 tracks or formatted with DOS 2m.\n");
      if( !force ) exit(1);
      fprintf(stderr, "But I'll try it\n");
   }
   write_sector(bs_offset, buffer);

   /* This needs to be altered to allow for the disk format description to
      be copied from the old boot sector */

   if( disk_sect == 23 ) mbr = boot_sector_2m_23_82;
   else                  mbr = boot_sector_2m_22_82;

   for(i=0; i<sysboot_dosfs_stat; i++)
      buffer[i] = mbr[i];
   for(i=sysboot_codestart; i<512; i++)
      buffer[i] = mbr[i];

   write_sector(0, buffer);

   for(i=0; i<sizeof(program_2m_vsn_20); i+=512)
   {
      write_sector(bs_offset+i/512+1, program_2m_vsn_20+i);
   }
#else
   fprintf(stderr, "To be bootable a 2M disk must be formatted with the DOS 2m driver.\n");
   exit(1);
#endif
}
