;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = SMARTFIX.ASM
;*
;* DESCRIPTIVE NAME = Fixed pitch character output
;*
;*
;* VERSION      V2.0
;*
;* DATE         07/24/87
;*
;* DESCRIPTION  This module contains the routines for outputting fixed
;*              pitch characters only.
;*
;*
;*
;* FUNCTIONS    fixed_pitch_strblt
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   07/24/87                     Written by Walt Moore [waltm]
;*
;*****************************************************************************/


        .386

        .xlist

INCL_GRE_CLIP           equ     1
INCL_FONTFILEFORMAT     equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1

        include pmgre.inc
        include fontmap.inc
        include driver.inc
        include egafam.inc
        include strblt.inc
        include extern.inc
        include protos.inc

        .list

        .MODEL FLAT

        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA

        .CODE

        OPTION  OLDMACROS

;/*
;**       Special cases
;*/

SPECIAL_CASE_BM_OBWNC   =0                        ;Opaque black on white, non-clipped
SPECIAL_CASE_BM_TBNC    =0                        ;Transparent black, non-clipped
SPECIAL_CASE_DEV_ONC    =1                        ;Device, opaque, non-clipped
SPECIAL_CASE_DEV_TNC    =1                        ;Device, transparent, non-clipped


UNROLL_BY_8 = 1

        EXTERN  comp_byte_interval                       :NEAR   ;Interval calculations
        EXTERN  setup_ega_opaque_clip_magic     :NEAR
        EXTERN  set_ega_opaque_mode             :NEAR
        EXTERN  bm_trans_color_fix              :NEAR
        EXTERN  or_bm_trans_color_fix           :NEAR
        EXTERN  xor_bm_trans_color_fix          :NEAR
        EXTERN  bm_opaque_color_fix             :NEAR

;/*
;**       Equates for indices into ega_oc_dispatch_table.
;*/

OC_MASK_TWO_CHAR        equ                      010b

OC_ONE_IN_FIRST         equ                      000b
OC_TWO_IN_FIRST         equ                      010b
OC_ONE_IN_LAST          equ                      100b
OC_TWO_IN_LAST          equ                      110b


;/*
;**       Definitions of the bits in smart_flags.
;*/

TWO_SOURCES_IN_FIRST    equ                      00000001b
TWO_SOURCES_IN_LAST     equ                      00000010b


page

;/*
;**                  Macro
;** char_check
;**
;**       char_check is a debugging macro turned on to count the
;**       number of character offsets popped off the stack.  When
;**       this number becomes negative, then offset about to be
;**       fetched will be invalid.
;**
;**       Usage:
;**               upd_bm
;*/

char_check      macro

        local   char_is_good

        endm


;/*
;**                  Macro
;** upd_bm
;**
;**       upd_bm is the macro used for generating the destination update
;**       code for a bitmap in the generic handlers.
;**
;**       Usage:
;**               upd_bm
;*/

upd_bm  macro

if DRAW_ADJUST                                    ;;If last logic operation defined

        dec     edi                               ;;  did a stosb, adjust for it
endif
        add     edi,ss_next_scan
        jmp     edx                               ;;Return to caller

        endm


;/*
;**                  Macro
;** upd_dev
;**
;**      upd_dev is the macro used for generating the destination update
;**       code for the physical device in the generic handlers.
;**
;**       Usage:
;**               upd_dev
;*/


upd_dev macro

if DRAW_ADJUST                                    ;;If last logic operation defined

        add     edi,SCREEN_CBSCAN-1      ;;  did a stosb, adjust for it
else
        add     edi,SCREEN_CBSCAN
endif
        jmp     edx                               ;;Return to caller

        endm
page

;/*
;**                  Macro
;** clipped_output
;**
;**       clipped_output is the macro passed to the "x" character macros
;**       when the default subroutines are to be called for outputing a
;**       clipped character
;**
;**       Usage:
;**               clipped_output fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

clipped_output macro fetch

        fetch

        jmp     ss_draw_clipped

        endm

;/*
;**                  Macro
;** non_clipped_output
;**
;**       non_clipped_output is the macro passed to the "x" character
;**       macros when the default subroutines are to be called for
;**       outputing a non-clipped character
;**
;**       Usage:
;**               non_clipped_output fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

non_clipped_output macro fetch

        fetch

        jmp     ss_draw

        endm


;/*
;**                  Macro
;** owwc
;**
;**       owwc  is a macro for generating the character drawing
;**       logic for opaque mode, white text, white background, clipped.
;**
;**       Usage:
;**               owwc fetch
;**      Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

owwc    macro   fetch

        mov     al,ss_clip_mask
        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;;STOSB isn't used

        endm


;/*
;**                  Macro
;** twc
;**
;**       twc is a macro for generating the character drawing
;**       logic for transparent mode, white text, clipped.
;**
;**       Usage:
;**               twc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

twc     macro   fetch

        fetch

        and     al,ss_clip_mask
        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;;STOSB isn't used

        endm


;/*
;**                  Macro
;** twnc
;**
;**       tw_non_clipped is a macro for generating the character drawing
;**       logic for transparent mode, white text, non-clipped.
;**
;**       Usage:
;**               twnc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

twnc    macro   fetch

        fetch
        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;;STOSB isn't used

        endm


;/*
;**                  Macro
;** obbc
;**
;**       obbc is a macro for generating the character drawing
;**       logic for opaque mode, black text, black background, clipped.
;**
;**       Usage:
;**               obbc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

obbc    macro   fetch

        mov     al,ss_clip_mask
        not     al
        and     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;;STOSB isn't used

        endm


;/*
;**                  Macro
;** tbc
;**
;**       tbc is a macro for generating the character drawing
;**       logic for transparent mode, black text, clipped.
;**
;**       Usage:
;**               tbc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

tbc     macro   fetch
        fetch
        and     al,ss_clip_mask
        not     al
        and     BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        endm


;/*
;**                  Macro
;** tbnc
;**
;**       tbnc is a macro for generating the character drawing
;**       logic for transparent mode, black text, non-clipped.
;**
;**       Usage:
;**               tbnc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

tbnc    macro   fetch
        fetch
        not     al
        and     BYTE PTR [edi],al
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        endm


;/*
;**                  Macro
;** obwc
;**
;**       obwc is a macro for generating the character drawing
;**       logic for opaque mode, black text, white background, clipped.
;**
;**       Usage:
;**               obwc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

obwc    macro   fetch
        fetch
        not     al
        mov     ah,ss_clip_mask
        and     al,ah
        not     ah
        and     ah,BYTE PTR [edi]
        or      al,ah
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        endm


;/*
;**                  Macro
;** owbc
;**
;**       owbc is a macro for generating the character drawing
;**       logic for opaque mode, white text, black background, clipped.
;**
;**       Usage:
;**               owbc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

owbc    macro   fetch
        fetch
        mov     ah,ss_clip_mask
        and     al,ah
        not     ah
        and     ah,BYTE PTR [edi]
        or      al,ah
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        endm


;/*
;**                  Macro
;** obwnc
;**
;**       obwnc is a macro for generating the character drawing
;**       logic for opaque mode, black text, white background, non-clipped.
;**
;**       Usage:
;**               obwnc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

obwnc   macro   fetch
        fetch
        not     al
        stosb
DRAW_ADJUST     = 1                               ;;STOSB is used
        endm

;/*
;**                  Macro
;** owbnc
;**
;**       owbnc is a macro for generating the character drawing
;**       logic for opaque mode, white text, black background, non-clipped.
;**
;**       Usage:
;**               owbnc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

owbnc   macro   fetch
if FETCH_IS_LODSB                                 ;;If fetch logic is simply a
        movsb                                     ;;  LODSB, then use a MOVSB
else                                              ;;else
        fetch                                     ;;  use passed fetch logic
        stosb
endif
DRAW_ADJUST     = 1                               ;;STOSB/MOVSB is used
        endm


;/*
;**                  Macro
;** obbnc
;**
;**       obwnc is a macro for generating the character drawing
;**       logic for opaque mode, black text, black background, non-clipped.
;**
;**       Usage:
;**               obbnc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

obbnc   macro   fetch
        mov     byte ptr [edi],0
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        endm

;/*
;**                  Macro
;** owwnc
;**
;**       owwnc is a macro for generating the character drawing
;**       logic for opaque mode, white text, white background, non-clipped.
;**
;**       Usage:
;**               owwnc fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

owwnc   macro   fetch
        mov     byte ptr [edi],0FFh
DRAW_ADJUST     = 0                               ;;STOSB isn't used
        endm

;/*
;**                  Macro
;** ega_onc_fix
;**
;**       ega_onc_fix is a macro for generating the character drawing
;**       logic for opaque mode, non-clipped, for the EGA.  The hardware
;**       has been correctly programmed for color.
;**
;**       Usage:
;**               ega_onc_fix fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

ega_onc_fix     macro   fetch
if FETCH_IS_LODSB                                 ;;If fetch logic is simply a
        movsb                                     ;;  LODSB, then use a MOVSB
else                                              ;;else
        fetch                                     ;;  use passed fetch logic
        stosb
endif
DRAW_ADJUST     = 1                               ;;STOSB/MOVSB is used
        endm
page

;/*
;**                  Macro
;** ega_tnc_fix
;**
;**       ega_tnc_fix is a macro for generating the character drawing
;**       logic for opaque mode, non-clipped, for the EGA.  The hardware
;**       has been correctly programmed for color.
;**
;**       Usage:
;**               ega_tnc_fix fetch
;**       Where
;**               fetch   is the macro to be invoked for generating
;**                       the fetching logic
;*/

