From 500832c01d9eba40ed91e82db73b4b8ff7cdd07d Mon Sep 17 00:00:00 2001
From: "Artem Jerdev (art_zh)" <artem@jerdev.co.uk>
Date: Sat, 6 Nov 2010 23:50:26 +0000
Subject: [PATCH] SYNC WITH MAIN TRUNC: kernel-A updated to $1687

git-svn-id: svn://kolibrios.org@1689 a494cfbc-eb01-0410-851d-a64ba20cac60
---
 .../branches/Kolibri-A/trunk/core/exports.inc |   10 +-
 kernel/branches/Kolibri-A/trunk/core/heap.inc |    3 +-
 .../branches/Kolibri-A/trunk/core/memory.inc  |   38 +-
 .../branches/Kolibri-A/trunk/core/peload.inc  |    9 +-
 .../Kolibri-A/trunk/docs/sysfuncs.txt         |  119 +-
 .../Kolibri-A/trunk/drivers/codec.inc         |   43 +-
 .../Kolibri-A/trunk/drivers/emu10k1x.asm      | 1166 +++++
 .../Kolibri-A/trunk/drivers/imports.inc       |    4 +
 .../Kolibri-A/trunk/drivers/infinity.asm      |  240 +-
 .../branches/Kolibri-A/trunk/drivers/main.inc |   30 +-
 .../Kolibri-A/trunk/drivers/mixer.asm         |    5 +-
 .../Kolibri-A/trunk/drivers/vt823(x).asm      | 1281 +++++
 kernel/branches/Kolibri-A/trunk/fs/fs_lfn.inc |    4 +-
 kernel/branches/Kolibri-A/trunk/gui/event.inc |   14 +-
 kernel/branches/Kolibri-A/trunk/gui/mouse.inc | 1402 +++---
 .../branches/Kolibri-A/trunk/gui/window.inc   | 4162 +++++++++--------
 .../branches/Kolibri-A/trunk/hid/keyboard.inc |    2 +-
 kernel/branches/Kolibri-A/trunk/kernel.asm    |   31 +-
 18 files changed, 5583 insertions(+), 2980 deletions(-)
 create mode 100644 kernel/branches/Kolibri-A/trunk/drivers/emu10k1x.asm
 create mode 100644 kernel/branches/Kolibri-A/trunk/drivers/vt823(x).asm

diff --git a/kernel/branches/Kolibri-A/trunk/core/exports.inc b/kernel/branches/Kolibri-A/trunk/core/exports.inc
index 7b64cb4ae4..b2c6a06de2 100644
--- a/kernel/branches/Kolibri-A/trunk/core/exports.inc
+++ b/kernel/branches/Kolibri-A/trunk/core/exports.inc
@@ -22,6 +22,10 @@ iglobal
   szReservePortArea   db 'ReservePortArea',0
   szBoot_Log          db 'Boot_Log',0
 
+  szMutexInit         db 'MutexInit',0
+  szMutexLock         db 'MutexLock',0
+  szMutexUnlock       db 'MutexUnlock',0
+
   szPciApi            db 'PciApi', 0
   szPciRead32         db 'PciRead32', 0
   szPciRead16         db 'PciRead16', 0
@@ -91,7 +95,11 @@ kernel_export:
   dd szReservePortArea , r_f_port_area
   dd szBoot_Log        , boot_log
 
-  dd szPciApi          , pci_api
+  dd szMutexInit       , mutex_init            ;gcc fastcall
+  dd szMutexLock       , mutex_lock            ;gcc fastcall
+  dd szMutexUnlock     , mutex_unlock          ;gcc fastcall
+
+  dd szPciApi          , pci_api_drv
   dd szPciRead32       , pci_read32
   dd szPciRead16       , pci_read16
   dd szPciRead8        , pci_read8
diff --git a/kernel/branches/Kolibri-A/trunk/core/heap.inc b/kernel/branches/Kolibri-A/trunk/core/heap.inc
index 6f8dcd7626..9f7021dc57 100644
--- a/kernel/branches/Kolibri-A/trunk/core/heap.inc
+++ b/kernel/branches/Kolibri-A/trunk/core/heap.inc
@@ -635,7 +635,8 @@ proc kernel_free stdcall, base:dword
            pop esi ebx
            ret
 .fail:
-           and [heap_mutex], 0
+           xor eax, eax
+           mov [heap_mutex], eax
            pop esi ebx
            ret
 endp
diff --git a/kernel/branches/Kolibri-A/trunk/core/memory.inc b/kernel/branches/Kolibri-A/trunk/core/memory.inc
index 97a50d161a..1d35930a44 100644
--- a/kernel/branches/Kolibri-A/trunk/core/memory.inc
+++ b/kernel/branches/Kolibri-A/trunk/core/memory.inc
@@ -1089,25 +1089,7 @@ sysfn_meminfo:
 .fail:
 	   or dword [esp+32], -1
 	   ret
-iglobal
-align 4
-f68call:
-	   dd f68.11   ; init_heap
-	   dd f68.12   ; user_alloc
-	   dd f68.13   ; user_free
-	   dd f68.14   ; get_event_ex
-	   dd f68.fail ;moved to f68.24
-	   dd f68.16   ; get_service
-	   dd f68.17   ; call_service
-	   dd f68.fail ;moved to f68.25
-	   dd f68.19   ; load_dll
-	   dd f68.20   ; user_realloc
-	   dd f68.21   ; load_driver
-	   dd f68.22   ; shmem_open
-	   dd f68.23   ; shmem_close
-	   dd f68.24
-	   dd f68.25
-endg
+
 align 4
 f68:
 	   cmp	ebx,4
@@ -1227,6 +1209,24 @@ f68:
 	   mov [esp+32], eax
 	   ret
 
+align 4
+f68call:
+	   dd f68.11   ; init_heap
+	   dd f68.12   ; user_alloc
+	   dd f68.13   ; user_free
+	   dd f68.14   ; get_event_ex
+	   dd f68.fail ;moved to f68.24
+	   dd f68.16   ; get_service
+	   dd f68.17   ; call_service
+	   dd f68.fail ;moved to f68.25
+	   dd f68.19   ; load_dll
+	   dd f68.20   ; user_realloc
+	   dd f68.21   ; load_driver
+	   dd f68.22   ; shmem_open
+	   dd f68.23   ; shmem_close
+	   dd f68.24
+	   dd f68.25
+
 align 4
 proc load_pe_driver stdcall, file:dword
 
diff --git a/kernel/branches/Kolibri-A/trunk/core/peload.inc b/kernel/branches/Kolibri-A/trunk/core/peload.inc
index d1d40e6c0c..85fede96b6 100644
--- a/kernel/branches/Kolibri-A/trunk/core/peload.inc
+++ b/kernel/branches/Kolibri-A/trunk/core/peload.inc
@@ -283,6 +283,12 @@ __exports:
           alloc_page,            'AllocPage',          \      ; gcc ABI
           alloc_pages,           'AllocPages',         \      ; stdcall
           commit_pages,          'CommitPages',        \      ; eax, ebx, ecx
+\
+          create_event,          'CreateEvent',        \      ; ecx, esi
+          raise_event,           'RaiseEvent',         \      ; eax, ebx, edx, esi
+          wait_event,            'WaitEvent',          \      ; eax, ebx
+          get_event_ex,          'GetEvent',           \      ; edi
+\
           create_kernel_object,  'CreateObject',       \
           create_ring_buffer,    'CreateRingBuffer',   \      ; stdcall
           destroy_kernel_object, 'DestroyObject',      \
@@ -300,7 +306,7 @@ __exports:
 \
           get_display,           'GetDisplay',         \
           set_screen,            'SetScreen',          \
-          pci_api,               'PciApi',             \
+          pci_api_drv,           'PciApi',             \
           pci_read8,             'PciRead8',           \      ; stdcall
           pci_read16,            'PciRead16',          \      ; stdcall
           pci_read32,            'PciRead32',          \      ; stdcall
@@ -315,6 +321,7 @@ __exports:
           user_free,             'UserFree',           \      ; stdcall
           unmap_pages,           'UnmapPages',         \      ; eax, ecx
           sys_msg_board_str,     'SysMsgBoardStr',     \
+          get_timer_ticks,       'GetTimerTicks',      \
           delay_hs,              'Delay',              \      ; ebx
           set_mouse_data,        'SetMouseData'
 
diff --git a/kernel/branches/Kolibri-A/trunk/docs/sysfuncs.txt b/kernel/branches/Kolibri-A/trunk/docs/sysfuncs.txt
index 8d226d1cf6..26824a32c9 100644
--- a/kernel/branches/Kolibri-A/trunk/docs/sysfuncs.txt
+++ b/kernel/branches/Kolibri-A/trunk/docs/sysfuncs.txt
@@ -347,6 +347,7 @@ Returned value:
       * bit 0 (mask 1): window is maximized
       * bit 1 (mask 2): window is minimized to panel
       * bit 2 (mask 4): window is rolled up
+    * +71 = +0x47: dword: event mask
 Remarks:
   * Slots are numbered starting from 1.
   * Returned value is not a total number of threads, because there
@@ -844,12 +845,12 @@ Returned value:
   * function does not return value
 Structure of the buffer:
 db a,b,c,d for version a.b.c.d
-db UID_xxx: one of UID_NONE=0, UID_MENUET=1, UID_KOLIBRI=2
+db 0
 dd REV - kernel SVN revision number
-For Kolibri 0.7.1.0 kernel:
-db 0,7,0,0
+For Kolibri 0.7.7.0 kernel:
+db 0,7,7,0
 db 2
-dd 638
+dd 1657
 
 ======================================================================
 ======= Function 18, subfunction 14 - wait for screen retrace. =======
@@ -1658,56 +1659,8 @@ Returned value:
 Remarks:
   * If the buffer is too small to hold all data, only first (edx-1)
     bytes are copied and than terminating 0 is inserted.
-
-======================================================================
-=============== Function 32 - delete file from ramdisk. ==============
-======================================================================
-Parameters:
-  * eax = 32 - function number
-  * ebx = pointer to the filename
-Returned value:
-  * eax = 0 - success; otherwise file system error code
-Remarks:
-  * This function is obsolete; function 58 allows to fulfill
-    the same operations with the extended possibilities.
-  * The current implementation returns only values 0(success) and
-    5(file not found).
-  * The filename must be either in the format 8+3 characters
-    (first 8 characters - name itself, last 3 - extension,
-    the short names and extensions are supplemented with spaces),
-    or in the format 8.3 characters "FILE.EXT"/"FILE.EX "
-    (name no more than 8 characters, dot, extension 3 characters
-    supplemented if necessary by spaces).
-    The filename must be written with capital letters. The terminating
-    character with code 0 is not necessary (not ASCIIZ-string).
-  * This function does not support folders on the ramdisk.
-
-======================================================================
-================ Function 33 - write file to ramdisk. ================
-======================================================================
-Parameters:
-  * eax = 33 - function number
-  * ebx = pointer to the filename
-  * ecx = pointer to data for writing
-  * edx = number of bytes for writing
-  * should be set esi=0
-Returned value:
-  * eax = 0 - success, otherwise file system error code
-Remarks:
-  * This function is obsolete; function 70 allows to fulfil
-    the same operations with extended possibilities.
-  * If esi contains non-zero value and selected file already exists,
-    one more file with the same name will be created.
-  * Otherwise file will be overwritten.
-  * The filename must be either in the format 8+3 characters
-    (first 8 characters - name itself, last 3 - extension,
-    the short names and extensions are supplemented with spaces),
-    or in the format 8.3 characters "FILE.EXT"/"FILE.EX "
-    (name no more than 8 characters, dot, extension 3 characters
-    supplemented if necessary by spaces).
-    The filename must be written with capital letters. The terminating
-    character with code 0 is not necessary (not ASCIIZ-string).
-  * This function does not support folders on the ramdisk.
+  * By default, current folder for the thread is "/rd/1".
+  * At process/thread creation the current folder will be inherited 
 
 ======================================================================
 ======= Function 35 - read the color of a pixel on the screen. =======
@@ -3421,7 +3374,6 @@ Remarks:
 ======================================================================
 The input mode influences results of reading keys by function 2.
 When a program loads, ASCII input mode is set for it.
-If subfunction is not support then eax=-1.
 
 -------------- Subfunction 1 - set keyboard input mode. --------------
 Parameters:
@@ -3773,6 +3725,58 @@ Remarks:
   * If ecx=0, the function frees memory block at edx and returns 0.
   * The contents of the block are unchanged up to the shorter of
     the new and old sizes.
+======================================================================
+======== Function 68, subfunction 22 - open named memory area. =======
+======================================================================
+Parameters:
+  * eax = 68 - function number
+  * ebx = 22 - subfunction number
+  * ecx = area name. Maximum of 31 characters with terminating zero
+  * edx = area size in bytes for SHM_CREATE and SHM_OPEN_ALWAYS
+  * esi = flags for open and access:
+    * SHM_OPEN        = 0x00 - open existing memory area. If an area
+                          with such name does not exist, the function
+                          will return error code 5.
+    * SHM_OPEN_ALWAYS = 0x04 - open existing or create new
+                          memory area.
+    * SHM_CREATE      = 0x08 - create new memory area. If an area
+                          with such name already exists, the function
+                          will return error code 10.
+    * SHM_READ        = 0x00 - only read access
+    * SHM_WRITE       = 0x01 - read and write access
+Returned value:
+  * eax = pointer to memory area, 0 if error has occured
+  * if new area is created (SHM_CREATE or SHM_OPEN_ALWAYS):
+    edx = 0 - success, otherwise - error code
+  * if existing area is opened (SHM_OPEN or SHM_OPEN_ALWAYS):
+    edx = error code (if eax=0) or area size in bytes
+Error codes:
+  * E_NOTFOUND = 5
+  * E_ACCESS = 10
+  * E_NOMEM = 30
+  * E_PARAM = 33
+Remarks:
+  * Before this call one must initialize process heap by call to
+    subfunction 11.
+  * If a new area is created, access flags set maximal rights
+    for other processes. An attempt from other process to open
+    with denied rights will fail with error code E_ACCESS.
+  * The process which has created an area always has write access.
+
+======================================================================
+======= Function 68, subfunction 23 - close named memory area. =======
+======================================================================
+Parameters:
+  * eax = 68 - function number
+  * ebx = 23 - subfunction number
+  * ecx = area name. Maximum of 31 characters with terminating zero
+Returned value:
+  * eax destroyed
+Remarks:
+  * A memory area is physically freed (with deleting all data and
+    freeing physical memory), when all threads which have opened
+    this area will close it.
+  * When thread is terminating, all opened by it areas are closed.
 
 ======================================================================
 ====== Function 68, subfunction 24 - set new exceptions handler ======
@@ -3813,6 +3817,7 @@ Parameters:
   * edx = value of activity (0/1)
 Returned value:
   * eax = value of old activity for this signal (0/1)
+  * eax = -1 - invalid signal number
 Remarks:
   * In current implementation, it is changed only exception mask for
     user exception handler, wich was previously set by subfunction 24.
@@ -4111,6 +4116,10 @@ Examples:
   * '/hd0/2/menuet/pics/tanzania.bmp',0
   * '/hd0/1/Program files/NameOfProgram/SomeFile.SomeExtension',0
   * '/sys/MySuperApp.ini',0
+Also function supports relative names.  If the path begins not 
+with '/', it is considered relative to a current folder. To get or 
+set a current folder, use the function 30.
+
 Available subfunctions:
   * subfunction 0 - read file
   * subfunction 1 - read folder
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/codec.inc b/kernel/branches/Kolibri-A/trunk/drivers/codec.inc
index 0c2569fd11..80a6661bec 100644
--- a/kernel/branches/Kolibri-A/trunk/drivers/codec.inc
+++ b/kernel/branches/Kolibri-A/trunk/drivers/codec.inc
@@ -173,7 +173,6 @@ patch_AD:
 	   ret
 
 
-
 align 16
 ac_unknown     db 'unknown manufacturer',13,10,0
 ac_Realtek     db 'Realtek Semiconductor',13,10,0
@@ -181,6 +180,9 @@ ac_Analog      db 'Analog Devices',13,10,0
 ac_CMedia      db 'C-Media Electronics',13,10,0
 ac_Cirrus      db 'Cirrus Logic',13,10,0
 ac_Wolfson     db 'Wolfson Microelectronics',13,10,0
+ac_VIA	       db 'VIA Technologies',13,10,0
+ac_SigmaTel    db 'SigmaTel',13,10,0
+ac_eMicro      db 'eMicro',13,10,0
 
 chip_unknown   db 'unknown codec id ', 0
 
@@ -189,6 +191,9 @@ CHIP_REALTEK   equ 0x414C4700
 CHIP_CMEDIA    equ 0x434D4900
 CHIP_CIRRUS    equ 0x43525900
 CHIP_WOLFSON   equ 0x574D4C00
+CHIP_VIA       equ 0x56494100
+CHIP_SIGMATEL  equ 0x83847600
+CHIP_EMICRO    equ 0x454D4300
 
 align 16
 codecs	       dd CHIP_ANALOG, ac_Analog,  chips_Analog
@@ -196,6 +201,9 @@ codecs	       dd CHIP_ANALOG, ac_Analog,  chips_Analog
 	       dd CHIP_REALTEK,ac_Realtek, chips_Realtek
 	       dd CHIP_CIRRUS, ac_Cirrus,  chips_Cirrus
 	       dd CHIP_WOLFSON,ac_Wolfson, chips_Wolfson
+	       dd CHIP_VIA,    ac_VIA,	   chips_VIA
+	       dd CHIP_SIGMATEL,    ac_SigmaTel,     chips_SigmaTel
+	       dd CHIP_EMICRO,	  ac_eMicro,	 chips_eMicro
 	       dd 0
 
 align 16
@@ -207,6 +215,8 @@ chips_Analog   dd 0x03, chip_AD1819
 	       dd 0x62, chip_AD1887
 	       dd 0x63, chip_AD1886A
 	       dd 0x70, chip_AD1980
+	       dd 0x72, chip_AD1981A
+	       dd 0x74, chip_AD1981B
 	       dd 0x75, chip_AD1985
 	       dd 0xFF
 
@@ -243,8 +253,17 @@ chips_Cirrus   dd 0x00, chip_CS4297
 	       dd 0xFF
 
 chips_Wolfson  dd 0x00, chip_WM9700
-               dd 0x03, chip_WM9703
-               dd 0x04, chip_WM9704
+	       dd 0x03, chip_WM9703
+	       dd 0x04, chip_WM9704
+	       dd 0xFF
+
+chips_VIA      dd 0x61, chip_VIA1612A
+	       dd 0xFF
+
+chips_SigmaTel dd 0x58, chip_STAC9758
+	       dd 0xFF
+
+chips_eMicro   dd 0x28, chip_EM28028
 	       dd 0xFF
 
 align 16
@@ -258,6 +277,8 @@ chip_AD1886	 db 'AD1886 ',0dh,0ah,00h
 chip_AD1886A	 db 'AD1886A',0dh,0ah,00h
 chip_AD1887	 db 'AD1887 ',0dh,0ah,00h
 chip_AD1980	 db 'AD1980 ',0dh,0ah,00h
+chip_AD1981A	 db 'AD1981A',0dh,0ah,00h
+chip_AD1981B	 db 'AD1981B',0dh,0ah,00h
 chip_AD1985	 db 'AD1985 ',0dh,0ah,00h
 
 ;Realtek
@@ -290,6 +311,16 @@ chip_CS4291	 db 'CS4291',13,10,0
 chip_CS4202	 db 'CS4202',13,10,0
 
 ;Wolfson
