10
20
30
40 :
50 kbd%=3
60 OSBYTE=&FFF4:OSARGS=&FFDA
70 OSASCI=&FFE3:OSNEWL=&FFE7:OSWRCH=&FFEE
80 EVNTV=&220:KEYV=&228:INSV=&22A
90 usb_D=&FCF8:usb_S=&FCF9
100 DIM mcode% &1000, L%-1
110 ver$="0.01":date$=" (28 May 2018)"
120 :
130 FOR pass%=0 TO 1
140 P%=&8000:O%=mcode%
150 opt%=pass%*3+4
160 [OPT opt%
170 .rombase
180 EQUB &00:EQUW RelocTable
190 JMP Service
200 EQUB &82:EQUB copyright-rombase
210 .ROMTitle
220 EQUB VALver$:EQUS "USB Support"
230 EQUB &00:EQUS ver$+date$
240 .copyright
250 EQUB &00:EQUS "(C)J.G.Harston"
260 EQUB &00
270 :
280 .Service
290 PHA :\ Save service number
300 CMP #&04:BNE P%+5:JMP ServCmd04 :\ *command
310 CMP #&09:BNE P%+5:JMP ServCmd09 :\ *help
320 CMP #&28:BNE P%+5:JMP ServCmd28 :\ *configure
330 CMP #&29:BNE P%+5:JMP ServCmd29 :\ *status
340 PLA:RTS
350 :
360 .ServCmd04:.ServCmd09
370 LSR A :\ Convert service call number to bitmap
380 .ServCmd28:.ServCmd29
390 PHA
400 \ 04 -> 02 -> 02 command xxxx0010
410 \ 09 -> 04 -> 04 help xxxx0100
420 \ 28 -> 28 -> 08 config xxxx1000
430 \ 29 -> 29 -> 09 status xxxx1001
440 \
450 LDX #0 :\ Point to start of table
460 STX &F5 :\ And set command number 0
470 LDA (&F2),Y :\ Get first character
480 CMP #&0D:BEQ ServCmdNull :\ *help<cr>, *status<cr>, *configure<cr>
490 CMP #&2E:BEQ ServCmdNull :\ *help . *status . *configure .
500 :
510 .ServCmdEntryLp
520 INC &F5 :\ Increment command number
530 PLA:PHA :\ Get search type bitmap
540 AND CmdTable,X:BEQ ServCmdSkip :\ Don't match for this call
550 INX :\ Point to start of command string
560 TYA:PHA :\ Save line pointer
570 :
580 .ServCmdCharLp
590 LDA (&F2),Y
600 CMP #ASC".":BEQ ServCmdDot :\ Abbreviation
610 AND #&5F :\ Force to upper case
620 CMP CmdTable,X:BNE ServCmdNext :\ No match, skip to next command
630 INX:INY :\ Step to next characters
640 LDA CmdTable,X
650 BPL ServCmdCharLp :\ Not end of table entry, loop back
660 LDA (&F2),Y
670 CMP #ASC"A":BCC ServCmdMatch :\ End of command string, command matches
680 .ServCmdNext
690 PLA:TAY :\ Restore line pointer
700 DEX :\ In case we are pointing to last+1 character
710 .ServCmdSkip
720 INX:LDA CmdTable,X
730 BPL ServCmdSkip :\ Step to next entry
740 AND #15:BNE ServCmdEntryLp :\ Not at end, check next entry
750 PLA :\ Drop command type
760 PLA:RTS :\ Restore and return unclaimed
770 :
780 .ServCmdDot
790 .ServCmdSkipSpc
800 INY :\ Step past dot
810 .ServCmdMatch
820 LDA (&F2),Y:CMP #ASC" "
830 BEQ ServCmdSkipSpc :\ And step past any spaces
840 PLA :\ Drop old line pointer
850 TSX:LDA #0:STA &102,X :\ Claim this call
860 .ServCmdNull
870 LDA &F5:ASL A:TAX :\ X=command offset, Carry Clear
880 .ServCmdDispatch
890 LDA CmdDispatch+1,X:STA &F7
900 LDA CmdDispatch+0,X:STA &F6
910 PLA:TAX:EOR #1:ADC #&D8:CMP #&01 :\ Convert command type, CC=Status
920 JSR JumpF6
930 PLA:RTS :\ Return claimed or unclaimed
940 :
950 \ On entry,
960 \ Flags set from A:
970 \ EQ = Status
980 \ PL = Status/Configure
990 \ MI = Help/Command
1000 \ (&F2),Y=>command line
1010 \ X=command type
1020 \
1030 .JumpF6
1040 JMP (&F6)
1050 .ServCallStatus
1060 PHA:PHA:CLC :\ Push command type onto stack
1070 JMP ServCmdDispatch :\ Jump to call *Status routines
1080 :
1090 .cmdUSB :\ *Help USB
1100 DEY
1110 .cmdNull
1120 CPX #4:BNE cmdHelp:JSR OSNEWL
1130 .cmdTitleLp
1140 LDA ROMTitle-3,X:BNE P%+4:LDA #ASC" "
1150 CMP #ASC"(":BEQ cmdTitleDone :\ Print ROM title
1160 JSR OSWRCH:INX:BNE cmdTitleLp
1170 .cmdTitleDone
1180 JSR OSNEWL:LDX #2 :\ X=2 - list commands
1190 LDA (&F2),Y:CMP #13:BNE cmdHelp
1200 RTS :\ No parameter, only display ROM title
1210 .cmdHelp
1220 TYA:PHA:TXA:PHA :\ Save Y=lineptr, X=command bitmap
1230 LDX #0:LDY #0 :\ Point to start of tables
1240 .cmdHelpLp1
1250 INY:INY :\ Step to next dispatch entry
1260 PLA:PHA :\ Get search type bitmap
1270 AND CmdTable,X:BEQ cmdHelpSkip :\ Don't match for this call
1280 AND #2:BEQ cmdHelpLp2
1290 JSR Pr2Spaces :\ Indent *Help list
1300 .cmdHelpLp2
1310 LDA CmdTable+1,X:BMI cmdHelpInfo
1320 JSR OSWRCH:INX:BNE cmdHelpLp2
1330 .cmdHelpInfo
1340 TXA:PHA:TYA:PHA :\ Save table index and command number
1350 TSX:LDA &103,X:AND #2:ASL A :\ Align syntax strings
1360 ADC &308:ADC #10:SBC &318:TAX
1370 .cmdHelpSpace
1380 JSR PrSpace:DEX:BNE cmdHelpSpace
1390 TSX:TXA:TAY
1400 LDA &103,Y :\ Command type
1410 LDX &101,Y :\ Dispatch table index
1420 LDY #0:JSR ServCallStatus :\ Call dispatcher to display info
1430 PLA:TAY:PLA:TAX :\ Get command number and index back
1440 DEX
1450 .cmdHelpSkip
1460 .cmdHelpSkipLp
1470 INX:LDA CmdTable,X
1480 BPL cmdHelpSkipLp :\ Step to next entry
1490 AND #15:BNE cmdHelpLp1 :\ Not at end, check next entry
1500 PLA:PLA:TAY:RTS
1510 :
1520 .CmdTable
1530 EQUB &84:EQUS "USB" :\ hlp
1540 EQUB &82:EQUS "USBDEVICES" :\ cmd
1550 EQUB &8B:EQUS "USBKBD" :\ cmd cfg sta
1560 EQUB &8B:EQUS "USBMOUSE" :\ cmd cfg sta
1570 EQUB &8B:EQUS "USBPRINT" :\ cmd cfg sta
1580 EQUB &82:EQUS "USBSTATUS" :\ cmd
1590 EQUB &80
1600 :
1610 .CmdDispatch
1620 EQUW cmdNull :\ <cr> or .
1630 EQUW cmdUSB :\ USB
1640 EQUW cmdDevices :\ USBDEVICES
1650 EQUW cmdKBD :\ USBKBD
1660 EQUW cmdMouse :\ USBMOUSE
1670 EQUW cmdPrint :\ USBPRINT
1680 EQUW cmdStatus :\ USBSTATUS
1690 :
1700 :
1710 .cmdPrint :LDX #128:BNE cmdDoIt
1720 .cmdMouse :LDX #64 :BNE cmdDoIt
1730 .cmdKBD :LDX #63
1740 .cmdDoIt
1750 BCC cmdStatus2 :\ *Status <command>
1760 PHA:TYA:BEQ cmdSyntax :\ Y=0, *help or *config. syntax requested
1770 LDA (&F2),Y :\ Save command type, get char from line
1780 CMP #13:BEQ cmdStatus1 :\ *command<cr> or *configure command<cr>
1790 JSR ScanOnOffName :\ Parse parameter OFF|ON|<num> to Y
1800 PLA:BMI cmdJump :\ *command <param>
1810 :
1820 : :\ *Configure <word> <param>
1830 TYA:PHA :\ Save <param>
1840 TXA:EOR #255:PHA :\ Mask to keep old bits
1850 JSR CMOSRead:TSX :\ Get my CMOS byte
1860 EOR &102,X:AND &101,X :\ Merge new setting into byte
1870 EOR &102,X:TAY
1880 PLA:PLA :\ Drop stacked bytes
1890 :
1900 .CMOSWrite :\ Write my CMOS byte
1910 LDX #19:LDA #162:JMP OSBYTE
1920 .CMOSRead :\ Read my CMOS byte
1930 CLC
1940 .CMOSRead1
1950 :\LDA &23D:\AND #&C0:\EOR #&80 :\ If keyboard not claimed, use 0
1960 :\TAY:\BEQ P%+5 :\ else use current setting
1970 LDY &23C:BCS CMOSRead2 :\ If CS or no CMOS, use current setting
1980 LDX #19:LDA #161:JSR OSBYTE
1990 .CMOSRead2
2000 TYA:RTS
2010 :
2020 .cmdJump
2030 TXA:ASL A
2040 BCC P%+5:JMP usbPRINT
2050 BPL P%+5:JMP usbMOUSE
2060 JMP usbKBD
2070 :
2080 .cmdSyntax
2090 PLA:CPX #64:BCS cmdSyntax2
2100 JSR PrText:EQUS "OFF|<num>":EQUB 13:EQUB 0:RTS
2110 .cmdSyntax2
2120 JSR PrText:EQUS "OFF|ON":EQUB 13:EQUB 0:RTS
2130 :
2140 .errBadConfigure
2150 JSR MkError
2160 EQUB 254:EQUS "Bad command":BRK
2170 :
2180 .cmdStatus1 :\ *command<cr> or *configure command<cr>
2190 PLA:BPL errBadConfigure :\ *configure command<cr>
2200 .cmdStatus2 :\ *Status <command>
2210 TXA:PHA :\ Save parameter bitmap
2220 JSR CMOSRead1:TSX :\ Get CMOS or current setting
2230 AND &101,X:TAY:PLA :\ Y=value, A=mask
2240 CMP #64:BCS PrOnOffEtc :\ mask=64 or 128, OFF/ON
2250 TYA:JSR PrDec:JSR PrSpace :\ Print decimal value
2260 .PrOnOffEtc
2270 TYA:LDX #&FF :\ Look for matching entry
2280 .PrOnOffLp1
2290 INX
2300 CMP txtNames,X:BEQ PrOnOffLp2 :\ Matched entry prefix
2310 LDY txtNames,X:BPL PrOnOffLp1 :\ End of table
2320 .PrOnOffDone
2330 JMP OSNEWL
2340 .PrOnOffLp2
2350 LDA txtNames+1,X:AND #127
2360 CMP #ASC"A":BCC PrOnOffDone
2370 JSR OSWRCH:INX:BNE PrOnOffLp2
2380 :
2390 .txtNames
2400 EQUB 0:EQUS "OFF"
2410 EQUB 1:EQUS "UK"
2420 EQUB 2:EQUS "BBC"
2430 EQUB 32:EQUS "Japan"
2440 EQUB 48:EQUS "USA"
2450 EQUB 64:EQUS "ON"
2460 EQUB 128:EQUS "ON"
2470 EQUB 0
2480 :
2490 :
2500 .cmdDevices :\ USBDEVICES
2510 DEX
2520 .cmdStatus :\ USBSTATUS
2530 TYA:BNE x:JMP OSNEWL
2540 .usbKBD :\ USBKBD <num>
2550 .usbMOUSE :\ USBMOUSE ON|OFF
2560 .usbPRINT :\ USBPRINT ON|OFF
2570 \
2580 .x
2590 JSR PrHex:JSR PrSpace :\ debug, command type
2600 TXA:JSR PrHex:JSR PrSpace :\ debug, command number
2610 TYA:JSR PrHex:JMP OSNEWL :\ debug, line pointer
2620 :
2630
2640
2650
2660
2670 \ (&F2),Y=> OFF|<dec>|OFF
2680 \ Returns Y=0 | 0-255 | 255
2690 .ScanOnOffName
2700 LDA (&F2),Y:AND #&DF
2710 CMP #ASC"O":BNE ScanOnOffNum
2720 INY:LDA (&F2),Y:AND #&DF
2730 LDY #0:CMP #ASC"F":BEQ ScanOnOffDone
2740 DEY:CMP #ASC"N":BEQ ScanOnOffDone
2750 JMP errBadNumber
2760 .ScanOnOffNum
2770 JSR ScanDec:TAY
2780 .ScanOnOffDone
2790 RTS
2800 :
2810 :
2820 .PrDec
2830 TAX:LDA #&99 :\ Move value to X, start at -1 in BCD
2840 SED :\ Switch to decimal arithmetic
2850 .PrDecLp
2860 CLC:ADC #1 :\ Add one in BCD mode
2870 DEX:BPL PrDecLp :\ Loop for all of source number
2880 CLD :\ Switch back to binary arithmetic
2890 CMP #10:BCC PrNyb :\ If <10, print single digit
2900 \ Fall through into PrHex
2910 :
2920 .PrHex
2930 PHA:LSR A:LSR A:LSR A:LSR A
2940 JSR PrNyb:PLA
2950 .PrNyb
2960 AND #15:CMP #10:BCC PrDig:ADC #6
2970 .PrDig
2980 ADC #ASC"0":JMP OSWRCH
2990 :
3000 .PrText
3010 PLA:STA &F6:PLA:STA &F7 :\ Pop address after JSR
3020 TYA:PHA :\ Save Y
3030 LDA #&FF:BNE PrTextNext :\ Jump into loop
3040 .PrTextLp
3050 LDY #0:LDA (&F6),Y :\ Get character
3060 BEQ PrTextNext:JSR OSASCI :\ Print if not zero
3070 .PrTextNext
3080 INC &F6:BNE P%+4:INC &F7 :\ Update address
3090 TAY:BNE PrTextLp :\ Loop back if not &00
3100 PLA:TAY:LDA #0:JMP (&F6) :\ Restore Y and return to code
3110 :
3120 .Pr2Spaces
3130 JSR PrSpace
3140 .PrSpace
3150 LDA #ASC" ":JMP OSWRCH
3160 :
3170 :
3180 .ScanDec
3190 JSR ScanChkDigit :\ Get current digit
3200 BCS ScanDecExit :\ Nothing to scan
3210 .ScanDecLp
3220 STA &F5 :\ Store as current number
3230 JSR ScanChkDigit :\ Get current digit
3240 BCS ScanDecDone :\ No more digits
3250 PHA:LDA &F5 :\ Save current digit
3260 CMP #26:BCS ScanDecTooBig :\ If num>25, will overflow
3270 ASL A:ASL A:ADC &F5:ASL A :\ num=num*10
3280 STA &F5:PLA :\ Get current digit back
3290 ADC &F5:BCC ScanDecLp :\ num=num*10+digit
3300 .ScanDecTooBig
3310 .errBadNumber
3320 JSR MkError
3330 EQUB 252:EQUS "Bad number":BRK
3340 .ScanDecDone
3350 LDA &F5:CLC :\ CC=valid number scanned
3360 .ScanDecExit :\ CS=bad number or digit
3370 RTS
3380 :
3390 .ScanChkDigit
3400 LDA (&F2),Y :\ Get current character
3410 CMP #ASC"0":BCC ScanDecErr :\ <'0'
3420 CMP #ASC"9"+1:BCS ScanDecErr :\ >'9'
3430 INY:AND #15:RTS :\ Convert character to binary
3440 .ScanDecErr
3450 SEC:RTS :\ CS=invalid digit
3460 :
3470 :
3480 .MkError
3490 PLA:STA &FD:PLA:STA &FE :\ Pop address after JSR
3500 LDY #0 :\ Index into the error block
3510 .MkErrorLp
3520 INY:LDA (&FD),Y:STA &100,Y :\ Copy error block to stack
3530 BNE MkErrorLp :\ Loop until terminating &00 byte
3540 STA &100:JMP &100 :\ Store &00 as BRK and jump to it
3550 :
3560 :
3570
3580 .RelocTable
3590 ]:NEXT
3600 PRINT"*Save ROMCMD ";~(mcode%);" ";~O%;" FFFF0000 FFFBBC00"
3610 END
3620 :