home *** CD-ROM | disk | FTP | other *** search
- IDEAL
- MODEL TPascal
- LOCALS @@
- JUMPS
-
- P286
-
- DATASEG
-
- MACRO SetBorder r,g,b
- MASM
- COMMENT %
- PUSH DX AX
- MOV DX,3C8h
- XOR AL,AL
- OUT DX,AL
- INC DX
- IFDIF <&r>,<0>
- MOV AL,&r
- ENDIF
- OUT DX,AL
- IFDIF <&g>,<&r>
- MOV AL,&g
- ENDIF
- OUT DX,AL
- IFDIF <&b>,<&g>
- MOV AL,&b
- ENDIF
- OUT DX,AL
- POP AX DX
- %
- IDEAL
- ENDM
-
-
- StackSize EQU 1000
- DMABufferSize EQU 2048
- FinalBufferSize EQU 4096
-
- GLOBAL DevStack : BYTE
- GLOBAL DevSS : WORD
- GLOBAL DevSP : WORD
-
- GLOBAL OldTimerHandler : DWORD
-
- GLOBAL Sounding : DWORD
- GLOBAL SoundLeft : WORD
-
- GLOBAL SystemClockIncr : WORD
- GLOBAL SystemClockCount : WORD
-
- GLOBAL PeriodicCount : WORD
- GLOBAL PeriodicStart : WORD
- GLOBAL PeriodicProc : DWORD
-
- GLOBAL DeviceIdling : BYTE
-
- GLOBAL NumChannels : WORD
- GLOBAL BytesPerSample : BYTE
-
- GLOBAL DoBassPower : BYTE
- GLOBAL MixMethod : BYTE
-
- GLOBAL DMABufferPtr : DWORD
- GLOBAL DMABufferEnd : WORD
- GLOBAL DMABuffer : DWORD
- GLOBAL DMABufferYet : BYTE
- GLOBAL DMAStopped : BYTE
- GLOBAL DMAStop : BYTE
- GLOBAL DMAIrqWatch : BYTE
-
- GLOBAL FinalBufferPos : WORD
- GLOBAL FinalBuffer : WORD
-
- GLOBAL DeviceStartRut : WORD
- GLOBAL DeviceRut1 : WORD
- GLOBAL DeviceRut2 : WORD
- GLOBAL DeviceKickRut : WORD
- GLOBAL DeviceFillRut : WORD
-
- GLOBAL TrebleFilterVal_Left : WORD
- GLOBAL TrebleFilterMult_Left : WORD
- GLOBAL BassFilterVal_Left : WORD
- GLOBAL BassFilterMult_Left : WORD
- GLOBAL TrebleFilterVal_Right : WORD
- GLOBAL TrebleFilterMult_Right : WORD
- GLOBAL BassFilterVal_Right : WORD
- GLOBAL BassFilterMult_Right : WORD
-
- CODESEG
-
- GLOBAL DoGetBuffer : FAR
- GLOBAL GetDMACount : NEAR
- GLOBAL InitTimer : FAR
-
-
-
-
- ; ┌──────────────────────────────────────────────────────────────────────────┐
- ; │ │
- ; │ MACRO: Saturate │
- ; │ │
- ; │ Macro that saturates a sample just after an addition. │
- ; │ │
- ; │ IN: Reg = Register to be saturated. │
- ; │ │
- ; └──────────────────────────────────────────────────────────────────────────┘
-
- MACRO Saturate Reg
- LOCAL @@posit, @@nooverf
-
- JNO SHORT @@nooverf
- JS SHORT @@posit
- MOV Reg,-32767
- JMP SHORT @@nooverf
- @@posit: MOV Reg,32767
- @@nooverf:
-
- ENDM Saturate
-
-
-
-
- INCLUDE "BASSPOW.INC"
- INCLUDE "MIXROUTS.INC"
-
-
-
-
- MACRO DevCall DevRut, Segm
-
- JMP [DevRut] ; Segm:
- DevRut&Ret:
-
- ENDM
-
-
-
-
- ; ┌──────────────────────────────────────────────────────────────────────────┐
- ; │ │
- ; │ ROUTINE: DMAFillBuffer │
- ; │ │
- ; │ This routine fills a portion of the DMA buffer with the whole buffer of │
- ; │ samples pointed to by Sounding & SoundLeft. │
- ; │ │
- ; │ IN: nothing │
- ; │ │
- ; │ OUT: nothing │
- ; │ │
- ; │ MODIFIES: AX, BX, CX, DX, SI, DI, ES │
- ; │ │
- ; └──────────────────────────────────────────────────────────────────────────┘
-
- DeviceIdCount DB 0
- TickCnt DB 0
-
- PUBLIC DMAFillBuffer
-
- DMAFillBuffer:
- XOR AL,AL
- MOV [CS:DeviceIdCount],AL
-
- CALL CalcNewMixData
- MOV CX,[SoundLeft]
- MOV AL,[BytesPerSample]
- MOV DX,CX
- XOR AH,AH
- MUL DX
- LES DI,[DMABufferPtr]
- MOV BX,[DMABufferEnd]
- LDS SI,[Sounding]
- CLD
-
- ADD AX,DI
- CMP AX,BX
- JBE SHORT @@end
- SUB BX,DI
- JZ SHORT @@skip1st
- PUSH CX
- MOV AX,BX
- MOV CL,[SS:BytesPerSample]
- XOR CH,CH
- XOR DX,DX
- DIV CX
- MOV CX,AX
- PUSH CX
- CALL [SS:DeviceFillRut]
- POP BX
- POP CX
- SUB CX,BX
- @@skip1st: MOV DI,[WORD PTR SS:DMABuffer]
- @@end: CALL [SS:DeviceFillRut]
-
- ;MOV AL,[CS:TickCnt]
- ;XOR AL,255
- ;MOV [CS:TickCnt],AL
- ;MOV [ES:DI-1],AL
-
- MOV AX,SS
- MOV DS,AX
- MOV [WORD PTR DMABufferPtr],DI
- RET
-
-
-
-
- ; ┌──────────────────────────────────────────────────────────────────────────┐
- ; │ │
- ; │ ROUTINE: DMADoGetBuff │
- ; │ │
- ; │ This is the main buffer-filling routine for DMA devices. First it calls │
- ; │ the buffer grabber. Then, it checks to see if the DMA has advanced │
- ; │ enough to leave space for this buffer. │
- ; │ │
- ; │ IN: nothing │
- ; │ │
- ; │ OUT: nothing │
- ; │ │
- ; │ MODIFIES: AX, BX, CX, DX, SI, DI, ES │
- ; │ │
- ; └──────────────────────────────────────────────────────────────────────────┘
-
- PUBLIC DMADoGetBuff
-
- DMADoGetBuff:
-
- MOV AX,[SoundLeft]
- MOV BL,[DMABufferYet]
- AND BL,BL
- JZ SHORT @@1
- CALL DoGetBuffer
- @@1: MOV BL,1
- MOV [DMABufferYet],BL
-
- CMP AX,10
- JC SHORT @@end
-
- MOV DL,[BytesPerSample]
- XOR DH,DH
- MUL DX
-
- PUSH AX
- CALL GetDMACount
- MOV BX,DMABufferSize
- SUB BX,AX
- ADD BX,[WORD PTR DMABuffer]
- MOV CX,BX
- SUB BX,[WORD PTR DMABufferPtr]
- JNC SHORT @@2
- ADD BX,DMABufferSize
- @@2: POP AX
- SUB BX,AX
- JNC DMAFillBuffer
-
- XOR BL,BL
- MOV [DMABufferYet],BL
- @@end:
- MOV AL,[CS:DeviceIdCount]
- CMP AL,20
- JNC @@end1
- INC [CS:DeviceIdCount]
- @@end1:
- MOV [DeviceIdling],AL
-
- RET
-
-
-
-
- ; MOV [DevSS],SS
- ; MOV [DevSP],SP
- ; MOV DX,DS
- ; MOV SS,DX
- ; MOV SP,OFFSET DevStack + StackSize
-
- ; MOV SS,[DevSS]
- ; MOV SP,[DevSP]
-
-
-
-
- ; ┌──────────────────────────────────────────────────────────────────────────┐
- ; │ │
- ; │ ROUTINE: TimerHandler │
- ; │ │
- ; │ This is the big routine for non-DMA devices. It is called through │
- ; │ interrupts from a timer whose period is the sampling period. │
- ; │ │
- ; └──────────────────────────────────────────────────────────────────────────┘
-
- PUBLIC TimerHandler
-
- TimerHandler:
- CLI ; Just for safety's sake.
-
- ; ┌────────────────────────────────────────────┐
- ; │ Startup: │
- ; │ │
- ; │ - Save the registers in the local stack. │
- ; │ - Set the data segment register. │
- ; └────────────────────────────────────────────┘
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
- PUSH DS
-
- MOV AX,SEG Sounding
- MOV DS,AX
-
- ; ┌──────────────────────────────────────────┐
- ; │ First, we jump to the device start code. │
- ; └──────────────────────────────────────────┘
-
- DevCall DeviceStartRut
-
- ; ┌───────────────────────────────────────────┐
- ; │ Check to see if there are samples to use. │
- ; └───────────────────────────────────────────┘
-
- MOV AX,[SoundLeft]
- AND AX,AX
- JZ SHORT thAfterProcessingSample
-
- ; ┌──────────────────────────────────────────────┐
- ; │ Decrement the number of samples left in the │
- ; │ buffer, do the device initialization if any, │
- ; │ and signal that the device is not idle. │
- ; └──────────────────────────────────────────────┘
-
- DEC AX
- MOV [SoundLeft],AX
-
- DevCall DeviceRut1
-
- XOR BH,BH
- MOV [DeviceIdling],BH
-
- ; ┌─────────────────────────────────┐
- ; │ Load the buffer pointer, do the │
- ; │ mixing and output the sample. │
- ; └─────────────────────────────────┘
-
- LDS SI,[Sounding]
-
- CALL MixChannels
-
- MOV DX,SEG Sounding
- MOV DS,DX
- MOV [WORD PTR Sounding],SI
-
- MOV SI,OFFSET FinalBuffer
- MOV CX,[FinalBufferPos]
- ADD SI,CX
- ADD SI,CX
- MOV [SI],AX
- INC CX
- AND CX,FinalBufferSize - 1
- MOV [FinalBufferPos],CX
-
- DevCall DeviceRut2
-
- ; ┌────────────────────┐
- ; │ Restore the stack. │
- ; └────────────────────┘
-
- thAfterProcessingSample:
- sti
- ; ┌────────────────────────────┐
- ; │ Check if the old interrupt │
- ; │ routine must be called. │
- ; └────────────────────────────┘
-
- MOV AX,[SystemClockIncr]
- ADD [SystemClockCount],AX
- JC SHORT @@SystemClock
-
- ; ┌──────────────────────────────────┐
- ; │ Else, signal the EOI to the PIC. │
- ; └──────────────────────────────────┘
-
- MOV AL,20h
- OUT 20h,AL
-
- @@CheckOutProc:
- MOV CX,[PeriodicCount]
- JCXZ SHORT @@OutProc
- DEC CX
- MOV [PeriodicCount],CX
- JZ SHORT @@OutProc
-
- MOV AX,[SoundLeft]
- AND AX,AX
- JZ SHORT @@OutProc
-
- @@exit:
- ; ┌────────────────────────────────────┐
- ; │ Do the final stuff: Pop registers. │
- ; └────────────────────────────────────┘
-
- POP DS
- POP SI
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
- IRET
-
- @@SystemClock:
- PUSHF
- CALL [OldTimerHandler]
- JMP SHORT @@CheckOutProc
-
- @@OutProc:
- ; ┌────────────────────────────────────────────┐
- ; │ Get a new sample buffer. If there is none, │
- ; │ signal that the device is in idle state. │
- ; └────────────────────────────────────────────┘
-
- MOV AL,0
- @@outsemaph:
- AND AL,AL
- JNZ SHORT @@exit
- INC AL
- MOV [BYTE PTR CS:@@outsemaph-1],AL
-
- MOV AX,[SoundLeft]
- AND AX,AX
- JNZ SHORT @@NoIdle
-
- CALL CalcNewMixData
-
- PUSH ES
- CALL DoGetBuffer
- POP ES
-
- CALL CalcNewMixData
-
- MOV AX,[SoundLeft]
- AND AX,AX
- JNZ SHORT @@NoIdle
-
- INC AH
- MOV [DeviceIdling],AH
-
- @@NoIdle:
- MOV [BYTE PTR CS:@@outsemaph-1],0
-
- ; ┌─────────────────────────────────────────────┐
- ; │ See if the periodic process must be called. │
- ; └─────────────────────────────────────────────┘
-
- MOV AX,[PeriodicCount]
- AND AX,AX
- JNZ SHORT @@NoPeriodic
-
- MOV AX,[PeriodicStart]
- MOV [PeriodicCount],AX
-
- ; ┌────────────────────────────┐
- ; │ Call the periodic process. │
- ; └────────────────────────────┘
-
- PUSH ES
- STI
- CALL [PeriodicProc]
- POP ES
-
- @@NoPeriodic:
- JMP SHORT @@exit
-
-
-
-
- ; ┌──────────────────────────────────────────────────────────────────────────┐
- ; │ │
- ; │ ROUTINE: DMATimerHandler │
- ; │ │
- ; │ This is the big routine for DMA devices. It is called through │
- ; │ interrupts from a timer whose period is a few Hertz (100 for example). │
- ; │ │
- ; └──────────────────────────────────────────────────────────────────────────┘
-
- DMASema DB 0
-
- PUBLIC DMATimerHandler
-
- DMATimerHandler:
- CLI ; Just for safety's sake.
-
- ; ┌─────────────────────────┐
- ; │ Startup: │
- ; │ │
- ; │ - Save the registers. │
- ; └─────────────────────────┘
-
- PUSHA
- PUSH ES
- PUSH DS
-
- MOV AX,SEG Sounding
- MOV DS,AX
-
- @@DoSystemClock:
-
- ; ┌────────────────────────────────────────────────────┐
- ; │ Check if the old interrupt routine must be called. │
- ; └────────────────────────────────────────────────────┘
-
- MOV AX,[SystemClockIncr]
- ADD [SystemClockCount],AX
- JNC SHORT @@NoSysClk
-
- ; ┌───────────────┐
- ; │ If so, do it. │
- ; └───────────────┘
-
- PUSHF
- CALL [OldTimerHandler]
- JMP SHORT @@SystemClkDone
-
- @@NoSysClk:
- ; ┌──────────────────────────────────┐
- ; │ Else, signal the EOI to the PIC. │
- ; └──────────────────────────────────┘
-
- MOV AL,20h
- OUT 20h,AL
-
- @@SystemClkDone:
- CLI
-
- ; ┌─────────────────────────────────────────┐
- ; │ First we check if the DMA operation is │
- ; │ requested to stop. If so, we signal the │
- ; │ stopping of the DMA and jump to the old │
- ; │ IRQ-checking part. │
- ; └─────────────────────────────────────────┘
-
- MOV AL,[DMAStop]
- AND AL,AL
- JZ SHORT @@notstop
- ; MOV [DMAStopped],AL
- MOV [DeviceIdling],AL
- JMP SHORT @@end
- @@notstop:
- ; ┌─────────────────────────────────────────┐
- ; │ Now, we check the IRQ watchdog, just in │
- ; │ case we need to kick the card. │
- ; └─────────────────────────────────────────┘
-
- MASM
- COMMENT #
-
- MOV AL,[DMAIrqWatch]
- CMP AL,200
- JC SHORT @@notwatch
- ; CALL [DeviceKickRut]
- @@notwatch:
- ; ┌─────────────────────────────────────────┐
- ; │ If the device is said to be idle, reset │
- ; │ the timer. This is to protect the timer │
- ; │ period from being modified. │
- ; └─────────────────────────────────────────┘
-
- MOV AL,[DeviceIdling]
- AND AL,AL
- JZ SHORT @@notidling
- ; CALL InitTimer
- @@notidling:
- ; ┌────────────────────────────────────────┐
- ; │ Signal that the device is not idling, │
- ; │ and fill a bit more of the DMA buffer. │
- ; └────────────────────────────────────────┘
- #
- IDEAL
- MOV AL,[CS:DMASema]
- AND AL,AL
- JNZ @@end
-
- INC [CS:DMASema]
- STI
-
- @@loop:
-
- PUSH DS
- MOV AX,0B800h
- MOV DS,AX
- INC [WORD PTR DS:90*4];
- POP DS
-
- MOV [DevSS],SS
- MOV [DevSP],SP
- MOV DX,DS
- MOV SS,DX
- MOV SP,OFFSET DevStack + StackSize
-
- XOR AL,AL
- MOV [DeviceIdling],AL
-
- ;SetBorder 0, 63, 63
-
- STI
- CALL DMADoGetBuff
- CLI
-
- ;SetBorder 0, 0, 63
-
- ; ┌─────────────────────────────────────┐
- ; │ Call the periodic process and exit. │
- ; └─────────────────────────────────────┘
-
- STI
- CALL [PeriodicProc]
- CLI
-
- MOV SS,[DevSS]
- MOV SP,[DevSP]
-
- MOV AL,[CS:DeviceIdCount]
- AND AL,AL
- ; JZ @@loop
-
- DEC [CS:DMASema]
-
- @@end:
- ; ┌────────────────────────────────────────┐
- ; │ Increment the watchdog, but don't let │
- ; │ it wrap around. │
- ; └────────────────────────────────────────┘
-
- MOV AL,[DMAIrqWatch]
- CMP AL,250
- JNC SHORT @@noinc
- INC [DMAIrqWatch]
- @@noinc:
-
- ; ┌────────────────────────────────────────────────┐
- ; │ Do the final stuff: Pop registers, restore the │
- ; │ stack, and exit. │
- ; └────────────────────────────────────────────────┘
-
- POP DS
- POP ES
- POPA
- IRET
-
-
-
-
-
- MASM
- COMMENT ~
-
- kk:
-
- CLI ; Just for safety's sake.
-
- ; ┌─────────────────────────┐
- ; │ Startup: │
- ; │ │
- ; │ - Save the registers. │
- ; └─────────────────────────┘
-
- PUSHA
- PUSH ES
- PUSH DS
-
- MOV AX,SEG Sounding
- MOV DS,AX
-
- @@DoSystemClock:
-
- ; ┌────────────────────────────────────────────────────┐
- ; │ Check if the old interrupt routine must be called. │
- ; └────────────────────────────────────────────────────┘
-
- MOV AX,[SystemClockIncr]
- ADD [SystemClockCount],AX
- JNC SHORT @@NoSysClk
-
- ; ┌───────────────┐
- ; │ If so, do it. │
- ; └───────────────┘
-
- PUSHF
- CALL [OldTimerHandler]
- JMP SHORT @@SystemClkDone
-
- @@NoSysClk:
- ; ┌──────────────────────────────────┐
- ; │ Else, signal the EOI to the PIC. │
- ; └──────────────────────────────────┘
-
- MOV AL,20h
- OUT 20h,AL
-
- @@SystemClkDone:
- CLI
-
- ; ┌─────────────────────────────────────────┐
- ; │ First we check if the DMA operation is │
- ; │ requested to stop. If so, we signal the │
- ; │ stopping of the DMA and jump to the old │
- ; │ IRQ-checking part. │
- ; └─────────────────────────────────────────┘
-
- MOV AL,[DMAStop]
- AND AL,AL
- JZ SHORT @@notstop
- ; MOV [DMAStopped],AL
- MOV [DeviceIdling],AL
- JMP SHORT @@end
- @@notstop:
- ; ┌─────────────────────────────────────────┐
- ; │ Now, we check the IRQ watchdog, just in │
- ; │ case we need to kick the card. │
- ; └─────────────────────────────────────────┘
-
- MOV AL,[DMAIrqWatch]
- CMP AL,200
- JC SHORT @@notwatch
- ; CALL [DeviceKickRut]
- @@notwatch:
- ; ┌─────────────────────────────────────────┐
- ; │ If the device is said to be idle, reset │
- ; │ the timer. This is to protect the timer │
- ; │ period from being modified. │
- ; └─────────────────────────────────────────┘
-
- MOV AL,[DeviceIdling]
- AND AL,AL
- JZ SHORT @@notidling
- ; CALL InitTimer
- @@notidling:
- ; ┌────────────────────────────────────────┐
- ; │ Signal that the device is not idling, │
- ; │ and fill a bit more of the DMA buffer. │
- ; └────────────────────────────────────────┘
-
- MOV AL,[CS:DMASema]
- AND AL,AL
- JNZ @@end
-
- INC [CS:DMASema]
- STI
-
- @@loop:
-
- PUSH DS
- MOV AX,0B800h
- MOV DS,AX
- INC [WORD PTR DS:90*4];
- POP DS
-
- MOV [DevSS],SS
- MOV [DevSP],SP
- MOV DX,DS
- MOV SS,DX
- MOV SP,OFFSET DevStack + StackSize
-
- XOR AL,AL
- MOV [DeviceIdling],AL
-
- ;SetBorder 0, 63, 63
-
- STI
- CALL DMADoGetBuff
- CLI
-
- ;SetBorder 0, 0, 63
-
- ; ┌─────────────────────────────────────┐
- ; │ Call the periodic process and exit. │
- ; └─────────────────────────────────────┘
-
- STI
- CALL [PeriodicProc]
- CLI
-
- MOV SS,[DevSS]
- MOV SP,[DevSP]
-
- MOV AL,[CS:DeviceIdCount]
- AND AL,AL
- ; JZ @@loop
-
- DEC [CS:DMASema]
-
- @@end:
- ; ┌────────────────────────────────────────┐
- ; │ Increment the watchdog, but don't let │
- ; │ it wrap around. │
- ; └────────────────────────────────────────┘
-
- MOV AL,[DMAIrqWatch]
- CMP AL,250
- JNC SHORT @@noinc
- INC [DMAIrqWatch]
- @@noinc:
-
- ; ┌────────────────────────────────────────────────┐
- ; │ Do the final stuff: Pop registers, restore the │
- ; │ stack, and exit. │
- ; └────────────────────────────────────────────────┘
-
- POP DS
- POP ES
- POPA
- IRET
-
- ~
- IDEAL
-
-
-
-
-
- PUBLIC NullTimerHandler
- NullTimerHandler:
- PUSHA
- PUSH DS
- PUSH ES
-
- MOV AX,SEG Sounding
- MOV DS,AX
-
- MOV [DevSS],SS
- MOV [DevSP],SP
- MOV DX,DS
- MOV SS,DX
- MOV SP,OFFSET DevStack + StackSize
-
- @@DoSystemClock:
-
- ; ┌────────────────────────────────────────────────────┐
- ; │ Check if the old interrupt routine must be called. │
- ; └────────────────────────────────────────────────────┘
-
- MOV AX,[SystemClockIncr]
- ADD [SystemClockCount],AX
- JNC SHORT @@NoSysClk
-
- ; ┌───────────────┐
- ; │ If so, do it. │
- ; └───────────────┘
-
- PUSHF
- CALL [OldTimerHandler]
- JMP SHORT @@SystemClkDone
-
- @@NoSysClk:
- ; ┌──────────────────────────────────┐
- ; │ Else, signal the EOI to the PIC. │
- ; └──────────────────────────────────┘
-
- MOV AL,20h
- OUT 20h,AL
-
- @@SystemClkDone:
- CALL [PeriodicProc]
-
- MOV SS,[DevSS]
- MOV SP,[DevSP]
-
- POP ES
- POP DS
- POPA
- IRET
-
-
-
-
-
-
- ; ┌──────────────────────────────────────────────────────────────────────────┐
- ; │ │
- ; │ ROUTINE: NullDevRut │
- ; │ │
- ; │ Do-nothing routine for the unused device services. │
- ; │ │
- ; └──────────────────────────────────────────────────────────────────────────┘
-
- NullDevRut:
- RET
-
-
-
-
- INCLUDE "DEVSB.INC"
- INCLUDE "DEVSPKR.INC"
- INCLUDE "DEVDAC.INC"
-
-
-
-
- END
-