From: Alan Cox Date: Mon, 25 Jun 2018 21:08:38 +0000 (+0100) Subject: visualize: provide a visual map of the memory layout - on Z80 at least X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=287d1c5c94d4d9d19ae77a3457437b5ca128f723;p=FUZIX.git visualize: provide a visual map of the memory layout - on Z80 at least A 64 x 4 display showing 64K split into 256 byte chunks in 64 x 1K vertical stripes showing free and used spaces. Doesn't produce sensible output for banked binaries. --- diff --git a/Kernel/tools/visualize.c b/Kernel/tools/visualize.c new file mode 100644 index 00000000..ad07096f --- /dev/null +++ b/Kernel/tools/visualize.c @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include + +static uint8_t use[256]; + +struct section { + struct section *next; + char name[64]; + char code; + unsigned int start; + unsigned int len; + int flags; +#define KNOW_START 1 +#define KNOW_SIZE 2 +}; + +static struct section *head; + +static struct section *find_create(const char *name) +{ + struct section *s = head; + while (s) { + if (strcmp(s->name, name) == 0) + return s; + s = s->next; + } + s = malloc(sizeof(struct section)); + if (s == NULL) { + fputs("Out of memory.\n", stderr); + exit(1); + } + s->flags = 0; + strncpy(s->name, name, 64); + s->name[63] = 0; + s->next = head; + head = s; + return s; +} + +static char code_for(const char *name) +{ + if (strcmp(name, "CODE") == 0) + return '1'; + if (strcmp(name, "CODE1") == 0) + return '1'; + if (strcmp(name, "CODE2") == 0) + return '2'; + if (strcmp(name, "CODE3") == 0) + return '3'; + if (strcmp(name, "CODE4") == 0) + return '4'; + if (strcmp(name, "CODE5") == 0) + return '5'; + if (strcmp(name, "CODE6") == 0) + return '6'; + if (strcmp(name, "VIDEO") == 0) + return 'V'; + if (strcmp(name, "FONT") == 0) + return 'F'; + if (strcmp(name, "INITIALIZED") == 0) + return 'I'; + if (strcmp(name, "HOME") == 0) + return 'H'; + if (strcmp(name, "DISCARD") == 0) + return 'X'; + if (strcmp(name, "DATA") == 0) + return 'D'; + if (strcmp(name, "BUFFERS") == 0) + return 'B'; + if (strcmp(name, "COMMONMEM") == 0) + return 'S'; + if (strcmp(name, "COMMONDATA") == 0) + return 's'; + if (strcmp(name, "CONST") == 0) + return 'C'; + if (strcmp(name, "INITIALIZER") == 0) + return 'i'; + return '?'; +} + +static void learn_size(const char *size, const char *name) +{ + struct section *s = find_create(name); + if (sscanf(size, "%8X", &s->len) != 1) { + fprintf(stderr, "Invalid size '%s'.\n", size); + exit(1); + } + s->flags |= KNOW_SIZE; +} + +static void learn_start(const char *addr, const char *name) +{ + struct section *s = find_create(name); + if (sscanf(addr, "%8X", &s->start) != 1) { + fprintf(stderr, "Invalid start '%s'.\n", addr); + exit(1); + } + s->flags |= KNOW_START; +} + +static void mark_map(void) +{ + unsigned int base, end; + struct section *s = head; + while (s) { + if (s->flags != (KNOW_SIZE | KNOW_START)) { + fprintf(stderr, "Incomplete section '%s'.\n", + s->name); + exit(1); + } + if (s->len) { + s->code = code_for(s->name); + base = (s->start + 127) >> 8; + end = (s->start + s->len + 127) >> 8; + while (base <= end) { + use[base++] = s->code; + } + } + s = s->next; + } +} + +int main(int argc, char *argv[]) +{ + char buf[512]; + int i; + int r; + + memset(use, '#', 256); + + while (fgets(buf, 511, stdin)) { + char *p1 = strtok(buf, " \t\n"); + char *p2 = NULL; + + if (p1) + p2 = strtok(NULL, " \t\n"); + + if (p1 == NULL || p2 == NULL) + continue; + + if (strncmp(p2, "l__", 3) == 0) + learn_size(p1, p2 + 3); + if (strncmp(p2, "s__", 3) == 0) + learn_start(p1, p2 + 3); + } + mark_map(); + for (r = 0; r < 4; r++) { + for (i = 0; i < 256; i += 4) + putchar(use[i + r]); + putchar('\n'); + } + exit(0); +}