;*DDK*************************************************************************/
;
; 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
;***********************************************************************
;
;   Module          = VIOTEXT.ASM
;
;   Description     = Private AI code
;
;   Function        = Does AVIO text work
;
;
;   Change log:
;   Date      Mark         APAR      Description
;   --------  ------------ --------- -----------------------------------
;
;***********************************************************************

INCL_GPIBITMAPS EQU     1
INCL_FONTFILEFORMAT     equ     1       ; to include pmfont.inc
include os2.inc
include eddinclt.inc

include eddhcone.inc
include eddhmacr.inc
include eddhtype.inc

?DF     equ     1       ; we dont want _TEXT segment defined
include cmacros.inc
include eddhavio.inc

ifdef _8514
include 8514.inc
endif

ifndef PALETTE_MGR
 .err "PALETTE_MGR is not defined."
 .err "This file can't be built without Palette Manager."
endif ;/* end PALETTE_MGR */

ifdef _8514
include viomacro.inc
endif

extrn _eddt_InvalidateCache         :PROC
extrn _eddt_LocateCachedFont        :PROC
extrn _GetToBeDrawnRect             :PROC

ifdef   _8514
extrn _AVIO24HVLine                 :PROC
ifdef BPP24
extrn _Copy16MonoToVRAM             :PROC
endif ; BPP24
endif ; _8514


ifdef   AVIO_CGA_TEXT
extrn _update_cache_charrect_2      :PROC
update_cache_charrect       equ <_update_cache_charrect_2>
CELL_SHIFT                  equ 1
endif ; AVIO_CGA_TEXT

ifdef   AVIO_MFI_TEXT
VARIABLE_BG_MIX             equ 1
AVIO_HAS_U_SCORE            equ 1
extrn _update_cache_charrect_4      :PROC
update_cache_charrect       equ <_update_cache_charrect_4>
CELL_SHIFT                  equ 2
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
VARIABLE_BG_MIX             equ 1
AVIO_HAS_GRID               equ 1
AVIO_HAS_U_SCORE            equ 1
extrn _common_update_cache_charrect :PROC
update_cache_charrect       equ <_common_update_cache_charrect>
CELL_SHIFT                  equ 2
endif ; AVIO_DBCS_TEXT

ifdef   AVIO_EPOCH_MONO_TEXT
AVIO_HAS_GRID               equ 1
AVIO_HAS_U_SCORE            equ 1
extrn _epoch_update_cache_charrect :PROC
update_cache_charrect       equ <_epoch_update_cache_charrect>
CELL_SHIFT                  equ 1
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
AVIO_HAS_GRID               equ 1
extrn _epoch_update_cache_charrect :PROC
update_cache_charrect       equ <_epoch_update_cache_charrect>
CELL_SHIFT                  equ 1
endif ; AVIO_EPOCH_COLOR_TEXT


ifdef   AVIO_EPOCH_MONO_TEXT
extrn _ulPhysColor                      :dword
ifdef   TMP
extrn _ulPhysColorIndex                 :dword
endif ; TMP
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
extrn _lQualifier                       :dword
endif ; AVIO_EPOCH_COLOR_TEXT


_DATA           segment dword use32 public 'DATA'

extrn _CIAArray                         :dword
extrn _CTArray                          :byte

ifdef _8514
extrn _CfpoArray                        :byte
endif ; _8514

ifdef BPP24
extrn _CIndexArray                      :dword
endif ; BPP24

_DATA           ends


CIAArray        equ     _CIAArray
CTArray         equ     _CTArray

ifdef _8514
CfpoArray       equ     _CfpoArray
endif ; _8514

ifdef BPP24
CIndexArray     equ     _CIndexArray
endif ; BPP24


_TEXT           segment dword use32 public 'CODE'
                assume  cs:FLAT, ds:FLAT, es:FLAT





;/********************************************************************/
;/*                                                                  */
;/* Function: CGATextBlock                                           */
;/* Function: MFITextBlock                                           */
;/* Function: DBCSCommonBlock                                        */
;/* Function: EpochMonoBlock                                         */
;/* Function: EpochColorBlock                                        */
;/*                                                                  */
;/* Called by: eddv*.c modules (charrect, charstr, scrollrect)       */
;/*                                                                  */
;/* This code draws a block of CGA/MFI text                          */
;/* into all the current clip rectangles.                            */
;/*                                                                  */
;/* This fonction was enhanced to be able to handle DBCS             */
;/* character.                                                       */
;/*                                                                  */
;/* Entry -  pFontDetails    pointer to base FONTDETAILS             */
;/*          pAvioInfo       pointer to AVIOINFO structure           */
;/*                                                                  */
;/* Exit  -  EAX             (no error: 0FFFFFFFFh  error: 0)        */
;/*                                                                  */
;/* Registers: EBX,ESI,EDI,ES,DS             -- will be preserved    */
;/********************************************************************/

        align   4

ifdef   AVIO_CGA_TEXT
cProc CGATextBlock <PUBLIC>,<ebx,esi,edi,es,ds>
endif ; AVIO_CGA_TEXT

ifdef   AVIO_MFI_TEXT
cProc MFITextBlock <PUBLIC>,<ebx,esi,edi,es,ds>
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
cProc DBCSCommonBlock <PUBLIC>,<ebx,esi,edi,es,ds>
endif ; AVIO_DBCS_TEXT

ifdef   AVIO_EPOCH_MONO_TEXT
cProc EpochMonoBlock <PUBLIC>,<ebx,esi,edi,es,ds>
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
cProc EpochColorBlock <PUBLIC>,<ebx,esi,edi,es,ds>
endif ; AVIO_EPOCH_COLOR_TEXT

        parmD   pFontDetails
        parmD   pAvioInfo
        localD  mask_org_store
        localD  pCharBuffer
        localD  pcbufRow
        localD  sbcsCell
        localD  lastSbcsCell
        localD  dlCell
        localD  dtCell
        localB  bColCounter
        localB  bRowCounter
        localW  sCharRectX0
        localW  sCharRectX1
        localW  sCharRectY0
        localW  sCharRectY1
        localD  lRowPos
        localD  lCurrentPos
        localD  indx
        localW  numClipRects
ifdef   AVIO_EPOCH_MONO_TEXT
  ifdef   BPP24
        localD  sWhiteStore
        localD  sBlackStore
        localD  sPhysColorStore
        localD  dCurrFG
        localD  dCurrBG
  else  ; BPP24
        localW  sWhiteStore
        localW  sBlackStore
        localW  sPhysColorStore
  endif ; BPP24
endif ; AVIO_EPOCH_MONO_TEXT
ifdef   AVIO_HAS_GRID
  ifdef   BPP24
        localD  sGridStore
  else  ; BPP24
        localW  sGridStore
  endif ; BPP24
        localB  bCurrGrid
endif ; AVIO_HAS_GRID
ifdef   AVIO_EPOCH_MONO_TEXT
        localB  bCurrFG
        localB  bCurrBG
endif ; AVIO_EPOCH_MONO_TEXT
        localB  bDLWritten
        localB  bDupCount
ifdef   AVIO_EPOCH_COLOR_TEXT
        localB  bIntensityBit
endif ; AVIO_EPOCH_COLOR_TEXT
ifdef _8514
        localD  pVRAM
ifdef BPP24
        localD  lWork
        localD  pFocafnt
        localW  usPels
        localW  usHeight
        localW  RightClip
        localW  LeftClip
        localW  TopClip
        localW  BottomClip
        localW  x_src
        localW  y_src
        localW  fGrey
endif ; BPP24
        localD  PattMap
        localD  DestMap
        localW  Dim2
endif ; _8514

cBegin

ifndef _8514
        pushxga                         ; save xga registers
endif ; _8514

ifdef BPP24
        mov     _CouldntCache, 0        ; assume we'll cache the fonts
endif ; BPP24

        ;/************************************************************/
        ;/* Are there any characters to print?                       */
        ;/************************************************************/
        cmp     AIxfer.bAcross, 0       ; columns in CharRect 0?
        je      short @f                ; yes, exit with do nothing
        cmp     AIxfer.bDown, 0         ; rows in CharRect 0?
        jne     short some_chars        ; yes exit with do nothing
@@:
        ;/************************************************************/
        ;/* Nothing here for us to do so quit                        */
        ;/************************************************************/
        mov     eax,0FFFFFFFFh
        jmp     do_nothing              ; exit at once

some_chars:
        ;/************************************************************/
        ;/* Something to do so get do some set-up                    */
        ;/* Get the font header and the base of the memory mapped    */
        ;/* registers                                                */
        ;/************************************************************/
        sub     eax,eax
        dec     eax
        mov     lastSbcsCell,eax        ; clear lastSbcsCell
ifndef _8514
        movxga  _pRealXGARegs           ; restore xga H/W registers
else ; _8514
        movxga  _pReal8514Regs
endif ; _8514

        ;/************************************************************/
        ;/* calculate CharRect dimension for later use.              */
        ;/************************************************************/
        mov     ecx,pAvioInfo
        movzx   ax,AIxfer.bRow
        mul     [ecx].bCellHeight
        add     ax,[ecx].sYoffset
        mov     sCharRectY0,ax          ; first, top left Y

        movzx   ax,AIxfer.bDown
        mul     [ecx].bCellHeight
        add     ax,sCharRectY0
        dec     ax
        mov     sCharRectY1,ax          ; bottom right Y

        movzx   ax, AIxfer.bColumn
        mul     [ecx].bCellWidth
        add     ax, [ecx].sXoffset
        mov     sCharRectX0,ax          ; top left X

        movzx   ax,AIxfer.bAcross
        mul     [ecx].bCellWidth
        add     ax,sCharRectX0
        dec     ax
        mov     sCharRectX1,ax          ; bottom right X

ifdef   AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Here, we get actual FG color index for Black, White.     */
        ;/* Through following drawing, we don't use any colors       */
        ;/* except above colors and Physical color.                  */
        ;/************************************************************/
        sub     eax,eax
        mov     al,0Fh                  ; index for White
        shl     eax,2                           ; table is dwords so * 4
        add     eax, dword ptr _pAVIOColorXlate ; add the table start
        mov     eax, [eax]                      ; get the color value
  ifdef   BPP24
        mov     sWhiteStore,eax
  else  ; BPP24
        mov     sWhiteStore,ax
  endif ; BPP24

        sub     eax,eax
        mov     al,0                    ; index for Black
        shl     eax,2                           ; table is dwords so * 4
        add     eax, dword ptr _pAVIOColorXlate ; add the table start
        mov     eax, [eax]                      ; get the color value
  ifdef   BPP24
        mov     sBlackStore,eax
  else  ; BPP24
        mov     sBlackStore,ax
  endif ; BPP24
        mov     eax,_ulPhysColor        ; get physical color value
  ifdef   BPP24
        mov     sPhysColorStore,eax
  else  ; BPP24
        mov     sPhysColorStore,ax
  endif ; BPP24
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_HAS_GRID                 ; DBCS EpochColor EpochMono
        ;/************************************************************/
        ;/* Here, we get actual FG color for Vertical/Horizontal     */
        ;/* grid (White/Green) and save it.                          */
        ;/************************************************************/
        sub     eax,eax

  ifdef   AVIO_EPOCH_MONO_TEXT
        ; Grid color is always green. NOT current character color !
        mov     al, 0Ah                 ; index for Green
  else ;  AVIO_EPOCH_MONO_TEXT
        mov     al, 0Fh                 ; index for White
  endif ; AVIO_EPOCH_MONO_TEXT
        mov     bCurrGrid, al

        shl     eax,2                           ; table is dwords so * 4
        add     eax, dword ptr _pAVIOColorXlate ; add the table start
        mov     eax, [eax]                      ; get the color value

  ifdef   BPP24
        mov     sGridStore,eax
  else  ; BPP24
        mov     sGridStore,ax
  endif ; BPP24

endif ; AVIO_HAS_GRID


ifdef   AVIO_EPOCH_COLOR_TEXT
        ;/************************************************************/
        ;/* Here, we check screen attribute and determine we use     */
        ;/* intensified color or not.                                */
        ;/************************************************************/
        sub     eax,eax
        mov     bIntensityBit,al        ; default is not intensified.
        mov     eax,_lQualifier         ; get scrren attribute
        and     eax,EPOCH_PHYSHILIGHTED ; color intensified?
        jz short @f                     ; no
        mov     al,08h
        mov     bIntensityBit,al
@@:
endif ; AVIO_EPOCH_COLOR_TEXT

        ;/************************************************************/
        ;/* Now loop through all the clip rectangles                 */
        ;/************************************************************/
        mov     ax, AIxfer.cClipRects   ; get number of clipping rects
        mov     numClipRects,ax         ; save it

        ;/************************************************************/
        ;/* Get offset to first clip rectangle and use it to         */
        ;/* initialize our current clip rectangle pointer            */
        ;/************************************************************/
        mov     eax, AIxfer.pFirstClipRect      ; get pointer to first
                                                ; clip rect
        mov     AIxfer.pCurrentClipRect, eax    ; save it

next_clip:
        ;/************************************************************/
        ;/* Here we call GetToBeDrawnRect and get Drawing area.      */
        ;/************************************************************/
        mov     ax,sCharRectY1
        swap    eax
        mov     ax,sCharRectX1
        push    eax                     ; CharRect(x1,y1)
        mov     ax,sCharRectY0
        swap    eax
        mov     ax,sCharRectX0
        push    eax                     ; CharRect(x0,y0)
        push    AIxfer.pCurrentClipRect ; pointer to clipping rect
        push    pAvioInfo               ; pointer to AvioInfo struc
        call    _GetToBeDrawnRect
        add     esp,16
        cmp     eax,0FFFFFFFFh          ; intersect region exists?
        je new_clip                     ; no, go to next clip

clipped_rect_constructed:
        ;/************************************************************/
        ;/* Set row counter.                                         */
        ;/************************************************************/
        mov     al,AIxfer.bNumOfRow
        mov     bRowCounter,al

        ;/************************************************************/
        ;/* We calculate demension of clipping rectangle and set     */
        ;/* mask map according to it. (Writing with mask map set     */
        ;/* deffects performance, so we need to change this logic    */
        ;/* in a near future.)                                       */
        ;/************************************************************/