-chip_WM9700      db 'WM9704',13,10,0
-chip_WM9703      db 'WM9703/9704',13,10,0
-chip_WM9704      db 'WM9704 (quad)',13,10,0
+chip_WM9700	 db 'WM9704',13,10,0
+chip_WM9703	 db 'WM9703/9704',13,10,0
+chip_WM9704	 db 'WM9704 (quad)',13,10,0
+
+;VIA
+chip_VIA1612A	 db 'VIA1612A',13,10,0
+
+;SigmaTel
+chip_STAC9758	 db 'STAC9758,59',13,10,0
+
+;eMicro
+chip_EM28028	 db 'EM28028',13,10,0
+
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/emu10k1x.asm b/kernel/branches/Kolibri-A/trunk/drivers/emu10k1x.asm
new file mode 100644
index 0000000000..e2b1809832
--- /dev/null
+++ b/kernel/branches/Kolibri-A/trunk/drivers/emu10k1x.asm
@@ -0,0 +1,1166 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                              ;;
+;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
+;; Distributed under terms of the GNU General Public License    ;;
+;;                                                              ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+format MS COFF
+
+DEBUG		equ 1
+
+include 'proc32.inc'
+include 'imports.inc'
+
+API_VERSION	equ 0x01000100
+
+USE_COM_IRQ	equ 0	 ;make irq 3 and irq 4 available for PCI devices
+IRQ_REMAP	equ 0
+IRQ_LINE	equ 0
+
+
+;irq 0,1,2,8,12,13 ������㯭�
+;                   FEDCBA9876543210
+VALID_IRQ	equ 1100111011111000b
+ATTCH_IRQ	equ 0000111010100000b
+
+if USE_COM_IRQ
+ATTCH_IRQ	equ 0000111010111000b
+end if
+
+CPU_FREQ	equ  2600d
+
+BIT0  EQU 0x00000001
+BIT1  EQU 0x00000002
+BIT5  EQU 0x00000020
+BIT10 EQU 0x00000400
+
+VID_Creative	  equ 0x1102
+
+CTRL_CT0200	  equ 0x0006  ; Dell OEM version (EMU10K1X)
+
+
+CODEC_MASTER_VOL_REG	     equ 0x02
+CODEC_AUX_VOL		     equ 0x04 ;
+CODEC_PCM_OUT_REG	     equ 0x18 ; PCM output volume
+CODEC_EXT_AUDIO_REG	     equ 0x28 ; extended audio
+CODEC_EXT_AUDIO_CTRL_REG     equ 0x2a ; extended audio control
+CODEC_PCM_FRONT_DACRATE_REG  equ 0x2c ; PCM out sample rate
+CODEC_PCM_SURND_DACRATE_REG  equ 0x2e ; surround sound sample rate
+CODEC_PCM_LFE_DACRATE_REG    equ 0x30 ; LFE sample rate
+
+
+;EMU10K1(X) host controller registers set
+;; common offsets
+;; some definitions were borrowed from emu10k1 driver as they seem to be the same
+;;**********************************************************************************************;;
+;; PCI function 0 registers, address = <val> + PCIBASE0                                         ;;
+;;**********************************************************************************************;;
+
+PTR			equ  0x00	     ;; Indexed register set pointer register        ;;
+						;; NOTE: The CHANNELNUM and ADDRESS words can   ;;
+						;; be modified independently of each other.     ;;
+
+DATA			equ  0x04	     ;; Indexed register set data register           ;;
+
+IPR			equ  0x08	     ;; Global interrupt pending register            ;;
+						;; Clear pending interrupts by writing a 1 to   ;;
+						;; the relevant bits and zero to the other bits ;;
+IPR_MIDITRANSBUFEMPTY	equ  0x00000001      ;; MIDI UART transmit buffer empty              ;;
+IPR_MIDIRECVBUFEMPTY	equ  0x00000002      ;; MIDI UART receive buffer empty               ;;
+IPR_CH_0_LOOP		equ  0x00000800      ;; Channel 0 loop                               ;;
+IPR_CH_0_HALF_LOOP	equ  0x00000100      ;; Channel 0 half loop                          ;;
+IPR_CAP_0_LOOP		equ  0x00080000      ;; Channel capture loop                         ;;
+IPR_CAP_0_HALF_LOOP	equ  0x00010000      ;; Channel capture half loop                    ;;
+
+INTE			equ  0x0c	     ;; Interrupt enable register                    ;;
+INTE_MIDITXENABLE	equ  0x00000001      ;; Enable MIDI transmit-buffer-empty interrupts ;;
+INTE_MIDIRXENABLE	equ  0x00000002      ;; Enable MIDI receive-buffer-empty interrupts  ;;
+INTE_CH_0_LOOP		equ  0x00000800      ;; Channel 0 loop                               ;;
+INTE_CH_0_HALF_LOOP	equ  0x00000100      ;; Channel 0 half loop                          ;;
+INTE_CAP_0_LOOP 	equ  0x00080000      ;; Channel capture loop                         ;;
+INTE_CAP_0_HALF_LOOP	equ  0x00010000      ;; Channel capture half loop                    ;;
+
+HCFG			equ  0x14	     ;; Hardware config register                     ;;
+
+HCFG_LOCKSOUNDCACHE	equ  0x00000008      ;; 1 = Cancel bustmaster accesses to soundcache ;;
+						;; NOTE: This should generally never be used.   ;;
+HCFG_AUDIOENABLE	equ  0x00000001      ;; 0 = CODECs transmit zero-valued samples      ;;
+						;; Should be set to 1 when the EMU10K1 is       ;;
+						;; completely initialized.                      ;;
+GPIO			equ  0x18	     ;; Defaults: 00001080-Analog, 00001000-SPDIF.   ;;
+
+
+AC97DATA		equ  0x1c	     ;; AC97 register set data register (16 bit)     ;;
+
+AC97ADDRESS		equ  0x1e	     ;; AC97 register set address register (8 bit)   ;;
+
+;;******************************************************************************************************;;
+;; Emu10k1x pointer-offset register set, accessed through the PTR and DATA registers                    ;;
+;;******************************************************************************************************;;
+PLAYBACK_LIST_ADDR	equ  0x00	     ;; Base DMA address of a list of pointers to each period/size ;;
+						;; One list entry: 4 bytes for DMA address,
+						 ;; 4 bytes for period_size << 16.
+						 ;; One list entry is 8 bytes long.
+						 ;; One list entry for each period in the buffer.
+						 ;;
+PLAYBACK_LIST_SIZE	equ  0x01	     ;; Size of list in bytes << 19. E.g. 8 periods -> 0x00380000  ;;
+PLAYBACK_LIST_PTR	equ  0x02	     ;; Pointer to the current period being played ;;
+PLAYBACK_DMA_ADDR	equ  0x04	     ;; Playback DMA addresss ;;
+PLAYBACK_PERIOD_SIZE	equ  0x05	     ;; Playback period size ;;
+PLAYBACK_POINTER	equ  0x06	     ;; Playback period pointer. Sample currently in DAC ;;
+PLAYBACK_UNKNOWN1	equ  0x07
+PLAYBACK_UNKNOWN2	equ  0x08
+
+;; Only one capture channel supported ;;
+CAPTURE_DMA_ADDR	equ  0x10	     ;; Capture DMA address ;;
+CAPTURE_BUFFER_SIZE	equ  0x11	     ;; Capture buffer size ;;
+CAPTURE_POINTER 	equ  0x12	     ;; Capture buffer pointer. Sample currently in ADC ;;
+CAPTURE_UNKNOWN 	equ  0x13
+
+;; From 0x20 - 0x3f, last samples played on each channel ;;
+
+TRIGGER_CHANNEL 	equ  0x40	     ;; Trigger channel playback                     ;;
+TRIGGER_CHANNEL_0	equ  0x00000001      ;; Trigger channel 0                            ;;
+TRIGGER_CHANNEL_1	equ  0x00000002      ;; Trigger channel 1                            ;;
+TRIGGER_CHANNEL_2	equ  0x00000004      ;; Trigger channel 2                            ;;
+TRIGGER_CAPTURE 	equ  0x00000100      ;; Trigger capture channel                      ;;
+
+ROUTING 		equ  0x41	     ;; Setup sound routing ?                        ;;
+ROUTING_FRONT_LEFT	equ  0x00000001
+ROUTING_FRONT_RIGHT	equ  0x00000002
+ROUTING_REAR_LEFT	equ  0x00000004
+ROUTING_REAR_RIGHT	equ  0x00000008
+ROUTING_CENTER_LFE	equ  0x00010000
+
+SPCS0			equ  0x42	     ;; SPDIF output Channel Status 0 register       ;;
+SPCS1			equ  0x43	     ;; SPDIF output Channel Status 1 register       ;;
+SPCS2			equ  0x44	     ;; SPDIF output Channel Status 2 register       ;;
+
+SPCS_CLKACCYMASK	equ  0x30000000      ;; Clock accuracy                               ;;
+SPCS_CLKACCY_1000PPM	equ  0x00000000      ;; 1000 parts per million                       ;;
+SPCS_CLKACCY_50PPM	equ  0x10000000      ;; 50 parts per million                         ;;
+SPCS_CLKACCY_VARIABLE	equ  0x20000000      ;; Variable accuracy                            ;;
+SPCS_SAMPLERATEMASK	equ  0x0f000000      ;; Sample rate                                  ;;
+SPCS_SAMPLERATE_44	equ  0x00000000      ;; 44.1kHz sample rate                          ;;
+SPCS_SAMPLERATE_48	equ  0x02000000      ;; 48kHz sample rate                            ;;
+SPCS_SAMPLERATE_32	equ  0x03000000      ;; 32kHz sample rate                            ;;
+SPCS_CHANNELNUMMASK	equ  0x00f00000      ;; Channel number                               ;;
+SPCS_CHANNELNUM_UNSPEC	equ  0x00000000      ;; Unspecified channel number                   ;;
+SPCS_CHANNELNUM_LEFT	equ  0x00100000      ;; Left channel                                 ;;
+SPCS_CHANNELNUM_RIGHT	equ  0x00200000      ;; Right channel                                ;;
+SPCS_SOURCENUMMASK	equ  0x000f0000      ;; Source number                                ;;
+SPCS_SOURCENUM_UNSPEC	equ  0x00000000      ;; Unspecified source number                    ;;
+SPCS_GENERATIONSTATUS	equ  0x00008000      ;; Originality flag (see IEC-958 spec)          ;;
+SPCS_CATEGORYCODEMASK	equ  0x00007f00      ;; Category code (see IEC-958 spec)             ;;
+SPCS_MODEMASK		equ  0x000000c0      ;; Mode (see IEC-958 spec)                      ;;
+SPCS_EMPHASISMASK	equ  0x00000038      ;; Emphasis                                     ;;
+SPCS_EMPHASIS_NONE	equ  0x00000000      ;; No emphasis                                  ;;
+SPCS_EMPHASIS_50_15	equ  0x00000008      ;; 50/15 usec 2 channel                         ;;
+SPCS_COPYRIGHT		equ  0x00000004      ;; Copyright asserted flag -- do not modify     ;;
+SPCS_NOTAUDIODATA	equ  0x00000002      ;; 0 = Digital audio, 1 = not audio             ;;
+SPCS_PROFESSIONAL	equ  0x00000001      ;; 0 = Consumer (IEC-958), 1 = pro (AES3-1992)  ;;
+
+SPDIF_SELECT		equ  0x45	     ;; Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF ;;
+
+;; This is the MPU port on the card                                                             ;;
+MUDATA		equ  0x47
+MUCMD		equ  0x48
+MUSTAT		equ  MUCMD
+
+;; From 0x50 - 0x5f, last samples captured ;;
+
+
+SRV_GETVERSION	      equ  0
+DEV_PLAY	      equ  1
+DEV_STOP	      equ  2
+DEV_CALLBACK	      equ  3
+DEV_SET_BUFF	      equ  4
+DEV_NOTIFY	      equ  5
+DEV_SET_MASTERVOL     equ  6
+DEV_GET_MASTERVOL     equ  7
+DEV_GET_INFO	      equ  8
+
+struc AC_CNTRL		    ;AC controller base class
+{ .bus		      dd ?
+  .devfn	      dd ?
+
+  .vendor	      dd ?
+  .dev_id	      dd ?
+  .pci_cmd	      dd ?
+  .pci_stat	      dd ?
+
+  .codec_io_base      dd ?
+  .codec_mem_base     dd ?
+
+  .ctrl_io_base       dd ?
+  .ctrl_mem_base      dd ?
+  .cfg_reg	      dd ?
+  .int_line	      dd ?
+
+  .vendor_ids	      dd ?    ;vendor id string
+  .ctrl_ids	      dd ?    ;hub id string
+
+  .buffer	      dd ?
+
+  .notify_pos	      dd ?
+  .notify_task	      dd ?
+
+  .lvi_reg	      dd ?
+  .ctrl_setup	      dd ?
+  .user_callback      dd ?
+  .codec_read16       dd ?
+  .codec_write16      dd ?
+
+  .ctrl_read8	      dd ?
+  .ctrl_read16	      dd ?
+  .ctrl_read32	      dd ?
+
+  .ctrl_write8	      dd ?
+  .ctrl_write16       dd ?
+  .ctrl_write32       dd ?
+}
+
+struc CODEC		   ;Audio Chip base class
+{
+  .chip_id	      dd ?
+  .flags	      dd ?
+  .status	      dd ?
+
+  .ac_vendor_ids      dd ?    ;ac vendor id string
+  .chip_ids	      dd ?    ;chip model string
+
+  .shadow_flag	      dd ?
+		      dd ?
+
+  .regs 	      dw ?     ; codec registers
+  .reg_master_vol     dw ?     ;0x02
+  .reg_aux_out_vol    dw ?     ;0x04
+  .reg_mone_vol       dw ?     ;0x06
+  .reg_master_tone    dw ?     ;0x08
+  .reg_beep_vol       dw ?     ;0x0A
+  .reg_phone_vol      dw ?     ;0x0C
+  .reg_mic_vol	      dw ?     ;0x0E
+  .reg_line_in_vol    dw ?     ;0x10
+  .reg_cd_vol	      dw ?     ;0x12
+  .reg_video_vol      dw ?     ;0x14
+  .reg_aux_in_vol     dw ?     ;0x16
+  .reg_pcm_out_vol    dw ?     ;0x18
+  .reg_rec_select     dw ?     ;0x1A
+  .reg_rec_gain       dw ?     ;0x1C
+  .reg_rec_gain_mic   dw ?     ;0x1E
+  .reg_gen	      dw ?     ;0x20
+  .reg_3d_ctrl	      dw ?     ;0X22
+  .reg_page	      dw ?     ;0X24
+  .reg_powerdown      dw ?     ;0x26
+  .reg_ext_audio      dw ?     ;0x28
+  .reg_ext_st	      dw ?     ;0x2a
+  .reg_pcm_front_rate dw ?     ;0x2c
+  .reg_pcm_surr_rate  dw ?     ;0x2e
+  .reg_lfe_rate       dw ?     ;0x30
+  .reg_pcm_in_rate    dw ?     ;0x32
+		      dw ?     ;0x34
+  .reg_cent_lfe_vol   dw ?     ;0x36
+  .reg_surr_vol       dw ?     ;0x38
+  .reg_spdif_ctrl     dw ?     ;0x3A
+		      dw ?     ;0x3C
+		      dw ?     ;0x3E
+		      dw ?     ;0x40
+		      dw ?     ;0x42
+		      dw ?     ;0x44
+		      dw ?     ;0x46
+		      dw ?     ;0x48
+		      dw ?     ;0x4A
+		      dw ?     ;0x4C
+		      dw ?     ;0x4E
+		      dw ?     ;0x50
+		      dw ?     ;0x52
+		      dw ?     ;0x54
+		      dw ?     ;0x56
+		      dw ?     ;0x58
+		      dw ?     ;0x5A
+		      dw ?     ;0x5C
+		      dw ?     ;0x5E
+  .reg_page_0	      dw ?     ;0x60
+  .reg_page_1	      dw ?     ;0x62
+  .reg_page_2	      dw ?     ;0x64
+  .reg_page_3	      dw ?     ;0x66
+  .reg_page_4	      dw ?     ;0x68
+  .reg_page_5	      dw ?     ;0x6A
+  .reg_page_6	      dw ?     ;0x6C
+  .reg_page_7	      dw ?     ;0x6E
+		      dw ?     ;0x70
+		      dw ?     ;0x72
+		      dw ?     ;0x74
+		      dw ?     ;0x76
+		      dw ?     ;0x78
+		      dw ?     ;0x7A
+  .reg_vendor_id_1    dw ?     ;0x7C
+  .reg_vendor_id_2    dw ?     ;0x7E
+
+
+  .reset	      dd ?    ;virual
+  .set_master_vol     dd ?
+}
+
+struc CTRL_INFO
+{   .pci_cmd	      dd ?
+    .irq	      dd ?
+    .glob_cntrl       dd ?
+    .glob_sta	      dd ?
+    .codec_io_base    dd ?
+    .ctrl_io_base     dd ?
+    .codec_mem_base   dd ?
+    .ctrl_mem_base    dd ?
+    .codec_id	      dd ?
+}
+
+struc IOCTL
+{  .handle	      dd ?
+   .io_code	      dd ?
+   .input	      dd ?
+   .inp_size	      dd ?
+   .output	      dd ?
+   .out_size	      dd ?
+}
+
+virtual at 0
+  IOCTL IOCTL
+end virtual
+
+EVENT_NOTIFY	equ 0x00000200
+
+public START
+public service_proc
+public version
+
+section '.flat' code readable align 16
+
+proc START stdcall, state:dword
+
+	   cmp	 [state], 1
+	   jne	 .stop
+
+     if DEBUG
+	   mov	 esi, msgInit
+	   call  SysMsgBoardStr
+     end if
+
+	   call     detect_controller
+	   test     eax, eax
+	   jz	    .fail
+
+     if DEBUG
+	   mov	 esi,[ctrl.vendor_ids]
+	   call  SysMsgBoardStr
+	   mov	 esi, [ctrl.ctrl_ids]
+	   call  SysMsgBoardStr
+     end if
+
+	   call     init_controller
+	   test     eax, eax
+	   jz	    .fail
+
+	   call     init_codec
+	   test     eax, eax
+	   jz	    .fail
+
+	   call     setup_codec
+
+	   mov	    esi, msgPrimBuff
+	   call     SysMsgBoardStr
+	   call     create_primary_buff
+	   mov	    esi, msgDone
+	   call     SysMsgBoardStr
+
+  if IRQ_REMAP
+	   pushf
+	   cli
+
+	   mov	    ebx, [ctrl.int_line]
+	   in	    al, 0xA1
+	   mov	    ah, al
+	   in	    al, 0x21
+	   test     ebx, ebx
+	   jz	    .skip
+	   bts	    ax, bx			;mask old line
+.skip:
+	   bts	    ax, IRQ_LINE		;mask new ine
+	   out	    0x21, al
+	   mov	    al, ah
+	   out	    0xA1, al
+
+	   stdcall  PciWrite8, 0, 0xF8, 0x61, IRQ_LINE	;remap IRQ
+
+	   mov	    dx, 0x4d0			;8259 ELCR1
+	   in	    al, dx
+	   bts	    ax, IRQ_LINE
+	   out	    dx, al			;set level-triggered mode
+	   mov	    [ctrl.int_line], IRQ_LINE
+	   popf
+	   mov	    esi, msgRemap
+	   call     SysMsgBoardStr
+  end if
+
+	   mov	    eax, VALID_IRQ
+	   mov	    ebx, [ctrl.int_line]
+	   mov	    esi, msgInvIRQ
+	   bt	    eax, ebx
+	   jnc	    .fail_msg
+	   mov	    eax, ATTCH_IRQ
+	   mov	    esi, msgAttchIRQ
+	   bt	    eax, ebx
+	   jnc	    .fail_msg
+
+	   stdcall  AttachIntHandler, ebx, ac97_irq, dword 0
+	   stdcall  create
+
+.reg:
+	   stdcall  RegService, sz_sound_srv, service_proc
+	   ret
+.fail:
+     if DEBUG
+	   mov	 esi, msgFail
+	   call  SysMsgBoardStr
+     end if
+	   xor	    eax, eax
+	   ret
+.fail_msg:
+	   call     SysMsgBoardStr
+	   xor	    eax, eax
+	   ret
+.stop:
+	   call     stop
+	   xor	    eax, eax
+	   ret
+endp
+
+handle	   equ	IOCTL.handle
+io_code    equ	IOCTL.io_code
+input	   equ	IOCTL.input
+inp_size   equ	IOCTL.inp_size
+output	   equ	IOCTL.output
+out_size   equ	IOCTL.out_size
+
+align 4
+proc service_proc stdcall, ioctl:dword
+
+	   mov	    edi, [ioctl]
+	   mov	    eax, [edi+io_code]
+
+	   cmp	    eax, SRV_GETVERSION
+	   jne	    @F
+	   mov	    eax, [edi+output]
+	   cmp	    [edi+out_size], 4
+	   jne	    .fail
+
+	   mov	    [eax], dword API_VERSION
+	   xor	    eax, eax
+	   ret
+@@:
+	   cmp	    eax, DEV_PLAY
+	   jne	    @F
+     if DEBUG
+	   mov	esi, msgPlay
+	   call SysMsgBoardStr
+     end if
+	   call     play
+	   ret
+@@:
+	   cmp	    eax, DEV_STOP
+	   jne	    @F
+     if DEBUG
+	   mov	esi, msgStop
+	   call SysMsgBoardStr
+     end if
+	   call     stop
+	   ret
+@@:
+	   cmp	    eax, DEV_CALLBACK
+	   jne	    @F
+	   mov	    ebx, [edi+input]
+	   stdcall  set_callback, [ebx]
+	   ret
+@@:
+	   cmp	    eax, DEV_SET_MASTERVOL
+	   jne	    @F
+	   mov	    eax, [edi+input]
+	   mov	    eax, [eax]
+	   call     set_master_vol	;eax= vol
+	   ret
+@@:
+	   cmp	    eax, DEV_GET_MASTERVOL
+	   jne	    @F
+	   mov	    ebx, [edi+output]
+	   stdcall  get_master_vol, ebx
+	   ret
+@@:
+	   cmp	    eax, DEV_GET_INFO
+	   jne	    @F
+	   mov	    ebx, [edi+output]
+	   stdcall  get_dev_info, ebx
+	   ret
+@@:
+.fail:
+	   or	    eax, -1
+	   ret
+endp
+
+restore   handle
+restore   io_code
+restore   input
+restore   inp_size
+restore   output
+restore   out_size
+
+
+align 4
+proc ac97_irq
+	   locals
+	     status dd 0
+	   endl
+
+;        status = inl(chip->port + IPR);
+	   mov	    edx, IPR
+	   call     [ctrl.ctrl_read32]
+	   test     eax, eax
+	   jz	    @f
+
+	   mov	    dword [status], eax
+
+	   mov	    ebx, dword [buff_list]
+	   cmp	    [ctrl.user_callback], 0
+	   je	    @f
+	   stdcall  [ctrl.user_callback], ebx
+       @@:
+	   mov	    eax, dword [status] 	  ;; ack ;;
+	   mov	    edx, IPR
+	   call     [ctrl.ctrl_write32]
+	   ret
+endp
+
+
+align 4
+proc create_primary_buff
+
+	   stdcall  KernelAlloc, 0x10000
+	   mov	    [ctrl.buffer], eax
+
+	   mov	    edi, eax
+	   mov	    ecx, 0x10000/4
+	   xor	    eax, eax
+	   cld
+	   rep	    stosd
+
+	   mov	    eax, [ctrl.buffer]
+	   call     GetPgAddr
+
+	   mov edi, pcmout_bdl
+	   stosd
+	   mov	    eax, 0x4000000
+	   stosd
+
+	   mov	    edi, buff_list
+	   mov	    eax, [ctrl.buffer]
+	   stosd		     ;1.]
+
+	   mov	    eax, [ctrl.buffer]
+	   call     GetPgAddr
+
+	   stdcall  ptr_write, PLAYBACK_POINTER,   0, 0
+	   stdcall  ptr_write, PLAYBACK_UNKNOWN1,  0, 0
+	   stdcall  ptr_write, PLAYBACK_UNKNOWN2,  0, 0
+	   stdcall  ptr_write, PLAYBACK_DMA_ADDR,  0, eax
+
+	   mov	    eax, pcmout_bdl
+	   mov	    ebx, eax
+	   call     GetPgAddr
+	   and	    ebx, 0xFFF
+	   add	    eax, ebx
+
+	   stdcall  ptr_write, PLAYBACK_LIST_ADDR, 0, eax
+	   stdcall  ptr_write, PLAYBACK_LIST_SIZE, 0, 0
+	   stdcall  ptr_write, PLAYBACK_LIST_PTR,  0, 0
+
+	   ;mov     eax, 0x00004000
+	   ;shl     eax, 16
+	   stdcall  ptr_write, PLAYBACK_PERIOD_SIZE, 0, 0x40000000;eax
+
+	   ret
+endp
+
+
+align 4
+proc detect_controller
+	   locals
+	     last_bus dd ?
+	     bus      dd ?
+	     devfn    dd ?
+	   endl
+
+	   xor eax, eax
+	   mov [bus], eax
+	   inc eax
+	   call PciApi
+	   cmp eax, -1
+	   je .err
+
+	   mov [last_bus], eax
+
+.next_bus:
+	   and [devfn], 0
+.next_dev:
+	   stdcall PciRead32, [bus], [devfn], dword 0
+	   test eax, eax
+	   jz .next
+	   cmp eax, -1
+	   je .next
+
+	   mov edi, devices
+@@:
+	   mov ebx, [edi]
+	   test ebx, ebx
+	   jz .next
+
+	   cmp eax, ebx
+	   je .found
+	   add edi, 12
+	   jmp @B
+.next:
+	   inc [devfn]
+	   cmp [devfn], 256
+	   jb .next_dev
+	   mov eax, [bus]
+	   inc eax
+	   mov [bus], eax
+	   cmp eax, [last_bus]
+	   jna .next_bus
+	   xor eax, eax
+	   ret
+.found:
+	   mov ebx, [bus]
+	   mov [ctrl.bus], ebx
+
+	   mov ecx, [devfn]
+	   mov [ctrl.devfn], ecx
+
+	   mov edx, eax
+	   and edx, 0xFFFF
+	   mov [ctrl.vendor], edx
+	   shr eax, 16
+	   mov [ctrl.dev_id], eax
+
+	   mov ebx, [edi+4]
+	   mov [ctrl.ctrl_ids], ebx
+	   mov esi, [edi+8]
+	   mov [ctrl.ctrl_setup], esi
+
+	   cmp edx, VID_Creative
+	   jne @F
+	   mov [ctrl.vendor_ids], msg_Creative
+	   ret
+@@:
+
+.err:
+	   xor eax, eax
+	   mov [ctrl.vendor_ids], eax	  ;something  wrong ?
+	   ret
+endp
+
+align 4
+proc init_controller
+
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C
+	   mov	    esi, msgPciSubsys
+	   call     SysMsgBoardStr
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 4
+	   mov	    ebx, eax
+	   and	    eax, 0xFFFF
+	   mov	    [ctrl.pci_cmd], eax
+	   shr	    ebx, 16
+	   mov	    [ctrl.pci_stat], ebx
+
+	   mov	    esi, msgPciCmd
+	   call     SysMsgBoardStr
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   mov	    esi, msgPciStat
+	   call     SysMsgBoardStr
+	   mov	    eax, [ctrl.pci_stat]
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   mov	    esi, msgCtrlIsaIo
+	   call     SysMsgBoardStr
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   and	    eax, 0xFFC0
+	   mov	    [ctrl.ctrl_io_base], eax
+
+.default:
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C
+	   and	    eax, 0xFF
+@@:
+	   mov	    [ctrl.int_line], eax
+
+	   call     [ctrl.ctrl_setup]
+	   xor	    eax, eax
+	   inc	    eax
+	   ret
+endp
+
+align 4
+proc set_Creative
+	   mov	    [ctrl.codec_read16],  codec_io_r16	  ;virtual
+	   mov	    [ctrl.codec_write16], codec_io_w16	  ;virtual
+
+	   mov	    [ctrl.ctrl_read8 ],  ctrl_io_r8	  ;virtual
+	   mov	    [ctrl.ctrl_read16],  ctrl_io_r16	  ;virtual
+	   mov	    [ctrl.ctrl_read32],  ctrl_io_r32	  ;virtual
+
+	   mov	    [ctrl.ctrl_write8 ], ctrl_io_w8	  ;virtual
+	   mov	    [ctrl.ctrl_write16], ctrl_io_w16	  ;virtual
+	   mov	    [ctrl.ctrl_write32], ctrl_io_w32	  ;virtual
+	   ret
+endp
+
+
+align 4
+proc init_codec
+	   call     reset_codec
+	   test     eax, eax
+	   jz	    .err
+	   call     detect_codec
+	   xor	    eax, eax
+	   inc	    eax
+	   ret
+     .err:
+	   xor	    eax, eax
+	   ret
+endp
+
+align 4
+proc reset_codec
+	   locals
+	     counter dd ?
+	   endl
+
+     if DEBUG
+	   mov	 esi, msgCold
+	   call  SysMsgBoardStr
+     end if
+
+	   mov	    eax, 100000     ; wait 100 ms ;400000     ; wait 400 ms
+	   call     StallExec
+
+	   stdcall  ptr_read, TRIGGER_CHANNEL, 0
+
+	   mov	    [counter], 16    ; total 20*100 ms = 2s
+.wait:
+	   stdcall  codec_read, dword 0x26
+	   test     eax, 1
+	   jnz	    .ok
+
+	   mov	    eax, 100000    ; wait 100 ms
+	   call     StallExec
+
+	   dec	    [counter]
+	   jnz	    .wait
+
+     if DEBUG
+	   mov	 esi, msgCRFail
+	   call  SysMsgBoardStr
+     end if
+
+.fail:
+	   stc
+	   ret
+.ok:
+
+
+	   xor	    eax, eax
+	   inc	    eax
+	   ret
+endp
+
+
+align 4
+play:
+	   mov	    eax, INTE_CH_0_LOOP
+	   stdcall  intr_enable, eax
+
+	   stdcall  ptr_read, TRIGGER_CHANNEL, 0
+	   mov	    ebx, TRIGGER_CHANNEL_0
+	   or	    eax, ebx
+	   stdcall  ptr_write, TRIGGER_CHANNEL, 0, eax
+
+	   xor	    eax, eax
+	   ret
+
+align 4
+stop:
+	   mov	    eax, INTE_CH_0_LOOP or INTE_CH_0_HALF_LOOP
+	   stdcall  intr_disable, eax
+
+	   stdcall  ptr_read, TRIGGER_CHANNEL, 0
+	   mov	    ebx, TRIGGER_CHANNEL_0
+	   xor	    ebx, -1
+	   or	    eax, ebx
+	   stdcall  ptr_write, TRIGGER_CHANNEL, 0, eax
+	   xor	    eax, eax
+	   ret
+
+align 4
+proc get_dev_info stdcall, p_info:dword
+	   virtual at esi
+	     CTRL_INFO CTRL_INFO
+	   end virtual
+
+	   mov	    esi, [p_info]
+	   mov	    eax, [ctrl.int_line]
+	   mov	    ecx, [ctrl.ctrl_io_base]
+	   mov	    [CTRL_INFO.irq], eax
+	   mov	    [CTRL_INFO.ctrl_io_base], ecx
+	   mov	    eax, [codec.chip_id]
+	   mov	    [CTRL_INFO.codec_id], eax
+	   mov	    ebx, [ctrl.pci_cmd]
+	   mov	    [CTRL_INFO.pci_cmd], ebx
+
+	   xor	    eax, eax
+	   mov	    [CTRL_INFO.codec_io_base], eax
+	   mov	    [CTRL_INFO.codec_mem_base], eax
+	   mov	    [CTRL_INFO.ctrl_mem_base], eax
+	   mov	    [CTRL_INFO.glob_cntrl], eax
+	   mov	    [CTRL_INFO.glob_sta], eax
+	   ret
+endp
+
+align 4
+proc set_callback stdcall, handler:dword
+	   mov	    eax, [handler]
+	   mov	    [ctrl.user_callback], eax
+	   ret
+endp
+
+
+align 4
+proc create stdcall
+	   stdcall  PciRead16, [ctrl.bus], [ctrl.devfn], dword 4
+	   test     eax, 4 ; test master bit
+	   jnz	    @f
+	   or	    eax, 4
+	   stdcall  PciWrite16, [ctrl.bus], [ctrl.devfn], dword 4, eax ; set master bit
+	 @@:
+
+	   xor	    eax, eax
+	   mov	    edx, INTE
+	   call     [ctrl.ctrl_write32]
+
+	   stdcall  ptr_write, SPCS0, 0, \
+			       SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \
+			       SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \
+			       SPCS_GENERATIONSTATUS or 0x00001200 or \
+			       0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT
+	   stdcall  ptr_write, SPCS1, 0, \
+			       SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \
+			       SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \
+			       SPCS_GENERATIONSTATUS or 0x00001200 or \
+			       0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT
+	   stdcall  ptr_write, SPCS2, 0, \
+			       SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \
+			       SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \
+			       SPCS_GENERATIONSTATUS or 0x00001200 or \
+			       0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT
+
+	   stdcall  ptr_write, SPDIF_SELECT, 0, 0x700  ; disable SPDIF
+	   stdcall  ptr_write, ROUTING, 0, 0x1003F     ; routing
+	   stdcall  gpio_write, 0x1080		       ; analog mode
+
+	   mov	    eax, dword HCFG_LOCKSOUNDCACHE or HCFG_AUDIOENABLE
+	   mov	    edx, HCFG
+	   call     [ctrl.ctrl_write32]
+	   ret
+endp
+
+align 4
+proc codec_read stdcall, reg:dword
+	   stdcall  ac97_read, dword [reg]
+	   ret
+endp
+
+
+align 4
+proc codec_write stdcall, reg:dword
+	   stdcall  ac97_write, dword [reg], eax
+	   ret
+endp
+
+
+align 4
+proc ac97_read stdcall, reg:dword
+	   push     edx
+	   mov	    eax, dword [reg]
+	   mov	    edx, AC97ADDRESS
+	   call     [ctrl.ctrl_write8]
+
+	   mov	    edx, AC97DATA
+	   call     [ctrl.ctrl_read16]
+	   and	    eax, 0xFFFF
+	   pop	    edx
+	   ret
+endp
+
+align 4
+proc ac97_write stdcall, reg:dword, val:dword
+	   push     eax edx
+	   mov	    eax, dword [reg]
+	   mov	    edx, AC97ADDRESS
+	   call     [ctrl.ctrl_write8]
+
+	   mov	    eax, dword [val]
+	   mov	    edx, AC97DATA
+	   call     [ctrl.ctrl_write16]
+	   pop	    edx eax
+	   ret
+endp
+
+align 4
+proc ptr_read stdcall, reg:dword, chn:dword
+	   push     edx
+	   mov	    eax, dword [reg]
+	   shl	    eax, 16
+	   or	    eax, dword [chn]
+
+	   mov	    edx, PTR
+	   call     [ctrl.ctrl_write32]
+
+	   mov	    edx, DATA
+	   call     [ctrl.ctrl_read32]
+	   pop	    edx
+	ret
+endp
+
+align 4
+proc ptr_write stdcall, reg:dword, chn:dword, data:dword
+	   push     eax edx
+	   mov	    eax, dword [reg]
+	   shl	    eax, 16
+	   or	    eax, dword [chn]
+
+	   mov	    edx, PTR
+	   call     [ctrl.ctrl_write32]
+
+	   mov	    eax, dword [data]
+	   mov	    edx, DATA
+	   call     [ctrl.ctrl_write32]
+	   pop	    edx eax
+	ret
+endp
+
+align 4
+proc intr_enable stdcall, intrenb:dword
+	   push     edx
+	   mov	    edx, INTE
+	   call     [ctrl.ctrl_read32]
+
+	   or	    eax, dword [intrenb]
+	   mov	    edx, INTE
+	   call     [ctrl.ctrl_write32]
+	   pop	    edx
+	   ret
+endp
+
+align 4
+proc intr_disable stdcall, intrenb:dword
+	   push     eax ebx edx
+	   mov	    edx, INTE
+	   call     [ctrl.ctrl_read32]
+
+	   mov	    ebx, dword [intrenb]
+	   xor	    ebx, -1
+	   and	    eax, ebx
+	   mov	    edx, INTE
+	   call     [ctrl.ctrl_write32]
+	   pop	    edx ebx eax
+	   ret
+endp
+
+align 4
+proc gpio_write stdcall, value:dword
+	   push     eax edx
+	   mov	    eax, dword [value]
+	   mov	    edx, GPIO
+	   call     [ctrl.ctrl_write32]
+	   pop	    edx eax
+	   ret
+endp
+
+
+align 4
+proc StallExec
+	   push     ecx
+	   push     edx
+	   push     ebx
+	   push     eax
+
+	   mov	    ecx, CPU_FREQ
+	   mul	    ecx
+	   mov	    ebx, eax	   ;low
+	   mov	    ecx, edx	   ;high
+	   rdtsc
+	   add	    ebx, eax
+	   adc	    ecx, edx
+@@:
+	   rdtsc
+	   sub	    eax, ebx
+	   sbb	    edx, ecx
+	   js	    @B
+
+	   pop	    eax
+	   pop	    ebx
+	   pop	    edx
+	   pop	    ecx
+	   ret
+endp
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;          CONTROLLER IO functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+align 4
+proc codec_io_r16 ;Not used.
+	   ;mov      edx, [ctrl.ctrl_io_base]
+	   ;in       eax, dx
+	   ret
+endp
+
+align 4
+proc codec_io_w16 ;Not used.
+	   ;mov      edx, [ctrl.ctrl_io_base]
+	   ;out      dx,  eax
+	   ret
+endp
+
+align 4
+proc ctrl_io_r8
+	   add	    edx, [ctrl.ctrl_io_base]
+	   in	    al, dx
+	   ret
+endp
+
+align 4
+proc ctrl_io_r16
+	   add	    edx, [ctrl.ctrl_io_base]
+	   in	    ax, dx
+	   ret
+endp
+
+align 4
+proc ctrl_io_r32
+	   add	    edx, [ctrl.ctrl_io_base]
+	   in	    eax, dx
+	   ret
+endp
+
+align 4
+proc ctrl_io_w8
+	   add	    edx, [ctrl.ctrl_io_base]
+	   out	    dx, al
+	   ret
+endp
+
+align 4
+proc ctrl_io_w16
+	   add	    edx, [ctrl.ctrl_io_base]
+	   out	    dx, ax
+	   ret
+endp
+
+align 4
+proc ctrl_io_w32
+	   add	    edx, [ctrl.ctrl_io_base]
+	   out	    dx, eax
+	   ret
+endp
+
+
+align 4
+dword2str:
+	   push     eax ebx ecx
+	   mov	    esi, hex_buff
+	   mov	    ecx, -8
+   @@:
+	   rol	    eax, 4
+	   mov	    ebx, eax
+	   and	    ebx, 0x0F
+	   mov	    bl, [ebx+hexletters]
+	   mov	    [8+esi+ecx], bl
+	   inc	    ecx
+	   jnz	    @B
+	   pop	    ecx ebx eax
+	   ret
+
+hexletters   db '0123456789ABCDEF'
+hex_buff     db 8 dup(0),13,10,0
+
+
+include "codec.inc"
+
+align 4
+devices dd (CTRL_CT0200 shl 16)+VID_Creative,msg_CT_EMU10K1X,set_Creative
+	dd 0	;terminator
+
+
+version      dd (5 shl 16) or (API_VERSION and 0xFFFF)
+
+msg_CT_EMU10K1X  db 'SB Live! Dell OEM', 13,10, 0
+msg_Creative	 db 'Creative ', 0
+
+szKernel	    db 'KERNEL', 0
+sz_sound_srv	    db 'SOUND',0
+
+msgInit      db 'detect hardware...',13,10,0
+msgFail      db 'device not found',13,10,0
+msgAttchIRQ  db 'IRQ line not supported', 13,10, 0
+msgInvIRQ    db 'IRQ line not assigned or invalid', 13,10, 0
+msgPlay      db 'start play', 13,10,0
+msgStop      db 'stop play',  13,10,0
+msgIRQ	     db 'AC97 IRQ', 13,10,0
+;msgInitCtrl  db 'init controller',13,10,0
+;msgInitCodec db 'init codec',13,10,0
+msgPrimBuff  db 'create primary buffer ...',0
+msgDone      db 'done',13,10,0
+msgRemap     db 'Remap IRQ',13,10,0
+;msgReg       db 'set service handler',13,10,0
+;msgOk        db 'service installed',13,10,0
+msgCold      db 'cold reset',13,10,0
+;msgWarm      db 'warm reset',13,10,0
+;msgWRFail    db 'warm reset failed',13,10,0
+msgCRFail    db 'cold reset failed',13,10,0
+;msgCFail     db 'codec not ready',13,10,0
+;msgCInvalid  db 'codec is not valid',13,10,0 ;Asper
+;msgResetOk   db 'reset complete',13,10,0
+;msgStatus    db 'global status   ',0
+;msgControl   db 'global control  ',0
+msgPciCmd    db 'PCI command     ',0
+msgPciStat   db 'PCI status      ',0
+msgPciSubsys db 'PCI subsystem   ',0
+msgCtrlIsaIo db 'controller io base   ',0
+;msgMixIsaIo  db 'codec io base        ',0
+;msgCtrlMMIo  db 'controller mmio base ',0
+;msgMixMMIo   db 'codec mmio base      ',0
+;msgIrqMap    db 'AC97 irq map as      ',0
+
+section '.data' data readable writable align 16
+
+pcmout_bdl	 rq 32
+buff_list	 rd 32
+
+codec CODEC
+ctrl AC_CNTRL
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/imports.inc b/kernel/branches/Kolibri-A/trunk/drivers/imports.inc
index df1ee70f0c..c4a7dac43c 100644
--- a/kernel/branches/Kolibri-A/trunk/drivers/imports.inc
+++ b/kernel/branches/Kolibri-A/trunk/drivers/imports.inc
@@ -26,6 +26,10 @@ kernel_export \
 	      FpuRestore,\
 	      ReservePortArea,\
 	      Boot_Log,\
+\
+              MutexInit,\
+              MutexLock,\
+              MutexUnlock,\
 \
 	      PciApi,\
 	      PciRead32,\
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/infinity.asm b/kernel/branches/Kolibri-A/trunk/drivers/infinity.asm
index bcfbe909d4..307d5a85b3 100644
--- a/kernel/branches/Kolibri-A/trunk/drivers/infinity.asm
+++ b/kernel/branches/Kolibri-A/trunk/drivers/infinity.asm
@@ -159,31 +159,44 @@ inp_size   equ  IOCTL.inp_size
 output     equ  IOCTL.output
 out_size   equ  IOCTL.out_size
 
+
+
 align 4
+
+srv_calls  dd service_proc.srv_getversion       ; 0
+           dd service_proc.snd_create_buff      ; 1
+           dd service_proc.snd_destroy_buff     ; 2
+           dd service_proc.snd_setformat        ; 3
+           dd service_proc.snd_getformat        ; 4
+           dd service_proc.snd_reset            ; 5
+           dd service_proc.snd_setpos           ; 6
+           dd service_proc.snd_getpos           ; 7
+           dd service_proc.snd_setbuff          ; 8
+           dd service_proc.snd_out              ; 9
+           dd service_proc.snd_play             ; 10
+           dd service_proc.snd_stop             ; 11
+           dd service_proc.snd_setvolume        ; 12
+           dd service_proc.snd_getvolume        ; 13
+           dd service_proc.snd_setpan           ; 14
+           dd service_proc.snd_getpan           ; 15
+           dd service_proc.snd_getbuffsize      ; 16
+           dd service_proc.snd_getfreespace     ; 17
+           dd service_proc.snd_settimebase      ; 18
+           dd service_proc.snd_gettimestamp     ; 19
+srv_calls_end:
+
 proc service_proc stdcall, ioctl:dword
 
            mov edi, [ioctl]
            mov eax, [edi+io_code]
 
-           cmp eax, SRV_GETVERSION
-           jne @F
-           mov eax, [edi+output]
-           cmp [edi+out_size], 4
-           jne .fail
-           mov eax, [eax]
-           mov [eax], dword API_VERSION
-           xor eax, eax
-           ret
-@@:
+           cmp eax, (srv_calls_end-srv_calls)/4
+           ja  .fail
+
            cmp eax, SND_CREATE_BUFF
-           jne @F
-           mov ebx, [edi+input]
-           stdcall CreateBuffer,[ebx],[ebx+4]
-           mov edi, [ioctl]
-           mov ecx, [edi+output]
-           mov ecx, [ecx]
-           mov [ecx], ebx
-           ret
+           ja @F
+
+           jmp [srv_calls+eax*4]
 @@:
            mov ebx, [edi+input]
            mov edx, [ebx]
@@ -191,114 +204,132 @@ proc service_proc stdcall, ioctl:dword
            cmp [edx+STREAM.magic], 'WAVE'
            jne .fail
 
-           cmp [edx+STREAM.size], STREAM_SIZE
+           cmp [edx+STREAM.size], STREAM.sizeof
            jne .fail
 
-           cmp eax, SND_DESTROY_BUFF
-           jne @F
-           mov eax, edx
-           call DestroyBuffer    ;edx= stream
+           jmp [srv_calls+eax*4]
+.fail:
+           mov eax, -1
            ret
-@@:
-           cmp eax, SND_SETFORMAT
-           jne @F
-           stdcall SetFormat,edx,[ebx+4]
-           ret
-@@:
-           cmp eax, SND_GETFORMAT
-           jne @F
 
+align 4
+.srv_getversion:
+           mov eax, [edi+output]
+           cmp [edi+out_size], 4
+           jne .fail
+           mov eax, [eax]
+           mov [eax], dword API_VERSION
+           xor eax, eax
+           ret
+
+align 4
+.snd_create_buff:
+           mov ebx, [edi+input]
+           stdcall CreateBuffer,[ebx],[ebx+4]
+           mov edi, [ioctl]
+           mov ecx, [edi+output]
+           mov ecx, [ecx]
+           mov [ecx], ebx
+           ret
+
+align 4
+.snd_destroy_buff:
+           mov eax, edx
+           call DestroyBuffer
+           ret
+
+align 4
+.snd_setformat:
+           stdcall SetFormat, edx,[ebx+4]
+           ret
+
+align 4
+.snd_getformat:
            movzx eax, word [edx+STREAM.format]
            mov ecx, [edi+output]
            mov ecx, [ecx]
            mov [ecx], eax
            xor eax, eax
            ret
-@@:
-           cmp eax, SND_RESET
-           jne @F
+
+align 4
+.snd_reset:
            stdcall ResetBuffer,edx,[ebx+4]
            ret
-@@:
-           cmp eax, SND_SETPOS
-           jne @F
+
+align 4
+.snd_setpos:
            stdcall SetBufferPos,edx,[ebx+4]
            ret
-@@:
-           cmp eax, SND_GETPOS
-           jne @F
+
+align 4
+.snd_getpos:
            stdcall GetBufferPos, edx
            mov edi, [ioctl]
            mov ecx, [edi+output]
            mov ecx, [ecx]
            mov [ecx], ebx
            ret
-@@:
-           cmp eax, SND_SETBUFF
-           jne @F
+
+align 4
+.snd_setbuff:
            mov eax, [ebx+4]
            stdcall set_buffer, edx,eax,[ebx+8],[ebx+12]
            ret
-@@:
-           cmp eax, SND_SETVOLUME
-           jne @F
+
+align 4
+.snd_out:
+           mov eax, [ebx+4]
+           stdcall wave_out, edx,eax,[ebx+8]
+           ret
+
+align 4
+.snd_play:
+           stdcall play_buffer, edx,[ebx+4]
+           ret
+
+align 4
+.snd_stop:
+           stdcall stop_buffer, edx
+           ret
+
+align 4
+.snd_setvolume:
            stdcall SetBufferVol,edx,[ebx+4],[ebx+8]
            ret
-@@:
-           cmp eax, SND_GETVOLUME
-           jne @F
 
+align 4
+.snd_getvolume:
            mov eax, [edi+output]
            mov ecx, [eax]
            mov eax, [eax+4]
            stdcall GetBufferVol,edx,ecx,eax
            ret
-@@:
-           cmp eax, SND_SETPAN
-           jne @F
+align 4
+.snd_setpan:
            stdcall SetBufferPan,edx,[ebx+4]
            ret
-@@:
-           cmp eax, SND_GETPAN
-           jne @F
+
+align 4
+.snd_getpan:
            mov eax, [edx+STREAM.pan]
            mov ebx, [edi+output]
            mov ebx, [ebx]
            mov [ebx], eax
            xor eax, eax
            ret
-@@:
-           cmp eax, SND_OUT
-           jne @F
 
-           mov eax, [ebx+4]
-           stdcall wave_out, edx,eax,[ebx+8]
-           ret
-@@:
-           cmp eax, SND_PLAY
-           jne @F
-
-           stdcall play_buffer, edx,[ebx+4]
-           ret
-@@:
-           cmp eax, SND_STOP
-           jne @F
-
-           stdcall stop_buffer, edx
-           ret
-@@:
-           cmp eax, SND_GETBUFFSIZE
-           jne @F
+align 4
+.snd_getbuffsize:
            mov eax, [edx+STREAM.in_size]
            mov ecx, [edi+output]
            mov ecx, [ecx]
            mov [ecx], eax
            xor eax, eax
            ret
-@@:
-           cmp eax, SND_GETFREESPACE
-           jne @F
 
+align 4
+.snd_getfreespace:
            test [edx+STREAM.format], PCM_OUT
            jz .fail
 
@@ -307,12 +338,38 @@ proc service_proc stdcall, ioctl:dword
            mov [ecx], ebx
            xor eax, eax
            ret
-@@:
-.fail:
-           or eax, -1
+align 4
+.snd_settimebase:
+           cmp [edi+inp_size], 8
+           jne .fail
+
+           mov edi, [edi+input]
+           mov eax, [edi]
+           mov ebx, [edi+4]
+           mov dword [edx+STREAM.time_base], eax
+           mov dword [edx+STREAM.time_base+4], ebx
+           xor eax, eax
+           ret
+
+.snd_gettimestamp:
+           cmp [edi+out_size], 8
+           jne .fail
+
+           mov edi, [edi+output]
+
+           push 48
+           emms
+           fild  qword [edx+STREAM.time_stamp]
+           fidiv dword [esp]
+           fadd  qword [edx+STREAM.time_base]
+           fstp  qword [edi]
+           add esp, 4
+
+           xor eax, eax
            ret
 endp
 
+
 restore   handle
 restore   io_code
 restore   input
@@ -352,7 +409,7 @@ proc CreateBuffer stdcall, format:dword, size:dword
 
            call GetPid
            mov ebx, eax
-           mov eax, STREAM_SIZE
+           mov eax, STREAM.sizeof
 
            call CreateObject
            test eax, eax
@@ -412,7 +469,6 @@ proc CreateBuffer stdcall, format:dword, size:dword
            mov [edi+STREAM.in_base], eax
            mov [edi+STREAM.in_size], ecx
            add eax, 128
-        ;   sub ecx, 128
            mov [edi+STREAM.in_wp], eax
            mov [edi+STREAM.in_rp], eax
            mov [edi+STREAM.in_count], 0
@@ -443,13 +499,21 @@ proc CreateBuffer stdcall, format:dword, size:dword
            stdcall AllocKernelSpace, dword 128*1024
 
            mov edi, [str]
+           xor ebx, ebx
+
            mov [edi+STREAM.out_base], eax
            mov [edi+STREAM.out_wp], eax
            mov [edi+STREAM.out_rp], eax
-           mov [edi+STREAM.out_count], 0
+           mov [edi+STREAM.out_count], ebx
            add eax, 64*1024
            mov [edi+STREAM.out_top], eax
 
