; kern_wasm.asm
;
; Open Watcom WASM/MASM-syntax port of the old TASM IDEAL kern.asm.
; Intended for 16-bit DOS large memory model builds on Linux with Open Watcom v2.
;
; Keep kern.asm as the historical TASM source and use this file for the
; reproducible Open Watcom build.

.286
.model large

.data
enterIPX dd 0

.code

public  _IPXinit
public  _IPXopen_socket
public  _IPXclose_socket
public  _IPXlisten
public  _xmemmove
public  _Net_Call
public  _C32_LoadNios_Probe
public  _C32_GetFunc_Probe
public  _C32_CallVersion_Nios_Probe
public  _C32_MapLock_Probe
public  _C32_NCP87_Raw_Probe
public  _Net_Call_VLM_Raw
public  _Net_Call_NWCVLMREQ

_IPXinit proc far
        push    bp
        mov     bp, sp
        push    ds
        push    si
        push    di

        mov     ax, 7A00h
        int     2Fh
        cmp     al, 0FFh
        jne     ipxinit_done

        mov     cx, @data
        mov     ds, cx
        mov     word ptr enterIPX, di
        mov     ax, es
        mov     word ptr enterIPX+2, ax
        mov     al, 1

ipxinit_done:
        mov     ah, 0

        pop     di
        pop     si
        pop     ds
        pop     bp
        ret
_IPXinit endp

_xmemmove proc far
        push    bp
        mov     bp, sp

        ; far procedure stack layout, large model:
        ; [bp+0]  old bp
        ; [bp+2]  return offset
        ; [bp+4]  return segment
        ; [bp+6]  z offset
        ; [bp+8]  z segment
        ; [bp+10] q offset
        ; [bp+12] q segment
        ; [bp+14] nmbr

        cli
        mov     cx, [bp+14]
        or      cx, cx
        jz      xmem_done

        push    ds
        push    si
        push    di
        pushf

        lds     si, dword ptr [bp+10]
        les     di, dword ptr [bp+6]
        cmp     di, si
        jl      xmem_forward

        std
        dec     cx
        add     di, cx
        add     si, cx
        inc     cx
        jmp     xmem_copy

xmem_forward:
        cld

xmem_copy:
        rep     movsb

        popf
        pop     di
        pop     si
        pop     ds

xmem_done:
        pop     bp
        sti
        ret
_xmemmove endp

_IPXopen_socket proc far
        push    bp
        mov     bp, sp
        push    ds
        push    si
        push    di

        ; int IPXopen_socket(UI sock, int live)
        mov     ax, [bp+8]       ; live
        mov     dx, [bp+6]       ; sock
        mov     bx, @data
        mov     ds, bx
        mov     bx, 0
        call    dword ptr enterIPX

        cmp     al, 0FFh
        jne     ipxopen_not_already
        mov     ax, -1           ; socket already open
        jmp     ipxopen_done

ipxopen_not_already:
        cmp     al, 0FEh
        jne     ipxopen_ok
        mov     ax, -2           ; socket table full
        jmp     ipxopen_done

ipxopen_ok:
        mov     ax, dx

ipxopen_done:
        pop     di
        pop     si
        pop     ds
        pop     bp
        ret
_IPXopen_socket endp

_IPXclose_socket proc far
        push    bp
        mov     bp, sp
        push    ds
        push    si
        push    di

        ; void IPXclose_socket(UI sock)
        mov     dx, [bp+6]
        mov     bx, @data
        mov     ds, bx
        mov     bx, 1
        call    dword ptr enterIPX

        pop     di
        pop     si
        pop     ds
        pop     bp
        ret
_IPXclose_socket endp

_IPXlisten proc far
        push    bp
        mov     bp, sp
        push    ds
        push    si
        push    di

        ; int IPXlisten(ECB *ecb)
        les     si, dword ptr [bp+6]
        mov     bx, @data
        mov     ds, bx
        mov     bx, 4
        call    dword ptr enterIPX

        pop     di
        pop     si
        pop     ds
        pop     bp
        mov     ah, 0
        ret
_IPXlisten endp

