;      /*****************************************************************/
;      /*                                                               */
;      /*           Copyright (c) IBM Corporation  1987, 1992           */
;      /*                     All Rights Reserved                       */
;      /*                                                               */
;      /*****************************************************************/
;      /******************* START OF SPECIFICATIONS *********************/
;      /*                                                               */
;      /*  SOURCE FILE NAME: LOCATOR.ASM                                */
;      /*                                                               */
;      /*  DESCRIPTIVE NAME: Locator handler                            */
;      /*                                                               */
;      /*  COPYRIGHT:  IBM Corp. 1992                                   */
;      /*                                                               */
;      /*  STATUS:  Version 1.0                                         */
;      /*                                                               */
;      /*  NOTES: This module provide support for locator logical       */
;      /*         devices. The device dependent routine calls LOC_ENGINE*/
;      /*         after filling in the DCB and extended event packet.   */
;      /*                                                               */
;      /*         Loc_ProxFilter is provided to filter out proximity    */
;      /*         points in a positonary position, for example, if the  */
;      /*         pen is left on the digitizer surface. This routine    */
;      /*         works inconjunction with Loc_ProxFitlerTC. The        */
;      /*         device dependent routine must allocate a BOX_FILTER   */
;      /*         structure and initialize it.                          */
;      /*                                                               */
;      /*         The device dependent routine may need to subclass,    */
;      /*         or replace, the coordinate adjustment routine or the  */
;      /*         forceClear routine. The latter is called after the    */
;      /*         proximity or contact time out occurs.                 */
;      /*                                                               */
;      /*         The locator module also supports a special IOCTL      */
;      /*         intended for use by the alignment calibration program */
;      /*         that returns raw cooridinates.                        */
;      /*                                                               */
;      /*  ENTRY POINTS:                                                */
;      /*      See public statements                                    */
;      /*  EXTERNAL REFERENCES:                                         */
;      /*      See extrn statements                                     */
;      /*                                                               */
;      /******************* END  OF  SPECIFICATIONS *********************/
.xlist
  include pensegs.inc
  include pen.inc
  include penidc.inc
  include penei.inc
  include penioctl.inc
  include struc.inc
  include devhlp.inc
  include infoseg.inc
.list

.286p

;------------------------------------------------------------------------------
; external data references
;------------------------------------------------------------------------------

extrn Device_Help  : dword

;------------------------------------------------------------------------------
; external routines
;------------------------------------------------------------------------------

extrn Idc_ReportEvent : near
extrn But_GetButtons : near
extrn But_GetButtonShift : near
extrn Dsp_GetSuppress    : near

;------------------------------------------------------------------------------
; local equates
;------------------------------------------------------------------------------

TICK_LIMIT equ 4
;------------------------------------------------------------------------------
; local data declarations
;------------------------------------------------------------------------------

DSEG   segment
public qlrc_sem
qlrc_sem   db  0     ; reentry semaphore for query locator raw coordinate

stateTable label word   ; state transition action table
       dw    clr_clr
       dw    0          ; reserved
       dw    clr_prx
       dw    clr_con

       dw    0          ; reserved
       dw    0          ; reserved
       dw    0          ; reserved
       dw    0          ; reserved

       dw    prx_clr
       dw    0          ; reserved
       dw    prx_prx
       dw    prx_con

       dw    con_clr
       dw    0          ; reserved
       dw    con_prx
       dw    con_con

DSEG   ends

CSEG SEGMENT
     ASSUME    CS:CGROUP, SS:nothing, ES:nothing, DS:DGROUP


;---- ROUTINES TO HANDLE EVENTS -----------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; process an event for a device dependent locator device
;  bx = dcb
;  di = extended event packet address
;------------------------------------------------------------------------------
public Loc_Engine
Loc_Engine    proc

  mov  [bx].dcb_StateTimeOut,0   ; reset the watchdog timer

; if anyone is waiting on a query locator raw coordinate (QLRC)

  .if <bit [bx].dcb_LocFlags nz QLRC_REQUEST> AND
  .if <[bx].dcb_LocNewState eq STATE_CONTACT>
     and  [bx].dcb_LocFlags,not QLRC_REQUEST  ;signals that its our ProcRun that
                                              ;woke up the thread, clean up,
                                              ;and we don't need to ProcRun
                                              ;multiple times if wakeup is slow
     push bx
     lea  bx,qlrc_sem           ; set up block id
     mov  ax,ds
     mov  dl, DevHlp_ProcRun
     call Device_Help           ; Invoke function
     pop  bx
  .endif

