299 lines
7.0 KiB
C
299 lines
7.0 KiB
C
/* Copyright 2005 Guillaume Duhamel
|
|
Copyright 2005-2006 Theo Berkau
|
|
|
|
This file is part of Yabause.
|
|
|
|
Yabause 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.
|
|
|
|
Yabause 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 Yabause; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef CORE_H
|
|
#define CORE_H
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#ifndef ALIGNED
|
|
#ifdef _MSC_VER
|
|
#define ALIGNED(x) __declspec(align(x))
|
|
#else
|
|
#define ALIGNED(x) __attribute__((aligned(x)))
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef STDCALL
|
|
#ifdef _MSC_VER
|
|
#define STDCALL __stdcall
|
|
#else
|
|
#define STDCALL
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef FASTCALL
|
|
#ifdef __MINGW32__
|
|
#define FASTCALL __attribute__((fastcall))
|
|
#elif defined (__i386__)
|
|
#define FASTCALL __attribute__((regparm(3)))
|
|
#else
|
|
#define FASTCALL
|
|
#endif
|
|
#endif
|
|
|
|
/* When building multiple arches on OS X you must use the compiler-
|
|
provided endian flags instead of the one provided by autoconf */
|
|
#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)
|
|
#undef WORDS_BIGENDIAN
|
|
#ifdef __BIG_ENDIAN__
|
|
#define WORDS_BIGENDIAN
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifndef INLINE
|
|
#ifdef _MSC_VER
|
|
#define INLINE _inline
|
|
#else
|
|
#define INLINE inline
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef GEKKO
|
|
/* Wii have both stdint.h and "yabause" definitions of fixed
|
|
size types */
|
|
#include <gccore.h>
|
|
typedef unsigned long pointer;
|
|
|
|
#else /* ! GEKKO */
|
|
|
|
#ifdef HAVE_STDINT_H
|
|
|
|
#include <stdint.h>
|
|
typedef uint8_t u8;
|
|
typedef int8_t s8;
|
|
typedef uint16_t u16;
|
|
typedef int16_t s16;
|
|
typedef uint32_t u32;
|
|
typedef int32_t s32;
|
|
typedef uint64_t u64;
|
|
typedef int64_t s64;
|
|
typedef uintptr_t pointer;
|
|
|
|
#else // !HAVE_STDINT_H
|
|
|
|
typedef unsigned char u8;
|
|
typedef unsigned short u16;
|
|
|
|
typedef signed char s8;
|
|
typedef signed short s16;
|
|
|
|
#if defined(__LP64__)
|
|
// Generic 64-bit
|
|
typedef unsigned int u32;
|
|
typedef unsigned long u64;
|
|
typedef unsigned long pointer;
|
|
|
|
typedef signed int s32;
|
|
typedef signed long s64;
|
|
|
|
#elif defined(_MSC_VER)
|
|
typedef unsigned long u32;
|
|
typedef unsigned __int64 u64;
|
|
typedef unsigned long long u64;
|
|
#ifdef _WIN64
|
|
typedef __int64 pointer;
|
|
#else
|
|
typedef unsigned long pointer;
|
|
#endif
|
|
|
|
typedef signed long s32;
|
|
typedef __int64 s64;
|
|
typedef signed long long s64;
|
|
|
|
#else
|
|
// 32-bit Linux GCC/MINGW/etc.
|
|
typedef unsigned long u32;
|
|
typedef unsigned long long u64;
|
|
typedef unsigned long pointer;
|
|
|
|
typedef signed long s32;
|
|
typedef signed long long s64;
|
|
#endif
|
|
|
|
#endif // !HAVE_STDINT_H
|
|
|
|
#endif // !GEKKO
|
|
|
|
typedef struct {
|
|
unsigned int size;
|
|
unsigned int done;
|
|
} IOCheck_struct;
|
|
|
|
static INLINE void ywrite(IOCheck_struct * check, void * ptr, size_t size, size_t nmemb, FILE * stream) {
|
|
check->done += (unsigned int)fwrite(ptr, size, nmemb, stream);
|
|
check->size += (unsigned int)nmemb;
|
|
}
|
|
|
|
static INLINE void yread(IOCheck_struct * check, void * ptr, size_t size, size_t nmemb, FILE * stream) {
|
|
check->done += (unsigned int)fread(ptr, size, nmemb, stream);
|
|
check->size += (unsigned int)nmemb;
|
|
}
|
|
|
|
static INLINE int StateWriteHeader(FILE *fp, const char *name, int version) {
|
|
IOCheck_struct check;
|
|
fprintf(fp, "%s", name);
|
|
check.done = 0;
|
|
check.size = 0;
|
|
ywrite(&check, (void *)&version, sizeof(version), 1, fp);
|
|
ywrite(&check, (void *)&version, sizeof(version), 1, fp); // place holder for size
|
|
return (check.done == check.size) ? ftell(fp) : -1;
|
|
}
|
|
|
|
static INLINE int StateFinishHeader(FILE *fp, int offset) {
|
|
/*
|
|
IOCheck_struct check;
|
|
int size = 0;
|
|
size = ftell(fp) - offset;
|
|
fseek(fp, offset - 4, SEEK_SET);
|
|
check.done = 0;
|
|
check.size = 0;
|
|
ywrite(&check, (void *)&size, sizeof(size), 1, fp); // write true size
|
|
fseek(fp, 0, SEEK_END);
|
|
return (check.done == check.size) ? (size + 12) : -1;
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
static INLINE int StateCheckRetrieveHeader(FILE *fp, const char *name, int *version, int *size) {
|
|
char id[4];
|
|
size_t ret;
|
|
|
|
if ((ret = fread((void *)id, 1, 4, fp)) != 4)
|
|
return -1;
|
|
|
|
if (strncmp(name, id, 4) != 0)
|
|
return -2;
|
|
|
|
if ((ret = fread((void *)version, 4, 1, fp)) != 1)
|
|
return -1;
|
|
|
|
if (fread((void *)size, 4, 1, fp) != 1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Terrible, but I'm not sure how to do the equivalent in inline
|
|
#ifdef HAVE_C99_VARIADIC_MACROS
|
|
#define AddString(s, ...) \
|
|
{ \
|
|
sprintf(s, __VA_ARGS__); \
|
|
s += strlen(s); \
|
|
}
|
|
#else
|
|
#define AddString(s, r...) \
|
|
{ \
|
|
sprintf(s, ## r); \
|
|
s += strlen(s); \
|
|
}
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef HAVE_LIBMINI18N
|
|
#include "mini18n.h"
|
|
#else
|
|
#ifndef _
|
|
#define _(a) (a)
|
|
#endif
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
/* Minimum/maximum values */
|
|
|
|
#undef MIN
|
|
#undef MAX
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
* BSWAP16(x) swaps two bytes in a 16-bit value (AABB -> BBAA) or adjacent
|
|
* bytes in a 32-bit value (AABBCCDD -> BBAADDCC).
|
|
*
|
|
* BSWAP32(x) reverses four bytes in a 32-bit value (AABBCCDD -> DDCCBBAA).
|
|
*
|
|
* WSWAP32(x) swaps two 16-bit words in a 32-bit value (AABBCCDD -> CCDDAABB).
|
|
*
|
|
* Any of these can be left undefined if there is no platform-specific
|
|
* optimization for them; the defaults below will then be used instead.
|
|
*/
|
|
|
|
#ifdef PSP
|
|
# define BSWAP16(x) ((typeof(x)) __builtin_allegrex_wsbh((x)))
|
|
# define BSWAP32(x) ((typeof(x)) __builtin_allegrex_wsbw((x)))
|
|
# define WSWAP32(x) ((typeof(x)) __builtin_allegrex_rotr((x), 16))
|
|
#endif
|
|
|
|
/* Defaults: */
|
|
|
|
#ifndef BSWAP16
|
|
# define BSWAP16(x) (((u32)(x)>>8 & 0x00FF00FF) | ((u32)(x) & 0x00FF00FF) << 8)
|
|
#endif
|
|
#ifndef BSWAP32
|
|
# define BSWAP32(x) ((u32)(x)>>24 | ((u32)(x)>>8 & 0xFF00) | ((u32)(x) & 0xFF00)<<8 | (u32)(x)<<24)
|
|
#endif
|
|
#ifndef WSWAP32
|
|
# define WSWAP32(x) ((u32)(x)>>16 | (u32)(x)<<16)
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __GNUC__
|
|
|
|
#define UNUSED __attribute ((unused))
|
|
|
|
#ifdef DEBUG
|
|
#define USED_IF_DEBUG
|
|
#else
|
|
#define USED_IF_DEBUG __attribute ((unused))
|
|
#endif
|
|
|
|
#ifdef SMPC_DEBUG
|
|
#define USED_IF_SMPC_DEBUG
|
|
#else
|
|
#define USED_IF_SMPC_DEBUG __attribute ((unused))
|
|
#endif
|
|
|
|
/* LIKELY(x) indicates that x is likely to be true (nonzero);
|
|
* UNLIKELY(x) indicates that x is likely to be false (zero).
|
|
* Use like: "if (UNLIKELY(a < b)) {...}" */
|
|
#define LIKELY(x) (__builtin_expect(!!(x), 1))
|
|
#define UNLIKELY(x) (__builtin_expect(!!(x), 0))
|
|
|
|
#else
|
|
|
|
#define UNUSED
|
|
#define USED_IF_DEBUG
|
|
#define USED_IF_SMPC_DEBUG
|
|
#define LIKELY(x) (x)
|
|
#define UNLIKELY(x) (x)
|
|
|
|
#endif
|
|
|
|
#endif
|