65.9K
CodeProject 正在变化。 阅读更多。
Home

Bin2Iso

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (60投票s)

2003年7月22日

4分钟阅读

viewsIcon

524120

downloadIcon

18164

一个免费工具,用于将 Bin 映像格式转换为 ISO 映像格式。

Sample Image - Bin2Iso.jpg

引言

这是一个免费工具,用于将一种CD映像格式(Bin)转换为另一种格式(ISO)。转换过程非常简单。只需读取Bin映像,并根据其结构,以另一种格式写入数据。为此,开发人员必须了解这两种格式的结构。

映像格式

CD-ROM规范(Yellow Book)定义了两种类型的扇区:模式1和模式2。模式2扇区用于CD-ROM XA格式。

CD-ROM扇区

存储在CD-ROM光盘上的数据被划分为扇区,这些扇区相当于CD音频光盘的音频帧。在正常(1倍速)播放速度下,每秒读取75个扇区。对于双速CD-ROM驱动器,这会增加到每秒150个扇区,依此类推。随着速度的提高,寻道时间(光盘旋转到所需起始位置所需的时间)也会缩短。

由于CD最初主要是为音频设计的,因此将其用于计算机数据需要添加每个扇区中都包含的头部数据和错误校正码。CD-ROM规范定义了两种不同类型的扇区:模式1模式2(后者用于CD-ROM XA光盘)。

模式1扇区

模式1扇区用于存储计算机数据,并包含以下字段。

  • Sync(12字节),用于使播放器能够识别每个扇区的起始位置。
  • Header(4字节),包含分钟、秒、扇区和模式(=1)。
  • ECC(错误校正码 - 276字节),包含额外的CIRC错误保护级别。
  • EDC(错误检测码 - 4字节),用于检测需要纠正的错误。

模式1扇区是最简单的类型,用于大多数遵循Yellow Book的基于CD-ROM的格式。

模式2扇区

模式2扇区用于基于CD-ROM XA的格式,可以是Form 1或Form 2。

  • 模式2 Form 1扇区包含2048字节,具有与模式1扇区相同的ECC。
  • 模式2 Form 2扇区每扇区包含2324字节用户数据,没有ECC,仅适用于可以隐藏错误的数据(例如音频或视频数据)。

模式2扇区包含以下字段:

  • Sync(12字节),用于使播放器能够识别每个扇区的起始位置。
  • Header(4字节),包含分钟、秒、扇区和模式(=1)。
  • Subheader(8字节),包含内容相关参数,例如数据类型。
  • ECC(错误校正码 - 276字节),包含仅适用于Form 1的额外CIRC错误保护级别。
  • EDC(错误检测码),适用于Form 1和Form 2。

请注意,模式1和模式2 Form 1使用相同的错误校正,因此可以互换使用,但不能在同一音轨内使用,最好也不要在同一光盘上使用。用于刻录CD-R的软件可以设置为模式1或模式2 Form 1。几乎所有的PC和Mac都可以读取模式2 Form 1 CD-ROM以及模式1。

请注意,任何CD-ROM至少会包含一些模式1或模式2 Form 1扇区。

容量

CD-ROM的容量取决于它是模式1 CD-ROM还是模式2 CD-ROM XA。假设最大容量为推荐的76分30秒,这意味着CD-ROM上有336,300个扇区。从中必须减去音轨1开头处的166个扇区,加上用于文件系统的几个扇区,总计约200个扇区,剩余336,100个扇区用于用户数据。

  • 模式1扇区每扇区包含2048字节,总容量为688,332,800字节或656MB(其中1 MB = 1024 * 1024)。
  • 模式2扇区每扇区包含2048或2324字节,因此容量会略高,具体取决于这两种扇区的混合比例。

以上假设CD-ROM由单个会话中的单个音轨组成。对于多音轨/多会话光盘,数据容量会减少。

解决方案

有了这些信息,就可以轻松开发一个程序来将一种映像格式转换为另一种。
程序中的主例程是Convert。下面的代码向您展示了所采用的技术。

UINT Convert(LPVOID pParam)
{
    PThreadData pth=(PThreadData) pParam;
    
    //Open files for reading/writing

    int   seek_header, seek_ecc, sector_size;
    long  i, source_length;
    char  buf[2352];
    const BYTE SYNC_HEADER[12] = 
        {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0};
    
    FILE *fpSource, *fpTarget;

    fpSource = _tfopen(pth->Source, _T("rb"));
    fpTarget = _tfopen(pth->Target, _T("wb"));

    
    if ((fpSource==NULL) || (fpTarget==NULL))
    {
        ::SendMessage(pth->hwnd, WM_THREAD_TERMINATE, 0, 
                (LPARAM) FILE_FAILED);
        
        return -1;
    }
    
    fread(buf, sizeof(char), 16, fpSource);

    if (memcmp(SYNC_HEADER, buf, 12))
    {
        seek_header = 8;        
        seek_ecc = 280;
        sector_size = 2336;
    }
    else        
    {
        switch(buf[15])
        {
            case 2:
            {    
                seek_header = 24;    // Mode2/2352    

                seek_ecc = 280;
                sector_size = 2352;
                break;
            }

            case 1:
            {
                seek_header = 16;    // Mode1/2352

                seek_ecc = 288;
                sector_size = 2352;
                break;
            }

            default:
            {
                ::SendMessage(pth->hwnd, WM_THREAD_TERMINATE, 
                    0, (LPARAM) TRACK_UNSUPPORTED);

                fclose(fpTarget);
                fclose(fpSource);

                return -1;
            }
        }
    }

    fseek(fpSource, 0L, SEEK_END);
    source_length = ftell(fpSource)/sector_size;
    fseek(fpSource, 0L, SEEK_SET);

    for(i=0; i<source_length; i++)
    {
        fseek(fpSource, seek_header, SEEK_CUR);
        fread(buf, sizeof(char), 2048, fpSource);  
        fwrite(buf, sizeof(char), 2048, fpTarget);
        fseek(fpSource, seek_ecc, SEEK_CUR);

        ::SendMessage(pth->hwnd, WM_THREAD_PROGRESS, 0, 
                (LPARAM) ((i+1)*100/source_length));
    }

    fclose(fpTarget);
    fclose(fpSource);

    return 0;
}

当按下“转换”按钮时,此函数将作为一个新线程调用。

更多信息

有关更多信息,请参阅Distronics网站。他们的网站上提供了关于各种CD/DVD技术的非常有用的信息。

尽情享用!

© . All rights reserved.