+           mov dword [edi+STREAM.time_base],   ebx
+           mov dword [edi+STREAM.time_base+4], ebx
+
+           mov dword [edi+STREAM.time_stamp],   ebx
+           mov dword [edi+STREAM.time_stamp+4], ebx
+
            stdcall AllocPages, dword 64/4
            mov edi, [str]
            mov ebx, [edi+STREAM.out_base]
@@ -488,7 +552,7 @@ proc CreateBuffer stdcall, format:dword, size:dword
 
            mov [ebx+STREAM.magic], 'WAVE'
            mov [ebx+STREAM.destroy], DestroyBuffer.destroy
-           mov [ebx+STREAM.size], STREAM_SIZE
+           mov [ebx+STREAM.size], STREAM.sizeof
            mov [ebx+STREAM.flags], SND_STOP
 
            pushf
@@ -1039,7 +1103,7 @@ do_mix_list:
            cmp [ebx+STREAM.magic], 'WAVE'
            jne .next
 
-           cmp [ebx+STREAM.size], STREAM_SIZE
+           cmp [ebx+STREAM.size], STREAM.sizeof
            jne .next
 
            cmp [ebx+STREAM.flags], SND_PLAY;
@@ -1108,7 +1172,7 @@ prepare_playlist:
            cmp [edi+STREAM.magic], 'WAVE'
            jne .next
 
-           cmp [edi+STREAM.size], STREAM_SIZE
+           cmp [edi+STREAM.size], STREAM.sizeof
            jne .next
 
            cmp [edi+STREAM.flags], SND_PLAY;
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/main.inc b/kernel/branches/Kolibri-A/trunk/drivers/main.inc
index 67198c304d..e1d10b3160 100644
--- a/kernel/branches/Kolibri-A/trunk/drivers/main.inc
+++ b/kernel/branches/Kolibri-A/trunk/drivers/main.inc
@@ -91,6 +91,8 @@ SND_SETPAN          equ 14
 SND_GETPAN          equ 15
 SND_GETBUFFSIZE     equ 16
 SND_GETFREESPACE    equ 17
+SND_SETTIMEBASE     equ 18
+SND_GETTIMESTAMP    equ 19
 
 struc STREAM
 {
@@ -113,6 +115,22 @@ struc STREAM
     .out_count     dd ?
     .out_top       dd ?          ;16*4
 
+    .in_base       dd ?
+    .in_size       dd ?
+    .in_wp         dd ?
+    .in_rp         dd ?
+    .in_count      dd ?
+    .in_free       dd ?
+    .in_top        dd ?
+
+align 8
+
+    .time_base     dq ?
+    .time_stamp    dq ?
+
+    .notify_event  dd ?
+    .notify_id     dd ?
+
     .r_size        dd ?
     .r_dt          dd ?
     .r_silence     dd ?
@@ -125,19 +143,9 @@ struc STREAM
     .l_amp_f       dd ? ;float point left
     .r_amp_f       dd ? ;float point right
 
-    .in_base       dd ?
-    .in_size       dd ?
-    .in_wp         dd ?
-    .in_rp         dd ?
-    .in_count      dd ?
-    .in_free       dd ?
-    .in_top        dd ?
-
-    .notify_event  dd ?
-    .notify_id     dd ?
+    .sizeof:
 }
 
-STREAM_SIZE    equ 36*4
 FD_OFFSET      equ 24
 
 virtual at 0
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/mixer.asm b/kernel/branches/Kolibri-A/trunk/drivers/mixer.asm
index f825ef4612..ccb533e463 100644
--- a/kernel/branches/Kolibri-A/trunk/drivers/mixer.asm
+++ b/kernel/branches/Kolibri-A/trunk/drivers/mixer.asm
@@ -87,7 +87,7 @@ end if
 endp
 
 align 4
-proc update_stream
+proc update_streams
            locals
              stream_index  dd ?
              event         rd 6
@@ -98,6 +98,9 @@ proc update_stream
            mov edx, [stream_index]
            mov esi, [play_list+edx*4]
 
+           add dword [esi+STREAM.time_stamp], 4096
+           adc dword [esi+STREAM.time_stamp+4], 0
+
            mov eax, [esi+STREAM.out_rp]
            cmp eax, [esi+STREAM.out_top]
            jb @f
diff --git a/kernel/branches/Kolibri-A/trunk/drivers/vt823(x).asm b/kernel/branches/Kolibri-A/trunk/drivers/vt823(x).asm
new file mode 100644
index 0000000000..51de417386
--- /dev/null
+++ b/kernel/branches/Kolibri-A/trunk/drivers/vt823(x).asm
@@ -0,0 +1,1281 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                              ;;
+;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
+;; Distributed under terms of the GNU General Public License    ;;
+;;                                                              ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+format MS COFF
+
+DEBUG		equ 1
+
+include 'proc32.inc'
+include 'imports.inc'
+
+API_VERSION	equ 0x01000100
+
+USE_COM_IRQ	equ 0	 ;make irq 3 and irq 4 available for PCI devices
+IRQ_REMAP	equ 0
+IRQ_LINE	equ 0
+
+
+;irq 0,1,2,8,12,13 ������㯭�
+;                   FEDCBA9876543210
+VALID_IRQ	equ 1100111011111000b
+ATTCH_IRQ	equ 0000111010100000b
+
+if USE_COM_IRQ
+ATTCH_IRQ	equ 0000111010111000b
+end if
+
+CPU_FREQ	equ  2600d
+
+BIT0  EQU 0x00000001
+BIT1  EQU 0x00000002
+BIT5  EQU 0x00000020
+BIT10 EQU 0x00000400
+
+VID_VIA 	  equ 0x1106
+
+CTRL_VT82C686	  equ 0x3058
+CTRL_VT8233_5	  equ 0x3059
+
+
+CODEC_MASTER_VOL_REG	     equ 0x02
+CODEC_AUX_VOL		     equ 0x04 ;
+CODEC_PCM_OUT_REG	     equ 0x18 ; PCM output volume
+CODEC_EXT_AUDIO_REG	     equ 0x28 ; extended audio
+CODEC_EXT_AUDIO_CTRL_REG     equ 0x2a ; extended audio control
+CODEC_PCM_FRONT_DACRATE_REG  equ 0x2c ; PCM out sample rate
+CODEC_PCM_SURND_DACRATE_REG  equ 0x2e ; surround sound sample rate
+CODEC_PCM_LFE_DACRATE_REG    equ 0x30 ; LFE sample rate
+
+
+;VIA host controller registers set
+;; common offsets
+VIA_REG_OFFSET_STATUS	     equ   0x00    ;; byte - channel status
+  VIA_REG_STAT_ACTIVE		   equ	 0x80	 ;; RO
+  VIA_REG_STAT_PAUSED		   equ	 0x40	 ;; RO
+  VIA_REG_STAT_TRIGGER_QUEUED	   equ	 0x08	 ;; RO
+  VIA_REG_STAT_STOPPED		   equ	 0x04	 ;; RWC
+  VIA_REG_STAT_EOL		   equ	 0x02	 ;; RWC
+  VIA_REG_STAT_FLAG		   equ	 0x01	 ;; RWC
+VIA_REG_OFFSET_CONTROL	     equ   0x01    ;; byte - channel control
+  VIA_REG_CTRL_START		   equ	 0x80	 ;; WO
+  VIA_REG_CTRL_TERMINATE	   equ	 0x40	 ;; WO
+  VIA_REG_CTRL_AUTOSTART	   equ	 0x20
+  VIA_REG_CTRL_PAUSE		   equ	 0x08	 ;; RW
+  VIA_REG_CTRL_INT_STOP 	   equ	 0x04
+  VIA_REG_CTRL_INT_EOL		   equ	 0x02
+  VIA_REG_CTRL_INT_FLAG 	   equ	 0x01
+  VIA_REG_CTRL_RESET		   equ	 0x01	 ;; RW - probably reset? undocumented
+  VIA_REG_CTRL_INT		   equ	(VIA_REG_CTRL_INT_FLAG or \
+					 VIA_REG_CTRL_INT_EOL or \
+					 VIA_REG_CTRL_AUTOSTART)
+VIA_REG_OFFSET_TYPE	     equ   0x02    ;; byte - channel type (686 only)
+  VIA_REG_TYPE_AUTOSTART	   equ	 0x80	 ;; RW - autostart at EOL
+  VIA_REG_TYPE_16BIT		   equ	 0x20	 ;; RW
+  VIA_REG_TYPE_STEREO		   equ	 0x10	 ;; RW
+  VIA_REG_TYPE_INT_LLINE	   equ	 0x00
+  VIA_REG_TYPE_INT_LSAMPLE	   equ	 0x04
+  VIA_REG_TYPE_INT_LESSONE	   equ	 0x08
+  VIA_REG_TYPE_INT_MASK 	   equ	 0x0c
+  VIA_REG_TYPE_INT_EOL		   equ	 0x02
+  VIA_REG_TYPE_INT_FLAG 	   equ	 0x01
+VIA_REG_OFFSET_TABLE_PTR     equ   0x04    ;; dword - channel table pointer
+VIA_REG_OFFSET_CURR_PTR      equ   0x04    ;; dword - channel current pointer
+VIA_REG_OFFSET_STOP_IDX      equ   0x08    ;; dword - stop index, channel type, sample rate
+  VIA8233_REG_TYPE_16BIT	   equ	 0x00200000	 ;; RW
+  VIA8233_REG_TYPE_STEREO	   equ	 0x00100000	 ;; RW
+VIA_REG_OFFSET_CURR_COUNT    equ   0x0c    ;; dword - channel current count (24 bit)
+VIA_REG_OFFSET_CURR_INDEX    equ   0x0f    ;; byte - channel current index (for via8233 only)
+
+
+VIADEV_PLAYBACK 	equ   0x00
+VIADEV_CAPTURE		equ   0x10
+VIADEV_FM		equ   0x20
+
+;; AC'97 ;;
+VIA_REG_AC97		 equ   0x80    ; dword
+  VIA_REG_AC97_CODEC_ID_MASK	   equ	0xC0000000 ;(3<<30)
+  VIA_REG_AC97_CODEC_ID_SHIFT	   equ	30
+  VIA_REG_AC97_CODEC_ID_PRIMARY    equ	0x00
+  VIA_REG_AC97_CODEC_ID_SECONDARY  equ	0x01
+  VIA_REG_AC97_SECONDARY_VALID	   equ	0x08000000 ;(1<<27)
+  VIA_REG_AC97_PRIMARY_VALID	   equ	0x02000000 ;(1<<25)
+  VIA_REG_AC97_BUSY		   equ	0x01000000 ;(1<<24)
+  VIA_REG_AC97_READ		   equ	0x00800000 ;(1<<23)
+  VIA_REG_AC97_CMD_SHIFT	   equ	16
+  VIA_REG_AC97_CMD_MASK 	   equ	0x7E
+  VIA_REG_AC97_DATA_SHIFT	   equ	0
+  VIA_REG_AC97_DATA_MASK	   equ	0xFFFF
+
+VIA_REG_SGD_SHADOW	 equ   0x84    ; dword
+
+;; via8233-specific registers ;;
+VIA_REG_OFS_PLAYBACK_VOLUME_L	equ  0x02    ;; byte
+VIA_REG_OFS_PLAYBACK_VOLUME_R	equ  0x03    ;; byte
+VIA_REG_OFS_MULTPLAY_FORMAT	equ  0x02    ;; byte - format and channels
+  VIA_REG_MULTPLAY_FMT_8BIT	     equ  0x00
+  VIA_REG_MULTPLAY_FMT_16BIT	     equ  0x80
+  VIA_REG_MULTPLAY_FMT_CH_MASK	     equ  0x70	  ;; # channels << 4 (valid = 1,2,4,6)
+VIA_REG_OFS_CAPTURE_FIFO	equ  0x02    ;; byte - bit 6 = fifo  enable
+  VIA_REG_CAPTURE_FIFO_ENABLE	     equ  0x40
+
+VIA_DXS_MAX_VOLUME		equ  31      ;; max. volume (attenuation) of reg 0x32/33
+
+VIA_TBL_BIT_FLAG	  equ	0x40000000
+VIA_TBL_BIT_EOL 	  equ	0x80000000
+
+;; pci space ;;
+VIA_ACLINK_STAT 	  equ	0x40
+  ;...
+  VIA_ACLINK_C00_READY		   equ	 0x01 ; primary codec ready
+VIA_ACLINK_CTRL 	  equ	0x41
+  VIA_ACLINK_CTRL_ENABLE	   equ	 0x80 ; 0: disable, 1: enable
+  VIA_ACLINK_CTRL_RESET 	   equ	 0x40 ; 0: assert, 1: de-assert
+  VIA_ACLINK_CTRL_SYNC		   equ	 0x20 ; 0: release SYNC, 1: force SYNC hi
+  VIA_ACLINK_CTRL_SDO		   equ	 0x10 ; 0: release SDO, 1: force SDO hi
+  VIA_ACLINK_CTRL_VRA		   equ	 0x08 ; 0: disable VRA, 1: enable VRA
+  VIA_ACLINK_CTRL_PCM		   equ	 0x04 ; 0: disable PCM, 1: enable PCM
+  VIA_ACLINK_CTRL_FM		   equ	 0x02 ; via686 only
+  VIA_ACLINK_CTRL_SB		   equ	 0x01 ; via686 only
+  VIA_ACLINK_CTRL_INIT		   equ	(VIA_ACLINK_CTRL_ENABLE or \
+					 VIA_ACLINK_CTRL_RESET or \
+					 VIA_ACLINK_CTRL_PCM or \
+					 VIA_ACLINK_CTRL_VRA)
+VIA_FUNC_ENABLE 	  equ	0x42
+  VIA_FUNC_MIDI_PNP		   equ	 0x80 ; FIXME: it's 0x40 in the datasheet!
+  VIA_FUNC_MIDI_IRQMASK 	   equ	 0x40 ; FIXME: not documented!
+  VIA_FUNC_RX2C_WRITE		   equ	 0x20
+  VIA_FUNC_SB_FIFO_EMPTY	   equ	 0x10
+  VIA_FUNC_ENABLE_GAME		   equ	 0x08
+  VIA_FUNC_ENABLE_FM		   equ	 0x04
+  VIA_FUNC_ENABLE_MIDI		   equ	 0x02
+  VIA_FUNC_ENABLE_SB		   equ	 0x01
+VIA_PNP_CONTROL 	  equ	0x43
+VIA_FM_NMI_CTRL 	  equ	0x48
+VIA8233_VOLCHG_CTRL	  equ	0x48
+VIA8233_SPDIF_CTRL	  equ	0x49
+  VIA8233_SPDIF_DX3		   equ	 0x08
+  VIA8233_SPDIF_SLOT_MASK	   equ	 0x03
+  VIA8233_SPDIF_SLOT_1011	   equ	 0x00
+  VIA8233_SPDIF_SLOT_34 	   equ	 0x01
+  VIA8233_SPDIF_SLOT_78 	   equ	 0x02
+  VIA8233_SPDIF_SLOT_69 	   equ	 0x03
+;] Asper
+
+
+SRV_GETVERSION	      equ  0
+DEV_PLAY	      equ  1
+DEV_STOP	      equ  2
+DEV_CALLBACK	      equ  3
+DEV_SET_BUFF	      equ  4
+DEV_NOTIFY	      equ  5
+DEV_SET_MASTERVOL     equ  6
+DEV_GET_MASTERVOL     equ  7
+DEV_GET_INFO	      equ  8
+
+struc AC_CNTRL		    ;AC controller base class
+{ .bus		      dd ?
+  .devfn	      dd ?
+
+  .vendor	      dd ?
+  .dev_id	      dd ?
+  .pci_cmd	      dd ?
+  .pci_stat	      dd ?
+
+  .codec_io_base      dd ?
+  .codec_mem_base     dd ?
+
+  .ctrl_io_base       dd ?
+  .ctrl_mem_base      dd ?
+  .cfg_reg	      dd ?
+  .int_line	      dd ?
+
+  .vendor_ids	      dd ?    ;vendor id string
+  .ctrl_ids	      dd ?    ;hub id string
+
+  .buffer	      dd ?
+
+  .notify_pos	      dd ?
+  .notify_task	      dd ?
+
+  .lvi_reg	      dd ?
+  .ctrl_setup	      dd ?
+  .user_callback      dd ?
+  .codec_read16       dd ?
+  .codec_write16      dd ?
+
+  .ctrl_read8	      dd ?
+  .ctrl_read16	      dd ?
+  .ctrl_read32	      dd ?
+
+  .ctrl_write8	      dd ?
+  .ctrl_write16       dd ?
+  .ctrl_write32       dd ?
+}
+
+struc CODEC		   ;Audio Chip base class
+{
+  .chip_id	      dd ?
+  .flags	      dd ?
+  .status	      dd ?
+
+  .ac_vendor_ids      dd ?    ;ac vendor id string
+  .chip_ids	      dd ?    ;chip model string
+
+  .shadow_flag	      dd ?
+		      dd ?
+
+  .regs 	      dw ?     ; codec registers
+  .reg_master_vol     dw ?     ;0x02
+  .reg_aux_out_vol    dw ?     ;0x04
+  .reg_mone_vol       dw ?     ;0x06
+  .reg_master_tone    dw ?     ;0x08
+  .reg_beep_vol       dw ?     ;0x0A
+  .reg_phone_vol      dw ?     ;0x0C
+  .reg_mic_vol	      dw ?     ;0x0E
+  .reg_line_in_vol    dw ?     ;0x10
+  .reg_cd_vol	      dw ?     ;0x12
+  .reg_video_vol      dw ?     ;0x14
+  .reg_aux_in_vol     dw ?     ;0x16
+  .reg_pcm_out_vol    dw ?     ;0x18
+  .reg_rec_select     dw ?     ;0x1A
+  .reg_rec_gain       dw ?     ;0x1C
+  .reg_rec_gain_mic   dw ?     ;0x1E
+  .reg_gen	      dw ?     ;0x20
+  .reg_3d_ctrl	      dw ?     ;0X22
+  .reg_page	      dw ?     ;0X24
+  .reg_powerdown      dw ?     ;0x26
+  .reg_ext_audio      dw ?     ;0x28
+  .reg_ext_st	      dw ?     ;0x2a
+  .reg_pcm_front_rate dw ?     ;0x2c
+  .reg_pcm_surr_rate  dw ?     ;0x2e
+  .reg_lfe_rate       dw ?     ;0x30
+  .reg_pcm_in_rate    dw ?     ;0x32
+		      dw ?     ;0x34
+  .reg_cent_lfe_vol   dw ?     ;0x36
+  .reg_surr_vol       dw ?     ;0x38
+  .reg_spdif_ctrl     dw ?     ;0x3A
+		      dw ?     ;0x3C
+		      dw ?     ;0x3E
+		      dw ?     ;0x40
+		      dw ?     ;0x42
+		      dw ?     ;0x44
+		      dw ?     ;0x46
+		      dw ?     ;0x48
+		      dw ?     ;0x4A
+		      dw ?     ;0x4C
+		      dw ?     ;0x4E
+		      dw ?     ;0x50
+		      dw ?     ;0x52
+		      dw ?     ;0x54
+		      dw ?     ;0x56
+		      dw ?     ;0x58
+		      dw ?     ;0x5A
+		      dw ?     ;0x5C
+		      dw ?     ;0x5E
+  .reg_page_0	      dw ?     ;0x60
+  .reg_page_1	      dw ?     ;0x62
+  .reg_page_2	      dw ?     ;0x64
+  .reg_page_3	      dw ?     ;0x66
+  .reg_page_4	      dw ?     ;0x68
+  .reg_page_5	      dw ?     ;0x6A
+  .reg_page_6	      dw ?     ;0x6C
+  .reg_page_7	      dw ?     ;0x6E
+		      dw ?     ;0x70
+		      dw ?     ;0x72
+		      dw ?     ;0x74
+		      dw ?     ;0x76
+		      dw ?     ;0x78
+		      dw ?     ;0x7A
+  .reg_vendor_id_1    dw ?     ;0x7C
+  .reg_vendor_id_2    dw ?     ;0x7E
+
+
+  .reset	      dd ?    ;virual
+  .set_master_vol     dd ?
+}
+
+struc CTRL_INFO
+{   .pci_cmd	      dd ?
+    .irq	      dd ?
+    .glob_cntrl       dd ?
+    .glob_sta	      dd ?
+    .codec_io_base    dd ?
+    .ctrl_io_base     dd ?
+    .codec_mem_base   dd ?
+    .ctrl_mem_base    dd ?
+    .codec_id	      dd ?
+}
+
+struc IOCTL
+{  .handle	      dd ?
+   .io_code	      dd ?
+   .input	      dd ?
+   .inp_size	      dd ?
+   .output	      dd ?
+   .out_size	      dd ?
+}
+
+virtual at 0
+  IOCTL IOCTL
+end virtual
+
+EVENT_NOTIFY	equ 0x00000200
+
+public START
+public service_proc
+public version
+
+section '.flat' code readable align 16
+
+proc START stdcall, state:dword
+
+	   cmp	 [state], 1
+	   jne	 .stop
+
+     if DEBUG
+	   mov	 esi, msgInit
+	   call  SysMsgBoardStr
+     end if
+
+	   call     detect_controller
+	   test     eax, eax
+	   jz	    .fail
+
+     if DEBUG
+	   mov	 esi,[ctrl.vendor_ids]
+	   call  SysMsgBoardStr
+	   mov	 esi, [ctrl.ctrl_ids]
+	   call  SysMsgBoardStr
+     end if
+
+	   call     init_controller
+	   test     eax, eax
+	   jz	    .fail
+
+	   call     init_codec
+	   test     eax, eax
+	   jz	    .fail
+
+	   call     setup_codec
+
+	   mov	    esi, msgPrimBuff
+	   call     SysMsgBoardStr
+	   call     create_primary_buff
+	   mov	    esi, msgDone
+	   call     SysMsgBoardStr
+
+  if IRQ_REMAP
+	   pushf
+	   cli
+
+	   mov	    ebx, [ctrl.int_line]
+	   in	    al, 0xA1
+	   mov	    ah, al
+	   in	    al, 0x21
+	   test     ebx, ebx
+	   jz	    .skip
+	   bts	    ax, bx			;mask old line
+.skip:
+	   bts	    ax, IRQ_LINE		;mask new ine
+	   out	    0x21, al
+	   mov	    al, ah
+	   out	    0xA1, al
+
+	   stdcall  PciWrite8, 0, 0xF8, 0x61, IRQ_LINE	;remap IRQ
+
+	   mov	    dx, 0x4d0			;8259 ELCR1
+	   in	    al, dx
+	   bts	    ax, IRQ_LINE
+	   out	    dx, al			;set level-triggered mode
+	   mov	    [ctrl.int_line], IRQ_LINE
+	   popf
+	   mov	    esi, msgRemap
+	   call     SysMsgBoardStr
+  end if
+
+	   mov	    eax, VALID_IRQ
+	   mov	    ebx, [ctrl.int_line]
+	   mov	    esi, msgInvIRQ
+	   bt	    eax, ebx
+	   jnc	    .fail_msg
+	   mov	    eax, ATTCH_IRQ
+	   mov	    esi, msgAttchIRQ
+	   bt	    eax, ebx
+	   jnc	    .fail_msg
+
+	   stdcall  AttachIntHandler, ebx, ac97_irq_VIA, dword 0
+.reg:
+	   stdcall  RegService, sz_sound_srv, service_proc
+	   ret
+.fail:
+     if DEBUG
+	   mov	 esi, msgFail
+	   call  SysMsgBoardStr
+     end if
+	   xor	    eax, eax
+	   ret
+.fail_msg:
+	   call     SysMsgBoardStr
+	   xor	    eax, eax
+	   ret
+.stop:
+	   call     stop
+	   xor	    eax, eax
+	   ret
+endp
+
+handle	   equ	IOCTL.handle
+io_code    equ	IOCTL.io_code
+input	   equ	IOCTL.input
+inp_size   equ	IOCTL.inp_size
+output	   equ	IOCTL.output
+out_size   equ	IOCTL.out_size
+
+align 4
+proc service_proc stdcall, ioctl:dword
+
+	   mov	    edi, [ioctl]
+	   mov	    eax, [edi+io_code]
+
+	   cmp	    eax, SRV_GETVERSION
+	   jne	    @F
+	   mov	    eax, [edi+output]
+	   cmp	    [edi+out_size], 4
+	   jne	    .fail
+
+	   mov	    [eax], dword API_VERSION
+	   xor	    eax, eax
+	   ret
+@@:
+	   cmp	    eax, DEV_PLAY
+	   jne	    @F
+     if DEBUG
+	   mov	esi, msgPlay
+	   call SysMsgBoardStr
+     end if
+	   call     play
+	   ret
+@@:
+	   cmp	    eax, DEV_STOP
+	   jne	    @F
+     if DEBUG
+	   mov	esi, msgStop
+	   call SysMsgBoardStr
+     end if
+	   call     stop
+	   ret
+@@:
+	   cmp	    eax, DEV_CALLBACK
+	   jne	    @F
+	   mov	    ebx, [edi+input]
+	   stdcall  set_callback, [ebx]
+	   ret
+@@:
+	   cmp	    eax, DEV_SET_MASTERVOL
+	   jne	    @F
+	   mov	    eax, [edi+input]
+	   mov	    eax, [eax]
+	   call     set_master_vol	;eax= vol
+	   ret
+@@:
+	   cmp	    eax, DEV_GET_MASTERVOL
+	   jne	    @F
+	   mov	    ebx, [edi+output]
+	   stdcall  get_master_vol, ebx
+	   ret
+@@:
+	   cmp	    eax, DEV_GET_INFO
+	   jne	    @F
+	   mov	    ebx, [edi+output]
+	   stdcall  get_dev_info, ebx
+	   ret
+@@:
+.fail:
+	   or	    eax, -1
+	   ret
+endp
+
+restore   handle
+restore   io_code
+restore   input
+restore   inp_size
+restore   output
+restore   out_size
+
+
+align 4
+proc ac97_irq_VIA
+	   locals
+	     status db 0
+	   endl
+
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_STATUS
+	   call     [ctrl.ctrl_read8]
+	   test     al, VIA_REG_STAT_ACTIVE
+	   jz	    @f
+
+	   and	    al, VIA_REG_STAT_EOL or VIA_REG_STAT_FLAG or VIA_REG_STAT_STOPPED
+	   mov	    byte [status], al
+
+	   mov	    ebx, dword [buff_list]
+	   cmp	    [ctrl.user_callback], 0
+	   je	    @f
+	   stdcall  [ctrl.user_callback], ebx
+       @@:
+	   mov	    al, byte [status]		;; ack ;;
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_STATUS
+	   call     [ctrl.ctrl_write8]
+
+	   ret
+endp
+
+
+align 4
+proc create_primary_buff
+
+	   stdcall  KernelAlloc, 0x10000
+	   mov	    [ctrl.buffer], eax
+
+	   mov	    edi, eax
+	   mov	    ecx, 0x10000/4
+	   xor	    eax, eax
+	   cld
+	   rep	    stosd
+
+	   mov	    eax, [ctrl.buffer]
+	   call     GetPgAddr
+	   mov	    edi, pcmout_bdl
+	   stosd
+	   mov	    eax, 0x80004000
+	   stosd
+
+	   mov	    edi, buff_list
+	   mov	    eax, [ctrl.buffer]
+	   mov	    ecx, 4
+@@:
+	   mov	    [edi], eax
+	   mov	    [edi+16], eax
+	   mov	    [edi+32], eax
+	   mov	    [edi+48], eax
+	   mov	    [edi+64], eax
+	   mov	    [edi+80], eax
+	   mov	    [edi+96], eax
+	   mov	    [edi+112], eax
+
+	   ;add      eax, 0x4000
+	   add	    edi, 4
+	   loop     @B
+
+	   stdcall  channel_reset, VIADEV_PLAYBACK
+	   stdcall  codec_check_ready
+
+	   mov	    eax, pcmout_bdl
+	   mov	    ebx, eax
+	   call     GetPgAddr
+	   and	    ebx, 0xFFF
+	   add	    eax, ebx
+
+	   mov	    edx, VIADEV_PLAYBACK  +VIA_REG_OFFSET_TABLE_PTR
+	   call     [ctrl.ctrl_write32]
+
+	   stdcall  codec_check_ready
+
+	   mov	    edx, VIADEV_PLAYBACK  +VIA_REG_OFS_PLAYBACK_VOLUME_L
+	   mov	    eax, 7;31
+	   call     [ctrl.ctrl_write8]
+
+	   mov	    edx, VIADEV_PLAYBACK  +VIA_REG_OFS_PLAYBACK_VOLUME_R
+	   mov	    eax, 7;31
+	   call     [ctrl.ctrl_write8]
+
+	   mov	    edx, VIADEV_PLAYBACK  +VIA_REG_OFFSET_STOP_IDX
+	   mov	    eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000
+	   mov	  [ctrl.lvi_reg], 16;0xF;eax
+	   call     [ctrl.ctrl_write32]
+
+	   stdcall  codec_check_ready
+	   ret
+endp
+
+
+proc channel_reset channel:dword
+	   mov	    esi, dword [channel]
+	   mov	    edx, esi
+	   add	    edx, VIA_REG_OFFSET_CONTROL
+	   mov	    eax, VIA_REG_CTRL_PAUSE or VIA_REG_CTRL_TERMINATE or VIA_REG_CTRL_RESET
+	   call     [ctrl.ctrl_write8]
+
+	   mov	    edx, esi
+	   add	    edx, VIA_REG_OFFSET_CONTROL
+	   call     [ctrl.ctrl_read8]
+
+	   mov	    eax, 50000	 ; wait 50 ms
+	   call     StallExec
+	   ; disable interrupts
+	   mov	    edx, esi
+	   add	    edx, VIA_REG_OFFSET_CONTROL
+	   xor	    eax, eax
+	   call     [ctrl.ctrl_write8]
+
+	   ; clear interrupts
+	   mov	    edx, esi
+	   add	    edx, VIA_REG_OFFSET_STATUS
+	   mov	    eax, 0x03
+	   call     [ctrl.ctrl_write8]
+
+	;outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */
+	  ; mov      edx, esi                  ;; for via686
+	  ; add      edx, VIA_REG_OFFSET_TYPE
+	  ; mov      eax, 0x03
+	  ; call     [ctrl.ctrl_write8]
+
+	;; outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR));
+	   ;mov      edx, esi
+	   ;add      edx, VIA_REG_OFFSET_CURR_PTR
+	   ;xor      eax, eax
+	   ;call     [ctrl.ctrl_write8]
+
+	   ret
+endp
+
+
+align 4
+proc detect_controller
+	   locals
+	     last_bus dd ?
+	     bus      dd ?
+	     devfn    dd ?
+	   endl
+
+	   xor eax, eax
+	   mov [bus], eax
+	   inc eax
+	   call PciApi
+	   cmp eax, -1
+	   je .err
+
+	   mov [last_bus], eax
+
+.next_bus:
+	   and [devfn], 0
+.next_dev:
+	   stdcall PciRead32, [bus], [devfn], dword 0
+	   test eax, eax
+	   jz .next
+	   cmp eax, -1
+	   je .next
+
+	   mov edi, devices
+@@:
+	   mov ebx, [edi]
+	   test ebx, ebx
+	   jz .next
+
+	   cmp eax, ebx
+	   je .found
+	   add edi, 12
+	   jmp @B
+.next:
+	   inc [devfn]
+	   cmp [devfn], 256
+	   jb .next_dev
+	   mov eax, [bus]
+	   inc eax
+	   mov [bus], eax
+	   cmp eax, [last_bus]
+	   jna .next_bus
+	   xor eax, eax
+	   ret
+.found:
+	   mov ebx, [bus]
+	   mov [ctrl.bus], ebx
+
+	   mov ecx, [devfn]
+	   mov [ctrl.devfn], ecx
+
+	   mov edx, eax
+	   and edx, 0xFFFF
+	   mov [ctrl.vendor], edx
+	   shr eax, 16
+	   mov [ctrl.dev_id], eax
+
+	   mov ebx, [edi+4]
+	   mov [ctrl.ctrl_ids], ebx
+	   mov esi, [edi+8]
+	   mov [ctrl.ctrl_setup], esi
+
+	   cmp edx, VID_VIA
+	   jne @F
+	   mov [ctrl.vendor_ids], msg_VIA
+	   ret
+@@:
+
+.err:
+	   xor eax, eax
+	   mov [ctrl.vendor_ids], eax	  ;something  wrong ?
+	   ret
+endp
+
+align 4
+proc init_controller
+
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 4
+	   mov	    ebx, eax
+	   and	    eax, 0xFFFF
+	   mov	    [ctrl.pci_cmd], eax
+	   shr	    ebx, 16
+	   mov	    [ctrl.pci_stat], ebx
+
+	   mov	    esi, msgPciCmd
+	   call     SysMsgBoardStr
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   mov	    esi, msgPciStat
+	   call     SysMsgBoardStr
+	   mov	    eax, [ctrl.pci_stat]
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   mov	    esi, msgCtrlIsaIo
+	   call     SysMsgBoardStr
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   and	    eax, 0xFFC0
+	   mov	    [ctrl.ctrl_io_base], eax
+
+.default:
+	   stdcall  PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C
+	   and	    eax, 0xFF
+@@:
+	   mov	    [ctrl.int_line], eax
+
+	   ;stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE ;0x42
+	   ;mov      byte [old_legacy], al
+
+	   ;stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_PNP_CONTROL ;0x43
+	   ;mov      byte [old_legacy_cfg], al
+
+	   ;mov      al, VIA_FUNC_ENABLE_SB or VIA_FUNC_ENABLE_FM
+	   ;xor      al, 0xFF
+	   ;and      al, byte [old_legacy]
+	   ;and      eax, 0xFF
+	   ;stdcall  PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE, eax ;0x42
+	   ;mov      byte [old_legacy], al
+
+	   call     [ctrl.ctrl_setup]
+	   xor	    eax, eax
+	   inc	    eax
+	   ret
+endp
+
+align 4
+proc set_VIA
+	   mov	    [ctrl.codec_read16],  codec_io_r16	  ;virtual
+	   mov	    [ctrl.codec_write16], codec_io_w16	  ;virtual
+
+	   mov	    [ctrl.ctrl_read8 ],  ctrl_io_r8	  ;virtual
+	   mov	    [ctrl.ctrl_read16],  ctrl_io_r16	  ;virtual
+	   mov	    [ctrl.ctrl_read32],  ctrl_io_r32	  ;virtual
+
+	   mov	    [ctrl.ctrl_write8 ], ctrl_io_w8	  ;virtual
+	   mov	    [ctrl.ctrl_write16], ctrl_io_w16	  ;virtual
+	   mov	    [ctrl.ctrl_write32], ctrl_io_w32	  ;virtual
+	   ret
+endp
+
+
+align 4
+proc init_codec
+	   locals
+	     counter dd ?
+	   endl
+
+	   mov	    esi, msgControl
+	   call     SysMsgBoardStr
+	   stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL
+	   and	    eax, 0xFF
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   mov	    esi, msgStatus
+	   call     SysMsgBoardStr
+	   stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT
+	   and	    eax, 0xFF
+	   push     eax
+	   call     dword2str
+	   call     SysMsgBoardStr
+	   pop	    eax
+
+	   test     eax, VIA_ACLINK_C00_READY
+	   jz	    .ready
+
+	   call     reset_codec
+	   test     eax, eax
+	   jz	    .err
+
+.ready:
+	   xor	    edx, edx	 ; ac_reg_0
+	   call     [ctrl.codec_write16]
+	   jmp	    .done
+
+.err:
+	   xor	    eax, eax	      ; timeout error
+	   ret
+
+.done:
+	   call     detect_codec
+
+	   xor	    eax, eax
+	   inc	    eax
+	   ret
+endp
+
+align 4
+proc reset_codec
+	   stdcall  PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, \
+			       VIA_ACLINK_CTRL_ENABLE or VIA_ACLINK_CTRL_RESET or VIA_ACLINK_CTRL_SYNC
+	   mov	    eax, 100000    ; wait 100 ms
+	   call     StallExec
+.cold:
+	   call     cold_reset
+	   jnc	    .ok
+
+     if DEBUG
+	   mov	 esi, msgCFail
+	   call  SysMsgBoardStr
+     end if
+	   xor	    eax, eax	 ; timeout error
+	   ret
+.ok:
+     if DEBUG
+	   mov	 esi, msgResetOk
+	   call  SysMsgBoardStr
+     end if
+	   xor	    eax, eax
+	   inc	    eax
+	   ret
+endp
+
+
+align 4
+proc cold_reset
+	   locals
+	     counter dd ?
+	   endl
+
+	   stdcall  PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0
+
+     if DEBUG
+	   mov	 esi, msgCold
+	   call  SysMsgBoardStr
+     end if
+
+	   mov	    eax, 100000     ; wait 100 ms ;400000     ; wait 400 ms
+	   call     StallExec
+
+	   ;; ACLink on, deassert ACLink reset, VSR, SGD data out
+	   ;; note - FM data out has trouble with non VRA codecs !!
+	   stdcall  PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT
+
+	   mov	    [counter], 16    ; total 20*100 ms = 2s
+.wait:
+	   stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT
+	   test     eax, VIA_ACLINK_C00_READY
+	   jnz	    .ok
+
+	   mov	    eax, 100000    ; wait 100 ms
+	   call     StallExec
+
+	   dec	    [counter]
+	   jnz	    .wait
+
+     if DEBUG
+	   mov	 esi, msgCRFail
+	   call  SysMsgBoardStr
+     end if
+
+.fail:
+	   stc
+	   ret
+.ok:
+	   mov	    esi, msgControl
+	   call     SysMsgBoardStr
+	   stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL
+	   call     dword2str
+	   call     SysMsgBoardStr
+
+	   mov	    esi, msgStatus
+	   call     SysMsgBoardStr
+	   stdcall  PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT
+	   and	    eax, 0xFF
+	   push     eax
+	   call     dword2str
+	   call     SysMsgBoardStr
+	   pop	    eax
+
+	   test     eax, VIA_ACLINK_C00_READY ;CTRL_ST_CREADY
+	   jz	    .fail
+	   clc
+	   ret
+endp
+
+align 4
+play:
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_STOP_IDX
+	   mov	    eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000
+	   mov	 [ctrl.lvi_reg], 16
+	   call     [ctrl.ctrl_write32]
+
+	   mov	    eax, VIA_REG_CTRL_INT
+	   or	    eax, VIA_REG_CTRL_START
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_CONTROL
+	   call     [ctrl.ctrl_write8]
+
+	   xor	    eax, eax
+	   ret
+
+align 4
+stop:
+	   mov	    eax, VIA_REG_CTRL_INT
+	   or	    eax, VIA_REG_CTRL_TERMINATE
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_CONTROL
+	   call     [ctrl.ctrl_write8]
+
+	   stdcall  channel_reset, VIADEV_PLAYBACK
+	   xor	    eax, eax
+	   ret
+
+align 4
+proc get_dev_info stdcall, p_info:dword
+	   virtual at esi
+	     CTRL_INFO CTRL_INFO
+	   end virtual
+
+	   mov	    esi, [p_info]
+	   mov	    eax, [ctrl.int_line]
+	   mov	    ecx, [ctrl.ctrl_io_base]
+	   mov	    [CTRL_INFO.irq], eax
+	   mov	    [CTRL_INFO.ctrl_io_base], ecx
+
+	   xor	    eax, eax
+	   ;mov      edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_TABLE_PTR
+	   ;call     [ctrl.ctrl_read32]
+	   mov	    [CTRL_INFO.codec_io_base], eax
+	   ;mov      edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_STOP_IDX
+	   ;call     [ctrl.ctrl_read32]
+	   mov	    [CTRL_INFO.codec_mem_base], eax
+	   ;mov      edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_CURR_COUNT
+	   ;call     [ctrl.ctrl_read32]
+	   mov	    [CTRL_INFO.ctrl_mem_base], eax
+
+	   mov	    eax, [codec.chip_id]
+	   mov	    [CTRL_INFO.codec_id], eax
+
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_CONTROL
+	   call     [ctrl.ctrl_read8]
+	   and	    eax, 0xFF
+	   mov	    [CTRL_INFO.glob_cntrl], eax
+
+	   mov	    edx, VIADEV_PLAYBACK   +VIA_REG_OFFSET_STATUS
+	   call     [ctrl.ctrl_read8]
+	   and	    eax, 0xFF
+	   mov	    [CTRL_INFO.glob_sta], eax
+
+	   mov	    ebx, [ctrl.pci_cmd]
+	   mov	    [CTRL_INFO.pci_cmd], ebx
+	   ret
+endp
+
+align 4
+proc set_callback stdcall, handler:dword
+	   mov	    eax, [handler]
+	   mov	    [ctrl.user_callback], eax
+	   ret
+endp
+
+
+align 4
+proc codec_check_ready stdcall
+	   locals
+	     counter dd ?
+	   endl
+
+	   mov	    [counter], 1000	; total 1000*1 ms = 1s
+.wait:
+	   call     [ctrl.codec_read16]
+	   test     eax, VIA_REG_AC97_BUSY
+	   jz	    .ok
+
+	   mov	    eax, 1000	; wait 1 ms
+	   call     StallExec
+
+	   sub	    [counter] , 1
+	   jnz	    .wait
+.err:
+	   mov	    eax, -1
+	   ret
+.ok:
+	   and	    eax, 0xFFFF
+	   ret
+endp
+
+
+align 4
+proc codec_valid stdcall
+	   stdcall  codec_check_ready
+	   ret
+endp
+
+align 4
+proc codec_read stdcall, ac_reg:dword	   ; reg = edx, reval = eax
+	   locals
+	     counter dd ?
+	   endl
+
+	   ;Use only primary codec.
+	   mov	    eax, [ac_reg]
+	   and	    eax, 0x7F
+	   shl	    eax, VIA_REG_AC97_CMD_SHIFT
+	   or	    eax, VIA_REG_AC97_PRIMARY_VALID or VIA_REG_AC97_READ
+
+	   mov	    [counter], 3     ; total 3*20 ms = 60ms
+.wait:
+	   push     eax
+	   call     [ctrl.codec_write16]
+
+	   mov	    eax, 20000	 ; wait 20 ms
+	   call     StallExec
+
+	   stdcall  codec_valid,
+	   cmp	    eax, 0
+	   pop	    eax
+	   jge	    .ok
+
+	   sub	    [counter] , 1
+	   jnz	    .wait
+	   jmp	    .err
+
+.ok:
+	   mov	    eax, 25000	 ; wait 25 ms
+	   call     StallExec
+
+	   call     [ctrl.codec_read16]  ;change edx !!!
+	   and	    eax, 0xFFFF
+	   ret
+.err:
+     if DEBUG
+	   mov	 esi, msgCInvalid
+	   call  SysMsgBoardStr
+     end if
+	   mov	    eax, -1	   ; invalid codec error
+	   ret
+endp
+
+align 4
+proc codec_write stdcall, ac_reg:dword
+	   ;Use only primary codec.
+	   mov	    esi, [ac_reg]
+	   mov	    edx, esi
+	   shl	    edx, VIA_REG_AC97_CMD_SHIFT
+
+	   shl	    eax, VIA_REG_AC97_DATA_SHIFT
+	   or	    edx, eax
+
+	   mov	    eax, VIA_REG_AC97_CODEC_ID_PRIMARY ;not VIA_REG_AC97_CODEC_ID_PRIMARY
+	   shl	    eax, VIA_REG_AC97_CODEC_ID_SHIFT
+	   or	    edx, eax
+
+	   mov	    eax, edx
+	   mov	    edx, esi
+	   call     [ctrl.codec_write16]
+	   mov	    [codec.regs+esi], ax
+
+	   stdcall  codec_check_ready
+	   cmp	    eax, 0
+	   jl	    .err
+.ok:
+	   ret
+.err:
+     if DEBUG
+	   mov	  esi, msgCFail
+	   call   SysMsgBoardStr
+     end if
+	   ;mov      eax, -1        ; codec not ready error
+	   ret
+endp
+
+align 4
+proc StallExec
+	   push     ecx
+	   push     edx
+	   push     ebx
+	   push     eax
+
+	   mov	    ecx, CPU_FREQ
+	   mul	    ecx
+	   mov	    ebx, eax	   ;low
+	   mov	    ecx, edx	   ;high
+	   rdtsc
+	   add	    ebx, eax
+	   adc	    ecx, edx
+@@:
+	   rdtsc
+	   sub	    eax, ebx
+	   sbb	    edx, ecx
+	   js	    @B
+
+	   pop	    eax
+	   pop	    ebx
+	   pop	    edx
+	   pop	    ecx
+	   ret
+endp
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;          CONTROLLER IO functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+align 4
+proc codec_io_r16 ;r32
+	   mov	    edx, [ctrl.ctrl_io_base]
+	   add	    edx, VIA_REG_AC97
+	   in	    eax, dx
+	   ret
+endp
+
+align 4
+proc codec_io_w16 ;w32
+	   mov	    edx, [ctrl.ctrl_io_base]
+	   add	    edx, VIA_REG_AC97
+	   out	    dx,  eax
+	   ret
+endp
+
+align 4
+proc ctrl_io_r8
+	   add	    edx, [ctrl.ctrl_io_base]
+	   in	    al, dx
+	   ret
+endp
+
+align 4
+proc ctrl_io_r16
+	   add	    edx, [ctrl.ctrl_io_base]
+	   in	    ax, dx
+	   ret
+endp
+
+align 4
+proc ctrl_io_r32
+	   add	    edx, [ctrl.ctrl_io_base]
+	   in	    eax, dx
+	   ret
+endp
+
+align 4
+proc ctrl_io_w8
+	   add	    edx, [ctrl.ctrl_io_base]
+	   out	    dx, al
+	   ret
+endp
+
+align 4
+proc ctrl_io_w16
+	   add	    edx, [ctrl.ctrl_io_base]
+	   out	    dx, ax
+	   ret
+endp
+
+align 4
+proc ctrl_io_w32
+	   add	    edx, [ctrl.ctrl_io_base]
+	   out	    dx, eax
+	   ret
+endp
+
+
+align 4
+dword2str:
+	   push     eax ebx ecx
+	   mov	    esi, hex_buff
+	   mov	    ecx, -8
+   @@:
+	   rol	    eax, 4
+	   mov	    ebx, eax
+	   and	    ebx, 0x0F
+	   mov	    bl, [ebx+hexletters]
+	   mov	    [8+esi+ecx], bl
+	   inc	    ecx
+	   jnz	    @B
+	   pop	    ecx ebx eax
+	   ret
+
+hexletters   db '0123456789ABCDEF'
+hex_buff     db 8 dup(0),13,10,0
+
+
+include "codec.inc"
+
+align 4
+devices dd (CTRL_VT82C686  shl 16)+VID_VIA,msg_VT82C686,set_VIA
+	dd (CTRL_VT8233_5  shl 16)+VID_VIA,msg_VT8233,set_VIA
+	dd 0	;terminator
+
+
+version      dd (5 shl 16) or (API_VERSION and 0xFFFF)
+
+msg_VT82C686 db 'VT82C686', 13,10, 0
+msg_VT8233   db 'VT8233',   13,10, 0
+msg_VIA      db 'VIA'	,   13,10, 0
+
+szKernel	    db 'KERNEL', 0
+sz_sound_srv	    db 'SOUND',0
+
+msgInit      db 'detect hardware...',13,10,0
+msgFail      db 'device not found',13,10,0
+msgAttchIRQ  db 'IRQ line not supported', 13,10, 0
+msgInvIRQ    db 'IRQ line not assigned or invalid', 13,10, 0
+msgPlay      db 'start play', 13,10,0
+msgStop      db 'stop play',  13,10,0
+;msgIRQ       db 'AC97 IRQ', 13,10,0
+;msgInitCtrl  db 'init controller',13,10,0
+;msgInitCodec db 'init codec',13,10,0
+msgPrimBuff  db 'create primary buffer ...',0
+msgDone      db 'done',13,10,0
+msgRemap     db 'Remap IRQ',13,10,0
+;msgReg       db 'set service handler',13,10,0
+;msgOk        db 'service installed',13,10,0
+msgCold      db 'cold reset',13,10,0
+;msgWarm      db 'warm reset',13,10,0
+;msgWRFail    db 'warm reset failed',13,10,0
+msgCRFail    db 'cold reset failed',13,10,0
+msgCFail     db 'codec not ready',13,10,0
+msgCInvalid  db 'codec is not valid',13,10,0 ;Asper
+msgResetOk   db 'reset complete',13,10,0
+msgStatus    db 'global status   ',0
+msgControl   db 'global control  ',0
+msgPciCmd    db 'PCI command     ',0
+msgPciStat   db 'PCI status      ',0
+msgCtrlIsaIo db 'controller io base   ',0
+;msgMixIsaIo  db 'codec io base        ',0
+;msgCtrlMMIo  db 'controller mmio base ',0
+;msgMixMMIo   db 'codec mmio base      ',0
+;msgIrqMap    db 'AC97 irq map as      ',0
+
+
+section '.data' data readable writable align 16
+
+pcmout_bdl	 rq 32
+buff_list	 rd 32
+
+codec CODEC
+ctrl AC_CNTRL
+
+chip_type	 rb 1
\ No newline at end of file
diff --git a/kernel/branches/Kolibri-A/trunk/fs/fs_lfn.inc b/kernel/branches/Kolibri-A/trunk/fs/fs_lfn.inc
index 1391030f8a..2149bb9a34 100644
--- a/kernel/branches/Kolibri-A/trunk/fs/fs_lfn.inc
+++ b/kernel/branches/Kolibri-A/trunk/fs/fs_lfn.inc
@@ -795,7 +795,7 @@ biosdisk_enum_root:
         xor     eax, eax
         ret
 .big:
