diff options
-rw-r--r-- | a8xd.1 | 14 | ||||
-rw-r--r-- | a8xd.c | 134 | ||||
-rw-r--r-- | a8xd.rst | 12 |
3 files changed, 108 insertions, 52 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 "A8XD" 1 "2024-06-30" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "A8XD" 1 "2024-07-01" "0.2.1" "Urchlay's Atari 8-bit Tools" .SH NAME a8xd \- Atari 8-bit ATASCII-aware hex dump .SH SYNOPSIS @@ -67,16 +67,16 @@ Without \fIinfile\fP, or if \fIinfile\fP is \fB\-\fP, \fBa8xd\fP reads from stan .TP .B \-a ANTIC mode: treat the input as screen bytes (aka "internal codes") -rather than ATASCII. Can usefully be combined with \fB\-g\fP\&. +rather than ATASCII. Can usefully be combined with \fB\-g\fP or \fB\-f\fP\&. +.TP +.B \-f +Like \fB\-g\fP, but using the top half of the character set. This is +what you\(aqd see on the Atari with \fIGRAPHICS 1:POKE 756,226\fP\&. .TP .B \-g -Graphics mode. Changes the character codes and colorization so it +Graphics mode. Changes the printed characters and colorization so it looks like \fIGRAPHICS 1\fP (or 2) on the Atari. .TP -.B \-G -\fINot yet implemeted\fP\&. Like \fB\-g\fP, but using the top half of the character set. This is -what you\(aqd see on the Atari with \fIGRAPHICS 1:POKE 756,226\fP\&. -.TP .B \-i Print XL/XE International Character Set conversions instead of ATASCII. .UNINDENT @@ -14,6 +14,15 @@ #define UC_WORD_FMT "%04X" #define UC_BYTE_FMT "%02X" +/* colors. don't use black or white: one or the other is likely + the terminal's text color already. + don't use blue because it's hard to read. */ +#define C_RED 1 +#define C_GREEN 2 +#define C_YELLOW 3 +#define C_PURPLE 5 +#define C_CYAN 6 + /* translation table (see atables.c), choices are ata2utf, ics2utf, or magazine. */ const char **table = ata2utf; @@ -31,7 +40,7 @@ const char *byte_format = LC_BYTE_FMT; /* command line options change these. */ int verbose = 0, color = 1, disp_offset = 0, maxlen = 0; int seek_whence = 0, seekpos = 0, filepos = 0, limit = 0; -int graphics = 0, screencodes = 0; +int graphics = 0, screencodes = 0, high_font = 0; const char *self; @@ -49,7 +58,7 @@ void die(const char *msg) { } void print_help(void) { - printf("Usage:\n %s [-a] [-g] [-i] [-l limit] [-m] [-o offset] [-s [-]seek] [-u] [-v] [file]\n", self); + printf("Usage:\n %s [-a] [-f] [-g] [-i] [-l limit] [-m] [-o offset] [-s [-]seek] [-u] [-v] [file]\n", self); printf(" -a: Input is ANTIC screencodes (default is ATASCII).\n"); printf(" -g: GR.1/2 style colorization.\n"); printf(" -i: Input is XL intl charset (default is ATASCII).\n"); @@ -128,32 +137,50 @@ FILE *open_input(const char *file) { return input; } +int get_text_color(unsigned char c) { + unsigned char c7 = c & 0x7f; + + if(c == 0 || c == 0x9b) { + return C_RED; + } else if((c7 >= 0x1b && c7 <= 0x1f) || (c7 >= 0x7d)) { + /* cursor control characters: + - 0x1b (esc) + - 0x1c-0x1f (arrows), 0x9c-0x9f + - 0x7d/0xf3 (cls, bell) + - 0x7e, 0xfe (delete line, char) + - 0x7f, 0xff (tab, insert char) + */ + return C_PURPLE; + } else if(c7 < 32 || c7 == 0x60 || c7 == 0x7b) { + return C_YELLOW; + } else { + return C_GREEN; + } +} + +int get_graphics_color(unsigned char c) { + if(c < 0x20) + return C_GREEN; + else if(c >= 0x20 && c < 0x60) + return C_YELLOW; + else if(c >= 0x60 && c < 0x80) + return C_GREEN; + else if(c >= 0x80 && c < 0xa0) + return C_RED; + else if(c >= 0xa0 && c < 0xe0) + return C_CYAN; + else /* c >= 0xe0 */ + return C_RED; +} + char *get_color(unsigned char c) { int color; - unsigned char c7 = c & 0x7f; static char outbuf[32]; if(graphics) { - if(c < 0x20) - color = 2; - else if(c >= 0x20 && c < 0x60) - color = 3; - else if(c >= 0x60 && c < 0x80) - color = 2; - else if(c >= 0x80 && c < 0xa0) - color = 1; - else if(c >= 0xa0 && c < 0xe0) - color = 6; /* cyan (blue is too dark on most terminals) */ - else /* c >= 0xe0 */ - color = 1; + color = get_graphics_color(c); } else { - if(c == 0 || c == 0x9b) { - color = 1; /* red */ - } else if(c7 < 32 || c7 == 0x60 || c7 == 0x7b || c7 == 0x7d || c7 == 0x7e || c7 == 0x7f) { - color = 3; /* yellow/orange */ - } else { - color = 2; /* green */ - } + color = get_text_color(c); } if(color) { @@ -171,16 +198,22 @@ char *get_color(unsigned char c) { $60-$7F get displayed in green, as $40-$5F. for $80-$FF, same thing, but green is red, and orange is blue. */ -char *get_graphics(unsigned char c) { - static char result[2]; +unsigned char get_graphics(unsigned char c) { c &= 0x7f; if(c < 0x20) c += 0x20; else if(c >= 0x60) c -= 0x20; - result[0] = c; - result[1] = 0; - return result; + return c; +} + +unsigned char get_high_graphics(unsigned char c) { + c &= 0x7f; + if(c >= 0x20 && c < 0x40) + c -= 0x20; + else if(c >= 0x40) + c += 0x20; + return c; } unsigned char screen2ata(unsigned char c) { @@ -231,6 +264,19 @@ void seek_input(FILE *input) { } } +void append_str_f(char *buf, int *pos, const char *fmt, const char *str) { + *pos += sprintf(buf + *pos, fmt, str); +} + +void append_str(char *buf, int *pos, const char *str) { + append_str_f(buf, pos, "%s", str); +} + +void append_hex(char *buf, int *pos, const unsigned char byte) { + *pos += sprintf(buf + *pos, byte_format, byte); +} + + void dump_line(const unsigned char *buf, int len) { char hex[1024], asc[1024]; int hpos = 0, apos = 0, count = len; @@ -247,23 +293,32 @@ void dump_line(const unsigned char *buf, int len) { inv = !graphics && (c & 0x80); if(screencodes) c = screen2ata(c); - if(color) hpos += sprintf(hex + hpos, "%s", get_color(c)); - if(inv) hpos += sprintf(hex + hpos, "%s", inverse_on); - hpos += sprintf(hex + hpos, byte_format, *buf); /* *buf here, not c! */ - if(color || inv) hpos += sprintf(hex + hpos, "%s", color_off); - hex[hpos++] = ' '; - if(count - len == 7) hex[hpos++] = ' '; + hpos += printf("%s", get_color(c)); + if(inv) hpos += printf("%s", inverse_on); + hpos += printf(byte_format, *buf); /* *buf here, not c! */ + if(color || inv) hpos += printf("%s", color_off); + putchar(' '); + hpos++; + if(count - len == 7) { + putchar(' '); + hpos++; + } - if(color) apos += sprintf(asc + apos, "%s", get_color(c)); - if(inv) apos += sprintf(asc + apos, "%s", inverse_on); - apos += sprintf(asc + apos, "%s", (graphics ? get_graphics(c) : table[c & 0x7f])); - if(color || inv) apos += sprintf(asc + apos, "%s", color_off); + if(color) append_str(asc, &apos, get_color(c)); + if(inv) append_str(asc, &apos, inverse_on); + if(graphics) { + if(high_font) + c = get_high_graphics(c); + else + c = get_graphics(c); + } + apos += sprintf(asc + apos, "%s", table[c & 0x7f]); + if(color || inv) append_str(asc, &apos, color_off); filepos++; buf++; len--; } - printf("%s", hex); /* what shall we use to fill the empty spaces? */ if(count < 8) putchar(' '); @@ -316,7 +371,7 @@ int main(int argc, char **argv) { exit(0); } - while( (opt = getopt(argc, argv, "vhimus:o:l:ga")) != -1) { + while( (opt = getopt(argc, argv, "vhimus:o:l:gaf")) != -1) { switch(opt) { case 'v': verbose = 1; break; case 'h': print_help(); exit(0); break; @@ -328,6 +383,7 @@ int main(int argc, char **argv) { case 'l': limit = parse_limit_arg(optarg); break; case 'g': graphics = 1; break; case 'a': screencodes = 1; break; + case 'f': graphics = high_font = 1; break; default: print_help(); exit(1); break; } } @@ -43,16 +43,16 @@ OPTIONS -a ANTIC mode: treat the input as screen bytes (aka "internal codes") - rather than ATASCII. Can usefully be combined with **-g**. + rather than ATASCII. Can usefully be combined with **-g** or **-f**. + +-f + Like **-g**, but using the top half of the character set. This is + what you'd see on the Atari with *GRAPHICS 1:POKE 756,226*. -g - Graphics mode. Changes the character codes and colorization so it + Graphics mode. Changes the printed characters and colorization so it looks like *GRAPHICS 1* (or 2) on the Atari. --G - *Not yet implemeted*. Like **-g**, but using the top half of the character set. This is - what you'd see on the Atari with *GRAPHICS 1:POKE 756,226*. - -i Print XL/XE International Character Set conversions instead of ATASCII. |