; process this coorindate point

  call detectMotion
  call [bx].dcb_@Adjust
  call computeStd
  call stateMachine
  call fillEventBuffer
  call Idc_ReportEvent
  call updateValues

  ret
Loc_Engine endp

;------------------------------------------------------------------------------
; see if the location has changed.
;  bx = dcb
;------------------------------------------------------------------------------
public detectMotion    ;ddxy
detectMotion proc
.386p
  mov  eax, [bx].dcb_LocNewX      ; check if x has changed
  .if <[bx].dcb_LocLastX eq eax> AND
  mov  eax, [bx].dcb_LocNewY      ; check if y has changed
  .if <[bx].dcb_LocLastY eq eax>
     and  [bx].dcb_LocFlags, not LOC_MOTION
  .else
     or   [bx].dcb_LocFlags, LOC_MOTION
  .endif
.286p
  ret
detectMotion endp

;------------------------------------------------------------------------------
; adjust the coordinates  - ABSOLUTE
;  bx = dcb
;------------------------------------------------------------------------------
public AdjustCoords    ;ddxy
AdjustCoords proc

.386p
; adjust x
  mov  eax, [bx].dcb_LocNewX
  lea  si, [bx].dcb_Xtrans
  call Loc_normalize
  call Loc_slide
  mov  [bx].dcb_LocNDCX,eax

; adjust y
  mov  eax, [bx].dcb_LocNewY
  lea  si, [bx].dcb_Ytrans
  call Loc_normalize
  call Loc_slide
  mov  [bx].dcb_LocNDCY,eax
.286p
  ret
AdjustCoords endp

;------------------------------------------------------------------------------
; adjust the coordinates  - RELATIVE
;  bx = dcb
;------------------------------------------------------------------------------
public AdjustRelCoords  ;ddxy
AdjustRelCoords proc
.386p
  mov  eax, [bx].dcb_LocNewX
  mov  [bx].dcb_LocNDCX,eax
  mov  eax, [bx].dcb_LocNewY
  mov  [bx].dcb_LocNDCY,eax
.286p
  ret
AdjustRelCoords endp

;------------------------------------------------------------------------------
; convert raw device cooridinate to normalized device cooridinate
;
;  1) adjust from raw device coridinate origin to normalized device origin
;  2) normalized from measured extent to fixed extent
;  3) clip to fixed extent
;  4) invert if necessary
;
;  eax = coordinate value
;  si = coordinate transformation structure
; returns
;  eax = adjusted coordinate value
;------------------------------------------------------------------------------
public Loc_normalize        ;ddxy
Loc_normalize proc
 .386p
; adjust realitive to normalized origin

  add  eax, [si].trn_org_adj
  .if  s                                   ; if result is negative
     mov   eax,0                           ; back it up to 0 (but no more)
  .endif

; normalize

  mov  edx, [si].trn_ext_max
  imul edx                                 ; eax*edx = EDX:EAX
  mov  ecx, [si].trn_ext_adj
  idiv ecx                                 ; edx:eax / ecx = EAX.EDX
  .if  <nonzero edx>                       ; if remainder
     inc  eax
  .endif

; clip to real extents (max value is extents - 1)

  .if  <eax ge [si].trn_ext_max>
     mov    eax,[si].trn_ext_max
     dec    eax
  .endif

; invert if necessary

  .if  <bit [si].trn_flags nz INVERTED_COORD>
     inc  eax
     neg  eax
     add  eax, [si].trn_ext_max
  .endif

.286p
  ret
Loc_Normalize endp

