DOS2解析
データセグメント編 カーネルパッチ編
FAT16のカーネルパッチはこんな風になっています。
アドレスはSTのものですが、アドレスが14hずれている別バージョンがあります。
GTならこのアドレス+1Ehです。
FAT16パッチver 0.03
;-----------------------------
;FAT読みだし (CALL 2D86h)
;設定 DEにクラスタ番号
;戻り値 DEに次のクラスタ番号
;FATRED
PUSH AF
CALL CHKDRV
JR Z,Z0018 ;FAT16ドライブ
POP AF
CALL 02D86h ;FAT12ドライブ
BIT 7,D
RET
Z0018: POP AF
CALL FATADR ;FATアドレスを得る
JR Z,Z0019
Z0020: XOR A
LD (0BBEAh),A
LD A,0F2h
LD DE,0FFFFh
CALL 0368Eh ;エラー処理ルーチン?
JR Z,Z0020
JR Z0021
Z0019: PUSH HL
LD A,(DE) ;DE = FATアドレス
LD L,A
INC DE
LD A,(DE)
LD H,A
EX DE,HL ;DE=next cluster
LD HL,0FFF7h ;HL=wrong cluster
OR A
SBC HL,DE
POP HL
JR NC,Z1021
Z0021: LD DE,0FFFFh
OR D ;Z=0 SCF ;Cy=1
RET
Z1021: XOR A ;Cy=0 Z=1
RET
;-----------------------------------------------------------
;クラスタ番号からFATのセクタ番号を求め、Disk Bufferに読み込む
;クラスタ番号からFATのアドレスを得る
;設定 DEにクラスタ番号
; HLにデータセグメント内のDPBアドレス
;戻り値 DEにFATアドレス
FATADR: PUSH IX
PUSH BC
PUSH HL
PUSH HL
POP IX
RES 0,(IY+29h)
LD L,(IX+16h)
LD H,(IX+17h)
XOR A
SBC HL,DE
JR C,FATAD_ ;エラー
LD H,D ;DE=クラスタ番号
LD L,E
ADD HL,HL
PUSH HL
LD E,D
LD D,0
LD L,(IX+0Ch) ;FATの先頭のセクタ番号
LD H,(IX+0Dh)
ADD HL,DE ;HL = FATのセクタ番号
EX DE,HL
CALL BUF_1 ;FATのセクタをBufferに読み込む
LD BC,0Bh
ADD HL,BC ;HL = Bufferのアドレス
POP BC
LD A,B
AND 01h
LD B,A
ADD HL,BC ;HL = そのクラスタのFATアドレス
EX DE,HL
CP A ;Z=1 right
FATAD_: POP HL
POP BC
POP IX
RET
;-----------------------------------------------------------
;FAT書き込み
FATWRT: CALL CHKDRV
JR Z,FATWR2 ;16bit FAT
LD A,B
CP 10h
JP 2DDAh ;12bit FAT
FATWR2: CALL FATADR ;FATアドレスを得る
JR Z,FATWR3
LD A,0FFh
LD (0BBEAh),A
FATWR4: LD A,0F2h
LD DE,0FFFFh
CALL 368Eh
JR Z,FATWR4
JP 2E35h ;Error
FATWR3: PUSH HL
LD A,C
LD (DE),A ;FAT書き込み
INC DE
LD A,B
LD (DE),A
JP 2E0Fh
;------------------------------------------------------------
;ルートかサブか クラスタ番号のチェック
CLST_1: LD D,(HL) ;1534h
JR CHECK
CLST_2: SET 3,(IY+20h) ;158Bh
JR CHECK
CLST_3: LD DE,(0BBE6h) ;1C0Dh
JR CHECK
CLST_4: LD DE,(0BBE8h) ;1C53h
JR CHECK
CLST_9: LD DE,(0BBE4h) ;1CB1h
JR CHECK
CLST_8: POP AF ;1B87h
POP DE
JR CLS_
CLST_5: POP AF ;2F6Fh
PUSH BC
CLS_: PUSH AF
JR CHECK
CLST_6: LD DE,(0BBA3h) ;2F9Bh
CHECK: LD A,D
INC A
JR Z,CSTMSB
XOR A
RET ;z=1 サブディレクトリ
CSTMSB: DEC A
RET ;z=0 ルートディレクトリ
CLST_7: JR NZ,CHECK ;300Dh
INC SP
INC SP
RET
;---------------------------------
CLUST: LD HL,(0B9FAh) ;FCB+20h DPB address
CALL CHKDRV
RET Z ;FAT16
LD A,(IX+2Ah)
JP 39D6h
CLUST2: LD HL,(0B9FAh)
CALL CHKDRV
RET Z ;FAT16
LD A,(IX+1Dh)
JP 3CDFh
;-------------------------------
;ドライブチェック
;z=1 FAT16 drive z=0 FAT12 drive
CHKDRV: PUSH HL
PUSH DE
LD DE,0008h
ADD HL,DE
LD A,(HL)
LD HL,(DRIVE)
CP L
JR Z,CHKD_1
CP H
CHKD_1: POP DE
POP HL
RET
;------------------------------------------------------------
;クラスタ番号をセクタ番号に換算
;設定: DE=クラスタ番号
;戻り値: DE=セクタ番号
GETSEC: LD C,A
CALL CHKDRV
LD A,C
LD BC,000Bh
JP NZ,2DBBh
ADD HL,BC
LD B,(HL) ;B=クラスタシフト
EX DE,HL
DEC HL ;クラスタ - 2
DEC HL
LD C,A
XOR A
JR Z0022
Z0023: ADD HL,HL ;セクタ番号bit 0-15
ADC A,A ;セクタ番号bit16-23
Z0022: DJNZ Z0023
LD B,A ;bit16-23
LD A,C
ADD A,L
LD L,A
EX DE,HL ;BDE=セクタ番号
LD A,B
LD BC,0009h
ADD HL,BC ;DPB+14h データ領域の先頭セクタ
LD C,(HL)
INC HL
LD H,(HL)
LD L,C
ADD HL,DE
JR NC,Z0024
INC A
Z0024: EX DE,HL ;BDE=sector number
LD (BIT16),A ;bit16-23を保存する
OR A
POP BC
POP HL
RET
;----------------------------------------------------------
;BBB4hのセクタ番号をINC
NUM_1: LD (0BBB4h),HL
RET NC
SECINC: LD A,(BIT16)
INC A
LD (BIT16),A
RET
NUM_2: INC (IY+35h)
RET NZ
JR SECINC
;-----------------------------------------------
;Disk bufferにセクタリード
BUF_1: XOR A ;0C22h,2E26h,2E63h,2E80h,2EDCh
LD (DSKEX),A ;セクタ番号のbit16-23
JP 2B6Ah
BUF_5: XOR A ;2FBEh
LD (BIT16),A
LD B,L
DEC B
DEC DE
RET
BUF_4: LD A,(0BBE9h) ;1CFEh Sub? or Root dir?
INC A
JR Z,BUF_3
LD A,(SUBSEC)
JR BUF_
BUF_2: LD A,(BIT16) ;1B34h,26C1h,2FDFh
JR BUF_
BUF_3: XOR A ;2ED7h,2F02h
BUF_: LD (DSKEX),A
JP 2B78h
;--------------------------------------------------------------
;ディスクアクセスのためにセクタ番号セットを24ビットでセット
RAMRED: PUSH AF ;25CDh
LD A,(BIT16)
LD (RW_16),A ;セクタ換算したときのbit16-23
LD DE,(0BBB4h) ;セクタ換算したときのbit0-15
POP AF
RET
;------------------------------------------------------------
;セクタ番号のbit16-23をセット(Disk bufferにリード・ライト)
REDBUF: PUSH AF ;2BF8h
LD A,(DSKEX)
JR REDB_1
WRTBUF: PUSH AF ;2D54h
LD A,(IX+0FDh) ;Disk bufferに保存したbit16-23
REDB_1: LD (RW_16),A ;Cにセットするために
POP AF
JP 0324Fh ;Disk-romの4010hへ
;---------------------------------
;Not a dos disk 対策
DSKROM: CP 06h ;34DCh
JP NC,3525h ;エラー
PUSH AF
XOR A ;ブートセクタ、FATを読むためbit16-23=0にする
LD (RW_16),A
POP AF
JP 034E0h
;-------------------------------------
DRIVE: DB 0,0 ;FAT16 DRIVE
BIT16: DB 0 ;ファイルアクセス用 bit16-23
DSKEX: DB 0 ;ディスクバッファ用 bit16-23
SUBSEC: DB 0 ;サブディレクトリ用 bit16-23
RW_16: DB 0 ;call 4010h時のbit16-23
FSTDAT: DS 6 ;ドライブ登録テーブル保存用
SECDAT: DS 6 ; 〃
;------------------------------------------------------------
;0FA00h -
;Disk bufferに読み込むセクタのbit16-23を保存する
SECNUM: LD A,(DRIVE) ;2BBDh
CP C ;C=ドライブ番号
JR Z,SECN_2
LD A,(DRIVE+1)
CP C
LD A,0 ;FAT12
JR NZ,SECN_1
SECN_2: LD A,(DSKEX)
SECN_1: LD C,(IX+11h)
LD (HL),C
RET
;-----------------------------------------------
;Disk bufferにリード済みかどうか、セクタ番号調べ
CMPSEC: ;2C33h
INC HL
LD A,(HL)
SUB D
RET NZ ;Z=0 セクタ番号が違う
LD A,(DRIVE)
CP C
JR Z,CMPSE_
LD A,(DRIVE+1)
CP C
JR Z,CMPSE_
XOR A ;FAT12 drive Disk bufferにリード済み
RET
CMPSE_: LD A,(DSKEX) ;FAT16 drive
COMPAR: INC HL
INC HL
INC HL
CP (HL) ;bit16-23の比較
RET
;------------------------------------------------------
;FAT12 driveならメディアID、FAT16 driveならセクタ番号のbit16-23を
;Cレジスタにセットする
SETNUM: PUSH AF ;3540h
PUSH HL
LD HL,(DRIVE)
LD A,(IX+08h)
CP L
JR Z,SNUM_1
CP H
SNUM_1: POP HL
JR NZ,MEDIA
LD A,(RW_16) ;bit16-23 セット
LD C,A
POP AF
RET
MEDIA: LD C,(IX+1Dh) ;Media ID セット
POP AF
RET
;-------------------------------------------------------
;クラスタ総数の計算
TALCLS: LD A,L
OR H
JR Z,WINFMT ;ブートセクタの+13h,14hが0ならFAT16フォーマット
SBC HL,DE
JP 346Fh ;FAT12
WINFMT: LD L,(IX+20h) ;総セクタ数
LD H,(IX+21h)
LD A,(IX+22h)
OR A
SBC HL,DE
SBC A,0
WINFM_: DEC C
JP Z,3478h
SRL A
RR H
RR L
JR WINFM_
;-----------------------------
;ファイルアクセス時のDisk buffer処理(bufferのフラッシュとか)
DSKBUF: SBC HL,BC ;2649h
PUSH AF
PUSH DE
DEC DE
DEC DE
DEC DE
EX DE,HL
LD A,(HL)
LD HL,(DRIVE)
CP L
JR Z,DSKB_1
CP H
DSKB_1: EX DE,HL
POP DE
JR Z,CALUC
POP AF
POP BC
JP 264Ch ;FAT12 drive
CALUC: POP AF
PUSH DE
INC DE
INC DE
INC DE
LD A,(DE)
LD BC,(BIT16)
SBC A,C
POP DE
POP BC
INC A
JP NZ,2665h
LD A,L
ADD A,B
JR NC,PAT_40
LD A,0
ADC A,H
PAT_40: JP 2642h
;-------------------------------------
GETSUB:
CALL 2DB6h ;1CC4h
LD A,(BIT16)
LD (SUBSEC),A ;Sub dirのセクタ番号bit16-23
RET
SUB_16: INC E ;1CA5h
JR NC,SUB_
INC D
JR NC,SUB_
LD A,(SUBSEC)
INC A
LD (SUBSEC),A
SUB_: LD A,(0BBE1h)
RET
;--------------------------------------
;セクタ直アクセスのときは、bit16-23を00hに固定
SECABS:
XOR A ;2588h
LD (BIT16),A
JP 2599h
DOS2解析データセグメント編
トップページに戻る