static PHYSFS_Io *UNPK_duplicate(PHYSFS_Io *_io) { UNPKfileinfo *origfinfo = (UNPKfileinfo *) _io->opaque; PHYSFS_Io *io = NULL; PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); UNPKfileinfo *finfo = (UNPKfileinfo *) allocator.Malloc(sizeof (UNPKfileinfo)); GOTO_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_duplicate_failed); GOTO_IF_MACRO(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_duplicate_failed); io = origfinfo->io->duplicate(origfinfo->io); if (!io) goto UNPK_duplicate_failed; finfo->io = io; finfo->entry = origfinfo->entry; finfo->curPos = 0; memcpy(retval, _io, sizeof (PHYSFS_Io)); retval->opaque = finfo; return retval; UNPK_duplicate_failed: if (finfo != NULL) allocator.Free(finfo); if (retval != NULL) allocator.Free(retval); if (io != NULL) io->destroy(io); return NULL; } /* UNPK_duplicate */
~RGSS_entryHandle() { io->destroy(io); }
static PHYSFS_sint64 RGSS_ioRead(PHYSFS_Io *self, void *buffer, PHYSFS_uint64 len) { RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); PHYSFS_Io *io = entry->io; uint64_t toRead = std::min<uint64_t>(entry->data.size - entry->currentOffset, len); uint64_t offs = entry->currentOffset; io->seek(io, entry->data.offset + offs); /* We divide up the bytes to be read in 3 categories: * * preAlign: If the current read address is not dword * aligned, this is the number of bytes to read til * we reach alignment again (therefore can only be * 3 or less). * * align: The number of aligned dwords we can read * times 4 (= number of bytes). * * postAlign: The number of bytes to read after the * last aligned dword. Always 3 or less. * * Treating the pre- and post aligned reads specially, * we can read all aligned dwords in one syscall directly * into the write buffer and then run the xor chain on * it afterwards. */ uint8_t preAlign = 4 - (offs % 4); if (preAlign == 4) preAlign = 0; else preAlign = std::min<uint64_t>(preAlign, len); uint8_t postAlign = (len > preAlign) ? (offs + len) % 4 : 0; uint64_t align = len - (preAlign + postAlign); /* Byte buffer pointer */ uint8_t *bBufferP = static_cast<uint8_t*>(buffer); if (preAlign > 0) { uint32_t dword; io->read(io, &dword, preAlign); /* Need to align the bytes with the * magic before xoring */ dword <<= 8 * (offs % 4); dword ^= entry->currentMagic; /* Shift them back to normal */ dword >>= 8 * (offs % 4); memcpy(bBufferP, &dword, preAlign); bBufferP += preAlign; /* Only advance the magic if we actually * reached the next alignment */ if ((offs+preAlign) % 4 == 0) advanceMagic(entry->currentMagic); }