_Net_Call proc far
        push    bp
        mov     bp, sp

        ; int Net_Call(UI func, void *req, void *repl)
        ; [bp+6]  func
        ; [bp+8]  req offset
        ; [bp+10] req segment
        ; [bp+12] repl offset
        ; [bp+14] repl segment
        mov     ax, [bp+6]

        push    ds
        push    si
        push    di
        pushf

        lds     si, dword ptr [bp+8]
        les     di, dword ptr [bp+12]
        int     21h

        popf
        pop     di
        pop     si
        pop     ds
        pop     bp
        mov     ah, 0
        ret
_Net_Call endp

; int Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx,
;                      void *req, void *repl,
;                      UI p1, UI p2, UI p3)
;
; Experimental VLM entry caller.
; INT 2F AX=7A20 returns ES:BX = VLM entry if AX == 0000.
;
; Register setup for VLM entry:
;   AX, BX, CX, DX from function args
;   DS:SI = req
;   ES:DI = repl
;
; Extra stack args pushed before calling VLM entry:
;   p3, p2, p1
;
; For NWCREQUEST/VLM test:
;   AX=function
;   BX=numReqFrags
;   CX=connid
;   DX=numReplyFrags
;   DS:SI=reqFragList
;   ES:DI=replyFragList
;   p1=6, p2=20h, p3=0
_Net_Call_VLM_Raw proc far
        push    bp
        mov     bp, sp
        sub     sp, 4

        push    ds
        push    si
        push    di
        push    es

        mov     ax, 7A20h
        xor     bx, bx
        int     2Fh
        or      ax, ax
        jz      vlm_raw_found

        mov     ax, 88FFh
        jmp     short vlm_raw_done

vlm_raw_found:
        ; save VLM entry ES:BX in stack locals
        mov     [bp-4], bx
        mov     ax, es
        mov     [bp-2], ax

        ; load caller-requested registers
        mov     ax, [bp+6]
        mov     bx, [bp+8]
        mov     cx, [bp+10]
        mov     dx, [bp+12]
        lds     si, dword ptr [bp+14]
        les     di, dword ptr [bp+18]

        push    word ptr [bp+26]
        push    word ptr [bp+24]
        push    word ptr [bp+22]
        call    dword ptr [bp-4]

vlm_raw_done:
        pop     es
        pop     di
        pop     si
        pop     ds

        mov     sp, bp
        pop     bp
        ret
_Net_Call_VLM_Raw endp


; int C32_LoadNios_Probe(UI axfunc, void *outbuf)
;
; 16-bit object, but captures 32-bit ESI and ECX using manual 386 opcodes.
; This keeps the OMF/linker in 16-bit mode while still reading Client32/NIOS
; values returned by:
;   INT 2F AX=D8C1
;
; outbuf:
;   +00 word AX after INT 2F
;   +02 dword ESI after INT 2F
;   +06 dword ECX after INT 2F
;   +0A word BX
;   +0C word CX low
;   +0E word DX
;   +10 word SI low
;   +12 word DS
;   +14 word ES
_C32_LoadNios_Probe proc far
        push    bp
        mov     bp, sp

        push    ds
        push    es
        push    si
        push    di

        ; xor ecx, ecx
        db      66h, 33h, 0C9h
        ; xor esi, esi
        db      66h, 33h, 0F6h

        mov     ax, [bp+6]
        int     2Fh

        push    ds
        push    es
        push    si
        push    cx
        push    bx
        push    dx
        push    ax

        les     di, dword ptr [bp+8]

        ; restore AX result into AX and store word at out+0
        pop     ax
        mov     es:[di+0], ax

        ; Store ESI dword at es:[di+2].
        ; Encoding: ES override + operand-size prefix + MOV r/m32,r32
        ;   mov es:[di+02], esi  = 26 66 89 75 02
        db      26h, 66h, 89h, 75h, 02h

        ; Store ECX dword at es:[di+6].
        ;   mov es:[di+06], ecx  = 26 66 89 4Dh 06
        db      26h, 66h, 89h, 4Dh, 06h

        pop     dx
        pop     bx
        pop     cx

        mov     es:[di+10], bx
        mov     es:[di+12], cx
        mov     es:[di+14], dx

        pop     ax              ; saved SI
        mov     es:[di+16], ax

        pop     ax              ; saved ES
        pop     bx              ; saved DS
        mov     es:[di+18], bx
        mov     es:[di+20], ax

        pop     di
        pop     si
        pop     es
        pop     ds
        pop     bp
        xor     ah, ah
        ret