-        push    ecx
+        push    ecx edx
         push    -'0'
         mov     ecx, 10
 @@:
@@ -810,7 +810,7 @@ biosdisk_enum_root:
         add     al, '0'
         stosb
         jnz     @b
-        pop     ecx
+        pop     edx ecx
         pop     eax
         inc     eax
         ret
diff --git a/kernel/branches/Kolibri-A/trunk/gui/event.inc b/kernel/branches/Kolibri-A/trunk/gui/event.inc
index 0610cd5220..a7a0e0dd85 100644
--- a/kernel/branches/Kolibri-A/trunk/gui/event.inc
+++ b/kernel/branches/Kolibri-A/trunk/gui/event.inc
@@ -7,6 +7,13 @@
 
 $Revision$
 
+WINDOW_MOVE_AND_RESIZE_FLAGS = \
+  mouse.WINDOW_RESIZE_N_FLAG + \
+  mouse.WINDOW_RESIZE_W_FLAG + \
+  mouse.WINDOW_RESIZE_S_FLAG + \
+  mouse.WINDOW_RESIZE_E_FLAG + \
+  mouse.WINDOW_MOVE_FLAG
+
 uglobal
 align 4
   event_start   dd ?
@@ -445,7 +452,7 @@ get_event_for_app:                                 ;; used from f10,f11,f23
         xor     eax,eax
         ret
 .IRQ:
-;TODO: ������� ��� ��, ��� � ��� FlagAutoReset (BgrRedraw,Mouse,IPC,Stack,Debug)
+;TODO: same thing as done for FlagAutoReset (BgrRedraw,Mouse,IPC,Stack,Debug)
         mov     edx,[irq_owner+eax*4-64] ; eax==16+irq
         cmp     edx,[edi+TASKDATA.pid]
         jne     .loop
@@ -460,8 +467,9 @@ get_event_for_app:                                 ;; used from f10,f11,f23
         push    eax
 ; If the window is captured and moved by the user, then no mouse events!!!
         mov     al, [mouse.active_sys_window.action]
-        test    al, mouse.WINDOW_MOVE_FLAG
-        pop     eax
+        and     al, WINDOW_MOVE_AND_RESIZE_FLAGS
+        test    al, al
+	pop     eax
         jnz     .loop
 @@:
         btr     [ebx+APPDATA.event_mask],eax
