/* snd_mixa.S x86 assembly-language sound code Copyright (C) 1996-1997 Id Software, Inc. 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. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA $Id$ */ #ifdef HAVE_CONFIG_H # include #endif #include "asm_i386.h" // #include "quakeasm.h" #ifdef USE_INTEL_ASM #ifdef _WIN32 # undef PIC //no such thing in win32 #endif .text .extern C(snd_scaletable) .extern C(paintbuffer) .extern C(snd_linear_count) .extern C(snd_p) .extern C(snd_vol) .extern C(snd_out) //---------------------------------------------------------------------- // 8-bit sound-mixing code //---------------------------------------------------------------------- #define ch 4+16 #define sc 8+16 #define count 12+16 .globl C(NOT_SND_PaintChannelFrom8) #ifdef PIC .type C(NOT_SND_PaintChannelFrom8),@function #endif C(NOT_SND_PaintChannelFrom8): pushl %esi // preserve register variables pushl %edi pushl %ebx pushl %ebp // int data; // short *lscale, *rscale; // unsigned char *sfx; // int i; movl ch(%esp),%ebx movl sc(%esp),%esi // if (ch->leftvol > 255) // ch->leftvol = 255; // if (ch->rightvol > 255) // ch->rightvol = 255; movl ch_leftvol(%ebx),%eax movl ch_rightvol(%ebx),%edx cmpl $255,%eax jna LLeftSet movl $255,%eax LLeftSet: cmpl $255,%edx jna LRightSet movl $255,%edx LRightSet: // lscale = snd_scaletable[ch->leftvol >> 3]; // rscale = snd_scaletable[ch->rightvol >> 3]; // sfx = (signed char *)sc->data + ch->pos; // ch->pos += count; andl $0xF8,%eax addl $(sfxc_data),%esi andl $0xF8,%edx movl ch_pos(%ebx),%edi movl count(%esp),%ecx addl %edi,%esi shll $7,%eax addl %ecx,%edi addl %ecx,%esi shll $7,%edx movl %edi,ch_pos(%ebx) #ifdef PIC call .Lpic1 .Lpic1: popl %ebx addl $C(_GLOBAL_OFFSET_TABLE_)+[.-.Lpic1],%ebx movl C(snd_scaletable)@GOT(%ebx,%eax),%eax movl C(snd_scaletable)@GOT(%ebx,%edx),%edx movl C(paintbuffer)@GOT(%ebx),%ebx #else leal C(snd_scaletable)(%eax),%eax leal C(snd_scaletable)(%edx),%edx leal C(paintbuffer),%ebx #endif pushl %ebx // save paintbuffer offset testl $1,%ecx leal 0(%ebx,%ecx,psp_size),%ecx movl $0,%ebx movb -1(%esi),%bl jz LMix8Loop movl (%eax,%ebx,4),%edi movl (%edx,%ebx,4),%ebp addl psp_left-psp_size(%ecx),%edi addl psp_right-psp_size(%ecx),%ebp movl %edi,psp_left-psp_size(%ecx) movl %ebp,psp_right-psp_size(%ecx) movb -2(%esi),%bl subl $psp_size,%ecx decl %esi cmpl (%esp),%ecx jz LDone // for (i=0 ; i>8; // if (val > 0x7fff) // snd_out[i] = 0x7fff; // else if (val < (short)0x8000) // snd_out[i] = (short)0x8000; // else // snd_out[i] = val; movl -8(%ebx,%ecx,4),%eax imull %esi,%eax sarl $8,%eax cmpl $0x7FFF,%eax jg LClampHigh cmpl $0xFFFF8000,%eax jnl LClampDone movl $0xFFFF8000,%eax jmp LClampDone LClampHigh: movl $0x7FFF,%eax LClampDone: // val = (snd_p[i+1]*snd_vol)>>8; // if (val > 0x7fff) // snd_out[i+1] = 0x7fff; // else if (val < (short)0x8000) // snd_out[i+1] = (short)0x8000; // else // snd_out[i+1] = val; movl -4(%ebx,%ecx,4),%edx imull %esi,%edx sarl $8,%edx cmpl $0x7FFF,%edx jg LClampHigh2 cmpl $0xFFFF8000,%edx jnl LClampDone2 movl $0xFFFF8000,%edx jmp LClampDone2 LClampHigh2: movl $0x7FFF,%edx LClampDone2: shll $16,%edx andl $0xFFFF,%eax orl %eax,%edx movl %edx,-4(%edi,%ecx,2) // } subl $2,%ecx jnz LWLBLoopTop // snd_p += snd_linear_count; popl %ebx popl %edi popl %esi ret #ifdef PIC .Lfe2: .size C(SND_WriteLinearBlastStereo16),.Lfe2-C(SND_WriteLinearBlastStereo16) #endif #endif // USE_INTEL_ASM