ifndef _8514
        ;/************************************************************/
        ;/* The offsets                                              */
        ;/************************************************************/
        mov     ecx,AIxfer.pCurrentClipRect
        mov     dx, [ecx].clip_y0
        swap    edx
        mov     dx, [ecx].clip_x0       ; EDX high word - top left Y
                                        ;     low  word - top left X

        ;/************************************************************/
        ;/* The height                                               */
        ;/************************************************************/
        mov     ax, [ecx].clip_y1
        sub     ax, [ecx].clip_y0
        swap    eax

        ;/************************************************************/
        ;/* The width                                                */
        ;/************************************************************/
        mov     ax, [ecx].clip_x1
        sub     ax, [ecx].clip_x0       ; EAX high word - height
                                        ;     low  word - width

        ;/************************************************************/
        ;/* Wait on the hardware before going any further            */
        ;/************************************************************/
        waitshort                       ; wait on the hardware

        ;/************************************************************/
        ;/* we want the mask map                                     */
        ;/************************************************************/
        memregwrite     pi_map_index_M, SEL_MASK_MAP
                                        ; select mask map registers
        ;/************************************************************/
        ;/* Set the offsets and dimensions of the mask map           */
        ;/************************************************************/
        mov             mask_org_store, edx ; save mask map origin
        memregwrite     mask_org, edx       ; set mask map origin
        memregwrite     pi_map_size_M, eax  ; set mask map dimension

        ;/************************************************************/
        ;/* Now set up the source (pattern) bitmap (ie the character)*/
        ;/* These values will be the same throughout the operation.  */
        ;/************************************************************/
        memregwrite     pi_map_index_B, SEL_PIX_MAP_B

endif ; _8514

        ;/************************************************************/
        ;/* Now set up for cell scaning in clipped rectangle.        */
        ;/************************************************************/

        mov     eax,AIxfer.pLVBChars    ; load pointer to char buffer
        mov     pCharBuffer,eax         ; from top left cell in
        movzx   eax,AIxfer.bBufferWidth ; CharRect to top left cell in
        mov     dl,AIxfer.bClppdRow
        mov     cl,AIxfer.bRow
        sub     dl,cl                   ; get number of row from char
        mul     dl                      ; rect top row to clipped rect
        shl     eax,CELL_SHIFT          ; convert it to number of cell (1/2)
        add     pCharBuffer,eax         ; move pointer
        movzx   eax,AIxfer.bClppdColumn ; get num of column from chat
        mov     dl,AIxfer.bColumn       ; rect left column to clipped
        sub     al,dl                   ; rect.
        shl     eax,CELL_SHIFT          ; convert it to number of cell (1/2)
        add     pCharBuffer,eax         ; move pointer
        mov     eax,pCharBuffer
        mov     pcbufRow,eax            ; save it to later use

        mov     edx,pAvioInfo
        movzx   ax,AIxfer.bClppdRow     ; get position of top left
        mul     [edx].bCellHeight       ; cell in current clipped rect.
        add     ax,[edx].sYoffset       ; (save it for later use)
        swap    eax
        movzx   ax,AIxfer.bClppdColumn
        mul     [edx].bCellWidth
        add     ax,[edx].sXoffset
        mov     lRowPos,eax

next_row:
ifdef _8514

        WaitQ   1
        outwQ   READ_ENABLE,READ_ALL_PLANES
        ifndef  S3
        setclip 0,0,SCR_8514_WIDTH-1,SCR_8514_HEIGHT-1
        else
        setclip 0,0,SCR_S3_WIDTH-1,SCR_S3_HEIGHT-1
        endif

endif ; _8514

        ;/************************************************************/
        ;/* We are at the first column in a row of a clipped         */
        ;/* rectangle. At first, we have to ensure that char images  */
        ;/* in this row are all cached. We do this by calling        */
        ;/* update_cache_charrect. This routine also constructs char */
        ;/* image/address array for cells in current row of clipped  */
        ;/* rect. We will perform char drawing later by using these  */
        ;/* array.                                                   */
        ;/************************************************************/
ifdef BPP24
        cmp     _CouldntCache, 0
        jz      short @f
        call    _eddt_InvalidateCache   ; flush the cache.
        push    pFontDetails
        call    _eddt_LocateCachedFont
        add     esp,4
        mov     _CouldntCache, 0        ; assume we'll cache the fonts
@@:
endif ; BPP24

        mov     al,0FFh                 ; set initial state of
        mov     bDLWritten,al           ; bDLWritten (base addr not set)
        mov     al,AIxfer.bNumOfColumn  ; load number of column
        mov     bColCounter,al          ; set column counter
        mov     eax,lRowPos             ; save first column position
        mov     lCurrentPos,eax         ; in current row
        push    pCharBuffer
        push    pFontDetails
        call    update_cache_charrect
        add     esp,8
        or      eax,eax                 ; caching succeeded?
        jnz short update_succeeded      ; yes, go writing

        ;/************************************************************/
        ;/* update_cache_charrect failed. The font may be flashed    */
        ;/* from cache. We must try once more.                       */
        ;/************************************************************/
        push    pCharBuffer
        push    pFontDetails
        call    update_cache_charrect
        add     esp,8
        or      eax,eax                 ; caching succeeded?
ifndef BPP24
        jz error_exit                   ; NO,THIS MUST NOT HAPPEN!!!!!
else ; BPP24
        jnz short update_succeeded      ; yes, go writing
        mov     _CouldntCache, 1
        push    pCharBuffer             ; Faild off-screen cacheing,
        push    pFontDetails            ; fill only C*Array.
        call    update_cache_charrect
        add     esp,8                   ; no error checking.
endif ; BPP24

update_succeeded:
        ;/************************************************************/
        ;/* If we are caching and writing chars by row, we have to   */
        ;/* set up src/dest bitmaps and some XGA registers.          */
        ;/* Cache updating routine may call eddt_CacheCharacter, and */
        ;/* eddt_CacheCharacter may change condition of H/W          */
        ;/* registers.!!!                                            */
        ;/************************************************************/
ifndef _8514
        ;/************************************************************/
        ;/* Set up the destination bitmap (will be the screen)       */
        ;/************************************************************/
        waitshort                       ; wait on the hardware

        ;/************************************************************/
        ;/* set up the destination bitmap (as pixel map A)           */
        ;/************************************************************/
        mov     edx, AIxfer.pbmhDest    ; get pointer to destination
                                        ; bitmap header
        memregwrite     pi_map_index_A, SEL_PIX_MAP_A

        ;/************************************************************/
        ;/* physical address                                         */
        ;/************************************************************/
        mov     eax, [edx].phys_addr
        memregwrite     pi_map_base_ptr_A, eax  ; set physical address

        ;/************************************************************/
        ;/* width and height                                         */
        ;/************************************************************/
        mov     eax, dword ptr [edx].hw_width   ; get width and height
        .erre   hw_height eq (hw_width + 2)     ;  low word  - width
        memregwrite     pi_map_size_A, eax      ;  high word - height

        ;/************************************************************/
        ;/* format                                                   */
        ;/************************************************************/
        mov     al, byte ptr [edx].hw_format
        memregwrite     pi_map_format_A, al     ; set format
endif ; _8514

        ;/************************************************************/
        ;/* Do some set up here which only needs to be done once     */
        ;/* AVIO CGA text WILL overpaint                             */
        ;/************************************************************/
ifndef _8514
        memregwrite     fg_mix, 03h     ; set fg_mix register opaque
  ifndef  VARIABLE_BG_MIX
        memregwrite     bg_mix, 03h     ; set bg_mix register opaque
  endif ; VARIABLE_BG_MIX
        memregwrite     colour_comp_fun, COLCOMP_ALWAYS
else ; _8514

        WaitQIdle

  ifndef  VARIABLE_BG_MIX
        WaitQ   5
  else  ; VARIABLE_BG_MIX
        WaitQ   4
  endif ; VARIABLE_BG_MIX

        outwQ   FUNCTION_1,(FUNC_2OP_COL1+FUNC_S)   ; fg_mix

  ifndef  VARIABLE_BG_MIX
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)   ; bg_mix
  endif ; VARIABLE_BG_MIX

        outwQ   MODE,(MODE_2DECODE+MD_PS_COPY+MD_UP_FALSE)
        mov     ebx,pFontDetails
        ifdef   BPP24
        mov     eax,[ebx].pFocaFont
        mov     pFocafnt,eax
        endif
        mov     cx, word ptr [ebx].usCachedFontIndex
        mov     _SPad.fontnum, cl               ;+ Font plane to read
        mov     eax,1
        shl     eax,cl
        ifndef  S3
        rol     al,1                            ; Read only one cache
        endif
        outwQ   READ_ENABLE,ax                  ; located on a bit plane.
        outwQ   WRITE_ENABLE,WRITE_ALL_PLANES   ; Expand to all planes.

        mov     ecx,AIxfer.pCurrentClipRect
        mov     dx, [ecx].clip_y0
        swap    edx
        mov     dx, [ecx].clip_x0
        mov     mask_org_store, edx     ; save mask map origin

  ifdef   BPP24
        mov     ax, [ecx].clip_x1
        test    [_DDT],USE_24BPP
        jz      @f

        mov     dx,3
        mul     dx
        add     ax,2
@@:
        mov     RightClip,ax
        mov     ax, [ecx].clip_x0
        test    [_DDT],USE_24BPP
        jz      @f

        mov     dx,3
        mul     dx
@@:
        mov     LeftClip,ax


        setclip LeftClip,[ecx].clip_y0,RightClip,[ecx].clip_y1

        mov     ax, [ecx].clip_x0
        mov     LeftClip,ax
        mov     ax, [ecx].clip_x1
        mov     RightClip,ax
        mov     ax,[ecx].clip_y0
        mov     TopClip,ax
        mov     ax,[ecx].clip_y1
        mov     BottomClip,ax

  else
        setclip [ecx].clip_x0,[ecx].clip_y0,[ecx].clip_x1,[ecx].clip_y1
  endif

endif ; _8514

ifndef _8514
        ;/************************************************************/
        ;/* Now set up the source (pattern) bitmap (ie the character)*/
        ;/* These values will be the same throughout the operation.  */
        ;/************************************************************/
        memregwrite     pi_map_index_B, SEL_PIX_MAP_B

        ;/************************************************************/
        ;/* set format to MOTOROLA - the pixel maps are tweaked when */
        ;/* caching them in VRAM so that this will be the correct    */
        ;/* setting                                                  */
        ;/************************************************************/
        memregwrite     pi_map_format_B, ONE_BPP+MOTOROLA
                                                ; we use motorola format pi map
endif ; _8514

ifdef   AVIO_CGA_TEXT
        ;/************************************************************/
        ;/* And also set source_map dimension.                       */
        ;/* For performance reason, we need to draw CharRect without */
        ;/* Mask Map set. To do this, we have to set appropriate     */
        ;/* Dimension2 register. So we don't fix dim2 register to    */
        ;/* cell height here and set it later.                       */
        ;/************************************************************/
  ifndef _8514

        mov     edx,pAvioInfo
        movzx   ax,[edx].bCellWidth     ; WIDTH
        dec     ax                      ; make zero based
        memregwrite     dim1,ax         ; set to H/W register

  else ; _8514

        WaitQIdle
        WaitQ   1
        mov     edx,pAvioInfo
        movzx   ax,[edx].bCellWidth
    ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      @f
        mov     dx,3
        mul     dx
@@:
    endif
        dec     ax
        outwQ   LX,ax

  endif ; _8514
endif ; AVIO_CGA_TEXT

        ;/************************************************************/
        ;/* Invalidate the previous colour store                     */
        ;/* (nb. writes to both fg and bg)                           */
        ;/************************************************************/
        mov     ax, 0FFFFh                      ; bFGIndex holds
        mov     word ptr AIxfer.bFGIndex, ax    ; previous color setting.
        .ERRE   bBGIndex eq (bFGIndex + 1)      ; Invalidate it

        ;/************************************************************/
        ;/* Now we believe char image in this row of clipped rect    */
        ;/* are all cached. And CIAArray must be created for these   */
        ;/* chars. Write them with H/W.                              */
        ;/************************************************************/
        mov     indx,0                  ; reset index for CIAArray

wrt_first_char:
        ;/************************************************************/
        ;/* we are at the first column in a row. we have to          */
        ;/* determine type of this cell, SBCS/DBCSLeading            */
        ;/* /DBCSTrailing by referring CTArray.                      */
        ;/************************************************************/
        mov     edx,indx
        movzx   eax,CTArray[edx]
        or      eax,eax                 ; SBCS column?
        jz short ini_sbcs               ; yes
        cmp     eax,1                   ; DBCSLeading?
        je short ini_dl_cell            ; yes

ifdef   AVIO_CGA_TEXT
        jmp short ini_dt_cell           ; It's DBCSTrailing
endif ; AVIO_CGA_TEXT

ifdef   AVIO_MFI_TEXT
        cmp     eax,2                   ; DBCSTrailing?
        je short ini_dt_cell            ; yes
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
        cmp     eax,2                   ; DBCSTrailing?
        je short ini_dt_cell            ; yes
endif ; AVIO_DBCS_TEXT

ifdef   AVIO_EPOCH_MONO_TEXT
        jmp short ini_dt_cell           ; It's DBCSTrailing
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
        jmp short ini_dt_cell           ; It's DBCSTrailing
endif ; AVIO_EPOCH_COLOR_TEXT

ini_sbcs:
        ;/************************************************************/
        ;/* first column is SBCS.                                    */
        ;/************************************************************/
        mov     eax,pCharBuffer
if      CELL_SHIFT eq 1
        movzx   eax,word ptr [eax]      ; get SBCS cell value
else  ; CELL_SHIFT eq 1
        mov     eax,dword ptr [eax]     ; get SBCS cell value
endif ; CELL_SHIFT eq 1
        mov     sbcsCell,eax
        jmp     wrt_sbcs                ; go writing

ini_dl_cell:
        ;/************************************************************/
        ;/* first column is DBCSLeading.                             */
        ;/************************************************************/
        mov     eax,pCharBuffer
if      CELL_SHIFT eq 1
        movzx   edx,word ptr [eax]      ; DBCSLeading
        mov     dlCell,edx
        movzx   edx,word ptr [eax+2]    ; DBCSTrailing
        mov     dtCell,edx
else  ; CELL_SHIFT eq 1
        mov     edx,dword ptr [eax]     ; DBCSLeading
        mov     dlCell,edx
        mov     edx,dword ptr [eax+4]   ; DBCSTrailing
        mov     dtCell,edx
endif ; CELL_SHIFT eq 1
        jmp short wrt_dbcs              ; go writing

ini_dt_cell:
        ;/************************************************************/
        ;/* first column is DBCSTrailing                             */
        ;/************************************************************/
        mov     edx,pCharBuffer
if      CELL_SHIFT eq 1
        movzx   eax,word ptr [edx]      ; EAX = DBCSTrailing
