Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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 https://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 2.0... */
28
#if defined(SDL_VERSION_ATLEAST)
29
#if SDL_VERSION_ATLEAST(2, 0, 0)
30
#define TARGET_SDL2 1
31
#endif
32
#endif
33
 
34
#if !TARGET_SDL2
35
#ifndef RW_SEEK_SET
36
#define RW_SEEK_SET SEEK_SET
37
#endif
38
#ifndef RW_SEEK_CUR
39
#define RW_SEEK_CUR SEEK_CUR
40
#endif
41
#ifndef RW_SEEK_END
42
#define RW_SEEK_END SEEK_END
43
#endif
44
#endif
45
 
46
#if TARGET_SDL2
47
static Sint64 SDLCALL physfsrwops_size(struct SDL_RWops *rw)
48
{
49
    PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
50
    return (Sint64) PHYSFS_fileLength(handle);
51
} /* physfsrwops_size */
52
#endif
53
 
54
 
55
#if TARGET_SDL2
56
static Sint64 SDLCALL physfsrwops_seek(struct SDL_RWops *rw, Sint64 offset, int whence)
57
#else
58
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
59
#endif
60
{
61
    PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
62
    PHYSFS_sint64 pos = 0;
63
 
64
    if (whence == RW_SEEK_SET)
65
        pos = (PHYSFS_sint64) offset;
66
 
67
    else if (whence == RW_SEEK_CUR)
68
    {
69
        const PHYSFS_sint64 current = PHYSFS_tell(handle);
70
        if (current == -1)
71
        {
72
            SDL_SetError("Can't find position in file: %s",
73
                          PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
74
            return -1;
75
        } /* if */
76
 
77
        if (offset == 0)  /* this is a "tell" call. We're done. */
78
        {
79
            #if TARGET_SDL2
80
            return (Sint64) current;
81
            #else
82
            return (int) current;
83
            #endif
84
        } /* if */
85
 
86
        pos = current + ((PHYSFS_sint64) offset);
87
    } /* else if */
88
 
89
    else if (whence == RW_SEEK_END)
90
    {
91
        const PHYSFS_sint64 len = PHYSFS_fileLength(handle);
92
        if (len == -1)
93
        {
94
            SDL_SetError("Can't find end of file: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
95
            return -1;
96
        } /* if */
97
 
98
        pos = len + ((PHYSFS_sint64) offset);
99
    } /* else if */
100
 
101
    else
102
    {
103
        SDL_SetError("Invalid 'whence' parameter.");
104
        return -1;
105
    } /* else */
106
 
107
    if ( pos < 0 )
108
    {
109
        SDL_SetError("Attempt to seek past start of file.");
110
        return -1;
111
    } /* if */
112
 
113
    if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
114
    {
115
        SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
116
        return -1;
117
    } /* if */
118
 
119
    #if TARGET_SDL2
120
    return (Sint64) pos;
121
    #else
122
    return (int) pos;
123
    #endif
124
} /* physfsrwops_seek */
125
 
126
 
127
#if TARGET_SDL2
128
static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr,
129
                                       size_t size, size_t maxnum)
130
#else
131
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
132
#endif
133
{
134
    PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
135
    const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size);
136
    const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen);
137
    if (rc != ((PHYSFS_sint64) readlen))
138
    {
139
        if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
140
        {
141
            SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
142
 
143
            #if TARGET_SDL2
144
            return 0;
145
            #else
146
            return -1;
147
            #endif
148
        } /* if */
149
    } /* if */
150
 
151
    #if TARGET_SDL2
152
    return (size_t) rc / size;
153
    #else
154
    return (int) rc / size;
155
    #endif
156
} /* physfsrwops_read */
157
 
158
 
159
#if TARGET_SDL2
160
static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr,
161
                                        size_t size, size_t num)
162
#else
163
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
164
#endif
165
{
166
    PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
167
    const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size);
168
    const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen);
169
    if (rc != ((PHYSFS_sint64) writelen))
170
        SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
171
 
172
    #if TARGET_SDL2
173
    return (size_t) rc;
174
    #else
175
    return (int) rc;
176
    #endif
177
} /* physfsrwops_write */
178
 
179
 
180
static int physfsrwops_close(SDL_RWops *rw)
181
{
182
    PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
183
    if (!PHYSFS_close(handle))
184
    {
185
        SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
186
        return -1;
187
    } /* if */
188
 
189
    SDL_FreeRW(rw);
190
    return 0;
191
} /* physfsrwops_close */
192
 
193
 
194
static SDL_RWops *create_rwops(PHYSFS_File *handle)
195
{
196
    SDL_RWops *retval = NULL;
197
 
198
    if (handle == NULL)
199
        SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
200
    else
201
    {
202
        retval = SDL_AllocRW();
203
        if (retval != NULL)
204
        {
205
            #if TARGET_SDL2
206
            retval->size  = physfsrwops_size;
207
            #endif
208
            retval->seek  = physfsrwops_seek;
209
            retval->read  = physfsrwops_read;
210
            retval->write = physfsrwops_write;
211
            retval->close = physfsrwops_close;
212
            retval->hidden.unknown.data1 = handle;
213
        } /* if */
214
    } /* else */
215
 
216
    return retval;
217
} /* create_rwops */
218
 
219
 
220
SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
221
{
222
    SDL_RWops *retval = NULL;
223
    if (handle == NULL)
224
        SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
225
    else
226
        retval = create_rwops(handle);
227
 
228
    return retval;
229
} /* PHYSFSRWOPS_makeRWops */
230
 
231
 
232
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
233
{
234
    return create_rwops(PHYSFS_openRead(fname));
235
} /* PHYSFSRWOPS_openRead */
236
 
237
 
238
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
239
{
240
    return create_rwops(PHYSFS_openWrite(fname));
241
} /* PHYSFSRWOPS_openWrite */
242
 
243
 
244
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
245
{
246
    return create_rwops(PHYSFS_openAppend(fname));
247
} /* PHYSFSRWOPS_openAppend */
248
 
249
 
250
/* end of physfsrwops.c ... */
251