INCLUDE MACRO
CODE    SEGMENT
        ORG 100H
        ASSUME CS:CODE,DS:CODE
START:
        JMP BEGIN
CUR_PATH        DB '\',64 DUP (0)
FIRST_NEXT      DB 4EH
USAGE           DB 10,13,9,9,'USAGE: QCD [DRIVE] PATH [/S]',10,13
                DB 10,13,9,9,'/S ――― SCAN PATH INFORMATION',10,13,36
DRV_ERR         DB 10,13,9,9,'Invalid drive specification !',10,13,36
INV_PARA        DB 10,13,9,9,'    Invalid parameter !',10,13,36
F_O_ERR         DB 10,13,'NO more files can be open ! Add more FILES="?" in CONFIG.SYS !',10,13,36
F_C_ERR         DB 10,13,9,9,'DWG_QCD.DAT CREATE ERROR !',10,13,36
OVER_MSG        DB 10,13,9,9,'Match directory is too MANY !',10,13,36
DIR_CHANGED_MSG DB 10,10,13,'     Specified directory has been REMOVED or RENAMED !',10,13,36
IS_R_D_MSG      DB 10,13,9,' Specified or Current Dirve is REMOVEABLE !'
                DB 10,10,13,9,9,'QCD only support FIXED DISK.',10,13,36
SP_FLAG         DB 0
DATLEN          DW 0
DATHD           DW 0
DATFN           DB '\DWG_QCD.DAT',0
PATH1           DB '*.*',0
PATH2           DB '..',0
ROOT            DB '\',0
MSG1            DB 10,13,9,'QCD Scan the Drive $'
MSG2            DB ': path information now !',10,13,36
MSG3            DB 10,13,9,9,' No match directory found !',10,13,36
CR           DB 10,10,13,9,'ΥΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΈ'
                DB 10,13,9,'³  Quick Change Directory advanced v2.55  ³'
                DB 10,13,9,'³   (C)opyright DWGsoft Group 1994,1995   ³'
                DB 10,13,9,'ΤΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΎ',10,13,36

PATHPOS         DW 20 DUP (0)
MATCH           DW 0
PATH_NAME       DW 0
NUMBER          DB 13,10,'[A] $'
ASK             DB 10,10,13,'Which directory do you want to enter ? Please press the LETTER in front of it !',10
                DB 10,13,'[ENTER] for first one , [ESC] for QUIT ..'
CUR_DIR         DB '.',0
CUR_DRV         DB 0
LAST_LETTER     DB 'A'
LAST_LETTER2    DB 'a'
DTA_POS         DW DTA_ADDR
DI_END          DW 0
CDROM           DB 0ABH
OLDSIZE         DD 2800


BEGIN:
        PUSH AX
        CALL CHK_MYSELF
        JNC GOON_EXEC
REKEY_LOOP:
        MOV AH,0
        INT 16H
        CMP AH,15H ;'Y'
        JZ GOON_EXEC
        CMP AH,31H ;'N'
        JNZ REKEY_LOOP
        POP AX
        MOV AX,4C05H
        INT 21H

GOON_EXEC:
        DISPSTR CR
        POP AX
        OR AH,AL
        JNZ DRIVE_ERR

DRV_RIGHT:
        GETDRV
        MOV CUR_DRV,AL
        MOV CL,DS:[80H]
        MOV CH,0
        JCXZ GO_ON
        MOV DI,81H
        MOV AL,':'
        REPNZ SCASB
        JNZ GO_ON
        MOV AL,[DI-2]
        CMP AL,32
        JZ DRIVE_ERR
        CMP AL,9
        JZ DRIVE_ERR
        MOV AL,[DI-3]
        CMP AL,32
        JZ GO_ON
        CMP AL,9
        JNZ DRIVE_ERR

GO_ON:
        MOV AX,1500H
        INT 2FH  ;BX=CDROM NUMBER CX=CDROM DRIVE x (E:,F:...) 0=A: 25=Z:
        CMP AL,-1
        JNZ NO_CDROM
        INC CX
        MOV CDROM,CL

NO_CDROM:
        MOV DL,DS:[6CH]
        OR DL,DL
        JNZ DRIVE_IN_P2
        MOV DL,DS:[5CH]

