home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 3 / FREEWARE.BIN / ms_dos / dsort / dstmain.pre < prev    next >
Text File  |  1980-01-02  |  34KB  |  1,072 lines

  1.     page    96,132
  2. ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
  3. ;§                                                                          §
  4. ;§              ディレクトリエントリ  ソート  ユーティリティ                §
  5. ;§                                                                          §
  6. ;§                                     DSORT.EXE  Ver1.11    §
  7. ;§                                                                          §
  8. ;§                   Copyright (C) by 福地 邦雄 1991. All rights reserved.  §
  9. ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
  10.     .MODEL  SMALL,C
  11. ;
  12.     DPB struc
  13. drivenumber     db      ?       ;ドライブ番号
  14. unitnumber      db      ?       ;ユニット番号
  15. sectorlength    dw      ?       ;セクタ長
  16. sectorperalloc  db      ?       ;1クラスタ当たりのセクタ数-1
  17. shiftcount      db      ?       ;1クラスタ当たりのセクタ数の2のべき乗
  18. reservedsector  dw      ?       ;先頭のリザーブセクタ数
  19. numberoffat     db      ?       ;FAT数
  20. directoryentry  dw      ?       ;ルートディレクトリのエントリ数
  21. datastartsector dw      ?       ;データ領域開始セクタ番号
  22. datasector      dw      ?       ;最大クラスタ数(全クラスタ数+1)
  23. fatsector       db      ?       ;1FAT当たりのセクタ数
  24. directorystart  dw      ?       ;ディレクトリ領域開始セクタ番号
  25. todeviceheader  dd      ?       ;デバイスヘッダへのポインタ
  26. mediadescriptor db      ?       ;メディアディスクリプタ
  27. diskchange      db      ?       ;ディスクの交換可能属性
  28. tonextdpb       dd      ?       ;次のDPBへのポインタ
  29. currentcluster  dw      ?       ;カレントクラスタ
  30. reserved        dw      ?       ;リザーブ
  31.     DPB ends
  32. ;
  33. YES     equ     1
  34. NO      equ     0
  35. FAT12   equ     0ff7h
  36. FAT16   equ     0fff7h
  37. direntrysize    equ 20h
  38. ;
  39.     extrn   sweep:word,sortexec:word,recursive:word,dirgather:word
  40.     extrn   dta:dword,srchname:dword,namebuff:dword,namebuffsiz:word
  41.     extrn   dirtype:word,fattype:word,attribute:word,clustcount:word
  42.     extrn   driveno:word,clustsize:word,fatsize:word,dirsize:word
  43.     extrn   fatbuff:word,dirbuff:word,sortbuff:word,sortcount:word
  44.     extrn   drvinf:byte,clustsect:word,sectcount:word,fatdrive:word
  45.     extrn   sortfuncs:word,subchain:word,wildcard:byte,pathbuff:byte
  46.     extrn   usagemsg:byte,entrycount:word,movecount:word,subsearch:word
  47.     extrn   procs:byte,dirover:byte,fatover:byte,veralarm:byte,_vermsgsz:abs
  48.     extrn   bothmsg:byte,sortmsg:byte,movemsg:byte,nothmsg:byte
  49.     extrn   errorno:word,adjustroot:word
  50. ;
  51.     extrn   getargs:near,options:near,usageout:near,abort:near,dosstdout:near
  52.     extrn   dirlist:near,dirfind:near,strcopywild:near
  53.     extrn   dosallocx:near,dirqsort:near,inttoasc0:near
  54. ;
  55.     PUBLIC  main,sortproc,getdirinfo,getdpb,readdirectory,readrootdir
  56.     PUBLIC  readfat,getfat12chain,getfat16chain,readsubdir,selection
  57.     PUBLIC  remainsweep,copyback,filldeleted,writedirectory,checkrootsize
  58.     PUBLIC  dspdirname,dspmsgend,altint23h,critical,breakflag,orgint23h
  59. ;
  60.     .code
  61. ;
  62. ;------------------------------------------------------------------------------
  63. ;   書き込み時のCtrl+C押下によるディレクトリ破壊を防ぐ処理のワーク
  64. ;------------------------------------------------------------------------------
  65. ;
  66. critical    dw  NO
  67. breakflag   dw  NO
  68. orgint23h   dd  0
  69. prgname     db  'DirSort',0     ; これは別に意味なし
  70. ;
  71. ;------------------------------------------------------------------------------
  72. ;
  73. ;   main
  74. ;       ディレクトリエントリソートユーティリティ メインプログラム
  75. ;
  76. ;   dsort   <options>   directory name
  77. ;
  78. ;   IN      ds & es PSP セグメント
  79. ;   OUT     ?
  80. ;
  81. ;------------------------------------------------------------------------------
  82. ;
  83. main        proc    near
  84. ;
  85.     call    getargs                 ; コマンド行パラメータを引き数リストに変換
  86.     @if (zf,on)
  87.         jmp     usageout            ; 引き数なしの時はヘルプメッセージ
  88.     @ifend
  89.     push    ax
  90.     mov     ax,_data                ; DS 設定
  91.     mov     ds,ax
  92. ;
  93.     mov     ah,30h                  ; DOS バージョンチェック
  94.     int     21h
  95.     @if (al,>,3)                    ; 4.00 以上なら未サポート
  96.         mov     cx,word ptr _vermsgsz
  97.         mov     dx,offset veralarm
  98.         jmp     abort
  99.     @ifend
  100. ;
  101.     mov     ax,1000h                ; ディレクトリ名バッファの獲得
  102.     xor     dx,dx                   ; 4KB
  103.     call    dosallocx
  104.     mov     word ptr namebuff+2,ax
  105. ;
  106.     mov     ax,3523h                ; Ctrl+C ベクタ取得
  107.     int     21h
  108.     mov     word ptr cs:orgint23h,bx
  109.     mov     word ptr cs:orgint23h+2,es
  110.     mov     bx,ds                   ; DS セーブ
  111.     mov     es,bx
  112.     mov     ax,2523h                ; Ctrl+C ベクタ置き換え
  113.     mov     dx,offset altint23h     ;
  114.     mov     bx,cs
  115.     mov     ds,bx
  116.     int     21h
  117.     mov     bx,es                   ; DS リストア
  118.     mov     ds,bx
  119.     pop     ax
  120. ;
  121.     call    options                 ; 引き数評価&対象ディレクトリリスト作成
  122.     @if (sortexec,/=,NO),or,(sweep,/=,NO)
  123.         @if (recursive,=,YES)       ; 再帰呼び出しをおこなうか?
  124.             mov     es,word ptr namebuff+2
  125.             mov     bx,800h         ; ディレクトリ名バッファのサイズ変更
  126.             mov     ah,4ah          ; 16KB
  127.             int     21h
  128.             @if (cf,off)
  129.                 add     namebuffsiz,7000h
  130.             @ifend
  131.         @ifend
  132.         push    namebuffsiz         ; パラメータセット
  133.         push    word ptr namebuff
  134.         push    word ptr namebuff+2
  135.         xor     ax,ax
  136.         push    ax
  137.         call    sortproc            ; ディレクトリソート実行
  138.     @ifend
  139. ;
  140.     mov     ax,2523h                ; Ctrl+C ベクタ復元
  141.     lds     dx,cs:orgint23h
  142.     int     21h
  143. ;
  144.     mov     ah,0dh              ; ディスクバッファ リセット
  145.     int     21h
  146. ;
  147.     mov     ax,4c00h                ; プログラム終了
  148.     int     21h
  149. ;
  150. main        endp
  151. ;
  152. ;------------------------------------------------------------------------------
  153. ;
  154. ;   sortproc
  155. ;       ディレクトリソートを実行する
  156. ;
  157. ;   TYPE    near call
  158. ;   IN      sp+2:ディレクトリ名リストアドレス
  159. ;           sp+6:ディレクトリ名バッファの空き領域の先頭
  160. ;           sp+8:ディレクトリ名バッファの空き領域サイズ
  161. ;   OUT     なし
  162. ;   保存レジスタ ds
  163. ;
  164. ;------------------------------------------------------------------------------
  165. ;
  166. sortproc    proc    near    curnameoff,curnameseg,freenameoff,freenamesiz
  167. ;
  168.     mov     di,curnameoff
  169.     mov     es,curnameseg
  170.     @do until
  171.         mov     entrycount,0        ; 処理したエントリのカウンタを初期化
  172.         mov     sortcount,0
  173.         mov     movecount,0
  174.         mov     ah,0dh              ; ディスクバッファ リセット
  175.         int     21h
  176. ;
  177.         call    getdirinfo          ; ディレクトリ情報獲得
  178.         @if (zf,on),L
  179.             mov     di,curnameoff   ; ディレクトリ名表示
  180.             mov     es,curnameseg
  181.             call    dspdirname
  182.             call    readdirectory   ; ディレクトリ読み込み
  183.             @if (zf,on)
  184.                 @if (sortexec,=,YES),S
  185.                     call    selection   ; ソート対象エントリ取り出し
  186.                     @if (ax,>,1)
  187.                         push    ds
  188.                         mov     ax,ds
  189.                         mov     es,ax
  190.                         mov     ax,offset sortfuncs
  191.                         push    ax
  192.                         push    sortcount
  193.                         xor     ax,ax
  194.                         push    ax
  195.                         mov     ds,sortbuff
  196.                         call    dirqsort    ; クイックソート
  197.                         pop ds
  198.                     @ifend
  199.                     @if (sweep,=,YES)
  200.                         call    remainsweep ; ソート対象外エントリを掻き集める
  201.                     @ifend
  202.                     call    copyback    ; ソートしたエントリを戻す
  203.                 @else
  204.                     call    predelete
  205.                     call    remainsweep
  206.                 @ifend
  207.                 call    filldeleted     ; 削除エントリの情報をクリアする
  208.                 mov     cs:critical,YES ; クリティカルセクション開始
  209.                 call    writedirectory  ; ディレクトリ書き込み
  210.                 call    dspmsgend       ; 終了メッセージ表示
  211.                 mov     cs:critical,NO  ; クリティカルセクション終了
  212.                 @if (cs:breakflag,=,YES)    ; Ctrl+Cが押下されたので終了
  213.                     mov     errorno,-1
  214.                     xor     cx,cx
  215.                     xor     dx,dx
  216.                     jmp     abort
  217.                 @ifend
  218.             @ifend
  219.             @if (recursive,=,YES)   ; 再帰呼び出し
  220.                 mov     ah,0dh      ; ディスクバッファ リセット
  221.                 int     21h
  222. ;
  223.                 mov     subsearch,YES   ;
  224.                 mov     di,curnameoff   ; サブディレクトリのリスト獲得
  225.                 mov     es,curnameseg
  226.                 call    strcopywild
  227.                 mov     word ptr srchname,di
  228.                 mov     word ptr srchname+2,es
  229.                 call    dirlist
  230.                 mov     ax,word ptr namebuff
  231.                 @if (ax,/=,freenameoff) ; サブディレクトリ有りの時
  232.                     push    namebuffsiz
  233.                     push    ax
  234.                     push    word ptr namebuff+2
  235.                     push    freenameoff
  236.                     call    sortproc    ; ディレクトリソート再帰実行
  237.                 @ifend
  238.                 mov     si,freenameoff  ; 各ワーク情報を再帰実行から戻す
  239.                 mov     es,freenamesiz
  240.                 mov     namebuffsiz,es
  241.                 mov     word ptr namebuff,si
  242.                 mov     es,curnameseg
  243.                 mov     word ptr es:[si],0
  244.                 mov     subsearch,NO    ;
  245.             @ifend
  246.         @ifend
  247.         mov     di,curnameoff       ; 次の対象ディレクトリへ
  248.         mov     es,curnameseg
  249.         cld
  250.         xor     ax,ax
  251.         mov     cx,-1
  252.       repne scasb
  253.         mov     curnameoff,di
  254.     @doend (byte ptr es:[di],=,0),L ; ディレクトリリストの終了か?
  255. ;
  256.     ret     8
  257. ;
  258. sortproc    endp
  259. ;
  260. ;------------------------------------------------------------------------------
  261. ;
  262. ;   getdirinfo
  263. ;       ディレクトリ及びその所属するドライブの情報を獲得する
  264. ;
  265. ;   TYPE    near call
  266. ;   IN      ds:di = ディレクトリ名
  267. ;   OUT     drvinf = DPBのコピー  その他 ディレクトリ情報
  268. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  269. ;
  270. ;------------------------------------------------------------------------------
  271. ;
  272. getdirinfo  proc    near
  273. ;
  274.     call    dirfind
  275.     @if (zf,on)
  276.         mov     dirtype,ax          ; ディレクトリタイプ ルート/サブ
  277.         mov     subchain,ax         ; FATチェインの先頭
  278.         mov     driveno,dx          ; ドライブ番号
  279.         dec     driveno
  280. ;
  281.         mov     di,offset drvinf    ; Drive Parameter Block 取得
  282.         call    getdpb
  283. ;
  284.         @if (drvinf.datasector,<=,4086),S    ; 12bitFAT/16bitFAT
  285.             mov     fattype,FAT12            ;   v1.00バグ '='が無かった
  286.         @else
  287.             mov     fattype,FAT16
  288.         @ifend
  289.         xor     ax,ax
  290.         mov     al,drvinf.sectorperalloc
  291.         inc     ax
  292.         mov     clustsect,ax        ; 1クラスタ当たりのセクタ数
  293.         mul     drvinf.sectorlength
  294.         mov     clustsize,ax        ; 1クラスタのバイトサイズ
  295.         xor     ax,ax
  296.     @ifend
  297.     ret
  298. ;
  299. getdirinfo  endp
  300. ;
  301. ;------------------------------------------------------------------------------
  302. ;
  303. ;   getdpb
  304. ;       ドライブパラメータブロックをコピーする
  305. ;
  306. ;   TYPE    near call
  307. ;   IN      dl = ドライブ番号 A:1 B:2 ...
  308. ;           ds:di = drive parameter block をコピーする領域のアドレス
  309. ;   OUT     ax = 完了コード
  310. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  311. ;
  312. ;------------------------------------------------------------------------------
  313. ;
  314. getdpb      proc    near    uses bx cx si di ds es
  315. ;
  316.     cld
  317.     mov     ax,ds
  318.     mov     es,ax
  319.     mov     ah,32h                  ; DPBアドレス取得 非公開
  320.     mov     cx,10h
  321.     int     21h
  322. ;
  323.     mov     si,bx
  324.   rep   movsw                       ; DPB コピー
  325.     ret
  326. ;
  327. getdpb      endp
  328. ;
  329. ;------------------------------------------------------------------------------
  330. ;
  331. ;   readdirectory
  332. ;       ディレクトリを読み込む
  333. ;
  334. ;   TYPE    near call
  335. ;   IN      dirtype,driveno,drvinf構造体,fatdrive
  336. ;   OUT     ax = 完了コード     entrycount,clustcount
  337. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  338. ;
  339. ;------------------------------------------------------------------------------
  340. ;
  341. readdirectory   proc    near
  342. ;
  343.     @if (dirtype,=,0),S             ; ルートディレクトリ
  344.         mov     ax,drvinf.directoryentry
  345.         @if (ax,<=,2048),S
  346.             mov     entrycount,ax   ; ディレクトリエントリ数 格納
  347.             mov     adjustroot,NO
  348.             call    readrootdir
  349.         @else
  350.             mov     entrycount,2048 ; ディレクトリエントリ数を2048とする
  351.             mov     adjustroot,YES  ; ルートのエントリ数評価を遅らせる
  352.             call    readrootdir
  353.             call    checkrootsize   ; エントリ数評価
  354.             @if (zf,off)
  355.                 mov     ah,9            ; ルートディレクトリサイズオーバー表示
  356.                 mov     dx,offset dirover
  357.                 int     21h
  358.                 mov     ax,-1
  359.                 jmp     rdirerror
  360.             @ifend
  361.         @ifend
  362.     @else
  363.         mov     ax,driveno          ; サブディレクトリ
  364.         @if (ax,/=,fatdrive)        ; 読み込み済FATと違うドライブ名の時
  365.             xor     ax,ax           ; FATサイズ計算
  366.             mov     al,drvinf.fatsector
  367.             mul     drvinf.sectorlength
  368.             @if (dx,=,1),and,(ax,=,0),or,(dx,=,0),S
  369.                 call    readfat     ; FAT読み込み
  370.             @else
  371.                 mov     ah,9        ; FATサイズオーバー表示
  372.                 mov     dx,offset fatover
  373.                 int     21h
  374.                 mov     ax,-1
  375.                 jmp     rdirerror
  376.             @ifend
  377.         @ifend
  378. ;
  379.         cld                         ; サブディレクトリのクラスタチェインを獲得
  380.         mov     di,offset subchain
  381.         mov     es,fatbuff
  382.         @if (fattype,=,FAT12),S
  383.             call    getfat12chain
  384.         @else
  385.             call    getfat16chain
  386.         @ifend
  387.         mov     clustcount,dx       ; サブディレクトリのクラスタ数を設定
  388.         mov     ax,dx
  389.         mul     clustsize
  390.         mov     cx,32               ; ディレクトリエントリ数 計算 格納
  391.         div     cx
  392.         @if (ax,<=,2048),S
  393.             mov     entrycount,ax
  394.             call    readsubdir      ; サブディレクトリ読み込み
  395.         @else
  396.             mov     ah,9            ; ディレクトリサイズオーバー表示
  397.             mov     dx,offset dirover
  398.             int     21h
  399.             mov     ax,-1
  400.         @ifend
  401.     @ifend
  402. rdirerror:
  403.     test    ax,ax
  404.     ret
  405. ;
  406. readdirectory   endp
  407. ;
  408. ;------------------------------------------------------------------------------
  409. ;
  410. ;   readrootdir
  411. ;       ルートディレクトリの内容をメモリに読み込む
  412. ;
  413. ;   TYPE    near call
  414. ;   IN      drive parameter block 領域      adjustroot
  415. ;   OUT     dirbuff = 読み込んだディレクトリのセグメントアドレス
  416. ;   保存レジスタ bp,ds,es
  417. ;
  418. ;------------------------------------------------------------------------------
  419. ;
  420. readrootdir     proc    near    uses bp
  421. ;
  422.     @if (adjustroot,=,NO),S
  423.         mov     ax,drvinf.datastartsector ; ディレクトリサイズ計算とメモリ獲得
  424.         sub     ax,drvinf.directorystart
  425.     @else
  426.         xor     ax,ax                     ; ルートディレクトリが2048を超えて
  427.         mov     dx,1                      ; いる場合の暫定措置
  428.         div     drvinf.sectorlength
  429.     @ifend
  430.     mov     sectcount,ax
  431.     mul     drvinf.sectorlength
  432.     mov     dirsize,ax
  433.     call    dosallocx
  434.     mov     dirbuff,ax
  435. ;
  436.     push    ds                      ; ルートディレクトリ読み込み
  437.     mov     ax,driveno
  438.     xor     bx,bx
  439.     mov     cx,sectcount
  440.     mov     dx,drvinf.directorystart
  441.     mov     ds,dirbuff
  442.     int     25h
  443.     @if (cf,on)
  444.         xor     cx,cx
  445.         xor     dx,dx
  446.         jmp     abort
  447.     @ifend
  448.     popf
  449.     pop     ds
  450.     xor     ax,ax
  451.     ret
  452. ;
  453. readrootdir     endp
  454. ;
  455. ;------------------------------------------------------------------------------
  456. ;
  457. ;   checkrootsize
  458. ;       ルートディレクトリのエントリ数をチェックする
  459. ;
  460. ;   TYPE    near call
  461. ;   IN      dirbuff = 読み込んだディレクトリのセグメントアドレス
  462. ;   OUT     ax = 0 ディレクトリ数が範囲内    ax /= 0 範囲オーバー
  463. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  464. ;
  465. ;------------------------------------------------------------------------------
  466. ;
  467. checkrootsize   proc    near    uses di es
  468. ;
  469.     xor     di,di                   ; オフセットを0
  470.     mov     es,dirbuff              ; ディレクトリバッファセグメントを取得
  471.     @do until
  472.         @if (byte ptr es:[di],=,0)  ; 最終エントリを発見したかの判定
  473.             xor     ax,ax           ; 有効+削除エントリが64KB未満(範囲内)
  474.             jmp     chrtszfind
  475.         @ifend
  476.         lea     di,[di+direntrysize] ; 次のエントリへ
  477.     @doend (di,=,0)                 ; 64KBひとまわりしたか?
  478.     mov     ax,-1                   ; 扱える範囲を超えている
  479. chrtszfind:
  480.     test    ax,ax
  481.     ret
  482. ;
  483. checkrootsize   endp
  484. ;
  485. ;------------------------------------------------------------------------------
  486. ;
  487. ;   readfat
  488. ;       FATを読み込むための領域を獲得し、FATを読み込む
  489. ;
  490. ;   TYPE    near call
  491. ;   IN      drive parameter block 領域
  492. ;   OUT     fatbuff = 読み込んだFATのセグメントアドレス
  493. ;   保存レジスタ bp,ds,es
  494. ;
  495. ;------------------------------------------------------------------------------
  496. ;
  497. readfat     proc    near    uses bp
  498. ;
  499.     @if (fatdrive,/=,-1)            ; 既に別のFATを読み込み済の時、解放する
  500.         mov     es,fatbuff
  501.         int     21h
  502.         mov     fatdrive,-1
  503.         mov     fatbuff,0
  504.     @ifend
  505.     xor     ax,ax                   ; FAT用領域獲得
  506.     mov     al,drvinf.fatsector
  507.     mul     drvinf.sectorlength
  508.     call    dosallocx
  509.     mov     fatbuff,ax
  510. ;
  511.     push    ds                      ; FAT読み込み
  512.     mov     ax,driveno
  513.     mov     fatdrive,ax
  514.     xor     bx,bx
  515.     xor     cx,cx
  516.     mov     cl,drvinf.fatsector
  517.     mov     dx,drvinf.reservedsector
  518.     mov     ds,fatbuff
  519.     int     25h
  520.     @if (cf,on)
  521.         xor     cx,cx
  522.         xor     dx,dx
  523.         jmp     abort
  524.     @ifend
  525.     popf
  526.     pop     ds
  527.     ret
  528. ;
  529. readfat     endp
  530. ;
  531. ;------------------------------------------------------------------------------
  532. ;
  533. ;   getfat12chain
  534. ;       12ビットFATのチェインをたどって、配列に書き出す。
  535. ;
  536. ;   TYPE    near call
  537. ;   IN      es:オフセット0= FAT領域
  538. ;           ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
  539. ;           番号を格納しておくこと
  540. ;   OUT     dx = チェインの総クラスタ数
  541. ;   保存レジスタ si,bp,ds,es
  542. ;
  543. ;------------------------------------------------------------------------------
  544. ;
  545. getfat12chain   proc    near
  546. ;
  547.     mov     cl,4
  548.     xor     dx,dx
  549.     @do while,(word ptr [di],<,FAT12)
  550.         mov     bx,[di]
  551.         mov     ax,bx
  552.         shr     ax,1
  553.         add     bx,ax
  554.         mov     ax,es:[bx]
  555.         @if (word ptr [di],off,1),S
  556.             and     ax,0fffh
  557.         @else
  558.             shr     ax,cl
  559.         @ifend
  560.         lea     di,[di+2]
  561.         mov     [di],ax
  562.         inc     dx
  563.     @doend
  564.     ret
  565. ;
  566. getfat12chain   endp
  567. ;
  568. ;------------------------------------------------------------------------------
  569. ;
  570. ;   getfat16chain
  571. ;       16ビットFATのチェインをたどって、配列に書き出す。
  572. ;
  573. ;   TYPE    near call
  574. ;   IN      es:オフセット0 = FAT領域
  575. ;           ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
  576. ;           番号を格納しておくこと
  577. ;   OUT     dx = チェインの総クラスタ数
  578. ;   保存レジスタ cx,si,bp,ds,es
  579. ;
  580. ;------------------------------------------------------------------------------
  581. ;
  582. getfat16chain   proc    near
  583. ;
  584.     xor     dx,dx
  585.     @do while,(word ptr [di],<,FAT16)
  586.         mov     bx,[di]
  587.         shl     bx,1
  588.         mov     ax,es:[bx]
  589.         lea     di,[di+2]
  590.         mov     [di],ax
  591.         inc     dx
  592.     @doend
  593.     ret
  594. ;
  595. getfat16chain   endp
  596. ;
  597. ;------------------------------------------------------------------------------
  598. ;
  599. ;   readsubdir
  600. ;       サブディレクトリを読み込む
  601. ;
  602. ;   TYPE    near call
  603. ;   IN      clustcount ディレクトリのクラスタ数
  604. ;   OUT     dirbuff = 読み込んだディレクトリのセグメントアドレス
  605. ;   保存レジスタ cx,si,bp,ds,es
  606. ;
  607. ;------------------------------------------------------------------------------
  608. ;
  609. readsubdir  proc    near
  610.     local cluster:word
  611. ;
  612.     mov     dx,clustcount           ; ディレクトリサイズ計算
  613.     mov     cluster,dx
  614.     mov     ax,clustsect
  615.     mul     dx
  616.     mul     drvinf.sectorlength
  617.     mov     dirsize,ax
  618.     call    dosallocx               ; ディレクトリバッファ獲得
  619.     mov     dirbuff,ax
  620.     xor     bx,bx
  621.     mov     di,offset subchain      ; ディレクトリクラスタチェインの先頭
  622. ;
  623.     push    ds
  624.     mov     ax,ds
  625.     mov     es,ax
  626.     mov     ds,dirbuff
  627.     @do until
  628.         mov     ax,es:[di]          ; ディレクトリクラスタ読み込み
  629.         sub     ax,2
  630.         mov     cx,es:clustsect
  631.         mul     cx
  632.         add     ax,es:drvinf.datastartsector
  633.         mov     dx,ax
  634.         mov     ax,es:driveno
  635.         push    bp
  636.         push    di
  637.         int     25h
  638.         @if (cf,on)
  639.             xor     cx,cx
  640.             xor     dx,dx
  641.             jmp     abort
  642.         @ifend
  643.         popf
  644.         pop     di
  645.         pop     bp
  646.         add     bx,es:clustsize     ; 次のバッファオフセット
  647.         lea     di,[di+2]           ; 次のクラスタ
  648.         dec     cluster             ; カウントダウン
  649.     @doend (zf,on)
  650.     pop ds
  651.     xor     ax,ax
  652.     ret
  653. ;
  654. readsubdir  endp
  655. ;
  656. ;------------------------------------------------------------------------------
  657. ;
  658. ;   selection
  659. ;       読み込んだディレクトリからattributeで指定されたエントリを選択して
  660. ;       ソートバッファに移動する
  661. ;
  662. ;   TYPE    near call
  663. ;   IN      dirbuff = 読み込んだディレクトリのセグメントアドレス その他
  664. ;   OUT     sortbuff = ソート対象を選択・移動したセグメントアドレス
  665. ;   保存レジスタ bp,ds
  666. ;
  667. ;------------------------------------------------------------------------------
  668. ;
  669. selection   proc    near
  670. ;
  671.     mov     ax,dirsize              ; ディレクトリサイズからバッファサイズ
  672.     @if (ax,/=,0),S                 ; 64KB未満
  673.         xor     dx,dx
  674.     @else                           ; 64KB
  675.         mov     dx,1
  676.     @ifend
  677.     call    dosallocx               ; ソートバッファ獲得
  678.     mov     sortbuff,ax
  679.     mov     es,ax
  680.     mov     bx,attribute            ; 選出属性
  681.     mov     dx,entrycount           ; エントリ数
  682.     xor     si,si
  683.     xor     di,di
  684.     @if (dirtype,/=,0)              ; サブディレクトリの時は最初の2つを除外
  685.         sub     dx,2
  686.         mov     si,64
  687.     @ifend
  688. ;
  689.     push    ds
  690.     cld
  691.     xor     ax,ax
  692.     mov     ds,dirbuff
  693.     @do while,(dx,/=,0),and,(byte ptr [si],/=,0)
  694.         @cbegin
  695.         @case (byte ptr [si],=,0e5h),S  ; 削除エントリか?
  696.             mov     byte ptr [si],0     ; 後の処理のために0を書いておく
  697.             lea     si,[si+20h]
  698.         @case (byte ptr [si+0bh],on,bl),S   ; 属性違いか?
  699.             lea     si,[si+20h]
  700.         @other                      ; ソートバッファへ移動
  701.             mov     cx,10h
  702.           rep   movsw
  703.             mov     byte ptr [si-20h],0 ; 移動元に0を書いておく
  704.             @if (byte ptr [di-20h],=,5) ; 名前の頭がE5用のコードなら戻しておく
  705.                 mov     byte ptr [di-20h],0e5h
  706.             @ifend
  707.             inc     ax              ; 移動したエントリ数を加算
  708.         @cend
  709.         dec     dx                  ; カウントダウン
  710.     @doend
  711.     pop     ds
  712.     mov     sortcount,ax            ; 移動したエントリ数を記録
  713.     ret
  714. ;
  715. selection   endp
  716. ;
  717. ;------------------------------------------------------------------------------
  718. ;
  719. ;   predelete
  720. ;       後のremainsweepルーチンのために削除エントリの先頭を00とする
  721. ;
  722. ;   TYPE    near call
  723. ;   IN      entrycount,dirbuff
  724. ;   OUT     なし
  725. ;   保存レジスタ ax,bx,dx,si,bp,ds
  726. ;
  727. ;------------------------------------------------------------------------------
  728. ;
  729. predelete   proc    near
  730. ;
  731.     mov     cx,entrycount
  732.     xor     di,di
  733.     mov     es,dirbuff
  734.     @do until
  735.         @if (byte ptr es:[di],=,0e5h)
  736.             mov     byte ptr es:[di],0
  737.         @ifend
  738.         lea     di,[di+20h]
  739.         dec     cx
  740.     @doend (zf,on)
  741.     ret
  742. ;
  743. predelete   endp
  744. ;
  745. ;------------------------------------------------------------------------------
  746. ;
  747. ;   remainsweep
  748. ;       ソート対象外のエントリをディレクトリバッファの先頭に集める
  749. ;
  750. ;   TYPE    near call
  751. ;   IN      entrycount,dirbuff
  752. ;   OUT     movecount
  753. ;   保存レジスタ ax,bp,ds
  754. ;
  755. ;------------------------------------------------------------------------------
  756. ;
  757. remainsweep proc    near
  758. ;
  759.     cld
  760.     push    ds
  761.     xor     bx,bx
  762.     mov     dx,entrycount           ; ディレクトリのエントリサイズ
  763.     mov     es,dirbuff
  764.     mov     ds,dirbuff
  765.     xor     di,di
  766.     @do while,(byte ptr [di],/=,0),and,(dx,/=,0) ; 最初の空きエントリ位置取得
  767.         lea     di,[di+20h]
  768.         dec     dx
  769.     @doend
  770.     mov     si,di
  771.     @do until
  772.         @do while,(byte ptr [si],=,0),and,(dx,/=,0) ; 次の有効エントリ位置取得
  773.             lea     si,[si+20h]
  774.             dec     dx
  775.         @doend
  776.         @if (dx,/=,0)               ; 終了でなければエントリを頭へ詰める
  777.             inc     bx
  778.             mov     cx,10h
  779.           rep   movsw
  780.             mov     byte ptr [si-20h],0 ; 移動元を空きエントリとする
  781.             dec     dx              ; カウントダウン
  782.             @do while,(byte ptr [di],/=,0)  ; 次の空きエントリ位置取得
  783.                 lea     di,[di+20h]
  784.             @doend
  785.         @ifend
  786.     @doend (dx,=,0)
  787.     pop     ds
  788.     mov     movecount,bx            ; 移動したエントリ数を記録
  789.     ret
  790. ;
  791. remainsweep endp
  792. ;
  793. ;------------------------------------------------------------------------------
  794. ;
  795. ;   copyback
  796. ;       ソートバッファの内容をディレクトリバッファへ書き戻す
  797. ;
  798. ;   TYPE    near call
  799. ;   IN      sortcount,sortbuff,dirbuff
  800. ;   OUT     dirbuff
  801. ;   保存レジスタ    bx,bp,ds
  802. ;
  803. ;------------------------------------------------------------------------------
  804. ;
  805. copyback    proc    near    uses ds
  806. ;
  807.     cld
  808.     mov     dx,sortcount            ; ソートバッファ上のエントリ数
  809.     mov     es,dirbuff
  810.     mov     ds,sortbuff
  811.     xor     si,si
  812.     xor     di,di
  813.     @do while,(dx,/=,0)
  814.         @if (byte ptr es:[di],=,0),S    ; ディレクトリバッファは空きエントリ?
  815.             @if (byte ptr [si],=,0e5h)  ; 名前の頭がE5なら、変換しておく
  816.                 mov     byte ptr [si],05h
  817.             @ifend
  818.             mov     cx,10h          ; コピー
  819.           rep   movsw
  820.             dec     dx              ; カウントダウン
  821.         @else
  822.             lea di,[di+20h]         ; 次のディレクトリバッファエントリへ
  823.         @ifend
  824.     @doend
  825. ;
  826.     mov     ax,ds                   ; ソートバッファの解放
  827.     mov     es,ax
  828.     mov     ah,49h
  829.     int     21h
  830. ;
  831.     ret
  832. ;
  833. copyback    endp
  834. ;
  835. ;------------------------------------------------------------------------------
  836. ;
  837. ;   filldeleted
  838. ;       ディレクトリ中の削除エントリをクリアする
  839. ;
  840. ;   TYPE    near call
  841. ;   IN      dirsize,dirbuff
  842. ;   OUT     なし
  843. ;   保存レジスタ    bx,dx,bp,ds
  844. ;
  845. ;------------------------------------------------------------------------------
  846. ;
  847. filldeleted proc    near
  848. ;
  849.     cld
  850.     mov     ax,0f6h                 ; 埋め込みデータの設定 
  851.     mov     si,dirsize              ; ディレクトリの最終ポイント取得
  852.     mov     es,dirbuff
  853.     @do until
  854.         lea     si,[si-20h]         ; 最終位置から先頭方向へ
  855.         @if (byte ptr es:[si],=,0),S    ; 削除エントリ判定
  856.             mov     es:[si],ah      ; 頭1バイト 0orE5
  857.             mov     cx,1fh          ; 残り31バイトをF6で埋める
  858.             lea     di,[si+1]
  859.           rep   stosb
  860.         @else                       ; 有効エントリが見つかったので
  861.             mov     ah,0e5h         ; それ以後は頭1バイトをE5に変更
  862.         @ifend
  863.     @doend (si,=,0)                 ; ディレクトリ先頭になるまで
  864.     ret
  865. ;
  866. filldeleted endp
  867. ;
  868. ;------------------------------------------------------------------------------
  869. ;
  870. ;   writedirectory
  871. ;       ディレクトリバッファをファイルに書き戻す
  872. ;
  873. ;   TYPE    near call
  874. ;   IN      dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
  875. ;           clustsect,clustsize,subchain
  876. ;   OUT     なし
  877. ;   保存レジスタ
  878. ;
  879. ;------------------------------------------------------------------------------
  880. ;
  881. writedirectory  proc    near
  882.         local cluster:word
  883. ;
  884.     @if (dirtype,=,0),S
  885.         push    ds                  ; ルートディレクトリ書き込み
  886.         mov     ax,driveno
  887.         xor     bx,bx
  888.         mov     cx,sectcount
  889.         mov     dx,drvinf.directorystart
  890.         mov     ds,dirbuff
  891.         push    bp
  892.         int     26h
  893.         @if (cf,on)
  894.             xor     cx,cx
  895.             xor     dx,dx
  896.             jmp     abort
  897.         @ifend
  898.         popf
  899.         pop     bp
  900.         pop     ds
  901.     @else
  902.         push    ds                  ; サブディレクトリ書き込み
  903.         mov     ax,clustcount
  904.         mov     cluster,ax
  905.         mov     di,offset subchain
  906.         mov     ax,ds
  907.         mov     es,ax
  908.         xor     bx,bx
  909.         mov     ds,dirbuff
  910.         @do until
  911.             mov     ax,es:[di]
  912.             sub     ax,2
  913.             mov     cx,es:clustsect
  914.             mul     cx
  915.             add     ax,es:drvinf.datastartsector
  916.             mov     dx,ax
  917.             mov     ax,es:driveno
  918.             push    bp
  919.             push    di
  920.             int     26h
  921.             @if (cf,on)
  922.                 xor     cx,cx
  923.                 xor     dx,dx
  924.                 jmp abort
  925.             @ifend
  926.             popf
  927.             pop     di
  928.             pop     bp
  929.             add     bx,es:clustsize
  930.             lea     di,[di+2]
  931.             dec     cluster
  932.         @doend (zf,on)
  933.         pop     ds
  934.     @ifend
  935. ;
  936.     mov     es,dirbuff              ; ソートバッファの開放
  937.     mov     ah,49h
  938.     int     21h
  939. ;
  940.     ret
  941. ;
  942. writedirectory  endp
  943. ;
  944. ;------------------------------------------------------------------------------
  945. ;
  946. ;   dspdirname
  947. ;       処理中ディレクトリ名を表示する
  948. ;
  949. ;   TYPE    near call
  950. ;   IN      ES:DI ディレクトリ名文字列アドレス
  951. ;   OUT     なし
  952. ;   保存レジスタ    DS
  953. ;
  954. ;------------------------------------------------------------------------------
  955. ;
  956. dspdirname  proc
  957. ;
  958.     mov     ah,9        ; 処理中メッセージ表示
  959.     mov     dx,offset procs
  960.     int     21h
  961. ;
  962.     cld                             ; ディレクトリ名長さを獲得
  963.     mov     cx,-1
  964.     xor     ax,ax
  965.     mov     dx,di
  966.   repne     scasb
  967.     not     cx
  968.     dec     cx
  969. ;
  970.     push    ds                      ; ディレクトリ名表示
  971.     mov     ax,es
  972.     mov     ds,ax
  973.     call    dosstdout
  974.     pop     ds
  975. ;
  976.     mov     ah,2                ; 行頭への復帰
  977.     mov     dl,0dh
  978.     int     21h
  979. ;
  980.     ret
  981. ;
  982. dspdirname  endp
  983. ;
  984. ;------------------------------------------------------------------------------
  985. ;
  986. ;   dspmsgend
  987. ;       処理終了メッセージを表示する
  988. ;
  989. ;   TYPE    near call
  990. ;   IN      sortcount,movecount,sortproc,sweep
  991. ;   OUT     なし
  992. ;   保存レジスタ    ax,bx,cx,dx,si,di,bp,ds,es
  993. ;
  994. ;------------------------------------------------------------------------------
  995. ;
  996. dspmsgend   proc    uses ax bx cx dx si di ds es
  997.         local   wrks:dword,wrka:word
  998. ;
  999.     mov     ax,sortcount            ; ソートしたエントリ数
  1000.     mov     bx,movecount            ; 移動したエントリ数
  1001.     mov     cx,ax
  1002.     add     cx,bx
  1003.     @cbegin
  1004.     @case (sortexec,=,YES),and,(sweep,=,YES),and,(cx,/=,0),S ; ソート&移動
  1005.         mov     ax,cx
  1006.         mov     si,offset bothmsg
  1007.     @case (sortexec,=,YES),and,(sweep,=,NO),and,(ax,/=,0),S ; ソートのみ
  1008.         @if (ax,>,1),S
  1009.             mov     si,offset sortmsg   ; 2つ以上ならソートのみ表示
  1010.         @else
  1011.             mov     si,offset bothmsg   ; 1つだけならソート&移動表示
  1012.         @ifend
  1013.     @case (sortexec,=,NO),and,(sweep,=,YES),and,(bx,/=,0),S ; 移動のみ
  1014.         mov     ax,cx
  1015.         mov     si,offset movemsg   ; 移動
  1016.     @other
  1017.         xor     ax,ax
  1018.         mov     si,offset nothmsg   ; 対象なし
  1019.     @cend
  1020.     @if (ax,/=,0)
  1021.         mov     di,ss               ; 処理したエントリ数表示
  1022.         mov     es,di
  1023.         lea     di,offset wrka+1
  1024.         call    inttoasc0
  1025.         lea     di,[di-5]           ; 0サプレス処理
  1026.         push    di
  1027.         mov     cx,4
  1028.         @do while,(byte ptr es:[di],=,'0'),and,(cx,/=,0)
  1029.             mov     byte ptr es:[di],' '
  1030.             inc     di
  1031.             dec     cx
  1032.         @doend
  1033.         mov     cx,5                ; エントリ数表示
  1034.         pop     dx
  1035.         mov     di,ds
  1036.         push    ss
  1037.         pop     ds
  1038.         call    dosstdout
  1039.         mov     ds,di
  1040.     @ifend
  1041.     mov     ah,9                    ; エントリ数に続くメッセージ表示
  1042.     mov     dx,si
  1043.     int     21h
  1044.     ret
  1045. ;
  1046. dspmsgend   endp
  1047. ;
  1048. ;------------------------------------------------------------------------------
  1049. ;
  1050. ;   altint23h
  1051. ;       Ctrl+C押下の横取り
  1052. ;
  1053. ;   TYPE    interrupt
  1054. ;   IN      なし
  1055. ;   OUT     なし
  1056. ;   保存レジスタ    ax,bx,cx,dx,si,di,bp,ds,es
  1057. ;
  1058. ;------------------------------------------------------------------------------
  1059. ;
  1060. altint23h   proc
  1061. ;
  1062.     @if (cs:critical,=,NO),S        ; クリティカルセクションではない時
  1063.         jmp     cs:orgint23h        ; 既存の終了処理へ
  1064.     @else                           ; クリティカルセクションの時
  1065.         mov     cs:breakflag,YES    ; Ctrl+C押下を記憶しただけで復帰
  1066.         iret
  1067.     @ifend
  1068. ;
  1069. altint23h   endp
  1070. ;
  1071.         end     main
  1072.