all repos — mgba @ 47c4eb97618aee3d04274cda0ffdba0a06d2aae0

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