home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8711.arc
/
CALL.LST
< prev
next >
Wrap
File List
|
1987-10-08
|
16KB
|
463 lines
Listing 1
@Listing 1@. The @SaveRegion@ Procedure copies any
upright rectangular graphics screen region into
a buffer, @buff@, where its upper-left (x1,y1)
and lower-right (x2,y2) screen coordinates are
specified. GETMEM is used to allocate memory,
rather than the standard NEW, because the buffer
size needs to be computed at run time.
{The following code is the property of H.D.
Callihan, University of Pittsburgh at Johnstown,
Johnstown, Pa. Personal use is encouraged. Feel
free to make copies for distribution to other
personal users. Commercial use is prohibited
without written permission and an
appropriate license.
Version: 4 (requires the CRTmode function in
file: CRTMODE.INC) Purpose:
save and restore a current screen
region in low- or hi-res mode.
Date: 6/22/87
Author: H.D. Callihan, Ph.D. (C) Copyright 1987
Applic: Turbo V3.0 for IBM PC and true compatibles.
File: GREGION4.INC
}
TYPE
buffermemory = ARRAY[1..3] OF INTEGER;
bufferaddress = ^buffermemory;
PROCEDURE SaveRegion(VAR buff : bufferaddress;
x1,y1, {upper left}
x2,y2 {lower right}
: INTEGER);
{---------- Local functions to SaveRegion-----------}
FUNCTION max(a,b: INTEGER) : INTEGER;
BEGIN
IF a<b THEN max := b ELSE max := a
END;
FUNCTION min(a,b : INTEGER) : INTEGER;
BEGIN
IF a<b THEN min := a ELSE min := b
END;
{---------- End local functions --------------------}
VAR width, height, size : INTEGER;
dummy1, dummy2 : BYTE;
BEGIN {SaveRegion}
{correct for negative x and y}
x1 := max(x1,0); x2 := max(x2,0);
y1 := max(y1,0); y2 := max(y2,0);
{correct for large y}
y1 := min(y1,199); y2 := min(y2,199);
{compute height of image in pixels}
height := ABS(y1-y2) +1;
CASE CRTmode(dummy1, dummy2) OF
{ dummy1 and dummy2 not used }
4,5: {one of the low resolutions}
BEGIN
x1 := min(x1,319); x2 := min(x2,319);
{compute width of image in pixels}
width := ABS(X1-X2) +1;
{compute size of buffer need to store image}
size := ((width+3) DIV 4) * height * 2 + 6;
GETMEM(buff, size);
GETPIC(buff^, x1,y1,x2,y2)
END;
6: {high resolution}
BEGIN
x1 := min(x1,639); x2 := min(x2,639);
width := ABS(x1-x2) +1;
size := ((width+7) DIV 8) * height + 6;
GETMEM(buff, size);
GETPIC(buff^, x1,y1,x2,y2)
END;
ELSE WRITE(^G); {unacceptable mode}
END {CASE}
END; {SaveRegion}
Listing 2
@Listing 2@. The @CRTmode@ function determines which
display mode is currently active. It returns an integer
code as well as two arguments which determine text row
and column information if a text mode is active.
FUNCTION CRTmode(VAR char_columns,
display_page : BYTE) : BYTE;
{Returns CRT mode of operation. It uses registers and
software interrupt 10h to BIOS video services. Also
returns the number of character columns in the current
video mode (80 or 40) and the video display page as
VARiable parameters.
Version: 2
Author: H. D. Callihan, PhD, UPJ
Date: 2/29/87
File: CRTMODE.INC
VIDEO MODES:
0 = 40x25 monochrome
1 = 40x25 color
2 = 80x25 monochrome
3 = 80x25 color
4 = 320x200 color graphics (40x25 text)
5 = 320x200 mono graphics (40x25 text)
6 = 640x200 b/w high res graphics (80x25 text)
The following values are returned on the AT&T 6300 for
superres mode (640x400).
$40 = 640x400 mono superres graphics
(80x25 high quality text)
$48 = 640x400 mono superres graphics
(80x50 tiny text)
Register input : (AH) <-- 0Fh
Register output: (AL) --> current mode
(AH) --> number of character
columns on screen
(BH) --> current active display page
Uses software interrupt 10h for BIOS video service.
}
TYPE regpack = RECORD
ax,bx,cx,dx,bp,si,di,ds,es,flags: INTEGER
END {regpack};
VAR dosreg : regpack;
BEGIN {CRTmode}
WITH dosreg DO
BEGIN
{set high byte $0F for register input}
ax := $0F00;
{ $0F = 00001111 binary}
INTR($10, dosreg); {software interrupt 10h}
CRTmode := LO(ax); {mask low byte}
char_columns := HI(ax); {mask high byte}
display_page := HI(bx) {mask high byte}
END
END; {CRTmode}
Listing 3
@Listing 3@. The @RestoreRegion@ procedure copies any
upright rectangular graphics screen region from a
buffer, @buff@, previously saved by @SaveRegion@ where
its lower-left screen coordinates (x,y) are specified.
FREEMEM is used, rather than the standard DISPOSE,
because the buffer size needs to be computed at run
time.
PROCEDURE RestoreRegion
(VAR buff : bufferaddress; {pointer}
x,y : INTEGER; {lower left corner}
freeup : BOOLEAN); {freemem after restore}
VAR width, height, resolution, size : INTEGER;
x_ok, y_ok : BOOLEAN;
BEGIN
resolution := buff^[1];
width := buff^[2];
height := buff^[3];
{check screen boundary y limits}
y_ok := (y-height+1 >= 0) AND (y < 200);
CASE resolution OF
2: {low}
BEGIN
{check x limits}
x_ok := (x >= 0) AND (x+width-1 < 320);
IF x_ok AND y_ok THEN
BEGIN
PUTPIC(buff^,x,y);
IF freeup THEN
BEGIN
size :=
((width+3) DIV 4) * height * 2 + 6;
FREEMEM(buff, size)
END
END
END;
1: {high}
BEGIN
x_ok := (x >= 0) AND (x+width-1 < 640);
IF x_ok AND y_ok THEN
BEGIN
PUTPIC(buff^,x,y);
IF freeup THEN {free the buffer}
BEGIN
size :=
((width+7) DIV 8) * height + 6;
FREEMEM(buff, size)
END
END
END;
ELSE WRITE(^G^G)
END {CASE}
END; {RestoreRegion}
Listing 4
@Listing 4@. The @FreeBuffer@ procedure permits memory to
be freed dynamically without displaying the image on the
screen. Like @RestoreRegion@, it also requires that the
size of the memory block be computed based upon the
block previously saved by @SaveRegion@.
PROCEDURE FreeBuffer ( VAR buff : bufferaddress );
VAR resolution, width, height, size : INTEGER;
BEGIN
resolution := buff^[1];
width := buff^[2];
height := buff^[3];
CASE resolution OF
2 : {LOW}
size := ((width+3) DIV 4) * height * 2 + 6;
1 : {HIGH}
size := ((width+7) DIV 8) * height + 6;
ELSE WRITE(^G^G^G)
END; {CASE}
IF resolution IN [1,2] THEN FREEMEM(buff, size)
END; {FreeBuffer}
Listing 5
@Listing 5@. The procedure, @SaveBlockToDisk@, facilitates
saving a screen region to disk that was previously
stored in a memory buffer using @SaveRegion@. The file
name is passed into the procedure as a string argument.
@GetBlockFromDisk@ is a procedure which does the opposite
by retrieving a block from disk and placing it into
contiguous memory located at @buffer@. @Resolution@ and
@size@ are also computed and returned as a matter of
convenience. This recovered region may now be placed
onto the screen using @RestoreRegion@.
{H D CALLIHAN, UNIVERSITY OF PGH AT JOHNSTOWN, 1987}
TYPE FileString80 = STRING[80];
PROCEDURE SaveBlockToDisk
( FileName : FileString80;
buffer : bufferaddress {mem address of block}
);
VAR
size, resolution, width, height : INTEGER;
FileVariable : FILE; {untyped file}
BEGIN
resolution := buffer^[1];
width := buffer^[2];
height := buffer^[3];
CASE resolution OF
1 : {HIGH}
size := ((width + 7) DIV 8) * height + 6;
2 : {LOW}
size := ((width + 3) DIV 4) * height *2 + 6;
ELSE WRITE (^G^G^G^G)
END; {CASE}
IF resolution IN [1,2] THEN BEGIN
ASSIGN ( FileVariable, FileName );
REWRITE ( FileVariable );
BLOCKWRITE ( FileVariable, buffer^, 1+(size-1) DIV 128 );
CLOSE ( FileVariable )
END {IF}
END; { BlockSave }
PROCEDURE GetBlockFromDisk
( FileName : FileString80;
VAR buffer : bufferaddress;
VAR resolution, {1=hi, 2=lo}
size : INTEGER );
VAR
FileVariable : FILE;
width, height,
SizeOfFile : INTEGER;
{number of 128-byte records in block file}
BEGIN
ASSIGN ( FileVariable, FileName );
RESET ( FileVariable );
SizeOfFile := FILESIZE ( FileVariable );
IF SizeOfFile <> 0 THEN BEGIN
GETMEM( buffer, SizeOfFile * 128 );
BLOCKREAD ( FileVariable, buffer^, SizeOfFile );
resolution := buffer^[1];
width := buffer^[2];
height := buffer^[3];
CASE resolution OF
1 : {HIGH}
size := ((width+7) DIV 8)*height +6;
2 : {LOW}
size := ((width+3) DIV 4)*height*2 +6;
ELSE WRITE(^G^G^G^G^G)
END {CASE}
END; {IF}
CLOSE ( FileVariable );
END; {GetBlock}
Listing 6
@Listing 6@. The following program demonstrates the use
of @SaveRegion@ and @RestoreRegion@. Figure 2 contains
images saved in @buffer@ and @buffer2@.
PROGRAM Test_SaveRegion_and_RestoreRegion;
{$I graph.p} {--> extended Turbo Graphics}
{$I crtmode.inc} {--> Callihan function to check
current crt mode}
{$I gregion4.inc} {--> Callihan save and restore
region Turbo Code
and FreeBuffer code}
VAR i : INTEGER;
buffer,
buffer2 : bufferaddress;
{TYPE declared in the above Callihan file.}
{The TYPE must be used here for SaveRegion,
RestoreRegion, and FreeBuffer to work. }
BEGIN
GRAPHCOLORMODE; {Pick your resolution}
{ HIRES; } { use only colors 0 and 1 if this is used}
GRAPHWINDOW(50,100,200,180);
{pick window: (50,100) to (200,180)}
FILLSCREEN(2);
{clear current window to green=1, black=0,etc.}
{red=2, yellow=3 }
{Now, draw lines in black=0, green=1, etc.}
{draw a nice border around the window}
DRAW(148,78,148, 2, 3);
DRAW(148, 2, 2, 2, 3);
DRAW( 2, 2, 2,78, 3);
DRAW( 2,78,148,78, 3);
{Now, let's draw a couple circles in the window
with center and radius determined by a loop index.
Use color as last parameter.}
FOR i := 10 TO 25 DO CIRCLE(3*i, 2*i, i, 1);
READLN; {wait for user to press return}
SaveRegion(buffer, 0,0,150,80);
{saves in current window coords}
{151 pixels wide by 81 high }
{ GRAPHCOLORMODE;} {this call clears and resets
window to full screen}
FILLSCREEN(0); {clear window to black,
don't reset to full screen}
READLN;
RestoreRegion(buffer,0,80,false);
{Restores in current window coords }
{at the lower left point 0,80 }
{but does not free the buffer. }
READLN;
GRAPHCOLORMODE; {Pick resolution again}
{ HIRES;}
RestoreRegion(buffer,0,80,false);
READLN;
FOR i := 1 TO 10 DO
{let's get fancy}
RestoreRegion(buffer,
150 - 8*i, 200 - 10*i, false);
READLN;
SaveRegion(buffer2,0,0,319,199);
{Use buffer2 for background}
FILLSCREEN(0);
FOR i := 1 TO 10 DO BEGIN
RestoreRegion(buffer, 10+4*i, 200-5*i, false);
READLN;
RestoreRegion(buffer2,0,199,false)
{Restore background}
END; {for}
READLN;
TEXTMODE {Return to the standard text screen}
END.