_C32_LoadNios_Probe endp


; int C32_GetFunc_Probe(char *name, void *outbuf)
;
; 16-bit OMF Client32 function resolver probe.
; This mimics C32BEGINUSE for one function name:
;   INT 2F AX=D8C1
;   save ESI as far pointer to __Nios+8 function resolver
;   push name segment
;   push name offset
;   push 0
;   push 0
;   call far [ESI]
;   add sp,8
;
; outbuf:
;   +00 word load AX from INT2F
;   +02 dword ESI from INT2F
;   +06 dword ECX from INT2F
;   +0A word resolver return AX
;   +0C word resolver return DX
;   +0E word BX
;   +10 word CX
_C32_GetFunc_Probe proc far
        push    bp
        mov     bp, sp
        sub     sp, 4

        push    ds
        push    es
        push    si
        push    di

        ; clear ECX/ESI
        db      66h, 33h, 0C9h
        db      66h, 33h, 0F6h

        mov     ax, 0D8C1h
        int     2Fh

        ; save ESI dword to [bp-4]
        db      66h, 89h, 76h, 0FCh

        push    ax              ; save load AX

        ; call resolver only if AX == 0
        or      ax, ax
        jne     c32get_store_fail

        push    word ptr [bp+8] ; name segment
        push    word ptr [bp+6] ; name offset
        push    0
        push    0
        call    dword ptr [bp-4]
        add     sp, 8

        jmp     short c32get_store

c32get_store_fail:
        xor     dx, dx
        xor     ax, ax

c32get_store:
        push    dx
        push    ax

        les     di, dword ptr [bp+10]

        pop     ax              ; resolver AX
        pop     dx              ; resolver DX
        pop     bx              ; load AX saved in BX temporarily

        mov     es:[di+0], bx

        ; Store ESI dword at out+2: ES override + operand prefix
        db      26h, 66h, 89h, 75h, 02h

        ; Store ECX dword at out+6
        db      26h, 66h, 89h, 4Dh, 06h

        mov     es:[di+10], ax
        mov     es:[di+12], dx
        mov     es:[di+14], bx
        mov     es:[di+16], cx

        pop     di
        pop     si
        pop     es
        pop     ds
        mov     sp, bp
        pop     bp
        xor     ah, ah
        ret
_C32_GetFunc_Probe endp


; int C32_CallVersion_Nios_Probe(void *outbuf)
;
; Safe Client32 version call using the exact d32wrap convention:
;   1) INT 2F AX=D8C1
;   2) use ESI resolver to resolve "CLIENT32GetVersion"
;   3) call ECX trampoline, not the function pointer directly:
;        push 0
;        push 0
;        push fn_seg
;        push fn_off
;        call ECX
;        add sp,8
;
; outbuf:
;   +00 load AX
;   +02 resolver off
;   +04 resolver seg
;   +06 trampoline off
;   +08 trampoline seg
;   +0A fn off
;   +0C fn seg
;   +0E call AX
;   +10 call DX
;   +12 flags
_C32_CallVersion_Nios_Probe proc far
        push    bp
        mov     bp, sp
        sub     sp, 12

        push    ds
        push    es
        push    si
        push    di
        pushf

        ; clear ECX/ESI
        db      66h, 33h, 0C9h
        db      66h, 33h, 0F6h

        mov     ax, 0D8C1h
        int     2Fh

        ; save ESI resolver at [bp-4]
        db      66h, 89h, 76h, 0FCh
        ; save ECX trampoline at [bp-8]
        db      66h, 89h, 4Eh, 0F8h

        push    ax              ; load AX for output
        or      ax, ax
        jne     c32ver_fail

        push    cs
        push    offset c32ver_name
        push    0
        push    0
        call    dword ptr [bp-4]
        add     sp, 8

        ; resolver returns DX:AX function pointer
        mov     [bp-12], ax
        mov     [bp-10], dx

        or      ax, dx
        je      c32ver_fail

        ; d32wrap _CLIENT32GetVersion convention:
        push    0
        push    0
        push    word ptr [bp-10]
        push    word ptr [bp-12]
        call    dword ptr [bp-8]
        add     sp, 8

        pushf
        push    dx
        push    ax
        jmp     short c32ver_store

