drc: handle upto 64k page size
[pcsx_rearmed.git] / deps / libretro-common / file / nbio / nbio_orbis.c
CommitLineData
3719602c
PC
1/* Copyright (C) 2010-2020 The RetroArch team
2 *
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (nbio_orbis.c).
5 * ---------------------------------------------------------------------------------------
6 *
7 * Permission is hereby granted, free of charge,
8 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23#include <file/nbio.h>
24
25#if defined(ORBIS)
26#include <stdio.h>
27#include <stdlib.h>
28#include <orbisFile.h>
29#include <unistd.h>
30#include <sys/fcntl.h>
31
32struct nbio_orbis_t
33{
34 void* data;
35 size_t progress;
36 size_t len;
37 int fd;
38 unsigned int mode;
39 /*
40 * possible values:
41 * NBIO_READ, NBIO_WRITE - obvious
42 * -1 - currently doing nothing
43 * -2 - the pointer was reallocated since the last operation
44 */
45 signed char op;
46};
47
48static void *nbio_orbis_open(const char * filename, unsigned int mode)
49{
50 static const int o_flags[] = { O_RDONLY, O_RDWR | O_CREAT | O_TRUNC,
51 O_RDWR, O_RDONLY, O_RDWR | O_CREAT | O_TRUNC };
52 void *buf = NULL;
53 struct nbio_orbis_t* handle = NULL;
54 size_t len = 0;
55 int fd = orbisOpen(filename, o_flags[mode], 0644);
56
57 if (fd < 0)
58 return NULL;
59 handle = (struct nbio_orbis_t*)malloc(sizeof(struct nbio_orbis_t));
60
61 if (!handle)
62 goto error;
63
64 handle->fd = fd;
65
66 switch (mode)
67 {
68 case NBIO_WRITE:
69 case BIO_WRITE:
70 break;
71 default:
72 len=orbisLseek(handle->fd, 0, SEEK_END);
73 orbisLseek(handle->fd, 0, SEEK_SET);
74 break;
75 }
76
77 handle->mode = mode;
78
79 if (len)
80 buf = malloc(len);
81
82 if (len && !buf)
83 goto error;
84
85 handle->data = buf;
86 handle->len = len;
87 handle->progress = handle->len;
88 handle->op = -2;
89
90 return handle;
91
92error:
93 if (handle)
94 free(handle);
95 orbisClose(fd);
96 return NULL;
97}
98
99static void nbio_orbis_begin_read(void *data)
100{
101
102 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
103 if (!handle)
104 return;
105
106 if (handle->op >= 0)
107 return;
108
109 orbisLseek(handle->fd, 0, SEEK_SET);
110
111 handle->op = NBIO_READ;
112 handle->progress = 0;
113}
114
115static void nbio_orbis_begin_write(void *data)
116{
117 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
118 if (!handle)
119 return;
120
121 if (handle->op >= 0)
122 return;
123
124 orbisLseek(handle->fd, 0, SEEK_SET);
125 handle->op = NBIO_WRITE;
126 handle->progress = 0;
127}
128
129static bool nbio_orbis_iterate(void *data)
130{
131 size_t amount = 65536;
132 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
133
134 if (!handle)
135 return false;
136
137 if (amount > handle->len - handle->progress)
138 amount = handle->len - handle->progress;
139
140 switch (handle->op)
141 {
142 case NBIO_READ:
143 if (handle->mode == BIO_READ)
144 amount = handle->len;
145 break;
146 case NBIO_WRITE:
147 if (handle->mode == BIO_WRITE)
148 {
149 size_t written = 0;
150 amount = handle->len;
151 written = orbisWrite(handle->fd, (char*)handle->data, amount);
152
153 if (written != amount)
154 return false;
155 }
156 break;
157 }
158
159 handle->progress += amount;
160
161 if (handle->progress == handle->len)
162 handle->op = -1;
163 return (handle->op < 0);
164}
165
166static void nbio_orbis_resize(void *data, size_t len)
167{
168 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
169 if (!handle)
170 return;
171
172 if (handle->op >= 0)
173 return;
174 if (len < handle->len)
175 return;
176
177 handle->len = len;
178 handle->data = realloc(handle->data, handle->len);
179 handle->op = -1;
180 handle->progress = handle->len;
181}
182
183static void *nbio_orbis_get_ptr(void *data, size_t* len)
184{
185 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
186 if (!handle)
187 return NULL;
188 if (len)
189 *len = handle->len;
190 if (handle->op == -1)
191 return handle->data;
192 return NULL;
193}
194
195static void nbio_orbis_cancel(void *data)
196{
197 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
198 if (!handle)
199 return;
200 handle->op = -1;
201 handle->progress = handle->len;
202}
203
204static void nbio_orbis_free(void *data)
205{
206 struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
207 if (!handle)
208 return;
209
210 if (handle->op >= 0)
211 return;
212
213 orbisClose(handle->fd);
214 free(handle->data);
215
216 handle->data = NULL;
217 free(handle);
218}
219
220nbio_intf_t nbio_orbis = {
221 nbio_orbis_open,
222 nbio_orbis_begin_read,
223 nbio_orbis_begin_write,
224 nbio_orbis_iterate,
225 nbio_orbis_resize,
226 nbio_orbis_get_ptr,
227 nbio_orbis_cancel,
228 nbio_orbis_free,
229 "nbio_orbis",
230};
231#endif