;------------------------------------------------------------------------------
; adjust a coordinate using slide algorithm
;  eax = coordinate value
;  si = coordinate transformation structure
; returns
;  eax = adjusted coordinate value
;------------------------------------------------------------------------------
public Loc_slide     ;ddxy
Loc_slide proc
.386p
  push eax
  mov  ax, [si].trn_offset
  cwde
  mov  ecx, eax
  pop eax
  .if  <nonzero cx>
     mov  edx, [si].trn_ext_max
     push ebx
     .if <ecx lt 0>            ; negative offset
        mov  ebx,ecx           ; put OFFSET in bx
        add  ebx,eax           ; add coord to offset
        .if  s                 ; if still negative
           mov    eax,0        ; back it up to 0 (but no more)
        .else
           mov    ebx,edx      ; put fixed extent in ebx
           add    ebx,ecx      ; add the OFFSET to fixed extent
           .if  <eax gt ebx>   ; If coord is greater than Offset+FixedExtent
                               ; 2*X - Xm    (when X=Xm, coord=extent)
              add    eax,eax   ; slide area situation, double coord
              sub    eax,edx   ; minus the fixed extent from coord
           .else               ; If coord is less than Offset+FixedExtent
              add    eax,ecx   ; normal area
           .endif
        .endif
     .else                     ; positive (or zero)
        mov    ebx,edx         ; put extent in ebx
        sub    ebx,ecx         ; ecx=OFFSET
        .if  <eax gt ebx>      ; if coord greater than extent-OFFSET
           mov    eax,edx      ; don't adjust past extent
        .else
           .if <eax lt ecx>
             add    eax,eax    ; slide area
           .else
             add    eax,ecx    ; normal area
           .endif
        .endif
     .endif
     pop  ebx
  .endif
  ret
Loc_slide endp

;------------------------------------------------------------------------------
; comput standard coordinate values
;  bx = dcb
;------------------------------------------------------------------------------
public computeStd
computeStd proc
  mov  si,[bx].dcb_@RegCaps
  mov  di, [bx].dcb_@EiEvent
  mov  eax,[si].lcap_std_x_extent
  imul [bx].dcb_LocNDCX
  idiv [si].lcap_dev_x_extent
  mov  [di].lev_std_x,eax

  mov  eax,[si].lcap_std_y_extent
  imul [bx].dcb_LocNDCY
  idiv [si].lcap_dev_y_extent
  mov  [di].lev_std_y,eax
  ret
computeStd endp

;------------------------------------------------------------------------------
; process state transitions. Figure out events and mouse buttons
;  bx = dcb
;------------------------------------------------------------------------------
public stateMachine
stateMachine proc
  mov  di,[bx].dcb_@EiEvent
  and  [di].lev_cntrl,LOC_REL+LOC_ABS+LOC_FAKE
  mov  si,[bx].dcb_LocLastState
  sal  si,2
  add  si,[bx].dcb_LocNewState
  jmp  stateTable[si]
stateMachine endp


; this is a strange transition and isn't expected, but its OK
public clr_clr
clr_clr proc
  mov  [di].cev_devicebits, EV_MOVE
  ret
clr_clr endp

; valid only for devices that report proximity
public clr_prx
clr_prx proc
  mov  [di].cev_devicebits, EV_MOVE + EV_ENTER_PROX
  or   [di].lev_cntrl,LOC_PROX
  ret
clr_prx endp

; can't tell if this is a device that doesn't support proximity or just
; a quite touchdown, so we have to check the capabilities before reporting
; EV_ENTER_PROX
public clr_con
clr_con proc
  call But_GetButtonShift
  mov  [bx].dcb_LocMouBut,al ; save for whole stroke
  or   [di].lev_cntrl,dx     ; returned control information
  call Dsp_GetSuppress
  or   [di].lev_cntrl,dx     ; returned control information
  mov  ah,al
  .if  <bit [bx].dcb_LocFlags nz LOC_MOTION>
     sar  al,1
     or   al,ah
  .endif
  mov  si,[bx].dcb_@regCaps
  .if <bit [si].lcap_caps nz PENCAP_PROXIMITY>
     or ax,EV_ENTER_PROX
  .endif
  mov  [di].cev_devicebits, ax
  or   [di].lev_cntrl,LOC_CONTACT
  ret
clr_con endp

public prx_clr
prx_clr proc
  mov  [di].cev_devicebits, EV_MOVE + EV_EXIT_PROX
  ret
prx_clr endp

public prx_prx
prx_prx proc
  mov  [di].cev_devicebits, EV_MOVE
  or   [di].lev_cntrl,LOC_PROX
  ret
prx_prx endp

public prx_con
prx_con proc
  call But_GetButtonShift
  mov  [bx].dcb_LocMouBut,al ; save for whole stroke
  or   [di].lev_cntrl,dx     ; returned control information
  call Dsp_GetSuppress
  or   [di].lev_cntrl,dx     ; returned control information
  mov  ah,al
  .if  <bit [bx].dcb_LocFlags nz LOC_MOTION>
     sar  al,1
     or   al,ah
  .endif
  mov  [di].cev_devicebits, ax
  or   [di].lev_cntrl,LOC_CONTACT
  ret
