244 lines
5.4 KiB
HolyC
Executable File
244 lines
5.4 KiB
HolyC
Executable File
Bool ISOInit(CDrv *dv,I64 blk)
|
|
{
|
|
CBlkDev *bd=dv->bd;
|
|
I64 spc=bd->blk_size>>BLK_SIZE_BITS,i=blk/spc,drv_offset=0;
|
|
CISOPriDesc *iso=MAlloc(bd->blk_size);
|
|
CISODirEntry *de;
|
|
Bool unlock,res=FALSE;
|
|
U8 buf[8];
|
|
|
|
try {
|
|
unlock=DrvLock(dv);
|
|
dv->fs_type=FSt_ISO9660;
|
|
dv->spc=spc;
|
|
dv->data_area=dv->root_clus=dv->drv_offset=bd->drv_offset=dv->size=0;
|
|
while (TRUE) {
|
|
dv->size=MaxI64(dv->size,(i+1)*spc);
|
|
BlkRead(dv,iso,i*spc,spc);
|
|
buf[0](U32)=iso->id[0](U32);
|
|
buf[4](U16)=iso->id[4](U8);
|
|
switch (LstMatch(buf,"CD001\0CDW02\0BEA01\0BOOT2\0NSR02\0NSR03\0TEA01\0",
|
|
LMF_EXACT)) {
|
|
case 0:
|
|
switch (iso->type) {
|
|
case ISOT_BOOT_RECORD:
|
|
drv_offset+=(2*DVD_BLK_SIZE+DVD_BLK_SIZE)/BLK_SIZE;
|
|
break;
|
|
case ISOT_SUPPLEMENTARY_DESC:
|
|
de=&iso->root_dir_record;
|
|
dv->size=iso->vol_space_size.little*bd->blk_size>>BLK_SIZE_BITS;
|
|
if (!StrCmp(iso->publisher_id,"TempleOS RedSea")) {
|
|
dv->fs_type=FSt_REDSEA;
|
|
bd->drv_offset=dv->drv_offset=19<<2+drv_offset;
|
|
bd->max_blk=dv->size-1;
|
|
dv->size-=bd->drv_offset;
|
|
RedSeaInit(dv);
|
|
} else
|
|
dv->root_clus=de->loc.little;
|
|
res=TRUE;
|
|
goto di_done;
|
|
case ISOT_TERMINATOR:
|
|
throw('Drv');
|
|
}
|
|
break;
|
|
default: //Its normal for ISO3346 to read NULL blk as terminator
|
|
PrintErr("File System Not Supported\n");
|
|
throw('Drv');
|
|
}
|
|
i++;
|
|
}
|
|
di_done:
|
|
Free(iso);
|
|
if (unlock)
|
|
DrvUnlock(dv);
|
|
} catch {
|
|
dv->fs_type=FSt_ISO9660;
|
|
dv->spc=spc;
|
|
dv->drv_offset=bd->drv_offset=dv->data_area=dv->root_clus=0;
|
|
Free(iso);
|
|
if (unlock)
|
|
DrvUnlock(dv);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
U0 DVDImageRead(U8 dvd_drv_let,U8 *out_name)
|
|
{//Read entire CD/DVD image into ISO file.
|
|
CDrv *dv=Let2Drv(dvd_drv_let);
|
|
CBlkDev *bd=dv->bd;
|
|
U8 *buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS),
|
|
*out_name2=ExtDft(out_name,"ISO");
|
|
CFile *f=FOpen(out_name2,"w");
|
|
I64 n,spc=bd->blk_size>>BLK_SIZE_BITS,blk=0,cnt,retry;
|
|
BlkDevInit(bd);
|
|
if (bd->type!=BDT_ATAPI)
|
|
throw('BlkDev');
|
|
if (!out_name)
|
|
out_name=blkdev.dft_iso_filename;
|
|
cnt=CeilU64(dv->size,spc);
|
|
while (cnt>0) {
|
|
if (cnt>COPY_BUF_BLKS)
|
|
n=COPY_BUF_BLKS;
|
|
else
|
|
n=cnt;
|
|
if (n>bd->max_reads)
|
|
n=bd->max_reads;
|
|
|
|
retry=4;
|
|
while (--retry)
|
|
if (ATAPIReadBlks2(bd,tS+7.0+0.004*n/spc,buf,blk/spc,n/spc,TRUE))
|
|
//n is 0x800 if max_reads. Up to 8 additional seconds
|
|
break;
|
|
|
|
if (!retry)
|
|
ATAPIReadBlks2(bd,0,buf,blk/spc,n/spc,TRUE);
|
|
|
|
FBlkWrite(f,buf,blk,n);
|
|
cnt-=n;
|
|
blk+=n;
|
|
}
|
|
FClose(f);
|
|
Free(buf);
|
|
Free(out_name2);
|
|
}
|
|
|
|
class CDualBuf
|
|
{
|
|
U8 *buf0,*buf1;
|
|
I64 in_buf,out_buf,cnt;
|
|
U8 *filename;
|
|
CBlkDev *dvd_bd;
|
|
};
|
|
|
|
U0 DVDImageWriteTask(CDualBuf *d)
|
|
{
|
|
U8 *buf;
|
|
I64 n,blk=0,cnt=d->cnt;
|
|
CFile *f;
|
|
if (FileAttr(d->filename)&RS_ATTR_CONTIGUOUS)
|
|
f=FOpen(d->filename,"rc");
|
|
else
|
|
f=FOpen(d->filename,"r");
|
|
while (cnt>0) {
|
|
if (cnt>COPY_BUF_BLKS)
|
|
n=COPY_BUF_BLKS;
|
|
else
|
|
n=cnt;
|
|
if (n>d->dvd_bd->max_writes)
|
|
n=d->dvd_bd->max_writes;
|
|
if (d->in_buf&1)
|
|
buf=d->buf1;
|
|
else
|
|
buf=d->buf0;
|
|
while (d->in_buf>d->out_buf+1)
|
|
Yield;
|
|
FBlkRead(f,buf,blk,n);
|
|
d->in_buf++;
|
|
cnt-=n;
|
|
blk+=n;
|
|
}
|
|
FClose(f);
|
|
}
|
|
|
|
U0 DVDImageWrite(U8 dvd_drv_let,U8 *in_name=NULL,I64 media_type=MT_DVD)
|
|
{//Write CD/DVD ISO file to disk.
|
|
CDualBuf *d=CAlloc(sizeof(CDualBuf));
|
|
U8 *buf,*in_name2,*in_name3;
|
|
I64 i,n,spc,blk=0,cnt;
|
|
CDrv *dv=Let2Drv(dvd_drv_let);
|
|
CBlkDev *bd=dv->bd,*bd2;
|
|
CTask *task;
|
|
CFile *f;
|
|
|
|
if (!in_name)
|
|
in_name=blkdev.dft_iso_filename;
|
|
in_name3=ExtDft(in_name,"ISO");
|
|
in_name2=FileNameAbs(in_name3);
|
|
f=FOpen(in_name2,"r");
|
|
if (!f) {
|
|
Free(d);
|
|
return;
|
|
}
|
|
cnt=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS;
|
|
FClose(f);
|
|
if (bd->type!=BDT_ATAPI)
|
|
throw('BlkDev');
|
|
bd2=Let2BlkDev(*in_name2);
|
|
while (bd2->lock_fwding)
|
|
bd2=bd2->lock_fwding; //If two blkdevs on same controller, use one lock
|
|
if ((bd2->type==BDT_ATA || bd2->type==BDT_ATAPI) &&
|
|
bd2->base0==bd->base0) {
|
|
PrintErr("Can't burn CD/DVD on same ATA controller as file.\n\n");
|
|
throw('BlkDev');
|
|
}
|
|
|
|
bd->flags|=BDF_READ_ONLY_OVERRIDE;
|
|
BlkDevInit(bd);
|
|
spc=bd->blk_size>>BLK_SIZE_BITS;
|
|
if (dv->size<cnt)
|
|
dv->size=cnt;
|
|
|
|
d->filename=in_name2;
|
|
d->dvd_bd=bd;
|
|
d->buf0=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
|
|
d->buf1=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
|
|
d->cnt=cnt;
|
|
|
|
task=Spawn(&DVDImageWriteTask,d,"Write CD/DVD");
|
|
while (d->in_buf<=d->out_buf)
|
|
Yield;
|
|
|
|
BlkDevLock(bd);
|
|
ATAPIWaitReady(bd,0);
|
|
|
|
progress1=0; progress1_max=cnt;
|
|
StrCpy(progress1_desc,"Writing");
|
|
while (cnt>0) {
|
|
if (cnt>COPY_BUF_BLKS)
|
|
n=COPY_BUF_BLKS;
|
|
else
|
|
n=cnt;
|
|
if (n>bd->max_writes)
|
|
n=bd->max_writes;
|
|
if (d->out_buf&1)
|
|
buf=d->buf1;
|
|
else
|
|
buf=d->buf0;
|
|
while (d->in_buf<=d->out_buf)
|
|
Yield;
|
|
ATAPIWriteBlks(bd,buf,blk/spc,(n+spc-1)/spc);
|
|
d->out_buf++;
|
|
cnt-=n;
|
|
blk+=n;
|
|
progress1+=n;
|
|
}
|
|
ATAPISync(bd);
|
|
|
|
progress1=0; progress1_max=2;
|
|
StrCpy(progress1_desc,"Closing");
|
|
for (i=0;i<2;i++) {
|
|
ATAPIClose(bd,0x100,i); //Close tracks
|
|
progress1++;
|
|
}
|
|
|
|
ATAPISync(bd);
|
|
|
|
ATAPIClose(bd,0x200); //close disk
|
|
ATAPISync(bd);
|
|
if (media_type==MT_DVD) {
|
|
ATAPIClose(bd,0x300);
|
|
ATAPISync(bd);
|
|
}
|
|
|
|
*progress1_desc=0;
|
|
progress1=progress1_max=0;
|
|
|
|
bd->flags&=~BDF_READ_ONLY_OVERRIDE;
|
|
BlkDevUnlock(bd);
|
|
Free(d->buf0);
|
|
Free(d->buf1);
|
|
Free(in_name2);
|
|
Free(in_name3);
|
|
Free(d);
|
|
}
|