diff --git a/kernel/branches/Kolibri-A/trunk/gui/mouse.inc b/kernel/branches/Kolibri-A/trunk/gui/mouse.inc
index deb3714977..32055cf99d 100644
--- a/kernel/branches/Kolibri-A/trunk/gui/mouse.inc
+++ b/kernel/branches/Kolibri-A/trunk/gui/mouse.inc
@@ -1,701 +1,701 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;                                                              ;;
-;; Copyright (C) KolibriOS team 2010. All rights reserved.      ;;
-;; Distributed under terms of the GNU General Public License    ;;
-;;                                                              ;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-$Revision: -1 $
-
-include 'mousepointer.inc'
-
-;==============================================================================
-;///// public functions ///////////////////////////////////////////////////////
-;==============================================================================
-
-mouse.LEFT_BUTTON_FLAG   = 0001b
-mouse.RIGHT_BUTTON_FLAG  = 0010b
-mouse.MIDDLE_BUTTON_FLAG = 0100b
-
-mouse.BUTTONS_MASK = \
-  mouse.LEFT_BUTTON_FLAG or \
-  mouse.RIGHT_BUTTON_FLAG or \
-  mouse.MIDDLE_BUTTON_FLAG
-
-mouse.WINDOW_RESIZE_N_FLAG = 000001b
-mouse.WINDOW_RESIZE_W_FLAG = 000010b
-mouse.WINDOW_RESIZE_S_FLAG = 000100b
-mouse.WINDOW_RESIZE_E_FLAG = 001000b
-mouse.WINDOW_MOVE_FLAG     = 010000b
-
-mouse.WINDOW_RESIZE_SW_FLAG = \
-  mouse.WINDOW_RESIZE_S_FLAG or \
-  mouse.WINDOW_RESIZE_W_FLAG
-mouse.WINDOW_RESIZE_SE_FLAG = \
-  mouse.WINDOW_RESIZE_S_FLAG or \
-  mouse.WINDOW_RESIZE_E_FLAG
-
-align 4
-;------------------------------------------------------------------------------
-mouse_check_events: ;//////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Check if mouse buttons state or cursor position has changed and call
-;? appropriate handlers
-;------------------------------------------------------------------------------
-        push    eax ebx
-
-        mov     al, [BTN_DOWN]
-        mov     bl, [mouse.state.buttons]
-        and     al, mouse.BUTTONS_MASK
-        mov     cl, al
-        xchg    cl, [mouse.state.buttons]
-        xor     bl, al
-        push    eax ebx
-
-        ; did any mouse button changed its state?
-        or      bl, bl
-        jz      .check_position
-
-        ; yes it did, is that the first button of all pressed down?
-        or      cl, cl
-        jnz     .check_buttons_released
-
-        ; yes it is, activate window user is pointing at, if needed
-        call    mouse._.activate_sys_window_under_cursor
-
-        ; NOTE: this code wouldn't be necessary if we knew window did
-        ;       already redraw itself after call above
-        or      eax, eax
-        jz      @f
-
-        and     [mouse.state.buttons], 0
-        jmp     .exit
-
-        ; is there any system button under cursor?
-    @@: call    mouse._.find_sys_button_under_cursor
-        or      eax, eax
-        jz      .check_buttons_released
-
-        ; yes there is, activate it and exit
-        mov     [mouse.active_sys_button.pbid], eax
-        mov     [mouse.active_sys_button.coord], ebx
-        mov     cl, [mouse.state.buttons]
-        mov     [mouse.active_sys_button.buttons], cl
-        call    sys_button_activate_handler
-        jmp     .exit
-
-  .check_buttons_released:
-        cmp     [mouse.state.buttons], 0
-        jnz     .buttons_changed
-
-        ; did we press some button earlier?
-        cmp     [mouse.active_sys_button.pbid], 0
-        je      .buttons_changed
-
-        ; yes we did, deactivate it
-        xor     eax, eax
-        xchg    eax, [mouse.active_sys_button.pbid]
-        mov     ebx, [mouse.active_sys_button.coord]
-        mov     cl, [mouse.active_sys_button.buttons]
-        push    eax ebx
-        call    sys_button_deactivate_handler
-        pop     edx ecx
-
-        ; is the button under cursor the one we deactivated?
-        call    mouse._.find_sys_button_under_cursor
-        cmp     eax, ecx
-        jne     .exit
-        cmp     ebx, edx
-        jne     .exit
-
-        ; yes it is, perform associated action
-        mov     cl, [mouse.active_sys_button.buttons]
-        call    sys_button_perform_handler
-        jmp     .exit
-
-  .buttons_changed:
-        test    byte[esp], mouse.LEFT_BUTTON_FLAG
-        jz      @f
-        mov     eax, [esp + 4]
-        call    .call_left_button_handler
-
-    @@: test    byte[esp], mouse.RIGHT_BUTTON_FLAG
-        jz      @f
-        mov     eax, [esp + 4]
-        call    .call_right_button_handler
-
-    @@: test    byte[esp], mouse.MIDDLE_BUTTON_FLAG
-        jz      .check_position
-        mov     eax, [esp + 4]
-        call    .call_middle_button_handler
-
-  .check_position:
-        movzx   eax, word[MOUSE_X]
-        movzx   ebx, word[MOUSE_Y]
-        cmp     eax, [mouse.state.pos.x]
-        jne     .position_changed
-        cmp     ebx, [mouse.state.pos.y]
-        je      .exit
-
-  .position_changed:
-        xchg    eax, [mouse.state.pos.x]
-        xchg    ebx, [mouse.state.pos.y]
-
-        call    mouse._.move_handler
-
-  .exit:
-        add     esp, 8
-        pop     ebx eax
-        ret
-
-  .call_left_button_handler:
-        test    eax, mouse.LEFT_BUTTON_FLAG
-        jnz     mouse._.left_button_press_handler
-        jmp     mouse._.left_button_release_handler
-
-  .call_right_button_handler:
-        test    eax, mouse.RIGHT_BUTTON_FLAG
-        jnz     mouse._.right_button_press_handler
-        jmp     mouse._.right_button_release_handler
-
-  .call_middle_button_handler:
-        test    eax, mouse.MIDDLE_BUTTON_FLAG
-        jnz     mouse._.middle_button_press_handler
-        jmp     mouse._.middle_button_release_handler
-
-;==============================================================================
-;///// private functions //////////////////////////////////////////////////////
-;==============================================================================
-
-uglobal
-  mouse.state:
-    .pos     POINT
-    .buttons db ?
-
-  ; NOTE: since there's no unique and lifetime-constant button identifiers,
-  ;       we're using two dwords to identify each of them:
-  ;       * pbid - process slot (high 8 bits) and button id (low 24 bits) pack
-  ;       * coord - left (high 16 bits) and top (low 16 bits) coordinates pack
-  align 4
-  mouse.active_sys_button:
-    .pbid    dd ?
-    .coord   dd ?
-    .buttons db ?
-
-  align 4
-  mouse.active_sys_window:
-    .pslot      dd ?
-    .old_box    BOX
-    .new_box    BOX
-    .delta      POINT
-    .last_ticks dd ?
-    .action     db ?
-endg
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.left_button_press_handler: ;///////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when left mouse button has been pressed down
-;------------------------------------------------------------------------------
-        test    [mouse.state.buttons], not mouse.LEFT_BUTTON_FLAG
-        jnz     .exit
-
-        call    mouse._.find_sys_window_under_cursor
-        call    mouse._.check_sys_window_actions
-        mov     [mouse.active_sys_window.action], al
-        or      eax, eax
-        jz      .exit
-
-        xchg    eax, edx
-        test    dl, mouse.WINDOW_MOVE_FLAG
-        jz      @f
-
-        mov     eax, [timer_ticks]
-        mov     ebx, eax
-        xchg    ebx, [mouse.active_sys_window.last_ticks]
-        sub     eax, ebx
-        cmp     eax, 50
-        jg      @f
-
-        mov     [mouse.active_sys_window.last_ticks], 0
-        call    sys_window_maximize_handler
-        jmp     .exit
-
-    @@: test    [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
-        jnz     .exit
-        mov     [mouse.active_sys_window.pslot], esi
-        lea     eax, [edi + WDATA.box]
-        mov     ebx, mouse.active_sys_window.old_box
-        mov     ecx, BOX.sizeof
-        call    memmove
-        mov     ebx, mouse.active_sys_window.new_box
-        call    memmove
-        test    edx, mouse.WINDOW_MOVE_FLAG
-        jz      @f
-
-        call    .calculate_n_delta
-        call    .calculate_w_delta
-        jmp     .call_window_handler
-
-    @@: test    dl, mouse.WINDOW_RESIZE_W_FLAG
-        jz      @f
-        call    .calculate_w_delta
-
-    @@: test    dl, mouse.WINDOW_RESIZE_S_FLAG
-        jz      @f
-        call    .calculate_s_delta
-
-    @@: test    dl, mouse.WINDOW_RESIZE_E_FLAG
-        jz      .call_window_handler
-        call    .calculate_e_delta
-
-  .call_window_handler:
-        mov     eax, mouse.active_sys_window.old_box
-        call    sys_window_start_moving_handler
-
-  .exit:
-        ret
-
-  .calculate_n_delta:
-        mov     eax, [mouse.state.pos.y]
-        sub     eax, [mouse.active_sys_window.old_box.top]
-        mov     [mouse.active_sys_window.delta.y], eax
-        ret
-
-  .calculate_w_delta:
-        mov     eax, [mouse.state.pos.x]
-        sub     eax, [mouse.active_sys_window.old_box.left]
-        mov     [mouse.active_sys_window.delta.x], eax
-        ret
-
-  .calculate_s_delta:
-        mov     eax, [mouse.active_sys_window.old_box.top]
-        add     eax, [mouse.active_sys_window.old_box.height]
-        sub     eax, [mouse.state.pos.y]
-        mov     [mouse.active_sys_window.delta.y], eax
-        ret
-
-  .calculate_e_delta:
-        mov     eax, [mouse.active_sys_window.old_box.left]
-        add     eax, [mouse.active_sys_window.old_box.width]
-        sub     eax, [mouse.state.pos.x]
-        mov     [mouse.active_sys_window.delta.x], eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.left_button_release_handler: ;/////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when left mouse button has been released
-;------------------------------------------------------------------------------
-        xor     esi, esi
-        xchg    esi, [mouse.active_sys_window.pslot]
-        or      esi, esi
-        jz      .exit
-
-        mov     eax, esi
-        shl     eax, 5
-        add     eax, window_data + WDATA.box
-        mov     ebx, mouse.active_sys_window.old_box
-        mov     ecx, BOX.sizeof
-        call    memmove
-
-        mov     eax, mouse.active_sys_window.old_box
-        mov     ebx, mouse.active_sys_window.new_box
-        call    sys_window_end_moving_handler
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.right_button_press_handler: ;//////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when right mouse button has been pressed down
-;------------------------------------------------------------------------------
-        test    [mouse.state.buttons], not mouse.RIGHT_BUTTON_FLAG
-        jnz     .exit
-
-        call    mouse._.find_sys_window_under_cursor
-        call    mouse._.check_sys_window_actions
-        test    al, mouse.WINDOW_MOVE_FLAG
-        jz      .exit
-
-        call    sys_window_rollup_handler
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.right_button_release_handler: ;////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when right mouse button has been released
-;------------------------------------------------------------------------------
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.middle_button_press_handler: ;/////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when middle mouse button has been pressed down
-;------------------------------------------------------------------------------
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.middle_button_release_handler: ;///////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when middle mouse button has been released
-;------------------------------------------------------------------------------
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.move_handler: ;////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Called when cursor has been moved
-;------------------------------------------------------------------------------
-;> eax = old x coord
-;> ebx = old y coord
-;------------------------------------------------------------------------------
-        cmp     [mouse.active_sys_button.pbid], 0
-        jnz     .exit
-
-        mov     esi, [mouse.active_sys_window.pslot]
-        or      esi, esi
-        jz      .exit
-
-        mov     eax, mouse.active_sys_window.new_box
-        mov     ebx, mouse.active_sys_window.old_box
-        mov     ecx, BOX.sizeof
-        call    memmove
-
-        mov     dl, [mouse.active_sys_window.action]
-        test    dl, mouse.WINDOW_MOVE_FLAG
-        jz      .check_resize_w
-
-        mov     eax, [mouse.state.pos.x]
-        sub     eax, [mouse.active_sys_window.delta.x]
-        mov     [mouse.active_sys_window.new_box.left], eax
-        mov     eax, [mouse.state.pos.y]
-        sub     eax, [mouse.active_sys_window.delta.y]
-        mov     [mouse.active_sys_window.new_box.top], eax
-
-        mov     eax, [mouse.active_sys_window.new_box.left]
-        or      eax, eax
-        jge     @f
-        xor     eax, eax
-        mov     [mouse.active_sys_window.new_box.left], eax
-    @@: add     eax, [mouse.active_sys_window.new_box.width]
-        cmp     eax, [Screen_Max_X]
-        jl      @f
-        sub     eax, [Screen_Max_X]
-        sub     [mouse.active_sys_window.new_box.left], eax
-    @@: mov     eax, [mouse.active_sys_window.new_box.top]
-        or      eax, eax
-        jge     @f
-        xor     eax, eax
-        mov     [mouse.active_sys_window.new_box.top], eax
-    @@: add     eax, [mouse.active_sys_window.new_box.height]
-        cmp     eax, [Screen_Max_Y]
-        jle     .call_window_handler
-        sub     eax, [Screen_Max_Y]
-        sub     [mouse.active_sys_window.new_box.top], eax
-        jmp     .call_window_handler
-
-  .check_resize_w:
-        test    dl, mouse.WINDOW_RESIZE_W_FLAG
-        jz      .check_resize_s
-
-        mov     eax, [mouse.state.pos.x]
-        sub     eax, [mouse.active_sys_window.delta.x]
-        mov     [mouse.active_sys_window.new_box.left], eax
-        sub     eax, [mouse.active_sys_window.old_box.left]
-        sub     [mouse.active_sys_window.new_box.width], eax
-
-        mov     eax, [mouse.active_sys_window.new_box.width]
-        sub     eax, 127
-        jge     @f
-        add     [mouse.active_sys_window.new_box.left], eax
-        mov     [mouse.active_sys_window.new_box.width], 127
-    @@: mov     eax, [mouse.active_sys_window.new_box.left]
-        or      eax, eax
-        jge     .check_resize_s
-        add     [mouse.active_sys_window.new_box.width], eax
-        xor     eax, eax
-        mov     [mouse.active_sys_window.new_box.left], eax
-
-  .check_resize_s:
-        test    dl, mouse.WINDOW_RESIZE_S_FLAG
-        jz      .check_resize_e
-
-        mov     eax, [mouse.state.pos.y]
-        add     eax, [mouse.active_sys_window.delta.y]
-        sub     eax, [mouse.active_sys_window.old_box.top]
-        mov     [mouse.active_sys_window.new_box.height], eax
-
-        push    eax
-        mov     edi, esi
-        shl     edi, 5
-        add     edi, window_data
-        call    window._.get_rolledup_height
-        mov     ecx, eax
-        pop     eax
-        mov     eax, [mouse.active_sys_window.new_box.height]
-        cmp     eax, ecx
-        jge     @f
-        mov     eax, ecx
-        mov     [mouse.active_sys_window.new_box.height], eax
-    @@: add     eax, [mouse.active_sys_window.new_box.top]
-        cmp     eax, [Screen_Max_Y]
-        jle     .check_resize_e
-        sub     eax, [Screen_Max_Y]
-        neg     eax
-        add     [mouse.active_sys_window.new_box.height], eax
-        mov     ecx, [Screen_Max_Y]
-        cmp     ecx, eax
-        jge     .check_resize_e
-        mov     [mouse.active_sys_window.new_box.height], ecx
-
-  .check_resize_e:
-        test    dl, mouse.WINDOW_RESIZE_E_FLAG
-        jz      .call_window_handler
-
-        mov     eax, [mouse.state.pos.x]
-        add     eax, [mouse.active_sys_window.delta.x]
-        sub     eax, [mouse.active_sys_window.old_box.left]
-        mov     [mouse.active_sys_window.new_box.width], eax
-
-        mov     eax, [mouse.active_sys_window.new_box.width]
-        cmp     eax, 127
-        jge     @f
-        mov     eax, 127
-        mov     [mouse.active_sys_window.new_box.width], eax
-    @@: add     eax, [mouse.active_sys_window.new_box.left]
-        cmp     eax, [Screen_Max_X]
-        jle     .call_window_handler
-        sub     eax, [Screen_Max_X]
-        neg     eax
-        add     [mouse.active_sys_window.new_box.width], eax
-        mov     ecx, [Screen_Max_X]
-        cmp     ecx, eax
-        jge     .call_window_handler
-        mov     [mouse.active_sys_window.new_box.width], ecx
-
-  .call_window_handler:
-        mov     eax, mouse.active_sys_window.old_box
-        mov     ebx, mouse.active_sys_window.new_box
-
-        push    esi
-        mov     esi, mouse.active_sys_window.old_box
-        mov     edi, mouse.active_sys_window.new_box
-        mov     ecx, BOX.sizeof / 4
-        repe
-        cmpsd
-        pop     esi
-        je      .exit
-
-        mov     [mouse.active_sys_window.last_ticks], 0
-        call    sys_window_moving_handler
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.find_sys_window_under_cursor: ;////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Find system window object which is currently visible on screen and has
-;? mouse cursor within its bounds
-;------------------------------------------------------------------------------
-;< esi = process slot
-;< edi = pointer to WDATA struct
-;------------------------------------------------------------------------------
-        mov     esi, [Screen_Max_X]
-        inc     esi
-        imul    esi, [mouse.state.pos.y]
-        add     esi, [_WinMapAddress]
-        add     esi, [mouse.state.pos.x]
-        movzx   esi, byte[esi]
-        mov     edi, esi
-        shl     edi, 5
-        add     edi, window_data
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.activate_sys_window_under_cursor: ;////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        ; activate and redraw window under cursor (if necessary)
-        call    mouse._.find_sys_window_under_cursor
-        movzx   esi, word[WIN_STACK + esi * 2]
-        lea     esi, [WIN_POS + esi * 2]
-        jmp     waredraw
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.find_sys_button_under_cursor: ;////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Find system button object which is currently visible on screen and has
-;? mouse cursor within its bounds
-;------------------------------------------------------------------------------
-;< eax = pack[8(process slot), 24(button id)] or 0
-;< ebx = pack[16(button x coord), 16(button y coord)]
-;------------------------------------------------------------------------------
-        push    ecx edx esi edi
-
-        call    mouse._.find_sys_window_under_cursor
-        mov     edx, esi
-
-        ; check if any process button contains cursor
-        mov     eax, [BTN_ADDR]
-        mov     ecx, [eax]
-        imul    esi, ecx, SYS_BUTTON.sizeof
-        add     esi, eax
-        inc     ecx
-        add     esi, SYS_BUTTON.sizeof
-
-  .next_button:
-        dec     ecx
-        jz      .not_found
-
-        add     esi, -SYS_BUTTON.sizeof
-
-        ; does it belong to our process?
-        cmp     dx, [esi + SYS_BUTTON.pslot]
-        jne     .next_button
-
-        ; does it contain cursor coordinates?
-        mov     eax, [mouse.state.pos.x]
-        sub     eax, [edi + WDATA.box.left]
-        sub     ax, [esi + SYS_BUTTON.left]
-        jl      .next_button
-        sub     ax, [esi + SYS_BUTTON.width]
-        jge     .next_button
-        mov     eax, [mouse.state.pos.y]
-        sub     eax, [edi + WDATA.box.top]
-        sub     ax, [esi + SYS_BUTTON.top]
-        jl      .next_button
-        sub     ax, [esi + SYS_BUTTON.height]
-        jge     .next_button
-
-        ; okay, return it
-        shl     edx, 24
-        mov     eax, dword[esi + SYS_BUTTON.id_hi - 2]
-        mov     ax, [esi + SYS_BUTTON.id_lo]
-        and     eax, 0x0ffffff
-        or      eax, edx
-        mov     ebx, dword[esi + SYS_BUTTON.left - 2]
-        mov     bx, [esi + SYS_BUTTON.top]
-        jmp     .exit
-
-  .not_found:
-        xor     eax, eax
-        xor     ebx, ebx
-
-  .exit:
-        pop     edi esi edx ecx
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-mouse._.check_sys_window_actions: ;////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;< eax = action flags or 0
-;------------------------------------------------------------------------------
-        ; is window movable?
-        test    byte[edi + WDATA.cl_titlebar + 3], 0x01
-        jnz     .no_action
-
-        mov     eax, [mouse.state.pos.x]
-        mov     ebx, [mouse.state.pos.y]
-        sub     eax, [edi + WDATA.box.left]
-        sub     ebx, [edi + WDATA.box.top]
-
-        ; is there a window titlebar under cursor?
-        push    eax
-        call    window._.get_titlebar_height
-        cmp     ebx, eax
-        pop     eax
-        jl      .move_action
-
-        ; no there isn't, can it be resized then?
-        mov     dl, [edi + WDATA.fl_wstyle]
-        and     dl, 0x0f
-        ; NOTE: dangerous optimization, revise if window types changed;
-        ;       this currently implies only types 2 and 3 could be resized
-        test    dl, 2
-        jz      .no_action
-
-        mov     ecx, [edi + WDATA.box.width]
-        add     ecx, -window.BORDER_SIZE
-        mov     edx, [edi + WDATA.box.height]
-        add     edx, -window.BORDER_SIZE
-
-        ; is it rolled up?
-        test    [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
-        jnz     .resize_w_or_e_action
-
-        cmp     eax, window.BORDER_SIZE
-        jl      .resize_w_action
-        cmp     eax, ecx
-        jg      .resize_e_action
-        cmp     ebx, edx
-        jle     .no_action
-
-  .resize_s_action:
-        cmp     eax, window.BORDER_SIZE + 10
-        jl      .resize_sw_action
-        add     ecx, -10
-        cmp     eax, ecx
-        jge     .resize_se_action
-        mov     eax, mouse.WINDOW_RESIZE_S_FLAG
-        jmp     .exit
-
-  .resize_w_or_e_action:
-        cmp     eax, window.BORDER_SIZE + 10
-        jl      .resize_w_action.direct
-        add     ecx, -10
-        cmp     eax, ecx
-        jg      .resize_e_action.direct
-        jmp     .no_action
-
-  .resize_w_action:
-        add     edx, -10
-        cmp     ebx, edx
-        jge     .resize_sw_action
-  .resize_w_action.direct:
-        mov     eax, mouse.WINDOW_RESIZE_W_FLAG
-        jmp     .exit
-
-  .resize_e_action:
-        add     edx, -10
-        cmp     ebx, edx
-        jge     .resize_se_action
-  .resize_e_action.direct:
-        mov     eax, mouse.WINDOW_RESIZE_E_FLAG
-        jmp     .exit
-
-  .resize_sw_action:
-        mov     eax, mouse.WINDOW_RESIZE_SW_FLAG
-        jmp     .exit
-
-  .resize_se_action:
-        mov     eax, mouse.WINDOW_RESIZE_SE_FLAG
-        jmp     .exit
-
-  .move_action:
-        mov     eax, mouse.WINDOW_MOVE_FLAG
-        jmp     .exit
-
-  .no_action:
-        xor     eax, eax
-
-  .exit:
-        ret
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                              ;;
+;; Copyright (C) KolibriOS team 2010. All rights reserved.      ;;
+;; Distributed under terms of the GNU General Public License    ;;
+;;                                                              ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+$Revision: 1532$
+
+include 'mousepointer.inc'
+
+;==============================================================================
+;///// public functions ///////////////////////////////////////////////////////
+;==============================================================================
+
+mouse.LEFT_BUTTON_FLAG   = 0001b
+mouse.RIGHT_BUTTON_FLAG  = 0010b
+mouse.MIDDLE_BUTTON_FLAG = 0100b
+
+mouse.BUTTONS_MASK = \
+  mouse.LEFT_BUTTON_FLAG or \
+  mouse.RIGHT_BUTTON_FLAG or \
+  mouse.MIDDLE_BUTTON_FLAG
+
+mouse.WINDOW_RESIZE_N_FLAG = 000001b
+mouse.WINDOW_RESIZE_W_FLAG = 000010b
+mouse.WINDOW_RESIZE_S_FLAG = 000100b
+mouse.WINDOW_RESIZE_E_FLAG = 001000b
+mouse.WINDOW_MOVE_FLAG     = 010000b
+
+mouse.WINDOW_RESIZE_SW_FLAG = \
+  mouse.WINDOW_RESIZE_S_FLAG or \
+  mouse.WINDOW_RESIZE_W_FLAG
+mouse.WINDOW_RESIZE_SE_FLAG = \
+  mouse.WINDOW_RESIZE_S_FLAG or \
+  mouse.WINDOW_RESIZE_E_FLAG
+
+align 4
+;------------------------------------------------------------------------------
+mouse_check_events: ;//////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Check if mouse buttons state or cursor position has changed and call
+;? appropriate handlers
+;------------------------------------------------------------------------------
+        push    eax ebx
+
+        mov     al, [BTN_DOWN]
+        mov     bl, [mouse.state.buttons]
+        and     al, mouse.BUTTONS_MASK
+        mov     cl, al
+        xchg    cl, [mouse.state.buttons]
+        xor     bl, al
+        push    eax ebx
+
+        ; did any mouse button changed its state?
+        or      bl, bl
+        jz      .check_position
+
+        ; yes it did, is that the first button of all pressed down?
+        or      cl, cl
+        jnz     .check_buttons_released
+
+        ; yes it is, activate window user is pointing at, if needed
+        call    mouse._.activate_sys_window_under_cursor
+
+        ; NOTE: this code wouldn't be necessary if we knew window did
+        ;       already redraw itself after call above
+        or      eax, eax
+        jz      @f
+
+        and     [mouse.state.buttons], 0
+        jmp     .exit
+
+        ; is there any system button under cursor?
+    @@: call    mouse._.find_sys_button_under_cursor
+        or      eax, eax
+        jz      .check_buttons_released
+
+        ; yes there is, activate it and exit
+        mov     [mouse.active_sys_button.pbid], eax
+        mov     [mouse.active_sys_button.coord], ebx
+        mov     cl, [mouse.state.buttons]
+        mov     [mouse.active_sys_button.buttons], cl
+        call    sys_button_activate_handler
+        jmp     .exit
+
+  .check_buttons_released:
+        cmp     [mouse.state.buttons], 0
+        jnz     .buttons_changed
+
+        ; did we press some button earlier?
+        cmp     [mouse.active_sys_button.pbid], 0
+        je      .buttons_changed
+
+        ; yes we did, deactivate it
+        xor     eax, eax
+        xchg    eax, [mouse.active_sys_button.pbid]
+        mov     ebx, [mouse.active_sys_button.coord]
+        mov     cl, [mouse.active_sys_button.buttons]
+        push    eax ebx
+        call    sys_button_deactivate_handler
+        pop     edx ecx
+
+        ; is the button under cursor the one we deactivated?
+        call    mouse._.find_sys_button_under_cursor
+        cmp     eax, ecx
+        jne     .exit
+        cmp     ebx, edx
+        jne     .exit
+
+        ; yes it is, perform associated action
+        mov     cl, [mouse.active_sys_button.buttons]
+        call    sys_button_perform_handler
+        jmp     .exit
+
+  .buttons_changed:
+        test    byte[esp], mouse.LEFT_BUTTON_FLAG
+        jz      @f
+        mov     eax, [esp + 4]
+        call    .call_left_button_handler
+
+    @@: test    byte[esp], mouse.RIGHT_BUTTON_FLAG
+        jz      @f
+        mov     eax, [esp + 4]
+        call    .call_right_button_handler
+
+    @@: test    byte[esp], mouse.MIDDLE_BUTTON_FLAG
+        jz      .check_position
+        mov     eax, [esp + 4]
+        call    .call_middle_button_handler
+
+  .check_position:
+        movzx   eax, word[MOUSE_X]
+        movzx   ebx, word[MOUSE_Y]
+        cmp     eax, [mouse.state.pos.x]
+        jne     .position_changed
+        cmp     ebx, [mouse.state.pos.y]
+        je      .exit
+
+  .position_changed:
+        xchg    eax, [mouse.state.pos.x]
+        xchg    ebx, [mouse.state.pos.y]
+
+        call    mouse._.move_handler
+
+  .exit:
+        add     esp, 8
+        pop     ebx eax
+        ret
+
+  .call_left_button_handler:
+        test    eax, mouse.LEFT_BUTTON_FLAG
+        jnz     mouse._.left_button_press_handler
+        jmp     mouse._.left_button_release_handler
+
+  .call_right_button_handler:
+        test    eax, mouse.RIGHT_BUTTON_FLAG
+        jnz     mouse._.right_button_press_handler
+        jmp     mouse._.right_button_release_handler
+
+  .call_middle_button_handler:
+        test    eax, mouse.MIDDLE_BUTTON_FLAG
+        jnz     mouse._.middle_button_press_handler
+        jmp     mouse._.middle_button_release_handler
+
+;==============================================================================
+;///// private functions //////////////////////////////////////////////////////
+;==============================================================================
+
+uglobal
+  mouse.state:
+    .pos     POINT
+    .buttons db ?
+
+  ; NOTE: since there's no unique and lifetime-constant button identifiers,
+  ;       we're using two dwords to identify each of them:
+  ;       * pbid - process slot (high 8 bits) and button id (low 24 bits) pack
+  ;       * coord - left (high 16 bits) and top (low 16 bits) coordinates pack
+  align 4
+  mouse.active_sys_button:
+    .pbid    dd ?
+    .coord   dd ?
+    .buttons db ?
+
+  align 4
+  mouse.active_sys_window:
+    .pslot      dd ?
+    .old_box    BOX
+    .new_box    BOX
+    .delta      POINT
+    .last_ticks dd ?
+    .action     db ?
+endg
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.left_button_press_handler: ;///////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when left mouse button has been pressed down
+;------------------------------------------------------------------------------
+        test    [mouse.state.buttons], not mouse.LEFT_BUTTON_FLAG
+        jnz     .exit
+
+        call    mouse._.find_sys_window_under_cursor
+        call    mouse._.check_sys_window_actions
+        mov     [mouse.active_sys_window.action], al
+        or      eax, eax
+        jz      .exit
+
+        xchg    eax, edx
+        test    dl, mouse.WINDOW_MOVE_FLAG
+        jz      @f
+
+        mov     eax, [timer_ticks]
+        mov     ebx, eax
+        xchg    ebx, [mouse.active_sys_window.last_ticks]
+        sub     eax, ebx
+        cmp     eax, 50
+        jg      @f
+
+        mov     [mouse.active_sys_window.last_ticks], 0
+        call    sys_window_maximize_handler
+        jmp     .exit
+
+    @@: test    [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
+        jnz     .exit
+        mov     [mouse.active_sys_window.pslot], esi
+        lea     eax, [edi + WDATA.box]
+        mov     ebx, mouse.active_sys_window.old_box
+        mov     ecx, BOX.sizeof
+        call    memmove
+        mov     ebx, mouse.active_sys_window.new_box
+        call    memmove
+        test    edx, mouse.WINDOW_MOVE_FLAG
+        jz      @f
+
+        call    .calculate_n_delta
+        call    .calculate_w_delta
+        jmp     .call_window_handler
+
+    @@: test    dl, mouse.WINDOW_RESIZE_W_FLAG
+        jz      @f
+        call    .calculate_w_delta
+
+    @@: test    dl, mouse.WINDOW_RESIZE_S_FLAG
+        jz      @f
+        call    .calculate_s_delta
+
+    @@: test    dl, mouse.WINDOW_RESIZE_E_FLAG
+        jz      .call_window_handler
+        call    .calculate_e_delta
+
+  .call_window_handler:
+        mov     eax, mouse.active_sys_window.old_box
+        call    sys_window_start_moving_handler
+
+  .exit:
+        ret
+
+  .calculate_n_delta:
+        mov     eax, [mouse.state.pos.y]
+        sub     eax, [mouse.active_sys_window.old_box.top]
+        mov     [mouse.active_sys_window.delta.y], eax
+        ret
+
+  .calculate_w_delta:
+        mov     eax, [mouse.state.pos.x]
+        sub     eax, [mouse.active_sys_window.old_box.left]
+        mov     [mouse.active_sys_window.delta.x], eax
+        ret
+
+  .calculate_s_delta:
+        mov     eax, [mouse.active_sys_window.old_box.top]
+        add     eax, [mouse.active_sys_window.old_box.height]
+        sub     eax, [mouse.state.pos.y]
+        mov     [mouse.active_sys_window.delta.y], eax
+        ret
+
+  .calculate_e_delta:
+        mov     eax, [mouse.active_sys_window.old_box.left]
+        add     eax, [mouse.active_sys_window.old_box.width]
+        sub     eax, [mouse.state.pos.x]
+        mov     [mouse.active_sys_window.delta.x], eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.left_button_release_handler: ;/////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when left mouse button has been released
+;------------------------------------------------------------------------------
+        xor     esi, esi
+        xchg    esi, [mouse.active_sys_window.pslot]
+        or      esi, esi
+        jz      .exit
+
+        mov     eax, esi
+        shl     eax, 5
+        add     eax, window_data + WDATA.box
+        mov     ebx, mouse.active_sys_window.old_box
+        mov     ecx, BOX.sizeof
+        call    memmove
+
+        mov     eax, mouse.active_sys_window.old_box
+        mov     ebx, mouse.active_sys_window.new_box
+        call    sys_window_end_moving_handler
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.right_button_press_handler: ;//////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when right mouse button has been pressed down
+;------------------------------------------------------------------------------
+        test    [mouse.state.buttons], not mouse.RIGHT_BUTTON_FLAG
+        jnz     .exit
+
+        call    mouse._.find_sys_window_under_cursor
+        call    mouse._.check_sys_window_actions
+        test    al, mouse.WINDOW_MOVE_FLAG
+        jz      .exit
+
+        call    sys_window_rollup_handler
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.right_button_release_handler: ;////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when right mouse button has been released
+;------------------------------------------------------------------------------
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.middle_button_press_handler: ;/////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when middle mouse button has been pressed down
+;------------------------------------------------------------------------------
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.middle_button_release_handler: ;///////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when middle mouse button has been released
+;------------------------------------------------------------------------------
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.move_handler: ;////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Called when cursor has been moved
+;------------------------------------------------------------------------------
+;> eax = old x coord
+;> ebx = old y coord
+;------------------------------------------------------------------------------
+        cmp     [mouse.active_sys_button.pbid], 0
+        jnz     .exit
+
+        mov     esi, [mouse.active_sys_window.pslot]
+        or      esi, esi
+        jz      .exit
+
+        mov     eax, mouse.active_sys_window.new_box
+        mov     ebx, mouse.active_sys_window.old_box
+        mov     ecx, BOX.sizeof
+        call    memmove
+
+        mov     dl, [mouse.active_sys_window.action]
+        test    dl, mouse.WINDOW_MOVE_FLAG
+        jz      .check_resize_w
+
+        mov     eax, [mouse.state.pos.x]
+        sub     eax, [mouse.active_sys_window.delta.x]
+        mov     [mouse.active_sys_window.new_box.left], eax
+        mov     eax, [mouse.state.pos.y]
+        sub     eax, [mouse.active_sys_window.delta.y]
+        mov     [mouse.active_sys_window.new_box.top], eax
+
+        mov     eax, [mouse.active_sys_window.new_box.left]
+        or      eax, eax
+        jge     @f
+        xor     eax, eax
+        mov     [mouse.active_sys_window.new_box.left], eax
+    @@: add     eax, [mouse.active_sys_window.new_box.width]
+        cmp     eax, [Screen_Max_X]
+        jl      @f
+        sub     eax, [Screen_Max_X]
+        sub     [mouse.active_sys_window.new_box.left], eax
+    @@: mov     eax, [mouse.active_sys_window.new_box.top]
+        or      eax, eax
+        jge     @f
+        xor     eax, eax
+        mov     [mouse.active_sys_window.new_box.top], eax
+    @@: add     eax, [mouse.active_sys_window.new_box.height]
+        cmp     eax, [Screen_Max_Y]
+        jle     .call_window_handler
+        sub     eax, [Screen_Max_Y]
+        sub     [mouse.active_sys_window.new_box.top], eax
+        jmp     .call_window_handler
+
+  .check_resize_w:
+        test    dl, mouse.WINDOW_RESIZE_W_FLAG
+        jz      .check_resize_s
+
+        mov     eax, [mouse.state.pos.x]
+        sub     eax, [mouse.active_sys_window.delta.x]
+        mov     [mouse.active_sys_window.new_box.left], eax
+        sub     eax, [mouse.active_sys_window.old_box.left]
+        sub     [mouse.active_sys_window.new_box.width], eax
+
+        mov     eax, [mouse.active_sys_window.new_box.width]
+        sub     eax, 127
+        jge     @f
+        add     [mouse.active_sys_window.new_box.left], eax
+        mov     [mouse.active_sys_window.new_box.width], 127
+    @@: mov     eax, [mouse.active_sys_window.new_box.left]
+        or      eax, eax
+        jge     .check_resize_s
+        add     [mouse.active_sys_window.new_box.width], eax
+        xor     eax, eax
+        mov     [mouse.active_sys_window.new_box.left], eax
+
+  .check_resize_s:
+        test    dl, mouse.WINDOW_RESIZE_S_FLAG
+        jz      .check_resize_e
+
+        mov     eax, [mouse.state.pos.y]
+        add     eax, [mouse.active_sys_window.delta.y]
+        sub     eax, [mouse.active_sys_window.old_box.top]
+        mov     [mouse.active_sys_window.new_box.height], eax
+
+        push    eax
+        mov     edi, esi
+        shl     edi, 5
+        add     edi, window_data
+        call    window._.get_rolledup_height
+        mov     ecx, eax
+        pop     eax
+        mov     eax, [mouse.active_sys_window.new_box.height]
+        cmp     eax, ecx
+        jge     @f
+        mov     eax, ecx
+        mov     [mouse.active_sys_window.new_box.height], eax
+    @@: add     eax, [mouse.active_sys_window.new_box.top]
+        cmp     eax, [Screen_Max_Y]
+        jle     .check_resize_e
+        sub     eax, [Screen_Max_Y]
+        neg     eax
+        add     [mouse.active_sys_window.new_box.height], eax
+        mov     ecx, [Screen_Max_Y]
+        cmp     ecx, eax
+        jge     .check_resize_e
+        mov     [mouse.active_sys_window.new_box.height], ecx
+
+  .check_resize_e:
+        test    dl, mouse.WINDOW_RESIZE_E_FLAG
+        jz      .call_window_handler
+
+        mov     eax, [mouse.state.pos.x]
+        add     eax, [mouse.active_sys_window.delta.x]
+        sub     eax, [mouse.active_sys_window.old_box.left]
+        mov     [mouse.active_sys_window.new_box.width], eax
+
+        mov     eax, [mouse.active_sys_window.new_box.width]
+        cmp     eax, 127
+        jge     @f
+        mov     eax, 127
+        mov     [mouse.active_sys_window.new_box.width], eax
+    @@: add     eax, [mouse.active_sys_window.new_box.left]
+        cmp     eax, [Screen_Max_X]
+        jle     .call_window_handler
+        sub     eax, [Screen_Max_X]
+        neg     eax
+        add     [mouse.active_sys_window.new_box.width], eax
+        mov     ecx, [Screen_Max_X]
+        cmp     ecx, eax
+        jge     .call_window_handler
+        mov     [mouse.active_sys_window.new_box.width], ecx
+
+  .call_window_handler:
+        mov     eax, mouse.active_sys_window.old_box
+        mov     ebx, mouse.active_sys_window.new_box
+
+        push    esi
+        mov     esi, mouse.active_sys_window.old_box
+        mov     edi, mouse.active_sys_window.new_box
+        mov     ecx, BOX.sizeof / 4
+        repe
+        cmpsd
+        pop     esi
+        je      .exit
+
+        mov     [mouse.active_sys_window.last_ticks], 0
+        call    sys_window_moving_handler
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.find_sys_window_under_cursor: ;////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Find system window object which is currently visible on screen and has
+;? mouse cursor within its bounds
+;------------------------------------------------------------------------------
+;< esi = process slot
+;< edi = pointer to WDATA struct
+;------------------------------------------------------------------------------
+        mov     esi, [Screen_Max_X]
+        inc     esi
+        imul    esi, [mouse.state.pos.y]
+        add     esi, [_WinMapAddress]
+        add     esi, [mouse.state.pos.x]
+        movzx   esi, byte[esi]
+        mov     edi, esi
+        shl     edi, 5
+        add     edi, window_data
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.activate_sys_window_under_cursor: ;////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        ; activate and redraw window under cursor (if necessary)
+        call    mouse._.find_sys_window_under_cursor
+        movzx   esi, word[WIN_STACK + esi * 2]
+        lea     esi, [WIN_POS + esi * 2]
+        jmp     waredraw
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.find_sys_button_under_cursor: ;////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Find system button object which is currently visible on screen and has
+;? mouse cursor within its bounds
+;------------------------------------------------------------------------------
+;< eax = pack[8(process slot), 24(button id)] or 0
+;< ebx = pack[16(button x coord), 16(button y coord)]
+;------------------------------------------------------------------------------
+        push    ecx edx esi edi
+
+        call    mouse._.find_sys_window_under_cursor
+        mov     edx, esi
+
+        ; check if any process button contains cursor
+        mov     eax, [BTN_ADDR]
+        mov     ecx, [eax]
+        imul    esi, ecx, SYS_BUTTON.sizeof
+        add     esi, eax
+        inc     ecx
+        add     esi, SYS_BUTTON.sizeof
+
+  .next_button:
+        dec     ecx
+        jz      .not_found
+
+        add     esi, -SYS_BUTTON.sizeof
+
+        ; does it belong to our process?
+        cmp     dx, [esi + SYS_BUTTON.pslot]
+        jne     .next_button
+
+        ; does it contain cursor coordinates?
+        mov     eax, [mouse.state.pos.x]
+        sub     eax, [edi + WDATA.box.left]
+        sub     ax, [esi + SYS_BUTTON.left]
+        jl      .next_button
+        sub     ax, [esi + SYS_BUTTON.width]
+        jge     .next_button
+        mov     eax, [mouse.state.pos.y]
+        sub     eax, [edi + WDATA.box.top]
+        sub     ax, [esi + SYS_BUTTON.top]
+        jl      .next_button
+        sub     ax, [esi + SYS_BUTTON.height]
+        jge     .next_button
+
+        ; okay, return it
+        shl     edx, 24
+        mov     eax, dword[esi + SYS_BUTTON.id_hi - 2]
+        mov     ax, [esi + SYS_BUTTON.id_lo]
+        and     eax, 0x0ffffff
+        or      eax, edx
+        mov     ebx, dword[esi + SYS_BUTTON.left - 2]
+        mov     bx, [esi + SYS_BUTTON.top]
+        jmp     .exit
+
+  .not_found:
+        xor     eax, eax
+        xor     ebx, ebx
+
+  .exit:
+        pop     edi esi edx ecx
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+mouse._.check_sys_window_actions: ;////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;< eax = action flags or 0
+;------------------------------------------------------------------------------
+        ; is window movable?
+        test    byte[edi + WDATA.cl_titlebar + 3], 0x01
+        jnz     .no_action
+
+        mov     eax, [mouse.state.pos.x]
+        mov     ebx, [mouse.state.pos.y]
+        sub     eax, [edi + WDATA.box.left]
+        sub     ebx, [edi + WDATA.box.top]
+
+        ; is there a window titlebar under cursor?
+        push    eax
+        call    window._.get_titlebar_height
+        cmp     ebx, eax
+        pop     eax
+        jl      .move_action
+
+        ; no there isn't, can it be resized then?
+        mov     dl, [edi + WDATA.fl_wstyle]
+        and     dl, 0x0f
+        ; NOTE: dangerous optimization, revise if window types changed;
+        ;       this currently implies only types 2 and 3 could be resized
+        test    dl, 2
+        jz      .no_action
+
+        mov     ecx, [edi + WDATA.box.width]
+        add     ecx, -window.BORDER_SIZE
+        mov     edx, [edi + WDATA.box.height]
+        add     edx, -window.BORDER_SIZE
+
+        ; is it rolled up?
+        test    [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
+        jnz     .resize_w_or_e_action
+
+        cmp     eax, window.BORDER_SIZE
+        jl      .resize_w_action
+        cmp     eax, ecx
+        jg      .resize_e_action
+        cmp     ebx, edx
+        jle     .no_action
+
+  .resize_s_action:
+        cmp     eax, window.BORDER_SIZE + 10
+        jl      .resize_sw_action
+        add     ecx, -10
+        cmp     eax, ecx
+        jge     .resize_se_action
+        mov     eax, mouse.WINDOW_RESIZE_S_FLAG
+        jmp     .exit
+
+  .resize_w_or_e_action:
+        cmp     eax, window.BORDER_SIZE + 10
+        jl      .resize_w_action.direct
+        add     ecx, -10
+        cmp     eax, ecx
+        jg      .resize_e_action.direct
+        jmp     .no_action
+
+  .resize_w_action:
+        add     edx, -10
+        cmp     ebx, edx
+        jge     .resize_sw_action
+  .resize_w_action.direct:
+        mov     eax, mouse.WINDOW_RESIZE_W_FLAG
+        jmp     .exit
+
+  .resize_e_action:
+        add     edx, -10
+        cmp     ebx, edx
+        jge     .resize_se_action
+  .resize_e_action.direct:
+        mov     eax, mouse.WINDOW_RESIZE_E_FLAG
+        jmp     .exit
+
+  .resize_sw_action:
+        mov     eax, mouse.WINDOW_RESIZE_SW_FLAG
+        jmp     .exit
+
+  .resize_se_action:
+        mov     eax, mouse.WINDOW_RESIZE_SE_FLAG
+        jmp     .exit
+
+  .move_action:
+        mov     eax, mouse.WINDOW_MOVE_FLAG
+        jmp     .exit
+
+  .no_action:
+        xor     eax, eax
+
+  .exit:
+        ret
diff --git a/kernel/branches/Kolibri-A/trunk/gui/window.inc b/kernel/branches/Kolibri-A/trunk/gui/window.inc
index 7194f2e8a5..ebf199d8ce 100644
--- a/kernel/branches/Kolibri-A/trunk/gui/window.inc
+++ b/kernel/branches/Kolibri-A/trunk/gui/window.inc
@@ -1,2077 +1,2085 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;                                                              ;;
-;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
-;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa      ;;
-;; Distributed under terms of the GNU General Public License    ;;
-;;                                                              ;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-$Revision$
-
-;==============================================================================
-;///// public functions ///////////////////////////////////////////////////////
-;==============================================================================
-
-window.BORDER_SIZE = 5
-
-macro FuncTable name, table_name, [label]
-{
-  common
-    align 4
-    \label name#.#table_name dword
-  forward
-    dd name#.#label
-  common
-    name#.sizeof.#table_name = $ - name#.#table_name
-}
-
-uglobal
-  common_colours rd 32
-  draw_limits    RECT
-endg
-
-align 4
-;------------------------------------------------------------------------------
-syscall_draw_window: ;///// system function 0 /////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        mov     eax, edx
-        shr     eax, 24
-        and     al, 0x0f
-        cmp     al, 5
-        jae     .exit
-
-        push    eax
-        inc     [mouse_pause]
-        call    [_display.disable_mouse]
-        call    window._.sys_set_window
-        call    [_display.disable_mouse]
-        pop     eax
-
-        or      al, al
-        jnz     @f
-
-        ; type I - original style
-        call    drawwindow_I
-        jmp     window._.draw_window_caption.2
-
-    @@: dec     al
-        jnz     @f
-
-        ; type II - only reserve area, no draw
-        call    sys_window_mouse
-        dec     [mouse_pause]
-        call    [draw_pointer]
-        jmp     .exit
-
-    @@: dec     al
-        jnz     @f
-
-        ; type III  - new style
-        call    drawwindow_III
-        jmp     window._.draw_window_caption.2
-
-        ; type IV & V - skinned window (resizable & not)
-    @@: mov     eax, [TASK_COUNT]
-        movzx   eax, word[WIN_POS + eax * 2]
-        cmp     eax, [CURRENT_TASK]
-        setz    al
-        movzx   eax, al
-        push    eax
-        call    drawwindow_IV
-        jmp     window._.draw_window_caption.2
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-syscall_display_settings: ;///// system function 48 ///////////////////////////
-;------------------------------------------------------------------------------
-;; Redraw screen:
-;< ebx = 0
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Set button style:
-;< ebx = 1
-;< ecx = 0 (flat) or 1 (with gradient)
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Set system color palette:
-;< ebx = 2
-;< ecx = pointer to color table
-;< edx = size of color table
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Get system color palette:
-;< ebx = 3
-;< ecx = pointer to color table buffer
-;< edx = size of color table buffer
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Get skinned caption height:
-;< ebx = 4
-;> eax = height in pixels
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Get screen working area:
-;< ebx = 5
-;> eax = pack[16(left), 16(right)]
-;> ebx = pack[16(top), 16(bottom)]
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Set screen working area:
-;< ebx = 6
-;< ecx = pack[16(left), 16(right)]
-;< edx = pack[16(top), 16(bottom)]
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Get skin margins:
-;< ebx = 7
-;> eax = pack[16(left), 16(right)]
-;> ebx = pack[16(top), 16(bottom)]
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Set skin:
-;< ebx = 8
-;< ecx = pointer to FileInfoBlock struct
-;> eax = FS error code
-;------------------------------------------------------------------------------
-        cmp     ebx, .sizeof.ftable / 4
-        ja      @f
-        jmp     [.ftable + ebx * 4]
-    @@: ret
-
-
-align 4
-syscall_display_settings.00:
-        xor     eax, eax
-        inc     ebx
-        cmp     [windowtypechanged], ebx
-        jne     .exit
-        mov     [windowtypechanged], eax
-
-        jmp     syscall_display_settings._.redraw_whole_screen
-
-  .exit:
-        ret
-
-align 4
-syscall_display_settings.01:
-        and     ecx, 1
-        cmp     ecx, [buttontype]
-        je      .exit
-        mov     [buttontype], ecx
-        mov     [windowtypechanged], ebx
-
-  .exit:
-        ret
-
-align 4
-syscall_display_settings.02:
-        dec     ebx
-        mov     esi, ecx
-        and     edx, 127
-        mov     edi, common_colours
-        mov     ecx, edx
-        rep     movsb
-        mov     [windowtypechanged], ebx
-        ret
-
-align 4
-syscall_display_settings.03:
-        mov     edi, ecx
-        and     edx, 127
-        mov     esi, common_colours
-        mov     ecx, edx
-        rep     movsb
-        ret
-
-align 4
-syscall_display_settings.04:
-        mov     eax, [_skinh]
-        mov     [esp + 32], eax
-        ret
-
-align 4
-syscall_display_settings.05:
-        mov     eax, [screen_workarea.left - 2]
-        mov     ax, word[screen_workarea.right]
-        mov     [esp + 32], eax
-        mov     eax, [screen_workarea.top - 2]
-        mov     ax, word[screen_workarea.bottom]
-        mov     [esp + 20], eax
-        ret
-
-align 4
-syscall_display_settings.06:
-        xor     esi, esi
-
-        mov     edi, [Screen_Max_X]
-        mov     eax, ecx
-        movsx   ebx, ax
-        sar     eax, 16
-        cmp     eax, ebx
-        jge     .check_horizontal
-        inc     esi
-        or      eax, eax
-        jge     @f
-        xor     eax, eax
-    @@: mov     [screen_workarea.left], eax
-        cmp     ebx, edi
-        jle     @f
-        mov     ebx, edi
-    @@: mov     [screen_workarea.right], ebx
-
-  .check_horizontal:
-        mov     edi, [Screen_Max_Y]
-        mov     eax, edx
-        movsx   ebx, ax
-        sar     eax, 16
-        cmp     eax, ebx
-        jge     .check_if_redraw_needed
-        inc     esi
-        or      eax, eax
-        jge     @f
-        xor     eax, eax
-    @@: mov     [screen_workarea.top], eax
-        cmp     ebx, edi
-        jle     @f
-        mov     ebx, edi
-    @@: mov     [screen_workarea.bottom], ebx
-
-  .check_if_redraw_needed:
-        or      esi, esi
-        jz      .exit
-
-        call    repos_windows
-        jmp     syscall_display_settings._.calculate_whole_screen
-
-  .exit:
-        ret
-
-align 4
-syscall_display_settings.07:
-        mov     eax, [_skinmargins + 0]
-        mov     [esp + 32], eax
-        mov     eax, [_skinmargins + 4]
-        mov     [esp + 20], eax
-        ret
-
-align 4
-syscall_display_settings.08:
-        mov     ebx, ecx
-        call    read_skin_file
-        mov     [esp + 32], eax
-        test    eax, eax
-        jnz     .exit
-
-        call    syscall_display_settings._.calculate_whole_screen
-        jmp     syscall_display_settings._.redraw_whole_screen
-
-  .exit:
-        ret
-
-syscall_display_settings._.calculate_whole_screen:
-        xor     eax, eax
-        xor     ebx, ebx
-        mov     ecx, [Screen_Max_X]
-        mov     edx, [Screen_Max_Y]
-        jmp     calculatescreen
-
-syscall_display_settings._.redraw_whole_screen:
-        xor     eax, eax
-        mov     [draw_limits.left], eax
-        mov     [draw_limits.top], eax
-        mov     eax, [Screen_Max_X]
-        mov     [draw_limits.right], eax
-        mov     eax, [Screen_Max_Y]
-        mov     [draw_limits.bottom], eax
-        mov     eax, window_data
-        jmp     redrawscreen
-
-align 4
-;------------------------------------------------------------------------------
-syscall_set_window_shape: ;///// system function 50 ///////////////////////////
-;------------------------------------------------------------------------------
-;; Set window shape address:
-;> ebx = 0
-;> ecx = shape data address
-; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-;; Set window shape scale:
-;> ebx = 1
-;> ecx = scale power (resulting scale is 2^ebx)
-;------------------------------------------------------------------------------
-        mov     edi, [current_slot]
-
-        test    ebx, ebx
-        jne     .shape_scale
-        mov     [edi + APPDATA.wnd_shape], ecx
-
-  .shape_scale:
-        dec     ebx
-        jnz     .exit
-        mov     [edi + APPDATA.wnd_shape_scale], ecx
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-syscall_move_window: ;///// system function 67 ////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        mov     edi, [CURRENT_TASK]
-        shl     edi, 5
-        add     edi, window_data
-
-        test    [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
-        jnz     .exit
-
-        cmp     ebx, -1
-        jne     @f
-        mov     ebx, [edi + WDATA.box.left]
-    @@: cmp     ecx, -1
-        jne     @f
-        mov     ecx, [edi + WDATA.box.top]
-    @@: cmp     edx, -1
-        jne     @f
-        mov     edx, [edi + WDATA.box.width]
-    @@: cmp     esi, -1
-        jne     @f
-        mov     esi, [edi + WDATA.box.height]
-
-    @@: push    esi edx ecx ebx
-        mov     eax, esp
-        mov     bl, [edi + WDATA.fl_wstate]
-        call    window._.set_window_box
-        add     esp, BOX.sizeof
-
-        ; NOTE: do we really need this? to be reworked
-;       mov     byte[DONT_DRAW_MOUSE], 0 ; mouse pointer
-;       mov     byte[MOUSE_BACKGROUND], 0 ; no mouse under
-;       mov     byte[MOUSE_DOWN], 0 ; react to mouse up/down
-
-        ; NOTE: do we really need this? to be reworked
-;       call    [draw_pointer]
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-syscall_window_settings: ;///// system function 71 /////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        dec     ebx     ; subfunction #1 - set window caption
-        jnz     .exit_fail
-
-        ; NOTE: only window owner thread can set its caption,
-        ;       so there's no parameter for PID/TID
-
-        mov     edi, [CURRENT_TASK]
-        shl     edi, 5
-
-        mov     [edi * 8 + SLOT_BASE + APPDATA.wnd_caption], ecx
-        or      [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION
-
-        call    window._.draw_window_caption
-
-        xor     eax, eax ; eax = 0 (success)
-        ret
-
-;  .get_window_caption:
-;        dec     eax     ; subfunction #2 - get window caption
-;        jnz     .exit_fail
-
-        ; not implemented yet
-
-  .exit_fail:
-        xor     eax, eax
-        inc     eax     ; eax = 1 (fail)
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-set_window_defaults: ;/////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        push    eax ecx
-        xor     eax, eax
-        mov     ecx, WIN_STACK
-    @@: inc     eax
-        add     ecx, 2
-        ; process no
-        mov     [ecx + 0x000], ax
-        ; positions in stack
-        mov     [ecx + 0x400], ax
-        cmp     ecx, WIN_POS - 2
-        jne     @b
-        pop     ecx eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-calculatescreen: ;/////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Scan all windows from bottom to top, calling `setscreen` for each one
-;? intersecting given screen area
-;------------------------------------------------------------------------------
-;> eax = left
-;> ebx = top
-;> ecx = right
-;> edx = bottom
-;------------------------------------------------------------------------------
-        push    esi
-        pushfd
-        cli
-
-        mov     esi, 1
-        call    window._.set_screen
-
-        push    ebp
-
-        mov     ebp, [TASK_COUNT]
-        cmp     ebp, 1
-        jbe     .exit
-
-        push    edx ecx ebx eax
-
-  .next_window:
-        movzx   edi, word[WIN_POS + esi * 2]
-        shl     edi, 5
-
-        cmp     [CURRENT_TASK + edi + TASKDATA.state], TSTATE_FREE
-        je      .skip_window
-
-        add     edi, window_data
-        test    [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
-        jnz     .skip_window
-
-        mov     eax, [edi + WDATA.box.left]
-        cmp     eax, [esp + RECT.right]
-        jg      .skip_window
-        mov     ebx, [edi + WDATA.box.top]
-        cmp     ebx, [esp + RECT.bottom]
-        jg      .skip_window
-        mov     ecx, [edi + WDATA.box.width]
-        add     ecx, eax
-        cmp     ecx, [esp + RECT.left]
-        jl      .skip_window
-        mov     edx, [edi + WDATA.box.height]
-        add     edx, ebx
-        cmp     edx, [esp + RECT.top]
-        jl      .skip_window
-
-        cmp     eax, [esp + RECT.left]
-        jae     @f
-        mov     eax, [esp + RECT.left]
-    @@: cmp     ebx, [esp + RECT.top]
-        jae     @f
-        mov     ebx, [esp + RECT.top]
-    @@: cmp     ecx, [esp + RECT.right]
-        jbe     @f
-        mov     ecx, [esp + RECT.right]
-    @@: cmp     edx, [esp + RECT.bottom]
-        jbe     @f
-        mov     edx, [esp + RECT.bottom]
-
-    @@: push    esi
-        movzx   esi, word[WIN_POS + esi * 2]
-        call    window._.set_screen
-        pop     esi
-
-  .skip_window:
-        inc     esi
-        dec     ebp
-        jnz     .next_window
-
-        pop     eax ebx ecx edx
-
-  .exit:
-        pop     ebp
-        popfd
-        pop     esi
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-repos_windows: ;///////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        mov     ecx, [TASK_COUNT]
-        mov     edi, window_data + WDATA.sizeof * 2
-        call    force_redraw_background
-        dec     ecx
-        jle     .exit
-
-  .next_window:
-        mov     [edi + WDATA.fl_redraw], 1
-        test    [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
-        jnz     .fix_maximized
-
-        mov     eax, [edi + WDATA.box.left]
-        add     eax, [edi + WDATA.box.width]
-        mov     ebx, [Screen_Max_X]
-        cmp     eax, ebx
-        jle     .fix_vertical
-        mov     eax, [edi + WDATA.box.width]
-        sub     eax, ebx
-        jle     @f
-        mov     [edi + WDATA.box.width], ebx
-    @@: sub     ebx, [edi + WDATA.box.width]
-        mov     [edi + WDATA.box.left], ebx
-
-  .fix_vertical:
-        mov     eax, [edi + WDATA.box.top]
-        add     eax, [edi + WDATA.box.height]
-        mov     ebx, [Screen_Max_Y]
-        cmp     eax, ebx
-        jle     .fix_client_box
-        mov     eax, [edi + WDATA.box.height]
-        sub     eax, ebx
-        jle     @f
-        mov     [edi + WDATA.box.height], ebx
-    @@: sub     ebx, [edi + WDATA.box.height]
-        mov     [edi + WDATA.box.top], ebx
-        jmp     .fix_client_box
-
-  .fix_maximized:
-        mov     eax, [screen_workarea.left]
-        mov     [edi + WDATA.box.left], eax
-        sub     eax, [screen_workarea.right]
-        neg     eax
-        mov     [edi + WDATA.box.width], eax
-        mov     eax, [screen_workarea.top]
-        mov     [edi + WDATA.box.top], eax
-        test    [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
-        jnz     .fix_client_box
-        sub     eax, [screen_workarea.bottom]
-        neg     eax
-        mov     [edi + WDATA.box.height], eax
-
-  .fix_client_box:
-        call    window._.set_window_clientbox
-
-        add     edi, WDATA.sizeof
-        loop    .next_window
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-sys_window_mouse: ;////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        ; NOTE: commented out since doesn't provide necessary functionality
-        ;       anyway, to be reworked
-;       push    eax
-;
-;       mov     eax, [timer_ticks]
-;       cmp     [new_window_starting], eax
-;       jb      .exit
-;
-;       mov     byte[MOUSE_BACKGROUND], 0
-;       mov     byte[DONT_DRAW_MOUSE], 0
-;
-;       mov     [new_window_starting], eax
-;
-; .exit:
-;       pop     eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-draw_rectangle: ;//////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;> eax = pack[16(left), 16(right)]
-;> ebx = pack[16(top), 16(bottom)]
-;> esi = color
-;------------------------------------------------------------------------------
-        push    eax ebx ecx edi
-
-        xor     edi, edi
-
-  .flags_set:
-        push    ebx
-
-        ; set line color
-        mov     ecx, esi
-
-        ; draw top border
-        rol     ebx, 16
-        push    ebx
-        rol     ebx, 16
-        pop     bx
-        call    [draw_line]
-
-        ; draw bottom border
-        mov     ebx, [esp - 2]
-        pop     bx
-        call    [draw_line]
-
-        pop     ebx
-        add     ebx, 1 * 65536 - 1
-
-        ; draw left border
-        rol     eax, 16
-        push    eax
-        rol     eax, 16
-        pop     ax
-        call    [draw_line]
-
-        ; draw right border
-        mov     eax, [esp - 2]
-        pop     ax
-        call    [draw_line]
-
-        pop     edi ecx ebx eax
-        ret
-
-  .forced:
-        push    eax ebx ecx edi
-        xor     edi, edi
-        inc     edi
-        jmp     .flags_set
-
-align 4
-;------------------------------------------------------------------------------
-drawwindow_I_caption: ;////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        push    [edx + WDATA.cl_titlebar]
-        mov     esi, edx
-
-        mov     edx, [esi + WDATA.box.top]
-        mov     eax, edx
-        lea     ebx, [edx + 21]
-        inc     edx
-        add     eax, [esi + WDATA.box.height]
-
-        cmp     ebx, eax
-        jbe     @f
-        mov     ebx, eax
-    @@: push    ebx
-
-        xor     edi, edi
-
-  .next_line:
-        mov     ebx, edx
-        shl     ebx, 16
-        add     ebx, edx
-        mov     eax, [esi + WDATA.box.left]
-        inc     eax
-        shl     eax, 16
-        add     eax, [esi + WDATA.box.left]
-        add     eax, [esi + WDATA.box.width]
-        dec     eax
-        mov     ecx, [esi + WDATA.cl_titlebar]
-        test    ecx, 0x80000000
-        jz      @f
-        sub     ecx, 0x00040404
-        mov     [esi + WDATA.cl_titlebar], ecx
-    @@: and     ecx, 0x00ffffff
-        call    [draw_line]
-        inc     edx
-        cmp     edx, [esp]
-        jb      .next_line
-
-        add     esp, 4
-        pop     [esi + WDATA.cl_titlebar]
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-drawwindow_I: ;////////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        pushad
-
-        ; window border
-
-        mov     eax, [edx + WDATA.box.left - 2]
-        mov     ax, word[edx + WDATA.box.left]
-        add     ax, word[edx + WDATA.box.width]
-        mov     ebx, [edx + WDATA.box.top - 2]
-        mov     bx, word[edx + WDATA.box.top]
-        add     bx, word[edx + WDATA.box.height]
-
-        mov     esi, [edx + WDATA.cl_frames]
-        call    draw_rectangle
-
-        ; window caption
-
-        call    drawwindow_I_caption
-
-        ; window client area
-
-        ; do we need to draw it?
-        mov     edi, [esi + WDATA.cl_workarea]
-        test    edi, 0x40000000
-        jnz     .exit
-
-        ; does client area have a positive size on screen?
-        mov     edx, [esi + WDATA.box.top]
-        add     edx, 21 + 5
-        mov     ebx, [esi + WDATA.box.top]
-        add     ebx, [esi + WDATA.box.height]
-        cmp     edx, ebx
-        jg      .exit
-
-        ; okay, let's draw it
-        mov     eax, 1
-        mov     ebx, 21
-        mov     ecx, [esi + WDATA.box.width]
-        mov     edx, [esi + WDATA.box.height]
-        call    [drawbar]
-
-  .exit:
-        popad
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-drawwindow_III_caption: ;/////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        mov     ecx, [edx + WDATA.cl_titlebar]
-        push    ecx
-        mov     esi, edx
-        mov     edx, [esi + WDATA.box.top]
-        add     edx, 4
-        mov     ebx, [esi + WDATA.box.top]
-        add     ebx, 20
-        mov     eax, [esi + WDATA.box.top]
-        add     eax, [esi + WDATA.box.height]
-
-        cmp     ebx, eax
-        jb      @f
-        mov     ebx, eax
-    @@: push    ebx
-
-        xor     edi, edi
-
-  .next_line:
-        mov     ebx, edx
-        shl     ebx, 16
-        add     ebx, edx
-        mov     eax, [esi + WDATA.box.left]
-        shl     eax, 16
-        add     eax, [esi + WDATA.box.left]
-        add     eax, [esi + WDATA.box.width]
-        add     eax, 4 * 65536 - 4
-        mov     ecx, [esi + WDATA.cl_titlebar]
-        test    ecx, 0x40000000
-        jz      @f
-        add     ecx, 0x00040404
-    @@: test    ecx, 0x80000000
-        jz      @f
-        sub     ecx, 0x00040404
-    @@: mov     [esi + WDATA.cl_titlebar], ecx
-        and     ecx, 0x00ffffff
-        call    [draw_line]
-        inc     edx
-        cmp     edx, [esp]
-        jb      .next_line
-
-        add     esp, 4
-        pop     [esi + WDATA.cl_titlebar]
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-drawwindow_III: ;//////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        pushad
-
-        ; window border
-
-        mov     eax, [edx + WDATA.box.left - 2]
-        mov     ax, word[edx + WDATA.box.left]
-        add     ax, word[edx + WDATA.box.width]
-        mov     ebx, [edx + WDATA.box.top - 2]
-        mov     bx, word[edx + WDATA.box.top]
-        add     bx, word[edx + WDATA.box.height]
-
-        mov     esi, [edx + WDATA.cl_frames]
-        shr     esi, 1
-        and     esi, 0x007f7f7f
-        call    draw_rectangle
-
-        push    esi
-        mov     ecx, 3
-        mov     esi, [edx + WDATA.cl_frames]
-
-  .next_frame:
-        add     eax, 1 * 65536 - 1
-        add     ebx, 1 * 65536 - 1
-        call    draw_rectangle
-        dec     ecx
-        jnz     .next_frame
-
-        pop     esi
-        add     eax, 1 * 65536 - 1
-        add     ebx, 1 * 65536 - 1
-        call    draw_rectangle
-
-        ; window caption
-
-        call    drawwindow_III_caption
-
-        ; window client area
-
-        ; do we need to draw it?
-        mov     edi, [esi + WDATA.cl_workarea]
-        test    edi, 0x40000000
-        jnz     .exit
-
-        ; does client area have a positive size on screen?
-        mov     edx, [esi + WDATA.box.top]
-        add     edx, 21 + 5
-        mov     ebx, [esi + WDATA.box.top]
-        add     ebx, [esi + WDATA.box.height]
-        cmp     edx, ebx
-        jg      .exit
-
-        ; okay, let's draw it
-        mov     eax, 5
-        mov     ebx, 20
-        mov     ecx, [esi + WDATA.box.width]
-        mov     edx, [esi + WDATA.box.height]
-        sub     ecx, 4
-        sub     edx, 4
-        call    [drawbar]
-
-  .exit:
-        popad
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-waredraw: ;////////////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Activate window, redrawing if necessary
-;------------------------------------------------------------------------------
-        push    -1
-        mov     eax, [TASK_COUNT]
-        lea     eax, [WIN_POS + eax * 2]
-        cmp     eax, esi
-        pop     eax
-        je      .exit
-
-        ; is it overlapped by another window now?
-        push    ecx
-        call    window._.check_window_draw
-        test    ecx, ecx
-        pop     ecx
-        jz      .do_not_draw
-
-        ; yes it is, activate and update screen buffer
-        mov     byte[MOUSE_DOWN], 1
-        call    window._.window_activate
-
-        pushad
-        mov     edi, [TASK_COUNT]
-        movzx   esi, word[WIN_POS + edi * 2]
-        shl     esi, 5
-        add     esi, window_data
-
-        mov     eax, [esi + WDATA.box.left]
-        mov     ebx, [esi + WDATA.box.top]
-        mov     ecx, [esi + WDATA.box.width]
-        mov     edx, [esi + WDATA.box.height]
-
-        add     ecx, eax
-        add     edx, ebx
-
-        mov     edi, [TASK_COUNT]
-        movzx   esi, word[WIN_POS + edi * 2]
-        call    window._.set_screen
-        popad
-
-        ; tell application to redraw itself
-        mov     [edi + WDATA.fl_redraw], 1
-        xor     eax, eax
-        jmp     .exit
-
-  .do_not_draw:
-        ; no it's not, just activate the window
-        call    window._.window_activate
-        xor     eax, eax
-        mov     byte[MOUSE_BACKGROUND], al
-        mov     byte[DONT_DRAW_MOUSE], al
-
-
-  .exit:
-        mov     byte[MOUSE_DOWN], 0
-        inc     eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-minimize_window: ;/////////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;> eax = window number on screen
-;------------------------------------------------------------------------------
-;# corrupts [dl*]
-;------------------------------------------------------------------------------
-        push    edi
-        pushfd
-        cli
-
-        ; is it already minimized?
-        movzx   edi, word[WIN_POS + eax * 2]
-        shl     edi, 5
-        add     edi, window_data
-        test    [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
-        jnz     .exit
-
-        push    eax ebx ecx edx esi
-
-        ; no it's not, let's do that
-        or      [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
-        mov     eax, [edi + WDATA.box.left]
-        mov     [draw_limits.left], eax
-        mov     ecx, eax
-        add     ecx, [edi + WDATA.box.width]
-        mov     [draw_limits.right], ecx
-        mov     ebx, [edi + WDATA.box.top]
-        mov     [draw_limits.top], ebx
-        mov     edx, ebx
-        add     edx, [edi + WDATA.box.height]
-        mov     [draw_limits.bottom], edx
-        call    calculatescreen
-        xor     esi, esi
-        xor     eax, eax
-        call    redrawscreen
-
-        pop     esi edx ecx ebx eax
-
-  .exit:
-        popfd
-        pop     edi
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-restore_minimized_window: ;////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;> eax = window number on screen
-;------------------------------------------------------------------------------
-;# corrupts [dl*]
-;------------------------------------------------------------------------------
-        pushad
-        pushfd
-        cli
-
-        ; is it already restored?
-        movzx   esi, word[WIN_POS + eax * 2]
-        mov     edi, esi
-        shl     edi, 5
-        add     edi, window_data
-        test    [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
-        jz      .exit
-
-        ; no it's not, let's do that
-        mov     [edi + WDATA.fl_redraw], 1
-        and     [edi + WDATA.fl_wstate], not WSTATE_MINIMIZED
-        mov     ebp, window._.set_screen
-        cmp     eax, [TASK_COUNT]
-        jz      @f
-        mov     ebp, calculatescreen
-    @@: mov     eax, [edi + WDATA.box.left]
-        mov     ebx, [edi + WDATA.box.top]
-        mov     ecx, [edi + WDATA.box.width]
-        mov     edx, [edi + WDATA.box.height]
-        add     ecx, eax
-        add     edx, ebx
-        call    ebp
-
-        mov     byte[MOUSE_BACKGROUND], 0
-
-  .exit:
-        popfd
-        popad
-        ret
-
-align 4
-; TODO: remove this proc
-;------------------------------------------------------------------------------
-window_check_events: ;/////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        ; do we have window minimize/restore request?
-        cmp     [window_minimize], 0
-        je      .exit
-
-        ; okay, minimize or restore top-most window and exit
-        mov     eax, [TASK_COUNT]
-        mov     bl, 0
-        xchg    [window_minimize], bl
-        dec     bl
-        jnz     @f
-        call    minimize_window
-        jmp     .exit
-
-    @@: call    restore_minimized_window
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-sys_window_maximize_handler: ;/////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> esi = process slot
-;------------------------------------------------------------------------------
-        mov     edi, esi
-        shl     edi, 5
-        add     edi, window_data
-
-        ; can window change its height?
-        mov     dl, [edi + WDATA.fl_wstyle]
-        and     dl, 0x0f
-        cmp     dl, 0x04
-        je      .exit
-
-        ; toggle normal/maximized window state
-        mov     bl, [edi + WDATA.fl_wstate]
-        xor     bl, WSTATE_MAXIMIZED
-
-        ; calculate and set appropriate window bounds
-        test    bl, WSTATE_MAXIMIZED
-        jz      .restore_size
-
-        mov     eax, [screen_workarea.left]
-        mov     ecx, [screen_workarea.top]
-        push    [screen_workarea.bottom] \
-                [screen_workarea.right] \
-                ecx \
-                eax
-        sub     [esp + BOX.width], eax
-        sub     [esp + BOX.height], ecx
-        mov     eax, esp
-        jmp     .set_box
-
-  .restore_size:
-        mov     eax, esi
-        shl     eax, 8
-        add     eax, SLOT_BASE + APPDATA.saved_box
-        push    [eax + BOX.height] \
-                [eax + BOX.width] \
-                [eax + BOX.top] \
-                [eax + BOX.left]
-        mov     eax, esp
-
-  .set_box:
-        test    bl, WSTATE_ROLLEDUP
-        jz      @f
-
-        xchg    eax, ecx
-        call    window._.get_rolledup_height
-        mov     [ecx + BOX.height], eax
-        xchg    eax, ecx
-
-    @@: call    window._.set_window_box
-        add     esp, BOX.sizeof
-
-  .exit:
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-sys_window_rollup_handler: ;///////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> esi = process slot
-;------------------------------------------------------------------------------
-        mov     edx, esi
-        shl     edx, 8
-        add     edx, SLOT_BASE
-
-        ; toggle normal/rolled up window state
-        mov     bl, [edi + WDATA.fl_wstate]
-        xor     bl, WSTATE_ROLLEDUP
-
-        ; calculate and set appropriate window bounds
-        test    bl, WSTATE_ROLLEDUP
-        jz      .restore_size
-
-        call    window._.get_rolledup_height
-        push    eax \
-                [edi + WDATA.box.width] \
-                [edi + WDATA.box.top] \
-                [edi + WDATA.box.left]
-        mov     eax, esp
-        jmp     .set_box
-
-  .restore_size:
-        test    bl, WSTATE_MAXIMIZED
-        jnz     @f
-        add     esp, -BOX.sizeof
-        lea     eax, [edx + APPDATA.saved_box]
-        jmp     .set_box
-
-    @@: mov     eax, [screen_workarea.top]
-        push    [screen_workarea.bottom] \
-                [edi + WDATA.box.width] \
-                eax \
-                [edi + WDATA.box.left]
-        sub     [esp + BOX.height], eax
-        mov     eax, esp
-
-  .set_box:
-        call    window._.set_window_box
-        add     esp, BOX.sizeof
-
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-sys_window_start_moving_handler: ;/////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> eax = old (original) window box
-;> esi = process slot
-;------------------------------------------------------------------------------
-        mov     edi, eax
-        call    window._.draw_negative_box
-
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-sys_window_end_moving_handler: ;///////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> eax = old (original) window box
-;> ebx = new (final) window box
-;> esi = process slot
-;------------------------------------------------------------------------------
-        mov     edi, ebx
-        call    window._.draw_negative_box
-
-        mov     edi, esi
-        shl     edi, 5
-        add     edi, window_data
-
-        mov     eax, ebx
-        mov     bl, [edi + WDATA.fl_wstate]
-        call    window._.set_window_box
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-sys_window_moving_handler: ;///////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> eax = old (from previous call) window box
-;> ebx = new (current) window box
-;> esi = process_slot
-;------------------------------------------------------------------------------
-        mov     edi, eax
-        call    window._.draw_negative_box
-        mov     edi, ebx
-        call    window._.draw_negative_box
-        ret
-
-;==============================================================================
-;///// private functions //////////////////////////////////////////////////////
-;==============================================================================
-
-iglobal
-  FuncTable syscall_display_settings, ftable, \
-    00, 01, 02, 03, 04, 05, 06, 07, 08
-
-  align 4
-  window_topleft dd \
-    1, 21, \ ;type 0
-    0,  0, \ ;type 1
-    5, 20, \ ;type 2
-    5,  ?, \ ;type 3 {set by skin}
-    5,  ?    ;type 4 {set by skin}
-endg
-
-;uglobal
-  ; NOTE: commented out since doesn't provide necessary functionality anyway,
-  ;       to be reworked
-; new_window_starting       dd ?
-;endg
-
-align 4
-;------------------------------------------------------------------------------
-window._.invalidate_screen: ;//////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> eax = old (original) window box
-;> ebx = new (final) window box
-;> edi = pointer to WDATA struct
-;------------------------------------------------------------------------------
-        push    eax ebx
-
-        ; TODO: do we really need `draw_limits`?
-        mov     ecx, [eax + BOX.left]
-        mov     edx, [ebx + BOX.left]
-        cmp     ecx, edx
-        jle     @f
-        xchg    ecx, edx
-    @@: mov     [draw_limits.left], ecx
-        mov     ecx, [eax + BOX.width]
-        cmp     ecx, [ebx + BOX.width]
-        jae     @f
-        mov     ecx, [ebx + BOX.width]
-    @@: add     ecx, edx
-        mov     [draw_limits.right], ecx
-        mov     ecx, [eax + BOX.top]
-        mov     edx, [ebx + BOX.top]
-        cmp     ecx, edx
-        jle     @f
-        xchg    ecx, edx
-    @@: mov     [draw_limits.top], ecx
-        mov     ecx, [eax + BOX.height]
-        cmp     ecx, [ebx + BOX.height]
-        jae     @f
-        mov     ecx, [ebx + BOX.height]
-    @@: add     ecx, edx
-        mov     [draw_limits.bottom], ecx
-
-        ; recalculate screen buffer at old position
-        push    ebx
-        mov     edx, [eax + BOX.height]
-        mov     ecx, [eax + BOX.width]
-        mov     ebx, [eax + BOX.top]
-        mov     eax, [eax + BOX.left]
-        add     ecx, eax
-        add     edx, ebx
-        call    calculatescreen
-        pop     eax
-
-        ; recalculate screen buffer at new position
-        mov     edx, [eax + BOX.height]
-        mov     ecx, [eax + BOX.width]
-        mov     ebx, [eax + BOX.top]
-        mov     eax, [eax + BOX.left]
-        add     ecx, eax
-        add     edx, ebx
-        call    calculatescreen
-
-        mov     eax, edi
-        call    redrawscreen
-
-        ; tell window to redraw itself
-        mov     [edi + WDATA.fl_redraw], 1
-
-        pop     ebx eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.set_window_box: ;/////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> eax = pointer to BOX struct
-;> bl = new window state flags
-;> edi = pointer to WDATA struct
-;------------------------------------------------------------------------------
-        push    eax ebx esi
-
-; don't do anything if the new box is identical to the old
-	cmp	bl, [edi + WDATA.fl_wstate]
-	jnz	@f
-	mov	esi, eax
-	push	edi
-if WDATA.box
-	add	edi, WDATA.box
-end if
-	mov	ecx, 4
-	repz	cmpsd
-	pop	edi
-	jz	.exit
-@@:
-
-        add     esp, -BOX.sizeof
-
-        mov     ebx, esp
-if WDATA.box
-        lea     esi, [edi + WDATA.box]
-else
-	mov	esi, edi ; optimization for WDATA.box = 0
-end if
-        xchg    eax, esi
-        mov     ecx, BOX.sizeof
-        call    memmove
-        xchg    eax, esi
-        xchg    ebx, esi
-        call    memmove
-        mov     eax, ebx
-        mov     ebx, esi
-
-        call    window._.check_window_position
-        call    window._.set_window_clientbox
-        call    window._.invalidate_screen
-
-        add     esp, BOX.sizeof
-
-        mov     cl, [esp + 4]
-        mov     ch, cl
-        xchg    cl, [edi + WDATA.fl_wstate]
-
-        or      cl, ch
-        test    cl, WSTATE_MAXIMIZED
-        jnz     .exit
-
-        mov     eax, edi
-        sub     eax, window_data
-        shl     eax, 3
-        add     eax, SLOT_BASE
-
-        lea     ebx, [edi + WDATA.box]
-        xchg    esp, ebx
-
-        pop     [eax + APPDATA.saved_box.left] \
-                [eax + APPDATA.saved_box.top] \
-                [eax + APPDATA.saved_box.width] \
-                edx
-
-        xchg    esp, ebx
-
-        test    ch, WSTATE_ROLLEDUP
-        jnz     .exit
-
-        mov     [eax + APPDATA.saved_box.height], edx
-
-  .exit:
-        pop     esi ebx eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.set_window_clientbox: ;///////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> edi = pointer to WDATA struct
-;------------------------------------------------------------------------------
-        push    eax ecx edi
-
-        mov     eax, [_skinh]
-        mov     [window_topleft + 8 * 3 + 4], eax
-        mov     [window_topleft + 8 * 4 + 4], eax
-
-        mov     ecx, edi
-        sub     edi, window_data
-        shl     edi, 3
-        test    [ecx + WDATA.fl_wstyle], WSTYLE_CLIENTRELATIVE
-        jz      .whole_window
-
-        movzx   eax, [ecx + WDATA.fl_wstyle]
-        and     eax, 0x0F
-        mov     eax, [eax * 8 + window_topleft + 0]
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax
-        shl     eax, 1
-        neg     eax
-        add     eax, [ecx + WDATA.box.width]
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax
-
-        movzx   eax, [ecx + WDATA.fl_wstyle]
-        and     eax, 0x0F
-        push    [eax * 8 + window_topleft + 0]
-        mov     eax, [eax * 8 + window_topleft + 4]
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax
-        neg     eax
-        sub     eax, [esp]
-        add     eax, [ecx + WDATA.box.height]
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax
-        add     esp, 4
-        jmp     .exit
-
-  .whole_window:
-        xor     eax, eax
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax
-        mov     eax, [ecx + WDATA.box.width]
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax
-        mov     eax, [ecx + WDATA.box.height]
-        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax
-
-  .exit:
-        pop     edi ecx eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.sys_set_window: ;/////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;< edx = pointer to WDATA struct
-;------------------------------------------------------------------------------
-        mov     eax, [CURRENT_TASK]
-        shl     eax, 5
-        add     eax, window_data
-
-        ; save window colors
-        mov     [eax + WDATA.cl_workarea], edx
-        mov     [eax + WDATA.cl_titlebar], esi
-        mov     [eax + WDATA.cl_frames], edi
-
-        mov     edi, eax
-
-        ; was it already defined before?
-        test    [edi + WDATA.fl_wdrawn], 1
-        jnz     .set_client_box
-
-        ; NOTE: commented out since doesn't provide necessary functionality
-        ;       anyway, to be reworked
-;       mov     eax, [timer_ticks] ; [0xfdf0]
-;       add     eax, 100
-;       mov     [new_window_starting], eax
-
-        ; no it wasn't, performing initial window definition
-        movzx   eax, bx
-        mov     [edi + WDATA.box.width], eax
-        movzx   eax, cx
-        mov     [edi + WDATA.box.height], eax
-        sar     ebx, 16
-        sar     ecx, 16
-        mov     [edi + WDATA.box.left], ebx
-        mov     [edi + WDATA.box.top], ecx
-
-        call    window._.check_window_position
-
-        push    ecx edi
-
-        mov     cl, [edi + WDATA.fl_wstyle]
-        mov     eax, [edi + WDATA.cl_frames]
-
-        sub     edi, window_data
-        shl     edi, 3
-        add     edi, SLOT_BASE
-
-        and     cl, 0x0F
-        cmp     cl, 3
-        je      @f
-        cmp     cl, 4
-        je      @f
-
-        xor     eax, eax
-
-    @@: mov     [edi + APPDATA.wnd_caption], eax
-
-        mov     esi, [esp]
-        add     edi, APPDATA.saved_box
-        movsd
-        movsd
-        movsd
-        movsd
-
-        pop     edi ecx
-
-        mov     esi, [CURRENT_TASK]
-        movzx   esi, word[WIN_STACK + esi * 2]
-        lea     esi, [WIN_POS + esi * 2]
-        call    waredraw
-
-        mov     eax, [edi + WDATA.box.left]
-        mov     ebx, [edi + WDATA.box.top]
-        mov     ecx, [edi + WDATA.box.width]
-        mov     edx, [edi + WDATA.box.height]
-        add     ecx, eax
-        add     edx, ebx
-        call    calculatescreen
-
-        mov     byte[KEY_COUNT], 0           ; empty keyboard buffer
-        mov     byte[BTN_COUNT], 0           ; empty button buffer
-
-  .set_client_box:
-        ; update window client box coordinates
-        call    window._.set_window_clientbox
-
-        ; reset window redraw flag and exit
-        mov     [edi + WDATA.fl_redraw], 0
-        mov     edx, edi
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.check_window_position: ;//////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Check if window is inside screen area
-;------------------------------------------------------------------------------
-;> edi = pointer to WDATA
-;------------------------------------------------------------------------------
-        push    eax ebx ecx edx esi
-
-        mov     eax, [edi + WDATA.box.left]
-        mov     ebx, [edi + WDATA.box.top]
-        mov     ecx, [edi + WDATA.box.width]
-        mov     edx, [edi + WDATA.box.height]
-
-        mov     esi, [Screen_Max_X]
-        cmp     ecx, esi
-        ja      .fix_width_high
-
-  .check_left:
-        or      eax, eax
-        jl      .fix_left_low
-        add     eax, ecx
-        cmp     eax, esi
-        jg      .fix_left_high
-
-  .check_height:
-        mov     esi, [Screen_Max_Y]
-        cmp     edx, esi
-        ja      .fix_height_high
-
-  .check_top:
-        or      ebx, ebx
-        jl      .fix_top_low
-        add     ebx, edx
-        cmp     ebx, esi
-        jg      .fix_top_high
-
-  .exit:
-        pop     esi edx ecx ebx eax
-        ret
-
-  .fix_width_high:
-        mov     ecx, esi
-        mov     [edi + WDATA.box.width], esi
-        jmp     .check_left
-
-  .fix_left_low:
-        xor     eax, eax
-        mov     [edi + WDATA.box.left], eax
-        jmp     .check_height
-
-  .fix_left_high:
-        mov     eax, esi
-        sub     eax, ecx
-        mov     [edi + WDATA.box.left], eax
-        jmp     .check_height
-
-  .fix_height_high:
-        mov     edx, esi
-        mov     [edi + WDATA.box.height], esi
-        jmp     .check_top
-
-  .fix_top_low:
-        xor     ebx, ebx
-        mov     [edi + WDATA.box.top], ebx
-        jmp     .exit
-
-  .fix_top_high:
-        mov     ebx, esi
-        sub     ebx, edx
-        mov     [edi + WDATA.box.top], ebx
-        jmp     .exit
-
-align 4
-;------------------------------------------------------------------------------
-window._.get_titlebar_height: ;////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> edi = pointer to WDATA
-;------------------------------------------------------------------------------
-        mov     al, [edi + WDATA.fl_wstyle]
-        and     al, 0x0f
-        cmp     al, 0x03
-        jne     @f
-        mov     eax, [_skinh]
-        ret
-    @@: mov     eax, 21
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.get_rolledup_height: ;////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-;> edi = pointer to WDATA
-;------------------------------------------------------------------------------
-        mov     al, [edi + WDATA.fl_wstyle]
-        and     al, 0x0f
-        cmp     al, 0x03
-        jb      @f
-        mov     eax, [_skinh]
-        add     eax, 3
-        ret
-    @@: or      al, al
-        jnz     @f
-        mov     eax, 21
-        ret
-    @@: mov     eax, 21 + 2
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.set_screen: ;/////////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Reserve window area in screen buffer
-;------------------------------------------------------------------------------
-;> eax = left
-;> ebx = top
-;> ecx = right
-;> edx = bottom
-;> esi = process number
-;------------------------------------------------------------------------------
-virtual at esp
-  ff_x     dd ?
-  ff_y     dd ?
-  ff_width dd ?
-  ff_xsz   dd ?
-  ff_ysz   dd ?
-  ff_scale dd ?
-end virtual
-
-        pushad
-
-        cmp     esi, 1
-        jz      .check_for_shaped_window
-        mov     edi, esi
-        shl     edi, 5
-        cmp     [window_data + edi + WDATA.box.width], 0
-        jnz     .check_for_shaped_window
-        cmp     [window_data + edi + WDATA.box.height], 0
-        jz      .exit
-
-  .check_for_shaped_window:
-        mov     edi, esi
-        shl     edi, 8
-        add     edi, SLOT_BASE
-        cmp     [edi + APPDATA.wnd_shape], 0
-        jne     .shaped_window
-
-        ; get x&y size
-        sub     ecx, eax
-        sub     edx, ebx
-        inc     ecx
-        inc     edx
-
-        ; get WinMap start
-        push    esi
-        mov     edi, [Screen_Max_X]
-        inc     edi
-        mov     esi, edi
-        imul    edi, ebx
-        add     edi, eax
-        add     edi, [_WinMapAddress]
-        pop     eax
-        mov     ah, al
-        push    ax
-        shl     eax, 16
-        pop     ax
-
-  .next_line:
-        push    ecx
-        shr     ecx, 2
-        rep     stosd
-        mov     ecx, [esp]
-        and     ecx, 3
-        rep     stosb
-        pop     ecx
-        add     edi, esi
-        sub     edi, ecx
-        dec     edx
-        jnz     .next_line
-
-        jmp     .exit
-
-  .shaped_window:
-        ;  for (y=0; y <= x_size; y++)
-        ;      for (x=0; x <= x_size; x++)
-        ;          if (shape[coord(x,y,scale)]==1)
-        ;             set_pixel(x, y, process_number);
-
-        sub     ecx, eax
-        sub     edx, ebx
-        inc     ecx
-        inc     edx
-
-        push    [edi + APPDATA.wnd_shape_scale]  ; push scale first -> for loop
-
-        ; get WinMap start  -> ebp
-        push    eax
-        mov     eax, [Screen_Max_X] ; screen_sx
-        inc     eax
-        imul    eax, ebx
-        add     eax, [esp]
-        add     eax, [_WinMapAddress]
-        mov     ebp, eax
-
-        mov     edi, [edi + APPDATA.wnd_shape]
-        pop     eax
-
-        ; eax = x_start
-        ; ebx = y_start
-        ; ecx = x_size
-        ; edx = y_size
-        ; esi = process_number
-        ; edi = &shape
-        ;       [scale]
-        push    edx ecx ; for loop - x,y size
-
-        mov     ecx, esi
-        shl     ecx, 5
-        mov     edx, [window_data + ecx + WDATA.box.top]
-        push    [window_data + ecx + WDATA.box.width]           ; for loop - width
-        mov     ecx, [window_data + ecx + WDATA.box.left]
-        sub     ebx, edx
-        sub     eax, ecx
-        push    ebx eax ; for loop - x,y
-
-        add     [ff_xsz], eax
-        add     [ff_ysz], ebx
-
-        mov     ebx, [ff_y]
-
-  .ff_new_y:
-        mov     edx, [ff_x]
-
-  .ff_new_x:
-        ; -- body --
-        mov     ecx, [ff_scale]
-        mov     eax, [ff_width]
-        inc     eax
-        shr     eax, cl
-        push    ebx edx
-        shr     ebx, cl
-        shr     edx, cl
-        imul    eax, ebx
-        add     eax, edx
-        pop     edx ebx
-        add     eax, edi
-        call    .read_byte
-        test    al,al
-        jz      @f
-        mov     eax, esi
-        mov     [ebp], al
-        ; -- end body --
-    @@: inc     ebp
-        inc     edx
-        cmp     edx, [ff_xsz]
-        jb      .ff_new_x
-
-        sub     ebp, [ff_xsz]
-        add     ebp, [ff_x]
-        add     ebp, [Screen_Max_X]  ; screen.x
-        inc     ebp
-        inc     ebx
-        cmp     ebx, [ff_ysz]
-        jb      .ff_new_y
-
-        add     esp, 24
-
-  .exit:
-        popad
-        ret
-
-  .read_byte:
-        ; eax - address
-        ; esi - slot
-        push    eax ecx edx esi
-        xchg    eax, esi
-        lea     ecx, [esp + 12]
-        mov     edx, 1
-        call    read_process_memory
-        pop     esi edx ecx eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.window_activate: ;////////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Activate window
-;------------------------------------------------------------------------------
-;> esi = pointer to WIN_POS+ window data
-;------------------------------------------------------------------------------
-        push    eax ebx
-
-        ; if type of current active window is 3 or 4, it must be redrawn
-        mov     ebx, [TASK_COUNT]
-        movzx   ebx, word[WIN_POS + ebx * 2]
-        shl     ebx, 5
-        add     eax, window_data
-        mov     al, [window_data + ebx + WDATA.fl_wstyle]
-        and     al, 0x0f
-        cmp     al, 0x03
-        je      .set_window_redraw_flag
-        cmp     al, 0x04
-        jne     .move_others_down
-
-  .set_window_redraw_flag:
-        mov     [window_data + ebx + WDATA.fl_redraw], 1
-
-  .move_others_down:
-        ; ax <- process no
-        movzx   ebx, word[esi]
-        ; ax <- position in window stack
-        movzx   ebx, word[WIN_STACK + ebx * 2]
-
-        ; drop others
-        xor     eax, eax
-
-  .next_stack_window:
-        cmp     eax, [TASK_COUNT]
-        jae     .move_self_up
-        inc     eax
-        cmp     [WIN_STACK + eax * 2], bx
-        jbe     .next_stack_window
-        dec     word[WIN_STACK + eax * 2]
-        jmp     .next_stack_window
-
-  .move_self_up:
-        movzx   ebx, word[esi]
-        ; number of processes
-        mov     ax, [TASK_COUNT]
-        ; this is the last (and the upper)
-        mov     [WIN_STACK + ebx * 2], ax
-
-        ; update on screen - window stack
-        xor     eax, eax
-
-  .next_window_pos:
-        cmp     eax, [TASK_COUNT]
-        jae     .reset_vars
-        inc     eax
-        movzx   ebx, word[WIN_STACK + eax * 2]
-        mov     [WIN_POS + ebx * 2], ax
-        jmp     .next_window_pos
-
-  .reset_vars:
-        mov     byte[KEY_COUNT], 0
-        mov     byte[BTN_COUNT], 0
-        mov     word[MOUSE_SCROLL_H], 0
-        mov     word[MOUSE_SCROLL_V], 0
-
-        pop     ebx eax
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.check_window_draw: ;//////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Check if window is necessary to draw
-;------------------------------------------------------------------------------
-;> edi = pointer to WDATA
-;------------------------------------------------------------------------------
-        mov     cl, [edi + WDATA.fl_wstyle]
-        and     cl, 0x0f
-        cmp     cl, 3
-        je      .exit.redraw      ; window type 3
-        cmp     cl, 4
-        je      .exit.redraw      ; window type 4
-
-        push    eax ebx edx esi
-
-        mov     eax, edi
-        sub     eax, window_data
-        shr     eax, 5
-
-        movzx   eax, word[WIN_STACK + eax * 2]  ; get value of the curr process
-        lea     esi, [WIN_POS + eax * 2]        ; get address of this process at 0xC400
-
-  .next_window:
-        add     esi, 2
-
-        mov     eax, [TASK_COUNT]
-        lea     eax, word[WIN_POS + eax * 2] ; number of the upper window
-
-        cmp     esi, eax
-        ja      .exit.no_redraw
-
-        movzx   edx, word[esi]
-        shl     edx, 5
-        cmp     [CURRENT_TASK + edx + TASKDATA.state], TSTATE_FREE
-        je      .next_window
-
-        mov     eax, [edi + WDATA.box.top]
-        mov     ebx, [edi + WDATA.box.height]
-        add     ebx, eax
-
-        mov     ecx, [window_data + edx + WDATA.box.top]
-        cmp     ecx, ebx
-        jge     .next_window
-        add     ecx, [window_data + edx + WDATA.box.height]
-        cmp     eax, ecx
-        jge     .next_window
-
-        mov     eax, [edi + WDATA.box.left]
-        mov     ebx, [edi + WDATA.box.width]
-        add     ebx, eax
-
-        mov     ecx, [window_data + edx + WDATA.box.left]
-        cmp     ecx, ebx
-        jge     .next_window
-        add     ecx, [window_data + edx + WDATA.box.width]
-        cmp     eax, ecx
-        jge     .next_window
-
-        pop     esi edx ebx eax
-
-  .exit.redraw:
-        xor     ecx, ecx
-        inc     ecx
-        ret
-
-  .exit.no_redraw:
-        pop     esi edx ebx eax
-        xor     ecx, ecx
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.draw_window_caption: ;////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? <description>
-;------------------------------------------------------------------------------
-        inc     [mouse_pause]
-        call    [_display.disable_mouse]
-
-        xor     eax, eax
-        mov     edx, [TASK_COUNT]
-        movzx   edx, word[WIN_POS + edx * 2]
-        cmp     edx, [CURRENT_TASK]
-        jne     @f
-        inc     eax
-    @@: mov     edx, [CURRENT_TASK]
-        shl     edx, 5
-        add     edx, window_data
-        movzx   ebx, [edx + WDATA.fl_wstyle]
-        and     bl, 0x0F
-        cmp     bl, 3
-        je      .draw_caption_style_3
-        cmp     bl, 4
-        je      .draw_caption_style_3
-
-        jmp     .not_style_3
-
-  .draw_caption_style_3:
-        push    edx
-        call    drawwindow_IV_caption
-        add     esp, 4
-        jmp     .2
-
-  .not_style_3:
-        cmp     bl, 2
-        jne     .not_style_2
-
-        call    drawwindow_III_caption
-        jmp     .2
-
-  .not_style_2:
-        cmp     bl, 0
-        jne     .2
-
-        call    drawwindow_I_caption
-
-  .2:   mov     edi, [CURRENT_TASK]
-        shl     edi, 5
-        test    [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION
-        jz      .exit
-        mov     edx, [edi * 8 + SLOT_BASE + APPDATA.wnd_caption]
-        or      edx, edx
-        jz      .exit
-
-        movzx   eax, [edi + window_data + WDATA.fl_wstyle]
-        and     al, 0x0F
-        cmp     al, 3
-        je      .skinned
-        cmp     al, 4
-        je      .skinned
-
-        jmp     .not_skinned
-
-  .skinned:
-        mov     ebp, [edi + window_data + WDATA.box.left - 2]
-        mov     bp, word[edi + window_data + WDATA.box.top]
-        movzx   eax, word[edi + window_data + WDATA.box.width]
-        sub     ax, [_skinmargins.left]
-        sub     ax, [_skinmargins.right]
-        push    edx
-        cwde
-        cdq
-        mov     ebx, 6
-        idiv    ebx
-        pop     edx
-        or      eax, eax
-        js      .exit
-
-        mov     esi, eax
-        mov     ebx, dword[_skinmargins.left - 2]
-        mov     bx, word[_skinh]
-        sub     bx, [_skinmargins.bottom]
-        sub     bx, [_skinmargins.top]
-        sar     bx, 1
-        adc     bx, 0
-        add     bx, [_skinmargins.top]
-        add     bx, -3
-        add     ebx, ebp
-        jmp     .dodraw
-
-  .not_skinned:
-        cmp     al, 1
-        je      .exit
-
-        mov     ebp, [edi + window_data + WDATA.box.left - 2]
-        mov     bp, word[edi + window_data + WDATA.box.top]
-        movzx   eax, word[edi + window_data + WDATA.box.width]
-        sub     eax, 16
-        push    edx
-        cwde
-        cdq
-        mov     ebx, 6
-        idiv    ebx
-        pop     edx
-        or      eax, eax
-        js      .exit
-
-        mov     esi, eax
-        mov     ebx, 0x00080007
-        add     ebx, ebp
-
-  .dodraw:
-        mov     ecx, [common_colours + 16]
-        or      ecx, 0x80000000
-        xor     edi, edi
-        call    dtext_asciiz_esi
-
-  .exit:
-        dec     [mouse_pause]
-        call    [draw_pointer]
-        ret
-
-align 4
-;------------------------------------------------------------------------------
-window._.draw_negative_box: ;//////////////////////////////////////////////////
-;------------------------------------------------------------------------------
-;? Draw negative box
-;------------------------------------------------------------------------------
-;> edi = pointer to BOX struct
-;------------------------------------------------------------------------------
-        push    eax ebx esi
-        mov     eax, [edi + BOX.left - 2]
-        mov     ax, word[edi + BOX.left]
-        add     ax, word[edi + BOX.width]
-        mov     ebx, [edi + BOX.top - 2]
-        mov     bx, word[edi + BOX.top]
-        add     bx, word[edi + BOX.height]
-        mov     esi, 0x01000000
-        call    draw_rectangle.forced
-        pop     esi ebx eax
-        ret
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                              ;;
+;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
+;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa      ;;
+;; Distributed under terms of the GNU General Public License    ;;
+;;                                                              ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+$Revision$
+
+;==============================================================================
+;///// public functions ///////////////////////////////////////////////////////
+;==============================================================================
+
+window.BORDER_SIZE = 5
+
+macro FuncTable name, table_name, [label]
+{
+  common
+    align 4
+    \label name#.#table_name dword
+  forward
+    dd name#.#label
+  common
+    name#.sizeof.#table_name = $ - name#.#table_name
+}
+
+uglobal
+  common_colours rd 32
+  draw_limits    RECT
+endg
+
+align 4
+;------------------------------------------------------------------------------
+syscall_draw_window: ;///// system function 0 /////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        mov     eax, edx
+        shr     eax, 24
+        and     al, 0x0f
+        cmp     al, 5
+        jae     .exit
+
+        push    eax
+        inc     [mouse_pause]
+        call    [_display.disable_mouse]
+        call    window._.sys_set_window
+        call    [_display.disable_mouse]
+        pop     eax
+
+        or      al, al
+        jnz     @f
+
+        ; type I - original style
+        call    drawwindow_I
+        jmp     window._.draw_window_caption.2
+
+    @@: dec     al
+        jnz     @f
+
+        ; type II - only reserve area, no draw
+        call    sys_window_mouse
+        dec     [mouse_pause]
+        call    [draw_pointer]
+        jmp     .exit
+
+    @@: dec     al
+        jnz     @f
+
+        ; type III  - new style
+        call    drawwindow_III
+        jmp     window._.draw_window_caption.2
+
+        ; type IV & V - skinned window (resizable & not)
+    @@: mov     eax, [TASK_COUNT]
+        movzx   eax, word[WIN_POS + eax * 2]
+        cmp     eax, [CURRENT_TASK]
+        setz    al
+        movzx   eax, al
+        push    eax
+        call    drawwindow_IV
+        jmp     window._.draw_window_caption.2
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+syscall_display_settings: ;///// system function 48 ///////////////////////////
+;------------------------------------------------------------------------------
+;; Redraw screen:
+;< ebx = 0
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Set button style:
+;< ebx = 1
+;< ecx = 0 (flat) or 1 (with gradient)
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Set system color palette:
+;< ebx = 2
+;< ecx = pointer to color table
+;< edx = size of color table
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Get system color palette:
+;< ebx = 3
+;< ecx = pointer to color table buffer
+;< edx = size of color table buffer
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Get skinned caption height:
+;< ebx = 4
+;> eax = height in pixels
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Get screen working area:
+;< ebx = 5
+;> eax = pack[16(left), 16(right)]
+;> ebx = pack[16(top), 16(bottom)]
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Set screen working area:
+;< ebx = 6
+;< ecx = pack[16(left), 16(right)]
+;< edx = pack[16(top), 16(bottom)]
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Get skin margins:
+;< ebx = 7
+;> eax = pack[16(left), 16(right)]
+;> ebx = pack[16(top), 16(bottom)]
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Set skin:
+;< ebx = 8
+;< ecx = pointer to FileInfoBlock struct
+;> eax = FS error code
+;------------------------------------------------------------------------------
+        cmp     ebx, .sizeof.ftable / 4
+        ja      @f
+        jmp     [.ftable + ebx * 4]
+    @@: ret
+
+
+align 4
+syscall_display_settings.00:
+        xor     eax, eax
+        inc     ebx
+        cmp     [windowtypechanged], ebx
+        jne     .exit
+        mov     [windowtypechanged], eax
+
+        jmp     syscall_display_settings._.redraw_whole_screen
+
+  .exit:
+        ret
+
+align 4
+syscall_display_settings.01:
+        and     ecx, 1
+        cmp     ecx, [buttontype]
+        je      .exit
+        mov     [buttontype], ecx
+        mov     [windowtypechanged], ebx
+
+  .exit:
+        ret
+
+align 4
+syscall_display_settings.02:
+        dec     ebx
+        mov     esi, ecx
+        and     edx, 127
+        mov     edi, common_colours
+        mov     ecx, edx
+        rep     movsb
+        mov     [windowtypechanged], ebx
+        ret
+
+align 4
+syscall_display_settings.03:
+        mov     edi, ecx
+        and     edx, 127
+        mov     esi, common_colours
+        mov     ecx, edx
+        rep     movsb
+        ret
+
+align 4
+syscall_display_settings.04:
+        mov     eax, [_skinh]
+        mov     [esp + 32], eax
+        ret
+
+align 4
+syscall_display_settings.05:
+        mov     eax, [screen_workarea.left - 2]
+        mov     ax, word[screen_workarea.right]
+        mov     [esp + 32], eax
+        mov     eax, [screen_workarea.top - 2]
+        mov     ax, word[screen_workarea.bottom]
+        mov     [esp + 20], eax
+        ret
+
+align 4
+syscall_display_settings.06:
+        xor     esi, esi
+
+        mov     edi, [Screen_Max_X]
+        mov     eax, ecx
+        movsx   ebx, ax
+        sar     eax, 16
+        cmp     eax, ebx
+        jge     .check_horizontal
+        inc     esi
+        or      eax, eax
+        jge     @f
+        xor     eax, eax
+    @@: mov     [screen_workarea.left], eax
+        cmp     ebx, edi
+        jle     @f
+        mov     ebx, edi
+    @@: mov     [screen_workarea.right], ebx
+
+  .check_horizontal:
+        mov     edi, [Screen_Max_Y]
+        mov     eax, edx
+        movsx   ebx, ax
+        sar     eax, 16
+        cmp     eax, ebx
+        jge     .check_if_redraw_needed
+        inc     esi
+        or      eax, eax
+        jge     @f
+        xor     eax, eax
+    @@: mov     [screen_workarea.top], eax
+        cmp     ebx, edi
+        jle     @f
+        mov     ebx, edi
+    @@: mov     [screen_workarea.bottom], ebx
+
+  .check_if_redraw_needed:
+        or      esi, esi
+        jz      .exit
+
+        call    repos_windows
+        jmp     syscall_display_settings._.calculate_whole_screen
+
+  .exit:
+        ret
+
+align 4
+syscall_display_settings.07:
+        mov     eax, [_skinmargins + 0]
+        mov     [esp + 32], eax
+        mov     eax, [_skinmargins + 4]
+        mov     [esp + 20], eax
+        ret
+
+align 4
+syscall_display_settings.08:
+        mov     ebx, ecx
+        call    read_skin_file
+        mov     [esp + 32], eax
+        test    eax, eax
+        jnz     .exit
+
+        call    syscall_display_settings._.calculate_whole_screen
+        jmp     syscall_display_settings._.redraw_whole_screen
+
+  .exit:
+        ret
+
+syscall_display_settings._.calculate_whole_screen:
+        xor     eax, eax
+        xor     ebx, ebx
+        mov     ecx, [Screen_Max_X]
+        mov     edx, [Screen_Max_Y]
+        jmp     calculatescreen
+
+syscall_display_settings._.redraw_whole_screen:
+        xor     eax, eax
+        mov     [draw_limits.left], eax
+        mov     [draw_limits.top], eax
+        mov     eax, [Screen_Max_X]
+        mov     [draw_limits.right], eax
+        mov     eax, [Screen_Max_Y]
+        mov     [draw_limits.bottom], eax
+        mov     eax, window_data
+        jmp     redrawscreen
+
+align 4
+;------------------------------------------------------------------------------
+syscall_set_window_shape: ;///// system function 50 ///////////////////////////
+;------------------------------------------------------------------------------
+;; Set window shape address:
+;> ebx = 0
+;> ecx = shape data address
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;; Set window shape scale:
+;> ebx = 1
+;> ecx = scale power (resulting scale is 2^ebx)
+;------------------------------------------------------------------------------
+        mov     edi, [current_slot]
+
+        test    ebx, ebx
+        jne     .shape_scale
+        mov     [edi + APPDATA.wnd_shape], ecx
+
+  .shape_scale:
+        dec     ebx
+        jnz     .exit
+        mov     [edi + APPDATA.wnd_shape_scale], ecx
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+syscall_move_window: ;///// system function 67 ////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        mov     edi, [CURRENT_TASK]
+        shl     edi, 5
+        add     edi, window_data
+
+        test    [edi + WDATA.fl_wdrawn], 1
+        jz      .exit
+
+        test    [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
+        jnz     .exit
+
+        cmp     ebx, -1
+        jne     @f
+        mov     ebx, [edi + WDATA.box.left]
+    @@: cmp     ecx, -1
+        jne     @f
+        mov     ecx, [edi + WDATA.box.top]
+    @@: cmp     edx, -1
+        jne     @f
+        mov     edx, [edi + WDATA.box.width]
+    @@: cmp     esi, -1
+        jne     @f
+        mov     esi, [edi + WDATA.box.height]
+
+    @@: push    esi edx ecx ebx
+        mov     eax, esp
+        mov     bl, [edi + WDATA.fl_wstate]
+        call    window._.set_window_box
+        add     esp, BOX.sizeof
+
+        ; NOTE: do we really need this? to be reworked
+;       mov     byte[DONT_DRAW_MOUSE], 0 ; mouse pointer
+;       mov     byte[MOUSE_BACKGROUND], 0 ; no mouse under
+;       mov     byte[MOUSE_DOWN], 0 ; react to mouse up/down
+
+        ; NOTE: do we really need this? to be reworked
+;       call    [draw_pointer]
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+syscall_window_settings: ;///// system function 71 /////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        dec     ebx     ; subfunction #1 - set window caption
+        jnz     .exit_fail
+
+        ; NOTE: only window owner thread can set its caption,
+        ;       so there's no parameter for PID/TID
+
+        mov     edi, [CURRENT_TASK]
+        shl     edi, 5
+
+        mov     [edi * 8 + SLOT_BASE + APPDATA.wnd_caption], ecx
+        or      [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION
+
+        call    window._.draw_window_caption
+
+        xor     eax, eax ; eax = 0 (success)
+        ret
+
+;  .get_window_caption:
+;        dec     eax     ; subfunction #2 - get window caption
+;        jnz     .exit_fail
+
+        ; not implemented yet
+
+  .exit_fail:
+        xor     eax, eax
+        inc     eax     ; eax = 1 (fail)
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+set_window_defaults: ;/////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        mov     byte [window_data + 0x20 + WDATA.cl_titlebar + 3], 1 ; desktop is not movable
+        push    eax ecx
+        xor     eax, eax
+        mov     ecx, WIN_STACK
+    @@: inc     eax
+        add     ecx, 2
+        ; process no
+        mov     [ecx + 0x000], ax
+        ; positions in stack
+        mov     [ecx + 0x400], ax
+        cmp     ecx, WIN_POS - 2
+        jne     @b
+        pop     ecx eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+calculatescreen: ;/////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Scan all windows from bottom to top, calling `setscreen` for each one
+;? intersecting given screen area
+;------------------------------------------------------------------------------
+;> eax = left
+;> ebx = top
+;> ecx = right
+;> edx = bottom
+;------------------------------------------------------------------------------
+        push    esi
+        pushfd
+        cli
+
+        mov     esi, 1
+        call    window._.set_screen
+
+        push    ebp
+
+        mov     ebp, [TASK_COUNT]
+        cmp     ebp, 1
+        jbe     .exit
+
+        push    edx ecx ebx eax
+
+  .next_window:
+        movzx   edi, word[WIN_POS + esi * 2]
+        shl     edi, 5
+
+        cmp     [CURRENT_TASK + edi + TASKDATA.state], TSTATE_FREE
+        je      .skip_window
+
+        add     edi, window_data
+        test    [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
+        jnz     .skip_window
+
+        mov     eax, [edi + WDATA.box.left]
+        cmp     eax, [esp + RECT.right]
+        jg      .skip_window
+        mov     ebx, [edi + WDATA.box.top]
+        cmp     ebx, [esp + RECT.bottom]
+        jg      .skip_window
+        mov     ecx, [edi + WDATA.box.width]
+        add     ecx, eax
+        cmp     ecx, [esp + RECT.left]
+        jl      .skip_window
+        mov     edx, [edi + WDATA.box.height]
+        add     edx, ebx
+        cmp     edx, [esp + RECT.top]
+        jl      .skip_window
+
+        cmp     eax, [esp + RECT.left]
+        jae     @f
+        mov     eax, [esp + RECT.left]
+    @@: cmp     ebx, [esp + RECT.top]
+        jae     @f
+        mov     ebx, [esp + RECT.top]
+    @@: cmp     ecx, [esp + RECT.right]
+        jbe     @f
+        mov     ecx, [esp + RECT.right]
+    @@: cmp     edx, [esp + RECT.bottom]
+        jbe     @f
+        mov     edx, [esp + RECT.bottom]
+
+    @@: push    esi
+        movzx   esi, word[WIN_POS + esi * 2]
+        call    window._.set_screen
+        pop     esi
+
+  .skip_window:
+        inc     esi
+        dec     ebp
+        jnz     .next_window
+
+        pop     eax ebx ecx edx
+
+  .exit:
+        pop     ebp
+        popfd
+        pop     esi
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+repos_windows: ;///////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        mov     ecx, [TASK_COUNT]
+        mov     edi, window_data + WDATA.sizeof * 2
+        call    force_redraw_background
+        dec     ecx
+        jle     .exit
+
+  .next_window:
+        mov     [edi + WDATA.fl_redraw], 1
+        test    [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
+        jnz     .fix_maximized
+
+        mov     eax, [edi + WDATA.box.left]
+        add     eax, [edi + WDATA.box.width]
+        mov     ebx, [Screen_Max_X]
+        cmp     eax, ebx
+        jle     .fix_vertical
+        mov     eax, [edi + WDATA.box.width]
+        sub     eax, ebx
+        jle     @f
+        mov     [edi + WDATA.box.width], ebx
+    @@: sub     ebx, [edi + WDATA.box.width]
+        mov     [edi + WDATA.box.left], ebx
+
+  .fix_vertical:
+        mov     eax, [edi + WDATA.box.top]
+        add     eax, [edi + WDATA.box.height]
+        mov     ebx, [Screen_Max_Y]
+        cmp     eax, ebx
+        jle     .fix_client_box
+        mov     eax, [edi + WDATA.box.height]
+        sub     eax, ebx
+        jle     @f
+        mov     [edi + WDATA.box.height], ebx
+    @@: sub     ebx, [edi + WDATA.box.height]
+        mov     [edi + WDATA.box.top], ebx
+        jmp     .fix_client_box
+
+  .fix_maximized:
+        mov     eax, [screen_workarea.left]
+        mov     [edi + WDATA.box.left], eax
+        sub     eax, [screen_workarea.right]
+        neg     eax
+        mov     [edi + WDATA.box.width], eax
+        mov     eax, [screen_workarea.top]
+        mov     [edi + WDATA.box.top], eax
+        test    [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
+        jnz     .fix_client_box
+        sub     eax, [screen_workarea.bottom]
+        neg     eax
+        mov     [edi + WDATA.box.height], eax
+
+  .fix_client_box:
+        call    window._.set_window_clientbox
+
+        add     edi, WDATA.sizeof
+        loop    .next_window
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+sys_window_mouse: ;////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        ; NOTE: commented out since doesn't provide necessary functionality
+        ;       anyway, to be reworked
+;       push    eax
+;
+;       mov     eax, [timer_ticks]
+;       cmp     [new_window_starting], eax
+;       jb      .exit
+;
+;       mov     byte[MOUSE_BACKGROUND], 0
+;       mov     byte[DONT_DRAW_MOUSE], 0
+;
+;       mov     [new_window_starting], eax
+;
+; .exit:
+;       pop     eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+draw_rectangle: ;//////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;> eax = pack[16(left), 16(right)]
+;> ebx = pack[16(top), 16(bottom)]
+;> esi = color
+;------------------------------------------------------------------------------
+        push    eax ebx ecx edi
+
+        xor     edi, edi
+
+  .flags_set:
+        push    ebx
+
+        ; set line color
+        mov     ecx, esi
+
+        ; draw top border
+        rol     ebx, 16
+        push    ebx
+        rol     ebx, 16
+        pop     bx
+        call    [draw_line]
+
+        ; draw bottom border
+        mov     ebx, [esp - 2]
+        pop     bx
+        call    [draw_line]
+
+        pop     ebx
+        add     ebx, 1 * 65536 - 1
+
+        ; draw left border
+        rol     eax, 16
+        push    eax
+        rol     eax, 16
+        pop     ax
+        call    [draw_line]
+
+        ; draw right border
+        mov     eax, [esp - 2]
+        pop     ax
+        call    [draw_line]
+
+        pop     edi ecx ebx eax
+        ret
+
+  .forced:
+        push    eax ebx ecx edi
+        xor     edi, edi
+        inc     edi
+        jmp     .flags_set
+
+align 4
+;------------------------------------------------------------------------------
+drawwindow_I_caption: ;////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        push    [edx + WDATA.cl_titlebar]
+        mov     esi, edx
+
+        mov     edx, [esi + WDATA.box.top]
+        mov     eax, edx
+        lea     ebx, [edx + 21]
+        inc     edx
+        add     eax, [esi + WDATA.box.height]
+
+        cmp     ebx, eax
+        jbe     @f
+        mov     ebx, eax
+    @@: push    ebx
+
+        xor     edi, edi
+
+  .next_line:
+        mov     ebx, edx
+        shl     ebx, 16
+        add     ebx, edx
+        mov     eax, [esi + WDATA.box.left]
+        inc     eax
+        shl     eax, 16
+        add     eax, [esi + WDATA.box.left]
+        add     eax, [esi + WDATA.box.width]
+        dec     eax
+        mov     ecx, [esi + WDATA.cl_titlebar]
+        test    ecx, 0x80000000
+        jz      @f
+        sub     ecx, 0x00040404
+        mov     [esi + WDATA.cl_titlebar], ecx
+    @@: and     ecx, 0x00ffffff
+        call    [draw_line]
+        inc     edx
+        cmp     edx, [esp]
+        jb      .next_line
+
+        add     esp, 4
+        pop     [esi + WDATA.cl_titlebar]
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+drawwindow_I: ;////////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        pushad
+
+        ; window border
+
+        mov     eax, [edx + WDATA.box.left - 2]
+        mov     ax, word[edx + WDATA.box.left]
+        add     ax, word[edx + WDATA.box.width]
+        mov     ebx, [edx + WDATA.box.top - 2]
+        mov     bx, word[edx + WDATA.box.top]
+        add     bx, word[edx + WDATA.box.height]
+
+        mov     esi, [edx + WDATA.cl_frames]
+        call    draw_rectangle
+
+        ; window caption
+
+        call    drawwindow_I_caption
+
+        ; window client area
+
+        ; do we need to draw it?
+        mov     edi, [esi + WDATA.cl_workarea]
+        test    edi, 0x40000000
+        jnz     .exit
+
+        ; does client area have a positive size on screen?
+        mov     edx, [esi + WDATA.box.top]
+        add     edx, 21 + 5
+        mov     ebx, [esi + WDATA.box.top]
+        add     ebx, [esi + WDATA.box.height]
+        cmp     edx, ebx
+        jg      .exit
+
+        ; okay, let's draw it
+        mov     eax, 1
+        mov     ebx, 21
+        mov     ecx, [esi + WDATA.box.width]
+        mov     edx, [esi + WDATA.box.height]
+        call    [drawbar]
+
+  .exit:
+        popad
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+drawwindow_III_caption: ;/////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        mov     ecx, [edx + WDATA.cl_titlebar]
+        push    ecx
+        mov     esi, edx
+        mov     edx, [esi + WDATA.box.top]
+        add     edx, 4
+        mov     ebx, [esi + WDATA.box.top]
+        add     ebx, 20
+        mov     eax, [esi + WDATA.box.top]
+        add     eax, [esi + WDATA.box.height]
+
+        cmp     ebx, eax
+        jb      @f
+        mov     ebx, eax
+    @@: push    ebx
+
+        xor     edi, edi
+
+  .next_line:
+        mov     ebx, edx
+        shl     ebx, 16
+        add     ebx, edx
+        mov     eax, [esi + WDATA.box.left]
+        shl     eax, 16
+        add     eax, [esi + WDATA.box.left]
+        add     eax, [esi + WDATA.box.width]
+        add     eax, 4 * 65536 - 4
+        mov     ecx, [esi + WDATA.cl_titlebar]
+        test    ecx, 0x40000000
+        jz      @f
+        add     ecx, 0x00040404
+    @@: test    ecx, 0x80000000
+        jz      @f
+        sub     ecx, 0x00040404
+    @@: mov     [esi + WDATA.cl_titlebar], ecx
+        and     ecx, 0x00ffffff
+        call    [draw_line]
+        inc     edx
+        cmp     edx, [esp]
+        jb      .next_line
+
+        add     esp, 4
+        pop     [esi + WDATA.cl_titlebar]
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+drawwindow_III: ;//////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        pushad
+
+        ; window border
+
+        mov     eax, [edx + WDATA.box.left - 2]
+        mov     ax, word[edx + WDATA.box.left]
+        add     ax, word[edx + WDATA.box.width]
+        mov     ebx, [edx + WDATA.box.top - 2]
+        mov     bx, word[edx + WDATA.box.top]
+        add     bx, word[edx + WDATA.box.height]
+
+        mov     esi, [edx + WDATA.cl_frames]
+        shr     esi, 1
+        and     esi, 0x007f7f7f
+        call    draw_rectangle
+
+        push    esi
+        mov     ecx, 3
+        mov     esi, [edx + WDATA.cl_frames]
+
+  .next_frame:
+        add     eax, 1 * 65536 - 1
+        add     ebx, 1 * 65536 - 1
+        call    draw_rectangle
+        dec     ecx
+        jnz     .next_frame
+
+        pop     esi
+        add     eax, 1 * 65536 - 1
+        add     ebx, 1 * 65536 - 1
+        call    draw_rectangle
+
+        ; window caption
+
+        call    drawwindow_III_caption
+
+        ; window client area
+
+        ; do we need to draw it?
+        mov     edi, [esi + WDATA.cl_workarea]
+        test    edi, 0x40000000
+        jnz     .exit
+
+        ; does client area have a positive size on screen?
+        mov     edx, [esi + WDATA.box.top]
+        add     edx, 21 + 5
+        mov     ebx, [esi + WDATA.box.top]
+        add     ebx, [esi + WDATA.box.height]
+        cmp     edx, ebx
+        jg      .exit
+
+        ; okay, let's draw it
+        mov     eax, 5
+        mov     ebx, 20
+        mov     ecx, [esi + WDATA.box.width]
+        mov     edx, [esi + WDATA.box.height]
+        sub     ecx, 4
+        sub     edx, 4
+        call    [drawbar]
+
+  .exit:
+        popad
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+waredraw: ;////////////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Activate window, redrawing if necessary
+;------------------------------------------------------------------------------
+        push    -1
+        mov     eax, [TASK_COUNT]
+        lea     eax, [WIN_POS + eax * 2]
+        cmp     eax, esi
+        pop     eax
+        je      .exit
+
+        ; is it overlapped by another window now?
+        push    ecx
+        call    window._.check_window_draw
+        test    ecx, ecx
+        pop     ecx
+        jz      .do_not_draw
+
+        ; yes it is, activate and update screen buffer
+        mov     byte[MOUSE_DOWN], 1
+        call    window._.window_activate
+
+        pushad
+        mov     edi, [TASK_COUNT]
+        movzx   esi, word[WIN_POS + edi * 2]
+        shl     esi, 5
+        add     esi, window_data
+
+        mov     eax, [esi + WDATA.box.left]
+        mov     ebx, [esi + WDATA.box.top]
+        mov     ecx, [esi + WDATA.box.width]
+        mov     edx, [esi + WDATA.box.height]
+
+        add     ecx, eax
+        add     edx, ebx
+
+        mov     edi, [TASK_COUNT]
+        movzx   esi, word[WIN_POS + edi * 2]
+        call    window._.set_screen
+        popad
+
+        ; tell application to redraw itself
+        mov     [edi + WDATA.fl_redraw], 1
+        xor     eax, eax
+        jmp     .exit
+
+  .do_not_draw:
+        ; no it's not, just activate the window
+        call    window._.window_activate
+        xor     eax, eax
+        mov     byte[MOUSE_BACKGROUND], al
+        mov     byte[DONT_DRAW_MOUSE], al
+
+
+  .exit:
+        mov     byte[MOUSE_DOWN], 0
+        inc     eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+minimize_window: ;/////////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;> eax = window number on screen
+;------------------------------------------------------------------------------
+;# corrupts [dl*]
+;------------------------------------------------------------------------------
+        push    edi
+        pushfd
+        cli
+
+        ; is it already minimized?
+        movzx   edi, word[WIN_POS + eax * 2]
+        shl     edi, 5
+        add     edi, window_data
+        test    [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
+        jnz     .exit
+
+        push    eax ebx ecx edx esi
+
+        ; no it's not, let's do that
+        or      [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
+        mov     eax, [edi + WDATA.box.left]
+        mov     [draw_limits.left], eax
+        mov     ecx, eax
+        add     ecx, [edi + WDATA.box.width]
+        mov     [draw_limits.right], ecx
+        mov     ebx, [edi + WDATA.box.top]
+        mov     [draw_limits.top], ebx
+        mov     edx, ebx
+        add     edx, [edi + WDATA.box.height]
+        mov     [draw_limits.bottom], edx
+        call    calculatescreen
+        xor     esi, esi
+        xor     eax, eax
+        call    redrawscreen
+
+        pop     esi edx ecx ebx eax
+
+  .exit:
+        popfd
+        pop     edi
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+restore_minimized_window: ;////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;> eax = window number on screen
+;------------------------------------------------------------------------------
+;# corrupts [dl*]
+;------------------------------------------------------------------------------
+        pushad
+        pushfd
+        cli
+
+        ; is it already restored?
+        movzx   esi, word[WIN_POS + eax * 2]
+        mov     edi, esi
+        shl     edi, 5
+        add     edi, window_data
+        test    [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
+        jz      .exit
+
+        ; no it's not, let's do that
+        mov     [edi + WDATA.fl_redraw], 1
+        and     [edi + WDATA.fl_wstate], not WSTATE_MINIMIZED
+        mov     ebp, window._.set_screen
+        cmp     eax, [TASK_COUNT]
+        jz      @f
+        mov     ebp, calculatescreen
+    @@: mov     eax, [edi + WDATA.box.left]
+        mov     ebx, [edi + WDATA.box.top]
+        mov     ecx, [edi + WDATA.box.width]
+        mov     edx, [edi + WDATA.box.height]
+        add     ecx, eax
+        add     edx, ebx
+        call    ebp
+
+        mov     byte[MOUSE_BACKGROUND], 0
+
+  .exit:
+        popfd
+        popad
+        ret
+
+align 4
+; TODO: remove this proc
+;------------------------------------------------------------------------------
+window_check_events: ;/////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        ; do we have window minimize/restore request?
+        cmp     [window_minimize], 0
+        je      .exit
+
+        ; okay, minimize or restore top-most window and exit
+        mov     eax, [TASK_COUNT]
+        mov     bl, 0
+        xchg    [window_minimize], bl
+        dec     bl
+        jnz     @f
+        call    minimize_window
+        jmp     .exit
+
+    @@: call    restore_minimized_window
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+sys_window_maximize_handler: ;/////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> esi = process slot
+;------------------------------------------------------------------------------
+        mov     edi, esi
+        shl     edi, 5
+        add     edi, window_data
+
+        ; can window change its height?
+        ; only types 2 and 3 can be resized
+        mov     dl, [edi + WDATA.fl_wstyle]
+        test    dl, 2
+        jz      .exit
+
+        ; toggle normal/maximized window state
+        mov     bl, [edi + WDATA.fl_wstate]
+        xor     bl, WSTATE_MAXIMIZED
+
+        ; calculate and set appropriate window bounds
+        test    bl, WSTATE_MAXIMIZED
+        jz      .restore_size
+
+        mov     eax, [screen_workarea.left]
+        mov     ecx, [screen_workarea.top]
+        push    [screen_workarea.bottom] \
+                [screen_workarea.right] \
+                ecx \
+                eax
+        sub     [esp + BOX.width], eax
+        sub     [esp + BOX.height], ecx
+        mov     eax, esp
+        jmp     .set_box
+
+  .restore_size:
+        mov     eax, esi
+        shl     eax, 8
+        add     eax, SLOT_BASE + APPDATA.saved_box
+        push    [eax + BOX.height] \
+                [eax + BOX.width] \
+                [eax + BOX.top] \
+                [eax + BOX.left]
+        mov     eax, esp
+
+  .set_box:
+        test    bl, WSTATE_ROLLEDUP
+        jz      @f
+
+        xchg    eax, ecx
+        call    window._.get_rolledup_height
+        mov     [ecx + BOX.height], eax
+        xchg    eax, ecx
+
+    @@: call    window._.set_window_box
+        add     esp, BOX.sizeof
+
+  .exit:
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+sys_window_rollup_handler: ;///////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> esi = process slot
+;------------------------------------------------------------------------------
+        mov     edx, esi
+        shl     edx, 8
+        add     edx, SLOT_BASE
+
+        ; toggle normal/rolled up window state
+        mov     bl, [edi + WDATA.fl_wstate]
+        xor     bl, WSTATE_ROLLEDUP
+
+        ; calculate and set appropriate window bounds
+        test    bl, WSTATE_ROLLEDUP
+        jz      .restore_size
+
+        call    window._.get_rolledup_height
+        push    eax \
+                [edi + WDATA.box.width] \
+                [edi + WDATA.box.top] \
+                [edi + WDATA.box.left]
+        mov     eax, esp
+        jmp     .set_box
+
+  .restore_size:
+        test    bl, WSTATE_MAXIMIZED
+        jnz     @f
+        add     esp, -BOX.sizeof
+        lea     eax, [edx + APPDATA.saved_box]
+        jmp     .set_box
+
+    @@: mov     eax, [screen_workarea.top]
+        push    [screen_workarea.bottom] \
+                [edi + WDATA.box.width] \
+                eax \
+                [edi + WDATA.box.left]
+        sub     [esp + BOX.height], eax
+        mov     eax, esp
+
+  .set_box:
+        call    window._.set_window_box
+        add     esp, BOX.sizeof
+
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+sys_window_start_moving_handler: ;/////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> eax = old (original) window box
+;> esi = process slot
+;------------------------------------------------------------------------------
+        mov     edi, eax
+        call    window._.draw_negative_box
+
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+sys_window_end_moving_handler: ;///////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> eax = old (original) window box
+;> ebx = new (final) window box
+;> esi = process slot
+;------------------------------------------------------------------------------
+        mov     edi, ebx
+        call    window._.draw_negative_box
+
+        mov     edi, esi
+        shl     edi, 5
+        add     edi, window_data
+
+        mov     eax, ebx
+        mov     bl, [edi + WDATA.fl_wstate]
+        call    window._.set_window_box
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+sys_window_moving_handler: ;///////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> eax = old (from previous call) window box
+;> ebx = new (current) window box
+;> esi = process_slot
+;------------------------------------------------------------------------------
+        mov     edi, eax
+        call    window._.draw_negative_box
+        mov     edi, ebx
+        call    window._.draw_negative_box
+        ret
+
+;==============================================================================
+;///// private functions //////////////////////////////////////////////////////
+;==============================================================================
+
+iglobal
+  FuncTable syscall_display_settings, ftable, \
+    00, 01, 02, 03, 04, 05, 06, 07, 08
+
+  align 4
+  window_topleft dd \
+    1, 21, \ ;type 0
+    0,  0, \ ;type 1
+    5, 20, \ ;type 2
+    5,  ?, \ ;type 3 {set by skin}
+    5,  ?    ;type 4 {set by skin}
+endg
+
+;uglobal
+  ; NOTE: commented out since doesn't provide necessary functionality anyway,
+  ;       to be reworked
+; new_window_starting       dd ?
+;endg
+
+align 4
+;------------------------------------------------------------------------------
+window._.invalidate_screen: ;//////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> eax = old (original) window box
+;> ebx = new (final) window box
+;> edi = pointer to WDATA struct
+;------------------------------------------------------------------------------
+        push    eax ebx
+
+        ; TODO: do we really need `draw_limits`?
+        ; Yes, they are used by background drawing code.
+        mov     ecx, [eax + BOX.left]
+        mov     edx, [ebx + BOX.left]
+        cmp     ecx, edx
+        jle     @f
+        mov     ecx, edx
+    @@: mov     [draw_limits.left], ecx
+        mov     ecx, [eax + BOX.left]
+        add     ecx, [eax + BOX.width]
+        add     edx, [ebx + BOX.width]
+        cmp     ecx, edx
+        jae     @f
+        mov     ecx, edx
+    @@: mov     [draw_limits.right], ecx
+        mov     ecx, [eax + BOX.top]
+        mov     edx, [ebx + BOX.top]
+        cmp     ecx, edx
+        jle     @f
+        mov     ecx, edx
+    @@: mov     [draw_limits.top], ecx
+        mov     ecx, [eax + BOX.top]
+        add     ecx, [eax + BOX.height]
+        add     edx, [ebx + BOX.height]
+        cmp     ecx, edx
+        jae     @f
+        mov     ecx, edx
+    @@: mov     [draw_limits.bottom], ecx
+
+        ; recalculate screen buffer at old position
+        push    ebx
+        mov     edx, [eax + BOX.height]
+        mov     ecx, [eax + BOX.width]
+        mov     ebx, [eax + BOX.top]
+        mov     eax, [eax + BOX.left]
+        add     ecx, eax
+        add     edx, ebx
+        call    calculatescreen
+        pop     eax
+
+        ; recalculate screen buffer at new position
+        mov     edx, [eax + BOX.height]
+        mov     ecx, [eax + BOX.width]
+        mov     ebx, [eax + BOX.top]
+        mov     eax, [eax + BOX.left]
+        add     ecx, eax
+        add     edx, ebx
+        call    calculatescreen
+
+        mov     eax, edi
+        call    redrawscreen
+
+        ; tell window to redraw itself
+        mov     [edi + WDATA.fl_redraw], 1
+
+        pop     ebx eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.set_window_box: ;/////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> eax = pointer to BOX struct
+;> bl = new window state flags
+;> edi = pointer to WDATA struct
+;------------------------------------------------------------------------------
+        push    eax ebx esi
+
+; don't do anything if the new box is identical to the old
+	cmp	bl, [edi + WDATA.fl_wstate]
+	jnz	@f
+	mov	esi, eax
+	push	edi
+if WDATA.box
+	add	edi, WDATA.box
+end if
+	mov	ecx, 4
+	repz	cmpsd
+	pop	edi
+	jz	.exit
+@@:
+
+        add     esp, -BOX.sizeof
+
+        mov     ebx, esp
+if WDATA.box
+        lea     esi, [edi + WDATA.box]
+else
+	mov	esi, edi ; optimization for WDATA.box = 0
+end if
+        xchg    eax, esi
+        mov     ecx, BOX.sizeof
+        call    memmove
+        xchg    eax, esi
+        xchg    ebx, esi
+        call    memmove
+        mov     eax, ebx
+        mov     ebx, esi
+
+        call    window._.check_window_position
+        call    window._.set_window_clientbox
+        call    window._.invalidate_screen
+
+        add     esp, BOX.sizeof
+
+        mov     cl, [esp + 4]
+        mov     ch, cl
+        xchg    cl, [edi + WDATA.fl_wstate]
+
+        or      cl, ch
+        test    cl, WSTATE_MAXIMIZED
+        jnz     .exit
+
+        mov     eax, edi
+        sub     eax, window_data
+        shl     eax, 3
+        add     eax, SLOT_BASE
+
+        lea     ebx, [edi + WDATA.box]
+        xchg    esp, ebx
+
+        pop     [eax + APPDATA.saved_box.left] \
+                [eax + APPDATA.saved_box.top] \
+                [eax + APPDATA.saved_box.width] \
+                edx
+
+        xchg    esp, ebx
+
+        test    ch, WSTATE_ROLLEDUP
+        jnz     .exit
+
+        mov     [eax + APPDATA.saved_box.height], edx
+
+  .exit:
+        pop     esi ebx eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.set_window_clientbox: ;///////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> edi = pointer to WDATA struct
+;------------------------------------------------------------------------------
+        push    eax ecx edi
+
+        mov     eax, [_skinh]
+        mov     [window_topleft + 8 * 3 + 4], eax
+        mov     [window_topleft + 8 * 4 + 4], eax
+
+        mov     ecx, edi
+        sub     edi, window_data
+        shl     edi, 3
+        test    [ecx + WDATA.fl_wstyle], WSTYLE_CLIENTRELATIVE
+        jz      .whole_window
+
+        movzx   eax, [ecx + WDATA.fl_wstyle]
+        and     eax, 0x0F
+        mov     eax, [eax * 8 + window_topleft + 0]
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax
+        shl     eax, 1
+        neg     eax
+        add     eax, [ecx + WDATA.box.width]
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax
+
+        movzx   eax, [ecx + WDATA.fl_wstyle]
+        and     eax, 0x0F
+        push    [eax * 8 + window_topleft + 0]
+        mov     eax, [eax * 8 + window_topleft + 4]
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax
+        neg     eax
+        sub     eax, [esp]
+        add     eax, [ecx + WDATA.box.height]
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax
+        add     esp, 4
+        jmp     .exit
+
+  .whole_window:
+        xor     eax, eax
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.left], eax
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.top], eax
+        mov     eax, [ecx + WDATA.box.width]
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.width], eax
+        mov     eax, [ecx + WDATA.box.height]
+        mov     [edi + SLOT_BASE + APPDATA.wnd_clientbox.height], eax
+
+  .exit:
+        pop     edi ecx eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.sys_set_window: ;/////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;< edx = pointer to WDATA struct
+;------------------------------------------------------------------------------
+        mov     eax, [CURRENT_TASK]
+        shl     eax, 5
+        add     eax, window_data
+
+        ; save window colors
+        mov     [eax + WDATA.cl_workarea], edx
+        mov     [eax + WDATA.cl_titlebar], esi
+        mov     [eax + WDATA.cl_frames], edi
+
+        mov     edi, eax
+
+        ; was it already defined before?
+        test    [edi + WDATA.fl_wdrawn], 1
+        jnz     .set_client_box
+        or      [edi + WDATA.fl_wdrawn], 1
+
+        ; NOTE: commented out since doesn't provide necessary functionality
+        ;       anyway, to be reworked
+;       mov     eax, [timer_ticks] ; [0xfdf0]
+;       add     eax, 100
+;       mov     [new_window_starting], eax
+
+        ; no it wasn't, performing initial window definition
+        movzx   eax, bx
+        mov     [edi + WDATA.box.width], eax
+        movzx   eax, cx
+        mov     [edi + WDATA.box.height], eax
+        sar     ebx, 16
+        sar     ecx, 16
+        mov     [edi + WDATA.box.left], ebx
+        mov     [edi + WDATA.box.top], ecx
+
+        call    window._.check_window_position
+
+        push    ecx edi
+
+        mov     cl, [edi + WDATA.fl_wstyle]
+        mov     eax, [edi + WDATA.cl_frames]
+
+        sub     edi, window_data
+        shl     edi, 3
+        add     edi, SLOT_BASE
+
+        and     cl, 0x0F
+        cmp     cl, 3
+        je      @f
+        cmp     cl, 4
+        je      @f
+
+        xor     eax, eax
+
+    @@: mov     [edi + APPDATA.wnd_caption], eax
+
+        mov     esi, [esp]
+        add     edi, APPDATA.saved_box
+        movsd
+        movsd
+        movsd
+        movsd
+
+        pop     edi ecx
+
+        mov     esi, [CURRENT_TASK]
+        movzx   esi, word[WIN_STACK + esi * 2]
+        lea     esi, [WIN_POS + esi * 2]
+        call    waredraw
+
+        mov     eax, [edi + WDATA.box.left]
+        mov     ebx, [edi + WDATA.box.top]
+        mov     ecx, [edi + WDATA.box.width]
+        mov     edx, [edi + WDATA.box.height]
+        add     ecx, eax
+        add     edx, ebx
+        call    calculatescreen
+
+        mov     byte[KEY_COUNT], 0           ; empty keyboard buffer
+        mov     byte[BTN_COUNT], 0           ; empty button buffer
+
+  .set_client_box:
+        ; update window client box coordinates
+        call    window._.set_window_clientbox
+
+        ; reset window redraw flag and exit
+        mov     [edi + WDATA.fl_redraw], 0
+        mov     edx, edi
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.check_window_position: ;//////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Check if window is inside screen area
+;------------------------------------------------------------------------------
+;> edi = pointer to WDATA
+;------------------------------------------------------------------------------
+        push    eax ebx ecx edx esi
+
+        mov     eax, [edi + WDATA.box.left]
+        mov     ebx, [edi + WDATA.box.top]
+        mov     ecx, [edi + WDATA.box.width]
+        mov     edx, [edi + WDATA.box.height]
+
+        mov     esi, [Screen_Max_X]
+        cmp     ecx, esi
+        ja      .fix_width_high
+
+  .check_left:
+        or      eax, eax
+        jl      .fix_left_low
+        add     eax, ecx
+        cmp     eax, esi
+        jg      .fix_left_high
+
+  .check_height:
+        mov     esi, [Screen_Max_Y]
+        cmp     edx, esi
+        ja      .fix_height_high
+
+  .check_top:
+        or      ebx, ebx
+        jl      .fix_top_low
+        add     ebx, edx
+        cmp     ebx, esi
+        jg      .fix_top_high
+
+  .exit:
+        pop     esi edx ecx ebx eax
+        ret
+
+  .fix_width_high:
+        mov     ecx, esi
+        mov     [edi + WDATA.box.width], esi
+        jmp     .check_left
+
+  .fix_left_low:
+        xor     eax, eax
+        mov     [edi + WDATA.box.left], eax
+        jmp     .check_height
+
+  .fix_left_high:
+        mov     eax, esi
+        sub     eax, ecx
+        mov     [edi + WDATA.box.left], eax
+        jmp     .check_height
+
+  .fix_height_high:
+        mov     edx, esi
+        mov     [edi + WDATA.box.height], esi
+        jmp     .check_top
+
+  .fix_top_low:
+        xor     ebx, ebx
+        mov     [edi + WDATA.box.top], ebx
+        jmp     .exit
+
+  .fix_top_high:
+        mov     ebx, esi
+        sub     ebx, edx
+        mov     [edi + WDATA.box.top], ebx
+        jmp     .exit
+
+align 4
+;------------------------------------------------------------------------------
+window._.get_titlebar_height: ;////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> edi = pointer to WDATA
+;------------------------------------------------------------------------------
+        mov     al, [edi + WDATA.fl_wstyle]
+        and     al, 0x0f
+        cmp     al, 0x03
+        jne     @f
+        mov     eax, [_skinh]
+        ret
+    @@: mov     eax, 21
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.get_rolledup_height: ;////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+;> edi = pointer to WDATA
+;------------------------------------------------------------------------------
+        mov     al, [edi + WDATA.fl_wstyle]
+        and     al, 0x0f
+        cmp     al, 0x03
+        jb      @f
+        mov     eax, [_skinh]
+        add     eax, 3
+        ret
+    @@: or      al, al
+        jnz     @f
+        mov     eax, 21
+        ret
+    @@: mov     eax, 21 + 2
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.set_screen: ;/////////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Reserve window area in screen buffer
+;------------------------------------------------------------------------------
+;> eax = left
+;> ebx = top
+;> ecx = right
+;> edx = bottom
+;> esi = process number
+;------------------------------------------------------------------------------
+virtual at esp
+  ff_x     dd ?
+  ff_y     dd ?
+  ff_width dd ?
+  ff_xsz   dd ?
+  ff_ysz   dd ?
+  ff_scale dd ?
+end virtual
+
+        pushad
+
+        cmp     esi, 1
+        jz      .check_for_shaped_window
+        mov     edi, esi
+        shl     edi, 5
+        cmp     [window_data + edi + WDATA.box.width], 0
+        jnz     .check_for_shaped_window
+        cmp     [window_data + edi + WDATA.box.height], 0
+        jz      .exit
+
+  .check_for_shaped_window:
+        mov     edi, esi
+        shl     edi, 8
+        add     edi, SLOT_BASE
+        cmp     [edi + APPDATA.wnd_shape], 0
+        jne     .shaped_window
+
+        ; get x&y size
+        sub     ecx, eax
+        sub     edx, ebx
+        inc     ecx
+        inc     edx
+
+        ; get WinMap start
+        push    esi
+        mov     edi, [Screen_Max_X]
+        inc     edi
+        mov     esi, edi
+        imul    edi, ebx
+        add     edi, eax
+        add     edi, [_WinMapAddress]
+        pop     eax
+        mov     ah, al
+        push    ax
+        shl     eax, 16
+        pop     ax
+
+  .next_line:
+        push    ecx
+        shr     ecx, 2
+        rep     stosd
+        mov     ecx, [esp]
+        and     ecx, 3
+        rep     stosb
+        pop     ecx
+        add     edi, esi
+        sub     edi, ecx
+        dec     edx
+        jnz     .next_line
+
+        jmp     .exit
+
+  .shaped_window:
+        ;  for (y=0; y <= x_size; y++)
+        ;      for (x=0; x <= x_size; x++)
+        ;          if (shape[coord(x,y,scale)]==1)
+        ;             set_pixel(x, y, process_number);
+
+        sub     ecx, eax
+        sub     edx, ebx
+        inc     ecx
+        inc     edx
+
+        push    [edi + APPDATA.wnd_shape_scale]  ; push scale first -> for loop
+
+        ; get WinMap start  -> ebp
+        push    eax
+        mov     eax, [Screen_Max_X] ; screen_sx
+        inc     eax
+        imul    eax, ebx
+        add     eax, [esp]
+        add     eax, [_WinMapAddress]
+        mov     ebp, eax
+
+        mov     edi, [edi + APPDATA.wnd_shape]
+        pop     eax
+
+        ; eax = x_start
+        ; ebx = y_start
+        ; ecx = x_size
+        ; edx = y_size
+        ; esi = process_number
+        ; edi = &shape
+        ;       [scale]
+        push    edx ecx ; for loop - x,y size
+
+        mov     ecx, esi
+        shl     ecx, 5
+        mov     edx, [window_data + ecx + WDATA.box.top]
+        push    [window_data + ecx + WDATA.box.width]           ; for loop - width
+        mov     ecx, [window_data + ecx + WDATA.box.left]
+        sub     ebx, edx
+        sub     eax, ecx
+        push    ebx eax ; for loop - x,y
+
+        add     [ff_xsz], eax
+        add     [ff_ysz], ebx
+
+        mov     ebx, [ff_y]
+
+  .ff_new_y:
+        mov     edx, [ff_x]
+
+  .ff_new_x:
+        ; -- body --
+        mov     ecx, [ff_scale]
+        mov     eax, [ff_width]
+        inc     eax
+        shr     eax, cl
+        push    ebx edx
+        shr     ebx, cl
+        shr     edx, cl
+        imul    eax, ebx
+        add     eax, edx
+        pop     edx ebx
+        add     eax, edi
+        call    .read_byte
+        test    al,al
+        jz      @f
+        mov     eax, esi
+        mov     [ebp], al
+        ; -- end body --
+    @@: inc     ebp
+        inc     edx
+        cmp     edx, [ff_xsz]
+        jb      .ff_new_x
+
+        sub     ebp, [ff_xsz]
+        add     ebp, [ff_x]
+        add     ebp, [Screen_Max_X]  ; screen.x
+        inc     ebp
+        inc     ebx
+        cmp     ebx, [ff_ysz]
+        jb      .ff_new_y
+
+        add     esp, 24
+
+  .exit:
+        popad
+        ret
+
+  .read_byte:
+        ; eax - address
+        ; esi - slot
+        push    eax ecx edx esi
+        xchg    eax, esi
+        lea     ecx, [esp + 12]
+        mov     edx, 1
+        call    read_process_memory
+        pop     esi edx ecx eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.window_activate: ;////////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Activate window
+;------------------------------------------------------------------------------
+;> esi = pointer to WIN_POS+ window data
+;------------------------------------------------------------------------------
+        push    eax ebx
+
+        ; if type of current active window is 3 or 4, it must be redrawn
+        mov     ebx, [TASK_COUNT]
+        movzx   ebx, word[WIN_POS + ebx * 2]
+        shl     ebx, 5
+        add     eax, window_data
+        mov     al, [window_data + ebx + WDATA.fl_wstyle]
+        and     al, 0x0f
+        cmp     al, 0x03
+        je      .set_window_redraw_flag
+        cmp     al, 0x04
+        jne     .move_others_down
+
+  .set_window_redraw_flag:
+        mov     [window_data + ebx + WDATA.fl_redraw], 1
+
+  .move_others_down:
+        ; ax <- process no
+        movzx   ebx, word[esi]
+        ; ax <- position in window stack
+        movzx   ebx, word[WIN_STACK + ebx * 2]
+
+        ; drop others
+        xor     eax, eax
+
+  .next_stack_window:
+        cmp     eax, [TASK_COUNT]
+        jae     .move_self_up
+        inc     eax
+        cmp     [WIN_STACK + eax * 2], bx
+        jbe     .next_stack_window
+        dec     word[WIN_STACK + eax * 2]
+        jmp     .next_stack_window
+
+  .move_self_up:
+        movzx   ebx, word[esi]
+        ; number of processes
+        mov     ax, [TASK_COUNT]
+        ; this is the last (and the upper)
+        mov     [WIN_STACK + ebx * 2], ax
+
+        ; update on screen - window stack
+        xor     eax, eax
+
+  .next_window_pos:
+        cmp     eax, [TASK_COUNT]
+        jae     .reset_vars
+        inc     eax
+        movzx   ebx, word[WIN_STACK + eax * 2]
+        mov     [WIN_POS + ebx * 2], ax
+        jmp     .next_window_pos
+
+  .reset_vars:
+        mov     byte[KEY_COUNT], 0
+        mov     byte[BTN_COUNT], 0
+        mov     word[MOUSE_SCROLL_H], 0
+        mov     word[MOUSE_SCROLL_V], 0
+
+        pop     ebx eax
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.check_window_draw: ;//////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Check if window is necessary to draw
+;------------------------------------------------------------------------------
+;> edi = pointer to WDATA
+;------------------------------------------------------------------------------
+        mov     cl, [edi + WDATA.fl_wstyle]
+        and     cl, 0x0f
+        cmp     cl, 3
+        je      .exit.redraw      ; window type 3
+        cmp     cl, 4
+        je      .exit.redraw      ; window type 4
+
+        push    eax ebx edx esi
+
+        mov     eax, edi
+        sub     eax, window_data
+        shr     eax, 5
+
+        movzx   eax, word[WIN_STACK + eax * 2]  ; get value of the curr process
+        lea     esi, [WIN_POS + eax * 2]        ; get address of this process at 0xC400
+
+  .next_window:
+        add     esi, 2
+
+        mov     eax, [TASK_COUNT]
+        lea     eax, word[WIN_POS + eax * 2] ; number of the upper window
+
+        cmp     esi, eax
+        ja      .exit.no_redraw
+
+        movzx   edx, word[esi]
+        shl     edx, 5
+        cmp     [CURRENT_TASK + edx + TASKDATA.state], TSTATE_FREE
+        je      .next_window
+
+        mov     eax, [edi + WDATA.box.top]
+        mov     ebx, [edi + WDATA.box.height]
+        add     ebx, eax
+
+        mov     ecx, [window_data + edx + WDATA.box.top]
+        cmp     ecx, ebx
+        jge     .next_window
+        add     ecx, [window_data + edx + WDATA.box.height]
+        cmp     eax, ecx
+        jge     .next_window
+
+        mov     eax, [edi + WDATA.box.left]
+        mov     ebx, [edi + WDATA.box.width]
+        add     ebx, eax
+
+        mov     ecx, [window_data + edx + WDATA.box.left]
+        cmp     ecx, ebx
+        jge     .next_window
+        add     ecx, [window_data + edx + WDATA.box.width]
+        cmp     eax, ecx
+        jge     .next_window
+
+        pop     esi edx ebx eax
+
+  .exit.redraw:
+        xor     ecx, ecx
+        inc     ecx
+        ret
+
+  .exit.no_redraw:
+        pop     esi edx ebx eax
+        xor     ecx, ecx
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.draw_window_caption: ;////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? <description>
+;------------------------------------------------------------------------------
+        inc     [mouse_pause]
+        call    [_display.disable_mouse]
+
+        xor     eax, eax
+        mov     edx, [TASK_COUNT]
+        movzx   edx, word[WIN_POS + edx * 2]
+        cmp     edx, [CURRENT_TASK]
+        jne     @f
+        inc     eax
+    @@: mov     edx, [CURRENT_TASK]
+        shl     edx, 5
+        add     edx, window_data
+        movzx   ebx, [edx + WDATA.fl_wstyle]
+        and     bl, 0x0F
+        cmp     bl, 3
+        je      .draw_caption_style_3
+        cmp     bl, 4
+        je      .draw_caption_style_3
+
+        jmp     .not_style_3
+
+  .draw_caption_style_3:
+        push    edx
+        call    drawwindow_IV_caption
+        add     esp, 4
+        jmp     .2
+
+  .not_style_3:
+        cmp     bl, 2
+        jne     .not_style_2
+
+        call    drawwindow_III_caption
+        jmp     .2
+
+  .not_style_2:
+        cmp     bl, 0
+        jne     .2
+
+        call    drawwindow_I_caption
+
+  .2:   mov     edi, [CURRENT_TASK]
+        shl     edi, 5
+        test    [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION
+        jz      .exit
+        mov     edx, [edi * 8 + SLOT_BASE + APPDATA.wnd_caption]
+        or      edx, edx
+        jz      .exit
+
+        movzx   eax, [edi + window_data + WDATA.fl_wstyle]
+        and     al, 0x0F
+        cmp     al, 3
+        je      .skinned
+        cmp     al, 4
+        je      .skinned
+
+        jmp     .not_skinned
+
+  .skinned:
+        mov     ebp, [edi + window_data + WDATA.box.left - 2]
+        mov     bp, word[edi + window_data + WDATA.box.top]
+        movzx   eax, word[edi + window_data + WDATA.box.width]
+        sub     ax, [_skinmargins.left]
+        sub     ax, [_skinmargins.right]
+        push    edx
+        cwde
+        cdq
+        mov     ebx, 6
+        idiv    ebx
+        pop     edx
+        or      eax, eax
+        js      .exit
+
+        mov     esi, eax
+        mov     ebx, dword[_skinmargins.left - 2]
+        mov     bx, word[_skinh]
+        sub     bx, [_skinmargins.bottom]
+        sub     bx, [_skinmargins.top]
+        sar     bx, 1
+        adc     bx, 0
+        add     bx, [_skinmargins.top]
+        add     bx, -3
+        add     ebx, ebp
+        jmp     .dodraw
+
+  .not_skinned:
+        cmp     al, 1
+        je      .exit
+
+        mov     ebp, [edi + window_data + WDATA.box.left - 2]
+        mov     bp, word[edi + window_data + WDATA.box.top]
+        movzx   eax, word[edi + window_data + WDATA.box.width]
+        sub     eax, 16
+        push    edx
+        cwde
+        cdq
+        mov     ebx, 6
+        idiv    ebx
+        pop     edx
+        or      eax, eax
+        js      .exit
+
+        mov     esi, eax
+        mov     ebx, 0x00080007
+        add     ebx, ebp
+
+  .dodraw:
+        mov     ecx, [common_colours + 16]
+        or      ecx, 0x80000000
+        xor     edi, edi
+        call    dtext_asciiz_esi
+
+  .exit:
+        dec     [mouse_pause]
+        call    [draw_pointer]
+        ret
+
+align 4
+;------------------------------------------------------------------------------
+window._.draw_negative_box: ;//////////////////////////////////////////////////
+;------------------------------------------------------------------------------
+;? Draw negative box
+;------------------------------------------------------------------------------
+;> edi = pointer to BOX struct
+;------------------------------------------------------------------------------
+        push    eax ebx esi
+        mov     eax, [edi + BOX.left - 2]
+        mov     ax, word[edi + BOX.left]
+        add     ax, word[edi + BOX.width]
+        mov     ebx, [edi + BOX.top - 2]
+        mov     bx, word[edi + BOX.top]
+        add     bx, word[edi + BOX.height]
+        mov     esi, 0x01000000
+        call    draw_rectangle.forced
+        pop     esi ebx eax
+        ret
diff --git a/kernel/branches/Kolibri-A/trunk/hid/keyboard.inc b/kernel/branches/Kolibri-A/trunk/hid/keyboard.inc
index 9d6d0b836e..f56ca11139 100644
--- a/kernel/branches/Kolibri-A/trunk/hid/keyboard.inc
+++ b/kernel/branches/Kolibri-A/trunk/hid/keyboard.inc
@@ -177,6 +177,7 @@ irq1:
        mov   eax,VKEY_SCRLOCK
        jmp   .no_key.xor
    @@:
+       xor   ebx, ebx
        test  ch,ch
        js    .writekey
        movzx eax,ch		 ; plain key
@@ -200,7 +201,6 @@ irq1:
        jz    @f
        mov   bl,[keymap_alt+eax]
    @@:
-	mov	bh, 0
 	jmp	.writekey
 .modifier:
 	test	ch, ch
diff --git a/kernel/branches/Kolibri-A/trunk/kernel.asm b/kernel/branches/Kolibri-A/trunk/kernel.asm
index 823287a213..d268eaf5fe 100644
--- a/kernel/branches/Kolibri-A/trunk/kernel.asm
+++ b/kernel/branches/Kolibri-A/trunk/kernel.asm
@@ -553,6 +553,13 @@ v20ga32:
 	mov	al, 0x3F
 	out	0xA1, al
 
+; Enable interrupts in IDE controller
+        mov     al, 0
+        mov     dx, 0x3F6
+        out     dx, al
+        mov     dl, 0x76
+        out     dx, al
+
 ;!!!!!!!!!!!!!!!!!!!!!!!!!!
 include 'detect/disks.inc'
 ;!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -2048,10 +2055,13 @@ sysfn_mouse_acceleration: ; 18.19 = set/get mouse features
 ;     cmp  ecx,4  ; set mouse pointer position
      dec   ecx
      jnz  .set_mouse_button
-     mov   [MOUSE_Y],dx    ;y
-     ror   edx,16
-     mov   [MOUSE_X],dx    ;x
+     cmp   dx, word[Screen_Max_Y]
+     ja    .end
+
      rol   edx,16
+     cmp   dx, word[Screen_Max_X]
+     ja    .end
+     mov   [MOUSE_X], edx
      ret
  .set_mouse_button:
 ;     cmp   ecx,5  ; set mouse button features
@@ -2124,15 +2134,11 @@ endg
 iglobal
 version_inf:
   db 0,7,7,0  ; version 0.7.7.0
-  db UID_KOLIBRI
+  db 0		;reserved
   dd __REV__
 version_end:
 endg
 
-UID_NONE=0
-UID_MENUETOS=1	 ;official
-UID_KOLIBRI=2	 ;russian
-
 sys_cachetodiskette:
 	cmp	ebx, 1
 	jne	.no_floppy_a_save
@@ -2588,6 +2594,10 @@ sys_cpuusage:
 	mov	al, [ecx+window_data+WDATA.fl_wstate]
 	stosb
 
+    ; Event mask (+71)
+        mov     EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask]
+        stosd
+
 	pop	esi
 	pop	edi
 
@@ -2720,11 +2730,6 @@ sys_redrawstat:
 	mov	eax, [Screen_Max_Y]
 	mov	[edx + RECT.bottom], eax
 
-	mov	edi, [TASK_BASE]
-	or	[edi - twdw + WDATA.fl_wdrawn], 1   ; no new position & buttons from app
-	call	sys_window_mouse
-	ret
-
   srl1:
 	ret