prx_con endp

; Could be quick lift off or a device that doesn't support proximity.
public con_clr
con_clr proc
  mov  al, EV_MOVE
  mov  ah,[bx].dcb_LocMouBut
  mov  si,[bx].dcb_@regCaps
  .if <bit [si].lcap_caps nz PENCAP_PROXIMITY>
     or ax,EV_EXIT_PROX
  .endif
  mov  [di].cev_devicebits, ax
  ret
con_clr endp

public con_prx
con_prx proc
  mov  al, EV_MOVE
  mov  ah,[bx].dcb_LocMouBut
  mov  [di].cev_devicebits, ax
  or   [di].lev_cntrl,LOC_PROX
  ret
con_prx endp

public con_con
con_con proc
  xor  ah,ah
  mov  al,[bx].dcb_LocMouBut
  .if  <bit [bx].dcb_LocFlags nz LOC_MOTION>
     sar  al,1
  .endif
  mov  [di].cev_devicebits, ax
  or   [di].lev_cntrl,LOC_CONTACT
  ret
con_con endp

;------------------------------------------------------------------------------
; fill in locator event fields
;  bx = dcb
;------------------------------------------------------------------------------
public fillEventBuffer
fillEventBuffer  proc

;    fill in EIQ locator position

  mov di,[bx].dcb_@EiEvent
.386p
  mov eax,[bx].dcb_LocNDCX
  mov [di].lev_dev_x, eax
  mov eax,[bx].dcb_LocNDCY
  mov [di].lev_dev_y, eax
.286p
  mov ax, [bx].dcb_LocNewZ
  mov [di].lev_dev_z, ax

; finish off extended event packet

  call But_GetButtons             ; get buttons
  mov  [di].lev_buttons,ax

  TraceAbs
  ret
fillEventBuffer endp

;------------------------------------------------------------------------------
; update fields for next time
;  bx = dcb
;------------------------------------------------------------------------------
public updateValues
updateValues proc
  mov ax, [bx].dcb_LocNewState
  mov [bx].dcb_LocLastState, ax
.386p
  mov eax, [bx].dcb_LocNewX
  mov [bx].dcb_LocLastX,eax
  mov eax, [bx].dcb_LocNewY
  mov [bx].dcb_LocLastY,eax
.286p
  mov ax, [bx].dcb_LocNewZ
  mov [bx].dcb_LocLastZ,ax
  mov di,[bx].dcb_@EiEvent
  mov ax, [di].lev_cntrl
  mov [bx].dcb_LocLastCntrl,ax
  ret
updateValues endp

;---- IOCTL ROUTINES ----------------------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; return next raw coordinate (used for calibration)
;  edx = timeout value
;  bx = dcb
; returns
;  eax = dqlrc.rc
;  ecx = dqlrc.xRaw
;  edx = dqlrc.yRaw
;------------------------------------------------------------------------------
public Loc_qlrc
Loc_qlrc proc
  .386p

; back sure only one guy doing this

  xor  al,al
  xchg qlrc_sem,al              ;set semaphore
  or   al,al
  .if  nz
     mov eax,QLRC_BUSY          ;someone already has it
  .else

; wait for coordinates to be saved by interrupt handler in loc_engine

     .repeat
        DISABLE
        or   [bx].dcb_LocFlags,QLRC_REQUEST
        push bx
        mov  cx,dx                 ; set up timeout value
        shr  edx,16
        mov  di,dx
        lea  bx,qlrc_sem           ; set up block id
        mov  ax,ds
        mov  dh,0                  ; allow interrupts
        mov  dl, DevHlp_ProcBlock
        call Device_Help           ; Invoke function
        DISABLE
        pop  bx
        .if  c                     ; unusual wake up
           mov  eax, QLRC_TIMEOUT
           and  [bx].dcb_LocFlags,not QLRC_REQUEST
           jmp  short qlrc_done
        .endif
     .until <bit [bx].dcb_LocFlags z QLRC_REQUEST> ;make sure its our wakeup
     mov  eax,QLRC_VALID

; return last coordinates saved by interrupt handler in loc_engine

qlrc_done:
     mov  ecx, [bx].dcb_LocNewX
     mov  edx, [bx].dcb_LocNewY

     ENABLE
     mov  qlrc_sem,0            ;clear reentry semaphore
  .endif
  ret
  .286p
Loc_qlrc endp