DRIVE_IN_P2:
        CMP DL,1 ;Drive A:
        JZ JMP_IS_REMOVEABLE_DRIVE
        CMP DL,2 ;Drive B:
        JZ JMP_IS_REMOVEABLE_DRIVE
        CMP DL,CDROM
        JZ JMP_IS_REMOVEABLE_DRIVE

        OR DL,DL
        JZ DEFAULT_DRIVE
        MOV AH,0EH
        DEC DL
        INT 21H
        JMP SHORT GO_QCD

DEFAULT_DRIVE:
        GETDRV
        INC AL
        CMP AL,3
        JB JMP_IS_REMOVEABLE_DRIVE
        CMP AL,CDROM
        JZ JMP_IS_REMOVEABLE_DRIVE

        JMP SHORT GO_QCD

JMP_IS_REMOVEABLE_DRIVE:
        JMP IS_REMOVEABLE_DRIVE


DRIVE_ERR:
        DISPSTR DRV_ERR
        MOV AX,4C03H
        INT 21H

GO_QCD:
        MOV SI,80H
        LODSB
        OR AL,AL
        JZ SHOW_USAGE

        LEA BX,STK
        MOV SP,BX
        LEA DX,DTA
        MOV AH,1AH
        INT 21H

PASS_EMPTY:
        MOV CL,AL
        XOR CH,CH
        MOV DI,SI
        MOV AL,'/'
        REPNZ SCASB
        JNZ HHHH
        CMP BYTE PTR [DI],'S'
        JZ SCAN_PATH
        CMP BYTE PTR [DI],'s'
        JZ SCAN_PATH
        DISPSTR INV_PARA
        MOV AX,4C02H
        INT 21H
SHOW_USAGE:
        DISPSTR USAGE
        MOV AX,4C01H
        INT 21H

SCAN_PATH:
        CALL SCANPATH
        JC IS_REMOVEABLE_DRIVE
        MOV SI,81H
        MOV SP_FLAG,1
HHHH:
        MOV CL,DS:[80H]
        XOR CH,CH
KKKK:
        JCXZ ABCD
        DEC CX
        LODSB ;SI=81H
        CMP AL,32
        JZ KKKK
        CMP AL,'/'
        JZ INCSI
        CMP AL,9
        JZ KKKK
        CMP AL,13
        JZ ABCD
        JMP SHORT NAME_BEGIN
ABCD:
        CMP SP_FLAG,0
        JZ SHOW_USAGE
        MOV AX,4C00H
        INT 21H
INCSI:
        INC SI
        DEC CX
        JMP SHORT KKKK

;parameters for here

NAME_BEGIN:
        XOR CX,CX
        DEC SI
        LEA DI,PARA
LP1:
        INC CX
        LODSB
        CMP AL,32
        JZ PARA_END
        CMP AL,'/'
        JZ PARA_END
        CMP AL,13
        JZ PARA_END
        CMP AL,9
        JZ PARA_END
        STOSB
        JMP SHORT LP1

ONLY_SCAN_PATH:
        JMP OK_EXIT

I_D_S_ERR:
        JMP DRIVE_ERR


IS_REMOVEABLE_DRIVE:
        DISPSTR IS_R_D_MSG
        MOV AH,4CH
        INT 21H

PARA_END:
        MOV AL,0
        STOSB
        LEA DI,PARA
        MOV AL,':'
        REPNZ SCASB
        JZ JMP2
        LEA DI,PARA

JMP2:
        MOV SI,DI
        LODSB
        MOV AH,SP_FLAG
        CMP AX,100H
        JZ ONLY_SCAN_PATH
        OR AL,AL
        JNZ DEC_SI
        MOV DL,DS:[5CH]
        MOV AH,0EH
        DEC DL
        INT 21H
        JMP OK_EXIT

DEC_SI:
        DEC SI
        LEA DI,PATH

