summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile36
-rw-r--r--int2tap.19
-rw-r--r--int2tap.c132
-rw-r--r--intel.c178
-rw-r--r--intel.h54
-rw-r--r--tap.c171
-rw-r--r--tap.h50
7 files changed, 616 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index 8a02f77..d4b4cb3 100644
--- a/Makefile
+++ b/Makefile
@@ -18,21 +18,43 @@
#
# -------------------------------------------------------------------------
#
-# $Id: Makefile,v 1.1.1.1 2004-08-20 01:14:42 ianc Exp $
+# $Id: Makefile,v 1.2 2004-08-21 01:15:19 ianc Exp $
#
# CFLAGS assumes that gcc is being used - simply change as required
#
-CFLAGS = -g -Wall -Werror $(DEBUG)
+CFLAGS = -g -Wall -Werror
TARGET = int2tap
+SOURCE = int2tap.c \
+ intel.c \
+ tap.c
-$(TARGET): $(TARGET).c
- $(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c
+OBJECTS = int2tap.o \
+ intel.o \
+ tap.o
-$(TARGET).txt: $(TARGET).1
- nroff -man $(TARGET).1 | sed 's/.//g' > $(TARGET).txt
+$(TARGET): $(OBJECTS)
+ $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS)
clean:
- rm -f $(TARGET) core
+ rm -f $(TARGET) $(OBJECTS) core
+
+depend:
+ make clean
+ makedepend -- $(CFLAGS) $(DEBUG) -- $(SOURCE)
+ if test -e Makefile ; then rm -f Makefile.bak ; fi
+
+# DO NOT DELETE THIS LINE -- make depend depends on it
+
+int2tap.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h
+int2tap.o: /usr/include/machine/ansi.h /usr/include/stdio.h
+int2tap.o: /usr/include/string.h /usr/include/stdarg.h /usr/include/time.h
+int2tap.o: /usr/include/sys/_posix.h /usr/include/errno.h
+intel.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h
+intel.o: /usr/include/machine/ansi.h /usr/include/string.h
+intel.o: /usr/include/stdio.h intel.h
+tap.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h
+tap.o: /usr/include/machine/ansi.h /usr/include/string.h /usr/include/stdio.h
+tap.o: tap.h
diff --git a/int2tap.1 b/int2tap.1
index e8cb4a6..12953b3 100644
--- a/int2tap.1
+++ b/int2tap.1
@@ -1,4 +1,4 @@
-.TH int2tap 1 "20 August 2004"
+.TH int2tap 1
.SH NAME
hex2tap \- Converts an Intel format segment dump to a Spectrum emulator
TAP file.
@@ -20,6 +20,12 @@ TAP file.
takes one or more Intel format segment files \- as produced by an assembler like
.B tpasm(1)
\- and produces a Spectrum compatible tape file (TAP file).
+.P
+The tape file will also optionally include a BASIC loader (see OPTIONS).
+This loader will do a CLEAR to the execution address (see
+.B -a
+in OPTIONS), and then load in the binary files in the same order they were on
+the command line.
.SH OPTIONS
.B int2tap
accepts these switches
@@ -29,7 +35,6 @@ Just produce the binary file. By default
.B int2tap
will generate a TAP file with two files in - a BASIC loader and then the
code itself. This switch disables the generation of the BASIC loader portion.
-disabled if this switch is provided (see USAGE).
.TP
.B \-s
By default
diff --git a/int2tap.c b/int2tap.c
index 68902a2..b2fba26 100644
--- a/int2tap.c
+++ b/int2tap.c
@@ -20,6 +20,8 @@
-------------------------------------------------------------------------
+ $Name$
+
*/
static const char id[]="$Id$";
@@ -30,8 +32,11 @@ static const char id[]="$Id$";
#include <time.h>
#include <errno.h>
+#include "intel.h"
+#include "tap.h"
+
-/* ---------------------------------------- MACROS
+/* ---------------------------------------- GLOBALS
*/
#undef TRUE
#undef FALSE
@@ -39,19 +44,136 @@ static const char id[]="$Id$";
#define TRUE 1
#define FALSE 0
-
-/* ---------------------------------------- TYPES
-*/
+const char *progname;
-/* ---------------------------------------- PROTOS
+/* ---------------------------------------- PRIVATE UTILS
*/
+static void Usage(void)
+{
+ fprintf(stderr,"%s: usage %s [ -b ] [ -s ] [ -a address ] "
+ "output-file input-file ... \n",progname,progname);
+}
/* ---------------------------------------- MAIN
*/
int main(int argc, char *argv[])
{
+ unsigned char mem[0x10000];
+ IntelInfo *info;
+ char *outname;
+ unsigned exec_addr;
+ int bin_only;
+ int split;
+ int addr_defined;
+ int base;
+ int no;
+ int f;
+ int done;
+
+ /* Set program name
+ */
+ if ((progname=strrchr(argv[0],'/')))
+ {
+ progname++;
+ }
+ else
+ {
+ progname=argv[0];
+ }
+
+ /* Set defaults and parse args
+ */
+ addr_defined=FALSE;
+ bin_only=FALSE;
+ split=FALSE;
+
+ done=FALSE;
+ f=1;
+
+ while(f<argc && !done)
+ {
+ if (argv[f][0]!='-')
+ {
+ base=f;
+ done=TRUE;
+ }
+ else
+ {
+ switch(argv[f][1])
+ {
+ case 'b':
+ bin_only=TRUE;
+ break;
+
+ case 's':
+ split=TRUE;
+ break;
+
+ case 'a':
+ if (f>argc-2)
+ {
+ Usage();
+ }
+
+ addr_defined=TRUE;
+
+ exec_addr=(unsigned)strtoul(argv[++f],NULL,0);
+
+ break;
+
+ default:
+ Usage();
+ break;
+ }
+
+ f++;
+ }
+ }
+
+ if (base>=argc-1)
+ {
+ Usage();
+ }
+
+ outname=argv[base++];
+
+ no=argc-base;
+
+ if (!(info=malloc(sizeof *info * no)))
+ {
+ fprintf(stderr,"%s: malloc failed\n",progname);
+ }
+
+ /* Process Intel files
+ */
+ for(f=0;f<no;f++)
+ {
+ if (!IntelLoad(argv[base+f],mem,info+f))
+ {
+ free(info);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Memory altered from 0x%4.4x for 0x%4.4x bytes, base 0x%4.4x\n",
+ info[f].low,info[f].len,info[f].addr);
+ }
+
+ /* TODO: Properly - just a quick test
+ */
+ printf("Creating %s\n",outname);
+
+ if (!TapOpen(outname))
+ {
+ free(info);
+ exit(EXIT_FAILURE);
+ }
+
+ TapWrite(mem,info[0].low,info[0].len,TRUE);
+
+ TapClose();
+
return EXIT_SUCCESS;
}
diff --git a/intel.c b/intel.c
new file mode 100644
index 0000000..3c65adf
--- /dev/null
+++ b/intel.c
@@ -0,0 +1,178 @@
+/*
+
+ int2tap - Convert an Intel segment file to a loadable Spectrum tape file
+
+ Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+*/
+static const char id[]="$Id$";
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "intel.h"
+
+static const char header_id[]=I2T_INTEL_H;
+
+extern const char *progname;
+
+
+/* ---------------------------------------- CONSTANTS
+*/
+#undef TRUE
+#undef FALSE
+
+#define TRUE 1
+#define FALSE 0
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static const unsigned ToHex(char c)
+{
+ if (c>='0' && c<='9')
+ {
+ return c-'0';
+ }
+
+ if (c>='A' && c<='F')
+ {
+ return c-'A'+10;
+ }
+
+ if (c>='a' && c<='f')
+ {
+ return c-'a'+10;
+ }
+
+ return 0;
+}
+
+
+
+/* ---------------------------------------- INTERFACES
+*/
+int IntelLoad(const char *filename,
+ unsigned char mem [0x1000],
+ IntelInfo *info)
+{
+ FILE *fp;
+ char buff[1024];
+ int done;
+ int addr_read;
+ int ret;
+
+ if (!(fp=fopen(filename,"r")))
+ {
+ fprintf(stderr,"%s: Failed to open %s\n",progname,filename);
+ return FALSE;
+ }
+
+ addr_read=FALSE;
+ info->low=0xffff;
+ info->high=0x0000;
+
+ done=FALSE;
+ ret=FALSE;
+
+ while(!done)
+ {
+ if (!fgets(buff,sizeof buff,fp))
+ {
+ fprintf(stderr,"%s: Missing EOF record in %s\n",progname,filename);
+ done=TRUE;
+ }
+
+ if (!done && buff[0]!=':')
+ {
+ fprintf(stderr,"%s: Invalid Intel HEX file %s\n",progname,filename);
+ done=TRUE;
+ }
+
+ if (!done && buff[8]=='1')
+ {
+ done=TRUE;
+ ret=TRUE;
+ }
+
+ if (!done && (buff[8]=='2' || buff[8]=='3'))
+ {
+ fprintf(stderr,"%s: Extended address in Intel HEX file %s\n",
+ progname,filename);
+ done=TRUE;
+ }
+
+ if (!done)
+ {
+ unsigned addr;
+ unsigned len;
+ unsigned f;
+
+ len=ToHex(buff[1])<<4|ToHex(buff[2]);
+
+ addr=ToHex(buff[3])<<12|ToHex(buff[4])<<8|
+ ToHex(buff[5])<<4|ToHex(buff[6]);
+
+ if (!addr_read)
+ {
+ info->addr=addr;
+ addr_read=TRUE;
+ }
+
+ for(f=0;f<len && !done;f++)
+ {
+ unsigned char b;
+
+ if (addr<info->low)
+ {
+ info->low=addr;
+ }
+
+ if (addr>info->high)
+ {
+ info->high=addr;
+ }
+
+ b=ToHex(buff[f*2+9])<<4|ToHex(buff[f*2+10]);
+ mem[addr++]=b;
+
+ if (addr==0)
+ {
+ fprintf(stderr,"%s: Intel HEX file %s has "
+ "wrapped from 0xffff to 0x0000\n",
+ progname,filename);
+ done=TRUE;
+ }
+ }
+ }
+ }
+
+ if (info->low!=0xffff)
+ {
+ info->len=(info->high-info->low)+1;
+ }
+
+ fclose(fp);
+
+ return ret;
+}
+
+
+/* END OF FILE */
diff --git a/intel.h b/intel.h
new file mode 100644
index 0000000..b34ef37
--- /dev/null
+++ b/intel.h
@@ -0,0 +1,54 @@
+/*
+
+ int2tap - Convert an Intel segment file to a loadable Spectrum tape file
+
+ Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+*/
+
+#ifndef I2T_INTEL_H
+#define I2T_INTEL_H "$Id$"
+
+/* ---------------------------------------- TYPES
+*/
+typedef struct
+{
+ unsigned addr;
+ unsigned low;
+ unsigned high;
+ unsigned len;
+} IntelInfo;
+
+/* ---------------------------------------- INTERFACES
+*/
+
+/* Loads an Intel segment file. Returns FALSE for failure.
+ If it works, info.addr is filled with the address of the first byte
+ written from the file and info.low and info.high hold the lowest and
+ highest address written to respectively.
+*/
+int IntelLoad(const char *filename,
+ unsigned char mem [0x1000],
+ IntelInfo *info);
+
+#endif
+
+/* END OF FILE */
diff --git a/tap.c b/tap.c
new file mode 100644
index 0000000..0c9b3c7
--- /dev/null
+++ b/tap.c
@@ -0,0 +1,171 @@
+/*
+
+ int2tap - Convert an Intel segment file to a loadable Spectrum tape file
+
+ Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+*/
+static const char id[]="$Id$";
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "tap.h"
+
+static const char header_id[]=I2T_TAP_H;
+
+
+/* ---------------------------------------- CONSTANTS
+*/
+#undef TRUE
+#undef FALSE
+
+#define TRUE 1
+#define FALSE 0
+
+
+/* ---------------------------------------- TYPES
+*/
+
+
+/* ---------------------------------------- GLOBALS
+*/
+extern const char *progname;
+
+static FILE *fp;
+static int file_no;
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+unsigned char TapWord(unsigned w, unsigned char chk)
+{
+ putc(w&0xff,fp);
+ chk^=w&0xff;
+ putc(w>>8,fp);
+ chk^=w>>8;
+ return chk;
+}
+
+unsigned char TapByte(unsigned char c, unsigned char chk)
+{
+ putc(c,fp);
+ chk^=c;
+ return chk;
+}
+
+unsigned char TapString(char *p, int len, unsigned char chk)
+{
+ while(len--)
+ {
+ chk=TapByte(*p++,chk);
+ }
+
+ return chk;
+}
+
+unsigned char TapStream(const unsigned char p[0x10000],
+ unsigned addr, unsigned len, unsigned char chk)
+{
+ while(len--)
+ {
+ chk=TapByte(p[addr],chk);
+ addr=(addr+1)&0xffff;
+ }
+
+ return chk;
+}
+
+/* ---------------------------------------- INTERFACES
+*/
+
+int TapOpen(const char *filename)
+{
+ file_no=0;
+
+ if (!(fp=fopen(filename,"wb")))
+ {
+ fprintf(stderr,"%s: Failed to create %s\n",progname,filename);
+ }
+
+ return fp!=NULL;
+}
+
+
+void TapWrite(const unsigned char mem[0x1000],
+ unsigned addr, unsigned len, int is_code)
+{
+ char name[11]={0};
+ unsigned char chk;
+
+ sprintf(name,"%10.10d",file_no);
+ file_no=(file_no+1)%10000;
+
+ /* Output file header
+ */
+ chk=TapWord(19,chk);
+ chk=TapByte(0,chk);
+
+ if (is_code)
+ {
+ chk=TapByte(3,chk);
+ }
+ else
+ {
+ chk=TapByte(3,chk);
+ }
+
+ chk=TapString(name,10,chk);
+ chk=TapWord(len,chk);
+
+ if (is_code)
+ {
+ chk=TapWord(addr,chk);
+ chk=TapWord(32768,chk);
+ }
+ else
+ {
+ chk=TapWord(0,chk);
+ chk=TapWord(0,chk);
+ }
+
+ TapByte(chk,0);
+
+ /* Output file data
+ */
+ chk=0;
+
+ chk=TapWord(len+2,chk);
+ chk=TapStream(mem,addr,len,chk);
+ TapByte(chk,0);
+}
+
+
+void TapClose(void)
+{
+ if (fp)
+ {
+ fclose(fp);
+ fp=NULL;
+ }
+}
+
+
+/* END OF FILE */
diff --git a/tap.h b/tap.h
new file mode 100644
index 0000000..38be2c6
--- /dev/null
+++ b/tap.h
@@ -0,0 +1,50 @@
+/*
+
+ int2tap - Convert an Intel segment file to a loadable Spectrum tape file
+
+ Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+*/
+
+#ifndef I2T_TAP_H
+#define I2T_TAP_H "$Id$"
+
+/* ---------------------------------------- INTERFACES
+*/
+
+/* Opens the TAP file for writing. Returns FALSE on failure.
+*/
+int TapOpen(const char *filename);
+
+/* Write a block of memory to the TAP file.
+*/
+void TapWrite(const unsigned char mem[0x1000],
+ unsigned addr,
+ unsigned len,
+ int is_code);
+
+/* Close the TAP file.
+*/
+void TapClose(void);
+
+#endif
+
+/* END OF FILE */