diff options
author | B. Watson <urchlay@slackware.uk> | 2024-04-25 00:11:30 -0400 |
---|---|---|
committer | B. Watson <urchlay@slackware.uk> | 2024-04-25 00:11:30 -0400 |
commit | 190dfb3149ebb353b0bde2b108b9282bfcd58dcc (patch) | |
tree | d9a331f6de2764cd35976002a4dd497197b07872 | |
parent | 3286d83fb8ddbcbbcde3adca2b41dbb3339daa02 (diff) | |
download | bw-atari8-tools-190dfb3149ebb353b0bde2b108b9282bfcd58dcc.tar.gz |
blob2xex: made reading stdin work, limit segment size to end at $FFFF, warn if start/end addrs are in ROM, unlink output file on error.
-rw-r--r-- | blob2xex.1 | 26 | ||||
-rw-r--r-- | blob2xex.c | 94 | ||||
-rw-r--r-- | blob2xex.rst | 24 |
3 files changed, 97 insertions, 47 deletions
@@ -40,26 +40,30 @@ blob2xex \fIoutfile\fP [\fB\-v\fP] [\fB\-r\fP \fIrunaddr\fP] [\fB\-l\fP \fIloada .SH DESCRIPTION .sp \fBblob2xex\fP creates an Atari 8\-bit binary load (xex) file from one or -more files of arbitrary data. +more files of arbitrary data. Each input file will become a separate +segment in the binary load file. A run address can be added with the +\fB\-r\fP option. .sp -Each input file \fIrequires\fP a \fB\-l\fP \fIloadaddr\fP option, to set the load -address. Optionally, run and init addresses can be included. Also, -using \fB\-o\fP and \fB\-s\fP, it\(aqs possible to include only part of the -input file. To read from standard input, use \fB\-\fP for the \fIinfile\fP\&. +Each input file \fIrequires\fP a \fB\-l\fP \fIloadaddr\fP option, to set the +load address. Optionally, init addresses can be included, per\-segment +(\fB\-i\fP). Also, using \fB\-o\fP and \fB\-s\fP, it\(aqs possible to include only +part of the input file. To read from standard input, use \fB\-\fP for the +\fIinfile\fP\&. .sp \fIoutfile\fP must be given as the first argument. When multiple input files are used, the resulting .xex file will have multiple -segments. If \fIoutfile\fP already exists, it will be overwritten. Use -\fB\-\fP to write to standard output. If \fIoutfile\fP is a filename that -begins with a \fB\-\fP, prefix it with "./", otherwise it\(aqll be taken as -an option. +segments. If \fIoutfile\fP already exists, it will be overwritten. +If \fIoutfile\fP is a filename that begins with a \fB\-\fP, prefix it with +"./", otherwise it\(aqll be taken as an option. Use \fB\-\fP to write to +standard output. \fBblob2xex\fP will not write output to a terminal; +\fB\-\fP must be used with redirection or a pipe. .sp Addresses, offsets, and sizes may be given in decimal or hex. Hex addresses must be prefixed with either \fB$\fP or \fB0x\fP\&. .SH OPTIONS .sp -A space is required between an option and its argument; use e.g. \fB\-l 0x2000*, -not **\-l0x2000\fP\&. +A space is required between an option and its argument; use e.g. \fB\-l 0x2000\fP, +not \fB\-l0x2000\fP\&. .INDENT 0.0 .TP .B \-l \fIloadaddr\fP @@ -32,7 +32,7 @@ int get_offset(const char *arg) { return (int)got; } -void write_segment( +int write_segment( const char *infile, const char *outfile, int loadaddr, @@ -47,16 +47,16 @@ void write_segment( if(size < 1) { fprintf(stderr, SELF ": invalid size %d (must be >= 1).\n", size); - exit(1); + return(0); } if(strcmp(infile, "-") == 0) { - infh = stdout; + infh = stdin; } else { infh = fopen(infile, "rb"); if(!infh) { - perror(outfile); - exit(1); + fprintf(stderr, SELF ": %s: %s\n", infile, strerror(errno)); + return(0); } } @@ -69,12 +69,18 @@ void write_segment( } else { outfh = fopen(outfile, "wb"); if(!outfh) { - perror(outfile); - exit(-1); + fprintf(stderr, SELF ": %s: %s\n", outfile, strerror(errno)); + return(0); } } } + if(isatty(fileno(outfh))) { + fprintf(stderr, + SELF ": Standard output is a terminal; not writing binary data\n"); + return 0; + } + seg.object = buffer; seg.len = 0; seg.start_addr = loadaddr; @@ -85,11 +91,15 @@ void write_segment( c = getc(infh); if(c < 0) { fprintf(stderr, SELF ": offset extends past EOF on file %s\n", infile); - exit(1); /* TODO: handle this better? */ + return(0); } offset--; } + /* make sure we don't wrap the Atari's address space. */ + if(size + loadaddr > 0xffff) + size = (size - loadaddr) + 1; + /* read <size> bytes, or until EOF (which is not an error) */ while(size) { c = getc(infh); @@ -98,8 +108,22 @@ void write_segment( seg.len++; size--; } + + if(seg.len == 0) { + fprintf(stderr, SELF ": read 0 bytes from %s, xex files cannot contain empty segments.\n", infile); + return(0); + } + seg.end_addr = seg.start_addr + seg.len - 1; + /* if we start/end in ROM, warn, but it's not an error. */ + if(seg.start_addr >= 0xc000) + fprintf(stderr, SELF ": warning: %s: start address $%04x loads into ROM.\n", infile, seg.start_addr); + + if(seg.end_addr >= 0xc000) + fprintf(stderr, SELF ": warning: %s: end address $%04x loads into ROM.\n", + infile, seg.end_addr); + xex_fwrite_seg(&seg, outfh); if(initaddr >= 0) { @@ -108,11 +132,13 @@ void write_segment( } fclose(infh); + return(1); } void usage() { - printf(SELF ": Usage:\n\t" - SELF " outfile [-r runaddr] [-l loadaddr [-i initaddr] " + printf(SELF ": Usage:\n " + SELF " outfile [-v] [-r runaddr]\n" + " [-l loadaddr ] [-i initaddr] " "[-o offset] [-s size] infile] ..." "\nSee man page for details.\n"); } @@ -120,6 +146,7 @@ void usage() { int main(int argc, char **argv) { char *outfile = 0, *infile = 0; int i, loadaddr = -1, runaddr = -1, initaddr = -1, offset = 0, size = DEFAULT_SIZE, *param = 0; + int segcount = 0, incount = 0; outfile = argv[1]; if(!outfile || strcmp(outfile, "--help") == 0 || strcmp(outfile, "-h") == 0) { @@ -137,12 +164,6 @@ int main(int argc, char **argv) { exit(1); } - if(argc < 5) { - fprintf(stderr, SELF ": not enough arguments.\n"); - usage(); - exit(1); - } - for(i = 2; i < argc; i++) { char *arg = argv[i]; @@ -157,7 +178,7 @@ int main(int argc, char **argv) { exit(1); } param = 0; - } else if(arg[0] == '-') { + } else if(arg[0] == '-' && arg[1] != '\0') { infile = 0; switch(arg[1]) { case 'l': param = &loadaddr; break; @@ -173,21 +194,33 @@ int main(int argc, char **argv) { break; } } else { - if(infile) { - fprintf(stderr, SELF ": input filename without -l option: %s\n", arg); - usage(); - exit(1); + if(loadaddr == -1) { + fprintf(stderr, SELF ": input filename without load address (-l): %s\n", arg); + segcount = 0; + break; } infile = arg; - write_segment(infile, outfile, loadaddr, initaddr, offset, size); + incount++; + if(write_segment(infile, outfile, loadaddr, initaddr, offset, size)) { + segcount++; + } else { + segcount = 0; + break; + } + infile = 0; loadaddr = -1; initaddr = -1; offset = 0; size = DEFAULT_SIZE; } } - if(param || (loadaddr >= 0) || (initaddr >= 0) || - (offset != 0) || (size != DEFAULT_SIZE)) { - fprintf(stderr, SELF ": " - "warning: extra arguments after last input file ignored.\n"); + if(incount) { + if(segcount && ((param || (loadaddr >= 0) || (initaddr >= 0)) || + (offset != 0) || (size != DEFAULT_SIZE))) + { + fprintf(stderr, SELF ": " + "warning: extra arguments after last input file ignored.\n"); + } + } else { + fprintf(stderr, SELF ": no input files!\n"); } if(outfh) { @@ -201,5 +234,14 @@ int main(int argc, char **argv) { fclose(outfh); } + if(segcount) { + if(xex_verbose) + fprintf(stderr, SELF ": read %d input files, wrote %d segments to %s.\n", + incount, segcount, outfile); + } else { + unlink(outfile); + return 1; + } + return 0; } diff --git a/blob2xex.rst b/blob2xex.rst index 18ebd6e..4166f64 100644 --- a/blob2xex.rst +++ b/blob2xex.rst @@ -20,19 +20,23 @@ DESCRIPTION =========== **blob2xex** creates an Atari 8-bit binary load (xex) file from one or -more files of arbitrary data. +more files of arbitrary data. Each input file will become a separate +segment in the binary load file. A run address can be added with the +**-r** option. -Each input file *requires* a **-l** *loadaddr* option, to set the load -address. Optionally, run and init addresses can be included. Also, -using **-o** and **-s**, it's possible to include only part of the -input file. To read from standard input, use **-** for the *infile*. +Each input file *requires* a **-l** *loadaddr* option, to set the +load address. Optionally, init addresses can be included, per-segment +(**-i**). Also, using **-o** and **-s**, it's possible to include only +part of the input file. To read from standard input, use **-** for the +*infile*. *outfile* must be given as the first argument. When multiple input files are used, the resulting .xex file will have multiple -segments. If *outfile* already exists, it will be overwritten. Use -**-** to write to standard output. If *outfile* is a filename that -begins with a **-**, prefix it with "./", otherwise it'll be taken as -an option. +segments. If *outfile* already exists, it will be overwritten. +If *outfile* is a filename that begins with a **-**, prefix it with +"./", otherwise it'll be taken as an option. Use **-** to write to +standard output. **blob2xex** will not write output to a terminal; +**-** must be used with redirection or a pipe. Addresses, offsets, and sizes may be given in decimal or hex. Hex addresses must be prefixed with either **$** or **0x**. @@ -40,7 +44,7 @@ addresses must be prefixed with either **$** or **0x**. OPTIONS ======= -A space is required between an option and its argument; use e.g. **-l 0x2000*, +A space is required between an option and its argument; use e.g. **-l 0x2000**, not **-l0x2000**. -l *loadaddr* |