/*
 *  SF3KtoProT - Converts Star Fighter 3000 music to Amiga ProTracker format
 *  Platform-specific code
 *  Copyright (C) 2009  Chris Bazley
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public Licence as published by
 *  the Free Software Foundation; either version 2 of the Licence, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public Licence for more details.
 *
 *  You should have received a copy of the GNU General Public Licence
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* ISO library header files */
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

/* RISC OS header files */
#include "kernel.h"

/* Local header files */
#include "platform.h"

#define FTYPE_TEQMUSIC 0xCC5 /* RISC OS file type equivalent to file
                                extension *.mod or *.nst */

char *append_leaf(const char *file_path, const char *leaf)
{
  char *new_path;

  assert(file_path != NULL);
  assert(leaf != NULL);

  /* Allocate memory for the file path with appended leaf name. */
  new_path = malloc(strlen(file_path) + sizeof(".") + strlen(leaf));
  if (new_path != NULL)
  {
    /* Append the leaf name to the specified file path. */
    strcpy(new_path, file_path);
    strcat(new_path, ".");
    strcat(new_path, leaf);
  }

  return new_path;
}

const char *find_leaf(const char *file_path)
{
  const char *leaf_name;

  assert(file_path != NULL);

  leaf_name = strrchr(file_path, '.'); /* e.g. ADFS::4.$.music */
  if (leaf_name == NULL)
    leaf_name = strrchr(file_path, ':'); /* e.g. ADFS:music */
  if (leaf_name == NULL)
    leaf_name = file_path;
  else
    leaf_name++; /* skip path separator */

  return leaf_name;
}

bool set_file_type(const char *file_path)
{
  _kernel_osfile_block kob;

  assert(file_path != NULL);

  /* Apply the RISC OS file type for Amiga ProTracker music
     to the specified file. */
  kob.load = FTYPE_TEQMUSIC;
  return (_kernel_osfile(18, file_path, &kob) != _kernel_ERROR);
}

char *append_ext(const char *file_path, const char *ext)
{
  char *new_path;
  char *sep;
  size_t path_len;

  assert(file_path != NULL);
  assert(ext != NULL);

  /* Locate separator between the file name and any existing extension. */
  sep = strrchr(file_path, '/');

  /* Calculate the length of the file path, not including any existing
     extension. */
  if (sep == NULL)
    path_len = strlen(file_path);
  else
    path_len = sep - file_path;

  /* Allocate memory for the file path with new extension. */
  new_path = malloc(path_len + sizeof("/") + strlen(ext));
  if (new_path != NULL)
  {
    /* Append the new extension to the specified file path. */
    strncpy(new_path, file_path, path_len);
    new_path[path_len] = '\0'; /* ensure string is terminated */
    strcat(new_path, "/");
    strcat(new_path, ext);
  }

  return new_path;
}

int32_t read_int32le(const void *p)
{
  const unsigned char *bytes;

  assert(p != NULL);

  /* Read a signed 32 bit little-endian integer from memory. It would probably
     be possible to optimise this for little-endian systems. */
  bytes = (const unsigned char *)p;
  return (int32_t)bytes[0] |
         (int32_t)bytes[1] << 8 |
         (int32_t)bytes[2] << 16 |
         (int32_t)bytes[3] << 24;
}
