all repos — mgba @ 6af9a742bda66c3785cd13f76895558eeac77725

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