#help_index "File/CD DVD" U0 FillU16Palindrome(CPalindromeU16 *dst, U16 w) { dst->big = EndianU16(w); dst->little = w; } U0 FillU32Palindrome(CPalindromeU32 *dst, I64 d) { dst->big = EndianU32(d); dst->little = d; } class CElTorito { U16 w[16]; U8 bootable; // 88=bootable 00=not bootable U8 media_type; // 0=no emulation 4=hard disk U16 load_seg; // 0000->07C0 U8 sys_type; U8 zero; U16 sect_count; U32 load_rba; // start addr of virtual disk U8 zero2[20]; }; U0 RedSeaISO9660Stage1(U8 *iso_filename, U8 *stage2_filename) { CDirEntry de; CFile *out_file = NULL; U8 *stage1_buf = CAlloc(DVD_BOOT_LOADER_SIZE); if (FileFind(stage2_filename, &de) && (out_file = FOpen(iso_filename, "wc+"))) { MemCopy(stage1_buf, BDVD_START, BDVD_END - BDVD_START); *(BDVD_BLK_LO - BDVD_START + stage1_buf)(U32 *) = de.clus >> 2; *(BDVD_BLK_COUNT - BDVD_START + stage1_buf)(U16 *) = (de.size + DVD_BLK_SIZE - 1) >> (BLK_SIZE_BITS + 2); *(BDVD_SHIFT_BLKS - BDVD_START + stage1_buf)(U16 *) = de.clus & 3; if (de.clus & 3) *(BDVD_BLK_COUNT - BDVD_START + stage1_buf)(U16 *) += 1; FBlkWrite(out_file, stage1_buf, 20 << 2 + 1 << 2, DVD_BOOT_LOADER_SIZE / BLK_SIZE); FClose(out_file); } Free(stage1_buf); } U0 RedSeaISO9660(U8 *iso_filename, U8 drv_let) { CDrive *drive = Letter2Drive(drv_let); CISOPriDesc *iso_pri = CAlloc(DVD_BLK_SIZE), *iso_boot = CAlloc(DVD_BLK_SIZE), *iso_sup = CAlloc(DVD_BLK_SIZE), *iso_term = CAlloc(DVD_BLK_SIZE); I64 iso_size = 0, i, j; U32 *d; CElTorito *et = CAlloc(DVD_BLK_SIZE); U8 *zero_buf = CAlloc(DVD_BLK_SIZE); CFile *out_file = NULL; if (out_file = FOpen(iso_filename, "wc+")) { iso_size = FSize(out_file) / DVD_BLK_SIZE; for (i = 0; i < drive->bd->drv_offset; i += 4) FBlkWrite(out_file, zero_buf, i, 4); iso_pri->type = ISOT_PRI_VOL_DESC; StrCopy(iso_pri->id, "CD001"); iso_pri->version = 1; FillU16Palindrome(&iso_pri->vol_set_size, 1); FillU16Palindrome(&iso_pri->vol_seq_num, 1); FillU16Palindrome(&iso_pri->log_block_size, DVD_BLK_SIZE); FillU32Palindrome(&iso_pri->vol_space_size, iso_size); FillU32Palindrome(&iso_pri->root_dir_record, drive->root_clus); iso_pri->file_structure_version = 1; StrCopy(iso_pri->publisher_id, "ZealOS RedSea"); MemCopy(iso_sup, iso_pri, DVD_BLK_SIZE); iso_sup->type = ISOT_SUPPLEMENTARY_DESC; iso_boot->type = ISOT_BOOT_RECORD; StrCopy(iso_boot->id, "CD001"); iso_boot->version = 1; StrCopy(iso_boot(U8 *) + 7, "EL TORITO SPECIFICATION"); FBlkWrite(out_file, iso_pri, 16 << 2, 4); iso_term->type = ISOT_TERMINATOR; StrCopy(iso_term->id, "CD001"); iso_term->version = 1; d = iso_boot(U8 *) + 0x47; *d = 20 << 2 >> 2; FBlkWrite(out_file, iso_boot, 17 << 2, 4); FBlkWrite(out_file, iso_sup, 18 << 2, 4); FBlkWrite(out_file, iso_term, 19 << 2, 4); et->w[0] = 1; StrCopy(&et->w[2], "ZealOS"); et->w[15] = 0xAA55; j = 0; for (i = 0; i < 16; i++) //Checksum j += et->w[i]; et->w[14] = -j; et->bootable = 0x88; et->media_type = 0;//0=no emu 2=1.44meg 4=hard drive et->sect_count = 4; //5 seems like the limit, 4 is safer et->load_rba = 20 << 2 >> 2 + 1; FBlkWrite(out_file, et, 20 << 2, 4); FClose(out_file); } Free(zero_buf); Free(et); Free(iso_pri); Free(iso_boot); Free(iso_sup); Free(iso_term); } I64 RedSeaISOPass1(CDirEntry *tmpde) { I64 dir_entry_count = 3 + LinkedListCount(tmpde), res = 0; while (tmpde) { if (tmpde->attr & RS_ATTR_DIR) { if (tmpde->sub) res += RedSeaISOPass1(tmpde->sub); else res += BLK_SIZE; //Empty dir } else res += CeilU64(tmpde->size, BLK_SIZE); tmpde = tmpde->next; } res += CeilU64(dir_entry_count << 6, BLK_SIZE); //Size in bytes #assert CDIR_SIZE == 64 return res; } public I64 RedSeaISO(U8 *_iso_filename=NULL, U8 *_src_dir, U8 *_stage2_filename=NULL) {//See ::/Misc/DoDistro.CC. Must be ISO.C I64 i, res, root_count, root_dir_blks, bitmap_blks, bitmap_blks1; CDirEntry *tmpde; U8 buf[STR_LEN], *iso_filename, *src_dir, *stage2_filename; CDrive *drive = DriveMakeFreeSlot(DriveNextFreeLet('Q')); //First BDT_ISO_FILE_WRITE CBlkDev *bd = BlkDevNextFreeSlot(drive->drv_let, BDT_ISO_FILE_WRITE); if (!IsDir(_src_dir)) PrintErr("'%s' is not a dir.\n", _src_dir); else { if (!_iso_filename) _iso_filename = blkdev.default_iso_c_filename; iso_filename = ExtChange(_iso_filename, "ISO.C"); src_dir = DirNameAbs(_src_dir); if (_stage2_filename) { stage2_filename = FileNameAbs(_stage2_filename); *stage2_filename = drive->drv_let; i = StrLen(src_dir); if (i != 3) //If not root i++; //Skip slash StrCopy(stage2_filename + 3, stage2_filename + i); } else stage2_filename = NULL; tmpde = FilesFind(src_dir, FUF_RECURSE); root_count = LinkedListCount(tmpde) + 3; root_dir_blks = CeilU64(root_count << 6, BLK_SIZE) >> BLK_SIZE_BITS; if (res = RedSeaISOPass1(tmpde) >> BLK_SIZE_BITS) { bd->drv_offset = 19 << 2 + (DVD_BLK_SIZE * 2 + DVD_BOOT_LOADER_SIZE) / BLK_SIZE; bitmap_blks = 1; do { bitmap_blks1 = bitmap_blks; bitmap_blks = (res + bitmap_blks + BLK_SIZE << 3 - 1) / BLK_SIZE << 3; } while (bitmap_blks != bitmap_blks1); bd->max_blk = CeilI64(bd->drv_offset + 1 + bitmap_blks + res, 4); bd->max_blk--; //Inclusive. bd->file_disk_name = SysStrNew(iso_filename); bd->init_root_dir_blks = root_dir_blks; BlkDevAdd(bd,, TRUE, TRUE); StrPrint(buf, "%C:/", drive->drv_let); CopyTree(src_dir, buf, TRUE); RedSeaISO9660Stage1(iso_filename, stage2_filename); DriveDel(drive); BlkDevDel(bd); } Free(stage2_filename); Free(src_dir); Free(iso_filename); } return res; }