xeij/SCMedia.java
//========================================================================================
//  SCMedia.java
//    en:SCSI hard disk media
//    ja:SCSIハードディスクメディア
//  Copyright (C) 2003-2019 Makoto Kamada
//
//  This file is part of the XEiJ (X68000 Emulator in Java).
//  You can use, modify and redistribute the XEiJ if the conditions are met.
//  Read the XEiJ License for more details.
//  https://stdkmd.net/xeij/
//========================================================================================

//----------------------------------------------------------------------------------------
//  SCSIハードディスクのメディアの種類
//----------------------------------------------------------------------------------------

package xeij;

import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,Timer,TimerTask,TreeMap

public class SCMedia extends HumanMedia {

  public int scmBytesShiftRecord;  //1レコードあたりのバイト数のシフトカウント
  public int scmBytesPerRecord;  //1レコードあたりのバイト数(2の累乗)
  public int scmDiskEndRecord;  //ディスクのレコード数
  public int scmPartitionStartSector;  //ディスクの先頭からパーティションの先頭までのセクタ数
  public int scmDiskEndSector;  //ディスクのセクタ数

  public SCMedia (int bytesPerRecord, int diskEndRecord) {
    super (1024,  //bytesPerSector
           -1,    //sectorsPerCluster
           2,     //fatCount
           1,     //reservedSectors
           512,   //rootEntries
           0xf7,  //mediaByte
           0xf7,  //fatID
           -1,    //fatSectors
           (long) bytesPerRecord * diskEndRecord,   //diskEndByte
           32768L,                                  //partitionStartByte
           (long) bytesPerRecord * diskEndRecord);  //partitionEndByte
    scmBytesShiftRecord = Integer.numberOfTrailingZeros (bytesPerRecord);  //1レコードあたりのバイト数のシフトカウント
    scmBytesPerRecord = 1 << scmBytesShiftRecord;  //1レコードあたりのバイト数(2の累乗)
    scmDiskEndRecord = diskEndRecord;  //ディスクのレコード数
    scmPartitionStartSector = (int) (humPartitionStartByte >> humBytesShiftSector);  //ディスクの先頭からパーティションの先頭までのセクタ数
    scmDiskEndSector = (int) (humDiskEndByte >> humBytesShiftSector);  //ディスクのセクタ数
  }  //new SCMedia()