LP2:
        LODSB
        STOSB
        OR AL,AL
        JNZ LP2

        LEA DX,PATH  ;CONVERT THE LETTERS TO UPPER
        MOV AX,6522H
        INT 21H
        MOV AX,3D00H
        LEA DX,DATFN
        INT 21H
        JNC DATFI_OK
        CMP AL,2 ;FILE NOT FOUND
        JZ CREATE_DATFI

        DISPSTR F_O_ERR
        MOV AX,4C04H
        INT 21H
CREATE_DATFI:
        CALL SCANPATH
        JNC SCANPATH_OK
        JMP IS_REMOVEABLE_DRIVE

SCANPATH_OK:
        MOV AX,3D00H
        LEA DX,DATFN
        INT 21H

DATFI_OK:
        MOV BX,AX
        MOV DATHD,AX

        MOV CX,20000
        LEA DX,DATBUF
        MOV AH,3FH
        INT 21H

        LEA DI,DATBUF
        MOV DATLEN,AX
        MOV CX,AX

        MOV AH,3EH
        INT 21H

FIRST_SEARCH:
        LEA SI,PATH
        LODSW
        CMP AX,5CH
        JZ IS_ROOT
        CMP AX,'..'
        JNZ INIT_DI
        MOV AH,3BH
        LEA DX,PATH2 ;'..'
        INT 21H
        JMP OK_EXIT
IS_ROOT:
        MOV AH,3BH
        LEA DX,ROOT
        INT 21H
        JMP OK_EXIT

INIT_DI:
        MOV DI_END,DI
        MOV CX,DATLEN
        ADD DI_END,CX
SEARCH_MATCH_DIR:
        CMP DI,DI_END
        JB DI_OK
        JMP CHANGE_DIR
DI_OK:
        MOV CX,-1
        LEA SI,PATH
        LODSB
        REPNZ SCASB
        JNZ DO_NOT_FIND
LP3:
        LODSB
        OR AL,AL
        JZ PATH_OK
        CMP [DI],AL
        JNZ SEARCH_MATCH_DIR
        INC DI
        JMP SHORT LP3
PATH_OK:
;EXCLUDE \XXX\DDD\XXX
        PUSH DI
        STD
        MOV CX,65
        MOV AL,10
        REPNE SCASB
        CLD
        MOV DX,DI
        ADD DX,2
        CALL INIT_DX
        POP DI
        JC SEARCH_MATCH_DIR

        LEA DI,PATHPOS
        XOR AX,AX
        MOV CX,20
        REPNZ SCASW
        JNZ DIR_BUF_OVER
        INC MATCH
        MOV [DI-2],DX
        MOV CX,65
        MOV AL,0
        MOV DI,DX
        REPNZ SCASB
        JMP SHORT SEARCH_MATCH_DIR

CHANGE_DIR:
        CALL JUDGE_MATCH_DIR
        CALL INIT_MATCH_DIR

CHANGE_DIR2:
        MOV AH,3BH ;CHDIR
        INT 21H
        JNC OK_EXIT

OK_EXIT_?:
        JNC OK_EXIT
        DISPSTR DIR_CHANGED_MSG
        CALL SCANPATH
OK_EXIT:
        CRLF
        MOV AX,4C00H
        INT 21H

DO_NOT_FIND:
        CMP MATCH,0
        JNZ CHANGE_DIR
        DISPSTR MSG3
        MOV AX,4CFFH
        INT 21H

DIR_BUF_OVER:
        DISPSTR OVER_MSG
        LEA SI,PATHPOS
        LODSW
        MOV DX,AX
        JMP SHORT CHANGE_DIR2

;--------------------

INIT_DX PROC
        MOV DI,DX
        MOV SI,DX
        MOV AX,1225H ;GET ASCZ LEN
        INT 2FH
SCAN_AGAIN:
        LEA SI,PATH
        LODSB
        REPNZ SCASB
CMP_AGAIN:
        LODSB
        OR AL,AL
        JZ FIND_IT
        CMP [DI],AL
        JNZ SCAN_AGAIN
        INC DI
        JMP SHORT CMP_AGAIN
FIND_IT:
        MOV AL,'\'
        REPNZ SCASB
        JNZ DX_OK
        CMP WORD PTR [DI-3],0A0DH
        JZ DX_OK
        STC
        RET
DX_OK:
        CLC
        RET
INIT_DX ENDP

;--------------------