else  ; CELL_SHIFT eq 1
        mov     eax,dword ptr [edx]     ; EAX = DBCSTrailing
endif ; CELL_SHIFT eq 1
        mov     dtCell,eax
        jmp dt_wrt_dbcs                 ; go writing

next_char:
        ;/************************************************************/
        ;/* Now write rest cells in a row until we exhaust them      */
        ;/************************************************************/
        mov     edx,indx
        movzx   eax,CTArray[edx]
        or      eax,eax                 ; SBCS column?
ifdef   AVIO_DBCS_TEXT
        jnz short dl_cell               ; yes
else ;  AVIO_DBCS_TEXT
  ifdef   AVIO_EPOCH_MONO_TEXT
        jz short sbcs                   ; yes
        jmp short dl_cell               ; DBCSLeading
  else ;  AVIO_EPOCH_MONO_TEXT
        jz short sbcs                   ; yes
        cmp     eax,1                   ; DBCSLeading?
        je short dl_cell                ; yes, it's DBCSLeading
  endif ; AVIO_EPOCH_MONO_TEXT
endif ; AVIO_DBCS_TEXT

sbcs:
        ;/************************************************************/
        ;/* this cell is SBCS                                        */
        ;/************************************************************/
        mov     eax,pCharBuffer
if      CELL_SHIFT eq 1
        movzx   eax,word ptr [eax]      ; cell value
else  ; CELL_SHIFT eq 1
        mov     eax,dword ptr [eax]     ; cell value
endif ; CELL_SHIFT eq 1
        mov     sbcsCell,eax            ; 
        jmp     wrt_sbcs                ; go writing

dl_cell:
        ;/************************************************************/
        ;/* this cell is DBCSLeading.                                */
        ;/************************************************************/
        mov     eax,pCharBuffer
if      CELL_SHIFT eq 1
        movzx   edx,word ptr [eax]      ; DBCSLeading cell
        mov     dlCell,edx
        movzx   edx,word ptr [eax+2]    ; DBCSTrailing cell
        mov     dtCell,edx
else  ; CELL_SHIFT eq 1
        mov     edx,dword ptr [eax]     ; DBCSLeading cell
        mov     dlCell,edx
        mov     edx,dword ptr [eax+4]   ; DBCSTrailing cell
        mov     dtCell,edx
endif ; CELL_SHIFT eq 1

wrt_dbcs:
        ;/************************************************************/
        ;/* Clear lastSbcsCell                                       */
        ;/************************************************************/
        sub     eax,eax
        dec     eax
        mov     lastSbcsCell,eax        ; lastSbcsCell = 0FFFFFFFFh

        ;/************************************************************/
        ;/* Now write DBCS character (first, DBCSLeading)            */
        ;/************************************************************/
        mov     eax,dlCell

ifdef   AVIO_EPOCH_MONO_TEXT

  ifdef   BPP24
        mov     ecx,sBlackStore         ; ECX = Black for BG Color
        mov     dCurrBG, ecx
  else  ; BPP24
        mov     cx,sBlackStore          ; CX = Black for BG Color
        swap    ecx                     ; ECX high word = BG Color
  endif ; BPP24

        mov     bCurrBG,0               ; store index for Black

endif ; AVIO_EPOCH_MONO_TEXT


ifdef   AVIO_EPOCH_MONO_TEXT
  ifdef   BPP24
        mov     ecx,sPhysColorStore     ; ECX = Phys Color for FG Color
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore,ecx          ; store Phys Color for grid
  else  ; BPP24
        mov     cx,sPhysColorStore      ; CX = Phys Color for FG Color
;@GRID  mov     sGridStore,cx           ; store Phys Color for grid
  endif ; BPP24

  ifdef   TMP
        mov     edx,_ulPhysColorIndex   ; index for physical color
  else  ; TMP
        mov     edx,_ulPhysColor        ; index for physical color
  endif ; TMP
        mov     bCurrFG,dl              ; store index for Phys Color
;@GRID  mov     bCurrGrid,dl            ; store index for Phys Color

        ;/************************************************************/
        ;/* At first, check visible or invisible                     */
        ;/************************************************************/
        mov     edx,eax                 ; get cell value
        and     edx,EPOCH_INVISIBLE
        cmp     edx,EPOCH_INVISIBLE     ; invisible combination?

  ifndef  TMP      ;@INVIS

        je dl_check_exhaust_row         ; yes, we don't have to write

  else ;  TMP      ;@INVIS

        jne     short @f

  ifdef   BPP24
        mov     ecx, dCurrBG
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore, ecx
  else  ; BPP24
        mov     edx, ecx
        swap    edx
;@GRID  mov     sGridStore, dx
  endif ; BPP24

        mov     dl,bCurrBG
        mov     bCurrFG,dl
        jmp     short dl_set_color

@@:
  endif ; TMP      ;@INVIS

        ;/************************************************************/
        ;/* Check Intensity                                          */
        ;/************************************************************/
        test    eax,EPOCH_INTENSITY     ; intensity required?
        jz short @f
  ifdef   BPP24
        mov     ecx,sWhiteStore         ; yes, so set White for FG
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore,ecx          ; store White for grid
  else  ; BPP24
        mov     cx,sWhiteStore          ; yes, so set White for FG
;@GRID  mov     sGridStore,cx           ; store White for grid
  endif ; BPP24
        mov     bCurrFG,0Fh             ; store index for White
;@GRID  mov     bCurrGrid,0Fh           ; store index for White
@@:
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,EPOCH_REV_VIDEO     ; reverse video required?
        jz short @f                     ; no, next attribute
  ifdef   BPP24
        mov     edx, dCurrFG
        xchg    edx, dCurrBG
        mov     dCurrFG, edx
  else  ; BPP24
        swap    ecx                     ; exchange FG & BG Color
  endif ; BPP24
        mov     dl,bCurrFG              ; DL = index for FG color
        xchg    dl,bCurrBG              ; exchange FG and BG index
        mov     bCurrFG,dl              ; store FG to param block
@@:
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
        ;/************************************************************/
        ;/* We have to change Epoch unique color specification to be */
        ;/* able to refer actual color index by using                */
        ;/* _AvioPhyLookup table.                                    */
        ;/************************************************************/
        sub     edx,edx                 ; to force BG color Black
        test    ah,EPOCH_NO_RED         ; red not required?
        jnz short @f                    ; not required
        or      dl,04h                  ; required so set to DL
@@:
        test    ah,EPOCH_NO_GREEN       ; green not required?
        jnz short @f                    ; not required
        or      dl,02h                  ; required so set to DL
@@:
        test    ah,EPOCH_NO_BLUE        ; blue  not required?
        jnz short @f                    ; not required
        or      dl,01h                  ; required so set to DL
@@:
        or      dl,bIntensityBit        ; set if intensity required.

        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,EPOCH_REV_VIDEO     ; reverse video required?
        jz short @f                     ; no, next attribute
        ror     dl,4                    ; yes, so reverse FG color and
@@:                                     ; BG color
endif ; AVIO_EPOCH_COLOR_TEXT
ifdef   AVIO_MFI_TEXT
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,MFI_REV_VIDEO       ; reverse video required?
        jz short @f                     ; no, next attribute
        ror     ah,4                    ; yes, so reverse FG color and
@@:                                     ; BG color
endif ; AVIO_MFI_TEXT
ifdef   AVIO_DBCS_TEXT
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,MFI_REV_VIDEO       ; reverse video required?
        jz short @f                     ; no, next attribute
        ror     ah,4                    ; yes, so reverse FG color and
@@:                                     ; BG color
endif ; AVIO_DBCS_TEXT

dl_set_color:               ;@INVIS
        ;/************************************************************/
        ;/* Set Color (AH holds color required)                      */
        ;/************************************************************/
ifdef   AVIO_EPOCH_COLOR_TEXT
        mov     eax, edx                ; ah <-- dl
        shl     eax, 8
endif ; AVIO_EPOCH_COLOR_TEXT

        ;/************************************************************/
        ;/* Is the foreground colour the same as it was last time?   */
        ;/************************************************************/
ifdef   AVIO_EPOCH_MONO_TEXT
        mov     dl,bCurrFG              ; get current FG index
else ;  AVIO_EPOCH_MONO_TEXT
        movzx   edx,ah                  ; EDX = color required
        and     dl,0Fh                  ; mask off BG color
endif ; AVIO_EPOCH_MONO_TEXT
        cmp     dl,AIxfer.bFGIndex      ; same as previous FG color?
        jz      short dl_same_fg1       ; yes

        ;/************************************************************/
        ;/* Foreground colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bFGIndex,dl      ; no, so save it

ifdef   AVIO_EPOCH_MONO_TEXT

  ifndef _8514

        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, cx   ; set to H/W register

  else ; _8514

        push    eax
        WaitQ   1
    ifdef   BPP24
        mov     eax, dCurrFG
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,cx                  ; only FG color
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24
        outwQ   COLOR_1,ax
        pop     eax

  endif ; _8514

else ;  AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Get the actual colour index to use and write it out      */
        ;/* The lookup table is dwords so edx*4                      */
        ;/************************************************************/
        shl     edx,2                           ; table is dwords so * 4
        add     edx, dword ptr _pAVIOColorXlate ; add the table start
  ifndef _8514

        mov     edx, [edx]                      ; get the color value
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register

  else ; _8514

        push    eax
        mov     ebx,[edx]
        WaitQ   1
        mov     eax,ebx
        outwQ   COLOR_1, ax
        pop     eax

  endif ; _8514
endif ; AVIO_EPOCH_MONO_TEXT

dl_same_fg1:
        ;/************************************************************/
        ;/* Is the background colour the same as it was last time?   */
        ;/************************************************************/
ifdef   AVIO_EPOCH_MONO_TEXT
        mov     dl,bCurrBG              ; get current BG color index
else ;  AVIO_EPOCH_MONO_TEXT
        movzx   edx, ah                 ; EDX = color required
        and     dl, 0F0h                ; mask off FG color
endif ; AVIO_EPOCH_MONO_TEXT

        cmp     dl, AIxfer.bBGIndex     ; same as previous BG color?
        jz      short dl_check_trans    ; yes

        ;/************************************************************/
        ;/* Background colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bBGIndex, dl     ; no, so save it

ifdef   AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Background colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bBGIndex, dl     ; no, so save it

  ifndef  BPP24
        swap    ecx                     ; restore actual BG color index
  endif ; BPP24

  ifndef _8514

        waitshort                       ; wait on the hardware
        memregwrite     bg_colour, cx   ; set to H/W register

  else ; _8514

        push    eax
        WaitQ   1
    ifdef   BPP24
        mov     eax,dCurrBG
        mov     _Shadow8514Regs.Color_0,eax
    else  ; BPP24
        mov     ax,cx
        mov     _Shadow8514Regs.Color_0,ax
    endif ; BPP24
        outwQ   COLOR_0,ax
        pop     eax
  endif ; _8514

  ifdef   BPP24
  else  ; BPP24
        swap    ecx                     ; put BG Color back to ECX high word
  endif ; BPP24

else ;  AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Get the actual colour index to use                       */
        ;/* Lookup table is dwords so edx/4 (edx was 16* the index)  */
        ;/************************************************************/
        shr     edx, 2                          ; divide by 4
        add     edx, dword ptr _pAVIOColorXlate ; add the table start
  ifndef _8514
        mov     edx, [edx]                      ; get the color value
        waitshort                       ; wait on the hardware
        memregwrite     bg_colour, dx   ; set to H/W register
  else ; _8514

        push    eax
        mov     ebx,[edx]
        WaitQ   1
        mov     eax, ebx
        outwQ   COLOR_0,ax
        pop     eax

  endif ; _8514
endif ; AVIO_EPOCH_MONO_TEXT

dl_check_trans:
ifdef AVIO_MFI_TEXT
        ;/************************************************************/
        ;/* Now check Transparent/Opaque                             */
        ;/************************************************************/
        test    eax,MFI_TRANSPARENT     ; bgTransparent required?
        jz short dl_set_opaque          ; no, so set opaque
  ifndef _8514
        waitshort
        memregwrite     bg_mix,05h      ; yes, so set bgTransparent
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_D)
  endif ; _8514
        jmp short dl_get_char_image_address

dl_set_opaque:
  ifndef _8514
        waitshort
        memregwrite     bg_mix,03h      ; set opaque
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)
  endif ; _8514
endif ; AVIO_MFI_TEX

ifdef   AVIO_DBCS_TEXT
        ;/************************************************************/
        ;/* Now check Transparent/Opaque                             */
        ;/************************************************************/
        test    eax,MFI_TRANSPARENT     ; bgTransparent required?
        jz short dl_set_opaque          ; no, so set opaque
  ifndef _8514
        waitshort
        memregwrite     bg_mix,05h      ; yes, so set bgTransparent
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_D)
  endif ; _8514
        jmp short dl_get_char_image_address
dl_set_opaque:
  ifndef _8514
        waitshort
        memregwrite     bg_mix,03h      ; set opaque
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)
  endif ; _8514
endif ; AVIO_DBCS_TEXT

dl_get_char_image_address:
        ;/************************************************************/
        ;/* Color handling ended. Now we get char image.             */
        ;/************************************************************/
        mov     eax,indx
        mov     eax,dword ptr CIAArray[eax*4]
                                        ; EAX = char image offset in
                                        ; cache

ifndef _8514
dl_set_base_addr:
        add     eax, _pCurCacheBasePhy  ; add cache start address
                                        ; (EAX holds char image
                                        ; address)

        ;/************************************************************/
        ;/* Set up base address for character                        */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     pi_map_base_ptr_B,eax   ; set char image addr in H/W register
else ; _8514
        mov     pVRAM,eax
endif ; _8514

        sub     dl,dl
        mov     bDLWritten,dl           ; indicate Char Image Addr already set

dl_do_blt:
ifndef _8514
        ;/************************************************************/
        ;/* Set up the bitmap dimensions for a character.            */
        ;/* Note that format is now padded, so the width must be     */
        ;/* whole bytes.                                             */
        ;/************************************************************/
        waitshort
        mov     ecx,pAvioInfo
        movzx   eax, [ecx].bCellWidth           ; WIDTH
        shl     ax,1                            ; because 2 cell width
        dec     ax
        or      ax, 7                           ; force byte width
        memregwrite     pi_map_width_B, ax      ; set it

        movzx   eax,[ecx].bCellHeight           ; HEIGHT
        dec     ax                              ; 
        memregwrite     pi_map_height_B, ax     ; set it
endif ; _8514

