walker@edge.UUCP (Dan Walker) (08/07/87)
I just set up my 3B1 and I have a question. I would like to write some educational type games for my daughter to play on the system, and I need to know where I can find terminal type information on how to send grahics characters to the screen. I would like to draw some animation type stuff. If anyone can point me to some documentation, I would sure appreciate it, and I would be happy to make available anything I develope. Thanx all. I would also be interested in anything like this that may already be written. =============================================================================== Dan Walker (N7GLK) Pay no attention to that man behind Edge Computer the curtain. Scottsdale, Arizona ...!ihnp4!mot!edge!walker ...!seismo!ism780c!edge!walker and now at ...!ihnp4!mot!edge!gtx!ariel!daddy When the odds are 50/50, chances are 10 to 1 against you.
egray@fthood.UUCP (08/11/87)
I found very little documentation on the bit mapped graphics routines and found a few errors in what documentation there was. (I don't rememeber exactly what the errors were...) I've written a program to read Macintosh "MacPaint" files and display them on the bit mapped screen. This source code might be useful as an example to others... Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ /* * Program to display and print Macintosh MacPaint images * * Emmet P. Gray US Army, HQ III Corps & Fort Hood * ...!ethos!gizzmo!fthood!egray Attn: AFZF-DE-ENV * ...!ihnp4!uiucuxc!fthood!egray Directorate of Engineering & Housing * Environmental Management Office * Fort Hood, TX 76544-5057 */ #include <stdio.h> #include <tam.h> #define INVERSE unsigned short pic[720][36]; int row, col, next_row, hi_byte = 1; /* table for transposing bits */ unsigned char xp_table[256] = {0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255}; main(argc, argv) int argc; char *argv[]; { FILE *fp; int choice, next; short win; char name[80]; winit(); if (!iswind()) { fprintf(stderr, "Sorry, readmac requires a bit-mapped screen\n"); wexit(1); } /* create the window */ win = wcreate(1, 0, 24, 80, BORDVSCROLL); clear(); wgoto(win, 0, 0); if (argc != 2) { wprintf(win, "Readmac - program to display and print Macintosh MacPaint images\n\n"); wprintf(win, "up move the image up 20 pixel rows\n"); wprintf(win, "down move the image down 20 pixel rows\n"); wprintf(win, "P Print the image\n"); wprintf(win, "L Load another image\n"); wprintf(win, "Q Quit\n\n"); wprintf(win, "Enter the file name : "); wgets(win, name); } else strcpy(name, argv[1]); start: row = 0; col = 0; next_row = 0; if (!(fp = fopen(name, "r"))) { wprintf(win, "Can't open '%s' for read\n", name); wprintf(win, "Enter the file name [or control-c to quit] : "); wgets(win, name); goto start; } wprintf(win, "Reading the data file...\n"); if (read_data(fp)) { wprintf(win, "Bad file or not in MacPaint format\n", name); sleep(3); clean_up(win); wexit(1); } fclose(fp); clear(); /* show first 240 rows */ wrastop(win, pic, 72, 0, 0, 0, 0, 0, 0, 576, 240, SRCSRC, DSTSRC, 0); wprintf(win, "\033[=1C"); /* turn cursor off */ while (1) { choice = wgetc(win); switch (choice) { case 033: /* escape character '^[' */ next = wgetc(win); if (next != '[') { wputc(win, 07); break; } next = wgetc(win); switch (next) { case 'B': /* roll down key */ case 'S': /* arrow on border */ roll(1, win); break; case 'A': /* roll up key */ case 'T': /* arrow on border */ roll(0, win); break; default: wputc(win, 07); break; } break; case 'P': case 'p': /* print the file */ wgoto(win, 0, 0); print_it(win); clear(); /* repaint the image */ wrastop(win, pic, 72, 0, 0, 0, 0, 0, 0, 576, 240, SRCSRC, DSTSRC, 0); break; case 'L': case 'l': /* load another image */ wgoto(win, 0, 0); wprintf(win, "\033[=0C"); wprintf(win, "Enter the new file name : "); wgets(win, name); wprintf(win, "\033[=1C"); goto start; case 3: case 'Q': case 'q': /* quit */ clean_up(win); wexit(0); break; default: wputc(win, 07); break; } } } /* * The data file uses a straight forward compression technique. If the * 'index' byte is greater than 127, then repeat the next character * (257-index) times. If the 'index' byte is less than 127, then read * the next (index+1) bytes. */ read_data(fp) FILE *fp; { int count, repeat, c; unsigned char byte; /* skip the 640 byte header */ if (fseek(fp, 640L, 0)) return(1); count = 0; repeat = 0; while ((c = fgetc(fp)) != EOF) { /* ignore trash after row 720 */ if (row == 720) return(0); byte = c & 0xff; if (count) { /* read the next 'count' bytes */ count--; store_video(byte); continue; } if (repeat) { /* repeat the byte */ while (repeat--) store_video(byte); repeat = 0; continue; } if (byte > 127) { /* repeat factor */ repeat = 257 - byte; if (repeat > 72) return(1); continue; } count = byte + 1; /* count factor */ if (count > 72) return(1); } /* short file ? */ if (row < 720) return(1); return(0); } /* * The image is stored in a two dimensional array of unsigned short * integers 36 wide by 720 long. The 8 bit char to 16 bit short integer * conversion is reversed (typical of Intel vs. Motorola chips). In * addition, the byte order of the bit-mapped screen on the Macintosh is * right to left (meaning the most significant bit appears on the screen * to the left) and ours is left to right. The byte transposition * table 'xp_table[]' is used to transpose the bit patterns (much faster * than rotating bits 180 degrees). */ store_video(byte) unsigned char byte; { static int previous; if (hi_byte) { /* xp_table[] rotates it 180 degrees */ #ifdef INVERSE previous = 0xff - xp_table[byte]; #else INVERSE previous = xp_table[byte]; #endif INVERSE hi_byte = 0; return; } hi_byte = 1; /* reverse the byte order */ #ifdef INVERSE pic[row][col] = ((0xff - xp_table[byte]) << 8) + previous; #else INVERSE pic[row][col] = (xp_table[byte] << 8) + previous; #endif INVERSE col++; if (col == 36) { row++; col = 0; } return; } /* * roll up or down 20 pixels */ roll(direction, win) int direction; short win; { unsigned short *npic; if (direction) { /* down 20 */ next_row += 20; if (next_row > 480) { next_row = 480; wputc(win, 07); } } else { /* up 20 */ next_row -= 20; if (next_row < 0) { next_row = 0; wputc(win, 07); } } /* new pointer to pic[] array */ npic = &pic[next_row][0]; wrastop(win, npic, 72, 0, 0, 0, 0, 0, 0, 576, 240, SRCSRC, DSTSRC, 0); return; } /* * set up a borderless window */ clean_up(win) short win; { WSTAT wbuf; wprintf(win, "\033[=0C"); /* turn cursor back on */ clear(); wbuf.begy = 1; wbuf.begx = 0; wbuf.height = 24; wbuf.width = 80; wbuf.uflags = NBORDER; wsetstat(win, &wbuf); wgoto(win, 0, 0); wdelete(win); return; } /* * get a string from a window, analogous to gets() except we do the * echoing, editing, and control-c handling */ wgets(win, string) short win; char *string; { int c; char *first; first = string; while ((c = wgetc(win)) != '\r') { /* if control c */ if (c == 3) { clean_up(win); wexit(0); } /* if backspace */ if (c == 8) { string--; if (string < first) string = first; else wputc(win, c); continue; } /* provide the echo ourselves */ wputc(win, c); *string++ = (c & 0177); } wprintf(win, "\r\n"); *string = '\0'; return; } /* * Print the image on a dot matrix printer. The 'start' string sets the * vertical line spacing to 8/72 inch, the 'middle' strings sends the * code to print the next 576 characters as graphics, and the 'end' string * returns the vertical line spacing to normal. On some printers, bit 0 * is at the top, others it's on the bottom. */ print_it(win) short win; { FILE *lp; int ptr_row, up_side_down; char *start, *middle, *end, printer[10]; unsigned char *ptr_str, *get_str(); wprintf(win, "Choice of printers\n\n"); wprintf(win, "1) Epson FX\n"); wprintf(win, "2) Apple DMP/NEC 8023\n"); wprintf(win, "3) Gemini 10\n"); wprintf(win, "4) IBM Graphics Printer\n"); wprintf(win, "5) other\n\n"); again: wprintf(win, "Enter choice [1-5] : "); wgets(win, printer); switch (*printer) { case 0: /* carriage return alone */ return; case '1': /* Epson */ start = "\033A\010"; middle = "\033*\004@\002"; end = "\0332"; up_side_down = 0; break; case '2': /* Apple DMP/NEC 8023 */ start = "\033T16"; middle = "\033G0576"; end = "\033B"; up_side_down = 1; break; case '3': /* Gemini 10 */ start = "\0333\020"; middle = "\033L@\002"; end = "\0332"; up_side_down = 0; break; case '4': /* IBM Graphics Printer */ start = "\033A\010"; middle = "\033L@\002"; end = "\0332"; up_side_down = 0; break; case '5': /* Other */ start = ""; middle = ""; end = ""; up_side_down = 0; break; default: /* oops! */ goto again; } /* * Please note, a 'popen()' to the '/usr/bin/lp' command WILL NOT WORK * since the device driver for the '/dev/lp' will do post-processing and * CR-LF translations. */ if (!(lp = fopen("/dev/rawlp", "w"))) { wprintf(win, "Can't open /dev/rawlp\n"); sleep(3); clean_up(win); wexit(1); } fputs(start, lp); for (ptr_row = 0; ptr_row < 720; ptr_row += 8) { /* get a 576 char raster */ ptr_str = get_str(ptr_row, up_side_down); fputs(middle, lp); /* spit out the raster */ fwrite(ptr_str, sizeof *ptr_str, 576, lp); fputc('\n', lp); } fputs(end, lp); fputc(014, lp); pclose(lp); return; } /* * Convert that mess in the pic[] array into a printer raster of 576 chars. * A byte sent to a printer makes a 8 pixel vertical line, however the same * byte sent to the screen makes a 8 pixel horizontal line. Therefore we * must 'rotate' the bit pattern of 8 rows of integers by 90 degrees to form * a printer raster of 16 characters. (Can't use a translation table now, * since the rotation actualy involves combining bits from different bytes) */ unsigned char * get_str(ptr_row, up_side_down) int ptr_row; int up_side_down; { static unsigned char raster[576]; int ras_col, offset, ras_row, bit, mult; unsigned char pat; for (ras_col = 0; ras_col < 36; ras_col++) { /* clear previous pattern */ for (bit = 0; bit < 16; bit++) raster[(ras_col * 16) + bit] = 0; /* for each stack of 8 */ for (offset = 0; offset < 8; offset++) { ras_row = ptr_row + offset; /* rotate bit pattern 90 degrees */ for (bit = 0; bit < 16; bit++) { mult = 1 << bit; #ifdef INVERSE if ((0xffff - pic[ras_row][ras_col]) & mult) { #else INVERSE if (pic[ras_row][ras_col] & mult) { #endif INVERSE if (up_side_down) pat = 1 << offset; else pat = 1 << (7 - offset); raster[(ras_col * 16) + bit] |= pat; } } } } return(raster); }