;=========================================================================== ; ; S C R N B L T - Graphics Screen Block Transfer for Turbo Pascal ; ;=========================================================================== ; ; by Larry Stone 21-Jul-84 ; ; SCRNBLT is written to be called from Turbo Pascal V2.0 using the ; EXTERNAL procedure convention. It will copy the contents of the ; video graphics display buffer (either low or high resolution) to ; a designated memory location on a virtual "pad" of set dimensions. ; ; To use SCRNBLT, the following lines must be included in your Turbo ; Pascal program. The type "padtype" demonstrates how a PAD data type ; may be declared. When the PAD type is declared, the dimensions of ; the array must be as shown here. It should also be specified ABSOLUTE ; with the initial offset 0, so that all of a 64K segment is available ; to it. ; ; PROCEDURE SCRNBLT( MOVDIR, PADX, PADY : INTEGER; VAR PAD : PADARRAY ); ; EXTERN 'SCRNBLT'; ; ; TYPE ; padtype = ARRAY [0..159, 0..399] OF BYTE; ; VAR ; pad : padtype ABSOLUTE $BA00 : $0000; (* sample declaration *) ; ; SCRNBLT(0, x, y, pad); (* sample call; saves screen on pad(x,y) *) ; ; The parameters PADX and PAXY are specified as absolute coordinates ; on the pad, exactly as screen coordinates would be specified. The ; X-coordinates correspond to the bits on the pad, not the bytes. ; ; The first parameter, "MOVDIR", determines the direction of the transfer. ; If 0 is specified, the contents of the screen are transferred to the ; designated area of the pad; if a nonzero number is specified, ; the designated area of the pad is transferred to the screen buffer. ; ; SCRNBLT transfers the contents of the screen as a rectangular block, ; 80 bytes wide by 200 bytes high, to a rectangular area of the pad ; at the designated x,y coordinates. The pad area is not organized ; exactly like the display buffer; odd and even lines are interleaved ; in a more straightforward fashion to allow the offset of an x,y location ; in the pad to be calculated as (y * padwidth) + x. ; ; To use SCRNBLT with a Turbo Program: ;------------------------------------- ; 1. Assemble this file with MASM. "A> MASM SCRNBLT;" ; 2. Link it into a .EXE file. "A> LINK SCRNBLT;" ; 3. Use EXE2BIN to make a .COM file. "A> EXE2BIN SCRNBLT.EXE SCRNBLT.COM" ; 4. Declare as shown in your Turbo Pascal program. ; 5. Ignore any minor diagnostic messages that may be generated when ; this file is assembled and linked. EXE2BIN is supplied with the ; supplemental programs for PC-DOS; see the DOS manual. ; ; ; EQUATES TO DEFINE GRAPHICS CONSTANTS ; PADWD EQU 160 ; WIDTH OF VIRTUAL PAD, BYTES SCRNWD EQU 80 ; WIDTH OF REAL SCREEN SCRNWD2 EQU 40 ; HALF OF SCREEN WIDTH HALFSC EQU 100 ; LINES FOR HALF OF SCREEN EVENSC EQU 0B800H ; ADDRESS OF EVEN HALF OF SCREEN ODDSC EQU 02000H ; OFFSET OF ODD HALF OF SCREEN CODE SEGMENT PUBLIC ASSUME CS:CODE PUBLIC SCRNBLT ; ; EQUATES FOR ARGUMENTS TO SCRNBLT ; PADOFS EQU 4[BP] ; OFFSET OF PAD ORIGIN PADSEG EQU 6[BP] ; SEGMENT OF PAD PADY EQU 8[BP] ; Y-COORD IN PAD PADX EQU 10[BP] ; X-COORD IN PAD MOVDIR EQU 12[BP] ; MOVE DIRECTION (0 = TO SCREEN) SCRNBLT PROC NEAR PUSH BP MOV BP,SP ; CALLING CONVENTION PUSH DS ; SAVE DS ; ; COMPUTE THE ADDRESS OF THE ORIGIN OF THE PAD AREA DESIGNATED BY ; PADX, PADY. LOC = PAD_OFFSET + (PADY * PADWD) + (PADX / 8) ; MOV AX,PADY ; PREPARE PADY * PADX MOV BX,PADWD MUL BX ; AX = PADY * PADX (DX TRASHED) MOV BX,PADX ; ADD IN X COMPONENT: MOV CL,3 ; (PREPARE TO SHIFT BY 3) SHR BX,CL ; DIV BY 8 SO WE MOVE BY BYTE ADD AX,BX ; ADD IT IN. ADD AX,PADOFS CMP WORD PTR MOVDIR,0 ; IS MOVDIR 0? JE BACKWRD ; IF SO, DO BACKWARDS MOVE. ;---------------------------------------------------- ; MOVE "FORWARD" : FROM PAD TO REAL SCREEN ;---------------------------------------------------- ; MOVE THE EVEN LINES OF THE SCREEN. THE LOOP IS CONTROLLED BY ; THE HALFSC VALUE IN DX; A REP MOVSW IS USED TO MOVE THE SCREEN ; LINES A WORD AT A TIME (PROBABLY NO MORE EFFICIENT ON AN 8088..) ; CLD ; BE SURE DIR. FLAG IS 0 MOV BX,PADSEG ; SOURCE IS PAD, SO SET DS TO MOV DS,BX ; PAD SEGMENT MOV SI,AX ; AND DI TO OFFSET IN PAD MOV BX,EVENSC ; DEST IS SCREEN, SET ES TO SCREEN MOV ES,BX ; SEGMENT. MOV DI,0 ; AND INDEX OF 0 ; ; LOOP TO COPY EVEN LINES ; MOV CX,HALFSC ; PREPARE LOOP COUNTER EVEN: MOV DX,CX ; RECORD LOOP COUNTER MOV CX,SCRNWD2 ; SET UP COUNTER REP MOVSW ; DO THE MOVE ADD SI,PADWD+PADWD-SCRNWD ; MOVE SI TO NEXT SCREEN LINE MOV CX,DX LOOP EVEN ; ; NOW SET UP FOR ODD LINES AND COPY THOSE ; MOV DI,ODDSC ; SET DI TO ODD SCREEN OFFSET MOV SI,AX ADD SI,PADWD ; SET SI TO FIRST ODD LINE ; ; COPY ODD LINES ; MOV CX,HALFSC ; LOAD COUNTER ODD: MOV DX,CX ; SAVE COUNTER MOV CX,SCRNWD2 ; SET UP LINE COUNTER REP MOVSW ADD SI,PADWD+PADWD-SCRNWD ; MOVE SI TO NEXT SCREEN LINE MOV CX,DX ; GET LOOP COUNTER LOOP ODD JMP BYE ; LEAVE ;---------------------------------------------------- ; MOVE "BACKWARD" : FROM REAL SCREEN TO PAD ;---------------------------------------------------- ; THIS IS ALMOST EXACTLY LIKE THE CODE ABOVE THAT MOVES ; FROM THE VIRTUAL SCREEN TO THE DISPLAY BUFFER ; BACKWRD: CLD ; BE SURE DIR. FLAG IS 0 MOV BX,PADSEG ; DEST IS PAD, SO SET ES TO MOV ES,BX ; PAD SEGMENT MOV DI,AX ; SET UP SOURCE INDEX MOV BX,EVENSC ; SET DS TO SCREEN SEGMENT MOV DS,BX ; FOR EVEN LINES OF SCREEN MOV SI,0 ; AND SOURCE INDEX ; ; LOOP TO COPY EVEN LINES ; MOV CX,HALFSC ; PREPARE LOOP COUNTER BEVEN: MOV DX,CX ; RECORD LOOP COUNTER MOV CX,SCRNWD2 ; SET UP COUNTER REP MOVSW ; DO THE MOVE ADD DI,PADWD+PADWD-SCRNWD ; MOVE SI TO NEXT SCREEN LINE MOV CX,DX LOOP BEVEN ; ; NOW SET UP FOR ODD LINES AND COPY THOSE ; MOV SI,ODDSC ; SET DI TO ODD SCREEN OFFSET MOV DI,AX ADD DI,PADWD ; SET SI TO FIRST ODD LINE ; ; COPY ODD LINES ; MOV CX,HALFSC ; LOAD COUNTER BODD: MOV DX,CX ; SAVE COUNTER MOV CX,SCRNWD2 ; SET UP LINE COUNTER REP MOVSW ADD DI,PADWD+PADWD-SCRNWD ; MOVE SI TO NEXT SCREEN LINE MOV CX,DX ; GET LOOP COUNTER LOOP BODD ; ; DONE.. CLEAN UP THE STACK AND LEAVE ; BYE: POP DS ; RESTORE DS MOV SP,BP POP BP ; CONVENTIONAL RETURN RET 10 ; TRASH 10 BYTES FOR PARMS SCRNBLT ENDP CODE ENDS END