;{--------------------------------------------------------------------------}
;{                         TechnoJock's Turbo Toolkit                       }
;{                                                                          }
;{                              Version   5.00                              }
;{                                                                          }
;{                                                                          }
;{              Copyright 1986, 1989 TechnoJock Software, Inc.              }
;{                           All Rights Reserved                            }
;{                          Restricted by License                           }
;{--------------------------------------------------------------------------}
;                     {--------------------------------}                                       
;                     {       OBJ:   FastTTT5          }
;                     {--------------------------------}
;
;

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+                                                                +
;+          This asm file contains 3 pascal procedures for        +
;+          linking with TTT version 5.0. The procedures are:     +
;+                                                                +
;+                  Fastwrite(X,Y,A,String)                       +
;+                  PlainWrite(X,Y,String)                        +
;+                  Attribute(X,Y,X,HowMany)                      +
;+                                                                + 
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+                                                                +
;+    The main pascal unit includes three global variables. The   +
;+    VSeg and Vofs indicate the active screen buffer - this may  +
;+    or may not be the visible screen buffer so "snow" checking  +
;+    is always performed.                                        +
;+                                                                +
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

DATA    SEGMENT BYTE PUBLIC

        EXTRN   VSeg : WORD     
 	EXTRN   Vofs : WORD
        EXTRN   SnowProne : BYTE

DATA    ENDS


CODE    SEGMENT BYTE PUBLIC

        ASSUME  CS:CODE,DS:DATA

        PUBLIC  FastWrite, PlainWrite, Attribute

;++++++++++++++++++++++++++++++++++++
;+     C A L M E M P O I N T E R    +
;++++++++++++++++++++++++++++++++++++

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+                                                                +
;+    CALCMEMPOINTER is a local procedure that is called by       +
;+    Fastwrite, PlainWrite and Attribute. It places the segment  +
;+    and offset of the first attribute, in ES:DI ready for an    +
;+    LDS. Vseg and Vofs point to the first attribute of the      +
;+    screen, the final location is computed by adding Row*160    +
;+    (80 attribs and 80 chars per row) and then adding 2*Col.    +
;+    The passed Row and Column are decremented by one to fit     +
;+    with DOS's 0..79, 0..24 coordinate system.                  + 
;+                                                                +
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Calcmempointer      PROC NEAR

        XOR     AX,AX                   ;AX = 0
        MOV     CL,AL                   ;CL = 0
        MOV     BH,AL                   ;BH = 0
        DEC     CH                      ;convert to DOS 0..24 coords
        SHR     CX,1                    ;CX = Row * 128
        MOV     DI,CX                   ;Store in DI
        SHR     DI,1                    ;DI = Row * 64
        SHR     DI,1                    ;DI = Row * 32
        ADD     DI,CX                   ;DI = (Row * 160)
        DEC     BX                      ;convert to DOS 0..79 coords
        SHL     BX,1                    ;Account for attribute bytes
        ADD     DI,BX                   ;DI = (Row * 160) + (Col * 2)
	ADD     DI,Vofs                 ;Add base address
        MOV     ES,Vseg                 ;ES:DI points to first Row,Col attribute
        RET                             ;Return

Calcmempointer      ENDP


;++++++++++++++++++++++++++++
;+     F A S T W R I T E    +
;++++++++++++++++++++++++++++

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+                                                                  +
;+   Why fastwrite. Normal BIOS services are too slow writing       +
;+   to the screen. Even Turbo  write procs are not as fast as      +
;+   we need - especially on snow-prone systems.                    +
;+                                                                  +
;+   Basic Process:    Save stack state                             +
;+                     Repeat                                       +         
;+                        Set ES:DI with target memory address      +
;+                        Load source with LODSB                    +
;+                        Check for vertical retrace if necessary   +    
;+                           and store the character in target      +
;+                           with STOSW                             +
;+                     Until no more chracters                      +
;+                                                                  +
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;  Turbo passed parameters

FWSt            EQU     DWORD PTR [BP+6]
FWAttr          EQU     BYTE PTR [BP+10]
FWRow           EQU     BYTE PTR [BP+12]
FWCol           EQU     BYTE PTR [BP+14]

FastWrite       PROC FAR

        PUSH    BP                      ;Save BP
        MOV     BP,SP                   ;Set up stack frame
        PUSH    DS                      ;Save DS
        MOV     CH,FWRow                ;CH = Row
        MOV     BL,FWCol                ;BL = Column
        CALL    Calcmempointer          ;Set up ES:DI for LDS
        MOV     CL,SnowProne            ;Need to wait?
        LDS     SI,FWSt                 ;DS:SI points to St[0]
        CLD                             ;Set direction to forward
        LODSB                           ;AX = Length(St); DS:SI -> St[1]
        XCHG    AX,CX                   ;CX = Length; AL = WaitForRetrace
        JCXZ    FWExit                  ;exit if string empty
        MOV     AH,FWAttr               ;AH = display attribute
        RCR     AL,1                    ;If WaitForRetrace is False...
        JNC     FWMono                  ; use "FWMono" routine
        MOV     DX,03DAh                ;Point DX to CGA status port
FWGetNext:
        LODSB                           ;Load next character into AL
        MOV     BX,AX                   ;Store video word in BX
        CLI                             ;hold interrupts
FWWaitNoH:
        IN      AL,DX                   ;get retrace situation
        TEST    AL,8                    ;retracing?
        JNZ     FWStore                 ;If so, go
        RCR     AL,1                    ;Else, wait for end of
        JC      FWWaitNoH               ; horizontal retrace
FWWaitH:
        IN      AL,DX                   ;get retrace situation
        RCR     AL,1                    ;Wait for horizontal
        JNC     FWWaitH                 ; retrace
FWStore:
        MOV     AX,BX                   ;Move word back to AX...
        STOSW                           ; and then to screen
        STI                             ;OK to interrupt now
        LOOP    FWGetNext               ;Get next character
        JMP     FWExit                  ;wind up
FWMono:
        LODSB                           ;Load next character into AL
        STOSW                           ;Move video word into place
        LOOP    FWMono                  ;Get next character
FWExit:
        POP     DS                      ;clean up and go home
        MOV     SP,BP                   ;
        POP     BP                      ;
        RET     10                      ;

FastWrite       ENDP


;+++++++++++++++++++++++++++++++
;+     P L A I N W R I T E     +
;+++++++++++++++++++++++++++++++

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+                                                                  +
;+   Uses same concept as Fastwrite but doesn't affect current      +
;+   display attribute.                                             +
;+                                                                  +
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;  Turbo passed parameters

PWSt            EQU     DWORD PTR [BP+6]
PWRow           EQU     BYTE PTR [BP+10]
PWCol           EQU     BYTE PTR [BP+12]

PlainWrite      PROC FAR

        PUSH    BP                      ;Save BP
        MOV     BP,SP                   ;Set up stack frame
        PUSH    DS                      ;Save DS
        MOV     CH,PWRow                ;CH = Row
        MOV     BL,PWCol                ;BL = Column
        CALL    Calcmempointer          ;Set up ES:DI for LDS
        MOV     CL,Snowprone            ;Need to wait?               
        LDS     SI,PWSt                 ;DS:SI points to St[0]
        CLD                             ;Set direction to forward
        LODSB                           ;AX = Length(St); DS:SI -> St[1]
        XCHG    AX,CX                   ;CX = Length; AL = Wait
        JCXZ    PWExit                  ;exit if string empty
        RCR     AL,1                    ;If WaitForRetrace is False...
        JNC     PWNoWait                ; use PWNoWait routine
        MOV     DX,03DAh                ;Point DX to CGA status port
PWGetNext:
        LODSB                           ;Load next character into AL
        MOV     AH,AL                   ;Store char in AH
        CLI                             ;hold interrupts
PWWaitNoH:
        IN      AL,DX                   ; get retrace situation
        TEST    AL,8                    ;Check for vertical retrace
        JNZ     PWStore                 ; In progress? go
        RCR     AL,1                    ;Else, wait for end of
        JC      PWWaitNoH               ; horizontal retrace
PWWaitH:
        IN      AL,DX                   ;Get 6845 status again
        RCR     AL,1                    ;Wait for horizontal
        JNC     PWWaitH                 ; retrace
PWStore:
        MOV     AL,AH                   ;Move char back to AL...
        STOSB                           ; and then to screen
        STI                             ;OK to interrupt now
        INC     DI                      ;Skip attribute bytes
        LOOP    PWGetNext               ;Get next character
        JMP     PWExit                  ;Done
PWNoWait:
        MOVSB                           ;Move character to screen
        INC     DI                      ;Skip attribute bytes
        LOOP    PWNoWait                ;Get next character
PWExit:
        POP     DS                      ;Clean up and go home
        MOV     SP,BP                   ;
        POP     BP                      ;
        RET     8                       ;

PlainWrite      ENDP

;+++++++++++++++++++++++++++++++
;+     A T T R I B U T E       +
;+++++++++++++++++++++++++++++++

;++++++++++++++++++++++++++++++++++++++
;+                                    +
;+   Changes the display attribute    +
;+                                    +
;++++++++++++++++++++++++++++++++++++++

;  Turbo passed parameters

ANumber        EQU     WORD PTR [BP+6]
AAttr          EQU     BYTE PTR [BP+8]
ARow           EQU     BYTE PTR [BP+10]
ACol           EQU     BYTE PTR [BP+12]

Attribute PROC FAR

        PUSH    BP                      ;Save BP
        MOV     BP,SP                   ;Set up stack frame
        MOV     CH,ARow                 ;CH = Row
        MOV     BL,ACol                 ;BL = Column
        CALL    Calcmempointer          ;Call routine to calculate offset
        INC     DI                      ;Skip character
        CLD                             ;Set direction to forward
        MOV     CX,ANumber              ;CX = Number to change
        JCXZ    AExit                   ;If zero, exit
        MOV     AL,AAttr                ;AL = Attribute
        CMP     SnowProne,1             ;Get wait state
        JNE     ANoWait                 ;If WaitForRetrace is False
                                        ; use ANoWait routine
        MOV     AH,AL                   ;Store attribute in AH
        MOV     DX,03DAh                ;Point DX to CGA status port
AGetNext:
        CLI                             ;No interrupts now
AWaitNoH:
        IN      AL,DX                   ;get retrace situation
        TEST    AL,8                    ;check for vertical retrace
        JNZ     AGo                     ;In progress? Go
        RCR     AL,1                    ;Wait for end of horizontal
        JC      AWaitNoH                ; retrace
AWaitH:
        IN      AL,DX                   ; get retrace situation
        RCR     AL,1                    ;Wait for horizontal
        JNC     AWaitH                  ; retrace
AGo:
        MOV     AL,AH                   ;Move Attr back to AL...
        STOSB                           ; and then to screen
        STI                             ;Allow interrupts
        INC     DI                      ;Skip characters
        LOOP    AGetNext                ;Look for next opportunity
        JMP     AExit                   ;Done
ANoWait:
        STOSB                           ;Change the attribute
        INC     DI                      ;Skip characters
        LOOP    ANoWait                 ;Get next character
AExit:                                  ;
        MOV     SP,BP                   ;Clean up and go home
        POP     BP                      ;
        RET     8                       ;

Attribute ENDP

CODE    ENDS

        END
