Buffer     EQU [BP + 8]
N          EQU [BP + 6]
POLY4_SIZE EQU 0Fh
POLY5_SIZE EQU 1Fh
POLY9_SIZE EQU 1FFh

data segment byte public 'data'
assume DS:data
        extrn AUDC            : byte
        extrn AUDV            : byte
        extrn p5              : byte
        extrn outvol          : byte
        extrn div_n_cnt       : byte
        extrn div_n_max       : byte
        extrn div31           : byte
        extrn p4              : byte
        extrn p9              : byte
        extrn bit4            : byte
        extrn bit5            : byte
        extrn bit9            : byte
        extrn samp_n_cnt      : byte
        extrn samp_n_max      : byte
        extrn ProcessSet      : byte
        extrn ProcessJump0    : byte
        extrn ProcessJump1    : byte

        RepData1 DW 0
        RepData2 DW 0
        RepData3 DW 0

data ends

code segment para public 'code'
assume DS:data,CS:code

public ProcessSound

.486

; ------------------------------------------------------

Ch0     macro _Bit8,_Bit4,_Bit2,_Bit1
        local _IsOne,_NotPOLY5_SIZE,_NotPOLY9_SIZE,_NotPOLY4_SIZE,_True2,_GetOut
        CMP   BYTE PTR div_n_cnt,1
        JBE   SHORT _IsOne
        DEC   BYTE PTR div_n_cnt
        JMP   _GetOut
_IsOne:
        JNE   SHORT _GetOut
        MOV   BYTE PTR div_n_cnt,DL
        INC   WORD PTR P5
        CMP   WORD PTR P5,POLY5_SIZE
        JNE   SHORT _NotPOLY5_SIZE
        MOV   WORD PTR P5,0
_NotPOLY5_SIZE:
        If _Bit2 ne 0
          MOV   SI,WORD PTR P5
          If _Bit1 ne 0
            TEST  BYTE PTR Bit5[SI],AH
            JZ    SHORT _GetOut
          else
            TEST  BYTE PTR Div31[SI],AH
            JZ    SHORT _GetOut
          endif
        endif
        If _Bit4 ne 0
          OR    BL,BL
          JZ    SHORT _True2
          SUB   BL,BL
          JMP   _GetOut
        else
          If    _Bit8 ne 0
            If (_Bit1 + _Bit2 + _Bit4) eq 0
              INC   WORD PTR P9
              CMP   WORD PTR P9,POLY9_SIZE
              JNE   SHORT _NotPOLY9_SIZE
              MOV   WORD PTR P9,0
_NotPOLY9_SIZE:
              MOV   SI,WORD PTR P9
              TEST  BYTE PTR Bit9[SI],AH
              JNZ   SHORT _True2
              SUB   BL,BL
              JMP   _GetOut
            else
              MOV   SI,WORD PTR P5
              TEST  BYTE PTR Bit5[SI],AH
              JNZ   SHORT _True2
              SUB   BL,BL
              JMP   _GetOut
            endif
          else
            INC   WORD PTR P4
            CMP   WORD PTR P4,POLY4_SIZE
            JNE   SHORT _NotPOLY4_SIZE
            MOV   WORD PTR P4,0
_NotPOLY4_SIZE:
            MOV   SI,WORD PTR P4
            TEST  BYTE PTR Bit4[SI],AH
            JNZ   SHORT _True2
            SUB   BL,BL
            JMP   _GetOut
          endif
        endif
_True2:
        MOV   BL,CL
_GetOut:
        endm

; ------------------------------------------------------

Ch1     macro _Bit8,_Bit4,_Bit2,_Bit1
        local _IsOneA,_NotPOLY5_SIZEA,_NotPOLY9_SIZEA,_NotPOLY4_SIZEA,_True2A,_GetOutA
        CMP   BYTE PTR div_n_cnt[1],1
        JBE   SHORT _IsOneA
        DEC   BYTE PTR div_n_cnt[1]
        JMP   _GetOutA
_IsOneA:
        JNE   SHORT _GetOutA
        MOV   BYTE PTR div_n_cnt[1],DH
        INC   WORD PTR P5[2]
        CMP   WORD PTR P5[2],POLY5_SIZE
        JNE   SHORT _NotPOLY5_SIZEA
        MOV   WORD PTR P5[2],0
_NotPOLY5_SIZEA:
        If _Bit2 ne 0
          MOV   SI,WORD PTR P5[2]
          If _Bit1 ne 0
            TEST  BYTE PTR Bit5[SI],AH
            JZ    SHORT _GetOutA
          else
            TEST  BYTE PTR Div31[SI],AH
            JZ    SHORT _GetOutA
          endif
        endif
        If _Bit4 ne 0
          OR    BH,BH
          JZ    SHORT _True2A
          SUB   BH,BH
          JMP   _GetOutA
        else
          If    _Bit8 ne 0
            If (_Bit1 + _Bit2 + _Bit4) eq 0
              INC   WORD PTR P9[2]
              CMP   WORD PTR P9[2],POLY9_SIZE
              JNE   SHORT _NotPOLY9_SIZEA
              MOV   WORD PTR P9[2],0