ifndef  AVIO_CGA_TEXT                           ; MFI, DBCS, EpCol
        ;/************************************************************/
        ;/* Set X dimension of blt.                                  */
        ;/************************************************************/
  ifndef _8514
        movzx   edx,[ecx].bCellWidth
        dec     dx                      ; H/W register requires
                                        ; width - 1
        memregwrite     dim1,dx         ; set to H/W register
  else ; _8514
        WaitQIdle
        WaitQ   1
        mov     edx,pAvioInfo
        movzx   ax,[edx].bCellWidth
    ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      @f
        mov     dx,3
        mul     dx
@@:
    endif
        dec     ax
        outwQ   LX,ax
  endif ; _8514
endif ; AVIO_CGA_TEXT

ifndef _8514
        ;/************************************************************/
        ;/* Set up start position                                    */
        ;/************************************************************/
        mov     edx,mask_org_store      ; load mask map origin
        waitshort                       ; wait on the hardware
        memregwrite     mask_org,edx    ; set mask map origin
endif ; _8514

        ;/************************************************************/
        ;/* And we have to set patt_map,dim2 and pixel_op registers  */
        ;/* according to current position.                           */
        ;/************************************************************/
        movzx   eax,bColCounter         ; get column counter
        cmp     al,AIxfer.bNumOfColumn  ; first column?
        je short dl_set_mask            ; yes
        dec     eax                     ; last column?
        jz short dl_set_mask            ; yes
        movzx   eax,bRowCounter         ; get row counter
        cmp     al,AIxfer.bNumOfRow     ; first row?
        je short dl_first_row           ; yes
        dec     eax                     ; last row?
        jz short dl_last_row            ; yes
        sub     eax,eax                 ; Y offset in source map is 0
        movzx   edx,AIxfer.usNextRowDim2 ; get dim2 (must be cell height)
        mov     ecx,AVIO_NoMaskCharBlt  ; get pixel op with mask
        jmp short dl_set_reg            ; disabled.

dl_set_mask:
        sub     eax,eax                 ; Y offset in source map is 0
        movzx   edx,AIxfer.usNextRowDim2 ; set dim2 (cell height)
        mov     ecx,AVIO_MaskCharBlt    ; get pixel op with mask
        jmp short dl_set_reg            ; enabled.

dl_first_row:
        movzx   eax,AIxfer.usFirstRowYAddr ; get Y offset in source map
        swap    eax                     ; shift Y to high word
        movzx   edx,AIxfer.usFirstRowDim2 ; get dim2
        mov     ecx,AVIO_NoMaskCharBlt  ; get pixel op with mask
        jmp short dl_set_reg            ; disabled.

dl_last_row:
        sub     eax,eax                 ; Y offset in source map is 0
        movzx   edx,AIxfer.usLastRowDim2 ; get dim2
        mov     ecx,AVIO_NoMaskCharBlt  ; get pixel op with mask

dl_set_reg:
ifndef _8514
        waitshort
        memregwrite patt_map,eax        ; set patt_map register
        push    ecx                     ; save pixel op
        mov     ecx,lCurrentPos
        swap    ecx
        swap    eax
        add     cx,ax
        swap    ecx
        memregwrite dest_map,ecx
        pop     ecx                     ; recover pixel op
        memregwrite dim2,dx             ; set dim2 register

        ;/************************************************************/
        ;/* Now do the DBCSLeading blt.                              */
        ;/************************************************************/
        memregwrite     pixel_op,ecx            ; do blt!!!
else ; _8514

        mov     PattMap,eax
        mov     ecx,lCurrentPos
        swap    ecx
        swap    eax
        add     cx,ax
        swap    ecx
        mov     DestMap,ecx
        mov     Dim2,dx

  ifdef   BPP24
        test    [_DDT], USE_24BPP
        jz      is_cached
        check_grey fGrey
        test    fGrey, 1
        jz      is_clipped
is_cached:
        cmp     _CouldntCache, 0
        jz      not_24bpp
is_clipped:
        calc_clip lCurrentPos, eax              ; on return, esi = new dest pos.
;;        mov     dx, Dim2
;;        calc_clip DestMap, eax                  ; on return, esi = new dest pos.

        cmp     eax, 1
        je      dl_blt_done                     ; totaly clipped.

        avio_mem_to_vram dlCell

        jmp     dl_blt_done

not_24bpp:
  endif ; BPP24

        avio_blt_from_vram

dl_blt_done:
endif ; _8514

ifdef   AVIO_HAS_U_SCORE
        ;/************************************************************/
        ;/* Now check underscore.                                    */
        ;/************************************************************/
        mov     eax,dlCell              ; get cell

  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_USCORE         ; underscore required?
  else  ; AVIO_EPOCH_MONO_TEXT
        test    eax,MFI_USCORE          ; underscore required?
  endif ; AVIO_EPOCH_MONO_TEXT
        jz short dl_no_uscore           ; no

        ;/************************************************************/
        ;/* The underscore is a solid line at the bottom of the cell */
        ;/************************************************************/
  ifndef _8514
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)
        swap    edx
        mov     ecx,pAvioInfo
        add     dl,[ecx].bCellHeight
        adc     dh,0
        dec     dx                      ; DX= Y bottom left of cell
        swap    edx

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to underscore               */
        ;/************************************************************/
                                        ; dim1 (width) is already set
        memregwrite     dim2,0          ; set height (actual 1 pel)

        ;/************************************************************/
        ;/* Do underscore writing                                    */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_usblt ; do line blt!!!
  else ; _8514

        push    dword ptr 1             ; height (one based)
        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellWidth
        push    eax                     ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        add     dl,[ecx].bCellHeight    ; add cell height
        adc     dh,0
        dec     dx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

        mov     eax,dlCell              ; Reload cell
  endif ; _8514
endif ; AVIO_HAS_U_SCORE

dl_no_uscore:
ifdef   AVIO_HAS_GRID                   ; DBCS. EpMono, EpCol
        ;/************************************************************/
        ;/* Check Horizontal Grid                                    */
        ;/************************************************************/
        mov     eax,dlCell              ; EpCol

  ifdef   AVIO_DBCS_TEXT
        test    eax,DBCS_HGRID4         ; horizontal grid required?
  endif ; AVIO_DBCS_TEXT
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_HGRID2         ; horizontal grid required?
  endif ; AVIO_EPOCH_MONO_TEXT
  ifdef   AVIO_EPOCH_COLOR_TEXT
        test    eax,DBCS_HGRID2         ; horizontal grid required?
  endif ; AVIO_EPOCH_COLOR_TEXT
        jz dl_no_hgrid                  ; no, next attribute
;;        jz short dl_no_hgrid            ; no, next attribute

        ;/************************************************************/
        ;/* Horizontal Grid required, so set the FG color White.     */
        ;/************************************************************/
        mov     dl,AIxfer.bFGIndex      ; get corrent FG color index
        cmp     dl,bCurrGrid            ; already set?
        je short dl_fg_white1           ; yes, don't have to set
        mov     dl,bCurrGrid
        mov     AIxfer.bFGIndex,dl      ; save as last FG color

  ifndef _8514

        mov     dx,sGridStore           ; no, need to set
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register

  else ; _8514

        WaitQ   1

    ifdef   BPP24
        mov     eax,sGridStore
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,sGridStore
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax

        mov     eax,dlCell              ; Reload cell
  endif ; _8514

dl_fg_white1:
  ifndef _8514
        ;/************************************************************/
        ;/* The horizontal grid is a solid line at the top of the    */
        ;/* cell                                                     */
        ;/************************************************************/
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to horizontal grid          */
        ;/************************************************************/
        waitshort                       ; dim1 is already set
        memregwrite     dim2,0          ; set height (actual 1 pel)

        ;/************************************************************/
        ;/* Do Horizontal Grid writing                               */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_hgblt ; do hgrid blt!!!
  else ; _8514

        push    dword ptr 1             ; height (one based)
        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellWidth
        push    eax                     ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

        mov     eax,dlCell              ; Reload cell
  endif ; _8514

dl_no_hgrid:
        ;/************************************************************/
        ;/* Check Vertical Grid                                      */
        ;/************************************************************/
  ifdef   AVIO_DBCS_TEXT
        test    eax,DBCS_VGRID4         ; vertical grid required?
  endif ; AVIO_DBCS_TEXT
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_VGRID2         ; vertical grid required?
  endif ; AVIO_EPOCH_MONO_TEXT
  ifdef   AVIO_EPOCH_COLOR_TEXT
        test    eax,DBCS_VGRID2         ; vertical grid required?
  endif ; AVIO_EPOCH_COLOR_TEXT
        jz dl_check_exhaust_row         ; no

        ;/************************************************************/
        ;/* Vertical Grid required, so set the FG color White.       */
        ;/************************************************************/
        mov     dl,AIxfer.bFGIndex      ; get corrent FG color index
        cmp     dl,bCurrGrid            ; already set?
        je short dl_fg_white2           ; yes, don't have to set
        mov     dl,bCurrGrid
        mov     AIxfer.bFGIndex,dl      ; save as last FG color

  ifndef _8514
        mov     dx,sGridStore           ; no, need to set
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514

        WaitQ   1

    ifdef   BPP24
        mov     eax,sGridStore
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,sGridStore
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax

  endif ; _8514

dl_fg_white2:
  ifndef _8514
        ;/************************************************************/
        ;/* The vertical grid is a solid line at the left edge of    */
        ;/* the cell                                                 */
        ;/************************************************************/
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to vertical grid            */
        ;/************************************************************/
        mov     ecx,pAvioInfo
        movzx   dx,[ecx].bCellHeight    ; get cell height
        dec     dl                      ; H/W register requires
                                        ; height - 1
        waitshort                       ; wait on the hardware
        memregwrite     dim1,0          ; set width  (actual 1 pel)
        memregwrite     dim2,dx         ; set height

        ;/************************************************************/
        ;/* Do Vertical Grid writing                                 */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_vgblt ; do vgrid blt!!!
  else ; _8514

        mov     ecx,pAvioInfo
        movzx   edx,[ecx].bCellHeight
        push    edx                     ; height (one based)
        push    dword ptr 1             ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

  endif ; _8514
endif ; AVIO_HAS_GRID

dl_check_exhaust_row:
        ;/************************************************************/
        ;/*  And moving on to the next position.. (DBCSTrailing)     */
        ;/*  Update the x position                                   */
        ;/************************************************************/
        dec     bColCounter             ; we wrote 1 column
                                        ; exhaust columns in this row?
        jz new_row                      ; yes, move to next row
                                        ; no
        mov     eax,pAvioInfo
        movzx   eax,[eax].bCellWidth    ; get cell width
        mov     edx,lCurrentPos
        add     dx,ax
        mov     lCurrentPos,edx         ; update current position
        inc     indx                    ; update index for CIAArray
        add     pCharBuffer,(CELL_SHIFT SHL 1) ; update pointer in char buffer (2/4)

dt_wrt_dbcs:
        ;/************************************************************/
        ;/* Clear lastSbcsCell                                       */
        ;/************************************************************/
        sub     eax,eax
        dec     eax
        mov     lastSbcsCell,eax        ; lastSbcsCell = 0FFFFFFFFh

        ;/************************************************************/
        ;/* Continue writing DBCS char (DBCSTrailing)                */
        ;/************************************************************/
        mov     eax,dtCell              ; EAX = DBCSTrailing cell

ifdef   AVIO_EPOCH_MONO_TEXT
  ifdef   BPP24
        mov     ecx,sBlackStore         ; ECX = Black for BG Color
        mov     dCurrBG, ecx
  else  ; BPP24
        mov     cx,sBlackStore          ; CX = Black for BG Color
        swap    ecx                     ; ECX high word = BG Color
  endif ; BPP24
        mov     bCurrBG,0               ; store index for Black

  ifdef   BPP24
        mov     ecx,sPhysColorStore     ; ECX = Phys Color for FG Color
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore,ecx          ; store Phys Color for grid
  else  ; BPP24
        mov     cx,sPhysColorStore      ; CX = Phys Color for FG Color
;@GRID  mov     sGridStore,cx           ; store Phys Color for grid
  endif ; BPP24

  ifdef   TMP
        mov     edx,_ulPhysColorIndex   ; index for physical color
  else  ; TMP
        mov     edx,_ulPhysColor        ; index for physical color
  endif ; TMP
        mov     bCurrFG,dl              ; store index for Phys Color
;@GRID  mov     bCurrGrid,dl            ; store index for Phys Color

        ;/************************************************************/
        ;/* At first, check visible or invisible                     */
        ;/************************************************************/
        mov     edx,eax                 ; get cell value
        and     edx,EPOCH_INVISIBLE
        cmp     edx,EPOCH_INVISIBLE     ; invisible combination?

  ifndef  TMP      ;@INVIS

        je dbcs_check_exhaust_row       ; yes, we don't have to write

  else ;  TMP      ;@INVIS

        jne     short @f

  ifdef   BPP24
        mov     ecx, dCurrBG
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore, ecx
  else  ; BPP24
        mov     edx, ecx
        swap    edx
;@GRID  mov     sGridStore, dx
  endif ; BPP24

        mov     dl,bCurrBG
        mov     bCurrFG,dl
        jmp     short dt_set_color

@@:
  endif ; TMP      ;@INVIS

        ;/************************************************************/
        ;/* Check Intensity                                          */
        ;/************************************************************/
        test    eax,EPOCH_INTENSITY     ; intensity required?
        jz short @f
  ifdef   BPP24
        mov     ecx,sWhiteStore         ; yes, so set White for FG
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore,ecx          ; store White for grid
  else  ; BPP24
        mov     cx,sWhiteStore          ; yes, so set White for FG
;@GRID  mov     sGridStore,cx           ; store White for grid
  endif ; BPP24
        mov     bCurrFG,0Fh             ; store index for White
;@GRID  mov     bCurrGrid,0Fh           ; store index for White
@@:
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,EPOCH_REV_VIDEO     ; reverse video required?
        jz short @f                     ; no, next attribute
  ifdef   BPP24
        mov     edx, dCurrFG
        xchg    edx, dCurrBG
        mov     dCurrFG, edx
  else  ; BPP24
        swap    ecx                     ; exchange FG & BG Color
  endif ; BPP24
        mov     dl,bCurrFG              ; BL = index for FG color
        xchg    dl,bCurrBG              ; exchange FG and BG index
        mov     bCurrFG,dl              ; store FG to param block
