     1                                  ; ****************************************************************************
     2                                  ; PLAYWAV.ASM - ICH AC97 .wav player for DOS.			   PLAYWAV.COM
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; Last Update: 17/02/2017
     5                                  ; ----------------------------------------------------------------------------
     6                                  ; Beginning: 17/02/2017
     7                                  ; ----------------------------------------------------------------------------
     8                                  ; Assembler: NASM version 2.11
     9                                  ;	     nasm playwav.asm -l playwav.lst -o PLAYWAV.COM	
    10                                  ; ----------------------------------------------------------------------------
    11                                  ; Derived from '.wav file player for DOS' Jeff Leyda, Sep 02, 2002 
    12                                  ; ****************************************************************************
    13                                  ; Modidified from 'PLAYER.COM' for VIA VT8233 wav player source code by
    14                                  ; (PLAYER.ASM) by Erdogan Tan (07/11/2016 - 08/12/2016)
    15                                  
    16                                  [BITS 16]
    17                                  
    18                                  [ORG 100h] 
    19                                  
    20                                  	%include 'ac97.inc' ; 17/02/2017
     1                              <1> ; 17/02/2017 (Erdogan Tan, PLAYWAV.ASM)
     2                              <1> ; constant.inc & codec.inc (for ICH AC97 wav player, 'PLAYWAV.COM') 
     3                              <1> 
     4                              <1> ; ----------------------------------------------------------------------------
     5                              <1> ; CONSTANT.INC
     6                              <1> ; ----------------------------------------------------------------------------
     7                              <1> 
     8                              <1> ;constants of stuff that seem hard to remember at times.
     9                              <1> 
    10                              <1> TRUE  EQU 1
    11                              <1> FALSE EQU 0
    12                              <1> 
    13                              <1> ENABLED  EQU 1
    14                              <1> DISABLED EQU 0
    15                              <1> 
    16                              <1> BIT0  EQU 1
    17                              <1> BIT1  EQU 2
    18                              <1> BIT2  EQU 4
    19                              <1> BIT3  EQU 8
    20                              <1> BIT4  EQU 10h
    21                              <1> BIT5  EQU 20h
    22                              <1> BIT6  EQU 40h
    23                              <1> BIT7  EQU 80h
    24                              <1> BIT8  EQU 100h
    25                              <1> BIT9  EQU 200h
    26                              <1> BIT10 EQU 400h
    27                              <1> BIT11 EQU 800h
    28                              <1> BIT12 EQU 1000h
    29                              <1> BIT13 EQU 2000h
    30                              <1> BIT14 EQU 4000h
    31                              <1> BIT15 EQU 8000h
    32                              <1> BIT16 EQU 10000h
    33                              <1> BIT17 EQU 20000h
    34                              <1> BIT18 EQU 40000h
    35                              <1> BIT19 EQU 80000h
    36                              <1> BIT20 EQU 100000h
    37                              <1> BIT21 EQU 200000h
    38                              <1> BIT22 EQU 400000h
    39                              <1> BIT23 EQU 800000h
    40                              <1> BIT24 EQU 1000000h
    41                              <1> BIT25 EQU 2000000h
    42                              <1> BIT26 EQU 4000000h
    43                              <1> BIT27 EQU 8000000h
    44                              <1> BIT28 EQU 10000000h
    45                              <1> BIT29 EQU 20000000h
    46                              <1> BIT30 EQU 40000000h
    47                              <1> BIT31 EQU 80000000h
    48                              <1> 
    49                              <1> ;special characters
    50                              <1> NUL     EQU 0
    51                              <1> NULL    EQU 0
    52                              <1> BELL    EQU 07
    53                              <1> BS      EQU 08
    54                              <1> TAB     EQU 09
    55                              <1> LF      EQU 10
    56                              <1> CR      EQU 13
    57                              <1> ESCAPE  EQU 27           ;ESC is a reserved word....
    58                              <1> 
    59                              <1> 
    60                              <1> ;file stuff
    61                              <1> READONLY  EQU   BIT0
    62                              <1> HIDDEN    EQU   BIT1
    63                              <1> SYSTEM    EQU   BIT2
    64                              <1> VOLUME    EQU   BIT3         ;ignored for file access
    65                              <1> DIRECTORY EQU   BIT4         ;must be 0 for file access
    66                              <1> ARCHIVE   EQU   BIT5
    67                              <1> SHAREABLE EQU   BIT7         ;for novell networks
    68                              <1> OPEN	EQU	2		; open existing file
    69                              <1> CREATE	EQU	1		; create new file
    70                              <1> 
    71                              <1> 
    72                              <1> ; PCI equates
    73                              <1> ; PCI function address (PFA)
    74                              <1> ; bit 31 = 1
    75                              <1> ; bit 23:16 = bus number     (0-255)
    76                              <1> ; bit 15:11 = device number  (0-31)
    77                              <1> ; bit 10:8 = function number (0-7)
    78                              <1> ; bit 7:0 = register number  (0-255)
    79                              <1> 
    80                              <1> IO_ADDR_MASK    EQU     0FFFEh          ; mask off bit 0 for reading BARs
    81                              <1> PCI_INDEX_PORT  EQU     0CF8h
    82                              <1> PCI_DATA_PORT   EQU     0CFCh
    83                              <1> PCI32           EQU     BIT31           ; bitflag to signal 32bit access
    84                              <1> PCI16           EQU     BIT30           ; bitflag for 16bit access
    85                              <1> 
    86                              <1> PCI_FN0         EQU     0 << 8
    87                              <1> PCI_FN1         EQU     1 << 8
    88                              <1> PCI_FN2         EQU     2 << 8
    89                              <1> PCI_FN3         EQU     3 << 8
    90                              <1> PCI_FN4         EQU     4 << 8
    91                              <1> PCI_FN5         EQU     5 << 8
    92                              <1> PCI_FN6         EQU     6 << 8
    93                              <1> PCI_FN7         EQU     7 << 8
    94                              <1> 
    95                              <1> PCI_CMD_REG		EQU	04h		; reg 04, command reg
    96                              <1>  IO_ENA			EQU	BIT0		; i/o decode enable
    97                              <1>  MEM_ENA		EQU	BIT1		; memory decode enable
    98                              <1>  BM_ENA                 EQU     BIT2		; bus master enable
    99                              <1> 
   100                              <1> ; ----------------------------------------------------------------------------
   101                              <1> ; CODEC.INC
   102                              <1> ; ----------------------------------------------------------------------------
   103                              <1> 
   104                              <1> ;Codec registers.
   105                              <1> ;
   106                              <1> ;Not all codecs are created equal. Refer to the spec for your specific codec.
   107                              <1> ;
   108                              <1> ;All registers are 16bits wide.  Access to codec registers over the AC97 link
   109                              <1> ;is defined by the OEM.  
   110                              <1> ;
   111                              <1> ;Secondary codec's are accessed by ORing in BIT7 of all register accesses.
   112                              <1> ;
   113                              <1> 
   114                              <1> ; each codec/mixer register is 16bits
   115                              <1> 
   116                              <1> CODEC_RESET_REG                 equ     00      ; reset codec
   117                              <1> CODEC_MASTER_VOL_REG            equ     02      ; master volume
   118                              <1> CODEC_HP_VOL_REG                equ     04      ; headphone volume
   119                              <1> CODEC_MASTER_MONO_VOL_REG       equ     06      ; master mono volume
   120                              <1> CODEC_MASTER_TONE_REG           equ     08      ; master tone (R+L)
   121                              <1> CODEC_PCBEEP_VOL_REG            equ     0ah     ; PC beep volume
   122                              <1> CODEC_PHONE_VOL_REG             equ     0bh     ; phone volume
   123                              <1> CODEC_MIC_VOL_REG               equ     0eh     ; MIC volume
   124                              <1> CODEC_LINE_IN_VOL_REG           equ     10h     ; line input volume
   125                              <1> CODEC_CD_VOL_REG                equ     12h     ; CD volume
   126                              <1> CODEC_VID_VOL_REG               equ     14h     ; video volume
   127                              <1> CODEC_AUX_VOL_REG               equ     16h     ; aux volume
   128                              <1> CODEC_PCM_OUT_REG               equ     18h     ; PCM output volume
   129                              <1> CODEC_RECORD_SELECT_REG         equ     1ah     ; record select input
   130                              <1> CODEC_RECORD_VOL_REG            equ     1ch     ; record volume
   131                              <1> CODEC_RECORD_MIC_VOL_REG        equ     1eh     ; record mic volume
   132                              <1> CODEC_GP_REG                    equ     20h     ; general purpose
   133                              <1> CODEC_3D_CONTROL_REG            equ     22h     ; 3D control
   134                              <1> ; 24h is reserved
   135                              <1> CODEC_POWER_CTRL_REG            equ     26h     ; powerdown control
   136                              <1> CODEC_EXT_AUDIO_REG             equ     28h     ; extended audio
   137                              <1> CODEC_EXT_AUDIO_CTRL_REG        equ     2ah     ; extended audio control
   138                              <1> CODEC_PCM_FRONT_DACRATE_REG     equ     2ch     ; PCM out sample rate
   139                              <1> CODEC_PCM_SURND_DACRATE_REG     equ     2eh     ; surround sound sample rate
   140                              <1> CODEC_PCM_LFE_DACRATE_REG       equ     30h     ; LFE sample rate
   141                              <1> CODEC_LR_ADCRATE_REG            equ     32h     ; PCM in sample rate
   142                              <1> CODEC_MIC_ADCRATE_REG           equ     34h     ; mic in sample rate
   143                              <1> 
   144                              <1> ; registers 36-7a are reserved on the ICH
   145                              <1> 
   146                              <1> CODEC_VENDORID1_REG             equ     7ch     ; codec vendor ID 1
   147                              <1> CODEC_VENDORID2_REG             equ     7eh     ; codec vendor ID 2
   148                              <1> 
   149                              <1> ; Mixer registers 0 through 51h reside in the ICH and are not forwarded over
   150                              <1> ; the AC97 link to the codec, which I think is a little weird.  Looks like
   151                              <1> ; the ICH makes it so you don't need a fully functional codec to play audio?
   152                              <1> ;
   153                              <1> ; whenever 2 codecs are present in the system, use BIT7 to access the 2nd
   154                              <1> ; set of registers, ie 80h-feh
   155                              <1> 
   156                              <1> PRIMARY_CODEC                   equ     0       ; 0-7F for primary codec
   157                              <1> SECONDARY_CODEC                 equ     BIT7    ; 80-8f registers for 2ndary
   158                              <1> 
   159                              <1> SAMPLE_RATE_441khz	equ     44100   ; 44.1Khz (cd quality) rate
   160                              <1> 
   161                              <1> ; ----------------------------------------------------------------------------
   162                              <1> ; 17/02/2017
   163                              <1> PCI_IO_BASE	equ 10h			; = NAMBAR register offset
   164                              <1> AC97_INT_LINE   equ 3Ch			; AC97 Interrupt Line register offset
   165                              <1> 
   166                              <1> ; ----------------------------------------------------------------------------
   167                              <1> ; ICH2AC97.INC
   168                              <1> ; ----------------------------------------------------------------------------
   169                              <1> 
   170                              <1> ; PCI stuff
   171                              <1> 
   172                              <1> ; Intel ICH2 equates. It is assumed that ICH0 and plain ole ICH are compatible.
   173                              <1> 
   174                              <1> INTEL_VID       equ     8086h           ; Intel's PCI vendor ID
   175                              <1> ICH_DID         equ     2415h           ; ICH device ID
   176                              <1> ICH0_DID        equ     2425h           ; ICH0
   177                              <1> ICH2_DID        equ     2445h           ; ICH2 I think there are more ICHes.
   178                              <1>                                         ; they all should be compatible.
   179                              <1> 
   180                              <1> ; 17/02/2017 (Erdogan Tan, ref: ALSA Device IDs, ALSA project)
   181                              <1> ICH3_DID	equ     2485h           ; ICH3
   182                              <1> ICH4_DID        equ     24C5h           ; ICH4
   183                              <1> ICH5_DID	equ     24D5h           ; ICH5 
   184                              <1> ICH6_DID	equ     266Eh           ; ICH6
   185                              <1> ESB6300_DID	equ     25A6h           ; 6300ESB
   186                              <1> ESB631X_DID	equ     2698h           ; 631XESB
   187                              <1> ICH7_DID	equ	27DEh		; ICH7
   188                              <1> ;
   189                              <1> 
   190                              <1> NAMBAR_REG      equ     10h             ; native audio mixer BAR
   191                              <1>  NAM_SIZE       equ     256             ; 256 bytes required.
   192                              <1> 
   193                              <1> NABMBAR_REG     equ     14h             ; native audio bus mastering BAR
   194                              <1>  NABM_SIZE      equ     64              ; 64 bytes
   195                              <1> 
   196                              <1> ; BUS master registers, accessed via NABMBAR+offset
   197                              <1> 
   198                              <1> ; ICH supports 3 different types of register sets for three types of things
   199                              <1> ; it can do, thus:
   200                              <1> ;
   201                              <1> ; PCM in (for recording) aka PI
   202                              <1> ; PCM out (for playback) aka PO
   203                              <1> ; MIC in (for recording) aka MC
   204                              <1> 
   205                              <1> PI_BDBAR_REG            equ     0       ; PCM in buffer descriptor BAR
   206                              <1> PO_BDBAR_REG            equ     10h     ; PCM out buffer descriptor BAR
   207                              <1> MC_BDBAR_REG            equ     20h     ; MIC in buffer descriptor BAR
   208                              <1> 
   209                              <1> ; each buffer descriptor BAR holds a pointer which has entries to the buffer
   210                              <1> ; contents of the .WAV file we're going to play.  Each entry is 8 bytes long
   211                              <1> ; (more on that later) and can contain 32 entries total, so each BAR is
   212                              <1> ; 256 bytes in length, thus:
   213                              <1> 
   214                              <1> BDL_SIZE                equ     32*8    ; Buffer Descriptor List size
   215                              <1> INDEX_MASK              equ     31      ; indexes must be 0-31
   216                              <1> 
   217                              <1> 
   218                              <1> 
   219                              <1> PI_CIV_REG              equ     4       ; PCM in current Index value (RO)
   220                              <1> PO_CIV_REG              equ     14h     ; PCM out current Index value (RO)
   221                              <1> MC_CIV_REG              equ     24h     ; MIC in current Index value (RO)
   222                              <1> ;8bit read only
   223                              <1> ; each current index value is simply a pointer showing us which buffer
   224                              <1> ; (0-31) the codec is currently processing.  Once this counter hits 31, it
   225                              <1> ; wraps back to 0.
   226                              <1> ; this can be handy to know, as once it hits 31, we're almost out of data to
   227                              <1> ; play back or room to record!
   228                              <1> 
   229                              <1> 
   230                              <1> PI_LVI_REG              equ     5       ; PCM in Last Valid Index
   231                              <1> PO_LVI_REG              equ     15h     ; PCM out Last Valid Index
   232                              <1> MC_LVI_REG              equ     25h     ; MIC in Last Valid Index
   233                              <1> ;8bit read/write
   234                              <1> ; The Last Valid Index is a number (0-31) to let the codec know what buffer
   235                              <1> ; number to stop on after processing.  It could be very nasty to play audio
   236                              <1> ; from buffers that aren't filled with the audio we want to play.
   237                              <1> 
   238                              <1> 
   239                              <1> PI_SR_REG               equ     6       ; PCM in Status register
   240                              <1> PO_SR_REG               equ     16h     ; PCM out Status register
   241                              <1> MC_SR_REG               equ     26h     ; MIC in Status register
   242                              <1> ;16bit read/write
   243                              <1> ; status registers.  Bitfields follow:
   244                              <1> 
   245                              <1> FIFO_ERR                equ     BIT4    ; FIFO Over/Underrun W1TC.
   246                              <1> 
   247                              <1> BCIS                    equ     BIT3    ; buffer completion interrupt status.
   248                              <1>                                         ; Set whenever the last sample in ANY
   249                              <1>                                         ; buffer is finished.  Bit is only
   250                              <1>                                         ; set when the Interrupt on Complete
   251                              <1>                                         ; (BIT4 of control reg) is set.
   252                              <1> 
   253                              <1> LVBCI                   equ     BIT2    ; Set whenever the codec has processed
   254                              <1>                                         ; the last buffer in the buffer list.
   255                              <1>                                         ; Will fire an interrupt if IOC bit is
   256                              <1>                                         ; set. Probably set after the last
   257                              <1>                                         ; sample in the last buffer is
   258                              <1>                                         ; processed.  W1TC
   259                              <1> 
   260                              <1>                                         ; 
   261                              <1> CELV                    equ     BIT1    ; Current buffer == last valid.
   262                              <1>                                         ; Bit is RO and remains set until LVI is
   263                              <1>                                         ; cleared.  Probably set up the start
   264                              <1>                                         ; of processing for the last buffer.
   265                              <1> 
   266                              <1> 
   267                              <1> DCH                     equ     BIT0    ; DMA controller halted.
   268                              <1>                                         ; set whenever audio stream is stopped
   269                              <1>                                         ; or something else goes wrong.
   270                              <1> 
   271                              <1> 
   272                              <1> PI_PICB_REG             equ     8       ; PCM in position in current buffer(RO)
   273                              <1> PO_PICB_REG             equ     18h     ; PCM out position in current buffer(RO)
   274                              <1> MC_PICB_REG             equ     28h     ; MIC in position in current buffer (RO)
   275                              <1> ;16bit read only
   276                              <1> ; position in current buffer regs show the number of dwords left to be
   277                              <1> ; processed in the current buffer.
   278                              <1> ; 
   279                              <1> 
   280                              <1> PI_PIV_REG              equ     0ah     ; PCM in Prefected index value
   281                              <1> PO_PIV_REG              equ     1ah     ; PCM out Prefected index value
   282                              <1> MC_PIV_REG              equ     2ah     ; MIC in Prefected index value
   283                              <1> ;8bit, read only
   284                              <1> ; Prefetched index value register.
   285                              <1> ; tells which buffer number (0-31) has be prefetched.  I'd imagine this
   286                              <1> ; value follows the current index value fairly closely. (CIV+1)
   287                              <1> ;
   288                              <1> 
   289                              <1> 
   290                              <1> PI_CR_REG               equ     0bh     ; PCM in Control Register
   291                              <1> PO_CR_REG               equ     1bh     ; PCM out Control Register
   292                              <1> MC_CR_REG               equ     2bh     ; MIC in Control Register
   293                              <1> ; 8bit
   294                              <1> ; Control register *MUST* only be accessed as an 8bit value.
   295                              <1> ; Control register.  See bitfields below.
   296                              <1> ;
   297                              <1> 
   298                              <1> 
   299                              <1> IOCE                    equ     BIT4    ; interrupt on complete enable.
   300                              <1>                                         ; set this bit if you want an intrtpt
   301                              <1>                                         ; to fire whenever LVBCI is set.
   302                              <1> FEIFE                   equ     BIT3    ; set if you want an interrupt to fire
   303                              <1>                                         ; whenever there is a FIFO (over or
   304                              <1>                                         ; under) error.
   305                              <1> LVBIE                   equ     BIT2    ; last valid buffer interrupt enable.
   306                              <1>                                         ; set if you want an interrupt to fire
   307                              <1>                                         ; whenever the completion of the last
   308                              <1>                                         ; valid buffer.
   309                              <1> RR                      equ     BIT1    ; reset registers.  Nukes all regs
   310                              <1>                                         ; except bits 4:2 of this register.
   311                              <1>                                         ; Only set this bit if BIT 0 is 0
   312                              <1> RPBM                    equ     BIT0    ; Run/Pause
   313                              <1>                                         ; set this bit to start the codec!
   314                              <1> 
   315                              <1> 
   316                              <1> GLOB_CNT_REG            equ     2ch     ; Global control register
   317                              <1> SEC_RES_EN              equ     BIT5    ; secondary codec resume event 
   318                              <1>                                         ; interrupt enable.  Not used here.
   319                              <1> PRI_RES_EN              equ     BIT4    ; ditto for primary. Not used here.
   320                              <1> ACLINK_OFF              equ     BIT3    ; Turn off the AC97 link
   321                              <1> ACWARM_RESET            equ     BIT2    ; Awaken the AC97 link from sleep.
   322                              <1>                                         ; registers preserved, bit self clears
   323                              <1> ACCOLD_RESET            equ     BIT1    ; Reset everything in the AC97 and
   324                              <1>                                         ; reset all registers.  Not self clearing
   325                              <1> 
   326                              <1> GPIIE                   equ     BIT0    ; GPI Interrupt enable.
   327                              <1>                                         ; set if you want an interrupt to
   328                              <1>                                         ; fire upon ANY of the bits in the
   329                              <1>                                         ; GPI (general pursose inputs?) not used.
   330                              <1> 
   331                              <1> GLOB_STS_REG            equ     30h     ; Global Status register (RO)
   332                              <1> 
   333                              <1> MD3                     equ     BIT17   ; modem powerdown status (yawn)
   334                              <1> AD3                     equ     BIT16   ; Audio powerdown status (yawn)
   335                              <1> RD_COMPLETE_STS         equ     BIT15   ; Codec read timed out. 0=normal
   336                              <1> BIT3SLOT12              equ     BIT14   ; shadowed status of bit 3 in slot 12
   337                              <1> BIT2SLOT12              equ     BIT13   ; shadowed status of bit 2 in slot 12
   338                              <1> BIT1SLOT12              equ     BIT12   ; shadowed status of bit 1 in slot 12
   339                              <1> SEC_RESUME_STS          equ     BIT11   ; secondary codec has resumed (and irqed)
   340                              <1> PRI_RESUME_STS          equ     BIT10   ; primary codec has resumed (and irqed)
   341                              <1> SEC_CODEC_RDY           equ     BIT9    ; secondary codec is ready for action
   342                              <1> PRI_CODEC_RDY           equ     BIT8    ; Primary codec is ready for action
   343                              <1>                                         ; software must check these bits before
   344                              <1>                                         ; starting the codec!
   345                              <1> MIC_IN_IRQ              equ     BIT7    ; MIC in caused an interrupt
   346                              <1> PCM_OUT_IRQ             equ     BIT6    ; One of the PCM out channels IRQed
   347                              <1> PCM_IN_IRQ              equ     BIT5    ; One of the PCM in channels IRQed
   348                              <1> MODEM_OUT_IRQ           equ     BIT2    ; modem out channel IRQed
   349                              <1> MODEM_IN_IRQ            equ     BIT1    ; modem in channel IRQed
   350                              <1> GPI_STS_CHANGE          equ     BIT0    ; set whenever GPI's have changed.
   351                              <1>                                         ; BIT0 of slot 12 also reflects this.
   352                              <1> 
   353                              <1> 
   354                              <1> ACC_SEMA_REG            equ     34h     ; Codec write semiphore register
   355                              <1> CODEC_BUSY              equ     BIT0    ; codec register I/O is happening
   356                              <1>                                         ; self clearing
   357                              <1> ;
   358                              <1> ; Buffer Descriptors List
   359                              <1> ; As stated earlier, each buffer descriptor list is a set of (up to) 32 
   360                              <1> ; descriptors, each 8 bytes in length.  Bytes 0-3 of a descriptor entry point
   361                              <1> ; to a chunk of memory to either play from or record to.  Bytes 4-7 of an
   362                              <1> ; entry describe various control things detailed below.
   363                              <1> ; 
   364                              <1> ; Buffer pointers must always be aligned on a Dword boundry.
   365                              <1> ;
   366                              <1> ;
   367                              <1> 
   368                              <1> IOC                     equ     BIT31   ; Fire an interrupt whenever this
   369                              <1>                                         ; buffer is complete.
   370                              <1> 
   371                              <1> BUP                     equ     BIT30   ; Buffer Underrun Policy.
   372                              <1>                                         ; if this buffer is the last buffer
   373                              <1>                                         ; in a playback, fill the remaining
   374                              <1>                                         ; samples with 0 (silence) or not.
   375                              <1>                                         ; It's a good idea to set this to 1
   376                              <1>                                         ; for the last buffer in playback,
   377                              <1>                                         ; otherwise you're likely to get a lot
   378                              <1>                                         ; of noise at the end of the sound.
   379                              <1> 
   380                              <1> ;
   381                              <1> ; Bits 15:0 contain the length of the buffer, in number of samples, which
   382                              <1> ; are 16 bits each, coupled in left and right pairs, or 32bits each.
   383                              <1> ; Luckily for us, that's the same format as .wav files.
   384                              <1> ;
   385                              <1> ; A value of FFFF is 65536 samples.  Running at 44.1Khz, that's just about
   386                              <1> ; 1.5 seconds of sample time.  FFFF * 32bits is 1FFFFh bytes or 128k of data.
   387                              <1> ;
   388                              <1> ; A value of 0 in these bits means play no samples.
   389                              <1> ;
    21                                  
    22                                  _STARTUP:
    23                                  
    24                                  ; memory allocation
    25                                  
    26 00000000 E87501                          call    setFree				; deallocate unused DOS mem
    27                                  
    28                                  	; 17/02/2017
    29                                  	; Clear BSS (uninitialized data) area
    30 00000003 31C0                    	xor	ax, ax ; 0
    31 00000005 B92440                  	mov	cx, (EOF - bss_start)/2
    32 00000008 BF[F808]                	mov	di, bss_start
    33 0000000B F3AB                    	rep	stosw
    34                                  
    35                                  ; allocate 256 bytes of data for DCM_OUT Buffer Descriptor List. (BDL)
    36                                  
    37 0000000D B81000                          mov     ax, BDL_SIZE / 16
    38 00000010 E86D01                          call    memAlloc
    39 00000013 A3[1E09]                        mov     [BDL_BUFFER], ax		; segment 
    40                                  
    41                                  ; allocate 2 buffers, 64k each for now.
    42                                  
    43 00000016 B80010                          mov     ax, BUFFERSIZE / 16		; 64k for .WAV file
    44 00000019 E86401                          call    memAlloc
    45 0000001C A3[2009]                        mov     [WAV_BUFFER1], ax		; segment
    46                                  
    47 0000001F B80010                  	mov	ax, BUFFERSIZE / 16
    48 00000022 E85B01                  	call	memAlloc
    49 00000025 A3[2209]                	mov	[WAV_BUFFER2], ax
    50                                  
    51                                  ; Detect/reset AC97 
    52                                  ;
    53 00000028 E8C802                          call    pciFindDevice
    54 0000002B 7342                            jnc     short _1
    55                                  
    56                                  ; couldn't find the audio device!
    57                                  
    58 0000002D 0E                      	push	cs
    59 0000002E 1F                      	pop	ds
    60 0000002F BA[3900]                        mov     dx, noDevMsg
    61 00000032 B409                            mov     ah, 9
    62 00000034 CD21                            int     21h
    63 00000036 E93801                          jmp     exit
    64                                  
    65                                  ; 17/02/2017
    66 00000039 4572726F723A20556E-     noDevMsg db "Error: Unable to find intel ICH based audio device!",CR,LF,"$"
    66 00000042 61626C6520746F2066-
    66 0000004B 696E6420696E74656C-
    66 00000054 204943482062617365-
    66 0000005D 6420617564696F2064-
    66 00000066 6576696365210D0A24 
    67                                  
    68                                  _1:
    69                                  	; eax = BUS/DEV/FN
    70                                  	;	00000000BBBBBBBBDDDDDFFF00000000
    71                                  	; edx = DEV/VENDOR
    72                                  	;	DDDDDDDDDDDDDDDDVVVVVVVVVVVVVVVV
    73                                  
    74 0000006F 66A3[2609]              	mov	[bus_dev_fn], eax
    75 00000073 668916[2A09]            	mov	[dev_vendor], edx
    76                                  
    77                                  	; get ICH base address regs for mixer and bus master
    78                                  
    79 00000078 B010                            mov     al, NAMBAR_REG
    80 0000007A E8E801                          call    pciRegRead16			; read PCI registers 10-11
    81 0000007D 83E2FE                          and     dx, IO_ADDR_MASK 		; mask off BIT0
    82                                  
    83 00000080 8916[1A09]                      mov     [NAMBAR], dx			; save audio mixer base addy
    84                                  
    85 00000084 B014                    	mov     al, NABMBAR_REG
    86 00000086 E8DC01                          call    pciRegRead16
    87 00000089 83E2FE                          and     dx, IO_ADDR_MASK
    88                                  
    89 0000008C 8916[1C09]                      mov     [NABMBAR], dx			; save bus master base addy
    90                                  
    91                                  	; init controller
    92                                  	; 17/02/2017
    93 00000090 B004                    	mov	al, PCI_CMD_REG ; command register (04h)
    94 00000092 E8D001                  	call	pciRegRead16 ; pciRegRead8
    95                                  
    96                                  	; eax = BUS/DEV/FN/REG
    97                                  	;  dx = PCI Command Register Content ; 17/02/2017
    98                                  	; 	00000000CCCCCCCC
    99 00000095 8916[2E09]              	mov	[stats_cmd], dx
   100                                  
   101 00000099 B010                    	mov	al, PCI_IO_BASE ; IO base address register (10h)
   102 0000009B E8D501                  	call	pciRegRead32
   103                                  
   104 0000009E 83E2C0                  	and     dx, 0FFC0h	; IO_ADDR_MASK (0FFFE) ?
   105 000000A1 8916[3009]                      mov     [ac97_io_base], dx
   106                                  
   107 000000A5 B03C                    	mov	al, AC97_INT_LINE ; Interrupt line register (3Ch)
   108 000000A7 E8B301                  	call	pciRegRead8 ; 17/02/2017
   109                                  
   110 000000AA 8816[2509]              	mov     [ac97_int_ln_reg], dl
   111                                  
   112                                  	; 28/11/2016
   113 000000AE BB0100                  	mov	bx, 1
   114 000000B1 30F6                    	xor	dh, dh 	 ; 17/02/2017
   115 000000B3 89D1                    	mov	cx, dx
   116 000000B5 D3E3                    	shl	bx, cl
   117                                  
   118                                  	;not	bx
   119 000000B7 E4A1                    	in	al, 0A1h ; irq 8-15
   120 000000B9 88C4                            mov	ah, al
   121 000000BB E421                            in	al, 21h  ; irq 0-7 
   122                                  	;and	ax, bx   ; unmask
   123 000000BD 0FB3D0                   	btr	ax, dx	 ; unmask
   124 000000C0 E621                    	out	21h, al  ; enable interrupt (if irq <= 7)
   125 000000C2 88E0                    	mov	al, ah
   126 000000C4 E6A1                    	out	0A1h, al ; enable interrupt (if irq > 7)
   127                                  	;not	bx
   128                                  
   129 000000C6 BAD104                  	mov	dx, 4D1h			;8259 ELCR1
   130 000000C9 EC                              in	al, dx
   131 000000CA 88C4                    	mov	ah, al
   132 000000CC BAD004                  	mov	dx, 4D0h 
   133 000000CF EC                              in	al, dx
   134                                  	;or	ax, bx        
   135 000000D0 0FABC8                  	bts	ax, cx
   136 000000D3 BAD004                  	mov	dx, 4D0h
   137 000000D6 EE                      	out	dx, al                          ;set level-triggered mode
   138 000000D7 88E0                    	mov	al, ah
   139 000000D9 BAD104                  	mov	dx, 4D1h
   140 000000DC EE                      	out	dx, al                          ;set level-triggered mode
   141                                  
   142                                  	; 24/11/2016 - Erdogan Tan
   143 000000DD 89CB                    	mov	bx, cx
   144                                  	;mov	bx, dx
   145 000000DF 8A9F[DE07]              	mov	bl, [bx+irq_int]
   146 000000E3 C1E302                  	shl	bx, 2 ; * 4
   147                                  
   148                                  	; set up interrupt vector
   149                                  	; 30/11/2016
   150 000000E6 06                      	push	es
   151 000000E7 31C0                    	xor	ax, ax
   152 000000E9 8EC0                    	mov	es, ax
   153 000000EB 26C707[3607]            	mov	word [es:bx], ac97_int_handler
   154 000000F0 8CC8                    	mov	ax, cs
   155 000000F2 26894702                	mov	[es:bx+2], ax
   156 000000F6 07                      	pop	es
   157                                  		
   158 000000F7 E8CC04                  	call	write_ac97_dev_info 
   159                                  
   160                                  ; check the command line for a file to play
   161                                  
   162                                          ;push    ds
   163 000000FA E88C00                          call    processCmdline			; get the filename
   164                                  
   165                                  ; open the file
   166 000000FD B002                            mov     al, OPEN                        ; open existing file
   167 000000FF E8A700                          call    openFile                        ; no error? ok.
   168                                          ;pop     ds
   169 00000102 7322                            jnc     short _gsr
   170                                  
   171                                  ; file not found!
   172                                  
   173                                          ;push   cs
   174                                          ;pop    ds
   175 00000104 BA[0D01]                        mov	dx, noFileErrMsg
   176 00000107 B409                            mov     ah, 9
   177 00000109 CD21                            int     21h
   178 0000010B EB64                            jmp     exit
   179                                  
   180 0000010D 4572726F723A206669-     noFileErrMsg  db "Error: file not found.",CR,LF,"$"
   180 00000116 6C65206E6F7420666F-
   180 0000011F 756E642E0D0A24     
   181                                  
   182                                  _gsr:
   183 00000126 E8A700                          call    getSampleRate                   ; read the sample rate
   184                                                                                  ; pass it onto codec.
   185 00000129 7246                    	jc	short exit ; 19/11/2016 - nothing to do
   186                                  
   187 0000012B A3[3209]                	mov	[sample_rate], ax
   188                                  	; 19/11/2016
   189 0000012E 880E[3409]              	mov	[stmo], cl
   190 00000132 8816[3609]              	mov	[bps], dl
   191                                  
   192                                  	; 17/02/2017
   193 00000136 C606[3809]00            	mov	byte [fbs_shift], 0 ; 0 = stereo and 16 bit 
   194 0000013B FEC9                    	dec	cl
   195 0000013D 7504                    	jnz	short _gsr_1 ; stereo
   196 0000013F FE06[3809]              	inc	byte [fbs_shift] ; 1 = mono or 8 bit		
   197                                  _gsr_1:	
   198 00000143 80FA08                  	cmp	dl, 8 
   199 00000146 7704                    	ja	short _gsr_2 ; 16 bit samples
   200 00000148 FE06[3809]              	inc	byte [fbs_shift] ; 2 = mono and 8 bit
   201                                  _gsr_2:	
   202 0000014C E89605                  	call	write_sample_rate
   203                                  
   204                                  	; 17/02/2017
   205 0000014F 8B16[2E09]              	mov	dx, [stats_cmd]
   206 00000153 80CA05                          or      dl, IO_ENA+BM_ENA               ; enable IO and bus master
   207 00000156 E87E01                          call    pciRegWrite16 ; pciRegWrite8
   208                                  
   209                                  ; setup the Codec (actually mixer registers) 
   210 00000159 E8D801                          call    codecConfig                     ; unmute codec, set rates.
   211                                  
   212                                  ;
   213                                  ; position file pointer to start in actual wav data
   214                                  ; MUCH improvement should really be done here to check if sample size is
   215                                  ; supported, make sure there are 2 channels, etc.  
   216                                  ;
   217 0000015C B442                            mov     ah, 42h
   218 0000015E B000                            mov     al, 0                           ; from start of file
   219 00000160 8B1E[1409]                      mov     bx, [filehandle]
   220 00000164 31C9                            xor     cx, cx
   221 00000166 BA2C00                          mov     dx, 44                          ; jump past .wav/riff header
   222 00000169 CD21                            int     21h
   223                                  
   224                                  ; play the .wav file.  Most of the good stuff is in here.
   225                                  
   226 0000016B E84D02                          call    playWav
   227                                  
   228                                  ; close the .wav file and exit.
   229                                  
   230 0000016E E84A00                          call    closeFile
   231                                  
   232                                  exit:
   233 00000171 B8004C                          mov     ax, 4c00h
   234 00000174 CD21                    	int 	21h
   235                                  
   236                                  here:
   237 00000176 EBFE                    	jmp	short here
   238                                  
   239                                  ; MEMALLOC.ASM
   240                                  ;-- SETFREE: Release memory not used  ----------------
   241                                  ;-- Input    : ES = address of PSP
   242                                  ;-- Output   : none
   243                                  ;-- Register : AX, BX, CL and FLAGS are changed 
   244                                  ;-- Info     : Since the stack-segment is always the last segment in an 
   245                                  ;              EXE-file, ES:0000 points to the beginning and SS:SP
   246                                  ;              to the end of the program in memory. Through this the
   247                                  ;              length of the program can be calculated 
   248                                  ; call this routine once at the beginning of the program to free up memory
   249                                  ; assigned to it by DOS.
   250                                  
   251                                  setFree:
   252 00000178 BB0010                  	  mov	bx, 65536/16	; 4K paragraphs ; 17/02/2017 (Erdogan Tan)		
   253                                  
   254 0000017B B44A                              mov	ah, 4ah		;pass new length to DOS
   255 0000017D CD21                              int	21h
   256                                  
   257 0000017F C3                                retn			; back to caller 
   258                                  				; new size (allocated memory) = 64KB
   259                                  
   260                                  memAlloc:
   261                                  ; input: AX = # of paragraphs required
   262                                  ; output: AX = segment of block to use
   263                                  
   264 00000180 53                      	push	bx
   265 00000181 89C3                    	mov	bx, ax
   266 00000183 B448                    	mov	ah, 48h
   267 00000185 CD21                    	int	21h
   268 00000187 5B                      	pop	bx
   269 00000188 C3                      	retn
   270                                  
   271                                  ; CMDLINE.ASM
   272                                  ; parse the command line
   273                                  ; entry: none
   274                                  ; exit: DS:DX to the 1st supplied item on the command line 
   275                                  
   276                                  processCmdline:
   277 00000189 53                              push    bx
   278 0000018A 56                              push    si
   279                                  
   280                                          ;mov    ah, 51h
   281                                          ;int    21h
   282                                          ;mov    ds, bx
   283                                  
   284 0000018B BE8000                          mov     si, 80h
   285 0000018E 0FB61C                          movzx   bx, byte [si]
   286 00000191 01DE                            add     si, bx
   287 00000193 46                              inc     si
   288                                  
   289 00000194 C60400                          mov     byte [si], NULL         ; zero terminate
   290                                  
   291 00000197 BE8100                          mov     si, 81h
   292                                  
   293                                  cmdlineloop:
   294 0000019A AC                              lodsb
   295                                  
   296 0000019B 3C00                            cmp     al, NULL                ; found end of line?
   297 0000019D 7404                            je      short exitpc
   298 0000019F 3C20                            cmp     al, ' '                 ; found a space?
   299 000001A1 74F7                            je      short cmdlineloop
   300                                  
   301                                          ; must be the filename here.
   302                                  exitpc:
   303 000001A3 4E                              dec     si                      ; point to start of filename
   304 000001A4 89F2                            mov     dx, si
   305 000001A6 5E                              pop     si
   306 000001A7 5B                              pop     bx
   307 000001A8 C3                      	retn
   308                                  
   309                                  ; FILE.ASM
   310                                  ;open or create file
   311                                  ;
   312                                  ;input: ds:dx-->filename (asciiz)
   313                                  ;       al=file Mode (create or open)
   314                                  ;output: none  cs:[filehandle] filled
   315                                  ;
   316                                  openFile:
   317 000001A9 50                      	push	ax
   318 000001AA 51                      	push	cx
   319 000001AB B43B                    	mov	ah, 3bh			; start with a mode
   320 000001AD 00C4                    	add	ah, al			; add in create or open mode
   321 000001AF 31C9                    	xor	cx, cx
   322 000001B1 CD21                    	int	21h
   323 000001B3 7203                    	jc	short _of1
   324                                  	;mov	[cs:filehandle], ax
   325 000001B5 A3[1409]                	mov	[filehandle], ax
   326                                  _of1:
   327 000001B8 59                      	pop	cx
   328 000001B9 58                      	pop	ax
   329 000001BA C3                      	retn
   330                                  
   331                                  ; close the currently open file
   332                                  ; input: none, uses cs:[filehandle]
   333                                  closeFile:
   334 000001BB 50                      	push	ax
   335 000001BC 53                      	push	bx
   336 000001BD 833E[1409]FF            	cmp	word [filehandle], -1
   337 000001C2 7409                    	jz	short _cf1
   338 000001C4 8B1E[1409]              	mov     bx, [filehandle]  
   339 000001C8 B8003E                  	mov     ax,3e00h
   340 000001CB CD21                            int     21h              ;close file
   341                                  _cf1:
   342 000001CD 5B                      	pop	bx
   343 000001CE 58                      	pop	ax
   344 000001CF C3                      	retn
   345                                  
   346                                  getSampleRate:
   347                                  	; 08/12/2016
   348                                  ; reads the sample rate from the .wav file.
   349                                  ; entry: none - assumes file is already open
   350                                  	; 19/11/2016 - Erdogan Tan
   351                                  ; exit: ax = sample rate (11025, 22050, 44100, 48000)
   352                                  ;	cx = number of channels (mono=1, stereo=2)
   353                                  ;	dx = bits per sample (8, 16)
   354                                  
   355 000001D0 53                      	push    bx
   356                                  
   357 000001D1 B442                            mov     ah, 42h
   358 000001D3 B000                            mov     al, 0				; from start of file
   359 000001D5 8B1E[1409]                      mov     bx, [filehandle]
   360 000001D9 31C9                            xor     cx, cx
   361 000001DB BA0800                          mov     dx, 08h				; "WAVE"
   362 000001DE CD21                            int     21h
   363                                  
   364 000001E0 BA[F808]                        mov     dx, smpRBuff
   365 000001E3 B91C00                          mov     cx, 28				; 28 bytes
   366 000001E6 B43F                    	mov	ah, 3fh
   367 000001E8 CD21                            int     21h
   368                                  
   369 000001EA 813E[F808]5741          	cmp	word [smpRBuff], 'WA'
   370 000001F0 751C                    	jne	short gsr_stc
   371                                  
   372 000001F2 813E[FA08]5645          	cmp	word [smpRBuff+2], 'VE'
   373 000001F8 7514                    	jne	short gsr_stc
   374                                  
   375 000001FA 833E[0409]01            	cmp	word [smpRBuff+12], 1	; Offset 20, must be 1 (= PCM)
   376 000001FF 750D                    	jne	short gsr_stc
   377                                  
   378                                  
   379 00000201 8B0E[0609]              	mov	cx, [smpRBuff+14]	; return num of channels in CX
   380 00000205 A1[0809]                        mov     ax, [smpRBuff+16]	; return sample rate in AX
   381 00000208 8B16[1209]              	mov	dx, [smpRBuff+26]	; return bits per sample value in DX
   382                                  gsr_retn:
   383 0000020C 5B                              pop     bx
   384 0000020D C3                              retn
   385                                  
   386                                  gsr_stc:
   387 0000020E F9                      	stc
   388 0000020F EBFB                    	jmp	short gsr_retn
   389                                  
   390                                  %include 'ac97.asm' ; 29/11/2016 (AC97 codec configuration)
     1                              <1> ; PCI and AC97 codec functions for wav player
     2                              <1> ; Erdogan Tan (17/02/2017)
     3                              <1>  
     4                              <1> ; ----------------------------------------------------------------------------
     5                              <1> ; PCI.ASM
     6                              <1> ; ----------------------------------------------------------------------------
     7                              <1> 
     8                              <1> ; PCI device register reader/writers.
     9                              <1> ; NASM version: Erdogan Tan (29/11/2016)
    10                              <1> ; 		Last Update: 17/02/2017
    11                              <1> 
    12                              <1> ;===============================================================
    13                              <1> ; 8/16/32bit PCI reader
    14                              <1> ;
    15                              <1> ; Entry: EAX=PCI Bus/Device/fn/register number
    16                              <1> ;           BIT30 set if 32 bit access requested
    17                              <1> ;           BIT29 set if 16 bit access requested
    18                              <1> ;           otherwise defaults to 8bit read
    19                              <1> ;
    20                              <1> ; Exit:  DL,DX,EDX register data depending on requested read size
    21                              <1> ;
    22                              <1> ; Note: this routine is meant to be called via pciRegRead8, pciRegread16,
    23                              <1> ;	or pciRegRead32, listed below.
    24                              <1> ;
    25                              <1> ; Note2: don't attempt to read 32bits of data from a non dword aligned reg
    26                              <1> ;	 number.  Likewise, don't do 16bit reads from non word aligned reg #
    27                              <1> ; 
    28                              <1> pciRegRead:
    29 00000211 6653                <1> 	push	ebx
    30 00000213 51                  <1> 	push	cx
    31 00000214 6689C3              <1>         mov     ebx, eax                        ; save eax, dh
    32 00000217 88F1                <1>         mov     cl, dh
    33 00000219 6625FFFFFFBF        <1>         and     eax, (~PCI32)+PCI16             ; clear out data size request
    34 0000021F 660D00000080        <1>         or      eax, BIT31                      ; make a PCI access request
    35 00000225 24FC                <1>         and     al, ~3 ; NOT 3                  ; force index to be dword
    36                              <1> 
    37 00000227 BAF80C              <1>         mov     dx, PCI_INDEX_PORT
    38 0000022A 66EF                <1>         out     dx, eax                         ; write PCI selector
    39                              <1> 
    40 0000022C BAFC0C              <1>         mov     dx, PCI_DATA_PORT
    41 0000022F 88D8                <1>         mov     al, bl
    42 00000231 2403                <1>         and     al, 3                           ; figure out which port to
    43 00000233 00C2                <1>         add     dl, al                          ; read to
    44                              <1> 
    45 00000235 66ED                <1> 	in      eax, dx                         ; do 32bit read
    46 00000237 66F7C300000080      <1>         test    ebx, PCI32
    47 0000023E 7403                <1>         jz      short _pregr1
    48                              <1> 
    49 00000240 6689C2              <1>         mov     edx, eax                        ; return 32bits of data
    50                              <1> _pregr1:
    51 00000243 89C2                <1> 	mov     dx, ax                          ; return 16bits of data
    52 00000245 66F7C3000000C0      <1>         test    ebx, PCI32+PCI16
    53 0000024C 7502                <1>         jnz     short _pregr2
    54 0000024E 88CE                <1>         mov     dh, cl                          ; restore dh for 8 bit read
    55                              <1> _pregr2:
    56 00000250 6689D8              <1>         mov     eax, ebx                        ; restore eax
    57 00000253 6625FFFFFFBF        <1>         and     eax, (~PCI32)+PCI16             ; clear out data size request
    58 00000259 59                  <1> 	pop	cx
    59 0000025A 665B                <1> 	pop	ebx
    60 0000025C C3                  <1> 	retn
    61                              <1> 
    62                              <1> pciRegRead8:
    63 0000025D 6625FFFFFF3F        <1>         and     eax, (~PCI16)+PCI32             ; set up 8 bit read size
    64 00000263 EBAC                <1>         jmp     short pciRegRead		; call generic PCI access
    65                              <1> 
    66                              <1> pciRegRead16:
    67 00000265 6625FFFFFF3F        <1>         and     eax, (~PCI16)+PCI32		; set up 16 bit read size
    68 0000026B 660D00000040        <1>         or      eax, PCI16			; call generic PCI access
    69 00000271 EB9E                <1>         jmp     short pciRegRead
    70                              <1> 
    71                              <1> pciRegRead32:
    72 00000273 6625FFFFFF3F        <1>         and     eax, (~PCI16)+PCI32		; set up 32 bit read size
    73 00000279 660D00000080        <1>         or      eax, PCI32			; call generic PCI access
    74 0000027F EB90                <1>         jmp     short pciRegRead
    75                              <1> 
    76                              <1> ;===============================================================
    77                              <1> ; 8/16/32bit PCI writer
    78                              <1> ;
    79                              <1> ; Entry: EAX=PCI Bus/Device/fn/register number
    80                              <1> ;           BIT31 set if 32 bit access requested
    81                              <1> ;           BIT30 set if 16 bit access requested
    82                              <1> ;           otherwise defaults to 8bit read
    83                              <1> ;        DL/DX/EDX data to write depending on size
    84                              <1> ;
    85                              <1> ;
    86                              <1> ; note: this routine is meant to be called via pciRegWrite8, pciRegWrite16,
    87                              <1> ; 	or pciRegWrite32 as detailed below.
    88                              <1> ;
    89                              <1> ; Note2: don't attempt to write 32bits of data from a non dword aligned reg
    90                              <1> ;	 number.  Likewise, don't do 16bit writes from non word aligned reg #
    91                              <1> ;
    92                              <1> pciRegWrite:
    93 00000281 6653                <1> 	push	ebx
    94 00000283 51                  <1> 	push	cx
    95 00000284 6689C3              <1>         mov     ebx, eax                        ; save eax, dx
    96 00000287 89D1                <1>         mov     cx, dx
    97 00000289 660D00000080        <1>         or      eax, BIT31                      ; make a PCI access request
    98 0000028F 6625FFFFFFBF        <1>         and     eax, ~PCI16 ; NOT PCI16         ; clear out data size request
    99 00000295 24FC                <1>         and     al, ~3 ; NOT 3                  ; force index to be dword
   100                              <1> 
   101 00000297 BAF80C              <1>         mov     dx, PCI_INDEX_PORT
   102 0000029A 66EF                <1>         out     dx, eax                         ; write PCI selector
   103                              <1> 
   104 0000029C BAFC0C              <1>         mov     dx, PCI_DATA_PORT
   105 0000029F 88D8                <1>         mov     al, bl
   106 000002A1 2403                <1>         and     al, 3                           ; figure out which port to
   107 000002A3 00C2                <1>         add     dl, al                          ; write to
   108                              <1> 
   109 000002A5 6689D0              <1>         mov     eax, edx                        ; put data into eax
   110 000002A8 89C8                <1>         mov     ax, cx
   111                              <1> 
   112 000002AA EE                  <1>         out     dx, al
   113 000002AB 66F7C3000000C0      <1>         test    ebx, PCI16+PCI32                ; only 8bit access? bail
   114 000002B2 740C                <1>         jz      short _pregw1
   115                              <1> 
   116 000002B4 EF                  <1>         out     dx, ax                          ; write 16 bit value
   117 000002B5 66F7C300000040      <1>         test    ebx, PCI16                      ; 16bit requested?  bail
   118 000002BC 7502                <1>         jnz     short _pregw1
   119                              <1> 
   120 000002BE 66EF                <1>         out     dx, eax                         ; write full 32bit
   121                              <1> _pregw1:
   122 000002C0 6689D8              <1>         mov     eax, ebx                        ; restore eax
   123 000002C3 6625FFFFFFBF        <1>         and     eax, (~PCI32)+PCI16             ; clear out data size request
   124 000002C9 89CA                <1>         mov     dx, cx                          ; restore dx
   125 000002CB 59                  <1> 	pop	cx
   126 000002CC 665B                <1> 	pop	ebx
   127 000002CE C3                  <1> 	ret
   128                              <1> 
   129                              <1> pciRegWrite8:
   130 000002CF 6625FFFFFF3F        <1>         and     eax, (~PCI16)+PCI32		; set up 8 bit write size
   131 000002D5 EBAA                <1>         jmp     short pciRegWrite		; call generic PCI access
   132                              <1> 
   133                              <1> pciRegWrite16:
   134 000002D7 6625FFFFFF3F        <1>         and     eax, (~PCI16)+PCI32		; set up 16 bit write size
   135 000002DD 660D00000040        <1>         or      eax, PCI16			; call generic PCI access
   136 000002E3 EB9C                <1>         jmp     short pciRegWrite
   137                              <1> 
   138                              <1> pciRegWrite32:
   139 000002E5 6625FFFFFF3F        <1>         and     eax, (~PCI16)+PCI32		; set up 32 bit write size
   140 000002EB 660D00000080        <1>         or      eax, PCI32			; call generic PCI access
   141 000002F1 EB8E                <1>         jmp     short pciRegWrite
   142                              <1> 
   143                              <1> ; 17/02/2017 (Modifed by Erdogan Tan for various ICH device IDs)
   144                              <1> ;===============================================================
   145                              <1> ; PCIFindDevice: scan through PCI space looking for a device+vendor ID
   146                              <1> ;
   147                              <1> ;  ENTRY: none
   148                              <1> ;; Entry: EAX=Device+Vendor ID
   149                              <1> ;
   150                              <1> ;  Exit: EAX=PCI address if device found
   151                              <1> ;	 EDX=Device+Vendor ID
   152                              <1> ;        CY clear if found, set if not found. EAX invalid if CY set.
   153                              <1> ;
   154                              <1> ; [old stackless] Destroys: ebx, esi, edi, cl
   155                              <1> ;
   156                              <1> pciFindDevice:
   157                              <1> 	;push	cx
   158                              <1> 	;push	eax ; *
   159                              <1> 	;push	esi
   160                              <1> 	;push	edi
   161                              <1> 
   162                              <1>  	;mov     esi, eax                ; save off vend+device ID
   163                              <1> 
   164                              <1> 	; 17/02/2017
   165 000002F3 BE[EE07]            <1> 	mov	si, valid_ids	; address of Valid ICH (AC97) Device IDs
   166 000002F6 B92800              <1> 	mov	cx, valid_id_count
   167                              <1> pfd_0:
   168 000002F9 66BF00FFFF7F        <1>        	mov     edi, (80000000h - 100h) ; start with bus 0, dev 0 func 0
   169                              <1> nextPCIdevice:
   170 000002FF 6681C700010000      <1>         add     edi, 100h
   171 00000306 6681FF00F8FF80      <1>         cmp     edi, 80FFF800h		; scanned all devices?
   172                              <1>         ;stc
   173                              <1>         ;je 	short PCIScanExit       ; not found
   174 0000030D 720D                <1> 	jb	short pfd_1
   175 0000030F 66BF00000080        <1> 	mov     edi, 80000000h
   176 00000315 83C604              <1> 	add	si, 4 ; scan for next device ID
   177 00000318 E202                <1> 	loop	pfd_1	 
   178 0000031A F9                  <1> 	stc	
   179                              <1> 	;jmp 	short PCIScanExit
   180 0000031B C3                  <1> 	retn
   181                              <1> pfd_1:
   182 0000031C 6689F8              <1>         mov     eax, edi                ; read PCI registers
   183 0000031F E851FF              <1>         call    pciRegRead32
   184                              <1>         ;cmp    edx, esi                ; found device?
   185 00000322 663B14              <1>         cmp	edx, dword [si]
   186 00000325 75D8                <1> 	jne     short nextPCIdevice
   187                              <1>         ;clc
   188                              <1> PCIScanExit:
   189                              <1> 	;pushf
   190 00000327 66B800000080        <1> 	mov	eax, BIT31
   191 0000032D 66F7D0              <1> 	not	eax
   192 00000330 6621F8              <1> 	and	eax, edi		; return only bus/dev/fn #
   193                              <1> 	;popf
   194                              <1> 
   195                              <1> 	;pop	edi
   196                              <1> 	;pop	esi
   197                              <1> 	;pop	edx ; *
   198                              <1> 	;pop	cx
   199 00000333 C3                  <1> 	retn
   200                              <1> 
   201                              <1> ; ----------------------------------------------------------------------------
   202                              <1> ; CODEC.ASM
   203                              <1> ; ----------------------------------------------------------------------------
   204                              <1> 
   205                              <1> ; codec configuration code.  Not much here really.
   206                              <1> ; NASM version: Erdogan Tan (29/11/2016)
   207                              <1> 
   208                              <1> ; enable codec, unmute stuff, set output rate to 44.1
   209                              <1> ; entry: ax = desired sample rate
   210                              <1> ;
   211                              <1> 
   212                              <1> codecConfig:
   213                              <1> 	; 17/02/2017 
   214                              <1> 	; 07/11/2016 (Erdogan Tan)
   215                              <1> 	PORT_NABM_GLB_CTRL_STAT equ 60h
   216                              <1> 
   217                              <1> 	;mov    dx, [NAMBAR]               	; mixer base address
   218                              <1> 	;add	dx, CODEC_EXT_AUDIO_REG	       	; 28h  	  
   219                              <1> 	;in	ax, dx
   220                              <1> 	;and	ax, 1
   221                              <1> 	;jnz	short _ssr
   222                              <1> 	;pop	ax
   223                              <1> 	;jmp	short cconf_1
   224                              <1> 
   225                              <1> _ssr:
   226 00000334 8B16[1A09]          <1> 	mov    	dx, [NAMBAR]               	
   227 00000338 83C22A              <1> 	add    	dx, CODEC_EXT_AUDIO_CTRL_REG  	; 2Ah  	  
   228 0000033B ED                  <1> 	in     	ax, dx
   229 0000033C 83C801              <1> 	or	ax, 1
   230 0000033F EF                  <1> 	out	dx, ax 				; Enable variable rate audio
   231                              <1> 
   232 00000340 E86302              <1>         call    delay1_4ms
   233 00000343 E86002              <1>         call    delay1_4ms
   234 00000346 E85D02              <1>         call    delay1_4ms
   235 00000349 E85A02              <1>         call    delay1_4ms
   236                              <1> 
   237 0000034C A1[3209]            <1> 	mov	ax, [sample_rate] ; 17/02/2017 (Erdogan Tan)
   238                              <1> 
   239 0000034F 8B16[1A09]          <1> 	mov    	dx, [NAMBAR]               	
   240 00000353 83C22C              <1> 	add    	dx, CODEC_PCM_FRONT_DACRATE_REG	; 2Ch  	  
   241 00000356 EF                  <1> 	out	dx, ax 				; out sample rate
   242                              <1> 		
   243                              <1> 	;mov    dx, [NAMBAR]               	
   244                              <1> 	;add    dx, CODEC_LR_ADCRATE_REG 	; 32h  	  
   245                              <1> 	;out	dx, ax 
   246                              <1> 
   247 00000357 E84C02              <1>         call    delay1_4ms
   248 0000035A E84902              <1>         call    delay1_4ms
   249 0000035D E84602              <1>         call    delay1_4ms
   250 00000360 E84302              <1>         call    delay1_4ms
   251                              <1> 
   252                              <1> ;cconf_1:
   253 00000363 8B16[1A09]          <1> 	mov     dx, [NAMBAR]			; mixer base address
   254 00000367 83C200              <1>         add     dx, CODEC_RESET_REG  		; reset register
   255 0000036A B82A00              <1>         mov	ax, 42
   256 0000036D EF                  <1> 	out     dx, ax                          ; reset
   257                              <1> 
   258 0000036E 8B16[1C09]          <1> 	mov     dx, [NABMBAR]			; bus master base address
   259 00000372 83C260              <1>         add     dx, PORT_NABM_GLB_CTRL_STAT
   260 00000375 B80200              <1>         mov	ax, 2
   261 00000378 EF                  <1> 	out     dx, ax                         
   262                              <1> 
   263 00000379 B90700              <1> 	mov	cx, 7
   264                              <1> _100ms:
   265 0000037C 51                  <1> 	push	cx
   266 0000037D E82602              <1>         call    delay1_4ms
   267 00000380 E82302              <1>         call    delay1_4ms
   268 00000383 E82002              <1>         call    delay1_4ms
   269 00000386 E81D02              <1>         call    delay1_4ms
   270 00000389 59                  <1> 	pop	cx
   271 0000038A E2F0                <1> 	loop	_100ms	
   272                              <1> 	
   273 0000038C 8B16[1A09]          <1>   	mov     dx, [NAMBAR]
   274 00000390 83C202              <1>   	add     dx, CODEC_MASTER_VOL_REG        ;02h 
   275 00000393 31C0                <1>   	xor     ax, ax ; ; volume attenuation = 0 (max. volume)
   276 00000395 EF                  <1>   	out     dx, ax
   277                              <1>  
   278 00000396 8B16[1A09]          <1>   	mov     dx, [NAMBAR]
   279 0000039A 83C206              <1>   	add     dx, CODEC_MASTER_MONO_VOL_REG   ;06h 
   280                              <1>   	;xor    ax, ax
   281 0000039D EF                  <1>   	out     dx, ax
   282                              <1> 
   283 0000039E 8B16[1A09]          <1>   	mov     dx, [NAMBAR]
   284 000003A2 83C20A              <1>   	add     dx, CODEC_PCBEEP_VOL_REG        ;0Ah 
   285                              <1>   	;xor    ax, ax
   286 000003A5 EF                  <1>   	out     dx, ax
   287                              <1> 
   288 000003A6 8B16[1A09]          <1>   	mov     dx, [NAMBAR]
   289 000003AA 83C218              <1>   	add     dx, CODEC_PCM_OUT_REG		;18h 
   290                              <1>   	;xor    ax, ax
   291 000003AD EF                  <1>   	out     dx, ax
   292                              <1> 
   293 000003AE E8F501              <1>         call    delay1_4ms
   294 000003B1 E8F201              <1>         call    delay1_4ms
   295 000003B4 E8EF01              <1>         call    delay1_4ms
   296 000003B7 E8EC01              <1>         call    delay1_4ms
   297                              <1> 
   298 000003BA C3                  <1>         retn
   391                                  %include 'ich_wav.asm' ; 17/02/2017 (ICH AC97 wav playing functions)
     1                              <1> ; DOS based .WAV player using AC'97 and codec interface.
     2                              <1> ; ---------------------------------------------------------------
     3                              <1> ; NASM version: Erdogan Tan (29/11/2016)
     4                              <1> ; Last Update: 17/02/2017 (by Erdogan Tan)
     5                              <1> 
     6                              <1> ; ICHWAV.ASM
     7                              <1> 
     8                              <1> ; player internal variables and other equates.
     9                              <1> BUFFERSIZE      equ     64 * 1024       ; 64k file buffer size.
    10                              <1> ENDOFFILE       equ     BIT0            ; flag for knowing end of file
    11                              <1> 
    12                              <1> ;===========================================================================
    13                              <1> ; entry: none.  File is already open and [filehandle] filled.
    14                              <1> ; exit:  not until the song is finished or the user aborts.
    15                              <1> ;
    16                              <1> playWav:
    17                              <1> 	; clear buffer 2
    18 000003BB 06                  <1>         push	es
    19 000003BC A1[2209]            <1> 	mov     ax, [WAV_BUFFER2]
    20 000003BF 8EC0                <1> 	mov	es, ax
    21 000003C1 29C0                <1> 	sub	ax, ax
    22 000003C3 89C7                <1> 	mov	di, ax ; 17/02/2017
    23 000003C5 B90080              <1> 	mov	cx, (BUFFERSIZE/2)
    24 000003C8 F3AB                <1> 	rep	stosw
    25 000003CA 07                  <1> 	pop	es	     
    26                              <1> 	
    27                              <1>        ; load 64k into buffer 1
    28 000003CB A1[2009]            <1>         mov     ax, [WAV_BUFFER1]
    29 000003CE E8E800              <1>         call    loadFromFile
    30                              <1> 
    31                              <1>        ; and 64k into buffer 2
    32 000003D1 A1[2209]            <1> 	mov     ax, [WAV_BUFFER2]
    33 000003D4 E8E200              <1>        	call    loadFromFile
    34                              <1> 
    35                              <1> ; register reset the DMA engine.  This may cause a pop noise on the output
    36                              <1> ; lines when the device is reset.  Prolly a better idea to mute output, then
    37                              <1> ; reset.
    38                              <1> ;
    39 000003D7 8B16[1C09]          <1>         mov     dx, [NABMBAR]
    40 000003DB 83C21B              <1>         add     dx, PO_CR_REG		; set pointer to Ctrl reg
    41 000003DE B002                <1>         mov	al, RR			; set reset
    42 000003E0 EE                  <1> 	out     dx, al			; self clearing bit
    43                              <1> 
    44                              <1> ; write last valid index to 31 to start with.
    45                              <1> ; The Last Valid Index register tells the DMA engine when to stop playing.
    46                              <1> ; 
    47                              <1> ; As we progress through the song we change the last valid index to always be
    48                              <1> ; something other than the index we're currently playing.  
    49                              <1> ;
    50                              <1>         ;;mov   al, 1
    51                              <1>         ;mov	al, 31
    52                              <1> 	;call   setLastValidIndex
    53                              <1> 
    54                              <1> ; create Buffer Descriptor List
    55                              <1> ;
    56                              <1> ; A buffer descriptor list is a list of pointers and control bits that the
    57                              <1> ; DMA engine uses to know where to get the .wav data and how to play it.
    58                              <1> ;
    59                              <1> ; I set it up to use only 2 buffers of .wav data, and whenever 1 buffer is
    60                              <1> ; playing, I refresh the other one with good data.
    61                              <1> ;
    62                              <1> ;
    63                              <1> ; For the control bits, you can specify that the DMA engine fire an interrupt
    64                              <1> ; after a buffer has been processed, but I poll the current index register
    65                              <1> ; to know when it's safe to update the other buffer.
    66                              <1> ;
    67                              <1> ; I set the BUP bit, which tells the DMA engine to just play 0's (silence)
    68                              <1> ; if it ever runs out of data to play.  Good for safety.
    69                              <1> ;
    70 000003E1 06                  <1>         push    es
    71 000003E2 A1[1E09]            <1>         mov     ax, [BDL_BUFFER]		; get segment # for BDL
    72 000003E5 8EC0                <1>         mov     es, ax
    73                              <1> 
    74 000003E7 B91000              <1>         mov     cx, 32 / 2                      ; make 32 entries in BDL
    75 000003EA 31FF                <1>         xor     di, di                          
    76                              <1> _0:
    77                              <1> 
    78                              <1> ; set buffer descriptor 0 to start of data file in memory
    79 000003EC 660FB706[2009]      <1>         movzx   eax, word [WAV_BUFFER1]
    80 000003F2 66C1E004            <1>         shl     eax, 4                          ; convert seg:off ->0:offset
    81 000003F6 66AB                <1>         stosd                                   ; store pointer to wavbuffer1
    82                              <1> 
    83                              <1> ;
    84                              <1> ; set length to 32k samples.  1 sample is 16bits or 2bytes.
    85                              <1> ; Set control (bits 31:16) to BUP, bits 15:0=number of samples.
    86                              <1> ; 
    87                              <1> 
    88                              <1> ; 17/02/2017 (Erdogan Tan)
    89                              <1> ; Intel® 82801AA (ICH) & Intel® 82801AB (ICH0) I/O Controller Hub AC ’97
    90                              <1> ; Programmer’s Reference Manual
    91                              <1> 
    92                              <1> ; 2.2.1 Buffer Descriptor List  (on Page 13)
    93                              <1> 	;
    94                              <1> 	;  Generic Form of Buffer Descriptor
    95                              <1> 	;  ---------------------------------
    96                              <1> 	;  63   62    61-48    47-32   31-0
    97                              <1> 	;  ---  ---  --------  ------- -----
    98                              <1> 	;  IOC  BUP -reserved- Buffer  Buffer
    99                              <1> 	;		      Length   Pointer
   100                              <1> 	;		      [15:0]   [31:0]
   101                              <1> 	;
   102                              <1> 	;  IOC:	Interrupt On Completion. 
   103                              <1> 	;	1 = Enabled. 
   104                              <1> 	;	    When this is set, it means that the controller should
   105                              <1> 	;	    issue an interrupt upon completion of this buffer.
   106                              <1> 	;	    It should also set the IOC bit in the status register
   107                              <1> 	;	0 = Disabled	
   108                              <1> 	;
   109                              <1> 	;  BUP: Buffer Underrun Policy.
   110                              <1> 	;       0 = When this buffer is complete,
   111                              <1> 	;	    if the next buffer is not yet ready 
   112                              <1> 	;	    (i.e., the last valid buffer has been processed),
   113                              <1> 	;	    then continue to transmit the last valid sample.
   114                              <1> 	;	1 = When this buffer is complete,
   115                              <1> 	;     	    if this is the last valid buffer, transmit zeros after
   116                              <1> 	;	    this buffer has been processed completely.
   117                              <1> 	;	    This bit typically is set only if this is the last 
   118                              <1> 	;	    buffer in the current stream.
   119                              <1> 	;
   120                              <1> 	; [31:0]: Buffer pointer. This field points to the location of
   121                              <1> 	;	  the data buffer. Since samples can be as wide as one
   122                              <1> 	;	  word, the buffer must be aligned with word boundaries,
   123                              <1> 	;	  to prevent samples from straddling DWord boundaries.
   124                              <1> 	;
   125                              <1> 	; [15:0]: Buffer Length: This is the length of the data buffer,
   126                              <1> 	;	  in number of samples. The controller uses this data
   127                              <1> 	;	  to determine the length of the buffer, in bytes.
   128                              <1> 	;	  "0" indicates no sample to process.
   129                              <1> 
   130                              <1> ; ICH2AC97.INC
   131                              <1> 
   132                              <1> ;	IOC	equ     BIT31   ; Fire an interrupt whenever this
   133                              <1> 				; buffer is complete.
   134                              <1> 
   135                              <1> ;	BUP	equ     BIT30   ; Buffer Underrun Policy.
   136                              <1> 				; if this buffer is the last buffer
   137                              <1> 				; in a playback, fill the remaining
   138                              <1> 				; samples with 0 (silence) or not.
   139                              <1> 				; It's a good idea to set this to 1
   140                              <1> 				; for the last buffer in playback,
   141                              <1> 				; otherwise you're likely to get a lot
   142                              <1> 				; of noise at the end of the sound.
   143                              <1> ;
   144                              <1> ; Bits 15:0 contain the length of the buffer, in number of samples, which
   145                              <1> ; are 16 bits each, coupled in left and right pairs, or 32bits each.
   146                              <1> ; Luckily for us, that's the same format as .wav files.
   147                              <1> ;
   148                              <1> ; A value of FFFF is 65536 samples.  Running at 44.1Khz, that's just about
   149                              <1> ; 1.5 seconds of sample time.  FFFF * 32bits is 1FFFFh bytes or 128k of data.
   150                              <1> ;
   151                              <1> ; A value of 0 in these bits means play no samples.
   152                              <1> ;
   153                              <1> 
   154                              <1> ; ICHWAV.ASM
   155                              <1> 
   156 000003F8 66B800800000        <1> 	mov	eax, BUFFERSIZE / 2 ; size of half buffer (32K)
   157 000003FE 660D000000C0        <1> 	or	eax, IOC + BUP
   158 00000404 66AB                <1> 	stosd
   159                              <1> 
   160                              <1> ; 2nd buffer:
   161                              <1> 
   162 00000406 660FB706[2209]      <1>         movzx   eax, word [WAV_BUFFER2]
   163 0000040C 66C1E004            <1>         shl     eax, 4                          ; convert seg:off ->0:offset
   164 00000410 66AB                <1>         stosd                                   ; store pointer to wavbuffer2
   165                              <1> 
   166                              <1> ; set length to 64k (32k of two 16 bit samples)
   167                              <1> ; Set control (bits 31:16) to BUP, bits 15:0=number of samples
   168                              <1> ; 
   169 00000412 66B800800000        <1> 	mov	eax, BUFFERSIZE / 2
   170 00000418 660D000000C0        <1> 	or	eax, IOC + BUP
   171 0000041E 66AB                <1> 	stosd
   172                              <1> 
   173 00000420 E2CA                <1>         loop    _0
   174 00000422 07                  <1>         pop     es
   175                              <1> 
   176                              <1> ;
   177                              <1> ; tell the DMA engine where to find our list of Buffer Descriptors.
   178                              <1> ; this 32bit value is a flat mode memory offset (ie no segment:offset)
   179                              <1> ;
   180                              <1> ; write NABMBAR+10h with offset of buffer descriptor list
   181                              <1> ;
   182 00000423 660FB706[1E09]      <1>         movzx   eax, word [BDL_BUFFER]
   183 00000429 66C1E004            <1> 	shl     eax, 4                          ; convert seg:off to 0:off
   184 0000042D 8B16[1C09]          <1>         mov     dx, [NABMBAR]
   185 00000431 83C210              <1>         add     dx, PO_BDBAR_REG                ; set pointer to BDL
   186 00000434 66EF                <1>         out     dx, eax                         ; write to AC97 controller
   187                              <1> ;
   188                              <1> ;
   189                              <1> ; All set.  Let's play some music.
   190                              <1> ;
   191                              <1> ;
   192                              <1> 	; 08/12/2016
   193                              <1> 	; 07/10/2016
   194                              <1>         ;mov    al, 1
   195 00000436 B01F                <1>         mov	al, 31
   196 00000438 E85201              <1> 	call    setLastValidIndex
   197                              <1> 
   198 0000043B C606[1909]01        <1> 	mov	byte [tLoop], 1 ; 30/11/2016
   199                              <1> 
   200                              <1> 	; 17/02/2017
   201 00000440 8B16[1C09]          <1>         mov     dx, [NABMBAR]
   202 00000444 83C21B              <1>         add     dx, PO_CR_REG                   ; PCM out Control Register
   203 00000447 B011                <1>         mov	al, IOCE + RPBM	; Enable 'Interrupt On Completion' + run
   204                              <1> 				; (LVBI interrupt will not be enabled)
   205 00000449 EE                  <1>         out     dx, al                          ; Start bus master operation.
   206                              <1> 
   207                              <1> ; while DMA engine is running, examine current index and wait until it hits 1
   208                              <1> ; as soon as it's 1, we need to refresh the data in wavbuffer1 with another
   209                              <1> ; 64k.  Likewise when it's playing buffer 2, refresh buffer 1 and repeat.
   210                              <1>    
   211                              <1> 	; 08/12/2016
   212                              <1> 	; 28/11/2016
   213                              <1> p_loop:
   214 0000044A E84901              <1> 	call    check4keyboardstop      ; keyboard halt?
   215 0000044D 7306                <1>         jnc     short r_loop
   216                              <1> 
   217 0000044F C606[1909]00        <1> 	mov	byte [tLoop], 0
   218 00000454 C3                  <1> 	retn
   219                              <1> r_loop:
   220                              <1> 	; 07/12/2016 - Erdogan Tan
   221 00000455 90                  <1> 	nop
   222 00000456 90                  <1> 	nop
   223 00000457 90                  <1> 	nop
   224                              <1> 	; 17/02/2017
   225 00000458 A0[2409]            <1> 	mov	al, [tBuff]
   226 0000045B FEC8                <1> 	dec	al ; 1-32 -> 0-31 or 0 -> 0FFh
   227 0000045D 78EB                <1> 	js	short  p_loop
   228 0000045F C606[2409]00        <1> 	mov	byte [tBuff], 0 ; reset
   229 00000464 2401                <1> 	and	al, 1
   230 00000466 750A                <1> 	jnz	short q_loop
   231 00000468 A1[2209]            <1>         mov     ax, [WAV_BUFFER2] ; [tBuff]=2 (from tuneLoop)
   232 0000046B E84B00              <1>         call    loadFromFile
   233 0000046E 7239                <1> 	jc	short _exit_
   234 00000470 EBE3                <1> 	jmp	short r_loop
   235                              <1> q_loop:
   236 00000472 A1[2009]            <1>      	mov     ax, [WAV_BUFFER1] ; [tBuff]=1 (from tuneLoop)
   237 00000475 E84100              <1>         call    loadFromFile
   238 00000478 722F                <1> 	jc	short _exit_
   239 0000047A EBD9                <1> 	jmp	short r_loop
   240                              <1> 			
   241                              <1> tuneLoop:
   242                              <1> 	; 08/12/2016
   243                              <1> 	; 28/11/2016 - Erdogan Tan
   244                              <1> 	
   245 0000047C 803E[1909]01        <1> 	cmp	byte [tLoop], 1
   246 00000481 722B                <1> 	jb	short _exit
   247                              <1> _tlp_1:	
   248                              <1> 	; 17/02/2017
   249 00000483 E8FE00              <1> 	call	getCurrentIndex
   250 00000486 FEC0                <1> 	inc	al ; 0-31 -> 1-32
   251 00000488 A2[2409]            <1> 	mov	[tBuff], al
   252                              <1> 
   253                              <1> 	; 17/02/2017 - Buffer switch test (temporary)
   254 0000048B 06                  <1> 	push	es 
   255 0000048C BE00B8              <1> 	mov	si, 0B800h ; video display page segment
   256 0000048F 8EC6                <1> 	mov	es, si
   257 00000491 29F6                <1> 	sub	si, si ; 0
   258 00000493 B44E                <1> 	mov	ah, 4Eh
   259 00000495 2401                <1> 	and	al, 1
   260 00000497 0431                <1> 	add	al, '1'
   261 00000499 268904              <1> 	mov	[es:si], ax ; show current play buffer (1, 2)
   262 0000049C 07                  <1> 	pop	es
   263                              <1> 
   264                              <1> 	; 17/02/2017
   265                              <1> 
   266                              <1> 	;test	byte [irq_status], LVBCI ; last buff completion intr.
   267                              <1> 	;jz	short _tlp2 ; BCIS ; Buffer completion interrupt
   268                              <1> 
   269                              <1> 	; Last Valid Buffer Completion Interrupt (LVBCI).
   270                              <1> 	;   1 = Last valid buffer has been processed. 
   271                              <1> 	;	It remains active until cleared by software. 
   272                              <1> 	;	This bit indicates the occurrence of the event 
   273                              <1> 	;	signified by the last valid buffer being processed.
   274                              <1> 	;	Thus, this is an event status bit that can be cleared
   275                              <1> 	;	by software once this event has been recognized.
   276                              <1> 	;	This event causes an interrupt if the enable bit
   277                              <1> 	;	in the Control Register is set. The interrupt is
   278                              <1> 	;	cleared when the software clears this bit.
   279                              <1> 	;	In the case of Transmits (PCM out, Modem out) this bit
   280                              <1> 	;	is set, after the last valid buffer has been
   281                              <1> 	;	fetched (not after transmitting it).
   282                              <1> 	;	While in the case of Receives, this bit is set after
   283                              <1> 	;	the data for the last buffer has been written to memory.
   284                              <1> 	;   0 = Cleared by writing a "1" to this bit position.
   285                              <1> 
   286                              <1> 	; Note: We are not using LVBCI 
   287                              <1> 	;     Last Buffer Completion Interrupt !!!
   288                              <1> 
   289                              <1> 	; 17/02/2017
   290                              <1>         ;mov     dx, [NABMBAR]
   291                              <1>         ;add     dx, PO_SR_REG	; PCM out Status register
   292                              <1>         ;mov     al, [irq_status]
   293                              <1>         ;out     dx, al		; Clear (LVBCI) interrupt status
   294                              <1> 	;retn
   295                              <1> 
   296                              <1> ;_tlp2:
   297                              <1> 	; Buffer Completion Interrupt Status (BCIS).
   298                              <1> 	;   1 =	Set by the hardware after the last sample 
   299                              <1> 	; 	of a buffer has been processed, AND if the Interrupt
   300                              <1> 	; 	on Completion (IOC) bit is set in the command byte of 
   301                              <1> 	; 	the buffer descriptor. It remains active
   302                              <1> 	; 	until cleared by software.
   303                              <1> 	;   0 =	Cleared by writing a "1" to this bit position.
   304                              <1> 
   305                              <1> 	; 17/02/2017
   306 0000049D 8B16[1C09]          <1>         mov     dx, [NABMBAR]
   307 000004A1 83C216              <1>         add     dx, PO_SR_REG	; PCM out Status register
   308 000004A4 A0[1709]            <1>         mov     al, [irq_status]
   309 000004A7 EE                  <1>         out     dx, al		; Clear (BCI) interrupt status
   310 000004A8 C3                  <1> 	retn
   311                              <1> _exit_:
   312 000004A9 C606[1909]00        <1> 	mov	byte [tLoop], 0
   313                              <1> _exit:
   314                              <1>         ; finished with song, stop everything
   315 000004AE 8B16[1C09]          <1> 	mov     dx, [NABMBAR]		
   316 000004B2 83C21B              <1>         add     dx, PO_CR_REG           ; PCM out Control Register
   317 000004B5 B000                <1>         mov     al, 0
   318 000004B7 EE                  <1>         out     dx, al                  ; stop player
   319                              <1> _return:
   320 000004B8 C3                  <1> 	retn
   321                              <1> 
   322                              <1> ; load data from file in 32k chunks.  Would be nice to load 1 64k chunk,
   323                              <1> ; but in DOS you can only load FFFF bytes at a time.
   324                              <1> ;
   325                              <1> ; entry: ax = segment to load data to
   326                              <1> ; exit: CY set if end of file reached.
   327                              <1> ; note: last file buffer is padded with 0's to avoid pops at the end of song.
   328                              <1> ; assumes file is already open.  uses [filehandle]
   329                              <1> ;
   330                              <1> loadFromFile:
   331                              <1> 	; 17/02/2017
   332 000004B9 50                  <1>         push    ax
   333 000004BA 51                  <1>         push    cx
   334 000004BB 52                  <1>         push    dx
   335 000004BC 53                  <1> 	push	bx
   336                              <1> 	;push	es
   337                              <1> 	;push	ds
   338                              <1> 	
   339 000004BD F606[1609]01        <1>         test    byte [flags], ENDOFFILE		; have we already read the
   340 000004C2 F9                  <1>         stc					; last of the file?
   341 000004C3 0F85A100            <1>         jnz     endLFF
   342                              <1>     
   343 000004C7 A3[3909]            <1> 	mov	[fbs_seg], ax ; save buffer segment
   344 000004CA 31D2                <1> 	xor	dx, dx
   345                              <1> lff_0:
   346 000004CC 8916[3B09]          <1> 	mov	[fbs_off], dx ; buffer offset
   347                              <1> 
   348 000004D0 BB0080              <1> 	mov     bx, (BUFFERSIZE / 2)              ; 32k chunk
   349 000004D3 8A0E[3809]          <1> 	mov	cl, [fbs_shift]   
   350 000004D7 20C9                <1> 	and	cl, cl
   351 000004D9 7407                <1> 	jz	short lff_1 ; stereo, 16 bit	
   352                              <1> 
   353                              <1> 	; fbs_shift =
   354                              <1> 	;	2 for mono and 8 bit sample (multiplier = 4)
   355                              <1> 	;	1 for mono or 8 bit sample (multiplier = 2)
   356 000004DB D3EB                <1> 	shr	bx, cl ; 32K / multiplier
   357                              <1> 
   358 000004DD 8CC8                <1> 	mov	ax, cs
   359 000004DF BA[3D09]            <1> 	mov	dx, temp_buffer ; temporary buffer for wav data
   360                              <1> lff_1:
   361                              <1> 	; 17/02/2017 (stereo/mono, 8bit/16bit corrections)
   362                              <1> 	; load file into memory
   363 000004E2 89D9                <1>         mov	cx, bx                         
   364 000004E4 8B1E[1409]          <1> 	mov	bx, [filehandle]
   365 000004E8 8ED8                <1> 	mov     ds, ax
   366 000004EA B43F                <1>        	mov	ah, 3fh
   367 000004EC CD21                <1> 	int	21h
   368                              <1> 
   369 000004EE 8CCB                <1> 	mov	bx, cs
   370 000004F0 8EDB                <1> 	mov	ds, bx
   371                              <1> 
   372 000004F2 7267                <1> 	jc	short lff_9 ; error !
   373                              <1> 
   374 000004F4 21C0                <1> 	and	ax, ax
   375 000004F6 7465                <1> 	jz	short lff_10
   376                              <1> 	
   377 000004F8 8A1E[3809]          <1> 	mov	bl, [fbs_shift] ; shift count  
   378 000004FC 08DB                <1> 	or	bl, bl
   379 000004FE 7441                <1> 	jz	short lff_7 ; 16 bit stereo samples
   380                              <1> 
   381 00000500 06                  <1> 	push	es
   382 00000501 57                  <1> 	push	di
   383 00000502 56                  <1> 	push	si
   384 00000503 8B3E[3B09]          <1> 	mov	di, [fbs_off]
   385 00000507 8B36[3909]          <1> 	mov	si, [fbs_seg] ; buffer segment
   386 0000050B 8EC6                <1> 	mov	es, si
   387 0000050D BE[3D09]            <1> 	mov	si, temp_buffer ; temporary buffer address
   388 00000510 8A0E[3609]          <1> 	mov	cl, [bps] ; bits per sample (8 or 16)
   389 00000514 80F908              <1> 	cmp	cl, 8
   390 00000517 7519                <1> 	jne	short lff_4 ; 16 bit samples
   391                              <1> 	; 8 bit samples
   392 00000519 89C1                <1> 	mov	cx, ax ; byte count
   393 0000051B FECB                <1> 	dec	bl  ; shift count, 1 = stereo, 2 = mono
   394 0000051D 740A                <1> 	jz	short lff_3 ; 8 bit, stereo
   395                              <1> lff_2:
   396                              <1> 	; mono & 8 bit
   397 0000051F AC                  <1> 	lodsb
   398 00000520 C1E008              <1> 	shl	ax, 8 ; convert 8 bit sample to 16 bit sample
   399 00000523 AB                  <1> 	stosw	; left channel
   400 00000524 AB                  <1> 	stosw	; right channel
   401 00000525 E2F8                <1> 	loop	lff_2
   402 00000527 EB10                <1> 	jmp	short lff_6	
   403                              <1> lff_3:
   404                              <1> 	; stereo & 8 bit
   405 00000529 AC                  <1> 	lodsb
   406 0000052A C1E008              <1> 	shl	ax, 8 ; convert 8 bit sample to 16 bit sample
   407 0000052D AB                  <1> 	stosw
   408 0000052E E2F9                <1> 	loop	lff_3			
   409 00000530 EB07                <1> 	jmp	short lff_6
   410                              <1> lff_4:
   411                              <1> 	; 16 bit mono samples
   412 00000532 89C1                <1> 	mov	cx, ax ; word count
   413                              <1> lff_5:	
   414 00000534 AD                  <1> 	lodsw
   415 00000535 AB                  <1> 	stosw	; left channel
   416 00000536 AB                  <1> 	stosw	; right channel
   417 00000537 E2FB                <1> 	loop	lff_5
   418                              <1> lff_6:
   419 00000539 89F8                <1> 	mov	ax, di ; save next buffer offset/position
   420 0000053B 5E                  <1> 	pop	si
   421 0000053C 5F                  <1> 	pop	di
   422 0000053D 07                  <1> 	pop	es
   423 0000053E B90080              <1> 	mov	cx, (BUFFERSIZE / 2)
   424                              <1> lff_7:        
   425 00000541 21C0                <1> 	and	ax, ax
   426 00000543 7423                <1> 	jz	short endLFF ; ; end of 2nd half
   427                              <1> 
   428 00000545 39C8                <1> 	cmp	ax, cx
   429 00000547 740A                <1> 	je	short lff_8
   430 00000549 7215                <1> 	jb	short lff_11
   431 0000054B 31C9                <1> 	xor	cx, cx
   432 0000054D 29C1                <1> 	sub	cx, ax
   433 0000054F F7D9                <1> 	neg	cx
   434 00000551 EB0D                <1> 	jmp	short lff_11
   435                              <1> lff_8:
   436 00000553 89C2                <1> 	mov	dx, ax ; buffer offset
   437 00000555 A1[3909]            <1> 	mov	ax, [fbs_seg] ; buffer segment
   438 00000558 E971FF              <1> 	jmp	lff_0
   439                              <1> lff_9:  
   440 0000055B 31C0                <1> 	xor	ax, ax
   441                              <1> lff_10:
   442 0000055D B90080              <1> 	mov	cx, (BUFFERSIZE / 2)  
   443                              <1> lff_11:
   444 00000560 E80A00              <1> 	call    padfill				; blank pad the remainder
   445                              <1>         ;clc					; don't exit with CY yet.
   446 00000563 800E[1609]01        <1>         or	byte [flags], ENDOFFILE		; end of file flag
   447                              <1> endLFF:
   448                              <1>         ;pop	ds
   449                              <1> 	;pop	es
   450 00000568 5B                  <1> 	pop	bx
   451 00000569 5A                  <1> 	pop     dx
   452 0000056A 59                  <1>         pop     cx
   453 0000056B 58                  <1>         pop     ax
   454 0000056C C3                  <1>         retn
   455                              <1> 
   456                              <1> ; entry ds:ax points to last byte in file
   457                              <1> ; cx=target size
   458                              <1> ; note: must do byte size fill
   459                              <1> ; destroys bx, cx
   460                              <1> ;
   461                              <1> padfill:
   462                              <1> 	; 17/02/2017
   463 0000056D 06                  <1> 	push	es
   464 0000056E 57                  <1>         push    di
   465 0000056F 8B3E[3909]          <1> 	mov	di, [fbs_seg]
   466 00000573 8EC7                <1> 	mov	es, di
   467 00000575 29C1                <1>         sub     cx, ax
   468 00000577 89C7                <1> 	mov	di, ax       	
   469 00000579 033E[3B09]          <1> 	add	di, [fbs_off]
   470 0000057D 30C0                <1>         xor     al, al
   471 0000057F F3AA                <1> 	rep	stosb
   472                              <1>         ;mov	[fbs_off], di
   473 00000581 5F                  <1> 	pop     di
   474 00000582 07                  <1>         pop	es
   475 00000583 C3                  <1> 	retn
   476                              <1> 
   477                              <1> ; returns AL = current index value
   478                              <1> getCurrentIndex:
   479                              <1> 	;push	dx
   480 00000584 8B16[1C09]          <1> 	mov	dx, [NABMBAR]      		
   481 00000588 83C214              <1> 	add	dx, PO_CIV_REG
   482 0000058B EC                  <1> 	in	al, dx
   483                              <1> 	;pop	dx
   484 0000058C C3                  <1> 	retn
   485                              <1> 	
   486                              <1> ;input AL = index # to stop on
   487                              <1> setLastValidIndex:
   488                              <1> 	;push	dx
   489 0000058D 8B16[1C09]          <1> 	mov	dx, [NABMBAR]
   490 00000591 83C215              <1> 	add	dx, PO_LVI_REG
   491 00000594 EE                  <1>         out     dx, al
   492                              <1> 	;pop	dx
   493 00000595 C3                  <1> 	retn
   494                              <1> 
   495                              <1> ; checks if either shift key has been pressed.  Exits with CY if so.
   496                              <1> ; 
   497                              <1> check4keyboardstop:
   498 00000596 06                  <1>         push    es
   499 00000597 6A00                <1>         push    0
   500 00000599 07                  <1>         pop     es		       ; examine BDA for keyboard flags
   501 0000059A 26F606170403        <1>         test    byte [es:417h], (BIT0 | BIT1)
   502 000005A0 07                  <1>         pop     es
   503 000005A1 F9                  <1>         stc
   504 000005A2 7501                <1>         jnz     short _cksr
   505 000005A4 F8                  <1>         clc
   506                              <1> _cksr:
   507 000005A5 C3                  <1>         retn
   392                                  
   393                                  ; UTILS.ASM
   394                                  ;----------------------------------------------------------------------------
   395                                  ;       delay1_4ms - Delay for 1/4 millisecond.
   396                                  ;		    1mS = 1000us
   397                                  ;       Entry:
   398                                  ;         None
   399                                  ;       Exit:
   400                                  ;	  None
   401                                  ;
   402                                  ;       Modified:
   403                                  ;         None
   404                                  ;
   405                                  PORTB			EQU	061h
   406                                    REFRESH_STATUS	EQU	010h		; Refresh signal status
   407                                  
   408                                  delay1_4ms:
   409 000005A6 50                              push    ax 
   410 000005A7 51                              push    cx
   411 000005A8 B91000                          mov     cx, 16			; close enough.
   412 000005AB E461                    	in	al,PORTB
   413 000005AD 2410                    	and	al,REFRESH_STATUS
   414 000005AF 88C4                    	mov	ah,al			; Start toggle state
   415 000005B1 09C9                    	or	cx, cx
   416 000005B3 7401                    	jz	short _d4ms1
   417 000005B5 41                      	inc	cx			; Throwaway first toggle
   418                                  _d4ms1:	
   419 000005B6 E461                    	in	al,PORTB		; Read system control port
   420 000005B8 2410                    	and	al,REFRESH_STATUS	; Refresh toggles 15.085 microseconds
   421 000005BA 38C4                    	cmp	ah,al
   422 000005BC 74F8                    	je	short _d4ms1		; Wait for state change
   423                                  
   424 000005BE 88C4                    	mov	ah,al			; Update with new state
   425 000005C0 49                      	dec	cx
   426 000005C1 75F3                    	jnz	short _d4ms1
   427                                  
   428 000005C3 59                              pop     cx
   429 000005C4 58                              pop     ax
   430 000005C5 C3                              retn
   431                                  
   432                                  	; 13/11/2016 - Erdogan Tan
   433                                  write_ac97_dev_info:
   434                                  	; BUS/DEV/FN
   435                                  	;	00000000BBBBBBBBDDDDDFFF00000000
   436                                  	; DEV/VENDOR
   437                                  	;	DDDDDDDDDDDDDDDDVVVVVVVVVVVVVVVV
   438                                  
   439 000005C6 30FF                    	xor	bh, bh
   440 000005C8 668B36[2A09]            	mov	esi, [dev_vendor]
   441 000005CD 89F0                    	mov	ax, si
   442 000005CF 88C3                    	mov	bl, al
   443 000005D1 88DA                    	mov	dl, bl
   444 000005D3 80E30F                  	and	bl, 0Fh
   445 000005D6 8A87[1608]              	mov	al, [bx+hex_chars]
   446 000005DA A2[5908]                	mov	[msgVendorId+3], al
   447 000005DD 88D3                    	mov	bl, dl
   448 000005DF C0EB04                  	shr	bl, 4
   449 000005E2 8A87[1608]              	mov	al, [bx+hex_chars]
   450 000005E6 A2[5808]                	mov	[msgVendorId+2], al
   451 000005E9 88E3                    	mov	bl, ah
   452 000005EB 88DA                    	mov	dl, bl
   453 000005ED 80E30F                  	and	bl, 0Fh
   454 000005F0 8A87[1608]              	mov	al, [bx+hex_chars]
   455 000005F4 A2[5708]                	mov	[msgVendorId+1], al
   456 000005F7 88D3                    	mov	bl, dl
   457 000005F9 C0EB04                  	shr	bl, 4
   458 000005FC 8A87[1608]              	mov	al, [bx+hex_chars]
   459 00000600 A2[5608]                	mov	[msgVendorId], al
   460 00000603 66C1EE10                	shr	esi, 16
   461 00000607 89F0                    	mov	ax, si
   462 00000609 88C3                    	mov	bl, al
   463 0000060B 88DA                    	mov	dl, bl
   464 0000060D 80E30F                  	and	bl, 0Fh
   465 00000610 8A87[1608]              	mov	al, [bx+hex_chars]
   466 00000614 A2[6A08]                	mov	[msgDevId+3], al
   467 00000617 88D3                    	mov	bl, dl
   468 00000619 C0EB04                  	shr	bl, 4
   469 0000061C 8A87[1608]              	mov	al, [bx+hex_chars]
   470 00000620 A2[6908]                	mov	[msgDevId+2], al
   471 00000623 88E3                    	mov	bl, ah
   472 00000625 88DA                    	mov	dl, bl
   473 00000627 80E30F                  	and	bl, 0Fh
   474 0000062A 8A87[1608]              	mov	al, [bx+hex_chars]
   475 0000062E A2[6808]                	mov	[msgDevId+1], al
   476 00000631 88D3                    	mov	bl, dl
   477 00000633 C0EB04                  	shr	bl, 4
   478 00000636 8A87[1608]              	mov	al, [bx+hex_chars]
   479 0000063A A2[6708]                	mov	[msgDevId], al
   480                                  
   481 0000063D 668B36[2609]            	mov	esi, [bus_dev_fn]
   482 00000642 66C1EE08                	shr	esi, 8
   483 00000646 89F0                    	mov	ax, si
   484 00000648 88C3                    	mov	bl, al
   485 0000064A 88DA                    	mov	dl, bl
   486 0000064C 80E307                  	and	bl, 7 ; bit 0,1,2
   487 0000064F 8A87[1608]              	mov	al, [bx+hex_chars]
   488 00000653 A2[8E08]                	mov	[msgFncNo+1], al
   489 00000656 88D3                    	mov	bl, dl
   490 00000658 C0EB03                  	shr	bl, 3
   491 0000065B 88DA                    	mov	dl, bl
   492 0000065D 80E30F                  	and	bl, 0Fh
   493 00000660 8A87[1608]              	mov	al, [bx+hex_chars]
   494 00000664 A2[8008]                	mov	[msgDevNo+1], al
   495 00000667 88D3                    	mov	bl, dl
   496 00000669 C0EB04                  	shr	bl, 4
   497 0000066C 8A87[1608]              	mov	al, [bx+hex_chars]
   498 00000670 A2[7F08]                	mov	[msgDevNo], al
   499 00000673 88E3                    	mov	bl, ah
   500 00000675 88DA                    	mov	dl, bl
   501 00000677 80E30F                  	and	bl, 0Fh
   502 0000067A 8A87[1608]              	mov	al, [bx+hex_chars]
   503 0000067E A2[7408]                	mov	[msgBusNo+1], al
   504 00000681 88D3                    	mov	bl, dl
   505 00000683 C0EB04                  	shr	bl, 4
   506 00000686 8A87[1608]              	mov	al, [bx+hex_chars]
   507 0000068A A2[7308]                	mov	[msgBusNo], al
   508                                  
   509 0000068D A1[3009]                	mov	ax, [ac97_io_base]
   510 00000690 88C3                    	mov	bl, al
   511 00000692 88DA                    	mov	dl, bl
   512 00000694 80E30F                  	and	bl, 0Fh
   513 00000697 8A87[1608]              	mov	al, [bx+hex_chars]
   514 0000069B A2[A708]                	mov	[msgIOBaseAddr+3], al
   515 0000069E 88D3                    	mov	bl, dl
   516 000006A0 C0EB04                  	shr	bl, 4
   517 000006A3 8A87[1608]              	mov	al, [bx+hex_chars]
   518 000006A7 A2[A608]                	mov	[msgIOBaseAddr+2], al
   519 000006AA 88E3                    	mov	bl, ah
   520 000006AC 88DA                    	mov	dl, bl
   521 000006AE 80E30F                  	and	bl, 0Fh
   522 000006B1 8A87[1608]              	mov	al, [bx+hex_chars]
   523 000006B5 A2[A508]                	mov	[msgIOBaseAddr+1], al
   524 000006B8 88D3                    	mov	bl, dl
   525 000006BA C0EB04                  	shr	bl, 4
   526 000006BD 8A87[1608]              	mov	al, [bx+hex_chars]
   527 000006C1 A2[A408]                	mov	[msgIOBaseAddr], al
   528                                  
   529                                  	; 24/11/2016
   530 000006C4 30E4                    	xor	ah, ah
   531 000006C6 A0[2509]                	mov	al, [ac97_int_ln_reg]
   532 000006C9 B10A                    	mov	cl, 10
   533 000006CB F6F1                    	div	cl
   534 000006CD 0106[AF08]              	add	[msgIRQ], ax
   535 000006D1 20C0                    	and	al, al
   536 000006D3 7508                    	jnz	short _pmi
   537 000006D5 A0[B008]                	mov	al, [msgIRQ+1]
   538 000006D8 B420                    	mov	ah, ' '
   539 000006DA A3[AF08]                	mov	[msgIRQ], ax
   540                                  _pmi:
   541 000006DD BA[2708]                        mov	dx, msgAC97Info
   542 000006E0 B409                            mov     ah, 9
   543 000006E2 CD21                            int     21h
   544 000006E4 C3                              retn
   545                                  
   546                                  write_sample_rate:
   547                                  	; ax = sample rate (hertz)
   548                                  
   549 000006E5 31D2                    	xor	dx, dx
   550 000006E7 B90A00                  	mov	cx, 10
   551 000006EA F7F1                    	div	cx
   552 000006EC 0016[C508]              	add	[msgHertz+4], dl
   553 000006F0 29D2                    	sub	dx, dx
   554 000006F2 F7F1                    	div	cx
   555 000006F4 0016[C408]              	add	[msgHertz+3], dl
   556 000006F8 29D2                    	sub	dx, dx
   557 000006FA F7F1                    	div	cx
   558 000006FC 0016[C308]              	add	[msgHertz+2], dl
   559 00000700 29D2                    	sub	dx, dx
   560 00000702 F7F1                    	div	cx
   561 00000704 0016[C208]              	add	[msgHertz+1], dl
   562 00000708 0006[C108]              	add	[msgHertz], al
   563                                  	
   564 0000070C BA[B408]                        mov     dx, msgSampleRate
   565 0000070F B409                            mov     ah, 9
   566 00000711 CD21                            int     21h
   567                                  
   568                                  	; 19/11/2016
   569 00000713 BA[DA08]                	mov	dx, msg16Bits
   570 00000716 803E[3609]10            	cmp	byte [bps], 16
   571 0000071B 7403                    	je	short wsr_1
   572 0000071D BA[CB08]                	mov	dx, msg8Bits
   573                                  wsr_1:
   574 00000720 B409                            mov     ah, 9
   575 00000722 CD21                            int     21h
   576                                  
   577 00000724 BA[D308]                	mov	dx, msgMono
   578 00000727 803E[3409]01            	cmp	byte [stmo], 1
   579 0000072C 7403                    	je	short wsr_2
   580 0000072E BA[E308]                	mov	dx, msgStereo		
   581                                  wsr_2:
   582 00000731 B409                            mov     ah, 9
   583 00000733 CD21                            int     21h
   584                                  
   585 00000735 C3                              retn
   586                                  
   587                                  ;detect_codec:
   588                                  ;	; 13/11/2016 - Erdogan Tan (Ref: KolibriOS, codec.inc)
   589                                  ;	mov	eax, 7Ch
   590                                  ;	call	codec_read
   591                                  ;       shl     eax, 16
   592                                  ;       mov     [codec_id], eax
   593                                  ;
   594                                  ;	mov	eax, 7Eh
   595                                  ;       call	codec_read
   596                                  ;       or      eax, [codec_id]
   597                                  ;       mov     [codec_chip_id], eax
   598                                  ;       and     eax, 0FFFFFF00h
   599                                  ;
   600                                  ;       mov     edi, codecs
   601                                  ;_dcb:
   602                                  ;       mov     ebx, [di]
   603                                  ;       test    ebx, ebx
   604                                  ;       jz      short _dco_unknown
   605                                  ;
   606                                  ;       cmp     eax, ebx
   607                                  ;       jne     short _dco_next
   608                                  ;       mov     ax, [di+4]
   609                                  ;       mov     [codec_vendor_ids], ax
   610                                  ;       movzx   esi, ax
   611                                  ;       call	print_msg
   612                                  ;       
   613                                  ;	mov	ax, [di+6]
   614                                  ;	call	detect_chip
   615                                  ;       retn
   616                                  ;
   617                                  ;_dco_next:
   618                                  ;       add     di, 8
   619                                  ;       jmp     short _dcb
   620                                  ;
   621                                  ;_dco_unknown:
   622                                  ;       mov    word [codec_vendor_ids], ac_unknown
   623                                  ;       mov    word [codec_chip_ids], chip_unknown
   624                                  ;       mov     esi, chip_unknown
   625                                  ;	call	print_msg
   626                                  ;       mov     eax, [codec_chip_id]
   627                                  ;       call    dword2str
   628                                  ;       call	print_msg
   629                                  ;       retn
   630                                  
   631                                  ;detect_chip:
   632                                  ;	; 13/11/2016 - Erdogan Tan (Ref: KolibriOS, codec.inc)
   633                                  ;	mov	di, ax ; chip_tab
   634                                  ;       mov     eax, [codec_chip_id]
   635                                  ;       and     ax, 0FFh
   636                                  ;_dch1:
   637                                  ;       mov     bx, [di]
   638                                  ;       cmp     bx, 0FFh
   639                                  ;       je      short _dch_unknown
   640                                  ;
   641                                  ;       cmp     ax, bx
   642                                  ;       jne     short _dch_next
   643                                  ;       mov     ax, [di+2]
   644                                  ;       mov     [codec_chip_ids], ax
   645                                  ;       mov     si, ax
   646                                  ;       call	print_msg
   647                                  ;       retn
   648                                  
   649                                  ;_dch_next:
   650                                  ;       add     di, 4
   651                                  ;       jmp     short _dch1
   652                                  ;
   653                                  ;_dch_unknown:
   654                                  ;       mov    word [codec_chip_ids], chip_unknown
   655                                  ;       mov     si, chip_unknown
   656                                  ;       call	print_msg
   657                                  ;       mov     eax, [codec_chip_id]
   658                                  ;       call    dword2str
   659                                  ;       call	print_msg
   660                                  ;       retn
   661                                  
   662                                  ac97_int_handler:
   663                                  	; 17/02/2016
   664 00000736 50                      	push	ax
   665 00000737 52                      	push	dx
   666 00000738 51                      	push	cx
   667 00000739 53                      	push	bx
   668 0000073A 56                      	push	si
   669 0000073B 57                      	push	di
   670                                  
   671 0000073C 803E[1809]01            	cmp	byte [inside], 1
   672 00000741 731C                    	jnb	short _busy
   673                                  
   674 00000743 C606[1809]01            	mov	byte [inside], 1
   675                                  
   676 00000748 8B16[1C09]                      mov     dx, [NABMBAR]
   677 0000074C 83C216                          add     dx, PO_SR_REG	; set pointer to Status reg
   678 0000074F EC                      	in	al, dx
   679 00000750 A2[1709]                	mov	[irq_status], al
   680 00000753 A808                    	test	al, BCIS ; Buffer Completion Interrupt Status (Bit 3)
   681 00000755 741C                    	jz	short _ih_3
   682                                  
   683                                  	; 28/11/2016 - Erdogan Tan
   684 00000757 E822FD                  	call	tuneLoop
   685                                  _ih0:
   686 0000075A C606[1809]00            	mov	byte [inside], 0
   687                                  _busy:
   688 0000075F B020                    	mov	al, 20h
   689 00000761 F606[2509]08            	test	byte [ac97_int_ln_reg], 8
   690 00000766 7402                    	jz	short _ih_1
   691 00000768 E6A0                    	out 	0A0h, al ; 20h ; EOI
   692                                  _ih_1:
   693 0000076A E620                    	out	20h, al  ; 20h ; EOI
   694                                  _ih_2:
   695 0000076C 5F                      	pop	di
   696 0000076D 5E                      	pop	si
   697 0000076E 5B                      	pop	bx
   698 0000076F 59                      	pop	cx
   699 00000770 5A                      	pop	dx
   700 00000771 58                      	pop	ax
   701 00000772 CF                      	iret
   702                                  _ih_3:
   703                                  	; 17/02/2017
   704 00000773 EE                      	out	dx, al ; clear interrupt event (by writing 1 to same bits)
   705 00000774 EBE4                    	jmp	short _ih0
   706                                  
   707                                  print_msg:
   708                                  	; 13/11/2016 - Erdogan Tan 
   709                                  	; esi = ASCIIZ text address
   710                                  	;
   711 00000776 BB0700                  	mov	bx, 7h
   712 00000779 B40E                    	mov	ah, 0Eh 
   713                                  pm_next_char:
   714 0000077B AC                      	lodsb
   715 0000077C 20C0                    	and	al, al
   716 0000077E 7404                    	jz	short pm_retn
   717 00000780 CD10                    	int	10h
   718 00000782 EBF7                    	jmp	short pm_next_char
   719                                  pm_retn:
   720 00000784 C3                      	retn
   721                                  
   722                                  dword2str:
   723                                  	; 13/11/2016 - Erdogan Tan 
   724                                  	; eax = dword value
   725                                  	;
   726 00000785 E84400                  	call	dwordtohex
   727 00000788 668916[EC08]            	mov	[dword_str], edx
   728 0000078D 66A3[F008]              	mov	[dword_str+4], eax
   729 00000791 BE[EC08]                	mov	si, dword_str
   730 00000794 C3                      	retn
   731                                  
   732                                  	; trdos386.s (unix386.s) - 10/05/2015
   733                                  	; Convert binary number to hexadecimal string
   734                                  
   735                                  bytetohex:
   736                                  	; INPUT ->
   737                                  	; 	AL = byte (binary number)
   738                                  	; OUTPUT ->
   739                                  	;	AX = hexadecimal string
   740                                  	;
   741 00000795 53                      	push	bx
   742 00000796 30FF                    	xor	bh, bh
   743 00000798 88C3                    	mov	bl, al
   744 0000079A C0EB04                  	shr	bl, 4
   745 0000079D 8A9F[1608]              	mov	bl, [bx+hex_chars] 	 	
   746 000007A1 86D8                    	xchg	bl, al
   747 000007A3 80E30F                  	and	bl, 0Fh
   748 000007A6 8AA7[1608]              	mov	ah, [bx+hex_chars] 
   749 000007AA 5B                      	pop	bx	
   750 000007AB C3                      	retn
   751                                  
   752                                  wordtohex:
   753                                  	; INPUT ->
   754                                  	; 	AX = word (binary number)
   755                                  	; OUTPUT ->
   756                                  	;	EAX = hexadecimal string
   757                                  	;
   758 000007AC 53                      	push	bx
   759 000007AD 30FF                    	xor	bh, bh
   760 000007AF 86E0                    	xchg	ah, al
   761 000007B1 50                      	push	ax
   762 000007B2 88E3                    	mov	bl, ah
   763 000007B4 C0EB04                  	shr	bl, 4
   764 000007B7 8A87[1608]              	mov	al, [bx+hex_chars] 	 	
   765 000007BB 88E3                    	mov	bl, ah
   766 000007BD 80E30F                  	and	bl, 0Fh
   767 000007C0 8AA7[1608]              	mov	ah, [bx+hex_chars]
   768 000007C4 66C1E010                	shl	eax, 16
   769 000007C8 58                      	pop	ax
   770 000007C9 5B                      	pop	bx
   771 000007CA EBC9                    	jmp	short bytetohex
   772                                  
   773                                  dwordtohex:
   774                                  	; INPUT ->
   775                                  	; 	EAX = dword (binary number)
   776                                  	; OUTPUT ->
   777                                  	;	EDX:EAX = hexadecimal string
   778                                  	;
   779 000007CC 6650                    	push	eax
   780 000007CE 66C1E810                	shr	eax, 16
   781 000007D2 E8D7FF                  	call	wordtohex
   782 000007D5 6689C2                  	mov	edx, eax
   783 000007D8 6658                    	pop	eax
   784 000007DA E8CFFF                  	call	wordtohex
   785 000007DD C3                      	retn
   786                                  
   787                                  _DATA:
   788                                  
   789                                  ; 24/11/2016
   790                                  ;	       IRQ  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 
   791 000007DE 08090A0B0C0D0E0F70-     irq_int		db 08h,09h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,70h,71h,72h,73h,74h,75h,76h,77h
   791 000007E7 71727374757677     
   792                                  
   793                                  ; 17/02/2017
   794                                  ; Valid ICH device IDs
   795                                  
   796                                  valid_ids:
   797 000007EE 86801524                dd	(ICH_DID << 16) + INTEL_VID  ; 8086h:2415h 
   798 000007F2 86802524                dd	(ICH0_DID << 16) + INTEL_VID ; 8086h:2425h 
   799 000007F6 86804524                dd	(ICH2_DID << 16) + INTEL_VID ; 8086h:2445h 
   800 000007FA 86808524                dd	(ICH3_DID << 16) + INTEL_VID ; 8086h:2485h 
   801 000007FE 8680C524                dd	(ICH4_DID << 16) + INTEL_VID ; 8086h:24C5h
   802 00000802 8680D524                dd	(ICH5_DID << 16) + INTEL_VID ; 8086h:24D5h
   803 00000806 86806E26                dd	(ICH6_DID << 16) + INTEL_VID ; 8086h:266Eh
   804 0000080A 8680A625                dd	(ESB6300_DID << 16) + INTEL_VID ; 8086h:25A6h
   805 0000080E 86809826                dd	(ESB631X_DID << 16) + INTEL_VID ; 8086h:2698h
   806 00000812 8680DE27                dd	(ICH7_DID << 16) + INTEL_VID ; 8086h:27DEh
   807                                  valid_id_count:	equ $ - valid_ids 
   808                                  
   809                                  ; 13/11/2016
   810 00000816 303132333435363738-     hex_chars	db "0123456789ABCDEF", 0
   810 0000081F 3941424344454600   
   811 00000827 414339372041756469-     msgAC97Info	db "AC97 Audio Controller & Codec Info", 0Dh, 0Ah 
   811 00000830 6F20436F6E74726F6C-
   811 00000839 6C6572202620436F64-
   811 00000842 656320496E666F0D0A 
   812 0000084B 56656E646F72204944-     		db "Vendor ID: "
   812 00000854 3A20               
   813 00000856 303030306820446576-     msgVendorId	db "0000h Device ID: "
   813 0000085F 6963652049443A20   
   814 00000867 30303030680D0A          msgDevId	db "0000h", 0Dh, 0Ah
   815 0000086E 4275733A20              		db "Bus: "
   816 00000873 303068204465766963-     msgBusNo	db "00h Device: "
   816 0000087C 653A20             
   817 0000087F 3030682046756E6374-     msgDevNo	db "00h Function: "
   817 00000888 696F6E3A20         
   818 0000088D 303068                  msgFncNo	db "00h"
   819 00000890 0D0A                    		db 0Dh, 0Ah
   820 00000892 492F4F204261736520-     		db "I/O Base Address: "
   820 0000089B 416464726573733A20 
   821 000008A4 303030306820495251-     msgIOBaseAddr	db "0000h IRQ: "
   821 000008AD 3A20               
   822 000008AF 3030                    msgIRQ		dw 3030h
   823 000008B1 0D0A24                  		db 0Dh, 0Ah, "$"
   824 000008B4 53616D706C65205261-     msgSampleRate	db "Sample Rate: "
   824 000008BD 74653A20           
   825 000008C1 303030303020487A20-     msgHertz	db "00000 Hz ", "$" 
   825 000008CA 24                 
   826 000008CB 3820626974732024        msg8Bits	db "8 bits ", "$" 
   827 000008D3 4D6F6E6F0D0A24          msgMono		db "Mono", 0Dh, 0Ah, "$"
   828 000008DA 313620626974732024      msg16Bits	db "16 bits ", "$" 
   829 000008E3 53746572656F0D0A24      msgStereo	db "Stereo", 0Dh, 0Ah, "$"
   830                                  
   831                                  ;; 13/11/2016 - Erdogan Tan (Ref: KolibriOS, codec.inc)
   832                                  ;codec_id	dd 0
   833                                  ;codec_chip_id	dd 0
   834                                  ;codec_vendor_ids dw 0
   835                                  ;codec_chip_ids	dw 0
   836                                  
   837 000008EC 3030303030303030        dword_str	 dd 30303030h, 30303030h
   838 000008F4 680D0A00                		 db 'h', 0Dh, 0Ah, 0
   839                                  
   840                                  ;ac_unknown     db 'unknown manufacturer',13,10,0
   841                                  ;ac_Realtek     db 'Realtek Semiconductor',13,10,0
   842                                  ;ac_Analog      db 'Analog Devices',13,10,0
   843                                  ;ac_CMedia      db 'C-Media Electronics',13,10,0
   844                                  ;ac_Cirrus      db 'Cirrus Logic',13,10,0
   845                                  ;ac_Wolfson     db 'Wolfson Microelectronics',13,10,0
   846                                  ;ac_VIA         db 'VIA Technologies',13,10,0
   847                                  ;ac_SigmaTel    db 'SigmaTel',13,10,0
   848                                  ;ac_eMicro      db 'eMicro',13,10,0
   849                                  ;
   850                                  ;chip_unknown   db 'unknown codec id ', 0
   851                                  
   852                                  ;CHIP_REALTEK   equ 414C4700h
   853                                  ;CHIP_CMEDIA    equ 434D4900h
   854                                  ;CHIP_VIA       equ 56494100h
   855                                  
   856                                  ;codecs        dd CHIP_CMEDIA
   857                                  ;	       dw ac_CMedia, chips_CMedia
   858                                  ;              dd CHIP_REALTEK
   859                                  ;	       dw ac_Realtek, chips_Realtek
   860                                  ;              dd CHIP_VIA
   861                                  ;	       dw ac_VIA, chips_VIA
   862                                  ;              dd 0
   863                                  
   864                                  ;chips_Realtek dw 10h, chip_ALC201a
   865                                  ;              dw 20h, chip_ALC650
   866                                  ;              dw 21h, chip_ALC650D
   867                                  ;              dw 22h, chip_ALC650E
   868                                  ;              dw 23h, chip_ALC650F
   869                                  ;              dw 60h, chip_ALC655
   870                                  ;              dw 80h, chip_ALC658
   871                                  ;              dw 81h, chip_ALC658D
   872                                  ;              dw 90h, chip_ALC850
   873                                  ;              dw 0FFh
   874                                  
   875                                  ;chips_CMedia  dw 41h, chip_CM9738
   876                                  ;              dw 61h, chip_CM9739
   877                                  ;              dw 69h, chip_CM9780
   878                                  ;              dw 78h, chip_CM9761
   879                                  ;              dw 82h, chip_CM9761
   880                                  ;              dw 83h, chip_CM9761
   881                                  ;              dw 0FFh
   882                                  
   883                                  ;chips_VIA     dw 61h, chip_VIA1612A
   884                                  ;              dw 0FFh
   885                                  
   886                                  ;Realtek
   887                                  ;chip_ALC201a    db 'ALC201a',0dh,0ah,00h
   888                                  ;chip_ALC650     db 'ALC650 ',0dh,0ah,00h
   889                                  ;chip_ALC650D    db 'ALC650D',0dh,0ah,00h
   890                                  ;chip_ALC650E    db 'ALC650E',0dh,0ah,00h
   891                                  ;chip_ALC650F    db 'ALC650F',0dh,0ah,00h
   892                                  ;chip_ALC655     db 'ALC655 ',0dh,0ah,00h
   893                                  ;chip_ALC658     db 'ALC658 ',0dh,0ah,00h
   894                                  ;chip_ALC658D    db 'ALC658D',0dh,0ah,00h
   895                                  ;chip_ALC850     db 'ALC850 ',0dh,0ah,00h
   896                                  
   897                                  ;CMedia
   898                                  ;chip_CM9738     db 'CMI9738', 0dh,0ah,0
   899                                  ;chip_CM9739     db 'CMI9739', 0dh,0ah,0
   900                                  ;chip_CM9780     db 'CMI9780', 0dh,0ah,0
   901                                  ;chip_CM9761     db 'CMI9761', 0dh,0ah,0
   902                                  
   903                                  ;VIA
   904                                  ;chip_VIA1612A   db 'VIA1612A',13,10,0
   905                                  
   906                                  ; 17/02/2017
   907                                  bss_start:
   908                                  
   909                                  ABSOLUTE bss_start
   910                                  
   911                                  alignb 2
   912                                  
   913                                  ; 28/11/2016
   914                                  
   915 000008F8 <res 0000001C>          smpRBuff:	resw 14 ; 19/11/2016 - Erdogan Tan
   916                                  
   917 00000914 <res 00000002>          filehandle:	resw 1
   918                                  
   919 00000916 <res 00000001>          flags:		resb 1
   920 00000917 <res 00000001>          irq_status:	resb 1
   921                                  
   922 00000918 <res 00000001>          inside:		resb 1
   923 00000919 <res 00000001>          tLoop:		resb 1	
   924                                  
   925                                  ; 17/02/2017
   926                                  ; NAMBAR:  Native Audio Mixer Base Address Register
   927                                  ;    (ICH, Audio D31:F5, PCI Config Space) Address offset: 10h-13h
   928                                  ; NABMBAR: Native Audio Bus Mastering Base Address register
   929                                  ;    (ICH, Audio D31:F5, PCI Config Space) Address offset: 14h-17h
   930 0000091A <res 00000002>          NAMBAR:		resw 1			; BAR for mixer
   931 0000091C <res 00000002>          NABMBAR         resw 1			; BAR for bus master regs
   932                                  
   933                                  ; 256 byte buffer for descriptor list
   934 0000091E <res 00000002>          BDL_BUFFER:	resw 1			; segment of our 256byte BDL buffer
   935 00000920 <res 00000002>          WAV_BUFFER1:	resw 1			; segment of our WAV storage
   936                                  ; 64k buffers for wav file storage
   937 00000922 <res 00000002>          WAV_BUFFER2:	resw 1			; segment of 2nd wav buffer
   938                                  
   939 00000924 <res 00000001>          tBuff:		resb 1
   940                                  
   941 00000925 <res 00000001>          ac97_int_ln_reg: resb 1
   942                                  
   943                                  ; 12/11/2016 - Erdogan Tan
   944                                  
   945 00000926 <res 00000004>          bus_dev_fn:	resd 1
   946 0000092A <res 00000004>          dev_vendor:	resd 1
   947 0000092E <res 00000002>          stats_cmd:	resw 1 ; 17/02/2017
   948 00000930 <res 00000002>          ac97_io_base:	resw 1
   949 00000932 <res 00000002>          sample_rate:	resw 1
   950                                  ; 19/11/2016
   951 00000934 <res 00000002>          stmo:		resw 1 
   952 00000936 <res 00000002>          bps:		resw 1
   953                                  
   954 00000938 <res 00000001>          fbs_shift:	resb 1
   955 00000939 <res 00000002>          fbs_seg:	resw 1
   956 0000093B <res 00000002>          fbs_off:	resw 1
   957                                  
   958                                  ; 32 kilo bytes for temporay buffer
   959                                  ; (for stereo-mono, 8bit/16bit corrections)
   960 0000093D <res 00008000>          temp_buffer:	resb 32768
   961 0000893D <res 00000003>          alignb 16
   962                                  EOF:
