view loadtools/srecreader.c @ 828:502aec4c1e8e

fc-buzplay: implement playt command for PWT melodies
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 30 May 2021 20:54:02 +0000
parents e7502631a0f9
children
line wrap: on
line source

/*
 * This module contains the functions for reading S-record files.
 */

#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
#include <strings.h>
#include "srecreader.h"

open_srec_file(sr)
	struct srecreader *sr;
{
	sr->openfile = fopen(sr->filename, "r");
	if (!sr->openfile) {
		perror(sr->filename);
		return(-1);
	}
	sr->lineno = 0;
	return(0);
}

static
srec2bin(sr, asciiline)
	struct srecreader *sr;
	char *asciiline;
{
	register int i, l, b;

	l = decode_hex_byte(asciiline + 2);
	if (l < 1) {
		fprintf(stderr, "%s line %d: S-record length octet is bad\n",
			sr->filename, sr->lineno);
		return(-1);
	}
	sr->record[0] = l;
	for (i = 1; i <= l; i++) {
		b = decode_hex_byte(asciiline + i*2 + 2);
		if (b < 0) {
			fprintf(stderr,
				"%s line %d: S-record hex decode error\n",
				sr->filename, sr->lineno);
			return(-1);
		}
		sr->record[i] = b;
	}
	return(0);
}

static
srec_cksum(sr)
	struct srecreader *sr;
{
	u_char accum;
	register int i, len;

	len = sr->record[0] + 1;
	accum = 0;
	for (i = 0; i < len; i++)
		accum += sr->record[i];
	if (accum != 0xFF) {
		fprintf(stderr, "%s line %d: bad S-record checksum\n",
			sr->filename, sr->lineno);
		return(-1);
	}
	return(0);
}

read_s_record(sr)
	struct srecreader *sr;
{
	char asciiline[1024];

	if (!fgets(asciiline, sizeof asciiline, sr->openfile)) {
		fprintf(stderr, "%s: premature EOF after %d S-records\n",
			sr->filename, sr->lineno);
		return(-1);
	}
	sr->lineno++;
	if (asciiline[0] != 'S' || !isdigit(asciiline[1])) {
		fprintf(stderr, "%s line %d: S-record expected\n",
			sr->filename, sr->lineno);
		return(-1);
	}
	sr->record_type = asciiline[1];
	if (srec2bin(sr, asciiline) < 0)
		return(-1);
	return srec_cksum(sr);
}

s3s7_get_addr_data(sr)
	struct srecreader *sr;
{
	if (sr->record[0] < 5) {
		fprintf(stderr, "%s line %d: S%c record is too short\n",
			sr->filename, sr->lineno, sr->record_type);
		return(-1);
	}
	sr->datalen = sr->record[0] - 5;
	sr->addr = ((uint32_t)sr->record[1] << 24) |
		   ((uint32_t)sr->record[2] << 16) |
		   ((uint32_t)sr->record[3] << 8) |
		    (uint32_t)sr->record[4];
	return(0);
}