update libretro-common
This commit is contained in:
parent
3685c6e1f6
commit
b0f4989230
|
@ -216,9 +216,6 @@ static int file_archive_get_file_list_cb(
|
||||||
(void)csize;
|
(void)csize;
|
||||||
(void)size;
|
(void)size;
|
||||||
(void)checksum;
|
(void)checksum;
|
||||||
(void)valid_exts;
|
|
||||||
(void)file_ext;
|
|
||||||
(void)ext_list;
|
|
||||||
|
|
||||||
memset(&attr, 0, sizeof(attr));
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
|
||||||
|
@ -538,10 +535,8 @@ static bool file_archive_parse_file(const char *file, const char *valid_exts,
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int ret = file_archive_parse_file_iterate(&state, &returnerr, file,
|
if (file_archive_parse_file_iterate(&state, &returnerr, file,
|
||||||
valid_exts, file_cb, userdata);
|
valid_exts, file_cb, userdata) != 0)
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,7 +651,7 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
||||||
{
|
{
|
||||||
case ZLIB_MODE_UNCOMPRESSED:
|
case ZLIB_MODE_UNCOMPRESSED:
|
||||||
if (!filestream_write_file(path, cdata, size))
|
if (!filestream_write_file(path, cdata, size))
|
||||||
return false;
|
goto error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZLIB_MODE_DEFLATE:
|
case ZLIB_MODE_DEFLATE:
|
||||||
|
@ -667,7 +662,7 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
||||||
|
|
||||||
if (!handle.backend->stream_decompress_data_to_file_init(&handle,
|
if (!handle.backend->stream_decompress_data_to_file_init(&handle,
|
||||||
cdata, csize, size))
|
cdata, csize, size))
|
||||||
return false;
|
goto error;
|
||||||
|
|
||||||
do{
|
do{
|
||||||
ret = handle.backend->stream_decompress_data_to_file_iterate(
|
ret = handle.backend->stream_decompress_data_to_file_iterate(
|
||||||
|
@ -677,14 +672,17 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
||||||
if (!file_archive_decompress_data_to_file(&handle,
|
if (!file_archive_decompress_data_to_file(&handle,
|
||||||
ret, path, valid_exts,
|
ret, path, valid_exts,
|
||||||
cdata, csize, size, crc32))
|
cdata, csize, size, crc32))
|
||||||
return false;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct file_archive_file_backend *file_archive_get_default_file_backend(void)
|
const struct file_archive_file_backend *file_archive_get_default_file_backend(void)
|
||||||
|
|
|
@ -167,7 +167,7 @@ static int zlib_stream_decompress_data_to_file_iterate(void *data)
|
||||||
z_stream *stream = (z_stream*)data;
|
z_stream *stream = (z_stream*)data;
|
||||||
|
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
zstatus = inflate(stream, Z_NO_FLUSH);
|
zstatus = inflate(stream, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
@ -175,9 +175,12 @@ static int zlib_stream_decompress_data_to_file_iterate(void *data)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
|
if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zlib_stream_compress_init(void *data, int level)
|
static void zlib_stream_compress_init(void *data, int level)
|
||||||
|
|
|
@ -421,6 +421,15 @@ void rglLinkProgram(GLuint program)
|
||||||
glLinkProgram(program);
|
glLinkProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rglFramebufferTexture(GLenum target, GLenum attachment,
|
||||||
|
GLuint texture, GLint level)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES32)
|
||||||
|
#else
|
||||||
|
glFramebufferTexture(target, attachment, texture, level);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||||
GLenum textarget, GLuint texture, GLint level)
|
GLenum textarget, GLuint texture, GLint level)
|
||||||
{
|
{
|
||||||
|
@ -446,7 +455,7 @@ void rglFramebufferRenderbuffer(GLenum target, GLenum attachment,
|
||||||
glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
|
glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers)
|
void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
|
||||||
{
|
{
|
||||||
glDeleteFramebuffers(n, framebuffers);
|
glDeleteFramebuffers(n, framebuffers);
|
||||||
}
|
}
|
||||||
|
@ -703,6 +712,12 @@ void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value)
|
||||||
glUniform4fv(location, count, value);
|
glUniform4fv(location, count, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat,
|
||||||
|
GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
glTexStorage2D(target, levels, internalFormat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void rglPolygonOffset(GLfloat factor, GLfloat units)
|
void rglPolygonOffset(GLfloat factor, GLfloat units)
|
||||||
{
|
{
|
||||||
glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL);
|
glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL);
|
||||||
|
@ -712,6 +727,41 @@ void rglPolygonOffset(GLfloat factor, GLfloat units)
|
||||||
gl_state.polygonoffset.units = units;
|
gl_state.polygonoffset.units = units;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rglDrawBuffers(GLsizei n, const GLenum *bufs)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31)
|
||||||
|
#else
|
||||||
|
glDrawBuffers(n, bufs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void rglBlendEquation(GLenum mode)
|
||||||
|
{
|
||||||
|
glBlendEquation(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
|
||||||
|
{
|
||||||
|
glBlendColor(red, green, blue, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rglBindVertexArray(GLuint array)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31)
|
||||||
|
#else
|
||||||
|
glBindVertexArray(array);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void rglGenVertexArrays(GLsizei n, GLuint *arrays)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31)
|
||||||
|
#else
|
||||||
|
glGenVertexArrays(n, arrays);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* GLSM-side */
|
/* GLSM-side */
|
||||||
|
|
||||||
static void glsm_state_setup(void)
|
static void glsm_state_setup(void)
|
||||||
|
|
|
@ -41,6 +41,7 @@ extern "C" {
|
||||||
#define glCompressedTexImage2D rglCompressedTexImage2D
|
#define glCompressedTexImage2D rglCompressedTexImage2D
|
||||||
#define glBindTexture rglBindTexture
|
#define glBindTexture rglBindTexture
|
||||||
#define glActiveTexture rglActiveTexture
|
#define glActiveTexture rglActiveTexture
|
||||||
|
#define glFramebufferTexture rglFramebufferTexture
|
||||||
#define glFramebufferTexture2D rglFramebufferTexture2D
|
#define glFramebufferTexture2D rglFramebufferTexture2D
|
||||||
#define glFramebufferRenderbuffer rglFramebufferRenderbuffer
|
#define glFramebufferRenderbuffer rglFramebufferRenderbuffer
|
||||||
#define glDeleteFramebuffers rglDeleteFramebuffers
|
#define glDeleteFramebuffers rglDeleteFramebuffers
|
||||||
|
@ -112,22 +113,35 @@ extern "C" {
|
||||||
#define glReadBuffer rglReadBuffer
|
#define glReadBuffer rglReadBuffer
|
||||||
#define glUniformMatrix4fv rglUniformMatrix4fv
|
#define glUniformMatrix4fv rglUniformMatrix4fv
|
||||||
#define glGetAttribLocation rglGetAttribLocation
|
#define glGetAttribLocation rglGetAttribLocation
|
||||||
|
#define glTexStorage2D rglTexStorage2D
|
||||||
|
#define glDrawBuffers rglDrawBuffers
|
||||||
|
#define glGenVertexArrays rglGenVertexArrays
|
||||||
|
#define glBindVertexArray rglBindVertexArray
|
||||||
|
#define glBlendEquation rglBlendEquation
|
||||||
|
#define glBlendColor rglBlendColor
|
||||||
|
|
||||||
|
void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||||
|
void rglBlendEquation(GLenum mode);
|
||||||
|
void rglGenVertexArrays(GLsizei n, GLuint *arrays);
|
||||||
void rglReadBuffer(GLenum mode);
|
void rglReadBuffer(GLenum mode);
|
||||||
void rglPixelStorei(GLenum pname, GLint param);
|
void rglPixelStorei(GLenum pname, GLint param);
|
||||||
void rglTexCoord2f(GLfloat s, GLfloat t);
|
void rglTexCoord2f(GLfloat s, GLfloat t);
|
||||||
void rglDrawElements(GLenum mode, GLsizei count, GLenum type,
|
void rglDrawElements(GLenum mode, GLsizei count, GLenum type,
|
||||||
const GLvoid * indices);
|
const GLvoid * indices);
|
||||||
|
void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat,
|
||||||
|
GLsizei width, GLsizei height);
|
||||||
void rglCompressedTexImage2D(GLenum target, GLint level,
|
void rglCompressedTexImage2D(GLenum target, GLint level,
|
||||||
GLenum internalformat, GLsizei width, GLsizei height,
|
GLenum internalformat, GLsizei width, GLsizei height,
|
||||||
GLint border, GLsizei imageSize, const GLvoid *data);
|
GLint border, GLsizei imageSize, const GLvoid *data);
|
||||||
void glBindTexture(GLenum target, GLuint texture);
|
void glBindTexture(GLenum target, GLuint texture);
|
||||||
void glActiveTexture(GLenum texture);
|
void glActiveTexture(GLenum texture);
|
||||||
|
void rglFramebufferTexture(GLenum target, GLenum attachment,
|
||||||
|
GLuint texture, GLint level);
|
||||||
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||||
GLenum textarget, GLuint texture, GLint level);
|
GLenum textarget, GLuint texture, GLint level);
|
||||||
void rglFramebufferRenderbuffer(GLenum target, GLenum attachment,
|
void rglFramebufferRenderbuffer(GLenum target, GLenum attachment,
|
||||||
GLenum renderbuffertarget, GLuint renderbuffer);
|
GLenum renderbuffertarget, GLuint renderbuffer);
|
||||||
void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers);
|
void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
|
||||||
void rglRenderbufferStorage(GLenum target, GLenum internalFormat,
|
void rglRenderbufferStorage(GLenum target, GLenum internalFormat,
|
||||||
GLsizei width, GLsizei height);
|
GLsizei width, GLsizei height);
|
||||||
void rglDeleteTextures(GLsizei n, const GLuint *textures);
|
void rglDeleteTextures(GLsizei n, const GLuint *textures);
|
||||||
|
@ -214,6 +228,8 @@ void rglDetachShader(GLuint program, GLuint shader);
|
||||||
void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
|
void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
|
||||||
const GLfloat *value);
|
const GLfloat *value);
|
||||||
GLint rglGetAttribLocation(GLuint program, const GLchar *name);
|
GLint rglGetAttribLocation(GLuint program, const GLchar *name);
|
||||||
|
void rglDrawBuffers(GLsizei n, const GLenum *bufs);
|
||||||
|
void rglBindVertexArray(GLuint array);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,11 @@ bool file_list_append(file_list_t *userdata, const char *path,
|
||||||
const char *label, unsigned type, size_t current_directory_ptr,
|
const char *label, unsigned type, size_t current_directory_ptr,
|
||||||
size_t entry_index);
|
size_t entry_index);
|
||||||
|
|
||||||
|
bool file_list_prepend(file_list_t *list,
|
||||||
|
const char *path, const char *label,
|
||||||
|
unsigned type, size_t directory_ptr,
|
||||||
|
size_t entry_idx);
|
||||||
|
|
||||||
void file_list_pop(file_list_t *list, size_t *directory_ptr);
|
void file_list_pop(file_list_t *list, size_t *directory_ptr);
|
||||||
|
|
||||||
void file_list_clear(file_list_t *list);
|
void file_list_clear(file_list_t *list);
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
#ifndef __LIBRETRO_SDK_SEMAPHORE_H
|
#ifndef __LIBRETRO_SDK_SEMAPHORE_H
|
||||||
#define __LIBRETRO_SDK_SEMAPHORE_H
|
#define __LIBRETRO_SDK_SEMAPHORE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct ssem ssem_t;
|
typedef struct ssem ssem_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,8 +41,14 @@ ssem_t *ssem_new(int value);
|
||||||
|
|
||||||
void ssem_free(ssem_t *semaphore);
|
void ssem_free(ssem_t *semaphore);
|
||||||
|
|
||||||
|
int ssem_get(ssem_t *semaphore);
|
||||||
|
|
||||||
void ssem_wait(ssem_t *semaphore);
|
void ssem_wait(ssem_t *semaphore);
|
||||||
|
|
||||||
void ssem_signal(ssem_t *semaphore);
|
void ssem_signal(ssem_t *semaphore);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __LIBRETRO_SDK_SEMAPHORE_H */
|
#endif /* __LIBRETRO_SDK_SEMAPHORE_H */
|
||||||
|
|
|
@ -66,6 +66,8 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len);
|
||||||
|
|
||||||
bool filestream_write_file(const char *path, const void *data, ssize_t size);
|
bool filestream_write_file(const char *path, const void *data, ssize_t size);
|
||||||
|
|
||||||
|
int filestream_putc(RFILE *stream, int c);
|
||||||
|
|
||||||
int filestream_get_fd(RFILE *stream);
|
int filestream_get_fd(RFILE *stream);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* Copyright (C) 2010-2015 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (interface_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_INTERFACE_STREAM_H
|
||||||
|
#define _LIBRETRO_SDK_INTERFACE_STREAM_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
enum intfstream_type
|
||||||
|
{
|
||||||
|
INTFSTREAM_FILE = 0,
|
||||||
|
INTFSTREAM_MEMORY
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct intfstream_internal intfstream_internal_t;
|
||||||
|
|
||||||
|
typedef struct intfstream intfstream_t;
|
||||||
|
|
||||||
|
typedef struct intfstream_info
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
} buf;
|
||||||
|
bool writable;
|
||||||
|
} memory;
|
||||||
|
enum intfstream_type type;
|
||||||
|
} intfstream_info_t;
|
||||||
|
|
||||||
|
void *intfstream_init(intfstream_info_t *info);
|
||||||
|
|
||||||
|
bool intfstream_resize(intfstream_internal_t *intf,
|
||||||
|
intfstream_info_t *info);
|
||||||
|
|
||||||
|
bool intfstream_open(intfstream_internal_t *intf,
|
||||||
|
const char *path, unsigned mode, ssize_t len);
|
||||||
|
|
||||||
|
ssize_t intfstream_read(intfstream_internal_t *intf,
|
||||||
|
void *s, size_t len);
|
||||||
|
|
||||||
|
ssize_t intfstream_write(intfstream_internal_t *intf,
|
||||||
|
const void *s, size_t len);
|
||||||
|
|
||||||
|
char *intfstream_gets(intfstream_internal_t *intf,
|
||||||
|
char *buffer, size_t len);
|
||||||
|
|
||||||
|
int intfstream_getc(intfstream_internal_t *intf);
|
||||||
|
|
||||||
|
int intfstream_seek(intfstream_internal_t *intf,
|
||||||
|
int offset, int whence);
|
||||||
|
|
||||||
|
void intfstream_rewind(intfstream_internal_t *intf);
|
||||||
|
|
||||||
|
int intfstream_tell(intfstream_internal_t *intf);
|
||||||
|
|
||||||
|
void intfstream_putc(intfstream_internal_t *intf, int c);
|
||||||
|
|
||||||
|
int intfstream_close(intfstream_internal_t *intf);
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
typedef struct memstream memstream_t;
|
typedef struct memstream memstream_t;
|
||||||
|
|
||||||
memstream_t *memstream_open(void);
|
memstream_t *memstream_open(unsigned writing);
|
||||||
|
|
||||||
void memstream_close(memstream_t *stream);
|
void memstream_close(memstream_t *stream);
|
||||||
|
|
||||||
|
@ -38,10 +38,14 @@ size_t memstream_write(memstream_t *stream, const void *data, size_t bytes);
|
||||||
|
|
||||||
int memstream_getc(memstream_t *stream);
|
int memstream_getc(memstream_t *stream);
|
||||||
|
|
||||||
|
void memstream_putc(memstream_t *stream, int c);
|
||||||
|
|
||||||
char *memstream_gets(memstream_t *stream, char *buffer, size_t len);
|
char *memstream_gets(memstream_t *stream, char *buffer, size_t len);
|
||||||
|
|
||||||
size_t memstream_pos(memstream_t *stream);
|
size_t memstream_pos(memstream_t *stream);
|
||||||
|
|
||||||
|
void memstream_rewind(memstream_t *stream);
|
||||||
|
|
||||||
int memstream_seek(memstream_t *stream, int offset, int whence);
|
int memstream_seek(memstream_t *stream, int offset, int whence);
|
||||||
|
|
||||||
void memstream_set_buffer(uint8_t *buffer, size_t size);
|
void memstream_set_buffer(uint8_t *buffer, size_t size);
|
||||||
|
|
|
@ -24,7 +24,7 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//ABI: Win64
|
/* ABI: Win64 */
|
||||||
static unsigned char co_swap_function[] = {
|
static unsigned char co_swap_function[] = {
|
||||||
0x48, 0x89, 0x22, /* mov [rdx],rsp */
|
0x48, 0x89, 0x22, /* mov [rdx],rsp */
|
||||||
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
|
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
|
||||||
|
@ -81,7 +81,7 @@ void co_init(void)
|
||||||
sizeof(co_swap_function), PAGE_EXECUTE_READWRITE, &old_privileges);
|
sizeof(co_swap_function), PAGE_EXECUTE_READWRITE, &old_privileges);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//ABI: SystemV
|
/* ABI: SystemV */
|
||||||
#ifndef CO_USE_INLINE_ASM
|
#ifndef CO_USE_INLINE_ASM
|
||||||
static unsigned char co_swap_function[] = {
|
static unsigned char co_swap_function[] = {
|
||||||
0x48, 0x89, 0x26, /* mov [rsi],rsp */
|
0x48, 0x89, 0x26, /* mov [rsi],rsp */
|
||||||
|
|
|
@ -59,6 +59,49 @@ static bool file_list_capacity(file_list_t *list, size_t cap)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool file_list_prepend(file_list_t *list,
|
||||||
|
const char *path, const char *label,
|
||||||
|
unsigned type, size_t directory_ptr,
|
||||||
|
size_t entry_idx)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
if (list->size >= list->capacity &&
|
||||||
|
!file_list_capacity(list, list->capacity * 2 + 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list->size++;
|
||||||
|
|
||||||
|
for (i = list->size -1; i > 0; i--)
|
||||||
|
{
|
||||||
|
struct item_file *copy = calloc(1, sizeof(struct item_file));
|
||||||
|
|
||||||
|
memcpy(copy, &list->list[i-1], sizeof(struct item_file));
|
||||||
|
|
||||||
|
memcpy(&list->list[i-1], &list->list[i], sizeof(struct item_file));
|
||||||
|
memcpy(&list->list[i], copy, sizeof(struct item_file));
|
||||||
|
|
||||||
|
free(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&list->list[0], 0, sizeof(file_list_t));
|
||||||
|
|
||||||
|
list->list[0].label = NULL;
|
||||||
|
list->list[0].path = NULL;
|
||||||
|
list->list[0].alt = NULL;
|
||||||
|
list->list[0].userdata = NULL;
|
||||||
|
list->list[0].actiondata = NULL;
|
||||||
|
list->list[0].type = type;
|
||||||
|
list->list[0].directory_ptr = directory_ptr;
|
||||||
|
list->list[0].entry_idx = entry_idx;
|
||||||
|
|
||||||
|
if (label)
|
||||||
|
list->list[0].label = strdup(label);
|
||||||
|
if (path)
|
||||||
|
list->list[0].path = strdup(path);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool file_list_append(file_list_t *list,
|
bool file_list_append(file_list_t *list,
|
||||||
const char *path, const char *label,
|
const char *path, const char *label,
|
||||||
unsigned type, size_t directory_ptr,
|
unsigned type, size_t directory_ptr,
|
||||||
|
|
|
@ -175,12 +175,9 @@ void msg_queue_clear(msg_queue_t *queue)
|
||||||
**/
|
**/
|
||||||
const char *msg_queue_pull(msg_queue_t *queue)
|
const char *msg_queue_pull(msg_queue_t *queue)
|
||||||
{
|
{
|
||||||
struct queue_elem *front = NULL, *last = NULL,
|
struct queue_elem *front = NULL, *last = NULL;
|
||||||
*parent = NULL, *child = NULL;
|
|
||||||
size_t tmp_ptr = 1;
|
size_t tmp_ptr = 1;
|
||||||
|
|
||||||
(void)parent;
|
|
||||||
(void)child;
|
|
||||||
(void)tmp_ptr;
|
(void)tmp_ptr;
|
||||||
|
|
||||||
/* Nothing in queue. */
|
/* Nothing in queue. */
|
||||||
|
@ -203,10 +200,12 @@ const char *msg_queue_pull(msg_queue_t *queue)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
size_t switch_index = tmp_ptr;
|
struct queue_elem *parent = NULL;
|
||||||
bool left = (tmp_ptr * 2 <= queue->ptr)
|
struct queue_elem *child = NULL;
|
||||||
|
size_t switch_index = tmp_ptr;
|
||||||
|
bool left = (tmp_ptr * 2 <= queue->ptr)
|
||||||
&& (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]);
|
&& (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2]);
|
||||||
bool right = (tmp_ptr * 2 + 1 <= queue->ptr)
|
bool right = (tmp_ptr * 2 + 1 <= queue->ptr)
|
||||||
&& (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]);
|
&& (queue->elems[tmp_ptr] < queue->elems[tmp_ptr * 2 + 1]);
|
||||||
|
|
||||||
if (!left && !right)
|
if (!left && !right)
|
||||||
|
@ -227,9 +226,9 @@ const char *msg_queue_pull(msg_queue_t *queue)
|
||||||
|
|
||||||
parent = (struct queue_elem*)queue->elems[tmp_ptr];
|
parent = (struct queue_elem*)queue->elems[tmp_ptr];
|
||||||
child = (struct queue_elem*)queue->elems[switch_index];
|
child = (struct queue_elem*)queue->elems[switch_index];
|
||||||
queue->elems[tmp_ptr] = child;
|
queue->elems[tmp_ptr] = child;
|
||||||
queue->elems[switch_index] = parent;
|
queue->elems[switch_index] = parent;
|
||||||
tmp_ptr = switch_index;
|
tmp_ptr = switch_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return queue->tmp_msg;
|
return queue->tmp_msg;
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __unix__
|
||||||
|
#define _POSIX_C_SOURCE 199309
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <rthreads/rthreads.h>
|
#include <rthreads/rthreads.h>
|
||||||
|
@ -73,6 +77,21 @@ void ssem_free(ssem_t *semaphore)
|
||||||
free((void*)semaphore);
|
free((void*)semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ssem_get(ssem_t *semaphore)
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
if (!semaphore)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
slock_lock(semaphore->mutex);
|
||||||
|
|
||||||
|
val = semaphore->value;
|
||||||
|
|
||||||
|
slock_unlock(semaphore->mutex);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
void ssem_wait(ssem_t *semaphore)
|
void ssem_wait(ssem_t *semaphore)
|
||||||
{
|
{
|
||||||
if (!semaphore)
|
if (!semaphore)
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __unix__
|
||||||
|
#define _POSIX_C_SOURCE 199309
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <boolean.h>
|
#include <boolean.h>
|
||||||
|
|
|
@ -66,10 +66,6 @@
|
||||||
#include <streams/file_stream.h>
|
#include <streams/file_stream.h>
|
||||||
#include <memmap.h>
|
#include <memmap.h>
|
||||||
|
|
||||||
#if 1
|
|
||||||
#define HAVE_BUFFERED_IO 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct RFILE
|
struct RFILE
|
||||||
{
|
{
|
||||||
unsigned hints;
|
unsigned hints;
|
||||||
|
@ -78,6 +74,9 @@ struct RFILE
|
||||||
#elif defined(__CELLOS_LV2__)
|
#elif defined(__CELLOS_LV2__)
|
||||||
int fd;
|
int fd;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#define HAVE_BUFFERED_IO 1
|
||||||
|
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,28 +93,25 @@ int filestream_get_fd(RFILE *stream)
|
||||||
{
|
{
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
return -1;
|
||||||
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
|
|
||||||
return stream->fd;
|
|
||||||
#else
|
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
return fileno(stream->fp);
|
return fileno(stream->fp);
|
||||||
#endif
|
#endif
|
||||||
return stream->fd;
|
return stream->fd;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int mode_int = 0;
|
int mode_int = 0;
|
||||||
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
const char *mode_str = NULL;
|
const char *mode_str = NULL;
|
||||||
|
#endif
|
||||||
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
|
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
|
||||||
|
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
(void)mode_str;
|
|
||||||
(void)mode_int;
|
(void)mode_int;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
|
|
||||||
|
@ -220,7 +216,8 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
||||||
|
|
||||||
filestream_rewind(stream);
|
filestream_rewind(stream);
|
||||||
|
|
||||||
stream->mapped = (uint8_t*)mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
|
stream->mapped = (uint8_t*)mmap((void*)0,
|
||||||
|
stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
|
||||||
|
|
||||||
if (stream->mapped == MAP_FAILED)
|
if (stream->mapped == MAP_FAILED)
|
||||||
stream->hints &= ~RFILE_HINT_MMAP;
|
stream->hints &= ~RFILE_HINT_MMAP;
|
||||||
|
@ -243,98 +240,103 @@ error:
|
||||||
|
|
||||||
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence)
|
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
#if defined(__CELLOS_LV2__)
|
||||||
|
uint64_t pos = 0;
|
||||||
|
#endif
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
(void)ret;
|
|
||||||
|
|
||||||
#if defined(VITA) || defined(PSP)
|
#if defined(VITA) || defined(PSP)
|
||||||
ret = sceIoLseek(stream->fd, (SceOff)offset, whence);
|
if (sceIoLseek(stream->fd, (SceOff)offset, whence) == -1)
|
||||||
if (ret == -1)
|
goto error;
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
#elif defined(__CELLOS_LV2__)
|
||||||
uint64_t pos = 0;
|
|
||||||
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
|
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
|
||||||
return -1;
|
goto error;
|
||||||
return 0;
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
return fseek(stream->fp, (long)offset, whence);
|
return fseek(stream->fp, (long)offset, whence);
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
/* Need to check stream->mapped because this function is
|
/* Need to check stream->mapped because this function is
|
||||||
* called in filestream_open() */
|
* called in filestream_open() */
|
||||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||||
|
{
|
||||||
|
/* fseek() returns error on under/overflow but allows cursor > EOF for
|
||||||
|
read-only file descriptors. */
|
||||||
|
switch (whence)
|
||||||
{
|
{
|
||||||
/* fseek() returns error on under/overflow but allows cursor > EOF for
|
case SEEK_SET:
|
||||||
read-only file descriptors. */
|
if (offset < 0)
|
||||||
switch (whence)
|
goto error;
|
||||||
{
|
|
||||||
case SEEK_SET:
|
|
||||||
if (offset < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
stream->mappos = offset;
|
stream->mappos = offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
||||||
(offset > 0 && stream->mappos + offset < stream->mappos))
|
(offset > 0 && stream->mappos + offset < stream->mappos))
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
stream->mappos += offset;
|
stream->mappos += offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
if (stream->mapsize + offset < stream->mapsize)
|
if (stream->mapsize + offset < stream->mapsize)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
stream->mappos = stream->mapsize + offset;
|
stream->mappos = stream->mapsize + offset;
|
||||||
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream->mappos;
|
|
||||||
}
|
}
|
||||||
else
|
return stream->mappos;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
ret = lseek(stream->fd, offset, whence);
|
if (lseek(stream->fd, offset, whence) < 0)
|
||||||
return ret < 0 ? -1 : ret;
|
goto error;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t filestream_tell(RFILE *stream)
|
ssize_t filestream_tell(RFILE *stream)
|
||||||
{
|
{
|
||||||
if (!stream)
|
#if defined(__CELLOS_LV2__)
|
||||||
return -1;
|
|
||||||
#if defined(VITA) || defined(PSP)
|
|
||||||
return sceIoLseek(stream->fd, 0, SEEK_CUR);
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
|
||||||
uint64_t pos = 0;
|
uint64_t pos = 0;
|
||||||
|
#endif
|
||||||
|
if (!stream)
|
||||||
|
goto error;
|
||||||
|
#if defined(VITA) || defined(PSP)
|
||||||
|
if (sceIoLseek(stream->fd, 0, SEEK_CUR) < 0)
|
||||||
|
goto error;
|
||||||
|
#elif defined(__CELLOS_LV2__)
|
||||||
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
|
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
|
||||||
return -1;
|
goto error;
|
||||||
return 0;
|
|
||||||
#else
|
#else
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
return ftell(stream->fp);
|
return ftell(stream->fp);
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
/* Need to check stream->mapped because this function
|
/* Need to check stream->mapped because this function
|
||||||
* is called in filestream_open() */
|
* is called in filestream_open() */
|
||||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||||
return stream->mappos;
|
return stream->mappos;
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
return lseek(stream->fd, 0, SEEK_CUR);
|
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
|
||||||
|
goto error;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filestream_rewind(RFILE *stream)
|
void filestream_rewind(RFILE *stream)
|
||||||
|
@ -345,70 +347,85 @@ void filestream_rewind(RFILE *stream)
|
||||||
ssize_t filestream_read(RFILE *stream, void *s, size_t len)
|
ssize_t filestream_read(RFILE *stream, void *s, size_t len)
|
||||||
{
|
{
|
||||||
if (!stream || !s)
|
if (!stream || !s)
|
||||||
return -1;
|
goto error;
|
||||||
#if defined(VITA) || defined(PSP)
|
#if defined(VITA) || defined(PSP)
|
||||||
return sceIoRead(stream->fd, s, len);
|
return sceIoRead(stream->fd, s, len);
|
||||||
#elif defined(__CELLOS_LV2__)
|
#elif defined(__CELLOS_LV2__)
|
||||||
uint64_t bytes_written;
|
uint64_t bytes_written;
|
||||||
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
||||||
return -1;
|
goto error;
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
#else
|
#else
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
return fread(s, 1, len, stream->fp);
|
return fread(s, 1, len, stream->fp);
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
if (stream->hints & RFILE_HINT_MMAP)
|
if (stream->hints & RFILE_HINT_MMAP)
|
||||||
{
|
{
|
||||||
if (stream->mappos > stream->mapsize)
|
if (stream->mappos > stream->mapsize)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
if (stream->mappos + len > stream->mapsize)
|
if (stream->mappos + len > stream->mapsize)
|
||||||
len = stream->mapsize - stream->mappos;
|
len = stream->mapsize - stream->mappos;
|
||||||
|
|
||||||
memcpy(s, &stream->mapped[stream->mappos], len);
|
memcpy(s, &stream->mapped[stream->mappos], len);
|
||||||
stream->mappos += len;
|
stream->mappos += len;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
return read(stream->fd, s, len);
|
return read(stream->fd, s, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t filestream_write(RFILE *stream, const void *s, size_t len)
|
ssize_t filestream_write(RFILE *stream, const void *s, size_t len)
|
||||||
{
|
{
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
goto error;
|
||||||
#if defined(VITA) || defined(PSP)
|
#if defined(VITA) || defined(PSP)
|
||||||
return sceIoWrite(stream->fd, s, len);
|
return sceIoWrite(stream->fd, s, len);
|
||||||
#elif defined(__CELLOS_LV2__)
|
#elif defined(__CELLOS_LV2__)
|
||||||
uint64_t bytes_written;
|
uint64_t bytes_written;
|
||||||
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
||||||
return -1;
|
goto error;
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
#else
|
#else
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
return fwrite(s, 1, len, stream->fp);
|
return fwrite(s, 1, len, stream->fp);
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
if (stream->hints & RFILE_HINT_MMAP)
|
if (stream->hints & RFILE_HINT_MMAP)
|
||||||
return -1;
|
goto error;
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
return write(stream->fd, s, len);
|
return write(stream->fd, s, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int filestream_putc(RFILE *stream, int c)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
return EOF;
|
||||||
|
|
||||||
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
|
return fputc(c, stream->fp);
|
||||||
|
#else
|
||||||
|
/* unimplemented */
|
||||||
|
return EOF;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int filestream_close(RFILE *stream)
|
int filestream_close(RFILE *stream)
|
||||||
{
|
{
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
goto error;
|
||||||
|
|
||||||
#if defined(VITA) || defined(PSP)
|
#if defined(VITA) || defined(PSP)
|
||||||
if (stream->fd > 0)
|
if (stream->fd > 0)
|
||||||
|
@ -430,12 +447,15 @@ int filestream_close(RFILE *stream)
|
||||||
munmap(stream->mapped, stream->mapsize);
|
munmap(stream->mapped, stream->mapsize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (stream->fd > 0)
|
if (stream->fd > 0)
|
||||||
close(stream->fd);
|
close(stream->fd);
|
||||||
#endif
|
#endif
|
||||||
free(stream);
|
free(stream);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -534,5 +554,8 @@ bool filestream_write_file(const char *path, const void *data, ssize_t size)
|
||||||
ret = filestream_write(file, data, size);
|
ret = filestream_write(file, data, size);
|
||||||
filestream_close(file);
|
filestream_close(file);
|
||||||
|
|
||||||
return (ret == size);
|
if (ret != size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
/* Copyright (C) 2010-2016 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (interface_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 <stdlib.h>
|
||||||
|
|
||||||
|
#include <streams/interface_stream.h>
|
||||||
|
#include <streams/file_stream.h>
|
||||||
|
#include <streams/memory_stream.h>
|
||||||
|
|
||||||
|
struct intfstream_internal
|
||||||
|
{
|
||||||
|
enum intfstream_type type;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
RFILE *fp;
|
||||||
|
} file;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
} buf;
|
||||||
|
memstream_t *fp;
|
||||||
|
bool writable;
|
||||||
|
} memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool intfstream_resize(intfstream_internal_t *intf, intfstream_info_t *info)
|
||||||
|
{
|
||||||
|
if (!intf || !info)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
intf->memory.buf.data = info->memory.buf.data;
|
||||||
|
intf->memory.buf.size = info->memory.buf.size;
|
||||||
|
|
||||||
|
memstream_set_buffer(intf->memory.buf.data,
|
||||||
|
intf->memory.buf.size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intfstream_open(intfstream_internal_t *intf, const char *path,
|
||||||
|
unsigned mode, ssize_t len)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
intf->file.fp = filestream_open(path, mode, len);
|
||||||
|
if (!intf->file.fp)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
intf->memory.fp = memstream_open(intf->memory.writable);
|
||||||
|
if (!intf->memory.fp)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intfstream_close(intfstream_internal_t *intf)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
return filestream_close(intf->file.fp);
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
memstream_close(intf->memory.fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *intfstream_init(intfstream_info_t *info)
|
||||||
|
{
|
||||||
|
intfstream_internal_t *intf = NULL;
|
||||||
|
if (!info)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
intf = (intfstream_internal_t*)calloc(1, sizeof(*intf));
|
||||||
|
|
||||||
|
if (!intf)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
intf->type = info->type;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
intf->memory.writable = info->memory.writable;
|
||||||
|
if (!intfstream_resize(intf, info))
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return intf;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (intf)
|
||||||
|
free(intf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intfstream_seek(intfstream_internal_t *intf, int offset, int whence)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
return filestream_seek(intf->file.fp, offset, whence);
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
return memstream_seek(intf->memory.fp, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t intfstream_read(intfstream_internal_t *intf, void *s, size_t len)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
return filestream_read(intf->file.fp, s, len);
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
return memstream_read(intf->memory.fp, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t intfstream_write(intfstream_internal_t *intf,
|
||||||
|
const void *s, size_t len)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
return filestream_write(intf->file.fp, s, len);
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
return memstream_write(intf->memory.fp, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *intfstream_gets(intfstream_internal_t *intf,
|
||||||
|
char *buffer, size_t len)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
/* unimplemented */
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
return memstream_gets(intf->memory.fp, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intfstream_getc(intfstream_internal_t *intf)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
/* unimplemented */
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
return memstream_getc(intf->memory.fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intfstream_tell(intfstream_internal_t *intf)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
return filestream_tell(intf->file.fp);
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
return memstream_pos(intf->memory.fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void intfstream_rewind(intfstream_internal_t *intf)
|
||||||
|
{
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
filestream_rewind(intf->file.fp);
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
memstream_rewind(intf->memory.fp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void intfstream_putc(intfstream_internal_t *intf, int c)
|
||||||
|
{
|
||||||
|
if (!intf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (intf->type)
|
||||||
|
{
|
||||||
|
case INTFSTREAM_FILE:
|
||||||
|
filestream_putc(intf->file.fp, c);
|
||||||
|
break;
|
||||||
|
case INTFSTREAM_MEMORY:
|
||||||
|
memstream_putc(intf->memory.fp, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,11 +32,19 @@ static size_t last_file_size = 0;
|
||||||
|
|
||||||
struct memstream
|
struct memstream
|
||||||
{
|
{
|
||||||
uint8_t *m_buf;
|
uint8_t *buf;
|
||||||
size_t m_size;
|
size_t size;
|
||||||
size_t m_ptr;
|
size_t ptr;
|
||||||
|
size_t max_ptr;
|
||||||
|
unsigned writing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void memstream_update_pos(memstream_t *stream)
|
||||||
|
{
|
||||||
|
if (stream->ptr > stream->max_ptr)
|
||||||
|
stream->max_ptr = stream->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
void memstream_set_buffer(uint8_t *buffer, size_t size)
|
void memstream_set_buffer(uint8_t *buffer, size_t size)
|
||||||
{
|
{
|
||||||
g_buffer = buffer;
|
g_buffer = buffer;
|
||||||
|
@ -48,21 +56,27 @@ size_t memstream_get_last_size(void)
|
||||||
return last_file_size;
|
return last_file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void memstream_init(memstream_t *stream, uint8_t *buffer, size_t max_size)
|
static void memstream_init(memstream_t *stream,
|
||||||
|
uint8_t *buffer, size_t max_size, unsigned writing)
|
||||||
{
|
{
|
||||||
stream->m_buf = buffer;
|
if (!stream)
|
||||||
stream->m_size = max_size;
|
return;
|
||||||
stream->m_ptr = 0;
|
|
||||||
|
stream->buf = buffer;
|
||||||
|
stream->size = max_size;
|
||||||
|
stream->ptr = 0;
|
||||||
|
stream->max_ptr = 0;
|
||||||
|
stream->writing = writing;
|
||||||
}
|
}
|
||||||
|
|
||||||
memstream_t *memstream_open(void)
|
memstream_t *memstream_open(unsigned writing)
|
||||||
{
|
{
|
||||||
memstream_t *stream;
|
memstream_t *stream;
|
||||||
if (!g_buffer || !g_size)
|
if (!g_buffer || !g_size)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
stream = (memstream_t*)calloc(1, sizeof(*stream));
|
stream = (memstream_t*)calloc(1, sizeof(*stream));
|
||||||
memstream_init(stream, g_buffer, g_size);
|
memstream_init(stream, g_buffer, g_size, writing);
|
||||||
|
|
||||||
g_buffer = NULL;
|
g_buffer = NULL;
|
||||||
g_size = 0;
|
g_size = 0;
|
||||||
|
@ -71,29 +85,44 @@ memstream_t *memstream_open(void)
|
||||||
|
|
||||||
void memstream_close(memstream_t *stream)
|
void memstream_close(memstream_t *stream)
|
||||||
{
|
{
|
||||||
last_file_size = stream->m_ptr;
|
if (!stream)
|
||||||
|
return;
|
||||||
|
|
||||||
|
last_file_size = stream->writing ? stream->max_ptr : stream->size;
|
||||||
free(stream);
|
free(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memstream_read(memstream_t *stream, void *data, size_t bytes)
|
size_t memstream_read(memstream_t *stream, void *data, size_t bytes)
|
||||||
{
|
{
|
||||||
size_t avail = stream->m_size - stream->m_ptr;
|
size_t avail = 0;
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
avail = stream->size - stream->ptr;
|
||||||
if (bytes > avail)
|
if (bytes > avail)
|
||||||
bytes = avail;
|
bytes = avail;
|
||||||
|
|
||||||
memcpy(data, stream->m_buf + stream->m_ptr, bytes);
|
memcpy(data, stream->buf + stream->ptr, bytes);
|
||||||
stream->m_ptr += bytes;
|
stream->ptr += bytes;
|
||||||
|
memstream_update_pos(stream);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memstream_write(memstream_t *stream, const void *data, size_t bytes)
|
size_t memstream_write(memstream_t *stream, const void *data, size_t bytes)
|
||||||
{
|
{
|
||||||
size_t avail = stream->m_size - stream->m_ptr;
|
size_t avail = 0;
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
avail = stream->size - stream->ptr;
|
||||||
if (bytes > avail)
|
if (bytes > avail)
|
||||||
bytes = avail;
|
bytes = avail;
|
||||||
|
|
||||||
memcpy(stream->m_buf + stream->m_ptr, data, bytes);
|
memcpy(stream->buf + stream->ptr, data, bytes);
|
||||||
stream->m_ptr += bytes;
|
stream->ptr += bytes;
|
||||||
|
memstream_update_pos(stream);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,26 +136,32 @@ int memstream_seek(memstream_t *stream, int offset, int whence)
|
||||||
ptr = offset;
|
ptr = offset;
|
||||||
break;
|
break;
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
ptr = stream->m_ptr + offset;
|
ptr = stream->ptr + offset;
|
||||||
break;
|
break;
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
ptr = stream->m_size + offset;
|
ptr = (stream->writing ? stream->max_ptr : stream->size) + offset;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr <= stream->m_size)
|
if (ptr <= stream->size)
|
||||||
{
|
{
|
||||||
stream->m_ptr = ptr;
|
stream->ptr = ptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memstream_rewind(memstream_t *stream)
|
||||||
|
{
|
||||||
|
memstream_seek(stream, 0L, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
size_t memstream_pos(memstream_t *stream)
|
size_t memstream_pos(memstream_t *stream)
|
||||||
{
|
{
|
||||||
return stream->m_ptr;
|
return stream->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
|
char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
|
||||||
|
@ -136,7 +171,20 @@ char *memstream_gets(memstream_t *stream, char *buffer, size_t len)
|
||||||
|
|
||||||
int memstream_getc(memstream_t *stream)
|
int memstream_getc(memstream_t *stream)
|
||||||
{
|
{
|
||||||
if (stream->m_ptr >= stream->m_size)
|
int ret = 0;
|
||||||
|
if (stream->ptr >= stream->size)
|
||||||
return EOF;
|
return EOF;
|
||||||
return stream->m_buf[stream->m_ptr++];
|
ret = stream->buf[stream->ptr++];
|
||||||
|
|
||||||
|
memstream_update_pos(stream);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memstream_putc(memstream_t *stream, int c)
|
||||||
|
{
|
||||||
|
if (stream->ptr < stream->size)
|
||||||
|
stream->buf[stream->ptr++] = c;
|
||||||
|
|
||||||
|
memstream_update_pos(stream);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue