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!