7103_300@uwovax.uwo.ca (Eric Smith) (02/09/89)
Here's a screen driver that allows low level access to the bitmapped graphics screen. It's specifically written for the Atari ST, but may be portable to the IBM without undue work (I've tried hard to make the interface as general as possible). This may give us something on which to base a screen manager like MGR; that's what I hope, anyways. -- Eric R. Smith email: Dept. of Mathematics 7103_300@uwovax.uwo.ca University of Western Ontario 7103_300@uwovax.bitnet London, Ont. Canada N6A 5B7 (a shared mailbox: put my name on ph: (519) 661-3638 the message, please!) ------------ cut here ------------ #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: README h.cdiff kernel.cdiff lib.cdiff sttools.cdiff # setcolr.c showpic.c # Wrapped by eric@Eric's Minix/ST on Wed Feb 8 23:41:18 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3468 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XEnclosed are the diffs and files necessary to install a screen Xdriver for the Atari ST version of Minix. All of the files ending Xin .cdiff should be run through 'patch' in the appropriate directory X(e.g. lib.cdiff are the patches for the C library, and kernel.cdiff Xare the patches for the kernel). The file "h/screen.h" contains Xdefinitions for accessing the screen, and should also be copied Xto /usr/include/minix. X XFinally, you should cd to /dev and enter: Xmknod screen c 1 4; chmod 666 screen X XTwo sample programs are also included. Showpic.c is a program for Xdisplaying DEGAS format picture files; it takes one argument, Xthe name of the file to display. Setcolr.c is a program for changing Xscreen colors. It takes 4 arguments; the first is the index of the Xcolor to change (0-16), and the second, third, and fourth are the Xred, green, and blue values respectively to set the color to. These Xmay range from 0 (minimum) to 255 (maximum). For example, the commands X setcolr 0 255 255 255; setcolr 1 0 0 0 Xchange the foreground color to white and the background color to black. XIn medium resolution, only colors 0-3 are meaningful; in high res only Xcolor 0 is meaningful, and can only assume two values, 0 (black) or X255 (white). X XThings you can do with the screen driver: X XFirstly, it's a normal device; so X cp /dev/screen junk Xcreates a screen dump in the file junk; later you can type X cp junk /dev/screen Xto restore the old screen image. X XSecondly, various ioctl options are provided to allow for getting/setting Xvarious screen parameters: X Xstruct scr_palette sc; X Xioctl(fd, SCRGETCOLOR, &sc): Xioctl(fd, SCRSETCOLOR, &sc): X Get/set the screen color palette. This is a structure which X contains one member, an array called scr_rgb. sc.scr_rgb[i][0] X contains the red value (0..255) for color i, sc.scr_rgb[i][1] the X green value, and sc.scr_rgb[i][2] the blue. X Xstruct scr_param sp; X Xioctl(fd, SCRGETPARAM, &sp): Xioctl(fd, SCRGETPARAM, &sp): X Get/set various screen parameters. The members of sp are: X scr_width, scr_height: width and height of screen X scr_depth: number of bits used for each pixel X scr_mode: resolution: 0 for low, 1 for medium, 2 for high X scr_base: physical address of the screen X At present, only scr_mode and scr_base can be changed with the X SCRSETPARAM call (although changes to scr_mode will automatically X imply changes to the screen's height, width, and depth). X XVarious useful constants are defined in <minix/screen.h>; the comments Xshould explain them. X XBUGS: X The console output routines and the screen driver don't know Xabout each other. If you change the screen's physical address, you have Xto send the appropriate ANSI codes to reset the tty, or no output Xwill appear on screen (this could be construed as a feature, since it Xmeans no interference with your graphics display). X The screen driver does its work without concern for the Xniceties of video refresh; rapid page-flipping is likely to produce Xugly results. X If you're running a multi-user system, security could be Xa problem; allowing anyone else either read OR write access to Xthe screen means that they can basically do what they want to it. X I haven't tested this in monochrome, but it should work XOK. X XIf you find bugs, let me know at the e-mail address below. X XPLEASE NOTE: I share this mailbox with the rest of my department, so Xif you want to make sure I get your mail, put "To: Eric Smith" as Xthe subject line! X XEric R. Smith X7103_300@uwovax.uwo.ca END_OF_FILE if test 3468 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'h.cdiff' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'h.cdiff'\" else echo shar: Extracting \"'h.cdiff'\" \(2623 characters\) sed "s/^X//" >'h.cdiff' <<'END_OF_FILE' X*** /tmp/,RCSt1000097 Wed Feb 8 23:09:51 1989 X--- com.h Wed Feb 8 23:08:41 1989 X*************** X*** 34,39 **** X--- 34,40 ---- X # define MEM_DEV 1 /* minor device for /dev/mem */ X # define KMEM_DEV 2 /* minor device for /dev/kmem */ X # define NULL_DEV 3 /* minor device for /dev/null */ X+ # define SCR_DEV 4 /* minor device for /dev/screen */ X X #define FLOPPY -5 /* floppy disk class */ X #define WINCHESTER -6 /* winchester (hard) disk class */ X*** screen.h.B Wed Feb 8 23:10:13 1989 X--- screen.h Wed Feb 8 23:07:42 1989 X*************** X*** 0 **** X--- 1,57 ---- X+ /* Data structures for IOCTL on /dev/screen */ X+ X+ #define SCR_NUM_COLORS 16 /* max possible num. of colors */ X+ X+ /* SCR_ALIGN gives a mask telling how the physical screen must be X+ aligned (for the SCRSETP ioctl call. A typical use might be X+ newscrn = malloc(size + SCR_ALIGN) & (~SCR_ALIGN) X+ If SCR_ALIGN is -1, then the physical screen may not be remapped X+ */ X+ #define SCR_ALIGN 0x0ffL X+ X+ /* define the following only if the physical memory occupied by the X+ screen is not accessible to user programs without an operating X+ system request to re-map or shar memory (i.e. don't define this X+ unless you have a version of Minix with a hardware memory X+ manager X+ */ X+ /* #define SCR_VIRT_MEM /* screen lives in virtual memory */ X+ X+ X+ /* physical screen attributes; information returned by the X+ SCRGETPARAM ioctl call */ X+ X+ struct scr_param { X+ long scr_base; /* physical address of screen */ X+ short scr_width; /* width of screen (pixels) */ X+ short scr_height; /* height of screen (pixels) */ X+ short scr_depth; /* no. of bitplanes on screen */ X+ short scr_mode; /* special mode info about screen */ X+ }; X+ X+ /* Each palette entry for the screen colors holds three entries; X+ the red, green, and blue values for this color, from 0 (no color) X+ to 255 (max. color). X+ The actual number of different values recognized by the hardware X+ is given by SCR_RGB_VALUES; for example, the atari ST recognizes X+ only 8 possible values for each of red, green, and blue, for X+ a total of 512 colors; for it, SCR_RGB_VALUES == 8. X+ */ X+ X+ #define SCR_RGB_VALUES 8 X+ X+ /* constants for accessing the scr_rgb array */ X+ #define RED 0 X+ #define BLUE 1 X+ #define GREEN 2 X+ X+ /* data structure returned by SCRGETCOLOR ioctl call */ X+ struct scr_palette { X+ unsigned char scr_rgb[SCR_NUM_COLORS][3]; X+ }; X+ X+ X+ #define SCRGETPARAM (('S'<<8) | 1) X+ #define SCRSETPARAM (('S'<<8) | 2) X+ #define SCRGETCOLOR (('S'<<8) | 3) X+ #define SCRSETCOLOR (('S'<<8) | 4) END_OF_FILE if test 2623 -ne `wc -c <'h.cdiff'`; then echo shar: \"'h.cdiff'\" unpacked with wrong size! fi # end of 'h.cdiff' fi if test -f 'kernel.cdiff' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'kernel.cdiff'\" else echo shar: Extracting \"'kernel.cdiff'\" \(6339 characters\) sed "s/^X//" >'kernel.cdiff' <<'END_OF_FILE' X*** /tmp/,RCSt1000068 Wed Feb 8 23:05:04 1989 X--- memory.c Wed Feb 8 22:14:13 1989 X*************** X*** 3,8 **** X--- 3,10 ---- X * /dev/mem - absolute memory X * /dev/kmem - kernel virtual memory X * /dev/ram - RAM disk X+ * /dev/screen - screen memory X+ * X * It accepts three messages, for reading, for writing, and for X * control. All use message format m2 and with these parameters: X * X*************** X*** 14,19 **** X--- 16,31 ---- X * |------------+---------+---------+---------+---------+---------| X * | DISK_IOCTL | device | | blocks | ram org | | X * ---------------------------------------------------------------- X+ * X+ * In addition, the screen driver accepts ioctl messages like the X+ * ones sent to the TTY driver (actually, they're the same message X+ * format, but it seems more logical to use the TTY names for the X+ * fields). X+ * X+ * m_type TTY_LINE PROC_NR COUNT TTY_SPEK TTY_FLAGS ADDRESS X+ * --------------------------------------------------------------------------- X+ * | TTY_IOCTL | device | proc nr | func code| buf ptr |flags | | X+ * --------------------------------------------------------------------------- X * X * X * The file contains one entry point: X*************** X*** 27,37 **** X #include "../h/callnr.h" X #include "../h/com.h" X #include "../h/error.h" X #include "const.h" X #include "type.h" X #include "proc.h" X X! #define NR_RAMS 4 /* number of RAM-type devices */ X #ifdef i8088 X #define EM_ORIGIN 0x100000 /* origin of extended memory on the AT */ X #endif X--- 39,57 ---- X #include "../h/callnr.h" X #include "../h/com.h" X #include "../h/error.h" X+ #include "../h/screen.h" X #include "const.h" X #include "type.h" X #include "proc.h" X X! #define MULT (256/SCR_RGB_VALUES) X! X! #ifdef ATARI_ST X! #include "staddr.h" X! #include "stvideo.h" /* for screen driver */ X! #endif X! X! #define NR_RAMS 5 /* number of RAM-type devices */ X #ifdef i8088 X #define EM_ORIGIN 0x100000 /* origin of extended memory on the AT */ X #endif X*************** X*** 60,65 **** X--- 80,93 ---- X ram_limit[KMEM_DEV] = (sizes[0] + sizes[1]) << CLICK_SHIFT; X ram_limit[MEM_DEV] = MEM_BYTES; X X+ #ifdef ATARI_ST X+ ram_origin[SCR_DEV] = (phys_bytes) ( X+ ( (VIDEO->vd_ramh & 0xFF) << 16L) X+ | X+ ((VIDEO->vd_ramm & 0xFF) << 8L) ); X+ ram_limit[SCR_DEV] = ram_origin[SCR_DEV] + 32000L; X+ #endif X+ X /* Here is the main loop of the memory task. It waits for a message, carries X * it out, and sends a reply. X */ X*************** X*** 75,80 **** X--- 103,109 ---- X switch(mess.m_type) { X case DISK_READ: r = do_mem(&mess); break; X case DISK_WRITE: r = do_mem(&mess); break; X+ /* case TTY_IOCTL: -- same value as DISK_IOCTL */ X case DISK_IOCTL: r = do_setup(&mess); break; X default: r = EINVAL; break; X } X*************** X*** 94,100 **** X PRIVATE int do_mem(m_ptr) X register message *m_ptr; /* pointer to read or write message */ X { X! /* Read or write /dev/null, /dev/mem, /dev/kmem, or /dev/ram. */ X X #ifdef i8088 X int device, count, words, status; X--- 123,129 ---- X PRIVATE int do_mem(m_ptr) X register message *m_ptr; /* pointer to read or write message */ X { X! /* Read or write /dev/null, /dev/mem, /dev/kmem, /dev/ram, or /dev/screen. */ X X #ifdef i8088 X int device, count, words, status; X*************** X*** 160,167 **** X--- 189,293 ---- X int device; X X device = m_ptr->DEVICE; X+ if (device == SCR_DEV) X+ return do_ioctl(m_ptr); X if (device != RAM_DEV) return(ENXIO); /* bad minor device */ X ram_origin[device] = m_ptr->POSITION; X ram_limit[device] = m_ptr->POSITION + (long) m_ptr->COUNT * BLOCK_SIZE; X return(OK); X+ } X+ X+ /*===========================================================================* X+ * do_ioctl * X+ *===========================================================================*/ X+ PRIVATE do_ioctl(m_ptr) X+ message *m_ptr; /* pointer to message sent to task */ X+ { X+ X+ static struct scr_param sp; X+ static struct scr_palette sc; X+ X+ int r, count, set, request, i; X+ unsigned short color; X+ phys_bytes user_buf, our_buf; X+ struct proc *rp; X+ extern phys_bytes umap(); X+ X+ r = OK; X+ rp = proc_addr(m_ptr->PROC_NR); X+ request = m_ptr->TTY_REQUEST; X+ if (request == SCRGETPARAM || request == SCRSETPARAM) { X+ count = sizeof(sp); X+ our_buf = (phys_bytes) &sp; X+ set = (request == SCRSETPARAM); X+ } X+ else if (request == SCRGETCOLOR || request == SCRSETCOLOR) { X+ count = sizeof(sc); X+ our_buf = (phys_bytes) ≻ X+ set = (request == SCRSETCOLOR); X+ } X+ else X+ return EINVAL; X+ X+ user_buf = umap(rp,D,(vir_bytes) m_ptr->TTY_SPEK,(vir_bytes) count); X+ if (set) X+ phys_copy(user_buf, our_buf, (long) count); X+ X+ switch (request) { X+ case SCRGETPARAM: X+ sp.scr_base = ram_origin[SCR_DEV]; X+ #ifdef ATARI_ST X+ sp.scr_mode = (VIDEO->vd_res) & 0x03; X+ switch (sp.scr_mode) { X+ case RES_LOW: X+ sp.scr_width = 320; X+ sp.scr_height = 200; X+ sp.scr_depth = 4; X+ break; X+ case RES_MID: X+ sp.scr_width = 640; X+ sp.scr_height = 200; X+ sp.scr_depth = 2; X+ break; X+ default: X+ sp.scr_width = 640; X+ sp.scr_height = 400; X+ sp.scr_depth = 1; X+ break; X+ } X+ #endif X+ break; X+ case SCRSETPARAM: X+ VIDEO->vd_res = sp.scr_mode & 0x03; X+ ram_origin[SCR_DEV] = sp.scr_base & 0x00ffff00L; X+ ram_limit[SCR_DEV] = ram_origin[SCR_DEV] + 32000L; X+ VIDEO->vd_ramh = (sp.scr_base & 0x00ff0000L) >> 16; X+ VIDEO->vd_ramm = (sp.scr_base & 0x0000ff00L) >> 8; X+ break; X+ case SCRGETCOLOR: X+ for (i = 0; i < SCR_NUM_COLORS; i++) { X+ #ifdef ATARI_ST X+ color = VIDEO->vd_rgb[i]; X+ sc.scr_rgb[i][BLUE] = MULT * (color & RGB_B); X+ sc.scr_rgb[i][GREEN] = MULT * ((color & RGB_G) >> 4); X+ sc.scr_rgb[i][RED] = MULT * ((color & RGB_R) >> 8); X+ #endif X+ } X+ break; X+ case SCRSETCOLOR: X+ for (i = 0; i < SCR_NUM_COLORS; i++) { X+ #ifdef ATARI_ST X+ color = sc.scr_rgb[i][RED] / MULT; X+ color = color << 4; X+ color |= (sc.scr_rgb[i][GREEN] / MULT); X+ color = color << 4; X+ color |= (sc.scr_rgb[i][BLUE] / MULT); X+ VIDEO->vd_rgb[i] = color; X+ #endif X+ } X+ break; X+ } X+ if (!set) X+ phys_copy(our_buf, user_buf, (long) count); X+ return r; X } END_OF_FILE if test 6339 -ne `wc -c <'kernel.cdiff'`; then echo shar: \"'kernel.cdiff'\" unpacked with wrong size! fi # end of 'kernel.cdiff' fi if test -f 'lib.cdiff' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lib.cdiff'\" else echo shar: Extracting \"'lib.cdiff'\" \(785 characters\) sed "s/^X//" >'lib.cdiff' <<'END_OF_FILE' X*** /tmp/,RCSt1000122 Wed Feb 8 23:14:07 1989 X--- ioctl.c Wed Feb 8 16:03:49 1989 X*************** X*** 1,6 **** X--- 1,7 ---- X #include "lib.h" X #include <minix/com.h> X #include <sgtty.h> X+ #include <minix/screen.h> X X PUBLIC int ioctl(fd, request, u) X int fd; X*************** X*** 8,13 **** X--- 9,16 ---- X union { X struct sgttyb *argp; X struct tchars *argt; X+ struct scr_param *args1; X+ struct scr_palette *args2; X } u; X X { X*************** X*** 55,60 **** X--- 58,71 ---- X u.argt->t_brkc = (M.TTY_FLAGS >> 8) & 0377; X return(n); X X+ case SCRSETPARAM: X+ case SCRGETPARAM: X+ case SCRSETCOLOR: X+ case SCRGETCOLOR: X+ M.TTY_SPEK = (long) u.args1; X+ n = callx(FS, IOCTL); X+ return(n); X+ X default: X n = -1; X errno = -(EINVAL); END_OF_FILE if test 785 -ne `wc -c <'lib.cdiff'`; then echo shar: \"'lib.cdiff'\" unpacked with wrong size! fi # end of 'lib.cdiff' fi if test -f 'sttools.cdiff' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sttools.cdiff'\" else echo shar: Extracting \"'sttools.cdiff'\" \(367 characters\) sed "s/^X//" >'sttools.cdiff' <<'END_OF_FILE' X*** /tmp/,RCSt1000111 Wed Feb 8 23:12:41 1989 X--- Makedev Wed Feb 8 23:02:58 1989 X*************** X*** 2,7 **** X--- 2,8 ---- X mknod mem c 1 1; chmod 640 mem X mknod kmem c 1 2; chmod 640 kmem X mknod null c 1 3; chmod 666 null X+ mknod screen c 1 4; chmod 666 screen X mknod fd0 b 2 0; chmod 666 fd0 X mknod fd1 b 2 1; chmod 666 fd1 X mknod dd0 b 2 8; chmod 666 dd0 END_OF_FILE if test 367 -ne `wc -c <'sttools.cdiff'`; then echo shar: \"'sttools.cdiff'\" unpacked with wrong size! fi # end of 'sttools.cdiff' fi if test -f 'setcolr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'setcolr.c'\" else echo shar: Extracting \"'setcolr.c'\" \(648 characters\) sed "s/^X//" >'setcolr.c' <<'END_OF_FILE' X#include <stdio.h> X#include <minix/screen.h> X Xmain(argc, argv) Xint argc; char *argv[]; X{ X int n, red, green, blue, fd; X struct scr_palette sc; X X if (argc != 5) { X fprintf(stderr, "Usage: setcolr n red green blue\n"); X exit(1); X } X n = atoi(argv[1]); X if (n < 0 || n >= SCR_NUM_COLORS) { X fprintf(stderr, "Illegal color number\n"); X exit(1); X } X red = atoi(argv[2]); X green = atoi(argv[3]); X blue = atoi(argv[4]); X if ( (fd = open("/dev/screen", 0)) < 0) { X perror("/dev/screen"); X exit(2); X } X ioctl(fd, SCRGETCOLOR, &sc); X sc.scr_rgb[n][RED] = red; X sc.scr_rgb[n][GREEN] = green; X sc.scr_rgb[n][BLUE] = blue; X ioctl(fd, SCRSETCOLOR, &sc); X} END_OF_FILE if test 648 -ne `wc -c <'setcolr.c'`; then echo shar: \"'setcolr.c'\" unpacked with wrong size! fi # end of 'setcolr.c' fi if test -f 'showpic.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'showpic.c'\" else echo shar: Extracting \"'showpic.c'\" \(2115 characters\) sed "s/^X//" >'showpic.c' <<'END_OF_FILE' X/* Program to display DEGAS format pictures on the screen */ X X#include <stdio.h> X#include <minix/screen.h> X#define MULT (256/SCR_RGB_VALUES) X Xstruct scr_palette newsc, oldsc; Xstruct scr_param sp; X Xmain(argc, argv) Xint argc; char *argv[]; X{ X extern char *malloc(); X long screen, buff; X int scr, pic; X int red, green, blue; X unsigned short color, res, oldres; X int i; X X if (argc != 2) { X fprintf(stderr, "Usage: showpic file\n"); X exit(1); X } X X if ( (buff = (long) malloc(32000 + SCR_ALIGN)) == 0L) { X fprintf(stderr, "Couldn't allocate 32K\n"); X exit(1); X } X buff &= (~SCR_ALIGN); X X/* open picture file */ X if ( (pic = open(argv[1], 0)) < 0 ) { X perror(argv[1]); X exit(1); X } X X/* open screen */ X if ( (scr = open("/dev/screen", 0)) < 0 ) { X perror("/dev/screen"); X exit(2); X } X X/* get screen parameters and colors */ X ioctl(scr, SCRGETPARAM, &sp); X ioctl(scr, SCRGETCOLOR, &oldsc); X X read(pic, &res, 2); /* read resolution */ X if (res < 0 || res > 2) { X fprintf(stderr, "%s: not a DEGAS picture file!\n", argv[1]); X exit(1); X } X if (res == 2 && sp.scr_mode != 2) { X fprintf(stderr, "Can't view mono picture in color.\n"); X exit(1); X } X else if (sp.scr_mode == 2 && res != 2) { X fprintf(stderr, "Can't view color picture in mono.\n"); X exit(1); X } X X/* set up screen colors to match picture */ X for (i = 0; i < 16; i++) { X read(pic, &color, 2); X newsc.scr_rgb[i][BLUE] = MULT * (color & 0x007); X newsc.scr_rgb[i][GREEN] = MULT * ((color & 0x070) >> 4); X newsc.scr_rgb[i][RED] = MULT * ((color & 0x0700) >> 8); X } X X/* read picture */ X read(pic, buff, 32000); X X/* set screen resolution to match picture */ X oldres = sp.scr_mode; X sp.scr_mode = res; X X/* save old screen address, then set the new address and new colors */ X screen = sp.scr_base; X sp.scr_base = buff; X ioctl(scr, SCRSETPARAM, &sp); X ioctl(scr, SCRSETCOLOR, &newsc); X X/* wait for user to hit return */ X read(0, &color, 1); X X/* restore former screen attributes, colors, and address */ X sp.scr_mode = oldres; X sp.scr_base = screen; X ioctl(scr, SCRSETPARAM, &sp); X ioctl(scr, SCRSETCOLOR, &oldsc); X X/* tidy up */ X close(pic); X close(scr); X} END_OF_FILE if test 2115 -ne `wc -c <'showpic.c'`; then echo shar: \"'showpic.c'\" unpacked with wrong size! fi # end of 'showpic.c' fi echo shar: End of shell archive. exit 0