include "MACROS.INC"
;
; OS function implementation
; SmallC for KolibriOS
;

;B+ General definitions

;B+ File defs
 ;const
  ;param
  BAD	equ -1
  files equ 100
  save_buffer		equ 0x20000 ;32
  save_buffer_w 	equ 0x400000 ;32
  save_file_name	equ 0x20000

  ;system
  EOF equ -1

 ;memory
 fileinfo     equ I_END
 start_data   equ (fileinfo+16384)
 ;
 mem_heap equ 0x100000
 ;
 g_handle equ 0x300000
  ;dword - pointer - relative to file
  ;dword - begin of file
  ;dword - file size
  ;dword - 0/1 <=> read/write
;E:.

;E:.

init_osfunc:
;B+ Init OS functions
;B+ Clear file handles
  mov  edi,g_handle
  mov  ecx,files
  shl  ecx,2 ;*4
  xor  eax,eax
  cld
rep stosd
;E:.
  ret
;E:.

;B+ Main OS functions
ppp dd 70

_OS_fopen:
;B+ Implement "fopen"
  ;esp+4 - mode
  ;esp+8 - file name

;  mov  eax,-1
;  int  0x40

;  mov  ebx,[esp+8];
; push dword 10
; push dword [ppp]
; push ebx
; push dword 12
;  call _outstrg
;  add  esp,4*4
;  add  [ppp],10

;  cmp  byte [ebx+8],0
;  jne .l
;  mov  byte [ebx+8],'?'
;.l:
;  cmp  [ppp],80
;  je   .l

	mov ecx , [esp+4] ; file mode
    mov [file_mode],ecx
;B+ Copy file name


  mov  esi,[esp+8]
  mov  edi,[p_filename]
  mov  ecx,12
.next_copy:
lodsb
  ;fill name (space)
  or   al,al
  jz   .fill_space
  ;set upper case
  cmp  al,'a'
  jb   .good_char
  cmp  al,'z'
  ja   .good_char
  add  al,'A'-'a'
.good_char:
stosb
  dec  ecx
  jnz  .next_copy
.fill_space:
  mov  al,' '
  cld
rep stosb

mov  eax,[file_mode]
  cmp  byte [eax],'w'
  jne	.no_wri


;B+ Copy file name
  mov  esi,[esp+8]
  mov  edi,[w_file_name]
  mov  ecx,12
.next_copy2:
lodsb
  ;fill name (space)
  or   al,al
  jz   .fill_space2
  ;set upper case
  cmp  al,'a'
  jb   .good_char2
  cmp  al,'z'
  ja   .good_char2
  add  al,'A'-'a'
.good_char2:
stosb
  dec  ecx
  jnz  .next_copy2
.fill_space2:
  ;mov  al,' '
  ;cld
rep stosb

.no_wri:



;E:.
;B+ Find file handle
  mov  eax,g_handle
.new_handle:
  cmp  dword [eax+4],0
  je   .find_place
  add  eax,16
  cmp  eax,g_handle+files*16-16
  jne  .new_handle
  xor  eax,eax ; no free handle
  ret
.find_place:
; TMP:  mov  eax,[.ccc]
; TMP:  add  [.ccc],16
;E:.
 push eax
;B+ Test open mode
  mov  eax,[esp+4+4]
  cmp  byte [eax],'r'
  je   .open_read
  cmp  byte [eax],'w'
  je   .open_write
  ;bad mode
  add  esp,4
  mov  eax,eax ; invalid open mode
  ret
;E:.

; TMP:.ccc dd g_handle

.open_read:
;B+ Open for read
;B+ Read file

  ;Wait to read correct
  mov  ebx,100
  mov  eax,5
  int  0x40

  mov  eax,[g_fileend]
  mov  dword [file_parameters+2*4],2000 ;read all
  mov  dword [file_parameters+3*4],eax

  mov  dword [file_parameters],0
  mov  ebx,file_parameters
  mov  eax,58
  int  0x40
;E:.

;B+ TEST FILE FOUND
  or   eax,eax
  jz   .file_found
  cmp  eax,5
  je   .file_found

;  mov  ecx,eax ; eax
;  mov  ebx,8 shl 16 + 0x0100
;  mov  edx,100 shl 16 + 120
;  mov  esi,0xffffff
;  mov  eax,47
;  int  0x40

  ;file not found - return 0
  add  esp,4
  xor  eax,eax
  ret
.file_found:
;E:.
 pop  eax
 push ebx
  xchg eax,ebx
;B+ Fill file handle
  ;save current pointer
  xor  eax,eax
  mov  [ebx],eax

  ;save file begin
  mov  eax,[g_fileend]
  mov  [ebx+4],eax

  ;save file size
 pop  eax
  mov  [ebx+8],eax
  ;reserve file zone
  add  eax,7
  and  eax,not 7
  add  [g_fileend],eax

  ;save file mode
  mov  eax,0 ;read
  mov  [ebx+12],eax
