/*  convert.c
 *  Copyright (C) 2002-2005  PCSX2 Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, 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 License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  PCSX2 members can be contacted through their website at www.pcsx2.net.
 */


#include <stddef.h>
#include <sys/types.h>

#include "convert.h"


off64_t ConvertEndianOffset(off64_t number) {
#ifndef CONVERTLITTLEENDIAN
  union {
    off64_t n;
    char c[sizeof(off64_t)];
  } oldnumber, newnumber;
  int i;

  oldnumber.n = number;
  for(i = 0; i < sizeof(off64_t); i++)
    newnumber.c[i] = oldnumber.c[sizeof(off64_t) - 1 - i];
  return(newnumber.n);
#else
  return(number);
#endif /* CONVERTLITTLEENDIAN */
} // END ConvertEndianOffset()


unsigned int ConvertEndianUInt(unsigned int number) {
#ifndef CONVERTLITTLEENDIAN
  union {
    unsigned int n;
    char c[sizeof(unsigned int)];
  } oldnumber, newnumber;
  int i;

  oldnumber.n = number;
  for(i = 0; i < sizeof(unsigned int); i++)
    newnumber.c[i] = oldnumber.c[sizeof(unsigned int) - 1 - i];
  return(newnumber.n);
#else
  return(number);
#endif /* CONVERTLITTLEENDIAN */
} // END ConvertEndianUInt()


unsigned short ConvertEndianUShort(unsigned short number) {
#ifndef CONVERTLITTLEENDIAN
  union {
    unsigned short n;
    char c[sizeof(unsigned short)];
  } oldnumber, newnumber;
  int i;

  oldnumber.n = number;
  for(i = 0; i < sizeof(unsigned short); i++)
    newnumber.c[i] = oldnumber.c[sizeof(unsigned short) - 1 - i];
  return(newnumber.n);
#else
  return(number);
#endif /* CONVERTLITTLEENDIAN */
} // END ConvertEndianUShort()


// Note: deposits M/S/F data in buffer[0]/[1]/[2] respectively.
void LBAtoMSF(unsigned long lsn, char *buffer) {
  unsigned long templsn;

  if(lsn >= 0xFFFFFFFF - 150) {
    *(buffer + 2) = 75-1;
    *(buffer + 1) = 60-1;
    *(buffer) = 100-1;
  } // ENDIF- Out of range?

  templsn = lsn;
  templsn += 150; // 2 second offset (75 Frames * 2 Seconds)
  *(buffer + 2) = templsn % 75; // Remainder in frames
  templsn -= *(buffer + 2);
  templsn /= 75;
  *(buffer + 1) = templsn % 60; // Remainder in seconds
  templsn -= *(buffer + 1);
  templsn /= 60;
  *(buffer) = templsn; // Leftover quotient in minutes
} // END LBAtoMSF()


unsigned long MSFtoLBA(char *buffer) {
  unsigned long templsn;

  if(buffer == NULL)  return(0xFFFFFFFF);

  templsn = *(buffer); // Minutes
  templsn *= 60;
  templsn += *(buffer + 1); // Seconds
  templsn *= 75;
  templsn += *(buffer + 2); // Frames
  if(templsn < 150)  return(0xFFFFFFFF);
  templsn -= 150; // Offset

  return(templsn);
} // END MSFtoLBA()
