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