From 163813ee05abffbb0fa2d48b8b380e8b3e972422 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Thu, 17 Nov 2022 15:02:49 -0500 Subject: dla2csv.xex: optimizations WIP. --- dla.atr | Bin 92176 -> 92176 bytes dla2csv.c | 179 +++++++++++++++++++++++++++++++++++++++++++++--------------- dla2csv.xex | Bin 10411 -> 10790 bytes 3 files changed, 135 insertions(+), 44 deletions(-) diff --git a/dla.atr b/dla.atr index 247fe9d..1af905c 100644 Binary files a/dla.atr and b/dla.atr differ diff --git a/dla2csv.c b/dla2csv.c index a7a4e6e..d8341a8 100644 --- a/dla2csv.c +++ b/dla2csv.c @@ -20,6 +20,7 @@ #define HEIGHT 170 #define WIDTH 176 +#define BYTEWIDTH 22 /* cc65 doesn't fold constants, it won't let us do this: #define INBUF_SIZE (WIDTH * HEIGHT) @@ -35,7 +36,7 @@ void print_id(void) { #ifdef __ATARI__ /* Uncomment this to see elapsed time in convert() */ - // #define PROFILE + #define PROFILE /* cc65 doesn't "localize" \b to the Atari backspace character, so: */ #define BS CH_DEL @@ -214,6 +215,12 @@ char *eoltypes[][2] = { { NULL, NULL } }; +char *eol; /* gets assigned one of the eoltypes */ + +/* using a table of masks instead of calculating them saves maybe 2s + on the Atari. */ +unsigned char masks[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + /* Read a string from stdin (E: on the Atari). Exit if we get EOF on stdin (e.g. ^D on Linux, ^3 on Atari). See exit_eof_stdin() comments above. @@ -320,11 +327,16 @@ char *prompt_eol(void) { return eoltypes[i][1]; } -void backspace3(void) { - putchar(BS); +#ifdef __ATARI__ +void backspace2(void) { + OS.colcrs -= 2; +} +#else +void backspace2(void) { putchar(BS); putchar(BS); } +#endif /* check_dla() returns 1 if all is well, 0 if there's a problem. */ int check_dla(int bytes) { @@ -351,7 +363,6 @@ int check_dla(int bytes) { } } - return ok; } @@ -375,39 +386,114 @@ int read_file(void) { return bytes; } +#if 0 /* convert() returns the number of particles on success, 0 on failure. */ int convert(char *eol) { + div_t d; + unsigned int particles; #ifdef __ATARI__ register #endif - unsigned char x, y; + unsigned int i; + unsigned char j, x, pct = 0; + + outf = prompt_filename("Output CSV", "wb"); +#ifdef __ATARI__ + printf("Press Ctrl-C to abort conversion.\n"); +#endif + printf("\nConverting... "); + fprintf(outf, "x,y%s", eol); + + for(i = 0; i < INBUF_SIZE; ++i) { + if(i % 38 == 0) { + backspace3(); + printf("%02d%%", pct++); + fflush(stdout); + } + if(inbuf[i]) { + d = div(i, 22); + x = d.rem * 8; + for(j = 0; j < 8; ++x, ++j) { + if(inbuf[i] & masks[j]) { + if(fprintf(outf, "%d,%d%s", x, d.quot, eol) < 0) { + putchar('\n'); + PERROR(stringbuf); + fclose(outf); + remove(stringbuf); + return 0; + } + particles++; + } + } + } + } + + fclose(outf); + + + return particles; +} +#endif + +#ifdef __ATARI__ +/* using utoa() rather than fprintf() saves ~12 sec on the Atari. */ +void writepoint(unsigned char x, unsigned char y) { + static char ubuf[10]; + static char fbuf[16]; + + utoa(x, fbuf, 10); + strcat(fbuf, ","); + strcat(fbuf, utoa(y, ubuf, 10)); + strcat(fbuf, eol); + fputs(fbuf, outf); + /* + utoa(x, buf, 10); + fputs(buf, outf); + fputc(',', outf); + utoa(y, buf, 10); + fputs(buf, outf); + fputs(eol, outf); + */ +} +#else +/* since utoa() only exists on cc65, can't use it on non-Atari. */ +void writepoint(unsigned char x, unsigned char y) { + fprintf(outf, "%d,%d%s", x, y, eol); +} +#endif + +/* currently, on the 800 with atariserver, convert() takes: + 5s for a DLA with no points (a file of zeroes). + 16s for a DLA with 1000 points. + 9s for the same DLA, with the fputs() in writepoint() commented out. +*/ +int convert(void) { + unsigned char x, y, j, pixx; #ifdef __ATARI__ register #endif char *inp = inbuf; - unsigned char xmask = 0x80; int particles = 0; outf = prompt_filename("Output CSV", "wb"); #ifdef __ATARI__ printf("Press Ctrl-C to abort conversion.\n"); + OS.crsinh = 1; +#endif + printf("\nConverting... %%"); +#ifdef __ATARI__ + putchar(0xa0); + backspace2(); #endif - printf("\nConverting... "); /* CSV file header row (column names) */ fprintf(outf, "x,y%s", eol); -#ifdef __ATARI__ - #ifdef PROFILE - OS.rtclok[0] = OS.rtclok[1] = OS.rtclok[2] = 0; - #endif -#endif - /* write output file one line at a time */ /* loop over all the pixels, by row, then column. this loop is rather slow. */ - for(y = 0; y < HEIGHT; y++) { + for(y = 0; y < HEIGHT; ++y) { #ifdef __ATARI__ /* check for ^C */ if(OS.ch == (KEY_C | KEY_CTRL)) { @@ -418,46 +504,37 @@ int convert(char *eol) { return 0; } #endif - backspace3(); - printf("%02d%%", y * 100 / HEIGHT); /* percentage */ + backspace2(); + printf("%02d", y * 100 / HEIGHT); /* percentage */ fflush(stdout); - for(x = 0; x < WIDTH; x++) { - /* slight optimization, saves ~12 sec (30% speedup) on Atari */ - if(!*inp) { - inp++; - x += 7; - continue; - } - if(*inp & xmask) { - if(fprintf(outf, "%d,%d%s", x, y, eol) < 0) { - putchar('\n'); - PERROR(stringbuf); - fclose(outf); - remove(stringbuf); - return 0; + for(x = 0; x < BYTEWIDTH; ++x) { + if(*inp) { + pixx = x * 8; + for(j = 0; j < 8; ++j) { + if(*inp & masks[j]) { + writepoint(pixx + j, y); + if(ferror(outf)) { + PERROR(stringbuf); + fclose(outf); + remove(stringbuf); + return 0; + } + particles++; + } } - particles++; - } - xmask >>= 1; - if(!xmask) { - xmask = 0x80; - inp++; } + inp++; } } fclose(outf); #ifdef __ATARI__ - #ifdef PROFILE - printf("\nElapsed time: %ds\n", ((OS.rtclok[1] << 8) | OS.rtclok[2]) / 60); - #endif + OS.crsinh = 0; #endif - return particles; } int main(int argc, char **argv) { - char *eol; int done, result = 0; init_console(); @@ -483,10 +560,18 @@ int main(int argc, char **argv) { without re-reading the input file. */ done = 0; while(!done) { - result = convert(eol); - if(result) { + +#ifdef __ATARI__ + #ifdef PROFILE + OS.rtclok[0] = OS.rtclok[1] = OS.rtclok[2] = 0; + #endif +#endif + + result = convert(); + + if(result >= 0) { done = 1; - backspace3(); + backspace2(); printf("100%%\n%d particles.\n", result); } else { if(!prompt_yn("Conversion failed, try again", 1)) @@ -494,6 +579,12 @@ int main(int argc, char **argv) { } } +#ifdef __ATARI__ + #ifdef PROFILE + printf("\nElapsed time: %ds\n", ((OS.rtclok[1] << 8) | OS.rtclok[2]) / 60); + #endif +#endif + if(!prompt_yn("\nConvert another file", 1)) break; } diff --git a/dla2csv.xex b/dla2csv.xex index c9bd19f..41b117c 100644 Binary files a/dla2csv.xex and b/dla2csv.xex differ -- cgit v1.2.3