Skip to content

Commit

Permalink
ディスクイメージの部分書き出しに対応。
Browse files Browse the repository at this point in the history
エントリ名指定オプションの仕様変更。
  • Loading branch information
BouKiCHi committed Jun 15, 2018
1 parent 2fcebbd commit b23a53b
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 73 deletions.
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "HuDisk append test",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/src/bin/Debug/netcoreapp2.0/HuDisk.dll",
"args": [
"test/TEST.D88",
"test/data/TEST.TXT",
"-a"
],
"cwd": "${workspaceFolder}/src",
"console": "internalConsole",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "HuDisk delete test",
"type": "coreclr",
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ IPLプログラムとして登録する場合はファイルサイズ分の連

* 展開時にファイル名を指定する
```
hudisk image.d88 -x file.txt --name localfile.txt
hudisk image.d88 -x localfile.txt --name etnry.txt
```

* 展開時にファイルを標準出力する
```
hudisk image.d88 -x file.txt --name -
hudisk image.d88 --name entry.txt -x -
```

## オプション
Expand All @@ -65,7 +65,7 @@ IPLプログラムとして登録する場合はファイルサイズ分の連
+ -r,--read {address} ... 読み出しアドレスの設定
+ -g,--go {address} ... 実行アドレスの設定
+ --x1s ... x1save.exe互換モードに設定
+ --name {name} エントリ名/出力ファイル名をnameに設定
+ --name {name} エントリ名をnameに設定

+ -h,-?,--help ... 表示

Expand All @@ -91,6 +91,10 @@ hudisk image.d88 file.bin --read 1234 --go 1234
+ [HuBASICフォーマット](doc/HuBASIC_Format.md)

## 履歴
* ver 1.12
ディスクイメージの部分書き換えに対応した。
エントリ名の指定(--name)を仕様変更した。

* ver 1.11
65535バイト以上のファイルの読み書きを可能にした。

Expand Down
Binary file modified hudisk.exe
Binary file not shown.
92 changes: 67 additions & 25 deletions src/DiskImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public enum DiskType
Disk2HD = 0x20
}

const int DefaultHeaderSize = 0x2b0;

const int DefaultSectorSize = 256;

const int MaxTrack = 164;

const int TrackPerSector2D = 16;
Expand All @@ -34,6 +38,8 @@ public enum DiskType

protected long[] TrackAddress = new long[MaxTrack];

protected long CurrentHeaderSize = 0;


protected List<SectorData> Sectors = new List<SectorData>();

Expand All @@ -42,7 +48,7 @@ public enum DiskType

public bool PlainFormat = false;

public string OutputName;
public string EntryName;

public DiskImage(string ImageFilePath)
{
Expand All @@ -61,11 +67,10 @@ public DiskImage(string ImageFilePath)
var ext = Path.GetExtension(ImageFilePath);
if (ext.StartsWith(".")) ext = ext.Substring(1);
ext = ext.ToUpper();
SpecialExtension(ext);

CheckExtension(ext);
}

private void SpecialExtension(string ext)
private void CheckExtension(string ext)
{
if (ext != "2D" && ext != "2HD") return;
PlainFormat = true;
Expand All @@ -80,13 +85,14 @@ public virtual void Format2D()

private void TrackFormat(int TrackMax, int TrackPerSector)
{
for (var t = 0; t < TrackMax; t++)
{
for (var s = 0; s < TrackPerSector; s++)
{
var Position = PlainFormat ? 0x0 : DefaultHeaderSize;
for (var t = 0; t < TrackMax; t++) {
TrackAddress[t] = Position;
for (var s = 0; s < TrackPerSector; s++) {
var Sector = new SectorData();
Sector.Make(t >> 1, t & 1, s + 1, 1, TrackPerSector, 0, false, 0, 256);
Sector.Make(t >> 1, t & 1, s + 1, 1, TrackPerSector, 0, false, 0, DefaultSectorSize);
Sectors.Add(Sector);
Position += DefaultSectorSize;
}
}
}
Expand Down Expand Up @@ -116,6 +122,7 @@ public void Format() {
Format2DD();
break;
}
CurrentHeaderSize = 0;
}

public void Write()
Expand All @@ -125,22 +132,39 @@ public void Write()
FileAccess.Write,
FileShare.ReadWrite);

if (!PlainFormat) WriteHeader(fs);
WriteSectors(fs);
var RebuildImage = IsRewriteImage();
if (Verbose) Console.WriteLine("RebuildImage:" + RebuildImage.ToString());
if (!PlainFormat) {
if (RebuildImage) WriteHeader(fs);
}
WriteSectors(fs,RebuildImage);
fs.Close();
}