ega_tnc_fix     macro   fetch
        fetch                                     ;;  use passed fetch logic
        out     dx,al
        xchg    al,BYTE PTR [edi]
DRAW_ADJUST     = 0                               ;;STOSB/MOVSB is used
        endm
page

;/*
;**
;** The following macros define the logic involved for processing the
;** various combinations of required sources and first/middle/last bytes.
;**
;**
;** The basic control flow is:
;**
;**       initialization by the invoking macro
;**       entry_logic
;**       while (count > 0)
;**       {
;**           loop_setup
;**           while (scans in font)
;**           {
;**               fetch_logic
;**               draw_logic
;**           }
;**           loop_logic
;**       }
;**       exit code by the invoking macro
;**
;**
;** entry_logic:
;**
;**   The entry_logic macro is invoked to define any preprocessing
;**   which may be required for the operation.  This is performed
;**   outside the outer most loop.
;**
;**       Entry:
;**           DS:SI   = font bits of char
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**       Registers Destroyed:
;**           AX,BX,CH
;**       Registers Preserved:
;**           SI,DI,DS,ES
;**
;**
;** loop_setup
;**
;**   The loop_setup macro is invoked for each destination character
;**   which must be accumulated.
;**
;**       Entry:
;**           DS:SI   = font bits of char or previous char, as determined
;**                     by the case being processed
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**           SS:SP   = offset of next character if required
;**       Exit:
;**           DS:SI   = font bits of char
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**           SS:SP   = offset of next character if required
;**           BX        as required by fetch logic
;**       Registers Destroyed:
;**           AX,BX,CH
;**       Registers Preserved:
;**           CL,DX,DI,DS,ES
;**
;**
;** fetch_logic:
;**
;**   The fetch_logic macro is invoked once for each destination byte
;**   which must be accumulated.
;**
;**       Entry:
;**           DS:SI   = font bits of char
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**           CH      = loop count
;**           SS:SP   = offset of next character if required
;**           BX        as required by fetch logic
;**       Exit:
;**           DS:SI   = next font bits of char
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**           CH      = loop count
;**           BX        as required by fetch logic
;**       Registers Destroyed:
;**            AX
;**       Registers Preserved:
;**           CX,DX,DI,DS,ES,SP
;**
;**
;** draw_logic:
;**
;**   The draw_logic macro is invoked once for each destination byte
;**   which must be displayed.
;**
;**       Entry:
;**           AL      = bits of character to be displayed
;**           DS:SI   = font bits of char
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**           CH      = loop count
;**           BX        as required by fetch logic
;**       Exit:
;**           DS:SI   = next font bits of char
;**           ES:DI   = next destination pointer
;**           CL      = phase (shift count)
;**           CH      = loop count
;**       Registers Destroyed:
;**           AX
;**       Registers Preserved:
;**           BX,CX,DX,SP
;**
;**
;** loop_logic:
;**
;**   The loop_logic macro is invoked after each complete character
;**   has been displayed.  loop_logic takes a parameter which is the
;**   label to jump to if more characters exist.   This parameter will
;**   only be used for the middle byte routines.
;**
;**       Entry:
;**           DS:SI   = font bits of char
;**           ES:DI   = destination pointer
;**           CL      = phase (shift count)
;**           SS:SP   = offset of next character if required
;**       Exit:
;**           DS:SI   = font bits of char incase char is required for next
;**                     output operation
;**           ES:DI   = start of next char's destination
;**           CL      = phase (shift count)
;**       Registers Destroyed:
;**           AX,BX,CH
;**       Registers Preserved:
;**           CL,DX,SP
;**
;*/


;/*
;**                  Macro
;** one_in_first
;**
;** one_in_last defines the macros for the case where the first horizontal
;** set of bytes contains part or all of only one character.
;**
;*/

one_in_first    macro

entry_logic     &macro                            ;;No entry logic is required
        &endm                                     ;;
                                                  ;;
loop_setup      &macro                            ;;DS:SI is setup for us at entry
        &endm                                     ;;
                                                  ;;
FETCH_IS_LODSB = 1                                ;;Show fetch is only a LODSB
fetch_logic     &macro                            ;;Bit fetching logic
        lodsb                                     ;;
        shr     al,cl                             ;;AL = bits to output
        &endm                                     ;;
                                                  ;;
loop_logic      &macro  target                    ;;Outer loop looping logic
        sub     esi,clipped_font_height          ;;Restore character start
        sub     edi,cell_adjust                   ;;Point to start of next char
        &endm

        endm
page

;/*
;**                  Macro
;** two_in_first
;**
;** two_in_first defines the macros for the case where the first
;** horizontal set of bytes contains part of two characters.
;**
;*/

two_in_first    macro

entry_logic     &macro                            ;;No entry logic is required
        &endm                                     ;;
                                                  ;;
loop_setup      &macro                            ;;Outer loop logic setup
        mov     ebx,esi                           ;;DS:BX = font bits of first char
        char_check
        pop     esi                               ;;Get offset of second character
        sub     ebx,esi                           ;;Using a delta saves an increment
        &endm                                     ;;
                                                  ;;
FETCH_IS_LODSB = 0                                ;;Show fetch is more than a LODSB
fetch_logic     &macro                            ;;Bit fetching logic
        mov     ah,BYTE PTR [ebx][esi]            ;;AH = byte from first char.
        lodsb                                     ;;AL = byte from second char.
        shr     ax,cl                             ;;AL = bits to output
        &endm                                     ;;
                                                  ;;
loop_logic      &macro  target                    ;;Outer loop looping logic
        sub     esi,clipped_font_height          ;;Restore character start
        sub     edi,cell_adjust                   ;;Point to start of next char
        &endm

        endm
page

;/*
;**                  Macro
;** one_in_last
;**
;** one_in_last handles the case when the last horizontal set of bytes
;** contains part or all of only one character.
;**
;*/

one_in_last     macro

entry_logic     &macro
        sub     cl,8                              ;;Reverse phase on entry.  Phase
        neg     cl                                ;;  will not be used again as this
        and     cl,7                              ;;  is the last character
        &endm                                     ;;
                                                  ;;
loop_setup      &macro                            ;;No outer loop logic is required
        &endm                                     ;;
                                                  ;;
FETCH_IS_LODSB = 0                                ;;Show fetch is more than a LODSB
fetch_logic     &macro                            ;;Bit fetching logic
        lodsb                                     ;;
        shl     al,cl                             ;;AL = bits to output
        &endm                                     ;;
                                                  ;;
loop_logic      &macro  target                    ;;No outer loop looping logic is
        &endm                                     ;;  needed as this is last char

        endm
page

;/*
;**                  Macro
;** two_in_last
;**
;** two_in_last handles the case when the last horizontal set of bytes
;** contains parts of two characters.
;**
;*/

two_in_last     macro

entry_logic     &macro                            ;;No entry logic is required
        &endm                                     ;;
                                                  ;;
loop_setup      &macro                            ;;Outer loop logic setup
        mov     ebx,esi                           ;;DS:BX = font bits of first char
        char_check
        pop     esi                               ;;Get offset of second character
        sub     ebx,esi                           ;;Using a delta saves an increment
        &endm                                     ;;
                                                  ;;
FETCH_IS_LODSB = 0                                ;;Show fetch is more than a LODSB
fetch_logic     &macro                            ;;Bit fetching logic
        mov     ah,BYTE PTR [ebx][esi]            ;;AH = byte from first char.
        lodsb                                     ;;AL = byte from second char.
        shr     ax,cl                             ;;AL = bits to output
        &endm                                     ;;
                                                  ;;
loop_logic      &macro  target                    ;;No outer loop looping logic is
        &endm                                     ;;  needed as this is last char

        endm

page

;/*
;**                  Macro
;** two_in_cell
;**
;** two_in_cell handles a variable number of middle bytes (not first
;** or last byte), where two source characters are required to make
;** up a destination byte.
;**
;*/

two_in_cell     macro

entry_logic     &macro                            ;;No entry logic is required
        &endm                                     ;;
                                                  ;;
