Category : Files from Magazines
Archive   : DDJ0689.ZIP
Filename : PORTER.LST
by Kent Porter
[LISTING ONE]
; EGAPIXEL.ASM: Reads EGA pixel value directly from video memory
; Returns pixel value at x, y, or -1 if outside viewport
; Microsoft MASM 5.1
; C prototype is
; int far egapixel (int x, int y);
; To be included in GRAFIX.LIB
; K. Porter, DDJ ``Graphics Programming'' column, June '89
.MODEL LARGE
PUBLIC _egapixel
EXTRN _vuport : WORD ; far ptr to vuport structure
; Arguments passed from C
x EQU [bp+6] ; Arguments passed from C
y EQU [bp+8]
; Macro to build pixel value in BL
pixval MACRO
out dx, ax ; set 6845 for bit plane
mov bh, BYTE PTR es:[si] ; get byte from current bit plane
and bh, ch ; mask bit
neg bh ; and flip it
rol bx, 1 ; move to bit 0 in accum (BH)
dec ah ; next bit plane
ENDM
.CODE
_egapixel PROC FAR
push bp ; Entry processing
mov bp, sp
push si ; Save SI (used here)
; Point ES:[BX] to vuport structure
mov ax, _vuport+2 ; get pointer segment
mov es, ax
mov bx, _vuport ; get offset
; Quit if coordinates outside viewport
mov al, -1 ; return value if outside
mov cx, y ; get y
cmp cx, WORD PTR es:[bx+6] ; is y within viewport?
jge exit ; quit if not
mov dx, x ; get x
cmp dx, WORD PTR es:[bx+4] ; is x within viewport?
jge exit ; quit if not
; Map pixel coordinates to current viewport
add dx, WORD PTR es:[bx] ; offset x by vuport.left
push dx ; save remapped X (used later)
add cx, WORD PTR es:[bx+2] ; offset y by vuport.top
; Point ES to video memory segment
mov bx, 0A000h
mov es, bx
; Row offset = y * 80;
push dx ; (modified by MUL)
mov ax, cx ; get y
mov bx, 80
mul bx ; y * 80
mov bx, ax ; into BX
; Column offset = x SHR 3
pop ax ; get x back
mov cl, 3 ; shift operand
shr ax, cl ; column offset
; Complete address of pixel byte
add bx, ax ; BX = row offset + col offset
mov si, bx ; ES:SI = address
; Build bit mask for pixel
pop cx ; get x back
and cl, 7 ; isolate low-order bits
xor cl, 7 ; number of bits to shift
mov ch, 1 ; start bit mask
shl ch, cl ; shift for pixel
xor bl, bl ; accumulator for pixel value
; Set graphics controller Read Map Select Register
mov dx, 03CEh ; 6845 command register
mov ax, 0304h ; first bit plane = 3
; Read bit planes 3-0, accumulating bits in BL
pixval
pixval
pixval
pixval
; AX = return value for function
mov al, bl
; Send pixel value back in AL
exit: xor ah, ah
pop si
mov sp, bp
pop bp
retf
_egapixel ENDP
END
[LISTING TWO]
/* RICOCHET.C: A line moving diagonally "feels" its way among obstacles */
/* Illustrates pixel-reading with egapixel() */
/* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
#include "grafix.h"
#include
void main ()
{
int x = 638; /* current X position of line */
int y = 348; /* and its Y */
int xdir = -1; /* current X direction (-1 = left, 1 = right) */
int ydir = -1; /* and Y direction (-1 = up, 1 = down */
if (init_video (EGA)) {
/* Draw a maze and border */
set_color1 (15);
draw_rect (0, 0, 639, 349);
draw_line (141, 40, 141, 119);
hline (141, 119, 120);
draw_line (421, 0, 421, 100);
hline (540, 199, 80);
hline (360, 160, 120);
hline (300, 261, 120);
draw_line (200, 259, 200, 330);
draw_line (99, 240, 99, 349);
/* Send the line bouncing around */
set_color1 (4);
while (!kbhit()) {
if (egapixel (x+xdir, y) == 15) /* feel ahead horizontally */
xdir = -xdir; /* reverse if obstacle */
if (egapixel (x, y+ydir) == 15) /* same vertically */
ydir = -ydir;
x += xdir; /* advance position */
y += ydir;
draw_point (x, y);
}
getch(); /* clear keyboard buffer */
}
}
[LISTING THREE]
/* FILL.C: Line adjacency flood fill algorithm */
/* For inclusion in GRAFIX.LIB */
/* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
/* ---------------------------------------------------- */
#include "grafix.h"
extern int color1; /* from GRAFIX library */
int far floodfill (int sx, int sy, /* seed coords */
int border, /* border color */
int dir, /* direction (-1=up, 1=down) */
int pleft, int prite) /* ends of previous line */
{
int x; /* current column */
int left, rite; /* ends of current line */
byte pixel; /* detected pixel value */
extern byte far isborder (int, int, byte);
int near leftborder (int, int, byte),
near rightborder (int, int, byte);
/* fix caller's arguments */
if (dir == 0) dir = -1;
else
if (dir > 0) dir = 1;
/* find ends of seed row */
left = leftborder (sx, sy, border);
rite = rightborder (sx, sy, border);
/* fill seed row */
if (left < rite)
draw_line (left+1, sy, rite-1, sy);
else
return rite;
/* fill adjacent rows in same direction */
for (x = left+1; x < rite; x++) {
pixel = egapixel (x, sy+dir); /* inspect adjacent row */
if ((pixel != color1) && (pixel != border))
x = floodfill (x, sy+dir, border, dir, left, rite);
}
/* fill adjacent rows in opposite direction */
for (x = left+1; x < pleft; x++) {
pixel = egapixel (x, sy-dir);
if ((pixel != color1) && (pixel != border))
x = floodfill (x, sy-dir, border, -dir, left, rite);
}
for (x = prite+1; x < rite; x++) {
pixel = egapixel (x, sy-dir);
if ((pixel != color1) && (pixel != border))
x = floodfill (x, sy-dir, border, -dir, left, rite);
}
return rite;
} /* -------------------------------------------------------------- */
/* Following are local routines serving floodfill() */
int near leftborder (int x, int y, byte border)
{
byte pixel;
do {
--x;
pixel = egapixel (x, y);
if ((pixel == border) || (pixel == color1))
break;
} while (x > 0);
return x;
} /* -------------------------------------------------------------- */
int near rightborder (int x, int y, byte border)
{
byte pixel;
do {
++x;
pixel = egapixel (x, y);
if ((pixel == border) || (pixel == color1))
break;
} while (x < vp_width());
return x;
} /* -------------------------------------------------------------- */
[LISTING FOUR]
/* From June, '89 */
/* -------------- */
int far egapixel (int x, int y); /* get pixel value at x, y */
int far floodfill (int sx, int sy, /* seed coords */
int border, /* border color */
int dir, /* pass as 0 */
int pleft, int prite); /* make same as sx */
[LISTING FIVE]
/* FILLS.C: Various filled figures */
/* K. Porter, DDJ ``Graphics Programming'' column, June '89 */
#include "grafix.h"
#include
int triangle[] = {
20,300, 120,300, 70,200, 20,300
};
int star[] = {
60,10, 120,80, 20,60, 100,140, 140,110,
260,190, 220,70, 370,30, 180,40, 60,10
};
int house[] = {
400,200, 400,340, 600,340, 600,200,
500,100, 400,200
};
void main() {
int x, y;
if (init_video (EGA)) {
set_color1 (15);
polyline (3, triangle);
set_color1 (4);
floodfill (70, 250, 15, 0, 60, 60);
set_color1 (14);
polyline (9, star);
set_color1 (6);
floodfill (140, 80, 14, 0, 140, 140);
set_color1 (15);
polyline (5, house);
for (x = 430; x < 560; x += 60)
for (y = 220; y < 300; y += 60)
draw_rect (x, y, 20, 35);
set_color1 (7);
floodfill (500, 200, 15, 0, 500, 500);
getch();
}
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/