BASE EQU 07c0h

code            segment byte public
                assume  cs:code, ds:code
                org     0h
simpboot        proc    far

jmp short init

start:

OEMlabel:
          db "NXDOS 80" 
BytesPerSector:    dw 512
SectorsPerCluster: db 1  
ReservedForBoot:   dw 1  
NumberOfFats:      db 2  
RootDirEntries:    dw 224
LogicalSectors:    dw 2880  
MediumByte:        db 0F0h
SectorsPerFat:     dw 9     
SectorsPerTrack:   dw 18    
Sides:             dw 2     
HiddenSectors:     dw 0     
TotalSectors:      dd 2280
Reserved4DOS:      db '                        '
bdrive             db 0

init:
   mov  ax, 07C0h
   add  ax, 512
   mov  ss, ax
   mov  sp, 4096
   mov  ax, 07C0h
   mov  ds, ax
   mov  byte ptr cs:[BASE+bdrive], dl
   xor  ax, ax
   int  11h
   and  ax, 1
   or   ax, ax
   jne  floppy
   call bootbeep
   int  16h
   jmp  exitptr
floppy:
   call flreset
   jnc  ok_floppy
   call bootbeep
   call bootbeep
   int  16h
   jmp  exitptr
ok_floppy:
   ; lba sect 19 = diskdesc = sector 2, side 1, track 0
   mov  ax, 19
   call L2HTS
   call loadroot
   call findfile
   or   ax, ax
   jz   fileerr

fileerr:
   call bootbeep
   call bootbeep
   call bootbeep
exitptr:
   int  19h

bootbeep proc near
   mov  ah, 0eh
   mov  al, 7
   mov  bl, 7
   int  10h
   ret
bootbeep endp

flreset proc near
   push ax
   push dx
   xor  ax, ax
   mov  dl, byte ptr cs:[BASE+bdrive]
   int  13h
   pop  dx
   pop  ax
   ret
flreset endp

L2HTS proc near
   push bx
   push ax
   mov BX, AX

; First the sector: 'Physical Sector' = ('logical sector' mod 'number of sectors per track/cylinder') + 1
   xor DX, DX
   div word ptr cs:[BASE+SectorsPerTrack]
; Physical Sectors start at 1, not at 0 (like the logical ones do ...)
   add DL, 01h
; The remainder of a division is in dx, rememember ??
   mov cl, DL ; sectors belong into cl for int 0x13
   mov AX, BX

; Now the head: 'head' = ('logical sector' / 'number of sectors per track') mod 'number of heads/sides'
; and track = ('logical sector' / 'number of sectors per track') / 'number of heads/sides'
   xor dx, dx
   div word ptr cs:[BASE+SectorsPerTrack]
   xor dx, dx
   div word ptr cs:[BASE+Sides]
   mov dh, DL ; head/side
   mov ch, AL ; track

   pop ax
   pop bx
   mov dl, byte ptr cs:[BASE+bdrive]
   ret
L2HTS endp

loadroot proc near
   ; es:bx
   lea  si, cs:[BASE+Buffer]
   mov  bx, ds
   mov  es, bx
   mov  bx, si
   mov  ah, 02h
   mov  al, 0Eh
   clc
   pusha
read_first_sector:
   popa
   pusha
   int  13h
   call flreset
   jc   read_first_sector
   popa
   ret
loadroot endp

findfile proc near
   ; es:di -> [Root-Dir]
   mov ax, ds
   mov es, ax
   lea di, cs:[BASE+Buffer]
   mov cx, word ptr cs:[BASE+RootDirEntries]
   mov ax, 0
next_root_entry:
   ; swap cx and dx, cause we also use cx in the inner loop...
   xchg cx, dx
   lea si, cs:[BASE+kernelfile]
   mov cx, 11
   rep cmpsb
   je found_file_2_load
; increase number of searched entries by 1 ... (offset += 32 (bytes))
   add ax, 32
; increase root-dir-pointer to point to next entry.
   lea di, cs:[BASE+Buffer]
   add di, ax
; swap cx and dx, cause we now need the 'outer' cx
   xchg dx, cx
   loop next_root_entry
; [file2load] not found ... (dump root-dir on screen,) print error and halt.
   xor  ax, ax
   jmp  ffexit
found_file_2_load:
   mov  ax, 1
ffexit:
   ret
findfile endp

loadfile proc near
   mov  ax, word ptr [es:di+0Fh]
   mov  word ptr cs:[BASE+CLUSTER], ax
   mov  ax, 1
   call L2HTS
   lea  di, cs:[BASE+Buffer]
   mov  bx, di
   mov  ah, 02h
   mov  al, 09h
   clc
   pusha
Read_Fat:
   popa
   pusha
   int  13h
   jnc  Read_Fat_OK
   call flreset
   jmp  Read_Fat
Read_Fat_OK:
   popa
   ; FAT table received in ram
   ; we load the file to 0060:0000h 
   mov  ax, 0060h
   mov  es, ax
   xor  bx, bx
   mov  ah, 02h
   mov  al, 01h
   push ax
Load_File_Sector:
   call C2L
   call L2HTS
; Set buffer past what we have already read.
   mov  ax, 0060h
   mov  es, ax
   mov  bx, word ptr cs:[BASE+POINTER]
   pop  ax
   push ax
   int  13h
   jnc  Calculate_Next_Cluster
   call flreset
   jmp  Load_File_Sector
Calculate_Next_Cluster:
   mov  ax, cs:[BASE+CLUSTER]
   xor  dx, dx
   mov  bx, 2
   div  bx
   ; dx = [CLUSTER] mod 2; so if dx = 0 [CLUSTER] is even, if dx = 1 [CLUSTER] is odd.
   or dx, dx
   ; if [CLUSTER] is even, we have to drop the last 4 bits of the word with the next cluster.
   ; when [CLUSTER] is odd, we'lll have to drop the first 4 bits.
   jz Even
Odd:
   mov ax, [CLUSTER]
   mov bx, 3
   mul bx
   mov bx, 2
   div bx
; now we have in ax the adress of the word in the FAT in which the 12 bits are, so we'll load the whole word
   lea si, [Buffer]
   add si, ax
   mov ax, word [ds:si]
; and shift out the first 4 bits. (which belong to another entry.)
   shr ax, 4
; so: ax contains the cluster now! Store it.
   mov word [CLUSTER], ax

   cmp ax, 0x0FF8
   jae End

; Done; increase buffer-ptr; next sector
   add word [POINTER], 512
   jmp Load_File_Sector

Even:
   mov ax, [CLUSTER]
   mov bx, 3
   mul bx
   mov bx, 2
   div bx
; now we have in ax the adress of the word in the FAT in which the 12 bits are, so we'll load the whole word
   lea si, [Buffer]
   add si, ax
   mov ax, word [ds:si]
; and mask out the last 4 bits. (which belong to another entry.)
   and ax, 0x0FFF
; so: ax contains the cluster now! Store it.
   mov word [CLUSTER], ax

   cmp ax, 0x0FF8
   jae End

; increase buffer-ptr; load next sector
   add word [POINTER], 512
   jmp Load_File_Sector

End:
; clear stack.
   pop ax
; provide second boot-loader with the boot-device.
   mov dl, byte [BOOTD]
; We have loaded the whole file, so lets execute it.
   jmp 0x2000:0x0000

kernelfile db 'NXBIO   SYS'

buffer:

simpboot        endp

code            ends

ProgramEnd      EQU $-01h

		end	start
