home *** CD-ROM | disk | FTP | other *** search
- /*
- ** 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 <ctype.h> /* isprint(), iscntrl(), etc. */
- #include <linea.h> /* Line A (low-level graphics) routines. */
- #include <osbind.h> /* Operating system bindings */
- #include <vdibind.h> /* The virtual device interface routines */
- #include <xbios.h> /* 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 */
- }
-