@@:
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
        ;/************************************************************/
        ;/* We have to change Epoch unique color specification to be */
        ;/* able to refer actual color index by using                */
        ;/* _AvioPhyLookup table.                                    */
        ;/************************************************************/
        sub     edx,edx
        test    ah,EPOCH_NO_RED         ; red not required?
        jnz short @f                    ; not required
        or      dl,04h                  ; required so set to DL
@@:
        test    ah,EPOCH_NO_GREEN       ; green not required?
        jnz short @f                    ; not required
        or      dl,02h                  ; required so set to DL
@@:
        test    ah,EPOCH_NO_BLUE        ; blue  not required?
        jnz short @f                    ; not required
        or      dl,01h                  ; required so set to DL
@@:
        or      dl,bIntensityBit        ; set if intensity required.

        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,EPOCH_REV_VIDEO     ; reverse video required?
        jz short @f                     ; no, next attribute
        ror     dl,4                    ; yes, so reverse FG color and BG color
@@:
endif ; AVIO_EPOCH_COLOR_TEXT

ifdef   AVIO_MFI_TEXT
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,MFI_REV_VIDEO       ; reverse video required?
        jz short @f                     ; no, next attribute
        ror     ah,4                    ; yes, so reverse FG color and BG color
@@:
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,MFI_REV_VIDEO       ; reverse video required?
        jz short @f                     ; no, next attribute
        ror     ah,4                    ; yes, so reverse FG color and BG color
@@:
endif ; AVIO_DBCS_TEXT

dt_set_color:               ;@INVIS
        ;/************************************************************/
        ;/* Set Color (AH holds color required)                      */
        ;/************************************************************/
ifdef   AVIO_EPOCH_COLOR_TEXT
        mov     eax, edx                ; ah <-- dl
        shl     eax, 8
endif ; AVIO_EPOCH_COLOR_TEXT

        ;/************************************************************/
        ;/* Is the foreground colour the same as it was last time?   */
        ;/************************************************************/
ifdef   AVIO_EPOCH_MONO_TEXT
        mov     dl,bCurrFG              ; get current FG index
else  ; AVIO_EPOCH_MONO_TEXT
        movzx   edx,ah                  ; EDX = color required
        and     dl,0Fh                  ; mask off BG color
endif ; AVIO_EPOCH_MONO_TEXT
        cmp     dl,AIxfer.bFGIndex      ; same as previous FG color?
        jz      short dt_same_fg1       ; yes

        ;/************************************************************/
        ;/* Foreground colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bFGIndex,dl      ; no, so save it

ifdef   AVIO_EPOCH_MONO_TEXT
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, cx   ; set to H/W register
  else ; _8514

        push    eax
        WaitQ   1
    ifdef   BPP24
        mov     eax, dCurrFG
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,cx
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax
        pop     eax

  endif ; _8514

else  ; AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Get the actual colour index to use and write it out      */
        ;/* The lookup table is dwords so edx*4                      */
        ;/************************************************************/
        shl     edx,2                           ; table is dwords so * 4
        add     edx, dword ptr _pAVIOColorXlate ; add the table start
  ifndef _8514
        mov     edx, [edx]              ; get the color value
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514
        push    eax
        mov     ebx, [edx]
        WaitQ   1
        mov     eax, ebx
        outwQ   COLOR_1,ax
        pop     eax
  endif ; _8514
endif ; AVIO_EPOCH_MONO_TEXT

dt_same_fg1:
        ;/************************************************************/
        ;/* Is the background colour the same as it was last time?   */
        ;/************************************************************/
ifdef   AVIO_EPOCH_MONO_TEXT
        mov     dl,bCurrBG              ; get current BG color index
else  ; AVIO_EPOCH_MONO_TEXT
        movzx   edx, ah                 ; EDX = color required
        and     dl, 0F0h                ; mask off FG color
endif; AVIO_EPOCH_MONO_TEXT
        cmp     dl, AIxfer.bBGIndex     ; same as previous BG color?
        jz      short dt_check_trans    ; yes

        ;/************************************************************/
        ;/* Background colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bBGIndex, dl     ; no, so save it

ifdef   AVIO_EPOCH_MONO_TEXT

  ifndef  BPP24
        swap    ecx                     ; get BG Color
  endif ; BPP24

  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_colour, cx   ; set to H/W register
  else ; _8514

        push    eax
        WaitQ   1

    ifdef   BPP24
        mov     eax, dCurrBG
        mov     _Shadow8514Regs.Color_0,eax
    else  ; BPP24
        mov     ax,cx
        mov     _Shadow8514Regs.Color_0,ax
    endif ; BPP24

        outwQ   COLOR_0,ax
        pop     eax

  endif ; _8514

  ifdef   BPP24
  else  ; BPP24
        swap    ecx                     ; put BG Color back to ECX high word
  endif ; BPP24

else  ; AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Get the actual colour index to use                       */
        ;/* Lookup table is dwords so edx/4 (edx was 16* the index)  */
        ;/************************************************************/
        shr     edx, 2                          ; divide by 4
        add     edx, dword ptr _pAVIOColorXlate ; add the table start

  ifndef _8514
        mov     edx, [edx]                      ; get the color value
        waitshort                       ; wait on the hardware
        memregwrite     bg_colour, dx   ; set to H/W register
  else ; _8514

        push    eax
        mov     ebx, [edx]
        WaitQ   1
        mov     eax, ebx
        outwQ   COLOR_0, ax
        pop     eax

  endif ; _8514

endif; AVIO_EPOCH_MONO_TEXT

dt_check_trans:
ifdef   AVIO_MFI_TEXT
        ;/************************************************************/
        ;/* Now check Transparent/Opaque                             */
        ;/************************************************************/
        test    eax,MFI_TRANSPARENT     ; bgTransparent required?
        jz short dt_set_opaque_4        ; no, so set opaque
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,05h      ; yes, so set bgTransparent
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_D)
  endif ; _8514
        jmp short dt_check_wrote_dl

dt_set_opaque_4:
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,03h      ; set opaque
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)
  endif ; _8514
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
        ;/************************************************************/
        ;/* Now check Transparent/Opaque                             */
        ;/************************************************************/
        test    eax,MFI_TRANSPARENT     ; bgTransparent required?
        jz short dt_set_opaque_4        ; no, so set opaque

  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,05h      ; yes, so set bgTransparent
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_D)
  endif ; _8514
        jmp short dt_check_wrote_dl

dt_set_opaque_4:
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,03h      ; set opaque
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)
  endif ; _8514
endif ; AVIO_DBCS_TEXT

dt_check_wrote_dl:
        ;/************************************************************/
        ;/* Check we wrote DBCSLeading.                              */
        ;/************************************************************/
        mov     al,bDLWritten           ; get flag
        or      al,al                   ; wrote DBCSLeading?
        jz short dt_do_blt              ; yes, so char image address is
                                        ; already set
        ;/************************************************************/
        ;/* We didn't write DBCSLeading. need to set base pointer.   */
        ;/************************************************************/
        mov     eax,indx
        mov     eax,dword ptr CIAArray[eax*4]
                                        ; EAX = char image offset in
                                        ; cache

ifndef _8514
dt_set_base_addr:
        add     eax, _pCurCacheBasePhy  ; add cache start address
                                        ; (EAX holds char image
                                        ; address)

        ;/************************************************************/
        ;/* Set up base address for character                        */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     pi_map_base_ptr_B,eax   ; set char image addr
                                                ; in H/W register
else ; _8514
        mov     pVRAM,eax
endif ; _8514

ifndef _8514
        ;/************************************************************/
        ;/* Set up the bitmap dimensions for a character.            */
        ;/* Note that format is now padded, so the width must be     */
        ;/* whole bytes.                                             */
        ;/************************************************************/
        waitshort
        mov     ecx,pAvioInfo
        movzx   eax, [ecx].bCellWidth           ; WIDTH
        shl     ax,1                            ; because 2 cell width
        dec     ax
        or      ax, 7                           ; force byte width
        memregwrite     pi_map_width_B, ax      ; set it

        movzx   eax,[ecx].bCellHeight           ; HEIGHT
        dec     ax
        memregwrite     pi_map_height_B, ax     ; set it

endif ; _8514

dt_do_blt:
        ;/************************************************************/
        ;/* Set up start position                                    */
        ;/************************************************************/
ifndef _8514
        mov     edx,mask_org_store      ; load mask map origin
        waitshort                       ; wait on the hardware
        memregwrite     mask_org,edx    ; set mask map origin

                                        ; by reaching here, pi_map_base
                                        ; ptr_B    has been already set
                                        ; to desired char image address
                                        ; in cache.
endif ; _8514

ifndef  AVIO_CGA_TEXT                           ; MFI, DBCS, EpCol
        ;/************************************************************/
        ;/* Set X dimension of blt.                                  */
        ;/************************************************************/
  ifndef _8514
        mov     ecx,pAvioInfo           ; WIDTH
        movzx   edx,[ecx].bCellWidth
        dec     dx                      ; zero based
        memregwrite     dim1,dx         ; set to H/W register
  else ; _8514

        WaitQIdle
        WaitQ   1
        mov     edx,pAvioInfo
        movzx   ax,[edx].bCellWidth
    ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      short @f
        mov     dx,3
        mul     dx
@@:
    endif
        dec     ax
        outwQ   LX,ax
  endif ; _8514

endif ; AVIO_CGA_TEXT

        ;/************************************************************/
        ;/* And we have to set patt_map,dim2 and pixel_op registers  */
        ;/* according to current position.                           */
        ;/************************************************************/
        mov     eax,pAvioInfo
        movzx   eax,[eax].bCellWidth    ; get cell width
        movzx   edx,bColCounter         ; get column counter
        cmp     dl,AIxfer.bNumOfColumn  ; first column?
        je short dt_set_mask            ; yes
        dec     edx                     ; last column?
        jz short dt_set_mask            ; yes
        movzx   edx,bRowCounter         ; get row counter
        cmp     dl,AIxfer.bNumOfRow     ; first row?
        je short dt_first_row           ; yes
        dec     edx                     ; last row?
        jz short dt_last_row            ; yes
                                        ; Y offset in source map is 0
                                        ; so position in source is
                                        ; already in EAX
        movzx   edx,AIxfer.usNextRowDim2 ; get dim2 (must be cell height)
        mov     ecx,AVIO_NoMaskCharBlt  ; get pixel op with mask
        jmp short dt_set_reg            ; disabled.

dt_set_mask:
                                        ; Y offset in source map is 0
                                        ; so position in source is
                                        ; already in EAX
        movzx   edx,AIxfer.usNextRowDim2 ; get dim2 (cell height)
        mov     ecx,AVIO_MaskCharBlt    ; get pixel op with mask
        jmp short dt_set_reg            ; enabled.

dt_first_row:
        movzx   edx,AIxfer.usFirstRowYAddr ; get Y offset in source map
        swap    edx                     ; shift Y to high word
        or      eax,edx
        movzx   edx,AIxfer.usFirstRowDim2 ; get dim2
        mov     ecx,AVIO_NoMaskCharBlt  ; get pixel op with mask
        jmp short dt_set_reg            ; disabled.

dt_last_row:
                                        ; Y offset in source map is 0
                                        ; so position in source map is
                                        ; already in EAX
        movzx   edx,AIxfer.usLastRowDim2 ; get dim2
        mov     ecx,AVIO_NoMaskCharBlt  ; get pixel op with mask

dt_set_reg:
ifndef _8514
        waitshort
        memregwrite patt_map,eax        ; set patt_map register
        push    ecx                     ; save pixel op
        mov     ecx,lCurrentPos
        swap    ecx
        swap    eax
        add     cx,ax
        swap    ecx
        memregwrite dest_map,ecx
        pop     ecx                     ; recover pixel op
        memregwrite dim2,dx             ; set dim2 register

        ;/************************************************************/
        ;/* Now do the DBCSTrailing blt.                             */
        ;/************************************************************/
        memregwrite     pixel_op,ecx            ; do blt!!!

else ; _8514

        mov     PattMap,eax
        mov     ecx,lCurrentPos
        swap    ecx
        swap    eax
        add     cx,ax
        swap    ecx
        mov     DestMap,ecx
        mov     Dim2,dx

  ifdef   BPP24
        test    [_DDT], USE_24BPP
        jz      is_cached2
        check_grey fGrey
        test    fGrey, 1
        jz      is_clipped2
is_cached2:
        cmp     _CouldntCache, 0
        jz      not_24bpp2
is_clipped2:
        calc_clip lCurrentPos, eax              ; on return, esi = new dest pos.
;;        mov     dx, Dim2
;;        calc_clip DestMap, eax                  ; on return, esi = new dest pos.

        cmp     eax, 1
        je      dt_blt_done                     ; totaly clipped.

        avio_mem_to_vram dtCell

        jmp     dt_blt_done

not_24bpp2:
  endif ; BPP24

        avio_blt_from_vram

dt_blt_done:
endif ; _8514

        mov     al,0FFh
        mov     bDLWritten,al           ; reset flag

ifdef   AVIO_HAS_U_SCORE
        ;/************************************************************/
        ;/* Now check underscore.                                    */
        ;/************************************************************/
        mov     eax,dtCell

  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_USCORE         ; underscore required?
  else  ; AVIO_EPOCH_MONO_TEXT
        test    eax,MFI_USCORE          ; underscore required?
  endif ; AVIO_EPOCH_MONO_TEXT
  ifndef _8514
        jz short dt_no_uscore           ; no
  else ; _8514
        jz dt_no_uscore                 ; no
  endif ; _8514

        ;/************************************************************/
        ;/* The underscore is a solid line at the bottom of the cell.*/
        ;/************************************************************/
  ifndef _8514
        mov     edx,lCurrentPos         ; re-load position

        swap    edx
        mov     ecx,pAvioInfo
        add     dl,[ecx].bCellHeight
        adc     dh,0
        dec     dx                      ; DX= Y bottom left of cell
        swap    edx

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to underscore               */
        ;/************************************************************/
                                        ; dim1 (width) is already set
        memregwrite     dim2,0          ; set height (actual 1 pel)

        ;/************************************************************/
        ;/* Do underscore writing                                    */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_usblt ; do line blt!!!
  else ; _8514

        push    dword ptr 1             ; height (one based)
        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellWidth
        push    eax                     ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        add     dl,[ecx].bCellHeight    ; add cell height
        adc     dh,0
        dec     dx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

;;;        mov     eax,dtCell              ; Reload cell
  endif ; _8514

endif ; AVIO_HAS_U_SCORE