;E:.
  xchg eax,ebx ;return pointer place
  ret
;E:.

.open_write:
;B+ Open for write
;B+ Reserve filename

; p_filename -> w_file_name

;pusha
;  mov eax, w_file_name
;  mov ebx, [p_filename]
;.ncpy:
;  mov ch, byte [ebx]
;  cmp ch, 0
;  je .ecpy
;  mov [eax], ch
;  inc dword [eax]
;  inc dword [ebx]
;jmp .ncpy
;
;.ecpy:
;
;popa

  mov [save_buffer_p], save_buffer_w

  mov  esi,[p_filename]
  mov  edi,[g_fileend]
  mov  ecx,12
  cld
rep movsb
  add  [g_fileend],16
;E:.
 pop  ebx
;B+ Fill file handle
  ;save begin pointer
  xor  eax,eax
  mov  [ebx],eax

  ;save file begin
  mov  eax,[g_fileend]
  mov  [ebx+4],eax

  ;save file zone
  mov  dword [ebx+8],save_buffer
  ;reserve file zone
  add  [g_fileend],save_buffer

  ;save file mode
  mov  eax,1 ;write
  mov  [ebx+12],eax
;E:.
  xchg eax,ebx ;return pointer place
  ret
;E:.

;E:.

_OS_fclos:
;B+ Close file
 ;esp+4 - file handle

;B+ Test write mode - save file
  mov  eax,[esp+4]
  mov  eax,[eax+12]
  cmp  eax,1
;E:.
  jne  .no_write

   mov eax, [esp+4]
   mov ecx, [eax]
   mov ebx, [eax+8]

   mov ebx, [save_buffer_p]
   sub ebx, save_buffer_w
	; ebx = number of read bytes = file size
    ; save loaded file
    mov  [dest_info.bytes],ebx ; file size in bytes

    mov  [dest_info.bytes+4], save_buffer_w
    ;mov eax, [p_filename];[w_file_name]
    ;mov [destination],eax
    mov  eax,70
    mov  ebx,dest_info
    mcall

    ; check if 58 function failed
    test eax,eax
    je	 .ok_write
    add  eax,7	      ; error number += 7
    cmp  eax,6+7
    jna  .copy_error
    mov  eax,7+7
    jmp  .copy_error

.copy_error:
  .ok_write:


;E:.
  jmp  .read

 .no_write:
;B+ Test read mode - if no error end
  cmp  eax,0
  je   .read
  mov  eax,BAD
  ret
;E:.
.read:

;B+ Relace memory
  ;find file size
  mov  eax,[esp+4]
  mov  ecx,[eax+8]
  add  ecx,7
  and  ecx,not 7
 push ecx

  ;mov memory
  mov  esi,[eax+4]
  mov  edi,esi
  add  esi,ecx
  mov  ecx,[g_fileend]
  sub  ecx,edi
  jz   .is_last
  shr  ecx,2
  inc  ecx ;not neccessery
  cld
rep movsd
  ;update gl. memory
.is_last:
 pop  ecx
  sub  dword [g_fileend],ecx

  ;update file pointers
  mov  edx,ecx
  mov  ecx,[eax+4]
  mov  eax,g_handle
.new_handle1:
  mov  ebx,[eax+4]
  cmp  ebx,ecx
  jbe  .no_update
  sub  ebx,edx
  mov  [eax+4],ebx
.no_update:
  add  eax,16
  cmp  eax,g_handle+files*16
  jne  .new_handle1

  ;clear handle
  mov  edi,[esp+4]
  xor  eax,eax
  cld
  stosd
  stosd
  stosd
  stosd
;E:.
  ret
;E:.

_OS_fgetc:
;B+ Load char from file
 ;esp+4 - input file

  mov  eax,[esp+4]
  mov  ebx,[eax]
  cmp  ebx,[eax+8]
  je   .eof
  inc  dword [eax]
  add  ebx,[eax+4]
  movzx eax,byte [ebx]
  ret
.eof:
  mov  eax,EOF
  ret
;E:.

;rrr db 'g',0

_OS_fputc:
;B+ Save char to file
 ;esp+4 - output file
 ;esp+8 - char to write

;push dword '<'
;mov  cl,1
;push dword 0
;call test_outch
;add  esp,8



;B+ Temp - write direct.
  cmp  dword [esp+4],__iob
  jne  .real_write0
  jmp  _OS_exit
.real_write0:
  cmp  dword [esp+4],__iob+32
  jne  .real_write1
  mov  [print_textcolor],0x00ffff
  jmp  test_outch
.real_write1:
  cmp  dword [esp+4],__iob+64
  jne  .real_write2
  mov  [print_textcolor],0x77ffff
  jmp  test_outch
.real_write2:
;E:.

mov ebx,[save_buffer_p]
mov eax,[esp+8]
mov [ebx],eax
inc dword [save_buffer_p]


ret

