OS SERIES 8GEOFF COX**************************************************************************                                                                       **        OSBYTE &F7 (247) INTERCEPT BREAK                               **                                                                       **************************************************************************EAD9	LDA &0287   ;get BREAK vector codeEADC	EOR #&4C    ;produces 0 if JMP not in &287EADE	BNE &EAF3   ;if not goto EAF3EAE0	JMP &0287   ;else jump to user BREAK code**************************************************************************                                                                       **        OSBYTE &90 (144)   *TV                                         **                                                                       **************************************************************************    	    ;X=display delay    	    ;Y=interlace flagEAE3	LDA &0290   ;VDU vertical adjustmentEAE6	STX &0290   ;store new valueEAE9	TAX         ;put old value in XEAEA	TYA         ;put interlace flag in AEAEB	AND #&01    ;maximum value =1EAED	LDY &0291   ;get old value into YEAF0	STA &0291   ;put new value into AEAF3	RTS         ;and Exit**************************************************************************                                                                       **        OSBYTE &93 (147)  WRITE TO FRED                                **                                                                       **************************************************************************    	            ;X is offset within page    	            ;Y is byte to writeEAF4	TYA         ;EAF5	STA &FC00,X ;EAF8	RTS         ;**************************************************************************                                                                       **        OSBYTE &95 (149)  WRITE TO JIM                                 **                                                                       **************************************************************************    	            ;X is offset within page    	            ;Y is byte to write    	            ;EAF9	TYA         ;EAFA	STA &FD00,X ;EAFD	RTS         ;**************************************************************************                                                                       **        OSBYTE &97 (151)  WRITE TO SHEILA                              **                                                                       **************************************************************************    	            ;X is offset within page    	            ;Y is byte to writeEAFE	TYA         ;EAFF	STA &FE00,X ;EB02	RTS         ;****************** Silence a sound channel *******************************    	            ;X=channel numberEB03	LDA #&04    ;mark end of release phaseEB05	STA &0808,X ;to channel XEB08	LDA #&C0    ;load code for zero volume****** if sound not disabled set sound generator volume ******************EB0A	STA &0804,X ;store A to give basic sound level of ZeroEB0D	LDY &0262   ;get sound output/enable flagEB10	BEQ &EB14   ;if sound enabled goto EB14EB12	LDA #&C0    ;else load zero sound codeEB14	SEC         ;set carryEB15	SBC #&40    ;subtract &40EB17	LSR         ;divide by 8EB18	LSR         ;to get into bits 0 - 3EB19	LSR         ;EB1A	EOR #&0F    ;invert bits 0-3EB1C	ORA &EB3C,X ;get channel number into top nybbleEB1F	ORA #&10    ;EB21	PHP         ;EB22	SEI         ;disable interruptsEB23	LDY #&FF    ;System VIA port A all outputsEB25	STY &FE43   ;setEB28	STA &FE4F   ;output A on port AEB2B	INY         ;Y=0EB2C	STY &FE40   ;enable sound chipEB2F	LDY #&02    ;set andEB31	DEY         ;execute short delayEB32	BNE &EB31   ;EB34	LDY #&08    ;then disable sound chip againEB36	STY &FE40   ;EB39	LDY #&04    ;set delayEB3B	DEY         ;and loop delayEB3C	BNE &EB3B   ;EB3E	PLP         ;get back flagsEB3F	RTS         ;and exit*******: Sound parameters look up table **********************************EB40	DB  &E0,&C0,&A0,&80EB44	JMP &EC59   ;just to allow relative branches in early part    	            ;of sound interrupt routine**************************************************************************                                                                       **       PROCESS SOUND INTERRUPT                                         **                                                                       **************************************************************************EB47	LDA #&00    ;EB49	STA &083B   ;zero number of channels on hold for syncEB4C	LDA &0838   ;get number of channels required for syncEB4F	BNE &EB57   ;if this <>0 then EB57EB51	INC &083B   ;else number of chanels on hold for sync =1EB54	DEC &0838   ;number of channels required for sync =255EB57	LDX #&08    ;set loop counterEB59	DEX         ;loopEB5A	LDA &0800,X ;get value of &800 +offset (sound queue occupancy)EB5D	BEQ &EB44   ;if 0 goto EC59 no sound this channelEB5F	LDA &02CF,X ;else get buffer busy flagEB62	BMI &EB69   ;if negative (buffer empty) goto EB69EB64	LDA &0818,X ;else if duration count not zer0EB67	BNE &EB6C   ;goto EB6CEB69	JSR &EC6B   ;check and pick up new sound if requiredEB6C	LDA &0818,X ;if duration count 0EB6F	BEQ &EB84   ;goto EB84EB71	CMP #&FF    ;else if it is &FF (infinite duration)EB73	BEQ &EB87   ;go onto EB87EB75	DEC &081C,X ;decrement 10 mS countEB78	BNE &EB87   ;and if 0EB7A	LDA #&05    ;reset to 5EB7C	STA &081C,X ;to give 50 mSec delayEB7F	DEC &0818,X ;and decrement main counterEB82	BNE &EB87   ;if not zero then EB87EB84	JSR &EC6B   ;else check and get nw soundEB87	LDA &0824,X ;if step progress counter is 0 no envelope involvedEB8A	BEQ &EB91   ;so jump to EB91EB8C	DEC &0824,X ;else decrement itEB8F	BNE &EB44   ;and if not zero go on to EC59EB91	LDY &0820,X ;get  envelope data offset from (8C0)EB94	CPY #&FF    ;if 255 no envelope set soEB96	BEQ &EB44   ;goto EC59EB98	LDA &08C0,Y ;else get get step lengthEB9B	AND #&7F    ;zero repeat bitEB9D	STA &0824,X ;and store itEBA0	LDA &0808,X ;get phase counterEBA3	CMP #&04    ;if release phase completedEBA5	BEQ &EC07   ;goto EC07EBA7	LDA &0808,X ;else start new step by getting phaseEBAA	CLC         ;EBAB	ADC &0820,X ;add it to interval multiplierEBAE	TAY         ;transfer to YEBAF	LDA &08CB,Y ;and get target value base for envelopeEBB2	SEC         ;EBB3	SBC #&3F    ;EBB5	STA &083A   ;store modified number as current target amplitudeEBB8	LDA &08C7,Y ;get byte from envelope storeEBBB	STA &0839   ;store as current amplitude stepEBBE	LDA &0804,X ;get base volumelevelEBC1	PHA         ;save itEBC2	CLC         ;clear carryEBC3	ADC &0839   ;add to current amplitude stepEBC6	BVC &EBCF   ;if no overflowEBC8	ROL         ;double it Carry = bit 7EBC9	LDA #&3F    ;if bit =1 A=&3FEBCB	BCS &EBCF   ;into &EBCFEBCD	EOR #&FF    ;else toggle bits (A=&C0)    	            ;at this point the BASIC volume commands are converted    	            ; &C0 (0) to &38 (-15) 3 times, In fact last 3 bits    	            ;are ignored so &3F represents -15EBCF	STA &0804,X ;store in current volumeEBD2	ROL         ;multiply by 2EBD3	EOR &0804,X ;if bits 6 and 7 are equalEBD6	BPL &EBE1   ;goto &EBE1EBD8	LDA #&3F    ;if carry clear A=&3F (maximum)EBDA	BCC &EBDE   ;orEBDC	EOR #&FF    ;&C0 minimumEBDE	STA &0804,X ;and this is stored in current volumeEBE1	DEC &0839   ;decrement amplitude change per stepEBE4	LDA &0804,X ;get volume againEBE7	SEC         ;set carryEBE8	SBC &083A   ;subtract target valueEBEB	EOR &0839   ;negative value undicates correct trendEBEE	BMI &EBF9   ;so jump to next partEBF0	LDA &083A   ;else enter new phaseEBF3	STA &0804,X ;EBF6	INC &0808,X ;EBF9	PLA         ;get the old volume levelEBFA	EOR &0804,X ;and compare with the oldEBFD	AND #&F8    ;EBFF	BEQ &EC07   ;if they are the same goto EC07EC01	LDA &0804,X ;else set new levelEC04	JSR &EB0A   ;via EB0AEC07	LDA &0810,X ;get absolute pitch valueEC0A	CMP #&03    ;if it =3EC0C	BEQ &EC59   ;skip rest of loop as all sections are finishedEC0E	LDA &0814,X ;else if 814,X is not 0 current section is not    	            ;completeEC11	BNE &EC3D   ;so EC3DEC13	INC &0810,X ;else implement a section changeEC16	LDA &0810,X ;check if its completeEC19	CMP #&03    ;if notEC1B	BNE &EC2D   ;goto EC2DEC1D	LDY &0820,X ;else set A fromEC20	LDA &08C0,Y ;&820 and &8C0 (first envelope byte)EC23	BMI &EC59   ;if negative there is no repeatEC25	LDA #&00    ;else restart section sequenceEC27	STA &0830,X ;EC2A	STA &0810,X ;EC2D	LDA &0810,X ;get number of steps in new sectionEC30	CLC         ;EC31	ADC &0820,X ;EC34	TAY         ;EC35	LDA &08C4,Y ;EC38	STA &0814,X ;set in 814+XEC3B	BEQ &EC59   ;and if 0 then EC59EC3D	DEC &0814,X ;decrementEC40	LDA &0820,X ;and pick up rate of pitch changeEC43	CLC         ;EC44	ADC &0810,X ;EC47	TAY         ;EC48	LDA &08C1,Y ;EC4B	CLC         ;EC4C	ADC &0830,X ;add to rate of differential pitch changeEC4F	STA &0830,X ;and save itEC52	CLC         ;EC53	ADC &080C,X ;ad to base pitchEC56	JSR &ED01   ;and set new pitchEC59	CPX #&04    ;if X=4 (last channel)EC5B	BEQ &EC6A   ;goto EC6A (RTS)EC5D	JMP &EB59   ;else do loop againEC60	LDX #&08    ;X=7 againEC62	DEX         ;loopEC63	JSR &ECA2   ;clear channelEC66	CPX #&04    ;if not 4EC68	BNE &EC62   ;do it againEC6A	RTS         ;and return    	            ;EC6B	LDA &0808,X ;check for last channelEC6E	CMP #&04    ;is it 4 (release complete)EC70	BEQ &EC77   ;if so EC77EC72	LDA #&03    ;else mark release in progressEC74	STA &0808,X ;and store itEC77	LDA &02CF,X ;is buffer not emptyEC7A	BEQ &EC90   ;if so EC90EC7C	LDA #&00    ;else mark buffer not emptyEC7E	STA &02CF,X ;an store itEC81	LDY #&04    ;loop counterEC83	STA &082B,Y ;zero sync bytesEC86	DEY         ;EC87	BNE &EC83   ;until Y=0EC89	STA &0818,X ;zero duration countEC8C	DEY         ;and set sync count toEC8D	STY &0838   ;&FFEC90	LDA &0828,X ;get synchronising flagEC93	BEQ &ECDB   ;if its 0 then ECDBEC95	LDA &083B   ;else get number of channels on holdEC98	BEQ &ECD0   ;if 0 then ECD0EC9A	LDA #&00    ;elseEC9C	STA &0828,X ;zero note length intervalEC9F	JMP &ED98   ;and goto ED98ECA2	JSR &EB03   ;silence the channelECA5	TYA         ;Y=0 A=YECA6	STA &0818,X ;zero main countECA9	STA &02CF,X ;mark buffer not emptyECAC	STA &0800,X ;mark channel dormantECAF	LDY #&03    ;loop counterECB1	STA &082C,Y ;zero sync flagsECB4	DEY         ;ECB5	BPL &ECB1   ;ECB7	STY &0838   ;number of channels to &FFECBA	BMI &ED06   ;jump to ED06 ALWAYSECBC	PHP         ;save flagsECBD	SEI         ;and disable interruptsECBE	LDA &0808,X ;check for end of releaseECC1	CMP #&04    ;ECC3	BNE &ECCF   ;and if not found ECCFECC5	JSR &E45B   ;elseexamine bufferECC8	BCC &ECCF   ;if not empty ECCFECCA	LDA #&00    ;else mark channel dormantECCC	STA &0800,X ;ECCF	PLP         ;get back flagsECD0	LDY &0820,X ;if no envelope 820=&FFECD3	CPY #&FF    ;ECD5	BNE &ECDA   ;then terminate soundECD7	JSR &EB03   ;via EB03ECDA	RTS         ;else return    	            ;************ Synchronise sound routines **********************************ECDB	JSR &E45B   ;examine buffer if empty carry setECDE	BCS &ECBC   ;ECE0	AND #&03    ;else examine next word if>3 or 0ECE2	BEQ &EC9F   ;goto ED98 (via EC9F)ECE4	LDA &0838   ;else get synchronising countECE7	BEQ &ECFE   ;in 0 (complete) goto ECFEECE9	INC &0828,X ;else set sync flagECEC	BIT &0838   ;if 0838 is +ve S has already been set soECEF	BPL &ECFB   ;jump to ECFBECF1	JSR &E45B   ;else get first byteECF4	AND #&03    ;mask bits 0,1ECF6	STA &0838   ;and store resultECF9	BPL &ECFE   ;Jump to ECFE (ALWAYS!!)ECFB	DEC &0838   ;decrement 0838ECFE	JMP &ECD0   ;and silence the channel if envelope not in use************ Pitch setting ***********************************************ED01	CMP &082C,X ;If A=&82C,X then pitch is unchangedED04	BEQ &ECDA   ;then exit via ECDAED06	STA &082C,X ;store new pitchED09	CPX #&04    ;if X<>4 then not noise soED0B	BNE &ED16   ;jump to ED16*********** Noise setting ************************************************ED0D	AND #&0F    ;convert to chip formatED0F	ORA &EB3C,X ;ED12	PHP         ;save flagsED13	JMP &ED95   ;and pass to chip control routine at EB22 via ED95ED16	PHA         ;ED17	AND #&03    ;ED19	STA &083C   ;lose eigth tone surplusED1C	LDA #&00    ;ED1E	STA &083D   ;ED21	PLA         ;get back AED22	LSR         ;divide by 12ED23	LSR         ;ED24	CMP #&0C    ;ED26	BCC &ED2F   ;ED28	INC &083D   ;store resultED2B	SBC #&0C    ;with remainder in AED2D	BNE &ED24   ;    	            ;at this point 83D defines the Octave    	            ;A the semitone within the octaveED2F	TAY         ;Y=AED30	LDA &083D   ;get octave number into AED33	PHA         ;push itED34	LDA &EDFB,Y ;get byte from look up tableED37	STA &083D   ;store itED3A	LDA &EE07,Y ;get byte from second tableED3D	PHA         ;push itED3E	AND #&03    ;keep two LS bits onlyED40	STA &083E   ;save themED43	PLA         ;pull second table byteED44	LSR         ;push hi nybble into lo nybbleED45	LSR         ;ED46	LSR         ;ED47	LSR         ;ED48	STA &083F   ;store itED4B	LDA &083D   ;get back octave numberED4E	LDY &083C   ;adjust for surplus eighth tonesED51	BEQ &ED5F   ;ED53	SEC         ;ED54	SBC &083F   ;ED57	BCS &ED5C   ;ED59	DEC &083E   ;ED5C	DEY         ;ED5D	BNE &ED53   ;ED5F	STA &083D   ;ED62	PLA         ;ED63	TAY         ;ED64	BEQ &ED6F   ;ED66	LSR &083E   ;ED69	ROR &083D   ;ED6C	DEY         ;ED6D	BNE &ED66   ;ED6F	LDA &083D   ;ED72	CLC         ;ED73	ADC &C43D,X ;ED76	STA &083D   ;ED79	BCC &ED7E   ;ED7B	INC &083E   ;ED7E	AND #&0F    ;ED80	ORA &EB3C,X ;ED83	PHP         ;push PED84	SEI         ;bar interruptsED85	JSR &EB21   ;set up chip access 1ED88	LDA &083D   ;ED8B	LSR &083E   ;ED8E	ROR         ;ED8F	LSR &083E   ;ED92	ROR         ;ED93	LSR         ;ED94	LSR         ;ED95	JMP &EB22   ;set up chip access 2 and return**************** Pick up and interpret sound buffer data *****************ED98	PHP         ;push flagsED99	SEI         ;disable interruptsED9A	JSR &E460   ;read a byte from bufferED9D	PHA         ;push AED9E	AND #&04    ;isolate H bitEDA0	BEQ &EDB7   ;if 0 then EDB7EDA2	PLA         ;get back AEDA3	LDY &0820,X ;if &820,X=&FFEDA6	CPY #&FF    ;envelope is not in useEDA8	BNE &EDAD   ;EDAA	JSR &EB03   ;so call EB03 to silence channelEDAD	JSR &E460   ;clear buffer of redundant dataEDB0	JSR &E460   ;and againEDB3	PLP         ;get back flagsEDB4	JMP &EDF7   ;set main duration count using last byte from bufferEDB7	PLA         ;get back AEDB8	AND #&F8    ;zero bits 0-2EDBA	ASL         ;put bit 7 into carryEDBB	BCC &EDC8   ;if zero (envelope) jump to EDC8EDBD	EOR #&FF    ;invert AEDBF	LSR         ;shift rightEDC0	SEC         ;EDC1	SBC #&40    ;subtract &40EDC3	JSR &EB0A   ;and set volumeEDC6	LDA #&FF    ;A=&FFEDC8	STA &0820,X ;get envelope no.-1 *16 into AEDCB	LDA #&05    ;set duration sub-counterEDCD	STA &081C,X ;EDD0	LDA #&01    ;set phase counterEDD2	STA &0824,X ;EDD5	LDA #&00    ;set step counterEDD7	STA &0814,X ;EDDA	STA &0808,X ;and envelope phaseEDDD	STA &0830,X ;and pitch differentialEDE0	LDA #&FF    ;EDE2	STA &0810,X ;set step countEDE5	JSR &E460   ;read pitchEDE8	STA &080C,X ;set itEDEB	JSR &E460   ;read bufferEDEE	PLP         ;EDEF	PHA         ;save durationEDF0	LDA &080C,X ;get back pitch valueEDF3	JSR &ED01   ;and set itEDF6	PLA         ;get back durationEDF7	STA &0818,X ;set itEDFA	RTS         ;and return********************* Pitch look up table 1*****************************EDFB	    DB         &F0EDFC	    DB         &B7EDFD	    DB         &82EDFE	    DB         &4FEDFF	    DB         &20EE00	    DB         &F3EE01	    DB         &C8EE02	    DB         &A0EE03	    DB         &7BEE04	    DB         &57EE05	    DB         &35EE06	    DB         &16********************* Pitch look up table 2 *****************************EE07	    DB         &E7EE08	    DB         &D7EE09	    DB         &CBEE0A	    DB         &C3EE0B	    DB         &B7EE0C	    DB         &AAEE0D	    DB         &A2EE0E	    DB         &9AEE0F	    DB         &92EE10	    DB         &8AEE11	    DB         &82EE12	    DB         &7A*********: set current filing system ROM/PHROM **************************EE13	LDA #&EF    ;get ROMEE15	STA &F5     ;store itEE17	RTS         ;return********** Get byte from data ROM ***************************************EE18	LDX #&0D    ;X=13EE1A	INC &F5     ;EE1C	LDY &F5     ;get RomEE1E	BPL &EE59   ;if +ve it's a sideways ROM else it's a PHROMEE20	LDX #&00    ;PHROMEE22	STX &F7     ;set address pointer in PHROMEE24	INX         ;EE25	STX &F6     ;to 0001EE27	JSR &EEBB   ;pass info to speech processorEE2A	LDX #&03    ;X=3EE2C	JSR &EE62   ;check for speech processor and output until    	            ;it reports, read byte from ROMEE2F	CMP &DF0C,X ;if A<> DF0C+X then EE18 (DF0C = (C))EE32	BNE &EE18   ;EE34	DEX         ;else decrement XEE35	BPL &EE2C   ;and do it againEE37	LDA #&3E    ;EE39	STA &F6     ;get noe lo byte addressEE3B	JSR &EEBB   ;pass info to speech processorEE3E	LDX #&FF    ;EE40	JSR &EE62   ;check for speech proc. etc.EE43	LDY #&08    ;EE45	ASL         ;EE46	ROR &F7,X   ;EE48	DEY         ;EE49	BNE &EE45   ;EE4B	INX         ;EE4C	BEQ &EE40   ;EE4E	CLC         ;EE4F	BCC &EEBB   ;************ ROM SERVICE ************************************************EE51	LDX #&0E    ;EE53	LDY &F5     ;if Y is negative (PHROM)EE55	BMI &EE62   ;GOTO EE62EE57	LDY #&FF    ;else Y=255EE59	PHP         ;push flagsEE5A	JSR &F168   ;offer paged rom serviceEE5D	PLP         ;pull processor flagsEE5E	CMP #&