loop_setup      &macro                            ;;Outer loop logic setup
        mov     ebx,esi                           ;;DS:BX = font bits of first char
        char_check
        pop     esi                               ;;Get offset of second character
        sub     ebx,esi                           ;;Using a delta saves an increment
        &endm                                     ;;
                                                  ;;
FETCH_IS_LODSB = 0                                ;;Show fetch is more than a LODSB
fetch_logic     &macro                            ;;Bit fetching logic
        mov     ah,BYTE PTR [ebx][esi]            ;;AH = byte from first char.
        lodsb                                     ;;AL = byte from second char.
        shr     ax,cl                             ;;AL = bits to output
        &endm                                     ;;
                                                  ;;
loop_logic      &macro  target                    ;;Outer loop looping logic
        sub     esi,clipped_font_height          ;;Restore character start
        sub     edi,cell_adjust                   ;;Point to start of next char
        dec     count                             ;;Update inner byte count
        jnz     target                            ;;If more characters exist
        &endm

long_loop_logic &macro  target                    ;;Outer loop looping logic
local   foo
        sub     esi,clipped_font_height          ;;Restore character start
        sub     edi,cell_adjust                   ;;Point to start of next char
        dec     count                             ;;Update inner byte count
        jz      foo
        jmp     target                            ;;If more characters exist
foo:
        &endm
        endm
page

;/*
;**                  Macro
;** one_in_cell
;**
;** one_in_cell handles a variable number of middle bytes (not first
;** or last byte), where one source character is required to make
;** up a destination byte.  This will be the case when the characters
;** are byte aligned.
;**
;*/

one_in_cell     macro

entry_logic     &macro                            ;;No entry logic is required
        &endm                                     ;;
                                                  ;;
loop_setup      &macro                            ;;Outer loop logic setup
        char_check
        pop     esi                               ;;Get offset of next character
        &endm                                     ;;
                                                  ;;
FETCH_IS_LODSB = 1                                ;;Show fetch is only a LODSB
fetch_logic     &macro                            ;;
        lodsb                                     ;;AL = bits to output
        &endm                                     ;;
                                                  ;;
loop_logic      &macro  target                    ;;Outer loop looping logic
        sub     edi,cell_adjust                   ;;Point to start of next char
        dec     count                             ;;Update inner byte count
        jnz     target                            ;;If more characters exist
        &endm

        endm
page

;/*
;**                  Macro
;** spec_case
;**
;**       spec_case is the macro invoked to define a special case
;**       The special case loop will be unrolled by 8.
;**
;**       Usage:
;**               spec_case name,logic,draw,ur
;**       Where
;**               name    is the name of the procedure being defined
;**               logic   is the name of the macro which will define
;**                       the following macros:
;**                           entry_logic - one shot entry preprocessing
;**                           loop_setup           - character offset fetching
;**                           fetch_logic - logic to fetch character bits
;**                           loop_logic           - per char looping
;**               draw    is the name of the macro to perform the actual
;**                       drawing of the bits
;*/

spec_case       macro   name,logic,draw

name&_DEST_ADJ = 0

        logic                                     ;;Define required macros

name&_disp_table label byte

        db      name&_loop_0-name&_loop
        db      name&_loop_1-name&_loop
        db      name&_loop_2-name&_loop
        db      name&_loop_3-name&_loop
if UNROLL_BY_8
        db      name&_loop_4-name&_loop
        db      name&_loop_5-name&_loop
        db      name&_loop_6-name&_loop
        db      name&_loop_7-name&_loop
endif

        public  name
name    proc    near
        mov     bl,byte ptr clipped_font_height
if UNROLL_BY_8
        and     ebx,0007h
else
        and     ebx,0003h
endif
        mov     bl,name&_disp_table[ebx]
        add     ebx,OFFSET name&_loop
        mov     unrolled_entry_point,ebx
        mov     edx,ss_next_scan                 ;;Index to next scan of a bitmap
if name&_DEST_ADJ
        dec     edx
else
        nop
endif
        entry_logic                               ;;Any specific entry logic required

name&_outer_loop proc near
        loop_setup                                ;;Char offset fetching
        mov     ch,byte ptr clipped_font_height
        jmp     unrolled_entry_point

        even
name&_loop:
name&_loop_0:
        draw    <fetch_logic>
        add     edi,edx
name&_DEST_ADJ = DRAW_ADJUST                      ;;Need to know if a stosb was used

if UNROLL_BY_8
name&_loop_7:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_6:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_5:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_4:
        draw    <fetch_logic>
        add     edi,edx
endif

name&_loop_3:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_2:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_1:
        draw    <fetch_logic>
        add     edi,edx
if UNROLL_BY_8
        sub     ch,8
else
        sub     ch,4
endif
        ja      name&_loop

name&_done_char:
        loop_logic name&_outer_loop
        jmp     ret_addr                          ;To caller

name&_outer_loop endp

name    endp
        endm
page

;/*
;**                  Macro
;** o_spec_case
;**
;**       o_spec_case is the macro invoked to define the opaque special
;**       case for the EGA.
;**
;**       The special case loop will be unrolled by 8.
;**
;**       Usage:
;**               o_spec_case name,logic,draw,ur
;**       Where
;**               name    is the name of the procedure being defined
;**               logic   is the name of the macro which will define
;**                       the following macros:
;**                           entry_logic - one shot entry preprocessing
;**                           loop_setup           - character offset fetching
;**                           fetch_logic - logic to fetch character bits
;**                           loop_logic           - per char looping
;**               draw    is the name of the macro to perform the actual
;**                       drawing of the bits
;*/

o_spec_case     macro   name,logic,draw
if1
name&_DEST_ADJ = 0
endif
        logic                                     ;;Define required macros

name&_disp_table label byte
        db      name&_loop_0-name&_loop
        db      name&_loop_1-name&_loop
        db      name&_loop_2-name&_loop
        db      name&_loop_3-name&_loop
if UNROLL_BY_8
        db      name&_loop_4-name&_loop
        db      name&_loop_5-name&_loop
        db      name&_loop_6-name&_loop
        db      name&_loop_7-name&_loop
endif

        PUBLIC  name
name::
        mov     bl,byte ptr clipped_font_height
if UNROLL_BY_8
        and     ebx,0007h
else
        and     ebx,0003h
endif
        mov     bl,name&_disp_table[ebx]
        add     ebx,OFFSET name&_loop
        mov     unrolled_entry_point,ebx
        mov     edx,ss_next_scan                 ;;Index to next scan of a bitmap
if name&_DEST_ADJ
        dec     edx
else
        nop
endif
        entry_logic                               ;;Any specific entry logic required

name&_outer_loop::
        loop_setup                                ;;Char offset fetching
        mov     ch,byte ptr clipped_font_height
        jmp     unrolled_entry_point

        even
name&_loop:
name&_loop_0:
        draw    <fetch_logic>
        add     edi,edx
name&_DEST_ADJ = DRAW_ADJUST                      ;;Need to know if a stosb was used

if UNROLL_BY_8
name&_loop_7:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_6:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_5:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_4:
        draw    <fetch_logic>
        add     edi,edx
endif

name&_loop_3:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_2:
        draw    <fetch_logic>
        add     edi,edx

name&_loop_1:
        draw    <fetch_logic>
        add     edi,edx
if UNROLL_BY_8
        sub     ch,8
else
        sub     ch,4
endif
        ja      name&_loop

name&_done_char:
        loop_logic name&_outer_loop
        jmp     ret_addr                          ;To caller

        endm
page

;/*
;**                  Macro
;** t1_spec_case
;**
;**       t1_spec_case is the macro invoked to define the transparent
;**       special case for the EGA.
;**
;**       The special case loop will be unrolled by 8.
;**
;**       Usage:
;**               t_spec_case name,logic,draw,ur
;**       Where
;**               name    is the name of the procedure being defined
;**               logic   is the name of the macro which will define
;**                       the following macros:
;**                           entry_logic - one shot entry preprocessing
;**                           loop_setup           - character offset fetching
;**                           fetch_logic - logic to fetch character bits
;**                           loop_logic           - per char looping
;**               draw    is the name of the macro to perform the actual
;**                       drawing of the bits
;*/

t1_spec_case    macro   name,logic,draw
if1
name&_DEST_ADJ = 0
endif
        logic                                     ;;Define required macros

name&_disp_table label byte
        db      name&_loop_0-name&_loop
        db      name&_loop_1-name&_loop
        db      name&_loop_2-name&_loop
        db      name&_loop_3-name&_loop
if UNROLL_BY_8
        db      name&_loop_4-name&_loop
        db      name&_loop_5-name&_loop
        db      name&_loop_6-name&_loop
        db      name&_loop_7-name&_loop
endif

        PUBLIC  name
name::
        mov     bl,byte ptr clipped_font_height
if UNROLL_BY_8
        and     ebx,0007h
else
        and     ebx,0003h
