;*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
        TITLE   DCAFMAC.INC
;/*****************************************************************************
;*
;* SOURCE FILE NAME = DCAFMAC.INC
;*
;* DESCRIPTIVE NAME = Macros for DCAF code
;*
;*
;* VERSION      V2.0
;*
;* DATE         04/28/92
;*
;* DESCRIPTION  Contains useful macros for the DCAF code.
;*
;* FUNCTIONS
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   04/28/92                     Created for DCAF 1.3
;*   07/01/92                     Ported to 32-bit for DCAF 2.0
;*
;*****************************************************************************/


;----------------------------------------------------------------------;
; Define macros to allow more readable "if" statements for single
; lines of code. e.g. a FLAT memory model specific instruction can
; be written as:
;
; @FLAT <mov    esi,pDest>
;
;----------------------------------------------------------------------;
@FLAT   macro   instruction
if      _FLAT
        instruction
endif
endm

@SEG    macro   instruction
if      _SEG
        instruction
endif
endm

@VGA    macro   instruction
if      _VGA
        instruction
endif
endm

BGA     macro   instruction
if      _BGA
        instruction
endif
endm

XGA     macro   instruction
if      _XGA
        instruction
endif
endm

BXGA    macro   instruction
if      _BGA or _XGA
        instruction
endif
endm

BVGA    macro   instruction
if      _BGA or _VGA
        instruction
endif
endm

VXGA    macro   instruction
if      _VGA or _XGA
        instruction
endif
endm

@FLD8   macro   instruction
ifdef _FIELD8
ifdef _FIELD16
if not (((_FIELD8 eq 0) and (_FIELD16 eq 1)) or ((_FIELD8 eq 1) and (_FIELD16 eq 0)))
%out _FIELD8 and _FIELD16 incorrectly defined
.err
endif
endif
endif
if      _FIELD8
        instruction
endif
endm

@FLD16  macro   instruction
ifdef _FIELD8
ifdef _FIELD16
if not (((_FIELD8 eq 0) and (_FIELD16 eq 1)) or ((_FIELD8 eq 1) and (_FIELD16 eq 0)))
.err _FIELD8 and _FIELD16 incorrectly defined
endif
endif
endif
if      _FIELD16
        instruction
endif
endm

NRPT    macro   instruction
if      data_type eq <non_repeating_data>
        instruction
endif
endm

RPT     macro   instruction
if      data_type eq <repeating_data>
        instruction
endif
endm


;----------------------------------------------------------------------;
;
; INITFIELDSIZE sets the values for _FIELD8 and _FIELD16 to be true or
; false depending on the field_size passed
;
;----------------------------------------------------------------------;
INITFIELDSIZE macro  field_size

        .erre   (field_size eq 8) or (field_size eq 16)

if (field_size) eq 8
        _FIELD8  =  1
        _FIELD16 =  0
else
        _FIELD8  =  0
        _FIELD16 =  1
endif
endm


;----------------------------------------------------------------------;
;
; store_repeating_data repeats the current data field ecx times to the
; destination
;
; Parameters:
;        field_size  - Specifies size in bits of data fields
;                      Must be 8 or 16
;
;
; Entry:
;        esi points to current data field
;        edi points to destination for data
;        ecx contains count of number of times to write data
;
; Exit:
;        esi incremented past data field
;        edi points to next free location in dest
;        ecx contains zero
;
;----------------------------------------------------------------------;
store_repeating_data     macro field_size

if      field_size eq 8
        lodsb
        rep     stosb
else
        .err    field_size ne 16
        lodsw
        rep     stosw
endif
endm


;----------------------------------------------------------------------;
;
; copy_non_repeating_data copies the next ecx data fields to the
; destination
;
; Parameters:
;        field_size  - Specifies size in bits of data fields
;                      Must be 8 or 16
;
;
; Entry:
;        esi points to first data field
;        edi points to destination for data
;        ecx contains count of number of data fields to copy
;
; Exit:
;        esi incremented past data fields
;        edi points to next free location in dest
;        ecx contains zero
;
;----------------------------------------------------------------------;
copy_non_repeating_data macro field_size

if      field_size eq 8
        rep     movsb
else
        .err    field_size ne 16
        rep     movsw
endif
endm


;----------------------------------------------------------------------;
;
; read_cell_header fetches the current cell header into ax (from the
; source pointer). The source pointer is incremented to point to the
; following data.
;
; If the data size is 8 bits, then the cell header is sign extended
; to fill all 16 bits of ax.
;
;----------------------------------------------------------------------;
read_cell_header macro field_size

if      field_size eq 8
        lodsb           ; Read byte into al
        cbw             ; Extend byte to fill ax
else
        lodsw           ; Read word into ax
endif
endm

;----------------------------------------------------------------------;
; Macro to enter the driver (i.e. grab the Driver semaphore etc.).
; This varies according to driver.
;----------------------------------------------------------------------;
enterdriver     macro
        mov     esi,hddc                ; Make ESI -> ddc
        mov     edx,esi                 ; Copy into EDX
        call    enter_driver            ; Do the business
        jc      gsb_exit_no_lock        ; DX:AX = 0 on error
endm


;----------------------------------------------------------------------;
;
;----------------------------------------------------------------------;
leavedriver     macro
        call    leave_driver
endm

;----------------------------------------------------------------------;
; Macro to exclude the pointer from the supplied screen bounding
; rectangle.
;----------------------------------------------------------------------;
exclude_pointer         macro   rclBound
        mov     edx,rclBound.rcl_yTop           ; EDX = top (inclusive)
;       sub     edx,SCREEN_CY-1                 ; !! Incorrect code generated
        sub     edx,SCREEN_CY
        inc     edx
        neg     edx                             ; EDX = top (flipped inclusive)
        mov     edi,rclBound.rcl_yBottom        ; EDI = top (exclusive)
