all repos — mgba @ 715efc63bd7178fc5a0058588b81de03fe74bc6d

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