Example #1
0
File: hio.c Project: kacmem/zxtune
uint32 hio_read24b(HIO_HANDLE *h)
{
	if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) {
		return read24b(h->f);
	} else {
		ptrdiff_t can_read = CAN_READ(h);
		if (can_read >= 3) {
			uint32 n = readmem24b(h->start + h->pos);
			h->pos += 3;
			return n;
		} else {
			h->pos += can_read;
			return EOF;
		}
	}
}
Example #2
0
static int decrunch_pp(FILE *f, FILE *fo)
{
    uint8 *packed /*, *unpacked */;
    int plen, unplen;
    struct stat st;

    if (fo == NULL)
        goto err;

    if (fstat(fileno(f), &st) < 0)
	goto err;

    plen = st.st_size;
    //counter = 0;

    /* Amiga longwords are only on even addresses.
     * The pp20 data format has the length stored in a longword
     * after the packed data, so I guess a file that is not even
     * is probl not a valid pp20 file. Thanks for Don Adan for
     * reminding me on this! - mld
     */

    if ((plen != (plen / 2) * 2)) {    
	 /*fprintf(stderr, "filesize not even\n");*/
         goto err;
    }

    packed = malloc(plen);
    if (packed == NULL) {
	 /*fprintf(stderr, "can't allocate memory for packed data\n");*/
	 goto err;
    }

    if (fread(packed, 1, plen, f) != plen) {
         goto err1;
    }

    /* Hmmh... original pp20 only support efficiency from 9 9 9 9 up to 9 10 12 13, afaik
     * but the xfd detection code says this... *sigh*
     *
     * move.l 4(a0),d0
     * cmp.b #9,d0
     * blo.b .Exit
     * and.l #$f0f0f0f0,d0
     * bne.s .Exit
     */	 

    if (((packed[4] < 9) || (packed[5] < 9) || (packed[6] < 9) || (packed[7] < 9))) {
	 /*fprintf(stderr, "invalid efficiency\n");*/
         goto err1;
    }


    if (((readmem24b(packed +4)  * 256  + packed[7]) & 0xf0f0f0f0) != 0 ) {
	 /*fprintf(stderr, "invalid efficiency(?)\n");*/
         goto err1;
    }

    unplen = readmem24b(packed + plen - 4);
    if (!unplen) {
	 /*fprintf(stderr, "not a powerpacked file\n");*/
         goto err1;
    }
    
    if (ppdepack (packed, plen, fo) == -1) {
	 /*fprintf(stderr, "error while decrunching data...");*/
         goto err1;
    }
     
    free (packed);

    return 0;

err1:
    free(packed);
err:
    return -1;
}
Example #3
0
static int ppdepack(uint8 *data, size_t len, FILE *fo)
{
  /* PP FORMAT:
   *      1 longword identifier           'PP20' or 'PX20'
   *     [1 word checksum (if 'PX20')     $ssss]
   *      1 longword efficiency           $eeeeeeee
   *      X longwords crunched file       $cccccccc,$cccccccc,...
   *      1 longword decrunch info        'decrlen' << 8 | '8 bits other info'
   */
  int success=0;
  uint8 *output /*, crypted*/;
  uint32 outlen;

  if (len < 16) {
    /*fprintf(stderr, "File is too short to be a PP file (%u bytes)\n", len);*/
    return -1;
  }

  if (data[0]=='P' && data[1]=='P' && data[2]=='2' && data[3]=='0') {
    if (len & 0x03) {
      /*fprintf(stderr, "File length is not a multiple of 4\n");*/
      return -1;
    }
    /*crypted = 0;*/
  }
#if 0
  else if (data[0]=='P' && data[1]=='X' && data[2]=='2' && data[3]=='0') {
    if ((len-2) & 0x03) {
      /*fprintf(stderr, "(file length - 2) is not a multiple of 4\n");*/
      return -1;
    }
    crypted = 1;
  }
#endif
  else {
    /*fprintf(stderr, "File does not have the PP signature\n");*/
    return -1;
  }

  outlen = readmem24b(data + len - 4);

  /* fprintf(stderr, "decrunched length = %u bytes\n", outlen); */

  output = (uint8 *) malloc(outlen);
  if (output == NULL) {
    /*fprintf(stderr, "out of memory!\n");*/
    return -1;
  }

  /* if (crypted == 0) { */
    /*fprintf(stderr, "not encrypted, decrunching anyway\n"); */
    if (ppDecrunch(&data[8], output, &data[4], len-12, outlen, data[len-1])) {
      /* fprintf(stderr, "Decrunch successful! "); */
      savefile(fo, (void *) output, outlen);
    } else {
      success=-1;
    } 
  /*} else {
    success=-1;
  }*/
  free(output);
  return success;
}