Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 30 → Rev 31

/programs/ac97wav/trunk/ac97.inc
0,0 → 1,288
; Vendor ids
INTEL_VID = 0x8086
SIS_VID = 0x1039
NVIDIA_VID = 0x10DE
AMD_VID = 0x1022
 
; Device ids
ICH_DID = 0x2415
ICH0_DID = 0x2425
ICH2_DID = 0x2445
ICH3_DID = 0x2485
ICH4_DID = 0x24C5
ICH5_DID = 0x24D5
MX440_DID = 0x7195
SI7012_DID = 0x7012
NFORCE_DID = 0x01B1
NFORCE2_DID = 0x006A
AMD8111_DID = 0x764D
AMD768_DID = 0x7445
 
NAMBAR_REG = 0x10 ; native audio mixer BAR
NAM_SIZE = 256 ; 256 bytes required.
 
NABMBAR_REG = 0x14 ; native audio bus mastering BAR
NABM_SIZE = 64 ; 64 bytes
 
IRQ_REG = 0x3c ; IRQ holder for PCI
INT_REG = 0x3d ; INT pin
ICH4_CFG_REG = 0x41 ; ICH4 config register
 
 
; BUS master registers, accessed via NABMBAR+offset
 
; ICH supports 3 different types of register sets for three types of things
; it can do, thus:
;
; PCM in (for recording) aka PI
; PCM out (for playback) aka PO
; MIC in (for recording) aka MC
 
PI_BDBAR_REG = 0 ; PCM in buffer descriptor BAR
PO_BDBAR_REG = 10h ; PCM out buffer descriptor BAR
MC_BDBAR_REG = 20h ; MIC in buffer descriptor BAR
 
; each buffer descriptor BAR holds a pointer which has entries to the buffer
; contents of the .WAV file we're going to play. Each entry is 8 bytes long
; (more on that later) and can contain 32 entries total, so each BAR is
; 256 bytes in length, thus:
 
BDL_SIZE = 32*8 ; Buffer Descriptor List size
INDEX_MASK = 31 ; indexes must be 0-31
 
 
 
PI_CIV_REG = 4 ; PCM in current Index value (RO)
PO_CIV_REG = 14h ; PCM out current Index value (RO)
MC_CIV_REG = 24h ; MIC in current Index value (RO)
 
;8bit read only
; each current index value is simply a pointer showing us which buffer
; (0-31) the codec is currently processing. Once this counter hits 31, it
; wraps back to 0.
; this can be handy to know, as once it hits 31, we're almost out of data to
; play back or room to record!
 
 
PI_LVI_REG = 5 ; PCM in Last Valid Index
PO_LVI_REG = 15h ; PCM out Last Valid Index
MC_LVI_REG = 25h ; MIC in Last Valid Index
;8bit read/write
; The Last Valid Index is a number (0-31) to let the codec know what buffer
; number to stop on after processing. It could be very nasty to play audio
; from buffers that aren't filled with the audio we want to play.
 
 
PI_SR_REG = 6 ; PCM in Status register
PO_SR_REG = 16h ; PCM out Status register
MC_SR_REG = 26h ; MIC in Status register
;16bit read/write
; status registers. Bitfields follow:
 
FIFO_ERR = BIT4 ; FIFO Over/Underrun W1TC.
 
BCIS = BIT3 ; buffer completion interrupt status.
; Set whenever the last sample in ANY
; buffer is finished. Bit is only
; set when the Interrupt on Complete
; (BIT4 of control reg) is set.
 
LVBCI = BIT2 ; Set whenever the codec has processed
; the last buffer in the buffer list.
; Will fire an interrupt if IOC bit is
; set. Probably set after the last
; sample in the last buffer is
; processed. W1TC
 
 
CELV = BIT1 ; Current buffer == last valid.
; Bit is RO and remains set until LVI is
; cleared. Probably set up the start
; of processing for the last buffer.
 
 
DCH = BIT0 ; DMA controller halted.
; set whenever audio stream is stopped
; or something else goes wrong.
 
 
PI_PICB_REG = 8 ; PCM in position in current buffer(RO)
PO_PICB_REG = 18h ; PCM out position in current buffer(RO)
MC_PICB_REG = 28h ; MIC in position in current buffer (RO)
;16bit read only
; position in current buffer regs show the number of dwords left to be
; processed in the current buffer.
;
 
 
 
 
 
PI_PIV_REG = 0ah ; PCM in Prefected index value
PO_PIV_REG = 1ah ; PCM out Prefected index value
MC_PIV_REG = 2ah ; MIC in Prefected index value
;8bit, read only
; Prefetched index value register.
; tells which buffer number (0-31) has be prefetched. I'd imagine this
; value follows the current index value fairly closely. (CIV+1)
;
 
 
PI_CR_REG = 0bh ; PCM in Control Register
PO_CR_REG = 1bh ; PCM out Control Register
MC_CR_REG = 2bh ; MIC in Control Register
; 8bit
; Control register *MUST* only be accessed as an 8bit value.
; Control register. See bitfields below.
;
 
 
IOCE = BIT4 ; interrupt on complete enable.
; set this bit if you want an intrtpt
; to fire whenever LVBCI is set.
FEIFE = BIT3 ; set if you want an interrupt to fire
; whenever there is a FIFO (over or
; under) error.
LVBIE = BIT2 ; last valid buffer interrupt enable.
; set if you want an interrupt to fire
; whenever the completion of the last
; valid buffer.
RR = BIT1 ; reset registers. Nukes all regs
; except bits 4:2 of this register.
; Only set this bit if BIT 0 is 0
RPBM = BIT0 ; Run/Pause
; set this bit to start the codec!
 
 
GLOB_CNT_REG = 2ch ; Global control register
SEC_RES_EN = BIT5 ; secondary codec resume event
; interrupt enable. Not used here.
PRI_RES_EN = BIT4 ; ditto for primary. Not used here.
ACLINK_OFF = BIT3 ; Turn off the AC97 link
ACWARM_RESET = BIT2 ; Awaken the AC97 link from sleep.
; registers preserved, bit self clears
ACCOLD_RESET = BIT1 ; Reset everything in the AC97 and
; reset all registers. Not self clearin
;g
 
GPIIE = BIT0 ; GPI Interrupt enable.
; set if you want an interrupt to
; fire upon ANY of the bits in the
; GPI (general pursose inputs?) not used
;.
 
GLOB_STS_REG = 30h ; Global Status register (RO)
 
MD3 = BIT17 ; modem powerdown status (yawn)
AD3 = BIT16 ; Audio powerdown status (yawn)
RD_COMPLETE_STS = BIT15 ; Codec read timed out. 0=normal
BIT3SLOT12 = BIT14 ; shadowed status of bit 3 in slot 12
BIT2SLOT12 = BIT13 ; shadowed status of bit 2 in slot 12
BIT1SLOT12 = BIT12 ; shadowed status of bit 1 in slot 12
SEC_RESUME_STS = BIT11 ; secondary codec has resumed (and irqed)
PRI_RESUME_STS = BIT10 ; primary codec has resumed (and irqed)
SEC_CODEC_RDY = BIT9 ; secondary codec is ready for action
PRI_CODEC_RDY = BIT8 ; Primary codec is ready for action
; software must check these bits before
; starting the codec!
MIC_IN_IRQ = BIT7 ; MIC in caused an interrupt
PCM_OUT_IRQ = BIT6 ; One of the PCM out channels IRQed
PCM_IN_IRQ = BIT5 ; One of the PCM in channels IRQed
MODEM_OUT_IRQ = BIT2 ; modem out channel IRQed
MODEM_IN_IRQ = BIT1 ; modem in channel IRQed
GPI_STS_CHANGE = BIT0 ; set whenever GPI's have changed.
; BIT0 of slot 12 also reflects this.
 
 
ACC_SEMA_REG = 34h ; Codec write semiphore register
CODEC_BUSY = BIT0 ; codec register I/O is happening
; self clearing
 
 
 
