|
1 /* |
|
2 * This code provides a glue layer between PhysicsFS and Simple Directmedia |
|
3 * Layer's (SDL) RWops i/o abstraction. |
|
4 * |
|
5 * License: this code is public domain. I make no warranty that it is useful, |
|
6 * correct, harmless, or environmentally safe. |
|
7 * |
|
8 * This particular file may be used however you like, including copying it |
|
9 * verbatim into a closed-source project, exploiting it commercially, and |
|
10 * removing any trace of my name from the source (although I hope you won't |
|
11 * do that). I welcome enhancements and corrections to this file, but I do |
|
12 * not require you to send me patches if you make changes. This code has |
|
13 * NO WARRANTY. |
|
14 * |
|
15 * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license. |
|
16 * Please see LICENSE.txt in the root of the source tree. |
|
17 * |
|
18 * SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS. |
|
19 * You can get SDL at http://www.libsdl.org/ |
|
20 * |
|
21 * This file was written by Ryan C. Gordon. (icculus@icculus.org). |
|
22 */ |
|
23 |
|
24 #include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */ |
|
25 #include "physfsrwops.h" |
|
26 |
|
27 /* SDL's RWOPS interface changed a little in SDL 1.3... */ |
|
28 #if defined(SDL_VERSION_ATLEAST) |
|
29 #if SDL_VERSION_ATLEAST(1, 3, 0) |
|
30 #define TARGET_SDL13 1 |
|
31 #endif |
|
32 #endif |
|
33 |
|
34 #if TARGET_SDL13 |
|
35 static long SDLCALL physfsrwops_seek(struct SDL_RWops *rw, long offset, int whence) |
|
36 #else |
|
37 static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence) |
|
38 #endif |
|
39 { |
|
40 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1; |
|
41 PHYSFS_sint64 pos = 0; |
|
42 |
|
43 if (whence == SEEK_SET) |
|
44 pos = (PHYSFS_sint64) offset; |
|
45 |
|
46 else if (whence == SEEK_CUR) |
|
47 { |
|
48 const PHYSFS_sint64 current = PHYSFS_tell(handle); |
|
49 if (current == -1) |
|
50 { |
|
51 SDL_SetError("Can't find position in file: %s", |
|
52 PHYSFS_getLastError()); |
|
53 return -1; |
|
54 } /* if */ |
|
55 |
|
56 if (offset == 0) /* this is a "tell" call. We're done. */ |
|
57 { |
|
58 #if TARGET_SDL13 |
|
59 return (long) current; |
|
60 #else |
|
61 return (int) current; |
|
62 #endif |
|
63 } /* if */ |
|
64 |
|
65 pos = current + ((PHYSFS_sint64) offset); |
|
66 } /* else if */ |
|
67 |
|
68 else if (whence == SEEK_END) |
|
69 { |
|
70 const PHYSFS_sint64 len = PHYSFS_fileLength(handle); |
|
71 if (len == -1) |
|
72 { |
|
73 SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError()); |
|
74 return -1; |
|
75 } /* if */ |
|
76 |
|
77 pos = len + ((PHYSFS_sint64) offset); |
|
78 } /* else if */ |
|
79 |
|
80 else |
|
81 { |
|
82 SDL_SetError("Invalid 'whence' parameter."); |
|
83 return -1; |
|
84 } /* else */ |
|
85 |
|
86 if ( pos < 0 ) |
|
87 { |
|
88 SDL_SetError("Attempt to seek past start of file."); |
|
89 return -1; |
|
90 } /* if */ |
|
91 |
|
92 if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos)) |
|
93 { |
|
94 SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); |
|
95 return -1; |
|
96 } /* if */ |
|
97 |
|
98 #if TARGET_SDL13 |
|
99 return (long) pos; |
|
100 #else |
|
101 return (int) pos; |
|
102 #endif |
|
103 } /* physfsrwops_seek */ |
|
104 |
|
105 |
|
106 #if TARGET_SDL13 |
|
107 static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr, |
|
108 size_t size, size_t maxnum) |
|
109 #else |
|
110 static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum) |
|
111 #endif |
|
112 { |
|
113 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1; |
|
114 const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size); |
|
115 const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen); |
|
116 if (rc != ((PHYSFS_sint64) readlen)) |
|
117 { |
|
118 if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */ |
|
119 SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); |
|
120 } /* if */ |
|
121 |
|
122 #if TARGET_SDL13 |
|
123 return (size_t) rc; |
|
124 #else |
|
125 return (int) rc; |
|
126 #endif |
|
127 } /* physfsrwops_read */ |
|
128 |
|
129 |
|
130 #if TARGET_SDL13 |
|
131 static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr, |
|
132 size_t size, size_t num) |
|
133 #else |
|
134 static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num) |
|
135 #endif |
|
136 { |
|
137 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1; |
|
138 const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size); |
|
139 const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen); |
|
140 if (rc != ((PHYSFS_sint64) writelen)) |
|
141 SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); |
|
142 |
|
143 #if TARGET_SDL13 |
|
144 return (size_t) rc; |
|
145 #else |
|
146 return (int) rc; |
|
147 #endif |
|
148 } /* physfsrwops_write */ |
|
149 |
|
150 |
|
151 static int physfsrwops_close(SDL_RWops *rw) |
|
152 { |
|
153 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1; |
|
154 if (!PHYSFS_close(handle)) |
|
155 { |
|
156 SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); |
|
157 return -1; |
|
158 } /* if */ |
|
159 |
|
160 SDL_FreeRW(rw); |
|
161 return 0; |
|
162 } /* physfsrwops_close */ |
|
163 |
|
164 |
|
165 static SDL_RWops *create_rwops(PHYSFS_File *handle) |
|
166 { |
|
167 SDL_RWops *retval = NULL; |
|
168 |
|
169 if (handle == NULL) |
|
170 SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); |
|
171 else |
|
172 { |
|
173 retval = SDL_AllocRW(); |
|
174 if (retval != NULL) |
|
175 { |
|
176 retval->seek = physfsrwops_seek; |
|
177 retval->read = physfsrwops_read; |
|
178 retval->write = physfsrwops_write; |
|
179 retval->close = physfsrwops_close; |
|
180 retval->hidden.unknown.data1 = handle; |
|
181 } /* if */ |
|
182 } /* else */ |
|
183 |
|
184 return retval; |
|
185 } /* create_rwops */ |
|
186 |
|
187 |
|
188 SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle) |
|
189 { |
|
190 SDL_RWops *retval = NULL; |
|
191 if (handle == NULL) |
|
192 SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops()."); |
|
193 else |
|
194 retval = create_rwops(handle); |
|
195 |
|
196 return retval; |
|
197 } /* PHYSFSRWOPS_makeRWops */ |
|
198 |
|
199 |
|
200 SDL_RWops *PHYSFSRWOPS_openRead(const char *fname) |
|
201 { |
|
202 return create_rwops(PHYSFS_openRead(fname)); |
|
203 } /* PHYSFSRWOPS_openRead */ |
|
204 |
|
205 |
|
206 SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname) |
|
207 { |
|
208 return create_rwops(PHYSFS_openWrite(fname)); |
|
209 } /* PHYSFSRWOPS_openWrite */ |
|
210 |
|
211 |
|
212 SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname) |
|
213 { |
|
214 return create_rwops(PHYSFS_openAppend(fname)); |
|
215 } /* PHYSFSRWOPS_openAppend */ |
|
216 |
|
217 |
|
218 /* end of physfsrwops.c ... */ |
|
219 |