/*
 * cdimage.c
 * Layered data source for CD images in raw mode.
 *
 * Copyright (c) 2003 Christoph Pfisterer
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 */

#include "global.h"

/*
 * types
 */

typedef struct cdimage_source {
  SOURCE c;
  u8 off;
} CDIMAGE_SOURCE;

/*
 * helper functions
 */

static SOURCE *init_cdimage_source(SOURCE *foundation, u8 offset);
static int read_block_cdimage(SOURCE *s, u8 pos, void *buf);

/*
 * cd image detection
 */

static unsigned char syncbytes[12] =
  { 0, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 0 };

void detect_cdimage(SECTION *section, int level)
{
  int mode, off;
  unsigned char *buf;
  SOURCE *s;

  if (get_buffer(section, 0, 2352, (void **)&buf) < 2352)
    return;

  /* check sync bytes as signature */
  if (memcmp(buf, syncbytes, 12) != 0)
    return;

  /* get mode of the track -- this determines sector layout */
  mode = buf[15];
  if (mode == 1) {
    /* standard data track */
    print_line(level, "Raw CD image, Mode 1");
    off = 16;
  } else if (mode == 2) {
    /* free-form track, assume XA form 1 */
    print_line(level, "Raw CD image, Mode 2, assuming Form 1");
    off = 24;
  } else
    return;

  /* create and analyze wrapped source */
  s = init_cdimage_source(section->source, section->pos + off);
  analyze_source(s, level);
  close_source(s);

  /* don't run other analyzers */
  stop_detect();
}

/*
 * initialize the cd image source
 */

static SOURCE *init_cdimage_source(SOURCE *foundation, u8 offset)
{
  CDIMAGE_SOURCE *src;

  src = (CDIMAGE_SOURCE *)malloc(sizeof(CDIMAGE_SOURCE));
  if (src == NULL)
    bailout("Out of memory");
  memset(src, 0, sizeof(CDIMAGE_SOURCE));

  if (foundation->size_known) {
    src->c.size_known = 1;
    src->c.size = ((foundation->size - offset + 304) / 2352) * 2048;
    /* TODO: pass the size in from the SECTION record and use it */
  }
  src->c.blocksize = 2048;
  src->c.foundation = foundation;
  src->c.read_block = read_block_cdimage;
  src->c.close = NULL;
  src->off = offset;

  return (SOURCE *)src;
}

/*
 * raw read
 */

static int read_block_cdimage(SOURCE *s, u8 pos, void *buf)
{
  SOURCE *fs = s->foundation;
  u8 filepos;

  /* translate position */
  filepos = (pos / 2048) * 2352 + ((CDIMAGE_SOURCE *)s)->off;

  /* read from lower layer */
  if (get_buffer_real(fs, filepos, 2048, buf, NULL) < 2048)
    return 0;

  return 1;
}

/* EOF */


syntax highlighted by Code2HTML, v. 0.9.1