;
; Buffer Descriptors List
; As stated earlier, each buffer descriptor list is a set of (up to) 32
; descriptors, each 8 bytes in length. Bytes 0-3 of a descriptor entry point
; to a chunk of memory to either play from or record to. Bytes 4-7 of an
; entry describe various control things detailed below.
;
; Buffer pointers must always be aligned on a Dword boundry.
;
;
 
IOC = BIT31 ; Fire an interrupt whenever this
; buffer is complete.
 
BUP = BIT30 ; Buffer Underrun Policy.
; if this buffer is the last buffer
; in a playback, fill the remaining
; samples with 0 (silence) or not.
; It's a good idea to set this to 1
; for the last buffer in playback,
; otherwise you're likely to get a lot
; of noise at the end of the sound.
 
;
; Bits 15:0 contain the length of the buffer, in number of samples, which
; are 16 bits each, coupled in left and right pairs, or 32bits each.
; Luckily for us, that's the same format as .wav files.
;
; A value of FFFF is 65536 samples. Running at 44.1Khz, that's just about
; 1.5 seconds of sample time. FFFF * 32bits is 1FFFFh bytes or 128k of data.
;
; A value of 0 in these bits means play no samples.
;
 
 
;*****************************************************************************
;* AC97 Codec registers include (based on Jeff Leyda AC97 wav player SDK :-)
;*****************************************************************************
 
; Not all codecs are created =al. Refer to the spec for your specific codec.
; All registers are 16bits wide. Access to codec registers over the AC97 link
; is defined by the OEM.
; Secondary codec's are accessed by ORing in BIT7 of all register accesses.
 
 
; each codec/mixer register is 16bits
 
CODEC_RESET_REG = 00 ; reset codec
CODEC_MASTER_VOL_REG = 02 ; master volume
CODEC_HP_VOL_REG = 04 ; headphone volume
CODEC_MASTER_MONO_VOL_REG = 06 ; master mono volume
CODEC_MASTER_TONE_REG = 08 ; master tone (R+L)
CODEC_PCBEEP_VOL_REG = 0ah ; PC beep volume
CODEC_PHONE_VOL_REG = 0ch ; phone volume
CODEC_MIC_VOL_REG = 0eh ; MIC volume
CODEC_LINE_IN_VOL_REG = 10h ; line input volume
CODEC_CD_VOL_REG = 12h ; CD volume
CODEC_VID_VOL_REG = 14h ; video volume
CODEC_AUX_VOL_REG = 16h ; aux volume
CODEC_PCM_OUT_REG = 18h ; PCM output volume
CODEC_RECORD_SELECT_REG = 1ah ; record select input
CODEC_RECORD_VOL_REG = 1ch ; record volume
CODEC_RECORD_MIC_VOL_REG = 1eh ; record mic volume
CODEC_GP_REG = 20h ; general purpose
CODEC_3D_CONTROL_REG = 22h ; 3D control
; 24h is reserved
CODEC_POWER_CTRL_REG = 26h ; powerdown control
CODEC_EXT_AUDIO_REG = 28h ; extended audio
CODEC_EXT_AUDIO_CTRL_REG = 2ah ; extended audio control
CODEC_PCM_FRONT_DACRATE_REG = 2ch ; PCM out sample rate
CODEC_PCM_SURND_DACRATE_REG = 2eh ; surround sound sample rate
CODEC_PCM_LFE_DACRATE_REG = 30h ; LFE sample rate
CODEC_LR_ADCRATE_REG = 32h ; PCM in sample rate
CODEC_MIC_ADCRATE_REG = 34h ; mic in sample rate
 
 
; registers 36-7a are reserved on the ICH
 
CODEC_VENDORID1_REG = 7ch ; codec vendor ID 1
CODEC_VENDORID2_REG = 7eh ; codec vendor ID 2
 
 
; When 2 codecs are present in the system, use BIT7 to access the 2nd
; set of registers, ie 80h-feh
 
SECONDARY_CODEC = BIT7 ; 80-8f registers for 2nda
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/ac97wav.asm
0,0 → 1,1084
;---------------------------------------------------------------------
;
; MenuetOS AC97 WAV Player
;
; 0.03 November 10, 2004 doesn't halt if file not found
; 0.04 November 11, 2004 better positioning (with mouse)
; 0.05 November 14, 2004 internals clean up
; fixed cutting sound at the edges
; 0.06 November 17, 2004 fixed many bugs
; 0.07 Nov 20, 2004 deactivates text box when 'play' pressed
; stops playing before closing a window
; 0.08 Nov 24, 2004 added support for 8bit and mono modes
; +variable rate for some chipsets
;
; Use [flat assembler 1.56] to compile.
;
;---------------------------------------------------------------------
 
use32 ; turn on 32 bit mode
org 0x0 ; the program is placed at 0 offset
 
db 'MENUET01' ; 8-byte identifier of MenuetOS application
dd 0x01 ; header version (always 1)
dd START ; address of the beginning of the code
dd IMAGE_END ; size of the program's image
dd MEMORY_END ; how much memory does it need
dd STACK_P ; a pointer to the top of the stack
dd textbox_string
; dd 0x0 ; address of buffer for parameters (not used)
dd 0x0 ; reserved
 
;---------------------------------------------------------------------
 
include "lang.inc"
include "macros.inc" ; standart macros & constants
include "meosfunc.inc" ; MenuetOS API functions names
include "debug.inc" ; printing to debug board
include "constant.inc" ; BIT?? constants
include "ac97.inc" ; AC'97 constants
include "pci.inc" ; PCI interface
include "codec.inc" ; functions for configuring codec
include "frontend.inc" ; main window
 
;---------------------------------------------------------------------
 
; Uncomment these strings if you don't want to receive debug messages:
 
; macro dps str {} ; dps prints a string without CRLF
; macro dpd num {} ; prints unsigned decimal number
; macro pregs {} ; outputs EAX, EBX, ECX, EDX
; macro newline {} ; CRLF
; macro print str {} ; output a string with CRLF
; macro dph arg {} ; print hex number
 
;---------------------------------------------------------------------
 
;macro device id, addr { dd id, addr }
macro devices [id, str]
{
common
label supported_devices dword
forward
local string
dd id
dd string
forward
string db str
db 0
}
 
 
devices \
(ICH_DID shl 16) + INTEL_VID, "ICH" ,\
(ICH0_DID shl 16) + INTEL_VID, "ICH0" ,\
(ICH2_DID shl 16) + INTEL_VID, "ICH2" ,\
(ICH3_DID shl 16) + INTEL_VID, "ICH2" ,\
(ICH4_DID shl 16) + INTEL_VID, "ICH4" ,\
(ICH5_DID shl 16) + INTEL_VID, "ICH5" ,\
(MX440_DID shl 16) + INTEL_VID, "440MX" ,\
(SI7012_DID shl 16) + SIS_VID, "SI7012" ,\
(NFORCE_DID shl 16) + NVIDIA_VID, "NForce" ,\
(NFORCE2_DID shl 16) + NVIDIA_VID, "NForce2",\
(AMD8111_DID shl 16) + AMD_VID, "AMD8111",\
(AMD768_DID shl 16) + AMD_VID, "AMD768"
dd 0
 
 
;---------------------------------------------------------------------
;--- MAIN PROGRAM --------------------------------------------------
;---------------------------------------------------------------------
 
START:
 
; Print PCI version (for example, 2.16)
; mcall MF_PCI, 0
; mov bl, al
; movzx eax, ah
; dps "PCI version: "
; dpd eax
; movzx eax, bl
; dpd eax
; newline
 
