POLY4_SIZE EQU 0Fh
POLY5_SIZE EQU 1Fh
POLY9_SIZE EQU 1FFh

.486
.MODEL FLAT

.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

        extrn Pf2Buf          : byte
        extrn ProcessPf2      : byte

        RepData1 DD 0
        RepData2 DD 0
        RepData3 DW 0
        Pf2Index DD 0

        Buffer   DD 0
        N        DD 0

.CODE

public ProcessSound

; ------------------------------------------------------

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   DWORD PTR P5
        CMP   DWORD PTR P5,POLY5_SIZE
        JNE   SHORT _NotPOLY5_SIZE
        MOV   DWORD PTR P5,0
_NotPOLY5_SIZE:
        If _Bit2 ne 0
          MOV   ESI,DWORD PTR P5
          If _Bit1 ne 0
            TEST  BYTE PTR Bit5[ESI],AH
            JZ    SHORT _GetOut
          else
            TEST  BYTE PTR Div31[ESI],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   DWORD PTR P9
              CMP   DWORD PTR P9,POLY9_SIZE
              JNE   SHORT _NotPOLY9_SIZE
              MOV   DWORD PTR P9,0
_NotPOLY9_SIZE:
              MOV   ESI,DWORD PTR P9
              TEST  BYTE PTR Bit9[ESI],AH
              JNZ   SHORT _True2
              SUB   BL,BL
              JMP   _GetOut
            else
              MOV   ESI,DWORD PTR P5
              TEST  BYTE PTR Bit5[ESI],AH
              JNZ   SHORT _True2
              SUB   BL,BL
              JMP   _GetOut
            endif
          else
            INC   DWORD PTR P4
            CMP   DWORD PTR P4,POLY4_SIZE
            JNE   SHORT _NotPOLY4_SIZE
            MOV   DWORD PTR P4,0
_NotPOLY4_SIZE:
            MOV   ESI,DWORD PTR P4
            TEST  BYTE PTR Bit4[ESI],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[4],1
        JBE   SHORT _IsOneA
        DEC   BYTE PTR div_n_cnt[4]
        JMP   _GetOutA
_IsOneA:
        JNE   SHORT _GetOutA
        MOV   BYTE PTR div_n_cnt[4],DH
        INC   DWORD PTR P5[4]
        CMP   DWORD PTR P5[4],POLY5_SIZE
        JNE   SHORT _NotPOLY5_SIZEA
        MOV   DWORD PTR P5[4],0
_NotPOLY5_SIZEA:
        If _Bit2 ne 0
          MOV   ESI,DWORD PTR P5[4]
          If _Bit1 ne 0
            TEST  BYTE PTR Bit5[ESI],AH
            JZ    SHORT _GetOutA
          else
            TEST  BYTE PTR Div31[ESI],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   DWORD PTR P9[4]
              CMP   DWORD PTR P9[4],POLY9_SIZE
              JNE   SHORT _NotPOLY9_SIZEA
              MOV   DWORD PTR P9[4],0
_NotPOLY9_SIZEA:
              MOV   ESI,DWORD PTR P9[4]
              TEST  BYTE PTR Bit9[ESI],AH
              JNZ   SHORT _True2A
              SUB   BH,BH
              JMP   _GetOutA
            else
              MOV   ESI,DWORD PTR P5[4]
              TEST  BYTE PTR Bit5[ESI],AH
              JNZ   SHORT _True2A
              SUB   BH,BH
              JMP   _GetOutA
            endif
          else
            INC   DWORD PTR P4[4]
            CMP   DWORD PTR P4[4],POLY4_SIZE
            JNE   SHORT _NotPOLY4_SIZEA
            MOV   DWORD PTR P4[4],0
_NotPOLY4_SIZEA:
            MOV   ESI,DWORD PTR P4[4]
            TEST  BYTE PTR Bit4[ESI],AH
            JNZ   SHORT _True2A
            SUB   BH,BH
            JMP   _GetOutA
          endif
        endif
_True2A:
        MOV   BH,CH
_GetOutA:
        endm

; ------------------------------------------------------