endif
        mov     bl,name&_disp_table[ebx]
        add     ebx,OFFSET name&_loop
        mov     unrolled_entry_point,ebx

        entry_logic                               ;;Any specific entry logic required

name&_outer_loop::
        loop_setup                                ;;Char offset fetching
        mov     ch,byte ptr clipped_font_height
        mov     dx,EGA_BASE + GRAF_DATA
        jmp     unrolled_entry_point

        even
name&_loop:
name&_loop_0:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST
name&_DEST_ADJ = DRAW_ADJUST                      ;;Need to know if a stosb was used

if UNROLL_BY_8
name&_loop_7:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_6:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_5:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_4:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST
endif

name&_loop_3:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_2:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_1:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST
if UNROLL_BY_8
        sub     ch,8
else
        sub     ch,4
endif
        ja      name&_loop

name&_done_char:
        loop_logic name&_outer_loop
        jmp     ret_addr                          ;To caller

        endm
page

;/*
;**                  Macro
;** t2_spec_case
;**
;**       t_spec_case is the macro invoked to define the transparent
;**       special case for the EGA.
;**
;**       The special case loop will be unrolled by 8.
;**
;**       Usage:
;**               t_spec_case name,logic,draw,ur
;**       Where
;**               name    is the name of the procedure being defined
;**               logic   is the name of the macro which will define
;**                       the following macros:
;**                           entry_logic - one shot entry preprocessing
;**                           loop_setup           - character offset fetching
;**                           fetch_logic - logic to fetch character bits
;**                           loop_logic           - per char looping
;**               draw    is the name of the macro to perform the actual
;**                       drawing of the bits
;*/

t2_spec_case    macro   name,logic,draw
if1
name&_DEST_ADJ = 0
endif
        logic                                     ;;Define required macros

name&_disp_table label byte
        db      name&_loop_0-name&_loop
        db      name&_loop_1-name&_loop
        db      name&_loop_2-name&_loop
        db      name&_loop_3-name&_loop
if UNROLL_BY_8
        db      name&_loop_4-name&_loop
        db      name&_loop_5-name&_loop
        db      name&_loop_6-name&_loop
        db      name&_loop_7-name&_loop
endif

        PUBLIC  name
name::
        mov     bl,byte ptr clipped_font_height
if UNROLL_BY_8
        and     ebx,0007h
else
        and     ebx,0003h
endif
        mov     bl,name&_disp_table[ebx]
        add     ebx,OFFSET name&_loop
        mov     unrolled_entry_point,ebx

        entry_logic                               ;;Any specific entry logic required

name&_outer_loop::
        loop_setup                                ;;Char offset fetching
        mov     ch,byte ptr clipped_font_height
        mov     dx,EGA_BASE + GRAF_DATA
        jmp     unrolled_entry_point

        even
name&_loop:
name&_loop_0:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST
name&_DEST_ADJ = DRAW_ADJUST                      ;;Need to know if a stosb was used

if UNROLL_BY_8
name&_loop_7:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_6:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_5:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_4:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST
endif

name&_loop_3:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_2:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST

name&_loop_1:
        draw    <fetch_logic>
        add     edi,SCREEN_CBSCAN - DRAW_ADJUST
if UNROLL_BY_8
        sub     ch,8
else
        sub     ch,4
endif
        ja      name&_loop

name&_done_char:
        long_loop_logic name&_outer_loop
        jmp     ret_addr                          ;To caller

        endm
page

;/*
;**                  Macro
;** general_case
;**
;**       general_case is the macro invoked to define a generic handler.
;**       It must be passed a call through ss_draw or ss_draw_clipped
;**       for the drawing logic.
;**
;**       Usage:
;**               general_case name,logic,draw
;**       Where
;**               name    is the name of the procedure being defined
;**               logic   is the name of the macro which will define
;**                       the following macros:
;**                           entry_logic - one shot entry preprocessing
;**                           loop_setup           - character offset fetching
;**                           fetch_logic - logic to fetch character bits
;**                           loop_logic           - per char looping logic
;**               draw    is the name of the macro to perform the actual
;**                       drawing of the bits
;**
;*/

general_case macro   name,logic,draw

        logic                                     ;;Define required macros

        PUBLIC  name
name::
        entry_logic                               ;;Any specific entry logic required
        mov     edx,OFFSET name&_loop

name&_outer_loop:
        loop_setup                                ;;Char offset fetching
        mov     ch,byte ptr clipped_font_height
        inc     ch                                ;;For entry into the loop

name&_loop:
        dec     ch
        jz      name&_done_char
        draw    <fetch_logic>

name&_done_char:
        loop_logic name&_outer_loop
        jmp     ret_addr                          ;To caller

        endm
page


;/***************************************************************************
;*
;* FUNCTION NAME = fixed_pitch_strblt
;*
;* DESCRIPTION   = Fixed pitch character output
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,DS,ES,FLAGS
;*                 Registers Preserved:
;*                       BP
;*
;* INPUT         =  stack frame as per strblt
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

fixed_pitch_strblt PROC SYSCALL,lp_DDC        :DWORD,  lp_DestDev :DWORD,
   x             :DWORD,
   y             :DWORD,
   lp_clip_rect  :DWORD,
   lp_string     :DWORD,
   count         :DWORD,
   npAttrs       :DWORD,
   lp_dx         :DWORD,
   lp_opaque_rect:DWORD,
   eto_options   :DWORD
        LOCAL   accel           :BYTE
        LOCAL   excel           :BYTE
        LOCAL   wc_flags        :BYTE
        LOCAL   fbTranslate     :BYTE
        LOCAL   colors          :DWORD
        LOCAL   char_extra      :DWORD
        LOCAL   num_null_pixels :DWORD
        LOCAL   null_char_offset:DWORD
        LOCAL   lhs             :DWORD
        LOCAL   rhs             :DWORD
        LOCAL   concat          :DWORD
        LOCAL   pFont           :DWORD
        LOCAL   lfd             :local_font_def
        LOCAL   clip            :RECTL
        LOCAL   text_bbox       :RECTL
        LOCAL   o_rect          :RECTL
        LOCAL   smart_flags            :BYTE
        LOCAL   special_bm_opaque_color:BYTE
        LOCAL   num_planes             :BYTE
        LOCAL   left_clip_mask         :BYTE
        LOCAL   right_clip_mask        :BYTE
        LOCAL   cell_adjust            :DWORD
        LOCAL   buffer                 :DWORD
        LOCAL   fix_total_bytes        :DWORD
        LOCAL   next_scan              :DWORD
        LOCAL   next_plane             :DWORD
        LOCAL   next_scan_xor          :DWORD
        LOCAL   opaque_routine         :DWORD
        LOCAL   opaque_height          :DWORD
        LOCAL   lp_surface             :DWORD
        LOCAL   temp_off_lp_bits       :DWORD
        LOCAL   scan_start             :DWORD
        LOCAL   clipped_font_height    :DWORD
        LOCAL   amt_clipped_on_top     :DWORD
        LOCAL   clear_stack            :DWORD
        LOCAL   min_stack              :DWORD
        LOCAL   build_proc             :DWORD
        LOCAL   phase                  :DWORD
        LOCAL   x2                     :DWORD
        LOCAL   inner_loop             :DWORD
        LOCAL   clipped_table          :DWORD
        LOCAL   non_clipped_table      :DWORD
        LOCAL   inner_byte_count       :DWORD
        LOCAL   current_lhs            :DWORD
        LOCAL   current_rhs            :DWORD
        LOCAL   wc_opaque_lhs          :DWORD
        LOCAL   wc_opaque_rhs          :DWORD
        LOCAL   string_start_bias      :DWORD
        LOCAL   ret_addr               :DWORD
        LOCAL   unrolled_entry_point   :DWORD
        LOCAL   vect_one_in_first      :DWORD
        LOCAL   vect_two_in_first      :DWORD
        LOCAL   vect_one_in_middle     :DWORD
        LOCAL   vect_two_in_middle     :DWORD
        LOCAL   vect_one_in_last       :DWORD
        LOCAL   vect_two_in_last       :DWORD
        LOCAL   ret_addr_2             :DWORD
        LOCAL   ega_oc_saved_data      :DWORD

        DebugMsg <fixed_pitch_strblt SMARTFIX CLIFFL>

        cmp     clipped_font_height,255 ;Height is kept in a byte register
        ja      use_proportional_code            ;Too big, pass it to proportional code
        test    accel,IS_XOR_TEXT or IS_OR_TEXT
        jnz     use_proportional_code

        xor     esi,esi                           ;# chars to bias string start by
        mov     edi,x                             ;X will be used many times
        mov     ecx,edi                           ;Set CL = phase (starting X mod 8)
        and     ecx,7                             ;  and CH = smart_flags = 0
        mov     phase,ecx                         ;Save phase for later

        mov     edx,edi                           ;Assume lhs is starting X
        mov     eax,clip.rcl_xLeft
        cmp     eax,edx                           ;If clip.left < X
        jle     only_one_in_first                ;  then no left side clipping
        mov     edx,eax                           ;Set new lhs
        sub     eax,edi                           ;Compute number of complete bytes
        shr     eax,3                             ;  clipped off the front of the string
        xchg    eax,esi                           ;SI is bias to string start
        mov     al,dl                             ;If lhs-phase < phase
        and     al,7                              ;  then two sources are required
        cmp     al,cl                             ;  for the first destination byte
        jge     only_one_in_first
        or      ch,TWO_SOURCES_IN_FIRST

only_one_in_first:

        mov     ebx,count
        test    bh,11100000b                      ;If any of these bits are set, we'll
        jnz     use_proportional_code            ;  overflow on shifting!
        shl     ebx,3                             ;Compute rhs of string
        add     ebx,edi

        mov     eax,clip.rcl_xRight     ;If rhs =< clip.right
        cmp     ebx,eax                           ;  then no clipping needed
        jle     only_one_in_last
        sub     ebx,eax                           ;Compute complete bytes clipped
        shr     ebx,3                             ;  and remove them from the count
        sub     count,ebx                         ;  of characters to display
        mov     ebx,eax                           ;BX = rhs = clip.right
        and     al,7                              ;If rhs-phase > phase
        cmp     al,cl                             ;  then two sources will be required
        jle     only_one_in_last                 ;  for the last byte
        or      ch,TWO_SOURCES_IN_LAST

only_one_in_last:

        mov     smart_flags,ch
        mov     string_start_bias,esi
        call    comp_byte_interval               ;BX,DX are parameters
        jnc     got_the_interval
        jmp     exit_smart_font                  ;Interval doesn't show

use_proportional_code:

        jmp     build_string                      ;Default to using proportional code

        public got_the_interval

got_the_interval::

        mov     scan_start,edi
        mov     left_clip_mask,al
        mov     right_clip_mask,ah

        mov     eax,count                         ;Adjust count for the complete
        sub     eax,string_start_bias            ;  chars clipped on lhs
        mov     ecx,eax
        mov     count,esi                         ;Set inner loop count
        add     eax,eax                           ;If not enough stack space for the
        add     eax,STACK_SLOP           ;  string, pass it to the
        cmp     eax,esp                           ;  proportional code
        ja      use_proportional_code

        mov     esi,lp_string                     ;--> last character of the string

        mov     eax,string_start_bias
        add     eax,ecx
        shl     eax,1
        add     esi,eax
        sub     esi,4

        std                                       ;!!

;/*
;**
;**       push_font_bits
;**
;**       This loop is used to push the offset of each character
;**       onto the stack.  The offset accounts for any clipping
;**       which may have occured.  Any character out of range will
;**       have the default character's offset pushed for it.
;**
;**       Currently:
;**               DS:SI --> current character in the string
;**               ES:    =  font segment
;**               CX     =  number of characters to process
;**
;*/

        public  push_char_offsets