JUDGE_MATCH_DIR PROC
        MOV CX,4 ;JUDGE CONTROL

J_M_D_LOOP:
        PUSH CX
        LEA BX,PATHPOS
        MOV CX,MATCH
JUDGE_LOOP:
        MOV DI,[BX]
        INC DI       ;SKIP '\'
        LEA SI,PATH
        MOV AX,121EH ;COMP TWO ASCZ STRINGS DI:SI ES:DI
        INT 2FH
        JZ IS_EQU
        ADD BX,2
        LOOP JUDGE_LOOP

        MOV CX,MATCH
        LEA BX,PATHPOS
LOOP_1:
        PUSH CX
        MOV DI,[BX]
        MOV AL,13
        MOV CX,65
        REPNZ SCASB

        SUB DI,3
        MOV SI,DI
        INC SI

        LODSB
        STOSB

        LODSW ;AH=0AH AL=0DH
        STOSW
        ADD BX,2
        POP CX
        LOOP LOOP_1

        POP CX
        LOOP J_M_D_LOOP

        JMP SHORT J_M_D_RET
IS_EQU:
        CALL READ_DAT
        ADD SP,4
        DEC DI
        MOV DX,DI
        MOV AH,3BH
        INT 21H
        JMP OK_EXIT_?
J_M_D_RET:
        CALL READ_DAT
        RET
JUDGE_MATCH_DIR ENDP


;--------------------

INIT_MATCH_DIR PROC
        CMP MATCH,1
        JA MORE_THAN_1
        LEA SI,PATHPOS
        LODSW
        MOV DX,AX
        RET
MORE_THAN_1:
        LEA DI,PATHPOS
DISP_MATCH_DIR:
        DISPSTR NUMBER
        MOV AX,[DI]
        MOV PATH_NAME,AX
        MOV AH,3
        MOV BH,0
        INT 10H
        PUSH DI
        DISPASCZ2 PATH_NAME,14
        LEA DI,NUMBER+3
        INC BYTE PTR [DI]
        POP DI
        ADD DI,2
        CMP WORD PTR [DI],0
        JNZ DISP_MATCH_DIR

MATCH_DIR_END:
        MOV AH,3
        MOV BH,0
        INT 10H
        DCS2 ASK,127,26
        MOV AX,MATCH
        ADD LAST_LETTER,AL
        ADD LAST_LETTER2,AL
RE_KEY:
        MOV AH,0
        INT 16H
        CMP AH,1
        JZ IS_ESC
        CMP AL,13
        JZ IS_ENTER
        CMP AL,'A'
        JB RE_KEY
        CMP AL,LAST_LETTER2
        JA RE_KEY
        CMP AL,LAST_LETTER
        JB KEY_OK
        CMP AL,'a'
        JB RE_KEY
KEY_OK:
        CMP AL,'a'
        JB IS_LOWER
        SUB AL,20H
IS_LOWER:
        SUB AL,'A'
        MOV AH,0
        SHL AX,1
        LEA SI,PATHPOS
        ADD SI,AX
        LODSW
        MOV DX,AX
        RET
IS_ESC:
        SETDRV CUR_DRV
        LEA DX,CUR_DIR
        RET
IS_ENTER:
        LEA SI,PATHPOS
        LODSW
        MOV DX,AX
        RET
INIT_MATCH_DIR ENDP

;--------------------
SCANPATH PROC
        DISPSTR MSG1
        MOV AH,19H
        INT 21H
        ADD AL,65
        MOV AH,14
        XOR BH,BH
        INT 10H
        DISPSTR MSG2

        MOV AH,47H
        LEA SI,CUR_PATH+1
        XOR DL,DL
        INT 21H

        MOV AX,4300H
        LEA DX,DATFN
        INT 21H
        JC DWG_QCD_DAT_NOT_EXIST
        MOV AX,4301H
        XOR CX,CX
        INT 21H

DWG_QCD_DAT_NOT_EXIST:
        MOV AH,3CH
        LEA DX,DATFN
        MOV CX,3
        INT 21H
        JNC FILE_CREATE_OK
        DISPSTR F_C_ERR
        ADD SP,2
        MOV AX,4C06H
        INT 21H

