PROGRAM FastWrite; { FASTWR.PAS contains two fast, snow-and-flicker-free routines for writing directly to the video memory of IBM PC/XT/AT's and close compatibles. The notes below are mostly for those familiar with the older program of the same name, written by Marshall Brain. If you're not, you can skip over them. The demonstration program included here should give you a good idea of how to use both of the *new* FastWrite routines. By the way, if you need help with video attributes, see my FWATTR.INC, in data library 1 of the Borland SIG on CompuServe. Notes: This began as a minor revision to the original FastWrite, a terrific routine that unfortunately had a couple of bugs in it. But the new FASTWR.PAS now differs radically from the old, in more ways than I care to enumerate. What follows is a brief list of the more notable differences: 1. The new version no longer leaves interrupts disabled on exit, as the earlier one did when writing to color displays. 2. The new version clears the CH register, avoiding the old one's compatibility problem when used in conjunction with Turbo Extender (a product of Turbo Power Software). 3. The new version should be compatible with more PC clones than the old one, since it uses a more reliable method for determining the base address of video memory. 4. The new version accepts Row and Column parameters in Turbo Pascal format, rather than DOS format (1..25 and 1..80, rather than 0..24 and 0..79). (If you wish, you can change this by deleting the code--it's labeled--that makes the conversion. Look for "DEC AX" and "DEC BX".) 5. The new version gives you the option of bypassing snow prevention (you have to figure out for yourself when to do so, however). 6. The new version should run faster on many machines than the old one did, *particularly* when snow prevention is disabled. (Do note that, if you ran benchmark tests on a machine with a color display, the old one would always come out ahead, since it disabled the timer tick interrupt.) 7. The new FASTWR.PAS includes a second routine, FastWriteV, to be used only with string variables. It can provide, maybe, a 5-30% speed increase (that's an educated guess), over the regular FastWrite, depending on the length of the string. (The extra speed is due to Turbo's not having to put the whole string on the stack, just an address; it has nothing to do with FastWriteV.) 8. This one comes with fully documented source code! Effusive thanks are due to Bela Lubkin and Kim Kokkonen, without whose help I'd still be at square one. But don't blame them if you find a problem with the routines here. Address all comments, complaints, etc. to Brian Foley, CompuServe ID # [76317,3247]. } TYPE String80 = String[ 80 ]; Registers = Record CASE Integer Of 1 : ( AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : Integer ); 2 : ( AL,AH,BL,BH,CL,CH,DL,DH : Byte ); END; VAR I : Byte; { Needed only for demo. } Bullet : String80; { ditto } Regs : Registers; WaitForRetrace : Boolean; { If False, FastWrite will use the faster "Mono" routine, regardless of display type. } BaseOfScreen : Integer; { Base address of screen memory. Note: Making this a typed constant will screw things up! FastWrite expects this to be a global variable located in the data segment. The same applies to WaitForRetrace. } PROCEDURE GetVideoMode; { Video mode of 7 indicates mono display; all other modes are for color displays. } BEGIN Regs.AH := $0F; Intr( $10, Regs ); IF Regs.AL = 7 THEN BaseOfScreen := $B000 { Mono } ELSE BaseOfScreen := $B800; { Color } WaitForRetrace := ( BaseOfScreen = $B800 ); { You may want to use some other, more sophisticated means to determine the value here, or you could allow the user to decide whether he wants to forego snow prevention in favor of faster screen updates. But... *VERY IMPORTANT* WaitForRetrace MUST be false if BaseOfScreen equals $B000. } END; PROCEDURE FastWrite( St : String80; Row, Col, Attr : Byte ); {InLine code was assembled with Dave Baldwin's INLINE.COM, and uses its notation.} BEGIN Inline( $1E { PUSH DS ;Save DS} /$8B/$46/BaseOfScreen { MOV DX,[>BaseOfScreen] ;DX = Base address of screen} /$8E/$C2 { MOV ES,DX ;ES:DI points to Base:Row,Col} /$A0/>WaitForRetrace { MOV AL,[BaseOfScreen { MOV DX,[>BaseOfScreen]} /$8E/$C2 { MOV ES,DX} /$A0/>WaitForRetrace { MOV AL,[