;SHAZAM 0.1
;A keyboard operating system for the PAiA 8700 computer
;By: Bob Yannes October 1978

DECODE	=$0F00 ;PIEBUG function
INIT	=$0D21 ;MUS-1 function
NOTE	=$0D2B ;MUS-1 function
FILL	=$0D52 ;MUS-1 function
POLY	=$0D71 ;MUS-1 function
TRNGN	=$0DC3 ;MUS-1 function

DISPLAY	=$0820

OUTS	=$EA
KTBLMAX	=$E7
OLDKEY	=$97	;CONTAINS PREVIOUS NOTE FOR COMPATISON W/NEW NOTE.
COUNT	=$98	;VOICE COUNTER/POINTER
NTS 	=$99	;START OF NTABLE FOR GIVEN NUMBER OF VOICES.
;NTS+1 (=0) SPECIFIES ZERO PAGE FOR INDIRECT ADDRESS.
SPLITMIN	=$9B	;DUMMY SPLIT POINT, ASSURES HIGHEST NOTE ASSIGNED
;TO LAST CHANNEL.
SPLIT	=$9C ;through $A2 TABLE OF SPLIT POINTS

CLK		=$BF ;MUS-1 clock
KTBL	=$DF ;MUS-1


ENT		=$13 ;keyboard commands
PCH		=$14
PLC		=$15
TAPE	=$16

	org $0100
	
	ldx #$ff		;GET THE STACK
	txs				;OUT OF THE WAY.
	lda #$df		;GET NTABLEMAX POSITION...
	sec				;PREPARE TO SUBTRACT...
	sbc OUTS		;WELL, SUBTRACT THE NUMBER OF VOICES
	sta NTS			;THIS IT EH START OF NTABLE NOW.
	lda #0			;ASSURE ADDR HIGH IS ZERO (PAGE)
	sta NTS+1		;FOR USE AS INDIRECT ADDR.
OPTN
	jsr INIT		;WIPE'EM OUT!
PLOOP
	jsr POLY		;ASSIGN NOTES ACCORDING TO POLY.
	jsr TRNGN		;DO TRANSIENTS IF SELECTED.
	jsr NOTE		;PLAY THE NOTES.
	lda CLK			;BELLS AND
	sta DISPLAY		;WHISTLES.
	jsr DECODE		;SCAN 8700 KYBD.
	cmp #1			;IS IT TUNE?
	bcc OPTN		;NO, IT'S LESS--MUST BE CLEAR.
	bne MORE		;NO, GO SEE WHAT IT WAS.
	ldy #$5C		;YES, GET NOTE TO TUNE WITH...
	jsr FILL		;PUT IN ALL CHANNELS...
	beq PLOOP		;AND PLAY IT.
MORE
	cmp #PCH		;IS IT PCH?
	beq CHORUS		;YES, GO TO CHORUS,
	cmp #PLC		;OKAY, THEN IS IT PLC?
	beq SPLITZ		;YES, GO TO SPLITZ.
	bne PLOOP		;NO, TAWS NONE OF THEM, KEEP ON POLY.
	
CHORUS
	lda OUTS		;GET THE NUMBER OF AVAILABLE VOICES.
	sta COUNT		;USE AS COUNTER/POINTER
IN
	jsr CLEAR		;TURN OFF ALL GATES.
	lda KTBLMAX		;GET LOWEST NOTE.
	beq OUT			;IF ZERO, SKIP ASSIGNMENT.
	cmp OLDKEY		;IS IT THE SAME KEY YOU JUST HAD?
	beq SAME		;YES, KEEP OLD CHANNEL ASSIGNMENT.
	dec COUNT		;NO, GET NEW CHANNEL ASSIGNMENT.
	beq OUT			;IF ZERO, SKIP ASSIGNMENT.
SAME
	ldy COUNT		;GET POINT.
	sta (NTS),y		;ASSIGN VOICE TO CHANNEL Y.
OUT
	sta OLDKEY		;ALSO, STOE IT FOR LATER.
	jsr NOTE		;PLAY THE NOTE.
	jsr DECODE		;SCAN 8700 KYBD.
	cmp #PLC		;IS IT PLC?
	beq SPLITZ		;YES, GO TO SPLITZ.
	cmp #TAPE		;IS IT TAPE?
	beq PLOOP		;YES, GO TO POLY
	lda COUNT		;GET COUNT.
	beq CHORUS		;IF ZERO, START OVER.
	sta DISPLAY		;IF NOT, GIVE US A LOOK...
	bne IN			;AND KEEP ON CHORUS.
SPLITZ
	lda OUTS		;GET THE NUMBER OF AVAILABLE VOICES.
	sta OLDKEY		;USE AS COUNTER/POINTER.
SELECT
	sta OLDKEY		;STORE THE PRESENT NOTE FOR LATER.
	jsr NOTE		;REFRESH QUASH AND LOAD KTABLE.
	lda KTBLMAX		;GET LOWEST NOTE.
	beq SELECT		;IF ZERO, TRY AGAIN.
	ldy OLDKEY		;GET LAST NOTE>
	bne SELECT		;IF NOT ZERO, YOU"RE STILL HOLDING IT.
	ldy COUNT		;IT'S A NEW NOTE--GET COUNTER/POINTER
	sty DISPLAY		;SHOW THE COUNT.
	sta SPLIT,y		;STORE THE NOTE AS SPLIT POINT Y.
	dec COUNT		;NEXT SPLIT POINT.
	bne SELECT		;GO BACK UNTIL ALL SPLIT POINTS ARE IN.
	lda #$FF		;DUMMY SPLIT POINT...
	sta SPLITMIN	;STORED AT END OF TABLE.
PERF
	jsr CLEAR		;ALL SPLITS ARE IN, TURN OFF ALL GATES.
	ldx #8			;PREPARE TO TEST KTABLE.
NXTNOT
	lda KTBL,x		;GET NOTE X FROM IT.
	beq NXT2		;IF ZERO, DO NEXT.
	ldy OUTS		;GET COUNTER/POINTER
NXT0
	cmp SPLIT,y		;COMPARE NOTE TO SPLIT POINT Y.
	bcc NXT1		;IF LESS THAN, GO ASSIGN IT.
	dey				;NEXT SPLIT POINT.
	bne NXT0		;KEEP ON UNTIL YOU;VE CHECKED ALL.
NXT1
	sta (NTS),y		;ASSIGN NOTE TO CHANNEL Y.
NXT2
	dex				;NEXT KEYBOARD ENTRY.
	bne NXTNOT		;KEEP ON UNTIL ALL KEYBOARD DONE.
	jsr NOTE		;PLAY THE NOTES.
	lda CLK			;MORE BELLS AND
	sta DISPLAY		;WHISTLES.
	jsr DECODE		;SCAN 8700 KYBD.
	cmp #PCH		;IS IT PCH?
	beq CHORUS		;YES< GO TO CHORUS.
	cmp #ENT		;IS IT ENT?
	beq SPLITZ		;YES, GO GET NEW SPLIT POINTS.
	cmp #TAPE		;IS IT TAPE?
	bne PERF		;NO, KEEP ON PLAYING SPLITZ.
	jmp PLOOP		;YES, GO TO POLY.

CLEAR
	ldy OUTS		;GET POINTER/COUNTER.
NANO
	lda (NTS),y		;GET NOTE BEING PLAYED ON CHANNEL Y.
	and #$3F		;TURN OFF ITS GATE...
	sta (NTS),y		;AND PUT IT BACK.
	dey				;NEXT CHANNEL.
	bne NANO		;GO BACK UNTIL DONE.
	rts				;RETURN.
	