タイトルに問題と書きましたが、課題や何かじゃないので咎めないでください。
FAT12でフォーマットしたFDにファイルを直接ディスクに書き込もうと思っています。
しかし、FAT16と違ってFATにクラスタ番号を書き込むのが難しいわけです。
環境はC言語で、アルゴリズムだけなので必要は無いかと思いますが、
Win32APIを使用できる環境です。
1.クラスタ番号は12bit長で
0x003 0x004 0x005 0x006 0xFFFをFATに書き込むと
03 40 00 05 60 00 FF 0F と記録されます。
2.ディスクへの書き込みは実装してあるためバッファへの書き込みが出来ればよい。
3.ディスクは初期化された状態で、0番と1番のテーブルは予約済み。2番からクラスタ番号を書き込むこととする。
4.一つのファイルを整列された状態で書き込むこと。初期化されているため、2番から後のテーブルは全て未使用。
5.クラスタサイズは1セクタ(512バイト)である。
6.書き込まれるファイルサイズは規定していないため、ループによる処理が望ましい。
7.ファイルサイズより必要なクラスタ数は求めてある。
typedef unsigned char byte;
typedef unsigned short word, *pword;
typedef unsigned long dword;
byte fat[512];//FATへの書き込みバッファ 0クリアされている。
dword clust;//必要なクラスタ数 既に求めてある。
dword i;//インクリメント
自分で書いたFAT16用のFAT書き込みコード
((pword)fat)[0] = 0xFFF8;//0番目のクラスタ(予約)
((pword)fat)[1] = 0xFFFF;//1番目のクラスタ(予約)
if (clust == 1) {//クラスタサイズが1なら
((pword)fat)[2] = 0xFFFF;//最終クラスタを示す値を書き込む
} else {//複数のクラスタに分割されるなら
for (i=0; i<clust-1; i++) {//クラスタサイズの-1個分までインクリメント
((pword)fat)[i+2] = (word)i+3;//n番(2番から始まる)のクラスタにn+1のクラスタ番号を書き込んでいく
}
((pword)fat)[i+2] = 0xFFFF;//最終クラスタを示す値を書き込む
}
書きかけのFAT12
((pword)fat)[0] |= 0x0FF0;
*((pword)&fat[1]) |= 0xFFF0;
if (clust == 1) {
*((pword)&fat[3]) = 0x0FFF;
} else {
/*ここに1クラスタを超えたファイルのクラスタ番号をFATに書き込む処理*/
}
どなたか、ヒントや情報をいただけると幸いです。
コードは書き直してもいいですし、変数も適当に名前付けて構いません。
他に必要な変数などがあれば追加してください。
また、補足要求があれば何なりとお書きください。
よろしくお願いいたします。
No.3
- 回答日時:
おっと。
シフトすんの忘れてる。誤
>// *p = (*p & 0x0f) | (WData & 0xf0); //1バイト目
> *p |= WData & 0xf0; //1バイト目
正
<// *p = (*p & 0x0f) | ((WData << 4) & 0xf0); //1バイト目
< *p |= (WData << 4) & 0xf0; //1バイト目
No.2ベストアンサー
- 回答日時:
まず第一の問題は「FATへのクラスタ番号の書き込みを関数にしてない」のが問題。
第二の問題は「何故第2FATを書かないのか」と言う事。
第三の問題は「ルートディレクトリは書かないのか?」と言う事。
とりあえず「第一の問題」だけ回答。
//先頭から順番に書き込まず、ランダムに書く場合は、コメントした行を使う
void WriteFAT12(byte *fat,int CNo,int WData)
{
byte *p = &fat[CNo * 3 / 2]; //書き込み位置を求める
if (CNo & 1) { //クラスタ番号が奇数か偶数か
// *p = (*p & 0x0f) | (WData & 0xf0); //1バイト目
*p |= WData & 0xf0; //1バイト目
*++p = (WData >> 4); //2バイト目
} else {
*p++ = WData & 0xff; //1バイト目
// *p = (*p & 0xf0) | ((WData >> 8) & 0x0f); //2バイト目
*p = (WData >> 8) & 0x0f; //2バイト目
}
}
int i;
WriteFAT12(fat, 0, 0xFF8);//0番目のクラスタ(予約)
WriteFAT12(fat, 1, 0xFFF);//1番目のクラスタ(予約)
for (i = 1; i < clust; i++) {//クラスタサイズの-1分までインクリメント
WriteFAT12(fat, i + 1, i + 2);//n番(2番から始まる)のクラスタにn+1のクラスタ番号を書き込んでいく
}
WriteFAT12(fat, clust + 1, 0xFFF);//最後のクラスタに終了マークを書き込む
いちいちclustが1か1以外か場合分けする必要はない。「clustが1ならループを回らないforループ」と「clustが1だろうが何だろうが、最後のクラスタにFFFを書き込む」と書けば済む。
この回答への補足
>「FATへのクラスタ番号の書き込みを関数にしてない」
これは、限られた条件の(初期化された状態で2番のクラスタから順番にかきこむ)ため
関数化の必要を感じていなかった訳です。
>「何故第2FATを書かないのか」
バッファを1stFATへ書き込んだ後に2ndFATに書き込むつもりでした。
>「ルートディレクトリは書かないのか?」
初期化された状態で書き込むので、ルートディレクトリエントリの最初に構造体を書き込もうと思っています。
何も書き込まれていないのが条件なので、特に問題は無いと思ってます。
>いちいちclustが1か1以外か場合分けする必要はない。
言われてから気づきました。
そうですよね、よく考えたらわざわざ処理分けする必要なんてありませんでした。
ご指摘ありがとう御座います。
お手本を示していただいたコードを元に
自分なりに書き直してみた結果です。
((pword)fat)[0] |= 0x0FF0;
*((pword)&fat[1]) |= 0xFFF0;
for (i=1; i<clust; i++) {
clustNo = ((i+1)*3)>>1;
if (i & 0x01) {
*((pword)&fat[clustNo]) |= (i+2);
} else {
*((pword)&fat[clustNo]) |= (i+2) << 4;
}
}
clustNo = ((i+1)*3)>>1;
if (i & 0x01) *((pword)&fat[clustNo]) = 0x0FFF;
else *((pword)&fat[clustNo]) = 0xFFF0;
>>start..
A Drive was Opened.
Boot sector was Read.
System file was Read.
Size of system file. [3168]
Size put together on sector boundary. [3584]
Necessary number of clusters. [7]
つたない英語はお許しください。
F0 FF FF 03 40 00 05 60
00 07 80 00 FF 0F 00 00
一応、期待通りに動いたみたいです。
大変参考になるコードを示していただき感謝いたします。
ありがとうございました。
No.1
- 回答日時:
クラスタ番号を書き込むときに, 次に書き込むべき位置が「バイト境界にそろっているかどうか」を判断するフラグが 1個必要ではないでしょうか. そして,
バイト境界に揃っているのであれば
fat[i++] = cluster & 0xff;
fat[i] = cluster >> 8;
揃っていなければ
fat[i++] |= (cluster & 0x0f) << 4;
fat[i++] = cluster >> 4;
という処理になるかと. もちろん, 処理するごとにフラグを反転させる必要があります. また, 512バイトを超えちゃったときの処理も別途必要かもしれません.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) ExcelからAccessのテーブルに書き込む時に時間がかかる 1 2022/10/14 20:38
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- その他(恋愛相談) 彼氏が新しい異動先で、着任1周目でクラスタが起こり、彼も無症状感染のため、自宅待機しているそうです。 3 2022/04/25 20:41
- その他(言語学・言語) 大昔に使われていた和製独語 復活して欲しいと思いませんか? 英語化がどんどん現れてきたため、私がいつ 8 2023/08/15 06:31
- Windows 10 再起動後 Pinが使用できず、PC(windows11)にサインインできない 3 2022/08/30 20:53
- SSL・HTTPS 掲示板サイトへの書き込みができない件(ブラウザソフトを変えてもできない) 2 2022/11/20 10:48
- 政治 日本のマイカードはあまりに遅すぎです 7 2023/04/02 18:36
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- PHP コメント機能に返信欄を矢印で追加したい 1 2022/05/09 21:17
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
UTF-8で5~6バイトになる文字コ...
-
エクセルシート名の制限を変更...
-
COBOLのCOMP形式について
-
char str[256]の256の意味は?
-
ビットスワップとバイトスワッ...
-
10Mバイトて文字数に すると何...
-
バイナリとBCDコード
-
ピクセル,dpiから容量(バイト...
-
全角半角を調べるライブラリ関...
-
VB6でのファイルサイズ取得につ...
-
シフトJISの2バイト文字
-
UCS-2の一覧表が欲しい
-
16bitアクセスRAMとは
-
【ActionScript】全角半角の判...
-
CRC計算方法
-
URLは最高何文字まで可能なので...
-
memcmp バイナリデータの比較方法
-
ソケット通信
-
1KBが1024byteな理由
-
文字コードの利点・欠点について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
10Mバイトて文字数に すると何...
-
UTF-8で5~6バイトになる文字コ...
-
char str[256]の256の意味は?
-
エクセルシート名の制限を変更...
-
COBOLのCOMP形式について
-
バイナリとBCDコード
-
バイト列とバイナリ列の違いが...
-
ビットスワップとバイトスワッ...
-
ピクセル,dpiから容量(バイト...
-
SQLで1バイト、2バイト混在...
-
Javaで日本語1文字のバイト数
-
「1TB」のHDDに日本語は何字入...
-
機種依存文字をチェックしたい。
-
VBAでShift-JISのURLエンコード
-
GetWindowTextでアドレスバーか...
-
COBOL PICTUREで X,S,Vの意味
-
【VB2005】テキストボックス内...
-
URLは最高何文字まで可能なので...
-
1KBが1024byteな理由
-
ワイド文字のバイト数が取得で...
おすすめ情報