//***************************************************************************
//
// this file is (c) '94-'96 Niklas Beisert
//
// this file is part of the cubic player development kit.
// you may only use/modify/spread this file under the terms stated
// in the cubic player development kit accompanying documentation.
//
//***************************************************************************


#include <stdlib.h>
#include <string.h>
#include "binfile.h"
#include "err.h"
#include "psetting.h"

struct packdirentry
{
  char name[0x38];
  long off;
  long len;
};

static int nfiles;
static packdirentry *dir;
static sbinfile packfile;

pakbinfile::pakbinfile()
{
  file=0;
}

long pakbinfile::read(void *b, long l)
{
  if (!file)
    return 0;
  l=file->read(b, l);
  filepos+=l;
  return l;
}

long pakbinfile::write(const void *b, long l)
{
  if (!file)
    return 0;
  l=file->write(b, l);
  filepos+=l;
  filelen=file->length();
  return l;
}

long pakbinfile::seek(long p)
{
  if (!file)
    return 0;
  p=file->seek(p);
  filepos=p;
  return p;
}

long pakbinfile::chsize(long l)
{
  if (!file)
    return 0;
  l=file->seek(l);
  filepos=file->tell();
  filelen=file->length();
  return l;
}

void pakbinfile::close()
{
  if (file)
  {
    file->close();
    delete file;
  }
  file=0;
}

int pakbinfile::open(const char *name)
{
  close();

  sbinfile *sf=new sbinfile;
  if (!sf)
    return 0;
  char path[_MAX_PATH];
  strcpy(path, cfDataDir);
  strcat(path, name);
  if (!sf->open(path, sbinfile::openro))
  {
    delete sf;
    int i;
    for (i=0; i<nfiles; i++)
      if (!stricmp(name, dir[i].name))
        break;
    if (i==nfiles)
      return 0;
    abinfile *f=new abinfile;
    if (!f)
      return 0;
    if (!f->open(packfile, dir[i].off, dir[i].len))
    {
      delete f;
      return 0;
    }
    file=f;
  }
  else
    file=sf;

  mode=file->getmode();
  filelen=file->length();
  filepos=file->tell();
  return 1;
}

int pakfInit()
{
  char path[_MAX_PATH];
  strcpy(path, cfDataDir);
  strcat(path, "cp.pak");
  nfiles=0;
  dir=0;
  if (!packfile.open(path, sbinfile::openro))
    return errOk;
  if (packfile.getl()!=0x4B434150)
    return errOk;
  int o=packfile.getl();
  nfiles=packfile.getl()/0x40;
  dir=new packdirentry[nfiles];
  if (!dir)
  {
    nfiles=0;
    return errGen;
  }
  packfile[o].read(dir, nfiles*0x40);
  int i,j;
  for (i=0; i<nfiles; i++)
    for (j=0; j<0x38; j++)
      if (dir[i].name[j]=='/')
        dir[i].name[j]='\\';

  return errOk;
}

void pakfClose()
{
  delete dir;
  packfile.close();
}
