Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

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