PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
subfile.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <errno.h>
12#include <irx_imports.h>
13#include <loadcore.h>
14
15#define MODNAME "subfile_driver"
16IRX_ID(MODNAME, 2, 1);
17// Based on the module from PBPX-95216
18
19static int subfile_op_open(iop_file_t *f, const char *name, int mode);
20static int subfile_op_close(iop_file_t *f);
21static int subfile_op_read(iop_file_t *f, void *ptr, int size);
22static int subfile_op_lseek(iop_file_t *f, int pos, int mode);
23
24typedef struct subfile_priv_fd_
25{
26 int m_fd;
27 int m_baseoffset;
28 int m_totalsize;
29 int m_curpos;
31
32IOMAN_RETURN_VALUE_IMPL(0);
33
34static iop_device_ops_t subfile_devops = {
35 IOMAN_RETURN_VALUE(0), // init
36 IOMAN_RETURN_VALUE(0), // deinit
37 IOMAN_RETURN_VALUE(0), // format
38 &subfile_op_open, // open
39 &subfile_op_close, // close
40 &subfile_op_read, // read
41 IOMAN_RETURN_VALUE(0), // write
42 &subfile_op_lseek, // lseek
43 IOMAN_RETURN_VALUE(0), // ioctl
44 IOMAN_RETURN_VALUE(0), // remove
45 IOMAN_RETURN_VALUE(0), // mkdir
46 IOMAN_RETURN_VALUE(0), // rmdir
47 IOMAN_RETURN_VALUE(0), // dopen
48 IOMAN_RETURN_VALUE(0), // dclose
49 IOMAN_RETURN_VALUE(0), // dread
50 IOMAN_RETURN_VALUE(0), // getstat
51 IOMAN_RETURN_VALUE(0), // chstat
52};
53static iop_device_t subfile_dev = {
54 "subfile",
55 IOP_DT_FS,
56 1u,
57 "SubFile",
58 &subfile_devops,
59};
60static subfile_priv_fd_t subfile_info[8];
61static void *tmpbuf;
62
63int _start(int ac, char *av[])
64{
65 int i;
66 int state;
67
68 (void)ac;
69 (void)av;
70 memset(subfile_info, 0, sizeof(subfile_info));
71 for ( i = 0; i < (int)(sizeof(subfile_info) / sizeof(subfile_info[0])); i += 1 )
72 {
73 subfile_info[i].m_fd = -1;
74 }
75 CpuSuspendIntr(&state);
76 tmpbuf = AllocSysMemory(ALLOC_LAST, 0x4000, NULL);
77 CpuResumeIntr(state);
78 if ( tmpbuf == NULL )
79 return MODULE_NO_RESIDENT_END;
80 return (AddDrv(&subfile_dev) < 0) ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END;
81}
82
83static int subfile_op_open(iop_file_t *f, const char *name, int mode)
84{
85 int cur_baseoffset;
86 int cur_totalsize;
87 int i;
88 int arrind;
89 char namechr_int;
90 int cur_fd;
91 char curfilename[128];
92 int state;
93
94 (void)mode;
95 cur_baseoffset = 0;
96 cur_totalsize = 0;
97 curfilename[0] = '\x00';
98 arrind = 0;
99 for ( i = 0; name[i]; ++i )
100 {
101 switch ( arrind )
102 {
103 case 0:
104 {
105 curfilename[i] = (name[i] != ',') ? name[i] : '\x00';
106 if ( curfilename[i] == '\x00' )
107 {
108 arrind += 1;
109 }
110 break;
111 }
112 case 1:
113 case 2:
114 default:
115 {
116 if ( name[i] == ',' )
117 {
118 arrind += 1;
119 break;
120 }
121 if ( name[i] < '0' )
122 return -ENOENT;
123 if ( name[i] > '9' )
124 {
125 if ( name[i] < 'A' || name[i] > 'F' )
126 return -ENOENT;
127 namechr_int = name[i] - '7';
128 }
129 else
130 {
131 namechr_int = name[i] - '0';
132 }
133 if ( arrind == 1 )
134 cur_baseoffset = 16 * cur_baseoffset + namechr_int;
135 else
136 cur_totalsize = 16 * cur_totalsize + namechr_int;
137 break;
138 }
139 }
140 }
141 cur_fd = open(curfilename, FIO_O_RDONLY);
142 if ( cur_fd < 0 )
143 {
144 return cur_fd;
145 }
146 CpuSuspendIntr(&state);
147 for ( i = 0; i < (int)(sizeof(subfile_info) / sizeof(subfile_info[0])) && subfile_info[i].m_fd >= 0; i += 1 )
148 {
149 }
150 if ( i >= (int)(sizeof(subfile_info) / sizeof(subfile_info[0])) )
151 {
152 CpuResumeIntr(state);
153 close(cur_fd);
154 return -ENOMEM;
155 }
156 subfile_info[i].m_fd = cur_fd;
157 subfile_info[i].m_baseoffset = cur_baseoffset;
158 subfile_info[i].m_totalsize = cur_totalsize;
159 subfile_info[i].m_curpos = 0;
160 CpuResumeIntr(state);
161 f->privdata = &subfile_info[i];
162 return 0;
163}
164
165static int subfile_op_close(iop_file_t *f)
166{
167 subfile_priv_fd_t *privdata;
168
169 privdata = (subfile_priv_fd_t *)f->privdata;
170 if ( privdata == NULL )
171 {
172 return -EBADF;
173 }
174 close(privdata->m_fd);
175 privdata->m_fd = -1;
176 f->privdata = NULL;
177 return 0;
178}
179
180static int subfile_op_read(iop_file_t *f, void *ptr, int size)
181{
182 subfile_priv_fd_t *privdata;
183 int size_tmp;
184 int i;
185 int baseoffs_plus_curpos_size;
186
187 privdata = (subfile_priv_fd_t *)f->privdata;
188 if ( privdata == NULL )
189 {
190 return -EBADF;
191 }
192 if ( ((uiptr)ptr & 3) != 0 )
193 {
194 return -EINVAL;
195 }
196 for ( size_tmp = (privdata->m_totalsize - privdata->m_curpos < size) ? privdata->m_totalsize - privdata->m_curpos :
197 size,
198 i = 0;
199 size_tmp > 0;
200 size_tmp -= baseoffs_plus_curpos_size, i += baseoffs_plus_curpos_size )
201 {
202 int baseoffs_plus_curpos;
203 int baseoffs_plus_curpos_chunk;
204 u32 baseoffs_plus_curpos_sub;
205 int baseoffs_plus_curpos_mask;
206
207 baseoffs_plus_curpos = privdata->m_baseoffset + privdata->m_curpos + i;
208 baseoffs_plus_curpos_chunk = baseoffs_plus_curpos & ~0x1FF;
209 baseoffs_plus_curpos_sub = privdata->m_baseoffset + privdata->m_totalsize - baseoffs_plus_curpos_chunk;
210 baseoffs_plus_curpos_mask = baseoffs_plus_curpos_sub & 0x1FF;
211 if ( (u32)(size_tmp + 0x400) < baseoffs_plus_curpos_sub )
212 {
213 baseoffs_plus_curpos_sub = size_tmp + 0x400;
214 baseoffs_plus_curpos_mask = baseoffs_plus_curpos_sub & 0x1FF;
215 }
216 if ( baseoffs_plus_curpos_mask )
217 baseoffs_plus_curpos_sub = (baseoffs_plus_curpos_sub + 0x1FF) & ~0x1FF;
218 if ( baseoffs_plus_curpos_sub > 0x4000 )
219 {
220 baseoffs_plus_curpos_sub = 0x4000;
221 }
222 baseoffs_plus_curpos_size = (baseoffs_plus_curpos_chunk + baseoffs_plus_curpos_sub) - baseoffs_plus_curpos;
223 if ( size_tmp < baseoffs_plus_curpos_size )
224 baseoffs_plus_curpos_size = size_tmp;
225 lseek(privdata->m_fd, baseoffs_plus_curpos_chunk, FIO_SEEK_SET);
226 read(privdata->m_fd, tmpbuf, baseoffs_plus_curpos_sub);
227 memcpy((u8 *)ptr + i, (u8 *)tmpbuf + (baseoffs_plus_curpos & 0x1FF), baseoffs_plus_curpos_size);
228 }
229 privdata->m_curpos += i;
230 return i;
231}
232
233static int subfile_op_lseek(iop_file_t *f, int pos, int mode)
234{
235 subfile_priv_fd_t *privdata;
236 int offs_relative;
237 u32 m_totalsize;
238 int pos_plus_curpos;
239
240 privdata = (subfile_priv_fd_t *)f->privdata;
241 if ( privdata == NULL )
242 return -EBADF;
243 switch ( mode )
244 {
245 case FIO_SEEK_SET:
246 offs_relative = 0;
247 break;
248 case FIO_SEEK_CUR:
249 offs_relative = privdata->m_curpos;
250 break;
251 case FIO_SEEK_END:
252 offs_relative = privdata->m_totalsize;
253 break;
254 default:
255 return -EINVAL;
256 }
257 m_totalsize = privdata->m_totalsize;
258 pos_plus_curpos = pos + offs_relative;
259 if ( (int)m_totalsize >= pos_plus_curpos )
260 {
261 m_totalsize = 0;
262 if ( pos_plus_curpos >= 0 )
263 m_totalsize = pos_plus_curpos;
264 }
265 privdata->m_curpos = m_totalsize;
266 return m_totalsize;
267}
#define ENOENT
Definition errno.h:23
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43
#define EBADF
Definition errno.h:37
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
void * privdata
Definition ioman.h:61