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 |