dt_no_uscore:
ifdef   AVIO_HAS_GRID                   ; DBCS, EpCol

        mov     eax,dtCell              ; Reload cell
        ;/************************************************************/
        ;/* Check Horizontal Grid                                    */
        ;/************************************************************/
  ifdef   AVIO_DBCS_TEXT
        test    eax,DBCS_HGRID4         ; horizontal grid required?
  endif ; AVIO_DBCS_TEXT
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_HGRID2         ; horizontal grid required?
  endif ; AVIO_EPOCH_MONO_TEXT
  ifdef   AVIO_EPOCH_COLOR_TEXT
        test    eax,DBCS_HGRID2         ; horizontal grid required?
  endif ; AVIO_EPOCH_COLOR_TEXT
        jz dt_no_hgrid                  ; no, next attribute

        ;/************************************************************/
        ;/* Horizontal Grid required, so set the FG color White.     */
        ;/************************************************************/
        mov     dl,AIxfer.bFGIndex      ; get corrent FG color index

        cmp     dl,bCurrGrid            ; already set to White?
        je short dt_fg_white1           ; yes, don't have to set
        mov     dl,bCurrGrid
        mov     AIxfer.bFGIndex,dl      ; save as last FG color

  ifndef _8514
        mov     dx,sGridStore           ; no, need to set
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514

        WaitQ   1

    ifdef   BPP24
        mov     eax,sGridStore
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,sGridStore
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax

        mov     eax,dtCell              ; Reload cell
  endif ; _8514

dt_fg_white1:
  ifndef _8514
        ;/************************************************************/
        ;/* The horizontal grid is a solid line at the top edge of   */
        ;/* the cell                                                 */
        ;/************************************************************/
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to horizontal grid          */
        ;/************************************************************/
        waitshort                       ; dim1 is already set
        memregwrite     dim2,0          ; set height (actual 1 pel)

        ;/************************************************************/
        ;/* Do Horizontal Grid writing                               */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_hgblt ; do hgrid blt!!!
  else ; _8514

        push    dword ptr 1             ; height (one based)
        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellWidth
        push    eax                     ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

        mov     eax,dtCell              ; Reload cell
  endif ; _8514

dt_no_hgrid:
        ;/************************************************************/
        ;/* Check Vertical Grid                                      */
        ;/************************************************************/
  ifdef   AVIO_DBCS_TEXT
        test    eax,DBCS_VGRID4         ; vertical grid required?
  endif ; AVIO_DBCS_TEXT
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_VGRID2         ; vertical grid required?
  endif ; AVIO_EPOCH_MONO_TEXT
  ifdef   AVIO_EPOCH_COLOR_TEXT
        test    eax,DBCS_VGRID2         ; vertical grid required?
  endif ; AVIO_EPOCH_COLOR_TEXT
        jz dbcs_check_exhaust_row       ; no

        ;/************************************************************/
        ;/* Vertical Grid required, so set the FG color White.       */
        ;/************************************************************/
        mov     dl,AIxfer.bFGIndex      ; get corrent FG color index
        cmp     dl,bCurrGrid            ; already set to White?
        je short dt_fg_white2           ; yes, don't have to set
        mov     dl,bCurrGrid
        mov     AIxfer.bFGIndex,dl      ; save as last FG color
  ifndef _8514
        mov     dx,sGridStore           ; no, need to set
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514

        WaitQ   1

    ifdef   BPP24
        mov     eax,sGridStore
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,sGridStore
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1,ax

        mov     eax,dtCell              ; Reload cell

  endif ; _8514

dt_fg_white2:
  ifndef _8514
        ;/************************************************************/
        ;/* The vertical grid is a solid line at the left edge of    */
        ;/* the cell                                                 */
        ;/************************************************************/
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to vertical grid            */
        ;/************************************************************/
        mov     ecx,pAvioInfo
        movzx   dx,[ecx].bCellHeight    ; get cell height
        dec     dx                      ; H/W register requires
                                        ; height - 1
                                        ; wait on the hardware
        memregwrite     dim1,0          ; set width  (actual 1 pel)
        memregwrite     dim2,dx         ; set height

        ;/************************************************************/
        ;/* Do Vertical Grid writing                                 */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_vgblt ; do vgrid blt!!!
  else ; _8514

        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellHeight
        push    eax                     ; height (one based)
        push    dword ptr 1             ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

  endif ; _8514
endif ; AVIO_DBCS_TEXT

;;;        mov     al,0FFh
;;;        mov     bDLWritten,al           ; reset flag

dbcs_check_exhaust_row:
        ;/************************************************************/
        ;/*  And moving on to the next position..                    */
        ;/*  Update the x position.                                  */
        ;/************************************************************/
        dec     bColCounter             ; we wrote 1 column
                                        ; exhaust columns in this row?
        jz      new_row                 ; yes, move to next row
                                        ; no
        mov     eax,pAvioInfo
        movzx   eax,[eax].bCellWidth    ; get cell width
        mov     edx,lCurrentPos
        add     dx,ax
        mov     lCurrentPos,edx         ; update current position
        inc     indx                    ; update index for CIAArray
        add     pCharBuffer,(CELL_SHIFT SHL 1) ; update pointer in char buffer (2/4)
        jmp     next_char               ; handle rest chars in this row

wrt_sbcs:
        ;/************************************************************/
        ;/* Now write SBCS character                                 */
        ;/************************************************************/
        mov     eax,sbcsCell

ifdef   AVIO_EPOCH_MONO_TEXT
  ifdef   BPP24
        mov     ecx,sBlackStore         ; ECX = Black for BG Color
        mov     dCurrBG, ecx
  else  ; BPP24
        mov     cx,sBlackStore          ; CX = Black for BG Color
        swap    ecx                     ; ECX high word - BG Color
  endif ; BPP24
        mov     bCurrBG,0               ; store index for Black

  ifdef   BPP24
        mov     ecx,sPhysColorStore     ; ECX = Phys Color for FG Color
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore,ecx          ; store Phys Color for grid
  else  ; BPP24
        mov     cx,sPhysColorStore      ; CX = Phys Color for FG Color
;@GRID  mov     sGridStore,cx           ; store Phys Color for grid
  endif ; BPP24

  ifdef   TMP
        mov     edx,_ulPhysColorIndex   ; index for physical color
  else  ; TMP
        mov     edx,_ulPhysColor        ; index for physical color
  endif ; TMP
        mov     bCurrFG,dl              ; store index for Phys Color
;@GRID  mov     bCurrGrid,dl            ; store index for Phys Color

        ;/************************************************************/
        ;/* At first, check visible or invisible                     */
        ;/************************************************************/
        mov     edx,eax                 ; get cell value
        and     edx,EPOCH_INVISIBLE
        cmp     edx,EPOCH_INVISIBLE     ; invisible combination?

  ifndef  TMP      ;@INVIS

        jne short @f                    ; no, continue writing
        mov     bDupCount,1             ; we checked 1 cell
        jmp sbcs_check_exhaust_row      ; go checking exhaust row immediately

  else ;  TMP      ;@INVIS

        jne     short @f

    ifdef   BPP24
        mov     ecx, dCurrBG
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore, ecx
    else  ; BPP24
        mov     edx, ecx
        swap    edx
;@GRID  mov     sGridStore, dx
    endif ; BPP24

        mov     dl,bCurrBG
        mov     bCurrFG,dl

        mov     lastSbcsCell,eax        ; keep this sbcs cell

        jmp     short sbcs_normal_video

  endif ; TMP      ;@INVIS

endif ; AVIO_EPOCH_MONO_TEXT

        cmp     eax,lastSbcsCell        ; same char we wrote just
                                        ; before?
ifdef   AVIO_MFI_TEXT
        jne short @f                    ; no
        test    eax,00800000h           ; last cell has No underscore?
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
        jne short @f                    ; no
        test    eax,008C0000h           ; last cell has No underscore &
                                        ; No grids?
endif ; AVIO_DBCS_TEXT

ifdef   AVIO_EPOCH_MONO_TEXT
        jne short @f                    ; no
        test    eax,00007000h           ; last cell has No uscore & grid?
        jz sbcs_same_char_blt           ; No attr , so H/W condition is
                                        ; not changed, we can skip some setting.
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
        jne short @f                    ; no
        test    eax,00003000h           ; last cell has No grids?
endif ; AVIO_EPOCH_COLOR_TEXT

        je sbcs_same_char_blt           ; yes, so we can skip some
                                        ; checking
ifndef  AVIO_CGA_TEXT                   ; MFI, DBCS, EpMono, EpCol
@@:
endif ; AVIO_CGA_TEXT

        mov     lastSbcsCell,eax        ; keep this sbcs cell

ifdef   AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Check Intensity                                          */
        ;/************************************************************/
        test    eax,EPOCH_INTENSITY     ; intensity required?
        jz short @f
  ifdef   BPP24
        mov     ecx,sWhiteStore         ; yes, so set White for FG
        mov     dCurrFG, ecx
;@GRID  mov     sGridStore,ecx          ; store White for grid
  else  ; BPP24
        mov     cx,sWhiteStore          ; yes, so set White for FG
;@GRID  mov     sGridStore,cx           ; store white for grid
  endif ; BPP24
        mov     bCurrFG,0Fh             ; store index for White
;@GRID  mov     bCurrGrid,0Fh           ; store index white for grid
@@:
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,EPOCH_REV_VIDEO     ; reverse video required?
        jz short @f

  ifdef   BPP24
        mov     edx, dCurrFG
        xchg    edx, dCurrBG
        mov     dCurrFG, edx
  else  ; BPP24
        swap    ecx                     ; exchange FG & BG Color
  endif ; BPP24
        mov     dl,bCurrFG              ; DL = index for FG color
        xchg    dl,bCurrBG              ; exchange FG and BG index
        mov     bCurrFG,dl              ; store FG to param block
@@:
endif ; AVIO_EPOCH_MONO_TEXT

ifdef   AVIO_EPOCH_COLOR_TEXT
        ;/************************************************************/
        ;/* We have to change Epoch unique color specification to be */
        ;/* able to refer actual color index by using                */
        ;/* _AvioPhyLookup table.                                    */
        ;/************************************************************/
        sub     edx,edx                 ; 
        test    ah,EPOCH_NO_RED         ; red not required?
        jnz short @f                    ; not required
        or      dl,04h                  ; required so set to DL
@@:
        test    ah,EPOCH_NO_GREEN       ; green not required?
        jnz short @f                    ; not required
        or      dl,02h                  ; required so set to DL
@@:
        test    ah,EPOCH_NO_BLUE        ; blue  not required?
        jnz short @f                    ; not required
        or      dl,01h                  ; required so set to DL
@@:
        or      dl,bIntensityBit        ; set if intensity required.

        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,EPOCH_REV_VIDEO     ; reverse video required?
        jz short sbcs_normal_video      ; no, next attribute
        ror     dl,4                    ; yes, so reverse FG color and
                                        ; BG color
endif ; AVIO_EPOCH_COLOR_TEXT

ifdef   AVIO_MFI_TEXT
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,MFI_REV_VIDEO       ; reverse video required?
        jz short sbcs_normal_video      ; no, next attribute
        ror     ah,4                    ; yes, so reverse FG color and
                                        ; BG color
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
        ;/************************************************************/
        ;/* Check Reverse Video                                      */
        ;/************************************************************/
        test    eax,MFI_REV_VIDEO       ; reverse video required?
        jz short sbcs_normal_video      ; no, next attribute
        ror     ah,4                    ; yes, so reverse FG color and
                                        ; BG color
endif ; AVIO_DBCS_TEXT

sbcs_normal_video:
        ;/************************************************************/
        ;/* Set Color (AH holds color required)                      */
        ;/************************************************************/
ifdef   AVIO_EPOCH_COLOR_TEXT
        mov     eax, edx                ; ah <-- dl
        shl     eax, 8
endif ; AVIO_EPOCH_COLOR_TEXT

        ;/************************************************************/
        ;/* Is the foreground colour the same as it was last time?   */
        ;/************************************************************/
ifdef   AVIO_EPOCH_MONO_TEXT
        mov     dl,bCurrFG              ; get current FG index
        cmp     dl,AIxfer.bFGIndex      ; same as previous FG color?
        jz      short sbcs_same_fg1     ; yes
else  ; AVIO_EPOCH_MONO_TEXT
        movzx   edx,ah                  ; EDX = color required
        and     dl,0Fh                  ; mask off BG color
        cmp     dl,AIxfer.bFGIndex      ; same as previous FG color?
        jz      short sbcs_same_fg1     ; yes
endif ; AVIO_EPOCH_MONO_TEXT

        ;/************************************************************/
        ;/* Foreground colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bFGIndex,dl      ; no, so save it

ifdef   AVIO_EPOCH_MONO_TEXT

  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, cx   ; set to H/W register
  else ; _8514

        push    eax
        WaitQ   1

    ifdef   BPP24
        mov     eax, dCurrFG
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,cx
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax
        pop     eax

  endif ; _8514

else  ; AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Get the actual colour index to use and write it out      */
        ;/* The lookup table is dwords so edx*4                      */
        ;/************************************************************/
        shl     edx,2                           ; table is dwords so * 4
        add     edx, dword ptr _pAVIOColorXlate ; add the table start
  ifndef _8514
        mov     edx, [edx]                      ; get the color value
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514
        push    eax
        mov     ebx,[edx]
        WaitQ   1
        mov     eax, ebx
        outwQ   COLOR_1, ax
        pop     eax
  endif ; _8514
endif ; AVIO_EPOCH_MONO_TEXT

sbcs_same_fg1:
        ;/************************************************************/
        ;/* Is the background colour the same as it was last time?   */
        ;/************************************************************/
ifdef   AVIO_EPOCH_MONO_TEXT
        mov     dl,bCurrBG              ; get current BG color index
        cmp     dl, AIxfer.bBGIndex     ; same as previous BG color?
        jz      short sbcs_check_trans  ; yes
else  ; AVIO_EPOCH_MONO_TEXT
        movzx   edx, ah                 ; EDX = color required
        and     dl, 0F0h                ; mask off FG color
        cmp     dl, AIxfer.bBGIndex     ; same as previous BG color?
        jz      short sbcs_check_trans  ; yes
endif ; AVIO_EPOCH_MONO_TEXT

        ;/************************************************************/
        ;/* Background colour has changed so set the new one in      */
        ;/* hardware                                                 */
        ;/************************************************************/
        mov     AIxfer.bBGIndex, dl     ; no, so save it

