Electric Duet player sources

- electricduet.asm is the original source code published by Paul Lutus.

- PLAYER.ED.S is a commented source in french written by Deckard

- MOCKINGDUET.S is an ED player for a Mockingboard installed on Slot 4.

- CRICKETDUET.S is an ED player for an Apple //c with a Cricket! from
Street Electronics.
This commit is contained in:
cybernesto 2017-10-22 18:46:06 +02:00
commit c390792a03
7 changed files with 678 additions and 0 deletions

20
README.md Normal file
View File

@ -0,0 +1,20 @@
# electric-mock
## Apple II Electric Duet player for the Mockingboard and the Cricket!
*Electric Duet* is probably the most popular music format in the Apple II world.
Unfortunately the sound quality of the internal speaker of the Apple II does not do much justice to the songs written with ED. On certain Apple II models like the //c the sound circuitry does not cut off the modulation frequency very well producing a high pitched background noise.
This motivated me to write my own routines to play ED songs using a sound card to produce pure tones with much higher quality. I chose the Cricket! because I own one and there is not much software compatible with it. A Mockingboard ED Player is also included for the expandable Apple IIs with a Mockingboard Sound, A or C on Slot 4.
I wanted to keep the player as small as the original one so that it could be handled the same way. This limited a bit the amount of code that I could use, so even though the Cricket! version is able to play in stereo, the Mockingboard version is not.
A compromise was done for the frequency calculation where only a simple factor is used. A frequency table would have provided more accurate notes, but it would have made the player way bigger, so that it could not be used as a direct replacement.
The src directory includes the original assembly code as made available by [Paul Lutus](https://arachnoid.com/electric_duet/index.html), as well as the commented source in french written by [Deckard](http://boutillon.free.fr). Also a clean crack of the Electric Duet disk including tools for composing original scores is in the dsk directory.
The CRICKETDUET.S and MOCKINGDUET.S sources were assembled with Merlin. The binaries are available in *The Music Disk* image which also includes some classical pieces put together with a nice menu system written by Walt Marcinko Jr.

Binary file not shown.

Binary file not shown.

128
src/CRICKETDUET.S Normal file
View File

@ -0,0 +1,128 @@
*ELECTRIC DUET MUSIC PLAYER FOR THE CRICKET
CHN = $1D
SONG = $1E
LEFTCHN = $10
RIGHTCHN = $20
ENAREG = $07
VOL_A = $08
TONE = $06
DURATION = $08
ACIACMD2 = $C0AA
ACIACTL2 = $C0AB
ACIAST2 = $C0A9
ACIARXTX2 = $C0A8
ORG $300
JSR INIT
JSR RESET
LDA #LEFTCHN
STA CHN
JSR ENACHN
LDA #RIGHTCHN
STA CHN
JSR ENACHN
JMP LOOP
SETVOL NOP
NEXT LDA SONG
CLC
ADC #$03
STA SONG
BCC LOOP
INC SONG+1
LOOP LDY #$00
LDA (SONG),Y
CMP #$01
BEQ SETVOL
BPL SETNOTE ;SET DURATION
END JSR RESET
RTS
SETNOTE STA DURATION
LDA #LEFTCHN
SEND STA CHN
JSR OUT
INY
LDA (SONG),Y
BEQ SKIP ;IF 0 KEEP LTTSA
JSR CONVFREQ
SKIP LDA TONE
JSR OUT
INC CHN
LDA CHN
JSR OUT
LDA TONE+1
JSR OUT
LDA #RIGHTCHN
STA CHN
CPY #$02
BNE SEND
LDX DURATION
W1 LDY TEMPO
W2 DEC TEMP
BNE W2
DEY
BNE W2
DEX
BNE W1
BIT $C000
BMI END
JMP NEXT
CONVFREQ LDX OCTAVE
INX
PHA
LDA #$00
STA TONE+1
PLA
DECOCT DEX
BMI LOBYTE
ASL
ROL TONE+1
JMP DECOCT
LOBYTE STA TONE
RTS
INIT LDA #$0B
STA ACIACMD2
LDA #$9E
STA ACIACTL2
RTS
OUT PHA ;SAVE BYTE TO SEND OUT
WT LDA ACIAST2 ;READ STATUS OF SERIAL PORT
AND #$10 ;SEE IF IT'S READY TO RECEIVE A BYTE
BEQ WT ;NOT READY, WAIT
PLA ;REGET BYTE TO SEND OUT
STA ACIARXTX2 ;SEND IT
RTS
IN LDA ACIAST2 ;IS THERE A BYTE TO GET YET?
AND #$08
BEQ IN ;NOPE, WAIT FOR IT
LDA ACIARXTX2 ;GET INCOMING BYTE
RTS
RESET LDA #$A1
JSR OUT
RTS
ENACHN LDA #ENAREG
ORA CHN
JSR OUT
LDA #%00111110
JSR OUT
LDA #VOL_A
ORA CHN
JSR OUT
LDA #$0F
JSR OUT
RTS
OCTAVE DFB 1
TEMPO DFB 8
TEMP DFB 0

137
src/MOCKINGDUET.S Normal file
View File

@ -0,0 +1,137 @@
*ELECTRIC DUET MUSIC PLAYER FOR THE MOCKINGBOARD
*COPYRIGHT 2014 CYBERNESTO
CHN = $1D
SONG = $1E
LEFTCHN = $00
RIGHTCHN = $02
ENAREG = $07
VOL_A = $08
VOL_B = $09
TONE = $06
DURATION = $08
ORG $300
JSR INIT
JSR RESET
JSR ENACHN
JMP LOOP
SETVOL
NEXT LDA SONG
CLC
ADC #$03
STA SONG
BCC LOOP
INC SONG+1
LOOP LDY #$00
LDA (SONG),Y
CMP #$01
BEQ SETVOL
BPL SETNOTE ;SET DURATION
END JSR RESET
RTS
SETNOTE STA DURATION
LDA #LEFTCHN
SEND STA CHN
STA $C401
JSR SETREG1
INY
LDA (SONG),Y
BEQ SKIP ;IF 0 KEEP LTTSA
JSR CONVFREQ
SKIP LDA TONE
STA $C401
JSR WRDATA1
INC CHN
LDA CHN
STA $C401
JSR SETREG1
LDA TONE+1
STA $C401
JSR WRDATA1
LDA #RIGHTCHN
STA CHN
CPY #$02
BNE SEND
LDX DURATION
W1 LDY TEMPO
W2 DEC TEMP
BNE W2
DEY
BNE W2
DEX
BNE W1
BIT $C000
BMI END
JMP NEXT
CONVFREQ LDX OCTAVE
INX
PHA
LDA #$00
STA TONE+1
PLA
DECOCT DEX
BMI LOBYTE
ASL
ROL TONE+1
JMP DECOCT
LOBYTE STA TONE
RTS
RESET LDA #$00
STA $C400
STA $C480
LDA #$04
STA $C400
STA $C480
RTS
INIT LDA #$FF
STA $C403
STA $C483
LDA #$07
STA $C402
STA $C482
RTS
SETREG1 LDA #$07
STA $C400
LDA #$04
STA $C400
RTS
WRDATA1 LDA #$06
STA $C400
LDA #$04
STA $C400
RTS
ENACHN LDA #ENAREG
STA $C401
JSR SETREG1
LDA #%00111100
STA $C401
JSR WRDATA1
LDA #VOL_A
STA $C401
JSR SETREG1
LDA #$0F
STA $C401
JSR WRDATA1
LDA #VOL_B
STA $C401
JSR SETREG1
LDA #$0F
STA $C401
JSR WRDATA1
RTS
OCTAVE DFB 1
TEMPO DFB 8
TEMP DFB 0

264
src/PLAYER.ED.S Normal file
View File

@ -0,0 +1,264 @@
LST OFF
DSK /HD1/DCKDLIB/LNK/MUSIC/PLAYER.ED
REL
********************************
* *
* Source: ELECTRIC DUET *
* interruptible pour intros *
* *
********************************
* Utilisation: LDA #<ED_TBL
* LDY #>ED_TBL
* JSR PLAYER_ED
*
* ED_TBL DA adresse datas musique
* DFB flag interruption [0=oui,1=non]
* DA adresse interruption (0 si non inter)
* DA liste des touches autoris{es en sortie
* DFB flag inter clavier [0=temporaire,1=fin]
* DA adresse sortie key temporaire
* DFB arrete @ la fin du morceau [0=oui,1=non]
*
* Au retour d'une sortie par touche:
* carry=0 -> reprise
* carry=1 -> force sortie d{finitive
*
* Utilisation page 0:
* $06/$07/$08/$09/$1D/$1E/$1F/$4E/$4F
********************************
PLAYER_ED ENT
STA $06 ; sauve pointeur table
STY $07
* Lecture table
LDY #10 ; place en pile 11 octets table
:1 LDA ($06),Y
PHA
DEY
BPL :1
PLA
STA ED_DATA ; adr datas low
PLA
STA ED_DATA+1 ; adr datas high
PLA
STA ED_FLAG ; flag interruption
PLA
STA ED_INTER+1 ; adr low inter
PLA
STA ED_INTER+2 ; adr high inter
PLA
STA ED_KEYL+1 ; adr low liste touches
PLA
STA ED_KEYL+2 ; adr high liste touches
PLA
STA ED_FLAGK ; flag interruption clavier
PLA
STA ED_INTERK+1 ; adr low inter clavier
PLA
STA ED_INTERK+2 ; adr high inter clavier
PLA
STA ED_AGAIN+1 ; recommence du d{but ou arrete
* Player
ED_M LDA ED_DATA
STA $1E
LDA ED_DATA+1
STA $1F
LDA #1
STA $09
STA $1D
PHA
PHA
PHA
BNE H0A2B
H0A16 INY
LDA ($1E),Y
STA $09
INY
LDA ($1E),Y
STA $1D
H0A20 LDA $1E
CLC
ADC #$03
STA $1E
BCC H0A2B
INC $1F
H0A2B LDY #$00
LDA ($1E),Y
CMP #$01
BEQ H0A16
BCS H0A45
PLA
PLA
PLA
ED_AGAIN LDA #$FF ; [0=fin,1=recommence]
BNE ED_M ; reprise du d{but
RTS ; fin
H0A38 LDX #$49
INY
LDA ($1E),Y
BNE :1
LDX #$C9
:1 RTS
H0A45 STA $08
JSR H0A38
STX H0A94
STA $06
LDX $09
:1 LSR
DEX
BNE :1
STA H0A8C+1
JSR H0A38
STX H0ACC
STA $07
LDX $1D
:2 LSR
DEX
BNE :2
STA H0AC4+1
********************************
* Interruption par JSR autoris{e ici
LDA ED_FLAG
BNE ED_NOINTER
ED_INTER JSR $FFFF ; adr interruption
********************************
ED_NOINTER PLA
TAY
PLA
TAX
PLA
BNE H0A76
H0A73 BIT $C030
H0A76 CMP #0
BMI H0A7D
NOP
BPL H0A80
H0A7D BIT $C030
H0A80 STA $4E
BIT $C000
BPL NOKEY
JSR ED_KEY ; test touche autoris{e
BCS NOKEY ; non. Pas de prise en compte
LDA ED_FLAGK ; arret d{finitif?
BNE ED_FIN ; oui
STX ED_X ; sauve registres
STY ED_Y
LDA ED_KEYINTER ; touche enfonc{e
ED_INTERK JSR $FFFF ; interruption touche
BCS ED_FIN ; the end (forc{)
LDX ED_X
LDY ED_Y
JMP NOKEY ; reprise comme si de rien n'{tait
ED_FIN RTS
NOKEY DEY
BNE H0A8C
BEQ H0A92
H0A8C CPY #$36
BEQ H0A94
BNE H0A96
H0A92 LDY $06
H0A94 EOR #$40
H0A96 BIT $4E
BVC H0AA1
BVS H0A9C
H0A9C BPL H0AA7
NOP
BMI H0AAA
H0AA1 NOP
BMI H0AA7
NOP
BPL H0AAA
H0AA7 CMP $C030
H0AAA DEC $4F
BNE H0ABF
DEC $08
BNE H0ABF
BVC H0AB7
BIT $C030
H0AB7 PHA
TXA
PHA
TYA
PHA
JMP H0A20
H0ABF DEX
BNE H0AC4
BEQ H0ACA
H0AC4 CPX #$0C
BEQ H0ACC
BNE H0ACE
H0ACA LDX $07
H0ACC EOR #$80
H0ACE BVS H0A73
NOP
BVC H0A76
RTS
* Test autorisation touche
ED_KEY STY ED_Y ; sauve Y
LDY #0
ED_KEYL LDA $FFFF,Y
BEQ :1 ; fin des touches autoris{es
CMP $C000
BEQ :2 ; found!
INY ; next
BNE ED_KEYL
:2 STA ED_KEYINTER
CLC
DFB $24 ; bit
:1 SEC ; bad key
BIT $C010
LDY ED_Y
RTS
********************************
ED_FLAG DFB 0 ; flag interruption
ED_FLAGK DFB 0 ; flag interruption clavier
ED_KEYINTER DFB 0 ; touche ayant provoqu{e l'inter
ED_DATA DFB 0,0 ; adr datas
ED_Y DFB 0 ; sauvegarde registre Y
ED_X DFB 0 ; sauvegarde registre X

129
src/electricduet.asm Normal file
View File

@ -0,0 +1,129 @@
/***************************************************************************
* Copyright (C) 1979-2015 by Paul Lutus *
* http://arachnoid.com/administration *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/* Electric Duet Player Routine circa 1980 */
$0900> A9 01: LDA #$01 ; 2 *!*
$0902> 85 09: STA $09 ; 3
$0904> 85 1D: STA $1D ; 3
$0906> 48: PHA ; 3
$0907> 48: PHA ; 3
$0908> 48: PHA ; 3
$0909> D0 15: BNE $0920 ; 4 *!*
$090B> C8: INY ; 2
$090C> B1 1E: LDA ($1E),Y ; 5 *!*
$090E> 85 09: STA $09 ; 3
$0910> C8: INY ; 2
$0911> B1 1E: LDA ($1E),Y ; 5 *!*
$0913> 85 1D: STA $1D ; 3
$0915> A5 1E: LDA $1E ; 3 *!*
$0917> 18: CLC ; 2
$0918> 69 03: ADC #$03 ; 2 *!*
$091A> 85 1E: STA $1E ; 3
$091C> 90 02: BCC $0920 ; 4 *!*
$091E> E6 1F: INC $1F ; 5
$0920> A0 00: LDY #$00 ; 2 *!*
$0922> B1 1E: LDA ($1E),Y ; 5 *!*
$0924> C9 01: CMP #$01 ; 2
$0926> F0 E3: BEQ $090B ; 4 *!*
$0928> B0 0D: BCS $0937 ; 4 *!*
$092A> 68: PLA ; 4
$092B> 68: PLA ; 4
$092C> 68: PLA ; 4
$092D> A2 49: LDX #$49 ; 2 *!*
$092F> C8: INY ; 2
$0930> B1 1E: LDA ($1E),Y ; 5 *!*
$0932> D0 02: BNE $0936 ; 4 *!*
$0934> A2 C9: LDX #$c9 ; 2 *!*
$0936> 60: RTS ; 6
$0937> 85 08: STA $08 ; 3
$0939> 20 2D09: JSR $092D ; 6
$093C> 8E 8309: STX $0983 ; 4
$093F> 85 06: STA $06 ; 3
$0941> A6 09: LDX $09 ; 3 *!*
$0943> 4A: LSR A ; 2
$0944> CA: DEX ; 2
$0945> D0 FC: BNE $0943 ; 4 *!*
$0947> 8D 7C09: STA $097C ; 4
$094A> 20 2D09: JSR $092D ; 6
$094D> 8E BB09: STX $09BB ; 4
$0950> 85 07: STA $07 ; 3
$0952> A6 1D: LDX $1D ; 3 *!*
$0954> 4A: LSR A ; 2
$0955> CA: DEX ; 2
$0956> D0 FC: BNE $0954 ; 4 *!*
$0958> 8D B409: STA $09B4 ; 4
$095B> 68: PLA ; 4
$095C> A8: TAY ; 2
$095D> 68: PLA ; 4
$095E> AA: TAX ; 2
$095F> 68: PLA ; 4
$0960> D0 03: BNE $0965 ; 4 *!*
$0962> 2C 30C0: BIT $C030 ; 4
$0965> C9 00: CMP #$00 ; 2
$0967> 30 03: BMI $096C ; 4 *!*
$0969> EA: NOP ; 2
$096A> 10 03: BPL $096F ; 4 *!*
$096C> 2C 30C0: BIT $C030 ; 4
$096F> 85 4E: STA $4E ; 3
$0971> 2C 00C0: BIT $C000 ; 4
$0974> 30 C0: BMI $0936 ; 4 *!*
$0976> 88: DEY ; 2
$0977> D0 02: BNE $097B ; 4 *!*
$0979> F0 06: BEQ $0981 ; 4 *!*
$097B> C0 00: CPY #$00 ; 2
$097D> F0 04: BEQ $0983 ; 4 *!*
$097F> D0 04: BNE $0985 ; 4 *!*
$0981> A4 06: LDY $06 ; 3 *!*
$0983> 49 40: EOR #$40 ; 2 *!*
$0985> 24 4E: BIT $4E ; 3
$0987> 50 07: BVC $0990 ; 4 *!*
$0989> 70 00: BVS $098B ; 4 *!*
$098B> 10 09: BPL $0996 ; 4 *!*
$098D> EA: NOP ; 2
$098E> 30 09: BMI $0999 ; 4 *!*
$0990> EA: NOP ; 2
$0991> 30 03: BMI $0996 ; 4 *!*
$0993> EA: NOP ; 2
$0994> 10 03: BPL $0999 ; 4 *!*
$0996> CD 30C0: CMP $C030 ; 4
$0999> C6 4F: DEC $4F ; 5
$099B> D0 11: BNE $09AE ; 4 *!*
$099D> C6 08: DEC $08 ; 5
$099F> D0 0D: BNE $09AE ; 4 *!*
$09A1> 50 03: BVC $09A6 ; 4 *!*
$09A3> 2C 30C0: BIT $C030 ; 4
$09A6> 48: PHA ; 3
$09A7> 8A: TXA ; 2
$09A8> 48: PHA ; 3
$09A9> 98: TYA ; 2
$09AA> 48: PHA ; 3
$09AB> 4C 1509: JMP $0915 ; 3
$09AE> CA: DEX ; 2
$09AF> D0 02: BNE $09B3 ; 4 *!*
$09B1> F0 06: BEQ $09B9 ; 4 *!*
$09B3> E0 00: CPX #$00 ; 2
$09B5> F0 04: BEQ $09BB ; 4 *!*
$09B7> D0 04: BNE $09BD ; 4 *!*
$09B9> A6 07: LDX $07 ; 3 *!*
$09BB> 49 80: EOR #$80 ; 2 *!*
$09BD> 70 A3: BVS $0962 ; 4 *!*
$09BF> EA: NOP ; 2
$09C0> 50 A3: BVC $0965 ; 4 *!*