U0 SysGlobalsInit()
{
	I64				i, j;
	CRAXRBXRCXRDX	regs;

	CPUId(0x1, &regs);
	sys_cache_line_width = regs.rbx.u8[1] * 8;

	sys_focus_task = Fs;
	QueueInit(&sys_macro_head);

	blkdev.default_iso_filename		= SysStrNew(DEFAULT_ISO_FILENAME);
	blkdev.default_iso_c_filename	= SysStrNew(DEFAULT_ISO_C_FILENAME);
	blkdev.tmp_filename				= SysStrNew("~/Tmp.DD");
	blkdev.dvd_boot_is_good			= TRUE;

	#exe
	{
		if (!kernel_config->mount_ide_auto_hd_let)
			kernel_config->mount_ide_auto_hd_let = 'C';

		if (!kernel_config->mount_ide_auto_cd_let)
			kernel_config->mount_ide_auto_cd_let = 'T';

		StreamPrint("blkdev.first_hd_drive_let  = %d;", kernel_config->mount_ide_auto_hd_let);
		StreamPrint("blkdev.first_dvd_drive_let = %d;", kernel_config->mount_ide_auto_cd_let);
	}

	DebugMode(ON);

	rev_bits_table = CAlloc(256);

	for (i = 0; i < 256; i++)
		for (j = 0; j < 8; j++) 
			if (Bt(&i, 7 - j))
				Bts(rev_bits_table + i, j);

	ext = CAlloc(EXT_EXTS_NUM * sizeof(U8 *));
	fp_getstr2 = &SysGetStr2;
	KeyDevInit;

	#exe
	{
		StreamPrint("blkdev.boot_drive_let = '%C';", kernel_config->boot_drive_let);

		StreamPrint("#exe{ Option(OPTf_WARN_PAREN, OFF); }");

		StreamPrint("DiskCacheInit(%s);", kernel_config->disk_cache_size_exp);

		StreamPrint("#exe{ Option(OPTf_WARN_PAREN, ON); }");
	};

	pow10_I64 = CAlloc(sizeof(F64) * (308 + 308 + 1));
	for (i = -308; i < 309; i++)
		pow10_I64[i + 309] = Pow10(i);

	QueueInit(&screencast.sound_head);
	screencast.t0_now	= Now;
	screencast.t0_tS	= tS;
	screencast.ona = screencast.sound_head.ona = 0;

	ProgressBarsReset;

	QueueInit(&dev.pci_head);
	dev.mem64_ptr = mem_mapped_space;

	debug.fun_seg_cache  = CAlloc(FUN_SEG_CACHE_SIZE * sizeof(CFunSegCache));
	debug.int_fault_code = IntFaultHandlersNew;
}

U0 SysGrInit()
{
	I64 i;

    text.font = sys_font_std;

	text.aux_font = sys_font_aux;

	//patch some chars
	text.aux_font[10]	= text.font[10]; //"Return" symbol 
	text.aux_font[255]	= text.font[255]; //Block symbol  

	for (i = '│'; i < '█'; i++)
		text.aux_font[i] = text.font[i];

	text.aux_font['⌐'] = text.font['⌐'];
	
	text.border_chars[2] (I64) = '─═│║┌╔┐╗';
	text.border_chars[10](U32) = '└╚┘╝';

	text.cols = sys_framebuffer_width  / FONT_WIDTH;
	text.rows = sys_framebuffer_height / FONT_HEIGHT;

	text.screen_size	= sys_framebuffer_pitch / (sys_framebuffer_bpp / 8) * sys_framebuffer_height;
	text.buffer_size	= text.screen_size * 4; //buffer for 32-bit, but only 16 colors now.
	text.raw_screen		= CAlloc(text.buffer_size);
	text.fb_alias		= sys_framebuffer_addr;

	MemSetU32(text.fb_alias, BLACK32, text.screen_size);
}

U0 TimerInit()
{//See $LK,"::/Doc/PIT.DD",A="FI:::/Doc/PIT.DD"$.
	OutU8(PIT_CMD, PIT_CMDF_CHANNEL0 | PIT_CMDF_OPMODE_RATE_GEN | PIT_CMDF_ACCESS_WORD);
	OutU8(PIT_0, SYS_TIMER0_PERIOD);
	OutU8(PIT_0, SYS_TIMER0_PERIOD >> 8);
}

U0 Reboot(Bool format_ramdisks=FALSE)
{//Hardware reset.
	if (format_ramdisks)
	{
		if (DriveIsWritable('A'))
			Format('A',, FALSE, FSt_REDSEA);
		if (DriveIsWritable('B'))
			Format('B',, FALSE, FSt_REDSEA);
	}
	CLI
	if (mp_count > 1)
		MPHalt;
	*0x472(U16 *) = 0;
	OutU8(0x70, 0x8F);
	OutU8(0x71, 0x00);
	OutU8(0x70, 0x00);
	OutU8(0x92, InU8(0x92) | 1);
	SysHlt;
}

