_CURRENTPSP  dw NXDOSBIO
PSP:    ; Program Segment Prefix
        PSP$wInt20      EQU $-PSP 
        PSP_wInt20      db  0CDh, 20h
        PSP$wNextSeg    EQU $-PSP  
        PSP_wNextSeg    dw  0a00h
        PSP$res1        EQU $-PSP  
        PSP_res1        db  0
        PSP$abdispatch  EQU $-PSP  
        PSP_abdispatch  db  5 dup(0)    ; INT 21h
        PSP$pfTerminate EQU $-PSP  
        PSP_pfTerminate dw  0           ; INT 22h
        PSP$pfCtlbrk    EQU $-PSP  
        PSP_pfCtlbrk    dw  0           ; INT 23h
        PSP$pfCritErr   EQU $-PSP  
        PSP_pfCritErr   dw  0           ; INT 24h
        PSP$res2        EQU $-PSP  
        PSP_res2        db  22 dup(0)
        PSP$wParentPsp  EQU $-PSP  
        PSP_wParentPsp  dw  0
        PSP$wEnvSeg     EQU $-PSP  
        PSP_wEnvSeg     dw  0
        PSP$res3        EQU $-PSP  
        PSP_res3        db  46 dup(0)   ; handle table, et al.
        PSP$rFCB_1      EQU $-PSP  
        PSP_rFCB_1      db  16 dup(0ffh); 1st cmd param
        PSP$rFCB_2      EQU $-PSP  
        PSP_rFCB_2      db  20 dup(0ffh); 2nd cmd param
        PSP$bCmdTaillen EQU $-PSP  
        PSP_bCmdTaillen db  0
        PSP$abCmdtail   EQU $-PSP  
        PSP_abCmdtail   db  127 dup(0)  ; Command Line
PSP_SIZE EQU $ - PSP    ; total size 512

; ===========================================================================
Copy_CurrentPSP proc far
; ES = PSP Segment to update
; ===========================================================================
    push dx
    mov  ax, word ptr cs:[_CurrentPSP]
    or   ax, ax
    jz   CCPSPx
Copy_PSP:
         xor  si, si
         xor  di, di
         mov  ds, ax
         mov  cx, (PSP_SIZE / 2)
         rep  movsw
         ;
; The following four lines set up a very basic Program Segment Prefix,
; aka PSP, which provides some information for DOS programs. For
; instance, CD 20 = 'int 20h', or 'return to DOS' -- a program can
; use this code to quit
         mov  byte ptr es:[PSP$wInt20+0], 0cdh ; INT 20h
         mov  byte ptr es:[PSP$wInt20+1], 020h 
         mov  ax, word ptr cs:[_CURRENTPSP]
         mov  word ptr es:[PSP$wParentPsp], ax
         mov  di, es
         sub  di, ax
         sub  word ptr es:[PSP$wNextSeg], di
         ;mov  byte ptr es:[PSP$wNextSeg+2], 0a0h ; always a000h for COM programs
         ;mov  byte ptr es:[PSP$wNextSeg+3], 000h 
CCPSPx:
    pop  dx
    ret
Copy_CurrentPSP endp

; ===========================================================================
New_PSP proc far
; 26h - Create new Program Segment Prefix
; DX = Segment Address
; ===========================================================================
    mov  es, dx
    call Copy_CurrentPSP
    ret
New_PSP endp

; ===========================================================================
Duplicate_PSP proc far
; 55H - UNDOCUMENTED
; DX = Segment of the New PSP
; SI = Value to place in memory size feild
; ===========================================================================
    push dx
    push si
    call New_PSP
    pop  si
    pop  es
    mov  word ptr es:[PSP$wNextSeg], si
    ret
Duplicate_PSP endp


