all repos — mgba @ bf0081e9b4c2c3b3faef6bfbfd93ac46066684e5

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
 13struct VFileSce {
 14	struct VFile d;
 15
 16	SceUID fd;
 17};
 18
 19struct VDirEntrySce {
 20	struct VDirEntry d;
 21	SceIoDirent ent;
 22};
 23
 24struct VDirSce {
 25	struct VDir d;
 26	struct VDirEntrySce de;
 27	SceUID fd;
 28	char* path;
 29};
 30
 31static bool _vfsceClose(struct VFile* vf);
 32static off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence);
 33static ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size);
 34static ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size);
 35static void* _vfsceMap(struct VFile* vf, size_t size, int flags);
 36static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size);
 37static void _vfsceTruncate(struct VFile* vf, size_t size);
 38static ssize_t _vfsceSize(struct VFile* vf);
 39static bool _vfsceSync(struct VFile* vf, const void* memory, size_t size);
 40
 41static bool _vdsceClose(struct VDir* vd);
 42static void _vdsceRewind(struct VDir* vd);
 43static struct VDirEntry* _vdsceListNext(struct VDir* vd);
 44static struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode);
 45static struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path);
 46static bool _vdsceDeleteFile(struct VDir* vd, const char* path);
 47
 48static const char* _vdesceName(struct VDirEntry* vde);
 49static enum VFSType _vdesceType(struct VDirEntry* vde);
 50
 51struct VFile* VFileOpenSce(const char* path, int flags, SceMode mode) {
 52	struct VFileSce* vfsce = malloc(sizeof(struct VFileSce));
 53	if (!vfsce) {
 54		return 0;
 55	}
 56
 57	vfsce->fd = sceIoOpen(path, flags, mode);
 58	if (vfsce->fd < 0) {
 59		free(vfsce);
 60		return 0;
 61	}
 62
 63	vfsce->d.close = _vfsceClose;
 64	vfsce->d.seek = _vfsceSeek;
 65	vfsce->d.read = _vfsceRead;
 66	vfsce->d.readline = VFileReadline;
 67	vfsce->d.write = _vfsceWrite;
 68	vfsce->d.map = _vfsceMap;
 69	vfsce->d.unmap = _vfsceUnmap;
 70	vfsce->d.truncate = _vfsceTruncate;
 71	vfsce->d.size = _vfsceSize;
 72	vfsce->d.sync = _vfsceSync;
 73
 74	return &vfsce->d;
 75}
 76
 77bool _vfsceClose(struct VFile* vf) {
 78	struct VFileSce* vfsce = (struct VFileSce*) vf;
 79	sceIoSyncByFd(vfsce->fd);
 80	return sceIoClose(vfsce->fd) >= 0;
 81}
 82
 83off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence) {
 84	struct VFileSce* vfsce = (struct VFileSce*) vf;
 85	return sceIoLseek(vfsce->fd, offset, whence);
 86}
 87
 88ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size) {
 89	struct VFileSce* vfsce = (struct VFileSce*) vf;
 90	return sceIoRead(vfsce->fd, buffer, size);
 91}
 92
 93ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size) {
 94	struct VFileSce* vfsce = (struct VFileSce*) vf;
 95	return sceIoWrite(vfsce->fd, buffer, size);
 96}
 97
 98static void* _vfsceMap(struct VFile* vf, size_t size, int flags) {
 99	struct VFileSce* vfsce = (struct VFileSce*) vf;
100	UNUSED(flags);
101	void* buffer = anonymousMemoryMap(size);
102	if (buffer) {
103		SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
104		sceIoLseek(vfsce->fd, 0, SEEK_SET);
105		sceIoRead(vfsce->fd, buffer, size);
106		sceIoLseek(vfsce->fd, cur, SEEK_SET);
107	}
108	return buffer;
109}
110
111static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) {
112	struct VFileSce* vfsce = (struct VFileSce*) vf;
113	SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
114	sceIoLseek(vfsce->fd, 0, SEEK_SET);
115	sceIoWrite(vfsce->fd, memory, size);
116	sceIoLseek(vfsce->fd, cur, SEEK_SET);
117	sceIoSyncByFd(vfsce->fd);
118	mappedMemoryFree(memory, size);
119}
120
121static void _vfsceTruncate(struct VFile* vf, size_t size) {
122	struct VFileSce* vfsce = (struct VFileSce*) vf;
123	SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
124	SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
125	if (end < size) {
126		uint8_t buffer[2048] = {};
127		size_t write = size - end;
128		while (write >= sizeof(buffer)) {
129			sceIoWrite(vfsce->fd, buffer, sizeof(buffer));
130			write -= sizeof(buffer);
131		}
132		if (write) {
133			sceIoWrite(vfsce->fd, buffer, write);
134		}
135	} // TODO: Else
136	sceIoLseek(vfsce->fd, cur, SEEK_SET);
137}
138
139ssize_t _vfsceSize(struct VFile* vf) {
140	struct VFileSce* vfsce = (struct VFileSce*) vf;
141	SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
142	SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
143	sceIoLseek(vfsce->fd, cur, SEEK_SET);
144	return end;
145}
146
147bool _vfsceSync(struct VFile* vf, const void* buffer, size_t size) {
148	struct VFileSce* vfsce = (struct VFileSce*) vf;
149	if (buffer && size) {
150		SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
151		sceIoLseek(vfsce->fd, 0, SEEK_SET);
152		sceIoWrite(vfsce->fd, buffer, size);
153		sceIoLseek(vfsce->fd, cur, SEEK_SET);
154	}
155	return sceIoSyncByFd(vfsce->fd) >= 0;
156}
157
158struct VDir* VDirOpen(const char* path) {
159	SceUID dir = sceIoDopen(path);
160	if (dir < 0) {
161		return 0;
162	}
163
164	struct VDirSce* vd = malloc(sizeof(struct VDirSce));
165	vd->fd = dir;
166	vd->d.close = _vdsceClose;
167	vd->d.rewind = _vdsceRewind;
168	vd->d.listNext = _vdsceListNext;
169	vd->d.openFile = _vdsceOpenFile;
170	vd->d.openDir = _vdsceOpenDir;
171	vd->d.deleteFile = _vdsceDeleteFile;
172	vd->path = strdup(path);
173
174	vd->de.d.name = _vdesceName;
175	vd->de.d.type = _vdesceType;
176
177	return &vd->d;
178}
179
180bool _vdsceClose(struct VDir* vd) {
181	struct VDirSce* vdsce = (struct VDirSce*) vd;
182	if (sceIoDclose(vdsce->fd) < 0) {
183		return false;
184	}
185	free(vdsce->path);
186	free(vdsce);
187	return true;
188}
189
190void _vdsceRewind(struct VDir* vd) {
191	struct VDirSce* vdsce = (struct VDirSce*) vd;
192	sceIoDclose(vdsce->fd);
193	vdsce->fd = sceIoDopen(vdsce->path);
194}
195
196struct VDirEntry* _vdsceListNext(struct VDir* vd) {
197	struct VDirSce* vdsce = (struct VDirSce*) vd;
198	if (sceIoDread(vdsce->fd, &vdsce->de.ent) <= 0) {
199		return 0;
200	}
201	return &vdsce->de.d;
202}
203
204struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode) {
205	struct VDirSce* vdsce = (struct VDirSce*) vd;
206	if (!path) {
207		return 0;
208	}
209	const char* dir = vdsce->path;
210	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
211	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
212
213	struct VFile* file = VFileOpen(combined, mode);
214	free(combined);
215	return file;
216}
217
218struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path) {
219	struct VDirSce* vdsce = (struct VDirSce*) vd;
220	if (!path) {
221		return 0;
222	}
223	const char* dir = vdsce->path;
224	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
225	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
226
227	struct VDir* vd2 = VDirOpen(combined);
228	if (!vd2) {
229		vd2 = VDirOpenArchive(combined);
230	}
231	free(combined);
232	return vd2;
233}
234
235bool _vdsceDeleteFile(struct VDir* vd, const char* path) {
236	struct VDirSce* vdsce = (struct VDirSce*) vd;
237	if (!path) {
238		return 0;
239	}
240	const char* dir = vdsce->path;
241	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
242	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
243
244	bool ret = sceIoRemove(combined) >= 0;
245	free(combined);
246	return ret;
247}
248
249static const char* _vdesceName(struct VDirEntry* vde) {
250	struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
251	return vdesce->ent.d_name;
252}
253
254static enum VFSType _vdesceType(struct VDirEntry* vde) {
255	struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
256	if (SCE_S_ISDIR(vdesce->ent.d_stat.st_mode)) {
257		return VFS_DIRECTORY;
258	}
259	return VFS_FILE;
260}