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