;align   32
ProcessSound proc
        PUSH  EBP
        PUSH  EDI
        PUSH  ESI
        PUSH  EBX

        MOV   DWORD PTR Buffer,EAX
        MOV   EDI,EAX
        MOV   DWORD PTR N,EDX

  ; Fill jump tables

        TEST  BYTE PTR ProcessSet,0FFh
        JNZ   TableFilled
        MOV   DWORD PTR ProcessJump0[00h * 4],OFFSET C0_0000
        MOV   DWORD PTR ProcessJump0[01h * 4],OFFSET C0_0001
        MOV   DWORD PTR ProcessJump0[02h * 4],OFFSET C0_0010
        MOV   DWORD PTR ProcessJump0[03h * 4],OFFSET C0_0011
        MOV   DWORD PTR ProcessJump0[04h * 4],OFFSET C0_0100
        MOV   DWORD PTR ProcessJump0[05h * 4],OFFSET C0_0101
        MOV   DWORD PTR ProcessJump0[06h * 4],OFFSET C0_0110
        MOV   DWORD PTR ProcessJump0[07h * 4],OFFSET C0_0111
        MOV   DWORD PTR ProcessJump0[08h * 4],OFFSET C0_1000
        MOV   DWORD PTR ProcessJump0[09h * 4],OFFSET C0_1001
        MOV   DWORD PTR ProcessJump0[0Ah * 4],OFFSET C0_1010
        MOV   DWORD PTR ProcessJump0[0Bh * 4],OFFSET C0_1011
        MOV   DWORD PTR ProcessJump0[0Ch * 4],OFFSET C0_1100
        MOV   DWORD PTR ProcessJump0[0Dh * 4],OFFSET C0_1101
        MOV   DWORD PTR ProcessJump0[0Eh * 4],OFFSET C0_1110
        MOV   DWORD PTR ProcessJump0[0Fh * 4],OFFSET C0_1111

        MOV   DWORD PTR ProcessJump1[00h * 4],OFFSET C1_0000
        MOV   DWORD PTR ProcessJump1[01h * 4],OFFSET C1_0001
        MOV   DWORD PTR ProcessJump1[02h * 4],OFFSET C1_0010
        MOV   DWORD PTR ProcessJump1[03h * 4],OFFSET C1_0011
        MOV   DWORD PTR ProcessJump1[04h * 4],OFFSET C1_0100
        MOV   DWORD PTR ProcessJump1[05h * 4],OFFSET C1_0101
        MOV   DWORD PTR ProcessJump1[06h * 4],OFFSET C1_0110
        MOV   DWORD PTR ProcessJump1[07h * 4],OFFSET C1_0111
        MOV   DWORD PTR ProcessJump1[08h * 4],OFFSET C1_1000
        MOV   DWORD PTR ProcessJump1[09h * 4],OFFSET C1_1001
        MOV   DWORD PTR ProcessJump1[0Ah * 4],OFFSET C1_1010
        MOV   DWORD PTR ProcessJump1[0Bh * 4],OFFSET C1_1011
        MOV   DWORD PTR ProcessJump1[0Ch * 4],OFFSET C1_1100
        MOV   DWORD PTR ProcessJump1[0Dh * 4],OFFSET C1_1101
        MOV   DWORD PTR ProcessJump1[0Eh * 4],OFFSET C1_1110
        MOV   DWORD PTR ProcessJump1[0Fh * 4],OFFSET C1_1111

        MOV   BYTE PTR ProcessSet,1
TableFilled:

  ; loop until the buffer is filled

        MOV   ESI,DWORD PTR AUDC
        SHL   ESI,2
        AND   ESI,03Ch
        MOV   ESI,DWORD PTR ProcessJump0[ESI]
        MOV   DWORD PTR RepData1,ESI

        MOV   ESI,DWORD PTR AUDC[4]
        SHL   ESI,2
        AND   ESI,03Ch
        MOV   ESI,DWORD PTR ProcessJump1[ESI]
        MOV   DWORD PTR RepData2,ESI

        MOV   SI,WORD PTR Samp_N_Max
        MOV   WORD PTR RepData3,SI

  ; Load commonly-used values into registers

        MOV   AH,0FFh
        MOV   BL,BYTE PTR OutVol
        MOV   BH,BYTE PTR OutVol[4]
        MOV   CL,BYTE PTR AUDV
        MOV   CH,BYTE PTR AUDV[4]
        MOV   DL,BYTE PTR Div_N_Max
        MOV   DH,BYTE PTR Div_N_Max[4]

  ; Start the loop

        CLD
        CMP   DWORD PTR N,0
        JZ    GetOut

  ; Set the Pitfall II index

        MOV   DWORD PTR Pf2Index,0

CheckN:

  ; Process channel 0

  ; If the game is Pitfall II, read from its buffer instead

        TEST  BYTE PTR ProcessPf2,0FFh
        JZ    Rep1
        MOV   ESI,DWORD PTR Pf2Index
        MOV   BL,BYTE PTR Pf2Buf[ESI]
        JMP   Channel1
Rep1:

        MOV   ESI,DWORD PTR RepData1
        JMP   ESI

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   ESI,DWORD PTR RepData2
        JMP   ESI

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
        MOV   SI,WORD PTR RepData3
        ADD   WORD PTR Samp_N_Cnt,SI

        MOV   AL,BL
        ADD   AL,BH

;      OV0     := OutVol_0 - (_audv0 Div 2);
;      OV1     := OutVol_1 - (_audv1 Div 2);
;      _OutVol := (OV0 + OV1) + 128;

        STOSB

        INC   DWORD PTR Pf2Index

        DEC   DWORD PTR N
        JNZ   CheckN

; ------------------------------------------------------

GetOut:
        MOV   BYTE PTR OutVol,BL
        MOV   BYTE PTR OutVol[4],BH
        POP   EBX
        POP   ESI
        POP   EDI
        POP   EBP
        RET
ProcessSound endp

        end