c32ver_fail:
        xor     dx, dx
        xor     ax, ax
        pushf
        push    dx
        push    ax

c32ver_store:
        les     di, dword ptr [bp+6]

        pop     ax              ; call AX
        pop     dx              ; call DX
        pop     bx              ; flags
        pop     cx              ; load AX

        mov     es:[di+0], cx
        mov     cx, word ptr [bp-4]
        mov     es:[di+2], cx
        mov     cx, word ptr [bp-2]
        mov     es:[di+4], cx
        mov     cx, word ptr [bp-8]
        mov     es:[di+6], cx
        mov     cx, word ptr [bp-6]
        mov     es:[di+8], cx
        mov     cx, word ptr [bp-12]
        mov     es:[di+10], cx
        mov     cx, word ptr [bp-10]
        mov     es:[di+12], cx
        mov     es:[di+14], ax
        mov     es:[di+16], dx
        mov     es:[di+18], bx

        popf
        pop     di
        pop     si
        pop     es
        pop     ds
        mov     sp, bp
        pop     bp
        xor     ah, ah
        ret

c32ver_name db 'CLIENT32GetVersion',0

_C32_CallVersion_Nios_Probe endp


; int C32_MapLock_Probe(void *ptr, UI len, void *outbuf)
;
; Probe d32wrap.o __MapLockFlat / __UnlockFlat:
;   INT 2F AX=D8C1
;   ESI resolver returned by D8C1 is used with command 2 and 3:
;     push len_hi
;     push len_lo
;     push seg
;     push off
;     push 0
;     push 2
;     call ESI          ; returns flat DX:AX
;
;     push len_hi
;     push len_lo
;     push flat_hi
;     push flat_lo
;     push 0
;     push 3
;     call ESI          ; unlock
;
; outbuf:
;   +00 load AX
;   +02 ESI off
;   +04 ESI seg
;   +06 map AX low
;   +08 map DX high
;   +0A unlock AX
;   +0C unlock DX
_C32_MapLock_Probe proc far
        push    bp
        mov     bp, sp
        sub     sp, 8

        push    ds
        push    es
        push    si
        push    di

        ; clear ECX/ESI
        db      66h, 33h, 0C9h
        db      66h, 33h, 0F6h

        mov     ax, 0D8C1h
        int     2Fh

        ; save ESI resolver at [bp-4]
        db      66h, 89h, 76h, 0FCh
        push    ax              ; load AX

        or      ax, ax
        jne     mapflat_fail

        ; MapLockFlat(ptr, len)
        push    0
        push    word ptr [bp+10]    ; len
        push    word ptr [bp+8]     ; ptr seg
        push    word ptr [bp+6]     ; ptr off
        push    0
        push    2
        call    dword ptr [bp-4]
        add     sp, 0cH

        ; save mapped flat DX:AX at [bp-8]
        mov     word ptr [bp-8], ax
        mov     word ptr [bp-6], dx

        ; UnlockFlat(flat, len)
        push    0
        push    word ptr [bp+10]    ; len
        push    dx
        push    ax
        push    0
        push    3
        call    dword ptr [bp-4]
        add     sp, 0cH

        jmp     short mapflat_store

mapflat_fail:
        xor     dx, dx
        xor     ax, ax
        mov     word ptr [bp-8], ax
        mov     word ptr [bp-6], dx