ifdef   AVIO_EPOCH_MONO_TEXT

  ifndef  BPP24
        swap    ecx                     ; restore actual BG color index
  endif ; BPP24

  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_colour, cx   ; set to H/W register
  else ; _8514

        push    eax
        WaitQ   1

    ifdef   BPP24
        mov   eax, dCurrBG
        mov     _Shadow8514Regs.Color_0,eax
    else  ; BPP24
        mov     ax,cx
        mov     _Shadow8514Regs.Color_0,ax
    endif ; BPP24

        outwQ   COLOR_0, ax
        pop     eax

  endif ; _8514

  ifndef  BPP24
        swap    ecx                     ; put BG Color back to ECX high word
  endif ; BPP24

else  ; AVIO_EPOCH_MONO_TEXT
        ;/************************************************************/
        ;/* Get the actual colour index to use                       */
        ;/* Lookup table is dwords so edx/4 (edx was 16* the index)  */
        ;/************************************************************/
        shr     edx, 2                          ; divide by 4
        add     edx, dword ptr _pAVIOColorXlate ; add the table start
  ifndef _8514
        mov     edx, [edx]                      ; get the color value
        waitshort                       ; wait on the hardware
        memregwrite     bg_colour, dx   ; set to H/W register
  else ; _8514
        push    eax
        mov     ebx,[edx]
        WaitQ   1
        mov     eax, ebx
        outwQ   COLOR_0, ax
        pop     eax
  endif ; _8514
endif ; AVIO_EPOCH_MONO_TEXT

sbcs_check_trans:
ifdef   AVIO_MFI_TEXT
        ;/************************************************************/
        ;/* Now check Transparent/Opaque                             */
        ;/************************************************************/
        test    eax,MFI_TRANSPARENT     ; bgTransparent required?
        jz short sbcs_set_opaque        ; no, so set opaque
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,05h      ; yes, so set bgTransparent
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_D)
  endif ; _8514
        jmp short sbcs_get_char_image_address

sbcs_set_opaque:
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,03h      ; set opaque
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)
  endif ; _8514
endif ; AVIO_MFI_TEXT

ifdef   AVIO_DBCS_TEXT
        ;/************************************************************/
        ;/* Now check Transparent/Opaque                             */
        ;/************************************************************/
        test    eax,MFI_TRANSPARENT     ; bgTransparent required?
        jz short sbcs_set_opaque        ; no, so set opaque

  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,05h      ; yes, so set bgTransparent
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_D)
  endif ; _8514
        jmp short sbcs_get_char_image_address

sbcs_set_opaque:
  ifndef _8514
        waitshort                       ; wait on the hardware
        memregwrite     bg_mix,03h      ; set opaque
  else ; _8514
        WaitQIdle
        WaitQ   2
        outwQ   FUNCTION_0,(FUNC_2OP_COL0+FUNC_S)
  endif ; _8514
endif ; AVIO_DBCS_TEXT

sbcs_get_char_image_address:
        ;/************************************************************/
        ;/* Color handling ended. Now we get char image.             */
        ;/************************************************************/
        mov     eax,indx
        mov     eax,dword ptr CIAArray[eax*4]
                                        ; EAX = char image offset in
                                        ; cache

ifndef _8514
sbcs_set_base_addr:
        add     eax, _pCurCacheBasePhy  ; add cache start address
                                        ; (EAX holds char image
                                        ; address)

        ;/************************************************************/
        ;/* Set up base address for character                        */
        ;/************************************************************/
        waitshort
        memregwrite     pi_map_base_ptr_B,eax   ; set char image addr
                                                ; in H/W register
else ; _8514
        mov     pVRAM,eax
endif ; _8514

sbcs_do_blt_2:
        ;/************************************************************/
        ;/* Set up the bitmap dimensions for a character.            */
        ;/* Note that format is now padded, so the width must be     */
        ;/* whole bytes.                                             */
        ;/************************************************************/
ifndef _8514
        mov     ecx,pAvioInfo
        movzx   eax, [ecx].bCellWidth           ; WIDTH
        dec     ax
        or      ax, 7                           ; force byte width
        waitshort
        memregwrite     pi_map_width_B, ax      ; set it

        movzx   eax,[ecx].bCellHeight           ; HEIGHT
        dec     ax
        waitshort
        memregwrite     pi_map_height_B, ax     ; set it

endif ; _8514

sbcs_same_char_blt:
        ;/************************************************************/
        ;/* Set up start position                                    */
        ;/************************************************************/
ifndef _8514
        waitshort                       ; wait on the hardware
        mov     edx,mask_org_store      ; load mask map origin
        memregwrite     mask_org,edx    ; set mask map origin
endif ; _8514

ifndef  AVIO_CGA_TEXT                           ; MFI, DBCS, EpCol
        ;/************************************************************/
        ;/* Set X dimension of blt.                                  */
        ;/************************************************************/
  ifndef _8514
        mov     ecx,pAvioInfo           ; WIDTH
        movzx   edx,[ecx].bCellWidth
        dec     dx                      ; H/W register requires
                                        ; width - 1
        memregwrite     dim1,dx         ; set to H/W register
  else ; _8514
        WaitQIdle
        WaitQ   1
        mov     edx,pAvioInfo
        movzx   ax,[edx].bCellWidth
    ifdef   BPP24
        test    [_DDT],USE_24BPP
        jz      short @f
        mov     dx,3
        mul     dx
@@:
    endif
        dec     ax
        outwQ   LX,ax
  endif ; _8514
endif ; AVIO_CGA_TEXT

        ;/************************************************************/
        ;/* And we have to set patt_map,dim2 and pixel_op registers  */
        ;/* according to current position.                           */
        ;/************************************************************/
        movzx   eax,bColCounter         ; get column counter
        cmp     al,AIxfer.bNumOfColumn  ; first column?
ifndef _8514
        je short sbcs_fl_col_blt        ; yes
else ; _8514
        je sbcs_fl_col_blt
endif ; _8514
        dec     eax                     ; last column?
ifndef _8514
        jz short sbcs_fl_col_blt        ; yes
else ; _8514
        jz sbcs_fl_col_blt
endif ; _8514
        movzx   eax,bRowCounter         ; get row counter
        cmp     al,AIxfer.bNumOfRow     ; first row?
        je sbcs_first_row               ; yes
        dec     eax                     ; last row?
        jz sbcs_last_row                ; yes
        sub     eax,eax                 ; Y offset in source map is 0
        mov     ecx,lCurrentPos         ; get current position
        movzx   edx,AIxfer.usNextRowDim2 ; get dim2 (cell height)
ifndef _8514
        waitshort
        memregwrite patt_map,eax
        memregwrite dest_map,ecx
        memregwrite dim2,dx
else ; _8514

        mov     PattMap,eax
        mov     DestMap,ecx
        mov     Dim2,dx

endif ; _8514
        jmp sbcs_check_dup              ; go to check we can duplicate
                                        ; blt

sbcs_fl_col_blt:
        sub     eax,eax                 ; Y offset in source map is 0
        mov     ecx,lCurrentPos         ; get current position
        movzx   edx,AIxfer.usNextRowDim2 ; get dim2 (cell height)
ifndef _8514
        waitshort
        memregwrite patt_map,eax        ; set patt_map register
        memregwrite dest_map,ecx        ; set dest_map register
        memregwrite dim2,dx             ; set dim2 register
else ; _8514

        mov     PattMap,eax
        mov     DestMap,ecx
        mov     Dim2,dx

endif ; _8514

        ;/************************************************************/
        ;/* Now do the SBCS blt (First/Last Column)                  */
        ;/************************************************************/
ifndef _8514
        mov     ecx,AVIO_MaskCharBlt
        memregwrite pixel_op,ecx        ; do blt!!!
else ; _8514

if 0
; Now, a bacon, lettuce & tomato please.
        WaitQ   1
        outwQ   CMD_FLAGS,CMD_DRAWTEXT
endif ; 0

ifdef   BPP24
        test    [_DDT], USE_24BPP
        jz      is_cached3
        check_grey fGrey
        test    fGrey, 1
        jz      is_clipped3
is_cached3:
        cmp     _CouldntCache, 0
        jz      not_24bpp3
is_clipped3:
        calc_clip lCurrentPos, eax              ; on return, esi = new dest pos.
;;        mov     dx, Dim2
;;        calc_clip DestMap, eax                  ; on return, esi = new dest pos.

        cmp     eax, 1
        je      sbcs_blt_done                   ; totaly clipped.

        avio_mem_to_vram sbcsCell

        jmp     sbcs_blt_done

not_24bpp3:
endif ; BPP24

        avio_blt_from_vram

sbcs_blt_done:

endif ; _8514
        mov     ecx,1                   ; set dup count 1
        mov     bDupCount,cl
        jmp sbcs_check_uscore           ; go to check attributes

sbcs_first_row:
        movzx   eax,AIxfer.usFirstRowYAddr ; get Y offset in source map
        mov     ecx,lCurrentPos         ; get current position
        swap    ecx                     ; shift Y to low word
        add     cx,ax                   ; add Y offset in dest map
        swap    ecx                     ; proper position in dest map
        swap    eax                     ; shift Y offset to high word
        movzx   edx,AIxfer.usFirstRowDim2 ; get dim2
ifndef _8514
        waitshort
        memregwrite patt_map,eax
        memregwrite dest_map,ecx
        memregwrite dim2,dx
else ; _8514

        mov     PattMap,eax
        mov     DestMap,ecx
        mov     Dim2,dx

endif ; _8514
        jmp sbcs_check_dup

sbcs_last_row:
        sub     eax,eax                 ; Y offset in source map is 0
        mov     ecx,lCurrentPos         ; get current position
        movzx   edx,AIxfer.usLastRowDim2 ; get dim2
ifndef _8514
        waitshort
        memregwrite patt_map,eax
        memregwrite dest_map,ecx
        memregwrite dim2,dx
else ; _8514

        mov     PattMap,eax
        mov     DestMap,ecx
        mov     Dim2,dx

endif ; _8514

sbcs_check_dup:
        push    ebx                     ; preserve ebx & edi, because
        push    edi                     ; we use ebx & edi as position
                                        ; in src & dest map

        ;/************************************************************/
        ;/* For performance reason, we check whether we can duplicate*/
        ;/* same char blt before really doing blt.                   */
        ;/************************************************************/
        push    eax                     ; save position in src  map
        push    ecx                     ; save position in dest map
        mov     eax,sbcsCell            ; current cell
        mov     bDupCount,1             ; initial dup count
;;@@        mov     cl,bColCounter          ; num of column
        movzx   ecx, bColCounter        ; num of column     ;;@@
        mov     edx,pCharBuffer         ; pointer in char buffer

@@:
        dec     cl                      ; last column in a row?
        cmp     cl,1                    ; 
        je short @f                     ; yes
        add     edx,(CELL_SHIFT SHL 1)  ; no, so get and check (2/4)
if      CELL_SHIFT EQ 1
        cmp     ax,word ptr [edx]       ; same char as current cell?
else  ; CELL_SHIFT EQ 1
        cmp     eax,dword ptr [edx]     ; same char as current cell?
endif ; CELL_SHIFT EQ 1
        jne short @f                    ; no
        inc     bDupCount               ; yes, increase dup count
        jmp short @b                    ; next cell

@@:
        pop     edi                     ; restore position in dest map
        pop     ebx                     ; restore position in src  map
        movzx   ecx,bDupCount
        mov     edx,pAvioInfo
        movzx   edx, [edx].bCellWidth   ; get cell width
        mov     eax,AVIO_NoMaskCharBlt  ; get pix op value

ifdef   BPP24
        mov     esi,lCurrentPos         ; used by calc_clip
        mov     lWork, esi
endif ; BPP24

sbcs_blt_loop:
        ;/************************************************************/
        ;/* Now do the SBCS blt                                      */
        ;/************************************************************/
ifndef _8514
        memregwrite pixel_op,eax        ; do blt!!!
else ; _8514
        push    ecx                     ; save dup-count
        push    edi
        push    edx
        push    eax
        push    ebx


  ifdef   BPP24
        test    [_DDT], USE_24BPP
        jz      is_cached4
        check_grey fGrey
        test    fGrey, 1
        jz      is_clipped4
is_cached4:
        cmp     _CouldntCache, 0
        jz      not_24bpp4
is_clipped4:
        calc_clip lWork, eax                    ; on return, esi = new dest pos.
;;        mov     dx, Dim2
;;        calc_clip DestMap, eax                  ; on return, esi = new dest pos.

        cmp     eax, 1
        je      sbcs_loop_end                   ; totaly clipped.

        avio_mem_to_vram sbcsCell

        jmp     sbcs_loop_end

not_24bpp4:
  endif ; BPP24

        avio_blt_from_vram

sbcs_loop_end:

        pop     ebx
        pop     eax
        pop     edx
        pop     edi
        pop     ecx                             ; restore dup-count

if 0
; Now, a bacon, lettuce & tomato please.
        push    edx
        push    eax
        WaitQ   1
        outwQ   CMD_FLAGS,CMD_DRAWTEXT
        pop     eax
        pop     edx
endif ; 0

endif ; _8514
        dec     ecx                     ; blt all ended? (ECX holds dup-count)
        jz short sbcs_blt_loop_end      ; yes
        add     di,dx                   ; update pos in dest map
ifndef _8514
        waitshort
        memregwrite patt_map,ebx
        memregwrite dest_map,edi
else ; _8514

  ifdef   BPP24
        add     word ptr lWork, dx      ; increment dest x-pos
  endif ; BPP24

        mov     PattMap,ebx
        mov     DestMap,edi
;;        mov     Dim2,dx

endif ; _8514
        jmp sbcs_blt_loop         ; next blt

sbcs_blt_loop_end:
        pop     edi                     ; recover edi
        pop     ebx                     ; recover ebx