; Check PCI access mechanism (must be 1 or 2)
mcall MF_PCI, 2
dec al
cmp al, 1
jna @f
print "Error: cannot access PCI bus."
jmp exit
; dps "PCI returned "
; movzx eax, al
; dpd eax
; newline
@@:
 
 
; Get last bus & then check all buses & devices
mcall MF_PCI, 1
mov [lastbus], al
 
; looking for a compatible device
mov [bus], -1
.next_bus:
inc [bus]
 
mov al, [lastbus]
cmp al, [bus]
jb .device_not_found
 
mov [devfn], 0
.next_devfn:
 
mov cl, 0
call pciRegRead32
 
mov edi, supported_devices
@@:
mov ebx, [edi]
test ebx, ebx
jz @f
cmp eax, ebx
jnz .skip
add edi, 4
mov [device_id], eax
mov edx, [edi]
call debug_outstr
jmp proceed
.skip:
add edi, 8
jmp @b
@@:
 
inc [devfn]
cmp [devfn], 255
jb .next_devfn
 
jmp .next_bus
 
 
.device_not_found:
print "Could not find Intel AC'97 compatible codec!"
print "1) Check if it's enabled in BIOS."
print "2) Check if your device is included in the device list."
jmp exit
 
 
proceed:
print " integrated AC97 audio codec detected."
mov eax, [device_id]
cmp eax, (ICH4_DID shl 16) + INTEL_VID
je .newich
cmp eax, (ICH5_DID shl 16) + INTEL_VID
jne .nonewich
.newich:
mov [AC97ICH4], 1
.nonewich:
 
cmp eax, (SI7012_DID shl 16) + SIS_VID
jne @f
mov [SI7012], 1
@@:
 
;---------------------------------------------------------------------
 
; Get NAMBAR register base port address & save it
mov cl, NAMBAR_REG
call pciRegRead16
 
and eax, 0xFFFE
mov [NAMBAR], ax
test eax, eax
jnz .mixer_base_ok
 
print "Error: Intel ICH based AC97 audio codec disabled in BIOS!"
jmp exit
 
.mixer_base_ok:
dps "NAMBAR: "
dph eax
 
; Get NABMBAR & save it
mov cl, NABMBAR_REG
call pciRegRead16
and eax, 0xFFC0
mov [NABMBAR], ax
test eax, eax
jnz .bm_base_ok
 
print "Error: Intel ICH based AC97 audio codec disabled in BIOS!"
jmp exit
 
.bm_base_ok:
dps " NABMBAR: "
dph eax
newline
 
;---------------------------------------------------------------------
 
; Get IRQ (not used)
mov cl, IRQ_REG
call pciRegRead8
mov [AC97IRQ], al
 
; Get Interrupt pin (not used)
mov cl, INT_REG
call pciRegRead8
mov [AC97INT], al
 
; AC97ICH4 should work then...
cmp [AC97ICH4], 1
jne .skip_ich4_init
 
mov cl, ICH4_CFG_REG ; 0x41
call pciRegRead8
or al, 0x1
mov dl, al
call pciRegWrite8
 
mov cl, 0x54
call pciRegRead16
and eax, 0xFFFF
dps "Power Control & Status: "
dph eax
newline
.skip_ich4_init:
 
;---------------------------------------------------------------------
 
mov cl, PCI_CMD_REG
call pciRegRead16 ; read PCI command register
mov dx, ax
or dx, IO_ENA+BM_ENA+BIT10 ; enable IO and bus master + disable
; interrupts
call pciRegWrite16
 
;---------------------------------------------------------------------
 
print "Enabling access to ports..."
 
movzx ecx, [NAMBAR]
mov edx, ecx
add edx, NAM_SIZE
mcall MF_PORTS, PRT_RESERVE
test eax, eax
jz @f
print "Error: couldn't enable access to ports"
jmp exit
@@:
 
movzx ecx, [NABMBAR]
mov edx, ecx
add edx, NABM_SIZE
mcall MF_PORTS, PRT_RESERVE
test eax, eax
jz @f
print "Error: couldn't enable access to ports"
jmp exit
@@:
 
;---------------------------------------------------------------------
 
; setup the Codec
mov eax, 48000
call codecConfig ; unmute codec, set rates.
test eax, eax
jnz @f
print "Error: cannot initialize AC97 device."
jmp fpexit
@@:
 
print "Congrutalations! Your device has been initialized properly!"
call print_info
 
;---------------------------------------------------------------------
 
; register reset the DMA engine.
mov edx, PO_CR_REG ; PCM out control register
mov al, RR ; reset
call NABMBAR_write_byte
;start fix for MM (1)
mcall MF_INTERNAL_SERVICES,ALLOC_PHYS_MEM,120*1024
test eax,eax
jz no_phys_buffers ;not enough memory
mov [phys_wav_buffer1],eax
add eax,60*1024
mov [phys_wav_buffer2],eax
mcall MF_INTERNAL_SERVICES,ALLOC_PHYS_MEM,32*8
test eax,eax
jnz @f
mcall MF_INTERNAL_SERVICES,FREE_PHYS_MEM,[phys_wav_buffer1]
jmp no_phys_buffers
@@:
mov [phys_bdl_buffer],eax
;end fix for MM (1)
 
; create Buffer Descriptors List
call prepare_BDL
 
; open player's window
mcall MF_THREAD, THR_CREATE, thread, thread_stack
 
; wait for command
.new_check:
cmp [status], ST_PLAY
jne @f
call play
@@:
cmp [status], ST_STOP
jne @f
call stop
@@:
cmp [status], ST_EXIT
je stopexit
 
mcall MF_DELAY, 10
jmp .new_check
 
stopexit:
call stop
 
fpexit:
 
; free ports
movzx ecx, [NAMBAR]
mov edx, ecx
add edx, NAM_SIZE
mcall MF_PORTS, PRT_FREE
 
movzx ecx, [NABMBAR]
mov edx, ecx
add edx, NABM_SIZE
mcall MF_PORTS, PRT_FREE
 
;---------------------------------------------------------------------
;start fix for MM (2)
mcall MF_INTERNAL_SERVICES,FREE_PHYS_MEM,[phys_bdl_buffer]
mcall MF_INTERNAL_SERVICES,FREE_PHYS_MEM,[phys_wav_buffer1]
;end fix for MM (2)
exit:
mcall MF_EXIT
no_phys_buffers:
print "allocation of physical buffers failed"
jmp exit
 
;---------------------------------------------------------------------
;--- FUNCTIONS -----------------------------------------------------
;---------------------------------------------------------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; prepare_BDL - initializes BUFFER DESCRIPTORS LIST
prepare_BDL:
mov ecx, 32 / 2 ; make 32 entries in BDL
mov edi, BDL_BUFFER
; call get_my_address
mov ebx, 30*1024
cmp [SI7012], 1
jne @f
add ebx, ebx
@@:
; set buf. desc. 0 to start of data file in memory
push eax
; add eax, WAV_BUFFER1
;start fix for MM (6)
mov eax,[phys_wav_buffer1]
;end fix for MM (6)
stosd
; set length to 60k samples. 1 sample is 16 bit or 2 bytes.
mov eax, ebx ;60*1024 ; number of samples
or eax, BUP
stosd
 
mov eax, [esp]
; add eax, WAV_BUFFER2
;start fix for MM (7)
mov eax,[phys_wav_buffer2]
;end fix for MM (7)
stosd
mov eax, ebx ;60*1024
or eax, BUP
stosd
 
pop eax
loop @b
 
; tell the DMA engine where to find our list of Buffer Descriptors.
; eax = base addr!
;start fix for MM (3)
;copy to physical memory
mcall MF_INTERNAL_SERVICES,SET_PHYS_BUFFER,[phys_bdl_buffer],BDL_BUFFER,32*8
;physical address of bdl
mov eax,[phys_bdl_buffer]
;end fix for MM (3)
mov edx, PO_BDBAR_REG
; add eax, BDL_BUFFER
call NABMBAR_write_dword
 
