all repos — mgba @ 2f5fb2265992581712525dad2b47fcad0a5c0372

mGBA Game Boy Advance Emulator

src/platform/psp2/sce-vfs.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba-util/platform/psp2/sce-vfs.h>
  7
  8#include <psp2/io/dirent.h>
  9
 10#include <mgba-util/vfs.h>
 11#include <mgba-util/memory.h>
 12
 13#ifndef SCE_CST_SIZE
 14#define SCE_CST_SIZE 0x0004
 15#endif
 16
 17struct VFileSce {
 18	struct VFile d;
 19
 20	SceUID fd;
 21};
 22
 23struct VDirEntrySce {
 24	struct VDirEntry d;
 25	SceIoDirent ent;
 26};
 27
 28struct VDirSce {
 29	struct VDir d;
 30	struct VDirEntrySce de;
 31	SceUID fd;
 32	char* path;
 33};
 34
 35static bool _vfsceClose(struct VFile* vf);
 36static off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence);
 37static ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size);
 38static ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size);
 39static void* _vfsceMap(struct VFile* vf, size_t size, int flags);
 40static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size);
 41static void _vfsceTruncate(struct VFile* vf, size_t size);
 42static ssize_t _vfsceSize(struct VFile* vf);
 43static bool _vfsceSync(struct VFile* vf, void* memory, size_t size);
 44
 45static bool _vdsceClose(struct VDir* vd);
 46static void _vdsceRewind(struct VDir* vd);
 47static struct VDirEntry* _vdsceListNext(struct VDir* vd);
 48static struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode);
 49static struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path);
 50static bool _vdsceDeleteFile(struct VDir* vd, const char* path);
 51
 52static const char* _vdesceName(struct VDirEntry* vde);
 53static enum VFSType _vdesceType(struct VDirEntry* vde);
 54
 55static bool _vdlsceClose(struct VDir* vd);
 56static void _vdlsceRewind(struct VDir* vd);
 57static struct VDirEntry* _vdlsceListNext(struct VDir* vd);
 58static struct VFile* _vdlsceOpenFile(struct VDir* vd, const char* path, int mode);
 59static struct VDir* _vdlsceOpenDir(struct VDir* vd, const char* path);
 60static bool _vdlsceDeleteFile(struct VDir* vd, const char* path);
 61
 62static const char* _vdlesceName(struct VDirEntry* vde);
 63static enum VFSType _vdlesceType(struct VDirEntry* vde);
 64
 65struct VFile* VFileOpenSce(const char* path, int flags, SceMode mode) {
 66	struct VFileSce* vfsce = malloc(sizeof(struct VFileSce));
 67	if (!vfsce) {
 68		return 0;
 69	}
 70
 71	vfsce->fd = sceIoOpen(path, flags, mode);
 72	if (vfsce->fd < 0) {
 73		free(vfsce);
 74		return 0;
 75	}
 76
 77	vfsce->d.close = _vfsceClose;
 78	vfsce->d.seek = _vfsceSeek;
 79	vfsce->d.read = _vfsceRead;
 80	vfsce->d.readline = VFileReadline;
 81	vfsce->d.write = _vfsceWrite;
 82	vfsce->d.map = _vfsceMap;
 83	vfsce->d.unmap = _vfsceUnmap;
 84	vfsce->d.truncate = _vfsceTruncate;
 85	vfsce->d.size = _vfsceSize;
 86	vfsce->d.sync = _vfsceSync;
 87
 88	return &vfsce->d;
 89}
 90
 91bool _vfsceClose(struct VFile* vf) {
 92	struct VFileSce* vfsce = (struct VFileSce*) vf;
 93	sceIoSyncByFd(vfsce->fd);
 94	return sceIoClose(vfsce->fd) >= 0;
 95}
 96
 97off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence) {
 98	struct VFileSce* vfsce = (struct VFileSce*) vf;
 99	return sceIoLseek(vfsce->fd, offset, whence);
100}
101
102ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size) {
103	struct VFileSce* vfsce = (struct VFileSce*) vf;
104	return sceIoRead(vfsce->fd, buffer, size);
105}
106
107ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size) {
108	struct VFileSce* vfsce = (struct VFileSce*) vf;
109	return sceIoWrite(vfsce->fd, buffer, size);
110}
111
112static void* _vfsceMap(struct VFile* vf, size_t size, int flags) {
113	struct VFileSce* vfsce = (struct VFileSce*) vf;
114	UNUSED(flags);
115	void* buffer = anonymousMemoryMap(size);
116	if (buffer) {
117		SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
118		sceIoLseek(vfsce->fd, 0, SEEK_SET);
119		sceIoRead(vfsce->fd, buffer, size);
120		sceIoLseek(vfsce->fd, cur, SEEK_SET);
121	}
122	return buffer;
123}
124
125static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) {
126	struct VFileSce* vfsce = (struct VFileSce*) vf;
127	SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
128	sceIoLseek(vfsce->fd, 0, SEEK_SET);
129	sceIoWrite(vfsce->fd, memory, size);
130	sceIoLseek(vfsce->fd, cur, SEEK_SET);
131	sceIoSyncByFd(vfsce->fd);
132	mappedMemoryFree(memory, size);
133}
134
135static void _vfsceTruncate(struct VFile* vf, size_t size) {
136	struct VFileSce* vfsce = (struct VFileSce*) vf;
137	SceIoStat stat = { .st_size = size };
138	sceIoChstatByFd(vfsce->fd, &stat, SCE_CST_SIZE);
139}
140
141ssize_t _vfsceSize(struct VFile* vf) {
142	struct VFileSce* vfsce = (struct VFileSce*) vf;
143	SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
144	SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
145	sceIoLseek(vfsce->fd, cur, SEEK_SET);
146	return end;
147}
148
149bool _vfsceSync(struct VFile* vf, void* buffer, size_t size) {
150	struct VFileSce* vfsce = (struct VFileSce*) vf;
151	if (buffer && size) {
152		SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
153		sceIoLseek(vfsce->fd, 0, SEEK_SET);
154		int res = sceIoWrite(vfsce->fd, buffer, size);
155		sceIoLseek(vfsce->fd, cur, SEEK_SET);
156		return res == size;
157	}
158	return sceIoSyncByFd(vfsce->fd) >= 0;
159}
160
161struct VDir* VDirOpen(const char* path) {
162	if (!path || !path[0]) {
163		return VDeviceList();
164	}
165
166	SceUID dir = sceIoDopen(path);
167	if (dir < 0) {
168		return 0;
169	}
170
171	struct VDirSce* vd = malloc(sizeof(struct VDirSce));
172	vd->fd = dir;
173	vd->d.close = _vdsceClose;
174	vd->d.rewind = _vdsceRewind;
175	vd->d.listNext = _vdsceListNext;
176	vd->d.openFile = _vdsceOpenFile;
177	vd->d.openDir = _vdsceOpenDir;
178	vd->d.deleteFile = _vdsceDeleteFile;
179	vd->path = strdup(path);
180
181	vd->de.d.name = _vdesceName;
182	vd->de.d.type = _vdesceType;
183
184	return &vd->d;
185}
186
187bool _vdsceClose(struct VDir* vd) {
188	struct VDirSce* vdsce = (struct VDirSce*) vd;
189	if (sceIoDclose(vdsce->fd) < 0) {
190		return false;
191	}
192	free(vdsce->path);
193	free(vdsce);
194	return true;
195}
196
197void _vdsceRewind(struct VDir* vd) {
198	struct VDirSce* vdsce = (struct VDirSce*) vd;
199	sceIoDclose(vdsce->fd);
200	vdsce->fd = sceIoDopen(vdsce->path);
201}
202
203struct VDirEntry* _vdsceListNext(struct VDir* vd) {
204	struct VDirSce* vdsce = (struct VDirSce*) vd;
205	if (sceIoDread(vdsce->fd, &vdsce->de.ent) <= 0) {
206		return 0;
207	}
208	return &vdsce->de.d;
209}
210
211struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode) {
212	struct VDirSce* vdsce = (struct VDirSce*) vd;
213	if (!path) {
214		return 0;
215	}
216	const char* dir = vdsce->path;
217	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
218	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
219
220	struct VFile* file = VFileOpen(combined, mode);
221	free(combined);
222	return file;
223}
224
225struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path) {
226	struct VDirSce* vdsce = (struct VDirSce*) vd;
227	if (!path) {
228		return 0;
229	}
230	const char* dir = vdsce->path;
231	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
232	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
233
234	struct VDir* vd2 = VDirOpen(combined);
235	if (!vd2) {
236		vd2 = VDirOpenArchive(combined);
237	}
238	free(combined);
239	return vd2;
240}
241
242bool _vdsceDeleteFile(struct VDir* vd, const char* path) {
243	struct VDirSce* vdsce = (struct VDirSce*) vd;
244	if (!path) {
245		return 0;
246	}
247	const char* dir = vdsce->path;
248	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
249	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
250
251	bool ret = sceIoRemove(combined) >= 0;
252	free(combined);
253	return ret;
254}
255
256static const char* _vdesceName(struct VDirEntry* vde) {
257	struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
258	return vdesce->ent.d_name;
259}
260
261static enum VFSType _vdesceType(struct VDirEntry* vde) {
262	struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
263	if (SCE_S_ISDIR(vdesce->ent.d_stat.st_mode)) {
264		return VFS_DIRECTORY;
265	}
266	return VFS_FILE;
267}
268
269struct VDirEntrySceDevList {
270	struct VDirEntry d;
271	ssize_t index;
272	const char* name;
273};
274
275struct VDirSceDevList {
276	struct VDir d;
277	struct VDirEntrySceDevList vde;
278};
279
280static const char* _devs[] = {
281	"ux0:",
282	"ur0:",
283	"uma0:"
284};
285
286struct VDir* VDeviceList() {
287	struct VDirSceDevList* vd = malloc(sizeof(struct VDirSceDevList));
288	if (!vd) {
289		return 0;
290	}
291
292	vd->d.close = _vdlsceClose;
293	vd->d.rewind = _vdlsceRewind;
294	vd->d.listNext = _vdlsceListNext;
295	vd->d.openFile = _vdlsceOpenFile;
296	vd->d.openDir = _vdlsceOpenDir;
297	vd->d.deleteFile = _vdlsceDeleteFile;
298
299	vd->vde.d.name = _vdlesceName;
300	vd->vde.d.type = _vdlesceType;
301	vd->vde.index = -1;
302	vd->vde.name = 0;
303
304	return &vd->d;
305}
306
307static bool _vdlsceClose(struct VDir* vd) {
308	struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd;
309	free(vdl);
310	return true;
311}
312
313static void _vdlsceRewind(struct VDir* vd) {
314	struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd;
315	vdl->vde.name = NULL;
316	vdl->vde.index = -1;
317}
318
319static struct VDirEntry* _vdlsceListNext(struct VDir* vd) {
320	struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd;
321	while (vdl->vde.index < 3) {
322		++vdl->vde.index;
323		vdl->vde.name = _devs[vdl->vde.index];
324		SceUID dir = sceIoDopen(vdl->vde.name);
325		if (dir < 0) {
326			continue;
327		}
328		sceIoDclose(dir);
329		return &vdl->vde.d;
330	}
331	return 0;
332}
333
334static struct VFile* _vdlsceOpenFile(struct VDir* vd, const char* path, int mode) {
335	UNUSED(vd);
336	UNUSED(path);
337	UNUSED(mode);
338	return NULL;
339}
340
341static struct VDir* _vdlsceOpenDir(struct VDir* vd, const char* path) {
342	UNUSED(vd);
343	return VDirOpen(path);
344}
345
346static bool _vdlsceDeleteFile(struct VDir* vd, const char* path) {
347	UNUSED(vd);
348	UNUSED(path);
349	return false;
350}
351
352static const char* _vdlesceName(struct VDirEntry* vde) {
353	struct VDirEntrySceDevList* vdle = (struct VDirEntrySceDevList*) vde;
354	return vdle->name;
355}
356
357static enum VFSType _vdlesceType(struct VDirEntry* vde) {
358	UNUSED(vde);
359	return VFS_DIRECTORY;
360}
361
362bool VDirCreate(const char* path) {
363	// TODO: Verify vitasdk explanation of return values
364	sceIoMkdir(path, 0777);
365	return true;
366}