  //success = media.scmMakeFormatData (bb, partitioningOn, copySystemFiles)
  //  SCSIディスクのフォーマットデータを作る
  public boolean scmMakeFormatData (byte[] bb, boolean partitioningOn, boolean copyHumanSysOn, boolean copyCommandXOn) {
    Arrays.fill (bb, (byte) 0);
    //SCSIディスクIDを作る
    System.arraycopy (SPC.SPC_DISK_ID_1, 0, bb, 0x00000000, SPC.SPC_DISK_ID_1.length);
    ByteArray.byaWw (bb, 0x00000008, scmBytesPerRecord);  //1レコードあたりのバイト数(2の累乗)
    ByteArray.byaWl (bb, 0x0000000a, scmDiskEndRecord);  //ディスクのレコード数
    ByteArray.byaWw (bb, 0x0000000e, 0x0100);
    System.arraycopy (SPC.SPC_DISK_ID_2, 0, bb, 0x00000010, SPC.SPC_DISK_ID_2.length);
    //SCSIディスクIPLを書き込む
    System.arraycopy (SPC.SPC_DISK_IPL, 0, bb, 0x00000400, SPC.SPC_DISK_IPL.length);
    //パーティションテーブルを作る
    ByteArray.byaWl (bb, 0x00000800, 'X' << 24 | '6' << 16 | '8' << 8 | 'K');  //X68Kマジック
    if (partitioningOn) {
      ByteArray.byaWl (bb, 0x00000804, scmDiskEndSector);  //ディスクの先頭から確保されている最後のパーティションの末尾までのセクタ数
    } else {
      ByteArray.byaWl (bb, 0x00000804, scmPartitionStartSector);  //ディスクの先頭から確保されている最後のパーティションの末尾までのセクタ数
    }
    ByteArray.byaWl (bb, 0x00000808, scmDiskEndSector);  //ディスクのセクタ数
    ByteArray.byaWl (bb, 0x0000080c, scmDiskEndSector);  //ディスクのセクタ数
    if (partitioningOn) {
      ByteArray.byaWl (bb, 0x00000810, 'H' << 24 | 'u' << 16 | 'm' << 8 | 'a');  //Humaマジック
      ByteArray.byaWl (bb, 0x00000814, 'n' << 24 | '6' << 16 | '8' << 8 | 'k');  //n68kマジック
      ByteArray.byaWl (bb, 0x00000818, scmPartitionStartSector);  //(0=自動起動,1=使用不可,2=使用可能)<<24|ディスクの先頭からパーティションの先頭までのセクタ数
      ByteArray.byaWl (bb, 0x0000081c, humPartitionSectors);  //パーティションのセクタ数
    }
    //SCSIデバイスドライバを書き込む
    System.arraycopy (SPC.SPC_DEVICE_DRIVER, 0, bb, 0x00000c00, SPC.SPC_DEVICE_DRIVER.length);
    if (partitioningOn) {
      //SCSIパーティションIPLを書き込む
      System.arraycopy (SPC.SPC_PARTITION_IPL, 0, bb, (int) humPartitionStartByte, SPC.SPC_PARTITION_IPL.length);
      //SCSIパーティションIPLにBPBを埋め込む
      ByteArray.byaWw (bb, (int) humPartitionStartByte + 0x12, humBytesPerSector);        //7bd4  0000.w  1セクタあたりのバイト数(2の累乗)
      ByteArray.byaWb (bb, (int) humPartitionStartByte + 0x14, humSectorsPerCluster);     //7bd6  0002.b  1クラスタあたりのセクタ数(2の累乗)
      ByteArray.byaWb (bb, (int) humPartitionStartByte + 0x15, humFatCount);              //7bd7  0003.b  FAT領域の個数
      ByteArray.byaWw (bb, (int) humPartitionStartByte + 0x16, humReservedSectors);       //7bd8  0004.w  予約領域のセクタ数(FAT領域の先頭セクタ番号)
      ByteArray.byaWw (bb, (int) humPartitionStartByte + 0x18, humRootEntries);           //7bda  0006.w  ルートディレクトリに入るエントリ数
      ByteArray.byaWw (bb, (int) humPartitionStartByte + 0x1a, 0);                        //7bdc  0008.w  全領域のセクタ数(0のとき000c.lを使う)
      ByteArray.byaWb (bb, (int) humPartitionStartByte + 0x1c, humFatID);                 //7bde  000a.b  FATID
      ByteArray.byaWb (bb, (int) humPartitionStartByte + 0x1d, humFatSectors);            //7bdf  000b.b  1個のFAT領域に使用するセクタ数
      ByteArray.byaWl (bb, (int) humPartitionStartByte + 0x1e, humPartitionSectors);      //7be0  000c.l  パーティションのセクタ数
      ByteArray.byaWl (bb, (int) humPartitionStartByte + 0x22, scmPartitionStartSector);  //7be4  0010.l  ディスクの先頭からパーティションの先頭までのセクタ数
      //FAT領域の先頭にFATマーカーを書き込む
      humWriteFatMarker (bb);
      //システムファイルを転送する
      //if (copySystemFiles) {
      //  if (!humCopyHumanSys (bb) ||
      //      !humCopyCommandX (bb)) {
      //    return false;
      //  }
      //}
      if (copyHumanSysOn) {
        if (!humCopyHumanSys (bb)) {
          return false;
        }
        if (copyCommandXOn) {
          if (!humCopyCommandX (bb)) {
            return false;
          }
        }
      }
      if (false) {
        humDumpFat (bb);
      }
    }
    return true;
  }  //media.scmMakeFormatData(byte[],boolean,boolean)

}  //class SCMedia