💾 Archived View for uscoffings.net › retro-computing › systems › TI994a › x99tape › x99tape_src › ti… captured on 2022-06-04 at 01:07:39.
View Raw
More Information
-=-=-=-=-=-=-
/*
Portable TI99 tape encoder/decoder
tifiles.c: Code to read and write TI99 data files.
Currently supports TIFILE format, though I intend to support V9T9 FIAD,
and native (header-less) binary and text files.
Raphael Nabet 2002
#include <stdio.h>
#include <string.h>
#include "common.h"
#include "tifiles.h"
/* 0: raw binary format, 1: TIFILE */
#define FORMAT 1
error_t open_tifile_in(FILE *handle, tifile_in_t *tifile, ftype_t default_type, unsigned int default_reclen)
{
#if FORMAT == 0
/* raw binary format */
int file_len;
tifile->handle = handle;
tifile->type = default_type;
/* raw binary format */
if (default_type == ftype_program)
tifile->reclen = 64;
else
{
if ((default_reclen < 0) || (default_reclen > 192))
return invalid_parameters;
if (default_reclen == 0)
return cant_auto_record_len;
tifile->reclen = default_reclen;
}
/* compute file len */
{
int increment;
char buf[16384];
file_len = 0;
do
{
increment = fread(buf, 1, sizeof(buf), handle);
file_len += increment;
}
while (increment == sizeof(buf));
if (ferror(handle))
return read_error;
rewind(handle);
}
if (file_len % /*tifile->reclen*/ ((tifile->reclen + 63) & ~63))
return invalid_record_len;
//file_len_in_records = file_len / /*record_len*/ ((record_len + 63) & ~63);
return no_error;
#else
/* tifile format */
tifile_header header;
int recspersec;
(void) default_type;
(void) default_reclen;
tifile->handle = handle;
if (! fread(&header, sizeof(header), 1, handle))
return read_error;
if (memcmp(header.tifiles, "\7TIFILES", 8))
return invalid_tifile_format;
tifile->secsused = (header.secsused_MSB << 8) | header.secsused_LSB;
tifile->eof = header.eof;
if (header.flags & fdr99_f_program)
{
tifile->type = ftype_program;
tifile->reclen = 64; /* no record, but, in order to write the tape, we read data in chunks of 64 bytes */
if (tifile->eof)
tifile->fixrecs = (tifile->secsused-1)*4 + (tifile->eof+63)/64;
else
tifile->fixrecs = tifile->secsused*4;
}
else
{
tifile->type = ftype_data;
/* check that the file does not have variable lenght records */
if (header.flags & fdr99_f_var)
return unsupported_tifile_format;
tifile->reclen = header.reclen;
/* check record size */
if (tifile->reclen == 0)
return invalid_tifile_format;
if (tifile->reclen > 192)
return unsupported_tifile_format;
recspersec = 256 / tifile->reclen;
if (recspersec != header.recspersec)
return invalid_tifile_format;
if (tifile->eof % tifile->reclen)
return invalid_tifile_format;
tifile->fixrecs = (header.fixrecs_MSB << 8) | header.fixrecs_LSB;
if (tifile->fixrecs != (tifile->eof ? ((tifile->secsused-1)*recspersec + tifile->eof/tifile->reclen)
: (tifile->secsused*recspersec)))
return invalid_tifile_format;
}
tifile->cursec = 0;
tifile->curpos = 0;
return no_error;
#endif
}
error_t tifile_read(unsigned char *dest, tifile_in_t *tifile)
{
#if FORMAT == 0
/* raw binary format */
if (! fread(dest, /*tifile->reclen*/ ((tifile->reclen + 63) & ~63), 1, tifile->handle))
return read_error; /* read error, or unexpected eof */
return no_error;
#else
int i;
/* tifile format */
if (tifile->curpos+tifile->reclen > 256)
{
if (fseek(tifile->handle, 256-tifile->curpos, SEEK_CUR))
return read_error;
tifile->curpos = 0;
tifile->cursec++;
}
if (tifile->cursec >= tifile->secsused)
return eof_error;
if (tifile->type == ftype_program)
{
if ((tifile->eof) ? ((tifile->cursec == (tifile->secsused-1))
&& (tifile->curpos >= tifile->eof))
: (tifile->cursec == tifile->secsused))
/* eof */
return eof_error;
else if ((tifile->eof) && (tifile->cursec == (tifile->secsused-1))
&& (tifile->curpos+64 > tifile->eof))
{ /* there is less than 64 bytes of data left */
if (! fread(dest, tifile->eof-tifile->curpos, 1, tifile->handle))
return read_error; /* read error, or unexpected eof */
for (i=tifile->eof-tifile->curpos; i<64; i++)
dest[i] = 0;
tifile->curpos = tifile->eof;
}
else
{ /* read one 64-byte chunk */
if (! fread(dest, 64, 1, tifile->handle))
return read_error; /* read error, or unexpected eof */
tifile->curpos += tifile->reclen;
}
}
else
{
/* check for eof */
if ((tifile->cursec == (tifile->secsused-1))
&& (tifile->curpos+tifile->reclen > tifile->eof))
return eof_error;
if (! fread(dest, tifile->reclen, 1, tifile->handle))
return read_error; /* read error, or unexpected eof */
tifile->curpos += tifile->reclen;
}
return no_error;
#endif
}
error_t open_tifile_out(FILE *handle, tifile_out_t *tifile, ftype_t type, unsigned int reclen)
{
/* tifile format */
int i;
tifile->handle = handle;
tifile->type = type;
switch (type)
{
case ftype_program:
tifile->reclen = 64; /* no record, but, in order to write the tape, we read data in chunks of 64 bytes */
break;
case ftype_data:
tifile->reclen = reclen;
/* check record size */
/*if (tifile->reclen == 0)
return invalid_parameters;*/
if (tifile->reclen > 192)
return invalid_parameters;
break;
}
for (i=0; i<128; i++)
if (putc(0, tifile->handle) == EOF)
return write_error;
tifile->fixrecs = 0;
tifile->cursec = 0;
tifile->curpos = 0;
return no_error;
}
error_t tifile_write(const unsigned char *src, tifile_out_t *tifile)
{
#if FORMAT == 0
/* raw binary format */
if (! fwrite(src, /*tifile->reclen*/ ((tifile->reclen + 63) & ~63), 1, tifile->handle))
return write_error;
return no_error;
#else
int i;
/* tifile format */
if (tifile->curpos+tifile->reclen > 256)
{
for (i=0; i<256-tifile->curpos; i++)
if (putc(0, tifile->handle) == EOF)
return write_error;
tifile->curpos = 0;
tifile->cursec++;
}
if (tifile->type == ftype_program)
{
/* write one 64-byte chunk */
if (! fwrite(src, 64, 1, tifile->handle))
return write_error;
tifile->curpos += tifile->reclen;
}
else
{
/* write one record */
if (! fwrite(src, tifile->reclen, 1, tifile->handle))
return write_error;
tifile->curpos += tifile->reclen;
tifile->fixrecs++;
}
return no_error;
#endif
}
error_t close_tifile_out(tifile_out_t *tifile)
{
#if FORMAT == 0
/* raw binary format */
(void) tifile;
/*fclose(tifile->handle);*/
return no_error;
#else
tifile_header header;
int secsused;
error_t error = no_error;
int i;
if (tifile->curpos == 256)
{
tifile->curpos = 0;
tifile->cursec++;
}
if (tifile->curpos)
for (i=0; i<256-tifile->curpos; i++)
if (putc(0, tifile->handle) == EOF)
return write_error;
rewind(tifile->handle);
memset(&header, 0, sizeof(header));
memcpy(header.tifiles, "\7TIFILES", 8);
secsused = (tifile->curpos) ? tifile->cursec+1 : tifile->cursec;
header.secsused_MSB = secsused >> 8;
header.secsused_LSB = secsused & 0xff;
header.flags = (tifile->type == ftype_program) ? fdr99_f_program : 0;
header.recspersec = (tifile->type == ftype_program) ? 0 : (256 / tifile->reclen);
header.eof = tifile->curpos;
header.reclen = (tifile->type == ftype_program) ? 0 : tifile->reclen;
header.fixrecs_MSB = tifile->fixrecs >> 8;
header.fixrecs_LSB = tifile->fixrecs & 0xff;
if (! fwrite(&header, sizeof(header), 1, tifile->handle))
error = write_error;
/*fclose(tifile->handle);*/
return error;
#endif
}