use16
org 0h
	jmp far  7c0h:start
	;**************************************************************************
	;***    definitions                                                     ***
	;**************************************************************************
	;OS kernel Sector count
	moskrnlsectcnt	dd 2
	mhexvalues	db '0123456789ABCDEF'
	;messages
	mokmsg		db 13,'  ...OK',0
	mnotokmsg	db 13,'  ...FAILURE',0
	mbootmsg	db 13,'loading 3OS',0
	mprotmodemsg	db 'switching to protected mode',0


	mprcmsg 	db 'sorry, you need an x86-64 compatible processor',0
	mtestmsg	db 'END OF CODE',0
	mkernelcrashmsg db 'fatal kernel crash; system halted.',0

	DriveInfo:
	 .DriveNumber	db 0
	 .Heads 	dd 2
	 .TracksPerHead dd 335
	 .SectPerTrack	dd 2

	;**************************************************************************
	;***    Function declarations                                           ***
	;**************************************************************************
	f_kernelcrash:
		mov	si, mkernelcrashmsg
		call	f_disp
	      f_kernelcrash_loop:
		jmp	near f_kernelcrash_loop
	;ret not needed
	;**************************************************************************
	f_disp:
		push	ax
		push	bx
	      f_disp_loop:
		lodsb
		or	al, al		;chk if end-char
		jz	near f_disp_ret
		mov	ah, 00eh
		mov	bx, 0007
		int	0x10
		jmp	near f_disp_loop
	      f_disp_ret:
		pop	bx
		pop	ax
		ret
	;**************************************************************************
	f_disp_ax_value:
		push BX
		mov	bl, ah
		shr	bl, 4
		call	f_disp_nibble
		mov	bl, ah
		call	f_disp_nibble
		mov	bl, ah
		shr	bl, 4
		call	f_disp_nibble
		mov	bl, al
		call	f_disp_nibble
		pop	bx
		ret
	f_disp_nibble:
		push	AX
		and	BX, 0Fh
		mov	AL, [bx + mhexvalues]
		mov	AH, 0Eh
		mov	BX, 0
		int	10h
		pop	AX
	ret
	;**************************************************************************
	f_crlf:
		mov	ah, 00eh
		mov	bx, 0007
		mov	al, 13
		int	0x10
		mov	al, 10
		int	0x10
	ret
	;**************************************************************************
	f_LBA_to_CHS:	       ;In: ECX = Sector  Out: CH, CL, DH, DL
		push	eax
		push	ebx
		;inc     ecx                        ;Sectors start with 1, not 0
		mov	eax, ecx
		xor	edx, edx
		div	[DriveInfo.SectPerTrack]
		mov	cl, dl			   ;Set the sector
		inc	cl
		and	cl, 63			   ;Top two bits are bits 8&9 of the cylinder
		xor	edx, edx
		div	[DriveInfo.TracksPerHead]
		mov	dh, al
		call	f_disp_ax_value
		mov	ch, dl			   ;Set the track bits 0-7
		mov	al, dh
		shl	al, 6
		or	cl, al			    ;Set bits 8&9 of track
		;xor     edx, edx
		;div     [DriveInfo.Heads]
		;mov     dh, dl                     ;Set the head
		pop	ebx
		pop	eax
	ret
	;**************************************************************************
	f_read_sector:
		push	ax
		push	bx
		push	cx
		push	dx
		call	f_LBA_to_CHS
		mov	ax, cx
		call	f_disp_ax_value
		mov	ax, 201h  ;Service 2, Read 1 sector
		mov	dl, [DriveInfo.DriveNumber]
		int	13h
		pop	dx
		pop	cx
		pop	bx
		pop	ax
	ret
	;**************************************************************************
	f_read_driveinfo:
		push	es
		mov	dl, [DriveInfo.DriveNumber]
		mov	ah, 8h
		int	13h
		xor	eax, eax
		mov	[DriveInfo.Heads], eax
		mov	[DriveInfo.TracksPerHead], eax
		mov	[DriveInfo.SectPerTrack], eax

		mov	al, dh
		mov	WORD [DriveInfo.Heads], ax

		push	cx
		mov	BYTE [DriveInfo.TracksPerHead], ch
		shr	cl, 6
		and	cl, 3
		mov	BYTE [DriveInfo.TracksPerHead+1], cl
		pop	cx

		xor	eax, eax
		mov	al, cl
		and	al, 63
		mov	[DriveInfo.SectPerTrack], eax

		inc	[DriveInfo.Heads]
		inc	[DriveInfo.TracksPerHead]
		pop	es
	ret
	;**************************************************************************

	;**************************************************************************
	;***    Main routine                                                    ***
	;**************************************************************************
start:
	mov	ax, cs
	mov	ds, ax
	mov	ax, 50h
	mov	es, ax

	mov	[DriveInfo.DriveNumber], dl
	;temporarily set up stack
	cli				;IRQ off
	mov	ax, 0x9000		;typical stack place
	mov	ss, ax
	mov	sp, 0xF800		;size
	sti				;IRQ on
	;output boot message
	mov	si, mbootmsg
	call	f_disp
	call	f_crlf

	;load next OS sectors (PMLoader, LMLoader, ObjectInterpreter, DriverClasses, TaskManagerClass, BashClass)
	;xor     bx, bx
	;xor     cx, cx
      ;readloop:
	;call    f_read_sector
	;add     bx, 200h
	;inc     cx
	;cmp     cx, WORD [moskrnlsectcnt]
	;jbe     readloop
	mov	ecx, 0
	mov	bx, 0h
	call	f_read_sector
	mov	ecx, 1
	mov	bx, 200h
	call	f_read_sector
	jmp far 50h:PMLoader_Start

	rb 512-2-$	  ;fill up to the signum

	db	055h,0AAh	     ;the signature
	;7E00h
org 200h

	f_checkcpu:
		;check for older than 286
		pushf
		xor	ah, ah		;-> ah = 0
		push	ax
		popf

		pushf
		pop	ax
		and	ah, 0f0h
		cmp	ah, 0f0h
		je	near f_checkcpu_no386
		;check for 286
		mov	ah, 0f0h
		push	ax
		popf
		pushf
		pop	ax
		and	ah, 0f0h
		jz	near f_checkcpu_no386
		popf
	ret
	      f_checkcpu_no386:
		mov	si, mprcmsg
		call	f_disp
		call	f_crlf
		call	f_kernelcrash
	;ret not needed

PMLoader_Start:
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	call	f_kernelcrash
	rb 1023-$
	db 0