Skip to content

Commit

Permalink
Merge pull request #655 from uyjulian/subfile
Browse files Browse the repository at this point in the history
Subfile module
  • Loading branch information
fjtrujy authored Oct 8, 2024
2 parents 9e35762 + 8030cf2 commit d1818f4
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 1 deletion.
3 changes: 2 additions & 1 deletion iop/fs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ SUBDIRS = \
http \
libbdm \
netfs \
romdrv
romdrv \
subfile

include $(PS2SDKSRC)/Defs.make
include $(PS2SDKSRC)/Rules.make
14 changes: 14 additions & 0 deletions iop/fs/subfile/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.

IOP_OBJS = subfile.o imports.o

include $(PS2SDKSRC)/Defs.make
include $(PS2SDKSRC)/iop/Rules.bin.make
include $(PS2SDKSRC)/iop/Rules.make
include $(PS2SDKSRC)/iop/Rules.release
16 changes: 16 additions & 0 deletions iop/fs/subfile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Subfile

IOP module for exposing a portion of a file (useful for loading an executable
embedded in a APA partition).

## Configurations

There are multiple configurations of this library, allowing the choice of
balancing between size, speed, and features.

* `subfile` -> The recommended version.

## How to use this module in your program

In order to use this module in your program, use `LoadModule` or \
`LoadModuleBuffer` with no arguments.
22 changes: 22 additions & 0 deletions iop/fs/subfile/src/imports.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

sysmem_IMPORTS_start
I_AllocSysMemory
sysmem_IMPORTS_end

intrman_IMPORTS_start
I_CpuSuspendIntr
I_CpuResumeIntr
intrman_IMPORTS_end

ioman_IMPORTS_start
I_open
I_close
I_read
I_lseek
I_AddDrv
ioman_IMPORTS_end

sysclib_IMPORTS_start
I_memcpy
I_memset
sysclib_IMPORTS_end
22 changes: 22 additions & 0 deletions iop/fs/subfile/src/irx_imports.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

#ifndef IOP_IRX_IMPORTS_H
#define IOP_IRX_IMPORTS_H

#include "irx.h"

/* Please keep these in alphabetical order! */
#include <intrman.h>
#include <ioman.h>
#include <sysclib.h>
#include <sysmem.h>

#endif /* IOP_IRX_IMPORTS_H */
271 changes: 271 additions & 0 deletions iop/fs/subfile/src/subfile.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

#include <errno.h>
#include <irx_imports.h>
#include <loadcore.h>

#define MODNAME "subfile_driver"
IRX_ID(MODNAME, 2, 1);
// Based on the module from PBPX-95216

static int subfile_op_nulldev(void);
static int subfile_op_open(iop_file_t *f, const char *name, int mode);
static int subfile_op_close(iop_file_t *f);
static int subfile_op_read(iop_file_t *f, void *ptr, int size);
static int subfile_op_lseek(iop_file_t *f, int pos, int mode);

typedef struct subfile_priv_fd_
{
int m_fd;
int m_baseoffset;
int m_totalsize;
int m_curpos;
} subfile_priv_fd_t;

static iop_device_ops_t subfile_devops = {
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
subfile_op_open,
subfile_op_close,
subfile_op_read,
(void *)subfile_op_nulldev,
subfile_op_lseek,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
(void *)subfile_op_nulldev,
};
static iop_device_t subfile_dev = {
"subfile",
IOP_DT_FS,
1u,
"SubFile",
&subfile_devops,
};
static subfile_priv_fd_t subfile_info[8];
static void *tmpbuf;

int _start(int ac, char *av[])
{
int i;
int state;

(void)ac;
(void)av;
memset(subfile_info, 0, sizeof(subfile_info));
for ( i = 0; i < (int)(sizeof(subfile_info) / sizeof(subfile_info[0])); i += 1 )
{
subfile_info[i].m_fd = -1;
}
CpuSuspendIntr(&state);
tmpbuf = AllocSysMemory(ALLOC_LAST, 0x4000, NULL);
CpuResumeIntr(state);
if ( tmpbuf == NULL )
return MODULE_NO_RESIDENT_END;
return (AddDrv(&subfile_dev) < 0) ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END;
}

