all repos — mgba @ 4c38f769565e8ddd7d3a8eef1a41975206c129a0

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 "sce-vfs.h"
  7
  8#include <psp2/io/dirent.h>
  9
 10#include "util/vfs.h"
 11#include "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	// TODO
124}
125
126ssize_t _vfsceSize(struct VFile* vf) {
127	struct VFileSce* vfsce = (struct VFileSce*) vf;
128	SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
129	SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
130	sceIoLseek(vfsce->fd, cur, SEEK_SET);
131	return end;
132}
133
134bool _vfsceSync(struct VFile* vf, const void* buffer, size_t size) {
135	struct VFileSce* vfsce = (struct VFileSce*) vf;
136	if (buffer && size) {
137		SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
138		sceIoLseek(vfsce->fd, 0, SEEK_SET);
139		sceIoWrite(vfsce->fd, buffer, size);
140		sceIoLseek(vfsce->fd, cur, SEEK_SET);
141	}
142	return sceIoSyncByFd(vfsce->fd) >= 0;
143}
144
145struct VDir* VDirOpen(const char* path) {
146	SceUID dir = sceIoDopen(path);
147	if (dir < 0) {
148		return 0;
149	}
150
151	struct VDirSce* vd = malloc(sizeof(struct VDirSce));
152	vd->fd = dir;
153	vd->d.close = _vdsceClose;
154	vd->d.rewind = _vdsceRewind;
155	vd->d.listNext = _vdsceListNext;
156	vd->d.openFile = _vdsceOpenFile;
157	vd->d.openDir = _vdsceOpenDir;
158	vd->d.deleteFile = _vdsceDeleteFile;
159	vd->path = strdup(path);
160
161	vd->de.d.name = _vdesceName;
162	vd->de.d.type = _vdesceType;
163
164	return &vd->d;
165}
166
167bool _vdsceClose(struct VDir* vd) {
168	struct VDirSce* vdsce = (struct VDirSce*) vd;
169	if (sceIoDclose(vdsce->fd) < 0) {
170		return false;
171	}
172	free(vdsce->path);
173	free(vdsce);
174	return true;
175}
176
177void _vdsceRewind(struct VDir* vd) {
178	struct VDirSce* vdsce = (struct VDirSce*) vd;
179	sceIoDclose(vdsce->fd);
180	vdsce->fd = sceIoDopen(vdsce->path);
181}
182
183struct VDirEntry* _vdsceListNext(struct VDir* vd) {
184	struct VDirSce* vdsce = (struct VDirSce*) vd;
185	if (sceIoDread(vdsce->fd, &vdsce->de.ent) <= 0) {
186		return 0;
187	}
188	return &vdsce->de.d;
189}
190
191struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode) {
192	struct VDirSce* vdsce = (struct VDirSce*) vd;
193	if (!path) {
194		return 0;
195	}
196	const char* dir = vdsce->path;
197	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
198	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
199
200	struct VFile* file = VFileOpen(combined, mode);
201	free(combined);
202	return file;
203}
204
205struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path) {
206	struct VDirSce* vdsce = (struct VDirSce*) vd;
207	if (!path) {
208		return 0;
209	}
210	const char* dir = vdsce->path;
211	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
212	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
213
214	struct VDir* vd2 = VDirOpen(combined);
215	if (!vd2) {
216		vd2 = VDirOpenArchive(combined);
217	}
218	free(combined);
219	return vd2;
220}
221
222bool _vdsceDeleteFile(struct VDir* vd, const char* path) {
223	struct VDirSce* vdsce = (struct VDirSce*) vd;
224	if (!path) {
225		return 0;
226	}
227	const char* dir = vdsce->path;
228	char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
229	sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
230
231	bool ret = sceIoRemove(combined) >= 0;
232	free(combined);
233	return ret;
234}
235
236static const char* _vdesceName(struct VDirEntry* vde) {
237	struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
238	return vdesce->ent.d_name;
239}
240
241static enum VFSType _vdesceType(struct VDirEntry* vde) {
242	struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
243	if (SCE_S_ISDIR(vdesce->ent.d_stat.st_mode)) {
244		return VFS_DIRECTORY;
245	}
246	return VFS_FILE;
247}