mapflat_store:
        les     di, dword ptr [bp+12]

        mov     bx, ax          ; unlock AX
        mov     cx, dx          ; unlock DX
        pop     ax              ; load AX

        mov     es:[di+0], ax
        mov     ax, word ptr [bp-4]
        mov     es:[di+2], ax
        mov     ax, word ptr [bp-2]
        mov     es:[di+4], ax
        mov     ax, word ptr [bp-8]
        mov     es:[di+6], ax
        mov     ax, word ptr [bp-6]
        mov     es:[di+8], ax
        mov     es:[di+10], bx
        mov     es:[di+12], cx

        pop     di
        pop     si
        pop     es
        pop     ds
        mov     sp, bp
        pop     bp
        xor     ah, ah
        ret
_C32_MapLock_Probe endp


; int C32_NCP87_Raw_Probe(UI connLo, UI connHi,
;                         void *hdr, UI hdrLen,
;                         void *path, UI pathLen,
;                         void *rep0, UI rep0Len,
;                         void *rep1, UI rep1Len,
;                         void *outbuf)
;
; Specialized raw Client32 NCP87/S6 request probe.
; Reproduces d32wrap.o _COMPATNcpRequestReply mechanics:
;   - INT 2F AX=D8C1
;   - resolve COMPATNcpRequestReply via ESI resolver
;   - MapLockFlat each fragment data buffer
;   - build flat 8-byte frag tables
;   - MapLockFlat frag tables and actualReplyLen
;   - call ECX NIOS trampoline with command 8 and COMPATNcpRequestReply pointer
;   - unlock mappings
;
; outbuf:
;   +00 load AX
;   +02 resolver off
;   +04 resolver seg
;   +06 trampoline off
;   +08 trampoline seg
;   +0A function off
;   +0C function seg
;   +0E ret AX
;   +10 ret DX
;   +12 actualReplyLen low
;   +14 actualReplyLen high
_C32_NCP87_Raw_Probe proc far
        push    bp
        mov     bp, sp
        sub     sp, 100

        push    ds
        push    es
        push    si
        push    di

        ; clear ESI/ECX
        db      66h, 33h, 0F6h
        db      66h, 33h, 0C9h

        mov     ax, 0D8C1h
        int     2Fh

        ; save resolver ESI at [bp-84]
        db      66h, 89h, 76h, 0ACh
        ; save trampoline ECX at [bp-88]
        db      66h, 89h, 4Eh, 0A8h

        mov     [bp-2], ax          ; load AX
        or      ax, ax
        jne     c32raw_fail

        ; resolve "COMPATNcpRequestReply"
        push    cs
        push    offset c32raw_name
        push    0
        push    0
        call    dword ptr [bp-84]
        add     sp, 8
        mov     [bp-92], ax
        mov     [bp-90], dx
        or      ax, dx
        jne     c32raw_have_func
        jmp     c32raw_fail

