New version from Jens.
committer: mfx <mfx> 1028128175 +0000
This commit is contained in:
+269
-227
@@ -20,8 +20,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -37,10 +37,31 @@ static const
|
|||||||
|
|
||||||
//#define TESTING
|
//#define TESTING
|
||||||
|
|
||||||
|
#define MIPS_HI(a) (((a)>>16)/*+((a&0x8000)>>15)*/)
|
||||||
|
#define MIPS_LO(a) (a&0xffff)
|
||||||
|
#define MIPS_JP(a) ((0x08<<24)|((a&0xfffffff)>>2))
|
||||||
|
#define CHK_ALIGNED(a,b) (b-(a%b))
|
||||||
|
|
||||||
|
#define PS_HDR_SIZE 2048 //one cd sector in bytes
|
||||||
|
#define PS_MAX_SIZE 0x1e8000
|
||||||
|
|
||||||
|
#define IH_BKUP (10*sizeof(LE32))
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
PackPsx::PackPsx(InputFile *f) :
|
||||||
|
super(f)
|
||||||
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(psx_exe_t) == 188);
|
||||||
|
COMPILE_TIME_ASSERT(IH_BKUP == 40);
|
||||||
|
|
||||||
|
cfile_size = 0;
|
||||||
|
scan_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const int *PackPsx::getCompressionMethods(int method, int level) const
|
const int *PackPsx::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
static const int m_nrv2b[] = { M_NRV2B_LE32, M_NRV2D_LE32, -1 };
|
static const int m_nrv2b[] = { M_NRV2B_LE32, M_NRV2D_LE32, -1 };
|
||||||
@@ -62,231 +83,6 @@ const int *PackPsx::getFilters() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
bool PackPsx::canPack()
|
|
||||||
{
|
|
||||||
right_file_size = 0;
|
|
||||||
file_data_size = file_size-PS_HDR_SIZE;
|
|
||||||
|
|
||||||
fi->seek(0, SEEK_SET);
|
|
||||||
fi->readx(&ih, sizeof(ih));
|
|
||||||
|
|
||||||
if ((memcmp(&ih.id,"PS-X EXE",8) != 0) && (memcmp(&ih.id,"EXE X-SP",8) != 0))
|
|
||||||
return false;
|
|
||||||
checkAlreadyPacked(&ih, sizeof(ih));
|
|
||||||
if (file_data_size != ih.tx_len || (ih.tx_len & 3))
|
|
||||||
if (!opt->force)
|
|
||||||
throwCantPack("check header for file size (try --force)");
|
|
||||||
else
|
|
||||||
right_file_size = file_data_size;
|
|
||||||
if (file_size <= (PS_HDR_SIZE*3) && !opt->force)
|
|
||||||
throwCantPack("file is too small");
|
|
||||||
if (file_size > PS_MAX_SIZE && !opt->force)
|
|
||||||
throwCantPack("file is too big (try --force)");
|
|
||||||
|
|
||||||
// i_hdrp = 0;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int PackPsx::buildLoader(const Filter *)
|
|
||||||
{
|
|
||||||
initLoader(nrv_loader,sizeof(nrv_loader));
|
|
||||||
addLoader("PSXMAIN0", "PSXDECO0", NULL);
|
|
||||||
if (M_IS_NRV2B(ph.method))
|
|
||||||
addLoader("PSXN2BD0", NULL);
|
|
||||||
else if (M_IS_NRV2D(ph.method))
|
|
||||||
addLoader("PSXN2DD0", NULL);
|
|
||||||
else
|
|
||||||
throwBadLoader();
|
|
||||||
if (scan_count)
|
|
||||||
addLoader("PSXMSET0", NULL);
|
|
||||||
addLoader("PSXEXIT0""PSXPHDR0", NULL);
|
|
||||||
return getLoaderSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
void PackPsx::pack(OutputFile *fo)
|
|
||||||
{
|
|
||||||
|
|
||||||
ibuf.alloc(file_size);
|
|
||||||
obuf.allocForCompression(file_data_size);
|
|
||||||
upx_byte *p_scan = ibuf+(file_size-1);
|
|
||||||
|
|
||||||
// read file
|
|
||||||
fi->seek(0,SEEK_SET);
|
|
||||||
fi->readx(ibuf, file_size);
|
|
||||||
|
|
||||||
// this scans the end of file for the 2048 bytes sector alignment
|
|
||||||
// this should be padded with zeros
|
|
||||||
scan_count = 0;
|
|
||||||
while (!(*p_scan--)) { if ((scan_count += 1) > (0xfffc<<3)) break; }
|
|
||||||
scan_count = ALIGN_DOWN(scan_count,8);
|
|
||||||
|
|
||||||
// prepare packheader
|
|
||||||
ph.u_len = (file_data_size - scan_count);
|
|
||||||
ph.filter = 0;
|
|
||||||
|
|
||||||
Filter ft(ph.level);
|
|
||||||
// compress (max_match = 65535)
|
|
||||||
compressWithFilters(&ft, 512, 0, NULL, 0, 65535, 0, PS_HDR_SIZE);
|
|
||||||
|
|
||||||
if (ph.overlap_overhead <= scan_count)
|
|
||||||
overlap = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
overlap = ALIGN_UP((ph.overlap_overhead-scan_count),4);
|
|
||||||
if (!opt->force)
|
|
||||||
throwCantPack("packed data overlap (try --force)");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
opt->info_mode += !opt->info_mode ? 1 : 0;
|
|
||||||
infoWarning("%s will load to a %d bytes higher offset",fi->getName(),overlap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&oh, &ih, sizeof(&ih));
|
|
||||||
|
|
||||||
// oki_hdrp->upx_hdr.hdr_adler = upx_adler32(&i_hdrp->exec,sizeof(exec_hdr_t));
|
|
||||||
|
|
||||||
const int lsize = getLoaderSize();
|
|
||||||
const int h_len = lsize-getLoaderSectionStart("PSXPHDR0");
|
|
||||||
const int e_len = lsize-h_len;
|
|
||||||
const int d_len = e_len-getLoaderSectionStart("PSXDECO0");
|
|
||||||
upx_uint pad_code = 0;
|
|
||||||
upx_uint pad = 0;
|
|
||||||
|
|
||||||
MemBuffer loader(lsize);
|
|
||||||
memcpy(loader,getLoader(),lsize);
|
|
||||||
|
|
||||||
pad = !right_file_size ? ih.tx_len : right_file_size;
|
|
||||||
pad = ALIGN_DOWN(pad,4);
|
|
||||||
pad_code = CHK_ALIGNED((ph.c_len),4);
|
|
||||||
|
|
||||||
upx_uint decomp_data_start = ih.tx_ptr;
|
|
||||||
|
|
||||||
// set the offset for compressed stuff at the very end of file
|
|
||||||
upx_uint comp_data_start = (decomp_data_start+pad)-ph.c_len+(overlap ? overlap : 0);
|
|
||||||
|
|
||||||
pad = 0; //clear pad, because of temp use
|
|
||||||
|
|
||||||
// align the packed file to mode 2 data sector size (2048)
|
|
||||||
if (!opt->psx.no_align)
|
|
||||||
pad = CHK_ALIGNED((ph.c_len+pad_code+e_len),2048);
|
|
||||||
|
|
||||||
int entry = (comp_data_start-e_len-pad_code);
|
|
||||||
|
|
||||||
patch_mips_le32(loader,e_len,"JPEP",MIPS_JP(ih.epc));
|
|
||||||
if (scan_count)
|
|
||||||
patch_mips_le16(loader,e_len,"SC",MIPS_LO(scan_count>>3));
|
|
||||||
patch_hi_lo(loader,e_len,"OH","OL",decomp_data_start);
|
|
||||||
// patch_hi_lo(loader,e_len,"LH","LL",ph.u_len+pad_code+pad);
|
|
||||||
patch_hi_lo(loader,e_len,"CH","CL",comp_data_start);
|
|
||||||
patch_hi_lo(loader,e_len,"DH","DL",entry+(e_len-d_len));
|
|
||||||
patch_mips_le16(loader,e_len,"LS",d_len);
|
|
||||||
|
|
||||||
// set the file load address
|
|
||||||
oh.tx_ptr = entry-pad;
|
|
||||||
// set the correct file len in header
|
|
||||||
oh.tx_len = (ph.c_len+e_len+pad+pad_code);
|
|
||||||
// set the code entry
|
|
||||||
oh.epc = entry;
|
|
||||||
|
|
||||||
// build upx header
|
|
||||||
// memcpy(&i_hdrp->upx_hdr.id,UPX_VERSION_STRING,sizeof(UPX_VERSION_STRING));
|
|
||||||
// memcpy(&i_hdrp->upx_hdr.ph_hdr,loader+e_len,h_len);
|
|
||||||
|
|
||||||
// patchPackHeader(&i_hdrp->upx_hdr,PS_HDR_SIZE);
|
|
||||||
// write loader + compressed file
|
|
||||||
fo->write(ibuf,PS_HDR_SIZE);
|
|
||||||
// clear ibuf to get padding data (0)
|
|
||||||
upx_bytep paddata = ibuf+PS_HDR_SIZE;
|
|
||||||
memset(paddata,0,file_data_size);
|
|
||||||
// align the file (mode 2 sector data size)
|
|
||||||
if (pad)
|
|
||||||
fo->write(paddata,pad);
|
|
||||||
// entry
|
|
||||||
fo->write(loader,e_len);
|
|
||||||
// align the compressed data for the mips runtime code
|
|
||||||
if (pad_code)
|
|
||||||
fo->write(paddata,pad_code);
|
|
||||||
|
|
||||||
fo->write(obuf,ph.c_len);
|
|
||||||
#if 0
|
|
||||||
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
|
|
||||||
printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) e_len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int PackPsx::canUnpack()
|
|
||||||
{
|
|
||||||
// FIXME: set ih
|
|
||||||
if (!readPackHeader(sizeof(ih)))
|
|
||||||
return false;
|
|
||||||
if (file_size <= (off_t) ph.c_len)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
void PackPsx::unpack(OutputFile *fo)
|
|
||||||
{
|
|
||||||
ibuf.alloc(file_size);
|
|
||||||
|
|
||||||
// i_hdrp = (ps_x_exe_t*)ibuf.getBuf();
|
|
||||||
|
|
||||||
// read the file header
|
|
||||||
fi->seek(0x0,SEEK_SET);
|
|
||||||
// and the remaining stuff
|
|
||||||
fi->readx(ibuf,file_size);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// test & restore orig exec hdr
|
|
||||||
if (i_hdrp->upx_hdr.hdr_adler != upx_adler32(&i_hdrp->upx_hdr.exec_bkup,sizeof(exec_hdr_t)))
|
|
||||||
throwCantUnpack("file is possibly modified/hacked/protected; take care!");
|
|
||||||
memcpy(&i_hdrp->exec,&i_hdrp->upx_hdr.exec_bkup,sizeof(exec_hdr_t));
|
|
||||||
|
|
||||||
upx_uint pad = (i_hdrp->exec.tx_len)-ph.u_len;
|
|
||||||
|
|
||||||
memset(&i_hdrp->upx_hdr,0,sizeof(upx_hdr_t));
|
|
||||||
|
|
||||||
obuf.allocForUncompression(ph.u_len+pad);
|
|
||||||
memset(obuf,0,obuf.getSize());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// decompress
|
|
||||||
decompress(ibuf+(file_size-ph.c_len),obuf);
|
|
||||||
|
|
||||||
// write decompressed file
|
|
||||||
if (fo)
|
|
||||||
{
|
|
||||||
fo->write(ibuf,PS_HDR_SIZE);
|
|
||||||
// fo->write(obuf,ph.u_len+pad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// functions for marker handling
|
// functions for marker handling
|
||||||
int PackPsx::patch_mips_le16(void *b, int blen, const void *old, unsigned new_)
|
int PackPsx::patch_mips_le16(void *b, int blen, const void *old, unsigned new_)
|
||||||
{
|
{
|
||||||
@@ -312,6 +108,252 @@ int PackPsx::patch_hi_lo(void *b, int blen, const void *old_hi, const void *old_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool PackPsx::canPack()
|
||||||
|
{
|
||||||
|
unsigned char buf[256];
|
||||||
|
fdata_size = file_size-PS_HDR_SIZE;
|
||||||
|
|
||||||
|
fi->seek(0, SEEK_SET);
|
||||||
|
fi->readx(&ih, sizeof(ih));
|
||||||
|
|
||||||
|
if ((memcmp(&ih.id,"PS-X EXE",8) != 0) && (memcmp(&ih.id,"EXE X-SP",8) != 0))
|
||||||
|
return false;
|
||||||
|
fi->readx(buf, sizeof(buf));
|
||||||
|
checkAlreadyPacked(&buf, sizeof(buf));
|
||||||
|
if (fdata_size != ih.tx_len || (ih.tx_len & 3))
|
||||||
|
if (!opt->force)
|
||||||
|
throwCantPack("check header for file size (try --force)");
|
||||||
|
else
|
||||||
|
cfile_size = fdata_size;
|
||||||
|
if (file_size <= (PS_HDR_SIZE*3) && !opt->force)
|
||||||
|
throwCantPack("file is too small (try --force)");
|
||||||
|
if (file_size > PS_MAX_SIZE && !opt->force)
|
||||||
|
throwCantPack("file is too big (try --force)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackPsx::buildLoader(const Filter *)
|
||||||
|
{
|
||||||
|
initLoader(nrv_loader,sizeof(nrv_loader));
|
||||||
|
addLoader("PSXMAIN0", "PSXDECO0", NULL);
|
||||||
|
if (ph.method == M_NRV2B_LE32)
|
||||||
|
addLoader("PSXN2BD0", NULL);
|
||||||
|
else if (ph.method == M_NRV2D_LE32)
|
||||||
|
addLoader("PSXN2DD0", NULL);
|
||||||
|
else
|
||||||
|
throwInternalError("unknown compression method");
|
||||||
|
if (scan_count)
|
||||||
|
{
|
||||||
|
if (scan_count > 0xfffc)
|
||||||
|
addLoader("MSETBIG0", NULL); // set big memset
|
||||||
|
else
|
||||||
|
addLoader("MSETSML0", NULL); // set small memset
|
||||||
|
if ((ih.tx_len & 3))
|
||||||
|
addLoader("MSETUAL0", NULL); // unaligned memset
|
||||||
|
else
|
||||||
|
addLoader("MSETALG0", NULL); // aligned memset
|
||||||
|
}
|
||||||
|
addLoader("PSXEXIT0", "IDENTSTR", "PSXPHDR0", NULL);
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackPsx::pack(OutputFile *fo)
|
||||||
|
{
|
||||||
|
|
||||||
|
ibuf.alloc(fdata_size);
|
||||||
|
obuf.allocForCompression(fdata_size);
|
||||||
|
upx_byte *p_scan = ibuf+(fdata_size-1);
|
||||||
|
|
||||||
|
// read file
|
||||||
|
fi->seek(PS_HDR_SIZE,SEEK_SET);
|
||||||
|
fi->readx(ibuf,fdata_size);
|
||||||
|
|
||||||
|
// this scans the end of file for 2048 bytes sector alignment
|
||||||
|
// this should be padded with zeros
|
||||||
|
while (!(*p_scan--)) { if ((scan_count += 1) > (0xfffc<<3)) break; }
|
||||||
|
if (scan_count > 0xfffc)
|
||||||
|
scan_count = ALIGN_DOWN(scan_count,8);
|
||||||
|
else
|
||||||
|
scan_count = ALIGN_DOWN(scan_count,4);
|
||||||
|
|
||||||
|
// prepare packheader
|
||||||
|
ph.u_len = (fdata_size - scan_count);
|
||||||
|
ph.filter = 0;
|
||||||
|
|
||||||
|
Filter ft(ph.level);
|
||||||
|
// compress (max_match = 65535)
|
||||||
|
compressWithFilters(&ft, 512, 0, NULL, 0, 65535, 0, 0);
|
||||||
|
|
||||||
|
if (ph.overlap_overhead <= scan_count)
|
||||||
|
overlap = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!opt->force)
|
||||||
|
throwCantPack("packed data overlap (try --force)");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
overlap = ALIGN_UP((ph.overlap_overhead-scan_count),4);
|
||||||
|
opt->info_mode += !opt->info_mode ? 1 : 0;
|
||||||
|
infoWarning("%s will load to a %d bytes higher offset",fi->getName(),overlap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&oh, &ih, sizeof(ih));
|
||||||
|
memcpy(&oh.ih_bkup, &ih.epc, IH_BKUP);
|
||||||
|
oh.ih_csum = upx_adler32(&ih.epc, IH_BKUP);
|
||||||
|
|
||||||
|
const int lsize = getLoaderSize();
|
||||||
|
const int h_len = lsize-getLoaderSectionStart("IDENTSTR");
|
||||||
|
const int e_len = lsize-h_len;
|
||||||
|
const int d_len = e_len-getLoaderSectionStart("PSXDECO0");
|
||||||
|
upx_uint pad_code = 0;
|
||||||
|
upx_uint pad = 0;
|
||||||
|
|
||||||
|
MemBuffer loader(lsize);
|
||||||
|
memcpy(loader,getLoader(),lsize);
|
||||||
|
|
||||||
|
pad = !cfile_size ? ih.tx_len : cfile_size;
|
||||||
|
pad = ALIGN_DOWN(pad,4);
|
||||||
|
pad_code = CHK_ALIGNED((ph.c_len),4);
|
||||||
|
|
||||||
|
upx_uint decomp_data_start = ih.tx_ptr;
|
||||||
|
|
||||||
|
// set the offset for compressed stuff at the very end of file
|
||||||
|
upx_uint comp_data_start = (decomp_data_start+pad)-ph.c_len+(overlap ? overlap : 0);
|
||||||
|
|
||||||
|
pad = 0;
|
||||||
|
|
||||||
|
if (!opt->psx.no_align)
|
||||||
|
// align the packed file to mode 2 data sector size (2048)
|
||||||
|
pad = CHK_ALIGNED((ph.c_len+pad_code+e_len),2048);
|
||||||
|
|
||||||
|
int entry = (comp_data_start-e_len-pad_code);
|
||||||
|
patchPackHeader(loader,lsize);
|
||||||
|
patch_mips_le32(loader,e_len,"JPEP",MIPS_JP(ih.epc));
|
||||||
|
if (scan_count)
|
||||||
|
patch_mips_le16(loader,e_len,"SC",
|
||||||
|
MIPS_LO(scan_count > 0xfffc ? scan_count >> 3 : scan_count));
|
||||||
|
patch_hi_lo(loader,e_len,"OH","OL",decomp_data_start);
|
||||||
|
// patch_hi_lo(loader,e_len,"LH","LL",ph.u_len+pad_code+pad);
|
||||||
|
patch_hi_lo(loader,e_len,"CH","CL",comp_data_start);
|
||||||
|
patch_hi_lo(loader,e_len,"DH","DL",entry+(e_len-d_len));
|
||||||
|
patch_mips_le16(loader,e_len,"LS",d_len);
|
||||||
|
|
||||||
|
// set the file load address
|
||||||
|
oh.tx_ptr = entry-pad;
|
||||||
|
// set the correct file len in header
|
||||||
|
oh.tx_len = (ph.c_len+e_len+pad+pad_code);
|
||||||
|
// set the code entry
|
||||||
|
oh.epc = entry;
|
||||||
|
|
||||||
|
// write loader + compressed file
|
||||||
|
upx_bytep paddata = ibuf;
|
||||||
|
memset(paddata,0,fdata_size);
|
||||||
|
|
||||||
|
fo->write(&oh,sizeof(oh));
|
||||||
|
|
||||||
|
// id & upx header
|
||||||
|
fo->write(loader+e_len,h_len);
|
||||||
|
// align the ps exe header (mode 2 sector data size)
|
||||||
|
fo->write(paddata,PS_HDR_SIZE-fo->getBytesWritten());
|
||||||
|
if (pad)
|
||||||
|
// align the file
|
||||||
|
fo->write(paddata,pad);
|
||||||
|
// entry
|
||||||
|
fo->write(loader,e_len);
|
||||||
|
if (pad_code)
|
||||||
|
// align the mips runtime code
|
||||||
|
fo->write(paddata,pad_code);
|
||||||
|
fo->write(obuf,ph.c_len);
|
||||||
|
|
||||||
|
// verify
|
||||||
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
|
// finally check the compression ratio
|
||||||
|
if (!checkFinalCompressionRatio(fo))
|
||||||
|
throwNotCompressible();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
|
||||||
|
printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) e_len);
|
||||||
|
printf("%-13s: code entry : %8ld bytes\n", getName(), (long) oh.epc);
|
||||||
|
printf("%-13s: load address : %8ld bytes\n", getName(), (long) oh.tx_ptr);
|
||||||
|
printf("%-13s: section size : %8ld bytes\n", getName(), (long) oh.tx_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackPsx::canUnpack()
|
||||||
|
{
|
||||||
|
if (!readPackHeader(0x400))
|
||||||
|
return false;
|
||||||
|
if (file_size <= (off_t) ph.c_len)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackPsx::unpack(OutputFile *fo)
|
||||||
|
{
|
||||||
|
fdata_size = file_size-PS_HDR_SIZE;
|
||||||
|
ibuf.alloc(file_size);
|
||||||
|
|
||||||
|
fi->seek(0x0,SEEK_SET);
|
||||||
|
fi->readx(&ih,sizeof(ih));
|
||||||
|
fi->seek(PS_HDR_SIZE,SEEK_SET);
|
||||||
|
fi->readx(ibuf,fdata_size);
|
||||||
|
|
||||||
|
// test & restore orig exec hdr
|
||||||
|
if (ih.ih_csum != upx_adler32(&ih.ih_bkup,IH_BKUP))
|
||||||
|
throwCantUnpack("file is possibly modified/hacked/protected; take care!");
|
||||||
|
|
||||||
|
memcpy(&oh, &ih, sizeof(ih));
|
||||||
|
memcpy(&oh.epc, &ih.ih_bkup, IH_BKUP);
|
||||||
|
|
||||||
|
// clear backup and checksum of header
|
||||||
|
memset(&oh.ih_bkup,0,IH_BKUP+4);
|
||||||
|
|
||||||
|
// check for removed sector alignment
|
||||||
|
upx_uint pad = oh.tx_len-ph.u_len;
|
||||||
|
|
||||||
|
obuf.allocForUncompression(ph.u_len+pad);
|
||||||
|
memset(obuf,0,obuf.getSize());
|
||||||
|
|
||||||
|
// decompress
|
||||||
|
decompress(ibuf+(fdata_size-ph.c_len),obuf);
|
||||||
|
|
||||||
|
// write decompressed file
|
||||||
|
if (fo)
|
||||||
|
{
|
||||||
|
fo->write(&oh,sizeof(oh));
|
||||||
|
memset(ibuf,0,fdata_size);
|
||||||
|
fo->write(ibuf,PS_HDR_SIZE-fo->getBytesWritten());
|
||||||
|
fo->write(obuf,ph.u_len+pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et:nowrap
|
vi:ts=4:et:nowrap
|
||||||
*/
|
*/
|
||||||
|
|||||||
+21
-34
@@ -20,29 +20,14 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __UPX_P_PSX_H
|
#ifndef __UPX_P_PSX_H
|
||||||
#define __UPX_P_PSX_H
|
#define __UPX_P_PSX_H
|
||||||
|
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
#define MIPS_HI(a) (((a)>>16)/*+((a&0x8000)>>15)*/)
|
|
||||||
#define MIPS_LO(a) (a&0xffff)
|
|
||||||
#define MIPS_JP(a) ((0x08<<24)|((a&0xfffffff)>>2))
|
|
||||||
#define CHK_ALIGNED(a,b) (b-(a%b))
|
|
||||||
|
|
||||||
#define PS_HDR_SIZE 2048 //one cd sector in bytes
|
|
||||||
#define PS_HDR 16
|
|
||||||
|
|
||||||
#define HDR_SIZE (sizeof(p_hdr_t))
|
|
||||||
#define VERSION_ID (sizeof(UPX_VERSION_STRING))
|
|
||||||
|
|
||||||
#define PS_MAX_SIZE 0x1e8000
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// psx/exe
|
// psx/exe
|
||||||
@@ -52,7 +37,7 @@ class PackPsx : public Packer
|
|||||||
{
|
{
|
||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackPsx(InputFile *f) : super(f) { }
|
PackPsx(InputFile *f);
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 11; }
|
||||||
virtual int getFormat() const { return UPX_F_PSX_EXE; }
|
virtual int getFormat() const { return UPX_F_PSX_EXE; }
|
||||||
virtual const char *getName() const { return "psx/exe"; }
|
virtual const char *getName() const { return "psx/exe"; }
|
||||||
@@ -71,17 +56,6 @@ protected:
|
|||||||
virtual int patch_mips_le32(void *b, int blen, const void *old, unsigned new_);
|
virtual int patch_mips_le32(void *b, int blen, const void *old, unsigned new_);
|
||||||
virtual int patch_hi_lo(void *b, int blen, const void *old_hi, const void *old_lo, unsigned new_);
|
virtual int patch_hi_lo(void *b, int blen, const void *old_hi, const void *old_lo, unsigned new_);
|
||||||
|
|
||||||
#if 0
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
upx_byte id[VERSION_ID];
|
|
||||||
upx_byte ph_hdr[32];
|
|
||||||
LE32 hdr_adler;
|
|
||||||
exec_hdr_t exec_bkup;
|
|
||||||
}
|
|
||||||
upx_hdr_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct psx_exe_t
|
struct psx_exe_t
|
||||||
{
|
{
|
||||||
char id[8];
|
char id[8];
|
||||||
@@ -99,16 +73,28 @@ protected:
|
|||||||
LE32 sd_len;
|
LE32 sd_len;
|
||||||
LE32 sp,fp,gp0,ra,k0;
|
LE32 sp,fp,gp0,ra,k0;
|
||||||
char origin[60];
|
char origin[60];
|
||||||
char pad[14];
|
// some safety space after that
|
||||||
};
|
char pad[8];
|
||||||
|
// i'll place the backup of the original
|
||||||
|
// execution file structure here (epc - sd_len)
|
||||||
|
LE32 ih_bkup[10];
|
||||||
|
// plus checksum for the backup
|
||||||
|
LE32 ih_csum;
|
||||||
|
// here will find the id & the upx header it's place.
|
||||||
|
// btw only the 'epc - sd_len' entries init the executable.
|
||||||
|
// so stuff placed here will not load and waste memory.
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct psx_exe_t ih, oh;
|
psx_exe_t ih, oh;
|
||||||
|
|
||||||
upx_uint overlap;
|
upx_uint overlap;
|
||||||
upx_uint scan_count;
|
upx_uint scan_count;
|
||||||
|
|
||||||
upx_uint file_data_size;
|
// filesize-PS_HDR_SIZE
|
||||||
upx_uint right_file_size;
|
upx_uint fdata_size;
|
||||||
|
// calculated filesize
|
||||||
|
upx_uint cfile_size;
|
||||||
|
|
||||||
MemBuffer pad_data;
|
MemBuffer pad_data;
|
||||||
};
|
};
|
||||||
@@ -121,3 +107,4 @@ protected:
|
|||||||
vi:ts=4:et
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -25,7 +25,7 @@
|
|||||||
;
|
;
|
||||||
; mips version by ssg
|
; mips version by ssg
|
||||||
|
|
||||||
;;;;;INCLUDE "mr3k/macros.asm"
|
INCLUDE "mr3k/macros.asm"
|
||||||
|
|
||||||
ORG 0
|
ORG 0
|
||||||
|
|
||||||
@@ -75,13 +75,13 @@ copyloop:
|
|||||||
; __PSXDECO0__
|
; __PSXDECO0__
|
||||||
; __PSXDECOZ__
|
; __PSXDECOZ__
|
||||||
; __PSXN2BD0__
|
; __PSXN2BD0__
|
||||||
;;;;;INCLUDE "mr3k/n2b_d32.asm"
|
INCLUDE "mr3k/n2b_d32.asm"
|
||||||
; __PSXN2BDZ__
|
; __PSXN2BDZ__
|
||||||
; __PSXN2DD0__
|
; __PSXN2DD0__
|
||||||
;;;;;INCLUDE "mr3k/n2d_d32.asm"
|
INCLUDE "mr3k/n2d_d32.asm"
|
||||||
; __PSXN2DDZ__
|
; __PSXN2DDZ__
|
||||||
; ;_PSXN2ED0__
|
; ;_PSXN2ED0__
|
||||||
; ;;;;;INCLUDE "mr3k/n2e_d32.asm"
|
; INCLUDE "mr3k/n2e_d32.asm"
|
||||||
; ;_PSXN2EDZ__
|
; ;_PSXN2EDZ__
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user