U0 KMain()
{//Continued from $LK,"KStart64.ZC",A="FF:::/Kernel/KStart64.ZC,I32 &KMain"$
	CBlkDev *bd;

	OutU8(PCSPKR, InU8(PCSPKR) & ~3); //Sound;
	sys_task = Fs;
	BlkPoolsInit;
	SysGlobalsInit;
	Mem32DevInit;
	UncachedAliasAlloc;
	LoadKernel;
	SysGrInit;
	StrCopy(Fs->task_name, "System Task CPU00");
	StrCopy(Fs->task_title, Fs->task_name);
	Fs->title_src = TTS_TASK_NAME;
	Fs->win_right = text.cols - 2;
	Fs->win_top++;
	TaskDerivedValsUpdate;

	SysDefinesLoad;
	Core0Init;
	IntInit1;

	//Before this point use $LK,"Sound",A="MN:Sound"$() and $LK,"Busy",A="MN:Busy"$()
	//to debug.  After this point, use $LK,"RawPrint",A="MN:RawPrint"$()
	LBts(&sys_run_level, RLf_RAW);
	sys_os_version_str = MStrPrint("ZealOS V%0.2f.%d", sys_os_version, sys_os_version_sub);
	sys_os_version_nice = MStrPrint("%s\t%D %T\n", sys_os_version_str, sys_compile_time, sys_compile_time);
	sys_os_version_full = MStrPrint("%s-%d.%d\n", sys_os_version_str, sys_compile_time.date, sys_compile_time.time);
	"\n%s\n", sys_os_version_full;
	"_________________________________\n\n";

	"TimerInit;\n";
	TimerInit;

	if (MemBIOSTotal < ToI64 (0.95 * MEM_MIN_MEG * 0x100000) )
		RawPrint(4000, "!!! Requires $TX,"256Meg",D="DD_MEM_MIN_MEG"$ of RAM Memory !!!");

	"IntPICInit;\n";
	IntPICInit;
	RFlagsSet(RFLAGG_NORMAL);
	Busy(2000);
	"IntInit2;\n";
	IntInit2;
	LBts(&sys_run_level, RLf_INTERRUPTS);

	"TimeCal;\n";
	TimeCal;

	"BlkDevsInitAll;\n";
	BlkDevsInitAll;
	"\nDiskChange(':');\n";
	DiskChange(':');

	#exe
	{
		StreamPrint("HomeSet(\"%s\");\n"
					"blkdev.ins_port = %d;",
					kernel_config->home_dir,
					blkdev.ins_port);
	}

	Gs->idle_task->cur_dv = blkdev.let_to_drive[*blkdev.home_dir - 'A'];
	DriveRep;
	if (blkdev.dvd_boot_is_good)
	{
		bd = Letter2BlkDev(':');
		if (bd->type == BDT_ATAPI)
			blkdev.ins_port = bd->port_num;
	}
	LBts(&sys_run_level, RLf_BLKDEV);

	#exe
	{
		if (!kernel_config->opts[CONFIG_NO_MP])
			StreamPrint("\"\\nCore0StartMP;\\n\\n\";"
						"Core0StartMP;"
						"LBts(&sys_run_level, RLf_MP);");
	};

	"KbdMouseInit;\n";
	KbdMouseInit;
	"MouseInit;\n";
	MouseInit;
	"KbdInit;\n";
	KbdInit;
	"Spawn(&MouseHardDriverInstall);\n\n";
	Spawn(&MouseHardDriverInstall);
	"Spawn(&MouseRawWatcher,, \"MouseRawWatcher\");\n";
	Spawn(&MouseRawWatcher,, "MouseRawWatcher");

	"Load(\"Compiler\");\n";
	Cd("/Compiler");
	Load("Compiler", LDF_SILENT);
	LBts(&sys_run_level, RLf_COMPILER);

	DebugMode(OFF);
	counts.time_stamp_freq_initial = TimeCal;
	Cd("/");
	try
		ExeFile("StartOS"); //Continues $LK,"/StartOS.ZC",A="FL:/StartOS.ZC,1"$
	catch
	{
		Raw(ON);
		Silent(OFF);
		GetOutOfDollar;
		PutExcept;
		Debug;
	}

	LBts(&sys_run_level, RLf_SYSTEM_SERVER);
	ServerTaskCont; //Never to return
}

asm
{

 	ALIGN 	16, OC_NOP
SYS_KERNEL_END::
#exe {
	if (kernel_config->opts[CONFIG_DEBUG_DISTRO])
		StreamPrint("DU8 0x%X - (SYS_KERNEL_END-SYS_KERNEL + BOOT_RAM_BASE + sizeof(CZXE)) DUP (0);"
					"BINLOAD \"%s\";",
					kernel_config->debug_distro_start, kernel_config->debug_distro_file);
};

}