ret
 
 
;---------------------------------------------------------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; stop - stops current music
;; in: nothing
;; out: nothing
stop:
; print "STOP!"
push eax edx
 
mcall MF_DELAY, 10
mov edx, PO_CR_REG
mov al, 0
call NABMBAR_write_byte
cmp [status], ST_STOP
jne .exit
mov [status], ST_DONE
.exit:
 
pop edx eax
ret
 
;---------------------------------------------------------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; play - plays wav file!
;; in: nothing
;; out: nothing (but sound :) !corrupts registers!
play:
; at first, reset file
mov [fileinfo.first_block], 0
mcall MF_SYSTREE, fileinfo ; load a block, returns error code in eax
; and size of the file in ebx
test eax, eax ; 0 - successful
jz @f
print "AC97: File not found!"
mov [status], ST_STOP
jmp .exit
@@:
shr ebx, 9 ; size_of_file / 512 = number_of_blocks
mov [file_size], ebx
 
 
mov al, [LOAD_BUFFER+32] ; bytes per sample
dec al
jz @f
cmp al, 3
je @f
sub al, [LOAD_BUFFER+22] ; channels
add al, 2
@@:
mov [wav_mode], al
 
pusha
movzx ebx,word [LOAD_BUFFER+24]
mov eax,48000
xor edx,edx
div ebx
mov [difference_of_frequency],al
; dph eax
mov ecx,edx
imul eax,ecx,10
xor edx,edx
div ebx
mov ecx,edx
imul ecx,10
push eax
mov eax,ecx
xor edx,edx
div ebx
; dph eax
cmp eax,5
jl .temp_15
pop eax
; dph eax
 
inc eax
jmp .temp_16
.temp_15:
pop eax
.temp_16:
mov [difference_of_frequency_1],al
; dph eax
xor edx,edx
movzx ebx,[difference_of_frequency]
imul ebx,10
add bl,[difference_of_frequency_1]
mov [difference_of_frequency_2],bl
; dph ebx
popa
 
movzx eax, word [LOAD_BUFFER+24]
;dps "Freq: "
;dpd eax
;newline
call set_sample_rate
 
 
; change the last_valid_index to the (current_index-1)
; the LVI register tells the DMA engine where to stop playing
call updateLVI
 
; if current index is odd, load buffer 1 then 0, jump to tuneLoop
; if it is even, buffers 0 then 1; tuneLoop1
call getCurrentIndex
and eax, BIT0
 
mov esi, eax
push eax
call update_next_buffer
pop eax
xor eax, 1
call update_next_buffer
 
; start playing!
mov edx, PO_CR_REG
mov al, RPBM
call NABMBAR_write_byte
 
jmp [jumpto+esi*4]
 
 
.tuneLoop:
; wait while the current_index is even
@@:
; dps "a"
mcall MF_DELAY, 7
call getCurrentIndex
test al, BIT0
jz @b ; loop if not ready yet
; print "fa"
 
call updateLVI
 
mov eax, 0
call update_next_buffer
test al, al
jnz .exit_wait
 
cmp [status], ST_PLAY
jne .exit
 
test [volume], 0x10000000 ; test volume_changed bit
je @f
mov al, byte [volume]
call setVolume
and [volume], 0x0FFFFFFF ; clear vloume_changed bit
@@:
 
.tuneLoop1:
@@:
; dps "b"
mcall MF_DELAY, 7
call getCurrentIndex
test al, BIT0
jnz @b ; loop if not ready yet
; print "fb"
 
cmp [status], ST_PLAY
jne .exit
 
call updateLVI
 
mov eax, 1
call update_next_buffer
test al, al
jnz .exit_wait
 
jmp .tuneLoop
.exit_wait:
mcall MF_DELAY, 30 ; a little pause - let the player finish
.exit:
ret
attempts db 0
 
buffers dd WAV_BUFFER1, WAV_BUFFER2
jumpto dd play.tuneLoop, play.tuneLoop1
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; update_first_buffer - load a chunk into the first buffer, increments offset
;; in: eax = number - 0 or 1
;; out: error code, 0 - successful
update_next_buffer:
push esi edi
 
movzx edx, byte [wav_mode]
mov ecx, [blocks + edx * 4]
mov [fileinfo.blocks], ecx
 
mov esi, LOAD_BUFFER
mov edi, [buffers+eax*4]
push eax ;save buffer index
start_attempts:
mcall MF_SYSTREE, fileinfo
test eax, eax
jz @f
cmp [attempts],100
je @f
inc [attempts]
jmp start_attempts
dpd eax
newline
dpd [fileinfo.first_block]
newline
@@:
; print " loaded!"
 
push eax ebx edx
mov eax,ecx
xor edx,edx
imul eax,10
movzx ebx,[difference_of_frequency_2]
 
div ebx
mov ecx,eax
 
; mov ebx,10
; mov eax,edx
; xor edx,edx
; div ebx
; cmp edx,5
; jb temp_12_7
; inc ecx
; temp_12_7:
cmp edx,0
je temp_12_7
inc ecx
temp_12_7:
 
pop edx ebx
mov eax,[esp+4] ;restore buffer index
add [fileinfo.first_block], ecx ; +60Kb
call [convert + edx * 4]
;start fix for MM (4)
mov eax,[esp+4] ;restore buffer index
test eax,not 1
jz .ok
print "buffer index out of range"
dpd eax
jmp .ret
.ok:
push ebp
mov ebp,[phys_wav_buffer1+eax*4]
mov edi,[buffers+eax*4]
mcall MF_INTERNAL_SERVICES,SET_PHYS_BUFFER,ebp,edi,60*1024
pop ebp
.ret:
pop eax
add esp,4 ;pop buffer index
;end fix for MM (4)
 
pop edi esi
ret
 
c8mono:
mov [type_of_conversion],1
jmp for_all_type
 
c8mono_1:
lodsb
call c8mono_2
push ax
shl eax,16
pop ax
push eax
mov al,[esi]
call c8mono_2
push ax
shl eax,16
pop ax
mov ebx,eax
pop eax
jmp for_all_type_1
 
c8mono_2:
sub al, 0x80
cbw
imul ax, 255
ret
 
c8stereo:
mov [type_of_conversion],2
jmp for_all_type
 
c8stereo_1:
lodsb
call c8stereo_2
shl eax,16
lodsb
call c8stereo_2
push eax
mov al,[esi]
call c8stereo_2
shl eax,16
mov al,[esi+1]
call c8stereo_2
mov ebx,eax
pop eax
jmp for_all_type_1
 
c8stereo_2:
sub al, 0x80
cbw
imul ax, 255
ret
 
c16mono:
mov [type_of_conversion],3
jmp for_all_type
 
c16mono_1:
lodsw
push ax
shl eax,16
pop ax
mov bx,[esi]
shl ebx,16
mov bx,[esi]
jmp for_all_type_1
 
c16stereo:
for_all_type:
xor edx,edx
mov eax, 15*1024*10
movzx ebx,[difference_of_frequency_2]
xor edx,edx
div ebx
mov ecx,eax
 
; mov ebx,10
; mov eax,edx
; xor edx,edx
; div ebx
; cmp edx,5
; jb temp_12_6
; inc ecx
; temp_12_6:
cmp edx,0
je temp_12_6
inc ecx
temp_12_6:
 
c16stereo_1:
mov [znak],0
 
cmp [type_of_conversion],1
je c8mono_1
cmp [type_of_conversion],2
je c8stereo_1
cmp [type_of_conversion],3
je c16mono_1
lodsd
 