push_char_offsets::

        mov     edi,amt_clipped_on_top           ;Adjustment for any clipping

;/*
;**       It is possible for our code to indicate that two characters
;**       are required for the first byte, when in fact only one
;**      character is left in the string.  We're going to cheat
;**       by pushing the offset of the null character.  If we use it,
;**       the fine, and if we don't, we'll be restoring the old SP
;**       so it will be cleaned off the stack.
;*/

        mov     clear_stack,esp
        push    null_char_offset

pco_next_char:

        lodsd
        add     eax,eax
        mov     ebx,eax
        add     eax,eax
        add     ebx,eax

        .errnz  (size FONT_ENTRIES) - 6

        mov     eax,pFont

        ASSUME  eax:PTR FONTMAP, ebx:PTR FONT_ENTRIES

        mov     eax,[eax].fsCharOffset[ebx].fe_dBits
        add     eax,edi                           ;Adjust pointer for any clipping
        push    eax                               ;Save offset
        loop    pco_next_char
        cld

;/*
;**       All the character offsets have been pushed onto the stack.
;**       Compute the starting address of the first character and
;**       start drawing characters (that is the reason we came here).
;*/

        call    preset_fix_text
        mov     edi,lp_surface
        mov     eax,text_bbox.rcl_yBottom
        mul     next_scan
        add     edi,eax
        add     edi,scan_start
        mov     ecx,phase                         ;CL = phase
        or      cl,cl
        jnz     phase_non_0


;/*
;**       The destination starts on a byte boundary.  A single source
;**       character is all which is needed for each destination. No
;**       rotation will be required for this case.
;*/

phase_0_do_first:

        mov     al,left_clip_mask                ;If the left clip mask is non-zero
        or      al,al                             ;  then a partial byte will have to
        jz      phase_0_do_inner                 ;  be processed on the lhs
        mov     ss_clip_mask,al                  ;Generic handlers require this
        mov     ret_addr,OFFSET phase_0_do_inner

        char_check

        pop     esi                               ;Offset to bits of first character
        mov     al,OC_ONE_IN_FIRST
        or      excel,RES_EGA_INNER
        jmp     vect_one_in_first

phase_0_do_inner:

        cmp     count,0                           ;Inner loop will exist only if count
        je      phase_0_do_last                  ;  is non-zero
        mov     ret_addr,OFFSET phase_0_do_last
        mov     ss_clip_mask,0FFh
        jmp     vect_one_in_middle

phase_0_do_last:

        mov     al,right_clip_mask               ;If the right clip mask is non-zero
        or      al,al                             ;  then a partial byte will have to
        jz      fixed_text_clean_up              ; be processed on rhs
        mov     ss_clip_mask,al
        mov     ret_addr,OFFSET fixed_text_clean_up

        char_check

        pop     esi                               ;Offset to bits of last character
        mov     al,OC_ONE_IN_LAST
        jmp     vect_one_in_last


;/*
;**       The destination doesn't start on a byte boundary.  Two source
;**       characters will be needed for each destination.  Rotation of
;**       the sources will be required for this case.  Either one or two
;**       source characters will be required for the first and last bytes,
;**       depending on the clipping mask.
;*/

phase_non_0:

        char_check

        pop     esi                               ;Offset to first character's bits
        mov     al,left_clip_mask                ;If the left clip mask is non-zero
        or      al,al                             ;  then a partial byte will have to
        jz      phase_non_0_do_inner             ;  be processed on the lhs
        mov     ss_clip_mask,al                  ;Generic handlers require this
        mov     ret_addr,OFFSET phase_non_0_do_inner
        or      excel,RES_EGA_INNER
        test    smart_flags,TWO_SOURCES_IN_FIRST
        jz      phase_non_0_one_in_first
        mov     al,OC_TWO_IN_FIRST
        jmp     vect_two_in_first

phase_non_0_one_in_first:

        mov     al,OC_ONE_IN_FIRST
        jmp     vect_one_in_first

phase_non_0_do_inner:

        cmp     count,0                           ;Inner loop will exist only if count
        je      phase_non_0_do_last              ;  is non-zero
        mov     ret_addr,OFFSET phase_non_0_do_last
        mov     ss_clip_mask,0FFh
        jmp     vect_two_in_middle

phase_non_0_do_last:

        mov     al,right_clip_mask               ;If the right clip mask is non-zero
        or      al,al                             ;  then a partial byte will have to
        jz      fixed_text_clean_up              ; be processed on rhs
        mov     ss_clip_mask,al
        mov     ret_addr,OFFSET fixed_text_clean_up
        test    smart_flags,TWO_SOURCES_IN_LAST
        jz      phase_non_0_one_in_last
        mov     al,OC_TWO_IN_LAST
        jmp     vect_two_in_last

phase_non_0_one_in_last:

        mov     al,OC_ONE_IN_LAST
        jmp     vect_one_in_last

fixed_text_clean_up:

        mov     esp,clear_stack                   ;Restore incase null char not used

exit_smart_font:

        ret

page

;/***************************************************************************
;*
;* PUBLIC ROUTINE  ega_oc_outer_loop
;*
;* DESCRIPTION   = Overall control logic for opaque clipped text to the EGA.
;*                 For fixed pitch text, this function supersedes the clipped
;*                 bit gathering functions (xxx_one_in_first, xxx_two_in_last,
;*                 etc.).  In either case, it sets up two passes through the
;*                 appropriate generic bit gathering functions.  Since the
;*                 drawing function changes between passes, ss_draw_clipped
;*                 must be set here as needed.
;*
;*                  Registers Preserved:
;*                        CX,DX,DI,DS,ES
;*                  Registers Destroyed:
;*                        AX,BX,SI,BP
;*
;* INPUT         = AL     =  index into ega_oc_dispatch_table
;*                 CL     =  phase
;*                 DS:SI --> font bits
;*                 ES:DI --> destination byte (ES = ScreenSelector)
;*                 ret_addr = return address offset
;* OUTPUT        = ES:DI  --> destination
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        public  ega_oc_outer_loop_fix_two
        public  ega_oc_outer_loop_fix

ega_oc_outer_loop_fix_two::

;/*
;**       The two_in_cell type drawing functions pop the stack for the
;**       next character offset.  Since we must save registers between
;**       passes, the second char offset must come off the stack, and
;**       go back on after registers have been saved.  Upon return from
;**       the lower level code, the stack is ready to restore the saved
;**       registers.
;*/

        pop     ega_oc_saved_data

