/* ascii2map - Simple ASCII map converter aimed at retro code Copyright (C) 2003-2015 Ian Cowburn (ianc@noddybox.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 3 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, see . ------------------------------------------------------------------------- Main */ #include #include #include /* ---------------------------------------- VERSION INFO */ static const char *usage = "Version 0.4 development\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License (Version 3) for more details.\n" "\n" "usage: ascii2map [-a|-b|-c] [-d directive] [input-file [output-file]]\n"; /* ---------------------------------------- TYPES */ typedef unsigned char uchar; typedef enum { Assembly, Binary, CSource } Mode; /* ---------------------------------------- GLOBALS */ static int code_point = 'A'; static char code_string[256] = {0}; static uchar point[256]; static uchar used[256]; static const char *directive = "byte"; static Mode mode = Assembly; /* ---------------------------------------- PRIVATE FUNCTIONS */ static void Chomp(char *p) { size_t l = strlen(p); while(l && (p[l-1] == '\n' || p[l-1] == '\r')) { p[--l] = 0; } } static void StartOutput(FILE *fp) { switch(mode) { case CSource: fprintf(fp, "int map[] =\n{\n"); break; default: break; } } static void EndOutput(FILE *fp) { switch(mode) { case Assembly: fprintf(fp, "\n"); break; case CSource: fprintf(fp, "\n};\n"); break; default: break; } } static unsigned CodePoint(char c) { int offset; if (code_string[0]) { char *p = strchr(code_string, c); if (p) { c = p - code_string; } offset = c + code_point; } else { offset = c - code_point; } if (offset < 0) { offset = 0; } if (offset > 255) { offset = 255; } return (unsigned)offset; } static void Output(FILE *fp, char c) { static int column; static int first = 1; if (c < 0 || c > 255) { return; } switch(mode) { case Assembly: if (column == 0) { if (!first) { fprintf(fp, "\n"); } fprintf(fp, "\t%s\t", directive); } else { fprintf(fp, ", "); } if (used[c]) { fprintf(fp, "%u", point[c]); } else { fprintf(fp, "%u", CodePoint(c)); } break; case Binary: if (used[c]) { putc(point[c], fp); } else { putc(CodePoint(c), fp); } break; case CSource: if (!first) { fprintf(fp, ", "); } if (column == 0) { if (!first) { fprintf(fp, "\n"); } fprintf(fp, "\t"); } if (used[c]) { fprintf(fp, "%u", point[c]); } else { fprintf(fp, "%u", CodePoint(c)); } break; } column = (column + 1) % 8; if (first) { first = 0; } } /* ---------------------------------------- MAIN */ int main(int argc, char *argv[]) { FILE *in; FILE *out; char line[1024]; int f; int in_map = 0; size_t len = 0; int warned = 0; f = 1; /* Process switches */ while(argv[f] && argv[f][0] == '-') { int handled = 1; switch(argv[f][1]) { case 'a': mode = Assembly; break; case 'b': mode = Binary; break; case 'c': mode = CSource; break; case 'd': if (argv[f+1]) { directive = argv[++f]; } else { handled = 0; } break; default: handled = 0; break; } if (!handled) { fprintf(stderr,"%s\n", usage); exit(EXIT_FAILURE); } f++; } /* Handle file args */ if (argv[f]) { in = fopen(argv[f], "r"); if (!in) { fprintf(stderr,"Failed to open %s\n", argv[f]); exit(EXIT_FAILURE); } f++; } else { in = stdin; } if (argv[f]) { if (mode == Binary) { out = fopen(argv[f], "wb"); } else { out = fopen(argv[f], "w"); } if (!in) { fprintf(stderr,"Failed to open %s\n", argv[f]); exit(EXIT_FAILURE); } } else { out = stdout; } /* Process input */ used[' '] = 1; while(fgets(line, sizeof line, in)) { Chomp(line); if (in_map) { char *p; if (len == 0) { len = strlen(line); } else { if (!warned && len != strlen(line)) { fprintf(stderr, "WARNING: Lines of different length\n"); warned = 1; } } p = line; while(*p) { Output(out, *p++); } } else { if (strcmp(line, "~") == 0) { StartOutput(out); in_map = 1; } if (line[0] == '!') { code_point = atoi(line + 1); } else { if (line[0] && line[1] && line[1] != ':') { char *p = strrchr(line, ':'); if (p) { *p++ = 0; code_point = atoi(p); strncpy(code_string, line, sizeof code_string); code_string[(sizeof code_string) - 1] = 0; } } if (line[0] && line[1] == ':' && line[2]) { char c; int i; c = line[0]; i = atoi(line + 2); if (c >= 0 && c <= 255) { point[c] = i; used[c] = 1; } } } } } EndOutput(out); return EXIT_SUCCESS; } /* vim: ai sw=4 ts=8 expandtab */