/kernel/branches/Kolibri-A/trunk/core/exports.inc |
---|
22,6 → 22,10 |
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 |
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 |
/kernel/branches/Kolibri-A/trunk/core/heap.inc |
---|
635,7 → 635,8 |
pop esi ebx |
ret |
.fail: |
and [heap_mutex], 0 |
xor eax, eax |
mov [heap_mutex], eax |
pop esi ebx |
ret |
endp |
/kernel/branches/Kolibri-A/trunk/core/memory.inc |
---|
1089,26 → 1089,8 |
.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 |
jbe sys_sheduler |
1228,6 → 1210,24 |
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 |
stdcall load_PE, [file] |
/kernel/branches/Kolibri-A/trunk/core/peload.inc |
---|
283,6 → 283,12 |
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 |
\ |
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 |
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' |
/kernel/branches/Kolibri-A/trunk/docs/sysfuncs.txt |
---|
347,6 → 347,7 |
* 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 |
* 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,58 → 1659,10 |
Remarks: |
* If the buffer is too small to hold all data, only first (edx-1) |
bytes are copied and than terminating 0 is inserted. |
* By default, current folder for the thread is "/rd/1". |
* At process/thread creation the current folder will be inherited |
====================================================================== |
=============== 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. |
====================================================================== |
======= Function 35 - read the color of a pixel on the screen. ======= |
====================================================================== |
Parameters: |
3421,7 → 3374,6 |
====================================================================== |
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,8 → 3725,60 |
* 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 ====== |
====================================================================== |
Parameters: |
3813,6 → 3817,7 |
* 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 |
* '/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 |
/kernel/branches/Kolibri-A/trunk/drivers/codec.inc |
---|
173,7 → 173,6 |
ret |
align 16 |
ac_unknown db 'unknown manufacturer',13,10,0 |
ac_Realtek db 'Realtek Semiconductor',13,10,0 |
181,6 → 180,9 |
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_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 |
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 |
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,10 → 253,19 |
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 |
;Analog Devices |
chip_AD1819 db 'AD1819 ',0dh,0ah,00h |
258,6 → 277,8 |
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_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 |
/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 |
/kernel/branches/Kolibri-A/trunk/drivers/imports.inc |
---|
27,6 → 27,10 |
ReservePortArea,\ |
Boot_Log,\ |
\ |
MutexInit,\ |
MutexLock,\ |
MutexUnlock,\ |
\ |
PciApi,\ |
PciRead32,\ |
PciRead16,\ |
/kernel/branches/Kolibri-A/trunk/drivers/infinity.asm |
---|
159,14 → 159,61 |
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 |
cmp eax, (srv_calls_end-srv_calls)/4 |
ja .fail |
cmp eax, SND_CREATE_BUFF |
ja @F |
jmp [srv_calls+eax*4] |
@@: |
mov ebx, [edi+input] |
mov edx, [ebx] |
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
cmp [edx+STREAM.size], STREAM.sizeof |
jne .fail |
jmp [srv_calls+eax*4] |
.fail: |
mov eax, -1 |
ret |
align 4 |
.srv_getversion: |
mov eax, [edi+output] |
cmp [edi+out_size], 4 |
jne .fail |
174,9 → 221,9 |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
@@: |
cmp eax, SND_CREATE_BUFF |
jne @F |
align 4 |
.snd_create_buff: |
mov ebx, [edi+input] |
stdcall CreateBuffer,[ebx],[ebx+4] |
mov edi, [ioctl] |
184,30 → 231,20 |
mov ecx, [ecx] |
mov [ecx], ebx |
ret |
@@: |
mov ebx, [edi+input] |
mov edx, [ebx] |
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
cmp [edx+STREAM.size], STREAM_SIZE |
jne .fail |
cmp eax, SND_DESTROY_BUFF |
jne @F |
align 4 |
.snd_destroy_buff: |
mov eax, edx |
call DestroyBuffer ;edx= stream |
call DestroyBuffer |
ret |
@@: |
cmp eax, SND_SETFORMAT |
jne @F |
stdcall SetFormat,edx,[ebx+4] |
align 4 |
.snd_setformat: |
stdcall SetFormat, edx,[ebx+4] |
ret |
@@: |
cmp eax, SND_GETFORMAT |
jne @F |
align 4 |
.snd_getformat: |
movzx eax, word [edx+STREAM.format] |
mov ecx, [edi+output] |
mov ecx, [ecx] |
214,19 → 251,19 |
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] |
233,34 → 270,48 |
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] |
267,28 → 318,9 |
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] |
295,10 → 327,9 |
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 |
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 |
call GetPid |
mov ebx, eax |
mov eax, STREAM_SIZE |
mov eax, STREAM.sizeof |
call CreateObject |
test eax, eax |
412,7 → 469,6 |
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 |
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 |
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 |
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 |
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; |
/kernel/branches/Kolibri-A/trunk/drivers/main.inc |
---|
91,6 → 91,8 |
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 |
.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 |
.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 |
/kernel/branches/Kolibri-A/trunk/drivers/mixer.asm |
---|
87,7 → 87,7 |
endp |
align 4 |
proc update_stream |
proc update_streams |
locals |
stream_index dd ? |
event rd 6 |
98,6 → 98,9 |
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 |
/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 |
/kernel/branches/Kolibri-A/trunk/fs/fs_lfn.inc |
---|
795,7 → 795,7 |
xor eax, eax |
ret |
.big: |
push ecx |
push ecx edx |
push -'0' |
mov ecx, 10 |
@@: |
810,7 → 810,7 |
add al, '0' |
stosb |
jnz @b |
pop ecx |
pop edx ecx |
pop eax |
inc eax |
ret |
/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 |
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 |
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 |
/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 |
/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 |
/kernel/branches/Kolibri-A/trunk/hid/keyboard.inc |
---|
177,6 → 177,7 |
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 |
jz @f |
mov bl,[keymap_alt+eax] |
@@: |
mov bh, 0 |
jmp .writekey |
.modifier: |
test ch, ch |
/kernel/branches/Kolibri-A/trunk/kernel.asm |
---|
553,6 → 553,13 |
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 |
; 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 |
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 |
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 |
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 |