home *** CD-ROM | disk | FTP | other *** search
- ;===========================================================================
- ;
- ; V I D B L A S T - Blast character pattern into memory, & add attributes
- ;
- ;===========================================================================
- ;
- ; by Jeff Duntemann 25 November 1988
- ;
- ; VIDBLAST is written to be called from Turbo Pascal V4.0 or 5.0 using the
- ; EXTERNAL machine-code procedure convention.
- ;
- ; Declare the procedure itself as external using this declaration:
- ;
- ; PROCEDURE VidBlast(ScreenEnd,StoreEnd : ScrnPtr;
- ; ScreenX,ScreenY : Integer;
- ; ULX,ULY : Integer;
- ; Width,Height : Integer;
- ; Attribute : Byte;
- ; DeadLines : Integer);
- ; EXTERNAL;
- ;
- ; What we have here is a means of moving a rectangular region of a text
- ; screen (either the visible screen or a screen stored on the heap) from
- ; the screen array to a storage array. It is the text analog of a BITBLT
- ; (BIT BLock Transfer.) It is an essential component of any windowing or
- ; menuing system that expects to update the display faster than the eyes
- ; can follow.
- ;
- ; It works like this: ScreenEnd and StoreEnd are the two pointers pointing
- ; to the screen array and the storage array, respectively. If the destination
- ; pointer is NIL, VidBlast returns without taking any action. ScreenX and
- ; ScreenY are the dimensions of the screen in use. ULX and ULY are the
- ; coordinates of the upper left hand corner of the rectangular region to be
- ; written to on the destination screen. Width and Height are the dimensions
- ; of the region to be written to on the destination screen.
- ;
- ; During the blast itself, the attribute byte passed in the Attribute
- ; parameter is written to the screen along with the character information
- ; pointed to by the source pointer. In effect, this means we do a byte-sized
- ; read from the source character data, but a word-sized write to the screen.
- ;
- ;
- ; There is a critical difference between a screen array and a storage array.
- ; A screen array has an implied structure of rows and columns, dictated by
- ; the ScreenX and ScreenY parameters. A rectangular region within such an
- ; array is not one contiguous block of elements, but rather a number of
- ; blocks of elements separated by some quantity of storage not included in
- ; the block transfer. Additionally, the rectangular region begins at some
- ; offset from the beginning of the screen array. A storage buffer, by
- ; contrast, is a simple contiguous array of character/attribute pairs without
- ; any consideration for the row/column structure of a visible screen. We
- ; do it this way for the utmost speed and most efficient use of memory.
- ;
- ; Allocation of both screen and storage arrays, of course, is the
- ; responsibility of the calling logic. HINT: Use GetMem and FreeMem
- ; rather than New and Dispose.
- ;
- ;
- ; To reassemble/relink WORDBLT:
- ;
- ; Assemble this file with MASM or TASM: "C>MASM VIDBLAST;"
- ; (The semicolon is unnecessary with TASM.)
- ;
- ;========================
- ;
- ; STACK PROTOCOL
- ;
- ; This creature puts lots of things on the stack. Study closely:
- ;
-
- ONSTACK STRUC
- OLDBP DW ? ;Caller's BP value saved on the stack
- RETADDR DD ? ;Full 32-bit return address. (This is a FAR proc!)
- DEADLNS DW ? ;Number of lines of dead space to insert between blasted lines
- ATTR DW ? ;Attribute to be added to blasted pattern
- WHEIGHT DW ? ;HEIGHT OF WINDOW TO BE MOVED
- WWIDTH DW ? ;WIDTH OF WINDOW TO BE MOVED
- ULY DW ? ;Y COORDINATE OF UPPER LEFT CORNER OF WINDOW
- ULX DW ? ;X COORDINATE OF UPPER LEFT CORNER OF WINDOW
- YSIZE DW ? ;GENNED MAX Y DIMENSION OF CURRENT VISIBLE SCREEN
- XSIZE DW ? ;GENNED MAX X DIMENSION OF CURRENT VISIBLE SCREEN
- STORE DD ? ;32-BIT POINTER TO STORE BUFFER
- SCREEN DD ? ;32-BIT POINTER TO SCREEN BUFFER
- ENDMRK DB ? ;DUMMY FIELD FOR SIZE CALCULATION PURPOSES
- ONSTACK ENDS
-
-
- CODE SEGMENT PUBLIC
- ASSUME CS:CODE
- PUBLIC VIDBLAST
-
- VIDBLAST PROC FAR
- PUSH BP ;SAVE CALLER'S BP VALUE
- MOV BP,SP ;SP BECOMES NEW VALUE OF BP
- PUSH DS ;SAVE CALLER'S DS VALUE
-
- ;-------------------------------------------------------------------------
- ; The increment between window lines must be calculated and stored in DX.
- ; This includes adding additional instances of the increment for "dead
- ; space" to avoid lines between forms, things like that.
- ;-------------------------------------------------------------------------
-
- MOV DX,[BP].XSIZE
- SUB DX,[BP].WWIDTH ;INCREMENT IS SCREEN WIDTH MINUS
- ; WINDOW WIDTH
- SHL DX,1 ;INCREMENT IS IN WORDS. MUST
- ; CONVERT TO BYTES FOR USE; HERE
- ; WE MULTIPLY IT BY TWO BY
- ; SHIFTING LEFT ONE BIT
- MOV CX,[BP].DeadLns ;Put deadspace line count in CX
- CMP CX,0 ;Is there any dead space needed?
- JE Inset ;If not, go calculate the inset
-
- MOV BX,[BP].XSIZE ;Mov screen width into BX
- SHL BX,1 ;Multiply by two for attributes
- AddDed: ADD DX,BX ;Add a screen width to increment
- LOOP AddDed ;Dec CX & loop backn if CX <> 0
-
-
- ;-------------------------------------------------------------------------
- ; HERE WE CALCULATE THE INSET FROM THE START OF THE VISIBLE
- ; SCREEN BUFFER TO THE FIRST BYTE OF THE WINDOW TO BE BLITTED
- ;-------------------------------------------------------------------------
-
- Inset: PUSH DX ;Save increment; MUL trashes DX
- MOV CX,[BP].XSIZE ;SCREEN MAX X DIMENSION IN CX
- MOV BX,[BP].ULX ;UL CORNER X DIMENSION IN BX
- MOV AX,[BP].ULY ;UL CORNER Y DIMENSION IN AX
- SUB BX,1 ;CORRECT FOR ORIGIN AT 1 NOT 0
- SUB AX,1 ;CORRECT FOR ORIGIN AT 1 NOT 0
- MUL CX ;MULTIPLY SCREEN WIDTH BY UL Y
- ADD AX,BX ; AND ADD INDENT FROM LEFT MARGIN
- MOV CX,AX
- SHL CX,1
-
-
- ;-------------------------------------------------------------------------
- ; NEXT WE HAVE TO FILL THE SOURCE AND DESTINATION SEGMENT AND OFFSET
- ; REGISTERS, DEPENDING ON WHICH WAY DATA WILL BE FLOWING. DS:SI IS
- ; ALWAYS THE SOURCE ADDRESS, AND ES:DI IS ALWAYS THE DESTINATION
- ; ADDRESS. TOWARD DETERMINES WHETHER DATA WILL BE FLOWING TOWARD THE
- ; SCREEN BUFFER OR TOWARD THE STORAGE BUFFER. MUCH OF THIS CODE IS
- ; CHECKING TO SEE IF EITHER POINTER WAS SET TO NIL, I.E. BOTH WORDS
- ; SET TO ZERO. IF EITHER POINTER WAS PASSED AS NIL, WORDBLT RETURNS
- ; WITHOUT TAKING FURTHER ACTION.
- ;-------------------------------------------------------------------------
-
- LES DI,[BP].SCREEN ;SCREEN IS DESTINATION: ES:DI
- LDS SI,[BP].STORE ;STORAGE BUFFER IS SOURCE: DS:SI
-
- MOV AX,ES ;CAN'T DO A CMP ON A SEGMENT REG.
- CMP AX,0 ;A NIL POINTER IS A SEGMENT AND
- JNE AddIn ; OFFSET BOTH SET TO 0
- CMP DI,0 ;RETURN WITHOUT ACTING IF BOTH
- JE GOHOME ; ARE SET TO 0
-
- AddIn: ADD DI,CX ;SCREEN END MUST ADD INSET VALUE
- ; TO OFFSET PORTION OF POINTER
- POP DX ;Restore saved increment to DX
-
- ;-------------------------------------------------------------------------
- ; THE POINTERS ARE NOW READY FOR WORK. NOW WE SET UP FOR THE LOOPS.
- ; THE DIRECTION FLAG MUST BE SET FOR AUTOINCREMENT DURING LOOPS.
- ;-------------------------------------------------------------------------
-
- MOV AX,[BP].WHEIGHT ;HEIGHT IS COUNT OF LINE MOVES
- MOV BX,[BP].Attr ;Move attribute byte into BX
- XCHG BH,BL ;Put attribute info into high byte
-
- ;-------------------------------------------------------------------------
- ; DOLINE IS THE LABEL FOR THE OUTER LOOP. THIS LOOP PERFORMS HEIGHT
- ; STOSW OPS WHICH EACH MOVE WIDTH WORDS FROM SOURCE TO DESTINATION
- ;-------------------------------------------------------------------------
-
- DOLINE: MOV CX,[BP].WWIDTH ;COUNT VALUE FOR INNER LOOP IS WIDTH
-
- DoChar: MOV BL,[SI] ;Bring source byte into BL
- MOV ES:[DI],BX ;Move WORD QUANTITY to ES:DI
- INC SI ;Bump SI to next byte
- INC DI ;Bump DI *by two* to next word
- INC DI
- LOOP DoChar ;Repeat inner loop until CX is zero
-
- ADD DI,DX ;ADD DESTINATION INCREMENT TO DI
- DEC AX ;AX IS HEIGHT; I.E. OUTER LOOP COUNTER
- JNZ DOLINE ;AND LOOP UNTIL AX IS ZERO
-
- ;-------------------------------------------------------------------------
- ; WHEN THE OUTER LOOP IS FINISHED, THE WORK IS DONE. RESTORE REGISTERS
- ; AND GO HOME.
- ;-------------------------------------------------------------------------
-
- GOHOME: POP DS ;RESTORE CALLER'S DS
- MOV SP,BP ;RESTORE PRIOR STACK POINTER & BP
- POP BP ; IN CONVENTIONAL RETURN
- RET ENDMRK-RETADDR-4
-
- VIDBLAST ENDP
- CODE ENDS
- END