mov ebx,[esi]
for_all_type_1:
cmp eax,ebx
jne c16stereo_2
inc [znak]
c16stereo_2:
push eax
push ecx
sub eax,ebx
push eax
shl eax,16
movzx ebx,[difference_of_frequency]
inc ebx
xor edx,edx
div ebx
shr eax,16
mov ecx,eax
pop eax
xor ax,ax
xor edx,edx
div ebx
shl eax,16
mov cx,ax
mov ebx,ecx
pop ecx
pop eax
mov dl,[difference_of_frequency]
inc dl
@@:
temp_12:
cmp [difference_of_frequency_1],0
je temp_12_3
cmp [difference_of_frequency_1],5
jne temp_12_4
cmp [difference_of_frequency_4],2
jne temp_12_3
jmp temp_12_5
temp_12_4:
cmp [difference_of_frequency_4],10
jne temp_12_3
 
temp_12_5:
 
cmp [znak],0
jne temp_12_5_1
sub eax,ebx
jmp temp_12_5_2
temp_12_5_1:
add eax,ebx
temp_12_5_2:
 
 
stosd
inc [schetchik]
mov [difference_of_frequency_4],0
temp_12_3:
cmp [znak],0
jne temp_13
sub eax,ebx
jmp temp_14
temp_13:
add eax,ebx
 
temp_14:
cld
dec dl
jz temp_14_1
stosd
inc [schetchik]
inc [difference_of_frequency_4]
jmp temp_12
temp_14_1:
dec ecx
cmp ecx,0
; jnz c16stereo_1
jg c16stereo_1
newline
dph [schetchik]
temp_14_2:
cmp [schetchik],15360
jge temp_14_3
stosd
inc [schetchik]
jmp temp_14_2
 
temp_14_3:
newline
dph [schetchik]
cmp [schetchik],15360
je temp_14_4
; mov [edi-4],dword 0
sub edi,4
; sub esi,4
temp_14_4:
mov [schetchik],0
ret
 
 
difference_of_frequency db 0
difference_of_frequency_1 db 0
difference_of_frequency_2 db 0
difference_of_frequency_4 db 0
schetchik dd 0
znak db 0
type_of_conversion db 0
 
convert dd c8mono, c8stereo, c16mono, c16stereo
blocks dd 30, 60, 60, 120
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; get_my_address - get base address of the program in physical memory
;; in: nothing
;; out: eax = address
;start fix for MM (8)
;function shouldn't used.
;get_my_address:
; pushad
; mcall MF_PROCINFO, procinfo, PN_MYSELF
; popad
; mov eax, [procinfo.memory_start]
;ret
;end fix for MM (8)
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; set the last valid index to something other than we're currently playing
;; so that we never end
;;
;; this routine just sets the last valid index to 1 less than the index
;; that we're currently playing, thus keeping it in and endless loop
;; input: none
;; output: none
updateLVI:
push eax
call getCurrentIndex
; dps "index "
; dpd eax
; newline
dec al
and al, INDEX_MASK
call setLastValidIndex
pop eax
ret
 
;---------------------------------------------------------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; returns AL = current index value
getCurrentIndex:
push edx
mov edx, PO_CIV_REG
call NABMBAR_read_byte
pop edx
ret
 
;---------------------------------------------------------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; input AL = index # to stop on
setLastValidIndex:
push edx
mov edx, PO_LVI_REG
call NABMBAR_write_byte
pop edx
ret
 
;---------------------------------------------------------------------
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; print_info - outputs debug information
;; in: nothing
;; out: nothing
print_info:
dps "BUS: "
movzx eax, [bus]
dph eax
 
dps " DEVFN: "
movzx eax, [devfn]
dph eax
 
dps " IRQ: "
movzx eax, [AC97IRQ]
dpd eax
newline
 
 
dps "CODEC_POWER_CTRL: "
mov edx, CODEC_POWER_CTRL_REG
call NAMBAR_read_word
dph eax
dps " (bits 0-3 should be set)"
newline
 
mov edx, 0x28
call NAMBAR_read_word
dph eax
dps " - supported features"
newline
mov edx, 0x2A
call NAMBAR_read_word
dph eax
dps " - config"
newline
mov edx, 0x2C
call NAMBAR_read_word
dph eax
dps " - PCM rate"
 
newline
ret
 
 
;---------------------------------------------------------------------
;--- DATA OF PROGRAM -----------------------------------------------
;---------------------------------------------------------------------
volume dd 15
 
fileinfo:
.mode dd 0 ; READ
.first_block dd 0
.blocks dd 120 ; 120 Kb
.dest dd LOAD_BUFFER ;file_data
.work dd work_area
; db "/HD/1/WINDOWS/MEDIA/WICEB7~1.WAV",0
;sz textbox_string, "/hd/1/testmuz/menuet11.wav",0
sz textbox_string, " ",0
; rb 256
;---------------------------------------------------------------------
 
IMAGE_END: ; end of program's image
rb 100-textbox_string.size
; textbox_string.size
 
;---------------------------------------------------------------------
 
device_id dd ? ; (device_id << 16) + vendor_id
lastbus db ? ; pci coordinates
bus db ?
devfn db ?
 
AC97ICH4 db ? ; Intel ICH4 codec flag
SI7012 db ? ; SiS SI7012 codec flag
NAMBAR dw ? ; Audio Mixers Registers (base)
NABMBAR dw ? ; Bus Master Registers (base)
 
AC97IRQ db ? ; Interrupt request
AC97INT db ? ; Interrupt pin
 
wav_mode db ? ; bits per sample & channels
 
;---------------------------------------------------------------------
 
ST_DONE = 0x0 ; for interacting with player's window
ST_PLAY = 0x1
ST_EXIT = 0x2
ST_STOP = 0x4
 
status db ?
 
;---------------------------------------------------------------------
phys_bdl_buffer rd 1
phys_wav_buffer1 rd 1
phys_wav_buffer2 rd 1
align 32
 
 
; Buffer Descriptors List
; ___________________________
; | physical address | dword
; |_________________________|
; | attr | length | dword max. length = 65535 samples
; |_________________________|
 
BDL_BUFFER:
rb 32*8 ; 32 descriptors, 8 bytes each
 
 
;---------------------------------------------------------------------
 
file_data:
 
WAV_BUFFER1:
rb 60 * 1024 ; 60 Kb
 
WAV_BUFFER2:
rb 60 * 1024
 
LOAD_BUFFER:
rb 60 * 1024
 
;---------------------------------------------------------------------
 
procinfo process_information
 
work_area:
rb 0x10000
 
;---------------------------------------------------------------------
 
rb 0x800
thread_stack:
 
rb 0x1000 ; for stack
STACK_P:
 
MEMORY_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/build_en.bat
0,0 → 1,4
@erase lang.inc
@echo lang fix en >lang.inc
@fasm ac97wav.asm ac97wav
@pause
/programs/ac97wav/trunk/build_ru.bat
0,0 → 1,4
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm ac97wav.asm ac97wav
@pause
/programs/ac97wav/trunk/codec.inc
0,0 → 1,344
 
NAMBAR_read_byte:
add dx, [NAMBAR]
in al, dx
ret
 
 
NAMBAR_read_word:
add dx, [NAMBAR]
in ax, dx
ret
 
 
NAMBAR_read_dword:
add dx, [NAMBAR]
in eax, dx
ret
 
NAMBAR_write_byte:
add dx, [NAMBAR]
out dx, al
ret
 
NAMBAR_write_word:
add dx, [NAMBAR]
out dx, ax
ret
 
NAMBAR_write_dword:
add dx, [NAMBAR]
out dx, eax
ret
 
 
 
NABMBAR_read_byte:
add dx, [NABMBAR]
in al, dx
ret
 
NABMBAR_read_word:
add dx, [NABMBAR]
in ax, dx
ret
 
NABMBAR_read_dword:
add dx, [NABMBAR]
in eax, dx
ret
 
NABMBAR_write_byte:
add dx, [NABMBAR]
out dx, al
ret
 
NABMBAR_write_word:
add dx, [NABMBAR]
out dx, ax
ret
 
