all repos — mgba @ d67844e95fe95343efc7e45378b4a99859453cad

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