;push dword '<'
;mov  cl,1
;push dword 0
;call test_outch
;add  esp,8

  mov  eax,[esp+4]
  mov  ebx,[eax]
 push ebx
  cmp  ebx,[eax+8]
  jne  .write_normal



;B+ Alloc save_buffer bytes
  ;mov memory
  mov  ebx,[esp+4+4]
  mov  esi,[g_fileend]
  mov  edi,esi
  add  edi,save_buffer-4
  mov  ecx,esi
  sub  ecx,[ebx+4]
  sub  ecx,[ebx+8]
  shr  ecx,2
  jz   .is_last
  sub  esi,4
  std
rep movsd
.is_last:

  ;expand file size
  add  dword [eax+8],save_buffer

  ;update file pointers
  mov  ebx,g_handle
.new_handle:
  mov  ecx,[ebx+4]
  cmp  [eax+4],ecx
  jae  .no_update
  add  dword [ebx+4],save_buffer
.no_update:
  add  ebx,16
  cmp  ebx,g_handle+files*16-16
  jne  .new_handle
;E:.

.write_normal:
 pop  ebx
  inc  dword [eax]
  add  ebx,[eax+4]
  mov  cl,[esp+8]
  mov  byte [ebx],cl

;sub  [test_outch.x_coord],2
;
;push dword '>'
;mov  cl,1
;push dword 0
;call test_outch
;add  esp,8
;
;sub  [test_outch.x_coord],6

  xor  eax,eax
  ret
;E:.

_OS_callo:
;B+ Alloc memory
  ;find all size
  mov  eax,[esp+4]
  mov  ebx,[esp+8]
  mul  ebx
 push eax

  ;clear memory
  mov  edi,[.mem_p]
  xor  eax,eax
  mov  ecx,[esp]
  cld
rep  stosb

  ;update new memory pointer
 pop  ebx
 push dword [.mem_p]
  add  ebx,7
  and  ebx,not 7
  add  [.mem_p],ebx

  ;return value
 pop  eax
  ret

.mem_p dd mem_heap
;E:.

_OS_exit:
;B+ Exit program
;  ;TMP
;  mov  eax,-1
;  int  0x40
  mov  esp,[exit_esp]
  sub  esp,4
  ret
;E:.

;E:.




;B+ Test procedures

;B+ Definitions
LEFTMARGIN equ 11
BEGIN_CHARS equ 20
NL equ 10
;E:.

print_textcolor dd 0x00ffff

_file_beg:
;B+ Show begin of file - test fopen
 ;esp+4 - file handle (descriptor)

  mov  eax,[esp+4]
  mov  ebx,10 shl 16 + 30
  mov  ecx,[print_textcolor]
  mov  edx,[eax+4]
  mov  esi,BEGIN_CHARS
  mov  eax,4
  int  0x40
  ret
;E:.

_outstrg:
;B+ Draw black text - test function call
 ;esp+4*4 - x
 ;esp+4*3 - y
 ;esp+4*2 - *c
 ;esp+4*1 - len

  mov  ebx,[esp+4*4]
  shl  ebx,16
  mov  bx,[esp+4*3]
  mov  ecx,[print_textcolor]
  mov  edx,[esp+4*2]
  mov  esi,[esp+4]
  mov  eax,4
  int  0x40
  ret
;E:.

test_outch:
;B+ Draw one char - use as _OS_fputc, to test printf(...)
 ;esp+8 - char to write

  ;this is test! \b \r - not nesessary

  mov  al,[esp+8]
  cmp  al,NL
  jne  .no_newline
  add  [.y_coord],10
  mov  [.x_coord],LEFTMARGIN
  ret
.no_newline:

  mov  ebx,[.x_coord]
  shl  ebx,16
  mov  bx,word [.y_coord]
  mov  ecx,[print_textcolor]
  mov  [.out_char],al
  mov  edx,.out_char
  mov  esi,1
  mov  eax,4
  int  0x40

  add  [.x_coord],6
;mov  eax,5
;mov  ebx,5
;int  0x40
  ret

.x_coord dd LEFTMARGIN
.y_coord dd 60
.out_char db 0
;E:.

;E:.

;B+ Data section
;B+ Memory managment
g_fileend dd g_handle+files*4*4 ;from 2MB+100*4*4
;w_buff dd
;E:.

save_buffer_p dd save_buffer_w
;B+ File parameters
file_parameters:
 dd 0x0 ; mode
 dd 0x0  ; first block
 dd 1000 ; block read
 dd -1	 ; return place
 dd fileinfo ; work area
filepath: times 100 db 0

file_mode dd 0 ;file mode

dest_info:		     ; DESTINATION FILEINFO
	dd	2
	dd	0
	dd	0
.bytes	dd	?
	dd	save_buffer
	db	0
destination:
	dd  save_file_name
	;db     "EXAMPLE.ASM",0



w_file_name dd	save_file_name

p_filename dd 0x0
;E:.
;E:.

  ;TO DO
  mov  eax,-1
  int  0x40
  ;TO DO