12#include <irx_imports.h>
15#define MODNAME "erom_file_driver"
22 u32 m_fileoffset_hash;
24 u32 m_next_fileoffset_hash;
25 u32 m_xordata_size_hash;
30 const void *m_erom_start;
41 void *m_xordata_offset;
46static int erom_op_lseek(
iop_file_t *f,
int pos,
int mode);
47static int erom_op_open(
iop_file_t *f,
const char *name,
int mode);
48static int erom_op_read(
iop_file_t *f,
void *ptr,
int size);
49static int get_val_from_hash0(u32 obfval);
50static int get_val_from_hash1(u32 obfval);
54IOMAN_RETURN_VALUE_IMPL(0);
55IOMAN_RETURN_VALUE_IMPL(
EIO);
58 IOMAN_RETURN_VALUE(0),
59 IOMAN_RETURN_VALUE(0),
60 IOMAN_RETURN_VALUE(0),
64 IOMAN_RETURN_VALUE(
EIO),
66 IOMAN_RETURN_VALUE(0),
67 IOMAN_RETURN_VALUE(0),
68 IOMAN_RETURN_VALUE(0),
69 IOMAN_RETURN_VALUE(0),
70 IOMAN_RETURN_VALUE(0),
71 IOMAN_RETURN_VALUE(0),
72 IOMAN_RETURN_VALUE(0),
73 IOMAN_RETURN_VALUE(0),
74 IOMAN_RETURN_VALUE(0),
98static int erom_op_lseek(
iop_file_t *f,
int pos,
int mode)
111 offs_relative = privdata->m_cur_offset;
114 offs_relative = privdata->m_file_size;
119 pos_plus_curpos = pos + offs_relative;
120 privdata->m_cur_offset = (privdata->m_file_size >= pos_plus_curpos) ? pos_plus_curpos : privdata->m_file_size;
121 return privdata->m_cur_offset;
124int _start(
int ac,
char **av)
133 dev1_address = *((vu32 *)0xBF801400);
134 dev1_delay = *((vu32 *)0xBF80100C);
135 *((vu32 *)0xBF801400) = 0xBE000000;
136 *((vu32 *)0xBF80100C) = 0x18344F;
137 has_erom = get_erom_info((u32 *)0xBE080000, (u32 *)0xBE080400, &erom_info) != 0;
140 *((vu32 *)0xBF80100C) = 0x18244F;
141 has_erom = get_erom_info((u32 *)0xBE080000, (u32 *)0xBE080400, &erom_info) != 0;
145 *((vu32 *)0xBF80100C) = dev1_delay;
146 *((vu32 *)0xBF801400) = dev1_address;
147 return MODULE_NO_RESIDENT_END;
149 DelDrv(erom_dev.name);
150 return (AddDrv(&erom_dev) < 0) ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END;
153static int erom_op_open(
iop_file_t *f,
const char *name,
int mode)
158 if ( f->
unit || !erom_info.m_erom_start )
160 while ( *name ==
'@' || *name ==
'&' )
162 erom_fdpriv.m_magic8 ^= 1u;
166 if ( erom_dentry != NULL )
171 erom_dentry = get_direntry_by_name(&erom_info, name);
173 if ( erom_dentry == NULL )
177 erom_fdpriv.m_unused0 = 0;
178 erom_fdpriv.m_cur_offset = 0;
179 erom_fdpriv.m_file_offset = (u8 *)erom_info.m_erom_start + get_val_from_hash0(erom_dentry->m_fileoffset_hash);
180 erom_fdpriv.m_xordata_size = 4 * get_val_from_hash0(erom_dentry->m_xordata_size_hash);
181 erom_fdpriv.m_xordata_offset = (u8 *)erom_fdpriv.m_file_offset - erom_fdpriv.m_xordata_size;
182 erom_fdpriv.m_file_size = get_val_from_hash1(erom_dentry->m_filesize_hash) & 0xFFFFFF;
187static int erom_op_read(
iop_file_t *f,
void *ptr,
int size)
201 m_cur_offset = privdata->m_cur_offset;
202 m_file_size = privdata->m_file_size;
203 size_tmp = (m_file_size - m_cur_offset < size) ? m_file_size - m_cur_offset : size;
208 m_xordata_size = privdata->m_xordata_size;
209 filesize_tmp = m_xordata_size - m_cur_offset;
210 if ( filesize_tmp > 0 )
215 if ( filesize_tmp > size_tmp )
216 filesize_tmp = size_tmp;
217 memcpy(dstptr, (u8 *)privdata->m_xordata_offset + m_cur_offset, filesize_tmp);
218 srcptr = (u8 *)privdata->m_file_offset + privdata->m_cur_offset;
219 srcptr_end = srcptr + filesize_tmp;
220 if ( ((uiptr)dstptr & 3) == ((uiptr)srcptr & 3) )
222 while ( ((uiptr)srcptr & 3) != 0 )
228 while ( (uiptr)srcptr < ((uiptr)srcptr_end & (~3)) )
230 *(u32 *)dstptr ^= *(u32 *)srcptr;
235 while ( srcptr < srcptr_end )
237 *dstptr ^= *(u8 *)srcptr;
241 size_tmp -= filesize_tmp;
242 privdata->m_cur_offset += filesize_tmp;
246 memcpy(dstptr, (u8 *)privdata->m_file_offset + privdata->m_cur_offset, size_tmp);
247 privdata->m_cur_offset += size_tmp;
249 return size_tmp + filesize_tmp;
252static u32 get_string_hash(
const char *name)
259 strncpy(nametmp, name,
sizeof(nametmp));
260 for ( i = 0; i < (int)(
sizeof(nametmp)); i += 1 )
265 tmpval1 = (u8)nametmp[i];
266 tmpval2 = tmpval1 - 64;
267 if ( (u32)(tmpval1 - 65) >= 0xD )
272 tmpval2 = (u8)tmpval1 - 63;
273 if ( (u8)tmpval1 < 0x4Eu )
276 if ( (u8)tmpval1 != 32 )
277 tmpval2 = (u8)tmpval1 - 19;
281 ret = 40 * ret + tmpval2;
286static int get_val_from_hash0(u32 obfval)
292 for ( i = 0; i < 32; i += 4 )
297 tmpval1 = obfval % 0x12;
298 tmpval2 = (tmpval1 - 1) << i;
299 if ( tmpval1 - 1 >= 0xA )
300 tmpval2 = (tmpval1 - 2) << i;
307static int get_val_from_hash1(u32 obfval)
313 for ( i = 0; i < 28; i += 4 )
317 tmpval1 = obfval % 0x13 + 9;
318 if ( obfval % 0x13 - 1 >= 6 )
319 tmpval1 = obfval % 0x13 - 8;
334 bufcount = erom_end - erom_start;
335 memcpy(tmpname,
" @ A B", 6);
336 info->m_erom_start = 0;
337 buf = (u32 *)AllocSysMemory(ALLOC_FIRST, bufcount *
sizeof(u32), NULL);
340 memcpy(buf, erom_start, bufcount *
sizeof(u32));
341 for ( c =
'C'; (u8)c <
'['; c += 1 )
345 tmpname[1] = tmpname[3];
346 tmpname[3] = tmpname[5];
348 string_hash = get_string_hash(tmpname);
349 for ( i = 0; (i < bufcount) && (buf[i] != string_hash); i += 1 )
354 info->m_erom_start = erom_start;
369 res =
info->m_erom_dentry_start;
370 string_hash = get_string_hash(name);
371 while ( res && res->m_filename_hash != string_hash )
375 val_from_hash0 = get_val_from_hash0(res->m_next_fileoffset_hash);
376 res = val_from_hash0 ? (
const erom_dentry_t *)((u8 *)
info->m_erom_start + val_from_hash0) : NULL;
int CpuResumeIntr(int state)
int CpuSuspendIntr(int *state)