2001-04-26 16:45:43 +00:00
|
|
|
/*
|
2011-04-08 13:03:26 -07:00
|
|
|
Simple DirectMedia Layer
|
2011-12-31 09:28:07 -05:00
|
|
|
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
2011-04-08 13:03:26 -07:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
2001-04-26 16:45:43 +00:00
|
|
|
*/
|
2006-02-21 08:46:50 +00:00
|
|
|
#include "SDL_config.h"
|
2001-04-26 16:45:43 +00:00
|
|
|
|
|
|
|
/* This file provides a general interface for SDL to read and write
|
|
|
|
data sources. It can easily be extended to files, memory, etc.
|
|
|
|
*/
|
|
|
|
|
2006-02-09 09:38:05 +00:00
|
|
|
#include "SDL_endian.h"
|
2006-02-07 09:29:18 +00:00
|
|
|
#include "SDL_rwops.h"
|
2006-02-06 08:28:51 +00:00
|
|
|
|
Added automated test to Xcode project plus needed changes to SDL_RWFromFile to be OS X bundle aware.
The Mac OS X project has a new target called testsdl which builds the automated test. I looked at using Xcode's native unit test support, but the impedance mismatch between the existing automated test structure and Apple's was more than I could handle.
As such, the testsdl application is a full blown proper OS X application, which means it is a self-contained .app bundle. This immediately revealed some problems from the automated test. The largest problem was the assumption about the current working directory and where to find resources. (I suspect Windows may have a similar problem depending on circumstance.) To open resources, the test was looking in directories relative to the SDL source directory, but this will not work well with self-contained .app bundles and Xcode which can place its built applications almost anywhere. And for real-world situations, this is pretty useless anyway.
So I modified SDL_RWFromFile to do special things on OS X. First, it will look for a file in the .app bundle. If not found, it will fallback and just call fopen as it used to do.
I also had to modify the automated test itself because it had a contrieved test which called fopen directly to do read from an existing FILE pointer. In addition, there was a write test. Since a .app bundle is likely going to be read-only, I added a special case for OS X to write to NSTemporaryDirectory.
I expect these changes should work for both Mac and iPhone OS (which includes iPad).
I will update the iPhone Xcode project next.
Finally, FYI, the X11 automated test seems to be failing. Below is my output.
Pending breakpoint 4 - "-[NSException raise]" resolved
Platform : All tests successful (2)
SDL_RWops : All tests successful (5)
Rect : All tests successful (1)
SDL_Surface : All tests successful (6)
Rendering with cocoa driver : All tests successful (3)
Assert Failed!
Blit output not the same.
Test Case 'Renderer x11'
Test Suite 'Rendering with x11 driver'
Last SDL error ''
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint() to catch errors as they are logged.
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Rendering with x11 driver : Failed 1 out of 4 testcases!
Rendering with dummy driver : All tests successful (3)
SDL_Audio : All tests successful (1)
Tests run with SDL 1.3.0 revision 1095906
System is running Mac OS X and is little endian
2010-05-08 00:54:22 -07:00
|
|
|
#ifdef __APPLE__
|
2010-05-09 10:00:33 -07:00
|
|
|
#include "cocoa/SDL_rwopsbundlesupport.h"
|
Added automated test to Xcode project plus needed changes to SDL_RWFromFile to be OS X bundle aware.
The Mac OS X project has a new target called testsdl which builds the automated test. I looked at using Xcode's native unit test support, but the impedance mismatch between the existing automated test structure and Apple's was more than I could handle.
As such, the testsdl application is a full blown proper OS X application, which means it is a self-contained .app bundle. This immediately revealed some problems from the automated test. The largest problem was the assumption about the current working directory and where to find resources. (I suspect Windows may have a similar problem depending on circumstance.) To open resources, the test was looking in directories relative to the SDL source directory, but this will not work well with self-contained .app bundles and Xcode which can place its built applications almost anywhere. And for real-world situations, this is pretty useless anyway.
So I modified SDL_RWFromFile to do special things on OS X. First, it will look for a file in the .app bundle. If not found, it will fallback and just call fopen as it used to do.
I also had to modify the automated test itself because it had a contrieved test which called fopen directly to do read from an existing FILE pointer. In addition, there was a write test. Since a .app bundle is likely going to be read-only, I added a special case for OS X to write to NSTemporaryDirectory.
I expect these changes should work for both Mac and iPhone OS (which includes iPad).
I will update the iPhone Xcode project next.
Finally, FYI, the X11 automated test seems to be failing. Below is my output.
Pending breakpoint 4 - "-[NSException raise]" resolved
Platform : All tests successful (2)
SDL_RWops : All tests successful (5)
Rect : All tests successful (1)
SDL_Surface : All tests successful (6)
Rendering with cocoa driver : All tests successful (3)
Assert Failed!
Blit output not the same.
Test Case 'Renderer x11'
Test Suite 'Rendering with x11 driver'
Last SDL error ''
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint() to catch errors as they are logged.
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Rendering with x11 driver : Failed 1 out of 4 testcases!
Rendering with dummy driver : All tests successful (3)
SDL_Audio : All tests successful (1)
Tests run with SDL 1.3.0 revision 1095906
System is running Mac OS X and is little endian
2010-05-08 00:54:22 -07:00
|
|
|
#endif /* __APPLE__ */
|
|
|
|
|
2011-07-29 16:51:25 -04:00
|
|
|
#ifdef ANDROID
|
|
|
|
#include "../core/android/SDL_android.h"
|
|
|
|
#endif
|
|
|
|
|
2008-08-27 15:10:03 +00:00
|
|
|
#ifdef __NDS__
|
|
|
|
/* include libfat headers for fatInitDefault(). */
|
|
|
|
#include <fat.h>
|
|
|
|
#endif /* __NDS__ */
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2011-01-24 15:46:11 -08:00
|
|
|
#ifdef __WIN32__
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2006-02-27 04:16:44 +00:00
|
|
|
/* Functions to read/write Win32 API file pointers */
|
2006-03-04 08:24:35 +00:00
|
|
|
/* Will not use it on WinCE because stdio is buffered, it means
|
|
|
|
faster, and all stdio functions anyway are embedded in coredll.dll -
|
|
|
|
the main wince dll*/
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2011-01-24 21:20:30 -08:00
|
|
|
#include "../core/windows/SDL_windows.h"
|
2006-02-27 03:48:48 +00:00
|
|
|
|
2006-03-04 08:24:35 +00:00
|
|
|
#ifndef INVALID_SET_FILE_POINTER
|
|
|
|
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF
|
|
|
|
#endif
|
|
|
|
|
2007-07-10 05:01:22 +00:00
|
|
|
#define READAHEAD_BUFFER_SIZE 1024
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
static int SDLCALL
|
2011-01-20 18:04:05 -08:00
|
|
|
windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
|
2006-03-04 08:24:35 +00:00
|
|
|
{
|
|
|
|
#ifndef _WIN32_WCE
|
2006-07-10 21:04:37 +00:00
|
|
|
UINT old_error_mode;
|
2006-03-04 08:24:35 +00:00
|
|
|
#endif
|
2006-07-10 21:04:37 +00:00
|
|
|
HANDLE h;
|
|
|
|
DWORD r_right, w_right;
|
|
|
|
DWORD must_exist, truncate;
|
|
|
|
int a_mode;
|
|
|
|
|
|
|
|
if (!context)
|
2007-07-10 16:05:50 +00:00
|
|
|
return -1; /* failed (invalid call) */
|
2007-07-10 05:01:22 +00:00
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
|
|
|
|
context->hidden.windowsio.buffer.data = NULL;
|
|
|
|
context->hidden.windowsio.buffer.size = 0;
|
|
|
|
context->hidden.windowsio.buffer.left = 0;
|
2007-07-10 19:06:02 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* "r" = reading, file must exist */
|
|
|
|
/* "w" = writing, truncate existing, file may not exist */
|
|
|
|
/* "r+"= reading or writing, file must exist */
|
|
|
|
/* "a" = writing, append file may not exist */
|
|
|
|
/* "a+"= append + read, file may not exist */
|
|
|
|
/* "w+" = read, write, truncate. file may not exist */
|
|
|
|
|
|
|
|
must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
|
|
|
|
truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
|
|
|
|
r_right = (SDL_strchr(mode, '+') != NULL
|
|
|
|
|| must_exist) ? GENERIC_READ : 0;
|
|
|
|
a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
|
|
|
|
w_right = (a_mode || SDL_strchr(mode, '+')
|
|
|
|
|| truncate) ? GENERIC_WRITE : 0;
|
|
|
|
|
|
|
|
if (!r_right && !w_right) /* inconsistent mode */
|
|
|
|
return -1; /* failed (invalid call) */
|
2006-03-04 08:24:35 +00:00
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
context->hidden.windowsio.buffer.data =
|
2007-07-11 14:51:49 +00:00
|
|
|
(char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
|
2011-01-20 18:04:05 -08:00
|
|
|
if (!context->hidden.windowsio.buffer.data) {
|
2007-07-10 19:06:02 +00:00
|
|
|
SDL_OutOfMemory();
|
|
|
|
return -1;
|
|
|
|
}
|
2006-03-04 08:24:35 +00:00
|
|
|
#ifdef _WIN32_WCE
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
2011-01-24 21:20:30 -08:00
|
|
|
LPTSTR tstr = WIN_UTF8ToString(filename);
|
|
|
|
h = CreateFile(tstr, (w_right | r_right),
|
2006-07-10 21:04:37 +00:00
|
|
|
(w_right) ? 0 : FILE_SHARE_READ, NULL,
|
|
|
|
(must_exist | truncate | a_mode),
|
|
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
2011-01-24 21:20:30 -08:00
|
|
|
SDL_free(tstr);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2006-03-04 08:24:35 +00:00
|
|
|
#else
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Do not open a dialog box if failure */
|
|
|
|
old_error_mode =
|
|
|
|
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
|
2006-03-04 08:24:35 +00:00
|
|
|
|
2011-01-24 21:20:30 -08:00
|
|
|
{
|
|
|
|
LPTSTR tstr = WIN_UTF8ToString(filename);
|
|
|
|
h = CreateFile(tstr, (w_right | r_right),
|
|
|
|
(w_right) ? 0 : FILE_SHARE_READ, NULL,
|
|
|
|
(must_exist | truncate | a_mode),
|
|
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
SDL_free(tstr);
|
|
|
|
}
|
2006-03-04 08:24:35 +00:00
|
|
|
|
2011-01-24 21:20:30 -08:00
|
|
|
/* restore old behavior */
|
2006-07-10 21:04:37 +00:00
|
|
|
SetErrorMode(old_error_mode);
|
2006-03-04 08:24:35 +00:00
|
|
|
#endif /* _WIN32_WCE */
|
2006-02-27 03:48:48 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
if (h == INVALID_HANDLE_VALUE) {
|
2011-01-20 18:04:05 -08:00
|
|
|
SDL_free(context->hidden.windowsio.buffer.data);
|
|
|
|
context->hidden.windowsio.buffer.data = NULL;
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_SetError("Couldn't open %s", filename);
|
|
|
|
return -2; /* failed (CreateFile) */
|
|
|
|
}
|
2011-01-20 18:04:05 -08:00
|
|
|
context->hidden.windowsio.h = h;
|
|
|
|
context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
return 0; /* ok */
|
2006-02-27 03:48:48 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static long SDLCALL
|
2011-01-20 18:04:05 -08:00
|
|
|
windows_file_seek(SDL_RWops * context, long offset, int whence)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
2011-01-20 18:04:05 -08:00
|
|
|
DWORD windowswhence;
|
2007-07-10 05:25:19 +00:00
|
|
|
long file_pos;
|
2006-02-27 03:48:48 +00:00
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
|
|
|
|
SDL_SetError("windows_file_seek: invalid context/file not opened");
|
2006-07-10 21:04:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-02-27 03:48:48 +00:00
|
|
|
|
2007-07-10 05:01:22 +00:00
|
|
|
/* FIXME: We may be able to satisfy the seek within buffered data */
|
2011-01-20 18:04:05 -08:00
|
|
|
if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
|
|
|
|
offset -= (long)context->hidden.windowsio.buffer.left;
|
2007-07-10 05:01:22 +00:00
|
|
|
}
|
2011-01-20 18:04:05 -08:00
|
|
|
context->hidden.windowsio.buffer.left = 0;
|
2007-07-10 05:01:22 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
switch (whence) {
|
|
|
|
case RW_SEEK_SET:
|
2011-01-20 18:04:05 -08:00
|
|
|
windowswhence = FILE_BEGIN;
|
2006-07-10 21:04:37 +00:00
|
|
|
break;
|
|
|
|
case RW_SEEK_CUR:
|
2011-01-20 18:04:05 -08:00
|
|
|
windowswhence = FILE_CURRENT;
|
2006-07-10 21:04:37 +00:00
|
|
|
break;
|
|
|
|
case RW_SEEK_END:
|
2011-01-20 18:04:05 -08:00
|
|
|
windowswhence = FILE_END;
|
2006-07-10 21:04:37 +00:00
|
|
|
break;
|
|
|
|
default:
|
2011-01-20 18:04:05 -08:00
|
|
|
SDL_SetError("windows_file_seek: Unknown value for 'whence'");
|
2006-07-10 21:04:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-02-27 03:48:48 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
file_pos =
|
2011-01-20 18:04:05 -08:00
|
|
|
SetFilePointer(context->hidden.windowsio.h, offset, NULL, windowswhence);
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
if (file_pos != INVALID_SET_FILE_POINTER)
|
|
|
|
return file_pos; /* success */
|
2006-02-27 04:16:44 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_Error(SDL_EFSEEK);
|
|
|
|
return -1; /* error */
|
2006-02-27 04:16:44 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
2011-01-20 18:04:05 -08:00
|
|
|
windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
2006-02-27 04:16:44 +00:00
|
|
|
{
|
2007-07-10 05:25:19 +00:00
|
|
|
size_t total_need;
|
|
|
|
size_t total_read = 0;
|
|
|
|
size_t read_ahead;
|
2007-07-10 05:01:22 +00:00
|
|
|
DWORD byte_read;
|
2006-02-27 04:16:44 +00:00
|
|
|
|
2007-07-10 05:01:22 +00:00
|
|
|
total_need = size * maxnum;
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
|
2007-07-10 05:25:19 +00:00
|
|
|
|| !total_need)
|
2006-07-10 21:04:37 +00:00
|
|
|
return 0;
|
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
if (context->hidden.windowsio.buffer.left > 0) {
|
|
|
|
void *data = (char *) context->hidden.windowsio.buffer.data +
|
|
|
|
context->hidden.windowsio.buffer.size -
|
|
|
|
context->hidden.windowsio.buffer.left;
|
2007-07-12 20:00:50 +00:00
|
|
|
read_ahead =
|
2011-01-20 18:04:05 -08:00
|
|
|
SDL_min(total_need, context->hidden.windowsio.buffer.left);
|
2007-07-10 05:01:22 +00:00
|
|
|
SDL_memcpy(ptr, data, read_ahead);
|
2011-01-20 18:04:05 -08:00
|
|
|
context->hidden.windowsio.buffer.left -= read_ahead;
|
2007-07-10 05:01:22 +00:00
|
|
|
|
|
|
|
if (read_ahead == total_need) {
|
|
|
|
return maxnum;
|
|
|
|
}
|
|
|
|
ptr = (char *) ptr + read_ahead;
|
|
|
|
total_need -= read_ahead;
|
|
|
|
total_read += read_ahead;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2007-07-10 05:01:22 +00:00
|
|
|
|
|
|
|
if (total_need < READAHEAD_BUFFER_SIZE) {
|
|
|
|
if (!ReadFile
|
2011-01-20 18:04:05 -08:00
|
|
|
(context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
|
2007-07-10 05:01:22 +00:00
|
|
|
READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
|
|
|
|
SDL_Error(SDL_EFREAD);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
read_ahead = SDL_min(total_need, (int) byte_read);
|
2011-01-20 18:04:05 -08:00
|
|
|
SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
|
|
|
|
context->hidden.windowsio.buffer.size = byte_read;
|
|
|
|
context->hidden.windowsio.buffer.left = byte_read - read_ahead;
|
2007-07-10 05:01:22 +00:00
|
|
|
total_read += read_ahead;
|
|
|
|
} else {
|
|
|
|
if (!ReadFile
|
2011-01-20 18:04:05 -08:00
|
|
|
(context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
|
2007-07-10 05:01:22 +00:00
|
|
|
SDL_Error(SDL_EFREAD);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
total_read += byte_read;
|
|
|
|
}
|
|
|
|
return (total_read / size);
|
2006-02-27 04:16:44 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
2011-01-20 18:04:05 -08:00
|
|
|
windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
|
2007-07-10 05:25:19 +00:00
|
|
|
size_t num)
|
2006-02-27 04:16:44 +00:00
|
|
|
{
|
2006-02-06 08:28:51 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
size_t total_bytes;
|
2009-09-05 23:37:35 +00:00
|
|
|
DWORD byte_written;
|
|
|
|
size_t nwritten;
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
total_bytes = size * num;
|
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
|
2006-07-10 21:04:37 +00:00
|
|
|
|| total_bytes <= 0 || !size)
|
|
|
|
return 0;
|
|
|
|
|
2011-01-20 18:04:05 -08:00
|
|
|
if (context->hidden.windowsio.buffer.left) {
|
|
|
|
SetFilePointer(context->hidden.windowsio.h,
|
|
|
|
-(LONG)context->hidden.windowsio.buffer.left, NULL,
|
2007-07-10 05:01:22 +00:00
|
|
|
FILE_CURRENT);
|
2011-01-20 18:04:05 -08:00
|
|
|
context->hidden.windowsio.buffer.left = 0;
|
2007-07-10 05:01:22 +00:00
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* if in append mode, we must go to the EOF before write */
|
2011-01-20 18:04:05 -08:00
|
|
|
if (context->hidden.windowsio.append) {
|
|
|
|
if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
|
2007-07-10 05:01:22 +00:00
|
|
|
INVALID_SET_FILE_POINTER) {
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_Error(SDL_EFWRITE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
if (!WriteFile
|
2011-01-20 18:04:05 -08:00
|
|
|
(context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_Error(SDL_EFWRITE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nwritten = byte_written / size;
|
|
|
|
return nwritten;
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
static int SDLCALL
|
2011-01-20 18:04:05 -08:00
|
|
|
windows_file_close(SDL_RWops * context)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
if (context) {
|
2011-01-20 18:04:05 -08:00
|
|
|
if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
|
|
|
|
CloseHandle(context->hidden.windowsio.h);
|
|
|
|
context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2011-01-20 18:04:05 -08:00
|
|
|
if (context->hidden.windowsio.buffer.data) {
|
|
|
|
SDL_free(context->hidden.windowsio.buffer.data);
|
|
|
|
context->hidden.windowsio.buffer.data = NULL;
|
2007-07-10 05:01:22 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_FreeRW(context);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
2011-01-24 15:46:11 -08:00
|
|
|
#endif /* __WIN32__ */
|
Patch from Antonio SJ Musumeci:
"
This code with SDL-1.2.8 and CVS:
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
int
main(int argc, char** argv)
{
char alphabet[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer_file[27] = {0};
char buffer_mem[27] = {0};
int rv_file;
int rv_mem;
FILE* file_ptr;
SDL_RWops* rwop_file;
SDL_RWops* rwop_mem;
file_ptr = fopen("./blah", "w");
fwrite(alphabet, 1, sizeof(alphabet), file_ptr);
fclose(file_ptr);
rwop_mem = SDL_RWFromMem(alphabet, sizeof(alphabet));
rwop_file = SDL_RWFromFile("./blah", "r");
rv_mem = SDL_RWread(rwop_mem , buffer_mem, 5, 6);
rv_file = SDL_RWread(rwop_file, buffer_file, 5, 6);
printf("From File: %d %s\n"
"From Mem: %d %s\n",
rv_file,
buffer_file,
rv_mem,
buffer_mem);
printf("Seek end of File: %d\n"
"Seek end of Mem: %d\n",
SDL_RWseek(rwop_file, 0, SEEK_END),
SDL_RWseek(rwop_mem , 0, SEEK_END));
SDL_RWclose(rwop_file);
SDL_RWclose(rwop_mem);
return 0;
}
Produces this output:
From File: 5 ABCDEFGHIJKLMNOPQRSTUVWXYZ
From Mem: 5 ABCDEFGHIJKLMNOPQRSTUVWXY
Seek end of File: 26
Seek end of Mem: 26
"
--ryan.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401079
2005-06-24 12:48:38 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
#ifdef HAVE_STDIO_H
|
Patch from Antonio SJ Musumeci:
"
This code with SDL-1.2.8 and CVS:
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
int
main(int argc, char** argv)
{
char alphabet[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer_file[27] = {0};
char buffer_mem[27] = {0};
int rv_file;
int rv_mem;
FILE* file_ptr;
SDL_RWops* rwop_file;
SDL_RWops* rwop_mem;
file_ptr = fopen("./blah", "w");
fwrite(alphabet, 1, sizeof(alphabet), file_ptr);
fclose(file_ptr);
rwop_mem = SDL_RWFromMem(alphabet, sizeof(alphabet));
rwop_file = SDL_RWFromFile("./blah", "r");
rv_mem = SDL_RWread(rwop_mem , buffer_mem, 5, 6);
rv_file = SDL_RWread(rwop_file, buffer_file, 5, 6);
printf("From File: %d %s\n"
"From Mem: %d %s\n",
rv_file,
buffer_file,
rv_mem,
buffer_mem);
printf("Seek end of File: %d\n"
"Seek end of Mem: %d\n",
SDL_RWseek(rwop_file, 0, SEEK_END),
SDL_RWseek(rwop_mem , 0, SEEK_END));
SDL_RWclose(rwop_file);
SDL_RWclose(rwop_mem);
return 0;
}
Produces this output:
From File: 5 ABCDEFGHIJKLMNOPQRSTUVWXYZ
From Mem: 5 ABCDEFGHIJKLMNOPQRSTUVWXY
Seek end of File: 26
Seek end of Mem: 26
"
--ryan.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401079
2005-06-24 12:48:38 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Functions to read/write stdio file pointers */
|
Patch from Antonio SJ Musumeci:
"
This code with SDL-1.2.8 and CVS:
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
int
main(int argc, char** argv)
{
char alphabet[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer_file[27] = {0};
char buffer_mem[27] = {0};
int rv_file;
int rv_mem;
FILE* file_ptr;
SDL_RWops* rwop_file;
SDL_RWops* rwop_mem;
file_ptr = fopen("./blah", "w");
fwrite(alphabet, 1, sizeof(alphabet), file_ptr);
fclose(file_ptr);
rwop_mem = SDL_RWFromMem(alphabet, sizeof(alphabet));
rwop_file = SDL_RWFromFile("./blah", "r");
rv_mem = SDL_RWread(rwop_mem , buffer_mem, 5, 6);
rv_file = SDL_RWread(rwop_file, buffer_file, 5, 6);
printf("From File: %d %s\n"
"From Mem: %d %s\n",
rv_file,
buffer_file,
rv_mem,
buffer_mem);
printf("Seek end of File: %d\n"
"Seek end of Mem: %d\n",
SDL_RWseek(rwop_file, 0, SEEK_END),
SDL_RWseek(rwop_mem , 0, SEEK_END));
SDL_RWclose(rwop_file);
SDL_RWclose(rwop_mem);
return 0;
}
Produces this output:
From File: 5 ABCDEFGHIJKLMNOPQRSTUVWXYZ
From Mem: 5 ABCDEFGHIJKLMNOPQRSTUVWXY
Seek end of File: 26
Seek end of Mem: 26
"
--ryan.
--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401079
2005-06-24 12:48:38 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static long SDLCALL
|
|
|
|
stdio_seek(SDL_RWops * context, long offset, int whence)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
|
|
|
if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
|
|
|
|
return (ftell(context->hidden.stdio.fp));
|
|
|
|
} else {
|
|
|
|
SDL_Error(SDL_EFSEEK);
|
|
|
|
return (-1);
|
|
|
|
}
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
|
|
|
stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
size_t nread;
|
|
|
|
|
|
|
|
nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
|
|
|
|
if (nread == 0 && ferror(context->hidden.stdio.fp)) {
|
|
|
|
SDL_Error(SDL_EFREAD);
|
|
|
|
}
|
|
|
|
return (nread);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
|
|
|
stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
|
2004-01-04 15:18:08 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
size_t nwrote;
|
|
|
|
|
|
|
|
nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
|
|
|
|
if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
|
|
|
|
SDL_Error(SDL_EFWRITE);
|
|
|
|
}
|
|
|
|
return (nwrote);
|
2004-01-04 15:18:08 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
static int SDLCALL
|
|
|
|
stdio_close(SDL_RWops * context)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2007-07-10 05:25:19 +00:00
|
|
|
int status = 0;
|
2006-07-10 21:04:37 +00:00
|
|
|
if (context) {
|
|
|
|
if (context->hidden.stdio.autoclose) {
|
|
|
|
/* WARNING: Check the return value here! */
|
2007-07-10 05:25:19 +00:00
|
|
|
if (fclose(context->hidden.stdio.fp) != 0) {
|
|
|
|
SDL_Error(SDL_EFWRITE);
|
|
|
|
status = -1;
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
SDL_FreeRW(context);
|
|
|
|
}
|
2007-07-10 05:25:19 +00:00
|
|
|
return status;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
#endif /* !HAVE_STDIO_H */
|
|
|
|
|
|
|
|
/* Functions to read/write memory pointers */
|
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static long SDLCALL
|
|
|
|
mem_seek(SDL_RWops * context, long offset, int whence)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
|
|
|
Uint8 *newpos;
|
|
|
|
|
|
|
|
switch (whence) {
|
|
|
|
case RW_SEEK_SET:
|
|
|
|
newpos = context->hidden.mem.base + offset;
|
|
|
|
break;
|
|
|
|
case RW_SEEK_CUR:
|
|
|
|
newpos = context->hidden.mem.here + offset;
|
|
|
|
break;
|
|
|
|
case RW_SEEK_END:
|
|
|
|
newpos = context->hidden.mem.stop + offset;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SDL_SetError("Unknown value for 'whence'");
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (newpos < context->hidden.mem.base) {
|
|
|
|
newpos = context->hidden.mem.base;
|
|
|
|
}
|
|
|
|
if (newpos > context->hidden.mem.stop) {
|
|
|
|
newpos = context->hidden.mem.stop;
|
|
|
|
}
|
|
|
|
context->hidden.mem.here = newpos;
|
2009-09-05 23:37:35 +00:00
|
|
|
return (long)(context->hidden.mem.here - context->hidden.mem.base);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
|
|
|
mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
|
|
|
size_t total_bytes;
|
|
|
|
size_t mem_available;
|
|
|
|
|
|
|
|
total_bytes = (maxnum * size);
|
|
|
|
if ((maxnum <= 0) || (size <= 0)
|
|
|
|
|| ((total_bytes / maxnum) != (size_t) size)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
|
|
|
|
if (total_bytes > mem_available) {
|
|
|
|
total_bytes = mem_available;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
|
|
|
|
context->hidden.mem.here += total_bytes;
|
|
|
|
|
|
|
|
return (total_bytes / size);
|
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
|
|
|
mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
|
|
|
if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
|
|
|
|
num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
|
|
|
|
}
|
|
|
|
SDL_memcpy(context->hidden.mem.here, ptr, num * size);
|
|
|
|
context->hidden.mem.here += num * size;
|
|
|
|
return (num);
|
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2007-07-10 05:25:19 +00:00
|
|
|
static size_t SDLCALL
|
|
|
|
mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
|
|
|
SDL_SetError("Can't write to read-only memory");
|
|
|
|
return (-1);
|
|
|
|
}
|
2008-08-27 15:10:03 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
static int SDLCALL
|
|
|
|
mem_close(SDL_RWops * context)
|
|
|
|
{
|
|
|
|
if (context) {
|
|
|
|
SDL_FreeRW(context);
|
|
|
|
}
|
|
|
|
return (0);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
2006-02-27 04:16:44 +00:00
|
|
|
|
2001-04-26 16:45:43 +00:00
|
|
|
/* Functions to create SDL_RWops structures from various data sources */
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *
|
|
|
|
SDL_RWFromFile(const char *file, const char *mode)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *rwops = NULL;
|
2006-03-04 08:24:35 +00:00
|
|
|
#ifdef HAVE_STDIO_H
|
2006-07-10 21:04:37 +00:00
|
|
|
FILE *fp = NULL;
|
2006-03-04 08:24:35 +00:00
|
|
|
#endif
|
2006-07-10 21:04:37 +00:00
|
|
|
if (!file || !*file || !mode || !*mode) {
|
|
|
|
SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-07-29 16:51:25 -04:00
|
|
|
#if defined(ANDROID)
|
|
|
|
rwops = SDL_AllocRW();
|
|
|
|
if (!rwops)
|
|
|
|
return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
|
|
|
|
if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
|
|
|
|
SDL_FreeRW(rwops);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
rwops->seek = Android_JNI_FileSeek;
|
|
|
|
rwops->read = Android_JNI_FileRead;
|
|
|
|
rwops->write = Android_JNI_FileWrite;
|
|
|
|
rwops->close = Android_JNI_FileClose;
|
|
|
|
|
|
|
|
#elif defined(__WIN32__)
|
2006-07-10 21:04:37 +00:00
|
|
|
rwops = SDL_AllocRW();
|
|
|
|
if (!rwops)
|
|
|
|
return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
|
2011-01-20 18:04:05 -08:00
|
|
|
if (windows_file_open(rwops, file, mode) < 0) {
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_FreeRW(rwops);
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-01-20 18:04:05 -08:00
|
|
|
rwops->seek = windows_file_seek;
|
|
|
|
rwops->read = windows_file_read;
|
|
|
|
rwops->write = windows_file_write;
|
|
|
|
rwops->close = windows_file_close;
|
2006-02-27 04:16:44 +00:00
|
|
|
|
|
|
|
#elif HAVE_STDIO_H
|
Added automated test to Xcode project plus needed changes to SDL_RWFromFile to be OS X bundle aware.
The Mac OS X project has a new target called testsdl which builds the automated test. I looked at using Xcode's native unit test support, but the impedance mismatch between the existing automated test structure and Apple's was more than I could handle.
As such, the testsdl application is a full blown proper OS X application, which means it is a self-contained .app bundle. This immediately revealed some problems from the automated test. The largest problem was the assumption about the current working directory and where to find resources. (I suspect Windows may have a similar problem depending on circumstance.) To open resources, the test was looking in directories relative to the SDL source directory, but this will not work well with self-contained .app bundles and Xcode which can place its built applications almost anywhere. And for real-world situations, this is pretty useless anyway.
So I modified SDL_RWFromFile to do special things on OS X. First, it will look for a file in the .app bundle. If not found, it will fallback and just call fopen as it used to do.
I also had to modify the automated test itself because it had a contrieved test which called fopen directly to do read from an existing FILE pointer. In addition, there was a write test. Since a .app bundle is likely going to be read-only, I added a special case for OS X to write to NSTemporaryDirectory.
I expect these changes should work for both Mac and iPhone OS (which includes iPad).
I will update the iPhone Xcode project next.
Finally, FYI, the X11 automated test seems to be failing. Below is my output.
Pending breakpoint 4 - "-[NSException raise]" resolved
Platform : All tests successful (2)
SDL_RWops : All tests successful (5)
Rect : All tests successful (1)
SDL_Surface : All tests successful (6)
Rendering with cocoa driver : All tests successful (3)
Assert Failed!
Blit output not the same.
Test Case 'Renderer x11'
Test Suite 'Rendering with x11 driver'
Last SDL error ''
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint() to catch errors as they are logged.
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetWindowBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Sat May 8 00:30:34 iMacAL.local testsdl[71586] <Error>: kCGErrorIllegalArgument: CGSBindSurface: Invalid window 0xa150
Rendering with x11 driver : Failed 1 out of 4 testcases!
Rendering with dummy driver : All tests successful (3)
SDL_Audio : All tests successful (1)
Tests run with SDL 1.3.0 revision 1095906
System is running Mac OS X and is little endian
2010-05-08 00:54:22 -07:00
|
|
|
#ifdef __APPLE__
|
|
|
|
fp = SDL_OpenFPFromBundleOrFallback(file, mode);
|
|
|
|
#else
|
|
|
|
fp = fopen(file, mode);
|
|
|
|
#endif
|
|
|
|
if (fp == NULL) {
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_SetError("Couldn't open %s", file);
|
|
|
|
} else {
|
|
|
|
rwops = SDL_RWFromFP(fp, 1);
|
|
|
|
}
|
2006-02-27 04:16:44 +00:00
|
|
|
#else
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_SetError("SDL not compiled with stdio support");
|
2006-02-27 03:48:48 +00:00
|
|
|
#endif /* !HAVE_STDIO_H */
|
2006-02-27 04:16:44 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
return (rwops);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
2006-02-06 08:28:51 +00:00
|
|
|
#ifdef HAVE_STDIO_H
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *
|
2007-07-10 05:29:56 +00:00
|
|
|
SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
|
|
|
SDL_RWops *rwops = NULL;
|
|
|
|
|
2008-08-27 15:10:03 +00:00
|
|
|
#if 0
|
|
|
|
/*#ifdef __NDS__*/
|
|
|
|
/* set it up so we can use stdio file function */
|
|
|
|
fatInitDefault();
|
|
|
|
printf("called fatInitDefault()");
|
|
|
|
#endif /* __NDS__ */
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
rwops = SDL_AllocRW();
|
|
|
|
if (rwops != NULL) {
|
|
|
|
rwops->seek = stdio_seek;
|
|
|
|
rwops->read = stdio_read;
|
|
|
|
rwops->write = stdio_write;
|
|
|
|
rwops->close = stdio_close;
|
|
|
|
rwops->hidden.stdio.fp = fp;
|
|
|
|
rwops->hidden.stdio.autoclose = autoclose;
|
|
|
|
}
|
|
|
|
return (rwops);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
2009-12-15 05:34:58 +00:00
|
|
|
#else
|
|
|
|
SDL_RWops *
|
|
|
|
SDL_RWFromFP(void * fp, SDL_bool autoclose)
|
|
|
|
{
|
|
|
|
SDL_SetError("SDL not compiled with stdio support");
|
|
|
|
return NULL;
|
|
|
|
}
|
2006-02-06 08:28:51 +00:00
|
|
|
#endif /* HAVE_STDIO_H */
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *
|
|
|
|
SDL_RWFromMem(void *mem, int size)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *rwops;
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
rwops = SDL_AllocRW();
|
|
|
|
if (rwops != NULL) {
|
|
|
|
rwops->seek = mem_seek;
|
|
|
|
rwops->read = mem_read;
|
|
|
|
rwops->write = mem_write;
|
|
|
|
rwops->close = mem_close;
|
|
|
|
rwops->hidden.mem.base = (Uint8 *) mem;
|
|
|
|
rwops->hidden.mem.here = rwops->hidden.mem.base;
|
|
|
|
rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
|
|
|
|
}
|
|
|
|
return (rwops);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *
|
|
|
|
SDL_RWFromConstMem(const void *mem, int size)
|
2004-01-04 15:18:08 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *rwops;
|
2004-01-04 15:18:08 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
rwops = SDL_AllocRW();
|
|
|
|
if (rwops != NULL) {
|
|
|
|
rwops->seek = mem_seek;
|
|
|
|
rwops->read = mem_read;
|
|
|
|
rwops->write = mem_writeconst;
|
|
|
|
rwops->close = mem_close;
|
|
|
|
rwops->hidden.mem.base = (Uint8 *) mem;
|
|
|
|
rwops->hidden.mem.here = rwops->hidden.mem.base;
|
|
|
|
rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
|
|
|
|
}
|
|
|
|
return (rwops);
|
2004-01-04 15:18:08 +00:00
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *
|
|
|
|
SDL_AllocRW(void)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWops *area;
|
2001-04-26 16:45:43 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
area = (SDL_RWops *) SDL_malloc(sizeof *area);
|
|
|
|
if (area == NULL) {
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
}
|
|
|
|
return (area);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
void
|
|
|
|
SDL_FreeRW(SDL_RWops * area)
|
2001-04-26 16:45:43 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_free(area);
|
2001-04-26 16:45:43 +00:00
|
|
|
}
|
2006-02-09 09:38:05 +00:00
|
|
|
|
|
|
|
/* Functions for dynamically reading and writing endian-specific values */
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint16
|
|
|
|
SDL_ReadLE16(SDL_RWops * src)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint16 value;
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWread(src, &value, (sizeof value), 1);
|
|
|
|
return (SDL_SwapLE16(value));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
Uint16
|
|
|
|
SDL_ReadBE16(SDL_RWops * src)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint16 value;
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWread(src, &value, (sizeof value), 1);
|
|
|
|
return (SDL_SwapBE16(value));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
Uint32
|
|
|
|
SDL_ReadLE32(SDL_RWops * src)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint32 value;
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWread(src, &value, (sizeof value), 1);
|
|
|
|
return (SDL_SwapLE32(value));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
Uint32
|
|
|
|
SDL_ReadBE32(SDL_RWops * src)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint32 value;
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWread(src, &value, (sizeof value), 1);
|
|
|
|
return (SDL_SwapBE32(value));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
Uint64
|
|
|
|
SDL_ReadLE64(SDL_RWops * src)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint64 value;
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWread(src, &value, (sizeof value), 1);
|
|
|
|
return (SDL_SwapLE64(value));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
Uint64
|
|
|
|
SDL_ReadBE64(SDL_RWops * src)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
Uint64 value;
|
2006-02-09 09:38:05 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_RWread(src, &value, (sizeof value), 1);
|
|
|
|
return (SDL_SwapBE64(value));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
|
|
|
|
2009-09-05 23:37:35 +00:00
|
|
|
size_t
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
value = SDL_SwapLE16(value);
|
|
|
|
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-09-05 23:37:35 +00:00
|
|
|
size_t
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
value = SDL_SwapBE16(value);
|
|
|
|
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-09-05 23:37:35 +00:00
|
|
|
size_t
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
value = SDL_SwapLE32(value);
|
|
|
|
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-09-05 23:37:35 +00:00
|
|
|
size_t
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
value = SDL_SwapBE32(value);
|
|
|
|
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-09-05 23:37:35 +00:00
|
|
|
size_t
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
value = SDL_SwapLE64(value);
|
|
|
|
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-09-05 23:37:35 +00:00
|
|
|
size_t
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
|
2006-02-09 09:38:05 +00:00
|
|
|
{
|
2006-07-10 21:04:37 +00:00
|
|
|
value = SDL_SwapBE64(value);
|
|
|
|
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
2006-02-09 09:38:05 +00:00
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|