0100 .OPT NO LIST 0110 *= $2000 0120 ; 0130 ;----------------------------- 0140 ;HUDSON'S DEBUG PROGRAM (HBUG) 0150 ;----------------------------- 0160 ; 0170 DOSVEC = $0A ;DOS run address 0180 BRKKEY = $11 ;BREAK key status 0190 STACK = $0100 ;hardware stack 0200 VBREAK = $0206 ;BRK inst vector 0210 RUNAD = $02E0 ;prog run addr 0220 ICCOM = $0342 ;CIO command 0230 ICBADR = $0344 ;CIO buffer address 0240 ICBLEN = $0348 ;CIO buffer length 0250 ICAUX1 = $034A ;CIO aux. byte 1 0260 ICAUX2 = $034B ;CIO aux. byte 2 0270 NMIEN = $D40E ;interrupt enable 0280 CIOV = $E456 ;CIO entry point 0290 SETVBV = $E45C ;VBLANK setup 0300 XITVBV = $E462 ;VBLANK exit 0310 ; 0320 ;Page zero usage 0330 ; 0340 CML = $D4 ;my two-byte 0350 CMH = $D5 ;address work area 0360 ; 0370 ;------------------- 0380 ;Program entry point 0390 ;------------------- 0400 ; 0410 HBUG 0420 LDA #$00 ;turn off... 0430 STA NMIEN ;interrupts 0440 STA EXEC ;and execute flag 0450 TSX ;get stack pointer 0460 STX USERS ;put in user area 0470 LDA VBREAK ;save old BRK 0480 STA BRKSVL ;vector in my 0490 LDA VBREAK+1 ;work area 0500 STA BRKSVH ;for later 0510 LDA # >BRKHAN ;now point to 0520 STA VBREAK+1 ;my BRK inst. 0530 LDA # VBI ;set up 0560 LDY # MYBUFF ;buffer 0680 STA ICBADR+1 0690 LDA #5 ;GET RECORD command 0700 STA ICCOM 0710 LDA #$7F ;my buffer's 0720 STA ICBLEN ;length 0730 STX ICBLEN+1 0740 JSR CIOV ;get input! 0750 BMI INPT2 ;go back if error 0760 ; 0770 ;This section 'squishes' all the 0780 ;spaces out of the input line. 0790 ; 0800 LDX #0 ;first find end 0810 FINDBE LDA MYBUFF,X ;of line 0820 CMP #$9B ;CR? 0830 BEQ GOTEND ;yes! 0840 INX ;no, next char. 0850 BPL FINDBE ;keep looking! 0860 GOTEND CPX #0 ;CR first char? 0870 BEQ INPUT ;yes, try again. 0880 STX ENDPTR ;save end index 0890 LDX #0 ;start w/1st char 0900 SQUISH LDA MYBUFF,X ;get the character 0910 CMP #32 ;space? 0920 BNE NOSQSH ;no! 0930 TXA ;move index 0940 TAY ;to Y register 0950 SQSHLP LDA MYBUFF+1,Y ;shift all 0960 STA MYBUFF,Y ;characters 0970 INY ;back to remove 0980 CPY ENDPTR ;the space. 0990 BNE SQSHLP 1000 DEC ENDPTR ;line 1 shorter 1010 JMP SQUISH ;keep squishing! 1020 NOSQSH INX ;next char 1030 CPX ENDPTR ;end? 1040 BNE SQUISH ;no, keep going! 1050 LDA ENDPTR ;was line all spaces? 1060 BNE GETCMD ;no, get command 1070 JMP INPUT ;get another input! 1080 ; 1090 ;Now find command & process it 1100 ; 1110 GETCMD LDA #0 ;start with 1st 1120 STA CMDPTR ;command. 1130 CHKCMD LDY CMDPTR ;get command pointer 1140 LDA CMDST+1,Y ;get index of 1150 STA CEND ;command text end 1160 LDX CMDST,Y ;and start. 1170 LDY #0 ;point to 1st char 1180 CMDCMP LDA MYBUFF,Y ;is buffer char 1190 CMP CMDTXT,X ;= command char? 1200 BNE NOTCMD ;no! 1210 INY ;yes, try next char 1220 INX ;next command char 1230 CPX CEND ;end of command? 1240 BNE CMDCMP ;no, keep comparing! 1250 LDA CMDPTR ;yes, mult command 1260 ASL A ;index by 2 to point 1270 TAX ;into jump table 1280 LDA CMDADR,X ;get command routine 1290 STA CMDJMP ;address low byte 1300 LDA CMDADR+1,X ;and high byte 1310 STA CMDJMP+1 ;and save. 1320 JMP (CMDJMP) ;jump to routine! 1330 NOTCMD INC CMDPTR ;try next command 1340 LDA CMDPTR ;get pointer 1350 CMP #7 ;more commands? 1360 BNE CHKCMD ;yes! 1370 GOTERR JSR ERRMSG ;oops! bad command! 1380 JMP INPUT ;get another input 1390 ; 1400 ;This section handles the DOS 1410 ;command. It shuts off the HBUG 1420 ;VBLANK and BRK vectors and JMPs 1430 ;to DOS. 1440 ; 1450 GODOS LDA MYBUFF,Y ;get next char 1460 CMP #$9B ;CR? 1470 BEQ DOSOK ;yes, go to DOS 1480 JMP GOTERR ;no, invalid command! 1490 DOSOK LDX # >XITVBV ;point VBLANK 1500 LDY # BRKTXT ;BREAK text 1840 JSR PRINT ;print it 1850 JMP INPUT ;and get input 1860 ; 1870 ;Display registers (DR) 1880 ; 1890 SHOREG LDA MYBUFF,Y ;is next char 1900 CMP #$9B ;a CR? 1910 BEQ DROKAY ;yes, it's OK! 1920 JMP GOTERR ;otherwise ERROR 1930 DROKAY JSR SETREG ;get registers 1940 LDX # DRTXT ;DR text 1960 JSR PRINT ;print it 1970 JMP INPUT ;and get input 1980 ; 1990 ;Set up register disp area 2000 ; 2010 SETREG LDY #0 ;start w/user byte 0 2020 SETLP LDA USER,Y ;get data 2030 JSR BINHEX ;convert to hex 2040 LDX DRPTR,Y ;get its position 2050 LDA HEX1 ;get first digit 2060 STA DRTXT,X ;put in line 2070 LDA HEX2 ;get second digit 2080 STA DRTXT+1,X ;put in line 2090 INY ;next byte 2100 CPY #5 ;done 5? 2110 BNE SETLP ;not yet! 2120 RTS ;all done! 2130 ; 2140 ;Change registers (CR) 2150 ; 2160 CHGREG LDX #4 ;first copy user 2170 INITMP LDA USER,X ;registers 2180 STA TMPUSR,X ;to temporary 2190 DEX ;hold area 2200 BPL INITMP 2210 LDX #0 ;1st user byte 2220 CRSTRT LDA #0 ;zero out... 2230 STA BHOLD ;byte hold 2240 STA HDIG ;and digit count 2250 CRLOOK LDA MYBUFF,Y ;get input char 2260 CMP #$9B ;CR? 2270 BEQ STOTRY ;yes, all done. 2280 CMP #$2C ;comma? 2290 BEQ STOTRY ;yes, try store 2300 JSR CTOBIN ;convert it to binary 2310 JMP CRLOOK ;and do next one 2320 STOTRY LDA HDIG ;any digits? 2330 BEQ NXTCCK ;no, skip it! 2340 LDA BHOLD ;yes, save the byte 2350 STA TMPUSR,X ;in temporary table 2360 NXTCCK LDA MYBUFF,Y ;was this 2370 CMP #$9B ;a CR? 2380 BNE NXTCHR ;no, keep going. 2390 LDX #4 ;otherwise, 2400 SETUSR LDA TMPUSR,X ;copy the 2410 STA USER,X ;temporary table 2420 DEX ;back to the 2430 BPL SETUSR ;user registers 2440 JMP INPUT ;get another line 2450 NXTCHR INX ;next user register 2460 INY ;next character 2470 CPX #5 ;done 5 regs? 2480 BNE CRSTRT ;no, loop back. 2490 JMP GOTERR ;UH-OH! too many! 2500 ; 2510 ;Convert char. to binary # 2520 ; 2530 CTOBIN STX XHOLD ;save X register 2540 LDX #$0F ;set scan index 2550 HDSCAN CMP HEXDIG,X ;compare ASCII 2560 BEQ GOTHD ;got it! 2570 DEX ;next char 2580 BPL HDSCAN ;scan all 16 2590 JMP CBERR ;not in table! 2600 GOTHD ASL BHOLD ;shift current # 2610 ASL BHOLD ;left 4 times to 2620 ASL BHOLD ;multiply it by 2630 ASL BHOLD ;16 2640 TXA ;get this digit 2650 ORA BHOLD ;and add it to 2660 STA BHOLD ;the hold area. 2670 INC HDIG ;one more digit 2680 LDA HDIG ;are there more 2690 CMP #3 ;than 2? 2700 BCS CBERR ;yes--too big! 2710 LDX XHOLD ;restore X reg 2720 INY ;next buffer char 2730 RTS ;and exit 2740 CBERR PLA ;remove return addr 2750 PLA ;from stack 2760 JMP GOTERR ;and do error routine 2770 ; 2780 ;Display memory contents 2790 ; 2800 SHOMEM LDA MYBUFF,Y ;is character... 2810 CMP #$9B ;a CR? 2820 BNE GETSAD ;no, get address. 2830 LDA CML ;get last address 2840 CLC ;and add 8 to it 2850 ADC #8 ;since no address 2860 STA CML ;was specified 2870 LDA CMH 2880 ADC #0 2890 STA CMH 2900 SHOW8 LDA #0 ;show only 8 2910 STA COUNTH ;bytes 2920 LDA #7 2930 STA COUNTL 2940 JMP SHOWLN ;go show 'em! 2950 SMERR JMP GOTERR ;jump to err routine 2960 GETSAD JSR GET4 ;get 4-byte address 2970 LDX G4DIGS ;any digits found? 2980 BEQ SMERR ;no! 2990 LDX ADL ;save address 3000 STX CML ;in page zero 3010 LDX ADH ;work area 3020 STX CMH 3030 CMP #$9B ;CR after address? 3040 BEQ SHOW8 ;yes, show 8 bytes. 3050 CMP #$2C ;comma? 3060 BNE SMERR ;no, bad command 3070 INY ;next char 3080 JSR GET4 ;get end address 3090 LDX G4DIGS ;got any digits? 3100 BEQ SMERR ;no! 3110 CMP #$9B ;CR after end addr? 3120 BNE SMERR ;no! 3130 LDA ADL ;now subtract 3140 SEC ;end address 3150 SBC CML ;from start 3160 STA COUNTL ;to get number 3170 LDA ADH ;of bytes to 3180 SBC CMH ;display. 3190 STA COUNTH 3200 SHOWLN LDA #32 ;clear out 3210 LDX #44 ;display line 3220 CLRML STA SHOM1,X 3230 DEX 3240 BPL CLRML 3250 LDA #$1B ;and set up ESC 3260 LDX #14 ;characters 3270 SETESC STA ASCII,X ;in the ASCII 3280 DEX ;display area 3290 DEX 3300 BPL SETESC 3310 LDA CML ;convert the 3320 JSR BINHEX ;current address 3330 LDA HEX2 ;to ascii hex 3340 STA SHOM4 ;characters 3350 LDA HEX1 ;and put in 3360 STA SHOM3 ;the memory 3370 LDA CMH ;display line. 3380 JSR BINHEX ;this is done 3390 LDA HEX2 ;2 times, for 3400 STA SHOM2 ;the low and high 3410 LDA HEX1 ;bytes of the 3420 STA SHOM1 ;address 3430 LDY #0 ;start showing! 3440 BILDLN LDA (CML),Y ;get mem byte 3450 CMP #$9B ;CR? 3460 BEQ NO9B ;yes, don't show it! 3470 LDX ASCPOS,Y ;put in ASCII 3480 STA ASCII,X ;display area 3490 NO9B JSR BINHEX ;convert byte to hex 3500 LDX SMPOS,Y ;get position 3510 LDA HEX2 ;get low char 3520 STA SMDATA+1,X ;and store 3530 LDA HEX1 ;get high char 3540 STA SMDATA,X ;and store. 3550 INY ;next byte 3560 LDA COUNTL ;now decrement 3570 SEC ;the byte count 3580 SBC #1 ;by 1 3590 STA COUNTL 3600 LDA COUNTH 3610 SBC #0 3620 STA COUNTH 3630 BPL MORESM ;more? yes! 3640 JSR PDATA ;no more, print line 3650 JMP INPUT ;and get next command 3660 MORESM CPY #8 ;done 8 bytes? 3670 BNE BILDLN ;no, loop back 3680 JSR PDATA ;done 8, print 'em 3690 BPL NOSTOP ;no BREAK key 3700 JMP INPUT ;get next command 3710 NOSTOP LDA CML ;increment display 3720 CLC ;address by 8 3730 ADC #8 3740 STA CML 3750 LDA CMH 3760 ADC #0 3770 STA CMH 3780 JMP SHOWLN ;and loop back. 3790 ; 3800 ;Change memory contents (Cnnnn<) 3810 ; 3820 CHGMEM LDA MYBUFF,Y ;get char 3830 CMP #$3C ;'<'? 3840 BEQ CMDFLT ;yes, default address 3850 JSR GET4 ;get the address 3860 LDX G4DIGS ;got any digits? 3870 BEQ CMERR ;no! 3880 CMP #$3C ;next char '<'? 3890 BNE CMERR ;no! 3900 LDX ADL ;save the 3910 STX CML ;change memory 3920 LDX ADH ;address on 3930 STX CMH ;page zero. 3940 CMDFLT INY ;next buffer char 3950 LDX #0 ;1st memory byte 3960 CMSTRT LDA #0 ;zero out... 3970 STA BHOLD ;byte hold 3980 STA HDIG ;and digit count 3990 CMLOOK LDA MYBUFF,Y ;get char 4000 CMP #$9B ;CR? 4010 BEQ CMTRY ;yes, all done! 4020 CMP #$2C ;comma? 4030 BEQ CMTRY ;yes, store last byte 4040 JSR CTOBIN ;convert char to binary 4050 JMP CMLOOK ;and get next 4060 CMTRY LDA HDIG ;any digits? 4070 BEQ NEXTCM ;no! don't store 4080 STY YHOLD ;save Y register 4090 TXA ;move X... 4100 TAY ;to Y 4110 LDA BHOLD ;get byte to store 4120 STA (CML),Y ;and store it! 4130 LDY YHOLD ;get Y back 4140 NEXTCM LDA MYBUFF,Y ;get last char 4150 CMP #$9B ;was it CR? 4160 BNE NXTLOC ;no, continue 4170 JMP INPUT ;all done! 4180 NXTLOC INX ;next mem byte 4190 INY ;next input char 4200 JMP CMSTRT ;loop back! 4210 CMERR JMP GOTERR ;go to error routine 4220 ; 4230 ;Execute at address (Gnnnn) 4240 ; 4250 EXECUT JSR GET4 ;get the run address 4260 CMP #$9B ;is that all? 4270 BNE EXERR ;no! 4280 LDA G4DIGS ;got any digits? 4290 BEQ EXERR ;no! 4300 LDX USERS ;put user stack 4310 TXS ;pointer in S 4320 LDA USERP ;put user status 4330 PHA ;on stack 4340 LDX USERX ;set user X reg 4350 LDY USERY ;and user Y reg 4360 LDA USERA ;and accumulator 4370 INC EXEC ;set execute flag 4380 PLP ;get status off stack 4390 JMP (ADL) ;go to run address! 4400 EXERR JMP GOTERR ;go to error routine 4410 ; 4420 ;Get 4-character address 4430 ; 4440 GET4 LDA #0 ;zero out... 4450 STA ADL ;address low byte 4460 STA ADH ;address high byte 4470 STA G4DIGS ;digit count 4480 G4LOOP LDA MYBUFF,Y ;get char 4490 CMP #$9B ;CR? 4500 BEQ G4END ;yes, all done! 4510 CMP #$2C ;comma? 4520 BEQ G4END ;yes, all done! 4530 CMP #$3C ;'<'? 4540 BNE TESTIT ;no, check digit 4550 G4END RTS ;exit! 4560 TESTIT LDX #$0F ;set hex digit pointer 4570 G4SCAN CMP HEXDIG,X ;is it this char? 4580 BEQ GOTG4D ;yes! 4590 DEX ;try next hex digit 4600 BPL G4SCAN ;loop if more. 4610 G4ERR PLA ;discard return 4620 PLA ;address, 4630 JMP GOTERR ;show error. 4640 GOTG4D ASL ADL ;this code 4650 ROL ADH ;shifts the 4660 ASL ADL ;current address 4670 ROL ADH ;left 4 bits 4680 ASL ADL ;in order to 4690 ROL ADH ;multiply it 4700 ASL ADL ;by 16. 4710 ROL ADH 4720 TXA ;get this digit 4730 ORA ADL ;and add it to 4740 STA ADL ;the address. 4750 INC G4DIGS ;one more digit 4760 LDA G4DIGS ;how many total? 4770 CMP #5 ;more than 4? 4780 BCS G4ERR ;yes! error! 4790 INY ;ok, do next character 4800 JMP G4LOOP ;and loop back. 4810 ; 4820 ;Set up new graphics 0 screen 4830 ; 4840 NEWSCR CLD 4850 JSR NOIOCB ;close all IOCB's 4860 ; 4870 ;now open screen! 4880 ; 4890 LDX #0 4900 LDA # EADR 4930 STA ICBADR+1 4940 LDA #3 ;OPEN command 4950 STA ICCOM 4960 LDA #12 ;I/O 4970 STA ICAUX1 4980 STX ICAUX2 ;zero aux byte 4990 JSR CIOV ;open it! 5000 RTS ;and return. 5010 ; 5020 ;Close all IOCB's 5030 ; 5040 NOIOCB LDX #7 ;first close 5050 STX SAVEX ;all IOCB's. 5060 CLOOP LDA #12 ;CLOSE command 5070 STA ICCOM,X 5080 JSR CIOV ;close it! 5090 DEC SAVEX ;next IOCB 5100 LDX SAVEX ;more IOCB's? 5110 BPL CLOOP ;yes! 5120 RTS ;all done! 5130 ; 5140 ;Show HBUG prompt 5150 ; 5160 PROMPT LDX # HMSG ;HBUG message 5180 JMP PRINT ;and print it! 5190 ; 5200 ;Show error message 5210 ; 5220 ERRMSG LDA #$80 ;set high bit 5230 ORA MYBUFF,Y ;inverse the 5240 STA MYBUFF,Y ;invalid character 5250 LDX # ERRTXT ;error message 5270 JSR PRINT ;print it 5280 LDX # MYBUFF ;input buffer 5300 JMP PRINT ;print it, too! 5310 ; 5320 ;Print memory display line 5330 ; 5340 PDATA LDX # SHOM1 ;display line 5360 JMP PRINT ;print it! 5370 ; 5380 ;Print carriage return only 5390 ; 5400 PRTCR LDX # CR ;fall thru to print 5420 ; 5430 ;General-use print routine 5440 ; 5450 PRINT STX ICBADR ;save print area lo 5460 STY ICBADR+1 ;and high 5470 LDX #0 ;zero X reg. 5480 LDA #9 ;PUT RECORD command 5490 STA ICCOM 5500 LDA #$7F ;set up... 5510 STA ICBLEN ;buffer length 5520 STX ICBLEN+1 5530 JSR CIOV ;print it! 5540 RTS ;and exit. 5550 ; 5560 ;Binary-to-hex converter 5570 ; 5580 BINHEX PHA ;save byte 5590 AND #$0F ;get low 4 bits 5600 TAX ;put in index 5610 LDA HEXDIG,X ;lookup hex 5620 STA HEX2 ;and save 5630 PLA ;get byte again 5640 LSR A ;shift right 5650 LSR A ;4 times 5660 LSR A ;to get 5670 LSR A ;high 4 bits 5680 TAX ;put in index 5690 LDA HEXDIG,X ;lookup hex 5700 STA HEX1 ;and save 5710 RTS ;all done! 5720 ; 5730 ;Handle 6502 BRK interrupt 5740 ; 5750 BRKHAN LDA EXEC ;executing? 5760 BNE SAVREG ;yes! 5770 PLA ;no, restore accum. 5780 RTI ;and return from int. 5790 SAVREG CLD ;no decimal mode! 5800 LDA #0 ;reset the 5810 STA EXEC ;executing flag 5820 STX USERX ;save X 5830 STY USERY ;and Y 5840 PLA 5850 STA USERA ;and accumulator 5860 PLA 5870 STA USERP ;and status reg. 5880 PLA 5890 SEC ;now get program 5900 SBC #2 ;counter from stack 5910 STA USRPCL ;and subtract 2 5920 PLA ;to get BREAK 5930 SBC #0 ;address. 5940 STA USRPCH 5950 STX XHOLD ;save X reg. 5960 TSX ;now store stack pntr 5970 STX USERS ;in the user area. 5980 LDX XHOLD ;restore X 5990 CLI ;clear interrupt 6000 JMP SHOBRK ;and show break info 6010 ; 6020 ;Handle BREAK key in VBI 6030 ; 6040 VBI LDA EXEC ;executing? 6050 BEQ NOBKEY ;no! 6060 LDA BRKKEY ;BREAK pressed? 6070 BNE NOBKEY ;no! 6080 LDA #$80 ;reset BREAK 6090 STA BRKKEY ;press flag 6100 LDA #0 ;and 6110 STA EXEC ;execute flag 6120 TSX ;get stack pntr 6130 LDA STACK+1,X ;get Y register 6140 STA USERY ;and save it 6150 LDA STACK+2,X ;get X register 6160 STA USERX ;and save it 6170 LDA STACK+3,X ;get accumulator 6180 STA USERA ;and save it 6190 LDA STACK+4,X ;get status register 6200 STA USERP ;and save it 6210 LDA STACK+5,X ;get program 6220 STA USRPCL ;counter 6230 LDA STACK+6,X ;and 6240 STA USRPCH ;store it! 6250 TXA ;move stack pntr 6260 CLC ;to A, add 6 to 6270 ADC #6 ;get true value 6280 STA USERS ;and save it! 6290 LDA # >SHOBRK ;change return 6300 STA STACK+6,X ;address to 6310 LDA #