     1                                  ; ****************************************************************************
     2                                  ; wavplay.s (for TRDOS 386)
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; WAVPLAY.PRG ! VIA VT8237R (VT8233) .WAV PLAYER program by Erdogan TAN
     5                                  ;
     6                                  ; 17/03/2017
     7                                  ;
     8                                  ; [ Last Modification: 24/06/2017 ]
     9                                  ;
    10                                  ; Modified from PLAYWAV.PRG .wav player program by Erdogan Tan, 10/03/2017 
    11                                  ;
    12                                  ; Derived from source code of 'PLAYER.COM' ('PLAYER.ASM') by Erdogan Tan
    13                                  ;	      (18/02/2017) 
    14                                  ; Assembler: NASM version 2.11
    15                                  ;	     nasm wavplay.asm -l wavplay.txt -o WAVPLAY.PRG	
    16                                  ; ----------------------------------------------------------------------------
    17                                  ; Derived from '.wav file player for DOS' Jeff Leyda, Sep 02, 2002
    18                                  
    19                                  ; 01/03/2017
    20                                  ; 16/10/2016
    21                                  ; 29/04/2016
    22                                  ; TRDOS 386 system calls (temporary list!)
    23                                  _ver 	equ 0
    24                                  _exit 	equ 1
    25                                  _fork 	equ 2
    26                                  _read 	equ 3
    27                                  _write	equ 4
    28                                  _open	equ 5
    29                                  _close 	equ 6
    30                                  _wait 	equ 7
    31                                  _creat 	equ 8
    32                                  _link 	equ 9
    33                                  _unlink	equ 10
    34                                  _exec	equ 11
    35                                  _chdir	equ 12
    36                                  _time 	equ 13
    37                                  _mkdir 	equ 14
    38                                  _chmod	equ 15
    39                                  _chown	equ 16
    40                                  _break	equ 17
    41                                  _stat	equ 18
    42                                  _seek	equ 19
    43                                  _tell 	equ 20
    44                                  _mount	equ 21
    45                                  _umount	equ 22
    46                                  _setuid	equ 23
    47                                  _getuid	equ 24
    48                                  _stime	equ 25
    49                                  _quit	equ 26	
    50                                  _intr	equ 27
    51                                  _fstat	equ 28
    52                                  _emt 	equ 29
    53                                  _mdate 	equ 30
    54                                  _video 	equ 31
    55                                  _audio	equ 32
    56                                  _timer	equ 33
    57                                  _sleep	equ 34
    58                                  _msg    equ 35
    59                                  _geterr	equ 36
    60                                  _fpsave	equ 37
    61                                  _pri	equ 38
    62                                  _rele	equ 39
    63                                  _fff	equ 40
    64                                  _fnf	equ 41
    65                                  _alloc	equ 42
    66                                  _dalloc equ 43
    67                                  _calbac equ 44
    68                                  
    69                                  %macro sys 1-4
    70                                      ; 29/04/2016 - TRDOS 386 (TRDOS v2.0)	
    71                                      ; 03/09/2015	
    72                                      ; 13/04/2015
    73                                      ; Retro UNIX 386 v1 system call.	
    74                                      %if %0 >= 2   
    75                                          mov ebx, %2
    76                                          %if %0 >= 3    
    77                                              mov ecx, %3
    78                                              %if %0 = 4
    79                                                 mov edx, %4   
    80                                              %endif
    81                                          %endif
    82                                      %endif
    83                                      mov eax, %1
    84                                      ;int 30h
    85                                      int 40h ; TRDOS 386 (TRDOS v2.0)	   
    86                                  %endmacro
    87                                  
    88                                  ; TRDOS 386 (and Retro UNIX 386 v1) system call format:
    89                                  ; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
    90                                  
    91                                  
    92                                  [BITS 32]
    93                                  
    94                                  [ORG 0] 
    95                                  
    96                                  _STARTUP:
    97                                  	; Prints the Credits Text.
    98                                  	sys	_msg, Credits, 255, 0Bh
    98                              <1> 
    98                              <1> 
    98                              <1> 
    98                              <1> 
    98                              <1>  %if %0 >= 2
    98 00000000 BB[85090000]        <1>  mov ebx, %2
    98                              <1>  %if %0 >= 3
    98 00000005 B9FF000000          <1>  mov ecx, %3
    98                              <1>  %if %0 = 4
    98 0000000A BA0B000000          <1>  mov edx, %4
    98                              <1>  %endif
    98                              <1>  %endif
    98                              <1>  %endif
    98 0000000F B823000000          <1>  mov eax, %1
    98                              <1> 
    98 00000014 CD40                <1>  int 40h
    99                                  
   100                                  	; clear bss
   101 00000016 B9[00000200]            	mov	ecx, EOF
   102 0000001B BF[E00A0000]            	mov	edi, bss_start
   103 00000020 29F9                    	sub	ecx, edi
   104 00000022 D1E9                    	shr	ecx, 1
   105 00000024 31C0                    	xor	eax, eax
   106 00000026 F366AB                  	rep	stosw
   107                                  
   108 00000029 E8A0010000              	call    DetectVT8233	; Detect the VT8233 Audio Device
   109                                  GetFileName:  
   110 0000002E 89E6                    	mov	esi, esp
   111 00000030 AD                      	lodsd
   112 00000031 83F802                  	cmp	eax, 2 ; two arguments 
   113                                  	       ; (program file name & mod file name)
   114 00000034 0F8264010000            	jb	pmsg_usage ; nothing to do
   115                                  
   116 0000003A AD                      	lodsd ; program file name address 
   117 0000003B AD                      	lodsd ; mod file name address (file to be read)
   118 0000003C 89C6                    	mov	esi, eax
   119 0000003E BF[180B0000]            	mov	edi, wav_file_name
   120                                  ScanName:       
   121 00000043 AC                      	lodsb
   122 00000044 84C0                    	test	al, al
   123 00000046 0F8452010000            	je	pmsg_usage
   124 0000004C 3C20                    	cmp	al, 20h
   125 0000004E 74F3                    	je	short ScanName	; scan start of name.
   126 00000050 AA                      	stosb
   127 00000051 B4FF                    	mov	ah, 0FFh
   128                                  a_0:	
   129 00000053 FEC4                    	inc	ah
   130                                  a_1:
   131 00000055 AC                      	lodsb
   132 00000056 AA                      	stosb
   133 00000057 3C2E                    	cmp	al, '.'
   134 00000059 74F8                    	je	short a_0	
   135 0000005B 20C0                    	and	al, al
   136 0000005D 75F6                    	jnz	short a_1
   137                                  
   138 0000005F 08E4                    	or	ah, ah		 ; if period NOT found,
   139 00000061 750B                    	jnz	short init_codec ; then add a .WAV extension.
   140                                  SetExt:
   141 00000063 4F                      	dec	edi
   142 00000064 C7072E574156            	mov	dword [edi], '.WAV'
   143 0000006A C6470400                	mov	byte [edi+4], 0
   144                                  
   145                                  init_codec:
   146                                  	; init AC97 codec
   147                                  
   148                                  	; 19/06/2017
   149                                  	; 05/06/2017
   150                                  	; 19/03/2017
   151 0000006E A1[E80A0000]            	mov	eax, [bus_dev_fn]
   152 00000073 B041                    	mov	al, VIA_ACLINK_CTRL  ; AC link interface control (41h)
   153 00000075 E8A7020000              	call	pciRegRead8
   154                                  
   155                                  	;mov	eax, [bus_dev_fn]
   156 0000007A B040                    	mov	al, VIA_ACLINK_STAT  ; AC Link interface status (40h)
   157 0000007C E8A0020000              	call	pciRegRead8
   158                                  	
   159 00000081 0FB6C2                  	movzx	eax, dl
   160 00000084 2401                    	and	al, VIA_ACLINK_C00_READY  ; 1 ; primary codec ready ?
   161 00000086 7522                    	jnz	short a_2
   162                                  
   163 00000088 E8EC030000              	call	reset_codec
   164 0000008D 731B                    	jnc	short a_2 ; EAX = 1
   165                                  
   166                                  	;test	al, VIA_ACLINK_C00_READY 	
   167                                          ;jnz     short a_2
   168                                  
   169                                  _codec_err:
   170                                  	sys	_msg, CodecErrMsg, 255, 0Fh
   170                              <1> 
   170                              <1> 
   170                              <1> 
   170                              <1> 
   170                              <1>  %if %0 >= 2
   170 0000008F BB[57090000]        <1>  mov ebx, %2
   170                              <1>  %if %0 >= 3
   170 00000094 B9FF000000          <1>  mov ecx, %3
   170                              <1>  %if %0 = 4
   170 00000099 BA0F000000          <1>  mov edx, %4
   170                              <1>  %endif
   170                              <1>  %endif
   170                              <1>  %endif
   170 0000009E B823000000          <1>  mov eax, %1
   170                              <1> 
   170 000000A3 CD40                <1>  int 40h
   171 000000A5 E9EB000000                      jmp     Exit
   172                                  
   173                                  a_2:
   174                                  	; eax = 1
   175 000000AA E81C040000              	call	codec_io_w16 ; w32
   176                                  	
   177                                  	;call	detect_codec
   178                                  
   179 000000AF E8D8040000              	call	channel_reset
   180                                  
   181 000000B4 E8E6060000              	call	write_ac97_dev_info 
   182                                  
   183                                  a_3:
   184                                  	; SETUP INTERRUPT CALLBACK SERVICE
   185                                  	; 05/03/2017
   186                                  	;mov	bl, [ac97_int_ln_reg] ; IRQ number
   187                                  	;mov	bh, 2 ; Link IRQ to user for callback service
   188                                  	;mov	edx, ac97_int_handler
   189                                  	;sys	_calbac
   190                                  	;jc	error_exit
   191                                  
   192                                  	; 24/06/2017
   193                                  	;; 23/06/2017
   194                                  	;mov	bl, [ac97_int_ln_reg] ; IRQ number
   195                                  	;mov	bh, 1 ; Link IRQ to user for signal response byte
   196                                  	;mov	cl, bh ; 1
   197                                  	;mov	edx, srb
   198                                  	;sys	_calbac
   199                                  
   200                                  	; DIRECT CGA (TEXT MODE) MEMORY ACCESS
   201                                  	; bl = 0, bh = 4
   202                                  	; Direct access/map to CGA (Text) memory (0B8000h)
   203                                  
   204                                  	sys	_video, 0400h
   204                              <1> 
   204                              <1> 
   204                              <1> 
   204                              <1> 
   204                              <1>  %if %0 >= 2
   204 000000B9 BB00040000          <1>  mov ebx, %2
   204                              <1>  %if %0 >= 3
   204                              <1>  mov ecx, %3
   204                              <1>  %if %0 = 4
   204                              <1>  mov edx, %4
   204                              <1>  %endif
   204                              <1>  %endif
   204                              <1>  %endif
   204 000000BE B81F000000          <1>  mov eax, %1
   204                              <1> 
   204 000000C3 CD40                <1>  int 40h
   205 000000C5 3D00800B00              	cmp	eax, 0B8000h
   206 000000CA 0F85E6000000            	jne	error_exit
   207                                  
   208                                  ; open the file
   209                                          ; open existing file
   210 000000D0 E85B010000                      call    openFile ; no error? ok.
   211 000000D5 731B                            jnc     short _gsr
   212                                  
   213                                  ; file not found!
   214                                  	sys	_msg, noFileErrMsg, 255, 0Fh
   214                              <1> 
   214                              <1> 
   214                              <1> 
   214                              <1> 
   214                              <1>  %if %0 >= 2
   214 000000D7 BB[CD090000]        <1>  mov ebx, %2
   214                              <1>  %if %0 >= 3
   214 000000DC B9FF000000          <1>  mov ecx, %3
   214                              <1>  %if %0 = 4
   214 000000E1 BA0F000000          <1>  mov edx, %4
   214                              <1>  %endif
   214                              <1>  %endif
   214                              <1>  %endif
   214 000000E6 B823000000          <1>  mov eax, %1
   214                              <1> 
   214 000000EB CD40                <1>  int 40h
   215 000000ED E9A3000000                      jmp     Exit
   216                                  
   217                                  _gsr:  
   218 000000F2 E869010000                     	call    getSampleRate		; read the sample rate
   219                                                                          ; pass it onto codec.
   220 000000F7 0F8298000000            	jc	Exit
   221                                  
   222 000000FD 66A3[FA0A0000]          	mov	[sample_rate], ax
   223 00000103 880D[F80A0000]          	mov	[stmo], cl
   224 00000109 8815[F90A0000]          	mov	[bps], dl
   225                                  
   226                                  	; 24/06/2017
   227                                  ; setup the Codec (actually mixer registers) 
   228 0000010F E8CF020000                      call    codecConfig            ; unmute codec, set rates.
   229                                  	;jc	_codec_err
   230                                  
   231                                  PlayNow: 
   232                                  	; DIRECT MEMORY ACCESS (for Audio Controller)
   233                                  	; ebx = BDL buffer address (virtual, user)
   234                                  	; ecx = buffer size (in bytes)
   235                                  	; edx = upper limit = 0 = no limit
   236                                  
   237                                  	sys	_alloc, BdlBuffer, 4096, 0 
   237                              <1> 
   237                              <1> 
   237                              <1> 
   237                              <1> 
   237                              <1>  %if %0 >= 2
   237 00000114 BB[00100000]        <1>  mov ebx, %2
   237                              <1>  %if %0 >= 3
   237 00000119 B900100000          <1>  mov ecx, %3
   237                              <1>  %if %0 = 4
   237 0000011E BA00000000          <1>  mov edx, %4
   237                              <1>  %endif
   237                              <1>  %endif
   237                              <1>  %endif
   237 00000123 B82A000000          <1>  mov eax, %1
   237                              <1> 
   237 00000128 CD40                <1>  int 40h
   238 0000012A 0F8286000000            	jc	error_exit
   239                                  
   240 00000130 A3[680B0000]            	mov	[BDL_phy_buff], eax	; physical address
   241                                  					; of the buffer
   242                                  					; (which is needed
   243                                  					; for Audio controller)
   244                                  
   245                                  	; DIRECT MEMORY ACCESS (for Audio Controller)
   246                                  	; ebx = DMA buffer address (virtual, user)
   247                                  	; ecx = buffer size (in bytes)
   248                                  	; edx = upper limit = 0 = no limit
   249                                  
   250                                  	sys	_alloc, DmaBuffer, 65536, 0 
   250                              <1> 
   250                              <1> 
   250                              <1> 
   250                              <1> 
   250                              <1>  %if %0 >= 2
   250 00000135 BB[00000100]        <1>  mov ebx, %2
   250                              <1>  %if %0 >= 3
   250 0000013A B900000100          <1>  mov ecx, %3
   250                              <1>  %if %0 = 4
   250 0000013F BA00000000          <1>  mov edx, %4
   250                              <1>  %endif
   250                              <1>  %endif
   250                              <1>  %endif
   250 00000144 B82A000000          <1>  mov eax, %1
   250                              <1> 
   250 00000149 CD40                <1>  int 40h
   251 0000014B 7269                    	jc	short error_exit
   252                                  
   253 0000014D A3[6C0B0000]            	mov	[DMA_phy_buff], eax	; physical address
   254                                  					; of the buffer
   255                                  					; (which is needed
   256                                  					; for Audio controller)
   257                                  ;
   258                                  ; position file pointer to start in actual wav data
   259                                  ; MUCH improvement should really be done here to check if sample size is
   260                                  ; supported, make sure there are 2 channels, etc.  
   261                                  ;
   262                                          ;mov     ah, 42h
   263                                          ;mov     al, 0	; from start of file
   264                                          ;mov     bx, [FileHandle]
   265                                          ;xor     cx, cx
   266                                          ;mov     dx, 44	; jump past .wav/riff header
   267                                          ;int     21h
   268                                  
   269                                  	sys	_seek, [FileHandle], 44, 0
   269                              <1> 
   269                              <1> 
   269                              <1> 
   269                              <1> 
   269                              <1>  %if %0 >= 2
   269 00000152 8B1D[060A0000]      <1>  mov ebx, %2
   269                              <1>  %if %0 >= 3
   269 00000158 B92C000000          <1>  mov ecx, %3
   269                              <1>  %if %0 = 4
   269 0000015D BA00000000          <1>  mov edx, %4
   269                              <1>  %endif
   269                              <1>  %endif
   269                              <1>  %endif
   269 00000162 B813000000          <1>  mov eax, %1
   269                              <1> 
   269 00000167 CD40                <1>  int 40h
   270                                  
   271                                  ; play the .wav file.  Most of the good stuff is in here.
   272                                  
   273 00000169 E89D040000                      call    PlayWav
   274                                  
   275                                  ; close the .wav file and exit.
   276                                  
   277 0000016E E8D6000000                      call    closeFile
   278                                  
   279                                  StopPlaying:
   280                                  	; 24/06/2017
   281                                  	;mov	bl, [ac97_int_ln_reg] ; Audio IRQ number
   282                                  	;sub	bh, bh ; 0 = Unlink IRQ from user
   283                                  	;sys	_calbac 
   284                                  
   285                                  	; Deallocate BDL buffer (not necessary just before exit!)
   286                                  	sys	_dalloc, BdlBuffer, 4096
   286                              <1> 
   286                              <1> 
   286                              <1> 
   286                              <1> 
   286                              <1>  %if %0 >= 2
   286 00000173 BB[00100000]        <1>  mov ebx, %2
   286                              <1>  %if %0 >= 3
   286 00000178 B900100000          <1>  mov ecx, %3
   286                              <1>  %if %0 = 4
   286                              <1>  mov edx, %4
   286                              <1>  %endif
   286                              <1>  %endif
   286                              <1>  %endif
   286 0000017D B82B000000          <1>  mov eax, %1
   286                              <1> 
   286 00000182 CD40                <1>  int 40h
   287                                  	; Deallocate DMA buffer (not necessary just before exit!)
   288                                  	sys	_dalloc, DmaBuffer, 65536  ; 14/03/2017
   288                              <1> 
   288                              <1> 
   288                              <1> 
   288                              <1> 
   288                              <1>  %if %0 >= 2
   288 00000184 BB[00000100]        <1>  mov ebx, %2
   288                              <1>  %if %0 >= 3
   288 00000189 B900000100          <1>  mov ecx, %3
   288                              <1>  %if %0 = 4
   288                              <1>  mov edx, %4
   288                              <1>  %endif
   288                              <1>  %endif
   288                              <1>  %endif
   288 0000018E B82B000000          <1>  mov eax, %1
   288                              <1> 
   288 00000193 CD40                <1>  int 40h
   289                                  Exit:           
   290                                  	sys	_exit	; Bye!
   290                              <1> 
   290                              <1> 
   290                              <1> 
   290                              <1> 
   290                              <1>  %if %0 >= 2
   290                              <1>  mov ebx, %2
   290                              <1>  %if %0 >= 3
   290                              <1>  mov ecx, %3
   290                              <1>  %if %0 = 4
   290                              <1>  mov edx, %4
   290                              <1>  %endif
   290                              <1>  %endif
   290                              <1>  %endif
   290 00000195 B801000000          <1>  mov eax, %1
   290                              <1> 
   290 0000019A CD40                <1>  int 40h
   291                                  here:
   292 0000019C EBFE                    	jmp	short here
   293                                  
   294                                  pmsg_usage:
   295                                  	sys	_msg, msg_usage, 255, 0Bh
   295                              <1> 
   295                              <1> 
   295                              <1> 
   295                              <1> 
   295                              <1>  %if %0 >= 2
   295 0000019E BB[67090000]        <1>  mov ebx, %2
   295                              <1>  %if %0 >= 3
   295 000001A3 B9FF000000          <1>  mov ecx, %3
   295                              <1>  %if %0 = 4
   295 000001A8 BA0B000000          <1>  mov edx, %4
   295                              <1>  %endif
   295                              <1>  %endif
   295                              <1>  %endif
   295 000001AD B823000000          <1>  mov eax, %1
   295                              <1> 
   295 000001B2 CD40                <1>  int 40h
   296 000001B4 EBDF                    	jmp	short Exit
   297                                  
   298                                  error_exit:
   299                                  	sys	_msg, trdos386_err_msg, 255, 0Eh
   299                              <1> 
   299                              <1> 
   299                              <1> 
   299                              <1> 
   299                              <1>  %if %0 >= 2
   299 000001B6 BB[E6090000]        <1>  mov ebx, %2
   299                              <1>  %if %0 >= 3
   299 000001BB B9FF000000          <1>  mov ecx, %3
   299                              <1>  %if %0 = 4
   299 000001C0 BA0E000000          <1>  mov edx, %4
   299                              <1>  %endif
   299                              <1>  %endif
   299                              <1>  %endif
   299 000001C5 B823000000          <1>  mov eax, %1
   299                              <1> 
   299 000001CA CD40                <1>  int 40h
   300 000001CC EBC7                    	jmp	short Exit
   301                                  
   302                                  DetectVT8233:
   303 000001CE B806115930              	mov     eax, (VT8233_DID << 16) + VIA_VID
   304 000001D3 E8DD010000                      call    pciFindDevice
   305 000001D8 7318                            jnc     short _1
   306                                  
   307                                  ; couldn't find the audio device!
   308                                  	sys	_msg, noDevMsg, 255, 0Fh
   308                              <1> 
   308                              <1> 
   308                              <1> 
   308                              <1> 
   308                              <1>  %if %0 >= 2
   308 000001DA BB[20090000]        <1>  mov ebx, %2
   308                              <1>  %if %0 >= 3
   308 000001DF B9FF000000          <1>  mov ecx, %3
   308                              <1>  %if %0 = 4
   308 000001E4 BA0F000000          <1>  mov edx, %4
   308                              <1>  %endif
   308                              <1>  %endif
   308                              <1>  %endif
   308 000001E9 B823000000          <1>  mov eax, %1
   308                              <1> 
   308 000001EE CD40                <1>  int 40h
   309 000001F0 EBA3                            jmp     short Exit
   310                                  
   311                                  _1:
   312                                  	; 19/06/2017
   313                                  	; 05/03/2017 (TRDOS 386)
   314                                  	; 12/11/2016
   315                                  	; Erdogan Tan - 8/11/2016
   316                                  	; References: Kolibrios - vt823x.asm (2016)
   317                                  	;	      VIA VT8235 V-Link South Bridge (VT8235-VIA.PDF)(2002)
   318                                  	;	      lowlevel.eu - AC97 (2016)
   319                                  	;	      .wav player for DOS by Jeff Leyda (2002) -this file-
   320                                  	;	      Linux kernel - via82xx.c (2016)
   321                                  
   322                                  	; eax = BUS/DEV/FN
   323                                  	;	00000000BBBBBBBBDDDDDFFF00000000
   324                                  	; edx = DEV/VENDOR
   325                                  	;	DDDDDDDDDDDDDDDDVVVVVVVVVVVVVVVV
   326                                  
   327 000001F2 A3[E80A0000]            	mov	[bus_dev_fn], eax
   328 000001F7 8915[EC0A0000]          	mov	[dev_vendor], edx
   329                                  
   330                                  	; init controller
   331 000001FD B004                    	mov	al, PCI_CMD_REG ; command register (04h)
   332 000001FF E830010000              	call	pciRegRead32
   333                                  
   334                                  	; eax = BUS/DEV/FN/REG
   335                                  	; edx = STATUS/COMMAND
   336                                  	; 	SSSSSSSSSSSSSSSSCCCCCCCCCCCCCCCC
   337 00000204 8915[F00A0000]          	mov	[stats_cmd], edx
   338                                  
   339 0000020A B010                    	mov	al, PCI_IO_BASE ; IO base address register (10h)
   340 0000020C E823010000              	call	pciRegRead32
   341                                  
   342 00000211 6683E2C0                	and     dx, 0FFC0h	; IO_ADDR_MASK (0FFFE) ?
   343 00000215 668915[F40A0000]                mov     [ac97_io_base], dx
   344                                  
   345 0000021C B03C                    	mov	al, AC97_INT_LINE ; Interrupt line register (3Ch)
   346 0000021E E811010000              	call	pciRegRead32
   347                                  
   348 00000223 81E2FF000000            	and 	edx, 0FFh
   349 00000229 8815[F60A0000]            	mov     [ac97_int_ln_reg], dl
   350                                  
   351 0000022F C3                      	retn
   352                                  
   353                                  ;open or create file
   354                                  ;
   355                                  ;input: ds:dx-->filename (asciiz)
   356                                  ;       al=file Mode (create or open)
   357                                  ;output: none  cs:[FileHandle] filled
   358                                  ;
   359                                  openFile:
   360                                  	;;push	eax
   361                                  	;;push	ecx
   362                                  	;mov	ah, 3Bh	; start with a mode
   363                                  	;add	ah, al	; add in create or open mode
   364                                  	;xor	cx, cx
   365                                  	;int	21h
   366                                  	;jc	short _of1
   367                                  	;;mov	[cs:FileHandle], ax
   368                                  
   369                                  	sys	_open, wav_file_name, 0
   369                              <1> 
   369                              <1> 
   369                              <1> 
   369                              <1> 
   369                              <1>  %if %0 >= 2
   369 00000230 BB[180B0000]        <1>  mov ebx, %2
   369                              <1>  %if %0 >= 3
   369 00000235 B900000000          <1>  mov ecx, %3
   369                              <1>  %if %0 = 4
   369                              <1>  mov edx, %4
   369                              <1>  %endif
   369                              <1>  %endif
   369                              <1>  %endif
   369 0000023A B805000000          <1>  mov eax, %1
   369                              <1> 
   369 0000023F CD40                <1>  int 40h
   370 00000241 7205                    	jc	short _of1
   371                                  
   372 00000243 A3[060A0000]            	mov	[FileHandle], eax
   373                                  _of1:
   374                                  	;;pop	ecx
   375                                  	;;pop	eax
   376 00000248 C3                      	retn
   377                                  
   378                                  ; close the currently open file
   379                                  ; input: none, uses cs:[FileHandle]
   380                                  closeFile:
   381                                  	;push	eax
   382                                  	;push	ebx
   383 00000249 833D[060A0000]FF        	cmp	dword [FileHandle], -1
   384 00000250 740D                    	je	short _cf1
   385                                  	;mov    bx, [FileHandle]  
   386                                  	;mov    ax, 3E00h
   387                                          ;int    21h              ;close file
   388                                  
   389                                  	sys	_close, [FileHandle]
   389                              <1> 
   389                              <1> 
   389                              <1> 
   389                              <1> 
   389                              <1>  %if %0 >= 2
   389 00000252 8B1D[060A0000]      <1>  mov ebx, %2
   389                              <1>  %if %0 >= 3
   389                              <1>  mov ecx, %3
   389                              <1>  %if %0 = 4
   389                              <1>  mov edx, %4
   389                              <1>  %endif
   389                              <1>  %endif
   389                              <1>  %endif
   389 00000258 B806000000          <1>  mov eax, %1
   389                              <1> 
   389 0000025D CD40                <1>  int 40h
   390                                  _cf1:
   391                                  	;pop	ebx
   392                                  	;pop	eax
   393 0000025F C3                      	retn
   394                                  
   395                                  getSampleRate:
   396                                  	
   397                                  ; reads the sample rate from the .wav file.
   398                                  ; entry: none - assumes file is already open
   399                                  ; exit: ax = sample rate (11025, 22050, 44100, 48000)
   400                                  ;	cx = number of channels (mono=1, stereo=2)
   401                                  ;	dx = bits per sample (8, 16)
   402                                  
   403 00000260 53                      	push    ebx
   404                                  
   405                                          ;mov	ah, 42h
   406                                          ;mov	al, 0	; from start of file
   407                                          ;mov	bx, [FileHandle]
   408                                          ;xor	cx, cx
   409                                          ;mov	dx, 08h	; "WAVE"
   410                                          ;int	21h
   411                                  	
   412                                  	sys	_seek, [FileHandle], 8, 0
   412                              <1> 
   412                              <1> 
   412                              <1> 
   412                              <1> 
   412                              <1>  %if %0 >= 2
   412 00000261 8B1D[060A0000]      <1>  mov ebx, %2
   412                              <1>  %if %0 >= 3
   412 00000267 B908000000          <1>  mov ecx, %3
   412                              <1>  %if %0 = 4
   412 0000026C BA00000000          <1>  mov edx, %4
   412                              <1>  %endif
   412                              <1>  %endif
   412                              <1>  %endif
   412 00000271 B813000000          <1>  mov eax, %1
   412                              <1> 
   412 00000276 CD40                <1>  int 40h
   413                                  
   414                                          ;mov	dx, smpRBuff
   415                                          ;mov	cx, 28	; 28 bytes
   416                                  	;mov	ah, 3fh
   417                                          ;int	21h
   418                                  
   419                                  	sys	_read, [FileHandle], smpRBuff, 28
   419                              <1> 
   419                              <1> 
   419                              <1> 
   419                              <1> 
   419                              <1>  %if %0 >= 2
   419 00000278 8B1D[060A0000]      <1>  mov ebx, %2
   419                              <1>  %if %0 >= 3
   419 0000027E B9[FC0A0000]        <1>  mov ecx, %3
   419                              <1>  %if %0 = 4
   419 00000283 BA1C000000          <1>  mov edx, %4
   419                              <1>  %endif
   419                              <1>  %endif
   419                              <1>  %endif
   419 00000288 B803000000          <1>  mov eax, %1
   419                              <1> 
   419 0000028D CD40                <1>  int 40h
   420                                  
   421 0000028F 813D[FC0A0000]5741-     	cmp	dword [smpRBuff], 'WAVE'
   421 00000297 5645               
   422 00000299 7520                    	jne	short gsr_stc
   423                                  
   424 0000029B 66833D[080B0000]01      	cmp	word [smpRBuff+12], 1	; Offset 20, must be 1 (= PCM)
   425 000002A3 7516                    	jne	short gsr_stc
   426                                  
   427 000002A5 668B0D[0A0B0000]        	mov	cx, [smpRBuff+14]	; return num of channels in CX
   428 000002AC 66A1[0C0B0000]                  mov     ax, [smpRBuff+16]	; return sample rate in AX
   429 000002B2 668B15[160B0000]        	mov	dx, [smpRBuff+26]	; return bits per sample value in DX
   430                                  gsr_retn:
   431 000002B9 5B                              pop     ebx
   432 000002BA C3                              retn
   433                                  gsr_stc:
   434 000002BB F9                      	stc
   435 000002BC EBFB                    	jmp	short gsr_retn
   436                                  
   437                                  ;ac97_int_handler:
   438                                  ;	; 19/06/2017
   439                                  ;	; 14/03/2017
   440                                  ;	; 06/03/2017 (Signal Response Byte Check)
   441                                  ;	; 05/03/2017 (Modified for TRDOS 386 IRQ callback method)
   442                                  ;
   443                                  ;	mov	byte [srb], 1 ; interrupt (or signal response byte)
   444                                  ;
   445                                  ;	cmp	byte [audio_busy], 1
   446                                  ;	jnb	short _ih1 ; busy !
   447                                  ;
   448                                  ;	mov	byte [audio_busy], 1
   449                                  ;
   450                                  ;	mov	byte [audio_flag_eol], 0
   451                                  ;
   452                                  ;       mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_STATUS
   453                                  ;       call    ctrl_io_r8
   454                                  ;
   455                                  ;	test    al, VIA_REG_STAT_ACTIVE
   456                                  ;       jz      short _ih1
   457                                  ;
   458                                  ;       and     al, VIA_REG_STAT_EOL + VIA_REG_STAT_FLAG + VIA_REG_STAT_STOPPED
   459                                  ;	mov	[audio_flag_eol], al
   460                                  ;       jz	short _ih1
   461                                  ;
   462                                  ;	; 28/11/2016 - Erdogan Tan
   463                                  ;	call	tuneLoop
   464                                  ;
   465                                  ;	; 19/06/2017
   466                                  ;	xor	al, al ; 0
   467                                  ;	cmp 	[audio_flag], al ; 0
   468                                  ;	ja	short _ih0
   469                                  ;	inc	al ; 1
   470                                  ;_ih0:
   471                                  ;	mov 	[audio_flag], al
   472                                  ;_ih1:
   473                                  ;	; 28/11/2016 - Erdogan Tan
   474                                  ;       mov     al, [audio_flag_eol]   ;; ack ;;
   475                                  ;       mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_STATUS
   476                                  ;       call    ctrl_io_w8
   477                                  ;
   478                                  ;	test	byte [audio_flag_eol], VIA_REG_STAT_FLAG 
   479                                  ;	jz	short _ih2 ; 21/04/2017 (19/06/2017)
   480                                  ;
   481                                  ;	mov	al, VIA_REG_CTRL_INT
   482                                  ;	or	al, VIA_REG_CTRL_START
   483                                  ;	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_CONTROL
   484                                  ;	call    ctrl_io_w8
   485                                  ;	
   486                                  ;	;call	codec_check_ready
   487                                  ;_ih2:
   488                                  ;	; 19/06/2017
   489                                  ;	mov	byte [audio_busy], 0
   490                                  ;	;
   491                                  ;	sys	_rele ; return from callback service 
   492                                  ;	; we must not come here !
   493                                  ;	sys	_exit
   494                                  ;;_ih3:
   495                                  ;;	;sti
   496                                  ;;	nop
   497                                  ;;	jmp	 short _ih3
   498                                  
   499                                  ;=============================================================================
   500                                  ;               PCI.ASM
   501                                  ;=============================================================================
   502                                  
   503                                  ; EQUATES
   504                                  
   505                                  ;constants of stuff that seem hard to remember at times.
   506                                  
   507                                  TRUE  EQU 1
   508                                  FALSE EQU 0
   509                                  
   510                                  ENABLED  EQU 1
   511                                  DISABLED EQU 0
   512                                  
   513                                  BIT0  EQU 1
   514                                  BIT1  EQU 2
   515                                  BIT2  EQU 4
   516                                  BIT3  EQU 8
   517                                  BIT4  EQU 10h
   518                                  BIT5  EQU 20h
   519                                  BIT6  EQU 40h
   520                                  BIT7  EQU 80h
   521                                  BIT8  EQU 100h
   522                                  BIT9  EQU 200h
   523                                  BIT10 EQU 400h
   524                                  BIT11 EQU 800h
   525                                  BIT12 EQU 1000h
   526                                  BIT13 EQU 2000h
   527                                  BIT14 EQU 4000h
   528                                  BIT15 EQU 8000h
   529                                  BIT16 EQU 10000h
   530                                  BIT17 EQU 20000h
   531                                  BIT18 EQU 40000h
   532                                  BIT19 EQU 80000h
   533                                  BIT20 EQU 100000h
   534                                  BIT21 EQU 200000h
   535                                  BIT22 EQU 400000h
   536                                  BIT23 EQU 800000h
   537                                  BIT24 EQU 1000000h
   538                                  BIT25 EQU 2000000h
   539                                  BIT26 EQU 4000000h
   540                                  BIT27 EQU 8000000h
   541                                  BIT28 EQU 10000000h
   542                                  BIT29 EQU 20000000h
   543                                  BIT30 EQU 40000000h
   544                                  BIT31 EQU 80000000h
   545                                  NOT_BIT31 EQU 7FFFFFFFh ; 19/03/2017
   546                                  
   547                                  ;special characters
   548                                  NUL     EQU 0
   549                                  NULL    EQU 0
   550                                  BELL    EQU 07
   551                                  BS      EQU 08
   552                                  TAB     EQU 09
   553                                  LF      EQU 10
   554                                  CR      EQU 13
   555                                  ESCAPE  EQU 27           ;ESC is a reserved word....
   556                                  
   557                                  ; PCI equates
   558                                  ; PCI function address (PFA)
   559                                  ; bit 31 = 1
   560                                  ; bit 23:16 = bus number     (0-255)
   561                                  ; bit 15:11 = device number  (0-31)
   562                                  ; bit 10:8 = function number (0-7)
   563                                  ; bit 7:0 = register number  (0-255)
   564                                  
   565                                  IO_ADDR_MASK    EQU     0FFFEh	; mask off bit 0 for reading BARs
   566                                  PCI_INDEX_PORT  EQU     0CF8h
   567                                  PCI_DATA_PORT   EQU     0CFCh
   568                                  PCI32           EQU     BIT31	; bitflag to signal 32bit access
   569                                  PCI16           EQU     BIT30	; bitflag for 16bit access
   570                                  NOT_PCI32_PCI16	EQU	03FFFFFFFh ; NOT BIT31+BIT30 ; 19/03/2017
   571                                  
   572                                  PCI_FN0         EQU     0 << 8
   573                                  PCI_FN1         EQU     1 << 8
   574                                  PCI_FN2         EQU     2 << 8
   575                                  PCI_FN3         EQU     3 << 8
   576                                  PCI_FN4         EQU     4 << 8
   577                                  PCI_FN5         EQU     5 << 8
   578                                  PCI_FN6         EQU     6 << 8
   579                                  PCI_FN7         EQU     7 << 8
   580                                  
   581                                  PCI_CMD_REG	EQU	04h	; reg 04, command reg
   582                                   IO_ENA		EQU	BIT0	; i/o decode enable
   583                                   MEM_ENA	EQU	BIT1	; memory decode enable
   584                                   BM_ENA		EQU     BIT2	; bus master enable
   585                                  
   586                                  ; CODE
   587                                  
   588                                  ; PCI device register reader/writers.
   589                                  
   590                                  ; 19/03/2017
   591                                  ; 05/03/2017 (TRDOS 386, INT 34h, IOCTL interrupt modifications)
   592                                  ; NASM version: Erdogan Tan (29/11/2016)
   593                                  
   594                                  ;===============================================================
   595                                  ; 8/16/32bit PCI reader
   596                                  ;
   597                                  ; Entry: EAX=PCI Bus/Device/fn/register number
   598                                  ;           BIT30 set if 32 bit access requested
   599                                  ;           BIT29 set if 16 bit access requested
   600                                  ;           otherwise defaults to 8bit read
   601                                  ;
   602                                  ; Exit:  DL,DX,EDX register data depending on requested read size
   603                                  ;
   604                                  ; Note: this routine is meant to be called via pciRegRead8, pciRegread16,
   605                                  ;	or pciRegRead32, listed below.
   606                                  ;
   607                                  ; Note2: don't attempt to read 32bits of data from a non dword aligned reg
   608                                  ;	 number.  Likewise, don't do 16bit reads from non word aligned reg #
   609                                  ; 
   610                                  pciRegRead:
   611 000002BE 53                      	push	ebx
   612 000002BF 51                      	push	ecx
   613 000002C0 89C3                            mov     ebx, eax		; save eax, dh
   614 000002C2 88F1                            mov     cl, dh
   615                                  
   616 000002C4 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; clear out data size request
   617 000002C9 0D00000080                      or      eax, BIT31		; make a PCI access request
   618 000002CE 24FC                            and     al, ~3 ; NOT 3		; force index to be dword
   619                                  
   620 000002D0 66BAF80C                        mov     dx, PCI_INDEX_PORT
   621                                          ;out	dx, eax			; write PCI selector
   622 000002D4 53                      	push	ebx
   623 000002D5 89C3                    	mov	ebx, eax ; Data dword		
   624 000002D7 B405                    	mov	ah, 5	; outd (32 bit write)
   625 000002D9 CD34                    	int	34h	
   626 000002DB 5B                      	pop	ebx
   627                                  
   628 000002DC 66BAFC0C                        mov     dx, PCI_DATA_PORT
   629 000002E0 88D8                            mov     al, bl
   630 000002E2 2403                            and     al, 3			; figure out which port to
   631 000002E4 00C2                            add     dl, al			; read to
   632                                  
   633                                  	; 19/03/2017
   634 000002E6 B404                    	mov	ah, 4  ; ind
   635 000002E8 F7C300000080            	test    ebx, PCI32
   636 000002EE 750C                            jnz     short _pregr0
   637 000002F0 D0EC                    	shr	ah, 1  ; ah = 2 ; inw
   638 000002F2 F7C300000040            	test    ebx, PCI16
   639 000002F8 7502                            jnz     short _pregr0
   640 000002FA 28E4                    	sub	ah, ah ; ah = 0 ; inb
   641                                  _pregr0:	
   642 000002FC CD34                    	int	34h
   643                                  
   644 000002FE F7C300000080            	test    ebx, PCI32
   645 00000304 7404                            jz      short _pregr1
   646                                  
   647 00000306 89C2                            mov     edx, eax		; return 32bits of data
   648 00000308 EB0D                    	jmp	short _pregr2
   649                                  _pregr1:
   650 0000030A 6689C2                  	mov	dx, ax			; return 16bits of data
   651 0000030D F7C300000040                    test    ebx, PCI16
   652 00000313 7502                            jnz     short _pregr2
   653 00000315 88CE                            mov     dh, cl			; restore dh for 8 bit read
   654                                  _pregr2:
   655 00000317 89D8                            mov     eax, ebx		; restore eax
   656 00000319 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; clear out data size request
   657 0000031E 59                      	pop	ecx
   658 0000031F 5B                      	pop	ebx
   659 00000320 C3                      	retn
   660                                  
   661                                  pciRegRead8:
   662 00000321 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; set up 8 bit read size
   663 00000326 EB96                            jmp     short pciRegRead	; call generic PCI access
   664                                  
   665                                  pciRegRead16:
   666 00000328 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; set up 16 bit read size
   667 0000032D 0D00000040                      or      eax, PCI16		; call generic PCI access
   668 00000332 EB8A                            jmp     short pciRegRead
   669                                  
   670                                  pciRegRead32:
   671 00000334 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; set up 32 bit read size
   672 00000339 0D00000080                      or      eax, PCI32		; call generic PCI access
   673 0000033E E97BFFFFFF                      jmp     pciRegRead
   674                                  
   675                                  
   676                                  ; 23/03/2017
   677                                  ; 19/03/2017
   678                                  ;===============================================================
   679                                  ; 8/16/32bit PCI writer
   680                                  ;
   681                                  ; Entry: EAX=PCI Bus/Device/fn/register number
   682                                  ;           BIT31 set if 32 bit access requested
   683                                  ;           BIT30 set if 16 bit access requested
   684                                  ;           otherwise defaults to 8bit read
   685                                  ;        DL/DX/EDX data to write depending on size
   686                                  ;
   687                                  ;
   688                                  ; note: this routine is meant to be called via pciRegWrite8, pciRegWrite16,
   689                                  ; 	or pciRegWrite32 as detailed below.
   690                                  ;
   691                                  ; Note2: don't attempt to write 32bits of data from a non dword aligned reg
   692                                  ;	 number.  Likewise, don't do 16bit writes from non word aligned reg #
   693                                  ;
   694                                  pciRegWrite:
   695 00000343 53                      	push	ebx
   696 00000344 51                      	push	ecx
   697 00000345 89C3                            mov     ebx, eax		; save eax, edx
   698 00000347 89D1                            mov     ecx, edx
   699 00000349 25FFFFFF3F              	and     eax, NOT_PCI32_PCI16	; clear out data size request
   700 0000034E 0D00000080                      or      eax, BIT31		; make a PCI access request
   701 00000353 24FC                            and     al, ~3 ; NOT 3		; force index to be dword
   702                                  
   703 00000355 66BAF80C                        mov     dx, PCI_INDEX_PORT
   704                                          ;out	dx, eax			; write PCI selector
   705 00000359 53                      	push	ebx
   706 0000035A 89C3                    	mov	ebx, eax ; Data dword		
   707 0000035C B405                    	mov	ah, 5	; outd (32 bit write)
   708 0000035E CD34                    	int	34h	
   709 00000360 8B1C24                  	mov	ebx, [esp]
   710                                  
   711 00000363 66BAFC0C                        mov     dx, PCI_DATA_PORT
   712 00000367 88D8                            mov     al, bl
   713 00000369 2403                            and     al, 3			; figure out which port to
   714 0000036B 00C2                            add     dl, al			; write to
   715                                  
   716                                  	; 19/03/2017
   717 0000036D F7C3000000C0            	test    ebx, PCI32+PCI16
   718 00000373 7506                            jnz     short _pregw0
   719 00000375 B401                    	mov	ah, 1
   720 00000377 88C8                    	mov	al, cl 			; put data into al
   721                                  	;int	34h
   722 00000379 EB0C                    	jmp	short _pregw2
   723                                  _pregw0:
   724                                  	;mov	ah, 5  ; outd
   725 0000037B F7C300000080            	test    ebx, PCI32
   726 00000381 7502                            jnz     short _pregw1
   727 00000383 B403                    	mov	ah, 3
   728                                  _pregw1:
   729 00000385 89CB                    	mov	ebx, ecx		; put data into ebx 		
   730                                  _pregw2:
   731 00000387 CD34                    	int	34h
   732                                  	;
   733 00000389 5B                      	pop	ebx
   734 0000038A 89D8                            mov     eax, ebx		; restore eax
   735 0000038C 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; clear out data size request
   736 00000391 89CA                            mov     edx, ecx		; restore dx
   737 00000393 59                      	pop	ecx
   738 00000394 5B                      	pop	ebx
   739 00000395 C3                      	retn
   740                                  
   741                                  pciRegWrite8:
   742 00000396 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; set up 8 bit write size
   743 0000039B EBA6                            jmp	short pciRegWrite	; call generic PCI access
   744                                  
   745                                  pciRegWrite16:
   746 0000039D 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; set up 16 bit write size
   747 000003A2 0D00000040                      or      eax, PCI16		; call generic PCI access
   748 000003A7 EB9A                            jmp	short pciRegWrite
   749                                  
   750                                  pciRegWrite32:
   751 000003A9 25FFFFFF3F                      and     eax, NOT_PCI32_PCI16	; set up 32 bit write size
   752 000003AE 0D00000080                      or      eax, PCI32		; call generic PCI access
   753 000003B3 EB8E                            jmp	pciRegWrite
   754                                  
   755                                  ;===============================================================
   756                                  ; PCIFindDevice: scan through PCI space looking for a device+vendor ID
   757                                  ;
   758                                  ; Entry: EAX=Device+Vendor ID
   759                                  ;
   760                                  ;  Exit: EAX=PCI address if device found
   761                                  ;	 EDX=Device+Vendor ID
   762                                  ;        CY clear if found, set if not found. EAX invalid if CY set.
   763                                  ;
   764                                  ; [old stackless] Destroys: ebx, esi, edi, cl
   765                                  ;
   766                                  pciFindDevice:
   767                                  	;push	ecx
   768 000003B5 50                      	push	eax
   769                                  	;push	esi
   770                                  	;push	edi
   771                                  
   772 000003B6 89C6                            mov     esi, eax                ; save off vend+device ID
   773 000003B8 BF00FFFF7F                      mov     edi, (80000000h - 100h) ; start with bus 0, dev 0 func 0
   774                                  
   775                                  nextPCIdevice:
   776 000003BD 81C700010000                    add     edi, 100h
   777 000003C3 81FF00F8FF80                    cmp     edi, 80FFF800h		; scanned all devices?
   778 000003C9 F9                              stc
   779 000003CA 740C                            je      short PCIScanExit       ; not found
   780                                  
   781 000003CC 89F8                            mov     eax, edi                ; read PCI registers
   782 000003CE E861FFFFFF                      call    pciRegRead32
   783 000003D3 39F2                            cmp     edx, esi                ; found device?
   784 000003D5 75E6                            jne     short nextPCIdevice
   785 000003D7 F8                              clc
   786                                  
   787                                  PCIScanExit:
   788 000003D8 9C                      	pushf
   789 000003D9 B8FFFFFF7F              	mov	eax, NOT_BIT31 	; 19/03/2017
   790 000003DE 21F8                    	and	eax, edi	; return only bus/dev/fn #
   791 000003E0 9D                      	popf
   792                                  
   793                                  	;pop	edi
   794                                  	;pop	esi
   795 000003E1 5A                      	pop	edx
   796                                  	;pop	ecx
   797 000003E2 C3                      	retn
   798                                  
   799                                  ;=============================================================================
   800                                  ;               CODEC.ASM
   801                                  ;=============================================================================
   802                                  
   803                                  ; EQUATES
   804                                  
   805                                  ;Codec registers.
   806                                  ;
   807                                  ;Not all codecs are created equal. Refer to the spec for your specific codec.
   808                                  ;
   809                                  ;All registers are 16bits wide.  Access to codec registers over the AC97 link
   810                                  ;is defined by the OEM.  
   811                                  ;
   812                                  ;Secondary codec's are accessed by ORing in BIT7 of all register accesses.
   813                                  ;
   814                                  
   815                                  ; each codec/mixer register is 16bits
   816                                  
   817                                  CODEC_RESET_REG                 equ     00      ; reset codec
   818                                  CODEC_MASTER_VOL_REG            equ     02      ; master volume
   819                                  CODEC_HP_VOL_REG                equ     04      ; headphone volume
   820                                  CODEC_MASTER_MONO_VOL_REG       equ     06      ; master mono volume
   821                                  CODEC_MASTER_TONE_REG           equ     08      ; master tone (R+L)
   822                                  CODEC_PCBEEP_VOL_REG            equ     0ah     ; PC beep volume
   823                                  CODEC_PHONE_VOL_REG             equ     0bh     ; phone volume
   824                                  CODEC_MIC_VOL_REG               equ     0eh     ; MIC volume
   825                                  CODEC_LINE_IN_VOL_REG           equ     10h     ; line input volume
   826                                  CODEC_CD_VOL_REG                equ     12h     ; CD volume
   827                                  CODEC_VID_VOL_REG               equ     14h     ; video volume
   828                                  CODEC_AUX_VOL_REG               equ     16h     ; aux volume
   829                                  CODEC_PCM_OUT_REG               equ     18h     ; PCM output volume
   830                                  CODEC_RECORD_SELECT_REG         equ     1ah     ; record select input
   831                                  CODEC_RECORD_VOL_REG            equ     1ch     ; record volume
   832                                  CODEC_RECORD_MIC_VOL_REG        equ     1eh     ; record mic volume
   833                                  CODEC_GP_REG                    equ     20h     ; general purpose
   834                                  CODEC_3D_CONTROL_REG            equ     22h     ; 3D control
   835                                  ; 24h is reserved
   836                                  CODEC_POWER_CTRL_REG            equ     26h     ; powerdown control
   837                                  CODEC_EXT_AUDIO_REG             equ     28h     ; extended audio
   838                                  CODEC_EXT_AUDIO_CTRL_REG        equ     2ah     ; extended audio control
   839                                  CODEC_PCM_FRONT_DACRATE_REG     equ     2ch     ; PCM out sample rate
   840                                  CODEC_PCM_SURND_DACRATE_REG     equ     2eh     ; surround sound sample rate
   841                                  CODEC_PCM_LFE_DACRATE_REG       equ     30h     ; LFE sample rate
   842                                  CODEC_LR_ADCRATE_REG            equ     32h     ; PCM in sample rate
   843                                  CODEC_MIC_ADCRATE_REG           equ     34h     ; mic in sample rate
   844                                  
   845                                  ; registers 36-7a are reserved on the ICH
   846                                  
   847                                  CODEC_VENDORID1_REG             equ     7ch     ; codec vendor ID 1
   848                                  CODEC_VENDORID2_REG             equ     7eh     ; codec vendor ID 2
   849                                  
   850                                  ; Mixer registers 0 through 51h reside in the ICH and are not forwarded over
   851                                  ; the AC97 link to the codec, which I think is a little weird.  Looks like
   852                                  ; the ICH makes it so you don't need a fully functional codec to play audio?
   853                                  ;
   854                                  ; whenever 2 codecs are present in the system, use BIT7 to access the 2nd
   855                                  ; set of registers, ie 80h-feh
   856                                  
   857                                  PRIMARY_CODEC		equ     0       ; 0-7F for primary codec
   858                                  SECONDARY_CODEC		equ     BIT7    ; 80-8f registers for 2ndary
   859                                  
   860                                  SAMPLE_RATE_441khz	equ     44100   ; 44.1Khz (cd quality) rate
   861                                  
   862                                  ; each buffer descriptor BAR holds a pointer which has entries to the buffer
   863                                  ; contents of the .WAV file we're going to play.  Each entry is 8 bytes long
   864                                  ; (more on that later) and can contain 32 entries total, so each BAR is
   865                                  ; 256 bytes in length, thus:
   866                                  
   867                                  BDL_SIZE                equ     32*8    ; Buffer Descriptor List size
   868                                  INDEX_MASK              equ     31      ; indexes must be 0-31
   869                                  
   870                                  ;
   871                                  ; Buffer Descriptors List
   872                                  ; As stated earlier, each buffer descriptor list is a set of (up to) 32 
   873                                  ; descriptors, each 8 bytes in length.  Bytes 0-3 of a descriptor entry point
   874                                  ; to a chunk of memory to either play from or record to.  Bytes 4-7 of an
   875                                  ; entry describe various control things detailed below.
   876                                  ; 
   877                                  ; Buffer pointers must always be aligned on a Dword boundry.
   878                                  ;
   879                                  ;
   880                                  
   881                                  IOC                     equ     BIT31	; Fire an interrupt whenever this
   882                                                                          ; buffer is complete.
   883                                  
   884                                  BUP                     equ     BIT30	; Buffer Underrun Policy.
   885                                                                          ; if this buffer is the last buffer
   886                                                                          ; in a playback, fill the remaining
   887                                                                          ; samples with 0 (silence) or not.
   888                                                                          ; It's a good idea to set this to 1
   889                                                                          ; for the last buffer in playback,
   890                                                                          ; otherwise you're likely to get a lot
   891                                                                          ; of noise at the end of the sound.
   892                                  
   893                                  ;
   894                                  ; Bits 15:0 contain the length of the buffer, in number of samples, which
   895                                  ; are 16 bits each, coupled in left and right pairs, or 32bits each.
   896                                  ; Luckily for us, that's the same format as .wav files.
   897                                  ;
   898                                  ; A value of FFFF is 65536 samples.  Running at 44.1Khz, that's just about
   899                                  ; 1.5 seconds of sample time.  FFFF * 32bits is 1FFFFh bytes or 128k of data.
   900                                  ;
   901                                  ; A value of 0 in these bits means play no samples.
   902                                  ;
   903                                  
   904                                  ;VIA VT8233 (VT8235) AC97 Codec equates 
   905                                  ;(edited by Erdogan Tan, 7/11/2016)
   906                                  
   907                                  ; PCI stuff
   908                                  
   909                                  VIA_VID		equ 1106h	; VIA's PCI vendor ID
   910                                  VT8233_DID      equ 3059h	; VT8233 (VT8235) device ID
   911                                  		
   912                                  PCI_IO_BASE          equ 10h
   913                                  AC97_INT_LINE        equ 3Ch
   914                                  VIA_ACLINK_CTRL      equ 41h
   915                                  VIA_ACLINK_STAT      equ 40h
   916                                  VIA_ACLINK_C00_READY equ 01h ; primary codec ready
   917                                  	
   918                                  VIA_REG_AC97	     equ 80h ; dword
   919                                  
   920                                  VIA_ACLINK_CTRL_ENABLE	equ   80h ; 0: disable, 1: enable
   921                                  VIA_ACLINK_CTRL_RESET	equ   40h ; 0: assert, 1: de-assert
   922                                  VIA_ACLINK_CTRL_SYNC	equ   20h ; 0: release SYNC, 1: force SYNC hi
   923                                  VIA_ACLINK_CTRL_VRA	equ   08h ; 0: disable VRA, 1: enable VRA
   924                                  VIA_ACLINK_CTRL_PCM	equ   04h ; 0: disable PCM, 1: enable PCM
   928                                  VIA_ACLINK_CTRL_INIT	equ  (VIA_ACLINK_CTRL_ENABLE +                               VIA_ACLINK_CTRL_RESET +                               VIA_ACLINK_CTRL_PCM +                               VIA_ACLINK_CTRL_VRA)
   929                                  
   930                                  CODEC_AUX_VOL		equ   04h
   931                                  VIA_REG_AC97_BUSY	equ   01000000h ;(1<<24) 
   932                                  VIA_REG_AC97_CMD_SHIFT	equ   10h ; 16
   933                                  VIA_REG_AC97_PRIMARY_VALID equ 02000000h ;(1<<25)
   934                                  VIA_REG_AC97_READ	equ   00800000h ;(1<<23)
   935                                  VIA_REG_AC97_CODEC_ID_SHIFT   equ  1Eh ; 30
   936                                  VIA_REG_AC97_CODEC_ID_PRIMARY equ  0
   937                                  VIA_REG_AC97_DATA_SHIFT equ   0
   938                                  VIADEV_PLAYBACK         equ   0
   939                                  VIA_REG_OFFSET_STATUS   equ   0    ;; byte - channel status
   940                                  VIA_REG_OFFSET_CONTROL  equ   01h  ;; byte - channel control
   941                                  VIA_REG_CTRL_START	equ   80h  ;; WO
   942                                  VIA_REG_CTRL_TERMINATE  equ   40h  ;; WO
   943                                  VIA_REG_CTRL_PAUSE      equ   08h  ;; RW
   944                                  VIA_REG_CTRL_RESET      equ   01h  ;; RW - probably reset? undocumented
   945                                  VIA_REG_OFFSET_STOP_IDX equ   08h  ;; dword - stop index, channel type, sample rate
   946                                  VIA8233_REG_TYPE_16BIT  equ   200000h ;; RW
   947                                  VIA8233_REG_TYPE_STEREO equ   100000h ;; RW
   948                                  VIA_REG_OFFSET_CURR_INDEX equ 0Fh ;; byte - channel current index (for via8233 only)
   949                                  VIA_REG_OFFSET_TABLE_PTR equ  04h  ;; dword - channel table pointer
   950                                  VIA_REG_OFFSET_CURR_PTR equ   04h  ;; dword - channel current pointer
   951                                  VIA_REG_OFS_PLAYBACK_VOLUME_L equ  02h ;; byte
   952                                  VIA_REG_OFS_PLAYBACK_VOLUME_R equ  03h ;; byte
   953                                  VIA_REG_CTRL_AUTOSTART	equ   20h
   954                                  VIA_REG_CTRL_INT_EOL	equ   02h
   955                                  VIA_REG_CTRL_INT_FLAG	equ   01h
   958                                  VIA_REG_CTRL_INT	equ  (VIA_REG_CTRL_INT_FLAG +                               VIA_REG_CTRL_INT_EOL +                               VIA_REG_CTRL_AUTOSTART)
   959                                  ; 24/11/2016
   960                                  VIA_REG_STAT_STOPPED	equ   04h    ;; RWC
   961                                  VIA_REG_STAT_EOL	equ   02h    ;; RWC
   962                                  VIA_REG_STAT_FLAG	equ   01h    ;; RWC
   963                                  VIA_REG_STAT_ACTIVE	equ   80h    ;; RO
   964                                  ; 28/11/2016
   965                                  VIA_REG_STAT_LAST	equ   40h    ;; RO
   966                                  VIA_REG_STAT_TRIGGER_QUEUED equ 08h  ;; RO
   967                                  VIA_REF_CTRL_INT_STOP	equ   04h  ; Interrupt on Current Index = Stop Index
   968                                  		   ; and End of Block
   969                                  
   970                                  ; 14/03/2017
   971                                  VIA_REG_OFFSET_CURR_COUNT equ 0Ch ;; dword - channel current count, index
   972                                  
   973                                  ; CODE
   974                                  
   975                                  ; codec configuration code.  Not much here really.
   976                                  ; NASM version: Erdogan Tan (29/11/2016)
   977                                  
   978                                  ; enable codec, unmute stuff, set output rate to 44.1
   979                                  ; entry: ax = desired sample rate
   980                                  ;
   981                                  codecConfig:
   982                                  	; 24/06/2017
   983                                  	; 19/06/2017, 23/06/2017
   984                                  	; 14/11/2016, 15/11/2016
   985                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, 'setup_codec', codec.inc)
   986                                  
   987                                  	;mov	eax, 0202h
   988 000003E3 B804040000              	mov	eax, 0404h ; 23/06/2017
   989 000003E8 BA02000000              	mov	edx, CODEC_MASTER_VOL_REG ; 02h ; Line Out
   990 000003ED E85F010000              	call	codec_write
   991                                  	;jc	cconfig_error
   992                                  
   993 000003F2 B802020000              	mov     eax, 0202h
   994 000003F7 BA18000000              	mov	edx, CODEC_PCM_OUT_REG ; 18h ; Wave Output (Stereo)
   995 000003FC E850010000              	call	codec_write
   996                                  	;jc	cconfig_error
   997                                        
   998 00000401 B802020000              	mov	eax, 0202h
   999 00000406 BA04000000              	mov	edx, CODEC_AUX_VOL ; 04h ; CODEC_HP_VOL_REG ; HeadPhone
  1000 0000040B E841010000              	call	codec_write
  1001                                  	;jc	cconfig_error
  1002                                  
  1003 00000410 B808800000                      mov     eax, 8008h ; Mute
  1004 00000415 BA0C000000                      mov	edx, 0Ch  ; AC97_PHONE_VOL ; TAD Input (Mono)
  1005 0000041A E832010000              	call	codec_write
  1006                                  	;jc	short cconfig_error
  1007                                  
  1008 0000041F B808080000                      mov     eax, 0808h
  1009 00000424 BA10000000                      mov	edx, CODEC_LINE_IN_VOL_REG ; 10h ; Line Input (Stereo)	
  1010 00000429 E823010000              	call	codec_write
  1011                                  	;jc	short cconfig_error
  1012                                  
  1013 0000042E B808080000              	mov     eax, 0808h
  1014 00000433 BA12000000                      mov	edx, CODEC_CD_VOL_REG ; 12h ; CR Input (Stereo)
  1015 00000438 E814010000              	call	codec_write
  1016                                  	;jc	short cconfig_error
  1017                                  
  1018 0000043D B808080000              	mov     eax, 0808h
  1019 00000442 BA16000000                      mov	edx, CODEC_AUX_VOL_REG ; 16h ; Aux Input (Stereo)
  1020 00000447 E805010000              	call	codec_write
  1021                                  	;jc	short cconfig_error
  1022                                  
  1023                                  	; Extended Audio Status (2Ah)
  1024 0000044C B82A000000              	mov	eax, CODEC_EXT_AUDIO_CTRL_REG ; 2Ah 
  1025 00000451 E8CF000000              	call	codec_read
  1026 00000456 25FDFF0000                      and     eax, 0FFFFh - 2 ; clear DRA (BIT1)
  1027                                          ;or     eax, 1		; set VRA (BIT0)
  1028 0000045B 83C805                  	or	eax, 5  	; VRA (BIT0) & S/PDIF (BIT2) ; 14/11/2016
  1029 0000045E BA2A000000              	mov	edx, CODEC_EXT_AUDIO_CTRL_REG
  1030 00000463 E8E9000000              	call	codec_write
  1031                                  	;jc	short cconfig_error
  1032                                  
  1033                                  	; 24/06/2017
  1034                                  set_sample_rate:
  1035 00000468 0FB705[FA0A0000]                movzx	eax, word [sample_rate]
  1036 0000046F BA2C000000              	mov	edx, CODEC_PCM_FRONT_DACRATE_REG ; 2Ch ; PCM Front DAC Rate
  1037                                          ;call	codec_write
  1038                                  	;ren
  1039 00000474 E9D8000000              	jmp	codec_write
  1040                                  
  1041                                  ;cconfig_error:
  1042                                  ;	retn
  1043                                  
  1044                                  reset_codec:
  1045                                  	; 23/03/2017
  1046                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, vt823x.asm)
  1047 00000479 A1[E80A0000]            	mov	eax, [bus_dev_fn]
  1048 0000047E B041                     	mov	al, VIA_ACLINK_CTRL
  1049 00000480 B2E0                           	mov	dl, VIA_ACLINK_CTRL_ENABLE + VIA_ACLINK_CTRL_RESET + VIA_ACLINK_CTRL_SYNC
  1050 00000482 E80FFFFFFF              	call	pciRegWrite8
  1051                                  
  1052 00000487 E8E5020000              	call	delay_100ms 	; wait 100 ms
  1053                                  _rc_cold:
  1054 0000048C E80A000000                      call    cold_reset
  1055 00000491 7303                            jnc     short _reset_codec_ok
  1056                                  
  1057 00000493 31C0                            xor     eax, eax         ; timeout error
  1058 00000495 C3                              retn
  1059                                  
  1060                                  _reset_codec_ok:
  1061 00000496 31C0                            xor     eax, eax
  1062                                          ;mov	al, VIA_ACLINK_C00_READY ; 1
  1063 00000498 FEC0                            inc	al
  1064 0000049A C3                      	retn
  1065                                  
  1066                                  cold_reset:
  1067                                  	; 23/03/2017
  1068                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, vt823x.asm)
  1069                                  	;mov	eax, [bus_dev_fn]
  1070                                  	;mov	al, VIA_ACLINK_CTRL
  1071 0000049B 30D2                    	xor	dl, dl ; 0
  1072 0000049D E8F4FEFFFF              	call	pciRegWrite8
  1073                                  
  1074 000004A2 E8CA020000              	call	delay_100ms 	; wait 100 ms
  1075                                  
  1076                                  	;; ACLink on, deassert ACLink reset, VSR, SGD data out
  1077                                          ;; note - FM data out has trouble with non VRA codecs !!
  1078                                          
  1079                                  	;mov	eax, [bus_dev_fn]
  1080                                  	;mov	al, VIA_ACLINK_CTRL
  1081 000004A7 B2CC                    	mov	dl, VIA_ACLINK_CTRL_INIT
  1082 000004A9 E8E8FEFFFF              	call	pciRegWrite8
  1083                                  
  1084 000004AE B910000000              	mov	ecx, 16	; total 2s
  1085                                  
  1086                                  _crst_wait:
  1087                                  	;mov	eax, [bus_dev_fn]
  1088 000004B3 B040                    	mov	al, VIA_ACLINK_STAT
  1089 000004B5 E867FEFFFF              	call	pciRegRead8	
  1090                                  
  1091 000004BA F6C201                          test    dl, VIA_ACLINK_C00_READY
  1092 000004BD 750B                            jnz     short _crst_ok
  1093                                  
  1094 000004BF 51                      	push	ecx
  1095 000004C0 E8AC020000              	call	delay_100ms
  1096 000004C5 59                      	pop	ecx
  1097                                  
  1098 000004C6 49                              dec     ecx
  1099 000004C7 75EA                            jnz     short _crst_wait
  1100                                  
  1101                                  _crst_fail:
  1102 000004C9 F9                              stc
  1103                                  _crst_ok:
  1104 000004CA C3                      	retn
  1105                                  
  1106                                  codec_io_w16: ;w32
  1107 000004CB 668B15[F40A0000]                mov	dx, [ac97_io_base]
  1108 000004D2 6681C28000                      add     dx, VIA_REG_AC97
  1109                                  	;out	dx, eax
  1110                                  	; 05/03/2017
  1111 000004D7 53                      	push	ebx
  1112 000004D8 89C3                    	mov	ebx, eax
  1113 000004DA B405                    	mov	ah, 5 ; outd
  1114 000004DC CD34                    	int	34h
  1115 000004DE 5B                      	pop	ebx
  1116 000004DF C3                              retn
  1117                                  
  1118                                  codec_io_r16: ;r32
  1119 000004E0 668B15[F40A0000]                mov     dx, [ac97_io_base]
  1120 000004E7 6681C28000                      add     dx, VIA_REG_AC97
  1121                                          ;in	eax, dx
  1122                                  	; 05/03/2017
  1123 000004EC B404                    	mov	ah, 4 ; ind
  1124 000004EE CD34                    	int	34h
  1125 000004F0 C3                              retn
  1126                                  
  1127                                  ctrl_io_w8:
  1128 000004F1 660315[F40A0000]                add     dx, [ac97_io_base]
  1129                                          ;out	dx, al
  1130                                  	; 05/03/2017
  1131 000004F8 B401                    	mov	ah, 1 ; outb
  1132 000004FA CD34                    	int	34h
  1133 000004FC C3                              retn
  1134                                  
  1135                                  ctrl_io_r8:
  1136 000004FD 660315[F40A0000]                add     dx, [ac97_io_base]
  1137                                          ;in	al, dx
  1138                                  	; 05/03/2017
  1139 00000504 B400                    	mov	ah, 0 ; inb
  1140 00000506 CD34                    	int	34h
  1141 00000508 C3                              retn
  1142                                  
  1143                                  ctrl_io_w32:
  1144 00000509 660315[F40A0000]                add     dx, [ac97_io_base]
  1145                                          ;out	dx, eax
  1146                                  	; 05/03/2017
  1147 00000510 53                      	push	ebx
  1148 00000511 89C3                    	mov	ebx, eax
  1149 00000513 B405                    	mov	ah, 5 ; outd
  1150 00000515 CD34                    	int	34h
  1151 00000517 5B                      	pop	ebx
  1152 00000518 C3                              retn
  1153                                  
  1154                                  ctrl_io_r32:
  1155 00000519 660315[F40A0000]                add	dx, [ac97_io_base]
  1156                                  	;in	eax, dx
  1157                                  	; 05/03/2017
  1158 00000520 B404                    	mov	ah, 4 ; ind
  1159 00000522 CD34                    	int	34h
  1160 00000524 C3                              retn
  1161                                  
  1162                                  codec_read:
  1163                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, vt823x.asm)
  1164                                          ; Use only primary codec.
  1165                                          ; eax = register
  1166 00000525 C1E010                          shl     eax, VIA_REG_AC97_CMD_SHIFT
  1167 00000528 0D00008002                      or      eax, VIA_REG_AC97_PRIMARY_VALID + VIA_REG_AC97_READ
  1168                                  
  1169 0000052D E899FFFFFF              	call    codec_io_w16
  1170                                  
  1171                                        	; codec_valid
  1172 00000532 E831000000              	call	codec_check_ready
  1173 00000537 7301                            jnc	short _cr_ok
  1174                                  
  1175 00000539 C3                      	retn
  1176                                  
  1177                                  _cr_ok:
  1178                                  	; wait 25 ms
  1179 0000053A B950000000              	mov	ecx, 80
  1180                                  _cr_wloop:
  1181 0000053F E83A020000              	call	delay1_4ms
  1182 00000544 E2F9                    	loop	_cr_wloop
  1183                                  
  1184 00000546 E895FFFFFF                      call    codec_io_r16
  1185 0000054B 25FFFF0000                      and     eax, 0FFFFh
  1186 00000550 C3                              retn
  1187                                  
  1188                                  codec_write:
  1189                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, vt823x.asm)
  1190                                          ; Use only primary codec.
  1191                                          
  1192                                  	; eax = data (volume)
  1193                                  	; edx = register (mixer register)
  1194                                  	
  1195 00000551 C1E210                  	shl     edx, VIA_REG_AC97_CMD_SHIFT
  1196                                  
  1197 00000554 C1E000                          shl     eax, VIA_REG_AC97_DATA_SHIFT ; shl eax, 0
  1198 00000557 09C2                            or      edx, eax
  1199                                  
  1200 00000559 B800000000                      mov     eax, VIA_REG_AC97_CODEC_ID_PRIMARY
  1201 0000055E C1E01E                          shl     eax, VIA_REG_AC97_CODEC_ID_SHIFT
  1202 00000561 09D0                            or      eax, edx
  1203                                  
  1204 00000563 E863FFFFFF                      call    codec_io_w16
  1205                                          ;mov    [codec.regs+esi], ax
  1206                                  
  1207                                          ;call	codec_check_ready
  1208                                         	;retn
  1209                                  	;jmp	short _codec_check_ready	
  1210                                  
  1211                                  codec_check_ready:
  1212                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, vt823x.asm)
  1213                                  
  1214                                  _codec_check_ready:
  1215 00000568 B914000000              	mov	ecx, 20	; total 2s
  1216                                  _ccr_wait:
  1217 0000056D 51                      	push	ecx
  1218                                  
  1219 0000056E E86DFFFFFF                      call    codec_io_r16
  1220 00000573 A900000001                      test    eax, VIA_REG_AC97_BUSY
  1221 00000578 740B                            jz      short _ccr_ok
  1222                                  
  1223 0000057A E8F2010000              	call	delay_100ms
  1224                                  
  1225 0000057F 59                      	pop	ecx
  1226                                  
  1227 00000580 49                      	dec     ecx
  1228 00000581 75EA                            jnz     short _ccr_wait
  1229                                  
  1230 00000583 F9                              stc
  1231 00000584 C3                              retn
  1232                                  
  1233                                  _ccr_ok:
  1234 00000585 59                      	pop	ecx
  1235 00000586 25FFFF0000              	and     eax, 0FFFFh
  1236 0000058B C3                              retn
  1237                                  
  1238                                  channel_reset:
  1239                                  	; 24/06/2017
  1240                                  	; 29/05/2017
  1241                                  	; 23/03/2017
  1242                                  	; 14/11/2016 - Erdogan Tan
  1243                                  	; 12/11/2016 - Erdogan Tan (Ref: KolibriOS, vt823x.asm)
  1244 0000058C BA01000000                      mov	edx, VIA_REG_OFFSET_CONTROL
  1245                                          ;mov	eax, VIA_REG_CTRL_PAUSE + VIA_REG_CTRL_TERMINATE + VIA_REG_CTRL_RESET
  1246 00000591 B848000000                      mov	eax, VIA_REG_CTRL_PAUSE + VIA_REG_CTRL_TERMINATE ; 24/06/2017        
  1247 00000596 E856FFFFFF              	call    ctrl_io_w8
  1248                                  
  1249                                          ;mov	edx, VIA_REG_OFFSET_CONTROL
  1250                                          ;call   ctrl_io_r8
  1251                                  
  1252 0000059B B9A0000000              	mov	ecx, 160 ; 200 (50 ms)	
  1253                                  _ch_rst_wait:
  1254 000005A0 E8D9010000              	call	delay1_4ms
  1255 000005A5 49                      	dec	ecx
  1256 000005A6 75F8                    	jnz	short _ch_rst_wait     
  1257                                  
  1258                                          ; disable interrupts
  1259 000005A8 BA01000000                      mov	edx, VIA_REG_OFFSET_CONTROL
  1260 000005AD 31C0                            xor     eax, eax
  1261 000005AF E83DFFFFFF                      call    ctrl_io_w8
  1262                                  
  1263                                          ; clear interrupts
  1264 000005B4 BA00000000                      mov	edx, VIA_REG_OFFSET_STATUS
  1265 000005B9 B803000000              	mov	eax, 3
  1266 000005BE E82EFFFFFF                      call	ctrl_io_w8
  1267                                  
  1268                                  	;mov	edx, VIA_REG_OFFSET_CURR_PTR
  1269                                  	;xor	eax, eax
  1270                                  	;call	ctrl_io_w32
  1271                                  
  1272 000005C3 C3                              retn
  1273                                  
  1274                                  loadFromFile:
  1275                                  	; 17/03/2017
  1276                                  	; edi = buffer address
  1277                                  	; edx = buffer size
  1278                                  	; 10/03/2017
  1279                                          ;push	eax
  1280                                          ;push	ecx
  1281                                          ;push	edx
  1282                                  	;push	ebx
  1283 000005C4 F605[E00A0000]01                test    byte [eof_flag], ENDOFFILE	; have we already read the
  1284 000005CB F9                              stc			; last of the file?
  1285 000005CC 7531                            jnz     short endLFF
  1286                                  	;clc
  1287                                  	; load file into memory
  1288                                  	sys 	_read, [FileHandle], edi
  1288                              <1> 
  1288                              <1> 
  1288                              <1> 
  1288                              <1> 
  1288                              <1>  %if %0 >= 2
  1288 000005CE 8B1D[060A0000]      <1>  mov ebx, %2
  1288                              <1>  %if %0 >= 3
  1288 000005D4 89F9                <1>  mov ecx, %3
  1288                              <1>  %if %0 = 4
  1288                              <1>  mov edx, %4
  1288                              <1>  %endif
  1288                              <1>  %endif
  1288                              <1>  %endif
  1288 000005D6 B803000000          <1>  mov eax, %1
  1288                              <1> 
  1288 000005DB CD40                <1>  int 40h
  1289 000005DD 89D1                    	mov	ecx, edx
  1290 000005DF 720A                    	jc	short padfill ; error !
  1291 000005E1 21C0                    	and	eax, eax
  1292 000005E3 7406                    	jz	short padfill
  1293 000005E5 29C1                    	sub	ecx, eax
  1294 000005E7 7416                    	jz	short endLFF
  1295 000005E9 01C7                    	add	edi, eax  
  1296                                  padfill:
  1297 000005EB 803D[F90A0000]10        	cmp 	byte [bps], 16
  1298 000005F2 740C                    	je	short _7
  1299                                  	; Minimum Value = 0
  1300 000005F4 30C0                            xor     al, al
  1301 000005F6 F3AA                    	rep	stosb
  1302                                  _6:
  1303                                          ;clc			; don't exit with CY yet.
  1304 000005F8 800D[E00A0000]01                or	byte [eof_flag], ENDOFFILE	; end of file flag
  1305                                  endLFF:
  1306                                  	;pop	ebx
  1307                                  	;pop	edx
  1308                                          ;pop	ecx
  1309                                          ;pop	eax
  1310 000005FF C3                              retn
  1311                                  _7:
  1312                                  	; Minimum value = 8000h (-32768)
  1313 00000600 D1E9                    	shr	ecx, 1 
  1314 00000602 66B80080                	mov	ax, 8000h ; -32768
  1315 00000606 F366AB                  	rep	stosw
  1316 00000609 EBED                    	jmp	short _6
  1317                                  
  1318                                  ;=============================================================================
  1319                                  ;               VIA_WAV.ASM
  1320                                  ;=============================================================================
  1321                                  
  1322                                  ; DOS based .WAV player using AC'97 and codec interface.
  1323                                  ; ---------------------------------------------------------------
  1324                                  ; VIA VT8233 Modification & NASM version: Erdogan Tan (29/11/2016)
  1325                                  ; Last Update: 08/12/2016 (by Erdogan Tan)
  1326                                  
  1327                                  ; player internal variables and other equates.
  1328                                  BUFFERSIZE      equ     32768	; 32K half buffer size. ; 14/03/2017
  1329                                  ENDOFFILE       equ     BIT0	; flag for knowing end of file
  1330                                  
  1331                                  ;===========================================================================
  1332                                  ; entry: none.  File is already open and [filehandle] filled.
  1333                                  ; exit:  not until the song is finished or the user aborts.
  1334                                  ;
  1335                                  	; 17/03/2017
  1336                                  PlayWav:
  1337                                         ; load 32768 bytes into half buffer 1
  1338                                  
  1339 0000060B BF[00000100]            	mov     edi, DmaBuffer
  1340 00000610 BA00800000              	mov	edx, BUFFERSIZE
  1341 00000615 E8AAFFFFFF              	call	loadFromFile
  1342                                  	
  1343                                         ; load 32768 bytes into half buffer 2
  1344                                  
  1345 0000061A BF[00000100]            	mov	edi, DmaBuffer
  1346 0000061F BA00800000              	mov	edx, BUFFERSIZE
  1347 00000624 01D7                    	add	edi, edx
  1348 00000626 E899FFFFFF              	call	loadFromFile
  1349                                  
  1350                                  ; write last valid index to 31 to start with.
  1351                                  ; The Last Valid Index register tells the DMA engine when to stop playing.
  1352                                  ; 
  1353                                  ; As we progress through the song we change the last valid index to always be
  1354                                  ; something other than the index we're currently playing.  
  1355                                  ;
  1356                                          ;;mov   al, 1
  1357                                          ;mov	al, 31
  1358                                  	;call   setLastValidIndex
  1359                                  
  1360                                  ; create Buffer Descriptor List
  1361                                  ;
  1362                                  ; A buffer descriptor list is a list of pointers and control bits that the
  1363                                  ; DMA engine uses to know where to get the .wav data and how to play it.
  1364                                  ;
  1365                                  ; I set it up to use only 2 buffers of .wav data, and whenever 1 buffer is
  1366                                  ; playing, I refresh the other one with good data.
  1367                                  ;
  1368                                  ;
  1369                                  ; For the control bits, you can specify that the DMA engine fire an interrupt
  1370                                  ; after a buffer has been processed, but I poll the current index register
  1371                                  ; to know when it's safe to update the other buffer.
  1372                                  ;
  1373                                  ; I set the BUP bit, which tells the DMA engine to just play 0's (silence)
  1374                                  ; if it ever runs out of data to play.  Good for safety.
  1375                                  ;
  1376                                  	; 05/03/2017 (32 bit buffer addresses)
  1377                                  
  1378                                  	; 14/02/2017
  1379 0000062B BF[00100000]                    mov     edi, BdlBuffer		; get BDL address
  1380 00000630 66B91000                        mov     cx, 32 / 2		; make 32 entries in BDL
  1381                                  _0:
  1382                                  
  1383                                  ; set buffer descriptor 0 to start of data file in memory
  1384                                  
  1385 00000634 A1[6C0B0000]                    mov	eax, [DMA_phy_buff]	; Physical address of DMA buffer
  1386 00000639 AB                              stosd				; store dmabuffer1 address
  1387                                  
  1388 0000063A 89C2                    	mov	edx, eax ; 05/03/2017
  1389                                  
  1390                                  ;
  1391                                  ; set length to 32k samples.  1 sample is 16bits or 2bytes.
  1392                                  ; Set control (bits 31:16) to BUP, bits 15:0=number of samples.
  1393                                  ; 
  1394                                  
  1395                                  ; VIA VT8235.PDF: (Page 110) (Erdogan Tan, 29/11/2016)
  1396                                  	;
  1397                                  	; 	Audio SGD Table Format
  1398                                  	;	-------------------------------
  1399                                  	;	63   62    61-56    55-32  31-0
  1400                                  	;	--   --   --------  -----  ----
  1401                                  	;	EOL FLAG -reserved- Base   Base
  1402                                  	;		    	    Count  Address
  1403                                  	;		            [23:0] [31:0]
  1404                                  	;	EOL: End Of Link. 
  1405                                  	;	     1 indicates this block is the last of the link.
  1406                                  	;	     If the channel Interrupt on EOL bit is set, then
  1407                                  	;	     an interrupt is generated at the end of the transfer.
  1408                                  	;
  1409                                  	;	FLAG: Block Flag. If set, transfer pauses at the end of this
  1410                                  	;	      block. If the channel Interrupt on FLAG bit is set,
  1411                                  	;	      then an interrupt is generated at the end of this block.
  1412                                  
  1413                                  	FLAG	EQU BIT30
  1414                                  	EOL	EQU BIT31
  1415                                  
  1416                                  	; 08/12/2016 - Erdogan Tan
  1417 0000063C B800800000              	mov	eax, BUFFERSIZE
  1418 00000641 01C2                    	add	edx, eax ; 05/03/2017
  1419 00000643 0D00000040              	or	eax, FLAG
  1420                                  	;or	eax, EOL
  1421 00000648 AB                      	stosd
  1422                                  
  1423                                  ; 2nd buffer:
  1424                                  
  1425 00000649 89D0                            mov	eax, edx ; Physical address of the 2nd half of DMA buffer	
  1426 0000064B AB                      	stosd		 ; store dmabuffer2 address
  1427                                  
  1428                                  ; set length to 64k (32k of two 16 bit samples)
  1429                                  ; Set control (bits 31:16) to BUP, bits 15:0=number of samples
  1430                                  ; 
  1431                                  	; 08/12/2016 - Erdogan Tan
  1432 0000064C B800800000              	mov	eax, BUFFERSIZE
  1433 00000651 0D00000080              	or	eax, EOL
  1434                                  	;or	eax, FLAG
  1435 00000656 AB                      	stosd
  1436                                  
  1437 00000657 E2DB                            loop    _0
  1438                                  
  1439                                  ;
  1440                                  ; tell the DMA engine where to find our list of Buffer Descriptors.
  1441                                  ; this 32bit value is a flat mode memory offset (ie no segment:offset)
  1442                                  ;
  1443                                  ; write buffer descriptor list address
  1444                                  ;
  1445 00000659 A1[680B0000]                    mov	eax, [BDL_phy_buff] ; Physical address of the BDL
  1446                                  	
  1447                                  	; 12/11/2016 - Erdogan Tan 
  1448                                  	; (Ref: KolibriOS, vt823x.asm, 'create_primary_buff')
  1449 0000065E BA04000000              	mov     edx, VIADEV_PLAYBACK + VIA_REG_OFFSET_TABLE_PTR
  1450 00000663 E8A1FEFFFF                      call    ctrl_io_w32
  1451                                  
  1452                                  	;call	codec_check_ready
  1453                                  
  1454 00000668 66BA0200                  	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFS_PLAYBACK_VOLUME_L
  1455 0000066C B802000000                      mov     eax, 2   ;31
  1456 00000671 E87BFEFFFF                      call    ctrl_io_w8
  1457                                  
  1458                                  	;call	codec_check_ready
  1459                                  
  1460 00000676 66BA0300                        mov     dx, VIADEV_PLAYBACK + VIA_REG_OFS_PLAYBACK_VOLUME_R
  1461 0000067A 66B80200                        mov     ax, 2   ;31
  1462 0000067E E86EFEFFFF                      call    ctrl_io_w8
  1463                                  
  1464                                  	;call	codec_check_ready
  1465                                  ;
  1466                                  ;
  1467                                  ; All set.  Let's play some music.
  1468                                  ;
  1469                                  ;
  1470                                         	;mov    dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_STOP_IDX
  1471                                          ;mov    ax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000
  1472                                          ;call   ctrl_io_w32
  1473                                  
  1474                                  	;call	codec_check_ready
  1475                                  
  1476                                  	; 08/12/2016
  1477                                  	; 07/10/2016
  1478                                          ;mov	al, 1
  1479 00000683 B01F                            mov	al, 31
  1480 00000685 E8A4000000              	call    setLastValidIndex
  1481                                  
  1482                                  	;mov	byte [audio_play_cmd], 1 ; 30/11/2016
  1483                                  
  1484                                  	; 23/06/2017
  1485                                          ;mov	al, VIA_REG_CTRL_INT ; 14/03/2017
  1486                                         	;or	al, VIA_REG_CTRL_START
  1487                                          ; 24/06/2017
  1488 0000068A 66B8A000                	mov	ax, VIA_REG_CTRL_AUTOSTART + VIA_REG_CTRL_START
  1489                                  	; 28/11/2016
  1490                                  	;mov	ax, VIA_REG_CTRL_AUTOSTART + VIA_REG_CTRL_START + VIA_REG_CTRL_INT_FLAG
  1491 0000068E 66BA0100                	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_CONTROL
  1492 00000692 E85AFEFFFF                      call    ctrl_io_w8
  1493                                  
  1494 00000697 E8CCFEFFFF              	call	codec_check_ready
  1495                                  
  1496                                  ; while DMA engine is running, examine current index and wait until it hits 1
  1497                                  ; as soon as it's 1, we need to refresh the data in wavbuffer1 with another
  1498                                  ; 64k.  Likewise when it's playing buffer 2, refresh buffer 1 and repeat.
  1499                                     
  1500                                  	; 21/04/2017
  1501                                  	; 17/03/2017
  1502                                  	; 05/03/2017 (TRDOS 386)
  1503                                  	; 14/02/2017
  1504                                  	; 13/02/2017
  1505                                  	; 08/12/2016
  1506                                  	; 28/11/2016
  1507                                  p_loop:
  1508 0000069C B401                    	mov     ah, 1		; any key pressed?
  1509 0000069E CD32                    	int     32h		; no, Loop.
  1510 000006A0 7409                    	jz	short q_loop
  1511                                  
  1512 000006A2 B400                    	mov     ah, 0		; flush key buffer...
  1513 000006A4 CD32                    	int     32h
  1514                                  p_return:
  1515                                  	;mov	byte [audio_play_cmd], 0	; 13/02/2017
  1516                                  	;retn
  1517                                  
  1518                                  	; 23/06/2017
  1519                                  _exit_:
  1520                                  	; 24/06/2017
  1521                                  	; finished with song, stop everything
  1522                                  	;mov	al, VIA_REG_CTRL_INT
  1523                                  	;or	al, VIA_REG_CTRL_TERMINATE
  1524                                  	;mov	dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_CONTROL
  1525                                  	;call	ctrl_io_w8
  1526                                  
  1527 000006A6 E9E1FEFFFF              	jmp	channel_reset
  1528                                  
  1529                                  q_loop:
  1530                                  	;cmp	byte [srb], 0
  1531                                  	;jna	short p_loop
  1532                                  
  1533                                  	;mov	byte [srb], 0
  1534                                  
  1535                                  	; 23/06/2017
  1536 000006AB E827000000              	call	tune_loop
  1537                                  
  1538 000006B0 803D[E40A0000]00        	cmp	byte [audio_flag_eol], 0
  1539 000006B7 76E3                    	jna	short p_loop
  1540                                  
  1541 000006B9 BF[00000100]            	mov     edi, DmaBuffer
  1542 000006BE BA00800000              	mov	edx, BUFFERSIZE
  1543                                  
  1544 000006C3 F605[E40A0000]01        	test	byte [audio_flag_eol], VIA_REG_STAT_FLAG 
  1545 000006CA 7502                    	jnz	short r_loop ; Fill Half Buffer 1
  1546                                  
  1547                                  	; Fill Half Buffer 2
  1548 000006CC 01D7                    	add	edi, edx	
  1549                                  r_loop:
  1550 000006CE E8F1FEFFFF              	call    loadFromFile
  1551 000006D3 72D1                    	jc	short p_return
  1552 000006D5 EBC5                    	jmp	short p_loop
  1553                                  
  1554                                  ;tuneLoop:
  1555                                  ;	; 19/06/2017
  1556                                  ;	; 21/04/2017
  1557                                  ;	; 14/03/2017, 17/03/2017, 24/03/2017
  1558                                  ;	; 05/03/2017 (TRDOS 386)
  1559                                  ;	; 08/12/2016
  1560                                  ;	; 28/11/2016 - Erdogan Tan
  1561                                  ;	
  1562                                  ;	cmp	byte [audio_play_cmd], 1
  1563                                  ;	jb	short _exit_
  1564                                  ;
  1565                                  ;	mov	ah, 4Eh
  1566                                  ;	mov	al, '1' ; Half Buffer 1 has been played
  1567                                  ;
  1568                                  ;	test	byte [audio_flag], 1  ; Current flag value
  1569                                  ;	jz	short _tlp1 ; EOL
  1570                                  ;	inc	al  ; Half Buffer 2 as been played
  1571                                  ;_tlp1: 
  1572                                  ;	mov 	[0B8000h], ax ; Display buffer number
  1573                                  ;	retn
  1574                                  ;_exit_:
  1575                                  ;        ; finished with song, stop everything
  1576                                  ;	mov     al, VIA_REG_CTRL_INT
  1577                                  ;       or      al, VIA_REG_CTRL_TERMINATE
  1578                                  ;	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_CONTROL
  1579                                  ;       call    ctrl_io_w8
  1580                                  ;
  1581                                  ;       jmp	channel_reset
  1582                                  
  1583                                  tune_loop:
  1584                                  	; 23/06/2017		
  1585                                  	; 19/06/2017
  1586                                  	; 21/04/2017
  1587                                  	; 14/03/2017, 24/03/2017
  1588                                  	; 06/03/2017 (Signal Response Byte Check)
  1589                                  	; 05/03/2017 (Modified for TRDOS 386 IRQ callback method)
  1590                                  	
  1591 000006D7 C605[E40A0000]00        	mov	byte [audio_flag_eol], 0
  1592                                  
  1593 000006DE 66BA0000                	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_STATUS
  1594 000006E2 E816FEFFFF              	call    ctrl_io_r8
  1595                                  
  1596 000006E7 A880                    	test    al, VIA_REG_STAT_ACTIVE
  1597 000006E9 7442                    	jz      short tlp2
  1598                                  
  1599 000006EB 2407                    	and     al, VIA_REG_STAT_EOL + VIA_REG_STAT_FLAG + VIA_REG_STAT_STOPPED
  1600 000006ED A2[E40A0000]            	mov	[audio_flag_eol], al
  1601 000006F2 7439                    	jz	short tlp2
  1602                                  	;
  1603                                  	;mov	al, [audio_flag_eol]   ;; ack ;;
  1604 000006F4 66BA0000                	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_STATUS
  1605 000006F8 E8F4FDFFFF              	call    ctrl_io_w8
  1606                                  
  1607 000006FD C605[E50A0000]31        	mov	byte [audio_flag], '1'
  1608                                  	
  1609 00000704 F605[E40A0000]01        	test	byte [audio_flag_eol], VIA_REG_STAT_FLAG 
  1610 0000070B 7413                    	jz	short tlp1
  1611                                  	
  1612 0000070D FE05[E50A0000]          	inc	byte [audio_flag] ; '2'	
  1613                                  	; 
  1614                                  	;mov	al, VIA_REG_CTRL_INT
  1615                                  	;or	al, VIA_REG_CTRL_START
  1616                                          ; 24/06/2017
  1617 00000713 66B8A000                	mov	ax, VIA_REG_CTRL_AUTOSTART + VIA_REG_CTRL_START
  1618                                  	;
  1619 00000717 66BA0100                	mov     dx, VIADEV_PLAYBACK + VIA_REG_OFFSET_CONTROL
  1620 0000071B E8D1FDFFFF              	call    ctrl_io_w8
  1621                                  tlp1:
  1622 00000720 A0[E50A0000]            	mov 	al, [audio_flag]
  1623 00000725 B44E                    	mov	ah, 4Eh
  1624 00000727 66A300800B00            	mov 	[0B8000h], ax ; Display current buffer number
  1625                                  tlp2:	
  1626 0000072D C3                      	retn
  1627                                  
  1628                                  ;input AL = index # to stop on
  1629                                  setLastValidIndex:
  1630                                  	; 05/03/2017 (TRDOS 386)
  1631                                  	; 19/11/2016
  1632                                  	; 14/11/2016 - Erdogan Tan (Ref: VIA VT8235.PDF, Page 110)
  1633                                  	; 12/11/2016 - Erdogan Tan
  1634                                  	; (Ref: KolibriOS, vt823x.asm, 'create_primary_buff')
  1635                                  	;push	edx
  1636 0000072E 50                      	push	eax
  1637                                  	;push	ecx
  1638 0000072F 0FB705[FA0A0000]        	movzx	eax, word [sample_rate] ; Hertz
  1639 00000736 BA00001000              	mov	edx, 100000h ; 2^20 = 1048576
  1640 0000073B F7E2                    	mul	edx
  1641 0000073D B980BB0000              	mov	ecx, 48000	
  1642 00000742 F7F1                    	div	ecx
  1643                                  	;and	eax, 0FFFFFh
  1644                                  	;pop	ecx
  1645 00000744 5A                      	pop	edx 
  1646 00000745 C1E218                  	shl	edx, 24  ; STOP Index Setting: Bit 24 to 31
  1647 00000748 09D0                    	or	eax, edx
  1648                                  	; 19/11/2016
  1649 0000074A 803D[F90A0000]10        	cmp	byte [bps], 16
  1650 00000751 7505                    	jne	short sLVI_1
  1651 00000753 0D00002000              	or	eax, VIA8233_REG_TYPE_16BIT
  1652                                  sLVI_1:
  1653 00000758 803D[F80A0000]02        	cmp	byte [stmo], 2
  1654 0000075F 7505                    	jne	short sLVI_2
  1655 00000761 0D00001000              	or	eax, VIA8233_REG_TYPE_STEREO
  1656                                  sLVI_2:
  1657 00000766 BA08000000              	mov     edx, VIADEV_PLAYBACK + VIA_REG_OFFSET_STOP_IDX
  1658 0000076B E899FDFFFF                      call    ctrl_io_w32
  1659                                  	;call	codec_check_ready
  1660                                  	;pop	edx
  1661 00000770 C3                      	retn
  1662                                  
  1663                                  delay_100ms:
  1664                                  	; wait 100 ms
  1665                                  	;mov	ecx, 400  ; 400*0.25ms  ; 29/05/2017
  1666 00000771 B964000000              	mov	ecx, 100  ; 23/06/2017
  1667                                  _delay_x_ms:
  1668 00000776 E803000000              	call	delay1_4ms
  1669 0000077B E2F9                            loop	_delay_x_ms
  1670 0000077D C3                      	retn
  1671                                  
  1672                                  ;       delay1_4ms - Delay for 1/4 millisecond.
  1673                                  ;	    1mS = 1000us
  1674                                  ;       Entry:
  1675                                  ;         None
  1676                                  ;       Exit:
  1677                                  ;	  None
  1678                                  ;
  1679                                  ;       Modified:
  1680                                  ;         None
  1681                                  ;
  1682                                  PORTB		EQU	061h
  1683                                  REFRESH_STATUS	EQU	010h	; Refresh signal status
  1684                                  
  1685                                  	; 29/05/2017
  1686                                  	; 05/03/2017 (TRDOS 386)
  1687                                  delay1_4ms:
  1688 0000077E 50                              push    eax 
  1689 0000077F 51                              push    ecx
  1690                                          ;mov	cl, 16		; close enough.
  1691 00000780 B10C                    	mov	cl, 12 ; + INT 34h delay	
  1692                                  
  1693                                  	;in	al, PORTB
  1694                                  	
  1695 00000782 66BA6100                	mov	dx, PORTB
  1696 00000786 28E4                    	sub	ah, ah ; 0 ; inb
  1697 00000788 CD34                    	int	34h
  1698                                  	
  1699 0000078A 2410                    	and	al, REFRESH_STATUS
  1700 0000078C 88C5                    	mov	ch, al		; Start toggle state
  1701                                  _d4ms1:	
  1702                                  	;in	al, PORTB	; Read system control port
  1703                                  	
  1704                                  	;mov	ah, 0 ; inb
  1705                                  	;mov	dx, PORTB
  1706 0000078E CD34                    	int	34h
  1707                                  	
  1708 00000790 2410                    	and	al, REFRESH_STATUS ; Refresh toggles 15.085 microseconds
  1709 00000792 38C5                    	cmp	ch, al
  1710 00000794 74F8                    	je	short _d4ms1	; Wait for state change
  1711                                  
  1712 00000796 88C5                    	mov	ch, al		; Update with new state
  1713 00000798 FEC9                    	dec	cl
  1714 0000079A 75F2                    	jnz	short _d4ms1
  1715                                  
  1716 0000079C 59                              pop     ecx
  1717 0000079D 58                              pop     eax
  1718 0000079E C3                              retn
  1719                                  
  1720                                  	; 05/03/2017 (TRDOS 386)
  1721                                  	; 13/11/2016 - Erdogan Tan
  1722                                  write_ac97_dev_info:
  1723                                  	; BUS/DEV/FN
  1724                                  	;	00000000BBBBBBBBDDDDDFFF00000000
  1725                                  	; DEV/VENDOR
  1726                                  	;	DDDDDDDDDDDDDDDDVVVVVVVVVVVVVVVV
  1727                                  
  1728 0000079F 8B35[EC0A0000]          	mov	esi, [dev_vendor]
  1729 000007A5 6689F0                  	mov	ax, si
  1730 000007A8 0FB6D8                  	movzx	ebx, al
  1731 000007AB 88DA                    	mov	dl, bl
  1732 000007AD 80E30F                  	and	bl, 0Fh
  1733 000007B0 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1734 000007B6 A2[4D0A0000]            	mov	[msgVendorId+3], al
  1735 000007BB 88D3                    	mov	bl, dl
  1736 000007BD C0EB04                  	shr	bl, 4
  1737 000007C0 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1738 000007C6 A2[4C0A0000]            	mov	[msgVendorId+2], al
  1739 000007CB 88E3                    	mov	bl, ah
  1740 000007CD 88DA                    	mov	dl, bl
  1741 000007CF 80E30F                  	and	bl, 0Fh
  1742 000007D2 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1743 000007D8 A2[4B0A0000]            	mov	[msgVendorId+1], al
  1744 000007DD 88D3                    	mov	bl, dl
  1745 000007DF C0EB04                  	shr	bl, 4
  1746 000007E2 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1747 000007E8 A2[4A0A0000]            	mov	[msgVendorId], al
  1748 000007ED C1EE10                  	shr	esi, 16
  1749 000007F0 6689F0                  	mov	ax, si
  1750 000007F3 88C3                    	mov	bl, al
  1751 000007F5 88DA                    	mov	dl, bl
  1752 000007F7 80E30F                  	and	bl, 0Fh
  1753 000007FA 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1754 00000800 A2[5E0A0000]            	mov	[msgDevId+3], al
  1755 00000805 88D3                    	mov	bl, dl
  1756 00000807 C0EB04                  	shr	bl, 4
  1757 0000080A 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1758 00000810 A2[5D0A0000]            	mov	[msgDevId+2], al
  1759 00000815 88E3                    	mov	bl, ah
  1760 00000817 88DA                    	mov	dl, bl
  1761 00000819 80E30F                  	and	bl, 0Fh
  1762 0000081C 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1763 00000822 A2[5C0A0000]            	mov	[msgDevId+1], al
  1764 00000827 88D3                    	mov	bl, dl
  1765 00000829 C0EB04                  	shr	bl, 4
  1766 0000082C 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1767 00000832 A2[5B0A0000]            	mov	[msgDevId], al
  1768                                  
  1769 00000837 8B35[E80A0000]          	mov	esi, [bus_dev_fn]
  1770 0000083D C1EE08                  	shr	esi, 8
  1771 00000840 6689F0                  	mov	ax, si
  1772 00000843 88C3                    	mov	bl, al
  1773 00000845 88DA                    	mov	dl, bl
  1774 00000847 80E307                  	and	bl, 7 ; bit 0,1,2
  1775 0000084A 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1776 00000850 A2[820A0000]            	mov	[msgFncNo+1], al
  1777 00000855 88D3                    	mov	bl, dl
  1778 00000857 C0EB03                  	shr	bl, 3
  1779 0000085A 88DA                    	mov	dl, bl
  1780 0000085C 80E30F                  	and	bl, 0Fh
  1781 0000085F 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1782 00000865 A2[740A0000]            	mov	[msgDevNo+1], al
  1783 0000086A 88D3                    	mov	bl, dl
  1784 0000086C C0EB04                  	shr	bl, 4
  1785 0000086F 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1786 00000875 A2[730A0000]            	mov	[msgDevNo], al
  1787 0000087A 88E3                    	mov	bl, ah
  1788 0000087C 88DA                    	mov	dl, bl
  1789 0000087E 80E30F                  	and	bl, 0Fh
  1790 00000881 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1791 00000887 A2[680A0000]            	mov	[msgBusNo+1], al
  1792 0000088C 88D3                    	mov	bl, dl
  1793 0000088E C0EB04                  	shr	bl, 4
  1794 00000891 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1795 00000897 A2[670A0000]            	mov	[msgBusNo], al
  1796                                  
  1797 0000089C 66A1[F40A0000]          	mov	ax, [ac97_io_base]
  1798 000008A2 88C3                    	mov	bl, al
  1799 000008A4 88DA                    	mov	dl, bl
  1800 000008A6 80E30F                  	and	bl, 0Fh
  1801 000008A9 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1802 000008AF A2[9B0A0000]            	mov	[msgIOBaseAddr+3], al
  1803 000008B4 88D3                    	mov	bl, dl
  1804 000008B6 C0EB04                  	shr	bl, 4
  1805 000008B9 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1806 000008BF A2[9A0A0000]            	mov	[msgIOBaseAddr+2], al
  1807 000008C4 88E3                    	mov	bl, ah
  1808 000008C6 88DA                    	mov	dl, bl
  1809 000008C8 80E30F                  	and	bl, 0Fh
  1810 000008CB 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1811 000008D1 A2[990A0000]            	mov	[msgIOBaseAddr+1], al
  1812 000008D6 88D3                    	mov	bl, dl
  1813 000008D8 C0EB04                  	shr	bl, 4
  1814 000008DB 8A83[0A0A0000]          	mov	al, [ebx+hex_chars]
  1815 000008E1 A2[980A0000]            	mov	[msgIOBaseAddr], al
  1816                                  
  1817                                  	; 24/11/2016
  1818 000008E6 30E4                    	xor	ah, ah
  1819 000008E8 A0[F60A0000]            	mov	al, [ac97_int_ln_reg]
  1820 000008ED B10A                    	mov	cl, 10
  1821 000008EF F6F1                    	div	cl
  1822 000008F1 660105[A30A0000]        	add	[msgIRQ], ax
  1823 000008F8 20C0                    	and	al, al
  1824 000008FA 750D                    	jnz	short _pmi
  1825 000008FC A0[A40A0000]            	mov	al, [msgIRQ+1]
  1826 00000901 B420                    	mov	ah, ' '
  1827 00000903 66A3[A30A0000]          	mov	[msgIRQ], ax
  1828                                  _pmi:
  1829                                  	; EBX = Message address
  1830                                  	; ECX = Max. message length (or stop on ZERO character)
  1831                                  	;	(1 to 255)
  1832                                  	; DL  = Message color (07h = light gray, 0Fh = white) 
  1833                                       	sys 	_msg, msgAC97Info, 255, 07h
  1833                              <1> 
  1833                              <1> 
  1833                              <1> 
  1833                              <1> 
  1833                              <1>  %if %0 >= 2
  1833 00000909 BB[1B0A0000]        <1>  mov ebx, %2
  1833                              <1>  %if %0 >= 3
  1833 0000090E B9FF000000          <1>  mov ecx, %3
  1833                              <1>  %if %0 = 4
  1833 00000913 BA07000000          <1>  mov edx, %4
  1833                              <1>  %endif
  1833                              <1>  %endif
  1833                              <1>  %endif
  1833 00000918 B823000000          <1>  mov eax, %1
  1833                              <1> 
  1833 0000091D CD40                <1>  int 40h
  1834 0000091F C3                              retn
  1835                                  
  1836                                  ;=============================================================================
  1837                                  ;               preinitialized data
  1838                                  ;=============================================================================
  1839                                  
  1840                                  noDevMsg:
  1841 00000920 4572726F723A20556E-     	db "Error: Unable to find VIA VT8233 based audio device!",CR,LF,0
  1841 00000929 61626C6520746F2066-
  1841 00000932 696E64205649412056-
  1841 0000093B 543832333320626173-
  1841 00000944 656420617564696F20-
  1841 0000094D 646576696365210D0A-
  1841 00000956 00                 
  1842                                  
  1843                                  CodecErrMsg:
  1844 00000957 436F64656320457272-     	db	"Codec Error !", CR,LF,0
  1844 00000960 6F7220210D0A00     
  1845                                  
  1846                                  msg_usage:
  1847 00000967 75736167653A207761-     	db	'usage: wavplay filename.wav',10,13,0
  1847 00000970 76706C61792066696C-
  1847 00000979 656E616D652E776176-
  1847 00000982 0A0D00             
  1848                                  Credits:
  1849 00000985 54696E792057415620-     	db	'Tiny WAV Player for TRDOS 386 by Erdogan Tan. '
  1849 0000098E 506C6179657220666F-
  1849 00000997 72205452444F532033-
  1849 000009A0 383620627920457264-
  1849 000009A9 6F67616E2054616E2E-
  1849 000009B2 20                 
  1850 000009B3 4A756E652032303137-     	db	'June 2017.',10,13,0
  1850 000009BC 2E0A0D00           
  1851 000009C0 32342F30362F323031-     	db	'24/06/2017', 10,13,0
  1851 000009C9 370A0D00           
  1852                                  noFileErrMsg:
  1853 000009CD 4572726F723A206669-     	db	'Error: file not found.',10,13,0
  1853 000009D6 6C65206E6F7420666F-
  1853 000009DF 756E642E0A0D00     
  1854                                  
  1855                                  trdos386_err_msg:
  1856 000009E6 5452444F5320333836-     	db	'TRDOS 386 System call error !',10,13,0
  1856 000009EF 2053797374656D2063-
  1856 000009F8 616C6C206572726F72-
  1856 00000A01 20210A0D00         
  1857                                  
  1858                                  FileHandle:	
  1859 00000A06 FFFFFFFF                	dd	-1
  1860                                  
  1861                                  ; 13/11/2016
  1862 00000A0A 303132333435363738-     hex_chars:	db "0123456789ABCDEF", 0
  1862 00000A13 3941424344454600   
  1863 00000A1B 414339372041756469-     msgAC97Info:	db "AC97 Audio Controller & Codec Info", 0Dh, 0Ah 
  1863 00000A24 6F20436F6E74726F6C-
  1863 00000A2D 6C6572202620436F64-
  1863 00000A36 656320496E666F0D0A 
  1864 00000A3F 56656E646F72204944-     		db "Vendor ID: "
  1864 00000A48 3A20               
  1865 00000A4A 303030306820446576-     msgVendorId:	db "0000h Device ID: "
  1865 00000A53 6963652049443A20   
  1866 00000A5B 30303030680D0A          msgDevId:	db "0000h", 0Dh, 0Ah
  1867 00000A62 4275733A20              		db "Bus: "
  1868 00000A67 303068204465766963-     msgBusNo:	db "00h Device: "
  1868 00000A70 653A20             
  1869 00000A73 3030682046756E6374-     msgDevNo:	db "00h Function: "
  1869 00000A7C 696F6E3A20         
  1870 00000A81 303068                  msgFncNo:	db "00h"
  1871 00000A84 0D0A                    		db 0Dh, 0Ah
  1872 00000A86 492F4F204261736520-     		db "I/O Base Address: "
  1872 00000A8F 416464726573733A20 
  1873 00000A98 303030306820495251-     msgIOBaseAddr:	db "0000h IRQ: "
  1873 00000AA1 3A20               
  1874 00000AA3 3030                    msgIRQ:		dw 3030h
  1875 00000AA5 0D0A00                  		db 0Dh, 0Ah, 0
  1876 00000AA8 53616D706C65205261-     msgSampleRate:	db "Sample Rate: "
  1876 00000AB1 74653A20           
  1877 00000AB5 303030303020487A20-     msgHertz:	db "00000 Hz ", 0
  1877 00000ABE 00                 
  1878 00000ABF 3820626974732000        msg8Bits:	db "8 bits ", 0
  1879 00000AC7 4D6F6E6F0D0A00          msgMono:	db "Mono", 0Dh, 0Ah, 0
  1880 00000ACE 313620626974732024      msg16Bits:	db "16 bits ", "$" 
  1881 00000AD7 53746572656F0D0A00      msgStereo:	db "Stereo", 0Dh, 0Ah, 0
  1882                                  
  1883                                  ;; 13/11/2016 - Erdogan Tan (Ref: KolibriOS, codec.inc)
  1884                                  ;codec_id:	   dd 0
  1885                                  ;codec_chip_id:	   dd 0
  1886                                  ;codec_vendor_ids: dw 0
  1887                                  ;codec_chip_ids:   dw 0
  1888                                  
  1889                                  ;dword_str:	dd 30303030h, 30303030h
  1890                                  ;	 	db 'h', 0Dh, 0Ah, 0
  1891                                  
  1892                                  ;=============================================================================
  1893                                  ;        	uninitialized data
  1894                                  ;=============================================================================
  1895                                  
  1896                                  bss_start:
  1897                                  
  1898                                  ABSOLUTE bss_start
  1899                                  
  1900                                  alignb 4
  1901                                  
  1902 00000AE0 <res 00000001>          eof_flag:	resb 1
  1903 00000AE1 <res 00000001>          srb:		resb 1
  1904 00000AE2 <res 00000001>          audio_busy:	resb 1 
  1905 00000AE3 <res 00000001>          audio_play_cmd:	resb 1
  1906                                  
  1907 00000AE4 <res 00000001>          audio_flag_eol:	resb 1
  1908 00000AE5 <res 00000001>          audio_flag:	resb 1
  1909 00000AE6 <res 00000002>          		resw 1
  1910                                  
  1911 00000AE8 <res 00000004>          bus_dev_fn:	resd 1
  1912 00000AEC <res 00000004>          dev_vendor:	resd 1
  1913 00000AF0 <res 00000004>          stats_cmd:	resd 1
  1914                                  
  1915 00000AF4 <res 00000002>          ac97_io_base:	resw 1
  1916 00000AF6 <res 00000001>          ac97_int_ln_reg: resb 1 
  1917 00000AF7 <res 00000001>          		resb 1
  1918                                  
  1919 00000AF8 <res 00000001>          stmo:		resb 1 ; stereo or mono  
  1920 00000AF9 <res 00000001>          bps:		resb 1 ; bits per sample (16)
  1921                                  sample_rate:
  1922 00000AFA <res 00000002>          		resw 1
  1923                                  
  1924 00000AFC <res 0000001C>          smpRBuff:	resw 14 
  1925                                  
  1926                                  wav_file_name:
  1927 00000B18 <res 00000050>          		resb 80
  1928                                  alignb 4
  1929                                  
  1930 00000B68 <res 00000004>          BDL_phy_buff:	resd 1
  1931 00000B6C <res 00000004>          DMA_phy_buff:	resd 1
  1932                                  
  1933 00000B70 <res 00000490>          alignb 4096
  1934                                  
  1935 00001000 <res 00001000>          BdlBuffer:	resb 4096 ; BDL_SIZE (round up to 1 page)
  1936                                  
  1937 00002000 <res 0000E000>          alignb 65536
  1938 00010000 <res 00010000>          DmaBuffer:	resb 65536 ; 2 * 32K half buffer (BUFFERSIZE)
  1939                                  EOF:
