/**************************************************************************
 *
 * FILE  crc.c
 * Written by Daniel Kahlin <daniel@kahlin.net>
 * $Id: crc.c,v 1.4 2005-12-26 12:31:30 tlr Exp $
 *
 * DESCRIPTION
 *   This is a C-language implementation of the ROM checksumming algorithm
 *   for the DTV V2, as found in the file "DTVTEST5".
 *   Use this to verify your ROM dumps.
 *
 * HISTORY
 *   0.1 (20051226) tlr - first public version.
 *
 * LICENSE
 *   crc - C64 DTV ROM CRC calculator
 *
 *   Copyright (c) 2005 Daniel Kahlin <daniel@kahlin.net>
 *   All rights reserved.
 * 
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. Neither the names of the copyright holders nor the names of their
 *      contributors may be used to endorse or promote products derived 
 *      from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   ``AS IS´´ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define PROGRAM "crc"
#define VERSION "0.1"

uint32_t tab[256];

int main(int argc, char *argv[])
{
    FILE *fp;
    uint8_t inbuf[0x800];
    uint8_t eorbuf[0x800];
    uint32_t offs;
    int i,j;
    uint32_t s,e;
    char *filename=argv[1];

    if (argc<2) {
	fprintf(stderr,
PROGRAM " " VERSION ": C64 DTV ROM CRC calculator\n"
"Copyright (c) 2005 Daniel Kahlin <daniel@kahlin.net>\n"
"Written by Daniel Kahlin <daniel@kahlin.net>\n"
"http://www.kahlin.net/daniel/dtv/\n"
"\n"
"usage: " PROGRAM " <filename>\n"
"\n"
"This progam calculates the pseudo CRC as calculated by the \"DTVTEST5\"\n"
"included in the C64 DTV V2 ROM. Use this to verify your ROM dumps.\n"
        );
	exit(-1);
    }

    /* 
     * create tables 
     * (replicates the routine at $0a94)
     */
    for (i=0; i<256; ++i) {
	e=((uint32_t)i)&0xff;
	for (j=0; j<8; ++j) {
	    e=(e>>1) ^ ((e&0x0000001)?0xedb88320:0);
	}
	tab[i]=e;
    }


    /* 
     * clear the eor accumulator buffer.
     * (replicates the routine at $0a7d)
     */
    for (i=0x000; i<0x800; ++i)
	eorbuf[i]=0x00;

    /* 
     * read the file
     */
    fp=fopen(filename,"rb");
    if (!fp) {
	fprintf(stderr,PROGRAM ": couldn't open file\n");
	exit(-1);
    }
    offs=0;
    while (offs < 0x200000) {

	/* 
	 * read data (this is originally done by using DMA at $0ad8)
	 */
	fread(inbuf, 0x800, 1, fp);

	if (feof(fp)) {
	    fprintf(stderr,PROGRAM ": premature end of file\n");
	    exit(-1);
	}

	/*
	 * eor with previous 0x800 bytes
	 * (done by the generated code at $3000)
	 */
	for (i=0; i<0x800; ++i)
	    eorbuf[i]^=inbuf[i];

	/* next block */
	offs+=0x800;
    }
    fclose(fp);


    /*
     * finish up
     * (replicates the routine at $0a39)
     */
    s=0xffffffff;
    for (i=0; i<0x800; ++i) {
	uint8_t tmp=eorbuf[i];
	tmp ^= s & 0xff;
	s = (s>>8) ^ tab[tmp];
    }
    s^=0xffffffff;

    /*
     * Done, print checksum and exit
     */
    printf("CRC: %08X\n",s);
    
    exit(0);
}


/* eof */