static int subfile_op_open(iop_file_t *f, const char *name, int mode)
{
int cur_baseoffset;
int cur_totalsize;
int i;
int arrind;
char namechr_int;
int cur_fd;
char curfilename[128];
int state;

(void)mode;
cur_baseoffset = 0;
cur_totalsize = 0;
curfilename[0] = '\x00';
arrind = 0;
for ( i = 0; name[i]; ++i )
{
switch ( arrind )
{
case 0:
{
curfilename[i] = (name[i] != ',') ? name[i] : '\x00';
if ( curfilename[i] == '\x00' )
{
arrind += 1;
}
break;
}
case 1:
case 2:
default:
{
if ( name[i] == ',' )
{
arrind += 1;
break;
}
if ( name[i] < '0' )
return -ENOENT;
if ( name[i] > '9' )
{
if ( name[i] < 'A' || name[i] > 'F' )
return -ENOENT;
namechr_int = name[i] - '7';
}
else
{
namechr_int = name[i] - '0';
}
if ( arrind == 1 )
cur_baseoffset = 16 * cur_baseoffset + namechr_int;
else
cur_totalsize = 16 * cur_totalsize + namechr_int;
break;
}
}
}
cur_fd = open(curfilename, FIO_O_RDONLY);
if ( cur_fd < 0 )
{
return cur_fd;
}
CpuSuspendIntr(&state);
for ( i = 0; i < (int)(sizeof(subfile_info) / sizeof(subfile_info[0])) && subfile_info[i].m_fd >= 0; i += 1 )
{
}
if ( i >= (int)(sizeof(subfile_info) / sizeof(subfile_info[0])) )
{
CpuResumeIntr(state);
close(cur_fd);
return -ENOMEM;
}
subfile_info[i].m_fd = cur_fd;
subfile_info[i].m_baseoffset = cur_baseoffset;
subfile_info[i].m_totalsize = cur_totalsize;
subfile_info[i].m_curpos = 0;
CpuResumeIntr(state);
f->privdata = &subfile_info[i];
return 0;
}

static int subfile_op_nulldev(void)
{
return 0;
}

static int subfile_op_close(iop_file_t *f)
{
subfile_priv_fd_t *privdata;

privdata = (subfile_priv_fd_t *)f->privdata;
if ( privdata == NULL )
{
return -EBADF;
}
close(privdata->m_fd);
privdata->m_fd = -1;
f->privdata = NULL;
return 0;
}

static int subfile_op_read(iop_file_t *f, void *ptr, int size)
{
subfile_priv_fd_t *privdata;
int size_tmp;
int i;
int baseoffs_plus_curpos_size;

privdata = (subfile_priv_fd_t *)f->privdata;
if ( privdata == NULL )
{
return -EBADF;
}
if ( ((uiptr)ptr & 3) != 0 )
{
return -EINVAL;
}
for ( size_tmp = (privdata->m_totalsize - privdata->m_curpos < size) ? privdata->m_totalsize - privdata->m_curpos :
size,
i = 0;
size_tmp > 0;
size_tmp -= baseoffs_plus_curpos_size, i += baseoffs_plus_curpos_size )
{
int baseoffs_plus_curpos;
int baseoffs_plus_curpos_chunk;
u32 baseoffs_plus_curpos_sub;
int baseoffs_plus_curpos_mask;

baseoffs_plus_curpos = privdata->m_baseoffset + privdata->m_curpos + i;
baseoffs_plus_curpos_chunk = baseoffs_plus_curpos & ~0x1FF;
baseoffs_plus_curpos_sub = privdata->m_baseoffset + privdata->m_totalsize - baseoffs_plus_curpos_chunk;
baseoffs_plus_curpos_mask = baseoffs_plus_curpos_sub & 0x1FF;
if ( (u32)(size_tmp + 0x400) < baseoffs_plus_curpos_sub )
{
baseoffs_plus_curpos_sub = size_tmp + 0x400;
baseoffs_plus_curpos_mask = baseoffs_plus_curpos_sub & 0x1FF;
}
if ( baseoffs_plus_curpos_mask )
baseoffs_plus_curpos_sub = (baseoffs_plus_curpos_sub + 0x1FF) & ~0x1FF;
if ( baseoffs_plus_curpos_sub > 0x4000 )
{
baseoffs_plus_curpos_sub = 0x4000;
}
baseoffs_plus_curpos_size = (baseoffs_plus_curpos_chunk + baseoffs_plus_curpos_sub) - baseoffs_plus_curpos;
if ( size_tmp < baseoffs_plus_curpos_size )
baseoffs_plus_curpos_size = size_tmp;
lseek(privdata->m_fd, baseoffs_plus_curpos_chunk, FIO_SEEK_SET);
read(privdata->m_fd, tmpbuf, baseoffs_plus_curpos_sub);
memcpy((u8 *)ptr + i, (u8 *)tmpbuf + (baseoffs_plus_curpos & 0x1FF), baseoffs_plus_curpos_size);
}
privdata->m_curpos += i;
return i;
}

static int subfile_op_lseek(iop_file_t *f, int pos, int mode)
{
subfile_priv_fd_t *privdata;
int offs_relative;
u32 m_totalsize;
int pos_plus_curpos;

privdata = (subfile_priv_fd_t *)f->privdata;
if ( privdata == NULL )
return -EBADF;
switch ( mode )
{
case FIO_SEEK_SET:
offs_relative = 0;
break;
case FIO_SEEK_CUR:
offs_relative = privdata->m_curpos;
break;
case FIO_SEEK_END:
offs_relative = privdata->m_totalsize;
break;
default:
return -EINVAL;
}
m_totalsize = privdata->m_totalsize;
pos_plus_curpos = pos + offs_relative;
if ( (int)m_totalsize >= pos_plus_curpos )
{
m_totalsize = 0;
if ( pos_plus_curpos >= 0 )
m_totalsize = pos_plus_curpos;
}
privdata->m_curpos = m_totalsize;
return m_totalsize;
}

0 comments on commit d1818f4

Please sign in to comment.