;const int
MENUET_BORDER_SIZE = 4;
;const int
MENUET_HEADER_SIZE = 20;

;const int
MENUET_THREAD_DATA_USER     = 0; // Thread data begin from the user dword
;const int
MENUET_THREAD_DATA_ST_BEGIN = 1; // Stack beginning follows after the user dword
;const int
MENUET_THREAD_DATA_NEXT     = 2;
;const int
MENUET_THREAD_DATA_PID      = 3;
;const int
MENUET_THREAD_DATA_FLAG     = 4;
;const int
MENUET_THREAD_DATA_X        = 5;
;const int
MENUET_THREAD_DATA_Y        = 6;
;const int
MENUET_THREAD_DATA_C_WINDOW = 7;
;const int
MENUET_THREAD_DATA_C_HEADER = 8;
;const int
MENUET_THREAD_DATA_C_BORDER = 9;
;const int
MENUET_THREAD_DATA_C_TITLE  = 10;
;const int
MENUET_THREAD_DATA_TITLE    = 11;
;const int
MENUET_THREAD_DATA_PICTURE  = 12;
;const int
MENUET_THREAD_DATA_SZ_PICT  = 13;
;const int
MENUET_THREAD_DATA_LAST_SX  = 14;
;const int
MENUET_THREAD_DATA_LAST_SY  = 15;
;const int
MENUET_THREAD_DATA_LEN      = 16;

;const int
MENUET_MUTEX_MAX_TIME_WAIT  = 20;

;const int
MENUET_FILE_BLOCK_SIZE      = 512;

;const int
MENUET_FILE_MEMORY_OS_NEED  = 4096;