ega_oc_outer_loop_fix::

        mov     ebx,ret_addr
        mov     ret_addr_2,ebx
jmp     ret_addr_2
        mov     ret_addr,OFFSET ega_oc_outer_loop_ret_1

        movsx   eax,al
        xchg    ebx,eax
        mov     ss_draw_clipped,OFFSET ega_opaque_clip_1_fix

        push    ebx                               ;save registers for next pass
        push    ecx
        push    esi
        push    edi

        call    setup_ega_opaque_clip_magic

        test    bl,OC_MASK_TWO_CHAR

        errnz   <OC_MASK_TWO_CHAR and 0FF00h>

        jz      ega_oc_outer_loop_do_1

        push    ega_oc_saved_data                ;if two_in_cell, put back data

ega_oc_outer_loop_do_1:

        add     ebx,OFFSET ega_oc_dispatch_table
        jmp     [ebx]   ;do first pass

ega_oc_outer_loop_ret_1:

        mov     dx,EGA_BASE + SEQ_DATA
        mov     al,BYTE PTR colors[BACKGROUND]
        out     dx,al

        pop     edi                               ;restore registers for second pass
        pop     esi
        pop     ecx
        pop     ebx

;/*
;**       The next block of code determines if the second pass is
;**       necessary.
;**
;**       Note that the EGA has been programmed to allow writing only to
;**       the planes composing the background color. Since we're writing
;**       opaque text, all planes in the background color also in the
;**       foreground have been set by the first pass.  The second
;**       pass cleans up the background planes not in the foreground
;**       color.  If there aren't any, then skip the second pass.
;*/

        mov     eax,ss_colors
        xor     al,ah                             ;determine mismatching bits
        and     al,ah                             ;isolate those in the bk color
        jz      ega_oc_outer_loop_skip_pass_2

        mov     ret_addr,OFFSET ega_oc_outer_loop_ret_2
        sub     ss_draw_clipped,2


        test    bl,OC_MASK_TWO_CHAR

        errnz   <OC_MASK_TWO_CHAR and 0FF00h>

        jz      ega_oc_outer_loop_do_2

        push    ega_oc_saved_data                ;if two_in_cell, put back data

ega_oc_outer_loop_do_2:

        add     ebx,OFFSET ega_oc_dispatch_table
        jmp     [ebx]                             ;do second pass

ega_oc_outer_loop_ret_2:

        test    excel,RES_EGA_INNER              ;is there a middle part to string?
        jz      ega_oc_outer_loop_exit           ;if no, skip EGA register setup
        call    set_ega_opaque_mode              ;else, prepare EGA for full opaque
        and     excel,not RES_EGA_INNER          ;prevent this at end of string

ega_oc_outer_loop_exit:

        jmp     ret_addr_2

;/*
;**       Update ES:DI as would have been done by second pass, then check
;**       to see if EGA reprogramming is necessary for a non-clipped section
;**       of opaque text.
;*/

ega_oc_outer_loop_skip_pass_2:

        test    bl,OC_MASK_TWO_CHAR

        errnz   <OC_MASK_TWO_CHAR and 0FF00h>

        jz      ega_oc_outer_loop_si_ok
        mov     esi,ega_oc_saved_data            ;if two_in_cell, put back data

ega_oc_outer_loop_si_ok:

        inc     edi                               ;update di for whoever follows
        jmp     ega_oc_outer_loop_ret_2

        page

;/***************************************************************************
;*
;* PUBLIC ROUTINES  ega_opaque_clip_2_fix
;*                  ega_opaque_clip_1_fix
;*
;* DESCRIPTION   =  Device drawing functions for:
;*
;*                      opaque, clipped
;*
;*                  Two passes are required for this mode of text output.  Label
;*                  ega_opaque_clip_x is the drawing function for pass x.
;*
;*                  Registers Preserved:
;*                        BX,CX,DX,SI,DI,DS,ES,BP
;*                  Registers Destroyed:
;*                        AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        public  ega_opaque_clip_2_fix

        public  ega_opaque_clip_1_fix

ega_opaque_clip_2_fix::

        not     al

ega_opaque_clip_1_fix::

        xchg    al,BYTE PTR [edi]

DRAW_ADJUST     = 0                               ;STOSB is not used

        upd_dev                                   ;Will generate the ret

page

;/***************************************************************************
;*
;* PUBLIC ROUTINE  ega_opaque_non_clip_fix:
;*
;* DESCRIPTION   = Standard device drawing functions for:
;*
;*                     opaque, black on white, non-clipped
;*                     opaque, white on black, non-clipped
;*
;*                     EGA opaque mode (color combination does not matter)
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;*
;*
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


ega_opaque_non_clip_fix:

        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_dev                                   ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES  ega_trans_clip_fix
;*                  ega_trans_non_clip_fix
;*
;* DESCRIPTION   =  Drawing routines for EGA, transparent mode, clipped and
;*                  non-clipped.
;*
;*                  Registers Preserved:
;*                        BX,CX,DX,SI,DI,DS,ES,BP
;*                  Registers Destroyed:
;*                        AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


ega_trans_clip_fix:

        and     al,ss_clip_mask

if SPECIAL_CASE_DEV_TNC eq 1

        push    edx
        mov     dx,EGA_BASE + GRAF_DATA
        out     dx,al
        pop     edx
        xchg    al,BYTE PTR [edi]

DRAW_ADJUST = 0                                   ;stosb is not used

        upd_dev                                   ;will generate ret
endif

ega_trans_non_clip_fix:

if SPECIAL_CASE_DEV_TNC eq 1

else
        push    edx
        mov     dx,EGA_BASE + GRAF_DATA
        out     dx,al
        pop     edx
        xchg    al,BYTE PTR [edi]

DRAW_ADJUST = 0                                   ;stosb is not used

        upd_dev <ret>                             ;will generate ret

endif
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES  opaque_white_on_white_clip
;*                  trans_white_clip
;*                  trans_white
;*                  xor_trans_white
;*
;* DESCRIPTION   =  Standard bitmap drawing functions for:
;*
;*                      opaque, white on white, clipped
;*                      transparent, white, clipped
;*                      transparent, white, non-clipped
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;*                 DX = return address
;*
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        public opaque_white_on_white_clip        ;!!!

opaque_white_on_white_clip::

        mov     al,0FFh

trans_white_clip:

        and     al,ss_clip_mask

trans_white:

        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm                                    ;Will generate the ret

xor_trans_white:

        xor     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm                                    ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES  opaque_black_on_black_clip
;*                  trans_black_clip
;*                  trans_black
;*                  or_trans_black
;*                  xor_trans_black
;*
;* DESCRIPTION   = Standard bitmap drawing functions for:
;*
;*                     opaque, black on black, clipped
;*                     transparent, black, clipped
;*                     transparent, black, non-clipped
;*
;*                  Registers Preserved:
;*                        BX,CX,DX,SI,DI,DS,ES,BP
;*                  Registers Destroyed:
;*                        AX
;*
;* INPUT         =  AL = character to output
;*                  ES:DI --> destination byte
;*                  DX = return address
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        public opaque_black_on_black_clip

opaque_black_on_black_clip::

        mov     al,0FFh

trans_black_clip:

        and     al,ss_clip_mask

trans_black:

        not     al
        and     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm                                    ;Will generate the ret

or_trans_black:

        not     al
        or      BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm                                    ;Will generate the ret

xor_trans_black:

        not     al
        xor     BYTE PTR [edi],al

DRAW_ADJUST     = 0                               ;STOSB isn't used

        upd_bm                                    ;Will generate the ret



page

;/***************************************************************************
;*
;* PUBLIC ROUTINES opaque_black_on_white
;*                 opaque_white_on_black
;*
;* DESCRIPTION   = Standard bitmap drawing functions for:
;*
;*                     opaque, black on white, non-clipped
;*                     opaque, white on black, non-clipped
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;*                 DX = return address
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


opaque_black_on_white:

        not     al

opaque_white_on_black:

        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_bm                                    ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES  opaque_black_on_white_clip
;*                  opaque_white_on_black_clip
;*
;* DESCRIPTION   = Standard bitmap drawing functions for:
;*
;*                     opaque, black on white, clipped
;*                     opaque, white on black, clipped
;*
;*                Registers Preserved:
;*                      BX,CX,DX,SI,DI,DS,ES,BP
;*                Registers Destroyed:
;*                      AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;*                 DX = return address
;*
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


opaque_black_on_white_clip:

        not     al

opaque_white_on_black_clip:

        mov     ah,ss_clip_mask
        and     al,ah
        not     ah
        and     ah,BYTE PTR [edi]
        or      al,ah
        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_bm                                    ;Will generate the ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINES  opaque_white_on_white
;*                  opaque_black_on_black
;*
;* DESCRIPTION   = Standard bitmap drawing functions for:
;*
;*                     opaque, white on white, non-clipped
;*                     opaque, black on black, non-clipped
;*
;*                Registers Preserved:
;*                      BX,CX,DX,SI,DI,DS,ES,BP
;*                Registers Destroyed:
;*                      AX
;*
;* INPUT         = AL = character to output
;*                 ES:DI --> destination byte
;*                 DX = return address
;*
;*
;* OUTPUT        = ES:DI --> same byte, next scan
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


opaque_white_on_white:

        mov     al,0FFh
ifndef JFIX        ;IBMJ
        jmpnext
else  ;JFIX        ;IBMJ
 jmp jstop
 ALIGN 4
endif ;JFIX        ;IBMJ

opaque_black_on_black:

        xor     al,al

ifndef JFIX        ;IBMJ
        jmpnext stop
endif ;JFIX        ;IBMJ

jstop:         ;IBMJ
        stosb

DRAW_ADJUST     = 1                               ;STOSB is used

        upd_bm                                    ;Will generate the ret
page


;/*
;**
;**       Define the drawing logic tables.  These tables are used to
;**       fetch the address of the output function for the combination
;**       of foreground/background colors, opaque/transparent mode,
;**       and device/bitmap.
;**
;**       The tables are indexed as follows:
;**
;**         DEV/BM O/T FG BK  0;
;**           |     |   |  |
;**           |     |   |   ----------  background color (0/1)
;**           |     |   |
;**           |     |    -------------  foreground color (0/1)
;**           |     |
;**           |      -----------------  0 if transparent, 1 if opaque
;**           |
;**            ------------------------ 0 if a bitmap, 1 if the device
;**
;** There are 3 sets of drawing logic tables with the first being overwrite,
;** then xor, and finally or. Each set has three tables clipped, nonclipped,
;** and mono-nonclipped. Each of these tables are 32 bytes long making each
;** group 96 bytes long. These lengths are expected to be such and the
;** dw 0's should be left in place.
;*/

