/*
** $VER: makedisk.c 1.0 (08 May 1996)
**
** memory.device-based creating of a RAM disk
**
** (C) Copyright 1996 Marius Gröger
**     All Rights Reserved
**
** $HISTORY:
**
** 08 May 1996 : 001.000 :  created
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/filehandler.h>
#include <dos/dos.h>
#include <libraries/expansion.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <clib/alib_stdio_protos.h>
#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>
#include <clib/expansion_protos.h>
#include <pragmas/expansion_pragmas.h>
#include <clib/dos_protos.h>
#include <pragmas/dos_pragmas.h>
#include "compiler.h"

#define VERSION 37
#define REVISION 1
#define DATE "08.05.96"
#define VERS "MakeDisk 37.1"
#define VSTRING "MakeDisk 37.1 (08.05.96)"
#define VERSTAG "\0$VER: MakeDisk 37.1 (08.05.96)"
const STATIC UBYTE version[]=VERSTAG;

extern FAR void *DOSBase;
struct Library *ExpansionBase;

extern void exit(LONG);

#include <string.h>

#define MYDOSTYPE ID_DOS_DISK

PRIVATE LONG parampkt[] = {
   0,           /*XXX*/ /* DOS name */
   (LONG)"memory.device",
   0,
   0,
   11,                  /* Size of Environment vector */
   0,           /*XXX*/ /* in longwords: standard value is 128 */
   0,                   /* not used; must be 0 */
   1,                   /* # of heads (surfaces). drive specific */
   1,                   /* not used; must be 1 */
   1,                   /* blocks per track. drive specific */
   1,                   /* DOS reserved blocks at start of partition. */
   0,                   /* DOS reserved blocks at end of partition */
   0,                   /* usually 0 */
   0,           /*XXX*/ /* starting cylinder. typically 0 */
   0,           /*XXX*/ /* max cylinder. drive specific */
   0,                   /* Initial # DOS of buffers.  */
   0,                   /* type of mem to allocate for buffers */
   (~0 >> 1),           /* Max number of bytes to transfer at a time */
   ~1,                  /* Address Mask to block out certain memory */
   0,                   /* Boot priority for autoboot */
   MYDOSTYPE            /* ASCII (HEX) string showing filesystem type */
};


PRIVATE ULONG strntolong(STRPTR s, LONG *number, LONG n)
{

#define IsDigit(c) ((c) >= '0' && (c) <= '9'))
#define IsXDigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F'))
#define ToUpper(c) (((c) >= 'a' && (c) <= 'f') ? ((c) & ~32) : (c))

   BOOL hex;
   UBYTE c;
   UWORD countdown;
   ULONG preconv, rc;

   if ((n > 2) && (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2)))
   {
      hex = TRUE;
      s += 2;
      n -= 2;
      preconv = 2;
   }
   else if ((n > 1) && (*s == '$'))
   {
      hex = TRUE;
      ++s;
      --n;
      preconv = 1;
   }
   else
   {
      hex = FALSE;
      preconv = 0;
   }

   if (countdown=n)
   {
      LONG num;

      for(num=0; countdown && (*s != '\0'); ++s, --countdown)
      {
         c = ToUpper((ULONG)*s);
         if (hex)
         {
            if (c >= '0' && c <= '9') num = num * 16 + c - '0';
            else if (c >= 'A' && c <= 'F') num = num * 16 + c - 'A' + 10;
            else break;
         }
         else
         {
            if (c >= '0' && c <= '9') num = num * 10 + c - '0';
            else break;
         }
      }

      if (n - countdown)
      {
         *number = num;
         rc = preconv + (n - countdown);
      }
      else rc = 0;
   }
   else rc = 0;

   return rc;
}

void SAVEDS STDARGS main(void)
{
   struct RDArgs *rda;
   struct {
      UBYTE *disk;
      UBYTE *name;
      UBYTE *blocks;
      ULONG getchip;
   } opts;
   APTR addr;
   LONG blocks, size;
   ULONG flags;
   LONG rc = RETURN_FAIL;
   PRIVATE UBYTE volname[34];
   PRIVATE UBYTE dosname[34];

   if (ExpansionBase = OpenLibrary("expansion.library", 36))
   {
      memset(&opts, 0, sizeof(opts));

      if (rda = ReadArgs("DRIVE/A,NAME/K,B=BLOCKS/K/A,C=CHIP/S", (LONG*)&opts, NULL))
      {
         strntolong(opts.blocks, &blocks, (LONG)strlen(opts.blocks));
         size = blocks * 512;

         flags = MEMF_CLEAR | MEMF_PUBLIC | (opts.getchip ? MEMF_CHIP : MEMF_ANY);

         if (addr = AllocVec(size+512, flags))
         {
            addr = (APTR)(((ULONG)addr + 511) & -512);

            parampkt[0] = (LONG)opts.disk;
            parampkt[4+DE_SIZEBLOCK] = 512 / 4;
            parampkt[4+DE_LOWCYL] = (ULONG)addr / 512;
            parampkt[4+DE_UPPERCYL] = (ULONG)((UBYTE*)addr+size-512) / 512;

            if (AddBootNode(0, ADNF_STARTPROC, MakeDosNode(parampkt), NULL))
            {
               if (opts.name)
                  strcpy(volname, opts.name);
               else
                  sprintf(volname, "$%lx", addr);
               sprintf(dosname, "%s:", opts.disk);

               if (Inhibit(dosname, DOSTRUE))
               {
                  if (Format(dosname, volname, MYDOSTYPE))
                     rc = RETURN_OK;
                  else
                     PrintFault(IoErr(), "Formatting of drive failed");

                  if (Inhibit(dosname, DOSFALSE) == DOSFALSE)
                  {
                     PrintFault(IoErr(), "Can't uninhibit drive");
                  }
                  else if (rc == RETURN_OK)
                     Printf("Drive \"%s\" added.\n", dosname);
               }
               else
                  PrintFault(IoErr(), "Can't inhibit drive");
            }
            else
            {
               PrintFault(IoErr(), "Can't add dos device");
            }
         }

         FreeArgs(rda);
      }
      else PrintFault(IoErr(), "Bad arguments");

      CloseLibrary(ExpansionBase);
   }
   else Printf("no expansion.library\n");

   exit(rc);

   return;
}
/*E*/

