head 1.5; access ; symbols ; locks ; comment @ * @; 1.5 date 89.01.31.14.27.13; author pkern; state Exp; branches ; next 1.4; 1.4 date 89.01.31.13.34.21; author pkern; state Exp; branches ; next 1.3; 1.3 date 89.01.05.12.02.49; author pkern; state Exp; branches ; next 1.2; 1.2 date 89.01.05.11.36.30; author pkern; state Exp; branches ; next 1.1; 1.1 date 89.01.04.20.08.25; author pkern; state Exp; branches ; next ; desc @@ 1.5 log @*** empty log message *** @ text @/* * screen handling routines for TI Professional (including graphics) * * Notes: * - the attribute information for individual positions on the screen * can only be accessed through AH=0x08 (as far as I can tell). * This would take too long when saving the screen image so * attributes are lost when switching save_scr() to restore_scr(). * * - it seems necessary to assert the status line after each CLEANing * (a minor annoyance, but if we want to enforce a status line ...) * * copyright (c) University of Toronto, 1988. */ static char rcsid[] = "$Header$"; #include #include "common.h" #include "tipro.h" #define BLANK 0x0f /* #define SCR_MEM (0xde000000) /* screen location */ #define SCR_MEM (0xde00) /* screen location segment */ #define L_ATTR *((char far *)0xdf000800) /* attribute latch */ #define CRSR_BLK 0x600c /* slow-blinking block cursor code */ #define CRSR_UL 0x4b0b /* fast-blinking underline cursor */ static union REGS r; static struct SREGS sr; static int xattr=0x0f; /* attribute storage */ /* static */ char o_scrn[SCRSIZE]; /* screen memory storage */ static int o_xy; /* cursor position memory */ static char far *scrn; /* screen position memory */ /* macros for frequently used code */ #define crtint int86(CRT_INT, &r, &r) #define GO_HOME r.h.ah=2; r.x.dx=0; crtint; #define DO_STAT r.h.ah=0x15; r.x.cx=24; crtint; #define GO_XY(a,b) \ r.h.ah=2; r.h.dh=(a); r.h.dl=(b); crtint; #define CLEAN(n) \ r.x.ax=0x0920; r.h.bl=BLANK; r.x.cx=(n); \ crtint; L_ATTR = xattr; /* set status region on 25th line */ init_scr() { DO_STAT segread(&sr); } /* eliminate status region, reset attributes */ reset_scr() { r.h.ah = 0x15; r.x.cx = 0; crtint; L_ATTR = BLANK; } curs_xy(x, y) uchar x, y; { GO_XY(x-1, y-1) } xypos(xp, yp) uchar *xp, *yp; { r.h.ah = 3; crtint; *xp = r.h.dh+1; *yp = r.h.dl+1; } /* scroll up n lines between min_y and max_y */ scrl_up(n, min_y, max_y, x, y) uchar n, min_y, max_y, x, y; { r.h.ah = 6; r.h.al = 1; r.h.dh = 0; r.h.dl = min_y-1+n; r.h.bh = 0; r.h.bl = min_y-1; r.h.ch = 80; r.h.cl = max_y - (min_y-1) - n; crtint; GO_XY(0, max_y-n) CLEAN(80 * n) GO_XY(x-1, y-1) DO_STAT } /* scroll down n lines between min_y and max_y */ scrl_down(n, min_y, max_y, x, y) uchar n, min_y, max_y, x, y; { r.h.ah = 7; r.h.al = 1; r.h.dh = 0; r.h.dl = min_y-1; r.h.bh = 0; r.h.bl = min_y-1+n; r.h.ch = 80; r.h.cl = max_y - (min_y-1) - n; crtint; GO_XY(0, min_y-1) CLEAN(80 * n) GO_XY(x-1, y-1) DO_STAT } /* eol : erase to end of line */ eol_erase(x, y) uchar x, y; { if (x > 80) return; CLEAN(80-(x-1)) DO_STAT } /* * bol : erase from beginning of line to cursor pos. * ie. goto head of line, erase chars, return to original pos */ bol_erase(x, y) uchar x, y; { GO_XY(0, y-1) CLEAN(x) GO_XY(x-1, y-1) DO_STAT } /* eos : erase to end of line and to end of screen */ eos_erase(x, y) uchar x, y; { CLEAN( (24-y) * 80 + (80-(x-1)) ) DO_STAT } /* * bos : erase from beginning of screen (home) to cursor pos. * ie. goto head of screen, erase to original pos, return to position */ bos_erase(x, y) uchar x, y; { GO_HOME CLEAN(80 * (y-1) + x) GO_XY(x-1, y-1) DO_STAT } /* goto head of line, erase line, return to original pos */ line_erase(x, y) uchar x, y; { GO_XY(0, y-1) CLEAN(80) GO_XY(x-1, y-1) DO_STAT } /* goto head of screen, erase all, return to pos */ /* could've used AH=0x13 but it also erases the status line */ all_erase(x, y) uchar x, y; { GO_HOME CLEAN(80*24) GO_XY(x-1, y-1) DO_STAT } /* * insert line(s) : * scroll down n lines, goto head of original line, erase empty space */ line_ins(n, x, y, max_y) uchar n, x, y, max_y; { if (y-1+n < max_y) { r.h.ah = 6; r.h.al = 1; r.h.dh = 0; r.h.dl = y-1; r.h.bh = 0; r.h.bl = y-1+n; r.h.ch = 80; r.h.cl = max_y-(y-1)-n; crtint; } else n = max_y - (y-1); GO_XY(0, y-1) CLEAN(80 * n) DO_STAT } /* * delete line(s) : * scroll up n lines, goto new empty line, erase lines, * return to head of original line */ line_del(n, x, y, max_y) uchar n, x, y, max_y; { if (y-1+n < max_y) { r.h.ah = 6; r.h.al = 1; r.h.dh = 0; r.h.dl = y-1+n; r.h.bh = 0; r.h.bl = y-1; r.h.ch = 80; r.h.cl = max_y-(y-1)-n; crtint; } else n = max_y - (y-1); GO_XY(0, max_y-n) CLEAN(80 * n) GO_XY(0, y-1) DO_STAT } /* * delete char(s) : * ie. scroll rest of line to the left, goto line-end, erase n chars * and return to original cursor pos */ char_del(n, x, y) uchar n, x, y; { if (x-1+n < 80) { r.h.ah = 6; r.h.al = 1; r.h.dh = x-1+n; r.h.dl = y-1; r.h.bh = x-1; r.h.bl = y-1; r.h.ch = 80-(x-1)-n; r.h.cl = 1; crtint; } else n = 80-(x-1); GO_XY(80-n, y-1) CLEAN(n) GO_XY(x-1, y-1) DO_STAT } /* * insert char(s) : * ie. scroll rest of line to right and clean out new space(s) */ char_ins(n, x, y) uchar n, x, y; { if (x-1+n < 80) { r.h.ah = 6; r.h.al = 1; r.h.dh = x-1; r.h.dl = y-1; r.h.bh = x-1+n; r.h.bl = y-1; r.h.ch = 80-(x-1)-n; r.h.cl = 1; crtint; } else n = 80-(x-1); CLEAN(n) DO_STAT } /* set attributes * "bold" = 2 levels dimmer * reverse video also = 2 levels dimmer. * (so reverse and bold is 4 levels dimmer) */ attribs(attr) uchar attr; { r.h.ah = 0x16; r.h.bl = 0x0f; /* char enable, max intensity */ if (attr & AT_BOLD) { r.h.bl -= 3; attr &= 0x07; } if (attr & AT_REV) r.h.bl -= 2; r.h.bl |= (attr << 4); L_ATTR = r.h.bl; xattr = r.h.bl; /* crtint; */ } /* * screen alignment test : * home cursor and write a screen of E's in normal attrib mode. * previous attribs are not forgotten. */ e_screen() { GO_HOME r.h.ah = 0x0a; r.h.al = 'E'; r.h.bl = 0x1d; /* ordinary attribs */ r.x.cx = 80 * 24; crtint; /* screen of E's */ L_ATTR = xattr; DO_STAT } /* basic single-char output */ burpc(c, x, y) int c, x, y; { r.h.ah = 0x0e; r.h.al = c; crtint; } /* insert mode burpc() */ /* move line right, deposit char */ insurpc(c, x, y) int c, x, y; { if (x < 80) { r.h.ah = 6; r.h.al = 1; r.h.bh = x; r.h.bl = y-1; r.h.ch = 80-x; r.h.cl = 1; r.h.dh = x-1; r.h.dl = y-1; crtint; } r.h.ah = 0x0e; r.h.al = c; crtint; } /* output string at x,y with attr */ burps(s, x, y, at) char *s; uchar x, y, at; { GO_XY(x-1, y-1) r.h.ah = 0x10; r.h.al = 0x0f; if (at & AT_BOLD) { r.h.al -= 2; at &= 0x07; } if (at & AT_REV) r.h.al -= 2; r.h.al |= (at << 4); xattr = r.h.al; r.x.bx = (int)s; r.x.cx = strlen(s); r.x.dx = sr.ds; crtint; } /* set cursor type */ curs_type(sw) uchar sw; { r.h.ah = 1; r.x.cx = (sw) ? CRSR_BLK : CRSR_UL; crtint; } /* save screen image & cursor position */ save_scr() { register int n; register char *os; register char far *s; r.h.ah = 3; crtint; o_xy = r.x.dx; r.h.ah = 0x17; crtint; /* scrn = SCR_MEM | r.x.dx; */ scrn = (char far *) MK_FP(SCR_MEM, r.x.dx); n = SCRSIZE; s = scrn; os = o_scrn; while (n--) *os++ = *s++; } /* restore screen image & cursor position */ restore_scr() { register int n; register char *os; register char far *s; r.h.ah = 0x17; crtint; /* scrn = SCR_MEM | r.x.dx; */ scrn = (char far *) MK_FP(SCR_MEM, r.x.dx); n = SCRSIZE; s = scrn; os = o_scrn; while (n--) *s++ = *os++; r.h.ah = 2; r.x.dx = o_xy; crtint; } /* write string to status line */ uchar stcolour=3; sturp(s, x, y) char *s; int x, y; { GO_XY(0, 24) r.h.ah = 0x10; r.h.al = (stcolour) ? (0x18 | stcolour) : 0; r.x.bx = (int)s; r.x.cx = strlen(s); r.x.dx = sr.ds; crtint; GO_XY(x-1, y-1) L_ATTR = xattr; } /* delay for n milliseconds */ dsleep(n) unsigned int n; { r.h.ah = 5; r.x.cx = n; int86(0x48, &r, &r); } /* bios -- Clear Text Screen And Home the Cursor */ clr_home() { r.h.ah = 0x13; crtint; } /* dburp -- put debug message on status line */ dburp(s) char *s; { uchar x, y; xypos(&x, &y); sturp(s, x, y); } /* erase graphics screen */ gfx_erase() { r.h.ah = 0x14; crtint; } /* TI Pro graphics nitty-gritty */ /* graphics screen limits */ #define GMAX_X 720 #define GMAX_Y 300 /* graphics palette attribute latches */ #define L_BLU *((char far *)0xdf000010) #define L_GRN *((char far *)0xdf000020) #define L_RED *((char far *)0xdf000030) static uchar l_blu=0xAA, l_red=0xCC, l_grn=0xF0; #define L_SYNC L_BLU=l_blu; L_RED=l_red; L_GRN=l_grn; /* graphics bank (or plane) access */ #define GBa(i) *((unsigned int far *)0xc0000000+i) #define GBb(i) *((unsigned int far *)0xc8000000+i) #define GBc(i) *((unsigned int far *)0xd0000000+i) #define GBOFS(a,b) (((b)*46)+((a)/16)) /* x,y byte offset */ #define GMASK(a) (0x8000 >> ((a)%16)) /* bit offset for x */ init_gfx() { extern int gmax_x, gmax_y; extern uchar interlace, gcolour; L_BLU = L_RED = L_GRN = 0; gmax_x = GMAX_X; gmax_y = GMAX_Y; if (interlace) { gcolour = 7; L_SYNC } } static unsigned int ofs, msk; #define BOINK(a) \ GBa(ofs) = (a & 1) ? (GBa(ofs) | msk) : (GBa(ofs) & ~msk); \ GBb(ofs) = (a & 4) ? (GBb(ofs) | msk) : (GBb(ofs) & ~msk); \ GBc(ofs) = (a & 2) ? (GBc(ofs) | msk) : (GBc(ofs) & ~msk); #define GPEEK \ ((((GBa(ofs) & msk) == msk) * 1) \ | (((GBc(ofs) & msk) == msk) * 2) \ | (((GBb(ofs) & msk) == msk) * 4)) /* gpeek -- get a pixel's colour */ gpeek(x, y) int x, y; { uchar c; msk = GMASK(x); ofs = GBOFS(x,y); /* * c = ((GBa(ofs) & msk) == msk); * c |= ((GBc(ofs) & msk) == msk) << 1; * c |= ((GBb(ofs) & msk) == msk) << 2; */ c = GPEEK; return(c); } /* boink -- light a pixel */ boink(x,y,c) int x, y; uchar c; { msk = GMASK(x); ofs = GBOFS(x,y); BOINK(c) } /* * hline -- only does horizontal lines (union regulations :-) * use solid(ie. multi bit) masks and increment the offset */ hline(x,y,n,c) int x,y,n; uchar c; { if (n < 0) { n = -n; x -= n; if (x < 0) { n += x; x = 0; } } msk = 0xffff >> (x%16); /* make mask go to end of 16bit word */ for(ofs=GBOFS(x,y); ofs < GBOFS(x+n, y); ofs++) { BOINK(c) msk = 0xffff; /* ie. solid while between end-points */ } msk &= ~(0xffff >> ((x+n)%16)); /* remainder word mask */ BOINK(c) } /* * vline -- vertical lines only * get bit mask once then move it up or down * by changing only the offset +/- 46. */ vline(x,y,n,c) int x,y,n; uchar c; { if (n < 0) { n = -n; y -= n; if (y < 0) { n += y; y = 0; } } msk = GMASK(x); ofs = GBOFS(x,y); for (; n; n--, ofs+=46) { BOINK(c) } } /* xrun -- optimize search for runs in x direction */ xrun(x, y, c, dir) int x, y, dir; uchar c; { uchar cx; unsigned int ba, bb, bc; msk = GMASK(x); ofs = GBOFS(x,y); ba = GBa(ofs); bb = GBb(ofs); bc = GBc(ofs); while (0 <= x && x < GMAX_X) { cx = ((ba & msk) == msk) \ + (((bc & msk) == msk) * 2)\ + (((bb & msk) == msk) * 4); if (c == cx) break; x += dir; msk = GMASK(x); if (((dir > 0) && (x%16) == 0) || ((dir < 0) && (x%16) == 15)) { ofs = GBOFS(x,y); ba = GBa(ofs); bb = GBb(ofs); bc = GBc(ofs); } } if (c == cx) x -= dir; if (x < 0) return(0); if (x >= GMAX_X) return(GMAX_X-1); return(x); } @ 1.4 log @minor cleaning @ text @d15 1 a15 1 static char *ID = "screen.c Oct/88 Univ. of Toronto"; @ 1.3 log @*** empty log message *** @ text @d595 2 @ 1.2 log @graphics nitty-gritty moved in from gfx.c @ text @d470 2 a471 2 #define GBOFS(a,b) (((b)*46)+((a)/16)) #define GMASK(a) (0x8000 >> ((a)%16)) a474 1 extern uchar interlace; d476 1 d479 1 @ 1.1 log @Initial revision @ text @d2 1 a2 1 * screen handling routines for TI Professional d11 1 a11 1 * (a minor annoyance, if we want to enforce a status line) d449 146 @