1st pass using libretro-common

This commit is contained in:
zeromus 2016-03-19 10:21:30 +00:00
parent ac26660c86
commit c4d7e476c5
142 changed files with 28698 additions and 527 deletions

View File

@ -25,7 +25,6 @@
#include <sstream>
#include <stdio.h>
#include <time.h>
#include <glib.h>
#include "debug.h"
#include "aggdraw.h"
@ -35,6 +34,10 @@
#include "mic.h"
#include "saves.h"
#ifdef _MSC_VER
#include <Windows.h>
#endif
bool HudEditorMode = false;
OSDCLASS *osd = NULL;
HudStruct Hud;
@ -511,9 +514,28 @@ static void DrawEditableElementIndicators()
void DrawHUD()
{
GTimeVal time;
g_get_current_time(&time);
hudTimer = ((s64)time.tv_sec * 1000) + ((s64)time.tv_usec/1000);
#ifdef _MSC_VER
//code taken from glib's g_get_current_time
FILETIME ft;
u64 time64;
GetSystemTimeAsFileTime (&ft);
memmove (&time64, &ft, sizeof (FILETIME));
/* Convert from 100s of nanoseconds since 1601-01-01
* to Unix epoch. Yes, this is Y2038 unsafe.
*/
time64 -= 116444736000000000LL;
time64 /= 10;
time_t tv_sec = time64 / 1000000;
time_t tv_usec = time64 % 1000000;
hudTimer = ((s64)tv_sec * 1000) + ((s64)tv_usec/1000);
#else
time_t t;
gettimeofday (&t, NULL);
result->tv_sec = r.tv_sec;
result->tv_usec = r.tv_usec;
#endif
if (HudEditorMode)
{

View File

@ -390,260 +390,6 @@ std::string getDeveloperNameByID(u16 id)
return "Unknown";
}
// ===============================================================================
// PNG/BMP
// ===============================================================================
static int WritePNGChunk(FILE *fp, uint32 size, const char *type, const uint8 *data)
{
uint32 crc;
uint8 tempo[4];
tempo[0]=size>>24;
tempo[1]=size>>16;
tempo[2]=size>>8;
tempo[3]=size;
if(fwrite(tempo,4,1,fp)!=1)
return 0;
if(fwrite(type,4,1,fp)!=1)
return 0;
if(size)
if(fwrite(data,1,size,fp)!=size)
return 0;
crc = crc32(0,(uint8 *)type,4);
if(size)
crc = crc32(crc,data,size);
tempo[0]=crc>>24;
tempo[1]=crc>>16;
tempo[2]=crc>>8;
tempo[3]=crc;
if(fwrite(tempo,4,1,fp)!=1)
return 0;
return 1;
}
int NDS_WritePNG_16bpp(int width, int height, const u16 *data, const char *fname)
{
int x, y;
const u16 * bmp = data;
FILE *pp=NULL;
uint8 *compmem = NULL;
uLongf compmemsize = (uLongf)( (height * (width + 1) * 3 * 1.001 + 1) + 12 );
if(!(compmem=(uint8 *)malloc(compmemsize)))
return 0;
if(!(pp=fopen(fname, "wb")))
{
goto PNGerr;
}
{
const uint8 header[8]={137,80,78,71,13,10,26,10};
if(fwrite(header,8,1,pp)!=1)
goto PNGerr;
}
{
uint8 chunko[13];
chunko[0] = width >> 24; // Width
chunko[1] = width >> 16;
chunko[2] = width >> 8;
chunko[3] = width;
chunko[4] = height >> 24; // Height
chunko[5] = height >> 16;
chunko[6] = height >> 8;
chunko[7] = height;
chunko[8]=8; // 8 bits per sample(24 bits per pixel)
chunko[9]=2; // Color type; RGB triplet
chunko[10]=0; // compression: deflate
chunko[11]=0; // Basic adapative filter set(though none are used).
chunko[12]=0; // No interlace.
if(!WritePNGChunk(pp,13,"IHDR",chunko))
goto PNGerr;
}
{
uint8 *tmp_buffer;
uint8 *tmp_inc;
tmp_inc = tmp_buffer = (uint8 *)malloc((width * 3 + 1) * height);
for(y=0;y<height;y++)
{
*tmp_inc = 0;
tmp_inc++;
for(x=0;x<width;x++)
{
int r,g,b;
u16 pixel = bmp[y*width+x];
r = pixel>>10;
pixel-=r<<10;
g = pixel>>5;
pixel-=g<<5;
b = pixel;
r*=255/31;
g*=255/31;
b*=255/31;
tmp_inc[0] = b;
tmp_inc[1] = g;
tmp_inc[2] = r;
tmp_inc += 3;
}
}
if(compress(compmem, &compmemsize, tmp_buffer, height * (width * 3 + 1))!=Z_OK)
{
if(tmp_buffer) free(tmp_buffer);
goto PNGerr;
}
if(tmp_buffer) free(tmp_buffer);
if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
goto PNGerr;
}
if(!WritePNGChunk(pp,0,"IEND",0))
goto PNGerr;
free(compmem);
fclose(pp);
return 1;
PNGerr:
if(compmem)
free(compmem);
if(pp)
fclose(pp);
return(0);
}
typedef struct
{
u32 size;
s32 width;
s32 height;
u16 planes;
u16 bpp;
u32 cmptype;
u32 imgsize;
s32 hppm;
s32 vppm;
u32 numcol;
u32 numimpcol;
} bmpimgheader_struct;
#include "PACKED.h"
typedef struct
{
u16 id __PACKED;
u32 size __PACKED;
u16 reserved1 __PACKED;
u16 reserved2 __PACKED;
u32 imgoffset __PACKED;
} bmpfileheader_struct;
#include "PACKED_END.h"
int NDS_WriteBMP_16bpp(int width, int height, const u16 *data, const char *filename)
{
bmpfileheader_struct fileheader;
bmpimgheader_struct imageheader;
FILE *file;
int i,j;
const u16 * bmp = data;
size_t elems_written = 0;
memset(&fileheader, 0, sizeof(fileheader));
fileheader.size = sizeof(fileheader);
fileheader.id = 'B' | ('M' << 8);
fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
memset(&imageheader, 0, sizeof(imageheader));
imageheader.size = sizeof(imageheader);
imageheader.width = width;
imageheader.height = height;
imageheader.planes = 1;
imageheader.bpp = 24;
imageheader.cmptype = 0; // None
imageheader.imgsize = imageheader.width * imageheader.height * 3;
if ((file = fopen(filename,"wb")) == NULL)
return 0;
elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
for(j=0;j<height;j++)
{
for(i=0;i<width;i++)
{
u8 r,g,b;
u16 pixel = bmp[(height-j-1)*width+i];
r = pixel>>10;
pixel-=r<<10;
g = pixel>>5;
pixel-=g<<5;
b = (u8)pixel;
r*=255/31;
g*=255/31;
b*=255/31;
elems_written += fwrite(&r, 1, sizeof(u8), file);
elems_written += fwrite(&g, 1, sizeof(u8), file);
elems_written += fwrite(&b, 1, sizeof(u8), file);
}
}
fclose(file);
return 1;
}
int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename)
{
bmpfileheader_struct fileheader;
bmpimgheader_struct imageheader;
FILE *file;
size_t elems_written = 0;
memset(&fileheader, 0, sizeof(fileheader));
fileheader.size = sizeof(fileheader);
fileheader.id = 'B' | ('M' << 8);
fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader);
memset(&imageheader, 0, sizeof(imageheader));
imageheader.size = sizeof(imageheader);
imageheader.width = width;
imageheader.height = height;
imageheader.planes = 1;
imageheader.bpp = 32;
imageheader.cmptype = 0; // None
imageheader.imgsize = imageheader.width * imageheader.height * 4;
if ((file = fopen(filename,"wb")) == NULL)
return 0;
elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file);
elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file);
for(int i=0;i<height;i++)
for(int x=0;x<width;x++)
{
u8* pixel = (u8*)buf + (height-i-1)*width*4;
pixel += (x*4);
elems_written += fwrite(pixel+2,1,1,file);
elems_written += fwrite(pixel+1,1,1,file);
elems_written += fwrite(pixel+0,1,1,file);
elems_written += fwrite(pixel+3,1,1,file);
}
fclose(file);
return 1;
}
// ===============================================================================
// Message dialogs
// ===============================================================================

View File

@ -86,11 +86,6 @@ struct MAKER
std::string getDeveloperNameByID(u16 id);
int NDS_WritePNG_16bpp(int width, int height, const u16 *data, const char *fname);
int NDS_WriteBMP_16bpp(int width, int height, const u16 *data, const char *filename);
int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename);
void* malloc_aligned(size_t length, size_t alignment);
void* malloc_aligned16(size_t length);
void* malloc_aligned32(size_t length);

View File

@ -0,0 +1,66 @@
/*
Copyright (C) 2008-2015 DeSmuME team
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <zlib.h>
#include "types.h"
#include "ImageOut.h"
#include "formats/rpng.h"
#include "formats/rbmp.h"
#include "gfx3d.h"
static u8* Convert15To24(const u16* src, int width, int height)
{
u8 *tmp_buffer;
u8 *tmp_inc;
tmp_inc = tmp_buffer = (u8 *)malloc(width * height * 3);
for(int y=0;y<height;y++)
{
for(int x=0;x<width;x++)
{
u16 pixel = *src++;
u32 expanded = RGB15TO32_NOALPHA(pixel);
*tmp_inc++ = (expanded>>16)&0xFF;
*tmp_inc++ = (expanded>>8)&0xFF;
*tmp_inc++ = expanded&0xFF;
}
}
return tmp_buffer;
}
int NDS_WritePNG_15bpp(int width, int height, const u16 *data, const char *filename)
{
u8* tmp = Convert15To24(data,width,height);
bool ok = rpng_save_image_bgr24(filename,tmp,width,height,width*3);
free(tmp);
return ok?1:0;
}
int NDS_WriteBMP_15bpp(int width, int height, const u16 *data, const char *filename)
{
u8* tmp = Convert15To24(data,width,height);
bool ok = rbmp_save_image(filename,tmp,width,height,width*3,RBMP_SOURCE_TYPE_BGR24);
free(tmp);
return ok?1:0;
}
int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename)
{
bool ok = rbmp_save_image(filename,buf,width,height,width*4,RBMP_SOURCE_TYPE_ARGB8888);
return ok?1:0;
}

View File

@ -0,0 +1,27 @@
/*
Copyright (C) 2015 DeSmuME team
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DESMUME_IMAGEOUT_H_
#define _DESMUME_IMAGEOUT_H_
#include "types.h"
int NDS_WritePNG_15bpp(int width, int height, const u16 *data, const char *fname);
int NDS_WriteBMP_15bpp(int width, int height, const u16 *data, const char *filename);
int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename);
#endif

View File

@ -29,6 +29,7 @@
#include <string.h>
#include <fcntl.h>
#include <rthreads/rthreads.h>
#include "../gdbstub.h"
#include "../types.h"
#include "../NDSSystem.h"
@ -47,12 +48,7 @@
#endif
#endif // HOST_WINDOWS
#ifndef HOST_WINDOWS
// to access the CPUs in any way, a thread has to get a lock on this first
pthread_mutex_t cpu_mutex;
#else
HANDLE cpu_mutex;
#endif
slock *cpu_mutex;
#ifdef __GNUC__
#define UNUSED_PARM( parm) parm __attribute__((unused))
@ -158,47 +154,22 @@ enum target_signal
void gdbstub_mutex_init()
{
#ifndef HOST_WINDOWS
pthread_mutex_init(&cpu_mutex, NULL);
#else
#ifdef USE_MUTEX_ON_WINDOWS
cpu_mutex = CreateMutex(NULL, FALSE, NULL);
#endif
#endif
cpu_mutex = slock_new();
}
void gdbstub_mutex_destroy()
{
#ifndef HOST_WINDOWS
pthread_mutex_destroy(&cpu_mutex);
#else
#ifdef USE_MUTEX_ON_WINDOWS
CloseHandle(cpu_mutex);
#endif
#endif
slock_free(cpu_mutex);
}
void gdbstub_mutex_lock()
{
#ifndef HOST_WINDOWS
pthread_mutex_lock(&cpu_mutex);
#else
#ifdef USE_MUTEX_ON_WINDOWS
// Maybe we should check the return value, but then again what could we do about it anyway.
WaitForSingleObject(cpu_mutex, INFINITE);
#endif
#endif
slock_lock(cpu_mutex);
}
void gdbstub_mutex_unlock()
{
#ifndef HOST_WINDOWS
pthread_mutex_unlock(&cpu_mutex);
#else
#ifdef USE_MUTEX_ON_WINDOWS
ReleaseMutex(cpu_mutex);
#endif
#endif
slock_unlock(cpu_mutex);
}
static void

View File

@ -26,16 +26,7 @@
#define _GDBSTUB_INTERNAL_H_ 1
#if defined(_MSC_VER)
#if _MSC_VER < 1900
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
#else
#include <stdint.h>
#endif
#include <stdint.h>
#include <winsock2.h>
#define SOCKET_TYPE SOCKET

View File

@ -0,0 +1,375 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <ctype.h>
#ifndef HAVE_GETOPT_LONG
#include <string.h>
#include <boolean.h>
#include <stddef.h>
#include <stdlib.h>
#include <retro_miscellaneous.h>
#endif
#include <compat/getopt.h>
#include <compat/strl.h>
#include <compat/strcasestr.h>
#include <compat/posix_string.h>
#include <retro_assert.h>
#ifndef HAVE_GETOPT_LONG
char *optarg;
int optind, opterr, optopt;
static bool is_short_option(const char *str)
{
return str[0] == '-' && str[1] != '-';
}
static bool is_long_option(const char *str)
{
return str[0] == '-' && str[1] == '-';
}
static int find_short_index(char * const *argv)
{
int idx;
for (idx = 0; argv[idx]; idx++)
{
if (is_short_option(argv[idx]))
return idx;
}
return -1;
}
static int find_long_index(char * const *argv)
{
int idx;
for (idx = 0; argv[idx]; idx++)
{
if (is_long_option(argv[idx]))
return idx;
}
return -1;
}
static int parse_short(const char *optstring, char * const *argv)
{
bool extra_opt, takes_arg, embedded_arg;
const char *opt = NULL;
char arg = argv[0][1];
if (arg == ':')
return '?';
opt = strchr(optstring, arg);
if (!opt)
return '?';
extra_opt = argv[0][2];
takes_arg = opt[1] == ':';
/* If we take an argument, and we see additional characters,
* this is in fact the argument (i.e. -cfoo is same as -c foo). */
embedded_arg = extra_opt && takes_arg;
if (takes_arg)
{
if (embedded_arg)
{
optarg = argv[0] + 2;
optind++;
}
else
{
optarg = argv[1];
optind += 2;
}
return optarg ? opt[0] : '?';
}
else if (embedded_arg)
{
/* If we see additional characters,
* and they don't take arguments, this
* means we have multiple flags in one. */
memmove(&argv[0][1], &argv[0][2], strlen(&argv[0][2]) + 1);
return opt[0];
}
else
{
optind++;
return opt[0];
}
}
static int parse_long(const struct option *longopts, char * const *argv)
{
size_t indice;
const struct option *opt = NULL;
for (indice = 0; longopts[indice].name; indice++)
{
if (!strcmp(longopts[indice].name, &argv[0][2]))
{
opt = &longopts[indice];
break;
}
}
if (!opt)
return '?';
/* getopt_long has an "optional" arg, but we don't bother with that. */
if (opt->has_arg && !argv[1])
return '?';
if (opt->has_arg)
{
optarg = argv[1];
optind += 2;
}
else
optind++;
if (opt->flag)
{
*opt->flag = opt->val;
return 0;
}
return opt->val;
}
static void shuffle_block(char **begin, char **last, char **end)
{
ptrdiff_t len = last - begin;
const char **tmp = (const char**)calloc(len, sizeof(const char*));
rarch_assert(tmp);
memcpy(tmp, begin, len * sizeof(const char*));
memmove(begin, last, (end - last) * sizeof(const char*));
memcpy(end - len, tmp, len * sizeof(const char*));
free(tmp);
}
int getopt_long(int argc, char *argv[],
const char *optstring, const struct option *longopts, int *longindex)
{
int short_index, long_index;
(void)longindex;
if (optind == 0)
optind = 1;
if (argc == 1)
return -1;
short_index = find_short_index(&argv[optind]);
long_index = find_long_index(&argv[optind]);
/* We're done here. */
if (short_index == -1 && long_index == -1)
return -1;
/* Reorder argv so that non-options come last.
* Non-POSIXy, but that's what getopt does by default. */
if ((short_index > 0) && ((short_index < long_index) || (long_index == -1)))
{
shuffle_block(&argv[optind], &argv[optind + short_index], &argv[argc]);
short_index = 0;
}
else if ((long_index > 0) && ((long_index < short_index)
|| (short_index == -1)))
{
shuffle_block(&argv[optind], &argv[optind + long_index], &argv[argc]);
long_index = 0;
}
rarch_assert(short_index == 0 || long_index == 0);
if (short_index == 0)
return parse_short(optstring, &argv[optind]);
else if (long_index == 0)
return parse_long(longopts, &argv[optind]);
else
return '?';
}
#endif
#ifndef HAVE_STRCASESTR
/* Pretty much strncasecmp. */
static int casencmp(const char *a, const char *b, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
{
int a_lower = tolower(a[i]);
int b_lower = tolower(b[i]);
if (a_lower != b_lower)
return a_lower - b_lower;
}
return 0;
}
char *strcasestr_rarch__(const char *haystack, const char *needle)
{
size_t i, hay_len, needle_len, search_off;
hay_len = strlen(haystack);
needle_len = strlen(needle);
if (needle_len > hay_len)
return NULL;
search_off = hay_len - needle_len;
for (i = 0; i <= search_off; i++)
if (!casencmp(haystack + i, needle, needle_len))
return (char*)haystack + i;
return NULL;
}
#endif
#ifndef HAVE_STRL
/* Implementation of strlcpy()/strlcat() based on OpenBSD. */
size_t strlcpy(char *dest, const char *source, size_t size)
{
size_t src_size = 0;
size_t n = size;
if (n)
while (--n && (*dest++ = *source++)) src_size++;
if (!n)
{
if (size) *dest = '\0';
while (*source++) src_size++;
}
return src_size;
}
size_t strlcat(char *dest, const char *source, size_t size)
{
size_t len = strlen(dest);
dest += len;
if (len > size)
size = 0;
else
size -= len;
return len + strlcpy(dest, source, size);
}
#endif
#ifdef _WIN32
#undef strcasecmp
#undef strdup
#undef isblank
#undef strtok_r
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
#include <compat/strl.h>
#include <string.h>
int rarch_strcasecmp__(const char *a, const char *b)
{
while (*a && *b)
{
int a_ = tolower(*a);
int b_ = tolower(*b);
if (a_ != b_)
return a_ - b_;
a++;
b++;
}
return tolower(*a) - tolower(*b);
}
char *rarch_strdup__(const char *orig)
{
size_t len = strlen(orig) + 1;
char *ret = (char*)malloc(len);
if (!ret)
return NULL;
strlcpy(ret, orig, len);
return ret;
}
int rarch_isblank__(int c)
{
return (c == ' ') || (c == '\t');
}
char *rarch_strtok_r__(char *str, const char *delim, char **saveptr)
{
char *first = NULL;
if (!saveptr || !delim)
return NULL;
if (str)
*saveptr = str;
do
{
char *ptr = NULL;
first = *saveptr;
while (*first && strchr(delim, *first))
*first++ = '\0';
if (*first == '\0')
return NULL;
ptr = first + 1;
while (*ptr && !strchr(delim, *ptr))
ptr++;
*saveptr = ptr + (*ptr ? 1 : 0);
*ptr = '\0';
} while (strlen(first) == 0);
return first;
}
#endif

View File

@ -0,0 +1,157 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_fnmatch.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#if __TEST_FNMATCH__
#include <assert.h>
#endif
#include <compat/fnmatch.h>
/* Implemnentation of fnmatch(3) so it can be
* distributed to non *nix platforms.
*
* No flags are implemented ATM.
* We don't use them. Add flags as needed. */
int rl_fnmatch(const char *pattern, const char *string, int flags)
{
const char *c;
int charmatch = 0;
int rv;
for (c = pattern; *c != '\0'; c++)
{
/* String ended before pattern */
if ((*c != '*') && (*string == '\0'))
return FNM_NOMATCH;
switch (*c)
{
/* Match any number of unknown chars */
case '*':
/* Find next node in the pattern
* ignoring multiple asterixes
*/
do {
c++;
if (*c == '\0')
return 0;
} while (*c == '*');
/* Match the remaining pattern
* ignoring more and more characters. */
do {
/* We reached the end of the string without a
* match. There is a way to optimize this by
* calculating the minimum chars needed to
* match the remaining pattern but I don't
* think it is worth the work ATM.
*/
if (*string == '\0')
return FNM_NOMATCH;
rv = rl_fnmatch(c, string, flags);
string++;
} while (rv != 0);
return 0;
/* Match char from list */
case '[':
charmatch = 0;
for (c++; *c != ']'; c++)
{
/* Bad format */
if (*c == '\0')
return FNM_NOMATCH;
/* Match already found */
if (charmatch)
continue;
if (*c == *string)
charmatch = 1;
}
/* No match in list */
if (!charmatch)
return FNM_NOMATCH;
string++;
break;
/* Has any character */
case '?':
string++;
break;
/* Match following character verbatim */
case '\\':
c++;
/* Dangling escape at end of pattern.
* FIXME: Was c == '\0' (makes no sense).
* Not sure if c == NULL or *c == '\0'
* is intended. Assuming *c due to c++ right before. */
if (*c == '\0')
return FNM_NOMATCH;
default:
if (*c != *string)
return FNM_NOMATCH;
string++;
}
}
/* End of string and end of pattend */
if (*string == '\0')
return 0;
return FNM_NOMATCH;
}
#if __TEST_FNMATCH__
int main(void)
{
assert(rl_fnmatch("TEST", "TEST", 0) == 0);
assert(rl_fnmatch("TE?T", "TEST", 0) == 0);
assert(rl_fnmatch("TE[Ssa]T", "TEST", 0) == 0);
assert(rl_fnmatch("TE[Ssda]T", "TEsT", 0) == 0);
assert(rl_fnmatch("TE[Ssda]T", "TEdT", 0) == 0);
assert(rl_fnmatch("TE[Ssda]T", "TEaT", 0) == 0);
assert(rl_fnmatch("TEST*", "TEST", 0) == 0);
assert(rl_fnmatch("TEST**", "TEST", 0) == 0);
assert(rl_fnmatch("TE*ST*", "TEST", 0) == 0);
assert(rl_fnmatch("TE**ST*", "TEST", 0) == 0);
assert(rl_fnmatch("TE**ST*", "TExST", 0) == 0);
assert(rl_fnmatch("TE**ST", "TEST", 0) == 0);
assert(rl_fnmatch("TE**ST", "TExST", 0) == 0);
assert(rl_fnmatch("TE\\**ST", "TE*xST", 0) == 0);
assert(rl_fnmatch("*.*", "test.jpg", 0) == 0);
assert(rl_fnmatch("*.jpg", "test.jpg", 0) == 0);
assert(rl_fnmatch("*.[Jj][Pp][Gg]", "test.jPg", 0) == 0);
assert(rl_fnmatch("*.[Jj]*[Gg]", "test.jPg", 0) == 0);
assert(rl_fnmatch("TEST?", "TEST", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TES[asd", "TEST", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TEST\\", "TEST", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TEST*S", "TEST", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TE**ST", "TExT", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TE\\*T", "TExT", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TES?", "TES", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TE", "TEST", 0) == FNM_NOMATCH);
assert(rl_fnmatch("TEST!", "TEST", 0) == FNM_NOMATCH);
assert(rl_fnmatch("DSAD", "TEST", 0) == FNM_NOMATCH);
}
#endif

View File

@ -0,0 +1,10 @@
#ifndef __LIBRETRO_SDK_CRT_STRING_H_
#define __LIBRETRO_SDK_CRT_STRING_H_
#include <stdio.h>
void *memcpy(void *dst, const void *src, size_t len);
void *memset(void *b, int c, size_t len);
#endif

View File

@ -0,0 +1,34 @@
#ifdef _MSC_VER
#include <cruntime.h>
#endif
#include <stdio.h>
#include <string.h>
void *memset(void *dst, int val, size_t count)
{
void *start = dst;
#if defined(_M_IA64) || defined (_M_AMD64) || defined(_M_ALPHA) || defined (_M_PPC)
extern void RtlFillMemory(void *, size_t count, char);
RtlFillMemory(dst, count, (char)val);
#else
while (count--)
{
*(char*)dst = (char)val;
dst = (char*)dst + 1;
}
#endif
return start;
}
void *memcpy(void *dst, const void *src, size_t len)
{
size_t i;
for (i = 0; i < len; i++)
((unsigned char *)dst)[i] = ((unsigned char *)src)[i];
return dst;
}

View File

@ -0,0 +1,149 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dylib.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include <dynamic/dylib.h>
#ifdef NEED_DYNAMIC
#ifdef _WIN32
#include <compat/posix_string.h>
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#ifdef _WIN32
static char last_dyn_error[512];
static void set_dl_error(void)
{
DWORD err = GetLastError();
if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
last_dyn_error,
sizeof(last_dyn_error) - 1,
NULL) == 0)
snprintf(last_dyn_error, sizeof(last_dyn_error) - 1,
"unknown error %lu", err);
}
#endif
/**
* dylib_load:
* @path : Path to libretro core library.
*
* Platform independent dylib loading.
*
* Returns: library handle on success, otherwise NULL.
**/
dylib_t dylib_load(const char *path)
{
#ifdef _WIN32
int prevmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
dylib_t lib = LoadLibrary(path);
SetErrorMode(prevmode);
if (!lib)
{
set_dl_error();
return NULL;
}
last_dyn_error[0] = 0;
#else
dylib_t lib = dlopen(path, RTLD_LAZY);
#endif
return lib;
}
char *dylib_error(void)
{
#ifdef _WIN32
if (last_dyn_error[0])
return last_dyn_error;
return NULL;
#else
return (char*)dlerror();
#endif
}
function_t dylib_proc(dylib_t lib, const char *proc)
{
function_t sym;
void *ptr_sym = NULL;
#ifdef _WIN32
sym = (function_t)GetProcAddress(lib ?
(HMODULE)lib : GetModuleHandle(NULL), proc);
if (!sym)
{
set_dl_error();
return NULL;
}
last_dyn_error[0] = 0;
#else
if (lib)
ptr_sym = dlsym(lib, proc);
else
{
void *handle = dlopen(NULL, RTLD_LAZY);
if (handle)
{
ptr_sym = dlsym(handle, proc);
dlclose(handle);
}
}
/* Dirty hack to workaround the non-legality of
* (void*) -> fn-pointer casts. */
memcpy(&sym, &ptr_sym, sizeof(void*));
#endif
return sym;
}
/**
* dylib_close:
* @lib : Library handle.
*
* Frees library handle.
**/
void dylib_close(dylib_t lib)
{
#ifdef _WIN32
if (!FreeLibrary((HMODULE)lib))
set_dl_error();
last_dyn_error[0] = 0;
#else
#ifndef NO_DLCLOSE
dlclose(lib);
#endif
#endif
}
#endif

View File

@ -0,0 +1,884 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (config_file.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#if !defined(_WIN32) && !defined(__CELLOS_LV2__) && !defined(_XBOX)
#include <sys/param.h> /* PATH_MAX */
#elif defined(_WIN32) && !defined(_XBOX)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(_XBOX)
#include <xtl.h>
#endif
#include <retro_miscellaneous.h>
#include <compat/strl.h>
#include <compat/posix_string.h>
#include <compat/msvc.h>
#include <file/config_file.h>
#include <file/file_path.h>
#include <retro_stat.h>
#include <string/string_list.h>
#include <rhash.h>
#define MAX_INCLUDE_DEPTH 16
static config_file_t *config_file_new_internal(const char *path, unsigned depth);
void config_file_free(config_file_t *conf);
static char *getaline(FILE *file)
{
char* newline = (char*)malloc(9);
char* newline_tmp = NULL;
size_t cur_size = 8;
size_t idx = 0;
int in = getc(file);
if (!newline)
return NULL;
while (in != EOF && in != '\n')
{
if (idx == cur_size)
{
cur_size *= 2;
newline_tmp = (char*)realloc(newline, cur_size + 1);
if (!newline_tmp)
{
free(newline);
return NULL;
}
newline = newline_tmp;
}
newline[idx++] = in;
in = getc(file);
}
newline[idx] = '\0';
return newline;
}
static char *extract_value(char *line, bool is_value)
{
char *save = NULL;
char *tok = NULL;
if (is_value)
{
while (isspace((int)*line))
line++;
/* If we don't have an equal sign here,
* we've got an invalid string. */
if (*line != '=')
return NULL;
line++;
}
while (isspace((int)*line))
line++;
/* We have a full string. Read until next ". */
if (*line == '"')
{
line++;
tok = strtok_r(line, "\"", &save);
if (!tok)
return NULL;
return strdup(tok);
}
else if (*line == '\0') /* Nothing */
return NULL;
/* We don't have that. Read until next space. */
tok = strtok_r(line, " \n\t\f\r\v", &save);
if (tok)
return strdup(tok);
return NULL;
}
static void set_list_readonly(struct config_entry_list *list)
{
while (list)
{
list->readonly = true;
list = list->next;
}
}
/* Move semantics? */
static void add_child_list(config_file_t *parent, config_file_t *child)
{
if (parent->entries)
{
struct config_entry_list *head = parent->entries;
while (head->next)
head = head->next;
set_list_readonly(child->entries);
head->next = child->entries;
}
else
{
set_list_readonly(child->entries);
parent->entries = child->entries;
}
child->entries = NULL;
/* Rebase tail. */
if (parent->entries)
{
struct config_entry_list *head =
(struct config_entry_list*)parent->entries;
while (head->next)
head = head->next;
parent->tail = head;
}
else
parent->tail = NULL;
}
static void add_include_list(config_file_t *conf, const char *path)
{
struct config_include_list *head = conf->includes;
struct config_include_list *node = (struct config_include_list*)calloc(1, sizeof(*node));
if (!node)
return;
node->path = strdup(path);
if (head)
{
while (head->next)
head = head->next;
head->next = node;
}
else
conf->includes = node;
}
static void add_sub_conf(config_file_t *conf, char *line)
{
char real_path[PATH_MAX_LENGTH] = {0};
config_file_t *sub_conf = NULL;
char *path = extract_value(line, false);
if (!path)
return;
add_include_list(conf, path);
#ifdef _WIN32
fill_pathname_resolve_relative(real_path, conf->path,
path, sizeof(real_path));
#else
#ifndef __CELLOS_LV2__
if (*path == '~')
{
const char *home = getenv("HOME");
strlcpy(real_path, home ? home : "", sizeof(real_path));
strlcat(real_path, path + 1, sizeof(real_path));
}
else
#endif
fill_pathname_resolve_relative(real_path, conf->path,
path, sizeof(real_path));
#endif
sub_conf = (config_file_t*)
config_file_new_internal(real_path, conf->include_depth + 1);
if (!sub_conf)
{
free(path);
return;
}
/* Pilfer internal list. */
add_child_list(conf, sub_conf);
config_file_free(sub_conf);
free(path);
}
static char *strip_comment(char *str)
{
/* Remove everything after comment.
* Keep #s inside string literals. */
char *strend = str + strlen(str);
bool cut_comment = true;
while (*str)
{
char *comment = NULL;
char *literal = strchr(str, '\"');
if (!literal)
literal = strend;
comment = (char*)strchr(str, '#');
if (!comment)
comment = strend;
if (cut_comment && literal < comment)
{
cut_comment = false;
str = literal + 1;
}
else if (!cut_comment && literal)
{
cut_comment = true;
str = literal + 1;
}
else if (comment)
{
*comment = '\0';
str = comment;
}
else
str = strend;
}
return str;
}
static bool parse_line(config_file_t *conf,
struct config_entry_list *list, char *line)
{
char *comment = NULL;
char *key = (char*)malloc(9);
char *key_tmp = NULL;
size_t cur_size = 8;
size_t idx = 0;
if (!key)
return false;
if (!line || !*line)
{
free(key);
return false;
}
comment = strip_comment(line);
/* Starting line with # and include includes config files. */
if ((comment == line) && (conf->include_depth < MAX_INCLUDE_DEPTH))
{
comment++;
if (strstr(comment, "include ") == comment)
{
add_sub_conf(conf, comment + strlen("include "));
free(key);
return false;
}
}
else if (conf->include_depth >= MAX_INCLUDE_DEPTH)
{
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
}
/* Skips to first character. */
while (isspace((int)*line))
line++;
while (isgraph((int)*line))
{
if (idx == cur_size)
{
cur_size *= 2;
key_tmp = (char*)realloc(key, cur_size + 1);
if (!key_tmp)
{
free(key);
return false;
}
key = key_tmp;
}
key[idx++] = *line++;
}
key[idx] = '\0';
list->key = key;
list->key_hash = djb2_calculate(key);
list->value = extract_value(line, true);
if (!list->value)
{
list->key = NULL;
free(key);
return false;
}
return true;
}
bool config_append_file(config_file_t *conf, const char *path)
{
config_file_t *new_conf = config_file_new(path);
if (!new_conf)
return false;
if (new_conf->tail)
{
new_conf->tail->next = conf->entries;
conf->entries = new_conf->entries; /* Pilfer. */
new_conf->entries = NULL;
}
config_file_free(new_conf);
return true;
}
static config_file_t *config_file_new_internal(
const char *path, unsigned depth)
{
FILE *file = NULL;
struct config_file *conf = (struct config_file*)calloc(1, sizeof(*conf));
if (!conf)
return NULL;
if (!path || !*path)
return conf;
if (path_is_directory(path))
goto error;
conf->path = strdup(path);
if (!conf->path)
goto error;
conf->include_depth = depth;
file = fopen(path, "r");
if (!file)
{
free(conf->path);
goto error;
}
while (!feof(file))
{
struct config_entry_list *list = (struct config_entry_list*)
calloc(1, sizeof(*list));
char *line = NULL;
if (!list)
{
config_file_free(conf);
fclose(file);
return NULL;
}
line = getaline(file);
if (line)
{
if (parse_line(conf, list, line))
{
if (conf->entries)
conf->tail->next = list;
else
conf->entries = list;
conf->tail = list;
}
free(line);
}
else
{
free(list);
continue;
}
if (list != conf->tail)
free(list);
}
fclose(file);
return conf;
error:
free(conf);
return NULL;
}
config_file_t *config_file_new_from_string(const char *from_string)
{
size_t i;
struct string_list *lines = NULL;
struct config_file *conf = (struct config_file*)calloc(1, sizeof(*conf));
if (!conf)
return NULL;
if (!from_string)
return conf;
conf->path = NULL;
conf->include_depth = 0;
lines = string_split(from_string, "\n");
if (!lines)
return conf;
for (i = 0; i < lines->size; i++)
{
struct config_entry_list *list = (struct config_entry_list*)
calloc(1, sizeof(*list));
char* line = lines->elems[i].data;
if (!list)
{
string_list_free(lines);
config_file_free(conf);
return NULL;
}
if (line)
{
if (parse_line(conf, list, line))
{
if (conf->entries)
conf->tail->next = list;
else
conf->entries = list;
conf->tail = list;
}
}
if (list != conf->tail)
free(list);
}
string_list_free(lines);
return conf;
}
config_file_t *config_file_new(const char *path)
{
return config_file_new_internal(path, 0);
}
void config_file_free(config_file_t *conf)
{
struct config_include_list *inc_tmp = NULL;
struct config_entry_list *tmp = NULL;
if (!conf)
return;
tmp = conf->entries;
while (tmp)
{
struct config_entry_list *hold = NULL;
free(tmp->key);
free(tmp->value);
hold = tmp;
tmp = tmp->next;
free(hold);
}
inc_tmp = (struct config_include_list*)conf->includes;
while (inc_tmp)
{
struct config_include_list *hold = NULL;
free(inc_tmp->path);
hold = (struct config_include_list*)inc_tmp;
inc_tmp = inc_tmp->next;
free(hold);
}
free(conf->path);
free(conf);
}
static struct config_entry_list *config_get_entry(const config_file_t *conf,
const char *key, struct config_entry_list **prev)
{
struct config_entry_list *entry;
struct config_entry_list *previous = NULL;
uint32_t hash = djb2_calculate(key);
if (prev)
previous = *prev;
for (entry = conf->entries; entry; entry = entry->next)
{
if (hash == entry->key_hash && !strcmp(key, entry->key))
return entry;
previous = entry;
}
if (prev)
*prev = previous;
return NULL;
}
bool config_get_double(config_file_t *conf, const char *key, double *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
*in = strtod(entry->value, NULL);
return entry != NULL;
}
bool config_get_float(config_file_t *conf, const char *key, float *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
{
/* strtof() is C99/POSIX. Just use the more portable kind. */
*in = (float)strtod(entry->value, NULL);
}
return entry != NULL;
}
bool config_get_int(config_file_t *conf, const char *key, int *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
errno = 0;
if (entry)
{
int val = strtol(entry->value, NULL, 0);
if (errno == 0)
*in = val;
}
return entry != NULL && errno == 0;
}
bool config_get_uint64(config_file_t *conf, const char *key, uint64_t *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
errno = 0;
if (entry)
{
uint64_t val = strtoull(entry->value, NULL, 0);
if (errno == 0)
*in = val;
}
return entry != NULL && errno == 0;
}
bool config_get_uint(config_file_t *conf, const char *key, unsigned *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
errno = 0;
if (entry)
{
unsigned val = strtoul(entry->value, NULL, 0);
if (errno == 0)
*in = val;
}
return entry != NULL && errno == 0;
}
bool config_get_hex(config_file_t *conf, const char *key, unsigned *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
errno = 0;
if (entry)
{
unsigned val = strtoul(entry->value, NULL, 16);
if (errno == 0)
*in = val;
}
return entry != NULL && errno == 0;
}
bool config_get_char(config_file_t *conf, const char *key, char *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
{
if (entry->value[0] && entry->value[1])
return false;
*in = *entry->value;
}
return entry != NULL;
}
bool config_get_string(config_file_t *conf, const char *key, char **str)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
*str = strdup(entry->value);
return entry != NULL;
}
bool config_get_array(config_file_t *conf, const char *key,
char *buf, size_t size)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
return strlcpy(buf, entry->value, size) < size;
return entry != NULL;
}
bool config_get_path(config_file_t *conf, const char *key,
char *buf, size_t size)
{
#if defined(RARCH_CONSOLE)
return config_get_array(conf, key, buf, size);
#else
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
fill_pathname_expand_special(buf, entry->value, size);
return entry != NULL;
#endif
}
bool config_get_bool(config_file_t *conf, const char *key, bool *in)
{
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
if (entry)
{
if (strcasecmp(entry->value, "true") == 0)
*in = true;
else if (strcasecmp(entry->value, "1") == 0)
*in = true;
else if (strcasecmp(entry->value, "false") == 0)
*in = false;
else if (strcasecmp(entry->value, "0") == 0)
*in = false;
else
return false;
}
return entry != NULL;
}
void config_set_string(config_file_t *conf, const char *key, const char *val)
{
struct config_entry_list *last = conf->entries;
struct config_entry_list *entry = config_get_entry(conf, key, &last);
if (entry && !entry->readonly)
{
free(entry->value);
entry->value = strdup(val);
return;
}
entry = (struct config_entry_list*)calloc(1, sizeof(*entry));
if (!entry)
return;
entry->key = strdup(key);
entry->value = strdup(val);
if (last)
last->next = entry;
else
conf->entries = entry;
}
void config_set_path(config_file_t *conf, const char *entry, const char *val)
{
#if defined(RARCH_CONSOLE)
config_set_string(conf, entry, val);
#else
char buf[PATH_MAX_LENGTH] = {0};
fill_pathname_abbreviate_special(buf, val, sizeof(buf));
config_set_string(conf, entry, buf);
#endif
}
void config_set_double(config_file_t *conf, const char *key, double val)
{
char buf[128] = {0};
#ifdef __cplusplus
snprintf(buf, sizeof(buf), "%f", (float)val);
#else
snprintf(buf, sizeof(buf), "%lf", val);
#endif
config_set_string(conf, key, buf);
}
void config_set_float(config_file_t *conf, const char *key, float val)
{
char buf[128] = {0};
snprintf(buf, sizeof(buf), "%f", val);
config_set_string(conf, key, buf);
}
void config_set_int(config_file_t *conf, const char *key, int val)
{
char buf[128] = {0};
snprintf(buf, sizeof(buf), "%d", val);
config_set_string(conf, key, buf);
}
void config_set_hex(config_file_t *conf, const char *key, unsigned val)
{
char buf[128] = {0};
snprintf(buf, sizeof(buf), "%x", val);
config_set_string(conf, key, buf);
}
void config_set_uint64(config_file_t *conf, const char *key, uint64_t val)
{
char buf[128] = {0};
#ifdef _WIN32
snprintf(buf, sizeof(buf), "%I64u", val);
#else
snprintf(buf, sizeof(buf), "%llu", (long long unsigned)val);
#endif
config_set_string(conf, key, buf);
}
void config_set_char(config_file_t *conf, const char *key, char val)
{
char buf[2] = {0};
snprintf(buf, sizeof(buf), "%c", val);
config_set_string(conf, key, buf);
}
void config_set_bool(config_file_t *conf, const char *key, bool val)
{
config_set_string(conf, key, val ? "true" : "false");
}
bool config_file_write(config_file_t *conf, const char *path)
{
FILE *file;
if (path)
{
file = fopen(path, "w");
if (!file)
return false;
}
else
file = stdout;
config_file_dump(conf, file);
if (path)
fclose(file);
return true;
}
void config_file_dump(config_file_t *conf, FILE *file)
{
struct config_entry_list *list = NULL;
struct config_include_list *includes = conf->includes;
while (includes)
{
fprintf(file, "#include \"%s\"\n", includes->path);
includes = includes->next;
}
list = (struct config_entry_list*)conf->entries;
while (list)
{
if (!list->readonly)
fprintf(file, "%s = \"%s\"\n", list->key, list->value);
list = list->next;
}
}
bool config_entry_exists(config_file_t *conf, const char *entry)
{
struct config_entry_list *list = conf->entries;
while (list)
{
if (!strcmp(entry, list->key))
return true;
list = list->next;
}
return false;
}
bool config_get_entry_list_head(config_file_t *conf,
struct config_file_entry *entry)
{
const struct config_entry_list *head = conf->entries;
if (!head)
return false;
entry->key = head->key;
entry->value = head->value;
entry->next = head->next;
return true;
}
bool config_get_entry_list_next(struct config_file_entry *entry)
{
const struct config_entry_list *next = entry->next;
if (!next)
return false;
entry->key = next->key;
entry->value = next->value;
entry->next = next->next;
return true;
}

View File

@ -0,0 +1,128 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (config_file_userdata.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <file/config_file_userdata.h>
#include <file/file_path.h>
#include <string/string_list.h>
#define get_array_setup() \
char key[2][256]; \
bool got; \
struct config_file_userdata *usr = (struct config_file_userdata*)userdata; \
char *str = NULL; \
fill_pathname_join_delim(key[0], usr->prefix[0], key_str, '_', sizeof(key[0])); \
fill_pathname_join_delim(key[1], usr->prefix[1], key_str, '_', sizeof(key[1])); \
got = config_get_string(usr->conf, key[0], &str); \
got = got || config_get_string(usr->conf, key[1], &str);
#define get_array_body(T) \
if (got) \
{ \
unsigned i; \
struct string_list *list = string_split(str, " "); \
*values = (T*)calloc(list->size, sizeof(T)); \
for (i = 0; i < list->size; i++) \
(*values)[i] = (T)strtod(list->elems[i].data, NULL); \
*out_num_values = list->size; \
string_list_free(list); \
return true; \
} \
else \
{ \
*values = (T*)calloc(num_default_values, sizeof(T)); \
memcpy(*values, default_values, sizeof(T) * num_default_values); \
*out_num_values = num_default_values; \
return false; \
}
int config_userdata_get_float(void *userdata, const char *key_str,
float *value, float default_value)
{
bool got;
char key[2][256];
struct config_file_userdata *usr = (struct config_file_userdata*)userdata;
fill_pathname_join_delim(key[0], usr->prefix[0], key_str, '_', sizeof(key[0]));
fill_pathname_join_delim(key[1], usr->prefix[1], key_str, '_', sizeof(key[1]));
got = config_get_float (usr->conf, key[0], value);
got = got || config_get_float(usr->conf, key[1], value);
if (!got)
*value = default_value;
return got;
}
int config_userdata_get_int(void *userdata, const char *key_str,
int *value, int default_value)
{
bool got;
char key[2][256];
struct config_file_userdata *usr = (struct config_file_userdata*)userdata;
fill_pathname_join_delim(key[0], usr->prefix[0], key_str, '_', sizeof(key[0]));
fill_pathname_join_delim(key[1], usr->prefix[1], key_str, '_', sizeof(key[1]));
got = config_get_int (usr->conf, key[0], value);
got = got || config_get_int(usr->conf, key[1], value);
if (!got)
*value = default_value;
return got;
}
int config_userdata_get_float_array(void *userdata, const char *key_str,
float **values, unsigned *out_num_values,
const float *default_values, unsigned num_default_values)
{
get_array_setup()
get_array_body(float)
}
int config_userdata_get_int_array(void *userdata, const char *key_str,
int **values, unsigned *out_num_values,
const int *default_values, unsigned num_default_values)
{
get_array_setup()
get_array_body(int)
}
int config_userdata_get_string(void *userdata, const char *key_str,
char **output, const char *default_output)
{
get_array_setup()
if (got)
{
*output = str;
return true;
}
*output = strdup(default_output);
return false;
}
void config_userdata_free(void *ptr)
{
if (ptr)
free(ptr);
}

View File

@ -0,0 +1,213 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dir_list.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <file/dir_list.h>
#include <file/file_path.h>
#include <string/string_list.h>
#include <compat/strl.h>
#include <retro_dirent.h>
#include <retro_miscellaneous.h>
static int qstrcmp_plain(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
return strcasecmp(a->data, b->data);
}
static int qstrcmp_dir(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
int a_type = a->attr.i;
int b_type = b->attr.i;
/* Sort directories before files. */
if (a_type != b_type)
return b_type - a_type;
return strcasecmp(a->data, b->data);
}
/**
* dir_list_sort:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing.
*
**/
void dir_list_sort(struct string_list *list, bool dir_first)
{
if (list)
qsort(list->elems, list->size, sizeof(struct string_list_elem),
dir_first ? qstrcmp_dir : qstrcmp_plain);
}
/**
* dir_list_free:
* @list : pointer to the directory listing
*
* Frees a directory listing.
*
**/
void dir_list_free(struct string_list *list)
{
string_list_free(list);
}
/**
* parse_dir_entry:
* @name : name of the directory listing entry.
* @file_path : file path of the directory listing entry.
* @is_dir : is the directory listing a directory?
* @include_dirs : include directories as part of the finished directory listing?
* @include_compressed : Include compressed files, even if not part of ext_list.
* @list : pointer to directory listing.
* @ext_list : pointer to allowed file extensions listing.
* @file_ext : file extension of the directory listing entry.
*
* Parses a directory listing.
*
* Returns: zero on success, -1 on error, 1 if we should
* continue to the next entry in the directory listing.
**/
static int parse_dir_entry(const char *name, char *file_path,
bool is_dir, bool include_dirs, bool include_compressed,
struct string_list *list, struct string_list *ext_list,
const char *file_ext)
{
union string_list_elem_attr attr;
bool is_compressed_file = false;
bool supported_by_core = false;
attr.i = RARCH_FILETYPE_UNSET;
if (!is_dir)
{
is_compressed_file = path_is_compressed_file(file_path);
if (string_list_find_elem_prefix(ext_list, ".", file_ext))
supported_by_core = true;
}
if (!include_dirs && is_dir)
return 1;
if (!strcmp(name, ".") || !strcmp(name, ".."))
return 1;
if (!is_dir && ext_list &&
((!is_compressed_file && !supported_by_core) ||
(!supported_by_core && !include_compressed)))
return 1;
if (is_dir)
attr.i = RARCH_DIRECTORY;
if (is_compressed_file)
attr.i = RARCH_COMPRESSED_ARCHIVE;
/* The order of these ifs is important.
* If the file format is explicitly supported by the libretro-core, we
* need to immediately load it and not designate it as a compressed file.
*
* Example: .zip could be supported as a image by the core and as a
* compressed_file. In that case, we have to interpret it as a image.
*
* */
if (supported_by_core)
attr.i = RARCH_PLAIN_FILE;
if (!string_list_append(list, file_path, attr))
return -1;
return 0;
}
/**
* dir_list_new:
* @dir : directory path.
* @ext : allowed extensions of file directory entries to include.
* @include_dirs : include directories as part of the finished directory listing?
* @include_compressed : Only include files which match ext. Do not try to match compressed files, etc.
*
* Create a directory listing.
*
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
* NULL in case of error. Has to be freed manually.
**/
struct string_list *dir_list_new(const char *dir,
const char *ext, bool include_dirs, bool include_compressed)
{
struct RDIR *entry = NULL;
struct string_list *ext_list = NULL;
struct string_list *list = NULL;
if (!(list = string_list_new()))
return NULL;
if (ext)
ext_list = string_split(ext, "|");
entry = retro_opendir(dir);
if (!entry)
goto error;
if (retro_dirent_error(entry))
goto error;
while (retro_readdir(entry))
{
char file_path[PATH_MAX_LENGTH];
int ret = 0;
const char *name = retro_dirent_get_name(entry);
bool is_dir = retro_dirent_is_dir(entry, file_path);
const char *file_ext = path_get_extension(name);
fill_pathname_join(file_path, dir, name, sizeof(file_path));
ret = parse_dir_entry(name, file_path, is_dir,
include_dirs, include_compressed, list, ext_list, file_ext);
if (ret == -1)
goto error;
if (ret == 1)
continue;
}
retro_closedir(entry);
string_list_free(ext_list);
return list;
error:
retro_closedir(entry);
string_list_free(list);
string_list_free(ext_list);
return NULL;
}

View File

@ -0,0 +1,230 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dir_list.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <file/dir_list.h>
#include <file/file_path.h>
#include <compat/strl.h>
#include <compat/posix_string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <retro_miscellaneous.h>
static int qstrcmp_plain(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
return strcasecmp(a->data, b->data);
}
static int qstrcmp_dir(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
int a_type = a->attr.i;
int b_type = b->attr.i;
/* Sort directories before files. */
if (a_type != b_type)
return b_type - a_type;
return strcasecmp(a->data, b->data);
}
/**
* dir_list_sort:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing.
*
**/
void dir_list_sort(struct string_list *list, bool dir_first)
{
if (list)
qsort(list->elems, list->size, sizeof(struct string_list_elem),
dir_first ? qstrcmp_dir : qstrcmp_plain);
}
/**
* dir_list_free:
* @list : pointer to the directory listing
*
* Frees a directory listing.
*
**/
void dir_list_free(struct string_list *list)
{
string_list_free(list);
}
/**
*
* dirent_is_directory:
* @path : path to the directory entry.
* @entry : pointer to the directory entry.
*
* Is the directory listing entry a directory?
*
* Returns: true if directory listing entry is
* a directory, false if not.
*/
static bool dirent_is_directory(const char *path)
{
BOOL is_directory;
BOOL file_exists_at_path = [[NSFileManager defaultManager] fileExistsAtPath:@(path) isDirectory:&is_directory];
(void)file_exists_at_path;
return is_directory;
}
/**
* parse_dir_entry:
* @name : name of the directory listing entry.
* @file_path : file path of the directory listing entry.
* @is_dir : is the directory listing a directory?
* @include_dirs : include directories as part of the finished directory listing?
* @include_compressed : include compressed files, even when not part of ext_list.
* @list : pointer to directory listing.
* @ext_list : pointer to allowed file extensions listing.
* @file_ext : file extension of the directory listing entry.
*
* Parses a directory listing.
*
* Returns: zero on success, -1 on error, 1 if we should
* continue to the next entry in the directory listing.
**/
static int parse_dir_entry(const char *name, char *file_path,
bool is_dir, bool include_dirs, bool include_compressed,
struct string_list *list, struct string_list *ext_list,
const char *file_ext)
{
union string_list_elem_attr attr;
bool is_compressed_file = false;
bool supported_by_core = false;
attr.i = RARCH_FILETYPE_UNSET;
if (!is_dir)
{
is_compressed_file = path_is_compressed_file(file_path);
if (string_list_find_elem_prefix(ext_list, ".", file_ext))
supported_by_core = true;
}
if (!include_dirs && is_dir)
return 1;
if (!strcmp(name, ".") || !strcmp(name, ".."))
return 1;
if (!is_dir && ext_list &&
((!is_compressed_file && !supported_by_core) ||
(!supported_by_core && !include_compressed)))
return 1;
if (is_dir)
attr.i = RARCH_DIRECTORY;
if (is_compressed_file)
attr.i = RARCH_COMPRESSED_ARCHIVE;
/* The order of these ifs is important.
* If the file format is explicitly supported by the libretro-core, we
* need to immediately load it and not designate it as a compressed file.
*
* Example: .zip could be supported as a image by the core and as a
* compressed_file. In that case, we have to interpret it as a image.
*
* */
if (supported_by_core)
attr.i = RARCH_PLAIN_FILE;
if (!string_list_append(list, file_path, attr))
return -1;
return 0;
}
/**
* dir_list_new:
* @dir : directory path.
* @ext : allowed extensions of file directory entries to include.
* @include_dirs : include directories as part of the finished directory listing?
* @include_compressed : Include compressed files, even if not part of ext.
*
* Create a directory listing.
*
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
* NULL in case of error. Has to be freed manually.
**/
struct string_list *dir_list_new(const char *dir,
const char *ext, bool include_dirs, bool include_compressed)
{
NSArray *entries = NULL;
char path_buf[PATH_MAX_LENGTH] = {0};
struct string_list *ext_list = NULL;
struct string_list *list = NULL;
(void)path_buf;
if (!(list = string_list_new()))
return NULL;
if (ext)
ext_list = string_split(ext, "|");
entries = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@(dir) error:nil];
for (NSString *name in entries)
{
int ret = 0;
char file_path[PATH_MAX_LENGTH] = {0};
const char *file_ext = path_get_extension([name UTF8String]);
bool is_dir = false;
fill_pathname_join(file_path, dir, [name UTF8String], sizeof(file_path));
is_dir = dirent_is_directory(file_path);
ret = parse_dir_entry([name UTF8String], file_path, is_dir,
include_dirs, include_compressed, list, ext_list, file_ext);
if (ret == -1)
goto error;
if (ret == 1)
continue;
}
string_list_free(ext_list);
return list;
error:
string_list_free(list);
string_list_free(ext_list);
return NULL;
}

View File

@ -0,0 +1,899 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_extract.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <compat/zlib.h>
#include <compat/strl.h>
#include <file/file_extract.h>
#include <file/file_path.h>
#include <retro_file.h>
#include <retro_miscellaneous.h>
#include <string/string_list.h>
/* File backends. Can be fleshed out later, but keep it simple for now.
* The file is mapped to memory directly (via mmap() or just
* plain retro_read_file()).
*/
struct zlib_file_backend
{
void *(*open)(const char *path);
const uint8_t *(*data)(void *handle);
size_t (*size)(void *handle);
void (*free)(void *handle); /* Closes, unmaps and frees. */
};
#ifndef CENTRAL_FILE_HEADER_SIGNATURE
#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50
#endif
#ifndef END_OF_CENTRAL_DIR_SIGNATURE
#define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50
#endif
#ifdef HAVE_MMAP
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
typedef struct
{
int fd;
void *data;
size_t size;
} zlib_file_data_t;
static void zlib_file_free(void *handle)
{
zlib_file_data_t *data = (zlib_file_data_t*)handle;
if (!data)
return;
if (data->data)
munmap(data->data, data->size);
if (data->fd >= 0)
close(data->fd);
free(data);
}
static const uint8_t *zlib_file_data(void *handle)
{
zlib_file_data_t *data = (zlib_file_data_t*)handle;
if (!data)
return NULL;
return (const uint8_t*)data->data;
}
static size_t zlib_file_size(void *handle)
{
zlib_file_data_t *data = (zlib_file_data_t*)handle;
if (!data)
return 0;
return data->size;
}
static void *zlib_file_open(const char *path)
{
struct stat fds;
zlib_file_data_t *data = (zlib_file_data_t*)calloc(1, sizeof(*data));
if (!data)
return NULL;
data->fd = open(path, O_RDONLY);
if (data->fd < 0)
{
/* Failed to open archive. */
goto error;
}
if (fstat(data->fd, &fds) < 0)
goto error;
data->size = fds.st_size;
if (!data->size)
return data;
data->data = mmap(NULL, data->size, PROT_READ, MAP_SHARED, data->fd, 0);
if (data->data == MAP_FAILED)
{
data->data = NULL;
/* Failed to mmap() file */
goto error;
}
return data;
error:
zlib_file_free(data);
return NULL;
}
#else
typedef struct
{
void *data;
size_t size;
} zlib_file_data_t;
static void zlib_file_free(void *handle)
{
zlib_file_data_t *data = (zlib_file_data_t*)handle;
if (!data)
return;
free(data->data);
free(data);
}
static const uint8_t *zlib_file_data(void *handle)
{
zlib_file_data_t *data = (zlib_file_data_t*)handle;
if (!data)
return NULL;
return (const uint8_t*)data->data;
}
static size_t zlib_file_size(void *handle)
{
zlib_file_data_t *data = (zlib_file_data_t*)handle;
if (!data)
return 0;
return data->size;
}
static void *zlib_file_open(const char *path)
{
ssize_t ret = -1;
bool read_from_file = false;
zlib_file_data_t *data = (zlib_file_data_t*)calloc(1, sizeof(*data));
if (!data)
return NULL;
read_from_file = retro_read_file(path, &data->data, &ret);
if (!read_from_file || ret < 0)
{
/* Failed to open archive. */
goto error;
}
data->size = ret;
return data;
error:
zlib_file_free(data);
return NULL;
}
#endif
static const struct zlib_file_backend zlib_backend = {
zlib_file_open,
zlib_file_data,
zlib_file_size,
zlib_file_free,
};
static const struct zlib_file_backend *zlib_get_default_file_backend(void)
{
return &zlib_backend;
}
#undef GOTO_END_ERROR
#define GOTO_END_ERROR() do { \
ret = false; \
goto end; \
} while(0)
static uint32_t read_le(const uint8_t *data, unsigned size)
{
unsigned i;
uint32_t val = 0;
size *= 8;
for (i = 0; i < size; i += 8)
val |= *data++ << i;
return val;
}
void *zlib_stream_new(void)
{
return (z_stream*)calloc(1, sizeof(z_stream));
}
bool zlib_inflate_init2(void *data)
{
z_stream *stream = (z_stream*)data;
if (!stream)
return false;
if (inflateInit2(stream, -MAX_WBITS) != Z_OK)
return false;
return true;
}
void zlib_deflate_init(void *data, int level)
{
z_stream *stream = (z_stream*)data;
if (stream)
deflateInit(stream, level);
}
bool zlib_inflate_init(void *data)
{
z_stream *stream = (z_stream*)data;
if (!stream)
return false;
if (inflateInit(stream) != Z_OK)
return false;
return true;
}
void zlib_stream_free(void *data)
{
z_stream *ret = (z_stream*)data;
if (ret)
inflateEnd(ret);
}
void zlib_stream_deflate_free(void *data)
{
z_stream *ret = (z_stream*)data;
if (ret)
deflateEnd(ret);
}
bool zlib_inflate_data_to_file_init(
zlib_file_handle_t *handle,
const uint8_t *cdata, uint32_t csize, uint32_t size)
{
z_stream *stream = NULL;
if (!handle)
return false;
if (!(handle->stream = (z_stream*)zlib_stream_new()))
goto error;
if (!(zlib_inflate_init2(handle->stream)))
goto error;
handle->data = (uint8_t*)malloc(size);
if (!handle->data)
goto error;
stream = (z_stream*)handle->stream;
if (!stream)
goto error;
zlib_set_stream(stream,
csize,
size,
(const uint8_t*)cdata,
handle->data
);
return true;
error:
if (handle->stream)
zlib_stream_free(handle->stream);
if (handle->data)
free(handle->data);
return false;
}
int zlib_deflate_data_to_file(void *data)
{
int zstatus;
z_stream *stream = (z_stream*)data;
if (!stream)
return -1;
zstatus = deflate(stream, Z_FINISH);
if (zstatus == Z_STREAM_END)
return 1;
return 0;
}
int zlib_inflate_data_to_file_iterate(void *data)
{
int zstatus;
z_stream *stream = (z_stream*)data;
if (!stream)
return -1;
zstatus = inflate(stream, Z_NO_FLUSH);
if (zstatus == Z_STREAM_END)
return 1;
if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
return -1;
return 0;
}
uint32_t zlib_crc32_calculate(const uint8_t *data, size_t length)
{
return crc32(0, data, length);
}
uint32_t zlib_crc32_adjust(uint32_t crc, uint8_t data)
{
/* zlib and nall have different assumptions on "sign" for this
* function. */
return ~crc32(~crc, &data, 1);
}
/**
* zlib_inflate_data_to_file:
* @path : filename path of archive.
* @valid_exts : Valid extensions of archive to be parsed.
* If NULL, allow all.
* @cdata : input data.
* @csize : size of input data.
* @size : output file size
* @checksum : CRC32 checksum from input data.
*
* Decompress data to file.
*
* Returns: true (1) on success, otherwise false (0).
**/
int zlib_inflate_data_to_file(zlib_file_handle_t *handle,
int ret, const char *path, const char *valid_exts,
const uint8_t *cdata, uint32_t csize, uint32_t size, uint32_t checksum)
{
if (handle)
{
zlib_stream_free(handle->stream);
free(handle->stream);
}
if (!handle || ret == -1)
{
ret = 0;
goto end;
}
handle->real_checksum = zlib_crc32_calculate(handle->data, size);
#if 0
if (handle->real_checksum != checksum)
{
/* File CRC difers from ZIP CRC. */
printf("File CRC differs from ZIP CRC. File: 0x%x, ZIP: 0x%x.\n",
(unsigned)handle->real_checksum, (unsigned)checksum);
}
#endif
if (!retro_write_file(path, handle->data, size))
GOTO_END_ERROR();
end:
if (handle->data)
free(handle->data);
return ret;
}
static int zlib_parse_file_iterate_step_internal(
zlib_transfer_t *state, char *filename,
const uint8_t **cdata,
unsigned *cmode, uint32_t *size, uint32_t *csize,
uint32_t *checksum, unsigned *payback)
{
uint32_t offset;
uint32_t namelength, extralength, commentlength,
offsetNL, offsetEL;
uint32_t signature = read_le(state->directory + 0, 4);
if (signature != CENTRAL_FILE_HEADER_SIGNATURE)
return 0;
*cmode = read_le(state->directory + 10, 2);
*checksum = read_le(state->directory + 16, 4);
*csize = read_le(state->directory + 20, 4);
*size = read_le(state->directory + 24, 4);
namelength = read_le(state->directory + 28, 2);
extralength = read_le(state->directory + 30, 2);
commentlength = read_le(state->directory + 32, 2);
if (namelength >= PATH_MAX_LENGTH)
return -1;
memcpy(filename, state->directory + 46, namelength);
offset = read_le(state->directory + 42, 4);
offsetNL = read_le(state->data + offset + 26, 2);
offsetEL = read_le(state->data + offset + 28, 2);
*cdata = state->data + offset + 30 + offsetNL + offsetEL;
*payback = 46 + namelength + extralength + commentlength;
return 1;
}
static int zlib_parse_file_iterate_step(zlib_transfer_t *state,
const char *valid_exts, void *userdata, zlib_file_cb file_cb)
{
const uint8_t *cdata = NULL;
uint32_t checksum = 0;
uint32_t size = 0;
uint32_t csize = 0;
unsigned cmode = 0;
unsigned payload = 0;
char filename[PATH_MAX_LENGTH] = {0};
int ret = zlib_parse_file_iterate_step_internal(state, filename, &cdata, &cmode, &size, &csize,
&checksum, &payload);
if (ret != 1)
return ret;
#if 0
RARCH_LOG("OFFSET: %u, CSIZE: %u, SIZE: %u.\n", offset + 30 +
offsetNL + offsetEL, csize, size);
#endif
if (!file_cb(filename, valid_exts, cdata, cmode,
csize, size, checksum, userdata))
return 0;
state->directory += payload;
return 1;
}
static int zlib_parse_file_init(zlib_transfer_t *state,
const char *file)
{
state->backend = zlib_get_default_file_backend();
if (!state->backend)
return -1;
state->handle = state->backend->open(file);
if (!state->handle)
return -1;
state->zip_size = state->backend->size(state->handle);
if (state->zip_size < 22)
return -1;
state->data = state->backend->data(state->handle);
state->footer = state->data + state->zip_size - 22;
for (;; state->footer--)
{
if (state->footer <= state->data + 22)
return -1;
if (read_le(state->footer, 4) == END_OF_CENTRAL_DIR_SIGNATURE)
{
unsigned comment_len = read_le(state->footer + 20, 2);
if (state->footer + 22 + comment_len == state->data + state->zip_size)
break;
}
}
state->directory = state->data + read_le(state->footer + 16, 4);
return 0;
}
int zlib_parse_file_iterate(void *data, bool *returnerr, const char *file,
const char *valid_exts, zlib_file_cb file_cb, void *userdata)
{
zlib_transfer_t *state = (zlib_transfer_t*)data;
if (!state)
return -1;
switch (state->type)
{
case ZLIB_TRANSFER_NONE:
break;
case ZLIB_TRANSFER_INIT:
if (zlib_parse_file_init(state, file) == 0)
state->type = ZLIB_TRANSFER_ITERATE;
else
state->type = ZLIB_TRANSFER_DEINIT_ERROR;
break;
case ZLIB_TRANSFER_ITERATE:
{
int ret2 = zlib_parse_file_iterate_step(state,
valid_exts, userdata, file_cb);
if (ret2 != 1)
state->type = ZLIB_TRANSFER_DEINIT;
if (ret2 == -1)
state->type = ZLIB_TRANSFER_DEINIT_ERROR;
}
break;
case ZLIB_TRANSFER_DEINIT_ERROR:
*returnerr = false;
case ZLIB_TRANSFER_DEINIT:
if (state->handle)
{
state->backend->free(state->handle);
state->handle = NULL;
}
break;
}
if (state->type == ZLIB_TRANSFER_DEINIT ||
state->type == ZLIB_TRANSFER_DEINIT_ERROR)
return -1;
return 0;
}
void zlib_parse_file_iterate_stop(void *data)
{
zlib_transfer_t *state = (zlib_transfer_t*)data;
if (!state || !state->handle)
return;
state->type = ZLIB_TRANSFER_DEINIT;
zlib_parse_file_iterate(data, NULL, NULL, NULL, NULL, NULL);
}
/**
* zlib_parse_file:
* @file : filename path of archive
* @valid_exts : Valid extensions of archive to be parsed.
* If NULL, allow all.
* @file_cb : file_cb function pointer
* @userdata : userdata to pass to file_cb function pointer.
*
* Low-level file parsing. Enumerates over all files and calls
* file_cb with userdata.
*
* Returns: true (1) on success, otherwise false (0).
**/
bool zlib_parse_file(const char *file, const char *valid_exts,
zlib_file_cb file_cb, void *userdata)
{
zlib_transfer_t state = {0};
bool returnerr = true;
state.type = ZLIB_TRANSFER_INIT;
for (;;)
{
int ret = zlib_parse_file_iterate(&state, &returnerr, file,
valid_exts, file_cb, userdata);
if (ret != 0)
break;
}
return returnerr;
}
struct zip_extract_userdata
{
char *zip_path;
const char *extraction_directory;
size_t zip_path_size;
struct string_list *ext;
bool found_content;
};
enum zlib_compression_mode
{
ZLIB_MODE_UNCOMPRESSED = 0,
ZLIB_MODE_DEFLATE = 8
};
static int zip_extract_cb(const char *name, const char *valid_exts,
const uint8_t *cdata,
unsigned cmode, uint32_t csize, uint32_t size,
uint32_t checksum, void *userdata)
{
struct zip_extract_userdata *data = (struct zip_extract_userdata*)userdata;
/* Extract first content that matches our list. */
const char *ext = path_get_extension(name);
if (ext && string_list_find_elem(data->ext, ext))
{
char new_path[PATH_MAX_LENGTH] = {0};
if (data->extraction_directory)
fill_pathname_join(new_path, data->extraction_directory,
path_basename(name), sizeof(new_path));
else
fill_pathname_resolve_relative(new_path, data->zip_path,
path_basename(name), sizeof(new_path));
switch (cmode)
{
case ZLIB_MODE_UNCOMPRESSED:
data->found_content = retro_write_file(new_path, cdata, size);
return false;
case ZLIB_MODE_DEFLATE:
{
int ret = 0;
zlib_file_handle_t handle = {0};
if (!zlib_inflate_data_to_file_init(&handle, cdata, csize, size))
return 0;
do{
ret = zlib_inflate_data_to_file_iterate(handle.stream);
}while(ret == 0);
if (zlib_inflate_data_to_file(&handle, ret, new_path, valid_exts,
cdata, csize, size, checksum))
{
strlcpy(data->zip_path, new_path, data->zip_path_size);
data->found_content = true;
return 0;
}
return 0;
}
default:
return 0;
}
}
return 1;
}
/**
* zlib_extract_first_content_file:
* @zip_path : filename path to ZIP archive.
* @zip_path_size : size of ZIP archive.
* @valid_exts : valid extensions for a content file.
* @extraction_directory : the directory to extract temporary
* unzipped content to.
*
* Extract first content file from archive.
*
* Returns : true (1) on success, otherwise false (0).
**/
bool zlib_extract_first_content_file(char *zip_path, size_t zip_path_size,
const char *valid_exts, const char *extraction_directory)
{
struct string_list *list;
bool ret = true;
struct zip_extract_userdata userdata = {0};
if (!valid_exts)
{
/* Libretro implementation does not have any valid extensions.
* Cannot unzip without knowing this. */
return false;
}
list = string_split(valid_exts, "|");
if (!list)
GOTO_END_ERROR();
userdata.zip_path = zip_path;
userdata.zip_path_size = zip_path_size;
userdata.extraction_directory = extraction_directory;
userdata.ext = list;
if (!zlib_parse_file(zip_path, valid_exts, zip_extract_cb, &userdata))
{
/* Parsing ZIP failed. */
GOTO_END_ERROR();
}
if (!userdata.found_content)
{
/* Didn't find any content that matched valid extensions
* for libretro implementation. */
GOTO_END_ERROR();
}
end:
if (list)
string_list_free(list);
return ret;
}
static int zlib_get_file_list_cb(const char *path, const char *valid_exts,
const uint8_t *cdata,
unsigned cmode, uint32_t csize, uint32_t size, uint32_t checksum,
void *userdata)
{
union string_list_elem_attr attr;
struct string_list *ext_list = NULL;
const char *file_ext = NULL;
struct string_list *list = (struct string_list*)userdata;
(void)cdata;
(void)cmode;
(void)csize;
(void)size;
(void)checksum;
(void)valid_exts;
(void)file_ext;
(void)ext_list;
memset(&attr, 0, sizeof(attr));
if (valid_exts)
ext_list = string_split(valid_exts, "|");
if (ext_list)
{
char last_char = ' ';
/* Checks if this entry is a directory or a file. */
last_char = path[strlen(path)-1];
if (last_char == '/' || last_char == '\\' ) /* Skip if directory. */
goto error;
file_ext = path_get_extension(path);
if (!file_ext ||
!string_list_find_elem_prefix(ext_list, ".", file_ext))
goto error;
attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE;
string_list_free(ext_list);
}
return string_list_append(list, path, attr);
error:
string_list_free(ext_list);
return 0;
}
/**
* zlib_get_file_list:
* @path : filename path of archive
*
* Returns: string listing of files from archive on success, otherwise NULL.
**/
struct string_list *zlib_get_file_list(const char *path, const char *valid_exts)
{
struct string_list *list = string_list_new();
if (!list)
return NULL;
if (!zlib_parse_file(path, valid_exts,
zlib_get_file_list_cb, list))
{
/* Parsing ZIP failed. */
string_list_free(list);
return NULL;
}
return list;
}
bool zlib_perform_mode(const char *path, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
uint32_t crc32, void *userdata)
{
switch (cmode)
{
case 0: /* Uncompressed */
if (!retro_write_file(path, cdata, size))
return false;
break;
case 8: /* Deflate */
{
int ret = 0;
zlib_file_handle_t handle = {0};
if (!zlib_inflate_data_to_file_init(&handle, cdata, csize, size))
return false;
do{
ret = zlib_inflate_data_to_file_iterate(handle.stream);
}while(ret == 0);
if (!zlib_inflate_data_to_file(&handle, ret, path, valid_exts,
cdata, csize, size, crc32))
return false;
}
break;
default:
return false;
}
return true;
}
void zlib_set_stream(void *data,
uint32_t avail_in,
uint32_t avail_out,
const uint8_t *next_in,
uint8_t *next_out
)
{
z_stream *stream = (z_stream*)data;
if (!stream)
return;
stream->avail_in = avail_in;
stream->avail_out = avail_out;
stream->next_in = (uint8_t*)next_in;
stream->next_out = next_out;
}
uint32_t zlib_stream_get_avail_in(void *data)
{
z_stream *stream = (z_stream*)data;
if (!stream)
return 0;
return stream->avail_in;
}
uint32_t zlib_stream_get_avail_out(void *data)
{
z_stream *stream = (z_stream*)data;
if (!stream)
return 0;
return stream->avail_out;
}
uint64_t zlib_stream_get_total_out(void *data)
{
z_stream *stream = (z_stream*)data;
if (!stream)
return 0;
return stream->total_out;
}
void zlib_stream_decrement_total_out(void *data, unsigned subtraction)
{
z_stream *stream = (z_stream*)data;
if (stream)
stream->total_out -= subtraction;
}

View File

@ -0,0 +1,411 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_list.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <file/file_list.h>
#include <compat/strcasestr.h>
void file_list_push(file_list_t *list,
const char *path, const char *label,
unsigned type, size_t directory_ptr,
size_t entry_idx)
{
if (list->size >= list->capacity)
{
list->capacity += 1;
list->capacity *= 2;
list->list = (struct item_file*)realloc(list->list,
list->capacity * sizeof(struct item_file));
if (!list->list)
return;
}
list->list[list->size].label = NULL;
list->list[list->size].path = NULL;
list->list[list->size].alt = NULL;
list->list[list->size].userdata = NULL;
list->list[list->size].actiondata = NULL;
list->list[list->size].type = type;
list->list[list->size].directory_ptr = directory_ptr;
list->list[list->size].entry_idx = entry_idx;
if (label)
list->list[list->size].label = strdup(label);
if (path)
list->list[list->size].path = strdup(path);
list->size++;
}
size_t file_list_get_size(const file_list_t *list)
{
if (!list)
return 0;
return list->size;
}
size_t file_list_get_entry_index(const file_list_t *list)
{
size_t size = 0;
if (!list)
return 0;
size = file_list_get_size(list);
return list->list[size].entry_idx;
}
size_t file_list_get_directory_ptr(const file_list_t *list)
{
size_t size = file_list_get_size(list);
return list->list[size].directory_ptr;
}
void file_list_pop(file_list_t *list, size_t *directory_ptr)
{
if (!list)
return;
if (list->size != 0)
{
--list->size;
if (list->list[list->size].path)
free(list->list[list->size].path);
list->list[list->size].path = NULL;
if (list->list[list->size].label)
free(list->list[list->size].label);
list->list[list->size].label = NULL;
}
if (directory_ptr)
*directory_ptr = list->list[list->size].directory_ptr;
}
void file_list_free(file_list_t *list)
{
size_t i;
if (!list)
return;
for (i = 0; i < list->size; i++)
{
file_list_free_userdata(list, i);
file_list_free_actiondata(list, i);
if (list->list[i].path)
free(list->list[i].path);
list->list[i].path = NULL;
if (list->list[i].label)
free(list->list[i].label);
list->list[i].label = NULL;
if (list->list[i].alt)
free(list->list[i].alt);
list->list[i].alt = NULL;
}
if (list->list)
free(list->list);
list->list = NULL;
if (list)
free(list);
}
void file_list_clear(file_list_t *list)
{
size_t i;
if (!list)
return;
for (i = 0; i < list->size; i++)
{
if (list->list[i].path)
free(list->list[i].path);
list->list[i].path = NULL;
if (list->list[i].label)
free(list->list[i].label);
list->list[i].label = NULL;
if (list->list[i].alt)
free(list->list[i].alt);
list->list[i].alt = NULL;
}
list->size = 0;
}
void file_list_copy(const file_list_t *src, file_list_t *dst)
{
struct item_file *item;
if (!src || !dst)
return;
if (dst->list)
{
for (item = dst->list; item < &dst->list[dst->size]; ++item)
{
if (item->path)
free(item->path);
if (item->label)
free(item->label);
if (item->alt)
free(item->alt);
}
free(dst->list);
}
dst->size = 0;
dst->capacity = 0;
dst->list = (struct item_file*)malloc(src->size * sizeof(struct item_file));
if (!dst->list)
return;
dst->size = dst->capacity = src->size;
memcpy(dst->list, src->list, dst->size * sizeof(struct item_file));
for (item = dst->list; item < &dst->list[dst->size]; ++item)
{
if (item->path)
item->path = strdup(item->path);
if (item->label)
item->label = strdup(item->label);
if (item->alt)
item->alt = strdup(item->alt);
}
}
void file_list_set_label_at_offset(file_list_t *list, size_t idx,
const char *label)
{
if (!list)
return;
if (list->list[idx].label)
free(list->list[idx].label);
list->list[idx].alt = NULL;
if (label)
list->list[idx].label = strdup(label);
}
void file_list_get_label_at_offset(const file_list_t *list, size_t idx,
const char **label)
{
if (!label || !list)
return;
*label = list->list[idx].path;
if (list->list[idx].label)
*label = list->list[idx].label;
}
void file_list_set_alt_at_offset(file_list_t *list, size_t idx,
const char *alt)
{
if (!list)
return;
if (list->list[idx].alt)
free(list->list[idx].alt);
list->list[idx].alt = NULL;
if (alt)
list->list[idx].alt = strdup(alt);
}
void file_list_get_alt_at_offset(const file_list_t *list, size_t idx,
const char **alt)
{
if (!list)
return;
if (alt)
*alt = list->list[idx].alt ?
list->list[idx].alt : list->list[idx].path;
}
static int file_list_alt_cmp(const void *a_, const void *b_)
{
const struct item_file *a = (const struct item_file*)a_;
const struct item_file *b = (const struct item_file*)b_;
const char *cmp_a = a->alt ? a->alt : a->path;
const char *cmp_b = b->alt ? b->alt : b->path;
return strcasecmp(cmp_a, cmp_b);
}
static int file_list_type_cmp(const void *a_, const void *b_)
{
const struct item_file *a = (const struct item_file*)a_;
const struct item_file *b = (const struct item_file*)b_;
if (a->type < b->type)
return -1;
if (a->type == b->type)
return 0;
return 1;
}
void file_list_sort_on_alt(file_list_t *list)
{
qsort(list->list, list->size, sizeof(list->list[0]), file_list_alt_cmp);
}
void file_list_sort_on_type(file_list_t *list)
{
qsort(list->list, list->size, sizeof(list->list[0]), file_list_type_cmp);
}
void *file_list_get_userdata_at_offset(const file_list_t *list, size_t idx)
{
if (!list)
return NULL;
return list->list[idx].userdata;
}
void file_list_set_userdata(const file_list_t *list, size_t idx, void *ptr)
{
if (!list || !ptr)
return;
list->list[idx].userdata = ptr;
}
void file_list_set_actiondata(const file_list_t *list, size_t idx, void *ptr)
{
if (!list || !ptr)
return;
list->list[idx].actiondata = ptr;
}
void *file_list_get_actiondata_at_offset(const file_list_t *list, size_t idx)
{
if (!list)
return NULL;
return list->list[idx].actiondata;
}
void file_list_free_actiondata(const file_list_t *list, size_t idx)
{
if (!list)
return;
if (list->list[idx].actiondata)
free(list->list[idx].actiondata);
list->list[idx].actiondata = NULL;
}
void file_list_free_userdata(const file_list_t *list, size_t idx)
{
if (!list)
return;
if (list->list[idx].userdata)
free(list->list[idx].userdata);
list->list[idx].userdata = NULL;
}
void *file_list_get_last_actiondata(const file_list_t *list)
{
if (!list)
return NULL;
return list->list[list->size - 1].actiondata;
}
void file_list_get_at_offset(const file_list_t *list, size_t idx,
const char **path, const char **label, unsigned *file_type,
size_t *entry_idx)
{
if (!list)
return;
if (path)
*path = list->list[idx].path;
if (label)
*label = list->list[idx].label;
if (file_type)
*file_type = list->list[idx].type;
if (entry_idx)
*entry_idx = list->list[idx].entry_idx;
}
void file_list_get_last(const file_list_t *list,
const char **path, const char **label,
unsigned *file_type, size_t *entry_idx)
{
if (!list)
return;
if (list->size)
file_list_get_at_offset(list, list->size - 1, path, label, file_type, entry_idx);
}
bool file_list_search(const file_list_t *list, const char *needle, size_t *idx)
{
size_t i;
const char *alt;
bool ret = false;
if (!list)
return false;
for (i = 0; i < list->size; i++)
{
const char *str;
file_list_get_alt_at_offset(list, i, &alt);
if (!alt)
{
file_list_get_label_at_offset(list, i, &alt);
if (!alt)
continue;
}
str = (const char *)strcasestr(alt, needle);
if (str == alt)
{
/* Found match with first chars, best possible match. */
*idx = i;
ret = true;
break;
}
else if (str && !ret)
{
/* Found mid-string match, but try to find a match with
* first characters before we settle. */
*idx = i;
ret = true;
}
}
return ret;
}

View File

@ -0,0 +1,642 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_path.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <boolean.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#ifdef __HAIKU__
#include <kernel/image.h>
#endif
#include <sys/stat.h>
#include <file/file_path.h>
#include <compat/strl.h>
#include <compat/posix_string.h>
#include <retro_assert.h>
#include <retro_stat.h>
#include <retro_miscellaneous.h>
/**
* path_mkdir:
* @dir : directory
*
* Create directory on filesystem.
*
* Returns: true (1) if directory could be created, otherwise false (0).
**/
bool path_mkdir(const char *dir)
{
const char *target = NULL;
/* Use heap. Real chance of stack overflow if we recurse too hard. */
char *basedir = strdup(dir);
bool ret = false;
if (!basedir)
return false;
path_parent_dir(basedir);
if (!*basedir || !strcmp(basedir, dir))
goto end;
if (path_is_directory(basedir))
{
target = dir;
ret = mkdir_norecurse(dir);
}
else
{
target = basedir;
ret = path_mkdir(basedir);
if (ret)
{
target = dir;
ret = mkdir_norecurse(dir);
}
}
end:
if (target && !ret)
printf("Failed to create directory: \"%s\".\n", target);
free(basedir);
return ret;
}
/**
* path_get_extension:
* @path : path
*
* Gets extension of file. Only '.'s
* after the last slash are considered.
*
* Returns: extension part from the path.
*/
const char *path_get_extension(const char *path)
{
const char *ext = strrchr(path_basename(path), '.');
if (!ext)
return "";
return ext + 1;
}
/**
* path_remove_extension:
* @path : path
*
* Removes the extension from the path and returns the result.
* Removes all text after and including the last '.'.
* Only '.'s after the last slash are considered.
*
* Returns: path with the extension part removed.
*/
char *path_remove_extension(char *path)
{
char *last = (char*)strrchr(path_basename(path), '.');
if (!last)
return NULL;
if (*last)
*last = '\0';
return last;
}
/**
* path_contains_compressed_file:
* @path : path
*
* Checks if path contains a compressed file.
*
* Currently we only check for hash symbol (#) inside the pathname.
* If path is ever expanded to a general URI, we should check for that here.
*
* Example: Somewhere in the path there might be a compressed file
* E.g.: /path/to/file.7z#mygame.img
*
* Returns: true (1) if path contains compressed file, otherwise false (0).
**/
bool path_contains_compressed_file(const char *path)
{
return (strchr(path,'#') != NULL);
}
/**
* path_is_compressed_file:
* @path : path
*
* Checks if path is a compressed file.
*
* Returns: true (1) if path is a compressed file, otherwise false (0).
**/
bool path_is_compressed_file(const char* path)
{
#ifdef HAVE_COMPRESSION
const char* file_ext = path_get_extension(path);
#ifdef HAVE_ZLIB
if (!strcmp(file_ext, "zip"))
return true;
#endif
#ifdef HAVE_7ZIP
if (!strcmp(file_ext, "7z"))
return true;
#endif
#endif
return false;
}
/**
* path_file_exists:
* @path : path
*
* Checks if a file already exists at the specified path (@path).
*
* Returns: true (1) if file already exists, otherwise false (0).
*/
bool path_file_exists(const char *path)
{
FILE *dummy = fopen(path, "rb");
if (!dummy)
return false;
fclose(dummy);
return true;
}
/**
* fill_pathname:
* @out_path : output path
* @in_path : input path
* @replace : what to replace
* @size : buffer size of output path
*
* FIXME: Verify
*
* Replaces filename extension with 'replace' and outputs result to out_path.
* The extension here is considered to be the string from the last '.'
* to the end.
*
* Only '.'s after the last slash are considered as extensions.
* If no '.' is present, in_path and replace will simply be concatenated.
* 'size' is buffer size of 'out_path'.
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" =>
* out_path = "/foo/bar/baz/boo.asm"
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" =>
* out_path = "/foo/bar/baz/boo"
*/
void fill_pathname(char *out_path, const char *in_path,
const char *replace, size_t size)
{
char tmp_path[PATH_MAX_LENGTH] = {0};
char *tok = NULL;
rarch_assert(strlcpy(tmp_path, in_path,
sizeof(tmp_path)) < sizeof(tmp_path));
if ((tok = (char*)strrchr(path_basename(tmp_path), '.')))
*tok = '\0';
rarch_assert(strlcpy(out_path, tmp_path, size) < size);
rarch_assert(strlcat(out_path, replace, size) < size);
}
/**
* fill_pathname_noext:
* @out_path : output path
* @in_path : input path
* @replace : what to replace
* @size : buffer size of output path
*
* Appends a filename extension 'replace' to 'in_path', and outputs
* result in 'out_path'.
*
* Assumes in_path has no extension. If an extension is still
* present in 'in_path', it will be ignored.
*
*/
void fill_pathname_noext(char *out_path, const char *in_path,
const char *replace, size_t size)
{
rarch_assert(strlcpy(out_path, in_path, size) < size);
rarch_assert(strlcat(out_path, replace, size) < size);
}
static char *find_last_slash(const char *str)
{
const char *slash = strrchr(str, '/');
#ifdef _WIN32
const char *backslash = strrchr(str, '\\');
if (backslash && ((slash && backslash > slash) || !slash))
slash = backslash;
#endif
return (char*)slash;
}
/**
* fill_pathname_slash:
* @path : path
* @size : size of path
*
* Assumes path is a directory. Appends a slash
* if not already there.
**/
void fill_pathname_slash(char *path, size_t size)
{
size_t path_len = strlen(path);
const char *last_slash = find_last_slash(path);
/* Try to preserve slash type. */
if (last_slash && (last_slash != (path + path_len - 1)))
{
char join_str[2];
strlcpy(join_str, last_slash, sizeof(join_str));
rarch_assert(strlcat(path, join_str, size) < size);
}
else if (!last_slash)
rarch_assert(strlcat(path, path_default_slash(), size) < size);
}
/**
* fill_pathname_dir:
* @in_dir : input directory path
* @in_basename : input basename to be appended to @in_dir
* @replace : replacement to be appended to @in_basename
* @size : size of buffer
*
* Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
* Basename of in_basename is the string after the last '/' or '\\',
* i.e the filename without directories.
*
* If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
* 'size' is buffer size of 'in_dir'.
*
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
**/
void fill_pathname_dir(char *in_dir, const char *in_basename,
const char *replace, size_t size)
{
const char *base = NULL;
fill_pathname_slash(in_dir, size);
base = path_basename(in_basename);
rarch_assert(strlcat(in_dir, base, size) < size);
rarch_assert(strlcat(in_dir, replace, size) < size);
}
/**
* fill_pathname_base:
* @out : output path
* @in_path : input path
* @size : size of output path
*
* Copies basename of @in_path into @out_path.
**/
void fill_pathname_base(char *out, const char *in_path, size_t size)
{
const char *ptr_bak = NULL;
const char *ptr = find_last_slash(in_path);
(void)ptr_bak;
if (ptr)
ptr++;
else
ptr = in_path;
#ifdef HAVE_COMPRESSION
/* In case of compression, we also have to consider paths like
* /path/to/archive.7z#mygame.img
* and
* /path/to/archive.7z#folder/mygame.img
* basename would be mygame.img in both cases
*/
ptr_bak = ptr;
ptr = strchr(ptr_bak,'#');
if (ptr)
ptr++;
else
ptr = ptr_bak;
#endif
rarch_assert(strlcpy(out, ptr, size) < size);
}
/**
* fill_pathname_basedir:
* @out_dir : output directory
* @in_path : input path
* @size : size of output directory
*
* Copies base directory of @in_path into @out_path.
* If in_path is a path without any slashes (relative current directory),
* @out_path will get path "./".
**/
void fill_pathname_basedir(char *out_dir,
const char *in_path, size_t size)
{
rarch_assert(strlcpy(out_dir, in_path, size) < size);
path_basedir(out_dir);
}
/**
* fill_pathname_parent_dir:
* @out_dir : output directory
* @in_dir : input directory
* @size : size of output directory
*
* Copies parent directory of @in_dir into @out_dir.
* Assumes @in_dir is a directory. Keeps trailing '/'.
**/
void fill_pathname_parent_dir(char *out_dir,
const char *in_dir, size_t size)
{
rarch_assert(strlcpy(out_dir, in_dir, size) < size);
path_parent_dir(out_dir);
}
/**
* fill_dated_filename:
* @out_filename : output filename
* @ext : extension of output filename
* @size : buffer size of output filename
*
* Creates a 'dated' filename prefixed by 'RetroArch', and
* concatenates extension (@ext) to it.
*
* E.g.:
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
**/
void fill_dated_filename(char *out_filename,
const char *ext, size_t size)
{
time_t cur_time;
time(&cur_time);
strftime(out_filename, size,
"RetroArch-%m%d-%H%M%S.", localtime(&cur_time));
strlcat(out_filename, ext, size);
}
/**
* path_basedir:
* @path : path
*
* Extracts base directory by mutating path.
* Keeps trailing '/'.
**/
void path_basedir(char *path)
{
char *last = NULL;
if (strlen(path) < 2)
return;
#ifdef HAVE_COMPRESSION
/* We want to find the directory with the zipfile in basedir. */
last = strchr(path,'#');
if (last)
*last = '\0';
#endif
last = find_last_slash(path);
if (last)
last[1] = '\0';
else
snprintf(path, 3, ".%s", path_default_slash());
}
/**
* path_parent_dir:
* @path : path
*
* Extracts parent directory by mutating path.
* Assumes that path is a directory. Keeps trailing '/'.
**/
void path_parent_dir(char *path)
{
size_t len = strlen(path);
if (len && path_char_is_slash(path[len - 1]))
path[len - 1] = '\0';
path_basedir(path);
}
/**
* path_basename:
* @path : path
*
* Get basename from @path.
*
* Returns: basename from path.
**/
const char *path_basename(const char *path)
{
const char *last_hash = NULL;
const char *last = find_last_slash(path);
(void)last_hash;
#ifdef HAVE_COMPRESSION
/* We cut either at the last hash or the last slash; whichever comes last */
last_hash = strchr(path,'#');
if (last_hash > last)
return last_hash + 1;
#endif
if (last)
return last + 1;
return path;
}
/**
* path_is_absolute:
* @path : path
*
* Checks if @path is an absolute path or a relative path.
*
* Returns: true (1) if path is absolute, false (1) if path is relative.
**/
bool path_is_absolute(const char *path)
{
if (path[0] == '/')
return true;
#ifdef _WIN32
/* Many roads lead to Rome ... */
if ((strstr(path, "\\\\") == path)
|| strstr(path, ":/") || strstr(path, ":\\") || strstr(path, ":\\\\"))
return true;
#endif
return false;
}
/**
* path_resolve_realpath:
* @buf : buffer for path
* @size : size of buffer
*
* Turns relative paths into absolute path.
* If relative, rebases on current working dir.
**/
void path_resolve_realpath(char *buf, size_t size)
{
#ifndef RARCH_CONSOLE
char tmp[PATH_MAX_LENGTH];
strlcpy(tmp, buf, sizeof(tmp));
#ifdef _WIN32
if (!_fullpath(buf, tmp, size))
strlcpy(buf, tmp, size);
#else
rarch_assert(size >= PATH_MAX_LENGTH);
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
* POSIX 2008 can automatically allocate for you,
* but don't rely on that. */
if (!realpath(tmp, buf))
strlcpy(buf, tmp, size);
#endif
#endif
}
/**
* fill_pathname_resolve_relative:
* @out_path : output path
* @in_refpath : input reference path
* @in_path : input path
* @size : size of @out_path
*
* Joins basedir of @in_refpath together with @in_path.
* If @in_path is an absolute path, out_path = in_path.
* E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg",
* out_path = "/foo/bar/foobar.cg".
**/
void fill_pathname_resolve_relative(char *out_path,
const char *in_refpath, const char *in_path, size_t size)
{
if (path_is_absolute(in_path))
{
rarch_assert(strlcpy(out_path, in_path, size) < size);
return;
}
rarch_assert(strlcpy(out_path, in_refpath, size) < size);
path_basedir(out_path);
rarch_assert(strlcat(out_path, in_path, size) < size);
}
/**
* fill_pathname_join:
* @out_path : output path
* @dir : directory
* @path : path
* @size : size of output path
*
* Joins a directory (@dir) and path (@path) together.
* Makes sure not to get two consecutive slashes
* between directory and path.
**/
void fill_pathname_join(char *out_path,
const char *dir, const char *path, size_t size)
{
rarch_assert(strlcpy(out_path, dir, size) < size);
if (*out_path)
fill_pathname_slash(out_path, size);
rarch_assert(strlcat(out_path, path, size) < size);
}
/**
* fill_pathname_join_delim:
* @out_path : output path
* @dir : directory
* @path : path
* @delim : delimiter
* @size : size of output path
*
* Joins a directory (@dir) and path (@path) together
* using the given delimiter (@delim).
**/
void fill_pathname_join_delim(char *out_path, const char *dir,
const char *path, const char delim, size_t size)
{
size_t copied = strlcpy(out_path, dir, size);
rarch_assert(copied < size+1);
out_path[copied] = delim;
out_path[copied+1] = '\0';
rarch_assert(strlcat(out_path, path, size) < size);
}
/**
* fill_short_pathname_representation:
* @out_rep : output representation
* @in_path : input path
* @size : size of output representation
*
* Generates a short representation of path. It should only
* be used for displaying the result; the output representation is not
* binding in any meaningful way (for a normal path, this is the same as basename)
* In case of more complex URLs, this should cut everything except for
* the main image file.
*
* E.g.: "/path/to/game.img" -> game.img
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
*/
void fill_short_pathname_representation(char* out_rep,
const char *in_path, size_t size)
{
char path_short[PATH_MAX_LENGTH] = {0};
char *last_hash = NULL;
fill_pathname(path_short, path_basename(in_path), "",
sizeof(path_short));
last_hash = (char*)strchr(path_short,'#');
if(last_hash != NULL)
{
/* We handle paths like:
* /path/to/file.7z#mygame.img
* short_name: mygame.img:
*
* We check whether something is actually
* after the hash to avoid going over the buffer.
*/
rarch_assert(strlen(last_hash) > 1);
strlcpy(out_rep, last_hash + 1, size);
}
else
strlcpy(out_rep, path_short, size);
}

View File

@ -0,0 +1,142 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memory_stream.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <file/memory_stream.h>
static uint8_t* g_buffer = NULL;
static size_t g_size = 0;
static size_t last_file_size = 0;
struct memstream
{
uint8_t *m_buf;
size_t m_size;
size_t m_ptr;
};
void memstream_set_buffer(uint8_t *buffer, size_t size)
{
g_buffer = buffer;
g_size = size;
}
size_t memstream_get_last_size(void)
{
return last_file_size;
}
static void memstream_init(memstream_t *stream, uint8_t *buffer, size_t max_size)
{
stream->m_buf = buffer;
stream->m_size = max_size;
stream->m_ptr = 0;
}
memstream_t *memstream_open(void)
{
memstream_t *stream;
if (!g_buffer || !g_size)
return NULL;
stream = (memstream_t*)calloc(1, sizeof(*stream));
memstream_init(stream, g_buffer, g_size);
g_buffer = NULL;
g_size = 0;
return stream;
}
void memstream_close(memstream_t *stream)
{
last_file_size = stream->m_ptr;
free(stream);
}
size_t memstream_read(memstream_t *stream, void *data, size_t bytes)
{
size_t avail = stream->m_size - stream->m_ptr;
if (bytes > avail)
bytes = avail;
memcpy(data, stream->m_buf + stream->m_ptr, bytes);
stream->m_ptr += bytes;
return bytes;
}
size_t memstream_write(memstream_t *stream, const void *data, size_t bytes)
{
size_t avail = stream->m_size - stream->m_ptr;
if (bytes > avail)
bytes = avail;
memcpy(stream->m_buf + stream->m_ptr, data, bytes);
stream->m_ptr += bytes;
return bytes;
}
int memstream_seek(memstream_t *stream, int offset, int whence)
{
size_t ptr;
switch (whence)
{
case SEEK_SET:
ptr = offset;
break;
case SEEK_CUR:
ptr = stream->m_ptr + offset;
break;
case SEEK_END:
ptr = stream->m_size + offset;
break;
default:
return -1;
}
if (ptr <= stream->m_size)
{
stream->m_ptr = ptr;
return 0;
}
return -1;
}
size_t memstream_pos(memstream_t *stream)
{
return stream->m_ptr;
}
char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
{
return NULL;
}
int memstream_getc(memstream_t *stream)
{
if (stream->m_ptr >= stream->m_size)
return EOF;
return stream->m_buf[stream->m_ptr++];
}

View File

@ -0,0 +1,20 @@
TARGET := nbio_test
SOURCES := $(wildcard *.c)
OBJS := $(SOURCES:.c=.o)
CFLAGS += -Wall -pedantic -std=gnu99 -O0 -g -I../../include
all: $(TARGET)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(TARGET) $(OBJS)
.PHONY: clean

View File

@ -0,0 +1,206 @@
#include <stdio.h>
#include <stdlib.h>
#include <file/nbio.h>
struct nbio_t
{
FILE* f;
void* data;
size_t progress;
size_t len;
/*
* possible values:
* NBIO_READ, NBIO_WRITE - obvious
* -1 - currently doing nothing
* -2 - the pointer was reallocated since the last operation
*/
signed char op;
signed char mode;
};
static const char * modes[]={ "rb", "wb", "r+b", "rb", "wb", "r+b" };
struct nbio_t* nbio_open(const char * filename, unsigned mode)
{
struct nbio_t* handle = NULL;
FILE* f = fopen(filename, modes[mode]);
if (!f)
return NULL;
handle = (struct nbio_t*)malloc(sizeof(struct nbio_t));
if (!handle)
goto error;
handle->f = f;
handle->len = 0;
switch (mode)
{
case NBIO_WRITE:
case BIO_WRITE:
break;
default:
fseek(handle->f, 0, SEEK_END);
handle->len = ftell(handle->f);
break;
}
handle->mode = mode;
handle->data = malloc(handle->len);
if (handle->len && !handle->data)
goto error;
handle->progress = handle->len;
handle->op = -2;
return handle;
error:
if (handle)
{
if (handle->data)
free(handle->data);
handle->data = NULL;
free(handle);
}
handle = NULL;
fclose(f);
return NULL;
}
void nbio_begin_read(struct nbio_t* handle)
{
if (!handle)
return;
if (handle->op >= 0)
{
puts("ERROR - attempted file read operation while busy");
abort();
}
fseek(handle->f, 0, SEEK_SET);
handle->op = NBIO_READ;
handle->progress = 0;
}
void nbio_begin_write(struct nbio_t* handle)
{
if (!handle)
return;
if (handle->op >= 0)
{
puts("ERROR - attempted file write operation while busy");
abort();
}
fseek(handle->f, 0, SEEK_SET);
handle->op = NBIO_WRITE;
handle->progress = 0;
}
bool nbio_iterate(struct nbio_t* handle)
{
size_t amount = 65536;
if (!handle)
return false;
if (amount > handle->len - handle->progress)
amount = handle->len - handle->progress;
switch (handle->op)
{
case NBIO_READ:
if (handle->mode == BIO_READ)
{
amount = handle->len;
fread((char*)handle->data, 1, amount, handle->f);
}
else
fread((char*)handle->data + handle->progress, 1, amount, handle->f);
break;
case NBIO_WRITE:
if (handle->mode == BIO_WRITE)
{
size_t written = 0;
amount = handle->len;
written = fwrite((char*)handle->data, 1, amount, handle->f);
if (written != amount)
return false;
}
else
fwrite((char*)handle->data + handle->progress, 1, amount, handle->f);
break;
}
handle->progress += amount;
if (handle->progress == handle->len)
handle->op = -1;
return (handle->op < 0);
}
void nbio_resize(struct nbio_t* handle, size_t len)
{
if (!handle)
return;
if (handle->op >= 0)
{
puts("ERROR - attempted file resize operation while busy");
abort();
}
if (len < handle->len)
{
puts("ERROR - attempted file shrink operation, not implemented");
abort();
}
handle->len = len;
handle->data = realloc(handle->data, handle->len);
handle->op = -1;
handle->progress = handle->len;
}
void* nbio_get_ptr(struct nbio_t* handle, size_t* len)
{
if (!handle)
return NULL;
if (len)
*len = handle->len;
if (handle->op == -1)
return handle->data;
return NULL;
}
void nbio_cancel(struct nbio_t* handle)
{
if (!handle)
return;
handle->op = -1;
handle->progress = handle->len;
}
void nbio_free(struct nbio_t* handle)
{
if (!handle)
return;
if (handle->op >= 0)
{
puts("ERROR - attempted free() while busy");
abort();
}
fclose(handle->f);
free(handle->data);
handle->f = NULL;
handle->data = NULL;
free(handle);
}

View File

@ -0,0 +1,63 @@
#include <stdio.h>
#include <string.h>
#include <file/nbio.h>
static void nbio_write_test(void)
{
size_t size;
bool looped = false;
void* ptr = NULL;
struct nbio_t* write = nbio_open("test.bin", NBIO_WRITE);
nbio_resize(write, 1024*1024);
ptr = nbio_get_ptr(write, &size);
if (size != 1024*1024)
puts("ERROR: wrong size (1)");
memset(ptr, 0x42, 1024*1024);
nbio_begin_write(write);
while (!nbio_iterate(write)) looped=true;
if (!looped)
puts("Write finished immediately?");
nbio_free(write);
}
static void nbio_read_test(void)
{
size_t size;
bool looped = false;
struct nbio_t* read = nbio_open("test.bin", NBIO_READ);
void* ptr = nbio_get_ptr(read, &size);
if (size != 1024*1024)
puts("ERROR: wrong size (2)");
if (ptr)
puts("Read pointer is available before iterating?");
nbio_begin_read(read);
while (!nbio_iterate(read)) looped=true;
if (!looped)
puts("Read finished immediately?");
ptr = nbio_get_ptr(read, &size);
if (size != 1024*1024)
puts("ERROR: wrong size (3)");
if (*(char*)ptr != 0x42 || memcmp(ptr, (char*)ptr+1, 1024*1024-1))
puts("ERROR: wrong data");
nbio_free(read);
}
int main(void)
{
nbio_write_test();
nbio_read_test();
}

View File

@ -0,0 +1,201 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_dirent.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#if defined(_WIN32)
# include <compat/posix_string.h>
# ifdef _MSC_VER
# define setmode _setmode
# endif
# ifdef _XBOX
# include <xtl.h>
# define INVALID_FILE_ATTRIBUTES -1
# else
# include <io.h>
# include <fcntl.h>
# include <direct.h>
# include <windows.h>
# endif
#elif defined(VITA)
# include <psp2/io/fcntl.h>
# include <psp2/io/dirent.h>
#else
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <unistd.h>
#endif
#ifdef __CELLOS_LV2__
#include <cell/cell_fs.h>
#endif
#include <boolean.h>
#include <retro_stat.h>
#include <retro_dirent.h>
struct RDIR
{
#if defined(_WIN32)
WIN32_FIND_DATA entry;
HANDLE directory;
#elif defined(VITA) || defined(PSP)
SceUID directory;
SceIoDirent entry;
#elif defined(__CELLOS_LV2__)
CellFsErrno error;
int directory;
CellFsDirent entry;
#else
DIR *directory;
const struct dirent *entry;
#endif
};
struct RDIR *retro_opendir(const char *name)
{
char path_buf[1024];
struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir));
if (!rdir)
return NULL;
(void)path_buf;
#if defined(_WIN32)
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
rdir->directory = FindFirstFile(path_buf, &rdir->entry);
#elif defined(VITA) || defined(PSP)
rdir->directory = sceIoDopen(name);
#elif defined(__CELLOS_LV2__)
rdir->error = cellFsOpendir(name, &rdir->directory);
#else
rdir->directory = opendir(name);
rdir->entry = NULL;
#endif
return rdir;
}
bool retro_dirent_error(struct RDIR *rdir)
{
#if defined(_WIN32)
return (rdir->directory == INVALID_HANDLE_VALUE);
#elif defined(VITA) || defined(PSP)
return (rdir->directory < 0);
#elif defined(__CELLOS_LV2__)
return (rdir->error != CELL_FS_SUCCEEDED);
#else
return !(rdir->directory);
#endif
}
int retro_readdir(struct RDIR *rdir)
{
#if defined(_WIN32)
return (FindNextFile(rdir->directory, &rdir->entry) != 0);
#elif defined(VITA) || defined(PSP)
return (sceIoDread(rdir->directory, &rdir->entry) > 0);
#elif defined(__CELLOS_LV2__)
uint64_t nread;
rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
return (nread != 0);
#else
return ((rdir->entry = readdir(rdir->directory)) != NULL);
#endif
}
const char *retro_dirent_get_name(struct RDIR *rdir)
{
#if defined(_WIN32)
return rdir->entry.cFileName;
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
return rdir->entry.d_name;
#else
return rdir->entry->d_name;
#endif
}
/**
*
* retro_dirent_is_dir:
* @rdir : pointer to the directory entry.
* @path : path to the directory entry.
*
* Is the directory listing entry a directory?
*
* Returns: true if directory listing entry is
* a directory, false if not.
*/
bool retro_dirent_is_dir(struct RDIR *rdir, const char *path)
{
#if defined(_WIN32)
const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry;
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
#elif defined(PSP) || defined(VITA)
const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry;
#if defined(PSP)
return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR;
#elif defined(VITA)
return PSP2_S_ISDIR(entry->d_stat.st_mode);
#endif
#elif defined(__CELLOS_LV2__)
CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
#elif defined(DT_DIR)
const struct dirent *entry = (const struct dirent*)rdir->entry;
if (entry->d_type == DT_DIR)
return true;
/* This can happen on certain file systems. */
if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)
return path_is_directory(path);
return false;
#else
/* dirent struct doesn't have d_type, do it the slow way ... */
return path_is_directory(path);
#endif
}
void retro_closedir(struct RDIR *rdir)
{
if (!rdir)
return;
#if defined(_WIN32)
if (rdir->directory != INVALID_HANDLE_VALUE)
FindClose(rdir->directory);
#elif defined(VITA) || defined(PSP)
sceIoDclose(rdir->directory);
#elif defined(__CELLOS_LV2__)
rdir->error = cellFsClosedir(rdir->directory);
#else
if (rdir->directory)
closedir(rdir->directory);
#endif
free(rdir);
}

View File

@ -0,0 +1,389 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_file.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#if defined(_WIN32)
# include <compat/posix_string.h>
# ifdef _MSC_VER
# define setmode _setmode
# endif
# ifdef _XBOX
# include <xtl.h>
# define INVALID_FILE_ATTRIBUTES -1
# else
# include <io.h>
# include <fcntl.h>
# include <direct.h>
# include <windows.h>
# endif
#elif defined(VITA)
# include <psp2/io/fcntl.h>
# include <psp2/io/dirent.h>
#define PSP_O_RDONLY PSP2_O_RDONLY
#define PSP_O_RDWR PSP2_O_RDWR
#define PSP_O_CREAT PSP2_O_CREAT
#define PSP_O_WRONLY PSP2_O_WRONLY
#define PSP_O_TRUNC PSP2_O_TRUNC
#else
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <unistd.h>
#endif
#ifdef __CELLOS_LV2__
#include <cell/cell_fs.h>
#else
#include <fcntl.h>
#endif
#ifdef RARCH_INTERNAL
#include <retro_log.h>
#endif
#include <retro_file.h>
#if 1
#define HAVE_BUFFERED_IO 1
#endif
struct RFILE
{
#if defined(PSP) || defined(VITA)
SceUID fd;
#elif defined(__CELLOS_LV2__)
int fd;
#elif defined(HAVE_BUFFERED_IO)
FILE *fd;
#else
int fd;
#endif
};
int retro_get_fd(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
return stream->fd;
#elif defined(HAVE_BUFFERED_IO)
return fileno(stream->fd);
#else
return stream->fd;
#endif
}
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
{
int flags = 0;
int mode_int = 0;
const char *mode_str = NULL;
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
if (!stream)
return NULL;
(void)mode_str;
(void)mode_int;
(void)flags;
switch (mode)
{
case RFILE_MODE_READ:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_RDONLY;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_RDONLY;
#elif defined(HAVE_BUFFERED_IO)
mode_str = "rb";
#else
flags = O_RDONLY;
#endif
break;
case RFILE_MODE_WRITE:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC;
#elif defined(HAVE_BUFFERED_IO)
mode_str = "wb";
#else
flags = O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR;
#endif
break;
case RFILE_MODE_READ_WRITE:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_RDWR;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_RDWR;
#elif defined(HAVE_BUFFERED_IO)
mode_str = "w+";
#else
flags = O_RDWR;
#ifdef _WIN32
flags |= O_BINARY;
#endif
#endif
break;
}
#if defined(VITA) || defined(PSP)
stream->fd = sceIoOpen(path, flags, mode_int);
#elif defined(__CELLOS_LV2__)
cellFsOpen(path, flags, &stream->fd, NULL, 0);
#elif defined(HAVE_BUFFERED_IO)
stream->fd = fopen(path, mode_str);
#else
stream->fd = open(path, flags);
#endif
#if defined(HAVE_BUFFERED_IO)
if (!stream->fd)
goto error;
#else
if (stream->fd == -1)
goto error;
#endif
return stream;
error:
retro_fclose(stream);
return NULL;
}
ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence)
{
int ret = 0;
if (!stream)
return -1;
(void)ret;
#if defined(VITA) || defined(PSP)
ret = sceIoLseek(stream->fd, (SceOff)offset, whence);
if (ret == -1)
return -1;
return 0;
#elif defined(__CELLOS_LV2__)
uint64_t pos = 0;
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
return -1;
return 0;
#elif defined(HAVE_BUFFERED_IO)
return fseek(stream->fd, (long)offset, whence);
#else
ret = lseek(stream->fd, offset, whence);
if (ret == -1)
return -1;
return 0;
#endif
}
ssize_t retro_ftell(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoLseek(stream->fd, 0, SEEK_CUR);
#elif defined(__CELLOS_LV2__)
uint64_t pos = 0;
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
return -1;
return 0;
#elif defined(HAVE_BUFFERED_IO)
return ftell(stream->fd);
#else
return lseek(stream->fd, 0, SEEK_CUR);
#endif
}
void retro_frewind(RFILE *stream)
{
retro_fseek(stream, 0L, SEEK_SET);
}
ssize_t retro_fread(RFILE *stream, void *s, size_t len)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoRead(stream->fd, s, len);
#elif defined(__CELLOS_LV2__)
uint64_t bytes_written;
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
return -1;
return bytes_written;
#elif defined(HAVE_BUFFERED_IO)
return fread(s, 1, len, stream->fd);
#else
return read(stream->fd, s, len);
#endif
}
ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoWrite(stream->fd, s, len);
#elif defined(__CELLOS_LV2__)
uint64_t bytes_written;
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
return -1;
return bytes_written;
#elif defined(HAVE_BUFFERED_IO)
return fwrite(s, 1, len, stream->fd);
#else
return write(stream->fd, s, len);
#endif
}
int retro_fclose(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
if (stream->fd > 0)
sceIoClose(stream->fd);
#elif defined(__CELLOS_LV2__)
if (stream->fd > 0)
cellFsClose(stream->fd);
#elif defined(HAVE_BUFFERED_IO)
if (stream->fd)
fclose(stream->fd);
#else
if (stream->fd > 0)
close(stream->fd);
#endif
free(stream);
return 0;
}
/**
* retro_read_file:
* @path : path to file.
* @buf : buffer to allocate and read the contents of the
* file into. Needs to be freed manually.
*
* Read the contents of a file into @buf.
*
* Returns: number of items read, -1 on error.
*/
int retro_read_file(const char *path, void **buf, ssize_t *len)
{
ssize_t ret = 0;
ssize_t content_buf_size = 0;
void *content_buf = NULL;
RFILE *file = retro_fopen(path, RFILE_MODE_READ, -1);
if (!file)
goto error;
if (retro_fseek(file, 0, SEEK_END) != 0)
goto error;
content_buf_size = retro_ftell(file);
if (content_buf_size < 0)
goto error;
retro_frewind(file);
content_buf = malloc(content_buf_size + 1);
if (!content_buf)
goto error;
if ((ret = retro_fread(file, content_buf, content_buf_size)) < content_buf_size)
{
#ifdef RARCH_INTERNAL
RARCH_WARN("Didn't read whole file: %s.\n", path);
#else
printf("Didn't read whole file: %s.\n", path);
#endif
}
if (!content_buf)
goto error;
*buf = content_buf;
/* Allow for easy reading of strings to be safe.
* Will only work with sane character formatting (Unix). */
((char*)content_buf)[content_buf_size] = '\0';
if (retro_fclose(file) != 0)
printf("Failed to close file stream.\n");
if (len)
*len = ret;
return 1;
error:
retro_fclose(file);
if (content_buf)
free(content_buf);
if (len)
*len = -1;
*buf = NULL;
return 0;
}
/**
* retro_write_file:
* @path : path to file.
* @data : contents to write to the file.
* @size : size of the contents.
*
* Writes data to a file.
*
* Returns: true (1) on success, false (0) otherwise.
*/
bool retro_write_file(const char *path, const void *data, ssize_t size)
{
ssize_t ret = 0;
RFILE *file = retro_fopen(path, RFILE_MODE_WRITE, -1);
if (!file)
return false;
ret = retro_fwrite(file, data, size);
retro_fclose(file);
return (ret == size);
}

View File

@ -0,0 +1,181 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_stat.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#if defined(_WIN32)
#ifdef _MSC_VER
#define setmode _setmode
#endif
#ifdef _XBOX
#include <xtl.h>
#define INVALID_FILE_ATTRIBUTES -1
#else
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <windows.h>
#endif
#elif defined(VITA)
#define SCE_ERROR_ERRNO_EEXIST 0x80010011
#include <psp2/io/fcntl.h>
#include <psp2/io/dirent.h>
#include <psp2/io/stat.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#if defined(PSP)
#include <pspkernel.h>
#endif
#ifdef __HAIKU__
#include <kernel/image.h>
#endif
#if defined(__CELLOS_LV2__)
#include <cell/cell_fs.h>
#endif
#if defined(VITA)
#define FIO_SO_ISDIR PSP2_S_ISDIR
#endif
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
#include <unistd.h> /* stat() is defined here */
#endif
#include <retro_miscellaneous.h>
#include <boolean.h>
enum stat_mode
{
IS_DIRECTORY = 0,
IS_CHARACTER_SPECIAL,
IS_VALID
};
static bool path_stat(const char *path, enum stat_mode mode)
{
#if defined(VITA) || defined(PSP)
SceIoStat buf;
if (sceIoGetstat(path, &buf) < 0)
return false;
#elif defined(__CELLOS_LV2__)
CellFsStat buf;
if (cellFsStat(path, &buf) < 0)
return false;
#elif defined(_WIN32)
DWORD ret = GetFileAttributes(path);
if (ret == INVALID_FILE_ATTRIBUTES)
return false;
#else
struct stat buf;
if (stat(path, &buf) < 0)
return false;
#endif
switch (mode)
{
case IS_DIRECTORY:
#if defined(VITA) || defined(PSP)
return FIO_SO_ISDIR(buf.st_mode);
#elif defined(__CELLOS_LV2__)
return ((buf.st_mode & S_IFMT) == S_IFDIR);
#elif defined(_WIN32)
return (ret & FILE_ATTRIBUTE_DIRECTORY);
#else
return S_ISDIR(buf.st_mode);
#endif
case IS_CHARACTER_SPECIAL:
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(_WIN32)
return false;
#else
return S_ISCHR(buf.st_mode);
#endif
case IS_VALID:
return true;
}
return false;
}
/**
* path_is_directory:
* @path : path
*
* Checks if path is a directory.
*
* Returns: true (1) if path is a directory, otherwise false (0).
*/
bool path_is_directory(const char *path)
{
return path_stat(path, IS_DIRECTORY);
}
bool path_is_character_special(const char *path)
{
return path_stat(path, IS_CHARACTER_SPECIAL);
}
bool stat_is_valid(const char *path)
{
return path_stat(path, IS_VALID);
}
/**
* path_mkdir_norecurse:
* @dir : directory
*
* Create directory on filesystem.
*
* Returns: true (1) if directory could be created, otherwise false (0).
**/
bool mkdir_norecurse(const char *dir)
{
int ret;
#if defined(_WIN32)
ret = _mkdir(dir);
#elif defined(IOS)
ret = mkdir(dir, 0755);
#elif defined(VITA) || defined(PSP)
ret = sceIoMkdir(dir, 0777);
#else
ret = mkdir(dir, 0750);
#endif
/* Don't treat this as an error. */
#if defined(VITA)
if ((ret == SCE_ERROR_ERRNO_EEXIST) && path_is_directory(dir))
ret = 0;
#else
if (ret < 0 && errno == EEXIST && path_is_directory(dir))
ret = 0;
#endif
if (ret < 0)
printf("mkdir(%s) error: %s.\n", dir, strerror(errno));
return ret == 0;
}

View File

@ -0,0 +1,220 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rbmp_encode.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <retro_file.h>
#include <formats/rbmp.h>
static bool write_header_bmp(RFILE *file, unsigned width, unsigned height, bool is32bpp)
{
unsigned line_size = (width * (is32bpp?4:3) + 3) & ~3;
unsigned size = line_size * height + 54;
unsigned size_array = line_size * height;
uint8_t header[54];
/* Generic BMP stuff. */
/* signature */
header[0] = 'B';
header[1] = 'M';
/* file size */
header[2] = (uint8_t)(size >> 0);
header[3] = (uint8_t)(size >> 8);
header[4] = (uint8_t)(size >> 16);
header[5] = (uint8_t)(size >> 24);
/* reserved */
header[6] = 0;
header[7] = 0;
header[8] = 0;
header[9] = 0;
/* offset */
header[10] = 54;
header[11] = 0;
header[12] = 0;
header[13] = 0;
/* DIB size */
header[14] = 40;
header[15] = 0;
header[16] = 0;
header[17] = 0;
/* Width */
header[18] = (uint8_t)(width >> 0);
header[19] = (uint8_t)(width >> 8);
header[20] = (uint8_t)(width >> 16);
header[21] = (uint8_t)(width >> 24);
/* Height */
header[22] = (uint8_t)(height >> 0);
header[23] = (uint8_t)(height >> 8);
header[24] = (uint8_t)(height >> 16);
header[25] = (uint8_t)(height >> 24);
/* Color planes */
header[26] = 1;
header[27] = 0;
/* Bits per pixel */
header[28] = is32bpp?32:24;
header[29] = 0;
/* Compression method */
header[30] = 0;
header[31] = 0;
header[32] = 0;
header[33] = 0;
/* Image data size */
header[34] = (uint8_t)(size_array >> 0);
header[35] = (uint8_t)(size_array >> 8);
header[36] = (uint8_t)(size_array >> 16);
header[37] = (uint8_t)(size_array >> 24);
/* Horizontal resolution */
header[38] = 19;
header[39] = 11;
header[40] = 0;
header[41] = 0;
/* Vertical resolution */
header[42] = 19;
header[43] = 11;
header[44] = 0;
header[45] = 0;
/* Palette size */
header[46] = 0;
header[47] = 0;
header[48] = 0;
header[49] = 0;
/* Important color count */
header[50] = 0;
header[51] = 0;
header[52] = 0;
header[53] = 0;
return retro_fwrite(file, header, sizeof(header)) == sizeof(header);
}
static void dump_line_565_to_24(uint8_t *line, const uint16_t *src, unsigned width)
{
unsigned i;
for (i = 0; i < width; i++)
{
uint16_t pixel = *src++;
uint8_t b = (pixel >> 0) & 0x1f;
uint8_t g = (pixel >> 5) & 0x3f;
uint8_t r = (pixel >> 11) & 0x1f;
*line++ = (b << 3) | (b >> 2);
*line++ = (g << 2) | (g >> 4);
*line++ = (r << 3) | (r >> 2);
}
}
static void dump_line_32_to_24(uint8_t *line, const uint32_t *src, unsigned width)
{
unsigned i;
for (i = 0; i < width; i++)
{
uint32_t pixel = *src++;
*line++ = (pixel >> 0) & 0xff;
*line++ = (pixel >> 8) & 0xff;
*line++ = (pixel >> 16) & 0xff;
}
}
static void dump_content(RFILE *file, const void *frame,
int width, int height, int pitch, rbmp_source_type type)
{
uint8_t *line;
size_t line_size;
int i, j;
int bytes_per_pixel = (type==RBMP_SOURCE_TYPE_ARGB8888?4:3);
union
{
const uint8_t *u8;
const uint16_t *u16;
const uint32_t *u32;
} u;
u.u8 = (const uint8_t*)frame + (height-1) * pitch;
line_size = (width * bytes_per_pixel + 3) & ~3;
if (type == RBMP_SOURCE_TYPE_BGR24)
{
/* BGR24 byte order input matches output. Can directly copy, but... need to make sure we pad it. */
uint32_t zeros = 0;
int pad = line_size-pitch;
for (j = height-1; j >= 0; j--, u.u8 -= pitch)
{
retro_fwrite(file, u.u8, pitch);
if(pad != 0) retro_fwrite(file, &zeros, pad);
}
return;
}
else if(type == RBMP_SOURCE_TYPE_ARGB8888)
{
/* ARGB8888 byte order input matches output. Can directly copy. */
for (j = height-1; j >= 0; j--, u.u8 -= pitch)
{
retro_fwrite(file, u.u8, line_size);
}
return;
}
/* allocate line buffer, and initialize the final four bytes to zero, for deterministic padding */
line = (uint8_t*)malloc(line_size);
if (!line) return;
*(uint32_t*)(line + line_size - 4) = 0;
if (type == RBMP_SOURCE_TYPE_XRGB888)
{
for (j = height-1; j >= 0; j--, u.u8 -= pitch)
{
dump_line_32_to_24(line, u.u32, width);
retro_fwrite(file, line, line_size);
}
}
else /* type == RBMP_SOURCE_TYPE_RGB565 */
{
for (j = height-1; j >= 0; j--, u.u8 -= pitch)
{
dump_line_565_to_24(line, u.u16, width);
retro_fwrite(file, line, line_size);
}
}
}
bool rbmp_save_image(const char *filename, const void *frame,
unsigned width, unsigned height,
unsigned pitch, rbmp_source_type type)
{
bool ret;
RFILE *file = retro_fopen(filename, RFILE_MODE_WRITE, -1);
if (!file)
return false;
ret = write_header_bmp(file, width, height, type==RBMP_SOURCE_TYPE_ARGB8888);
if (ret)
dump_content(file, frame, width, height, pitch, type);
retro_fclose(file);
return ret;
}

View File

@ -0,0 +1,37 @@
TARGET := rpng
HAVE_IMLIB2=1
LDFLAGS += -lz
ifeq ($(HAVE_IMLIB2),1)
CFLAGS += -DHAVE_IMLIB2
LDFLAGS += -lImlib2
endif
SOURCES_C := rpng.c \
rpng_encode.c \
rpng_test.c \
../../compat/compat.c \
../../file/nbio/nbio_stdio.c \
../../file/file_extract.c \
../../file/file_path.c \
../../file/retro_file.c \
../../string/string_list.c
OBJS := $(SOURCES_C:.c=.o)
CFLAGS += -Wall -pedantic -std=gnu99 -O0 -g -DHAVE_ZLIB -DHAVE_ZLIB_DEFLATE -DRPNG_TEST -I../../include
all: $(TARGET)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(TARGET) $(OBJS)
.PHONY: clean

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,383 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rpng.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <retro_file.h>
#include "rpng_internal.h"
#undef GOTO_END_ERROR
#define GOTO_END_ERROR() do { \
fprintf(stderr, "[RPNG]: Error in line %d.\n", __LINE__); \
ret = false; \
goto end; \
} while(0)
#ifdef HAVE_ZLIB_DEFLATE
static void dword_write_be(uint8_t *buf, uint32_t val)
{
*buf++ = (uint8_t)(val >> 24);
*buf++ = (uint8_t)(val >> 16);
*buf++ = (uint8_t)(val >> 8);
*buf++ = (uint8_t)(val >> 0);
}
static bool png_write_crc(RFILE *file, const uint8_t *data, size_t size)
{
uint8_t crc_raw[4] = {0};
uint32_t crc = zlib_crc32_calculate(data, size);
dword_write_be(crc_raw, crc);
return retro_fwrite(file, crc_raw, sizeof(crc_raw)) == sizeof(crc_raw);
}
static bool png_write_ihdr(RFILE *file, const struct png_ihdr *ihdr)
{
uint8_t ihdr_raw[21];
ihdr_raw[0] = '0'; /* Size */
ihdr_raw[1] = '0';
ihdr_raw[2] = '0';
ihdr_raw[3] = '0';
ihdr_raw[4] = 'I';
ihdr_raw[5] = 'H';
ihdr_raw[6] = 'D';
ihdr_raw[7] = 'R';
ihdr_raw[8] = 0; /* Width */
ihdr_raw[9] = 0;
ihdr_raw[10] = 0;
ihdr_raw[11] = 0;
ihdr_raw[12] = 0; /* Height */
ihdr_raw[13] = 0;
ihdr_raw[14] = 0;
ihdr_raw[15] = 0;
ihdr_raw[16] = ihdr->depth; /* Depth */
ihdr_raw[17] = ihdr->color_type;
ihdr_raw[18] = ihdr->compression;
ihdr_raw[19] = ihdr->filter;
ihdr_raw[20] = ihdr->interlace;
dword_write_be(ihdr_raw + 0, sizeof(ihdr_raw) - 8);
dword_write_be(ihdr_raw + 8, ihdr->width);
dword_write_be(ihdr_raw + 12, ihdr->height);
if (retro_fwrite(file, ihdr_raw, sizeof(ihdr_raw)) != sizeof(ihdr_raw))
return false;
if (!png_write_crc(file, ihdr_raw + sizeof(uint32_t),
sizeof(ihdr_raw) - sizeof(uint32_t)))
return false;
return true;
}
static bool png_write_idat(RFILE *file, const uint8_t *data, size_t size)
{
if (retro_fwrite(file, data, size) != (ssize_t)size)
return false;
if (!png_write_crc(file, data + sizeof(uint32_t), size - sizeof(uint32_t)))
return false;
return true;
}
static bool png_write_iend(RFILE *file)
{
const uint8_t data[] = {
0, 0, 0, 0,
'I', 'E', 'N', 'D',
};
if (retro_fwrite(file, data, sizeof(data)) != sizeof(data))
return false;
if (!png_write_crc(file, data + sizeof(uint32_t),
sizeof(data) - sizeof(uint32_t)))
return false;
return true;
}
static void copy_argb_line(uint8_t *dst, const uint32_t *src, unsigned width)
{
unsigned i;
for (i = 0; i < width; i++)
{
uint32_t col = src[i];
*dst++ = (uint8_t)(col >> 16);
*dst++ = (uint8_t)(col >> 8);
*dst++ = (uint8_t)(col >> 0);
*dst++ = (uint8_t)(col >> 24);
}
}
static void copy_bgr24_line(uint8_t *dst, const uint8_t *src, unsigned width)
{
unsigned i;
for (i = 0; i < width; i++, dst += 3, src += 3)
{
dst[2] = src[0];
dst[1] = src[1];
dst[0] = src[2];
}
}
static unsigned count_sad(const uint8_t *data, size_t size)
{
size_t i;
unsigned cnt = 0;
for (i = 0; i < size; i++)
cnt += abs((int8_t)data[i]);
return cnt;
}
static unsigned filter_up(uint8_t *target, const uint8_t *line,
const uint8_t *prev, unsigned width, unsigned bpp)
{
unsigned i;
width *= bpp;
for (i = 0; i < width; i++)
target[i] = line[i] - prev[i];
return count_sad(target, width);
}
static unsigned filter_sub(uint8_t *target, const uint8_t *line,
unsigned width, unsigned bpp)
{
unsigned i;
width *= bpp;
for (i = 0; i < bpp; i++)
target[i] = line[i];
for (i = bpp; i < width; i++)
target[i] = line[i] - line[i - bpp];
return count_sad(target, width);
}
static unsigned filter_avg(uint8_t *target, const uint8_t *line,
const uint8_t *prev, unsigned width, unsigned bpp)
{
unsigned i;
width *= bpp;
for (i = 0; i < bpp; i++)
target[i] = line[i] - (prev[i] >> 1);
for (i = bpp; i < width; i++)
target[i] = line[i] - ((line[i - bpp] + prev[i]) >> 1);
return count_sad(target, width);
}
static unsigned filter_paeth(uint8_t *target,
const uint8_t *line, const uint8_t *prev,
unsigned width, unsigned bpp)
{
unsigned i;
width *= bpp;
for (i = 0; i < bpp; i++)
target[i] = line[i] - paeth(0, prev[i], 0);
for (i = bpp; i < width; i++)
target[i] = line[i] - paeth(line[i - bpp], prev[i], prev[i - bpp]);
return count_sad(target, width);
}
static bool rpng_save_image(const char *path,
const uint8_t *data,
unsigned width, unsigned height, unsigned pitch, unsigned bpp)
{
unsigned h;
bool ret = true;
struct png_ihdr ihdr = {0};
size_t encode_buf_size = 0;
uint8_t *encode_buf = NULL;
uint8_t *deflate_buf = NULL;
uint8_t *rgba_line = NULL;
uint8_t *up_filtered = NULL;
uint8_t *sub_filtered = NULL;
uint8_t *avg_filtered = NULL;
uint8_t *paeth_filtered = NULL;
uint8_t *prev_encoded = NULL;
uint8_t *encode_target = NULL;
void *stream = NULL;
RFILE *file = retro_fopen(path, RFILE_MODE_WRITE, -1);
if (!file)
GOTO_END_ERROR();
if (retro_fwrite(file, png_magic, sizeof(png_magic)) != sizeof(png_magic))
GOTO_END_ERROR();
ihdr.width = width;
ihdr.height = height;
ihdr.depth = 8;
ihdr.color_type = bpp == sizeof(uint32_t) ? 6 : 2; /* RGBA or RGB */
if (!png_write_ihdr(file, &ihdr))
GOTO_END_ERROR();
encode_buf_size = (width * bpp + 1) * height;
encode_buf = (uint8_t*)malloc(encode_buf_size);
if (!encode_buf)
GOTO_END_ERROR();
prev_encoded = (uint8_t*)calloc(1, width * bpp);
if (!prev_encoded)
GOTO_END_ERROR();
rgba_line = (uint8_t*)malloc(width * bpp);
up_filtered = (uint8_t*)malloc(width * bpp);
sub_filtered = (uint8_t*)malloc(width * bpp);
avg_filtered = (uint8_t*)malloc(width * bpp);
paeth_filtered = (uint8_t*)malloc(width * bpp);
if (!rgba_line || !up_filtered || !sub_filtered || !avg_filtered || !paeth_filtered)
GOTO_END_ERROR();
encode_target = encode_buf;
for (h = 0; h < height;
h++, encode_target += width * bpp, data += pitch)
{
if (bpp == sizeof(uint32_t))
copy_argb_line(rgba_line, (const uint32_t*)data, width);
else
copy_bgr24_line(rgba_line, data, width);
/* Try every filtering method, and choose the method
* which has most entries as zero.
*
* This is probably not very optimal, but it's very
* simple to implement.
*/
{
unsigned none_score = count_sad(rgba_line, width * bpp);
unsigned up_score = filter_up(up_filtered, rgba_line, prev_encoded, width, bpp);
unsigned sub_score = filter_sub(sub_filtered, rgba_line, width, bpp);
unsigned avg_score = filter_avg(avg_filtered, rgba_line, prev_encoded, width, bpp);
unsigned paeth_score = filter_paeth(paeth_filtered, rgba_line, prev_encoded, width, bpp);
uint8_t filter = 0;
unsigned min_sad = none_score;
const uint8_t *chosen_filtered = rgba_line;
if (sub_score < min_sad)
{
filter = 1;
chosen_filtered = sub_filtered;
min_sad = sub_score;
}
if (up_score < min_sad)
{
filter = 2;
chosen_filtered = up_filtered;
min_sad = up_score;
}
if (avg_score < min_sad)
{
filter = 3;
chosen_filtered = avg_filtered;
min_sad = avg_score;
}
if (paeth_score < min_sad)
{
filter = 4;
chosen_filtered = paeth_filtered;
min_sad = paeth_score;
}
*encode_target++ = filter;
memcpy(encode_target, chosen_filtered, width * bpp);
memcpy(prev_encoded, rgba_line, width * bpp);
}
}
deflate_buf = (uint8_t*)malloc(encode_buf_size * 2); /* Just to be sure. */
if (!deflate_buf)
GOTO_END_ERROR();
stream = zlib_stream_new();
if (!stream)
GOTO_END_ERROR();
zlib_set_stream(
stream,
encode_buf_size,
encode_buf_size * 2,
encode_buf,
deflate_buf + 8);
zlib_deflate_init(stream, 9);
if (zlib_deflate_data_to_file(stream) != 1)
{
zlib_stream_deflate_free(stream);
GOTO_END_ERROR();
}
zlib_stream_deflate_free(stream);
memcpy(deflate_buf + 4, "IDAT", 4);
dword_write_be(deflate_buf + 0, zlib_stream_get_total_out(stream));
if (!png_write_idat(file, deflate_buf, zlib_stream_get_total_out(stream) + 8))
GOTO_END_ERROR();
if (!png_write_iend(file))
GOTO_END_ERROR();
end:
retro_fclose(file);
free(encode_buf);
free(deflate_buf);
free(rgba_line);
free(prev_encoded);
free(up_filtered);
free(sub_filtered);
free(avg_filtered);
free(paeth_filtered);
zlib_stream_free(stream);
return ret;
}
bool rpng_save_image_argb(const char *path, const uint32_t *data,
unsigned width, unsigned height, unsigned pitch)
{
return rpng_save_image(path, (const uint8_t*)data,
width, height, pitch, sizeof(uint32_t));
}
bool rpng_save_image_bgr24(const char *path, const uint8_t *data,
unsigned width, unsigned height, unsigned pitch)
{
return rpng_save_image(path, (const uint8_t*)data,
width, height, pitch, 3);
}
#endif

View File

@ -0,0 +1,71 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rpng.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _RPNG_COMMON_H
#define _RPNG_COMMON_H
#include <retro_inline.h>
#include <formats/rpng.h>
#include <stdint.h>
#undef GOTO_END_ERROR
#define GOTO_END_ERROR() do { \
fprintf(stderr, "[RPNG]: Error in line %d.\n", __LINE__); \
ret = false; \
goto end; \
} while(0)
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif
static const uint8_t png_magic[8] = {
0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a,
};
struct png_ihdr
{
uint32_t width;
uint32_t height;
uint8_t depth;
uint8_t color_type;
uint8_t compression;
uint8_t filter;
uint8_t interlace;
};
/* Paeth prediction filter. */
static INLINE int paeth(int a, int b, int c)
{
int p = a + b - c;
int pa = abs(p - a);
int pb = abs(p - b);
int pc = abs(p - c);
if (pa <= pb && pa <= pc)
return a;
else if (pb <= pc)
return b;
return c;
}
#endif

View File

@ -0,0 +1,133 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rpng_test.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef HAVE_IMLIB2
#include <Imlib2.h>
#endif
#include <file/nbio.h>
#include <formats/rpng.h>
static int test_rpng(const char *in_path)
{
#ifdef HAVE_IMLIB2
Imlib_Image img;
const uint32_t *imlib_data = NULL;
#endif
const uint32_t test_data[] = {
0xff000000 | 0x50, 0xff000000 | 0x80,
0xff000000 | 0x40, 0xff000000 | 0x88,
0xff000000 | 0x50, 0xff000000 | 0x80,
0xff000000 | 0x40, 0xff000000 | 0x88,
0xff000000 | 0xc3, 0xff000000 | 0xd3,
0xff000000 | 0xc3, 0xff000000 | 0xd3,
0xff000000 | 0xc3, 0xff000000 | 0xd3,
0xff000000 | 0xc3, 0xff000000 | 0xd3,
};
uint32_t *data = NULL;
unsigned width = 0;
unsigned height = 0;
if (!rpng_save_image_argb("/tmp/test.png", test_data, 4, 4, 16))
return 1;
if (!rpng_load_image_argb(in_path, &data, &width, &height))
return 2;
fprintf(stderr, "Path: %s.\n", in_path);
fprintf(stderr, "Got image: %u x %u.\n", width, height);
#if 0
fprintf(stderr, "\nRPNG:\n");
for (unsigned h = 0; h < height; h++)
{
unsigned w;
for (w = 0; w < width; w++)
fprintf(stderr, "[%08x] ", data[h * width + w]);
fprintf(stderr, "\n");
}
#endif
#ifdef HAVE_IMLIB2
/* Validate with imlib2 as well. */
img = imlib_load_image(in_path);
if (!img)
return 4;
imlib_context_set_image(img);
width = imlib_image_get_width();
height = imlib_image_get_width();
imlib_data = imlib_image_get_data_for_reading_only();
#if 0
fprintf(stderr, "\nImlib:\n");
for (unsigned h = 0; h < height; h++)
{
for (unsigned w = 0; w < width; w++)
fprintf(stderr, "[%08x] ", imlib_data[h * width + w]);
fprintf(stderr, "\n");
}
#endif
if (memcmp(imlib_data, data, width * height * sizeof(uint32_t)) != 0)
{
fprintf(stderr, "Imlib and RPNG differs!\n");
return 5;
}
else
fprintf(stderr, "Imlib and RPNG are equivalent!\n");
imlib_free_image();
#endif
free(data);
return 0;
}
int main(int argc, char *argv[])
{
const char *in_path = "/tmp/test.png";
if (argc > 2)
{
fprintf(stderr, "Usage: %s <png file>\n", argv[0]);
return 1;
}
if (argc == 2)
in_path = argv[1];
fprintf(stderr, "Doing tests...\n");
if (test_rpng(in_path) != 0)
{
fprintf(stderr, "Test failed.\n");
return -1;
}
return 0;
}

View File

@ -0,0 +1,96 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2015 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <formats/tga.h>
#include <formats/image.h>
bool rtga_image_load_shift(uint8_t *buf,
void *data,
unsigned a_shift, unsigned r_shift,
unsigned g_shift, unsigned b_shift)
{
unsigned i, bits, size, bits_mul;
uint8_t info[6] = {0};
unsigned width = 0;
unsigned height = 0;
const uint8_t *tmp = NULL;
struct texture_image *out_img = (struct texture_image*)data;
if (buf[2] != 2)
{
fprintf(stderr, "TGA image is not uncompressed RGB.\n");
goto error;
}
memcpy(info, buf + 12, 6);
width = info[0] + ((unsigned)info[1] * 256);
height = info[2] + ((unsigned)info[3] * 256);
bits = info[4];
fprintf(stderr, "Loaded TGA: (%ux%u @ %u bpp)\n", width, height, bits);
size = width * height * sizeof(uint32_t);
out_img->pixels = (uint32_t*)malloc(size);
out_img->width = width;
out_img->height = height;
if (!out_img->pixels)
{
fprintf(stderr, "Failed to allocate TGA pixels.\n");
goto error;
}
tmp = buf + 18;
bits_mul = 3;
if (bits != 32 && bits != 24)
{
fprintf(stderr, "Bit depth of TGA image is wrong. Only 32-bit and 24-bit supported.\n");
goto error;
}
if (bits == 32)
bits_mul = 4;
for (i = 0; i < width * height; i++)
{
uint32_t b = tmp[i * bits_mul + 0];
uint32_t g = tmp[i * bits_mul + 1];
uint32_t r = tmp[i * bits_mul + 2];
uint32_t a = tmp[i * bits_mul + 3];
if (bits == 24)
a = 0xff;
out_img->pixels[i] = (a << a_shift) |
(r << r_shift) | (g << g_shift) | (b << b_shift);
}
return true;
error:
if (out_img->pixels)
free(out_img->pixels);
out_img->pixels = NULL;
out_img->width = out_img->height = 0;
return false;
}

View File

@ -0,0 +1,20 @@
TARGET := rxml
SOURCES := $(wildcard *.c)
OBJS := $(SOURCES:.c=.o)
CFLAGS += -DRXML_TEST -Wall -pedantic -std=gnu99 -O0 -g -I../../include
all: $(TARGET)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(TARGET) $(OBJS)
.PHONY: clean

View File

@ -0,0 +1,490 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rxml.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <formats/rxml.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdint.h>
#include <boolean.h>
#include <compat/posix_string.h>
struct rxml_document
{
struct rxml_node *root_node;
};
struct rxml_node *rxml_root_node(rxml_document_t *doc)
{
if (doc)
return doc->root_node;
return NULL;
}
static void rxml_free_node(struct rxml_node *node)
{
struct rxml_node *head = NULL;
struct rxml_attrib_node *attrib_node_head = NULL;
if (!node)
return;
for (head = node->children; head; )
{
struct rxml_node *next_node = (struct rxml_node*)head->next;
rxml_free_node(head);
head = next_node;
}
for (attrib_node_head = node->attrib; attrib_node_head; )
{
struct rxml_attrib_node *next_attrib = NULL;
if (!attrib_node_head)
continue;
next_attrib = (struct rxml_attrib_node*)attrib_node_head->next;
if (!next_attrib)
continue;
if (attrib_node_head->attrib)
free(attrib_node_head->attrib);
if (attrib_node_head->value)
free(attrib_node_head->value);
if (attrib_node_head)
free(attrib_node_head);
attrib_node_head = next_attrib;
}
if (node->name)
free(node->name);
if (node->data)
free(node->data);
if (node)
free(node);
}
static bool validate_header(const char **ptr)
{
if (memcmp(*ptr, "<?xml", 5) == 0)
{
const char *eol = strstr(*ptr, "?>\n");
if (!eol)
return false;
/* Always use UTF-8. Don't really care to check. */
*ptr = eol + 3;
return true;
}
return true;
}
static bool range_is_space(const char *begin, const char *end)
{
for (; begin < end; begin++)
if (!isspace(*begin))
return false;
return true;
}
static void skip_spaces(const char **ptr_)
{
const char *ptr = *ptr_;
while (isspace(*ptr))
ptr++;
*ptr_ = ptr;
}
static char *strdup_range(const char *begin, const char *end)
{
ptrdiff_t len = end - begin;
char *ret = (char*)malloc(len + 1);
if (!ret)
return NULL;
memcpy(ret, begin, len);
ret[len] = '\0';
return ret;
}
static char *strdup_range_escape(const char *begin, const char *end)
{
/* Escaping is ignored. Assume we don't deal with that. */
return strdup_range(begin, end);
}
static struct rxml_attrib_node *rxml_parse_attrs(const char *str)
{
char *copy = strdup(str);
if (!copy)
return NULL;
char *last_char = copy + strlen(copy) - 1;
if (*last_char == '/')
*last_char = '\0';
struct rxml_attrib_node *list = NULL;
struct rxml_attrib_node *tail = NULL;
char *attrib = NULL;
char *value = NULL;
char *save;
const char *elem = strtok_r(copy, " \n\t\f\v\r", &save);
while (elem)
{
const char *eq = strstr(elem, "=\"");
if (!eq)
goto end;
const char *end = strrchr(eq + 2, '\"');
if (!end || end != (elem + strlen(elem) - 1))
goto end;
attrib = strdup_range_escape(elem, eq);
value = strdup_range_escape(eq + 2, end);
if (!attrib || !value)
goto end;
struct rxml_attrib_node *new_node =
(struct rxml_attrib_node*)calloc(1, sizeof(*new_node));
if (!new_node)
goto end;
new_node->attrib = attrib;
new_node->value = value;
attrib = NULL;
value = NULL;
if (tail)
{
tail->next = new_node;
tail = new_node;
}
else
list = tail = new_node;
elem = strtok_r(NULL, " \n\t\f\v\r", &save);
}
end:
if (copy)
free(copy);
if (attrib)
free(attrib);
if (value)
free(value);
return list;
}
static char *find_first_space(const char *str)
{
while (*str && !isspace(*str))
str++;
return isspace(*str) ? (char*)str : NULL;
}
static bool rxml_parse_tag(struct rxml_node *node, const char *str)
{
const char *str_ptr = str;
skip_spaces(&str_ptr);
const char *name_end = find_first_space(str_ptr);
if (name_end)
{
node->name = strdup_range(str_ptr, name_end);
if (!node->name || !*node->name)
return false;
node->attrib = rxml_parse_attrs(name_end);
return true;
}
else
{
node->name = strdup(str_ptr);
return node->name && *node->name;
}
}
static struct rxml_node *rxml_parse_node(const char **ptr_)
{
const char *ptr = NULL;
const char *closing = NULL;
char *str = NULL;
bool is_closing = false;
struct rxml_node *node = (struct rxml_node*)calloc(1, sizeof(*node));
if (!node)
return NULL;
skip_spaces(ptr_);
ptr = *ptr_;
if (*ptr != '<')
goto error;
closing = strchr(ptr, '>');
if (!closing)
goto error;
str = strdup_range(ptr + 1, closing);
if (!str)
goto error;
if (!rxml_parse_tag(node, str))
goto error;
/* Are spaces between / and > allowed? */
is_closing = strstr(ptr, "/>") + 1 == closing;
/* Look for more data. Either child nodes or data. */
if (!is_closing)
{
size_t closing_tag_size = strlen(node->name) + 4;
char *closing_tag = (char*)malloc(closing_tag_size);
const char *cdata_start = NULL;
const char *child_start = NULL;
const char *closing_start = NULL;
if (!closing_tag)
goto error;
snprintf(closing_tag, closing_tag_size, "</%s>", node->name);
cdata_start = strstr(closing + 1, "<![CDATA[");
child_start = strchr(closing + 1, '<');
closing_start = strstr(closing + 1, closing_tag);
if (!closing_start)
{
free(closing_tag);
goto error;
}
if (cdata_start && range_is_space(closing + 1, cdata_start))
{
/* CDATA section */
const char *cdata_end = strstr(cdata_start, "]]>");
if (!cdata_end)
{
free(closing_tag);
goto error;
}
node->data = strdup_range(cdata_start +
strlen("<![CDATA["), cdata_end);
}
else if (closing_start && closing_start == child_start) /* Simple Data */
node->data = strdup_range(closing + 1, closing_start);
else
{
/* Parse all child nodes. */
struct rxml_node *list = NULL;
struct rxml_node *tail = NULL;
const char *first_start = NULL;
const char *first_closing = NULL;
ptr = child_start;
first_start = strchr(ptr, '<');
first_closing = strstr(ptr, "</");
while (
first_start &&
first_closing &&
(first_start < first_closing)
)
{
struct rxml_node *new_node = rxml_parse_node(&ptr);
if (!new_node)
{
free(closing_tag);
goto error;
}
if (tail)
{
tail->next = new_node;
tail = new_node;
}
else
list = tail = new_node;
first_start = strchr(ptr, '<');
first_closing = strstr(ptr, "</");
}
node->children = list;
closing_start = strstr(ptr, closing_tag);
if (!closing_start)
{
free(closing_tag);
goto error;
}
}
*ptr_ = closing_start + strlen(closing_tag);
free(closing_tag);
}
else
*ptr_ = closing + 1;
if (str)
free(str);
return node;
error:
if (str)
free(str);
rxml_free_node(node);
return NULL;
}
static char *purge_xml_comments(const char *str)
{
size_t len = strlen(str);
char *new_str = (char*)malloc(len + 1);
if (!new_str)
return NULL;
new_str[len] = '\0';
char *copy_dest = new_str;
const char *copy_src = str;
for (;;)
{
ptrdiff_t copy_len;
const char *comment_start = strstr(copy_src, "<!--");
const char *comment_end = strstr(copy_src, "-->");
if (!comment_start || !comment_end)
break;
copy_len = comment_start - copy_src;
memcpy(copy_dest, copy_src, copy_len);
copy_dest += copy_len;
copy_src = comment_end + strlen("-->");
}
/* Avoid strcpy() as OpenBSD is anal and hates you
* for using it even when it's perfectly safe. */
len = strlen(copy_src);
memcpy(copy_dest, copy_src, len);
copy_dest[len] = '\0';
return new_str;
}
rxml_document_t *rxml_load_document(const char *path)
{
#ifndef RXML_TEST
RARCH_WARN("Using RXML as drop in for libxml2. Behavior might be very buggy.\n");
#endif
char *memory_buffer = NULL;
char *new_memory_buffer = NULL;
const char *mem_ptr = NULL;
long len = 0;
FILE *file = fopen(path, "r");
if (!file)
return NULL;
rxml_document_t *doc = (rxml_document_t*)calloc(1, sizeof(*doc));
if (!doc)
goto error;
fseek(file, 0, SEEK_END);
len = ftell(file);
rewind(file);
memory_buffer = (char*)malloc(len + 1);
if (!memory_buffer)
goto error;
memory_buffer[len] = '\0';
if (fread(memory_buffer, 1, len, file) != (size_t)len)
goto error;
fclose(file);
file = NULL;
mem_ptr = memory_buffer;
if (!validate_header(&mem_ptr))
goto error;
new_memory_buffer = purge_xml_comments(mem_ptr);
if (!new_memory_buffer)
goto error;
free(memory_buffer);
mem_ptr = memory_buffer = new_memory_buffer;
doc->root_node = rxml_parse_node(&mem_ptr);
if (!doc->root_node)
goto error;
free(memory_buffer);
return doc;
error:
free(memory_buffer);
if (file)
fclose(file);
rxml_free_document(doc);
return NULL;
}
void rxml_free_document(rxml_document_t *doc)
{
if (!doc)
return;
if (doc->root_node)
rxml_free_node(doc->root_node);
free(doc);
}
char *rxml_node_attrib(struct rxml_node *node, const char *attrib)
{
struct rxml_attrib_node *attribs = NULL;
for (attribs = node->attrib; attribs; attribs = attribs->next)
{
if (!strcmp(attrib, attribs->attrib))
return attribs->value;
}
return NULL;
}

View File

@ -0,0 +1,67 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rxml_test.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <formats/rxml.h>
#include <stdio.h>
static void print_siblings(struct rxml_node *node, unsigned level)
{
fprintf(stderr, "\n%*sName: %s\n", level * 4, "", node->name);
if (node->data)
fprintf(stderr, "%*sData: %s\n", level * 4, "", node->data);
for (const struct rxml_attrib_node *attrib =
node->attrib; attrib; attrib = attrib->next)
fprintf(stderr, "%*s Attrib: %s = %s\n", level * 4, "",
attrib->attrib, attrib->value);
if (node->children)
print_siblings(node->children, level + 1);
if (node->next)
print_siblings(node->next, level);
}
static void rxml_log_document(const char *path)
{
rxml_document_t *doc = rxml_load_document(path);
if (!doc)
{
fprintf(stderr, "rxml: Failed to load document: %s\n", path);
return;
}
print_siblings(rxml_root_node(doc), 0);
rxml_free_document(doc);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <path>\n", argv[0]);
return 1;
}
rxml_log_document(argv[1]);
}

View File

@ -0,0 +1,251 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (matrix_3x3.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <gfx/math/matrix_3x3.h>
#include <math.h>
#include <string.h>
#define floats_are_equal(x, y) (fabs(x - y) <= 0.00001f * ((x) > (y) ? (y) : (x)))
#define float_is_zero(x) (floats_are_equal((x) + 1, 1))
void matrix_3x3_identity(math_matrix_3x3 *mat)
{
unsigned i;
memset(mat, 0, sizeof(*mat));
for (i = 0; i < 3; i++)
MAT_ELEM_3X3(*mat, i, i) = 1.0f;
}
void matrix_3x3_inits(math_matrix_3x3 *mat,
const float n11, const float n12, const float n13,
const float n21, const float n22, const float n23,
const float n31, const float n32, const float n33)
{
MAT_ELEM_3X3(*mat, 0, 0) = n11;
MAT_ELEM_3X3(*mat, 0, 1) = n12;
MAT_ELEM_3X3(*mat, 0, 2) = n13;
MAT_ELEM_3X3(*mat, 1, 0) = n21;
MAT_ELEM_3X3(*mat, 1, 1) = n22;
MAT_ELEM_3X3(*mat, 1, 2) = n23;
MAT_ELEM_3X3(*mat, 2, 0) = n31;
MAT_ELEM_3X3(*mat, 2, 1) = n32;
MAT_ELEM_3X3(*mat, 2, 2) = n33;
}
void matrix_3x3_transpose(math_matrix_3x3 *out, const math_matrix_3x3 *in)
{
unsigned i, j;
math_matrix_3x3 mat;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
MAT_ELEM_3X3(mat, j, i) = MAT_ELEM_3X3(*in, i, j);
*out = mat;
}
void matrix_3x3_multiply(math_matrix_3x3 *out,
const math_matrix_3x3 *a, const math_matrix_3x3 *b)
{
unsigned r, c, k;
math_matrix_3x3 mat;
for (r = 0; r < 3; r++)
{
for (c = 0; c < 3; c++)
{
float dot = 0.0f;
for (k = 0; k < 3; k++)
dot += MAT_ELEM_3X3(*a, r, k) * MAT_ELEM_3X3(*b, k, c);
MAT_ELEM_3X3(mat, r, c) = dot;
}
}
*out = mat;
}
void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, const float s)
{
unsigned i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
MAT_ELEM_3X3(*mat, i, j) /= s;
}
float matrix_3x3_determinant(const math_matrix_3x3 *mat)
{
float det = MAT_ELEM_3X3(*mat, 0, 0) * (MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 1));
det -= MAT_ELEM_3X3(*mat, 0, 1) * (MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 0));
det += MAT_ELEM_3X3(*mat, 0, 2) * (MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 1) - MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 0));
return det;
}
void matrix_3x3_adjoint(math_matrix_3x3 *mat)
{
math_matrix_3x3 out;
MAT_ELEM_3X3(out, 0, 0) = (MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 1));
MAT_ELEM_3X3(out, 0, 1) = -(MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 2, 1));
MAT_ELEM_3X3(out, 0, 2) = (MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 1, 1) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 1, 1));
MAT_ELEM_3X3(out, 1, 0) = -(MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 0));
MAT_ELEM_3X3(out, 1, 1) = (MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 2, 0));
MAT_ELEM_3X3(out, 1, 2) = -(MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 1, 2) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 1, 0));
MAT_ELEM_3X3(out, 2, 0) = (MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 1) - MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 0));
MAT_ELEM_3X3(out, 2, 1) = -(MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 2, 1) - MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 2, 0));
MAT_ELEM_3X3(out, 2, 2) = (MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 1, 1) - MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 1, 0));
*mat = out;
}
bool matrix_3x3_invert(math_matrix_3x3 *mat)
{
float det = matrix_3x3_determinant(mat);
if (float_is_zero(det))
return false;
matrix_3x3_adjoint(mat);
matrix_3x3_divide_scalar(mat, det);
return true;
}
/**************************************************************************
*
* the following code is Copyright 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
bool matrix_3x3_square_to_quad(const float dx0, const float dy0,
const float dx1, const float dy1,
const float dx3, const float dy3,
const float dx2, const float dy2,
math_matrix_3x3 *mat)
{
float ax = dx0 - dx1 + dx2 - dx3;
float ay = dy0 - dy1 + dy2 - dy3;
if (float_is_zero(ax) && float_is_zero(ay))
{
/* affine case */
matrix_3x3_inits(mat,
dx1 - dx0, dy1 - dy0, 0,
dx2 - dx1, dy2 - dy1, 0,
dx0, dy0, 1);
}
else
{
float a, b, c, d, e, f, g, h;
float ax1 = dx1 - dx2;
float ax2 = dx3 - dx2;
float ay1 = dy1 - dy2;
float ay2 = dy3 - dy2;
/* determinants */
float gtop = ax * ay2 - ax2 * ay;
float htop = ax1 * ay - ax * ay1;
float bottom = ax1 * ay2 - ax2 * ay1;
if (!bottom)
return false;
g = gtop / bottom;
h = htop / bottom;
a = dx1 - dx0 + g * dx1;
b = dx3 - dx0 + h * dx3;
c = dx0;
d = dy1 - dy0 + g * dy1;
e = dy3 - dy0 + h * dy3;
f = dy0;
matrix_3x3_inits(mat,
a, d, g,
b, e, h,
c, f, 1.f);
}
return true;
}
bool matrix_3x3_quad_to_square(const float sx0, const float sy0,
const float sx1, const float sy1,
const float sx2, const float sy2,
const float sx3, const float sy3,
math_matrix_3x3 *mat)
{
if (!matrix_3x3_square_to_quad(sx0, sy0, sx1, sy1,
sx2, sy2, sx3, sy3,
mat))
return false;
return matrix_3x3_invert(mat);
}
bool matrix_3x3_quad_to_quad(const float dx0, const float dy0,
const float dx1, const float dy1,
const float dx2, const float dy2,
const float dx3, const float dy3,
const float sx0, const float sy0,
const float sx1, const float sy1,
const float sx2, const float sy2,
const float sx3, const float sy3,
math_matrix_3x3 *mat)
{
math_matrix_3x3 quad_to_square, square_to_quad;
if (!matrix_3x3_square_to_quad(dx0, dy0, dx1, dy1,
dx2, dy2, dx3, dy3,
&square_to_quad))
return false;
if (!matrix_3x3_quad_to_square(sx0, sy0, sx1, sy1,
sx2, sy2, sx3, sy3,
&quad_to_square))
return false;
matrix_3x3_multiply(mat, &quad_to_square, &square_to_quad);
return true;
}

View File

@ -0,0 +1,192 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (matrix.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <math.h>
#include <gfx/math/matrix_4x4.h>
/*
* Sets mat to an identity matrix
*/
void matrix_4x4_identity(math_matrix_4x4 *mat)
{
unsigned i;
memset(mat, 0, sizeof(*mat));
for (i = 0; i < 4; i++)
MAT_ELEM_4X4(*mat, i, i) = 1.0f;
}
/*
* Sets out to the transposed matrix of in
*/
void matrix_4x4_transpose(math_matrix_4x4 *out, const math_matrix_4x4 *in)
{
unsigned i, j;
math_matrix_4x4 mat;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
MAT_ELEM_4X4(mat, j, i) = MAT_ELEM_4X4(*in, i, j);
*out = mat;
}
/*
* Builds an X-axis rotation matrix
*/
void matrix_4x4_rotate_x(math_matrix_4x4 *mat, float rad)
{
float cosine = cosf(rad);
float sine = sinf(rad);
matrix_4x4_identity(mat);
MAT_ELEM_4X4(*mat, 1, 1) = cosine;
MAT_ELEM_4X4(*mat, 2, 2) = cosine;
MAT_ELEM_4X4(*mat, 1, 2) = -sine;
MAT_ELEM_4X4(*mat, 2, 1) = sine;
}
/*
* Builds a rotation matrix using the
* rotation around the Y-axis.
*/
void matrix_4x4_rotate_y(math_matrix_4x4 *mat, float rad)
{
float cosine = cosf(rad);
float sine = sinf(rad);
matrix_4x4_identity(mat);
MAT_ELEM_4X4(*mat, 0, 0) = cosine;
MAT_ELEM_4X4(*mat, 2, 2) = cosine;
MAT_ELEM_4X4(*mat, 0, 2) = -sine;
MAT_ELEM_4X4(*mat, 2, 0) = sine;
}
/*
* Builds a rotation matrix using the
* rotation around the Z-axis.
*/
void matrix_4x4_rotate_z(math_matrix_4x4 *mat, float rad)
{
float cosine = cosf(rad);
float sine = sinf(rad);
matrix_4x4_identity(mat);
MAT_ELEM_4X4(*mat, 0, 0) = cosine;
MAT_ELEM_4X4(*mat, 1, 1) = cosine;
MAT_ELEM_4X4(*mat, 0, 1) = -sine;
MAT_ELEM_4X4(*mat, 1, 0) = sine;
}
/*
* Creates an orthographic projection matrix.
*/
void matrix_4x4_ortho(math_matrix_4x4 *mat,
float left, float right,
float bottom, float top,
float znear, float zfar)
{
float tx, ty, tz;
matrix_4x4_identity(mat);
tx = -(right + left) / (right - left);
ty = -(top + bottom) / (top - bottom);
tz = -(zfar + znear) / (zfar - znear);
MAT_ELEM_4X4(*mat, 0, 0) = 2.0f / (right - left);
MAT_ELEM_4X4(*mat, 1, 1) = 2.0f / (top - bottom);
MAT_ELEM_4X4(*mat, 2, 2) = -2.0f / (zfar - znear);
MAT_ELEM_4X4(*mat, 0, 3) = tx;
MAT_ELEM_4X4(*mat, 1, 3) = ty;
MAT_ELEM_4X4(*mat, 2, 3) = tz;
}
void matrix_4x4_scale(math_matrix_4x4 *out, float x, float y,
float z)
{
memset(out, 0, sizeof(*out));
MAT_ELEM_4X4(*out, 0, 0) = x;
MAT_ELEM_4X4(*out, 1, 1) = y;
MAT_ELEM_4X4(*out, 2, 2) = z;
MAT_ELEM_4X4(*out, 3, 3) = 1.0f;
}
/*
* Builds a translation matrix. All other elements in
* the matrix will be set to zero except for the
* diagonal which is set to 1.0
*/
void matrix_4x4_translate(math_matrix_4x4 *out, float x,
float y, float z)
{
matrix_4x4_identity(out);
MAT_ELEM_4X4(*out, 0, 3) = x;
MAT_ELEM_4X4(*out, 1, 3) = y;
MAT_ELEM_4X4(*out, 2, 3) = z;
}
/*
* Creates a perspective projection matrix.
*/
void matrix_4x4_projection(math_matrix_4x4 *out, float znear,
float zfar)
{
float delta_z = zfar - znear;
memset(out, 0, sizeof(*out));
MAT_ELEM_4X4(*out, 0, 0) = znear;
MAT_ELEM_4X4(*out, 1, 1) = zfar;
MAT_ELEM_4X4(*out, 2, 2) = (zfar + znear) / delta_z;
MAT_ELEM_4X4(*out, 2, 3) = -2.0f * zfar * znear / delta_z;
MAT_ELEM_4X4(*out, 3, 2) = -1.0f;
}
/*
* Multiplies a with b, stores the result in out
*/
void matrix_4x4_multiply(
math_matrix_4x4 *out,
const math_matrix_4x4 *a,
const math_matrix_4x4 *b)
{
unsigned r, c, k;
math_matrix_4x4 mat;
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
float dot = 0.0f;
for (k = 0; k < 4; k++)
dot += MAT_ELEM_4X4(*a, r, k) * MAT_ELEM_4X4(*b, k, c);
MAT_ELEM_4X4(mat, r, c) = dot;
}
}
*out = mat;
}

View File

@ -0,0 +1,821 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (pixconv.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <retro_inline.h>
#include <gfx/scaler/pixconv.h>
#ifdef SCALER_NO_SIMD
#undef __SSE2__
#endif
#if defined(__SSE2__)
#include <emmintrin.h>
#endif
void conv_rgb565_0rgb1555(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint16_t *output = (uint16_t*)output_;
#if defined(__SSE2_)
int max_width = width - 7;
const __m128i hi_mask = _mm_set1_epi16(0x7fe0);
const __m128i lo_mask = _mm_set1_epi16(0x1f);
#endif
for (h = 0; h < height;
h++, output += out_stride >> 1, input += in_stride >> 1)
{
w = 0;
#if defined(__SSE2_)
for (; w < max_width; w += 8)
{
const __m128i in = _mm_loadu_si128((const __m128i*)(input + w));
__m128i hi = _mm_and_si128(_mm_slli_epi16(in, 1), hi_mask);
__m128i lo = _mm_and_si128(in, lo_mask);
_mm_storeu_si128((__m128i*)(output + w), _mm_or_si128(hi, lo));
}
#endif
for (; w < width; w++)
{
uint16_t col = input[w];
uint16_t hi = (col >> 1) & 0x7fe0;
uint16_t lo = col & 0x1f;
output[w] = hi | lo;
}
}
}
void conv_0rgb1555_rgb565(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint16_t *output = (uint16_t*)output_;
#if defined(__SSE2__)
int max_width = width - 7;
const __m128i hi_mask = _mm_set1_epi16(
(int16_t)((0x1f << 11) | (0x1f << 6)));
const __m128i lo_mask = _mm_set1_epi16(0x1f);
const __m128i glow_mask = _mm_set1_epi16(1 << 5);
#endif
for (h = 0; h < height;
h++, output += out_stride >> 1, input += in_stride >> 1)
{
w = 0;
#if defined(__SSE2__)
for (; w < max_width; w += 8)
{
const __m128i in = _mm_loadu_si128((const __m128i*)(input + w));
__m128i rg = _mm_and_si128(_mm_slli_epi16(in, 1), hi_mask);
__m128i b = _mm_and_si128(in, lo_mask);
__m128i glow = _mm_and_si128(_mm_srli_epi16(in, 4), glow_mask);
_mm_storeu_si128((__m128i*)(output + w),
_mm_or_si128(rg, _mm_or_si128(b, glow)));
}
#endif
for (; w < width; w++)
{
uint16_t col = input[w];
uint16_t rg = (col << 1) & ((0x1f << 11) | (0x1f << 6));
uint16_t b = col & 0x1f;
uint16_t glow = (col >> 4) & (1 << 5);
output[w] = rg | b | glow;
}
}
}
void conv_0rgb1555_argb8888(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint32_t *output = (uint32_t*)output_;
#ifdef __SSE2__
const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10);
const __m128i pix_mask_gb = _mm_set1_epi16(0x1f << 5);
const __m128i mul15_mid = _mm_set1_epi16(0x4200);
const __m128i mul15_hi = _mm_set1_epi16(0x0210);
const __m128i a = _mm_set1_epi16(0x00ff);
int max_width = width - 7;
#endif
for (h = 0; h < height;
h++, output += out_stride >> 2, input += in_stride >> 1)
{
w = 0;
#ifdef __SSE2__
for (; w < max_width; w += 8)
{
__m128i res_lo_bg, res_hi_bg;
__m128i res_lo_ra, res_hi_ra;
__m128i res_lo, res_hi;
const __m128i in = _mm_loadu_si128((const __m128i*)(input + w));
__m128i r = _mm_and_si128(in, pix_mask_r);
__m128i g = _mm_and_si128(in, pix_mask_gb);
__m128i b = _mm_and_si128(_mm_slli_epi16(in, 5), pix_mask_gb);
r = _mm_mulhi_epi16(r, mul15_hi);
g = _mm_mulhi_epi16(g, mul15_mid);
b = _mm_mulhi_epi16(b, mul15_mid);
res_lo_bg = _mm_unpacklo_epi8(b, g);
res_hi_bg = _mm_unpackhi_epi8(b, g);
res_lo_ra = _mm_unpacklo_epi8(r, a);
res_hi_ra = _mm_unpackhi_epi8(r, a);
res_lo = _mm_or_si128(res_lo_bg,
_mm_slli_si128(res_lo_ra, 2));
res_hi = _mm_or_si128(res_hi_bg,
_mm_slli_si128(res_hi_ra, 2));
_mm_storeu_si128((__m128i*)(output + w + 0), res_lo);
_mm_storeu_si128((__m128i*)(output + w + 4), res_hi);
}
#endif
for (; w < width; w++)
{
uint32_t col = input[w];
uint32_t r = (col >> 10) & 0x1f;
uint32_t g = (col >> 5) & 0x1f;
uint32_t b = (col >> 0) & 0x1f;
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0);
}
}
}
void conv_rgb565_argb8888(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint32_t *output = (uint32_t*)output_;
#if defined(__SSE2__)
const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10);
const __m128i pix_mask_g = _mm_set1_epi16(0x3f << 5);
const __m128i pix_mask_b = _mm_set1_epi16(0x1f << 5);
const __m128i mul16_r = _mm_set1_epi16(0x0210);
const __m128i mul16_g = _mm_set1_epi16(0x2080);
const __m128i mul16_b = _mm_set1_epi16(0x4200);
const __m128i a = _mm_set1_epi16(0x00ff);
int max_width = width - 7;
#endif
for (h = 0; h < height;
h++, output += out_stride >> 2, input += in_stride >> 1)
{
w = 0;
#if defined(__SSE2__)
for (; w < max_width; w += 8)
{
__m128i res_lo, res_hi;
__m128i res_lo_bg, res_hi_bg, res_lo_ra, res_hi_ra;
const __m128i in = _mm_loadu_si128((const __m128i*)(input + w));
__m128i r = _mm_and_si128(_mm_srli_epi16(in, 1), pix_mask_r);
__m128i g = _mm_and_si128(in, pix_mask_g);
__m128i b = _mm_and_si128(_mm_slli_epi16(in, 5), pix_mask_b);
r = _mm_mulhi_epi16(r, mul16_r);
g = _mm_mulhi_epi16(g, mul16_g);
b = _mm_mulhi_epi16(b, mul16_b);
res_lo_bg = _mm_unpacklo_epi8(b, g);
res_hi_bg = _mm_unpackhi_epi8(b, g);
res_lo_ra = _mm_unpacklo_epi8(r, a);
res_hi_ra = _mm_unpackhi_epi8(r, a);
res_lo = _mm_or_si128(res_lo_bg,
_mm_slli_si128(res_lo_ra, 2));
res_hi = _mm_or_si128(res_hi_bg,
_mm_slli_si128(res_hi_ra, 2));
_mm_storeu_si128((__m128i*)(output + w + 0), res_lo);
_mm_storeu_si128((__m128i*)(output + w + 4), res_hi);
}
#endif
for (; w < width; w++)
{
uint32_t col = input[w];
uint32_t r = (col >> 11) & 0x1f;
uint32_t g = (col >> 5) & 0x3f;
uint32_t b = (col >> 0) & 0x1f;
r = (r << 3) | (r >> 2);
g = (g << 2) | (g >> 4);
b = (b << 3) | (b >> 2);
output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0);
}
}
}
void conv_argb8888_rgba4444(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint32_t *input = (const uint32_t*)input_;
uint16_t *output = (uint16_t*)output_;
for (h = 0; h < height;
h++, output += out_stride >> 2, input += in_stride >> 1)
{
for (w = 0; w < width; w++)
{
uint32_t col = input[w];
uint32_t r = (col >> 16) & 0xf;
uint32_t g = (col >> 8) & 0xf;
uint32_t b = (col) & 0xf;
uint32_t a = (col >> 24) & 0xf;
r = (r >> 4) | r;
g = (g >> 4) | g;
b = (b >> 4) | b;
a = (a >> 4) | a;
output[w] = (r << 12) | (g << 8) | (b << 4) | a;
}
}
}
void conv_rgba4444_argb8888(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint32_t *output = (uint32_t*)output_;
for (h = 0; h < height;
h++, output += out_stride >> 2, input += in_stride >> 1)
{
for (w = 0; w < width; w++)
{
uint32_t col = input[w];
uint32_t r = (col >> 12) & 0xf;
uint32_t g = (col >> 8) & 0xf;
uint32_t b = (col >> 4) & 0xf;
uint32_t a = (col >> 0) & 0xf;
r = (r << 4) | r;
g = (g << 4) | g;
b = (b << 4) | b;
a = (a << 4) | a;
output[w] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
}
}
}
void conv_rgba4444_rgb565(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint16_t *output = (uint16_t*)output_;
for (h = 0; h < height;
h++, output += out_stride >> 1, input += in_stride >> 1)
{
for (w = 0; w < width; w++)
{
uint32_t col = input[w];
uint32_t r = (col >> 12) & 0xf;
uint32_t g = (col >> 8) & 0xf;
uint32_t b = (col >> 4) & 0xf;
output[w] = (r << 12) | (g << 7) | (b << 1);
}
}
}
#if defined(__SSE2__)
/* :( TODO: Make this saner. */
static INLINE void store_bgr24_sse2(void *output, __m128i a,
__m128i b, __m128i c, __m128i d)
{
const __m128i mask_0 = _mm_set_epi32(0, 0, 0, 0x00ffffff);
const __m128i mask_1 = _mm_set_epi32(0, 0, 0x00ffffff, 0);
const __m128i mask_2 = _mm_set_epi32(0, 0x00ffffff, 0, 0);
const __m128i mask_3 = _mm_set_epi32(0x00ffffff, 0, 0, 0);
__m128i a0 = _mm_and_si128(a, mask_0);
__m128i a1 = _mm_srli_si128(_mm_and_si128(a, mask_1), 1);
__m128i a2 = _mm_srli_si128(_mm_and_si128(a, mask_2), 2);
__m128i a3 = _mm_srli_si128(_mm_and_si128(a, mask_3), 3);
__m128i a4 = _mm_slli_si128(_mm_and_si128(b, mask_0), 12);
__m128i a5 = _mm_slli_si128(_mm_and_si128(b, mask_1), 11);
__m128i b0 = _mm_srli_si128(_mm_and_si128(b, mask_1), 5);
__m128i b1 = _mm_srli_si128(_mm_and_si128(b, mask_2), 6);
__m128i b2 = _mm_srli_si128(_mm_and_si128(b, mask_3), 7);
__m128i b3 = _mm_slli_si128(_mm_and_si128(c, mask_0), 8);
__m128i b4 = _mm_slli_si128(_mm_and_si128(c, mask_1), 7);
__m128i b5 = _mm_slli_si128(_mm_and_si128(c, mask_2), 6);
__m128i c0 = _mm_srli_si128(_mm_and_si128(c, mask_2), 10);
__m128i c1 = _mm_srli_si128(_mm_and_si128(c, mask_3), 11);
__m128i c2 = _mm_slli_si128(_mm_and_si128(d, mask_0), 4);
__m128i c3 = _mm_slli_si128(_mm_and_si128(d, mask_1), 3);
__m128i c4 = _mm_slli_si128(_mm_and_si128(d, mask_2), 2);
__m128i c5 = _mm_slli_si128(_mm_and_si128(d, mask_3), 1);
__m128i *out = (__m128i*)output;
_mm_storeu_si128(out + 0,
_mm_or_si128(a0, _mm_or_si128(a1, _mm_or_si128(a2,
_mm_or_si128(a3, _mm_or_si128(a4, a5))))));
_mm_storeu_si128(out + 1,
_mm_or_si128(b0, _mm_or_si128(b1, _mm_or_si128(b2,
_mm_or_si128(b3, _mm_or_si128(b4, b5))))));
_mm_storeu_si128(out + 2,
_mm_or_si128(c0, _mm_or_si128(c1, _mm_or_si128(c2,
_mm_or_si128(c3, _mm_or_si128(c4, c5))))));
}
#endif
void conv_0rgb1555_bgr24(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint8_t *output = (uint8_t*)output_;
#if defined(__SSE2__)
const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10);
const __m128i pix_mask_gb = _mm_set1_epi16(0x1f << 5);
const __m128i mul15_mid = _mm_set1_epi16(0x4200);
const __m128i mul15_hi = _mm_set1_epi16(0x0210);
const __m128i a = _mm_set1_epi16(0x00ff);
int max_width = width - 15;
#endif
for (h = 0; h < height;
h++, output += out_stride, input += in_stride >> 1)
{
uint8_t *out = output;
w = 0;
#if defined(__SSE2__)
for (; w < max_width; w += 16, out += 48)
{
__m128i res_lo_bg0, res_lo_bg1, res_hi_bg0, res_hi_bg1,
res_lo_ra0, res_lo_ra1, res_hi_ra0, res_hi_ra1,
res_lo0, res_lo1, res_hi0, res_hi1;
const __m128i in0 = _mm_loadu_si128((const __m128i*)(input + w + 0));
const __m128i in1 = _mm_loadu_si128((const __m128i*)(input + w + 8));
__m128i r0 = _mm_and_si128(in0, pix_mask_r);
__m128i r1 = _mm_and_si128(in1, pix_mask_r);
__m128i g0 = _mm_and_si128(in0, pix_mask_gb);
__m128i g1 = _mm_and_si128(in1, pix_mask_gb);
__m128i b0 = _mm_and_si128(_mm_slli_epi16(in0, 5), pix_mask_gb);
__m128i b1 = _mm_and_si128(_mm_slli_epi16(in1, 5), pix_mask_gb);
r0 = _mm_mulhi_epi16(r0, mul15_hi);
r1 = _mm_mulhi_epi16(r1, mul15_hi);
g0 = _mm_mulhi_epi16(g0, mul15_mid);
g1 = _mm_mulhi_epi16(g1, mul15_mid);
b0 = _mm_mulhi_epi16(b0, mul15_mid);
b1 = _mm_mulhi_epi16(b1, mul15_mid);
res_lo_bg0 = _mm_unpacklo_epi8(b0, g0);
res_lo_bg1 = _mm_unpacklo_epi8(b1, g1);
res_hi_bg0 = _mm_unpackhi_epi8(b0, g0);
res_hi_bg1 = _mm_unpackhi_epi8(b1, g1);
res_lo_ra0 = _mm_unpacklo_epi8(r0, a);
res_lo_ra1 = _mm_unpacklo_epi8(r1, a);
res_hi_ra0 = _mm_unpackhi_epi8(r0, a);
res_hi_ra1 = _mm_unpackhi_epi8(r1, a);
res_lo0 = _mm_or_si128(res_lo_bg0,
_mm_slli_si128(res_lo_ra0, 2));
res_lo1 = _mm_or_si128(res_lo_bg1,
_mm_slli_si128(res_lo_ra1, 2));
res_hi0 = _mm_or_si128(res_hi_bg0,
_mm_slli_si128(res_hi_ra0, 2));
res_hi1 = _mm_or_si128(res_hi_bg1,
_mm_slli_si128(res_hi_ra1, 2));
/* Non-POT pixel sizes ftl :( */
store_bgr24_sse2(out, res_lo0, res_hi0, res_lo1, res_hi1);
}
#endif
for (; w < width; w++)
{
uint32_t col = input[w];
uint32_t b = (col >> 0) & 0x1f;
uint32_t g = (col >> 5) & 0x1f;
uint32_t r = (col >> 10) & 0x1f;
b = (b << 3) | (b >> 2);
g = (g << 3) | (g >> 2);
r = (r << 3) | (r >> 2);
*out++ = b;
*out++ = g;
*out++ = r;
}
}
}
void conv_rgb565_bgr24(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint16_t *input = (const uint16_t*)input_;
uint8_t *output = (uint8_t*)output_;
#if defined(__SSE2__)
const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10);
const __m128i pix_mask_g = _mm_set1_epi16(0x3f << 5);
const __m128i pix_mask_b = _mm_set1_epi16(0x1f << 5);
const __m128i mul16_r = _mm_set1_epi16(0x0210);
const __m128i mul16_g = _mm_set1_epi16(0x2080);
const __m128i mul16_b = _mm_set1_epi16(0x4200);
const __m128i a = _mm_set1_epi16(0x00ff);
int max_width = width - 15;
#endif
for (h = 0; h < height; h++, output += out_stride, input += in_stride >> 1)
{
uint8_t *out = output;
w = 0;
#if defined(__SSE2__)
for (; w < max_width; w += 16, out += 48)
{
__m128i res_lo_bg0, res_hi_bg0, res_lo_ra0, res_hi_ra0;
__m128i res_lo_bg1, res_hi_bg1, res_lo_ra1, res_hi_ra1;
__m128i res_lo0, res_hi0, res_lo1, res_hi1;
const __m128i in0 = _mm_loadu_si128((const __m128i*)(input + w));
const __m128i in1 = _mm_loadu_si128((const __m128i*)(input + w + 8));
__m128i r0 = _mm_and_si128(_mm_srli_epi16(in0, 1), pix_mask_r);
__m128i g0 = _mm_and_si128(in0, pix_mask_g);
__m128i b0 = _mm_and_si128(_mm_slli_epi16(in0, 5), pix_mask_b);
__m128i r1 = _mm_and_si128(_mm_srli_epi16(in1, 1), pix_mask_r);
__m128i g1 = _mm_and_si128(in1, pix_mask_g);
__m128i b1 = _mm_and_si128(_mm_slli_epi16(in1, 5), pix_mask_b);
r0 = _mm_mulhi_epi16(r0, mul16_r);
g0 = _mm_mulhi_epi16(g0, mul16_g);
b0 = _mm_mulhi_epi16(b0, mul16_b);
r1 = _mm_mulhi_epi16(r1, mul16_r);
g1 = _mm_mulhi_epi16(g1, mul16_g);
b1 = _mm_mulhi_epi16(b1, mul16_b);
res_lo_bg0 = _mm_unpacklo_epi8(b0, g0);
res_hi_bg0 = _mm_unpackhi_epi8(b0, g0);
res_lo_ra0 = _mm_unpacklo_epi8(r0, a);
res_hi_ra0 = _mm_unpackhi_epi8(r0, a);
res_lo_bg1 = _mm_unpacklo_epi8(b1, g1);
res_hi_bg1 = _mm_unpackhi_epi8(b1, g1);
res_lo_ra1 = _mm_unpacklo_epi8(r1, a);
res_hi_ra1 = _mm_unpackhi_epi8(r1, a);
res_lo0 = _mm_or_si128(res_lo_bg0,
_mm_slli_si128(res_lo_ra0, 2));
res_hi0 = _mm_or_si128(res_hi_bg0,
_mm_slli_si128(res_hi_ra0, 2));
res_lo1 = _mm_or_si128(res_lo_bg1,
_mm_slli_si128(res_lo_ra1, 2));
res_hi1 = _mm_or_si128(res_hi_bg1,
_mm_slli_si128(res_hi_ra1, 2));
store_bgr24_sse2(out, res_lo0, res_hi0, res_lo1, res_hi1);
}
#endif
for (; w < width; w++)
{
uint32_t col = input[w];
uint32_t r = (col >> 11) & 0x1f;
uint32_t g = (col >> 5) & 0x3f;
uint32_t b = (col >> 0) & 0x1f;
r = (r << 3) | (r >> 2);
g = (g << 2) | (g >> 4);
b = (b << 3) | (b >> 2);
*out++ = b;
*out++ = g;
*out++ = r;
}
}
}
void conv_bgr24_argb8888(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint8_t *input = (const uint8_t*)input_;
uint32_t *output = (uint32_t*)output_;
for (h = 0; h < height;
h++, output += out_stride >> 2, input += in_stride)
{
const uint8_t *inp = input;
for (w = 0; w < width; w++)
{
uint32_t b = *inp++;
uint32_t g = *inp++;
uint32_t r = *inp++;
output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0);
}
}
}
void conv_argb8888_0rgb1555(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint32_t *input = (const uint32_t*)input_;
uint16_t *output = (uint16_t*)output_;
for (h = 0; h < height;
h++, output += out_stride >> 1, input += in_stride >> 2)
{
for (w = 0; w < width; w++)
{
uint32_t col = input[w];
uint16_t r = (col >> 19) & 0x1f;
uint16_t g = (col >> 11) & 0x1f;
uint16_t b = (col >> 3) & 0x1f;
output[w] = (r << 10) | (g << 5) | (b << 0);
}
}
}
void conv_argb8888_bgr24(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint32_t *input = (const uint32_t*)input_;
uint8_t *output = (uint8_t*)output_;
#if defined(__SSE2__)
int max_width = width - 15;
#endif
for (h = 0; h < height;
h++, output += out_stride, input += in_stride >> 2)
{
uint8_t *out = output;
w = 0;
#if defined(__SSE2__)
for (; w < max_width; w += 16, out += 48)
{
store_bgr24_sse2(out,
_mm_loadu_si128((const __m128i*)(input + w + 0)),
_mm_loadu_si128((const __m128i*)(input + w + 4)),
_mm_loadu_si128((const __m128i*)(input + w + 8)),
_mm_loadu_si128((const __m128i*)(input + w + 12)));
}
#endif
for (; w < width; w++)
{
uint32_t col = input[w];
*out++ = (uint8_t)(col >> 0);
*out++ = (uint8_t)(col >> 8);
*out++ = (uint8_t)(col >> 16);
}
}
}
void conv_argb8888_abgr8888(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint32_t *input = (const uint32_t*)input_;
uint32_t *output = (uint32_t*)output_;
for (h = 0; h < height;
h++, output += out_stride >> 2, input += in_stride >> 2)
{
for (w = 0; w < width; w++)
{
uint32_t col = input[w];
output[w] = ((col << 16) & 0xff0000) |
((col >> 16) & 0xff) | (col & 0xff00ff00);
}
}
}
#define YUV_SHIFT 6
#define YUV_OFFSET (1 << (YUV_SHIFT - 1))
#define YUV_MAT_Y (1 << 6)
#define YUV_MAT_U_G (-22)
#define YUV_MAT_U_B (113)
#define YUV_MAT_V_R (90)
#define YUV_MAT_V_G (-46)
void conv_yuyv_argb8888(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h, w;
const uint8_t *input = (const uint8_t*)input_;
uint32_t *output = (uint32_t*)output_;
#if defined(__SSE2__)
const __m128i mask_y = _mm_set1_epi16(0xffu);
const __m128i mask_u = _mm_set1_epi32(0xffu << 8);
const __m128i mask_v = _mm_set1_epi32(0xffu << 24);
const __m128i chroma_offset = _mm_set1_epi16(128);
const __m128i round_offset = _mm_set1_epi16(YUV_OFFSET);
const __m128i yuv_mul = _mm_set1_epi16(YUV_MAT_Y);
const __m128i u_g_mul = _mm_set1_epi16(YUV_MAT_U_G);
const __m128i u_b_mul = _mm_set1_epi16(YUV_MAT_U_B);
const __m128i v_r_mul = _mm_set1_epi16(YUV_MAT_V_R);
const __m128i v_g_mul = _mm_set1_epi16(YUV_MAT_V_G);
const __m128i a = _mm_cmpeq_epi16(
_mm_setzero_si128(), _mm_setzero_si128());
#endif
for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride)
{
const uint8_t *src = input;
uint32_t *dst = output;
w = 0;
#if defined(__SSE2__)
/* Each loop processes 16 pixels. */
for (; w + 16 <= width; w += 16, src += 32, dst += 16)
{
__m128i u, v, u0_g, u1_g, u0_b, u1_b, v0_r, v1_r, v0_g, v1_g,
r0, g0, b0, r1, g1, b1;
__m128i res_lo_bg, res_hi_bg, res_lo_ra, res_hi_ra;
__m128i res0, res1, res2, res3;
__m128i yuv0 = _mm_loadu_si128((const __m128i*)(src + 0)); /* [Y0, U0, Y1, V0, Y2, U1, Y3, V1, ...] */
__m128i yuv1 = _mm_loadu_si128((const __m128i*)(src + 16)); /* [Y0, U0, Y1, V0, Y2, U1, Y3, V1, ...] */
__m128i _y0 = _mm_and_si128(yuv0, mask_y); /* [Y0, Y1, Y2, ...] (16-bit) */
__m128i u0 = _mm_and_si128(yuv0, mask_u); /* [0, U0, 0, 0, 0, U1, 0, 0, ...] */
__m128i v0 = _mm_and_si128(yuv0, mask_v); /* [0, 0, 0, V1, 0, , 0, V1, ...] */
__m128i _y1 = _mm_and_si128(yuv1, mask_y); /* [Y0, Y1, Y2, ...] (16-bit) */
__m128i u1 = _mm_and_si128(yuv1, mask_u); /* [0, U0, 0, 0, 0, U1, 0, 0, ...] */
__m128i v1 = _mm_and_si128(yuv1, mask_v); /* [0, 0, 0, V1, 0, , 0, V1, ...] */
/* Juggle around to get U and V in the same 16-bit format as Y. */
u0 = _mm_srli_si128(u0, 1);
v0 = _mm_srli_si128(v0, 3);
u1 = _mm_srli_si128(u1, 1);
v1 = _mm_srli_si128(v1, 3);
u = _mm_packs_epi32(u0, u1);
v = _mm_packs_epi32(v0, v1);
/* Apply YUV offsets (U, V) -= (-128, -128). */
u = _mm_sub_epi16(u, chroma_offset);
v = _mm_sub_epi16(v, chroma_offset);
/* Upscale chroma horizontally (nearest). */
u0 = _mm_unpacklo_epi16(u, u);
u1 = _mm_unpackhi_epi16(u, u);
v0 = _mm_unpacklo_epi16(v, v);
v1 = _mm_unpackhi_epi16(v, v);
/* Apply transformations. */
_y0 = _mm_mullo_epi16(_y0, yuv_mul);
_y1 = _mm_mullo_epi16(_y1, yuv_mul);
u0_g = _mm_mullo_epi16(u0, u_g_mul);
u1_g = _mm_mullo_epi16(u1, u_g_mul);
u0_b = _mm_mullo_epi16(u0, u_b_mul);
u1_b = _mm_mullo_epi16(u1, u_b_mul);
v0_r = _mm_mullo_epi16(v0, v_r_mul);
v1_r = _mm_mullo_epi16(v1, v_r_mul);
v0_g = _mm_mullo_epi16(v0, v_g_mul);
v1_g = _mm_mullo_epi16(v1, v_g_mul);
/* Add contibutions from the transformed components. */
r0 = _mm_srai_epi16(_mm_adds_epi16(_mm_adds_epi16(_y0, v0_r),
round_offset), YUV_SHIFT);
g0 = _mm_srai_epi16(_mm_adds_epi16(
_mm_adds_epi16(_mm_adds_epi16(_y0, v0_g), u0_g), round_offset), YUV_SHIFT);
b0 = _mm_srai_epi16(_mm_adds_epi16(
_mm_adds_epi16(_y0, u0_b), round_offset), YUV_SHIFT);
r1 = _mm_srai_epi16(_mm_adds_epi16(
_mm_adds_epi16(_y1, v1_r), round_offset), YUV_SHIFT);
g1 = _mm_srai_epi16(_mm_adds_epi16(
_mm_adds_epi16(_mm_adds_epi16(_y1, v1_g), u1_g), round_offset), YUV_SHIFT);
b1 = _mm_srai_epi16(_mm_adds_epi16(
_mm_adds_epi16(_y1, u1_b), round_offset), YUV_SHIFT);
/* Saturate into 8-bit. */
r0 = _mm_packus_epi16(r0, r1);
g0 = _mm_packus_epi16(g0, g1);
b0 = _mm_packus_epi16(b0, b1);
/* Interleave into ARGB. */
res_lo_bg = _mm_unpacklo_epi8(b0, g0);
res_hi_bg = _mm_unpackhi_epi8(b0, g0);
res_lo_ra = _mm_unpacklo_epi8(r0, a);
res_hi_ra = _mm_unpackhi_epi8(r0, a);
res0 = _mm_unpacklo_epi16(res_lo_bg, res_lo_ra);
res1 = _mm_unpackhi_epi16(res_lo_bg, res_lo_ra);
res2 = _mm_unpacklo_epi16(res_hi_bg, res_hi_ra);
res3 = _mm_unpackhi_epi16(res_hi_bg, res_hi_ra);
_mm_storeu_si128((__m128i*)(dst + 0), res0);
_mm_storeu_si128((__m128i*)(dst + 4), res1);
_mm_storeu_si128((__m128i*)(dst + 8), res2);
_mm_storeu_si128((__m128i*)(dst + 12), res3);
}
#endif
/* Finish off the rest (if any) in C. */
for (; w < width; w += 2, src += 4, dst += 2)
{
int _y0 = src[0];
int u = src[1] - 128;
int _y1 = src[2];
int v = src[3] - 128;
uint8_t r0 = clamp_8bit((YUV_MAT_Y * _y0 + YUV_MAT_V_R * v + YUV_OFFSET) >> YUV_SHIFT);
uint8_t g0 = clamp_8bit((YUV_MAT_Y * _y0 + YUV_MAT_U_G * u + YUV_MAT_V_G * v + YUV_OFFSET) >> YUV_SHIFT);
uint8_t b0 = clamp_8bit((YUV_MAT_Y * _y0 + YUV_MAT_U_B * u + YUV_OFFSET) >> YUV_SHIFT);
uint8_t r1 = clamp_8bit((YUV_MAT_Y * _y1 + YUV_MAT_V_R * v + YUV_OFFSET) >> YUV_SHIFT);
uint8_t g1 = clamp_8bit((YUV_MAT_Y * _y1 + YUV_MAT_U_G * u + YUV_MAT_V_G * v + YUV_OFFSET) >> YUV_SHIFT);
uint8_t b1 = clamp_8bit((YUV_MAT_Y * _y1 + YUV_MAT_U_B * u + YUV_OFFSET) >> YUV_SHIFT);
dst[0] = 0xff000000u | (r0 << 16) | (g0 << 8) | (b0 << 0);
dst[1] = 0xff000000u | (r1 << 16) | (g1 << 8) | (b1 << 0);
}
}
}
void conv_copy(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride)
{
int h;
int copy_len = abs(out_stride);
const uint8_t *input = (const uint8_t*)input_;
uint8_t *output = (uint8_t*)output_;
if (abs(in_stride) < copy_len)
copy_len = abs(in_stride);
for (h = 0; h < height;
h++, output += out_stride, input += in_stride)
memcpy(output, input, copy_len);
}

View File

@ -0,0 +1,379 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (scaler.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <gfx/scaler/scaler.h>
#include <gfx/scaler/scaler_int.h>
#include <gfx/scaler/filter.h>
#include <gfx/scaler/pixconv.h>
/**
* scaler_alloc:
* @elem_size : size of the elements to be used.
* @siz : size of the image that the scaler needs to handle.
*
* Allocate and returns a scaler object.
*
* Returns: pointer to a scaler object of type 'void *' on success,
* NULL in case of error. Has to be freed manually.
**/
void *scaler_alloc(size_t elem_size, size_t size)
{
void *ptr = calloc(elem_size, size);
if (!ptr)
return NULL;
return ptr;
}
/**
* scaler_free:
* @ptr : pointer to scaler object.
*
* Frees a scaler object.
**/
void scaler_free(void *ptr)
{
if (ptr)
free(ptr);
}
static bool allocate_frames(struct scaler_ctx *ctx)
{
ctx->scaled.stride = ((ctx->out_width + 7) & ~7) * sizeof(uint64_t);
ctx->scaled.width = ctx->out_width;
ctx->scaled.height = ctx->in_height;
ctx->scaled.frame = (uint64_t*)
scaler_alloc(sizeof(uint64_t),
(ctx->scaled.stride * ctx->scaled.height) >> 3);
if (!ctx->scaled.frame)
return false;
if (ctx->in_fmt != SCALER_FMT_ARGB8888)
{
ctx->input.stride = ((ctx->in_width + 7) & ~7) * sizeof(uint32_t);
ctx->input.frame = (uint32_t*)
scaler_alloc(sizeof(uint32_t),
(ctx->input.stride * ctx->in_height) >> 2);
if (!ctx->input.frame)
return false;
}
if (ctx->out_fmt != SCALER_FMT_ARGB8888)
{
ctx->output.stride = ((ctx->out_width + 7) & ~7) * sizeof(uint32_t);
ctx->output.frame = (uint32_t*)
scaler_alloc(sizeof(uint32_t),
(ctx->output.stride * ctx->out_height) >> 2);
if (!ctx->output.frame)
return false;
}
return true;
}
/**
* set_direct_pix_conv:
* @ctx : pointer to scaler context object.
*
* Bind a pixel converter callback function to the 'direct_pixconv' function pointer
* of the scaler context object.
*
* Returns: true if a pixel converter function callback could be bound, false if not.
* If false, the function callback 'direct_pixconv' is still unbound.
**/
static bool set_direct_pix_conv(struct scaler_ctx *ctx)
{
if (ctx->in_fmt == ctx->out_fmt)
{
ctx->direct_pixconv = conv_copy;
return true;
}
switch (ctx->in_fmt)
{
case SCALER_FMT_0RGB1555:
switch (ctx->out_fmt)
{
case SCALER_FMT_ARGB8888:
ctx->direct_pixconv = conv_0rgb1555_argb8888;
break;
case SCALER_FMT_RGB565:
ctx->direct_pixconv = conv_0rgb1555_rgb565;
break;
case SCALER_FMT_BGR24:
ctx->direct_pixconv = conv_0rgb1555_bgr24;
break;
default:
break;
}
break;
case SCALER_FMT_RGB565:
switch (ctx->out_fmt)
{
case SCALER_FMT_ARGB8888:
ctx->direct_pixconv = conv_rgb565_argb8888;
break;
case SCALER_FMT_BGR24:
ctx->direct_pixconv = conv_rgb565_bgr24;
break;
case SCALER_FMT_0RGB1555:
ctx->direct_pixconv = conv_rgb565_0rgb1555;
break;
default:
break;
}
break;
case SCALER_FMT_BGR24:
switch (ctx->out_fmt)
{
case SCALER_FMT_ARGB8888:
ctx->direct_pixconv = conv_bgr24_argb8888;
break;
default:
break;
}
break;
case SCALER_FMT_ARGB8888:
switch (ctx->out_fmt)
{
case SCALER_FMT_0RGB1555:
ctx->direct_pixconv = conv_argb8888_0rgb1555;
break;
case SCALER_FMT_BGR24:
ctx->direct_pixconv = conv_argb8888_bgr24;
break;
case SCALER_FMT_ABGR8888:
ctx->direct_pixconv = conv_argb8888_abgr8888;
break;
case SCALER_FMT_RGBA4444:
ctx->direct_pixconv = conv_argb8888_rgba4444;
break;
default:
break;
}
break;
case SCALER_FMT_YUYV:
switch (ctx->out_fmt)
{
case SCALER_FMT_ARGB8888:
ctx->direct_pixconv = conv_yuyv_argb8888;
break;
default:
break;
}
break;
case SCALER_FMT_RGBA4444:
switch (ctx->out_fmt)
{
case SCALER_FMT_ARGB8888:
ctx->direct_pixconv = conv_rgba4444_argb8888;
break;
case SCALER_FMT_RGB565:
ctx->direct_pixconv = conv_rgba4444_rgb565;
break;
default:
break;
}
break;
case SCALER_FMT_ABGR8888:
/* FIXME/TODO */
break;
}
if (!ctx->direct_pixconv)
return false;
return true;
}
static bool set_pix_conv(struct scaler_ctx *ctx)
{
switch (ctx->in_fmt)
{
case SCALER_FMT_ARGB8888:
/* No need to convert :D */
break;
case SCALER_FMT_0RGB1555:
ctx->in_pixconv = conv_0rgb1555_argb8888;
break;
case SCALER_FMT_RGB565:
ctx->in_pixconv = conv_rgb565_argb8888;
break;
case SCALER_FMT_BGR24:
ctx->in_pixconv = conv_bgr24_argb8888;
break;
case SCALER_FMT_RGBA4444:
ctx->in_pixconv = conv_rgba4444_argb8888;
break;
default:
return false;
}
switch (ctx->out_fmt)
{
case SCALER_FMT_ARGB8888:
/* No need to convert :D */
break;
case SCALER_FMT_RGBA4444:
ctx->out_pixconv = conv_argb8888_rgba4444;
break;
case SCALER_FMT_0RGB1555:
ctx->out_pixconv = conv_argb8888_0rgb1555;
break;
case SCALER_FMT_BGR24:
ctx->out_pixconv = conv_argb8888_bgr24;
break;
default:
return false;
}
return true;
}
bool scaler_ctx_gen_filter(struct scaler_ctx *ctx)
{
scaler_ctx_gen_reset(ctx);
if (ctx->in_width == ctx->out_width && ctx->in_height == ctx->out_height)
ctx->unscaled = true; /* Only pixel format conversion ... */
else
{
ctx->scaler_horiz = scaler_argb8888_horiz;
ctx->scaler_vert = scaler_argb8888_vert;
ctx->unscaled = false;
}
ctx->scaler_special = NULL;
if (!allocate_frames(ctx))
return false;
if (ctx->unscaled)
{
if (!set_direct_pix_conv(ctx))
return false;
}
else
{
if (!set_pix_conv(ctx))
return false;
}
if (!ctx->unscaled && !scaler_gen_filter(ctx))
return false;
return true;
}
void scaler_ctx_gen_reset(struct scaler_ctx *ctx)
{
scaler_free(ctx->horiz.filter);
scaler_free(ctx->horiz.filter_pos);
scaler_free(ctx->vert.filter);
scaler_free(ctx->vert.filter_pos);
scaler_free(ctx->scaled.frame);
scaler_free(ctx->input.frame);
scaler_free(ctx->output.frame);
memset(&ctx->horiz, 0, sizeof(ctx->horiz));
memset(&ctx->vert, 0, sizeof(ctx->vert));
memset(&ctx->scaled, 0, sizeof(ctx->scaled));
memset(&ctx->input, 0, sizeof(ctx->input));
memset(&ctx->output, 0, sizeof(ctx->output));
}
/**
* scaler_ctx_scale:
* @ctx : pointer to scaler context object.
* @output : pointer to output image.
* @input : pointer to input image.
*
* Scales an input image to an output image.
**/
void scaler_ctx_scale(struct scaler_ctx *ctx,
void *output, const void *input)
{
const void *input_frame = input;
void *output_frame = output;
int input_stride = ctx->in_stride;
int output_stride = ctx->out_stride;
if (ctx->unscaled)
{
/* Just perform straight pixel conversion. */
ctx->direct_pixconv(output, input,
ctx->out_width, ctx->out_height,
ctx->out_stride, ctx->in_stride);
return;
}
if (ctx->in_fmt != SCALER_FMT_ARGB8888)
{
ctx->in_pixconv(ctx->input.frame, input,
ctx->in_width, ctx->in_height,
ctx->input.stride, ctx->in_stride);
input_frame = ctx->input.frame;
input_stride = ctx->input.stride;
}
if (ctx->out_fmt != SCALER_FMT_ARGB8888)
{
output_frame = ctx->output.frame;
output_stride = ctx->output.stride;
}
if (ctx->scaler_special)
{
/* Take some special, and (hopefully) more optimized path. */
ctx->scaler_special(ctx, output_frame, input_frame,
ctx->out_width, ctx->out_height,
ctx->in_width, ctx->in_height,
output_stride, input_stride);
}
else
{
/* Take generic filter path. */
if (ctx->scaler_horiz)
ctx->scaler_horiz(ctx, input_frame, input_stride);
if (ctx->scaler_vert)
ctx->scaler_vert (ctx, output, output_stride);
}
if (ctx->out_fmt != SCALER_FMT_ARGB8888)
ctx->out_pixconv(output, ctx->output.frame,
ctx->out_width, ctx->out_height,
ctx->out_stride, ctx->output.stride);
}

View File

@ -0,0 +1,282 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (scaler_filter.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gfx/scaler/filter.h>
#include <gfx/scaler/scaler_int.h>
#include <retro_miscellaneous.h>
#include <retro_inline.h>
#include <filters.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static bool allocate_filters(struct scaler_ctx *ctx)
{
ctx->horiz.filter = (int16_t*)scaler_alloc(sizeof(int16_t), ctx->horiz.filter_stride * ctx->out_width);
ctx->horiz.filter_pos = (int*)scaler_alloc(sizeof(int), ctx->out_width);
ctx->vert.filter = (int16_t*)scaler_alloc(sizeof(int16_t), ctx->vert.filter_stride * ctx->out_height);
ctx->vert.filter_pos = (int*)scaler_alloc(sizeof(int), ctx->out_height);
return ctx->horiz.filter && ctx->vert.filter;
}
static void gen_filter_point_sub(struct scaler_filter *filter,
int len, int pos, int step)
{
int i;
for (i = 0; i < len; i++, pos += step)
{
filter->filter_pos[i] = pos >> 16;
filter->filter[i] = FILTER_UNITY;
}
}
static bool gen_filter_point(struct scaler_ctx *ctx)
{
int x_pos, x_step, y_pos, y_step;
ctx->horiz.filter_len = 1;
ctx->horiz.filter_stride = 1;
ctx->vert.filter_len = 1;
ctx->vert.filter_stride = 1;
if (!allocate_filters(ctx))
return false;
x_pos = (1 << 15) * ctx->in_width / ctx->out_width - (1 << 15);
x_step = (1 << 16) * ctx->in_width / ctx->out_width;
y_pos = (1 << 15) * ctx->in_height / ctx->out_height - (1 << 15);
y_step = (1 << 16) * ctx->in_height / ctx->out_height;
gen_filter_point_sub(&ctx->horiz, ctx->out_width, x_pos, x_step);
gen_filter_point_sub(&ctx->vert, ctx->out_height, y_pos, y_step);
ctx->scaler_special = scaler_argb8888_point_special;
return true;
}
static void gen_filter_bilinear_sub(struct scaler_filter *filter,
int len, int pos, int step)
{
int i;
for (i = 0; i < len; i++, pos += step)
{
filter->filter_pos[i] = pos >> 16;
filter->filter[i * 2 + 1] = (pos & 0xffff) >> 2;
filter->filter[i * 2 + 0] = FILTER_UNITY - filter->filter[i * 2 + 1];
}
}
static bool gen_filter_bilinear(struct scaler_ctx *ctx)
{
int x_pos, x_step, y_pos, y_step;
ctx->horiz.filter_len = 2;
ctx->horiz.filter_stride = 2;
ctx->vert.filter_len = 2;
ctx->vert.filter_stride = 2;
if (!allocate_filters(ctx))
return false;
x_pos = (1 << 15) * ctx->in_width / ctx->out_width - (1 << 15);
x_step = (1 << 16) * ctx->in_width / ctx->out_width;
y_pos = (1 << 15) * ctx->in_height / ctx->out_height - (1 << 15);
y_step = (1 << 16) * ctx->in_height / ctx->out_height;
gen_filter_bilinear_sub(&ctx->horiz, ctx->out_width, x_pos, x_step);
gen_filter_bilinear_sub(&ctx->vert, ctx->out_height, y_pos, y_step);
return true;
}
static void gen_filter_sinc_sub(struct scaler_filter *filter,
int len, int pos, int step, double phase_mul)
{
int i, j;
const int sinc_size = filter->filter_len;
for (i = 0; i < len; i++, pos += step)
{
filter->filter_pos[i] = pos >> 16;
for (j = 0; j < sinc_size; j++)
{
double sinc_phase = M_PI * ((double)((sinc_size << 15) + (pos & 0xffff)) / 0x10000 - j);
double lanczos_phase = sinc_phase / ((sinc_size >> 1));
int16_t sinc_val = FILTER_UNITY * sinc(sinc_phase * phase_mul) * sinc(lanczos_phase) * phase_mul;
filter->filter[i * sinc_size + j] = sinc_val;
}
}
}
static bool gen_filter_sinc(struct scaler_ctx *ctx)
{
int x_pos, x_step, y_pos, y_step;
double phase_mul_horiz, phase_mul_vert;
/* Need to expand the filter when downsampling
* to get a proper low-pass effect. */
const int sinc_size = 8 * ((ctx->in_width > ctx->out_width)
? next_pow2(ctx->in_width / ctx->out_width) : 1);
ctx->horiz.filter_len = sinc_size;
ctx->horiz.filter_stride = sinc_size;
ctx->vert.filter_len = sinc_size;
ctx->vert.filter_stride = sinc_size;
if (!allocate_filters(ctx))
return false;
x_pos = (1 << 15) * ctx->in_width / ctx->out_width - (1 << 15) - (sinc_size << 15);
x_step = (1 << 16) * ctx->in_width / ctx->out_width;
y_pos = (1 << 15) * ctx->in_height / ctx->out_height - (1 << 15) - (sinc_size << 15);
y_step = (1 << 16) * ctx->in_height / ctx->out_height;
phase_mul_horiz = ctx->in_width > ctx->out_width ? (double)ctx->out_width / ctx->in_width : 1.0;
phase_mul_vert = ctx->in_height > ctx->out_height ? (double)ctx->out_height / ctx->in_height : 1.0;
gen_filter_sinc_sub(&ctx->horiz, ctx->out_width, x_pos, x_step, phase_mul_horiz);
gen_filter_sinc_sub(&ctx->vert, ctx->out_height, y_pos, y_step, phase_mul_vert);
return true;
}
static bool validate_filter(struct scaler_ctx *ctx)
{
int i;
int max_h_pos;
int max_w_pos = ctx->in_width - ctx->horiz.filter_len;
for (i = 0; i < ctx->out_width; i++)
{
if (ctx->horiz.filter_pos[i] > max_w_pos || ctx->horiz.filter_pos[i] < 0)
{
fprintf(stderr, "Out X = %d => In X = %d\n", i, ctx->horiz.filter_pos[i]);
return false;
}
}
max_h_pos = ctx->in_height - ctx->vert.filter_len;
for (i = 0; i < ctx->out_height; i++)
{
if (ctx->vert.filter_pos[i] > max_h_pos || ctx->vert.filter_pos[i] < 0)
{
fprintf(stderr, "Out Y = %d => In Y = %d\n", i, ctx->vert.filter_pos[i]);
return false;
}
}
return true;
}
static void fixup_filter_sub(struct scaler_filter *filter, int out_len, int in_len)
{
int i;
int max_pos = in_len - filter->filter_len;
for (i = 0; i < out_len; i++)
{
int postsample = filter->filter_pos[i] - max_pos;
int presample = -filter->filter_pos[i];
if (postsample > 0)
{
int16_t *base_filter = NULL;
filter->filter_pos[i] -= postsample;
base_filter = filter->filter + i * filter->filter_stride;
if (postsample > (int)filter->filter_len)
memset(base_filter, 0, filter->filter_len * sizeof(int16_t));
else
{
memmove(base_filter + postsample, base_filter,
(filter->filter_len - postsample) * sizeof(int16_t));
memset(base_filter, 0, postsample * sizeof(int16_t));
}
}
if (presample > 0)
{
int16_t *base_filter = NULL;
filter->filter_pos[i] += presample;
base_filter = filter->filter + i * filter->filter_stride;
if (presample > (int)filter->filter_len)
memset(base_filter, 0, filter->filter_len * sizeof(int16_t));
else
{
memmove(base_filter, base_filter + presample,
(filter->filter_len - presample) * sizeof(int16_t));
memset(base_filter + (filter->filter_len - presample), 0, presample * sizeof(int16_t));
}
}
}
}
/* Makes sure that we never sample outside our rectangle. */
static void fixup_filter(struct scaler_ctx *ctx)
{
fixup_filter_sub(&ctx->horiz, ctx->out_width, ctx->in_width);
fixup_filter_sub(&ctx->vert, ctx->out_height, ctx->in_height);
}
bool scaler_gen_filter(struct scaler_ctx *ctx)
{
bool ret = true;
switch (ctx->scaler_type)
{
case SCALER_TYPE_POINT:
ret = gen_filter_point(ctx);
break;
case SCALER_TYPE_BILINEAR:
ret = gen_filter_bilinear(ctx);
break;
case SCALER_TYPE_SINC:
ret = gen_filter_sinc(ctx);
break;
default:
return false;
}
if (!ret)
return false;
fixup_filter(ctx);
return validate_filter(ctx);
}

View File

@ -0,0 +1,285 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (scaler_int.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <gfx/scaler/scaler_int.h>
#include <retro_inline.h>
#ifdef SCALER_NO_SIMD
#undef __SSE2__
#endif
#if defined(__SSE2__)
#include <emmintrin.h>
#ifdef _WIN32
#include <intrin.h>
#endif
#endif
/* ARGB8888 scaler is split in two:
*
* First, horizontal scaler is applied.
* Here, all 8-bit channels are expanded to 16-bit. Values are then shifted 7 to left to occupy 15 bits.
* The sign bit is kept empty as we have to do signed multiplication for the filter.
* A mulhi [(a * b) >> 16] is applied which loses some precision, but is very efficient for SIMD.
* It is accurate enough for 8-bit purposes.
*
* The fixed point 1.0 for filter is (1 << 14). After horizontal scale, the output is kept
* with 16-bit channels, and will now have 13 bits of precision as [(a * (1 << 14)) >> 16] is effectively a right shift by 2.
*
* Vertical scaler takes the 13 bit channels, and performs the same mulhi steps.
* Another 2 bits of precision is lost, which ends up as 11 bits.
* Scaling is now complete. Channels are shifted right by 3, and saturated into 8-bit values.
*
* The C version of scalers perform the exact same operations as the SIMD code for testing purposes.
*/
#if defined(__SSE2__)
void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output_, int stride)
{
int h, w, y;
const uint64_t *input = ctx->scaled.frame;
uint32_t *output = (uint32_t*)output_;
const int16_t *filter_vert = ctx->vert.filter;
for (h = 0; h < ctx->out_height; h++, filter_vert += ctx->vert.filter_stride, output += stride >> 2)
{
const uint64_t *input_base = input + ctx->vert.filter_pos[h] * (ctx->scaled.stride >> 3);
for (w = 0; w < ctx->out_width; w++)
{
__m128i final;
__m128i res = _mm_setzero_si128();
const uint64_t *input_base_y = input_base + w;
for (y = 0; (y + 1) < ctx->vert.filter_len; y += 2, input_base_y += (ctx->scaled.stride >> 2))
{
__m128i coeff = _mm_set_epi64x(filter_vert[y + 1] * 0x0001000100010001ll, filter_vert[y + 0] * 0x0001000100010001ll);
__m128i col = _mm_set_epi64x(input_base_y[ctx->scaled.stride >> 3], input_base_y[0]);
res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res);
}
for (; y < ctx->vert.filter_len; y++, input_base_y += (ctx->scaled.stride >> 3))
{
__m128i coeff = _mm_set_epi64x(0, filter_vert[y] * 0x0001000100010001ll);
__m128i col = _mm_set_epi64x(0, input_base_y[0]);
res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res);
}
res = _mm_adds_epi16(_mm_srli_si128(res, 8), res);
res = _mm_srai_epi16(res, (7 - 2 - 2));
final = _mm_packus_epi16(res, res);
output[w] = _mm_cvtsi128_si32(final);
}
}
}
#else
void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output_, int stride)
{
int h, w, y;
const uint64_t *input = ctx->scaled.frame;
uint32_t *output = (uint32_t*)output_;
const int16_t *filter_vert = ctx->vert.filter;
for (h = 0; h < ctx->out_height; h++, filter_vert += ctx->vert.filter_stride, output += stride >> 2)
{
const uint64_t *input_base = input + ctx->vert.filter_pos[h] * (ctx->scaled.stride >> 3);
for (w = 0; w < ctx->out_width; w++)
{
int16_t res_a = 0;
int16_t res_r = 0;
int16_t res_g = 0;
int16_t res_b = 0;
const uint64_t *input_base_y = input_base + w;
for (y = 0; y < ctx->vert.filter_len; y++, input_base_y += (ctx->scaled.stride >> 3))
{
uint64_t col = *input_base_y;
int16_t a = (col >> 48) & 0xffff;
int16_t r = (col >> 32) & 0xffff;
int16_t g = (col >> 16) & 0xffff;
int16_t b = (col >> 0) & 0xffff;
int16_t coeff = filter_vert[y];
res_a += (a * coeff) >> 16;
res_r += (r * coeff) >> 16;
res_g += (g * coeff) >> 16;
res_b += (b * coeff) >> 16;
}
res_a >>= (7 - 2 - 2);
res_r >>= (7 - 2 - 2);
res_g >>= (7 - 2 - 2);
res_b >>= (7 - 2 - 2);
output[w] = (clamp_8bit(res_a) << 24) | (clamp_8bit(res_r) << 16) | (clamp_8bit(res_g) << 8) | (clamp_8bit(res_b) << 0);
}
}
}
#endif
#if defined(__SSE2__)
void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input_, int stride)
{
int h, w, x;
const uint32_t *input = (const uint32_t*)input_;
uint64_t *output = ctx->scaled.frame;
for (h = 0; h < ctx->scaled.height; h++, input += stride >> 2, output += ctx->scaled.stride >> 3)
{
const int16_t *filter_horiz = ctx->horiz.filter;
for (w = 0; w < ctx->scaled.width; w++, filter_horiz += ctx->horiz.filter_stride)
{
__m128i res = _mm_setzero_si128();
const uint32_t *input_base_x = input + ctx->horiz.filter_pos[w];
for (x = 0; (x + 1) < ctx->horiz.filter_len; x += 2)
{
__m128i coeff = _mm_set_epi64x(filter_horiz[x + 1] * 0x0001000100010001ll, filter_horiz[x + 0] * 0x0001000100010001ll);
__m128i col = _mm_unpacklo_epi8(_mm_set_epi64x(0,
((uint64_t)input_base_x[x + 1] << 32) | input_base_x[x + 0]), _mm_setzero_si128());
col = _mm_slli_epi16(col, 7);
res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res);
}
for (; x < ctx->horiz.filter_len; x++)
{
__m128i coeff = _mm_set_epi64x(0, filter_horiz[x] * 0x0001000100010001ll);
__m128i col = _mm_unpacklo_epi8(_mm_set_epi32(0, 0, 0, input_base_x[x]), _mm_setzero_si128());
col = _mm_slli_epi16(col, 7);
res = _mm_adds_epi16(_mm_mulhi_epi16(col, coeff), res);
}
res = _mm_adds_epi16(_mm_srli_si128(res, 8), res);
#ifdef __x86_64__
output[w] = _mm_cvtsi128_si64(res);
#else /* 32-bit doesn't have si64. Do it in two steps. */
union
{
uint32_t *u32;
uint64_t *u64;
} u;
u.u64 = output + w;
u.u32[0] = _mm_cvtsi128_si32(res);
u.u32[1] = _mm_cvtsi128_si32(_mm_srli_si128(res, 4));
#endif
}
}
}
#else
static INLINE uint64_t build_argb64(uint16_t a, uint16_t r, uint16_t g, uint16_t b)
{
return ((uint64_t)a << 48) | ((uint64_t)r << 32) | ((uint64_t)g << 16) | ((uint64_t)b << 0);
}
void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input_, int stride)
{
int h, w, x;
const uint32_t *input = (uint32_t*)input_;
uint64_t *output = ctx->scaled.frame;
for (h = 0; h < ctx->scaled.height; h++, input += stride >> 2, output += ctx->scaled.stride >> 3)
{
const int16_t *filter_horiz = ctx->horiz.filter;
for (w = 0; w < ctx->scaled.width; w++, filter_horiz += ctx->horiz.filter_stride)
{
const uint32_t *input_base_x = input + ctx->horiz.filter_pos[w];
int16_t res_a = 0;
int16_t res_r = 0;
int16_t res_g = 0;
int16_t res_b = 0;
for (x = 0; x < ctx->horiz.filter_len; x++)
{
uint32_t col = input_base_x[x];
int16_t a = (col >> (24 - 7)) & (0xff << 7);
int16_t r = (col >> (16 - 7)) & (0xff << 7);
int16_t g = (col >> ( 8 - 7)) & (0xff << 7);
int16_t b = (col << ( 0 + 7)) & (0xff << 7);
int16_t coeff = filter_horiz[x];
res_a += (a * coeff) >> 16;
res_r += (r * coeff) >> 16;
res_g += (g * coeff) >> 16;
res_b += (b * coeff) >> 16;
}
output[w] = build_argb64(res_a, res_r, res_g, res_b);
}
}
}
#endif
void scaler_argb8888_point_special(const struct scaler_ctx *ctx,
void *output_, const void *input_,
int out_width, int out_height,
int in_width, int in_height,
int out_stride, int in_stride)
{
int h, w;
const uint32_t *input = NULL;
uint32_t *output = NULL;
int x_pos = (1 << 15) * in_width / out_width - (1 << 15);
int x_step = (1 << 16) * in_width / out_width;
int y_pos = (1 << 15) * in_height / out_height - (1 << 15);
int y_step = (1 << 16) * in_height / out_height;
(void)ctx;
if (x_pos < 0)
x_pos = 0;
if (y_pos < 0)
y_pos = 0;
input = (const uint32_t*)input_;
output = (uint32_t*)output_;
for (h = 0; h < out_height; h++, y_pos += y_step, output += out_stride >> 2)
{
int x = x_pos;
const uint32_t *inp = input + (y_pos >> 16) * (in_stride >> 2);
for (w = 0; w < out_width; w++, x += x_step)
output[w] = inp[x >> 16];
}
}

View File

@ -0,0 +1,12 @@
# Autogenerate GL extension loaders
## OpenGL desktop
Use Khronos' recent [header](www.opengl.org/registry/api/glext.h).
./glgen.py /usr/include/GL/glext.h glsym_gl.h glsym_gl.c
## OpenGL ES
./glgen.py /usr/include/GLES2/gl2ext.h glsym_es2.h glsym_es2.c

View File

@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""
License statement applies to this file (glgen.py) only.
"""
"""
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
import sys
import os
import re
banned_ext = [ 'AMD', 'APPLE', 'EXT', 'NV', 'NVX', 'ATI', '3DLABS', 'SUN', 'SGI', 'SGIX', 'SGIS', 'INTEL', '3DFX', 'IBM', 'MESA', 'GREMEDY', 'OML', 'PGI', 'I3D', 'INGL', 'MTX', 'QCOM', 'IMG', 'ANGLE', 'SUNX', 'INGR' ]
def noext(sym):
for ext in banned_ext:
if sym.endswith(ext):
return False
return True
def find_gl_symbols(lines):
typedefs = []
syms = []
for line in lines:
m = re.search(r'^typedef.+PFN(\S+)PROC.+$', line)
g = re.search(r'^.+(gl\S+)\W*\(.+\).*$', line)
if m and noext(m.group(1)):
typedefs.append(m.group(0).replace('PFN', 'RGLSYM').replace('GLDEBUGPROC', 'RGLGENGLDEBUGPROC'))
if g and noext(g.group(1)):
syms.append(g.group(1))
return (typedefs, syms)
def generate_defines(gl_syms):
res = []
for line in gl_syms:
res.append('#define {} __rglgen_{}'.format(line, line))
return res
def generate_declarations(gl_syms):
return ['RGLSYM' + x.upper() + 'PROC ' + '__rglgen_' + x + ';' for x in gl_syms]
def generate_macros(gl_syms):
return [' SYM(' + x.replace('gl', '') + '),' for x in gl_syms]
def dump(f, lines):
f.write('\n'.join(lines))
f.write('\n\n')
if __name__ == '__main__':
if len(sys.argv) > 4:
for banned in sys.argv[4:]:
banned_ext.append(banned)
with open(sys.argv[1], 'r') as f:
lines = f.readlines()
typedefs, syms = find_gl_symbols(lines)
overrides = generate_defines(syms)
declarations = generate_declarations(syms)
externs = ['extern ' + x for x in declarations]
macros = generate_macros(syms)
with open(sys.argv[2], 'w') as f:
f.write('#ifndef RGLGEN_DECL_H__\n')
f.write('#define RGLGEN_DECL_H__\n')
f.write('#ifdef __cplusplus\n')
f.write('extern "C" {\n')
f.write('#endif\n')
f.write('#ifdef GL_APIENTRY\n')
f.write('typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n')
f.write('typedef void (GL_APIENTRY *RGLGENGLDEBUGPROCKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n')
f.write('#else\n')
f.write('#ifndef APIENTRY\n')
f.write('#define APIENTRY\n')
f.write('#endif\n')
f.write('#ifndef APIENTRYP\n')
f.write('#define APIENTRYP APIENTRY *\n')
f.write('#endif\n')
f.write('typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n')
f.write('typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n')
f.write('#endif\n')
f.write('#ifndef GL_OES_EGL_image\n')
f.write('typedef void *GLeglImageOES;\n')
f.write('#endif\n')
f.write('#if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2)\n')
f.write('typedef GLint GLfixed;\n')
f.write('#endif\n')
f.write('#if defined(OSX) && !defined(MAC_OS_X_VERSION_10_7)\n')
f.write('typedef long long int GLint64;\n')
f.write('typedef unsigned long long int GLuint64;\n')
f.write('typedef unsigned long long int GLuint64EXT;\n')
f.write('typedef struct __GLsync *GLsync;\n')
f.write('#endif\n')
dump(f, typedefs)
dump(f, overrides)
dump(f, externs)
f.write('struct rglgen_sym_map { const char *sym; void *ptr; };\n')
f.write('extern const struct rglgen_sym_map rglgen_symbol_map[];\n')
f.write('#ifdef __cplusplus\n')
f.write('}\n')
f.write('#endif\n')
f.write('#endif\n')
with open(sys.argv[3], 'w') as f:
f.write('#include "glsym.h"\n')
f.write('#include <stddef.h>\n')
f.write('#define SYM(x) { "gl" #x, &(gl##x) }\n')
f.write('const struct rglgen_sym_map rglgen_symbol_map[] = {\n')
dump(f, macros)
f.write(' { NULL, NULL },\n')
f.write('};\n')
dump(f, declarations)

View File

@ -0,0 +1,87 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro SDK code part (glsym).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <glsym/glsym.h>
#include <stddef.h>
#define SYM(x) { "gl" #x, &(gl##x) }
const struct rglgen_sym_map rglgen_symbol_map[] = {
SYM(DebugMessageControlKHR),
SYM(DebugMessageInsertKHR),
SYM(DebugMessageCallbackKHR),
SYM(GetDebugMessageLogKHR),
SYM(PushDebugGroupKHR),
SYM(PopDebugGroupKHR),
SYM(ObjectLabelKHR),
SYM(GetObjectLabelKHR),
SYM(ObjectPtrLabelKHR),
SYM(GetObjectPtrLabelKHR),
SYM(GetPointervKHR),
SYM(EGLImageTargetTexture2DOES),
SYM(EGLImageTargetRenderbufferStorageOES),
SYM(GetProgramBinaryOES),
SYM(ProgramBinaryOES),
SYM(MapBufferOES),
SYM(UnmapBufferOES),
SYM(GetBufferPointervOES),
SYM(TexImage3DOES),
SYM(TexSubImage3DOES),
SYM(CopyTexSubImage3DOES),
SYM(CompressedTexImage3DOES),
SYM(CompressedTexSubImage3DOES),
SYM(FramebufferTexture3DOES),
SYM(BindVertexArrayOES),
SYM(DeleteVertexArraysOES),
SYM(GenVertexArraysOES),
SYM(IsVertexArrayOES),
{ NULL, NULL },
};
RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR;
RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR;
RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR;
RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR;
RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR;
RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR;
RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR;
RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR;
RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR;
RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR;
RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR;
RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES;
RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES;
RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES;
RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES;
RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES;
RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES;
RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES;
RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES;
RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES;
RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES;
RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES;
RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES;
RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES;
RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES;
RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES;
RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES;
RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro SDK code part (glsym).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <string.h>
#include <glsym/rglgen.h>
#include <glsym/glsym.h>
void rglgen_resolve_symbols_custom(rglgen_proc_address_t proc,
const struct rglgen_sym_map *map)
{
for (; map->sym; map++)
{
rglgen_func_t func = proc(map->sym);
memcpy(map->ptr, &func, sizeof(func));
}
}
void rglgen_resolve_symbols(rglgen_proc_address_t proc)
{
rglgen_resolve_symbols_custom(proc, rglgen_symbol_map);
}

View File

@ -0,0 +1,550 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rhash.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <rhash.h>
#include <retro_miscellaneous.h>
#include <retro_endianness.h>
#include <retro_file.h>
#define LSL32(x, n) ((uint32_t)(x) << (n))
#define LSR32(x, n) ((uint32_t)(x) >> (n))
#define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n)))
/* First 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 */
static const uint32_t T_H[8] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
};
/* First 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 */
static const uint32_t T_K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
/* SHA256 implementation from bSNES. Written by valditx. */
struct sha256_ctx
{
union
{
uint8_t u8[64];
uint32_t u32[16];
} in;
unsigned inlen;
uint32_t w[64];
uint32_t h[8];
uint64_t len;
};
static void sha256_init(struct sha256_ctx *p)
{
memset(p, 0, sizeof(struct sha256_ctx));
memcpy(p->h, T_H, sizeof(T_H));
}
static void sha256_block(struct sha256_ctx *p)
{
unsigned i;
uint32_t s0, s1;
uint32_t a, b, c, d, e, f, g, h;
uint32_t t1, t2, maj, ch;
for (i = 0; i < 16; i++)
p->w[i] = load32be(p->in.u32 + i);
for (i = 16; i < 64; i++)
{
s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3);
s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10);
p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1;
}
a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3];
e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7];
for (i = 0; i < 64; i++)
{
s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25);
ch = (e & f) ^ (~e & g);
t1 = h + s1 + ch + T_K[i] + p->w[i];
h = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d;
p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h;
/* Next block */
p->inlen = 0;
}
static void sha256_chunk(struct sha256_ctx *p,
const uint8_t *s, unsigned len)
{
unsigned l;
p->len += len;
while (len)
{
l = 64 - p->inlen;
l = (len < l) ? len : l;
memcpy(p->in.u8 + p->inlen, s, l);
s += l;
p->inlen += l;
len -= l;
if (p->inlen == 64)
sha256_block(p);
}
}
static void sha256_final(struct sha256_ctx *p)
{
uint64_t len;
p->in.u8[p->inlen++] = 0x80;
if (p->inlen > 56)
{
memset(p->in.u8 + p->inlen, 0, 64 - p->inlen);
sha256_block(p);
}
memset(p->in.u8 + p->inlen, 0, 56 - p->inlen);
len = p->len << 3;
store32be(p->in.u32 + 14, (uint32_t)(len >> 32));
store32be(p->in.u32 + 15, (uint32_t)len);
sha256_block(p);
}
static void sha256_subhash(struct sha256_ctx *p, uint32_t *t)
{
unsigned i;
for (i = 0; i < 8; i++)
store32be(t++, p->h[i]);
}
/**
* sha256_hash:
* @s : Output.
* @in : Input.
* @size : Size of @s.
*
* Hashes SHA256 and outputs a human readable string.
**/
void sha256_hash(char *s, const uint8_t *in, size_t size)
{
unsigned i;
struct sha256_ctx sha;
union
{
uint32_t u32[8];
uint8_t u8[32];
} shahash;
sha256_init(&sha);
sha256_chunk(&sha, in, size);
sha256_final(&sha);
sha256_subhash(&sha, shahash.u32);
for (i = 0; i < 32; i++)
snprintf(s + 2 * i, 3, "%02x", (unsigned)shahash.u8[i]);
}
#ifndef HAVE_ZLIB
/* Zlib CRC32. */
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t crc32_adjust(uint32_t checksum, uint8_t input)
{
return ((checksum >> 8) & 0x00ffffff) ^ crc32_table[(checksum ^ input) & 0xff];
}
uint32_t crc32_calculate(const uint8_t *data, size_t length)
{
size_t i;
uint32_t checksum = ~0;
for (i = 0; i < length; i++)
checksum = crc32_adjust(checksum, data[i]);
return ~checksum;
}
#endif
/* SHA-1 implementation. */
/*
* sha1.c
*
* Copyright (C) 1998, 2009
* Paul E. Jones <paulej@packetizer.com>
* All Rights Reserved
*
*****************************************************************************
* $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $
*****************************************************************************
*
* Description:
* This file implements the Secure Hashing Standard as defined
* in FIPS PUB 180-1 published April 17, 1995.
*
* The Secure Hashing Standard, which uses the Secure Hashing
* Algorithm (SHA), produces a 160-bit message digest for a
* given data stream. In theory, it is highly improbable that
* two messages will produce the same message digest. Therefore,
* this algorithm can serve as a means of providing a "fingerprint"
* for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code was
* written with the expectation that the processor has at least
* a 32-bit machine word size. If the machine word size is larger,
* the code should still function properly. One caveat to that
* is that the input functions taking characters and character
* arrays assume that only 8 bits of information are stored in each
* character.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits
* long. Although SHA-1 allows a message digest to be generated for
* messages of any number of bits less than 2^64, this
* implementation only works with messages with a length that is a
* multiple of the size of an 8-bit character.
*
*/
/* Define the circular shift macro */
#define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))
static void SHA1Reset(SHA1Context *context)
{
if (!context)
return;
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Message_Digest[0] = 0x67452301;
context->Message_Digest[1] = 0xEFCDAB89;
context->Message_Digest[2] = 0x98BADCFE;
context->Message_Digest[3] = 0x10325476;
context->Message_Digest[4] = 0xC3D2E1F0;
context->Computed = 0;
context->Corrupted = 0;
}
static void SHA1ProcessMessageBlock(SHA1Context *context)
{
const unsigned K[] = /* Constants defined in SHA-1 */
{
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* Loop counter */
unsigned temp; /* Temporary word value */
unsigned W[80]; /* Word sequence */
unsigned A, B, C, D, E; /* Word buffers */
/* Initialize the first 16 words in the array W */
for(t = 0; t < 16; t++)
{
W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
}
for(t = 16; t < 80; t++)
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
A = context->Message_Digest[0];
B = context->Message_Digest[1];
C = context->Message_Digest[2];
D = context->Message_Digest[3];
E = context->Message_Digest[4];
for(t = 0; t < 20; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | ((~B) & D)) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
context->Message_Digest[0] =
(context->Message_Digest[0] + A) & 0xFFFFFFFF;
context->Message_Digest[1] =
(context->Message_Digest[1] + B) & 0xFFFFFFFF;
context->Message_Digest[2] =
(context->Message_Digest[2] + C) & 0xFFFFFFFF;
context->Message_Digest[3] =
(context->Message_Digest[3] + D) & 0xFFFFFFFF;
context->Message_Digest[4] =
(context->Message_Digest[4] + E) & 0xFFFFFFFF;
context->Message_Block_Index = 0;
}
static void SHA1PadMessage(SHA1Context *context)
{
if (!context)
return;
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
context->Message_Block[context->Message_Block_Index++] = 0x80;
if (context->Message_Block_Index > 55)
{
while(context->Message_Block_Index < 64)
context->Message_Block[context->Message_Block_Index++] = 0;
SHA1ProcessMessageBlock(context);
}
while(context->Message_Block_Index < 56)
context->Message_Block[context->Message_Block_Index++] = 0;
/* Store the message length as the last 8 octets */
context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
context->Message_Block[59] = (context->Length_High) & 0xFF;
context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
context->Message_Block[63] = (context->Length_Low) & 0xFF;
SHA1ProcessMessageBlock(context);
}
static int SHA1Result(SHA1Context *context)
{
if (context->Corrupted)
return 0;
if (!context->Computed)
{
SHA1PadMessage(context);
context->Computed = 1;
}
return 1;
}
static void SHA1Input(SHA1Context *context,
const unsigned char *message_array,
unsigned length)
{
if (!length)
return;
if (context->Computed || context->Corrupted)
{
context->Corrupted = 1;
return;
}
while(length-- && !context->Corrupted)
{
context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF);
context->Length_Low += 8;
/* Force it to 32 bits */
context->Length_Low &= 0xFFFFFFFF;
if (context->Length_Low == 0)
{
context->Length_High++;
/* Force it to 32 bits */
context->Length_High &= 0xFFFFFFFF;
if (context->Length_High == 0)
context->Corrupted = 1; /* Message is too long */
}
if (context->Message_Block_Index == 64)
SHA1ProcessMessageBlock(context);
message_array++;
}
}
int sha1_calculate(const char *path, char *result)
{
unsigned char buff[4096] = {0};
SHA1Context sha;
int rv = 1;
RFILE *fd = retro_fopen(path, RFILE_MODE_READ, -1);
if (!fd)
goto error;
SHA1Reset(&sha);
do
{
rv = retro_fread(fd, buff, 4096);
if (rv < 0)
goto error;
SHA1Input(&sha, buff, rv);
}while(rv);
if (!SHA1Result(&sha))
goto error;
sprintf(result, "%08X%08X%08X%08X%08X",
sha.Message_Digest[0],
sha.Message_Digest[1],
sha.Message_Digest[2],
sha.Message_Digest[3], sha.Message_Digest[4]);
retro_fclose(fd);
return 0;
error:
if (fd)
retro_fclose(fd);
return -1;
}
uint32_t djb2_calculate(const char *str)
{
const unsigned char *aux = (const unsigned char*)str;
uint32_t hash = 5381;
while ( *aux )
hash = ( hash << 5 ) + hash + *aux++;
return hash;
}

View File

@ -0,0 +1,39 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_BOOLEAN_H
#define __LIBRETRO_SDK_BOOLEAN_H
#ifndef __cplusplus
#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
#define bool unsigned char
#define true 1
#define false 0
#else
#include <stdbool.h>
#endif
#endif
#endif

View File

@ -0,0 +1,65 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_CLAMPING_H
#define _LIBRETRO_SDK_CLAMPING_H
#include <stdint.h>
#include <retro_inline.h>
/**
* clamp_float:
* @val : initial value
* @lower : lower limit that value should be clamped against
* @upper : upper limit that value should be clamped against
*
* Clamps a floating point value.
*
* Returns: a clamped value of initial float value @val.
*/
static INLINE float clamp_float(float val, float lower, float upper)
{
if (val < lower)
return lower;
if (val > upper)
return upper;
return val;
}
/**
* clamp_8bit:
* @val : initial value
*
* Clamps an unsigned 8-bit value.
*
* Returns: a clamped value of initial unsigned 8-bit value @val.
*/
static INLINE uint8_t clamp_8bit(int val)
{
if (val > 255)
return 255;
if (val < 0)
return 0;
return (uint8_t)val;
}
#endif

View File

@ -0,0 +1,48 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (apple_compat.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
#ifdef __OBJC__
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
typedef int NSInteger;
typedef unsigned NSUInteger;
#endif
#endif
#ifdef IOS
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#import <Foundation/Foundation.h>
#include <objc/objc-runtime.h>
#endif
#endif

View File

@ -0,0 +1,30 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_fnmatch.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_FNMATCH_H__
#define __LIBRETRO_SDK_COMPAT_FNMATCH_H__
#define FNM_NOMATCH 1
int rl_fnmatch(const char *pattern, const char *string, int flags);
#endif

View File

@ -0,0 +1,66 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_getopt.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_GETOPT_H
#define __LIBRETRO_SDK_COMPAT_GETOPT_H
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
/* Custom implementation of the GNU getopt_long for portability.
* Not designed to be fully compatible, but compatible with
* the features RetroArch uses. */
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
/* Avoid possible naming collisions during link since we
* prefer to use the actual name. */
#define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_rarch(argc, argv, optstring, longopts, longindex)
#ifdef __cplusplus
extern "C" {
#endif
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
/* argv[] is declared with char * const argv[] in GNU,
* but this makes no sense, as non-POSIX getopt_long
* mutates argv (non-opts are moved to the end). */
int getopt_long(int argc, char *argv[],
const char *optstring, const struct option *longopts, int *longindex);
extern char *optarg;
extern int optind, opterr, optopt;
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -0,0 +1,80 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (msvc_compat.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_MSVC_H
#define __LIBRETRO_SDK_COMPAT_MSVC_H
#ifdef _MSC_VER
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
#if _MSC_VER < 1900
#ifndef snprintf
#define snprintf _snprintf
#endif
#endif
#undef UNICODE /* Do not bother with UNICODE at this time. */
#include <direct.h>
#include <stddef.h>
#include <math.h>
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
* Cannot duplicate these efforts.
*/
#ifndef HAVE_SSIZE_T
#if defined(_WIN64)
typedef __int64 ssize_t;
#elif defined(_WIN32)
typedef int ssize_t;
#endif
#endif
#define mkdir(dirname, unused) _mkdir(dirname)
#define strtoull _strtoui64
#undef strcasecmp
#define strcasecmp(x,y) _stricmp(x,y)
#undef strncasecmp
#define strncasecmp(x, y, l) _strnicmp(x, y, l)
/* Disable some of the annoying warnings. */
#pragma warning(disable : 4800)
#pragma warning(disable : 4805)
#pragma warning(disable : 4244)
#pragma warning(disable : 4305)
#pragma warning(disable : 4146)
#pragma warning(disable : 4267)
#pragma warning(disable : 4723)
#pragma warning(disable : 4996)
#define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f))
#ifndef PATH_MAX
#define PATH_MAX _MAX_PATH
#endif
#ifndef SIZE_MAX
#define SIZE_MAX _UI32_MAX
#endif
#endif
#endif

View File

@ -0,0 +1,254 @@
/* ISO C9x compliant stdint.h for Microsoft Visual Studio
* Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
*
* Copyright (c) 2006-2008 Alexander Chemeris
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RARCH_STDINT_H
#define __RARCH_STDINT_H
#if _MSC_VER && (_MSC_VER < 1600)
/* Pre-MSVC 2010 needs an implementation of stdint.h. */
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
/* For Visual Studio 6 in C++ mode and for many Visual Studio versions when
* compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
* or compiler give many errors like this:
*
* error C2733: second C linkage of overloaded function 'wmemchr' not allowed
*/
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
/* Define _W64 macros to mark types changing their size, like intptr_t. */
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
/* 7.18.1 Integer types. */
/* 7.18.1.1 Exact-width integer types. */
/* Visual Studio 6 and Embedded Visual C++ 4 doesn't
* realize that, e.g. char has the same size as __int8
* so we give up on __intX for them.
*/
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
/* 7.18.1.2 Minimum-width integer types. */
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
/* 7.18.1.3 Fastest minimum-width integer types. */
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
/* 7.18.1.4 Integer types capable of holding object pointers. */
#ifdef _WIN64 /* [ */
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else /* _WIN64 ][ */
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif /* _WIN64 ] */
/* 7.18.1.5 Greatest-width integer types. */
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
/* 7.18.2 Limits of specified-width integer types. */
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
/* [ See footnote 220 at page 257 and footnote 221 at page 259. */
/* 7.18.2.1 Limits of exact-width integer types. */
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
/* 7.18.2.2 Limits of minimum-width integer types. */
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
/* 7.18.2.3 Limits of fastest minimum-width integer types. */
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
/* 7.18.2.4 Limits of integer types capable of holding object pointers. */
#ifdef _WIN64 /* [ */
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else /* _WIN64 ][ */
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif /* _WIN64 ] */
/* 7.18.2.5 Limits of greatest-width integer types */
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
/* 7.18.3 Limits of other integer types */
#ifdef _WIN64 /* [ */
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else /* _WIN64 ][ */
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif /* _WIN64 ] */
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX /* [ */
# ifdef _WIN64 /* [ */
# define SIZE_MAX _UI64_MAX
# else /* _WIN64 ][ */
# define SIZE_MAX _UI32_MAX
# endif /* _WIN64 ] */
#endif /* SIZE_MAX ] */
/* WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> */
#ifndef WCHAR_MIN /* [ */
# define WCHAR_MIN 0
#endif /* WCHAR_MIN ] */
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif /* WCHAR_MAX ] */
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif /* __STDC_LIMIT_MACROS ] */
/* 7.18.4 Limits of other integer types */
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
/* [ See footnote 224 at page 260 */
/* 7.18.4.1 Macros for minimum-width integer constants */
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
/* 7.18.4.2 Macros for greatest-width integer constants */
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif
/* __STDC_CONSTANT_MACROS ] */
#else
/* Sanity for everything else. */
#include <stdint.h>
#endif
#endif

View File

@ -0,0 +1,53 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (posix_string.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_POSIX_STRING_H
#define __LIBRETRO_SDK_COMPAT_POSIX_STRING_H
#ifdef _MSC_VER
#include <compat/msvc.h>
#ifdef __cplusplus
extern "C" {
#endif
#undef strcasecmp
#undef strdup
#undef isblank
#undef strtok_r
#define strcasecmp(a, b) rarch_strcasecmp__(a, b)
#define strdup(orig) rarch_strdup__(orig)
#define isblank(c) rarch_isblank__(c)
#define strtok_r(str, delim, saveptr) rarch_strtok_r__(str, delim, saveptr)
int strcasecmp(const char *a, const char *b);
char *strdup(const char *orig);
int isblank(int c);
char *strtok_r(char *str, const char *delim, char **saveptr);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strcasestr.h). * ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_STRCASESTR_H
#define __LIBRETRO_SDK_COMPAT_STRCASESTR_H
#include <string.h>
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
#ifndef HAVE_STRCASESTR
#ifdef __cplusplus
extern "C" {
#endif
/* Avoid possible naming collisions during link
* since we prefer to use the actual name. */
#define strcasestr(haystack, needle) strcasestr_rarch__(haystack, needle)
char *strcasestr(const char *haystack, const char *needle);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -0,0 +1,54 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strl.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_STRL_H
#define __LIBRETRO_SDK_COMPAT_STRL_H
#include <string.h>
#include <stddef.h>
#ifdef HAVE_CONFIG_H
#include "../../../config.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef HAVE_STRL
/* Avoid possible naming collisions during link since
* we prefer to use the actual name. */
#define strlcpy(dst, src, size) strlcpy_rarch__(dst, src, size)
#define strlcat(dst, src, size) strlcat_rarch__(dst, src, size)
size_t strlcpy(char *dest, const char *source, size_t size);
size_t strlcat(char *dest, const char *source, size_t size);
#endif
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
#ifndef _COMPAT_ZUTIL_H
#define _COMPAT_ZUTIL_H
#ifdef WANT_ZLIB
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2013 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef ZUTIL_H
#define ZUTIL_H
#ifdef HAVE_HIDDEN
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
#endif
#include <compat/zlib.h>
#if defined(STDC) && !defined(Z_SOLO)
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
# include <stddef.h>
# endif
# include <string.h>
# include <stdlib.h>
#endif
#ifdef Z_SOLO
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
typedef unsigned char uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
extern char z_errmsg[10][21]; /* indexed by 2-zlib_error */
/* (array size given to avoid silly warnings with Visual C++) */
/* (array entry size given to avoid silly string cast warnings) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00
# ifndef Z_SOLO
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
# endif
#endif
#ifdef AMIGA
# define OS_CODE 0x01
#endif
#if defined(VAXC) || defined(VMS)
# define OS_CODE 0x02
# define F_OPEN(name, mode) \
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
#if defined(ATARI) || defined(atarist)
# define OS_CODE 0x05
#endif
#ifdef OS2
# define OS_CODE 0x06
# if defined(M_I86) && !defined(Z_SOLO)
# include <malloc.h>
# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 0x07
# ifndef Z_SOLO
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
# endif
# endif
#endif
#ifdef TOPS20
# define OS_CODE 0x0a
#endif
#ifdef WIN32
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
# define OS_CODE 0x0b
# endif
#endif
#ifdef __50SERIES /* Prime/PRIMOS */
# define OS_CODE 0x0f
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
# if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */
# ifndef _PTRDIFF_T_DEFINED
typedef int ptrdiff_t;
# define _PTRDIFF_T_DEFINED
# endif
# else
# define fdopen(fd,type) _fdopen(fd,type)
# endif
#endif
#if defined(__BORLANDC__) && !defined(MSDOS)
#pragma warn -8004
#pragma warn -8008
#pragma warn -8066
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_WIN32) && \
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
#endif
/* common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef F_OPEN
# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
#if defined(pyr) || defined(Z_SOLO)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
/* Use our own functions for small and medium model with MSC <= 5.0.
* You may have to use the same strategy for Borland C (untested).
* The __SC__ check is for Symantec.
*/
# define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
# define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
# define zmemcpy _fmemcpy
# define zmemcmp _fmemcmp
# define zmemzero(dest, len) _fmemset(dest, 0, len)
# else
# define zmemcpy memcpy
# define zmemcmp memcmp
# define zmemzero(dest, len) memset(dest, 0, len)
# endif
#else
void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
#endif
/* Diagnostic functions */
#ifdef DEBUG
# include <stdio.h>
extern int ZLIB_INTERNAL z_verbose;
extern void ZLIB_INTERNAL z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
#ifndef Z_SOLO
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
unsigned size));
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
#endif
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
/* Reverse the bytes in a 32-bit value */
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
#endif /* ZUTIL_H */
#else
#include <zutil.h>
#endif
#endif

View File

@ -0,0 +1,74 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dylib.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DYLIB_H
#define __DYLIB_H
#include <boolean.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
#define NEED_DYNAMIC
#else
#undef NEED_DYNAMIC
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void *dylib_t;
typedef void (*function_t)(void);
#ifdef NEED_DYNAMIC
/**
* dylib_load:
* @path : Path to libretro core library.
*
* Platform independent dylib loading.
*
* Returns: library handle on success, otherwise NULL.
**/
dylib_t dylib_load(const char *path);
/**
* dylib_close:
* @lib : Library handle.
*
* Frees library handle.
**/
void dylib_close(dylib_t lib);
char *dylib_error(void);
function_t dylib_proc(dylib_t lib, const char *proc);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,170 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (config_file.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_CONFIG_FILE_H
#define __LIBRETRO_SDK_CONFIG_FILE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <boolean.h>
struct config_entry_list
{
/* If we got this from an #include,
* do not allow overwrite. */
bool readonly;
char *key;
char *value;
uint32_t key_hash;
struct config_entry_list *next;
};
struct config_include_list
{
char *path;
struct config_include_list *next;
};
struct config_file
{
char *path;
struct config_entry_list *entries;
struct config_entry_list *tail;
unsigned include_depth;
struct config_include_list *includes;
};
typedef struct config_file config_file_t;
/* Config file format
* - # are treated as comments. Rest of the line is ignored.
* - Format is: key = value. There can be as many spaces as you like in-between.
* - Value can be wrapped inside "" for multiword strings. (foo = "hai u")
* - #include includes a config file in-place.
*
* Path is relative to where config file was loaded unless an absolute path is chosen.
* Key/value pairs from an #include are read-only, and cannot be modified.
*/
/* Loads a config file. Returns NULL if file doesn't exist.
* NULL path will create an empty config file. */
config_file_t *config_file_new(const char *path);
/* Load a config file from a string. */
config_file_t *config_file_new_from_string(const char *from_string);
/* Frees config file. */
void config_file_free(config_file_t *conf);
/* Loads a new config, and appends its data to conf.
* The key-value pairs of the new config file takes priority over the old. */
bool config_append_file(config_file_t *conf, const char *path);
/* All extract functions return true when value is valid and exists.
* Returns false otherwise. */
bool config_entry_exists(config_file_t *conf, const char *entry);
struct config_entry_list;
struct config_file_entry
{
const char *key;
const char *value;
/* Used intentionally. Opaque here. */
const struct config_entry_list *next;
};
bool config_get_entry_list_head(config_file_t *conf, struct config_file_entry *entry);
bool config_get_entry_list_next(struct config_file_entry *entry);
/* Extracts a double from config file. */
bool config_get_double(config_file_t *conf, const char *entry, double *in);
/* Extracts a float from config file. */
bool config_get_float(config_file_t *conf, const char *entry, float *in);
/* Extracts an int from config file. */
bool config_get_int(config_file_t *conf, const char *entry, int *in);
/* Extracts an uint from config file. */
bool config_get_uint(config_file_t *conf, const char *entry, unsigned *in);
/* Extracts an uint64 from config file. */
bool config_get_uint64(config_file_t *conf, const char *entry, uint64_t *in);
/* Extracts an unsigned int from config file treating input as hex. */
bool config_get_hex(config_file_t *conf, const char *entry, unsigned *in);
/* Extracts a single char. If value consists of several chars,
* this is an error. */
bool config_get_char(config_file_t *conf, const char *entry, char *in);
/* Extracts an allocated string in *in. This must be free()-d if
* this function succeeds. */
bool config_get_string(config_file_t *conf, const char *entry, char **in);
/* Extracts a string to a preallocated buffer. Avoid memory allocation. */
bool config_get_array(config_file_t *conf, const char *entry, char *in, size_t size);
/* Extracts a string to a preallocated buffer. Avoid memory allocation.
* Recognized magic like ~/. Similar to config_get_array() otherwise. */
bool config_get_path(config_file_t *conf, const char *entry, char *in, size_t size);
/* Extracts a boolean from config.
* Valid boolean true are "true" and "1". Valid false are "false" and "0".
* Other values will be treated as an error. */
bool config_get_bool(config_file_t *conf, const char *entry, bool *in);
/* Setters. Similar to the getters.
* Will not write to entry if the entry was obtained from an #include. */
void config_set_double(config_file_t *conf, const char *entry, double value);
void config_set_float(config_file_t *conf, const char *entry, float value);
void config_set_int(config_file_t *conf, const char *entry, int val);
void config_set_hex(config_file_t *conf, const char *entry, unsigned val);
void config_set_uint64(config_file_t *conf, const char *entry, uint64_t val);
void config_set_char(config_file_t *conf, const char *entry, char val);
void config_set_string(config_file_t *conf, const char *entry, const char *val);
void config_set_path(config_file_t *conf, const char *entry, const char *val);
void config_set_bool(config_file_t *conf, const char *entry, bool val);
/* Write the current config to a file. */
bool config_file_write(config_file_t *conf, const char *path);
/* Dump the current config to an already opened file.
* Does not close the file. */
void config_file_dump(config_file_t *conf, FILE *file);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,55 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (config_file_userdata.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_CONFIG_FILE_USERDATA_H
#define _LIBRETRO_SDK_CONFIG_FILE_USERDATA_H
#include <string.h>
#include "config_file.h"
struct config_file_userdata
{
config_file_t *conf;
const char *prefix[2];
};
int config_userdata_get_float(void *userdata, const char *key_str,
float *value, float default_value);
int config_userdata_get_int(void *userdata, const char *key_str,
int *value, int default_value);
int config_userdata_get_float_array(void *userdata, const char *key_str,
float **values, unsigned *out_num_values,
const float *default_values, unsigned num_default_values);
int config_userdata_get_int_array(void *userdata, const char *key_str,
int **values, unsigned *out_num_values,
const int *default_values, unsigned num_default_values);
int config_userdata_get_string(void *userdata, const char *key_str,
char **output, const char *default_output);
void config_userdata_free(void *ptr);
#endif

View File

@ -0,0 +1,70 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dir_list.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_DIR_LIST_H
#define __LIBRETRO_SDK_DIR_LIST_H
#include <string/string_list.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* dir_list_new:
* @dir : directory path.
* @ext : allowed extensions of file directory entries to include.
* @include_dirs : include directories as part of the finished directory listing?
* @include_compressed : include compressed files, even when not part of ext.
*
* Create a directory listing.
*
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
* NULL in case of error. Has to be freed manually.
**/
struct string_list *dir_list_new(const char *dir, const char *ext,
bool include_dirs, bool include_compressed);
/**
* dir_list_sort:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing.
*
**/
void dir_list_sort(struct string_list *list, bool dir_first);
/**
* dir_list_free:
* @list : pointer to the directory listing
*
* Frees a directory listing.
*
**/
void dir_list_free(struct string_list *list);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,174 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_extract.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FILE_EXTRACT_H__
#define FILE_EXTRACT_H__
#include <stdint.h>
#include <stddef.h>
#include <boolean.h>
typedef struct zlib_handle
{
void *stream;
uint8_t *data;
uint32_t real_checksum;
} zlib_file_handle_t;
enum zlib_transfer_type
{
ZLIB_TRANSFER_NONE = 0,
ZLIB_TRANSFER_INIT,
ZLIB_TRANSFER_ITERATE,
ZLIB_TRANSFER_DEINIT,
ZLIB_TRANSFER_DEINIT_ERROR
};
typedef struct zlib_transfer
{
void *handle;
const uint8_t *footer;
const uint8_t *directory;
const uint8_t *data;
int32_t zip_size;
enum zlib_transfer_type type;
const struct zlib_file_backend *backend;
} zlib_transfer_t;
/* Returns true when parsing should continue. False to stop. */
typedef int (*zlib_file_cb)(const char *name, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
uint32_t crc32, void *userdata);
uint32_t zlib_crc32_calculate(const uint8_t *data, size_t length);
uint32_t zlib_crc32_adjust(uint32_t crc, uint8_t data);
/**
* zlib_parse_file:
* @file : filename path of archive
* @valid_exts : Valid extensions of archive to be parsed.
* If NULL, allow all.
* @file_cb : file_cb function pointer
* @userdata : userdata to pass to file_cb function pointer.
*
* Low-level file parsing. Enumerates over all files and calls
* file_cb with userdata.
*
* Returns: true (1) on success, otherwise false (0).
**/
bool zlib_parse_file(const char *file, const char *valid_exts,
zlib_file_cb file_cb, void *userdata);
int zlib_parse_file_iterate(void *data, bool *returnerr,
const char *file,
const char *valid_exts, zlib_file_cb file_cb, void *userdata);
void zlib_parse_file_iterate_stop(void *data);
/**
* zlib_extract_first_content_file:
* @zip_path : filename path to ZIP archive.
* @zip_path_size : size of ZIP archive.
* @valid_exts : valid extensions for a content file.
* @extraction_directory : the directory to extract temporary
* unzipped content to.
*
* Extract first content file from archive.
*
* Returns : true (1) on success, otherwise false (0).
**/
bool zlib_extract_first_content_file(char *zip_path, size_t zip_path_size,
const char *valid_exts, const char *extraction_dir);
/**
* zlib_get_file_list:
* @path : filename path of archive
* @valid_exts : Valid extensions of archive to be parsed.
* If NULL, allow all.
*
* Returns: string listing of files from archive on success, otherwise NULL.
**/
struct string_list *zlib_get_file_list(const char *path, const char *valid_exts);
bool zlib_inflate_data_to_file_init(
zlib_file_handle_t *handle,
const uint8_t *cdata, uint32_t csize, uint32_t size);
int zlib_inflate_data_to_file_iterate(void *data);
/**
* zlib_inflate_data_to_file:
* @path : filename path of archive.
* @cdata : input data.
* @csize : size of input data.
* @size : output file size
* @checksum : CRC32 checksum from input data.
*
* Decompress data to file.
*
* Returns: true (1) on success, otherwise false (0).
**/
int zlib_inflate_data_to_file(zlib_file_handle_t *handle,
int ret, const char *path, const char *valid_exts,
const uint8_t *cdata, uint32_t csize, uint32_t size, uint32_t checksum);
bool zlib_perform_mode(const char *name, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
uint32_t crc32, void *userdata);
struct string_list *compressed_file_list_new(const char *filename,
const char* ext);
void *zlib_stream_new(void);
void zlib_stream_free(void *data);
void zlib_deflate_init(void *data, int level);
int zlib_deflate_data_to_file(void *data);
void zlib_stream_deflate_free(void *data);
bool zlib_inflate_init(void *data);
bool zlib_inflate_init2(void *data);
void zlib_set_stream(void *data,
uint32_t avail_in,
uint32_t avail_out,
const uint8_t *next_in,
uint8_t *next_out
);
uint32_t zlib_stream_get_avail_in(void *data);
uint32_t zlib_stream_get_avail_out(void *data);
uint64_t zlib_stream_get_total_out(void *data);
void zlib_stream_decrement_total_out(void *data,
unsigned subtraction);
#endif

View File

@ -0,0 +1,118 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_list.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FILE_LIST_H__
#define __LIBRETRO_SDK_FILE_LIST_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <boolean.h>
struct item_file
{
char *path;
char *label;
char *alt;
unsigned type;
size_t directory_ptr;
size_t entry_idx;
void *userdata;
void *actiondata;
};
typedef struct file_list
{
struct item_file *list;
size_t capacity;
size_t size;
} file_list_t;
void *file_list_get_userdata_at_offset(const file_list_t *list,
size_t index);
void *file_list_get_actiondata_at_offset(const file_list_t *list,
size_t index);
void file_list_free(file_list_t *list);
void file_list_push(file_list_t *userdata, const char *path,
const char *label, unsigned type, size_t current_directory_ptr,
size_t entry_index);
void file_list_pop(file_list_t *list, size_t *directory_ptr);
void file_list_clear(file_list_t *list);
void file_list_copy(const file_list_t *src, file_list_t *dst);
void file_list_get_last(const file_list_t *list,
const char **path, const char **label,
unsigned *type, size_t *entry_idx);
void *file_list_get_last_actiondata(const file_list_t *list);
size_t file_list_get_size(const file_list_t *list);
size_t file_list_get_entry_index(const file_list_t *list);
size_t file_list_get_directory_ptr(const file_list_t *list);
void file_list_get_at_offset(const file_list_t *list, size_t index,
const char **path, const char **label,
unsigned *type, size_t *entry_idx);
void file_list_free_userdata(const file_list_t *list, size_t index);
void file_list_free_actiondata(const file_list_t *list, size_t idx);
void file_list_set_label_at_offset(file_list_t *list, size_t index,
const char *label);
void file_list_get_label_at_offset(const file_list_t *list, size_t index,
const char **label);
void file_list_set_alt_at_offset(file_list_t *list, size_t index,
const char *alt);
void file_list_set_userdata(const file_list_t *list, size_t idx, void *ptr);
void file_list_set_actiondata(const file_list_t *list, size_t idx, void *ptr);
void file_list_get_alt_at_offset(const file_list_t *list, size_t index,
const char **alt);
void file_list_sort_on_alt(file_list_t *list);
void file_list_sort_on_type(file_list_t *list);
bool file_list_search(const file_list_t *list, const char *needle,
size_t *index);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,396 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_path.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FILE_PATH_H
#define __LIBRETRO_SDK_FILE_PATH_H
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <sys/types.h>
#include <boolean.h>
#include <retro_inline.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Order in this enum is equivalent to negative sort order in filelist
* (i.e. DIRECTORY is on top of PLAIN_FILE) */
enum
{
RARCH_FILETYPE_UNSET,
RARCH_PLAIN_FILE,
RARCH_COMPRESSED_FILE_IN_ARCHIVE,
RARCH_COMPRESSED_ARCHIVE,
RARCH_DIRECTORY,
RARCH_FILE_UNSUPPORTED
};
/**
* path_is_compressed_file:
* @path : path
*
* Checks if path is a compressed file.
*
* Returns: true (1) if path is a compressed file, otherwise false (0).
**/
bool path_is_compressed_file(const char *path);
/**
* path_contains_compressed_file:
* @path : path
*
* Checks if path contains a compressed file.
*
* Currently we only check for hash symbol (#) inside the pathname.
* If path is ever expanded to a general URI, we should check for that here.
*
* Example: Somewhere in the path there might be a compressed file
* E.g.: /path/to/file.7z#mygame.img
*
* Returns: true (1) if path contains compressed file, otherwise false (0).
**/
bool path_contains_compressed_file(const char *path);
/**
* path_file_exists:
* @path : path
*
* Checks if a file already exists at the specified path (@path).
*
* Returns: true (1) if file already exists, otherwise false (0).
*/
bool path_file_exists(const char *path);
/**
* path_get_extension:
* @path : path
*
* Gets extension of file. Only '.'s
* after the last slash are considered.
*
* Returns: extension part from the path.
*/
const char *path_get_extension(const char *path);
/**
* path_remove_extension:
* @path : path
*
* Removes the extension from the path and returns the result.
* Removes all text after and including the last '.'.
* Only '.'s after the last slash are considered.
*
* Returns: path with the extension part removed.
*/
char *path_remove_extension(char *path);
/**
* path_basename:
* @path : path
*
* Get basename from @path.
*
* Returns: basename from path.
**/
const char *path_basename(const char *path);
/**
* path_basedir:
* @path : path
*
* Extracts base directory by mutating path.
* Keeps trailing '/'.
**/
void path_basedir(char *path);
/**
* path_parent_dir:
* @path : path
*
* Extracts parent directory by mutating path.
* Assumes that path is a directory. Keeps trailing '/'.
**/
void path_parent_dir(char *path);
/**
* path_resolve_realpath:
* @buf : buffer for path
* @size : size of buffer
*
* Turns relative paths into absolute path.
* If relative, rebases on current working dir.
**/
void path_resolve_realpath(char *buf, size_t size);
/**
* path_is_absolute:
* @path : path
*
* Checks if @path is an absolute path or a relative path.
*
* Returns: true (1) if path is absolute, false (1) if path is relative.
**/
bool path_is_absolute(const char *path);
/**
* fill_pathname:
* @out_path : output path
* @in_path : input path
* @replace : what to replace
* @size : buffer size of output path
*
* FIXME: Verify
*
* Replaces filename extension with 'replace' and outputs result to out_path.
* The extension here is considered to be the string from the last '.'
* to the end.
*
* Only '.'s after the last slash are considered as extensions.
* If no '.' is present, in_path and replace will simply be concatenated.
* 'size' is buffer size of 'out_path'.
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" =>
* out_path = "/foo/bar/baz/boo.asm"
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" =>
* out_path = "/foo/bar/baz/boo"
*/
void fill_pathname(char *out_path, const char *in_path,
const char *replace, size_t size);
/**
* fill_dated_filename:
* @out_filename : output filename
* @ext : extension of output filename
* @size : buffer size of output filename
*
* Creates a 'dated' filename prefixed by 'RetroArch', and
* concatenates extension (@ext) to it.
*
* E.g.:
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
**/
void fill_dated_filename(char *out_filename,
const char *ext, size_t size);
/**
* fill_pathname_noext:
* @out_path : output path
* @in_path : input path
* @replace : what to replace
* @size : buffer size of output path
*
* Appends a filename extension 'replace' to 'in_path', and outputs
* result in 'out_path'.
*
* Assumes in_path has no extension. If an extension is still
* present in 'in_path', it will be ignored.
*
*/
void fill_pathname_noext(char *out_path, const char *in_path,
const char *replace, size_t size);
/**
* fill_pathname_dir:
* @in_dir : input directory path
* @in_basename : input basename to be appended to @in_dir
* @replace : replacement to be appended to @in_basename
* @size : size of buffer
*
* Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
* Basename of in_basename is the string after the last '/' or '\\',
* i.e the filename without directories.
*
* If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
* 'size' is buffer size of 'in_dir'.
*
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
**/
void fill_pathname_dir(char *in_dir, const char *in_basename,
const char *replace, size_t size);
/**
* fill_pathname_base:
* @out : output path
* @in_path : input path
* @size : size of output path
*
* Copies basename of @in_path into @out_path.
**/
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
/**
* fill_pathname_basedir:
* @out_dir : output directory
* @in_path : input path
* @size : size of output directory
*
* Copies base directory of @in_path into @out_path.
* If in_path is a path without any slashes (relative current directory),
* @out_path will get path "./".
**/
void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
/**
* fill_pathname_parent_dir:
* @out_dir : output directory
* @in_dir : input directory
* @size : size of output directory
*
* Copies parent directory of @in_dir into @out_dir.
* Assumes @in_dir is a directory. Keeps trailing '/'.
**/
void fill_pathname_parent_dir(char *out_dir,
const char *in_dir, size_t size);
/**
* fill_pathname_resolve_relative:
* @out_path : output path
* @in_refpath : input reference path
* @in_path : input path
* @size : size of @out_path
*
* Joins basedir of @in_refpath together with @in_path.
* If @in_path is an absolute path, out_path = in_path.
* E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg",
* out_path = "/foo/bar/foobar.cg".
**/
void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
const char *in_path, size_t size);
/**
* fill_pathname_join:
* @out_path : output path
* @dir : directory
* @path : path
* @size : size of output path
*
* Joins a directory (@dir) and path (@path) together.
* Makes sure not to get two consecutive slashes
* between directory and path.
**/
void fill_pathname_join(char *out_path, const char *dir,
const char *path, size_t size);
/**
* fill_pathname_join_delim:
* @out_path : output path
* @dir : directory
* @path : path
* @delim : delimiter
* @size : size of output path
*
* Joins a directory (@dir) and path (@path) together
* using the given delimiter (@delim).
**/
void fill_pathname_join_delim(char *out_path, const char *dir,
const char *path, const char delim, size_t size);
/**
* fill_short_pathname_representation:
* @out_rep : output representation
* @in_path : input path
* @size : size of output representation
*
* Generates a short representation of path. It should only
* be used for displaying the result; the output representation is not
* binding in any meaningful way (for a normal path, this is the same as basename)
* In case of more complex URLs, this should cut everything except for
* the main image file.
*
* E.g.: "/path/to/game.img" -> game.img
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
*/
void fill_short_pathname_representation(char* out_rep,
const char *in_path, size_t size);
void fill_pathname_expand_special(char *out_path,
const char *in_path, size_t size);
void fill_pathname_abbreviate_special(char *out_path,
const char *in_path, size_t size);
/**
* path_char_is_slash:
* @c : character
*
* Checks if character (@c) is a slash.
*
* Returns: true (1) if character is a slash, otherwise false (0).
*/
static INLINE bool path_char_is_slash(char c)
{
#ifdef _WIN32
return (c == '/') || (c == '\\');
#else
return (c == '/');
#endif
}
/**
* path_default_slash:
*
* Gets the default slash separator.
*
* Returns: default slash separator.
*/
static INLINE const char *path_default_slash(void)
{
#ifdef _WIN32
return "\\";
#else
return "/";
#endif
}
/**
* fill_pathname_slash:
* @path : path
* @size : size of path
*
* Assumes path is a directory. Appends a slash
* if not already there.
**/
void fill_pathname_slash(char *path, size_t size);
#ifndef RARCH_CONSOLE
void fill_pathname_application_path(char *buf, size_t size);
#endif
/**
* path_mkdir:
* @dir : directory
*
* Create directory on filesystem.
*
* Returns: true (1) if directory could be created, otherwise false (0).
**/
bool path_mkdir(const char *dir);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,51 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memory_stream.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_FILE_MEMORY_STREAM_H
#define _LIBRETRO_SDK_FILE_MEMORY_STREAM_H
#include <stdint.h>
#include <stddef.h>
typedef struct memstream memstream_t;
memstream_t *memstream_open(void);
void memstream_close(memstream_t * stream);
size_t memstream_read(memstream_t * stream, void *data, size_t bytes);
size_t memstream_write(memstream_t * stream, const void *data, size_t bytes);
int memstream_getc(memstream_t * stream);
char *memstream_gets(memstream_t * stream, char *buffer, size_t len);
size_t memstream_pos(memstream_t * stream);
int memstream_seek(memstream_t * stream, int offset, int whence);
void memstream_set_buffer(uint8_t *buffer, size_t size);
size_t memstream_get_last_size(void);
#endif

View File

@ -0,0 +1,96 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dir_list.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_NBIO_H
#define __LIBRETRO_SDK_NBIO_H
#include <stddef.h>
#include <boolean.h>
#ifndef NBIO_READ
#define NBIO_READ 0
#endif
#ifndef NBIO_WRITE
#define NBIO_WRITE 1
#endif
#ifndef NBIO_UPDATE
#define NBIO_UPDATE 2
#endif
#ifndef BIO_READ
#define BIO_READ 3
#endif
#ifndef BIO_WRITE
#define BIO_WRITE 4
#endif
struct nbio_t;
/*
* Creates an nbio structure for performing the given operation on the given file.
*/
struct nbio_t* nbio_open(const char * filename, unsigned mode);
/*
* Starts reading the given file. When done, it will be available in nbio_get_ptr.
* Can not be done if the structure was created with nbio_write.
*/
void nbio_begin_read(struct nbio_t* handle);
/*
* Starts writing to the given file. Before this, you should've copied the data to nbio_get_ptr.
* Can not be done if the structure was created with nbio_read.
*/
void nbio_begin_write(struct nbio_t* handle);
/*
* Performs part of the requested operation, or checks how it's going.
* When it returns true, it's done.
*/
bool nbio_iterate(struct nbio_t* handle);
/*
* Resizes the file up to the given size; cannot shrink.
* Can not be done if the structure was created with nbio_read.
*/
void nbio_resize(struct nbio_t* handle, size_t len);
/*
* Returns a pointer to the file data. Writable only if structure was not created with nbio_read.
* If any operation is in progress, the pointer will be NULL, but len will still be correct.
*/
void* nbio_get_ptr(struct nbio_t* handle, size_t* len);
/*
* Stops any pending operation, allowing the object to be freed.
*/
void nbio_cancel(struct nbio_t* handle);
/*
* Deletes the nbio structure and its associated pointer.
*/
void nbio_free(struct nbio_t* handle);
#endif

View File

@ -0,0 +1,73 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (filters.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_FILTERS_H
#define _LIBRETRO_SDK_FILTERS_H
#include <math.h>
#include <retro_inline.h>
static INLINE double sinc(double val)
{
if (fabs(val) < 0.00001)
return 1.0;
return sin(val) / val;
}
/* Modified Bessel function of first order.
* Check Wiki for mathematical definition ... */
static INLINE double besseli0(double x)
{
unsigned i;
double sum = 0.0;
double factorial = 1.0;
double factorial_mult = 0.0;
double x_pow = 1.0;
double two_div_pow = 1.0;
double x_sqr = x * x;
/* Approximate. This is an infinite sum.
* Luckily, it converges rather fast. */
for (i = 0; i < 18; i++)
{
sum += x_pow * two_div_pow / (factorial * factorial);
factorial_mult += 1.0;
x_pow *= x_sqr;
two_div_pow *= 0.25;
factorial *= factorial_mult;
}
return sum;
}
static INLINE double kaiser_window_function(double index, double beta)
{
return besseli0(beta * sqrtf(1 - index * index));
}
static INLINE double lanzcos_window_function(double index)
{
return sinc(M_PI * index);
}
#endif

View File

@ -0,0 +1,62 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2015 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_IMAGE_CONTEXT_H
#define __RARCH_IMAGE_CONTEXT_H
#include <stdint.h>
#include <boolean.h>
#ifdef __cplusplus
extern "C" {
#endif
enum image_process_code
{
IMAGE_PROCESS_ERROR = -2,
IMAGE_PROCESS_ERROR_END = -1,
IMAGE_PROCESS_NEXT = 0,
IMAGE_PROCESS_END = 1
};
struct texture_image
{
unsigned width;
unsigned height;
#ifdef _XBOX1
unsigned x;
unsigned y;
void *texture_buf;
void *vertex_buf;
#endif
uint32_t *pixels;
};
bool texture_image_set_color_shifts(unsigned *r_shift, unsigned *g_shift,
unsigned *b_shift, unsigned *a_shift);
bool texture_image_color_convert(unsigned r_shift,
unsigned g_shift, unsigned b_shift, unsigned a_shift,
struct texture_image *out_img);
bool texture_image_load(struct texture_image *img, const char *path);
void texture_image_free(struct texture_image *img);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,48 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rbmp.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FORMAT_RBMP_H__
#define __LIBRETRO_SDK_FORMAT_RBMP_H__
#include <boolean.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
RBMP_SOURCE_TYPE_BGR24,
RBMP_SOURCE_TYPE_XRGB888,
RBMP_SOURCE_TYPE_RGB565,
RBMP_SOURCE_TYPE_ARGB8888,
} rbmp_source_type;
bool rbmp_save_image(const char *filename, const void *frame,
unsigned width, unsigned height,
unsigned pitch, rbmp_source_type type);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,70 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rpng.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FORMAT_RPNG_H__
#define __LIBRETRO_SDK_FORMAT_RPNG_H__
#include <stdint.h>
#include <stddef.h>
#include <boolean.h>
#include <file/file_extract.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct rpng rpng_t;
bool rpng_load_image_argb(const char *path, uint32_t **data,
unsigned *width, unsigned *height);
rpng_t *rpng_nbio_load_image_argb_init(const char *path);
bool rpng_is_valid(rpng_t *rpng);
bool rpng_set_buf_ptr(rpng_t *rpng, uint8_t *data);
rpng_t *rpng_alloc(void);
void rpng_nbio_load_image_free(rpng_t *rpng);
bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng);
int rpng_nbio_load_image_argb_process(rpng_t *rpng,
uint32_t **data, unsigned *width, unsigned *height);
bool rpng_nbio_load_image_argb_start(rpng_t *rpng);
#ifdef HAVE_ZLIB_DEFLATE
bool rpng_save_image_argb(const char *path, const uint32_t *data,
unsigned width, unsigned height, unsigned pitch);
bool rpng_save_image_bgr24(const char *path, const uint8_t *data,
unsigned width, unsigned height, unsigned pitch);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,97 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rxml.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FORMAT_RXML_H__
#define __LIBRETRO_SDK_FORMAT_RXML_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Total NIH. Very trivial "XML" implementation for use in RetroArch.
* Error checking is minimal. Invalid documents may lead to very
* buggy behavior, but memory corruption should never happen.
*
* Only parts of standard that RetroArch cares about is supported.
* Nothing more, nothing less. "Clever" XML documents will
* probably break the implementation.
*
* Do *NOT* try to use this for anything else. You have been warned.
*/
typedef struct rxml_document rxml_document_t;
struct rxml_attrib_node
{
char *attrib;
char *value;
struct rxml_attrib_node *next;
};
struct rxml_node
{
char *name;
char *data;
struct rxml_attrib_node *attrib;
struct rxml_node *children;
struct rxml_node *next;
/* Dummy. Used by libxml2 compat.
* Is always set to 0, so XML_ELEMENT_NODE check goes through. */
int type;
};
rxml_document_t *rxml_load_document(const char *path);
void rxml_free_document(rxml_document_t *doc);
struct rxml_node *rxml_root_node(rxml_document_t *doc);
/* Drop const-correctness here to avoid warnings
* when used as libxml2 compat.
* xmlGetProp() returns xmlChar*, which is supposed
* to be passed to xmlFree(). */
char *rxml_node_attrib(struct rxml_node *node, const char *attrib);
#ifdef RXML_LIBXML2_COMPAT
/* Compat for part of libxml2 that RetroArch uses. */
#define LIBXML_TEST_VERSION ((void)0)
typedef char xmlChar; /* It's really unsigned char, but it doesn't matter. */
typedef struct rxml_node *xmlNodePtr;
typedef void *xmlParserCtxtPtr;
typedef rxml_document_t *xmlDocPtr;
#define XML_ELEMENT_NODE (0)
#define xmlNewParserCtxt() ((void*)-1)
#define xmlCtxtReadFile(ctx, path, a, b) rxml_load_document(path)
#define xmlGetProp(node, prop) rxml_node_attrib(node, prop)
#define xmlFree(p) ((void)0)
#define xmlNodeGetContent(node) (node->data)
#define xmlDocGetRootElement(doc) rxml_root_node(doc)
#define xmlFreeDoc(doc) rxml_free_document(doc)
#define xmlFreeParserCtxt(ctx) ((void)0)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rpng.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FORMAT_RTGA_H__
#define __LIBRETRO_SDK_FORMAT_RTGA_H__
#include <stdint.h>
#include <stddef.h>
#include <boolean.h>
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
bool rtga_image_load_shift(uint8_t *buf,
void *data,
unsigned a_shift, unsigned r_shift,
unsigned g_shift, unsigned b_shift);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,69 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (matrix_3x3.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_GFX_MATH_MATRIX_3X3_H__
#define __LIBRETRO_SDK_GFX_MATH_MATRIX_3X3_H__
#include <boolean.h>
typedef struct math_matrix_3x3
{
float data[9];
} math_matrix_3x3;
#define MAT_ELEM_3X3(mat, r, c) ((mat).data[3 * (r) + (c)])
void matrix_3x3_inits(math_matrix_3x3 *mat,
const float n11, const float n12, const float n13,
const float n21, const float n22, const float n23,
const float n31, const float n32, const float n33);
void matrix_3x3_identity(math_matrix_3x3 *mat);
void matrix_3x3_transpose(math_matrix_3x3 *out, const math_matrix_3x3 *in);
void matrix_3x3_multiply(math_matrix_3x3 *out,
const math_matrix_3x3 *a, const math_matrix_3x3 *b);
void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, float s);
float matrix_3x3_determinant(const math_matrix_3x3 *mat);
void matrix_3x3_adjoint(math_matrix_3x3 *mat);
bool matrix_3x3_invert(math_matrix_3x3 *mat);
bool matrix_3x3_square_to_quad(const float dx0, const float dy0,
const float dx1, const float dy1,
const float dx3, const float dy3,
const float dx2, const float dy2,
math_matrix_3x3 *mat);
bool matrix_3x3_quad_to_square(const float sx0, const float sy0,
const float sx1, const float sy1,
const float sx2, const float sy2,
const float sx3, const float sy3,
math_matrix_3x3 *mat);
bool matrix_3x3_quad_to_quad(const float dx0, const float dy0,
const float dx1, const float dy1,
const float dx2, const float dy2,
const float dx3, const float dy3,
const float sx0, const float sy0,
const float sx1, const float sy1,
const float sx2, const float sy2,
const float sx3, const float sy3,
math_matrix_3x3 *mat);
#endif

View File

@ -0,0 +1,57 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (matrix.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_GFX_MATH_MATRIX_4X4_H__
#define __LIBRETRO_SDK_GFX_MATH_MATRIX_4X4_H__
/* Column-major matrix (OpenGL-style).
* Reimplements functionality from FF OpenGL pipeline to be able
* to work on GLES 2.0 and modern GL variants.
*/
typedef struct math_matrix_4x4
{
float data[16];
} math_matrix_4x4;
#define MAT_ELEM_4X4(mat, r, c) ((mat).data[4 * (c) + (r)])
void matrix_4x4_identity(math_matrix_4x4 *mat);
void matrix_4x4_transpose(math_matrix_4x4 *out, const math_matrix_4x4 *in);
void matrix_4x4_rotate_x(math_matrix_4x4 *mat, float rad);
void matrix_4x4_rotate_y(math_matrix_4x4 *mat, float rad);
void matrix_4x4_rotate_z(math_matrix_4x4 *mat, float rad);
void matrix_4x4_ortho(math_matrix_4x4 *mat,
float left, float right,
float bottom, float top,
float znear, float zfar);
void matrix_4x4_multiply(math_matrix_4x4 *out, const math_matrix_4x4 *a, const math_matrix_4x4 *b);
void matrix_4x4_scale(math_matrix_4x4 *out, float x, float y, float z);
void matrix_4x4_translate(math_matrix_4x4 *out, float x, float y, float z);
void matrix_4x4_projection(math_matrix_4x4 *out, float znear, float zfar);
#endif

View File

@ -0,0 +1,40 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (filter.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_SCALER_FILTER_H__
#define __LIBRETRO_SDK_SCALER_FILTER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <boolean.h>
#include <gfx/scaler/scaler.h>
bool scaler_gen_filter(struct scaler_ctx *ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,93 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (pixconv.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_SCALER_PIXCONV_H__
#define __LIBRETRO_SDK_SCALER_PIXCONV_H__
#include <clamping.h>
void conv_0rgb1555_argb8888(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_0rgb1555_rgb565(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_rgb565_0rgb1555(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_rgb565_argb8888(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_rgba4444_argb8888(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_rgba4444_rgb565(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_bgr24_argb8888(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_argb8888_0rgb1555(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_argb8888_rgba4444(void *output_, const void *input_,
int width, int height,
int out_stride, int in_stride);
void conv_argb8888_rgb565(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_argb8888_bgr24(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_argb8888_abgr8888(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_0rgb1555_bgr24(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_rgb565_bgr24(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_yuyv_argb8888(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
void conv_copy(void *output, const void *input,
int width, int height,
int out_stride, int in_stride);
#endif

View File

@ -0,0 +1,153 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (scaler.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_SCALER_H__
#define __LIBRETRO_SDK_SCALER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <boolean.h>
#include <clamping.h>
#define FILTER_UNITY (1 << 14)
enum scaler_pix_fmt
{
SCALER_FMT_ARGB8888 = 0,
SCALER_FMT_ABGR8888,
SCALER_FMT_0RGB1555,
SCALER_FMT_RGB565,
SCALER_FMT_BGR24,
SCALER_FMT_YUYV,
SCALER_FMT_RGBA4444
};
enum scaler_type
{
SCALER_TYPE_UNKNOWN = 0,
SCALER_TYPE_POINT,
SCALER_TYPE_BILINEAR,
SCALER_TYPE_SINC
};
struct scaler_filter
{
int16_t *filter;
int filter_len;
int filter_stride;
int *filter_pos;
};
struct scaler_ctx
{
int in_width;
int in_height;
int in_stride;
int out_width;
int out_height;
int out_stride;
enum scaler_pix_fmt in_fmt;
enum scaler_pix_fmt out_fmt;
enum scaler_type scaler_type;
void (*scaler_horiz)(const struct scaler_ctx*,
const void*, int);
void (*scaler_vert)(const struct scaler_ctx*,
void*, int);
void (*scaler_special)(const struct scaler_ctx*,
void*, const void*, int, int, int, int, int, int);
void (*in_pixconv)(void*, const void*, int, int, int, int);
void (*out_pixconv)(void*, const void*, int, int, int, int);
void (*direct_pixconv)(void*, const void*, int, int, int, int);
bool unscaled;
struct scaler_filter horiz, vert;
struct
{
uint32_t *frame;
int stride;
} input;
struct
{
uint64_t *frame;
int width;
int height;
int stride;
} scaled;
struct
{
uint32_t *frame;
int stride;
} output;
};
bool scaler_ctx_gen_filter(struct scaler_ctx *ctx);
void scaler_ctx_gen_reset(struct scaler_ctx *ctx);
/**
* scaler_ctx_scale:
* @ctx : pointer to scaler context object.
* @output : pointer to output image.
* @input : pointer to input image.
*
* Scales an input image to an output image.
**/
void scaler_ctx_scale(struct scaler_ctx *ctx,
void *output, const void *input);
/**
* scaler_alloc:
* @elem_size : size of the elements to be used.
* @siz : size of the image that the scaler needs to handle.
*
* Allocate and returns a scaler object.
*
* Returns: pointer to a scaler object of type 'void *' on success,
* NULL in case of error. Has to be freed manually.
**/
void *scaler_alloc(size_t elem_size, size_t size);
/**
* scaler_free:
* @ptr : pointer to scaler object.
*
* Frees a scaler object.
**/
void scaler_free(void *ptr);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,41 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (scaler_int.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_SCALER_INT_H__
#define __LIBRETRO_SDK_SCALER_INT_H__
#include <gfx/scaler/scaler.h>
void scaler_argb8888_vert(const struct scaler_ctx *ctx,
void *output, int stride);
void scaler_argb8888_horiz(const struct scaler_ctx *ctx,
const void *input, int stride);
void scaler_argb8888_point_special(const struct scaler_ctx *ctx,
void *output, const void *input,
int out_width, int out_height,
int in_width, int in_height,
int out_stride, int in_stride);
#endif

View File

@ -0,0 +1,37 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro SDK code part (glsym).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_GLSYM_H__
#define __LIBRETRO_SDK_GLSYM_H__
#include "rglgen.h"
#ifndef HAVE_PSGL
#ifdef HAVE_OPENGLES2
#include "glsym_es2.h"
#else
#include "glsym_gl.h"
#endif
#endif
#endif

View File

@ -0,0 +1,145 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro SDK code part (glsym).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef RGLGEN_DECL_H__
#define RGLGEN_DECL_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef GL_APIENTRY
typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);
typedef void (GL_APIENTRY *RGLGENGLDEBUGPROCKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);
#else
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef APIENTRYP
#define APIENTRYP APIENTRY *
#endif
typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);
typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);
#endif
#ifndef GL_OES_EGL_image
typedef void *GLeglImageOES;
#endif
#if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2)
typedef GLint GLfixed;
#endif
#if defined(OSX) && !defined(MAC_OS_X_VERSION_10_7)
typedef long long int GLint64;
typedef unsigned long long int GLuint64;
typedef unsigned long long int GLuint64EXT;
typedef struct __GLsync *GLsync;
#endif
typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC) (RGLGENGLDEBUGPROCKHR callback, const void *userParam);
typedef GLuint (GL_APIENTRYP RGLSYMGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
typedef void (GL_APIENTRYP RGLSYMGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
typedef void (GL_APIENTRYP RGLSYMGLPOPDEBUGGROUPKHRPROC) (void);
typedef void (GL_APIENTRYP RGLSYMGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
typedef void (GL_APIENTRYP RGLSYMGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label);
typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
typedef void (GL_APIENTRYP RGLSYMGLGETPOINTERVKHRPROC) (GLenum pname, void **params);
typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
typedef void (GL_APIENTRYP RGLSYMGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
typedef GLboolean (GL_APIENTRYP RGLSYMGLUNMAPBUFFEROESPROC) (GLenum target);
typedef void (GL_APIENTRYP RGLSYMGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params);
typedef void (GL_APIENTRYP RGLSYMGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
typedef void (GL_APIENTRYP RGLSYMGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
typedef void (GL_APIENTRYP RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
typedef void (GL_APIENTRYP RGLSYMGLBINDVERTEXARRAYOESPROC) (GLuint array);
typedef void (GL_APIENTRYP RGLSYMGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
typedef void (GL_APIENTRYP RGLSYMGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
typedef GLboolean (GL_APIENTRYP RGLSYMGLISVERTEXARRAYOESPROC) (GLuint array);
#define glDebugMessageControlKHR __rglgen_glDebugMessageControlKHR
#define glDebugMessageInsertKHR __rglgen_glDebugMessageInsertKHR
#define glDebugMessageCallbackKHR __rglgen_glDebugMessageCallbackKHR
#define glGetDebugMessageLogKHR __rglgen_glGetDebugMessageLogKHR
#define glPushDebugGroupKHR __rglgen_glPushDebugGroupKHR
#define glPopDebugGroupKHR __rglgen_glPopDebugGroupKHR
#define glObjectLabelKHR __rglgen_glObjectLabelKHR
#define glGetObjectLabelKHR __rglgen_glGetObjectLabelKHR
#define glObjectPtrLabelKHR __rglgen_glObjectPtrLabelKHR
#define glGetObjectPtrLabelKHR __rglgen_glGetObjectPtrLabelKHR
#define glGetPointervKHR __rglgen_glGetPointervKHR
#define glEGLImageTargetTexture2DOES __rglgen_glEGLImageTargetTexture2DOES
#define glEGLImageTargetRenderbufferStorageOES __rglgen_glEGLImageTargetRenderbufferStorageOES
#define glGetProgramBinaryOES __rglgen_glGetProgramBinaryOES
#define glProgramBinaryOES __rglgen_glProgramBinaryOES
#define glMapBufferOES __rglgen_glMapBufferOES
#define glUnmapBufferOES __rglgen_glUnmapBufferOES
#define glGetBufferPointervOES __rglgen_glGetBufferPointervOES
#define glTexImage3DOES __rglgen_glTexImage3DOES
#define glTexSubImage3DOES __rglgen_glTexSubImage3DOES
#define glCopyTexSubImage3DOES __rglgen_glCopyTexSubImage3DOES
#define glCompressedTexImage3DOES __rglgen_glCompressedTexImage3DOES
#define glCompressedTexSubImage3DOES __rglgen_glCompressedTexSubImage3DOES
#define glFramebufferTexture3DOES __rglgen_glFramebufferTexture3DOES
#define glBindVertexArrayOES __rglgen_glBindVertexArrayOES
#define glDeleteVertexArraysOES __rglgen_glDeleteVertexArraysOES
#define glGenVertexArraysOES __rglgen_glGenVertexArraysOES
#define glIsVertexArrayOES __rglgen_glIsVertexArrayOES
extern RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR;
extern RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR;
extern RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR;
extern RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR;
extern RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR;
extern RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR;
extern RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR;
extern RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR;
extern RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR;
extern RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR;
extern RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR;
extern RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES;
extern RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES;
extern RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES;
extern RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES;
extern RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES;
extern RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES;
extern RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES;
extern RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES;
extern RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES;
extern RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES;
extern RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES;
extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES;
extern RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES;
extern RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES;
extern RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES;
extern RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES;
extern RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES;
struct rglgen_sym_map { const char *sym; void *ptr; };
extern const struct rglgen_sym_map rglgen_symbol_map[];
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro SDK code part (glsym).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef RGLGEN_H__
#define RGLGEN_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "rglgen_headers.h"
#ifdef __cplusplus
extern "C" {
#endif
struct rglgen_sym_map;
typedef void (*rglgen_func_t)(void);
typedef rglgen_func_t (*rglgen_proc_address_t)(const char*);
void rglgen_resolve_symbols(rglgen_proc_address_t proc);
void rglgen_resolve_symbols_custom(rglgen_proc_address_t proc,
const struct rglgen_sym_map *map);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,80 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro SDK code part (glsym).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef RGLGEN_HEADERS_H__
#define RGLGEN_HEADERS_H__
#ifdef HAVE_EGL
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
#if defined(IOS)
#if defined(HAVE_OPENGLES3)
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#else
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#endif
#elif defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#elif defined(HAVE_PSGL)
#include <PSGL/psgl.h>
#include <GLES/glext.h>
#elif defined(HAVE_OPENGL_MODERN)
#include <GL3/gl3.h>
#include <GL3/gl3ext.h>
#elif defined(HAVE_OPENGLES3)
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h> /* There are no GLES3 extensions yet. */
#elif defined(HAVE_OPENGLES2)
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#elif defined(HAVE_OPENGLES1)
#include <GLES/gl.h>
#include <GLES/glext.h>
#else
#if defined(_WIN32) && !defined(_XBOX)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glext.h>
#endif
#ifndef GL_MAP_WRITE_BIT
#define GL_MAP_WRITE_BIT 0x0002
#endif
#ifndef GL_MAP_INVALIDATE_BUFFER_BIT
#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
#endif
#ifndef GL_RED_INTEGER
#define GL_RED_INTEGER 0x8D94
#endif
#endif

View File

@ -0,0 +1,81 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (libco.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBCO_H
#define LIBCO_H
#ifdef LIBCO_C
#ifdef LIBCO_MP
#define thread_local __thread
#else
#define thread_local
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void* cothread_t;
/**
* co_active:
*
* Gets the currently active context.
*
* Returns: active context.
**/
cothread_t co_active(void);
/**
* co_create:
* @int : stack size
* @funcptr : thread entry function callback
*
* Create a co_thread.
*
* Returns: cothread if successful, otherwise NULL.
*/
cothread_t co_create(unsigned int, void (*)(void));
/**
* co_delete:
* @cothread : cothread object
*
* Frees a co_thread.
*/
void co_delete(cothread_t cothread);
/**
* co_switch:
* @cothread : cothread object to switch to
*
* Do a context switch to @cothread.
*/
void co_switch(cothread_t cothread);
#ifdef __cplusplus
}
#endif
/* ifndef LIBCO_H */
#endif

View File

@ -0,0 +1,40 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memalign.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_MEMALIGN_H
#define _LIBRETRO_MEMALIGN_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *memalign_alloc(size_t boundary, size_t size);
void memalign_free(void *ptr);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_MEMMAP_H
#define _LIBRETRO_MEMMAP_H
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h>
#include <errno.h>
#include <io.h>
#else
#define HAVE_MMAN
#include <sys/mman.h>
#endif
#if !defined(HAVE_MMAN) || defined(_WIN32)
void* mmap(void *addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off);
int munmap(void *addr, size_t len);
int mprotect(void *addr, size_t len, int prot);
#endif
int memsync(void *start, void *end);
int memprotect(void *addr, size_t len);
#endif

View File

@ -0,0 +1,206 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2015 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETPLAY_COMPAT_H__
#define NETPLAY_COMPAT_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <boolean.h>
#include <retro_inline.h>
#include <stdint.h>
#if defined(_WIN32) && !defined(_XBOX)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#elif defined(_XBOX)
#define NOD3D
#include <xtl.h>
#include <io.h>
#elif defined(GEKKO)
#include <network.h>
#elif defined(VITA)
#include <psp2/net/net.h>
#include <psp2/net/netctl.h>
#define sockaddr_in SceNetSockaddrIn
#define sockaddr SceNetSockaddr
#define sendto sceNetSendto
#define MSG_DONTWAIT PSP2_NET_MSG_DONTWAIT
#else
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifndef __PSL1GHT__
#include <netinet/tcp.h>
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
#include <cell/sysmodule.h>
#include <netex/net.h>
#include <netex/libnetctl.h>
#include <sys/timer.h>
#ifndef EWOULDBLOCK
#define EWOULDBLOCK SYS_NET_EWOULDBLOCK
#endif
#else
#include <signal.h>
#endif
#endif
#include <errno.h>
#ifdef GEKKO
#define sendto(s, msg, len, flags, addr, tolen) net_sendto(s, msg, len, 0, addr, 8)
#define socket(domain, type, protocol) net_socket(domain, type, protocol)
static INLINE int inet_pton(int af, const char *src, void *dst)
{
if (af != AF_INET)
return -1;
return inet_aton (src, dst);
}
#endif
static INLINE bool isagain(int bytes)
{
#if defined(_WIN32)
if (bytes != SOCKET_ERROR)
return false;
if (WSAGetLastError() != WSAEWOULDBLOCK)
return false;
return true;
#else
return (bytes < 0 && (errno == EAGAIN || errno == EWOULDBLOCK));
#endif
}
#ifdef _XBOX
#define socklen_t int
#ifndef h_addr
#define h_addr h_addr_list[0] /* for backward compatibility */
#endif
#ifndef SO_KEEPALIVE
#define SO_KEEPALIVE 0 /* verify if correct */
#endif
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#ifndef _WIN32
#include <sys/time.h>
#include <unistd.h>
#endif
/* Compatibility layer for legacy or incomplete BSD socket implementations.
* Only for IPv4. Mostly useful for the consoles which do not support
* anything reasonably modern on the socket API side of things. */
#ifdef HAVE_SOCKET_LEGACY
#define sockaddr_storage sockaddr_in
#define addrinfo addrinfo_rarch__
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
#ifndef AI_PASSIVE
#define AI_PASSIVE 1
#endif
/* gai_strerror() not used, so we skip that. */
#endif
int getaddrinfo_rarch(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
void freeaddrinfo_rarch(struct addrinfo *res);
bool socket_nonblock(int fd);
int socket_close(int fd);
int socket_select(int nfds, fd_set *readfs, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout);
int socket_send_all_blocking(int fd, const void *data_, size_t size);
int socket_receive_all_blocking(int fd, void *data_, size_t size);
/**
* network_init:
*
* Platform specific socket library initialization.
*
* Returns: true (1) if successful, otherwise false (0).
**/
bool network_init(void);
/**
* network_deinit:
*
* Deinitialize platform specific socket libraries.
**/
void network_deinit(void);
#endif

View File

@ -0,0 +1,65 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2015 - Daniel De Matteis
* Copyright (C) 2014-2015 - Alfred Agrell
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NET_HTTP_H
#define _NET_HTTP_H
#include <stdint.h>
#include <boolean.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
struct http_t;
struct http_connection_t;
struct http_connection_t *net_http_connection_new(const char *url);
bool net_http_connection_iterate(struct http_connection_t *conn);
bool net_http_connection_done(struct http_connection_t *conn);
void net_http_connection_free(struct http_connection_t *conn);
struct http_t *net_http_new(struct http_connection_t *conn);
/* You can use this to call net_http_update
* only when something will happen; select() it for reading. */
int net_http_fd(struct http_t *state);
/* Returns true if it's done, or if something broke.
* 'total' will be 0 if it's not known. */
bool net_http_update(struct http_t *state, size_t* progress, size_t* total);
/* 200, 404, or whatever. */
int net_http_status(struct http_t *state);
/* Returns the downloaded data. The returned buffer is owned by the
* HTTP handler; it's freed by net_http_delete.
*
* If the status is not 20x and accept_error is false, it returns NULL. */
uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error);
/* Cleans up all memory. */
void net_http_delete(struct http_t *state);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,62 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FIFO_BUFFER_H
#define __LIBRETRO_SDK_FIFO_BUFFER_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
struct fifo_buffer
{
uint8_t *buffer;
size_t bufsize;
size_t first;
size_t end;
};
typedef struct fifo_buffer fifo_buffer_t;
fifo_buffer_t *fifo_new(size_t size);
void fifo_clear(fifo_buffer_t *buffer);
void fifo_write(fifo_buffer_t *buffer, const void *in_buf, size_t size);
void fifo_read(fifo_buffer_t *buffer, void *in_buf, size_t size);
void fifo_free(fifo_buffer_t *buffer);
size_t fifo_read_avail(fifo_buffer_t *buffer);
size_t fifo_write_avail(fifo_buffer_t *buffer);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,90 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_MSG_QUEUE_H
#define __LIBRETRO_SDK_MSG_QUEUE_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct msg_queue msg_queue_t;
/**
* msg_queue_new:
* @size : maximum size of message
*
* Creates a message queue with maximum size different messages.
*
* Returns: NULL if allocation error, pointer to a message queue
* if successful. Has to be freed manually.
**/
msg_queue_t *msg_queue_new(size_t size);
/**
* msg_queue_push:
* @queue : pointer to queue object
* @msg : message to add to the queue
* @prio : priority level of the message
* @duration : how many times the message can be pulled
* before it vanishes (E.g. show a message for
* 3 seconds @ 60fps = 180 duration).
*
* Push a new message onto the queue.
**/
void msg_queue_push(msg_queue_t *queue, const char *msg,
unsigned prio, unsigned duration);
/**
* msg_queue_pull:
* @queue : pointer to queue object
*
* Pulls highest priority message in queue.
*
* Returns: NULL if no message in queue, otherwise a string
* containing the message.
**/
const char *msg_queue_pull(msg_queue_t *queue);
/**
* msg_queue_clear:
* @queue : pointer to queue object
*
* Clears out everything in the queue.
**/
void msg_queue_clear(msg_queue_t *queue);
/**
* msg_queue_free:
* @queue : pointer to queue object
*
* Frees message queue..
**/
void msg_queue_free(msg_queue_t *queue);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,40 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_assert.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RETRO_ASSERT_H
#define __RETRO_ASSERT_H
#ifdef RARCH_INTERNAL
#include <retro_log.h>
#else
#include <assert.h>
#endif
#ifdef RARCH_INTERNAL
#define rarch_assert(cond) do { \
if (!(cond)) { RARCH_ERR("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
} while(0)
#else
#define rarch_assert(cond) assert(cond)
#endif
#endif

View File

@ -0,0 +1,61 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_dirent.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RETRO_DIRENT_H
#define __RETRO_DIRENT_H
#include <boolean.h>
#ifdef __cplusplus
extern "C" {
#endif
struct RDIR;
struct RDIR *retro_opendir(const char *name);
int retro_readdir(struct RDIR *rdir);
bool retro_dirent_error(struct RDIR *rdir);
const char *retro_dirent_get_name(struct RDIR *rdir);
/**
*
* retro_dirent_is_dir:
* @rdir : pointer to the directory entry.
* @path : path to the directory entry.
*
* Is the directory listing entry a directory?
*
* Returns: true if directory listing entry is
* a directory, false if not.
*/
bool retro_dirent_is_dir(struct RDIR *rdir, const char *path);
void retro_closedir(struct RDIR *rdir);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,205 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_endianness.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_ENDIANNESS_H
#define __LIBRETRO_SDK_ENDIANNESS_H
#include <retro_inline.h>
#include <stdint.h>
#include <stdlib.h>
#if defined(_MSC_VER)
#define SWAP16 _byteswap_ushort
#define SWAP32 _byteswap_ulong
#else
#define SWAP16(x) ((uint16_t)( \
(((uint16_t)(x) & 0x00ff) << 8) | \
(((uint16_t)(x) & 0xff00) >> 8) \
))
#define SWAP32(x) ((uint32_t)( \
(((uint32_t)(x) & 0x000000ff) << 24) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0xff000000) >> 24) \
))
#endif
#define SWAP64(val) \
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
/**
* is_little_endian:
*
* Checks if the system is little endian or big-endian.
*
* Returns: greater than 0 if little-endian,
* otherwise big-endian.
**/
static INLINE uint8_t is_little_endian(void)
{
#if defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
return 1;
#elif defined(MSB_FIRST)
return 0;
#else
union
{
uint16_t x;
uint8_t y[2];
} u;
u.x = 1;
return u.y[0];
#endif
}
/**
* swap_if_big64:
* @val : unsigned 64-bit value
*
* Byteswap unsigned 64-bit value if system is big-endian.
*
* Returns: Byteswapped value in case system is big-endian,
* otherwise returns same value.
**/
static INLINE uint64_t swap_if_big64(uint64_t val)
{
if (is_little_endian())
return val;
return SWAP64(val);
}
/**
* swap_if_big32:
* @val : unsigned 32-bit value
*
* Byteswap unsigned 32-bit value if system is big-endian.
*
* Returns: Byteswapped value in case system is big-endian,
* otherwise returns same value.
**/
static INLINE uint32_t swap_if_big32(uint32_t val)
{
if (is_little_endian())
return val;
return SWAP32(val);
}
/**
* swap_if_little64:
* @val : unsigned 64-bit value
*
* Byteswap unsigned 64-bit value if system is little-endian.
*
* Returns: Byteswapped value in case system is little-endian,
* otherwise returns same value.
**/
static INLINE uint64_t swap_if_little64(uint64_t val)
{
if (is_little_endian())
return SWAP64(val);
return val;
}
/**
* swap_if_little32:
* @val : unsigned 32-bit value
*
* Byteswap unsigned 32-bit value if system is little-endian.
*
* Returns: Byteswapped value in case system is little-endian,
* otherwise returns same value.
**/
static INLINE uint32_t swap_if_little32(uint32_t val)
{
if (is_little_endian())
return SWAP32(val);
return val;
}
/**
* swap_if_big16:
* @val : unsigned 16-bit value
*
* Byteswap unsigned 16-bit value if system is big-endian.
*
* Returns: Byteswapped value in case system is big-endian,
* otherwise returns same value.
**/
static INLINE uint16_t swap_if_big16(uint16_t val)
{
if (is_little_endian())
return val;
return SWAP16(val);
}
/**
* swap_if_little16:
* @val : unsigned 16-bit value
*
* Byteswap unsigned 16-bit value if system is little-endian.
*
* Returns: Byteswapped value in case system is little-endian,
* otherwise returns same value.
**/
static INLINE uint16_t swap_if_little16(uint16_t val)
{
if (is_little_endian())
return SWAP16(val);
return val;
}
/**
* store32be:
* @addr : pointer to unsigned 32-bit buffer
* @data : unsigned 32-bit value to write
*
* Write data to address. Endian-safe. Byteswaps the data
* first if necessary before storing it.
**/
static INLINE void store32be(uint32_t *addr, uint32_t data)
{
*addr = swap_if_little32(data);
}
/**
* load32be:
* @addr : pointer to unsigned 32-bit buffer
*
* Load value from address. Endian-safe.
*
* Returns: value from address, byte-swapped if necessary.
**/
static INLINE uint32_t load32be(const uint32_t *addr)
{
return swap_if_little32(*addr);
}
#endif

View File

@ -0,0 +1,68 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_environment.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_ENVIRONMENT_H
#define __LIBRETRO_SDK_ENVIRONMENT_H
#if defined (__cplusplus)
#if 0
printf("This is C++, version %d.\n", __cplusplus);
#endif
/* The expected values would be
* 199711L, for ISO/IEC 14882:1998 or 14882:2003
*/
#elif defined(__STDC__)
/* This is standard C. */
#if (__STDC__ == 1)
/* The implementation is ISO-conforming. */
#define __STDC_ISO__
#else
/* The implementation is not ISO-conforming. */
#endif
#if defined(__STDC_VERSION__)
#if (__STDC_VERSION__ >= 201112L)
/* This is C11. */
#define __STDC_C11__
#elif (__STDC_VERSION__ >= 199901L)
/* This is C99. */
#define __STDC_C99__
#elif (__STDC_VERSION__ >= 199409L)
/* This is C89 with amendment 1. */
#define __STDC_C89__
#define __STDC_C89_AMENDMENT_1__
#else
/* This is C89 without amendment 1. */
#define __STDC_C89__
#endif
#else /* !defined(__STDC_VERSION__) */
/* This is C89. __STDC_VERSION__ is not defined. */
#define __STDC_C89__
#endif
#else /* !defined(__STDC__) */
/* This is not standard C. __STDC__ is not defined. */
#endif
#endif

View File

@ -0,0 +1,74 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_file.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RETRO_FILE_H
#define __RETRO_FILE_H
#include <stdint.h>
#include <stddef.h>
#include <sys/types.h>
#ifdef _MSC_VER
#include <compat/msvc.h>
#endif
#include <boolean.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct RFILE RFILE;
enum
{
RFILE_MODE_READ = 0,
RFILE_MODE_WRITE,
RFILE_MODE_READ_WRITE
};
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len);
ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence);
ssize_t retro_fread(RFILE *stream, void *s, size_t len);
ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len);
ssize_t retro_ftell(RFILE *stream);
void retro_frewind(RFILE *stream);
int retro_fclose(RFILE *stream);
int retro_read_file(const char *path, void **buf, ssize_t *len);
bool retro_write_file(const char *path, const void *data, ssize_t size);
int retro_get_fd(RFILE *stream);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,39 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_INLINE_H
#define __LIBRETRO_SDK_INLINE_H
#ifndef INLINE
#if !defined(__cplusplus) && defined(_WIN32)
#define INLINE _inline
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
#define INLINE inline
#elif defined(__GNUC__)
#define INLINE __inline__
#else
#define INLINE
#endif
#endif
#endif

View File

@ -0,0 +1,278 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2015 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_LOGGER_H
#define __RARCH_LOGGER_H
#ifdef _XBOX1
#include <xtl.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#ifdef __MACH__
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
#include <stdio.h>
#else
#include <asl.h>
#endif
#endif
#ifdef ANDROID
#include <android/log.h>
#endif
#include <retro_inline.h>
#include <boolean.h>
#include <compat/posix_string.h>
#include <compat/strl.h>
#if defined(HAVE_FILE_LOGGER) && defined(RARCH_INTERNAL) && !defined(IS_JOYCONFIG)
#ifdef __cplusplus
extern "C"
#endif
FILE *rarch_main_log_file(void);
#define LOG_FILE (rarch_main_log_file())
#else
#define LOG_FILE (stderr)
#endif
#if defined(IS_SALAMANDER)
#define PROGRAM_NAME "RetroArch Salamander"
#elif defined(RARCH_INTERNAL)
#define PROGRAM_NAME "RetroArch"
#elif defined(MARCH_INTERNAL)
#define PROGRAM_NAME "MicroArch"
#else
#define PROGRAM_NAME "N/A"
#endif
#if defined(RARCH_INTERNAL) && !defined(ANDROID)
#ifdef __cplusplus
extern "C" {
#endif
bool rarch_main_verbosity(void);
#ifdef __cplusplus
}
#endif
#define RARCH_LOG_VERBOSE (rarch_main_verbosity())
#else
#define RARCH_LOG_VERBOSE (true)
#endif
#if TARGET_OS_IPHONE && defined(RARCH_INTERNAL) && !TARGET_IPHONE_SIMULATOR
static aslclient asl_client;
static int asl_inited = 0;
#endif
#if defined(HAVE_LOGGER) && defined(RARCH_INTERNAL)
#define BUFSIZE (64 * 1024)
#define TCPDUMP_STACKSIZE (16 * 1024)
#define TCPDUMP_PRIO (2048)
void logger_init (void);
void logger_shutdown (void);
void logger_send (const char *__format,...);
void logger_send_v(const char *__format, va_list args);
#ifdef IS_SALAMANDER
#define RARCH_LOG(...) do { \
logger_send("RetroArch Salamander: " __VA_ARGS__); \
} while(0)
#define RARCH_LOG_V(tag, fmt, vp) do { \
logger_send("RetroArch Salamander: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#define RARCH_LOG_OUTPUT(...) do { \
logger_send("RetroArch Salamander [OUTPUT] :: " __VA_ARGS__); \
} while(0)
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
logger_send("RetroArch Salamander [OUTPUT] :: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#define RARCH_ERR(...) do { \
logger_send("RetroArch Salamander [ERROR] :: " __VA_ARGS__); \
} while(0)
#define RARCH_ERR_V(tag, fmt, vp) do { \
logger_send("RetroArch Salamander [ERROR] :: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#define RARCH_WARN(...) do { \
logger_send("RetroArch Salamander [WARN] :: " __VA_ARGS__); \
} while(0)
#define RARCH_WARN_V(tag, fmt, vp) do { \
logger_send("RetroArch Salamander [WARN] :: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#else
#define RARCH_LOG(...) do { \
logger_send("RetroArch: " __VA_ARGS__); \
} while(0)
#define RARCH_LOG_V(tag, fmt, vp) do { \
logger_send("RetroArch: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#define RARCH_ERR(...) do { \
logger_send("RetroArch [ERROR] :: " __VA_ARGS__); \
} while(0)
#define RARCH_ERR_V(tag, fmt, vp) do { \
logger_send("RetroArch [ERROR] :: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#define RARCH_WARN(...) do { \
logger_send("RetroArch [WARN] :: " __VA_ARGS__); \
} while(0)
#define RARCH_WARN_V(tag, fmt, vp) do { \
logger_send("RetroArch [WARN] :: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#define RARCH_LOG_OUTPUT(...) do { \
logger_send("RetroArch [OUTPUT] :: " __VA_ARGS__); \
} while(0)
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
logger_send("RetroArch [OUTPUT] :: " tag); \
logger_send_v(fmt, vp); \
} while (0)
#endif
#else
static INLINE void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
{
if (!RARCH_LOG_VERBOSE)
return;
#if TARGET_OS_IPHONE && defined(RARCH_INTERNAL)
#if TARGET_IPHONE_SIMULATOR
vprintf(fmt, ap);
#else
if (!asl_inited)
{
asl_client = asl_open("RetroArch", "com.apple.console", ASL_OPT_STDERR | ASL_OPT_NO_DELAY);
asl_inited = 1;
}
aslmsg msg = asl_new(ASL_TYPE_MSG);
asl_set(msg, ASL_KEY_READ_UID, "-1");
if (tag)
asl_log(asl_client, msg, ASL_LEVEL_NOTICE, "%s", tag);
asl_vlog(asl_client, msg, ASL_LEVEL_NOTICE, fmt, ap);
asl_free(msg);
#endif
#elif defined(_XBOX1)
/* FIXME: Using arbitrary string as fmt argument is unsafe. */
char msg_new[1024], buffer[1024];
snprintf(msg_new, sizeof(msg_new), "%s: %s %s",
PROGRAM_NAME,
tag ? tag : "",
fmt);
wvsprintf(buffer, msg_new, ap);
OutputDebugStringA(buffer);
#elif defined(ANDROID) && defined(HAVE_LOGGER) && defined(RARCH_INTERNAL)
int prio = ANDROID_LOG_INFO;
if (tag)
{
if (!strcmp("[WARN]", tag))
prio = ANDROID_LOG_WARN;
else if (!strcmp("[ERROR]", tag))
prio = ANDROID_LOG_ERROR;
}
__android_log_vprint(prio, PROGRAM_NAME, fmt, ap);
#else
fprintf(LOG_FILE, "%s %s :: ", PROGRAM_NAME, tag ? tag : "[INFO]");
vfprintf(LOG_FILE, fmt, ap);
#endif
}
static INLINE void RARCH_LOG(const char *fmt, ...)
{
va_list ap;
if (!RARCH_LOG_VERBOSE)
return;
va_start(ap, fmt);
RARCH_LOG_V("[INFO]", fmt, ap);
va_end(ap);
}
static INLINE void RARCH_LOG_OUTPUT_V(const char *tag,
const char *msg, va_list ap)
{
RARCH_LOG_V(tag, msg, ap);
}
static INLINE void RARCH_LOG_OUTPUT(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
RARCH_LOG_OUTPUT_V("[INFO]", msg, ap);
va_end(ap);
}
static INLINE void RARCH_WARN_V(const char *tag, const char *fmt, va_list ap)
{
RARCH_LOG_V(tag, fmt, ap);
}
static INLINE void RARCH_WARN(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
RARCH_WARN_V("[WARN]", fmt, ap);
va_end(ap);
}
static INLINE void RARCH_ERR_V(const char *tag, const char *fmt, va_list ap)
{
RARCH_LOG_V(tag, fmt, ap);
}
static INLINE void RARCH_ERR(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
RARCH_ERR_V("[ERROR]", fmt, ap);
va_end(ap);
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More