MASK_DEVBM      equ     00010000b
MASK_OT         equ     00001000b
MASK_FG         equ     00000100b
MASK_BK         equ     00000010b

MASK_DEV_ONC    equ     MASK_DEVBM or MASK_OT    ;MASK_BK, MASK_FG wildcards
MASK_DEV_TNC    equ     MASK_DEVBM                ;MASK_BK, MASK_FG wildcards
MASK_DEV_OC     equ     MASK_DEVBM or MASK_OT    ;MASK_BK, MASK_FG wildcards
MASK_DEV_TC     equ     MASK_DEVBM                ;MASK_BK, MASK_FG wildcards

MASK_BM_OBWNC   equ     MASK_OT or MASK_BK
MASK_BM_OWBNC   equ     MASK_OT or MASK_FG
MASK_BM_TBNC    equ     0                          ;MASK_BK is a wildcard
MASK_BM_TWNC    equ     MASK_FG                    ;MASK_BK is a wildcard


clipped_drawing_functions label DWORD

        DWORD   bm_trans_color_fix
        DWORD   bm_trans_color_fix
        DWORD   bm_trans_color_fix
        DWORD   bm_trans_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   4 dup (0)                         ;these are a special case


non_clipped_drawing_functions label DWORD

        DWORD   bm_trans_color_fix
        DWORD   bm_trans_color_fix
        DWORD   bm_trans_color_fix
        DWORD   bm_trans_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix


mono_non_clipped_drawing_functions label DWORD

        DWORD   trans_black
        DWORD   trans_black
        DWORD   trans_white
        DWORD   trans_white
        DWORD   opaque_black_on_black
        DWORD   opaque_black_on_white
        DWORD   opaque_white_on_black
        DWORD   opaque_white_on_white
        DWORD   8 dup (0)

clipped_table_size = $ - clipped_drawing_functions

xor_clipped_drawing_functions label DWORD

        DWORD   xor_bm_trans_color_fix
        DWORD   xor_bm_trans_color_fix
        DWORD   xor_bm_trans_color_fix
        DWORD   xor_bm_trans_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   4 dup (0)                         ;these are a special case


xor_non_clipped_drawing_functions label DWORD

        DWORD   xor_bm_trans_color_fix
        DWORD   xor_bm_trans_color_fix
        DWORD   xor_bm_trans_color_fix
        DWORD   xor_bm_trans_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix


xor_mono_non_clipped_drawing_functions label DWORD

        DWORD   xor_trans_black
        DWORD   xor_trans_black
        DWORD   xor_trans_white
        DWORD   xor_trans_white
        DWORD   opaque_white_on_black
        DWORD   opaque_white_on_white
        DWORD   opaque_black_on_black
        DWORD   opaque_black_on_white
        DWORD   8 dup (0)

xor_clipped_table_size = $ - xor_clipped_drawing_functions

        .errnz  clipped_table_size - xor_clipped_table_size

or_clipped_drawing_functions label DWORD

        DWORD   or_bm_trans_color_fix
        DWORD   or_bm_trans_color_fix
        DWORD   or_bm_trans_color_fix
        DWORD   or_bm_trans_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   ega_trans_clip_fix
        DWORD   4 dup (0)                         ;these are a special case


or_non_clipped_drawing_functions label DWORD

        DWORD   or_bm_trans_color_fix
        DWORD   or_bm_trans_color_fix
        DWORD   or_bm_trans_color_fix
        DWORD   or_bm_trans_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   bm_opaque_color_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_trans_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix
        DWORD   ega_opaque_non_clip_fix


or_mono_non_clipped_drawing_functions label DWORD

        DWORD   or_trans_black
        DWORD   or_trans_black
        DWORD   trans_white
        DWORD   trans_white
        DWORD   opaque_black_on_black
        DWORD   opaque_black_on_white
        DWORD   opaque_white_on_black
        DWORD   opaque_white_on_white

or_clipped_table_size = $ - or_clipped_drawing_functions

        .errnz  or_clipped_table_size - xor_clipped_table_size + 32

;/*
;**       The table ega_oc_dispatch_table is used by ega_oc_outer_loop
;**       to determine which case to call for each pass at drawing text.
;*/


ega_oc_dispatch_table   label                    DWORD

        DWORD   gen_one_in_first
        DWORD   gen_two_in_first
        DWORD   gen_one_in_last
        DWORD   gen_two_in_last

page


;/***************************************************************************
;*
;* FUNCTION NAME = preset_fix_text
;*
;* DESCRIPTION   = Set any frame variables and stack locations (at top of ring
;*                 2 stack) required to output text with the current
;*                 attributes.
;*
;*                 Registers Preserved:
;*                       DX,SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,ES,FLAGS
;*
;* INPUT         = SS = ring 2 stack
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        public  preset_fix_text

preset_fix_text::

        mov     ss_p_frame,ebp
        mov     ecx,next_scan
        mov     ss_next_scan,ecx
        mov     ecx,colors
        mov     ss_colors,ecx

;/*
;**       Accumulate foreground/background colors, opaque/transparent mode,
;**       and device/bitmap to determine which drawing functions will be
;**       used.
;*/

        mov     bl,accel
        mov     ah,excel
        and     ebx,IS_OPAQUE                     ;BL = 0000000 O/T

        errnz   IS_OPAQUE-00000001

        shr     cl,1
        rcl     bl,1                              ;BL = 000000 O/T FG

        errnz   FOREGROUND

        shr     ch,1                              ;BL = 00000 O/T FG BK
        rcl     bl,1

        errnz   BACKGROUND-FOREGROUND-1

        mov     dl,ah                             ;save the excel flag
        and     ah,IS_DEVICE
        or      bl,ah                             ;BL = 0000 DEV/BM O/T FG BK

        errnz   IS_DEVICE-00001000b

        shl     ebx,1                             ;BX = 00000000 000 DEV/BM O/T FG BK 0

