home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 4 Drivers
/
04-Drivers.zip
/
cs0929a.zip
/
stream.lst
< prev
next >
Wrap
File List
|
1999-09-29
|
81KB
|
2,174 lines
Module: D:\dev\csrc\os2dd\scd\stream.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
Segment: _TEXT PARA 00000661 bytes
//
// stream.c
// 27-Jan-99
//
// VOID streamReturnBuffer(STREAM *streamPtr);
// VOID streamReturnBuffers(STREAM *streamPtr);
// USHORT streamPauseTime(STREAM *streamPtr);
// USHORT streamResumeTime(STREAM *streamPtr);
// USHORT streamRegister(DDCMDREGISTER __far *cmdPtr, STREAM *streamPtr);
// VOID streamDeregister(STREAM *streamPtr);
// USHORT streamRead(UCHAR __far *bufferPtr, ULONG length, STREAM *streamPtr);
// USHORT streamWrite(UCHAR __far *bufferPtr, ULONG length, STREAM *streamPtr);
// USHORT streamInit(USHORT streamType, STREAM *streamPtr);
// USHORT streamDeinit(STREAM *streamPtr);
// STREAM *streamFindActive(USHORT streamType);
// STREAM *streamFindStreamSFN(ULONG SFN);
// STREAM *streamFindStreamHandle(HSTREAM streamH);
// STREAM_BUFFER *sbHead(STREAM_BUFFER_ANCHOR *sbaPtr);
// STREAM_BUFFER *sbTail(STREAM_BUFFER_ANCHOR *sbaPtr);
// VOID sbPushOnHead(STREAM_BUFFER *sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr);
// VOID sbPushOnTail(STREAM_BUFFER *sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr);
// STREAM_BUFFER *sbPopHead(STREAM_BUFFER_ANCHOR *sbaPtr);
// STREAM_BUFFER *sbPopTail(STREAM_BUFFER_ANCHOR *sbaPtr);
// USHORT sbDestroyElement(STREAM_BUFFER *sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr);
// STREAM_BUFFER *sbPopElement(STREAM_BUFFER *match_sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr);
// USHORT sbNotEmpty(STREAM_BUFFER_ANCHOR *sbaPtr);
// STREAM *streamHead(VOID);
// STREAM *streamTail(VOID);
// VOID streamPushOnHead(STREAM *sPtr);
// VOID streamPushOnTail(STREAM *sPtr);
// STREAM *streamPopHead(VOID);
// STREAM *streamPopTail(VOID);
// USHORT streamDestroyElement(STREAM *sPtr);
// STREAM *streamPopElement(STREAM *match_sPtr);
// USHORT streamNotEmpty(VOID);
//
// to init queue set headPtr/tailPtr = 0
// which is accomplished by simply MEMSET()'ing the allocation
// ie, the contructor (doesn't seem to be a destructor for the QUEUE class)
//
// ----------------------------------------- NOTE -------------------------------------------
// the following event-support routines are not yet done (stubs, all now have STREAM * as parm)
// parm list subject change (:
//
//VOID streamProcessEvents(STREAM *streamPtr) ;
//VOID streamEnableEvent(DDCMDCONTROL __far *ddcmdPtr, STREAM *streamPtr);
//VOID streamDisableEvent(DDCMDCONTROL __far *ddcmdPtr, STREAM *streamPtr);
//VOID streamSetNextEvent(STREAM *streamPtr);
#include "cs40.h"
static STREAM_ANCHOR streamList = {0,0}; // head of list (has .headPtr and .tailPtr to STREAM structures)
// ---------------------------------------------------------------------
// in: streamPtr -> stream from which to remove head buffer of done list
//out: n/a
//nts: frees stream buffer that was at head of done list
VOID streamReturnBuffer(STREAM *streamPtr) {
static SHD_REPORTINT shdri = {SHD_REPORT_INT,0,0,0,0,0}; // structure to return buffers to SHD
0000 streamReturnBuffer_:
0000 53 push bx
0001 51 push cx
0002 52 push dx
0003 56 push si
0004 57 push di
0005 89 c6 mov si,ax
STREAM_BUFFER *tsbPtr = sbPopHead(&streamPtr->sbaDone); // was STREAM_BUFFER *tsbPtr = (PSTREAMBUFFER)qhDone.PopHead();
// !!!
//ddprintf("@streamReturnBuffer, streamPtr=%x\n",streamPtr);
0007 8d 7c 14 lea di,[si+14H]
000a 8b 1d mov bx,[di]
000c 85 db test bx,bx
000e 74 0f je L2
0010 8b 07 mov ax,[bx]
0012 89 05 mov [di],ax
0014 85 c0 test ax,ax
0016 75 03 jne L1
0018 89 45 02 mov [di+2H],ax
001b c7 07 00 00 L1 mov word ptr [bx],0000H
001f 89 df L2 mov di,bx
if (tsbPtr) {
0021 85 db test bx,bx
0023 74 6a je L5
if (streamPtr->streamType & STREAM_WRITE) {
// this is a write (playback): tell stream handler that we played all of the buffer
0025 f6 44 1c 01 test byte ptr [si+1cH],01H
0029 74 15 je L3
shdri.ulFlag = SHD_WRITE_COMPLETE;
002b ba 02 00 mov dx,0002H
002e 31 c9 xor cx,cx
0030 89 16 10 00 mov L84,dx
0034 89 0e 12 00 mov L85,cx
shdri.ulStatus = tsbPtr->bufferSize;
}
0038 8b 57 08 mov dx,[bx+8H]
003b 8b 47 0a mov ax,[bx+0aH]
else {
// this is a capture: tell stream hamdler how much data we wrote to the buffer
003e eb 12 jmp L4
shdri.ulFlag = SHD_READ_COMPLETE;
0040 b9 01 00 L3 mov cx,0001H
0043 31 c0 xor ax,ax
0045 89 0e 10 00 mov L84,cx
0049 a3 12 00 mov L85,ax
shdri.ulStatus = tsbPtr->bufferCurrPos;
}
004c 8b 57 0c mov dx,[bx+0cH]
004f 8b 47 0e mov ax,[bx+0eH]
0052 89 16 14 00 L4 mov L86,dx
0056 a3 16 00 mov L87,ax
shdri.hStream = streamPtr->streamH;
0059 8b 54 04 mov dx,[si+4H]
005c 8b 44 06 mov ax,[si+6H]
005f 89 16 08 00 mov L80,dx
0063 a3 0a 00 mov L81,ax
shdri.pBuffer = tsbPtr->bufferPtr;
// wavestreamGetCurrentTime() needs to access stream's parent WAVESTREAM structure --
// this is the only case (so far) where a stream operation needs to look at what's
// in WAVSTREAM (specifically, abPtr, needed by this get time call) -- had to add
// this member to the STREAM structure (1-Feb-99), and set it up in streamInit(),
// which is called by wavestreamInit() (WAVESTREAM constructor) by IoctlAudioInit()...
// ugh, the driver docs just plain suck
0066 8b 55 04 mov dx,[di+4H]
0069 8b 45 06 mov ax,[di+6H]
006c 89 16 0c 00 mov L82,dx
0070 a3 0e 00 mov L83,ax
shdri.ulStreamTime = wavestreamGetCurrentTime(streamPtr->wsParentPtr);
#ifdef TRACE_RETBUFFER
tracePerf(TRACE_RETBUFFER_IN, _IF());
#endif
0073 8b 44 24 mov ax,[si+24H]
0076 e8 00 00 call wavestreamGetCurrentTime_
streamPtr->pfnSHD(&shdri); // function call
#ifdef TRACE_RETBUFFER
tracePerf(TRACE_RETBUFFER_OUT,_IF());
#endif
0079 1e push ds
007a a3 18 00 mov L88,ax
007d 68 04 00 push offset L79
0080 89 16 1a 00 mov L89,dx
0084 ff 5c 08 call dword ptr [si+8H]
0087 83 c4 04 add sp,0004H
free(tsbPtr); // this is what lots and lots of allocations come from
// !!!
//ddprintf("~streamReturnBuffer:free:%x\n",tsbPtr);
}
return;
008a 89 f8 mov ax,di
008c e8 00 00 call free_
}
// --------------------------------------------------------
// in: streamPtr -> stream from which to remove head buffer
//out: n/a
//nts: returns (and frees) all stream buffers
008f 5f L5 pop di
0090 5e pop si
0091 5a pop dx
0092 59 pop cx
0093 5b pop bx
0094 c3 ret
0095 89 c0 mov ax,ax
0097 fc cld
VOID streamReturnBuffers(STREAM *streamPtr) {
STREAM_BUFFER *tsbPtr;
0098 streamReturnBuffers_:
0098 53 push bx
0099 51 push cx
009a 52 push dx
009b 56 push si
009c 57 push di
009d 89 c2 mov dx,ax
009f 89 c1 mov cx,ax
00a1 89 c6 mov si,ax
00a3 83 c1 14 add cx,0014H
00a6 83 c6 10 add si,0010H
while(sbNotEmpty(&streamPtr->sbaProc)) { // likely gets inlined so use sbNotEmpty()
tsbPtr = sbPopHead(&streamPtr->sbaProc); // rather than sbPopHead() until it returns 0
sbPushOnTail(tsbPtr, &streamPtr->sbaDone); // pop from proc list and push on done list since...
}
00a9 8b 3c L6 mov di,[si]
00ab 31 db xor bx,bx
00ad 85 ff test di,di
00af 74 03 je L7
00b1 bb 01 00 mov bx,0001H
00b4 85 db L7 test bx,bx
00b6 74 33 je L11
00b8 8b 1c mov bx,[si]
00ba 85 db test bx,bx
00bc 74 0f je L9
00be 8b 07 mov ax,[bx]
00c0 89 04 mov [si],ax
00c2 85 c0 test ax,ax
00c4 75 03 jne L8
00c6 89 44 02 mov [si+2H],ax
00c9 c7 07 00 00 L8 mov word ptr [bx],0000H
00cd 89 cf L9 mov di,cx
00cf c7 07 00 00 mov word ptr [bx],0000H
00d3 83 3d 00 cmp word ptr [di],0000H
00d6 75 07 jne L10
00d8 89 1d mov [di],bx
00da 89 5d 02 mov [di+2H],bx
00dd eb ca jmp L6
00df 8b 7d 02 L10 mov di,[di+2H]
00e2 89 1d mov [di],bx
00e4 89 cf mov di,cx
00e6 89 5d 02 mov [di+2H],bx
00e9 eb be jmp L6
while(sbNotEmpty(&streamPtr->sbaDone)) { // stream buffers were moved to the done list
00eb 89 d6 L11 mov si,dx
00ed 83 c6 14 add si,0014H
00f0 31 c9 xor cx,cx
00f2 8b 3c L12 mov di,[si]
00f4 89 cb mov bx,cx
00f6 39 f9 cmp cx,di
00f8 74 03 je L13
00fa bb 01 00 mov bx,0001H
00fd 85 db L13 test bx,bx
00ff 74 8e je L5
streamReturnBuffer(streamPtr); // because that's what streamReturnBuffer() uses
0101 89 d0 mov ax,dx
0103 e8 00 00 call streamReturnBuffer_
} // namely, the head of the done list
return;
}
// ---------------------------------------------------
// in: streamPtr -> stream to pause/resume time counter
//out: always 0, for okay
//nts: returns USHORT though caller (ssm_idc.c) expects ULONG to return back to MMPM
0106 eb ea jmp L12
USHORT streamPauseTime(STREAM *streamPtr) {
0108 streamPauseTime_:
0108 53 push bx
0109 89 c3 mov bx,ax
streamPtr->counterIncFlag = 0;
return 0;
010b c6 47 1f 00 mov byte ptr [bx+1fH],00H
}
010f 31 c0 xor ax,ax
0111 5b pop bx
0112 c3 ret
0113 fc cld
USHORT streamResumeTime(STREAM *streamPtr) {
0114 streamResumeTime_:
0114 53 push bx
0115 89 c3 mov bx,ax
streamPtr->counterIncFlag = 1;
return 0;
0117 c6 47 1f 01 mov byte ptr [bx+1fH],01H
}
// ---------------------------------------------------
// in: cmdPtr -> DDCMDREGISTER pack (far ptr)
// streamPtr -> stream working on
//out: always 0, for okay
//nts: returns USHORT though caller (ssm_idc.c) expects ULONG to return back to MMPM
//
// ulBufSize: Specifies VSD or PDD output buffer size in bytes that will be sent to
// the driver. The caller will fill in a default value. If the device driver
// does not override this value, it will be used to determine the buffer size.
//
// Note: The device driver sets this field to indicate the buffer size that it would like to
// receive from the streaming subsystem. For MIDI, this field is usually set to 512. For DMA-based
// audio or other systems where the interrupt rate equals the buffer rate, this field should
// be set to about 1/30 the quantity of data consumed or produced per second. This field supplies
// the system with a minimal buffer size for wave audio. Because other system elements also
// negotiate to determine buffer size and for software motion video, the system might provide
// buffers smaller than the size requested.
011b 31 c0 xor ax,ax
011d 5b pop bx
011e c3 ret
011f fc cld
USHORT streamRegister(DDCMDREGISTER __far *cmdPtr, STREAM *streamPtr) {
0120 56 streamRegister_ push si
0121 89 c6 mov si,ax
0123 8e c2 mov es,dx
streamPtr->streamH = cmdPtr->hStream;
0125 26 8b 44 04 mov ax,es:[si+4H]
0129 26 8b 54 06 mov dx,es:[si+6H]
012d 89 47 04 mov [bx+4H],ax
0130 89 57 06 mov [bx+6H],dx
streamPtr->pfnSHD = (T_PFNSHD) cmdPtr->pSHDEntryPoint; // need cast since using a __cdecl cc
0133 26 8b 44 0c mov ax,es:[si+0cH]
0137 26 8b 54 0e mov dx,es:[si+0eH]
013b 89 47 08 mov [bx+8H],ax
013e 89 57 0a mov [bx+0aH],dx
cmdPtr->ulAddressType = ADDRESS_TYPE_VIRTUAL; // type of buffer pointer want to get from SSM
0141 26 c7 44 28 00 00 mov word ptr es:[si+28H],0000H
0147 26 c7 44 2a 00 00 mov word ptr es:[si+2aH],0000H
cmdPtr->mmtimePerUnit = 0; // not used
014d 26 c7 44 30 00 00 mov word ptr es:[si+30H],0000H
0153 26 c7 44 32 00 00 mov word ptr es:[si+32H],0000H
cmdPtr->ulBytesPerUnit = 0; // not used
// suggestions:
0159 26 c7 44 2c 00 00 mov word ptr es:[si+2cH],0000H
015f 26 c7 44 2e 00 00 mov word ptr es:[si+2eH],0000H
cmdPtr->ulNumBufs = 0x00000006; // 6 default buffers, at 60K each, is about 2 secs
0165 26 c7 44 24 06 00 mov word ptr es:[si+24H],0006H
016b 26 c7 44 26 00 00 mov word ptr es:[si+26H],0000H
cmdPtr->ulBufSize = 0x0000F000; // see Note above
return 0;
0171 26 c7 44 20 00 f0 mov word ptr es:[si+20H],0f000H
0177 26 c7 44 22 00 00 mov word ptr es:[si+22H],0000H
}
// ---------------------------------------------------
// in: streamPtr -> stream to deregister
//out: n/a
//nts:
017d 31 c0 xor ax,ax
017f 5e pop si
0180 c3 ret
0181 89 c0 mov ax,ax
0183 fc cld
VOID streamDeregister(STREAM *streamPtr) {
0184 streamDeregister_:
0184 53 push bx
0185 89 c3 mov bx,ax
streamPtr->streamH = 0;
0187 c7 47 04 00 00 mov word ptr [bx+4H],0000H
018c c7 47 06 00 00 mov word ptr [bx+6H],0000H
streamPtr->pfnSHD = 0;
return;
0191 c7 47 08 00 00 mov word ptr [bx+8H],0000H
0196 c7 47 0a 00 00 mov word ptr [bx+0aH],0000H
}
// ---------------------------------------------
// in: bufferPtr -> stream buffer data (far ptr)
// bufferSize = size of empty buffer (passed down as ULONG from kernel, org was short)
// wsPtr -> WAVESTREAM structure
//out: 0 if okay, else rc (no memory, eg)
//nts: called by DDCMD_READ
// original was getting length as "unsigned" as in USHORT
// similar to streamWrite()
// was called Read(), was also in wavestrm.c but why? so moved here, to stream.c
// (when it was in wavestrm.c, it was using &wsPtr->streamPtr->sbaProc... otherwise same)
019b 5b pop bx
019c c3 ret
019d 89 c0 mov ax,ax
019f fc cld
USHORT streamRead(UCHAR __far *bufferPtr, ULONG length, STREAM *streamPtr) {
USHORT rc = 0;
01a0 56 streamRead_ push si
01a1 57 push di
01a2 55 push bp
01a3 89 e5 mov bp,sp
01a5 83 ec 02 sub sp,0002H
01a8 89 c6 mov si,ax
01aa 89 d7 mov di,dx
01ac 89 5e fe mov [bp-2H],bx
01af b8 14 00 mov ax,0014H
01b2 e8 00 00 call malloc_
STREAM_BUFFER *newsbPtr = malloc(sizeof(STREAM_BUFFER));
// !!!
//ddprintf("@streamRead:newsbPtr=%x\n",newsbPtr);
01b5 31 d2 xor dx,dx
01b7 89 c3 mov bx,ax
if (newsbPtr) {
01b9 85 c0 test ax,ax
01bb 74 40 je L15
newsbPtr->nextPtr = 0;
01bd 89 17 mov [bx],dx
newsbPtr->rsv2 = 0;
01bf 89 57 02 mov [bx+2H],dx
newsbPtr->bufferPtr = bufferPtr;
newsbPtr->bufferSize = length;
01c2 89 77 04 mov [bx+4H],si
01c5 89 7f 06 mov [bx+6H],di
01c8 89 4f 0a mov [bx+0aH],cx
newsbPtr->bufferCurrPos = 0;
01cb 89 57 0c mov [bx+0cH],dx
01ce 89 57 0e mov [bx+0eH],dx
newsbPtr->bufferDonePos = 0;
01d1 89 57 10 mov [bx+10H],dx
01d4 89 57 12 mov [bx+12H],dx
01d7 8b 76 fe mov si,[bp-2H]
01da 89 77 08 mov [bx+8H],si
sbPushOnTail(newsbPtr, &streamPtr->sbaProc);
}
else {
01dd 8b 76 08 mov si,[bp+8H]
01e0 89 17 mov [bx],dx
01e2 8b 4c 10 mov cx,[si+10H]
01e5 83 c6 10 add si,0010H
01e8 85 c9 test cx,cx
01ea 75 07 jne L14
01ec 89 04 mov [si],ax
01ee 89 44 02 mov [si+2H],ax
01f1 eb 0d jmp L16
01f3 8b 7c 02 L14 mov di,[si+2H]
01f6 89 05 mov [di],ax
01f8 89 44 02 mov [si+2H],ax
01fb eb 03 jmp L16
rc = 8;
}
return rc;
01fd ba 08 00 L15 mov dx,0008H
}
// ---------------------------------------------------
// in: bufferPtr -> streaming buffer to add
// length = size of streaming buffer to add
// streamPtr -> stream to add stream buffer to
//out: 0 if okay, else rc (no memory, eg)
//nts: original was getting length as "unsigned" as in USHORT
// org was also always in stream.c, unlike Read() which was in wavestrm.c
0200 89 d0 L16 mov ax,dx
0202 89 ec mov sp,bp
0204 5d pop bp
0205 5f pop di
0206 5e pop si
0207 c2 02 00 ret 0002H
020a 89 c0 mov ax,ax
USHORT streamWrite(UCHAR __far *bufferPtr, ULONG length, STREAM *streamPtr) {
USHORT rc = 0;
020c 56 streamWrite_ push si
020d 57 push di
020e 55 push bp
020f 89 e5 mov bp,sp
0211 83 ec 02 sub sp,0002H
0214 89 c6 mov si,ax
0216 89 d7 mov di,dx
0218 89 5e fe mov [bp-2H],bx
021b b8 14 00 mov ax,0014H
021e e8 00 00 call malloc_
STREAM_BUFFER *newsbPtr = malloc(sizeof(STREAM_BUFFER));
// !!!
//ddprintf("@streamWrite:newsbPtr=%x\n",newsbPtr);
0221 31 d2 xor dx,dx
0223 89 c3 mov bx,ax
if (newsbPtr) {
0225 85 c0 test ax,ax
0227 74 40 je L18
newsbPtr->nextPtr = 0;
0229 89 17 mov [bx],dx
newsbPtr->rsv2 = 0;
022b 89 57 02 mov [bx+2H],dx
newsbPtr->bufferPtr = bufferPtr;
newsbPtr->bufferSize = length;
022e 89 77 04 mov [bx+4H],si
0231 89 7f 06 mov [bx+6H],di
0234 89 4f 0a mov [bx+0aH],cx
newsbPtr->bufferCurrPos = 0;
0237 89 57 0c mov [bx+0cH],dx
023a 89 57 0e mov [bx+0eH],dx
newsbPtr->bufferDonePos = 0;
023d 89 57 10 mov [bx+10H],dx
0240 89 57 12 mov [bx+12H],dx
0243 8b 76 fe mov si,[bp-2H]
0246 89 77 08 mov [bx+8H],si
sbPushOnTail(newsbPtr, &streamPtr->sbaProc);
}
else {
0249 8b 76 08 mov si,[bp+8H]
024c 89 17 mov [bx],dx
024e 8b 4c 10 mov cx,[si+10H]
0251 83 c6 10 add si,0010H
0254 85 c9 test cx,cx
0256 75 07 jne L17
0258 89 04 mov [si],ax
025a 89 44 02 mov [si+2H],ax
025d eb 0d jmp L19
025f 8b 7c 02 L17 mov di,[si+2H]
0262 89 05 mov [di],ax
0264 89 44 02 mov [si+2H],ax
0267 eb 03 jmp L19
rc = 8;
}
return rc;
0269 ba 08 00 L18 mov dx,0008H
}
// ---------------------------------------------------
// in: streamType = eg, STREAM_WAVE_CAPTURE (==AUDIOHW_WAVE_CAPTURE)(org ULONG)
// streamPtr -> stream structure
//out: always 0 for now
//nts:
//
// actually, STREAM constructor is called as part of WAVESTREAM constructor (STREAM
// constructor is done first, though) so this (streamInit()) will be called by
// wavestreamInit()...
026c 89 d0 L19 mov ax,dx
026e 89 ec mov sp,bp
0270 5d pop bp
0271 5f pop di
0272 5e pop si
0273 c2 02 00 ret 0002H
0276 89 c0 mov ax,ax
USHORT streamInit(USHORT streamType, STREAM *streamPtr) {
0278 53 streamInit_ push bx
0279 56 push si
027a 89 d3 mov bx,dx
027c 8b 16 00 00 mov dx,_streamList
streamPushOnTail(streamPtr);
streamPtr->streamType = streamType;
// already have verified that streamType is a supported type in IOCtl audio init
// so ahwPtr will be valid (so don't need to check here)
0280 c7 07 00 00 mov word ptr [bx],0000H
0284 85 d2 test dx,dx
0286 75 0a jne L20
0288 89 1e 00 00 mov _streamList,bx
028c 89 1e 02 00 mov _streamList+2H,bx
0290 eb 0a jmp L21
0292 8b 36 02 00 L20 mov si,_streamList+2H
0296 89 1e 02 00 mov _streamList+2H,bx
029a 89 1c mov [si],bx
streamPtr->streamH = 0; // ensure won't match yet on FindStream()
029c c7 47 04 00 00 L21 mov word ptr [bx+4H],0000H
02a1 c7 47 06 00 00 mov word ptr [bx+6H],0000H
streamPtr->SFN = 0; // ditto (since these are not yet operational streams)
02a6 c7 47 0c 00 00 mov word ptr [bx+0cH],0000H
streamPtr->counterIncFlag = 1;
02ab c6 47 1f 01 mov byte ptr [bx+1fH],01H
streamPtr->currentTime = 0; // this is updated when DDCMD_STATUS gotten
02af c7 47 20 00 00 mov word ptr [bx+20H],0000H
02b4 c7 47 22 00 00 mov word ptr [bx+22H],0000H
streamPtr->streamState = STREAM_STOPPED;
return 0;
02b9 c6 47 1e 00 mov byte ptr [bx+1eH],00H
02bd 89 47 1c mov [bx+1cH],ax
}
// ---------------------------------------------------
// in: streamPtr -> stream structure
//out: always 0 for now
//nts: stream destructor (does not free(streamPtr) though...that's done in wavestreamDeinit)
02c0 31 c0 xor ax,ax
02c2 5e pop si
02c3 5b pop bx
02c4 c3 ret
02c5 89 c0 mov ax,ax
02c7 fc cld
USHORT streamDeinit(STREAM *streamPtr) {
USHORT rc = 0;
STREAM_BUFFER *tsbPtr;
02c8 53 streamDeinit_ push bx
02c9 51 push cx
02ca 52 push dx
02cb 56 push si
02cc 57 push di
02cd 89 c7 mov di,ax
if (streamPtr->streamState == STREAM_STREAMING) {
// this has been replaced...
// streamPtr->wsParentPtr->waPtr->ahwPtr->xStop(); // yipes, talk about an indirect function call
// by this:
02cf 8a 45 1e mov al,[di+1eH]
02d2 30 e4 xor ah,ah
02d4 3d 01 00 cmp ax,0001H
02d7 75 18 jne L23
if (streamPtr->wsParentPtr->waPtr->devType == AUDIOHW_WAVE_PLAY) {
02d9 8b 5d 24 mov bx,[di+24H]
02dc 8b 77 02 mov si,[bx+2H]
02df 83 7c 02 11 cmp word ptr [si+2H],0011H
02e3 75 07 jne L22
rc = waveplayStop(streamPtr->wsParentPtr);
}
02e5 89 d8 mov ax,bx
02e7 e8 00 00 call waveplayStop_
else {
02ea eb 05 jmp L23
rc = waverecStop(streamPtr->wsParentPtr);
}
}
// destroy all stream buffers and events still associated with this stream
02ec 89 d8 L22 mov ax,bx
02ee e8 00 00 call waverecStop_
while(sbNotEmpty(&streamPtr->sbaProc)) {
tsbPtr = sbHead(&streamPtr->sbaProc);
02f1 8d 75 10 L23 lea si,[di+10H]
02f4 31 c9 xor cx,cx
02f6 8b 1c L24 mov bx,[si]
02f8 89 c8 mov ax,cx
02fa 39 d9 cmp cx,bx
02fc 74 03 je L25
02fe b8 01 00 mov ax,0001H
0301 85 c0 L25 test ax,ax
0303 74 14 je L26
0305 8b 1c mov bx,[si]
sbDestroyElement(tsbPtr, &streamPtr->sbaProc);
}
0307 89 f2 mov dx,si
0309 89 d8 mov ax,bx
030b e8 00 00 call sbPopElement_
030e 85 c0 test ax,ax
0310 74 e4 je L24
0312 89 d8 mov ax,bx
0314 e8 00 00 call free_
0317 eb dd jmp L24
while(sbNotEmpty(&streamPtr->sbaDone)) {
tsbPtr = sbHead(&streamPtr->sbaDone);
0319 8d 75 14 L26 lea si,[di+14H]
031c 31 c9 xor cx,cx
031e 8b 14 L27 mov dx,[si]
0320 89 c8 mov ax,cx
0322 39 d1 cmp cx,dx
0324 74 03 je L28
0326 b8 01 00 mov ax,0001H
0329 85 c0 L28 test ax,ax
032b 74 14 je L29
032d 8b 1c mov bx,[si]
sbDestroyElement(tsbPtr, &streamPtr->sbaDone);
}
// can do this event processing code now since won't do anything (always empty for now)
032f 89 f2 mov dx,si
0331 89 d8 mov ax,bx
0333 e8 00 00 call sbPopElement_
0336 85 c0 test ax,ax
0338 74 e4 je L27
033a 89 d8 mov ax,bx
033c e8 00 00 call free_
033f eb dd jmp L27
while(sbNotEmpty(&streamPtr->sbaEvent)) {
tsbPtr = sbHead(&streamPtr->sbaEvent);
0341 8d 75 18 L29 lea si,[di+18H]
0344 31 c9 xor cx,cx
0346 8b 04 L30 mov ax,[si]
0348 89 cb mov bx,cx
034a 39 c1 cmp cx,ax
034c 74 03 je L31
034e bb 01 00 mov bx,0001H
0351 85 db L31 test bx,bx
0353 74 14 je L32
0355 8b 1c mov bx,[si]
sbDestroyElement(tsbPtr, &streamPtr->sbaEvent);
}
0357 89 f2 mov dx,si
0359 89 d8 mov ax,bx
035b e8 00 00 call sbPopElement_
035e 85 c0 test ax,ax
0360 74 e4 je L30
0362 89 d8 mov ax,bx
0364 e8 00 00 call free_
0367 eb dd jmp L30
streamPopElement(streamPtr); // remove this stream from list
return 0;
0369 89 f8 L32 mov ax,di
036b e8 00 00 call streamPopElement_
}
// ---------------------------------------------------
// in: streamType (was ULONG)
//out: streamPtr -> active stream
//nts: finds first active stream of matching type
036e 31 c0 xor ax,ax
0370 5f pop di
0371 5e pop si
0372 5a pop dx
0373 59 pop cx
0374 5b pop bx
0375 c3 ret
0376 89 c0 mov ax,ax
STREAM *streamFindActive(USHORT streamType) {
0378 streamFindActive_:
0378 53 push bx
0379 52 push dx
037a 89 c2 mov dx,ax
STREAM *streamPtr = streamList.headPtr;
while (streamPtr) {
037c 8b 1e 00 00 mov bx,_streamList
0380 85 db test bx,bx
0382 74 15 je L35
if (streamPtr->streamType == streamType && streamPtr->streamState == STREAM_STREAMING) break;
0384 3b 57 1c L33 cmp dx,[bx+1cH]
0387 75 0a jne L34
0389 8a 47 1e mov al,[bx+1eH]
038c 30 e4 xor ah,ah
038e 3d 01 00 cmp ax,0001H
0391 74 06 je L35
streamPtr = streamPtr->nextPtr;
0393 8b 1f L34 mov bx,[bx]
}
return streamPtr;
0395 85 db test bx,bx
0397 75 eb jne L33
}
// ---------------------------------------------------
// in: SFN (was ULONG)
//out: streamPtr -> stream with this SFN
//nts: map SFN to stream object
0399 89 d8 L35 mov ax,bx
039b 5a pop dx
039c 5b pop bx
039d c3 ret
039e 89 c0 mov ax,ax
STREAM *streamFindStreamSFN(USHORT SFN) {
03a0 streamFindStreamSFN_:
03a0 53 push bx
STREAM *streamPtr = streamList.headPtr;
while (streamPtr) {
03a1 8b 1e 00 00 mov bx,_streamList
03a5 85 db test bx,bx
03a7 74 0b je L37
if (streamPtr->SFN == SFN) break;
03a9 3b 47 0c L36 cmp ax,[bx+0cH]
03ac 74 06 je L37
streamPtr = streamPtr->nextPtr;
03ae 8b 1f mov bx,[bx]
}
return streamPtr;
03b0 85 db test bx,bx
03b2 75 f5 jne L36
}
// ---------------------------------------------------
// in: streamH
//out: streamPtr -> stream with this handle
//nts: map stream handle to stream object
03b4 89 d8 L37 mov ax,bx
03b6 5b pop bx
03b7 c3 ret
STREAM *streamFindStreamHandle(HSTREAM streamH) {
03b8 streamFindStreamHandle_:
03b8 53 push bx
03b9 51 push cx
03ba 56 push si
STREAM *streamPtr = streamList.headPtr;
while (streamPtr) {
03bb 8b 1e 00 00 mov bx,_streamList
03bf 85 db test bx,bx
03c1 74 14 je L40
if (streamPtr->streamH == streamH) break;
03c3 8b 4f 06 L38 mov cx,[bx+6H]
03c6 8b 77 04 mov si,[bx+4H]
03c9 39 ca cmp dx,cx
03cb 75 04 jne L39
03cd 39 f0 cmp ax,si
03cf 74 06 je L40
streamPtr = streamPtr->nextPtr;
03d1 8b 1f L39 mov bx,[bx]
}
return streamPtr;
03d3 85 db test bx,bx
03d5 75 ec jne L38
}
// -----------------------------------------------------------------------------
// Queue support for STREAM_BUFFER objects (STREAM objects follows this, below)
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// in: streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: stream_buffer pointer -> head
//nts: sort of like PopHead() but doesn't remove head
//
// eg,
// STREAM_BUFFER *DoneHeadPtr = sbHead(&streamPtr->sbaDone);
03d7 89 d8 L40 mov ax,bx
03d9 5e pop si
03da 59 pop cx
03db 5b pop bx
03dc c3 ret
03dd 89 c0 mov ax,ax
03df fc cld
STREAM_BUFFER *sbHead(STREAM_BUFFER_ANCHOR *sbaPtr) {
03e0 53 sbHead_ push bx
03e1 89 c3 mov bx,ax
STREAM_BUFFER *tempPtr = sbaPtr->headPtr;
return tempPtr;
03e3 8b 07 mov ax,[bx]
}
// -------------------------------------------------------------------
// in: streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: stream_buffer pointer -> tail
//nts: sort of like PopTail() but doesn't remove tail
//
// eg,
// STREAM_BUFFER *DoneHeadPtr = sbTail(&streamPtr->sbaDone);
03e5 5b pop bx
03e6 c3 ret
03e7 fc cld
STREAM_BUFFER *sbTail(STREAM_BUFFER_ANCHOR *sbaPtr) {
03e8 53 sbTail_ push bx
03e9 89 c3 mov bx,ax
STREAM_BUFFER *tempPtr = sbaPtr->tailPtr;
return tempPtr;
03eb 8b 47 02 mov ax,[bx+2H]
}
// -----------------------------------------------------------------------------
// in: stream buffer ptr -> stream buffer item to put on head of queue
// streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: n/a
//nts:
//
// eg,
// sbPushOnHead(sbPtr, &streamPtr->sbaDone);
03ee 5b pop bx
03ef c3 ret
VOID sbPushOnHead(STREAM_BUFFER *sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr) {
03f0 53 sbPushOnHead_ push bx
03f1 56 push si
03f2 89 c3 mov bx,ax
03f4 89 d6 mov si,dx
if (sbaPtr->headPtr == 0) { // empty list so just put it on
03f6 8b 14 mov dx,[si]
03f8 85 d2 test dx,dx
03fa 75 0a jne L41
sbPtr->nextPtr = 0;
03fc 89 17 mov [bx],dx
sbaPtr->headPtr = sbPtr;
03fe 89 04 mov [si],ax
sbaPtr->tailPtr = sbPtr;
}
0400 89 44 02 mov [si+2H],ax
else {
0403 5e pop si
0404 5b pop bx
0405 c3 ret
sbPtr->nextPtr = sbaPtr->headPtr; // set buffer's nextPtr to current head
0406 89 17 L41 mov [bx],dx
sbaPtr->headPtr = sbPtr; // and make this buffer the new head
}
return;
0408 89 04 mov [si],ax
}
// -----------------------------------------------------------------------------
// in: stream buffer ptr -> stream buffer item to put on tail of queue
// streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: n/a
//nts:
//
// eg,
// sbPushOnTail(sbPtr, &streamPtr->sbaDone);
040a 5e pop si
040b 5b pop bx
040c c3 ret
040d 89 c0 mov ax,ax
040f fc cld
VOID sbPushOnTail(STREAM_BUFFER *sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr) {
0410 53 sbPushOnTail_ push bx
0411 56 push si
0412 57 push di
0413 89 c3 mov bx,ax
0415 89 d6 mov si,dx
sbPtr->nextPtr = 0;
0417 c7 07 00 00 mov word ptr [bx],0000H
if (sbaPtr->headPtr == 0) { // empty list so just put it on
041b 83 3c 00 cmp word ptr [si],0000H
041e 75 04 jne L42
sbaPtr->headPtr = sbPtr;
sbaPtr->tailPtr = sbPtr;
}
0420 89 04 mov [si],ax
else {
0422 eb 05 jmp L43
sbaPtr->tailPtr->nextPtr = sbPtr; // set current tail's nextPtr to new tail
0424 8b 7c 02 L42 mov di,[si+2H]
0427 89 05 mov [di],ax
sbaPtr->tailPtr = sbPtr; // and make this buffer the new tail
}
return;
0429 89 44 02 L43 mov [si+2H],ax
}
// -----------------------------------------------------------------------------
// in: streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: stream_buffer pointer -> what was at head of the queue
//nts:
//
// eg,
// STREAM_BUFFER *DoneHeadPtr = sbPopHead(&streamPtr->sbaDone);
042c 5f pop di
042d 5e pop si
042e 5b pop bx
042f c3 ret
STREAM_BUFFER *sbPopHead(STREAM_BUFFER_ANCHOR *sbaPtr) {
0430 53 sbPopHead_ push bx
0431 56 push si
0432 89 c3 mov bx,ax
STREAM_BUFFER *tempPtr = sbaPtr->headPtr;
0434 8b 37 mov si,[bx]
if (tempPtr) {
0436 85 f6 test si,si
0438 74 0f je L45
sbaPtr->headPtr = tempPtr->nextPtr;
043a 8b 04 mov ax,[si]
043c 89 07 mov [bx],ax
if (sbaPtr->headPtr == 0) sbaPtr->tailPtr = 0;
043e 85 c0 test ax,ax
0440 75 03 jne L44
0442 89 47 02 mov [bx+2H],ax
tempPtr->nextPtr = 0;
}
return tempPtr;
0445 c7 04 00 00 L44 mov word ptr [si],0000H
}
// -----------------------------------------------------------------------------
// in: streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: stream_buffer pointer -> what was at tail of the queue
//nts:
//
// eg,
// STREAM_BUFFER *DoneTailPtr = sbPopTail(&streamPtr->sbaDone);
0449 89 f0 L45 mov ax,si
044b 5e pop si
044c 5b pop bx
044d c3 ret
044e 89 c0 mov ax,ax
STREAM_BUFFER *sbPopTail(STREAM_BUFFER_ANCHOR *sbaPtr) {
0450 53 sbPopTail_ push bx
0451 52 push dx
0452 56 push si
0453 57 push di
0454 89 c7 mov di,ax
STREAM_BUFFER *tempPtr = sbaPtr->tailPtr;
0456 8b 75 02 mov si,[di+2H]
STREAM_BUFFER *temp2Ptr = sbaPtr->headPtr;
0459 8b 1d mov bx,[di]
if (tempPtr == temp2Ptr) {
// only one item in list, or it's empty
045b 39 de cmp si,bx
045d 75 13 jne L46
sbaPtr->headPtr = 0;
045f c7 05 00 00 mov word ptr [di],0000H
sbaPtr->tailPtr = 0;
0463 c7 45 02 00 00 mov word ptr [di+2H],0000H
if (tempPtr) tempPtr->nextPtr = 0; // set the old tail's nextPtr to 0
}
else {
0468 85 db test bx,bx
046a 74 27 je L51
046c c7 07 00 00 mov word ptr [bx],0000H
0470 eb 21 jmp L51
if (tempPtr) {
while (temp2Ptr->nextPtr != tempPtr) {
0472 85 f6 L46 test si,si
0474 74 1d je L51
0476 8b 17 L47 mov dx,[bx]
0478 39 d6 cmp si,dx
047a 74 04 je L48
temp2Ptr = temp2Ptr->nextPtr; // scan down list to just before tail
047c 89 d3 mov bx,dx
}
047e eb f6 jmp L47
sbaPtr->tailPtr = temp2Ptr; // set the new tail to be that one
0480 89 5d 02 L48 mov [di+2H],bx
if (sbaPtr->tailPtr == 0) { // hm, can this happen (seem like has to only
0483 85 db test bx,bx
0485 75 04 jne L49
sbaPtr->headPtr = 0; // have one item for it to, and that's covered above)
}
0487 89 1d mov [di],bx
else {
0489 eb 04 jmp L50
sbaPtr->tailPtr->nextPtr = 0; // mark new tail's nextPtr as 0 (since it's the tail!)
}
048b c7 07 00 00 L49 mov word ptr [bx],0000H
tempPtr->nextPtr = 0; // set the old tail's nextPtr to 0
}
}
return tempPtr;
048f c7 04 00 00 L50 mov word ptr [si],0000H
}
// -----------------------------------------------------------------------------
// in: sbPtr -> stream buffer to destroy
// streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: 1 if destroyed it, else not there
//nts: frees memory allocated at sbPtr
//
// eg,
// destroyedItFlag = sbDestroyElement(sbPtr, &streamPtr->sbaDone);
0493 89 f0 L51 mov ax,si
0495 5f pop di
0496 5e pop si
0497 5a pop dx
0498 5b pop bx
0499 c3 ret
049a 89 c0 mov ax,ax
USHORT sbDestroyElement(STREAM_BUFFER *sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr) {
USHORT rc = 0;
049c sbDestroyElement_:
049c 53 push bx
049d 51 push cx
049e 89 c3 mov bx,ax
if (sbPopElement(sbPtr,sbaPtr)) {
04a0 e8 00 00 call sbPopElement_
04a3 31 c9 xor cx,cx
04a5 85 c0 test ax,ax
04a7 74 08 je L52
free(sbPtr);
// !!!
//ddprintf("@sbDestroyElement:free:%x\n",sbPtr);
04a9 89 d8 mov ax,bx
rc = 1;
}
return rc;
04ab b9 01 00 mov cx,0001H
04ae e8 00 00 call free_
}
// -----------------------------------------------------------------------------
// in: match_sbPtr -> stream buffer to remove for queue (based on address)
// streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: returns match_sbPtr (same as entry) if found/removed, else 0 if not there
//nts: see below
//
// eg,
// sbPtr = sbPopElement(sbPtr, &streamPtr->sbaDone);
04b1 89 c8 L52 mov ax,cx
04b3 59 pop cx
04b4 5b pop bx
04b5 c3 ret
04b6 89 c0 mov ax,ax
STREAM_BUFFER *sbPopElement(STREAM_BUFFER *match_sbPtr, STREAM_BUFFER_ANCHOR *sbaPtr) {
STREAM_BUFFER *tempPtr = 0;
04b8 53 sbPopElement_ push bx
04b9 56 push si
04ba 89 c6 mov si,ax
04bc 89 d3 mov bx,dx
if (sbaPtr->headPtr == 0) { // empty queue
04be 8b 17 mov dx,[bx]
04c0 85 d2 test dx,dx
04c2 75 04 jne L53
return 0;
}
04c4 31 c6 xor si,ax
04c6 eb 42 jmp L59
if (match_sbPtr == sbaPtr->headPtr) { // if matches head, pop head
04c8 39 d0 L53 cmp ax,dx
04ca 75 18 jne L55
tempPtr = sbPopHead(sbaPtr);
return tempPtr;
}
04cc 85 d2 test dx,dx
04ce 74 3a je L59
04d0 8b 04 mov ax,[si]
04d2 89 07 mov [bx],ax
04d4 85 c0 test ax,ax
04d6 75 03 jne L54
04d8 89 47 02 mov [bx+2H],ax
04db c7 04 00 00 L54 mov word ptr [si],0000H
04df 89 f0 mov ax,si
04e1 5e pop si
04e2 5b pop bx
04e3 c3 ret
if (match_sbPtr == sbaPtr->tailPtr) { // if matches tail, pop tail
04e4 3b 47 02 L55 cmp ax,[bx+2H]
04e7 75 0c jne L56
tempPtr = sbPopTail(sbaPtr);
return tempPtr;
}
// this next section scans items, check the nextPtrs of each -- when a nextPtr points
// to the match_sbPtr it's known that the item is there, so set that nextPtr to point
// to the item's nextPtr rather than the item itself (item is match_sbPtr in this case)
// effectively removing the item from the list
04e9 89 d8 mov ax,bx
04eb e8 00 00 call sbPopTail_
04ee 89 c6 mov si,ax
04f0 89 f0 mov ax,si
04f2 5e pop si
04f3 5b pop bx
04f4 c3 ret
tempPtr = sbaPtr->headPtr;
04f5 89 d3 L56 mov bx,dx
04f7 3b 37 cmp si,[bx]
04f9 74 0b je L58
while (tempPtr->nextPtr != match_sbPtr && tempPtr->nextPtr != 0) {
04fb 83 3f 00 L57 cmp word ptr [bx],0000H
04fe 74 06 je L58
tempPtr = tempPtr->nextPtr; // scan elements until find it in someone's nextPtr...
0500 8b 1f mov bx,[bx]
}
0502 3b 37 cmp si,[bx]
0504 75 f5 jne L57
if (tempPtr == 0) return 0; // not found at all
tempPtr->nextPtr = match_sbPtr->nextPtr; // now set links so the item is removed from the list
return match_sbPtr;
0506 8b 04 L58 mov ax,[si]
0508 89 07 mov [bx],ax
}
// -----------------------------------------------------------------------------
// in: streamBufferAnchorPtr -> queue anchor to either proc, done, or event queues
//out: 0 if the list is empty, otherwise 1
//nts: original returned a ULONG for some reason
//
// eg,
// notEmpty = sbNotEmpty(&streamPtr->sbaDone);
050a 89 f0 L59 mov ax,si
050c 5e pop si
050d 5b pop bx
050e c3 ret
050f fc cld
USHORT sbNotEmpty(STREAM_BUFFER_ANCHOR *sbaPtr) {
USHORT rc = 0;
0510 53 sbNotEmpty_ push bx
0511 52 push dx
0512 89 c3 mov bx,ax
if (sbaPtr->headPtr) rc = 1;
return rc;
0514 8b 17 mov dx,[bx]
0516 31 c0 xor ax,ax
0518 85 d2 test dx,dx
051a 74 03 je L60
051c b8 01 00 mov ax,0001H
}
// -------------------------------------
// to init queue set headPtr/tailPtr = 0
// which is accomplished by simply MEMSET()'ing the allocation
// ie, the contructor (doesn't seem to be a destructor for the QUEUE class)
// -----------------------------------------------------------------------------
// Queue support for STREAM objects
// -----------------------------------------------------------------------------
// note: unlike STREAM_BUFFER queue support, don't need to pass anchor pointer
// since it's known to be streamList
// -----------------------------------------------------------------------------
// in: n/a
//out: stream pointer -> head
//nts: sort of like PopHead() but doesn't remove head
//
// eg,
// STREAM *HeadPtr = streamHead();
051f 5a L60 pop dx
0520 5b pop bx
0521 c3 ret
0522 89 c0 mov ax,ax
STREAM *streamHead(VOID) {
STREAM *tempPtr = streamList.headPtr;
return tempPtr;
0524 a1 00 00 streamHead_ mov ax,_streamList
}
// -------------------------------------------------------------------
// in: n/a
//out: stream pointer -> tail
//nts: sort of like PopTail() but doesn't remove tail
//
// eg,
// STREAM *TailPtr = streamTail();
0527 c3 ret
STREAM *streamTail(VOID) {
STREAM *tempPtr = streamList.tailPtr;
return tempPtr;
0528 a1 02 00 streamTail_ mov ax,_streamList+2H
}
// -----------------------------------------------------------------------------
// in: stream ptr -> stream item to put on head of queue
//out: n/a
//nts:
//
// eg,
// streamPushOnHead(sPtr);
052b c3 ret
VOID streamPushOnHead(STREAM *sPtr) {
052c streamPushOnHead_:
052c 53 push bx
052d 52 push dx
052e 89 c3 mov bx,ax
if (streamList.headPtr == 0) { // empty list so just put it on
0530 8b 16 00 00 mov dx,_streamList
0534 85 d2 test dx,dx
0536 75 0b jne L61
sPtr->nextPtr = 0;
0538 89 17 mov [bx],dx
streamList.headPtr = sPtr;
053a a3 00 00 mov _streamList,ax
streamList.tailPtr = sPtr;
}
053d a3 02 00 mov _streamList+2H,ax
else {
0540 5a pop dx
0541 5b pop bx
0542 c3 ret
sPtr->nextPtr = streamList.headPtr; // set stream's nextPtr to current head
0543 89 17 L61 mov [bx],dx
streamList.headPtr = sPtr; // and make this buffer the new head
}
return;
0545 a3 00 00 mov _streamList,ax
}
// -----------------------------------------------------------------------------
// in: stream ptr -> stream item to put on tail of queue
//out: n/a
//nts:
//
// eg,
// streamPushOnTail(sPtr);
0548 5a pop dx
0549 5b pop bx
054a c3 ret
054b fc cld
VOID streamPushOnTail(STREAM *sPtr) {
sPtr->nextPtr = 0;
054c streamPushOnTail_:
054c 53 push bx
054d 52 push dx
054e 56 push si
054f 89 c3 mov bx,ax
0551 8b 16 00 00 mov dx,_streamList
if (streamList.headPtr == 0) { // empty list so just put it on
0555 c7 07 00 00 mov word ptr [bx],0000H
0559 85 d2 test dx,dx
055b 75 05 jne L62
streamList.headPtr = sPtr;
streamList.tailPtr = sPtr;
}
055d a3 00 00 mov _streamList,ax
else {
0560 eb 06 jmp L63
streamList.tailPtr->nextPtr = sPtr; // set current tail's nextPtr to new tail
0562 8b 36 02 00 L62 mov si,_streamList+2H
0566 89 04 mov [si],ax
streamList.tailPtr = sPtr; // and make this buffer the new tail
}
return;
0568 a3 02 00 L63 mov _streamList+2H,ax
}
// -----------------------------------------------------------------------------
// in: n/a
//out: stream pointer -> what was at head of the queue
//nts:
//
// eg,
// STREAM *HeadPtr = streamPopHead();
056b 5e pop si
056c 5a pop dx
056d 5b pop bx
056e c3 ret
056f fc cld
STREAM *streamPopHead(VOID) {
0570 53 streamPopHead_ push bx
STREAM *tempPtr = streamList.headPtr;
0571 8b 1e 00 00 mov bx,_streamList
if (tempPtr) {
0575 85 db test bx,bx
0577 74 10 je L65
streamList.headPtr = tempPtr->nextPtr;
0579 8b 07 mov ax,[bx]
057b a3 00 00 mov _streamList,ax
if (streamList.headPtr == 0) streamList.tailPtr = 0;
057e 85 c0 test ax,ax
0580 75 03 jne L64
0582 a3 02 00 mov _streamList+2H,ax
tempPtr->nextPtr = 0;
}
return tempPtr;
0585 c7 07 00 00 L64 mov word ptr [bx],0000H
}
// -----------------------------------------------------------------------------
// in: n/a
//out: stream pointer -> what was at tail of the queue
//nts:
//
// eg,
// STREAM *TailPtr = streamPopTail();
0589 89 d8 L65 mov ax,bx
058b 5b pop bx
058c c3 ret
058d 89 c0 mov ax,ax
058f fc cld
STREAM *streamPopTail(VOID) {
0590 53 streamPopTail_ push bx
0591 51 push cx
0592 52 push dx
0593 56 push si
0594 57 push di
STREAM *tempPtr = streamList.tailPtr;
0595 8b 36 02 00 mov si,_streamList+2H
STREAM *temp2Ptr = streamList.headPtr;
0599 8b 1e 00 00 mov bx,_streamList
if (tempPtr == temp2Ptr) {
// only one item in list, or it's empty
059d 39 de cmp si,bx
059f 75 12 jne L66
streamList.headPtr = 0;
05a1 31 d2 xor dx,dx
05a3 89 16 00 00 mov _streamList,dx
streamList.tailPtr = 0;
05a7 89 16 02 00 mov _streamList+2H,dx
if (tempPtr) tempPtr->nextPtr = 0; // set the old tail's nextPtr to 0
}
else {
05ab 85 db test bx,bx
05ad 74 1e je L69
05af 89 17 mov [bx],dx
05b1 eb 1a jmp L69
if (tempPtr) {
while (temp2Ptr->nextPtr != tempPtr) {
05b3 85 f6 L66 test si,si
05b5 74 16 je L69
05b7 8b 0f L67 mov cx,[bx]
05b9 39 ce cmp si,cx
05bb 74 04 je L68
temp2Ptr = temp2Ptr->nextPtr; // scan down list to just before tail
05bd 89 cb mov bx,cx
}
05bf eb f6 jmp L67
streamList.tailPtr = temp2Ptr; // set the new tail to be that one
if (streamList.tailPtr == 0) { // hm, can this happen (seem like has to only
streamList.headPtr = 0; // have one item for it to, and that's covered above)
}
else {
05c1 89 1e 02 00 L68 mov _streamList+2H,bx
streamList.tailPtr->nextPtr = 0; // mark new tail's nextPtr as 0 (since it's the tail!)
}
05c5 c7 07 00 00 mov word ptr [bx],0000H
tempPtr->nextPtr = 0; // set the old tail's nextPtr to 0
}
}
return tempPtr;
05c9 c7 04 00 00 mov word ptr [si],0000H
}
// -----------------------------------------------------------------------------
// in: sPtr -> stream to destroy
//out: 1 if destroyed it, else not there
//nts: frees memory allocated at sPtr
//
// eg,
// destroyedItFlag = streamDestroyElement(sPtr);
05cd 89 f0 L69 mov ax,si
05cf 5f pop di
05d0 5e pop si
05d1 5a pop dx
05d2 59 pop cx
05d3 5b pop bx
05d4 c3 ret
05d5 89 c0 mov ax,ax
05d7 fc cld
USHORT streamDestroyElement(STREAM *sPtr) {
USHORT rc = 0;
05d8 streamDestroyElement_:
05d8 53 push bx
05d9 52 push dx
05da 89 c2 mov dx,ax
if (streamPopElement(sPtr)) {
05dc e8 00 00 call streamPopElement_
05df 31 db xor bx,bx
05e1 85 c0 test ax,ax
05e3 74 08 je L70
free(sPtr);
// !!!
//ddprintf("@streamDestroyElement:free:%x\n",sPtr);
05e5 89 d0 mov ax,dx
rc = 1;
}
return rc;
05e7 bb 01 00 mov bx,0001H
05ea e8 00 00 call free_
}
// -----------------------------------------------------------------------------
// in: match_sPtr -> stream to remove for queue (based on address)
//out: returns match_sPtr (same as entry) if found/removed, else 0 if not there
//nts: see below
//
// eg,
// sPtr = streamPopElement(sPtr);
05ed 89 d8 L70 mov ax,bx
05ef 5a pop dx
05f0 5b pop bx
05f1 c3 ret
05f2 89 c0 mov ax,ax
STREAM *streamPopElement(STREAM *match_sPtr) {
STREAM *tempPtr = 0;
05f4 streamPopElement_:
05f4 53 push bx
05f5 52 push dx
05f6 56 push si
05f7 89 c6 mov si,ax
if (streamList.headPtr == 0) { // empty queue
05f9 8b 16 00 00 mov dx,_streamList
05fd 85 d2 test dx,dx
05ff 75 04 jne L71
return 0;
}
0601 31 c6 xor si,ax
0603 eb 44 jmp L77
if (match_sPtr == streamList.headPtr) { // if matches head, pop head
0605 39 d0 L71 cmp ax,dx
0607 75 1a jne L73
tempPtr = streamPopHead();
return tempPtr;
}
0609 85 d2 test dx,dx
060b 74 3c je L77
060d 8b 04 mov ax,[si]
060f a3 00 00 mov _streamList,ax
0612 85 c0 test ax,ax
0614 75 03 jne L72
0616 a3 02 00 mov _streamList+2H,ax
0619 c7 04 00 00 L72 mov word ptr [si],0000H
061d 89 f0 mov ax,si
061f 5e pop si
0620 5a pop dx
0621 5b pop bx
0622 c3 ret
if (match_sPtr == streamList.tailPtr) { // if matches tail, pop tail
0623 3b 06 02 00 L73 cmp ax,_streamList+2H
0627 75 0b jne L74
tempPtr = streamPopTail();
return tempPtr;
}
// this next section scans items, check the nextPtrs of each -- when a nextPtr points
// to the match_sPtr it's known that the item is there, so set that nextPtr to point
// to the item's nextPtr rather than the item itself (item is match_sPtr in this case)
// effectively removing the item from the list
0629 e8 00 00 call streamPopTail_
062c 89 c6 mov si,ax
062e 89 f0 mov ax,si
0630 5e pop si
0631 5a pop dx
0632 5b pop bx
0633 c3 ret
tempPtr = streamList.headPtr;
0634 89 d3 L74 mov bx,dx
0636 3b 07 cmp ax,[bx]
0638 74 0b je L76
while (tempPtr->nextPtr != match_sPtr && tempPtr->nextPtr != 0) {
063a 83 3f 00 L75 cmp word ptr [bx],0000H
063d 74 06 je L76
tempPtr = tempPtr->nextPtr; // scan elements until find it in someone's nextPtr...
063f 8b 1f mov bx,[bx]
}
0641 3b 37 cmp si,[bx]
0643 75 f5 jne L75
if (tempPtr == 0) return 0; // not found at all
tempPtr->nextPtr = match_sPtr->nextPtr; // now set links so the item is removed from the list
return match_sPtr;
0645 8b 04 L76 mov ax,[si]
0647 89 07 mov [bx],ax
}
// -----------------------------------------------------------------------------
// in: n/a
//out: 0 if the list is empty, otherwise 1
//nts: original returned a ULONG for some reason
//
// eg,
// notEmpty = streamNotEmpty();
0649 89 f0 L77 mov ax,si
064b 5e pop si
064c 5a pop dx
064d 5b pop bx
064e c3 ret
064f fc cld
USHORT streamNotEmpty(VOID) {
USHORT rc = 0;
0650 52 streamNotEmpty_ push dx
if (streamList.headPtr) rc = 1;
return rc;
0651 8b 16 00 00 mov dx,_streamList
0655 31 c0 xor ax,ax
0657 85 d2 test dx,dx
0659 74 03 je L78
065b b8 01 00 mov ax,0001H
}
// ---------------------------------
// in: streamPtr -> stream structure
//out:
//nts:
VOID streamProcessEvents(STREAM *streamPtr) {
return;
streamPtr;
}
// --------------------------------------
// in: ddcmdPtr -> DDCMDCONTROL structure (far ptr)
// streamPtr -> stream structure
//out:
//nts:
VOID streamEnableEvent(DDCMDCONTROL __far *ddcmdPtr, STREAM *streamPtr) {
return;
ddcmdPtr;
streamPtr;
}
// --------------------------------------
// in: ddcmdPtr -> DDCMDCONTROL structure (far ptr)
// streamPtr -> stream structure
//out:
//nts:
VOID streamDisableEvent(DDCMDCONTROL __far *ddcmdPtr, STREAM *streamPtr) {
return;
ddcmdPtr;
streamPtr;
}
// --------------------------------------
// in: streamPtr -> stream structure
//out:
//nts:
VOID streamSetNextEvent(STREAM *streamPtr) {
return;
streamPtr;
}
#if 0
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// the following event-support routines are not yet done
// void STREAM::ProcessEvents(void)
// ULONG STREAM::EnableEvent(PDDCMDCONTROL pControl)
// ULONG STREAM::DisableEvent(PDDCMDCONTROL pControl)
// void STREAM::SetNextEvent(void)
class EVENT;
// ProcessEvents
// called by the Process at interrupt time to see if there are
// any events that have timed out
//
void STREAM::ProcessEvents(void)
{
if (qhEvent.IsElements()) {
PEVENT pnextevent = (PEVENT)qhEvent.Head();
ULONG time = GetCurrentTime();
ULONG eventtime = pnextevent->GetEventTime();
if (eventtime <= time)
pnextevent->Report(time);
}
}
ULONG STREAM::EnableEvent(PDDCMDCONTROL pControl)
{
// see if the event already exists on the event queue
// call FindEvent if we get back an address (event exists)
// call the UpdateEvent member function and get the event info updated.
// if Findevent returns NULL (no event on queue) then call the construct
// a new event and put it on the tail of the event queue. then call
// SetNextEvent to update the next event to time out....
PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
if (pevent)
pevent->UpdateEvent(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
else {
pevent= new EVENT(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
}
if (!pevent)
return ERROR_TOO_MANY_EVENTS;
SetNextEvent();
return NO_ERROR;
}
ULONG STREAM::DisableEvent(PDDCMDCONTROL pControl)
{
pTrace->vLog(DDCMD_DisableEvent,pControl->hEvent);
PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
if (!pevent)
return ERROR_INVALID_EVENT;
// destroying an event may change things that get referenced in the ISR
// so we really need to cli/sti around the call to DestroyElement
_cli_();
qhEvent.DestroyElement((PQUEUEELEMENT)pevent);
if (qhEvent.Head() != qhEvent.Tail())
SetNextEvent();
_sti_();
return NO_ERROR;
}
/**@internal SetNextEvent
* @param None
* @return None
* @notes
* the function walks the event list and finds the next event to timeout.
* the event is moved to the head of the event queue.
*
*/
void STREAM::SetNextEvent(void)
{
// if there are no events or only one event on the
// queue just return
if ((qhEvent.Head()) == (qhEvent.Tail()))
return;
PQUEUEELEMENT pele1 = qhEvent.Head();
PQUEUEELEMENT pele2 = NULL;
ULONG ulTimeToBeat = -1; // -1 equals 0xFFFFFFFF the maximum time
while (pele1) {
if (((PEVENT)pele1)->GetEventTime() <= ulTimeToBeat) {
pele2 = pele1;
ulTimeToBeat = ((PEVENT)pele1)->GetEventTime();
}
pele1 = pele1->pNext;
}
// pele2 should now contain the address of the next
// event to time out.. if it is not already on
// the head of the Event queue then put it there
if (pele2 != qhEvent.Head()) {
_cli_();
qhEvent.PopElement(pele2);
qhEvent.PushOnHead(pele2);
_sti_();
}
}
#endif
065e 5a L78 pop dx
065f fc cld
0660 streamDisableEvent_:
0660 streamEnableEvent_:
0660 streamProcessEvents_:
0660 streamSetNextEvent_:
0660 c3 ret
No disassembly errors
List of external symbols
Symbol
----------------
wavestreamGetCurrentTime_
00000077
free_ 000005eb 000004af 00000365 0000033d 00000315 0000008d
streamReturnBuffer_
00000104
malloc_ 0000021f 000001b3
_streamList 00000653 00000625 00000617 00000610 000005fb 000005c3 000005a9 000005a5 0000059b 00000597
00000583 0000057c 00000573 00000569 00000564 0000055e 00000553 00000546 0000053e 0000053b
00000532 00000529 00000525 000003bd 000003a3 0000037e 00000298 00000294 0000028e 0000028a
0000027e
waveplayStop_ 000002e8
waverecStop_ 000002ef
sbPopElement_ 000004a1 0000035c 00000334 0000030c
streamPopElement_
000005dd 0000036c
sbPopTail_ 000004ec
streamPopTail_ 0000062a
------------------------------------------------------------
Segment: _DATA PARA 0000001c bytes
0000 00 00 00 00 _streamList - ....
0004 00 00 00 00 L79 - ....
0008 00 00 L80 - ..
000a 00 00 L81 - ..
000c 00 00 L82 - ..
000e 00 00 L83 - ..
0010 00 00 L84 - ..
0012 00 00 L85 - ..
0014 00 00 L86 - ..
0016 00 00 L87 - ..
0018 00 00 L88 - ..
001a 00 00 L89 - ..
No disassembly errors
------------------------------------------------------------
List of public symbols
SYMBOL GROUP SEGMENT ADDRESS
---------------------------------------------------------
_streamList DGROUP _DATA 00000000
sbDestroyElement_
_TEXT 0000049c
sbHead_ _TEXT 000003e0
sbNotEmpty_ _TEXT 00000510
sbPopElement_ _TEXT 000004b8
sbPopHead_ _TEXT 00000430
sbPopTail_ _TEXT 00000450
sbPushOnHead_ _TEXT 000003f0
sbPushOnTail_ _TEXT 00000410
sbTail_ _TEXT 000003e8
streamDeinit_ _TEXT 000002c8
streamDeregister_
_TEXT 00000184
streamDestroyElement_
_TEXT 000005d8
streamDisableEvent_
_TEXT 00000660
streamEnableEvent_
_TEXT 00000660
streamFindActive_
_TEXT 00000378
streamFindStreamHandle_
_TEXT 000003b8
streamFindStreamSFN_
_TEXT 000003a0
streamHead_ _TEXT 00000524
streamInit_ _TEXT 00000278
streamNotEmpty_ _TEXT 00000650
streamPauseTime_
_TEXT 00000108
streamPopElement_
_TEXT 000005f4
streamPopHead_ _TEXT 00000570
streamPopTail_ _TEXT 00000590
streamProcessEvents_
_TEXT 00000660
streamPushOnHead_
_TEXT 0000052c
streamPushOnTail_
_TEXT 0000054c
streamRead_ _TEXT 000001a0
streamRegister_ _TEXT 00000120
streamResumeTime_
_TEXT 00000114
streamReturnBuffer_
_TEXT 00000000
streamReturnBuffers_
_TEXT 00000098
streamSetNextEvent_
_TEXT 00000660
streamTail_ _TEXT 00000528
streamWrite_ _TEXT 0000020c
------------------------------------------------------------