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解析データセグメント編
トップページに戻る