NABMBAR_write_dword:
add dx, [NABMBAR]
out dx, eax
ret
 
 
 
semaphore:
push ecx edx
 
mov edx, GLOB_STS_REG ; 0x30 global status register
call NABMBAR_read_dword
and eax, PRI_CODEC_RDY ; 100h primary codec ready
jz .success ; exit if codec not ready !!!
 
; mov ecx, 1024 ; try 1024 times
mov ecx, 0ffffh ; try 65535 times
.wait:
mov edx, ACC_SEMA_REG ; 0x34 codec write semaphore
call NABMBAR_read_byte
and al, CODEC_BUSY ; 01h codec access semaphore
jz .success ; exit if codec not busy !!!
 
dec ecx
jnz .wait
 
pop edx ecx
mov eax, 0
jmp .exit
 
.success:
pop edx ecx
mov eax, 1
.exit:
ret
 
 
 
 
 
codecStop:
push eax ebx edx
 
mov edx, PO_CR_REG ; 0x1B control register
mov al, 0 ; stop all PCM out data
call NABMBAR_write_byte
 
mcall MF_DELAY, eax ; ebx = (eax = MF_DELAY = 5); wait 50 ms
 
mov edx, PO_CR_REG ; 0x1B control register
mov al, RR ; reset PCM out regs
call NABMBAR_write_byte
 
mcall MF_DELAY, eax
 
pop edx ebx eax
ret
 
 
 
 
; set voulme
; in ax = volume level
setVolume:
push eax edx
 
push eax
call semaphore
mov edx, CODEC_RESET_REG ; 0
xor eax, eax ; register reset the codec
call NAMBAR_write_word
 
call semaphore
pop eax
imul ax, 0101h ; set volume for both chn
mov edx, CODEC_MASTER_VOL_REG ; 2
call NAMBAR_write_word
push eax
 
call semaphore
pop eax ; set volume for both chn
mov edx, CODEC_HP_VOL_REG ; 4
call NAMBAR_write_word
push eax
 
call semaphore
mov edx, CODEC_CD_VOL_REG ; 12h
pop eax ; set volume for both chn
shr eax, 2 ; adjust CD VOL
call NAMBAR_write_word
 
call semaphore
mov edx, CODEC_PCM_OUT_REG ; 18h
mov ax, 0808h ; standard PCM out volume
call NAMBAR_write_word
 
pop edx eax
ret
 
 
 
 
samplerate dw 0
 
 
 
; enable codec, unmute stuff, set output to desired rate
; in : ax = desired sample rate
; out: ax = true or false
;
codecConfig:
pushad
mov [samplerate], ax ; save sample rate
 
 
; mov edx, GLOB_STS_REG ; 30h global status register
; call NABMBAR_read_dword
; and eax, PRI_CODEC_RDY ; 0100h primary codec ready
; jnz skip_init ; skip init if codec ready !!!
 
; stop the codec if currently playing
;;; call codecStop
 
; mov edx, GLOB_STS_REG
; call NABMBAR_read_dword
; dps "GLOB_STA = "
; dph eax
; newline
 
; mov edx, GLOB_CNT_REG
; call NABMBAR_read_dword
; dps "GLOB_CNT = "
; dph eax
; newline
 
; mcall 5, 10
 
;; test eax, ACCOLD_RESET
;; jnz .skip_cold_reset
 
; print "cold reset"
; do a cold reset
mov edx, GLOB_CNT_REG ; 2ch global control register
xor eax, eax
call NABMBAR_write_dword ; enable (AC Link off clear)
 
; print "wait"
mcall 5, 5
; print "alive!"
 
;; .skip_cold_reset:
 
mov edx, GLOB_CNT_REG ; 2ch global control register
mov eax, ACCOLD_RESET + PRI_RES_EN ; cold reset + primary resume
call NABMBAR_write_dword ; 2 channels & 16 bit samples
 
mov edx, GLOB_CNT_REG ; 2ch global control register
call NABMBAR_read_dword
and eax, ACCOLD_RESET ; cold reset
jz init_error ; INIT FAILED !!!
 
; print "cold reset finished"
 
; wait for primary codec ready status
mov ecx, 128
codec_ready_loop:
mov edx, GLOB_STS_REG ; 30h global status register
call NABMBAR_read_dword
and eax, PRI_CODEC_RDY ; 0100h primary codec ready
jnz codec_ready_exit ; move on if codec ready !!!
mcall 5, 1
dec ecx
jnz codec_ready_loop
;dps "~"
codec_ready_exit:
 
; wait until codec init ready (*** replaces warm reset wait ***)
mcall 5, 60
 
; test if codec ready bit is finally set
mov edx, GLOB_STS_REG ; 30h global status register
call NABMBAR_read_dword
and eax, PRI_CODEC_RDY ; 0100h primary codec ready
jnz codec_ready_bit_set ; move on if codec ready !!!
cmp [AC97ICH4], 1
jne init_error
; je codec_ready_bit_set ; ignore codec ready for ICH4
; jmp init_error ; codec ready bit not set !!!
codec_ready_bit_set:
 
; clear semaphore flag
mov edx, CODEC_RESET_REG ; 0h codec reset register
call NAMBAR_read_word
 
 
; check if codec sections ready
call semaphore
test eax, eax
jz init_error
mov edx, CODEC_POWER_CTRL_REG ; 26h codec powerdown ctrl
call NAMBAR_read_word
and eax, 01111b
cmp eax, 01111b
jne init_error ; codec sections not ready
 
 
 
; disable interrupts
mov al, 0
 
mov edx, PI_CR_REG ; 0Bh PCM in control register
call NABMBAR_write_byte
 
mov edx, PO_CR_REG ; 1Bh PCM out control register
call NABMBAR_write_byte
 
mov edx, MC_CR_REG ; 2Bh MIC in control register
call NABMBAR_write_byte
 
; reset channels
mov al, RR ; 02h reset Bus master regs
 
mov edx, PI_CR_REG ; 0Bh PCM in control register
call NABMBAR_write_byte
 
mov edx, PO_CR_REG ; 1Bh PCM out control register
call NABMBAR_write_byte
 
mov edx, MC_CR_REG ; 2Bh MIC in control register
call NABMBAR_write_byte
 
; set default volume
mov eax, 15 ; set average volume level
call setVolume
 
; set VRA and clear DRA (if not supported will be skipped)
call semaphore
test eax, eax
jz init_error
mov edx, CODEC_EXT_AUDIO_CTRL_REG ; register 2ah
call NAMBAR_read_word ; get ext audio ctl
 
mov ebx, eax
call semaphore
test eax, eax
jz init_error
mov eax, ebx
and eax, 0FFFFh - BIT1 ; clear DRA (BIT1)
or eax, BIT0 ; set VRA (BIT0)
mov edx, CODEC_EXT_AUDIO_CTRL_REG ; register 2ah
call NAMBAR_write_word ; write ext audio ctl
 
; set desired sample rate
skip_init:
call semaphore
test eax, eax
jz init_error
 
; mov edx, CODEC_PCM_FRONT_DACRATE_REG
; call NAMBAR_read_word
; and eax, 0xFFFF
; newline
; dps "old PCM OUT RATE: "
; dpd eax
; newline
 
mov ax, [samplerate] ; restore sample rate
; mov edx, CODEC_PCM_FRONT_DACRATE_REG ; register 2ch
; call NAMBAR_write_word
call set_sample_rate
 
popad
mov eax, 1 ; exit with success
jmp exit_config
init_error:
popad
xor eax, eax ; exit with error
exit_config:
ret
 
set_sample_rate: ; rate in ax
mov edx, CODEC_PCM_FRONT_DACRATE_REG ; 0x2C reg
call NAMBAR_write_word
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/constant.inc
0,0 → 1,35
;constants of stuff that seem hard to remember at times.
 