c32raw_have_func:
        ; actualReplyLen local at [bp-52]
        mov     word ptr [bp-52], 0
        mov     word ptr [bp-50], 0

        ; Map hdr data -> [bp-56]
        push    0
        push    word ptr [bp+0eH]
        push    word ptr [bp+0cH]
        push    word ptr [bp+0aH]
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-56], ax
        mov     [bp-54], dx

        ; Map path data -> [bp-60]
        push    0
        push    word ptr [bp+14H]
        push    word ptr [bp+12H]
        push    word ptr [bp+10H]
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-60], ax
        mov     [bp-58], dx

        ; Map reply0 -> [bp-64]
        push    0
        push    word ptr [bp+1aH]
        push    word ptr [bp+18H]
        push    word ptr [bp+16H]
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-64], ax
        mov     [bp-62], dx

        ; Map reply1 -> [bp-68]
        push    0
        push    word ptr [bp+20H]
        push    word ptr [bp+1eH]
        push    word ptr [bp+1cH]
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-68], ax
        mov     [bp-66], dx

        ; Build req flat table at [bp-32], two entries:
        ; entry = flatptr dword + len dword
        mov     ax, [bp-56]
        mov     [bp-32], ax
        mov     ax, [bp-54]
        mov     [bp-30], ax
        mov     ax, [bp+0eH]
        mov     [bp-28], ax
        mov     word ptr [bp-26], 0

        mov     ax, [bp-60]
        mov     [bp-24], ax
        mov     ax, [bp-58]
        mov     [bp-22], ax
        mov     ax, [bp+14H]
        mov     [bp-20], ax
        mov     word ptr [bp-18], 0

        ; Build reply flat table at [bp-48]
        mov     ax, [bp-64]
        mov     [bp-48], ax
        mov     ax, [bp-62]
        mov     [bp-46], ax
        mov     ax, [bp+1aH]
        mov     [bp-44], ax
        mov     word ptr [bp-42], 0

        mov     ax, [bp-68]
        mov     [bp-40], ax
        mov     ax, [bp-66]
        mov     [bp-38], ax
        mov     ax, [bp+20H]
        mov     [bp-36], ax
        mov     word ptr [bp-34], 0

        ; Map req table [bp-32] len 16 -> [bp-72]
        push    0
        push    10H
        push    ss
        lea     ax, -32[bp]
        push    ax
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-72], ax
        mov     [bp-70], dx

        ; Map reply table [bp-48] len 16 -> [bp-76]
        push    0
        push    10H
        push    ss
        lea     ax, -48[bp]
        push    ax
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-76], ax
        mov     [bp-74], dx

        ; Map actualReplyLen [bp-52] len 4 -> [bp-80]
        push    0
        push    4
        push    ss
        lea     ax, -52[bp]
        push    ax
        push    0
        push    2
        call    dword ptr [bp-84]
        add     sp, 0cH
        mov     [bp-80], ax
        mov     [bp-78], dx

        ; Call NIOS trampoline command 8 with COMPATNcpRequestReply pointer.
        push    word ptr [bp-78]        ; actual flat hi
        push    word ptr [bp-80]        ; actual flat lo
        push    word ptr [bp-74]        ; reply table flat hi
        push    word ptr [bp-76]        ; reply table flat lo
        push    0
        push    2                       ; num reply frags
        push    word ptr [bp-70]        ; req table flat hi
        push    word ptr [bp-72]        ; req table flat lo
        push    0
        push    2                       ; num req frags
        push    0
        push    57H                     ; NCP function 87
        push    0
        push    0
        push    word ptr [bp+8]         ; conn high
        push    word ptr [bp+6]         ; conn low
        push    0
        push    8
        push    word ptr [bp-90]        ; function seg
        push    word ptr [bp-92]        ; function off
        call    dword ptr [bp-88]
        add     sp, 28H

        mov     [bp-96], ax
        mov     [bp-94], dx

        ; unlock mapped actual/table/data.  Ignore returns.
        push    0
        push    4
        push    word ptr [bp-78]
        push    word ptr [bp-80]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        push    0
        push    10H
        push    word ptr [bp-74]
        push    word ptr [bp-76]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        push    0
        push    10H
        push    word ptr [bp-70]
        push    word ptr [bp-72]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        push    0
        push    word ptr [bp+20H]
        push    word ptr [bp-66]
        push    word ptr [bp-68]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        push    0
        push    word ptr [bp+1aH]
        push    word ptr [bp-62]
        push    word ptr [bp-64]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        push    0
        push    word ptr [bp+14H]
        push    word ptr [bp-58]
        push    word ptr [bp-60]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        push    0
        push    word ptr [bp+0eH]
        push    word ptr [bp-54]
        push    word ptr [bp-56]
        push    0
        push    3
        call    dword ptr [bp-84]
        add     sp, 0cH

        jmp     short c32raw_store

c32raw_fail:
        mov     word ptr [bp-92], 0
        mov     word ptr [bp-90], 0
        mov     word ptr [bp-96], 0FFFFH
        mov     word ptr [bp-94], 0FFFFH
        mov     word ptr [bp-52], 0
        mov     word ptr [bp-50], 0

