#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/times.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>

#include "riscos.h"
#include "module-resourcefs.h"

bool ResourceFS::SWI (unsigned int swinum, bool xbit)
{
  switch (swinum)
    {
    case ResourceFS_RegisterFiles: RegisterFiles (); break;
    case ResourceFS_DeregisterFiles: DeregisterFiles (); break;
    default:
      return false;
      break;
    }
  return true;
}

struct file_data
{
  uint32_t next_file_offset;
  uint32_t load_address;
  uint32_t exec_address;
  uint32_t file_size;
  uint32_t file_attributes;
  char filename[];  // Pointer to filename
};

void ResourceFS::RegisterFiles (void) // 0x41b40 PRM 2-414
{
  // R0 = pointer to resource file data
  struct file_data *f = (struct file_data *) READ_REG (0);

  printf ("RegisterFiles: R0=%08x, offset=%08x\n",
	  (uint32_t) f, f->next_file_offset);

  // Offset of zero terminates the list
  while (f->next_file_offset != 0)
    {
      fileinfo_t i;
      //printf ("Add file: '%s', load=%08x, exec=%08x, size=%08x\n",
      //	f->filename, f->load_address, f->exec_address, f->file_size);

      i.filename = strdup (f->filename);
      i.load_address = f->load_address;
      i.exec_address = f->exec_address;
      i.file_size = f->file_size;

      // Point directly to the filedata, which is 4 bytes after the
      // the filename (padded).
      i.file_data = (uint32_t *) ((uint32_t) i.filename
				  + strlen (i.filename) + 4);
      i.file_data -= ((uint32_t) i.file_data & 3);

      data.push_back (i);

      // Move to next record.
      f = (struct file_data *) ((uint32_t) f + f->next_file_offset);
    }

  printf ("RegisterFiles complete\n");
}

void ResourceFS::DeregisterFiles (void) // 0x41b41 PRM 2-415
{
  // R0 = pointer to resource file data
  struct file_data *f = (struct file_data *) READ_REG (0);
  // Offset of zero terminates the list
  while (f->next_file_offset != 0)
    {
      // Search for, and remove file data from tree
      for (fileinfo_iter x = data.begin (); x != data.end (); x++)
	if (strcmp (x->filename, f->filename) == 0)
	  {
	    data.erase (x);
	    break;
	  }

      // Move to next record.
      f = (struct file_data *) ((uint32_t) f + f->next_file_offset);
    }
}