;/***

macro segment name
{
  segment name
  if name eq _init_ | name eq _INIT_
Menuet_SegmentInit:
  else if name eq _exit_ | name eq _EXIT_
Menuet_SegmentExit:
  end if
}

macro endseg  name
{
  if name eq _init_ | name eq _INIT_
Menuet_SegmentInitEnd:
  else if name eq _exit_ | name eq _EXIT_
Menuet_SegmentExitEnd:
  end if
  endseg  name
}

macro Menuet_Put_MovEaxVal_Ret  address,val
{
  mov  byte [address],0xB8
  mov  dword [address+4],0xC089C300
  mov  dword [address+1],val
}

define @Menuet@Main$qv
nextdef MenuetEntryPoint
  and  esp,not 3
  sub  esp,1024
  mov  eax,9
  mov  ebx,esp
  mov  ecx,-1
  int  0x40
  mov  ebx,[esp+26]
  mov  edx,[esp+30]
  lea  eax,[ebx-0x20]
  add  esp,1024
  cmp  esp,eax
  cmova esp,eax
  and  esp,not 3
if defined @Menuet@CommandLine
	mov	byte [@Menuet@CommandLine+256], 0
end if
  xor  eax,eax
  cld
  mov  edi,@Menuet@_ThreadTable
  mov  ecx,256
  rep stos dword [edi]
  mov  esi,@Menuet@GetPid$qv
  mov  edi,@Menuet@_ThreadSavedBegProc
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  mov  esi,@Menuet@GetThreadData$qv
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  Menuet_Put_MovEaxVal_Ret  @Menuet@GetPid$qv,edx
if defined MenuetHeapInit
  mov  ecx,esp
  push ebx
  push ecx
  push U_END
  call MenuetHeapInit   ; Initialize a dynamic heap and create new memory in its begin.
  pop  ecx              ; Parameters: begin of a new heap, end of data to create in
  mov  [esp+4],eax      ; the begin of a heap. Return address of the created data.
  mov  dword [esp],0
else
  xor  eax,eax
  push eax
  push eax
end if
  call @Menuet@ThreadMain$qpvt1
nextdef Menuet_ThreadFinish
  add  esp,8
if defined MenuetHeapFreeAndThreadFinish
  test eax,eax
  jz   Menuet_ThreadFinish_end
  push dword @Menuet@_ExitProcessNow
  push eax
  call MenuetHeapFreeAndThreadFinish   ; Free the given memory and finish the thread,
end if                                 ; should exit process if second argument points to not zero.
Menuet_ThreadFinish_end:
  or   eax,-1
  int  0x40
enddef

define @Menuet@ThreadMain$qpvt1
  xchg ebx,[esp+4]
  xchg ebp,[esp+8]
  push esi
  push edi
  sub  esp,MENUET_THREAD_DATA_LEN*4
  mov  [esp],ebx
  mov  [esp+4],ebp
  mov  eax,40
  mov  ebx,0x27
  int  0x40
  mov  ebx,esp
  cmp  byte [@Menuet@_ThreadSavedBegProc],0x90
  jz   Menuet_main_else_first_check
  Menuet_Put_MovEaxVal_Ret  @Menuet@GetThreadData$qv,esp
if defined Menuet_SegmentInit & defined Menuet_SegmentInitEnd
  push Menuet_SegmentInitEnd
  push Menuet_SegmentInit
  jmp  Menuet_main_after_first_check
end if
Menuet_main_else_first_check:
  xor  eax,eax
  push eax
  push eax
Menuet_main_after_first_check:
  push ebx
  call @@Menuet@_CallStart$qppvpvt2
  add  esp,12
  test al,al
  jnz  Menuet_main_test_close_first
  jmp  Menuet_main_end
Menuet_main_close_first:
  btr  dword [esp+MENUET_THREAD_DATA_FLAG*4],31
  push esp
  call @@MenuetOnClose$qppv
  pop  ecx
  test al,al
  jnz  Menuet_main_end
Menuet_main_test_close_first:
  cmp  dword [esp+MENUET_THREAD_DATA_FLAG*4],0
  jl   Menuet_main_close_first
  push esp
  push dword 1
  call @Menuet@Redraw$qippv
  add  esp,8
Menuet_main_paint_msg:
  or   dword [esp+MENUET_THREAD_DATA_FLAG*4],3
  sub  esp,1024
  mov  eax,9
  mov  ebx,esp
  mov  ecx,-1
  int  0x40
  mov  eax,[esp+34]
  mov  ebx,[esp+38]
  mov  ecx,[esp+42]
  mov  edx,[esp+46]
  add  esp,1024
  cmp  ecx,[esp+MENUET_THREAD_DATA_LAST_SX*4]
  jnz  Menuet_main_size
  cmp  edx,[esp+MENUET_THREAD_DATA_LAST_SY*4]
  jz   Menuet_main_paint
Menuet_main_size:
  mov  [esp+MENUET_THREAD_DATA_LAST_SX*4],ecx
  mov  [esp+MENUET_THREAD_DATA_LAST_SY*4],edx
  push edx
  push ecx
  push ebx
  push eax
  lea  ecx,[esp+16]
  mov  edx,esp
  push ecx
  push edx
  call @@MenuetOnSize$qpippv
  add  esp,24
  test dword [esp+MENUET_THREAD_DATA_FLAG*4],3
  jz   Menuet_main_cycle
Menuet_main_paint:
  cmp  dword [esp+MENUET_THREAD_DATA_FLAG*4],0
  jl   Menuet_main_close
  push esp
  push dword 0
  call @Menuet@Redraw$qippv
  add  esp,8
Menuet_main_cycle:
  mov  eax,11
Menuet_main_message:
  cmp  dword [esp+MENUET_THREAD_DATA_FLAG*4],0
  jl   Menuet_main_close
  int  0x40
  test eax,eax
  jnz  Menuet_main_on_message
  cmp  dword [esp+MENUET_THREAD_DATA_FLAG*4],0
  jne  Menuet_main_paint
  push esp
  call @@MenuetOnIdle$qppv
  pop  ecx
  test eax,eax
  jz   Menuet_main_cycle
  jl   Menuet_main_wait_message
  mov  ebx,eax
  mov  eax,23
  jmp  Menuet_main_message
Menuet_main_wait_message:
  mov  eax,10
  jmp  Menuet_main_message
Menuet_main_key_press:
  push esp
  call @@MenuetOnKeyPress$qppv
  pop  ecx
  jmp  Menuet_main_cycle
Menuet_main_mouse:
  push esp
  call @@MenuetOnMouse$qppv
  pop  ecx
  jmp  Menuet_main_cycle
Menuet_main_on_message:
  dec  eax
  jz   Menuet_main_paint_msg
  dec  eax
  jz   Menuet_main_key_press
  cmp  eax,4
  jz   Menuet_main_mouse
  dec  eax
  jnz  Menuet_main_cycle
Menuet_main_button:
  mov  eax,17
  int  0x40
  test al,al
  jnz  Menuet_main_cycle
Menuet_main_close:
  btr  dword [esp+MENUET_THREAD_DATA_FLAG*4],31
  push esp
  call @@MenuetOnClose$qppv
  pop  ecx
  test al,al
  jz   Menuet_main_button
Menuet_main_end:
  mov  ebx,esp
  lock dec dword [@Menuet@_ThreadNumber]
if defined Menuet_SegmentExit & defined Menuet_SegmentExitEnd
  jnz  Menuet_main_else_last_check
  push Menuet_SegmentExitEnd
  push Menuet_SegmentExit
  jmp  Menuet_main_after_last_check
end if
Menuet_main_else_last_check:
  xor  eax,eax
  push eax
  push eax
Menuet_main_after_last_check:
  push ebx
  call @@Menuet@_RemoveThreadData$qppvpvt2
  add  esp,12
  lock inc dword [@Menuet@_ThreadScanCount+4]
  mov  ebx,1
  jmp  Menuet_main_end_wait
Menuet_main_end_wait_loop:
  mov  eax,5
  int  0x40
  shl  ebx,1
  cmp  ebx,MENUET_MUTEX_MAX_TIME_WAIT
  jna  Menuet_main_end_wait
  mov  ebx,MENUET_MUTEX_MAX_TIME_WAIT
Menuet_main_end_wait:
  cmp  dword [@Menuet@_ExitProcessNow],0
  jnz  @Menuet@ExitProcess$qv
  cmp  dword [@Menuet@_ThreadScanCount],0
  jnz  Menuet_main_end_wait_loop
  lock dec dword [@Menuet@_ThreadScanCount+4]
  mov  ebp,[esp+4]
  mov  ebx,[esp]
  add  esp,MENUET_THREAD_DATA_LEN*4
  mov  eax,ebp
  pop  edi
  pop  esi
  xchg ebp,[esp+8]
  xchg ebx,[esp+4]
  ret
enddef

macro call func
{
  if func eq __chkstk
	sub  esp,eax
  else
	call func
  end if
}

define @Menuet@Redraw$qippv
  push ebp
  mov  ebp,[esp+12]
  mov  edx,[ebp+MENUET_THREAD_DATA_FLAG*4]
  cmp  dword [esp+8],0
  jl   Menuet_redraw_only_inv
  jz   Menuet_redraw_no_frame
  or   dl,2
Menuet_redraw_no_frame:
  bt   edx,30
  jnc  Menuet_redraw_begin
  or   dl,1
  mov  [ebp+MENUET_THREAD_DATA_FLAG*4],edx
  jmp  Menuet_redraw_end
Menuet_redraw_only_inv:
  test dl,3
  jnz  Menuet_redraw_no_frame
Menuet_redraw_end:
  pop  ebp
  ret
Menuet_redraw_begin:
  push ebx
  push esi
  push edi
  and  dword [ebp+MENUET_THREAD_DATA_FLAG*4],0xFFFFFFFC
  test dl,2
  jz   Menuet_redraw_picture
  mov  eax,12
  mov  ebx,1
  int  0x40
  xor  eax,eax
  mov  ebx,[ebp+MENUET_THREAD_DATA_X*4]
  mov  ecx,[ebp+MENUET_THREAD_DATA_Y*4]
  mov  edx,[ebp+MENUET_THREAD_DATA_C_WINDOW*4]
  mov  esi,[ebp+MENUET_THREAD_DATA_C_HEADER*4]
  mov  edi,[ebp+MENUET_THREAD_DATA_C_BORDER*4]
  int  0x40
  mov  edx,[ebp+MENUET_THREAD_DATA_TITLE*4]
  test edx,edx
  jz   Menuet_window_defined
  mov  edi,edx
  mov  ecx,0xFFFFFFFF
  xor  al,al
  cld
  repnz scas byte [edi]
  not  ecx
  mov  esi,ecx
  dec  esi
  jz   Menuet_window_defined
  mov  eax,4
  mov  ebx,0x00070007
  mov  ecx,[ebp+MENUET_THREAD_DATA_C_TITLE*4]
  int  0x40
Menuet_window_defined:
  mov  eax,12
  mov  ebx,2
  int  0x40
Menuet_redraw_picture:
  mov  eax,12
  mov  ebx,2
  int  0x40
  mov  esi,[ebp+MENUET_THREAD_DATA_PICTURE*4]
  test esi,esi
  jz   Menuet_redraw_end_draw
  mov  ecx,[ebp+MENUET_THREAD_DATA_SZ_PICT*4]
  jecxz Menuet_redraw_end_draw
  mov  al,byte [ebp+MENUET_THREAD_DATA_C_WINDOW*4+3]
  and  al,15
  mov  edx,MENUET_BORDER_SIZE*65536+MENUET_HEADER_SIZE
  cmp  al,3
  jnz  Menuet_redraw_no_skin
  mov  eax,48
  mov  ebx,4
  int  0x40
  mov  dx,ax
Menuet_redraw_no_skin:
  mov  eax,7
  mov  ebx,esi
  int  0x40
Menuet_redraw_end_draw:
  pop  edi
  pop  esi
  pop  ebx
  pop  ebp
  ret
enddef

define @Menuet@MoveWindow$qxpxi
  push ebx
  push esi
  mov  eax,[esp+12]
  mov  ebx,[eax]
  mov  ecx,[eax+4]
  mov  edx,[eax+8]
  mov  esi,[eax+12]
  mov  eax,67
  int  0x40
  pop  esi
  pop  ebx
  ret
enddef

define @Menuet@Abort$qv
  push dword [@Menuet@DebugPrefix]
  call @Menuet@DebugPutString$qpxc
  mov  dword [esp],Menuet_abort_string
  call @Menuet@DebugPutString$qpxc
  pop  ecx
nextdef @Menuet@ExitProcess$qv
  lock bts dword [@Menuet@_ExitProcessNow],0
  jc   Menuet_exit_process_wait
  sub  esp,1024
  mov  eax,9
  mov  ebx,esp
  mov  ecx,-1
  int  0x40
  mov  esi,eax
  mov  edi,[esp+30]
Menuet_exit_process_loop:
  mov  eax,9
  mov  ebx,esp
  mov  ecx,esi
  int  0x40
  mov  eax,[esp+30]
  cmp  eax,edi
  jz   Menuet_exit_process_continue
  mov  ebx,eax
  or   bl,15
  inc  ebx
  jz   Menuet_exit_process_continue
  mov  ebx,eax
  call Menuet_HashInt
  movzx eax,al
  mov  eax,dword [@Menuet@_ThreadTable+eax*4]
  jmp  Menuet_exit_process_test
Menuet_exit_process_next:
  mov  eax,dword [eax+MENUET_THREAD_DATA_NEXT*4]
Menuet_exit_process_test:
  test eax,eax
  jz   Menuet_exit_process_continue
  cmp  ebx,[eax+MENUET_THREAD_DATA_PID*4]
  jnz  Menuet_exit_process_next
  mov  eax,18
  mov  ebx,2
  mov  ecx,esi
  int  0x40
Menuet_exit_process_continue:
  dec  esi
  jnl  Menuet_exit_process_loop
  add  esp,1024
  mov  dword [@Menuet@_ExitProcessNow],-1
if defined EMULATOR
  int3
  call 0x76543210
end if
Menuet_exit_process_end:
  mov  dword [@Menuet@_ThreadMutex],0
  or   eax,-1
  int  0x40
Menuet_exit_process_wait:
  mov  eax,5
  mov  ebx,1
Menuet_exit_process_wait_loop:
  cmp  dword [@Menuet@_ExitProcessNow],0
  jl   Menuet_exit_process_end
  int  0x40
  shl  ebx,1
  cmp  ebx,MENUET_MUTEX_MAX_TIME_WAIT
  jna  Menuet_exit_process_wait_loop
  mov  ebx,MENUET_MUTEX_MAX_TIME_WAIT
  jmp  Menuet_exit_process_wait_loop
enddef

define @Menuet@ExitThread$qppv,@Menuet@ThreadMain$qpvt1
  mov  esp,[esp+4]
  jmp  Menuet_main_end
enddef

define @Menuet@ReturnMessageLoop$qppv,@Menuet@ThreadMain$qpvt1
  mov  esp,[esp+4]
  bt   dword [esp+MENUET_THREAD_DATA_FLAG*4],30
  jc   Menuet_main_end
  jmp  Menuet_main_cycle
enddef

define @Menuet@Delay$qui
  push ebx
  mov  eax,5
  mov  ebx,[esp+8]
  int  0x40
  pop  ebx
  ret
enddef

define @Menuet@Clock$qv
  push ebx
  mov  eax,26
  mov  ebx,9
  int  0x40
  pop  ebx
  ret
enddef

define @Menuet@GetPackedTime$qv
  mov  eax,3
  int  0x40
  ret
enddef

define @Menuet@GetTime$qpi
  mov  eax,3
  int  0x40
  mov  edx,[esp+4]
  movzx ecx,al
  shr  ecx,4
  and  al,0x0F
  imul ecx,10
  add  cl,al
  mov  dword [edx+8],ecx
  mov  cl,ah
  shr  ecx,4
  and  ah,0x0F
  imul ecx,10
  add  cl,ah
  mov  dword [edx+4],ecx
  bswap eax
  mov  cl,ah
  shr  ecx,4
  and  ah,0x0F
  imul ecx,10
  add  cl,ah
  mov  dword [edx],ecx
  ret
enddef

define @Menuet@GetPackedDate$qv
  mov  eax,29
  int  0x40
  ret
enddef

define @Menuet@GetDate$qpi
  mov  eax,29
  int  0x40
  mov  edx,[esp+4]
  movzx ecx,al
  shr  ecx,4
  and  al,0x0F
  imul ecx,10
  add  cl,al
  mov  dword [edx+4],ecx
  mov  cl,ah
  shr  ecx,4
  and  ah,0x0F
  imul ecx,10
  add  cl,ah
  mov  dword [edx],ecx
  bswap eax
  mov  cl,ah
  shr  ecx,4
  and  ah,0x0F
  imul ecx,10
  add  cl,ah
  mov  dword [edx+8],ecx
  ret
enddef

define @Menuet@ReadCommonColors$qpui
  push ebx
  mov  eax,48
  mov  ebx,3
  mov  ecx,[esp+8]
  mov  edx,40
  int  0x40
  pop  ebx
  ret
enddef

define @Menuet@GetProcessInfo$qpuipct1t1piui
  push ebx
  push esi
  push edi
  sub  esp,1024
  mov  eax,9
  mov  ebx,esp
  mov  ecx,[1024+12+24+esp]
  int  0x40
  xor  edi,edi
  or   edi,[1024+12+4+esp]
  jz   Menuet_get_proc_info_no_usecpu
  mov  ecx,[esp]
  mov  [edi],ecx
  xor  edi,edi
Menuet_get_proc_info_no_usecpu:
  or   edi,[1024+12+8+esp]
  jz   Menuet_get_proc_info_no_name
  lea  esi,[esp+10]
  cld
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  mov  byte [edi],0
  xor  edi,edi
Menuet_get_proc_info_no_name:
  or   edi,[1024+12+12+esp]
  jz   Menuet_get_proc_info_no_mem
  mov  ecx,[esp+26]
  mov  [edi],ecx
  xor  edi,edi
Menuet_get_proc_info_no_mem:
  or   edi,[1024+12+16+esp]
  jz   Menuet_get_proc_info_no_pid
  mov  ecx,[esp+30]
  mov  [edi],ecx
  xor  edi,edi
Menuet_get_proc_info_no_pid:
  or   edi,[1024+12+20+esp]
  jz   Menuet_get_proc_info_no_rect
  lea  esi,[esp+34]
  cld
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  xor  edi,edi
Menuet_get_proc_info_no_rect:
  add  esp,1024
  pop  edi
  pop  esi
  pop  ebx
  ret
enddef

define @Menuet@GetPid$qv
  push ebx
  sub  esp,1024
  mov  eax,9
  mov  ebx,esp
  mov  ecx,-1
  int  0x40
  mov  eax,[esp+30]
  add  esp,1024
  pop  ebx
  ret
enddef

define @Menuet@GetPid$qppv
  mov  ecx,[esp+4]
  mov  eax,[ecx+MENUET_THREAD_DATA_PID*4]
  ret
enddef

define @Menuet@_HashByte$qui
nextdef @Menuet@_HashWord$qui
nextdef @Menuet@_HashDword$qui
  mov  eax,[esp+4]
nextdef Menuet_HashInt
  mul  dword [Menuet_hash_int_val0]
  xor  eax,edx
  bswap eax
  mul  dword [Menuet_hash_int_val1]
  shrd eax,edx,14
  bswap eax
  lea  eax,[eax+4*eax]
  ror  eax,9
  ret
Menuet_hash_int_val0:
  dd   0xA82F94C5
Menuet_hash_int_val1:
  dd   0x9193780B
enddef

define @Menuet@GetThreadData$qv
  call @Menuet@GetPid$qv
  push eax
  call @Menuet@GetThreadData$qui
  pop  ecx
  ret
enddef

define @Menuet@GetThreadData$qui
  mov  eax,[esp+4]
  call Menuet_HashInt
  movzx eax,al
  cmp  dword [@Menuet@_ThreadScanCount+4],0
  jnz  Menuet_get_thread_data_wait
Menuet_get_thread_data_nowait:
  lock inc dword [@Menuet@_ThreadScanCount]
  mov  eax,dword [@Menuet@_ThreadTable+eax*4]
  mov  ecx,[esp+4]
  jmp  Menuet_get_thread_data_test
Menuet_get_thread_data_loop:
  mov  eax,dword [eax+MENUET_THREAD_DATA_NEXT*4]
Menuet_get_thread_data_test:
  test eax,eax
  jz   Menuet_get_thread_data_end
  cmp  ecx,[eax+MENUET_THREAD_DATA_PID*4]
  jnz  Menuet_get_thread_data_loop
Menuet_get_thread_data_end:
  lock dec dword [@Menuet@_ThreadScanCount]
  ret
Menuet_get_thread_data_wait:
  push eax
  push ebx
  mov  eax,5
  mov  ebx,1
Menuet_get_thread_data_wait_loop:
  int  0x40
  cmp  dword [@Menuet@_ThreadScanCount+4],0
  jz   Menuet_get_thread_data_wait_end
  shl  ebx,1
  cmp  ebx,MENUET_MUTEX_MAX_TIME_WAIT
  jna  Menuet_get_thread_data_wait_loop
  mov  ebx,MENUET_MUTEX_MAX_TIME_WAIT
  jmp  Menuet_get_thread_data_wait_loop
Menuet_get_thread_data_wait_end:
  pop  ebx
  pop  eax
  jmp Menuet_get_thread_data_nowait
enddef

define @Menuet@_GetSkinHeader$qv
  push ebx
  mov  eax,48
  mov  ebx,4
  int  0x40
  pop  ebx
  ret
enddef

define @Menuet@GetScreenSize$qrust1
  mov  eax,14
  int  0x40
  mov  ecx,[esp+8]
  mov  word [ecx],ax
  mov  ecx,[esp+4]
  shr  eax,16
  mov  word [ecx],ax
  ret
enddef

define Menuet_MutexLockNoWait
  pop  eax
  xor  al,al
  ret
enddef

define Menuet_MutexLockWait
  push ebx
  mov  eax,5
  xor  ebx,ebx
Menuet_lock_wait_cycle:
  int  0x40
  shl  byte [ecx],1
  jz   Menuet_lock_wait_cycle
  pop  ebx
  mov  al,1
  ret
enddef

define Menuet_MutexLockWaitTime
  cmp  dword [esp+12],0
  jng  Menuet_MutexLockWait
  push ebx
  push edx
  mov  edx,[esp+20]
  mov  eax,26
  mov  ebx,9
  int  0x40
  add  edx,eax
Menuet_lock_wait_time_cycle:
  mov  eax,5
  xor  ebx,ebx
  int  0x40
  shl  byte [ecx],1
  jnz  Menuet_lock_wait_time_ret_true
  mov  eax,26
  mov  ebx,9
  int  0x40
  cmp  eax,edx
  js   Menuet_lock_wait_time_cycle
  pop  edx
  pop  ebx
  pop  eax
  xor  al,al
  ret
Menuet_lock_wait_time_ret_true:
  pop  edx
  pop  ebx
  mov  al,1
  ret
enddef

define Menuet_MutexLock
  shl  byte [ecx],1
  jnz  Menuet_lock_first
  call eax
Menuet_lock_first:
  mov  al,1
  ret
enddef

define @Menuet@TryLock$qp13Menuet@TMutex
  mov  eax,Menuet_MutexLockNoWait
  mov  ecx,[esp+4]
  jmp  Menuet_MutexLock
enddef

define @Menuet@Lock$qp13Menuet@TMutex
  mov  eax,Menuet_MutexLockWait
  mov  ecx,[esp+4]
  jmp  Menuet_MutexLock
enddef

define @Menuet@LockTime$qp13Menuet@TMutexi
  mov  eax,Menuet_MutexLockWaitTime
  mov  ecx,[esp+4]
  jmp  Menuet_MutexLock
enddef

define @Menuet@UnLock$qp13Menuet@TMutex
  mov  ecx,[esp+4]
  shr  byte [ecx],1
  jz   Menuet_unlock_pause
  ret
Menuet_unlock_pause:
  mov  byte [ecx],0x40
  push ebx
  mov  eax,5
  xor  ebx,ebx
  int  0x40
  pop  ebx
  ret
enddef

define Menuet_MutexLockRec
  shl  byte [ecx],1
  jng  Menuet_lock_first
  cmp  dword [ecx+4],edx
  jz   Menuet_lock_rec_self
  call eax
Menuet_lock_rec_first:
  mov  al,1
  mov  dword [ecx+4],edx
  ret
Menuet_lock_rec_self:
  mov  al,1
  add  dword [ecx],0x100
  jc   Menuet_lock_rec_overflow
  ret
Menuet_lock_rec_overflow:
  push dword [@Menuet@DebugPrefix]
  call @Menuet@DebugPutString$qpxc
  mov  dword [esp],Menuet_try_lock_rec_overflow_string
  call @Menuet@DebugPutString$qpxc
  pop  ecx
  jmp  @Menuet@Abort$qv
enddef

define @Menuet@TryLock$qp16Menuet@TRecMutexui
  mov  eax,Menuet_MutexLockNoWait
  mov  ecx,[esp+4]
  mov  edx,[esp+8]
  jmp  Menuet_MutexLockRec
enddef

define @Menuet@Lock$qp16Menuet@TRecMutexui
  mov  eax,Menuet_MutexLockWait
  mov  ecx,[esp+4]
  mov  edx,[esp+8]
  jmp  Menuet_MutexLockRec
enddef

define @Menuet@LockTime$qp16Menuet@TRecMutexiui
  mov  eax,Menuet_MutexLockWaitTime
  mov  ecx,[esp+4]
  mov  edx,[esp+12]
  jmp  Menuet_MutexLockRec
enddef

define @Menuet@UnLock$qp16Menuet@TRecMutexui
  mov  ecx,[esp+4]
  mov  edx,[esp+8]
  cmp  dword [ecx+4],edx
  jnz  Menuet_unlock_rec_notlocked
  sub  dword [ecx],0x100
  jnc  Menuet_unlock_rec_end
  add dword [ecx],0x100
  shl byte [ecx],1
  shr byte [ecx],2
  jng  Menuet_unlock_rec_pause
Menuet_unlock_rec_end:
  ret
Menuet_unlock_rec_pause:
  mov  byte [ecx],0x20
  push ebx
  mov  eax,5
  xor  ebx,ebx
  int  0x40
  pop  ebx
  ret
Menuet_unlock_rec_notlocked:
  push dword [@Menuet@DebugPrefix]
  call @Menuet@DebugPutString$qpxc
  mov  dword [esp],Menuet_unlock_rec_notlocked_string
  call @Menuet@DebugPutString$qpxc
  pop  ecx
  jmp  @Menuet@Abort$qv
enddef

define @Menuet@DebugPutChar$qc
  mov  cl,byte [esp+4]
  cmp  cl,13
  jz   Menuet_debug_put_char_ret
  push ebx
  cmp  cl,10
  jz   Menuet_debug_put_char_enter
Menuet_debug_put_char_after_cmp:
  mov  eax,63
  mov  ebx,1
  int  0x40
  pop  ebx
Menuet_debug_put_char_ret:
  ret
Menuet_debug_put_char_enter:
  mov  cl,13
  mov  eax,63
  mov  ebx,1
  int  0x40
  mov  cl,10
  jmp  Menuet_debug_put_char_after_cmp
enddef

define @Menuet@DebugPutString$qpxc
  push esi
  push dword 0
  mov  esi,dword [esp+12]
  jmp  Menuet_debug_put_string_test
Menuet_debug_put_string_loop:
  mov  dword [esp],eax
  call @Menuet@DebugPutChar$qc
  inc  esi
Menuet_debug_put_string_test:
  xor  eax,eax
  or   al,[esi]
  test al,al
  jnz  Menuet_debug_put_string_loop
  pop  ecx
  pop  esi
  ret
enddef

define @Menuet@GetKey$qv
  mov  eax,2
  int  0x40
  test al,al
  jnz  Menuet_get_key_eof
  movzx eax,ah
  ret
Menuet_get_key_eof:
  mov  eax,-1
  ret
enddef

define @Menuet@GetMouseButton$qv
  push ebx
  mov  eax,37
  mov  ebx,2
  int  0x40
  pop  ebx
  ret
enddef

define @Menuet@GetMousePosition$qrst1o
  push ebx
  mov  eax,37
  xor  ebx,ebx
  cmp  byte [esp+16],0
  jnz  Menuet_get_mouse_pos_absolute
  inc  ebx
Menuet_get_mouse_pos_absolute:
  int  0x40
  mov  ecx,[esp+12]
  mov  word [ecx],ax
  mov  ecx,[esp+8]
  shr  eax,16
  mov  word [ecx],ax
  pop  ebx
  ret
enddef

define @Menuet@WasThreadCreated$qv
  cmp  byte [@Menuet@_ThreadSavedBegProc],0x90
  setz al
  ret
enddef

define @Menuet@CreateThread$qpvuit1
  push ebx
  mov  edx,[esp+16]
  mov  ebx,[esp+12]
  test edx,edx
  jnz  Menuet_create_thread_after_new
if defined MenuetHeapAlloc
  cmp  ebx,4096
  jnb  Menuet_create_thread_alloc
  mov  ebx,STACKSIZE
Menuet_create_thread_alloc:
  push ebx
  call MenuetHeapAlloc   ; Create new dynamic memory of the given size
  pop  ecx
  test eax,eax
  jnz  Menuet_create_thread_mem_created
end if
  or   eax,-1
  jmp  Menuet_create_thread_end
Menuet_create_thread_mem_created:
  lea  edx,[eax+ebx]
Menuet_create_thread_after_new:
  neg  ebx
  jz   Menuet_create_thread_test_first
  add  ebx,edx
Menuet_create_thread_test_first:
  cmp  byte [@Menuet@_ThreadSavedBegProc],0x90
  jnz  Menuet_create_thread_init
Menuet_create_thread_fill_stack:
  lock inc dword [@Menuet@_ThreadNumber]
  and  edx,not 3
  sub  edx,12
  mov  ecx,[esp+8]
  mov  dword [edx+8],ebx
  mov  dword [edx+4],ecx
  mov  dword [edx],Menuet_ThreadFinish
  mov  eax,51
  mov  ebx,1
  mov  ecx,@Menuet@ThreadMain$qpvt1
  int  0x40
  mov  ebx,eax
  or   bl,15
  inc  ebx
  jnz  Menuet_create_thread_end
  lock dec dword [@Menuet@_ThreadNumber]
if defined MenuetHeapFree
  or   ebx,[edx+8]
  jz   Menuet_create_thread_end
  push ebx
  call MenuetHeapFree   ; Delete the given dynamic memory
  pop  ecx
end if
Menuet_create_thread_end:
  pop  ebx
  ret
Menuet_create_thread_init:
  push esi
  push edi
  cld
  mov  esi,@Menuet@_ThreadSavedBegProc
  mov  edi,@Menuet@GetPid$qv
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  mov  edi,@Menuet@GetThreadData$qv
  movs dword [edi],[esi]
  movs dword [edi],[esi]
  mov  eax,0x90909090
  mov  edi,@Menuet@_ThreadSavedBegProc
  stos dword [edi]
  stos dword [edi]
  stos dword [edi]
  stos dword [edi]
  pop  edi
  pop  esi
  jmp  Menuet_create_thread_fill_stack
enddef

define @Menuet@_FileAccess$qpv
  push ebx
  mov  eax,70
  mov  ebx,[esp+8]
  int  0x40
  mov  ecx,[esp+8]
  mov  [ecx],ebx
  pop  ebx
  ret
enddef

define Menuet_abort_string
  db 'Abnormal program termination.',10,0
newdef Menuet_try_lock_rec_overflow_string
  db 'Recursive mutex lock count overflow.',10,0
newdef Menuet_unlock_rec_notlocked_string
  db 'Recursive mutex unlock error.',10,0
enddef

include "me_lib.inc"

;/**/