;/*
;**       All clipped text will use the generic handlers, though text
;**       destined for the display needs special consideration, as two
;**       passes at drawing may be required.
;*/

        and     dl,IS_DEVICE                      ; are we using a bitmap
        jnz     preset_fix_no_x_or               ;no
        xor     edx,edx
        mov     cl,accel
        and     cl,(IS_OR_TEXT OR IS_XOR_TEXT)
        jz      preset_fix_no_x_or
        shr     cl,2

        .errnz  IS_XOR_TEXT-00000010b

        .errnz  IS_OR_TEXT -00000100b

        mov     edx,clipped_table_size
        shl     edx,cl
        add     ebx,edx

 preset_fix_no_x_or:

        mov     eax,ebx                           ;check for EGA,opaque,clip
        and     eax,MASK_DEV_OC
        cmp     eax,MASK_DEV_OC
        jne     preset_fix_text_def_clip_fun

        mov     eax,OFFSET ega_oc_outer_loop_fix ;special case
        mov     ecx,OFFSET ega_oc_outer_loop_fix_two
        mov     vect_one_in_first,eax
        mov     vect_two_in_first,ecx
        mov     vect_one_in_last,eax
        mov     vect_two_in_last,ecx
        jmp     preset_fix_text_set_clip_draw_fun

preset_fix_text_def_clip_fun:

        mov     vect_one_in_first,OFFSET gen_one_in_first
        mov     vect_two_in_first,OFFSET gen_two_in_first
        mov     vect_one_in_last,OFFSET  gen_one_in_last
        mov     vect_two_in_last,OFFSET  gen_two_in_last

preset_fix_text_set_clip_draw_fun:

        mov     eax,clipped_drawing_functions[ebx]
        mov     ss_draw_clipped,eax
        mov     eax,next_scan
        mov     ss_next_scan,eax


;/*
;**       Set any special case middle byte routines
;*/


if SPECIAL_CASE_DEV_ONC eq 1

        mov     eax,ebx
        and     al,MASK_DEV_ONC
        cmp     al,MASK_DEV_ONC

        errnz   <MASK_DEV_ONC and 0FF00h>

        jne     preset_fix_text_not_dev_onc

        mov     eax,OFFSET dev_onc_one_in_cell
        mov     ecx,OFFSET dev_onc_two_in_cell
        jmp     preset_fix_text_finish

preset_fix_text_not_dev_onc:

endif

if SPECIAL_CASE_DEV_TNC eq 1

        mov     eax,ebx
        and     al,MASK_DEV_TNC
        cmp     al,MASK_DEV_TNC

        errnz   <MASK_DEV_TNC and 0FF00h>

        jne     preset_fix_text_not_dev_tnc

        mov     eax,OFFSET dev_tnc_one_in_cell
        mov     ecx,OFFSET dev_tnc_two_in_cell
        jmp     preset_fix_text_finish

preset_fix_text_not_dev_tnc:

endif

if SPECIAL_CASE_BM_OBWNC eq 1

        mov     eax,OFFSET bm_obwnc_one_in_cell
        mov     ecx,OFFSET bm_obwnc_two_in_cell
        cmp     bl,INDEX_OBW
        je      preset_fix_text_finish

endif


if SPECIAL_CASE_BM_TBNC eq 1

        mov     eax,OFFSET bm_tbnc_one_in_cell
        mov     ecx,OFFSET bm_tbnc_two_in_cell
        cmp     bl,INDEX_TB
        je      preset_fix_text_finish
        cmp     bl,INDEX_TB_ALT
        je      preset_fix_text_finish
endif

        mov     eax,mono_non_clipped_drawing_functions[ebx]

        cmp     num_planes,1                      ;assumes color display
        je      preset_fix_text_set_nc_draw_fun ;if mono bitmap, jump

        mov     eax,non_clipped_drawing_functions[ebx]

preset_fix_text_set_nc_draw_fun:

        mov     ss_draw,eax
        mov     eax,OFFSET gen_one_in_cell
        mov     ecx,OFFSET gen_two_in_cell

preset_fix_text_finish:

        mov     vect_one_in_middle,eax
        mov     vect_two_in_middle,ecx

        test    bl,MASK_DEVBM

        errnz   <MASK_DEVBM and 0FF00h>

        jz      preset_fix_text_exit


;/*
;**       These last initializations are only for the EGA.
;*/

        test    bl,MASK_OT

        errnz   <MASK_OT and 0FF00h>

        jnz     preset_fix_text_opaque
        call    preset_fix_ega_trans_mode
        jmp     preset_fix_text_exit

preset_fix_text_opaque:

        call    preset_fix_ega_opaque_mode

preset_fix_text_exit:

        ret

page

;/***************************************************************************
;*
;* PUBLIC ROUTINE   preset_fix_ega_opaque_mode
;*
;* DESCRIPTION   = Do any one-time initialization of the EGA hardware for
;*                 opaque text.
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,DX,ES,FLAGS
;*
;* INPUT         = BP = local variable frame
;*                 SS = ring 2 stack
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


preset_fix_ega_opaque_mode:

        mov     dx,EGA_BASE + SEQ_DATA
        mov     al,MM_ALL
        out     dx,al
        mov     dl,GRAF_ADDR                      ;DX = GRAF_ADDR
        mov     ax,0FFh shl 8 + GRAF_BIT_MASK
        out     dx,ax
        mov     ax,0000b shl 8 + GRAF_ENAB_SR
        out     dx,ax

        push    ebx                               ;this routine saves BX
        mov     ebx,colors

        .errnz  FOREGROUND

        .errnz  BACKGROUND-1

        INVOKE  InitTonysBarNGrill               ;kills bx

        mov     ebx,colors
        mov     ah,bl                             ;get foreground color in AH
        xor     ah,bh                             ;xor in background color, so
        pop     ebx                               ;  AH now reflects the differences
                                                  ;  between fore and back
        mov     al,GRAF_SET_RESET
        out     dx,ax
        not     ah
        mov     al,GRAF_ENAB_SR
        out     dx,ax
        mov     ax,DR_XOR shl 8 + GRAF_DATA_ROT
        out     dx,ax

        ret

;/***************************************************************************
;*
;* PUBLIC ROUTINE  preset_fix_ega_trans_mode
;*
;* DESCRIPTION   = Do any one-time initialization of the EGA hardware for
;*                 transparent text.
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,DX,FLAGS
;*
;* INPUT         = BP =
;*                 SS = ring 2 stack
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


preset_fix_ega_trans_mode:

        mov     dx,EGA_BASE + GRAF_ADDR
        mov     ah,byte ptr colors[FOREGROUND]
        mov     al,GRAF_SET_RESET
        out     dx,ax

        mov     al,accel
        mov     ah,DR_XOR
        shr     al,2
        jc      pfetm_have_mode

        .errnz  IS_XOR_TEXT-00000010b

        mov     ah,DR_OR
        shr     al,1
        jc      pfetm_have_mode

        .errnz  IS_OR_TEXT-00000100b

        mov     ah,DR_SET

pfetm_have_mode:

        mov     al,GRAF_DATA_ROT
        out     dx,ax

        mov     ax,MM_ALL shl 8 + GRAF_ENAB_SR
        out     dx,ax
        mov     al,GRAF_BIT_MASK
        out     dx,al

        ret

;/*
;**
;**       The following cases are the general purpose routines for
;**       outputting the text.  They will call through the stack
;**       locations ss_draw and ss_draw_clipped to perform the
;**       actual output operations.
;**
;**       Following the general purpose routines are any special
;**       case routines.
;**
;*/

        general_case    <gen_one_in_first>,<one_in_first>,<clipped_output>
        general_case    <gen_two_in_first>,<two_in_first>,<clipped_output>
        general_case    <gen_one_in_cell>,<one_in_cell>,<non_clipped_output>
        general_case    <gen_two_in_cell>,<two_in_cell>,<non_clipped_output>
        general_case    <gen_one_in_last>,<one_in_last>,<clipped_output>
        general_case    <gen_two_in_last>,<two_in_last>,<clipped_output>


if SPECIAL_CASE_BM_OBWNC eq 1                     ;Bitmap, opaque blk on white, no clip

        spec_case   <bm_obwnc_one_in_cell>,<one_in_cell>,<obwnc>
        spec_case   <bm_obwnc_two_in_cell>,<two_in_cell>,<obwnc>
endif

if SPECIAL_CASE_BM_TBNC eq 1                      ;Bitmap, transp black, non-clipped

        spec_case   <bm_tbnc_one_in_cell>,<one_in_cell>,<tbnc>
        spec_case   <bm_tbnc_two_in_cell>,<two_in_cell>,<tbnc>
endif

if SPECIAL_CASE_DEV_ONC eq 1                      ;Device, opaque, non-clipped

        o_spec_case   <dev_onc_one_in_cell>,<one_in_cell>,<ega_onc_fix>
        o_spec_case   <dev_onc_two_in_cell>,<two_in_cell>,<ega_onc_fix>
endif

if SPECIAL_CASE_DEV_TNC eq 1                      ;Device, transparent, non-clipped

        t1_spec_case   <dev_tnc_one_in_cell>,<one_in_cell>,<ega_tnc_fix>
        t2_spec_case   <dev_tnc_two_in_cell>,<two_in_cell>,<ega_tnc_fix>
endif

fixed_pitch_strblt      ENDP

        end
