#ifndef XPKMASTER_HOOK_MEM_C
#define XPKMASTER_HOOK_MEM_C

/* Routinesheader

	Name:		hook_mem.c
	Main:		xpkmaster
	Versionstring:	$VER: hook_mem.c 1.2 (29.03.97)
	Author:		SDI
	Distribution:	PD
	Description:	Memory IO hooks

 1.0   06.10.96 : first real version
 1.1   01.01.97 : added debug info
 1.2   29.03.97 : added TOTSIZE in inhook
*/

#include <exec/types.h>
#include <pragma/exec_lib.h>
#include "xpkmaster.h"

#ifdef __MAXON__
  #define __asm
#endif

/*************************** read-from-mem hook **************************/
static LONG __asm meminfunc(register __a1 struct XpkMasterMsg *msg)
{
  STRPTR bufpos;
  LONG ofs;

  bufpos = (STRPTR) msg->xmm_Buf + msg->xmm_BufOfs;

  switch (msg->xmm_Type)
  {
  case XIO_READ:
    if(msg->xmm_BufOfs + msg->xmm_Size > msg->xmm_Len)
      return XPKERR_TRUNCATED;
    msg->xmm_BufOfs += msg->xmm_Size;
    if(!msg->xmm_Ptr)
      msg->xmm_Ptr = bufpos;
    else if(bufpos != msg->xmm_Ptr)
      CopyMem(bufpos, msg->xmm_Ptr, msg->xmm_Size);
    break;
  case XIO_SEEK:
    ofs = msg->xmm_BufOfs + msg->xmm_Size;
    if((ofs < 0) || (ofs > msg->xmm_Len))
      return XPKERR_IOERRIN;
    msg->xmm_Size = msg->xmm_BufOfs;	/* preSEEK position. */
    msg->xmm_BufOfs = ofs;
    break;
//  case XIO_ABORT:
//  case XIO_FREE:
  case XIO_TOTSIZE: return XPKERR_BADPARAMS; break; /* always needed */
  }

  return 0;
}

struct Hook meminhook = { {0}, (ULONG (*) ()) meminfunc, 0, 0};

/*************************** write-to-mem hook **************************/
static LONG __asm memoutfunc(register __a1 struct XpkMasterMsg *msg)
{
  STRPTR bufpos = (STRPTR) msg->xmm_Buf + msg->xmm_BufOfs;
  LONG ofs;

  switch (msg->xmm_Type)
  {
  case XIO_SEEK:
    ofs = msg->xmm_BufOfs + msg->xmm_Size;
    if((ofs < 0) || (ofs > msg->xmm_BufLen))
      return XPKERR_IOERROUT;
    msg->xmm_Size = msg->xmm_BufOfs;	/* preSEEK position. */
    msg->xmm_BufOfs = ofs;
    break;
  case XIO_TOTSIZE:
    if(msg->xmm_Flags & XIO_GETOUTBUF)
    {
      if(!(msg->xmm_Buf = (STRPTR) AllocMem(msg->xmm_Size, msg->xmm_MemType)))
	return XPKERR_NOMEM;
      msg->xmm_BufLen = msg->xmm_Size;
    }
    else if(!msg->xmm_Buf)
      return XPKERR_SMALLBUF;
    break;
  case XIO_GETBUF:
    if(msg->xmm_BufOfs + msg->xmm_Size > msg->xmm_BufLen)
      return XPKERR_SMALLBUF;
    msg->xmm_Ptr = bufpos;
    break;
  case XIO_WRITE:
    if(msg->xmm_BufOfs + msg->xmm_Size > msg->xmm_BufLen)
      return XPKERR_SMALLBUF;
    if(msg->xmm_Ptr && (msg->xmm_Ptr != bufpos))
      CopyMem(msg->xmm_Ptr, bufpos, msg->xmm_Size);
    msg->xmm_BufOfs += msg->xmm_Size;
    break;
  case XIO_ABORT:
    if((msg->xmm_Flags & XIO_GETOUTBUF) && msg->xmm_Buf)
    {
      FreeMem(msg->xmm_Buf, msg->xmm_BufLen);
      msg->xmm_Buf = 0;
    }
    break;
  }

  return 0;
}

struct Hook memouthook = {{0}, (ULONG (*) ()) memoutfunc,0 ,0};

#endif
