software/dmaplayw: modified like `keymap` and improved

This commit is contained in:
Ivan Tatarinov 2021-06-12 12:21:22 +03:00
parent 6d19576ef0
commit 6c35e881ba
1 changed files with 116 additions and 72 deletions

View File

@ -1,6 +1,6 @@
; dmaplayw.asm - play an audio file using the SpecDrum and DMA at 15.625 kHz. ; dmaplayw.asm - play an audio file using the SpecDrum and DMA at 15.625 kHz.
; ;
; Copyright (C) 2017 AZXUNO association ; Copyright (C) 2017-2021 AZXUNO association
; Contributors: ; Contributors:
; 2021 Ivan Tatarinov <ivan-tat@ya.ru> ; 2021 Ivan Tatarinov <ivan-tat@ya.ru>
; ;
@ -17,7 +17,7 @@
; You should have received a copy of the GNU General Public License ; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>. ; along with this program. If not, see <https://www.gnu.org/licenses/>.
; ;
; SPDX-FileCopyrightText: Copyright (C) 2017 AZXUNO association ; SPDX-FileCopyrightText: Copyright (C) 2017-2021 AZXUNO association
; ;
; SPDX-FileContributor: 2021 Ivan Tatarinov <ivan-tat@ya.ru> ; SPDX-FileContributor: 2021 Ivan Tatarinov <ivan-tat@ya.ru>
; ;
@ -28,8 +28,11 @@
; output DMAPLAYW ; output DMAPLAYW
define PROGRAM "dmaplayw" define PROGRAM "dmaplayw"
define VERSION "0.1" define VERSION "0.1"
define DESCRIPTION "Plays an audio file using the", 13, "SpecDrum and DMA at 15.625 kHz"
define COPYRIGHT 127, " 2017-2021 AZXUNO association"
define LICENSE "License: GNU GPL 3.0 or above"
include "zxuno.def" include "zxuno.def"
include "esxdos.def" include "esxdos.def"
@ -40,29 +43,50 @@
; Prescaler for timed DMA. The count goes from 0 to 223, that is, 224 cycles ; Prescaler for timed DMA. The count goes from 0 to 223, that is, 224 cycles
define DMA_PRESCALER CPU_FREQ / SPECDRUM_FREQ - 1 define DMA_PRESCALER CPU_FREQ / SPECDRUM_FREQ - 1
org $2000 ; entry point of ESXDOS program define DMA_BUFSIZE 2048 ; DMA buffer size
org $2000 ; entry point of ESXDOS program
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
; Subroutine ; Subroutine
; In: HL = pointer to the command line arguments string (ASCIIZ) ; In: HL = pointer to the command line arguments string (ASCIIZ)
Main ld a, h Main: ld a, h
or l or l
jp nz, Init jr nz, Init
ld hl, aUsage ; jr ShowUsage ; No need, it follows
.PrintLoop ld a, (hl)
or a
ret z ; Return on string end
rst $10
inc hl
jr .PrintLoop
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
; Subroutine ; Subroutine
; In: HL = pointer to the command line arguments (filename)
GetFileName ld de, BufferFileName ShowUsage: ld hl, aUsage
.CheckCharacter ld a, (hl) ; jr Print ; No need, it follows
;-----------------------------------------------------------------------------
; Subroutine
; In: HL = pointer to an ASCIIZ string
Print: ld a, (hl)
or a
ret z ; Return on string end
rst $10
inc hl
jr Print
;-----------------------------------------------------------------------------
; Subroutine
; In: HL = pointer to the command line arguments string (ASCIIZ)
Init: ld de, FileName
; call GetFileName ; inline
;-----------------------------------------------------------------------------
; Subroutine
; In: HL = pointer to the command line arguments (filename)
; DE = pointer to the output ASCIIZ string (filename)
; Out: DE = pointer to terminating 0 character of output string
.GetFileName: ld a, (hl)
or a or a
jr z, .End jr z, .End
cp " " cp " "
@ -72,30 +96,21 @@ GetFileName ld de, BufferFileName
cp 13 cp 13
jr z, .End jr z, .End
ldi ldi
jr .CheckCharacter jr .GetFileName
.End xor a .End: xor a
ld (de), a ld (de), a
inc de ; DE remains pointing to the buffer that is needed in OPEN, I don't know what for ; ret ; skipped
ret
; 01234567890123456789012345678901 ; continue Init()
aUsage db " .", PROGRAM, " audiofile.wav", 13 inc de ; DE remains pointing to the buffer that is
db 13 ; needed in OPEN, I don't know what for
db "Plays an audio file using the", 13
db "SpecDrum and DMA at 15.625 kHz", 13, 0
;-----------------------------------------------------------------------------
; Subroutine
; In: HL = pointer to the command line arguments string (ASCIIZ)
Init call GetFileName ; results DE = buffer for OPEN
xor a xor a
esxdos M_GETSETDRV ; A = current unit esxdos M_GETSETDRV ; A = current drive
ld b, FA_READ ; B = opening mode ld b, FA_READ ; B = file open mode
ld hl, BufferFileName ; HL = pointer to file name (ASCIIZ) ld hl, FileName ; HL = pointer to filename (ASCIIZ)
esxdos F_OPEN esxdos F_OPEN
ret c ; Return on error ret c ; Return on error
ld (FHandle), a ld (FileHandle), a
ld l, SEEK_START ld l, SEEK_START
ld bc, 0 ld bc, 0
ld de, 44 ; Skip 44 bytes from start (WAV header) ld de, 44 ; Skip 44 bytes from start (WAV header)
@ -103,13 +118,40 @@ Init call GetFileName ; results DE = buffer for OPEN
ret c ; Return on error ret c ; Return on error
ld hl, ScreenAddr ld hl, ScreenAddr
ld de, ScreenAddr+1 ld de, ScreenAddr+1
ld bc, 31 ld bc, 32-1
ld (hl), 255 ld (hl), 255
ldir ; This line will be deleted on the first wave plot ldir ; This line will be deleted on the first wave plot
ld hl, ScreenLines ; Fill ScreenLines
ld de, ScreenAddr ; with screen lines addresses
ld b, (192-1)+1 ; 191 repeats
.LineDownLoop: ld (hl), e
inc hl
ld (hl), d
inc hl
; Calculate next line (down one line)
inc d ; D = (D + 1) & 255
ld a, d ; A = D
and %00000111 ; A = D & 7, CY = 0
jr nz, .SamePart ; if (D & 7) goto SamePart
ld a, e ; A = E
sub a, -32 ; A = (E + 32) & 255, CY = !A
ld e, a ; E = (E + 32) & 255, CY = !E
sbc a, a ; A = -CY
and %11111000 ; A = -8 * CY
add a, d ; A = (D - 8 * CY) & 255
ld d, a ; D = (D - 8 * CY) & 255
.SamePart: djnz .LineDownLoop
; ld hl, WaveBuffer ; HL already points to WaveBuffer
ld de, WaveBuffer+1
ld bc, 256-1 ; B = 0
ld (hl), b
ldir ; Clear WaveBuffer
ld hl, DMABuffer ld hl, DMABuffer
ld de, DMABuffer+1 ld de, DMABuffer+1
ld bc, DMABuffer_Len-1 ld bc, DMA_BUFSIZE-1
ld (hl), 0 ld (hl), 0
ldir ; Clear DMA buffer ldir ; Clear DMA buffer
@ -140,7 +182,7 @@ Init call GetFileName ; results DE = buffer for OPEN
ld a, dma_len ld a, dma_len
out (c), a out (c), a
inc b ; BC = zxuno_data inc b ; BC = zxuno_data
ld hl, DMABuffer_Len ld hl, DMA_BUFSIZE
out (c), l out (c), l
out (c), h out (c), h
dec b ; BC = zxuno_port dec b ; BC = zxuno_port
@ -157,7 +199,7 @@ Init call GetFileName ; results DE = buffer for OPEN
ld a, %00000111 ; Mem to I/O, redisparable, timed, source address is checked ld a, %00000111 ; Mem to I/O, redisparable, timed, source address is checked
out (c), a out (c), a
dec b ; BC = zxuno_port dec b ; BC = zxuno_port
.PlayLoop ld bc, $7ffe ; SPACE halfrow .PlayLoop: ld bc, $7ffe ; SPACE halfrow
in a, (c) in a, (c)
and %00000001 and %00000001
jp z, .ExitPlay jp z, .ExitPlay
@ -165,7 +207,7 @@ Init call GetFileName ; results DE = buffer for OPEN
ld a, dma_stat ld a, dma_stat
out (c), a out (c), a
inc b ; BC = zxuno_data inc b ; BC = zxuno_data
.StillInSecondHalf .StillInSecondHalf:
in a, (c) in a, (c)
bit 7, a bit 7, a
jr z, .StillInSecondHalf jr z, .StillInSecondHalf
@ -173,7 +215,7 @@ Init call GetFileName ; results DE = buffer for OPEN
ld a, dma_prob ld a, dma_prob
out (c), a out (c), a
inc b ; BC = zxuno_data inc b ; BC = zxuno_data
ld hl, DMABuffer + DMABuffer_Len/2 ld hl, DMABuffer + DMA_BUFSIZE/2
out (c), l out (c), l
out (c), h out (c), h
dec b ; BC = zxuno_port dec b ; BC = zxuno_port
@ -183,23 +225,23 @@ Init call GetFileName ; results DE = buffer for OPEN
in a, (c) in a, (c)
; Fill second half of buffer with audio data ; Fill second half of buffer with audio data
ld hl, DMABuffer + DMABuffer_Len/2 ld hl, DMABuffer + DMA_BUFSIZE/2
ld bc, DMABuffer_Len/2 ld bc, DMA_BUFSIZE/2
ld a, (FHandle) ld a, (FileHandle)
esxdos F_READ esxdos F_READ
jp c, .ExitPlay ; End read on error jp c, .ExitPlay ; End read on error
ld a, b ld a, b
or c or c
jp z, .ExitPlay ; End read on end of data jp z, .ExitPlay ; End read on end of data
ld hl, DMABuffer + DMABuffer_Len/2 ld hl, DMABuffer + DMA_BUFSIZE/2
call PlotWave call PlotWave
ld bc, zxuno_port ld bc, zxuno_port
ld a, dma_stat ld a, dma_stat
out (c), a out (c), a
inc b ; BC = zxuno_data inc b ; BC = zxuno_data
.StillInFirstHalf .StillInFirstHalf:
in a, (c) in a, (c)
bit 7, a bit 7, a
jr z, .StillInFirstHalf jr z, .StillInFirstHalf
@ -219,8 +261,8 @@ Init call GetFileName ; results DE = buffer for OPEN
; Fill first half of buffer with audio data ; Fill first half of buffer with audio data
ld hl, DMABuffer ld hl, DMABuffer
ld bc, DMABuffer_Len/2 ld bc, DMA_BUFSIZE/2
ld a, (FHandle) ld a, (FileHandle)
esxdos F_READ esxdos F_READ
jp c, .ExitPlay ; End read on error jp c, .ExitPlay ; End read on error
ld a, b ld a, b
@ -232,7 +274,7 @@ Init call GetFileName ; results DE = buffer for OPEN
jp .PlayLoop jp .PlayLoop
.ExitPlay ld bc, zxuno_port .ExitPlay: ld bc, zxuno_port
ld a, dma_ctrl ld a, dma_ctrl
out (c), a out (c), a
inc b ; BC = zxuno_data inc b ; BC = zxuno_data
@ -240,21 +282,19 @@ Init call GetFileName ; results DE = buffer for OPEN
out (c), a out (c), a
dec b ; BC = zxuno_port dec b ; BC = zxuno_port
ld a, (FHandle) ld a, (FileHandle)
esxdos F_CLOSE esxdos F_CLOSE
or a ; Clear carry flag or a ; Return to ESXDOS without errors (CY=0)
ei ei
ret ret
FHandle db 0
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
; Subroutine ; Subroutine
PlotWave ld de, BufferCleared PlotWave: ld de, WaveBuffer
ld c, 0 ld c, 0
.Loop ld a, (de) .Loop: ld a, (de)
ld b, a ld b, a
call Plot call Plot
ld a, (hl) ld a, (hl)
@ -275,14 +315,14 @@ PlotWave ld de, BufferCleared
; In: B = y ; In: B = y
; C = x ; C = x
Plot push bc Plot: push bc
push de push de
push hl push hl
ld e, b ld e, b
ld d, 0 ; DE = y ld d, 0 ; DE = y
sla e sla e
rl d ; DE = DE*2 rl d ; DE = DE*2
ld hl, DirScan ld hl, ScreenLines
add hl, de ; HL = pointer to the address of the first pixel of Y add hl, de ; HL = pointer to the address of the first pixel of Y
ld e, (hl) ld e, (hl)
inc hl inc hl
@ -296,7 +336,7 @@ Plot push bc
add hl, bc ; HL contains the address to paint the pixel add hl, bc ; HL contains the address to paint the pixel
ld a, d ; restore X coordinate ld a, d ; restore X coordinate
and %00000111 and %00000111
ld de, DirBits ld de, PixelMask
add a, e add a, e
ld e, a ld e, a
ld a, d ld a, d
@ -310,25 +350,29 @@ Plot push bc
pop bc pop bc
ret ret
DirBits ; 01234567890123456789012345678901
aUsage: db PROGRAM, " version ", VERSION, 13
db DESCRIPTION, 13
db COPYRIGHT, 13
db LICENSE, 13
db 13
db "Usage:", 13
db " .", PROGRAM, " audiofile.wav", 13, 0
FileHandle: db 0
i = %10000000 i = %10000000
while i > 0 PixelMask: dup 8
db i db i
i = i / 2 i = i / 2
endw edup
DirScan ScreenLines: org $+192*2
y = 0
while y < 192
dw ScreenAddr + (256 * (y & 7)) + (32 * ((y / 8) & 7)) + (64 * 32 * (y / 64))
y = y + 1
endw
BufferCleared ds 256 WaveBuffer: org $+256
BufferFileName: equ $ ; Rest of RAM for filename FileName: ; Rest of RAM for filename
ScreenAddr: equ $4000 ScreenAddr: equ $4000
DMABuffer: equ $8000 ; DMA buffer start address (circular play buffer) DMABuffer: equ $8000 ; DMA buffer start address (circular play buffer)
DMABuffer_Len: equ 2048 ; DMA buffer length