Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ; Cb-n#%li.-# @l$i Lkbnbe
  2. convert_color:
  3.         bswap   eax
  4.         shr     eax, 8
  5.         ret
  6.  
  7. draw_window_base:
  8.         mov     al, byte [ebp+tls.color_main+3]
  9.         and     eax, 0xF
  10.         dec     eax
  11.         js      .type1
  12.         jz      .nodraw
  13.         dec     eax
  14.         jz      .type2
  15. ; window with skin
  16.         push    1
  17.         call    draw_border
  18.         call    draw_caption_skinned
  19.         movzx   eax, [ebp+tls.y_size]
  20.         cmp     eax, 21+5
  21.         jle     @f
  22.         test    byte [ebp+tls.color_main+3], 40h
  23.         jnz     @f
  24.         push    1
  25.         push    [ebp+tls.color_main]
  26.         movzx   ecx, [ebp+tls.y_size]
  27.         sub     ecx, 5
  28.         push    ecx
  29.         movzx   ecx, [ebp+tls.x_size]
  30.         sub     ecx, 5
  31.         push    ecx
  32.         push    [_skinh]
  33.         push    5
  34.         call    rectangle_gradient
  35. @@:
  36. ; close button
  37.         mov     edx, 40000001h  ; id=1, no draw
  38.         xor     ebx, ebx
  39.         cmp     [skin_btn_close.left], ebx
  40.         jge     @f
  41.         mov     ebx, dword [ebp+tls.x_size]
  42. @@:
  43.         add     ebx, [skin_btn_close.left]
  44.         shl     ebx, 16
  45.         mov     bx, word [skin_btn_close.width]
  46.         dec     ebx
  47.         mov     ecx, [skin_btn_close.top]
  48.         shl     ecx, 16
  49.         mov     cx, word [skin_btn_close.height]
  50.         dec     ecx
  51.         call    add_button
  52. ; minimize button
  53.         mov     edx, 4000FFFFh  ; id=65535, no draw
  54.         xor     ebx, ebx
  55.         cmp     [skin_btn_minimize.left], ebx
  56.         jge     @f
  57.         mov     ebx, dword [ebp+tls.x_size]
  58. @@:
  59.         add     ebx, [skin_btn_minimize.left]
  60.         shl     ebx, 16
  61.         mov     bx, word [skin_btn_minimize.width]
  62.         dec     ebx
  63.         mov     ecx, [skin_btn_minimize.top]
  64.         shl     ecx, 16
  65.         mov     cx, word [skin_btn_minimize.height]
  66.         dec     ecx
  67.         call    add_button
  68.         jmp     .nodraw
  69. .type1:
  70. ; border
  71.         mov     eax, [ebp+tls.color_border]
  72.         call    create_select_pen
  73.         push    eax
  74.         xor     esi, esi
  75.         call    rect_wnd
  76.         call    select_delete
  77. ; caption
  78.         call    draw_caption_type1
  79. ; work area
  80.         test    byte [ebp+tls.color_main+3], 40h
  81.         jnz     .nodraw
  82.         push    1
  83.         push    [ebp+tls.color_main]
  84.         movzx   eax, [ebp+tls.y_size]
  85.         dec     eax
  86.         push    eax
  87.         movzx   eax, [ebp+tls.x_size]
  88.         dec     eax
  89.         push    eax
  90.         push    21
  91.         push    1
  92.         call    rectangle_gradient
  93.         jmp     .nodraw
  94. .type2:
  95. ; border
  96.         push    eax
  97.         call    draw_border
  98. ; caption
  99.         call    draw_caption_type2
  100. ; work area
  101.         test    byte [ebp+tls.color_main+3], 40h
  102.         jnz     .nodraw
  103.         push    1
  104.         push    [ebp+tls.color_main]
  105.         movzx   eax, [ebp+tls.y_size]
  106.         sub     eax, 5
  107.         push    eax
  108.         movzx   eax, [ebp+tls.x_size]
  109.         sub     eax, 5
  110.         push    eax
  111.         push    20
  112.         push    5
  113.         call    rectangle_gradient
  114. .nodraw:
  115. ; caption string
  116.         call    draw_caption_string
  117. ; draw buttons
  118.         pushad
  119.         mov     esi, [ebp+tls.buttons]
  120. @@:
  121.         test    esi, esi
  122.         jz      @f
  123.         push    [esi+button_desc.next]
  124.         mov     ebx, dword [esi+button_desc.xsize]
  125.         mov     ecx, dword [esi+button_desc.ysize]
  126.         test    byte [esi+button_desc.id+3], 0x40
  127.         mov     esi, [esi+button_desc.color]
  128.         jnz     .sk
  129.         call    draw_button
  130. .sk:
  131.         pop     esi
  132.         jmp     @b
  133. @@:
  134.         popad
  135.         ret
  136.  
  137. draw_caption_type1:
  138.         push    040404h
  139.         push    [ebp+tls.color_capt]
  140.         movzx   eax, [ebp+tls.y_size]
  141.         dec     eax
  142.         cmp     eax, 21
  143.         jb      @f
  144.         mov     eax, 21
  145. @@:
  146.         push    eax
  147.         movzx   eax, [ebp+tls.x_size]
  148.         dec     eax
  149.         push    eax
  150.         push    1
  151.         push    1
  152.         call    rectangle_gradient
  153.         ret
  154.  
  155. draw_caption_type2:
  156.         mov     eax, [ebp+tls.color_capt]
  157.         mov     ecx, 0x040404
  158.         test    eax, 0x40000000
  159.         jz      @f
  160.         or      ecx, 0x80000000
  161.         xor     eax, 0xC0000000
  162. @@:
  163.         push    ecx
  164.         push    eax
  165.         movzx   eax, [ebp+tls.y_size]
  166.         sub     eax, 4
  167.         cmp     eax, 20
  168.         jb      @f
  169.         mov     eax, 20
  170. @@:     push    eax
  171.         movzx   eax, [ebp+tls.x_size]
  172.         sub     eax, 4
  173.         push    eax
  174.         push    4
  175.         push    4
  176.         call    rectangle_gradient
  177.         ret
  178.  
  179. draw_caption_skinned:
  180.         xor     ebx, ebx
  181.         mov     eax, [left_bmp]
  182.         cmp     [ebp+tls.bActive], bl
  183.         jnz     @f
  184.         mov     eax, [left1_bmp]
  185. @@:
  186.         xor     ecx, ecx
  187.         call    putbmp
  188.         movzx   esi, [ebp+tls.x_size]
  189.         mov     ecx, [eax+4]
  190.         sub     esi, ecx
  191.         mov     eax, [oper_bmp]
  192.         cmp     [ebp+tls.bActive], bl
  193.         jnz     @f
  194.         mov     eax, [oper1_bmp]
  195. @@:
  196.         sub     esi, [eax+4]
  197.         mov     eax, [base_bmp]
  198.         cmp     [ebp+tls.bActive], bl
  199.         jnz     @f
  200.         mov     eax, [base1_bmp]
  201. @@:
  202.         cmp     esi, [eax+4]
  203.         jle     .nobase
  204. @@:
  205.         call    putbmp
  206.         add     ecx, [eax+4]
  207.         sub     esi, [eax+4]
  208.         jg      @b
  209. .nobase:
  210.         movzx   ecx, [ebp+tls.x_size]
  211.         mov     eax, [oper_bmp]
  212.         cmp     [ebp+tls.bActive], bl
  213.         jnz     @f
  214.         mov     eax, [oper1_bmp]
  215. @@:
  216.         sub     ecx, [eax+4]
  217.  
  218. putbmp:
  219. ; in: eax=bmpinfo,ecx=y*65536+x,edi=hDC
  220.         push    eax ecx
  221.         lea     edx, [eax+40]
  222.         push    ebx             ; fuColorUse = DIB_RGB_COLORS
  223.         push    eax             ; lpbmi
  224.         push    edx             ; lpBits
  225.         push    dword [eax+8]   ; cScanLines
  226.         push    ebx             ; uStartScan
  227.         push    ebx             ; YSrc
  228.         push    ebx             ; XSrc
  229.         push    dword [eax+8]   ; dwHeight
  230.         push    dword [eax+4]   ; dwWidth
  231.         movzx   eax, cx
  232.         shr     ecx, 10h
  233.         push    ecx             ; YDest
  234.         push    eax             ; XDest
  235.         push    edi             ; hDC
  236.         call    [SetDIBitsToDevice]
  237.         pop     ecx eax
  238.         ret
  239.  
  240. draw_caption_string:
  241.         test    byte [ebp+tls.color_main+3], 0x10
  242.         jnz     @f
  243. .ret:
  244. .nodraw:
  245.         ret
  246. @@:
  247.         mov     esi, [ebp+tls.caption]
  248.         test    esi, esi
  249.         jz      .ret
  250.         add     esi, [base]
  251.         mov     al, byte [ebp+tls.color_main+3]
  252.         and     eax, 0xF
  253.         dec     eax
  254.         js      .type1
  255.         jz      .nodraw
  256.         dec     eax
  257.         jz      .type2
  258. ; caption for skinned windows
  259. ; determine maximum caption length
  260.         mov     ax, [ebp+tls.x_size]
  261.         sub     ax, [margins+2]
  262.         sub     ax, [margins]
  263.         js      .ret
  264.         cwd
  265.         push    6
  266.         pop     ebx
  267.         div     bx
  268.         mov     ecx, eax
  269. ; determine coordinates
  270.         mov     ebx, dword [margins]
  271.         mov     bx, word [_skinh]
  272.         sub     bx, [margins+6]
  273.         sub     bx, [margins+4]
  274.         sar     bx, 1
  275.         adc     bx, 0
  276.         add     bx, [margins+6]
  277.         add     bx, -3
  278. .common:
  279.         mov     edx, esi
  280. @@:
  281.         lodsb
  282.         test    al, al
  283.         loopnz  @b
  284.         jnz     @f
  285.         dec     esi
  286. @@:     sub     esi, edx
  287.         mov     ecx, dword [common_colors+16]
  288.         jmp     i40_writetext_l2
  289. .type1:
  290. .type2:
  291. ; caption for windows without skin
  292.         movzx   eax, [ebp+tls.x_size]
  293.         sub     eax, 16
  294.         js      .ret
  295.         cdq
  296.         push    6
  297.         pop     ebx
  298.         div     ebx
  299.         mov     ecx, eax
  300.         mov     ebx, 0x00080007
  301.         jmp     .common
  302.  
  303. i40_draw_window:
  304.         mov     [ebp+tls.color_main], edx
  305.         mov     [ebp+tls.color_capt], esi
  306.         mov     [ebp+tls.color_border], edi
  307.         mov     [ebp+tls.curdraw], 0
  308.         cmp     [ebp+tls.showwnd], 0
  309.         jnz     .wasshown
  310. ; real size is 1 pixel more
  311.         inc     ebx
  312.         mov     dword [ebp+tls.x_size], ebx
  313.         inc     ecx
  314.         mov     dword [ebp+tls.y_size], ecx
  315.         test    edx, 0x10000000
  316.         jz      @f
  317.         mov     [ebp+tls.caption], edi
  318. @@:
  319.         push    0
  320.         movzx   eax, cx
  321.         push    eax
  322.         movzx   eax, bx
  323.         push    eax
  324.         shr     ecx, 10h
  325.         push    ecx
  326.         shr     ebx, 10h
  327.         push    ebx
  328.         push    [ebp+tls.hWnd]
  329.         call    [MoveWindow]
  330.         push    5       ; SW_SHOW
  331.         push    [ebp+tls.hWnd]
  332.         call    [ShowWindow]
  333.         mov     [ebp+tls.showwnd], 1
  334.         cmp     [ebp+tls.lpShapeData], 0
  335.         jz      @f
  336.         call    set_window_shape
  337. @@:
  338. .wasshown:
  339. ; define client box
  340.         test    byte [ebp+tls.color_main+3], 0x20
  341.         jnz     .client_relative
  342.         and     [ebp+tls.client_left], 0
  343.         and     [ebp+tls.client_top], 0
  344.         movzx   eax, [ebp+tls.x_size]
  345.         mov     [ebp+tls.client_width], eax
  346.         movzx   eax, [ebp+tls.y_size]
  347.         mov     [ebp+tls.client_height], eax
  348.         jmp     .client_set
  349. .client_relative:
  350.         mov     eax, [_skinh]
  351.         mov     [window_topleft+8*3+4], eax
  352.         mov     [window_topleft+8*4+4], eax
  353.         mov     al, byte [ebp+tls.color_main+3]
  354.         and     eax, 0xF
  355.         mov     edx, [eax*8+window_topleft]
  356.         mov     [ebp+tls.client_left], edx
  357.         neg     edx
  358.         movzx   ecx, [ebp+tls.x_size]
  359.         lea     ecx, [ecx+edx*2]
  360.         mov     [ebp+tls.client_width], ecx
  361.         mov     eax, [eax*8+window_topleft+4]
  362.         mov     [ebp+tls.client_top], eax
  363.         movzx   ecx, [ebp+tls.y_size]
  364.         sub     ecx, eax
  365.         add     ecx, edx
  366.         mov     [ebp+tls.client_height], ecx
  367. .client_set:
  368.         push    0
  369.         push    [ebp+tls.hWnd]
  370.         call    [ValidateRect]
  371.         push    [ebp+tls.hWnd]
  372.         call    [GetDC]
  373.         xchg    eax, edi
  374.         call    draw_window_base
  375.         push    edi
  376.         push    [ebp+tls.hWnd]
  377.         call    [ReleaseDC]
  378.         ret
  379.  
  380. i40_put_pixel:
  381.         test    edx, 1000000h
  382.         jnz     .negate
  383.         mov     eax, edx
  384.         call    convert_color
  385.         push    eax
  386.         add     ebx, [ebp+tls.client_left]
  387.         add     ecx, [ebp+tls.client_top]
  388.         push    ecx
  389.         push    ebx
  390.         push    [ebp+tls.hWnd]
  391.         call    [GetDC]
  392.         xchg    eax, edi
  393. .1:
  394.         push    edi
  395.         call    [SetPixel]
  396.         push    edi
  397.         push    [ebp+tls.hWnd]
  398.         call    [ReleaseDC]
  399.         ret
  400. .negate:
  401.         push    ecx
  402.         push    ecx
  403.         push    ebx
  404.         push    [ebp+tls.hWnd]
  405.         call    [GetDC]
  406.         xchg    eax, edi
  407.         push    edi
  408.         call    [GetPixel]
  409.         pop     ecx
  410.         not     eax
  411.         push    eax
  412.         push    ecx
  413.         push    ebx
  414.         jmp     .1
  415.  
  416. i40_getkey:
  417.         movzx   ecx, [ebp+tls.keybuflen]
  418.         jecxz   .empty
  419.         lea     esi, [ebp+tls.keybuffer]
  420.         mov     edi, esi
  421.         lodsb
  422.         shl     eax, 8
  423.         mov     [esp+20h], ax
  424.         dec     ecx
  425.         mov     [ebp+tls.keybuflen], cl
  426.         rep     movsb
  427.         ret
  428. .empty:
  429.         mov     byte [esp+20h], 1
  430.         ret
  431.  
  432. i40_get_sys_time:
  433.         sub     esp, 10h
  434.         push    esp
  435.         call    [GetLocalTime]
  436.         movzx   eax, word [esp+12]
  437.         aam
  438.         shl     ax, 4
  439.         shr     ah, 4
  440.         shl     eax, 16-4
  441.         mov     ax, [esp+10]
  442.         aam
  443.         shl     ax, 4
  444.         shr     ah, 4
  445.         shr     ax, 4
  446.         mov     bl, al
  447.         mov     ax, [esp+8]
  448.         aam
  449.         shl     ax, 4
  450.         shr     ah, 4
  451.         shr     ax, 4
  452.         mov     ah, bl
  453.         add     esp, 10h
  454.         mov     [esp+20h], eax
  455.         ret
  456.  
  457. i40_writetext:
  458.         add     edx, [base]
  459. i40_writetext_l1:
  460.         add     bx, word [ebp+tls.client_top]
  461.         ror     ebx, 16
  462.         add     bx, word [ebp+tls.client_left]
  463.         ror     ebx, 16
  464. i40_writetext_l2:
  465.         push    edi
  466.         push    ecx
  467.         push    edx
  468.         push    [ebp+tls.hWnd]
  469.         call    [GetDC]
  470.         mov     ecx, esi
  471.         pop     esi
  472.         pop     edi
  473.         push    eax
  474. ; ecx=length, esi=pointer, ebx=x*65536+y, edi=font&color
  475. .loop:
  476.         xor     eax, eax
  477.         lodsb
  478.         test    edi, edi
  479.         js      .test_asciiz
  480.         dec     ecx
  481.         js      .done
  482.         jmp     @f
  483. .test_asciiz:
  484.         test    eax, eax
  485.         jz      .done
  486. @@:
  487.         push    esi
  488.         push    ecx
  489.         mov     esi, [char_mt]
  490.         lea     esi, [esi + eax*8]
  491.         add     esi, eax
  492.         mov     ecx, 6
  493.         test    edi, 10000000h
  494.         jz      @f
  495.         sub     esi, [char_mt]
  496.         add     esi, [char2_mt]
  497.         add     esi, eax
  498.         lodsb
  499.         mov     ecx, eax
  500. @@:
  501.         mov     edx, 9
  502. .intloop:
  503.         lodsb
  504.         push    ebx
  505.         push    ecx
  506. .intintloop:
  507.         shr     al, 1
  508.         pushad
  509.         jnc     .nopix
  510.         mov     eax, edi
  511. @@:
  512.         call    convert_color
  513.         push    eax
  514.         movzx   eax, bx
  515.         push    eax
  516.         shr     ebx, 16
  517.         push    ebx
  518.         push    dword [esp+3Ch] ; hDC
  519.         call    [SetPixel]
  520.         jmp     @f
  521. .nopix:
  522.         mov     eax, [esp+34h]
  523.         test    edi, 0x40000000
  524.         jnz     @b
  525. @@:
  526.         popad
  527.         add     ebx, 10000h
  528.         loop    .intintloop
  529.         pop     ecx
  530.         pop     ebx
  531.         inc     ebx
  532.         dec     edx
  533.         jnz     .intloop
  534.         sub     ebx, 9
  535.         shl     ecx, 16
  536.         add     ebx, ecx
  537.         pop     ecx
  538.         pop     esi
  539.         jmp     .loop
  540. .done:
  541.         push    [ebp+tls.hWnd]
  542.         call    [ReleaseDC]
  543.         pop     edi
  544.         ret
  545.  
  546. i40_delay:
  547.         imul    ebx, ebx, 10
  548.         push    ebx
  549.         call    [Sleep]
  550.         ret
  551.  
  552. ramdisk2win32:
  553.         push    edi
  554.         add     ebx, [base]
  555.         mov     esi, ramdisk_path
  556.         push    esi
  557.         call    [lstrlenA]
  558.         xchg    eax, ecx
  559.         rep     movsb
  560.         push    edi
  561.         push    edi
  562.         mov     ecx, 8
  563. @@:
  564.         mov     al, [ebx]
  565.         inc     ebx
  566.         cmp     al, '.'
  567.         jz      @f
  568.         stosb
  569.         loop    @b
  570. @@:
  571.         dec     edi
  572.         cmp     byte [edi], ' '
  573.         jz      @b
  574.         inc     edi
  575.         mov     al, '.'
  576.         stosb
  577.         cmp     [ebx], al
  578.         jnz     @f
  579.         inc     ebx
  580. @@:
  581.         mov     ecx, 3
  582. @@:
  583.         mov     al, [ebx]
  584.         inc     ebx
  585.         stosb
  586.         loop    @b
  587. @@:
  588.         dec     edi
  589.         cmp     byte [edi], ' '
  590.         jz      @b
  591.         inc     edi
  592.         xor     eax, eax
  593.         stosb
  594.         call    [OemToCharA]
  595.         xor     eax, eax
  596.         pop     edi
  597.         ret
  598.  
  599. i40_read_floppy_file:
  600.         sub     esp, 512
  601.         mov     edi, esp
  602.         push    esi
  603.         call    ramdisk2win32
  604.         pop     ebx
  605.         push    eax
  606.         push    eax
  607.         push    3
  608.         push    eax
  609.         push    1
  610.         push    80000000h
  611.         push    edi
  612.         call    [CreateFileA]
  613.         add     esp, 512
  614.         inc     eax
  615.         jz      .err_ret
  616.         dec     eax
  617.         xchg    eax, esi
  618.         push    0
  619.         push    esi
  620.         call    [GetFileSize]
  621.         xchg    eax, edi
  622.         push    eax
  623.         mov     ecx, esp
  624.         push    0
  625.         push    ecx
  626.         push    edi
  627.         add     ebx, [base]
  628.         push    ebx
  629.         push    esi
  630.         call    [ReadFile]
  631.         pop     eax
  632.         push    esi
  633.         call    [CloseHandle]
  634.         mov     [esp+20h], edi
  635.         ret
  636. .err_ret:
  637.         or      dword [esp+20h], -1
  638.         ret
  639.  
  640. pad_bmp:
  641.         pushad
  642.         movzx   eax, cx
  643.         shr     ecx, 10h
  644.         lea     ecx, [ecx+ecx*2]
  645.         add     ecx, 3
  646.         and     ecx, not 3
  647.         mul     ecx
  648.         push    eax
  649.         call    malloc
  650.         mov     [esp+1Ch], eax
  651.         popad
  652.         push    eax
  653.         mov     edi, eax
  654.         push    ecx
  655.         mov     esi, ebx
  656. .extloop:
  657.         push    ecx
  658.         shr     ecx, 10h
  659.         lea     ecx, [ecx+ecx*2]
  660.         mov     eax, ecx
  661.         shr     ecx, 2
  662.         rep     movsd
  663.         mov     ecx, eax
  664.         and     ecx, 3
  665.         rep     movsb
  666.         mov     al, 0
  667. @@:     test    edi, 3
  668.         jz      @f
  669.         stosb
  670.         jmp     @b
  671. @@:     pop     ecx
  672.         dec     cx
  673.         jnz     .extloop
  674.         pop     ecx
  675.         pop     edi
  676.         jmp     pad_cont
  677.  
  678. i40_putimage:
  679.         add     ebx, [base]
  680. ; Windows requires that all scanlines are DWORD-padded
  681.         mov     edi, ebx
  682.         test    ecx, 30000h
  683.         jnz     pad_bmp
  684. pad_cont:
  685.         xor     esi, esi
  686. ; BITMAPINFO
  687.         push    esi     ; biClrImportant
  688.         push    esi     ; biClrUsed
  689.         push    esi     ; biYPelsPerMeter
  690.         push    esi     ; biXPelsPerMeter
  691.         push    esi     ; biSizeImage
  692.         push    esi     ; biCompression
  693.         push    180001h ; biPlanes, biBitCount
  694.         movzx   eax, cx
  695.         neg     eax
  696.         push    eax     ; biHeight
  697.         neg     eax
  698.         shr     ecx, 10h
  699.         push    ecx     ; biWidth
  700.         push    40      ; biSize
  701.         push    ebx
  702.         lea     ebx, [esp+4]
  703. ; SetDIBitsToDevice
  704.         push    esi     ; fuColorUse = DIB_RGB_COLORS
  705.         push    ebx     ; lpbmi
  706.         push    edi     ; lpvBits
  707.         push    eax     ; cScanLines
  708.         dec     eax
  709.         push    eax     ; uStartScan
  710.         push    eax     ; YSrc
  711.         inc     eax
  712.         push    esi     ; XSrc
  713.         push    eax     ; dwHeight
  714.         push    ecx     ; dwWidth
  715.         movzx   ecx, dx
  716.         add     ecx, [ebp+tls.client_top]
  717.         push    ecx     ; YDest
  718.         shr     edx, 10h
  719.         add     edx, [ebp+tls.client_left]
  720.         push    edx     ; XDest
  721.         push    [ebp+tls.hWnd]
  722.         call    [GetDC]
  723.         xchg    eax, ebx
  724.         push    ebx     ; hdc
  725.         call    [SetDIBitsToDevice]
  726.         xchg    eax, ebx
  727.         pop     ebx
  728.         add     esp, 40
  729.         push    eax
  730.         push    [ebp+tls.hWnd]
  731.         call    [ReleaseDC]
  732.         cmp     edi, ebx
  733.         jz      @f
  734.         push    edi
  735.         call    free
  736. @@:
  737.         ret
  738.  
  739. draw_button:
  740.         push    ebx
  741.         push    ecx
  742.         push    ebp
  743.         mov     ebp, esp
  744. ; word [ebp+4]=y_size, word [ebp+6]=y_start, word [ebp+8]=x_size, word [ebp+10]=x_start
  745. ; button body
  746.         push    esi
  747.         cmp     [buttontype], 0
  748.         jz      .flatbtn
  749.         or      esi, 80000000h
  750.         push    esi
  751.         mov     edx, 2
  752. .l2:
  753.         cmp     byte [esp+edx], 0xEB
  754.         jbe     @f
  755.         mov     byte [esp+edx], 0xEB
  756. @@:     add     byte [esp+edx], 0x14
  757.         dec     edx
  758.         jns     .l2
  759.         pop     esi
  760.         mov     eax, 010101h
  761.         cmp     cx, 20
  762.         ja      @f
  763.         mov     eax, 020202h
  764. @@:
  765.         sub     esi, eax
  766. .flatbtn:
  767.         push    eax
  768.         push    esi
  769.         movzx   eax, word [ebp+6]
  770.         add     ax, cx
  771.         push    eax
  772.         movzx   eax, word [ebp+10]
  773.         add     ax, bx
  774.         push    eax
  775.         shr     ecx, 16
  776.         push    ecx
  777.         shr     ebx, 16
  778.         push    ebx
  779.         call    rectangle_gradient
  780. ; button frames
  781.         pop     eax
  782.         push    eax
  783.         push    eax
  784.         xor     ecx, ecx
  785. .l1:
  786.         cmp     byte [esp+ecx], 0xDF
  787.         jbe     @f
  788.         mov     byte [esp+ecx], 0xDF
  789. @@:
  790.         inc     ecx
  791.         cmp     ecx, 3
  792.         jb      .l1
  793.         pop     eax
  794.         add     eax, 202020h
  795.         call    create_select_pen
  796.         push    eax
  797.         push    0
  798.         movzx   eax, word [ebp+6]
  799.         add     ax, [ebp+4]
  800.         push    eax
  801.         push    ebx
  802.         push    edi
  803.         call    [MoveToEx]
  804.         movzx   eax, word [ebp+6]
  805.         push    eax
  806.         push    ebx
  807.         push    edi
  808.         call    [LineTo]
  809.         movzx   eax, word [ebp+6]
  810.         push    eax
  811.         movzx   eax, word [ebp+8]
  812.         add     ax, bx
  813.         push    eax
  814.         push    edi
  815.         call    [LineTo]
  816.         call    select_delete
  817.         cmp     byte [ebp-4], 20h
  818.         jae     @f
  819.         mov     byte [ebp-4], 20h
  820. @@:
  821.         cmp     byte [ebp-3], 20h
  822.         jae     @f
  823.         mov     byte [ebp-3], 20h
  824. @@:
  825.         cmp     byte [ebp-2], 20h
  826.         jae     @f
  827.         mov     byte [ebp-2], 20h
  828. @@:
  829.         mov     eax, [ebp-4]
  830.         sub     eax, 202020h
  831.         call    create_select_pen
  832.         push    eax
  833.         movzx   eax, word [ebp+4]
  834.         add     ax, [ebp+6]
  835.         push    eax
  836.         movzx   eax, word [ebp+8]
  837.         add     ax, bx
  838.         push    eax
  839.         push    edi
  840.         call    [LineTo]
  841.         movzx   eax, word [ebp+4]
  842.         add     ax, [ebp+6]
  843.         push    eax
  844.         push    ebx
  845.         push    edi
  846.         call    [LineTo]
  847.         call    select_delete
  848.         pop     eax
  849.         pop     ebp
  850.         pop     ecx
  851.         pop     ebx
  852.         ret
  853.  
  854. add_button:
  855.         push    esi
  856.         lea     esi, [ebp+tls.buttons]
  857. @@:
  858.         mov     eax, [esi]
  859.         test    eax, eax
  860.         jz      .end
  861.         xchg    esi, eax
  862.         jmp     @b
  863. .end:
  864.         push    ecx
  865.         push    edx
  866.         push    button_desc.size
  867.         call    malloc
  868.         mov     [esi], eax
  869.         mov     [eax+button_desc.next], 0
  870.         pop     [eax+button_desc.id]
  871.         mov     dword [eax+button_desc.xsize], ebx
  872.         pop     dword [eax+button_desc.ysize]
  873.         pop     [eax+button_desc.color]
  874.         ret
  875.  
  876. i40_define_button:
  877.         test    edx, 0x80000000
  878.         jnz     .delete
  879.         rol     ebx, 16
  880.         add     bx, word [ebp+tls.client_left]
  881.         rol     ebx, 16
  882.         rol     ecx, 16
  883.         add     cx, word [ebp+tls.client_top]
  884.         rol     ecx, 16
  885.         test    edx, 0x40000000
  886.         jnz     .nodraw
  887.         push    ecx
  888.         push    edx
  889.         push    [ebp+tls.hWnd]
  890.         call    [GetDC]
  891.         xchg    eax, edi
  892.         pop     edx
  893.         pop     ecx
  894.         pushad
  895.         call    draw_button
  896.         push    edi
  897.         push    [ebp+tls.hWnd]
  898.         call    [ReleaseDC]
  899.         popad
  900. .nodraw:
  901.         call    add_button
  902. .ret:
  903.         ret
  904. .delete:
  905.         and     edx, not 0x80000000
  906.         lea     esi, [ebp+tls.buttons]
  907. @@:
  908.         mov     eax, [esi]
  909.         test    eax, eax
  910.         jz      @f
  911. ; The kernel checks only low word of button ID!
  912.         cmp     word [eax+button_desc.id], dx
  913.         jz      .found
  914.         xchg    eax, esi
  915.         jmp     @b
  916. @@:
  917.         ret
  918. .found:
  919. ; if active button is deleting, there is no more active button
  920.         cmp     eax, [ebp+tls.active_button]
  921.         jnz     @f
  922.         and     [ebp+tls.active_button], 0
  923. @@:
  924.         push    [eax+button_desc.next]
  925.         push    eax
  926.         call    free
  927.         pop     [esi+button_desc.next]
  928.         ret
  929.  
  930. invalid_slot_msg db 'Emulated program has requested information on non-existent slot'
  931.         db      ' and will be terminated',0
  932. invalid_slot:
  933.         call    release_shared
  934.         push    0
  935.         push    0
  936.         push    invalid_slot_msg
  937.         push    0
  938.         call    [MessageBoxA]
  939.         jmp     i40_terminate
  940.  
  941. get_os_process_info:
  942.         pushad
  943.         mov     ebx, 5
  944.         call    i40_sys_service
  945.         popad
  946.         stosd           ; .cpu_usage
  947.         xor     eax, eax
  948.         inc     eax
  949.         stosw           ; .window_stack_position
  950.         stosw           ; .window_stack_value
  951.         dec     eax
  952.         stosw           ; .not_used1
  953.         mov     eax, 'OS/I'
  954.         stosd
  955.         mov     eax, 'DLE '
  956.         stosd
  957.         mov     eax, '   '
  958.         stosd
  959.         xor     eax, eax
  960.         stosd           ; .memory_start
  961.         mov     eax, 0x01000000-1
  962.         stosd           ; .used_memory
  963.         xor     eax, eax
  964.         inc     eax
  965.         stosd           ; .PID
  966.         dec     eax
  967.         stosd
  968.         stosd
  969.         stosd
  970.         stosd
  971.         stosw           ; .slot_state
  972.         scasw
  973.         stosd
  974.         stosd
  975.         stosd
  976.         stosd
  977.         stosb
  978.         jmp     got_process_info
  979.  
  980. i40_get_process_info:
  981.         cmp     ecx, -1
  982.         jnz     @f
  983.         mov     ecx, [ebp+tls.cur_slot]
  984.         inc     ecx
  985. @@:
  986.         add     ebx, [base]
  987.         mov     edx, [shared_data]
  988. ;       cmp     ecx, [edx+shared_data_struc.alloc_threads]      ; too many programs will fail
  989.         cmp     ecx, 256
  990.         ja      invalid_slot
  991.         dec     ecx
  992.         call    acquire_shared
  993.         mov     eax, ecx
  994.         call    get_slot_ptr
  995.         mov     esi, edi
  996.         mov     edi, ebx
  997.         jecxz   get_os_process_info
  998.         xor     eax, eax
  999.         stosd           ; .cpu_usage
  1000.         mov     eax, [edx+shared_data_struc.alloc_threads]
  1001.         stosw           ; .window_stack_position
  1002.         stosw           ; .window_stack_value
  1003.         xor     eax, eax
  1004.         stosw           ; .not_used1
  1005.         push    esi
  1006.         add     esi, 28
  1007.         movsd
  1008.         movsd
  1009.         movsd
  1010.         pop     esi
  1011.         stosd           ; .memory_start
  1012.         mov     eax, [esi+24]
  1013.         stosd           ; .used_memory
  1014.         mov     eax, [esi]
  1015.         stosd           ; .PID
  1016.         push    ecx
  1017.         xor     eax, eax
  1018.         push    eax
  1019.         push    eax
  1020.         push    eax
  1021.         push    eax
  1022.         push    esp
  1023.         push    dword [esi+20]
  1024.         call    [GetWindowRect]
  1025.         pop     eax
  1026.         stosd
  1027.         pop     eax
  1028.         stosd
  1029.         pop     eax
  1030.         sub     eax, [edi-8]
  1031.         sub     eax, 1
  1032.         adc     eax, 0
  1033.         stosd
  1034.         pop     eax
  1035.         sub     eax, [edi-8]
  1036.         sub     eax, 1
  1037.         adc     eax, 0
  1038.         stosd
  1039.         pop     ecx
  1040.         and     word [edi], 0   ; .slot_state
  1041.         cmp     dword [esi], 0
  1042.         jnz     @f
  1043.         mov     byte [edi], 9
  1044. @@:
  1045.         scasd
  1046. ; client area coordinates
  1047.         push    esi
  1048. ; for my window, return true coordinates from tls
  1049.         cmp     ecx, [ebp+tls.cur_slot]
  1050.         jnz     .notmy
  1051.         lea     esi, [ebp+tls.client_left]
  1052.         movsd
  1053.         movsd
  1054.         lodsd
  1055.         dec     eax
  1056.         stosd
  1057.         lodsd
  1058.         dec     eax
  1059.         stosd
  1060.         jmp     @f
  1061. .notmy:
  1062. ; for other windows, return copy of window coordinates
  1063.         add     esi, 0x22
  1064.         movsd
  1065.         movsd
  1066.         movsd
  1067.         movsd
  1068. @@:
  1069.         pop     esi
  1070. ; window state
  1071.         sub     esp, 40
  1072.         push    44
  1073.         push    esp
  1074.         push    dword [esi+20]
  1075.         call    [GetWindowPlacement]
  1076.         test    eax, eax
  1077.         jnz     @f
  1078.         add     esp, 44
  1079.         jmp     .normal
  1080. @@:
  1081.         mov     eax, [esp+8]    ; showCmd
  1082.         add     esp, 44
  1083.         cmp     eax, 3
  1084.         jz      .maximized
  1085.         cmp     eax, 2
  1086.         jz      .minimized
  1087.         test    eax, eax
  1088.         jz      .minimized
  1089.         push    dword [esi+20]
  1090.         call    [IsWindowVisible]
  1091.         test    eax, eax
  1092.         jz      .minimized
  1093. .normal:
  1094.         xor     eax, eax
  1095.         jmp     @f
  1096. .minimized:
  1097.         mov     al, 2
  1098.         jmp     @f
  1099. .maximized:
  1100.         mov     al, 1
  1101. @@:
  1102.         stosb
  1103. got_process_info:
  1104.         mov     eax, [shared_data]
  1105.         mov     eax, [eax+shared_data_struc.alloc_threads]
  1106.         mov     dword [esp+20h], eax    ; number of processes
  1107.         call    release_shared
  1108.         ret
  1109.  
  1110. test_button_mouse:
  1111.         cmp     al, 86h
  1112.         jnz     @f
  1113.         mov     al, 6
  1114.         test    [ebp+tls.message_mask], 4
  1115.         jz      @f
  1116.         mov     [ebp+tls.translated_msg_code], al       ; mouse
  1117.         mov     al, 3   ; button
  1118. @@:     ret
  1119.  
  1120. event_test_redraw:
  1121. ; if function 0 has not been called, then redraw message is present
  1122. ;        cmp     [ebp+tls.showwnd], 0
  1123. ;        jnz     @f
  1124.         cmp     [ebp+tls.curdraw], 0
  1125.         jz      @f
  1126.         test    [ebp+tls.message_mask], 1
  1127.         jz      @f
  1128.         pop     eax
  1129.         mov     dword [esp+20h], 1
  1130. @@:
  1131.         ret
  1132.  
  1133. i40_wait_event:
  1134.         call    event_test_redraw
  1135.         sub     esp, 20h
  1136.         xor     eax, eax
  1137.         xchg    al, [ebp+tls.translated_msg_code]
  1138.         test    eax, eax
  1139.         jnz     @f
  1140.         mov     al, 2
  1141.         test    byte [ebp+tls.message_mask], al
  1142.         jz      .nokey
  1143.         cmp     [ebp+tls.keybuflen], ah
  1144.         jnz     @f
  1145. .nokey:
  1146.         inc     eax
  1147.         test    [ebp+tls.message_mask], 4
  1148.         jz      .nobut
  1149.         cmp     [ebp+tls.butbuflen], ah
  1150.         jnz     @f
  1151. .nobut:
  1152.         mov     ebx, esp
  1153.         push    0
  1154.         push    0
  1155.         push    0
  1156.         push    ebx
  1157.         call    [GetMessageA]
  1158.         test    eax, eax
  1159.         jz      i40_terminate
  1160.         push    ebx
  1161.         call    [TranslateMessage]
  1162.         push    ebx
  1163.         call    [DispatchMessageA]
  1164.         add     esp, 20h
  1165.         jmp     i40_wait_event
  1166. @@:
  1167.         add     esp, 20h
  1168.         cmp     al, 6
  1169.         jnz     @f
  1170.         test    [ebp+tls.message_mask], 20h
  1171.         jz      i40_wait_event
  1172. @@:
  1173.         call    test_button_mouse
  1174.         mov     [esp+20h], eax
  1175.         ret
  1176.  
  1177. i40_check_event:
  1178.         call    event_test_redraw
  1179.         sub     esp, 20h
  1180.         xor     eax, eax
  1181.         xchg    al, [ebp+tls.translated_msg_code]
  1182.         or      eax, eax
  1183.         jnz     .event
  1184.         mov     al, 2
  1185.         test    byte [ebp+tls.message_mask], al
  1186.         jz      .nokey
  1187.         cmp     [ebp+tls.keybuflen], ah
  1188.         jnz     .event
  1189. .nokey:
  1190.         inc     eax
  1191.         test    [ebp+tls.message_mask], 4
  1192.         jz      .nobut
  1193.         cmp     [ebp+tls.butbuflen], ah
  1194.         jnz     .event
  1195. .nobut:
  1196. @@:
  1197.         mov     ebx, esp
  1198.         push    1
  1199.         push    0
  1200.         push    0
  1201.         push    0
  1202.         push    ebx
  1203.         call    [PeekMessageA]
  1204.         test    eax, eax
  1205.         jz      .noevent
  1206.         cmp     dword [ebx+4], 0x12     ; WM_QUIT
  1207.         jz      i40_terminate
  1208.         push    ebx
  1209.         call    [TranslateMessage]
  1210.         push    ebx
  1211.         call    [DispatchMessageA]
  1212.         xor     eax, eax
  1213.         cmp     [ebp+tls.curdraw], al
  1214.         jnz     .redraw
  1215.         xchg    al, [ebp+tls.translated_msg_code]
  1216.         or      eax, eax
  1217.         jz      @b
  1218. .event:
  1219.         add     esp, 20h
  1220.         cmp     al, 6
  1221.         jnz     @f
  1222.         test    [ebp+tls.message_mask], 20h
  1223.         jz      i40_check_event
  1224. @@:
  1225.         call    test_button_mouse
  1226.         mov     [esp+20h], eax
  1227.         ret
  1228. .redraw:
  1229.         inc     eax
  1230.         add     esp, 20h
  1231.         test    [ebp+tls.message_mask], eax
  1232.         jz      i40_check_event
  1233.         mov     [esp+20h], eax
  1234.         ret
  1235. .noevent:
  1236.         add     esp, 20h
  1237.         and     dword [esp+20h], 0
  1238.         ret
  1239.  
  1240. i40_redraw_status:
  1241.         dec     ebx
  1242.         jz      .fn1
  1243.         dec     ebx
  1244.         jnz     not_supported_i40_fn
  1245.         ret
  1246. .fn1:
  1247. ; delete all defined buttons
  1248.         xor     ebx, ebx
  1249.         mov     [ebp+tls.active_button], ebx    ; no more active buttons
  1250.         xchg    ebx, [ebp+tls.buttons]
  1251. @@:
  1252.         test    ebx, ebx
  1253.         jz      .done
  1254.         push    ebx
  1255.         mov     ebx, [ebx]
  1256.         call    free
  1257.         jmp     @b
  1258. .done:
  1259.         ret
  1260.  
  1261. i40_drawrect:
  1262.         push    ecx
  1263.         push    edx
  1264.         push    [ebp+tls.hWnd]
  1265.         call    [GetDC]
  1266.         pop     edx
  1267.         pop     ecx
  1268.         xchg    eax, edi
  1269.         push    1
  1270.         push    edx
  1271.         movzx   eax, cx
  1272.         shr     ecx, 16
  1273.         add     ecx, [ebp+tls.client_top]
  1274.         add     eax, ecx
  1275.         push    eax
  1276.         movzx   eax, bx
  1277.         shr     ebx, 16
  1278.         add     ebx, [ebp+tls.client_left]
  1279.         add     eax, ebx
  1280.         push    eax
  1281.         push    ecx
  1282.         push    ebx
  1283.         call    rectangle_gradient
  1284.         push    edi
  1285.         push    [ebp+tls.hWnd]
  1286.         call    [ReleaseDC]
  1287.         ret
  1288.  
  1289. get_screen_size:
  1290.         call    [GetDesktopWindow]
  1291.         push    eax
  1292.         push    eax
  1293.         call    [GetDC]
  1294.         xchg    eax, esi
  1295.         push    8       ; HORZRES
  1296.         push    esi
  1297.         call    [GetDeviceCaps]
  1298.         dec     eax
  1299.         xchg    ebx, eax
  1300.         shl     ebx, 16
  1301.         push    10      ; VERTRES
  1302.         push    esi
  1303.         call    [GetDeviceCaps]
  1304.         dec     eax
  1305.         or      ebx, eax
  1306.         pop     eax
  1307.         push    esi
  1308.         push    eax
  1309.         call    [ReleaseDC]
  1310.         ret
  1311.  
  1312. i40_get_screen_size:
  1313.         call    get_screen_size
  1314.         mov     [esp+20h], ebx
  1315.         ret
  1316.  
  1317. i40_set_background:
  1318.         pushad
  1319.         push    1
  1320.         call    init_background
  1321.         popad
  1322.         mov     eax, [bgr_section]
  1323.         test    eax, eax
  1324.         jnz     @f
  1325.         ret
  1326. @@:
  1327.         dec     ebx
  1328.         jz      .setsize
  1329.         dec     ebx
  1330.         jz      .setpixel
  1331.         dec     ebx
  1332.         jz      .redraw
  1333.         dec     ebx
  1334.         jz      .method
  1335.         dec     ebx
  1336.         jz      .setblock
  1337.         dec     ebx
  1338.         jz      .map
  1339.         dec     ebx
  1340.         jnz     not_supported_i40_fn
  1341. .unmap:
  1342.         push    ecx
  1343.         mov     esi, ecx
  1344.         add     esi, [base]
  1345.         lea     edi, [eax+10h]
  1346.         mov     ecx, [eax]
  1347.         imul    ecx, [eax+4]
  1348.         lea     ecx, [ecx*3]
  1349.         mov     edx, ecx
  1350.         shr     ecx, 2
  1351.         rep     movsd
  1352.         mov     ecx, edx
  1353.         and     ecx, 3
  1354.         rep     movsb
  1355.         mov     byte [eax+12], 1
  1356.         mov     byte [eax+13], 0
  1357.         pop     ecx
  1358.         jmp     i40_sys_services.free_heap
  1359. .map:
  1360.         mov     cl, 1
  1361.         xchg    cl, [eax+13]
  1362.         test    cl, cl
  1363.         jz      @f
  1364.         push    eax ecx edx
  1365.         push    100
  1366.         call    [Sleep]
  1367.         pop     edx ecx eax
  1368.         jmp     .map
  1369. @@:
  1370.         lea     esi, [eax+10h]
  1371.         mov     ecx, [eax]
  1372.         imul    ecx, [eax+4]
  1373.         lea     ecx, [ecx*3]
  1374.         pushad
  1375.         call    i40_sys_services.allocate_heap
  1376.         popad
  1377.         mov     [esp+20h], eax
  1378.         test    eax, eax
  1379.         jnz     @f
  1380.         mov     byte [esi-10h+13], 0
  1381.         ret
  1382. @@:
  1383.         mov     edi, eax
  1384.         add     edi, [base]
  1385.         mov     edx, ecx
  1386.         shr     ecx, 2
  1387.         rep     movsd
  1388.         mov     ecx, edx
  1389.         and     ecx, 3
  1390.         rep     movsb
  1391.         ret
  1392. .setblock:
  1393.         xchg    esi, ecx
  1394.         add     esi, [base]
  1395.         lea     edi, [eax+edx+10h]
  1396.         rep     movsb
  1397.         mov     byte [eax+12], 1
  1398.         ret
  1399. .setsize:
  1400.         push    ecx
  1401. @@:
  1402.         mov     cl, 1
  1403.         xchg    cl, [eax+13]
  1404.         test    cl, cl
  1405.         jz      @f
  1406.         push    eax ecx edx
  1407.         push    100
  1408.         call    [Sleep]
  1409.         pop     edx ecx eax
  1410.         jmp     @b
  1411. @@:
  1412.         pop     ecx
  1413.         mov     [eax], ecx
  1414.         mov     [eax+4], edx
  1415.         mov     byte [eax+12], 1
  1416.         mov     byte [eax+13], 0
  1417.         ret
  1418. .method:
  1419.         mov     [eax+8], ecx
  1420.         mov     byte [eax+12], 1
  1421.         ret
  1422. .setpixel:
  1423.         and     edx, 0x00FFFFFF
  1424.         and     dword [eax+ecx+10h], 0xFF000000
  1425.         or      [eax+ecx+10h], edx
  1426.         mov     byte [eax+12], 1
  1427. @@:     ret
  1428. .redraw:
  1429.         cmp     byte [eax+12], 0
  1430.         jz      @b
  1431. .redraw_force:
  1432.         mov     byte [eax+12], 0
  1433.         mov     ebx, 2
  1434.         mov     eax, [shared_data]
  1435.         cmp     [eax+shared_data_struc.vk], 0
  1436.         jnz     .settmp
  1437.         mov     eax, [SetBgrQuestion]
  1438.         dec     eax
  1439.         js      .ask
  1440.         jz      .permanent
  1441.         dec     eax
  1442.         jz      .settmp
  1443. ; don't set
  1444.         ret
  1445. .ask:
  1446.         push    123h
  1447.         push    aConfirm
  1448.         push    BgrQuestionText
  1449.         push    0
  1450.         call    [MessageBoxA]
  1451.         cmp     al, 6
  1452.         jz      .permanent
  1453.         cmp     al, 7
  1454.         jz      .settmp
  1455.         ret
  1456. .permanent:
  1457.         inc     ebx
  1458. .settmp:
  1459.         push    eax
  1460.         push    esp
  1461.         push    3       ; KEY_QUERY_VALUE | KEY_SET_VALUE
  1462.         push    0
  1463.         push    bgrkeyname
  1464.         push    80000001h
  1465.         call    [RegOpenKeyExA]
  1466.         test    eax, eax
  1467.         pop     esi
  1468.         jnz     .nopos
  1469. ; save old reg values
  1470.         push    '0'
  1471.         push    '0'
  1472.         push    2
  1473.         mov     eax, esp
  1474.         push    eax     ; lpcbData
  1475.         add     eax, 4
  1476.         push    eax     ; lpData
  1477.         push    0       ; lpType
  1478.         push    0       ; lpReserved
  1479.         push    bgrstylevalue   ; lpValueName
  1480.         push    esi     ; hKey
  1481.         call    [RegQueryValueExA]
  1482.         mov     eax, esp
  1483.         mov     dword [eax], 2
  1484.         push    eax     ; lpcbData
  1485.         add     eax, 8
  1486.         push    eax     ; lpData
  1487.         push    0       ; lpType
  1488.         push    0       ; lpReserved
  1489.         push    bgrtilevalue    ; lpValueName
  1490.         push    esi     ; hKey
  1491.         call    [RegQueryValueExA]
  1492.         pop     eax
  1493.         mov     ecx, '0'
  1494.         mov     eax, [bgr_section]
  1495.         cmp     byte [eax+8], 1
  1496.         jz      @f
  1497.         mov     cl, '2'
  1498. @@:
  1499.         push    ecx
  1500.         mov     eax, esp
  1501.         push    2
  1502.         push    eax
  1503.         push    1
  1504.         push    0
  1505.         push    bgrstylevalue
  1506.         push    esi
  1507.         call    [RegSetValueExA]
  1508.         pop     ecx
  1509.         cmp     cl, '0'
  1510.         jnz     .stretch
  1511.         push    '1'     ; tile
  1512.         jmp     @f
  1513. .stretch:
  1514.         push    '0'
  1515. @@:
  1516.         mov     eax, esp
  1517.         push    2
  1518.         push    eax
  1519.         push    1
  1520.         push    0
  1521.         push    bgrtilevalue
  1522.         push    esi
  1523.         call    [RegSetValueExA]
  1524.         pop     ecx
  1525.         push    esi
  1526.         call    [RegCloseKey]
  1527. .nopos:
  1528.         mov     edi, win32_path
  1529.         push    startcurdir
  1530.         push    edi
  1531.         call    [lstrcpyA]
  1532.         push    bgrfilename
  1533.         test    bl, 1
  1534.         jnz     @f
  1535.         mov     dword [esp], bgrtempfilename
  1536. @@:
  1537.         push    edi
  1538.         call    [lstrcatA]
  1539.         push    0
  1540.         push    80h
  1541.         push    2
  1542.         push    0
  1543.         push    0
  1544.         push    40000000h
  1545.         push    edi
  1546.         call    [CreateFileA]
  1547.         inc     eax
  1548.         jnz     @f
  1549.         push    10h
  1550.         push    0
  1551.         push    BgrFileErrorMsg
  1552.         push    0
  1553.         call    [MessageBoxA]
  1554.         pop     ecx
  1555.         pop     ecx
  1556.         ret
  1557. @@:
  1558.         dec     eax
  1559.         xchg    eax, esi
  1560. ; bmp header
  1561.         mov     ecx, [bgr_section]
  1562.         mov     eax, [ecx+4]
  1563.         mov     [bgr_bmp_header+16h], eax
  1564.         mov     eax, [ecx]
  1565.         mov     [bgr_bmp_header+12h], eax
  1566.         add     eax, eax
  1567.         add     eax, [ecx]
  1568.         add     eax, 3
  1569.         and     al, not 3
  1570.         mul     dword [ecx+4]
  1571. ; eax=size of image
  1572.         mov     [bgr_bmp_header+22h], eax
  1573.         add     eax, 36h
  1574.         mov     [bgr_bmp_header+2], eax
  1575.         push    eax
  1576.         mov     eax, esp
  1577.         push    0
  1578.         push    eax
  1579.         push    36h
  1580.         push    bgr_bmp_header
  1581.         push    esi
  1582.         call    [WriteFile]
  1583.         pop     eax
  1584. ; bmp data
  1585.         mov     eax, [bgr_section]
  1586.         mov     ecx, [eax+4]
  1587.         lea     edi, [eax+10h]
  1588.         mov     eax, [eax]
  1589.         mul     ecx
  1590.         imul    eax, 3
  1591.         add     edi, eax
  1592. .putline:
  1593.         push    ecx
  1594.         mov     ecx, [bgr_section]
  1595.         mov     eax, [ecx]
  1596.         add     eax, eax
  1597.         add     eax, [ecx]
  1598.         sub     edi, eax
  1599.         push    eax
  1600.         push    eax
  1601.         mov     ecx, esp
  1602.         push    0
  1603.         push    ecx
  1604.         push    eax
  1605.         push    edi
  1606.         push    esi
  1607.         call    [WriteFile]
  1608.         pop     eax
  1609.         pop     ecx
  1610.         and     ecx, 3
  1611.         jz      .nopad
  1612. .padloop:
  1613.         push    ecx
  1614.         push    0
  1615.         push    eax
  1616.         mov     eax, esp
  1617.         push    0
  1618.         push    eax
  1619.         add     eax, 4
  1620.         push    1
  1621.         push    eax
  1622.         push    esi
  1623.         call    [WriteFile]
  1624.         pop     eax
  1625.         pop     eax
  1626.         pop     ecx
  1627.         loop    .padloop
  1628. .nopad:
  1629.         pop     ecx
  1630.         loop    .putline
  1631.         push    esi
  1632.         call    [CloseHandle]
  1633.         mov     eax, [shared_data]
  1634.         mov     [eax+shared_data_struc.dwNewBgrTime], -1
  1635.         ;or     [dwNewBgrTime], -1
  1636.         push    ebx
  1637.         push    win32_path
  1638.         push    0
  1639.         push    14h
  1640.         call    [SystemParametersInfoA]
  1641.         cmp     bl, 2
  1642.         jnz     @f
  1643.         push    eax
  1644.         push    esp
  1645.         push    500
  1646.         push    0
  1647.         push    0
  1648.         push    0
  1649.         push    0x1A
  1650.         push    0xFFFF
  1651.         call    [SendMessageTimeoutA]
  1652.         pop     eax
  1653. ; restore key values
  1654.         push    eax
  1655.         push    esp
  1656.         push    2       ; KEY_SET_VALUE
  1657.         push    0
  1658.         push    bgrkeyname
  1659.         push    80000001h
  1660.         call    [RegOpenKeyExA]
  1661.         test    eax, eax
  1662.         pop     esi
  1663.         jnz     @f
  1664.         mov     eax, esp
  1665.         push    2
  1666.         push    eax
  1667.         push    1
  1668.         push    0
  1669.         push    bgrstylevalue
  1670.         push    esi
  1671.         call    [RegSetValueExA]
  1672.         lea     eax, [esp+4]
  1673.         push    2
  1674.         push    eax
  1675.         push    1
  1676.         push    0
  1677.         push    bgrtilevalue
  1678.         push    esi
  1679.         call    [RegSetValueExA]
  1680.         push    esi
  1681.         call    [RegCloseKey]
  1682. @@:
  1683.         mov     esi, [shared_data]
  1684.         call    [GetTickCount]
  1685.         add     eax, 3000
  1686.         ;mov    [dwNewBgrTime], eax
  1687.         mov     [esi+shared_data_struc.dwNewBgrTime], eax
  1688.         pop     ecx
  1689.         pop     ecx
  1690.         ret
  1691.  
  1692. i40_getbutton:
  1693.         movzx   ecx, [ebp+tls.butbuflen]
  1694.         jecxz   .empty
  1695.         lea     edi, [ebp+tls.butbuffer]
  1696.         mov     eax, [edi]
  1697.         and     al, not 1
  1698.         mov     [esp+20h], eax
  1699.         lea     esi, [edi+4]
  1700.         dec     ecx
  1701.         mov     [ebp+tls.butbuflen], cl
  1702.         rep     movsd
  1703.         ret
  1704. .empty:
  1705.         mov     byte [esp+20h], 1
  1706.         ret
  1707.  
  1708. i40_sys_service:
  1709.         cmp     ebx, 1
  1710.         jz      .19
  1711.         cmp     ebx, 2
  1712.         jz      .kill
  1713.         cmp     ebx, 18
  1714.         jnz     .not2
  1715. .kill:
  1716.         call    acquire_shared
  1717.         xchg    eax, ecx
  1718.         cmp     eax, 1
  1719.         jbe     release_shared          ; invalid PID/slot - ignore
  1720.         mov     esi, [shared_data]
  1721.         mov     edi, esi
  1722.         mov     ecx, [esi]
  1723.         add     esi, shared_data_struc.threads
  1724.         cmp     ebx, 2
  1725.         jz      .slot
  1726. @@:
  1727.         cmp     [esi], eax
  1728.         jz      .found
  1729.         add     esi, 64
  1730.         loop    @b
  1731.         jmp     release_shared          ; no such PID - ignore
  1732. .slot:
  1733.         dec     eax
  1734.         cmp     eax, ecx
  1735.         jae     release_shared
  1736.         shl     eax, 6
  1737.         add     esi, eax
  1738.         cmp     dword [esi], 0
  1739.         jz      release_shared
  1740. .found:
  1741. ; terminate self?
  1742.         call    get_cur_slot_ptr
  1743.         cmp     esi, edi
  1744.         jnz     @f
  1745.         call    release_shared
  1746.         jmp     i40_terminate
  1747. @@:
  1748. ; get thread and process handles
  1749.         mov     eax, [esi+shared_data_struc.win32_hThread-shared_data_struc.threads]
  1750.         call    server_convert
  1751.         mov     edi, eax
  1752.         call    release_shared
  1753. ; target thread is suspended? if so, do not wait
  1754.         push    edi
  1755.         call    [SuspendThread]
  1756.         test    eax, eax
  1757.         jnz     .suspended
  1758.         push    edi
  1759.         call    [ResumeThread]
  1760. ; send WM_CLOSE to thread window
  1761.         push    0
  1762.         push    0
  1763.         push    0x10            ; WM_CLOSE
  1764.         push    [esi+shared_data_struc.hWnd-shared_data_struc.threads]
  1765.         call    [PostMessageA]
  1766. ; wait no more than 1 second
  1767.         push    1000
  1768.         push    edi
  1769.         call    [WaitForSingleObject]
  1770.         cmp     eax, 258        ; WAIT_TIMEOUT
  1771.         jnz     .ret_close
  1772. ; let target thread to terminate itself
  1773.         push    edi
  1774.         call    [SuspendThread]
  1775. .suspended:
  1776.         mov     ebx, [esi+shared_data_struc.win32_stack-shared_data_struc.threads]
  1777.         sub     esp, 0xB2*4
  1778.         push    1000Fh
  1779.         mov     esi, esp
  1780.         push    esp
  1781.         push    edi
  1782.         call    [GetThreadContext]
  1783.         mov     ax, ss
  1784.         cmp     [esi+0xC8], ax
  1785.         jz      @f
  1786.         mov     [esi+0xC8], ss
  1787.         mov     [esi+0xC4], ebx
  1788. @@:
  1789.         mov     [esi+0xBC], cs
  1790.         mov     [esi+0x98], ds
  1791.         mov     [esi+0x94], es
  1792.         mov     [esi+0xB8], dword i40_terminate
  1793.         push    esi
  1794.         push    edi
  1795.         call    [SetThreadContext]
  1796.         add     esp, 0xB3*4
  1797. @@:
  1798.         push    edi
  1799.         call    [ResumeThread]
  1800.         cmp     eax, 1
  1801.         ja      @b
  1802. .ret_close:
  1803.         push    edi
  1804.         call    [CloseHandle]
  1805.         ret
  1806. .not2:
  1807.         cmp     ebx, 3
  1808.         jnz     .not3
  1809.         cmp     ecx, 2
  1810.         jb      .noactivate_ret
  1811.         call    acquire_shared
  1812.         mov     eax, [shared_data]
  1813.         cmp     ecx, [eax+shared_data_struc.alloc_threads]
  1814.         ja      .noactivate_release
  1815.         lea     eax, [ecx-1]
  1816.         call    get_slot_ptr
  1817.         cmp     dword [edi], 0
  1818.         jz      .noactivate_release
  1819.         mov     esi, [edi+shared_data_struc.hWnd-shared_data_struc.threads]
  1820.         call    release_shared
  1821. .restore_given_window:
  1822.         sub     esp, 40
  1823.         push    44
  1824.         push    esp
  1825.         push    esi
  1826.         call    [GetWindowPlacement]
  1827.         mov     eax, [esp+8]
  1828.         add     esp, 44
  1829.         mov     ecx, 5  ; SW_SHOW
  1830.         cmp     al, 2   ; SW_SHOWMINIMIZED
  1831.         jnz     @f
  1832.         mov     cl, 9   ; SW_RESTORE
  1833. @@:
  1834.         push    ecx
  1835.         push    esi
  1836.         call    [ShowWindow]
  1837. ;       push    esi
  1838. ;       call    [BringWindowToTop]
  1839.         push    esi
  1840.         call    [SetForegroundWindow]
  1841.         ret
  1842. .noactivate_release:
  1843.         call    release_shared
  1844. .noactivate_ret:
  1845.         ret
  1846. .not3:
  1847.         cmp     ebx, 4
  1848.         jnz     .not4
  1849. ; get idle time - current implementation on NT simply returns cpuspeed
  1850.         cmp     [bIs9x], 0
  1851.         jz      .5
  1852. idletime_via_ring0 = 1
  1853. if ~idletime_via_ring0
  1854.         mov     eax, [shared_data]
  1855.         cmp     [eax+shared_data_struc.b9xPerfInited], 0
  1856.         jnz     .perfinited
  1857.         call    acquire_shared
  1858.         cmp     [eax+shared_data_struc.b9xPerfInited], 0
  1859.         jnz     @f
  1860.         push    eax
  1861.         push    esp     ; phkResult
  1862.         push    1       ; samDesired = KEY_QUERY_VALUE
  1863.         push    0       ; ulOptions
  1864.         push    perfstart       ; lpSubKey
  1865.         push    80000006h       ; hKey = HKEY_DYN_DATA
  1866.         call    [RegOpenKeyExA]
  1867.         pop     esi
  1868.         test    eax, eax
  1869.         jnz     .perfinitfail
  1870.         push    eax
  1871.         mov     eax, esp
  1872.         push    4
  1873.         push    esp     ; lpcbData
  1874.         push    eax     ; lpData
  1875.         push    0       ; lpType
  1876.         push    0       ; lpReserved
  1877.         push    perfval ; lpValueName
  1878.         push    esi     ; hKey
  1879.         call    [RegQueryValueExA]
  1880.         pop     ecx
  1881.         pop     ecx
  1882.         push    eax
  1883.         push    esi
  1884.         call    [RegCloseKey]
  1885.         pop     eax
  1886.         test    eax, eax
  1887.         jnz     .perfinitfail
  1888.         push    200
  1889.         call    [Sleep]         ; give chance to collect data
  1890. @@:
  1891.         mov     eax, [shared_data]
  1892.         mov     [eax+shared_data_struc.b9xPerfInited], 1
  1893.         call    release_shared
  1894. .perfinited:
  1895.         push    100
  1896.         pop     ebx
  1897.         push    eax
  1898.         push    esp     ; phkResult
  1899.         push    1       ; samDesired = KEY_QUERY_VALUE
  1900.         push    0       ; ulOptions
  1901.         push    perfget ; lpSubKey
  1902.         push    80000006h       ; hKey = HKEY_DYN_DATA
  1903.         call    [RegOpenKeyExA]
  1904.         pop     esi
  1905.         test    eax, eax
  1906.         jnz     @f
  1907.         push    ebx
  1908.         mov     eax, esp
  1909.         push    4
  1910.         push    esp     ; lpcbData
  1911.         push    eax     ; lpData
  1912.         push    0       ; lpType
  1913.         push    0       ; lpReserved
  1914.         push    perfval ; lpValueName
  1915.         push    esi     ; hKey
  1916.         call    [RegQueryValueExA]
  1917.         pop     ecx
  1918.         pop     ebx
  1919.         push    esi
  1920.         call    [RegCloseKey]
  1921. @@:
  1922.         pushad
  1923.         call    .5
  1924.         popad
  1925.         push    100
  1926.         pop     ecx
  1927.         sub     ebx, ecx
  1928.         neg     ebx
  1929.         mul     ebx
  1930.         div     ecx
  1931.         mov     [esp+20h], eax
  1932.         ret
  1933. .perfinitfail:
  1934.         call    release_shared
  1935.         push    40h
  1936.         push    0
  1937.         push    aPerfInitFailed
  1938.         push    0
  1939.         call    [MessageBoxA]
  1940.         jmp     .5
  1941. else
  1942.         mov     eax, [shared_data]
  1943.         cmp     [eax+shared_data_struc.b9xPerfInited], 0
  1944.         jnz     @f
  1945. .idlecount_init:
  1946.         div     edx
  1947. @@:
  1948.         mov     ebx, [eax+shared_data_struc.idlecount]
  1949.         pushad
  1950.         call    .5
  1951.         popad
  1952.         mul     ebx
  1953.         mov     ecx, 1000
  1954.         div     ecx
  1955.         mov     [esp+20h], eax
  1956.         ret
  1957. end if
  1958. .not4:
  1959.         cmp     ebx, 5
  1960.         jnz     .not5
  1961. .5:
  1962.         mov     eax, [shared_data]
  1963.         mov     ebx, [eax+shared_data_struc.cpuspeed]
  1964.         test    ebx, ebx
  1965.         jnz     @f
  1966. ; determine cpu speed
  1967. ; 1) check for value in registry
  1968.         push    eax
  1969.         push    esp
  1970.         push    1       ; KEY_QUERY_VALUE
  1971.         push    0
  1972.         push    keycpu
  1973.         push    80000002h
  1974.         call    [RegOpenKeyExA]
  1975.         test    eax, eax
  1976.         pop     eax
  1977.         jnz     .nokey
  1978.         xchg    eax, esi
  1979.         push    eax
  1980.         push    4
  1981.         push    esp
  1982.         lea     eax, [esp+8]
  1983.         push    eax
  1984.         push    0
  1985.         push    0
  1986.         push    keymhz
  1987.         push    esi
  1988.         call    [RegQueryValueExA]
  1989.         push    eax
  1990.         push    esi
  1991.         call    [RegCloseKey]
  1992.         pop     eax
  1993.         test    eax, eax
  1994.         pop     eax
  1995.         pop     eax
  1996.         jnz     .nokey
  1997.         imul    eax, 1000000
  1998.         jmp     .speed_found
  1999. .nokey:
  2000. ; 2) sleep for 1/4 sec and read TSC
  2001.         rdtsc
  2002.         push    eax edx
  2003.         push    250
  2004.         call    [Sleep]
  2005.         rdtsc
  2006.         pop     ecx ebx
  2007.         sub     eax, ebx
  2008.         sbb     edx, ecx
  2009.         shl     eax, 2
  2010. .speed_found:
  2011.         xchg    ebx, eax
  2012.         mov     eax, [shared_data]
  2013.         mov     [eax+shared_data_struc.cpuspeed], ebx
  2014. @@:
  2015.         mov     [esp+20h], ebx
  2016.         ret
  2017. .not5:
  2018.         cmp     ebx, 7
  2019.         jnz     .not7
  2020.         mov     eax, [shared_data]
  2021.         mov     eax, [eax+shared_data_struc.active_process]
  2022.         mov     [esp+20h], eax
  2023.         ret
  2024. .not7:
  2025.         cmp     ebx, 8
  2026.         jnz     .not8
  2027.         dec     ecx
  2028.         jnz     @f
  2029.         mov     eax, [shared_data]
  2030.         movzx   eax, [eax+shared_data_struc.sound_flag]
  2031.         mov     [esp+20h], eax
  2032.         ret
  2033. @@:
  2034.         dec     ecx
  2035.         jnz     not_supported_i40_fn
  2036.         mov     eax, [shared_data]
  2037. lock    xor     [eax+shared_data_struc.sound_flag], 1
  2038.         ret
  2039. .not8:
  2040.         cmp     ebx, 9
  2041.         jnz     .not9
  2042. .19:
  2043.         mov     eax, [shared_data]
  2044.         cmp     [eax+shared_data_struc.vk], 0
  2045.         jz      not_supported_i40_fn
  2046. .server_terminate:
  2047.         div     edx
  2048.         ret
  2049. .not9:
  2050.         cmp     ebx, 10
  2051. ;       jnz     .not10
  2052. ;       call    minimize_window
  2053. ;       ret
  2054.         jz      minimize_window
  2055. .not10:
  2056.         cmp     ebx, 11
  2057.         jnz     .not11
  2058.         dec     ecx
  2059.         jnz     not_supported_i40_fn
  2060.         xor     eax, eax
  2061.         mov     edi, edx
  2062.         add     edi, [base]
  2063. ; floppy is not supported yet => return "no floppy installed"
  2064.         stosb
  2065. ; IDEx configuration
  2066. ; CD is not supported yet. On IDEx there may be only HD (or nothing)
  2067.         xor     edx, edx
  2068.         mov     esi, hd_partitions_num
  2069.         push    esi
  2070. .idex:
  2071.         lodsd
  2072.         shl     edx, 2
  2073.         test    eax, eax
  2074.         jz      @f
  2075.         inc     edx
  2076. @@:
  2077.         cmp     esi, hd_partitions_num+4*4
  2078.         jc      .idex
  2079.         mov     [edi], dl
  2080.         inc     edi
  2081. ; number of partitions
  2082.         pop     esi
  2083.         mov     cl, 4
  2084. @@:
  2085.         lodsd
  2086.         stosb
  2087.         loop    @b
  2088. ; reserved bytes
  2089.         and     dword [edi], 0
  2090.         ret
  2091. .not11:
  2092.         cmp     ebx, 12
  2093.         jnz     .not12
  2094. .return0:
  2095.         and     dword [esp+20h], 0
  2096.         ret
  2097. .not12:
  2098.         cmp     ebx, 13
  2099.         jnz     .not13
  2100.         mov     edi, ecx
  2101.         add     edi, [base]
  2102.         mov     esi, version_inf
  2103.         mov     ecx, version_end - version_inf
  2104.         rep     movsb
  2105.         ret
  2106. .not13:
  2107.         cmp     ebx, 14
  2108.         jz      .return0
  2109.         cmp     ebx, 15
  2110.         jnz     .not15
  2111.         call    get_screen_size
  2112.         movzx   eax, bx
  2113.         inc     eax
  2114.         shr     eax, 1
  2115.         push    eax
  2116.         shr     ebx, 16
  2117.         inc     ebx
  2118.         shr     ebx, 1
  2119.         push    ebx
  2120.         call    [SetCursorPos]
  2121.         ret
  2122. .not15:
  2123.         cmp     ebx, 16
  2124.         jnz     .not16
  2125.         sub     esp, 20h
  2126.         push    esp
  2127.         call    [GlobalMemoryStatus]
  2128.         mov     eax, [esp+12]
  2129.         add     esp, 20h
  2130.         shr     eax, 10
  2131.         mov     [esp+20h], eax
  2132.         ret
  2133. .not16:
  2134.         cmp     ebx, 17
  2135.         jnz     .not17
  2136.         sub     esp, 20h
  2137.         push    esp
  2138.         call    [GlobalMemoryStatus]
  2139.         mov     eax, [esp+8]
  2140.         add     esp, 20h
  2141.         shr     eax, 10
  2142.         mov     [esp+20h], eax
  2143.         ret
  2144. .not17:
  2145.         cmp     ebx, 19
  2146.         jnz     .not19
  2147.         jecxz   .19_0
  2148.         dec     ecx
  2149.         jz      .19_1
  2150.         dec     ecx
  2151.         jz      .19_2
  2152.         dec     ecx
  2153.         jz      .19_3
  2154.         dec     ecx
  2155.         jnz     not_supported_i40_fn
  2156.         movzx   eax, dx
  2157.         push    eax
  2158.         shr     edx, 16
  2159.         push    edx
  2160.         call    [SetCursorPos]
  2161.         ret
  2162. .19_0:
  2163.         mov     eax, [shared_data]
  2164.         movzx   eax, [eax+shared_data_struc.mouse_speed_factor]
  2165.         mov     [esp+20h], eax
  2166.         ret
  2167. .19_1:
  2168.         mov     eax, [shared_data]
  2169.         mov     [eax+shared_data_struc.mouse_speed_factor], dx
  2170.         ret
  2171. .19_2:
  2172.         mov     eax, [shared_data]
  2173.         mov     eax, [eax+shared_data_struc.mouse_delay]
  2174.         mov     [esp+20h], eax
  2175.         ret
  2176. .19_3:
  2177.         mov     eax, [shared_data]
  2178.         mov     [eax+shared_data_struc.mouse_delay], edx
  2179.         ret
  2180. .not19:
  2181.         cmp     ebx, 21
  2182.         jnz     .not21
  2183.         xchg    eax, ecx
  2184.         call    get_slot_num
  2185.         mov     [esp+20h], edx
  2186.         ret
  2187. .not21:
  2188.         cmp     ebx, 22
  2189.         jnz     not_supported_i40_fn
  2190.         cmp     ecx, 4
  2191.         jae     not_supported_i40_fn
  2192.         shr     ecx, 1
  2193.         jnc     @f
  2194.         xchg    eax, edx
  2195.         call    get_slot_num
  2196. @@:
  2197.         dec     edx
  2198.         jz      .22err
  2199.         mov     esi, [shared_data]
  2200.         cmp     edx, [esi]
  2201.         jae     .22err
  2202.         shl     edx, 6
  2203.         mov     esi, [esi+edx+shared_data_struc.hWnd]
  2204.         and     dword [esp+20h], 0
  2205.         dec     ecx
  2206.         js      minimize_given_window
  2207.         jmp     .restore_given_window
  2208. .22err:
  2209.         or      dword [esp+20h], -1
  2210.         ret
  2211.  
  2212. get_slot_num:
  2213.         push    ecx
  2214.         mov     esi, [shared_data]
  2215.         mov     ecx, [esi]
  2216.         add     esi, shared_data_struc.threads
  2217.         xor     edx, edx
  2218. @@:
  2219.         inc     edx
  2220.         cmp     [esi], eax
  2221.         jz      @f
  2222.         add     esi, 64
  2223.         loop    @b
  2224.         xor     edx, edx
  2225. @@:
  2226.         pop     ecx
  2227.         ret
  2228.  
  2229. minimize_window:
  2230.         mov     esi, [ebp+tls.hWnd]
  2231. minimize_given_window:
  2232.         mov     [ebp+tls.butbuflen], 0
  2233.         xor     eax, eax        ; SW_HIDE
  2234.         mov     ecx, [shared_data]
  2235.         cmp     [ecx+shared_data_struc.vk], 0
  2236.         jnz     @f
  2237.         mov     al, 6           ; SW_MINIMIZE
  2238. @@:
  2239.         push    eax
  2240.         push    esi
  2241.         call    [ShowWindow]
  2242.         ret
  2243.  
  2244. server_convert:
  2245.         div     edx
  2246.         ret
  2247.  
  2248. i40_sys_setup:
  2249.         mov     eax, [shared_data]
  2250.         and     dword [esp+20h], 0
  2251.         dec     ebx
  2252.         jnz     .nomidi
  2253.         cmp     ecx, 100h
  2254.         jb      .nomidi
  2255.         cmp     ecx, 0xFFFF
  2256.         ja      .nomidi
  2257.         mov     [eax+shared_data_struc.midi_base], cx
  2258.         ret
  2259. .nomidi:
  2260.         dec     ebx
  2261.         jnz     .not2
  2262.         mov     edi, keymap
  2263.         dec     ecx
  2264.         jz      .settable
  2265.         mov     edi, keymap_shift
  2266.         dec     ecx
  2267.         jz      .settable
  2268.         mov     edi, keymap_alt
  2269.         dec     ecx
  2270.         jnz     .nosettable
  2271. .settable:
  2272.         add     edx, [base]
  2273.         mov     esi, edx
  2274.         mov     ecx, 80h/4
  2275.         rep     movsd
  2276.         ret
  2277. .nosettable:
  2278.         cmp     ecx, 9-3
  2279.         jnz     .nosetkeyboard
  2280.         mov     [eax+shared_data_struc.keyboard], dx
  2281.         ret
  2282. .nosetkeyboard:
  2283.         inc     dword [esp+20h]
  2284.         ret
  2285. .not2:
  2286.         dec     ebx
  2287.         jnz     .not3
  2288.         mov     [eax+shared_data_struc.cd_base], cl
  2289.         ret
  2290. .not3:
  2291.         dec     ebx
  2292.         jnz     .not4
  2293.         cmp     ecx, 0x100
  2294.         jb      .not4
  2295.         cmp     ecx, 0xFFFF
  2296.         ja      .not4
  2297.         mov     word [eax+shared_data_struc.sb16], cx
  2298.         ret
  2299. .not4:
  2300.         dec     ebx
  2301.         jnz     .not5
  2302.         mov     [eax+shared_data_struc.syslang], ecx
  2303.         ret
  2304. .not5:
  2305.         dec     ebx
  2306.         jnz     .not6
  2307.         cmp     ecx, 0x100
  2308.         jb      .not6
  2309.         mov     [eax+shared_data_struc.wss], ecx
  2310.         ret
  2311. .not6:
  2312.         dec     ebx
  2313.         jnz     .not7
  2314.         mov     [eax+shared_data_struc.hd_base], cl
  2315.         ret
  2316. .not7:
  2317.         dec     ebx
  2318.         jnz     .not8
  2319.         mov     [eax+shared_data_struc.fat32part], ecx
  2320.         ret
  2321. .not8:
  2322.         dec     ebx
  2323.         dec     ebx
  2324.         jnz     .not10
  2325.         mov     [eax+shared_data_struc.sound_dma], ecx
  2326.         ret
  2327. .not10:
  2328.         dec     ebx
  2329.         jnz     .not11
  2330.         and     ecx, 1
  2331.         mov     [eax+shared_data_struc.lba_read_enabled], ecx
  2332.         ret
  2333. .not11:
  2334.         dec     ebx
  2335.         jnz     .not12
  2336.         and     ecx, 1
  2337.         jz      .okcheck11
  2338.         cmp     [eax+shared_data_struc.bAllowReadPCI], 0
  2339.         jnz     .okcheck11
  2340. ; be silent, because in loading process (of VirtualKolibri) SETUP will try this anyway
  2341. ;       push    40h
  2342. ;       push    0
  2343. ;       push    aPciDisabled
  2344. ;       push    0
  2345. ;       call    [MessageBoxA]
  2346.         ret
  2347. .okcheck11:
  2348.         mov     [eax+shared_data_struc.pci_access_enabled], ecx
  2349.         ret
  2350. .not12:
  2351.         mov     byte [esp+20h], 21      ; restore eax
  2352.         jmp     not_supported_i40_fn
  2353.  
  2354. i40_wait_event_timeout:
  2355. ;        call    event_test_redraw
  2356. ;       imul    ebx, ebx, 10
  2357.         sub     esp, 20h
  2358.         mov     esi, esp
  2359.         jmp     .M
  2360. .L:
  2361.         push    2
  2362.         pop     eax
  2363.         test    byte [ebp+tls.message_mask], al
  2364.         jz      .nokey
  2365.         cmp     [ebp+tls.keybuflen], ah
  2366.         jnz     .event
  2367. .nokey:
  2368.         inc     eax
  2369.         test    [ebp+tls.message_mask], 4
  2370.         jz      .nobut
  2371.         cmp     [ebp+tls.butbuflen], ah
  2372.         jnz     .event
  2373. .nobut:
  2374.         push    1       ; PM_REMOVE
  2375.         push    0
  2376.         push    0
  2377.         push    0
  2378.         push    esi
  2379.         call    [PeekMessageA]
  2380.         test    eax, eax
  2381.         jz      .notfound
  2382.         cmp     dword [esi+4], 0x12     ; WM_QUIT
  2383.         jz      i40_terminate
  2384.         push    esi
  2385.         call    [TranslateMessage]
  2386.         push    esi
  2387.         call    [DispatchMessageA]
  2388. .M:
  2389.         xor     eax, eax
  2390.         cmp     [ebp+tls.curdraw], al
  2391.         jz      @f
  2392.         test    [ebp+tls.message_mask], 1
  2393.         jz      @f
  2394.         inc     eax
  2395.         add     esp, 20h
  2396.         mov     dword [esp+20h], eax
  2397.         ret
  2398. @@:
  2399.         xchg    al, [ebp+tls.translated_msg_code]
  2400.         test    eax, eax
  2401.         jz      .L
  2402.         cmp     al, 6
  2403.         jnz     .event
  2404.         test    [ebp+tls.message_mask], 20h
  2405.         jz      .L
  2406. .event:
  2407.         add     esp, 20h
  2408.         call    test_button_mouse
  2409.         mov     [esp+20h], eax
  2410.         ret
  2411. .notfound:
  2412.         push    10
  2413.         call    [Sleep]
  2414.         dec     ebx
  2415.         jnz     .L
  2416. .timeout:
  2417.         add     esp, 20h
  2418.         and     dword [esp+20h], 0
  2419.         ret
  2420.  
  2421. i40_getsetup:
  2422.         mov     eax, [shared_data]
  2423.         dec     ebx
  2424.         jnz     .not_midi_base
  2425.         movzx   eax, [eax+shared_data_struc.midi_base]
  2426.         mov     [esp+20h], eax
  2427.         ret
  2428. .not_midi_base:
  2429.         dec     ebx
  2430.         jnz     .not_keyboard
  2431.         mov     esi, keymap
  2432.         dec     ecx
  2433.         jz      .getmap
  2434.         mov     esi, keymap_shift
  2435.         dec     ecx
  2436.         jz      .getmap
  2437.         mov     esi, keymap_alt
  2438.         dec     ecx
  2439.         jnz     .nobase
  2440. .getmap:
  2441.         mov     ecx, 128/4
  2442.         mov     edi, edx
  2443.         add     edi, [base]
  2444.         rep     movsd
  2445.         ret
  2446. .nobase:
  2447.         cmp     ecx, 9-3
  2448.         jnz     not_supported_i40_fn
  2449.         movzx   eax, [eax+shared_data_struc.keyboard]
  2450.         mov     [esp+20h], eax
  2451.         ret
  2452. .not_keyboard:
  2453.         dec     ebx
  2454.         jnz     .not_cd_base
  2455.         movzx   eax, [eax+shared_data_struc.cd_base]
  2456.         mov     [esp+20h], eax
  2457.         ret
  2458. .not_cd_base:
  2459.         dec     ebx
  2460.         jnz     .not_sb16
  2461.         mov     eax, [eax+shared_data_struc.sb16]
  2462.         mov     [esp+20h], eax
  2463.         ret
  2464. .not_sb16:
  2465.         dec     ebx
  2466.         jnz     .not_lang
  2467.         mov     eax, [eax+shared_data_struc.syslang]
  2468.         mov     [esp+20h], eax
  2469.         ret
  2470. .not_lang:
  2471.         dec     ebx
  2472.         jnz     .not_wss
  2473.         mov     eax, [eax+shared_data_struc.wss]
  2474.         mov     [esp+20h], eax
  2475.         ret
  2476. .not_wss:
  2477.         dec     ebx
  2478.         jnz     .not_hdbase
  2479.         movzx   eax, [eax+shared_data_struc.hd_base]
  2480.         mov     [esp+20h], eax
  2481.         ret
  2482. .not_hdbase:
  2483.         dec     ebx
  2484.         jnz     .not_fat32part
  2485.         mov     eax, [eax+shared_data_struc.fat32part]
  2486.         mov     [esp+20h], eax
  2487.         ret
  2488. .not_fat32part:
  2489.         dec     ebx
  2490.         jnz     .not_timer_ticks
  2491.         call    [GetTickCount]
  2492.         push    10
  2493.         pop     ecx
  2494.         xor     edx, edx
  2495.         div     ecx
  2496.         mov     [esp+20h], eax
  2497.         ret
  2498. .not_timer_ticks:
  2499.         dec     ebx
  2500.         jnz     .not_sound_dma
  2501.         mov     eax, [eax+shared_data_struc.sound_dma]
  2502.         mov     [esp+20h], eax
  2503.         ret
  2504. .not_sound_dma:
  2505.         dec     ebx
  2506.         jnz     .not_lba_enabled
  2507.         mov     eax, [eax+shared_data_struc.lba_read_enabled]
  2508.         mov     [esp+20h], eax
  2509.         ret
  2510. .not_lba_enabled:
  2511.         dec     ebx
  2512.         jnz     .not_pci_enabled
  2513.         mov     eax, [eax+shared_data_struc.pci_access_enabled]
  2514.         mov     [esp+20h], eax
  2515.         ret
  2516. .not_pci_enabled:
  2517.         mov     dword [esp+20h], 1      ; this is kernel rule, not my
  2518.         ret
  2519.  
  2520. i40_get_sys_date:
  2521.         sub     esp, 10h
  2522.         push    esp
  2523.         call    [GetLocalTime]
  2524.         movzx   eax, word [esp+6]
  2525.         aam
  2526.         shl     ax, 4
  2527.         shr     ah, 4
  2528.         shl     eax, 16-4
  2529.         mov     ax, [esp+2]
  2530.         aam
  2531.         shl     ax, 4
  2532.         shr     ah, 4
  2533.         shr     ax, 4
  2534.         mov     bl, al
  2535.         mov     ax, [esp]
  2536.         sub     ax, 2000
  2537.         aam
  2538.         shl     ax, 4
  2539.         shr     ah, 4
  2540.         shr     ax, 4
  2541.         mov     ah, bl
  2542.         add     esp, 10h
  2543.         mov     [esp+20h], eax
  2544.         ret
  2545.  
  2546. i40_current_folder:
  2547.         add     ecx, [base]
  2548.         dec     ebx
  2549.         jz      .set
  2550.         dec     ebx
  2551.         jnz     not_supported_i40_fn
  2552.         mov     edi, ecx
  2553.         mov     esi, [ebp+tls.cur_dir]
  2554.         push    edx
  2555.         push    esi
  2556.         call    [lstrlenA]
  2557.         pop     ecx
  2558.         inc     eax
  2559.         cmp     ecx, eax
  2560.         jb      @f
  2561.         mov     ecx, eax
  2562. @@:
  2563.         rep     movsb
  2564.         mov     byte [edi-1], 0
  2565.         mov     [esp+20h], eax
  2566.         ret
  2567. .set:
  2568.         mov     esi, ecx
  2569.         cmp     byte [ecx], '/'
  2570.         jnz     .relative
  2571.         push    [ebp+tls.cur_dir]
  2572.         call    free
  2573.         push    esi
  2574.         call    [lstrlenA]
  2575.         inc     eax     ; (for terminating zero)
  2576.         inc     eax     ; '/sys' -> '/rd/1' requires one additional byte
  2577.         push    eax
  2578.         push    eax
  2579.         call    malloc
  2580.         mov     [ebp+tls.cur_dir], eax
  2581.         mov     edi, eax
  2582.         pop     ecx
  2583.         mov     eax, [esi]
  2584.         or      eax, '    '
  2585.         cmp     eax, '/sys'
  2586.         jnz     @f
  2587.         mov     eax, '/rd/'
  2588.         stosd
  2589.         mov     al, '1'
  2590.         stosb
  2591.         sub     ecx, 4
  2592.         add     esi, 4
  2593. @@:
  2594.         rep     movsb
  2595.         ret
  2596. .relative:
  2597.         push    [ebp+tls.cur_dir]
  2598.         call    [lstrlenA]
  2599.         push    eax
  2600.         push    esi
  2601.         call    [lstrlenA]
  2602.         mov     edi, eax
  2603.         inc     eax
  2604.         add     [esp], eax
  2605.         push    [ebp+tls.cur_dir]
  2606.         push    0
  2607.         push    [hHeap]
  2608.         call    [HeapReAlloc]
  2609.         mov     [ebp+tls.cur_dir], eax
  2610.         add     edi, eax
  2611. .l1:
  2612.         cmp     word [esi], '.'
  2613.         jz      .ret
  2614.         cmp     word [esi], './'
  2615.         jnz     @f
  2616.         inc     esi
  2617.         inc     esi
  2618.         jmp     .l1
  2619. @@:
  2620.         cmp     word [esi], '..'
  2621.         jnz     .copy
  2622.         cmp     byte [esi+2], 0
  2623.         jz      @f
  2624.         cmp     byte [esi+2], '/'
  2625.         jnz     .copy
  2626. @@:
  2627.         dec     edi
  2628.         cmp     edi, [ebp+tls.cur_dir]
  2629.         jbe     @f
  2630.         cmp     byte [edi], '/'
  2631.         jnz     @b
  2632. @@:
  2633.         inc     esi
  2634.         inc     esi
  2635.         cmp     byte [esi], 0
  2636.         jz      .ret
  2637.         inc     esi
  2638.         jmp     .l1
  2639. .copy:
  2640.         lodsb
  2641.         stosb
  2642.         test    al, al
  2643.         jnz     .copy
  2644.         ret
  2645. .ret:
  2646.         mov     byte [edi], 0
  2647.         ret
  2648.  
  2649. i40_delete_ramdisk_file:
  2650.         sub     esp, 512
  2651.         mov     edi, esp
  2652.         call    ramdisk2win32
  2653.         push    edi
  2654.         call    [DeleteFileA]
  2655.         add     esp, 512
  2656.         ret
  2657.  
  2658. i40_write_ramdisk_file:
  2659.         test    esi, esi
  2660.         jnz     not_supported_i40_fn
  2661.         sub     esp, 512
  2662.         mov     edi, esp
  2663.         push    ecx edx
  2664.         call    ramdisk2win32
  2665.         push    0
  2666.         push    80h
  2667.         push    2
  2668.         push    0
  2669.         push    0
  2670.         push    40000000h
  2671.         push    edi
  2672.         call    [CreateFileA]
  2673.         inc     eax
  2674.         jz      .ret
  2675.         dec     eax
  2676.         xchg    eax, esi
  2677.         pop     edx ecx
  2678.         add     ecx, [base]
  2679.         push    eax
  2680.         mov     eax, esp
  2681.         push    0
  2682.         push    eax
  2683.         push    edx
  2684.         push    ecx
  2685.         push    esi
  2686.         call    [WriteFile]
  2687.         pop     eax
  2688.         push    esi
  2689.         call    [CloseHandle]
  2690. .ret:
  2691.         add     esp, 512
  2692.         and     dword [esp+20h], 0
  2693.         ret
  2694.  
  2695. i40_screen_getpixel:
  2696.         push    0
  2697.         call    [GetDC]
  2698.         xchg    eax, esi
  2699.         push    8
  2700.         push    esi
  2701.         call    [GetDeviceCaps]
  2702.         xchg    eax, ebx
  2703.         xor     edx, edx
  2704.         div     ebx
  2705.         push    eax
  2706.         push    edx
  2707.         push    esi
  2708.         call    [GetPixel]
  2709.         push    eax
  2710.         push    esi
  2711.         push    0
  2712.         call    [ReleaseDC]
  2713.         pop     eax
  2714.         call    convert_color
  2715.         mov     [esp+20h], eax
  2716.         ret
  2717.  
  2718. i40_screen_getarea:
  2719.         add     ebx, [base]
  2720.         push    ecx ebx edx
  2721.         mov     edi, ecx
  2722.         movsx   ebx, cx
  2723.         sar     edi, 16
  2724.         cmp     ebx, 0
  2725.         jle     .nodata
  2726.         cmp     edi, 0
  2727.         jg      .okdata
  2728. .nodata:
  2729.         pop     edx ebx ecx
  2730.         ret
  2731. .okdata:
  2732.         xor     eax, eax
  2733.         push    eax
  2734.         call    [GetDC]
  2735.         push    eax
  2736.         push    eax
  2737.         call    [CreateCompatibleDC]
  2738.         xchg    eax, esi
  2739.         push    ebx
  2740.         push    edi
  2741.         push    dword [esp+8]
  2742.         call    [CreateCompatibleBitmap]
  2743.         push    eax
  2744.         push    esi
  2745.         call    [SelectObject]
  2746.         push    eax
  2747.         movzx   eax, word [esp+8]
  2748.         movzx   ecx, word [esp+8+2]
  2749.         push    0xCC0020
  2750.         push    eax
  2751.         push    ecx
  2752.         push    dword [esp+16]
  2753.         push    ebx
  2754.         push    edi
  2755.         push    0
  2756.         push    0
  2757.         push    esi
  2758.         call    [BitBlt]
  2759.         push    esi
  2760.         call    [SelectObject]
  2761.         push    ebp
  2762.         xchg    eax, ebp
  2763. ; esi=hDC, ebp=hBitmap, ebx=height, edi=width
  2764.         xor     eax, eax
  2765.         push    eax     ; biClrImportant
  2766.         push    eax     ; biClrUsed
  2767.         push    eax     ; biYPelsPerMeter
  2768.         push    eax     ; biXPelsPerMeter
  2769.         push    eax     ; biSizeImage
  2770.         push    eax     ; biCompression
  2771.         push    180001h ; biBitCount, biPlanes
  2772.         push    ebx     ; biHeight
  2773.         neg     dword [esp]
  2774.         push    edi     ; biWidth
  2775.         push    40      ; biSize
  2776.         mov     ecx, esp
  2777.         push    eax     ; uUsage
  2778.         push    ecx     ; lpbi
  2779.         mov     eax, [ecx+52]
  2780.         test    edi, 3
  2781.         jz      .width_aligned_1
  2782.         lea     eax, [3*edi+3]
  2783.         and     al, not 3
  2784.         mul     ebx
  2785.         call    malloc_big
  2786. .width_aligned_1:
  2787.         push    eax     ; lpvBits
  2788.         push    ebx     ; cScanLines
  2789.         push    0       ; uStartScan
  2790.         push    ebp     ; hbmp
  2791.         push    esi     ; hdc
  2792.         xchg    eax, edi
  2793.         call    [GetDIBits]
  2794.         add     esp, 40
  2795.         push    ebp
  2796.         call    [DeleteObject]
  2797.         pop     ebp
  2798.         push    esi
  2799.         call    [DeleteDC]
  2800.         push    0
  2801.         call    [ReleaseDC]
  2802.         pop     edx eax edx
  2803.         cmp     eax, edi
  2804.         jz      .ret
  2805. ; edi -> bits from Windows [dword-aligned scanlines], eax -> bits for Kolibri [no spaces],
  2806.         shr     edx, 16
  2807. ; ebx = height, edx = width
  2808.         push    8000h
  2809.         push    0
  2810.         push    edi
  2811.         xchg    eax, edi
  2812.         lea     edx, [edx*3]
  2813.         xchg    eax, esi
  2814. @@:
  2815.         mov     ecx, edx
  2816.         shr     ecx, 2
  2817.         rep     movsd
  2818.         mov     ecx, edx
  2819.         and     ecx, 3
  2820.         rep     movsb
  2821.         add     esi, 3
  2822.         and     esi, not 3
  2823.         sub     ebx, 1
  2824.         jnz     @b
  2825.         call    [VirtualFree]
  2826. .ret:
  2827.         ret
  2828.  
  2829. i40_read_mouse_pos:
  2830.         dec     ebx
  2831.         js      .get_coord
  2832.         jz      .get_coord
  2833.         dec     ebx
  2834.         jnz     .ifcursor
  2835.         cmp     [bIs9x], 0
  2836.         jnz     read_9x_mouse_buttons
  2837.         xor     ebx, ebx
  2838.         push    6       ; VK_XBUTTON2
  2839.         call    .aks
  2840.         push    5       ; VK_XBUTTON1
  2841.         call    .aks
  2842.         push    4       ; VK_MBUTTON
  2843.         call    .aks
  2844.         push    2       ; VK_RBUTTON
  2845.         call    .aks
  2846.         push    1       ; VK_LBUTTON
  2847.         call    .aks
  2848.         mov     [esp+20h], ebx
  2849.         ret
  2850. .get_coord:
  2851.         push    eax
  2852.         push    eax
  2853.         push    esp
  2854.         call    [GetCursorPos]
  2855.         pop     eax     ; x
  2856.         pop     ecx     ; y
  2857.         test    ebx, ebx
  2858.         js      @f
  2859.         sub     ax, [ebp+tls.x_start]
  2860.         sub     ax, word [ebp+tls.client_left]
  2861.         sub     cx, [ebp+tls.y_start]
  2862.         sub     cx, word [ebp+tls.client_top]
  2863. @@:
  2864.         shl     eax, 16
  2865.         add     eax, ecx
  2866.         mov     [esp+20h], eax
  2867.         ret
  2868. .ifcursor:
  2869.         dec     ebx
  2870.         dec     ebx
  2871.         jz      .load_cursor
  2872.         dec     ebx
  2873.         jz      .set_cursor
  2874.         dec     ebx
  2875.         jnz     .not_cursor
  2876. .delete_cursor:
  2877.         jecxz   .delete_invalid
  2878.         call    acquire_shared
  2879.         mov     eax, ecx
  2880.         mov     ecx, num_cursors
  2881.         mov     edi, [shared_data]
  2882.         add     edi, shared_data_struc.cursors
  2883. @@:
  2884.         add     edi, 8
  2885.         cmp     [edi-8], eax
  2886.         loopnz  @b
  2887.         jnz     .delete_invalid_release
  2888.         mov     ecx, [ebp+tls.cur_slot]
  2889.         cmp     [edi-4], ecx
  2890.         jnz     .delete_invalid_release
  2891.         and     dword [edi-8], 0
  2892.         and     dword [edi-4], 0
  2893.         call    release_shared
  2894.         push    eax
  2895.         call    [DestroyCursor]
  2896. ; the current kernel implementation returns garbage !
  2897.         mov     dword [esp+20h], 0xBAADF00D     ; is it garbage? :-)
  2898.         ret
  2899. .delete_invalid_release:
  2900.         call    release_shared
  2901. .delete_invalid:
  2902.         push    10h
  2903.         push    0
  2904.         push    aInvalidCursor
  2905.         push    0
  2906.         call    [MessageBoxA]
  2907. ; the current kernel implementation returns 6 !?
  2908.         mov     dword [esp+20h], 6
  2909.         ret
  2910. .set_cursor:
  2911. ; set_cursor for invalid handle reverts to standard arrow
  2912.         call    acquire_shared
  2913.         mov     eax, ecx
  2914.         jecxz   .setarrow
  2915.         mov     ecx, num_cursors
  2916.         mov     edi, [shared_data]
  2917.         add     edi, shared_data_struc.cursors
  2918. @@:
  2919.         add     edi, 8
  2920.         cmp     [edi-8], eax
  2921.         loopnz  @b
  2922.         jz      @f
  2923. .setarrow:
  2924.         mov     eax, [hArrow]
  2925. @@:
  2926. ; N.B. I don't check process field, because the kernel allows to set
  2927. ;       cursors, loaded by another process
  2928.         call    release_shared
  2929.         mov     [ebp+tls.hCursor], eax
  2930.         push    eax
  2931.         call    [SetCursor]
  2932.         mov     [esp+20h], eax
  2933.         ret
  2934. .load_cursor:
  2935.         test    dx, dx
  2936.         jz      .fromfile
  2937.         dec     dx
  2938.         jz      .frommem
  2939.         dec     dx
  2940.         jz      .indirect
  2941.         jmp     not_supported_i40_fn
  2942. .fromfile:
  2943.         mov     esi, ecx
  2944.         add     esi, [base]
  2945.         sub     esp, 204h
  2946.         mov     edi, esp
  2947.         call    i40_file_system_lfn.parse
  2948.         test    eax, eax
  2949.         jz      @f
  2950.         add     esp, 204h
  2951.         and     dword [esp+20h], 0
  2952.         ret
  2953. @@:
  2954.         push    10h     ; LR_LOADFROMFILE
  2955.         push    32
  2956.         push    32
  2957.         push    2       ; IMAGE_CURSOR
  2958.         push    edi
  2959.         push    0
  2960.         call    [LoadImageA]
  2961.         add     esp, 204h
  2962.         test    eax, eax
  2963.         jnz     .addcursor
  2964.         push    10h
  2965.         push    0
  2966.         push    aCursorFailed
  2967.         jmp     .mberr
  2968. .addcursor:
  2969.         call    acquire_shared
  2970.         mov     ecx, num_cursors
  2971.         mov     edi, [shared_data]
  2972.         add     edi, shared_data_struc.cursors
  2973. @@:
  2974.         add     edi, 8
  2975.         cmp     dword [edi-8], 0
  2976.         loopnz  @b
  2977.         jz      @f
  2978.         call    release_shared
  2979.         push    10h
  2980.         push    0
  2981.         push    aCursorLimitExceeded
  2982.         jmp     .mberr
  2983. @@:
  2984.         mov     [edi-8], eax
  2985.         mov     edx, [ebp+tls.cur_slot]
  2986.         mov     [edi-4], edx
  2987.         call    release_shared
  2988.         mov     [esp+20h], eax
  2989.         ret
  2990. .frommem:
  2991.         add     ecx, [base]
  2992.         cmp     dword [ecx], 0x020000
  2993.         jz      @f
  2994.         push    10h
  2995.         push    0
  2996.         push    aInvCursorData
  2997. .mberr:
  2998.         push    0
  2999.         call    [MessageBoxA]
  3000. .reterr:
  3001.         and     dword [esp+20h], 0
  3002.         ret
  3003. @@:
  3004.         cmp     word [ecx+4], 1
  3005.         jz      @f
  3006.         push    10h
  3007.         push    0
  3008.         push    aOnlyOneCursor
  3009.         jmp     .mberr
  3010. @@:
  3011.         cmp     word [ecx+6], 0x2020
  3012.         jz      @f
  3013.         push    10h
  3014.         push    0
  3015.         push    aInvCursorDim
  3016.         jmp     .mberr
  3017. @@:
  3018.         mov     eax, [ecx+0Ah]
  3019.         add     ecx, [ecx+12h]
  3020.         sub     ecx, 4
  3021.         push    dword [ecx]
  3022.         mov     [ecx], eax
  3023.         push    ecx
  3024.         push    0
  3025.         push    32
  3026.         push    32
  3027.         push    0x00030000
  3028.         push    0
  3029.         push    0x2E8+4
  3030.         push    ecx
  3031.         call    [CreateIconFromResourceEx]
  3032.         pop     ecx
  3033.         pop     dword [ecx]
  3034.         test    eax, eax
  3035.         jnz     .addcursor
  3036. .gen_failed:
  3037.         push    10h
  3038.         push    0
  3039.         push    aCursorFailed
  3040.         jmp     .mberr
  3041. .indirect:
  3042.         mov     ebx, edx
  3043.         shr     ebx, 16         ; bl = y, bh = x
  3044.         mov     esi, ecx
  3045.         add     esi, [base]
  3046.         push    32*32*4
  3047.         call    malloc
  3048.         mov     edi, eax
  3049.         mov     ecx, 32*32
  3050.         push    esi edi
  3051. @@:
  3052.         lodsd
  3053.         and     eax, 0xFFFFFF
  3054.         stosd
  3055.         loop    @b
  3056.         pop     edi esi
  3057.         push    edi     ; lpvBits
  3058.         push    32      ; cBitsPerPel
  3059.         push    1       ; cPlanes
  3060.         push    32      ; nHeight
  3061.         push    32      ; nWidth
  3062.         call    [CreateBitmap]
  3063.         test    eax, eax
  3064.         jnz     @f
  3065. .free_edi:
  3066.         push    edi
  3067.         call    free
  3068.         jmp     .gen_failed
  3069. @@:
  3070.         push    eax     ; ICONINFO.hbmColor
  3071.         mov     ecx, 32*4
  3072.         push    esi edi
  3073. .1:
  3074.         push    ecx
  3075.         mov     cl, 8
  3076.         xor     edx, edx
  3077. @@:
  3078.         lodsd
  3079.         shr     eax, 24
  3080.         setz    al
  3081.         lea     edx, [edx*2+eax]
  3082.         loop    @b
  3083.         mov     al, dl
  3084.         stosb
  3085.         pop     ecx
  3086.         loop    .1
  3087.         pop     edi esi
  3088.         push    edi     ; lpvBits
  3089.         push    1       ; cBitsPerPel
  3090.         push    1       ; cPlanes
  3091.         push    32      ; nHeight
  3092.         push    32      ; nWidth
  3093.         call    [CreateBitmap]
  3094.         test    eax, eax
  3095.         jnz     @f
  3096.         call    [DeleteObject]
  3097.         jmp     .free_edi
  3098. @@:
  3099.         push    eax     ; ICONINFO.hbmMask
  3100.         movzx   eax, bl
  3101.         push    eax     ; ICONINFO.yHotSpot
  3102.         movzx   eax, bh
  3103.         push    eax     ; ICONINFO.xHotSpot
  3104.         push    0       ; ICONINFO.fIcon
  3105.         push    esp
  3106.         call    [CreateIconIndirect]
  3107.         mov     ebx, eax
  3108.         add     esp, 12
  3109.         call    [DeleteObject]
  3110.         call    [DeleteObject]
  3111.         test    ebx, ebx
  3112.         jz      .free_edi
  3113.         push    edi
  3114.         call    free
  3115.         mov     eax, ebx
  3116.         jmp     .addcursor
  3117.  
  3118. .not_cursor:
  3119.         dec     ebx
  3120.         jnz     not_supported_i40_fn
  3121.         mov     eax, [ebp+tls.scroll]
  3122.         cdq
  3123.         mov     ecx, 120        ; WHEEL_DELTA
  3124.         idiv    ecx
  3125.         mov     [ebp+tls.scroll], edx
  3126.         movzx   eax, ax
  3127.         mov     [esp+20h], eax
  3128.         ret
  3129.  
  3130. .aks:
  3131.         push    dword [esp+4]
  3132.         call    [GetAsyncKeyState]
  3133.         cmp     ah, 80h
  3134.         cmc
  3135.         adc     ebx, ebx
  3136.         ret     4
  3137.  
  3138. read_9x_mouse_buttons:
  3139.         call    [jmp_temp_int33]
  3140.         movzx   eax, bl
  3141.         mov     [esp+20h], eax
  3142.         ret
  3143.  
  3144. use16
  3145. temp_code:
  3146.         mov     eax, esp
  3147.         mov     ss, [temp_ss]
  3148.         mov     sp, temp_stack_size
  3149.         push    eax
  3150.  
  3151.         mov     ax, 3
  3152.         int     33h
  3153.  
  3154.         pop     eax
  3155.         push    ds
  3156.         pop     ss
  3157.         mov     esp, eax
  3158.         db      66h
  3159.         retf
  3160.  
  3161. temp_code_int1A:
  3162.         mov     esi, esp
  3163.         mov     ss, [temp_ss]
  3164.         mov     sp, temp_stack_size
  3165.         push    esi
  3166.  
  3167.         int     1Ah
  3168.  
  3169.         pop     esi
  3170.         push    ds
  3171.         pop     ss
  3172.         mov     esp, esi
  3173.         db      66h
  3174.         retf
  3175.  
  3176. temp_code_size = $ - temp_code
  3177. use32
  3178.  
  3179. i40_draw_line:
  3180.         push    edx
  3181.         mov     esi, ecx
  3182.         mov     eax, edx
  3183.         call    convert_color
  3184.         push    eax
  3185.         push    eax
  3186.         push    1
  3187.         push    0
  3188.         call    [CreatePen]
  3189.         push    eax
  3190.         push    [ebp+tls.hWnd]
  3191.         call    [GetDC]
  3192.         xchg    eax, edi
  3193.         push    edi
  3194.         call    [SelectObject]
  3195.         push    eax
  3196.         push    0
  3197.         test    byte [esp+12+3], 0x01
  3198.         jz      @f
  3199.         push    6       ; R2_NOT
  3200.         push    edi
  3201.         call    [SetROP2]
  3202.         mov     [esp], eax
  3203. @@:
  3204.         push    0
  3205.         mov     eax, esi
  3206.         shr     eax, 16
  3207.         add     eax, [ebp+tls.client_top]
  3208.         push    eax
  3209.         mov     eax, ebx
  3210.         shr     eax, 16
  3211.         add     eax, [ebp+tls.client_left]
  3212.         push    eax
  3213.         push    edi
  3214.         call    [MoveToEx]
  3215.         movzx   esi, si
  3216.         add     esi, [ebp+tls.client_top]
  3217.         push    esi
  3218.         movzx   ebx, bx
  3219.         add     ebx, [ebp+tls.client_left]
  3220.         push    ebx
  3221.         push    edi
  3222.         call    [LineTo]
  3223.         pop     eax
  3224.         test    byte [esp+8+3], 0x01
  3225.         jz      @f
  3226.         push    eax
  3227.         push    edi
  3228.         call    [SetROP2]
  3229.         push    esi
  3230.         push    ebx
  3231.         push    edi
  3232.         call    [GetPixel]
  3233.         xor     eax, 0xFFFFFF
  3234.         mov     [esp+4], eax
  3235. @@:
  3236.         pop     eax
  3237.         pop     ecx
  3238.         push    eax
  3239.         push    ecx
  3240.         push    esi
  3241.         push    ebx
  3242.         push    edi
  3243.         call    [SetPixel]
  3244.         push    edi
  3245.         call    [SelectObject]
  3246.         push    eax
  3247.         call    [DeleteObject]
  3248.         push    edi
  3249.         push    [ebp+tls.hWnd]
  3250.         call    [ReleaseDC]
  3251.         pop     edx
  3252.         ret
  3253.  
  3254. i40_get_background:
  3255.         pushad
  3256.         push    0
  3257.         call    init_background
  3258.         popad
  3259.         mov     eax, [bgr_section]
  3260.         dec     ebx
  3261.         jz      .1
  3262.         dec     ebx
  3263.         jz      .2
  3264.         dec     ebx
  3265.         dec     ebx
  3266.         jnz     not_supported_i40_fn
  3267.         test    eax, eax
  3268.         mov     ecx, 2
  3269.         jz      @f
  3270.         mov     ecx, [eax+8]
  3271. @@:
  3272.         mov     [esp+20h], ecx
  3273.         ret
  3274. .1:
  3275.         test    eax, eax
  3276.         jz      @f
  3277.         mov     ecx, [eax]
  3278.         shl     ecx, 16
  3279.         mov     cx, [eax+4]
  3280.         jmp     @b
  3281. @@:
  3282.         call    get_screen_size
  3283.         add     ebx, 10001h
  3284. @@:
  3285.         mov     [esp+20h], ebx
  3286. .ret:
  3287.         ret
  3288. .2:
  3289. ;       cmp     ecx, 0x160000-16
  3290. ;       jae     .ret
  3291.         xor     ebx, ebx
  3292.         test    eax, eax
  3293.         jz      @b
  3294.         mov     ebx, [eax+ecx+10h]
  3295.         and     ebx, 0x00FFFFFF
  3296.         jmp     @b
  3297.  
  3298. i40_set_event_mask:
  3299.         test    ebx, not 1F7h
  3300.         jnz     not_supported_i40_fn
  3301.         mov     [ebp+tls.message_mask], ebx
  3302.         ret
  3303.  
  3304. i40_reserve_free_ports:
  3305.         cmp     ebx, 1
  3306.         ja      not_supported_i40_fn
  3307.         cmp     edx, 0xFFFF
  3308.         ja      .inv_range
  3309.         cmp     ecx, edx
  3310.         jbe     .range_ok
  3311. .inv_range:
  3312.         push    30h
  3313.         push    aWarning
  3314.         push    PortsRangeErr
  3315.         push    0
  3316.         call    [MessageBoxA]
  3317.         mov     dword [esp+20h], 1
  3318.         ret
  3319. .range_ok:
  3320.         call    acquire_shared
  3321.         mov     esi, [shared_data]
  3322.         mov     eax, ecx
  3323.         test    ebx, ebx
  3324.         jnz     .free
  3325. ; reserve ports
  3326. @@:
  3327.         mov     edi, PortsNotEnabledErr
  3328.         bt      dword [esi+shared_data_struc.DisabledPorts], eax
  3329.         jc      .err_release
  3330.         mov     edi, PortsUsedErr
  3331.         bt      dword [esi+shared_data_struc.UsedIoMap], eax
  3332.         jnc     .err_release
  3333.         inc     eax
  3334.         cmp     eax, edx
  3335.         jbe     @b
  3336.         mov     eax, ecx
  3337. @@:
  3338.         btr     dword [esi+shared_data_struc.UsedIoMap], eax
  3339.         inc     eax
  3340.         cmp     eax, edx
  3341.         jbe     @b
  3342.         jmp     .update_iomap
  3343. .free:
  3344.         mov     edi, PortsNotUsedErr
  3345.         bt      dword [esi+shared_data_struc.UsedIoMap], eax
  3346.         jc      .err_release
  3347.         inc     eax
  3348.         cmp     eax, edx
  3349.         jbe     .free
  3350.         mov     eax, ecx
  3351. @@:
  3352.         bts     dword [esi+shared_data_struc.UsedIoMap], eax
  3353.         inc     eax
  3354.         cmp     eax, edx
  3355.         jbe     @b
  3356. .update_iomap:
  3357.         cmp     [bIs9x], 0
  3358.         jz      .nt
  3359.         call    release_shared
  3360.         and     dword [esp+20h], 0
  3361.         ret
  3362. .nt:
  3363.         mov     eax, [shared_data]
  3364.         push    0
  3365.         push    0
  3366.         add     eax, shared_data_struc.UsedIoMap
  3367.         push    2000h
  3368.         push    eax
  3369.         push    0x22203C
  3370.         call    send_driver_request
  3371.         mov     edi, DrvOpenErr
  3372.         jnz     @f
  3373. .err_release:
  3374.         call    release_shared
  3375.         push    30h
  3376.         push    aWarning
  3377.         push    edi
  3378.         push    0
  3379.         call    [MessageBoxA]
  3380.         mov     dword [esp+20h], 1
  3381.         ret
  3382. @@:
  3383.         call    release_shared
  3384. ;       push    0
  3385. ;       call    [Sleep]         ; force task switch
  3386.         and     dword [esp+20h], 0
  3387.         ret
  3388.  
  3389. i40_display_number:
  3390.         cmp     bl, 1
  3391.         ja      not_supported_i40_fn
  3392.         push    ebx esi
  3393.         and     ebx, not 0xC0000000
  3394.         xor     esi, esi
  3395.         cmp     bl, 1
  3396.         jb      .noptr
  3397.         mov     eax, [base]
  3398.         test    byte [esp+7], 0x40
  3399.         jz      @f
  3400.         mov     esi, [eax+ecx+4]
  3401. @@:
  3402.         mov     ecx, [eax+ecx]
  3403. .noptr:
  3404.         mov     eax, 10
  3405.         cmp     bh, 1
  3406.         jb      @f
  3407.         mov     eax, 16
  3408.         jz      @f
  3409.         mov     eax, 2
  3410. @@:
  3411.         shr     ebx, 16
  3412.         cmp     ebx, 64
  3413.         jbe     @f
  3414.         pop     esi ebx
  3415.         jmp     not_supported_i40_fn
  3416. @@:
  3417.         push    edi
  3418.         mov     edi, esp
  3419.         sub     esp, 64
  3420.         dec     edi
  3421.         std
  3422.         push    edx
  3423.         push    ebx
  3424.         xchg    eax, ecx
  3425.         test    ebx, ebx
  3426.         jz      .done
  3427. .digit:
  3428.         xor     edx, edx
  3429.         test    esi, esi
  3430.         jz      .dig0
  3431.         push    eax
  3432.         mov     eax, esi
  3433.         div     ecx
  3434.         pop     esi
  3435.         xchg    eax, esi
  3436. .dig0:
  3437.         div     ecx
  3438.         xchg    eax, edx
  3439.         cmp     al, 10
  3440.         sbb     al, 69h
  3441.         das
  3442.         stosb
  3443.         xchg    eax, edx
  3444.         dec     ebx
  3445.         jnz     .digit
  3446. .done:
  3447.         cld
  3448.         mov     edx, edi
  3449.         inc     edx
  3450.         pop     esi
  3451.         pop     ebx
  3452.         lea     edi, [esp+40h]
  3453.         test    byte [esp+48h+3], 80h
  3454.         jz      .okleadzero
  3455. @@:
  3456.         cmp     byte [edx], '0'
  3457.         jnz     .okleadzero
  3458.         inc     edx
  3459.         dec     esi
  3460.         cmp     edx, edi
  3461.         jb      @b
  3462.         dec     edx
  3463.         inc     esi
  3464.         mov     byte [edx], '0'
  3465. .okleadzero:
  3466.         mov     ecx, [edi+4]
  3467.         and     ecx, not 0x80000000
  3468.         mov     edi, [edi]
  3469.         call    i40_writetext_l1
  3470.         add     esp, 4Ch
  3471.         ret
  3472.  
  3473. i40_display_settings:
  3474.         dec     ebx
  3475.         jnz     @f
  3476. set_button_style:
  3477.         div     edx
  3478.         ret
  3479. @@:
  3480.         dec     ebx
  3481.         jnz     @f
  3482.         add     ecx, [base]
  3483. set_wnd_colors:
  3484.         div     edx
  3485.         ret
  3486. @@:
  3487.         dec     ebx
  3488.         jnz     @f
  3489.         add     ecx, [base]
  3490. get_wnd_colors:
  3491.         div     edx
  3492.         ret
  3493. @@:
  3494.         dec     ebx
  3495.         jnz     @f
  3496.         mov     eax, [_skinh]
  3497.         mov     [esp+20h], eax
  3498.         ret
  3499. @@:
  3500.         dec     ebx
  3501.         jnz     @f
  3502.         call    acquire_shared
  3503.         mov     eax, [shared_data]
  3504.         mov     ecx, [eax+shared_data_struc.workarea_right]
  3505.         mov     [esp+20h], ecx
  3506.         mov     ecx, [eax+shared_data_struc.workarea_left]
  3507.         mov     [esp+22h], cx
  3508.         mov     ecx, [eax+shared_data_struc.workarea_bottom]
  3509.         mov     [esp+14h], ecx
  3510.         mov     ecx, [eax+shared_data_struc.workarea_top]
  3511.         mov     [esp+16h], cx
  3512.         call    release_shared
  3513.         ret
  3514. @@:
  3515.         dec     ebx
  3516.         jnz     @f
  3517.         call    acquire_shared
  3518.         mov     eax, [shared_data]
  3519.         mov     bx, cx
  3520.         mov     [eax+shared_data_struc.workarea_right], ebx
  3521.         shr     ecx, 10h
  3522.         mov     [eax+shared_data_struc.workarea_left], ecx
  3523.         mov     bx, dx
  3524.         mov     [eax+shared_data_struc.workarea_bottom], ebx
  3525.         shr     edx, 10h
  3526.         mov     [eax+shared_data_struc.workarea_top], edx
  3527.         call    release_shared
  3528.         ret
  3529. @@:
  3530.         dec     ebx
  3531.         jnz     not_supported_i40_fn
  3532.         mov     eax, dword [margins]
  3533.         mov     [esp+20h], eax
  3534.         mov     eax, dword [margins+4]
  3535.         mov     [esp+14h], eax
  3536.         ret
  3537.  
  3538. i40_set_window_shape:
  3539.         test    ebx, ebx
  3540.         jnz     @f
  3541.         mov     [ebp+tls.lpShapeData], ecx
  3542.         jmp     .common
  3543. @@:     dec     ebx
  3544.         jnz     not_supported_i40_fn
  3545.         inc     ebx
  3546.         shl     ebx, cl
  3547.         mov     [ebp+tls.scale], ebx
  3548. .common:
  3549.         cmp     [ebp+tls.showwnd], 0
  3550.         jz      .done
  3551.         call    set_window_shape
  3552. .done:  ret
  3553.  
  3554. set_window_shape:
  3555.         mov     esi, [ebp+tls.lpShapeData]
  3556.         add     esi, [base]
  3557.         movzx   ebx, [ebp+tls.y_size]
  3558.         mov     eax, ebx
  3559.         inc     eax
  3560.         inc     eax
  3561.         shl     eax, 4
  3562.         push    eax
  3563.         call    malloc
  3564.         push    eax
  3565.         xchg    eax, edi
  3566.         push    20h
  3567.         pop     eax
  3568.         stosd           ; RGNDATAHEADER.dwSize
  3569.         push    1
  3570.         pop     eax
  3571.         stosd           ; .iType
  3572.         xor     eax, eax
  3573.         stosd           ; .nCount
  3574.         stosd           ; .nRgnSize
  3575.         stosd           ; RGNDATAHEADER.rcBound.left
  3576.         stosd           ; .top
  3577.         movzx   eax, [ebp+tls.x_size]
  3578.         stosd           ; .right
  3579.         movzx   eax, [ebp+tls.y_size]
  3580.         stosd           ; .bottom
  3581.         xor     edx, edx        ; edx=number of rects, ebp=allocated number of rects
  3582.         xor     ecx, ecx
  3583. .yloop:
  3584.         push    ecx
  3585.         xor     ecx, ecx
  3586. .1:
  3587.         lodsb
  3588.         cmp     al, 0
  3589.         jnz     .2
  3590.         add     ecx, [ebp+tls.scale]
  3591.         cmp     cx, [ebp+tls.x_size]
  3592.         jae     .3
  3593.         jmp     .1
  3594. .2:
  3595.         inc     edx
  3596.         cmp     edx, ebx
  3597.         ja      .realloc_rects
  3598. .realloc_cont:
  3599.         mov     [edi], ecx
  3600.         pop     eax
  3601.         mov     [edi+4], eax
  3602.         push    eax
  3603.         add     eax, [ebp+tls.scale]
  3604.         mov     [edi+12], eax
  3605.         add     ecx, [ebp+tls.scale]
  3606. .4:
  3607.         lodsb
  3608.         cmp     al, 0
  3609.         jz      .5
  3610.         add     ecx, [ebp+tls.scale]
  3611.         cmp     cx, [ebp+tls.x_size]
  3612.         jb      .4
  3613. .5:
  3614.         mov     [edi+8], ecx
  3615.         add     edi, 10h
  3616.         add     ecx, [ebp+tls.scale]
  3617.         cmp     cx, [ebp+tls.x_size]
  3618.         jb      .1
  3619. .3:
  3620.         pop     ecx
  3621.         add     ecx, [ebp+tls.scale]
  3622.         cmp     cx, [ebp+tls.y_size]
  3623.         jb      .yloop
  3624.         pop     edi
  3625.         mov     [edi+8], edx
  3626.         push    edi
  3627.         inc     edx
  3628.         inc     edx
  3629.         shl     edx, 4
  3630.         push    edx
  3631.         push    0
  3632.         call    [ExtCreateRegion]
  3633.         push    1
  3634.         push    eax
  3635.         push    [ebp+tls.hWnd]
  3636.         call    [SetWindowRgn]
  3637.         push    edi
  3638.         call    free
  3639.         ret
  3640.  
  3641. .realloc_rects:
  3642.         push    ecx
  3643.         push    edx
  3644.         add     ebx, ebx        ; multiply size by 2
  3645.         mov     eax, ebx
  3646.         inc     eax
  3647.         inc     eax
  3648.         shl     eax, 4
  3649.         push    eax
  3650.         push    dword [esp+10h]
  3651.         push    0
  3652.         push    [hHeap]
  3653.         call    [HeapReAlloc]
  3654.         sub     edi, [esp+0xC]
  3655.         add     edi, eax
  3656.         mov     [esp+0xC], eax
  3657.         pop     edx
  3658.         pop     ecx
  3659.         jmp     .realloc_cont
  3660.  
  3661. i40_create_thread:
  3662.         dec     ebx
  3663.         jnz     not_supported_i40_fn
  3664.         push    ecx
  3665.         push    edx
  3666.         push    16
  3667.         call    malloc
  3668.         xchg    eax, ebx
  3669.         pop     dword [ebx+4]   ; esp
  3670.         pop     dword [ebx]     ; eip
  3671.         push    0
  3672.         push    0
  3673.         push    0
  3674.         push    0
  3675.         call    [CreateEventA]
  3676.         mov     [ebx+8], eax
  3677.         mov     eax, [ebp+tls.cur_dir]
  3678.         mov     [ebx+12], eax
  3679.         push    eax
  3680.         push    esp
  3681.         push    0
  3682.         push    ebx
  3683.         push    KolibriThreadProc
  3684.         push    10000h
  3685.         push    0
  3686.         call    [CreateThread]
  3687.         pop     ecx
  3688.         test    eax, eax
  3689.         jnz     @f
  3690.         or      dword [esp+20h], -1
  3691.         ret
  3692. @@:
  3693.         push    eax
  3694.         call    [CloseHandle]
  3695.         push    -1
  3696.         push    dword [ebx+8]
  3697.         call    [WaitForSingleObject]
  3698.         push    dword [ebx+8]
  3699.         call    [CloseHandle]
  3700.         mov     esi, [ebx]
  3701.         push    ebx
  3702.         call    free
  3703. ; esi = slot; get PID
  3704.         call    acquire_shared
  3705.         xchg    eax, esi
  3706.         call    get_slot_ptr
  3707.         mov     eax, [edi]
  3708.         mov     dword [esp+20h], eax
  3709.         push    edi
  3710.         call    get_cur_slot_ptr
  3711.         lea     esi, [edi+24]
  3712.         pop     edi
  3713.         add     edi, 24
  3714.         movsd
  3715.         movsd
  3716.         movsd
  3717.         movsd
  3718.         call    release_shared
  3719.         ret
  3720.  
  3721. KolibriThreadProc:
  3722.         mov     ebp, [tls_index]
  3723.         mov     eax, [fs:2Ch]
  3724.         mov     ebp, [eax+ebp*4]
  3725.         mov     ebx, [esp+4]
  3726.         mov     ecx, [ebx]
  3727.         mov     edx, [ebx+4]
  3728.         mov     [ebp+tls._cs], cs
  3729.         mov     [ebp+tls._ds], ds
  3730.         mov     [ebp+tls._fs], fs
  3731.         mov     [ebp+tls._esp], edx
  3732.         mov     [ebp+tls._eip], ecx
  3733.         mov     esi, [ebx+12]
  3734.         push    esi
  3735.         call    [lstrlenA]
  3736.         inc     eax
  3737.         push    eax
  3738.         push    eax
  3739.         call    malloc
  3740.         pop     ecx
  3741.         mov     [ebp+tls.cur_dir], eax
  3742.         mov     edi, eax
  3743.         rep     movsb
  3744. lock    inc     [NumThreads]
  3745.         call    acquire_shared
  3746. server_new_thread:
  3747.         div     edx
  3748.         call    release_shared
  3749.         mov     [ebp+tls.cur_slot], ecx
  3750.         mov     [ebx], ecx
  3751.         push    dword [ebx+8]
  3752.         call    [SetEvent]
  3753.         xor     ebx, ebx
  3754.         push    ebx
  3755.         push    400000h
  3756.         push    ebx
  3757.         push    ebx
  3758.         mov     eax, 80000000h
  3759.         push    eax
  3760.         push    eax
  3761.         push    eax
  3762.         push    eax
  3763.         push    eax
  3764.         push    [process_name]
  3765.         push    classname
  3766.         push    ebx
  3767.         call    [CreateWindowExA]
  3768.         mov     [ebp+tls.hWnd], eax
  3769.         mov     [ebp+tls.bActive], 1
  3770.         mov     [ebp+tls.bFirstMouseMove], 1
  3771.         call    acquire_shared
  3772.         call    get_cur_slot_ptr
  3773.         mov     [edi+shared_data_struc.hWnd-shared_data_struc.threads], eax
  3774.         call    release_shared
  3775.         xor     eax, eax
  3776.         xor     ecx, ecx
  3777.         xor     edx, edx
  3778.         xor     esi, esi
  3779.         xor     edi, edi
  3780.         push    202h
  3781.         pushad
  3782.         and     dword [esp+8], 0
  3783.         jmp     i40_done
  3784.  
  3785. ; initialize_winsock:
  3786.         ; push  ecx edx
  3787.         ; cmp   [WinSockDLL], -1
  3788.         ; jz    .failed_ret
  3789.         ; cmp   [WinSockDLL], 0
  3790.         ; jnz   .ok
  3791.         ; push  winsock_name
  3792.         ; call  [LoadLibraryA]
  3793.         ; mov   [WinSockDLL], eax
  3794.         ; test  eax, eax
  3795.         ; jz    .failed
  3796.         ; push  esi
  3797.         ; mov   esi, winsock_imports
  3798. ; .import:
  3799.         ; lodsd
  3800.         ; test  eax, eax
  3801.         ; jz    .importok
  3802.         ; push  eax
  3803.         ; push  [WinSockDLL]
  3804.         ; call  [GetProcAddress]
  3805.         ; mov   [esi-4], eax
  3806.         ; test  eax, eax
  3807.         ; jnz   .import
  3808.         ; pop   esi
  3809.         ; jmp   .failed
  3810. ; .importok:
  3811.         ; sub   esp, 190h
  3812.         ; push  esp
  3813.         ; push  101h
  3814.         ; call  [WSAStartup]
  3815.         ; add   esp, 190h
  3816.         ; test  eax, eax
  3817.         ; jz    .ok
  3818. ; .failed:
  3819.         ; or    [WinSockDLL], -1
  3820.         ; push  10h
  3821.         ; push  0
  3822.         ; push  aWinsockInitErr
  3823.         ; push  0
  3824.         ; call  [MessageBoxA]
  3825. ; .failed_ret:
  3826.         ; stc
  3827. ; .ok:
  3828.         ; pop   edx ecx
  3829.         ; ret
  3830.  
  3831. ; i40_socket:
  3832.         ; call  initialize_winsock
  3833.         ; jnc   @f
  3834.         ; or    dword [esp+20h], -1
  3835.         ; ret
  3836. ; @@:
  3837.         ; cmp   ebx, 9
  3838.         ; jnz   not_supported_i40_fn
  3839. ; .is_localport_unused:
  3840.         ; mov   esi, ecx
  3841. ; ; destroy old tcp socket
  3842.         ; mov   eax, [ebp+tls.cursocket]
  3843.         ; test  eax, eax
  3844.         ; jz    @f
  3845.         ; dec   eax
  3846.         ; push  eax
  3847.         ; call  [closesocket]
  3848. ; @@:
  3849.         ; xor   ebx, ebx
  3850.         ; mov   [ebp+tls.curport], bx
  3851. ; ; create new tcp socket
  3852.         ; push  ebx     ; protocol - unspecified
  3853.         ; push  1       ; SOCK_STREAM aka TCP
  3854.         ; push  2       ; AF_INET
  3855.         ; call  [socket]
  3856.         ; inc   eax
  3857.         ; mov   [ebp+tls.cursocket], eax
  3858.         ; jnz   @f
  3859.         ; push  10h
  3860.         ; push  ebx
  3861.         ; push  aSocketErr
  3862.         ; push  ebx
  3863.         ; call  [MessageBoxA]
  3864.         ; mov   dword [esp+20h], ebx
  3865.         ; ret
  3866. ; @@:
  3867.         ; push  ebx
  3868.         ; push  ebx     ; sockaddr_in.sin_zero
  3869.         ; push  0x0100007F      ; sockaddr_in.sin_addr = 127.0.0.1
  3870.         ; shl   esi, 16
  3871.         ; inc   esi
  3872.         ; inc   esi     ; sockaddr_in.sin_family = 2 = AF_INET
  3873.         ; push  esi     ; sockaddr_in.sin_port
  3874.         ; mov   ecx, esp
  3875.         ; push  10h     ; namelen
  3876.         ; push  ecx     ; name
  3877.         ; dec   eax
  3878.         ; push  eax     ; s
  3879.         ; call  [bind]
  3880.  
  3881. i40_sound_interface:
  3882.         cmp     ebx, 55
  3883.         jnz     not_supported_i40_fn
  3884.         mov     eax, [shared_data]
  3885.         cmp     [eax+shared_data_struc.sound_flag], 0
  3886.         jz      @f
  3887.         ret
  3888. @@:
  3889. ; prepare wave-block
  3890.         push    800h
  3891.         call    malloc
  3892.         push    eax
  3893.         lea     ebx, [eax+800h]
  3894.         xchg    eax, edi
  3895.         push    esi
  3896.         mov     esi, wave_block_begin
  3897.         mov     ecx, wbb_size/4
  3898.         rep     movsd
  3899.         stosd
  3900.         pop     esi
  3901.         add     esi, [base]
  3902. .mainloop:
  3903.         lodsb
  3904.         test    al, al
  3905.         jz      .done
  3906.         cmp     al, 81h
  3907.         jae     .note
  3908.         movzx   edx, al
  3909.         xor     eax, eax
  3910.         lodsw
  3911.         jmp     .doit
  3912. .note:
  3913.         sub     al, 81h
  3914.         movzx   edx, al
  3915.         lodsb
  3916.         cmp     al, 0xFF
  3917.         jz      .pause
  3918.         mov     cl, al
  3919.         and     eax, 0xF
  3920.         movzx   eax, word [kontrOctave+eax+eax]
  3921.         shr     cl, 4
  3922.         shr     eax, cl
  3923. .doit:
  3924. ; eax=divider (freq=1193180/divider), edx=time (in 1/100 sec)
  3925.         mov     ecx, edx
  3926.         mul     [wave_r]
  3927.         div     [_1193180]
  3928.         push    eax
  3929.         mov     eax, ecx
  3930.         mul     [wave_r]
  3931.         div     [_100]
  3932.         mov     ecx, eax
  3933.         pop     edx
  3934. .doit2:
  3935. ; ecx=number of bytes required for this note
  3936.         lea     eax, [edi+ecx]
  3937.         cmp     eax, ebx
  3938.         ja      .realloc
  3939. ;       mov     al, 0xFF
  3940. ;       cmp     edx, ecx
  3941. ;       jbe     @f
  3942. ;       mov     al, 0   ; this is for pause
  3943. ;@@:
  3944.         mov     al, 80h
  3945. ; if edx is zero, make it 1
  3946.         cmp     edx, 1
  3947.         adc     edx, 0
  3948. .writeloop:
  3949.         push    ecx
  3950.         cmp     ecx, edx
  3951.         jb      @f
  3952.         mov     ecx, edx
  3953. @@:     rep     stosb
  3954.         pop     ecx
  3955.         xor     al, [sound_vol]
  3956.         sub     ecx, edx
  3957.         ja      .writeloop
  3958.         jmp     .mainloop
  3959. .pause:
  3960.         mov     eax, edx
  3961.         mul     [wave_r]
  3962.         div     [_100]
  3963.         mov     ecx, eax
  3964.         mov     edx, eax
  3965.         inc     edx
  3966.         jmp     .doit2
  3967. .realloc:
  3968.         pop     eax
  3969.         sub     ebx, eax
  3970.         add     ebx, ebx        ; ebx=new size
  3971.         sub     edi, eax        ; edi=delta
  3972.         push    ecx edx
  3973.         push    ebx
  3974.         push    eax
  3975.         push    0
  3976.         push    [hHeap]
  3977.         call    [HeapReAlloc]
  3978.         pop     edx ecx
  3979.         push    eax
  3980.         add     ebx, eax
  3981.         add     edi, eax
  3982.         jmp     .doit2
  3983. .done:
  3984.         pop     ebx
  3985.         sub     edi, ebx
  3986.         sub     edi, 8
  3987.         mov     [ebx+4], edi
  3988.         sub     edi, 24h
  3989.         mov     [ebx+28h], edi
  3990. ; because we use asynchronous call of PlaySoundA, we can not free used memory,
  3991. ; but we can free previous wave-block
  3992.         push    0
  3993.         push    0
  3994.         push    0
  3995.         call    [PlaySoundA]    ; force previous sound terminate
  3996.         push    5       ; SND_ASYNC|SND_MEMORY
  3997.         push    0
  3998.         push    ebx
  3999.         call    [PlaySoundA]
  4000.         xchg    ebx, [ebp+tls.prev_snd_block]
  4001.         test    ebx, ebx
  4002.         jz      @f
  4003.         push    ebx
  4004.         call    free
  4005. @@:
  4006.         and     dword [esp+20h], 0
  4007.         ret
  4008.  
  4009. i40_file_system:
  4010.         add     ebx, [base]
  4011.         lea     esi, [ebx+0x14]
  4012.         cmp     dword [ebx], 0
  4013.         jnz     not_supported_i40_fn
  4014. emul_read_file:
  4015. ; read 0 bytes - OK
  4016.         cmp     dword [ebx+8], 0
  4017.         jnz     @f
  4018.         and     dword [esp+20h], 0
  4019.         ret
  4020. @@:
  4021. ; check for root dir
  4022.         cmp     byte [esi], 0
  4023.         jz      .root
  4024.         cmp     byte [esi+1], 0
  4025.         jnz     .noroot
  4026. .root:
  4027.         mov     esi, dir0
  4028.         mov     edi, [ebx+12]
  4029.         add     edi, [base]
  4030.         mov     ecx, 12
  4031.         push    ecx
  4032.         rep     movsb
  4033.         add     edi, 32-12
  4034.         pop     ecx
  4035.         rep     movsb
  4036.         and     dword [esp+20h], 0      ; eax=0: read ok
  4037.         mov     dword [esp+14h], 64     ; ebx=size
  4038.         ret
  4039. .noroot:
  4040.         sub     esp, 200h
  4041.         call    convert_path
  4042.         jc      emul_path_err
  4043.         dec     eax
  4044.         jz      .ramdisk
  4045.         sub     al, 3
  4046.         jae     .harddisk
  4047.         add     esp, 200h
  4048.         jmp     not_supported_i40_fn
  4049. .ramdisk:
  4050.         lodsb
  4051.         cmp     al, 0
  4052.         jz      .give_dir1
  4053. ; must be {/RD | /RAMDISK}{/1 | /FIRST}/...
  4054.         lodsw
  4055.         cmp     ax, '1\'
  4056.         jz      .ramdisk_ok
  4057.         cmp     ax, '1'
  4058.         jz      .ramdisk_readdir
  4059.         cmp     ax, 'FI'
  4060.         jnz     emul_path_err
  4061.         lodsd
  4062.         cmp     eax, 'RST\'
  4063.         jz      .ramdisk_ok
  4064.         cmp     eax, 'RST'
  4065.         jnz     emul_path_err
  4066. .ramdisk_readdir:
  4067.         add     esp, 200h
  4068.         mov     esi, ramdisk_path
  4069.         push    0       ; read /rd/1
  4070.         call    read_directory
  4071.         mov     [esp+20h], eax
  4072.         mov     [esp+14h], ebx
  4073.         ret
  4074. .ramdisk_ok:
  4075. ; now esi points to filename, relative from ramdisk
  4076.         sub     esp, 200h
  4077.         mov     edi, esp
  4078.         push    ramdisk_path
  4079. .doit1:
  4080.         push    edi
  4081.         call    [lstrcpyA]
  4082.         cmp     byte [esi], 0
  4083.         setz    al
  4084.         push    eax
  4085.         push    esi
  4086.         push    edi
  4087.         call    [lstrcatA]
  4088.         pop     eax
  4089.         lea     esi, [esp+200h]
  4090.         xchg    esi, edi
  4091.         mov     ecx, 200h/4
  4092.         rep     movsd
  4093.         add     esp, 200h
  4094.         mov     esi, esp
  4095. ; now esi contains full Win32 name of requested file
  4096.         push    eax
  4097.         push    esi
  4098.         call    [GetFileAttributesA]
  4099.         inc     eax
  4100.         pop     ecx
  4101.         jz      emul_filenotfound
  4102.         dec     eax
  4103.         test    al, 10h         ; FILE_ATTRIBUTE_DIRECTORY
  4104.         jnz     .read_dir
  4105.         push    0
  4106.         push    0
  4107.         push    3
  4108.         push    0
  4109.         push    1
  4110.         push    80000000h
  4111.         push    esi
  4112.         call    [CreateFileA]
  4113.         inc     eax
  4114.         jz      emul_filenotfound
  4115.         dec     eax
  4116.         xchg    eax, esi
  4117.         mov     eax, [ebx+4]
  4118.         xor     edx, edx
  4119.         shld    edx, eax, 9
  4120.         shl     eax, 9
  4121.         push    edx
  4122.         mov     edi, esp
  4123.         push    0
  4124.         push    edi
  4125.         push    eax
  4126.         push    esi
  4127.         call    [SetFilePointer]
  4128.         push    0
  4129.         push    edi
  4130.         mov     eax, [ebx+8]
  4131.         shl     eax, 9
  4132. ; check limits
  4133.         mov     ecx, [limit]
  4134.         inc     ecx
  4135.         sub     ecx, [ebx+0xC]
  4136.         cmp     eax, ecx
  4137.         jbe     @f
  4138.         mov     eax, ecx
  4139. @@:     push    eax
  4140.         mov     eax, [ebx+0xC]
  4141.         add     eax, [base]
  4142.         push    eax
  4143.         push    esi
  4144.         call    [ReadFile]
  4145.         pop     eax
  4146.         push    0
  4147.         push    esi
  4148.         call    [GetFileSize]
  4149.         add     esp, 200h
  4150.         mov     [esp+14h], eax
  4151.         push    esi
  4152.         call    [CloseHandle]
  4153.         and     dword [esp+20h], 0
  4154.         ret
  4155. .read_dir:
  4156.         inc     ecx
  4157.         push    ecx     ; 2 for exclude '..', 1 for all
  4158.         call    read_directory
  4159.         add     esp, 200h
  4160.         mov     [esp+20h], eax
  4161.         mov     [esp+14h], ebx
  4162.         ret
  4163. .harddisk:
  4164.         movzx   edx, al
  4165.         lodsb
  4166.         test    al, al
  4167.         jnz     @f
  4168.         add     esp, 200h
  4169.         mov     dword [esp+20h], 10     ; access denied
  4170.         ret
  4171. @@:
  4172.         xor     ecx, ecx        ; partition
  4173. @@:
  4174.         lodsb
  4175.         cmp     al, '\'
  4176.         jz      @f
  4177.         cmp     al, 0
  4178.         jz      @f
  4179.         sub     al, '0'
  4180.         cmp     al, 9
  4181.         ja      emul_path_err
  4182.         imul    ecx, 10
  4183.         add     cl, al
  4184.         jmp     @b
  4185. @@:
  4186.         test    al, al
  4187.         jnz     @f
  4188.         dec     esi
  4189. @@:
  4190.         test    ecx, ecx
  4191.         jz      emul_path_err
  4192.         cmp     ecx, [hd_partitions_num+edx*4]
  4193.         jbe     @f
  4194.         add     esp, 200h
  4195.         mov     dword [esp+20h], 4      ; partition not defined
  4196.         ret
  4197. @@:
  4198.         sub     esp, 200h
  4199.         mov     edi, esp
  4200.         mov     eax, [hd_partitions_array+edx*4]
  4201.         dec     ecx
  4202.         shl     ecx, 9
  4203.         add     eax, ecx
  4204.         push    eax
  4205.         jmp     .doit1
  4206. .give_dir1:
  4207.         add     esp, 200h
  4208.         mov     esi, dir1
  4209.         mov     edi, [ebx+12]
  4210.         add     edi, [base]
  4211.         mov     ecx, 12
  4212.         push    ecx
  4213.         rep     movsb
  4214.         and     dword [esp+20h], 0      ; eax=0: read ok
  4215.         mov     dword [esp+14h], 32     ; ebx=size
  4216.         ret
  4217.  
  4218. emul_path_err:
  4219.         push    0
  4220.         push    aWarning
  4221.         push    aPathIsInvalid
  4222.         push    0
  4223.         call    [MessageBoxA]
  4224. emul_filenotfound:
  4225.         add     esp, 200h
  4226.         mov     dword [esp+20h], 5      ; file not found
  4227.         cmp     dword [ebx], 10h
  4228.         jnz     @f
  4229.         neg     dword [esp+20h]
  4230. @@:     ret
  4231.  
  4232. aWarning db 'Warning',0
  4233. aPathIsInvalid db 'Requested path is invalid',0
  4234.  
  4235. convert_path:
  4236.         lea     edi, [esp+4]
  4237.         push    ebx
  4238.         lea     ebx, [edi + 511]
  4239. .1:
  4240.         lodsb
  4241.         cmp     al, '/'
  4242.         jz      .1
  4243.         dec     esi
  4244.         mov     ecx, 11
  4245.         sub     ebx, ecx
  4246.         cmp     edi, ebx
  4247.         ja      .5
  4248.         mov     edx, edi
  4249.         mov     al, ' '
  4250.         add     ebx, ecx
  4251.         rep     stosb
  4252.         mov     edi, edx
  4253. .2:
  4254.         lodsb
  4255.         cmp     al, '/'
  4256.         jz      .3
  4257.         cmp     al, '.'
  4258.         jz      .4
  4259.         cmp     al, 0
  4260.         jz      .3
  4261.         cmp     edi, ebx
  4262.         jae     .5
  4263.         cmp     al, 'a'
  4264.         jb      @f
  4265.         cmp     al, 'z'
  4266.         ja      @f
  4267.         sub     al, ' '
  4268. @@:     stosb
  4269.         jmp     .2
  4270. .4:
  4271.         lea     edi, [edx+8]
  4272.         jmp     .2
  4273. .3:
  4274.         lea     edi, [edx+7]
  4275.         mov     ecx, 8
  4276.         std
  4277.         mov     al, ' '
  4278.         repz    scasb
  4279.         cld
  4280.         jz      .5
  4281.         mov     ecx, [edx+8]
  4282.         mov     [edi+3], ecx
  4283.         mov     byte [edi+2], '.'
  4284.         add     edi, 5
  4285.         mov     ecx, 3
  4286.         std
  4287.         repz    scasb
  4288.         cld
  4289.         jz      @f
  4290.         inc     edi
  4291.         inc     edi
  4292. @@:
  4293.         mov     al, '\'
  4294.         stosb
  4295.         cmp     byte [esi-1], 0
  4296.         jnz     .1
  4297.         mov     byte [edi-1], 0
  4298.         mov     esi, path_begin
  4299.         xor     eax, eax
  4300.         xor     ecx, ecx
  4301. .6:
  4302.         add     esi, ecx
  4303.         lodsb
  4304.         test    al, al
  4305.         jz      .5
  4306.         xchg    eax, ecx
  4307.         lodsb
  4308.         xchg    ecx, eax
  4309.         lea     edi, [esp+8]
  4310.         repz    cmpsb
  4311.         jnz     .6
  4312.         cmp     byte [edi], 0
  4313.         jz      .7
  4314.         cmp     byte [edi], '\'
  4315.         jnz     .6
  4316. .7:
  4317.         mov     esi, edi
  4318.         pop     ebx
  4319.         push    eax
  4320.         push    esi
  4321.         push    esi
  4322.         call    [OemToCharA]
  4323.         pop     eax
  4324. ; convert /hd to /hdx
  4325.         cmp     al, 3
  4326.         jnz     @f
  4327.         mov     eax, [shared_data]
  4328.         movzx   eax, [eax+shared_data_struc.hd_base]
  4329.         add     eax, 3
  4330. @@:
  4331.         clc
  4332.         ret
  4333. .5:
  4334.         stc
  4335.         pop     ebx
  4336.         ret
  4337.  
  4338. read_directory:
  4339. ; in: ebx->fileinfo block, esi->mask
  4340. ;     byte [esp+4] = 0 for /rd/1, 1 for normal call, 2 for exclude '..'
  4341. ; out: eax,ebx according to kernel fn58 read /rd/1
  4342.  
  4343. ; note that all returned values have been taken from kernel code
  4344.  
  4345.         mov     ecx, [ebx+8]    ; number of blocks
  4346.         mov     edi, [ebx+12]   ; output memory
  4347.         add     edi, [base]
  4348.         mov     ebx, [ebx+4]    ; start block
  4349. ; /rd/1 = 14 clusters
  4350.         cmp     byte [esp+4], 0
  4351.         jnz     .ok2
  4352.         cmp     ebx, 14         ; 14 clusters = root dir
  4353.         jae     .err1
  4354.         cmp     ecx, 14
  4355.         jbe     .ok1
  4356. .err1:
  4357.         mov     eax, 5          ; out of range
  4358.         or      ebx, -1
  4359.         ret     4
  4360. .ok1:
  4361.         lea     edx, [ebx+ecx]
  4362.         cmp     edx, 14
  4363.         pushfd
  4364.         jbe     @f
  4365.         sub     edx, 14
  4366.         sub     ecx, edx
  4367.         jz      .doret2
  4368. @@:
  4369.         popfd
  4370. .ok2:
  4371.         pushfd
  4372.         shl     ebx, 9
  4373.         shl     ecx, 9
  4374.         xor     edx, edx
  4375.         sub     esp, 200h
  4376.         pushad
  4377.         lea     edi, [esp+20h]
  4378.         push    esi
  4379.         call    [lstrlenA]
  4380.         mov     ecx, eax
  4381.         rep     movsb
  4382.         mov     al, '\'
  4383.         cmp     [edi-1], al
  4384.         jz      @f
  4385.         stosb
  4386. @@:
  4387.         mov     eax, '*.*'
  4388.         stosd
  4389.         popad
  4390.         push    0
  4391.         sub     esp, 400h
  4392. .loop:
  4393.         mov     esi, esp
  4394.         push    ecx
  4395.         lea     eax, [esi+404h]
  4396.         call    get_next_file
  4397. ; if no file => zero record
  4398.         test    eax, eax
  4399.         jnz     .still
  4400.         push    edi
  4401.         mov     edi, esi
  4402.         mov     ecx, 0x20/4
  4403.         rep     stosd
  4404.         pop     edi
  4405.         mov     al, 0x20
  4406.         add     [esi+400h], eax
  4407. .still:
  4408.         pop     ecx
  4409.         cmp     byte [esp+60Ch], 1
  4410.         jz      @f
  4411.         cmp     word [esi], '..'
  4412.         jz      .loop
  4413. @@:
  4414.         push    ecx
  4415.         cmp     ebx, eax
  4416.         jae     .skip
  4417.         add     esi, ebx
  4418.         mov     ecx, eax
  4419.         sub     ecx, ebx
  4420.         cmp     ecx, [esp]
  4421.         jb      @f
  4422.         mov     ecx, [esp]
  4423. @@:
  4424.         sub     [esp], ecx
  4425.         rep     movsb
  4426. .skip:
  4427.         sub     ebx, eax
  4428.         jae     @f
  4429.         xor     ebx, ebx
  4430. @@:
  4431.         pop     ecx
  4432.         test    ecx, ecx
  4433.         jnz     .loop
  4434.         call    done_find_file
  4435. .doret:
  4436.         add     esp, 400h
  4437.         pop     ecx
  4438.         add     esp, 200h
  4439. .doret2:
  4440.         xor     ebx, ebx
  4441.         xor     eax, eax
  4442.         cmp     byte [esp+8], 0
  4443.         jz      .check_rd1
  4444.         popfd
  4445. ;       cmp     edx, -1
  4446. ;       jz      .eof
  4447.         cmp     ecx, 0x200
  4448.         jae     .eof
  4449.         jmp     .ret
  4450. .check_rd1:
  4451.         popfd
  4452.         jb      .ret
  4453. .eof:
  4454.         mov     al, 6           ; EOF
  4455. .ret:   ret     4
  4456.  
  4457. get_next_file:
  4458. ; in: eax=mask, edx=hFindData, edx=0 or edx=-1, esi->buffer
  4459. ; out: buffer filled, eax=length
  4460.         cmp     edx, -1
  4461.         jnz     @f
  4462.         xor     eax, eax
  4463.         ret
  4464. @@:
  4465.         sub     esp, 0x140      ; sizeof(WIN32_FIND_DATA)
  4466.         pushad
  4467.         lea     ecx, [esp+0x20]
  4468.         push    ecx
  4469.         test    edx, edx
  4470.         jnz     .inited
  4471.         push    eax
  4472.         call    [FindFirstFileA]
  4473.         mov     edx, eax
  4474.         mov     [esp+0x14], edx
  4475.         inc     eax
  4476.         jmp     .cmn
  4477. .inited:
  4478.         push    edx
  4479.         call    [FindNextFileA]
  4480.         mov     edx, [esp+0x14]
  4481. .cmn:
  4482.         test    eax, eax
  4483.         jnz     .ok
  4484.         cmp     edx, -1
  4485.         jz      @f
  4486.         push    edx
  4487.         call    [FindClose]
  4488. @@:
  4489.         popad
  4490.         add     esp, 0x140
  4491.         xor     eax, eax
  4492.         or      edx, -1
  4493.         ret
  4494. .ok:
  4495.         popad
  4496. ; Long File Names are not supported yet
  4497. ; file name
  4498.         push    edi
  4499.         lea     edi, [esp+4+0x130]      ; WIN32_FIND_DATA.cAlternateFileName
  4500.         cmp     byte [edi], 0
  4501.         jnz     .shortname
  4502.         push    esi
  4503.         lea     esi, [esp+8+0x2C]       ; WIN32_FIND_DATA.cFileName
  4504.         push    edi
  4505. .l2s:
  4506.         lodsb
  4507.         cmp     al, 'a'
  4508.         jb      @f
  4509.         cmp     al, 'z'
  4510.         ja      @f
  4511.         sub     al, 0x20
  4512. @@:     stosb
  4513.         cmp     al, 0
  4514.         jnz     .l2s
  4515.         pop     edi esi
  4516. .shortname:
  4517.         pushad
  4518.         push    edi
  4519.         push    edi
  4520.         call    [CharToOemA]
  4521.         popad
  4522. ; file name
  4523.         mov     ecx, 10
  4524. @@:
  4525.         mov     byte [esi+ecx], ' '
  4526.         dec     ecx
  4527.         jns     @b
  4528.         inc     ecx
  4529. @@:
  4530.         cmp     byte [edi], '.'
  4531.         jnz     @f
  4532.         inc     edi
  4533.         mov     byte [esi+ecx], '.'
  4534.         inc     ecx
  4535.         jmp     @b
  4536. @@:
  4537.         mov     al, [edi]
  4538.         inc     edi
  4539.         cmp     al, 0
  4540.         jz      .namedone
  4541.         cmp     al, '.'
  4542.         jz      .dot
  4543.         mov     [esi+ecx], al
  4544.         inc     ecx
  4545.         jmp     @b
  4546. .dot:
  4547.         mov     cl, 8
  4548.         jmp     @b
  4549. .namedone:
  4550.         pop     edi
  4551. ; attributes
  4552.         mov     eax, [esp]      ; WIN32_FIND_DATA.dwFileAttributes
  4553.         and     al, 0x3F
  4554.         mov     [esi+11], al
  4555.         and     word [esi+12], 0
  4556. ; creation file and date
  4557.         pushad
  4558.         lea     eax, [esi+14]
  4559.         push    eax
  4560.         inc     eax
  4561.         inc     eax
  4562.         push    eax
  4563.         lea     eax, [esp+8+20h+4]
  4564.         push    eax
  4565.         call    [FileTimeToDosDateTime]
  4566. ; last access date
  4567.         lea     eax, [esp+1Ch]
  4568.         push    eax
  4569.         lea     eax, [esi+18]
  4570.         push    eax
  4571.         lea     eax, [esp+8+20h+0xC]
  4572.         push    eax
  4573.         call    [FileTimeToDosDateTime]
  4574. ; high word of cluster
  4575.         and     word [esi+20], 0
  4576. ; last write file and date
  4577.         lea     eax, [esi+22]
  4578.         push    eax
  4579.         inc     eax
  4580.         inc     eax
  4581.         push    eax
  4582.         lea     eax, [esp+8+20h+0x14]
  4583.         push    eax
  4584.         call    [FileTimeToDosDateTime]
  4585. ; low word of cluster
  4586.         mov     word [esi+26], 0xBAD    ; random value
  4587. ; file size
  4588.         popad
  4589.         mov     eax, [esp+0x20]
  4590.         mov     [esi+28], eax
  4591. ; return
  4592.         add     esp, 0x140
  4593.         mov     eax, 0x20
  4594.         ret
  4595.  
  4596. done_find_file:
  4597.         test    edx, edx
  4598.         jz      .ret
  4599.         cmp     edx, -1
  4600.         jz      .ret
  4601.         push    edx
  4602.         push    edx
  4603.         call    [FindClose]
  4604.         pop     edx
  4605. .ret:   ret
  4606.  
  4607. notify_run_prg:
  4608.         test    esi, esi
  4609.         jz      @f
  4610.         add     esi, [base]
  4611. @@:
  4612.         call    acquire_shared
  4613.         push    eax esi edi
  4614.         mov     esi, [ebp+tls.cur_dir]
  4615.         mov     edi, process_curdir
  4616. @@:
  4617.         lodsb
  4618.         stosb
  4619.         test    al, al
  4620.         jz      @f
  4621.         cmp     edi, process_curdir+4096
  4622.         jb      @b
  4623.         mov     byte [edi-1], 0
  4624. @@:
  4625.         pop     edi esi eax
  4626. server_run_prg:
  4627.         div     edx
  4628.         call    release_shared
  4629.         push    ecx
  4630.         push    -1
  4631.         push    ecx
  4632.         call    [WaitForSingleObject]
  4633.         call    [CloseHandle]
  4634. server_get_run_result:
  4635.         div     edx
  4636.         jecxz   .ret
  4637.         push    eax ecx edx
  4638.         push    24
  4639.         call    malloc
  4640.         mov     [eax+16], esi
  4641.         mov     [eax+20], edi
  4642.         mov     esi, [ebp + tls.debuggees]
  4643.         mov     [eax], esi
  4644.         mov     [ebp + tls.debuggees], eax
  4645.         pop     dword [eax+12]
  4646.         pop     dword [eax+8]
  4647.         pop     dword [eax+4]
  4648.         mov     eax, [eax+4]
  4649. .ret:
  4650.         ret
  4651.  
  4652. i40_ipc:
  4653.         dec     ebx
  4654.         jnz     @f
  4655. ; set IPC memory
  4656.         call    acquire_shared
  4657.         call    get_cur_slot_ptr
  4658.         add     ecx, [base]
  4659.         mov     [edi+4], ecx
  4660.         mov     [edi+8], edx
  4661.         call    release_shared
  4662.         and     dword [esp+20h], 0
  4663.         ret
  4664. @@:
  4665.         dec     ebx
  4666.         jnz     not_supported_i40_fn
  4667.         add     edx, [base]
  4668.         call    acquire_shared
  4669. server_send_ipc:
  4670.         div     edx
  4671.         call    release_shared
  4672.         test    eax, eax
  4673.         jnz     @f
  4674.         push    0
  4675.         push    0
  4676.         push    400h            ; WM_USER
  4677.         push    ecx
  4678.         call    [PostMessageA]
  4679.         xor     eax, eax
  4680. @@:
  4681.         mov     [esp+20h], eax
  4682.         ret
  4683.  
  4684. i40_direct_scr_access:
  4685.         cmp     [ColorDepth], 0
  4686.         jnz     @f
  4687.         push    10h
  4688.         push    0
  4689.         push    DSADisabled
  4690.         push    0
  4691.         call    [MessageBoxA]
  4692.         jmp     i40_terminate
  4693. @@:
  4694.         dec     ebx
  4695.         jz      .1
  4696.         dec     ebx
  4697.         jz      .2
  4698.         dec     ebx
  4699.         jz      .3
  4700.         jmp     not_supported_i40_fn
  4701. .1:
  4702.         call    get_screen_size
  4703.         add     ebx, 10001h
  4704.         mov     [esp+20h], ebx
  4705.         ret
  4706. .2:
  4707.         mov     eax, [ColorDepth]
  4708.         mov     [esp+20h], eax
  4709.         ret
  4710. .3:
  4711.         call    get_screen_size
  4712.         shr     ebx, 16
  4713.         lea     eax, [ebx+1]
  4714.         mul     [ColorDepth]
  4715.         shr     eax, 3
  4716.         add     eax, 3
  4717.         and     eax, not 3
  4718.         mov     [esp+20h], eax
  4719.         ret
  4720.  
  4721. i40_pci:
  4722.         mov     eax, [shared_data]
  4723.         cmp     [eax+shared_data_struc.pci_access_enabled], 0
  4724.         jnz     @f
  4725. .reterr:
  4726.         or      dword [esp+20h], -1     ; PCI access disabled
  4727.         ret
  4728. @@:
  4729.         cmp     bl, 2
  4730.         ja      .noinit
  4731.         cmp     [eax+shared_data_struc.pci_data_init], 0
  4732.         jnz     @f
  4733.         push    eax ebx
  4734.         call    pci_data_init
  4735.         pop     ebx eax
  4736. @@:
  4737.         test    bl, bl
  4738.         jnz     .not0
  4739.         xor     ecx, ecx
  4740.         cmp     [eax+shared_data_struc.pci_data_init], 1
  4741.         jnz     .unsupp0        ; emulate "unsupported" behavior
  4742.         mov     ch, [eax+shared_data_struc.pci_bios_mj]
  4743.         mov     cl, [eax+shared_data_struc.pci_bios_mn]
  4744. .unsupp0:
  4745.         mov     [esp+20h], ecx
  4746.         ret
  4747. .not0:
  4748.         dec     bl
  4749.         mov     ecx, ebx
  4750.         jnz     .not1
  4751.         cmp     [eax+shared_data_struc.pci_data_init], 1
  4752.         jnz     .unsupp1
  4753.         mov     cl, [eax+shared_data_struc.pci_bios_lb]
  4754. .unsupp1:
  4755. .retecx:
  4756.         mov     [esp+20h], ecx
  4757.         ret
  4758. .not1:
  4759.         test    [eax+shared_data_struc.pci_bios_pc], 1
  4760.         jnz     @b
  4761.         test    [eax+shared_data_struc.pci_bios_pc], 2
  4762.         jz      @b
  4763.         inc     ecx
  4764.         jmp     @b
  4765. .noinit:
  4766.         sub     bl, 4
  4767.         cmp     bl, 2
  4768.         ja      not_supported_i40_fn
  4769.         cmp     [bIs9x], 0
  4770.         jz      .read_nt
  4771.         mov     ah, 0xB1
  4772.         mov     al, bl
  4773.         add     al, 8
  4774.         mov     bl, ch
  4775.         movzx   di, cl
  4776.         mov     ecx, ebx
  4777.         call    [jmp_temp_int1A]
  4778.         jc      .reterr
  4779.         jmp     .retecx
  4780. .read_nt:
  4781.         push    cx
  4782.         push    bx
  4783.         mov     eax, esp
  4784.         push    ecx
  4785.         mov     ecx, esp
  4786.         push    4
  4787.         push    ecx
  4788.         push    4
  4789.         push    eax
  4790.         push    0x222004
  4791.         call    send_driver_request
  4792.         pop     ecx edx
  4793.         test    eax, eax
  4794.         jnz     .retecx
  4795.         push    30h
  4796.         push    aWarning
  4797.         push    DrvOpenErr
  4798.         push    0
  4799.         call    [MessageBoxA]
  4800.         jmp     .reterr
  4801.  
  4802. pci_data_init:
  4803.         call    acquire_shared
  4804.         cmp     [bIs9x], 0
  4805.         jz      .nt
  4806. ; On 9x systems, just do "int 1Ah" from 16-bit code
  4807.         mov     ax, 0xB101
  4808.         call    [jmp_temp_int1A]
  4809.         test    ah, ah
  4810.         jnz     .err
  4811.         cmp     edx, 'PCI '
  4812.         jnz     .err
  4813.         mov     edx, [shared_data]
  4814.         mov     [edx+shared_data_struc.pci_bios_mj], bh
  4815.         mov     [edx+shared_data_struc.pci_bios_mn], bl
  4816.         mov     [edx+shared_data_struc.pci_bios_lb], cl
  4817.         mov     [edx+shared_data_struc.pci_bios_pc], al
  4818.         mov     [edx+shared_data_struc.pci_data_init], 1
  4819.         jmp     .ok
  4820. .nt:
  4821. ; On NT systems, there is 'HKLM\HARDWARE\DESCRIPTION\System\MultifunctionAdapter' key,
  4822. ;   with some subkeys '0','1',..., which hold information on periphery.
  4823. ; Each PCI bus has its own subkey with 'Identifier'="PCI".
  4824. ; For first PCI bus 'Configuration Data' holds 4 additional bytes = info on PCI BIOS.
  4825. .loop:
  4826.         push    eax
  4827.         push    esp     ; phkResult
  4828.         push    1       ; samDesired = KEY_QUERY_VALUE
  4829.         push    0       ; ulOptions
  4830.         push    keymfa  ; lpSubKey
  4831.         push    80000002h       ; hKey = HKEY_LOCAL_MACHINE
  4832.         call    [RegOpenKeyExA]
  4833.         pop     esi     ; key handle
  4834.         test    eax, eax
  4835.         jnz     .err    ; subkeys are done, and we do not find required
  4836.         push    eax
  4837.         mov     eax, esp
  4838.         push    4
  4839.         push    esp     ; lpcbData
  4840.         push    eax     ; lpData
  4841.         push    0       ; lpType
  4842.         push    0       ; lpReserved
  4843.         push    aIdentifier     ; lpValueName
  4844.         push    esi     ; hKey
  4845.         call    [RegQueryValueExA]
  4846.         pop     ecx
  4847.         pop     edx
  4848.         test    eax, eax
  4849.         jnz     .cont
  4850.         cmp     ecx, 4
  4851.         jnz     .cont
  4852.         cmp     edx, 'PCI'
  4853.         jnz     .cont
  4854.         sub     esp, 24h
  4855.         mov     eax, esp
  4856.         push    24h
  4857.         push    esp
  4858.         push    eax
  4859.         push    0
  4860.         push    0
  4861.         push    aConfigurationData
  4862.         push    esi
  4863.         call    [RegQueryValueExA]
  4864.         pop     ecx
  4865.         test    eax, eax
  4866.         jnz     .err3
  4867.         cmp     ecx, 24h
  4868.         jnz     .err3
  4869.         mov     eax, [shared_data]
  4870.         add     esp, 20h
  4871.         pop     dword [eax+shared_data_struc.pci_bios_mj]
  4872.         dec     [eax+shared_data_struc.pci_bios_lb]
  4873.         js      .err2
  4874.         mov     [eax+shared_data_struc.pci_data_init], 1
  4875.         push    esi
  4876.         call    [RegCloseKey]
  4877. .ok:
  4878.         call    release_shared
  4879.         ret
  4880. .cont:
  4881.         push    esi
  4882.         call    [RegCloseKey]
  4883.         inc     [idxmfa]
  4884.         cmp     [idxmfa], '9'
  4885.         jbe     .loop
  4886.         jmp     .err
  4887. .err3:
  4888.         add     esp, 24h
  4889. .err2:
  4890.         push    esi
  4891.         call    [RegCloseKey]
  4892. .err:
  4893.         mov     eax, [shared_data]
  4894.         mov     [eax+shared_data_struc.pci_data_init], 2
  4895.         call    release_shared
  4896.         push    40h
  4897.         push    0
  4898.         push    aCannotGetPci
  4899.         push    0
  4900.         call    [MessageBoxA]
  4901.         ret
  4902.  
  4903. i40_debug_board:
  4904.         dec     ebx
  4905.         jz      .write
  4906.         dec     ebx
  4907.         jnz     not_supported_i40_fn
  4908. .read:
  4909.         call    acquire_shared
  4910.         mov     eax, [shared_data]
  4911.         mov     ecx, [eax+shared_data_struc.msg_board_count]
  4912.         test    ecx, ecx
  4913.         jnz     @f
  4914.         mov     [esp+20h], ecx  ; zero eax
  4915.         mov     [esp+14h], ecx  ; zero ebx
  4916.         jmp     .ret
  4917. @@:
  4918.         dec     [eax+shared_data_struc.msg_board_count]
  4919.         lea     edi, [eax+shared_data_struc.msg_board_data]
  4920.         lea     esi, [edi+1]
  4921.         movzx   edx, byte [edi]
  4922.         mov     [esp+20h], edx
  4923.         mov     dword [esp+14h], 1
  4924.         dec     ecx
  4925.         rep     movsb
  4926. .ret:
  4927.         jmp     release_shared
  4928. .write:
  4929.         call    acquire_shared
  4930.         mov     eax, [shared_data]
  4931.         mov     edx, [eax+shared_data_struc.msg_board_count]
  4932.         mov     [eax+shared_data_struc.msg_board_data+edx], cl
  4933.         inc     edx
  4934.         and     edx, 511
  4935.         mov     [eax+shared_data_struc.msg_board_count], edx
  4936.         jmp     .ret
  4937.  
  4938. i40_resize_app_memory:
  4939.         dec     ebx
  4940.         jnz     not_supported_i40_fn
  4941.         cmp     [heap_status], 0
  4942.         jz      @f
  4943.         push    30h
  4944.         push    aWarning
  4945.         push    aInvFn64Call
  4946.         push    0
  4947.         call    [MessageBoxA]
  4948.         mov     dword [esp+20h], 1
  4949.         ret
  4950. @@:
  4951.         cmp     [NumThreads], 1
  4952.         jnz     not_supported_i40_fn
  4953.         push    ecx
  4954.         push    40h     ; PAGE_EXECUTE_READWRITE
  4955.         push    1000h   ; MEM_COMMIT
  4956.         push    ecx
  4957.         push    0
  4958.         call    [VirtualAlloc]
  4959.         pop     ecx
  4960.         test    eax, eax
  4961.         jnz     .ok
  4962.         mov     dword [esp+0x20], 1
  4963.         ret
  4964. .ok:
  4965.         mov     edi, eax
  4966.         mov     esi, [base]
  4967.         push    ecx
  4968.         cmp     ecx, [limit]
  4969.         jbe     @f
  4970.         mov     ecx, [limit]
  4971.         inc     ecx
  4972. @@:
  4973.         push    eax
  4974.         rep     movsb
  4975.         call    acquire_shared
  4976.         call    get_cur_slot_ptr
  4977.         mov     ecx, [edi+4]
  4978.         jecxz   @f
  4979.         sub     ecx, [base]
  4980.         add     ecx, [esp]
  4981.         mov     [edi+4], ecx
  4982. @@:
  4983.         call    release_shared
  4984.         push    8000h   ; MEM_RELEASE
  4985.         push    0
  4986.         push    [base]
  4987.         call    [VirtualFree]
  4988.         pop     eax
  4989.         pop     ecx
  4990.         mov     [base], eax
  4991.         dec     ecx
  4992.         mov     [limit], ecx
  4993.         mov     [fn9limit], ecx
  4994.         call    get_cur_slot_ptr
  4995.         mov     [edi+24], ecx
  4996.         mov     esi, selector_data
  4997.         mov     [esi+2], ax
  4998.         shr     eax, 10h
  4999.         mov     [esi+4], al
  5000.         mov     [esi+7], ah
  5001.         shr     ecx, 0Ch
  5002.         mov     [esi], cx
  5003.         shr     ecx, 10h
  5004.         or      cl, 11000000b
  5005.         mov     [esi+6], cl
  5006.         mov     byte [esi+5], 11110010b
  5007.         lea     edi, [esi+8]
  5008.         movsd
  5009.         movsd
  5010.         mov     byte [esi+5], 11111010b
  5011.         cmp     [bIs9x], 0
  5012.         jnz     .9x
  5013.         push    dword [esi-4]
  5014.         push    dword [esi-8]
  5015.         push    17h
  5016.         push    dword [esi+4]
  5017.         push    dword [esi]
  5018.         push    0Fh
  5019.         call    [NtSetLdtEntries]
  5020.         mov     esi, ldterr
  5021.         test    eax, eax
  5022.         js      fail
  5023. .d:     and     dword [esp+20h], 0
  5024.         ret
  5025. .9x:
  5026.         mov     eax, sl0p
  5027.         call    CallRing0
  5028.         jmp     .d
  5029.  
  5030. convert_2bpp:
  5031.         mov     esi, edi
  5032.         add     esi, [base]
  5033.         movzx   eax, word [esp]
  5034.         pushad
  5035.         add     ecx, 7
  5036.         shr     ecx, 1
  5037.         and     ecx, not 3
  5038.         mul     ecx
  5039.         push    eax
  5040.         call    malloc
  5041.         mov     [esp+1Ch], eax
  5042.         popad
  5043.         push    eax edx esi
  5044.         mov     edi, eax
  5045.         movzx   eax, word [esp+12]
  5046.         mov     esi, ebx
  5047. .extloop:
  5048.         push    eax
  5049.         push    ecx
  5050. .innloop:
  5051.         lodsb
  5052.         mov     dl, al
  5053.         push    eax
  5054.         shr     al, 6
  5055.         shr     dl, 4
  5056.         shl     al, 4
  5057.         and     dl, 3
  5058.         or      al, dl
  5059.         stosb
  5060.         pop     eax
  5061.         mov     dl, al
  5062.         shl     al, 2
  5063.         and     dl, 3
  5064.         and     al, 0x30
  5065.         or      al, dl
  5066.         stosb
  5067.         sub     ecx, 4
  5068.         ja      .innloop
  5069.         test    edi, 3
  5070.         jz      @f
  5071.         stosw
  5072. @@:
  5073.         pop     ecx
  5074.         pop     eax
  5075.         add     esi, [esp+16+0Ch]
  5076.         dec     eax
  5077.         jnz     .extloop
  5078.         pop     esi edx edi
  5079.         jmp     pad_cont8
  5080.  
  5081. pad_bmp8:
  5082.         movzx   eax, word [esp]
  5083.         pushad
  5084.         add     ecx, 3
  5085.         and     ecx, not 3
  5086.         mul     ecx
  5087.         push    eax
  5088.         call    malloc
  5089.         mov     [esp+1Ch], eax
  5090.         popad
  5091.         push    eax esi
  5092.         mov     edi, eax
  5093.         movzx   eax, word [esp+8]
  5094.         mov     esi, ebx
  5095. .extloop:
  5096.         push    eax
  5097.         push    ecx
  5098.         mov     eax, ecx
  5099.         shr     ecx, 2
  5100.         rep     movsd
  5101.         mov     ecx, eax
  5102.         and     ecx, 3
  5103.         rep     movsb
  5104.         mov     ecx, eax
  5105.         neg     ecx
  5106.         and     ecx, 3
  5107.         mov     al, 0
  5108.         rep     stosb
  5109.         pop     ecx
  5110.         pop     eax
  5111.         add     esi, [esp+4*3+0Ch]
  5112.         dec     eax
  5113.         jnz     .extloop
  5114.         pop     esi edi
  5115.         jmp     pad_cont8
  5116.  
  5117. i40_putimage_palette:
  5118.         add     ebx, [base]
  5119.         push    ecx
  5120.         shr     ecx, 16
  5121.         cmp     esi, 1
  5122.         jz      .1
  5123.         cmp     esi, 4
  5124.         jz      .4
  5125.         cmp     esi, 8
  5126.         jz      .8
  5127.         cmp     esi, 15
  5128.         jz      .15
  5129.         cmp     esi, 16
  5130.         jz      .16
  5131.         cmp     esi, 32
  5132.         jz      .32
  5133.         cmp     esi, 2
  5134.         jz      convert_2bpp
  5135.         cmp     esi, 24
  5136.         jz      .24
  5137.         pop     ecx
  5138.         jmp     not_supported_i40_fn
  5139. .24:
  5140.         lea     ecx, [ecx*3]
  5141.         jmp     @f
  5142. .1:
  5143.         add     ecx, 7
  5144.         shr     ecx, 3
  5145.         jmp     @f
  5146. .2:
  5147.         add     ecx, 3
  5148.         shr     ecx, 2
  5149.         jmp     @f
  5150. .4:
  5151.         inc     ecx
  5152.         shr     ecx, 1
  5153.         jmp     @f
  5154. .32:
  5155.         add     ecx, ecx
  5156. .15:
  5157. .16:
  5158.         add     ecx, ecx
  5159. .8:
  5160. @@:
  5161.         add     edi, [base]
  5162.         mov     esi, edi
  5163. ; Windows requires that all scanlines are DWORD-padded
  5164.         mov     edi, ebx
  5165.         test    cl, 3
  5166.         jnz     pad_bmp8
  5167.         cmp     dword [esp+10h], 0
  5168.         jnz     pad_bmp8
  5169. pad_cont8:
  5170.         pop     ecx
  5171.         mov     eax, [esp+8]
  5172. ; palette
  5173.         sub     esp, 256*4
  5174.         push    ecx edi
  5175.         lea     edi, [esp+8]
  5176.         cmp     al, 8
  5177.         jnz     @f
  5178.         mov     ecx, 256
  5179.         rep     movsd
  5180. @@:
  5181.         cmp     al, 4
  5182.         jnz     @f
  5183.         mov     ecx, 16
  5184.         rep     movsd
  5185. @@:
  5186.         cmp     al, 2
  5187.         jnz     @f
  5188.         movsd
  5189.         movsd
  5190.         movsd
  5191.         movsd
  5192.         add     eax, eax
  5193. @@:
  5194.         cmp     al, 1
  5195.         jnz     @f
  5196.         movsd
  5197.         movsd
  5198. @@:
  5199.         cmp     al, 16
  5200.         jnz     @f
  5201.         mov     dword [edi+0], 0xF800
  5202.         mov     dword [edi+4], 0x07E0
  5203.         mov     dword [edi+8], 0x001F
  5204. @@:
  5205.         pop     edi ecx
  5206.         xor     esi, esi
  5207. ; BITMAPINFO
  5208.         push    esi     ; biClrImportant
  5209.         push    esi     ; biClrUsed
  5210.         push    esi     ; biYPelsPerMeter
  5211.         push    esi     ; biXPelsPerMeter
  5212.         push    esi     ; biSizeImage
  5213.         cmp     al, 15
  5214.         jnz     .no15
  5215.         push    esi     ; biCompression
  5216.         push    100001h ; biPlanes, biBitCount
  5217.         jmp     @f
  5218. .no15:
  5219.         cmp     al, 16
  5220.         jnz     .no16
  5221.         push    3       ; biCompression
  5222.         push    100001h ; biPlanes, biBitCount
  5223.         jmp     @f
  5224. .no16:
  5225.         push    esi     ; biCompression
  5226. ;       push    80001h  ; biPlanes, biBitCount
  5227.         shl     eax, 16
  5228.         inc     eax
  5229.         push    eax     ; biPlanes, biBitCount
  5230. @@:
  5231.         movzx   eax, cx
  5232.         neg     eax
  5233.         push    eax     ; biHeight
  5234.         neg     eax
  5235.         shr     ecx, 10h
  5236.         push    ecx     ; biWidth
  5237.         push    40      ; biSize
  5238.         push    ebx
  5239.         lea     ebx, [esp+4]
  5240. ; SetDIBitsToDevice
  5241.         push    esi     ; fuColorUse = DIB_RGB_COLORS
  5242.         push    ebx     ; lpbmi
  5243.         push    edi     ; lpvBits
  5244.         push    eax     ; cScanLines
  5245.         dec     eax
  5246.         push    eax     ; uStartScan
  5247.         push    eax     ; YSrc
  5248.         inc     eax
  5249.         push    esi     ; XSrc
  5250.         push    eax     ; dwHeight
  5251.         push    ecx     ; dwWidth
  5252.         movzx   ecx, dx
  5253.         add     ecx, [ebp+tls.client_top]
  5254.         push    ecx     ; YDest
  5255.         shr     edx, 10h
  5256.         add     edx, [ebp+tls.client_left]
  5257.         push    edx     ; XDest
  5258.         push    [ebp+tls.hWnd]
  5259.         call    [GetDC]
  5260.         xchg    eax, ebx
  5261.         push    ebx     ; hdc
  5262.         call    [SetDIBitsToDevice]
  5263.         xchg    eax, ebx
  5264.         pop     ebx
  5265.         add     esp, 40+256*4
  5266.         push    eax
  5267.         push    [ebp+tls.hWnd]
  5268.         call    [ReleaseDC]
  5269.         cmp     edi, ebx
  5270.         jz      @f
  5271.         push    edi
  5272.         call    free
  5273. @@:
  5274.         ret
  5275.  
  5276. i40_process_def:
  5277.         dec     ebx
  5278.         jz      .setmode
  5279.         dec     ebx
  5280.         jz      .getmode
  5281.         dec     ebx
  5282.         jz      .get_control
  5283.         dec     ebx
  5284.         jz      .add_hotkey
  5285.         dec     ebx
  5286.         jz      .del_hotkey
  5287.         jmp     not_supported_i40_fn
  5288. .setmode:
  5289.         mov     [ebp+tls.usescancode], cl
  5290.         ret
  5291. .getmode:
  5292.         movzx   eax, [ebp+tls.usescancode]
  5293.         mov     [esp+20h], eax
  5294.         ret
  5295. .get_control:
  5296.         mov     esi, .vkeycodes
  5297.         mov     edi, 1
  5298. .gcloop:
  5299.         xor     eax, eax
  5300.         lodsb
  5301.         push    eax
  5302.         call    [GetAsyncKeyState]
  5303.         test    ax, ax
  5304.         jns     @f
  5305.         or      ebx, edi
  5306. @@:
  5307.         add     edi, edi
  5308.         cmp     esi, .vkeycodes_end
  5309.         jb      .gcloop
  5310.         mov     [esp+20h], ebx
  5311.         ret
  5312. .add_hotkey:
  5313. .del_hotkey:
  5314.         and     dword [esp+20h], 0
  5315.         ret
  5316. .vkeycodes:
  5317.         db      0xA0    ; VK_LSHIFT
  5318.         db      0xA1    ; VK_RSHIFT
  5319.         db      0xA2    ; VK_LCONTROL
  5320.         db      0xA3    ; VK_RCONTROL
  5321.         db      0xA4    ; VK_LMENU
  5322.         db      0xA5    ; VK_RMENU
  5323.         db      0x14    ; VK_CAPITAL
  5324.         db      0x90    ; VK_NUMLOCK
  5325.         db      0x91    ; VK_SCROLL
  5326. .vkeycodes_end:
  5327.  
  5328. i40_move_resize:
  5329.         cmp     ebx, -1
  5330.         jnz     @f
  5331.         movzx   ebx, [ebp+tls.x_start]
  5332. @@:     cmp     ecx, -1
  5333.         jnz     @f
  5334.         movzx   ecx, [ebp+tls.y_start]
  5335. @@:     cmp     edx, -1
  5336.         jnz     @f
  5337.         movzx   edx, [ebp+tls.x_size]
  5338.         dec     edx
  5339. @@:     cmp     esi, -1
  5340.         jnz     @f
  5341.         movzx   esi, [ebp+tls.y_size]
  5342.         dec     esi
  5343. @@:
  5344.         inc     edx
  5345.         mov     [ebp+tls.x_start], bx
  5346.         inc     esi
  5347.         mov     [ebp+tls.y_start], cx
  5348.         mov     [ebp+tls.x_size], dx
  5349.         mov     [ebp+tls.y_size], si
  5350.         push    1
  5351.         push    esi
  5352.         push    edx
  5353.         push    ecx
  5354.         push    ebx
  5355.         push    [ebp+tls.hWnd]
  5356.         call    [MoveWindow]
  5357.         push    0
  5358.         push    0
  5359.         push    [ebp+tls.hWnd]
  5360.         call    [InvalidateRect]
  5361.         ret
  5362.  
  5363. i40_sys_services:
  5364.         cmp     ebx, 3
  5365.         jnz     .not3
  5366.         mov     esi, [shared_data]
  5367.         cmp     [esi+shared_data_struc.bAllowReadMSR], 0
  5368.         mov     edi, aReadMSRDisabled
  5369.         jz      .err
  5370.         cmp     [bIs9x], 0
  5371.         jz      .nt
  5372.         mov     ecx, edx
  5373.         mov     eax, rdmsrp
  5374.         call    CallRing0
  5375.         test    ebx, ebx
  5376.         jnz     .nomsr
  5377.         mov     [esp+20h], eax
  5378.         mov     [esp+14h], edx
  5379.         ret
  5380. .nt:
  5381.         push    0
  5382.         push    edx
  5383.         push    edx
  5384.         mov     eax, esp
  5385.         push    9
  5386.         push    eax
  5387.         push    4
  5388.         push    eax
  5389.         push    0x222000
  5390.         call    send_driver_request
  5391.         pop     ecx
  5392.         pop     edx
  5393.         pop     esi
  5394.         mov     edi, DrvOpenErr
  5395.         test    eax, eax
  5396.         jz      .err
  5397.         test    esi, esi
  5398.         jnz     .nomsr
  5399.         mov     [esp+20h], ecx
  5400.         mov     [esp+14h], edx
  5401.         ret
  5402. .err:
  5403.         push    30h
  5404.         push    aWarning
  5405.         push    edi
  5406.         push    0
  5407.         call    [MessageBoxA]
  5408.         and     dword [esp+20h], 0
  5409.         and     dword [esp+14h], 0
  5410.         ret
  5411. .nomsr:
  5412.         push    10h
  5413.         push    0
  5414.         push    aNoMsr
  5415.         push    0
  5416.         call    [MessageBoxA]
  5417.         jmp     i40_terminate
  5418. .not3:
  5419.         cmp     ebx, 11
  5420.         jnz     .not11
  5421. .initialize_heap:
  5422. ; initialize heap
  5423.         cmp     [heap_status], 0
  5424.         jz      .create_heap
  5425. @@:
  5426.         cmp     [heap_status], 1
  5427.         jnz     @f
  5428.         push    5
  5429.         call    [Sleep]
  5430.         jmp     @b
  5431. @@:
  5432. .heap_ret_size:
  5433.         mov     eax, 0x5FC00000-0x1000
  5434.         sub     eax, [heap_start]
  5435.         mov     [esp+20h], eax
  5436.         ret
  5437. .create_heap:
  5438.         cmp     [NumThreads], 1
  5439.         jnz     not_supported_i40_fn
  5440.         mov     [heap_status], 1
  5441.         xor     ebx, ebx
  5442. ; reserve needed big region
  5443.         mov     esi, 0x40000000
  5444. @@:
  5445.         push    40h     ; PAGE_EXECUTE_READWRITE
  5446.         push    2000h   ; MEM_RESERVE
  5447.         push    esi
  5448.         push    ebx
  5449.         call    [VirtualAlloc]
  5450.         test    eax, eax
  5451.         jnz     @f
  5452.         shr     esi, 1
  5453.         cmp     esi, 0x01000000
  5454.         jae     @b
  5455. .nomem_fatal:
  5456.         xor     ebx, ebx
  5457.         mov     esi, memerr
  5458.         jmp     fail
  5459. @@:
  5460.         mov     [heap_region_size], esi
  5461.         push    eax
  5462.         mov     ecx, [limit]
  5463.         inc     ecx
  5464.         push    40h     ; PAGE_EXECUTE_READWRITE
  5465.         push    1000h   ; MEM_COMMIT
  5466.         push    ecx
  5467.         push    eax
  5468.         call    [VirtualAlloc]
  5469.         test    eax, eax
  5470.         jz      .nomem_fatal
  5471.         mov     esi, [base]
  5472.         pop     edi
  5473.         push    edi
  5474.         mov     edi, eax
  5475.         mov     ecx, [limit]
  5476.         inc     ecx
  5477.         rep     movsb
  5478.         push    8000h   ; MEM_RELEASE
  5479.         push    ebx
  5480.         push    [base]
  5481.         call    [VirtualFree]
  5482.         pop     eax
  5483.         mov     [base], eax
  5484.         mov     ecx, [heap_region_size]
  5485.         dec     ecx
  5486.         mov     [limit], ecx
  5487.         mov     esi, selector_data
  5488.         mov     [esi+2], ax
  5489.         shr     eax, 10h
  5490.         mov     [esi+4], al
  5491.         mov     [esi+7], ah
  5492.         shr     ecx, 0Ch
  5493.         mov     [esi], cx
  5494.         shr     ecx, 10h
  5495.         or      cl, 11000000b
  5496.         mov     [esi+6], cl
  5497.         mov     byte [esi+5], 11110010b
  5498.         lea     edi, [esi+8]
  5499.         movsd
  5500.         movsd
  5501.         mov     byte [esi+5], 11111010b
  5502.         cmp     [bIs9x], bl
  5503.         jnz     .9x
  5504.         push    dword [esi-4]
  5505.         push    dword [esi-8]
  5506.         push    17h
  5507.         push    dword [esi+4]
  5508.         push    dword [esi]
  5509.         push    0Fh
  5510.         call    [NtSetLdtEntries]
  5511.         mov     esi, ldterr
  5512.         test    eax, eax
  5513.         js      fail
  5514.         jmp     .heap_created
  5515. .9x:
  5516.         mov     eax, sl0p
  5517.         call    CallRing0
  5518.         xor     ebx, ebx
  5519. .heap_created:
  5520.         mov     eax, [fn9limit]
  5521.         or      eax, 0xFFF
  5522.         inc     eax
  5523.         mov     [heap_start], eax
  5524.         mov     eax, [heap_region_size]
  5525.         sub     eax, [heap_start]
  5526.         shr     eax, 10
  5527.         call    malloc_big
  5528.         mov     [heap_control_block], eax
  5529.         test    eax, eax
  5530.         jz      .nomem_fatal
  5531.         mov     ecx, [heap_region_size]
  5532.         sub     ecx, [heap_start]
  5533.         or      ecx, 4
  5534.         mov     [eax], ecx
  5535.         push    heap_critical_sec
  5536.         call    [InitializeCriticalSection]
  5537.         mov     [heap_status], 2
  5538.         jmp     .heap_ret_size
  5539. .not11:
  5540.         cmp     ebx, 12
  5541.         jnz     .not12
  5542. ; allocate memory block in heap
  5543. .allocate_heap:
  5544.         cmp     [heap_status], 0
  5545.         jnz     @f
  5546.         push    30h
  5547.         push    aWarning
  5548.         push    aHeapNotInited
  5549.         push    0
  5550.         call    [MessageBoxA]
  5551.         and     dword [esp+20h], 0
  5552.         ret
  5553. @@:
  5554.         lea     edi, [ecx+0x1FFF]
  5555.         and     edi, not 0xFFF
  5556. @@:
  5557.         cmp     [heap_status], 1
  5558.         jnz     @f
  5559.         push    5
  5560.         call    [Sleep]
  5561.         jmp     @b
  5562. @@:
  5563.         push    heap_critical_sec
  5564.         call    [EnterCriticalSection]
  5565.         xor     esi, esi
  5566.         mov     ecx, [heap_region_size]
  5567.         sub     ecx, [heap_start]
  5568.         mov     edx, [heap_control_block]
  5569. .l_0:
  5570.         cmp     esi, ecx
  5571.         jae     .m_exit
  5572.         mov     ebx, esi
  5573.         shr     ebx, 12
  5574.         mov     eax, [edx+ebx*4]
  5575.         test    al, 4
  5576.         jz      .test_used
  5577.         and     eax, not 0xFFF
  5578.         cmp     eax, edi
  5579.         jb      .m_next
  5580.         jz      @f
  5581.         push    esi
  5582.         add     esi, edi
  5583.         sub     eax, edi
  5584.         or      al, 4
  5585.         shr     esi, 12
  5586.         mov     [edx+esi*4], eax
  5587.         pop     esi
  5588.         mov     eax, edi
  5589. @@:
  5590.         or      al, 8
  5591.         mov     [edx+ebx*4], eax
  5592.         mov     eax, [heap_start]
  5593.         lea     eax, [eax+esi+0x1000]
  5594.         push    eax
  5595.         sub     edi, 0x1000
  5596. ; now do real allocate at eax with size edi
  5597.         push    40h     ; PAGE_EXECUTE_READWRITE
  5598.         push    1000h   ; MEM_COMMIT
  5599.         push    edi
  5600.         add     eax, [base]
  5601.         push    eax
  5602.         call    [VirtualAlloc]
  5603.         test    eax, eax
  5604.         jz      .nomem_fatal
  5605.         jmp     .allocated
  5606. .m_next:
  5607.         add     esi, eax
  5608.         jmp     .l_0
  5609. .test_used:
  5610.         test    al, 8
  5611.         jnz     @f
  5612. .fail_internal:
  5613.         xor     ebx, ebx
  5614.         mov     esi, aInternalError
  5615.         jmp     fail
  5616. @@:
  5617.         and     eax, not 0xFFF
  5618.         jmp     .m_next
  5619. .m_exit:
  5620.         push    0
  5621. .allocated:
  5622.         push    heap_critical_sec
  5623.         call    [LeaveCriticalSection]
  5624.         cmp     dword [esp], 0
  5625.         jnz     @f
  5626.         push    30h
  5627.         push    aWarning
  5628.         push    aMallocFailed
  5629.         push    0
  5630.         call    [MessageBoxA]
  5631. @@:
  5632.         pop     eax
  5633.         mov     [esp+20h], eax
  5634.         ret
  5635. .not12:
  5636.         cmp     ebx, 13
  5637.         jnz     .not13
  5638. ; free memory block in heap
  5639. .free_heap:
  5640.         cmp     [heap_status], 0
  5641.         jnz     @f
  5642.         push    30h
  5643.         push    aWarning
  5644.         push    aHeapNotInited
  5645.         push    0
  5646.         call    [MessageBoxA]
  5647.         and     dword [esp+20h], 0
  5648.         ret
  5649. @@:
  5650.         test    ecx, ecx
  5651.         jnz     @f
  5652. ; free(NULL) is OK
  5653.         mov     dword [esp+20h], 1
  5654.         ret
  5655. @@:
  5656.         mov     esi, ecx
  5657.         cmp     [heap_status], 1
  5658.         jnz     @f
  5659.         push    5
  5660.         call    [Sleep]
  5661.         jmp     @b
  5662. @@:
  5663.         cmp     esi, [heap_region_size]
  5664.         jae     .inv_exit
  5665.         sub     esi, [heap_start]
  5666.         jb      .inv_exit
  5667.         cmp     esi, 0x1000
  5668.         jae     @f
  5669. .inv_exit:
  5670.         mov     dword [esp+20h], 1
  5671. .inv_exit_cmn:
  5672.         push    30h
  5673.         push    aWarning
  5674.         push    aFreeInvalid
  5675.         push    0
  5676.         call    [MessageBoxA]
  5677.         ret
  5678. .inv_exit_realloc:
  5679.         and     dword [esp+20h], 0
  5680.         jmp     .inv_exit_cmn
  5681. @@:
  5682.         push    heap_critical_sec
  5683.         call    [EnterCriticalSection]
  5684.         mov     eax, esi
  5685.         shr     esi, 12
  5686.         dec     esi
  5687.         mov     edx, [heap_control_block]
  5688.         test    byte [edx+esi*4], 10h
  5689.         jnz     .inv_exit_realloc
  5690.         test    byte [edx+esi*4], 8
  5691.         jz      .inv_wrn
  5692.         test    eax, 0xFFF
  5693.         jz      @f
  5694. .inv_wrn:
  5695.         push    edx
  5696.         push    30h
  5697.         push    aWarning
  5698.         push    aFreeInvalid
  5699.         push    0
  5700.         call    [MessageBoxA]
  5701.         pop     edx
  5702. @@:
  5703.         mov     eax, [edx+esi*4]
  5704.         test    al, 8
  5705.         jz      .freed
  5706.         push    edx
  5707.         and     eax, not 0xFFF
  5708.         push    0x4000          ; MEM_DECOMMIT
  5709.         sub     eax, 0x1000
  5710.         push    eax
  5711.         lea     eax, [esi+1]
  5712.         shl     eax, 12
  5713.         add     eax, [heap_start]
  5714.         add     eax, [base]
  5715.         push    eax
  5716.         call    [VirtualFree]
  5717.         pop     edx
  5718.         mov     eax, [edx+esi*4]
  5719.         and     eax, not 0xFFF
  5720.         push    eax
  5721.         or      al, 4
  5722.         mov     [edx+esi*4], al
  5723.         shr     eax, 12
  5724.         add     eax, esi
  5725.         test    byte [edx+eax*4], 4
  5726.         jz      @f
  5727.         xor     ecx, ecx
  5728.         xchg    ecx, [edx+eax*4]
  5729.         and     ecx, not 0xFFF
  5730.         add     [edx+esi*4], ecx
  5731.         add     [esp], ecx
  5732. @@:
  5733.         pop     eax
  5734.         test    esi, esi
  5735.         jz      .freed
  5736.         xor     edi, edi
  5737. .findprev:
  5738.         cmp     edi, esi
  5739.         jz      .foundprev
  5740.         mov     ecx, edi
  5741.         mov     ebx, [edx+ecx*4]
  5742.         shr     ebx, 12
  5743.         add     edi, ebx
  5744.         jmp     .findprev
  5745. .foundprev:
  5746.         test    byte [edx+ecx*4], 4
  5747.         jz      .freed
  5748.         and     dword [edx+esi*4], 0
  5749.         add     [edx+ecx*4], eax
  5750. .freed:
  5751.         push    heap_critical_sec
  5752.         call    [LeaveCriticalSection]
  5753.         mov     dword [esp+20h], 1
  5754.         ret
  5755. .not13:
  5756.         cmp     ebx, 16
  5757.         jnz     .not16
  5758.         add     ecx, [base]
  5759.         mov     esi, ecx
  5760.         push    esi
  5761.         push    aSound
  5762.         call    [lstrcmpA]
  5763.         test    eax, eax
  5764.         jnz     @f
  5765.         and     dword [esp+20h], 0
  5766.         ret
  5767. @@:
  5768.         push    esi
  5769.         push    aInfinity
  5770.         call    [lstrcmpA]
  5771.         test    eax, eax
  5772.         jnz     @f
  5773.         and     dword [esp+20h], 0
  5774.         ret
  5775. @@:
  5776.         push    10h
  5777.         push    0
  5778.         push    aUnknownDriver
  5779.         push    0
  5780.         call    [MessageBoxA]
  5781.         and     dword [esp+20h], 0
  5782.         ret
  5783. .not16:
  5784.         cmp     ebx, 19
  5785.         jnz     .not19
  5786. ; load DLL
  5787.         sub     esp, 40
  5788.         mov     eax, esp
  5789.         sub     eax, [base]
  5790.         push    0
  5791.         push    0
  5792.         push    eax
  5793.         push    0
  5794.         push    0
  5795.         push    0
  5796.         push    5
  5797.         mov     ebx, esp
  5798.         mov     [ebx+21], ecx
  5799.         pushad
  5800.         call    i40_file_system_lfn.noadd
  5801.         popad
  5802.         test    eax, eax
  5803.         jz      @f
  5804. .err1:
  5805.         add     esp, 28+40
  5806.         and     dword [esp+20h], 0
  5807.         ret
  5808. @@:
  5809.         pop     eax
  5810.         push    0
  5811.         mov     ebx, esp
  5812.         cmp     dword [ebx+28+36], 0
  5813.         jnz     .err1
  5814.         mov     eax, [ebx+28+32]
  5815.         mov     [ebx+12], eax
  5816.         call    malloc_big
  5817.         test    eax, eax
  5818.         jnz     @f
  5819. .nomem_dll:
  5820.         push    10h
  5821.         push    memerr
  5822.         push    aCannotLoadDll
  5823.         push    0
  5824.         call    [MessageBoxA]
  5825.         jmp     .err1
  5826. @@:
  5827.         sub     eax, [base]
  5828.         mov     [ebx+16], eax
  5829.         push    ebx
  5830.         pushad
  5831.         call    i40_file_system_lfn.noadd
  5832.         popad
  5833.         pop     ebx
  5834.         test    eax, eax
  5835.         jnz     .err1
  5836.         mov     eax, [ebx+16]
  5837.         add     eax, [base]
  5838.         mov     [ebx+16], eax
  5839.         cmp     dword [eax], 'KPCK'
  5840.         jnz     .notpacked
  5841.         mov     eax, [eax+4]
  5842.         call    malloc_big
  5843.         test    eax, eax
  5844.         jnz     @f
  5845.         push    dword [ebx+16]
  5846.         call    free_big
  5847.         jmp     .nomem_dll
  5848. @@:
  5849.         push    eax
  5850.         push    eax
  5851.         push    dword [ebx+16]
  5852.         call    unpack
  5853.         push    dword [ebx+16]
  5854.         call    free_big
  5855.         pop     eax
  5856.         mov     [ebx+16], eax
  5857. .notpacked:
  5858.         add     esp, 28+40
  5859. ; eax contains pointer to loaded file
  5860.         mov     ebx, eax
  5861. ; 1. Calculate image size & allocate memory for image
  5862.         movzx   ecx, word [eax+2]
  5863.         lea     edx, [eax+20+16]
  5864.         xor     esi, esi
  5865. @@:
  5866.         add     esi, [edx]
  5867.         add     esi, 0xF
  5868.         and     esi, not 0xF
  5869.         add     edx, 40
  5870.         loop    @b
  5871.         pushad
  5872.         call    .initialize_heap
  5873.         mov     ecx, [esp+4]
  5874.         call    .allocate_heap
  5875.         popad
  5876.         test    eax, eax
  5877.         jnz     @f
  5878. ; no memory in user space, user has already been notified
  5879.         and     dword [esp+20h], 0
  5880.         ret
  5881. @@:
  5882. ; eax = base addr in user space
  5883. ; ebx = pointer to loaded DLL data
  5884. ; 2. Copy image data
  5885.         mov     edi, eax
  5886.         add     edi, [base]
  5887.         movzx   ecx, word [ebx+2]
  5888.         lea     edx, [ebx+20+16]
  5889. @@:
  5890.         mov     [edx+12-16], edi
  5891.         mov     esi, [edx+20-16]
  5892.         test    esi, esi
  5893.         jnz     .copy
  5894.         add     edi, [edx+16-16]
  5895.         jmp     .next
  5896. .copy:
  5897.         add     esi, ebx
  5898.         push    ecx
  5899.         mov     ecx, [edx+16-16]
  5900.         rep     movsb
  5901.         pop     ecx
  5902. .next:
  5903.         add     edi, 0xF
  5904.         and     edi, not 0xF
  5905.         add     edx, 40
  5906.         loop    @b
  5907. ; 3. Fixup COFF symbols
  5908. ; symbols table = ebx + [ebx+8]
  5909. ; strings ptr = (symbols table)+[ebx+12]*18
  5910.         mov     ecx, [ebx+12]
  5911.         mov     edx, ebx
  5912.         add     edx, [ebx+8]
  5913.         lea     esi, [ecx+ecx*8]
  5914.         lea     esi, [edx+esi*2]
  5915. .fix_sym:
  5916.         movsx   edi, word [edx+12]
  5917.         test    edi, edi
  5918.         jnz     .internal
  5919. ; current implementation does not support exports
  5920. ; this is kernel limitation, not my
  5921.         and     dword [edx+8], 0
  5922.         jmp     .next_sym
  5923. .internal:
  5924.         js      .next_sym
  5925.         dec     edi
  5926.         shl     edi, 3
  5927.         lea     edi, [edi+edi*4]
  5928.         mov     edi, [ebx+20+edi+12]
  5929.         sub     edi, [base]
  5930.         add     [edx+8], edi
  5931. .next_sym:
  5932.         add     edx, 18
  5933.         loop    .fix_sym
  5934. ; 4. Fixup COFF relocations
  5935.         movzx   ecx, word [ebx+2]
  5936.         lea     esi, [ebx+20]
  5937. .fix_sec_reloc:
  5938.         mov     edi, [esi+24]
  5939.         add     edi, ebx
  5940.         push    ecx
  5941.         movzx   ecx, word [esi+32]
  5942.         jecxz   .next_sec_reloc
  5943. .fix_reloc:
  5944.         mov     edx, [edi+4]
  5945.         lea     edx, [edx+edx*8]
  5946.         lea     edx, [ebx+edx*2]
  5947.         add     edx, [ebx+8]
  5948.         mov     edx, [edx+8]
  5949.         mov     eax, [edi]
  5950.         add     eax, [esi+12]
  5951.         cmp     word [edi+8], 6
  5952.         jz      .dir32
  5953.         cmp     word [edi+8], 20
  5954.         jz      .rel32
  5955.         pushad
  5956.         push    30h
  5957.         push    aWarning
  5958.         push    aUnknownReloc
  5959.         push    0
  5960.         call    [MessageBoxA]
  5961.         popad
  5962.         jmp     .next_reloc
  5963. .rel32:
  5964.         sub     edx, eax
  5965.         sub     edx, 4
  5966. .dir32:
  5967.         add     [eax], edx
  5968. .next_reloc:
  5969.         add     edi, 10
  5970.         loop    .fix_reloc
  5971. .next_sec_reloc:
  5972.         add     esi, 40
  5973.         pop     ecx
  5974.         loop    .fix_sec_reloc
  5975. ; 5. Lookup 'EXPORTS' symbol
  5976.         mov     eax, ebx
  5977.         add     eax, [ebx+8]
  5978.         mov     ecx, [ebx+12]
  5979. .find_exp:
  5980.         cmp     dword [eax], 'EXPO'
  5981.         jnz     @f
  5982.         cmp     dword [eax+4], 'RTS'
  5983.         jz      .found_exp
  5984. @@:
  5985.         add     eax, 18
  5986.         loop    .find_exp
  5987. ; 5b. Lookup '_EXPORTS' symbol
  5988.         mov     eax, ebx
  5989.         add     eax, [ebx+8]
  5990.         mov     ecx, [ebx+12]
  5991. .find__exp:
  5992.         cmp     dword [eax], '_EXP'
  5993.         jnz     @f
  5994.         cmp     dword [eax+4], 'ORTS'
  5995.         jz      .found_exp
  5996. @@:
  5997.         add     eax, 18
  5998.         loop    .find__exp
  5999.         push    30h
  6000.         push    aWarning
  6001.         push    aExportsNotFound
  6002.         push    0
  6003.         call    [MessageBoxA]
  6004.         xor     eax, eax
  6005.         jmp     @f
  6006. .found_exp:
  6007.         mov     eax, [eax+8]
  6008. @@:
  6009.         mov     [esp+20h], eax
  6010.         push    ebx
  6011.         call    free_big
  6012.         ret
  6013. .not19:
  6014.         cmp     ebx, 20
  6015.         jnz     .not20
  6016. ; reallocate memory block in heap
  6017.         cmp     [heap_status], 0
  6018.         jnz     @f
  6019.         push    30h
  6020.         push    aWarning
  6021.         push    aHeapNotInited
  6022.         push    0
  6023.         call    [MessageBoxA]
  6024.         and     dword [esp+20h], 0
  6025.         ret
  6026. @@:
  6027.         cmp     [heap_status], 1
  6028.         jnz     @f
  6029.         push    ecx edx
  6030.         push    5
  6031.         call    [Sleep]
  6032.         pop     edx ecx
  6033.         jmp     @b
  6034. @@:
  6035. ; realloc(NULL,sz) = malloc(sz)
  6036.         test    edx, edx
  6037.         jz      .allocate_heap
  6038.         cmp     edx, [heap_region_size]
  6039.         jae     .inv_exit_realloc
  6040.         sub     edx, [heap_start]
  6041.         jb      .inv_exit_realloc
  6042.         cmp     edx, 0x1000
  6043.         jb      .inv_exit_realloc
  6044.         push    ecx edx
  6045.         push    heap_critical_sec
  6046.         call    [EnterCriticalSection]
  6047.         pop     edx ecx
  6048.         test    edx, 0xFFF
  6049.         jnz     @f
  6050.         shr     edx, 12
  6051.         dec     edx
  6052.         mov     esi, [heap_control_block]
  6053.         mov     eax, [esi+edx*4]
  6054.         test    al, 10h
  6055.         jnz     @f
  6056.         test    al, 8
  6057.         jnz     .realloc_valid
  6058. @@:
  6059.         push    heap_critical_sec
  6060.         call    [LeaveCriticalSection]
  6061.         jmp     .inv_exit_realloc
  6062. .realloc_valid:
  6063.         add     ecx, 0x1FFF
  6064.         and     ecx, not 0xFFF
  6065.         and     eax, not 0xFFF
  6066.         cmp     eax, ecx
  6067.         jb      .realloc_inc
  6068.         jz      .realloc_done
  6069.         sub     eax, ecx
  6070.         push    eax ecx edx
  6071.         push    0x4000  ; MEM_DECOMMIT
  6072.         push    eax
  6073.         shl     edx, 12
  6074.         add     edx, ecx
  6075.         add     edx, [heap_start]
  6076.         add     edx, [base]
  6077.         push    edx
  6078.         call    [VirtualFree]
  6079.         test    eax, eax
  6080.         jz      $
  6081.         pop     edx ecx
  6082.         mov     eax, ecx
  6083.         cmp     eax, 0x1000
  6084.         jz      .realloc_freeall
  6085.         or      al, 8
  6086.         mov     [esi+edx*4], eax
  6087.         pop     eax
  6088.         shr     ecx, 12
  6089.         add     edx, ecx
  6090.         mov     edi, [heap_region_size]
  6091.         sub     edi, [heap_start]
  6092.         shr     edi, 12
  6093.         push    edx
  6094.         mov     edx, eax
  6095.         shr     edx, 12
  6096.         add     edx, [esp]
  6097. @@:
  6098.         cmp     edx, edi
  6099.         jae     @f
  6100.         mov     ecx, [esi+edx*4]
  6101.         test    cl, 4
  6102.         jz      @f
  6103.         and     dword [esi+edx*4], 0
  6104.         and     ecx, not 0xFFF
  6105.         add     eax, ecx
  6106.         shr     ecx, 12
  6107.         add     edx, ecx
  6108.         jmp     @b
  6109. @@:
  6110.         pop     edx
  6111.         or      al, 4
  6112.         mov     [esi+edx*4], eax
  6113. .realloc_done:
  6114.         push    heap_critical_sec
  6115.         call    [LeaveCriticalSection]
  6116.         mov     eax, [esp+18h]
  6117.         mov     [esp+20h], eax
  6118.         ret
  6119. .realloc_freeall:
  6120.         pop     eax
  6121.         xor     ecx, ecx
  6122.         xor     eax, eax
  6123. @@:
  6124.         cmp     ecx, edx
  6125.         jae     @f
  6126.         mov     eax, [esi+ecx*4]
  6127.         shr     eax, 12
  6128.         add     ecx, eax
  6129.         jmp     @b
  6130. @@:
  6131.         test    eax, eax
  6132.         jz      @f
  6133.         sub     ecx, eax
  6134.         test    byte [esi+ecx*4], 4
  6135.         jz      @f
  6136.         xor     eax, eax
  6137.         xchg    eax, [esi+edx*4]
  6138.         and     eax, not 0xFFF
  6139.         add     [esi+ecx*4], eax
  6140.         mov     edx, ecx
  6141. @@:
  6142.         mov     eax, [esi+edx*4]
  6143.         shr     eax, 12
  6144.         add     eax, edx
  6145.         mov     edi, [heap_region_size]
  6146.         sub     edi, [heap_start]
  6147.         shr     edi, 12
  6148.         cmp     eax, edi
  6149.         jae     @f
  6150.         test    byte [esi+eax*4], 4
  6151.         jz      @f
  6152.         xor     ecx, ecx
  6153.         xchg    ecx, [esi+eax*4]
  6154.         and     ecx, not 0xFFF
  6155.         add     [esi+edx*4], ecx
  6156. @@:
  6157.         mov     byte [esi+edx*4], 4
  6158.         push    heap_critical_sec
  6159.         call    [LeaveCriticalSection]
  6160.         and     dword [esp+20h], 0
  6161.         ret
  6162. .realloc_inc:
  6163.         mov     edi, [heap_region_size]
  6164.         sub     edi, [heap_start]
  6165.         shr     edi, 12
  6166.         push    eax
  6167.         shr     eax, 12
  6168.         add     eax, edx
  6169.         cmp     eax, edi
  6170.         jae     .realloc_realloc
  6171.         mov     eax, [esi+eax*4]
  6172.         test    al, 4
  6173.         jz      .realloc_realloc
  6174.         and     eax, not 0xFFF
  6175.         add     eax, [esp]
  6176.         sub     eax, ecx
  6177.         jb      .realloc_realloc
  6178. ; reallocate in place
  6179.         jz      @f
  6180.         push    ecx edx
  6181.         shr     ecx, 12
  6182.         add     edx, ecx
  6183.         or      al, 4
  6184.         mov     [esi+edx*4], eax
  6185.         pop     edx ecx
  6186. @@:
  6187.         pop     eax
  6188.         sub     ecx, eax
  6189.         add     [esi+edx*4], ecx
  6190.         mov     edi, edx
  6191.         inc     edi
  6192.         shl     edi, 12
  6193.         add     edi, [heap_start]
  6194.         mov     [esp+20h], edi
  6195.         push    40h     ; PAGE_EXECUTE_READWRITE
  6196.         push    1000h   ; MEM_COMMIT
  6197.         push    ecx
  6198.         shl     edx, 12
  6199.         add     edx, eax
  6200.         add     edx, [heap_start]
  6201.         add     edx, [base]
  6202.         push    edx
  6203.         call    [VirtualAlloc]
  6204.         test    eax, eax
  6205.         jz      .nomem_fatal
  6206.         push    heap_critical_sec
  6207.         call    [LeaveCriticalSection]
  6208.         ret
  6209. .realloc_realloc:
  6210.         pop     esi
  6211.         push    ecx
  6212.         push    heap_critical_sec
  6213.         call    [LeaveCriticalSection]
  6214.         pop     ecx
  6215.         pushad
  6216.         call    .allocate_heap
  6217.         popad
  6218.         mov     [esp+20h], eax
  6219.         mov     edi, eax
  6220.         test    edi, edi
  6221.         jnz     @f
  6222.         ret
  6223. @@:
  6224.         lea     ecx, [esi-0x1000]
  6225.         mov     esi, [esp+18h]
  6226.         push    esi
  6227.         add     esi, [base]
  6228.         add     edi, [base]
  6229.         shr     ecx, 2
  6230.         rep     movsd
  6231.         pop     ecx
  6232.         pushad
  6233.         call    .free_heap
  6234.         popad
  6235.         ret
  6236. .not20:
  6237.         cmp     ebx, 22
  6238.         jnz     .not22
  6239. ; open/create named memory area
  6240.         test    esi, not 0xD
  6241.         jnz     not_supported_i40_fn
  6242.         add     ecx, [base]
  6243.         mov     edi, ecx
  6244. ..server_create_shmem:
  6245.         div     edx
  6246.         test    eax, eax
  6247.         jz      @f
  6248. .shmem.err:
  6249.         and     dword [esp+20h], 0
  6250.         mov     [esp+18h], eax
  6251.         ret
  6252. @@:
  6253.         pushad
  6254.         call    .allocate_heap
  6255.         popad
  6256.         test    eax, eax
  6257.         jnz     @f
  6258.         mov     ecx, edi
  6259.         call    ..server_destroy_shmem
  6260.         mov     al, 30
  6261.         jmp     .shmem.err
  6262. @@:
  6263.         mov     [esp+20h], eax
  6264.         mov     [esp+18h], edx
  6265.         mov     ecx, eax
  6266.         sub     ecx, [heap_start]
  6267.         shr     ecx, 12
  6268.         mov     edx, [heap_control_block]
  6269.         or      byte [edx+(ecx-1)*4], 10h
  6270.         add     eax, [base]
  6271. ..server_notify_shmem:
  6272.         div     edx
  6273.         push    eax
  6274.         push    esp
  6275.         push    1       ; PAGE_NOACCESS
  6276.         push    ecx
  6277.         push    eax
  6278.         call    [VirtualProtect]
  6279.         pop     eax
  6280.         ret
  6281. .not22:
  6282.         cmp     ebx, 23
  6283.         jnz     not_supported_i40_fn
  6284.         add     ecx, [base]
  6285.         call    ..server_destroy_shmem
  6286.         jecxz   @f
  6287.         sub     ecx, [base]
  6288.         mov     eax, ecx
  6289.         sub     eax, [heap_start]
  6290.         shr     eax, 12
  6291.         mov     edx, [heap_control_block]
  6292.         and     byte [edx+(eax-1)*4], not 10h
  6293.         pushad
  6294.         call    .free_heap
  6295.         popad
  6296.         jmp     .ret22
  6297. @@:
  6298.         push    30h
  6299.         push    aWarning
  6300.         push    aCannotDestroyShMem
  6301.         push    0
  6302.         call    [MessageBoxA]
  6303. .ret22:
  6304.         mov     dword [esp+20h], 0x87654320
  6305.         ret
  6306. ..server_destroy_shmem:
  6307.         div     edx
  6308.         ret
  6309.  
  6310. include 'unpacker.inc'
  6311.  
  6312. align 4
  6313. debug_services_table:
  6314.         dd      i40_debug_services.set_event_data
  6315.         dd      i40_debug_services.getcontext
  6316.         dd      i40_debug_services.setcontext
  6317.         dd      not_supported_i40_fn    ;i40_debug_services.detach
  6318.         dd      i40_debug_services.suspend
  6319.         dd      i40_debug_services.resume
  6320.         dd      i40_debug_services.read_process_memory
  6321.         dd      i40_debug_services.write_process_memory
  6322.         dd      i40_debug_services.terminate
  6323. ;       dd      i40_debug_services.set_drx
  6324. .size = ($ - debug_services_table)/4
  6325.  
  6326. i40_debug_services:
  6327.         cmp     ebx, debug_services_table.size
  6328.         jae     not_supported_i40_fn
  6329.         jmp     dword [debug_services_table+ebx*4]
  6330. .set_event_data:
  6331.         call    get_cur_slot_ptr
  6332. ; atomic operation, no synchronization required
  6333.         mov     [edi+shared_data_struc.debugger_mem-shared_data_struc.threads], ecx
  6334.         ret
  6335. .m1pop2:
  6336.         pop     eax
  6337. .m1pop:
  6338.         pop     eax
  6339. .m1:
  6340.         or      dword [esp+20h], -1
  6341. .ret:
  6342.         ret
  6343. .getcontext:
  6344.         call    find_debuggee
  6345.         test    ebx, ebx
  6346.         jz      .ret
  6347.         cmp     edx, 40
  6348.         jnz     .ret
  6349.         push    dword [ebx+12]
  6350.         call    suspend_safe
  6351.         sub     esp, 0xB2*4
  6352.         push    1000Fh
  6353.         mov     edi, esp
  6354.         push    edi
  6355.         push    dword [ebx+12]
  6356.         call    [GetThreadContext]
  6357.         add     esi, [base]
  6358.         mov     ax, cs
  6359.         cmp     word [edi+0xBC], ax
  6360.         jz      .context_win
  6361.         mov     eax, [edi+0xB8]
  6362.         mov     [esi], eax
  6363.         mov     eax, [edi+0xC0]
  6364.         mov     [esi+4], eax
  6365.         mov     eax, [edi+0xB0]
  6366.         mov     [esi+8], eax
  6367.         mov     eax, [edi+0xAC]
  6368.         mov     [esi+12], eax
  6369.         mov     eax, [edi+0xA8]
  6370.         mov     [esi+16], eax
  6371.         mov     eax, [edi+0xA4]
  6372.         mov     [esi+20], eax
  6373.         mov     eax, [edi+0xC4]
  6374.         mov     [esi+24], eax
  6375.         mov     eax, [edi+0xB4]
  6376.         mov     [esi+28], eax
  6377.         mov     eax, [edi+0xA0]
  6378.         mov     [esi+32], eax
  6379.         mov     eax, [edi+0x9C]
  6380.         mov     [esi+36], eax
  6381.         jmp     .gotcontext
  6382. .context_win:
  6383.         mov     eax, [ebx+16]
  6384.         add     eax, tls._esp
  6385.         sub     esp, 2Ch
  6386.         mov     ecx, esp
  6387.         push    0
  6388.         push    esp
  6389.         push    8
  6390.         push    ecx
  6391.         push    eax
  6392.         push    dword [ebx+8]
  6393.         call    [ReadProcessMemory]
  6394.         pop     eax
  6395.         pop     dword [esi+24]
  6396.         pop     dword [esi]
  6397.         mov     ecx, esp
  6398.         push    0
  6399.         push    esp
  6400.         push    24h
  6401.         push    ecx
  6402.         push    dword [ebx+20]
  6403.         push    dword [ebx+8]
  6404.         call    [ReadProcessMemory]
  6405.         pop     eax
  6406.         pop     dword [esi+36]
  6407.         pop     dword [esi+32]
  6408.         pop     dword [esi+28]
  6409.         pop     eax
  6410.         pop     dword [esi+20]
  6411.         pop     dword [esi+16]
  6412.         pop     dword [esi+12]
  6413.         pop     dword [esi+8]
  6414.         pop     dword [esi+4]
  6415. .gotcontext:
  6416.         add     esp, 0xB3*4
  6417. @@:
  6418.         push    dword [ebx+12]
  6419.         call    [ResumeThread]
  6420.         ret
  6421. .resume:
  6422.         call    find_debuggee
  6423.         test    ebx, ebx
  6424.         jz      .ret
  6425.         jmp     @b
  6426. .suspend:
  6427.         call    find_debuggee
  6428.         test    ebx, ebx
  6429.         jz      .ret
  6430.         push    dword [ebx+12]
  6431.         call    suspend_safe
  6432.         ret
  6433. .setcontext:
  6434.         call    find_debuggee
  6435.         test    ebx, ebx
  6436.         jz      .ret
  6437.         cmp     edx, 40
  6438.         jnz     .ret
  6439.         push    dword [ebx+12]
  6440.         call    suspend_safe
  6441.         sub     esp, 0xB2*4
  6442.         push    1000Fh
  6443.         mov     edi, esp
  6444.         push    edi
  6445.         push    dword [ebx+12]
  6446.         call    [GetThreadContext]
  6447.         add     esi, [base]
  6448.         mov     ax, cs
  6449.         cmp     word [edi+0xBC], ax
  6450.         jz      .context_win_set
  6451.         lodsd
  6452.         mov     [edi+0xB8], eax
  6453.         lodsd
  6454.         mov     [edi+0xC0], eax
  6455.         lodsd
  6456.         mov     [edi+0xB0], eax
  6457.         lodsd
  6458.         mov     [edi+0xAC], eax
  6459.         lodsd
  6460.         mov     [edi+0xA8], eax
  6461.         lodsd
  6462.         mov     [edi+0xA4], eax
  6463.         lodsd
  6464.         mov     [edi+0xC4], eax
  6465.         lodsd
  6466.         mov     [edi+0xB4], eax
  6467.         lodsd
  6468.         mov     [edi+0xA0], eax
  6469.         lodsd
  6470.         mov     [edi+0x9C], eax
  6471.         push    edi
  6472.         push    dword [ebx+12]
  6473.         call    [SetThreadContext]
  6474.         jmp     .setcontextdone
  6475. .context_win_set:
  6476.         mov     edx, [ebx+16]
  6477.         add     edx, tls._esp
  6478.         lodsd
  6479.         push    eax
  6480.         push    dword [esi-4+24]
  6481.         mov     ecx, esp
  6482.         push    0
  6483.         push    esp
  6484.         push    8
  6485.         push    ecx
  6486.         push    eax
  6487.         push    dword [ebx+8]
  6488.         call    [WriteProcessMemory]
  6489.         pop     eax
  6490.         pop     eax
  6491.         pop     eax
  6492.         push    9
  6493.         pop     ecx
  6494. @@:
  6495.         lodsd
  6496.         push    eax
  6497.         loop    @b
  6498.         mov     ecx, esp
  6499.         push    0
  6500.         push    esp
  6501.         push    24h
  6502.         push    ecx
  6503.         push    dword [ebx+20]
  6504.         push    dword [ebx+8]
  6505.         call    [WriteProcessMemory]
  6506.         add     esp, 4+24h
  6507. .setcontextdone:
  6508.         add     esp, 0xB3*4
  6509.         push    dword [ebx+12]
  6510.         call    [ResumeThread]
  6511.         ret
  6512. .write_process_memory:
  6513.         push    [WriteProcessMemory]
  6514.         jmp     @f
  6515. .read_process_memory:
  6516.         push    [ReadProcessMemory]
  6517. @@:
  6518.         call    find_debuggee
  6519.         test    ebx, ebx
  6520.         jz      .m1pop
  6521. ; get base and limit of target process
  6522.         push    eax
  6523.         push    eax
  6524.         mov     eax, esp
  6525.         push    edx
  6526.         push    0
  6527.         push    esp
  6528.         push    8
  6529.         push    eax
  6530.         push    base
  6531.         push    dword [ebx+8]
  6532.         call    [ReadProcessMemory]
  6533.         pop     eax
  6534.         pop     edx
  6535.         pop     ecx     ; ecx = [base] for target process
  6536.         cmp     eax, 8
  6537.         jnz     .m1pop2
  6538.         pop     eax     ; eax = [limit] for target process
  6539.         push    edx
  6540.         inc     eax
  6541.         add     edx, esi
  6542.         sub     edx, eax
  6543.         jc      @f
  6544.         sub     dword [esp], edx
  6545.         jnc     @f
  6546.         and     dword [esp], 0
  6547. @@:
  6548.         add     esi, ecx
  6549.         pop     edx
  6550.         pop     ecx
  6551.         xor     eax, eax
  6552.         test    edx, edx
  6553.         jz      @f
  6554.         push    -1
  6555.         push    esp
  6556.         add     edi, [base]
  6557.         push    edx
  6558.         push    edi
  6559.         push    esi
  6560.         push    dword [ebx+8]
  6561.         call    ecx
  6562.         pop     eax
  6563. @@:
  6564.         mov     [esp+20h], eax
  6565.         ret
  6566. .terminate:
  6567.         call    find_debuggee
  6568.         test    ebx, ebx
  6569.         jnz     i40_sys_service.kill
  6570.         ret
  6571. .set_drx:
  6572.         sub     esp, 0xB2*4
  6573.         push    1001Fh
  6574.         call    find_debuggee
  6575.         test    ebx, ebx
  6576.         jz      .ret1
  6577.         mov     edi, esp
  6578.         push    ecx edx
  6579.         push    edi
  6580.         push    dword [ebx+12]
  6581.         call    [GetThreadContext]
  6582.         pop     edx ecx
  6583.         test    dh, dh
  6584.         js      .clear
  6585. ; set hardware breakpoint, dl=index (0..3), dh=(length*4)+(condition), esi=address
  6586.         cmp     esi, 0x80000000
  6587.         jae     .ret1
  6588.         cmp     dl, 4
  6589.         jae     .ret1
  6590.         test    dh, 0xF0
  6591.         jnz     .ret1
  6592.         mov     al, dh
  6593.         and     al, 3
  6594.         cmp     al, 2
  6595.         jz      .ret1
  6596.         movzx   eax, dh
  6597.         shr     al, 2
  6598.         cmp     al, 2
  6599.         jz      .ret1
  6600.         test    esi, eax
  6601.         jnz     .ret1
  6602.         push    edx
  6603.         push    0
  6604.         mov     eax, esp
  6605.         push    eax
  6606.         push    esp
  6607.         push    4
  6608.         push    eax
  6609.         push    base
  6610.         push    dword [ebx+8]
  6611.         call    [ReadProcessMemory]
  6612.         pop     eax
  6613.         pop     eax
  6614.         pop     edx
  6615.         add     esi, eax
  6616.         or      byte [edi+18h+1], 3     ; set GE and LE flags
  6617.         movzx   eax, dh
  6618.         movzx   ecx, dl
  6619.         add     ecx, ecx
  6620.         bts     dword [edi+18h], ecx    ; set L<i> flag
  6621.         mov     [edi+4+ecx*2], esi      ; set DR<i>
  6622.         shl     eax, cl
  6623.         mov     edx, 0xF
  6624.         shl     edx, cl
  6625.         not     edx
  6626.         and     [edi+18h+2], dx
  6627.         or      [edi+18h+2], ax         ; set R/W and LEN fields
  6628.         jmp     .set_and_ret
  6629. .clear:
  6630.         movzx   ecx, dl
  6631.         add     ecx, ecx
  6632.         btr     dword [edi+18h], ecx    ; clear L<i> flag
  6633. .set_and_ret:
  6634.         push    edi
  6635.         push    dword [ebx+12]
  6636.         call    [SetThreadContext]
  6637.         add     esp, 0xB3*4
  6638.         and     dword [esp+20h], 0
  6639.         ret
  6640. .ret1:
  6641.         add     esp, 0xB3*4
  6642.         push    30h
  6643.         push    aWarning
  6644.         push    aInvalidDataForDR
  6645.         push    0
  6646.         call    [MessageBoxA]
  6647.         mov     dword [esp+20h], 1
  6648.         ret
  6649.  
  6650. find_debuggee:
  6651.         lea     ebx, [ebp+tls.debuggees]
  6652. @@:
  6653.         mov     ebx, [ebx]
  6654.         test    ebx, ebx
  6655.         jz      @f
  6656.         cmp     dword [ebx+4], ecx
  6657.         jnz     @b
  6658. @@:
  6659.         ret
  6660.  
  6661. suspend_safe:
  6662.         xchg    ebx, [esp+4]
  6663. .redo:
  6664.         push    ebx
  6665.         call    [SuspendThread]
  6666.         sub     esp, 0xB2*4
  6667.         push    1000Fh
  6668.         push    esp
  6669.         push    ebx
  6670.         call    [GetThreadContext]
  6671.         mov     ax, cs
  6672.         cmp     word [context+0xBC], ax
  6673.         jnz     .ok
  6674.         cmp     dword [context+0xB8], i40_nt
  6675.         jz      .wait
  6676.         cmp     dword [context+0xB8], i40_9x
  6677.         jb      .test2
  6678.         cmp     dword [context+0xB8], safe_to_suspend
  6679.         ja      .test2
  6680. .wait:
  6681.         add     esp, 0xB3*4
  6682.         push    ebx
  6683.         call    [ResumeThread]
  6684.         push    50
  6685.         call    [Sleep]
  6686.         jmp     .redo
  6687. .test2:
  6688.         cmp     dword [context+0xB8], i40_done
  6689.         jb      .ok
  6690.         cmp     dword [context+0xB8], not_supported_i40_fn
  6691.         jb      .wait
  6692. .ok:
  6693.         add     esp, 0xB3*4
  6694.         xchg    ebx, [esp+4]
  6695.         ret     4
  6696.  
  6697. rootdirs:
  6698.         db      2,'rd'
  6699.         dd      fs_OnRamdisk
  6700.         dd      fs_NextRamdisk
  6701.         db      7,'ramdisk'
  6702.         dd      fs_OnRamdisk
  6703.         dd      fs_NextRamdisk
  6704. ;        db      2,'fd'
  6705. ;        dd      fs_OnFloppy
  6706. ;        dd      fs_NextFloppy
  6707. ;        db      10,'floppydisk'
  6708. ;        dd      fs_OnFloppy
  6709. ;        dd      fs_NextFloppy
  6710.         db      3,'hd0'
  6711.         dd      fs_OnHd0
  6712.         dd      fs_NextHd0
  6713.         db      3,'hd1'
  6714.         dd      fs_OnHd1
  6715.         dd      fs_NextHd1
  6716.         db      3,'hd2'
  6717.         dd      fs_OnHd2
  6718.         dd      fs_NextHd2
  6719.         db      3,'hd3'
  6720.         dd      fs_OnHd3
  6721.         dd      fs_NextHd3
  6722.         db      0
  6723.  
  6724. virtual_root_query:
  6725.         dd      fs_HasRamdisk
  6726.         db      'rd',0
  6727. ;        dd      fs_HasFloppy
  6728. ;        db      'fd',0
  6729.         dd      fs_HasHd0
  6730.         db      'hd0',0
  6731.         dd      fs_HasHd1
  6732.         db      'hd1',0
  6733.         dd      fs_HasHd2
  6734.         db      'hd2',0
  6735.         dd      fs_HasHd3
  6736.         db      'hd3',0
  6737.         dd      0
  6738.  
  6739. i40_file_system_lfn:
  6740.         add     ebx, [base]
  6741. .noadd:
  6742.         push    0
  6743. ; parse file name
  6744.         lea     esi, [ebx+20]
  6745.         lodsb
  6746.         test    al, al
  6747.         jnz     @f
  6748.         mov     esi, [esi]
  6749.         add     esi, [base]
  6750.         lodsb
  6751.         jmp     @f
  6752. .parse:
  6753.         push    edi
  6754.         lodsb
  6755. @@:
  6756.         push    0
  6757.         cmp     al, '/'
  6758.         jz      @f
  6759.         dec     esi
  6760.         mov     dword [esp], esi
  6761.         mov     esi, [ebp+tls.cur_dir]
  6762.         inc     esi
  6763.         jmp     @f
  6764. .notfound:
  6765.         pop     eax
  6766.         pop     eax
  6767.         test    eax, eax
  6768.         mov     eax, 5                  ; file not found
  6769.         jnz     .notfound_retparse
  6770.         mov     [esp+20h], eax
  6771. .notfound_retparse:
  6772.         ret
  6773. @@:
  6774.         mov     eax, [esi]
  6775.         or      eax, '   '
  6776.         cmp     eax, 'sys'
  6777.         jz      .sys1
  6778.         cmp     eax, 'sys/'
  6779.         jnz     @f
  6780.         inc     esi
  6781. .sys1:
  6782.         mov     eax, ramdisk_path
  6783.         add     esi, 3
  6784.         jmp     fs_common
  6785. @@:
  6786.         cmp     byte [esi], 0
  6787.         jz      .rootdir
  6788.         mov     edi, rootdirs-8
  6789.         xor     ecx, ecx
  6790.         push    esi
  6791. .scan1:
  6792.         pop     esi
  6793.         add     edi, ecx
  6794.         scasd
  6795.         scasd
  6796.         mov     cl, byte [edi]
  6797.         jecxz   .notfound
  6798.         inc     edi
  6799.         push    esi
  6800. @@:
  6801.         lodsb
  6802.         or      al, 20h
  6803.         scasb
  6804.         loopz   @b
  6805.         jnz     .scan1
  6806.         lodsb
  6807.         cmp     al, '/'
  6808.         jz      .found1
  6809.         test    al, al
  6810.         jnz     .scan1
  6811.         pop     eax
  6812. ; directory /xxx
  6813. .maindir:
  6814.         pop     eax
  6815.         pop     eax
  6816.         test    eax, eax
  6817.         jz      @f
  6818. .parse_access_denied:
  6819.         mov     eax, 10         ; access denied
  6820.         ret
  6821. @@:
  6822.         cmp     dword [ebx], 1
  6823.         jnz     .access_denied
  6824.         xor     eax, eax
  6825.         push    dword [ebx+12]
  6826.         mov     edx, [ebx+16]
  6827.         add     edx, [base]
  6828.         push    dword [ebx+4]   ; first block
  6829.         mov     ebx, [ebx+8]    ; flags
  6830.         and     ebx, 1
  6831.         mov     esi, [edi+4]
  6832. ; [esp]=first block, [esp+4]=number of blocks, ebx=flags, edx=return area, esi='Next' handler
  6833.         mov     edi, edx
  6834.         mov     ecx, 32/4
  6835.         rep     stosd
  6836.         mov     byte [edx], 1   ; version
  6837. .maindir_loop:
  6838.         call    esi
  6839.         jc      .maindir_done
  6840.         inc     dword [edx+8]
  6841.         dec     dword [esp]
  6842.         jns     .maindir_loop
  6843.         dec     dword [esp+4]
  6844.         js      .maindir_loop
  6845.         inc     dword [edx+4]
  6846.         mov     dword [edi], 0x10       ; attributes: folder
  6847.         mov     dword [edi+4], ebx      ; name type
  6848.         push    eax
  6849.         xor     eax, eax
  6850.         add     edi, 8
  6851.         mov     ecx, 40/4-2
  6852.         rep     stosd
  6853.         pop     eax
  6854.         push    eax edx
  6855. ; convert number in eax to decimal ANSI/UNICODE string
  6856.         push    edi
  6857.         push    -'0'
  6858.         mov     cl, 10
  6859. @@:
  6860.         xor     edx, edx
  6861.         div     ecx
  6862.         push    edx
  6863.         test    eax, eax
  6864.         jnz     @b
  6865. @@:
  6866.         pop     eax
  6867.         add     al, '0'
  6868.         stosb
  6869.         pushf
  6870.         test    bl, 1
  6871.         jz      .ansi_name
  6872.         xor     eax, eax
  6873.         stosb
  6874. .ansi_name:
  6875.         popf
  6876.         jnz     @b
  6877.         pop     edi
  6878.         add     edi, 520
  6879.         test    bl, 1
  6880.         jnz     @f
  6881.         sub     edi, 520-264
  6882. @@:
  6883.         pop     edx eax
  6884.         jmp     .maindir_loop
  6885. .maindir_done:
  6886.         mov     ebx, [edx+4]
  6887.         xor     eax, eax
  6888.         pop     ecx ecx
  6889.         dec     ecx
  6890.         js      @f
  6891.         mov     al, 6
  6892. @@:
  6893.         mov     [esp+20h], eax
  6894.         mov     [esp+14h], ebx
  6895.         ret
  6896. ; directory /
  6897. .rootdir:
  6898.         pop     eax
  6899.         pop     eax
  6900.         test    eax, eax
  6901.         jnz     .parse_access_denied
  6902.         cmp     dword [ebx], 1  ; read folder?
  6903.         jz      .readroot
  6904. .access_denied:
  6905.         mov     dword [esp+20h], 10      ; access denied
  6906.         ret
  6907.  
  6908. .readroot:
  6909. ; virtual root folder - special handler
  6910.         mov     esi, virtual_root_query
  6911.         push    dword [ebx+12]
  6912.         mov     edx, [ebx+16]
  6913.         add     edx, [base]
  6914.         push    dword [ebx+4]
  6915.         mov     ebx, [ebx+8]
  6916.         xor     eax, eax
  6917. ; eax=0, [esp]=first block, [esp+4]=number of blocks, ebx=flags, edx=return area
  6918.         mov     edi, edx
  6919.         mov     ecx, 32/4
  6920.         rep     stosd
  6921.         mov     byte [edx], 1   ; version
  6922. .readroot_loop:
  6923.         cmp     dword [esi], eax
  6924.         jz      .readroot_done
  6925.         call    dword [esi]
  6926.         add     esi, 4
  6927.         test    eax, eax
  6928.         jnz     @f
  6929. .readroot_next:
  6930.         or      ecx, -1
  6931.         xchg    esi, edi
  6932.         repnz   scasb
  6933.         xchg    esi, edi
  6934.         jmp     .readroot_loop
  6935. @@:
  6936.         xor     eax, eax
  6937.         inc     dword [edx+8]
  6938.         dec     dword [esp]
  6939.         jns     .readroot_next
  6940.         dec     dword [esp+4]
  6941.         js      .readroot_next
  6942.         inc     dword [edx+4]
  6943.         mov     dword [edi], 0x10       ; attributes: folder
  6944.         mov     dword [edi+4], ebx      ; name type
  6945.         add     edi, 8
  6946.         push    40/4-2
  6947.         pop     ecx
  6948.         rep     stosd
  6949.         push    edi
  6950. @@:
  6951.         lodsb
  6952.         stosb
  6953.         test    bl, 1
  6954.         jz     .ansi_name2
  6955.         mov     byte [edi], 0
  6956.         inc     edi
  6957. .ansi_name2:
  6958.         test    eax, eax
  6959.         jnz     @b
  6960.         pop     edi
  6961.         add     edi, 520
  6962.         test    bl, 1
  6963.         jnz     @f
  6964.         sub     edi, 520-264
  6965. @@:
  6966.         jmp     .readroot_loop
  6967. .readroot_done:
  6968.         mov     ebx, [edx+4]
  6969.         xor     eax, eax
  6970.         pop     ecx ecx
  6971.         dec     ecx
  6972.         js      @f
  6973.         mov     al, 6
  6974. @@:
  6975.         mov     [esp+20h], eax
  6976.         mov     [esp+14h], ebx
  6977.         ret
  6978.  
  6979. .found1:
  6980.         pop     eax
  6981.         cmp     byte [esi], 0
  6982.         jz      .maindir
  6983. ; read partition number
  6984.         xor     ecx, ecx
  6985.         xor     eax, eax
  6986. @@:
  6987.         lodsb
  6988.         cmp     al, '/'
  6989.         jz      .done1
  6990.         test    al, al
  6991.         jz      .done1
  6992.         sub     al, '0'
  6993.         cmp     al, 9
  6994.         ja      .notfound
  6995.         imul    ecx, 10
  6996.         add     ecx, eax
  6997.         jmp     @b
  6998. .done1:
  6999.         test    ecx, ecx
  7000.         jz      .notfound
  7001.         test    al, al
  7002.         jnz     @f
  7003.         dec     esi
  7004. @@:
  7005. ; now [edi] contains handler address, ecx - partition number,
  7006. ; esi points to ASCIIZ string - rest of name
  7007.         jmp     dword [edi]
  7008.  
  7009. fs_NextRamdisk:
  7010.         test    eax, eax
  7011.         stc
  7012.         jnz     @f
  7013.         mov     al, 1
  7014.         clc
  7015. @@:     ret
  7016.  
  7017. fs_NextHd0:
  7018.         push    0
  7019.         jmp     fs_NextHd
  7020. fs_NextHd1:
  7021.         push    1
  7022.         jmp     fs_NextHd
  7023. fs_NextHd2:
  7024.         push    2
  7025.         jmp     fs_NextHd
  7026. fs_NextHd3:
  7027.         push    3
  7028. fs_NextHd:
  7029.         pop     ecx
  7030.         mov     ecx, [hd_partitions_num+ecx*4]
  7031.         cmp     eax, ecx
  7032.         jae     .no
  7033.         inc     eax
  7034.         clc
  7035.         ret
  7036. .no:
  7037.         stc
  7038.         ret
  7039.  
  7040. fs_HasRamdisk:
  7041.         mov     al, 1
  7042.         ret
  7043.  
  7044. fs_HasHd0:
  7045.         cmp     [hd_partitions_num], 0
  7046.         setnz   al
  7047.         ret
  7048. fs_HasHd1:
  7049.         cmp     [hd_partitions_num+4], 0
  7050.         setnz   al
  7051.         ret
  7052. fs_HasHd2:
  7053.         cmp     [hd_partitions_num+8], 0
  7054.         setnz   al
  7055.         ret
  7056. fs_HasHd3:
  7057.         cmp     [hd_partitions_num+12], 0
  7058.         setnz   al
  7059.         ret
  7060.  
  7061. fs_OnRamdisk:
  7062.         cmp     ecx, 1
  7063.         jnz     i40_file_system_lfn.notfound
  7064.         mov     eax, ramdisk_path
  7065.         jmp     fs_common
  7066.  
  7067. fs_OnHd0:
  7068.         push    0
  7069.         jmp     fs_OnHd
  7070. fs_OnHd1:
  7071.         push    1
  7072.         jmp     fs_OnHd
  7073. fs_OnHd2:
  7074.         push    2
  7075.         jmp     fs_OnHd
  7076. fs_OnHd3:
  7077.         push    3
  7078. fs_OnHd:
  7079.         pop     eax
  7080.         cmp     ecx, [hd_partitions_num+eax*4]
  7081.         jbe     @f
  7082.         pop     eax eax
  7083.         test    eax, eax
  7084.         mov     eax, 5
  7085. .hderr:
  7086.         jnz     .ret
  7087.         mov     dword [esp+20h], eax
  7088. .ret:
  7089.         ret
  7090. @@:
  7091.         dec     ecx
  7092.         mov     eax, [hd_partitions_array+eax*4]
  7093.         shl     ecx, 9
  7094.         add     eax, ecx
  7095.         cmp     byte [eax+511], 0
  7096.         jz      fs_common
  7097. ; readonly disk - allow only subfunctions 0,1,5,7
  7098.         cmp     dword [ebx], 0
  7099.         jz      fs_common
  7100.         cmp     dword [ebx], 1
  7101.         jz      fs_common
  7102.         cmp     dword [ebx], 5
  7103.         jz      fs_common
  7104.         cmp     dword [ebx], 7
  7105.         jz      fs_common
  7106. ; access denied!
  7107.         pop     eax eax
  7108.         test    eax, eax
  7109.         mov     eax, 10
  7110.         jmp     .hderr
  7111. fs_common:
  7112.         pop     ecx
  7113.         pop     edi
  7114.         test    edi, edi
  7115.         jnz     @f
  7116.         sub     esp, 204h
  7117.         mov     edi, esp
  7118. @@:
  7119.         push    ecx
  7120.         push    eax
  7121.         push    edi
  7122.         call    [lstrcpyA]
  7123.         push    edi
  7124.         call    [lstrlenA]
  7125.         pop     ecx
  7126.         push    edi
  7127.         add     edi, eax
  7128.         sub     eax, 204h
  7129.         neg     eax
  7130.         push    ecx
  7131.         push    eax
  7132.         push    esi
  7133.         push    edi
  7134.         call    [lstrcpynA]
  7135.         pop     ecx
  7136.         jecxz   .slash_pass
  7137.         cmp     byte [ecx], 0
  7138.         jz      .slash_pass
  7139.         mov     esi, ecx
  7140.         push    edi
  7141.         call    [lstrlenA]
  7142.         add     edi, eax
  7143.         mov     eax, edi
  7144.         sub     eax, [esp]
  7145.         sub     eax, 204h
  7146.         neg     eax
  7147.         push    eax
  7148.         push    esi
  7149.         push    edi
  7150.         call    [lstrcpynA]
  7151. .slash_pass:
  7152.         mov     al, [edi]
  7153.         test    al, al
  7154.         jz      .slash_pass_done
  7155.         cmp     al, '\'
  7156.         jz      .invalid
  7157.         cmp     al, '/'
  7158.         jnz     @f
  7159.         mov     al, '\'
  7160. @@:
  7161.         stosb
  7162.         jmp     .slash_pass
  7163. .slash_pass_done:
  7164. ; delete trailing slashes, if present
  7165.         dec     edi
  7166.         cmp     byte [edi], '\'
  7167.         jz      .slash_pass_done
  7168.         inc     edi
  7169.         stosb
  7170. ; but do not delete one slash in X:\
  7171.         pop     edi
  7172.         cmp     byte [edi+1], ':'
  7173.         jnz     @f
  7174.         cmp     byte [edi+2], 0
  7175.         jnz     @f
  7176.         mov     word [edi+2], '\'
  7177. @@:
  7178.         push    edi
  7179.         push    edi
  7180.         call    [OemToCharA]
  7181. ; now edi -> Win32 path
  7182.         cmp     edi, esp
  7183.         jz      fs_do
  7184.         xor     eax, eax
  7185.         ret
  7186. .invalid:
  7187.         pop     edi
  7188.         cmp     edi, esp
  7189.         jnz     @f
  7190.         add     esp, 204h
  7191.         mov     dword [esp+20h], 5      ; file not found
  7192.         ret
  7193. @@:
  7194.         push    5
  7195.         pop     eax
  7196.         ret
  7197. fs_do:
  7198.         cmp     dword [ebx], 10
  7199.         jb      @f
  7200. fs_unsupported:
  7201.         add     esp, 204h
  7202.         jmp     not_supported_i40_fn
  7203. @@:
  7204.         push    edi
  7205.         call    [GetFileAttributesA]
  7206.         mov     ecx, dword [ebx]
  7207.         jmp     dword [i40_fs_subfunctions + ecx*4]
  7208.  
  7209. i40_fs_subfunctions:
  7210.         dd      fs_read
  7211.         dd      fs_read_folder
  7212.         dd      fs_rewrite
  7213.         dd      fs_write
  7214.         dd      fs_setsize
  7215.         dd      fs_getattr
  7216.         dd      fs_setattr
  7217.         dd      fs_execute
  7218.         dd      fs_delete
  7219.         dd      fs_makedir
  7220.  
  7221. fs_read:
  7222.         inc     eax
  7223.         jnz     @f
  7224.         add     esp, 204h
  7225.         mov     dword [esp+20h], 5      ; file not found
  7226.         or      dword [esp+14h], -1
  7227.         ret
  7228. @@:
  7229.         dec     eax
  7230.         test    al, 10h         ; FILE_ATTRIBUTE_DIRECTORY
  7231.         jz      @f
  7232.         add     esp, 204h
  7233. .access_denied:
  7234.         mov     dword [esp+20h], 10     ; access denied
  7235.         or      dword [esp+14h], -1
  7236.         ret
  7237. @@:
  7238.         push    0
  7239.         push    0
  7240.         push    3
  7241.         push    0
  7242.         push    1
  7243.         push    80000000h
  7244.         push    edi
  7245.         call    [CreateFileA]
  7246.         add     esp, 204h
  7247.         inc     eax
  7248.         jz      .access_denied
  7249.         dec     eax
  7250.         xchg    eax, esi
  7251.         push    dword [ebx+8]
  7252.         mov     eax, esp
  7253.         push    0
  7254.         push    eax
  7255.         push    dword [ebx+4]
  7256.         push    esi
  7257.         call    [SetFilePointer]
  7258.         inc     eax
  7259.         jnz     @f
  7260.         call    [GetLastError]
  7261.         test    eax, eax
  7262.         jz      @f
  7263.         pop     eax
  7264.         mov     dword [esp+20h], 6      ; EOF
  7265.         and     dword [esp+14h], 0      ; no bytes read
  7266.         push    esi
  7267.         call    [CloseHandle]
  7268.         ret
  7269. @@:
  7270.         mov     eax, esp
  7271.         push    0
  7272.         push    eax
  7273. ;        mov     eax, [limit]
  7274. ;        inc     eax
  7275. ;        sub     eax, [ebx+16]
  7276. ;        cmp     eax, [ebx+12]
  7277. ;        jb      @f
  7278. ;        mov     eax, [ebx+12]
  7279. ;@@:
  7280. ;        push    eax
  7281.         push    dword [ebx+12]
  7282.         mov     eax, [ebx+16]
  7283.         add     eax, [base]
  7284.         push    eax
  7285.         push    esi
  7286.         call    [ReadFile]
  7287.         pop     ecx
  7288.         xor     eax, eax
  7289.         cmp     ecx, [ebx+12]
  7290.         jz      @f
  7291.         mov     al, 6   ; EOF
  7292. @@:
  7293.         mov     [esp+20h], eax
  7294.         mov     [esp+14h], ecx  ; bytes read
  7295.         push    esi
  7296.         call    [CloseHandle]
  7297.         ret
  7298.  
  7299. fs_read_folder:
  7300.         inc     eax
  7301.         jnz     @f
  7302.         add     esp, 204h
  7303.         mov     dword [esp+20h], 5      ; file not found
  7304.         or      dword [esp+14h], -1
  7305.         ret
  7306. @@:
  7307.         push    edi
  7308.         call    [lstrlenA]
  7309.         cmp     eax, 202h
  7310.         jb      @f
  7311.         add     esp, 204h
  7312.         mov     dword [esp+20h], 5
  7313.         or      dword [esp+14h], -1
  7314.         ret
  7315. @@:
  7316.         cmp     byte [edi+eax-1], '/'
  7317.         jz      @f
  7318.         cmp     byte [edi+eax-1], '\'
  7319.         jz      @f
  7320.         mov     byte [edi+eax], '/'
  7321.         inc     eax
  7322. @@:
  7323.         mov     word [edi+eax], '*'
  7324.         cmp     byte [esi], 0
  7325.         mov     esi, 2
  7326.         jz      @f
  7327.         xor     esi, esi
  7328. @@:
  7329.         sub     esp, 140h       ; sizeof(WIN32_FIND_DATAA)
  7330.         push    esp
  7331.         push    edi
  7332.         call    [FindFirstFileA]
  7333.         inc     eax
  7334.         jnz     @f
  7335.         add     esp, 140h+204h
  7336.         mov     dword [esp+20h], 10     ; access denied
  7337.         or      dword [esp+14h], -1
  7338.         ret
  7339. @@:
  7340.         dec     eax
  7341.         push    dword [ebx+8]   ; flags
  7342.         push    dword [ebx+4]   ; 1st block
  7343.         push    dword [ebx+12]  ; number of blocks
  7344.         mov     edi, [ebx+16]   ; buffer
  7345.         add     edi, [base]
  7346.         push    edi
  7347.         xchg    eax, ebx
  7348.         mov     ecx, 32/4
  7349.         xor     eax, eax
  7350.         rep     stosd
  7351.         mov     byte [edi-32], 1        ; version
  7352. .loop:
  7353.         test    esi, 2
  7354.         jz      .noroot
  7355.         cmp     word [esp+16+44], '.'
  7356.         jz      .cont
  7357.         cmp     word [esp+16+44], '..'
  7358.         jnz     .noroot
  7359.         cmp     byte [esp+16+46], 0
  7360.         jz      .cont
  7361. .noroot:
  7362.         pop     eax
  7363.         push    eax
  7364.         inc     dword [eax+8]   ; new file found
  7365.         dec     dword [esp+8]
  7366.         jns     .cont
  7367.         dec     dword [esp+4]
  7368.         js      .cont
  7369.         inc     dword [eax+4]   ; new file copied
  7370.         mov     eax, [esp+16]   ; attributes
  7371.         and     eax, 3Fh
  7372.         stosd
  7373.         mov     al, [esp+12]    ; name type
  7374.         and     eax, 1
  7375.         stosd
  7376.         lea     eax, [esp+16+4]
  7377.         call    get_bdfe_time
  7378.         lea     eax, [esp+16+12]
  7379.         call    get_bdfe_time
  7380.         lea     eax, [esp+16+20]
  7381.         call    get_bdfe_time
  7382.         mov     eax, [esp+16+32]
  7383.         stosd
  7384.         mov     eax, [esp+16+28]
  7385.         stosd
  7386.         lea     eax, [esp+16+44]
  7387.         test    byte [esp+12], 1
  7388.         jz      .name_ansi
  7389.         push    260
  7390.         push    edi
  7391.         push    -1
  7392.         push    eax
  7393.         push    0
  7394.         push    0
  7395.         call    [MultiByteToWideChar]
  7396.         add     edi, 260*2
  7397.         jmp     .cont
  7398. .name_ansi:
  7399.         push    edi
  7400.         push    eax
  7401.         call    [CharToOemA]
  7402.         add     edi, 264
  7403. .cont:
  7404.         lea     eax, [esp+16]
  7405.         push    eax
  7406.         push    ebx
  7407.         call    [FindNextFileA]
  7408.         test    eax, eax
  7409.         jnz     .loop
  7410.         push    ebx
  7411.         call    [FindClose]
  7412.         pop     edx
  7413.         mov     ebx, [edx+4]
  7414.         xor     eax, eax
  7415.         pop     ecx
  7416.         dec     ecx
  7417.         js      @f
  7418.         mov     al, 6
  7419. @@:
  7420.         add     esp, 140h+204h+8
  7421.         mov     [esp+20h], eax
  7422.         mov     [esp+14h], ebx
  7423.         ret
  7424.  
  7425. get_bdfe_time:
  7426.         sub     esp, 10h
  7427.         push    esp
  7428.         push    eax
  7429.         call    [FileTimeToSystemTime]
  7430.         mov     ax, [esp+8]
  7431.         shl     eax, 16
  7432.         mov     ah, [esp+10]
  7433.         mov     al, [esp+12]
  7434.         stosd
  7435.         mov     ax, [esp+0]
  7436.         shl     eax, 16
  7437.         mov     ah, [esp+2]
  7438.         mov     al, [esp+6]
  7439.         stosd
  7440.         add     esp, 10h
  7441.         ret
  7442. from_bdfe_time:
  7443.         sub     esp, 10h
  7444.         xor     eax, eax
  7445.         lodsb
  7446.         mov     [esp+12], ax
  7447.         lodsb
  7448.         mov     [esp+10], ax
  7449.         lodsw
  7450.         mov     [esp+8], ax
  7451.         mov     ah, 0
  7452.         lodsb
  7453.         mov     [esp+6], ax
  7454.         lodsb
  7455.         mov     [esp+2], ax
  7456.         lodsw
  7457.         mov     [esp+0], ax
  7458.         mov     eax, esp
  7459.         push    edi
  7460.         push    eax
  7461.         call    [SystemTimeToFileTime]
  7462.         add     esp, 10h
  7463.         add     edi, 8
  7464.         ret
  7465.  
  7466. fs_rewrite:
  7467.         push    0
  7468.         push    80h
  7469.         push    2
  7470.         push    0
  7471.         push    0
  7472.         push    40000000h
  7473.         push    edi
  7474.         call    [CreateFileA]
  7475.         add     esp, 204h
  7476.         inc     eax
  7477.         jnz     @f
  7478.         mov     dword [esp+20h], 10
  7479.         and     dword [esp+14h], 0
  7480.         ret
  7481. @@:
  7482.         dec     eax
  7483.         xchg    eax, esi
  7484.         push    eax
  7485.         mov     eax, esp
  7486.         push    0
  7487.         push    eax
  7488.         push    dword [ebx+12]
  7489.         mov     eax, [ebx+16]
  7490.         add     eax, [base]
  7491.         push    eax
  7492.         push    esi
  7493.         call    [WriteFile]
  7494.         pop     ebx
  7495.         push    esi
  7496.         call    [CloseHandle]
  7497.         and     dword [esp+20h], 0
  7498.         mov     [esp+14h], ebx
  7499.         ret
  7500.  
  7501. fs_write:
  7502.         inc     eax
  7503.         jnz     @f
  7504.         add     esp, 204h
  7505.         mov     dword [esp+20h], 5      ; file not found
  7506.         or      dword [esp+14h], -1
  7507.         ret
  7508. @@:
  7509.         dec     eax
  7510.         test    al, 10h         ; FILE_ATTRIBUTE_DIRECTORY
  7511.         jz      @f
  7512.         add     esp, 204h
  7513. .access_denied:
  7514.         mov     dword [esp+20h], 10     ; access denied
  7515.         or      dword [esp+14h], -1
  7516.         ret
  7517. @@:
  7518.         push    0
  7519.         push    0
  7520.         push    3
  7521.         push    0
  7522.         push    1
  7523.         push    40000000h
  7524.         push    edi
  7525.         call    [CreateFileA]
  7526.         add     esp, 204h
  7527.         inc     eax
  7528.         jz      .access_denied
  7529.         dec     eax
  7530.         xchg    eax, esi
  7531.         push    dword [ebx+8]
  7532.         mov     eax, esp
  7533.         push    0
  7534.         push    eax
  7535.         push    dword [ebx+4]
  7536.         push    esi
  7537.         call    [SetFilePointer]
  7538.         inc     eax
  7539.         jnz     @f
  7540.         call    [GetLastError]
  7541.         test    eax, eax
  7542.         jz      @f
  7543.         pop     eax
  7544.         mov     dword [esp+20h], 6      ; EOF
  7545.         and     dword [esp+14h], 0      ; no bytes read
  7546.         push    esi
  7547.         call    [CloseHandle]
  7548.         ret
  7549. @@:
  7550.         mov     eax, esp
  7551.         push    0
  7552.         push    eax
  7553.         mov     eax, [limit]
  7554.         inc     eax
  7555.         sub     eax, [ebx+16]
  7556.         cmp     eax, [ebx+12]
  7557.         jb      @f
  7558.         mov     eax, [ebx+12]
  7559. @@:
  7560.         push    eax
  7561.         mov     eax, [ebx+16]
  7562.         add     eax, [base]
  7563.         push    eax
  7564.         push    esi
  7565.         call    [WriteFile]
  7566.         pop     ecx
  7567.         xor     eax, eax
  7568.         cmp     ecx, [ebx+12]
  7569.         jz      @f
  7570.         mov     al, 6   ; EOF
  7571. @@:
  7572.         mov     [esp+20h], eax
  7573.         mov     [esp+14h], ecx  ; bytes read
  7574.         push    esi
  7575.         call    [CloseHandle]
  7576.         ret
  7577.  
  7578. fs_setsize:
  7579.         inc     eax
  7580.         jnz     @f
  7581.         add     esp, 204h
  7582.         mov     dword [esp+20h], 5      ; file not found
  7583.         or      dword [esp+14h], -1
  7584.         ret
  7585. @@:
  7586.         dec     eax
  7587.         test    al, 10h         ; FILE_ATTRIBUTE_DIRECTORY
  7588.         jz      @f
  7589.         add     esp, 204h
  7590. .access_denied:
  7591.         mov     dword [esp+20h], 10     ; access denied
  7592.         or      dword [esp+14h], -1
  7593.         ret
  7594. @@:
  7595.         push    0
  7596.         push    0
  7597.         push    3
  7598.         push    0
  7599.         push    1
  7600.         push    40000000h
  7601.         push    edi
  7602.         call    [CreateFileA]
  7603.         add     esp, 204h
  7604.         inc     eax
  7605.         jz      .access_denied
  7606.         dec     eax
  7607.         xchg    eax, esi
  7608.         push    dword [ebx+8]
  7609.         mov     eax, esp
  7610.         push    0
  7611.         push    eax
  7612.         push    dword [ebx+4]
  7613.         push    esi
  7614.         call    [SetFilePointer]
  7615.         inc     eax
  7616.         jnz     @f
  7617.         call    [GetLastError]
  7618.         test    eax, eax
  7619.         jz      @f
  7620.         pop     eax
  7621.         mov     dword [esp+20h], 6      ; EOF
  7622.         mov     dword [esp+14h], 1234567h       ; destroy ebx
  7623.         push    esi
  7624.         call    [CloseHandle]
  7625.         ret
  7626. @@:
  7627.         pop     ecx
  7628.         push    esi
  7629.         call    [SetEndOfFile]
  7630.         and     dword [esp+20h], 0
  7631.         mov     dword [esp+14h], 234567h        ; destroy ebx
  7632.         push    esi
  7633.         call    [CloseHandle]
  7634.         ret
  7635.  
  7636. fs_getattr:
  7637.         inc     eax
  7638.         jnz     @f
  7639. .notfound:
  7640.         add     esp, 204h
  7641.         mov     dword [esp+20h], 5      ; file not found
  7642. .ret_destroy_ebx:
  7643.         mov     dword [esp+14h], 12345678h
  7644.         ret
  7645. @@:
  7646. ; Win32 does not allow to read attributes of root directories through FindFirstFile.
  7647. ; Moreover, on FAT systems the root directory simply does not contain attributes.
  7648. ; The current kernel implementation in Kolibri returns error eax = 2.
  7649. ; Let it be.
  7650.         cmp     word [edi+1], ':\'
  7651.         jnz     @f
  7652.         cmp     byte [edi+3], 0
  7653.         jnz     @f
  7654. ; The program requests root directory. Return eax=2.
  7655. ; N.B. All previous words are related to the case when Kolibri-disk is mapped to
  7656. ;      real disk, /hdi/j = N:\. Otherwise, it is possible to get real attributes
  7657. ;      of root directory, and emulator will do so (in another branch).
  7658.         add     esp, 204h
  7659.         mov     dword [esp+20h], 2
  7660.         jmp     .ret_destroy_ebx
  7661. @@:
  7662.         sub     esp, 140h       ; sizeof(WIN32_FIND_DATAA)
  7663.         push    esp
  7664.         push    edi
  7665.         call    [FindFirstFileA]
  7666.         inc     eax
  7667.         jnz     @f
  7668.         add     esp, 140h+204h
  7669.         mov     dword [esp+20h], 10     ; access denied
  7670.         mov     dword [esp+14h], 12345678h
  7671.         ret
  7672. @@:
  7673.         dec     eax
  7674.         push    eax
  7675.         call    [FindClose]
  7676.         mov     edi, [ebx+16]
  7677.         add     edi, [base]
  7678.         pop     eax             ; attributes
  7679.         and     eax, 3Fh
  7680.         stosd
  7681.         xor     eax, eax
  7682.         stosd
  7683.         mov     eax, esp
  7684.         call    get_bdfe_time
  7685.         lea     eax, [esp+12-4]
  7686.         call    get_bdfe_time
  7687.         lea     eax, [esp+20-4]
  7688.         call    get_bdfe_time
  7689.         mov     eax, [esp+32-4]
  7690.         stosd
  7691.         mov     eax, [esp+28-4]
  7692.         stosd
  7693.         add     esp, 140h-4+204h
  7694.         and     dword [esp+20h], 0
  7695.         mov     dword [esp+14h], 12345678h
  7696.         ret
  7697.  
  7698. fs_setattr:
  7699.         inc     eax
  7700.         jz      fs_getattr.notfound
  7701.         mov     esi, [ebx+16]
  7702.         add     esi, [base]
  7703.         lodsd
  7704.         push    eax     ; remember attributes
  7705.         push    80h     ; FILE_ATTRIBUTE_NORMAL
  7706.         push    edi
  7707.         call    [SetFileAttributesA]
  7708.         push    0
  7709.         push    0
  7710.         push    3       ; OPEN_EXISTING
  7711.         push    0
  7712.         push    3       ; FILE_SHARE_READ | FILE_SHARE_WRITE
  7713.         push    0x40000000      ; GENERIC_WRITE
  7714.         push    edi
  7715.         call    [CreateFileA]
  7716.         mov     ebx, eax
  7717.         inc     eax
  7718.         jnz     @f
  7719.         push    edi
  7720.         call    [SetFileAttributesA]
  7721.         add     esp, 204h
  7722.         mov     dword [esp+20h], 10
  7723.         ret
  7724. @@:
  7725.         lodsd
  7726.         sub     esp, 8*3
  7727.         mov     edi, esp
  7728.         call    from_bdfe_time
  7729.         call    from_bdfe_time
  7730.         call    from_bdfe_time
  7731.         lea     eax, [esp+16]
  7732.         push    eax
  7733.         sub     eax, 8
  7734.         push    eax
  7735.         sub     eax, 8
  7736.         push    eax
  7737.         push    ebx
  7738.         call    [SetFileTime]
  7739.         add     esp, 8*3
  7740.         push    ebx
  7741.         call    [CloseHandle]
  7742.         push    edi
  7743.         call    [SetFileAttributesA]
  7744.         add     esp, 204h
  7745.         and     dword [esp+20h], 0
  7746.         ret
  7747.  
  7748. fs_execute:
  7749.         inc     eax
  7750.         jnz     @f
  7751.         add     esp, 204h
  7752.         mov     dword [esp+20h], -5     ; file not found
  7753.         or      dword [esp+14h], -1
  7754.         ret
  7755. @@:
  7756.         mov     eax, [ebx+4]
  7757.         mov     esi, [ebx+8]
  7758.         call    notify_run_prg
  7759.         add     esp, 204h
  7760.         mov     [esp+20h], eax
  7761.         mov     dword [esp+14h], 23456789h
  7762.         ret
  7763.  
  7764. fs_delete:
  7765.         inc     eax
  7766.         jnz     @f
  7767.         add     esp, 204h
  7768.         mov     dword [esp+20h], 5      ; file not found
  7769. .ret:
  7770.         mov     dword [esp+14h], 0x12345678
  7771.         ret
  7772. @@:
  7773.         dec     eax
  7774.         test    al, 10h
  7775.         jnz     .directory
  7776.         push    edi
  7777.         call    [DeleteFileA]
  7778. @@:
  7779.         add     esp, 204h
  7780.         and     dword [esp+20h], 0
  7781.         test    eax, eax
  7782.         jnz     .ret
  7783.         mov     byte [esp+20h], 10      ; access denied
  7784.         jmp     .ret
  7785. .directory:
  7786.         push    edi
  7787.         call    [RemoveDirectoryA]
  7788.         jmp     @b
  7789.  
  7790. fs_makedir:
  7791.         push    0
  7792.         push    edi
  7793.         call    [CreateDirectoryA]
  7794.         add     esp, 204h
  7795.         and     dword [esp+20h], 0
  7796.         test    eax, eax
  7797.         jnz     @f
  7798.         call    [GetLastError]
  7799.         cmp     eax, 183        ; ERROR_ALREADY_EXISTS
  7800.         jz      @f
  7801.         mov     byte [esp+20h], 10
  7802. @@:
  7803.         ret
  7804.  
  7805. i40_window_settings:
  7806.         cmp     ebx, 1
  7807.         jnz     not_supported_i40_fn
  7808.         mov     [ebp+tls.caption], ecx
  7809.         or      byte [ebp+tls.color_main+3], 10h
  7810.         push    [ebp+tls.hWnd]
  7811.         call    [GetDC]
  7812.         push    eax
  7813.         push    [ebp+tls.hWnd]
  7814.         mov     edi, eax
  7815. ; redraw caption
  7816.         mov     al, byte [ebp+tls.color_main+3]
  7817.         and     eax, 0xF
  7818.         dec     eax
  7819.         js      .type1
  7820.         jz      .nodraw
  7821.         dec     eax
  7822.         jz      .type2
  7823.         call    draw_caption_skinned
  7824. .str:
  7825.         call    draw_caption_string
  7826. .nodraw:
  7827.         call    [ReleaseDC]
  7828.         ret
  7829. .type1:
  7830.         call    draw_caption_type1
  7831.         jmp     .str
  7832. .type2:
  7833.         call    draw_caption_type2
  7834.         jmp     .str
  7835.