;--- RUNS UNDER TIMER TICK HANDLER --------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; See if proximity or contact state has timed out. If so, return to clear.
;  bx = dcb
;  si = locator event packet
;------------------------------------------------------------------------------
public Loc_Tick
Loc_Tick proc
 .if <[bx].dcb_LocLastState ne STATE_CLEAR>
     inc [bx].dcb_StateTimeOut

    .if <[bx].dcb_LocLastState eq STATE_PROX>
       mov cx,[bx].dcb_TimeoutLimProx
    .else
       mov cx,[bx].dcb_TimeoutLimCont
    .endif
    .if <nonzero cx>
       .if <[bx].dcb_StateTimeout gt cx>    ;have we timed out waiting
         call [bx].dcb_@Dev_ForceClear          ;for Prox data???
       .endif
    .endif
 .endif
  ret
Loc_Tick endp

;---- DEFAULT DCB@ ROUTINES ---------------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; force to clear state after either prox or contact state timed out
; bx = dcb for this device
;------------------------------------------------------------------------------
public Loc_ForceClear
Loc_ForceClear proc
  GetCritSec [bx].dcb_Sem1
  .if  z
     mov [bx].dcb_LocNewState, STATE_CLEAR
.386p
     mov eax,[bx].dcb_LocLastX           ;Use last position
     mov [bx].dcb_LocNewX,eax
     mov eax,[bx].dcb_LocLastY
     mov [bx].dcb_LocNewY,eax
.286p
     mov ax,[bx].dcb_LocLastZ
     mov [bx].dcb_LocNewZ,ax

     mov di,[bx].dcb_@EiEvent           ; set cntrl
     mov ax,[bx].dcb_LocLastCntrl
     and ax,LOC_ABS+LOC_REL
     or  ax,LOC_FAKE
     mov [di].lev_cntrl, ax

     call Loc_Engine                    ; bx = dcb
                                        ; di = event
  .endif
  ClearCritSec [bx].dcb_Sem1
  ret
Loc_ForceClear endp

;---- BOX FILTRER ROUTINES ----------------------------------------------------
;
;------------------------------------------------------------------------------
.386p
;------------------------------------------------------------------------------
; see if the location has moved out the the 'box', if not, then use old
; cooridinates. This must be done before coordinate normalization in case we
; are going to use the last raw coordinates
;
; This routine is called directly from the device dependent routine before
; calling the locator engine.
;
; note: box_flags bit BOX_SMOOTH should be ON if calling to smooth contact pts
;
;  bx = dcb
;  di = box struc
; returns
;  cx == 0 in the box, New coordinates updated to last values
;     != 0 out of the box
;------------------------------------------------------------------------------
public Loc_BoxFilter
Loc_BoxFilter proc
  xor  cx,cx

  mov  eax, [bx].dcb_LocNewX      ; check if x is in the box
  sub  eax, [di].box_LocLastX
  .if  s
     neg eax
  .endif
  .if <[di].box_Size lt eax>
     inc  cx
  .endif

  mov  eax, [bx].dcb_LocNewY      ; check if y is in the box
  sub  eax, [di].box_LocLastY
  .if  s
     neg eax
  .endif
  .if <[di].box_Size lt eax>
     inc cx
  .endif

; if its out of the box, update the box for the next area

  .if <nonzero cx>
     mov  eax, [bx].dcb_LocNewX
     mov  [di].box_LocLastX, eax
     mov  eax, [bx].dcb_LocNewY
     mov  [di].box_LocLastY, eax

; if its in the box, then use the
; old raw coordinates so the box does not drift.
  .elseif <bit [di].box_flags nz BOX_SMOOTH>
     mov  eax, [di].box_LocLastX
     mov  [bx].dcb_LocNewX, eax
     mov  eax, [di].box_LocLastY
     mov  [bx].dcb_LocNewY, eax
  .endif
  ret
Loc_BoxFilter endp

;------------------------------------------------------------------------------
; This routine is called directly from the device dependent routine before
; calling the locator engine. This routine can filters out proximity
; that do not change, for example, a pen left on the digitizer.
;
; note: box_flags bit BOX_SMOOTH should probably be off for filtering prox pts
;
; Inorder of this to work right, the caller should be calling Loc_ProxFilterTC
; on each timer tick from the device dependent tick count routine.
;
;  bx = dcb
;  di = box structure
; returns
;  cx == 0 ignore proximity point
;     != 0 pass on prox point
;------------------------------------------------------------------------------
public Loc_ProxFilter
Loc_ProxFilter proc
  mov [di].box_ClearCnt, 0             ; used to clear box after prox pts
  call Loc_BoxFilter
  .if <nonzero cx>     ; out of the box
     mov  [di].box_TickCount,0
  .else
     mov  ax,[di].box_TickCount
     .if  <ax lt [di].box_TickLimit>
        inc cx
     .endif
  .endif
  ret
