rosenkra@hall.cray.com (Bill Rosenkranz) (09/13/89)
--- someone wanted some non-GEM put pixel routine. here are some line-A calls for C (written for alcyon/madmac, should work with sozobon)... i wrote these a long time ago but they should be ok and be pretty fast. if u really need speed, write in asm and inline these calls... -bill rosenkra@boston.cray.com #! /bin/sh : This is a shar archive. Extract with sh, not csh. echo x - Readme cat > Readme << '19165!Funky!Stuff!' the linea functions here are callable from c. so far the basic ones are written (init, get/put pixel, line, blit). the test programs exercise the functions as follows: tst1.ttp put random pixels (linea1) and lines (linea3) tst2.ttp bit blit an image around the screen they seem to work fine but i don't yet know all the side effects (i.e. which regs get clobbered). tst2 never does an init (linea0). the linea0 function could be expanded to pass all the pointers back thru args. right now it just returns ptr to the linea structure. the init also gives a ptr to the font header list as well as ptrs to the actual linea functions though to use them directly, you must be in supervisor mode. the line drawing demo is very fast. so far, there is no need to be in supervisor mode to do these things. the file "linea.h" is not needed. it does, however, present a list of all the things in the line A structure in memory. 19165!Funky!Stuff! echo x - Makefile cat > Makefile << '19165!Funky!Stuff!' CFLAGS = -new T1_OBJS = tst1.o linea0.o linea1.o linea3.o T2_OBJS = tst2.o linea7.o all: tst1 tst2 tst1: tst1.ttp tst2: tst2.ttp tst1.ttp: $(T1_OBJS) $(CC) -new -s -o tst1.ttp $(T1_OBJS) @echo tst1.ttp (point and line tests) made @echo execute with: tst1 500 tst2.ttp: $(T2_OBJS) $(CC) -new -s -o tst2.ttp $(T2_OBJS) @echo tst2.ttp (bit blit test) made @echo execute with: tst2 tst1.o: tst1.c tst2.o: tst2.c linea0.o: linea0.s linea1.o: linea1.s linea3.o: linea3.s linea7.o: linea7.s 19165!Funky!Stuff! echo x - linea0.s cat > linea0.s << '19165!Funky!Stuff!' * * linea0 - return long pointer to struct * * synopsis: * * ptr = (struct line_a *) linea0 (); * Init=$A000 .globl _linea0 .text _linea0: link a6,#0 * stack frame movem.l a0-a2,-(a7) * save regs we clobber (except d0) dc.w Init * pointer to struct now in d0 and a0. a1 -> array of font headers, a2 -> array * of linea functions movem.l (a7)+,a0-a2 * restore regs unlk a6 * fix stack frame rts * d0 is pointer .end 19165!Funky!Stuff! echo x - linea1.s cat > linea1.s << '19165!Funky!Stuff!' * * linea1 - put pixel * * synopsis: * * void linea1 (struct line_a *ptr, x, y, color); * * linea struct offsets: INTIN=8 PTSIN=12 * args: (wrt stack frame ptr a6) ptr=8 x=12 y=14 color=16 .globl _linea1 .text _linea1: link a6,#0 * movem.l a0,-(a7) move.l ptr(a6),a0 * linea struct ptr move.l INTIN(a0),a1 move.l PTSIN(a0),a2 move.w color(a6),(a1) * put color in intin table move.l x(a6),(a2) * put coord in ptsin table dc.w $A001 * draw pixel * movem.l (a7)+,a0 unlk a6 rts .end 19165!Funky!Stuff! echo x - linea2.s cat > linea2.s << '19165!Funky!Stuff!' * * linea2 - get pixel * * synopsis: * * int linea1 (struct line_a *ptr, x, y); * * linea struct offsets: PTSIN=12 * args: (wrt stack frame ptr a6) ptr=8 x=12 y=14 .globl _linea2 .text _linea2: link a6,#0 movem.l a0-a1,-(a7) move.l ptr(a6),a0 * linea struct ptr move.l PTSIN(a0),a1 move.l x(a6),(a1) * put coord in ptsin table dc.w $A002 * get pixel. returns d0.w movem.l (a7)+,a0-a1 unlk a6 rts .end 19165!Funky!Stuff! echo x - linea3.s cat > linea3.s << '19165!Funky!Stuff!' * * linea3 - draw line * * synopsis: * * void linea3 (struct line_a *ptr, x1, y1, x2, y2, mode, mask, opt); * * uses line A to draw a line from x1,y1 to x2,y2. * * linea struct offsets: CBIT0=24 CBIT1=26 CBIT2=28 CBIT3=30 LSTLIN=32 LNMASK=34 WMODE=36 X1=38 Y1=40 X2=42 Y2=44 * args: (wrt stack frame ptr a6) ptr=8 x_1=12 y_1=14 x_2=16 y_2=18 mode=20 mask=22 opt=24 .globl _linea3 .text _linea3: link a6,#0 move.l ptr(a6),a0 * line A init (a0 -> structure) move.w #1,CBIT0(a0) * plane 0 (all) move.w #1,CBIT1(a0) * plane 1 (color only) move.w #1,CBIT2(a0) * plane 2 (lo res only) move.w #1,CBIT3(a0) * plane 3 (lo res only) move.w opt(a6),LSTLIN(a0) * draw last pixel of line? move.w mask(a6),LNMASK(a0) * line mask (solid=FFFF) move.w mode(a6),WMODE(a0) * write mode (replace=0) move.l x_1(a6),X1(a0) * coord of points move.l x_2(a6),X2(a0) dc.w $A003 * draw line unlk a6 rts .end 19165!Funky!Stuff! echo x - linea7.s cat > linea7.s << '19165!Funky!Stuff!' * * linea7 - bit blit * * synopsis: * * void linea7 (long blit_parm_block); * pblock=8 .globl _linea7 .text _linea7: link a5,#0 * set up a stack frame with a5 movem.l a6,-(a7) * save a6 since it is used move.l pblock(a5),a6 * copy arg to a6 (-> blit parm block) dc.w $A007 * do it... movem.l (a7)+,a6 * restore a6 unlk a5 rts * returns nothing .end 19165!Funky!Stuff! echo x - tst1.c cat > tst1.c << '19165!Funky!Stuff!' /*#define DEBUG*/ #ifdef DEBUG #include <stdio.h> #endif #include <osbind.h> #ifndef void #define void int #endif long linea0 (); void linea1 (); long atol (); int rand (); int rand_range (); long lrand_range (); long lrand (); main(argc, argv) int argc; char *argv[]; { long ii; int x1, y1, x2, y2; int x, y; int mode = 2; /* 0=replace,2=XOR */ int opt = 0; int mask = 0xFFFF; int color = 1; long ptr; long num = 1000L; argc--, argv++; if (argc > 0) num = atol (*argv); ptr = linea0 (); #ifdef DEBUG fprintf (stderr, "linea0 ptr: 0x%08lx\n\n\n", ptr); fprintf (stderr, "planes: %d\n", *(int *)(ptr)); fprintf (stderr, "v_rez_vt: %d\n", *(int *)(ptr-4)); fprintf (stderr, "v_rez_hz: %d\n", *(int *)(ptr-12)); #endif Cconws ("any key to start pixel test (linea1):\n\r"); Cconin (); Cconws ("\33E"); for (ii = 0; ii < num; ii++) { x = rand_range (100, 500); y = rand_range (100, 300); linea1 (ptr, x, y, color); } Cconws ("pixel test done...any key to start line test (linea3):\n\r"); Cconin (); Cconws ("\33E"); for (ii = 0; ii < num; ii++) { x1 = rand_range (100, 500); x2 = rand_range (100, 500); y1 = rand_range (100, 300); y2 = rand_range (100, 300); linea3 (ptr, x1, y1, x2, y2, mode, mask, opt); } exit (0); } /*------------------------------*/ /* rand_range */ /*------------------------------*/ int rand_range (lo, hi) int lo, hi; { /* * return random int in the range specified (0-7fff): lo <= val < hi */ return (((int) rand () % (hi - lo)) + lo); } /*------------------------------*/ /* lrand_range */ /*------------------------------*/ long lrand_range (lo, hi) long lo, hi; { /* * return random long in the range specified (0-7fffffff): lo <= val < hi * * note: alcyon may have a problem with % for longs... */ extern long lrand (); return (((long) lrand () % (hi - lo)) + lo); } /*------------------------------*/ /* lrand */ /*------------------------------*/ long lrand () { /* * return random long. * * fills each word with a random int. also could interleave the ints. */ union { long lval; int ival[2]; } uuu; uuu.ival[0] = rand (); uuu.ival[1] = rand (); return ((long) uuu.lval); } 19165!Funky!Stuff! echo x - tst2.c cat > tst2.c << '19165!Funky!Stuff!' /* * demo the linea bit blit ($A007) */ #include <portab.h> #include <osbind.h> #include <gem\blit.h> extern void linea7 (); extern long atol (); long tfac; /* for speed control */ BBPB pblock; /* for transfer to screen */ BBPB pblock2; /* for transfer from screen */ int save_space[60]; /* place to save screen rect*/ int bug[60] = /* our thingie to blit... */ { 0x0000,0x0000,0x0030, 0x0000,0x0000,0x0066, 0x0000,0x0000,0x006c, 0x0000,0x0000,0x00ce, 0x0000,0x0000,0x00cc, 0x0000,0x0000,0x0198, 0x0000,0x0000,0x03b0, 0x0000,0x0000,0x0770, 0x0000,0x0000,0x0760, 0x0000,0x0000,0x0ee0, 0x0000,0x0000,0x7fc0, 0x0000,0x0003,0xffc0, 0x0000,0x003f,0xffc0, 0x0000,0x00ff,0xffe0, 0x0000,0x1fff,0xfff0, 0x01ff,0xffff,0xfef0, 0x0fff,0xffff,0xff70, 0x1fff,0xffff,0xff80, 0xffff,0xffff,0xffe0, 0xffff,0xffff,0xffc0 }; int unbug[60] = /* not really needed... */ { 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0 }; main (argc, argv) int argc; char *argv[]; { register int x, y; register int xdirection, ydirection; register int inc; int i; int xmin, xmax, ymin, ymax; long screen; long old_phys; long old_log; /* * check arg...(time delay) */ argc--, argv++; tfac = 1000L; if (argc > 0) tfac = atol (*argv); /* * erase screen */ /* Cconws ("\33E");*/ Cconws ("up/down arrow controls speed. any other key quits...any key to start: \n\r"); Cconin (); /* * get old phys/logbase and reset screen */ old_phys = Physbase (); old_log = Logbase (); screen = old_phys; /* Setscreen (screen, screen, -1);*/ /* * fill in blit param blocks. first one is used for sprite->screen * second one used for screen->buf. the op_tab stuff is critical. */ pblock.bb_b_wd = 48; /* pixels/line */ pblock.bb_b_ht = 20; /* lines */ pblock.bb_plane_ct = 1; /* num conseq planes to blit */ pblock.bb_fg_col = 1; /*!!!*/ pblock.bb_bg_col = 0; /* was 0 */ pblock.bb_op_tab.fg0bg0 = 4; /* replace */ pblock.bb_op_tab.fg0bg1 = 4; pblock.bb_op_tab.fg1bg0 = 7; pblock.bb_op_tab.fg1bg1 = 7; pblock.bb_s.bl_xmin = 0; /* src always 0,0 */ pblock.bb_s.bl_ymin = 0; pblock.bb_s.bl_form = (char *) bug; pblock.bb_s.bl_nxwd = HI_NXWD; pblock.bb_s.bl_nxln = 6; /* byte offset (48/8) */ pblock.bb_s.bl_nxpl = NXPL; /* always 2 */ pblock.bb_d.bl_xmin = 0x00FF; /* initial dest x,y */ pblock.bb_d.bl_ymin = 0x0064; pblock.bb_d.bl_form = (char *) screen; pblock.bb_d.bl_nxwd = HI_NXWD; pblock.bb_d.bl_nxln = HI_NXLN; /* 80*8 pix/lines */ pblock.bb_d.bl_nxpl = NXPL; /* always 2 */ pblock.bb_p_addr = 0L; /* no "pattern"... */ pblock.bb_p_nxln = 0; pblock.bb_p_nxpl = 0; pblock.bb_p_mask = 0; for (i = 0; i < 24; i++) pblock.bb_fill[i] = 0; pblock2.bb_b_wd = pblock.bb_b_wd; pblock2.bb_b_ht = pblock.bb_b_ht; pblock2.bb_plane_ct = 1; pblock2.bb_fg_col = 1; pblock2.bb_bg_col = 0; pblock2.bb_op_tab.fg0bg0= 3; pblock2.bb_op_tab.fg0bg1= 3; pblock2.bb_op_tab.fg1bg0= 3; pblock2.bb_op_tab.fg1bg1= 3; pblock2.bb_s.bl_xmin = pblock.bb_d.bl_xmin; pblock2.bb_s.bl_ymin = pblock.bb_d.bl_ymin; pblock2.bb_s.bl_form = pblock.bb_d.bl_form; pblock2.bb_s.bl_nxwd = pblock.bb_d.bl_nxwd; pblock2.bb_s.bl_nxln = pblock.bb_d.bl_nxln; pblock2.bb_s.bl_nxpl = pblock.bb_d.bl_nxpl; pblock2.bb_d.bl_xmin = pblock.bb_s.bl_xmin; pblock2.bb_d.bl_ymin = pblock.bb_s.bl_ymin; pblock2.bb_d.bl_form = pblock.bb_s.bl_form; pblock2.bb_d.bl_nxwd = pblock.bb_s.bl_nxwd; pblock2.bb_d.bl_nxln = pblock.bb_s.bl_nxln; pblock2.bb_d.bl_nxpl = pblock.bb_s.bl_nxpl; pblock2.bb_p_addr = 0L; pblock2.bb_p_nxln = 0; pblock2.bb_p_nxpl = 0; pblock2.bb_p_mask = 0; for (i = 0; i < 24; i++) pblock2.bb_fill[i] = 0; /* * for direction changes... */ xdirection = -1; ydirection = -1; xmin = 0; /* limits */ xmax = 640-48; ymin = 0; ymax = 400-14; inc = 2; /* movement each cycle (pix)*/ /* * do it until a non-arrow key is pressed */ while (1) { /* * save old background. use block 2 */ pblock2.bb_s.bl_form = (char *) screen; pblock2.bb_d.bl_form = (char *) save_space; linea7 (&pblock2); /* * draw block (vsync is bad...) */ pblock.bb_op_tab.fg0bg0 = 4; /* !s & d */ pblock.bb_op_tab.fg0bg1 = 4; pblock.bb_op_tab.fg1bg0 = 7; /* s | d */ pblock.bb_op_tab.fg1bg1 = 7; pblock.bb_d.bl_form = (char *) screen; pblock.bb_s.bl_form = (char *) bug; linea7 (&pblock); /* * delay controls speed */ time_delay (tfac); /* * calc new position during the delay */ x = pblock.bb_d.bl_xmin + (xdirection * inc); if (x < xmin) { x = xmin + inc; xdirection *= -1; } if (x > xmax) { x = xmax - inc; xdirection *= -1; } y = pblock.bb_d.bl_ymin + (ydirection * inc); if (y < ymin) { y = ymin + inc; ydirection *= -1; } if (y > ymax) { y = ymax - inc; ydirection *= -1; } /* * get user key input. right now just track up/down * arrows for speed control. any other char quits. */ if (user_break ()) break; /* * now undraw (could actually blit old background back) */ pblock.bb_op_tab.fg0bg0 = 3; /* replace */ pblock.bb_op_tab.fg0bg1 = 3; pblock.bb_op_tab.fg1bg0 = 3; pblock.bb_op_tab.fg1bg1 = 3; /* pblock.bb_s.bl_form = (char *) unbug;*/ pblock.bb_s.bl_form = (char *) save_space; pblock.bb_d.bl_form = (char *) screen; linea7 (&pblock); /* Vsync ();*/ /* vsync here makes it smoother, but it is much slower */ /* * set new coords */ pblock.bb_d.bl_xmin = x; pblock2.bb_s.bl_xmin = x; pblock.bb_d.bl_ymin = y; pblock2.bb_s.bl_ymin = y; } /* * reset screen */ /* Setscreen (old_log, old_phys, -1);*/ exit (0); } time_delay (n) long n; { long i; for (i = 0; i < n; i++) ; } int user_break () { long inkey; if (Bconstat (2)) { /* * ret 2 bytes in low byte of each word (not like * evnt_keybd) */ inkey = Bconin (2); if (inkey == 0x00480000L) /* up arrow -> faster */ tfac -= 55; else if (inkey == 0x00500000L) /* down arrow -> slower */ tfac += 55; else return (1); } return (0); } 19165!Funky!Stuff!