PT3 shorter replayer

Página 1/3
| 2 | 3

Por dioniso

Champion (474)

Imagen del dioniso

25-11-2005, 19:16

Hi.

Could someone try this code? It's supossed to free 500 bytes in RAM (compared to previous PT3 player version).

Delete first 100 bytes from the PT3 module (part of the header).
Replayer is already around 400 bytes shorter.

Before INITialite the module (CALL INIT) load the song in HL but substract 100 to that address. For instance, if your song is pasted at the end of the code (in label MDLADDR) just do this:

ld hl,MDLADDR-100
call init

I don't have a MSX here to test it so ... just emulators. Fingers crossed.

I won't be able to modify the code this weekend but if there's something that doesn't work I'll try to "repair" it next Monday.

New PT3 replayer

Login sesión o register para postear comentarios

Por ARTRAG

Enlighted (6234)

Imagen del ARTRAG

25-11-2005, 22:14

I have just emulators as well.

BTW have you ever seen a ZXspec demo named apology that is a demonstration of producing 6-channel sound from the 3-channel AY?
The idea that appears from the code (that is open) is genial apart from a bug in the use of AY levels that implies some non linear artifacts.

As far as i can see the player is CPU intensive, but much lighter that a PCM player, as the sole task that
the z80 have, is counting the period duration of the 6 squared waves.
Actually, while counting, you can do also other things.

have a look
http://www.west.co.tt/matt/speccy/apology/

PS
the error in the AY levels can be easily corrected...

PPS
PT3 files ues 3 channels, but with 6 channels one could do many things

Por dioniso

Champion (474)

Imagen del dioniso

26-11-2005, 16:47

have a look
http://www.west.co.tt/matt/speccy/apology/

... my name is there ... OK, he wrote Dioniso Hernández, which is false. He should have written only Dioniso. Matt Westcott (aka Gasman) is a source of knowledge related to the AY, Z80 assembler and C.

Por ARTRAG

Enlighted (6234)

Imagen del ARTRAG

26-11-2005, 17:45

If you know the demo I need to point you that
the aplogy player has a problem with the AY levels that
are NOT linear.

Look at this example:

