home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Jason Aller Floppy Collection
/
94.img
/
THEDRAW.ZIP
/
UNCRUNCH.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1989-11-01
|
9KB
|
165 lines
procedure UNCRUNCH (var Addr1,Addr2; BlkLen:Integer);
(*
This is the flash display routine used to display crunched TheDraw image
files. It uses a custom protocol for reproducing an image with any
possible color combinations. The control codes below #32 are reserved
for this function. The following data structure shows the format of a
sequence. Not all operations use the optional bytes <x> or <y>.
Data Structure: <current byte>[<x>[<y>]]
0..15 = New Foreground Color
16..23 = New Background Color
24 = Go down to next line, return to same horizontal position as when
routine was started (akin to a c/r).
25 = Displays <x> number of spaces.
26 = Displays <x> number of <y>. Also used to display ANY characters
below #32. This function is the only way to do this although it
uses three bytes. Otherwise the character would be interpreted
as another command code.
27 = Toggles on/off the foreground attribute blink flag.
----------------------------------------------------------------------------
To use this routine, call the procedure with the ImageData as the
first parameter, the display address as the second parameter, and the
length of the ImageData as the third parameter.
Assume we have an ImageData file of a 40 character by 10 line block. Also
the following defintions. ie:
{ TheDraw Pascal Crunched Screen Image }
const <- This CONST area is
IMAGEDATA_WIDTH = 40; generated by TheDraw
IMAGEDATA_DEPTH = 10;
IMAGEDATA_LENGTH = 467;
IMAGEDATA : array [1..467] of Char =
(...list of image bytes here...);
type ScreenType = array [0..3999] of Byte;
var ScreenAddr : ScreenType absolute $B800:$0000;
begin
UnCrunch (IMAGEDATA,ScreenAddr[ (34*2) + (5*160) -162],IMAGEDATA_LENGTH);
end;
SCREENADDR is a variable mapped to the same location as the physical video
addresses (via Turbo's absolute addressing). The rather messy array offset
tells UnCrunch where to start displaying the ImageData block. The 34*2
indicates the horizontal position number 34 with the 5*160 indicating line
number 5. This is similar to a Turbo GOTOXY (34,5) statement.
UnCrunch remembers the original horizontal (X) starting position when it
goes down to the next line. This permits a block to be displayed correctly
anywhere on the screen. ie:
+-------------------------------------------------+
| |
| | <- Pretend this
| | is the video
| ┌─────────────────────┐ | display.
| │█████████████████████│ |
| │█████████████████████│ |
| │██ ImageData block ██│ |
| │█████████████████████│ |
| │█████████████████████│ |
| │█████████████████████│ |
| └─────────────────────┘ |
| |
| |
| |
+-------------------------------------------------+
The ImageData block could just as well have been display in the upper-left
corner of the screen with:
UNCRUNCH (IMAGEDATA,ScreenAddr[ (1*2) + (1*160) -162],IMAGEDATA_LENGTH);
Notice the array address changed to the equivilant of GOTOXY (1,1);
To display the block in the lower-right corner you would use:
UNCRUNCH (IMAGEDATA,ScreenAddr[ (40*2) + (15*160) -162],IMAGEDATA_LENGTH);
In this example, the block is 40 characters wide by 10 lines deep. Thus,
to display such a large block, we must display the block at GOTOXY (40,15);
Obviously the documentation here attempts to describe the procedure by use
of examples. This was felt to be the clearest way of explaining it. The
routine was designed to make using it easy; however, for some people the
best way to learn it is to experiment. Try creating a program using the
above example information. Use TheDraw to make a 40 by 10 block (or any
size) to experiment with. Good luck.
*)
begin
inline (
$1E/ { PUSH DS}
$C5/$B6/Addr1/ { LDS SI,[BP+Addr1] ;Source Address}
$C4/$BE/Addr2/ { LES DI,[BP+Addr2] ;Destination Addr}
$8B/$8E/BlkLen/ { MOV CX,[BP+BlkLen] ;Length of block}
$8B/$D7/ { MOV DX,DI ;Save X coordinate for later.}
$33/$C0/ { XOR AX,AX ;Set Current attributes.}
$FC/ { CLD ;Clear direction flag.}
$AC/ {LOOPA: LODSB ;Get next character.}
$3C/$1B/ { CMP AL,27 ;Does user want to toggle the blink}
$75/$05/ { JNZ ForeGround ;attibute?}
$80/$F4/$80/ { XOR AH,128 ;Done.}
$EB/$4D/ { JMP Short Next}
{ForeGround:}
$3C/$10/ { CMP AL,16 ;If less than 16, then change the}
$73/$07/ { JNC BackGround ;foreground color. Otherwise jump.}
$80/$E4/$70/ { AND AH,70H ;Strip off old foreground.}
$0A/$E0/ { OR AH,AL}
$EB/$42/ { JMP Short Next}
{BackGround:}
$3C/$18/ { CMP AL,24 ;If less than 24, then change the}
$74/$13/ { JZ NextLine ;background color. If exactly 24,}
$73/$19/ { JNC MultiOutput ;then jump down to next line.}
$2C/$10/ { SUB AL,16 ;Otherwise jump to multiple output}
$02/$C0/ { ADD AL,AL ;routines.}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$80/$E4/$8F/ { AND AH,8FH ;Strip off old background.}
$0A/$E0/ { OR AH,AL}
$EB/$2B/ { JMP Short Next}
{NextLine:}
$81/$C2/$A0/$00/ { ADD DX,160 ;If equal to 24,}
$8B/$FA/ { MOV DI,DX ;then jump down to}
$EB/$23/ { JMP Short Next ;the next line.}
{MultiOutput:}
$3C/$19/ { CMP AL,25 ;If equal to 25,}
$75/$0B/ { JNZ NotMultiSpaces ;then using the}
$AC/ { LODSB ;following code as}
$51/ { PUSH CX ;a count, output}
$32/$ED/ { XOR CH,CH ;said number of}
$8A/$C8/ { MOV CL,AL ;spaces.}
$B0/$20/ { MOV AL,32}
$EB/$0D/$90/ { JMP StartOutput ;Use below loop.}
{NotMultiSpaces:}
$3C/$1A/ { CMP AL,26 ;If equal to 26, then using}
$75/$0F/ { JNZ NormalLetter ;the following two codes, display}
$AC/ { LODSB ;<x> number of <y> characters.}
$49/ { DEC CX ;Adjust main counter.}
$51/ { PUSH CX ;Display as many of}
$32/$ED/ { XOR CH,CH ;whatever the user}
$8A/$C8/ { MOV CL,AL ;wants.}
$AC/ { LODSB ;Get character.}
{StartOutput:}
$E3/$03/ { JCXZ Stop ;Abort if already at zilch.}
$AB/ {LOOPB: STOSW}
$E2/$FD/ { LOOP LOOPB}
$59/ {Stop: POP CX}
$49/ { DEC CX ;Adjust main counter.}
{NormalLetter:}
$AB/ { STOSW ;Save screen letter.}
$E3/$02/ {Next: JCXZ Done ;Get next, unless CX}
$E2/$A5/ { LOOP LOOPA ;has already gone to zero.}
$1F); {Done: POP DS}
end; {UNCRUNCH}