BIT0 EQU 1
BIT1 EQU 2
BIT2 EQU 4
BIT3 EQU 8
BIT4 EQU 10h
BIT5 EQU 20h
BIT6 EQU 40h
BIT7 EQU 80h
BIT8 EQU 100h
BIT9 EQU 200h
BIT10 EQU 400h
BIT11 EQU 800h
BIT12 EQU 1000h
BIT13 EQU 2000h
BIT14 EQU 4000h
BIT15 EQU 8000h
BIT16 EQU 10000h
BIT17 EQU 20000h
BIT18 EQU 40000h
BIT19 EQU 80000h
BIT20 EQU 100000h
BIT21 EQU 200000h
BIT22 EQU 400000h
BIT23 EQU 800000h
BIT24 EQU 1000000h
BIT25 EQU 2000000h
BIT26 EQU 4000000h
BIT27 EQU 8000000h
BIT28 EQU 10000000h
BIT29 EQU 20000000h
BIT30 EQU 40000000h
BIT31 EQU 80000000h
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/debug.inc
0,0 → 1,131
macro debug_print str
{
local ..string, ..label
 
jmp ..label
..string db str,0
..label:
 
pushf
pushad
mov edx,..string
call debug_outstr
popad
popf
}
 
dps fix debug_print
 
macro debug_print_dec arg
{
pushf
pushad
if ~arg eq eax
mov eax,arg
end if
call debug_outdec
popad
popf
}
 
dpd fix debug_print_dec
 
;---------------------------------
debug_outdec: ;(eax - num, edi-str)
push 10 ;2
pop ecx ;1
push -'0' ;2
.l0:
xor edx,edx ;2
div ecx ;2
push edx ;1
test eax,eax ;2
jnz .l0 ;2
.l1:
pop eax ;1
add al,'0' ;2
call debug_outchar ; stosb
jnz .l1 ;2
ret ;1
;---------------------------------
 
debug_outchar: ; al - char
pushf
pushad
mov cl,al
mov eax,63
mov ebx,1
int 0x40
popad
popf
ret
 
debug_outstr:
mov eax,63
mov ebx,1
@@:
mov cl,[edx]
test cl,cl
jz @f
int 40h
inc edx
jmp @b
@@:
ret
 
 
macro newline
{
dps <13,10>
}
 
macro print message
{
dps message
newline
}
 
macro pregs
{
dps "EAX: "
dpd eax
dps " EBX: "
dpd ebx
newline
dps "ECX: "
dpd ecx
dps " EDX: "
dpd edx
newline
}
 
macro debug_print_hex arg
{
pushf
pushad
if ~arg eq eax
mov eax, arg
end if
call debug_outhex
popad
popf
}
dph fix debug_print_hex
 
debug_outhex:
; eax - number
mov edx, 8
.new_char:
rol eax, 4
movzx ecx, al
and cl, 0x0f
mov cl, [__hexdigits + ecx]
pushad
mcall 63, 1
popad
dec edx
jnz .new_char
ret
 
__hexdigits:
db '0123456789ABCDEF'
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/frontend.inc
0,0 → 1,270
thread:
call draw_window
call main_loop
mov [status], ST_EXIT
mcall MF_EXIT
 
;---------------------------------------------------------------------
 
main_loop:
cmp [status], ST_PLAY
je @f
mcall MF_WAIT_EVENT
jmp .handle_event
@@:
call draw_progress_bar
mcall MF_WAIT_EVENT_TIMEOUT, 80
.handle_event:
cmp eax, EV_REDRAW
je redraw
cmp eax, EV_BUTTON
je button
cmp eax, EV_KEY
je key
jmp main_loop
 
redraw:
call draw_window
jmp main_loop
 
key:
mcall MF_GETKEY
cmp [textbox_active], 1
jne main_loop
cmp ah, 13
je .enter
cmp ah, 8
je .backspace
movzx ecx, [textbox_position]
cmp ecx, 47
jae .enter
mov [textbox_string + ecx], ah
inc [textbox_position]
call textbox_draw
jmp main_loop
.enter:
mov [textbox_active], 0
call textbox_draw
jmp main_loop
.backspace:
movzx ecx, [textbox_position]
test ecx, ecx
jz main_loop
mov [textbox_string + ecx], byte 0
dec [textbox_position]
call textbox_draw
jmp main_loop
 
button:
mcall MF_GETBUTTON
cmp ah, 0x10
je play_button
cmp ah, 0x11
je stop_button
cmp ah, 0x12
je decr_button
cmp ah, 0x13
je incr_button
cmp ah, 0x14
je volm_button
cmp ah, 0x15
je volp_button
cmp ah, 0x20
je activate_textbox
cmp ah, 0x30
je progressbar_click
cmp ah, 1
jne main_loop
 
; mov [status], ST_STOP
; mcall MF_DELAY, 40
ret
 
play_button:
xor eax, eax
xchg al, [textbox_active]
cmp al, 0
je @f
call textbox_draw
@@:
mov [status], ST_PLAY
jmp main_loop
stop_button:
mov [status], ST_STOP
jmp main_loop
 
decr_button:
; mov [status], ST_STOP
; @@:
; mcall 5, 1
; cmp [status], ST_DONE
; jne @b
; movzx esi, [textbox_position]
; add esi, textbox_string
; @@:
; cmp byte [esi], '/'
; je @f
; dec esi
; jmp @b
; @@:
; mov byte [esi+1], 0
; mov [fileinfo.first_block], 0
; mov [fileinfo.dest], WAV_BUFFER1
; mcall 58, fileinfo
; add ebx, WAV_BUFFER1
; mov esi, WAV_BUFFER1+8
; .next_file:
; cmp ebx, esi
; jbe .fin
; cmp word [esi], "WA"
; jne .next_file
; cmp byte [esi+1], "V"
; jne .next_file
; .fin:
 
;mov eax, [fileinfo.first_block]
;cmp eax, 1000
;jnl @f
;mov [fileinfo.first_block], 0
;jmp main_loop
;@@:
;sub [fileinfo.first_block], 1000
;jmp main_loop
 
incr_button:
;add [fileinfo.first_block], 1000
jmp main_loop
 
volm_button:
inc byte [volume]
and byte [volume], 0x1f
jz volp_button
or [volume], 0x10000000
jmp _print_volume
; jmp main_loop
 
volp_button:
dec byte [volume]
and byte [volume], 0x1f
jz volm_button
or [volume], 0x10000000
; jmp main_loop
 
_print_volume:
movzx eax, byte [volume]
neg eax
add eax, 31
dps "Volume: "
dpd eax
newline
jmp main_loop
 
activate_textbox:
cmp [status], ST_DONE
jne main_loop
mov [textbox_active], 1
call textbox_draw
jmp main_loop
 
progressbar_click:
;print "click on progress bar"
cmp [status], ST_DONE
je main_loop
mcall MF_GETMOUSE, MS_COORDS_WINDOW
shr eax, 16 ; get mouse.x
sub eax, 7
test eax, eax
jz @f
imul eax, [file_size]
mov ebx, 286
cdq
div ebx
@@:
;dps "block: "
;dpd eax
;newline
mov [fileinfo.first_block], eax
call draw_progress_bar
jmp main_loop
ret
 
;---------------------------------------------------------------------
 
PBAR_WIDTH = 286
 
draw_window:
mcall MF_DRAWSTATUS, DS_BEGIN
 
mcall MF_WINDOW, <100,299>, <100,72>, 0x03404040
 
; create six buttons
mov edi, 6
mpack ebx, 7, 45
mpack ecx, 24, 13
mov edx, 0x10
mov esi, 0xA0A0A0
@@:
mcall MF_BUTTON
add ebx, 48 shl 16
inc edx
dec edi
jnz @b
 
mcall MF_TEXT, <8,8>, 0x10FFFFFF, header, header.size
 
