;ALBUG.M65.71 12-Mar-82 15:25:26, Edit by HESS ; .TITLE LBUG - 6502 DEBUGGER (ATARI VERSION) ; (C) Ted Hess, Hudson, Ma. 1977,1978,1979,1980,1981,1982 ; .LIST MB ;LIST BINARY IN MACROS ; .NLIST TOC ;NO TABLE OF CONTENTS ; .ENABL LC ;ALLOW LOWER CASE TEXT ; INVOKE SYSTEM MACROS FOR PARAMETER DEFINITIONS ; .MCALL ATARI ; .MCALL M6502 ; ATARI ; ================================================================ ; VECTOR TABLE EDITRV =$E400 ;EDITOR SCRENV =$E410 ;TELEVISION SCREEN KEYBDV =$E420 ;KEYBOARD PRINTV =$E430 ;PRINTER CASETV =$E440 ;CASSETTE ; JUMP VECTOR TABLE DISKIV =$E450 ;DISK INITIALIZATION DSKINV =$E453 ;DISK INTERFACE CIOV =$E456 ;CIO ROUTINE SIOV =$E459 ;SIO ROUTINE SETVBV =$E45C ;SET VERTICAL BLANK VECTORS SYSVBV =$E45F ;SYSTEM VERTICAL BLANK ROUTINE XITVBV =$E462 ;EXIT VERTICAL BLANK ROUTINE SIOINV =$E465 ;SIO INIT SENDEV =$E468 ;SEND ENABLE ROUTINE INTINV =$E46B ;INTERRUPT HANDLER INIT CIOINV =$E46E ;CIO INIT BLKBDV =$E471 ;BLACKBOARD MODE WARMSV =$E474 ;WARM START ENTRY POINT COLDSV =$E477 ;COLD START ENTRY POINT RBLOKV =$E47D ;CASSETTE READ BLOCK VECTOR DSOPIV =$E480 ;CASSETTE OPEN FOR INPUT VECTOR ; SOME USEFUL INTERNAL ROUTINES ;KGETCH =$F6E2 ;GET CHAR FROM KEYBOARD EOUTCH =$F6A4 ;OUTPUT CHAR TO SCREEN ;PUTLIN =$F385 ;OUTPUT LINE TO IOCB#0 ; COMMAND CODES FOR IOCB OPEN =$03 ;OPEN FOR INPUT/OUTPUT GETREC =$05 ;GET RECORD (TEXT) GETCHR =$07 ;GET CHARACTER(S) PUTREC =$09 ;PUT RECORD (TEXT) PUTCHR =$0B ;PUT CHARACTER(S) CLOSE =$0C ;CLOSE DEVICE STATIS =$0D ;STATUS REQUEST SPECIL =$0E ;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 DISK LOCKFL =$23 ;LOCK FILE (READ ONLY) UNLOCK =$24 ;UNLOCK FILE ;POINT =$25 ;POINT SECTOR NOTE =$26 ;NOTE SECTOR CCIO =$28 ;CONCURRENT I/O MODE IOCFRE =$FF ;IOCB "FREE" ; AUX1 VALUES FOR OPEN APPEND =$01 ;OPEN FOR APPEND DIRECT =$02 ;OPEN FOR DIRECTORY ACCESS OPNIN =$04 ;OPEN FOR INPUT OPNOT =$08 ;OPEN FOR OUTPUT OPNINO =OPNIN!OPNOT ;OPEN FOR INPUT/OUTPUT MXDMOD =$10 ;OPEN FOR MIXED MODE INSCLR =$20 ;OPEN WITHOUT CLEARING SCREEN ; OS STATUS CODES SUCCES =$01 ;SUCCESSFUL OPERATION BRKABT =$80 ;(128) BREAK KEY ABORT PRVOPN =$81 ;(129) IOCB ALREADY OPEN NONDEV =$82 ;(130) NON-EX DEVICE WRONLY =$83 ;(131) IOCB OPENED FOR WRITE ONLY NVALID =$84 ;(132) INVALID COMMAND NOTOPN =$85 ;(133) DEVICE OR FILE NOT OPEN BADIOC =$86 ;(134) INVALID IOCB NUMBER RDONLY =$87 ;(135) IOCB OPENED FOR READ ONLY EOFERR =$88 ;(136) END OF FILE TRNRCD =$89 ;(137) TRUNCATED RECORD TIMOUT =$8A ;(138) DEVICE TIMEOUT DNACK =$8B ;(139) DEVICE DOES NOT ACK COMMAND FRMERR =$8C ;(140) SERIAL BUS FRAMING ERROR CRSROR =$8D ;(141) CURSOR OUT OF RANGE OVRRUN =$8E ;(142) SERIAL BUS DATA OVERRUN CHKERR =$8F ;(143) SERIAL BUS CHECKSUM ERROR DERROR =$90 ;(144) DEVICE ERROR (OPERATION INCOMPLETE) BADMOD =$91 ;(145) BAD SCREEN MODE NUMBER FNCNOT =$92 ;(146) FUNCTION NOT IN HANDLER SCRMEM =$93 ;(147) INSUFFICIENT MEMORY FOR SCREEN MODE ; PAGE 0 LOCATIONS LINZBS =$00 ;LINBUG STORAGE ; THESE LOCS ARE NOT CLEARED CASINI =$02 ;CASSETTE INIT LOC RAMLO =$04 ;RAM POINTER FOR MEM TEST TRAMSZ =$06 ;TEMP LOC FOR RAM SIZE TSTDAT =$07 ;RAM TEST DATA LOC ; CLEARED ON COLDSTART ONLY WARMST =$08 ;WARM START FLAG BOOTQ =$09 ;SUCCESSFUL BOOT FLAG DOSVEC =$0A ;DOS START VECTOR DOSINI =$0C ;DOS INIT ADDRESS APPMHI =$0E ;APPLICATION MEM HI LIMIT ; CLEARED ON COLD OR WARM START INTZBS =$10 ; START OF OS RAM CLEAR LOC => $7F POKMSK =$10 ;SYSTEM MASK FOR POKEY IRQ ENABLE BRKKEY =$11 ;BREAK KEY FLAG RTCLOK =$12 ;REAL TIME CLOCK (60HZ OR 16.66666 MS) BUFADR =$15 ;INDIRECT BUFFER ADDRESS REG ICCOMT =$17 ;COMMAND FOR VECTOR HANDLER DSKFMS =$18 ;DISK FILE MANAGER POINTER DSKUTL =$1A ;DISK UTILITIES POINTER PTIMOT =$1C ;PRINTER TIME OUT REGISTER PBPNT =$1D ;PRINT BUFFER POINTER PBUFSZ =$1E ;PRINT BUFFER SIZE PTEMP =$1F ;TEMP REG ZIOCB =$20 ;PAGE 0 I/O CONTROL BLOCK IOCBSZ =16 ;NUMBER OF BYTES / IOCB MAXIOC =8*IOCBSZ ;LENGTH OF IOCB AREA IOCBAS =ZIOCB ICHIDZ =$20 ;HANDLER INDEX NUMBER ($FF := IOCB FREE) ICDNOZ =$21 ;DEVICE NUMBER (DRIVE NUMBER) ICCOMZ =$22 ;COMMAND CODE ICSTAZ =$23 ;STATUS OF LAST IOCB ACTION ICBALZ =$24 ;BUFFER ADDRESS (LOW) ICBAHZ =$25 ; " " (HIGH) ICPTLZ =$26 ;PUT BYTE ROUTINE ADDRESS - 1 ICPTHZ =$27 ICBLLZ =$28 ;BUFFER LENGTH (LOW) ICBLHZ =$29 ; " " (HIGH) ICAX1Z =$2A ;AUX INFO ICAX2Z =$2B ICSPRZ =$2C ;SPARE BYTES (CIO LOCAL USE) ICIDNO =ICSPRZ+2 ;IOCB LUMBER * 16 CIOCHR =ICSPRZ+3 ;CHARACTER BYTE FOR CURRENT OPERATION STATUS =$30 ;INTERNAL STATUS STORAGE CHKSUM =$31 ;CHECKSUM (SINGLE BYTE SUM WITH CARRY) BUNRLO =$32 ;POINTER TO DATA BUFFER (LO BYTE) BUFRHI =$33 ;POINTER TO DATA BUFFER (HI BYTE) BFENLO =$34 ;NEXT BYTE PAST END OF BUFFER (LO BYTE) BNENHI =$35 ;NEXT BYTE PAST END OF BUFFER (HI BYTE) CRETRY =$36 ;NUMBER OF COMMAND FRAM RETRIES DRETRY =$37 ;NUMBER OF DEVICE RETRIES BUFRFL =$38 ;DATA BUFFER FULL FLAG RECVDN =$39 ;RECEIVE DONE FLAG XMTDON =$3A ;XMIT DONE FLAG CHKSNT =$3B ;CHECKSUM SENT FLAG NOCKSM =$3C ;NO CHECKSUM FOLLOWS DATA FLAG BPTR =$3D ;BUFFER POINTER (CASSETTE) FTYPE =$3E ;FILE TYPE (SHORT IRG/LONG IRG) FEOF =$3F ;END OF FILE FLAG (CASSETTE) FREQ =$40 ;FREQ COUNTER FOR CONSOLE SPEAKER SOUNDR =$41 ;NOISY I/O FLAG. (ZERO IS QUIET) CRITIC =$42 ;CRITICAL CODE IF NON-ZERO) FMSZPG =$43 ;DISK FILE MANAGER SYSTEM STORAGE (7 BYTES) CKEY =$4A ;SET WHEN GAME START PRESSED CASSBT =$4B ;CASSETTE BOOT FLAG DSTAT =$4C ;DISPLAY STATUS ATRACT =$4D ;ATTRACT MODE FLAG DRKMSK =$4E ;DARK ATTRACT MASK COLRSH =$4F ;ATTRACT COLOR SHIFTER (XOR'D WITH PLAYFIELD) TMPCHR =$50 ;TEMP CHAR STORAGE (DISPLAY HANDLER) HOLD1 =$51 ;TEMP STG (DISPLAY HANDLER) LMARGN =$52 ;LEFT MARGIN RMARGN =$53 ;RIGHT MARGIN ROWCRS =$54 ;CURSOR COUNTERS COLCRS =$55 DINDEX =$57 ;DISPLAY INDEX (VARIOUS QUANTS) SAVMSC =$58 OLDROW =$5A ;PREVIOUS ROW/COL OLDCOL =$5B OLDCHR =$5D ;DATA UNDER CURSOR OLDADR =$5E NEWROW =$60 ;POINT DRAWS TO HERE NEWCOL =$61 LOGCOL =$63 ;POINTS AT COLUMN IN LOGICAL LINE ADRESS =$64 ;INDIRECT POINTER MLTTMP =$66 ;MULTIPLY TEMP OPNTMP =MLTTMP ;FIRST BYTE IS USED IN OPEN AS TEMP SAVADR =$68 RAMTOP =$6A ;RAM SIZE DEFINED BY POWER ON LOGIC BUFCNT =$6B ;BUFFER COUNT BUFSTR =$6C ;EDITOR GETCH POINTER BITMSK =$6E ;BIT MASK SHFAMT =$6F ;OUTCHR SHIFT ROWAC =$70 ;USED BY "DRAW" COLAC =$72 ENDPT =$74 DELTAR =$76 DELTAC =$77 ROWINC =$79 COLINC =$7A SWPFLG =$7B ;NON-0 IF TXT AND RAM SWAPPED HOLDCH =$7C ;CH BEFORE CNTL & SHFT PROCESSING IN KGETCH INSDAT =$7D ;INSERT CHAR SAVE COUNTR =$7E ;DRAW COUNTER ;;; $80 TO $FF ARE RESERVED FOR USER APPLICATIONS ; PAGE 2 LOCATIONS INTABS =$200 ;INTERRUPT TABLE VDSLST =$200 ;DISPLAY LIST NMI VECTOR VPRCED =$202 ;PROCEED LINE IRQ VECTOR VINTER =$204 ;INTERRUPT LINE IRQ VECTOR VBREAK =$206 ;"BRK" VECTOR VKEYBD =$208 ;POKEY KEYBOARD IRQ VECTOR VSERIN =$20A ;POKEY SERIAL INPUT READY VSEROR =$20C ;POKEY SERIAL OUTPUT READY VSEROC =$20E ;POKEY SERIAL OUTPUT DONE VTIMR1 =$210 ;POKEY TIMER 1 IRQ VTIMR2 =$212 ;POKEY TIMER 2 IRQ VTIMR4 =$214 ;POKEY TIMER 4 IRQ (DO NOT USE) VIMIRQ =$216 ;IMMEDIATE IRQ VECTOR CDTMV1 =$218 ;COUNT DOWN TIMER 1 CDTMV2 =$21A ;COUNT DOWN TIMER 2 CDTMV3 =$21C ;COUNT DOWN TIMER 3 CDTMV4 =$21E ;COUNT DOWN TIMER 4 CDTMV5 =$220 ;COUNT DOWN TIMER 5 VVBLKI =$222 ;IMMEDIATE VERTICAL BLANK NMI VECTOR VVBLKD =$224 ;DEFERRED VERTICAL BLANK NMI VECTOR CDTMA1 =$226 ;COUNT DOWN TIMER 1 JSR ADDRESS CDTMA2 =$228 ;COUNT DOWN TIMER 2 JSR ADDRESS CDTMF3 =$22A ;COUNT DOWN TIMER 3 FLAG SRTIMR =$22B ;SOFTWARE REPEAT TIMER CDTMF4 =$22C ;COUNT DOWN TIMER 4 FLAG INTEMP =$22D ;IAN'S TEMP (???) CDTMF5 =$22E ;COUNT DOWN TIMER 5 FLAG SDMCTL =$22F ;SAVE DMACTL REGISTER SDLSTL =$230 ;SAVE DISPLAY LIST (LOW) SDLSTH =$231 ;SAVE DISPLAY LIST (HIGH) SSKCTL =$232 ;SKCTL REGISTER RAM LPENH =$234 ;LIGHT PEN HORIZ VALUE LPENV =$235 ;LIGHT PEN VERT VALUE ; ($236 - $239 SPARE) CDEVIC =$23A ;COMMAND FRAME BUFFER - DEVICE CCOMND =$23B ;COMMAND CAUX1 =$23C ;COMMAND AUX BYTE 1 CAUX2 =$23D ;COMMAND AUX BYTE 2 TEMP =$23E ;YES ERRFLG =$23F ;ERROR FLAG - ANY DEVICE ERROR EXCEPT TIMEOUT DFLAGS =$240 ;DISK FLAGS FROM SECTOR ONE DBSECT =$241 ;NUMBER OF DISK BOOT SECTORS BOOTAD =$242 ;ADDRESS FOR DISK BOOT LOADER COLDST =$244 ;COLDSTART FLAG (1 = DOING COLDSTART) ;($245 SPARE) DSKTIM =$246 ;DISK TIME OUT REG LINBUF =$247 ;CHAR LINE BUFFER (40 BYTES) GPRIOR =$26F ;GLOBAL PRIORITY CELL PADDL0 =$270 ;POT 0 SHADOW PADDL1 =$271 ;POT 1 SHADOW PADDL2 =$272 ;POT 2 SHADOW PADDL3 =$273 ;POT 3 SHADOW PADDL4 =$274 ;POT 4 SHADOW PADDL5 =$275 ;POT 5 SHADOW PADDL6 =$276 ;POT 6 SHADOW PADDL7 =$277 ;POT 7 SHADOW STICK0 =$278 ;JOYSTICK 0 SHADOW STICK1 =$279 ;JOYSTICK 1 SHADOW STICK2 =$27A ;JOYSTICK 2 SHADOW STICK3 =$27B ;JOYSTICK 3 SHADOW PTRIG0 =$27C ;PADDLE 0 TRIGGER PTRIG1 =$27D ;PADDLE 1 TRIGGER PTRIG2 =$27E ;PADDLE 2 TRIGGER PTRIG3 =$27F ;PADDLE 3 TRIGGER PTRIG4 =$280 ;PADDLE 4 TRIGGER PTRIG5 =$281 ;PADDLE 5 TRIGGER PTRIG6 =$282 ;PADDLE 6 TRIGGER PTRIG7 =$283 ;PADDLE 7 TRIGGER STRIG0 =$284 ;JOYSTICK 0 TRIGGER STRIG1 =$285 ;JOYSTICK 1 TRIGGER STRIG2 =$286 ;JOYSTICK 2 TRIGGER STRIG3 =$287 ;JOYSTICK 3 TRIGGER CSTAT =$288 ;(UNUSED) WMODE =$289 ;R/W FLAG FOR CASSETTE BLIM =$28A ;BUFFER LIMIT (CASSETTE) ;($28B - $28F SPARE) TXTROW =$290 ;TEXT ROWCRS TXTCOL =$291 ;TEXT ROWCOL TINDEX =$293 ;TEXT INDEX TXTMSC =$294 ;FOOLS CONVRT INTO NEW MSC TXTOLD =$296 ;OLDROW & OLDCOL FOR TEXT (AND THEN SOME) TMPX1 =$29C HOLD3 =$29D SUBTMP =$29E HOLD2 =$29F DMASK =$2A0 TMPLBT =$2A1 ESCFLG =$2A2 ;ESCAPE FLAG TABMAP =$2A3 ;TAB BUFFER LOGMAP =$2B2 ;LOGICAL LINE START BIT MAP INVFLG =$2B6 ;INVERSE VIDEO FLAG (ATARI KEY) FILFLG =$2B7 ;RIGHT FILL FLAG FOR DRAW TMPROW =$2B8 TMPCOL =$2B9 SCRFLG =$2BB ;SET IF SCROLL OCCURS HOLD4 =$2BC ;MORE DRAW TEMPS HOLD5 =$2BD SHFLOK =$2BE ;SHIFT LOCK KEY BOTSCR =$2BF ;BOTTOM OF SCREEN (24 NORM, 4 SPLIT) PCOLR0 =$2C0 ;P0 COLOR PCOLR1 =$2C1 ;P1 COLOR PCOLR2 =$2C2 ;P2 COLOR PCOLR3 =$2C3 ;P3 COLOR COLOR0 =$2C4 ;COLOR 0 COLOR1 =$2C5 COLOR2 =$2C6 COLOR3 =$2C7 COLOR4 =$2C8 ;BACKGROUND ;($2C9 - $2DF SPARE) GLBABS =$2E0 ;GLOBAL VARIABLES ;($2E0 - $2E3 SPARE) RAMSIZ =$2E4 ;RAM SIZE (HI BYTE ONLY) MEMTOP =$2E5 ;TOP OF AVAILABLE MEMORY MEMLO =$2E7 ;BOTTOM OF AVAILABLE MEMORY ;($2E9 SPARE) DVSTAT =$2EA ;STATUS BUFFER CBAUDL =$2EE ;CASSETTE BAUD RATE (LO BYTE) CBAUDH =$2EF ; " " " (HI BYTE) CRSINH =$2F0 ;CURSOR INHIBIT (00 = CURSOR ON) KEYDEL =$2F1 ;KEY DELAY CH1 =$2F2 CHACT =$2F3 ;CHACTL REGISTER (SHADOW) CHBAS =$2F4 ;CHBAS REGISTER (SHADOW) ;($2F5 - $2F9 SPARE) CHAR =$2FA ATACHR =$2FB ;ATASCII CHARACTER CH =$2FC ;GLOBAL VARIABLE FOR KEYBOARD FILDAT =$2FD ;RIGHT FILL DATA (DRAW) DSPFLG =$2FE ;DISPLAY FLAG: DISP CONTROLS IF NON-ZERO SSFLAG =$2FF ;START/STOP FLAG (CNTL-1) FOR PAGING ; PAGE 3 LOCATIONS DCB =$300 ;DEVICE CONTROL BLOCK DDEVIC =$300 ;BUS I.D. NUMBER DUNIT =$301 ;UNIT NUMBER DCOMND =$302 ;BUS COMMAND DSTATS =$303 ;COMMAND TYPE/STATUS RETURN DBUFLO =$304 ;DATA BUFFER POINTER DBUFHI =$305 ; ... DTIMLO =$306 ;DEVICE TIME OUT IN 1 SEC. UNITS DUNUSE =$307 ;UNUSED DBYTLO =$308 ;BYTE COUNT DBYTHI =$309 ; ... DAUX1 =$30A ;COMMAND AUXILLARY BYTES DAUX2 =$30B ; ... TIMER1 =$30C ;INITIAL TIMER VALUE ADDCOR =$30E ;ADDITION CORRECTION CASFLG =$30F ;CASSETTE MODE WHEN SET TIMER2 =$310 ;FINAL TIME VALUE (USED TO COMPUTE BAUD RATE) TEMP1 =$312 ;TEMP LOCATIONS TEMP2 =$314 ; ... TEMP3 =$315 ; ... SAVIO =$316 ;SAVE SERIAL IN DATA PORT TIMFLG =$317 ;TIME OUT FLAG FOR BAUD RATE CORRECTION STACKP =$318 ;SIO STACK POINTER SAVE LOC TSTAT =$319 ;TEMP STATUS LOC HATABS =$31A ;HANDLER ADDRESS TABLE MAXDEV =$21 ;MAXIMUM HANDLER ADDRESS INDEX ; IOCB OFFSETS IOCB =$340 ;I/O CONTROL BLOCKS ICHID =$340 ;HANDLER INDEX ($FF = FREE) ICDNO =$341 ;DEVICE NUMBER (DRIVE NUMBER) ICCOM =$342 ;COMMAND CODE ICSTA =$343 ;STATUS ICBAL =$344 ;BUFFER ADDRESS ICBAH =$345 ; ... ICPTL =$346 ;PUT BYTE ROUTINE ADDRESS - 1 ICPTH =$347 ; ... ICBLL =$348 ;BUFFER LENGTH ICBLH =$349 ; ... ICAX1 =$34A ;AUXILLARY INFO ICAX2 =$34B ; ... ICSPR =$34C ;4 SPARE BYTES PRNBUF =$3C0 ;PRINTER BUFFER ;($3EA - $3FC SPARE) ; PAGE 4 LOCATIONS CASBUF =$3FD ;CASSETTE BUFFER ; USER AREA STARTS HERE AND GOES TO THE END OF PAGE 5 USAREA =$480 ;ATASCII CHARACTER DEFS ATCLR =$7D ;CLEAR SCREEN CHARACTER ATRUB =$7E ;BACK SPACE (RUBOUT) ATTAB =$7F ;TAB ATEOL =$9B ;END-OF-LINE ATBEL =$FD ;CONSOLE BELL ATURW =$1C ;UP-ARROW ATDRW =$1D ;DOWN-ARROW ATLRW =$1E ;LEFT-ARROW ATRRW =$1F ;RIGHT-ARROW ASSPACE = $20 ; added by jrd... ASESC = $1B ; USEFUL VALUES LEDGE =2 ;LMARGN'S INITIAL VALUE REDGE =39 ;RMARGN'S INITIAL VALUE ; ================================================================ ; M6502 ;***** THINGS TO DO ****** ; ; 1) Re-write parser for DDT syntax and better defaults ; Make better use of ATARI keyboard! ; ;************************* ;LBUG STORAGE ASSIGNMENTS (PAGE 0) INBUF =$E0 ;INPUT BUFFER (2 BYTES) POINT =$E2 ;OPEN CELL ADDRS (2 BYTES) AC =$E4 ;ACCUMULATOR XREG =$E5 ;X INDEX YREG =$E6 ;Y INDEX PS =$E7 ;PROCESSOR STATUS REG SP =$E8 ;STACK POINTER ;RANDOM CONSTANTS AND PARAMETERS DSKCOD =$31 ;DISK DEVICE CODE DSKR ='R ;DISK READ COMMAND DSKW ='W ;DISK WRITE COMMAND MAXBP =8 ;EIGHT IS TRADITIONAL (BREAK POINTS) LNSCR =24 ;# OF LINES ON SCREEN LPP =55 ;LINES/PAGE ON PRINTER ;.IIF NDF,LORG, LORG= $8000 ;DEFAULT PROG ORIGIN *= $B000 ;MAIN ENTRY POINT - NORMAL START (LORG) ;RESET ENTRY - REMOVE BREAKPOINTS (LORG+3) ; SETPC PPC,LORG ;NORMAL START ENTRY START: JMP STRT1 JMP RST VERS: ; .ASCII "Lady Bug - V4.0, (C) Ted Hess 1981" .BYTE ATCLR,"Lady Bug - V4.0, (C) Ted Hess 1981",ATEOL ; ROF: .BLKB 1 ; REGISTER OPENED FLAG ; 0 = CLOSED ; $1 = HEX/OCTAL ; $FF = SYMBOLIC CF: .BLKB 1 ;ADDRESS FLAG ; $FF = NO ADDRESSES TYPED ; $00 = ONE ADDRESS TYPED ; $01 = COMMA TYPED PRPC: .BLKB 2 ;PROGRAM COUNTER (AT BREAK) LENGTH: .BLKB 1 ; LENGTH OF INSTR (0 := 1-BYTE) PFRMT: .BLKB 1 ; PRINT FORMAT INDEX VEB: .BLKB 2 ;4 BYTE PROGRAM BLOCK LMNEM: .BLKB 1 ;(VEB+2) TEMP FOR MNEMONIC PRINT RMNEM: .BLKB 1 ;(VEB+3) ... STARTA: .BLKB 2 ;STARTING ADDRESS ENDAD: .BLKB 2 ;ENDING ADDRESS TEMPX: .BLKB 1 ;NEED TO SAVE X AROUND OS TEMPY: .BLKB 1 ;TEMP SAVE Y SNGLF: .BLKB 1 ;SINGLE STEP FLAG BPN: .BLKB 1 ;BREAKPOINT NUMBER OR 0 DRVNO: .BLKB 1 ;DISK UNIT # PIOCB: .BLKB 1 ;IOCB INDEX FOR PRINTER/EDITOR PNTF: .BLKB 1 ; PRINTER FLAG TABPT: .BLKB 1 ;INDEX INTO TAB RING TABRNG: .BLKB 16 ;RING BUFFER FOR TAB/UNTAB ;BREAKPOINT TABLES BPINS: .BLKB MAXBP ;SAVE INSTR BPCNT: .BLKB MAXBP ;PROCEED COUNT BPLOCL: .BLKB MAXBP ;LOCATION LOW BPLOCH: .BLKB MAXBP ;LOCATION HIGH ;RESET ENTRY RST: JSR REMB ;REMOVE BREAK POINTS ; NORMAL STARTUP JOINS HERE STRT1: JSR INITS ;INITIALIZE THINGS ; TYPE VERS ;OUTPUT HERALD LDX #VERS&$FF LDY #VERS^ JSR PUTLIN ; ; CLR ;CLEAR SS FLAG, ETC. LDA #0 STA SNGLF STA BPN STA DRVNO STA PS ; ; SET2 BREAK,VBREAK ;BREAK POINT ENTRY LDA #BREAK&$FF STA VBREAK LDA #BREAK^ STA VBREAK+1 ; TSX ;SAVE CURRENT STACK POINTER STX SP JMP RALL ;CLEAR ALL BREAK POINTS ;MAIN DECODER ERR: JSR ERRFST ;PRINT ? DCD: JSR CLOSEP ;CLOSE PRINTER IF OPEN JSR CRLFS ;PRINT CRLF DCD4: ; CLR ROF ;CLOSE OPEN REG LDA #0 STA ROF ; LDX SP ;RESTORE STACK POINTER TXS SCAN: LDA #$FF ;SET UP ADDRESS FLAG STA CF JSR GETNUM ;INPUT SOMETHING LDX CF ;GET QUANITY TYPED FLAG BMI CLGL ;DO NOT DESTROY OLD VALUE FOR ' AND = SCAN1: ; MOV2X INBUF,STARTA ;SET UP STARTING ADDRESS LDX INBUF STX STARTA LDX INBUF+1 STX STARTA+1 ; ;FALL INTO SPECAIL CHARACTER DECODER ;HERE TO CHECK LEGAL CHARACTER CLGL: LDX #MAXL ;INIT INDEX LGL1: CMP LGCH,X ;MATCH? BEQ LGL2 ;YES - PROCEED DEX ;NO - STEP TO NEXT BPL LGL1 ;BRANCH IF MORE TO GO BMI ERR ;ERROR IF NONE ;FOUND MATCH - DISPATCH LGL2: TXA ;GET INDEX LGL3: ASL A ; TIMES 2 TAX ; BACK TO X LDA LDISP+1,X ;GET HIGH BYTE OF XFER PHA ;PUT ON STACK LDA LDISP,X ;GET XFER LOW PHA ;STACK NOW HAS XFER ADDRS LDA CF ;GET ARGUMENT FLAG IN AC CMP #1 ;SET FLAGS BASED ON ONE RTS ;DISPATCH ERRFST: LDA #ATBEL ;RING BELL JSR OUTSCH LDA #'? ;THEN PRINT ? JMP OUTSCH ;COMMA - SAVE INPUT AS STARTING ADDRESS COMMA: LDA CF ;GET ARGUMENT FLAG IN AC BNE ERR ;MUST BE ONE AND ONLY ONE ARGUMENT TYPED SO FAR JSR GETNUM ;GET ANOTHER ARGUMENT COMMA1: ; MOV2X INBUF,ENDAD ;SET UP ENDING ADDRESS LDX INBUF STX ENDAD LDX INBUF+1 STX ENDAD+1 ; LDX CF ;GET ARGUMENT FLAG CPX #2 ;CHECK TO SEE IF IT IS OPEN BPL ERR ;NO THEN IT IS AN ERROR BMI CLGL ;GO DISPATCH ON BREAK CHARACTER ;ESC SEEN (ECHO $) ESC: LDA #'$ JSR OUTSCH JSR GETSCH ;GET NEXT CHARACTER SEC ;CLEAR BORROW SBC #'1 ;CHECK FOR NUMBER BMI ERR ;IF LESS THAN THEN IT IS AN ERROR CMP #MAXBP ;IS IT LESS THAN MAXIMUM ALLOWABLE BREAKPOINT BMI ESCB ;YES GO GET BREAKPOINT B SBC #@20 ;CHECK FOR A BMI ERR ;IF LESS THAN A IT IS AN ERROR AND #@337 ;GET RID OF LOWERCASE BIT CMP #'Z-@100 ;IS IT GREATER THAN Z BPL ERR1 ;YES. REPORT ERROR TAX ;PUT IT IN THE X REGISTER LDA ARGNUM,X ;GET NUMBER OF ARGUMENTS CMP CF ;IS IT CORRECT BEQ ESC10 ;YES. SKIP REST OF TEST CMP #$80 ;IS IT ONE OR NONE FLAG BNE ERR1 ;NO GIVE ERROR LDA CF ;GET FLAG CMP #1 ;LESS THAN ONE BPL ERR1 ;NO. GO GIVE ERROR ESC10: TXA ;GET INDEX BACK TO A CLC ADC #/2 ;CALC TABLE OFFSET BNE LGL3 ;DISPATCH ESCB: TAX ;SAVE BP NUMBER IN X JSR GETSCH ;GET THE CHARACTER AND #@337 ;GET RID OF CASE BIT CMP #'B ;IS IT A B BNE ERR1 ;NO. THEN IT IS AN ERROR JMP BKPT1 ;YES. GO DO BREAKPOINT ;DOT (.) SEEN - SUBSTITUE CURRENT LOC DOT: ; MOV2 POINT,INBUF ;PUT LOC INTO BUFFER LDA POINT STA INBUF LDA POINT+1 STA INBUF+1 ; DOT1: JSR GETSCH ;GET ANOTHER CHARACTER INC CF ;SAY QUANT TYPED BNE COMMA1 ;GO SET UP ENDING ADDRESS JMP SCAN1 ;BACK TO SCAN LOOP ;PERCENT SEEN - SPECIAL REGISTER PERC: JSR GETSCH ;LOOK AT NEXT CHAR AND #@337 ;GET RID OF CASE BIT LDX #MAXS ; AND CHECK FOR SPECIAL PERC1: CMP LGPC,X ;MATCH? BEQ PERC2 ;??? DEX ;NO - STEP TO NEXT BPL PERC1 ERR1: JMP ERR ;ERROR IF NO MORE ;SETUP DESIRED REGISTER ADDRS AS INPUT TYPED PERC2: LDA PERAD,X ;GET ADDRS OF BYTE STA INBUF ;STORE AS INPUT ; CLR INBUF+1 LDA #0 STA INBUF+1 ; BEQ DOT1 ;BACK TO INPUT LOOP ;CARRIAGE RETURN TYPED CRET: JSR CLSE ;CLOSE OPEN REG IF ANY JMP DCD ;RE-INIT THINGS ;SLASH TYPED - OPEN A REG IN SYMBOLIC SLSH: BPL ERR1 ;IF MORE THAN ONE ARGUMENT IT IS AN ERROR LDA #$FF ;SET ROF FLAG BNE SLSH1 ;JOIN COMMON CODE ;SLASH TYPED - OPEN A REG (HEX) BRAKET: BPL ERR1 ;IF MORE THAN ONE ARGUMENT IT IS AN ERROR LDA #1 ;SET REG OPEN SLSH1: STA ROF JSR OUTSSP ;TYPE A SPACE LDA CF ;ANYTHING TYPED BNE BRAKET10 ; ?? JSR INTPT ;YES - OPEN IT BRAKET10: JSR PRTSCN ;GO DO OUTPUT JMP SCAN ;LINE FEED - OPEN NEXT REG LFD: BPL ERR1 ;IF MORE THAN ONE ARGUMENT IT IS AN ERROR JSR CRLFS ;OUTPUT LFD0: LDA ROF ;CHECK TYPE BMI LFDS ;DO SYMBOLIC NEXT INSTR JSR CLSE ;CLOSE OPEN REG IF ANY JSR INCPT ;STEP TO NEXT LOC LFDC: INC ROF ;MARK OPEN HEX LDX #'[ ;SLASH JSR PRTSLC ;GO PRINT THE CONTENTS JMP SCAN LFDS: JSR PCADJ ;STEP OVER INSTR STA POINT ;SAVE NEW PC STY POINT+1 LFDS1: JSR PRTSLS ;GO PRINT LOCATION IN SYMBOLIC JMP SCAN ;BACK TO MAIN COMMAND DECODER ;^ OR TYPED - OPEN PREVIOUS BACK: BPL ERR1 ;IF MORE THAN ONE ARGUMENT IT IS AN ERROR JSR CLSE ;CLOSE OPEN REG JSR DECPT ;DECREMENT THE POINTER JSR CRLFS ;PUT OUT A CARRIAGE RETURN LINE FEED JMP LFDC ;COMMON CODE ;TAB GO TO ADDRESS IF IN SYMBOLIC MODE TAB: BPL ERR1 ;ERROR IF MORE THAN 1 ARG LDA ROF ;GET OUTPUT MODE FLAG BPL ERR1 ;ONLY GET EFFECTIVE ADDRESS IF SYMBOLIC LDX TABPT ;SAVE POINT LDA POINT STA TABRNG,X ;IN RING BUFFER LDA POINT+1 STA TABRNG+8,X INX ;STEP INDEX TXA AND #$07 ;MASK TO MOD 8 CNTR STA TABPT ;STORE IT BACK JSR CALCAD ;CALCULATE EFFECTIVE ADDRESS ; MOV2 INBUF,POINT ;GET JMP ADDRESS LDA INBUF STA POINT LDA INBUF+1 STA POINT+1 ; TAB1: JSR CRLFS ;PUT OUT CARRIAGE RETURN LINE FEED JMP LFDS1 ;GO TYPE OUT NEW ADDRESS ; UNTABIFY - POP RING THEN TAB UNTAB: BPL UNTAB5 ;ERROR IF ANYTHING TYPED LDA ROF ;REGISTER OPEN FLAG UNTAB5: BPL ERR2 ;ERROR IF NOT SYMBOLIC MODE LDA #$7 ;MASK FOR MOD 8 SUBTRACT DEC TABPT ;DECREMENT INDEX AND TABPT ;MASK IT STA TABPT ;STORE RESULT TAX ;XFER TO INDEX LDA TABRNG,X ;FETCH SAVED VALUE STA POINT ;RESTORE TO POINT LDA TABRNG+8,X STA POINT+1 JMP TAB1 ;FINISH THRU COMMON CODE ;EQUAL SIGN - TYPE IN OCTAL TOC: BPL ERR2 ;IF MORE THAN ONE ARGUMENT IT IS AN ERROR LDA STARTA ;GET CHARACTER IN A STA PFRMT ;SAVE BYTE LDX #3 ;TYPE 3 DIGITS LDY #3 ; OF 3 BITS EACH CLC ;INIT CARRY BIT BCC TOC15 ;SKIP FIRST SHIFT TOC10: ASL PFRMT ;SHIFT LEFT TOC15: ROL A ;GET BIT INTO AC DEY ;COUNT BITS BNE TOC10 ;CONTINUE FOR 3 BITS AND #@7 ;GRNTEE OIT JSR HEXST1 ;TYPE OUT LDY #3 ;RELOAD BIT COUNTER DEX ;DECREMENT DIGIT COUNTER BNE TOC10 ;LOOP TILL DONE TOCRET: JSR OUTSSP ;PRINT SPACE JMP SCAN ;BACK TO MAIN LOOP ;QUOTE - TYPE OUT ASCII QUOTE: BPL ERR2 ;IF MORE THAN ONE ARGUMENT IT IS AN ERROR LDA STARTA ;GET CHARACTER IN A JSR OUTSCH ;PRINT THE CHARACTER IN ASCII JMP TOCRET ;GO PRINT A SPACE AND RETURN ;$A - TYPE MEMORY OUT IN ASCII ASCII: JSR INTPT ;SET UP POINT FROM ADDRESS TYPED JSR GETSCH ;GET QUOTE CHARACTER STA CF ;SAVE IT FOR COMPARE ASCII10: JSR GETSCH ;GET ANOTHER CHARACTER CMP CF BEQ ASCII20 ;IF QUOTE RETURN LDY #0 ;SET UP FOR INDEXING STA (POINT),Y ;PUT THE CHARACTER IN MEMORY JSR INCPT ;INCREMENT THE POINTER JMP ASCII10 ;GO DO ANOTHER CHARACTER ASCII20: JMP DCD ;GO BACK TO MAIN SCANING LOOP ;$B - BREAKPOINT COMMAND BKPT: LDX #$FF ;SAY NO BREAKPOINT NUMBER GIVEN BKPT1: LDA CF ;GET ARGUMENT FLAG BMI CLRALL ;POSSIBLE CLEAR ALL $B OR $NB/ CPX #0 ;SPECIFIC BREAK POINT BPL BKPT2 ; IF QUANT AFTER $ LDX #MAXBP-1 ;LOOK FOR A FREE ONE BKPT15: LDA BPINS,X BEQ BKPT2 ;FOUND IF ZERO DEX ;STEP TO NEXT BPL BKPT15 ; AND TRY AGAIN ERR2: JMP ERR ;BRANCH TO HERE FOR ERROR ;X NOW CONTAINS AN INDEX INTO THE BP TABLES BKPT2: LDA STARTA ;CHECK FOR 0$NB BNE SETBP ;IF NOT ZERO CONTINUE LDA STARTA+1 ;GET HIGH BYTE BEQ CLRONE ;CLEAR JUST ONE ;NOW SET A BREAK POINT - ADDRS IN INTMP SETBP: ; MOV2 STARTA,INBUF ;NEED IN PAGE 0 LOC LDA STARTA STA INBUF LDA STARTA+1 STA INBUF+1 ; LDY #0 ;SET FOR INDIRECT LDA (INBUF),Y ;FETCH INSTR BEQ ERR2 ;ERROR IF 00 STA BPINS,X ;SAVE IN TABLE LDA INBUF ;SAVE ADDRS STA BPLOCL,X ; LOW LDA INBUF+1 ; AND HIGH STA BPLOCH,X ;... ; ... ; ... BPXIT: JSR PRBLNK ;PRINT SOME SPACES JMP SCAN ;BACK TO DECODER ;ROUTINE TO CLEAR ONE BREAKPOINT ;C(X) - INDEX INTO BP TABLES, C(AC) := 0 CLRONE: STA BPINS,X ;CLEAR BP STA BPCNT,X ; AND PROCEED COUNT BEQ BPXIT ;RETURN ;ROUTINE TO CLEAR ALL BREAK POINTS CLRALL: CPX #0 ;SPECIFIC BREAK POINT BPL SHONE ;SHOW ONE BP RALL: LDX #MAXBP-1 ;INIT COUNT LDA #0 ;GET A ZERO RALL5: STA BPINS,X ;CLEAR BP STA BPCNT,X ;... DEX BPL RALL5 ;LOOP TILL DONE JMP DCD ;RE-INIT THINGS ;ROUTINE TO SHOW LOC OF BP SHONE: JSR GETSCH ;LOOK AHEAD CHAR CMP #'/ ;GAURNTEE SLASH BNE ERR2 JSR OUTSSP ;SPACE OVER LDA BPINS,X ;SEE IF ACTIVE BEQ ERR2 ;NO - SORRY LDA BPLOCH,X ;GET LOC HIGH JSR PRTSBY ;PRINT IT LDA BPLOCL,X ;GET LOC LOW JSR PRTSBY ;PRINT IT JMP DCD ;CLOSE REG, ETC. ;$D - JUMP TO DOS TODOS: JMP (DOSVEC) ;$U - SELECT DISK UNIT SETU: LDA STARTA ;GET UNIT # BEQ ERR2 ;MUST BE 1-4 CMP #5 ;VALID? BCC ERR2 ;TOO LARGE STA DRVNO ;STORE UNIT # JMP BPXIT ;RETURN ;$W - WRITE DISK SECTORS FROM MEMORY WRSECT: JSR GETVAL ;BUFFER LDA #DSKW ;WRITE COMMAND BNE INIDSK ;DO IT ;$R - READ DISK SECTORS INTO MEMORY RDSECT: JSR GETVAL ;GET BUFFER ADDRS LDA #DSKR ;READ COMMAND INIDSK: STA DCOMND ;STORE ; MOV2 INBUF,DBUFLO ;SETUP BUFFER LDA INBUF STA DBUFLO LDA INBUF+1 STA DBUFLO+1 ; JSR INTPTC ;SET POINT := START SECTOR LDA #DSKCOD ;BUS I.D. FOR DISK STA DDEVIC LDA DRVNO ;SETUP DRIVE # STA DUNIT LDA #128 ;BYTE COUNT STA DBYTLO ; CLR DBYTHI LDA #0 STA DBYTHI ; DSKLUP: ; MOV2 POINT,DAUX1 ;SETUP SECTOR ADDRS LDA POINT STA DAUX1 LDA POINT+1 STA DAUX1+1 ; JSR DSKINV ;INVOKE DISK HANDLER BMI IOCERR ;ERROR CODE IS .GE. $80 JSR ENDCHK ;CHECK END, INCR POINT CLC ;NOT END - STEP TO NEXT BUFFER LDA #128 ;128 BYTE/BUFFER ADC DBUFLO STA DBUFLO LDA #0 ;PROPAGATE CARRY ADC DBUFHI STA DBUFHI BNE DSKLUP ;LOOP TILL DONE IOCERR: JSR ERRFST ;OUT ? JSR OUTSSP LDA DSTATS ;GET STATUS JSR PRTSBY ;PRINT ERROR CODE JSR PRBLNK ;SOME BLANKS JSR PRTSPT ; THEN DISK ADDRS JMP DCD ;RETURN ;$F - FIND A BYTE IN MEMORY FIND: JSR GETVAL ;GET THE BYTE JSR INTPTC ;SET UP INDIRECT POINTER FROM START LDA #1 STA ROF ;SET THE MODE FLAG FIND10: LDY #0 ;SET UP INDEX LDA (POINT),Y ;GET BYTE FROM MEMORY CMP INBUF ;DOES IT MATCH BNE FIND20 ;NO LDX #'[ ;SLASH JSR PRTSLC ;GO PRINT THE CONTENTS JSR CRLFS ;PUT OUT CARRIAGE RETURN LINE FEED FIND20: JSR ENDCHK ;ARE WE FINISHED JMP FIND10 ;NO ;$G - START SOMEWHERE GO: JSR INTPTC ;GO SETUP ADDRESS ; CLR ;CLEAR CURRENT BP LDA #0 STA BPN STA SNGLF ; GO2: JSR INSB ;INSERT BP'S GO3: LDX SP ;RESTORE STACK TXS LDA POINT+1 ;SETUP RETURN ADDRS PHA ; ON STACK FOR RTI LDA POINT PHA ;... LDA PS ;PROCESSOR STATUS PHA LDX XREG ;RESTORE REGS LDY YREG LDA AC ;... RTI ;GO BACK ;HERE IF SINGLE STEP - SETUP FOR RE-ENTER AFTER XCT GO1: LDY IOPC ;CHECK FOR JUMPS CPY #$4C BEQ GOJMP ;VANILLA JUMP CPY #$6C ;MAYBE JUMP, INDIRECT BEQ GOJMPI ; A LITTLE MORE HAIRY CPY #$60 ;"RTS"? BEQ IRTS ; INTERPRET SUBROUTINE RETURN CPY #$40 ;"RTI" BEQ IRTI ; INTERPRET INTERRUPT RETURN BNE GO3 ; AND GO EXECUTE GOJMP: ; SET2 XCTBR,POINT ;EXECUTE HERE LDA #XCTBR&$FF STA POINT LDA #XCTBR^ STA POINT+1 ; BNE GO3 GOJMPI: ; MOV2 XBTARG,POINT ;NEED TO PICK UP ACTUAL TARGET LDA XBTARG STA POINT LDA XBTARG+1 STA POINT+1 ; LDY #0 LDA (POINT),Y STA XBTARG ;AND SET UP FOR "BRANCH" SIMULATION INY ;SET TO NEXT LOC LDA (POINT),Y STA XBTARG+1 JMP GOJMP ;NO GO SIMULATE JMP (I) IRTS: LDX SP ;GET STACK POINTER TXS ;SETUP FOR "RTS" SIMULATION IRTS1: PLA ;PCL STA XBTARG PLA ;PCH STA XBTARG+1 CPY #$40 ;IS THIS SUBR OR INTERRUPT BEQ IRTS110 ;DON'T INCREMENT PC IF "RTI" INC XBTARG ;"RTS" NEED PC + 1 BNE IRTS110 INC XBTARG+1 IRTS110: TSX ;SAVE MODIFIED STACK PNTR STX SP JMP GOJMP IRTI: LDX SP ;SETUP STACK POINTER TXS PLA ;GET PROCESSOR STATUS STA PS JMP IRTS1 ;GOIN COMMON CODE ;$H - HEX DUMP TO TTY HDUMP: JSR INTPT ;SET UP START AND END ADDRESS LDA POINT ;GET LOW PART OF ADDRESS AND #$F0 ;MAKE IT START ON A NICE BOUNDRY STA POINT HDUMP10: JSR SETOUT ;SETUP OUTPUT DEVICE / GET LPP STA LENGTH ; SAVE IT AWAY HDUMP20: JSR CRLFS ;PRINT OUT CARRAGE RETURN LINEFEED JSR PRTSPT ;PRINT OUT THE LOCATION LDA #$10 ;NUMBER OF BYTES PER LINE JSR DMPLIN ;PRINT A LINE OF DUMP JSR ENDCHK ;CHECK TO SEE IF WE ARE FINISHED DEC LENGTH ;COUNT LINE BNE HDUMP20 ;GO DO ANOTHER LINE JSR PAGEWT ;GO WAIT FOR CONTINUE JMP HDUMP10 ;GO DO ANOTHER PAGE ;$I - INITIALIZE MEMORY INIT: JSR GETVAL ;GET VALUE LDX INBUF ;GET BYTE INTO X INITM1: JSR INTPTC ;SET UP ADDRESSES INITM110: TXA ;GET CHARACTER BACK LDY #0 ;SET UP FOR INDEXING STA (POINT),Y ;SET MEMORY TO SPECIFIED VALUE JSR ENDCHK ;CHECK TO SEE IF FINISHED JMP INITM110 ;NO GO DO ANOTHER VALUE ;$Z - ZERO MEMORY ZERO: LDX #0 ;GET A ZERO BEQ INITM1 ;GO INITIALIZE MEMORY ;$M - MOVE A BLOCK OF STORE MOVE: LDA #$8D ;GET STORE OPCODE JSR INTIVB ;SET UP STORE AND RETURN IN VEB JSR GETVAL ;GET TO ADDRESS JSR INTPT ;SET UP POINT FROM START ; MOV2 INBUF,VEB+1 ;SET UP ADDRESS LDA INBUF STA VEB LDA INBUF+1 STA VEB+1 ; MOVE10: LDY #0 ;SET UP FOR INDEXING LDA (POINT),Y ;GET BYTE JSR VEB ;STORE IT AT NEW ADDRESS JSR INCVEB ;BUMP THE VEB POINTER JSR ENDCHK ;FINISHED? JMP MOVE10 ;NO ;$L - PRINTER SELECT TOGGLE PNTSEL: LDA STARTA ;COMPLIMENT PRINTER FLAG STA PNTF JMP BPXIT ;RETURN TO MAIN LOOP ;$O - CALCULATE BRANCH OFFSET OFFSET: JSR PRBLNK ;PUT OUT SOME BLANKS CLC ;MAKE FROM BE ONE MORE LDA ENDAD ;GET FIRST OF TO ADDRESS SBC STARTA ;SUBTRACT FROM ADDRESS TAX ;SAVE LOW ORDER PART OF ADDRESS LDA ENDAD+1 ;GET HIGH PART OF TO ADDRESS SBC STARTA+1 ;SUBTRACT FROM ADDRESS TAY ;SAVE HIGH ORDER BYTE BNE OFFSET10 ;IF IT IS ZERO MAY BE LEGAL ADDRESS TXA ;GET LOW PART BACK BPL OFFSET30 ;VALID ADDRESS BMI OFFSET20 ;ELSE ILLEGAL ADDRESS OFFSET10: CMP #$FF ;OR $FF IS LEGAL BNE OFFSET20 TXA ;GET LOW PART BACK BMI OFFSET30 ;VALID ADDRESS OFFSET20: TYA ;GET HIGH ORDER BYTE JSR PRTSBY ;GO PRINT HIGH ORDER BYTE OFFSET30: TXA ;GET LOW ORDER BYTE JSR PRTSBY ;PRINT LOW BYTE JSR CRLFS ;AND CARRIAGE RETURN LINE FEED JMP SCAN ;GO BACK TO MAIN LOOP ;$P - PROCEED FROM BREAKPOINT PROC: JSR CRLFS ;SIGNAL START ; CLR SNGLF ;NOT SINGLE STEP LDA #0 STA SNGLF ; LDA CF ;QUANT TYPED BMI PROC1 ;NO - PROCEED ONCE LDA STARTA ;GET LOW BYTE OF COUNT BEQ PERR ;DON'T ALLOW 0$P BNE PROC2 ;PROCEED COUNT IN AC PROC1: LDA #1 ;PRELOAD A ONE PROC2: LDX BPN ;ACTUAL BP # BEQ IXCT ;COULD BE FROM PANIC INT STA BPCNT-1,X ;STORE COUNT BNE IXCT ;JOIN SS CODE PERR: JMP ERR ;HANDY BRANCH LOC ;$X - SINGLE STEP EXEC: ; CLR BPN ;NO BREAKS IN PROGRESS LDA #0 STA BPN ; INC SNGLF ;SET FLAG IXCT: ; MOV2 PRPC,POINT ;SET START ADDRESS LDA PRPC STA POINT LDA PRPC+1 STA POINT+1 ; JSR CALCAD ;GET LENGHT, EA, FORMAT ; MOV2 INBUF,XBTARG ;SET EA TO BRANCH TARGET LDA INBUF STA XBTARG LDA INBUF+1 STA XBTARG+1 ; LDX #$EA ;GET NOP STX IOPC+1 ;INIT FOR 1 BYTE INSTR STX IOPC+2 LDA (POINT),Y ;GET OPCODE BNE IXCT5 ;CONVERT "BRK" INTO "NOP" TXA IXCT5: STA IOPC LDA LENGTH ;LENGTH OF INSTR BEQ IXCT1 ;1 BYTE - GO NOW JSR INCPT ;MOVE TO NEXT BYTE LDA PFRMT ;CHECK FOR BRANCH CMP #$1D ; INSTR BNE IXCT3 ;NOT BRANCH LDA #XCTBR-IOPC-2 ;BRANCH - SET UP DISPLACEMENT STA IOPC+1 ;STORE IN OFFSET BYTE BNE IXCT1 ;JOIN COMMON EXIT IXCT3: LDA (POINT),Y ;GET NEXT BYTE STA IOPC+1 ;STORE IN XCT BLOCK LDA LENGTH CMP #2 ;CHECK FOR 1 OR 2 EXTRA BYTES BNE IXCT1 ;ONLY 1 BYTE JSR INCPT ;MOVE TO NEXT LDA (POINT),Y ;GET 3RD AND LAST STA IOPC+2 LDA IOPC ;GET OPCODE BYTE CMP #$20 ;IS IT "JSR"? BNE IXCT1 ;BRANCH IF NOT LDX SP ;GET SAVED STACK POINTER TXS ;SET STACK LDA POINT+1 ;YES - SETUP RETURN PC PHA LDA POINT PHA TSX ;SAVE UPDATED POINTER STX SP ; FOR PROCEED LDA #$4C ;CHANGE INTO "JMP" STA IOPC IXCT1: JSR INCPT ;STEP TO INSTR AFTER THIS ONE ; MOV2 POINT,XNOBR ;SETUP NO BRANCH LOC LDA POINT STA XNOBR LDA POINT+1 STA XNOBR+1 ; ; SET2 IOPC,POINT ;SET START ADDR TO IOPC BLOCK LDA #IOPC&$FF STA POINT LDA #IOPC^ STA POINT+1 ; JMP GO1 ;AND START UP ;EXECUTE BLOCK FOR INSTR XCT SIMULATOR IOPC: BEQ XCTBR .BYTE $EA ;NOP STY YREG ;SAVE NEW STATE AFTER $X STX XREG STA AC PHP PLA STA PS ;PROCESSOR STATUS TSX STX SP ;STACK POINTER XCTNB: ; MOV2 XNOBR,POINT ;NO BRANCH OCCURED LDA XNOBR STA POINT LDA XNOBR+1 STA POINT+1 ; JMP BRKY XCTBR: ; MOV2 XBTARG,POINT ;BRANCH OCCURED LDA XBTARG STA POINT LDA XBTARG+1 STA POINT+1 ; JMP BRKY XNOBR: ; .BLKW 1 ;SAVED POINTERS FOR SINGLE STEP .word 0 ; .BLKB 2 ; XBTARG: ; .BLKW 1 .word 0 ; .BLKB 2 ; ;$Q - DISASSEMBLE CODE DISASS: JSR INTPT ;SET UP POINT DISASS10: JSR SETOUT ;SET OUTPUT DEVICE STA CF ; RETURNS LINES/PAGE DISASS20: JSR CRLFS ;PUT OUT CARRIAGE RETURN LINE FEED JSR PRTSLS ;GO PRINT A LINE JSR ENDCHK ;CHECK TO SEE IF FINISHED LDA LENGTH ;GET LENGTH OF INSTRUCTION CLC ;ONE ALREADY ADDED AT ENDCHK JSR PCADJ3 ;POINT TO NEXT INSTRUCTION STA POINT ;SAVE UPDATED ADDRESS STY POINT+1 DEC CF ;ACCOUNT FOR LINE BNE DISASS20 ;GO DO ANOTHER INSTRUCTION JSR PAGEWT ;GO WAIT FOR GO AHEAD BNE DISASS10 ;GO DO ANOTHER PAGE ;ROUTINE TO SETUP FOR OUTPUT - CHECK PNTF FOR PRINTER SETOUT: LDA PNTF ;WANT PRINTER? BEQ SETOUT10 JSR OPENP ;YES - OPEN IT IF NOT OPEN ALREADY LDA #LPP ;RETURN LINES/PAGE RTS SETOUT10: LDA #LNSCR ;LINE/SCREEN (EDITOR) RTS ;$S - SEARCH FOR ADDRESS SEARCH: JSR GETVAL ;GET A WORD ; MOV2 INBUF,VEB ;SAVE VALUE SEARCHING FOR LDA INBUF STA VEB LDA INBUF+1 STA VEB+1 ; JSR INTPTC ;SET UP ADDRESSES JSR DECPT ;DECREMENT IT BY ONE SEARCH10: LDY #0 ;SET UP INDEX LDA (POINT),Y ;GET FIRST BYTE CMP VEB ;DOES IT MATCH BNE SEARCH20 ;NO INY ;BUMP POINTER LDA (POINT),Y ;GET SECOND BYTE CMP VEB+1 ;DOES IT MATCH BNE SEARCH20 ;NO JSR PRTSPT ;PRINT THE ADDRESS LDA #'/ ;PRINT SEPERATOR JSR OUTSCH ;PRINT IT JSR OUTSSP ;PUT OUT A SPACE LDA VEB+1 ;GET HIGH BYTE JSR PRTSBY ;PRINT THE BYTE LDA VEB ;GET LOW BYTE JSR PRTSBY ;PRINT IT JMP SEARCH30 ;GO DO CARRIAGE RETURN LINE FEED SEARCH20: JSR CALCAD ;GET EFFECTIVE ADDRESS OF INSTRUCTION LDA INBUF ;GET LOW BYTE CMP VEB ;DOES IT MATCH BNE SEARCH40 ;NO LDA INBUF+1 ;GET HIGH BYTE CMP VEB+1 ;DOES IT MATCH BNE SEARCH40 ;NO JSR PRTSLS ;GO PRINT THE CONTENTS LDA PFRMT ; CMP #$1D ;CHECK TO SEE IF IT WAS A BRANCH BEQ SEARCH30 ;YES. NO NEED TO BUMP TWO JSR INCPT ;BUMP POINTER SO WE DO NOT GET ADDRESS AGAIN SEARCH30: JSR CRLFS ;PUT OUT CARRIAGE RETURN LINE FEED SEARCH40: JSR ENDCHK ;ARE WE FINISHED JMP SEARCH10 ;NO ;$T - TYPE OUT MEMORY IN ASCII TYPE: JSR INTPTC ;SET UP ADDRESSES TYPE10: LDY #0 ;SET UP FOR INDEXING LDA (POINT),Y ;GET A CHARACTER JSR OUTSCH ;PRINT THE CHARACTER JSR ENDCHK ;FINISHED? JMP TYPE10 ;NO ;ROUTINES DEALING WITH POINT ;REGISTER CLOSE ROUTINE ;CLOSE LOCATION AND UPDATE IF NECESSARY CLSE: LDY #0 ;PREPARE TO MODIFY LDA ROF ;GET FLAG BEQ CLSEX ;XFER IF NONE OPEN BMI CLSEX ; OR SYMBOLIC LDA CF ;ANYTHING TYPED? BMI CLSEX ;NO - DO NOTHING LDA STARTA ; CURRENT OPEN REG STA (POINT),Y ; WITH INPUT VALUE CLSEX: STY ROF ;SET REGISTER CLOSED RTS ;RETURN ;SET UP POINT FROM THE STARTING ADDRESS INTPTC: JSR CRLFS ;PUT OUT CARRIAGE RETURN LINE FEED FIRST INTPT: ; MOV2 STARTA,POINT LDA STARTA STA POINT LDA STARTA+1 STA POINT+1 ; RTS ;DECREMENT THE PC DECPT: SEC ;PREPARE TO DECREMENT POINT LDA POINT SBC #1 STA POINT BCS DECPT10 DEC POINT+1 ;HANDLE BORROW DECPT10: RTS ;CHECK TO SEE IF POINT IS AT END YET ENDCHK: LDA POINT ;CHECK TO SEE IF FINISHED CMP ENDAD LDA POINT+1 SBC ENDAD+1 BCS ENDCHK20 ;IF GREATER THAN, FINISHED JMP INCPT ;INCREMENT THE POINTER ENDCHK20: JMP DCD ;FINISHED GO BACK TO MAIN LOOP ;ROUTINES TO PICK UP VALUES ; GET ADDITIONAL VALUE, PROMPT FOR INPUT, ERROR IF NOT ; TERMINATED BY GETVAL: JSR OUTSSP ;OUTPUT SPACE LDA #': ; AND PROMPT JSR OUTSCH JSR GETNUM CMP #ATEOL ;TERMINATED PROPERLY? BEQ ABTRET ;YES - RETURN JMP ERR ;NOPE -ERROR ;GET A NUMBER RETURN WITH TERMINATOR IN A GETNUM: ; CLR2 INBUF ;CLEAR THE BUFFER LDA #0 STA INBUF ; JSR PACKCH ;GET A CHARACTER BNE ABTCHK ;IF NOT HEX RETURN WITH CHARACTER IN A INC CF ;SAY WE HAVE A NUMBER GETNUM10: JSR PACKCH ;GO GET ANOTHER CHARACTER BEQ GETNUM10 ;IF HEX GO GET ANOTHER CHARACTER ;;; ... ; FALL INTO ABTCHK ;CHECK FOR RUBOUT OR BREAK. IF FOUND RETURN TO COMMAND DECODER ABTCHK: CMP #ATRUB ;RUBOUT BEQ ABORT ;ABORT COMMAND CMP #BRKABT ;BREAK TYPED BEQ ABORT ABTRET: RTS ABORT: ; TYPE EXES ;PUT OUT XXX LDX #EXES&$FF LDY #EXES^ JSR PUTLIN JMP DCD4 EXES: ; .ASCII " XXX" .BYTE " XXX" .BYTE ATEOL ;GET A CHARACTER AND PACK IT PACKCH: JSR GETSCH ;GET THE CHARACTER CMP #'9+1 ;CAN IT BE A NUMBER BMI PACK ;YES GO TRY TO PACK IT CMP #'A ;IS IT A CHARACTER BMI PACKCH10 ;NO. INVALID CHARACTER RETURN CMP #ATRUB ;RUBOUT BEQ PACKCH10 ;YES. INVALID CHARACTER RETURN AND #@337 ;GET RID OF LOWERCASE BIT CMP #'F+1 ;IS IT G OR LARGER BMI PACK ;NO. GO PACK IT PACKCH10: TAY ;SIGNAL ILLEGAL CHARACTER RTS PACK: CMP #'0 ;CHECK FOR HEX BMI PACKX CMP #'A-1 ;ADJUST FOR A-F BMI PACK10 CLC ;BY ADDING OFFSET ADC #$09 PACK10: ROL A ;SHIFT IN ROL A ROL A ROL A LDY #$04 ;4 MORE SHIFTS THRU CARRY PACK20: ROL A ; TO MOVE INTO INBUF ROL INBUF ROL INBUF+1 ;RIPPLE BIT THROUGH DEY ;COUNT LOOP BNE PACK20 LDA #$00 ;RETURN A = 0 IF OK NUMBER PACKX: RTS ;WAIT FOR A CHARACTER TO BE TYPED IF IT IS A RUBOUT RETURN TO COMMAND ;DECODER PAGEWT: LDA PIOCB ;ARE WE PRINTING? BEQ PAGEWT10 LDA #@14 ;OUTPUT FF JMP OUTSCH PAGEWT10: LDA #ATBEL ;GET BELL JSR OUTSCH ;RING IT JSR GETSCH ;WAIT FOR CHARACTER JMP ABTCHK ;CHECK FOR ABORT OR PROCEED ;ROUTINE TO GET A CARACTER ; RETURNS CHARACTER IN A ; USES Y GETSCH: STX TEMPX ;SAVE X STY TEMPY ; AND Y AROUND O/S LDA #0 STA ICAX1Z ;CLEAR FLAG JSR KGETCH ;RETURNS STATUS IN Y, CHAR IN A BMI GETSCH20 ;DON'T ECHO SPECIAL CHARS CMP #ATRUB ;CHECK BS/DEL KEY BEQ GETSCH30 ; RUBOUT DOESN'T ECHO CMP #ASSPACE ;CHECK FOR CONTROLS BCS OUTSCN ; ECHO IF NOT BCC GETSCH30 ;RETURN CHAR - NO ECHO GETSCH20: CPY #BRKABT ;BREAK KEY TYPED? BNE GETSCH30 TYA ;YES - RETURN BREAK FLAG GETSCH30: LDX TEMPX ;RESTORE LDY TEMPY RTS ; ELSE RETURN ;ROUTINE TO GET TWO HEX CARACTERS INTO AC ; RETURNS CHARACTER IN A ; X PRESERVED Y RETURNED = 0 GETSBY: JSR PACKCH ;GET A CHARACTER JSR PACKCH ;GET ANOTHER CHARACTER LDA INBUF ;LOAD UP BYTE RTS ;GENERAL PURPOSE PRINTING ROUTIMES ;PRINT LOCATION AND IT'S CONTENETS IF FORM SPECIFIED BY ROF PRTSLS: LDA #$FF ;SET THE TYPEOUT MODE BACK STA ROF LDX #'/ ;SLASH PRTSLC: JSR PRTSPT ;PRINT CONTENTS OF POINT TXA ;GET CHAR BACK JSR OUTSCH JSR OUTSSP ; AND A SPACE ;;; ... ; FALL INTO PRTSCN ;PRINT OUT CONTENTS OF CURRENT LOCATION IN FORM SPECIFIED BY ROF PRTSCN: LDY #0 ;SET FOR GLOBAL INDEX LDA (POINT),Y ;GET CURRENT LOCATION IN A STA STARTA ;SAVE FOR QUOTE OR EQUAL LDX ROF ;SEE WHAT KIND BMI PRTSCN20 ;BR IF SYMBOLIC JSR PRTSBY ;PRINT CONTENTS PRTSCN10: JMP OUTSSP ;AWAIT NEXT REQUEST PRTSCN20: JSR DSMBL ;PRINT SYMBOLIC JMP PRTSCN10 ; AND RETURN TO CMD LOOP ;DUMP NUMBER OF LOCATIONS IN A TO SCREEN DMPLIN: STA PFRMT ;SAVE IT JSR PRBLNK ;SPACE OVER 2 BEQ DMPLIN20 ;DO NOT INCREMENT POINTER FIRST TIME DMPLIN10: JSR INCPT ;INCREMENT THE POINTER JSR OUTSSP ;PRINT BLANK DMPLIN20: LDY #0 ;SET UP FOR INDEXING LDA (POINT),Y ;GET LOCATION JSR PRTSBY ;PRINT IT DEC PFRMT ;ACCOUNT FOR CHARACTER BNE DMPLIN10 ;NOT FINISHED GO DO MORE RTS ;OUTPUT NUMBER OF BLANKS IN X PRBLNK: LDX #$2 PRBL2: JSR OUTSSP DEX BNE PRBL2 ;LOOP TILL COUNT = 0 RTS ;ROUTINE TO OUTPUT CHARACTER TO OUTPUT PORT ; CHARACTER IN A ; USES Y AND RETURNS CHARACTER IN A OUTSSP: LDA #ASSPACE ;LOAD UP A BLANK OUTSCH: STX TEMPX ;SAVE X & Y AROUND O/S JSRS STY TEMPY OUTSCN: PHA ;SAVE THE CHARACTER TAY ; AND MOVE TO Y LDX PIOCB ;GET IOCB INDEX LDA #PUTCHR ;1 CHAR OUTPUT JSR CIOC ;OUTPUT TO EDITOR/PRINTER LDX TEMPX ;RESTORE X LDY TEMPY ;RESTORE Y PLA RTS ;ROUTINE TO WRITE OUT CARRIAGE RETURN LINE FEED ; USES A AND Y CRLFS: LDA #ATEOL JMP OUTSCH ;WRITE IT OUT AND RETURN ;ROUTINE TO PRINT CURRENT LOCATION ; PRINTS POINT ; USES A AND Y PRTSPT: LDA POINT+1 ;GET HIGH ORDER BYTE JSR PRTSBY LDA POINT ;GET LOW ORDER BYTE ;;; ... ;FALL INTO PRTSBY ;ROUTINE TO PRINT BYTE AS TWO HEX DIGITS ; BYTE IS IN A PRTSBY: PHA ;SAVE THE BYTE LSR A ;GET HIGH ORDER FOUR BITS LSR A LSR A LSR A JSR HEXSTA ;GO CONVERT IT TO HEX PLA ;GET THE ORGINAL BYTE BACK ;;; ... ; FALL INTO HEXSTA ;ROUTINE TO CONVERT A HEX DIGIT TO ASCII ; DIGIT IS IN A HEXSTA: AND #$0F ;GET JUST ONE DIGIT CMP #$0A ;IS IT A DECIMAL DIGIT CLC ;CLEAR THE CARRY BMI HEXST1 ;IF NEGATIVE IT IS A DECIMAL DIGIT ADC #$07 ;ADD IN OFFSET TO GET A-F HEXST1: ADC #$30 ;CONVERT TO ASCII JMP OUTSCH ;GOT WRITE CHARACTER AND RETURN ; MISC ROUTINES INITS: CLD ;CLEAR DECIMAL MODE LDA #LEDGE ;SET DEFAULT MARGINS STA LMARGN LDA #REDGE STA RMARGN LDA #$94 ;SETUP BACKGROUND COLOR STA COLOR4 ;TO BE SAME AS FOREGROUND JMP CLOSEP ;CLOSE PRINTER IF OPEN ;SET UP VEB AREA INTSVB: LDA #$AD ;LDA OP CODE INTIVB: STA VEB INTVEB: LDA STARTA ;SET UP SUB STA VEB+1 LDA STARTA+1 STA VEB+2 LDA #$60 ;"RTS" STA VEB+3 RTS ;ROUTINE TO INCRENT POINT INCPT: ; INC2 POINT INC POINT BNE INCPT1 INC POINT+1 INCPT1: RTS ;ROUTINE TO INCREMENT ADDRS IN VEB INCVEB: ; INC2 VEB+1 INC VEB+1 BNE INCRET INC VEB+2 INCRET: RTS ;PRINTER ROUTINES OPENP: LDA PIOCB ;CHECK IF ALREADY OPEN BNE INCRET ;YES - DON'T REOPEN LDX #$10 ;START AT IOCB#1 OPENP5: LDA ICHID,X ;GET ID CMP #$FF ;FREE? BEQ THSONE CPX #$70 ;LAST ONE? BEQ PNONE TXA ;STEP INDEX TO NEXT CLC ADC #$10 TAX ;BACK TO X BNE OPENP5 PNONE: JMP ERR ;NO FREE IOCB'S ;FOUND FREE IOCB (INDEX IN X) THSONE: STX PIOCB ;SAVE IOCB INDEX LDA #OPNOT ;OPEN FOR OUTPUT STA ICAX1,X ; SET2 PDEV,ICBAL,X ;POINT TO DEVICE TEXT LDA #PDEV&$FF STA ICBAL LDA #PDEV^ STA ICBAL+1 ; LDA #OPEN ;OPEN COMMAND CIOC: STA ICCOM,X ;STORE COMMAND LDA #0 ;SET LENGTH TO ZERO STA ICBLL,X STA ICBLH,X TYA ;MIGHT HAVE CHARACTER JSR CIOV ;INVOKE O/S STY DSTATS ;PUT COMPLETION CODE HERE BPL INCRET ;RETURN IF NO ERROR CPY #BRKABT ;BREAK TYPED? BEQ CIOC10 JMP IOCERR ;COMMON ERROR HANDLER CIOC10: JMP ABORT ;ABORT I/O - RETURN TO TOP LEVEL ; CLOSE PRINTER IOCB CLOSEP: LDX PIOCB ;SETUP IOCB INDEX BEQ INCRET ;RETURN IF NONE ; CLR PIOCB ;FLAG NO PRINTER LDA #0 STA PIOCB ; LDA #CLOSE ;CLOSE COMMAND BNE CIOC ; INVOKE CIO PDEV: ; .ASCII "P:" .BYTE "P:",ATEOL ;GENERAL BREAKPOINT ROUTINES ;ROUTINE TO REMOVE BREAKPOINTS REMB: LDX #MAXBP-1 ;COUNT OF THINGS TO DO REMB5: LDA BPINS,X ;GET INSTR OR ZERO BEQ REMB10 ;NO BP IF ZERO JSR SETA ;SET UP ADDRS STA (INBUF),Y ;STORE INSTR REMB10: DEX BPL REMB5 ;LOOP OVER ALL RTS ;RETURN ;SETUP ADDRS OF GIVEN BREAKPOINT FOR INDIRECT ;RETURNS INBUF WITH BPLOC,X , Y := 0 ;PRESERVES AC SETA: LDY BPLOCL,X ;GET LOW ADDRS BYTE STY INBUF ;USE THIS AS TEMP LDY BPLOCH,X ;GET HIGH ADDRS BYTE STY INBUF+1 LDY #0 ;SET FOR GLOBAL INDIRECT RTS ;RETURN ;ROUTINE TO INSERT BREAKPOINTS INSB: LDX #MAXBP-1 ;DO ALL INSB5: LDA BPINS,X ;SEE IF ACTIVE BEQ INSB10 ;SKIP IF NO BP JSR SETA ;SET UP ADDRS LDA (INBUF),Y ;GET OLD INSTR STA BPINS,X ;SAVE OLD INSTR LDA #0 ;PUT BREAK IN PLACE STA (INBUF),Y ;... INSB10: DEX BPL INSB5 ;LOOP TILL DONE RTS ;RETURN ;INTERUPT SERVICES ;IRQ - INSTRUCTION OR ACTUAL APPLICATION INT. BREAK: PLA ;AC IS ON STACK STA AC ;SAVE ACCUM PLA ;PROCESSOR STATUS STA PS STY YREG ;SAVE INDEX REGS STX XREG PLA ;PC LOW SEC ;DECREMENT PC TO REAL LOC SBC #2 ;ADJUST PC FOR ACTUAL BP LOC BREAK10: STA PRPC ;SAVE HERE FOR $P STA POINT ;SAVE HERE FOR EXAMINE PLA ;PC HIGH BCS BREAK20 ;CHECK BORROW SBC #0 ;ADJUST BY 1 BREAK20: STA PRPC+1 STA POINT+1 TSX ;GET STACK PNTR STX SP ; SAVE IT AWAY JSR REMB ;REMOVE BREAKPOINTS NOW LDX #MAXBP ;SEARCH FOR BPN BREAK25: LDA BPINS-1,X ;ACTIVE BP? BEQ BREAK30 ;NO - SKIP TO NEXT LDA PRPC+1 ;GET PC HIGH CMP BPLOCH-1,X ;MATCH? BEQ BREAK35 ;YES - TRY FOR LOW BREAK30: DEX ;STEP TO NEXT BNE BREAK25 ; MORE TO DO STX BPN ;SIGNAL NO B.P. BEQ BRKX ;NONE FOUND (MAYBE PANIC) ;.. ;.. BREAK35: LDA PRPC ;GET PC LOW CMP BPLOCL-1,X ;MATCH? BNE BREAK30 ;NO - KEEP LOOKING ;ACTUAL BPN IN X STX BPN ;SAVE BPN LDA BPCNT-1,X ;BREAT THIS TIME? (0) BEQ BRKX ;BREAK IF ZERO DEC BPCNT-1,X ;COUNT THIS TIME BEQ BRKX ; AND DO AUTO PROC (IF .NE. 0) ; CLR SNGLF ; NOT SINGLE STEP LDA #0 STA SNGLF ; ; SETXA IXCT ;EXIT THROUGH HERE LDX #IXCT&$FF LDA #IXCT^ ; BRKRTI: PHA ;SAVE HIGH PC TXA ;GET LOW PHA ;SAVE IT TOO LDA PS PHA ;CURRENT PROCESSOR STATUS RTI ;DISMISS TO ROUTINE ;HERE TO ENTER BREAKPOINT - CLEAR SINGLE STEP FLAG BRKX: ; CLR SNGLF ; CLEAR SS FLAG LDA #0 STA SNGLF ; ; SETXA DOBRK LDX #DOBRK&$FF LDA #DOBRK^ ; BNE BRKRTI ;EXIT INT TO DOBRK DOBRK: JSR CRLFS ;PUT OUT A CR/LF LDA #'B ;PRINT BN;ADDRS JSR OUTSCH LDA BPN ;MAYBE 0 JSR HEXSTA ;TYPE LOW 4 BITS LDA #'; JSR OUTSCH JMP LFDS1 ;GO PRINT OUT ADDRESS AND INSTR. BRKY: ; MOV2 POINT,PRPC ;SINGLE STEP ENTRY - POINT HAS PC LDA POINT STA PRPC LDA POINT+1 STA PRPC+1 ; LDA SNGLF ;WAS THIS SINGLE STEP? BNE DOBRK ; SIMULATE BREAK IF $X JMP GO2 ;ELSE - JUST PROCEED ; .SBTTL 6502 DISASSEMBLER DSMBL: JSR CALCAD ;CALCULATE EFFECTIVE ADDRESS PHA ;SAVE MNEMONIC TABLE INDEX PROP: LDA (POINT),Y ;GET OP AND PRINT IT JSR PRTSBY LDX #$1 ;ONE SPACE PROP10: JSR PRBL2 CPY LENGTH ;PRINT INSTR (1 TO 3 BYTES) INY ; IN A 12-CHAR FIELD BCC PROP LDX #$3 ;CHAR COUNT FOR MNEMONIC PRINT CPY #$4 BCC PROP10 PLA ;RECOVER MNEMONIC INDEX TAY LDA MNEML,Y STA LMNEM ;FETCH 3-CHAR MNEMONIC LDA MNEMR,Y ; (PACKED IN 2 BYTES) STA RMNEM PRMN1: LDA #$0 LDY #$5 PRMN2: ASL RMNEM ROL LMNEM ;SHIFT 5 BITS OF CHAR INTO A ROL A ; (CLEARS CARRY) DEY BNE PRMN2 ADC #$3F ;ADD '?' OFFSET JSR OUTSCH DEX BNE PRMN1 JSR PRBLNK ;PRINT 3 BLANKS LDX #$6 ;COUNT FOR 6 PRINT FORMAT BITS PRADR1: CPX #$3 BNE PRADR3 ;IF X=3 THEN PRINT ADDRESS VAL LDY LENGTH BEQ PRADR3 ;NO PRINT IF LENGTH=0 LDA PFRMT CMP #$E8 ;HANDLE REL ADDRESSING MODE BNE PRADR2 ;IF NOT DO NOT ADJUST NUMBER OF BYTES INY ;IF RELATIVE BRANCH PRINT 2 BYTES ; CLR PFRMT ;CLEAR PFRMT LDA #0 STA PFRMT ; PRADR2: LDA INBUF-1,Y ;SPECIAL (PRINT TARGET ADDRS) JSR PRTSBY ;OUTPUT 1 OR 2 BYTE ADDRS DEY ; MSB FIRST BNE PRADR2 PRADR3: ASL PFRMT ;TEST NEXT PRINT FORMAT BIT BCC PRADR4 ;IF 0, DON'T PRINT LDA CHAR1-1,X ; CORRESPONDING CHARS JSR OUTSCH ;OUTPUT 1 OR 2 CHARS LDA CHAR2-1,X ; (IF CHAR FROM CHAR2 IS 0, BEQ PRADR4 ; DON'T OUTPUT IT) JSR OUTSCH PRADR4: DEX BNE PRADR1 RTS ;SET UP LENGTH, PFRMT AND EFFECTIV ADDRESS ; RETURNS INDEX INTO MNEMONIC TABLES IN A AND 0 IN Y CALCAD: LDY #0 ;SET UP FOR INDEXING STY INBUF+1 ;ZERO HIGH BYTE OF ADDRESS IN CASE ONLY ONE BYTE LDA (POINT),Y ;GET OPCODE TAY ;SAVE IN Y LSR A ; EVEN/ODD TEST BCC IEVEN LSR A ; TEST B1 BCS IERR ; XXXXXX11 INSTR INVALID CMP #$22 BEQ IERR ; 10001001 INSTR INVALID AND #$7 ;MASK 3 BITS FOR ADDRS MODE ORA #$80 ; ADD INDEXING OFFSET. IEVEN: LSR A ;LSB INTO CARRY FOR TAX ; LEFT/RIGHT TEST BELOW. LDA MODE1,X ;INDEX INTO ADDRS MODE TABLE BCS RTMODE ;IF CARRY SET USE LSD FOR LSR A ; PRINT FORMAT INDEX. LSR A LSR A LSR A ; IF CARRY CLEAR, USE MSD RTMODE: AND #$F ;MASK FOR 4-BIT INDEX BNE GETFMT ; 0 FOR INVALID OPCODES IERR: LDY #$80 ;SUBSTITUTE $80 FOR INVALID OP. LDA #$0 ;SET PRINT FORMAT TO 0 GETFMT: TAX LDA MODE2,X ;INDEX INTO PRINT FORMAT TABLE STA PFRMT ;SAVE FOR ADDRESS FIELD FORMAT AND #$3 ;MASK 2-BIT LENGTH 0 = 1-BYTE, STA LENGTH ; 1 = 2-BYTE, 2 = 3-BYTE. TYA ;RESTORE OP CODE PHA ;SAVE OPCODE ON STACK LDY LENGTH ;GET LENGTH BEQ GETFMT10 ;IF ZERO SET CURRENT ADDRESS IN INBUF FOR TAB LDA (POINT),Y ;GET FIRST BYTE OF ADDRESS CPY #1 ;IS IT A 2 BYTE INSTRUCTION BNE GETFMT20 ;NO GO PRINT BOTH BYTES CPX #13 ;WAS INDEX TO MODE2 FOR RELATIVE BNE GETFMT30 ;NO GO DO JUST ONE BYTE JSR RELADR ;GO CALCULATE RELATIVE ADDRESS STY INBUF+1 ;SAVE HIGH ORDER BYTE TXA ;GET LOW ORDER BYTE BACK JMP GETFMT30 ;GO FINISH UP GETFMT10: LDA POINT+1 ;GET HIGH ORDER BYTE OF ADDRESS STA INBUF+1 ;AND SAVE IT LDA POINT ;GET LOW BYTE JMP GETFMT30 ;GO SAVE IT AND FINISH GETFMT20: STA INBUF+1 ;SAVE HIGH BYTE OF ADDRESS DEY ;SET TO GET LOW ORDER BYTE LDA (POINT),Y ;GET LOW BYTE GETFMT30: STA INBUF ;SAVE LOW BYTE OF ADDRESS PLA ;GET OPCODE BACK TAY ;AND SAVE IT IN Y AND #$8F ;MASK IT FOR 1XXX1010 TEST TAX ; AND SAVE IT. TYA ;OPCODE AGAIN LDY #$3 CPX #$8A BEQ GETFMT60 GETFMT40: LSR A BCC GETFMT60 ;FORM INDEX INTO MNEMONIC TABLE LSR A GETFMT50: LSR A ; 1XXX1010 -> 00101XXX ORA #$20 ; XXXYYY01 -> 00111XXX DEY ; XXXYYY10 -> 00110XXX BNE GETFMT50 ; XXXYY100 -> 00100XXX INY ; XXXXX000 -> 000XXXXX GETFMT60: DEY BNE GETFMT40 RTS ;HERE TO HANDLE RELATIVE BRANCH ADDRS RELADR: JSR PCADJ3 ;PCL,H + DISPL + 1 TO A,Y TAX INX BNE RELADR10 ; +1 TO X,Y INY RELADR10: RTS ;ADD LENGTH TO POINT PCADJ: LDA LENGTH ;0=1-BYTE, 1=2-BYTE, 2=3-BYTE SEC PCADJ3: LDY POINT+1 TAX ;TEST DISPL SIGN (FOR REL BPL PCADJ310 ; BRANCH). EXTEND NEG DEY ; BY DECREMENTING PCH. PCADJ310: ADC POINT BCC PCADJ320 ;PCL+LENGTH (OR DISPL) +1 TO A. INY ;CARRY INTO Y (PCH) PCADJ320: RTS ;TABLES MODE1: .BYTE $40 .BYTE $2 .BYTE $45 .BYTE $3 .BYTE $D0 .BYTE $8 .BYTE $40 .BYTE $9 .BYTE $30 ;XXXXXXZ0 INSTRS. .BYTE $22 .BYTE $45 ; Z=0, LEFT HALF-BYTE .BYTE $33 ; Z=1, RIGHT HALF-BYTE .BYTE $D0 .BYTE $8 .BYTE $40 .BYTE $9 .BYTE $40 .BYTE $2 .BYTE $45 .BYTE $33 .BYTE $D0 .BYTE $8 .BYTE $40 .BYTE $9 .BYTE $40 .BYTE $2 ;(WAS 0) .BYTE $45 ;(WAS 40) .BYTE $B3 ;(WAS B0) .BYTE $D0 .BYTE $8 ;(WAS 0) .BYTE $40 .BYTE $9 ;(WAS 0) .BYTE $0 .BYTE $22 .BYTE $44 .BYTE $33 .BYTE $D0 .BYTE $8C .BYTE $44 .BYTE $0 .BYTE $11 .BYTE $22 .BYTE $44 .BYTE $33 .BYTE $D0 .BYTE $8C .BYTE $44 .BYTE $9A .BYTE $10 .BYTE $22 .BYTE $44 .BYTE $33 .BYTE $D0 .BYTE $8 .BYTE $40 .BYTE $9 .BYTE $10 .BYTE $22 .BYTE $44 .BYTE $33 .BYTE $D0 .BYTE $8 .BYTE $40 .BYTE $9 .BYTE $62 .BYTE $13 ;YYXXXZ01 INSTRS. .BYTE $78 .BYTE $A9 MODE2: .BYTE $0 ;ERR .BYTE $21 ;IMM .BYTE $1 ;Z-PAG (WAS 81) .BYTE $2 ;ABS (WAS 82) .BYTE $0 ;IMPL .BYTE $80 ;ACC (WAS 0) .BYTE $59 ;(Z-PAG,X) .BYTE $4D ;(Z-PAG),Y .BYTE $11 ;Z-PAG,X (WAS 91) .BYTE $12 ;ABS,X (WAS 92) .BYTE $6 ;ABS,Y (WAS 86) .BYTE $4A ;(ABS) .BYTE $5 ;Z-PAG,Y (WAS 85) .BYTE $1D ;REL (WAS 9D) CHAR1: .BYTE ', ;COMMA .BYTE ') ;RPAREN .BYTE ', ;COMMA .BYTE '# ;SHARP .BYTE '( ;LPAREN .BYTE 'A ;(WAS '$) CHAR2: .BYTE 'Y .BYTE 0 ;NULL .BYTE 'X .BYTE 0 ;(WAS '$) .BYTE 0 ;(WAS '$) .BYTE 0 MNEML: .BYTE $1C ;XXXXX000 INSTRS. .BYTE $8A .BYTE $1C .BYTE $23 .BYTE $5D .BYTE $8B .BYTE $1B .BYTE $A1 .BYTE $9D .BYTE $8A .BYTE $1D .BYTE $23 .BYTE $9D .BYTE $8B .BYTE $1D .BYTE $A1 .BYTE $0 .BYTE $29 .BYTE $19 .BYTE $AE .BYTE $69 .BYTE $A8 .BYTE $19 .BYTE $23 .BYTE $24 .BYTE $53 .BYTE $1B .BYTE $23 .BYTE $24 .BYTE $53 .BYTE $19 .BYTE $A1 .BYTE $0 ;XXXYY100 INSTRS .BYTE $1A .BYTE $5B .BYTE $5B .BYTE $A5 .BYTE $69 .BYTE $24 .BYTE $24 .BYTE $AE ;1XXX1010 INSTRS. .BYTE $AE .BYTE $A8 .BYTE $AD .BYTE $29 .BYTE $0 .BYTE $7C .BYTE $0 .BYTE $15 ;XXXYYY10 INSTRS. .BYTE $9C .BYTE $6D .BYTE $9C ;(WAS 0) .BYTE $A5 .BYTE $69 .BYTE $29 .BYTE $53 .BYTE $84 ;XXXYYY01 INSTRS. .BYTE $13 .BYTE $34 .BYTE $11 .BYTE $A5 .BYTE $69 .BYTE $23 .BYTE $A0 MNEMR: .BYTE $D8 ;XXXXX000 INSTRS. .BYTE $62 .BYTE $5A .BYTE $48 .BYTE $26 .BYTE $62 .BYTE $94 .BYTE $88 .BYTE $54 .BYTE $44 .BYTE $C8 .BYTE $54 .BYTE $68 .BYTE $44 .BYTE $E8 .BYTE $94 .BYTE $0 .BYTE $B4 .BYTE $8 .BYTE $84 .BYTE $74 .BYTE $B4 .BYTE $28 .BYTE $6E .BYTE $74 .BYTE $F4 .BYTE $CC .BYTE $4A .BYTE $72 .BYTE $F2 .BYTE $A4 .BYTE $8A .BYTE $0 ;XXXYY100 INSTRS. .BYTE $AA .BYTE $A2 .BYTE $A2 .BYTE $74 .BYTE $74 .BYTE $74 .BYTE $72 .BYTE $44 ;1XXX1010 INSTRS. .BYTE $68 .BYTE $B2 .BYTE $32 .BYTE $B2 .BYTE $0 .BYTE $22 .BYTE $0 .BYTE $1A ;XXXYYY10 INSTRS. .BYTE $1A .BYTE $26 .BYTE $26 ;(WAS 0) .BYTE $72 .BYTE $72 .BYTE $88 .BYTE $C8 .BYTE $C4 .BYTE $CA .BYTE $26 .BYTE $48 .BYTE $44 .BYTE $44 .BYTE $A2 .BYTE $C8 ;SPECIAL SYMBOL TABLE LGCH: .BYTE '/ ;SLASH .BYTE '% ;PERCENT .BYTE '= ;EQUAL SIGN .BYTE '' ;QUOTE .BYTE ', ;COMMA .BYTE '. ;DOT .BYTE ASESC ;ESCAPE .BYTE ATEOL ;CARRIAGE RETURN .BYTE '[ ;BRACKET .BYTE ATURW ;ATARI UP-ARROW .BYTE ATDRW ;ATARI DOWN-ARROW .BYTE ATLRW ;ATARI LEFT-ARROW .BYTE ATRRW ;ATARI RIGHT-ARROW MAXL = *-LGCH-1 ;DISPATCH FOR % CONTSTRUCTS LGPC: .BYTE 'X ;X REGISTER .BYTE 'Y ;Y REGISTER .BYTE 'A ;ACCUMULATOR .BYTE 'S ;STACK .BYTE 'F ;PROCESSOR STATUS MAXS = *-LGPC-1 ;THE FOLLOWING ARE ALL PAGE 0 VARIABLES PERAD: .BYTE XREG ;ADDRS OF X .BYTE YREG ;ADDRS OF Y .BYTE AC ;ADDRS OF ACCUM .BYTE SP ;ADDRS OF STACK PNTR .BYTE PS ;ADDRS OF STATUS ;SPECIAL SYMBOL DISPATCH TABLE LDISP: .WORD SLSH-1 ;SLASH - OPEN SYMBOLIC .WORD PERC-1 ;PERCENT - SPECIAL REG .WORD TOC-1 ;EQUAL - TYPE OCTAL .WORD QUOTE-1 ;QUOTE - TYPE OUT ASCII .WORD COMMA-1 ;COMMA - SAVE STARTING ADDRESS .WORD DOT-1 ;DOT - USE CURRENT LOC .WORD ESC-1 ;ESCAPE - MORE FOLLOWS .WORD CRET-1 ;CARRIAGE RETURN - CLOSE REG .WORD BRAKET-1 ;BRACKET - OPEN REG (HEX) .WORD BACK-1 ;ATARI ARROWS (PREV LOC) .WORD LFD-1 ; (NEXT LOC) .WORD UNTAB-1 ; POP PC STACK .WORD TAB-1 ; PUSH PC - OPEN EA ;DISPATCH CHARACTER TABLES DISP: .WORD ASCII-1 ;$A - ASSIGN ASCII TO MEMORY .WORD BKPT-1 ;$B - SET BP .WORD ERR-1 ;$C - .WORD TODOS-1 ;$D - XFER TO DOS .WORD ERR-1 ;$E - .WORD FIND-1 ;$F - FIND BYTE .WORD GO-1 ;$G - GO .WORD HDUMP-1 ;$H - HEX DUMP TO TTY .WORD INIT-1 ;$I - INITALIZE MEMORY .WORD ERR-1 ;$J - .WORD ERR-1 ;$K - .WORD PNTSEL-1 ;$L - TOGGLE PRINTER .WORD MOVE-1 ;$M - MOVE A BLOCK OF MEMORY .WORD ERR-1 ;$N - .WORD OFFSET-1 ;$O - CALCULATE BRANCH OFFSET .WORD PROC-1 ;$P - PROCEED .WORD DISASS-1 ;$Q - DISASSEMBLE .WORD RDSECT-1 ;$R - READ DISK .WORD SEARCH-1 ;$S - SEARCH FOR ADDRESS .WORD TYPE-1 ;$T - TYPE OUT MEMORY IN ASCII .WORD SETU-1 ;$U - SET DISK UNIT .WORD ERR-1 ;$V - .WORD WRSECT-1 ;$W - WRITE DISK .WORD EXEC-1 ;$X - SINGLE STEP .WORD ERR-1 ;$Y - .WORD ZERO-1 ;$Z - ZERO MEMORY ;NUMBER OF ARGUMENTS TABLE $FF=NONE, $0=1, $1=2, $80=NONE OR ONE ARGNUM: .BYTE $00 ;$A - ASSIGN ASCII TO MEMORY .BYTE $80 ;$B - SET BP .BYTE $01 ;$C - .BYTE $FF ;$D - JUMP TO DOS .BYTE $FF ;$E - .BYTE $01 ;$F - FIND BYTE .BYTE $00 ;$G - GO .BYTE $01 ;$H - HEX DUMP TO TTY .BYTE $01 ;$I - INITALIZE MEMORY .BYTE $FF ;$J - .BYTE $FF ;$K - .BYTE $00 ;$L - TOGGLE PRINTER .BYTE $01 ;$M - MOVE A BLOCK OF MEMORY .BYTE $FF ;$N - .BYTE $01 ;$O - CALCULATE BRANCH OFFSET .BYTE $80 ;$P - PROCEED .BYTE $01 ;$Q - DISASSEMBLE .BYTE $01 ;$R - READ DISK .BYTE $01 ;$S - SEARCH FOR ADDRESS .BYTE $01 ;$T - TYPE OUT MEMORY IN ASCII .BYTE $00 ;$U - SELECT DISK UNIT .BYTE $FF ;$V - .BYTE $01 ;$W - WRITE DISK .BYTE $FF ;$X - SINGLE STEP .BYTE $FF ;$Y - .BYTE $01 ;$Z - ZERO MEMORY ; ---------------------------------------------------------------- ; This section of stuff added by jrd. ; get a keyboard char KGETCH: JSR KBCALL RTS KBCALL: LDA KEYBDV+5 ; getbyte-1^ PHA LDA KEYBDV+4 ; getbyte-1\ PHA RTS ; 'call' it ; output a line (in X/Y) to screen PUTLIN: PHA LDA INBUF PHA LDA INBUF+1 PHA STX INBUF STY INBUF+1 LDY #0 PUTLIN1: LDA (INBUF),Y PHA JSR OUTSCH PLA CMP #ATEOL BEQ PUTLIN2 INY BNE PUTLIN1 PUTLIN2: PLA STA INBUF+1 PLA STA INBUF PLA RTS ; ---------------------------------------------------------------- ; END START *=$2E0 .WORD START