let x be the value corresponding to the first channal of the AY (let's say CHA),
bchan,cchan are the logical channels mapped on this sole phisical channel

for bchan = off & cchan = off, Apology uses x=0
for bchan = on & cchan = off, Apology uses x=8
for bchan = off & cchan = on, Apology uses x=7
for bchan = on & cchan = on, Apology uses x=15

But this means a very distorted square wave as the resulting levels are

for bchan = off & cchan = off, use x=0 => CHA = 0
for bchan = on & cchan = off, use x=8 => CHA = 0,0884
for bchan = off & cchan = on, use x=7 => CHA = 0,0626
for bchan = on & cchan = on, use x=15 => CHA = 1

this is due to the fact that the volume levels go like 2^(x/2)/2^(7,5)

the corrrect strategy should be

for bchan = off & cchan = off, use x=0 => CHA = 0
for bchan = on & cchan = off, use x=13 => CHA = 0,5
for bchan = off & cchan = on, use x=15 => CHA = 0,5
for bchan = on & cchan = on, use x=15 => CHA = 1

I was thinking to a port of the (corrected) algorithm to msx...

Por ARTRAG

Enlighted (6234)

Imagen del ARTRAG

26-11-2005, 19:51

I was thinking to somethig like this



        ld  a,5
        call #5f
        
        ld a,7      ; turn off AY's wave generator.
        out (#A0),a
        ld a,63
        out (#a1),a


main    di
        vdpw 15,1
loop
        ld  a,(splitline)
        add a,4                    ; this should mean a max freq of 3200Hz : this gives almost 7 octaves
        ld  (splitline),a

        vdp 19
        wait_FH

        exx
        ; update noteperiods here
        exx
    

        dec b           ; the wonderful main loop.
        jp  z,bchan    ; shadow registers b, c, d, e, h, l
1       dec c           ; contain period counters for each channel.
        jp  z,cchan    ; When they reach zero,
3       dec d           ; do something important.
        jp  z,dchan
3       dec e
        jp  z,echan
4       dec h
        jp  z,hchan
5       dec l
        jp  z,lchan
6    
    
        exx
        ; do other things
        exx
    
        call    testesc
        jp nz,loop
        
        vdpw 15,0
        ei

        xor a
        call #5f

        ret

where i still need to update the xchan parts

Por jltursan

Prophet (2159)

Imagen del jltursan

26-11-2005, 21:31

I've just tested the code and seems to work fine in MSX1, MSX2 and TR. The only minor flaw is a short fuzzy noise at the beginning of the song, it doesn't sound at the begginning of the loop anyway...

Por dioniso

Champion (474)

Imagen del dioniso

27-11-2005, 11:37

ARTRAG: I was thinking to somethig like this ... where i still need to update the xchan parts

That would be very very interesting, ARTRAG. Can you release the whole replayer? Maybe you can comment that on Gasman too. I'm sure he'll be very interested too.

jltursan: I've just tested the code and seems to work fine in MSX1, MSX2 and TR. The only minor flaw is a short fuzzy noise at the beginning of the song, it doesn't sound at the begginning of the loop anyway...

... sh1t! That is a problem of initialization, I would say, related to register 6. Sadly, I can't veryfy that right now. Tomorrow ... Thanks for testing it.

Por KNM

Master (172)

Imagen del KNM

27-11-2005, 19:10

6 Channels from PSG?That´s a COOL thing Big smile

Por ARTRAG

Enlighted (6234)

Imagen del ARTRAG

28-11-2005, 19:48

Apology code in MSX version at the current state of developement.

Open problems:
1) the VDP Hblank interrupt has an UGE gap during the vertical retrace.
In openmsx and in blue I see all the upper border without interrupts.
The resulting sound has a 50Hz interference !!
Is this effect a true HW behaviour of the VDP or a lack in the emulators?

2) In case the behaviour is true and confirmed, how to get a different external
source of syncronization in the MSX2 HW? Any idea?

Here follows the code:


    OUTPUT  apo.com
    org #100

    INCLUDE macro.asm


        
        ld a,7          ; turn off AY's wave generator.
        out (#A0),a
        ld a,63
        out (#a1),a

        ld  ix,vols
        ld  iyl,0

        ld  bc,#11      ; init alll counters
        ld  de,bc
        ld  hl,bc

main    di
        vdpw 15,1
        vdpw 19,iyl
                
loop
        wait_FH
    
        dec b           ; the wonderful main loop.
        call  z,bchan     ; registers b, c, d, e, h, l
        dec c           ; contain period counters for each channel.
        call  z,cchan     ; When they reach zero,
        dec d           ; do something important.
        call  z,dchan
        dec e
        call  z,echan
        dec h
        call  z,hchan
        dec l
        call  z,lchan

        vdpw    7,iyl

        ld  a,4
        add a,iyl
        ld  iyl,a
        vdp 19
        jp  nz,loop         
        
;        exx             ; update note period only at 50Hz
;datpos  ld hl,dat       ; store here note lenght
;
;        ld a,(hl)
;        ld (bchan+1),a
;        inc hl
;
;        ld a,(hl)
;        ld (cchan+1),a
;        inc hl
;
;        ld a,(hl)
;        ld (dchan+1),a
;        inc hl
;
;        ld a,(hl)
;        ld (echan+1),a
;        inc hl
;
;        ld a,(hl)
;        ld (hchan+1),a
;        inc hl
;
;        ld a,(hl)
;        ld (lchan+1),a
;        inc hl
;
;        ld a,(hl)
;        or a
;        jr z,fin
;        inc hl
;        ld (datpos+1),hl
;        exx
    
        call    testesc          
        jp nz,loop
fin        
        vdpw 15,0
        ei

        vdpw 7,#F4

        ret

;------------------
bchan   ld b,0      ; note period will be poked here -
        ld a,8      ; select AY channel A volume register
        out (#A0),a
        ld a,01b    ; we will flip b0 to generate tone
        jp 11F

cchan   ld c,0      ; note period will be poked here -
        ld a,8      ; use AY channel A here, too
        out (#A0),a
        ld a,10b    ; we will flip b1 this time
11
.rechan  xor 0           ; flip the appropriate bits of the
        ld (.rechan+1),a   ; stored levels
        ld (.tabvol+2),a   
        
.tabvol ld  a,(ix+0)
        out (#A1),a   ; and write back to the AY
	  ret
;------------------
dchan   ld d,0  ; do exactly the same thing
        ld a,9  ; for all other channels
        out (#A0),a
        ld a,01b
        jp 11F
        
echan   ld e,0
        ld a,9
        out (#A0),a
        ld a,10b
11
.rechan  xor 0           ; flip the appropriate bits of the
        ld (.rechan+1),a   ; stored levels 
        ld (.tabvol+2),a   
        
.tabvol ld  a,(ix+0)
        out (#A1),a
        ret
;------------------
hchan   ld h,0
        ld a,10
        out (#A0),a
        ld a,01b
        jp 11F
        
lchan   ld l,0
        ld a,10
        out (#A0),a
        ld a,10b
11
.rechan  xor 0           ; flip the appropriate bits of the
        ld (.rechan+1),a   ; stored levels 
        ld (.tabvol+2),a   
        
.tabvol ld  a,(ix+0)
        out (#A1),a
        ret
;------------------

;************************************************************
; Test if esc key is pressed.
; If pressed, z flag is positioned to 0
;************************************************************
testesc:
        in a,(#aa)
        and %11110000
        add a,7
        out (#aa),a
        in a,(#a9)
        and 4
        ret

vols    db  0,13,13,15


dat     
        db 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,0

Por ARTRAG

Enlighted (6234)

Imagen del ARTRAG

30-11-2005, 01:51

Final version !!!

This is the msx version of Matt Westcott's PSG 6 channel player for Spectrum.
As far as I can understand, this version corrects a problem of the original source
due to the non linear behaviour of the DAC in the PSG.
Thanks to Matt Westcott (aka Gasman) for its idea and code (and music)!!


        OUTPUT  apo.com
        org #100
          
        ld a,7          ; turn off AY's wave generator.
        out (#A0),a
        ld a,63
        out (#a1),a

        ld  ix,vols

        ld  bc,#11      ; init all counters
        ld  de,bc
        ld  hl,bc

main    di

mainloop
               
        exx             ; update note period only at 50Hz
datpos  ld hl,dat       ; store here note lenght

        ldi a,(hl)
        ld (bchan+1),a

        ldi a,(hl)
        ld (cchan+1),a

        ldi a,(hl)
        ld (dchan+1),a

        ldi a,(hl)
        ld (echan+1),a

        ldi a,(hl)
        ld (hchan+1),a

        ldi a,(hl)
        ld (lchan+1),a

        ldi a,(hl)
        or a
        jp z,fin
        ld (datpos+1),hl

        exx
 
        ld  iyh,a
        ld  iyl,0        
loop
        dec b           ; the wonderful main loop.
        call  z,bchan     ; registers b, c, d, e, h, l
        dec c           ; contain period counters for each channel.
        call  z,cchan     ; When they reach zero,
        dec d           ; do something important.
        call  z,dchan
        dec e
        call  z,echan
        dec h
        call  z,hchan
        dec l
        call  z,lchan

        dec iyl
        jp  nz,loop                 
        dec iyh
        jp  nz,loop         

        jp  mainloop
fin        
        ei

        ret

;------------------
bchan   ld b,0      ; note period will be poked here -
        ld a,8      ; select AY channel A volume register
        out (#A0),a
        ld a,01b    ; we will flip b0 to generate tone
        jp 1F

cchan   ld c,0      ; note period will be poked here -
        ld a,8      ; use AY channel A here, too
        out (#A0),a
        ld a,10b    ; we will flip b1 this time
1
.rechan xor 0           ; flip the appropriate bits of the
        ld (.rechan+1),a   ; stored levels
        ld (.tabvol+2),a   
.tabvol ld  a,(ix+0)
        out (#A1),a   ; and write back to the AY
        ret
;------------------
dchan   ld d,0  ; do exactly the same thing
        ld a,9  ; for all other channels
        out (#A0),a
        ld a,01b
        jp 1F
        
echan   ld e,0
        ld a,9
        out (#A0),a
        ld a,10b
1
.rechan xor 0           ; flip the appropriate bits of the
        ld (.rechan+1),a   ; stored levels 
        ld (.tabvol+2),a   
.tabvol ld  a,(ix+0)
        out (#A1),a
        ret
;------------------
hchan   ld h,0
        ld a,10
        out (#A0),a
        ld a,01b
        jp 1F
        
lchan   ld l,0
        ld a,10
        out (#A0),a
        ld a,10b
1
.rechan xor 0           ; flip the appropriate bits of the
        ld (.rechan+1),a   ; stored levels 
        ld (.tabvol+2),a   
.tabvol ld  a,(ix+0)
        out (#A1),a
        ret
;------------------


vols    db  0,13,13,15


dat   
        db 1Fh,27h,34h,4Fh,67h,1Fh,38h,29h,37h,42h,52h,6Eh,A8h,38h,1Eh,28h
        db 3Ch,5Fh,76h,BAh,50h,24h,28h,3Dh,48h,61h,BBh,60h,1Ah,27h,34h,4Eh
        db 4Fh,7Ch,78h,24h,28h,35h,47h,6Bh,6Bh,40h,24h,2Ah,3Bh,47h,6Bh,D5h
        db 38h,1Eh,2Ah,3Bh,47h,6Bh,D5h,48h,20h,28h,3Fh,50h,6Ah,9Fh,30h,1Ah
        db 35h,3Fh,4Fh,6Ah,9Fh,38h,13h,1Eh,25h,3Ch,5Bh,B6h,70h,23h,27h,47h
        db 38h,5Fh,B6h,40h,14h,22h,28h,44h,65h,C9h,60h,27h,2Ah,4Fh,5Eh,7Fh
        db BCh,50h,49h,56h,56h,6Dh,7Dh,D8h,30h,3Dh,49h,56h,6Dh,6Dh,D8h,30h
        db 40h,51h,51h,6Dh,A3h,D8h,30h,35h,40h,4Fh,6Ah,6Ah,9Ch,38h,1Fh,33h
        db 3Dh,67h,3Dh,9Eh,60h,3Bh,3Fh,5Eh,6Ah,6Ah,9Ch,50h,22h,39h,51h,6Ah
        db A4h,A4h,60h,3Eh,46h,6Ah,6Ah,A6h,A6h,60h,3Bh,4Fh,5Eh,78h,BDh,BBh
        db 2Ch,2Fh,4Fh,5Eh,78h,BDh,BBh,2Ch,29h,3Bh,52h,67h,8Bh,CDh,2Ch,22h
        db 3Ah,52h,67h,8Ah,CDh,34h,16h,21h,2Ch,6Fh,DEh,DDh,58h,28h,2Dh,51h
        db 76h,74h,E7h,50h,19h,25h,32h,4Bh,97h,EAh,50h,2Eh,34h,4Eh,5Ch,82h
        db FFh,50h,28h,3Ah,52h,89h,CFh,CFh,2Ch,22h,3Ah,52h,89h,CFh,CFh,2Ch
        db 1Ch,2Ch,38h,4Bh,5Ah,9Dh,2Ch,2Dh,4Dh,39h,4Ch,5Bh,9Dh,30h,34h,3Ah
        db 45h,68h,A6h,A6h,50h,28h,3Ah,52h,89h,CFh,CFh,28h,22h,3Ah,52h,89h
        db CFh,CFh,28h,1Ch,2Ch,38h,4Bh,5Ah,9Dh,28h,2Dh,4Dh,39h,4Ch,5Bh,9Dh
        db 30h,34h,3Ah,45h,68h,A6h,A6h,50h,28h,3Ah,52h,89h,CFh,CFh,30h,22h
        db 3Ah,52h,89h,44h,CFh,30h,1Ch,2Eh,38h,4Bh,60h,9Eh,24h,26h,4Bh,61h
        db 74h,61h,F3h,24h,30h,61h,EAh,74h,61h,F3h,28h,34h,44h,67h,8Fh,A4h
        db A4h,40h,34h,4Eh,67h,9Ah,BAh,BAh,40h,34h,52h,6Ah,6Bh,D6h,D7h,30h
        db 3Bh,4Fh,5Eh,6Bh,D6h,D7h,30h,46h,53h,69h,76h,D6h,D7h,60h,1Dh,24h
        db 31h,49h,61h,8Fh,40h,25h,32h,3Ah,4Ah,64h,93h,40h,1Bh,24h,36h,56h
        db 6Ah,ABh,40h,21h,25h,38h,42h,58h,ABh,48h,18h,24h,30h,74h,92h,FBh
        db 70h,21h,25h,31h,42h,63h,C5h,30h,21h,27h,31h,42h,63h,C5h,30h,1Ch
        db 27h,31h,42h,63h,C5h,48h,1Dh,25h,31h,49h,63h,92h,A0h,00h

Por AuroraMSX

Paragon (1901)

Imagen del AuroraMSX

30-11-2005, 11:14

...
        ldi a,(hl)
...
        ld  iyh,a
        ld  iyl,0        
...
        dec iyl
...
        dec iyh


I have seen IYh and IYl before - undocumented z80 instructions.
But ldi a,(hl) is a new one! Is that also an undocumented instruction, or just some macro which does

        ld   a
        inc  hl

?

Página 1/3
| 2 | 3