/* * ddconv -- 320kフロッピーの読み取り * * 320kフロッピーとは、 * PC-8801 などで使われていた 5インチ両面倍密度 (2D) ディスクのこと。 * 両面、40トラック、16セクタ/トラック、MFM、256バイト/セクタ * * デフォルトの対象ドライブは 3台目の 1M/640kドライブ。(0x12) * * つかいかた: * ddconv [-#] [-o 出力ファイル] * * # はフロッピードライブの番号 (0-3) (ドライブレター A: B:..ではない) * * コンパイル方法: * tcc ddconv (Turbo C++ 1.0 2nd Editionの場合) * bcc ddconv (Borland C++ 2.0の場合) * * 0.0: Nov. 25, 1997 by Dai ISHIJIMA * 0.1: Apr. 11, 1998 */ /* 98互換機でしか動きません */ /* MS-DOSでしか動きません */ /* * 参考文献: * 吉田 功:「PC98シリーズのBIOS」, * トランジスタ技術スペシャル No.45 (CQ出版, 1994), pp.129-139. */ #include #include #include /* 320k = 40 * 2 * 16 * 256 */ #define NCYL 40 /* 40シリンダ (48トラック/インチ[tpi]) */ #define NHD 2 /* 両面 */ #define NSEC 16 /* 16セクタ/トラック */ #define NLEN 256 /* 256バイト/セクタ */ #define CFLAG 0x01 #define ZFLAG 0x40 #define shift --argc; ++argv char *prog; /* define register array */ typedef union { struct byteregisters { unsigned char al, ah, bl, bh, cl, ch, dl, dh; unsigned int bp, si, di, ds, es, flag; } h; struct wordresisters { unsigned int ax, bx, cx, dx; unsigned int bp, si, di, ds, es, flag; } x; struct REGPACK p; } registers; static registers reg; static unsigned char buf[16384]; #define DISKBIOS 0x1b /* ディスクBIOS */ /* PC-9801のディスクBIOSを呼び出す */ void diskbios() { intr(DISKBIOS, ®.p); if (reg.x.flag & CFLAG) { /* エラー */ fprintf(stderr, "diskbios error (%02x): ", reg.h.ah); if (reg.h.ah == 0x40) { fprintf(stderr, "Equipment Check"); } else if (reg.h.ah == 0x60) { fprintf(stderr, "Not Ready"); } fprintf(stderr, "\n"); } } /* シリンダ0 へシーク */ void seekzero(int drv) { reg.h.ah = 0x07; /* シリンダ 0へのシーク */ reg.h.al = drv; diskbios(); } /* 指定シリンダへシーク */ void seekto(int drv, int cyl) { reg.h.ah = 0x10; /* シーク */ reg.h.al = drv; reg.h.cl = cyl; diskbios(); } /* 指定セクタを読む */ void readsec(int drv, int c, int h, int r, int n, unsigned char *buf) { reg.h.ah = 0x06 /* データの読みだし */ + 0x40; /* 倍密度 (MFM) */ reg.h.al = drv; /* ドライブ */ reg.h.cl = c; /* シリンダ */ reg.h.dh = h; /* ヘッド (面の指定) */ reg.h.dl = r; /* セクタ */ if (n == 128) { /* セクタ長 */ reg.h.ch = 0; } else if (n == 256) { reg.h.ch = 1; } else if (n == 512) { reg.h.ch = 2; } else if (n == 1024) { reg.h.ch = 3; } else { n = 512; reg.h.ch = 2; } reg.x.bx = n; reg.x.es = FP_SEG((void far *)buf); reg.x.bp = FP_OFF((void far *)buf); diskbios(); } /* ドライブを320kモードにする */ void diskmode(drv) { reg.h.ah = 0x0e /* 動作モードの設定 */ + 0x80; /* 48tpi/96tpiの設定 */ /* ah = 0x0e だけなら、片面/両面の設定 */ reg.h.al = 0x10; /* 全ドライブを48tpiに (=0x1f: 96tpi) */ diskbios(); reg.h.ah = 0x84; /* ドライブ状態のセンス */ reg.h.al = drv; diskbios(); fprintf(stderr, "current mode: %02x\n", reg.h.ah); /* ビット: =0 / =1 d0: 片面 / 両面 d1: AIあり / なし d2: 48tpi (40シリンダモード) / 96tpi (80シリンダモード) d3: 640kドライブ / 1Mドライブ */ } void main(int argc, char *argv[]) { FILE *fp; int drive; int x; char outfil[80]; int drv, cyl, hd, sec, len; strcpy(outfil, "g:disk.img"); /* デフォルト出力 */ drive = 2; /* デフォルトドライブ */ prog = *argv; shift; while ((argc > 0) && (argv[0][0] == '-')) { if (sscanf(*argv, "-%d", &x) == 1) { drive = x % 4; } else if (argv[0][1] == 'o') { shift; strcpy(outfil, *argv); } else { fprintf(stderr, "%s: [-] [-o ]\n", prog); fprintf(stderr, " drive #: 0-3\n"); exit(1); } shift; } if ((fp = fopen(outfil, "wb")) == NULL) { fprintf(stderr, "%s: can't open %s\n", prog, outfil); exit(1); } drv = 0x10 /* 1M/640k両用ドライブ */ + drive; /* ドライブ番号 0..3 */ diskmode(drv); seekzero(drv); len = NLEN; for (cyl = 0; cyl < NCYL; cyl++) { fprintf(stderr, "cyl = %2d\r", cyl); seekto(drv, cyl); for (hd = 0; hd < NHD; hd++) { for (sec = 1; sec <= NSEC; sec++) { readsec(drv, cyl, hd, sec, len, buf); fwrite(buf, 1, len, fp); } } } fclose(fp); exit(0); }