public bool IsRewriteImage() {
var LastTrack = -1;
var MaxDirtyTrack = 0;
foreach (SectorData s in Sectors) {
if (s.IsDirty) MaxDirtyTrack = s.Track;
}

for (var i = 0; i < MaxTrack; i++) {
if (TrackAddress[i] == 0x0) break;
LastTrack = i;
}
if (!PlainFormat && CurrentHeaderSize != DefaultHeaderSize) return true;
if (LastTrack < MaxDirtyTrack) return true;

return false;
}

private void WriteHeader(FileStream fs)
{
byte[] header = new byte[0x2b0];
byte[] header = new byte[DefaultHeaderSize];
ImageSize = header.Length;
int t = 0;
foreach (SectorData s in Sectors)
{
if (s.Sector == 0x01)
{
TrackAddress[t++] = ImageSize;
}
foreach (SectorData s in Sectors) {
if (s.Sector == 0x01) TrackAddress[t++] = ImageSize;
ImageSize += s.GetLength();
}

Expand All @@ -161,10 +185,27 @@ private void WriteHeader(FileStream fs)
fs.Write(header, 0, header.Length);
}

private void WriteSectors(FileStream fs)
private void WriteSectors(FileStream fs,bool isRebuild)
{
var Length = fs.Length;
var Position = TrackAddress[0];
var Skip = true;

foreach (SectorData s in Sectors)
{
if (!isRebuild) {
// 変更セクタまでスキップする
if (Position < Length && !s.IsDirty) {
Position += s.GetLength();
Skip = true;
continue;
}
if (Skip) {
fs.Position = Position;
Skip = false;
}
Position += s.GetLength();
}
byte[] d = PlainFormat ? s.Data : s.GetBytes();
fs.Write(d, 0, d.Length);
}
Expand Down Expand Up @@ -215,8 +256,7 @@ string GetDiskTypeName()
}
}

