From b0f4989230eb5c7ee21e81966dcf1cb6e5e464f0 Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 22 Apr 2016 00:34:34 +0000 Subject: [PATCH] update libretro-common --- .../src/libretro-common/file/archive_file.c | 20 +- .../libretro-common/file/archive_file_zlib.c | 7 +- desmume/src/libretro-common/glsm/glsm.c | 52 +++- .../libretro-common/include/glsm/glsmsym.h | 18 +- .../libretro-common/include/lists/file_list.h | 5 + .../include/rthreads/rsemaphore.h | 10 + .../include/streams/file_stream.h | 2 + .../include/streams/interface_stream.h | 85 ++++++ .../include/streams/memory_stream.h | 6 +- desmume/src/libretro-common/libco/amd64.c | 4 +- desmume/src/libretro-common/lists/file_list.c | 43 +++ .../libretro-common/queues/message_queue.c | 17 +- .../src/libretro-common/rthreads/rsemaphore.c | 19 ++ .../src/libretro-common/rthreads/rthreads.c | 4 + .../src/libretro-common/streams/file_stream.c | 211 ++++++++------ .../streams/interface_stream.c | 270 ++++++++++++++++++ .../libretro-common/streams/memory_stream.c | 94 ++++-- 17 files changed, 723 insertions(+), 144 deletions(-) create mode 100644 desmume/src/libretro-common/include/streams/interface_stream.h create mode 100644 desmume/src/libretro-common/streams/interface_stream.c diff --git a/desmume/src/libretro-common/file/archive_file.c b/desmume/src/libretro-common/file/archive_file.c index 9592f2294..936f4f374 100644 --- a/desmume/src/libretro-common/file/archive_file.c +++ b/desmume/src/libretro-common/file/archive_file.c @@ -216,9 +216,6 @@ static int file_archive_get_file_list_cb( (void)csize; (void)size; (void)checksum; - (void)valid_exts; - (void)file_ext; - (void)ext_list; memset(&attr, 0, sizeof(attr)); @@ -538,10 +535,8 @@ static bool file_archive_parse_file(const char *file, const char *valid_exts, for (;;) { - int ret = file_archive_parse_file_iterate(&state, &returnerr, file, - valid_exts, file_cb, userdata); - - if (ret != 0) + if (file_archive_parse_file_iterate(&state, &returnerr, file, + valid_exts, file_cb, userdata) != 0) break; } @@ -656,7 +651,7 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts, { case ZLIB_MODE_UNCOMPRESSED: if (!filestream_write_file(path, cdata, size)) - return false; + goto error; break; 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, cdata, csize, size)) - return false; + goto error; do{ 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, ret, path, valid_exts, cdata, csize, size, crc32)) - return false; + goto error; } break; default: - return false; + goto error; } return true; + +error: + return false; } const struct file_archive_file_backend *file_archive_get_default_file_backend(void) diff --git a/desmume/src/libretro-common/file/archive_file_zlib.c b/desmume/src/libretro-common/file/archive_file_zlib.c index 42f3ba92c..fd9fb281b 100644 --- a/desmume/src/libretro-common/file/archive_file_zlib.c +++ b/desmume/src/libretro-common/file/archive_file_zlib.c @@ -167,7 +167,7 @@ static int zlib_stream_decompress_data_to_file_iterate(void *data) z_stream *stream = (z_stream*)data; if (!stream) - return -1; + goto error; zstatus = inflate(stream, Z_NO_FLUSH); @@ -175,9 +175,12 @@ static int zlib_stream_decompress_data_to_file_iterate(void *data) return 1; if (zstatus != Z_OK && zstatus != Z_BUF_ERROR) - return -1; + goto error; return 0; + +error: + return -1; } static void zlib_stream_compress_init(void *data, int level) diff --git a/desmume/src/libretro-common/glsm/glsm.c b/desmume/src/libretro-common/glsm/glsm.c index 7e36c4c8c..fdeee70d3 100644 --- a/desmume/src/libretro-common/glsm/glsm.c +++ b/desmume/src/libretro-common/glsm/glsm.c @@ -421,6 +421,15 @@ void rglLinkProgram(GLuint 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, GLenum textarget, GLuint texture, GLint level) { @@ -446,7 +455,7 @@ void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); } -void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers) +void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { glDeleteFramebuffers(n, framebuffers); } @@ -703,6 +712,12 @@ void rglUniform4fv(GLint location, GLsizei count, const GLfloat *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) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -712,6 +727,41 @@ void rglPolygonOffset(GLfloat factor, GLfloat 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 */ static void glsm_state_setup(void) diff --git a/desmume/src/libretro-common/include/glsm/glsmsym.h b/desmume/src/libretro-common/include/glsm/glsmsym.h index eac9b3627..78553a372 100644 --- a/desmume/src/libretro-common/include/glsm/glsmsym.h +++ b/desmume/src/libretro-common/include/glsm/glsmsym.h @@ -41,6 +41,7 @@ extern "C" { #define glCompressedTexImage2D rglCompressedTexImage2D #define glBindTexture rglBindTexture #define glActiveTexture rglActiveTexture +#define glFramebufferTexture rglFramebufferTexture #define glFramebufferTexture2D rglFramebufferTexture2D #define glFramebufferRenderbuffer rglFramebufferRenderbuffer #define glDeleteFramebuffers rglDeleteFramebuffers @@ -112,22 +113,35 @@ extern "C" { #define glReadBuffer rglReadBuffer #define glUniformMatrix4fv rglUniformMatrix4fv #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 rglPixelStorei(GLenum pname, GLint param); void rglTexCoord2f(GLfloat s, GLfloat t); void rglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); +void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, + GLsizei width, GLsizei height); void rglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); void glBindTexture(GLenum target, GLuint texture); void glActiveTexture(GLenum texture); +void rglFramebufferTexture(GLenum target, GLenum attachment, + GLuint texture, GLint level); void rglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers); +void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers); void rglRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); 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, const GLfloat *value); GLint rglGetAttribLocation(GLuint program, const GLchar *name); +void rglDrawBuffers(GLsizei n, const GLenum *bufs); +void rglBindVertexArray(GLuint array); #ifdef __cplusplus } diff --git a/desmume/src/libretro-common/include/lists/file_list.h b/desmume/src/libretro-common/include/lists/file_list.h index 849c5a5f0..d23c2ce3a 100644 --- a/desmume/src/libretro-common/include/lists/file_list.h +++ b/desmume/src/libretro-common/include/lists/file_list.h @@ -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, 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_clear(file_list_t *list); diff --git a/desmume/src/libretro-common/include/rthreads/rsemaphore.h b/desmume/src/libretro-common/include/rthreads/rsemaphore.h index 9dbb82155..6c0f1a392 100644 --- a/desmume/src/libretro-common/include/rthreads/rsemaphore.h +++ b/desmume/src/libretro-common/include/rthreads/rsemaphore.h @@ -23,6 +23,10 @@ #ifndef __LIBRETRO_SDK_SEMAPHORE_H #define __LIBRETRO_SDK_SEMAPHORE_H +#ifdef __cplusplus +extern "C" { +#endif + typedef struct ssem ssem_t; /** @@ -37,8 +41,14 @@ ssem_t *ssem_new(int value); void ssem_free(ssem_t *semaphore); +int ssem_get(ssem_t *semaphore); + void ssem_wait(ssem_t *semaphore); void ssem_signal(ssem_t *semaphore); +#ifdef __cplusplus +} +#endif + #endif /* __LIBRETRO_SDK_SEMAPHORE_H */ diff --git a/desmume/src/libretro-common/include/streams/file_stream.h b/desmume/src/libretro-common/include/streams/file_stream.h index 5a1784df3..5fd1aa148 100644 --- a/desmume/src/libretro-common/include/streams/file_stream.h +++ b/desmume/src/libretro-common/include/streams/file_stream.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); +int filestream_putc(RFILE *stream, int c); + int filestream_get_fd(RFILE *stream); #ifdef __cplusplus diff --git a/desmume/src/libretro-common/include/streams/interface_stream.h b/desmume/src/libretro-common/include/streams/interface_stream.h new file mode 100644 index 000000000..c5b2e46b6 --- /dev/null +++ b/desmume/src/libretro-common/include/streams/interface_stream.h @@ -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 +#include + +#include + +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 diff --git a/desmume/src/libretro-common/include/streams/memory_stream.h b/desmume/src/libretro-common/include/streams/memory_stream.h index 3609d6f0f..5f196ea62 100644 --- a/desmume/src/libretro-common/include/streams/memory_stream.h +++ b/desmume/src/libretro-common/include/streams/memory_stream.h @@ -28,7 +28,7 @@ typedef struct memstream memstream_t; -memstream_t *memstream_open(void); +memstream_t *memstream_open(unsigned writing); 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); +void memstream_putc(memstream_t *stream, int c); + char *memstream_gets(memstream_t *stream, char *buffer, size_t len); size_t memstream_pos(memstream_t *stream); +void memstream_rewind(memstream_t *stream); + int memstream_seek(memstream_t *stream, int offset, int whence); void memstream_set_buffer(uint8_t *buffer, size_t size); diff --git a/desmume/src/libretro-common/libco/amd64.c b/desmume/src/libretro-common/libco/amd64.c index fd95843a3..24944159f 100644 --- a/desmume/src/libretro-common/libco/amd64.c +++ b/desmume/src/libretro-common/libco/amd64.c @@ -24,7 +24,7 @@ static void (*co_swap)(cothread_t, cothread_t) = 0; #endif #ifdef _WIN32 -//ABI: Win64 +/* ABI: Win64 */ static unsigned char co_swap_function[] = { 0x48, 0x89, 0x22, /* mov [rdx],rsp */ 0x48, 0x8b, 0x21, /* mov rsp,[rcx] */ @@ -81,7 +81,7 @@ void co_init(void) sizeof(co_swap_function), PAGE_EXECUTE_READWRITE, &old_privileges); } #else -//ABI: SystemV +/* ABI: SystemV */ #ifndef CO_USE_INLINE_ASM static unsigned char co_swap_function[] = { 0x48, 0x89, 0x26, /* mov [rsi],rsp */ diff --git a/desmume/src/libretro-common/lists/file_list.c b/desmume/src/libretro-common/lists/file_list.c index 736a24bde..2dc9770f5 100644 --- a/desmume/src/libretro-common/lists/file_list.c +++ b/desmume/src/libretro-common/lists/file_list.c @@ -59,6 +59,49 @@ static bool file_list_capacity(file_list_t *list, size_t cap) 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, const char *path, const char *label, unsigned type, size_t directory_ptr, diff --git a/desmume/src/libretro-common/queues/message_queue.c b/desmume/src/libretro-common/queues/message_queue.c index 56e7895d1..9b27745cb 100644 --- a/desmume/src/libretro-common/queues/message_queue.c +++ b/desmume/src/libretro-common/queues/message_queue.c @@ -175,12 +175,9 @@ void msg_queue_clear(msg_queue_t *queue) **/ const char *msg_queue_pull(msg_queue_t *queue) { - struct queue_elem *front = NULL, *last = NULL, - *parent = NULL, *child = NULL; + struct queue_elem *front = NULL, *last = NULL; size_t tmp_ptr = 1; - (void)parent; - (void)child; (void)tmp_ptr; /* Nothing in queue. */ @@ -203,10 +200,12 @@ const char *msg_queue_pull(msg_queue_t *queue) for (;;) { - size_t switch_index = tmp_ptr; - bool left = (tmp_ptr * 2 <= queue->ptr) + struct queue_elem *parent = NULL; + 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]); - 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]); if (!left && !right) @@ -227,9 +226,9 @@ const char *msg_queue_pull(msg_queue_t *queue) parent = (struct queue_elem*)queue->elems[tmp_ptr]; child = (struct queue_elem*)queue->elems[switch_index]; - queue->elems[tmp_ptr] = child; + queue->elems[tmp_ptr] = child; queue->elems[switch_index] = parent; - tmp_ptr = switch_index; + tmp_ptr = switch_index; } return queue->tmp_msg; diff --git a/desmume/src/libretro-common/rthreads/rsemaphore.c b/desmume/src/libretro-common/rthreads/rsemaphore.c index 2a9411ee9..1e7cc852b 100644 --- a/desmume/src/libretro-common/rthreads/rsemaphore.c +++ b/desmume/src/libretro-common/rthreads/rsemaphore.c @@ -20,6 +20,10 @@ * 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 #include @@ -73,6 +77,21 @@ void ssem_free(ssem_t *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) { if (!semaphore) diff --git a/desmume/src/libretro-common/rthreads/rthreads.c b/desmume/src/libretro-common/rthreads/rthreads.c index 8221c9abf..7d6767cd0 100644 --- a/desmume/src/libretro-common/rthreads/rthreads.c +++ b/desmume/src/libretro-common/rthreads/rthreads.c @@ -20,6 +20,10 @@ * 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 #include diff --git a/desmume/src/libretro-common/streams/file_stream.c b/desmume/src/libretro-common/streams/file_stream.c index 40d381495..d6ee69691 100644 --- a/desmume/src/libretro-common/streams/file_stream.c +++ b/desmume/src/libretro-common/streams/file_stream.c @@ -66,10 +66,6 @@ #include #include -#if 1 -#define HAVE_BUFFERED_IO 1 -#endif - struct RFILE { unsigned hints; @@ -78,6 +74,9 @@ struct RFILE #elif defined(__CELLOS_LV2__) int fd; #else + +#define HAVE_BUFFERED_IO 1 + #if defined(HAVE_BUFFERED_IO) FILE *fp; #endif @@ -94,28 +93,25 @@ int filestream_get_fd(RFILE *stream) { if (!stream) return -1; -#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) - return stream->fd; -#else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fileno(stream->fp); #endif return stream->fd; -#endif } RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) { int flags = 0; int mode_int = 0; +#if defined(HAVE_BUFFERED_IO) const char *mode_str = NULL; +#endif RFILE *stream = (RFILE*)calloc(1, sizeof(*stream)); if (!stream) return NULL; - (void)mode_str; (void)mode_int; (void)flags; @@ -220,7 +216,8 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) 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) stream->hints &= ~RFILE_HINT_MMAP; @@ -243,98 +240,103 @@ error: 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) - return -1; - - (void)ret; + goto error; #if defined(VITA) || defined(PSP) - ret = sceIoLseek(stream->fd, (SceOff)offset, whence); - if (ret == -1) - return -1; - return 0; + if (sceIoLseek(stream->fd, (SceOff)offset, whence) == -1) + goto error; #elif defined(__CELLOS_LV2__) - uint64_t pos = 0; if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED) - return -1; - return 0; + goto error; #else + #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fseek(stream->fp, (long)offset, whence); - else #endif + #ifdef HAVE_MMAP - /* Need to check stream->mapped because this function is - * called in filestream_open() */ - if (stream->mapped && stream->hints & RFILE_HINT_MMAP) + /* Need to check stream->mapped because this function is + * called in filestream_open() */ + 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 - read-only file descriptors. */ - switch (whence) - { - case SEEK_SET: - if (offset < 0) - return -1; + case SEEK_SET: + if (offset < 0) + goto error; - stream->mappos = offset; - break; + stream->mappos = offset; + break; - case SEEK_CUR: - if ((offset < 0 && stream->mappos + offset > stream->mappos) || - (offset > 0 && stream->mappos + offset < stream->mappos)) - return -1; + case SEEK_CUR: + if ((offset < 0 && stream->mappos + offset > stream->mappos) || + (offset > 0 && stream->mappos + offset < stream->mappos)) + goto error; - stream->mappos += offset; - break; + stream->mappos += offset; + break; - case SEEK_END: - if (stream->mapsize + offset < stream->mapsize) - return -1; + case SEEK_END: + if (stream->mapsize + offset < stream->mapsize) + goto error; - stream->mappos = stream->mapsize + offset; - - break; - } - - return stream->mappos; + stream->mappos = stream->mapsize + offset; + break; } - else + return stream->mappos; + } #endif - { - ret = lseek(stream->fd, offset, whence); - return ret < 0 ? -1 : ret; - } + + if (lseek(stream->fd, offset, whence) < 0) + goto error; + #endif + + return 0; + +error: + return -1; } ssize_t filestream_tell(RFILE *stream) { - if (!stream) - return -1; -#if defined(VITA) || defined(PSP) - return sceIoLseek(stream->fd, 0, SEEK_CUR); -#elif defined(__CELLOS_LV2__) +#if defined(__CELLOS_LV2__) 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) - return -1; - return 0; + goto error; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return ftell(stream->fp); - else #endif #ifdef HAVE_MMAP - /* Need to check stream->mapped because this function - * is called in filestream_open() */ - if (stream->mapped && stream->hints & RFILE_HINT_MMAP) - return stream->mappos; - else + /* Need to check stream->mapped because this function + * is called in filestream_open() */ + if (stream->mapped && stream->hints & RFILE_HINT_MMAP) + return stream->mappos; #endif - return lseek(stream->fd, 0, SEEK_CUR); + if (lseek(stream->fd, 0, SEEK_CUR) < 0) + goto error; #endif + + return 0; + +error: + return -1; } 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) { if (!stream || !s) - return -1; + goto error; #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; + goto error; return bytes_written; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fread(s, 1, len, stream->fp); - else #endif #ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP) - { - if (stream->mappos > stream->mapsize) - return -1; + if (stream->hints & RFILE_HINT_MMAP) + { + if (stream->mappos > stream->mapsize) + goto error; - if (stream->mappos + len > stream->mapsize) - len = stream->mapsize - stream->mappos; + if (stream->mappos + len > stream->mapsize) + len = stream->mapsize - stream->mappos; - memcpy(s, &stream->mapped[stream->mappos], len); - stream->mappos += len; + memcpy(s, &stream->mapped[stream->mappos], len); + stream->mappos += len; - return len; - } - else + return len; + } #endif - return read(stream->fd, s, len); + return read(stream->fd, s, len); #endif + +error: + return -1; } ssize_t filestream_write(RFILE *stream, const void *s, size_t len) { if (!stream) - return -1; + goto error; #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; + goto error; return bytes_written; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fwrite(s, 1, len, stream->fp); - else #endif #ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP) - return -1; - else + if (stream->hints & RFILE_HINT_MMAP) + goto error; #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 } int filestream_close(RFILE *stream) { if (!stream) - return -1; + goto error; #if defined(VITA) || defined(PSP) if (stream->fd > 0) @@ -430,12 +447,15 @@ int filestream_close(RFILE *stream) munmap(stream->mapped, stream->mapsize); #endif - if (stream->fd > 0) - close(stream->fd); + if (stream->fd > 0) + close(stream->fd); #endif free(stream); 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); filestream_close(file); - return (ret == size); + if (ret != size) + return false; + + return true; } diff --git a/desmume/src/libretro-common/streams/interface_stream.c b/desmume/src/libretro-common/streams/interface_stream.c new file mode 100644 index 000000000..995ac218a --- /dev/null +++ b/desmume/src/libretro-common/streams/interface_stream.c @@ -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 + +#include +#include +#include + +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; + } +} diff --git a/desmume/src/libretro-common/streams/memory_stream.c b/desmume/src/libretro-common/streams/memory_stream.c index 745ae7e08..6bffa3b72 100644 --- a/desmume/src/libretro-common/streams/memory_stream.c +++ b/desmume/src/libretro-common/streams/memory_stream.c @@ -32,11 +32,19 @@ static size_t last_file_size = 0; struct memstream { - uint8_t *m_buf; - size_t m_size; - size_t m_ptr; + uint8_t *buf; + size_t size; + 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) { g_buffer = buffer; @@ -48,21 +56,27 @@ 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) +static void memstream_init(memstream_t *stream, + uint8_t *buffer, size_t max_size, unsigned writing) { - stream->m_buf = buffer; - stream->m_size = max_size; - stream->m_ptr = 0; + if (!stream) + return; + + 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; if (!g_buffer || !g_size) return NULL; 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_size = 0; @@ -71,29 +85,44 @@ memstream_t *memstream_open(void) 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); } 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) bytes = avail; - memcpy(data, stream->m_buf + stream->m_ptr, bytes); - stream->m_ptr += bytes; + memcpy(data, stream->buf + stream->ptr, bytes); + stream->ptr += bytes; + memstream_update_pos(stream); return 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) bytes = avail; - memcpy(stream->m_buf + stream->m_ptr, data, bytes); - stream->m_ptr += bytes; + memcpy(stream->buf + stream->ptr, data, bytes); + stream->ptr += bytes; + memstream_update_pos(stream); return bytes; } @@ -107,26 +136,32 @@ int memstream_seek(memstream_t *stream, int offset, int whence) ptr = offset; break; case SEEK_CUR: - ptr = stream->m_ptr + offset; + ptr = stream->ptr + offset; break; case SEEK_END: - ptr = stream->m_size + offset; + ptr = (stream->writing ? stream->max_ptr : stream->size) + offset; break; default: return -1; } - if (ptr <= stream->m_size) + if (ptr <= stream->size) { - stream->m_ptr = ptr; + stream->ptr = ptr; return 0; } + return -1; } +void memstream_rewind(memstream_t *stream) +{ + memstream_seek(stream, 0L, SEEK_SET); +} + 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) @@ -136,7 +171,20 @@ char *memstream_gets(memstream_t *stream, char *buffer, size_t len) int memstream_getc(memstream_t *stream) { - if (stream->m_ptr >= stream->m_size) + int ret = 0; + if (stream->ptr >= stream->size) 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); }