/* ** Atari ST driver for starchart. ** Works on color systems only, compiled with Mark Williams C. ** Written by Dave Yearke (dgy@sigmast), September 1988. ** Portions of this program (c) Mark Williams Company. ** Thanks to the authors of the other starchart drivers for giving ** me some examples to work from. */ extern int exit_and_save; extern char *getenv(), picturefile[]; #include /* isprint(), iscntrl(), etc. */ #include /* Line A (low-level graphics) routines. */ #include /* Operating system bindings */ #include /* The virtual device interface routines */ #include /* Extended BIOS bindings */ #include "starchrt.h" /* Starchart information */ /* Global line A variables used by vdi; MUST be included */ int contrl[12], intin[128], ptsin[128], intout[128], ptsout[128]; /* Array used by vs_clip() */ int cliparray[] = { 1, 1, 319, 199 }; /* Arrays used by v_opvwk() */ int work_in[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 }; int work_out[57]; #define TRUE 1 #define NULL 0 /* ** Starchart was designed for 1024x768 pixels. These macros scale the ** image to the 320x200 Atari ST low-resolution (16-color) mode. Also, ** the y coord is subtracted from 200 so the image isn't upside-down. */ #define xadjust(x) ((x) * 0.3125) #define yadjust(y) (200 - ((y) * 0.2604167)) struct la_font *fontp; /* Line A font header. */ char line[100], linemode, *p; char scr_wrk[1024]; int vdihandle; /* Virtual device's handle */ int CURRX, CURRY, currez, old_color[16], oldrez = 99; /* 99 is impossible! */ /* ** Settings for the palette, given as RGB, 3 bits for each color (512 total). ** I tried to use different registers for different types of objects so they ** could be set individually (for example, in DEGAS you could blink a register ** for an object you're trying to point out). */ int new_color[16] = { 0x000, /* Black - Background color */ 0x777, /* White - 1st and higher mag. stars */ 0x666, /* White - 2nd mag. stars */ 0x555, /* White - 3rd mag. stars */ 0x444, /* White - 4th mag. stars */ 0x333, /* White - 5th mag. stars */ 0x222, /* White - 6th and lower mag. stars */ 0x222, /* White - Nebulae, Galaxies, Clusters */ 0x007, /* Blue - 1st and higher mag. stars */ 0x700, /* Red - 1st and higher mag. stars */ 0x770, /* Yellow - Sol */ 0x704, /* Pink - Inferior Planets */ 0x404, /* Purple - Superior Planets */ 0x020, /* Dark Green - Dotted lines */ 0x200, /* Dark Red - Hyphenated lines */ 0x003 }; /* Deep Blue - Text and borders */ /* ** These are reverse-image colors for the background and stars, used when the ** 'r' key is hit when the program pauses before exiting. Switching these ** registers makes a .ice output image for a screen dump to a printer. */ int rev_color[8] = { 0x777, /* White - Background color */ 0x000, /* Black - 1st and higher mag. stars */ 0x222, /* Black - 2nd mag. stars */ 0x333, /* Black - 3rd mag. stars */ 0x444, /* Black - 4th mag. stars */ 0x555, /* Black - 5th mag. starag. starag. starag. starag. star /* Loop if 'r' is pressed, return for anything else */ switch (i = Crawcin()) { /* Wait for keypress before quitting */ case 'r': /* Reverse the color registers */ if (Setcolor(0, -1) == 0) { /* If normal, reverse it */ for (i = 0; i < 8; i++) Setcolor(i, rev_color[i]); } else { /* Make it normal */ for (i = 0; i < 8; i++) Setcolor(i, new_color[i]); } continue; /* Restart the loop */ break; case 's': /* Save as a DEGAS picture */ strcpy(picturefile, "star.pi1"); savepic(); break; case 'S': /* Save as a NeoChrome picture */ strcpy(picturefile, "star.neo"); savepic(); break; default: break; } break; } vecreset(); } /* ** Restore the screen */ vecreset() { int i; v_clsvwk(vdihandle); /* Close the virtual workscreen */ appl_exit(); /* Remove the application from AES */ Cconws("\033H\033J"); /* Clear the screen */ Setscreen((char *)-1, (char *)-1, oldrez); /* Set resolution */ for (i = 0; i < 16; i++) /* Set the colors back to their saved values */ Setcolor(i, old_color[i]); if (((getenv("PATH")) == 0) || (strlen(getenv("PATH")) == 0)) linea9(); /* Show mouse pointer */ else /* If called from a shell */ Cursconf(1, 0); /* Show cursor */ } /* ** Save the screen as a DEGAS or NeoChrome picture */ savepic() { int neo = 0, file; /* Assume DEGAS file */ if (strrchr(picturefile, '.') != NULL) { /* Extender given */ if ((!strncmp(picturefile + strrchr(picturefile, '.'), ".neo", 4)) || (!strncmp(picturefile + strrchr(picturefile, '.'), ".NEO", 4))) ++neo; /* Save as a NeoChrome picture */ } else strcat(picturefile, ".pi1"); if ((file = creat(picturefile, 0)) == -1) die("Cannot open %s.", picturefile); if (neo) /* NeoChrome has two extra null bytes at the beginning */ if (write(file, &currez, 2) != 2) die("Write failure on file %s.", picturefile); if (write(file, &currez, 2) != 2) /* Write the resolution */ die("Write failure on file %s.", picturefile); if (write(file, &new_color[0], 32) != 32) /* Write the palette info */ die("Write failure on file %s.", picturefile); if (neo) /* NeoChrome has a 128-byte header, so we'll pad with 94 bytes */ for (neo = 0; neo < 47; ++neo) /* Recycle the variable "neo" */ if (write(file, &currez, 2) != 2) die("Write failure on file %s.", picturefile); if (write(file, Physbase(), 32000) != 32000) /* Write the screen */ die("Write failure on file %s.", picturefile); close(file); /* Done! (that wasn't too bad, was it?) */ } /* ** This function is duplicated in starchrt.c for non-ST versions, using ** the INTERACTIVE manifest constant. */ die(a,b) char *a, *b; { char buf[80]; int i; if (oldrez != 99) /* See if we ever initialized the screen. */ vecreset(); /* Reset the screen to something sane */ if (!strncmp(b, "\nusage", 6)) { /* Sub in the ST's usage */ Cconws("\n\rusage:\tstar* [ Ra Dcl Scale Title Maglim Labellim ]\n"); Cconws("\ror\tstar* [ -r Ra -d Dcl -s Scale -t Title -m Maglim -l "); Cconws("Labellim -f x.str ]\n\ror\tstar* [ -c con (3 or 4 letters "); Cconws("chosen from con.loc) -l ... ]\n\ror\tstarst -x [ file.PI1 "); Cconws("| file.NEO ] ... (to exit and save screen)\n\n\r"); Cconws("Portions of this program, copyright 1984, "); Cconws("Mark Williams Company"); } else { sprintf(buf, a, b); Cconws(buf); } Cconws("\n\r"); /* Cconws does not map \n into \n\r */ /* We want to hold the screen if invoked from the GEM desktop; the desktop doesn't usually set any environment variables, and if getenv() does find anything, it's probably a NULL string. */ if (((getenv("PATH")) == 0) || (strlen(getenv("PATH")) == 0)) { Cconws("press any key to continue: "); /* Hold screen if desktop */ i = Crawcin(); /* Read raw character input */ } exit(1); } /* ** Functions for manipulating text. */ /* ** This function sets the point size for text. (not applicable) */ vecsize (points) int points; { } /* ** This function puts text on the screen. */ vecsyms (x, y, s) int x,y; char *s; { register char *ptr; register unsigned int tmp; if (*s == '\0') /* Don't bother if the string is empty */ return; /* (A null char can make linea8() crash!) */ fontp = la_init.li_a1[0]; /* 6x6 system font */ FBASE = fontp->font_data; /* Pointer to start of font form */ FWIDTH = fontp->font_width; /* Width of font form */ DELY = fontp->font_height; /* Height of character in font */ DSTX = xadjust(x); if ((DSTY = yadjust(y)) > 2) DSTY -= 2; /* This vertically centers the text on the line */ if (DSTY > 191) DSTY = 191; /* Make sure the bottom line shows up */ ptr = s; do { /* Output the characters until the end of the string is hit */ if (!iscntrl(*ptr)) { tmp = *ptr - fontp->font_low_ade; /* Find the character data */ SRCX = fontp->font_char_off[tmp]; /* within the font data */ DELX = fontp->font_char_off[tmp + 1] - SRCX; /* Check screen boundaries */ if ((DSTX > 0) && (DSTX < 311) && (DSTY > 0)) if (isspace(*ptr)) { WMODE = 1; /* Writing mode = transparent */ linea8(); WMODE = 0; /* Writing mode = replace */ } else linea8(); /* Line A trap for text blit routine */ } } while (*++ptr != '\0'); } /* ** This function puts text on the screen using the greek alphabet. ** (Well, not yet, but someday ... :-)) */ vecsymsgk(s, x, y) char *s; { vecsyms(s, x, y); } /* ** Functions for drawing points and lines. */ /* ** Change the current position of x and y. */ vecmove (x, y) int x,y; { CURRX = x; CURRY = y; } /* ** Move to a new location (x1, y1) and draw a solid line to (x2, y2). */ vecmovedraw (x1, y1, x2, y2) int x1, y1, x2, y2; { vecmove(x1, y1); vecdraw(x2, y2); } /* ** Draw a solid line to (x,y) */ vecdraw (x, y) int x,y; { if (linemode != 'S') { linemode = 'S'; COLBIT0 = 1; /* Set the bit plane for line drawing (color 15) */ COLBIT1 = 1; COLBIT2 = 1; COLBIT3 = 1; } X1 = xadjust(CURRX); Y1 = yadjust(CURRY); X2 = xadjust(CURRX = x); Y2 = yadjust(CURRY = y); linea3(); /* Line blit routine */ } /* ** Draw a dotted line (dark green on the ST) to (x,y) */ vecdrawdot(x, y) { if (linemode != 'D') { linemode = 'D'; COLBIT0 = 1; /* Set the bit plane for line drawing (color 13) */ COLBIT1 = 0; COLBIT2 = 1; COLBIT3 = 1; } X1 = xadjust(CURRX); Y1 = yadjust(CURRY); X2 = xadjust(CURRX = x); Y2 = yadjust(CURRY = y); linea3(); } /* ** Draw a hyphenated line (dark red on the ST) to (x,y) */ vecdrawhyph(x, y) { if (linemode != 'H') { linemode = 'H'; COLBIT0 = 0; /* Set the bit plane for line drawing (color 14) */ COLBIT1 = 1; COLBIT2 = 1; COLBIT3 = 1; } X1 = xadjust(CURRX); Y1 = yadjust(CURRY); X2 = xadjust(CURRX = x); Y2 = yadjust(CURRY = y); linea3(); } /* ** Draw a horizontal line. */ drawlen (x, y, dx, dy, len) int x, y, dx, dy, len; { if (linemode != 'S') { linemode = 'S'; COLBIT0 = 1; /* Set the bit plane for line drawing (color 15) */ COLBIT1 = 1; COLBIT2 = 1; COLBIT3 = 1; } X1 = xadjust(x + dx); Y1 = yadjust(y + dy); X2 = xadjust(CURRX = x + dx + len - 1); Y2 = yadjust(CURRY = y + dy); linea3(); } /* ** Functions for astronomical objects. */ /* ** Draw the sun or a planet */ drawPlan(x, y, mag, type, color) int x, y, mag, type; char *color; { if (type == 'S') INTIN[0] = 10; /* Yellow for the Sun */ else if ((type == 'M') || (type == 'V')) INTIN[0] = 11; /* Pink for inferior planets (Mercury or Venus) */ else INTIN[0] = 12; /* Purple for superior planets (m, J, s, U, or N) */ PTSIN[0] = xadjust(CURRX = x); PTSIN[1] = yadjust(CURRY = y); if (linea2() == 0) /* See if there's anything there already */ linea1(); /* Put a pixel on the screen */ } /* ** Draw a star. */ drawStar(x, y, mag, type, color) int x, y, mag, type; char *color; { if (mag > 6) INTIN[0] = 6; else if (mag < 1) INTIN[0] = 1; else INTIN[0] = mag; /* No conversion necessary, direct map into palette */ if (mag < 2) /* Brightest stars will be in color if possible */ if (color != NULL) if ((color[0] == 'O') || (color[0] == 'B')) INTIN[0] = 8; /* Color register 8 holds blue */ else if ((color[0] == 'K') || (color[0] == 'M')) INTIN[0] = 9; /* Color register 9 holds red */ PTSIN[0] = xadjust(CURRX = x); PTSIN[1] = yadjust(CURRY = y); if (mag < 1) drawBigStar(x, y); /* Bright stars clobber anything under them */ else if (linea2() == 0) /* See if there's anything there already */ linea1(); } /* ** Draw a bright star as a cross shape. */ drawBigStar(x, y) int x, y; { linea1(); /* x, y */ --PTSIN[0]; linea1(); /* x-1, y */ ++PTSIN[0]; --PTSIN[1]; linea1(); /* x, y-1 */ PTSIN[1] += 2; linea1(); /* x, y+1 */ ++PTSIN[0]; --PTSIN[1]; linea1(); /* x+1, y */ } /* ** Draw a nebula. ('type' = 'D' for diffuse, 'P' for planetary) */ drawNebu(x, y, mag, type, color) int x, y, mag, type; char *color; { /* This isn't as clever as cstar() in starimag.c, but it's fast */ INTIN[0] = 7; /* Make 'em faint, with this shape: */ PTSIN[0] = xadjust(CURRX = x) - 1; /* ** */ PTSIN[1] = yadjust(CURRY = y); /* * * */ linea1(); /* x-1, y ** */ ++PTSIN[1]; linea1(); /* x-1, y+1 */ ++PTSIN[0]; ++PTSIN[1]; linea1(); /* x, y+2 */ PTSIN[1] -= 3; linea1(); /* x, y-1 */ ++PTSIN[0]; ++PTSIN[1]; linea1(); /* x+1, y */ ++PTSIN[1]; linea1(); /* x+1, y+1 */ } /* ** Draw a galaxy. ('type' = 'P' for sphere, 'S' for spiral) */ drawGalx(x, y, mag, type, color) int x, y, mag, type; char *color; { int i; CURRX = x; CURRY = y; INTIN[0] = 7; /* Make 'em faint, with this shape: */ PTSIN[0] = xadjust(CURRX = x) - 2; /* ** * */ PTSIN[1] = yadjust(CURRY = y); /* ****** */ for (i = 0; i < 6; ++i) { /* * ** */ PTSIN[0] += 1; linea1(); /* (x-2)+i, y */ } ++PTSIN[0]; --PTSIN[1]; linea1(); /* x+4, y-1 */ PTSIN[0] -= 3; linea1(); /* x+1, y-1 */ --PTSIN[0]; linea1(); /* x, y-1 */ PTSIN[1] += 2; linea1(); /* x, y+1 */ ++PTSIN[0]; linea1(); /* x+1, y+1 */ PTSIN[0] -= 4; linea1(); /* x-3, y+1 */ } /* ** Draw a cluster. ('type' = 'G' for glob., 'O' for open, 'C' for Galactic) */ drawClus(x, y, mag, type, color) int x, y, mag, type; char *color; { INTIN[0] = 7; /* Make 'em faint, with this shape: */ PTSIN[0] = xadjust(CURRX = x); /* * * */ PTSIN[1] = yadjust(CURRY = y); /* * * * */ linea1(); /* x, y * * */ PTSIN[0] -= 2; linea1(); /* x-2, y */ ++PTSIN[0]; --PTSIN[1]; linea1(); /* x-1, y-1 */ PTSIN[0] += 2; linea1(); /* x+1, y-1 */ PTSIN[1] += 2; linea1(); /* x+1, y+1 */ PTSIN[0] -= 2; linea1(); /* x-1, y+1 */ PTSIN[0] += 3; --PTSIN[1]; linea1(); /* x+2, y */ }