void ReadHeader(FileStream fs)
{
void ReadHeader(FileStream fs) {
byte[] header = new byte[0x2b0];
fs.Read(header, 0, header.Length);

Expand All @@ -227,9 +267,12 @@ void ReadHeader(FileStream fs)
ImageType = (DiskType)Enum.ToObject(typeof(DiskType), t);
ImageSize = (long)dc.GetLong(0x1c);

for (var i = 0; i < MaxTrack; i++)
{
TrackAddress[i] = (long)dc.GetLong(0x20 + (i * 4));
CurrentHeaderSize = 0;

for (var i = 0; i < MaxTrack; i++) {
var a = (long)dc.GetLong(0x20 + (i * 4));
TrackAddress[i] = a;
if (i == 0) CurrentHeaderSize = a;
}
}

Expand Down Expand Up @@ -287,6 +330,5 @@ public virtual void ExtractFiles(string Pattern) {
public virtual void DeleteFiles(string Pattern) {
}


}
}
2 changes: 1 addition & 1 deletion src/DiskManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void RunDiskEdit(MiniOption Options, DiskImage Image)
break;
case RunModeType.Extract:
Console.WriteLine("Extract files:");
Image.OutputName = EntryName;
Image.EntryName = EntryName;
EditFiles(Options,Image,true,false);
break;

Expand Down
45 changes: 28 additions & 17 deletions src/HuBasicDiskImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public HuBasicDiskImage(string Path) : base(Path)

private void FillFileSystem()
{
var dc = new DataController(Sectors[AllocationTableStart].Data);
var dc = GetDataControllerForWrite(AllocationTableStart);
dc.Fill(0);
dc.SetByte(0, 0x01);
dc.SetByte(1, 0x8f);
Expand Down Expand Up @@ -130,12 +130,20 @@ private void SetDiskParameter() {

private void SetAllocateController() {
AllocationController = new DataController[2];
AllocationController[0] = new DataController(Sectors[AllocationTableStart].Data);
AllocationController[0] = GetDataControllerForWrite(AllocationTableStart);
if (ImageType == DiskType.Disk2DD || ImageType ==DiskType.Disk2HD) {
AllocationController[1] = new DataController(Sectors[AllocationTableStart+1].Data);
AllocationController[1] = GetDataControllerForWrite(AllocationTableStart+1);
}
}

private DataController GetDataControllerForWrite(int Sector) {
Sectors[Sector].IsDirty = true;
return new DataController(Sectors[Sector].Data);
}
private DataController GetDataControllerForRead(int Sector) {
return new DataController(Sectors[Sector].Data);
}


public int GetNextFreeCluster(int Step=1) {
for(var i=0; i<MaxCluster; i++) {
Expand Down Expand Up @@ -189,7 +197,7 @@ public void RemoveAllocation(int StartCluster) {
var FillLength = end ? (next & 0x0f) + 1 : ClusterPerSector;

for(var i=0; i < FillLength; i++) {
(new DataController(Sectors[(c*ClusterPerSector)+i].Data)).Fill(0);
GetDataControllerForWrite((c*ClusterPerSector)+i).Fill(0);
}
// 0x8x = 最後のクラスタ
if (end) break;
Expand Down Expand Up @@ -244,7 +252,7 @@ public List<HuFileEntry> GetEntriesFromSector(int Sector)
List<HuFileEntry> FileList = new List<HuFileEntry>();
for (int i = 0; i < ClusterPerSector; i++,Sector++)
{
var dc = new DataController(Sectors[Sector].Data);
var dc = GetDataControllerForRead(Sector);
for (var j = 0; j < 8; j++)
{
int pos = (j * 0x20);
Expand Down Expand Up @@ -274,7 +282,7 @@ public HuFileEntry GetFileEntry(string Filename, int EntrySector)

for (int i = 0; i < ClusterPerSector; i++,Sector++)
{
var dc = new DataController(Sectors[Sector].Data);
var dc = GetDataControllerForRead(Sector);
for (var j = 0; j < EntriesInSector; j++)
{
int pos = (j * FileEntrySize);
Expand All @@ -290,18 +298,18 @@ public HuFileEntry GetFileEntry(string Filename, int EntrySector)
return null;
}

public HuFileEntry GetNewFileEntry(int sector)
public HuFileEntry GetNewFileEntry(int Sector)
{
for (int i = 0; i < ClusterPerSector; i++)
{
var dc = new DataController(Sectors[sector + i].Data);
var dc = GetDataControllerForRead(Sector+i);
for (var j = 0; j < EntriesInSector; j++)
{
int pos = (j * FileEntrySize);
var mode = dc.GetByte(pos);
if (mode != EntryEnd && mode != EntryDelete) continue;
var fe = new HuFileEntry();
fe.EntrySector = sector + i;
fe.EntrySector = Sector + i;
fe.EntryPosition = pos;
return fe;
}
Expand All @@ -324,13 +332,13 @@ public void FileEntryNormalize(HuFileEntry fe) {
// ファイルエントリ書き出し
public void WriteFileEntry(HuFileEntry fe) {
FileEntryNormalize(fe);
var dc = new DataController(Sectors[fe.EntrySector].Data);
var dc = GetDataControllerForWrite(fe.EntrySector);
WriteEntry(dc,fe,fe.EntryPosition ,fe.StartCluster,false);
}

// IPLエントリ書き出し
public void WriteIplEntry(HuFileEntry fe) {
var dc = new DataController(Sectors[0].Data);
var dc = GetDataControllerForWrite(0);
WriteEntry(dc,fe,0x00,fe.StartCluster * ClusterPerSector,true);
}

Expand Down Expand Up @@ -462,7 +470,7 @@ public override bool AddFile(string FilePath,string EntryName) {
}

if (fe == null) {
Console.WriteLine("no entry space!");
Console.WriteLine("ERROR:No entry space!");
return false;
}

Expand All @@ -484,7 +492,7 @@ public override bool AddFile(string FilePath,string EntryName) {
fc = GetNextFreeCluster();
}
if (fc < 0) {
Console.WriteLine("no free cluster!");
Console.WriteLine("ERROR:No free cluster!");
return false;
}
fe.StartCluster = fc;
Expand All @@ -505,15 +513,18 @@ private string PatternToRegex(string Pattern) {
return "^" + Regex.Escape(Pattern).Replace(@"\*", ".*" ).Replace( @"\?", "." ) + "$";
}

private void PatternFiles(string Pattern,bool Extract,bool Delete) {
var r = new Regex(PatternToRegex(Pattern),RegexOptions.IgnoreCase);
private void PatternFiles(string Name,bool Extract,bool Delete) {
string EntryPattern = !string.IsNullOrEmpty(EntryName) ? EntryName : Name;

var r = new Regex(PatternToRegex(EntryPattern),RegexOptions.IgnoreCase);
var Files = GetEntriesFromSector(EntrySector);
foreach(var fe in Files) {
if (!r.IsMatch(fe.GetFilename())) continue;
fe.Description();
var OutputName = !string.IsNullOrEmpty(EntryName) ? Name : fe.GetFilename();

if (Extract) {
string name =!string.IsNullOrEmpty(OutputName) ? OutputName : fe.GetFilename();
ExtractFileFromCluster(name,fe.StartCluster,fe.Size);
ExtractFileFromCluster(OutputName, fe.StartCluster, fe.Size);
}
if (Delete) {
fe.SetDelete();
Expand Down
Loading

0 comments on commit b23a53b

Please sign in to comment.