/******************************************************************** * * * PowerPacker DATA file support function V1.1 * * ------------------------------------------- * * (Read Packer.doc for more information) * * * * error = PP_LoadData (file, col, typeofmem, buffer, length, pw) * * with: * * char *file; filename * * UBYTE col; color (see ppdata.h) * * ULONG typeofmem type of memory that will be allocated * * UBYTE **buffer pointer to pointer to buffer * * ULONG *length pointer to buffer length * * char *pw; pointer to password or NULL * * * * NOTE: - After loading you must free the allocated memory: * * DO NOT FORGET !!!!! * * FreeMem (buffer, length); * * - Errors are defined in ppdata.h * * - For encrypted data call first with pw = NULL, then * * if error is PP_CRYPTED you know file is crypted. * * Prompt the user for a password and call again with * * pw pointing to this password. If the password is * * incorrect error is PP_PASSERR, otherwise the file will * * be loaded and decrypted. * * * * Example: * * * * #include * * ... * * * * UBYTE *mymem = NULL; * * ULONG mylen = 0; * * * * err = PP_LoadData ("df0:myfile.pp", DECR_POINTER, * * MEMF_PUBLIC+MEMF_CHIP, &mymem, &mylen, NULL); * * if (err == PP_LOADOK) { * * DoSomething (mymem, mylen); * * FreeMem (mymem, mylen); * * } * * else switch (err) { * * case PP_CRYPTED: * * puts ("File is encrypted !"); * * break; * * case PP_READERR: * * puts ("Loading error !!!"); * * break; * * ... * * } * * * ********************************************************************/ /******************************************************************** * * * 'PP_LoadData' PowerPacker DATA file support function V1.1 * * * * You may use this code for non-commercial purposes provided this * * copyright notice is left intact ! * * * * Copyright (c) Aug 1989 by Nico François * ********************************************************************/ #include #include #include #include #include #include #define SAFETY_MARGIN 64L #define SIZEOF (ULONG)sizeof #define myRead(to,len) if (Read (pp_lock, to, len) != len) {\ pp_FreeStuff(); return (PP_READERR); } struct FileLock *pp_lock; struct FileInfoBlock *pp_FileInfoBlock; UBYTE *pp_filestart; ULONG pp_bufferlen; UWORD pp_coladdr[4] = { 0xf180, 0xf182, 0xf1a2, 0xf102 }; UWORD pp_CalcCheckSum(); ULONG pp_CalcPasskey(); PP_LoadData (pp_file, color, typeofmem, buffer, length, pw) /* Version 1.1 */ char *pp_file; UBYTE color; ULONG typeofmem; UBYTE **buffer; ULONG *length; char *pw; { ULONG hdr, pp_seek; UWORD *decrcol, instr, hicol, locol, pp_passchecksum; ULONG pp_filelen, pp_crunlen, pp_efficiency; UBYTE pp_crunched, pp_crypt = FALSE; extern void pp_DecrunchBuffer(), pp_DecrunchColor(); pp_filestart = NULL; if (!(pp_FileInfoBlock = (struct FileInfoBlock *)AllocMem (SIZEOF(*pp_FileInfoBlock), MEMF_PUBLIC))) return (PP_NOMEMORY); /* Set decruncher color */ decrcol = (UWORD *)pp_DecrunchColor; if (color != 4) { instr = 0x33c9; hicol = 0x00df; locol = pp_coladdr[color]; /* = move.w a1,$dff1xx */ } else instr = hicol = locol = 0x4e71; /* nop */ *decrcol = instr; *(decrcol+1) = hicol; *(decrcol+2) = locol; if (!(pp_lock = (struct FileLock *)Lock (pp_file, ACCESS_READ))) { pp_FreeStuff(); return (PP_LOCKERR); } Examine (pp_lock, pp_FileInfoBlock); UnLock (pp_lock); pp_crunlen = pp_FileInfoBlock->fib_Size; /* read decrunched length */ if (!(pp_lock = (struct FileLock *)Open (pp_file, MODE_OLDFILE))) { pp_FreeStuff(); return (PP_OPENERR); } myRead (&hdr, 4L); /* check if crunched */ if ((hdr == 'PX20' || hdr == 'PP11' || hdr == 'PP20') && (pp_crunlen>16L)) { if (hdr == 'PX20') { if (!pw) { pp_FreeStuff(); return (PP_CRYPTED); } myRead (&pp_passchecksum, 2L); if (pp_CalcCheckSum (pw) != pp_passchecksum) { pp_FreeStuff(); return (PP_PASSERR); } pp_crypt = TRUE; pp_seek = 6L; } else pp_seek = 4L; Seek (pp_lock, pp_crunlen - 4L, OFFSET_BEGINNING); myRead (&pp_filelen, 4L); pp_filelen >>= 8L; pp_crunlen -= 4L + pp_seek; Seek (pp_lock, pp_seek, OFFSET_BEGINNING); myRead (&pp_efficiency, 4L); pp_bufferlen = pp_filelen + SAFETY_MARGIN; pp_crunched = TRUE; } else { Seek (pp_lock, 0L, OFFSET_BEGINNING); pp_bufferlen = pp_filelen = pp_crunlen; pp_crunched = FALSE; } if (!(pp_filestart=(UBYTE *)AllocMem (pp_bufferlen, typeofmem))) { pp_FreeStuff(); return (PP_NOMEMORY); } /* load file */ myRead (pp_filestart, pp_crunlen); Close (pp_lock); FreeMem (pp_FileInfoBlock, SIZEOF(*pp_FileInfoBlock)); if (pp_crunched) { if (pp_crypt) pp_Decrypt (pp_filestart, pp_crunlen-4L, pp_CalcPasskey (pw)); pp_DecrunchBuffer (pp_filestart + pp_crunlen, pp_filestart + SAFETY_MARGIN, pp_efficiency); FreeMem (pp_filestart, SAFETY_MARGIN); pp_filestart += SAFETY_MARGIN; } *buffer = pp_filestart; *length = pp_filelen; return (PP_LOADOK); } pp_FreeStuff() { if (pp_lock) Close (pp_lock); if (pp_filestart) FreeMem (pp_filestart, pp_bufferlen); if (pp_FileInfoBlock) FreeMem (pp_FileInfoBlock, SIZEOF(*pp_FileInfoBlock)); } #asm ; ; PowerPacker Decrunch assembler subroutine V1.1 ; ; call as: ; DecrunchBuffer (endcrun, buffer, efficiency); ; with: ; endcrun : UBYTE * just after last byte of crunched file ; buffer : UBYTE * to memory block to decrunch in ; efficiency: Longword defining efficiency with wich file was crunched ; ; NOTE: ; Decrunch a few bytes higher (safety margin) than the crunched file ; to decrunch in the same memory space. (64 bytes suffice) ; XDEF _pp_DecrunchBuffer XDEF _pp_DecrunchColor XDEF _pp_CalcCheckSum XDEF _pp_CalcPasskey XDEF _pp_Decrypt _pp_DecrunchBuffer: move.l 4(a7),a0 move.l 8(a7),a1 move.l 12(a7),d0 movem.l d1-d7/a2-a6,-(a7) bsr.s Decrunch movem.l (a7)+,d1-d7/a2-a6 rts Decrunch: lea myBitsTable(PC),a5 move.l d0,(a5) move.l a1,a2 move.l -(a0),d5 moveq #0,d1 move.b d5,d1 lsr.l #8,d5 add.l d5,a1 move.l -(a0),d5 lsr.l d1,d5 move.b #32,d7 sub.b d1,d7 LoopCheckCrunch: bsr.s ReadBit tst.b d1 bne.s CrunchedBytes NormalBytes: moveq #0,d2 Read2BitsRow: moveq #2,d0 bsr.s ReadD1 add.w d1,d2 cmp.w #3,d1 beq.s Read2BitsRow ReadNormalByte: move.w #8,d0 bsr.s ReadD1 move.b d1,-(a1) dbf d2,ReadNormalByte cmp.l a1,a2 bcs.s CrunchedBytes rts CrunchedBytes: moveq #2,d0 bsr.s ReadD1 moveq #0,d0 move.b (a5,d1.w),d0 move.l d0,d4 move.w d1,d2 addq.w #1,d2 cmp.w #4,d2 bne.s ReadOffset bsr.s ReadBit move.l d4,d0 tst.b d1 bne.s LongBlockOffset moveq #7,d0 LongBlockOffset: bsr.s ReadD1 move.w d1,d3 Read3BitsRow: moveq #3,d0 bsr.s ReadD1 add.w d1,d2 cmp.w #7,d1 beq.s Read3BitsRow bra.s DecrunchBlock ReadOffset: bsr.s ReadD1 move.w d1,d3 DecrunchBlock: move.b (a1,d3.w),d0 move.b d0,-(a1) dbf d2,DecrunchBlock EndOfLoop: _pp_DecrunchColor: move.w a1,$dff1a2 cmp.l a1,a2 bcs.s LoopCheckCrunch rts ReadBit: moveq #1,d0 ReadD1: moveq #0,d1 subq.w #1,d0 ReadBits: lsr.l #1,d5 roxl.l #1,d1 subq.b #1,d7 bne.s No32Read move.b #32,d7 move.l -(a0),d5 No32Read: dbf d0,ReadBits rts myBitsTable: dc.b $09,$0a,$0b,$0b _pp_CalcCheckSum: move.l 4(a7),a0 moveq #0,d0 moveq #0,d1 sumloop: move.b (a0)+,d1 beq.s exitasm ror.w d1,d0 add.w d1,d0 bra.s sumloop _pp_CalcPasskey: move.l 4(a7),a0 moveq #0,d0 moveq #0,d1 keyloop: move.b (a0)+,d1 beq.s exitasm rol.l #1,d0 add.l d1,d0 swap d0 bra.s keyloop exitasm: rts _pp_Decrypt: move.l 4(a7),a0 move.l 8(a7),d1 move.l 12(a7),d0 move.l d2,-(a7) addq.l #3,d1 lsr.l #2,d1 subq.l #1,d1 encryptloop: move.l (a0),d2 eor.l d0,d2 move.l d2,(a0)+ dbf d1,encryptloop move.l (a7)+,d2 rts #endasm