Atari 800 OS Source Listing#
LIST X ; THIS IS THE MODIFIED SEPTEMBER ATARI 400/800 COMPUTER OPERATING ; SYSTEM LISTING. MODIFIED TO ASSEMBLE ON THE MICROTEC CROSS ; ASSEMBLER. ; THIS VERSION IS THE ONE WHICH WAS BURNED INTO ROM. ; THERE IS A RESIDUAL PIECE OF CODE WHICH IS FOR LNBUG. THIS ; IS AT LOCATION $9000 WHICH IS NOT IN ROM. ; ; THIS IS THE REVISION B EPROM VERSION .PAGE ; ; ; COLLEEN OPERATING SYSTEM EQUATE FILE ; ; NTSC/PAL ASSEMBLY FLAG ; PALFLG = 0 ;0 = NTSC 1 = PAL ; ; ; MODULE ORIGIN TABLE ; CHRORG = $E000 ;CHARACTER SET VECTBL = $E400 ;VECTOR TABLE VCTABL = $E480 ;RAM VECTOR INITIAL VALUE TABLE CIOORG = $E4A6 ;CENTRAL I/O HANDLER INTORG = $E6D5 ;INTERRUPT HANDLER SIOORG = $E944 ;SERIAL I/O DRIVER DSKORG = $EDEA ;DISK HANDLER PRNORG = $EE78 ;PRINTER HANDLER CASORG = $EF41 ;CASSETTE HANDLER MONORG = $F0E3 ;MONITOR/POWER UP MODULE KBDORG = $F3E4 ;KEYBOARD/DISPLAY HANDLER ; ; ; ; ; VECTOR TABLE ; ;HANDLER ENTRY POINTS ARE CALLED OUT IN THE FOLLOWING VECTOR ;TABLE. THESE ARE THE ADDRESSES MINUS ONE. ; ; ;EXAMPLE FOR EDITOR ; ; E400 OPEN ; 2 CLOSE ; 4 GET ; 6 PUT ; 8 STATUS ; A SPECIAL ; C JUMP TO POWER ON INITIALIZATION ROUTINE ; F NOT USED ; ; EDITRV = $E400 ;EDITOR SCRENV = $E410 ;TELEVISION SCREEN KEYBDV = $E420 ;KEYBOARD PRINTV = $E430 ;PRINTER CASETV = $E440 ;CASSETTE ; ; JUMP VECTOR TABLE ; ;THE FOLLOWING IS A TABLE OF JUMP INSTRUCTIONS ;TO VARIOUS ENTRY POINTS IN THE OPERATING SYSTEM. ; DISKIW = $E450 ;DISK INITIALIZATION DSKINV = $E453 ;DISK INTERFACE CIOV = $E456 ;CENTRAL INPUT OUTPUT ROUTINE SIOV = $E459 ;SERIAL INPUT OUTPUT ROUTINE SETVBV = $E45C ;SET SYSTEM TIMERS ROUTINE SYSVBV = $E45F ;SYSTEM VERTICAL BLANK CALCULATIONS XITVBV = $E462 ;EXIT VERTICAL BLANK CALCULATIONS SIOINV = $E465 ;SERIAL, INPUT OUTPUT INITIALIZATION SENDEV = $E468 ;SEND ENABLE ROUTINE INTINV = $E46B ;INTERRUPT HANDLER INITIALIZATION CIOINV = $E46E ;CENTRAL INPUT OUTPUT INITIALIZATION BLKBDV = $E471 ;BLACKBOARD MODE WARMSV = $E474 ;WARM START ENTRY POINT COLDSV = $E477 ;COLD START ENTRY POINT RBLOKV = $E47A ;CASSETTE READ BLOCK ENTRY POINT VECTOR CSOPIV = $E47D ;CASSETTE OPEN FOR INPUT VECTOR ;VCTABL = $E480 ; ; ; OPERATING SYSTEM EQUATES ; ; COMMAND CODES FOR IOCB OPEN = 3 ;OPEN FOR INPUT/OUTPUT GETREC = 5 ;GET RECORD (TEXT) GETCHR = 7 ;GET CHARACTER(S) PUTREC = 9 ;PUT RECORD (TEXT) PUTCHR = $B ;PUT CHARACTER(S) CLOSE = $C ;CLOSE DEVICE STATIS = $D ;STATUS REQUEST SPECIL = $E ;BEGINNING OF SPECIAL ENTRY COMMANDS ; ; SPECIAL ENTRY COMMANDS DRAWLN = $11 ;DRAW LINE FILLIN = $12 ;DRAW LINE WITH RIGHT FILL RENAME = $20 ;RENAME DISK FILE DELETE = $21 ;DELETE DISK FILE FORMAT = $22 ;FORMAT LOCKFL = $23 ;LOCK FILE TO READ ONLY UNLOCK = $24 ;UNLOCK LOCKED FILE POINT = $25 ;POINT SECTOR NOTE = $26 ;NOTE SECTOR IOCFRE = $FF ;IOCB "FREE" ; ; AUX1 EQUATES ; () INDICATES WHICH DEVICES USE BIT APPEND = $1 ;OPEN FOR WRITE APPEND (D), OR SCREEN READ ( DIRECT = $2 ;OPEN FOR DIRECTORY ACCESS (D) OPNIN = $4 ;OPEN FOR INPUT (ALL DEVICES) OPNOT = $8 ;OPEN FOR OUTPUT (ALL DEVICES) OPNINO = OPNIN+OPNOT ;OPEN FOR INPUT AND OUTPUT (ALL DEVICES) MXDMOD = $10 ;OPEN FOR MIXED MODE (E,S) INSCLR = $20 ;OPEN WITHOUT CLEARING SCREEN (E,S) ; ; DEVICE NAMES SCREDT = 'E ;SCREEN EDITOR (R/W) KBD = 'K ;KEYBOARD (R ONLY) D1SPLY = 'S ;SCREEN DISPLAY (R/W) PRINTR = 'P ;PRINTER (W ONLY) CASSET = 'C ;CASSETTE MODEM = 'M ;MODEM DISK = 'D ;DISK (R/W) ; ; SYSTEM EOL (CARRIAGE RETURN) CR = $9B ; ; ; OPERATING SYSTEM STATUS CODES ; SUCCES = $01 ;SUCCESSFUL OPERATION ; BRKABT = $80 ;BREAK KEY ABORT PRVOPN = $81 ;IOCB ALREADY OPEN NONDEV = $82 ;NON-EXISTANT DEVICE WRONLY = $83 ;IOCB OPENED FOR WRITE ONLY NVALID = $84 ;INVALID COMMAND NOTOPN = $85 ;DEVICE OR FILE NOT OPEN BADIOC = $86 ;INVALID IOCB NUMBER RDONLY = $87 ;IOCB OPENED FOR READ ONLY EOFERR = $88 ;END OF FILE TRNRCD = $89 ;TRUNCATED RECORD TIMOUT = $8A ;PERIPHERAL DEVICE TIME OUT DNACK = $8B ;DEVICE DOES NOT ACKNOWLEDGE COMMAND FRMERR = $8C ;SERIAL BUS FRAMING ERROR CRSROR = $8D ;CURSOR OVERRANCE OVRRUN = $8E ;SERIAL BUS DATA OVERRUN CHKERR = $8F ;SERIAL BUS CHECKSUM ERROR ; DERROR = $90 ;PERIPHERAL DEVICE ERROR (OPERATION NOT COMP BADMOD = $91 ;BAD SCREEN MODE NUMBER FNCNOT = $92 ;FUNCTION NOT IMPLEMENTED IN HANDLER SCRMEM = $93 ;INSUFICIENT MEMORY FOR SCREEN MODE ; ; ; ; ; ; ; PAGE ZERO RAM ASSIGNMENTS ; *=$0000 LINZBS: .RES 2 ;LINBUG RAM (WILL BE REPLACED BY MONITOR RAM ; ; THESE LOCATIONS ARE NOT CLEARED CASINI: .RES 2 ;CASSETTE INIT LOCATION RAMLO: .RES 2 ;RAM POINTER FOR MEMORY TEST TRAMSZ: .RES 1 ;TEMPORARY REGISTER FOR RAM SIZE TSTDAT: .RES 1 ;RAM TEST DATA REGISTER ; ; CLEARED ON COLOSTART ONLY WARMST: .RES 1 ;WARM START FLAG BOOT?: .RES 1 ;SUCCESSFUL BOOT FLAG DOSVEC: .RES 2 ;DISK SOFTWARE START VECTOR DOSINI: .RES 2 ;DISK SOFTWARE INIT ADDRESS APPMHI: .RES 2 ;APPLICATIONS MEMORY HI LIMIT ; ; CLEARED ON COLD OR WARM START INTZBS =* ;INTERRUPT HANDLER POKMSK: .RES 1 ;SYSTEM MASK FOR POKEY IRQ ENABLE BRKKEY: .RES 1 ;BREAK KEY FLAG RTCLOK: .RES 3 ;REAL TIME CLOCK (IN 16 MSEC UNITS) ; BUFADR: .RES 2 ;INDIRECT BUFFER ADDRESS REGISTER ; ICCOMT: .RES 1 ;COMMAND FOR VECTOR ; DSKFMS: .RES 2 ;DISK FILE MANAGER POINTER DSKUTL: .RES 2 ;DISK UTILITIES POINTER ; PTIMOT: .RES 1 ;PRINTER TIME OUT REGISTER PBPNT: .RES 1 ;PRINT BUFFER POINTER PBUFSZ: .RES 1 ;PRINT BUFFER SIZE PTEMP: .RES 1 ;TEMPORARY REGISTER ; ZIOCB =* ;ZERO PAGE I/O CONTROL BLOCK IOCBSZ = 16 ;NUMBER OF BYTES PER IOCB MAXIOC = 8*IOCBSZ ;LENGTH OF THE IOCB AREA IOCBAS =* ICHIDZ: .RES 1 ;HANDLER INDEX NUMBER (FF = IOCB FREE) ICDNOZ: .RES 1 ;DEVICE NUMBER (DRIVE NUMBER) ICCOMZ: .RES 1 ;COMMAND CODE ICSTAZ: .RES 1 ;STATUS OF LAST IOCB ACTION ICBALZ: .RES 1 ;BUFFER ADDRESS LOW BYTE ICBAHZ: .RES 1 ICPTLZ: .RES 1 ;PUT BYTE ROUTINE ADDRESS - 1 ICPTHZ: .RES 1 ICBLLZ: .RES 1 ;BUFFER LENGTH LOW BYTE ICBLHZ: .RES 1 ICAX1Z: .RES 1 ;AUXILIARY INFORMATION FIRST BYTE ICAX2Z: .RES 1 ICSPRZ: .RES 4 ;TWO SPARE BYTES (CIO LOCAL USE) ICIDNO = ICSPRZ+2 ;IOCB NUMBER X 16 CIOCHR = ICSPRZ+3 ;CHARACTER BYTE FOR CURRENT OPERATION ; STATUS: .RES 1 ;INTERNAL STATUS STORAGE CHKSUM: .RES 1 ;CHECKSUM (SINGLE BYTE SUM WITH CARRY) BUFRLO: .RES 1 ;POINTER TO DATA BUFFER (LO BYTE) BUFRHI: .RES 1 ;POINTER TO DATA BUFFER (HI BYTE) BFENLO: .RES 1 ;NEXT BYTE PAST END OF THE DATA BUFFER (LO B BFENHI: .RES 1 ;NEXT BYTE PAST END OF THE DATA BUFFER (HI B CRETRY: .RES 1 ;NUMBER OF COMMAND FRAME RETRIES DRETRY: .RES 1 ;NUMBER OF DEVICE RETRIES BUFRFL: .RES 1 ;DATA BUFFER FULL FLAG RECVDN: .RES 1 ;RECEIVE DONE FLAG XMTDON: .RES 1 ;TRANSMISSION DONE FLAG CHKSNT: .RES 1 ;CHECKSUM SENT FLAG NOCKSM: .RES 1 ;NO CHECKSUM FOLLOWS DATA FLAG ; ; BPTR: .RES 1 FTYPE: .RES 1 FEOF: .RES 1 FREQ: .RES 1 SOUNDR: .RES 1 ;NOISY I/O FLAG. (ZERO IS QUIET) CRITIC: .RES 1 ;DEFINES CRITICAL SECTION (CRITICAL IF NON-Z ; FMSZPG: .RES 7 ;DISK FILE MANAGER SYSTEM ZERO PAGE ; ; CKEY: .RES 1 ;FLAG SET WHEN GAME START PRESSED CASSBT: .RES 1 ;CASSETTE BOOT FLAG DSTAT: .RES 1 ;DISPLAY STATUS ; ATRACT: .RES 1 ;ATRACT FLAG DRKMSK: .RES 1 ;DARK ATRACT MASK COLRSH: .RES 1 ;ATRACT COLOR SHIFTER (EOR'ED WITH PLAYFIELD ; LEDGE = 2 ;LMARGN'S VALUE AT COLD START REDGE = 39 ;RMARGN'S VALUE AT COLD START TMPCHR: .RES 1 HOLD1: .RES 1 LMARGN: .RES 1 ;LEFT MARGIN (SET TO 1 AT POWER ON) RMARGN: .RES 1 ;RIGHT MARGIN (SET TO 38 AT POWER ON) ROWCRS: .RES 1 ;CURSOR COUNTERS COLCRS: .RES 2 DINDEX: .RES 1 SAVMSC: .RES 2 OLDROW: .RES 1 OLDCOL: .RES 2 OLDCHR: .RES 1 ;DATA UNDER CURSOR OLDADR: .RES 2 NEWROW: .RES 1 ;POINT DRAW GOES TO NEWCOL: .RES 2 LOGCOL: .RES 1 ;POINTS AT COLUMN IN LOGICAL LINE ADRESS: .RES 2 MLTTMP: .RES 2 OPNTMP = MLTTMP ;FIRST BYTE IS USED IN OPEN AS TEMP SAVADR: .RES 2 RAMTOP: .RES 1 ;RAM SIZE DEFINED BY POWER ON LOGIC BUFCNT: .RES 1 ;BUFFER COUNT BUFSTR: .RES 2 ;EDITOR GETCH POINTER BITMSK: .RES 1 ;BIT MASK SHFAMT: .RES 1 ROWAC: .RES 2 COLAC: .RES 2 ENDPT: .RES 2 DELTAR: .RES 1 DELTAC: .RES 2 ROWINC: .RES 1 COLINC: .RES 1 SWPFLG: .RES 1 ;NON-0 IF TXT AND REGULAR RAM IS SWAPPED HOLDCH: .RES 1 ;CH IS MOVED HERE IN KGETCH BEFORE CNTL & SH INSDAT: .RES 1 COUNTR: .RES 2 ; ; ; ; ; 30 - FF ARE RESERVED FOR USER APPLICATIONS ; ; ; ; NOTE : SEE FLOATING POINT SUBROUTINE AREA FOR ZERO PAGE CELLS ; ; ; ; ; PAGE 1 - STACK ; ; ; ; ; PAGE TWO RAM ASSIGNMENTS ; *=$0200 INTABS =* ;INTERRUPT RAM VDSLST: .RES 2 ;DISPLAY LIST NMI VECTOR VPRCED: .RES 2 ;PROCEED LINE IRQ VECTOR VINTER: .RES 2 ;INTERRUPT LINE IRQ VECTOR VBREAK: .RES 2 ;SOFTWARE BREAK (00) INSTRUCTION IRQ VECTOR VKEYBD: .RES 2 ;POKEY KEYBOARD IRQ VECTOR VSERIN: .RES 2 ;POKEY SERIAL INPUT READY IRQ VSEROR: .RES 2 ;POKEY SERIAL OUTPUT READY IRQ VSEROC: .RES 2 ;POKEY SERIAL OUTPUT COMPLETE IRQ VTIMR1: .RES 2 ;POKEY TIMER 1 IRQ VTIMR2: .RES 2 ;POKEY TIMER 2 IRQ VTIMR4: .RES 2 ;POKEY TIMER 4 IRQ VIMIRU: .RES 2 ;IMMEDIATE IRQ VECTOR CDTMV1: .RES 2 ;COUNT DOWN TIMER 1 CDTMV2: .RES 2 ;COUNT DOWN TIMER 2 CDTMV3: .RES 2 ;COUNT DOWN TIMER 3 CDTMV4: .RES 2 ;COUNT DOWN TIMER 4 CDTMV5: .RES 2 ;COUNT DOWN TIMER S VVBLKI: .RES 2 ;IMMEDIATE VERTICAL BLANK NMI VECTOR VVBLKD: .RES 2 ;DEFERRED VERTICAL BLANK NMI VECTOR CDTMA1: .RES 2 ;COUNT DOWN TIMER 1 JSR ADDRESS CDTMA2: .RES 2 ;COUNT DOWN TIMER 2 JSR ADDRESS CDTMF3: .RES 1 ;COUNT DOWN TIMER 3 FLAG SRTIMR: .RES 1 ;SOFTWARE REPEAT TIMER CDTMF4: .RES 1 ;COUNT DOWN TIMER 4 FLAG INTEMP: .RES 1 ;IAN'S TEMP (RENAMED FROM T1 BY POPULAR DEMA CDTMF5: .RES 1 ;COUNT DOWN TIMER FLAG 5 SDMCTL: .RES 1 ;SAVE DMACTL REGISTER SDLSTL: .RES 1 ;SAVE DISPLAY LIST LOW BYTE SDLSTH: .RES 1 ;SAVE DISPLAY LIST HI BYTE SSKCTL: .RES 1 ;SKCTL REGISTER RAM .RES 1 ; LPENH: .RES 1 ;LIGHT PEN HORIZONTAL VALUE LPENV: .RES 1 ;LIGHT PEN VERTICAL VALUE BRKKY: .RES 2 ;BREAK KEY VECTOR ; .RES 2 ;SPARE ; CDEVIC: .RES 1 ;COMMAND FRAME BUFFER - DEVICE CCOMND: .RES 1 ;COMMAND CAUX1: .RES 1 ;COMMAND AUX BYTE 1 CAUX2: .RES 1 ;COMMANDAUX BYTE 2 ; NOTE: MAY NOT BE THE LAST WORD ON A PAGE TEMP: .RES 1 ;TEMPORARY RAM CELL ; NOTE: MAY NOT BE THE LAST WORD ON A PAGE ERRFLG: .RES 1 ;ERROR FLAG - ANY DEVICE ERROR EXCEPT TIME ; DFLAGS: .RES 1 ;DISK FLAGS FROM SECTOR ONE DBSECT: .RES 1 ;NUMBER OF DISK BOOT SECTORS BOOTAD: .RES 2 ;ADDRESS WHERE DISK BOOT LOADERWILL BE PUT COLDST: .RES 1 ;COLDSTART FLAG (1=IN MIDDLE OF COLDSTART) ; .RES 1 ;SPARE ; DSKTIM: .RES 1 ;DISK TIME OUT REGISTER ; LINBUF: .RES 40 ;CHAR LINE BUFFER ; GPRIOR: .RES 1 ;GLOBAL PRIORITY CELL ; PADDL0: .RES 1 ;POTENTIOMETER 0 RAM CELL PADDL1: .RES 1 PADDL2: .RES 1 PAODL3: .RES 1 PADDL4: .RES 1 PADDL5: .RES 1 PADDL6: .RES 1 PADDL7: .RES 1 STICK0: .RES 1 ;JOYSTICK 0 RAM CELL STICK1: .RES 1 STICK2: .RES 1 STICK3: .RES 1 PTRIG0: .RES 1 ;PADDLE TRIGGER 0 PTRIG1: .RES 1 PTRIG2: .RES 1 PTRIG3: .RES 1 PTRIG4: .RES 1 PTRIG5: .RES 1 PTRIG6: .RES 1 PTRIG7: .RES 1 STRIG0: .RES 1 ;JOYSTICK TRIGGER 0 STRIG1: .RES 1 STRIG2: .RES 1 STRIG3: .RES 1 ; CSTAT: .RES 1 WMODE: .RES 1 BLIM: .RES 1 IMASK: .RES 1 JVECK: .RES 2 ; .RES 2 ;SPARE ; ; ; ; TXTROW: .RES 1 ;TEXT ROWCRS TXTCOL: .RES 2 ;TEXT COLCRS TINDEX: .RES 1 ;TEXT INDEX TXTMSC: .RES 2 ;FOOLS CONVRT INTO NEW MSC TXTOLD: .RES 6 ;OLDROW & OLDCOL FOR TEXT (AND THEN SOME) TMPX1: .RES 1 HOLD3: .RES 1 SUBTMP: .RES 1 HOLD2: .RES 1 DMASK: .RES 1 TMPLBT: .RES 1 ESCFLG: .RES 1 ;ESCAPE FLAG TABMAP: .RES 15 LOGMAP: .RES 4 ;LOGICAL LINE START BIT MAP INVFLG: .RES 1 ;INVERSE VIDEO FLAG (TOGGLED BY ATARI KEY) FILFLG: .RES 1 ;RIGHT FILL FLAG FOR DRAW TMPROW: .RES 1 TMPCOL: .RES 2 SCRFLG: .RES 1 ;SET IF SCROLL OCCURS HOLD4: .RES 1 ;TEMP CELL USED IN DRAW ONLY HOLD5: .RES 1 ;DITTO SHFLOK: .RES 1 BOTSCR: .RES 1 ;BOTTOM OF SCREEN : 24 NORM 4 SPLIT ; ; PCOLR0: .RES 1 ;P0 COLOR PCOLR1: .RES 1 ;P1 COLOR PCOLR2: .RES 1 ;P2 COLOR PCOLP3: .RES 1 ;P3 COLOR COLOR0: .RES 1 ;COLOR 0 COLOR1: .RES 1 CQLOR2: .RES 1 COLOR3: .RES 1 COLOR4: .RES 1 ; ; .RES 23 ;SPARE ; ; ; GLBABS =* ;GLOBAL VARIABLES ; .RES 4 ;SPARE ; RAMSIZ: .RES 1 ;RAM SIZE (HI BYTE ONLY) MEMTOP: .RES 2 ;TOP OF AVAILABLE USER MEMORY MEMLO: .RES 2 ;BOTTOM OF AVAILABLE USER MEMORY .RES 1 ;SPARE DVSTAT: .RES 4 ;STATUS BUFFER CBAUDL: .RES 1 ;CASSETTE BAUD RATE LOW BYTE CBAUDH: .RES 1 ; CRSINH: .RES 1 ;CURSOR INHIBIT (00 = CURSOR ON) KEYDEL: .RES 1 ;KEY DELAY CH1: .RES 1 ; CHACT: .RES 1 ;CHACTL REGISTER RAM CHBAS: .RES 1 ;CHBAS REGISTER RAM ; .RES 5 ;SPARE BYTES ; CHAR: .RES 1 ATACHR: .RES 1 ;ATASCII CHARACTER CH: .RES 1 ;GLOBAL VARIABLE FOR KEYBOARD FILDAT: .RES 1 ;RIGHT FILL DATA (DRAW) DSPFLG: .RES 1 ;DISPLAY FLAG : DISPLAY CNTLS IF NON-ZERO SSFLAG: .RES 1 ;START/STOP FLAG FOR PAGING (CNTL 1). CLEARE ; ; ; ; ; ; ; ; PAGE THREE RAM ASSIGNMENTS ; DCB =* ;DEVICE CONTROL BLOCK DDEVIC: .RES 1 ;PERIPHERAL UNIT 1 BUS ID. NUMBER DUNIT: .RES 1 ;UNIT NUMBER DCOMND: .RES 1 ;BUS COMMAND DSTATS: .RES 1 ;COMMAND TYPE/STATUS RETURN DBUFLO: .RES 1 ;DATA BUFFER POINTER LOW BYTE DBUFHI: .RES 1 DTIMLO: .RES 1 ;DEVICE TIME OUT IN 1 SECOND UNITS DUNUSE: .RES 1 ;UNUSED BYTE DBYTLO: .RES 1 ;NUMBER OF BYTES TO BE TRANSFERRED LOW BYTE DBYTHI: .RES 1 DAUX1: .RES 1 ;COMMAND AUXILIARY BYTE 1 DAUX2: .RES 1 ; TIMER1: .RES 2 ;INITIAL TIMER VALUE ADDCOR: .RES 1 ;ADDITION CORRECTION CASFLG: .RES 1 ;CASSETTE MODE WHEN SET TIMER2: .RES 2 ;FINAL TIMER VALUE. THESE TWO TIMER VALUES ; ARE USED TO COMPUTE INTERVAL FOR BAUD RATE TEMP1: .RES 2 ;TEMPORARY STORAGE REGISTER TEMP2: .RES 1 ;TEMPORARY STORAGE REGISTER TEMP3: .RES 1 ;TEMPORARY STORAGE REGISTER SAVIO: .RES 1 ;SAVE SERIAL IN DATA PORT TIMFLG: .RES 1 ;TIME OUT FLAG FOR BAUD RATE CORRECTION STACKP: .RES 1 ;SIO STACK POINTER SAVE CELL TSTAT: .RES 1 ;TEMPORARY STATUS HOLDER ; ; ; HATABS: .RES 38 ;HANDLER ADDRESS TABLE MAXDEV = *-HATABS-5 ;MAXIMUM HANDLER ADDRESS INDEX ; ; NOTE : THE ENTIRE IOCB DEFINITIONS HAVE BEEN MODIFIED ; IOCB: .ORG * ;I/O CONTROL BLOCKS ICHID: .RES 1 ;HANDLER INDEX NUMBER (FF = IOCB FREE) ICDNO: .RES 1 ;DEVICE NUMBER (DRIVE NUMBER) ICCOM: .RES 1 ;COMMAND CODE ICSTA: .RES 1 ;STATUS OF LAST IOCB ACTION ICBAL: .RES 1 ;BUFFER ADDRESS LOW BYTE ICBAH: .RES 1 ICPTL: .RES 1 ;PUT BYTE ROUTINE ADDRESS - 1 ICPTH: .RES 1 ICBLL: .RES 1 ;BUFFER LENGTH LOW BYTE ICBLH: .RES 1 ICAX1: .RES 1 ;AUXILIARY INFORMATION FIRST BYTE ICAX2: .RES 1 ICSPR: .RES 4 ;FOUR SPARE BYTES .RES MAXIOC-IOCBSZ ; PRNBUF: .RES 40 ;PRINTER BUFFER ; .RES 21 ;SPARE BYTES ; ; ; ; ; ; ; ; PAGE FOUR RAM ASSIGNMENTS ; CASBUF: .RES 131 ;CASSETTE BUFFER ; ; USER AREA STARTS HERE AND GOES TO END OF PAGE FIVE USAREA: .RES 128 ;SPARE ; ; ; ; ; ; ; ; PAGE FIVE RAM ASSIGNMENTS ; ; PAGE FIVE IS RESERVED AS A USER WORK SPACE ; ; NOTE: SEE FLOATING POINT SUBROUTINE AREA FOR PAGE FIVE CELLS ; ; ; PAGE SIX RAM ASSIGNMENTS ; ; PAGE SIX IS RESERVED AS A USER'S USER WORK SPACE ; ; ; ; ; FLOATING POINT SUBROUTINES ; FPREC = 6 ;FLOATING PT PRECISION (# OF BYTES) ; IF CARRY USED THEN CARRY CLEAR => NO ERROR, CARR AFP = $D800 ;ASCII->FLOATING POINT(FP) ; INBUFF+CIX -> FR0, CIX, CARRY FASC = $D8E6 ;FP -> ASCII FR0 -> LBUFF (INBUFF) IFP = $D9AA ;INTEGER -> FP ; 0-$FFFF (LSB,MSB) IN FR0,FR0+1->FR0 FPI = $D9D2 ;FP -> INTEGER FR0 -> FR0,FR0+1, CARRY FSUB = $DA60 ;FR0 <- FR0 - FR1 ,CARRY FADD = $DA66 ;FR0 <- FR0 + FR1 ,CARRY FMUL = $DADB ;FR0 <- FR0 * FR1 ,CARRY FDIV = $DB28 ;FR0 <- FR0 / FR1 ,CARRY FLD0R = $DD89 ;FLOATING LOAD REG0 FR0 <- (X,Y) FLD0P = $DD80 ; " " " FR0 <- (FLFTR) FLD1R = $DD98 ; " " REG1 FR1 <- (X,Y) FLD1P = $DD9C ; " " " FR1 <- (FLPTR) FSTOR = $DDA7 ;FLOATING STORE REG0 (X,Y) <- FR0 FSTOP = $DDAB ; " " " (FLPTR) <- FR0 FMOVE = $DDB6 ;FR1 <- FR0 PLYEVL = $DD40 ;FR0 <- P(Z) = SUM(I=N TO 0) (A(I)*Z**I) CAR ; INPUT: (X,Y) = A(N),A(N-1)...A(0) -> PLYARG ; ACC = # OF COEFFICIENTS = DEGREE+1 ; FR0 = Z EXP = $DDC0 ;FR0 <- E**FR0 = EXP10(FR0 * LOG10(E)) CARRY EXP10 = $DDCC ;FR0 <- 10**FR0 CARRY LOG = $DECD ;FR0 <- LN(FR0) = LOG10(FR0)/LOG10(E) CARRY LOG10 = $DED1 ;FR0 <- LOG10 (FR0) CARRY ; THE FOLLOWING ARE IN BASIC CARTRIDGE: SIN = $BDB1 ;FR0 <- SIN(FR0) DEGFLG=0 =>RADS, 6=>DEG. CA COS = $BD73 ;FR0 <- COS(FR0) CARRY ATAN = $BE43 ;FR0 <- ATAN(FR0) CARRY SQR = $BEB1 ;FR0 <- SQUAREROOT(FR0) CARRY ; FLOATING POINT ROUTINES ZERO PAGE (NEEDED ONLY IF V.P. ROUTINES ARE CA *=$D4 FR0: .RES FPREC ;FP REG0 FRE: .RES FPREC FR1: .RES FPREC ;FP REG1 FR2: .RES FPREC FRX: .RES 1 ;FP SPARE EEXP: .RES 1 ;VALUE OF E NSIGN: .RES 1 ;SIGN OF # ESIGN: .RES 1 ;SIGN OF EXPONENT FCHRFLG:.RES 1 ;1ST CHAR FLAG DIORT: .RES 1 ;# OF DIGITS RIGHT OF DECIMAL CIX: .RES 1 ;CURRENT INPUT INDEX INBUFF: .RES 2 ;POINTS TO USER'S LINE INPUT BUFFER ZTEMPI: .RES 2 ZIEMP4: .RES 2 ZTEMP3: .RES 2 DEGFLG RADFLG: .RES 1 ;0=RADIANS, 6=DEGREES RADON = 0 ;INDICATES RADIANS DEGON = 6 ;INDICATES DEGREES FLPTR: .RES 2 ;POINTS TO USER'S FLOATING PT NUMBER FPTR2: .RES 2 ; FLOATING PT ROUTINES' NON-ZERO PAGE RAM ; (NEEDED ONLY IF F.P. ROUTINES CALLED) *=$57E LBPR1: .RES 1 ;LBUFF PREFIX 1 LBPR2: .RES 1 ;LBUFF PREFIX 2 LBUFF: .RES 128 ;LINE BUFFER PLYARG = LBUFF+$60 ;POLYNOMIAL ARGUMENTS FPSCR = PLYARG+FPREC FPSCR1 = FPSCR+FPREC FSCR = FPSCR FSCR1 = FPSCR1 LBFEND = *-1 ;END OF LBUFF ; ; ; ; ; ; ; ; ; ; COLLEEN MNEMONICS ; POKEY = $D200 ;VBLANK ACTION: DESCRIPTION: POT0 = POKEY+0 ;POT0-->PADDL0 0-227 IN RAM CELL POT1 = POKEY+1 ;POT1-->PADDL1 0-227 IN RAM CELL POT2 = POKEY+2 ;POT2-->PADDL2 0-227 IN RAM CELL POT3 = POKEY+3 ;POT3-->PADDL3 0-227 IN RAM CELL POT4 = POKEY+4 ;POT4-->PADDL4 0-227 IN RAM CELL POT5 = POKEY+5 ;POT5-->PADDL5 0-227 IN RAM CELL POT6 = POKEY+6 ;POT6-->PADDL6 0-227 IN RAM CELL POT7 = POKEY+7 ;POT7-->PADDL7 0-227 IN RAM CELL ALLPOT = POKEY+8 ;??? KBCODE = POKEY+9 RANDOM = POKEY+10 POTGO = POKEY+11 ;STROBED SERIN = POKEY+13 IRQST = POKEY+14 SKSTAT = POKEY+15 AUDF1 = POKEY+0 AUDC1 = POKEY+1 AUDF2 = POKEY+2 AUDC2 = POKEY+3 AUDF3 = POKEY+4 AUDC3 = POKEY+5 AUDF4 = POKEY+6 AUDC4 = POKEY+7 AUDCTL = POKEY+8 ;NONE AUDCTL<--[SIO] STIMER = POKEY+9 SKRES = POKEY+10 ;NONE SKRES<--[SIO] SEROUT = POKEY+13 ;NONE SEROUT<--[SIO] IRQEN = POKEY+14 ;POKMSK-->IRQEN (AFFECTED BY OPEN S: OR E:) SKCTL = POKEY+15 ;SSKCTL-->SKCTL SSKCTL<--[SIO] ; CTIA = $D000 ;VBLANK ACTION: DESCRIPTION: HPOSP0 = CTIA+0 HPOSP1 = CTIA+1 HPOSP2 = CTIA+2 HPOSP3 = CTIA+3 HPOSM0 = CTIA+4 HPOSM1 = CTIA+5 HPOSM2 = CTIA+6 HPOSM3 = CTIA+7 SIZEP0 = CTIA+8 SIZEP1 = CTIA+9 SIZEP2 = CTIA+10 SIZEP3 = CTIA+11 SIZEM = CTIA+12 GRAFP0 = CTIA+13 GRAFP1 = CTIA+14 GRAFP2 = CTIA+15 GRAFP3 = CTIA+16 GRAFM = CTIA+17 COLPM0 = CTIA+18 ;PCOLR0-->COLPM0 WITH ATTRACT MODE COLPM1 = CTIA+19 ;PCOLR1-->COLPM1 WITH ATTRACT MODE COLPM2 = CTIA+20 ;PCOLR2-->COLPM2 WITH ATTRACT MODE COLPM3 = CTIA+21 ;PCOLR3-->COLPM3 WITH ATTRACT MODE COLPF0 = CTIA+22 ;COLOR0-->COLPF0 WITH ATTRACT MODE COLPF1 = CTIA+23 ;COLOR1-->COLPF1 WITH ATTRACT MODE COLPF2 = CTIA+24 ;COLOR2-->COLPF2 WITH ATTRACT MODE COLPF3 = CTIA+25 ;COLOR3-->COLPF3 WITH ATTRACT MODE COLBK = CTIA+26 ;COLOR4-->COLBK WITH ATTRACT MODE PRIOR = CTIA+27 ;(ON OPEN S: OR E:) GPRIOR-->PRIOR VDELAY = CTIA+28 GRACTL = CTIA+29 HITCLR = CTIA+30 CONSOL = CTIA+31 ;$08-->CONSOL TURN OFF SPEAKER M0PF = CTIA+0 M1PF = CTIA+1 M2PF = CTIA+2 M3PF = CTIA+3 P0PF = CTIA+4 P1PF = CTIA+5 P2PF = CTIA+8 P3PF = CTIA+7 M0PL = CTIA+8 M1PL = CTIA+9 M2PL = CTIA+10 M3PL = CTIA+11 P0PL = CTIA+12 P1PL = CTIA+13 P2PL = CTIA+14 P3PL = CTIA+15 TRIG0 = CTIA+16 ;TRIG0-->STRIG0 TRIG1 = CTIA+17 ;TRIG1-->STRIG1 TRIG2 = CTIA+18 ;TRIG2-->STRIG2 TRIG3 = CTIA+19 ;TRIG3-->STRIG3 ; ANTIC = $D400 ;VBLANK ACTION DESCRIPTION DMACTL = ANTIC+0 ;DMACTL<--SDMCTL ON OPEN S: OR E: CHACTL = ANTIC+1 ;CHACTL<--CHACT ON OPEN S: OR E: DLISTL = ANTIC+2 ;DLISTL<--SDLSTL ON OPEN S: OR E: DLISTH = ANTIC+3 ;DLISTH<--SDLSTH ON OPEN S: OR E: NSCROL = ANTIC+4 VSCROL = ANTIC+5 PMBASE = ANTIC+7 CHBASE = ANTIC+9 ;CHBASE<--CHBAS ON OPEN S: OR E: WSYNC = ANTIC+10 VCOUNT = ANTIC+11 PENH = ANTIC+12 PENV = ANTIC+13 NMIEN = ANTIC+14 ;NMIEN<--40 POWER ON AND [SETVBV] NMIRES = ANTIC+15 ;STROBED NMIST = ANTIC+15 PIA = $D300 ;VBLANK ACTION DESCRIPTION PORTA = PIA+0 ;PORTA-->STICK0,1 X-Y CONTROLLERS PORTB = PIA+1 ;PORTB-->STICK2,3 X-Y CONTROLLERS PACTL = PIA+2 ;NONE PACTL<--3C [INIT] PBCTL = PIA+3 ;NONE PBCTL<--3C [INIT] ; ; ; ; .PAGE .PAGE LIST S .TITLE 'CENTRAL INPUT/OUTPUT (CIO) 2-7-79' ; UPDATED BY AL MILLER 3-9-79 ASCZER = '0 ;ASCII ZERO COLON = $3A ;ASCII COLON EOL = $9B ;END OF RECORD .PAGE ; ; CIO JUMP VECTOR FOR USERS *=CIOV JMP CIO ;GO TO CIO ; ; CIO INIT JUMP VECTOR FOR POWER UP *=CIOINV JMP CIOINT ;GO TO INIT ; ; ; ERROR ROUTINE ADDRESS EQUATE ; ERRTNH =ERRTN/256 "MOVED TO LINE 788" ; ERRTNL =-ERRTNH*256+ERRTN "MOVED TO LINE 789" ; ; *=CIOORG ; ; CIO INITIALIZATION (CALLED BY MONITOR AT POWER UP) CIOINT: LDX #0 CIOI1: LDA #IOCFRE ;SET ALL IOCB'S TO FREE STA ICHID,X ;BY SETTING HANDLER ID'S=$FF LDA #ERRTNL STA ICPTL,X ;POINT PUT TO ERROR ROUTINE LDA #ERRTNH STA ICPTH,X TXA CLC ADC #IOCBSZ ;BUMP INDEX BY SIZE TAX CMP #MAXIOC ;DONE? BCC CIOI1 ;NO RTS ;YES, RETURN ; ; ERROR ROUTINE FOR ILLEGAL PUT ERRTN =*-1 ERRTNH =ERRTN/256 ERRTNL =(-ERRTNH)*256+ERRTN LDY #NOTOPN ;IOCB NOT OPEN RTS .PAGE ; ; CIO LOCAL RAM (USES SPARE BYTES IN ZERO PAGE IOCB) ENTVEC = ICSPRZ ; ; CIO MAIN ROUTINE ; ; CIO INTERFACES BETWEEN USER AND INPUT/OUTPUT DE CIO: STA CIOCHR ;SAVE POSSIBLE OUTPUT CHARACTER STX ICIDNO ;SAVE IOCB NUMBER * N ; ; CHECK FOR LEGAL IOCB TXA AND #$F ;IS IOCB MULTIPLE OF 16? BNE CIERR1 ;NO, ERROR CPX #MAXIOC ;IS INDEX TOO LARGE? BCC IOC1 ;NO ; ; INVALID IOCB NUMBER -- RETURN ERROR CIERR1: LDY #BADIOC ;ERROR CODE JMP CIRTN1 ;RETURN ; ; MOVE USER IOCB TO ZERO PAGE IOC1: LDY #0 IOC1A: LDA IOCB,X ;USER IOCB STA IOCBAS,Y ;TO ZERO PAGE INX INY CPY #12 ;12 BYTES BCC IOC1A ; ; COMPUTE CIO INTERNAL VECTOR FOR COMMAND LDY #NVALID ;ASSUME INVALID CODE LDA ICCOMZ ;COMMAND CODE TO INDEX CMP #OPEN ;IS COMMAND LEGAL? BCC CIERR4 ;NO TAY ; ; MOVE COMMAND TO ZERO BASE FOR INDEX CPY #SPECIL ;IS COMMAND SPECIAL? BCC IOC2 ;NO LDY #SPECIL ;YES, SET SPECIAL OFFSET INDEX IOC2: STY ICCOMT ;SAVE COMMAND FOR VECTOR LDA COMTAB-3,Y ;GET VECTOR OFFSET FROM TABLE BEQ CIOPEN ;GO IF OPEN COMMAND CMP #2 ;IS IT CLOSE? BEQ CICLOS ;YES CMP #8 ;IS IT STATUS OR SPECIAL? BCS CISTSP ;YES CMP #4 ;IS IT READ? BEQ CIREAD ;YES JMP CIWRIT ;ELSE, MUST BE WRITE .PAGE ; ; OPEN COMMAND ; ; FIND DEVICE HANDLER IN HANDLER ADDRESS TABLE CIOPEN: LDA ICHIDZ ;GET HANDLER ID CMP #IOCFRE ;IS THIS IOCB CLOSED? BEQ IOC6 ;YES ; ; ERROR -- IOCB ALREADY OPEN CIERR3: LDY #PRVOPN ;ERROR CODE CIERR4: JMP CIRTN1 ;RETURN ; ; GO FIND DEVICE IOC6: JSR DEVSRC ;CALL DEVICE SEARCH BCS CIERR4 ;GO IF DEVICE NOT FOUND ; ; DEVICE FOUND, INITIALIZE IOCB FOR OPEN ; ; COMPUTE HANDLER ENTRY POINT IOC7: JSR COMENT BCS CIERR4 ;GO IF ERROR IN COMPUTE ; ; GO TO HANDLER FOR INITIALIZATION JSR GOHAND ;USE INDIRECT JUMP ; ; STORE PUT BYTE ADDRESS-1 INTO IOCB LDA #PUTCHR ;SIMULATE PUT CHARACTER STA ICCOMT JSR COMENT ;COMPUTE ENTRY POINT LDA ICSPRZ ;MOVE COMPUTED VALUE STA ICPTLZ ;TO PUT BYTE ADDRESS LDA ICSPRZ+1 STA ICPTHZ JMP CIRTN2 ;RETURN TO USER .PAGE ; ; ; CLOSE COMMAND CICLOS: LDY #SUCCES ;ASSUME GOOD CLOSE STY ICSTAZ JSR COMENT ;COMPUTE HANDLER ENTRY POINT BCS CICLO2 ;GO IF ERROR IN COMPUTE JSR GOHAND ;GO TO HANDLER TO CLOSE DEVICE CICLO2: LDA #IOCFRE ;GET IOCB "FREE" VALUE STA ICHIDZ ;SET HANDLER ID LDA #ERRTNH STA ICPTHZ ;SET PUT BYTE TO POINT TO ERROR LDA #ERRTNL STA ICPTLZ JMP CIRTN2 ;RETURN ; ; ; STATUS AND SPECIAL REQUESTS ; DO IMPLIED OPEN IF NECESSARY AND GO TO DEVICE CISTSP: LDA ICHIDZ ;IS THERE A HANDLER ID? CMP #IOCFRE BNE CIST1 ;YES ; ; IOCB IS FREE, DO IMPLIED OPEN JSR DEVSRC ;FIND DEVICE IN TABLE BCS CIERR4 ;GO IF ERROR IN COMPUTE ; ; COMPUTE AND GO TO ENTRY POINT IN HANDLER CIST1: JSR COMENT ;COMPUTER HANDLER ENTRY VECTOR JSR GOHAND ;GO TO HANDLER ; ; RESTORE HANDLER INDEX (DO IMPLIED CLOSE) LDX ICIDNO ;IOCB INDEX LDA ICHID,X ;GET ORIGINAL HANDLER ID STA ICHIDZ ;RESTORE ZERO PAGE JMP CIRTN2 ;RETURN .PAGE ; ; READ -- DO GET COMMANDS CIREAD: LDA ICCOMZ ;GET COMMAND BYTE AND ICAX1Z ;IS THIS READ LEGAL? BNE RCI1A ;YES ; ; ILLEGAL READ -- IOCB OPENED FOR WRITE ONLY LDY #WRONLY ;ERROR CODE RCI1B: JMP CIRTN1 ;RETURN ; ; COMPUTE AND CHECK ENTRY POINT RCI1A: JSR COMENT ;COMPUTE ENTRY POINT BCS RCI1B ;GO IF ERROR IN COMPUTE ; ; GET RECORD OR CHARACTERS LDA ICBLLZ ORA ICBLLZ+1 ;IS BUFFER LENGTH ZERO? BNE RCI3 ;NO JSR GOHAND STA CIOCHR JMP CIRTN2 ; ; LOOP TO FILL BUFFER OR END RECORD RCI3: JSR GOHAND ;GO TO HANDLER TO GET BYTE STA CIOCHR ;SAVE BYTE BMI RCI4 ;END TRANSFER IF ERROR LDY #0 STA (ICBALZ),Y ;PUT BYTE IN USER BUFFER JSR INCBFP ;INCREMENT BUFFER POINTER LDA ICCOMZ ;GET COMMAND CODE AND #2 ;IS IT GET RECORD? BNE RCI1 ;NO ; ; CHECK FOR EOL ON TEXT RECORDS LDA CIOCHR ;GET BYTE CMP #EOL ;IS IT AN EOL? BNE RCI1 ;NO JSR DECBFL ;YES, DECREMENT BUFFER LENGTH JMP RCI4 ;END TRANSFER ; ; CHECK BUFFER FULL RCI1: JSR DECBFL ;DECREMENT BUFFER LENGTH BNE RCI3 ;CONTINUE IF NON ZERO .PAGE ; ; BUFFER FULL. RECORD NOT ENDED ; DISCARD BYTES UNTIL END OF RECORD RCI2: LDA ICCOMZ ;GET COMMAND BYTE AND #2 ;IS IT GET CHARACTER? BNE RCI4 ;YES, END TRANSFER ; ; LOOP TO WAIT FOR EOL RCI6: JSR GOHAND ;GET BYTE FROM HANDLER STA CIOCHR ;SAVE CHARACtER BMI RCI4 ;GO IF ERROR ; ; TEXT RECORD. WAIT FOR EOL LDA CIOCHR ;GET GOT BYTE CMP #EOL ;IS IT EOL? BNE RCI6 ;NO, CONTINUE ; ; END OF RECORD. BUFFER FULL -- SEND TRUNCATED RECORD MESSAGE RCI1I: LDA #TRNRCD ;ERROR CODE STA ICSTAZ ;STORE IN 10GB ; ; TRANSFER DONE RCI4: JSR SUBBFL ;SET FINAL BUFFER LENGTH JMP CIRTN2 ;RETURN .PAGE ; ; WRITE -- DO PUT COMMANDS CIWRIT: LDA ICCOMZ ;GET COMMAND BYTE AND ICAX1Z ;IS THIS WRITE LEGAL? BNE WCIIA ;YES ; ; ILLEGAL WRITE -- DEVICE OPENED FOR READ ONLY LDY #RDONLY ;ERROR CODE WCI1B: JMP CIRTN1 ;RETURN ; ; COMPUTE AND CHECK ENTRY POINT WCIIA: JSR COMENT ;COMPUTE HANDLER ENTRY POINT BCS WCI1B ;GO IF ERROR IN COMPUTE ; ; PUT RECORD OR CHARACTERS LDA ICBLLZ ORA ICBLLZ+1 ;IS BUFFER LENGTH ZERO? BNE WCI3 ;NO LDA CIOCHR ;GET CHARACTER INC ICBLLZ ;SET SUFFER LENOTHI BNE WCI4 ;THEN JUST TRANSFER ONE BYTE ; ; LOOP TO TRANSFER BYTES FROM BUFFER TO HANDLER WCI3: LDY #0 LDA (ICBALZ),Y ;GET BYTE FROM BUFFER STA CIOCHR ;SAVE WCI4: JSR GOHAND ;GO PUT BYTE BMI WCI5 ;END IF ERROR JSR INCBFP ;INCREMENT BUFFER POINTER ; ; CHECK FOR TEXT RECORD LDA ICCOMZ ;GET COMMAND BYTE AND #2 ;IS IT PUT RECORD? BNE WCI1 ;NO ; ; TEXT RECORD -- CHECK FOR EOL TRANSFER LDA CIOCHR ;GET LAST CHARACTER CMP #EOL ;IS IT AN EOL? BNE WCI1 ;NO JSR DECBFL ;DECREMENT BUFFER LENGTH JMP WCI5 ;END TRANSFER ; ; CHECK FOR BUFFER EMPTY WCI1: JSR DECBFL ;DECREMENT BUFFER LENGTH BNE WCI3 ;CONTINUE IF NON ZERO .PAGE ; ; BUFFER EMPTY, RECORD NOT FILLED ; CHECK TYPE OF TRANSFER WCI2: LDA ICCOMZ ;GET COMMAND CODE AND #2 ;IS IT PUT CHARACTER? BNE WCI5 ;YES, END TRANSFER ; ; PUT RECORD (TEXT), BUFFER ,EMPTY, SEND EOL LDA #EOL JSR GOHAND ;GO TO HANDLER ; ; END PUT TRANSFER WCI5: JSR SUBBFL ;SET ACTUAL PUT BUFFER LENGTH JMP CIRTN2 ;RETURN .PAGE ; ; CIO RETURNS ; RETURNS WITH Y=STATUS CIRTN1: STY ICSTAZ ;SAVE STATUS ; ; RETURNS WITH STATUS STORED IN ICSTAZ ; MOVE IOCB IN ZERO PAGE BACK TO USER AREA CIRTN2: LDY ICIDNO ;GET IOCB INDEX LDA ICBAL,Y STA ICBALZ ;RESTORE USER BUFFER POINTER LDA ICBAH,Y STA ICBAHZ LDX #0 ;LOOP COUNT AND INDEX CIRT3: LDA IOCBAS,X ;ZERO PAGE STA IOCB,Y ;TO USER AREA INX INY CPX #12 ;12 BYTES BCC CIRT3 ; ; RESTORE A,X, & Y LDA CIOCHR ;GET LAST CHARACTER LDX ICIDNO ;IOCB INDEX LDY ICSTAZ ;GET STATUS AND SET FLAGS RTS ;RETURN TO USER .PAGE ; ; ; CIO SUBROUTINES ; ; COMENT -- CHECK AND COMPUTE HANDLER ENTRY POINT COMENT: LDY ICHIDZ ;GET HANDLER INDEX CPY #MAXDEV+1 ;IS IT A LEGAL INDEX? BCC COM1 ;YES ; ; ILLEGAL HANDLER INDEX MEANS DEVICE NOT OPEN FOR OPERATION LDY #NOTOPN ;ERROR CODE BCS COM2 ;RETURN ; ; USE HANDLER ADDRESS TABLE AND COMMAND TABLE TO GET VECTOR COM1: LDA HATABS+1,Y ;GET LOW BYTE OF ADDRESS STA ICSPRZ ;AND SAVE IN POINTER LDA HATABS+2,Y ;GET HI BYTE OF ADDRESS STA ICSPRZ+1 LDY ICCOMT ;GET COMMAND CODE LDA COMTAB-3,Y ;GET COMMAND OFFSET TAY LDA (ICSPRZ),Y ;GET LOW BYTE OF VECTOR FROM TAX ;HANDLER ITSELF AND SAVE INY LDA (ICSPRZ),Y ;GET HI BYTE OF VECTOR STA ICSPRZ+1 STX ICSPRZ ;SET LO BYTE CLC ;SHOW NO ERROR COM2: RTS ; ; ; DECBFL -- DECREMENT BUFFER LENGTH DOUBLE BYTE ; Z FLAG = 0 ON RETURN IF LENGTH = 0 AFTER DECREMENT DECBFL: DEC ICBLLZ ;DECREMENT LOW BYTE LDA ICBLLZ ;CHECK IT CMP #$FF ;DID IT GO BELOW? BNE DECBF1 ;NO DEC ICBLLZ+1 ;DECREMENT HI BYTE DECBF1: ORA ICBLLZ+1 ;SET Z IF BOTH ARE ZERO RTS ; ; ; INCBFP -- INCREMENT WORKING BUFFER POINTER INCBFP: INC ICBALZ ;BUMP LOW BYTE BNE INCBF1 ;GO IF NOT ZERO INC ICBALZ+1 ;ELSE, BUMP HI BYTE INCBF1: RTS ; ; ; SUBBFL -- SET BUFFER LENGTH = BUFFER LENGTH - WORKING BYTE COUNT SUBBFL: LDX ICIDNO ;GET IOCB INDEX SEC LDA ICBLL,X ;GET LOW BYTE OF INITIAL LENGTH SBC ICBLLZ ;SUBTRACT FINAL LOW BYTE STA ICBLLZ ;AND SAVE BACK LDA ICBLH,X ;GET HI BYTE SBC ICBLLZ+1 STA ICBLHZ RTS ; ; ; GOHAND -- GO INDIRECT TO A DEVICE HANDLER ; Y= STATUS ON RETURN, N FLAG=1 IF ERROR ON RETURN GOHAND: LDY #FNCNOT ;PREPARE NO FUNCTION STATUS FOR HANDLER RTS JSR CIJUMP ;USE THE INDIRECT JUMP STY ICSTAZ ;SAVE STATUS CPY #0 ;AND SET N FLAG RTS ; ; INDIRECT JUMP TO HANDLER BY PAUL'S METHOD CIJUMP: TAX ;SAVE A LDA ICSPRZ+1 ;GET JUMP ADDRESS HI BYTE PHA ;PUT ON STACK LDA ICSPRZ ;GET JUMP ADDRESS LO BYTE PHA ;PUT ON STACK TXA ;RESTORE A LDX ICIDNO ;GET IOCB INDEX RTS ;GO TO HANDLER INDIRECTLY .PAGE ; ; DEVSRC -- DEVICE SEARCH, FIND DEVICE IN HANDLER ADDRESS TABLE ; ; LOOP TO FIND DEVICE DEVSRC: LDY #0 LDA (ICBALZ),Y ;GET DEVICE NAME FROM USER BEQ CIERR2 LDY #MAXDEV ;INITIAL COMPARE INDEX DEVS1: CMP HATABS,Y ;IS THIS THE DEVICE? BEQ DEVS2 ;YES DEY DEY ;ELSE, POINT TO NEXT DEVICE NAME DEY BPL DEVS1 ;CONTINUE FOR ALL DEVICES ; ; NO DEVICE FOUND, DECLARE NON-EXISTENT DEVICE ERROR CIERR2: LDY #NONDEV ;ERROR CODE SEC ;SHOW ERROR BCS DEVS4 ;AND RETURN ; ; FOUND DEVICE, SET ICHID,ICDNO, AND INIT DEVICE DEVS2: TYA STA ICHIDZ ;SAVE HANDLER INDEX SEC LDY #1 LDA (ICBALZ),Y ;GET DEVICE NUMBER (DRIVE NUMBER) SBC #ASCZER ;SUBTRACT ASCII ZERO CMP #$A ;IS NUMBER IN RANGE? BCC DEVS3 ;YES LDA #1 ;NO. DEFAULT TO ONE DEVS3: STA ICDNOZ ;SAVE DEVICE NUMBER CLC ;SHOW NO ERROR ; ; RETURN DEVS4: RTS .PAGE ; ; ; CIO ROM TABLES ; ; COMMAND TABLE ; MAPS EACH COMMAND TO OFFSET FOR APPROPRIATE VECTOR IN HANDLER COMTAB: BYTE 0,4,4,4,4,6,6,6,6,2,8,10 LENGTH =*-CIOINT CRNTP1 =* *=$14 CIOSPR: BYTE INTORG-CRNTP1 ;^GCIOL IS TOO LONG ; .TITLE 'INTERRUPT HANDLER' ;LIVES ON DK1:INTHV.SRC SRTIM2 = 6 ;SECOND REPEAT INTERVAL ; ; THIS IS TO MAKE DOS 2 WORK WHICH USED AN ABSOLUTE ADDRESS ; *=$E912 JMP SETVBL *=SETVBV JMP SETVBL JMP SYSVBL JMP XITVBL *=INTINV JMP IHINIT ; *=VCTABL+INTABS-VDSLST ; .WORD SYRTI ;VDSLST .WORD SYIRQB ;VPRCED .WORD SYIRQB ;VINTER .WORD SYIRQB ;VBREAK ; .RES 8 .WORD SYIRQB ;VTMIR1 .WORD SYIRQB ;VTIMR2 .WORD SYIRQB ;VTMIR4 .WORD SYIRQ ;VIMIRQ .WORD 0,0,0,0,0 ;CDTMV1-4 .WORD SYSVBL ;VVBLKI .WORD XITVBL ;VVSLKD ; *=$900C ; LDA #PIRQH ;SET UP RAM VECTORS FOR LINBUG VERSION STA $FFF9 LDA #PIRQL STA $FFF8 LDA #PNMIH STA $FFFB LDA #PNMIL STA $FFFA RTS .PAGE ; ; IRQ HANDLER ; ; JUMP THRU IMMEDIATE IRQ VECTOR, WHICH ORDINARILY POINTS TO ; SYSTEM IRQ; DETERMINE & CLEAR CAUSE, JUMP THRU SOFTWARE VECTOR. ; *=INTORG IHINIT: LDA #$40 ;VBL ON BUF DLIST OFF***FOR NOW*** STA NMIEN ;ENABLE DISPLAY LIST, VERTICAL BLANK LDA #$38 ;LOOK AT DATA DIRECTION REGISTERS IN PIA STA PACTL STA PBCTL LDA #0 ;MAKE ALL INPUTS STA PORTA STA PORTB LDA #$3C ;BACK TO PORTS STA PACTL STA PBCTL RTS PIRQ: JMP (VIMIRU) CMPTAB: .BYTE $80 ;BREAK KEY .BYTE $40 ;KEY STROKE .BYTE $04 ;TIMER 4 .BYTE $02 ;TIMER 2 .BYTE $01 ;TIMER 1 .BYTE $08 ;SERIAL OUT COMPLETE .BYTE $10 ;SERIAL OUT READY .BYTE $20 ;SERIAL IN READY ; THIS IS A TABLE OF OFFSETS INTO PAGE 2. THEY POINT TO ADRTAB: .BYTE BRKKY-INTABS .BYTE VKEYBD-INTABS .BYTE VTIMR4-INTABS .BYTE VTIMR2-INTABS .BYTE VTIMR1-INTABS .BYTE VSEROC-INTABS .BYTE VSEROR-INTABS .BYTE VSERIN-INTABS SYIRQ: PHA ;SAVE ACCUMULATOR LDA IRQST ; CHECK FOR SERIAL IN AND #$20 BNE SYIRQ2 LDA #$DF ; MASK ALL OTHERS STA IRQEN LDA POKMSK STA IRQEN JMP (VSERIN) SYIRQ2: TXA ;PUT X INTO ACC PHA ;SAVE K ONTO STACK LDX #$6 ;START WITH SIX OFFSET LOOPM: LDA CMPTAB,X ;LOAD MASK CPX #5 ;CHECK TO SEE IF COMPLETE IS SET BNE LOOPM2 AND POKMSK ;IS THIS INTERUPT ENABLED? BEQ LL LOOPM2: BIT IRQST ; IS IT THE INTERUPT? BEQ JMPP LL: DEX ;NO DEC X AND TRY NEXT MASK BPL LOOPM ;IF NOT NEC 0010 LOOPH JMP SYIRQ8 ;DONE BUT NO INTERUPT JMPP: EOR #$FF ;COMPLEMENT MASK STA IRQEN ;ENABLE ALL OTHERS LDA POKMSK ; GET POKE MASK STA IRQEN ; ENABLE THOSE IN POKE MASK LDA ADRTAB,X TAX LDA INTABS,X ; GET ADDRESS LOW PART STA JVECK ; PUT IN VECTOR LDA INTABS+1,X ; GET ADDRESS HIGH PART STA JVECK+1 ; PUT IN VECTOR HIGH PART PLA ; PULL X REGISTER FROM STACK TAX ; PUT IT INTO X JMP (JVECK) ; JUMP TO THE PROPER ROUTINE BRKKY2: LDA #0 ; BREAK KEY ROUTINE STA BRKKEY ; SET BREAK KEY FLAG STA SSFLAG ; START/STOP FLAG STA CRSINH ; CURSOR INHIBIT STA ATRACT ; TURN OFF ATRACT MODE PLA RTI ;EXIT FROM INT SYIRQ8: PLA TAX BIT PACTL ;PROCEED ***I GUESS*** BPL SYIRQ9 LDA PORTA ;CLEAR INT STATUS BIT JMP (VPRCED) SYIRQ9: BIT PBCTL ;INTERRUPT ***I GUESS*** BPL SYIRQA LDA PORTB ;CLEAR INT STATUS JMP (VINTER) SYIRQA: PLA STA JVECK PLA PHA AND #$10 ;B BIT OF P REGISTER BEQ SYRTI2 LDA JVECK PHA JMP (VBREAK) SYRTI2: LDA JVECK PHA SYIRQB: PLA SYRTI: RTI ;UNIDENTIFIED INTERRUPT, JUST RETURN .PAGE ; ; NMI HANDLER ; ; DETERMINE CAUSE AND JUMP THRU VECTOR ; PNMI: BIT NMIST BPL PNMI1 ;SEE IF DISPLAY LIST JMP (VDSLST) PNMI1: PHA LDA NMIST AND #$20 ;SEE IF RESET BEQ *+5 JMP WARMSV ;DO THRU WARM START JUMP TXA ;SAVE REGISTERS PHA TYA PHA STA NMIRES ;RESET INTERRUPT STATUS JMP (VVBLKI) ;JUMP THRU VECTOR .PAGE ; ; SYSTEM VBLANK ROUTINE ; ; INC FRAME COUNTER. PROCESS COUNTDOWN TIMERS. EXIT IF I WAS SET. CLEAR ; SET DLISTL, DLISTH, DMACTL FROM RAM CELLS. DO SOFTWARE REPEAT. ; SYSVBL: INC RTCLOK+2 ;INC FRAME COUNTER BNE SYSVB1 INC ATRACT ;INCREMENT ATRACT (CAUSES ATRACT WHEN MINUS) INC RTCLOK+1 BNE SYSVB1 INC RTCLOK SYSVB1: LDA #$FE ;{ATRACT] SET DARK MASK TO NORMAL LDX #0 ;SET COLRSH TO NORMAL LDY ATRACT ;TEST ATRACT FOR NEGATIVE BPL VBATRA ;WHILE POSITIVE DONT GO INTO ATRACT STA ATRACT ;IN ATRACTI SO STAY BY STA $FE LDX RTCLOK+1 ;COLOR SHIFT FOLLOWS RICLOK+1 LDA #$F6 ;SET DARK MASK TO DARK VBATRA: STA DRKMSK STX COLRSH LDX #0 ;POINT TO TIMER1 JSR DCTIMR ;GO DECREMENT TIMER1 BNE SYSVB2 ;BRANCH IF STILL COUNTING JSR JTIMR1 ;GO JUMP TO ROUTINE SYSVB2: LDA CRITIC BNE XXIT ;GO IF CRITICAL SET TSX ;SEE IF I WAS SET LDA $104,X ;GET STACKED P AND #$04 ;I BIT BEQ SYSVB3 ;BRANCH IF OK XXIT: JMP XITVBL ;I WAS SET, EXIT SYSVB3: LDA PENV STA LPENV LDA PENH STA LPENH LDA SDLSTH STA DLISTH LDA SDLSTL STA DLISTL LDA SDMCTL STA DMACTL LDA GPRIOR ;GLOBAL PRIOR STA PRIOR LDX #$08 ;TURN OFF KEYBOARD SPEAKER STX CONSOL SCOLLP: CLI ;DISABLE INTERUPTS LDA PCOLR0, X ;LOAD COLOR REGISTERS FROMRAM EOR COLRSH ;DO COLOR SHIFT AND DRKMSK ;AND DARK ATRACT STA COLPM0,X DEX BPL SCOLLP LDA CHBAS STA CHBASE LDA CHACT STA CHACTL LDX #2 ;POINT TO TIMER 2 JSR DCTIMR BNE SYSVB4 ;IF DIDNT GO ZERO JSR JTIMR2 ;GO JUMP TO TIMER2 ROUTINE SYSVB4: LDX #2 ;RESTORE X SYSVBB: INX INX LDA CDTMV1,X ORA CDTMV1+1,X BEQ SYSVBA JSR DCTIMR ;DECREMENT AND SET FLAG IF NONZERO STA CDTMF3-4,X SYSVBA: CPX #8 ;SEE IF DONE ALL 3 BNE SYSVBB ;LOOP ; CHECK DEBOUNCE COUNTER LDA SKSTAT AND #$04 ;KEY DOWN BIT BEQ SYVB6A ;IF KEY DOWN ; KEY UP SO COUNT IT LDA KEYDEL ;KEY DELAY COUNTER BEQ SYVB6A ;IF COUNTED DOWN ALREADY DEC KEYDEL ;COUNT IT ; CHECK SOFTWARE REPEAT TIMER SYVB6A: LDA SRTIMR BEQ SYSVB7 ;DOESN'T COUNT LDA SKSTAT AND #$04 ;CHECK KEY DOWN BIT BNE SYSVB6 ;BRANCH IF NO LONGER DOWN DEC SRTIMR ;COUNT FRAME OF KEY DOWN BNE SYSVB7 ;BRANCH IF NOT RUN OUT ; TIMER RAN OUT - RESET AND SIMULATE KEYBOARD IRQ LDA #SRTIM2 ;TIMER VALUE STA SRTIMR ;SET TIMER LDA KBCODE ;GET THE KEY STA CH ;PUT INTO CH ; READ GAME CONTROLLERS SYSVB7: LDY #1 LDX #3 STLOOP: LDA PORTA,Y LSR A LSR A LSR A LSR A STA STICK0,X ;STORE JOYSTICK DEX LDA PORTA,Y AND #$F STA STICK0,X ;STORE JOYSTICK DEX DEY BPL STLOOP ; LDX #3 STRL: LDA TRIG0,X ;MOVE JOYSTICK TRIGGERS STA STRIG0,X LDA POT0,X ;MOVE POT VALUES STA PADDL0,X LDA POT4,X STA PADDL4,X DEX BPL STRL STA POTGO ;START POTS FOR NEXT TIME ; LDX #6 LDY #3 PTRLP: LDA STICK0,Y ;TRANSFER BITS FROM JOYSTICKS LSR A ;TO PADDLE TRIGGERS LSR A LSR A STA PTRIG1,X LDA #0 ROL A STA PTRIG0,X DEX DEX DEY BPL PTRLP ; JMP (VVBLKD) ;GO TO DEFERRED VBLANK ROUTINE SV7H = SYSVB7/256 SV7L = (-256)*SV7H+SYSVB7 SYSVB6: LDA #0 STA SRTIMR ;ZERO TIMER BEQ SYSVB7 ;UNCOND JTIMR1: JMP (CDTMA1) JTIMR2: JMP (CDTMA2) ; ; SUBROUTINE TO DECREMENT A COUNTDOWN TIMER ; ENTRY X=OFFSET FROM TIMER 1 ; EXIT A,P=ZERO IF WENT ZERO, FF OTHERWISE ; DCTIMR: LDY CDTMV1,X ;LO BYTE BNE DCTIM1 ;NONZERO, GO DEC IT LDY CDTMV1+1,X ;SEE IF BOTH ZERO BEQ DCTXF ;YES, EXIT NONZERO DEC CDTMV1+1,X ;DEC HI BYTE DCTIM1: DEC CDTMV1,X ;DEC LO BYTE BNE DCTXF LDY CDTMV1+1,X BNE DCTXF LDA #0 ;WENT ZERO. RETURN ZERO RTS DCTXF: LDA #$FF ;RETURN NONZERO RTS .PAGE ; ; SUBROUTINE TO SET VERTICAL BLANK VECTORS AND TIMERS ; ENTRY X=HI,Y=LO BYTE TO SET ; A= 1-5 TIMERS 1-5 ; 6 IMM VBLANK ; 7 DEF VBLANK ; SETVBL: ASL A ;MUL BY 2 STA INTEMP TXA LDX #5 STA WSYNC ;WASTE 20 CPU CYCLES SETLOP: DEX ;TO ALOWD VBLANK TO HAPPEN BNE SETLOP ;IF THIS IS LINE "7C" LDX INTEMP STA CDTMV1-1,X TYA STA CDTMV1-2,X RTS ; ; EXIT FROM VERTICAL BLANK ; XITVBL: PLA ;UNSTACK Y TAY PLA ;UNSTACK X TAX PLA ;UNSTACK A RTI ;AND GO BACK FROM WHENCE. PIRQH = PIRQ/256 PIRQL = (-256)*PIRQH+PIRQ PNMIH = PNMI/256 PNMIL = (-256)*PNMIH+PNMI ; SPARE BYTE OR MODULE TOO LONG FLAG CRNTP2 =* *=$14 INTSPR: .BYTE SIOORG-CRNTP2 ;^GINTHV IS TOO LONG ; .TITLE 'SIO ( SERIAL BUS INPUT/OUTPUT CONTROLLER )' ; COLLEEN OPERATING SYSTEM ; ; SIO ( SERIAL BUS INPUT/OUTPUT CONTROLLER ) ; WITH SOFTWARE BAUD RATE CORRECTION ON CASSETTE ; ; ; AL MILLER 3-APR-19 ; ; ; THIS MODULE HAS ONE ENTRY POINT. IT IS CALLED BY THE DEVICE ; HANDLERS. IT INTERPRETS A PREVIOUSLY ESTABLISHED DEVICE CONTROL ; BLOCK (STORED IN GLOBAL RAM) TO ISSUE COMMANDS ; TO THE SERIAL BUS TO CONTROL TRANSMITTING AND RECEIVING DATA. ; ; ; ; .PAGE ; EQUATES ; ; DCD DEVICE BUS ID NUMBERS FLOPPY = $30 ;PRINTR = $40 ;CASSET = $80 ;!!!!! ***** CASET = $60 ;!!!!! ***** ; ; ;BUS COMMANDS ; READ = 'R WRITE = 'W ;STATIS = 'S ;FORMAT = '! ; ; ; COMMAND AUX BYTES ; SIDWAY = 'S ;PRINT 18 CHARACTERS SIDEWAYS NORMAL = 'N ;PRINT 40 CHARACTERS NORMALLY DOUBLE = 'D ;PRINT 20 CHARACTERS DOUBLE WIDE PLOT = 'P ;PLOT MODE ; ; ; BUS RESPONSES ; ACK = 'A ;DEVICE ACKNOWLEDGES INFORMATION NACK = 'N ;DEVICE DID NOT UNDERSTAND COMPLT = 'C ;DEVICE SUCCESSFULLY COMPLETED OPERATION ERROR = 'E ;DEVICE INCURRED AN ERROR IN AN ATTEMPTED OP ; ; ; MISCELLANEOUS EQUATES ; B192LO = $28 ;19200 BAUD RATE POKEY COUNTER VALUES (LO BY B192HI = $00 ;(HI BYTE) B600LO = $CC ;600 BAUD (LO BYTE) B600HI = $05 ;(HI BYTE) HITONE = $05 ;FSK HI FREQ POKEY COUNTER VALUE (5326 HZ) LOTONE = $07 ;FSK LO FREQ POKEY COUNTER VALUE (3995 HZ) ; .IF PALFLG WIRGLO = 150 ;WRITE INTER RECORD GAP (IN 1/60 SEC) RIRGLO = 100 ;READ INTER RECORD GAP (IN 1/60 SEC) WSIRG = 13 ;SHORT WRITE INTER RECORD GAP RSIRG = 8 ;SHORT READ INTER RECORD GAP .ENDIF .IF PALFLG-1 WIRGLO = 180 ;WRITE INTER RECORD GAP (IN 1/60 SEC) RIRGLO = 120 ;READ INTER RECORD GAP (IN 1/60 SEC) WSIRG = 15 ;SHORT WRITE INTER RECORD GAP RSIRG = 10 ;SHORT READ INTER RECORD GAP .ENDIF WIRGHI = 0 RIRGHI = 0 ; NCOMLO = $34 ;PIA COMMAND TO LOWER NOT COMMAND LINE NCOMHI = $3C ;PIA COMMAND TO RAISE NOT COMMAND LINE MOTRGO = $34 ;PIA COMMAND TO TURN ON CASSETTE MOTOR MOTRST = $3C ;PIA COMMAND TO TURN OFF MOTOR ; TEMPHI = TEMP/256 ;ADDRESS OF TEMP CELL (HI BYTE) TEMPLO = (-256)*TEMPHI+TEMP ;(LO BYTE) CBUFHI = CDEVIC/256 ;ADDRESS OF COMMAND BUFFER (HI BYTE) CBUFLO = (-256)*CBUFHI+CDEVIC ;(LO BYTE) ; CRETRI = 13 ;NUMBER OF COMMAND FRAME RETRIES DRETRI = 1 ;NUMBER OF DEVICE RETRIES CTIMLO = 2 ;COMMAND FRAME ACK TIME OUT (LO BYTE) CTIMHI = 0 ;COMMAND FRAME ACK TIME OUT (HI BYTE) ; ; ;JTADRH = JTIMER/256 ;HI BYTE OF JUMP TIMER ROUTINE ADDR ;JTADRL = (-256)*JTADRH+JTIMER ;"MOVED TO LINE 1428" ; .PAGE ; SIO ; ; *=SIOV JMP SIO ;SIO ENTRY POINT ; *=SIOINV JMP SIOINT ;SIO INITIALIZATION ENTRY POINT ; *=SENDEV JMP SENDEN ;SEND ENABLE ENTRY POINT ; *=VCTABL-INTABS+VSERIN ; .WORD ISRSIR ;VSERIN .WORD ISRODN ;VSEROR .WORD ISRTD ;VSEROC ; ; ; *=SIOORG ; ; SIO INITIALIZATION SUBROUTINE ; SIOINT: LDA #MOTRST STA PACTL ;TURN OFF MOTOR ; LDA #NCOMHI STA PBCTL ;RAISE NOT COMMAND LINE ; ; LDA #3 STA SSKCTL ;GET POKEY OUT OF INITIALIZE MODE STA SOUNDR ;INIT POKE ADDRESS FOR QUIET I/O STA SKCTL ; ; RTS ;RETURN ; ; ; ; ; ; SIO: TSX STX STACKP ;SAVE STACK POINTER LDA #1 STA CRITIC ; LDA DDEVIC CMP #CASET BNE NOTCST ;BRANCH IF NOT CASSETTE JMP CASENT ;OTHERWISE JUMP TO CASSETTE ENTER ; ; ALL DEVICES EXCEPT CASSETTE ARE INTELLIGENT ; NOTCST: LDA #0 STA CASFLG ; INIT CASSETTE FLAG TO NO CASSETTE ; LDA #DRETRI ;SET NUMBER OF DEVICE RETRIES STA DRETRY COMMND: LDA #CRETRI ;SET NUMBER OF COMMAND FRAMERETRIES STA CRETRY ; ; SEND A COMMAND FRAME ; COMFRM: LDA #B192LO ;SET BAUD RATE TO 19200 STA AUDF3 LDA #B192HI STA AUDF4 ; CLC ;SET UP COMMAND BUFFER LDA DDEVIC ADC DUNIT ADC #$FF ;SUBTRACT 1 STA CDEVIC ;SET BUS ID NUMBER ; LDA DCOMND STA CCOMND ;SET BUS COMMAND ; LDA DAUX1 ;STORE COMMAND FRAME AUX BYTES 1 AND 2 STA CAUX1 LDA DAUX2 STA CAUX2 ;DONE SETTING UP COMMAND BUFFER ; CLC ;SET BUFFER POINTER TO COMMAND FRAME BUFFER LDA #CBUFLO STA BUFRLO ;AND BUFFER END ADDRESS ADC #4 STA BFENLO LDA #CBUFHI STA BUFRHI STA BFENHI ;DONE SETTING UP BUFFER POINTER ; LDA #NCOMLO ;LOWER NOT COMMAND LINE STA PBCTL ; JSR SENDIN ;SEND THE COMMAND FRAME TO A SMART DEVICE ; LDA ERRFLG BNE BADCOM ;BRANCH IF AN ERROR RECEIVED ; TYA BNE ACKREC ;BRANCH IF ACK RECEIVED ; ; BADCOM: DEC CRETRY ;A NACK OR TIME OUT OCCURED BPL COMFRM ;SO BRANCH IF ANY RETRIES LEFT ; JMP DERR1 ;OTHERWISE, JUMP TO RETURN SECTION ; ; ACKREC: LDA DSTATS ;ACK WAS RECEIVED BPL WATCOM ;BRANCH TO WAIT FOR COMPLETE ; IF THERE IS NO DATA TO BE SENT ; ; ; ; SEND A DATA FRAME TO PERIPHERAL ; LDA #CRETRI ;SET NUMBER OF RETRIES STA CRETRY ; JSR LDPNTR ;LOAD BUFFER POINTER WITH DCB INFORMATION ; JSR SENDIN ;GO SEND THE DATA FRAME TO A SMART DEVICE ; BEQ BADCOM ;BRANCH IF BAD ; ; ; ; WAIT FOR COMPLETE SIGNAL FROM PERIPHERAL ; WATCOM: JSR STTMOT ;SET DDEVICE TIME OUT VALUES IN Y,X ; LDA #$00 STA ERRFLG ;CLEAR ERROR FLAG ; JSR WAITER ;SET UP TIMER AND WAIT BEQ DERR ;BRANCH IF TIME OUT ; ; ; DEVICE DID NOT TIME OUT ; BIT DSTATS BVS MODATA ;BRANCH IF MORE DATA FOLLOWS ; LDA ERRFLG BNE DERR1 ;BRANCH IF AN ERROR OCCURRED BEQ RETURN ;OTHERWISE RETURN ; ; ; ; ; RECEIVE A DATA FRAME FROM PERIPHERAL ; MODATA: JSR LDPNTR ;LOAD BUFFER POINTER WITH DCB INFORMATION ; JSR RECEIV ;GO RECEIVE A DATA FRAME ; DERR: LDA ERRFLG BEQ NOTERR ;BRANCH IF NO ERROR PRECEEDED DATA ; LDA TSTAT ;GET TEMP STATUS STA STATUS ;STORE IN REAL STATUS ; ; NOTERR: LDA STATUS CMP #SUCCES BEQ RETURN ;BRANCH IF COMPLETELY SUCCESSFUL ; DERR1: DEC DRETRY BMI RETURN ;BRANCH IF OUT OF DEVICE RETRIES ; JMP COMMND ;OTHERWISE ONE MORE TIME ; ; ; ; RETURN: JSR SENDDS ;DISABLE POKEY INTERRUPTS LDA #0 STA CRITIC LDY STATUS ;RETURN STATUS IN Y STY DSTATS ;AND THE DCB STATUS WORD RTS RETURN ; ; ; ; ; WAIT SUBROUTINE ; ; WAITS FOR COMPLETE OR ACK ; RETURNS Y=$FF IF SUCCESSFUL, Y=$00 IF NOT ; WAIT: LDA #$00 STA ERRFLG ;CLEAR ERROR FLAG ; CLC ;LOAD BUFFER POINTER WITH ADDRESS LDA #TEMPLO ;OF TEMPORARY RAM CELL STA BUFRLO ADC #1 STA BFENLO ;ALSO SET BUFFER END +1 ADDRESS LDA #TEMPHI STA BUFRHI STA BFENHI ;DONE LOADING POINTER ; LDA #$FF STA NOCKSM ;SET NO CHECKSUM FOLLOWS DATA FLAG ; JSR RECEIV ;GO RECEIVE A BYTE ; LDY #$FF ;ASSUME SUCCESS LDA STATUS CMP #SUCCES BNE NWOK ;BRANCH IF IT DID NOT WORK OK ; ; ; ; WOK: LDA TEMP ;MAKE SURE THE BYTE SUCCESSFULLY RECEIVED CMP #ACK ;WAS ACTUALLY AN ACK OR COMPLETE BEQ GOOD CMP #COMPLT BEQ GOOD ; CMP #ERROR BNE NOTDER ;BRANCH IF DEVICE DID NOT SEND BACK ; A DEVICE ERROR CODE LDA #DERROR STA STATUS ;SET DEVICE ERROR STATUS BNE NWOK ; NOTDER: LDA #DNACK ;OTHERWISE SET HACK STATUS STA STATUS ; NWOK: LDA STATUS CMP #TIMOUT BEQ BAD ;BRANCH IF TIME OUT ; LDA #$FF STA ERRFLG ;SET SOME ERROR FLAG BNE GOOD ;RETURN WITH OUT SETTING Y = 0 ; BAD: LDY #0 ; GOOD: LDA STATUS STA TSTAT RTS ;RETURN ; ; ; ; ; ; SEND SUBROUTINE ; ; SENDS A BUFFER OF BYTES OUT OVER THE SERIAL BUS ; ; SEND: LDA #SUCCES ;ASSUME SUCCESS STA STATUS ; JSR SENDEN ;ENABLE SENDING ; LDY #0 STY CHKSUM ;CLEAR CHECK SUM STY CHKSNT ;CHECKSUM SENT FLAG STY XMTDON ;TRANSMISSION DONE FLAG ; ; LDA (BUFRLO),Y ;PUT FIRST BYTE FROM BUFFER STA SEROUT ;INTO THE SERIAL OUTPUT REGISTER ; ; STA CHKSUM ;PUT IT IN CHECKSUM ; NOTDON: LDA BRKKEY BNE NTBRKO JMP BROKE ;JUMP IF BREAK KEY PRESSED ; NTBRKO: LDA XMTDON ;LOOP UNTIL TRANSMISSION IS DONE BEQ NOTDON ; JSR SENDDS ;DISABLE SENDING ; RTS RETURN ; ; ; ; ; ; ; OUTPUT DATA NEEDED INTERRUPT SERVICE ROUTINE ; ISRODN: TYA PHA ;SAVE Y REG ON STACK ; INC BUFRLO ;INCREMENT DUFFER POINTER BNE NOWRPO INC BUFRHI ; NOWRPO: LDA BUFRLO ;CHECK IF PAST END OF BUFFER CMP BFENLO LDA BUFRHI ;HIGH PART SBC BFENHI BCC NOTEND ;BRANCH IF NOT PAST END OF BUFFER ; LDA CHKSNT BNE RELONE ;BRANCH IF CHECKSUM ALREADY SENT ; LDA CHKSUM STA SEROUT ;SEND CHECK SUM LDA #$FF STA CHKSNT ;SET CHECKSUM SENT FLAG BNE CHKDON ; RELONE: LDA POKMSK ;ENABLE TRANSMIT DONE INTERRUPT ORA #$08 STA POKMSK STA IRQEN ; CHKDON: PLA TAY ;RESTORE Y REG PLA ;RETURN FROM INTERRUPT RTI ; ; NOTEND: LDY #0 LDA (BUFRLO),Y ;PUT NEXT BYTE FROM BUFFER STA SEROUT ;INTO THE SERIAL OUTPUT REGISTER ; CLC ;ADD IT TO CHECKSUM ADC CHKSUM ADC #0 STA CHKSUM ; JMP CHKDON ;GO RETURN ; ; ; ; ; ; ; TRANSMIT DONE INTERRUPT SERVICE ROUTINE ; ISRTD: LDA CHKSNT BEQ FOOEY ;BRANCH IF CHECKSUM NOT YET SENT ; STA XMTDON ;OTHERWISE SET TRANSMISSION DONE FLAG ; LDA POKMSK ;DISABLE TRANSMIT DONE INTERRUPT AND #$F7 STA POKMSK STA IRQEN ; FOOEY: PLA ;RETURN FROM INTERRUPT RTI ; ; ; ; ; ; ; ; ; RECEIVE SUBROUTINE ; RECEIV: LDA #0 ; LDY CASFLG BNE NOCLR ;BRANCH IF CASSETTE ; STA CHKSUM ;CLEAR CHKSUM NOCLR: STA BUFRFL ;BUFFER FULL FLAG STA RECVDN ;RECEIVE DONE FLAG ; ; ; LDA #SUCCES STA STATUS ;SET GOOD STATUS FOR DEFAULT CASE. JSR RECVEN ;DO RECEIVE ENABLE LDA #NCOMHI ;COMMAND FRAME HI COMMAND STA PBCTL ;STORE IN PIA CHKTIM: LDA BRKKEY BNE NTBRK1 JMP BROKE ;JUMP IF BREAK KEY PRESSED ; NTBRK1: LDA TIMFLG ;NO, BEQ TOUT ;IF TIMEOUT, GO SET ERROR STATUS LDA RECVDN BEQ CHKTIM ;DONE ? GOBACK: RTS TOUT: LDA #TIMOUT ;YES, STA STATUS ;SET TIMEOUT STATUS ; ; ; ; ; ; RRETRN: RTS ;RETURN ; ; ; ; ; ; ; ; SERIAL INPUT READY INTERRUPT SERVICE ROUTINE ; ISRSIR: TYA PHA ;SAVE Y REG ON STACK ; ; ; LDA SKSTAT STA SKRES ;RESET STATUS REGISTER ; ******** THIS MAY NOT BE THE PLACE TO DO IT ********* ; BMI NTFRAM ;BRANCH IF NO FRAMING ERROR ; LDY #FRMERR STY STATUS ;SET FRAME ERRORR STATUS ; NTFRAM: AND #$20 BNE NTOVRN ;BRANCH IF NO OVERRUN ERROR ; LDY #OVRRUN STY STATUS ;SET OVERRUN ERROR STATUS ; NTOVRN: LDA BUFRFL BEQ NOTYET ;BRANCH IF BUFFER WAS NOTYET FILLED ; LDA SERIN ;THIS INPUT BYTE 15 THE CHECKSUM CMP CHKSUM BEQ SRETRN ;BRANCH IF CHECKSUMS MATCH ; LDY #CHKERR STY STATUS ;SET CHECKSUM ERROR STATUS ; SRETRN: LDA #$FF ;SET RECEIVE DONE FLAG STA RECVDN ; SUSUAL: PLA TAY ;RESTORE Y REG PLA ;RETURN FROM INTERRUPT RTI ; ; ; NOTYET: LDA SERIN LDY #0 STA (BUFRLO),Y ;STORE INPUT REGISTER INTO BUFFER ; CLC ;ADD IT TO CHECKSUM ADC CHKSUM ADC #0 STA CHKSUM ; INC BUFRLO ;INCREMENT BUFFER POINTER BNE NTWRP1 INC BUFRHI ; NTWRP1: LDA BUFRLO CMP BFENLO LDA BUFRHI SBC BFENHI DCC SUSUAL ;BRANCH IF NEW BUFFER ADDRESS IS IN BUFFER L ; LDA NOCKSM BEQ GOON ;BRANCH IF A CHECKSUM WILL FOLLOW DATA ; LDA #0 STA NOCKSM ;CLEAR NO CHECKSUM FLAG ; BEQ SRETRN ;GO RETURN AND SET RECEIVE DONE FLAG ; ; GOON: LDA #$FF STA BUFRFL ;SET BUFFER FULL FLAG ; BNE SUSUAL ;GO RETURN ; ; ; ; ; ; ; ; ; LOAD BUFFER POINTER SUBROUTINE ; ; LOAD BUFFER POINTER WITH DCB BUFFER INFORMATION ; LDPNTR: CLC LDA DBUFLO STA BUFRLO ADC DBYTLO STA BFENLO ;ALSO SET SUFFER END + 1 ADDRESS ; LDA DBUFHI STA BUFRHI ADC DBYTHI STA BFENHI ; RTS ;RETURN ; ; ; ; ; ; ; ; ; CASSETTE HANDLING CODE ; CASENT: LDA DSTATS BPL CASRED ;BRANCH IF INPUT FROM CASSETTE ; ; WRITE A RECORD ; LDA #B600LO ;SET BAUD RATE TO 600 STA AUDF3 LDA #B600HI STA AUDF4 ; JSR SENDEN ;TURN ON POKEY MARK TONE ; LDY #WSIRG ;LOAD SHORT WRITE INTER RECORD GAP TIME LDA DAUX2 BMI SRTIR0 ;BRANCH IF SHORT GAP IS DESIRED ; LDY #WIRGLO ;SET WRITE IRQ TIME SRTIR0: LDX #WIRGHI JSR SETVBX ; LDA #MOTRGO STA PACTL ;TURN ON MOTOR ; TIMIT: LDA TIMFLG ;LOOP UNTIL DONE BNE TIMIT ; JSR LDPNTR ;LOAD BUFFER POINTER WITH DCB INFORMATION ; JSR SEND ;SEND A BUFFER ; JMP CRETRN ;GO, RETURN ; ; ; ; RECEIVE A RECORD ; CASRED: LDA #$FF STA CASFLG ;SET SET CASSETTE FLAG ; LDY #RSIRG ;LOAD SHORT READ INTER RECORD GAP TIME LDA DAUX2 BMI SRTIR1 ;BRANCH IF SHORT GAP IS DESIRED ; LDY #RIRGLO ;SET TIME OUT FOR READ IRQ SRTIR1: LDX #RIRGHI JSR SETVBX ; LDA #MOTRGO STA PACTL ;TURN ON MOTOR ; TIMIT1: LDA TIMFLG ;LOOP UNTIL DONE BNE TIMIT1 ; JSR LDPNTR ;LOAD BUFFER POINTER WITH DOS INFORMATION ; JSR STTMOT ;SET DEVICE TIME OUT IN Y,X JSR SETVBX ; JSR BEGIN ;SET INITIAL BAUD RATE ; JSR RECEIV ;GO RECEIVE A BLOCK ; CRETRN: LDA DAUX2 BMI SRTIR2 ;BRANCH IF DOING SHORT INTER RECORD GAPS ; DON'T TURN OFF CASSETTE MOTOR LDA #MOTRST STA PACTL ;TURN OFF MOTOR ; SRTIR2: JMP RETURN ;GO RETURN ; ; ; ; ; JTIMER: LDA #$00 JTADRH = JTIMER/256 ;HI BYTE OF JUMP TIMER ROUTINE ADDR JTADRL = (-256)*JTADRH+JTIMER STA TIMFLG ;SET TIME OUT FLAG RTS ; ; ; ; ; ; ; SEND ENABLE SUBROUTINE ; SENDEN: LDA #$07 ;MASK OFF PREVIOUS SERIAL BUS CONTROL BITS AND SSKCTL ORA #$20 ;SET TRANSMIT MODE ; LDY DDEVIC CPY #CASET BNE NOTCAS ;BRANCH IF NOT CASSETTE ; ORA #$08 ;SET THE FSK OUTPUT BIT ; LDY #LOTONE ;SET FSK TONE FREQUENCIES STY AUDF2 LDY #HITONE STY AUDF1 ; NOTCAS: STA SSKCTL ;STORE NEW VALUE TO SYSTEM MASK STA SKCTL ;STORE TO ACTUAL REGISTER ; LDA #$C7 ;MASK OFF PREVIOUS SERIAL BUS INTERRUPT BITS AND POKMSK ORA #$10 ;ENABLE OUTPUT DATA NEEDED INTERRUPT ; ; JMP CONTIN ;GO CONTINUE IN RECEIVE ENABLE SUBROUTINE ; ; ; ; ; ; ; ; ; ; ; RECEIVE ENABLE SUBROUTINE ; RECVEN: LDA #$07 ;MASK OFF PREVIOUS SERIAL BUS CONTROL BITS AND SSKCTL ORA #$10 ;SET RECEIVE MODE ASYNCH. STA SSKCTL ;STORE NEW VALUE TO SYSTEM MASK STA SKCTL ;STORE TO ACTUAL REGISTER ; STA SKRES ;RESET SERIAL PORT/KEYBOARD STATUS REGISTER ; LDA #$C7 ;MASK OFF PREVIOUS SERIAL BUS INTERRUPTBITS AND POKMSK ORA #$20 ;ENABLE RECEIVE INTERRUPT CONTIN: STA POKMSK ;STORE NEW VALUE TO SYSTEM MASK STA IRQEN ;STORE TO ACTUAL. REGISTER ; ; LDA #$28 ;CLOCK CH.3 WITH 1.79 MHZ STA AUDCTL ;CLOCK CH.4 WITH CH. 3 ; LDX #6 ;SET PURE TONES, NO VOLUME LDA #$A8 LDY SOUNDR ;TEST QUIET I/O FLAG BNE NOISE1 ;NE IS NORMAL (NOISY) LDA #$A0 NOISE1: STA AUDC1,X DEX DEX BPL NOISE1 ; LDA #$A0 STA AUDC3 ;TURN OFF SOUND ON CHANNEL 3 LDY DDEVIC CPY #CASET BEQ CAS31 ;BRANCH IF CASSETTE IS DESIRED STA AUDC1 ;OTHERWISE TURN OFF CHANNELS 1 AND 2 STA AUDC2 ; ; CAS31: RTS ;RETURN ; ; ; ; ; ; ; ; ; ; ; DISABLE SEND AND DISABLE RECEIVE SUBROUTINES ; SENDDS: NOP RECVDS: LDA #$C7 ;MASK OFF SERIAL BUS INTERRUPTS AND POKMSK STA POKMSK ;STORE NEW VALUE TO SYSTEM MASK STA IRQEN ;STORE TO ACTUAL REGISTER ; LDX #6 LDA #0 ZERIT: STA AUDC11X DEX DEX BPL ZERIT ;TURN OFF AUDIO VOLUME ; RTS ;RETURN ; ; ; ; ; ; ; ; ; ; ; SET DDEVICE TIME OUT VALUES IN Y,X SUBROUTINE ; STTMOT: LDA DTIMLO ;GET DEVICE TIME OUT IN 1 SECOND INCR ROR A ;PUT 6 HI BITS IN X, LO 2 BITS IN Y ROR A TAY ;TEMP SAVE AND #$3F ;MASK OFF 2 HI BITS TAX ;THIS IS HZ BYTE OF TIME OUT ; TYA ;RESTORE ROR A AND #$C0 ;MASK OFF ALL BUT 2 HI BITS TAY ;THIS IS LO BYTE OF TIME OUT ; RTS ; ; ; ; ; ; ; ; ; ; INTTBL: .WORD ISRSIR ;SERIAL INPUT READY .WORD ISRODN ;OUTPUT DATA NEEDED .WORD ISRTD ;TRANSMISSION DONE ; SIRHI = ISRSIR/256 ;SERIAL INPUT READY ISR ADDRESS SIRLO = (-256)*SIRHI+ISRSIR ODNHI = ISRODN/256 ;OUTPUT DATA NEEDED ISR ADDRESS ODNLO = (-256)*ODNHI+ISRODN TDHI = ISRTD/256 ;TRANSMISSION DONE ISR ADDRESS IDLO = (-256)*TDHI+ISRTD ; ; ; ; ; SEND A DATA FRAME TO AN INTELLIGENT PERIPHERAL SUBROUTINE ; ; SENDIN: LDX #$01 DELAY0: LDY #$FF DELAY1: DEY BNE DELAY1 DEX BNE DELAY0 ; JSR SEND ;GO SEND THE DATA FRAME ; LDY #CTIMLO ;SET ACK TIME OUT LDX #CTIMHI WAITER: JSR SETVBX JSR WAIT ;WAIT FOR ACK ; TYA ;IF Y=0, A TIME OUT OR NACK OCCURED ; RTS ;RETURN ; ; ; ; ; ; ; ; ; ; ; ; COMPUTE VALUE FOR POKEY FREQ REGS FOR THE BAUD RATE AS ; MEASURED BY AN INTERVAL OF THE 'VCOUNT' TIMER. ; COMPUT: STA TIMER2 STY TIMER2+1 ;SAVE FINAL TIMER VALUE JSR ADJUST ;ADJUST VCOUNT VALUE STA TIMER2 ;SAVE ADJUSTED VALUE LDA TIMER1 JSR ADJUST ;ADJUST STA TIMER1 ;SAVE ADJUSTED TIMER1 VALUE LDA TIMER2 SEC SBC TIMER1 STA TEMP1 ;FIND VCOUNT DIFFERENCE LDA TIMER2+1 SEC SBC TIMER1+1 TAY ;FIND VBLANK COUNT DIFFERENCE .IF PALFLG LDA #-$9C HITIMR: CLC ADC #$9C .ENDIF .IF PALFLG-1 LDA #-$83 HITIMR: CLC ADC #$83 ;ACCUMULATE MULTIPLICATION .ENDIF DEY BPL HITIMR ;DONE? CLC ADC TEMP1 ;TOTAL VCOUNT DIFFERENCE FINDX: TAY ;SAVE ACCUM LSR A LSR A LSR A ASL A SEC SBC #22 ;ADJUST TABLE INDEX TAX ;DIVIDE INTERVAL BY 4 TO CET TABLE INDEX TYA ;RESTORE ACCUM AND #7 TAY ;PULL OFF 3 LO BITS OF INTERVAL LDA #-11 DOINTP: CLC ADC #11 ;ACCUMULATE INTERPOLATION CONSTANT DEY BPL DOINTP ;INTERPOLATION CONSTANT COMPUTATION DONE? ; ENINTP: LDY #0 STY ADDCOR ;CLEAR ADDITION CORRECTION FLAG SEC SBC #7 ;ADJUST INTERPOLATION CONSTANT BPL PLUS DEC ADDCOR PLUS: CLC ADC POKTAB,X ;ADD CONSTANT TO LO BYTE TABLE VALUE TAY ;LO BYTE POKEY FREQ VALUE LDA ADDCOR ADC POKTAB+1,X ;ADD CARRY TO HI BYTE TABLEVALUE ; HI BYTE POKEY FREQ VALUE RTS ; ; ; ; ROUTINE TO ADJUST VCOUNT VALUE ; ADJUST: CMP #$7C BMI ADJ1 ;LAROER THAN '7C' ? SEC ;YES SBC #$7C RTS ADJ1: CLC .IF PALFLG ADC #$20 .ENDIF .IF PALFLG-1 ADC #$7 .ENDIF RTS ; ; ; ; ; ; ; ; INITIAL BAUD RATE MEASUREMENT -- USED TO SET THE ; BAUD RATE AT THE START OF A RECORD. ; ; IT IS ASSUMED THAT THE FIRST TWO BYTES OF EVERY ; RECORD ARE 'AA' HEX. ; BEGIN: LDA BRKKEY BNE NTBRK2 JMP BROKE ;JUMP IF BREAK KEY PRESSED ; NTBRK2: SEI ; LDA TIMFLG BNE OKTIM1 ;BRANCH IF NOT TIMEDOUT BEQ TOUT1 ;BRANCH IF TIME OUT ; OKTIM1: LDA SKSTAT AND #$10 ;READ SERIAL PORT BNE BEGIN ;START BIT? STA SAVIO ;SAVE SER. DATA IN LDX VCOUNT ;READ VERTICAL LINECOUNTER LDY RTCLOK+2 ;READ LO BYTE OF VBLANK CLOCK STX TIMER1 STY TIMER1+1 ;SAVE INITIAL TIMER VALUE ; LDX #1 ;SET MODE FLAG STX TEMP3 LDY #10 ;SET BIT COUNTER FOR 10 BITS COUNT: LDA BRKKEY BEQ BROKE ;BRANCH IF BREAK KEY PRESSED ; LDA TIMFLG BNE OKTIMR ;BRANCH IF NOT TIMED OUT TOUT1: CLI JMP TOUT ;BRANCH IF TIME OUT ; OKTIMR: LDA SKSTAT AND #$10 ;READ SERIAL PORT CMP SAVIO ;DATA IN CHANGED YET? BEQ COUNT STA SAVIO ;YES,SAVE SER. DATA IN DEY ;DECR. BIT COUNTER BNE COUNT ;DONE? ; DEC TEMP3 ;YES, BMI GOREAD ;DONE WITH BOTH MODES? LDA VCOUNT LDY RTCLOK+2 ;READ TIMER LO & HI BYTES JSR COMPUT ;NO, COMPUTE SAUD RATE STY CBAUDL STA CBAUDH ;SET BAUD RATE INTO RAM CELLS LDY #9 ;SET BIT COUNTER FOR 9 BITS BNE COUNT ; GOREAD: LDA CBAUDL STA AUDF3 LDA CBAUDH STA AUDF4 ;SET POKEY FREQ REGS FOR BAUD RATE LDA #0 STA SKSTAT LDA SSKCTL STA SKSTAT ; INIT. POKEY SERIAL PORT LDA #$55 STA (BUFRLO),Y ;STORE '$55' AS FIRST RCV. BUFFER INY STA (BUFRLO),Y LDA #$AA STA CHKSUM ;STORE CHECKSUM FOR 2 BYTES OF '$AA' CLC LDA BUFRLO ADC #2 STA BUFRLO LDA BUFRHI ADC #0 STA BUFRHI ;INCR. BUFFER POINTER BY 1 CLI RTS ; ; ; BROKE: JSR SENDDS ;BREAK KEY WAS PRESSED, SO PREPARE LDA #MOTRST ;TO RETURN STA PACTL ;TURN OFF MOTOR STA PBCTL ;RAISE NOT COMMAND LINE ; LDA #BRKABT STA STATUS ;STORE BREAK ABORT STATUS CODE ; LDX STACKP TXS ;RESTORE STACK POINTER ; DEC BRKKEY ;SET BREAK KEY FLAG TO NONZERO CLI ;ALLOW IRQ'S ; JMP RETURN ;GO RETURN ; ; ; ; ; SETVBX: LDA #JTADRL ;STORE TIME OUT ROUTINE ADDRESS STA CDTMA1 LDA #JTADRH STA CDTMA1+1 ; LDA #1 ;SET FOR TIMER 1 ; SEI ;THE SETVBL ROUTINE NEEDS THIS TO CUT SHORT JSR SETVBV ;ANY VBLANKS THAT OCCUR LDA #1 ;SET FOR TIMER 1 STA TIMFLG ;SET FLAG TO NOT TIMED OUT CLI RTS ; ; ; ; ; ; ; ; 'VCOUNT' INTERVAL TIMER MEASUREMENT -- TO -- POKEY FREQ REG VALUE ; CONVERSION TABLE ; ; ; THE VALUES STORED IN THE TABLE ARE 'AUDF+7'. ; ; THE FOLLOWING FORMULAS WERE USED TO DETERMINE THE TABLE VALUES: ; ; F OUT F IN/(2*(AUDF+M)) , WHERE F IN=1.78979 MHZ. & M=7 ; ; FROM THIS WAS DERIVED THE FORMULA USED TO COMPUTE THE ; TABLE VALUES BASED ON A MEASUREMENT OF THE PERIOD BY ; AN INTERVAL OF THE 'VCOUNT' TIMER. ; ; AUDF+7=(11.365167)*T OUT, WHERE T OUT=# OF COUNTS ; (127 USEC. RESOLUTION) OF 'VCOUNT' FOR 1 ; CHARACTER TIME (10 BIT TIMES). ; ; ; ; ; AUDF+7 BAUD RATE VCOUNT INTERVAL ; ------ ----------- ---------------- ; .WORD $27C ;1407 56 ; .WORD $2D7 ;1231 64 ; .WORD $332 ;1094 72 ; .WORD $38D ;985 80 POKTAB: .WORD $3E8 ;895 88 .WORD $443 ;820 96 .WORD $49E ;757 104 .WORD $4F9 ;703 112 .WORD $554 ;656 120 .WORD $5AF ;615 128 .WORD $60A ;579 136 .WORD $665 ;547 144 .WORD $6C0 ;518 152 .WORD $71A ;492 160 .WORD $775 ;469 168 .WORD $7D0 ;447 176 ; .WORD $828 ;428 184 ; .WORD $886 ;410 192 ; .WORD $8E1 ;394 200 ; .WORD $93C ;379 208 ; .WORD $997 ;365 216 ; .WORD $9F2 ;352 224 ; .WORD $A4D ;339 232 ; .WORD $AA8 ;328 240 ; .WORD $803 ;318 248 ; ; ; ; ; CRNTP3 =* *=$14 SIOSPR: .BYTE DSKORG-CRNTP3 ;^GSIOL IS TOO LONG ; .TITLE 'DISK ***** DISKP.SRC ***** 3/9/79 ***** 4:00:00 P.M.' ; ; ; ; ; ; STATVH = DVSTAT/256 STATVL = (-256)*STATVH+DVSTAT ;STATUS POINTER ; ; ; ; ; CONSTANT EQUATES ; DISKID = $31 ;SERIAL BUS DISK I.D. PUTSEC = $50 ;DISK PUT SECTOR DCB COMMAND ; READ = $52 ;DISK GET SECTOR DCB COMMAND ; WRITE = $57 ;DISK PUT SECTOR WITH READ CHECK DCB COMMAND STATC = $53 ;DISK STATUS DCB COMMAND FOMAT = $21 ;DISK FORMAT DCB COMMAND !!!!! ***** NODAT = 0 ;SIO COMMAND FOR "NO DATA" OPERATION GETDAT = $40 ;SIO COMMAND FOR "DATA FROM DEVICE" PUTDAT = $80 ;SIO COMMAND FOR "DATA TO DEVICE" ; ; ; VECTORS ; *=$E450 ; JMP DINIT ;DISK INIT. VECTOR JMP DSKIF ;DISK INTERFACE ENTRY POINT ; ; ; ; ; ; ; CONSTANTS ; *=DSKORG ; ; ; ; ; ; ; ; ; ;*********************************************************************** ; DISK INTERFACE ROUTINE STARTS HERE ;*********************************************************************** ; ; ; ; ; DISK INTERFACE INITIALIZATION ROUTINE ; DINIT: LDA #160 STA DSKTIM ;SET INITIAL DISK TIMEOUT TO 160 SEC RTS ; ; ; ; DISK INTERFACE ENTRY POINT ; DSKIF: LDA #DISKID STA DDEVIC ;SET SERIAL BUS ID IN DCB LDA DSKTIM LDX DCOMND CPX #FOMAT ;IS COMMAND A FORMAT COMMAND? BEQ PUTDTO LDA #7 ;NO, SET TIMEOUT TO 7 SECS. PUTDTO: STA DTIMLO ;PUT DISK TIMEOUT IN DCB LDX #GETDAT ;SET "GET DATA" COMMAND FOR SIO LDY #$80 ;SET BYTE COUNT TO 128 LDA DCOMND ;READ COMMAND IN DCB CMP #WRITE ;IS COMMAND A "PUT SECTOR" COMMAND? BNE CKSTC LDX #PUTDAT ;YES, SET "PUT DATA" COMMAND FOR 610 CKSTC: CMP #STATC ;IS COMMAND A STATUS COMMAND? BNE PUTCNT LDA #STATVL STA DBUFLO LDA #STATVH STA DBUFHI ;SET BUFFER ADDR TO GLOBAL STATUS BUFFER LDY #4 ;YES, SET BYTE COUNT TO 4 PUTCNT: STX DSTATS ;PUT STATUS COMMAND FOR SIO IN DCB STY DBYTLO LDA #0 STA DBYTHI ;PUT BYTE COUNT IN DCB JSR SIOV ;CALL SERIAL I/O. BPL GOODST ;NO ERROR RTS ;NO, GO BACK GOODST: LDA DCOMND ;READ THE COMMAND CMP #STATC ;WAS IT A STATUS COMMAND? BNE PUTBC JSR PUTADR ;PUT BUFFER ADDR IN TEMP REQ. LDY #2 LDA (BUFADR),Y ;READ DISK TIMEOUT VALUE BYTE OF STATUS STA DSKTIM ;PUT IT IN DISK TIMEOUT REQ. PUTBC: LDA DCOMND CMP #FOMAT ;WAS COMMAND A FORMAT COMMAND? BNE ENDDIF FMTD: JSR PUTADR ;YES PUT BUFFER, ADDR INTO TEMP REC LDY #$FE ;SET BUFFER POINTER TWICE: INY INY ;INCR BUFFER POINTER BY 2 RDBAD: LDA (BUFADR),Y ;READ LO BYTE BAD SECTOR DATA CMP #$FF BNE TWICE ;IS IT "FF" ? INY ;YES, LDA (BUFADR),Y ;READ HI BYTE BAD SECTOR DATA INY CMP #$FF BNE RDBAD ;IS IT "FF" ? DEY DEY ;YES STY DBYTLO ;PUT BAD SECTOR BYTE COUNT INTO DCB LDA #0 STA DBYTHI ENDDIF: LDY DSTATS RTS ; ; ; ; ; SUBROUTINES ; ; ; PUT BUFFER ADDR FROM DCB INTO TEMP REQ ; PUTADR: LDA DBUFLO STA BUFADR LDA DBUFHI STA BUFADR+1 ;PUT BUFFER ADDR IN TEMP REQ RTS ;*********************************************************************** ; ; ; SPARE BYTE OR MODULE TOO LONG FLAG ; CRNTP4 = * ; ; DSKSPR: .BYTE PRNORG-CRNTP4 ;^GDISKP TOO LONG ; .PAGE .TITLE 'PRINTER ***** PRINTP.SRC ***** 3/9/79 ***** 4:00:00 P ; ; ; ; ; ; ; ; ; ; ; ; DEVICE NUMBER OR CODE EQUATES ; OPNOUT = $2 ;IOCB OPEN FOR OUTPUT COMMAND NBUFSZ = 40 ;PRINT NORMAL BUFFER SIZE DBUFSZ = 20 ;PRINT DOUBLE BUFFFER SIZE SBUFSZ = 29 ;PRINT SIDEWAYS BUFFER SIZE PDEVN = $40 ;PRINTER DEVICE NUMBER ; STATC = $53 ;DCB STATUS COMMAND CODE WRITEC = $57 ;DCB WRITE COMMAND SPACE = $20 ;ASCII SPACE CHAR. N = $4E ;ASCII "N" CHAR. D = $44 ;ASCII "D" CHAR. S = $53 ;ASCII "S" CHAR. ; ; ; PRINTER HANDLER ENTRY POINTS ; ; ; ; *=$E430 ; .WORD PHOPEN-1 ;PRINTER HANDLER OPEN .WORD PHCLOS-1 ;PH CLOSE .WORD BADST-1 ;PH READ .WORD PHWRIT-1 ;PH WRITE .WORD PHSTAT-1 ;PH STATUS .WORD BADST-1 ;PH SPECIAL JMP PHINIT ;PH INIT. .BYTE 0 ;ROM FILLER ; ; ; ; ; *=PRNORG ; ; ; ; ; PRINTER HANDLER INITIALIZATION ROUTINE ; PHINIT: LDA #30 STA PTIMOT ;SET UP INITIAL PRINTER TIMEOUT OF 30 SEC. RTS ; ; ; PRINTER HANDLER CONSTANTS ; PHSTLO: .WORD DVSTAT ;STATUS BUFFER POINTER PHCHLO: .WORD PRNBUF ;CHAR. BUFFER POINTER ; ; ; ; ************************ ; PRINTER HANDLER ROUTINES ; ************************ ; ; ; ; ; ; PRINTER HANDLER STATUS ROUTINE ; PHSTAT: LDA #4 STA PBUFSZ ;SET BUFFER SIZE TO 4 BYTES LDX PHSTLO LDY PHSTLO+1 ;SET POINTER TO STATUS BUFFER LDA #STATC ;SETCOMMAND TO "STATUS" STA DCOMND ;SET STATUS COMMAND STA DAUX1 JSR SETDCB ;GO SETUP DCH JSR SIOV ;SEND STATUS COMMAND BMI BADST ;GO IF ERROR JSR PHPUT ;YES, PUT STATUS INTO GLOBAL BUFFER. BADST: RTS ; ; ; ; ; PRINTER HANDLER OPEN ROUTINE ; PHOPEN: JSR PHSTAT ;DO STATUS COMMAND TO SIO LDA #0 STA PBPNT ;CLEAR PRINT BUFFER POINTER RTS ; ; ; ; ; PRINTER HANDLER WRITE ROUTINE ; PHWRIT: STA PTEMP ;SAVE ACCUM JSR PRMODE ;GO DETERMINE PRINTMODE LDX PBPNT LDA PTEMP ;GET CHAR. SENT BY CID STA PRNBUF,X ;PUT CHAR. IN PRINT BUFFER INX ;INCR. BUFFER POINTER CPX PBUFSZ ;BUFFER POINTERBUFFER SIZE? BEQ BUFFUL STX PBPNT ;SAVE SUFFER POINTER CMP #CR ;IS CHAR. = EOL ? BEQ BLFILL ;IF YES, GO DO BLANK FILL. LDY #SUCCES ;PUT GOOD STATUS IN Y REQ FOR CIO. RTS BLFILL: LDA #SPACE ;PUT BLANK IN ACCUM. FILLBF: STA PRNBUF,X ;STORE IT IN PRINT BUFFER. INX CPX PBUFSZ BNE FILLBF ;BUFFER BLANK FILLED? BUFFUL: LDA #0 STA PBPNT ;CLEAR PRINT BUFFER POINTER LDX PHCHLO LDY PHCHLO+1 ;SET POINTER TO PRINT BUFFER JSR SETDCB ;GO SETUP OCR JSR SIOV ;SEND PRINT COMMAND RTS ;YES. ; ; ; ; ; PRINTER HANDLER CLOSE ROUTINE ; PHCLOS: JSR PRMODE ;GO DETERMINE PRINT MODE LDX PBPNT BNE BLFILL LDY #SUCCES RTS ; ; ; ; ; ; ; ; ; S U B R O U T I N E S ; ; ; ; ; ; SET UP DCB TO CALL SIO ; SETDCB: STX DBUFLO STY DBUFHI ;SET BUFFER POINTER LDA #PDEVN STA DDEVIC ;SET PRINTER BUS I.D. FOR DCB LDA #1 STA DUNIT ;SET UNIT NUMBER TO 1 LDA #$80 ;DEVICE WILL EXPECT DATA LDX DCOMND CPX #STATC ;STATUS COMMAND? BNE PSIOC LDA #$40 ;EXPECT DATA FROM DEVICE PSIOC: STA DSTATS ;SET SIO MODE COMMAND LDA PBUFSZ STA DBYTLO ;SET LO BYTE COUNT LDA #0 STA DBYTHI ;SET HI BYTE COUNT LDA PTIMOT STA DTIMLO ;SET DEVICE TIMEOUT COUNT RTS ; ; ; ; ; GET DEVICE TIMEOUT FROM STATUS & SAVE IT ; PHPUT: LDA DVSTAT+2 STA PTIMOT ;SAVE DEVICE TIMEOUT RTS ; ; ; ; ; DETERMINE PRINT MODE & SETUP PRINT BUFFER SIZE, DCB PRINT ; COMMAND, &. DCB AUX1 FOR PRINT MODE ; PRMODE: LDY #WRITEC ;PUT WRITE COMMAND IN Y REG LDA ICAX2Z ;READ PRINT MODE CMODE: CMP #N BNE CDUBL ;PRINT NORMAL ? LDX #NBUFSZ ;YES, SET NORMAL CHAR. BUFFER SIZE BNE SETBSZ CDUBL: CMP #D BNE CSIDE ;PRINT DOUBLE? LDX #DBUFSZ ;YES, SET DOUBLE CHAR. BUFFER SIZE BNE SETBSZ CSIDE: CMP #S ;PRINT SIDEWAYS ? BNE GOERR ;IF NOT, GO TO ERROR ROUTINE LDX #SBUFSZ ;YES, SET SIDEWAYS BUFFER SIZE SETBSZ: STX PBUFSZ ;STORE PRINT BUFFER SIZE STY DCOMND ;STORE DCB COMMAND STA DAUX1 ;STORE DCB AUX1 PRINT MODE RTS GOERR: LDA #N ;SET DEFAULT PRINT MODE TO NORMAL BNE CMODE ;************************************************************* ; ; ; SPARE BYTE OR MODULE TOO LONG FLAG ; CRNTP5 = * ; ; ; PRNSPR: .BYTE CASORG-CRNTP5 ;^GPRINTP TOO LONG ; .PAGE .TITLE 'CASSET HANDLER 3/12 (DK1:CASCV)' CBUFH = CASBUF/256 CBUFL = (-256)*CBUFH+CASBUF SRSTA = $40 ;SIO READ STATUS SWSTA = $80 ;SIO WRITE STATUS ;MOTRGO = $34 ;MOTRST = $3C ; ; DTA = $FC ;DATA RECORD TYPE BYTE DT1 = $FA ;LAST DATA RECORD EOT = $FE ;END OF TAPE HDR = $FB ;HEADER TONE1 = 2 ;CHANGE TO RECORD MODE TONE TONE2 = 1 ;PRESS PLAY TONE ; ; ; *=CASETV .WORD OPENC-1,CLOSEC-1,GBYTE-1,PBYTE-1,STATU-1,SPECIAL-1 JMP INIT .BYTE 0 ;ROM FILLER BYTE ; ; ; ; USED IN MONITP FOR CASSETTE BOOT ; *=RBLOKV JMP RBLOK ; *=CSOPIV JMP OPINP ; ; *=CASORG ; ; ; INIT ROUTINE ; INIT: LDA #$CC STA CBAUDL LDA #$05 STA CBAUDH ;SET CASSET BAUD RATE TO 600 SPECIAL: ;THATS ALL FOLKS RTS .PAGE ; ; OPEN FUNCTION - WITH NO TIMING ADJUST ; OPENC: LDA ICAX2Z ;GET AX2 STA FTYPE ;SAVE IT FOR FUTURE REFERENCE LDA ICAX1Z AND #$0C ;IN AND OUT BITS CMP #$04 BEQ OPINP CMP #$08 ;SEE IF OPEN FOR OUTPUT BEQ OPOUT RTS ;IF ALREADY OPEN, RETURN LEAVING STATUS=$84 OPINP: LDA #0 STA WMODE ;SET READ MODE STA FEOF ;NO EOF YET SFH: LDA #TONE2 ;TONE FOR PRESS PLAY JSR BEEP ;GO BEEP BMI OPNRTN ;IF ERROR DURING BEEP LDA #MOTRGO STA PACTL ;TURN MOTOR ON .IF PALFLG LDY #$E0 LDX #1 .ENDIF .IF PALFLG-1 LDY #$40 ;5-31-79 9 SEC READ LEADER LDX #2 .ENDIF LDA #3 STA CDTMF3 JSR SETVBV ;SET UP YBLANK TIMER WAITTM: LDA CDTMF3 BNE WAITTM ;WAIT FOR MOTOR TO COME UP TO SPEED LDA #$80 ;NEXT BYTE=NO BYTES IN BUFFER STA BPTR STA BLIM JMP OPOK ;OPEN OK ; ; OPEN FOR OUTPUT ; PBRK: LDY #BRKABT ;BREAK KEY ABORT STATUS DEC BRKKEY ;RESET BREAK KEY OPNRTN: LDA #0 ;CLEAR WRITE MODE FLAG STA WMODE RTS ;AND EXIT. ; OPOUT: LDA #$80 STA WMODE ;SET WRITE MODE LDA #TONE1 ;TELL USER TO TURN ON RECORD MODE JSR BEEP BMI OPNRTN ;IF ERROR DURING BEEP LDA #$CC ;SET BAUD RATE STA AUDF3 ;WHICH SEEMS TO BE NESSECARY LDA #$05 ;FOR SOME OBSCURE REASON STA AUDF4 LDA #$60 STA DDEVIC JSR SENDEV ;TELL POKEY TO WRITE MARKS LDA #MOTRGO ;WRITE 5 SEC BLANK TAPE STA PACTL LDA #3 .IF PALFLG LDX #$3 LDY #$C0 .ENDIF .IF PALFLG-1 LDX #4 ;5/30/79 20 SEC LEADER LDY #$80 .ENDIF JSR SETVBV LDA #$FF STA CDTMF3 WDLR: LDA BRKKEY BEQ PBRK ;IF BREAK DURING WRITE LEADER LDA CDTMF3 BNE WDLR LDA #0 ;INIT BUFFER POINTER STA BPTR OPOK: LDY #SUCCES RTS .PAGE ; ; GET BYTE ; GBYTE: LDA FEOF ;IF AT EOF ALREADY BMI ISEOF ;RETURN EOF STATUS LDX BPTR ;BUFFER POINTER CPX BLIM ;IF END OF BUFFER BEQ RBLOK ;READ ANOTHER BLOCK LDA CASBUF+3,X ;GET NEXT BYTE INC BPTR ;DUMP POINTER LDY #SUCCES ;OK STATUS GBX: RTS RBLOK: LDA #'R ;READ OPCODE JSR SIOSB ;SIO ON SYS BUF TYA BMI GBX ;IF SIO ERRORS, RETURN LDA #0 STA BPTR ;RESET POINTER LDX #$80 ;DEFAULT # BYTES LDA CASBUF+2 CMP #EOT BEQ ATEOF ;IF HEADER, GO READ AGAIN CMP #DT1 ;IF LAST DATA REC BNE NLR LDX CASBUF+130 ;LAST DATA RECORD, GET # BYTES NLR: STX BLIM JMP GBYTE ;GET NEXT BYTE ATEOF: DEC FEOF ;SET FEOF ISEOF: LDY #EOFERR ;ENDFILE STATUS RTS .PAGE ; ; PUT BYTE TO BUFFER ; PBYTE: LDX BPTR ;BUFFER POINTER STA CASBUF+3,X ;STORE CHAR AWAY INC BPTR ;BUMP POINTER LDY #SUCCES ;OK STATUS CPX #127 ;IF BUFFER FULL BEQ *+3 RTS ; WRITE OUT THE BUFFER LDA #DTA ;RECORD TYPE = DATA JSR WSIOSB ;DO WRITE ON SYSTEM BUFFER LDA #0 STA BPTR ;RESET BUFFER POINTER RTS ;EXIT. .PAGE ; ; STATUS - RETURN STATUS INFO THRU DVSTAT ; STATU: LDY #SUCCES RTS .PAGE ; ; CLOSE ; CLOSEC: LDA WMODE ;SEE IF WRITING BMI CLWRT ;300 CLOSE FOR WRITE ; CLOSE FOR READ - FLAG CLOSED LDY #SUCCES ;SUCCESSFULL FCAX: LDA #MOTRST ;STOP THE MOTOR IN CASE WAS SHORT IRQ MODE STA PACTL RTS CLWRT: LDX BPTR ;BUFFER POINTER BEQ WTLR ;IF NO DATA BYTES IN BUFFER, NO DT1 REC STX CASBUF+130 ;WRITE TO LAST RECORD LDA #DT1 ;REC TYPE JSR WSIOSB ;WRITE OUT USER BUFFER BMI FCAX ;GO IF ERROR WTLR: LDX #127 ;ZERO BUFFER LDA #0 ZTBUF: STA CASBUF+3,X DEX BPL ZTBUF LDA #EOT ;WRITE EOT RECORD JSR WSIOSB JMP FCAX ;FLAG CLOSED AND EXIT .PAGE ; ; SUBROUTINES ; ; BEEP - GENERATE TONE ON KEYBOARD SPEAKER ; ON ENTRY A= FREQ ; BEEP: STA FREQ BEEP1: LDA RTCLOK+2 ;CURRENT CLOCK CLC .IF PALFLG ADC #25 .ENDIF .IF PALFLG-1 ADC #30 ; 1 SEC TONE .ENDIF TAX WFL: LDA #$FF STA CONSOL ;TURN ONSPEAKER LDA #0 LDY #$F0 DEY BNE *-1 STA CONSOL ;TURN OFF SPEAKER LDY #$F0 DEY BNE *-1 CPX RTCLOK+2 ;SEE IF 1 SEC IS UP YET BNE WFL DEC FREQ ;COUNT BEEPS BEQ WFAK ;IF ALL DONE GO WAIT FOR KEY TXA CLC .IF PALFLG ADC #8 .ENDIF .IF PALFLG-1 ADC #10 .ENDIF TAX CPX RTCLOK+2 BNE *-2 BEQ BEEP1 ;UNCOND DO BEEP AGIN WEAK: JSR WFAK1 ;USE SIMULATED "JMP (KGETCH)" TYA RTS WFAK1: LDA KEYBDV+5 PHA LDA KEYBDV+4 ;SIMULATE "JMP (KGETCH)" PHA RTS ; ; SIOBS - CALL SIO ON SYSTEM BUFFER ; SIOSB: STA DCOMND ;SAVE COMMAND LDA #0 STA DBYTHI ;SET BUFFER LENGTH LDA #131 STA DBYTLO LDA #CBUFH STA DBUFHI ;SET BUFFER ADDRESS LDA #CBUFL STA DBUFLO CSIO: LDA #$60 ;CASSET PSEUDO DEVICE STA DDEVIC LDA #0 STA DUNIT LDA #35 ;DEVICE TIMEOUT (5/30/79) STA DTIMLO LDA DCOMND ;GET COMMAND SACK LDY #SRSTA ;SIO READ STATUS COMMAND CMP #'R BEQ *+4 LDY #SWSTA ;SIC WRITE STATUS COMMAND STY DSTATS ;SET STATUS FOR SIO LDA FTYPE STA DAUX2 ;INDICATE IF SHORT IRQ MODE JSR SIOV ;GO CALL SIO RTS ; ; WSIOSB - WRITE SIC SYSTEM SUFFER ; WSIOSB: STA CASBUF+2 ;STORE TYPE BYTE LDA #$55 STA CASBUF+0 STA CASBUF+1 LDA #'W ;WRITE JSR SIOSB ;CALL SIO ON SYSTEM BUFFER RTS AND ;RETURN CRNTP6 =* *=$14 CASSPR: .BYTE MONORG-CRNTP6 ;^GCASCV IS TOO LONG ; .TITLE 'MONITOR ***** MONITP.SRC ***** 3/9/79 ***** 4:00:00 P ; ; ; ; CONSTANT EQUATES ; PUTTXT = $9 ;"PUT TEXT RECORD" CIO COMMANDCODE GETCAR = $7 ;"GET CHARACTER" CIO COMMAND CODE PUTCAR = $B ;"PUT CHARACTER" CIO COMMAND CODE INIMLL = $00 ;INITIAL HEM LO LOW BYTE INIMLH = $07 ;INITIAL HEM LO HIGH BYTE ; GOOD = $1 ;GOOD STATUS CODE ; WRITE = $57 ;WRITE COMMAND ; READ = $52 ;READ COMMAND ; STATC = $53 ;STATUS COMMAND SEX = $0 ;SCREEN EDITOR 10CR INDEX CLS = $7D ;CLEAR SCREEN CODE CTRLC = $92 ;KEYBOARD CODE FOR 'CONTROL C' EOF = $88 ;CASSETTE END OF FILE CODE LIRQ = $0 ;LONG IRQ TYPE CODE ; BUFFH = (CASBUF+3)/256 BUFFL = (-256)*BUFFH+CASBUF+3 ;BUFFER POINTER ; ; ; ; THE FOLLOWING EQUATES ARE IN THE CARTRIDGE ADDRESS SPACE. ; ; ; "B" CARTRIDGE ADDR'S ARE 8000-9FFF (36K CONFIG. ONLY) ; "A" CART. ADDR'S ARE A000-BFFF (36K CONFIG. ONLY) ; ; "A" CART. ADDR'S ARE B000-BFFF (48K CONFIG. ONLY) ; *=$BFFA CARTCS: .RES 2 ;CARTRIDGE COLD START ADDRESS. CART: .RES 1 ;CARTRIDGE AVAILABLE FLAG BYTE. CARTFG: .RES 1 ;CARTRIDGE FLAG BYTE. BIT 0=FLAG1, CARTAD: .RES 2 ;2-BYTE CARTRIDGE START VECTOR ; ; ; CARTRIDGE FLAG ACTION DEFINITIONS ; ; ; BIT ACTION IF SET ; ; 7 SPECIAL -- DON'T POWER-UP, JUST RUN CARTRIDGE ; 6-3 NONE ; 2 RUN CARTRIDGE ; 1 NONE ; 0 BOOT DOS ; ; ; ***** ; NOTE ; ***** ; ; 1.IF BIT2 IS 0, GOTO BLACKBOARD MODE. ; 2.IF BIT0 SET THE DISK WILL BE BOOTED BEFORE ANY ; OTHER ACTION. ; ; ; ; ; ; ; ; ; ; POWER-UP VECTOR ; ;*************************** ; *=$FFFC ; ; PVECT .WORD PWRUP POWER-UP VECTOR ;************************ ; ; ; ; ; ; ENTRY POINT VECTOR ; *=BLKBDV ; JMP SIGNON ;BLACK BOARD VECTOR ; *=WARMSV ; JMP RESET ;WARM START VECTOR ; *=COLDSV ; JMP PWRUP ;COLD START VECTOR (9000 FOR RAM VECTOR WRIT ; *=$9000 JSR $900C JMP PWRUP ;(TO HANDLE RAM VECTOR WRITING) JSR $900C JMP RESET ; ; ; *=MONORG ; ; ; ; ; HANDLER TABLE ENTRIES ; TBLENT: .BYTE 'P' .WORD PRINTV .BYTE 'C' .WORD CASETV .BYTE 'E' .WORD EDITRV .BYTE 'S' .WORD SCRENV .BYTE 'K' .WORD KEYBDV ; ; ;TBLLEN = IDENT-TBLENT-1 HANDLER TABLE LENGTH. "MOVED TO LINE 8 ; ; ***** PRINT MESSAGES ***** ; ; IDENT: .BYTE CLS,'ATARI COMPUTER - MEMO PAD',CR ; IDENTH = IDENT/256 IDENTL = (-256)*IDENTH+IDENT ;SYSTEM I.D. MSG POINTER ; TBLLEN = IDENT-TBLENT-1 ;HANDLER TABLE LENGTH DERR5: .BYTE 'BOOT ERROR',CR ; DERRH = DERR5/256 DERRL = (-256)*DERRH+DERR5 ;DISK ERROR MSG POINTER ; ; ; ; ; DEVICE/FILENAME SPECIFICATIONS ; OPNEDT: .BYTE 'E:',CR ;"OPEN SCREEN EDITOR" DEVICE SPEC. ; OPNH = OPNEDT/256 OPNL = (-256)*OPNH+OPNEDT ;SCREEN EDITOR OPEN POINTER ; ; ; ; ;***************************************************************** ; RESET BUTTON ROUTINE STARTS HERE ; ; RESET: SEI ;DISABLE IRQ INTERRUPTS LDA COLDST ;WERE WE IN MIDDLE OF COLDSTART? BNE PWRUP ;YES, GO TRY IT AGAIN LDA #$FF BNE PWRUP1 ;SET WARM START FLAG ; ; ; ;*************************************************************** ; POWER UP ROUTINES START HERE ;*************************************************************** ; PWRUP: SEI ;DISABLE IRQ INTERRUPTS LDA #0 ;CLEAR WARMSTART FLAG PWRUP1: STA WARMST CLD ;CLEAR DECIMAL FLAG. LDX #$FF TXS ;SET STACK POINTER JSR SPECL ;CARTRIDGE SPECIAL CASE? JSR HARDI ;DO HARDWARE INITIALIZATION LDA WARMST ;IS IT WARMSTART? BNE ZOSRAM ;YES, ONLY ZERO OS RAM ; ZERORM: LDA #0 LDY #WARMST STA RAMLO STA RAMLO+1 ;INITIALIZE RAM POINTER CLRRAM: STA (RAMLO),Y ;CLEAR MEMORY LOC. INY CPY #0 ;AT END OF PAGE? BNE CLRRAM INC RAMLO+1 ;YES. INCR PAGE POINTER LDX RAMLO+1 CPX TRAMSZ ;AT END OF MEM? BNE CLRRAM ;NO. ; ; INITIALIZE DOSVEC TO POINT TO SIGNON (BLACKBOARD) LDA BLKBDV+1 STA DOSVEC ;USE BLACKBOARD VECTOR LDA BLKBDV+2 ;FOR DOSVEC STA DOSVEC+1 LDA #$FF STA COLDST ;SET TO SHOW IN MIDDLE OF COLDSTART BNE ESTSCM ;GO AROUND ZOSRAM ; ; CLEAR OS RAM (FOR WARMSTART) ZOSRAM: LDX #0 TXA ZOSRM2: STA $200,X ;CLEAR PAGES 2 AND 3 STA $300,X DEX BNE ZOSRM2 LDX #INTZBS ZOSRM3: STA 0,X ;CLEAR ZERO PAGE LOCATIONS INTZBS-7F INX BPL ZOSRM3 ; ; ESTABLISH SCREEN MARGINS ESTSCM: LDA #LEDGE STA LMARGN LDA #REDGE STA RMARGN ; ; ; MOVE VECTOR TABLE FROM ROM TO RAM OPSYS: LDX #$25 MOVVEC: LDA VCTABL,X ;ROM TABLE STA INTABS,X ;TO RAM DEX BPL MOVVEC JSR OSRAM ;DO O.S. RAM SETUP CLI ;ENABLE IRQ INTERRUPTS ; ; ; LINK HANDLERS ; LDX #TBLLEN NXTENT: LDA TBLENT,X ;READ HANDLER TABLE ENTRY STA HATABS,X ;PUT IN TABLE DEX BPL NXTENT ;DONE WITH ALL ENTRIES? ; ; ; ; ; ; INTERROGATE CARTRIDGE ADDR. SPACE TO SEE WHICH CARTRIDGES THERE ARE ; LDX #0 STX TSTDAT ;CLEAR "B" CART. FLAG STX TRAMSZ ;CLEAR "A" CART. FLAG LDX RAMSIZ CPX #$90 ;RAM IN "B" CART. SLOT? BCS ENDBCK LDA CART-$2000 ;NO. BNE ENDBCK ;CART. PLUGGED INTO "B" SLOT'? INC TSTDAT ;YES, SET "B" CART, FLAG JSR CBINI ;INITIALIZE CARTRIDGE "B" ; ENDBCK: LDX RAMSIZ CPX #$B0 ;RAM IN "A" CART. SLOT? BCS ENDACK LDX CART ;NO, BNE ENDACK ;CART. PLUGGED INTO "A" SLOT? INC TRAMSZ ;YES, SET "A" CART. FLAG JSR CAINI ;INITIALIZE CARTRIDGE "A" ; ; ; OPEN SCREEN EDITOR ; ENDACK: LDA #3 LDX #SEX STA ICCOM,X ;OPEN I/O COMMAND LDA #OPNL STA ICBAL,X LDA #OPNH STA ICBAH,X ;SET BUFFER POINTER TO OPEN SCREEN EDITOR LDA #$C STA ICAX1,X ;SET UP OPEN FOR INPUT/OUTPUT JSR CIOV ;GO TO CIO ; BPL SCRNOK ;BR IF NO ERROR JMP PWRUP ;RETRY PWRUP IF ERROR (SHOULD NEVER HAPPEN!) SCRNOK: INX ;SCREEN OK, SO WAIT FOR YBLANK TO BNE SCRNOK ;BRING UP THE DISPLAY INY BPL SCRNOK ; ; ; DO CASSETTE BOOT JSR CSBOOT ;CHECK, BOOT, AND INIT ; ; CHECK TO SEE IF EITHER CARTRIDGE WANTS DISK BOOT LDA TRAMSZ ;CHECK BOTH CARTRIDGES ORA TSTDAT ; BEQ NOCART ;NEITHER CARTRIDGE LIVES LDA TRAMSZ ;"A" CART? BEQ NOA1 ;NO LDA CARTFG ;GET CARTRIDGE MODE FLAG NOA1: LDX TSTDAT ;"B" CART? BEQ NOB1 ;NO ORA CARTFG-$2000 ;ADD OTHER FLAG NOB1: AND #1 ;DOES EITHER CART WANT BOOT? BEQ NOBOOT ;NO ; ; DO DISK BOOT NOCART: JSR BOOT ;CHECK. BOOT. AND INIT ; ; GO TO ONE OF THE CARTRIDGES IF THEY SO DESIRE NOBOOT: LDA #0 STA COLDST ;RESET TO SHOW DONE WITH COLDSTART LDA TRAMSZ ;"A" CART? BEQ NOA2 ;NO LDA CARTFG ;GET CARTRIDGE MODE FLAG AND #4 ;DOES IT WANT TO RUN? BEQ NOA2 ;NO JMP (CARTCS) ;RUN "A" CARTRIDGE NOA2: LDA TSTDAT ;"B" CART? BEQ NOCAR2 ;NO LDA CARTFG-$2000 ;GET "B" MODE FLAG AND #4 ;DOES IT WANT TO RUN? BEQ NOCART ;NO JMP (CARTCS-$2000) ;RUN "B" CARTRIDGE ; ; NO CARTRIDGES, OR NEITHER WANTS TO RUNS ; SO GO TO DOSVEC (DOS, CASSETTE, OR BLACKBOARD) NOCAR2: JMP (DOSVEC) ; ; PRINT SIGN-ON MESSAGE SIGNON: LDX #IDENTL LDY #IDENTH JSR PUTLIN ;GO PUT SIGN-ON MSG ON SCREEN ; ; ; ; BLACKBOARD ROUTINE BLACKB: JSR BLKB2 ;"JSR EGETCH" JMP BLACKB ;FOREVER BLKB2: LDA EDITRV+5 ;HIGH BYTE PHA LDA EDITRV+4 ;LOW BYTE PHA RTS ;SIMULATES "JMP (EDITRV)" ; ; ; CARTRIDGE INITIALIZATION INDIRECT JUMPS CAINI: JMP (CARTAD) CBINI: JMP (CARTAD-$2000) .PAGE ; ; ; ; ; ; ; S U B R O U T I N E S ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; CHECK FOR HOW MUCH RAM & SPECIAL CARTRIDGE CASE. ; IF SPECIAL CARTRIDGE CASE, DON'T GO BACK -- GO TO CART. ; SPECL: LDA CART ;CHECK FOR RAM OR CART BNE ENSPE2 ;GO IF NOTHING OR MAYBE RAM INC CART ;NOW DO RAM CHECK LDA CART ;IS IT ROM? BNE ENSPEC ;NO LDA CARTFG ;YES, BPL ENSPEC ;BIT SET? JMP (CARTAD) ;YES, GO RUN CARTRIDGE ; ; CHECK FOR AMOUNT OF RAM ; ; ENSPEC: DEC CART ;RESTORE RAM IF NEEDED ENSPE2: LDY #0 STY RAMLO+1 LDA #$10 STA TRAMSZ ;SET RAM POINTER TO 4K. HOWMCH: LDA (RAMLO+1),Y ;READ RAM LOCATION EOR #$FF ;INVERT IT. STA (RAMLO+1),Y ;WRITE INVERTED DATA. CMP (RAMLO+1),Y ;READ RAM AGAIN BNE ENDRAM EOR #$FF ;CONVERT IT BACK STA (RAMLO+1),Y ;RESTORE ORIGINAL RAMDATA LDA TRAMSZ CLC ADC #$10 STA TRAMSZ ;INCR. RAM POINTER BY 4K. BNE HOWMCH ;GO FIND HOW MUCH RAM. ENDRAM: RTS ; ; ; ; HARDWARE INITIALIZATION ; ; HARDI: LDA #0 TAX CLRCHP: STA $D000,X STA $D400,X STA $D200,X STA $D300,X INX BNE CLRCHP RTS ; ; ; O.S. RAM SETUP ; OSRAM: DEC BRKKEY ;TURN OFF BREAK KEY FLAG LDA #.LOW.BRKKY2 STA BRKKY LDA #.HIGH.BRKKY2 STA BRKKY+1 LDA TRAMSZ ;READ RAM SIZE IN TEMP. REG. STA RAMSIZ ;SAVE IT IN RAM SIZE. STA MEMTOP+1 ;INIT. MEMTOP ADDR HI BYTE LDA #0 STA MEMTOP ;INIT. MEMTOP ADDR LO BYTE LDA #INIMLL STA MEMLO LDA #INIMLH STA MEMLO+1 ;INITIALIZE MEMLO ADDR VECTOR JSR EDITRV+$C ;EDITOR INIT. JSR SCRENV+$C ;SCREEN INIT. JSR KEYBDV+$C ;KEYBOARD INIT. JSR PRINTV+$C ;PRINTER HANDLER INIT JSR CASETV+$C ;CASSETTE HANDLER INIT JSR CIOINV ;CIO INIT. JSR SIOINV ;SIO INIT. JSR INTINV ;INTERRUPT HANDLER INIT. LDA CONSOL AND #$1 BNE NOKEY ;GAME START KEY DEPRESSED? INC CKEY ;YES. SET KEY FLAG. NOKEY: RTS ; ; ; DO BOOT OF DISK ; BOOT: LDA WARMST BEQ NOWARM ;WARMSTART? LDA BOOT? ;YES, AND #1 BEQ NOINIT ;VALID BOOT? JSR DINI ;YES, RE-INIT. DOS SOFTWARE NOINIT: RTS NOWARM: LDA #1 STA DUNIT ;ASSIGN DISK DRIVE NO. LDA #STATC STA DCOMND ;SET UPSTATUS COMMAND JSR DSKINV ;GO DO DISK STATUS BPL DOBOOT ;IS STATUS FROM 510 GOOD? RTS ;NO, GO BACK WITH BAD BOOT STATUS ; DOBOOT: LDA #0 STA DAUX2 LDA #1 STA DAUX1 ;SET SECTOR # TO 1. LDA #BUFFL STA DBUFLO LDA #BUFFH STA DBUFHI ;SET UP BUFFER ADDR SECT1: JSR GETSEC ;GET SECTOR BPL ALLSEC ;STATUS O.K.? BADDSK: JSR DSKRDE ;NO, GO PRINT DISK READ ERROR LDA CASSBT BEQ DOBOOT ;CASSETTE BOOT? RTS ;YES, QUIT ALLSEC: LDX #3 RDBYTE: LDA CASBUF+3,X ;READ A BUFFER BYTE STA DFLAGS,X ;STORE IT DEX BPL RDBYTE ;DONE WITH 4 BYTE TRANSFER LDA BOOTAD ;YES. STA RAMLO LDA BOOTAD+1 STA RAMLO+1 ;PUT BOOT ADDR INTO Z. PAGE RAM LDA CASBUF+7 STA DOSINI ;ESTABLISH DOS INIT ADDRESS LDA CASBUF+8 STA DOSINI+1 MVBUFF: LDY #$7F ;YES, SET BYTE COUNT MVNXB: LDA CASBUF+3,Y STA (RAMLO),Y ;MOVE A BYTE FROM SECTOR BUFFER TO BOOT ADDR DEY BPL MVNXB ;DONE ? CLC ;YES, LDA RAMLO ADC #$80 STA RAMLO LDA RAMLO+1 ADC #0 STA RAMLO+1 ;INCR BOOT LOADER BUFFER POINTER DEC DBSECT ;DECR # OF SECTORS. BEQ ENBOOT ;MORE SECTORS ? INC DAUX1 ;YES INCR SECTOR # SECTX: JSR GETSEC ;GO GET SECTOR. BPL MVBUFF ;STATUS O.K. ? JSR DSKRDE ;NO, GO PRINT DISK READ ERROR LDA CASSBT BNE BADDSK ;IF CASSETTE, QUIT. BEQ SECTX ;IF DISK, TRY SECTOR AGAIN. ENBOOT: LDA CASSBT BEQ XBOOT ;A CASSETTE BOOT ? JSR GETSEC ;YES, GET EOF RECORD, BUT DON'T USE IT. XBOOT: JSR BLOAD ;GO EXECUVE BOOT LOADER BCS BADDSK ;IF BAD BOOT, DO IT OVER AGAIN JSR DINI ;GO INIT. SOFTWARE INC BOOT? ;SHOW BOOT SUCCESS RTS BLOAD: CLC LDA BOOTAD ADC #6 STA RAMLO LDA BOOTAD+1 ADC #0 STA RAMLO+1 ;PUT START ADDR OF BOOTLOADER INTO RAM JMP (RAMLO) DINI: JMP (DOSINI) ; ; ; ; ; DISPLAY DISK READ ERROR MSG ; DSKRDE: LDX #DERRL LDY #DERRH ; ; ; ; PUT LINE ON SCREEN AT PRESENT CURSOR POSITION ; ; X-REG -- LO BYTE, BEGIN ADDR OF LINE ; Y-REG -- HI BYTE, BEGIN ADDR OF LINE ; PUTLIN: TXA LDX #SEX STA ICBAL,X TYA STA ICBAH,X ;SET UP ADDR OF BEGIN OF LINE LDA #PUTTXT STA ICCOM,X ;"PUT TEXT RECORD" COMMAND LDA #$FF STA ICBLL,X ;SET BUFFER LENGTH JSR CIOV ;PUT LINE ON SCREEN RTS ; ; ; ; ; GET SECTOR FROM DISK 0 ; GETSEC: LDA CASSBT BEQ DISKM ;CASSETTE BOOT? JMP RBLOKV ;YES, GO TO READ BLOCK ROUTINE DISKM: LDA #READ STA DCOMND ;SET READ SECTOR COMMAND LDA #1 STA DUNIT ;SET DRIVE NO. TO DRIVE 0 JSR DSKINV ;GET SECTOR RTS ; ; ; ; DO CHECK FOR CASSETTE BOOT & IF SO DO BOOT ; CSBOOT: LDA WARMST ;WARMSTART? BEQ CSBOT2 ;NO LDA BOOT? ;GET BOOT FLAG AND #2 ;WAS CASSETTE BOOT SUCCESFULL? BEQ NOCSB2 ;NO JSR CINI ;YES, INIT CASSETTE SOFTWARE NOCSB2: RTS ; CSBOT2: LDA CKEY BEQ NOCSBT ;"C" KEY FLAG SET ? LDA #$80 ;YES, STA FTYPE ;SET LONG IRQ TYPE INC CASSBT ;SET CASSETTE BOOT FLAG JSR CSOPIV ;OPEN CASSETTE FOR INPUT JSR SECT1 ;DO BOOT & INIT. LDA #0 STA CASSBT ;RESET CASSETTE BOOT FLAG STA CKEY ;CLEAR KEY FLAG ASL BOOT? ;SHIFT BOOT FLAG (NOW=2 IF SUCCESS) LDA DOSINI STA CASINI ;MOVE INIT ADDRESS FOR CASSETTE LDA DOSINI+1 STA CASINI+1 NOCSBT: RTS ; CINI: JMP (CASINI) ;INIT CASSETTE ;**************************************************************** ; ; ; SPARE BYTE OR MODULE TOO LONG FLAG ; CRNTP7 =* ; *=$14 MONSPR: .BYTE KBDORG-CRNTP7 ;^GMONITP TOO LONG ; .PAGE .TITLE 'DISPLAY HANDLER -- 10-30-78 -- DISPLC' ; ; HANDLER DEPENDENT EQUATES ; CLRCOD = $7D ;CLEAR SCREEN ATASCI CODE CNTL1 = $9F ;POKEY KEY CODE FOR ^1 ; FRMADR = SAVADR TOADR = MLTTMP ; .PAGE ; ; *=EDITRV ; ; SCREEN EDITOR HANDLER ENTRY POINT ; EDITOR: .WORD EOPEN-1 .WORD RETUR1-1 ;(CLOSE) .WORD EGETCH-1 .WORD EOUTCH-1 .WORD RETUR1-1 ;(STATUS) .WORD NOFUNC-1 ;(SPECIAL) JMP PWRONA .BYTE 0 ;ROM FILLER BYTE ; *=SCRENV ; ; DISPLAY HANDLER ENTRY POINT ; DISPLA: .WORD DOPEN-1 .WORD RETUR1-1 ;(CLOSE) .WORD GETCH-1 .WORD OUTCH-1 .WORD RETUR1-1 ;(STATUS) .WORD DRAW-1 ;(SPECIAL) JMP PWRONA .BYTE 0 ;ROM FILLER BYTE ; ; ; ; ; KEYBOARD HANDLER ENTRY POINT ; KBDHND: .WORD RETUR1-1 .WORD RETUR1-1 ;(CLOSE) .WORD KGETCH-1 .WORD NOFUNC-1 ;(OUTCH) .WORD RETUR1-1 ;(STATUS) .WORD NOFUNC-1 ;(SPECIAL) JMP PWRONA .BYTE 0 ;ROM FILLER BYTE ; ; ; INTERRUPT VECTOR TABLE ENTRY *=VCTABL-INTABS+VKEYBD .WORD PIRQ5 ;KEYBOARD IRQ INTERRUPT VECTOR ; *=KBDORG ; PWRONA: LDA #$FF STA CH LDA MEMTOP+1 AND #$F0 ;INSURE 4K PAGE BOUNDARY STA RAMTOP LDA #$40 ;DEFAULT TO UPPER CASE ALPHA AT PWRON STA SHFLOK RTS ;POWER ON COMPLETED .PAGE ; ; ; BEGIN DISPLAY HANDLER OPEN PROCESSING ; DOPEN: LDA ICAX2Z ;GET AUX 2 BYTE AND #$F BNE OPNCOM ;IF MODE ZERO, CLEAR ICAX1Z EOPEN: LDA ICAX1Z ;CLEAR "CLR INHIBIT" AND "MXD MODE" BITS AND #$F STA ICAX1Z LDA #0 OPNCOM: STA DINDEX LDA #$E0 ;INITIALIZE GLOBAL VBLANK RAM STA CHBAS LDA #2 STA CHACT STA SDMCTL ;TURN OFF DMA NEXT VBLANK LDA #SUCCES STA DSTAT ;CLEAR STATUS LDA #$C0 ;DO IRQEN ORA POKMSK STA POKMSK STA IRQEN LDA #0 STA TINDEX ;TEXT INDEX MUST ALWAYS BE 0 STA ADRESS STA SWPFLG STA CRSINH ;TURN CURSOR ON ATOPEN LDY #14 ;CLEAR TAB STOPS LDA #1 ;INIT TAB STOPS TO EVERY 8 CHARACTERS CLRTBS: STA TABMAP,Y DEY BPL CLRTBS LDX #4 ;LOAD COLOR REGISTERS DOPEN8: LDA COLRTB,X STA COLOR0,X DEX BPL DOPEN8 LDY RAMTOP ;DO TXTMSC=$2C40 (IF MEMTOP=3000) DEY STY TXTMSC+1 LDA #$60 STA TXTMSC LDX DINDEX LDA ANCONV,X ;CONVERT IT TO ANTIC CODE BNE DOPENA ;IF ZERO, IT IS ILLEGAL OPNERR: LDA #BADMOD ;SET ERROR STATUS STA DSTAT DOPENA: STA HOLD1 LDA RAMTOP ;SET UP AN INDIRECT POINTER STA ADRESS+1 LDY ALOCAT,X ;ALLOCATE N BLOCKS OF 40 BYTES DOPEN1: LDA #40 JSR DBSUB DEY BNE DOPEN1 LDA GPRIOR ;ICLEAR GTIA MODES AND #$3F STA OPNTMP+1 TAY CPX #8 ;TEST IF 320X1 BCC NOT8 TXA ;GET 2 LOW BITS ROR A ROR A ROR A AND #$C0 ;NOW 2 TOP BITS ORA OPNTMP+1 TAY LDA #16 ;SUBTRACT 16 MORE FOR PAGE BOUNDARY JSR DBSUB CPX #11 ;TEST MODE 11 BNE NOT8 ;IF MODE = 11 LDA #6 ;PUT GTIA LUM VALUE INTO BACKGROUND REGISTER STA COLOR4 NOT8: STY GPRIOR ;STORE NEW PRIORITY LDA ADRESS ;SAVE MEMORY SCAN COUNTER ADDRESS STA SAVMSC LDA ADRESS+1 STA SAVMSC+1 VBWAIT: LDA VCOUNT ;WAIT FOR NEXT VBLANK BEFORE MESSING CMP #$7A ;WITH THE DISPLAY LIST BNE VBWAIT JSR DBDEC ;START PUTTING DISPLAY LIST RIGHT UNDER RAM LDA PAGETB,X ;TEST IF DISPLAY LIST WILL BE IN TROUBLE BEQ NOMOD ;OF CROSSING A 256 BYTE PAGE BOUNDARY LDA #$FF ;IF SO, DROP DOWN A PAGE STA ADRESS DEC ADRESS+1 NOMOD: LDA ADRESS ;SAVE END OF DISPLAY LIST FOR LATER STA SAVADR LDA ADRESS+1 STA SAVADR+1 JSR DBDDEC ;(DOUBLE BYTE DOUBLE DECREMENT) LDA #$41 ;(ANTIC) WAIT FOR VBLANK AND JMP TO TOP JSR STORE STX OPNTMP LDA #24 ;INITIALIZE BOTSCR STA BOTSCR LDA DINDEX ;DISALLOW MIXED MODE IF MODE.GE.9 CMP #9 BCS NOTMXD LDA ICAX1Z ;TEST MIXED MODE AND #$10 BEQ NOTMXD LDA #4 STA BOTSCR LDX #2 ;ADD 4 LINES OF TEXT AT BOTTOM OF SCREEN DOPEN2: LDA #2 JSR STORE DEX BPL DOPEN2 LDY RAMTOP ;RELOAD MSC FOR TEXT DEY TYA JSR STORE LDA #$60 JSR STORE LDA #$42 JSR STORE CLC LDA #MXDMDE-NUMDLE ;POINT X AT MIXED MODE TABLE ADC OPNTMP STA OPNTMP NOTMXD: LDY OPNTMP LDX NUMDLE,Y ;GET NUMBER OF DISPLAY LIST ENTRIES DOPEN3: LDA HOLD1 ;STORE N DLE'S JSR STORE DEX BNE DOPEN3 LDA DINDEX ;DO THE MESSY 320X1 PROBLEM CMP #8 BCC DOPEN5 LDX #93 ;GET REMAINING NUMBER OF DLE'S LDA RAMTOP ;RELOAD MEMORY SCAN COUNTER SEC SBC #$10 JSR STORE LDA #0 JSR STORE LDA #$4F ;(ANTIC) RELOAD MSC CODE JSR STORE DOPEN4: LDA HOLD1 ;DO REMAINING DLE'S JSR STORE DEX BNE DOPEN4 DOPEN5: LDA SAVMSC+1 ;POLISH OFF DISPLAY LIST JSR STORE LDA SAVMSC JSR STORE LDA HOLD1 ORA #$40 JSR STORE LDA #$70 ;24 BLANK LINES JSR STORE LDA #$70 JSR STORE LDA ADRESS ;SAVE DISPLAY LIST ADDRESS STA SDLSTL LDA ADRESS+1 STA SDLSTL+1 LDA #$70 ;ADD LAST BLANK LINE ENTRY JSR STORE ;POSITION ADRESS=SDLSTL-1 LDA ADRESS ;STORE NEW MEMTOP STA MEMTOP LDA ADRESS+1 STA MEMTOP+1 LDA SAVADR STA ADRESS LDA SAVADR+1 STA ADRESS+1 LDA SDLSTL+1 JSR STORE LDA SDLSTL JSR STORE LDA DSTAT ;IF ERROR OCURRED ON ALLOCATION, OPEN THE ED BPL DOPEN9 PHA ;SAVE STATUS JSR EOPEN ;OPEN THE EDITOR PLA ;RESTORE STATUS TAY ;AND RETURN IT TO CIO RTS DOPEN9: LDA ICAX1Z ;TEST CLEAR INHIBIT BIT AND #$20 BNE DOPEN7 JSR CLRSCR ;CLEAR SCREEN STA TXTROW ;AND HOME TEXT CURSOR (AC IS ZERO) LDA LMARGN STA TXTCOL DOPEN7: LDA #$22 ;EVERYTHING ELSE IS SET UP ORA SDMCTL ;SO TURN ON DMACTL STA SDMCTL JMP RETUR2 ; ; GETCH: JSR RANGE ;GETCH DOES INCRSR. GETPLT DOESN'T JSR GETPLT JSR INATAC ;CONVERT INTERNAL CODE TO ATASCII JSR INCRSB JMP RETUR1 GETPLT: JSR CONVRT ;CONVERT ROW/COLUMN TO ADRESS LDA (ADRESS),Y AND DMASK SHIFTD: LSR SHFAMT ;SHIFT DATA DOWN TO LOW BITS BCS SHIFT1 LSR A BPL SHIFTD ;(UNCONDITIONAL) SHIFT1: STA CHAR CMP #0 ;RESTORE FLAGS ALSO RTS ; ; ; OUTCH: STA ATACHR JSR RANGE ; JSR OFFCRS OUTCHA: LDA ATACHR ;TEST FOR CLEAR SCREEN CMP #CLRCOD BNE OUTCHE JSR CLRSCR JMP RETUR2 OUTCHE: LDA ATACHR ;TEST FOR CARRIAGE RETURN CMP #CR BNE OUTCHB JSR DOCRWS ;DO CR JMP RETUR2 OUTCHB: JSR OUTPLT JSR INCRSR JMP RETUR2 ; ; OUTPLT: LDA SSFLAG ;*****LOOP HERE IF START/STOP FLAG ISNON-0 BNE OUTPLT LDX #2 CRLOOP: LDA ROWCRS,X ;SAVE CURSOR LOCATION FOR DRAW LINE TO DRAW STA OLDROW,X DEX BPL CRLOOP LDA ATACHR ;CONVERT ATASCII(ATACHR) TO INTERNAL(CHAR) TAY ;SAVE ATACHR ROL A ROL A ROL A ROL A AND #3 TAX ;X HAS INDEX INTO ATAINT TYA ;RESTORE ATACHR AND #$9F ;STRIP OFF COLUMN ADDRESS ORA ATAINT,X ;OR IN NEW COLUMN ADDRESS OUTCH2: STA CHAR JSR CONVRT LDA CHAR SHIFTU: LSR SHFAMT ;SHIFT UP TO PROPER POSITION BCS SHIFT2 ASL A JMP SHIFTU SHIFT2: AND DMASK STA TMPCHR ;SAVE SHIFTED DATA LDA DMASK ;INVERT MASK EOR #$FF AND (ADRESS),Y ;MASK OFF OLD DATA ORA TMPCHR ;OR IN NEW DATA STA (ADRESS),Y RTS ; ; RETUR2: JSR GETPLT ;DO CURSOR ON THE WAY OUT STA OLDCHR LDX DINDEX ;GRAPHICS HAVE INVISIBLE CURSOR BNE RETUR1 LDX CRSINH ;TEST CURSOR INHIBIT BNE RETUR1 EOR #$80 ;TOGGLE MSB JSR OUTCH2 ;DISPLAY IT RETUR1: LDY DSTAT ;RETURN TO CIO WITH STATUS IN Y LDA #SUCCES STA DSTAT ;SET STATUS= SUCCESSFUL COMPLETION LDA ATACHR ;PUT ATACHR IN AC FOR RETURN TO CIO NOFUNC: RTS ;(NON-EXISTENT FUNCTION RETURN POINT) ; ; ; ; END OF DISPLAY HANDLER ; .PAGE ; ; ; ; EGETCH: JSR SWAP JSR ERANGE LDA BUFCNT ;ANYTHING IN THE BUFFER? BNE EGETC3 ;YES LDA ROWCRS ;NO, SO SAVE BUFFER START ADDRESS STA BUFSTR LDA COLCRS STA BUFSTR+1 EGETC1: JSR KGETCH ;LET'S FILL OUR BUFFER STY DSTAT ;SAVE KEYBOARD STATUS LDA ATACHR ;TEST FOR CR CMP #CR BEQ EGETC2 JSR DOSS ;NO, GO PRINT IT JSR SWAP ;JSR DOSS DID SWAP SO SWAP BACK LDA LOGCOL ;BEEP IF NEARING LOGICAL COL 120 CMP #113 BNE EGETC6 JSR BELL EGETC6: JMP EGETC1 EGETC2: JSR OFFCRS ;GET BUFFER COUNT JSR DOBUFC LDA BUFSTR ;RETURN A CHARACTER STA ROWCRS LDA BUFSTR+1 STA COLCRS EGETC3: LDA BUFCNT BEQ EGETC5 EGETC7: DEC BUFCNT ;AND RETURN TILL BUFCNT=0 BEQ EGETC5 LDA DSTAT ;IF ERR, LOOP ON EGETC7 UNTIL BUFR IS E1IPTIE BMI EGETC7 JSR GETCH STA ATACHR JMP SWAP ;AND RETURN WITHOUT TURNING CURSOR BACK ON EGETC5: JSR DOCRWS ;DO REAL CARRIAGE RETURN LDA #CR ;AND RETURN EOL STA ATACHR JSR RETUR2 ;TURN ON CURSOR THEN SWAP STY DSTAT ;SAVE KEYBOARD STATUS JMP SWAP ;AND RETURN THROUGH RETUR1 ; JSRIND: JMP (ADRESS) ;J5R TO THIS CAUSES JSR INDIRECT ; EOUTCH: STA ATACHR ;SAVE ATASCII VALUE JSR SWAP JSR ERANGE DOSS: JSR OFFCRS ;TURN OFF CURSOR JSR TSTCTL ;TEST FOR CONTROL CHARACTERS (Z=1 IF CTL) BEQ EOUTC5 EOUTC6: ASL ESCFLG ;ESCFLG ONLY WORKS ONCE JSR OUTCHE ERETN: JMP SWAP ;AND RETURN THROUGH RETUR1 EOUTC5: LDA DSPFLG ;DO DSPFLG AND ESCFLC ORA ESCFLG BNE EOUTC6 ;IF NON-0 DISPLAY RATHER THAN EXECUTE IT ASL ESCFLG INX ;PROCESS CONTROL CHARACTERS LDA CNTRLS,X ;GET DISPLACEMENT INTO ROUTINE STA ADRESS LDA CNTRLS+1,X ;GET HIGH BYTE STA ADRESS+1 JSR JSRIND ;DO COMPUTED JSR JSR RETUR2 ;DO CURSOR JMP SWAP ;ALL DONE SO RETURN THROUGH RETUR1 ; ; ; ; ; END SCREEN EDITOR. ; ; ; BEGIN KEYBOARD HANDLER ; ; ; ; KGETC2: LDA #$FF STA CH KGETCH: LDA ICAX1Z ;TEST LSB OF AUX1 FOR SPECIAL EDITOR READ MO LSR A BCS GETOUT LDA #BRKABT LDX BRKKEY ;TEST BREAK BEQ K7 ;IF BREAK, PUT BRKABT IN DSTAT AND CRIN ATA LDA CH CMP #$FF BEQ KGETCH STA HOLDCH ;SAVE CH FOR SHIFT LOCK PROC LDX #$FF ;"CLEAR" CH STX CH JSR CLICK ;DO KEYBOARD AUDIO FEEDBACK (A IS OK) KGETC3: TAX ;DO ASCCON CPX #$C0 ;TEST FOR CTL & SHIFT TOGETHER BCC ASCCO1 LDX #3 ;BAD CODE ASCCO1: LDA ATASCI,X STA ATACHR ;DONE CMP #$80 ;DO NULLS BEQ KGETC2 CMP #$81 ;CHECK ATARI KEY BNE KGETC1 LDA INVFLG EOR #$80 STA INVFLG JMP KGETC2 ;DONT RETURN A VALUE KGETC1: CMP #$82 ;CAPS/LOWER. BNE K1 LDA #0 ;CLEAR SHFLOK STA SHFLOK BEQ KGETC2 K1: CMP #$83 ;SHIFT CAPS/LOWER BNE K2 LDA #$40 STA SHFLOK ;SHIFT BIT BNE KGETC2 K2: CMP #$84 ;CNTL CAPS/LOWER BNE K3 LDA #$80 ;CNTL BIT STA SHFLOK BNE KGETC2 K3: CMP #$85 ;DO EOF BNE K6 LDA #EOFERR K7: STA DSTAT STA BRKKEY ;RESTORE BREAK GETOUT: LDA #CR ;PUT CR IN ATACHR BNE K8 ;(UNCONDITIONAL) K6: LDA HOLDCH ;PROCESS SHIFT LOCKS CMP #$40 ;REGULAR SHIFT AND CONTROL TAKE PRECEDENCE BCS K5 ;OVER LOCK LDA ATACHR ;TEST FOR ALPHA CMP #$61 ;LOWER CASE A BCC K5 ;NOT ALPHA IF LT CMP #$7B ;LOWER CASE Z+1 BCS K5 ;NOT ALPHA IF GE LDA SHFLOK ;DO SHIFT/CONTROL LOCK BEQ K5 ;IF NO LOCK. DONT RE-DO IT ORA HOLDCH JMP KGETC3 ;DO RETRY K5: JSR TSTCTL ;DONT INVERT M58 OF CONTROL CHARACTERS BEQ K4 LDA ATACHR EOR INVFLG K8: STA ATACHR K4: JMP RETUR1 ;ALL DONE ; ; .PAGE ; ; ;CONTROL CHARACTER PROCESSORS ; ESCAPE: LDA #$80 ;SET ESCAPE FLAG STA ESCFLG RTS CRSRUP: DEC ROWCRS BPL COMRET LDX BOTSCR ;WRAPAROUND DEX UPDNCM: STX ROWCRS COMRET: JMP STRBEG ;CULVERT ROW AND COL TO LOGCOL AND RETURN CRSRDN: INC ROWCRS LDA ROWCRS CMP BOTSCR BCC COMRET LDX #0 BEQ UPDNCM ;(UNCONDITIONAL) CRSRLF: DEC COLCRS LDA COLCRS BMI CRSRL1 ;(IF LMARGN=0, THIS ELIMINATES PROBLEM CASE) CMP LMARGN BCS COMRE1 CRSRL1: LDA RMARGN LFRTCM: STA COLCRS COMRE1: JMP DOLCOL ;COLVERT ROW AND COL TO LOGCOL AND RETURN CRSRRT: INC COLCRS LDA COLCRS CMP RMARGN BCC COMRE1 BEQ COMRE1 ;(CAUSE OLE) LDA LMARGN JMP LFRTCM ;UNCONDITIONAL TO COMMON STORE CLRSCR: JSR PUTMSC LDY #0 TYA ;PUT 0 IN THEAC CLRSC2: STA (ADRESS),Y ;(AC IS ZERO) INY BNE CLRSC2 INC ADRESS+1 LDX ADRESS+1 CPX RAMTOP BCC CLRSC2 LDA #$FF ;CLEAN UP LOGICAL LINE BITMAP CLRSC3: STA LOGMAP,Y ;(Y IS ZERO AFTER CLRSC2 LOOP) INY CPY #4 BCC CLRSC3 HOME: JSR COLCR ;PLACE COLCRS AT LEFT EDGE STA LOGCOL STA BUFSTR+1 LDA #0 STA ROWCRS STA COLCRS+1 STA BUFSTR RTS ; BS: LDA LOGCOL ;BACKSPACE CMP LMARGN BEQ BS1 BSA: LDA COLCRS ;LEFT EDGE? CMP LMARGN BNE BS3 ;NO JSR DELTIM ;YES, SEE IF LINE SHOULD BE DELETED BS3: JSR CRSRLF LDA COLCRS CMP RMARGN BNE BS2 LDA ROWCRS BEQ BS2 JSR CRSRUP BS2: LDA #$20 ;MAKE BACKSPACE DESTRUCTIVE STA ATACHR JSR OUTPLT BS1: JMP DOLCOL ;AND RETURN TAB: JSR CRSRRT ;BEGIN SEARCH LDA COLCRS ;TEST FOR NEW LINE CMP LMARGN BNE TAB1 ;NO JSR DOCR ;DO CARRIAGE RETURN JSR LOGGET ;CHECK IF END OF LOGICAL LINE BCC TAB1 ;NO, CONTINUE BCS TAB2 ;(UNCONDITIONAL) TAB1: LDA LOGCOL ;CHECK FOR TAB STOP JSR BITGET BCC TAB ;NO, SO KEEP LOOKING TAB2: JMP DOLCOL ;CULVERT ROW AND COL TO LOGCOL AND RETURN SETTAB: LDA LOGCOL JMP BITSET ;SET BIT IN MAP AND RETURN CLRTAB: LDA LOGCOL JMP BITCLR ;CLEAR " " " " " INSCHR: JSR PHACRS JSR GETPLT ;GET CHARACTER UNDER CURSOR STA INSDAT LDA #0 STA SCRFLG INSCH4: JSR OUTCH2 ;STORE DATA LDA LOGCOL ;SAVE LOGCOL: IF AFTER INCRSA LOGCOL IS PHA ;< THAN IT IS NOW, END LOOP JSR INCRSA ;SPECIAL INCRSR ENTRY POINT PLA CMP LOGCOL BCS INSCH3 ;QUIT INSCH1: LDA INSDAT ;KEEP GOING PHA JSR GETPLT STA INSDAT PLA JMP INSCH4 INSCH3: JSR PLACRS INSCH6: DEC SCRFLG BMI INSCH5 ;IF SCROLL OCCURRED DEC ROWCRS ;MOVE CURSOR UP BNE INSCH6 ;(UNCOND) CONTINUE UNTIL SCRFLG IS MINUS INSCH5: JMP DOLCOL ;CULVERT ROW AND COL TO LOGCOL AND RETURN ; ; DELCHR: JSR PHACRS DELCH1: JSR CONVRT ;GET DATA TO THE RIGHT OF THE CURSOR LDA ADRESS STA SAVADR ;SAVE ADRESS TO KNOW WHERE TO PUT DATA LDA ADRESS+1 STA SAVADR+1 LDA LOGCOL PHA JSR INCRSB ;PUT CURSOR OVER NEXT CHARACTER PLA CMP LOGCOL ;TEST NEW LOGCOL AGAINST OLD LOGCOL BCS DELCH2 ;IF OLD.GE.NEW THEN QUIT LDA ROWCRS ;IS ROW OFF SCREEN? CMP BOTSCR BCS DELCH2 ;YES, SO QUIT JSR GETPLT ;GET DATA UNDER CURSOR LDY #0 STA (SAVADR),Y ;PUT IT IN PREVIOUS POSITION BEQ DELCH1 ;AND LOOP (UNCONDITIONAL) DELCH2: LDY #0 TYA STA (SAVADR),Y ;CLEAR THE LAST POSITION JSR DELTIA ;TRY TO DELETE A LINE JSR PLACRS JMP DOLCOL ;AND RETURN INSLIN: SEC ;INSLIN PUTS "1" INTO BIT MAP INSLIA: JSR EXTEND ;ENTRY POINT FOR C=0 LDA LMARGN ;DO CARRIAGE RETURN (NO LF) STA COLCRS JSR CONVRT ;GET ADDRESS LDA ADRESS ;SET UP TO=40+FROM (FROM = CURSOR) STA FRMADR CLC ADC #40 STA TOADR LDA ADRESS+1 STA FRMADR+1 ADC #0 STA TOADR+1 LDX ROWCRS ;SET UP LOOP COUNTER CPX #23 BEQ INSLI2 INSLI1: JSR MOVLIN INX CPX #23 BNE INSLI1 INSLI2: JSR CLRLIN ;CLEAR CURRENT LINE JMP DOLCOL ;COLVERT ROW AND COL TO LOGCOL AND RETURN DELLIN: JSR DOLCOL ;GET BEGINNING OF LOG LINE (HOLD1) DELLIA: LDY HOLD1 ;SQUEEZE BIT MAP STY ROWCRS ;PUT CURSOR THERE DELLIB: LDY ROWCRS DELLI1: TYA SEC JSR LO2GET ;GET NEXT BIT PHP TYA CLC ADC #120 PLP JSR BITPUT ;WRITE IT OVER PRESENT BIT INY CPY #24 BNE DELLI1 ;LOOP LDA LOGMAP+2 ;SET LSB ORA #1 STA LOGMAP+2 DELLI2: LDA LMARGN ;DELETE LINE OF DATA USING PART OF SCROLL STA COLCRS ;CR NO LF JSR CONVRT JSR SCROL1 JSR LOGGET ;TEST NEXT LINE FOR CONTINUATION ; IS IT A NEW LOG LINE? BCC DELLIB ;NO SO DELETE ANOTHER JMP DOLCOL ;YES SO DOLCOL AND RETURN BELL: LDY #$20 BELL1: JSR CLICK DEY BPL BELL1 RTS .PAGE ; ; ; ROUTINES ; ; ; DOUBLE BYTE DECREMENT OF INDIRECT POINTER ; INCLUDING DB SUBTRACT AND DB DOUBLE DECREMENT ; DBDDEC: LDA #2 BNE DBSUB ;(UNCONDITIONAL) ; ; STORE DATA INDIRECT AND DECREMENT POINTER ; (PLACED HERE TO SAVE JMP DBDEC AFTER STORE) STORE: LDY DSTAT ;RETURN ON ERROR BMI STROK LDY #0 STOREI: STA (ADRESS),Y ; JMP DBDEC ;DECREMENT AND RETURN ; DBDEC: LDA #1 DBSUB: STA SUBTMP LDA DSTAT ;RETURN ON ERROR BMI STROK LDA ADRESS SEC SBC SUBTMP STA ADRESS BCS DBSUB1 DEC ADRESS+1 DBSUB1: LDA APPMHI+1 ;MARE SURE NOTHING EVER OVERWRITES APPMHI CMP ADRESS+1 BCC STROK ;OK BNE STRERR ;ERROR LDA APPMHI CMP ADRESS BCC STROK STRERR: LDA #SCRMEM ;SHOW MEM TOO SMALL FOR SCREEN ERROR STA DSTAT STROK: RTS ; ; ; ; CONVERT ROW/COLUMN CURSOR INTO REAL ADDRESS (FROM SAVMSC ON UP) ; CONVRT: LDA ROWCRS ;SAVE CURSOR PHA LDA COLCRS PHA LDA COLCRS+1 PHA JSR PUTMSC LDA ROWCRS ;PUT 10*ROWCRS INTO MLTTMP STA MLTTMP LDA #0 STA MLTTMP+1 LDA MLTTMP ;QUICK X8 ASL A ROL MLTTMP+1 STA HOLD1 ;(SAVE 2X VALUE) LDY MLTTMP+1 STY HOLD2 ASL A ROL MLTTMP+1 ASL A ROL MLTTMP+1 CLC ;ADD IN 2X ADC HOLD1 STA MLTTMP LDA MLTTMP+1 ADC HOLD2 STA MLTTMP+1 LDX DINDEX ;NOW SHIFT MLTTMP LEFT DHLINE TIMES TO FINIS LDY DHLINE,X ;MULTIPLY CONVR1: DEY ;LOOP N TIMES BMI CONVR2 ASL MLTTMP ROL MLTTMP+1 JMP CONVR1 CONVR2: LDY DIV2TB,X ;NOW DIVIDE HCRSR TO ACCOUNT FOR PARTIAL BYT LDA COLCRS LDX #7 ;* TRICKY * CONVR3: DEY BMI CONVR4 DEX LSR COLCRS+1 ROR A ROR TMPLBT ;SAVE LOW BITS FOR MASK JMP CONVR3 CONVR4: INY ;SO Y IS ZERO UPON RETURN FROM THIS ROUTINE CLC ADC MLTTMP ;ADD SHIFTED COLCRS TO MLTThP STA MLTTMP BCC CONVR5 INC MLTTMP+1 CONVR5: SEC ;* TRICKY * CONVR6: ROR TMPLBT ;SLIDE A "1" UP AGAINST LOW BITS (CONTINUE T CLC DEX ;AND FINISH SHIFT SO LOW BITS ARE BPL CONVR6 ;RIGHT JUSTIFIED. LDX TMPLBT ;TMPLBT IS NOW THE INDEX INTO DMASKTB LDA MLTTMP ;PREPARE FOR RETURN CLC ADC ADRESS STA ADRESS STA OLDADR ;REMEMBER THIS ADDRESS FOR CURSOR LDA MLTTMP+1 ADC ADRESS+1 STA ADRESS+1 STA OLDADR+1 LDA DMASKT,X STA DMASK STA SHFAMT PLA STA COLCRS+1 PLA STA COLCRS PLA STA ROWCRS RTS ; ; ; INCREMENT CURSOR AND DETECT BOTH END OF LINE AND END OF SCREEN ; INCRSB: LDA #0 ;NON-EXTEND ENTRY POINT BEQ INCREC INCRSR: LDA #$9B ;SPECIAL CASE ELIMINATOR INCREC: STA INSDAT INCRSA: INC LOGCOL ;(INSCHR ENTRY POINT) INC COLCRS BNE INCRS2 ;DO HIGH BYTE INC COLCRS+1 INCRS2: LDA COLCRS ;TEST END OF LINE LDX DINDEX CMP COLUMN,X ;TEST TABLED VALUE FOR ALL SCREEN MODES BEQ INC2A ;DO CR IF EQUAL CPX #0 ;MODE 0? BNE INCRS3 ;IF NOT. JUST RETURN CMP RMARGN ;TEST AGAINST RMARGN BEQ INCRS3 ;EGUAL IS OK BCS INC2A ;IF GREATER THAN, DO CR INCRS3: RTS INC2A: CPX #8 ;CHECK MODE BCC DOCR1 ;NOT 320X1 $O DO IT LDA COLCRS+1 ;TEST MED BEQ INCRS3 ;ONLY AT 64 SO DON'T DO IT DOCR1: LDA DINDEX ;DON'T MESS WITH LOGMAP IF NO MODE ZERO BNE DOCR LDA LOGCOL ;TEST LINE OVERRUN CMP #81 BCC DOCR1B ;IF LESS THAN 81 IT IS DEFINITELY NOT LINE 3 LDA INSDAT BEQ DOCR ;ONLY DO LOG LINE OVERFLOW IF INSDAT <>0 JSR DOCRWS ;LOG LINE OVERFLOW IS SPECIAL CASE JMP INCRS1 ;RETURN DOCR1B: JSR DOCR ;GET IT OVER WITH LDA ROWCRS CLC ;TEST LOGICAL LINE BIT MAP ADC #120 JSR BITGET BCC DOCR1A ;DON'T EXTEND IF OVERRUN IS INTO MIDDLE OF L LDA INSDAT ;DON'T EXTEND IF INSDAT IS ZERO BEQ DOCR1A ;(INSCHR SPECIAL CASE) CLC ;INSERT "0" INTO BIT MAP JSR INSLIA DOCR1A: JMP DOLCOL ;CONVERT ROW AND COL TO LOGCOL AND RETURN NOSCRL: LDA #0 ;DOCR WITHOUT SCROLL BEQ NOSCR1 ;(UNCONDITIONAL) DOCRWS: LDA #$9B ;DOCR WITH SCROLLING (NORMAL MODE) NOSCR1: STA INSDAT DOCR: JSR COLCR ;PLACE COLCRS AT LEFT EDGE LDA #0 STA COLCRS+1 INC ROWCRS DOCR2: LDX DINDEX LDY #24 ;SET UP SCROLL LOOP COUNTER BIT SWPFLG BPL DOCR2A ;BRANCH IF NORMAL LDY #4 TYA BNE DOCR2B ;(UNCONDITIONAL) DOCR2A: LDA NOROWS,X ;GET NO OF ROWS DOCR2B: CMP ROWCRS BNE INCRS1 STY HOLD3 TXA ;DON'T SCROLL IF MODE <> 0 BNE INCRS1 LDA INSDAT ;OR IF INSDAT = 0 BEQ INCRS1 ; LDA INSDAT IF INSDAT <> $9B THEN ROLL IN A 0 CMP #$9B ;TO EXTEND BOTTOM LOGICAL LINE SEC BEQ DOCR4B CLC DOCR4B: JSR SCROLL ;LOOP SACK TO HERE IF >1 SCROLLS INC SCRFLG DEC BUFSTR ;ROWS MOVE UP SO BUFSTR SHOULD TOO DEC HOLD3 LDA LOGMAP SEC ;FOR PARTIAL LINES ROLL IN A "1" BPL DOCR4B ;AGAIN IF PARTIAL LOGICAL LINE LDA HOLD3 ;PLACE CURSOR AT NEW LINE NEAR THE BOTTOM STA ROWCRS INCRS1: JMP DOLCOL ;COLVERT ROW AND COL TO LOGCDL AND RETURN ; ; ; SUBEND: SUBTRACT ENDPT FROM ROWAC OR COLAC. (X=0 OR 2) ; SUBEND: SEC LDA ROWAC,X SBC ENDPT STA ROWAC,X LDA ROWAC+1,X SBC ENDPT+1 STA ROWAC+1,X RTS ; ; ; RANGE: DO CURSOR RANGE TEST. IF ERROR, POP STACK TWICE AND JMP RETURN ; (ERANGE IS EDITOR ENTRY POINT AND TEST IF EDITOR IS OPEN. ; IF IT ISNT IT OPENS THE EDITOR AND CONTINUES) ; ERANGE: LDA BOTSCR ; IF BOTSCR=4 CMP #4 BEQ RANGE ;THEN IT IS IN MIXED NODE AND OK LDA DINDEX ;IF MODE = 0 BEQ RANGE ;THEN IT IS INEDITOR MODE AND OK JSR EOPEN ;IF NOT, OPEN EDITOR RANGE: LDA #39 ;***** RANGE CHECK RMARGN ***** SET UP AC CMP RMARGN ;***** RANGE CHECK RMARGN ***** COMPARE BCS RANGE3 ;***** RANGE CHECK RMARGN ***** BRANCH GE STA RMARGN ;***** RANGE CHECK RMARGN ***** BAD SO STORE RANGE3: LDX DINDEX LDA NOROWS,X ;CHECK ROWS CMP ROWCRS BCC RNGERR ;(ERROR IF TABLE.GE.ROWCRS) BEQ RNGERR CPX #8 ;CHECK FOR 320X1 BNE RANGE1 ;SPECIAL CASE IT LDA COLCRS+1 BEQ RNGOK ;IF HIGH BYTE IS 0, COL IS OK CMP #1 BNE RNGERR ;IF >1, BAD BEQ RANGE2 ;IF 1, GO CHECK LOWBYTE RANGE1: LDA COLCRS+1 ;FOR OTHERS, NON-ZERO HIGH BYTE IS BAD BNE RNGERR RANGE2: LDA COLUMN,X ;CHECK LOWBYTE CMP COLCRS BCC RNGERR BEQ RNGERR RNGOK: LDA #SUCCES ;SET STATUS OK STA DSTAT LDA #BRKABT ;PREPARE BREAK ABORT STATUS LDX BRKKEY ;CHECK BREAK KEY FLAG STA BRKKEY ;'CLEAR' BREAK BEQ RNGER2 ;IF BREAK, QUIT IMMEDIATELY AND RETURN TO CI RTS RNGERR: JSR HOME ;ON RANGE ERROR, BRING CURSOR BACK LDA #CRSROR ;SHOW CURSOR OVERRANGE ERROR RNGER2: STA DSTAT RNGER1: PLA ;RESTORE STACK (THIS ROUTINE IS ALWAYS 1 LEV PLA ;AWAY FROM RETURN TO CIO) LDA SWPFLG ;IF SWAPPED. SWAP BACK BPL RETUR3 JSR SWAPA ;AND DONT DO RETUR1 RETUR3: JMP RETUR1 ;RETURN TO CIO ; ; ; ; OFFCRS: RESTORE OLD DATA UNDER CURSOR SO IT CAN BE MOVED ; OFFCRS: LDY #0 LDA OLDCHR STA (OLDADR),Y RTS ; ; ; ; BITMAP ROUTINES: ; ; BITCON: PUT MASK IN BITMSK AND INDEX IN X ; BITPUT: PUT CARRY INTO BITMAP ; BITROL: ROL CARRY INTO BOTTOM OF BiTMAP (SCROLL) ; BITSET: SET PROPER BIT ; BITCLR: CLEAR PROPER BIT ; BITGET: RETURN CARRY SET IF BIT IS THERE ; LOGGET: DO BITGET FOR LOGMAP INSTEAD OF TABMAP ; BITCON: PHA AND #7 TAX ;GET MASK LDA MASKTB,X STA BITMSK PLA ;PROCESS INDEX LSR A LSR A LSR A TAX RTS ; ; BITROL: ROL LOGMAP+2 ROL LOGMAP+1 ROL LOGMAP RTS ; ; BITPUT: BCC BITCLR ;AND RETURN ; OTHERWISE FALL THROUGH TO BITSET AND RETURN BITSET: JSR BITCON LDA TABMAP,X ORA BITMSK STA TABMAP,X RTS ; BITCLR: JSR BITCON LDA BITMSK EOR #$FF AND TABMAP,X STA TABMAP,X RTS ; LOGGET: LDA ROWCRS LO1GET: CLC LO2GET: ADC #120 BITGET: JSR BITCON CLC LDA TABMAP,X AND BITMSK BEQ BITGE1 SEC BITGE1: RTS ; ; ; ; ; INATAC: INTERNAL(CHAR) TO ATASCII(ATACHR) CONVERSION ; INATAC: LDA CHAR LDY DINDEX ;IF GRAPHICS MODES CPY #3 BCS INATA1 ;THEN DON'T CHANGE CHAR ROL A ROL A ROL A ROL A AND #3 TAX LDA CHAR AND #$9F ORA INTATA,X INATA1: STA ATACHR RTS ; ; ; ; MOVLLN: MOVE 40 BYTES AT FRMADR TO TOADR SAVING OLD TOAOR ; DATA IN THE LINBUF. THEN MAKE NEXT FRMADR ; BE AT LINBUF FOR NEXT TRANSFER & TOADR=TOADR+40 ; MOVLIN: LDA #LINBUF/256 ;SET UP ADRESS=LINBUF$=247 STA ADRESS+1 LDA #LINBUF.AND.$FF STA ADRESS LDY #39 MOVLI1: LDA (TOADR),Y ;SAVE TO DATA STA TMPCHR LDA (FRMADR),Y ;STORE DATA STA (TOADR),Y LDA TMPCHR STA (ADRESS),Y DEY BPL MOVLI1 LDA ADRESS+1 ;SET UP FRMADR=LAST LINE STA FRMADR+1 LDA ADRESS STA FRMADR CLC ;ADD 40 TO TOADR LDA TOADR ADC #40 STA TOADR BCC MOVLI2 INC TOADR+1 MOVLI2: RTS ; ; ; ; EXTEND: EXTEND BIT MAP FROM ROWCRS (EXTEND LOGICAL LINE ; EXTEND: PHP ;SAVE CARRY LDY #23 EXTEN1: TYA JSR LO1GET PHP TYA CLC ADC #121 PLP JSR BITPUT EXTEN3: DEY BMI EXTEN4 CPY ROWCRS BCS EXTEN1 EXTEN4: LDA ROWCRS CLC ADC #120 PLP JMP BITPUT ;STORE NEW LINE'S BIT AND RETURN ; ; ; ; CLRLIN: CLEAR LINE CURSOR IS ON ; CLRLIN: LDA LMARGN STA COLCRS JSR CONVRT LDY #39 LDA #0 CLRLI1: STA (ADRESS),Y DEY BPL CLRLI1 RTS ; ; ; ; ; SCROLL: SCROLL SCREEN ; SCROLL: JSR BITROL ;ROLL IN CARRY LDA SAVMSC ;SET UP WORKING REGISTERS STA ADRESS LDA SAVMSC+1 STA ADRESS+1 SCROL1: LDY #40 ;LOOP LDA (ADRESS),Y LDX RAMTOP ;TEST FOR LAST LINE DEX CPX ADRESS+1 BNE SCROL2 LDX #$D7 CPX ADRESS BCS SCROL2 LDA #0 ;YES SO STORE ZERO DATA FOR THIS ENTIRE LINE SCROL2: LDY #0 STA (ADRESS),Y INC ADRESS BNE SCROL1 INC ADRESS+1 LDA ADRESS+1 CMP RAMTOP BNE SCROL1 JMP DOLCOL ;AND RETURN ; ; ; DOLCOL: DO LOGICAL COLUMN FROM BITMAP AND COLCRS ; DOLCOL: LDA #0 ;START WITH ZERO STA LOGCOL LDA ROWCRS STA HOLD1 DOLCO1: LDA HOLD1 ;ADD IN ROW COMPONENT JSR LO1GET BCS DOLCO2 ;FOUND BEGINNING OF LINE LDA LOGCOL ;ADD 40 AND LOOK BAC ONE CLC ADC #40 STA LOGCOL DEC HOLD1 ;UP ONE LINE JMP DOLCO1 DOLCO2: CLC ;ADD IN COLCRS LDA LOGCOL ADC COLCRS STA LOGCOL RTS ; ; ; ; DOBUFC: COMPUTE BUFFER COUNT AS THE NUMBER OF BYTES FROM ; BUFSTR TO END OF LOGICAL LINE WITH TRAILING SPACES REMOVED ; DOBUFC: JSR PHACRS LDA LOGCOL PHA LDA BUFSTR ;START STA ROWCRS LDA BUFSTR+1 STA COLCRS LDA #1 STA BUFCNT DOBUF1: LDX #23 ;NORMAL LDA SWPFLG ;IF SWAPPED, ROW 3 IS THE LAST LINE ON SCREE BPL DOB1 LDX #3 DOB1: CPX ROWCRS ;TEST IF CRSR IS AT LAST SCREEN POSITION BNE DOBU1A LDA COLCRS CMP RMARGN BNE DOBU1A INC BUFCNT ;YES, SO FAKE INCRSP TO AVOID SCROLLING JMP D0BUF2 DOBU1A: JSR INCRSB INC BUFCNT LDA LOGCOL CMP LMARGN BNE DOBUF1 ;NOT YET EOL DEC ROWCRS ;BACK UP ONE INCRSR JSR CRSRLF DOBUF2: JSR GETPLT ;TEST CURRENT COLUMN FOR NON-ZERO DATA BNE DOBUF4 ;QUIT IF NON-ZERO DEC BUFCNT ;DECREMENT COUNTER LDA LOGCOL ;BEGINNING OF LOGICAL LINE YET? CMP LMARGN BEQ DOBUF4 ;YES, SO QUIT JSR CRSRLF ;BACK UP CURSOR LDA COLCRS ;IF LOGCOL=RMARGN, GO UP 1 ROW CMP RMARGN BNE DOBUF3 DEC ROWCRS DOBUF3: LDA BUFCNT BNE DOBUF2 ;LOOP UNLESS BUFCNT JUST WENT TO ZERO DOBUF4: PLA STA LOGCOL JSR PLACRS RTS ; ; ; ; ; STRBEG: MOVE BUFSTR TO BEGINNING OF LOGICAL LINE. ; STRBEG: JSR DOLCOL ;USE DOLCOL TO POINT HOLD1 AT BOL LDA HOLD1 STA BUFSTR LDA LMARGN STA BUFSTR+1 RTS ; ; ; ; ; ; DELTIM: TIME TO DELETE A LINE IF IT IS EMPTY AND AN EXTENSION ; DELTIA: LDA LOGCOL ;IF LOGCOL<>LMARGN CMP LMARGN ;THEN DONT MOVE UP ONE BNE DELTIG ;LINE BEFORE TESTING DELTIM DEC ROWCRS DELTIG: JSR DOLCOL DELTIM: LDA LOGCOL ;TEST FOR EXTENSION CMP LMARGN BEQ DELTI3 ;NO JSR CONVRT LDA RMARGN ;SET UP COUNT SEC SBC LMARGN TAY DELTI1: LDA (ADRESS),Y BNE DELTI3 ;FOUND A NON-0 SD QUIT AND RETURN DEY BPL DELTI1 DELTI2: JMP DELLIB ;DELETE A LINE AND RETURN DELTI3: RTS ; ; ; ; TSTCTL: SEARCH CNTRLS TABLE TO SEE IF ATACHR IS A CNTL CHAR ; TSTCTL: LDX #45 ;PREPARE TO SEARCH TABLE TSTCT1: LDA CNTRLS,X CMP ATACHR BEQ TSTCT2 DEX DEX DEX BPL TSTCT1 TSTCT2: RTS ; ; ; ; PUSH ROWCRS,COLCRS AND COLCRS+1 ; PHACRS: LDX #2 PHACR1: LDA ROWCRS,X STA TMPROW,X DEX BPL PHACR1 RTS ; ; ; PULL COLCRS+1,COLCRS AND ROWCRS ; PLACRS: LDX #2 PLACR1: LDA TMPROW,X STA ROWCRS,X DEX BPL PLACR1 RTS ; ; ; ; SWAP: IF MIXED MODE, SWAP TEXT CURSORS WITH REGULAR CURSORS ; SWAP: JSR SWAPA ;THIS ENTRY POINT DOESRETUR1 JMP RETURI SWAPA: LDA BOTSCR CMP #24 BEQ SWAP3 LDX #11 SWAP1: LDA ROWCRS,X PHA LDA TXTROW,X STA ROWCRS,X PLA STA TXTROW,X DEX BPL SWAP1 LDA SWPFLG EOR #$FF STA SWPFLG SWAP3: RTS ; ; ; CLICK: MAKE CLICK THROUGH KEYBOARD SPEAKER ; CLICK: LDX #$7F CLICK1: STX CONSOL STX WSYNC DEX BPL CLICK1 RTS ; ; ; COLCR: PUTS EITHER 0 OR LMARQN INTO COLCRS BASED ON MODE AND SWPFLG ; COLCR: LDA #0 LDX SWPFLG BNE COLCR1 LDX DINDEX BNE COLCR2 COLCR1: LDA LMARGN COLCR2: STA COLCRS RTS ; ; ; PUTMSC: PUT SAVMSC INTO ADRESS ; PUTMSC: LDA SAVMSC ;SETUP ADDRESS STA ADRESS LDA SAVMSC+1 STA ADRESS+1 RTS ; .PAGE ; ; ; DRAW -- DRAW A LINE FROM OLDROW,OLDCOL TO NEWROW,NEWCOL ; (THE AL MILLER METHOD FROM BASKETBALL) DRAW: LDX #0 LDA ICCOMZ ;TEST COMMAND: $11=DRAW $12=FILL CMP #$11 BEQ DRAWA CMP #$12 ;TEST FILL BEQ DRAWB ;YES LDY #NVALID ;NO, SO RETURN INVALID COMMAND RTS DRAWB: INX DRAWA: STX FILFLG LDA ROWCRS ;PUT CURSOR INTO NEWROW,NEWCOL STA NEWROW LDA COLCRS STA NEWCOL LDA COLCRS+1 STA NEWCOL+1 LDA #1 STA ROWINC ;SET UP INITIAL DIRECTIONS STA COLINC SEC LDA NEWROW ;DETERMINE DELTA ROW SBC OLDROW STA DELTAR BCS DRAW1 ;DO DIRECTION AND ABSOLUTE VALUE LDA #$FF ;BORROW WAS ATTEMPTED STA ROWINC ;SET DIRECTION DOWN LDA DELTAR EOR #$FF ;DELTAR = |DELTAR| CLC ADC #1 STA DELTAR DRAW1: SEC LDA NEWCOL ;NOW DELTA COLUMN SBC OLDCOL STA DELTAC LDA NEWCOL+1 ;TWO-BYTE QUANTITY SBC OLDCOL+1 STA DELTAC+1 BCS DRAW2 ;DIRECTION AND ABSOLUTE VALUE LDA #$FF ;BORROW WAS ATTEMPTED STA COLINC ;SET DIRECTION = LEFT LDA DELTAC EOR #$FF ;DELTAC = |DELTAC| STA DELTAC LDA DELTAC+1 EOR #$FF STA DELTAC+1 INC DELTAC ;ADD ONE FOR TWOS COMPLEMENT BNE DRAW2 INC DELTAC+1 DRAW2: LDX #2 ;ZERO RAM FOR DRAW LOOP LDY #0 STY COLAC+1 DRAW3A: TYA STA ROWAC,X LDA OLDROW,X STA ROWCRS,X DEX BPL DRAW3A LDA DELTAC ;FIND LARGER ONE (ROW OR COL) ; STA COUNTR (PREPARE COUNTR AND ENDPT) ; STA ENDPT INX ;MAKE X 0 TAY LDA DELTAC+1 STA COUNTR+1 STA ENDPT+1 BNE DRAW3 ;AUTOMATICALLY LARGER IF MSD>0 LDA DELTAC CMP DELTAR ;LOW COL >LOW ROW? BCS DRAW3 ;YES LDA DELTAR LDX #2 TAY DRAW3: TYA ;PUT IN INITIAL CONDITIONS STA COUNTR STA ENDPT PHA ;SAVE AC LDA ENDPT+1 ;PUT LSB OF HIGH BYTE LSR A ;INTO CARRY PLA ;RESTORE AC ROR A ;ROR THE 9 BIT ACUMULATOR STA ROWAC,X DRAW4A: LDA COUNTR ;TEST ZERO ORA COUNTR+1 BNE DRAWI1 ;IF COUNTER IS ZERO, LEAVE DRAW JMP DRAW10 DRAWI1: CLC ;ADD ROW TO ROWAC (PLOT LOOP) LDA ROWAC ADC DELTAR STA ROWAC BCC DRAW5 INC ROWAC+1 DRAW5: LDA ROWAC+1 ;COMPARE ROW TO ENDPOINT CMP ENDPT+1 ;IF HIGH BYTE OF ROW IS .LT. HIGH BCC DRAW6 ;BYTE OF ENDPT, BLT TO COLUMN BNE DRAW5A LDA ROWAC CMP ENDPT ;LOW BYTE BCC DRAW6 ;ALSO TILT DRAW5A: CLC ;GE SO MOVE POINT LDA ROWCRS ADC ROWINC STA ROWCRS LDX #0 ;AND SUBTRACT ENDPT FROM ROWAC JSR SUBEND DRAW6: CLC ;DO SAME FOR COLUMN (DOUBLE BYTE ADD) LDA COLAC ;ADD ADC DELTAC STA COLAC LDA COLAC+1 ADC DELTAC+1 STA COLAC+1 CMP ENDPT+1 ;COMPARE HIGH BYTE BCC DRAW8 BNE DRAW6A LDA COLAC ;COMPARE LOW BYTE CMP ENDPT BCC DRAW8 DRAW6A: BIT COLINC ;+ OR - ? BPL DRAW6B DEC COLCRS ;DO DOUBLE BYTE DECREMENT LDA COLCRS CMP #$FF BNE DRAW7 LDA COLCRS+1 BEQ DRAW7 ;DON'T DEC IF ZERO DEC COLCRS+1 BPL DRAW7 ;(UNCONDITIONAL) DRAW6B: INC COLCRS ;DO DOUBLE BYTE INCREMENT BNE DRAW7 INC COLCRS+1 DRAW7: LDX #2 ;AND SUBTRACT ENDPT FROM COLAC JSR SUBEND DRAW8: JSR RANGE JSR OUTPLT ;PLOT POINT LDA FILFLG ;TEST RIGHT FILL BEQ DRAW9 JSR PHACRS LDA ATACHR STA HOLD4 DRAW8A: LDA ROWCRS ;SAVE ROW IN CASE OF CR PHA JSR INCRSA ;POSITION CURSOR ONE PAST DOT PLA ;RESTORE ROWCRS STA ROWCRS DRAW8C: JSR RANGE JSR GETPLT ;GET DATA BNE DRAW8B ;STOP IF NON-ZERO DATA IS ENCOUNTERED LDA FILDAT ;FILL DATA STA ATACHR JSR OUTPLT ;DRAW IT JMP DRAW8A ;LOOP DRAW8B: LDA HOLD4 STA ATACHR JSR PLACRS DRAW9: SEC ;DO DOUBLE BYTE SUBTRACT LDA COUNTR SBC #1 STA COUNTR LDA COUNTR+1 SBC #0 STA COUNTR+1 BMI DRAW10 JMP DRAW4A DRAW10: JMP RETUR1 .PAGE ; ; ; TABLES ; ; ; MEMORY ALLOCATION ; ALOCAT: .BYTE 24,16,10,10,16,28,52,100,196,196,196,196 ; ; ; NUMBER OF DISPLAY LIST ENTRIES ; NUMDLE: .BYTE 23,23,11,23,47,47,95,95,97,97,97,97 MXDMDE: .BYTE 19,19,9,19,39,39,79,79,65,65,65,65 ;(EXT OF NUMDLE) ; ; ; ANTIC CODE FROM INTERNAL MODE CONVERSION TABLE ; ; INTERNAL ANTIC CODE DESCRIPTION ; 0 2 40X2X8 CHARACTERS ; 1 6 20X5X8 "" ; 2 7 20X5X16 "" ; 3 8 40X4X8 GRAPHICS ; 4 9 80X2X4 "" ; 5 A 80X4X4 "" ; 4 B 160X2X2 "" ; 7 D 160X4X2 "" ; 8 F 320X2X1 "" ; 9 SAME AS 8 BUT GTIA 'LUM' MODE ; 10 SAME AS 8 BUT GTIA 'COL/LUM REGISTER' MODE ; 11 SAME AS 8 BUT GTIA 'COLOR' MODE ; ANCONV: .BYTE 2,6,7,8,9,$A,$B,$D,$F,$F,$F,$F ;ZEROS FOR RANGE TEST IN ; ; ; PAGE TABLE TELLS WHICH DISPLAY LISTS ARE IN DANGER OF ; CROSSING A 256 BYTE PAGE BOUNDARY ; PAGETB: .BYTE 0,0,0,0,0,0,0,1,1,1,1,1 ; ; ; THIS IS THE NUMBER OF LEFT SHIFTS NEEDED TO MULTIPLY ; COLCRS BY 10,20, OR 40. (ROWCRS*10)/(2**DHLINE) ; DHLINE: .BYTE 2,1,1,0,0,1,1,2,2,2,2,2 ; ; ; COLUMN: NUMBER OF COLUMNS ; COLUMN: .BYTE 40,20,20,40,80,80,160,160,64,80,80,80 ;MODE 8 IS SPECIAL ; ; ; ; NOROWS: NUMBER OF ROWS ; NOROWS: .BYTE 24,24,12,24,48,48,96,96,192,192,192,192 ; ; ; ; ; DIV2TB: HOW MANY RIGHT SHIFTS FOR HCRSR FOR PARTIAL BYTE MODES ; DIV2TB: .BYTE 0,0,0,2,3,2,3,2,3,1,1,1 ; ; ; DMASKT: DISPLAY MASK TABLE ; DMASKT: .BYTE $00,$FF,$F0,$0F .BYTE $C0,$30,$0C,$03 ; ; MASKTB: BIT MASK. (ALSO PART OF DMASKTB DO NOT SEPARATE) ; MASKTB: .BYTE $80,$40,$20,$10,$08,$04,$02,$01 ; ; ; ; COLRTB: .BYTE $28,$CA,$94,$46,$00 ; ; ; ; ;CNTRLS: CONTROL CODES AND THEIR DISPLACEMENTS INTO THE ; CONTROL CHARACTER PROCESSORS ; CNTRLS: .BYTE $1B .WORD ESCAPE .BYTE $1C .WORD CRSRUP .BYTE $1D .WORD CRSRDN .BYTE $1E .WORD CRSRLF .BYTE $1F .WORD CRSRRT .BYTE $7D .WORD CLRSCR .BYTE $7E .WORD BS .BYTE $7F .WORD TAB .BYTE $9B .WORD DOCRWS .BYTE $9C .WORD DELLIN .BYTE $9D .WORD INSLIN .BYTE $9E .WORD CLRTAB .BYTE $9F .WORD SETTAB .BYTE $FD .WORD BELL .BYTE $FE .WORD DELCHR .BYTE $FF .WORD INSCHR ; ; ; ; ; ; ATAINT: ATASCI TO INTERNAL TABLE ; ATAINT: .BYTE $40,$00,$20,$60 ; ; ; INTATA: INTERNAL TO ATASCI TABLE ; INTATA: .BYTE $20,$40,$00,$60 ; ; ; ATASCI: ATASCII CONVERSION TABLE ; ATASCI: .BYTE $6C,$6A,$3B,$80,$80,$6B,$2B,$2A ;LOWER CASE .BYTE $6F,$80,$70,$75,$9B,$69,$2D,$3D .BYTE $76,$80,$63,$80,$80,$62,$78,$7A .BYTE $34,$80,$33,$36,$1B,$35,$32,$31 .BYTE $2C,$20,$2E,$6E,$80,$6D,$2F,$81 .BYTE $72,$80,$65,$79,$7F,$74,$77,$71 .BYTE $39,$80,$30,$37,$7E,$38,$3C,$3E .BYTE $66,$68,$64,$80,$82,$67,$73,$61 .BYTE $4C,$4A,$3A,$80,$80,$4B,$5C,$5E ;UPPER CASE .BYTE $4F,$80,$50,$55,$9B,$49,$5F,$7C .BYTE $56,$80,$43,$80,$80,$42,$58,$5A .BYTE $24,$80,$23,$26,$1B,$25,$22,$21 .BYTE $5B,$20,$5D,$4E,$80,$4D,$3F,$81 .BYTE $52,$80,$45,$59,$9F,$54,$57,$51 .BYTE $28,$80,$29,$27,$9C,$40,$7D,$9D .BYTE $46,$48,$44,$80,$83,$47,$53,$41 .BYTE $0C,$0A,$7B,$80,$80,$0B,$1E,$1F ;CONTROL .BYTE $0F,$80,$10,$15,$9B,$09,$1C,$1D .BYTE $16,$80,$03,$80,$80,$02,$18,$1A .BYTE $80,$80,$85,$80,$1B,$80,$FD,$80 .BYTE $00,$20,$60,$0E,$80,$0D,$80,$81 .BYTE $12,$80,$05,$19,$9E,$14,$17,$11 .BYTE $80,$80,$80,$80,$FE,$80,$7D,$FF .BYTE $06,$08,$04,$80,$84,$07,$13,$01 ; ; ; ; ; PIRQ5: LDA KBCODE CMP CH1 ;TEST AGAINST LAST KEY PRESSED BNE PIRQ3 ;IF NOT, GO PROCESS KEY LDA KEYDEL ;IF KEY DELAY BYTE > 0 BNE PIRQ4 ;IGNORE KEY AS BOUNCE PIRQ3: LDA KBCODE ;RESTORE AC CMP #CNTL1 ;TEST CONTROL 1 (SSFLAG) BNE PIRQ1 LDA SSFLAG EOR #$FF STA SSFLAG BCS PIRQ4 ;(UNCONDITIONAL) MAKE ^1 INVISIBLE PIRQ1: STA CH STA CH1 LDA #3 STA KEYDEL ;INITIALIZE KEY DELAY FOR DEBOUNCE LDA #0 ;CLEAR COLOR SHIFT BYTE STA ATRACT PIRQ4: LDA #$30 STA SRTIMR PIRQ2: PLA RTI ; ; .BYTE $FF,$FF,$FF,$FF,$FF,$FF ; CRNTPC =* *=$14 KBDSPR: .BYTE $FFF8-CRNTPC ;^GDISPLC IS TOO LONG .END LIST X ; THIS IS THE MODIFIED SEPTEMBER ATARI 400/800 COMPUTER OPERATING ; SYSTEM LISTING. MODIFIED TO ASSEMBLE ON THE MICROTEC CROSS ; ASSEMBLER. ; THIS VERSION IS THE ONE WHICH WAS BURNED INTO ROM. ; THERE IS A RESIDUAL PIECE OF CODE WHICH IS FOR LNBUG. THIS ; IS AT LOCATION $9000 WHICH IS NOT IN ROM. ; ; THIS IS THE REVISION B EPROM VERSION .PAGE ; ; ; COLLEEN OPERATING SYSTEM EQUATE FILE ; ; NTSC/PAL ASSEMBLY FLAG ; PALFLG = 0 ;0 = NTSC 1 = PAL ; ; ; MODULE ORIGIN TABLE ; CHRORG = $E000 ;CHARACTER SET VECTBL = $E400 ;VECTOR TABLE VCTABL = $E480 ;RAM VECTOR INITIAL VALUE TABLE CIOORG = $E4A6 ;CENTRAL I/O HANDLER INTORG = $E6D5 ;INTERRUPT HANDLER SIOORG = $E944 ;SERIAL I/O DRIVER DSKORG = $EDEA ;DISK HANDLER PRNORG = $EE78 ;PRINTER HANDLER CASORG = $EF41 ;CASSETTE HANDLER MONORG = $F0E3 ;MONITOR/POWER UP MODULE KBDORG = $F3E4 ;KEYBOARD/DISPLAY HANDLER ; ; ; ; ; VECTOR TABLE ; ;HANDLER ENTRY POINTS ARE CALLED OUT IN THE FOLLOWING VECTOR ;TABLE. THESE ARE THE ADDRESSES MINUS ONE. ; ; ;EXAMPLE FOR EDITOR ; ; E400 OPEN ; 2 CLOSE ; 4 GET ; 6 PUT ; 8 STATUS ; A SPECIAL ; C JUMP TO POWER ON INITIALIZATION ROUTINE ; F NOT USED ; ; EDITRV = $E400 ;EDITOR SCRENV = $E410 ;TELEVISION SCREEN KEYBDV = $E420 ;KEYBOARD PRINTV = $E430 ;PRINTER CASETV = $E440 ;CASSETTE ; ; JUMP VECTOR TABLE ; ;THE FOLLOWING IS A TABLE OF JUMP INSTRUCTIONS ;TO VARIOUS ENTRY POINTS IN THE OPERATING SYSTEM. ; DISKIW = $E450 ;DISK INITIALIZATION DSKINV = $E453 ;DISK INTERFACE CIOV = $E456 ;CENTRAL INPUT OUTPUT ROUTINE SIOV = $E459 ;SERIAL INPUT OUTPUT ROUTINE SETVBV = $E45C ;SET SYSTEM TIMERS ROUTINE SYSVBV = $E45F ;SYSTEM VERTICAL BLANK CALCULATIONS XITVBV = $E462 ;EXIT VERTICAL BLANK CALCULATIONS SIOINV = $E465 ;SERIAL, INPUT OUTPUT INITIALIZATION SENDEV = $E468 ;SEND ENABLE ROUTINE INTINV = $E46B ;INTERRUPT HANDLER INITIALIZATION CIOINV = $E46E ;CENTRAL INPUT OUTPUT INITIALIZATION BLKBDV = $E471 ;BLACKBOARD MODE WARMSV = $E474 ;WARM START ENTRY POINT COLDSV = $E477 ;COLD START ENTRY POINT RBLOKV = $E47A ;CASSETTE READ BLOCK ENTRY POINT VECTOR CSOPIV = $E47D ;CASSETTE OPEN FOR INPUT VECTOR ;VCTABL = $E480 ; ; ; OPERATING SYSTEM EQUATES ; ; COMMAND CODES FOR IOCB OPEN = 3 ;OPEN FOR INPUT/OUTPUT GETREC = 5 ;GET RECORD (TEXT) GETCHR = 7 ;GET CHARACTER(S) PUTREC = 9 ;PUT RECORD (TEXT) PUTCHR = $B ;PUT CHARACTER(S) CLOSE = $C ;CLOSE DEVICE STATIS = $D ;STATUS REQUEST SPECIL = $E ;BEGINNING OF SPECIAL ENTRY COMMANDS ; ; SPECIAL ENTRY COMMANDS DRAWLN = $11 ;DRAW LINE FILLIN = $12 ;DRAW LINE WITH RIGHT FILL RENAME = $20 ;RENAME DISK FILE DELETE = $21 ;DELETE DISK FILE FORMAT = $22 ;FORMAT LOCKFL = $23 ;LOCK FILE TO READ ONLY UNLOCK = $24 ;UNLOCK LOCKED FILE POINT = $25 ;POINT SECTOR NOTE = $26 ;NOTE SECTOR IOCFRE = $FF ;IOCB "FREE" ; ; AUX1 EQUATES ; () INDICATES WHICH DEVICES USE BIT APPEND = $1 ;OPEN FOR WRITE APPEND (D), OR SCREEN READ ( DIRECT = $2 ;OPEN FOR DIRECTORY ACCESS (D) OPNIN = $4 ;OPEN FOR INPUT (ALL DEVICES) OPNOT = $8 ;OPEN FOR OUTPUT (ALL DEVICES) OPNINO = OPNIN+OPNOT ;OPEN FOR INPUT AND OUTPUT (ALL DEVICES) MXDMOD = $10 ;OPEN FOR MIXED MODE (E,S) INSCLR = $20 ;OPEN WITHOUT CLEARING SCREEN (E,S) ; ; DEVICE NAMES SCREDT = 'E ;SCREEN EDITOR (R/W) KBD = 'K ;KEYBOARD (R ONLY) D1SPLY = 'S ;SCREEN DISPLAY (R/W) PRINTR = 'P ;PRINTER (W ONLY) CASSET = 'C ;CASSETTE MODEM = 'M ;MODEM DISK = 'D ;DISK (R/W) ; ; SYSTEM EOL (CARRIAGE RETURN) CR = $9B ; ; ; OPERATING SYSTEM STATUS CODES ; SUCCES = $01 ;SUCCESSFUL OPERATION ; BRKABT = $80 ;BREAK KEY ABORT PRVOPN = $81 ;IOCB ALREADY OPEN NONDEV = $82 ;NON-EXISTANT DEVICE WRONLY = $83 ;IOCB OPENED FOR WRITE ONLY NVALID = $84 ;INVALID COMMAND NOTOPN = $85 ;DEVICE OR FILE NOT OPEN BADIOC = $86 ;INVALID IOCB NUMBER RDONLY = $87 ;IOCB OPENED FOR READ ONLY EOFERR = $88 ;END OF FILE TRNRCD = $89 ;TRUNCATED RECORD TIMOUT = $8A ;PERIPHERAL DEVICE TIME OUT DNACK = $8B ;DEVICE DOES NOT ACKNOWLEDGE COMMAND FRMERR = $8C ;SERIAL BUS FRAMING ERROR CRSROR = $8D ;CURSOR OVERRANCE OVRRUN = $8E ;SERIAL BUS DATA OVERRUN CHKERR = $8F ;SERIAL BUS CHECKSUM ERROR ; DERROR = $90 ;PERIPHERAL DEVICE ERROR (OPERATION NOT COMP BADMOD = $91 ;BAD SCREEN MODE NUMBER FNCNOT = $92 ;FUNCTION NOT IMPLEMENTED IN HANDLER SCRMEM = $93 ;INSUFICIENT MEMORY FOR SCREEN MODE ; ; ; ; ; ; ; PAGE ZERO RAM ASSIGNMENTS ; *=$0000 LINZBS: .RES 2 ;LINBUG RAM (WILL BE REPLACED BY MONITOR RAM ; ; THESE LOCATIONS ARE NOT CLEARED CASINI: .RES 2 ;CASSETTE INIT LOCATION RAMLO: .RES 2 ;RAM POINTER FOR MEMORY TEST TRAMSZ: .RES 1 ;TEMPORARY REGISTER FOR RAM SIZE TSTDAT: .RES 1 ;RAM TEST DATA REGISTER ; ; CLEARED ON COLOSTART ONLY WARMST: .RES 1 ;WARM START FLAG BOOT?: .RES 1 ;SUCCESSFUL BOOT FLAG DOSVEC: .RES 2 ;DISK SOFTWARE START VECTOR DOSINI: .RES 2 ;DISK SOFTWARE INIT ADDRESS APPMHI: .RES 2 ;APPLICATIONS MEMORY HI LIMIT ; ; CLEARED ON COLD OR WARM START INTZBS =* ;INTERRUPT HANDLER POKMSK: .RES 1 ;SYSTEM MASK FOR POKEY IRQ ENABLE BRKKEY: .RES 1 ;BREAK KEY FLAG RTCLOK: .RES 3 ;REAL TIME CLOCK (IN 16 MSEC UNITS) ; BUFADR: .RES 2 ;INDIRECT BUFFER ADDRESS REGISTER ; ICCOMT: .RES 1 ;COMMAND FOR VECTOR ; DSKFMS: .RES 2 ;DISK FILE MANAGER POINTER DSKUTL: .RES 2 ;DISK UTILITIES POINTER ; PTIMOT: .RES 1 ;PRINTER TIME OUT REGISTER PBPNT: .RES 1 ;PRINT BUFFER POINTER PBUFSZ: .RES 1 ;PRINT BUFFER SIZE PTEMP: .RES 1 ;TEMPORARY REGISTER ; ZIOCB =* ;ZERO PAGE I/O CONTROL BLOCK IOCBSZ = 16 ;NUMBER OF BYTES PER IOCB MAXIOC = 8*IOCBSZ ;LENGTH OF THE IOCB AREA IOCBAS =* ICHIDZ: .RES 1 ;HANDLER INDEX NUMBER (FF = IOCB FREE) ICDNOZ: .RES 1 ;DEVICE NUMBER (DRIVE NUMBER) ICCOMZ: .RES 1 ;COMMAND CODE ICSTAZ: .RES 1 ;STATUS OF LAST IOCB ACTION ICBALZ: .RES 1 ;BUFFER ADDRESS LOW BYTE ICBAHZ: .RES 1 ICPTLZ: .RES 1 ;PUT BYTE ROUTINE ADDRESS - 1 ICPTHZ: .RES 1 ICBLLZ: .RES 1 ;BUFFER LENGTH LOW BYTE ICBLHZ: .RES 1 ICAX1Z: .RES 1 ;AUXILIARY INFORMATION FIRST BYTE ICAX2Z: .RES 1 ICSPRZ: .RES 4 ;TWO SPARE BYTES (CIO LOCAL USE) ICIDNO = ICSPRZ+2 ;IOCB NUMBER X 16 CIOCHR = ICSPRZ+3 ;CHARACTER BYTE FOR CURRENT OPERATION ; STATUS: .RES 1 ;INTERNAL STATUS STORAGE CHKSUM: .RES 1 ;CHECKSUM (SINGLE BYTE SUM WITH CARRY) BUFRLO: .RES 1 ;POINTER TO DATA BUFFER (LO BYTE) BUFRHI: .RES 1 ;POINTER TO DATA BUFFER (HI BYTE) BFENLO: .RES 1 ;NEXT BYTE PAST END OF THE DATA BUFFER (LO B BFENHI: .RES 1 ;NEXT BYTE PAST END OF THE DATA BUFFER (HI B CRETRY: .RES 1 ;NUMBER OF COMMAND FRAME RETRIES DRETRY: .RES 1 ;NUMBER OF DEVICE RETRIES BUFRFL: .RES 1 ;DATA BUFFER FULL FLAG RECVDN: .RES 1 ;RECEIVE DONE FLAG XMTDON: .RES 1 ;TRANSMISSION DONE FLAG CHKSNT: .RES 1 ;CHECKSUM SENT FLAG NOCKSM: .RES 1 ;NO CHECKSUM FOLLOWS DATA FLAG ; ; BPTR: .RES 1 FTYPE: .RES 1 FEOF: .RES 1 FREQ: .RES 1 SOUNDR: .RES 1 ;NOISY I/O FLAG. (ZERO IS QUIET) CRITIC: .RES 1 ;DEFINES CRITICAL SECTION (CRITICAL IF NON-Z ; FMSZPG: .RES 7 ;DISK FILE MANAGER SYSTEM ZERO PAGE ; ; CKEY: .RES 1 ;FLAG SET WHEN GAME START PRESSED CASSBT: .RES 1 ;CASSETTE BOOT FLAG DSTAT: .RES 1 ;DISPLAY STATUS ; ATRACT: .RES 1 ;ATRACT FLAG DRKMSK: .RES 1 ;DARK ATRACT MASK COLRSH: .RES 1 ;ATRACT COLOR SHIFTER (EOR'ED WITH PLAYFIELD ; LEDGE = 2 ;LMARGN'S VALUE AT COLD START REDGE = 39 ;RMARGN'S VALUE AT COLD START TMPCHR: .RES 1 HOLD1: .RES 1 LMARGN: .RES 1 ;LEFT MARGIN (SET TO 1 AT POWER ON) RMARGN: .RES 1 ;RIGHT MARGIN (SET TO 38 AT POWER ON) ROWCRS: .RES 1 ;CURSOR COUNTERS COLCRS: .RES 2 DINDEX: .RES 1 SAVMSC: .RES 2 OLDROW: .RES 1 OLDCOL: .RES 2 OLDCHR: .RES 1 ;DATA UNDER CURSOR OLDADR: .RES 2 NEWROW: .RES 1 ;POINT DRAW GOES TO NEWCOL: .RES 2 LOGCOL: .RES 1 ;POINTS AT COLUMN IN LOGICAL LINE ADRESS: .RES 2 MLTTMP: .RES 2 OPNTMP = MLTTMP ;FIRST BYTE IS USED IN OPEN AS TEMP SAVADR: .RES 2 RAMTOP: .RES 1 ;RAM SIZE DEFINED BY POWER ON LOGIC BUFCNT: .RES 1 ;BUFFER COUNT BUFSTR: .RES 2 ;EDITOR GETCH POINTER BITMSK: .RES 1 ;BIT MASK SHFAMT: .RES 1 ROWAC: .RES 2 COLAC: .RES 2 ENDPT: .RES 2 DELTAR: .RES 1 DELTAC: .RES 2 ROWINC: .RES 1 COLINC: .RES 1 SWPFLG: .RES 1 ;NON-0 IF TXT AND REGULAR RAM IS SWAPPED HOLDCH: .RES 1 ;CH IS MOVED HERE IN KGETCH BEFORE CNTL & SH INSDAT: .RES 1 COUNTR: .RES 2 ; ; ; ; ; 30 - FF ARE RESERVED FOR USER APPLICATIONS ; ; ; ; NOTE : SEE FLOATING POINT SUBROUTINE AREA FOR ZERO PAGE CELLS ; ; ; ; ; PAGE 1 - STACK ; ; ; ; ; PAGE TWO RAM ASSIGNMENTS ; *=$0200 INTABS =* ;INTERRUPT RAM VDSLST: .RES 2 ;DISPLAY LIST NMI VECTOR VPRCED: .RES 2 ;PROCEED LINE IRQ VECTOR VINTER: .RES 2 ;INTERRUPT LINE IRQ VECTOR VBREAK: .RES 2 ;SOFTWARE BREAK (00) INSTRUCTION IRQ VECTOR VKEYBD: .RES 2 ;POKEY KEYBOARD IRQ VECTOR VSERIN: .RES 2 ;POKEY SERIAL INPUT READY IRQ VSEROR: .RES 2 ;POKEY SERIAL OUTPUT READY IRQ VSEROC: .RES 2 ;POKEY SERIAL OUTPUT COMPLETE IRQ VTIMR1: .RES 2 ;POKEY TIMER 1 IRQ VTIMR2: .RES 2 ;POKEY TIMER 2 IRQ VTIMR4: .RES 2 ;POKEY TIMER 4 IRQ VIMIRU: .RES 2 ;IMMEDIATE IRQ VECTOR CDTMV1: .RES 2 ;COUNT DOWN TIMER 1 CDTMV2: .RES 2 ;COUNT DOWN TIMER 2 CDTMV3: .RES 2 ;COUNT DOWN TIMER 3 CDTMV4: .RES 2 ;COUNT DOWN TIMER 4 CDTMV5: .RES 2 ;COUNT DOWN TIMER S VVBLKI: .RES 2 ;IMMEDIATE VERTICAL BLANK NMI VECTOR VVBLKD: .RES 2 ;DEFERRED VERTICAL BLANK NMI VECTOR CDTMA1: .RES 2 ;COUNT DOWN TIMER 1 JSR ADDRESS CDTMA2: .RES 2 ;COUNT DOWN TIMER 2 JSR ADDRESS CDTMF3: .RES 1 ;COUNT DOWN TIMER 3 FLAG SRTIMR: .RES 1 ;SOFTWARE REPEAT TIMER CDTMF4: .RES 1 ;COUNT DOWN TIMER 4 FLAG INTEMP: .RES 1 ;IAN'S TEMP (RENAMED FROM T1 BY POPULAR DEMA CDTMF5: .RES 1 ;COUNT DOWN TIMER FLAG 5 SDMCTL: .RES 1 ;SAVE DMACTL REGISTER SDLSTL: .RES 1 ;SAVE DISPLAY LIST LOW BYTE SDLSTH: .RES 1 ;SAVE DISPLAY LIST HI BYTE SSKCTL: .RES 1 ;SKCTL REGISTER RAM .RES 1 ; LPENH: .RES 1 ;LIGHT PEN HORIZONTAL VALUE LPENV: .RES 1 ;LIGHT PEN VERTICAL VALUE BRKKY: .RES 2 ;BREAK KEY VECTOR ; .RES 2 ;SPARE ; CDEVIC: .RES 1 ;COMMAND FRAME BUFFER - DEVICE CCOMND: .RES 1 ;COMMAND CAUX1: .RES 1 ;COMMAND AUX BYTE 1 CAUX2: .RES 1 ;COMMANDAUX BYTE 2 ; NOTE: MAY NOT BE THE LAST WORD ON A PAGE TEMP: .RES 1 ;TEMPORARY RAM CELL ; NOTE: MAY NOT BE THE LAST WORD ON A PAGE ERRFLG: .RES 1 ;ERROR FLAG - ANY DEVICE ERROR EXCEPT TIME ; DFLAGS: .RES 1 ;DISK FLAGS FROM SECTOR ONE DBSECT: .RES 1 ;NUMBER OF DISK BOOT SECTORS BOOTAD: .RES 2 ;ADDRESS WHERE DISK BOOT LOADERWILL BE PUT COLDST: .RES 1 ;COLDSTART FLAG (1=IN MIDDLE OF COLDSTART) ; .RES 1 ;SPARE ; DSKTIM: .RES 1 ;DISK TIME OUT REGISTER ; LINBUF: .RES 40 ;CHAR LINE BUFFER ; GPRIOR: .RES 1 ;GLOBAL PRIORITY CELL ; PADDL0: .RES 1 ;POTENTIOMETER 0 RAM CELL PADDL1: .RES 1 PADDL2: .RES 1 PAODL3: .RES 1 PADDL4: .RES 1 PADDL5: .RES 1 PADDL6: .RES 1 PADDL7: .RES 1 STICK0: .RES 1 ;JOYSTICK 0 RAM CELL STICK1: .RES 1 STICK2: .RES 1 STICK3: .RES 1 PTRIG0: .RES 1 ;PADDLE TRIGGER 0 PTRIG1: .RES 1 PTRIG2: .RES 1 PTRIG3: .RES 1 PTRIG4: .RES 1 PTRIG5: .RES 1 PTRIG6: .RES 1 PTRIG7: .RES 1 STRIG0: .RES 1 ;JOYSTICK TRIGGER 0 STRIG1: .RES 1 STRIG2: .RES 1 STRIG3: .RES 1 ; CSTAT: .RES 1 WMODE: .RES 1 BLIM: .RES 1 IMASK: .RES 1 JVECK: .RES 2 ; .RES 2 ;SPARE ; ; ; ; TXTROW: .RES 1 ;TEXT ROWCRS TXTCOL: .RES 2 ;TEXT COLCRS TINDEX: .RES 1 ;TEXT INDEX TXTMSC: .RES 2 ;FOOLS CONVRT INTO NEW MSC TXTOLD: .RES 6 ;OLDROW & OLDCOL FOR TEXT (AND THEN SOME) TMPX1: .RES 1 HOLD3: .RES 1 SUBTMP: .RES 1 HOLD2: .RES 1 DMASK: .RES 1 TMPLBT: .RES 1 ESCFLG: .RES 1 ;ESCAPE FLAG TABMAP: .RES 15 LOGMAP: .RES 4 ;LOGICAL LINE START BIT MAP INVFLG: .RES 1 ;INVERSE VIDEO FLAG (TOGGLED BY ATARI KEY) FILFLG: .RES 1 ;RIGHT FILL FLAG FOR DRAW TMPROW: .RES 1 TMPCOL: .RES 2 SCRFLG: .RES 1 ;SET IF SCROLL OCCURS HOLD4: .RES 1 ;TEMP CELL USED IN DRAW ONLY HOLD5: .RES 1 ;DITTO SHFLOK: .RES 1 BOTSCR: .RES 1 ;BOTTOM OF SCREEN : 24 NORM 4 SPLIT ; ; PCOLR0: .RES 1 ;P0 COLOR PCOLR1: .RES 1 ;P1 COLOR PCOLR2: .RES 1 ;P2 COLOR PCOLP3: .RES 1 ;P3 COLOR COLOR0: .RES 1 ;COLOR 0 COLOR1: .RES 1 CQLOR2: .RES 1 COLOR3: .RES 1 COLOR4: .RES 1 ; ; .RES 23 ;SPARE ; ; ; GLBABS =* ;GLOBAL VARIABLES ; .RES 4 ;SPARE ; RAMSIZ: .RES 1 ;RAM SIZE (HI BYTE ONLY) MEMTOP: .RES 2 ;TOP OF AVAILABLE USER MEMORY MEMLO: .RES 2 ;BOTTOM OF AVAILABLE USER MEMORY .RES 1 ;SPARE DVSTAT: .RES 4 ;STATUS BUFFER CBAUDL: .RES 1 ;CASSETTE BAUD RATE LOW BYTE CBAUDH: .RES 1 ; CRSINH: .RES 1 ;CURSOR INHIBIT (00 = CURSOR ON) KEYDEL: .RES 1 ;KEY DELAY CH1: .RES 1 ; CHACT: .RES 1 ;CHACTL REGISTER RAM CHBAS: .RES 1 ;CHBAS REGISTER RAM ; .RES 5 ;SPARE BYTES ; CHAR: .RES 1 ATACHR: .RES 1 ;ATASCII CHARACTER CH: .RES 1 ;GLOBAL VARIABLE FOR KEYBOARD FILDAT: .RES 1 ;RIGHT FILL DATA (DRAW) DSPFLG: .RES 1 ;DISPLAY FLAG : DISPLAY CNTLS IF NON-ZERO SSFLAG: .RES 1 ;START/STOP FLAG FOR PAGING (CNTL 1). CLEARE ; ; ; ; ; ; ; ; PAGE THREE RAM ASSIGNMENTS ; DCB =* ;DEVICE CONTROL BLOCK DDEVIC: .RES 1 ;PERIPHERAL UNIT 1 BUS ID. NUMBER DUNIT: .RES 1 ;UNIT NUMBER DCOMND: .RES 1 ;BUS COMMAND DSTATS: .RES 1 ;COMMAND TYPE/STATUS RETURN DBUFLO: .RES 1 ;DATA BUFFER POINTER LOW BYTE DBUFHI: .RES 1 DTIMLO: .RES 1 ;DEVICE TIME OUT IN 1 SECOND UNITS DUNUSE: .RES 1 ;UNUSED BYTE DBYTLO: .RES 1 ;NUMBER OF BYTES TO BE TRANSFERRED LOW BYTE DBYTHI: .RES 1 DAUX1: .RES 1 ;COMMAND AUXILIARY BYTE 1 DAUX2: .RES 1 ; TIMER1: .RES 2 ;INITIAL TIMER VALUE ADDCOR: .RES 1 ;ADDITION CORRECTION CASFLG: .RES 1 ;CASSETTE MODE WHEN SET TIMER2: .RES 2 ;FINAL TIMER VALUE. THESE TWO TIMER VALUES ; ARE USED TO COMPUTE INTERVAL FOR BAUD RATE TEMP1: .RES 2 ;TEMPORARY STORAGE REGISTER TEMP2: .RES 1 ;TEMPORARY STORAGE REGISTER TEMP3: .RES 1 ;TEMPORARY STORAGE REGISTER SAVIO: .RES 1 ;SAVE SERIAL IN DATA PORT TIMFLG: .RES 1 ;TIME OUT FLAG FOR BAUD RATE CORRECTION STACKP: .RES 1 ;SIO STACK POINTER SAVE CELL TSTAT: .RES 1 ;TEMPORARY STATUS HOLDER ; ; ; HATABS: .RES 38 ;HANDLER ADDRESS TABLE MAXDEV = *-HATABS-5 ;MAXIMUM HANDLER ADDRESS INDEX ; ; NOTE : THE ENTIRE IOCB DEFINITIONS HAVE BEEN MODIFIED ; IOCB: .ORG * ;I/O CONTROL BLOCKS ICHID: .RES 1 ;HANDLER INDEX NUMBER (FF = IOCB FREE) ICDNO: .RES 1 ;DEVICE NUMBER (DRIVE NUMBER) ICCOM: .RES 1 ;COMMAND CODE ICSTA: .RES 1 ;STATUS OF LAST IOCB ACTION ICBAL: .RES 1 ;BUFFER ADDRESS LOW BYTE ICBAH: .RES 1 ICPTL: .RES 1 ;PUT BYTE ROUTINE ADDRESS - 1 ICPTH: .RES 1 ICBLL: .RES 1 ;BUFFER LENGTH LOW BYTE ICBLH: .RES 1 ICAX1: .RES 1 ;AUXILIARY INFORMATION FIRST BYTE ICAX2: .RES 1 ICSPR: .RES 4 ;FOUR SPARE BYTES .RES MAXIOC-IOCBSZ ; PRNBUF: .RES 40 ;PRINTER BUFFER ; .RES 21 ;SPARE BYTES ; ; ; ; ; ; ; ; PAGE FOUR RAM ASSIGNMENTS ; CASBUF: .RES 131 ;CASSETTE BUFFER ; ; USER AREA STARTS HERE AND GOES TO END OF PAGE FIVE USAREA: .RES 128 ;SPARE ; ; ; ; ; ; ; ; PAGE FIVE RAM ASSIGNMENTS ; ; PAGE FIVE IS RESERVED AS A USER WORK SPACE ; ; NOTE: SEE FLOATING POINT SUBROUTINE AREA FOR PAGE FIVE CELLS ; ; ; PAGE SIX RAM ASSIGNMENTS ; ; PAGE SIX IS RESERVED AS A USER'S USER WORK SPACE ; ; ; ; ; FLOATING POINT SUBROUTINES ; FPREC = 6 ;FLOATING PT PRECISION (# OF BYTES) ; IF CARRY USED THEN CARRY CLEAR => NO ERROR, CARR AFP = $D800 ;ASCII->FLOATING POINT(FP) ; INBUFF+CIX -> FR0, CIX, CARRY FASC = $D8E6 ;FP -> ASCII FR0 -> LBUFF (INBUFF) IFP = $D9AA ;INTEGER -> FP ; 0-$FFFF (LSB,MSB) IN FR0,FR0+1->FR0 FPI = $D9D2 ;FP -> INTEGER FR0 -> FR0,FR0+1, CARRY FSUB = $DA60 ;FR0 <- FR0 - FR1 ,CARRY FADD = $DA66 ;FR0 <- FR0 + FR1 ,CARRY FMUL = $DADB ;FR0 <- FR0 * FR1 ,CARRY FDIV = $DB28 ;FR0 <- FR0 / FR1 ,CARRY FLD0R = $DD89 ;FLOATING LOAD REG0 FR0 <- (X,Y) FLD0P = $DD80 ; " " " FR0 <- (FLFTR) FLD1R = $DD98 ; " " REG1 FR1 <- (X,Y) FLD1P = $DD9C ; " " " FR1 <- (FLPTR) FSTOR = $DDA7 ;FLOATING STORE REG0 (X,Y) <- FR0 FSTOP = $DDAB ; " " " (FLPTR) <- FR0 FMOVE = $DDB6 ;FR1 <- FR0 PLYEVL = $DD40 ;FR0 <- P(Z) = SUM(I=N TO 0) (A(I)*Z**I) CAR ; INPUT: (X,Y) = A(N),A(N-1)...A(0) -> PLYARG ; ACC = # OF COEFFICIENTS = DEGREE+1 ; FR0 = Z EXP = $DDC0 ;FR0 <- E**FR0 = EXP10(FR0 * LOG10(E)) CARRY EXP10 = $DDCC ;FR0 <- 10**FR0 CARRY LOG = $DECD ;FR0 <- LN(FR0) = LOG10(FR0)/LOG10(E) CARRY LOG10 = $DED1 ;FR0 <- LOG10 (FR0) CARRY ; THE FOLLOWING ARE IN BASIC CARTRIDGE: SIN = $BDB1 ;FR0 <- SIN(FR0) DEGFLG=0 =>RADS, 6=>DEG. CA COS = $BD73 ;FR0 <- COS(FR0) CARRY ATAN = $BE43 ;FR0 <- ATAN(FR0) CARRY SQR = $BEB1 ;FR0 <- SQUAREROOT(FR0) CARRY ; FLOATING POINT ROUTINES ZERO PAGE (NEEDED ONLY IF V.P. ROUTINES ARE CA *=$D4 FR0: .RES FPREC ;FP REG0 FRE: .RES FPREC FR1: .RES FPREC ;FP REG1 FR2: .RES FPREC FRX: .RES 1 ;FP SPARE EEXP: .RES 1 ;VALUE OF E NSIGN: .RES 1 ;SIGN OF # ESIGN: .RES 1 ;SIGN OF EXPONENT FCHRFLG:.RES 1 ;1ST CHAR FLAG DIORT: .RES 1 ;# OF DIGITS RIGHT OF DECIMAL CIX: .RES 1 ;CURRENT INPUT INDEX INBUFF: .RES 2 ;POINTS TO USER'S LINE INPUT BUFFER ZTEMPI: .RES 2 ZIEMP4: .RES 2 ZTEMP3: .RES 2 DEGFLG RADFLG: .RES 1 ;0=RADIANS, 6=DEGREES RADON = 0 ;INDICATES RADIANS DEGON = 6 ;INDICATES DEGREES FLPTR: .RES 2 ;POINTS TO USER'S FLOATING PT NUMBER FPTR2: .RES 2 ; FLOATING PT ROUTINES' NON-ZERO PAGE RAM ; (NEEDED ONLY IF F.P. ROUTINES CALLED) *=$57E LBPR1: .RES 1 ;LBUFF PREFIX 1 LBPR2: .RES 1 ;LBUFF PREFIX 2 LBUFF: .RES 128 ;LINE BUFFER PLYARG = LBUFF+$60 ;POLYNOMIAL ARGUMENTS FPSCR = PLYARG+FPREC FPSCR1 = FPSCR+FPREC FSCR = FPSCR FSCR1 = FPSCR1 LBFEND = *-1 ;END OF LBUFF ; ; ; ; ; ; ; ; ; ; COLLEEN MNEMONICS ; POKEY = $D200 ;VBLANK ACTION: DESCRIPTION: POT0 = POKEY+0 ;POT0-->PADDL0 0-227 IN RAM CELL POT1 = POKEY+1 ;POT1-->PADDL1 0-227 IN RAM CELL POT2 = POKEY+2 ;POT2-->PADDL2 0-227 IN RAM CELL POT3 = POKEY+3 ;POT3-->PADDL3 0-227 IN RAM CELL POT4 = POKEY+4 ;POT4-->PADDL4 0-227 IN RAM CELL POT5 = POKEY+5 ;POT5-->PADDL5 0-227 IN RAM CELL POT6 = POKEY+6 ;POT6-->PADDL6 0-227 IN RAM CELL POT7 = POKEY+7 ;POT7-->PADDL7 0-227 IN RAM CELL ALLPOT = POKEY+8 ;??? KBCODE = POKEY+9 RANDOM = POKEY+10 POTGO = POKEY+11 ;STROBED SERIN = POKEY+13 IRQST = POKEY+14 SKSTAT = POKEY+15 AUDF1 = POKEY+0 AUDC1 = POKEY+1 AUDF2 = POKEY+2 AUDC2 = POKEY+3 AUDF3 = POKEY+4 AUDC3 = POKEY+5 AUDF4 = POKEY+6 AUDC4 = POKEY+7 AUDCTL = POKEY+8 ;NONE AUDCTL<--[SIO] STIMER = POKEY+9 SKRES = POKEY+10 ;NONE SKRES<--[SIO] SEROUT = POKEY+13 ;NONE SEROUT<--[SIO] IRQEN = POKEY+14 ;POKMSK-->IRQEN (AFFECTED BY OPEN S: OR E:) SKCTL = POKEY+15 ;SSKCTL-->SKCTL SSKCTL<--[SIO] ; CTIA = $D000 ;VBLANK ACTION: DESCRIPTION: HPOSP0 = CTIA+0 HPOSP1 = CTIA+1 HPOSP2 = CTIA+2 HPOSP3 = CTIA+3 HPOSM0 = CTIA+4 HPOSM1 = CTIA+5 HPOSM2 = CTIA+6 HPOSM3 = CTIA+7 SIZEP0 = CTIA+8 SIZEP1 = CTIA+9 SIZEP2 = CTIA+10 SIZEP3 = CTIA+11 SIZEM = CTIA+12 GRAFP0 = CTIA+13 GRAFP1 = CTIA+14 GRAFP2 = CTIA+15 GRAFP3 = CTIA+16 GRAFM = CTIA+17 COLPM0 = CTIA+18 ;PCOLR0-->COLPM0 WITH ATTRACT MODE COLPM1 = CTIA+19 ;PCOLR1-->COLPM1 WITH ATTRACT MODE COLPM2 = CTIA+20 ;PCOLR2-->COLPM2 WITH ATTRACT MODE COLPM3 = CTIA+21 ;PCOLR3-->COLPM3 WITH ATTRACT MODE COLPF0 = CTIA+22 ;COLOR0-->COLPF0 WITH ATTRACT MODE COLPF1 = CTIA+23 ;COLOR1-->COLPF1 WITH ATTRACT MODE COLPF2 = CTIA+24 ;COLOR2-->COLPF2 WITH ATTRACT MODE COLPF3 = CTIA+25 ;COLOR3-->COLPF3 WITH ATTRACT MODE COLBK = CTIA+26 ;COLOR4-->COLBK WITH ATTRACT MODE PRIOR = CTIA+27 ;(ON OPEN S: OR E:) GPRIOR-->PRIOR VDELAY = CTIA+28 GRACTL = CTIA+29 HITCLR = CTIA+30 CONSOL = CTIA+31 ;$08-->CONSOL TURN OFF SPEAKER M0PF = CTIA+0 M1PF = CTIA+1 M2PF = CTIA+2 M3PF = CTIA+3 P0PF = CTIA+4 P1PF = CTIA+5 P2PF = CTIA+8 P3PF = CTIA+7 M0PL = CTIA+8 M1PL = CTIA+9 M2PL = CTIA+10 M3PL = CTIA+11 P0PL = CTIA+12 P1PL = CTIA+13 P2PL = CTIA+14 P3PL = CTIA+15 TRIG0 = CTIA+16 ;TRIG0-->STRIG0 TRIG1 = CTIA+17 ;TRIG1-->STRIG1 TRIG2 = CTIA+18 ;TRIG2-->STRIG2 TRIG3 = CTIA+19 ;TRIG3-->STRIG3 ; ANTIC = $D400 ;VBLANK ACTION DESCRIPTION DMACTL = ANTIC+0 ;DMACTL<--SDMCTL ON OPEN S: OR E: CHACTL = ANTIC+1 ;CHACTL<--CHACT ON OPEN S: OR E: DLISTL = ANTIC+2 ;DLISTL<--SDLSTL ON OPEN S: OR E: DLISTH = ANTIC+3 ;DLISTH<--SDLSTH ON OPEN S: OR E: NSCROL = ANTIC+4 VSCROL = ANTIC+5 PMBASE = ANTIC+7 CHBASE = ANTIC+9 ;CHBASE<--CHBAS ON OPEN S: OR E: WSYNC = ANTIC+10 VCOUNT = ANTIC+11 PENH = ANTIC+12 PENV = ANTIC+13 NMIEN = ANTIC+14 ;NMIEN<--40 POWER ON AND [SETVBV] NMIRES = ANTIC+15 ;STROBED NMIST = ANTIC+15 PIA = $D300 ;VBLANK ACTION DESCRIPTION PORTA = PIA+0 ;PORTA-->STICK0,1 X-Y CONTROLLERS PORTB = PIA+1 ;PORTB-->STICK2,3 X-Y CONTROLLERS PACTL = PIA+2 ;NONE PACTL<--3C [INIT] PBCTL = PIA+3 ;NONE PBCTL<--3C [INIT] ; ; ; ; .PAGE .PAGE LIST S .TITLE 'CENTRAL INPUT/OUTPUT (CIO) 2-7-79' ; UPDATED BY AL MILLER 3-9-79 ASCZER = '0 ;ASCII ZERO COLON = $3A ;ASCII COLON EOL = $9B ;END OF RECORD .PAGE ; ; CIO JUMP VECTOR FOR USERS *=CIOV JMP CIO ;GO TO CIO ; ; CIO INIT JUMP VECTOR FOR POWER UP *=CIOINV JMP CIOINT ;GO TO INIT ; ; ; ERROR ROUTINE ADDRESS EQUATE ; ERRTNH =ERRTN/256 "MOVED TO LINE 788" ; ERRTNL =-ERRTNH*256+ERRTN "MOVED TO LINE 789" ; ; *=CIOORG ; ; CIO INITIALIZATION (CALLED BY MONITOR AT POWER UP) CIOINT: LDX #0 CIOI1: LDA #IOCFRE ;SET ALL IOCB'S TO FREE STA ICHID,X ;BY SETTING HANDLER ID'S=$FF LDA #ERRTNL STA ICPTL,X ;POINT PUT TO ERROR ROUTINE LDA #ERRTNH STA ICPTH,X TXA CLC ADC #IOCBSZ ;BUMP INDEX BY SIZE TAX CMP #MAXIOC ;DONE? BCC CIOI1 ;NO RTS ;YES, RETURN ; ; ERROR ROUTINE FOR ILLEGAL PUT ERRTN =*-1 ERRTNH =ERRTN/256 ERRTNL =(-ERRTNH)*256+ERRTN LDY #NOTOPN ;IOCB NOT OPEN RTS .PAGE ; ; CIO LOCAL RAM (USES SPARE BYTES IN ZERO PAGE IOCB) ENTVEC = ICSPRZ ; ; CIO MAIN ROUTINE ; ; CIO INTERFACES BETWEEN USER AND INPUT/OUTPUT DE CIO: STA CIOCHR ;SAVE POSSIBLE OUTPUT CHARACTER STX ICIDNO ;SAVE IOCB NUMBER * N ; ; CHECK FOR LEGAL IOCB TXA AND #$F ;IS IOCB MULTIPLE OF 16? BNE CIERR1 ;NO, ERROR CPX #MAXIOC ;IS INDEX TOO LARGE? BCC IOC1 ;NO ; ; INVALID IOCB NUMBER -- RETURN ERROR CIERR1: LDY #BADIOC ;ERROR CODE JMP CIRTN1 ;RETURN ; ; MOVE USER IOCB TO ZERO PAGE IOC1: LDY #0 IOC1A: LDA IOCB,X ;USER IOCB STA IOCBAS,Y ;TO ZERO PAGE INX INY CPY #12 ;12 BYTES BCC IOC1A ; ; COMPUTE CIO INTERNAL VECTOR FOR COMMAND LDY #NVALID ;ASSUME INVALID CODE LDA ICCOMZ ;COMMAND CODE TO INDEX CMP #OPEN ;IS COMMAND LEGAL? BCC CIERR4 ;NO TAY ; ; MOVE COMMAND TO ZERO BASE FOR INDEX CPY #SPECIL ;IS COMMAND SPECIAL? BCC IOC2 ;NO LDY #SPECIL ;YES, SET SPECIAL OFFSET INDEX IOC2: STY ICCOMT ;SAVE COMMAND FOR VECTOR LDA COMTAB-3,Y ;GET VECTOR OFFSET FROM TABLE BEQ CIOPEN ;GO IF OPEN COMMAND CMP #2 ;IS IT CLOSE? BEQ CICLOS ;YES CMP #8 ;IS IT STATUS OR SPECIAL? BCS CISTSP ;YES CMP #4 ;IS IT READ? BEQ CIREAD ;YES JMP CIWRIT ;ELSE, MUST BE WRITE .PAGE ; ; OPEN COMMAND ; ; FIND DEVICE HANDLER IN HANDLER ADDRESS TABLE CIOPEN: LDA ICHIDZ ;GET HANDLER ID CMP #IOCFRE ;IS THIS IOCB CLOSED? BEQ IOC6 ;YES ; ; ERROR -- IOCB ALREADY OPEN CIERR3: LDY #PRVOPN ;ERROR CODE CIERR4: JMP CIRTN1 ;RETURN ; ; GO FIND DEVICE IOC6: JSR DEVSRC ;CALL DEVICE SEARCH BCS CIERR4 ;GO IF DEVICE NOT FOUND ; ; DEVICE FOUND, INITIALIZE IOCB FOR OPEN ; ; COMPUTE HANDLER ENTRY POINT IOC7: JSR COMENT BCS CIERR4 ;GO IF ERROR IN COMPUTE ; ; GO TO HANDLER FOR INITIALIZATION JSR GOHAND ;USE INDIRECT JUMP ; ; STORE PUT BYTE ADDRESS-1 INTO IOCB LDA #PUTCHR ;SIMULATE PUT CHARACTER STA ICCOMT JSR COMENT ;COMPUTE ENTRY POINT LDA ICSPRZ ;MOVE COMPUTED VALUE STA ICPTLZ ;TO PUT BYTE ADDRESS LDA ICSPRZ+1 STA ICPTHZ JMP CIRTN2 ;RETURN TO USER .PAGE ; ; ; CLOSE COMMAND CICLOS: LDY #SUCCES ;ASSUME GOOD CLOSE STY ICSTAZ JSR COMENT ;COMPUTE HANDLER ENTRY POINT BCS CICLO2 ;GO IF ERROR IN COMPUTE JSR GOHAND ;GO TO HANDLER TO CLOSE DEVICE CICLO2: LDA #IOCFRE ;GET IOCB "FREE" VALUE STA ICHIDZ ;SET HANDLER ID LDA #ERRTNH STA ICPTHZ ;SET PUT BYTE TO POINT TO ERROR LDA #ERRTNL STA ICPTLZ JMP CIRTN2 ;RETURN ; ; ; STATUS AND SPECIAL REQUESTS ; DO IMPLIED OPEN IF NECESSARY AND GO TO DEVICE CISTSP: LDA ICHIDZ ;IS THERE A HANDLER ID? CMP #IOCFRE BNE CIST1 ;YES ; ; IOCB IS FREE, DO IMPLIED OPEN JSR DEVSRC ;FIND DEVICE IN TABLE BCS CIERR4 ;GO IF ERROR IN COMPUTE ; ; COMPUTE AND GO TO ENTRY POINT IN HANDLER CIST1: JSR COMENT ;COMPUTER HANDLER ENTRY VECTOR JSR GOHAND ;GO TO HANDLER ; ; RESTORE HANDLER INDEX (DO IMPLIED CLOSE) LDX ICIDNO ;IOCB INDEX LDA ICHID,X ;GET ORIGINAL HANDLER ID STA ICHIDZ ;RESTORE ZERO PAGE JMP CIRTN2 ;RETURN .PAGE ; ; READ -- DO GET COMMANDS CIREAD: LDA ICCOMZ ;GET COMMAND BYTE AND ICAX1Z ;IS THIS READ LEGAL? BNE RCI1A ;YES ; ; ILLEGAL READ -- IOCB OPENED FOR WRITE ONLY LDY #WRONLY ;ERROR CODE RCI1B: JMP CIRTN1 ;RETURN ; ; COMPUTE AND CHECK ENTRY POINT RCI1A: JSR COMENT ;COMPUTE ENTRY POINT BCS RCI1B ;GO IF ERROR IN COMPUTE ; ; GET RECORD OR CHARACTERS LDA ICBLLZ ORA ICBLLZ+1 ;IS BUFFER LENGTH ZERO? BNE RCI3 ;NO JSR GOHAND STA CIOCHR JMP CIRTN2 ; ; LOOP TO FILL BUFFER OR END RECORD RCI3: JSR GOHAND ;GO TO HANDLER TO GET BYTE STA CIOCHR ;SAVE BYTE BMI RCI4 ;END TRANSFER IF ERROR LDY #0 STA (ICBALZ),Y ;PUT BYTE IN USER BUFFER JSR INCBFP ;INCREMENT BUFFER POINTER LDA ICCOMZ ;GET COMMAND CODE AND #2 ;IS IT GET RECORD? BNE RCI1 ;NO ; ; CHECK FOR EOL ON TEXT RECORDS LDA CIOCHR ;GET BYTE CMP #EOL ;IS IT AN EOL? BNE RCI1 ;NO JSR DECBFL ;YES, DECREMENT BUFFER LENGTH JMP RCI4 ;END TRANSFER ; ; CHECK BUFFER FULL RCI1: JSR DECBFL ;DECREMENT BUFFER LENGTH BNE RCI3 ;CONTINUE IF NON ZERO .PAGE ; ; BUFFER FULL. RECORD NOT ENDED ; DISCARD BYTES UNTIL END OF RECORD RCI2: LDA ICCOMZ ;GET COMMAND BYTE AND #2 ;IS IT GET CHARACTER? BNE RCI4 ;YES, END TRANSFER ; ; LOOP TO WAIT FOR EOL RCI6: JSR GOHAND ;GET BYTE FROM HANDLER STA CIOCHR ;SAVE CHARACtER BMI RCI4 ;GO IF ERROR ; ; TEXT RECORD. WAIT FOR EOL LDA CIOCHR ;GET GOT BYTE CMP #EOL ;IS IT EOL? BNE RCI6 ;NO, CONTINUE ; ; END OF RECORD. BUFFER FULL -- SEND TRUNCATED RECORD MESSAGE RCI1I: LDA #TRNRCD ;ERROR CODE STA ICSTAZ ;STORE IN 10GB ; ; TRANSFER DONE RCI4: JSR SUBBFL ;SET FINAL BUFFER LENGTH JMP CIRTN2 ;RETURN .PAGE ; ; WRITE -- DO PUT COMMANDS CIWRIT: LDA ICCOMZ ;GET COMMAND BYTE AND ICAX1Z ;IS THIS WRITE LEGAL? BNE WCIIA ;YES ; ; ILLEGAL WRITE -- DEVICE OPENED FOR READ ONLY LDY #RDONLY ;ERROR CODE WCI1B: JMP CIRTN1 ;RETURN ; ; COMPUTE AND CHECK ENTRY POINT WCIIA: JSR COMENT ;COMPUTE HANDLER ENTRY POINT BCS WCI1B ;GO IF ERROR IN COMPUTE ; ; PUT RECORD OR CHARACTERS LDA ICBLLZ ORA ICBLLZ+1 ;IS BUFFER LENGTH ZERO? BNE WCI3 ;NO LDA CIOCHR ;GET CHARACTER INC ICBLLZ ;SET SUFFER LENOTHI BNE WCI4 ;THEN JUST TRANSFER ONE BYTE ; ; LOOP TO TRANSFER BYTES FROM BUFFER TO HANDLER WCI3: LDY #0 LDA (ICBALZ),Y ;GET BYTE FROM BUFFER STA CIOCHR ;SAVE WCI4: JSR GOHAND ;GO PUT BYTE BMI WCI5 ;END IF ERROR JSR INCBFP ;INCREMENT BUFFER POINTER ; ; CHECK FOR TEXT RECORD LDA ICCOMZ ;GET COMMAND BYTE AND #2 ;IS IT PUT RECORD? BNE WCI1 ;NO ; ; TEXT RECORD -- CHECK FOR EOL TRANSFER LDA CIOCHR ;GET LAST CHARACTER CMP #EOL ;IS IT AN EOL? BNE WCI1 ;NO JSR DECBFL ;DECREMENT BUFFER LENGTH JMP WCI5 ;END TRANSFER ; ; CHECK FOR BUFFER EMPTY WCI1: JSR DECBFL ;DECREMENT BUFFER LENGTH BNE WCI3 ;CONTINUE IF NON ZERO .PAGE ; ; BUFFER EMPTY, RECORD NOT FILLED ; CHECK TYPE OF TRANSFER WCI2: LDA ICCOMZ ;GET COMMAND CODE AND #2 ;IS IT PUT CHARACTER? BNE WCI5 ;YES, END TRANSFER ; ; PUT RECORD (TEXT), BUFFER ,EMPTY, SEND EOL LDA #EOL JSR GOHAND ;GO TO HANDLER ; ; END PUT TRANSFER WCI5: JSR SUBBFL ;SET ACTUAL PUT BUFFER LENGTH JMP CIRTN2 ;RETURN .PAGE ; ; CIO RETURNS ; RETURNS WITH Y=STATUS CIRTN1: STY ICSTAZ ;SAVE STATUS ; ; RETURNS WITH STATUS STORED IN ICSTAZ ; MOVE IOCB IN ZERO PAGE BACK TO USER AREA CIRTN2: LDY ICIDNO ;GET IOCB INDEX LDA ICBAL,Y STA ICBALZ ;RESTORE USER BUFFER POINTER LDA ICBAH,Y STA ICBAHZ LDX #0 ;LOOP COUNT AND INDEX CIRT3: LDA IOCBAS,X ;ZERO PAGE STA IOCB,Y ;TO USER AREA INX INY CPX #12 ;12 BYTES BCC CIRT3 ; ; RESTORE A,X, & Y LDA CIOCHR ;GET LAST CHARACTER LDX ICIDNO ;IOCB INDEX LDY ICSTAZ ;GET STATUS AND SET FLAGS RTS ;RETURN TO USER .PAGE ; ; ; CIO SUBROUTINES ; ; COMENT -- CHECK AND COMPUTE HANDLER ENTRY POINT COMENT: LDY ICHIDZ ;GET HANDLER INDEX CPY #MAXDEV+1 ;IS IT A LEGAL INDEX? BCC COM1 ;YES ; ; ILLEGAL HANDLER INDEX MEANS DEVICE NOT OPEN FOR OPERATION LDY #NOTOPN ;ERROR CODE BCS COM2 ;RETURN ; ; USE HANDLER ADDRESS TABLE AND COMMAND TABLE TO GET VECTOR COM1: LDA HATABS+1,Y ;GET LOW BYTE OF ADDRESS STA ICSPRZ ;AND SAVE IN POINTER LDA HATABS+2,Y ;GET HI BYTE OF ADDRESS STA ICSPRZ+1 LDY ICCOMT ;GET COMMAND CODE LDA COMTAB-3,Y ;GET COMMAND OFFSET TAY LDA (ICSPRZ),Y ;GET LOW BYTE OF VECTOR FROM TAX ;HANDLER ITSELF AND SAVE INY LDA (ICSPRZ),Y ;GET HI BYTE OF VECTOR STA ICSPRZ+1 STX ICSPRZ ;SET LO BYTE CLC ;SHOW NO ERROR COM2: RTS ; ; ; DECBFL -- DECREMENT BUFFER LENGTH DOUBLE BYTE ; Z FLAG = 0 ON RETURN IF LENGTH = 0 AFTER DECREMENT DECBFL: DEC ICBLLZ ;DECREMENT LOW BYTE LDA ICBLLZ ;CHECK IT CMP #$FF ;DID IT GO BELOW? BNE DECBF1 ;NO DEC ICBLLZ+1 ;DECREMENT HI BYTE DECBF1: ORA ICBLLZ+1 ;SET Z IF BOTH ARE ZERO RTS ; ; ; INCBFP -- INCREMENT WORKING BUFFER POINTER INCBFP: INC ICBALZ ;BUMP LOW BYTE BNE INCBF1 ;GO IF NOT ZERO INC ICBALZ+1 ;ELSE, BUMP HI BYTE INCBF1: RTS ; ; ; SUBBFL -- SET BUFFER LENGTH = BUFFER LENGTH - WORKING BYTE COUNT SUBBFL: LDX ICIDNO ;GET IOCB INDEX SEC LDA ICBLL,X ;GET LOW BYTE OF INITIAL LENGTH SBC ICBLLZ ;SUBTRACT FINAL LOW BYTE STA ICBLLZ ;AND SAVE BACK LDA ICBLH,X ;GET HI BYTE SBC ICBLLZ+1 STA ICBLHZ RTS ; ; ; GOHAND -- GO INDIRECT TO A DEVICE HANDLER ; Y= STATUS ON RETURN, N FLAG=1 IF ERROR ON RETURN GOHAND: LDY #FNCNOT ;PREPARE NO FUNCTION STATUS FOR HANDLER RTS JSR CIJUMP ;USE THE INDIRECT JUMP STY ICSTAZ ;SAVE STATUS CPY #0 ;AND SET N FLAG RTS ; ; INDIRECT JUMP TO HANDLER BY PAUL'S METHOD CIJUMP: TAX ;SAVE A LDA ICSPRZ+1 ;GET JUMP ADDRESS HI BYTE PHA ;PUT ON STACK LDA ICSPRZ ;GET JUMP ADDRESS LO BYTE PHA ;PUT ON STACK TXA ;RESTORE A LDX ICIDNO ;GET IOCB INDEX RTS ;GO TO HANDLER INDIRECTLY .PAGE ; ; DEVSRC -- DEVICE SEARCH, FIND DEVICE IN HANDLER ADDRESS TABLE ; ; LOOP TO FIND DEVICE DEVSRC: LDY #0 LDA (ICBALZ),Y ;GET DEVICE NAME FROM USER BEQ CIERR2 LDY #MAXDEV ;INITIAL COMPARE INDEX DEVS1: CMP HATABS,Y ;IS THIS THE DEVICE? BEQ DEVS2 ;YES DEY DEY ;ELSE, POINT TO NEXT DEVICE NAME DEY BPL DEVS1 ;CONTINUE FOR ALL DEVICES ; ; NO DEVICE FOUND, DECLARE NON-EXISTENT DEVICE ERROR CIERR2: LDY #NONDEV ;ERROR CODE SEC ;SHOW ERROR BCS DEVS4 ;AND RETURN ; ; FOUND DEVICE, SET ICHID,ICDNO, AND INIT DEVICE DEVS2: TYA STA ICHIDZ ;SAVE HANDLER INDEX SEC LDY #1 LDA (ICBALZ),Y ;GET DEVICE NUMBER (DRIVE NUMBER) SBC #ASCZER ;SUBTRACT ASCII ZERO CMP #$A ;IS NUMBER IN RANGE? BCC DEVS3 ;YES LDA #1 ;NO. DEFAULT TO ONE DEVS3: STA ICDNOZ ;SAVE DEVICE NUMBER CLC ;SHOW NO ERROR ; ; RETURN DEVS4: RTS .PAGE ; ; ; CIO ROM TABLES ; ; COMMAND TABLE ; MAPS EACH COMMAND TO OFFSET FOR APPROPRIATE VECTOR IN HANDLER COMTAB: BYTE 0,4,4,4,4,6,6,6,6,2,8,10 LENGTH =*-CIOINT CRNTP1 =* *=$14 CIOSPR: BYTE INTORG-CRNTP1 ;^GCIOL IS TOO LONG ; .TITLE 'INTERRUPT HANDLER' ;LIVES ON DK1:INTHV.SRC SRTIM2 = 6 ;SECOND REPEAT INTERVAL ; ; THIS IS TO MAKE DOS 2 WORK WHICH USED AN ABSOLUTE ADDRESS ; *=$E912 JMP SETVBL *=SETVBV JMP SETVBL JMP SYSVBL JMP XITVBL *=INTINV JMP IHINIT ; *=VCTABL+INTABS-VDSLST ; .WORD SYRTI ;VDSLST .WORD SYIRQB ;VPRCED .WORD SYIRQB ;VINTER .WORD SYIRQB ;VBREAK ; .RES 8 .WORD SYIRQB ;VTMIR1 .WORD SYIRQB ;VTIMR2 .WORD SYIRQB ;VTMIR4 .WORD SYIRQ ;VIMIRQ .WORD 0,0,0,0,0 ;CDTMV1-4 .WORD SYSVBL ;VVBLKI .WORD XITVBL ;VVSLKD ; *=$900C ; LDA #PIRQH ;SET UP RAM VECTORS FOR LINBUG VERSION STA $FFF9 LDA #PIRQL STA $FFF8 LDA #PNMIH STA $FFFB LDA #PNMIL STA $FFFA RTS .PAGE ; ; IRQ HANDLER ; ; JUMP THRU IMMEDIATE IRQ VECTOR, WHICH ORDINARILY POINTS TO ; SYSTEM IRQ; DETERMINE & CLEAR CAUSE, JUMP THRU SOFTWARE VECTOR. ; *=INTORG IHINIT: LDA #$40 ;VBL ON BUF DLIST OFF***FOR NOW*** STA NMIEN ;ENABLE DISPLAY LIST, VERTICAL BLANK LDA #$38 ;LOOK AT DATA DIRECTION REGISTERS IN PIA STA PACTL STA PBCTL LDA #0 ;MAKE ALL INPUTS STA PORTA STA PORTB LDA #$3C ;BACK TO PORTS STA PACTL STA PBCTL RTS PIRQ: JMP (VIMIRU) CMPTAB: .BYTE $80 ;BREAK KEY .BYTE $40 ;KEY STROKE .BYTE $04 ;TIMER 4 .BYTE $02 ;TIMER 2 .BYTE $01 ;TIMER 1 .BYTE $08 ;SERIAL OUT COMPLETE .BYTE $10 ;SERIAL OUT READY .BYTE $20 ;SERIAL IN READY ; THIS IS A TABLE OF OFFSETS INTO PAGE 2. THEY POINT TO ADRTAB: .BYTE BRKKY-INTABS .BYTE VKEYBD-INTABS .BYTE VTIMR4-INTABS .BYTE VTIMR2-INTABS .BYTE VTIMR1-INTABS .BYTE VSEROC-INTABS .BYTE VSEROR-INTABS .BYTE VSERIN-INTABS SYIRQ: PHA ;SAVE ACCUMULATOR LDA IRQST ; CHECK FOR SERIAL IN AND #$20 BNE SYIRQ2 LDA #$DF ; MASK ALL OTHERS STA IRQEN LDA POKMSK STA IRQEN JMP (VSERIN) SYIRQ2: TXA ;PUT X INTO ACC PHA ;SAVE K ONTO STACK LDX #$6 ;START WITH SIX OFFSET LOOPM: LDA CMPTAB,X ;LOAD MASK CPX #5 ;CHECK TO SEE IF COMPLETE IS SET BNE LOOPM2 AND POKMSK ;IS THIS INTERUPT ENABLED? BEQ LL LOOPM2: BIT IRQST ; IS IT THE INTERUPT? BEQ JMPP LL: DEX ;NO DEC X AND TRY NEXT MASK BPL LOOPM ;IF NOT NEC 0010 LOOPH JMP SYIRQ8 ;DONE BUT NO INTERUPT JMPP: EOR #$FF ;COMPLEMENT MASK STA IRQEN ;ENABLE ALL OTHERS LDA POKMSK ; GET POKE MASK STA IRQEN ; ENABLE THOSE IN POKE MASK LDA ADRTAB,X TAX LDA INTABS,X ; GET ADDRESS LOW PART STA JVECK ; PUT IN VECTOR LDA INTABS+1,X ; GET ADDRESS HIGH PART STA JVECK+1 ; PUT IN VECTOR HIGH PART PLA ; PULL X REGISTER FROM STACK TAX ; PUT IT INTO X JMP (JVECK) ; JUMP TO THE PROPER ROUTINE BRKKY2: LDA #0 ; BREAK KEY ROUTINE STA BRKKEY ; SET BREAK KEY FLAG STA SSFLAG ; START/STOP FLAG STA CRSINH ; CURSOR INHIBIT STA ATRACT ; TURN OFF ATRACT MODE PLA RTI ;EXIT FROM INT SYIRQ8: PLA TAX BIT PACTL ;PROCEED ***I GUESS*** BPL SYIRQ9 LDA PORTA ;CLEAR INT STATUS BIT JMP (VPRCED) SYIRQ9: BIT PBCTL ;INTERRUPT ***I GUESS*** BPL SYIRQA LDA PORTB ;CLEAR INT STATUS JMP (VINTER) SYIRQA: PLA STA JVECK PLA PHA AND #$10 ;B BIT OF P REGISTER BEQ SYRTI2 LDA JVECK PHA JMP (VBREAK) SYRTI2: LDA JVECK PHA SYIRQB: PLA SYRTI: RTI ;UNIDENTIFIED INTERRUPT, JUST RETURN .PAGE ; ; NMI HANDLER ; ; DETERMINE CAUSE AND JUMP THRU VECTOR ; PNMI: BIT NMIST BPL PNMI1 ;SEE IF DISPLAY LIST JMP (VDSLST) PNMI1: PHA LDA NMIST AND #$20 ;SEE IF RESET BEQ *+5 JMP WARMSV ;DO THRU WARM START JUMP TXA ;SAVE REGISTERS PHA TYA PHA STA NMIRES ;RESET INTERRUPT STATUS JMP (VVBLKI) ;JUMP THRU VECTOR .PAGE ; ; SYSTEM VBLANK ROUTINE ; ; INC FRAME COUNTER. PROCESS COUNTDOWN TIMERS. EXIT IF I WAS SET. CLEAR ; SET DLISTL, DLISTH, DMACTL FROM RAM CELLS. DO SOFTWARE REPEAT. ; SYSVBL: INC RTCLOK+2 ;INC FRAME COUNTER BNE SYSVB1 INC ATRACT ;INCREMENT ATRACT (CAUSES ATRACT WHEN MINUS) INC RTCLOK+1 BNE SYSVB1 INC RTCLOK SYSVB1: LDA #$FE ;{ATRACT] SET DARK MASK TO NORMAL LDX #0 ;SET COLRSH TO NORMAL LDY ATRACT ;TEST ATRACT FOR NEGATIVE BPL VBATRA ;WHILE POSITIVE DONT GO INTO ATRACT STA ATRACT ;IN ATRACTI SO STAY BY STA $FE LDX RTCLOK+1 ;COLOR SHIFT FOLLOWS RICLOK+1 LDA #$F6 ;SET DARK MASK TO DARK VBATRA: STA DRKMSK STX COLRSH LDX #0 ;POINT TO TIMER1 JSR DCTIMR ;GO DECREMENT TIMER1 BNE SYSVB2 ;BRANCH IF STILL COUNTING JSR JTIMR1 ;GO JUMP TO ROUTINE SYSVB2: LDA CRITIC BNE XXIT ;GO IF CRITICAL SET TSX ;SEE IF I WAS SET LDA $104,X ;GET STACKED P AND #$04 ;I BIT BEQ SYSVB3 ;BRANCH IF OK XXIT: JMP XITVBL ;I WAS SET, EXIT SYSVB3: LDA PENV STA LPENV LDA PENH STA LPENH LDA SDLSTH STA DLISTH LDA SDLSTL STA DLISTL LDA SDMCTL STA DMACTL LDA GPRIOR ;GLOBAL PRIOR STA PRIOR LDX #$08 ;TURN OFF KEYBOARD SPEAKER STX CONSOL SCOLLP: CLI ;DISABLE INTERUPTS LDA PCOLR0, X ;LOAD COLOR REGISTERS FROMRAM EOR COLRSH ;DO COLOR SHIFT AND DRKMSK ;AND DARK ATRACT STA COLPM0,X DEX BPL SCOLLP LDA CHBAS STA CHBASE LDA CHACT STA CHACTL LDX #2 ;POINT TO TIMER 2 JSR DCTIMR BNE SYSVB4 ;IF DIDNT GO ZERO JSR JTIMR2 ;GO JUMP TO TIMER2 ROUTINE SYSVB4: LDX #2 ;RESTORE X SYSVBB: INX INX LDA CDTMV1,X ORA CDTMV1+1,X BEQ SYSVBA JSR DCTIMR ;DECREMENT AND SET FLAG IF NONZERO STA CDTMF3-4,X SYSVBA: CPX #8 ;SEE IF DONE ALL 3 BNE SYSVBB ;LOOP ; CHECK DEBOUNCE COUNTER LDA SKSTAT AND #$04 ;KEY DOWN BIT BEQ SYVB6A ;IF KEY DOWN ; KEY UP SO COUNT IT LDA KEYDEL ;KEY DELAY COUNTER BEQ SYVB6A ;IF COUNTED DOWN ALREADY DEC KEYDEL ;COUNT IT ; CHECK SOFTWARE REPEAT TIMER SYVB6A: LDA SRTIMR BEQ SYSVB7 ;DOESN'T COUNT LDA SKSTAT AND #$04 ;CHECK KEY DOWN BIT BNE SYSVB6 ;BRANCH IF NO LONGER DOWN DEC SRTIMR ;COUNT FRAME OF KEY DOWN BNE SYSVB7 ;BRANCH IF NOT RUN OUT ; TIMER RAN OUT - RESET AND SIMULATE KEYBOARD IRQ LDA #SRTIM2 ;TIMER VALUE STA SRTIMR ;SET TIMER LDA KBCODE ;GET THE KEY STA CH ;PUT INTO CH ; READ GAME CONTROLLERS SYSVB7: LDY #1 LDX #3 STLOOP: LDA PORTA,Y LSR A LSR A LSR A LSR A STA STICK0,X ;STORE JOYSTICK DEX LDA PORTA,Y AND #$F STA STICK0,X ;STORE JOYSTICK DEX DEY BPL STLOOP ; LDX #3 STRL: LDA TRIG0,X ;MOVE JOYSTICK TRIGGERS STA STRIG0,X LDA POT0,X ;MOVE POT VALUES STA PADDL0,X LDA POT4,X STA PADDL4,X DEX BPL STRL STA POTGO ;START POTS FOR NEXT TIME ; LDX #6 LDY #3 PTRLP: LDA STICK0,Y ;TRANSFER BITS FROM JOYSTICKS LSR A ;TO PADDLE TRIGGERS LSR A LSR A STA PTRIG1,X LDA #0 ROL A STA PTRIG0,X DEX DEX DEY BPL PTRLP ; JMP (VVBLKD) ;GO TO DEFERRED VBLANK ROUTINE SV7H = SYSVB7/256 SV7L = (-256)*SV7H+SYSVB7 SYSVB6: LDA #0 STA SRTIMR ;ZERO TIMER BEQ SYSVB7 ;UNCOND JTIMR1: JMP (CDTMA1) JTIMR2: JMP (CDTMA2) ; ; SUBROUTINE TO DECREMENT A COUNTDOWN TIMER ; ENTRY X=OFFSET FROM TIMER 1 ; EXIT A,P=ZERO IF WENT ZERO, FF OTHERWISE ; DCTIMR: LDY CDTMV1,X ;LO BYTE BNE DCTIM1 ;NONZERO, GO DEC IT LDY CDTMV1+1,X ;SEE IF BOTH ZERO BEQ DCTXF ;YES, EXIT NONZERO DEC CDTMV1+1,X ;DEC HI BYTE DCTIM1: DEC CDTMV1,X ;DEC LO BYTE BNE DCTXF LDY CDTMV1+1,X BNE DCTXF LDA #0 ;WENT ZERO. RETURN ZERO RTS DCTXF: LDA #$FF ;RETURN NONZERO RTS .PAGE ; ; SUBROUTINE TO SET VERTICAL BLANK VECTORS AND TIMERS ; ENTRY X=HI,Y=LO BYTE TO SET ; A= 1-5 TIMERS 1-5 ; 6 IMM VBLANK ; 7 DEF VBLANK ; SETVBL: ASL A ;MUL BY 2 STA INTEMP TXA LDX #5 STA WSYNC ;WASTE 20 CPU CYCLES SETLOP: DEX ;TO ALOWD VBLANK TO HAPPEN BNE SETLOP ;IF THIS IS LINE "7C" LDX INTEMP STA CDTMV1-1,X TYA STA CDTMV1-2,X RTS ; ; EXIT FROM VERTICAL BLANK ; XITVBL: PLA ;UNSTACK Y TAY PLA ;UNSTACK X TAX PLA ;UNSTACK A RTI ;AND GO BACK FROM WHENCE. PIRQH = PIRQ/256 PIRQL = (-256)*PIRQH+PIRQ PNMIH = PNMI/256 PNMIL = (-256)*PNMIH+PNMI ; SPARE BYTE OR MODULE TOO LONG FLAG CRNTP2 =* *=$14 INTSPR: .BYTE SIOORG-CRNTP2 ;^GINTHV IS TOO LONG ; .TITLE 'SIO ( SERIAL BUS INPUT/OUTPUT CONTROLLER )' ; COLLEEN OPERATING SYSTEM ; ; SIO ( SERIAL BUS INPUT/OUTPUT CONTROLLER ) ; WITH SOFTWARE BAUD RATE CORRECTION ON CASSETTE ; ; ; AL MILLER 3-APR-19 ; ; ; THIS MODULE HAS ONE ENTRY POINT. IT IS CALLED BY THE DEVICE ; HANDLERS. IT INTERPRETS A PREVIOUSLY ESTABLISHED DEVICE CONTROL ; BLOCK (STORED IN GLOBAL RAM) TO ISSUE COMMANDS ; TO THE SERIAL BUS TO CONTROL TRANSMITTING AND RECEIVING DATA. ; ; ; ; .PAGE ; EQUATES ; ; DCD DEVICE BUS ID NUMBERS FLOPPY = $30 ;PRINTR = $40 ;CASSET = $80 ;!!!!! ***** CASET = $60 ;!!!!! ***** ; ; ;BUS COMMANDS ; READ = 'R WRITE = 'W ;STATIS = 'S ;FORMAT = '! ; ; ; COMMAND AUX BYTES ; SIDWAY = 'S ;PRINT 18 CHARACTERS SIDEWAYS NORMAL = 'N ;PRINT 40 CHARACTERS NORMALLY DOUBLE = 'D ;PRINT 20 CHARACTERS DOUBLE WIDE PLOT = 'P ;PLOT MODE ; ; ; BUS RESPONSES ; ACK = 'A ;DEVICE ACKNOWLEDGES INFORMATION NACK = 'N ;DEVICE DID NOT UNDERSTAND COMPLT = 'C ;DEVICE SUCCESSFULLY COMPLETED OPERATION ERROR = 'E ;DEVICE INCURRED AN ERROR IN AN ATTEMPTED OP ; ; ; MISCELLANEOUS EQUATES ; B192LO = $28 ;19200 BAUD RATE POKEY COUNTER VALUES (LO BY B192HI = $00 ;(HI BYTE) B600LO = $CC ;600 BAUD (LO BYTE) B600HI = $05 ;(HI BYTE) HITONE = $05 ;FSK HI FREQ POKEY COUNTER VALUE (5326 HZ) LOTONE = $07 ;FSK LO FREQ POKEY COUNTER VALUE (3995 HZ) ; .IF PALFLG WIRGLO = 150 ;WRITE INTER RECORD GAP (IN 1/60 SEC) RIRGLO = 100 ;READ INTER RECORD GAP (IN 1/60 SEC) WSIRG = 13 ;SHORT WRITE INTER RECORD GAP RSIRG = 8 ;SHORT READ INTER RECORD GAP .ENDIF .IF PALFLG-1 WIRGLO = 180 ;WRITE INTER RECORD GAP (IN 1/60 SEC) RIRGLO = 120 ;READ INTER RECORD GAP (IN 1/60 SEC) WSIRG = 15 ;SHORT WRITE INTER RECORD GAP RSIRG = 10 ;SHORT READ INTER RECORD GAP .ENDIF WIRGHI = 0 RIRGHI = 0 ; NCOMLO = $34 ;PIA COMMAND TO LOWER NOT COMMAND LINE NCOMHI = $3C ;PIA COMMAND TO RAISE NOT COMMAND LINE MOTRGO = $34 ;PIA COMMAND TO TURN ON CASSETTE MOTOR MOTRST = $3C ;PIA COMMAND TO TURN OFF MOTOR ; TEMPHI = TEMP/256 ;ADDRESS OF TEMP CELL (HI BYTE) TEMPLO = (-256)*TEMPHI+TEMP ;(LO BYTE) CBUFHI = CDEVIC/256 ;ADDRESS OF COMMAND BUFFER (HI BYTE) CBUFLO = (-256)*CBUFHI+CDEVIC ;(LO BYTE) ; CRETRI = 13 ;NUMBER OF COMMAND FRAME RETRIES DRETRI = 1 ;NUMBER OF DEVICE RETRIES CTIMLO = 2 ;COMMAND FRAME ACK TIME OUT (LO BYTE) CTIMHI = 0 ;COMMAND FRAME ACK TIME OUT (HI BYTE) ; ; ;JTADRH = JTIMER/256 ;HI BYTE OF JUMP TIMER ROUTINE ADDR ;JTADRL = (-256)*JTADRH+JTIMER ;"MOVED TO LINE 1428" ; .PAGE ; SIO ; ; *=SIOV JMP SIO ;SIO ENTRY POINT ; *=SIOINV JMP SIOINT ;SIO INITIALIZATION ENTRY POINT ; *=SENDEV JMP SENDEN ;SEND ENABLE ENTRY POINT ; *=VCTABL-INTABS+VSERIN ; .WORD ISRSIR ;VSERIN .WORD ISRODN ;VSEROR .WORD ISRTD ;VSEROC ; ; ; *=SIOORG ; ; SIO INITIALIZATION SUBROUTINE ; SIOINT: LDA #MOTRST STA PACTL ;TURN OFF MOTOR ; LDA #NCOMHI STA PBCTL ;RAISE NOT COMMAND LINE ; ; LDA #3 STA SSKCTL ;GET POKEY OUT OF INITIALIZE MODE STA SOUNDR ;INIT POKE ADDRESS FOR QUIET I/O STA SKCTL ; ; RTS ;RETURN ; ; ; ; ; ; SIO: TSX STX STACKP ;SAVE STACK POINTER LDA #1 STA CRITIC ; LDA DDEVIC CMP #CASET BNE NOTCST ;BRANCH IF NOT CASSETTE JMP CASENT ;OTHERWISE JUMP TO CASSETTE ENTER ; ; ALL DEVICES EXCEPT CASSETTE ARE INTELLIGENT ; NOTCST: LDA #0 STA CASFLG ; INIT CASSETTE FLAG TO NO CASSETTE ; LDA #DRETRI ;SET NUMBER OF DEVICE RETRIES STA DRETRY COMMND: LDA #CRETRI ;SET NUMBER OF COMMAND FRAMERETRIES STA CRETRY ; ; SEND A COMMAND FRAME ; COMFRM: LDA #B192LO ;SET BAUD RATE TO 19200 STA AUDF3 LDA #B192HI STA AUDF4 ; CLC ;SET UP COMMAND BUFFER LDA DDEVIC ADC DUNIT ADC #$FF ;SUBTRACT 1 STA CDEVIC ;SET BUS ID NUMBER ; LDA DCOMND STA CCOMND ;SET BUS COMMAND ; LDA DAUX1 ;STORE COMMAND FRAME AUX BYTES 1 AND 2 STA CAUX1 LDA DAUX2 STA CAUX2 ;DONE SETTING UP COMMAND BUFFER ; CLC ;SET BUFFER POINTER TO COMMAND FRAME BUFFER LDA #CBUFLO STA BUFRLO ;AND BUFFER END ADDRESS ADC #4 STA BFENLO LDA #CBUFHI STA BUFRHI STA BFENHI ;DONE SETTING UP BUFFER POINTER ; LDA #NCOMLO ;LOWER NOT COMMAND LINE STA PBCTL ; JSR SENDIN ;SEND THE COMMAND FRAME TO A SMART DEVICE ; LDA ERRFLG BNE BADCOM ;BRANCH IF AN ERROR RECEIVED ; TYA BNE ACKREC ;BRANCH IF ACK RECEIVED ; ; BADCOM: DEC CRETRY ;A NACK OR TIME OUT OCCURED BPL COMFRM ;SO BRANCH IF ANY RETRIES LEFT ; JMP DERR1 ;OTHERWISE, JUMP TO RETURN SECTION ; ; ACKREC: LDA DSTATS ;ACK WAS RECEIVED BPL WATCOM ;BRANCH TO WAIT FOR COMPLETE ; IF THERE IS NO DATA TO BE SENT ; ; ; ; SEND A DATA FRAME TO PERIPHERAL ; LDA #CRETRI ;SET NUMBER OF RETRIES STA CRETRY ; JSR LDPNTR ;LOAD BUFFER POINTER WITH DCB INFORMATION ; JSR SENDIN ;GO SEND THE DATA FRAME TO A SMART DEVICE ; BEQ BADCOM ;BRANCH IF BAD ; ; ; ; WAIT FOR COMPLETE SIGNAL FROM PERIPHERAL ; WATCOM: JSR STTMOT ;SET DDEVICE TIME OUT VALUES IN Y,X ; LDA #$00 STA ERRFLG ;CLEAR ERROR FLAG ; JSR WAITER ;SET UP TIMER AND WAIT BEQ DERR ;BRANCH IF TIME OUT ; ; ; DEVICE DID NOT TIME OUT ; BIT DSTATS BVS MODATA ;BRANCH IF MORE DATA FOLLOWS ; LDA ERRFLG BNE DERR1 ;BRANCH IF AN ERROR OCCURRED BEQ RETURN ;OTHERWISE RETURN ; ; ; ; ; RECEIVE A DATA FRAME FROM PERIPHERAL ; MODATA: JSR LDPNTR ;LOAD BUFFER POINTER WITH DCB INFORMATION ; JSR RECEIV ;GO RECEIVE A DATA FRAME ; DERR: LDA ERRFLG BEQ NOTERR ;BRANCH IF NO ERROR PRECEEDED DATA ; LDA TSTAT ;GET TEMP STATUS STA STATUS ;STORE IN REAL STATUS ; ; NOTERR: LDA STATUS CMP #SUCCES BEQ RETURN ;BRANCH IF COMPLETELY SUCCESSFUL ; DERR1: DEC DRETRY BMI RETURN ;BRANCH IF OUT OF DEVICE RETRIES ; JMP COMMND ;OTHERWISE ONE MORE TIME ; ; ; ; RETURN: JSR SENDDS ;DISABLE POKEY INTERRUPTS LDA #0 STA CRITIC LDY STATUS ;RETURN STATUS IN Y STY DSTATS ;AND THE DCB STATUS WORD RTS RETURN ; ; ; ; ; WAIT SUBROUTINE ; ; WAITS FOR COMPLETE OR ACK ; RETURNS Y=$FF IF SUCCESSFUL, Y=$00 IF NOT ; WAIT: LDA #$00 STA ERRFLG ;CLEAR ERROR FLAG ; CLC ;LOAD BUFFER POINTER WITH ADDRESS LDA #TEMPLO ;OF TEMPORARY RAM CELL STA BUFRLO ADC #1 STA BFENLO ;ALSO SET BUFFER END +1 ADDRESS LDA #TEMPHI STA BUFRHI STA BFENHI ;DONE LOADING POINTER ; LDA #$FF STA NOCKSM ;SET NO CHECKSUM FOLLOWS DATA FLAG ; JSR RECEIV ;GO RECEIVE A BYTE ; LDY #$FF ;ASSUME SUCCESS LDA STATUS CMP #SUCCES BNE NWOK ;BRANCH IF IT DID NOT WORK OK ; ; ; ; WOK: LDA TEMP ;MAKE SURE THE BYTE SUCCESSFULLY RECEIVED CMP #ACK ;WAS ACTUALLY AN ACK OR COMPLETE BEQ GOOD CMP #COMPLT BEQ GOOD ; CMP #ERROR BNE NOTDER ;BRANCH IF DEVICE DID NOT SEND BACK ; A DEVICE ERROR CODE LDA #DERROR STA STATUS ;SET DEVICE ERROR STATUS BNE NWOK ; NOTDER: LDA #DNACK ;OTHERWISE SET HACK STATUS STA STATUS ; NWOK: LDA STATUS CMP #TIMOUT BEQ BAD ;BRANCH IF TIME OUT ; LDA #$FF STA ERRFLG ;SET SOME ERROR FLAG BNE GOOD ;RETURN WITH OUT SETTING Y = 0 ; BAD: LDY #0 ; GOOD: LDA STATUS STA TSTAT RTS ;RETURN ; ; ; ; ; ; SEND SUBROUTINE ; ; SENDS A BUFFER OF BYTES OUT OVER THE SERIAL BUS ; ; SEND: LDA #SUCCES ;ASSUME SUCCESS STA STATUS ; JSR SENDEN ;ENABLE SENDING ; LDY #0 STY CHKSUM ;CLEAR CHECK SUM STY CHKSNT ;CHECKSUM SENT FLAG STY XMTDON ;TRANSMISSION DONE FLAG ; ; LDA (BUFRLO),Y ;PUT FIRST BYTE FROM BUFFER STA SEROUT ;INTO THE SERIAL OUTPUT REGISTER ; ; STA CHKSUM ;PUT IT IN CHECKSUM ; NOTDON: LDA BRKKEY BNE NTBRKO JMP BROKE ;JUMP IF BREAK KEY PRESSED ; NTBRKO: LDA XMTDON ;LOOP UNTIL TRANSMISSION IS DONE BEQ NOTDON ; JSR SENDDS ;DISABLE SENDING ; RTS RETURN ; ; ; ; ; ; ; OUTPUT DATA NEEDED INTERRUPT SERVICE ROUTINE ; ISRODN: TYA PHA ;SAVE Y REG ON STACK ; INC BUFRLO ;INCREMENT DUFFER POINTER BNE NOWRPO INC BUFRHI ; NOWRPO: LDA BUFRLO ;CHECK IF PAST END OF BUFFER CMP BFENLO LDA BUFRHI ;HIGH PART SBC BFENHI BCC NOTEND ;BRANCH IF NOT PAST END OF BUFFER ; LDA CHKSNT BNE RELONE ;BRANCH IF CHECKSUM ALREADY SENT ; LDA CHKSUM STA SEROUT ;SEND CHECK SUM LDA #$FF STA CHKSNT ;SET CHECKSUM SENT FLAG BNE CHKDON ; RELONE: LDA POKMSK ;ENABLE TRANSMIT DONE INTERRUPT ORA #$08 STA POKMSK STA IRQEN ; CHKDON: PLA TAY ;RESTORE Y REG PLA ;RETURN FROM INTERRUPT RTI ; ; NOTEND: LDY #0 LDA (BUFRLO),Y ;PUT NEXT BYTE FROM BUFFER STA SEROUT ;INTO THE SERIAL OUTPUT REGISTER ; CLC ;ADD IT TO CHECKSUM ADC CHKSUM ADC #0 STA CHKSUM ; JMP CHKDON ;GO RETURN ; ; ; ; ; ; ; TRANSMIT DONE INTERRUPT SERVICE ROUTINE ; ISRTD: LDA CHKSNT BEQ FOOEY ;BRANCH IF CHECKSUM NOT YET SENT ; STA XMTDON ;OTHERWISE SET TRANSMISSION DONE FLAG ; LDA POKMSK ;DISABLE TRANSMIT DONE INTERRUPT AND #$F7 STA POKMSK STA IRQEN ; FOOEY: PLA ;RETURN FROM INTERRUPT RTI ; ; ; ; ; ; ; ; ; RECEIVE SUBROUTINE ; RECEIV: LDA #0 ; LDY CASFLG BNE NOCLR ;BRANCH IF CASSETTE ; STA CHKSUM ;CLEAR CHKSUM NOCLR: STA BUFRFL ;BUFFER FULL FLAG STA RECVDN ;RECEIVE DONE FLAG ; ; ; LDA #SUCCES STA STATUS ;SET GOOD STATUS FOR DEFAULT CASE. JSR RECVEN ;DO RECEIVE ENABLE LDA #NCOMHI ;COMMAND FRAME HI COMMAND STA PBCTL ;STORE IN PIA CHKTIM: LDA BRKKEY BNE NTBRK1 JMP BROKE ;JUMP IF BREAK KEY PRESSED ; NTBRK1: LDA TIMFLG ;NO, BEQ TOUT ;IF TIMEOUT, GO SET ERROR STATUS LDA RECVDN BEQ CHKTIM ;DONE ? GOBACK: RTS TOUT: LDA #TIMOUT ;YES, STA STATUS ;SET TIMEOUT STATUS ; ; ; ; ; ; RRETRN: RTS ;RETURN ; ; ; ; ; ; ; ; SERIAL INPUT READY INTERRUPT SERVICE ROUTINE ; ISRSIR: TYA PHA ;SAVE Y REG ON STACK ; ; ; LDA SKSTAT STA SKRES ;RESET STATUS REGISTER ; ******** THIS MAY NOT BE THE PLACE TO DO IT ********* ; BMI NTFRAM ;BRANCH IF NO FRAMING ERROR ; LDY #FRMERR STY STATUS ;SET FRAME ERRORR STATUS ; NTFRAM: AND #$20 BNE NTOVRN ;BRANCH IF NO OVERRUN ERROR ; LDY #OVRRUN STY STATUS ;SET OVERRUN ERROR STATUS ; NTOVRN: LDA BUFRFL BEQ NOTYET ;BRANCH IF BUFFER WAS NOTYET FILLED ; LDA SERIN ;THIS INPUT BYTE 15 THE CHECKSUM CMP CHKSUM BEQ SRETRN ;BRANCH IF CHECKSUMS MATCH ; LDY #CHKERR STY STATUS ;SET CHECKSUM ERROR STATUS ; SRETRN: LDA #$FF ;SET RECEIVE DONE FLAG STA RECVDN ; SUSUAL: PLA TAY ;RESTORE Y REG PLA ;RETURN FROM INTERRUPT RTI ; ; ; NOTYET: LDA SERIN LDY #0 STA (BUFRLO),Y ;STORE INPUT REGISTER INTO BUFFER ; CLC ;ADD IT TO CHECKSUM ADC CHKSUM ADC #0 STA CHKSUM ; INC BUFRLO ;INCREMENT BUFFER POINTER BNE NTWRP1 INC BUFRHI ; NTWRP1: LDA BUFRLO CMP BFENLO LDA BUFRHI SBC BFENHI DCC SUSUAL ;BRANCH IF NEW BUFFER ADDRESS IS IN BUFFER L ; LDA NOCKSM BEQ GOON ;BRANCH IF A CHECKSUM WILL FOLLOW DATA ; LDA #0 STA NOCKSM ;CLEAR NO CHECKSUM FLAG ; BEQ SRETRN ;GO RETURN AND SET RECEIVE DONE FLAG ; ; GOON: LDA #$FF STA BUFRFL ;SET BUFFER FULL FLAG ; BNE SUSUAL ;GO RETURN ; ; ; ; ; ; ; ; ; LOAD BUFFER POINTER SUBROUTINE ; ; LOAD BUFFER POINTER WITH DCB BUFFER INFORMATION ; LDPNTR: CLC LDA DBUFLO STA BUFRLO ADC DBYTLO STA BFENLO ;ALSO SET SUFFER END + 1 ADDRESS ; LDA DBUFHI STA BUFRHI ADC DBYTHI STA BFENHI ; RTS ;RETURN ; ; ; ; ; ; ; ; ; CASSETTE HANDLING CODE ; CASENT: LDA DSTATS BPL CASRED ;BRANCH IF INPUT FROM CASSETTE ; ; WRITE A RECORD ; LDA #B600LO ;SET BAUD RATE TO 600 STA AUDF3 LDA #B600HI STA AUDF4 ; JSR SENDEN ;TURN ON POKEY MARK TONE ; LDY #WSIRG ;LOAD SHORT WRITE INTER RECORD GAP TIME LDA DAUX2 BMI SRTIR0 ;BRANCH IF SHORT GAP IS DESIRED ; LDY #WIRGLO ;SET WRITE IRQ TIME SRTIR0: LDX #WIRGHI JSR SETVBX ; LDA #MOTRGO STA PACTL ;TURN ON MOTOR ; TIMIT: LDA TIMFLG ;LOOP UNTIL DONE BNE TIMIT ; JSR LDPNTR ;LOAD BUFFER POINTER WITH DCB INFORMATION ; JSR SEND ;SEND A BUFFER ; JMP CRETRN ;GO, RETURN ; ; ; ; RECEIVE A RECORD ; CASRED: LDA #$FF STA CASFLG ;SET SET CASSETTE FLAG ; LDY #RSIRG ;LOAD SHORT READ INTER RECORD GAP TIME LDA DAUX2 BMI SRTIR1 ;BRANCH IF SHORT GAP IS DESIRED ; LDY #RIRGLO ;SET TIME OUT FOR READ IRQ SRTIR1: LDX #RIRGHI JSR SETVBX ; LDA #MOTRGO STA PACTL ;TURN ON MOTOR ; TIMIT1: LDA TIMFLG ;LOOP UNTIL DONE BNE TIMIT1 ; JSR LDPNTR ;LOAD BUFFER POINTER WITH DOS INFORMATION ; JSR STTMOT ;SET DEVICE TIME OUT IN Y,X JSR SETVBX ; JSR BEGIN ;SET INITIAL BAUD RATE ; JSR RECEIV ;GO RECEIVE A BLOCK ; CRETRN: LDA DAUX2 BMI SRTIR2 ;BRANCH IF DOING SHORT INTER RECORD GAPS ; DON'T TURN OFF CASSETTE MOTOR LDA #MOTRST STA PACTL ;TURN OFF MOTOR ; SRTIR2: JMP RETURN ;GO RETURN ; ; ; ; ; JTIMER: LDA #$00 JTADRH = JTIMER/256 ;HI BYTE OF JUMP TIMER ROUTINE ADDR JTADRL = (-256)*JTADRH+JTIMER STA TIMFLG ;SET TIME OUT FLAG RTS ; ; ; ; ; ; ; SEND ENABLE SUBROUTINE ; SENDEN: LDA #$07 ;MASK OFF PREVIOUS SERIAL BUS CONTROL BITS AND SSKCTL ORA #$20 ;SET TRANSMIT MODE ; LDY DDEVIC CPY #CASET BNE NOTCAS ;BRANCH IF NOT CASSETTE ; ORA #$08 ;SET THE FSK OUTPUT BIT ; LDY #LOTONE ;SET FSK TONE FREQUENCIES STY AUDF2 LDY #HITONE STY AUDF1 ; NOTCAS: STA SSKCTL ;STORE NEW VALUE TO SYSTEM MASK STA SKCTL ;STORE TO ACTUAL REGISTER ; LDA #$C7 ;MASK OFF PREVIOUS SERIAL BUS INTERRUPT BITS AND POKMSK ORA #$10 ;ENABLE OUTPUT DATA NEEDED INTERRUPT ; ; JMP CONTIN ;GO CONTINUE IN RECEIVE ENABLE SUBROUTINE ; ; ; ; ; ; ; ; ; ; ; RECEIVE ENABLE SUBROUTINE ; RECVEN: LDA #$07 ;MASK OFF PREVIOUS SERIAL BUS CONTROL BITS AND SSKCTL ORA #$10 ;SET RECEIVE MODE ASYNCH. STA SSKCTL ;STORE NEW VALUE TO SYSTEM MASK STA SKCTL ;STORE TO ACTUAL REGISTER ; STA SKRES ;RESET SERIAL PORT/KEYBOARD STATUS REGISTER ; LDA #$C7 ;MASK OFF PREVIOUS SERIAL BUS INTERRUPTBITS AND POKMSK ORA #$20 ;ENABLE RECEIVE INTERRUPT CONTIN: STA POKMSK ;STORE NEW VALUE TO SYSTEM MASK STA IRQEN ;STORE TO ACTUAL. REGISTER ; ; LDA #$28 ;CLOCK CH.3 WITH 1.79 MHZ STA AUDCTL ;CLOCK CH.4 WITH CH. 3 ; LDX #6 ;SET PURE TONES, NO VOLUME LDA #$A8 LDY SOUNDR ;TEST QUIET I/O FLAG BNE NOISE1 ;NE IS NORMAL (NOISY) LDA #$A0 NOISE1: STA AUDC1,X DEX DEX BPL NOISE1 ; LDA #$A0 STA AUDC3 ;TURN OFF SOUND ON CHANNEL 3 LDY DDEVIC CPY #CASET BEQ CAS31 ;BRANCH IF CASSETTE IS DESIRED STA AUDC1 ;OTHERWISE TURN OFF CHANNELS 1 AND 2 STA AUDC2 ; ; CAS31: RTS ;RETURN ; ; ; ; ; ; ; ; ; ; ; DISABLE SEND AND DISABLE RECEIVE SUBROUTINES ; SENDDS: NOP RECVDS: LDA #$C7 ;MASK OFF SERIAL BUS INTERRUPTS AND POKMSK STA POKMSK ;STORE NEW VALUE TO SYSTEM MASK STA IRQEN ;STORE TO ACTUAL REGISTER ; LDX #6 LDA #0 ZERIT: STA AUDC11X DEX DEX BPL ZERIT ;TURN OFF AUDIO VOLUME ; RTS ;RETURN ; ; ; ; ; ; ; ; ; ; ; SET DDEVICE TIME OUT VALUES IN Y,X SUBROUTINE ; STTMOT: LDA DTIMLO ;GET DEVICE TIME OUT IN 1 SECOND INCR ROR A ;PUT 6 HI BITS IN X, LO 2 BITS IN Y ROR A TAY ;TEMP SAVE AND #$3F ;MASK OFF 2 HI BITS TAX ;THIS IS HZ BYTE OF TIME OUT ; TYA ;RESTORE ROR A AND #$C0 ;MASK OFF ALL BUT 2 HI BITS TAY ;THIS IS LO BYTE OF TIME OUT ; RTS ; ; ; ; ; ; ; ; ; ; INTTBL: .WORD ISRSIR ;SERIAL INPUT READY .WORD ISRODN ;OUTPUT DATA NEEDED .WORD ISRTD ;TRANSMISSION DONE ; SIRHI = ISRSIR/256 ;SERIAL INPUT READY ISR ADDRESS SIRLO = (-256)*SIRHI+ISRSIR ODNHI = ISRODN/256 ;OUTPUT DATA NEEDED ISR ADDRESS ODNLO = (-256)*ODNHI+ISRODN TDHI = ISRTD/256 ;TRANSMISSION DONE ISR ADDRESS IDLO = (-256)*TDHI+ISRTD ; ; ; ; ; SEND A DATA FRAME TO AN INTELLIGENT PERIPHERAL SUBROUTINE ; ; SENDIN: LDX #$01 DELAY0: LDY #$FF DELAY1: DEY BNE DELAY1 DEX BNE DELAY0 ; JSR SEND ;GO SEND THE DATA FRAME ; LDY #CTIMLO ;SET ACK TIME OUT LDX #CTIMHI WAITER: JSR SETVBX JSR WAIT ;WAIT FOR ACK ; TYA ;IF Y=0, A TIME OUT OR NACK OCCURED ; RTS ;RETURN ; ; ; ; ; ; ; ; ; ; ; ; COMPUTE VALUE FOR POKEY FREQ REGS FOR THE BAUD RATE AS ; MEASURED BY AN INTERVAL OF THE 'VCOUNT' TIMER. ; COMPUT: STA TIMER2 STY TIMER2+1 ;SAVE FINAL TIMER VALUE JSR ADJUST ;ADJUST VCOUNT VALUE STA TIMER2 ;SAVE ADJUSTED VALUE LDA TIMER1 JSR ADJUST ;ADJUST STA TIMER1 ;SAVE ADJUSTED TIMER1 VALUE LDA TIMER2 SEC SBC TIMER1 STA TEMP1 ;FIND VCOUNT DIFFERENCE LDA TIMER2+1 SEC SBC TIMER1+1 TAY ;FIND VBLANK COUNT DIFFERENCE .IF PALFLG LDA #-$9C HITIMR: CLC ADC #$9C .ENDIF .IF PALFLG-1 LDA #-$83 HITIMR: CLC ADC #$83 ;ACCUMULATE MULTIPLICATION .ENDIF DEY BPL HITIMR ;DONE? CLC ADC TEMP1 ;TOTAL VCOUNT DIFFERENCE FINDX: TAY ;SAVE ACCUM LSR A LSR A LSR A ASL A SEC SBC #22 ;ADJUST TABLE INDEX TAX ;DIVIDE INTERVAL BY 4 TO CET TABLE INDEX TYA ;RESTORE ACCUM AND #7 TAY ;PULL OFF 3 LO BITS OF INTERVAL LDA #-11 DOINTP: CLC ADC #11 ;ACCUMULATE INTERPOLATION CONSTANT DEY BPL DOINTP ;INTERPOLATION CONSTANT COMPUTATION DONE? ; ENINTP: LDY #0 STY ADDCOR ;CLEAR ADDITION CORRECTION FLAG SEC SBC #7 ;ADJUST INTERPOLATION CONSTANT BPL PLUS DEC ADDCOR PLUS: CLC ADC POKTAB,X ;ADD CONSTANT TO LO BYTE TABLE VALUE TAY ;LO BYTE POKEY FREQ VALUE LDA ADDCOR ADC POKTAB+1,X ;ADD CARRY TO HI BYTE TABLEVALUE ; HI BYTE POKEY FREQ VALUE RTS ; ; ; ; ROUTINE TO ADJUST VCOUNT VALUE ; ADJUST: CMP #$7C BMI ADJ1 ;LAROER THAN '7C' ? SEC ;YES SBC #$7C RTS ADJ1: CLC .IF PALFLG ADC #$20 .ENDIF .IF PALFLG-1 ADC #$7 .ENDIF RTS ; ; ; ; ; ; ; ; INITIAL BAUD RATE MEASUREMENT -- USED TO SET THE ; BAUD RATE AT THE START OF A RECORD. ; ; IT IS ASSUMED THAT THE FIRST TWO BYTES OF EVERY ; RECORD ARE 'AA' HEX. ; BEGIN: LDA BRKKEY BNE NTBRK2 JMP BROKE ;JUMP IF BREAK KEY PRESSED ; NTBRK2: SEI ; LDA TIMFLG BNE OKTIM1 ;BRANCH IF NOT TIMEDOUT BEQ TOUT1 ;BRANCH IF TIME OUT ; OKTIM1: LDA SKSTAT AND #$10 ;READ SERIAL PORT BNE BEGIN ;START BIT? STA SAVIO ;SAVE SER. DATA IN LDX VCOUNT ;READ VERTICAL LINECOUNTER LDY RTCLOK+2 ;READ LO BYTE OF VBLANK CLOCK STX TIMER1 STY TIMER1+1 ;SAVE INITIAL TIMER VALUE ; LDX #1 ;SET MODE FLAG STX TEMP3 LDY #10 ;SET BIT COUNTER FOR 10 BITS COUNT: LDA BRKKEY BEQ BROKE ;BRANCH IF BREAK KEY PRESSED ; LDA TIMFLG BNE OKTIMR ;BRANCH IF NOT TIMED OUT TOUT1: CLI JMP TOUT ;BRANCH IF TIME OUT ; OKTIMR: LDA SKSTAT AND #$10 ;READ SERIAL PORT CMP SAVIO ;DATA IN CHANGED YET? BEQ COUNT STA SAVIO ;YES,SAVE SER. DATA IN DEY ;DECR. BIT COUNTER BNE COUNT ;DONE? ; DEC TEMP3 ;YES, BMI GOREAD ;DONE WITH BOTH MODES? LDA VCOUNT LDY RTCLOK+2 ;READ TIMER LO & HI BYTES JSR COMPUT ;NO, COMPUTE SAUD RATE STY CBAUDL STA CBAUDH ;SET BAUD RATE INTO RAM CELLS LDY #9 ;SET BIT COUNTER FOR 9 BITS BNE COUNT ; GOREAD: LDA CBAUDL STA AUDF3 LDA CBAUDH STA AUDF4 ;SET POKEY FREQ REGS FOR BAUD RATE LDA #0 STA SKSTAT LDA SSKCTL STA SKSTAT ; INIT. POKEY SERIAL PORT LDA #$55 STA (BUFRLO),Y ;STORE '$55' AS FIRST RCV. BUFFER INY STA (BUFRLO),Y LDA #$AA STA CHKSUM ;STORE CHECKSUM FOR 2 BYTES OF '$AA' CLC LDA BUFRLO ADC #2 STA BUFRLO LDA BUFRHI ADC #0 STA BUFRHI ;INCR. BUFFER POINTER BY 1 CLI RTS ; ; ; BROKE: JSR SENDDS ;BREAK KEY WAS PRESSED, SO PREPARE LDA #MOTRST ;TO RETURN STA PACTL ;TURN OFF MOTOR STA PBCTL ;RAISE NOT COMMAND LINE ; LDA #BRKABT STA STATUS ;STORE BREAK ABORT STATUS CODE ; LDX STACKP TXS ;RESTORE STACK POINTER ; DEC BRKKEY ;SET BREAK KEY FLAG TO NONZERO CLI ;ALLOW IRQ'S ; JMP RETURN ;GO RETURN ; ; ; ; ; SETVBX: LDA #JTADRL ;STORE TIME OUT ROUTINE ADDRESS STA CDTMA1 LDA #JTADRH STA CDTMA1+1 ; LDA #1 ;SET FOR TIMER 1 ; SEI ;THE SETVBL ROUTINE NEEDS THIS TO CUT SHORT JSR SETVBV ;ANY VBLANKS THAT OCCUR LDA #1 ;SET FOR TIMER 1 STA TIMFLG ;SET FLAG TO NOT TIMED OUT CLI RTS ; ; ; ; ; ; ; ; 'VCOUNT' INTERVAL TIMER MEASUREMENT -- TO -- POKEY FREQ REG VALUE ; CONVERSION TABLE ; ; ; THE VALUES STORED IN THE TABLE ARE 'AUDF+7'. ; ; THE FOLLOWING FORMULAS WERE USED TO DETERMINE THE TABLE VALUES: ; ; F OUT F IN/(2*(AUDF+M)) , WHERE F IN=1.78979 MHZ. & M=7 ; ; FROM THIS WAS DERIVED THE FORMULA USED TO COMPUTE THE ; TABLE VALUES BASED ON A MEASUREMENT OF THE PERIOD BY ; AN INTERVAL OF THE 'VCOUNT' TIMER. ; ; AUDF+7=(11.365167)*T OUT, WHERE T OUT=# OF COUNTS ; (127 USEC. RESOLUTION) OF 'VCOUNT' FOR 1 ; CHARACTER TIME (10 BIT TIMES). ; ; ; ; ; AUDF+7 BAUD RATE VCOUNT INTERVAL ; ------ ----------- ---------------- ; .WORD $27C ;1407 56 ; .WORD $2D7 ;1231 64 ; .WORD $332 ;1094 72 ; .WORD $38D ;985 80 POKTAB: .WORD $3E8 ;895 88 .WORD $443 ;820 96 .WORD $49E ;757 104 .WORD $4F9 ;703 112 .WORD $554 ;656 120 .WORD $5AF ;615 128 .WORD $60A ;579 136 .WORD $665 ;547 144 .WORD $6C0 ;518 152 .WORD $71A ;492 160 .WORD $775 ;469 168 .WORD $7D0 ;447 176 ; .WORD $828 ;428 184 ; .WORD $886 ;410 192 ; .WORD $8E1 ;394 200 ; .WORD $93C ;379 208 ; .WORD $997 ;365 216 ; .WORD $9F2 ;352 224 ; .WORD $A4D ;339 232 ; .WORD $AA8 ;328 240 ; .WORD $803 ;318 248 ; ; ; ; ; CRNTP3 =* *=$14 SIOSPR: .BYTE DSKORG-CRNTP3 ;^GSIOL IS TOO LONG ; .TITLE 'DISK ***** DISKP.SRC ***** 3/9/79 ***** 4:00:00 P.M.' ; ; ; ; ; ; STATVH = DVSTAT/256 STATVL = (-256)*STATVH+DVSTAT ;STATUS POINTER ; ; ; ; ; CONSTANT EQUATES ; DISKID = $31 ;SERIAL BUS DISK I.D. PUTSEC = $50 ;DISK PUT SECTOR DCB COMMAND ; READ = $52 ;DISK GET SECTOR DCB COMMAND ; WRITE = $57 ;DISK PUT SECTOR WITH READ CHECK DCB COMMAND STATC = $53 ;DISK STATUS DCB COMMAND FOMAT = $21 ;DISK FORMAT DCB COMMAND !!!!! ***** NODAT = 0 ;SIO COMMAND FOR "NO DATA" OPERATION GETDAT = $40 ;SIO COMMAND FOR "DATA FROM DEVICE" PUTDAT = $80 ;SIO COMMAND FOR "DATA TO DEVICE" ; ; ; VECTORS ; *=$E450 ; JMP DINIT ;DISK INIT. VECTOR JMP DSKIF ;DISK INTERFACE ENTRY POINT ; ; ; ; ; ; ; CONSTANTS ; *=DSKORG ; ; ; ; ; ; ; ; ; ;*********************************************************************** ; DISK INTERFACE ROUTINE STARTS HERE ;*********************************************************************** ; ; ; ; ; DISK INTERFACE INITIALIZATION ROUTINE ; DINIT: LDA #160 STA DSKTIM ;SET INITIAL DISK TIMEOUT TO 160 SEC RTS ; ; ; ; DISK INTERFACE ENTRY POINT ; DSKIF: LDA #DISKID STA DDEVIC ;SET SERIAL BUS ID IN DCB LDA DSKTIM LDX DCOMND CPX #FOMAT ;IS COMMAND A FORMAT COMMAND? BEQ PUTDTO LDA #7 ;NO, SET TIMEOUT TO 7 SECS. PUTDTO: STA DTIMLO ;PUT DISK TIMEOUT IN DCB LDX #GETDAT ;SET "GET DATA" COMMAND FOR SIO LDY #$80 ;SET BYTE COUNT TO 128 LDA DCOMND ;READ COMMAND IN DCB CMP #WRITE ;IS COMMAND A "PUT SECTOR" COMMAND? BNE CKSTC LDX #PUTDAT ;YES, SET "PUT DATA" COMMAND FOR 610 CKSTC: CMP #STATC ;IS COMMAND A STATUS COMMAND? BNE PUTCNT LDA #STATVL STA DBUFLO LDA #STATVH STA DBUFHI ;SET BUFFER ADDR TO GLOBAL STATUS BUFFER LDY #4 ;YES, SET BYTE COUNT TO 4 PUTCNT: STX DSTATS ;PUT STATUS COMMAND FOR SIO IN DCB STY DBYTLO LDA #0 STA DBYTHI ;PUT BYTE COUNT IN DCB JSR SIOV ;CALL SERIAL I/O. BPL GOODST ;NO ERROR RTS ;NO, GO BACK GOODST: LDA DCOMND ;READ THE COMMAND CMP #STATC ;WAS IT A STATUS COMMAND? BNE PUTBC JSR PUTADR ;PUT BUFFER ADDR IN TEMP REQ. LDY #2 LDA (BUFADR),Y ;READ DISK TIMEOUT VALUE BYTE OF STATUS STA DSKTIM ;PUT IT IN DISK TIMEOUT REQ. PUTBC: LDA DCOMND CMP #FOMAT ;WAS COMMAND A FORMAT COMMAND? BNE ENDDIF FMTD: JSR PUTADR ;YES PUT BUFFER, ADDR INTO TEMP REC LDY #$FE ;SET BUFFER POINTER TWICE: INY INY ;INCR BUFFER POINTER BY 2 RDBAD: LDA (BUFADR),Y ;READ LO BYTE BAD SECTOR DATA CMP #$FF BNE TWICE ;IS IT "FF" ? INY ;YES, LDA (BUFADR),Y ;READ HI BYTE BAD SECTOR DATA INY CMP #$FF BNE RDBAD ;IS IT "FF" ? DEY DEY ;YES STY DBYTLO ;PUT BAD SECTOR BYTE COUNT INTO DCB LDA #0 STA DBYTHI ENDDIF: LDY DSTATS RTS ; ; ; ; ; SUBROUTINES ; ; ; PUT BUFFER ADDR FROM DCB INTO TEMP REQ ; PUTADR: LDA DBUFLO STA BUFADR LDA DBUFHI STA BUFADR+1 ;PUT BUFFER ADDR IN TEMP REQ RTS ;*********************************************************************** ; ; ; SPARE BYTE OR MODULE TOO LONG FLAG ; CRNTP4 = * ; ; DSKSPR: .BYTE PRNORG-CRNTP4 ;^GDISKP TOO LONG ; .PAGE .TITLE 'PRINTER ***** PRINTP.SRC ***** 3/9/79 ***** 4:00:00 P ; ; ; ; ; ; ; ; ; ; ; ; DEVICE NUMBER OR CODE EQUATES ; OPNOUT = $2 ;IOCB OPEN FOR OUTPUT COMMAND NBUFSZ = 40 ;PRINT NORMAL BUFFER SIZE DBUFSZ = 20 ;PRINT DOUBLE BUFFFER SIZE SBUFSZ = 29 ;PRINT SIDEWAYS BUFFER SIZE PDEVN = $40 ;PRINTER DEVICE NUMBER ; STATC = $53 ;DCB STATUS COMMAND CODE WRITEC = $57 ;DCB WRITE COMMAND SPACE = $20 ;ASCII SPACE CHAR. N = $4E ;ASCII "N" CHAR. D = $44 ;ASCII "D" CHAR. S = $53 ;ASCII "S" CHAR. ; ; ; PRINTER HANDLER ENTRY POINTS ; ; ; ; *=$E430 ; .WORD PHOPEN-1 ;PRINTER HANDLER OPEN .WORD PHCLOS-1 ;PH CLOSE .WORD BADST-1 ;PH READ .WORD PHWRIT-1 ;PH WRITE .WORD PHSTAT-1 ;PH STATUS .WORD BADST-1 ;PH SPECIAL JMP PHINIT ;PH INIT. .BYTE 0 ;ROM FILLER ; ; ; ; ; *=PRNORG ; ; ; ; ; PRINTER HANDLER INITIALIZATION ROUTINE ; PHINIT: LDA #30 STA PTIMOT ;SET UP INITIAL PRINTER TIMEOUT OF 30 SEC. RTS ; ; ; PRINTER HANDLER CONSTANTS ; PHSTLO: .WORD DVSTAT ;STATUS BUFFER POINTER PHCHLO: .WORD PRNBUF ;CHAR. BUFFER POINTER ; ; ; ; ************************ ; PRINTER HANDLER ROUTINES ; ************************ ; ; ; ; ; ; PRINTER HANDLER STATUS ROUTINE ; PHSTAT: LDA #4 STA PBUFSZ ;SET BUFFER SIZE TO 4 BYTES LDX PHSTLO LDY PHSTLO+1 ;SET POINTER TO STATUS BUFFER LDA #STATC ;SETCOMMAND TO "STATUS" STA DCOMND ;SET STATUS COMMAND STA DAUX1 JSR SETDCB ;GO SETUP DCH JSR SIOV ;SEND STATUS COMMAND BMI BADST ;GO IF ERROR JSR PHPUT ;YES, PUT STATUS INTO GLOBAL BUFFER. BADST: RTS ; ; ; ; ; PRINTER HANDLER OPEN ROUTINE ; PHOPEN: JSR PHSTAT ;DO STATUS COMMAND TO SIO LDA #0 STA PBPNT ;CLEAR PRINT BUFFER POINTER RTS ; ; ; ; ; PRINTER HANDLER WRITE ROUTINE ; PHWRIT: STA PTEMP ;SAVE ACCUM JSR PRMODE ;GO DETERMINE PRINTMODE LDX PBPNT LDA PTEMP ;GET CHAR. SENT BY CID STA PRNBUF,X ;PUT CHAR. IN PRINT BUFFER INX ;INCR. BUFFER POINTER CPX PBUFSZ ;BUFFER POINTERBUFFER SIZE? BEQ BUFFUL STX PBPNT ;SAVE SUFFER POINTER CMP #CR ;IS CHAR. = EOL ? BEQ BLFILL ;IF YES, GO DO BLANK FILL. LDY #SUCCES ;PUT GOOD STATUS IN Y REQ FOR CIO. RTS BLFILL: LDA #SPACE ;PUT BLANK IN ACCUM. FILLBF: STA PRNBUF,X ;STORE IT IN PRINT BUFFER. INX CPX PBUFSZ BNE FILLBF ;BUFFER BLANK FILLED? BUFFUL: LDA #0 STA PBPNT ;CLEAR PRINT BUFFER POINTER LDX PHCHLO LDY PHCHLO+1 ;SET POINTER TO PRINT BUFFER JSR SETDCB ;GO SETUP OCR JSR SIOV ;SEND PRINT COMMAND RTS ;YES. ; ; ; ; ; PRINTER HANDLER CLOSE ROUTINE ; PHCLOS: JSR PRMODE ;GO DETERMINE PRINT MODE LDX PBPNT BNE BLFILL LDY #SUCCES RTS ; ; ; ; ; ; ; ; ; S U B R O U T I N E S ; ; ; ; ; ; SET UP DCB TO CALL SIO ; SETDCB: STX DBUFLO STY DBUFHI ;SET BUFFER POINTER LDA #PDEVN STA DDEVIC ;SET PRINTER BUS I.D. FOR DCB LDA #1 STA DUNIT ;SET UNIT NUMBER TO 1 LDA #$80 ;DEVICE WILL EXPECT DATA LDX DCOMND CPX #STATC ;STATUS COMMAND? BNE PSIOC LDA #$40 ;EXPECT DATA FROM DEVICE PSIOC: STA DSTATS ;SET SIO MODE COMMAND LDA PBUFSZ STA DBYTLO ;SET LO BYTE COUNT LDA #0 STA DBYTHI ;SET HI BYTE COUNT LDA PTIMOT STA DTIMLO ;SET DEVICE TIMEOUT COUNT RTS ; ; ; ; ; GET DEVICE TIMEOUT FROM STATUS & SAVE IT ; PHPUT: LDA DVSTAT+2 STA PTIMOT ;SAVE DEVICE TIMEOUT RTS ; ; ; ; ; DETERMINE PRINT MODE & SETUP PRINT BUFFER SIZE, DCB PRINT ; COMMAND, &. DCB AUX1 FOR PRINT MODE ; PRMODE: LDY #WRITEC ;PUT WRITE COMMAND IN Y REG LDA ICAX2Z ;READ PRINT MODE CMODE: CMP #N BNE CDUBL ;PRINT NORMAL ? LDX #NBUFSZ ;YES, SET NORMAL CHAR. BUFFER SIZE BNE SETBSZ CDUBL: CMP #D BNE CSIDE ;PRINT DOUBLE? LDX #DBUFSZ ;YES, SET DOUBLE CHAR. BUFFER SIZE BNE SETBSZ CSIDE: CMP #S ;PRINT SIDEWAYS ? BNE GOERR ;IF NOT, GO TO ERROR ROUTINE LDX #SBUFSZ ;YES, SET SIDEWAYS BUFFER SIZE SETBSZ: STX PBUFSZ ;STORE PRINT BUFFER SIZE STY DCOMND ;STORE DCB COMMAND STA DAUX1 ;STORE DCB AUX1 PRINT MODE RTS GOERR: LDA #N ;SET DEFAULT PRINT MODE TO NORMAL BNE CMODE ;************************************************************* ; ; ; SPARE BYTE OR MODULE TOO LONG FLAG ; CRNTP5 = * ; ; ; PRNSPR: .BYTE CASORG-CRNTP5 ;^GPRINTP TOO LONG ; .PAGE .TITLE 'CASSET HANDLER 3/12 (DK1:CASCV)' CBUFH = CASBUF/256 CBUFL = (-256)*CBUFH+CASBUF SRSTA = $40 ;SIO READ STATUS SWSTA = $80 ;SIO WRITE STATUS ;MOTRGO = $34 ;MOTRST = $3C ; ; DTA = $FC ;DATA RECORD TYPE BYTE DT1 = $FA ;LAST DATA RECORD EOT = $FE ;END OF TAPE HDR = $FB ;HEADER TONE1 = 2 ;CHANGE TO RECORD MODE TONE TONE2 = 1 ;PRESS PLAY TONE ; ; ; *=CASETV .WORD OPENC-1,CLOSEC-1,GBYTE-1,PBYTE-1,STATU-1,SPECIAL-1 JMP INIT .BYTE 0 ;ROM FILLER BYTE ; ; ; ; USED IN MONITP FOR CASSETTE BOOT ; *=RBLOKV JMP RBLOK ; *=CSOPIV JMP OPINP ; ; *=CASORG ; ; ; INIT ROUTINE ; INIT: LDA #$CC STA CBAUDL LDA #$05 STA CBAUDH ;SET CASSET BAUD RATE TO 600 SPECIAL: ;THATS ALL FOLKS RTS .PAGE ; ; OPEN FUNCTION - WITH NO TIMING ADJUST ; OPENC: LDA ICAX2Z ;GET AX2 STA FTYPE ;SAVE IT FOR FUTURE REFERENCE LDA ICAX1Z AND #$0C ;IN AND OUT BITS CMP #$04 BEQ OPINP CMP #$08 ;SEE IF OPEN FOR OUTPUT BEQ OPOUT RTS ;IF ALREADY OPEN, RETURN LEAVING STATUS=$84 OPINP: LDA #0 STA WMODE ;SET READ MODE STA FEOF ;NO EOF YET SFH: LDA #TONE2 ;TONE FOR PRESS PLAY JSR BEEP ;GO BEEP BMI OPNRTN ;IF ERROR DURING BEEP LDA #MOTRGO STA PACTL ;TURN MOTOR ON .IF PALFLG LDY #$E0 LDX #1 .ENDIF .IF PALFLG-1 LDY #$40 ;5-31-79 9 SEC READ LEADER LDX #2 .ENDIF LDA #3 STA CDTMF3 JSR SETVBV ;SET UP YBLANK TIMER WAITTM: LDA CDTMF3 BNE WAITTM ;WAIT FOR MOTOR TO COME UP TO SPEED LDA #$80 ;NEXT BYTE=NO BYTES IN BUFFER STA BPTR STA BLIM JMP OPOK ;OPEN OK ; ; OPEN FOR OUTPUT ; PBRK: LDY #BRKABT ;BREAK KEY ABORT STATUS DEC BRKKEY ;RESET BREAK KEY OPNRTN: LDA #0 ;CLEAR WRITE MODE FLAG STA WMODE RTS ;AND EXIT. ; OPOUT: LDA #$80 STA WMODE ;SET WRITE MODE LDA #TONE1 ;TELL USER TO TURN ON RECORD MODE JSR BEEP BMI OPNRTN ;IF ERROR DURING BEEP LDA #$CC ;SET BAUD RATE STA AUDF3 ;WHICH SEEMS TO BE NESSECARY LDA #$05 ;FOR SOME OBSCURE REASON STA AUDF4 LDA #$60 STA DDEVIC JSR SENDEV ;TELL POKEY TO WRITE MARKS LDA #MOTRGO ;WRITE 5 SEC BLANK TAPE STA PACTL LDA #3 .IF PALFLG LDX #$3 LDY #$C0 .ENDIF .IF PALFLG-1 LDX #4 ;5/30/79 20 SEC LEADER LDY #$80 .ENDIF JSR SETVBV LDA #$FF STA CDTMF3 WDLR: LDA BRKKEY BEQ PBRK ;IF BREAK DURING WRITE LEADER LDA CDTMF3 BNE WDLR LDA #0 ;INIT BUFFER POINTER STA BPTR OPOK: LDY #SUCCES RTS .PAGE ; ; GET BYTE ; GBYTE: LDA FEOF ;IF AT EOF ALREADY BMI ISEOF ;RETURN EOF STATUS LDX BPTR ;BUFFER POINTER CPX BLIM ;IF END OF BUFFER BEQ RBLOK ;READ ANOTHER BLOCK LDA CASBUF+3,X ;GET NEXT BYTE INC BPTR ;DUMP POINTER LDY #SUCCES ;OK STATUS GBX: RTS RBLOK: LDA #'R ;READ OPCODE JSR SIOSB ;SIO ON SYS BUF TYA BMI GBX ;IF SIO ERRORS, RETURN LDA #0 STA BPTR ;RESET POINTER LDX #$80 ;DEFAULT # BYTES LDA CASBUF+2 CMP #EOT BEQ ATEOF ;IF HEADER, GO READ AGAIN CMP #DT1 ;IF LAST DATA REC BNE NLR LDX CASBUF+130 ;LAST DATA RECORD, GET # BYTES NLR: STX BLIM JMP GBYTE ;GET NEXT BYTE ATEOF: DEC FEOF ;SET FEOF ISEOF: LDY #EOFERR ;ENDFILE STATUS RTS .PAGE ; ; PUT BYTE TO BUFFER ; PBYTE: LDX BPTR ;BUFFER POINTER STA CASBUF+3,X ;STORE CHAR AWAY INC BPTR ;BUMP POINTER LDY #SUCCES ;OK STATUS CPX #127 ;IF BUFFER FULL BEQ *+3 RTS ; WRITE OUT THE BUFFER LDA #DTA ;RECORD TYPE = DATA JSR WSIOSB ;DO WRITE ON SYSTEM BUFFER LDA #0 STA BPTR ;RESET BUFFER POINTER RTS ;EXIT. .PAGE ; ; STATUS - RETURN STATUS INFO THRU DVSTAT ; STATU: LDY #SUCCES RTS .PAGE ; ; CLOSE ; CLOSEC: LDA WMODE ;SEE IF WRITING BMI CLWRT ;300 CLOSE FOR WRITE ; CLOSE FOR READ - FLAG CLOSED LDY #SUCCES ;SUCCESSFULL FCAX: LDA #MOTRST ;STOP THE MOTOR IN CASE WAS SHORT IRQ MODE STA PACTL RTS CLWRT: LDX BPTR ;BUFFER POINTER BEQ WTLR ;IF NO DATA BYTES IN BUFFER, NO DT1 REC STX CASBUF+130 ;WRITE TO LAST RECORD LDA #DT1 ;REC TYPE JSR WSIOSB ;WRITE OUT USER BUFFER BMI FCAX ;GO IF ERROR WTLR: LDX #127 ;ZERO BUFFER LDA #0 ZTBUF: STA CASBUF+3,X DEX BPL ZTBUF LDA #EOT ;WRITE EOT RECORD JSR WSIOSB JMP FCAX ;FLAG CLOSED AND EXIT .PAGE ; ; SUBROUTINES ; ; BEEP - GENERATE TONE ON KEYBOARD SPEAKER ; ON ENTRY A= FREQ ; BEEP: STA FREQ BEEP1: LDA RTCLOK+2 ;CURRENT CLOCK CLC .IF PALFLG ADC #25 .ENDIF .IF PALFLG-1 ADC #30 ; 1 SEC TONE .ENDIF TAX WFL: LDA #$FF STA CONSOL ;TURN ONSPEAKER LDA #0 LDY #$F0 DEY BNE *-1 STA CONSOL ;TURN OFF SPEAKER LDY #$F0 DEY BNE *-1 CPX RTCLOK+2 ;SEE IF 1 SEC IS UP YET BNE WFL DEC FREQ ;COUNT BEEPS BEQ WFAK ;IF ALL DONE GO WAIT FOR KEY TXA CLC .IF PALFLG ADC #8 .ENDIF .IF PALFLG-1 ADC #10 .ENDIF TAX CPX RTCLOK+2 BNE *-2 BEQ BEEP1 ;UNCOND DO BEEP AGIN WEAK: JSR WFAK1 ;USE SIMULATED "JMP (KGETCH)" TYA RTS WFAK1: LDA KEYBDV+5 PHA LDA KEYBDV+4 ;SIMULATE "JMP (KGETCH)" PHA RTS ; ; SIOBS - CALL SIO ON SYSTEM BUFFER ; SIOSB: STA DCOMND ;SAVE COMMAND LDA #0 STA DBYTHI ;SET BUFFER LENGTH LDA #131 STA DBYTLO LDA #CBUFH STA DBUFHI ;SET BUFFER ADDRESS LDA #CBUFL STA DBUFLO CSIO: LDA #$60 ;CASSET PSEUDO DEVICE STA DDEVIC LDA #0 STA DUNIT LDA #35 ;DEVICE TIMEOUT (5/30/79) STA DTIMLO LDA DCOMND ;GET COMMAND SACK LDY #SRSTA ;SIO READ STATUS COMMAND CMP #'R BEQ *+4 LDY #SWSTA ;SIC WRITE STATUS COMMAND STY DSTATS ;SET STATUS FOR SIO LDA FTYPE STA DAUX2 ;INDICATE IF SHORT IRQ MODE JSR SIOV ;GO CALL SIO RTS ; ; WSIOSB - WRITE SIC SYSTEM SUFFER ; WSIOSB: STA CASBUF+2 ;STORE TYPE BYTE LDA #$55 STA CASBUF+0 STA CASBUF+1 LDA #'W ;WRITE JSR SIOSB ;CALL SIO ON SYSTEM BUFFER RTS AND ;RETURN CRNTP6 =* *=$14 CASSPR: .BYTE MONORG-CRNTP6 ;^GCASCV IS TOO LONG ; .TITLE 'MONITOR ***** MONITP.SRC ***** 3/9/79 ***** 4:00:00 P ; ; ; ; CONSTANT EQUATES ; PUTTXT = $9 ;"PUT TEXT RECORD" CIO COMMANDCODE GETCAR = $7 ;"GET CHARACTER" CIO COMMAND CODE PUTCAR = $B ;"PUT CHARACTER" CIO COMMAND CODE INIMLL = $00 ;INITIAL HEM LO LOW BYTE INIMLH = $07 ;INITIAL HEM LO HIGH BYTE ; GOOD = $1 ;GOOD STATUS CODE ; WRITE = $57 ;WRITE COMMAND ; READ = $52 ;READ COMMAND ; STATC = $53 ;STATUS COMMAND SEX = $0 ;SCREEN EDITOR 10CR INDEX CLS = $7D ;CLEAR SCREEN CODE CTRLC = $92 ;KEYBOARD CODE FOR 'CONTROL C' EOF = $88 ;CASSETTE END OF FILE CODE LIRQ = $0 ;LONG IRQ TYPE CODE ; BUFFH = (CASBUF+3)/256 BUFFL = (-256)*BUFFH+CASBUF+3 ;BUFFER POINTER ; ; ; ; THE FOLLOWING EQUATES ARE IN THE CARTRIDGE ADDRESS SPACE. ; ; ; "B" CARTRIDGE ADDR'S ARE 8000-9FFF (36K CONFIG. ONLY) ; "A" CART. ADDR'S ARE A000-BFFF (36K CONFIG. ONLY) ; ; "A" CART. ADDR'S ARE B000-BFFF (48K CONFIG. ONLY) ; *=$BFFA CARTCS: .RES 2 ;CARTRIDGE COLD START ADDRESS. CART: .RES 1 ;CARTRIDGE AVAILABLE FLAG BYTE. CARTFG: .RES 1 ;CARTRIDGE FLAG BYTE. BIT 0=FLAG1, CARTAD: .RES 2 ;2-BYTE CARTRIDGE START VECTOR ; ; ; CARTRIDGE FLAG ACTION DEFINITIONS ; ; ; BIT ACTION IF SET ; ; 7 SPECIAL -- DON'T POWER-UP, JUST RUN CARTRIDGE ; 6-3 NONE ; 2 RUN CARTRIDGE ; 1 NONE ; 0 BOOT DOS ; ; ; ***** ; NOTE ; ***** ; ; 1.IF BIT2 IS 0, GOTO BLACKBOARD MODE. ; 2.IF BIT0 SET THE DISK WILL BE BOOTED BEFORE ANY ; OTHER ACTION. ; ; ; ; ; ; ; ; ; ; POWER-UP VECTOR ; ;*************************** ; *=$FFFC ; ; PVECT .WORD PWRUP POWER-UP VECTOR ;************************ ; ; ; ; ; ; ENTRY POINT VECTOR ; *=BLKBDV ; JMP SIGNON ;BLACK BOARD VECTOR ; *=WARMSV ; JMP RESET ;WARM START VECTOR ; *=COLDSV ; JMP PWRUP ;COLD START VECTOR (9000 FOR RAM VECTOR WRIT ; *=$9000 JSR $900C JMP PWRUP ;(TO HANDLE RAM VECTOR WRITING) JSR $900C JMP RESET ; ; ; *=MONORG ; ; ; ; ; HANDLER TABLE ENTRIES ; TBLENT: .BYTE 'P' .WORD PRINTV .BYTE 'C' .WORD CASETV .BYTE 'E' .WORD EDITRV .BYTE 'S' .WORD SCRENV .BYTE 'K' .WORD KEYBDV ; ; ;TBLLEN = IDENT-TBLENT-1 HANDLER TABLE LENGTH. "MOVED TO LINE 8 ; ; ***** PRINT MESSAGES ***** ; ; IDENT: .BYTE CLS,'ATARI COMPUTER - MEMO PAD',CR ; IDENTH = IDENT/256 IDENTL = (-256)*IDENTH+IDENT ;SYSTEM I.D. MSG POINTER ; TBLLEN = IDENT-TBLENT-1 ;HANDLER TABLE LENGTH DERR5: .BYTE 'BOOT ERROR',CR ; DERRH = DERR5/256 DERRL = (-256)*DERRH+DERR5 ;DISK ERROR MSG POINTER ; ; ; ; ; DEVICE/FILENAME SPECIFICATIONS ; OPNEDT: .BYTE 'E:',CR ;"OPEN SCREEN EDITOR" DEVICE SPEC. ; OPNH = OPNEDT/256 OPNL = (-256)*OPNH+OPNEDT ;SCREEN EDITOR OPEN POINTER ; ; ; ; ;***************************************************************** ; RESET BUTTON ROUTINE STARTS HERE ; ; RESET: SEI ;DISABLE IRQ INTERRUPTS LDA COLDST ;WERE WE IN MIDDLE OF COLDSTART? BNE PWRUP ;YES, GO TRY IT AGAIN LDA #$FF BNE PWRUP1 ;SET WARM START FLAG ; ; ; ;*************************************************************** ; POWER UP ROUTINES START HERE ;*************************************************************** ; PWRUP: SEI ;DISABLE IRQ INTERRUPTS LDA #0 ;CLEAR WARMSTART FLAG PWRUP1: STA WARMST CLD ;CLEAR DECIMAL FLAG. LDX #$FF TXS ;SET STACK POINTER JSR SPECL ;CARTRIDGE SPECIAL CASE? JSR HARDI ;DO HARDWARE INITIALIZATION LDA WARMST ;IS IT WARMSTART? BNE ZOSRAM ;YES, ONLY ZERO OS RAM ; ZERORM: LDA #0 LDY #WARMST STA RAMLO STA RAMLO+1 ;INITIALIZE RAM POINTER CLRRAM: STA (RAMLO),Y ;CLEAR MEMORY LOC. INY CPY #0 ;AT END OF PAGE? BNE CLRRAM INC RAMLO+1 ;YES. INCR PAGE POINTER LDX RAMLO+1 CPX TRAMSZ ;AT END OF MEM? BNE CLRRAM ;NO. ; ; INITIALIZE DOSVEC TO POINT TO SIGNON (BLACKBOARD) LDA BLKBDV+1 STA DOSVEC ;USE BLACKBOARD VECTOR LDA BLKBDV+2 ;FOR DOSVEC STA DOSVEC+1 LDA #$FF STA COLDST ;SET TO SHOW IN MIDDLE OF COLDSTART BNE ESTSCM ;GO AROUND ZOSRAM ; ; CLEAR OS RAM (FOR WARMSTART) ZOSRAM: LDX #0 TXA ZOSRM2: STA $200,X ;CLEAR PAGES 2 AND 3 STA $300,X DEX BNE ZOSRM2 LDX #INTZBS ZOSRM3: STA 0,X ;CLEAR ZERO PAGE LOCATIONS INTZBS-7F INX BPL ZOSRM3 ; ; ESTABLISH SCREEN MARGINS ESTSCM: LDA #LEDGE STA LMARGN LDA #REDGE STA RMARGN ; ; ; MOVE VECTOR TABLE FROM ROM TO RAM OPSYS: LDX #$25 MOVVEC: LDA VCTABL,X ;ROM TABLE STA INTABS,X ;TO RAM DEX BPL MOVVEC JSR OSRAM ;DO O.S. RAM SETUP CLI ;ENABLE IRQ INTERRUPTS ; ; ; LINK HANDLERS ; LDX #TBLLEN NXTENT: LDA TBLENT,X ;READ HANDLER TABLE ENTRY STA HATABS,X ;PUT IN TABLE DEX BPL NXTENT ;DONE WITH ALL ENTRIES? ; ; ; ; ; ; INTERROGATE CARTRIDGE ADDR. SPACE TO SEE WHICH CARTRIDGES THERE ARE ; LDX #0 STX TSTDAT ;CLEAR "B" CART. FLAG STX TRAMSZ ;CLEAR "A" CART. FLAG LDX RAMSIZ CPX #$90 ;RAM IN "B" CART. SLOT? BCS ENDBCK LDA CART-$2000 ;NO. BNE ENDBCK ;CART. PLUGGED INTO "B" SLOT'? INC TSTDAT ;YES, SET "B" CART, FLAG JSR CBINI ;INITIALIZE CARTRIDGE "B" ; ENDBCK: LDX RAMSIZ CPX #$B0 ;RAM IN "A" CART. SLOT? BCS ENDACK LDX CART ;NO, BNE ENDACK ;CART. PLUGGED INTO "A" SLOT? INC TRAMSZ ;YES, SET "A" CART. FLAG JSR CAINI ;INITIALIZE CARTRIDGE "A" ; ; ; OPEN SCREEN EDITOR ; ENDACK: LDA #3 LDX #SEX STA ICCOM,X ;OPEN I/O COMMAND LDA #OPNL STA ICBAL,X LDA #OPNH STA ICBAH,X ;SET BUFFER POINTER TO OPEN SCREEN EDITOR LDA #$C STA ICAX1,X ;SET UP OPEN FOR INPUT/OUTPUT JSR CIOV ;GO TO CIO ; BPL SCRNOK ;BR IF NO ERROR JMP PWRUP ;RETRY PWRUP IF ERROR (SHOULD NEVER HAPPEN!) SCRNOK: INX ;SCREEN OK, SO WAIT FOR YBLANK TO BNE SCRNOK ;BRING UP THE DISPLAY INY BPL SCRNOK ; ; ; DO CASSETTE BOOT JSR CSBOOT ;CHECK, BOOT, AND INIT ; ; CHECK TO SEE IF EITHER CARTRIDGE WANTS DISK BOOT LDA TRAMSZ ;CHECK BOTH CARTRIDGES ORA TSTDAT ; BEQ NOCART ;NEITHER CARTRIDGE LIVES LDA TRAMSZ ;"A" CART? BEQ NOA1 ;NO LDA CARTFG ;GET CARTRIDGE MODE FLAG NOA1: LDX TSTDAT ;"B" CART? BEQ NOB1 ;NO ORA CARTFG-$2000 ;ADD OTHER FLAG NOB1: AND #1 ;DOES EITHER CART WANT BOOT? BEQ NOBOOT ;NO ; ; DO DISK BOOT NOCART: JSR BOOT ;CHECK. BOOT. AND INIT ; ; GO TO ONE OF THE CARTRIDGES IF THEY SO DESIRE NOBOOT: LDA #0 STA COLDST ;RESET TO SHOW DONE WITH COLDSTART LDA TRAMSZ ;"A" CART? BEQ NOA2 ;NO LDA CARTFG ;GET CARTRIDGE MODE FLAG AND #4 ;DOES IT WANT TO RUN? BEQ NOA2 ;NO JMP (CARTCS) ;RUN "A" CARTRIDGE NOA2: LDA TSTDAT ;"B" CART? BEQ NOCAR2 ;NO LDA CARTFG-$2000 ;GET "B" MODE FLAG AND #4 ;DOES IT WANT TO RUN? BEQ NOCART ;NO JMP (CARTCS-$2000) ;RUN "B" CARTRIDGE ; ; NO CARTRIDGES, OR NEITHER WANTS TO RUNS ; SO GO TO DOSVEC (DOS, CASSETTE, OR BLACKBOARD) NOCAR2: JMP (DOSVEC) ; ; PRINT SIGN-ON MESSAGE SIGNON: LDX #IDENTL LDY #IDENTH JSR PUTLIN ;GO PUT SIGN-ON MSG ON SCREEN ; ; ; ; BLACKBOARD ROUTINE BLACKB: JSR BLKB2 ;"JSR EGETCH" JMP BLACKB ;FOREVER BLKB2: LDA EDITRV+5 ;HIGH BYTE PHA LDA EDITRV+4 ;LOW BYTE PHA RTS ;SIMULATES "JMP (EDITRV)" ; ; ; CARTRIDGE INITIALIZATION INDIRECT JUMPS CAINI: JMP (CARTAD) CBINI: JMP (CARTAD-$2000) .PAGE ; ; ; ; ; ; ; S U B R O U T I N E S ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; CHECK FOR HOW MUCH RAM & SPECIAL CARTRIDGE CASE. ; IF SPECIAL CARTRIDGE CASE, DON'T GO BACK -- GO TO CART. ; SPECL: LDA CART ;CHECK FOR RAM OR CART BNE ENSPE2 ;GO IF NOTHING OR MAYBE RAM INC CART ;NOW DO RAM CHECK LDA CART ;IS IT ROM? BNE ENSPEC ;NO LDA CARTFG ;YES, BPL ENSPEC ;BIT SET? JMP (CARTAD) ;YES, GO RUN CARTRIDGE ; ; CHECK FOR AMOUNT OF RAM ; ; ENSPEC: DEC CART ;RESTORE RAM IF NEEDED ENSPE2: LDY #0 STY RAMLO+1 LDA #$10 STA TRAMSZ ;SET RAM POINTER TO 4K. HOWMCH: LDA (RAMLO+1),Y ;READ RAM LOCATION EOR #$FF ;INVERT IT. STA (RAMLO+1),Y ;WRITE INVERTED DATA. CMP (RAMLO+1),Y ;READ RAM AGAIN BNE ENDRAM EOR #$FF ;CONVERT IT BACK STA (RAMLO+1),Y ;RESTORE ORIGINAL RAMDATA LDA TRAMSZ CLC ADC #$10 STA TRAMSZ ;INCR. RAM POINTER BY 4K. BNE HOWMCH ;GO FIND HOW MUCH RAM. ENDRAM: RTS ; ; ; ; HARDWARE INITIALIZATION ; ; HARDI: LDA #0 TAX CLRCHP: STA $D000,X STA $D400,X STA $D200,X STA $D300,X INX BNE CLRCHP RTS ; ; ; O.S. RAM SETUP ; OSRAM: DEC BRKKEY ;TURN OFF BREAK KEY FLAG LDA #.LOW.BRKKY2 STA BRKKY LDA #.HIGH.BRKKY2 STA BRKKY+1 LDA TRAMSZ ;READ RAM SIZE IN TEMP. REG. STA RAMSIZ ;SAVE IT IN RAM SIZE. STA MEMTOP+1 ;INIT. MEMTOP ADDR HI BYTE LDA #0 STA MEMTOP ;INIT. MEMTOP ADDR LO BYTE LDA #INIMLL STA MEMLO LDA #INIMLH STA MEMLO+1 ;INITIALIZE MEMLO ADDR VECTOR JSR EDITRV+$C ;EDITOR INIT. JSR SCRENV+$C ;SCREEN INIT. JSR KEYBDV+$C ;KEYBOARD INIT. JSR PRINTV+$C ;PRINTER HANDLER INIT JSR CASETV+$C ;CASSETTE HANDLER INIT JSR CIOINV ;CIO INIT. JSR SIOINV ;SIO INIT. JSR INTINV ;INTERRUPT HANDLER INIT. LDA CONSOL AND #$1 BNE NOKEY ;GAME START KEY DEPRESSED? INC CKEY ;YES. SET KEY FLAG. NOKEY: RTS ; ; ; DO BOOT OF DISK ; BOOT: LDA WARMST BEQ NOWARM ;WARMSTART? LDA BOOT? ;YES, AND #1 BEQ NOINIT ;VALID BOOT? JSR DINI ;YES, RE-INIT. DOS SOFTWARE NOINIT: RTS NOWARM: LDA #1 STA DUNIT ;ASSIGN DISK DRIVE NO. LDA #STATC STA DCOMND ;SET UPSTATUS COMMAND JSR DSKINV ;GO DO DISK STATUS BPL DOBOOT ;IS STATUS FROM 510 GOOD? RTS ;NO, GO BACK WITH BAD BOOT STATUS ; DOBOOT: LDA #0 STA DAUX2 LDA #1 STA DAUX1 ;SET SECTOR # TO 1. LDA #BUFFL STA DBUFLO LDA #BUFFH STA DBUFHI ;SET UP BUFFER ADDR SECT1: JSR GETSEC ;GET SECTOR BPL ALLSEC ;STATUS O.K.? BADDSK: JSR DSKRDE ;NO, GO PRINT DISK READ ERROR LDA CASSBT BEQ DOBOOT ;CASSETTE BOOT? RTS ;YES, QUIT ALLSEC: LDX #3 RDBYTE: LDA CASBUF+3,X ;READ A BUFFER BYTE STA DFLAGS,X ;STORE IT DEX BPL RDBYTE ;DONE WITH 4 BYTE TRANSFER LDA BOOTAD ;YES. STA RAMLO LDA BOOTAD+1 STA RAMLO+1 ;PUT BOOT ADDR INTO Z. PAGE RAM LDA CASBUF+7 STA DOSINI ;ESTABLISH DOS INIT ADDRESS LDA CASBUF+8 STA DOSINI+1 MVBUFF: LDY #$7F ;YES, SET BYTE COUNT MVNXB: LDA CASBUF+3,Y STA (RAMLO),Y ;MOVE A BYTE FROM SECTOR BUFFER TO BOOT ADDR DEY BPL MVNXB ;DONE ? CLC ;YES, LDA RAMLO ADC #$80 STA RAMLO LDA RAMLO+1 ADC #0 STA RAMLO+1 ;INCR BOOT LOADER BUFFER POINTER DEC DBSECT ;DECR # OF SECTORS. BEQ ENBOOT ;MORE SECTORS ? INC DAUX1 ;YES INCR SECTOR # SECTX: JSR GETSEC ;GO GET SECTOR. BPL MVBUFF ;STATUS O.K. ? JSR DSKRDE ;NO, GO PRINT DISK READ ERROR LDA CASSBT BNE BADDSK ;IF CASSETTE, QUIT. BEQ SECTX ;IF DISK, TRY SECTOR AGAIN. ENBOOT: LDA CASSBT BEQ XBOOT ;A CASSETTE BOOT ? JSR GETSEC ;YES, GET EOF RECORD, BUT DON'T USE IT. XBOOT: JSR BLOAD ;GO EXECUVE BOOT LOADER BCS BADDSK ;IF BAD BOOT, DO IT OVER AGAIN JSR DINI ;GO INIT. SOFTWARE INC BOOT? ;SHOW BOOT SUCCESS RTS BLOAD: CLC LDA BOOTAD ADC #6 STA RAMLO LDA BOOTAD+1 ADC #0 STA RAMLO+1 ;PUT START ADDR OF BOOTLOADER INTO RAM JMP (RAMLO) DINI: JMP (DOSINI) ; ; ; ; ; DISPLAY DISK READ ERROR MSG ; DSKRDE: LDX #DERRL LDY #DERRH ; ; ; ; PUT LINE ON SCREEN AT PRESENT CURSOR POSITION ; ; X-REG -- LO BYTE, BEGIN ADDR OF LINE ; Y-REG -- HI BYTE, BEGIN ADDR OF LINE ; PUTLIN: TXA LDX #SEX STA ICBAL,X TYA STA ICBAH,X ;SET UP ADDR OF BEGIN OF LINE LDA #PUTTXT STA ICCOM,X ;"PUT TEXT RECORD" COMMAND LDA #$FF STA ICBLL,X ;SET BUFFER LENGTH JSR CIOV ;PUT LINE ON SCREEN RTS ; ; ; ; ; GET SECTOR FROM DISK 0 ; GETSEC: LDA CASSBT BEQ DISKM ;CASSETTE BOOT? JMP RBLOKV ;YES, GO TO READ BLOCK ROUTINE DISKM: LDA #READ STA DCOMND ;SET READ SECTOR COMMAND LDA #1 STA DUNIT ;SET DRIVE NO. TO DRIVE 0 JSR DSKINV ;GET SECTOR RTS ; ; ; ; DO CHECK FOR CASSETTE BOOT & IF SO DO BOOT ; CSBOOT: LDA WARMST ;WARMSTART? BEQ CSBOT2 ;NO LDA BOOT? ;GET BOOT FLAG AND #2 ;WAS CASSETTE BOOT SUCCESFULL? BEQ NOCSB2 ;NO JSR CINI ;YES, INIT CASSETTE SOFTWARE NOCSB2: RTS ; CSBOT2: LDA CKEY BEQ NOCSBT ;"C" KEY FLAG SET ? LDA #$80 ;YES, STA FTYPE ;SET LONG IRQ TYPE INC CASSBT ;SET CASSETTE BOOT FLAG JSR CSOPIV ;OPEN CASSETTE FOR INPUT JSR SECT1 ;DO BOOT & INIT. LDA #0 STA CASSBT ;RESET CASSETTE BOOT FLAG STA CKEY ;CLEAR KEY FLAG ASL BOOT? ;SHIFT BOOT FLAG (NOW=2 IF SUCCESS) LDA DOSINI STA CASINI ;MOVE INIT ADDRESS FOR CASSETTE LDA DOSINI+1 STA CASINI+1 NOCSBT: RTS ; CINI: JMP (CASINI) ;INIT CASSETTE ;**************************************************************** ; ; ; SPARE BYTE OR MODULE TOO LONG FLAG ; CRNTP7 =* ; *=$14 MONSPR: .BYTE KBDORG-CRNTP7 ;^GMONITP TOO LONG ; .PAGE .TITLE 'DISPLAY HANDLER -- 10-30-78 -- DISPLC' ; ; HANDLER DEPENDENT EQUATES ; CLRCOD = $7D ;CLEAR SCREEN ATASCI CODE CNTL1 = $9F ;POKEY KEY CODE FOR ^1 ; FRMADR = SAVADR TOADR = MLTTMP ; .PAGE ; ; *=EDITRV ; ; SCREEN EDITOR HANDLER ENTRY POINT ; EDITOR: .WORD EOPEN-1 .WORD RETUR1-1 ;(CLOSE) .WORD EGETCH-1 .WORD EOUTCH-1 .WORD RETUR1-1 ;(STATUS) .WORD NOFUNC-1 ;(SPECIAL) JMP PWRONA .BYTE 0 ;ROM FILLER BYTE ; *=SCRENV ; ; DISPLAY HANDLER ENTRY POINT ; DISPLA: .WORD DOPEN-1 .WORD RETUR1-1 ;(CLOSE) .WORD GETCH-1 .WORD OUTCH-1 .WORD RETUR1-1 ;(STATUS) .WORD DRAW-1 ;(SPECIAL) JMP PWRONA .BYTE 0 ;ROM FILLER BYTE ; ; ; ; ; KEYBOARD HANDLER ENTRY POINT ; KBDHND: .WORD RETUR1-1 .WORD RETUR1-1 ;(CLOSE) .WORD KGETCH-1 .WORD NOFUNC-1 ;(OUTCH) .WORD RETUR1-1 ;(STATUS) .WORD NOFUNC-1 ;(SPECIAL) JMP PWRONA .BYTE 0 ;ROM FILLER BYTE ; ; ; INTERRUPT VECTOR TABLE ENTRY *=VCTABL-INTABS+VKEYBD .WORD PIRQ5 ;KEYBOARD IRQ INTERRUPT VECTOR ; *=KBDORG ; PWRONA: LDA #$FF STA CH LDA MEMTOP+1 AND #$F0 ;INSURE 4K PAGE BOUNDARY STA RAMTOP LDA #$40 ;DEFAULT TO UPPER CASE ALPHA AT PWRON STA SHFLOK RTS ;POWER ON COMPLETED .PAGE ; ; ; BEGIN DISPLAY HANDLER OPEN PROCESSING ; DOPEN: LDA ICAX2Z ;GET AUX 2 BYTE AND #$F BNE OPNCOM ;IF MODE ZERO, CLEAR ICAX1Z EOPEN: LDA ICAX1Z ;CLEAR "CLR INHIBIT" AND "MXD MODE" BITS AND #$F STA ICAX1Z LDA #0 OPNCOM: STA DINDEX LDA #$E0 ;INITIALIZE GLOBAL VBLANK RAM STA CHBAS LDA #2 STA CHACT STA SDMCTL ;TURN OFF DMA NEXT VBLANK LDA #SUCCES STA DSTAT ;CLEAR STATUS LDA #$C0 ;DO IRQEN ORA POKMSK STA POKMSK STA IRQEN LDA #0 STA TINDEX ;TEXT INDEX MUST ALWAYS BE 0 STA ADRESS STA SWPFLG STA CRSINH ;TURN CURSOR ON ATOPEN LDY #14 ;CLEAR TAB STOPS LDA #1 ;INIT TAB STOPS TO EVERY 8 CHARACTERS CLRTBS: STA TABMAP,Y DEY BPL CLRTBS LDX #4 ;LOAD COLOR REGISTERS DOPEN8: LDA COLRTB,X STA COLOR0,X DEX BPL DOPEN8 LDY RAMTOP ;DO TXTMSC=$2C40 (IF MEMTOP=3000) DEY STY TXTMSC+1 LDA #$60 STA TXTMSC LDX DINDEX LDA ANCONV,X ;CONVERT IT TO ANTIC CODE BNE DOPENA ;IF ZERO, IT IS ILLEGAL OPNERR: LDA #BADMOD ;SET ERROR STATUS STA DSTAT DOPENA: STA HOLD1 LDA RAMTOP ;SET UP AN INDIRECT POINTER STA ADRESS+1 LDY ALOCAT,X ;ALLOCATE N BLOCKS OF 40 BYTES DOPEN1: LDA #40 JSR DBSUB DEY BNE DOPEN1 LDA GPRIOR ;ICLEAR GTIA MODES AND #$3F STA OPNTMP+1 TAY CPX #8 ;TEST IF 320X1 BCC NOT8 TXA ;GET 2 LOW BITS ROR A ROR A ROR A AND #$C0 ;NOW 2 TOP BITS ORA OPNTMP+1 TAY LDA #16 ;SUBTRACT 16 MORE FOR PAGE BOUNDARY JSR DBSUB CPX #11 ;TEST MODE 11 BNE NOT8 ;IF MODE = 11 LDA #6 ;PUT GTIA LUM VALUE INTO BACKGROUND REGISTER STA COLOR4 NOT8: STY GPRIOR ;STORE NEW PRIORITY LDA ADRESS ;SAVE MEMORY SCAN COUNTER ADDRESS STA SAVMSC LDA ADRESS+1 STA SAVMSC+1 VBWAIT: LDA VCOUNT ;WAIT FOR NEXT VBLANK BEFORE MESSING CMP #$7A ;WITH THE DISPLAY LIST BNE VBWAIT JSR DBDEC ;START PUTTING DISPLAY LIST RIGHT UNDER RAM LDA PAGETB,X ;TEST IF DISPLAY LIST WILL BE IN TROUBLE BEQ NOMOD ;OF CROSSING A 256 BYTE PAGE BOUNDARY LDA #$FF ;IF SO, DROP DOWN A PAGE STA ADRESS DEC ADRESS+1 NOMOD: LDA ADRESS ;SAVE END OF DISPLAY LIST FOR LATER STA SAVADR LDA ADRESS+1 STA SAVADR+1 JSR DBDDEC ;(DOUBLE BYTE DOUBLE DECREMENT) LDA #$41 ;(ANTIC) WAIT FOR VBLANK AND JMP TO TOP JSR STORE STX OPNTMP LDA #24 ;INITIALIZE BOTSCR STA BOTSCR LDA DINDEX ;DISALLOW MIXED MODE IF MODE.GE.9 CMP #9 BCS NOTMXD LDA ICAX1Z ;TEST MIXED MODE AND #$10 BEQ NOTMXD LDA #4 STA BOTSCR LDX #2 ;ADD 4 LINES OF TEXT AT BOTTOM OF SCREEN DOPEN2: LDA #2 JSR STORE DEX BPL DOPEN2 LDY RAMTOP ;RELOAD MSC FOR TEXT DEY TYA JSR STORE LDA #$60 JSR STORE LDA #$42 JSR STORE CLC LDA #MXDMDE-NUMDLE ;POINT X AT MIXED MODE TABLE ADC OPNTMP STA OPNTMP NOTMXD: LDY OPNTMP LDX NUMDLE,Y ;GET NUMBER OF DISPLAY LIST ENTRIES DOPEN3: LDA HOLD1 ;STORE N DLE'S JSR STORE DEX BNE DOPEN3 LDA DINDEX ;DO THE MESSY 320X1 PROBLEM CMP #8 BCC DOPEN5 LDX #93 ;GET REMAINING NUMBER OF DLE'S LDA RAMTOP ;RELOAD MEMORY SCAN COUNTER SEC SBC #$10 JSR STORE LDA #0 JSR STORE LDA #$4F ;(ANTIC) RELOAD MSC CODE JSR STORE DOPEN4: LDA HOLD1 ;DO REMAINING DLE'S JSR STORE DEX BNE DOPEN4 DOPEN5: LDA SAVMSC+1 ;POLISH OFF DISPLAY LIST JSR STORE LDA SAVMSC JSR STORE LDA HOLD1 ORA #$40 JSR STORE LDA #$70 ;24 BLANK LINES JSR STORE LDA #$70 JSR STORE LDA ADRESS ;SAVE DISPLAY LIST ADDRESS STA SDLSTL LDA ADRESS+1 STA SDLSTL+1 LDA #$70 ;ADD LAST BLANK LINE ENTRY JSR STORE ;POSITION ADRESS=SDLSTL-1 LDA ADRESS ;STORE NEW MEMTOP STA MEMTOP LDA ADRESS+1 STA MEMTOP+1 LDA SAVADR STA ADRESS LDA SAVADR+1 STA ADRESS+1 LDA SDLSTL+1 JSR STORE LDA SDLSTL JSR STORE LDA DSTAT ;IF ERROR OCURRED ON ALLOCATION, OPEN THE ED BPL DOPEN9 PHA ;SAVE STATUS JSR EOPEN ;OPEN THE EDITOR PLA ;RESTORE STATUS TAY ;AND RETURN IT TO CIO RTS DOPEN9: LDA ICAX1Z ;TEST CLEAR INHIBIT BIT AND #$20 BNE DOPEN7 JSR CLRSCR ;CLEAR SCREEN STA TXTROW ;AND HOME TEXT CURSOR (AC IS ZERO) LDA LMARGN STA TXTCOL DOPEN7: LDA #$22 ;EVERYTHING ELSE IS SET UP ORA SDMCTL ;SO TURN ON DMACTL STA SDMCTL JMP RETUR2 ; ; GETCH: JSR RANGE ;GETCH DOES INCRSR. GETPLT DOESN'T JSR GETPLT JSR INATAC ;CONVERT INTERNAL CODE TO ATASCII JSR INCRSB JMP RETUR1 GETPLT: JSR CONVRT ;CONVERT ROW/COLUMN TO ADRESS LDA (ADRESS),Y AND DMASK SHIFTD: LSR SHFAMT ;SHIFT DATA DOWN TO LOW BITS BCS SHIFT1 LSR A BPL SHIFTD ;(UNCONDITIONAL) SHIFT1: STA CHAR CMP #0 ;RESTORE FLAGS ALSO RTS ; ; ; OUTCH: STA ATACHR JSR RANGE ; JSR OFFCRS OUTCHA: LDA ATACHR ;TEST FOR CLEAR SCREEN CMP #CLRCOD BNE OUTCHE JSR CLRSCR JMP RETUR2 OUTCHE: LDA ATACHR ;TEST FOR CARRIAGE RETURN CMP #CR BNE OUTCHB JSR DOCRWS ;DO CR JMP RETUR2 OUTCHB: JSR OUTPLT JSR INCRSR JMP RETUR2 ; ; OUTPLT: LDA SSFLAG ;*****LOOP HERE IF START/STOP FLAG ISNON-0 BNE OUTPLT LDX #2 CRLOOP: LDA ROWCRS,X ;SAVE CURSOR LOCATION FOR DRAW LINE TO DRAW STA OLDROW,X DEX BPL CRLOOP LDA ATACHR ;CONVERT ATASCII(ATACHR) TO INTERNAL(CHAR) TAY ;SAVE ATACHR ROL A ROL A ROL A ROL A AND #3 TAX ;X HAS INDEX INTO ATAINT TYA ;RESTORE ATACHR AND #$9F ;STRIP OFF COLUMN ADDRESS ORA ATAINT,X ;OR IN NEW COLUMN ADDRESS OUTCH2: STA CHAR JSR CONVRT LDA CHAR SHIFTU: LSR SHFAMT ;SHIFT UP TO PROPER POSITION BCS SHIFT2 ASL A JMP SHIFTU SHIFT2: AND DMASK STA TMPCHR ;SAVE SHIFTED DATA LDA DMASK ;INVERT MASK EOR #$FF AND (ADRESS),Y ;MASK OFF OLD DATA ORA TMPCHR ;OR IN NEW DATA STA (ADRESS),Y RTS ; ; RETUR2: JSR GETPLT ;DO CURSOR ON THE WAY OUT STA OLDCHR LDX DINDEX ;GRAPHICS HAVE INVISIBLE CURSOR BNE RETUR1 LDX CRSINH ;TEST CURSOR INHIBIT BNE RETUR1 EOR #$80 ;TOGGLE MSB JSR OUTCH2 ;DISPLAY IT RETUR1: LDY DSTAT ;RETURN TO CIO WITH STATUS IN Y LDA #SUCCES STA DSTAT ;SET STATUS= SUCCESSFUL COMPLETION LDA ATACHR ;PUT ATACHR IN AC FOR RETURN TO CIO NOFUNC: RTS ;(NON-EXISTENT FUNCTION RETURN POINT) ; ; ; ; END OF DISPLAY HANDLER ; .PAGE ; ; ; ; EGETCH: JSR SWAP JSR ERANGE LDA BUFCNT ;ANYTHING IN THE BUFFER? BNE EGETC3 ;YES LDA ROWCRS ;NO, SO SAVE BUFFER START ADDRESS STA BUFSTR LDA COLCRS STA BUFSTR+1 EGETC1: JSR KGETCH ;LET'S FILL OUR BUFFER STY DSTAT ;SAVE KEYBOARD STATUS LDA ATACHR ;TEST FOR CR CMP #CR BEQ EGETC2 JSR DOSS ;NO, GO PRINT IT JSR SWAP ;JSR DOSS DID SWAP SO SWAP BACK LDA LOGCOL ;BEEP IF NEARING LOGICAL COL 120 CMP #113 BNE EGETC6 JSR BELL EGETC6: JMP EGETC1 EGETC2: JSR OFFCRS ;GET BUFFER COUNT JSR DOBUFC LDA BUFSTR ;RETURN A CHARACTER STA ROWCRS LDA BUFSTR+1 STA COLCRS EGETC3: LDA BUFCNT BEQ EGETC5 EGETC7: DEC BUFCNT ;AND RETURN TILL BUFCNT=0 BEQ EGETC5 LDA DSTAT ;IF ERR, LOOP ON EGETC7 UNTIL BUFR IS E1IPTIE BMI EGETC7 JSR GETCH STA ATACHR JMP SWAP ;AND RETURN WITHOUT TURNING CURSOR BACK ON EGETC5: JSR DOCRWS ;DO REAL CARRIAGE RETURN LDA #CR ;AND RETURN EOL STA ATACHR JSR RETUR2 ;TURN ON CURSOR THEN SWAP STY DSTAT ;SAVE KEYBOARD STATUS JMP SWAP ;AND RETURN THROUGH RETUR1 ; JSRIND: JMP (ADRESS) ;J5R TO THIS CAUSES JSR INDIRECT ; EOUTCH: STA ATACHR ;SAVE ATASCII VALUE JSR SWAP JSR ERANGE DOSS: JSR OFFCRS ;TURN OFF CURSOR JSR TSTCTL ;TEST FOR CONTROL CHARACTERS (Z=1 IF CTL) BEQ EOUTC5 EOUTC6: ASL ESCFLG ;ESCFLG ONLY WORKS ONCE JSR OUTCHE ERETN: JMP SWAP ;AND RETURN THROUGH RETUR1 EOUTC5: LDA DSPFLG ;DO DSPFLG AND ESCFLC ORA ESCFLG BNE EOUTC6 ;IF NON-0 DISPLAY RATHER THAN EXECUTE IT ASL ESCFLG INX ;PROCESS CONTROL CHARACTERS LDA CNTRLS,X ;GET DISPLACEMENT INTO ROUTINE STA ADRESS LDA CNTRLS+1,X ;GET HIGH BYTE STA ADRESS+1 JSR JSRIND ;DO COMPUTED JSR JSR RETUR2 ;DO CURSOR JMP SWAP ;ALL DONE SO RETURN THROUGH RETUR1 ; ; ; ; ; END SCREEN EDITOR. ; ; ; BEGIN KEYBOARD HANDLER ; ; ; ; KGETC2: LDA #$FF STA CH KGETCH: LDA ICAX1Z ;TEST LSB OF AUX1 FOR SPECIAL EDITOR READ MO LSR A BCS GETOUT LDA #BRKABT LDX BRKKEY ;TEST BREAK BEQ K7 ;IF BREAK, PUT BRKABT IN DSTAT AND CRIN ATA LDA CH CMP #$FF BEQ KGETCH STA HOLDCH ;SAVE CH FOR SHIFT LOCK PROC LDX #$FF ;"CLEAR" CH STX CH JSR CLICK ;DO KEYBOARD AUDIO FEEDBACK (A IS OK) KGETC3: TAX ;DO ASCCON CPX #$C0 ;TEST FOR CTL & SHIFT TOGETHER BCC ASCCO1 LDX #3 ;BAD CODE ASCCO1: LDA ATASCI,X STA ATACHR ;DONE CMP #$80 ;DO NULLS BEQ KGETC2 CMP #$81 ;CHECK ATARI KEY BNE KGETC1 LDA INVFLG EOR #$80 STA INVFLG JMP KGETC2 ;DONT RETURN A VALUE KGETC1: CMP #$82 ;CAPS/LOWER. BNE K1 LDA #0 ;CLEAR SHFLOK STA SHFLOK BEQ KGETC2 K1: CMP #$83 ;SHIFT CAPS/LOWER BNE K2 LDA #$40 STA SHFLOK ;SHIFT BIT BNE KGETC2 K2: CMP #$84 ;CNTL CAPS/LOWER BNE K3 LDA #$80 ;CNTL BIT STA SHFLOK BNE KGETC2 K3: CMP #$85 ;DO EOF BNE K6 LDA #EOFERR K7: STA DSTAT STA BRKKEY ;RESTORE BREAK GETOUT: LDA #CR ;PUT CR IN ATACHR BNE K8 ;(UNCONDITIONAL) K6: LDA HOLDCH ;PROCESS SHIFT LOCKS CMP #$40 ;REGULAR SHIFT AND CONTROL TAKE PRECEDENCE BCS K5 ;OVER LOCK LDA ATACHR ;TEST FOR ALPHA CMP #$61 ;LOWER CASE A BCC K5 ;NOT ALPHA IF LT CMP #$7B ;LOWER CASE Z+1 BCS K5 ;NOT ALPHA IF GE LDA SHFLOK ;DO SHIFT/CONTROL LOCK BEQ K5 ;IF NO LOCK. DONT RE-DO IT ORA HOLDCH JMP KGETC3 ;DO RETRY K5: JSR TSTCTL ;DONT INVERT M58 OF CONTROL CHARACTERS BEQ K4 LDA ATACHR EOR INVFLG K8: STA ATACHR K4: JMP RETUR1 ;ALL DONE ; ; .PAGE ; ; ;CONTROL CHARACTER PROCESSORS ; ESCAPE: LDA #$80 ;SET ESCAPE FLAG STA ESCFLG RTS CRSRUP: DEC ROWCRS BPL COMRET LDX BOTSCR ;WRAPAROUND DEX UPDNCM: STX ROWCRS COMRET: JMP STRBEG ;CULVERT ROW AND COL TO LOGCOL AND RETURN CRSRDN: INC ROWCRS LDA ROWCRS CMP BOTSCR BCC COMRET LDX #0 BEQ UPDNCM ;(UNCONDITIONAL) CRSRLF: DEC COLCRS LDA COLCRS BMI CRSRL1 ;(IF LMARGN=0, THIS ELIMINATES PROBLEM CASE) CMP LMARGN BCS COMRE1 CRSRL1: LDA RMARGN LFRTCM: STA COLCRS COMRE1: JMP DOLCOL ;COLVERT ROW AND COL TO LOGCOL AND RETURN CRSRRT: INC COLCRS LDA COLCRS CMP RMARGN BCC COMRE1 BEQ COMRE1 ;(CAUSE OLE) LDA LMARGN JMP LFRTCM ;UNCONDITIONAL TO COMMON STORE CLRSCR: JSR PUTMSC LDY #0 TYA ;PUT 0 IN THEAC CLRSC2: STA (ADRESS),Y ;(AC IS ZERO) INY BNE CLRSC2 INC ADRESS+1 LDX ADRESS+1 CPX RAMTOP BCC CLRSC2 LDA #$FF ;CLEAN UP LOGICAL LINE BITMAP CLRSC3: STA LOGMAP,Y ;(Y IS ZERO AFTER CLRSC2 LOOP) INY CPY #4 BCC CLRSC3 HOME: JSR COLCR ;PLACE COLCRS AT LEFT EDGE STA LOGCOL STA BUFSTR+1 LDA #0 STA ROWCRS STA COLCRS+1 STA BUFSTR RTS ; BS: LDA LOGCOL ;BACKSPACE CMP LMARGN BEQ BS1 BSA: LDA COLCRS ;LEFT EDGE? CMP LMARGN BNE BS3 ;NO JSR DELTIM ;YES, SEE IF LINE SHOULD BE DELETED BS3: JSR CRSRLF LDA COLCRS CMP RMARGN BNE BS2 LDA ROWCRS BEQ BS2 JSR CRSRUP BS2: LDA #$20 ;MAKE BACKSPACE DESTRUCTIVE STA ATACHR JSR OUTPLT BS1: JMP DOLCOL ;AND RETURN TAB: JSR CRSRRT ;BEGIN SEARCH LDA COLCRS ;TEST FOR NEW LINE CMP LMARGN BNE TAB1 ;NO JSR DOCR ;DO CARRIAGE RETURN JSR LOGGET ;CHECK IF END OF LOGICAL LINE BCC TAB1 ;NO, CONTINUE BCS TAB2 ;(UNCONDITIONAL) TAB1: LDA LOGCOL ;CHECK FOR TAB STOP JSR BITGET BCC TAB ;NO, SO KEEP LOOKING TAB2: JMP DOLCOL ;CULVERT ROW AND COL TO LOGCOL AND RETURN SETTAB: LDA LOGCOL JMP BITSET ;SET BIT IN MAP AND RETURN CLRTAB: LDA LOGCOL JMP BITCLR ;CLEAR " " " " " INSCHR: JSR PHACRS JSR GETPLT ;GET CHARACTER UNDER CURSOR STA INSDAT LDA #0 STA SCRFLG INSCH4: JSR OUTCH2 ;STORE DATA LDA LOGCOL ;SAVE LOGCOL: IF AFTER INCRSA LOGCOL IS PHA ;< THAN IT IS NOW, END LOOP JSR INCRSA ;SPECIAL INCRSR ENTRY POINT PLA CMP LOGCOL BCS INSCH3 ;QUIT INSCH1: LDA INSDAT ;KEEP GOING PHA JSR GETPLT STA INSDAT PLA JMP INSCH4 INSCH3: JSR PLACRS INSCH6: DEC SCRFLG BMI INSCH5 ;IF SCROLL OCCURRED DEC ROWCRS ;MOVE CURSOR UP BNE INSCH6 ;(UNCOND) CONTINUE UNTIL SCRFLG IS MINUS INSCH5: JMP DOLCOL ;CULVERT ROW AND COL TO LOGCOL AND RETURN ; ; DELCHR: JSR PHACRS DELCH1: JSR CONVRT ;GET DATA TO THE RIGHT OF THE CURSOR LDA ADRESS STA SAVADR ;SAVE ADRESS TO KNOW WHERE TO PUT DATA LDA ADRESS+1 STA SAVADR+1 LDA LOGCOL PHA JSR INCRSB ;PUT CURSOR OVER NEXT CHARACTER PLA CMP LOGCOL ;TEST NEW LOGCOL AGAINST OLD LOGCOL BCS DELCH2 ;IF OLD.GE.NEW THEN QUIT LDA ROWCRS ;IS ROW OFF SCREEN? CMP BOTSCR BCS DELCH2 ;YES, SO QUIT JSR GETPLT ;GET DATA UNDER CURSOR LDY #0 STA (SAVADR),Y ;PUT IT IN PREVIOUS POSITION BEQ DELCH1 ;AND LOOP (UNCONDITIONAL) DELCH2: LDY #0 TYA STA (SAVADR),Y ;CLEAR THE LAST POSITION JSR DELTIA ;TRY TO DELETE A LINE JSR PLACRS JMP DOLCOL ;AND RETURN INSLIN: SEC ;INSLIN PUTS "1" INTO BIT MAP INSLIA: JSR EXTEND ;ENTRY POINT FOR C=0 LDA LMARGN ;DO CARRIAGE RETURN (NO LF) STA COLCRS JSR CONVRT ;GET ADDRESS LDA ADRESS ;SET UP TO=40+FROM (FROM = CURSOR) STA FRMADR CLC ADC #40 STA TOADR LDA ADRESS+1 STA FRMADR+1 ADC #0 STA TOADR+1 LDX ROWCRS ;SET UP LOOP COUNTER CPX #23 BEQ INSLI2 INSLI1: JSR MOVLIN INX CPX #23 BNE INSLI1 INSLI2: JSR CLRLIN ;CLEAR CURRENT LINE JMP DOLCOL ;COLVERT ROW AND COL TO LOGCOL AND RETURN DELLIN: JSR DOLCOL ;GET BEGINNING OF LOG LINE (HOLD1) DELLIA: LDY HOLD1 ;SQUEEZE BIT MAP STY ROWCRS ;PUT CURSOR THERE DELLIB: LDY ROWCRS DELLI1: TYA SEC JSR LO2GET ;GET NEXT BIT PHP TYA CLC ADC #120 PLP JSR BITPUT ;WRITE IT OVER PRESENT BIT INY CPY #24 BNE DELLI1 ;LOOP LDA LOGMAP+2 ;SET LSB ORA #1 STA LOGMAP+2 DELLI2: LDA LMARGN ;DELETE LINE OF DATA USING PART OF SCROLL STA COLCRS ;CR NO LF JSR CONVRT JSR SCROL1 JSR LOGGET ;TEST NEXT LINE FOR CONTINUATION ; IS IT A NEW LOG LINE? BCC DELLIB ;NO SO DELETE ANOTHER JMP DOLCOL ;YES SO DOLCOL AND RETURN BELL: LDY #$20 BELL1: JSR CLICK DEY BPL BELL1 RTS .PAGE ; ; ; ROUTINES ; ; ; DOUBLE BYTE DECREMENT OF INDIRECT POINTER ; INCLUDING DB SUBTRACT AND DB DOUBLE DECREMENT ; DBDDEC: LDA #2 BNE DBSUB ;(UNCONDITIONAL) ; ; STORE DATA INDIRECT AND DECREMENT POINTER ; (PLACED HERE TO SAVE JMP DBDEC AFTER STORE) STORE: LDY DSTAT ;RETURN ON ERROR BMI STROK LDY #0 STOREI: STA (ADRESS),Y ; JMP DBDEC ;DECREMENT AND RETURN ; DBDEC: LDA #1 DBSUB: STA SUBTMP LDA DSTAT ;RETURN ON ERROR BMI STROK LDA ADRESS SEC SBC SUBTMP STA ADRESS BCS DBSUB1 DEC ADRESS+1 DBSUB1: LDA APPMHI+1 ;MARE SURE NOTHING EVER OVERWRITES APPMHI CMP ADRESS+1 BCC STROK ;OK BNE STRERR ;ERROR LDA APPMHI CMP ADRESS BCC STROK STRERR: LDA #SCRMEM ;SHOW MEM TOO SMALL FOR SCREEN ERROR STA DSTAT STROK: RTS ; ; ; ; CONVERT ROW/COLUMN CURSOR INTO REAL ADDRESS (FROM SAVMSC ON UP) ; CONVRT: LDA ROWCRS ;SAVE CURSOR PHA LDA COLCRS PHA LDA COLCRS+1 PHA JSR PUTMSC LDA ROWCRS ;PUT 10*ROWCRS INTO MLTTMP STA MLTTMP LDA #0 STA MLTTMP+1 LDA MLTTMP ;QUICK X8 ASL A ROL MLTTMP+1 STA HOLD1 ;(SAVE 2X VALUE) LDY MLTTMP+1 STY HOLD2 ASL A ROL MLTTMP+1 ASL A ROL MLTTMP+1 CLC ;ADD IN 2X ADC HOLD1 STA MLTTMP LDA MLTTMP+1 ADC HOLD2 STA MLTTMP+1 LDX DINDEX ;NOW SHIFT MLTTMP LEFT DHLINE TIMES TO FINIS LDY DHLINE,X ;MULTIPLY CONVR1: DEY ;LOOP N TIMES BMI CONVR2 ASL MLTTMP ROL MLTTMP+1 JMP CONVR1 CONVR2: LDY DIV2TB,X ;NOW DIVIDE HCRSR TO ACCOUNT FOR PARTIAL BYT LDA COLCRS LDX #7 ;* TRICKY * CONVR3: DEY BMI CONVR4 DEX LSR COLCRS+1 ROR A ROR TMPLBT ;SAVE LOW BITS FOR MASK JMP CONVR3 CONVR4: INY ;SO Y IS ZERO UPON RETURN FROM THIS ROUTINE CLC ADC MLTTMP ;ADD SHIFTED COLCRS TO MLTThP STA MLTTMP BCC CONVR5 INC MLTTMP+1 CONVR5: SEC ;* TRICKY * CONVR6: ROR TMPLBT ;SLIDE A "1" UP AGAINST LOW BITS (CONTINUE T CLC DEX ;AND FINISH SHIFT SO LOW BITS ARE BPL CONVR6 ;RIGHT JUSTIFIED. LDX TMPLBT ;TMPLBT IS NOW THE INDEX INTO DMASKTB LDA MLTTMP ;PREPARE FOR RETURN CLC ADC ADRESS STA ADRESS STA OLDADR ;REMEMBER THIS ADDRESS FOR CURSOR LDA MLTTMP+1 ADC ADRESS+1 STA ADRESS+1 STA OLDADR+1 LDA DMASKT,X STA DMASK STA SHFAMT PLA STA COLCRS+1 PLA STA COLCRS PLA STA ROWCRS RTS ; ; ; INCREMENT CURSOR AND DETECT BOTH END OF LINE AND END OF SCREEN ; INCRSB: LDA #0 ;NON-EXTEND ENTRY POINT BEQ INCREC INCRSR: LDA #$9B ;SPECIAL CASE ELIMINATOR INCREC: STA INSDAT INCRSA: INC LOGCOL ;(INSCHR ENTRY POINT) INC COLCRS BNE INCRS2 ;DO HIGH BYTE INC COLCRS+1 INCRS2: LDA COLCRS ;TEST END OF LINE LDX DINDEX CMP COLUMN,X ;TEST TABLED VALUE FOR ALL SCREEN MODES BEQ INC2A ;DO CR IF EQUAL CPX #0 ;MODE 0? BNE INCRS3 ;IF NOT. JUST RETURN CMP RMARGN ;TEST AGAINST RMARGN BEQ INCRS3 ;EGUAL IS OK BCS INC2A ;IF GREATER THAN, DO CR INCRS3: RTS INC2A: CPX #8 ;CHECK MODE BCC DOCR1 ;NOT 320X1 $O DO IT LDA COLCRS+1 ;TEST MED BEQ INCRS3 ;ONLY AT 64 SO DON'T DO IT DOCR1: LDA DINDEX ;DON'T MESS WITH LOGMAP IF NO MODE ZERO BNE DOCR LDA LOGCOL ;TEST LINE OVERRUN CMP #81 BCC DOCR1B ;IF LESS THAN 81 IT IS DEFINITELY NOT LINE 3 LDA INSDAT BEQ DOCR ;ONLY DO LOG LINE OVERFLOW IF INSDAT <>0 JSR DOCRWS ;LOG LINE OVERFLOW IS SPECIAL CASE JMP INCRS1 ;RETURN DOCR1B: JSR DOCR ;GET IT OVER WITH LDA ROWCRS CLC ;TEST LOGICAL LINE BIT MAP ADC #120 JSR BITGET BCC DOCR1A ;DON'T EXTEND IF OVERRUN IS INTO MIDDLE OF L LDA INSDAT ;DON'T EXTEND IF INSDAT IS ZERO BEQ DOCR1A ;(INSCHR SPECIAL CASE) CLC ;INSERT "0" INTO BIT MAP JSR INSLIA DOCR1A: JMP DOLCOL ;CONVERT ROW AND COL TO LOGCOL AND RETURN NOSCRL: LDA #0 ;DOCR WITHOUT SCROLL BEQ NOSCR1 ;(UNCONDITIONAL) DOCRWS: LDA #$9B ;DOCR WITH SCROLLING (NORMAL MODE) NOSCR1: STA INSDAT DOCR: JSR COLCR ;PLACE COLCRS AT LEFT EDGE LDA #0 STA COLCRS+1 INC ROWCRS DOCR2: LDX DINDEX LDY #24 ;SET UP SCROLL LOOP COUNTER BIT SWPFLG BPL DOCR2A ;BRANCH IF NORMAL LDY #4 TYA BNE DOCR2B ;(UNCONDITIONAL) DOCR2A: LDA NOROWS,X ;GET NO OF ROWS DOCR2B: CMP ROWCRS BNE INCRS1 STY HOLD3 TXA ;DON'T SCROLL IF MODE <> 0 BNE INCRS1 LDA INSDAT ;OR IF INSDAT = 0 BEQ INCRS1 ; LDA INSDAT IF INSDAT <> $9B THEN ROLL IN A 0 CMP #$9B ;TO EXTEND BOTTOM LOGICAL LINE SEC BEQ DOCR4B CLC DOCR4B: JSR SCROLL ;LOOP SACK TO HERE IF >1 SCROLLS INC SCRFLG DEC BUFSTR ;ROWS MOVE UP SO BUFSTR SHOULD TOO DEC HOLD3 LDA LOGMAP SEC ;FOR PARTIAL LINES ROLL IN A "1" BPL DOCR4B ;AGAIN IF PARTIAL LOGICAL LINE LDA HOLD3 ;PLACE CURSOR AT NEW LINE NEAR THE BOTTOM STA ROWCRS INCRS1: JMP DOLCOL ;COLVERT ROW AND COL TO LOGCDL AND RETURN ; ; ; SUBEND: SUBTRACT ENDPT FROM ROWAC OR COLAC. (X=0 OR 2) ; SUBEND: SEC LDA ROWAC,X SBC ENDPT STA ROWAC,X LDA ROWAC+1,X SBC ENDPT+1 STA ROWAC+1,X RTS ; ; ; RANGE: DO CURSOR RANGE TEST. IF ERROR, POP STACK TWICE AND JMP RETURN ; (ERANGE IS EDITOR ENTRY POINT AND TEST IF EDITOR IS OPEN. ; IF IT ISNT IT OPENS THE EDITOR AND CONTINUES) ; ERANGE: LDA BOTSCR ; IF BOTSCR=4 CMP #4 BEQ RANGE ;THEN IT IS IN MIXED NODE AND OK LDA DINDEX ;IF MODE = 0 BEQ RANGE ;THEN IT IS INEDITOR MODE AND OK JSR EOPEN ;IF NOT, OPEN EDITOR RANGE: LDA #39 ;***** RANGE CHECK RMARGN ***** SET UP AC CMP RMARGN ;***** RANGE CHECK RMARGN ***** COMPARE BCS RANGE3 ;***** RANGE CHECK RMARGN ***** BRANCH GE STA RMARGN ;***** RANGE CHECK RMARGN ***** BAD SO STORE RANGE3: LDX DINDEX LDA NOROWS,X ;CHECK ROWS CMP ROWCRS BCC RNGERR ;(ERROR IF TABLE.GE.ROWCRS) BEQ RNGERR CPX #8 ;CHECK FOR 320X1 BNE RANGE1 ;SPECIAL CASE IT LDA COLCRS+1 BEQ RNGOK ;IF HIGH BYTE IS 0, COL IS OK CMP #1 BNE RNGERR ;IF >1, BAD BEQ RANGE2 ;IF 1, GO CHECK LOWBYTE RANGE1: LDA COLCRS+1 ;FOR OTHERS, NON-ZERO HIGH BYTE IS BAD BNE RNGERR RANGE2: LDA COLUMN,X ;CHECK LOWBYTE CMP COLCRS BCC RNGERR BEQ RNGERR RNGOK: LDA #SUCCES ;SET STATUS OK STA DSTAT LDA #BRKABT ;PREPARE BREAK ABORT STATUS LDX BRKKEY ;CHECK BREAK KEY FLAG STA BRKKEY ;'CLEAR' BREAK BEQ RNGER2 ;IF BREAK, QUIT IMMEDIATELY AND RETURN TO CI RTS RNGERR: JSR HOME ;ON RANGE ERROR, BRING CURSOR BACK LDA #CRSROR ;SHOW CURSOR OVERRANGE ERROR RNGER2: STA DSTAT RNGER1: PLA ;RESTORE STACK (THIS ROUTINE IS ALWAYS 1 LEV PLA ;AWAY FROM RETURN TO CIO) LDA SWPFLG ;IF SWAPPED. SWAP BACK BPL RETUR3 JSR SWAPA ;AND DONT DO RETUR1 RETUR3: JMP RETUR1 ;RETURN TO CIO ; ; ; ; OFFCRS: RESTORE OLD DATA UNDER CURSOR SO IT CAN BE MOVED ; OFFCRS: LDY #0 LDA OLDCHR STA (OLDADR),Y RTS ; ; ; ; BITMAP ROUTINES: ; ; BITCON: PUT MASK IN BITMSK AND INDEX IN X ; BITPUT: PUT CARRY INTO BITMAP ; BITROL: ROL CARRY INTO BOTTOM OF BiTMAP (SCROLL) ; BITSET: SET PROPER BIT ; BITCLR: CLEAR PROPER BIT ; BITGET: RETURN CARRY SET IF BIT IS THERE ; LOGGET: DO BITGET FOR LOGMAP INSTEAD OF TABMAP ; BITCON: PHA AND #7 TAX ;GET MASK LDA MASKTB,X STA BITMSK PLA ;PROCESS INDEX LSR A LSR A LSR A TAX RTS ; ; BITROL: ROL LOGMAP+2 ROL LOGMAP+1 ROL LOGMAP RTS ; ; BITPUT: BCC BITCLR ;AND RETURN ; OTHERWISE FALL THROUGH TO BITSET AND RETURN BITSET: JSR BITCON LDA TABMAP,X ORA BITMSK STA TABMAP,X RTS ; BITCLR: JSR BITCON LDA BITMSK EOR #$FF AND TABMAP,X STA TABMAP,X RTS ; LOGGET: LDA ROWCRS LO1GET: CLC LO2GET: ADC #120 BITGET: JSR BITCON CLC LDA TABMAP,X AND BITMSK BEQ BITGE1 SEC BITGE1: RTS ; ; ; ; ; INATAC: INTERNAL(CHAR) TO ATASCII(ATACHR) CONVERSION ; INATAC: LDA CHAR LDY DINDEX ;IF GRAPHICS MODES CPY #3 BCS INATA1 ;THEN DON'T CHANGE CHAR ROL A ROL A ROL A ROL A AND #3 TAX LDA CHAR AND #$9F ORA INTATA,X INATA1: STA ATACHR RTS ; ; ; ; MOVLLN: MOVE 40 BYTES AT FRMADR TO TOADR SAVING OLD TOAOR ; DATA IN THE LINBUF. THEN MAKE NEXT FRMADR ; BE AT LINBUF FOR NEXT TRANSFER & TOADR=TOADR+40 ; MOVLIN: LDA #LINBUF/256 ;SET UP ADRESS=LINBUF$=247 STA ADRESS+1 LDA #LINBUF.AND.$FF STA ADRESS LDY #39 MOVLI1: LDA (TOADR),Y ;SAVE TO DATA STA TMPCHR LDA (FRMADR),Y ;STORE DATA STA (TOADR),Y LDA TMPCHR STA (ADRESS),Y DEY BPL MOVLI1 LDA ADRESS+1 ;SET UP FRMADR=LAST LINE STA FRMADR+1 LDA ADRESS STA FRMADR CLC ;ADD 40 TO TOADR LDA TOADR ADC #40 STA TOADR BCC MOVLI2 INC TOADR+1 MOVLI2: RTS ; ; ; ; EXTEND: EXTEND BIT MAP FROM ROWCRS (EXTEND LOGICAL LINE ; EXTEND: PHP ;SAVE CARRY LDY #23 EXTEN1: TYA JSR LO1GET PHP TYA CLC ADC #121 PLP JSR BITPUT EXTEN3: DEY BMI EXTEN4 CPY ROWCRS BCS EXTEN1 EXTEN4: LDA ROWCRS CLC ADC #120 PLP JMP BITPUT ;STORE NEW LINE'S BIT AND RETURN ; ; ; ; CLRLIN: CLEAR LINE CURSOR IS ON ; CLRLIN: LDA LMARGN STA COLCRS JSR CONVRT LDY #39 LDA #0 CLRLI1: STA (ADRESS),Y DEY BPL CLRLI1 RTS ; ; ; ; ; SCROLL: SCROLL SCREEN ; SCROLL: JSR BITROL ;ROLL IN CARRY LDA SAVMSC ;SET UP WORKING REGISTERS STA ADRESS LDA SAVMSC+1 STA ADRESS+1 SCROL1: LDY #40 ;LOOP LDA (ADRESS),Y LDX RAMTOP ;TEST FOR LAST LINE DEX CPX ADRESS+1 BNE SCROL2 LDX #$D7 CPX ADRESS BCS SCROL2 LDA #0 ;YES SO STORE ZERO DATA FOR THIS ENTIRE LINE SCROL2: LDY #0 STA (ADRESS),Y INC ADRESS BNE SCROL1 INC ADRESS+1 LDA ADRESS+1 CMP RAMTOP BNE SCROL1 JMP DOLCOL ;AND RETURN ; ; ; DOLCOL: DO LOGICAL COLUMN FROM BITMAP AND COLCRS ; DOLCOL: LDA #0 ;START WITH ZERO STA LOGCOL LDA ROWCRS STA HOLD1 DOLCO1: LDA HOLD1 ;ADD IN ROW COMPONENT JSR LO1GET BCS DOLCO2 ;FOUND BEGINNING OF LINE LDA LOGCOL ;ADD 40 AND LOOK BAC ONE CLC ADC #40 STA LOGCOL DEC HOLD1 ;UP ONE LINE JMP DOLCO1 DOLCO2: CLC ;ADD IN COLCRS LDA LOGCOL ADC COLCRS STA LOGCOL RTS ; ; ; ; DOBUFC: COMPUTE BUFFER COUNT AS THE NUMBER OF BYTES FROM ; BUFSTR TO END OF LOGICAL LINE WITH TRAILING SPACES REMOVED ; DOBUFC: JSR PHACRS LDA LOGCOL PHA LDA BUFSTR ;START STA ROWCRS LDA BUFSTR+1 STA COLCRS LDA #1 STA BUFCNT DOBUF1: LDX #23 ;NORMAL LDA SWPFLG ;IF SWAPPED, ROW 3 IS THE LAST LINE ON SCREE BPL DOB1 LDX #3 DOB1: CPX ROWCRS ;TEST IF CRSR IS AT LAST SCREEN POSITION BNE DOBU1A LDA COLCRS CMP RMARGN BNE DOBU1A INC BUFCNT ;YES, SO FAKE INCRSP TO AVOID SCROLLING JMP D0BUF2 DOBU1A: JSR INCRSB INC BUFCNT LDA LOGCOL CMP LMARGN BNE DOBUF1 ;NOT YET EOL DEC ROWCRS ;BACK UP ONE INCRSR JSR CRSRLF DOBUF2: JSR GETPLT ;TEST CURRENT COLUMN FOR NON-ZERO DATA BNE DOBUF4 ;QUIT IF NON-ZERO DEC BUFCNT ;DECREMENT COUNTER LDA LOGCOL ;BEGINNING OF LOGICAL LINE YET? CMP LMARGN BEQ DOBUF4 ;YES, SO QUIT JSR CRSRLF ;BACK UP CURSOR LDA COLCRS ;IF LOGCOL=RMARGN, GO UP 1 ROW CMP RMARGN BNE DOBUF3 DEC ROWCRS DOBUF3: LDA BUFCNT BNE DOBUF2 ;LOOP UNLESS BUFCNT JUST WENT TO ZERO DOBUF4: PLA STA LOGCOL JSR PLACRS RTS ; ; ; ; ; STRBEG: MOVE BUFSTR TO BEGINNING OF LOGICAL LINE. ; STRBEG: JSR DOLCOL ;USE DOLCOL TO POINT HOLD1 AT BOL LDA HOLD1 STA BUFSTR LDA LMARGN STA BUFSTR+1 RTS ; ; ; ; ; ; DELTIM: TIME TO DELETE A LINE IF IT IS EMPTY AND AN EXTENSION ; DELTIA: LDA LOGCOL ;IF LOGCOL<>LMARGN CMP LMARGN ;THEN DONT MOVE UP ONE BNE DELTIG ;LINE BEFORE TESTING DELTIM DEC ROWCRS DELTIG: JSR DOLCOL DELTIM: LDA LOGCOL ;TEST FOR EXTENSION CMP LMARGN BEQ DELTI3 ;NO JSR CONVRT LDA RMARGN ;SET UP COUNT SEC SBC LMARGN TAY DELTI1: LDA (ADRESS),Y BNE DELTI3 ;FOUND A NON-0 SD QUIT AND RETURN DEY BPL DELTI1 DELTI2: JMP DELLIB ;DELETE A LINE AND RETURN DELTI3: RTS ; ; ; ; TSTCTL: SEARCH CNTRLS TABLE TO SEE IF ATACHR IS A CNTL CHAR ; TSTCTL: LDX #45 ;PREPARE TO SEARCH TABLE TSTCT1: LDA CNTRLS,X CMP ATACHR BEQ TSTCT2 DEX DEX DEX BPL TSTCT1 TSTCT2: RTS ; ; ; ; PUSH ROWCRS,COLCRS AND COLCRS+1 ; PHACRS: LDX #2 PHACR1: LDA ROWCRS,X STA TMPROW,X DEX BPL PHACR1 RTS ; ; ; PULL COLCRS+1,COLCRS AND ROWCRS ; PLACRS: LDX #2 PLACR1: LDA TMPROW,X STA ROWCRS,X DEX BPL PLACR1 RTS ; ; ; ; SWAP: IF MIXED MODE, SWAP TEXT CURSORS WITH REGULAR CURSORS ; SWAP: JSR SWAPA ;THIS ENTRY POINT DOESRETUR1 JMP RETURI SWAPA: LDA BOTSCR CMP #24 BEQ SWAP3 LDX #11 SWAP1: LDA ROWCRS,X PHA LDA TXTROW,X STA ROWCRS,X PLA STA TXTROW,X DEX BPL SWAP1 LDA SWPFLG EOR #$FF STA SWPFLG SWAP3: RTS ; ; ; CLICK: MAKE CLICK THROUGH KEYBOARD SPEAKER ; CLICK: LDX #$7F CLICK1: STX CONSOL STX WSYNC DEX BPL CLICK1 RTS ; ; ; COLCR: PUTS EITHER 0 OR LMARQN INTO COLCRS BASED ON MODE AND SWPFLG ; COLCR: LDA #0 LDX SWPFLG BNE COLCR1 LDX DINDEX BNE COLCR2 COLCR1: LDA LMARGN COLCR2: STA COLCRS RTS ; ; ; PUTMSC: PUT SAVMSC INTO ADRESS ; PUTMSC: LDA SAVMSC ;SETUP ADDRESS STA ADRESS LDA SAVMSC+1 STA ADRESS+1 RTS ; .PAGE ; ; ; DRAW -- DRAW A LINE FROM OLDROW,OLDCOL TO NEWROW,NEWCOL ; (THE AL MILLER METHOD FROM BASKETBALL) DRAW: LDX #0 LDA ICCOMZ ;TEST COMMAND: $11=DRAW $12=FILL CMP #$11 BEQ DRAWA CMP #$12 ;TEST FILL BEQ DRAWB ;YES LDY #NVALID ;NO, SO RETURN INVALID COMMAND RTS DRAWB: INX DRAWA: STX FILFLG LDA ROWCRS ;PUT CURSOR INTO NEWROW,NEWCOL STA NEWROW LDA COLCRS STA NEWCOL LDA COLCRS+1 STA NEWCOL+1 LDA #1 STA ROWINC ;SET UP INITIAL DIRECTIONS STA COLINC SEC LDA NEWROW ;DETERMINE DELTA ROW SBC OLDROW STA DELTAR BCS DRAW1 ;DO DIRECTION AND ABSOLUTE VALUE LDA #$FF ;BORROW WAS ATTEMPTED STA ROWINC ;SET DIRECTION DOWN LDA DELTAR EOR #$FF ;DELTAR = |DELTAR| CLC ADC #1 STA DELTAR DRAW1: SEC LDA NEWCOL ;NOW DELTA COLUMN SBC OLDCOL STA DELTAC LDA NEWCOL+1 ;TWO-BYTE QUANTITY SBC OLDCOL+1 STA DELTAC+1 BCS DRAW2 ;DIRECTION AND ABSOLUTE VALUE LDA #$FF ;BORROW WAS ATTEMPTED STA COLINC ;SET DIRECTION = LEFT LDA DELTAC EOR #$FF ;DELTAC = |DELTAC| STA DELTAC LDA DELTAC+1 EOR #$FF STA DELTAC+1 INC DELTAC ;ADD ONE FOR TWOS COMPLEMENT BNE DRAW2 INC DELTAC+1 DRAW2: LDX #2 ;ZERO RAM FOR DRAW LOOP LDY #0 STY COLAC+1 DRAW3A: TYA STA ROWAC,X LDA OLDROW,X STA ROWCRS,X DEX BPL DRAW3A LDA DELTAC ;FIND LARGER ONE (ROW OR COL) ; STA COUNTR (PREPARE COUNTR AND ENDPT) ; STA ENDPT INX ;MAKE X 0 TAY LDA DELTAC+1 STA COUNTR+1 STA ENDPT+1 BNE DRAW3 ;AUTOMATICALLY LARGER IF MSD>0 LDA DELTAC CMP DELTAR ;LOW COL >LOW ROW? BCS DRAW3 ;YES LDA DELTAR LDX #2 TAY DRAW3: TYA ;PUT IN INITIAL CONDITIONS STA COUNTR STA ENDPT PHA ;SAVE AC LDA ENDPT+1 ;PUT LSB OF HIGH BYTE LSR A ;INTO CARRY PLA ;RESTORE AC ROR A ;ROR THE 9 BIT ACUMULATOR STA ROWAC,X DRAW4A: LDA COUNTR ;TEST ZERO ORA COUNTR+1 BNE DRAWI1 ;IF COUNTER IS ZERO, LEAVE DRAW JMP DRAW10 DRAWI1: CLC ;ADD ROW TO ROWAC (PLOT LOOP) LDA ROWAC ADC DELTAR STA ROWAC BCC DRAW5 INC ROWAC+1 DRAW5: LDA ROWAC+1 ;COMPARE ROW TO ENDPOINT CMP ENDPT+1 ;IF HIGH BYTE OF ROW IS .LT. HIGH BCC DRAW6 ;BYTE OF ENDPT, BLT TO COLUMN BNE DRAW5A LDA ROWAC CMP ENDPT ;LOW BYTE BCC DRAW6 ;ALSO TILT DRAW5A: CLC ;GE SO MOVE POINT LDA ROWCRS ADC ROWINC STA ROWCRS LDX #0 ;AND SUBTRACT ENDPT FROM ROWAC JSR SUBEND DRAW6: CLC ;DO SAME FOR COLUMN (DOUBLE BYTE ADD) LDA COLAC ;ADD ADC DELTAC STA COLAC LDA COLAC+1 ADC DELTAC+1 STA COLAC+1 CMP ENDPT+1 ;COMPARE HIGH BYTE BCC DRAW8 BNE DRAW6A LDA COLAC ;COMPARE LOW BYTE CMP ENDPT BCC DRAW8 DRAW6A: BIT COLINC ;+ OR - ? BPL DRAW6B DEC COLCRS ;DO DOUBLE BYTE DECREMENT LDA COLCRS CMP #$FF BNE DRAW7 LDA COLCRS+1 BEQ DRAW7 ;DON'T DEC IF ZERO DEC COLCRS+1 BPL DRAW7 ;(UNCONDITIONAL) DRAW6B: INC COLCRS ;DO DOUBLE BYTE INCREMENT BNE DRAW7 INC COLCRS+1 DRAW7: LDX #2 ;AND SUBTRACT ENDPT FROM COLAC JSR SUBEND DRAW8: JSR RANGE JSR OUTPLT ;PLOT POINT LDA FILFLG ;TEST RIGHT FILL BEQ DRAW9 JSR PHACRS LDA ATACHR STA HOLD4 DRAW8A: LDA ROWCRS ;SAVE ROW IN CASE OF CR PHA JSR INCRSA ;POSITION CURSOR ONE PAST DOT PLA ;RESTORE ROWCRS STA ROWCRS DRAW8C: JSR RANGE JSR GETPLT ;GET DATA BNE DRAW8B ;STOP IF NON-ZERO DATA IS ENCOUNTERED LDA FILDAT ;FILL DATA STA ATACHR JSR OUTPLT ;DRAW IT JMP DRAW8A ;LOOP DRAW8B: LDA HOLD4 STA ATACHR JSR PLACRS DRAW9: SEC ;DO DOUBLE BYTE SUBTRACT LDA COUNTR SBC #1 STA COUNTR LDA COUNTR+1 SBC #0 STA COUNTR+1 BMI DRAW10 JMP DRAW4A DRAW10: JMP RETUR1 .PAGE ; ; ; TABLES ; ; ; MEMORY ALLOCATION ; ALOCAT: .BYTE 24,16,10,10,16,28,52,100,196,196,196,196 ; ; ; NUMBER OF DISPLAY LIST ENTRIES ; NUMDLE: .BYTE 23,23,11,23,47,47,95,95,97,97,97,97 MXDMDE: .BYTE 19,19,9,19,39,39,79,79,65,65,65,65 ;(EXT OF NUMDLE) ; ; ; ANTIC CODE FROM INTERNAL MODE CONVERSION TABLE ; ; INTERNAL ANTIC CODE DESCRIPTION ; 0 2 40X2X8 CHARACTERS ; 1 6 20X5X8 "" ; 2 7 20X5X16 "" ; 3 8 40X4X8 GRAPHICS ; 4 9 80X2X4 "" ; 5 A 80X4X4 "" ; 4 B 160X2X2 "" ; 7 D 160X4X2 "" ; 8 F 320X2X1 "" ; 9 SAME AS 8 BUT GTIA 'LUM' MODE ; 10 SAME AS 8 BUT GTIA 'COL/LUM REGISTER' MODE ; 11 SAME AS 8 BUT GTIA 'COLOR' MODE ; ANCONV: .BYTE 2,6,7,8,9,$A,$B,$D,$F,$F,$F,$F ;ZEROS FOR RANGE TEST IN ; ; ; PAGE TABLE TELLS WHICH DISPLAY LISTS ARE IN DANGER OF ; CROSSING A 256 BYTE PAGE BOUNDARY ; PAGETB: .BYTE 0,0,0,0,0,0,0,1,1,1,1,1 ; ; ; THIS IS THE NUMBER OF LEFT SHIFTS NEEDED TO MULTIPLY ; COLCRS BY 10,20, OR 40. (ROWCRS*10)/(2**DHLINE) ; DHLINE: .BYTE 2,1,1,0,0,1,1,2,2,2,2,2 ; ; ; COLUMN: NUMBER OF COLUMNS ; COLUMN: .BYTE 40,20,20,40,80,80,160,160,64,80,80,80 ;MODE 8 IS SPECIAL ; ; ; ; NOROWS: NUMBER OF ROWS ; NOROWS: .BYTE 24,24,12,24,48,48,96,96,192,192,192,192 ; ; ; ; ; DIV2TB: HOW MANY RIGHT SHIFTS FOR HCRSR FOR PARTIAL BYTE MODES ; DIV2TB: .BYTE 0,0,0,2,3,2,3,2,3,1,1,1 ; ; ; DMASKT: DISPLAY MASK TABLE ; DMASKT: .BYTE $00,$FF,$F0,$0F .BYTE $C0,$30,$0C,$03 ; ; MASKTB: BIT MASK. (ALSO PART OF DMASKTB DO NOT SEPARATE) ; MASKTB: .BYTE $80,$40,$20,$10,$08,$04,$02,$01 ; ; ; ; COLRTB: .BYTE $28,$CA,$94,$46,$00 ; ; ; ; ;CNTRLS: CONTROL CODES AND THEIR DISPLACEMENTS INTO THE ; CONTROL CHARACTER PROCESSORS ; CNTRLS: .BYTE $1B .WORD ESCAPE .BYTE $1C .WORD CRSRUP .BYTE $1D .WORD CRSRDN .BYTE $1E .WORD CRSRLF .BYTE $1F .WORD CRSRRT .BYTE $7D .WORD CLRSCR .BYTE $7E .WORD BS .BYTE $7F .WORD TAB .BYTE $9B .WORD DOCRWS .BYTE $9C .WORD DELLIN .BYTE $9D .WORD INSLIN .BYTE $9E .WORD CLRTAB .BYTE $9F .WORD SETTAB .BYTE $FD .WORD BELL .BYTE $FE .WORD DELCHR .BYTE $FF .WORD INSCHR ; ; ; ; ; ; ATAINT: ATASCI TO INTERNAL TABLE ; ATAINT: .BYTE $40,$00,$20,$60 ; ; ; INTATA: INTERNAL TO ATASCI TABLE ; INTATA: .BYTE $20,$40,$00,$60 ; ; ; ATASCI: ATASCII CONVERSION TABLE ; ATASCI: .BYTE $6C,$6A,$3B,$80,$80,$6B,$2B,$2A ;LOWER CASE .BYTE $6F,$80,$70,$75,$9B,$69,$2D,$3D .BYTE $76,$80,$63,$80,$80,$62,$78,$7A .BYTE $34,$80,$33,$36,$1B,$35,$32,$31 .BYTE $2C,$20,$2E,$6E,$80,$6D,$2F,$81 .BYTE $72,$80,$65,$79,$7F,$74,$77,$71 .BYTE $39,$80,$30,$37,$7E,$38,$3C,$3E .BYTE $66,$68,$64,$80,$82,$67,$73,$61 .BYTE $4C,$4A,$3A,$80,$80,$4B,$5C,$5E ;UPPER CASE .BYTE $4F,$80,$50,$55,$9B,$49,$5F,$7C .BYTE $56,$80,$43,$80,$80,$42,$58,$5A .BYTE $24,$80,$23,$26,$1B,$25,$22,$21 .BYTE $5B,$20,$5D,$4E,$80,$4D,$3F,$81 .BYTE $52,$80,$45,$59,$9F,$54,$57,$51 .BYTE $28,$80,$29,$27,$9C,$40,$7D,$9D .BYTE $46,$48,$44,$80,$83,$47,$53,$41 .BYTE $0C,$0A,$7B,$80,$80,$0B,$1E,$1F ;CONTROL .BYTE $0F,$80,$10,$15,$9B,$09,$1C,$1D .BYTE $16,$80,$03,$80,$80,$02,$18,$1A .BYTE $80,$80,$85,$80,$1B,$80,$FD,$80 .BYTE $00,$20,$60,$0E,$80,$0D,$80,$81 .BYTE $12,$80,$05,$19,$9E,$14,$17,$11 .BYTE $80,$80,$80,$80,$FE,$80,$7D,$FF .BYTE $06,$08,$04,$80,$84,$07,$13,$01 ; ; ; ; ; PIRQ5: LDA KBCODE CMP CH1 ;TEST AGAINST LAST KEY PRESSED BNE PIRQ3 ;IF NOT, GO PROCESS KEY LDA KEYDEL ;IF KEY DELAY BYTE > 0 BNE PIRQ4 ;IGNORE KEY AS BOUNCE PIRQ3: LDA KBCODE ;RESTORE AC CMP #CNTL1 ;TEST CONTROL 1 (SSFLAG) BNE PIRQ1 LDA SSFLAG EOR #$FF STA SSFLAG BCS PIRQ4 ;(UNCONDITIONAL) MAKE ^1 INVISIBLE PIRQ1: STA CH STA CH1 LDA #3 STA KEYDEL ;INITIALIZE KEY DELAY FOR DEBOUNCE LDA #0 ;CLEAR COLOR SHIFT BYTE STA ATRACT PIRQ4: LDA #$30 STA SRTIMR PIRQ2: PLA RTI ; ; .BYTE $FF,$FF,$FF,$FF,$FF,$FF ; CRNTPC =* *=$14 KBDSPR: .BYTE $FFF8-CRNTPC ;^GDISPLC IS TOO LONG .END