AY Magic version for ZX81 was born

edited August 2011 in Hardware
Modified Ay magic ,my previous interface for zx48. On board, ay chip based on Zonx interface but with stereo output and rampack 16 or 32 kilo on board. I back to life from long break.Regards,Zaxon.
Post edited by zaxon on

Comments

  • edited May 2011
    Any photos?
  • edited May 2011
    zaxon wrote: »
    Modified Ay magic ,my previous interface for zx48. On board, ay chip based on Zonx interface but with stereo output and rampack 16 or 32 kilo on board. I back to life from long break.Regards,Zaxon.

    So it's an AY interface for the '81 using the same ports as the Speccy 128? I'm fairly sure Bruno was asking about something like this a while back. Got any tracker stuff working on it?
  • edited May 2011
    It's compatible with the most popular ZX81 standard: ZonX.
    ZX81/ZX Spectrum/Amiga/Atari music: http://yerzmyey.i-demo.pl/
  • edited May 2011
    These are of course good news, but if we had a way to enjoy the huge library of Spectrum AY tunes it would make it even better. I'm going to have to revisit the old topic I started a long time ago and see how complicated it would be. I do remember Gasman saying the tunes would sound different but not too much. Imagine being able to use all trackers and tunes that already exist and easily use them for the ZX81!
  • edited May 2011
    zxbruno wrote: »
    These are of course good news, but if we had a way to enjoy the huge library of Spectrum AY tunes it would make it even better. I'm going to have to revisit the old topic I started a long time ago and see how complicated it would be. I do remember Gasman saying the tunes would sound different but not too much. Imagine being able to use all trackers and tunes that already exist and easily use them for the ZX81!

    All you have to do is change the I/O ports to match whatever the ZX81 standard is. Providing you know what the clock of the AY is you just use an appropriate note table and it will sound exactly the same, assuming 50Hz interrupt driven sound, and that the 81 is running in fast mode.
  • edited May 2011
    I second Andrew with that, it would be enough to have written a proper convector.
    ZX81/ZX Spectrum/Amiga/Atari music: http://yerzmyey.i-demo.pl/
  • edited May 2011
    Ok, let's make it interesting then. :)

    Yerzmyey, how soon can we expect some ZX81 tunes from you? :)
    Can the ZX81 AY interface be used to play digital samples? What about music made with Sample Tracker?
    If a conversion tool can be created and if it can process files in batch mode, people will start hearing more about the ZX81. This will also drive sales of this new interface.

    edit:

    A ZX81 running demos in high-resolution and with AY sound can really compete with the Spectrum!

    If the ZX81 can cope with digital samples, we might start seeing a lot of impressive stuff in terms of ZX81 demos. DivIDEo for the ZX81?
  • edited May 2011
    digital samples?

    Yes, you just need enough RAM to store the data.
    Sample Tracker?

    Not sure how Sample Tracker works but if you give me the clock frequency and port addresses of the AY chip I can write a version of the Vortex Tracker playback routine to support it. And I'm pretty sure Vortex can handle Sample Tracker format files.
    If a conversion tool can be created

    Well you don't really need that, since the raw data doesn't need any modification.
    A ZX81 running demos in high-resolution and with AY sound can really compete with the Spectrum!

    That would be trickier. There may not be enough t-states left in the IM2 routine after pushing all of the video data to do much with the AY.
    If the ZX81 can cope with digital samples, we might start seeing a lot of impressive stuff in terms of ZX81 demos. DivIDEo for the ZX81?

    Well first you'd need a 16-bit IDE device. Not sure if the existing ones are full 16-bit or simple 8-bit interfaces.
  • edited May 2011
    zxbruno wrote: »
    A ZX81 running demos in high-resolution and with AY sound can really compete with the Spectrum!
    In shades of grey...
    I wanna tell you a story 'bout a woman I know...
  • edited May 2011
    aowen:

    > Not sure how Sample Tracker works but if you give me the clock frequency and port addresses of the AY chip I can write a version of the Vortex Tracker playback routine to support it. And I'm pretty sure Vortex can handle Sample Tracker format files.
    Well you don't really need that, since the raw data doesn't need any modification.
    *********
    Well, not really, however I wouldn't start from such hard things.
    For the start it would be really cool to have a regular VortexTracker procedure ported to ZX81 ports + *.p file output (with player). :)
    ZX81/ZX Spectrum/Amiga/Atari music: http://yerzmyey.i-demo.pl/
  • edited May 2011
    karingal wrote: »
    In shades of grey...

    you just need a CBS colour wheel!


    hmm, control a stepper motor driver from an I/O output... MUST STOP SELF DAYDREAMING BEFORE DOING SOMETHING STUPID LIKE BUILD ONE :-o

    :)
    My rubbish website including the redrawn Amstrad schematics and the new home of the Sinclair FAQ wiki.
  • edited May 2011
    guesser wrote: »
    you just need a CBS colour wheel!


    hmm, control a stepper motor driver from an I/O output... MUST STOP SELF DAYDREAMING BEFORE DOING SOMETHING STUPID LIKE BUILD ONE :-o

    :)
    Just buy a Spectrum off eBay, much easier...
    I wanna tell you a story 'bout a woman I know...
  • edited May 2011
    Yerzmyey wrote: »
    aowen:

    > Not sure how Sample Tracker works but if you give me the clock frequency and port addresses of the AY chip I can write a version of the Vortex Tracker playback routine to support it. And I'm pretty sure Vortex can handle Sample Tracker format files.
    Well you don't really need that, since the raw data doesn't need any modification.
    *********
    Well, not really, however I wouldn't start from such hard things.
    For the start it would be really cool to have a regular VortexTracker procedure ported to ZX81 ports + *.p file output (with player). :)

    I think you're missing my point. I need the AY clock frequency and port addresses of the AY chip *in order* to port the Vortex Tracker player code to the ZX81. Unless I have the AY clock speed I can't generate the correct values for the required tone table. And unless I have the AY's I/O ports, you won't be able to hear anything.
  • edited May 2011
    Well, found my old ZX81 topic:

    http://www.rwapservices.co.uk/ZX80_ZX81/forums/ay-tunes-on-a-zx81-t12.html

    And here's some interesting info that was give to me by Mike Whynne (creator of EightyOne). Maybe software is all we need to turn the AY Magic into an all-in-one interface?
    Board        Frequency   Register   Select      Data
    Quicksilva   0.8125MHz   0x7fff     0x7ffe      (Memory Mapped, Write Only)
    Zon-X        1.625MHz    0xdf       0x0f
    Fuller       1.625MHz    0x3f       0x5f
    Sinclair     1.7734MHz   0xfdff     0xfdbf
    Timex        1.764MHz    0xf5       0xf6
    

    On that old topic you can see the participation of Mike Whynne, Gasman, etc. The creator of SpecAY also stopped by!
  • edited May 2011
    aowen wrote: »
    I think you're missing my point. I need the AY clock frequency and port addresses of the AY chip *in order* to port the Vortex Tracker player code to the ZX81. Unless I have the AY clock speed I can't generate the correct values for the required tone table. And unless I have the AY's I/O ports, you won't be able to hear anything.

    yes, that's what I meant.
    ZX81/ZX Spectrum/Amiga/Atari music: http://yerzmyey.i-demo.pl/
  • edited May 2011
    Thanks. This is what I needed:
    Board        Frequency   Register   Data
    Zon-X        1.625MHz    0xdf       0x0f
    

    I can see why the OP went for Zon-X rather than Quicksilva compatibility. Once I find my spreadsheet for generating tone tables it will take mere minutes to update the Vortex Tracker routine. However I've got a huge amount of revising to do tonight for an exam tomorrow so you may have to wait until Saturday. On the other hand I'll probably get bored and do it tonight.
  • edited May 2011
    That is really good news - it is good to see Zaxon back on the scene as well - if we can get AY tunes converted to run on the ZX81, then with the ZXpand interface and the release of Nanako in Classic Japanese Monster Castle, 2011 has been a really successful 30th anniversary for the ZX81 (so far!)

    For those not in the know, ZXpand is an SD card interface, with built in configurable 32K RAM. You can even solder a joystick port to the board. We are also working on a daughter-board for ZXpand which will provide AY output based on ZonX too !!
    Supporting Sinclairs since 1986 !

    www.rwapsoftware.co.uk
    www.sellmyretro.com
  • edited May 2011
    The ZXpand is a nifty interface, but did it have to be three times the size of the original MOBO!?
  • edited May 2011
    I must find out if the ZXpand is 8-bit or 16-bit. Must ask SirMorris.
  • edited May 2011
    I just made hardware, Yerzmyey give me clear instructions about stereo, canal mix ,etc for real use. Like my previous AY magic for zx48. Compare my AY magic to AY kempston,made by Lotharek...and cry. My device is projected by proffesional electronic designer, boards is made in good pcb factory i use quality parts, not save fev penny on quartz.
    Just compare: real play from my ay magic:


    And other:

  • edited May 2011
    Oddly enough it looks as if the first note table in ProTracker (which the notes say is not interesting) is actually for an AY clocked at 3.25Mhz/2. This is exactly what is needed so there was no need to do the note calculation.

    So here's a new version of my ProTracker Extreme playback code (music has to be in PT3 v3.6 format and you have to cut the 100 byte header off it). I've cleaned the code up a bit since last time. The routine now supports Zon-X (untested), TC2068/Pentagon, and Spectrum 128. You will need to comment out / uncomment for machines other than the ZX81 (and change the start address).
    ; ProTracker3 Extreme (P3X) player
    ; for ZX81 (Zon-X), TC2068, and Spectrum 128
    
    ; Copyright (c) 2004, 2007 S.V.Bulba <vorobey@mail.khstu.ru>
    
    ; http://bulba.untergrund.net (http://bulba.at.kz)
    ; Formatted by Gasman for Pasmo and optimized by Cheveron
    
    ; variables are 541 bytes long and follow the player
    ; music is in ProTracker3.6 format (minus the 100 byte header)
    
    	org	12288			; any address is valid
    
    init:
    	ld	hl, music - 100
    	jr	p3x_init
    	jp	play
    	jr	mute
    
    setup:
    	defb	0
    
    crpsptr:
    	defw	0
    
    checklp:
    	ld	hl, setup
    	set	7, (hl)
    	bit	0, (hl)
    	ret	z
    	pop	hl
    	ld	hl, delycnt
    	inc	(hl)
    	ld	hl, chana + chp_ntskcn
    	inc	(hl)
    
    mute:
    	xor	a
    	ld	h, a
    	ld	l, a	 
    	ld	(ayregs + ar_ampla), a
    	ld	(ayregs + ar_amplb), hl
    	jp	rout_a0
    
    p3x_init:
    	ld	(modaddr + 1), hl
    	ld	(mdaddr2 + 1), hl
    	push	hl
    	ld	de, 100
    	add	hl, de
    	ld	a, (hl)
    	ld	(p3x_delay + 1), a
    	push	hl
    	pop	ix
    	add	hl, de
    	ld	(crpsptr), hl
    	ld	e, (ix + 2)
    	add	hl, de
    	inc	hl
    	ld	(lposptr + 1), hl
    	pop	de
    	ld	l, (ix + 3)
    	ld	h, (ix + 4)
    	add	hl, de
    	ld	(patsptr + 1), hl
    	ld	hl, 169
    	add	hl, de
    	ld	(ornptrs + 1), hl
    	ld	hl, 105
    	add	hl, de
    	ld	(samptrs + 1), hl
    	ld	hl, setup
    	res	7, (hl)
    
    	ld	de, t_pack		; note table data depacker
    	ld	bc, t1_ + (2 * 49) - 1
    
    tp_0:
    	ld	a, (de)
    	inc	de
    	cp	01eh
    	jr	nc, tp_1
    	ld	h, a
    	ld	a, (de)
    	ld	l, a
    	inc	de
    	jr	tp_2
    tp_1:
    	push	de
    	ld	d, 0
    	ld	e, a
    	add	hl, de
    	add	hl, de
    	pop	de
    tp_2:
    	ld	a, h
    	ld	(bc), a
    	dec	bc
    	ld	a, l
    	ld	(bc), a
    	dec	bc
    	sub	0f0h
    	jr	nz, tp_0
    	ld	hl, vars
    	ld	(hl), a
    	ld	de, vars + 1
    	ld	bc, var0end - vars - 1
    	ldir
    	inc	a
    	ld	(delycnt), a
    	ld	hl, 0f001h
    	ld	(chana + chp_ntskcn), hl
    	ld	(chanb + chp_ntskcn), hl
    	ld	(chanc + chp_ntskcn), hl
    	ld	hl, emptysamorn
    	ld	(adinpta + 1), hl
    	ld	(chana + chp_ornptr), hl
    	ld	(chanb + chp_ornptr), hl
    	ld	(chanc + chp_ornptr), hl
    
    					; select AY tone table
    	xor	a			; 1.625Mhz (ZX81)
    ;	ld	a, 1			; 1.7734Mhz (128)
    ;	ld	a, 2			; 1.75Mhz (TC2068)
    ;	ld	a, 3			; 1.75Mhz (half tone lower)
    	rla
    	and 007h
    
    ; Note Table Creator (c) Ivan Roshin
    ; a - notetablenumber * 2 + versionfornotetable
    ; (xx1b - 3.xx..3.4r, xx0b - 3.4x..3.6x..vtii1.0)
    
    	ld	hl, nt_data
    	push	de
    	ld	d, b
    	add	a, a
    	ld	e, a
    	add	hl, de
    	ld	e, (hl)
    	inc	hl
    	srl	e
    	sbc	a, a
    	and	167 			; #00 (nop) or #a7 (and	a)
    	ld	(l3), a
    	ex	de, hl
    	pop	bc
    	add	hl, bc
    	ld	a, (de)
    	add	a, t_ & 255
    	ld	c, a
    	adc	a, t_ >> 8
    	sub	c
    	ld	b, a
    	push	bc
    	ld	de, nt_
    	push	de
    	ld	b, 00ch
    
    l1:
    	push	bc
    	ld	c, (hl)
    	inc	hl
    	push	hl
    	ld	b, (hl)
    	push	de
    	ex	de, hl
    	ld	de, 00017h
    	defb	221			; ld ixh, 8
    	ld	h, 8			; 
    
    l2:
    	srl b
    	rr c
    
    l3:
    	add	hl, de			; will be replaced by and	a or nop
    	ld	a, c
    	adc	a, d
    	ld	(hl), a
    	inc	hl
    	ld	a, b
    	adc	a, d
    	ld	(hl), a
    	add	hl, de
    	defb	221			; dec ixh
    	dec	h			;
    	jr	nz, l2
    	pop	de
    	inc	de
    	inc	de
    	pop	hl
    	inc	hl
    	pop	bc
    	djnz	l1
    	pop	hl
    	pop	de
    	ld	a, e
    	cp	tcold_1 & 255
    	jr	nz, corr_1
    	ld	a, 253
    	ld	(nt_ + 46), a
    
    corr_1:
    	ld	a, (de)
    	and	a
    	jr	z, tc_exit
    	rra
    	push	af
    	add	a, a
    	ld	c, a
    	add	hl, bc
    	pop	af
    	jr	nc, corr_2
    	dec	(hl)
    	dec	(hl)
    
    corr_2:
    	inc	(hl)
    	and	a
    	sbc	hl, bc
    	inc	de
    	jr	corr_1
    
    tc_exit:
    	pop	af
    
    ; Vol Table Creator (c) Ivan Roshin
    ; a - versionforvolumetable (0..4 - 3.xx..3.4x;
    ; 5.. - 3.5x..3.6x..vtii1.0)
    
    	cp	5
    	ld	hl, 17
    	ld	d, h
    	ld	e, h
    	ld	a, 23
    	jr	nc, m1
    	dec	l
    	ld	e, l
    	xor	a
    
    m1:
    	ld	(m2), a
    	ld	ix, vt_ + 16
    	ld	c, 16
    
    p3x_initv2:
    	push	hl
    	add	hl, de
    	ex	de, hl
    	sbc	hl, hl
    
    p3x_initv1:
    	ld	a, l
    
    m2:
    	ld	a, l
    	ld	a, h
    	adc	a, 0
    	ld	(ix + 0), a
    	inc	ix
    	add	hl, de
    	inc	c
    	ld	a, c
    	and	15
    	jr	nz, p3x_initv1
    	pop	hl
    	ld	a, e
    	cp	119
    	jr	nz, m3
    	inc	e
    
    m3:
    	ld	a, c
    	and	a
    	jr	nz, p3x_initv2
    	jp	rout_a0
    
    
    pd_orsm:
    	ld	(ix + 8), 0		; pattern decoder
    	call	setorn
    	ld	a, (bc)
    	inc	bc
    	rrca
    
    pd_sam:
    	add	a, a
    
    pd_sam_:
    	ld	e, a
    	ld	d, 0
    
    samptrs:
    	ld	hl, 8481
    	add	hl, de
    	ld	e, (hl)
    	inc	hl
    	ld	d, (hl)
    
    modaddr
    	ld	hl, 8481
    	add	hl, de
    	ld	(ix + 3), l
    	ld	(ix + 4), h
    	jr	pd_loop
    
    pd_vol:
    	rlca
    	rlca
    	rlca
    	rlca
    	ld	(ix + 16), a
    	jr	pd_lp2
    
    pd_eoff:
    	ld	(ix + 8), a
    	ld	(ix - 12), a
    	jr	pd_lp2
    
    pd_sore:
    	dec	a
    	jr	nz, pd_env
    	ld	a, (bc)
    	inc	bc
    	ld	(ix + 5), a
    	jr	pd_lp2
    
    pd_env:
    	call	setenv
    	jr	pd_lp2
    
    pd_orn:
    	call	setorn
    	jr	pd_loop
    
    pd_esam:
    	ld	(ix + 8), a
    	ld	(ix - 12), a
    	call	nz, setenv
    	ld	a, (bc)
    	inc	bc
    	jr	pd_sam_
    
    ptdecod:
    	ld	a, (ix + 6)
    	ld	(prnote + 1), a
    	ld	l, (ix - 6)
    	ld	h, (ix - 5)
    	ld	(prslide + 1), hl
    
    pd_loop:
    	ld	de, 8208
    
    pd_lp2:
    	ld	a, (bc)
    	inc	bc
    	add	a, e
    	jr	c, pd_orsm
    	add	a, d
    	jr	z, pd_fin
    	jr	c, pd_sam
    	add	a, e
    	jr	z, pd_rel
    	jr	c, pd_vol
    	add	a, e
    	jr	z, pd_eoff
    	jr	c, pd_sore
    	add	a, 060h
    	jr	c, pd_note
    	add	a, e
    	jr	c, pd_orn
    	add	a, d
    	jr	c, pd_nois
    	add	a, e
    	jr	c, pd_esam
    	add	a, a
    	ld	e, a
    	ld	hl, spccoms + 57120
    	add	hl, de
    	ld	e, (hl)
    	inc	hl
    	ld	d, (hl)
    	push	de
    	jr	pd_loop
    
    pd_nois:
    	ld	(ns_base), a
    	jr	pd_lp2
    
    pd_rel:
    	res	0, (ix + 9)
    	jr	pd_res
    
    pd_note:
    	ld	(ix + 6), a
    	set	0, (ix + 9)
    	xor	a
    
    pd_res:
    	ld	(pdsp_ + 1), sp
    	ld	sp, ix
    	ld	h, a
    	ld	l, a
    	push	hl
    	push	hl
    	push	hl
    	push	hl
    	push	hl
    	push	hl
    
    pdsp_
    	ld	sp, 12593
    
    pd_fin:
    	ld	a, (ix + 5)
    	ld	(ix + 15), a
    	ret
    
    c_portm:
    	res	2, (ix + 9)
    	ld	a, (bc)
    	inc	bc
    	inc	bc
    	inc	bc
    	ld	(ix + 10), a
    	ld	(ix - 7), a
    	ld	de, nt_
    	ld	a, (ix + 6)
    	ld	(ix + 7), a
    	add	a, a
    	ld	l, a
    	ld	h, 0
    	add	hl, de
    	ld	a, (hl)
    	inc	hl
    	ld	h, (hl)
    	ld	l, a
    	push	hl
    
    prnote:
    	ld	a, 62
    	ld	(ix + 6), a
    	add	a, a
    	ld	l, a
    	ld	h, 0
    	add	hl, de
    	ld	e, (hl)
    	inc	hl
    	ld	d, (hl)
    	pop	hl
    	sbc	hl, de
    	ld	(ix + 13), l
    	ld	(ix + 14), h
    	ld	e, (ix - 6)
    	ld	d, (ix - 5)
    
    prslide:
    	ld	de, 4369
    	ld	(ix - 6), e
    	ld	(ix - 5), d
    	ld	a, (bc)
    	inc	bc
    	ex	af, af'
    	ld	a, (bc)
    	inc	bc
    	and	a
    	jr	z, nosig
    	ex	de, hl
    
    nosig:
    	sbc	hl, de
    	jp	p, set_stp
    	cpl
    	ex	af, af'
    	neg
    	ex	af, af'
    
    set_stp:
    	ld	(ix + 12), a
    	ex	af, af'
    	ld	(ix + 11), a
    	ld	(ix - 2), 0
    	ret
    
    c_gliss:
    	set	2, (ix + 9)
    	ld	a, (bc)
    	inc	bc
    	ld	(ix + 10), a
    	and	a
    	jr	nz, gl36
    	ld	a, 6			; P3X version is always PT3.6
    	cp	7
    	sbc	a, a
    	inc	a
    
    gl36:
    	ld	(ix - 7), a
    	ld	a, (bc)
    	inc	bc
    	ex	af, af'
    	ld	a, (bc)
    	inc	bc
    	jr	set_stp
    
    c_smpos:
    	ld	a, (bc)
    	inc	bc
    	ld	(ix - 11), a
    	ret
    
    c_orpos:
    	ld	a, (bc)
    	inc	bc
    	ld	(ix - 12), a
    	ret
    
    c_vibrt:
    	ld	a, (bc)
    	inc	bc
    	ld	(ix - 1), a
    	ld	(ix - 2), a
    	ld	a, (bc)
    	inc	bc
    	ld	(ix + 0), a
    	xor a
    	ld	(ix - 7), a
    	ld	(ix - 6), a
    	ld	(ix - 5), a
    	ret
    
    c_engls
    	ld	a, (bc)
    	inc	bc
    	ld	(env_del + 1), a
    	ld	(curedel), a
    	ld	a, (bc)
    	inc	bc
    	ld	l, a
    	ld	a, (bc)
    	inc	bc
    	ld	h, a
    	ld	(esldadd + 1), hl
    	ret
    
    c_p3x_delay:
    	ld	a, (bc)
    	inc	bc
    	ld	(p3x_delay + 1), a
    	ld	(delycnt), a		; bugfix by lee_dc
    	ret
    
    setenv:
    	ld	(ix + 8), e
    	ld	(ayregs + ar_envtp), a
    	ld	a, (bc)
    	inc	bc
    	ld	h, a
    	ld	a, (bc)
    	inc	bc
    	ld	l, a
    	ld	(envbase), hl
    	xor	a
    	ld	(ix - 12), a
    	ld	(curedel), a
    	ld	h, a
    	ld	l, a
    	ld	(curesld), hl
    c_nop:
    	ret
    
    setorn:
    	add	a, a
    	ld	e, a
    	ld	d, 0
    	ld	(ix - 12), d
    
    ornptrs:
    	ld	hl, 8481
    	add	hl, de
    	ld	e, (hl)
    	inc	hl
    	ld	d, (hl)
    
    mdaddr2:
    	ld	hl, 8481
    	add	hl, de
    	ld	(ix + 1), l
    	ld	(ix + 2), h
    	ret
    
    ;all 16 addresses to protect from broken pt3 modules
    
    spccoms:
    	defw	c_nop
    	defw	c_gliss
    	defw	c_portm
    	defw	c_smpos
    	defw	c_orpos
    	defw	c_vibrt
    	defw	c_nop
    	defw	c_nop
    	defw	c_engls
    	defw	c_p3x_delay
    	defw	c_nop
    	defw	c_nop
    	defw	c_nop
    	defw	c_nop
    	defw	c_nop
    	defw	c_nop
    
    chregs:
    	xor	a
    	ld	(ampl), a
    	bit	0, (ix + 21)
    	push	hl
    	jp	z, ch_exit
    	ld	(csp_ + 1), sp
    	ld	l, (ix + 13)
    	ld	h, (ix + 14)
    	ld	sp, hl
    	pop	de
    	ld	h, a
    	ld	a, (ix + 0)
    	ld	l, a
    	add	hl, sp
    	inc	a
    	cp	d
    	jr	c, ch_orps
    	ld	a, e
    
    ch_orps:
    	ld	(ix + 0), a
    	ld	a, (ix + 18)
    	add	a, (hl)
    	jp	p, ch_ntp
    	xor a
    
    ch_ntp:
    	cp	96
    	jr	c, ch_nok
    	ld	a, 95
    
    ch_nok:
    	add	a, a
    	ex	af, af'
    	ld	l, (ix + 15)
    	ld	h, (ix + 16)
    	ld	sp, hl
    	pop	de
    	ld	h, 0
    	ld	a, (ix + 1)
    	ld	b, a
    	add	a, a
    	add	a, a
    	ld	l, a
    	add	hl, sp
    	ld	sp, hl
    	ld	a, b
    	inc	a
    	cp	d
    	jr	c, ch_smps
    	ld	a, e
    
    ch_smps:
    	ld	(ix + 1), a
    	pop	bc
    	pop	hl
    	ld	e, (ix + 8)
    	ld	d, (ix + 9)
    	add	hl, de
    	bit	6, b
    	jr	z, ch_noac
    	ld	(ix + 8), l
    	ld	(ix + 9), h
    
    ch_noac:
    	ex	de, hl
    	ex	af, af'
    	ld	l, a
    	ld	h, 0
    	ld	sp, nt_
    	add	hl, sp
    	ld	sp, hl
    	pop	hl
    	add	hl, de
    	ld	e, (ix + 6)
    	ld	d, (ix + 7)
    	add	hl, de
    
    csp_:
    	ld	sp, 03131h
    	ex	(sp), hl
    	xor	a
    	or	(ix + 5)
    	jr	z, ch_amp
    	dec	(ix + 5)
    	jr	nz, ch_amp
    	ld	a, (ix + 22)
    	ld	(ix + 5), a
    	ld	l, (ix + 23)
    	ld	h, (ix + 24)
    	ld	a, h
    	add	hl, de
    	ld	(ix + 6), l
    	ld	(ix + 7), h
    	bit	2, (ix + 21)
    	jr	nz, ch_amp
    	ld	e, (ix + 25)
    	ld	d, (ix + 26)
    	and	a
    	jr	z, ch_stpp
    	ex	de, hl
    
    ch_stpp:
    	sbc	hl, de
    	jp	m, ch_amp
    	ld	a, (ix + 19)
    	ld	(ix + 18), a
    	xor	a
    	ld	(ix + 5), a
    	ld	(ix + 6), a
    	ld	(ix + 7), a
    
    ch_amp:
    	ld	a, (ix + 2)
    	bit	7, c
    	jr	z, ch_noam
    	bit	6, c
    	jr	z, ch_amin
    	cp	15
    	jr	z, ch_noam
    	inc	a
    	jr	ch_svam
    
    ch_amin:
    	cp	241
    	jr	z, ch_noam
    	dec	a
    
    ch_svam:
    	ld	(ix + 2), a
    
    ch_noam:
    	ld	l, a
    	ld	a, b
    	and	15
    	add	a, l
    	jp	p, ch_apos
    	xor	a
    
    ch_apos:
    	cp	16
    	jr	c, ch_vol
    	ld	a, 15
    
    ch_vol:
    	or	(ix + 28)
    	ld	l, a
    	ld	h, 0
    	ld	de, vt_
    	add	hl, de
    	ld	a, (hl)
    
    ch_env:
    	bit	0, c
    	jr	nz, ch_noen
    	or	(ix + 20)
    
    ch_noen:
    	ld	(ampl), a
    	bit	7, b
    	ld	a, c
    	jr	z, no_ensl
    	rla
    	rla
    	sra	a
    	sra	a
    	sra	a
    	add	a, (ix + 4)
    	bit	5, b
    	jr	z, no_enac
    	ld	(ix + 004h), a
    
    no_enac:
    	ld	hl, addtoen + 1
    	add	a, (hl)
    	ld	(hl), a
    	jr	ch_mix
    
    no_ensl:
    	rra
    	add	a, (ix + 3)
    	ld	(addtons), a
    	bit	5, b
    	jr	z, ch_mix
    	ld	(ix + 3), a
    
    ch_mix:
    	ld	a, b
    	rra
    	and	72
    
    ch_exit:
    	ld	hl, ayregs + ar_mixer
    	or	(hl)
    	rrca
    	ld	(hl), a
    	pop	hl
    	xor	a
    	or	(ix + 10)
    	ret	z
    	dec	(ix + 10)
    	ret	nz
    	xor	(ix + 21)
    	ld	(ix + 21), a
    	rra
    	ld	a, (ix + 11)
    	jr	c, ch_ondl
    	ld	a, (ix + 12)
    
    ch_ondl:
    	ld	(ix + 10), a
    	ret
    
    play:
    	xor	a
    	ld	(addtoen + 1), a
    	ld	(ayregs + ar_mixer), a
    	dec	a
    	ld	(ayregs + ar_envtp), a
    	ld	hl, delycnt
    	dec	(hl)
    	jr	nz, pl2
    	ld	hl, chana + chp_ntskcn
    	dec	(hl)
    	jr	nz, pl1b
    
    adinpta:
    	ld	bc, 00101h
    	ld	a, (bc)
    	and	a
    	jr	nz, pl1a
    	ld	d, a
    	ld	(ns_base), a
    	ld	hl, (crpsptr)
    	inc	hl
    	ld	a, (hl)
    	inc	a
    	jr	nz, plnlp
    	call	checklp
    
    lposptr:
    	ld	hl, 8481
    	ld	a, (hl)
    	inc	a
    plnlp:
    	ld	(crpsptr), hl
    	dec	a
    	add	a, a
    	ld	e, a
    	rl	d
    
    patsptr:
    	ld	hl, 8481
    	add	hl, de
    	ld	de, (modaddr + 1)
    	ld	(psp_ + 1), sp
    	ld	sp, hl
    	pop	hl
    	add	hl, de
    	ld	b, h
    	ld	c, l
    	pop	hl
    	add	hl, de
    	ld	(adinptb + 1), hl
    	pop	hl
    	add	hl, de
    	ld	(adinptc + 1), hl
    
    psp_:
    	ld	sp, 12593
    
    pl1a:
    	ld	ix, chana + 12
    	call	ptdecod
    	ld	(adinpta + 1), bc
    
    pl1b:
    	ld	hl, chanb + chp_ntskcn
    	dec	(hl)
    	jr	nz, pl1c
    	ld	ix, chanb + 12
    
    adinptb:
    	ld	bc, 257
    	call	ptdecod
    	ld	(adinptb + 1), bc
    
    pl1c:
    	ld	hl, chanc + chp_ntskcn
    	dec	(hl)
    	jr	nz, p3x_delay
    	ld	ix, chanc + 12
    
    adinptc:
    	ld	bc, 257
    	call	ptdecod
    	ld	(adinptc + 1), bc
    
    p3x_delay:
    	ld	a, 62
    	ld	(delycnt), a
    
    pl2:
    	ld	ix, chana
    	ld	hl, (ayregs + ar_tona)
    	call	chregs
    	ld	(ayregs + ar_tona), hl
    	ld	a, (ampl)
    	ld	(ayregs + ar_ampla), a
    	ld	ix, chanb
    	ld	hl, (ayregs + ar_tonb)
    	call	chregs
    	ld	(ayregs + ar_tonb), hl
    	ld	a, (ampl)
    	ld	(ayregs + ar_amplb), a
    	ld	ix, chanc
    	ld	hl, (ayregs + ar_tonc)
    	call	chregs
    	ld	(ayregs + ar_tonc), hl
    	ld	hl, (ns_base_addtons)
    	ld	a, h
    	add	a, l
    	ld	(ayregs + ar_noise), a
    
    addtoen:
    	ld	a, 62
    	ld	e, a
    	add	a, a
    	sbc	a, a
    	ld	d, a
    	ld	hl, (envbase)
    	add	hl, de
    	ld	de, (curesld)
    	add	hl, de
    	ld	(ayregs + ar_env), hl
    	xor	a
    	ld	hl, curedel
    	or	(hl)
    	jr	z, rout_a0
    	dec	(hl)
    	jr	nz, rout
    
    env_del:
    	ld	a, 62
    	ld	(hl), a
    
    esldadd:
    	ld	hl, 8481
    	add	hl, de
    	ld	(curesld), hl
    
    rout:
    	xor	a
    
    rout_a0:
    	ld	de, #df0f		; Zon-X ports
    	ld	bc, #ffdf		;
    
    ;	ld	de, #f5f6		; TC2068 ports
    ;	ld	bc, #fff5		;
    
    ;	ld	de, #ffbf		; 128 ports
    ;	ld	bc, #fffd		;
    
    	ld	hl, ayregs
    
    code continued in next post ...
  • edited May 2011
    lout:
    	out	(c), a
    	ld	c, e			; Zon-X / TC2068
    ;	ld	b, e			; 128
    	outi
    	ld	c, d			; Zon-X / TC2068
    ;	ld	b, d			; 128
    	inc	a
    	cp	00dh
    	jr	nz, lout
    	out	(c), a
    	ld	a, (hl)
    	and	a
    	ret	m
    	ld	c, e			; Zon-X / TC2068
    ;	ld	b, e			; 128
    	out	(c), a
    	ret
    
    nt_data:
    	defb	(t_new_0 - t1_) * 2
    	defb	tcnew_0 - t_
    	defb	(t_old_0 - t1_) * 2 + 1
    	defb	tcold_0 - t_
    	defb	(t_new_1 - t1_) * 2 + 1
    	defb	tcnew_1 - t_
    	defb	(t_old_1 - t1_) * 2 + 1
    	defb	tcold_1 - t_
    	defb	(t_new_2 - t1_) * 2
    	defb	tcnew_2 - t_
    	defb	(t_old_2 - t1_) * 2
    	defb	tcold_2 - t_
    	defb	(t_new_3 - t1_) * 2
    	defb	tcnew_3 - t_
    	defb	(t_old_3 - t1_) * 2
    	defb	tcold_3 - t_
    
    t_:
    
    tcold_0:
    	defb	#00 + 1, #04 + 1, #08 + 1, #0a + 1, #0c + 1, #0e + 1
    	defb	#12 + 1, #14 + 1, #18 + 1, #24 + 1, #3c + 1, 0
    tcold_1:
    	defb	#5c + 1, 0
    
    tcold_2:
    	defb	#30 + 1, #36 + 1, #4c + 1, #52 + 1, #5e + 1, #70 + 1
    	defb	#82, #8c, #9c, #9e, #a0, #a6, #a8, #aa, #ac, #ae, #ae, 0
    
    tcnew_3:
    	defb	#56 + 1
    
    tcold_3:
    	defb	#1e + 1, #22 + 1, #24 + 1, #28 + 1, #2c + 1, #2e + 1
    	defb	#32 + 1, #be + 1, 0
    
    tcnew_0:
    	defb	#1c + 1, #20 + 1, #22 + 1, #26 + 1, #2a + 1, #2c + 1
    	defb	#30 + 1, #54 + 1, #bc + 1, #be + 1, 0
    
    tcnew_1 equ tcold_1
    
    tcnew_2:
    	defb	#1a + 1, #20 + 1, #24 + 1, #28 + 1, #2a + 1, #3a + 1
    	defb	#4c + 1, #5e + 1, #ba + 1, #bc + 1, #be + 1, 0
    
    emptysamorn equ $ - 1
    
    	defb	1, 0;, #90 ;delete #90 if you don't need default sample
    
    ;first 12 values of tone tables (packed)
    
    t_pack	defb	#06ec * 2/256, #06ec * 2	; Zon-X
    	defb	#0755 - #06ec
    	defb	#07c5 - #0755
    	defb	#083b - #07c5
    	defb	#08b8 - #083b
    	defb	#093d - #08b8
    	defb	#09ca - #093d
    	defb	#0a5f - #09ca
    	defb	#0afc - #0a5f
    	defb	#0ba4 - #0afc
    	defb	#0c55 - #0ba4
    	defb	#0d10 - #0c55
    	defb	#066d * 2/256, #066d * 2	; 128
    	defb	#06cf - #066d
    	defb	#0737 - #06cf
    	defb	#07a4 - #0737
    	defb	#0819 - #07a4
    	defb	#0894 - #0819
    	defb	#0917 - #0894
    	defb	#09a1 - #0917
    	defb	#0a33 - #09a1
    	defb	#0acf - #0a33
    	defb	#0b73 - #0acf
    	defb	#0c22 - #0b73
    	defb	#0cda - #0c22
    	defb	#0704 * 2/256, #0704 * 2	; TC2068
    	defb	#076e - #0704
    	defb	#07e0 - #076e
    	defb	#0858 - #07e0
    	defb	#08d6 - #0858
    	defb	#095c - #08d6
    	defb	#09ec - #095c
    	defb	#0a82 - #09ec
    	defb	#0b22 - #0a82
    	defb	#0bcc - #0b22
    	defb	#0c80 - #0bcc
    	defb	#0d3e - #0c80
    	defb	#07e0 * 2/256, #07e0 * 2	; TC2068 - half tone
    	defb	#0858 - #07e0
    	defb	#08e0 - #0858
    	defb	#0960 - #08e0
    	defb	#09f0 - #0960
    	defb	#0a88 - #09f0
    	defb	#0b28 - #0a88
    	defb	#0bd8 - #0b28
    	defb	#0c80 - #0bd8
    	defb	#0d60 - #0c80
    	defb	#0e10 - #0d60
    	defb	#0ef8 - #0e10
    
    ; channel data offsets
    
    chp_psinor	equ 0
    chp_psinsm	equ 1
    chp_cramsl	equ 2
    chp_crnssl	equ 3
    chp_crensl	equ 4
    chp_tslcnt	equ 5
    chp_crtnsl	equ 6
    chp_tnacc	equ 8
    chp_conoff	equ 10
    chp_onoffd	equ 11			; ix for ptdecod here ( + 12)
    chp_offond	equ 12
    chp_ornptr	equ 13
    chp_samptr	equ 15
    chp_nntskp	equ 17
    chp_note	equ 18
    chp_sltont	equ 19
    chp_env_en	equ 20
    chp_flags	equ 21			; enabled - 0, simplegliss - 2
    chp_tnsldl	equ 22
    chp_tslstp	equ 23
    chp_tndelt	equ 25
    chp_ntskcn	equ 27
    chp_volume	equ 28
    
    vars:
    chana	ds 29
    chanb	ds 29
    chanc	ds 29
    delycnt	defb	0			; globalvars
    curesld	defw	0
    curedel	defb	0
    
    ns_base_addtons:
    ns_base	defb	0
    addtons	defb	0
    
    ar_tona equ 0				; word 1
    ar_tonb equ 2				; word 1
    ar_tonc equ 4				; word 1
    ar_noise equ 6				; byte 1
    ar_mixer equ 7				; byte 1
    ar_ampla equ 8				; byte 1
    ar_amplb equ 9				; byte 1
    ar_amplc equ 10				; byte 1
    ar_env equ 11				; word 1
    ar_envtp equ 13				; byte 1
    ar_size equ 14				; byte 1
    
    ayregs equ $
    
    vt_:	defb	"volume table"		; created volume table address
    	defs	244
    
    envbase:
    	equ vt_ + 14
    
    t1_:
    	equ vt_ + 16			; tone tables data depacked here
    
    t_old_1	equ t1_
    t_old_2	equ t_old_1 + 24
    t_old_3	equ t_old_2 + 24
    t_old_0	equ t_old_3 + 2
    t_new_0	equ t_old_0
    t_new_1	equ t_old_1
    t_new_2	equ t_new_0 + 24
    t_new_3	equ t_old_3
    
    nt_:	defb	"note table"		 ; created note table address
    	defs	182
    
    ;local vars
    ampl equ ayregs + ar_amplc
    var0end	equ vt_ + 16			; p3x_init zeroes from vars to
    					; var0end - 1
    varsend equ $
    mdladdr equ $
    
    music:
    	incbin	"track.p3x"		; protracker 3.6 format track
    					; excluding 100 byte header
    
  • edited August 2011
    Whooey i'm here....:D

    I love it when things i'm doing end up else where...

    but yeah my PT3 player is based very much on Sergey Bulba's work, i asked for his permission to use his code and he said yes :p

    But it's much more modified than anybody would imagine, the reason? So that ZX81 can still run in SLOW, with full display and ability to run other code in the spare time left over. it was tricky, firstly i had to overcome the use of the alternate af' in Sergey's code, this was more complicated than just bunging it into another register as ZX81 interpreter uses pretty much all of them ! So before any code is run i save alt hl' on stack and then use that, since as user code can't run till final RET all is good.

    Second and quite difficult task was to do away with the Stack pointer manipulation, it is used as a kind of direct index into various tables, this again was complicated by the fact that as times there are no spare registers to use. but i managed it in the end.

    Third change all IX to IY, IX is used by zx81 NMI interrupt routine as a jump vector, hopefully the player has finished by the time the next NMI jump comes but that cannot be garanteed. your not really supposed to use The IY register in SLOW mode either but since as only the interrupt routine can stop the player part way through it is accounted for, other wise once player finished that quark IY is restored to whatever it was before hand.

    and lastly a special interrupt handler is written with minimal controls built in for player, monitors a memory address. 255 = mute and stop handler, 1 = play every 1/50th second, 0 = mute and stop (but remeber position). in very execeptional cases the player has not exitied before the next NMI jump comes along, the handler can cope with recurrsive calls :lol:

    So.... i give credit to Sergey Bulba for a great bit of coding.

    Regards Andy
  • edited August 2011
    Now that you're here you must stick around. :razz:
    Yerzmyey just sent me a YouTube link with one of his tunes but it sounds slower that it should be? Is this because it was written on Spectrum or PC tracker software or is it just a matter of adjusting something on the ZX81 player side?

    Welcome to WOS!
  • edited August 2011
    lots and lots slower like 50Hz playback instaed of 60Hz ?

    the ZX81's 50Hz varies slightly from machine to machine as the ceramic oscilators used are a bit *crap* but lets say for example a 2 minute track played 1% slow should only be about 1 and a half seconds longer, it could be an aural illusion because it is playing at a lower pitch.

    Send me the link or post it here and i'll have a look, if i can i'll hook up a real spectrum :o that will be fun.... and do some comparisons.

    i was thinking about the tone tables used in the PT3 playback module too, i might see if i can make it always use table 0, thats the one with the ZON-x values in it, then they should sound alot closer in pitch when compared side by side.

    It could also be a bug in the program and it is playing at a speed +/- 1 maybe...

    Andy
Sign In or Register to comment.