#ifndef XADMASTER_TRD_C
#define XADMASTER_TRD_C

/* Programmheader

        Name:           TR-DOS.c
        Main:           xadmaster
        Versionstring:  $VER: TR-DOS.c 1.1 (28.07.2002)
        Author:         AmiS (amis@amiga.org.ru)
        Distribution:   GPL
        Description:    TR-DOS FS this is filesystem client for TR-DOS disk images.

 1.0   23.07.02 : first version
 1.1   28.07.02 : fixed some little problems (SDI)
*/

#include <proto/xadmaster.h>
#include "SDI_compiler.h"
#include "ConvertE.c"
#include "xadSPrintF.c"
#include "xadCPU.h"

#ifndef XADMASTERFILE
#define TRD_Client              FirstClient
#define NEXTCLIENT              0
#define XADMASTERVERSION        11
UBYTE version[] = "$VER: TR-DOS 1.1 (28.07.2002)" CPUTEXT " GPL by AmiS";
#endif
#define TRD_VERSION             1
#define TRD_REVISION            1

/*
struct TRD_File
{
  char Name[8];
  UBYTE Type;
  UWORD Start;
  UWORD Length;
  UBYTE Sectors;
  UBYTE FirstSector;
  UBYTE Track;
} fl[128];

struct ControlSector
{
  UBYTE Zero;
  UBYTE Reserv1[224];
  UBYTE FirstFreeSector;
  UBYTE TrackFirstFreeSector;
  UBYTE DiskType;
  UBYTE FilesCount;
  UWORD FreeSectorsCount;
  UBYTE TRDOS_ID;
  UBYTE Reserv2[2];
  UBYTE Reserv3[9];
  UBYTE Reserv4;
  UBYTE FeleteFilesCount;
  UBYTE DiskName[8];
  UBYTE Reserv5[3];
} cs;
*/

#ifdef DEBUG
#include <proto/dos.h>
#define DOSBase xadMasterBase->xmb_DOSBase
#endif

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
ASM(LONG) TRD_GetInfo(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{ CPUCHECK {
  UBYTE fl[16], cs[256];
  LONG err;

  if(ai->xai_InSize == 655360)
  {
    if(!(err = xadHookAccess(XADAC_INPUTSEEK, 256*8, NULL, ai)))
    {
      if(!(err = xadHookAccess(XADAC_READ, 256, cs, ai)))
      {
#ifdef DEBUG
  Printf("TR-DOS:\n");
  Printf("Inputfile size=%ld\n", ai->xai_InSize);
  Printf("Control Secor:\n");
  Printf("Zero = %ld\n", cs[0]);
  Printf("FirstFreeSector = %ld\n", cs[1+224]);
  Printf("TrackFirstFreeSector = %ld\n", cs[1+224+1]);
  Printf("DiskType = %ld\n", cs[1+224+1+1]);
  Printf("FilesCount = %ld\n", cs[1+224+1+1+1]);
  Printf("FreeSectorsCount = %ld\n", EndGetI16(&(cs[1+224+1+1+1+1])));
  Printf("TRDOS_ID = %ld\n", cs[1+224+1+1+1+1+2]);
#endif

        if(cs[1+224+1+1+1+1+2] == 0x10 && cs[1+224+1+1] == 0x16)
        {
          if(!(err = xadHookAccess(XADAC_INPUTSEEK, -(256*8+256), NULL, ai)))
          {
            ULONG filecount;
            struct xadFileInfo *fi;
            UWORD CheckSum;

            for(filecount=1; !err && filecount<=cs[1+224+1+1+1]; filecount++)
            {
              if(!(err = xadHookAccess(XADAC_READ, 16, fl, ai)))
              {
                if((fi = (struct xadFileInfo *)xadAllocObject(XADOBJ_FILEINFO,
                XAD_OBJPRIVINFOSIZE, 17, XAD_OBJNAMESIZE, 8+1+2+1,
                XAD_OBJCOMMENTSIZE, 10, TAG_DONE)))
                {
                  ULONG i;
                  fi->xfi_EntryNumber = filecount;
                  fi->xfi_Flags = XADFIF_NODATE|XADFIF_SEEKDATAPOS
                                  |XADFIF_EXTRACTONBUILD;
                  xadConvertDates(XAD_DATECURRENTTIME, 1, XAD_GETDATEXADDATE,
                  &fi->xfi_Date, TAG_DONE);

                  fi->xfi_Size = fi->xfi_CrunchSize = fl[13]*256+17;
                  fi->xfi_DataPos = fl[14]*256+fl[15]*16*256;

                  /* Fill Header */
                  xadCopyMem(fl, (UBYTE *)(fi->xfi_PrivateInfo), 13);
                  ((UBYTE *)(fi->xfi_PrivateInfo))[13] = 0;
                  ((UBYTE *)(fi->xfi_PrivateInfo))[14] = fl[13];
                  CheckSum=0;
                  for(i=0; i<=14; i++)
                    CheckSum += (((UBYTE *)(fi->xfi_PrivateInfo))[i] * 257) + i;
                  ((UBYTE *)(fi->xfi_PrivateInfo))[16] = CheckSum>>8;
                  ((UBYTE *)(fi->xfi_PrivateInfo))[15] = CheckSum&0x00ff;

                  SPrintF(xadMasterBase->xmb_SysBase, fi->xfi_Comment, "%ld",
                  EndGetI16(&(fl[11])));
                  SPrintF(xadMasterBase->xmb_SysBase, fi->xfi_FileName,
                  "%.8s.!%lc", fl, fl[8]);

                  err = xadAddFileEntry(fi, ai, XAD_SETINPOS, ai->xai_InPos,
                  TAG_DONE);
                }
                else err = XADERR_NOMEMORY;
              }
            }
          }
        }
        else err = XADERR_FILESYSTEM;
      }
    }
  }
  else
    err = XADERR_FILESYSTEM;

  if(err && ai->xai_FileInfo)
  {
    ai->xai_Flags |= XADAIF_FILECORRUPT;
    ai->xai_LastError = err;
    err = XADERR_OK;
  }

  return err;
}}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
ASM(LONG) TRD_UnArchive(REG(a0, struct xadArchiveInfo *ai),
REG(a6, struct xadMasterBase *xadMasterBase))
{
  LONG err;
  if(!(err = xadHookAccess(XADAC_WRITE, 17, ai->xai_CurFile->xfi_PrivateInfo, ai)))
  {
    err = xadHookAccess(XADAC_COPY, ai->xai_CurFile->xfi_Size-17, NULL, ai);
  }
  return err;
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
const struct xadClient TRD_Client =
{
  NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, TRD_VERSION, TRD_REVISION,
  0,
  XADCF_FILESYSTEM | XADCF_FREEFILEINFO,
  0,
  "TR-DOS FS",
  (BOOL (*)()) NULL,
  (LONG (*)()) TRD_GetInfo,
  (LONG (*)()) TRD_UnArchive,
  (void (*)()) NULL,
};

#endif /* XADASTER_TRD_C */
