無料
-
出会い
-
花
-
ライヴチャット
-
アクセス解析
MSXの普通の2DDイメージのDSKファイル(または、DSKファイルとDERファイル)をD88ファイルに変換するツールのソース
本題
・DSKファイル
または
・DSKファイルとDERファイル
を、D88ファイルに変換するツールです。
ただし、実行ファイルは配布しません。C言語とC#のソースだけ置いておきます。
DSKファイルだけだったら他のツールを使うほうが良いでしょう。これの需要があるのかどうかは不明です。
実行ファイル生成について
C言語のほうは、VC++でもBorland C++でもCygwinのgccでもLSI C-86試食版でも使えそうな気がします。ただし、一部の環境ではtypedefの部分を書き換える必要があります。
(追記:stricmpがエラーになる場合は、strcasecmp、strcmpi、_stricmpなど適切に書き換えて下さい。)
C#のほうは、.NET Frameworkのプログラムが動作するWindows環境であればコマンドプロンプトから
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe dsk2d88.cs
みたいなので実行ファイルを生成できるような気がしますが、”v3.5”の部分を変更する必要があったりするかもしれません。
コマンドライン
パラメータ無しで実行すれば大体わかるんじゃないかと思いますが、
dsk2d88.exe In.dsk In.der Out.d88 0xb0
な感じで。パラメータの4番目はエラーセクターのステータスのコードです。これだけは省略可能。
DERファイルの拡張子は”.der”で。D88ファイルの拡張子は”.d88”で。アルファベットを大文字にしても同じです。
DSKファイルは、”.der”や”.d88”でなければ何でもいいです。アルファベットを大文字にしても同じです。
DERファイルを使用しない場合は、存在しない適当なファイル名を指定して下さい。拡張子は”.der”で。アルファベットを大文字にしても同じです。
入出力ファイル仕様
DSKファイルはヘッダー無し、非圧縮、2DD、512バイト/セクター、 9セクター/トラック専用です。普通は512バイト×9セクター×160トラック=737280バイトですが、セクター数が18の倍数であれば受け入れるようにしているので、512バイト×9セクター×162トラックのイメージファイルにも対応できます。(1DDのDSKファイルを入力すると、「半分しかフォーマットされていない2DDで、セクターの中に記録されたメディアID等は1DD相当」のD88ファイルが出力されるかもしれません。2HDのフロッピーをサポートしたMSXも世の中には存在するそうですが、そのDSKファイルを入力すると、途中までのデータを使用して「164トラックまで存在する2DDで、セクターの中に記録されたメディアID等は2HD相当」のD88ファイルが出力されるかもしれません。)
DERファイルでエラーの存在するセクターは、D88ファイルでは「データCRCエラー」になります。コマンドラインパラメータの4番目を指定すると他のエラーにもできますが、その場合の動作は未確認です。
D88ファイルは上書き確認しません。エラー発生時には、生成途中だったD88ファイルを消すこともあります。
駄文1
RuMSXと同じ作者のDisk-Managerを使用して実フロッピーからイメージファイルを作成すると、
・リードエラーのセクターが無い場合:DSKファイルだけが生成される
・リードエラーのセクターがある場合:DSKファイルとDERファイルが生成される
という結果になるはずです。(Win9xを使っていた頃に試した結果です。USB接続のFDDや非9x系のOSや最新版のDisk-Managerでは試してません。)
DSKファイルは、論理セクターの内容を0番から順に並べただけのファイルで、普通のMSXの2DDディスクであれば512バイト×1440セクター=737280バイトになります。このファイルは多くのエミュレータでフロッピーディスクイメージとして使用できます。(Disk-Managerを使用する以外の方法でも作成できますが、拡張子がDSKではないかもしれません。また、拡張子がDSKでも全く異なる形式のファイルの可能性もあります。)
DERファイルは、20バイトのヘッダーの後ろに、1セクターあたり1ビットでエラーの有無が記録されています。(Disk-Managerを使用する以外の方法で作成できるかどうかは知りません。また、セキュリティ関連の分野で拡張子DERが使われることもあるようですが、ここでは無関係です。)RuMSXでは昔から対応、blueMSXでは2.8.2以降で対応しています。1ビットなのでエラーの種類を使い分けることはできません。RuMSXではCRCエラーになるようです。blueMSX2.8.2ではFDCの種類によってCRCエラーになったりother errorになったりするようですが、other errorになるのは不具合で、CRCエラーになるのがblueMSXの本来の動作かもしれません。
DERファイルは「コピープロテクトチェックを行っているソフト」を動かすのに役に立つことがあります。役に立たないこともあるかもしれません。
駄文2
私の手元には、「コピープロテクトチェック処理を解除してなくて、DERファイルが存在するイメージファイル」がいくつかあります。Disk-Managerでイメージ化しただけなので。
しかし、Common Source Code ProjectではDERファイルに対応していません。もし対応させたとしても、例えば「CRCエラーじゃなくてRECORD NOT FOUNDにしたいソフトもある」なんてことになったら面倒です。
一方、D88ファイルというのはMSXには馴染みの無かったファイルなので、その形式ではイメージ化してません。今からD88のためのイメージ化をやり直すのも色々面倒です。
DSKファイルだけであればVFIC(Virtual Floppy Image Converter)というツールでD88ファイルに変換できそうですが、エラー情報無しであれば、変換する必要は無いでしょう。
DERファイルの情報も含めて変換して、openMSXやfMSXSOで使えるようにするツールはそれぞれ存在するようです。しかし、D88ファイルに直接変換するツールは知りません。なので、とりあえず作ってみた物をここに置いておきます。ソースだけ。
駄文3
不具合修正・機能追加・仕様変更・醜いソースの改善・英文のつもりかもしれない箇所の表記修正などを行う人が現れるかどうかはわかりませんが、もしそういうのを配布する場合は、ハンドルネームと日付とかバージョン番号なんかが実行ファイルにも含まれるようにして、改変されていることを容易に判別できるようにすればいいんじゃないかなと思います。
C言語 dsk2d88.c
#include
#include
#include
typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; int check_ext(const char *filename, const char *ext) { size_t len_f, len_e; len_f = strlen(filename); len_e = strlen(ext); if (len_f < len_e) return 1; return stricmp(filename + len_f - len_e, ext); } int check_ext_all(const char *dsk, const char *der, const char *d88) { if ( (0 == check_ext(dsk, ".der")) || (0 == check_ext(dsk, ".d88")) || (0 != check_ext(der, ".der")) || (0 != check_ext(d88, ".d88")) ) { printf(" Filename extension error.\n"); return 11; } return 0; } int write_d88(const char *dsk, const char *der, const char *d88, u8 error_status) { int ret = 0; int track, head, sector; FILE *fp_dsk = NULL; FILE *fp_der = NULL; FILE *fp_d88 = NULL; static u8 d88header[0x2b0]; static u8 secheader[0x10]; static u8 derfile[((164*9+7)>>3)+1]; fp_der = fopen(der, "rb"); memset(derfile, 0, sizeof(derfile)); if (fp_der == NULL) { printf(" der is not used.\n"); } else { fread(derfile, 1, 0x14, fp_der); if (0 != memcmp(derfile, "DiskImage errors\x0D\x0A\x1A\x00", 0x14)) { printf(" wrong der file.\n"); ret = 21; goto FINISH; } memset(derfile, 0, sizeof(derfile)); fread(derfile, 1, sizeof(derfile), fp_der); printf("error_status=0x%02X\n", error_status); } fp_dsk = fopen(dsk, "rb"); fp_d88 = fopen(d88, "wb"); if ((fp_dsk == NULL) || (fp_d88 == NULL)) { printf(" file open error.\n"); ret = 22; goto FINISH; } memset(d88header, 0, sizeof(d88header)); d88header[0x1b] = 0x10; /* 0x00:2D 0x10:2DD 0x20:2HD */ fwrite(d88header, 1, sizeof(d88header), fp_d88); for(track=0; track<164; track+=2) { static u8 sector18[512*9*2]; size_t sz; sz = fread(sector18, 1, sizeof(sector18), fp_dsk); if (0 == sz) break; else if (sz < sizeof(sector18)) { printf(" dsk must be RAW, 2DD, 512bytes/sector, 9sectors/track.\n"); ret = 23; goto FINISH_DEL; } for(head=0; head<2; head++) for(sector=0; sector<9; sector++) { int logicalsector = (track+head)*9+sector; memset(secheader, 0, sizeof(secheader)); secheader[0] = track>>1; secheader[1] = head; secheader[2] = sector+1; secheader[3] = 2; /* 512bytes/sector */ secheader[4] = 9; secheader[8] = (derfile[logicalsector>>3]&(0x80>>(logicalsector&7)))?error_status:0; /* error_status */ secheader[15] = 2; /* 512>>8 */ fwrite(secheader, 1, sizeof(secheader), fp_d88); fwrite(sector18+512*(sector+head*9), 1, 512, fp_d88); } } fseek(fp_d88, 0x1c, SEEK_SET); { u32 *p = (u32*)(d88header+0x1c); u32 offset; *p = sizeof(d88header) + (u32)track*9*(512+sizeof(secheader)); p++; offset = sizeof(d88header); for(;track>0; track--) { *p = offset; p++; offset += 9*(512+sizeof(secheader)); } } fwrite(d88header+0x1c, 1, sizeof(d88header)-0x1c, fp_d88); FINISH: if (fp_dsk != NULL) fclose(fp_dsk); if (fp_der != NULL) fclose(fp_der); if (fp_d88 != NULL) fclose(fp_d88); return ret; FINISH_DEL: if (fp_dsk != NULL) fclose(fp_dsk); if (fp_der != NULL) fclose(fp_der); if (fp_d88 != NULL) fclose(fp_d88); remove(d88); return ret; } int main(int ac, char *av[]) { int ret = 0; u8 error_status; if ((sizeof(u8)!=1) || (sizeof(u16)!=2) || (sizeof(u32)!=4)) { printf("sizeof(u8)=%d sizeof(u16)=%d sizeof(u32)=%d\n", sizeof(u8), sizeof(u16), sizeof(u32)); printf(" please modify, recompile and set to sizeof(u8)=1, sizeof(u16)=2, sizeof(u32)=4\n"); ret = 1; goto FINISH; } { u32 a = 0x12345678; if (0x78 != *((u8*)(&a))) { printf(" please use on little endian.\n"); ret = 2; goto FINISH; } } if (ac<4) { printf("MSX 2DD RAW DiskImage (typically 737280 bytes) to D88 converter\n"); printf(" ver.2015-03-31 / umaiboux / C language\n"); printf(" 2DD, 512bytes/sector, 9sectors/track only\n"); printf(" usage: %s InputFile.dsk InputFile.der OutputFile.d88 [ErrorStatus]\n", av[0]); printf(" example: %s my.dsk my.der mytest.d88 0xb0\n", av[0]); printf(" if you don't use *.der, please set dummy der filename.\n"); ret = 3; goto FINISH; } ret = check_ext_all(av[1], av[2], av[3]); if (ret != 0) { goto FINISH; } if (ac<5) { error_status = 0xb0; } else { error_status = strtol(av[4], NULL, 0); } ret = write_d88(av[1], av[2], av[3], error_status); FINISH: printf("return code = %d\n", ret); return ret; }
C# dsk2d88.cs
using System; using System.IO; using System.Text; class dsk2d88 { static int write_d88(string dsk, string der, string d88, byte error_status) { int ret = 0; int track, head, sector; track=head=sector=0; byte[] d88header = new byte[0x2b0]; byte[] secheader = new byte[0x10]; byte[] derfile = new byte[((164*9+7)>>3)+1]; Array.Clear(derfile, 0, derfile.Length); try { using (FileStream fs_der = File.OpenRead(der)) { fs_der.Read(derfile, 0, 0x14); if ("DiskImage errors\x0D\x0A\x1A\x00" != Encoding.GetEncoding("ASCII").GetString(derfile, 0, 0x14)) { Console.WriteLine(" wrong der file.\n"); ret = 21; goto FINISH; } Array.Clear(derfile, 0, derfile.Length); fs_der.Read(derfile, 0, derfile.Length); Console.WriteLine("error_status = 0x{0}", error_status.ToString("X2")); } } catch /*(Exception e)*/ { //Console.WriteLine(e.Message); Console.WriteLine(" der is not used."); } try { using (FileStream fs_dsk = File.OpenRead(dsk)) using (FileStream fs_d88 = File.Open(d88, FileMode.Create, FileAccess.Write)) { Array.Clear(d88header, 0, d88header.Length); d88header[0x1b] = 0x10; /* 0x00:2D 0x10:2DD 0x20:2HD */ using (BinaryWriter bw = new BinaryWriter(fs_d88)) { bw.Write(d88header); for(track=0; track<164; track+=2) { byte[] sector18 = new byte[512*9*2]; int sz; sz = fs_dsk.Read(sector18, 0, sector18.Length); if (0 == sz) break; else if (sz < sector18.Length) { Console.WriteLine(" dsk must be RAW, 2DD, 512bytes/sector, 9sectors/track."); ret = 23; goto FINISH_DEL; } for(head=0; head<2; head++) for(sector=0; sector<9; sector++) { int logicalsector = (track+head)*9+sector; Array.Clear(secheader, 0, secheader.Length); secheader[0] = (byte)(track>>1); secheader[1] = (byte)head; secheader[2] = (byte)(sector+1); secheader[3] = 2; /* 512bytes/sector */ secheader[4] = 9; secheader[8] = 0!=(derfile[logicalsector>>3]&(0x80>>(logicalsector&7)))?error_status:(byte)0; /* error_status */ secheader[15] = 2; /* 512>>8 */ bw.Write(secheader); bw.Write(sector18,512*(sector+head*9), 512); } } bw.Seek(0x1c, SeekOrigin.Begin); bw.Write(d88header.Length + track*9*(512+secheader.Length)); int offset = d88header.Length; for(; track>0; track--) { bw.Write(offset); offset += 9*(512+secheader.Length); } } } } catch (Exception e) { Console.WriteLine(e.Message); //Console.WriteLine(" file open error."); ret = 22; goto FINISH; } FINISH: return ret; FINISH_DEL: File.Delete(d88); return ret; } static int check_ext(string filename, string ext) { int len_f, len_e; len_f = filename.Length; len_e = ext.Length; if (len_f < len_e) return 1; return String.Compare(filename.Substring(len_f - len_e), ext, true); } static int check_ext_all(string dsk, string der, string d88) { if ( (0 == check_ext(dsk, ".der")) || (0 == check_ext(dsk, ".d88")) || (0 != check_ext(der, ".der")) || (0 != check_ext(d88, ".d88")) ) { Console.WriteLine(" Filename extension error.\n"); return 11; } return 0; } static int Main(string[] args) { int ret = 0; byte error_status; if (!(BitConverter.IsLittleEndian)) { Console.WriteLine(" please use on little endian."); ret = 2; goto FINISH; } if (args.Length<3) { string av0; av0 = System.Windows.Forms.Application.ExecutablePath; av0 = System.IO.Path.GetFileName(av0); Console.WriteLine("MSX 2DD RAW DiskImage (typically 737280 bytes) to D88 converter"); Console.WriteLine(" ver.2015-03-31 / umaiboux / C#"); Console.WriteLine(" 2DD, 512bytes/sector, 9sectors/track only"); Console.WriteLine(" usage: {0} InputFile.dsk InputFile.der OutputFile.d88 [ErrorStatus]", av0); Console.WriteLine(" example: {0} my.dsk my.der mytest.d88 0xb0", av0); Console.WriteLine(" if you don't use *.der, please set dummy der filename."); ret = 3; goto FINISH; } ret = check_ext_all(args[0], args[1], args[2]); if (ret != 0) { goto FINISH; } if (args.Length<4) { error_status = 0xb0; } else { try { if ((args[3].Length > 2) && (args[3].Substring(0,2).ToLower() == "0x" )) { error_status = Convert.ToByte(args[3], 16); } else { error_status = Convert.ToByte(args[3]); } } catch (Exception e) { Console.WriteLine("ErrorStatus: " + e.Message); error_status = 0; } } ret = write_d88(args[0], args[1], args[2], error_status); FINISH: Console.WriteLine("return code = {0}", ret); return ret; } }
戻る
★
★
アクセス解析
SEO
/
SEO対策
★
FC2
:
Text
AD
:
開発・提供:皆C2
無料ホームページ
無料サービスランキング
ショッピングカート
BBS
ライブチャット
カウンター
投票
ドメイン登録798円〜
レンタルサーバー
アプリケーション開発
無料!可愛い出会い