_NotPOLY9_SIZEA:
              MOV   SI,WORD PTR P9[2]
              TEST  BYTE PTR Bit9[SI],AH
              JNZ   SHORT _True2A
              SUB   BH,BH
              JMP   _GetOutA
            else
              MOV   SI,WORD PTR P5[2]
              TEST  BYTE PTR Bit5[SI],AH
              JNZ   SHORT _True2A
              SUB   BH,BH
              JMP   _GetOutA
            endif
          else
            INC   WORD PTR P4[2]
            CMP   WORD PTR P4[2],POLY4_SIZE
            JNE   SHORT _NotPOLY4_SIZEA
            MOV   WORD PTR P4[2],0
_NotPOLY4_SIZEA:
            MOV   SI,WORD PTR P4[2]
            TEST  BYTE PTR Bit4[SI],AH
            JNZ   SHORT _True2A
            SUB   BH,BH
            JMP   _GetOutA
          endif
        endif
_True2A:
        MOV   BH,CH
_GetOutA:
        endm

; ------------------------------------------------------

align   16
ProcessSound proc far
        PUSH  BP
        MOV   BP,SP

  ; Fill jump tables

        TEST  BYTE PTR ProcessSet,0FFh
        JNZ   TableFilled
        MOV   WORD PTR ProcessJump0[00h * 2],OFFSET C0_0000
        MOV   WORD PTR ProcessJump0[01h * 2],OFFSET C0_0001
        MOV   WORD PTR ProcessJump0[02h * 2],OFFSET C0_0010
        MOV   WORD PTR ProcessJump0[03h * 2],OFFSET C0_0011
        MOV   WORD PTR ProcessJump0[04h * 2],OFFSET C0_0100
        MOV   WORD PTR ProcessJump0[05h * 2],OFFSET C0_0101
        MOV   WORD PTR ProcessJump0[06h * 2],OFFSET C0_0110
        MOV   WORD PTR ProcessJump0[07h * 2],OFFSET C0_0111
        MOV   WORD PTR ProcessJump0[08h * 2],OFFSET C0_1000
        MOV   WORD PTR ProcessJump0[09h * 2],OFFSET C0_1001
        MOV   WORD PTR ProcessJump0[0Ah * 2],OFFSET C0_1010
        MOV   WORD PTR ProcessJump0[0Bh * 2],OFFSET C0_1011
        MOV   WORD PTR ProcessJump0[0Ch * 2],OFFSET C0_1100
        MOV   WORD PTR ProcessJump0[0Dh * 2],OFFSET C0_1101
        MOV   WORD PTR ProcessJump0[0Eh * 2],OFFSET C0_1110
        MOV   WORD PTR ProcessJump0[0Fh * 2],OFFSET C0_1111

        MOV   WORD PTR ProcessJump1[00h * 2],OFFSET C1_0000
        MOV   WORD PTR ProcessJump1[01h * 2],OFFSET C1_0001
        MOV   WORD PTR ProcessJump1[02h * 2],OFFSET C1_0010
        MOV   WORD PTR ProcessJump1[03h * 2],OFFSET C1_0011
        MOV   WORD PTR ProcessJump1[04h * 2],OFFSET C1_0100
        MOV   WORD PTR ProcessJump1[05h * 2],OFFSET C1_0101
        MOV   WORD PTR ProcessJump1[06h * 2],OFFSET C1_0110
        MOV   WORD PTR ProcessJump1[07h * 2],OFFSET C1_0111
        MOV   WORD PTR ProcessJump1[08h * 2],OFFSET C1_1000
        MOV   WORD PTR ProcessJump1[09h * 2],OFFSET C1_1001
        MOV   WORD PTR ProcessJump1[0Ah * 2],OFFSET C1_1010
        MOV   WORD PTR ProcessJump1[0Bh * 2],OFFSET C1_1011
        MOV   WORD PTR ProcessJump1[0Ch * 2],OFFSET C1_1100
        MOV   WORD PTR ProcessJump1[0Dh * 2],OFFSET C1_1101
        MOV   WORD PTR ProcessJump1[0Eh * 2],OFFSET C1_1110
        MOV   WORD PTR ProcessJump1[0Fh * 2],OFFSET C1_1111

        MOV   BYTE PTR ProcessSet,1
TableFilled:

  ; loop until the buffer is filled

  ; Self-modifying code

        MOV   SI,WORD PTR AUDC
        ADD   SI,SI
        AND   SI,01Eh
        MOV   SI,WORD PTR ProcessJump0[SI]