Loc_ProxFilter endp

;------------------------------------------------------------------------------
; This routine is called directly from the device dependent routine from
; the device dependent tick routine. It works with Loc_ProxFilter to filter
; out proximity points that do not change.
;
;  bx = dcb
;  di = box structure
; returns
;------------------------------------------------------------------------------
public Loc_ProxFilterTC
Loc_ProxFilterTC proc
  mov cx,[di].box_ClearCnt
  inc cx
  .if <cx lt [bx].dcb_TimeoutLimProx> ; haven't seen a prox latly
     mov  [di].box_ClearCnt,cx
     mov  ax,[di].box_TickCount
     .if  <ax lt [di].box_TickLimit>
        inc [di].box_TickCount
     .endif
  .else
     mov  [di].box_LocLastX, -1     ; make sure next prox is not 'in the box'
  .endif
  ret
Loc_ProxFilterTC endp
.286p

CSEG ends
;---- INITIALIZATION ROUTINES -------------------------------------------------
;
; note: this code is truncated from the driver after the INIT command returns
;       to OS/2
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Initialize engine
;  bx = dcb
;------------------------------------------------------------------------------
CSEGI segment
public Loc_Init
Loc_Init proc
  mov  [bx].dcb_LocLastState, STATE_CLEAR
  mov  [bx].dcb_StateTimeout,0
  mov  [bx].dcb_@Dev_DTTick,  offset Loc_Tick

; set the following default handlers

  .if <[bx].dcb_@Dev_ForceClear eq 0>
     mov  [bx].dcb_@Dev_ForceClear, offset Loc_ForceClear
  .endif
  .if <[bx].dcb_@Adjust eq 0>
     mov  [bx].dcb_@Adjust,         offset AdjustCoords
  .endif

; do some error checking on the device dependent set up

  .386p
  mov  si,[bx].dcb_@RegCaps
  lea  di, [bx].dcb_Xtrans          ; check X extents
  call Loc_chk_exts
  .if  <[si].lcap_dev_x_extent eq 0>
     mov   [si].lcap_dev_x_extent, eax
     PANIC PANIC_EXTZERO
  .endif
  lea  di, [bx].dcb_Ytrans          ; check Y extents
  call Loc_chk_exts
  .if  <[si].lcap_dev_y_extent eq 0>
     mov   [si].lcap_dev_y_extent, eax
     PANIC PANIC_EXTZERO
  .endif

  mov ax,[si].lcap_sample_rate      ; check rates
  .if <zero ax>
     mov   ax,FAKE_SAMPLE_RATE
     mov   [si].lcap_sample_rate,ax
     PANIC PANIC_RATEZERO
  .endif
  .if <[si].lcap_max_sample_rate eq 0>
     mov   [si].lcap_max_sample_rate,ax
     PANIC PANIC_RATEZERO
  .endif
  .286p
  ret
Loc_Init endp

;------------------------------------------------------------------------------
; check extents
;  di = trn
; returns
;  eax = default extent
;------------------------------------------------------------------------------
public Loc_chk_exts
Loc_chk_exts proc
  .386p
  mov eax,[di].trn_ext_max_PM
  .if <zero eax>
     mov   eax, FAKE_EXTENT
     mov   [di].trn_ext_max_PM, eax
     PANIC PANIC_EXTZERO
  .endif
  .if <[di].trn_ext_max eq 0>
     mov   [di].trn_ext_max, eax
     PANIC PANIC_EXTZERO
  .endif
  .if <[di].trn_ext_adj eq 0>
     mov   [di].trn_ext_adj, eax
     PANIC PANIC_EXTZERO
  .endif
  .if <[di].trn_ext_adj_default eq 0>
     mov   [di].trn_ext_adj_default, eax
     PANIC PANIC_EXTZERO
  .endif
  .if <[di].trn_ext_adj_calibrated eq 0>
     mov   [di].trn_ext_adj_calibrated, eax
     PANIC PANIC_EXTZERO
  .endif
  .286p
  ret
Loc_chk_exts endp

CSEGI ends

end
