;link +
;
; -Title:
;   Echo v1.01
;
; -Purpose:
;   To Echo
;
; -Author:
;   Tomi Marin, Supervisor Software
;
; -Copyright:
;   Copyright © 1989 by Supervisor Software
;
; -Bugs:
;   
;
; -Usage:
;   ECH [b#] [p#] [r] [v#d] [v#i]
;
; -Modification history:
;   17.09.89 by TM -> v0.00	  - created
;   19.09.89 by TM -> v1.00	  - a working version
;   21.09.89 by JM,TM -> v1.00.1  - kommentoitu suomeksi
;   23.09.89 by JM -> v1.01       - small modifications
;


	include	"relative.i"
	include	"jmplibs.i"
	include	"gfxlib.i"
	include	"execlib.i"
	include	"doslib.i"
	include	"strlib.i"
	include	"mathlib.i"
	include	"numlib.i"
	include	"macros.i"
	include	"util.i"
	include	"hards.i"
	include	"constants.i"
	include	"dos.xref"
	include	"exec.xref"


RELATIVE set	-1			käytetään suhteellista osoitusta
BUF	equ	5000			viivepuskurin oletuspituus
PER	equ	200			näytteenottotaajuuden oletusarvo
VOL	equ	64			voimakkuuden oletusarvo

	.var
	dl	_DosBase,cmdlin		varataan muuttujille tilaa pinosta
	dl	exitcode,buflen,buffer
	dl	tables,tablea
	dw	periot,repeti,vola,volb

main	.begin				itse tilan varaus (LINK-käsky)
	ra				nollataan muuttujat
	clr.b	-1(a0,d0.l)		lisätään nolla komentorivin loppuun
	move.l	a0,cmdlin(a4)		talletetaan komentorivin osoitin
	moveq	#20,d0
	move.l	d0,exitcode(a4)		asetetaan virhekoodi

	openlib	Dos,clean		avataan Dos-kirjasto

	move.l	#512,d0			varataan 512 tavua muistia
	moveq	#1,d1
	lib	Exec,AllocMem
	move.l	d0,tables(a4)		muistin alkuosoite talteen
	beq	clean			jos muistia ei saatu, poistutaan

	move.l	tables(a4),a0		kopioidaan alkuosoite
	move.l	a0,tablea(a4)

	move.l	#BUF,buflen(a4)		puskurin pituuden oletusarvo
	move.w	#PER,periot(a4)		näytteenottotaajuuden oletusarvo
	moveq	#VOL,d0			äänenvoimakkuuden oletusarvo
	move.w	d0,vola(a4)
	move.w	d0,volb(a4)
	move.l	cmdlin(a4),a0		otetaan komentorivin osoite
parse1	move.b	(a0)+,d0		merkki komentoriviltä
	beq	parse0			nolla -> rivin loppu -> pois
	cmp.b	#32,d0			jos välilyönti,
	beq.s	parse1			 otetaan seuraava merkki
	cmp.b	#9,d0			jos tabulaattori,
	beq.s	parse1			 otetaan seuraava merkki

	cmp.b	#'b',d0			onko 'b' (puskurin koko)?
	bne.s	parse2			ei -> hyppää
	bsr	get10			otetaan 10-järjestelmän luku
	bcs	badargs			rivi loppui -> virheilmoitus
	move.l	d0,buflen(a4)		talletetaan puskurin koko
	bra	parse1			jatketaan rivin käsittelyä

parse2	cmp.b	#'p',d0			onko 'p' (näytt.ottonop.)?
	bne.s	parse3			ei -> hyppää
	bsr	get10			otetaan 10-järjestelmän luku
	bcs	badargs			rivi loppui -> virheilmoitus
	move.w	d0,periot(a4)		talletetaan nopeus
	bra	parse1			jatketaan rivin käsittelyä

parse3	cmp.b	#'r',d0			onko 'r' (toistuva kaiku)?
	bne.s	parse4			ei -> hyppää
	st	repeti(a4)		asetetaan lippu: toistuva
	bra	parse1			jatketaan rivin käsittelyä

parse4	cmp.b	#'v',d0			onko 'v' (voimakkuus)?
	bne.s	parse5			ei -> hyppää
	bsr	get10			otetaan 10-järjestelmän luku
	bcs	badargs			rivi loppui -> virheilmoitus
	move.b	(a0)+,d1		seuraava merkki (pitäisi olla d tai i)
	cmp.b	#'d',d1			onkos 'd'?
	bne.s	1$			eipä ole -> hyppele!
	move.w	d0,vola(a4)		on -> tallenna suoran äänen voim.
	bra	parse1			jatka rivin käsittelyä
1$	cmp.b	#'i',d1			onkos se sitten 'i'?
	bne.s	2$			ei -> hyppää taas
	move.w	d0,volb(a4)		on -> tallenna viivästetyn äänen voim.
	bra	parse1			jatka rivin käsittelyä
2$	lea	3$(pc),a0		virheilmoituksen osoite a0:aan
	bsr	dpymsg			tulostetaan virheilmoitus
	bra	clean			pois ohjelmasta!
3$	dc.b	'use vNNd / vNNi',LF,0
	ds.w	0			tasataan parilliseen osoitteeseen

parse5	lea	1$(pc),a0		virheilmoituksen osoite
	bsr	dpymsg			tulostetaan se
	bra	clean			 ja poistutaan koko roskasta
1$	dc.b	'Bad option "%lc"',LF,0
	ds.w	0			tasataan taas parilliseen osoitteeseen

parse0	move.l	buflen(a4),d0		puskurin koko
	move.l	#MEMF_CLEAR!MEMF_PUBLIC,d1
	lib	Exec,AllocMem		varataan kaikupuskuri
	move.l	d0,buffer(a4)		tallennetaan alkuosoite
	bne.s	main1			jos muistia saatiin -> main1

	move.l	buflen(a4),d0		jos ei saatu, valitetaan:
	lea	1$(pc),a0		virheilmoituksen osoite
	bsr	dpymsg			tulostetaan
	bra	clean			ja pian pois täältä!
1$	dc.b	'Can''t get %ld bytes.',LF,0
	ds.w	0			ja taas tasataan

main1	move.l	tablea(a4),a0		aputaulukon osoite
	moveq	#0,d0
1$	move.w	d0,d1			lasketaan taulukkoon luvut
	mulu.w	#$101,d1		 $0000, $0101, $0202,...$ffff
	move.w	d1,(a0)+		luku talteen
	addq.w	#1,d0			seuraava nummero
	cmp.w	#$100,d0		jokos lopetetaan?
	blo.s	1$			ei -> hyppää

	lib	Exec,Disable		Nyt loppui moniajo!!
	clr.b	$bfe301			rinnakkaisportti sisäänmenoksi
	lea	$dff000,a6		apuprosessorien osoite
	move.w	vola(a4),AUD0VOL(a6)	kanavan 0 voimakkuus
	move.w	vola(a4),AUD1VOL(a6)	kanavan 1 voimakkuus
	move.w	volb(a4),AUD2VOL(a6)	kanavan 2 voimakkuus
	move.w	volb(a4),AUD3VOL(a6)	kanavan 3 voimakkuus
	move.w	periot(a4),d0
	move.w	d0,AUD0PER(a6)		kanavan 0 toistonopeus
	move.w	d0,AUD1PER(a6)		kanavan 1 toistonopeus
	move.w	d0,AUD2PER(a6)		kanavan 2 toistonopeus
	move.w	d0,AUD3PER(a6)		kanavan 3 toistonopeus

	move.w	#%1000000000001111,DMACON(a6)	DMA päälle
	move.w	#%0000000000001111,DMACON(a6)	DMA pois
	move.w	#%0000011110000000,INTENA(a6)	äänikesk. pois

	move.l	buffer(a4),a2		kaikupuskurin osoite
	move.l	a2,a0			a0 = luku-kirjoitusosoitin
	move.l	a2,d6			d6 = kaikupuskurin alkuosoite
	move.l	a2,d7
	add.l	buflen(a4),d7		d7 = kaikupuskurin loppuosoite
	lea	$bfe101,a2		a2 = rinnakkaisportin osoite
	move.l	tablea(a4),a3		a3 = aputaulukon osoite
	tst.w	repeti(a4)		toistuva kaiku valittu?
	beq.s	main3			ei, hyppää main3:een

main2	move.w	INTREQR(a6),d0		joko entinen näyte on soinut?
	and.w	#%0000000010000000,d0	vahditaan kanavaa 0
	beq.s	main2b			hyppää, jos pitää odottaa vielä
	move.w	#$f0f,COLOR0(a6)	muuten väläyttää näytön taustaa
	bra.s	main2c			 ja jatkaa kiireesti
main2b	move.w	INTREQR(a6),d0		varsinainen odotussilmukka
	and.w	#%0000000010000000,d0
	beq.s	main2b

main2c	move.w	#%0000011110000000,INTREQ(a6)	nollataan keskeytys
	moveq	#0,d2
	move.b	(a2),d0			otetaan digitoijalta näyte
	sub.b	#$80,d0			muunnetaan välille -128...+127
	move.b	d0,d2			kopio talteen
	add.w	d2,d2			kerrotaan 2:lla
	move.w	0(a3,d2.w),d2
	move.w	d2,AUD0DAT(a6)		Paulalle näyte 16-bittisenä
	move.w	d2,AUD1DAT(a6)
	moveq	#0,d1
	move.b	(a0),d1			otetaan viivästetty näyte puskurista
	ext.w	d0			muunnetaan uusi ja vanha
	ext.w	d1			 16-bittisiksi
	add.w	d1,d0			 ja lasketaan ne yhteen
	muls	#11,d0			kerrotaan tulos 11:lla
	asr.w	#4,d0			 ja jaetaan 16:lla
	move.b	d0,(a0)+		 sekä talletetaan puskuriin
	and.w	#$ff,d0
	add.w	d0,d0			kerrotaan 2:lla
	move.w	0(a3,d0.w),d2
	move.w	d2,AUD2DAT(a6)		ja annetaan Paulalle 16-bittisenä
	move.w	d2,AUD3DAT(a6)
	cmp.l	d7,a0			puskurin loppuosoite?
	blo.s	1$			ei -> hyppää
	move.l	d6,a0			on -> siirrytään takaisin alkuun
1$	btst	#6,-$100(a2)		vasen hiiren nappi?
	bne.s	main2			ei oo -> jatkuu!
	bra.s	exitti			on -> männään pois!


main3	move.w	INTREQR(a6),d0		onko entinen näyte jo soinut?
	and.w	#%0000000010000000,d0
	beq.s	main3b			ei, ->
	move.w	#$f0f,COLOR0(a6)	on, näytön tausta sinipunaiseksi
	bra.s	main3c			 ja jatka
main3b	move.w	INTREQR(a6),d0		odota näytteen loppua
	and.w	#%0000000010000000,d0
	beq.s	main3b

main3c	move.w	#%0000011110000000,INTREQ(a6)	nollataan keskeytys
	moveq	#0,d2
	move.b	(a2),d0			lue uusi näyte digitoijalta
	sub.b	#$80,d0			muunnetaan välille -128..127
	move.b	d0,d2
	add.w	d2,d2			taulukon indeksi
	move.w	0(a3,d2.w),d2
	move.w	d2,AUD0DAT(a6)		lue taulukosta ja soita näyte
	move.w	d2,AUD1DAT(a6)
	moveq	#0,d1
	move.b	(a0),d1			lue entinen (kaiutettava) näyte
	move.b	d0,(a0)+		korvaa se uudella puskuriin
	add.w	d1,d1
	move.w	0(a3,d1.w),d2		lue taulukosta ja kaiuta
	move.w	d2,AUD2DAT(a6)
	move.w	d2,AUD3DAT(a6)
	cmp.l	d7,a0			puskurin loppu?
	blo.s	1$
	move.l	d6,a0			on: takaisin puskurin alkuun
1$	btst	#6,-$100(a2)		vasen hiiren nappi?
	bne.s	main3			ei: jatketaan

exitti	lib	Exec,Enable		salli keskeytykset ja moniajo

	clr.l	exitcode(a4)		nollaa virhekoodi: ei virhettä
clean	move.l	buffer(a4),d0		puskuri varattu?
	beq.s	clean1
	move.l	d0,a1			on: vapauta se
	move.l	buflen(a4),d0
	lib	Exec,FreeMem
clean1	move.l	tables(a4),d0		taulukko varattu?
	beq.s	clean2
	move.l	d0,a1			on: vapauta
	move.l	#512,d0
	lib	Exec,FreeMem
clean2	closlib	Dos			sulje Dos
	move.l	exitcode(a4),d0		palauta mahdollinen virhekoodi
	.end				pois

	;	ilmoita 'Bad arguments' ja poistu:
badargs	lea	1$(pc),a0		tekstin osoite
	bsr.s	dpymsg			tulosta
	bra.s	clean
1$	dc.b	'Bad args',LF,0
	ds.w	0

	;	tulosta muotoiltu viesti:
	;	a0 = muotoilumerkkijono, d0..d7 = mahd. parametrit
dpymsg	movem.l	d0-d7/a0-a6,-(sp)	tallenna rekisterit
	move.l	#256,d0
	moveq	#1,d1
	lib	Exec,AllocMem		varaa 256 tavua puskuria
	tst.l	d0			saatiinko varattua?
	beq.s	dpymsg0			ei: poistu
	move.l	d0,a1
	move.l	d0,a2
	movem.l	(sp),d0-d1		palauta d0:n ja d1:n arvot
	move.l	32(sp),a0		ja a0:n arvo
	bsr.s	sformat			muotoile merkkijono puskuriin
	lib	Dos,Output		minne tulostetaan?
	move.l	d0,d1
	beq.s	dpymsg1			ei minnekään: poistu
	move.l	a2,a0
	move.l	a0,d2
1$	tst.b	(a0)+			etsi merkkijonon loppu
	bne.s	1$
	subq.w	#1,a0			siirry takaisin nollan yli
	move.l	a0,d3
	sub.l	d2,d3			vähennä siitä alkuos. -> pituus
	flib	Dos,Write		tulosta merkkijono
dpymsg1	move.l	a2,a1
	move.l	#256,d0
	lib	Exec,FreeMem		vapauta puskuri
dpymsg0	movem.l	(sp)+,d0-d7/a0-a6	palauta rekisterit
	rts

	;	muotoile merkkijono:
	;	a0 = muotoilumerkkijono, a1 = puskuri
	;	d0..d7 = mahd. parametrit
sformat	push	a2-a3/a6/d0-d1
	lea	-32(sp),sp		varaa 32 tavua pinosta
	move.l	a1,a3			a3 = puskurin osoite
	move.l	sp,a1			a1 = parametrien osoite
	movem.l	d0-d7,(a1)		kirjoita parametrit sinne
	lea	1$(pc),a2		a2 = merkki puskuriin -rutiini
	lib	Exec,RawDoFmt		muotoile!
	lea.l	-1(a3),a1		palauta loppunolla osoite a1:ssä
	move.l	a1,a0			ja a0:ssa
	lea	32(sp),sp		vapauta pinomuisti
	pull	a2-a3/a6/d0-d1
	rts
	;	edellisen rutiini merkin kirjoittamiseksi puskuriin:
	;	a3 = osoitin puskuriin
	;	d0 = merkki
1$	move.b	d0,(a3)+		kirjoita merkki ja suurenna
	rts				osoitinta

	;	lue 10-järjestelmän luku merkkijonosta:
	;	a0 = merkkijono
get10	move.b	(a0),d0			ota merkki
	bne.s	get10a			merkkijonon loppu -> virhe
get10x	setc				c = 1: virhe
	rts
get10a	push	d1			ei:
	moveq	#0,d1			nollaa luku
get10b	moveq	#0,d0
	move.b	(a0)+,d0		ota seur. merkki
	sub.b	#'0',d0
	blo.s	get10z			pienempi kuin '0' ->
	cmp.b	#10,d0
	bhs.s	get10z			suurempi kuin '9' ->
	add.l	d1,d1			kerro jo saatu luku 10:llä
	add.l	d1,d0			ja lisää uusi numero
	asl.l	#2,d1
	add.l	d0,d1
	bra.s	get10b			ota seur. numero
get10z	subq.w	#1,a0			siirry takaisin tunnistamatto-
	move.l	d1,d0			maan merkkin; tulos d1:een
	pull	d1			c = 0: ei virhettä
	rts


	libnames			käytetyt kirjastonimet
	end