;        MOV   WORD PTR CS:[Rep1 - 2],SI
        MOV   WORD PTR RepData1,SI


        MOV   SI,WORD PTR AUDC[1]
        ADD   SI,SI
        AND   SI,01Eh
        MOV   SI,WORD PTR ProcessJump1[SI]
;        MOV   WORD PTR CS:[Rep2 - 2],SI
        MOV   WORD PTR RepData2,SI

        MOV   SI,WORD PTR Samp_N_Max
;        MOV   WORD PTR CS:[Rep3 - 2],SI
        MOV   WORD PTR RepData3,SI

;        MOV   AL,128
;        MOV   BX,WORD PTR AUDV
;        SHR   BL,1
;        SHR   BH,1
;        SUB   AL,BL
;        SUB   AL,BH
;        MOV   BYTE PTR CS:[Rep4 - 1],AL

  ; Load commonly-used values into registers

        MOV   AH,0FFh
        MOV   BX,WORD PTR OutVol
        MOV   CX,WORD PTR AUDV
        MOV   DX,WORD PTR Div_N_Max

  ; Start the loop

        LES   DI,DWORD PTR Buffer
        CLD
        CMP   WORD PTR N,0
        JZ    GetOut
CheckN:

  ; Process channel 0

;        MOV   SI,1212h          ; Self-modified code
        MOV   SI,WORD PTR RepData1
Rep1:
        JMP   SI

C0_0000:
        Ch0 0 0 0 0
        JMP Channel1
C0_0001:
        Ch0 0 0 0 1
        JMP Channel1
C0_0010:
        Ch0 0 0 1 0
        JMP Channel1
C0_0011:
        Ch0 0 0 1 1
        JMP Channel1
C0_0100:
        Ch0 0 1 0 0
        JMP Channel1
C0_0101:
        Ch0 0 1 0 1
        JMP Channel1
C0_0110:
        Ch0 0 1 1 0
        JMP Channel1
C0_0111:
        Ch0 0 1 1 1
        JMP Channel1
C0_1000:
        Ch0 1 0 0 0
        JMP Channel1
C0_1001:
        Ch0 1 0 0 1
        JMP Channel1
C0_1010:
        Ch0 1 0 1 0
        JMP Channel1
C0_1011:
        Ch0 1 0 1 1
        JMP Channel1
C0_1100:
        Ch0 1 1 0 0
        JMP Channel1
C0_1101:
        Ch0 1 1 0 1
        JMP Channel1
C0_1110:
        Ch0 1 1 1 0
        JMP Channel1
C0_1111:
        Ch0 1 1 1 1

; ------------------------------------------------------

Channel1:

;        MOV   SI,1212h          ; Self-modified code
        MOV   SI,WORD PTR RepData2
Rep2:
        JMP   SI

C1_0000:
        Ch1 0 0 0 0
        JMP Next
C1_0001:
        Ch1 0 0 0 1
        JMP Next
C1_0010:
        Ch1 0 0 1 0
        JMP Next
C1_0011:
        Ch1 0 0 1 1
        JMP Next
C1_0100:
        Ch1 0 1 0 0
        JMP Next
C1_0101:
        Ch1 0 1 0 1
        JMP Next
C1_0110:
        Ch1 0 1 1 0
        JMP Next
C1_0111:
        Ch1 0 1 1 1
        JMP Next
C1_1000:
        Ch1 1 0 0 0
        JMP Next
C1_1001:
        Ch1 1 0 0 1
        JMP Next
C1_1010:
        Ch1 1 0 1 0
        JMP Next
C1_1011:
        Ch1 1 0 1 1
        JMP Next
C1_1100:
        Ch1 1 1 0 0
        JMP Next
C1_1101:
        Ch1 1 1 0 1
        JMP Next
C1_1110:
        Ch1 1 1 1 0
        JMP Next
C1_1111:
        Ch1 1 1 1 1

; ------------------------------------------------------

Next:

        DEC   BYTE PTR Samp_N_Cnt[1]
        JNZ   CheckN
;        ADD   WORD PTR Samp_N_Cnt,1212h   ; Self-modified code
        MOV   SI,WORD PTR RepData3
        ADD   WORD PTR Samp_N_Cnt,SI
Rep3:
        MOV   AL,BL
        ADD   AL,BH

;      OV0     := OutVol_0 - (_audv0 Div 2);
;      OV1     := OutVol_1 - (_audv1 Div 2);
;      _OutVol := (OV0 + OV1) + 128;

;        ADD   AL,12h                      ; Self-modified code
;Rep4:


        STOSB
        DEC   WORD PTR N
        JNZ   CheckN

; ------------------------------------------------------

GetOut:
        MOV   WORD PTR OutVol,BX
        POP   BP
        RET   6
ProcessSound endp
code    ends
        end
