TITLE 4-VOICE MIDI CONTROLLER RUN-TIME CODE * * * OBHM. MICRO-CONTROLLER MEMORY MAP * * * ADDRESS DEVICE * ------------------------------------------------------------------ * 0 I * I 8K RAM (5564) * 1FFF I * * 2000 I * I 8K RAM (5564) NON-VOLATILE MEMORY * 3FFF I * * 4000 I * I HOLE * 5FFF I * * 6000 I 6821 PIA { DATA DIRECTION REGISTER (A) * I { CONTROL REGISTER (A) * I { DATA DIRECTION REGISTER (B) * 6003 I { CONTROL REGISTER (B) * * 6004 I 8253 TIMER { COUNTER #1 (WRITE/READ) * I { COUNTER #2 (WRITE/READ) * I { COUNTER #3 (WRITE/READ) * 6007 I { MODE REGISTER (WRITE ONLY) * * 6008 I 6850 ACIA (MIDI PORT) { CONTROL/STATUS REGISTER * 6009 I { WRITE/READ DATA * * 600A I FLAGS FROM 8253 TIMER AND IRQ SWITCH * I (LOW 3 BITS ARE #1,#2,#3; 4'TH BIT = CLOCK; 5'TH BIT = IRQ) * * 600B I PITCH-BEND SENSITIVITY DAC (FULL 8 BITS) * * 600C I PITCH-BEND DAC { MSB (TOP 7 BITS) * 600D I { LSB (LOW 5 BITS) * * 600E I VCF MODULATION * * 600F I LOUDNESS COMPENSATION (0 = OFF, NONZERO = ON) * * 6010 I * I 12-CHARACTER ASCII DISPLAY * 601B I * * 601C I * I UNUSED * 601F I * * 6020 | OUTPUT VOLUME CONTROL * 6021 | OUTPUT STEREO BALANCE CONTROL * 6022 | OUTPUT BASS CONTROL * 6023 | OUTPUT TREBLE CONTROL * * 6024 | VCF BASE FREQUENCY * 6025 | VCF MODULATION RANGE * * 6026 | STEREO ENHANCE EFFECT (0 = OFF, 127 = ON) * 6027 | STEREO/MONO SWITCH (0 = OFF, 127 = ON) * * 6028 I * I UNUSED * CFFF I * * D000 I * I 16K EPROM (27128) * FFFF I * * * NOTES ON PIA: * * LOW 5 BITS ON PORT A ARE KEYPAD INPUT. * BIT #6 ON PORT A IS KEYPAD STROBE INPUT. * BIT #8 ON PORT A IS A DISPLAY CLEAR OUTPUT. * BIT #7 ON PORT A IS A DISPLAY CURSOR ENABLE OUTPUT. * CA1 IS A KEYPAD STROBE/GATE INTERRUPT INPUT. * PORT B IS THE OBHM. BUS OUTPUT. * CB2 IS THE OBHM. BUS STROBE OUTPUT. * PAGE ********************************************************************** * * PATCH EDITOR AND RUN PACKAGE FOR 6809 OBHM. CONTROLLER * * -- 13-MARCH.- 88 -- J. PARADISO * -- 19-NOV.-89 UPDATED FOR HARDWARE MODS. & UPGRADES -- J. PARADISO * -- 21-AUG.-90 UPDATED TO HANDLE THOSE HARDWARE MODS/UPGRADES/BUGS -- J. PARADISO * ********************************************************************** * * SPECIAL SYMBOL DEFINITIONS * ********************************************** * * DEVICES........... *--------------------------------------------- * * PIA ADDRESSES * PIACA EQU $6001 PIA A-CONTROL REG. PIACB EQU $6003 PIA B-CONTROL REG. PIADA EQU $6000 PIA A-DATA REG. PIADB EQU $6002 PIA B-DATA REG. * * ACIA ADDRESSES * ACIACR EQU $6008 ACIA CONTROL REG. ACIADR EQU $6009 ACIA DATA REG. * * TIMER ADDRESSES * TMRCR EQU $6007 TIMER CONTROL REG. TMR0 EQU $6004 TIMER #1 IN/OUT REG. TMR1 EQU $6005 TIMER #2 IN/OUT REG. TMR2 EQU $6006 TIMER #3 IN/OUT REG. TMROUT EQU $600A TIMER OUTPUT FLAGS * * PITCH-BEND ADDRESSES * PBSENS EQU $600B PITCH-BEND SENSITIVITY DAC PBLOW EQU $600D PITCH-BEND DAC: LOW BYTE PBHI EQU $600C PITCH-BEND DAC: HIGH BYTE * * DISPLAY ADDRESSES * DSPLY0 EQU $6010 ADDRESS OF LOWEST DISPLAY CHAR. * * VCF CONTROL ADDRESSES * VCFMOD EQU $600E VCF MODULATION DAC VCFSEN EQU $6025 VCF MODULATION SENSITIVITY DAC VCF0 EQU $6024 VCF BASE-FREQUENCY DAC * * TONE/VOLUME/BALANCE EFFECTS ADDRESSES * OUTVOL EQU $6020 VOLUME CONTROL OUTBAL EQU $6021 STEREO BALANCE CONTROL OUTBAS EQU $6022 BASS CONTROL OUTTRB EQU $6023 TREBLE CONTROL OUTCMP EQU $600F LOUDNESS COMPENSATION (ON/OFF) OUTENH EQU $6026 STEREO ENHANCE (ON/OFF) OUTSTM EQU $6027 STEREO/MONO SWITCH (ON/OFF) * PAGE * * DEVICE CODES *--------------------------------------------------------- * * PIA DATA * CUE EQU $40 TURN DISPLAY CURSOR ON KSTRBE EQU $20 MASK FOR KEYPAD STROBE PCTLA EQU $37 CONTROL BYTE FOR PIA-A PCTLB0 EQU $3C TURN PIA-B STROBE ON PCTLB1 EQU $34 TURN PIA-B STROBE OFF PCTLB2 EQU $2C PUT PIA-B STROBE IN AUTO MODE * * ACIA DATA * ACIANI EQU $56 ACIA CONTROL BYTE; NO INTERRUPTS ACIARI EQU $D6 ACIA CONTROL BYTE; RECEIVE INTERRUPTS ACIAXI EQU $B6 ACIA CONTROL BYTE; XMIT/REC. INTERRUPTS * * TIMER DATA * T0SEQ EQU $30 CHOOSE T0; TIMER BYTES SEQUENTIAL T0LSB EQU $10 CHOOSE T0; LSB ONLY * * PITCH-BEND DATA * PBNULL EQU $4000 NULL PBEND FOR OUTPUT DEVICES PBOFF EQU $4014 NULL FOR OB. PITCH-BEND PBIAS EQU $14 BEND NULL BIAS * * MIDI DATA * MNOFF EQU 0 NOTE-OFF CODE MNON EQU 1 NOTE-ON CODE MPLYKY EQU 2 POLY-KEY PRESSURE MCTLCH EQU 3 CONTROL-CHANGE CODE MPCHG EQU 4 PROGRAM-CHANGE CODE MCHPR EQU 5 CHANNEL-PRESSURE CODE MPBND EQU 6 PITCH-BEND CODE MRTIME EQU 7 REAL-TIME/SYS-EX CODE * * KEYPAD DATA * DOTKEY EQU 10 "." KEY EQUALS EQU 11 "=" KEY PLUS EQU 12 "+" KEY XKEY EQU 13 "X" KEY DIVIDE EQU 14 DIVIDE KEY MINUS EQU 15 "-" KEY KKEY EQU 16 "K" KEY CLEAR EQU 17 CLEAR KEY ENTER EQU 18 ENTER KEY PUNT EQU 19 PUNT KEY * * OBHM. KEYBOARD MAP * TOPNTE EQU 63 TOP IN GENERAL HLFNTE EQU 23 TOP OF LOWER SPLIT * PAGE * * MEMORY & PATCH ORGANIZATION *------------------------------------------------------------ * * PATCH DIMENSIONS * MAXPCH EQU 98 MAX. # OF PATCHES (-1) TOTVAR EQU 76 NO. OF VARIABLES IN COMPRESSED PATCH MXLVL0 EQU 7 # OF LEVEL 0 HEADINGS * * SYS-EX CODES * PCHALL EQU 100 SYS-EX PATCH # TO DUMP ALL PATCHES PCHLOC EQU 101 SYS-EX PATCH # TO DUMP ONLY LOCAL PATCH STRDMP EQU 127 SYS-EX PATCH # TO DUMP DATA STRUCTURE * * STACK ADDRESSES * HSTK0 EQU $1AFF HARDWARE STACK START USTK0 EQU $1FFF USER STACK START * * MIDI BUFFERS * ADIBUF EQU 1000 MIDI INPUT BUFFER START ADIMAX EQU 3999 MIDI INPUT BUFFER END ADOBUF EQU 4000 MIDI OUTPUT BUFFER START ADOMAX EQU 4250 MIDI OUTPUT BUFFER END NBYOMX EQU ADOMAX-ADOBUF+1 MAX. NUMBER OF MIDI OUTPUT BYTES * * SYSEX. PATCH BUFFER * PEBUF EQU ADOMAX+1 * PAGE * * DEFINITION OF PROGRAM SEGMENT ADDRESSES *------------------------------------------------------------- * DEFS GLOBALS,$0 GLOBAL VARIABLE DECLARATIONS DEFS NVRAM,$2000 DEFS PROGRAM,$C000 PROGRAM (EPROM) START DEFS VECTORS,$FFF2 6809 TRAP VECTORS * PAGE * * NON-VOLATILE RAM *---------------------------------------------------------------------- * SEG NVRAM NVRAM0 RMB (MAXPCH+1)*TOTVAR PATCH STORAGE AUTCRD RMB (MAXPCH+1)*2 AUTOCHORD INTERVAL STORAGE NONTE RMB 1 # OF NOTES IN NOTE TABLE NTETAB RMB 128 NOTE TABLE WRTPRT RMB 1 WRITE-PROTECT FLAG NVMPCH RMB 1 INDEX OF LAST LOADED PATCH * * * ---- PAGE 0 MEMORY ADDRESSES & GLOBAL VARIABLES ---- *----------------------------------------------------------------------- * SEG GLOBALS * * CHARACTER INPUT VARIABLES * CHRBUF RMB 1 CHARACTER BUFFER FOR KEY INTERRUPT CHRFLG RMB 1 CHARACTER FLAG FOR KEY INTERRUPT PNTFLG RMB 1 SET IF CANCEL ENTERED ON READ * * MIDI INPUT / OUTPUT * ADFIN RMB 2 FOREGROUND MIDI INPUT BUFFER POINTER ADRIN RMB 2 BACKGROUND MIDI INPUT BUFFER POINTER ADFOUT RMB 2 FOREGROUND MIDI OUTPUT BUFFER POINTER ADROUT RMB 2 BACKGROUND MIDI OUTPUT BUFFER POINTER NREADH RMB 1 NUMBER OF MIDI INPUT BYTES OUTSTANDING NREAD RMB 1 LOW BYTE OF ABOVE NWRITE RMB 1 NUMBER OF MIDI OUTPUT BYTES OUTSTANDING ACRSAV RMB 1 ACIA STATUS STORAGE XMTINT RMB 1 FLAG INDICATING INTERRUPT ON XMIT * * PATCH DATA * PNUM RMB 1 PATCH # PNAME RMB 9 PATCH TITLE * CHNL0 RMB 1 BASIC MIDI CHANNEL OMNIFG RMB 1 OMNI ON/OFF FLAG MONOFG RMB 1 MONO ON/OFF FLAG KPRTY RMB 1 KEYBOARD PRIORITY KREALC RMB 1 KEYBOARD REALLOCATION FLAG (ON NTE OFF) TRNPSE RMB 1 KEY TRANSPOSE AUTOCT RMB 1 AUTOCUT FLAG AUTINT RMB 1 AUTOCUT INTERVAL KYSAFE RMB 1 KEY TRIGGER SAFEING * CMDNTE RMB 1 4-V CONTROL OBPGRM RMB 1 4-V PROGRAM PBRNGE RMB 1 PITCH-BEND RANGE PMNMDE RMB 1 PRTMNTO MODE PMNTME RMB 1 PRTMNTO TIME UNISON RMB 1 UNISON ON/OFF SPLTMD RMB 1 SPLIT MODE RSNMDE RMB 1 REASSIGN MODE ASSIGN RMB 1 ASSIGN MODE OCTAVE RMB 1 OCTAVE TRANSPOSE VCFBSE RMB 1 VCF BASE FREQUENCY VCFSWP RMB 1 VCF SWEEP SENSITIVITY VCFCTL RMB 1 VCF CONTROLLER SELECTION VCFVEL RMB 1 VCF VELOCITY SENS. * CHNL1 RMB 1 MIDI OUTPUT CHANNEL XMITMD RMB 1 XMIT MODE SENDMD RMB 1 SEND MODE SNDPB RMB 1 SEND PBEND FILLMD RMB 1 FILL MODE FILLNT RMB 1 FILL NOTE NVOICE RMB 1 #VOICES ON OUTPUT DLYTRG RMB 1 DELAY-TRIGGER FLAG NTETRG RMB 1 NOTE-ON UPON NOTE RELEASE FLAG NTETME RMB 1 HOLD TIME FOR NOTE-ON @ RELEASE NTMVLS RMB 1 RVEL SENS. FOR ABOVE NBUFKY RMB 1 NOTE BUFFER TRIGGER KEY OVFPLY RMB 1 OVERFLOW/TABLE NOTES FLAG OVFORD RMB 1 OVERFLOW TABLE ORDER OVFVEL RMB 1 OVERFLOW ORDER VELOCITY SENSITIVITY * APMNTO RMB 1 AUTO-PRTMNTO FLAG AVPMPT RMB 1 A-VEL EFFECT ON AUTO-P AVSAPT RMB 1 A-VEL SIGN EFFECT ON AUTO-P APTDST RMB 1 AUTO-PRMNTO DESTINATION DLYAPT RMB 1 NOTE START DELAY * ABEND RMB 1 AUTO-BEND FLAG RVDRBD RMB 1 R-VEL DIRECTION BARDIR RMB 1 BEND-DIR. ON ATK OR RLS RVSBND RMB 1 R-VEL EFFECT RVSSNB RMB 1 R-VEL SENSE SBBND RMB 1 SWEEP BIAS MXBND RMB 1 MAX. SWING RTEBND RMB 1 BEND RATE MNHBND RMB 1 MIN. KEY HOLD TGMBND RMB 1 BEND TRIGGER MODE CTLBND RMB 1 OUTPUT CONTROLLER # OCLBND RMB 1 DESTINATION FLAG IVLBND RMB 1 INITIAL CTLR. VALUE UPON RESET TKYBND RMB 1 BEND TRIGGER NOTE # (+1) VCFBND RMB 1 BEND FEED INTO VCF VOLBND RMB 1 BEND FEED INTO VOLUME BALBND RMB 1 BEND FEED INTO BALANCE BASBND RMB 1 BEND FEED INTO BASS TRBBND RMB 1 BEND FEED INTO TREBLE * ATRILL RMB 1 AUTO-TRILL FLAG AVSTRL RMB 1 A-VEL EFFECT TARDIR RMB 1 A-VEL SENSE RVSTRL RMB 1 R-VEL EFFECT RVSSNT RMB 1 R-VEL SENSE SBTRL RMB 1 SWEEP BIAS RTBTRL RMB 1 RATE BIAS MXTRL RMB 1 MAX. TRILL MNHTRL RMB 1 MIN. KEY HOLD TGMTRL RMB 1 TRILL TRIGGER MODE CTLTRL RMB 1 OUTPUT CONTROLLER # OCLTRL RMB 1 DESTINATION FLAG IVLTRL RMB 1 INITIAL CTLR. VALUE UPON RESET TKYTRL RMB 1 TRILL TRIGGER NOTE # (+1) VCFTRL RMB 1 TRILL FEED INTO VCF VOLTRL RMB 1 TRILL FEED INTO VOLUME BALTRL RMB 1 TRILL FEED INTO BALANCE BASTRL RMB 1 TRILL FEED INTO BASS TRBTRL RMB 1 TRILL FEED INTO TREBLE PWTRLL RMB 1 TRILL PULSE WIDTH TRLSEL RMB 1 TRILL WAVE SELECT TRLPOL RMB 1 TRILL POLARITY FLAG * TVBVOL RMB 1 VOLUME VOLSNS RMB 1 VOLUME VEL. SENSITIVITY TVBBAL RMB 1 BALANCE BALSNS RMB 1 BALANCE VEL. SENSITIVITY TVBBAS RMB 1 BASS BASSNS RMB 1 BASS VEL. SENSITIVITY TVBTRB RMB 1 TREBLE TRBSNS RMB 1 TREBLE VEL. SENSITIVITY TVBSTM RMB 1 STEREO/MONO TVBENH RMB 1 STEREO ENHANCE TVBLDC RMB 1 LOUDNESS COMPENSATION * TOTVP EQU TVBLDC-PNUM+1 TOTAL NO. OF BYTES PER LOADED PATCH * * MIDI OUTPUT INTERMEDIATE BUFFER * OCOUNT RMB 1 OUTPUT COUNT ODATSS RMB 1 1 BYTE FOR STATUS ODATAS RMB 3 3 OUTPUT BYTES STATLO RMB 1 LAST STATUS CODE OUTPUT CHANLO RMB 1 LAST CHANNEL FOR OUTPUT CHONOW RMB 1 LOCAL STORAGE NTEQQQ RMB 1 NTOFIL RMB 1 LOCVLO RMB 1 OUTVLX RMB 1 * * MIDI COMMAND INTERPRETER * LSTAT RMB 1 OLDSTT RMB 1 OBSTAT RMB 1 STAOUT RMB 1 MPHASE RMB 1 MSYEX RMB 1 MEX RMB 1 MDILBF RMB 1 MIDICB RMB 1 PBLSB RMB 1 CTLNR RMB 1 PCHLX RMB 1 PCHCTX RMB 1 SXNLV0 RMB 1 MEXBUF RMB 1 MADDX RMB 1 MCMDX RMB 1 M1PHX RMB 1 MEBUFF RMB 1 MCHL RMB 1 LSTNBF RMB 1 MCHLX RMB 1 NONDLY RMB 1 SAFEFG RMB 1 LDNOTE RMB 1 NTECNT RMB 1 * * NOTE ALLOCATION * NONOUT RMB 1 # NOTES ON IN OUTPUT NTESND RMB 4 4-BYTES FOR NOTES-SOUNDING IN 4-V SUSTFG RMB 1 SUSTAIN QUEUE NDOWN RMB 1 # NOTES DOWN (TOTAL) NTAKEN RMB 1 # NOTES TAKEN (TOTAL) NQUEQ RMB 1 NDOWNL RMB 1 NDOWNH RMB 1 LSTNTE RMB 1 LSTVEL RMB 1 LSTAVL RMB 1 LSTRVL RMB 1 KEYHLF RMB 1 NTCVAL RMB 1 NTEOB0 RMB 1 NAVAIL RMB 1 HLFBS RMB 1 NTAKNL RMB 1 NTAKNR RMB 1 NREALC RMB 1 VREALC RMB 1 NTENOW RMB 1 NFIN RMB 1 NHLFG RMB 1 NPTRA RMB 1 NTELOC RMB 1 LOCDLY RMB 1 NOSPLT RMB 2 (X2) NTSCUT RMB 1 NTOPCT RMB 1 NRVCUT RMB 1 NSTRQ RMB 1 SCNINC RMB 1 NOVRQ RMB 1 NBTMCT RMB 1 LSTPLC RMB 1 CUTCNT RMB 1 CTROOT RMB 1 NEGFLG RMB 1 * * AUTO BEND / AUTO TRILL DATA & FLAGS * ATACTV RMB 1 AUTO-TRILL ACTIVE ABACTV RMB 1 AUTO-BEND ACTIVE ZFSSQ RMB 1 AB/AP CLEAR SHAPPP RMB 1 SHAPPT RMB 1 APBCNT RMB 2 (X2) APBOUT RMB 2 (X2) APBGO RMB 1 APBSGN RMB 1 TRLLMT RMB 1 TRLSUM RMB 1 TRLSGN RMB 1 TRLOUT RMB 1 TRLCNT RMB 1 ATRATE RMB 2 (X2) ATRTED RMB 2 (X2) OCSUMQ RMB 1 PBSMQT RMB 2 (X2) BSTMP RMB 1 LSTACT RMB 1 OPBFLG RMB 1 ABTGED RMB 1 ATTGED RMB 1 TRKBND RMB 1 TRKTRL RMB 1 BCTOFF RMB 1 TCTOFF RMB 1 TGLSGN RMB 1 TSSGN RMB 1 PBSLOC RMB 1 PBFGG RMB 1 VCFB00 RMB 2 VOLB00 RMB 2 BALB00 RMB 2 BASB00 RMB 2 TRBB00 RMB 2 VCFTGG RMB 1 VOLTGG RMB 1 BALTGG RMB 1 BASTGG RMB 1 TRBTGG RMB 1 TSSGNV RMB 1 * * GENERAL FLAGS * ODLYON RMB 1 NOTE-ON OUTPUT DELAY ACTIVE CLRFLG RMB 1 CLEAR IS CUEUED NCTLTG RMB 1 DELAYED-NOTE CONTROLLER TRIGGER FLAG * * ADDED 8/90 * LOCVOL RMB 1 LOCBAL RMB 1 LOCBAS RMB 1 LOCTRB RMB 1 OVFON RMB 1 OVFVLB RMB 1 OVDIR RMB 1 OVIND RMB 1 OBIVAL RMB 3 PORTBF RMB 1 PORTON RMB 1 * * PATCH EDITOR VARIABLES * N0 RMB 1 LEVEL0 POINTER N1 RMB 1 LEVEL1 POINTER LDOBH RMB 1 FLAG INDICATING OB. IS TO BE LOADED PCHLDQ RMB 1 PATCH TO LOAD DATAID RMB 1 DATAI RMB 1 OFFSET FOR NUMERIC INPUT TQTRIG RMB 1 TRIGGER FLAG FOR ALP. INPUT TMPINM RMB 1 TEMPORARY FOR NUMERIC INPUT DSPOFF RMB 1 DISPLAY OFFSET NCHRSI RMB 1 #CHARACTERS FOR NUMERIC INPUT LMTPLD RMB 1 LMTPLS RMB 1 "+" LIMIT ON INPUT LMTMND RMB 1 LMTMNS RMB 1 "-" LIMIT ON INPUT L1OFST RMB 1 LEVEL1 OFFSET N1ITMS RMB 1 # LEVEL1 ITEMS INPTMP RMB 1 INPUT STORAGE IDXDEC RMB 1 DECIMAL COUNT I1TM RMB 1 INPADR RMB 2 ADDRESS OF INPUT VARIABLE (NUM.) INPADC RMB 2 ADDR. OF INPUT VARIABLE (CHAR.) CPTCH RMB 1 STORAGE FOR TITLE-EDIT ROUTINE NCK RMB 1 " " NCKD RMB 1 " " TMPCHR RMB 1 " " CINC RMB 1 " " CHRZRO RMB 1 FLAG FOR ZERO CHAR. REPLACEMENT ZROREP RMB 2 ADDR. OF TEXT FOR ZERO REPL. WTDS1 RMB 1 WRITE DECIMAL STORAGE WTDS2 RMB 1 " " TMKMDE RMB 1 FLAG FOR TIMED WAIT MODE SVPQ RMB 1 BUFFER FOR SAVE-COMPRESS ROUTINE CTRQ1 RMB 1 GENERIC COUNTER 1 CTRQ2 RMB 1 GENERIC COUNTER 2 LSTPCH RMB 9 9 CHARACTERS RESERVED FOR LAST PATCH CTRQX RMB 1 GENERIC COUNTER 3 PNUMZ RMB 1 SAVL0 STORAGE OF PATCH NUMBER LDUTVB RMB 1 LOAD TVB FLAG * * NOTE LISTS * MMBUFF RMB 6 NCTLST RMB 4 NLST4V RMB 64 4-V NOTE LIST OUTLST RMB 128 OUTPUT DEVICE LIST OUTREV RMB 128 OUTPUT DEVICE QUEUE (REVERSE N-ON) STSVEL RMB 64 SUSTAIN LIST FILQUE RMB 64 OUTPUT VOICE FILLER LIST (64 NOTES MAX.) XLIST RMB 128 OUTPUT NOTE REASSIGN LIST * * MEMORY SIZES * LOWMEM EQU OBIVAL+1 TOTMEM EQU $+1 * PAGE ********************************************************************* * SEG PROGRAM 16K EPROM ASSUMED @ END OF MEMORY * ********************************************************************* * * INTERRUPT SERVICE ROUTINES * ********************************************************************* * * KEYPAD INTERRUPT ROUTINE (ON NMI) * KEYSRV LDA PIADA READ KEY DATA ANDA #$1F MASK OUT UNUSED BITS STA CHRBUF STORE IN CHARACTER BUFFER INC CHRFLG SET CHARACTER FLAG RTI RETURN.... ******************************************************************** * * MIDI INTERRUPT ROUTINE (ON FIRQ AND SWI) * ********************************************************************* * MIDISV PSHS A,B,X SAVE NEEDED REGS. LDA ACIACR GET ACIA STATUS STA ACRSAV STASH IT... TFR A,B COPY IT... ANDB #1 HAS NEW DATA COME IN?? BEQ MIDIXT NO.. CHECK XMIT INC NREAD COUNT ANOTHER BYTE IN BUFFER BNE MINOK BR. IF NO CARRY INC NREADH INC. HIGH BYTE MINOK LDX ADFIN GET BUFFER COUNT LDB ACIADR GET DATA STB ,X+ STORE IT IN OUTPUT BUFFER CMPX #ADIMAX BUFFER AT TOP? BLE NOSETI NOT SO.... LDX #ADIBUF RESET BUFFER POINTER NOSETI STX ADFIN REPLACE BUFFER POINTER CMPX ADRIN MIDI OVERFLOW??? BNE MIDIXT NO.. CHECK FOR XMIT LDX #OVFMSG CLRB LBSR PRTCHR PRINT OVERFLOW MESSAGE MIDIXT TST NWRITE IS ANY DATA QUEUED FOR XMIT?? BEQ MDIRTN NOPE.. RETURN ANDA #2 CHECK FOR ACIA XMIT BUSY BEQ MDIBSY BR. IF ACIA BUSY DEC NWRITE DEC. WRITE-BUFFER COUNTER LDX ADFOUT GET OUTPUT BUFFER ADDRESS LDB ,X+ GET NEXT OUTPUT BYTE STB ACIADR XMIT IT! CMPX #ADOMAX ARE WE @ MAXIMUM?? BLE NOSETO NO.. BR. LDX #ADOBUF RESET OUTPUT POINTER NOSETO STX ADFOUT REPLACE BUFFER POINTER MDIBSY TST XMTINT TEST XMIT INTERRUPT FLAG BNE MDIRTI RETURN IF SET INC XMTINT SET XMIT INTERRUPT FLAG LDB #ACIAXI STB ACIACR ENABLE XMIT INTERRUPT BRA MDIRTI RETURN... MDIRTN TST XMTINT TEST XMIT INTERRUPT FLAG BEQ MDIRTI RETURN IF NOT SET CLR XMTINT CLEAR XMIT INTERRUPT FLAG LDB #ACIARI STB ACIACR DISABLE XMIT INTERRUPT MDIRTI PULS A,B,X RESTORE USED REGISTERS RTI RETURN... * OVFMSG FCB 12 FCC /MIDI OVFLOW!/ * ********************************************* * * IRQ INTERRUPT HANDLER * ********************************************* * IRQKEY LDB #1 STB PIADB TURN OFF OB. NOTES IMMEDIATELY! STB CLRFLG QUEUE GENERAL CLEAR IRQK1 LDB TMROUT GET IRQ KEY FLAG ANDB #$10 BNE IRQK1 WAIT FOR KEY UP RTI RETURN... * ********************************************* * * DUMMY INTERRUPT HANDLER * ********************************************* * * DUMMY INTERRUPT HANDLER (ON ALL SWI'S) * INTDMY RTI RETURN.... * PAGE ********************************************************************* * * ---- PATCH EDITOR TABLES ---- * ********************************************************************* * * LEVEL 0 TITLES * L0TIT FCC / MIDI MODE / FCC /4-VCE SET-UP/ FCC /SET MIDI OUT/ FCC /AUTO PMNTO / FCC /AUTO PBEND / FCC /AUTO TRILL / FCC /TONE-VOL-BAL/ * * LEVEL 0 OFFSETS INTO PATCH DATA * L0OFF FCB 10 FCB 19 FCB 33 FCB 48 FCB 53 FCB 72 FCB 94 * * # LEVEL 1 ITEMS FOR EACH LEVEL 0 HEADING * N1HEAD FCB 9 FCB 14 FCB 15 FCB 5 FCB 19 FCB 22 FCB 11 * PAGE * * --- MAIN LEVEL 1 ARGUMENT TABLE --- * * * MIDI MODE SEGMENT * L1ARG FDB T1 POINTER TO TITLE FCB -1 >0 = CHAR. POINTER; ELSE NUM. OFFSET FCB 15 POSITIVE LIMIT (NEG. LIMIT ASS. ZERO) * FDB T2 FCB 1 FCB 3 * FDB T3 FCB 1 FCB 1 * FDB T4 FCB 5 FCB 4 * FDB T44 FCB 1 FCB 1 * FDB T5 FCB 0 FCB 127 * FDB T6 FCB 1 FCB 1 * FDB T45 FCB 44 FCB 2 * FDB T76 FCB 1 FCB 1 * * 4-VOICE SETUP SEGMENT * FDB T7 FCB 1 FCB 1 * FDB T8 FCB -1 FCB 15 * FDB T9 FCB 0 FCB $FF * FDB T10 FCB 10 FCB 3 * FDB T11 FCB 0 FCB 63 * FDB T12 FCB 1 FCB 1 * FDB T13 FCB 14 FCB 3 * FDB T41 FCB 1 FCB 1 * FDB T46 FCB 62 FCB 2 * FDB T47 FCB 47 FCB 3 * FDB T48 FCB 0 FCB $FF * FDB T49 FCB 0 FCB $FF * FDB T50 FCB 58 FCB 1 * FDB T51 FCB 0 FCB 127 * * SET MIDI OUT SEGMENT * FDB T14 FCB -1 FCB 15 * FDB T15 FCB 18 FCB 3 * FDB T16 FCB 22 FCB 3 * FDB T17 FCB 37 FCB 1 * FDB T18 FCB 1 FCB 1 * FDB T19 FCB 26 FCB 1 * FDB T20 FCB 0 FCB 64 * FDB T21 FCB 0 FCB $FF * FDB T38 FCB 34 FCB 2 * FDB T39 FCB 0 FCB $FF * FDB T40 FCB 0 FCB 63 * FDB T52 FCB 0 FCB 129 * FDB T53 FCB 51 FCB 1 * FDB T54 FCB 53 FCB 4 * FDB T55 FCB 0 FCB 127 * * AUTO PORTMENTO * FDB T22 FCB 1 FCB 1 * FDB T23 FCB 0 FCB $FF * FDB T24 FCB 28 FCB 1 * FDB T78 FCB 30 FCB 3 * FDB T25 FCB 0 FCB 63 * * AUTO PBEND SEGMENT * FDB T26 FCB 1 FCB 1 * FDB T27 FCB 0 FCB 127 * FDB T43 FCB 42 FCB 1 * FDB T28 FCB 0 FCB 127 * FDB T36 FCB 28 FCB 1 * FDB T29 FCB 0 FCB $FF * FDB T30 FCB 0 FCB 63 * FDB T31 FCB 0 FCB $FE * FDB T32 FCB 0 FCB $FF * FDB T42 FCB 39 FCB 2 * FDB T34 FCB 0 FCB 121 * FDB T33 FCB 30 FCB 3 * FDB T56 FCB 0 FCB 127 * FDB T57 FCB 0 FCB 128 * FDB T58 FCB 0 FCB $FF * FDB T59 FCB 0 FCB $FF * FDB T60 FCB 0 FCB $FF * FDB T61 FCB 0 FCB $FF * FDB T62 FCB 0 FCB $FF * * AUTO TRILL SEGMENT * FDB T35 FCB 1 FCB 1 * FDB T23 FCB 0 FCB 127 * FDB T24 FCB 28 FCB 1 * FDB T28 FCB 0 FCB 127 * FDB T36 FCB 28 FCB 1 * FDB T29 FCB 0 FCB $FF * FDB T37 FCB 0 FCB $FF * FDB T30 FCB 0 FCB 63 * FDB T32 FCB 0 FCB $FF * FDB T42 FCB 39 FCB 2 * FDB T34 FCB 0 FCB 121 * FDB T33 FCB 30 FCB 3 * FDB T56 FCB 0 FCB 127 * FDB T57 FCB 0 FCB 128 * FDB T58 FCB 0 FCB $FF * FDB T59 FCB 0 FCB $FF * FDB T60 FCB 0 FCB $FF * FDB T61 FCB 0 FCB $FF * FDB T62 FCB 0 FCB $FF * FDB T63 FCB 0 FCB $FF * FDB T64 FCB 65 FCB 2 * FDB T77 FCB 68 FCB 2 * * TVB MENU * FDB T65 FCB 0 FCB $FF * FDB T72 FCB 0 FCB 127 * FDB T66 FCB 0 FCB $FF * FDB T73 FCB 0 FCB 127 * FDB T67 FCB 0 FCB $FF * FDB T74 FCB 0 FCB 127 * FDB T68 FCB 0 FCB $FF * FDB T75 FCB 0 FCB 127 * FDB T69 FCB 60 FCB 1 * FDB T70 FCB 1 FCB 1 * FDB T71 FCB 1 FCB 1 * PAGE * * LEVEL 1 TITLE LIST * T1 FCB 9 FCC /CHANNEL#:/ T2 FCB 5 FCC /OMNI:/ T3 FCB 5 FCC /MONO:/ T4 FCB 9 FCC /KEY PRTY:/ T5 FCB 8 FCC /TRNSPSE:/ T6 FCB 8 FCC /AUTOCRD:/ T7 FCB 9 FCC /PLY NTES:/ T8 FCB 7 FCC /PRGM #:/ T9 FCB 9 FCC /PBND RNG:/ T10 FCB 8 FCC /PMNTO M:/ T11 FCB 8 FCC /PMNTO T:/ T12 FCB 7 FCC /UNISON:/ T13 FCB 8 FCC /SPLIT M:/ T14 FCB 9 FCC /OUT CHL#:/ T15 FCB 7 FCC /XMIT M:/ T16 FCB 5 FCC /SEND:/ T17 FCB 8 FCC /XMIT PB:/ T18 FCB 9 FCC /FILL DLY:/ T19 FCB 7 FCC /FILL N:/ T20 FCB 8 FCC /#VOICES:/ T21 FCB 8 FCC /DLY TRG:/ T22 FCB 9 FCC /AUTO PRT:/ T23 FCB 9 FCC /AVEL SCL:/ T24 FCB 10 FCC /AVEL SNCE:/ T25 FCB 6 FCC /DELAY:/ T26 FCB 9 FCC /AUTO BND:/ T27 FCB 9 FCC /BEND DIR:/ T28 FCB 9 FCC /RVEL SCL:/ T29 FCB 9 FCC /SWP BIAS:/ T30 FCB 9 FCC /MAX SWNG:/ T31 FCB 9 FCC /RATE SET:/ T32 FCB 9 FCC /MIN HOLD:/ T33 FCB 8 FCC /CONTROL:/ T34 FCB 9 FCC /OUT CTL#:/ T35 FCB 9 FCC /AUTO TRL:/ T36 FCB 10 FCC /RVEL SNCE:/ T37 FCB 9 FCC /RTE BIAS:/ T38 FCB 8 FCC /NOTE ON:/ T39 FCB 9 FCC /NOTE DUR:/ T40 FCB 9 FCC /DUR VSCL:/ T41 FCB 9 FCC /REASSIGN:/ T42 FCB 8 FCC /TRIGGER:/ T43 FCB 7 FCC /DIR ON:/ T44 FCB 8 FCC /REALLOC:/ T45 FCB 9 FCC /INTERVAL:/ T46 FCB 7 FCC /ASSIGN:/ T47 FCB 7 FCC /OCTAVE:/ T48 FCB 9 FCC /VCF BASE:/ T49 FCB 8 FCC /VCF SWP:/ T50 FCB 9 FCC /VCF CTLR:/ T51 FCB 8 FCC /VCF VEL:/ T52 FCB 9 FCC /REC KEY#:/ T53 FCB 9 FCC /OUT PLAY:/ T54 FCB 8 FCC /OUT ORD:/ T55 FCB 8 FCC /OUT VEL:/ T56 FCB 9 FCC /INIT VAL:/ T57 FCB 9 FCC /TRG KEY#:/ T58 FCB 9 FCC /VCF FEED:/ T59 FCB 9 FCC /VOL FEED:/ T60 FCB 9 FCC /BAL FEED:/ T61 FCB 9 FCC /BAS FEED:/ T62 FCB 9 FCC /TRB FEED:/ T63 FCB 9 FCC /TRL WDTH:/ T64 FCB 7 FCC /WV SEL:/ T65 FCB 7 FCC /VOLUME:/ T66 FCB 8 FCC /BALANCE:/ T67 FCB 5 FCC /BASS:/ T68 FCB 7 FCC /TREBLE:/ T69 FCB 6 FCC /INPUT:/ T70 FCB 9 FCC /ST ENHCE:/ T71 FCB 7 FCC /LD CMP:/ T72 FCB 9 FCC /VOL VSCL:/ T73 FCB 9 FCC /BAL VSCL:/ T74 FCB 9 FCC /BAS VSCL:/ T75 FCB 9 FCC /TRB VSCL:/ T76 FCB 9 FCC /KEY SAFE:/ T77 FCB 9 FCC /POLARITY:/ T78 FCB 7 FCC /AFFECT:/ * PAGE * * POINTER TABLE TO CHARACTER OPTION TITLES * CHROPT FDB QOFF FDB QON FDB QXCTL FDB QMULTI FDB QNRM FDB QHI FDB QLOW FDB QFST FDB QLST FDB QOFF FDB QBTH FDB QUPR FDB QLWR FDB QOFF FDB Q22 FDB Q31 FDB Q13 FDB QOFF FDB QONLY FDB QRECHN FDB QALL FDB QMUTE FDB QNRML FDB QECHO FDB QOVF FDB QSAME FDB QSEMI FDB QMNS FDB QPLS FDB Q4V FDB QOUT FDB QBOTH FDB QOFF FDB QATK FDB QRLSM FDB QRLSP FDB QNO FDB QYES FDB QNRM FDB QQUE FDB QCTLR FDB QATK FDB RLMQQ FDB QOCT FDB QUSR FDB QSET FDB QZRO FDB QN2 FDB QN1 FDB QP1 FDB QNTE FDB QBUF FDB QFWD FDB QRTRO FDB QCRCL FDB QNDWN FDB QMAP FDB QMOD FDB QNCTL FDB QSTRO FDB QMONO FDB QRC FDB QCONT FDB QRST FDB QSQRE FDB QTNGLE FDB QSWEEP FDB QBI FDB QUP FDB QDWN QXXX FDB QEXP * BTMLST EQU (QXXX-CHROPT)/2+1 INDEX OF BOTTOM STRING IN OPTION LIST * PAGE * * CHARACTER OPTION LIST * QON FCB 2 FCC /ON/ QOFF FCB 3 FCC /OFF/ QHI FCB 2 FCC /HI/ QLOW FCB 3 FCC /LOW/ QFST FCB 3 FCC /FST/ QLST FCB 3 FCC /LST/ QNRM FCB 3 FCC /NRM/ QBTH FCB 3 FCC /BTH/ QUPR FCB 3 FCC /UPR/ QLWR FCB 3 FCC /LWR/ Q22 FCB 3 FCC /2-2/ Q13 FCB 3 FCC /1-3/ Q31 FCB 3 FCC /3-1/ QALL FCB 3 FCC /ALL/ QONLY FCB 4 FCC /ONLY/ QRECHN FCB 5 FCC /RECHN/ QOVF FCB 6 FCC /OVFLOW/ QNRML FCB 6 FCC /NORMAL/ QECHO FCB 6 FCC /ECHO4V/ QMUTE FCB 4 FCC /MUTE/ QSAME FCB 4 FCC /SAME/ QSEMI FCB 4 FCC /SEMI/ QPLS FCB 1 FCC /+/ QMNS FCB 1 FCC /-/ Q4V FCB 4 FCC /4VCE/ QOUT FCB 3 FCC /OUT/ QBOTH FCB 4 FCC /BOTH/ QN FCB 1 FCC /N/ QY FCB 1 FCC /Y/ QATK FCB 3 FCC /ATK/ QRLSM FCB 4 FCC /RLS-/ QRLSP FCB 4 FCC /RLS+/ QNO FCB 2 FCC /NO/ QYES FCB 3 FCC /YES/ QQUE FCB 3 FCC /QUE/ QCTLR FCB 4 FCC /CTLR/ QXCTL FCB 7 FCC /X-CTLRS/ QMULTI FCB 5 FCC /MULTI/ QOCT FCB 3 FCC /OCT/ QUSR FCB 3 FCC /USR/ QSET FCB 3 FCC /SET/ QN1 FCB 2 FCC /-1/ QZRO FCB 1 FCC /0/ QP1 FCB 2 FCC /+1/ QN2 FCB 2 FCC /-2/ QNTE FCB 3 FCC /NTE/ QBUF FCB 3 FCC /BUF/ QRTRO FCB 4 FCC /RTRO/ QCRCL FCB 4 FCC /CRCL/ QNDWN FCB 4 FCC /NDWN/ QMAP FCB 3 FCC /MAP/ QMOD FCB 3 FCC /MOD/ QNCTL FCB 2 FCC /#3/ QSTRO FCB 6 FCC /STEREO/ QMONO FCB 4 FCC /MONO/ QCONT FCB 4 FCC /CONT/ QRC FCB 3 FCC "R/C" QRST FCB 5 FCC /RESET/ QSQRE FCB 5 FCC /PULSE/ QTNGLE FCB 5 FCC /TNGLE/ QSWEEP FCB 5 FCC /SWEEP/ QFWD FCB 3 FCC /FWD/ QEXP FCB 1 FCC /!/ QBI FCB 3 FCC "+/-" QUP FCB 2 FCC /UP/ QDWN FCB 3 FCC /DWN/ * PAGE CHRASK FCB 1 FCC /*/ ********************************************************************* * * INITIALIZE PROCESSOR AND PERIPHALS * ********************************************************************* * RBOOT ORCC #$50 MASK ALL INTERRUPTS * * SET PIA * CLR PIACA SELECT DATA DIRECTION REGISTER CLR PIACB " " LDA #$C0 LOW 6 BITS ARE INPUT STA PIADA SET "A" DATA DIR. REG. LDA #$FF ALL BITS ARE OUTPUTS STA PIADB SET "B" DATA DIR. REG. LDA #PCTLA INTERRUPT ENABLE ON A (KEYPAD) STA PIACA SET A CTL. REG. LDA #PCTLB2 LOAD B AUTO-STROBE CTL WORD STA PIACB PUT IT AWAY LDA PIADA CLEAR POTENTIAL INTERRUPT (NO NEED?) CLRA STA PIADA CLEAR DATA BITS IN A STA PIADB CLEAR DATA BITS IN B * * SET ACIA * LDA #$FF RESET ACIA STA ACIACR LDA #ACIARI SET ACIA TO INTERRUPT ON INPUT STA ACIACR * * LOAD STACK POINTERS * LDS #HSTK0 HARDWARE STACK LDU #USTK0 USER STACK * * CLEAR DISPLAY * LBSR CLRDSP USE THE SUBROUTINE * * SET TIMER * LDA #$20 STA CTRQ1 TIMER # FLAG LDB #3 SET COUNT (3 TIMES) SETTCR LDA #T0SEQ COMMAND SEQUENTIAL (LO/HI) COUNT ORA CTRQ1 OR IN TIMER # STA TMRCR STORE IN CTL. REG. LSL CTRQ1 NEXT TIMER DECB DO 3 TIMES BNE SETTCR LDB #3 GET NEW COUNT LDX #TMR0 GET BASE TIMER ADDR. CLRA CLRTMR INCA STA ,X LOAD 1 INTO LOW BYTE CLRA STA ,X+ CLEAR HI BYTE DECB DO 3 TIMES BNE CLRTMR * * RESET PITCH BEND * LDA #25 GET 1/10 OF FULL SCALE STA PBSENS LOAD INTO PB SENSITIVITY LDD #PBOFF LOAD PB. NEUTRAL VALUE STD PBHI PUT INTO PB. REGS. * * RESET SPECIAL LOCATIONS * LDX #0 ZERO INDEX REG. CLRLOC CLR ,X+ CLEAR IT OUT CMPX #ADIBUF ADVANCE COUNT BNE CLRLOC CONTINUE... * * SET UP MIDI BUFFER POINTERS * LDD #ADIBUF LOAD INITIAL INPUT BUFFER POINTER STD ADRIN STASH FOR BACKGROUND INPUT STD ADFIN STASH FOR FOREGROUND INPUT LDD #ADOBUF LOAD INITIAL OUTPUT BUFFER POINTER STD ADROUT STASH FOR BACKGROUND OUTPUT STD ADFOUT STASH FOR FOREGROUND OUTPUT LDB #8 NULL STATUS STB STATLO INCB INCB SET FOR FOREIGN CHANNEL STB LSTAT STB OLDSTT STB STAOUT * * LOAD IN LAST PATCH * LDX #CHRASK POINT AT DIAGNOSTIC CHARS. CLRB PSHS B,X LBSR PRTCHR PRINT FIRST OUT LDB NVMPCH GET LAST PATCH# STB PCHLDQ STASH IT LBSR LDPTCH LOAD IT UP!!! PULS B,X INCB PSHS B,X LBSR PRTCHR PRINT SECOND OUT CLRB LBSR LDOBHM LOAD UP OB. PULS B,X INCB LBSR PRTCHR PRINT THIRD OUT LBSR CLRART CLEAR OUT EVERYTHING * ANDCC #$AF ENABLE IRQ AND FIRQ * PAGE * * LEVEL 0 PATCH EDITOR * LEVEL0 LDB N0 GET LEVEL 0 INDEX BGT LVL01 BR. IF NOT AT ROOT LDX #PNUM GET POINTER TO RESIDENT PATCH LBSR SHOPCH WRITE IT OUT BRA LVL02 CONTINUE... LVL01 LBSR SHOTIT PRINT OUT TITLE OF ITEM LVL02 LBSR WTKEY WAIT FOR KEYPAD.... TST PNTFLG PUNT?? BEQ LVL03 BRANCH IF NOT * LVL02A CLR N0 CLEAR LVL0 INDEX ON PUNT BRA LEVEL0 CONTINUE.. * LVL03 CMPB #ENTER ENTER KEY??? BEQ LVL04P THEN ADVANCE N0... CMPB #PLUS + KEY?? BEQ LVL04P ADVANCE N0 ON PLUS TOO CMPB #MINUS - KEY?? BNE LVL04 BR. IF NOT. LDA N0 GET N0 DECA DECREMENT ON MINUS BGE LVL04M BR. IF OK LDA #MXLVL0 OVERFLOW; LOAD MAX. N0 LVL04M STA N0 REPLACE N0 BRA LEVEL0 CONTINUE.... LVL04P LDA N0 GET N0; INCREMENT CODE... INCA INCREMENT N0 CMPA #MXLVL0 AT MAXIMUM?? BGT LVL02A THEN BR... STA N0 REPLACE N0 BRA LEVEL0 CONTINUE.... * LVL04 CMPB #DOTKEY IS IT "."?? (SAVE PATCH) BNE LVL05 BR. IF NOT LBSR SAVL0 BR. TO ROUTINE TO DO SAVE BRA LEVEL0 BACK... * LVL05 CMPB #EQUALS IS IT "="?? (LOAD PATCH) LBNE LVL08 BR. IF NOT LBSR LDRL0 BR. TO ROUTINE TO LOAD PATCH BRA LEVEL0 BACK... * LVL08 CMPB #DIVIDE IS KEY DVD?? (EDIT WRITE-PROTECT) BNE LVL014 NO.. BR. CLRB LDX #WRPQRY LBSR PRTCHR PRINT OUT WRITE PROTECT QUERY LDB #1 STB LMTPLS INCB STB DATAI LDX #WRTPRT LDY #YNOPT LBSR INPALP INPUT Y/N RESPONSE BRA LEVEL0 GO BACK... YNOPT FDB QN YES/NO RESPONSE FDB QY WRPQRY FCB 12 FCC /WRITE PRT: / * LVL014 CMPB #CLEAR IS KEY "C"?? (CLEAR OB. ROUTINE) BNE LVL015 BR. IF NOT... CLRB LDX #CLRMSG LBSR PRTCHR PRINT OUT CLEAR MESSAGE LBSR WTKEY WAIT FOR KEYPAD CMPB #CLEAR ANOTHER "C"? LBNE LEVEL0 NO.. KICK OUT LBSR CLRART YES... CLEAR ALL ARTIFACTS CLR PIADB CLEAR OB. LDX #CLRMSF CLRB LBSR PRTCHR PRINT OUT ACKNOWLEDGEMENT LBSR WTKEY WAIT FOR KEY LBRA LEVEL0 GO BACK.... CLRMSG FCB 12 FCC /C TO CLR 4-V/ CLRMSF FCB 12 FCC /4-V CLEARED!/ * LVL015 CMPB #XKEY IS KEY "X"?? (RELOAD OB.) BNE LVL016 BR. IF NOT... CLRB LDX #OBLMSG LBSR PRTCHR PRINT OUT CLEAR MESSAGE LBSR WTKEY WAIT FOR KEYPAD CMPB #XKEY ANOTHER "X"? LBNE LEVEL0 NO.. KICK OUT CLRB LOAD EVERYTHING LBSR LDOBHM LOAD UP OB. LDX #OBLMSF CLRB LBSR PRTCHR PRINT OUT ACKNOWLEDGEMENT LBSR WTKEY WAIT FOR KEY LBRA LEVEL0 GO BACK.... OBLMSG FCB 12 FCC /X TO PGM 4-V/ OBLMSF FCB 12 FCC /4-V LOADED!/ * LVL016 CMPB #KKEY IS IT "K"?? (EDIT VIA LEVEL 1) LBNE LEVEL0 NO... OUT OF OPTIONS, SO IGNORE LBSR LEVEL1 YES... CALL LEVEL1 EDITOR LBRA LEVEL0 GO BACK... * * TIMED WAIT FOR KEYPAD ROUTINE * ON ENTRY, REG. A = TMR. LSB, REG. B = TMR. MSB (USE T0) * TMKEY1 CLR TMKMDE CLEAR MODE FLAG (DON'T ACCEPT +/-) BRA TMKY10 TMKEY2 INC TMKMDE SET MODE FLAG (ACCEPT +/-) BNE TMKY10 INC TMKMDE CHECK FOR OVERFLOW TMKY10 CLR CHRFLG CLEAR OUT FLAGS CLR CHRBUF CLR PNTFLG STA TMR0 LOAD TIMER LSB STB TMR0 LOAD TIMER MSB TMK12 CLRB TST CHRFLG CHARACTER HIT?? BNE TMK11 YES, BR.. LDA TMROUT GET TIMER FLAGS ANDA #1 SELECT T0 BNE TMK12 TIMER RUNNING... LOOP.... RTS TMK11 CLR CHRFLG PREPARE TO ACCEPT ANOTHER CHARACTER LDB CHRBUF GET CHARACTER CMPB #PUNT PUNT?? BNE TMK13 NOT PUNT... BR. INC PNTFLG SET PUNT FLAG RTS GO BACK.... TMK13 CMPB #ENTER IS IT ENTER?? BEQ TMK14 YES, BRA... TST TMKMDE DO WE ACCEPT +/- ?? BEQ TMK12 NO, LOOP AGAIN; CHARACTER NOT ALLOWED CMPB #PLUS + KEY?? BEQ TMK14 YES, RETURN CMPB #MINUS - KEY?? BNE TMK12 NO, LOOP..... TMK14 RTS RETURN * * ROUTINE TO SAVE PATCH IN NON-VOL. MEMORY * SAVL0 LDB PNUM GET CURRENT PATCH NUMBER STB PNUMZ STASH IT SOMEWHERE WHERE IT CAN BE CHANGED SAVL0X CLRB LDX #SAVCHR GET SAVE MESSAGE LBSR PRTCHR PRINT IT OUT... LDA #$A0 TIMER LSB CLRB TIMER MSB STB TQTRIG CLEAR FLAG LBSR TMKEY2 WAIT INTERVAL TSTB KEY HIT?? BNE LVL07 BR. IF SO... LDB PNUMZ GET PATCH# LDA #TOTVAR GET #BYTES/COMPRESSED-PATCH MUL SCALE 'EM ADDD #NVRAM0 ADD IN START OF NV-RAM TFR D,X SHOVE IT INTO X-REG. LBSR SHOPCH SHOW ORIGINAL ON DISPLAY LDA #$FF CLRB LBSR TMKEY2 AGAIN, A TIMED WAIT TSTB KEY HIT?? BEQ SAVL0X START AGAIN IF NOT... LVL07 TST PNTFLG DID WE PUNT?? BNE LVLRSN BACK TO ROOT IF SO.. CMPB #ENTER WAS IT ENTER?? BNE LVL0XZ BR. IF NO... TST TQTRIG TEST FLAG BEQ LVL07B BRA SAVL0X LVL0XZ LDA PNUMZ GET LATEST PATCH # CMPB #PLUS DID WE HIT A "+"?? BNE LVL0Z2 NO... BRANCH INCA INCREMENT PATCH # CMPA #MAXPCH BEYOND MAXIMUM??? BLE LVL0Z3 NO, BR.. CLRA YES, RESET PATCH # BRA LVL0Z3 LVL0Z2 CMPB #MINUS MINUS KEY?? BNE SAVL0X IGNORE KEYPAD IF NOT DECA DECREMENT PATCH # BGE LVL0Z3 BR. IF OK LDA #MAXPCH SATURATE @ MAX. PATCH ON OVFLOW LVL0Z3 STA PNUMZ STORE LATEST VALUE IN LOAD ARGUMENT LDB #TOTVAR GET BYTES/PATCH MUL GET INDEX INTO TABLE ADDD #NVRAM0 ADD IN NV. RAM START STD INPADR STASH PATCH ADDR. TFR D,X PUT ABSOLUTE ADDR. IN X LBSR SHOPCH SHOW CANDIDATE PATCH # LDB #1 STB TQTRIG SET FLAG LDX #9 LBSR CURSOR CURSOR ON OVER COLON LBSR WTKEY WAIT FOR KEYPAD LBSR CLRDSP CLEAR DISPLAY BRA LVL07 LOOP... LVL07B TST WRTPRT IS WRITE PROTECT ACTIVE?? BEQ LVL07A BR. IF OK TO WRITE LBSR WPMESS YES, GIVE WARNING MESSAGE LDB #1 LDX #0 LBSR CURSOR FLASH CURSOR LBSR WTKEY WAIT FOR RESPONSE LVLRSN RTS BACK TO ROOT.... LVL07A LDB PNUMZ GET PATCH NO. STB PNUM PUT IT IN PROPER PLACE LBSR SAVPCH BRANCH TO SAVE ROUTINE LDX #PNUM LBSR SHOPCH PRINT OUT PATCH TITLE CLRB LDX #PSVMSG LBSR PRTCHR PRINT OUT SAVED MESSAGE LBRA WTKEY WAIT FOR KEYPAD * SAVCHR FCB 12 FCC /* OVRWRITE */ PSVMSG FCB 10 FCC / = SAVED! / * * ROUTINE TO LOAD PATCH FROM NON-VOLATILE MEMORY * LDRL0 LDB #2 LDX #LPHCHR LBSR PRTCHR PRINT OUT PATCH QUERY LDA PNUM GET PATCH NO. INCA LDB #2 LDX #0 LBSR WRTDEC WRITE OUT VALUE... LDB PNUM LOAD PATCH AGAIN LDX #PCHLDQ GET STORAGE ADDR. STB ,X STASH PATCH NO. CLRB STB LMTMNS ZERO - LIMIT STB DSPOFF NO DISPLAY OFFSET INCB STB DATAI INCREMENT # BY ONE FOR DISPLAY INCB STB NCHRSI 2 CHARACTERS LDB #MAXPCH GET UPPER LIMIT STB LMTPLS PUT IT IN PLACE LBSR INPNBR GET A NEW DECIMAL PATCH # TST PNTFLG WAS PUNT ENTERED?? LBNE LDRRTN BACK AGAIN IF SO.... LDB PCHLDQ LDA #TOTVAR GET TOT. BYTES/PATCH MUL GET INDEX ADDD #NVRAM0 ADD NVRAM OFFSET STD INPADR STASH PATCH ADDR. LVL010 CLRB STB TQTRIG CLEAR FLAG LDX #LDCHR LBSR PRTCHR PRINT OUT LOAD MESSAGE LDA #$A0 CLRB LBSR TMKEY2 A TIMED KEYPAD WAIT... TSTB CHAR. HIT?? BNE LVL09 YES.. BRANCH LDX INPADR COPY PATCH ADDR. INTO X LBSR SHOPCH SHOW PATCH NUMBER & TITLE LDA #$FF CLRB LBSR TMKEY2 ANOTHER TIMED KEYPAD WAIT... TSTB CHAR HIT?? BEQ LVL010 NO... LOOP.... LVL09 TST PNTFLG WAS IT PUNT?? LBNE LEVEL0 YES... EXIT CMPB #ENTER WAS IT ENTER?? BNE LVL0XY BR. IF SO... TST TQTRIG TEST FLAG BEQ LVL011 BRA LVL010 LVL0XY LDA PCHLDQ GET LATEST PATCH # CMPB #PLUS DID WE HIT A "+"?? BNE LVL012 NO... BRANCH INCA INCREMENT PATCH # CMPA #MAXPCH BEYOND MAXIMUM??? BLE LVL013 NO, BR.. CLRA YES, RESET PATCH # BRA LVL013 LVL012 CMPB #MINUS MINUS KEY?? BNE LVL010 IGNORE KEYPAD IF NOT DECA DECREMENT PATCH # BGE LVL013 BR. IF OK LDA #MAXPCH SATURATE @ MAX. PATCH ON OVFLOW LVL013 STA PCHLDQ STORE LATEST VALUE IN LOAD ARGUMENT LDB #TOTVAR GET BYTES/PATCH MUL GET INDEX INTO TABLE ADDD #NVRAM0 ADD IN NV. RAM START STD INPADR STASH PATCH ADDR. TFR D,X PUT ABSOLUTE ADDR. IN X LBSR SHOPCH SHOW CANDIDATE PATCH # LDB #1 STB TQTRIG SET FLAG LDX #9 LBSR CURSOR CURSOR ON OVER COLON LBSR WTKEY WAIT FOR KEYPAD LBSR CLRDSP CLEAR DISPLAY BRA LVL09 LOOP... LVL011 LBSR CLRART CLEAR ALL ARTIFACTS LBSR LDPTCH LOAD IN PATCH CLRB LOAD UP ALL PARAMETERS LBSR LDOBHM LOAD OB. LDX #PNUM LBSR SHOPCH SHOW PATCH TITLE CLRB LDX #LPHCFM LBSR PRTCHR PRINT OUT CONFIRMATION LBSR WTKEY WAIT FOR KEY LDRRTN RTS BACK UP * LPHCHR FCB 10 FCC /LOAD PCH: / LDCHR FCB 12 FCC /*** LOAD ***/ LPHCFM FCB 10 FCC / = LOADED!/ * * DISPLAY LEVEL 0 TITLE * ON ENTRY, REG. B ASSUMED TO HOLD N0 VALUE * SHOTIT PSHS B SAVE N0 LBSR CLRDSP CLEAR DISPLAY DECB CORRECT FOR OFFSET LDA #12 12 BYTES PER TITLE MUL SCALE UP ADDD #L0TIT ADD IN START ADDRESS TFR D,X XFER RESULT LDY #DSPLY0+12 TOP OF DISPLAY LDA #12 12 CHARS. SHOT1 LDB ,X+ GET NEXT CHAR. STB ,-Y PUT IN DISPLAY DECA BNE SHOT1 LOOP... PULS B RESTORE N0 POINTER CMPB #4 DO WE PRINT ON/OFF?? BLT SHOT2 NO, BRA... CMPB #6 BGT SHOT2 LDX #L0OFF GET OFFSET TABLE DECB LDA B,X GET OFFSET VAL. LDX #PNUM GET PATCH ADDR. TST A,X IS ITEM ON??? BEQ SHOT2 BR. IF NOT LDA #'*' LOAD ASTERICK STA DSPLY0 DRAW "*" IN RIGHT CHAR. SHOT2 RTS RETURN.... * * DISPLAY WRITE-PROTECT MESSAGE * WPMESS CLRB LDX #WPCHRS LBRA PRTCHR PRINT OUT MESSAGE WPCHRS FCB 12 FCC /WRT PROTECT!/ * * ROUTINE TO DISPLAY PATCH TITLE AND HEADING * ADDRESS OF PATCH START IS IN X ON ENTRY * SHOPCH LBSR CLRDSP CLEAR DISPLAY LDB ,X+ GET PATCH # PSHS B STORE FOR NOW LDA #8 WRITE 9-CHAR. PATCH TITLE LDY #DSPLY0 WN1 LDB ,X+ GET CHAR. STB A,Y PRINT ON DISPLAY DECA BGE WN1 CONTINUE... LDB #':' LOAD COLON STB DSPLY0+9 PUT ":" BEFORE TITLE LDX #10 PRINT @ CHAR. 11 LDB #2 PRINT 2 CHARS. PULS A GET PATCH# BACK INCA CORRECT FOR DISPLAY LBRA WRTDEC WRITE DECIMAL VALUE TO DISPLAY * PAGE * * LEVEL 1 PATCH EDITOR * LEVEL1 TST N0 EDIT THE TITLE?? LBEQ EDTTLE BRANCH TO TITLE EDIT IF SELECTED LVL11 CLR N1 CLEAR THE LEVEL1 INDEX LVL12 LBSR CLRDSP CLEAR THE DISPLAY * CLR CHRZRO CLEAR CHARACTER REPLACE FLAG LDB #3 CMPB N0 IS LEVEL 0 INDEX AT SET OUT? BNE LVL1MN BR. IF NOT LDB N1 CMPB #6 ARE WE POINTING AT FILL VCE? BNE LVL1QZ BR. IF NOT INC CHRZRO LDY #RLMQOF GET "OFF" REPLACEMENT CHRS. STY ZROREP BRA LVL1QR CONTINUE... LVL1QZ CMPB #11 ARE WE POINTING AT KEY TRIGGER FOR BUFFER? BNE LVL1QR BR. IF NO INC CHRZRO LDY #RLMQSS GET "SOS" REPLACEMENT CHRS. STY ZROREP BRA LVL1QR CONTINUE... LVL1MN LDB #5 SUBB N0 IS LEVEL 0 INDEX IN AUTO PB.? BEQ LVL1QX BR. IF SO INCB IS LEVEL 0 INDEX IN AUTO TRILL? BNE LVL1QR BR. IF NO LDB #19 AT SET PW? CMPB N1 IS LEVEL1 INDEX AT 19? BNE LVL1QX BR. IF NOT INC CHRZRO LDY #QOFF POINT AT OFF STY ZROREP BRA LVL1QR LVL1QX LDB #8 CMPB N1 IS LEVEL1 INDEX AT 8?? BNE LVL1MM BR. IF NOT INC CHRZRO SET CHAR @ ZERO FLAG LDY #RLMQQ LOAD "RELEASE" ABBREVIATION ADDR. STY ZROREP STORE IT IN BUFFER BRA LVL1QR CONTINUE... LVL1MM INCB INCB CMPB N1 IS LVL. 1 INDEX AT 10?? BNE LVL1QS BR. IF NOT INC CHRZRO SET CHAR. @ ZERO FLAG LDY #RLMQR LOAD "PITCH BEND" ABBREV. ADDR. STY ZROREP STASH IN APPROVED BUFFER BRA LVL1QR LVL1QS LDB #13 CMPB N1 IS LVL. 1 INDEX AT 13 (TRG. KEY?) BNE LVL1QR INC CHRZRO LDY #QOFF POINT AT OFF STY ZROREP * LVL1QR LDA N0 GET LVL 0 INDEX DECA CORRECT LEVEL 0 OFFSET LDX #N1HEAD GET LEVEL 1 HEADING TABLE ADDR. LDB A,X GET # LEVEL 1 ITEMS DECB CORRECT IT STB N1ITMS STASH # LEVEL 1 ITEMS LDX #L0OFF GET ADDR. OF LEVEL 0 OFFSET TABLE LDB A,X GET LEVEL 0 OFFSET ADDB N1 ADD IN LEVEL 1 INDEX PSHS B STASH IT SUBB #10 GO FROM CHNL0 CLRA CLEAR HIGH-ORDER ADDRESS OFFSET LSLB CORRECT FOR 4 BYTES/ENTRY ROLA LSLB ROLA ADDD #L1ARG POINT TO LVL 1 ARGUMENT TABLE TFR D,X COPY ADDR. TFR X,Y COPY ADDR. LDX ,Y++ GET ADDR.; INCR. POINTER LDB ,X GET # BYTES IN TITLE NEGB COMPLIMENT ADDB #12 GET B TO BECOME DISPLAY OFFSET STB DATAI STORE RESULT IN PROPER PLACE LBSR PRTCHR DISPLAY ITEM HEADING LDX #PNUM POINT TO BEGINNING OF REAL PATCH DATA PULS B BACK TO BYTE POINTER ABX POINT AT ITEM TO EDIT PSHS X,Y SAVE THESE ADDRS. TST ,Y CHAR. OR NUMERIC INPUT?? BGT LVL13 BR. IF CHAR. LDA ,Y+ GET NUMERIC OFFSET NEGA CORRECT IT ADDA ,X ADD INTO VALUE LDX #0 NO OFFSET INTO DISPLAY LDB ,Y GET UPPER BOUND LBSR CLCCHR CALCULATE # OF CHARS LBSR WRTDEC PRINT VALUE BRA LVL14 CONTINUE.... LVL13 LDB ,Y GET OFFSET INTO CHAR. TABLE ADDB ,X ADD IN DATA VALUE BCS LVL1PB CODE TO PREVENT OVERFLOW TROUBLE BMI LVL1PB CMPB #BTMLST TOO BIG?? BLE LVL1OK BR. IF OK LVL1PB LDB #BTMLST LOAD ! POINTER LVL1OK DECB CORRECT FOR OFFSET LSLB CORRECT FOR DOUBLE-WORD LDX #CHROPT GET POINTER TO CHARACTER OPTION TABLE ABX GET ADDR. OF CHARS. LDX ,X GET THE ADDR. OF CHARS CLRB NO OFFSET IN DISPLAY LBSR PRTCHR PRINT 'EM LVL14 LBSR WTKEY WAIT FOR KEYPAD PULS X,Y RESTORE STACK TST PNTFLG PUNT?? BEQ LVL1S NO, BR. RTS LEAVE ON PUNT LVL1S CMPB #ENTER ENTER KEY?? BEQ LVL1P BR. IF SO CMPB #PLUS PLUS KEY?? BNE LVL16 BR. IF NOT... LVL1P LDA N1 GET LVL 1 INDEX INCA INCREMENT CMPA N1ITMS AT TOP?? BLE LVL1P1 BR IF OK CLRA RESET LVL1P1 STA N1 RESTORE LVL 1 INDEX LBRA LVL12 CONTINUE... LVL16 CMPB #MINUS MINUS KEY?? BNE LVL18 NO, BR... LDA N1 GET LVL 1 INDEX DECA DECREMENT BGE LVL1P1 BR. IF OK LDA N1ITMS SATURATE AT MAX. BRA LVL1P1 STORE & CONTINUE LVL18 CMPB #KKEY K KEY?? BEQ LVL19 BR. IF SO CMPB #DIVIDE DIVIDE KEY?? BEQ LVL113 BR. IF SO TO SHOW PATCH CMPB #XKEY X KEY?? BEQ LVL133 THEN BR. TO LEVEL0 TITLE CMPB #DOTKEY DOT KEY?? BEQ LVL144 THEN BRANCH TO SAVE PATCH CMPB #EQUALS = KEY?? BEQ LVL155 THEN BRANCH TO LOAD PATCH PSHS X,Y STASH ADDRS. BACK ON STACK BRA LVL14 CONTINUE... LVL19 LDB N0 GET LVL. 0 INDEX CMPB #2 ARE WE IN OB. SETUP?? BNE LVL110 BR. IF NOT LDB N1 GET LV1 1. INDEX STB LDOBH SET LOAD-OB. FLAG BRA LVL11X LVL110 CMPB #7 ARE WE IN TVB SETUP? BNE LVL11X SKIP IF NOT LDB N1 GET LVL 1. INDEX INCB CORRECT FOR VOLUME #0 STB LDUTVB SET FLAG IF SO LVL11X CLR DSPOFF NO DISPLAY OFFSET CLR LMTMNS ZERO NEGATIVE LIMITS LDA ,Y+ GET NUM/CHAR FLAG LDB ,Y GET UPPER LIMIT STB LMTPLS STORE + LIMIT TSTA NUM. OR CHAR. INPUT?? BGT LVL111 BR. IF CHAR. INPUT BEQ LVL112 BR. IF NO NUMERIC OFFSET NEGA MAKE OFFSET POSITIVE LVL112 STA DATAI STASH OFFSET BSR CLCCHR CALCULATE # OF CHARS. TO READ STB NCHRSI SET IT * LVL1NN LBSR INPNBR READ IN A DECIMAL NUMBER * LVL1EE CLR LDOBH CLEAR OB. FLAG CLR LDUTVB CLEAR TVB FLAG LBRA LVL12 GO BACK.... * LVL111 PSHS X STASH DATA POINTER LDX #CHROPT POINT TO CHARACTER OPTION TABLE TFR A,B COPY INDEX DECB LSLB CORRECT FOR DOUBLE-BYTES ABX GET POINTER TO CHAR. STRINGS TFR X,Y COPY IT PULS X RESTORE STACK LBSR INPALP ACCEPT CHARACTER-CHOICE INPUT BRA LVL1EE RETURN... * LVL113 LDX #PNUM POINT TO PATCH LBSR SHOPCH SHOW IT LVL114 LDA PIADA WAIT TILL KEY IS UP ANDA #KSTRBE BNE LVL114 LBRA LVL12 GO BACK... * LVL133 LDB N0 GET N0 LBSR SHOTIT SHOW IT BRA LVL114 WAIT FOR KEY-UP * LVL144 LBSR SAVL0 SAVE PATCH LBRA LVL12 BACK... * LVL155 LBSR LDRL0 LOAD PATCH LBRA LVL12 * CLCCHR TSTB GET # OF CHARACTERS TO READ IN FROM LMT BLT LVL1M3 NEG. MEANS 3 CHARS. NEEDED CMPB #100 BGE LVL1M3 >= 100 NEEDS 3 CHARS. CMPB #10 BGE LVL1M2 >= 10 NEEDS 2 CHARS. LDB #1 < 10 NEEDS 1 CHAR. BRA LVL1M0 LVL1M2 LDB #2 BRA LVL1M0 LVL1M3 LDB #3 LVL1M0 RTS RETURN * RLMQQ FCB 3 FCC /RLS/ RLMQR FCB 3 FCC / PB/ RLMQOF FCB 2 FCC /--/ RLMQSS FCB 3 FCC /SOS/ * PAGE * * ROUTINE TO DISPLAY DECIMAL VALUE * * ON ENTRY; X HOLDS OFFSET INTO DISPLAY * B HOLDS # OF CHARS. TO PRINT * A HOLDS VALUE TO PRINT * * IF "CHRZRO " IS NON-0 A ZERO VALUE IN A CAUSES THE * STRING POINTED TO BY "ZROREP" TO BE SHOWN * WRTDEC TST CHRZRO ZERO REPLACEMENT?? BEQ WRD1 BRA. IF NOT TSTA IS INPUT ZERO?? BNE WRD1 BRA. IF NOT TFR X,D GET DISPLAY OFFSET INTO B LDX ZROREP POINT TO ZERO REPLACEMENT TEXT LBRA PRTCHR PRINT IT OUT WRD1 ABX POINT @ LAST CHAR. + 1 CLR WTDS2 CLEAR DECIMAL COUNT CLR SVPQ CLEAR FLAG STB WTDS1 STASH # CHARS. LDY #PWR10 POINT @ TABLE OF POWERS OF 10 CMPB #3 IF 3 CHARS., IGNORE OVERFLOW TEST BEQ WTD1 CMPA B,Y CMP. W. 100 OR 10 BGE WTDOV BRA. IF OVERFLOW TSTA BMI WTDOV >128, CAN'T FIT IN UNDER 3 CHARS. LEAY -1,Y DECREMENT POWER-OF-10 POINTER BRA WTD2 CONTINUE WTD1 LEAY -1,Y POINT AT 100 (3-CHARS. HERE) TSTA BGE WTD2 CAN USE 1 BYTE IF INPUT POSITIVE INC WTDS2 INCREMENT LEADING DIGIT ANDA #$7F MAKE POSITIVE ADDA #28 ADD IN REMAINDER TSTA BPL WTD2 BR. IF NOW POSITIVE INC WTDS2 AGAIN INCREMENT LEADING DIGIT ANDA #$7F MAKE POSITIVE ADDA #28 ADD IN REMAINDER WTD2 CMPA B,Y HAVE WE PASSED LIMIT OF THIS DIGIT? BLT WTD3 BR. IF SO INC WTDS2 NO, INCREMENT DIGIT SUBA B,Y SUBTRACT POWER OF 10 BRA WTD2 DO AGAIN WTD3 LEAX -1,X DECREMENT DISPLAY POINTER (X) TST WTDS2 INHIBIT LEADING ZEROES BNE WTD4 BR. IF NON-ZERO DIGIT CMPB #1 IS THIS THE LAST DIGIT?? BEQ WTD4 IF YES, BR. AND PRINT THE ZERO TST SVPQ TEST FLAG BNE WTD4 CLR DSPLY0,X CLEAR OUT THE DISPLAY CHAR. BRA WTD5 CONTINUE... WTD4 PSHS A SAVE REMAINDER LDA WTDS2 LOAD COUNT ADDA #$30 CONVERT TO ASCII STA DSPLY0,X WRITE OUT CHAR. TO DISPLAY STA SVPQ SET FLAG; NON-BLANK CHARACTER WRITTEN PULS A RESTORE REMAINDER WTD5 CLR WTDS2 CLEAR COUNT DECB DECREMENT DIGIT POINTER BGT WTD2 DO NEXT DIGIT RTS DONE; RETURN!! WTDOV LDA #'@' LOAD OVERFLOW CHARACTER WTDOV1 LEAX -1,X INDEX IN DISPLAY STA DSPLY0,X PRINT CHAR. DECB BGT WTDOV1 CONTINUE RTS RETURN * PWR10 FCB 1 POWERS OF 10 TABLE FCB 10 FCB 100 * PAGE * DECIMAL NUMERIC INPUT ROUTINE * * ON ENTRY: LIMITS IN LMTPLS(+), LMTMNS(-) * NUMERIC OFFSET IN DATAI * PHYSICAL (CHAR) OFFSET IN DSPOFF * # CHARS. TO USE IN NCHRSI * ADDR. OF DATA LOCATION IN X-REG. * IF LDOBH > 0, OB. PARM. INSIDE LOADED * INPNBR LDB ,X GET STARTING VALUE STB INPTMP STASH AWAY STX INPADR STASH ADDR. TOO CLR DATAID CLEAR UPPER DATAI INPNCX LDB #1 LBSR INPCSR TURN ON CURSOR OVER CHARS. * INPN1 LBSR WTKEY WAIT FOR KEYPAD * INPNP TST PNTFLG PUNT?? BEQ INPN2 BR. IF NOT LDB INPTMP LOAD ORIGINAL VALUE INPNSE LDX INPADR GET DATA ADDR. LBSR CLRNUM CLEAR FLAGS BEFORE CHANGING STB ,X REPLACE VALUE LBSR INPSHN SHOW IT @ OFFSET W. DATAI INPN3 CLRB LBRA INPCSR CLEAR THE CURSORS * INPN2 CMPB #9 IS INPUT NUMERIC?? BGT INPN4 BR. IF NOT INPNNN LDY INPADR GET ADDR. OF DATA LBSR CLRNUM CLEAR PARAMS. BEFORE CHANGING CLR ,Y CLEAR DATA OUT CLR IDXDEC CLEAR DECIMAL INDEX INPN5 STB TMPINM STASH KEYPAD RESULT FOR NOW LDB ,Y CODE TO HANDLE DISPLAY OFFSET TST IDXDEC BEQ INPNS ADDB DATAI INPNS LDA #10 MUL SCALE PREV. RESULT UP BY 10 ADDB TMPINM ADD IN CURRENT KEYPAD RESULT ADCA #0 ADD CARRY FOR DOUBLE-BYTE SUBD DATAID CORRECT FOR OFFSET LBSR INPCLM INCORPORATE LIMITS AND STASH LDY INPADR RESTORE ADDRESS INPN8 LBSR WTKEY WAIT FOR ANOTHER KEYPAD INPUT CMPB #9 IS IT DECIMAL?? BGT INPNP BR. IF NOT NUMERIC LDA IDXDEC LOAD DIGIT COUNTER BNE INPNZZ BR. IF NOT FIRST DIGIT TST TMPINM WAS IT ZERO?? BEQ INPNNN IGNORE IF SO INPNZZ CMPA NCHRSI ALL DIGITS IN?? BGE INPN8 IGNORE KEYPAD IF SO INCA STA IDXDEC RESTORE DIGIT COUNTER BRA INPN5 CONTINUE * INPN4 CMPB #CLEAR C KEY?? BNE INPN9 BR. IF NOT LBSR CLRNUM CLEAR STUFF LDY INPADR LOAD UP INPUT ADDR. LDB LMTMNS GET LOW LIMIT STB ,Y SATURATE AT LOW LIMIT LBSR INPSHN SHOW RESULT BRA INPN1 CONTINUE... * INPN9 CMPB #ENTER IS IT ENTER?? BEQ INPN3 EXIT IF ENTER TST N0 BNE INPNL0 BR. IF NOT @ TITLE EDIT CMPB #KKEY IS IT K?? BEQ INPN3 BR. IF SO * INPNL0 CMPB #PLUS IS IT PLUS?? BNE INPN10 BR. IF NOT LDB #1 INCREMENT POSITIVE STB IDXDEC BRA INPNPM BR. TO +/- ROUTINE INPN10 CMPB #MINUS IS IT MINUS?? LBNE INPN1 NO; NO OTHER CHARS ALLOWED, CONTINUE.. LDB #-1 INCREMENT NEGATIVE STB IDXDEC INPNPM CLR I1TM CLEAR TIMER SPEED FLAG CLRB LBSR INPCSR CLEAR THE CURSOR INPN11 LDY INPADR POINT TO DATA LDB ,Y GET IT CLRA ADDB IDXDEC ADD INC/DEC. TST IDXDEC BGE INPNGZ BCS INPN1X LDA #$FF LOAD DOUBLE NEGATIVE BRA INPN1X INPNGZ BCC INPN1X BR. IF IT OVERFLOWED INPN2X LDA #$7F LOAD MAX. CODE IN MSB IF SO INPN1X BSR INPCLM CLAMP @ LIMITS AND SHOW TST I1TM IS TIMER SLOW?? BNE INPN12 BR. IF NOT CLRB GET TIMER LSB STB TMR0 STORE IT LDB #$1 GET TIMER MSB STB TMR0 STORE IT INPN12 LDB PIADA GET KEY FLAGS ANDB #KSTRBE LOOK AT KEY STROBE LBEQ INPNCX STOP ON KEY RELEASE LDB TMROUT GET TIMER FLAGS ANDB #1 LOOK AT T0 BNE INPN12 LOOP UNTIL TIMEOUT OR KEYPAD-UP LDB #$20 SET T0 FOR SHORT TIME STB TMR0 SET TIMER LSB CLRB STB TMR0 SET TIMER MSB INCB STB I1TM SET TIMER FLAG TO FAST MODE BRA INPN11 CONTINUE AUTO-INC./DEC. * * SUBROUTINE TO HANDLE LIMITS AND SHOW DATA * INPCLM CMPD LMTPLD > + LIMIT??? BLE INPN6 BR. IF OK LDB LMTPLS SATURATE + BRA INPN7 INPN6 CMPD LMTMND < - LIMIT?? BGE INPN7 BR. IF OK LDB LMTMNS SATURATE - INPN7 BSR CLRNUM CLEAR PARMS. BEFORE CHANGING STB ,Y STASH VALUE * * SUBROUTINE TO SHOW CURRENT VALUE AND LOAD UP OB. * INPSHN TFR B,A SAVE VALUE LDB DSPOFF GET DISPLAY OFFSET LDX #0 ABX PUT INTO X LDB NCHRSI GET # CHARS. ADDA DATAI ADD IN OFFSET LBSR WRTDEC WRITE OUT RESULT * LDB LDOBH SHOULD WE LOAD UP OB.?? BEQ INPNRX BR. IF NOT LBRA LDOBHM LOAD UP OB. INPNRX LDB LDUTVB SHOULD WE PROGRAM THE TVB?? BEQ INPNRR BR. IF NOT LBRA LDTVB PROGRAM TVB * * ROUTINE TO HANDLE CURSOR (ON/OFF FLAG IN B ON ENTRY) * INPCSR LDA DSPOFF GET DISPLAY OFFSET LDX #0 LEAX A,X PUT IN X LDA NCHRSI GET # CHARS. INN1 LBSR CURSOR TURN CURSOR ON/OFF LEAX 1,X INCREMENT DISPLAY POINTER DECA ANY MORE?? BNE INN1 BR. IF SO INPNRR RTS RETURN * * FRONT-END ROUTINE TO "CLRART" TO RESET PARMS. * CLROUT PSHS A,B,X,Y LBSR CLREDT PULS A,B,X,Y RTS * CLRNUM PSHS B LDB N0 CMPB #5 BLT CLRNXY SKIP IF LVL. 0 INDEX NOT AUTO B OR T LDB N1 CMPB #10 BNE CLRNRS RETURN IF NOT CONTROLLER # CLRNXZ BSR CLROUT CLEAR STUFF CLRNRS PULS B RTS CLRNXY CMPB #1 BEQ CLRNXZ JUMP IF MIDI MODE CMPB #3 BNE CLRNRQ RETURN IF NOT SET MIDI OUT CLRXXX LDB N1 GET N1 INDEX BNE CLRNRS RETURN IF NOT CHANNEL # BRA CLRNXZ DO IT CLRNRQ CMPB #4 AUTP PORTAMENTO? BNE CLRNRS LDB N1 BEQ CLRNXZ CLEAR ON EFFECT ON/OFF CMPB #3 AFFECT? BEQ CLRNXZ BRA CLRNRS * PAGE * * CHARACTER- STRING- BASED INPUT ROUTINE * * ON ENTRY: LMTPLS HAS + LIMIT * #CHARS AVAILABLE TO USE IN DATAI * ADDR. OF ARGUMENT PASSED IN X * ADDR. OF ROOT FOR STRING TABLE IN Y * INPALP CLR DSPOFF NO DISPLAY OFFSET HERE CLR TQTRIG LDB ,X GET VALUE STB INPTMP STASH FOR NOW STX INPADR STASH ADDR. TOO! STY INPADC STASH ROOT ADDR. FOR SAFEKEEPING DECB STB ,X DEC. VALUE TO KLUDGE STATIC START * INPA1 LDB ,X GET VALUE INCB INCREMENT IT CMPB LMTPLS CHECK IF OVER + LIMIT BLE INPA2 BR. IF OK CLRB CLEAR IF OVER INPA2 BSR CLROUT CLEAR FLAGS BEFORE CHANGING ANYTHING STB ,X PUT RESULT BACK INPAAA PSHS B SAVE RESULT LDA DATAI GET #CHARS. AVAILABLE STA NCHRSI STASH FOR CURSOR ROUTINE CLRB TURN CURSORS OFF BSR INPCSR LDA DATAI GET # CHARS. AGAIN LDX #DSPLY0 INPA3 CLR ,X+ CLEAR ALL USED CHARS. DECA BGT INPA3 GET 'EM ALL LDY INPADC GET ROOT STRING ADDR. PULS A GET VALUE BACK LSLA CORRECT FOR DOUBLE-BYTE LDX A,Y POINT TO CHAR. STRING LDB ,X GET # CHARS. STB NCHRSI STASH IT FOR CURSOR CLRB LBSR PRTCHR PRINT STRING OUT LDB LDOBH LOAD UP OB.?? BEQ INPA4Q BR. IF NOT LBSR LDOBHM LOAD OB!! INPA4Q LDB LDUTVB PROGRAM TVB?? BEQ INPA4 BR. IF NOT LBSR LDTVB PROGRAM TVB!! INPA4 TST PNTFLG PUNT?? BNE INPAQ BR. IF SO * TST TQTRIG BEQ INPAWT BR. IF NO TIMED WAIT LDA #$70 STA TMR0 CLRA STA TMR0 SET TIMER INPATW LDA PIADA GET KEYPAD FLAGS ANDA #KSTRBE SELECT KEYPAD STROBE BEQ INPAWT BR. IF KEY UP LDA TMROUT GET TIMER FLAGS ANDA #1 SELECT TIMER LSB BNE INPATW LOOP IF TIMER STILL UP LDB CHRBUF GET CHARACTER BRA INPATT SKIP KEYPAD WAIT; AUTO INC/DEC-REMENT * INPAWT LDB #1 TURN CURSOR ON LBSR INPCSR TURN CURSORS ON OVER STRING * LBSR WTKEY WAIT FOR KEYPAD STB TQTRIG SET AUTO-INC/DEC-FLAG INPATT TST PNTFLG PUNT?? BEQ INPA5 BR. IF NOT LDB INPTMP RESTORE ORIGINAL VALUE LDX INPADR BRA INPA2 PUT IT IN AND EXIT * INPA5 CMPB #ENTER ENTER KEY?? BNE INPA6 BR. IF NOT INPAQ LDB DATAI GET # CHARS. STB NCHRSI PUT IN FOR CURSOR CLRB LBRA INPCSR TURN CURSORS OFF * INPA6 LDX INPADR RESTORE ARGUMENT ADDR. CMPB #KKEY K KEY?? LBEQ INPA1 BR. TO INCREMENT AGAIN IF SO CMPB #PLUS PLUS KEY?? LBEQ INPA1 BR. TO INCREMENT ALSO IF SO CMPB #MINUS MINUS KEY?? BEQ INPA7 BR. FOR AUTO DECREMENT * CMPB #CLEAR CLEAR KEY?? BNE INPAWT IGNORE IF NOT; NO OTHER OPTIONS LDB ,X GET VALUE CLRB CLEAR IT LBRA INPA2 CONTINUE * INPA7 LDB ,X LOAD & DECREMENT VALUE DECB LBGE INPA2 CONTINUE IF NO OVERFLOW LDB LMTPLS SATURATE AT LIMIT IF OVERFLOW LBRA INPA2 CONTINUE... * PAGE * * SUBROUTINE TO EDIT PATCH NUMBER AND TITLE * EDTTLE CLRB FIRST, PREPARE TO EDIT PATCH # STB LMTMNS ZERO LOWER LIMIT INCB STB DATAI NUMERIC OFFSET OF ONE INCB STB NCHRSI 2 CHARS. TO INPUT LDB #MAXPCH LOAD MAX. # PATCHES STB LMTPLS STORE AS MAX. LIMIT LDB #10 STB DSPOFF DISPLAY OFFSET OF 10 LDX #PNUM GET PATCH NUMBER ADDR. LBSR INPNBR ACCEPT NEW PATCH NUMBER TST PNTFLG WAS IT PUNT?? BEQ EDTT1 CONTINUE IF NOT EDTTRR RTS RETURN * EDTT1 CLR TQTRIG CLEAR FLAG LDX #PNUM NOW, PREPARE TO EDIT PATCH TITLE LDB ,X+ GET PATCH#, INCREMENT ADDR. STB CPTCH STASH IN CURRENT PATCH VALUE LDA #9 9 CHARS/PATCH STA NCHRSI STASH FOR CURSOR LDY #LSTPCH POINT AT TEMP. BUFFER EDTT2 LDB ,X+ GET A CHAR. OF PATCH TITLE STB ,Y+ STASH IT DECA BNE EDTT2 CONTINUE TILL DONE; SAVE ALL CHRS. EDTTST LDB #1 CLR DSPOFF LBSR INPCSR WRITE CURSORS OVER PATCH TITLE * EDTTWT LBSR WTKEY WAIT FOR KEYPAD * TST PNTFLG HAVE WE PUNTED?? BEQ EDTT3 BR. IF NOT EDTTRS LBSR CLRDSP CLEAR OUT DISPLAY LDA #9 LDX #LSTPCH LDY #PNAME EDTTR1 LDB ,X+ REPLACE PATCH TITLE WITH ORIGINAL STB ,Y+ DECA BNE EDTTR1 LDX #PNUM LBSR SHOPCH SHOW PATCH TITLE TST TQTRIG CHECK FLAG BEQ EDTTLE START OVER AGAIN.... CLR TQTRIG CLEAR FLAG BRA EDTTST * EDTT3 CMPB #CLEAR CLEAR KEY?? BNE EDTT4 BR. IF NOT LDY #DSPLY0 LDX #PNAME LDA #9 EDTTC1 LDB #$20 STB ,X+ CLEAR OUT PATCH CHARACTERS STB ,Y+ CLEAR OUT DISPLAY CHARACTERS DECA BNE EDTTC1 BRA EDTTWT CONTINUE... * EDTT4 CMPB #ENTER IS IT ENTER?? BEQ EDTTKK YES -- RETURN * CMPB #PLUS + KEY?? BNE EDTT5 BR. IF NOT LDA CPTCH LOAD CURRENT PATCH FOR TITLE EDITOR INCA INCREMENT IT CMPA #MAXPCH AT LIMIT?? BLE EDTT6 BR. IF OK CLRA ZERO IF NOT BRA EDTT6 * EDTT5 CMPB #MINUS - KEY?? BNE EDTT7 BR. IF NOT LDA CPTCH GET CURRENT PATCH FOR TITLE EDITOR DECA DECREMENT IT BGE EDTT6 BR. IF OK LDA #MAXPCH LOAD MAXIMUM IF NOT * EDTT6 STA CPTCH RESTORE PATCH # LDB #TOTVAR #VARIABLES/COMPRESSED PATCH MUL GET POINTER INTO PATCHES ADDD #NVRAM0+1 ADD IN OFFSET TFR D,X PUT INTO INDEX REG. LDY #PNAME POINT @ LOADED PATCH NAME LDA #9 EDTT8 LDB ,X+ COPY CHARS. FROM CANNED PATCH STB ,Y+ INTO LOADED PATCH DECA BNE EDTT8 * LDX #PNAME LDY #DSPLY0 LDA #8 EDTT9 LDB ,X+ PRINT NEW CHARS. OUT STB A,Y DECA BGE EDTT9 LBRA EDTTWT NEXT KEYPAD INPUT... * EDTT7 CMPB #KKEY K KEY?? LBNE EDTTWT IGNORE OTHERWISE, NO OPTIONS LEFT EDTTKK LDB #-1 STB NCK INITIALIZE CURRENT CURSOR POSITION EDTT10 LDB NCK GET CURRENT CURSOR CLR CINC CLEAR INCREMENT/DECREMENT INCB CMPB #8 ONLY 9 CHARS. ALLOWED BLE EDTT11 BR. IF OK CLRB RESET EDTT11 STB NCK RESTORE IT EDTQST LDX #PNAME LDA B,X GET CHAR. STA TMPCHR STASH CURRENT CHAR. NEGB ADDB #8 STB NCKD STORE DISPLAY-RELATIVE INDEX CLRB LBSR INPCSR CLEAR ALL CURSORS EDTTCS LDX #0 LDB NCKD ABX PUT DISPLAY-RELATIVE OFFSET INTO X LDB #1 LBSR CURSOR TURN CURSOR ON @ CURRENT CHAR. * EDTT12 LBSR WTKEY WAIT FOR KEYPAD LDX #PNAME POINT AT TITLE LDA NCK GET OFFSET LEAY A,X POINT @ CHAR. LDA NCKD GET DISPLAY-RELATIVE INDEX * TST PNTFLG DID WE PUNT?? BEQ EDTT13 BR. IF NOT LDB TMPCHR GET ORIG. CHAR. STB ,Y RESTORE IT LDX #DSPLY0 STB A,X REPLACE CHAR. TST CINC HAVE WE EDITED THIS BABY?? BNE EDTTAE BR. IF SO INC TQTRIG SET FLAG LBRA EDTTRS BUMP UP EDTTAE LDB NCK CLR CINC CLEAR P/M FLAG BRA EDTQST START OVER * EDTT13 CMPB #ENTER ENTER KEY?? LBEQ EDTTRR THEN RETURN * CMPB #CLEAR CLEAR KEY?? BNE EDTT14 BR. IF NOT LDB #$20 LOAD ASCII BLANK STB ,Y CLEAR OUT CHAR. LDX #DSPLY0 STB A,X CLEAR OUT CHAR. ON DISPLAY STB CINC SET INCRE/DECRE FLAG BRA EDTT12 CONTINUE * EDTT14 CMPB #KKEY K AGAIN?? BEQ EDTT10 THEN INCREMENT INDEX * CLR I1TM CLEAR TIMER FLAG LDX #DSPLY0 CMPB #PLUS + KEY?? BNE EDTT15 BR. IF NOT LDB #1 POSITIVE INCREMENT STB CINC STASH IT BRA EDTT1Z * EDTT15 CMPB #MINUS - KEY?? BNE EDTT12 OUT OF OPTIONS; IGNORE KEY LDB #-1 NEGATIVE INCREMENT STB CINC STASH IT * EDTT1Z PSHS X LDB NCKD LDX #0 ABX CLRB LBSR CURSOR TURN OFF CURSOR PULS X * EDTT16 LDB ,Y GET VALUE ADDB CINC ADD IN INCREMENT CMPB #$20 CHECK FOR UNDERFLOW BGE EDTT17 BR. IF NO OVERFLOW LDB #$5F LARGEST CHAR. VALUE BRA EDTT18 EDTT17 CMPB #$5F TOO BIG?? BLE EDTT18 BR. IF OK LDB #$20 CLEAR IF NOT EDTT18 STB ,Y REPLACE CHAR. IN TITLE STB A,X SHOW IT TST I1TM SLOW TIMER MODE?? BNE EDTT19 BR. IF NOT CLRB LOAD SLOW TIMER CODE STB TMR0 STORE T0 LSB LDB #1 STB TMR0 SET T0 MXB EDTT19 LDB PIADA GET CHAR. FLAG ANDB #KSTRBE LOOK ONLY AT KEYPAD STROBE LBEQ EDTTCS BRA. ON KEY UP LDB TMROUT GET TIMER FLAGS ANDB #1 LOOK @ T0 BNE EDTT19 WAIT FOR TIMER LDB #$20 SET T0 FOR FASTER TIME STB TMR0 SET T0 LSB CLRB STB TMR0 SET T0 MSB INCB STB I1TM SET TIMER FLAG FOR FAST BRA EDTT16 CONTINUE AUTO INCREMENT/DECREMENT * PAGE ********************************************************************* * * UTILITY SUBROUTINE COLLECTION FOR DISPLAY * ********************************************************************* * * SUBROUTINE TO CLEAR DISPLAY * CLRDSP PSHS A,X SAVE NEEDED REGS. LDA #CUE STA PIADA PUT DISPLAY IN CURSOR MODE LDX #DSPLY0 GET DISPLAY ADDR. LDA #11 LOAD CHAR. COUNT CLRCSR CLR A,X CLEAR CURSOR DECA DECREMENT COUNT BGE CLRCSR NEXT CHAR. CLR PIADA RESET CURSOR MODE LDA #11 LOAD CHAR. COUNT CLRCHR CLR A,X CLEAR DISPLAY DECA DEC. COUNT BGE CLRCHR NEXT CHAR. PULS A,X RESTORE STACK RTS RETURN... * * SUBROUTINE TO PRINT CHARACTERS ON DISPLAY * ON ENTRY.. * X = ADDR. OF CHAR. STRING (1'ST BYTE = COUNT) * B = START CHAR. IN DISPLAY (0 TO 11) * PRTCHR PSHS A,Y SAVE NEEDED REG. TFR X,Y LDX #DSPLY0 GET DISPLAY ADDR. ABX ADD DISPLAY OFFSET (IN B) LDB ,Y+ GET CHAR. COUNT IN LEADING BYTE ABX CORRECT FOR # OF CHARS. SHOWC LDA ,Y+ GET NEXT CHARACTER STA ,-X WRITE INTO NEXT DISPLAY LOC. DECB DECREMENT COUNT BNE SHOWC CONTINUE... PULS A,Y RESTORE STACK RTS RETURN.... * * SUBROUTINE TO WRITE AND CLEAR CURSOR * ON ENTRY.. * X = DISPLY OFFSET (0 TO 11) * B = 1 (SET CURSOR) OR 0 (CLEAR CURSOR) * CURSOR PSHS A CAN A FOR NOW LDA #CUE GET CURSOR CODE STA PIADA ENABLE CURSOR STB DSPLY0,X WRITE B INTO DISPLAY CHAR. CLRA STA PIADA DISABLE CURSOR PULS A RESTORE STACK RTS RETURN.... * PAGE * * LOAD PATCH IN FROM NON-VOLATILE MEMORY * ON ENTRY: PATCH# TO LOAD IS IN "PCHLDQ" * LDPTCM LDY #PEBUF POINT @ SYSEX BUFFER LDA PCHLDQ GET PTCH# BRA LDP2 CONTINUE LDPTCH LDY #PNUM POINT @ MASTER PATCH LIST LDP0 LDA PCHLDQ GET PTCH# STA NVMPCH STORE AS LAST PATCH LOADED * * GET AUTOCHORD INTERVAL * LDX #AUTCRD POINT AT AUTOCHORD BUFFER LSLA 2 BYTES PER PATCH TFR A,B PREPARE ABX ADD IN THE OFFSET LDB ,X+ PSHS B ANDB #$F GET FIRST BYTE STB OBIVAL STASH FIRST BYTE PULS B LSRB LSRB LSRB LSRB STB OBIVAL+1 STASH SECOND BYTE LDB ,X STB OBIVAL+2 STASH THIRD BYTE LDA NVMPCH GET THE PATCH# * LDP2 LDB #TOTVAR GET # COMPRESSED VARIABLES/PATCH MUL GET INDEX INTO PATCH LIST ADDD #NVRAM0 GET START OF PATCH STORAGE TFR D,X POINT @ STARTING SOURCE ADDR. IN X * * LOAD TITLE AND PATCH NUMBER * LDB #10 LOAD FIRST 10 BYTES LDP1 LDA ,X+ STA ,Y+ DECB BNE LDP1 * * LOAD MIDI MODE DATA * LDB ,X+ TFR B,A STASH ANDB #$F GET LOW 4 BITS STB ,Y+ LSRA LSRA LSRA LSRA TFR A,B TRANSFER REMAINDER ANDB #3 GET LOW 2 BITS STB ,Y+ LSRA LSRA STA ,Y+ STORE LAST BITS LDB ,X+ TFR B,A STASH ANDB #7 GET LOW 3 BITS STB ,Y+ CLRB LSRA LSRA LSRA LSRA ROLB STB ,Y+ STORE A BIT LDB ,X+ NEXT BYTE STB ,Y+ STA ,Y+ STORE REMAINING BITS FROM BEFORE LDA ,X+ TFR A,B ANDA #3 STA ,Y+ LSRB LSRB STB ,Y+ * * 4-VOICE SETUP DATA * LDA ,X+ CLRB LSRA ROLB STB ,Y+ STORE FIRST BIT PSHU A STASH LEFTOVER ANDA #$F GET NEXT 4 BITS STA ,Y+ LDA ,X+ STA ,Y+ LOAD ENTIRE BYTE LDB ,X+ TFR B,A SAVE THIS ANDB #$3F LOW 6 BITS PSHU B STASH THIS FOR LATER LSRA LSRA LSRA LSRA LSRA LSRA STA ,Y+ STORE REMAINDER PULU A RESTORE OLD GUY STA ,Y+ PUT OUT THE 6 BITS PULU A GET THE OLDER GUY LSRA CORRECT FOR LAST 4 BITS LSRA LSRA LSRA TFR A,B PRESERVE ANDB #1 LOW BIT STB ,Y+ LSRA STA ,Y+ STORE REMAINDER LDA ,X+ NEXT BYTE CLRB LSRA ROLB STB ,Y+ STORE BIT TFR A,B ANDA #3 STA ,Y+ LSRB LSRB STB ,Y+ LDA ,X+ STA ,Y+ LDA ,X+ STA ,Y+ LDA ,X+ TFR A,B ANDA #127 LSLB ROLB ANDB #1 STB ,Y+ STA ,Y+ * * SET MIDI OUT DATA * LDB ,X+ LSRB CORRECT FOR UNUSED BIT PSHU B STASH FOR LATER LDA ,X+ TFR A,B STASH ANDB #$F LOW 4 BITS STB ,Y+ LSRA LSRA LSRA LSRA TFR A,B ANDB #3 NEXT 2 BITS STB ,Y+ LSRA LSRA STA ,Y+ NEXT BIT PULU A RESTORE 7 BITS TFR A,B ANDB #1 LOW BIT STB ,Y+ CLRB LSRA LSRA ROLB STB ,Y+ NEXT BIT CLRB LSRA ROLB STB ,Y+ NEXT BIT LDB ,X+ STB ,Y+ NEXT BYTE LDB ,X+ STB ,Y+ NEXT BYTE STA ,Y+ LAST BITS LDB ,X+ NEXT BYTE STB ,Y+ LDB ,X+ TFR B,A LSRB LSRB STB ,Y+ PSHU A LDB ,X+ STB ,Y+ LDB ,X+ TFR B,A ANDB #1 STB ,Y+ LSRA STA ,Y+ LDA ,X+ STA ,Y+ PULU A * * AUTO PRTMNTO DATA * CLRB LSRA ROLB STB ,Y+ LOW BIT LDB ,X+ STB ,Y+ NEXT BYTE ANDA #1 STA ,Y+ NEXT BIT OF REMAINDER LDA ,X+ TFR A,B COPY ANDB #3 STB ,Y+ STORE LOW 2 BITS LSRA LSRA STA ,Y+ LAST BITS * * AUTO BEND AND AUTO TRILL * LDA #2 STA CTRQ1 INITIALIZE COUNTER FOR TWO TIMES LDBT1 LDA ,X+ CLRB LSRA ROLB STB ,Y+ STORE LOW BIT PSHU A STASH REMAINDER LDA #2 STA CTRQX SET COUNTER LDBT3 LDA ,X+ GET A BYTE TFR A,B ANDB #$7F LOOK @ LOW 7 BITS STB ,Y+ STASH 'EM CLRB LSLA ROLB GET HIGH BIT STB ,Y+ STASH IT DEC CTRQX BNE LDBT3 LOOP TWICE LDA #4 LOAD NEXT 4 BYTES LDBT2 LDB ,X+ STB ,Y+ DECA BNE LDBT2 LOOP... PULU A RESTORE REMAINDER TFR A,B STASH ANDB #3 GET LOW 2 BITS STB ,Y+ STORE THEM LSRA LSRA CORRECT REMAINDER LDB ,X+ GET A BYTE STB ,Y+ STASH IT STA ,Y+ STASH LAST BIT LDB #7 DO 7 TIMES LDBT4 LDA ,X+ STA ,Y+ DECB BNE LDBT4 DEC CTRQ1 DECREMENT COUNTER BNE LDBT1 CONTINUE FOR AUTO-TRILL LDA ,X+ LAST 3 ITEMS FOR TRILL ONLY STA ,Y+ LDA ,X+ TFR A,B ANDA #3 STA ,Y+ LSRB LSRB STB ,Y+ * * TVB * LDA ,X+ STA ,Y+ LDB ,X+ LDA ,X+ PSHS A LDA ,X+ STA SVPQ LDA ,X+ PSHU A LDA ,X+ PSHU A LDA ,X+ PSHU A LDA ,X+ PSHU B TFR A,B ANDA #127 STA ,Y+ LSLB ROLB ANDB #1 PULU A STA ,Y+ PULU A PSHU A ANDA #127 STA ,Y+ PULS A STA ,Y+ PSHS B PULU A LSLA ROLA ANDA #1 PSHS A PULU A TFR A,B ANDA #127 STA ,Y+ LSLB ROLB ANDB #1 LDA SVPQ STA ,Y+ PULU A STA ,Y+ STB ,Y+ PULS B STB ,Y+ PULS B STB ,Y+ * * ALL LOADED !!! * RTS RETURN * PAGE * * SAVE PATCH TO NON-VOLATILE MEMORY * ON ENTRY: PATCH # IS IN REG. B * SAVPCM LDY #PEBUF POINT @ SEX BUFFER BRA SAVP0 SAVPCH LDY #PNUM Y NOW POINTS TO PATCH BUFFER STB NVMPCH SAVE PATCH # FOR RE-BOOT LOAD * * SAVE AUTOCHORD SETTINGS * LDX #AUTCRD LSLB 2 BYTES PER PATCH ABX LDA OBIVAL+1 LSLA LSLA LSLA LSLA ORA OBIVAL STA ,X+ LDA OBIVAL+2 STA ,X LDB NVMPCH RESTORE PATCH# * SAVP0 LDA #TOTVAR GET # VARIABLES/COMPRESSED PATCH MUL ADDD #NVRAM0 POINT TO NON-V. RAM TFR D,X X NOW REFERENCES PATCH ADDR. DEST. * * SAVE PATCH NUMBER AND TITLE * LDA #10 STORE FIRST 10 BYTES STRAIGHT THRU SAVP1 LDB ,Y+ STB ,X+ DECA BNE SAVP1 * * SAVE MIDI MODE DATA * LDA ,Y+ SAVE LOW 4 BITS ON THIS LDB ,Y+ LSLB LSLB LSLB LSLB STB SVPQ ORA SVPQ PACK NEXT BIT LDB ,Y+ LSRB RORB LSRB STB SVPQ ORA SVPQ PACK NEXT BIT STA ,X+ STASH 6 BITS LDA ,Y+ WILL BE LOW 3 BITS LDB ,Y+ GET ANOTHER BIT LSLB LSLB LSLB STB SVPQ ORA SVPQ PUT 'EM TOGETHER LDB ,Y+ WILL BE NEXT BYTE PSHU B STASH IT LDB ,Y+ WILL BE UPPER BIT LSLB LSLB LSLB LSLB STB SVPQ ORA SVPQ STA ,X+ SAVE PULU A RESTORE STACK STA ,X+ NEXT BYTE LDA ,Y+ LDB ,Y+ LSLB LSLB STB SVPQ ORA SVPQ STA ,X+ * * 4-VOICE SETUP DATA * LDA ,Y+ LOW BIT LDB ,Y+ LSLB STB SVPQ ORA SVPQ LDB ,Y+ PSHU B CAN FOR NOW LDB ,Y+ PSHS B CAN FOR NOW LDB ,Y+ PSHS B CAN FOR NOW LDB ,Y+ PACK LOW BIT INTO A LSRB RORB LSRB LSRB STB SVPQ ORA SVPQ LDB ,Y+ PACK 2 BITS INTO A LSRB RORB RORB STB SVPQ ORA SVPQ STA ,X+ STORE ALL PACKED 8 BITS PULU A STA ,X+ RESTORE AND STASH PULS A RESTORE THE 6 BITS PULS B RESTORE NEXT 2 LSRB RORB RORB STB SVPQ ORA SVPQ STA ,X+ STORE 6 + 2 STASHED BITS LDA ,Y+ GET A BYTE PSHU A SAVE FOR NOW LDA ,Y+ LSLA LDB ,Y+ LSLB LSLB LSLB STB SVPQ ORA SVPQ PULU B LOW BIT STB SVPQ ORA SVPQ STA ,X+ LDA ,Y+ STA ,X+ LDA ,Y+ STA ,X+ LDA ,Y+ LDB ,Y+ LSRA RORA STA SVPQ ORB SVPQ STB ,X+ * * SET MIDI OUT * LDA ,Y+ GET LOW 4 BITS LDB ,Y+ GET NEXT 2 BITS LSLB LSLB LSLB LSLB STB SVPQ ORA SVPQ LDB ,Y+ GET NEXT 2 BITS LSRB RORB RORB STB SVPQ ORA SVPQ PSHS A HOLD FOR NOW CLRA A PLACEHOLDER FOR AN OLD GUY LDB ,Y+ LSLB STB SVPQ ORA SVPQ NOW OBSOLETE... LDB ,Y+ LSLB LSLB STB SVPQ ORA SVPQ LDB ,Y+ PACK ANOTHER BIT LSLB LSLB LSLB STB SVPQ ORA SVPQ LDB ,Y+ GET ANOTHER BYTE PSHU B STASH FOR NOW LDB ,Y+ GET ANOTHER BYTE PSHU B STASH FOR NOW LDB ,Y+ LSLB LSLB LSLB LSLB STB SVPQ ORA SVPQ STA ,X+ PULS A STA ,X+ SAVE OLD GUY PULU B RESTORE STACK PULU A STA ,X+ STB ,X+ LDB ,Y+ GET A BYTE STB ,X+ SAVE IT LDB ,Y+ GET A BYTE LSLB LSLB SHIFT 2 PSHU B SAVE FOR LATER LDB ,Y+ PSHS B SAVE FOR EVEN LATER LDB ,Y+ LDA ,Y+ LSLA STA SVPQ ORB SVPQ PSHS B DITTO LDA ,Y+ PSHS A EVEN MORE DITTO PULU B RESTORE STB SVPQ STASH HIGH 6 BITS * * AUTO PORTAMNTO. * LDA ,Y+ LOW BIT ORA SVPQ STA SVPQ LDA ,Y+ LDB ,Y+ GET NEXT BIT LSLB ORB SVPQ STB ,X+ SAVE IT PULS B THESE ARE TO RESTORE THE LAST 3 ITEMS FROM MIDI OUT (KLUDGE) STB SVPQ PULS B STB CTRQ1 PULS B STB ,X+ LDB CTRQ1 STB ,X+ LDB SVPQ STB ,X+ STA ,X+ LDB ,Y+ NEXT BYTE (2 BITS) STB SVPQ LDB ,Y+ UPPER 6 BITS LSLB LSLB ORB SVPQ STB ,X+ * * AUTO BEND AND AUTO TRILL * LDB #2 STB CTRQ1 LOAD UP COUNTER SVBT1 LDB ,Y+ PICK UP LOW BIT STB ,X+ STASH FOR NOW LDB #2 STB CTRQX SET COUNTER SVBT3 LDA ,Y+ GET 7 BITS LDB ,Y+ GET A BIT LSRB RORB PUT IT IN HIGH BIT STB SVPQ ORA SVPQ COMBINE IT W. THE 7 STA ,X+ STASH IT DEC CTRQX BNE SVBT3 LOOP... LDA #4 XFER NEXT 4 BYTES SVBT2 LDB ,Y+ STB ,X+ DECA BNE SVBT2 LDB ,Y+ GET 2 BITS FOR OLD BYTE LSLB LDA #-7 OFFSET TO SEE OLD BYTE ORB A,X OR IN NEW DATA PSHU B STASH BITS LDB ,Y+ STB ,X XFER NEXT BYTE INTACT LDB ,Y+ GET A BIT LSLB LSLB LSLB SHIFT UP STB SVPQ PULU B RESTORE BITS ORB SVPQ COMBINE THEM STB A,X STASH BACK LEAX 1,X INCREMENT OUTPUT POINTER LDB #7 DO 7 TIMES SVTB4 LDA ,Y+ STA ,X+ DECB BNE SVTB4 DEC CTRQ1 DECREMENT COUNTER BNE SVBT1 GO BACK TO DO AUTO TRILL BLOCK LDA ,Y+ THESE ONLY FOR AUTO TRILL STA ,X+ LDA ,Y+ LDB ,Y+ LSLB LSLB STB SVPQ ORA SVPQ STA ,X+ * * TVB * LDB #4 DO 4 TIMES SVBT5 LDA ,Y+ STA ,X+ LDA ,Y+ PSHU A DECB BNE SVBT5 PULU A STA ,X+ LDB #3 DO 3 TIMES SVBT6 PULU A STA SVPQ LDA ,Y+ LSRA RORA ORA SVPQ STA ,X+ DECB BNE SVBT6 * * ALL SAVED! * RTS RETURN * PAGE * * SUBROUTINE TO LOAD UP OBHM. HARDWARE * ON ENTRY: PARM# ASSUMED IN REG. B * (0 => LOAD EVERYTHING) * LDOBHM CMPB #11 INDEX > MAX?? BLE LDOB1 BR. IF OK RTS RETURN IF NOT LDOB1 LSLB CORRECT FOR ADDR. INDEX LDX #OB1ADL LOAD JUMP TABLE ADDR. LDY B,X GET ADDR. TO JUMP TO JMP ,Y JUMP TO SELECTED ROUTINE * OB1ADL FDB LDALL ROUTINE ADDR. LIST FDB LDPGCG FDB LDPBRG FDB LDPMMD FDB LDPMTM FDB LDUNSN FDB LDSPLM FDB LDRSGN FDB LDASSN FDB LDOCTV FDB LDBASE FDB LDSWPS * * LOAD EVERYTHING * LDALL BSR LDPGCG BSR LDPBRG BSR LDPMMD BSR LDPMTM BSR LDUNSN BSR LDSPLM BSR LDRSGN BSR LDASSN BSR LDOCTV BSR LDBASE BSR LDSWPS LBRA LDTVB0 LOAD UP TVB TOO!! * * SET OB. PROGRAM NUMBER (1 - 16) * LDPGCG LDB OBPGRM GET IT ADDB #$28 INSERT PCG CODE & ADJUST FOR BANK EORB #$18 FIX BANK SWITCH BITS STB PIADB WRITE OUT TO OB. BUS RTS * * SET PBEND RANGE * LDPBRG LDB PBRNGE GET VALUE STB PBSENS LOAD PB-SENS DAC RTS * * SET PMNTO. MODE * LDPMMD LDB PMNMDE GET PORT. MODE BEQ LDPM1 BR. IF PORT. IS OFF DECB ADJUST OFFSET ORB #$1C OR IN PORT. MODE CODE STB PIADB WRITE TO OB. BUS LDPM2 LDB PMNTME GET PORT. TIME ORB #$80 OR IN CODE STB PIADB LOAD UP PORT. DAC RTS LDPM1 LDB #$80 LOAD CODE TO TURN PORT. OFF STB PIADB CLEAR PORT. DAC LDB #$1C GET NULL "BOTH" CODE STB PIADB STORE INTO PORT. MODE RTS * * SET PMNTO. TIME * LDPMTM TST PMNMDE CHECK PORT. MODE BEQ LDPM1 BR. AND CLEAR PORT DAC IF OFF BRA LDPM2 BR. TO LOAD PORT DAC IF ON * * SET UNISON SWITCH * LDUNSN LDB UNISON GET UNISON FLAG ORB #$14 OR IN CODE STB PIADB WRITE TO OB. BUS RTS * * SET SPLIT MODE * LDSPLM LDB SPLTMD GET SPLIT MODE BEQ LDSPL1 BR. IF SPLIT OFF DECB ADJUST OFFSET BEQ LDSPL2 EORB #3 FIX MODE BIT REVERSALS LDSPL2 ORB #$18 OR IN CODE STB PIADB SET SPLIT MODE LDB #$11 LOAD SPLIT ON CODE STB PIADB TURN SPLIT ON RTS LDSPL1 LDB #$18 STB PIADB SET SPLIT MODE TO NULL 2-2 LDB #$10 LOAD SPLIT OFF CODE STB PIADB TURN SPLIT OFF RTS * * SET REASSIGN MODE * LDRSGN LDB RSNMDE GET REASSIGN MODE EORB #1 FLIP BIT FOR REVERSED SWITCH ORB #8 INSERT CODE STB PIADB SEND COMMAND RTS * * SET KEYBOARD ASSIGN MODE * LDASSN LDB ASSIGN GET ASSIGN MODE ORB #4 PUT IN CODE STB PIADB SET RTS * * SET OCTAVE TRANSPOSE * LDOCTV LDB OCTAVE GET THE OCTAVE TO SET ORB #$C INSERT OB. CODE STB PIADB RTS * * SET VCF BASE FREQ. * LDBASE LDB VCFBSE GET & SET STB VCF0 RTS * * SET VCF MOD SENSITIVITY * LDSWPS LDB VCFSWP STB VCFSEN RTS * PAGE * * ROUTINES TO LOAD UP TVB * LDTVB0 BSR LDVOL BSR LDBAL BSR LDBASS BSR LDTRBL BSR LDSTM BSR LDENH BRA LDLDC * LDTVB DECB COMPENSATE FOR ADDED OFFSET CMPB #10 INDEX TOO BIG? BLE LDT1 BR. IF OK LDRTS RTS LDT1 LSLB LDX #TVBADL LDY B,X JMP ,Y GO TO IT... * TVBADL FDB LDVOL FDB LDRTS FDB LDBAL FDB LDRTS FDB LDBASS FDB LDRTS FDB LDTRBL FDB LDRTS FDB LDSTM FDB LDENH FDB LDLDC * LDVOL LDB TVBVOL SET VOLUME STB OUTVOL STB LOCVOL RTS * LDBAL LDB TVBBAL SET BALANCE STB OUTBAL STB LOCBAL RTS * LDBASS LDB TVBBAS SET BASS STB OUTBAS STB LOCBAS RTS * LDTRBL LDB TVBTRB SET TREBLE STB OUTTRB STB LOCTRB RTS * LDSTM LDB TVBSTM SET STEREO/MONO NEGB SET 1 => -1 STB OUTSTM RTS * LDENH LDB TVBENH SET STEREO ENHANCE NEGB SET 1 => -1 STB OUTENH RTS * LDLDC LDB TVBLDC SET LOUDNESS COMPENSATION STB OUTCMP RTS * PAGE * * ROUTINE TO CLEAR ALL AND CLEAN UP ARTIFACTS * CLREDT LBSR CLRNTE TURN NOTES OFF LBSR CLRPBO CLEAR LOCAL PB BSR CLRPRM CLEAR STUFF RTS * CLRART LBSR CLRNTE TURN NOTES OFF FIRST LBSR CLRPBO CLEAR PITCH BEND ON OB. * CLREFS LDX #TMR0 POINT @ T0 LDA #3 DO ALL 3 TIMERS CLRA0 LDB #1 LOWEST TIME STB ,X CLRB STB ,X+ DECA DECREMENT COUNT BNE CLRA0 * CLRPRM CLRA ENTRY TO ONLY CLEAR EFFECTS STA CLRFLG RESET QUEUED CLEAR FLAG STA ATACTV CLEAR AUTO-TRILL ACTIVE MODE STA ABACTV CLEAR AUTO-BEND ACTIVE MODE STA LSTACT CLEAR LAST ACTION STA ABTGED CLEAR AUTO-BEND TRIGGER STA ATTGED CLEAR AUTO-TRILL TRIGGER STA NCTLTG CLEAR DELAY CONTROLLER BYPASS STA TGLSGN CLEAR TRIANGLE SLOPE STA APBOUT CLEAR BEND WORD STA APBOUT+1 STA TRLOUT CLEAR TRILL WORD INCA STA ZFSSQ INITIALIZE CONTROLLER FLAG TST ABEND AUTO-BEND ENABLED?? BEQ CLRA2 BR. IF NOT TST VCFBND VCF MOD INCLUDED? BEQ CLRA2X BR. IF NOT CLR VCFMOD CLEAR IF SO CLRA2X LDB OCLBND OUTPUT ENABLED FOR AUTO-BEND?? BEQ CLRAX BR. IF NOT CMPB #3 IS IT OFF? BEQ CLRAX THEN BR. TST CTLBND OUT. CTLR. = PBND?? BNE CLRA3 BR. IF NOT LDD #PBNULL GET NULL PB. BSR PBSOUT SEND IT BRA CLRAX CLRA3 LDB IVLBND USE DEFAULT VALUE FOR CLEAR LDA CTLBND GET CONTROLLER # BSR CTLOUT SEND IT CLRAX LDA OCLBND ANDA #1 LOOK @ OUTPUT ENABLE BIT STA ZFSSQ STASH IN KLUDGY FLAG * CLRA2 TST ATRILL AUTO-TRILL ACTIVE?? BEQ CLRAZ BR. IF NOT TST VCFTRL VCF MOD INCLUDED? BEQ CLRA22 BR. IF NOT CLR VCFMOD CLEAR IF SO CLRA22 LDB OCLTRL OUTPUT ENABLED FOR A. TRILL??? BEQ CLRAY BR. IF NOT CMPB #3 IS IT OFF? BEQ CLRAY THEN BR. TST CTLTRL PB SELECTED?? BNE CLRA5 BR. IF NOT LDD #PBNULL GET NULL PB. BSR PBSOUT SEND IT BRA CLRAY CLRA5 LDB IVLTRL USE DEFAULT VALUE FOR CLEAR LDA CTLTRL GET CONTROLLER # BSR CTLOUT SEND IT CLRAY LDA OCLTRL ANDA #1 LOOK AT OUTPUT-ENABLE BIT ANDA ZFSSQ COMBINE W. PREVIOUS RESULT BEQ CLRPBO CLEAR LOCAL PB. IF EFFECT SET CLRAZ TST ZFSSQ ANYTHING HAPPEN? BEQ CLRPBO BR. IF YES * CLRA4 RTS RETURN * * SEND PTCH. BEND VALUE IN D TO OUTPUT CONTROLLER * PBSOUT EXG A,B SWAP BYTES STD ODATAS STORE DATA IN QUEUE LDB #2 STB OCOUNT STORE COUNT OF BYTES LDB #MPBND LOAD MIDI BEND CODE LDA CHNL1 GET OUTPUT CHNL. LBRA MDIOUT SHIP IT OUT * * TURN LOCAL PBEND TO NULL VALUE * CLRPBO LDD #PBOFF GET ZERO OB. BEND VALUE STD PBHI NULL PBEND RTS * * * SEND CONTROLLER (A) VALUE (B) TO OUTPUT * CTLOUT ANDB #$7F AND OUT CRAP STD ODATAS STORE DATA IN QUEUE LDB #2 2-BYTE COUNT STB OCOUNT STASH IT LDB #MCTLCH GET CONTROL CHANGE CODE LDA CHNL1 GET OUTPUT CHNL. LBRA MDIOUT SHIP IT OUT * * TURN NOTES OFF ON OB . AND RESET ASSOCIATED ITEMS * CLRNTE LDB #1 LOAD OB. NOTE RESET CODE STB PIADB CLEAR OB. NOTES * LDB SENDMD CHECK SEND MODE?? BEQ CLRN1 BR. IF MUTE LDX #OCOUNT SET UP FOR "ALL NOTES OFF" TO OUT LDB #2 STB ,X++ PUT 2 INTO BYTE COUNT LDB #123 ALL-NOTES-OFF CTLR. CODE STB ,X+ CLRB STB ,X LAST BYTE IS ZERO LDA CHNL1 GET OUTPUT CHNL. LDB #MCTLCH CONTROL CHANGE CODE LBSR MDIOUT SEND IT TO OUT CLRA STA CUTCNT STA SAFEFG STA VCFMOD STA LDNOTE STA OVIND STA NONOUT CLEAR # NOTES ON AT OUT LDB #127 CLEAR ALL 128 OUTPUT NTE. ENTRIES LDX #OUTLST LDY #OUTREV PSHS U LDU #XLIST CLRN2 STA B,X CLEAR STA B,Y CLEAR STA B,U CLEAR DECB BGE CLRN2 PULS U * TST APMNTO AUTO PORT. UP? BEQ CLRN0 BR. IF NO LDA APTDST GET DEST. FLAG BEQ CLRN0 BR. IF 4-V ONLY CMPA #3 OFF? BEQ CLRN0 BR. IF SO LBSR LDPMTM CLEAR 4V PORTAMENTO LDA #65 GET PORT. OFF/ON CODE STA ODATAS CLRA STA ODATAS+1 LDA CHNL1 LDB #MCTLCH BSR MDIOUT PUT PORT. OFF CODE OUT LDA #5 PORT. TIME CODE STA ODATAS CLRA SET TO ZERO STA ODATAS+1 STA PORTON RESET INTERNAL FLAG LDA CHNL1 LDB #MCTLCH BSR MDIOUT SET PORT. TIME TO ZERO * CLRN0 LDA #121 RESET ALL CONTROLLERS CODE STA ODATAS CLRA STA ODATAS+1 LDA CHNL1 LDB #MCTLCH BSR MDIOUT SHIP IT OUT * CLRN5 LDA #15 STA STATLO RESET RUNNING OUTPUT STATUS! * CLRN1 CLRA CLEAR 64-NTE. 4-VOICE LIST LDB #63 LDX #NLST4V LDY #STSVEL CLRN3 STA B,X STA B,Y DECB BGE CLRN3 STA SUSTFG * LDB #6 CLEAR 7 NOTE-RELATED BYTES LDX #NTESND CLRN4 STA B,X DECB BGE CLRN4 * CLRB STD NDOWNL STD NTAKNL STA NONDLY STA LSTPLC STA NCTLTG STA ODLYON STA NQUEQ DECA STA NTCVAL * LDB TVBVOL SET VOLUME STB OUTVOL STB LOCVOL LDB TVBBAL SET BALANCE STB OUTBAL STB LOCBAL LDB TVBBAS SET BASS STB OUTBAS STB LOCBAS LDB TVBTRB SET TREBLE STB OUTTRB STB LOCTRB * RTS RETURN * PAGE * * BASIC ROUTINE TO HANDLE MIDI OUTPUT * ON ENTRY: STATUS CODE IN B, OUT CHL. # IN A * #BYTES IN OCOUNT, DATA IN ODATAS * MDIOUT STA CHONOW STASH CHANNEL # LDX #OCOUNT LDA ,X++ GET BYTE COUNT, POINT AT DATA START TSTB BMI MDIO2 NEG. => FORCE OUT; NO STATUS CMPB #7 IS THIS A SYS-EX, OR SYS-COMMON? BLT MDIO6 BR. IF NOT STB STATLO STASH IN LOCAL STATUS BRA MDIO2 SKIP INITIAL PROTOCOL MDIO6 PSHS A STASH LDA CHONOW GET CHANNEL CMPA CHANLO IS IT THE SAME AS BEFORE?? BEQ MDIOX BR. IF IT'S THE SAME STA CHANLO REPLACE CHANNEL# PULS A RESTORE BRA MDIOY BR. MDIOX PULS A RESTORE CMPB STATLO STATUS SAME?? BEQ MDIO2 BR. IF YES MDIOY STB STATLO STATUS NEW; REPLACE CURRENT STATUS INCA INCREMENT OUTPUT COUNT LSLB SHIFT STATUS CODE UP 4 BITS LSLB LSLB LSLB ORB #$80 SET STATUS FLAG ORB CHONOW OR IN OUTPUT CHANNEL NO. STB ,-X STORE NEW STATUS FOR OUTPUT IN ODATSS MDIO2 LDY ADROUT GET CURRENT OUTPUT BUFFER ADR. MDIOR LDB ,X+ GET NEXT DATA BYTE STB ,Y+ PUT IT INTO OUTPUT BUFFER INC NWRITE INCREMENT # BYTES TO OUTPUT CMPY #ADOMAX AT TOP OF BUFFER?? BLE MDIO3 BR. IF NOT LDY #ADOBUF GET STARTING ADDR. OF OUTPUT BUFFER MDIO3 LDB #NBYOMX ARE WE STUCK?? CMPB NWRITE BNE MDIO4 BRA. IF OK BSR MDISWI TRY & JOG THINGS IF PROBLEM.... BRA MDIO3 WAIT, AND TRY AGAIN... MDIO4 DECA DECREMENT BYTE COUNT BNE MDIOR TAKE NEXT BYTES STY ADROUT STASH ADDRESS BACK MDISWI LDB ACIACR GET ACIA STATUS ANDB #2 CHECK XMIT BUSY & OUTPUT REG. FULL BEQ MDIO5 RETURN IF BUSY SWI JOG THE ACIA INTO ACTIVITY MDIO5 RTS RETURN.... * PAGE * ********************************************************************* * * * SUBROUTINE TO WAIT FOR KEYPAD INPUT * CHARACTER RETURNED IN REG. B * WTKEY CLR CHRFLG CLEAR CHARACTER FLAG CLR PNTFLG CLEAR CANCEL FLAG PSHS A,X,Y SAVE EVERYTHING CHRTST TST CHRFLG TEST FOR KEYPAD INPUT BEQ WTMIDI CHECK FOR MIDI LDB CHRBUF GET CHARACTER CMPB #PUNT IS IT CANCEL?? BNE CHRRTN INC PNTFLG SET PUNT FLAG CHRRTN CLR CHRFLG CLEAR CHARACTER FLAG PULS A,X,Y RESTORE EVERYTHING RTS RETURN.... * WTMIDI LDB ACRSAV GET ACIA STATUS ANDB #$70 CHECK FOR ERRORS BEQ WTMNE BR. IF OK LDX #ACIAEM CLRB LBSR PRTCHR PRINT ACIA ERROR MESSAGE WTMNE LDD NREADH CHECK MIDI READ BEQ WTCLR BR. IF NONE LBSR MIDIRD BR. TO READ ROUTINE WTCLR TST CLRFLG CLEAR QUEUED?? BEQ WTDLYO BR. IF NOT LBSR CLRART CLEAR ALL * WTDLYO TST ODLYON OUTPUT DELAY ON?? BEQ WTABAT BR. IF NOT TST NCTLTG HAS THE HOLD-2 CONTROLLER TRIGGERED? BNE WTDLY1 SKIP THE TIMER CHECK IF SO LDB TMROUT GET TIMER FLAGS ANDB #4 CHECK TMR3 BNE WTABAT BR. IF STILL UP WTDLY1 LDX #OUTLST POINT @ OUT-ON LISTS CLRA WTDL02 LDB A,X GET VALUE BLE WTDL01 BR. IF ALREADY ON OR NOT QUEUED PSHS A,B,X STASH POINTERS AND DATA LBSR OUTON1 TURN NOTE ON IF QUEUED PULS A,B,X RESTORE WTDL01 INCA NEXT BVC WTDL02 BR. IF MORE CLRA STA ODLYON CLEAR FLAG STA NONDLY CLEAR DELAYED COUNTER STA NCTLTG * WTABAT TST NTETRG RELEASE-ON SELECTED? BEQ WTABAQ BR. IF NOT TST NQUEQ NOTES QUEUED FOR RELEASE? BNE WTABAQ BR. IF YES TST NONOUT ANY NOTES ON? BEQ WTABAQ BR. IF NOT LDB TMROUT GET FLAGS ANDB #4 SELECT TMR#3 BNE WTABAQ WAIT FOR T3 TIMEOUT LBSR RSTRVR TURN NOTES OFF * WTABAQ TST ABEND AUTO-BEND SELECTED? BNE WTABT1 BR. IF SO TST ATRILL AUTO-TRILL SELECTED? BEQ CHRTST LOOP IF BOTH OFF * WTABT1 TST NDOWN ANY NOTES HELD DOWN (ON OB. SPAN)? BEQ WTNH1 BR. IF NO NOTE ON * TST LSTACT LAST ACTION? * BEQ WTNH1 BR. IF NO NOTE ON TST ABEND AUTO BEND ON? BEQ WTNH2 BR. IF NOT TST ABACTV AUTO BEND ACTIVE? BNE WTNH2 BR. IF SO TST MNHBND MIN-HOLD BND > 0 ?? BEQ WTNH2 BR. IF NOT TST ABTGED AUTO BEND ALREADY TRIGGERED? BNE WTNH2 BR. IF SO LDB TMROUT GET FLAGS ANDB #1 TIMER T1 CLEAR? BNE WTNH2 BR. IF NOT LDB TGMBND GET BEND TRIGGER MODE DECB BNE WTABTZ CONTINUE IF NOT SET TO QUEUE INC ABTGED SET BEND TRIGGER FLAG BRA WTNH2 CONTINUE; DON'T SETUP BEND HERE WTABTZ DECB BEQ WTNH2 DON'T SETUP HERE IF "CTLR" SELECTED LBSR ABSET BR. TO AUTO-BND SETUP * WTNH2 TST ATRILL AUTO TRILL ON? BEQ WTNH1 BR. IF NOT TST ATACTV AUTO TRILL ACTIVE? BNE WTNH1 BR. IF NOT TST MNHTRL MIN. HOLD TRILL > 0?? BEQ WTNH1 BR. IF NOT TST ATTGED AUTO TRILL ALREADY TRIGGERED? BNE WTNH1 BR. IF YES LDB TMROUT GET FLAGS ANDB #2 TIMER T2 CLEAR?? BNE WTNH1 BR. IF NOT LDB TGMTRL GET TRILL TRIGGER MODE DECB BNE WTATTZ BR. IF NOT SET TO QUEUE INC ATTGED SET TRILL TRIGGERED FLAG BRA WTNH1 DON'T SETUP HERE WTATTZ DECB BEQ WTNH1 DON'T SETUP HERE IF "CTLR" SELECTED LBSR ATSET BR. TO AUTO-TRILL SETUP * WTNH1 CLRA STA SHAPPP CLEAR SOMETHING-HAPPENED P STA SHAPPT CLEAR SOMETHING-HAPPENED T TST ABACTV AUTO BEND ACTIVE?? BEQ WTAB0 BR. IF NOT TST APBGO SATURATED? BNE WTAB0 IGNORE IF SO LDB TMROUT ANDB #1 T1 READY?? BNE WTAB0 BR. IF NOT LDD APBCNT GET PB INCR. ADDD APBOUT ADD INTO SUM WTPB1 STD APBOUT RESTORE CLR APBSGN CLEAR SIGN FACTOR TSTA BGE WTPB4 BR. IF + NEGA COMPLEMENT INC APBSGN SET FLAG WTPB4 CMPA MXBND > MAX?? BLT WTPBT BR. IF OK CLRB LDA MXBND GET MAX. WTPB5 TST APBSGN TEST SIGN BEQ WTPB6 BR. IF OK NEGA RE-COMPLIMENT LDB #$FF NEGATIVE NUMBER WTPB6 STD APBOUT @ MAX; SATURATE OUTPUT INC APBGO SET SAT. FLAG WTPBT LDB RTEBND GET BEND RATE INCB ZERO NOT ALLOWED STB TMR0 SET T1 CLRB STB TMR0 ZERO MSB INCB STB SHAPPP SET SOMETHING-HAPPENED FLAG * WTAB0 TST ATACTV AUTO-TRILL ACTIVE? BEQ WTBB0 BR. IF NOT LDB TMROUT GET FLAGS ANDB #2 CHECK T3 BNE WTBB0 BR. IF STILL UP LDB TRLSEL GET WAVE SELECT FLAG DECB LBEQ WTTG0 BR. IF TRIANGLE WAVE SELECTED LDA TRLSUM GET CURRENT SUM TST TRLLMT BR. IF TRILL SWING @ LIMIT BNE WTAB1 ADDA TRLCNT ADD IN 8-BIT INCR. BVC WTAB2 BR. IF NO OVERFLOW LDA #$3F SATURATED VALUE INC TRLLMT SET TRILL LIMIT FLAG WTAB2 CMPA MXTRL AT MAX?? BLT WTAB1 BR. IF OK LDA MXTRL LOAD MAXIMUM INC TRLLMT SET LIMIT FLAG WTAB1 STA TRLSUM STASH IT LDA TRLPOL GET POLARITY LDB TRLSGN SIGN FLIP? BEQ WTAB3 BR. IF NOT TST TRLSEL GET WAVE SELECT BNE WTAB11 BR. IF SWEEP TSTA TEST POLARITY BEQ WTAB12 BR. IF BIPOLAR CLRA MONOPOLAR; CLEAR TRILL OUTPUT ON NEG. SWING BRA WTAB9 WTAB12 LDA TRLSUM GET TRILL VALUE NEGA COMPL. BRA WTAB9 WTAB11 LDA TRLPOL GET POLARITY DECA BLE WTAB10 BR. IF BIPOLAR OR POSITIVE BRA WTAB12 BR. IF NEGATIVE WTAB3 DECA POSITIVE SWING; CHECK POLARITY BGT WTAB12 BR. TO COMPLIMENT IF NEGATIVE WTAB10 LDA TRLSUM GET TRILL VALUE WTAB9 STA TRLOUT STASH WTABR EORB #1 TOGGLE SIGN STB TRLSGN REPLACE BNE WTAB4 BR. IF SIGN FLIPPED TO NEG. LDD ATRATE GET POSITIVE TRL. RATE BRA WTAB5 WTAB4 LDD ATRTED LOAD NEG. TRL. RATE WTAB5 STB TMR1 STORE LSB STA TMR1 STORE MSB INC SHAPPT INC. SOMETHING-HAPPENED FLAG * WTBB0 CLRB LDA OCLBND GET BEND OUTPUT CTLR. BEQ WTAB6 BR. IF NO OUTPUT CMPA #3 TURNED OFF? BEQ WTAB6 BR. IF SO INCB SET FLAG FOR BEND CTLR ON ANDB ABEND MASK BY BEND ENABLE WTAB6 STB BCTOFF SAVE FLAG CLRB LDA OCLTRL GET TRILL OUTPUT CTLR. BEQ WTAB7 BR. IF NO OUTPUT CMPA #3 TURNED OFF? BEQ WTAB7 BR IF SO INCB SET FLAG FOR TRILL CTLR ON ANDB ATRILL MASK BY TRILL ENABLE WTAB7 STB TCTOFF SAVE FLAG * TST SHAPPP SOMETHING-HAPPENED-P?? BEQ WTBB1 BR. IF NOT TST BCTOFF TEST OUTPUT SELECT BEQ WTBB1 BR. IF OUTPUT NOT ENABLED LDA CTLBND LOAD BEND CONTROLLER TST TCTOFF TEST TRILL SELECT BEQ WTBBA IGNORE TEST IF UNSELECTED CMPA CTLTRL PB-CTL. = TRL CTL? BEQ WTBB1 BR. OUT IF SO WTBBA LBSR BTOUTP SHIP OUT PB RESULT * WTBB1 TST SHAPPT SOMETHING-HAPPENED-T?? BEQ WTBB2 BR. IF NOT TST TCTOFF BEQ WTBB2 BR. OUT IF OUTPUT OFF LDA CTLTRL TST BCTOFF BEQ WTBBB IGNORE TEST IF BEND OFF CMPA CTLBND TRL CTL = PB CTL? BEQ WTBB2 BR. IF YES WTBBB LBSR BOUTT SHIP OUT TRL RESULT * WTBB2 LDA SHAPPP ORA SHAPPT LBEQ CHRTST CONTINUE WAIT IF NOTHING HAPPENED LDB CTLBND GET BND. CTL CMPB CTLTRL BNE WTBB4 BR. IF PB-CTL NE. BND CTL LDA BCTOFF ANDA TCTOFF BEQ WTBB4 SKIP IF OUT OFF FOR EITHER EFFECT CLRA CLRB CLEAR D STB OPBFLG TST BCTOFF BEQ WTBBX BR. IF OUT-BND OFF TST ABACTV ABEND WORKING? BEQ WTBBX SKIP IF NOT LDD APBOUT GET A-BND RESULT INC OPBFLG WTBBX TST TCTOFF BEQ WTBBY BR. IF OUT-TRL OFF TST ATACTV ATRILL WORKING? BEQ WTBBY SKIP IF NOT ADDA TRLOUT ADD TRL. SUM WTBBY STD PBSMQT STASH RESULT LDA CTLBND GET COMMON CONTROLLER BNE WTBB6 BR. IF NOT PB LDD PBSMQT GET RESULT LBSR BTOPQ SHIP IT OUT BRA WTBB4 WTBB6 LDB PBSMQT TAKE HIGH BYTE- NOT PB. * TST OPBFLG ** PRESENT DEFAULT IS TO USE TRILL CODE IF BOTH SAME CTLR. * BNE WTBBF * LBSR BTOQ1 * BRA WTBB4 WTBBF LBSR BTOC1 PUT RESULT OUT * WTBB4 LDB OCLBND GET BND OUTPUT ANDB #1 LOOK @ 1'ST BIT BEQ WTBB7 BR. IF 4V SELECTED LDB OCLTRL GET TRL OUTPUT ANDB #1 LOOK AT 1'ST BIT BNE WTBTV0 BR. IF OUT ONLY WTBB7 CLRB CLRA STD PBSMQT CLEAR PB SUM TST ABACTV BEND WORKING? BEQ WTBB8 BR. IF NOT LDA OCLBND BEND ON 4V? ANDA #1 BNE WTBB8 BR. IF NOT LDD APBOUT GET PB. OUTPUT STD PBSMQT STASH BEND VAL. IN SUM WTBB8 TST ATACTV TRILL WORKING? BEQ WTBB9 LDA OCLTRL TRILL ON 4V?? ANDA #1 BNE WTBB9 BR. IF NOT LDD PBSMQT ADDA TRLOUT ADD IN TRILL SUM STD PBSMQT STASH WTBB9 LDD PBSMQT ADDD #PBOFF ADD PB OFFSET TO INC BPL WTBB10 BR. IF OK TST PBSMQT CHECK SUM BLT WTBB11 BR. IF OVF. - LDA #$FF TFR A,B SAT + BRA WTBB10 BR. OUT WTBB11 CLRA CLRB SAT - WTBB10 LSRB SKIP BLANK BIT STD PBHI WRITE OB. PB REGISTER * *CLIPIT TSTA CHECK SUM * BPL WTBBRY RETURN IF OK * TST TRLOUT CHECK INCREMENT * BMI WTBBZ BR. IF NEG. * LDA #$FF SATURATE + * TFR A,B * LSRA CLIP SIGN *WTBBRY RTS RETURN *WTBBZ CLRA * CLRB * RTS * * ROUTINE TO CROSSFEED BEND/TRILL TO TVB * WTBTV0 LDD #0 CLEAR ACCUMULATORS STD VCFB00 STD VOLB00 STD BALB00 STD BASB00 STD TRBB00 STA VCFTGG CLEAR TRIGGERS STA VOLTGG STA BALTGG STA BASTGG STA TRBTGG * TST ABACTV AUTO BEND EVENT? BEQ WTBTV1 BR. IF NOT LDB APBOUT GET BEND OUTPUT BPL WTVBX NEGB TAKE ABSOLUTE VALUE INCA SET SIGN FLAG WTVBX STB PBSLOC STASH LOCALLY STA TSSGN STASH SIGN FLAG * LDA VCFBND ANY BEND INTO VCF? BEQ WTVB1 BR. IF NOT LBSR TSTSGN GET AMOUNT STD VCFB00 STASH INC VCFTGG SET FLAG WTVB1 LDA VOLBND ANY BEND INTO VOLUME? BEQ WTVB2 BR. IF NOT LBSR TSTSGN GET AMOUNT STD VOLB00 STASH INC VOLTGG SET FLAG WTVB2 LDA BALBND ANY BEND INTO BALANCE? BEQ WTVB3 BR. IF NOT LBSR TSTSGN GET AMOUNT STD BALB00 STASH INC BALTGG SET FLAG WTVB3 LDA BASBND ANY BEND INTO BASS? BEQ WTVB4 BR. IF NOT LBSR TSTSGN GET AMOUNT STD BASB00 STASH INC BASTGG SET FLAG WTVB4 LDA TRBBND ANY BEND INTO TREBLE? BEQ WTBTV1 BR. IF NOT LBSR TSTSGN GET AMOUNT STD TRBB00 STASH INC TRBTGG SET FLAG * WTBTV1 TST ATACTV ANYTHING HAPPEN W. TRILL? BEQ WTBTV3 BR. IF NOT CLRA LDB TRLOUT GET TRILL VALUE BPL WTBVY BR. IF PLUS NEGB TAKE ABSOLUTE VAL. INCA SET SIGN FLAG WTBVY STA TSSGN STASH SIGN FLAG STB PBSLOC STASH VALUE * LDA VCFTRL ANY TRILL INTO VCF? BEQ WTVT1 BR. IF NOT LBSR TSTSGN GET AMOUNT ADDD VCFB00 ADD IN OFFSET STD VCFB00 STASH INC VCFTGG SET FLAG WTVT1 LDA VOLTRL ANY TRILL INTO VOLUME? BEQ WTVT2 BR. IF NOT LBSR TSTSGN GET AMOUNT ADDD VOLB00 ADD IN OFFSET STD VOLB00 STASH INC VOLTGG SET FLAG WTVT2 LDA BALTRL ANY TRILL INTO BALANCE? BEQ WTVT3 BR. IF NOT BSR TSTSGN GET AMOUNT ADDD BALB00 ADD IN OFFSET STD BALB00 STASH INC BALTGG SET FLAG WTVT3 LDA BASTRL ANY TRILL INTO BASS? BEQ WTVT4 BR. IF NOT BSR TSTSGN GET AMOUNT ADDD BASB00 ADD IN OFFSET STD BASB00 STASH INC BASTGG SET FLAG WTVT4 LDA TRBTRL ANY TRILL INTO TREBLE? BEQ WTBTV3 BR. IF NOT BSR TSTSGN GET AMOUNT ADDD TRBB00 ADD IN OFFSET STD TRBB00 STASH INC TRBTGG SET FLAG * WTBTV3 TST VCFTGG ANY ACTION ON VCF?? BEQ WTV01 BR. IF NOT LDX VCFB00 GET RESULT CLRB CLEAR BIAS BSR ADBIN ADD IN BIAS STB VCFMOD SHIP OUT WTV01 TST VOLTGG ANY ACTION ON VOLUME?? BEQ WTV02 BR. IF NOT LDX VOLB00 GET RESULT LDB LOCVOL GET BIAS BSR ADBIN ADD IN BIAS STB OUTVOL SHIP OUT WTV02 TST BALTGG ANY ACTION ON BALANCE?? BEQ WTV03 BR. IF NOT LDX BALB00 GET RESULT LDB LOCBAL GET BIAS BSR ADBIN ADD IN BIAS STB OUTBAL SHIP OUT WTV03 TST BASTGG ANY ACTION ON BASS?? BEQ WTV04 BR. IF NOT LDX BASB00 GET RESULT LDB LOCBAS GET BIAS BSR ADBIN ADD IN BIAS STB OUTBAS SHIP OUT WTV04 TST TRBTGG ANY ACTION ON TREBLE?? BEQ WTBTV2 BR. IF NOT LDX TRBB00 GET RESULT LDB LOCTRB GET BIAS BSR ADBIN ADD IN BIAS STB OUTTRB SHIP OUT * WTBTV2 LBRA CHRTST CONTINUE TO WAIT FOR EVENT..... * ACIAEM FDB 12 FCC /ACIA ERROR!!/ * * SCALE BEND OR TRILL BY FEED AMOUNT & MAKE DOUBLEWORD * TSTSGN LDB PBSLOC GET TRILL OR BEND VALUE LSLB LSLB SCALE FOR 8 BITS MUL SCALE VALUE BY FEED AMOUNT EXG A,B RESULT IN B; CHECK SIGN FOR A LDA TSSGN SIGN? BEQ TSTSG1 BR. IF POSITIVE LDA #$FF SET NEGATIVE NEGB FLIP SIGN OF RESULT TSTSG1 RTS BYE BYE * * ADD NEW RESULT INTO DOUBLEWORD SUM, AND SATURATE * ADBIN ABX ADD IT IN TFR X,D PUT IT IN THE D REGISTER TSTA TEST HIGH BYTE BPL ADBIN1 BR. IF POSITIVE CLRB NEGATIVE; SATURATE ZERO ADBIN2 RTS RETURN ADBIN1 BEQ ADBIN2 BR. IF HIGH BYTE CLEAR LDB #$FF SATURATE AT 8 BITS RTS * * TRIANGLE WAVE TRILL CODE * WTTG0 LDB TRLCNT GET COUNT TST TGLSGN TEST THE TRIANGLE SIGN BEQ WTTG1 BR. IF POSITIVE SLOPE NEGB SUBTRACT THE CONTRIBUTION WTTG1 ADDB TRLSUM ADD IT IN LDA TRLPOL CHECK POLARITY BNE WTTG2 BR. IF NOT BIPOLAR TFR B,A COPY RUNNING TRILL SUM CLR TSSGN CLEAR FLAG TSTA POSITIVE? BPL WTTG3 THEN BR. NEGA TAKE ABS. VAL. INC TSSGN SET FLAG WTTG3 CMPA MXTRL OVER MAX SWING? BLT WTTG4 BR. IF NOT LDB TGLSGN GET TRIANGLE SLOPE EORB #1 FLIP IT STB TGLSGN REPLACE LDB MXTRL SATURATE IT TST TSSGN CHECK THE SIGN BEQ WTTG4 BR. IF PLUS NEGB FLIP IT WTTG4 STB TRLSUM STASH STB TRLOUT OUTPUT... LDB TRLSGN GET TRILL SIGN LBRA WTABR CONTINUE IN TRILL CODE * WTTG2 DECA UNIPOLAR TRIANGLE; CHECK POLARITY SIGN BNE WTTG5 TRILL DOWN => BR. TSTB TRILL UP HERE BGT WTTG6 RESULT OVER ZERO, THEN BR. CLRB SATURATE AT ZERO CLR TGLSGN FLIP THE SLOPE POSITIVE BRA WTTG4 STASH & CONTINUE WTTG6 CMPB MXTRL OVER TOP? BLT WTTG4 BR. IF OK LDB MXTRL SATURATE AT MAX INC TGLSGN FLIP THE SLOPE NEGATIVE BRA WTTG4 STASH & CONTINUE WTTG5 TSTB TRILL DOWN HERE BMI WTTG7 BR. IF BELOW ZERO CLRB SATURATE AT ZERO INC TGLSGN FLIP THE SLOPE NEGATIVE BRA WTTG4 STASH & CONTINUE WTTG7 TFR B,A COPY THE RESULT FOR TESTS NEGA ABSOLUTE VALUE CMPA MXTRL OVER TOP? BLT WTTG4 BR. IF OK LDB MXTRL SATURATE AT PEAK NEGB COMPLIMENT FOR NEGATIVE SWING CLR TGLSGN FLIP SLOPE POSITIVE BRA WTTG4 STASH & CONTINUE * * PICK UP PB DOUBLE WORD AND SEND OUT * BTOUTP TSTA CHECK CONTROLLER BNE BTOP1 BR. IF NOT PB LDD APBOUT GET PB WORD BTOPQ STA BSTMP STORE MSB LOCALLY ADDD #PBNULL MAKE INTO PB WORD BPL BTOPQ1 BR. IF OK TST BSTMP TEST OLD MSB BMI BTOPQ2 BR. IF MINUS LDA #$FF SATURATE PLUS TFR A,B LSRA MAKE PLUS BRA BTOPQ1 CONTINUE BTOPQ2 CLRA CLRB BTOPQ1 LSRB INSURE STATUS LBRA PBSOUT SEND DATA OUT * BTOP1 PSHU A LDB IVLBND GET INITIAL VALUE LSRB CORRECT FOR BELOW SHIFT STB SVPQ STASH LDD APBOUT GET PB WORD ADDA SVPQ ADD IN INITIAL VALUE LSLB ADD ANOTHER BIT FOR BETTER RES. ROLA TFR A,B PULU A TSTB WHAT WAS THE SIGN? BPL BTOQ1 BR. IF POSITIVE; OVERFLOW IF NOT TST APBOUT BPL BTOPX1 BR. IF POS.; NO OVERFLOW CLRA SATURATE NEGATIVE BRA BTOQ1 BTOPX1 LDA #$7F SATURATE POSITIVE BTOQ1 ANDB #$7F CLEAR HIGH BIT STD ODATAS SHIP IT OUT LDB #2 STB OCOUNT COUNT... LDB #MCTLCH GET CTL. CHANGE CODE LDA CHNL1 GET OUTPUT CHANNEL LBRA MDIOUT SHIP OUT * * PICK UP TRILL WORD AND SEND TO OUTPUT * BOUTT TSTA BNE BTOT1 BR. IF NOT PB CLRB LDA TRLOUT GET DATA BGE BTOPQ BR. IF OK LDB #$FF SET NEGATIVE BRA BTOPQ BTOT1 LDB TRLOUT GET DATA; CONTROLLER SEND BTOC1 PSHS A STASH CLTR# STB CTRQ1 STASH ARGUMENT LDA IVLTRL GET OFFSET LSRA CORRECT FOR BELOW SHIFT STA SVPQ STASH ADDB SVPQ ADD IN OFFSET PULS A RESTORE CTLR# LSLB SCALE UP FOR CONTROLLER TSTB BPL BTOQ1 BR. IF NO OVERFLOW TST CTRQ1 WAS ORIG. NEG? BPL BTOTX1 BR. IF POSITIVE INCREMENT * NEGB TAKE ABS. VALUE CLRB SATURATE AT ZERO BRA BTOQ1 BTOTX1 LDB #$7F SATURATE POSITIVE BRA BTOQ1 * PAGE * * AUTO BEND SETUP * ABSET TST ABEND BEQ ABOK4 RETURN IF A-BND OFF LDB LSTVEL GET LAST VEL. LDA RVSBND GET BEND VEL-SENS. TST RVSSNB TEST INVERT FLAG BNE ABSS1 BR. IF NOT + NEGB ADDB #127 ABSS1 LSLB MUL SCALE 'EM ADDA SBBND ADD SWEEP BIAS BCC ABOK1 BR. IF NO OVERFLOW LDA #$FF SAT. + ABOK1 TST BARDIR CHECK DIR. FLAG BEQ ABOK5 BR. IF ATK. LDB LSTVEL GET RLS BRA ABOK6 ABOK5 LDB LSTAVL ABOK6 SUBB RVDRBD GET VEL - VEL DIR. BGT ABOK2 BR. IF + BSR SHFT4 SHIFT A-REG. LEFT 4 PLACES COMA TAKE 2'S COMP. OF D COMB ADDB #1 ADCA #0 BRA ABOK3 ABOK2 BSR SHFT4 SHIFT A ABOK3 STD APBCNT STASH COUNT CLRA CLRB STD APBOUT CLEAR OUTPUT WORD STA APBGO CLEAR OVERFLOW FLAG INCA STA ABACTV SET ACTIVE FLAG STA TMR0 CLEAR OUT TIMER STB TMR0 DECB STB ABTGED MAKE THIS NEGATIVE ABOK4 RTS * * ROUTINE TO SHIFT A IN D BY 4 BITS * SHFT4 TFR A,B PUT IN LSB CLRA CLEAR HIGH BYTE LSLB SHIFT 4 TIMES ROLA LSLB ROLA LSLB ROLA LSLB ROLA RTS * * SETUP FOR AUTO TRILL * ATSET TST ATRILL BEQ ATOK1 PUNT IF OFF * -INCR.- LDA LSTVEL GET LAST (RLS.) VEL. ATOK3 LDB RVSTRL GET RVEL. SCALE TST RVSSNT TEST SENSE BNE ATSS1 BR. IF NOT INVERTED NEGA ADDA #127 ATSS1 LSLA MUL SCALE 'EM ADDA SBTRL ADD SWEEP BIAS BNE ATOK7 INCA KEEP AT LEAST ONE BRA ATOK4 ATOK7 BPL ATOK4 BR. IF NO OVF. LDA #$7F SAT. PLUS ATOK4 STA TRLCNT STASH * - RATE - LDA LSTAVL GET LAST AVEL LDB AVSTRL GET AVEL SCALE TST TARDIR TEST TRILL DIR. BEQ ATSS2 NEGA ADDA #127 ATSS2 LSLA MUL SCALE 'EM UP STA TSSGNV STASH FOR NOW ADDA RTBTRL ADD IN RATE BIAS BCC ATOK5 BR. IF NO OVF. LDA #$FF SATURATE + ATOK5 TFR A,B PUT INTO LSB CLRA LSLB ROLA SHIFT LEFT ONE PLACE STD ATRATE STASH TRILL RATE BNE ATOK8 BR. IF OK LDB #8 GET MINIMAL VALUE STB ATRATE+1 BOOST LSB * ATOK8 TST PWTRLL CHECK PW BEQ ATOK6 BR. IF NO DUTY FACTOR SELECTED LDA PWTRLL GET THE ALTERNATE SIGN PW ADDA TSSGNV ADD IN THE VELOCITY BIAS BCC ATOKC BR. IF NO OVF. LDA #$FF SATURATE + ATOKC TFR A,B PUT INTO LSB CLRA LSLB ROLA SHIFT LEFT ONE PLACE ATOK6 STD ATRTED BNE ATOKD BR. IF OK LDB #8 GET MINIMAL VALUE STB ATRTED+1 BOOST LSB * ATOKD CLRA STA TRLLMT CLEAR TRL. LIMIT FLAG STA TRLSUM CLEAR TRL. SUM STA TRLSGN CLEAR TRL. SIGN STA TGLSGN CLEAR TRIANGLE SLOPE INCA STA ATACTV SET TRL. ACTIVE STA TMR1 CLRA STA TMR1 CLEAR OUT TIMER DECA STA ATTGED MAKE TRIGGER NEGATIVE * ATOK1 RTS * PAGE * * MIDI SERVICE & COORDINATION ROUTINES * * - GET DATA & HANDLE BUFFER - * MIDIRD LDX ADRIN GET NEXT ADDR. LDA ,X+ GET DATA, INC. POINTER CMPX #ADIMAX @ MAX??? BLE MIDI01 NO, BR... LDX #ADIBUF RESET POINTER MIDI01 STX ADRIN RESTORE POINTER ORCC #$40 INHIBIT FIRQ LDB NREAD GET # READ BNE MIDI02 BR. IF OK DEC NREADH CORRECT HIGH BYTE MIDI02 DECB DEC. LOW BYTE STB NREAD RESTORE ANDCC #$BF ENABLE FIRQ AGAIN * * - CHECK DATA - * TSTA BPL MIDI03 BR. IF NOT A STATUS LDB LSTAT STB OLDSTT RESET OLD STATUS TFR A,B COPY DATA LSLB KNOCK OFF SIGN LSRB GET STAT. LSRB LSRB LSRB LSRB STB LSTAT STORE LAST STAT. CMPB #$7 BNE MIDI04 BR. IF NOT RT/SE BITA #8 IS IT RT?? BEQ MIDI05 BR. IF NOT STA ODATAS SHIP OUT IMMEDIATELY LDB #1 STB OCOUNT STASH COUNT LDB #-1 LOAD NEG. NO. LDA MCHL LOAD CH. LBSR MDIOUT MIDI OUTPUT LDB OLDSTT STB LSTAT RESTORE STATUS RTS RETURN... MIDI05 CMPA #$F0 IS IT SYS-EX START? BNE MIDI06 BR. IF NOT LDB #8 LOAD START-EX CODE BRA MIDI07 MIDI06 CMPA #$F7 END OF SYS-EX?? BNE MIDI08 SYS-COMMON; GIVE UP LDB #9 LOAD SYS-EX END CODE MIDI07 STB OBSTAT STASH LOCAL CODE... MIDIXX STB STAOUT STASH LOCAL STATUS CODE STA ODATAS STASH BYTE FOR OUT LDA #1 STA OCOUNT ONE BYTE FOR OUT LDA CHNL1 LOAD OUTPUT CHANNEL STA MCHL STASH AS CURRENT CHANNEL (FOR KICKS) LBSR MDIOUT SHIP IT CLRA STA MPHASE CLEAR PHASE STA MSYEX CLEAR SYSEX COUNTER LDB OBSTAT CMPB #9 IS IT SYS-EX OFF? LBEQ QSXOFF BR. IF SO STA MEX ZERO SYSEX FLAG RTS MIDI08 LDB #7 SYS COMMON CODE BRA MIDI07 SHIP IT * * NOT RT/SE/ SC * MIDI04 TFR A,B STASH ANDB #$F GET CHANNEL NO. STB MCHL STASH IN CURRENT VAL. CLR MPHASE CLEAR OUT PHASE TST OMNIFG OMNI MODE?? BNE MIDI09 ACCEPT CMD IF SO CMPB CHNL0 IS IT FOR OB CHL?? BNE MIDI10 BR. IF NOT MIDI09 LDB LSTAT GET LAST STAT. MIDI11 STB OBSTAT STORE COMMAND LOCALLY RTS RETURN MIDI10 LDB #10 GET WRONG CHL. CODE BRA MIDI11 * * NON-STATUS DATA * MIDI03 PSHS A SAVE MIDI BYTE LDB OBSTAT GET OB STATUS LSLB CORRECT FOR ADDR. TABLE LDX #MIDIAA GET ADDR. TABLE START LDY B,X POINT AT ROUTINE JSR ,Y JUMP TO IT LDB #1 EORB MPHASE STB MPHASE STEP PHASE BIT LDA LSTAT LDX #NAGLST LEAY A,X LDA ,Y PICK UP ARG. COUNTER STA MIDICB BNE MIDIZ1 BR. TO OUT. IF 2-BYTES EXPECTED MIDIZ2 INCA INC. BYTE COUNT STA OCOUNT STORE ABOVE BRA MIDIXQ CONTINUE MIDIZ1 TSTB TEST PHASE BEQ MIDIZ2 BR. IF READY FOR OUTPUT PULS A RESTORE MIDI DATA STA MDILBF STORE IN TEMP. BUFFER RTS NAGLST FCB 1 FCB 1 FCB 1 FCB 1 FCB 0 FCB 0 FCB 1 FCB 0 * MIDIXQ PULS A RESTORE MIDI BYTE LDB LSTAT GET LAST STAT. CMPB #MPBND PB? BNE MIDINN BR. IF NOT TST SNDPB TEST XMIT PB BEQ MIDIRR BR. IF OFF MIDINN LDB MCHL STB MCHLX START WITH ORIGINAL CHL. FOR OUT LDB XMITMD CHECK XMIT CMPB #3 ALL MODE? BEQ MIDI12 BR. IF YES LDB LSTAT CMPB #MPCHG ALWAYS SEND PRG. CHG. UNDER OFF BEQ MIDI12 CMPB #MRTIME COULD IT HAVE BEEN A SYEX?? BNE MIDI12X LDB OBSTAT GET CODE CMPB #8 SYSEX BEQ MIDI12 MIDI12X LDB XMITMD OFF?? BEQ MIDIRR CMPB #2 RE-CHANNELIZE OPTION? BNE MIDINM NO; MUST BE "ONLY" OPTION LDB MCHL CMPB CHNL0 BNE MIDINM ONLY RE-CHANNEL MESSAGES FOR CHNL0 LDB LSTAT CHECK CURRENT STATUS DECB BLE MIDIRR IGNORE NTE-ON/NTE-OFF LDB CHNL1 STB MCHLX RE-CHANNELIZE BRA MIDI12 SHIP OUT MIDINM LDB MCHL GET OUT CHL. CMPB CHNL1 COMP. TO ASSIGNED BNE MIDIRR EXIT IF NOT IN AGREEMENT MIDI12 LDX #ODATAS TST MIDICB 2 BYTES? BEQ MIDI13 BR. IF NOT LDB MDILBF GET BUFFER STB ,X+ STASH IN BUFFER MIDI13 STA ,X STASH CURRENT BYTE LDA MCHLX GET CURRENT CHL. LDB LSTAT GET CURRENT STAT. LBSR MDIOUT SHIP A BYTE OR TWO OUT MIDIRR RTS * MIDIAA FDB QNOFF NTE OFF FDB QNON NTE ON FDB QDUMMY POLY PRES. FDB QCTLCH CTL. CHG. FDB QPGMCH PGM. CHG. FDB QDUMMY CHL. PRES. FDB QPBEND PB CHG. FDB QDUMMY SYS COMMON FDB QSXON SYSEX ON FDB QDUMMY SYSEX OFF FDB QDUMMY OTHER CHANNEL * * DUMMY RETURN * QDUMMY RTS * * NTE OFF * QNOFF TST MPHASE BEQ QNOBB1 BR. IF COMMAND NOT COMPLETED TSTA BNE QNOFF2 QNOFF3 LDA #64 GIVE HALF-RVEL IF ZERO QNOFF2 STA LSTRVL STORE VEL. STA LSTVEL LDA LSTNBF GET FORMER NTE LDB OMNIFG CMPB #3 ARE WE IN MULTI MODE? LBNE HNOFF IGNORE CHECK IF SO; TURN NTE OFF BSR CHKHLF CHECK KEY HALF/CHL.# TSTA REJECT? LBPL HNOFF TURN NTE. OFF IF NOT RTS * QNOBB1 STA LSTNBF FILE NTE FOR LATER RTS * CHKHLF LDB MCHL ROUTINE TO CHECK CHL. ON MULTI SUBB CHNL0 IS IT THE BASE? BNE CHCHL1 IGNORE IF NOT TFR A,B SUBB TRNPSE BMI CHCRJ SKIP IF OVF. CMPB #HLFNTE BGT CHCRJ SKIP IF IN TOP HALF CHCOK RTS CHCHL1 DECB IS IT ONE OVER THE BASE? BNE CHCRJ REJECT IF NOT ADDA #HLFNTE+1 ADD UP INTO TOP HALF BVC CHCOK BR. IF NOT OVERFLOWED CHCRJ LDA #-1 REJECT CODE RTS * * NTE ON * QNON TST MPHASE BEQ QNOBB1 BR. IF COMMAND NOT COMPLETED STA LSTAVL STORE AS LAST VEL BEQ QNOFF3 BR. IF NTE OFF STA LSTVEL BSR NTLOOK CHECK FOR NOTE-ON TRIGGERING FUNCTIONS LDA LSTNBF GET FORMER NTE LDB OMNIFG CMPB #3 ARE WE MULTI MODE? BEQ QNON1 BR. IF SO LBSR HNON IGNORE CHECK IF NOT BRA QNON2 QNON1 BSR CHKHLF DO THE CHECK TSTA BMI QNON2 BR. IF NOT OK LBSR HNON TURN NTE ON IF OK QNON2 TST TRKBND WAS THERE A BEND TRIGGER KEY HIT? BEQ QNON3 BR. IF NO LBSR QCTLSB SET THE BEND QNON3 TST TRKTRL WAS THERE A TRILL TRIGGER KEY HIT? LBNE QCTLST BR. IF SO RTS * * CHECK NOTE HIT FOR TRIGGERS & EFFECTS * NTLOOK TST LDNOTE ARE WE IN THE BUFFER-LOAD MODE? BEQ NTLK00 BR. IF NO TST KYSAFE SAFETY ON?? BEQ NTLK0A NO, SKIP THE CHECK TST SAFEFG SOFT PEDAL DOWN? BEQ NTLK0B BR. IF NO NTLK0A LDA NBUFKY NOTE BUFFER TRIGGER? BEQ NTLK0B BR. IF NOT ENABLED DECA CORRECT FOR OFFSET CMPA LSTNBF IS THIS THE NOTE? BEQ NTLK00 BR. IF YES; DON'T RECORD IT NTLK0B LDA LSTNBF GET THE LAST NOTE LDB NONTE GET THE NOTE BUFFER INDEX INCB INCREMENT CMPB #125 AT MAXIMUM? BLE NTLKVV BR. IF NO TABLE FULL * CLR LDNOTE CLEAR BUFFER LOAD FLAG; TABLE FULL BRA NTLK00 CONTINUE... NTLKVV LDX #NTETAB STA B,X STORE THE NOTE IN THE TABLE STB NONTE * NTLK00 TST KYSAFE SAFETY ON?? BEQ NTLK01 NO, SKIP THE CHECK TST SAFEFG SOFT PEDAL DOWN? BEQ NTLK02 BR. IF NO NTLK01 LDA NBUFKY NOTE BUFFER TRIGGER? BEQ NTLK02 BR. IF NOT ENABLED DECA CORRECT FOR OFFSET CMPA LSTNBF IS THIS THE NOTE? BNE NTLK02 BR. IF NOT CLRB STB OVIND CLEAR INDEX STB OVDIR CLEAR DIRECTION LDB LDNOTE GET LOAD TRIGGER EORB #1 TOGGLE IT STB LDNOTE REPLACE BEQ NTLK02 BR. IF CLEARED LDB #-1 LOAD RESET CODE STB NONTE RESET COUNTER * NTLK02 TST APMNTO AUTO PORT. ON? BEQ NTLK2A CONTINUE IF NOT LDA LSTVEL GET LAST VEL. TST AVSAPT SIGN?? BNE OBNN03 BR. IF + NEGA ADDA #127 REVERSE VEL OBNN03 LDB AVPMPT GET VEL. SCALE LSLA MUL TSTA BMI OBNN02 BR. IF OVF. CMPA #63 BLE OBNN04 BR. IF NO OVF. OBNN02 LDA #63 SATURATE + OBNN04 STA PORTBF STASH TST SENDMD SEND ACTIVE? BEQ NTLK2A SKIP OUT IF NOT LDA APTDST CHECK DESTINATION FLAG BEQ NTLK2A SKIP IF 4V ONLY CMPA #3 BEQ NTLK2A SKIP IF OFF LDA #2 STA OCOUNT 2 BYTES TST PORTON HAS THE PORT. BEEN TURNED OFF? BNE NTLK2B BR. IF NOT LDA #65 GET PORT ON/OFF CODE STA ODATAS LDB #$7F ON CODE STB ODATAS+1 STB PORTON SET INTERNAL FLAG LDA CHNL1 LDB #MCTLCH LBSR MDIOUT SEND PORT ON NTLK2B LDA #5 PORT. TIME CODE STA ODATAS LDA PORTBF GET DATA LSLA CORRECT FOR 7-BIT STA ODATAS+1 LDA CHNL1 LDB #MCTLCH LBSR MDIOUT SEND PORT TIME * NTLK2A LDB #1 INITIALIZE TRIGGER CLR TRKBND CLEAR TRIGGER FLAG LDA TKYBND GET TRIGGER KEY BEQ NTLK03 BR. IF NONE SET DECA CORRECT FOR OFFSET CMPA LSTNBF IS THIS THE NOTE? BNE NTLK03 BR. IF NO TST KYSAFE IS THE SAFETY ON? BEQ NTLK3A BR. IF NOT TST SAFEFG IS THE PEDAL DOWN? BEQ NTLK03 BR. IF NOT NTLK3A STB TRKBND SET TRIGGER NTLK03 CLR TRKTRL RESET TRILL TRIGGER LDA TKYTRL GET TRIGGER KEY BEQ NTLK04 BR. IF NONE SET DECA CORRECT FOR OFFSET CMPA LSTNBF IS THIS THE NOTE? BNE NTLK04 BR. IF NO TST KYSAFE IS THE SAFETY ON? BEQ NTLK4A BR. IF NOT TST SAFEFG IS THE PEDAL DOWN? BEQ NTLK04 BR. IF NOT NTLK4A STB TRKTRL SET TRIGGER * NTLK04 LDA TVBVOL LDB VOLSNS GET VOLUME VEL. SENSITIVITY BEQ NTLK06 BR. IF NONE LDA LSTVEL GET NOTE VELOCITY LSLB LSLA CORRECT FOR 7 BITS MUL SCALE ADDA TVBVOL ADD IN OFFSET BCC NTLK06 BR. IF NO OVERFLOW LDA #$FF SATURATE POSITIVE NTLK06 STA OUTVOL WRITE TVB STA LOCVOL STORE LOCALLY * NTLK05 LDA TVBBAL LDB BALSNS GET BALANCE VEL. SENSITIVITY BEQ NTLK08 BR. IF NONE LDA LSTVEL GET NOTE VELOCITY LSLB LSLA CORRECT FOR 7 BITS MUL SCALE ADDA TVBBAL ADD IN OFFSET BCC NTLK08 BR. IF NO OVERFLOW LDA #$FF SATURATE POSITIVE NTLK08 STA OUTBAL WRITE TVB STA LOCBAL STORE LOCALLY * NTLK07 LDA TVBBAS LDB BASSNS GET BASS VEL. SENSITIVITY BEQ NTLK10 BR. IF NONE LDA LSTVEL GET NOTE VELOCITY LSLB LSLA CORRECT FOR 7 BITS MUL SCALE ADDA TVBBAS ADD IN OFFSET BCC NTLK10 BR. IF NO OVERFLOW LDA #$FF SATURATE POSITIVE NTLK10 STA OUTBAS WRITE TVB STA LOCBAS STORE LOCALLY * NTLK09 LDA TVBTRB LDB TRBSNS GET TREBLE VEL. SENSITIVITY BEQ NTLK12 BR. IF NONE LDA LSTVEL GET NOTE VELOCITY LSLB LSLA CORRECT FOR 7 BITS MUL SCALE ADDA TVBTRB ADD IN OFFSET BCC NTLK12 BR. IF NO OVERFLOW LDA #$FF SATURATE POSITIVE NTLK12 STA OUTTRB WRITE TVB STA LOCTRB STORE LOCALLY * NTLK11 RTS RETURN... * * PBEND * QPBEND TST MPHASE BNE QPB1 BR. IF COMMAND COMPLETE STA PBLSB STORE HALF RESULT RTS QPB1 LDB OMNIFG CMPB #2 ARE WE IN X-CONTROLLERS OMNI MODE? BLT QPB3 IGNORE CHANNEL TEST IF NOT LDB MCHL GET CURRENT CHANNEL CMPB CHNL0 IS IT FOR US?? BNE QPB2 SKIP IF NOT QPB3 LDB PBLSB GET LSB STD PBHI WRITE OUT RESULT QPB2 RTS * * PGM CHG. * QPGMCH CMPA #MAXPCH IS THIS A LOAD OR OB CMD? BGT OBPGM1 BR. IF OB CMD. LDB OMNIFG GET OMNI MODE CMPB #2 BLT OBPGM2 IGNORE TEST IF MERELY ON/OFF LDB MCHL CMPB CHNL0 IS IT FOR US?? BNE QPB2 RETURN IF NOT OBPGM2 STA PCHLDQ SET PATCH # LBSR CLRART CLEAR EVERYTHING LBSR LDPTCH LOAD IT UP CLRB LBSR LDOBHM LOAD UP OB. LDX #PNUM LBRA SHOPCH DISPLAY IT OBPGM1 SUBA #MAXPCH+2 SUBTRACT OFFSET BMI QPB2 RETURN IF NEGATIVE (IE. DEADZONE) CMPA #15 TOO BIG? BGT QPB2 THEN PUNT STA OBPGRM STORE IN CURRENT PGM. LBRA LDPGCG SET OB * * CONTROL CHANGE * QCTLCH TST MPHASE ARE WE READY? BNE QCTLC1 BR. IF SO STA CTLNR STORE CONTROLLER # QCTLRT RTS QCTLC1 LDB CTLNR GET CTLR. # CMPB #123 MODE MESSAGE? BLT QCTL08 BR. IF NOT LDA MCHL GET CHL. # CMPA CHNL0 IS THIS EXPRESSLY FOR US? BNE QCTLRT RETURN IF NOT CMPB #123 ALL NTE OFF? BNE QCTL01 !!! EMPLOY CHANNEL MODE COMMANDS !!! TST SUSTFG TEST SUSTN. BEQ QCTL1X BR. IF OFF LDA #63 LDX #STSVEL LDY #NLST4V QCTL03 TST A,Y BEQ QCTL02 BR. IF NOT ON TST A,X BNE QCTL02 BR. IF ALREADY QUEUED STB A,X QUE FOR NTE. OFF QCTL02 DECA BGE QCTL03 LOOP RTS * QCTL1X LDA #1 STA PIADB CLEAR NTS. LDX #NLST4V LDA #63 QCTL2X TST A,X IS IT ON OR QUEUED? BEQ QCTL3X LOOP IF NOT PSHU A,X ADDA TRNPSE LBSR HNOFF TURN IT OFF PULU A,X QCTL3X DECA STEP CTR. BGE QCTL2X LOOP... RTS * * THE CODE BELOW IS TO HANDLE CHANNEL MODE MESSAGES. * AS THEY CAUSE TOO MUCH CONFUSION (EVERYTHING IS LOADED * VIA PATCH ANYWAY), THIS CODE WAS COMMENTED OUT. I DECIDED * TO PUT IT BACK IN. * * QCTL01 LBSR CLRART ALL NTES OFF LDB CTLNR RESTORE CNTLR # SUBB #124 SUBTRACT OFFSET BLT QCTLRT RETURN ON ALL-NTS-OFF BNE QCTL04 STB OMNIFG SET OMNI OFF (#124) RTS QCTL04 DECB BNE QCTL05 INCB INCB SET TO OMNI; X-CTLRS MODE STB OMNIFG SET OMNI ON (#125) RTS QCTL05 DECB BNE QCTL06 INCB STB MONOFG SET MONO ON (#126) STB UNISON SET UNISON ON TOO! LBRA LDUNSN LOAD UP OB. QCTL06 CLRA STA MONOFG SET MONO OFF (#127) STA UNISON SET UNISON OFF TOO! LBRA LDUNSN LOAD UP OB. * QCTL08 CMPB #64 SUSTN? (CTLR. 64) BNE QCTL7X STA SUSTFG SET/RESET FLAG BNE QCTL10 BR. IF SET ON LDA SENDMD PSHS A STASH OLD SEND MODE CMPA #2 ECHO OR OVERFLOW MODE? BGE QCTLEH DON'T MUTE IF SO CLR SENDMD MUTE IT FOR NOW QCTLEH LDA #63 LDX #STSVEL GET TABLE ADDR. QCTL13 LDB A,X GET VEL. BEQ QCTL11 BR. IF NOT QUEUED CLR A,X CLEAR TABLE ENTRY PSHS A,X STASH COUNT ADDA TRNPSE ADD TRNSPSE BMI QCTL12 IGNORE IF OVERFLOW STB LSTRVL STB LSTVEL STASH VEL LBSR HNOFF TURN NTE OFF QCTL12 PULS A,X RESTORE COUNT QCTL11 DECA BGE QCTL13 CONTINUE... PULS A STA SENDMD RESTORE SEND MODE QCTL10 RTS * QCTL7X PSHU B CODE TO CHECK FOR CHANNEL LDB OMNIFG CMPB #2 ARE WE IN X-CONTROLLERS MODE? BLT QCTL00 SKIP CHANNEL CHECK IF NOT LDB MCHL GET CURRENT CHANNEL CMPB CHNL0 IS IT FOR US? BEQ QCTL00 BR. IF OK PULU B RESTORE STACK QCTL2E RTS RETURN * QCTL00 PULU B RESTORE STACK FROM ABOVE ACTIVITY * CMPB #1 MOD CONTROLLER (VCF?) BNE QCTL1A BR. IF NOT TST VCFCTL CHECK ASSIGNED CONTROLLER BNE QCTL2A BR. IF NOT SET TO MOD WHEEL BRA QCTL3A BR. TO SET VCF VALUE QCTL1A CMPB #3 CONTROLLER #3 (VCF?) BNE QCTL2A CONTINUE IF NOT TST VCFCTL CHECK ASSIGNED CONTROLLER BEQ QCTL2A BR. IF SET TO MOD WHEEL QCTL3A LSLA CORRECT STA VCFMOD SET VCF MODULATION DIRECTLY RTS * QCTL2A CMPB #7 VOLUME CONTROLLER? BNE QCTL4A LSLA CORRECT FOR 7 BITS STA OUTVOL SET TVB STA TVBVOL STA LOCVOL RTS * QCTL4A CMPB #8 BALANCE CONTROLLER? BNE QCTL5A LSLA STA OUTBAL SET TVB STA TVBBAL STA LOCBAL RTS * QCTL5A CMPB #11 BASS => EXPRESSION CONTROLLER? BNE QCTL6A LSLA STA OUTBAS SET TVB STA TVBBAS STA LOCBAS RTS * QCTL6A CMPB #4 TREBLE => FOOT CONTROLLER? BNE QCTL7A LSLA STA OUTTRB SET TVB STA TVBTRB STA LOCTRB RTS * QCTL7A CMPB #9 UNDEFINED => VCF SWEEP SENSITIVITY BNE QCTL8A LSLA STA VCFSWP STA VCFSEN RTS * QCTL8A CMPB #20 UNDEFINED => TRILL RATE BNE QCTL9A CLRB LSLA STA RTBTRL QXTOK8 BEQ QXTOK6 BR. IF NO DUTY FACTOR SELECTED TFR A,B PUT INTO LSB CLRA LSLB ROLA SHIFT LEFT ONE PLACE QXTOK6 STD ATRATE BNE XTOKR BR. IF OK LDB #8 GET MINIMAL VALUE STB ATRATE+1 BOOST LSB XTOKR TST PWTRLL PW SET?? BEQ QATOK6 LOAD IF NOT RTS * QCTL9A CMPB #21 UNDEFINED => TRILL PW BNE QCTL99 CLRB LSLA STA PWTRLL QATOK8 BEQ QATOK6 BR. IF NO DUTY FACTOR SELECTED TFR A,B PUT INTO LSB CLRA LSLB ROLA SHIFT LEFT ONE PLACE QATOK6 STD ATRTED BNE ATOKR BR. IF OK LDB #8 GET MINIMAL VALUE STB ATRTED+1 BOOST LSB ATOKR RTS * QCTL99 CMPB #22 UNDEFINED => TRILL AMPLITUDE BNE QCTL1B LSLA INCA CORRECT & MAKE @ LEAST UNITY STA TRLCNT STA SBTRL PUT INTO TRILL AMPLITUDES RTS * QCTL1B CMPB #23 UNDEFINED => TRILL WAVEFORM BNE QCTL2B CMPA #2 TOO BIG? BLE QCTL3B LDA #2 SATURATE POSITIVE QCTL3B STA TRLSEL RTS * QCTL2B CMPB #12 UNDEFINED => OCTAVE SHIFT BNE QCTL4B CMPA #3 TOO BIG? BLE QCTL5B LDA #3 QCTL5B STA OCTAVE LBRA LDOCTV LOAD UP 4V * QCTL4B CMPB #13 UNDEFINED => ASSIGN SET? BNE QCTL6B CMPA #2 TOO BIG? BLE QCTL7B LDA #1 SET AT CONTINUOUS QCTL7B STA ASSIGN LBRA LDASSN LOAD UP 4V * QCTL6B CMPB #27 UNDEFINED => AUTOCUT SET? BNE QCTLAX TFR A,B CMPB #1 BLE QCTL8B IF VALUE ZERO, TURN AUTOCUT OFF LDB #1 QCTL8B STB AUTOCT SET AUTOCUT FLAG CMPA #2 BLE QCTL9B LOAD DIRECTLY IF SMALL LDA #2 SATURATE QCTL9B STA AUTINT SET AUTOCUT INTERVAL RTS * QCTLAX CMPB #5 PORT. TIME? BNE QCTL09 CMPA #63 OVER MAX?? BLE CTLLPT BR. IF OK LDA #63 SATURATE POSITIVE CTLLPT STA PMNTME STASH IN PATCH LBRA LDPMTM LOAD UP * QCTL09 CMPB #65 PORT MODE (65) BNE QCTL07 CMPA #3 ARE WE TOO LARGE? BLE QCTL9G BR. IF OK LDA #1 SET FOR "BOTH" ON SAT. QCTL9G STA PMNMDE STASH LBRA LDPMMD LOAD UP * QCTL07 CMPB #94 PB SENS? (#94; CELESTE/DETUNE DEPTH) BNE QCTL14 LSLA SCALE UP 1 BIT STA PBRNGE LBRA LDPBRG LOAD UP * QCTL14 CMPB #16 BNE QCTL15 SPLIT MODE (16; GEN CTL. 1) PSHS A LBSR CLRART PULS A CMPA #3 ARE WE TOO BIG? BLE QCTL4G BR. IF OK LDA #1 SATURATE AT 2-2 QCTL4G STA SPLTMD STASH IN MODE LBRA LDSPLM * QCTL15 TSTA BEQ QCTL16 LDA #1 SATURATE AT 1 * QCTL16 CMPB #17 UNISON MODE (17; GEN CTLR. 2) BNE QCTL21 PSHS A LBSR CLRART PULS A STA UNISON LBRA LDUNSN * QCTL21 CMPB #18 REASSIGN MODE (18; GEN. CTLR. 3) BNE QCTL17 STA RSNMDE LBRA LDRSGN * QCTL17 CMPB #19 AUTO PORT (19; GEN. CTLR. 4) BNE QCTL8X STA APMNTO BNE QCTL7R BR. IF NOT TURNED OFF LBSR LDPMTM RESTORE PORT. VALUE IF OFF LBRA CLRNTE TAKE CARE OF MIDI OUTPUT QCTL7R RTS * QCTL8X CMPB #69 DELAYED NTE TRIGGER (69; HOLD 2) BNE QCTL1C STA NCTLTG SET (RESET) NTE TRIGGER RTS * QCTL1C CMPB #24 UNDEFINED => LOUDNESS COMP. BNE QCTL2C STA TVBLDC STA OUTCMP LOAD TVB RTS * QCTL2C CMPB #25 UNDEFINED => STEREO/MONO SW. BNE QCTL3C STA TVBSTM NEGA ALL 1'S STA OUTSTM LOAD TVB RTS * QCTL3C CMPB #26 UNDEFINED => STEREO ENHANCE BNE QCTL1D STA TVBENH NEGA ALL 1'S STA OUTENH LOAD TVB RTS * QCTL1D CMPB #28 UNDEFINED => PLAY NOTES OR BUFFER BNE QCTL4C PSHS A LBSR CLRNTE TURN ALL NOTES OFF FIRST PULS A STA OVFPLY SET FLAG RTS * QCTL4C CMPB #66 SOST. PEDAL (NOTE BUFFER TRIGGER) BNE QCTL5C TST NBUFKY IS THE TRIGGER SET TO THE PEDAL? BNE QCTL5C BR. IF NO TST KYSAFE SAFING ON? BEQ QCTL6C BR. IF OFF TST SAFEFG FLAG SET? BEQ QCTL5C IGNORE IF NO QCTL6C STA LDNOTE SET FLAG BEQ QCTL3E EXIT IF TURNED OFF LDB #-1 STB NONTE INIT. COUNTER QCTL3E RTS * QCTL5C CMPB #67 SOFT PEDAL (NOTE TRIGGER SAFETY) BNE QCTL7C STA SAFEFG SET SAFE FLAG RTS * QCTL7C CMPB #121 RESET ALL CONTROLLERS CODE? BNE QCTL18 LDA NVMPCH GET LAST PATCH LOADED LBRA OBPGM2 GO AND LOAD IT UP TO CLEAR ALL PARAMETERS TO ORIGINALS * QCTL18 SUBB #80 BMI QCTL3E QUIT IF TOO SMALL BNE QCTL19 PSHS A LBSR CLRART PULS A STA ABEND RTS * QCTL19 DECB AUTO TRILL ENABLE (81; GEN. CTLR. 6) BNE QCTL20 PSHS A LBSR CLRART PULS A STA ATRILL RTS * QCTL20 DECB AUTO BEND TRIGGER (82; GEN. CTLR. 7) BNE QCTL25 TSTA BEQ QCTL2R IGNORE IF ARG. ZERO QCTLSB LDB TGMBND GET TRG. MODE CMPB #2 CTLR MODE? BNE QCTL23 BR. IF NO LDB MNHBND ANY MIN. HOLD? BEQ QCTL23 BR. IF NO STB ABTGED SET TRIGGERED FLAG (FOR RELEASE TRG.) QCTL2R RTS QCTL23 LBRA ABSET SETUP BEND * QCTL25 DECB AUTO TRL. TRIGGER (83; GEN. CTLR. 8) BNE QCTL22 TSTA BEQ QCTL2R IGNORE IF ARG. ZERO QCTLST LDB TGMTRL GET TRG. MODE CMPB #2 CTLR MODE? BNE QCTL24 BR. IF NO LDB MNHTRL ANY MIN. HOLD? BEQ QCTL24 BR. IF SO STB ATTGED SET TRIGGERED FLAG (FOR RELEASE TRG.) RTS QCTL24 LBRA ATSET SETUP TRILL * QCTL22 RTS END OF IMPLIMENTED CONTROLLERS * * SYS-EX ON HANDLER * QSXON LDB MSYEX GET SYSEX COUNTER CMPB #10 HOW BIG HAS IT GROWN? BGT QSXZZZ SKIP INCREMENT TO AVOID OVERFLOW INCB INC SYSEX COUNTER STB MSYEX PUT IT BACK INTO STORAGE QSXZZZ CMPB #1 AT BEGINNING? BNE QSXN01 BR. IF SO... CMPA #$10 OB. CODE BNE QSXNRT RETURN IF NOT INC MEX RTS QSXNRT CLR MEX RTS QSXN01 CMPB #2 2'ND BYTE? BNE QSXN02 CMPA #$77 JAP INTERFACE CUSTOM CODE? BNE QSXNRT BR. IF NO INC MEX RTS QSXN02 CMPB #3 THIRD BYTE? BNE QSXN03 BR. IF NO STA MCMDX STORE COMMAND BEQ QSXN04 BR. IF SEND DUMP CMPA #1 ACCEPT DUMP? BNE QSXNRT BR. IF JUNK CLRA STA M1PHX STA MADDX CLEAR COUNTERS QSXN04 RTS QSXN03 CMPB #4 FOURTH BYTE? BNE QSXN05 BR. IF NOT INC MEX DUMMY INCREMENT; BYTE MEANS NOTHING RTS QSXN05 CMPB #5 FIFTH BYTE? BGT QSXN06 BR. IF NOT (OR LARGER) CMPA #STRDMP DUMP OUT THE DATA STRUCTURE?? BNE QSXNAX BR. IF NOT LDB MCMDX GET COMMAND CMPB #1 EAT DATA? BEQ QSXNRT PUNT IF EAT DATA STRUCTURES; ONLY OUTPUT BRA QSXNAL BR. IF OUTPUT DATA STR. QSXNAX CMPA #PCHALL DUMP OUT ALL PATCHES?? BNE QSXN0B BR. IF NOT CLR PCHCTX CLEAR OUT THE PATCH COUNTER BRA QSXNAL QSXN0B CMPA #PCHLOC AFFECT ONLY LOCAL PATCH BEQ QSXNAL QSXN0A CMPA #MAXPCH BGT QSXNRT PATCH#; IGNORE IF OUT OF LIMITS QSXNAL STA PCHLX STASH PATCH # INC MEX RTS QSXN06 LDB MEX GET VALIDITY COUNT CMPB #4 BNE QSXN04 RETURN IF NOT VALID LDB MCMDX GET CMD. CMPB #1 EAT DATA? BNE QSXN04 BR. IF NOT TAKE DUMP LDB MADDX GET # BYTES CMPB #TOTVP MAX? BGE QSXN04 IGNORE IF > TST M1PHX TEST PHASE BNE QSXN07 BR. IF BYTE ASSEMBLED STA MEXBUF STORE LS NIBBLE INC M1PHX ADVANCE PHASE RTS QSXN07 LSLA FORM MS NIBBLE LSLA LSLA LSLA ORA MEXBUF OR IN LS NIBBLE LDX #PEBUF STA B,X STORE IN PATCH INCB STB MADDX INC. ADDR. CLR M1PHX CLEAR PHASE CMPB #TOTVP ARE WE @ THE TOP OF THE PATCH?? BLT QSXN04 RETURN IF NOT LDA PCHLX GET COMMANDED PATCH NO. CMPA #PCHALL IS IT THE ALL-PATCHES DUMP REQUEST?? BNE QSXN04 RETURN IF NOT TST WRTPRT TEST THE WRITE-PROTECT FLAG BEQ WWWWX BR. IF OFF CLR MEX BRA WWXQ PUNT W. WRITE PRT. MESSAGE IF FLAG SET WWWWX CLR MADDX CLEAR PATCH VARIABLE COUNTER LDB PCHCTX GET PATCH# COUNTER CMPB #MAXPCH ARE WE OVER THE TOP?? BGT QSXN04 BR. IF YES INC PCHCTX INCREMENT THE PATCH# COUNTER LBRA SAVPCM SAVE THE PATCH * * SYSEX OFF HANDLER * QSXOFF LDB MEX GET VALIDITY COUNT CMPB #4 DID WE GET FAR ENOUGH?? LBNE QSXNRT EXIT IF NOT VALID TST MCMDX TEST CMD. BEQ QSXF01 BR. IF SEND DUMP * LDB PCHLX GET LOADED PNUM CMPB #PCHLOC AFFECT ONLY LOCAL PATCH? BNE WWXQQ1 BR. IF NOT LDA #TOTVP GET PATCH VARIABLE COUNT LDX #PEBUF LDY #PNUM WWLOOP LDB ,X+ GET DATA STB ,Y+ STASH IN LOCAL PATCH DECA BNE WWLOOP LOOP TILL DONE CLRB CHANGE LOCAL PATCH => LOAD OB. AND DISPLAY LBSR LDOBHM LOAD UP OB. LDX #PNUM LBSR SHOPCH DISPLAY IT BRA QSXF02 SEND ACK * WWXQQ1 TST WRTPRT WRITE-PROTECT ON? BEQ QSXF02 BR. IF OK WWXQ LBSR WPMESS WRITE MESSAGE IF W-PROT. LDA #$7E STA MMBUFF+3 LBSR SXSNDA SEND NAK SYEX MESSAGE LBRA QSXNRT PUNT OUT QSXF02 LDA #$7F GET ACK CODE STA MMBUFF+3 LBSR SXSNDA SHIP IT CLR MEX CLEAR SYSEX VALIDITY COUNT LDB PCHLX GET LOADED PNUM CMPB #MAXPCH PNUM IN EXCESS?? LBGT QSXNRT THEN DON'T TRY TO SAVE IT LBRA SAVPCM SAVE PATCH IN NVRAM * QSXF01 CLR MEX LOAD DUMP HEADER CODE LBSR SXSNDB SEND IT LDA PCHLX GET ASSIGNED PNUM CMPA #STRDMP DUMP DATA STRUCTURE? LBEQ QSXCHR BR. IF SO CMPA #PCHLOC DUMP ONLY LOCAL PATCH? BNE QSXBNL BR IF NOT LDX #PNUM POINT AT LOCAL PATCH BRA QSXFDD DUMP IT OUT QSXBNL CMPA #PCHALL DUMP ALL PATCHES?? BNE QSXFA1 BR. IF NOT LDA PCHCTX LOAD NEXT PNUM QSXFA1 STA PCHLDQ PUT PATCH# UP FOR LOADER LBSR LDPTCM LOAD PATCH INTO SPECIAL BUFFER LDX #PEBUF POINT AT BUFFER QSXFDD LDA #TOTVP GET VARIABLE COUNT STA MEBUFF QSXF03 LDB ,X+ GET DATA TFR B,A ANDB #$F GET LOW 4 BITS STB ODATAS PUT IN DATA LOW LSRA LSRA LSRA LSRA STA ODATAS+1 PUT IN DATA HI LDA #2 2 BYTES STA OCOUNT LDB OBSTAT GET SYSEX STAT LDA CHNL1 GET OUTPUT CHANNEL PSHS X SAVE POINTER LBSR MDIOUT SHIP OUT PULS X RESTORE POINTER DEC MEBUFF DEC COUNTER BNE QSXF03 LOOP OVER BUFFER LDA PCHLX GET PATCH COMMAND CMPA #PCHALL DUMP ALL?? BNE QSXFA2 BR. IF NOT LDA PCHCTX LOAD PNUM COUNTER INCA INCR. IT STA PCHCTX PUT IT BACK CMPA #MAXPCH BLE QSXFA1 LOOP IF MORE LEFT QSXFA2 LDA #$F7 GET END CODE STA ODATAS LDA #1 STA OCOUNT ONLY ONE BYTE LDA CHNL1 GET OUTPUT CHNL. LDB OBSTAT GET OB. STATUS LBRA MDIOUT SHIP IT * * SEND SIX BYTE MESS. @ X TO OUTPUT * SXSEND LDX #MMBUFF LDA #6 SXSND1 LDB ,X+ STB ODATAS GET DATA LDB #1 STB OCOUNT 1-BYTE LDB OBSTAT GET STAT. PSHS A,X LDA CHNL1 GET OUT CHNL. LBSR MDIOUT SHIP IT PULS A,X DECA BNE SXSND1 LOOP QSXRTS RTS * * SEND ONE BYTE (IN B) TO MIDI OUTPUT * SXSNDX STB ODATAS GET DATA LDB #1 STB OCOUNT 1-BYTE LDB OBSTAT GET STAT. PSHS A,X,Y LDA CHNL1 GET OUT CHNL. LBSR MDIOUT SHIP IT PULS A,X,Y RTS * * SYSEX ACK/NAK MESSAGE MAKER * SXSNDA LDX #MMBUFF LDA #$F0 STA ,X+ LDA #$7E STA ,X+ LDA CHNL0 STA ,X++ LDA PCHLX STA ,X+ LDA #$F7 STA ,X BRA SXSEND * * SHIP OUT DUMP HEADR * SXSNDB LDY #MMBUFF LDX #DMPMSG LDA #4 SXSND2 LDB ,X+ STB ,Y+ DECA BNE SXSND2 LDA CHNL0 STA ,Y+ LDA PCHLX STA ,Y BRA SXSEND * DMPMSG FCB $F0 FCB $10 FCB $77 FCB 1 * * DUMP OUT DATA STRUCTURES * QSXCHR LDB #MAXPCH GET MAX # PATCHES BSR SXSNDX SEND IT LDB #MXLVL0 GET # HEADINGS IN LVL 0 BSR SXSNDX SEND # HEADINGS CLR PCHCTX CLEAR COUNTER QSXCH1 LDA PCHCTX GET CURRENT HEADING LDB #12 12 CHARS PER HEADING TITLE MUL LDX #L0TIT POINT AT HEADING TITLES ABX ADD OFFSET LDB #12 12 CHARS. TFR B,A BSR SXSNDX SEND 12 TO DENOTE 12 CHARS. FOLLOWING QSXCH2 LDB ,X+ PICK UP NEXT CHAR. BSR SXSNDX SHIP IT OUT DECA BNE QSXCH2 LOOP UNITL DONE * QSXCH5 LDX #N1HEAD POINT AT LEVEL 1 NO. OF ARGUMENTS TABLE LDA PCHCTX LOAD LEVEL0 POINTER LDB A,X GET # OF LVL 1 ARGS. STB SXNLV0 STASH IT BSR SXSNDX SEND IT LDX #L0OFF POINT AT OFFSET INTO PATCH LIST LDA PCHCTX GET LVL0 INDEX LDB A,X PICK UP THE INDEX SUBB #10 CORRECT IT FOR TITLE OFFSET CLRA LSLB ROLA LSLB MULTIPLY BY 4 ROLA ADDD #L1ARG ADD OFFSET INTO POINTER TFR D,X PUT IT INTO INDEX REG. CLRA CLEAR COUNTER QSXCH3 LDY ,X++ POINT AT ITEM TITLE LDB ,Y+ GET # CHARS. PSHS A STASH ITEM COUNTER TFR B,A SAVE # CHARS LBSR SXSNDX SEND IT OUT QSXCH4 LDB ,Y+ GET A CHARACTER LBSR SXSNDX SEND IT OUT DECA BNE QSXCH4 GET NEXT CHAR. LDB ,X+ GET ARGUMENT FLAGS ANDB #$7F MASK OUT TOP BIT LBSR SXSNDX SHIP IT OUT LDB ,X+ GET VARIABLE LIMIT TFR B,A SAVE IT ANDB #$F ONLY LOW 4 BITS LBSR SXSNDX SHIP 'EM TFR A,B RESTORE LSRB SHIFT HIGH 4 BITS DOWN LSRB LSRB LSRB LBSR SXSNDX SEND OUT THE HIGH 4 BITS PULS A RESTORE COUNTER INCA INCR. IT CMPA SXNLV0 LOOP OVER ALL LEVEL 1 ITEMS BNE QSXCH3 LOOP... LDA PCHCTX GET LVL 0 COUNTER INCA INCR. IT STA PCHCTX RESTORE IT CMPA #MXLVL0 ALL ITEMS DONE? BNE QSXCH1 LOOP IF NOT * LDB #BTMLST GET # ITEMS IN OPTION LIST TFR B,A SAVE IT LBSR SXSNDX SEND IT LDY #CHROPT POINT AT OPTION TABLE SXSND7 LDX ,Y++ POINT AT THE OPTION CHARACTERS PSHS A SAVE COUNTER LDB ,X+ GET THE # CHARS. TFR B,A STASH IT INCA INC. IT TO ACCOUNT FOR ITSELF SXSND6 LBSR SXSNDX SHIP IT OUT LDB ,X+ GET NEXT CHAR. DECA BNE SXSND6 LOOP UNTIL ALL SENT PULS A RESTORE ITEM COUNTER DECA BNE SXSND7 LOOP UNTIL ALL ITEMS SENT LBRA QSXFA2 SEND SYS-EX END CODE PAGE * * KEY ALLOCATION LOGIC * HNON STA LSTNTE STASH NTE# LBSR CLREFS CLEAR TRL/BND EFFECTS LDB SENDMD DECB BNE HNON01 LDA LSTNTE LDB LSTAVL LBSR OUTON SEND TO OUT IF NRM. SET HNON01 LDA LSTNTE RESTORE SUBA TRNPSE SUBTRACT TRNPSE BLT HNONOV BR. ON - OVF. CMPA #TOPNTE BLE HNON00 BR. IF NO + OVF. HNONOV LDB SENDMD OVERFLOW; IS SEND-OV SELECTED? CMPB #3 BNE HNONR1 RETURN IF NOT HNONXT LDA LSTNTE GET NTE# LDB LSTAVL GET AVEL. LBSR OUTON NTE ON @ OUT HNONR1 RTS RETURN HNON00 STA NTEOB0 STASH OB. NTE CLRB STB NTENOW CLEAR NOTE-ALREADY-SOUNDING FLAG CMPA #HLFNTE WHICH HALF? BLE HNON03 BR. IF LOWER INCB HNON03 STB KEYHLF STORE HALF FLAG LDX #NLST4V POINT @ NTE LIST TST A,X BNE HNON02 BR. IF NTE ALREADY ON INC NDOWN INC #DOWN LDY #NDOWNL INC B,Y INC #DOWN PER HALF HNON02 LDB LSTAVL GET LAST VEL TST A,X IS THE NOTE ALREADY SOUNDING? BGE HNON0D BR. IF NOT INC NTENOW SET SOUNDING FLAG ORB #$80 OR-IN SIGN BIT HNON0D STB A,X STORE AVEL IN KEY TABLE TST MONOFG MONO MODE? BEQ HNONPY PR. TO POLY IF NOT LDB KPRTY GET KEY PRTY. BEQ HNON04 BR. IF NRM. TST NTCVAL BMI HNON04 IGNORE COMPARISON IF SET CMPB #4 BNE HNON05 BR. IF NOT LAST HNON04 LDB NTCVAL GET LST. NTE. LEAY B,X LDB ,Y BEQ HNONCV BR. IF PREVIOUSLY OFF PSHS A,B,X,Y SAVE EVERYTHING LDB SENDMD DECB BLE HNONNW SKIP IF NOT ECHO OR OVF. MODE LDA NTCVAL GET PREVIOUS NTE ADDA TRNPSE MAKE IT ABSOLUTE DECB BEQ HNONNP BR. IF ECHO LDB NTCVAL GET BUMPED NTE LEAY B,X LDB ,Y GET BUMPED VEL. ANDB #$7F MAKE PLUS LBSR OUTON TURN IT ON BRA HNONNW HNONNP LDB #64 A RESPECTABLE RVEL LBSR OUTOFF TURN IT OFF HNONNW PULS A,B,X,Y RESTORE ANDB #$7F CLEAR SIGN BIT ON NTE. ENTRY STB ,Y REPLACE HNONCV STA NTCVAL REP. CUR. VAL. TST CMDNTE BEQ HNONPT SKIP IF COMMAND OFF LDB #1 GET ALL-OFF CODE STB PIADB TURN ALL NTE OFF HNONPT LBRA OBNON BR. TO TURN SELECTED NTE. ON * HNON05 LDB NDOWN CMPB #1 BLE HNON04 BR. IF NO NTS. DOWN LDB KPRTY GET PRIO. CMPB #3 FST. NTE? BNE HNON07 BR. IF NOT HNON08 LDB SENDMD CMPB #3 SEND OVF? LBEQ HNONXT XMIT NTE IF SO RTS HNON07 CMPB #1 HIGH NT PRIO? BNE HNON09 BR. IF NOT CMPA NTCVAL NEW NTE HIGHER? BLE HNON08 BR. IF NOT BRA HNON04 SEND IF SO HNON09 CMPA NTCVAL NEW NTE LOWER? BGE HNON08 BR. IF NOT BRA HNON04 BR. IF SO * * POLY MODE * HNONPY TST KPRTY TEST KEY PRIO LBEQ OBNON BR. IF NONE LDB KEYHLF LDY #NTAKNL LEAY B,Y LDB SPLTMD TEST SPLIT MODE BEQ HNON10 BR. IF OFF TST UNISON UNIS. ON? BNE HNON11 BR. IF SO CMPB #1 2-2? BNE HNON12 INCB LOAD B W. 1 BRA HNON13 HNON12 LDA KEYHLF BNE HNON15 LDA #-1 HNON15 STA HLFBS CMPB #2 3-1? BNE HNON14 BR. IF NOT SUBB HLFBS BRA HNON13 HNON14 DECB 1-3 ADDB HLFBS HNON13 STB NAVAIL STORE # AVAILABLE LDB ,Y GET # TAKEN BRA HNON16 HNON11 LDB #1 ONLY 1 AVAIL. ON UNISON BRA HNON13 HNON10 TST UNISON UNISON ON? BEQ HNON17 BR. IF NO LDB #1 YES, 1 VCE BRA HNON18 HNON17 LDB #4 NO, 4 VCES HNON18 STB NAVAIL STORE # AVAILABLE LDB NTAKEN GET # TAKEN HNON16 CMPB NAVAIL #TAKEN = #AVAIL? BGE HNON19 BR. IF SATURATED TST NTENOW NOTE ALREADY SOUNDING?? BNE HNONR2 BR. IF SO INC NTAKEN STEP THE NO. TAKEN INC ,Y STEP # PER HALF LDA NTEOB0 LBSR OBNON NTE. ON IF ROOM LEFT HNONR2 RTS HNON19 LDB KPRTY GET KEY PRIO. CMPB #3 FST NTE? BEQ HNON08 SEND IF SEND OV. BRA HNON20 * HNON22 LDX #NTESND LDA B,X GET # OF NTE TO TURN OFF DECA CORRECT STA NREALC STASH CLR B,X CLEAR IT OUT LDY #NLST4V POINT @ NTE LST. LDB A,Y GET VEL. ANDB #$7F CLEAR SIGN STB VREALC STASH STB A,Y PUT BACK TST CMDNTE BEQ HNONHA ORA #$40 NTE-OFF CODE STA PIADB DO IT; TURN OFF HNONHA LDA NTEOB0 LBSR OBNON TURN THE NTE ON LDB SENDMD DECB BLE HNONR2 RET. IF MUTE OR NORMAL LDA NREALC OVF. MODE - GET BUMPED # ADDA TRNPSE MAKE ABSOLUTE DECB BEQ HNON23 BR. IF ECHO LDB VREALC " " - GET BUMPED VEL LBRA OUTON SEND IT HNON23 LDB #64 AVG. VEL LBRA OUTOFF TURN OFF * HNON20 DECB STB NHLFG SET HI/LO PRIO FLG. LDB #-1 STB NREALC STORE INIT. CODE TST SPLTMD BNE HNON24 NO SPLIT CLRA HNON2X LDB #3 FULL 4-V SCAN TST UNISON UNISON ON? BEQ HNON3X IGNORE IF NOT CLRB END AT FIRST LOCATION IF NO SPLIT TST SPLTMD SPLIT ON? BEQ HNON3X OK IF NOT LDB #3 RESTORE SUBB SPLTMD CALCULATE START IN LIST (FOR TOP HLF) CMPB #2 BEQ HNON4X NO CORRECTION NEEDED IF 2-2 LSLB INCB CORRECTION FOR OTHER MODES HNON4X TFR B,A HNON3X STB NFIN BRA HNON25 HNON24 TST KEYHLF SPLIT BEQ HNON26 BR. IF LOWER LDA #4 SUBA NAVAIL GET STARTING # BRA HNON2X HNON26 CLRA LOWER END/ START # LDB NAVAIL END # DECB CORRECT STB NFIN HNON25 LDX #NTESND LOOK @ CURRENT TABLE LDB KPRTY GET PRIO. CMPB #4 IS IT LAST? BNE HNONLP BR. IF NOT LDB LSTPLC GET LAST POSITION IN NTE. ACTIVE LST CMPB NFIN TOO BIG? BGT HNONLX THEN RESET STA SVPQ CMPB SVPQ TOO SMALL? BLT HNONLX THEN RESET HNONBG INC LSTPLC INC. CURRENT POS. LBRA HNON22 DO THE SWAP HNONLX TFR A,B RESET POINTER STA LSTPLC RESET LOC. BRA HNONBG DO THE SWAP HNONLP LDB A,X EXAMINE ENTRY DECB CORRECT TST NHLFG HI OR LOW PRIO? BNE HNONLO BR. IF LOW CMPB NTEOB0 COMP. W. CURRENT NTE BGT HNONRJ IGNORE IF > TST NREALC BLT HNON27 BR. FOR INITIALIZATION CMPB NREALC WANT TO SWAP HIGHEST NTE BGT HNONRJ HNON27 STB NREALC STASH NTE STA NPTRA STASH POINTER BRA HNONRJ HNONLO CMPB NTEOB0 LOW-PRIO; COMP. W. CURRENT NTE BLT HNONRJ REJECT IF > TST NREALC BLT HNON27 BR. FOR INITIALIZATION CMPB NREALC WANT TO BUMP LOWEST NTE BGT HNON27 HNONRJ INCA NEXT ENTRY CMPA NFIN @ END? BLE HNONLP LOOP IF NOT TST NREALC ANY LUCK? LBLT HNON08 PUNT IF NONE LDB NPTRA FOUND NTE TO BUMP; GET POINTER LBRA HNON22 HANDLE BUMP * PAGE * * ROUTINE TO HANDLE OB. NTE ON (NTE# IN A) * OBNON LDX #NLST4V POINT @ LIST LDB A,X ORB #$80 STB A,X SET FLG. FOR NTE-ON STA NTELOC LOCAL STASH LDA VCFVEL GET VCF VELOCITY SENS. BEQ OBNNNV BR. IF NONE LDB LSTVEL GET VELOCITY LSLA LSLB CORRECT MUL SCALE ADDA VCFBSE ADD IN BIAS BCC OBNNNW BR. IF NO OVERFLOW LDA #$FF SATURATE POSITIVE OBNNNW STA VCF0 WRITE INTO VCF OFFSET OBNNNV CLRB STB NTSCUT CLEAR CUT SUM * TST APMNTO AUTO-PORT ON? BEQ OBNN01 BR. IF NOT LDA APTDST GET DEST. FLAG ANDA #1 IS THE 4-V ENABLED? BNE OBNN44 BR. IF NO LDA PORTBF GET LATEST PORT. CODE ORA #$80 SET PORT. FLG. STA PIADB WRITE TO OB. * OBNN44 LDB DLYAPT LOAD DELAY CONST. LSLB LSLB CORRECT FOR 6-BITS BEQ OBNN01 BR. IF OFF STB LOCDLY SET FLAG FOR LOC. DELAY ON STB TMR2 CLRB STB TMR2 GET TIMER #2 GOING OBNN01 TST AUTOCT TEST AUTOCUT MODE LBEQ OBNN05 PUNT IF OFF LDB AUTINT CMPB #2 SET TO CHORD DEFINE? BNE OBNNNC BR. IF NO TST CUTCNT CHECK #NOTES ALREADY IN BNE OBNC01 LDA NTELOC FIRST NOTE STA CTROOT SET THE ROOT INC CUTCNT LBRA OBNN05 CONTINUE... OBNC01 LDA NTELOC GET NOTE SUBA CTROOT SUBTRACT OFF ROOT FOR INTERVAL OBNC12 BGE OBNC02 BR. IF NOT LESS ADDA #12 GO UP AN OCTAVE BRA OBNC12 CHECK AGAIN OBNC02 LDB CUTCNT GET COUNT CMPB #3 IS THIS THE LAST PASS? BEQ OBNCN2 BR. IF SO (SKIP CLIP SINCE WE HAVE AN ENTIRE WORD) OBNCX2 CMPA #16 CLIP IF 16 OR OVER BLT OBNCN2 SUBA #12 GET AN OCTAVE DOWN BRA OBNCX2 OBNCN2 DECB CORRECT COUNT LDX #OBIVAL POINT AT LOCAL INTERVAL TABLE STA B,X STASH INC CUTCNT CMPB #2 LBLT OBNN05 BR. IF NOT DONE CLR CUTCNT CLEAR THE COUNT LDA #1 STA AUTINT TURN THE INTERVAL DEFINE OFF LBRA OBNN05 SKIP THE AUTOCUT * OBNNNC TST CMDNTE COMMAND NTS? LBEQ OBNN05 PUNT IF NO LDB NDOWN GET # DOWN DECB LBNE OBNN05 PUNT IF PRIOR NTES DOWN TST SPLTMD TEST SPLIT MODE BNE OBNN06 BR. IF SET TST UNISON TEST UNISON BNE OBNN05 PUNT IF SET W/O SPLIT LDA #3 CUT 4 NTS. TST LOCDLY DELAY ON? BEQ OBNN07 BR. IF NOT LDB TMROUT GET TIMER FLAGS ANDB #4 LOOK @ T3 BEQ OBNN07 BR. IF DELAY CLEAR INCA CORRECT FOR MISSING NTE OBNN07 PSHU A PUSH # TO CUT CLRA CLEAR START INDEX LDB #TOPNTE SCAN ENTIRE TABLE LBSR DOCUT DO AUTO CUTS BRA OBNN14 CONTINUE OBNN06 TST UNISON UNIS. ON? BNE OBNN08 BR. ON LDB SPLTMD GET SPLIT MD. DECB BNE OBNN09 LDA #2 2/2 MODE TFR A,B STD NOSPLT BRA OBNN10 OBNN09 DECB BNE OBNN11 INCB 3/1 MODE LDA #3 STD NOSPLT BRA OBNN10 OBNN11 LDB #3 1/3 MODE LDA #1 STD NOSPLT BRA OBNN10 OBNN08 LDA #1 UNISON TFR A,B STD NOSPLT OBNN10 TST LOCDLY DELAY ON? BEQ OBNN12 BR. IF NO LOCAL DELAY LDB TMROUT ANDB #4 LOOK @ T3 BNE OBNN13 BR. IF TIMER CLEAR OBNN12 LDY #NOSPLT LDB KEYHLF DEC B,Y CORRECT #TO CUT IF NO DELAY OBNN13 TST KEYHLF BNE OBNNXH DO ONLY CORRECT HALF LDA NOSPLT PSHU A PUSH # CLRA LDB #HLFNTE LBSR DOCUT DO LOWER HALF BRA OBNN14 OBNNXH LDA NOSPLT+1 PSHU A LDA #HLFNTE+1 LDB #TOPNTE LBSR DOCUT DO UPPER HALF OBNN14 TST NTSCUT BEQ OBNN05 IGNORE IF NO NTS. CUT LDB #5 LOAD DELAY FOR 1 SCAN COUNT STB TMR1 CLRB STB TMR1 GET TIMER2 GOING OBNN05 TST LOCDLY DELAY? BEQ OBNN15 LDB TMROUT ANDB #4 BNE OBNN16 BR. WHILE DELAY STILL ON OBNN15 TST CMDNTE COMMAND NTS? BEQ OBNN16 IGNORE IF OFF CLRA STA LOCDLY CLEAR LOCAL DELAY LDB NTELOC GET NOTE ORB #$C0 SET FOR NTE ON STB PIADB TURN ON OBNN16 TST NTSCUT ANY CUT? BEQ OBNN17 BR. IF NOT LDB TMROUT ANDB #2 BNE OBNN17 BR. IF SCAN DELAY STILL ON LDA NTSCUT LDY #NCTLST OBNN18 LDB ,Y+ GET NTE FOR CUT ORB #$40 INSERT OFF CODE STB PIADB TURN NTE OFF DECA BNE OBNN18 STA NTSCUT CLEAR FLAG/CTR OBNN17 TST LOCDLY BNE OBNN05 CONTINUE NTE DELAY TST NTSCUT BNE OBNN16 CONTINUE AUTOCUT DELAY TST KPRTY ANY PRIO ENFORCED? BEQ OBNN20 IGNORE IF NOT CLRA TST KEYHLF BEQ OBNN19 BR. IF LOWER LDB SPLTMD BEQ OBNN19 BR. IF NO SPLIT TFR B,A INCA CMPB #3 BNE OBNN19 LDA #1 OBNN19 LDY #NTESND TABLE... OBNN22 TST A,Y ENTRY OPEN? BEQ OBNN21 YEP, BR. INCA CMPA #3 BLE OBNN22 LOOP... BRA OBNN20 GIVE UP! OBNN21 LDB NTELOC INCB CORRECT STB A,Y FILL ENTRY OBNN20 LDB SENDMD GET SEND MODE CMPB #2 BNE OBNN23 IGNORE IF NOT ECHO LDA NTELOC GET NTE/ADD OFFSET LDB A,X GET VEL. ANDB #$7F ADDA TRNPSE ADD TRANSPOSE LBSR OUTON SEND IT OBNN23 TST ABEND A. BND ENABLED? BEQ OBNN24 BR. IF NOT LDA MNHBND MIN. HLD?? BEQ OBNN24 IGNORE IF REL. DECA NO DELAY ON "1" SETTING BEQ OBNN24 LBSR SHFT4 SHIFT UP 4 BITS INCB STB TMR0 STA TMR0 LOAD TIMER #1 OBNN24 TST ATRILL A. TRILL ENABLED? BEQ OBNN25 BR. IF NOT LDA MNHTRL GET MIN. HLD. BEQ OBNN25 IGNORE IF ON REL. DECA NO DELAY ON "1" SETTING BEQ OBNN25 LBSR SHFT4 SCALE UP INCB STB TMR1 STA TMR1 LOAD TIMER #2 OBNN25 LDB #1 STB LSTACT SET LAST ACT. TO NTE-ON RTS * * ROUTINE TO DO AUTOCT * STRT IN A, STOP IN B, NLST POINTER IN X, # TO CUT IN U-STK * DOCUT CLR CTRQX CLEAR THE FLAG TST SPLTMD BNE DOCUTX BR. IF SPLIT TST RSNMDE BEQ DOCUTX BR. IF RSGN. PSHS B STASH IT LDB ASSIGN GET FLAG DECB STB SVPQ STASH PULS B RESTORE TST SVPQ TEST IT BNE DOCUTX BR. IF SET INC CTRQX SET THE FLAG; CAN DO THE 10 MSEC. TST AUTINT TEST THE INTERVAL SETTING BNE DOCUTX DO SAME NOTE IF OCTAVES PULU B GET # TO CUT TSTB BLE DORXS PUNT IF NONE DOCX1 LDA NTELOC CUT ALL SAME NTE ORA #$C0 STA PIADB TURN IT ON BSR WT10MS WAIT 10 MSEC LDA NTELOC ORA #$40 STA PIADB TURN IT OFF BSR WT10MS WAIT DECB BNE DOCX1 CUT 'EM ALL DORXS RTS * WT10MS LDA #5 ROUTINE TO WAIT 10 MSEC. STA TMR1 CLRA STA TMR1 DOCX2 LDA TMROUT ANDA #2 BNE DOCX2 LOOP RTS * DOCUTX STB NTOPCT STASH TOP STA NBTMCT STASH BOTTOM PULU B GET # TO CUT TSTB BLE DORXS RETURN IF NONE STB NRVCUT STASH IT LDY #NCTLST POINT @ CUT LIST PSHS U STASH USER POINTER TST AUTINT BEQ DOCUT0 BR. IF OCTAVES CLRB DOCUT2 LDA NTELOC GET NOTE LDU #OBIVAL GET INTERVAL TABLE ADDA B,U ADD IN INTERVAL DOCUT3 CMPA NTOPCT TOO HIGH?? BLE DOCUT4 BR. IF OK SUBA #12 TRY AN OCTAVE DOWN BRA DOCUT3 DOCUT4 CMPA NBTMCT TOO LOW?? BGE DOCUT5 BR. IF OK ADDA #12 TRY NEXT OCTAVE UP BRA DOCUT3 DOCUT5 TST CTRQX TEST THE FLAG BEQ DOCTTT DO THE REASSIGN-OFF CUT IF NOT SET PSHS A STASH THE NOTE ORA #$C0 NOTE ON CODE STA PIADB NOTE ON BSR WT10MS WAIT... PULS A RESTORE THE NOTE ORA #$40 NOTE OFF CODE STA PIADB NOTE OFF BSR WT10MS WAIT... LDA NRVCUT GET CUT COUNT DECA DECREMENT STA NRVCUT RESTORE BRA DOCTTQ CONTINUE... * DOCTTT PSHS B STASH INDEX LDB NTELOC GET NOTE PSHS B STASH STA NTELOC STORE NEW NOTE AS CURRENT LDB NRVCUT GET # TO CUT PSHS B STASH LDB #1 STB NRVCUT CUT 1 NOTE TFR A,B PUT NEW NOTE IN B CLRA LDU #CUTPTY POINT AT PREFERENCE LIST BSR DOCUTZ DO THE CUT PULS A DECA STA NRVCUT RESTORE THE # TO CUT PULS B STB NTELOC RESTORE THE LOCAL NOTE PULS B GET LOCAL INTERVAL COUNTER DOCTTQ INCB INC. TSTA ALL DONE? BEQ DORTS RETURN IF SO BRA DOCUT2 CONTINUE DOCUTZ PSHS U GET STACK READY BRA DOCUTY BR. TO ROUTINE (THIS IS A DUMMY FOR STACK ORDERING) * DOCUT0 LDU #CUTPTY POINT AT PREFERENCE LIST CLRA CLEAR INDEX DOCUT1 LDB A,U GET PREFERRED OFFSET ADDB NTELOC ADD INTO NOTE CMPB NBTMCT TOO LOW?? BLT DOCONT IGNORE IF SO CMPB NTOPCT TOO HIGH?? BGT DOCONT IGNORE IF SO DOCUTY TST B,X IS THIS NTE AVAILABLE? BMI DOCONT CONTINUE IF NOT STB ,Y+ STASH IN CUT LIST ORB #$C0 STB PIADB TURN ON INC NTSCUT INC CUT COUNT DEC NRVCUT DEC COUNTER BNE DOCONT BR. IF MORE NEEDED DORTS PULS U RESTORE USER STACK RTS DOCONT INCA INC. POINTER CMPA #16 ANY MORE LEFT?? BLT DOCUT1 CONTINUE PULS U RESTORE USER STACK RTS * CUTPTY FCB 12 FCB -12 FCB 24 FCB -24 FCB 36 FCB -36 FCB 48 FCB -48 FCB 60 FCB -60 FCB 7 FCB -5 FCB 19 FCB -17 FCB 31 FCB -29 * PAGE * * NTE-OFF HANDLER * HNOFF STA LSTNTE STASH HANDY LDB SENDMD BEQ HNOF01 BR. IF OFF CMPB #2 ECHO 4V?? BEQ HNOF01 DON'T TURN NTE OFF HERE ON OUT IF NOT LDB LSTRVL GET VEL. LBSR OUTOFF TURN NTE OFF IF "NRM" LDA LSTNTE HNOF01 SUBA TRNPSE CORRECT FOR TRANSPOSE BLT HNOFXT BR. ON - OVF CMPA #TOPNTE BLE HNOF00 BR. IF OK ON + OVF. HNOFXT LDB SENDMD CMPB #2 ECHO 4V?? BNE HNOFR1 RETURN IF NOT LDA LSTNTE LDB LSTRVL LBSR OUTOFF TURN OVERFLOW NOTE OFF IF ECHO HNOFR1 RTS HNOF00 TST SUSTFG SUSTN. ON? BEQ HNOF02 BR. IF NOT LDX #STSVEL POINT TO SUST. TABLE LDB LSTRVL GET VEL STB A,X STORE INTO TABLE RTS HNOF02 STA NTEOB0 STASH CLRB STB LSTACT SET LAST ACTION = 0 FOR NTE-OFF TST CMDNTE COMMAND NTS? BEQ HNOFQQ BR. IF OFF TFR A,B ORB #$40 INSERT OFF CODE STB PIADB TURN IT OFF HNOFQQ LDB SENDMD CMPB #2 ECHO 4V?? BNE HNOFQ1 BR. IF NOT PSHS A LDB LSTRVL LDA LSTNTE LBSR OUTOFF TURN NOTE OFF ON OUTPUT IF ECHO4V PULS A HNOFQ1 LDX #NLST4V POINT @ MASTER LIST TST A,X TEST NTE VAL. LBEQ HNOFXY PUNT IF ZERO CLRB DEC NDOWN DEC. NTS. DOWN BGE HNOF03 SATURATE STB NDOWN HNOF03 CMPA #HLFNTE WHICH HALF? BLE HNOF04 LOWER- BR. INCB UPPER HNOF04 STB KEYHLF STASH LDY #NDOWNL DEC B,Y DEC. COUNT PER HALF BGE HNOF05 CLR B,Y SATURATE HNOF05 TST A,X TEST NTE. VAL. AGAIN LBPL HNOFXX PUNT IF ONLY QUEUED DEC NTAKEN DEC. # ACTIVE VCS. TAKEN LDY #NTAKNL DEC B,Y DEC. " " PER HALF TST KPRTY ANY PRIORITY? LBEQ HNOFXX PUNT IF NONE LDB #3 LDY #NTESND SEARCH TABLE INCA CORRECT HNOF08 CMPA B,Y IS THIS THE NTE? BNE HNOF06 CLR B,Y CLEAR IT! BRA HNOF07 HNOF06 DECB BGE HNOF08 HNOF07 DECA CORRECT FROM ABOVE TST NDOWN ANY NTES LEFT DOWN? LBEQ HNOFXX PUNT IF NO TST KREALC IS THE KEYBOARD REALLOCATION ENABLED? BNE HNOFXM CONTINUE IF NOT LDB #-1 STB NTCVAL RESET MONO CVAL LBRA HNOFXX * HNOFXM TST MONOFG MONO MODE? BNE HNOFMN THEN BR... TST SPLTMD SPLIT? BNE HNOF11 THEN BR... TST UNISON UNISON? BEQ HNOF10 BR. IF CLEAR HNOFMN LDB #1 UNISON ON BRA HNOF09 HNOF10 LDB #4 UNISON OFF HNOF09 STB NAVAIL STASH AS # AVAILABLE LDB #TOPNTE STB NFIN STOP SCAN AT TOP CLRB STB NSTRQ STASH FOR SCAN START LDB NDOWN BRA HNOF12 HNOF11 TST UNISON UNISON ON? BEQ HNOF13 BR. IF NOT LDB #1 ONLY 1 V. IF SO BRA HNOF14 HNOF13 LDB SPLTMD UNISON OFF; CALCULATE # V'S CMPB #1 2-2? BNE HNOF15 BR. IF NO INCB 2 V'S AVAIL BRA HNOF14 HNOF15 LDA KEYHLF TST HALF BNE HNOF16 LDA #-1 HNOF16 STA HLFBS CMPB #2 3-1? BNE HNOF17 BR. IF NOT SUBB HLFBS BRA HNOF14 BR. HNOF17 DECB 1-3 ADDB HLFBS HNOF14 STB NAVAIL STASH # AVAIL. LDB #HLFNTE TST KEYHLF BNE HNOF18 BR. ON TOP HLF. STB NFIN STORE TOP CLRB STB NSTRQ STORE START BRA HNOF19 HNOF18 INCB STB NSTRQ STORE START LDB #TOPNTE STB NFIN STORE TOP HNOF19 LDY #NDOWNL LDA KEYHLF LDB A,Y GET #DOWN PER HALF HNOF12 LDA NTEOB0 CMPB NAVAIL #NTS > #AVAIL? BLT HNOFXX BR. IF NOT LDB KPRTY GET PRIO CMPB #2 FST/LST? BGT HNOFFL BR. IF SO CMPB #1 BEQ HNOF20 BR. ON HI PRIO LDB #1 INC. LOW TO HI STB SCNINC LDB NSTRQ BRA HNOF21 HNOF20 LDB #-1 INC. HI TO LOW STB SCNINC LDB NFIN HNOF21 TST B,X IS THIS VALUE ALREADY ON? BGT HNOF23 BR. IF NOT ADDB SCNINC INC COUNTER CMPB NFIN OVER TOP?? BGT HNOFXX THEN PUNT CMPB NSTRQ UNDER BOTTOM?? BGE HNOF21 LOOP IF OK BRA HNOFXX PUNT IF NOT HNOFFL TFR A,B COPY NT# CLR NOVRQ CLEAR OVF. COUNTER HNOF22 DECA STEP POINTERS; FIND NEAREST NT. INCB CMPA NSTRQ UNDER LOW LIMIT? BGE HNOF24 BR. IF OK INC NOVRQ INC. ERROR COUNTER BRA HNOF25 HNOF24 TST A,X TEST LOW NTE BGT HNOF27 BR. IF A CANDIDATE HNOF25 CMPB NFIN OVER HI LIMIT? BLE HNOF26 BR. IF OK TST NOVRQ UNDER LOW LIMIT TOO? BNE HNOFXQ PUNT IF SO BRA HNOF22 LOOP IF NOT HNOF26 TST B,X TEST HIGH NT. BLE HNOF22 LOOP IF NOT A CANDIDATE HNOF23 TFR B,A COPY CANDIDATE INTO A HNOF27 LDB A,X GET VEL. STB VREALC STASH IT PSHU A ADDA TRNPSE STA NREALC STASH TRANSPOSED NT. PULU A CLRB CMPA #HLFNTE WHICH HALF? BLE HNOF28 BR. IF LOW INCB HNOF28 STB KEYHLF SET KEYHALF FLAG INC NTAKEN INC. NO. OF VOICES TAKEN LDY #NTAKNL INC B,Y DITTO PER HALF STA NTCVAL REVISE MONO ALLOCATION LBSR OBNON TURN NT. ON IN OB. LDA NREALC RESTORE IT (W. TRNSPSE) LDB SENDMD CMPB #3 OVERLFOW? BNE HNOFXQ PUNT IF MUTE/NRM LDB #64 GET MID-VEL. LBSR OUTOFF PUT NT-OFF @ OUT HNOFXQ LDA NTEOB0 RESTORE NT# LDX #NLST4V HNOFXX CLRB STB A,X CLEAR KEY TABLE ENTRY HNOFXY TST NDOWN ANY NT. LEFT DOWN? BNE HNOFRF RETURN IF NOT LDB #-1 STB NTCVAL RESET MONO NOTE PRIORITY TST ABTGED A. BND TRIGGERED? BMI HNOFXZ SKIP IF ALREADY DONE BGT HNOFX1 DO IT IF TRIGGERED LDB TGMBND GET TRIGGER MODE BNE HNOFXZ BR. OUT IF NOT "NRM" TST MNHBND BEND ON RLS? BNE HNOFXZ IGNORE IF SO HNOFX1 LBSR ABSET SET IF SO HNOFXZ TST ATTGED A. TRL TRIGGERED? BMI HNOFRF RETURN IF ALREADY DONE BGT HNOFX2 DO IT IF TRIGGERED LDB TGMTRL GET TRIGGER MODE BNE HNOFRF BR. OUT IF NOT "NRM" TST MNHTRL TRL. ON RLS? BNE HNOFRF IFNORE IF SO HNOFX2 LBSR ATSET SET IF SO HNOFRF RTS * PAGE * * NTE-ON TO OUTPUT ROUTINE * A = NT # B = VEL. * OUTON TST SENDMD SEND OFF?? BEQ OUTNRT RETURN IF SO LDX #XLIST LOOK AT CROSS-LIST TST OVFPLY OVERFLOW PLAY ON?? BEQ OUTOV0 BR. IF NO TST A,X HAS THIS ALREADY BEEN CROSSED? BPL OUTOVZ BR. IF NOT PSHS A,B,X STASH VARIABLES LBSR OUTOFF TURN THE NOTE OFF FIRST PULS A,B,X RESTORE VARIABLES OUTOVZ TST LDNOTE ARE WE CURRENTLY RECORDING NOTES? BNE OUTOV0 THEN PLAY THE NOTES THAT ARE INPUT TST NONTE ANY NOTES LOADED IN? BMI OUTOV0 BR. IF NO LBSR OVFALC BR. TO THE OVERFLOW ALLOCATION ROUTINE BRA OUTOVX * OUTOV0 PSHS A ORA #$80 NOTE ON CODE STA A,X PUT NOTE IN ITS OWN POSITION IN XLIST PULS A OUTOVX TST NTETRG NTS ON RLS? BEQ OUTN0 BR. IF NOT TST NQUEQ ANY NTS. QUEUED FOR ON? BNE OUTN0 BR. IF YES TST NONOUT ANY ON @ OUTPUT? BEQ OUTN0 IGNORE IF NOT PSHS A,B LBSR RSTRVR CLEAR NTS. IF ALL TRUE PULS A,B OUTN0 TST DLYTRG ANY MIN. HLD FOR OUTPUT? BEQ OUTON1 SKIP IF NOT LDX #OUTLST STB A,X STASH VEL. IN OUTPUT LST. LDA DLYTRG GET DELAY STA ODLYON SET OUTPUT DELAY FLG. INC NONDLY INC COUNT CMPA #$FF IS DELAY AT MAX.?? BNE OUTNXX BE NORMAL IF NOT TFR A,B ARRANGE A REALLY LONG DELAY IF SO BRA OUTNXY BRANCH OUT OUTNXX LBSR SHFT4 SHIFT LEFT 4 INCB OUTNXY STB TMR2 STORE LSB IN T3 STA TMR2 STORE MSB IN T3 OUTNRT RTS OUTON1 TST NTETRG NTE-ON-RLS? BEQ OUTON2 BR. IF NOT LDX #OUTREV TST A,X IS IT ALREADY QUEUED?? BNE OUTNRT IGNORE IF SO INC NQUEQ INC NT-QUEUED COUNTER STB A,X STASH NT. IN TABLE RTS OUTON2 STA NTEQQQ LDX #OUTLST TST A,X BMI OUTNRT IGNORE IF ALREADY ON STB OUTVLX STASH THE VEL. NEGB STB A,X STORE NEG-VEL. IN OUTLIST NEGB LBSR SDNON SEND THE NT-ON INC NONOUT INC COUNT LDB NVOICE FILL MODE ON? BEQ OUTNRT RETURN IF NOT LDA SENDMD GET SEND MODE CMPA #2 IS IT ECHO? BNE OUTKK2 CONVENTIONAL IF NOT SUBB #4 OTHERWISE ASSUME 4 VCS. LDA UNISON ORA MONOFG BEQ OUTKK1 UNLESS WE ARE IN MONO OR UNISON (1 VC.) ADDB #3 THEN CORRECT... OUTKK1 TSTB BRA OUTKK3 OUTKK2 SUBB NONOUT B = #V - #ON OUTKK3 BLE OUTNRT SKIP IF OVF. DECB CORRECT STB NTOFIL LDA NTEQQQ CLEAR NT. POINTER DECA CORRECT LDY #FILQUE LDX #OUTLST FILLP TST FILLNT FILL NT. TO USE? BEQ FIL01 BR. IF SAME-STEP INCA INCREMENT INDEX BMI FIL0X BR. ON OVF. FIL00 TST A,X NTE ALREADY ON? BPL FIL01 BR. IF CLEAR INCA INC. POINTER TSTA BPL FIL00 LOOP IF OK FIL0X CLRA BRA FIL00 RESET ON OVERFLOW FIL01 STA B,Y STASH IN FILL TABLE PSHU A,B,X,Y STASH ALL USED REGS. LDB OUTVLX USE ORIG. AVEL BSR SDNON JOG A NTE-ON BSR WTAFEW WAIT FOR MIDI CLOGGING (??) PULU A,B,X,Y RESTORE THE REGS. DECB DEC. LOOP CTR. BGE FILLP LOOP IF MORE LEFT TO FILL LDA NTOFIL GET FILL COUNT FIL02 PSHU A,Y STASH LDB A,Y GET NTE# LDA #64 GET MED. RVEL EXG A,B BSR SDNOFF JOG A NT. OFF BSR WTAFEW WAIT FOR MIDI CLOGGING (??) PULU A,Y RESTORE DECA BGE FIL02 CONTINUE UNTIL DONE RTS * WTAFEW TST FILLMD DELAY ON? BEQ WTARTS RETURN IF NOT LDB #150 ROUGHLY 600 MICROSEC WAIT?? WTABCH PSHU B LDB #50 LDA #80 MUL THIS IS THE MAIN DELAY PULU B DECB BNE WTABCH WAIT LOOP WTARTS RTS * * ROUTINE TO CLEAR ALL NOTES ON IN OUTPUT * RSTRVR TST SENDMD PUNT IF SEND OFF BEQ RSTRRN CLRA STA NQUEQ CLEAR QUEUED NTES STA NONDLY CLEAR DELAYED NTES LDY #OUTREV LDX #OUTLST RSTRV0 LDB A,X CHECK ENTRY BEQ RSTRV1 BR. IF EMPTY BGT RSTRV2 BR. IF QUEUED NEGB CORRECT VAL. PSHU A,X,Y STASH LBSR OUTOF1 TURN OFF NTE PULU A,X,Y RESTORE RSTRV1 CLRB STB A,Y CLEAR OUT QUEUED TABLE (REV) INCA TSTA BGT RSTRV0 LOOP... RSTRRN RTS RSTRV2 CLR A,X UN-QUEUE ENTRY BRA RSTRV1 CONTINUE... * * SEND ON * SDNON STD ODATAS LDB #2 STB OCOUNT LDA CHNL1 LDB #MNON GET ON CODE LBRA MDIOUT SHIP IT OUT * * SEND OFF * SDNOFF STD ODATAS LDB #2 STB OCOUNT LDA CHNL1 LDB #MNOFF GET OFF CODE LBRA MDIOUT SHIP IT OUT * * ROUTINE TO REASSIGN NOTES TO TABULATED NOTES * OVFALC: STB OVFVLB STORE VEL STA OVFON STORE NOTE LDA OVFORD LOOK AT TABLE ORDER CLRB CLEAR TABLE TRAVERSAL SIGN * STB SVPQ CLEAR NEGATIVE INDEX FLAG TSTA BNE OUTOV1 BR. IF NOT UP OUTOV4 INCB SET SIGN POSITIVE BRA OUTOV3 OUTOV1 DECA BNE OUTOV2 BR. IF NOT DOWN DECB SET SIGN NEGATIVE BRA OUTOV3 OUTOV2 DECA BNE OUTOV3 BR. IF NOT CIRCULAR LDB OVDIR GET DIRECTION BEQ OUTOV4 MAKE SURE IT'S NONZERO OUTOV3 STB OVDIR ADDB OVIND ADD INDEX INTO DISPLACEMENT DECA BNE OUTOV5 BR. IF NOT #DOWN INCB SET B TO UNITY ADDB NDOWN ADD IN # NOTES DOWN BRA OVFOV7 OUTOV5 DECA BNE OVFOV7 BR. IF NOT MAP LDB OVFON LOAD NOTE FOR MAP OVFOV7 STB OVIND REPLACE INDEX LDA OVFVEL GET VELOCITY COMPONENT BEQ OVFOV8 IGNORE FOLLOWING IF OFF TFR A,B SWAP FOR MULTIPLY LDA OVFVLB GET VEL LSLA MUL SCALE TST OVDIR CHECK DIRECTION BPL OVFOV9 BR. IF NOT NEG. NEGA INVERT RESULT OVFOV9 TFR A,B ADDB OVIND ADD INTO INDEX STB OVIND STASH OVFOV8 LDA OVFORD GET ORDER CMPA #2 CIRCLE?? BNE OVFOVB BR. IF NOT TSTB DID WE UNDERFLOW? BMI OVFOVA BR. IF SO CMPB NONTE ARE WE TOO HIGH? BLE OVFOVB BR. IF NO OVFOVA TST OVDIR TEST DIRECTION BPL OVFOVF BR. IF POS. LDB #1 SET INDEX AT START BRA OVFOVG OVFOVF LDB NONTE START INDEX AT MAX DECB CORRECT OVFOVG NEG OVDIR REVERSE DIRECTION OVFOVB CLR NEGFLG CLEAR FLAG TSTB TEST INDEX BPL OVFOVC BR. IF NO OVERFLOW INCB CORRECT OFFSET NEGB NEGATE TO FORM POSITIVE # INC NEGFLG SET FLAG OVFOVC CMPB NONTE TOO BIG? BLE OVFOVD BR. IF NO SUBB NONTE CORRECT IF TOO BIG DECB BRA OVFOVC OVFOVD TST NEGFLG WHAT DIRECTION? BEQ OVFOVE BR. IF + NEGB INVERT ADDB NONTE GET POINTER OVFOVE STB OVIND REPLACE INDEX LDY #NTETAB POINT AT NOTE TABLE LDA B,Y GET A NOTE ORA #$80 NEGATE IT TO SAY THAT IT'S ON LDB OVFON GET THE ORIGINAL NOTE STA B,X PUT ORIGINAL NOTE ON IN B AS NOTE IN A ANDA #$7F TAKE OFF THE SIGN BIT LDB OVFVLB GET THE VELOCITY RTS * PAGE * * NTE-OFF HANDLER * A = NTE# B = VEL * OUTOFF TST SENDMD MUTE?? BEQ RETCDS RETURN IF SO * TST OVFPLY PLAY THE TABULATED NOTES? * BEQ OUTOFZ BR. IF NOT * TST NONTE ANY LOADED? * BMI OUTOFZ BR. IF NOT LDX #XLIST POINT AT LIST PSHS B LDB A,X GET THE NOTE REFERENCE BPL OUTOFP SKIP IF IT'S ALREADY BEEN TURNED OFF ANDB #$7F PULL OFF SIGN STB A,X REPLACE TABLE ENTRY TFR B,A REPLACE NOTE NUMBER OUTOFP PULS B RESTORE VELOCITY OUTOFZ LDX #OUTLST LDY #OUTREV TST NTETRG BNE OUTFRL BR. IF NO REL. OUTOF1 CLR A,Y CLEAR REV. TABLE ENTRY TST A,X BPL OUTOFX BR. IF ONLY QUEUED CLR A,X CLEAR NTE. TABLE ENTRY DEC NONOUT DEC. ON COUNTER BGT OUTOFW BEQ OUTOFG CLR NONOUT SATURATE ON UNDERFLOW OUTOFG CLR ODLYON OUTOFW LBRA SDNOFF SEND OFF CMD. OUTOFX TST A,X BEQ RETCDS BR. IF DUMMY CALL CLRB STB A,X CLEAR IT OUT DEC NONDLY BMI OUTOFR BGT RETCDS STB ODLYON RETCDS RTS OUTOFR STB NONDLY STB ODLYON RTS * RETCXS TST DLYTRG DELAY ON?? BNE OUTOFX CLEAR IF ENABLED RTS * OUTFRL TST A,Y IS IT QUEUED?? BEQ RETCXS IGNORE IF NOT STB LOCVLO STASH LOC. VEL. LDB NTETRG GET NT. TRIG DECB BNE OUTOF2 BR. IF NORM RLS- LDB A,Y GET AVEL PSHU B LDB LOCVLO GET RVEL STB A,Y STASH IT INTO TABLE PULU B OUTOF3 LBSR OUTON2 SEND NTE-ON DEC NQUEQ DEC QUEUE BGT RETCDS RETURN IF MORE LEFT BEQ OUTOFK BR. IF NO OVF. CLR NQUEQ CLIP IT OUTOFK LDB LSTRVL GET LAST REL. NEGB ADDB #127 FLIP SENSE OF RVEL LDA NTMVLS GET VEL SENS. LSLA LSLA SCALE UP A BIT LSLB MUL ADDA NTETME ADD BIAS BCC OUTOK1 BR. IF NO OV. LDA #$FF SATURATE OUTOK1 LBSR SHFT4 SCALE UP INCB STB TMR2 T3 LSB STA TMR2 T3 MSB CLRA STA ODLYON CLEAR OUTPUT DELAY FLAG RTS OUTOF2 LDB LOCVLO BRA OUTOF3 * PAGE ********************************************************************* * * INTERRUPT VECTORS AT END OF MEMORY * ********************************************************************* * SEG VECTORS SET FOR VECTORS * FDB INTDMY SWI3 TRAP FDB INTDMY SWI2 TRAP FDB MIDISV MIDI INPUT (FIRQ) FDB IRQKEY IRQ MESSAGE ROUTINE FDB MIDISV SWI TRAP FDB KEYSRV KEYPAD INPUT (NMI) FDB RBOOT POWER UP INTERRUPT * END