sbcs_check_uscore:
ifdef   AVIO_HAS_U_SCORE
        ;/************************************************************/
        ;/* Now check underscore.                                    */
        ;/************************************************************/
        mov     eax,sbcsCell
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,00007000h           ; last cell has No uscore & grid?
        jz sbcs_check_exhaust_row       ; no attrs
        test    eax,DBCS_USCORE         ; underscore required?
    ifndef _8514
        jz short sbcs_no_uscore         ; no, next attribute
    else ; _8514
        jz sbcs_no_uscore               ; no, next attribute
    endif ; _8514
  endif ; AVIO_EPOCH_MONO_TEXT

  ifdef   AVIO_DBCS_TEXT
        test    eax,008C0000h           ; This cell has no underscore
                                        ; & no grids?
        jz sbcs_check_exhaust_row
        test    eax,MFI_USCORE          ; underscore required?
    ifndef _8514
        jz short sbcs_no_uscore         ; no, next attribute
    else ; _8514
        jz sbcs_no_uscore               ; no, next attribute
    endif ; _8514
  endif ; AVIO_DBCS_TEXT

  ifdef   AVIO_MFI_TEXT
        test    eax,MFI_USCORE          ; underscore required?
    ifndef _8514
        jz short sbcs_check_exhaust_row ; no
    else ; _8514
        jz sbcs_check_exhaust_row       ; no
  endif ; _8514
  endif ; AVIO_MFI_TEXT

        ;/************************************************************/
        ;/* The underscore is a solid line at the bottom of the cell.*/
        ;/************************************************************/
  ifndef _8514
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)
        swap    edx
        mov     ecx,pAvioInfo
        add     dl,[ecx].bCellHeight
        adc     dh,0
        dec     dx                      ; DX= Y bottom left of the cell
        swap    edx

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to underscore               */
        ;/************************************************************/
        push    eax                     ; save cell value
        movzx   eax,[ecx].bCellWidth    ; get cell width
        mul     bDupCount               ; get uscore length
        dec     ax                      ; H/W requires length - 1
        memregwrite     dim1,ax         ; set line width
        memregwrite     dim2,0          ; set height (actual 1 pel)

        ;/************************************************************/
        ;/* Do underscore writing                                    */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_usblt ; do line blt!!!
        pop     eax                     ; recover cell value
  else ; _8514

        push    dword ptr 1             ; height (one based)
        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellWidth
        mul     bDupCount
        push    eax                     ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        add     dl,[ecx].bCellHeight    ; add cell height
        adc     dh,0
        dec     dx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

        mov     eax,sbcsCell            ; reload cell
  endif ; _8514
endif ; AVIO_HAS_U_SCORE

sbcs_no_uscore:
ifdef   AVIO_HAS_GRID
        ;/************************************************************/
        ;/* Check Horizontal Grid                                    */
        ;/************************************************************/
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_HGRID2         ; horizontal grid required?
        jz sbcs_no_hgrid                ; no, next attribute
  endif ; AVIO_EPOCH_MONO_TEXT

  ifdef   AVIO_EPOCH_COLOR_TEXT
        mov     eax,sbcsCell
        test    eax,00003000h           ; Grids required?
        jz sbcs_check_exhaust_row       ; no @@@@@@@@@@@@@@
        test    eax,DBCS_HGRID2         ; horizontal grid required?
        jz sbcs_no_hgrid                ; no, next attribute
  endif ; AVIO_EPOCH_COLOR_TEXT

  ifdef   AVIO_DBCS_TEXT
        test    eax,DBCS_HGRID4         ; horizontal grid required?
        jz sbcs_no_hgrid                ; no, next attribute
  endif ; AVIO_DBCS_TEXT

        ;/************************************************************/
        ;/* Horizontal Grid required, so set the FG color White.     */
        ;/************************************************************/
        mov     dl,AIxfer.bFGIndex      ; get corrent FG color index

        cmp     dl,bCurrGrid            ; already set?
        je short sbcs_fg_white1         ; yes, don't have to set
        mov     dl,bCurrGrid
        mov     AIxfer.bFGIndex,dl      ; save as last FG color

  ifndef _8514
        mov     dx,sGridStore           ; no, need to set
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514

        WaitQ   1

    ifdef   BPP24
        mov     eax,sGridStore
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,sGridStore
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax

        mov     eax,sbcsCell            ; reload cell
  endif ; _8514

sbcs_fg_white1:
  ifndef _8514
        ;/************************************************************/
        ;/* The horizontal grid is a solid line at the top edge of   */
        ;/* the cell                                                 */
        ;/************************************************************/
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination

        ;/************************************************************/
        ;/* Set the operating dimensions to horizontal grid          */
        ;/************************************************************/
        push    eax                     ; save cell value
        mov     ecx,pAvioInfo           ; 
        movzx   eax,[ecx].bCellWidth    ; get cell width
        mul     bDupCount               ; get hgrid length
        dec     ax                      ; H/W requires length - 1
        waitshort                       ; 
        memregwrite     dim1,ax         ; set width
        memregwrite     dim2,0          ; set height (actual 1 pel)

        ;/************************************************************/
        ;/* Do Horizontal Grid writing                               */
        ;/************************************************************/
        memregwrite     pixel_op,AVIO_hgblt ; do hgrid blt!!!
        pop     eax                     ; recover cell value
  else ; _8514

        push    dword ptr 1             ; height (one based)
        mov     ecx,pAvioInfo
        movzx   eax,[ecx].bCellWidth
        mul     bDupCount
        push    eax                     ; width (one based)

        mov     edx,lCurrentPos
        swap    edx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

        mov     eax,sbcsCell            ; reload cell
  endif ; _8514

sbcs_no_hgrid:
        ;/************************************************************/
        ;/* Check Vertical Grid                                      */
        ;/************************************************************/
  ifdef   AVIO_DBCS_TEXT
        test    eax,DBCS_VGRID4         ; vertical grid required?
  endif ; AVIO_DBCS_TEXT
  ifdef   AVIO_EPOCH_MONO_TEXT
        test    eax,DBCS_VGRID2         ; vertical grid required?
  endif ; AVIO_EPOCH_MONO_TEXT
  ifdef   AVIO_EPOCH_COLOR_TEXT
        test    eax,DBCS_VGRID2         ; vertical grid required?
  endif ; AVIO_EPOCH_COLOR_TEXT
        jz sbcs_check_exhaust_row       ; no

        ;/************************************************************/
        ;/* Vertical Grid required, so set the FG color White.       */
        ;/************************************************************/
        mov     dl,AIxfer.bFGIndex      ; get corrent FG color index
        cmp     dl,bCurrGrid            ; already set?
        je short sbcs_fg_white2         ; yes, don't have to set
        mov     dl,bCurrGrid
        mov     AIxfer.bFGIndex,dl      ; save as last FG color
  ifndef _8514
        mov     dx,sGridStore           ; no, need to set
        waitshort                       ; wait on the hardware
        memregwrite     fg_colour, dx   ; set to H/W register
  else ; _8514

        WaitQ   1

    ifdef   BPP24
        mov     eax,sGridStore
        mov     _Shadow8514Regs.Color_1,eax
    else  ; BPP24
        mov     ax,sGridStore
        mov     _Shadow8514Regs.Color_1,ax
    endif ; BPP24

        outwQ   COLOR_1, ax

  endif ; _8514

sbcs_fg_white2:
        ;/************************************************************/
        ;/* Set the operating dimensions to vertical grid            */
        ;/************************************************************/
  ifndef _8514
        mov     ecx,pAvioInfo
        movzx   ax,[ecx].bCellWidth     ; get and keep cell width
        movzx   dx,[ecx].bCellHeight    ; get cell height
        dec     dx                      ; H/W register requires
                                        ; height - 1
        waitshort                       ; wait on the hardware
        memregwrite     dim1,0          ; set width  (actual 1 pel)
        memregwrite     dim2,dx         ; set height
  else ; _8514

    ifndef  BPP24

        WaitQIdle
        WaitQ   3

        mov     ecx,pAvioInfo
        movzx   dx,[ecx].bCellHeight    ; get cell height
        dec     dx                      ; H/W register requires
                                        ; height - 1
        mov     ax,dx
        outwQ   LY,ax
        outwQ   LX,0

    endif ; BPP24

  endif ; _8514

        ;/************************************************************/
        ;/* The vertical grid is a solid line at the left edge of    */
        ;/* the cell                                                 */
        ;/************************************************************/
  ifndef _8514
        mov     edx,lCurrentPos         ; re-load position same chars
                                        ; start at. (top left of cell)

        ;/************************************************************/
        ;/* Wait for the character blt to finish                     */
        ;/************************************************************/
        waitshort                       ; wait on the hardware
        memregwrite     dest_map,edx    ; set start pos in destination
        movzx   ecx,bDupCount           ; get duplicate count
  else ; _8514

    ifndef  BPP24

        WaitQIdle
        WaitQ   3

        mov     eax,lCurrentPos
        outwQ   X0,ax
        swap    eax
        outwQ   Y0,ax

        ; Set the mode to use foreground color for the underscore.
        outwQ   MODE,(MODE_2DECODE+MD_PS_ONES+MD_UP_FALSE)

    endif ; BPP24

        mov     ebx,pAvioInfo
        movzx   bx,[ebx].bCellWidth
        mov     edx,lCurrentPos
        movzx   ecx,bDupCount

  endif ; _8514

sbcs_vgrid_loop:
        ;/************************************************************/
        ;/* Do Vertical Grid writing                                 */
        ;/************************************************************/
  ifndef _8514
        memregwrite     pixel_op,AVIO_vgblt ; do vgrid blt!!!
        dec     ecx                     ; decrease duplicate count
        jz short sbcs_check_exhaust_row
        add     dx,ax
        waitshort                       ; update position in dest map
        memregwrite     dest_map,edx    ; one cell width forward
        jmp short sbcs_vgrid_loop
  else ; _8514
    ifdef   BPP24

        push    edx

        mov     eax,pAvioInfo
        movzx   ax,[eax].bCellHeight    ; get cell height
        push    eax                     ; height (one based)
        push    dword ptr 1             ; width (one based)

        swap    edx
        movzx   eax, dx
        push    eax                     ; y position
        swap    edx
        movzx   eax, dx
        push    eax                     ; x position

        call    _AVIO24HVLine
        add     esp,16

        pop     edx
        add     dx,bx
        dec     ecx
        jz short sbcs_check_exhaust_row
        jmp short sbcs_vgrid_loop

    else  ; BPP24

        push    edx
        WaitQ   1
        outwQ   CMD_FLAGS,CMDSOLID
        pop     edx
        dec     ecx
        jz short sbcs_check_exhaust_row

        push    edx
        WaitQ   2
        pop     edx

        add     dx,bx
        push    edx
        mov     eax,edx
        outwQ   X0,ax
        swap    eax
        outwQ   Y0,ax
        pop     edx
        jmp short sbcs_vgrid_loop

    endif ; BPP24
  endif ; _8514
endif ; AVIO_HAS_GRID

sbcs_check_exhaust_row:

ifdef AVIO_HAS_GRID
  ifdef _8514
    ifndef  BPP24
        WaitQIdle
        WaitQ   1
        ; Set the mode back to plane mode for Fonts
        outwQ   MODE,(MODE_2DECODE+MD_PS_COPY+MD_UP_FALSE)
    endif ; BPP24
  endif ; _8514
endif ; AVIO_HAS_GRID

        ;/************************************************************/
        ;/*  And moving on to the next position..                    */
        ;/*  Update the x position.                                  */
        ;/************************************************************/
        movzx   ecx,bDupCount           ; get duplicate count   ;;@MFI, DBCS
        sub     bColCounter,cl          ; declease column counter
                                        ; exhaust columns in this row?
        jz short new_row                ; yes, move to next row
                                        ; no
        mov     eax,pAvioInfo
        movzx   eax,[eax].bCellWidth    ; get cell width
        mul     cl                      ; multiply by dup count
        mov     edx,lCurrentPos
        add     dx,ax
        mov     lCurrentPos,edx         ; update current position
        add     indx,ecx                ; update index for CIAArray
        shl     ecx,CELL_SHIFT          ; mul by cell byte  (1/2)
        add     pCharBuffer,ecx         ; update pointer in char buffer
        jmp     next_char               ; handle rest chars in this row

        ;/************************************************************/
        ;/*  We exhaust colums in current row. Go to new row.        */
        ;/************************************************************/
new_row:
        dec     bRowCounter             ; exhaust rows in current
                                        ; clipped rect?
        jz short new_clip               ; yes, go next clip rect
        movzx   eax,AIxfer.bBufferWidth ; no, so update pointer in
        shl     eax,CELL_SHIFT          ; char buffer to the first (1/2)
        add     pcbufRow,eax            ; column in next row of clipped
        mov     eax,pcbufRow            ; rect.
        mov     pCharBuffer,eax
        mov     eax,lRowPos             ; also update position..
        swap    eax
        mov     edx,pAvioInfo
        movzx   dx,[edx].bCellHeight
        add     ax,dx
        swap    eax
        mov     lRowPos,eax
        sub     eax,eax                 ;        we have to clear
        dec     eax                     ; lastSbcsCell because we may
        mov     lastSbcsCell,eax        ; call _AvioForceCharInCache
                                        ; and change H/W condition!
        jmp     next_row                ; go to check this row

        ;/************************************************************/
        ;/*  We exhaust rows in current clipped  rect. Go to new     */
        ;/*  clipping rectangle.                                     */
        ;/************************************************************/
new_clip:
        dec     numClipRects                    ; exhaust clipping rect?
        jz short exhaust_clips                  ; yes, exit
        mov     eax,AIxfer.pCurrentClipRect     ; no, so
        add     eax,len_clip_rect               ; update pointer to
        mov     AIxfer.pCurrentClipRect,eax     ; next clipping rect.
        ;/************************************************************/
        
        ;/* If we have multiple clip rectangles and the first cell   */
        ;/* in next clip is SBCS and same cell as the last one in    */
        ;/* current clip, we draws it without setting H/W because    */
        ;/* lastSbcsCell is not reset, although H/W configuration is */
        ;/* changed by character caching routine!                    */
        
        ;/************************************************************/
        sub     eax,eax                 ; no, so we have to clear
        dec     eax                     ; lastSbcsCell because we may
        mov     lastSbcsCell,eax        ; call _AvioForceCharInCache
                                        ; and change H/W condition!
        jmp     next_clip               ; go to check this clip

        ;/************************************************************/
        ;/*  Drawing for all clipping rects done.                    */
        ;/************************************************************/
exhaust_clips:
        mov     eax,0FFFFFFFFh                  ; indicate success
        jmp short do_nothing

error_exit:
        sub     eax,eax                         ; indicate error

do_nothing:

ifdef _8514

  ifdef BPP24
        cmp     _CouldntCache, 0
        jz      short @f
        call    _eddt_InvalidateCache
        push    pFontDetails
        call    _eddt_LocateCachedFont
        add     esp,4
        mov     _CouldntCache, 0        ; assume we'll cache the fonts
@@:
  endif ; BPP24

; tidy up and go home
        push    eax
        WaitQ   1
        outwQ   READ_ENABLE,READ_ALL_PLANES
        ifndef  S3
        setclip 0,0,SCR_8514_WIDTH-1,SCR_8514_HEIGHT-1
        else
        setclip 0,0,SCR_S3_WIDTH-1,SCR_S3_HEIGHT-1
        endif
        pop     eax

endif ; _8514

ifndef _8514
        popxga                                  ; recover H/W register
endif ; _8514

cEnd

_TEXT           ends

END

