0,0 → 1,795 |
; |
; This file is part of the Infinity sound library. |
; (C) copyright Serge 2006 |
; email: infinity_sound@mail.ru |
; |
; This program is free software; you can redistribute it and/or modify |
; it under the terms of the GNU General Public License as published by |
; the Free Software Foundation; either version 2 of the License, or |
; (at your option) any later version. |
; |
; This program is distributed in the hope that it will be useful, |
; but WITHOUT ANY WARRANTY; without even the implied warranty of |
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
; GNU General Public License for more details. |
|
format MS COFF |
|
include 'proc32.inc' |
include 'main.inc' |
|
DEBUG equ 1 |
|
EVENT_NOTIFY equ 0x00000200 |
|
OS_BASE equ 0; 0x80400000 |
new_app_base equ 0x60400000; 0x01000000 |
PROC_BASE equ OS_BASE+0x0080000 |
|
public service_proc |
public START |
public IMPORTS |
|
SND_CREATE_BUFF equ 2 |
SND_PLAY equ 3 |
SND_STOP equ 4 |
SND_SETBUFF equ 5 |
SND_DESTROY_BUFF equ 6 |
|
DEV_PLAY equ 1 |
DEV_STOP equ 2 |
DEV_CALLBACK equ 3 |
|
struc IOCTL |
{ .handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
|
virtual at 0 |
IOCTL IOCTL |
end virtual |
|
section '.flat' align 16 |
|
START: |
stdcall [GetService], szSound |
test eax, eax |
jz .fail |
mov [hSound], eax |
|
stdcall [KernelAlloc], 16*512 |
test eax, eax |
jz .out_of_mem |
mov [mix_buff], eax |
|
mov edi, stream_list |
mov ecx, 17 |
xor eax, eax |
cld |
rep stosd |
|
mov edi, stream |
mov ecx, 4*STREAM_SIZE |
rep stosd |
|
stdcall set_handler, [hSound], new_mix |
|
stdcall [RegService], szInfinity, service_proc |
mov [stream_count],0 |
|
ret |
.fail: |
if DEBUG |
mov esi, msgFail |
call [SysMsgBoardStr] |
end if |
xor eax, eax |
ret |
|
.out_of_mem: |
if DEBUG |
mov esi, msgMem |
call [SysMsgBoardStr] |
end if |
xor eax, eax |
ret |
|
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, SND_CREATE_BUFF |
jne @F |
mov ebx, [edi+input] |
stdcall CreateBuffer,[ebx] |
ret |
@@: |
cmp eax, SND_PLAY |
jne @F |
|
mov ebx, [edi+input] |
stdcall play_buffer, [ebx] |
ret |
@@: |
cmp eax, SND_STOP |
jne @F |
|
; if DEBUG |
; mov esi, msgStop |
; call [SysMsgBoardStr] |
; end if |
|
mov ebx, [edi+input] |
stdcall stop_buffer, [ebx] |
ret |
@@: |
cmp eax, SND_SETBUFF |
jne @F |
|
mov ebx, [edi+input] |
mov eax, [ebx+4] |
add eax, new_app_base |
stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12] |
ret |
@@: |
cmp eax, SND_DESTROY_BUFF |
jne @F |
|
mov ebx, [edi+input] |
stdcall DestroyBuffer, [ebx] |
ret |
@@: |
xor eax, eax |
ret |
endp |
|
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
|
TASK_COUNT equ 0x0003004 |
CURRENT_TASK equ 0x0003000 |
|
|
align 8 |
proc CreateBuffer stdcall, format:dword |
locals |
str dd ? |
endl |
|
call alloc_stream |
and eax, eax |
jz .fail |
mov [str], eax |
mov edi, eax |
|
mov edx, [stream_count] |
mov [stream_list+edx*4], eax |
inc [stream_count] |
|
mov [edi+STREAM.magic], 'WAVE' |
mov [edi+STREAM.size], STREAM_SIZE |
|
stdcall [KernelAlloc], 180*1024 |
|
mov edi, [str] |
mov [edi+STREAM.base], eax |
mov [edi+STREAM.curr_seg], eax |
mov [edi+STREAM.notify_off1], eax |
add eax, 0x8000 |
mov [edi+STREAM.notify_off2], eax |
add eax, 0x7FFF |
mov [edi+STREAM.limit], eax |
|
inc eax |
|
mov [edi+STREAM.work_buff], eax |
mov [edi+STREAM.work_read], eax |
mov [edi+STREAM.work_write], eax |
mov [edi+STREAM.work_count], 0 |
add eax, 0x10000 |
mov [edi+STREAM.work_top], eax |
add eax, 1024*32 |
mov [edi+STREAM.r_buff], eax |
|
mov ebx, [CURRENT_TASK] |
shl ebx, 5 |
mov eax, [0x3000+ebx+4] |
|
mov [edi+STREAM.notify_task], eax |
|
mov eax, [format] |
mov [edi+STREAM.format], eax |
mov [edi+STREAM.flags], SND_STOP |
|
xor ebx, ebx |
cmp eax, 19 |
jb @f |
mov ebx, 0x80808080 |
@@: |
mov [edi+STREAM.r_silence], ebx |
|
shl eax, 4 |
mov ebx, [resampler_params+eax] |
mov ecx, [resampler_params+eax+4] |
mov edx, [resampler_params+eax+8] |
|
mov [edi+STREAM.r_size],ebx |
mov [edi+STREAM.r_end], ecx |
mov [edi+STREAM.r_dt], edx |
|
mov ebx, [resampler_params+eax+12] |
mov [edi+STREAM.resample], ebx |
|
mov edi, [edi+STREAM.base] |
mov ecx, 180*1024/4 |
xor eax, eax |
rep stosd |
|
mov eax, [str] |
ret |
|
.fail: |
xor eax, eax |
ret |
endp |
|
align 4 |
pid_to_slot: |
|
push ebx |
push ecx |
mov ebx,[TASK_COUNT] |
shl ebx,5 |
mov ecx,2*32 |
.loop: |
cmp byte [CURRENT_TASK+ecx+0xa],9 |
jz .endloop ;skip empty slots |
cmp [CURRENT_TASK+ecx+0x4],eax ;check PID |
jz .pid_found |
.endloop: |
add ecx,32 |
cmp ecx,ebx |
jle .loop |
pop ecx |
pop ebx |
xor eax,eax |
ret |
|
.pid_found: |
shr ecx,5 |
mov eax,ecx |
pop ecx |
pop ebx |
ret |
|
|
|
align 4 |
proc DestroyBuffer stdcall, str:dword |
|
mov esi, [str] |
|
cmp [esi+STREAM.magic], 'WAVE' |
jne .fail |
|
cmp [esi+STREAM.size], STREAM_SIZE |
jne .fail |
|
stdcall [KernelFree], [esi+STREAM.base] |
|
mov eax, [str] |
call free_stream |
|
mov edi, [str] |
mov ecx, STREAM_SIZE/4 |
xor eax, eax |
cld |
rep stosd |
|
mov eax, [str] |
mov esi, stream_list |
mov ecx, 16 |
@@: |
cmp [esi], eax |
je .remove |
add esi, 4 |
dec ecx |
jnz @B |
xor eax, eax |
inc eax |
ret |
.remove: |
mov edi, esi |
add esi, 4 |
cld |
rep movsd |
dec [stream_count] |
xor eax, eax |
inc eax |
ret |
.fail: |
xor eax, eax |
ret |
endp |
|
align 4 |
proc play_buffer stdcall, str:dword |
|
mov ebx, [str] |
|
cmp [ebx+STREAM.magic], 'WAVE' |
jne .fail |
|
cmp [ebx+STREAM.size], STREAM_SIZE |
jne .fail |
|
mov [ebx+STREAM.flags], SND_PLAY |
|
mov eax,[ebx+STREAM.work_buff] |
mov [ebx+STREAM.work_read], eax |
mov [ebx+STREAM.work_write], eax |
mov [ebx+STREAM.work_count], 0 |
|
mov eax, [ebx+STREAM.base] |
mov [ebx+STREAM.curr_seg], eax |
|
mov esi, [ebx+STREAM.curr_seg] |
mov edi, [ebx+STREAM.work_write] |
mov edx, [ebx+STREAM.r_buff] |
|
mov ecx, 32 |
mov eax, [ebx+STREAM.r_silence] |
@@: |
mov [edx], eax |
add edx, 4 |
dec ecx |
jnz @B |
|
mov edx, [ebx+STREAM.r_buff] |
|
stdcall [ebx+STREAM.resample], edi, esi, edx,\ |
[ebx+STREAM.r_dt],[ebx+STREAM.r_size],[ebx+STREAM.r_end] |
|
mov ebx, [str] |
|
add [ebx+STREAM.work_count], eax; |
add [ebx+STREAM.work_write], eax; |
|
mov eax, [ebx+STREAM.r_size] |
add [ebx+STREAM.curr_seg], eax |
|
; if DEBUG |
; mov esi, msgPlay |
; call [SysMsgBoardStr] |
; end if |
|
stdcall dev_play, [hSound] |
|
xor eax, eax |
inc eax |
ret |
|
.fail: |
xor eax, eax |
ret |
|
endp |
|
|
align 4 |
proc stop_buffer stdcall, str:dword |
|
mov edi, [str] |
|
cmp [edi+STREAM.magic], 'WAVE' |
jne .fail |
|
cmp [edi+STREAM.size], STREAM_SIZE |
jne .fail |
|
mov [edi+STREAM.flags], SND_STOP |
|
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 |
|
xor eax, eax |
inc eax |
ret |
|
.fail: |
xor eax, eax |
ret |
|
endp |
|
align 4 |
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword |
|
mov edx, [str] |
test edx, edx |
jz .fail |
|
cmp [edx+STREAM.magic], 'WAVE' |
jne .fail |
|
cmp [edx+STREAM.size], STREAM_SIZE |
jne .fail |
|
mov esi,[src] |
test esi, esi |
jz .fail |
|
cmp esi, new_app_base |
jb .fail |
|
mov ecx, [size] |
test ecx, ecx |
jz .fail |
|
mov eax, [edx+STREAM.base] |
add eax, [offs] |
|
cmp eax, [edx+STREAM.base] |
jb .fail |
|
mov edi, eax |
add eax, ecx |
sub eax, 1 |
|
cmp eax, [edx+STREAM.limit] |
ja .fail |
|
shr ecx, 2 |
cld |
rep movsd |
|
xor eax, eax |
inc eax |
ret |
.fail: |
xor eax, eax |
ret |
endp |
|
align 4 |
proc alloc_stream |
|
mov esi, stream_map |
|
pushf |
cli |
|
bsf eax, [esi] |
jnz .find |
popf |
xor eax, eax |
ret |
|
.find: btr [esi], eax |
popf |
mov ebx, STREAM_SIZE |
mul ebx |
add eax, stream |
ret |
endp |
|
align 4 |
proc free_stream |
sub eax, stream |
mov ebx, STREAM_SIZE |
xor edx, edx |
div ebx |
|
and edx, edx |
jnz .err |
|
bts [stream_map], eax |
|
ret |
.err: |
xor eax, eax |
ret |
endp |
|
align 4 |
proc check_stream |
|
xor edx, edx |
mov ecx, [play_count] |
.l1: |
mov esi, [play_list+edx] |
|
mov eax, [esi+STR.curr_seg] |
cmp eax, [esi+STR.limit] |
jb .next |
|
.m1: mov eax,[esi+STR.base] |
mov [esi+STR.curr_seg], eax |
.next: |
add edx, 4 |
loop .l1 |
ret |
endp |
|
|
align 4 |
proc prepare_playlist |
|
.restart: |
xor ebx, ebx |
xor edx, edx |
mov [play_count], 0 |
mov ecx, [stream_count] |
jcxz .exit |
.l1: |
mov esi, [stream_list+ebx] |
test esi, esi |
jz .next |
|
cmp [esi+STREAM.magic], 'WAVE' |
jne .next |
|
cmp [esi+STREAM.size], STREAM_SIZE |
jne .next |
|
mov eax,[esi+STREAM.notify_task] |
cmp eax, -1 |
je .fail |
|
call pid_to_slot |
test eax, eax |
jz .fail |
|
cmp [esi+STREAM.flags], SND_PLAY; |
jne .next |
cmp [esi+STREAM.work_count], 16384 |
jb .next |
|
mov [play_list+edx], esi |
inc [play_count] |
add edx, 4 |
.next: |
add ebx, 4 |
loop .l1 |
.exit: |
ret |
|
.fail: |
stdcall DestroyBuffer, esi |
jmp .restart |
endp |
|
align 4 |
proc prepare_updatelist |
|
xor ebx, ebx |
xor edx, edx |
mov [play_count], 0 |
mov ecx, [stream_count] |
jcxz .exit |
.l1: |
mov eax, [stream_list+ebx] |
test eax, eax |
jz .next |
cmp [eax+STREAM.flags], SND_PLAY |
jne .next |
|
mov [play_list+edx], eax |
inc [play_count] |
add edx, 4 |
.next: |
add ebx, 4 |
loop .l1 |
.exit: |
ret |
endp |
|
|
align 4 |
proc set_handler stdcall, hsrv:dword, handler_proc:dword |
locals |
handler dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
|
mov eax, [hsrv] |
lea ecx, [handler_proc] |
xor ebx, ebx |
|
mov [handler], eax |
mov [io_code], DEV_CALLBACK |
mov [input], ecx |
mov [inp_size], 4 |
mov [output], ebx |
mov [out_size], 0 |
|
lea eax, [handler] |
stdcall [ServiceHandler], eax |
ret |
endp |
|
align 4 |
proc dev_play stdcall, hsrv:dword |
locals |
handle dd ? |
io_code dd ? |
input dd ? |
inp_size dd ? |
output dd ? |
out_size dd ? |
val dd ? |
endl |
|
mov eax, [hsrv] |
xor ebx, ebx |
|
mov [handle], eax |
mov [io_code], DEV_PLAY |
mov [input], ebx |
mov [inp_size], ebx |
mov [output], ebx |
mov [out_size], ebx |
|
lea eax, [handle] |
stdcall [ServiceHandler], eax |
ret |
endp |
|
include 'mixer.asm' |
|
align 16 |
play_list dd 16 dup(0) |
stream_list dd 17 dup(0) |
|
align 16 |
resampler_params: |
;r_size r_end r_dt resampler_func |
dd 0,0,0,0 ; 0 PCM_ALL |
dd 16384, 0, 0, copy_stream ; 1 PCM_2_16_48 |
dd 16384, 0, 0, m16_stereo ; 2 PCM_1_16_48 |
|
dd 16384, 0x08000000, 30109, resample_2 ; 3 PCM_2_16_44 |
dd 8192, 0x08000000, 30109, resample_1 ; 4 PCM_1_16_44 |
|
dd 16384, 0x08000000, 21846, resample_2 ; 5 PCM_2_16_32 |
dd 8192, 0x08000000, 21846, resample_1 ; 6 PCM_1_16_32 |
|
dd 16384, 0x08000000, 16384, resample_2 ; 7 PCM_2_16_24 |
dd 8192, 0x08000000, 16384, resample_1 ; 8 PCM_1_16_24 |
|
dd 8192, 0x04000000, 15052, resample_2 ; 9 PCM_2_16_22 |
dd 4096, 0x04000000, 15052, resample_1 ;10 PCM_1_16_22 |
|
dd 8192, 0x04000000, 10923, resample_2 ;11 PCM_2_16_16 |
dd 4096, 0x04000000, 10923, resample_1 ;12 PCM_1_16_16 |
|
dd 8192, 0x04000000, 8192, resample_2 ;13 PCM_2_16_12 |
dd 4096, 0x04000000, 8192, resample_1 ;14 PCM_1_16_12 |
|
dd 4096, 0x02000000, 7527, resample_2 ;15 PCM_2_16_11 |
dd 2048, 0x02000000, 7527, resample_1 ;16 PCM_1_16_11 |
|
dd 4096, 0x02000000, 5462, resample_2 ;17 PCM_2_16_8 |
dd 2048, 0x02000000, 5462, resample_1 ;18 PCM_1_16_8 |
|
dd 16384, 0, 0, s8_stereo ;19 PCM_2_8_48 |
dd 8192, 0, 0, m8_stereo ;20 PCM_1_8_48 |
|
dd 8192, 0x08000000, 30109, resample_28 ;21 PCM_2_8_44 |
dd 4096, 0x08000000, 30109, resample_18 ;22 PCM_1_8_44 |
|
dd 8192, 0x08000000, 21846, resample_28 ;23 PCM_2_8_32 |
dd 4096, 0x08000000, 21846, resample_18 ;24 PCM_1_8_32 |
|
dd 8192, 0x08000000, 16384, resample_28 ;25 PCM_2_8_24 |
dd 4096, 0x08000000, 16384, resample_18 ;26 PCM_1_8_24 |
|
dd 4096, 0x04000000, 15052, resample_28 ;27 PCM_2_8_22 |
dd 2048, 0x04000000, 15052, resample_18 ;28 PCM_1_8_22 |
|
dd 4096, 0x04000000, 10923, resample_28 ;29 PCM_2_8_16 |
dd 2048, 0x04000000, 10923, resample_18 ;30 PCM_1_8_16 |
|
dd 4096, 0x04000000, 8192, resample_28 ;31 PCM_2_8_12 |
dd 2048, 0x04000000, 8192, resample_18 ;32 PCM_1_8_12 |
|
dd 2048, 0x02000000, 7527, resample_28 ;33 PCM_2_8_11 |
dd 1024, 0x02000000, 7527, resample_18 ;34 PCM_1_8_11 |
|
dd 2048, 0x02000000, 5462, resample_28 ;35 PCM_2_8_8 |
dd 1024, 0x02000000, 5462, resample_18 ;36 PCM_1_8_8 |
|
|
play_count dd 0 |
|
stream_count dd 0 |
|
align 8 |
hSound dd 0 |
|
m7 dw 0x8000,0x8000,0x8000,0x8000 |
mm80 dq 0x8080808080808080 |
mm_mask dq 0xFF00FF00FF00FF00 |
|
mix_input dd 16 dup(0) |
|
align 16 |
;fpu_state db 512 dup(0) |
|
align 16 |
stream db STREAM_SIZE*16 dup(0) |
stream_map dd 0xFFFF ; 16 |
mix_buff dd 0 |
mix_buff_map dd 0 |
|
align 16 |
IMPORTS: |
|
AttachIntHandler dd szAttachIntHandler |
SysMsgBoardStr dd szSysMsgBoardStr |
PciApi dd szPciApi |
PciRead32 dd szPciRead32 |
PciRead8 dd szPciRead8 |
AllocKernelSpace dd szAllocKernelSpace |
MapPage dd szMapPage |
KernelAlloc dd szKernelAlloc |
KernelFree dd szKernelFree |
GetPgAddr dd szGetPgAddr |
RegService dd szRegService |
GetCurrentTask dd szGetCurrentTask |
GetService dd szGetService |
ServiceHandler dd szServiceHandler |
FpuSave dd szFpuSave |
FpuRestore dd szFpuRestore |
dd 0 |
|
szKernel db 'KERNEL', 0 |
szAttachIntHandler db 'AttachIntHandler',0 |
szSysMsgBoardStr db 'SysMsgBoardStr', 0 |
szPciApi db 'PciApi', 0 |
szPciRead32 db 'PciRead32', 0 |
szPciRead8 db 'PciRead8', 0 |
szAllocKernelSpace db 'AllocKernelSpace',0 |
szMapPage db 'MapPage',0 |
szRegService db 'RegService',0 |
szKernelAlloc db 'KernelAlloc',0 |
szGetPgAddr db 'GetPgAddr',0 |
szGetCurrentTask db 'GetCurrentTask ',0 |
szGetService db 'GetService',0 |
szServiceHandler db 'ServiceHandler',0 |
szKernelFree db 'KernelFree',0 |
szFpuSave db 'FpuSave',0 |
szFpuRestore db 'FpuRestore',0 |
|
|
szInfinity db 'INFINITY',0 |
szSound db 'SOUND',0 |
|
if DEBUG |
msgFail db 'Sound service not found',13,10,0 |
msgPlay db 'Play buffer',13,10,0 |
msgStop db 'Stop',13,10,0 |
msgUser db 'User callback',13,10,0 |
msgMem db 'Not enough memory',13,10,0 |
end if |