;       SCCSID = @(#)debiocs.asm        6.1 90/11/17
;      SCCSID = @(#)debiocs.asm 13.11 90/02/10
PAGE    ,132
NAME    DEBIOCS
TITLE   DEBIOCS.ASM - Debug i/o control stuff
.286p

;***    DEBIOCS.ASM
;
;       Debugger I/O control routines
;
; Modification:
;********************************************************************
;82818 ChangeTeam 02/07/95                                    ;82818
;82818     Moving r206 debug .mk command to R207              ;82818
;

.xlist
        include debseg.inc
        include debmac.inc
        include debequ.inc
        include debdesc.inc
        include debinit.inc
.list


DataSegmentStart

Extern DebData,         WORD
Extern DefType,         BYTE
Extern CmdInputBuffer,  BYTE            ; command line buffer
Extern pTXT,            WORD
Extern pTXTstart,       WORD

IFDEF  KDP
Extern fKDPEnabled,     BYTE
Extern fKDPRaw,         BYTE
Extern fKDPPacketStop,  BYTE
Extern fKDPReceived,    BYTE
Extern fKDPPacketMode,  BYTE
ENDIF

Global CursorColumn,    BYTE,   0       ; cursor column
Static UnGetChar,       BYTE,   0       ; !0 == char to get on next inchr
Static fLower,          BYTE,   0       ; !0 force lower case output

DataSegmentEnd

CodeSegmentStart

Extern  CmdBreak, NEAR
Extern  perr, NEAR

;***    LowerCaseOn - force lower case display
;
;       Forces lower case display if INIT_DISLWR flags is set.
;
;       ENTRY   NONE
;
;       EXIT    NONE
;
;       USES    Flags
;
        assumeDATA <ds, es, ss>

DefProc LowerCaseOn, NEAR, PUBLIC
        test    DebData.InitFlag,INIT_DISLWR
        jz      short lcox
        mov     [fLower],1
lcox:
EndProc

;***    LowerCaseOff - allows case sensitive output again
;
;       ENTRY   NONE
;
;       EXIT    NONE
;
;       USES    NONE
;
        assumeDATA <ds, es, ss>

DefProc LowerCaseOff, NEAR, PUBLIC
        mov     [fLower],0
EndProc

;***    inbuf
;
;       Get input line. Convert all characters NOT in quotes
;       to upper case.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   Flags
;
        assumeDATA <ds, es, ss>

DefProc inbuf, NEAR, PUBLIC

        IFDEF   KDP
        cmp     fKDPRaw,0               ; if (raw command)
        je      inb1
        SaveReg <ax,bx,cx,dx>
        Ccall   KDPRawInput             ;  KDPRawInput();
        RestReg <dx,cx,bx,ax>
        jmp     inb2
inb1:                                   ; else
        ENDIF

        call    rbufin                  ;  rbufin();
        Pcall   crlf
inb2:
        push    si
        mov     si,dataOFFSET CmdInputBuffer
        Pcall   StrUpr
        pop     si
        mov     pTXT,dataOFFSET CmdInputBuffer
        mov     pTXTstart,dataOFFSET CmdInputBuffer
EndProc

;***    StrUpr
;
;       Convert all characters not in quotes or double quotes to
;       upper case.
;
;       ENTRY:  (SI) = pointer to string in debugger data segment.
;
;       EXIT:   NONE
;
;       USES:   Flags
;
        assumeDATA <ds, es, ss>

DefProc StrUpr, NEAR, PUBLIC
        push    ax
        push    si

stp1:   lodsb
        Pcall   upper
        mov     [si - 1],al
        or      al,al
        jz      stp3
        Pcall   CheckString
        jne     stp1

        mov     ah,al
stp2:   lodsb
        or      al,al
        jz      stp3
        cmp     al,ah
        jne     stp2
        cmp     ah,[si]         ; check if two quotes in a row
        jne     stp1
        inc     si
        jmp     short stp2

stp3:   pop     si
        pop     ax
EndProc

;***    upper
;
;       Convert character to upper case
;
;       Entry:  AL = character to convert.
;
;       Exit:   AL = character upper case.
;
;       Uses:   AL, FLAGS
;
        assumeDATA <ds, es, ss>

DefProc upper, NEAR, PUBLIC
        cmp     al,'a'
        jb      short upr1
        cmp     al,'z'
        ja      short upr1
        add     al,"A"-"a"              ; Convert to upper case
upr1:
EndProc

;***    lower - Convert character to lower case.
;
;       Entry:  AL = character to convert.
;
;       Exit:   AL = character lower
;
;       Uses:   AL, FLAGS
;
        assumeDATA <ds, es, ss>

DefProc lower, NEAR, PUBLIC
        test    [DebData].InitFlag,INIT_DISLWR
        jz      short lwrx
        cmp     al,'A'
        jb      short lwrx
        cmp     al,'Z'
        ja      short lwrx
        sub     al,'A' - 'a'            ; Convert to lower case
lwrx:
EndProc

;***    rbufin
;
;       Read buffer in
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc rbufin, NEAR, LOCAL
        push    ax
        push    si
        push    cx

rbf1:   xor     cx,cx
        mov     si,dataOFFSET CmdInputBuffer
rbf2:   Pcall   waitchr
        cmp     al,CR
        je      rbf8
        cmp     al,BS
        je      rbf3
        cmp     al,DEL
        je      rbf3
        cmp     al,ESCCHR
        je      rbf5
        cmp     al,01h                  ; ctrl-A - repeat command
        je      rbf7
        Pcall   putbuf                  ; put character into buffer
        jmp     short rbf2

rbf3:   jcxz    rbf1                    ; backspace a char
        mov     al,BS
        Pcall   putchar
        dec     si
        dec     cx
        jmp     short rbf2

rbf5:   jcxz    rbf1                    ; cancel buffer
rbf6:   mov     al,BS
        Pcall   putchar
        loop    rbf6
        jmp     rbf1

rbf7:   mov     al,[si]                 ; repeat command
        or      al,al
        je      rbf8
        Pcall   putbuf
        jmp     short rbf7

rbf8:   Pcall   putchar                 ; return
        mov     byte ptr [si],0
        pop     cx
        pop     si
        pop     ax
EndProc

;***    putbuf - put character in line buffer.
;
;       Puts character into line buffer and checks for full.
;
;       ENTRY:  AL = character
;               SI = buffer pointer
;               CX = current number of characters
;
;       EXIT:   SI = new buffer pointer
;
;       USES:   AL, SI, CX, Flags
;
        assumeDATA <ds, es, ss>

DefProc putbuf, NEAR, LOCAL
        cmp     cx,CMDLINELEN
        jae     ptb1
        cmp     al,' '          ; only allow printable characters
        jb      ptb2            ;
        cmp     al,7eh          ;
        ja      ptb2            ;
        Pcall   putchar
        mov     [si],al
        inc     si
        inc     cx
        jmp     short ptb2

ptb1:   mov     al,BEL
        Pcall   putchar
ptb2:

EndProc

;***    prtstr
;
;       Prints a string out to console, used by the putstr macro.
;
;       ENTRY:  (Addr) = address of string terminated by a NULL
;
;       EXIT:   NONE
;
;       USES:   NONE
;
        assumeDATA <ds, es, ss>

DefProc prtstr, NEAR, PUBLIC

ArgVar  Addr, WORD

BeginProc
        push    dx
        mov     dx,Addr
        Pcall   rprbuf
        pop     dx
EndProc

;***    rprbuf
;
;       Writes a string out to console
;
;       ENTRY:  (DX) = address of string terminated by a NULL
;
;       EXIT:   NONE
;
;       USES:   NONE
;
        assumeDATA <ds, es, ss>

DefProc rprbuf, NEAR, PUBLIC
        pushf
        push    ax
        push    si
        mov     si,dx

rpr1:   cld
        lodsb
        or      al,al
        jz      rpr2
        Pcall   putchar
        jmp     short rpr1

rpr2:   pop     si
        pop     ax
        POPFF
EndProc

;***    OutAddrOff
;
;       Pcall OutAddrOff, <AddrPtr, OffAddr.LowWord, OffAddr.HighWord>
;
;       ENTRY:  (AddrPtr) = Pointer to AddrS Structure to print
;               (OffAddr) = Value to add to above AddrS
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc OutAddrOff, NEAR, PUBLIC

ArgVar  AddrPtr, WORD
ArgVar  OffAddr, DWORD
LocVar  TmpAddr, <size AddrS>

BeginProc
        SaveReg <ax, bx>
        mov     ax,AddrPtr              ; (AX) = AddrS pointer
        lea     bx,TmpAddr              ; (BX) = Temporary AddrS pointer
        Pcall                       CopyAddr, <ax, bx>
        Pcall   AddAddr, <OffAddr.LowWord, OffAddr.HighWord>
        Pcall   OutAddrS, <bx>
        RestReg <bx, ax>
EndProc

;***    OutAddrS
;
;       Pcall OutAddrS, <AddrPtr>
;
;       ENTRY:  (AddrPtr) = Pointer to AddrS Structure to print
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc OutAddrS, NEAR, PUBLIC

ArgVar  AddrPtr, WORD
LocVar  Buffer,  64

BeginProc
        SaveReg <ax, bx, cx, dx>
        lea     bx,Buffer                       ; (BX) = pointer to buffer
        mov     ax,FMT_ADDR_SEG                 ; (AX) = format flags
        test    DebData.InitFlag,INIT_ENV386    ; check 386 env flag
        jz      oar1
        or      ax,FMT_ADDR_32ENV               ; (AX) = format 32 bit offset
oar1:   Ccall   fmtaddr, <bx, AddrPtr, ax>
        lea     dx,Buffer
        Pcall   rprbuf                          ; print buffer out
        RestReg <dx, cx, bx, ax>
EndProc

;***    OutColonDword
;
;       Prints an dword in the format ssss:oooo.
;
;       Pcall OutColonDword, <Data>
;
;       Entry:  (Data)  = address to print.
;
;       Exit:   NONE
;
;       Uses:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc OutColonDword, NEAR, PUBLIC

ArgVar  Data, DWORD

BeginProc
        SaveReg <ax, dx>
        mov     dx,Data.HighWord
        Pcall   out16
        mov     al,":"
        Pcall   putchar
        mov     dx,Data.LowWord
        Pcall   out16
        RestReg <dx, ax>
EndProc

;***    Out32
;
;       Print data in dword hex format.
;
;       ENTRY:  AX, DX = value to print
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc Out32, NEAR, PUBLIC
        Pcall   OutRadix, <dx, ax, 16, 8, "0">
EndProc

;***    Out24
;
;       Print data in 24 bit hex format.
;
;       ENTRY:  AL, DX = value to print
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc Out24, NEAR, PUBLIC
        Pcall   OutRadix, <dx, ax, 16, 6, "0">
EndProc

;***    Out20
;
;       Print data in 20 bit hex format.
;
;       ENTRY:  AL, DX = value to print
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc Out20, NEAR, PUBLIC
        Pcall   OutRadix, <dx, ax, 16, 5, "0">
EndProc

;***    out16
;
;       Print out 16-bit value in DX in hex
;
;       ENTRY:  DX = value to print
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc out16, NEAR, PUBLIC
        Pcall   OutRadix, <dx, 0, 16, 4, "0">
EndProc

;***    hex
;
;       Output byte in AL as two hex digits
;
;       ENTRY:  AL = byte to print.
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc hex, NEAR, PUBLIC
        Pcall   OutRadix, <ax, 0, 16, 2, "0">
EndProc

;***    OutHex
;
;       Outputs (AX:DX) as a hex number with no padding.
;
;       ENTRY:  (AX:DX) = data to print.
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc OutHex, NEAR, PUBLIC
        Pcall   OutRadix, <dx, ax, 16, 0, 0>
EndProc

;***    OutRadix
;
;       Output data to console in any radix.
;
;       Pcall   OutRadix, <Data.LowWord,Data.HighWord,Radix,PadWidth,PadChar>
;
;       ENTRY:  (Data) = dword data to print.
;               (Radix) = word base to print data in.
;               (PadWidth) = byte field width. If negative left justify the
;                         padding and if positive right justify (normal).
;               (PadChar) = character used to pad data less than field width.
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc OutRadix, NEAR, PUBLIC

ArgVar  Data, DWORD
ArgVar  Radix, WORD
ArgVar  PadWidth, WORD
ArgVar  PadChar, WORD
LocVar  Buffer, 64

BeginProc
        SaveReg <ax, bx, dx>
        lea     bx,Buffer               ; (BX) = buffer to put result
        xor     ax,ax                   ; (AX) = right justify flag
        mov     dx,PadWidth             ; (DX) = pad width
        or      dx,dx                   ; if field zero, then no padding
        jns     orx1                    ; jump if positive
        neg     dx                      ; get absolute value
        not     ax                      ; (AX) = left justify flag
orx1:   Ccall   fmtnum, <bx,Data.LowWord,Data.HighWord,Radix,dx,dx,PadChar,ax>
        lea     dx,Buffer
        Pcall   rprbuf
        RestReg <dx, bx, ax>
EndProc

;***    fmtnum
;
;       Format data in any radix.
;
;       EndPtr = fmtnum(BufPtr,Data,Radix,PadWidth,Precision,PadChar,LeftJust);
;
;       ENTRY:  (BufPtr) = word offset to buffer to put number.
;               (Data) = dword data to print.
;               (Radix) = word base to print data in.
;               (PadWidth) = minimum field width.
;               (Precision) = maximum field width.
;               (PadChar) = character used to pad data less than field width.
;               (LeftJust) = if 0, right justify result, !0 left justify.
;
;       EXIT:   (AX) = end of string (points to null)
;
;       USES:   AX, FLAGS
;
;       Uses C calling convention.
;
        assumeDATA <ds, es, ss>

DefProc fmtnum, NEAR, PUBLIC, C

ArgVar  BufPtr, WORD
ArgVar  Data, DWORD
ArgVar  Radix, WORD
ArgVar  PadWidth, WORD
ArgVar  Precision, WORD
ArgVar  PadChar, BYTE
ArgVar  LeftJust, BYTE
LocVar  FmtBuf, 64                      ; format buffer

BeginProc
        SaveReg <dx, si, di>
        xor     si,si                   ; si = buffer index

;       Loop converting the data to ascii

frx1:   mov     ax,Data.HighWord        ; divide high word of divisor
        xor     dx,dx
        div     Radix
        mov     Data.HighWord,ax        ; save high word of quotient

        mov     ax,Data.LowWord         ; divide low word of divisor
        div     Radix
        mov     Data.LowWord,ax         ; save low word of quotient

        mov     al,dl                   ; get remainder
        cmp     al,10
        jb      frx2
        add     al,"A" - "0" - 10       ; convert remainder to character
        test    [DebData].InitFlag,INIT_DISLWR
        jz      short frx2
        sub     al,'A' - 'a'            ; Convert to lower case

frx2:   add     al,"0"
        mov     FmtBuf[si],al           ; put character into buffer
        inc     si
        cmp     Data.LowWord,0          ; check if quotient zero
        jne     frx1                    ;
        cmp     Data.HighWord,0         ;
        jne     frx1

;       Trunicate result if too big or pad result if not big enough
;       (SI) = number of characters in buffer

        mov     dx,Precision            ; (DX) = max width
        or      dx,dx                   ; if field zero, then no trunication
        jz      frx3

        cmp     si,dx                   ; if size is greater than field
        jbe     frx3                    ;  width, trunicate size.
        mov     si,dx

frx3:   cmp     LeftJust,0              ; jump if left justify result
        jne     frx5                    ;

        mov     dx,PadWidth             ; (DX) = minimum width
        or      dx,dx                   ; if field zero, then no padding
        jz      frx5

        mov     al,PadChar              ; get pad character
frx4:   cmp     si,dx                   ; put pad characters in until
        jae     frx5                    ;  number of characters is
        mov     FmtBuf[si],al           ;   field width.
        inc     si
        cmp     si,64                   ; don't overflow buffer
        jb      frx4                    ;

;       Now copy the padded number to the output buffer

frx5:   push    si                      ; save buffer index
        mov     di,BufPtr               ; (DI) = output buffer pointer
frx6:   dec     si                      ; move buffer in reverse order
        mov     al,FmtBuf[si]
        stosb
        or      si,si
        jnz     frx6                    ; jump if not end of buffer
        pop     si                      ; restore buffer index

;       Left justify flag result if flag set.

        cmp     LeftJust,0
        je      frx8                    ; jump if right justify result

        mov     al,PadChar              ; (AL) = pad character
        mov     dx,PadWidth             ; (DX) = pad width
frx7:   cmp     si,dx
        jae     frx8                    ; left justify result
        inc     si
        stosb
        jmp     short frx7

frx8:   mov     byte ptr [di],0         ; null terminate string
        mov     ax,di                   ; (AX) = end of string
        RestReg <di, si, dx>
EndProc

;***    CrLfColOne
;
;       Output CR/LF sequence if not at column one
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc CrLfColOne, NEAR, PUBLIC
        cmp     CursorColumn,0          ; if 0, we are already at column one
        je      cco1
        Pcall   crlf
cco1:
EndProc

;***    crlf
;
;       Output CR/LF sequence
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc crlf, NEAR, PUBLIC
        push    ax
        mov     al,CR
        Pcall   putchar
        mov     al,LF
        Pcall   putchar
        pop     ax
EndProc

;***    backup
;
;       Physical backspace - blank, backspace, blank
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc backup, NEAR, PUBLIC
        push    ax
        mov     al,' '
        Pcall   putchar
        mov     al,BS
        Pcall   putchar
        pop     ax
EndProc

;***    tab
;
;       Output the number of blanks in CX
;
;       ENTRY:  (CX) = number of blanks
;
;       EXIT:   NONE
;
;       USES:   CX
;
        assumeDATA <ds, es, ss>

DefProc tab, NEAR, PUBLIC
        Pcall   blank
        loop    tab
EndProc

;***    blank
;
;       Output one space
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc blank, NEAR, PUBLIC
        push    ax
        mov     al," "
        Pcall   putchar
        pop     ax
EndProc

;***    putchar
;
;       Console output of character in AL. No registers affected
;       but bit 7 is reset before output.
;
;       ENTRY:  (AL) = character to print
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc putchar, NEAR, PUBLIC
        or      al,al                   ; don't print nulls
        jz      short pchx              ;
        cmp     [fLower],0
        je      short pch10
        Pcall   lower
pch10:  push    ax
        and     al,7fh
        cmp     al,DEL
        jnz     pch20
        mov     al,BS                   ; DELETE same as backspace
pch20:  Pcall   doconout
        cmp     al,BS
        jnz     pch30
        mov     al," "
        Pcall   doconout
        mov     al,BS
        Pcall   doconout
pch30:  pop     ax
pchx:
EndProc

;******* Defect:82818 *******************
;***    putcharl
;
;       Console output of character in AL. No registers affected
;       but bit 7 is reset before output.
;
;       ENTRY:  (AL) = character to print
;               (CX) = number of times to print character
;
;       EXIT:   NONE
;
;       USES:   FLAGS
;
        assumeDATA <ds, es, ss>

DefProc putcharl, NEAR, PUBLIC
pchl0:  or      al,al                   ; don't print nulls
        jz      short pchlx             ;
        cmp     [fLower],0
        je      short pchl5
        Pcall   lower
pchl5:  push    ax
        and     al,7fh
        cmp     al,DEL
        jnz     pchl6
        mov     al,BS                   ; DELETE same as backspace
pchl6:  Pcall   doconout
        cmp     al,BS
        jnz     pchl7
        mov     al," "
        Pcall   doconout
        mov     al,BS
        Pcall   doconout
pchl7:  pop     ax
pchlx:  loop    pchl0
EndProc
;**** End of 82818 ************************

;***    InitComPort - initialize the com port
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   AX, DX
;
        assumeDATA <ds, es, ss>

DefProc InitComPort, NEAR, PUBLIC
        Pcall   DebCallOut, <DEB_CALLOUT_INIT_COM>
EndProc

;***    doconout
;
;       Do console output
;
;       ENTRY:  (AL) = character
;
;       EXIT:   NONE
;
;       USES:   NONE
;
        assumeDATA <ds, es, ss>

DefProc doconout, NEAR, LOCAL
        push    ax              ; (AL) = character

;       See if ctrl-q or ctrl-s

        Pcall   inchr
        jz      dcn3            ; no characters incoming
        cmp     al,CTRLC        ; ctl-C?
        je      dcn1

        IFDEF   KDP
        cmp     al,KDP_BREAK    ; if (packet break)
        jne     dcna
        cmp     fKDPEnabled,0   ;  if (packets not enabled)
        je      dcnb            ;   skip it
        mov     fKDPPacketStop,TRUE
        jmp     dcn1a
dcna:
        ENDIF

        cmp     al,CTRLS        ; ctl-S?
        je      dcn2            ; no, ignore
dcnb:   Pcall   ungetc
        jmp     short dcn3

dcn1:
        IFDEF   KDP
        mov     fKDPRaw,FALSE
        mov     fKDPPacketMode,FALSE
        mov     fKDPReceived,FALSE
dcn1a:
        ENDIF

        jmp     CmdBreak

;       Have ctrl-s.    wait till we see ctrl-Q or ctrl-C

dcn2:   Pcall   waitchr
        cmp     al,CTRLQ        ; ctl-Q
        jne     dcn2

dcn3:   pop     ax              ; (AL) = character to print

        IFDEF   KDP
        cmp     fKDPRaw,0
        je      dcn3a

        SaveReg <ax,bx,cx,dx>
        Ccall   KDPRawOutput,<ax>               ; if (KDPRawOutput != 0) {
        cmp     ax,0
        RestReg <dx,cx,bx,ax>
        je      dcn3b

        mov     al,KDP_NOEVENT
        Jump    KDPEvent
dcn3a:
        ENDIF

        Pcall   DebCallOut, <DEB_CALLOUT_OUTPUT_CHAR>

dcn3b:

;       Update the cursor column

        cmp     al,BS
        jne     dcn4
        cmp     CursorColumn,0
        je      dcnx            ; jump if already zero
        dec     CursorColumn
        jmp     short dcnx

dcn4:   cmp     al,TABCHR
        jne     dcn5
        and     CursorColumn,11111000b
        add     CursorColumn,7  ; move to next tab stop
        jmp     short dcnx

dcn5:   cmp     al,CR
        jne     dcn6
        mov     CursorColumn,0
        jmp     short dcnx

dcn6:   cmp     al,' '          ; only printable characters are counted
        jb      dcnx
        cmp     al,DEL
        jae     dcnx
        inc     CursorColumn
        jnz     dcnx            ; jump if no byte wrap
        dec     CursorColumn
dcnx:
EndProc

;***    GetEchoChr - get a character and echo
;
;       Console input of single character
;
;       Enter:  NONE
;
;       Exit:   AL = char
;
;       Uses:   AX, Flags
;
        assumeDATA <ds, es, ss>

DefProc GetEchoChr, NEAR, PUBLIC

        IFDEF   KDP
        cmp     fKDPRaw,0               ; if (raw command)
        je      gec1
        SaveReg <bx,cx,dx>
        Ccall   KDPCharInput            ;  KDPRawInput();
        RestReg <dx,cx,bx>
        jmp     gec2
gec1:                                   ; else
        ENDIF
        Pcall   waitchr
gec2:
        Pcall   putchar
EndProc

;***    waitchr - wait for input character
;
;       ENTER:     NONE
;
;       EXIT:   AL = character
;
;       USES:   AX, Flags
;
        assumeDATA <ds, es, ss>

DefProc waitchr, NEAR, PUBLIC
wcr1:   Pcall   inchr
        jz      wcr1

        IFDEF   KDP
        cmp     al,KDP_BREAK
        jne     wcr2
        cmp     fKDPEnabled,0
        je      wcrx
        mov     fKDPPacketStop,TRUE
        jmp     CmdBreak
wcr2:
        ENDIF

        cmp     al,CTRLC
        jne     wcrx

        IFDEF   KDP
        mov     fKDPRaw,FALSE
        mov     fKDPPacketMode,FALSE
        mov     fKDPReceived,FALSE
        ENDIF

        jmp     CmdBreak
wcrx:
EndProc

;***    inchr - input character
;
;       ENTER:  NONE
;
;       EXIT:   if ZR, no characters
;               if NZ, AL = character
;
;       USES:   AX, Flags
;
        assumeDATA <ds>
        ASSUME  ES:NOTHING, SS:NOTHING

DefProc inchr, NEAR, PUBLIC
        Pcall   DebCallOut, <DEB_CALLOUT_SCAN_CHAR>
        jnz     ich1                    ; (AL) = character if NZ
        xor     al,al
        xchg    al,UnGetChar
        or      al,al                   ;  set NZ flag if there is a char
ich1:
EndProc

;***    ungetc - put back input character
;
;       ENTER:  AL = character to put back.
;
;       EXIT:   NONE
;
;       USES:   NONE
;
        assumeDATA <ds>
        ASSUME  ES:NOTHING, SS:NOTHING

DefProc ungetc, NEAR, PUBLIC
        mov     UnGetChar,al
EndProc

;***    EnableNMI
;
;       Make the IBM AT ready for another NMI.
;
;       ENTRY:  (DS) = Debugger's data segment
;
;       EXIT:   NONE
;
;       USES:   Flags
;
        assumeDATA <ds>
        ASSUME  ES:NOTHING, SS:NOTHING

DefProc EnableNMI, NEAR, PUBLIC
        Pcall   DebCallOut, <DEB_CALLOUT_ENABLE_NMI>
EndProc

;***    EnableA20 - switch 20th address line
;
;       This routine is used to enable the 20th address line in
;       the system.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   Flags
;
        assumeDATA <ds, es, ss>

DefProc EnableA20, NEAR, PUBLIC
        Pcall   DebCallOut, <DEB_CALLOUT_ENABLE_A20>
EndProc

;***    RestoreA20Status - restore the orignal A20 status
;
;       This routine is used to restore the previous A20 line
;       status retrived with GetA20Status.
;
;       ENTRY:  NONE
;
;       EXIT:   NONE
;
;       USES:   Flags
;
        assumeDATA <ds, es, ss>

DefProc RestoreA20Status, NEAR, PUBLIC
        Pcall   DebCallOut, <DEB_CALLOUT_RESTORE_A20>
EndProc

IFDEF   KDP
;***    KDPDSend - send a buffer
;
;       This routine is used by the packet communications software
;       to send packets.
;
;       ENTRY:  Addr = pointer to packet buffer
;               Count = length of packet buffer (in bytes)
;
;       EXIT:   NONE
;
        assumeDATA <ds, es, ss>

DefProc KDPDSend, NEAR, PUBLIC, C

ArgVar  Addr,WORD
ArgVar  Count,WORD

BeginProc
        push    cx
        push    si

        mov     al,KDP_START
        Pcall   DebCallOut,<DEB_CALLOUT_OUTPUT_CHAR>

        mov     si,Addr
        mov     cx,Count
kds1:
        lodsb
        Pcall   DebCallOut,<DEB_CALLOUT_OUTPUT_CHAR>
        loop    kds1

        mov     al,KDP_END
        Pcall   DebCallOut,<DEB_CALLOUT_OUTPUT_CHAR>

        pop     si
        pop     cx
EndProc

;***    KDPDReceive - receive a packet
;
;       This routine is used by the packet communications software
;       to receive packets.
;
;       ENTRY:  Addr = pointer to packet buffer
;
;       EXIT:   ax = Count of bytes received
;
        assumeDATA <ds, es, ss>

DefProc KDPDReceive, NEAR, PUBLIC, C

ArgVar  Addr,WORD

BeginProc
        push    cx
        push    di

kdr1:   xor     cx,cx                   ; InPacket = FALSE
                                        ; for (;;) {
kdr2:   Pcall   DebCallOut,<DEB_CALLOUT_SCAN_CHAR>
        jz      kdr2                    ;  al = Input Character

        cmp     al,CTRLC                ;  if al == CTRLC
        jne     kdr3

        mov     fKDPRaw,FALSE
        mov     fKDPPacketMode,FALSE
        mov     fKDPReceived,FALSE
        jmp     CmdBreak                ;   goto CmdBreak

kdr3:   cmp     al,KDP_START            ;  if al == KDP_START {
        jne     kdr4
        mov     di,Addr                 ;   reset buffer
        inc     cx                      ;   InPacket = TRUE
        jmp     kdr2                    ;   continue
                                        ;  }

kdr4:   jcxz    kdr2                    ;  if (!InPacket) continue

        cmp     al,KDP_END              ;  if al == KDP_END {
        je      kdrx                    ;   break
                                        ;  }

kdr5:   test    al,80h                  ;  if (al & 0x80 == 0x00)
        jz      kdr1                    ;   reset count and continue
                                        ;  else
        stosb                           ;   store al
        jmp     kdr2                    ; }

kdrx:
        mov     ax,di                   ; return( count )
        sub     ax,Addr
        pop     di
        pop     cx
EndProc
ENDIF

CodeSegmentEnd

        end
