diff options
| -rw-r--r-- | xexcat.1 | 33 | ||||
| -rw-r--r-- | xexcat.c | 65 | ||||
| -rw-r--r-- | xexcat.rst | 27 | 
3 files changed, 102 insertions, 23 deletions
| @@ -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 @@ -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); @@ -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  ===== | 