FILE_CREATE_OK:
        MOV DATHD,AX
        LEA DI,DATBUF
        XOR AL,AL
        STOSB
        MOV AX,'..'
        STOSW
        MOV AX,0A0DH
        STOSW
        MOV AX,5CH
        STOSW
        MOV AX,0A0DH
        STOSW
        MOV DATLEN,9

        LEA DX,ROOT
        CALL SEARCH_DIR
        MOV AH,40H
        MOV BX,DATHD
        MOV CX,DATLEN
        LEA DX,DATBUF
        INT 21H
        MOV AH,3EH
        INT 21H
        MOV AH,3BH
        LEA DX,CUR_PATH
        INT 21H
SP_RET:
        RET
SCANPATH ENDP


SAVEDTA PROC
        PUSH CX
        PUSH DI
        PUSH SI
        PUSHF
        LEA SI,DTA
        MOV CX,43
        MOV DI,DTA_POS
        CLD
        REP MOVSB
        MOV DTA_POS,DI
        POPF
        POP SI
        POP DI
        POP CX
        RET
SAVEDTA ENDP

;-------------------
LOADDTA PROC
        PUSH CX
        PUSH DI
        PUSH SI
        PUSHF
        LEA DI,DTA
        MOV CX,43
        SUB DTA_POS,43
        MOV SI,DTA_POS
        CLD
        REP MOVSB
        POPF
        POP SI
        POP DI
        POP CX
        RET
LOADDTA ENDP

;-------------------
SEARCH_DIR      PROC
        MOV AH,3BH
        INT 21H
        LEA DX,PATH1 ;'*.*'
        MOV AH,FIRST_NEXT
S_D_LP1:
        MOV CX,17H
        INT 21H
        JC DIR_END1
        MOV AL,DTA+15H
        TEST AL,10H
        JZ SEARCH_NEXT_DIR
        LEA SI,DTA+1EH
        LODSB
        CMP AL,2EH
        JZ SEARCH_NEXT_DIR
        CALL SAVE_PATH_NAME
        CALL SAVEDTA
        MOV FIRST_NEXT,4EH
        LEA DX,DTA+1EH
        CALL SEARCH_DIR
        JMP SHORT ROOT_?
SEARCH_NEXT_DIR:
        MOV AH,4FH
        JMP SHORT S_D_LP1
DIR_END1:
        RET
ROOT_?:
        CMP DTA_POS ,OFFSET  DTA_ADDR
        JZ DIR_END2
        CALL LOADDTA
        MOV FIRST_NEXT,4FH
        LEA DX,PATH2 ;'..'
        CALL SEARCH_DIR
DIR_END2:
        RET
SEARCH_DIR      ENDP

;--------------------

SAVE_PATH_NAME PROC
        MOV AH,47H
        XOR DL,DL
        LEA SI,PARA
        INT 21H
        MOV AL,'\'
        STOSB
        INC DATLEN
SP_LP1:
        INC DATLEN
        LODSB
        STOSB
        OR AL,AL
        JNZ SP_LP1
        LEA SI,DTA+1EH
        DEC DI
        DEC DATLEN
        CMP BYTE PTR [DI-1],'\'
        JZ  SP_LP2
        MOV AL,'\'
        STOSB
        INC DATLEN

SP_LP2:
        INC DATLEN
        LODSB
        STOSB
        OR AL,AL
        JNZ SP_LP2
        MOV AX,0A0DH
        STOSW
        ADD DATLEN,2
        RET
SAVE_PATH_NAME ENDP
           
READ_DAT PROC
        MOV AX,3D00H
        LEA DX,DATFN
        INT 21H

        MOV BX,AX
        MOV AH,3FH
        MOV CX,20000
        LEA DX,DATBUF
        INT 21H

        MOV AH,3EH
        INT 21H
        RET
READ_DAT ENDP

INCLUDE CMPROC

PC      =$
PC      =PC+20000
STK     =PC

DTA     =PC
PC      =PC+43

PARA    =PC
PC      =PC+128

PATH    =PC
PC      =PC+66

DATBUF  =PC
PC      =PC+20000

DTA_ADDR =PC

CODE    ENDS
        END START