mcall ,<13,28>, 0x404040, buttons_text, buttons_text.size
sub ebx, 0x00010001
mov ecx, 0xFFFFFF
mcall
 
call draw_progress_bar
call textbox_draw
 
mcall MF_DRAWSTATUS, DS_END
ret
 
;---------------------------------------------------------------------
 
textbox_draw:
mcall MF_BUTTON, <7,285>, <55,10>, 0x60000020
 
mov edx, 0x808080
cmp [textbox_active], 1
jne @f
mov edx, 0xA0A0A0
@@:
mcall MF_BAR, <7,286>, <55,11>
 
movzx esi, [textbox_position]
mcall MF_TEXT, <10,56>, 0x404040, textbox_string
ret
 
;---------------------------------------------------------------------
 
draw_progress_bar:
pushad
 
imul eax, [fileinfo.first_block], PBAR_WIDTH
cdq
div [file_size]
 
push eax
mcall MF_BAR, <7,286>, <41,11>, 0x808080
mcall MF_BUTTON, , , 0x60000030
pop eax
 
mov bx, ax
mov edx, 0xA0A0A0
mcall MF_BAR
 
popad
ret
 
;---------------------------------------------------------------------
 
sz header, "AC'97 WAV player - all PCM audio"
sz buttons_text, " Play Stop << >> Vol- Vol+"
 
textbox_active db 0
textbox_position db textbox_string.size-1
file_size dd 100
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/includes.inc
0,0 → 1,10
include "MACROS.INC"
include "DEBUG.INC"
include "CONSTANT.INC"
include "AC97.INC"
include "PCI.INC"
include "CODEC.INC"
include "FRONTEND.INC"
 
 
MF_PCI = 62
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/macros.inc
0,0 → 1,266
; new application structure
macro meos_app_start
{
use32
org 0x0
 
db 'MENUET01'
dd 0x01
dd __start
dd __end
dd __memory
dd __stack
 
if used __params & ~defined __params
dd __params
else
dd 0x0
end if
 
dd 0x0
}
MEOS_APP_START fix meos_app_start
 
macro code
{
__start:
}
CODE fix code
 
macro data
{
__data:
}
DATA fix data
 
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
}
UDATA fix udata
 
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_APP_END fix meos_app_end
 
 
; macro for defining multiline text data
struc mstr [sstring]
{
forward
local ssize
virtual at 0
db sstring
ssize = $
end virtual
dd ssize
db sstring
common
dd -1
}
 
 
; strings
macro sz name,[data] { ; from MFAR [mike.dld]
common
if used name
label name
end if
forward
if used name
db data
end if
common
if used name
.size = $-name
end if
}
 
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
common
if used name
label name
end if
forward
if (used name)&(lang eq lng)
db data
end if
common
if used name
.size = $-name
end if
}
 
 
 
; easy system call macro
macro mpack dest, hsrc, lsrc
{
if (hsrc eqtype 0) & (lsrc eqtype 0)
mov dest, (hsrc) shl 16 + lsrc
else
if (hsrc eqtype 0) & (~lsrc eqtype 0)
mov dest, (hsrc) shl 16
add dest, lsrc
else
mov dest, hsrc
shl dest, 16
add dest, lsrc
end if
end if
}
 
macro __mov reg,a,b { ; mike.dld
if (~a eq)&(~b eq)
mpack reg,a,b
else if (~a eq)&(b eq)
mov reg,a
end if
}
 
macro mcall a,b,c,d,e,f { ; mike.dld
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
int 0x40
}
 
 
 
 
 
 
; optimize the code for size
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
 
macro add arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
inc arg1
else
add arg1,arg2
end if
else
add arg1,arg2
end if
}
 
macro sub arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
dec arg1
else
sub arg1,arg2
end if
else
sub arg1,arg2
end if
}
 
macro mov arg1,arg2
{
if (arg1 in __regs) & (arg2 eqtype 0)
if (arg2) = 0
xor arg1,arg1
else if (arg2) = 1
xor arg1,arg1
inc arg1
else if (arg2) = -1
or arg1,-1
else if (arg2) > -128 & (arg2) < 128
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
 
 
macro struct name
{
virtual at 0
name name
sizeof.#name = $ - name
end virtual
}
 
; structures used in MeOS
struc process_information
{
.cpu_usage dd ? ; +0
.window_stack_position dw ? ; +4
.window_stack_value dw ? ; +6
.not_used1 dw ? ; +8
.process_name rb 12 ; +10
.memory_start dd ? ; +22
.used_memory dd ? ; +26
.PID dd ? ; +30
.x_start dd ? ; +34
.y_start dd ? ; +38
.x_size dd ? ; +42
.y_size dd ? ; +46
.slot_state dw ? ; +50
rb (1024-52)
}
struct process_information
 
struc system_colors
{
.frame dd ?
.grab dd ?
.grab_button dd ?
.grab_button_text dd ?
.grab_text dd ?
.work dd ?
.work_button dd ?
.work_button_text dd ?
.work_text dd ?
.work_graph dd ?
}
struct system_colors
 
 
; constants
 
; events
EV_IDLE = 0
EV_TIMER = 0
EV_REDRAW = 1
EV_KEY = 2
EV_BUTTON = 3
EV_EXIT = 4
EV_BACKGROUND = 5
EV_MOUSE = 6
EV_IPC = 7
EV_STACK = 8
 
; event mask bits for function 40
EVM_REDRAW = 1b
EVM_KEY = 10b
EVM_BUTTON = 100b
EVM_EXIT = 1000b
EVM_BACKGROUND = 10000b
EVM_MOUSE = 100000b
EVM_IPC = 1000000b
EVM_STACK = 10000000b
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/meosfunc.inc
0,0 → 1,29
MF_WINDOW = 0
MF_GETKEY = 2
MF_TEXT = 4
MF_DELAY = 5
MF_BUTTON = 8
MF_PROCINFO = 9
PN_MYSELF = -1
MF_WAIT_EVENT = 10
MF_DRAWSTATUS = 12
DS_BEGIN = 1
DS_END = 2
MF_BAR = 13
MF_GETBUTTON = 17
MF_WAIT_EVENT_TIMEOUT = 23
MF_GETMOUSE = 37
MS_COORDS_WINDOW = 1
MF_PORTS = 46
PRT_RESERVE = 0
PRT_FREE = 1
MF_THREAD = 51
THR_CREATE = 1
MF_SYSTREE = 58
MF_PCI = 62
MF_EXIT = -1
MF_INTERNAL_SERVICES = 68
ALLOC_PHYS_MEM =5
FREE_PHYS_MEM =6
SET_PHYS_BUFFER =7
GET_PHYS_BUFFER =8
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/ac97wav/trunk/pci.inc
0,0 → 1,46
PCI_CMD_REG = 04h ; reg 04, command reg
IO_ENA = 0x00000001 ; i/o decode enable
MEM_ENA = 0x00000002 ; memory decode enable
BM_ENA = 0x00000004 ; bus master enable
 
pciRegRead8: ; register in CL!
mov bl, 4
mov bh, [bus]
mov ch, [devfn]
mcall MF_PCI
ret
 
pciRegRead16:
mov bl, 5
mov bh, [bus]
mov ch, [devfn]
mcall MF_PCI
ret
 
pciRegRead32:
mov bl, 6
mov bh, [bus]
mov ch, [devfn]
mcall MF_PCI
ret
 
pciRegWrite8: ; value in DL!
mov bl, 8
mov bh, [bus]
mov ch, [devfn]
mcall MF_PCI
ret
 
pciRegWrite16:
mov bl, 9
mov bh, [bus]
mov ch, [devfn]
mcall MF_PCI
ret
 
pciRegWrite32:
mov bl, 10
mov bh, [bus]
mov ch, [devfn]
mcall MF_PCI
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property