//See Install Documentation.
//Study the account examples: Config Strs, Update Funs

#include "BootHD"

#help_index "Install"

#define KERNEL_ZXE          "Kernel.ZXE"
#define BOOT_DIR                "/Boot"
#define BOOT_DIR_KERNEL_ZXE BOOT_DIR "/" KERNEL_ZXE

U0 CompComp()
{
    if (Comp("/Compiler/Compiler", "Compiler",, ':'))
        throw;
}

U0 MakeAll()
{
    CompComp;
    if (Comp("/Kernel/Kernel", "Kernel",, ':'))
        throw;
}

public U0 BootHDIns(U8 drv_let=0)
{//MakeAll and install new boot-loader.
    CDrive      *drive;
    CFAT32Boot   br;
    CDirEntry    de;
    I64          i;

    try
    {
        if (!Drive(drv_let))
            throw;

        drive = Fs->cur_dv;
        MakeAll;

        switch (Letter2BlkDevType(drive->drv_let))
        {
            case BDT_RAM:
            case BDT_ATA:
                Move("/Kernel/Kernel.ZXE", BOOT_DIR_KERNEL_ZXE);

                if (!FileFind(BOOT_DIR_KERNEL_ZXE, &de, FUF_JUST_FILES))
                    "No Kernel.ZXE\n";
                else
                {
                    Free(de.full_name);
                    "Modifying partition boot record.\n";
                    BlkRead(drive, &br, drive->drv_offset, 1);

                    br.jump_and_nop[0] = OC_JMP_REL8;
                    br.jump_and_nop[1] = offset(CFAT32Boot.code) - 2;

#assert offset(CFAT32Boot.code) >= offset(CRedSeaBoot.code)

                    br.jump_and_nop[2] = OC_NOP;
                    *BHD_BLK_COUNT(U16 *) = (de.size + BLK_SIZE - 1) >> BLK_SIZE_BITS;
                    *BHD_DAP_BLK(I64 *) = Clus2Blk(drive, de.clus);

                    for (i = 0; i < BHD_END - BHD_CODE; i++)
                        br.code[i] = BHD_CODE(U8 *)[i];

#assert sizeof(CFAT32Boot.code) >= BHD_END - BHD_CODE

                    for (; i < sizeof(CFAT32Boot.code); i++)
                        br.code[i] = 0;

                    BlkWrite(drive, &br, drive->drv_offset, 1);
                }
                break;

            default:
                throw;
        }
    }
    catch
    {
        PutExcept;
        Beep;
    }
}