;       sub     edi,SCREEN_CY-1                 ; !! Incorrect code generated
        sub     edi,SCREEN_CY
        inc     edi
        neg     edi                             ; EDI = bottom (flipped inclusive)
        mov     ecx,rclBound.rcl_xLeft          ; ECX = left
        mov     esi,rclBound.rcl_xRight         ; ESI = right
        INVOKE  far_exclude
endm


;----------------------------------------------------------------------;
; Macro to unexclude the pointer
;----------------------------------------------------------------------;
unexclude_pointer       macro
        INVOKE  far_unexclude
endm

;----------------------------------------------------------------------;
; Macro to fill the rect buffer with rectangles from the engine.
;
; no_more_rects_exit - label to jump to if no more rectangles in region
;----------------------------------------------------------------------;
fill_rect_buffer        macro   no_more_rects_exit
        ; Set up the control structure
        mov     Control.rgnrc_ircStart,1
        mov     Control.rgnrc_crc,NRECTS
        mov     Control.rgnrc_ulDirection,RECTDIR_LFRT_TOPBOT

        ; Make the call to the engine
        INVOKE  PFNDefGetRegionRects PTR pfnDefGetRegionRects,
                hdc,
                hrgnApp,
                NULL,
                ADDR Control,
                ADDR arclBuffer,
                hddc,
                NGreGetRegionRects

ifdef FIREWALLS
        or      eax,eax
        jnz     @F
        rip     text,<GetRegionRects returns error>
        int     3
@@:
endif
        ; Set flag to indicate whether there are more rects in engine
        ; If there were less rects returned than we asked for then the
        ; engine has run out. If the engine had exactly the number of
        ; rects that we asked for then at this point we will believe
        ; that there are more to come. This is not a problem because when
        ; we try to refill the buffer we wil get nothing returned and
        ; exit gracefully.
        xor     eax,eax         ; Assume no more rects - put FALSE in ax.
        cmp     Control.rgnrc_crcReturned,NRECTS ; See how many rects returned
        jl      @F              ; Jump if fewer returned than we asked for
        inc     eax             ; Set ax to TRUE
@@:     mov     fMoreEngineRects,eax ; Store flag

        ; Update the number of compressed rectangles in our buffer
        xor     eax, eax
        mov     cCompressedRectsInBuffer, eax

        ; Update the count of the rectangles in our buffer
        mov     ecx,Control.rgnrc_crcReturned
        mov     cRemainingRectsInBuffer,ecx

        ; Check that we have some rectangles
        or      ecx, ecx
        jz      no_more_rects_exit

        ; Reset prclCurrentRect
        lea     ebx,arclBuffer
        mov     prclCurrentRect,ebx
endm

;----------------------------------------------------------------------;
; Macro to remove the compressed rectangles from the application
; region.
;----------------------------------------------------------------------;
remove_compressed_rects macro
local   remove_next_rect
local   rects_removed

        ; Check that there are some rectangles to remove
        cmp     cCompressedRectsInBuffer, 0
        je      rects_removed

        lea     ebx,arclBuffer
        mov     prclCurrentRect,ebx

remove_next_rect:
        INVOKE  PFNDefCombineRectRegion PTR pfnDefCombineRectRegion,
                hdc,
                hrgnApp,
                ebx,
                hrgnApp,
                CRGN_DIFF,
                hddc,
                NGreCombineRectRegion


ifdef FIREWALLS
        ; Rip if     return code
        or      eax, eax
        jnz     @F
        rip     text,<Bad return from CombineRectRegion>
        int     3
@@:
endif
        .errnz  RGN_ERROR
        or      eax,eax
        jz      csb_exit_ax             ;error logged by CombineRectRegion

        add     prclCurrentRect,SIZE RECTL
        mov     ebx, prclCurrentRect
        dec     cCompressedRectsInBuffer
        jnz     remove_next_rect
rects_removed:
endm


;----------------------------------------------------------------------;
; Return NULL region is a macro that sets the apps region to NULL
; as efficiently as possible.
; This is done by removing the bounding rectangle from the region.
;----------------------------------------------------------------------;
return_null_region      macro

        INVOKE  PFNDefSetRectRegion PTR pfnDefSetRectRegion,
                hdc,
                hrgnApp,
                NULL,
                0,
                hddc,
                NGreSetRectRegion

ifdef FIREWALLS
        ; Rip if     return code
        or      eax, eax
        jnz     @F
        rip     text,<Bad return from SetRegion>
        int     3
@@:
endif

        .errnz  RGN_ERROR
        or      eax,eax
        jz      csb_exit_ax             ;error logged by SetRectRegion
endm

;----------------------------------------------------------------------;
; The following macros deal with selecting VGA planes
;
;  plane_select_local_vars - defines the local variables required
;  plane_select_initialise - initialises the local varaibles
;  plane_select_next       - moves onto the next plane
;  plane_select_repeat     - loops back for the next plane
;----------------------------------------------------------------------;

;plane_select_local_vars macro
;        cPlane  :DWORD
;endm

plane_select_initialise macro
        mov     cPlane, 0

        ; we assume the foloowing values
        .erre   (RM_C0 eq 0)
        .erre   (RM_C1 eq 1)
        .erre   (RM_C2 eq 2)
        .erre   (RM_C3 eq 3)
endm

plane_select_next macro

        mov     edx, EGA_BASE+GRAF_ADDR
        mov     eax, cPlane
        mov     ah, al
        mov     al, GRAF_READ_MAP
        out     dx, ax
endm


plane_select_repeat macro loop_address
        inc     cPlane
        cmp     cPlane, 4
        jl      loop_address
endm