c32raw_store:
        les     di, dword ptr [bp+22H]

        mov     ax, [bp-2]
        mov     es:[di+0], ax
        mov     ax, [bp-84]
        mov     es:[di+2], ax
        mov     ax, [bp-82]
        mov     es:[di+4], ax
        mov     ax, [bp-88]
        mov     es:[di+6], ax
        mov     ax, [bp-86]
        mov     es:[di+8], ax
        mov     ax, [bp-92]
        mov     es:[di+10], ax
        mov     ax, [bp-90]
        mov     es:[di+12], ax
        mov     ax, [bp-96]
        mov     es:[di+14], ax
        mov     ax, [bp-94]
        mov     es:[di+16], ax
        mov     ax, [bp-52]
        mov     es:[di+18], ax
        mov     ax, [bp-50]
        mov     es:[di+20], ax

        pop     di
        pop     si
        pop     es
        pop     ds
        mov     sp, bp
        pop     bp
        xor     ah, ah
        ret

c32raw_name db 'COMPATNcpRequestReply',0

_C32_NCP87_Raw_Probe endp


; int Net_Call_NWCVLMREQ(UI flags, void *regblk, UI p1, UI p2, UI p3)
;
; 16-bit wrapper that reproduces the DeveloperNet NWCVLMREQ register-block
; calling convention, but without using Novell globals.
;
; regblk layout, same as dvlmreq.o:
;   +00 SI
;   +02 DS
;   +04 DI
;   +06 ES
;   +08 AX
;   +0A BX
;   +0C CX
;   +0E DX
;
; It calls the VLM entry returned by INT 2F AX=7A20.
; Stack args are pushed as p3,p2,p1, exactly like NWCVLMREQ.
_Net_Call_NWCVLMREQ proc far
        push    bp
        mov     bp, sp
        sub     sp, 4

        push    ds
        push    si
        push    di
        push    es

        mov     ax, 7A20h
        xor     bx, bx
        int     2Fh
        or      ax, ax
        jz      nwcvlm_found

        mov     ax, 88FFh
        jmp     short nwcvlm_done

nwcvlm_found:
        ; save VLM entry ES:BX in [bp-4]
        mov     [bp-4], bx
        mov     ax, es
        mov     [bp-2], ax

        les     bx, dword ptr [bp+8]       ; regblk

        ; Match NWCVLMREQ defaulting:
        ; if !(flags & 2), set regblk.ES to current ES.
        ; We normally pass flags=2, so this is skipped.
        test    word ptr [bp+6], 2
        jne     nwcvlm_skip_es
        mov     ax, es
        mov     word ptr es:[bx+6], ax
nwcvlm_skip_es:

        ; if !(flags & 1), set regblk.DS to current DS.
        test    word ptr [bp+6], 1
        jne     nwcvlm_skip_ds
        mov     ax, ds
        mov     word ptr es:[bx+2], ax
nwcvlm_skip_ds:

        ; Load target registers from regblk.
        mov     ax, word ptr es:[bx+0Ah]
        push    ax                  ; target BX
        mov     ax, word ptr es:[bx+6]
        push    ax                  ; target ES

        mov     ax, word ptr es:[bx+8]
        mov     cx, word ptr es:[bx+0Ch]
        mov     dx, word ptr es:[bx+0Eh]
        mov     si, word ptr es:[bx+0]
        mov     di, word ptr es:[bx+4]
        mov     ds, word ptr es:[bx+2]

        pop     es
        pop     bx

        push    word ptr [bp+10h]   ; p3
        push    word ptr [bp+0eh]   ; p2
        push    word ptr [bp+0ch]   ; p1
        call    dword ptr [bp-4]

        ; Store registers back into regblk.
        push    bx
        push    es

        les     bx, dword ptr [bp+8]
        mov     word ptr es:[bx+8], ax
        pop     ax
        mov     word ptr es:[bx+6], ax
        pop     ax
        mov     word ptr es:[bx+0Ah], ax
        mov     word ptr es:[bx+0Ch], cx
        mov     word ptr es:[bx+0Eh], dx
        mov     word ptr es:[bx+0], si
        mov     word ptr es:[bx+4], di
        mov     word ptr es:[bx+2], ds

        mov     ax, word ptr es:[bx+8]

nwcvlm_done:
        pop     es
        pop     di
        pop     si
        pop     ds

        mov     sp, bp
        pop     bp
        ret
_Net_Call_NWCVLMREQ endp



end
