Logo Search packages:      
Sourcecode: c2n version File versions  Download package

encode.c

Go to the documentation of this file.
/**
 * @file encode.c
 * C2N pulse stream encoder
 * @author Marko Mäkelä (msmakela@nic.funet.fi)
 */

/* Copyright © 2001 Marko Mäkelä.

   This file is part of C2N, a program for processing data tapes in
   Commodore C2N format.

   C2N is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   C2N is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

#include <stdio.h>
#include <stdlib.h>

#include "c2n.h"
#include "encode.h"

/** The pulse writer */
00034 static pulse_w_t enc_wr;

/**
 * Encode a stream of synchronization pulses
 * @param count   number of pulses
 */
static void
00041 encodeSync (unsigned count)
{
  if (verbose)
    fprintf (stderr, "encoding a sync mark (%u pulses)\n", count);
  while (count--)
    (*enc_wr) (Short);
}

/**
 * Encode a bit
 * @param b the bit to be encoded
 */
static void
00054 encodeBit (unsigned b)
{
  if (b) {
    (*enc_wr) (Medium);
    (*enc_wr) (Short);
  }
  else {
    (*enc_wr) (Short);
    (*enc_wr) (Medium);
  }
}

/**
 * Encode a byte marker
 */
static void
00070 encodeMarker (void)
{
  (*enc_wr) (Long);
  (*enc_wr) (Medium);
}

/**
 * Encode a byte marker and a byte
 * @param c the byte to be encoded
 */
static void
00081 encodeByte (unsigned char c)
{
  register unsigned i, parity;

  encodeMarker ();

  for (parity = 1, i = 8; i--; c >>= 1) {
    encodeBit (c & 1);
    if (c & 1)
      parity = !parity;
  }

  encodeBit (parity);
}

/**
 * Encode both copies of a data block
 * @param buf     the data buffer
 * @param size    length of the data in bytes
 */
static void
00102 encodeBlock (const char* buf, unsigned size)
{
  unsigned i;
  /** data checksum */
  unsigned chk = 0;

  if (verbose)
    fprintf (stderr, "encoding %u bytes (1st copy)\n", size);

  for (i = 0x89; i > 0x80; )
    encodeByte (i--);

  for (i = 0; i < size; i++) {
    chk ^= buf[i];
    encodeByte (buf[i]);
  }

  encodeByte (chk);
  (*enc_wr) (Long);
  encodeSync (80);

  if (verbose)
    fprintf (stderr, "encoding %u bytes (2nd copy)\n", size);

  for (i = 9; i; )
    encodeByte (i--);

  for (i = 0; i < size; i++)
    encodeByte (buf[i]);

  encodeByte (chk);
  (*enc_wr) (Long);
  encodeSync (79);
}

/**
 * Encode both copies of a data block in Commodore 264 format
 * @param buf     the data buffer
 * @param size    length of the data in bytes
 */
static void
00143 encode264Block (const char* buf, unsigned size)
{
  unsigned i;
  /** data checksum */
  unsigned chk = 0;

  if (verbose)
    fprintf (stderr, "encoding %u bytes (1st copy)\n", size);

  for (i = 0x89; i > 0x80; )
    encodeByte (i--);

  for (i = 0; i < size; i++) {
    chk ^= buf[i];
    encodeByte (buf[i]);
  }

  encodeByte (chk);
  (*enc_wr) (Medium);
  encodeSync (437);

  if (verbose)
    fprintf (stderr, "encoding %u bytes (2nd copy)\n", size);

  for (i = 9; i; )
    encodeByte (i--);

  for (i = 0; i < size; i++)
    encodeByte (buf[i]);

  encodeByte (chk);
  (*enc_wr) (Medium);
  encodeSync (192);
}

/**
 * Encode both copies of a data block
 * @param buf     the data buffer
 * @param size    length of the data in bytes
 * @param plus4   flag: encode in Commodore 264 series format
 */
static void
00185 encBlock (const char* buf, unsigned size, unsigned plus4)
{
  if (plus4)
    encode264Block (buf, size);
  else
    encodeBlock (buf, size);
}

/** Pulse stream encoder
 * @param in      the data stream
 * @param err     the error reporter
 * @param wr      the pulse stream writer
 * @param begin   number of initial synchronization pulses
 * @param intra   number of intra-block synchronization pulses
 * @param plus4   flag: encode in Commodore 264 series format
 * @return  number of blocks written; 0 on failure
 */
static unsigned
00203 enc (FILE* in, pulse_error_t err, pulse_w_t wr,
     unsigned begin, unsigned intra, unsigned plus4)
{
  /** current block */
  unsigned block;
  enc_wr = wr;

  for (block = 0;; block++) {
    /** data block header */
    static char header[192];

    if (1 != fread (header, sizeof header, 1, in))
      break;

    switch (*header) {
    case tBasic:
    case tML:
      {
      /** program data buffer */
      char* buf;
      /** program length in bytes */
      unsigned length;
      /** received data length */
      unsigned readlength;

      length = ((unsigned) (unsigned char) header[3]) |
        ((unsigned) (unsigned char) header[4]) << 8;
      length -= ((unsigned) (unsigned char) header[1]) |
        ((unsigned) (unsigned char) header[2]) << 8;
      length &= 0xffff;

      if (!(buf = malloc (length))) {
        fputs ("out of memory\n", stderr);
        return block;
      }

      block++;
      readlength = fread (buf, 1, length, in);

      if (readlength != length) {
        if (!err || (*err) (ShortBlock, block, length - readlength)) {
          free (buf);
          return block;
        }
      }

      if (block)
        (*enc_wr) (Pause);
      encodeSync (begin);
      encBlock (header, sizeof header, plus4);
      (*enc_wr) (Pause);
      encodeSync (intra);
      encBlock (buf, readlength, plus4);
      free (buf);
      }
      break;
    case tDataBlock:
      (*enc_wr) (Pause);
      encodeSync (intra);
      encBlock (header, sizeof header, plus4);
      break;
    case tDataHeader:
    case tEnd:
      if (block)
      (*enc_wr) (Pause);
      encodeSync (begin);
      encBlock (header, sizeof header, plus4);
      break;
    default:
      if (!err || (*err) (Unexpected, block, (unsigned char) *header))
      return 0;
    }
  }

  (*enc_wr) (Pause);
  return block;
}

/** C2N pulse stream encoder
 * @param in      the data stream
 * @param err     the error reporter
 * @param wr      the pulse stream writer
 * @param begin   number of initial synchronization pulses
 * @param intra   number of intra-block synchronization pulses
 * @return  number of blocks written; 0 on failure
 */
unsigned
00290 encode (FILE* in, pulse_error_t err, pulse_w_t wr,
      unsigned begin, unsigned intra)
{
  return enc (in, err, wr, begin, intra, 0);
}

/** Commodore 1531 (Commodore 264 series) pulse stream encoder
 * @param in      the data stream
 * @param err     the error reporter
 * @param wr      the pulse stream writer
 * @param begin   number of initial synchronization pulses
 * @param intra   number of intra-block synchronization pulses
 * @return  number of blocks written; 0 on failure
 */
unsigned
00305 encode264 (FILE* in, pulse_error_t err, pulse_w_t wr,
         unsigned begin, unsigned intra)
{
  return enc (in, err, wr, begin, intra, 1);
}

Generated by  Doxygen 1.6.0   Back to index