/* * fdrmul.c - disk image --> file * original code:SASANO Takayoshi * --- public domain, no warranty. */ #include #include #include #include #include #include #ifdef DEBUG #define DP(x) printf x #else #define DP(x) /* */ #endif LOCAL TC target_drive[][4] = { {L"fda"}, {L"fdb"}, {L"fdc"}, {L"fdd"}, {L"uda"}, {L"udb"}, {L"udc"}, {L"udd"}, }; #define READ_RETRY 4 LOCAL ERR read_sect(W dd, W sect, W sectsize, UB *buf, UB *sectbuf, W retry) { ERR err; W i, j, rsz; /* retryに指定した回数だけ同一のセクタを読む */ for (i = 0; i < retry; i++) { err = rea_dev(dd, sect, sectbuf + sectsize * i, 1, &rsz, NULL); if (err < ER_OK) { goto fin; } else if (rsz != 1) { err = ER_REC; goto fin; } } /* データが全て正常に読み出せていることを確認 */ err = ER_OBJ; for (i = 0; i < retry - 1; i++) { for (j = sectsize * i; j < sectsize * (i + 1); j++) { if (sectbuf[j] != sectbuf[j + sectsize]) goto fin; } } err = ER_OK; fin: if (err < ER_OK) memset(buf, 0xe5, sectsize); else memcpy(buf, sectbuf, sectsize); return err; } LOCAL WERR fdrmul(W argc, TC *argv[]) { WERR err; W i, dd, fd, imgsize, rsz; UB *buf, *sectbuf; LINK link; DiskInfo di; /* デバイスをオープン */ err = opn_dev(target_drive[*argv[1] - L'a'], D_READ | D_EXCL, NULL); if (err < ER_OK) { printf("opn_dev(): %d\n", err); goto fin0; } dd = err; /* ディスクのチェック */ err = rea_dev(dd, DN_DISKINFO, (UB *)&di, sizeof(di), &rsz, NULL); if (err < ER_OK) { printf("rea_dev(): %d\n", err); goto fin1; } if (di.format != DiskFmt_2DD && di.format != DiskFmt_2HD) { printf("unsupported media: %d\n", di.format); err = ER_DEV; goto fin1; } DP(("di.format: %d\n", di.format)); /* イメージサイズの計算 */ imgsize = di.blocksize * di.blockcont; DP(("di.blocksize: %d di.blockcont: %d imgsize: %d\n", di.blocksize, di.blockcont, imgsize)); /* メモリの確保(イメージ格納用バッファ) */ buf = malloc(imgsize); if (buf == NULL) { printf("malloc(buf): NULL\n"); err = ER_NOMEM; goto fin1; } /* メモリの確保(セクタ読み出し用バッファ) */ sectbuf = malloc(di.blocksize * READ_RETRY); if (sectbuf == NULL) { printf("malloc(sectbuf): NULL\n"); err = ER_NOMEM; goto fin2; } /* イメージの読み込み */ for (i = 0; i < di.blockcont; i++) { printf("%5d", i); err = read_sect(dd, i, di.blocksize, buf + di.blocksize * i, sectbuf, READ_RETRY); if (err < ER_OK) printf(" [%08x]\n", err); else printf("\r"); } printf("done.\n"); /* 出力ファイルへのリンク取り出し */ err = get_lnk(NULL, &link, F_NORM); if (err < 0) { printf("get_lnk(): %d\n", err); goto fin3; } /* 出力ファイルの作成 */ err = cre_fil(&link, argv[2], NULL, 0, F_FIX); if (err < 0) { printf("cre_fil(): %d\n", err); goto fin3; } fd = err; /* レコードの書き込み */ err = apd_rec(fd, buf, imgsize, 31, 0, 0); if (err < 0) { printf("apd_rec(): %d\n", err); goto fin4; } err = ER_OK; fin4: cls_fil(fd); fin3: free(sectbuf); fin2: free(buf); fin1: cls_dev(dd, 0, NULL); /* dd, 1, NULL だとディスクを抜く羽目になる */ fin0: return err; } EXPORT WERR main(W argc, TC *argv[]) { /* 使い方を表示 */ if (argc < 3) { printf("usage: fdrmul [drive] [filename]\n"); return ER_PAR; } return fdrmul(argc, argv); }