aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xexcat.133
-rw-r--r--xexcat.c65
-rw-r--r--xexcat.rst27
3 files changed, 102 insertions, 23 deletions
diff --git a/xexcat.1 b/xexcat.1
index 70bded7..8b94f98 100644
--- a/xexcat.1
+++ b/xexcat.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "XEXCAT" 1 "2024-04-26" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XEXCAT" 1 "2024-04-27" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xexcat \- Concatenate Atari 8-bit executables (XEX) into a single XEX file.
.\" RST source for xexcat(1) man page. Convert with:
@@ -38,7 +38,7 @@ xexcat \- Concatenate Atari 8-bit executables (XEX) into a single XEX file.
.
.SH SYNOPSIS
.sp
-\fIxexcat\fP [\fI\-hvc\fP] [\-l \fIaddress\fP [\-r \fIaddress\fP] [\-i \fIaddress\fP] [\-o \fIoutfile.xex\fP] [\fIinfile.xex\fP] [\fIinfile.xex ...\fP]
+\fBxexcat\fP [\fB\-hvc\fP] [\fB\-f\fP \fI1\fP | \fI2\fP] [\fB\-l\fP \fIaddress\fP [\fB\-r\fP \fIaddress\fP] [\fB\-i\fP \fIaddress\fP] [\fB\-o\fP \fIoutfile.xex\fP] [\fIinfile.xex\fP] [\fIinfile.xex ...\fP]
.SH DESCRIPTION
.sp
\fBxexcat\fP reads one or more Atari executables (XEX/BIN/COM/etc)
@@ -56,13 +56,6 @@ optional \fI$FFFF\fP header.
.SH OPTIONS
.INDENT 0.0
.TP
-.B \-h
-Print a short help message and exit.
-.TP
-.B \-v
-Verbose operation. Each segment\(aqs information is printed to
-standard error, including start/end address and length.
-.TP
.B \-c
Check only; no output file is written. Equivalent to \fB\-v \-o /dev/null\fP\&.
.TP
@@ -91,6 +84,28 @@ is 0, all run addresses from all input files are ignored,
and the output file will not contain a run address segment
at all. Such a file can still be loaded from DOS, but it will
not execute (user will be returned to the DOS menu).
+.TP
+.B \-a
+"Automatic" run address: Force the output file\(aqs run address to the
+load address of the first segment.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-f 1|2
+Input file(s) are \fBdasm\fP(1) object files created by \fB\-f1\fP or
+\fB\-f2\fP options, rather than .xex files. \fB\-f1\fP files can\(aqt contain
+run or init addresses, so you\(aqll probably want to use \fB\-r\fP,
+\fB\-a\fP, and/or \fB\-i\fP with these. \fB\-f2\fP files can contain run or
+init addresses. The output file is still a .xex file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-h
+Print a short help message and exit.
+.TP
+.B \-v
+Verbose operation. Each segment\(aqs information is printed to
+standard error, including start/end address and length.
.UNINDENT
.SH NOTES
.sp
diff --git a/xexcat.c b/xexcat.c
index 22d8276..c4234bd 100644
--- a/xexcat.c
+++ b/xexcat.c
@@ -12,20 +12,51 @@
#endif
#define SELF "xexcat"
-#define OPTIONS "hvo:l:r:i:c"
+#define OPTIONS "hvo:l:r:i:cf:a"
char *usage =
SELF " v" VERSION " - by B. Watson (WTFPL)\n"
"Join one or more Atari 8-bit executables into one multi-segment file.\n"
- "usage: " SELF " -[hvc] [-l address] [-i address] [-r address]\n"
+ "usage: " SELF " -[hvc] [-f 1|2 ] [-l address] [-i address] [-r address]\n"
" [-o outfile.xex] [infile1.xex] [infile2.xex ...]\n"
- " -h Print this help\n"
" -o outfile.xex Output file (default: standard output)\n"
+ " -h Print this help\n"
" -v Verbose operation\n"
" -c Check only; no output (same as -v -o/dev/null)\n"
" -l address Force first load address (decimal, $hex, or 0xhex)\n"
" -i address Force first init address\n"
- " -r address Force run address\n";
+ " -r address Force run address\n"
+ " -a Force run address to load address of 1st segment.\n"
+ " -f 1|2 Input is DASM -f1 or -f2 format, not xex.\n";
+
+int read_seg(xex_segment *seg, FILE *f, int type) {
+ int i, j;
+
+ switch(type) {
+ /* byte 0 = LSB of load address, byte 1 = MSB, rest = data. */
+ case 1:
+ if( (i = fgetc(f)) < 0 )
+ return 0;
+ if( (j = fgetc(f)) < 0 )
+ return 0;
+ seg->start_addr = i | (j << 8);
+ for(i = 0; (i < 65536) && ((j = fgetc(f)) >= 0); i++) {
+ seg->object[i] = j;
+ seg->len++;
+ }
+ seg->end_addr = seg->start_addr + seg->len - 1;
+ seg->has_ff_header = 1;
+ xex_print_seg_info(seg);
+ return (i != 0);
+
+ case 2:
+ return 0;
+
+ case 0:
+ default:
+ return xex_fread_seg(seg, f);
+ }
+}
int main(int argc, char **argv) {
xex_segment seg;
@@ -34,7 +65,8 @@ int main(int argc, char **argv) {
int count = 1, c, errcount = 0;
unsigned char buffer[65536]; /* be lazy: statically allocate large buffer */
int force_load = -1, force_run = -1, force_init = -1;
- int read_stdin = 0;
+ int read_stdin = 0, run_1st_seg = 0;
+ int input_type = 0; /* 0 = xex, 1 and 2 are dasm -f1/-f2. */
/* parse args */
while( (c = getopt(argc, argv, OPTIONS)) > 0) {
@@ -72,6 +104,18 @@ int main(int argc, char **argv) {
exit(1);
break;
+ case 'f':
+ input_type = atoi(optarg);
+ if(input_type < 1 || input_type > 2) {
+ fprintf(stderr, SELF ": invalid -f argument (must be 1 or 2).\n");
+ exit(1);
+ }
+ break;
+
+ case 'a':
+ run_1st_seg = 1;
+ break;
+
default:
fprintf(stderr, usage);
exit(1);
@@ -122,13 +166,22 @@ int main(int argc, char **argv) {
fprintf(stderr, SELF ": reading from file %s\n", infile);
/* process every segment in current input file */
- while(xex_fread_seg(&seg, in)) {
+ while(read_seg(&seg, in, input_type)) {
if(filecount++ == 1 && !seg.has_ff_header) {
fprintf(stderr, SELF ": warning: '%s' first segment "
"lacks $FFFF header (bad/partial XEX file?)\n",
infile);
}
+ if(run_1st_seg && (force_run == -1)) {
+ force_run = seg.start_addr;
+ if(xex_verbose)
+ fprintf(stderr,
+ SELF ": %s: setting run address to %04X "
+ "due to -a option\n",
+ infile, force_run);
+ }
+
/* normalize the $FFFF headers: only the first segment needs one */
seg.has_ff_header = (count == 1);
diff --git a/xexcat.rst b/xexcat.rst
index a7ce20b..a91130f 100644
--- a/xexcat.rst
+++ b/xexcat.rst
@@ -15,7 +15,7 @@ Concatenate Atari 8-bit executables (XEX) into a single XEX file.
SYNOPSIS
========
-*xexcat* [*-hvc*] [-l *address* [-r *address*] [-i *address*] [-o *outfile.xex*] [*infile.xex*] [*infile.xex ...*]
+**xexcat** [**-hvc**] [**-f** *1* | *2*] [**-l** *address* [**-r** *address*] [**-i** *address*] [**-o** *outfile.xex*] [*infile.xex*] [*infile.xex ...*]
DESCRIPTION
===========
@@ -36,13 +36,6 @@ optional *$FFFF* header.
OPTIONS
=======
--h
- Print a short help message and exit.
-
--v
- Verbose operation. Each segment's information is printed to
- standard error, including start/end address and length.
-
-c
Check only; no output file is written. Equivalent to **-v -o /dev/null**.
@@ -72,6 +65,24 @@ OPTIONS
at all. Such a file can still be loaded from DOS, but it will
not execute (user will be returned to the DOS menu).
+-a
+ "Automatic" run address: Force the output file's run address to the
+ load address of the first segment.
+
+-f 1|2
+ Input file(s) are **dasm**\(1) object files created by **-f1** or
+ **-f2** options, rather than .xex files. **-f1** files can't contain
+ run or init addresses, so you'll probably want to use **-r**,
+ **-a**, and/or **-i** with these. **-f2** files can contain run or
+ init addresses. The output file is still a .xex file.
+
+-h
+ Print a short help message and exit.
+
+-v
+ Verbose operation. Each segment's information is printed to
+ standard error, including start/end address and length.
+
NOTES
=====