IMD 1.16: 13/08/2007 18:16:37 rom 4d2008-00 .asm 1d2008-00 .prn 4d1088-00 .com rev b 9/12/81  OCCROM0AH OCCROM2AH #OCCROM7AH = OCCROM6AH d OCCROM8AH OCCROM3AH OCCROM3AH  !OCCROM3AH "#OCCROM1AH G$%&'(OCCROM5AH )OCCROM4AH e*+,-./0OCCROM9AH 1OCCRAMA ASM!234OCCTXTA ASTI56789OCCROM9BASM :OCCROM0BASM ;OCCROM0BHEXX<=>?@AOCCROM2BASM#BCDOCCROM3BASMEFGHIJKLOCCROM3BASMMNOPQRSTOCCROM3BASMUVOCCROM6BASMWWXYZ[\OCCROM7BASM=]^_`OCCROM5BASM aOCCROM8BASM bOCCROM0BCOM cdOCCROM0BPRNefghijklOCCROM0BPRNmnopqrstOCCROM0BPRNuvwxyz{|OCCROM0BPRN}~OCCROM0BPRNOCCROM0BPRN TITLE 'B o o t C P / M f r o m d i s k.' ; ; The CBOOT entry point gets control from the cold start ; loader and is responsible for the basic system initial- ; ization. This includes outputting a sign-on message and ; initializing the following page zero locations: ; ; 0,1,2: Set to the warmstart jump vector. ; 3: Set to the initial IOBYTE value. ; 4: Default and logged on drive. ; 5,6,7: Set to a jump to BDOS. ; ; Before any data is read in, the maximum drive step rate ; must be determined: ; 1. set slowest seek ; 2. home drive A: ; 3. seek track #12 ; 4. speed up step rate ; 5. seek 4 tracks outward (12=>8,8=>4,4=>0) ; 6. if error, slow down step rate by 1, ; load in CP/M, boot, exit, etc. ; 7. else try faster step rate ; (if not fastest, GOTO #4 above) ; 8. if stepping fastest rate, boot CP/M. ; The exit address is to the CCP routine. ; ; ; The WBOOT entry point gets control when a warm start ; occurs, a ^C from the console, a jump to BDOCCROM0BPRNOCCROM0BPRNOCCROM0BPRNOCCROM0BPRN OCCROM0BPRN OCCROM0BPRN +OCCROM1BASMAOCCROM4BASMe;OCCROM0A.H TITLE 'Osborne-One Monitor for Model 1 system.' * 4D2008-00 MASTER .ASM * 2D2008-00 ASSY .ASM * 1D2008-00 LISTING .PRN * 4D1008-00 MASTER .COM * 2D1008-00 ASSY .COM LIST -F ;4-25, Do not list opted out code ; Initial Monitor for Osborne-One System. ; +-------------------------------+ ; | | ; | Osborne-One Monitor | ; | | ; +-------------------------------+ ;VER = REV A ;DATE = 180 ;DEB ; Assembly Constants ORG 0 ;FWA of memory @XFRMT = TRUE ;FALSE IF FORMAT IS IN ROM INACMD = FALSE INBCMD = TRUE INDCMD = FALSE INFCMD = FALSE INGCMD = FALSE INHCMD = FALSE INMCMD = FALSE INRCMD = FALSE INSCMD = FALSE INTCMD = FALSE INXCMD = FALSE INZCMD = FALSE INDIA = TRUE ;INTERNAL DIAGNOSTICS INDMON = FALSE INUTIL = FALSE NULINT MACRO NUMB ORG %1*8 DI JMP ILINT NOP ! NOP ! NOP ! NOP ENDM PUSHAL MACRO PUSH AF PUSH BC PUSH DE PUSH HL PUSH IX PUSH IY ENDM POPALL MACRO POP IY POP IX POP HL POP DE POP BC POP AF OS (function ; 0), or a jump to location zero. The WBOOT routine reads ; the CCP and BDOS from the appropriate disk sectors. ; WBOOT must also re-initialize locations 0,1,2 and 5,6,7. ; The WBOOT routines exits with the C register set to the ; appropriate drive selection value. The exit address ; is to the CCP routine. ; ; Disk layout Definition ; --Note: Tracks 0, 1, and 2 are reserved for CPM.-- ; Track 0----------- ; 1 thru 8 CCP 2k ; 9 thru 10 BDOS ; Track 1----------- ; 1 thru 10 BDOS ; Track 2----------- ; 1 thru 2 BDOS 3.5k ; 3 thru 10 CBIOS 2k ; Sectors 3,4,5,6 are currently used. page CBOOT: ;Entry C= drive to boot from ; Exit A= drive Proc LDK A,6 ;read 5 sectors of trk 3 STO A,TEM MOV A,C CALL BCPM ;boot system LD A,SDISK ;use requested drive JMP BIOS ;enter CPM ; LK A,3 ; STO A,SEKDEL ;set step rate =3 (slowest) ; CALL HOMED ;send A: home ; ; LK BC,12 ; CALL SETTRK ;track 12 ; LK C,0 ; CALL SETSEC ;sector 0 ; CALL SEEK ;do (sl ENDM PAGE LINK OCCROM1A.H ;ROM STANDARDS ;LOP,ROMD LINK OCCROM2A.H ;CPM BOOT ;BOOT LINK OCCROM3A.H ;CONSOL ROUTINES ;KEY LINK OCCROM4A.H ;PIA ROUTINES ;PIO,IEEE LINK OCCROM5A.H ;SIA ROUTINES ;SIO LINK OCCROM6A.H ;DISK ROUTINES ;DSK LINK OCCROM7A.H ;DIAGNOSIC ROUTINES ;DIA LINK OCCROM8A.H ;FORMAT ROUTINE ;XFMT LINK OCCROM9A.H ;UTILITES ;UTIL2 LINK OCCRAMA.ASM ;RAM LOCATIONS ; Endx FORMAT IS IN ROM INACMD = FALSE INBCMD = TRUE INDCMD = FALSE INFCMD = FALSE INGCMD = FALSE INHCMD = FALSE INMCMD = FALSE INRCMD = FALSE INSCMD = FALSE INTCMD = FALSE INXCMD = FALSE INZCMD = FALSE INDIA = TRUE ;INTERNAL DIAGNOSTICS INDMON = FALSE INUTIL = FALSE NULINT MACRO NUMB ORG %1*8 DI JMP ILINT NOP ! NOP ! NOP ! NOP ENDM PUSHAL MACRO PUSH AF PUSH BC PUSH DE PUSH HL PUSH IX PUSH IY ENDM POPALL MACRO POP IY POP IX POP HL POP DE POP BC POP AF ow) seek to trk 12, sec 0 ; ;:fastr: LK HL,SAVTRK ; LK A,-4 ;seek 4 tracks out ; ADD [hl] ; STO A,[hl] ; LK HL,SEKDEL ; DEC [hl] ;speed up step rate ; CALL SEEK ;seek 4 track outwards, faster ; JRNZ :err ;if stepping too fast ; LD A,SEKDEL ; OR A ;stepping fastest possible? ; JRNZ :fastr ;try a faster seek ;; JR :end ;..else seeking fastest already ; ;:end: CALL BCPM1 ;read in cpm ; JMP BIOS ;cold start ; ;:err: LK HL,SEKDEL ; INC [hl] ;seek at previous (slower) speed ; LK A,0000_0011b ; AND [hl] ;limit seek to (slowest) 3 ; STO A,[hl] ; JR :end WBOOT: Proc LDK A,6-4 ;don't read CBIOS STO A,TEM ;save sectors LD A,CDISK ;Current logged in drive ; JR BCPM ;Boot CP/M space 4,10 BCPM: ;Boot CPM from disk ; Entry A = Drive to boot from. ; TEM = Number of sectors to read from ; track 3. ; A = Drive to boot or warm-boot from ; Exit A = 0, load sucessful. ; Z bit = 1, load successful. proc STO A,SDISK ;Set drive to boot from BCPM1: CALL HOM is aligned and data path is valid. ; Entry None. ; Exit Back to diag main loop. proc CALL DSKDI ;initialize LDK A,100 :2: STO A,TEM CALL GNRN ;get next track STO A,SAVTRK LDK B,1 CALL DREAD ;read sector OR A CNZ DERR ;if disk error CALL GNRN ;get random CALL DELAY ;delay LD A,TEM DEC A JRNZ :2 ;if not done JR DERC ;display error count space 4,8 ;DDAM: ;Test data address marks ;; Entry None ;; Exit After 1000 tries and displays ; proc ; CALL DSKDI ;initialize disk ; LDK BC,1000 ;:2: PUSH BC ; CALL DRDA ;read address mark ; LDK C,' ' ; JRZ :4 ;if good xfer ; LD HL,ERCNT ; INC HL ; STO HL,ERCNT ;update error count ; LDK C,80h ;pure white space ;:4: CALL COUT ;output indicator ; POP BC ; DEC BC ; MOV A,B ; OR C ; JRNZ :2 ;if not done ; JR DERC ;display error count space 4,8 DERC: ;Display error counter. ; Entry ERCNT = current error count LDK DE,DERCMG CALL ESTR ;output error prompt LD HL,ERCNT JMP ADRD ;output number DERCMG:ED ;home drive OR A JRNZ BCPME ;if drive NOT ready LDK BC,CCP ;Set buffer address CALL SETDMA LDK HL,0 STO HL,SAVTRK ;set track LDK A,1 STO A,SAVSEC ;set sector=1 ; Read in 1st two track LDK B,2 :4: PUSH BC LDK B,MSEC CALL DREAD ;read 1st track POP BC JRNZ BRDE ;if read error STO HL,DMADR ;update DMA LD HL,SAVTRK INC HL STO HL,SAVTRK ;update track to read DJNZ :4 ;if not all tracks ; Now read in requested number of sectors ; from track 3. LD A,TEM MOV B,A ;sectors to read :8: PUSH BC LDK B,1 CALL DREAD ;read one sector POP BC JRNZ BRDE ;if read error STO HL,DMADR ;update DMA LDK HL,SAVSEC INC [hl] ;update sector number DJNZ :8 ;if not all secs LDK HL,HSTACT LDK DE,(LOGSEC-HSTACT)+1 CALL FILLZ ;clear Host BIOS cells LDK A,0FFh STO A,UNASEC LDK A,VLL-1 STO A,LDTRK ;set other drive NOT int XRA A ;Clear error indicator RET ; Here on Drive NOT ready BCPME: LDK DE,DNRMSG ; Output error message and return to BCP TITLE 'Diagnostic section.' ; This section of code is entered either via the 1st prompt ; level by entering ^d, or by using the monitor command of ; 'T' if DEBUG is assembled on. ; ; This section of code contains all of the rom resident ; diagnostics to assist production and distributors. ; ; The diagnostic section uses a menu and contain test ; for major hardware pieces. These diagnostics are NOT ; considered to be all-encompassing...... ; Entry from monitor loop DIAG: proc IF ~INDMON NEXTC = DIAG ENDIF LK SP,ROMSTK LDK DE,DIAMSG CALL ASKU ;ask user for input LDK HL,DSKSWP ;disk swap cell LDK C,0 STO C,[HL] ;SET A=A,B=B CMP 'A' JZ CBOOT ;IF BOOT A DRIVE INC [HL] ;SWAP DRIVES A=B,B=A CMP 'B' JZ CBOOT ;IF BOOT B DRIVE DEC [HL] ;A=A, B=B CMP 'K' JZ KEYBT ;if Keyboard test CMP 'M' JZ TSTMEM ;if memory test CMP 'R' JZ TSERI ;if input test program CMP 'D' JRNZ DIAG ;if illegal DSKD: ;Here to run disk diagnostic LDK DE,DSKMSG CALL ASK DBE cr,lf DCE 'ERR cnt- ' page DSKDI: ;Disk diagnostic initialize ; Entry SDISK set to disk to test(0 or 1) proc LD A,SEC6 STO A,RNDV ;set random seed CALL DDRV ;deselect drive :2: LDK DE,0 STO DE,ERCNT ;clear error count MOV C,E CALL HOMED ;select drive 0, home. JRZ :3 ;if drive ready CALL RDSKC ;reset disk controller LDK DE,DNRMSG CALL ODER ;output disk error JR :2 :3: LDK BC,HSTBUF CALL SETDMA ;set to default dma RET page ASKU: ;Ask user for input, first displaying prompt ; Entry DE= FWA of prompt message ; Exit A= normalized input from user CALL ESTR ;prompt user CALL GETCH ;get next char CMP ESC JZ NEXTC ;if abort RET page KEYBT: ;Perform reading of keyboard and echoing to screen ; Keeps running till user types in ^Z. LDK DE,KEYTM CALL ESTR ;output prompt LDK HL,4000h JMP ACMDD ;enter A command KEYTM: DBE cr,lf DCE 'Enter keys (till ^Z) : ' page TSTMEM: ;performs a test of memory validating that the ; memory is workingM BCPME1: PUSH DE LDK A,low(256) CALL DELAY ;Delay 256 milli-seconds POP DE ;FWA of message CALL ODER ;indicate drive NOT ready JR BCPM1 ;try again ; Here on Boot READ error BRDE: LDK DE,BRDEMG JR BCPME1 ;delay output error DNRMSG: DCE 'Drive NOT ready.' BRDEMG: DCE 'Boot READ error.' ; Endx BMboot.asm date track to read DJNZ :4 ;if not all tracks ; Now read in requested number of sectors ; from track 3. LD A,TEM MOV B,A ;sectors to read :8: PUSH BC LDK B,1 CALL DREAD ;read one sector POP BC JRNZ BRDE ;if read error STO HL,DMADR ;update DMA LDK HL,SAVSEC INC [hl] ;update sector number DJNZ :8 ;if not all secs LDK HL,HSTACT LDK DE,(LOGSEC-HSTACT)+1 CALL FILLZ ;clear Host BIOS cells LDK A,0FFh STO A,UNASEC LDK A,VLL-1 STO A,LDTRK ;set other drive NOT int XRA A ;Clear error indicator RET ; Here on Drive NOT ready BCPME: LDK DE,DNRMSG ; Output error message and return to BCPU ;Ask user for input SUB 'A' JRZ :2 ;if 'A' DEC A JRNZ DIAG ;if not A or B INC A :2: STO A,SDISK ;set drive CALL DRDT ;test reading entire disk CALL DSEKT ;test random seeks JMP NEXTC ;next DIAMSG: DBE 'Z'-40h DBE ' ROM DIAGNOSTICs' DBE cr,lf,'Select Test:' DBE cr,lf,'A,B Boot Sys' DBE cr,lf,' D isk' DBE cr,lf,' K ey-vdt' DBE cr,lf,' M emory' DBE cr,lf,' R ead in test' DBE lf,cr,lf,' :' DCE ' ' DSKMSG: DBE cr,lf DCE 'Select (A,B): ' ; Disk diagnostic section. DRDT: ;Disk read test ; reads each sector on disk and reports any errors proc CALL DSKDI ;initialize disk LDK A,0 :2: STO A,SAVTRK LDK A,1 :3: STO A,SAVSEC LDK B,1 CALL DREAD ;read sector OR A CNZ DERR ;if error LD A,SAVSEC INC A CMP MSEC+1 JRNZ :3 ;if not full track LD A,SAVTRK INC A CMP MTRK JRNZ :2 ;if not full disk JR DERC ;display error count space 4,10 DSEKT: ;Disk seek test ; Routine performs random seeks followed by reads validating ; drive correctly. ; Fixed limits on memory test are 4000h to EF00h ; (TEM = EF00h) ; Entry none. ; Exit To error if any errors occurred during ; the testing ; Calls GETNM proc LDK DE,TSMSG CALL ESTR ;prompt user about mem test LDK DE,TEM LDK HL,4000h LDK C,0A5h ;initial test pattern ; Loop thu testing memory within limits ; HL= FWA ; DE= LWA :2: DI PUSH DE ;save LWA PUSH HL ;save FWA :3: STO C,[hl] ;data to memory INC HL ;update address CALL CDEHL JRNZ :3 ;if not all done ; Now perform test on memory reading ; what was just written and comparing ; with pattern C. POP HL ;restore FWA PUSH H :5: DI LD A,[hl] CMP C ;validate good write JRZ :7 ;If GOOD compare EI MOV B,A ;save BAD data PUSH BC CALL OCRLF ;output new line CALL ADRD ;Output Location in error CALL OSP ;Output space char POP BC PUSH BC MOV A,C CALL NMOUT ;Output good data LDK C,'=' CALL COUT MOV A,B CALL NMOUT ;Output BAD data POP BC ;restore pattern CALL BREAK :7:  JR PBBH space 4,10 BREAK: ;Check for break key. ; Entry NONE ; Exit To DIAG if char entered is ESC, else ; return to caller A= char or 0 if none ; Calls SKEY, CI ; DESTROYS: A,F/F'S CALL SKEY ;get console status RZ ;If not ready CALL CI ;get char CMP ESC JZ DIAG ;if ESC, abort RET space 4,10 GETCH: ;returns the next character in the input stream ; TO the calling program. ; Entry NONE ; Exit C - next character normalized to UPPER case. ; Calls CI,CO,NORM ; DESTROYS: A,C,F/F'S CALL CI ;Get character from terminal CALL CO ;output it JMP NORM ENDIF ; Endx BMDIA.asm INC HL :5: MOV C,A CALL COUT ;back to user JR :3 ;next character space 4,10 ADRD: PBWH: ;Print Binary Word in Hex. ; PBWH outputs to the console the address ; contained in the H,L registers. ; Entry HL= address to be displayed ; Exit NONE ; Calls PBBH ; DESTROYS: AF, C. MOV A,H ;display First half of address CALL PBBH MOV A,L ;display second half of address0, if drive is ready ; Calls OPBD, DELAY ; Uses A,B proc LD A,SDISK SDRV1: LK HL,DSKSWP ;disk drive swap cell XOR [hl] ;swap A for B if DSKSWP=1 AND 1 ;Can only be 0 or 1 CMP 1 JRNZ :2 ;if not drive 1 LDK A,40h :2: ADI 40h MOV C,A LD A,PIABD MOV B,A AND 1100_0000b ;get drive bits only CMP C JZ RDSKD ;if drive already selected ; Check to see if this drive is the same as the last ; one selected. ; IF true, go to 3 ; else ; Save current trk register in LDSEL and ; set trk reg to last track used for newly selected ; drive ; end LD A,LDSEL ;last selected disk CMP C JRZ :3 ;if same drive MOV A,C STO A,LDSEL ;set to new drive PUSH BC LDK HL,LDTRK LD C,[hl] ;get last accessed track for new drive LD A,D.TRKR ;get current track STO A,[hl] ;save in table MOV A,C STO A,D.TRKR ;set trk register to last selected POP BC ; Set drive select perserving vio offset values :3: CALL RDSKD ;reset Controller LDK B,5 ;number of tries :5: LDK A,2 INC HL CALL CDEHL JRNZ :5 ;If not all done EI ;allow key entry MOV A,C RRC ;shift one position MOV C,A LDK HL,FWAVM+40 INC [hl] ;indicate running POP HL POP DE CALL BREAK JRZ :2 ;if not data MOV C,A ;next test pattern JMP :2 ;keep on looping TSMSG: DBE cr,lf,'Memory tes' DCE 't' page TSERI: ;Input test routine through serial port ; Format of input: ; 8 bit binary data, no parity ; 1st two bytes are DW (length) ; (length) following bytes are placed ; at 4000h in memory; ; Exit: JMP 4000h Proc LK DE,:lmsg ;length msg CALL ESTR CALL READER ;get chr MOV L,C ;low byte of length CALL READER MOV H,C CALL PBWH ;print out length of test routine EX HL,DE ;DE = length LK HL,4000h ;FWA of test program :loop: MOV A,D OR E JRZ :xit ;if finished with input, run prgm CALL READER STO A,[hl] ;get & deposit next byte STO A,FWAVM+40 ;indicate recieved data INC HL DEC DE JR :loop :xit: LK DE,:xmsg ;exit message CALL ESTR JMP TITLE 'Disk I/O routines.' ; Disk interface definitions and functions. ; 1792 functions. DML = 4 ;= 15 ms delay on function LTRKB = 3125 ;length of a track ; Note: Shugart says LTRKB = 3125... NRTRYS = 4 ;Number of retries MSECB = 10h ;Multi-sector r/w bit ; Function codes D.RES = 00h+0Ch ;restore D.SEK = 10h+08h ;seek D.STP = 20h ;step D.STPI = 40h ;Step IN D.STPO = 60h ;Step out D.RDS = 80h ;Read sector D.WRTS = 0A0h+DML ;Write sector D.RDA = 0C0h+DML ;read address D.RDT = 0E0h+DML ;read track D.WRTT = 0F0h+DML ;write track D.FINT = 0D0h ;Force interrupt ; Disk status and command registers D.CMDR = H.FDC ;Disk command reg (write) D.STSR = H.FDC ;Status reg (read) D.TRKR = D.CMDR+1 ;track reg D.SECR = D.CMDR+2 ;Sector reg D.DATR = D.CMDR+3 ;Data reg (r/w) ; Status definitions BS.BSY = 0 ;Busy DS.BSY = 1 shl BS.BSY BS.DRQ = 1 DS.INX = 1 shl BS.DRQ ;Index mark detected DS.DRQ = DS.INX ;DR is full on read, empty on write BS.TK0 = 2 DS.TK0 = 1 shl 50 CALL DELAY LK A,250 ;2nd delay CALL DELAY LD A,D.STSR AND DS.INX RZ ;if index DJNZ :5 ;keep trying OR 80h or DS.INX ;indicate NOT ready RET space 4,10 DDRV: ;Deselect drive ; Entry SDISK = current disk drive LD A,PIABD AND 1_1111b MOV C,A JMP OPBD ;deselect last drive page PSEKC: ;Perform seek type command ; Entry A= command to perform without r1, and r0. ; PSEKC will or in the low two bits as defined ; by SEKDEL. ; Exit A= last value of D.STSr LDK HL,SEKDEL OR [hl] ;or in delay time for seek CALL FDSK ;function disk RNZ ;if Drive NOT ready JMP WBUSY space 4,10 SELDSK: ;Select disk in register C MOV A,C ;drive to home CALL SDRV1 ;C= drive JR HOMED1 HOMED: ;Home disk drive ; Entry SDISK= drive ; Exit A=0 if drive on home. proc CALL SDRV ;select drive HOMED1: LDK A,D.RES CALL PSEKC ;perform seek command CMP -1 JRZ SKEX1 ;if error BIT BS.SEK,A JRNZ SKEX1 ;if error BIT BS.TK0,A JRZ :4 ;if NOT home IF ODEBUG CA 4000h ;...to user program :lmsg: DBE cr,lf,'Start input: Len' ! DCE '=' :xmsg: DBE cr,lf,'Program begins' ! DCE ':' space 4,10 GNRN: ;Get next random number ; Exit A= new number to use (0 to MTRK-1) proc MOV A,R ;refresh register XOR [hl] AND 3Fh ;cannot exceed 28h=40d ADD A,17 CMP MTRK JC :4 ;if in range SUB MTRK :4: STO A,[hl] ;update RET space 4,10 IF ~INDMON ACMDD: ;Entry here from Diagnostic loop HL = 4000h proc :3: CALL CI ;read char CPI EOFC JZ DIAG ;if request to quit STO A,[hl] ;into memory INC HL ;update pointer CPI CR JRNZ :5 ;If not carriage return STO LF,[hl] INC HL :5: MOV C,A CALL COUT ;back to user JR :3 ;next character space 4,10 ADRD: PBWH: ;Print Binary Word in Hex. ; PBWH outputs to the console the address ; contained in the H,L registers. ; Entry HL= address to be displayed ; Exit NONE ; Calls PBBH ; DESTROYS: AF, C. MOV A,H ;display First half of address CALL PBBH MOV A,L ;display second half of addressBS.TK0 DS.LSD = DS.TK0 ;lost data DS.CRC = 08h ;CRC error in ID field BS.SEK = 4 DS.SEK = 1 shl BS.SEK ;Seek error DS.RNF = DS.SEK ;Record NOT found DS.HDL = 20h ;Head loaded DS.WTF = DS.HDL ;Write fault DS.WTP = 40h ;Write protected DS.NRY = 80h ;Drive NOT ready ; Disk timing counts D.DEL = 20 ;Delay after function page SDMA: ;Set DMA SETDMA: ; Entry BC = DMA address STO BC,DMADR RET space 4,10 SETTRK: ;Set track ; Entry BC = track STO BC,SAVTRK RET space 4,10 SETSEC: ;Set Sector ; Entry C= sector number (1 to MSEC) MOV A,C STO A,SAVSEC RET space 4,10 HOME: ;Home selected disk drive LDK BC,0 JMP SETTRK ;reset track to 0 IF ODEBUG space 4,10 LDSKS: ;List status of disk system CALL OCRLF LDSKS1: LD A,D.STSR CALL PBBH ;output status LDK C,' ' CALL CO CALL RDSKC ;reset disk controller LD A,D.STSR ;get status CALL PBBH ;new status JMP OCRLF ;new line ENDIF space 4,10 SDRV: ;Select Drive ; Entry SDISK= drive ; Exit A= LL LDSKS1 ;list status **** ENDIF XRA A ;clear A SKEX1: PUSH AF LDK A,-1 STO A,DACTVE ;start counter CALL STAT17 ;save disk controller regs POP AF RET ; Here if drive NOT homed, possible NOT ready :4: AND 80h JR SKEX1 space 4,10 SEEK: ;Seek to track defined by SAVTRK ; Entry SAVTRK set to track ; SAVSEC set to sector number ; Exit A= 0, if no error, else status ; MUST NOT destroy DE, HL pair proc CALL SDRV ;select drive ; Here if drive already selected ; Check to see if SEEK is necessary by ; comparing SAVTRK to controller track ; register SEEKN: LD A,SAVTRK STO A,D.DATR ;set track wanted MOV C,A LD A,D.TRKR CMP C JRZ :8 ;if on track ; Disk seek required, function controller ; with SEEK command LDK A,5 SEEKA: STO A,RTRY ;update retry count LDK A,D.SEK CALL PSEKC ;perform seek command MOV C,A AND DS.CRC or DS.SEK JRNZ :10 ;if error ; Now read-address and verify on-track CALL DRDAS ;read address JRNZ :10 ;if error LDK HL,F EI ! RET space 4,10 DWRT: ;Write to disk ; Entry SDISK= drive ; B= Number of sectors to xmit. ; DMADR= FWA of data ; Exit same as DREAD ; Uses All registers proc MOV D,B CALL SEEK JRNZ RWEX1 ;if seek error MOV B,D PUSH BC LDK A,D.WRTS DEC D JRZ :3 ;if NOT multi-sectors OR MSECB ;add 'm' bit :3: CALL FDSK POP BC ; Now xfer bytes to controller from DMA. DI LD HL,DMADR :5: PUSH BC LDK BC,LSECB ;length of std sector :6: CALL XDD ;xfer to disk JRNZ RWEX ;if error ; Now check if multi sector POP BC DJNZ :5 ;continue XRA A :8: JR RWEX1 space 4,10 IF ODEBUG DTREAD: ;Read disk track ; Entry SDISK= drive ; DMADR= FWA for data. ; Exit DSTSB= status proc CALL SEEK LDK A,D.RDT ;read track command CALL FDSK ; Now xfer bytes from controller to DMA. DI LDK BC,LTRKB LD HL,DMADR :2: LD A,D.STSR BIT BS.BSY,A JRZ :5 ;if all done ANI DS.DRQ JRZ :2 ;if no data LD A,D.DATR STO A,[hl] INC HL DEC BC ;lower counter MOV A,and MOV A,B STO A,D.CMDR ;function drive ; Wait for busy to be set LDK C,0 :2: LD A,D.STSR RAR ;DS.BSY JRC :3 ;if chip went busy DEC C JRNZ :2 ;if not time-out JR WBUSYX ;exit, error ; Set DACTVE indicating activity on drive :3: XRA A STO A,DACTVE RET space 4,10 WBUSY: ;Wait for Busy to clear ; Exit A= -1, if time out occurred, ; else ; A= last status and is positive. ; Uses A, C proc PUSH BC LDK BC,0 :1: LD A,D.STSR RAR ;DS.BSY JRNC :1A ;if NOT busy, proceed DEC BC MOV A,B OR C JRNZ :1 ;if not time-out WBUSYX: LDK A,-1 ;indicate error, drive NOT ready POP BC OR A ;set flags RET :1A: RAL ;restore A POP BC ;restore BC AND 7Fh ;make sure its positive RET space 4,8 RDSKD: ;Reset PIA and disk controller ; selecting drive specified by C ; Entry C= drive ; B= PIABD MOV A,B AND 0001_1111b ;get vio offset only OR C MOV C,A CALL OPBD ;function PIO-b ; JMP RDSKC RDSKC: ;reset disk controller ; Entry None ; ExiDSTSB LD A,SAVTRK CMP [hl] JRZ :8 ;if ON track LD A,RTRY DEC A JRNZ SEEKA ;if not max retrys ; here if seek error :10: MOV A,C ORI 80h ;indicate movement error JR SKEX1 ; Now set the sector register to requested ; Sector :8: CALL WBUSY ;wait for FDC quiescence LD A,SAVSEC STO A,D.SECR ;set sector register XRA A ;indicate good RET space 4,10 DRDA: ;Read Address info. ; Entry SDISK= drive ; Exit D.STSB = data bytes ; MUST NOT destroy DE pair proc CALL SDRV ;select drive DRDAS: LDK A,D.RDA CALL FDSK ;function disk ; Get status bytes LDK HL,DSTSB LDK B,6 DI PUSH DE ;save DE :2: LDK DE,4000 ;time out :3: LD A,D.STSR BIT BS.BSY,A JRZ RWEX ;if possible error BIT BS.DRQ,A JRNZ :4 ;if data ready DEC DE MOV A,D OR E JRNZ :3 ;if NOT time out LK C,SEKTMO ;seek time out JR RWEX ;error exit :4: LD A,D.DATR STO A,[hl] ;save byte INC HL DJNZ :2 ;if not done POP DE XRA A ;indicate good EI ! RET space 4,10 DREAD:B OR C JRNZ :2 ;if not done ; Here if all done :5: EI RET ENDIF page ; Code to load system from external hardware and to write ; code onto the system tracks is totally contained in this ; section. RDSYS: ;Read in system data in binary from external box. ; Entry None ; Exit Data contained from 4000h to xxxxh proc DI LDK HL,4000h :2: CALL READER ;read in data STO A,[hl] INC HL JR :2 ;infinite loop space 4,10 WRTSYS: ;Write out system tracks as specified by ; the current setting of DMADR ; Entry Memory has valid system image. ; Exit system written. proc CALL HOMED ;initialization LDK HL,4000h STO HL,DMADR ;set DMA LDK A,1 STO A,SAVSEC ;set to 1st sector LDK HL,0 STO HL,SAVTRK ;set track ; loop writing data out :2: LDK B,MSEC CALL DWRT ;write entire track CNZ DERR ;if error STO HL,DMADR ;reset DMA LD HL,SAVTRK INC HL STO HL,SAVTRK ;update track MOV A,L CMP 3 JRNZ :2 ;if not done RET page XDD: ;Xfer data from memory to disk t Busy cleared. ; A= 0. LDK A,D.FINT STO A,D.STSR ;clear controller XRA A ;clear A and flags RET ODER: ;Output disk error to console ; Entry DE= FWA of message ; SDISK = drive with error PUSH DE CALL OCRLF ;new line LD A,SDISK ADD A,'A' MOV C,A CALL CO ;output drive name CALL O2SP POP DE ;get message JMP ESTR DERR: ;Output disk system error ; Entry A= status from controller ; Exit error output PUSH DE PUSH HL PUSH BC PUSH AF LDK DE,DERMSG CALL ESTR ;output error POP AF ;get status value CALL PBBH ;output status CALL O2SP LD A,SAVTRK CALL PBBH ;output track LDK C,',' CALL COUT ;output comma LD A,D.TRKR CALL PBBH ;output controller track CALL O2SP LD A,SAVSEC CALL PBBH ;output sector LDK C,',' CALL COUT ;output comma LD A,D.SECR CALL PBBH ;output controller sector ; Update error counter LD HL,ERCNT INC HL STO HL,ERCNT ;update error count ; Clear controller CALL RDSKC ;reset disk controller ; Restore DRSECS: ;Read disk sectors. ; Entry SDISK= drive ; B = number of sectors to read ; Number from 1 to MSEC ; DMADR= FWA for data. ; Exit DSTSB= A= 0, if no error ; HL = next DMA ; Uses All registers proc MOV D,B ;save sectors CALL SEEK ;seek to track, set sector JRNZ RWEX1 ;if seek error MOV B,D PUSH BC LDK A,D.RDS DEC D JRZ :3 ;if NOT multi-sectors OR MSECB ;add 'm' bit :3: CALL FDSK POP BC CMP -1 JRZ RWEX1 ;if drive NOT ready ; Now xfer bytes from controller to DMA. DI LD HL,DMADR :5: PUSH BC LDK B,low LSECB :6: LD A,D.STSR BIT BS.BSY,A JRZ RWEX ;if possible error BIT BS.DRQ,A JRZ :6 ;if no data LD A,D.DATR STO A,[hl] INC HL DJNZ :6 ;if not all data ; Now check if multi sector POP BC DJNZ :5 ;continue XRA A JR RWEX1 ; here on error RWEX: CALL STAT17 ;save disk controller regs POP DE ;restore stack OR 80h ;if busy cleared, indicate with 80h RWEX1: OR A ;set status PUSH AF LDK A,-1 STO A,DACTVE POP A ; Entry BC = length ; HL = FWA ; Exit HL = next address ; A=0 if no error, else status ; Uses A,BC,E, HL proc LD A,D.STSR BIT BS.BSY,A JRZ :5 ;if possible error BIT BS.DRQ,A JRZ XDD ;if no data LD A,[hl] STO A,D.DATR ;send to controller INC HL DEC BC MOV A,B OR C JRNZ XDD ;if not done XRA A ;indicate good xfer RET ; here if error :5: OR 80h ;indicate busy dropped RET page FDSK: ;Function disk routine ; All functions for DSK controller SHALL do so by using ; this routine. FDSK sets DACTVE to 0 indicating activity ; UPTIM uses this cell to turn off select if one sec has ; occurred. ; Entry A= function code ; Exit A= 0, if chip accepted function ; else, A=-1, indicating time-out, See WBUSY ; Uses A, B, C proc MOV B,A ;save function code LD A,PIABD AND 1100_0000b JRNZ :1 ;if drive active PUSH BC CALL SDRV ;reselect drive POP BC :1: CALL WBUSY ;Wait for busy to clear RM ;if will NOT clear busy ; Controller NOT busy, issue comm regs POP BC POP HL POP DE RET DERMSG: DBE cr,lf DCE 'Dsk ERR (sts trk sec)- ' space 4,10 STAT17: ;save 179x status ;called when disk error discovered: ;...saves 179x regs in high RAM. PUSH BC ! PUSH DE ! PUSH HL LK HL,D.STSR ;1st (lowest) 179x register LK DE,R179x ;register save area LK BC,4 ;move 4 bytes LDIR POP HL ! POP DE ! POP BC RET ; endx BMDSK tput error POP AF ;get status value CALL PBBH ;output status CALL O2SP LD A,SAVTRK CALL PBBH ;output track LDK C,',' CALL COUT ;output comma LD A,D.TRKR CALL PBBH ;output controller track CALL O2SP LD A,SAVSEC CALL PBBH ;output sector LDK C,',' CALL COUT ;output comma LD A,D.SECR CALL PBBH ;output controller sector ; Update error counter LD HL,ERCNT INC HL STO HL,ERCNT ;update error count ; Clear controller CALL RDSKC ;reset disk controller ; RestoreT ; endx BMXFMT.asm ks, with each ; track containing 10 sectors. ; Entry BC = FWA of buffer ; BUF+0= DW length ; BUF+2= beginning of data ; SAVTRK = next track to format ; SAVSEC = 1 ; Drive already selected and ready ; Exit track formatted proc PUSH BC ;save address LD A,SAVTRK OR A JZ :2 ;if already on track LDK A,D.STPI CALL PSEKC ;perform step IN :2: LDK A,D.WRTT ;request write track DI CALL FDSK ;request write POP HL ;FWA of buffer EI RNZ ;if error DI ; Load BC with length and set ; HL = FWA of data to xmit to disk LD C,[hl] ! INC HL LD B,[hl] ! INC HL ;BC = length of xfer ; Now write out data :4: CALL XDD ;xfer to disk JRNZ :11 ;if error ; Pad rest of track with FFh :10: LD A,D.STSR OR A JRZ :11 ;if all done AND DS.DRQ JRZ :10 LDK A,0FFh STO A,D.DATR ;pad JR :10 ;continue ; Exit A=0, if no error :11: EI RE CALL UPTIM ;UPDATE TIME ; PERFORM SCAN OF KEYBOARD LD A,KEYLCK ;LOCKED KEYBOARD? OR A JZ GKEYX ;IF LOCKED KEYBOARD, CAN'T READ CHRS CALL RDKEY ;READ KEYBOARD CMP -2 JRNZ :4 ;IF KEY DEPRESSED ; HERE IF NO KEY PRESS, CHECK FOR HOLDING ; DEBOUNCED KEY, IF SO SURFACE KEY. :2: LD A,TKEY BIT 7,A JRZ :3 ;IF NO KEY HOLDING LD A,LKEY STO A,TKEY ;CLEAR-SET HOLD :3: JMP GKEYX ;EXIT :4: PUSH AF CALL RDKEY ;TRY AGAIN POP DE ;LAST A CMP D JRNZ :2 ;IF NOT MATCH, ERROR CMP -1 JZ GKEYX ;IF NULL CONTROL KEY ; A= CURRENT KEY PRESSED ; TKEY = LAST SCAN KEY FOUND GKEY10: MOV C,A ;SAVE CURRENT KEY LD A,CKEY ;CONTROL KEY VALUE OR A JRZ :20 ;IF NO SPECIAL FUNCTION KEYS ; IF SPECIAL, CHECK TYPE BIT 6,A ;40H JRZ :17 ;IF NOT CONTRL KEY ; PROCESS CONTROL KEY ; CHECK FOR ^1, 2, OR 3 FOR FIXED ALIGNMENT MOV A,C CMP '1' LDK C,VFLO JRZ :10B ;IF ^0, ALIGN TO 0 OFFSET CMP '2' LDK C,VFLO+2*52 ;2*52 COMPENSATES FOR 1/2 CHR SHIFT JRZ :10B ;IF ^1, TITLE 'KEYBOARD AND CONSOLE ROUTINES.' ; ASSEMBLY CONSTANT @KEY = 1 ;PRODUCTION KEYBOARD ; CONTROL KEYS CBELL = 'G'-40H ;RING THE BELL MCUP = 'K'-40H ;MOVE CURSOR UP MCDOWN = LF ;MOVE CURSOR DOWN MCLEFT = BKS ;MOVE CURSOR LEFT MCRIGH = 'L'-40H ;MOVE CURSOR RIGHT VCLRS = 'Z'-40H ;CLEAR AND HOME CURSOR VHOME = '^'-40H ;HOME CURSOR ; ESCAPE KEYS VLOCK: = '#' ;LOCK KEYBOARD VUNLK = '"' ;UNLOCK KEYBOARD VCAD: = '=' ;CURSOR ADDRESSING VSAD: = 'S' ;SCREEN ADDRESSING VINC: = 'Q' ;INSERT CHAR VDELC: = 'W' ;DELETE CHAR VINL: = 'E' ;INSERT LINE VDELL: = 'R' ;DELETE LINE VCEOL: = 'T' ;CLEAR TO END OF LINE VSHI: = ')' ;START HALF INTENSITY VEHI: = '(' ;END VSUL: = 'L' ;START UNDERLINE VEUL: = 'M' ;END VSGH: = 'G' ;START GRAPHICS VEGH: = 'G' ;END SKEY: ;GET STATUS OF KEYBOARD ; EXIT CBIT SET IF NO DATA READY LD A,KEYLCK OR A RZ ;IF LOCKED KEYBOARD LD A,LKEY BIT 7,A RET ;=0 IF NO DATA SPACE 4,10 CI: RKEY: ;READ NEXT KEY FROM KEYBOARD ; EXIT ALIGN TO 52 CMP '3' LDK C,VFLO+4*52 ;4*52 = 208 SHIFTS = 104 CHARACTERS JRZ :10B ;IF ^2, ALIGN TO 104 ; CHECK FOR SPECIAL CONTROL CODE SCEEN MOVEMENT CODES ; IF SO PROCESS LOCAL AND RETURN LDK E,2 CMP MCLEFT JRZ :10A ;IF MOVE SCREEN LDK E,-2 CMP MCRIGH JRNZ :10C ;IF NOT SCREEN RIGHT :10A: LD A,PIAAD ;CURRENT HORZ OFFSET ADD A,E MOV C,A :10B: CALL OPAD ;RESET OFFSET HARDWARE XRA A ;CLEAR ENTRY KEY JR GKEYX ;EXIT :10C: CMP ' ' JC :20 ;IF LITERAL CMP '@' LDK C,0 JC :20 ;IF ILLEGAL CODE CALL NORM SUB '@' CMP ' ' JNC :20 ;IF ILLEGAL JR :19 ;CONVERTED CONTROL CODE ; CHECK FOR SHIFT KEY ; A= SHIFT STATUS ; C= CURRENT CHARACTER :17: BIT 5,A ;20H JRZ :20 ;IF NOT SHIFTED MOV A,C ;GET ACTUAL CHAR ; CHECK FOR LEGAL SHIFTED CODE :17B: CMP ',' JRC :19 ;IF IMPOSSIBLE SHIFT CMP '/'+1 JRNC :17C ;IF NOT ASCII REVERSE PAIRING ADD A,10H JR :19 :17C: CMP '0' LDK C,'^' JRZ :20 ;IF O, SHIFTED = '^' CMP '@' LDK C,'\' JRZ :20  page FORMT: ;Format one track ; Format will format one disk as specified by SDISK ; in IBM 3740 format consisting of 40 tracks, with each ; track containing 10 sectors. ; Entry BC = FWA of buffer ; BUF+0= DW length ; BUF+2= beginning of data ; SAVTRK = next track to format ; SAVSEC = 1 ; Drive already selected and ready ; Exit track formatted proc PUSH BC ;save address LD A,SAVTRK OR A JZ :2 ;if already on track LDK A,D.STPI CALL PSEKC ;perform step IN :2: LDK A,D.WRTT ;request write track DI CALL FDSK ;request write POP HL ;FWA of buffer EI RNZ ;if error DI ; Load BC with length and set ; HL = FWA of data to xmit to disk LD C,[hl] ! INC HL LD B,[hl] ! INC HL ;BC = length of xfer ; Now write out data :4: CALL XDD ;xfer to disk JRNZ :11 ;if error ; Pad rest of track with FFh :10: LD A,D.STSR OR A JRZ :11 ;if all done AND DS.DRQ JRZ :10 LDK A,0FFh STO A,D.DATR ;pad JR :10 ;continue ; Exit A=0, if no error :11: EI RE A=C= LAST KEY PROC CALL SKEY JRZ RKEY ;IF NO DATA DI MOV C,A XRA A STO A,LKEY ;CLEAR KEY FROM HOLD MOV A,C AND 7FH MOV C,A ;A=C EI RET SPACE 4,10 NORM: ;NORMALIZE TO UPPER CASE ; ENTRY A= CHAR ; EXIT A= CHAR CMP 'A' RC ;IF UPPER CMP 'Z'+1 RNC ;IF NOT LOWER SUI 'A'-'A' RET REPD = 45 ;INITIAL REP DELAY REPK = 5 ;REPEAT CONSTANT .NKBD IF @KEY = 0 ;IF NOT NEW KEYBOARD, USE OLD CODE GKEY: ;KEYBOARD INTERRUPT PROCESSOR. ; SCANS BOTH SETS OF DATA LINES TO SEE IF ANY KEY ; PRESSED. IF SO THEN DETERMINES KEY AND ; SETS TKEY TO VALUE. ; IF TKEY AND NEXT KEY SAME THEN HKCNT SET. ; IF HKCNT SET AND NO KEY ON THIS ENTRY, THEN ; LKEY IS SET AND WE HAVE FOUND A VALID KEY CLOSURE. ; ENTRY NONE ; EXIT CBIT SET IF KEY RNK5: = 21H ;RANK 5 RNK6: = 01H ;RANK 6 RNKCTL: = 0A0H ;CONTROL RANK PROC .MAC IF RSIZE = 64 DI .MAC ENDIF STO SP,IESTK ;SAVE INT PROCESS STACK LDK SP,ISTK ;SET TO RAM INT STK PUSHAL ; UPDATE AND DISPLAY CURRENT TIME ;IF @, SHIFTED = '\' CMP '[' LDK C,']' JRZ :20 ;IF [, SHIFTED = ']' CMP '1' JRC :19 ;IF NOT SHIFTABLE CMP 'A' JRNC :18 ;IF POSSIBLE ALPHA SUB 10H JR :19 :18: CALL NORM :19: MOV C,A ; HERE TO ACTUAL SET KEY ; ENTRY C= CURRENT KEYSTROKE VALUE :20: SBIT 7,C ;SET BIT 2**7 LD A,TKEY CMP C JRZ :16 ;IF LAST = CURRENT MOV A,C STO A,TKEY ;CONFIRM KEY (DEBOUNCE) STO A,LKEY LDK A,REPD STO A,HKCNT ;SET TO SURFACE NEXT TIME ; JR GKEYX ;EXIT ; RESTORE REGS, CLEAR INTERRUPT AND RETURN GKEYX: JMP EXITI ;EXIT INTERRUPT ; HERE IF DEBOUNCED KEY, PROCESS SHIFT, CONTROL AND ; REPEAT FUNCTIONS ; ENTRY C= CURRENT CHARACTER :16: LDK HL,HKCNT DEC [HL] ;RESET HOLD COUNT JRNZ GKEYX ;IF KEEP HOLDING MOV A,C :16A: STO A,LKEY ;SHOW KEEP TO USER MOV C,A ;SAVE CURRENT KEY LDK A,REPK STO A,HKCNT ;RESET HOLD FOR REPEAT JR GKEYX ;EXIT PAGE RDKEY: ;READ KEYBOARD FOR VALID KEY PRESSURE ; EXIT A= CURRENT KEY ; IF A = -1, EXIT TO GKEYX ; = -2, NO IN NON-CNTRL KEY RANKS. CHECK FOR TAB, ; ELSE KEY DOWN IS TO BE IGNORED. :5: LDK HL,T5KEY LD A,CKEY OR A JRZ :NOKEY ;IF NO CNTL-KEY SENSED EITHER CALL DRNK ;CHECK FOR TAB CMP TAB RZ ;IF TAB :NOKEY: LDK A,-2 ;INDICATE NO KEY, JUST CNTRL RET ; HERE IF FOUND KEY DOWN I NON-CNTRL RANKS ; HL = RANK ADDRESS ; A = VALUE ; B = 7..1, 7-(ORDINAL OF RANK) :7: PUSH AF ;SAVE VALUE LK A,8 SUB B ;A = ORDINAL OF RANK RLC ! RLC ! RLC ;*8 TO GET ADDRESS MOV E,A LDK HL,T5KEY ;BASE FOR DECODE LDK D,0 ADD HL,DE ;GET KEY DECODE BASE POP AF DRNK: ;DECODE RANK VALUE ; ENTRY A= RANK VALUE READ ; HL=FWA OF RANK ENTRY ; EXIT A= KEY VALUE IN ASCII LDK BC,-1 OR A ;CLEAR CARRY :8: INC BC ;UPDATE BASE ADDER RRC JRNC :8 ADD HL,BC LD A,[HL] ;GET ACTUAL KEY RET .RDKEY ENDIF PAGE ; CHARACTER INPUT TRANSLATION TABLE IF @KEY = 0 T5KEY: DB ESC, ESC, ERC, ERC, ERC, ERC, ERC, ERC ;5KEY: DB TAB, ESC, ERC, ERC, ERC, ERC, ERC, ERC DB '1', '2', 'S STO 0,[HL] ;RESET SECONDS DEC HL LD A,[HL] ! INC A ! DAA ! STO A,[HL] CMP 60H RC ;IF NOT 60 MINUTES STO 0,[HL] DEC HL LD A,[HL] ! INC A ! DAA ! STO A,[HL] CMP 25H RC ;IF TIME <= 24:59:59 STO 1,[HL] RET PAGE CO: ;OUTPUT ROUTINE FOR MONITOR ; ENTRY C= CHAR ; CO WILL PROCESS ^P TO TOGGLE ; ECHO TO LIST DEVICE ALA CPM. ; EXIT C=C=A. PROC MOV A,C CMP 'P'-40H JRNZ :5 ;IF NOT TOGGLE ECHO LIST LD A,ECHOP CMA STO A,ECHOP ;TOGGLE LIST ECHO :2: MOV A,C ;PERSERVE A RET :5: CALL COUT ;OUTPUT CHAR LD A,ECHOP OR A JRZ :2 ;IF NO ECHO TO LIST JMP LIST ;ECHO IT PAGE ; BIT DEFINITIONS FOR ESCH FLAG BYTE ; NOTE BIT 7 IS CURRENTLY FREE. EF_X: = 64 ;B6= EXTEGTING X-COORDINATE EF_SCR: = 32 ;B5= SCREEN/CURSOR ADDRESSING EF_ADR: = 16 ;B4= EXPEGTING ADDRESS-CHR EF_ESC: = 8 ;B3=$LAST CHAR WAS ESC EF_UN: = 4 ;B2= UNDERLINE MODE EF_HA: = 2 ;B1= HALF INTENSITY MODE EF_GR: = 1 ;B0= GRAPHICS MODE EF_MSK: = EF_UN+EF_HA+EF_GR ;MASK TO GET MODE. KEY PRESSURE PROC .RDKEY IF @KEY = 0 LD A,H.KEY+0DFH CMA MOV B,A LD A,H.KEY+07FH ;EVERYTHING BUT CNTRL RANK CMA OR B LDK A,-2 RZ ;IF NO KEY PRESSURE ; SAVE ANY CONTRL KEYS LD A,H.KEY+RNKCTL CMA STO A,CKEY ;SAVE CONTROL KEY ; B <> 0 MEANS BIT 5 TABLE MOV A,B OR A JRZ :5 ;IF BIT 5 TABLE :3: LDK HL,H.KEY+1 LDK DE,T6KEY-1 JR :5A ;PROCESS ; HERE IF BIT 5 SET :5: LDK HL,H.KEY+21H LDK DE,T5KEY-1 :5A: LDK BC,0 :5B: LD A,[HL] ;GET NEXT SCAN LINE CMA OR A JRNZ :6 ;IF KEY ACTIVE PUSH BC LDK IX,SCANI ADD IX,BC LD C,[IX+0] ADD HL,BC ;NEXT LINE POP BC INC BC JR :5B ;LOOP TO NEXT SCANI: DB 1,2,4,8,30H,40H ; HERE WITH C = ADDRESS LINE ; A= KEY DOWN BIT :6: PUSH AF ; CHECK FOR CONTROL KEY RANK MOV A,L CMP RNKCTL JRNZ :6A ;IF NOT CONTROL RANK LD A,H.KEY+0DFH CMA OR A JRNZ :3 ;IF KEY ACTIVE IN OTHER RANK STO A,TKEY ;CLEAR KEY POP AF ;RESTORE STACK LDK A,-1 ;INDICATE EXIT RET ; PROCESS ACTIVE KEY :6A: MOV A,3', '4', '9', '0', ':', '-' ; DB '1', '2', '3', '4', '9', '0', '-', '~' DB 'Q', 'W', 'E', 'R', 'O', 'P', '@', 7FH ; DB 'Q', 'W', 'E', 'R', 'O', 'P', '{', '}' DB 'A', 'S', 'D', 'F', 'L', ';', BKS, FMFD ; DB 'A', 'S', 'D', 'F', 'L', ';', ':', '\' DB 'Z', 'X', 'C', 'V', ERC, '.', '/', ERC DB ' ', ERC, ERC, ERC, ERC, ERC, ERC, ERC DB ERC, ERC, ERC, REP, CAPS, SHTK, CTRL, ERC T6KEY: DB ERC, ERC, ERC, BKS, VTAB, ERC, ERC, ERC DB '6', '5', '7', '8', '[', ERC, ERC, ERC DB 'Y', 'T', 'U', 'I', '-', ERC, ERC, ERC DB 'H', 'G', 'J', 'K', CR, ERC, ERC, ERC DB 'N', 'B', 'M', ',', LF, ERC, ERC, ERC ELSE T5KEY: T6KEY: DB ESC, CTRL, CAPS, SHTK, CR, TAB, TAB, '_' DB '1', '2', '3', '4', '5', '6', '7', '8' DB 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I' DB 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K' DB 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',' DB MCUP, BKS, '0', ' ', '.', SPACE 4,10 ; VECTOR (BRANCH) TABLE FOR VIDEO OUTPUT MODE SELECTION ; CONTROLLED BY ESCH MODE ESCHTB: DW VNORM ;0 NORMAL MODE DW VGRAPH ;1 GRAPHICS MODE DW VHALF ;2 HALF INTENSITY MODE DW VHA_GR ;3 HALF AND GRAPHICS DW VUNDER ;4 UNDERLINE MODE DW VUN_GR ;5 UNDER AND GRAPHICS DW VUN_HA ;6 UNDER AND HALF INTENSITY DW VUN_HA_GR ;7 UNDER AND HALF AND GRAPHICS SPACE 4,10 VALIDE: ;VALID ESC-SEQUENCE TABLE ; 3 BYTES PER ENTRY:ASCII CHAR , "DW"-VECTOR. ; NO. OF ENTRIES IS VALETS ; FOLLOWING BODY OF TABLE IS 2 BYTE NO-MATCH ADRS DB VCAD ! DW ESCCAD ;CURSOR ADDRESSING DB VSAD ! DW ESCSAD ;SCREEN ADDRESSING DB VSGH ! DW ESCSGR ;SET GRAPHICS MODE DB VEGH ! DW ESCCGR ;CLR GRAPHICS MODE DB VSHI ! DW ESCSHA ;SET HALF INT. MODE DB VEHI ! DW ESCCHA ;CLR HALF INT. MODE DB VSUL ! DW ESCSUN ;SET UNDERLINE MODE DB VEUL ! DW ESCCUN ;CLR UNDERLINE MODE DB VCLRS ! DW ESCZZ ;CLEAR SCREEN TO BLANKS DB VINC ! DW EINSRT ;INSERT CHAR DB VDELC ! DW EDELC ;DELETE CHAR DB VINL ! DW C ANI 7 ;GET RELATIVE TO 0 RAL ! RAL ! RAL ;*8 MOV C,A LDK B,0 EX DE,HL ;BASE TO HL ADD HL,BC LDK BC,0 POP AF ;GET BIT BACK OR A ;CLEAR CARRY ; NOW CONVERT BIT VALUE TO BINARY :7: INC C RRC JRNC :7 ;IF NOT BIT ADD HL,BC ;ADD IN VALUE ; GET ACTUAL KEY PRESSURE VALUE INTO A. LD A,[HL] ;GET TABLE VALUE RET .RDKEY ELSE LD A,H.KEY+0FFH XOR 0FFH ;1S COMPLEMENT, SET FLAGS MOV B,A LDK A,-2 RZ ;IF NO KEY ; READ CNTRL RANK AND SAVE LD A,H.KEY+01 CMA STO A,CKEY ;SAVE IT ; KEY DEPRESSED, CHECK FOR WHICH RANK, MAKE ; SURE ITS LEGAL, IE. NOT JUST CNTRL KEY. LDK DE,2 ;IGNORE CONTRL RANK LDK B,6 ;NUMBER OF RANKS-CNTRL RANK :3: LDK HL,H.KEY ;BASE ADD HL,DE ;ADDRESS OF NEXT RANK LD A,[HL] ;GET POSSIBLE ENTRY XOR 0FFH JRNZ :7 ;IF FOUND KEY PRESSURE DEC B JRZ :5 ;IF ALL DONE WITH SCAN EX DE,HL ;POWER OF 2 TO DE ADD HL,HL ;*2 EX DE,HL ;NEXT RANK TO DE JR :3 ;CONTINUE ; HERE IF SUPPOSE TO BE KEY DOWN, BUT NONE ; FOUND  'P', 'O', 'P' DB MCRIGH DB LF, ':', '/', ';', '\', '1', '-' ENDIF .NKBD ENDIF PAGE UPTIM: ;UPDATE TIME VIA 60HZ INTERRUPT ; TIME IS KEPT IN VIDEO MEMORY AS ; HHMMSS (3 LOCATIONS) ; ROUTINE ALSO CHECKS TO SEE IF THE DISK DRIVE MOTOR ; SHOULD BE TURNED OFF BY UPDATING DACTIVE ; ...ROUTINE ALSO CHECKS TO SEE IF BELL IS CURRENTLY ; RINGING: IF SO, DECREMENT COUNTER. ; IF COUNTER TURNS ZERO, SHUT OFF BELL. PROC LK HL,BELCNT XOR A OR [HL] ;CELL=ZERO ? JRZ :2 ;IF BELL NOW OFF DEC [HL] ;...BELL IS ON. DECREMENT COUNTER JRNZ :2 ;IF BELL SHOULD STAY ON AWHILE YET LD A,PIABD AND 1101_1111B ;CLEAR BELL BIT MOV C,A CALL OPBD :2: DEC HL ;HL => DACTVE LD A,[HL] OR A JRZ :3 ;IF INACTIVE DEC [HL] ;RESET DELAY CZ DDRV ;IF DESELECT DRIVE :3: DEC HL ;HL => SEC6 DEC [HL] RNZ ;IF NOT 1 SEC TRANSITION STO 59,[HL] ;60TH TICK IS NOW XOR A ;A:=0, CY:=0 FOR DAA DEC HL ;HL => SECS LD A,[HL] ! INC A ! DAA ! STO A,[HL] CMP 60H RC ;IF NOT 60 SECESCEE ;INSERT LINE DB VDELL ! DW ESCRR ;DELETE LINE DB VCEOL ! DW EEOL ;CLEAR TO END OF LINE DB VLOCK ! DW ESCLCK ;LOCK KEYBOARD DB VUNLK ! DW ESCULK ;UNLOCK KEYBOARD :END: DW COUT2 ;NO MATCH EXIT ; IGNORE CHAR UPON UNDEFINED ESC-SEQUENCE ; (TO TREAT UNDEFINED CHAR AFTER ESC AS A REGULAR ; DATA CHAR, SHOULD GO TO COUT2). VALETS: = (:END-VALIDE)/3 ;# OF ENTRIES IN TABLE SPACE 4,10 VALIDC: ;VALID CONTROL CHARACTER TABLE ; 3 BYTES PER ENTRY: ASCII CHAR , "DW"- VECTOR ; NO. OF ENTRIES IS VALCTS ; FOLLOWING BODY OF TABLE IS 2 BYTE NO-MATCH ADRS DB CR ! DW VC_CR ;CARRIAGE RETURN ROUTINE DB LF ! DW VC_LF ;LINE FEED DB BKS ! DW VC_BKS ;BACK SPACE DB MCRIGH ! DW VC_MCRT ;MOVE CURSOR RIGHT DB MCUP ! DW VC_MCUP ;MOVE CURSOR UP DB 'A'-40H ! DW VSHFT_L ;SHIFT SCREEN LEFT DB 'B'-40H ! DW VSHFT_R ;SHIFT RIGHT DB 'C'-40H ! DW VSHFT_0 ;LEFT COLUMN (^1) DB CBELL ! DW VC_BEL ;RING BELL DB VCLRS ! DW VC_CLRS ;CLEAR SCREEN DB VHOME ! DW VC_HOME ;CURSOR HOME ; DW VOUT9R TO A JR LOOKUPB ;GO TO ROUTINE TO BRANCH PER TBL SPACE 4,15 VNORM: ;NORMAL MODE CHARACTER PROCESSING. ; ENTRY A= CHAR TO OUTPUT ; HL=CURS CMP ' ' JRC :2 ;IF CONTROL CHR VBRIGH: DI ! ENADIM ;9TH BIT MEMORY STO BRTBIT,[HL] ;SET THIS CHR BRIGHT DISDIM ! EI JMP VOUT80 :2: PUSH HL ;SAVE CURS LDK HL,VALIDC ;BRANCH TABLE ADRS LDK E,VALCTS ;TABLE SIZE ; JMP LOOKUPB ;SCAN TABLE OF VALID CONTROL CHRS ; ;AND BRANCH TO APPROPRIATE ROUTINE. SPACE 4,20 LOOKUPB: ;LOGIC TO SCAN 3 BYTE BRANCH TABLE ; NOT A SUBROUTINE---DO NOT CALL. ; ENTRY HL =1ST BYTE OF TABLE (MATCH CODE) ; (2ND,3RD BYTES = BRANCH ADRS) ; (TABLE REPEATS [3 BYTE ENTRIES]) ; E IS TABLE SIZE (NO. OF ENTRIES) ; (TABLE BODY IS FOLLOWED WITH ; 2 BYTE "NO-MATCH" ADRS) ; STACK HAS HL SAVED AS TOP ENTRY. ; C = CHAR ; A = VALUE TO SCAN FOR POSSIBLE MATCH CMP [HL] INC HL ;(2ND BYTE OF THIS 3 BYTE ENTRY) JRZ VECTOR ;IF MATCH PROCESS INC HL ;(3RD BYTE OF THIS ENTRY) INC HL ;1ST BYTE OF NEXT ENTRY WILL BE X-COORD OR B JR :EXIT2 :CX: RAL ;TRASH 7TH BIT SRA H ;BIT0(H) -> CY, BIT7 STAYS 1 RAR ;... CY -> BIT7(A) MOV L,A ; JR :EXITX :EXITX: LK A,EF_MSK AND B ;FINISHED ADDRESSING: RESET ADDR BITS :EXIT2: STO A,ESCH JMP VOUT90 PAGE ; CONTROL CODE CHARACTER PROCESSING VC_HOME: ;HOME CURSOR PROC CALL UN_CUR LD A,PIABD RAR ;BIT0 => CY LK L,0 RR L ;CY => BIT7, TRASH BIT0 MOV H,A JR :FIXHL ;HL := HL OR F000H SPACE 4,7 VC_MCUP: ;MOVE CURSOR UP. ; A=C=CHR=MCUP. HL=CURS. CALL UN_CUR PUSH HL ;OLD CURSOR MUST BE ON STACK LK BC,(-VLL) JR :FWA ;...AT THIS ENTRY POINT SPACE 4,28 VC_BKS: ;HL=CURS=CURRENT (OLD) CHAR CALL UN_CUR ;CLEAR 80H BIT LK A,7FH AND L JRZ :WRAP ;IF MUST WRAP FROM COL 0 TO LLIMIT DEC HL JR VOUT90 ;EXIT :WRAP: PUSH HL ;SAVE OLD CURSOR LK BC,-(VLL+1) ADD HL,BC ;HL = PREV_LINE, (-1)ST COLUMN LD A,LLIMIT ;LLIMIT = #COLUMNS ON SCREEN MOV C,A LK B,0 :FWA: ADD HL,BC XTHL ;GET OLD CURSOR, SAVE NEW ADD7 ;NO MATCH--IGNORE UNDEF CONTROL CHAR ; VALCTS: = ((*-2)-VALIDC)/3 ;NUMBER OF VALID ENTRIES PAGE COUT: ;GENERAL OUTPUT ROUTINE TO VIDEO SCREEN ; ENTRY C=CHARACTER, CURS=CURSOR, ESCH=FLAG+MODE ; EXIT CURS & ESCH UPDATED, A=CHARACTER ; (BC, DE, HL PRESERVED) ; ; ESCH IS FLAG + MODE BYTE AS FOLLOWS ; =00 NORMAL MODE & LAST CHR ESC FLAG FALSE ; =08 NORMAL MODE & LAST CHR ESC FLAG TRUE ; =01,02,04 MODE IS GRAPHICS, HALF, OR UNDER, RESPECTIVELY ; , AND LAST CHR ESC FLAG IS FALSE. ; =3,5,6,7 AS ABOVE, BUT MODE IS COMBINATION ; =9-15 LAST CHR ESC FLAG TRUE;OTHERWISE LIKE 1-7. PROC PUSH HL PUSH DE PUSH BC LD HL,CURS ;HL WILL USUALLY BE CURSOR. LD A,ESCH MOV B,A ;B WILL BE ESCH FOR A WHILE AND EF_ESC ;TEST FLAG BIT JRNZ PSTESC ;IF LAST CHR WAS ESC ;CURRENT CHR IS NOT ESCAPED. IS THIS CHR ESC? MOV A,C ;CHR CMP ESC MOV A,B ;(A=ESCH) JRZ :ESC ;IF THIS CHR = ESC SPACE 4,10 ;HERE WITH A=B= ESCH :OUT: PUSH HL LK HL,ESCHTB AND EF_MSK ;MO DEC E ;DEC COUNT OF ENTRIES REMAINING JRNZ LOOKUPB ;CONTINUE THRU BODY OF TABLE JR VECTOR ;NO-MATCH. HL=POINTS TO VECTOR PAGE ; PROCESSING FOR MODES OTHER THAN NORMAL. ; -------------------------------------- ;VGRAPH = VOUT80 ;NORMAL MODE EXCEPT: CNTL CHRS ARE PRINTED VUNDER: ;UNDERLINE ONLY CMP ' ' JRC VNORM ;IF CNTL-CHR, PROCESS AS NORMAL ; JR VUN_GR ;CONTINUE VUN_GR: ;UNDERLINED GRAPHICS OR 80H ;UNDERLINE BIT JR VBRIGH ;SET THIS CHR BRIGHT VUN_HA: ;UNDERLINE AND HALF INTENSITY CMP ' ' JRC VNORM ;IF CNTL-CHR, PROCESS AS NORMAL ; JR VUN_HA_GR VUN_HA_GR: ;UNDERLINE, HALF INTENSITY, GRAPHICS OR 80H ;SET UNDERLINE BIT ; JR VHA_GR VHALF: ;HALF INTENSITY CMP ' ' JRC VNORM ;IF CNTL-CHR, PROCESS AS NORMAL ; JR VHA_GR VHA_GR: ;C=CHR, HL=CURS DI ENADIM STO DIMBIT,[HL] ;SET DIM FIELD BIT ; LD E,[HL] ;DIAGNOSTIC DISDIM EI JMP VOUT80 ;CONTINUE SPACE 4,22 SCREEN: ;SETXY FOR SCREEN MOVEMENT ; ENTRY B= ESCH ; A= NEW CO-ORD VAL, NO OFFSET P HL,HL ;SHIFT LINE# INTO H REG. LD A,PIABD OR 1110_0000B ;A = LINE# OF UL CORNER CMP H ;SET ZFLAG: @HOME? POP HL ;GET NEW CURSOR... JRNZ :FIXHL ;IF NOT @VIDEO HOME LK BC,(24*VLL) ;WRAP CONSTANT ADD HL,BC :FIXHL: LK A,0F0H OR H ;MODULO RESULT: KEEP CURSOR MOV H,A ;INSIDE VIDEO MEMORY. JR VOUT90 SPACE 4,8 VC_BEL: ;RING THE BELL VIA SETTING PIAB 2**5 BIT LD A,PIABD OR 0010_0000B ;BELL BIT MOV C,A CALL OPBD ;FUNCTION PIAB LK A,30 ;RING BELL FOR 30 TICKS STO A,BELCNT ;... = 1/2 SECOND JR VOUT97 ;EXIT NO CHANGE SPACE 4,10 VC_CLRS: LK HL,FWAVM CALL CLRLN ;CLEAR 1ST LINE LK BC,LVMEM-VLL CALL VLDIR ;CLEAR REMAINING LINES LD A,PIABD ;RESET FOR 1ST LINE OF DISPLAY MEM AND NOT(1_1111B) MOV C,A CALL OPBD LK HL,FWAVM ;NEW CURSOR JR VOUT90 ;EXIT SPACE 4,8 VC_CR: CALL UN_CUR ;ERASE CURSOR LK A,80H ;CARRIAGE RETURN AND L MOV L,A JR VOUT90 VC_LF: CALL DO_LF ;LINE FEED JR VOUT90 SPACE 4,3 VC_MCRT ;MOVE CURSOR RIGHT CALL UN_CUR LD ADE BITS ONLY ADD A,A ;TIMES TWO MOV E,A LK D,0 ;DE = OFFSET ADD HL,DE ;HL = TBL ADDRS VECTOR: ;ENTRY POINT. NOTE HL ON STACK. LD A,[HL] ;1ST BYTE (LOW ORDER ADRS) INC HL LD H,[HL] ;2ND BYTE (HI ORDER ADRS) MOV L,A ;HL=ADRS FROM TABLE XTHL ;RESTORE HL FROM STACK ;STACK=TBL ADRS MOV A,C ;CHR. NOTE B=ESCH BYTE VALUE RET ;ENTER ROUTINE PER TABLE ADRS. COUT2: MOV A,B ;RECALL ESCH VALUE JR :OUT ;OUTPUT CHR PER CURRENT SETTINGS :ESC: ;CURRENT CHR IS ESC. SET FLAG AND EXIT OR EF_ESC ;INDICATE LAST CHAR= ESC STO A,ESCH JMP VOUT97 ;EXIT SPACE 4,17 PSTESC: ;LAST CHR WAS ESC ; ENTRY A= EF_ESC ; B= ESCH ; C= CHAR TO OUTPUT ; HL=CURS PROC BIT 4,B ;IS THIS CHR REALLY AN ADDRESS? JRNZ SETXY ;...IF CHR IS PART OF AN ADDR ;NO CURSOR/SCREEN ADDRESSING IN EFFECT: XOR B ;CLR EF_ESC BIT (FOR NEXT TIME) MOV B,A ;SET UP B = ESCH BYTE VALUE. STO A,ESCH PUSH HL ;SAVE CURS LDK HL,VALIDE ;BRANCH TABLE ADRS LDK E,VALETS ;TABLE SIZE MOV A,C ;CHROC BIT 6,B JRNZ :SX ;IF X-COORDINATE :SY: AND 0001_1111B ;MOD 32 MOV C,A LD A,PIABD AND 1110_0000B OR C MOV C,A CALL OPBD ;SET Y COORDINATE JR :EXITY :SX: ADD A,A ;DOUBLE A ADD A,VFLO ;PIA A-REG MAGIC OFFSET CONSTANT AND 1111_1110B ;CLEAR BIT 0 => NO 1/2 CHR SHIFT MOV C,A CALL OPAD ;SET X COORDINATE CBIT 5,B ;FINISHED SCREEN-ADDRESSING JR :EXITX SPACE 4,10 SETXY: ;SET X-Y VALUE FOR CURSOR/SCREEN ADDRESSING ; ENTRY HL= CURSOR_ADDR ; B = ESCH ; C = CHR ; EXIT TO VOUT90; ESCH UPDATED CALL UN_CUR LK A,-(' ') ADD C ;REMOVE CURSOR BIAS BIT 5,B ;CURSOR/SCREEN ADDRESSING? JRNZ SCREEN ;IF SCREEN ADDRESSING ;CURSOR ADDRESSING: ADD HL,HL ;SHIFT HL LEFT BIT 6,B ;X/Y COORDINATE? JRNZ :CX ;IF X COORDINATE :CY: MOV H,A ;SAVE LD A,PIABD ADD H ;OFFSET BY START-Y CO-ORD OF VIDEO RAR ;BIT0(A) -> CY, SHIFT A RIGHT RR L ;CY -> BIT7(L) OR 0F0H ;TURN ON UPPER NYBL MOV H,A ;HL= NEW CURSOR ADDR ; JR :EXITY :EXITY: LK A,0100_0000B ;NEXT ADDR-CHR  ,[HL] ; JR VOUT80 ;RE-ECHO CURRENT CHR PAGE ; EXIT POINTS FOR COUT ; HERE TO STORE NEW DATA AND TO UPDATE CURSOR VGRAPH: VOUT80: STO A,[HL] ;THIS EXIT PATH STORES A (NEW CHAR) MOV E,L CBIT 7,E ;E = COL(CURSOR) LD A,LLIMIT DEC A ;A = LAST_LEGAL_COL SUB E ;A = LAST_LEGAL_COL - COL(CUR) JRNZ VOUT85 ;IF NOT @LLIMIT LK A,80H AND L MOV L,A ;DO CR... CALL DO_LF2 ;...AND LF. JR VOUT90 VOUT85: INC HL ;MOVE CURSOR ; HERE IF NO CURSOR UPDATE VOUT90: LD A,[HL] ;THIS EXIT PATH TURNS ON 80H BIT ; HERE IF NEW DATA ALREADY IN A VOUT95: RAL ;MAKE THIS CHR CURSOR VOUT96: CMC ;INVERT CURSOR BIT RAR STO A,[HL] STO HL,CURS ;UPDATE CURSOR ; HERE IF NO CHANGE TO CURSOR, RESTORE REG AND EXIT VOUT97: POP BC POP DE POP HL MOV A,C ;EXIT WITH A=CHR RET ;RETURN, END OF COUT SUBR. SPACE 4 :FIRST = VOUT97 - (127 + 2) ;EARLIEST POSSIBLE JR :LAST = VOUT80 + (128 - 2) ;LATEST POSSIBLE JR PAGE ESC_LCK: ;LOCK KEYBOARD PROC XOR A JR :2 ESC_ULK: ;UNLOSCCUN: LDK A,NOT EF_UN ;ESC-M CLEAR UNDERLINE :140: AND B ;CLEAR BIT JR :130 ;GO STORE ESCH BYTE ESCZZ: = VC_CLRS ;ESC-Z CLEAR SCREEN -SAME AS ; ;CONTROL-Z ROUTINE. PAGE PROC VSHFT_L: ;SHIFT SCREEN LEFT LK C,+2 JR :SLIDE VSHFT_R: ;SHIFT SCREEN RIGHT LK C,-2 :SLIDE: DI LD A,PIAAD ;GET OLD OFFSET ADD C ;MODIFY... MOV C,A :1: CALL OPAD ;NEW SETTING FOR VIDEO OFFSET EI JMP VOUT97 VSHFT_0: ;SHIFT TO COLUMN #0 (LIKE ^1) LK C,VFLO ;CONSTANT FOR COLUMN #0 JR :1 ;SET VIDEO OFFSET PAGE ESCRR: ;DELETE LINE ESCEE: ;INSERT LINE ; ENTRY HL = CURSOR ; C = CHR ; EXIT SCREEN UPDATED ; HL = NEW CURSOR ; ...TO VOUT90 PROC CALL UN_CUR LK A,1000_0000B AND L MOV L,A ;DO CR PUSH HL ;SAVE NEW CURSOR ADD HL,HL LD A,PIABD ADD A,24 ;A = ADDR(25TH LINE) SUB H ;A = LINES_TO_MOVE + 1 AND 0001_1111B ;MOD 32 MOV B,A LK A,VDELL CMP C MOV A,B ;RECALL #LINES TO MOVE JRZ :DELT ;IF DELETING A LINE SPACE 3,17 :INSRT: ;INSERT A LINE ADD HA,PIABD ADD A,23 ;START + 23 = LAST_VIDEO_LINE SUB H ;A = L_LINE - CURR_LINE AND 0001_1111B ;MODULO 32 JRZ :VMOV ;IF CURSOR IS ON 24TH LINE OF SCREEN :END: POP HL ;GET NEW CURSOR RET :VMOV: LD A,LLIMIT SRL L ;UNSHIFT L REGISTER SUB L ;A = LLIMIT - COL(CURSOR) JRC :END ;IF CURSOR IS OUTSIDE LOGICAL LINE ;CURSOR IS ON LAST LINE OF SCREEN, INSIDE OF LOGICAL LINE. ;MUST MOVE SCREEN TO FOLLOW CURSOR DOWN THROUGH VIDEO MEMORY. POP HL PUSH HL LK A,80H AND L MOV L,A ;HL = BEGINNING OF LINE CALL CLRLN ;ERASE TO EOL LD A,PIABD MOV B,A AND NOT 31 ;A = LINE ZERO MOV C,A ;C = HOUSEKEEPING BITS 5..7 LK A,31 INC B ;INCREMENT LINE# AND B ;A = LINE# OR C ;A = NEW LINE# OR HOUSEKEEPING_BITS MOV C,A ;C = NEW VALUE FOR OPBD CALL OPBD ;MOVE VIDEO SCREEN DOWN 1 LINE IN MEMORY POP HL RET SPACE 4,12 VLDDR: ;VIDEO BLOCK MOVE ; ENTRY BC, DE, HL SET ; EXIT LDDR ON MAIN & 9TH BIT MEMORY ; USES BC, DE, HL PUSH BC ! PUSH DE ! PUSH HL LDDR ;MAIN MEMORY POP HL ! POCK KEYBOARD LK A,0FFH :2: STO A,KEYLCK JR VOUT97 SPACE 4,5 EEOL: ;ERASE TO END OF LINE PUSH HL ;SAVE CURSOR CALL CLRLN POP HL JR VOUT90 SPACE 4,12 ESC_CAD: ;CURSOR ADDRESSING LK A,EF_MSK AND B OR EF_ESC OR EF_ADR ;NEXT CHR WILL BE Y-COORD :EXIT3: STO A,ESCH JR VOUT97 ESC_SAD: ;SCREEN ADDRESSING LK A,EF_MSK AND B OR EF_ESC OR EF_ADR OR EF_SCR JR :EXIT3 PAGE ;SUBROUTINE FOR USE WITH EDELC AND EINSRT: ;CALCULATE #CHRS TO MOVE; IF MOVE ZERO CHRS, NEVER RETURN. PROC :CALC: LK A,VLL-1 ;A= MAX #CHRS TO BE MOVED MOV C,L CBIT 7,C ;C = COL(CURSOR) SUB C ;A = #CHRS TO MOVE JRZ :END ;IF MOVE ZERO CHARACTERS MOV C,A LK B,0 ;BC = #CHRS TO MOVE RET :END: POP HL ;TRASH RETURN_ADDR POP HL ;CURSOR_ADDR JR VOUT90 SPACE 4,14 EDELC: ;DELETE CHARACTER PUSH HL ;SAVE CURSOR_ADDR CALL :CALC ;CALCULATE BC MOV D,H MOV E,L ;DE = CURSOR_ADDR INC HL ;HL = CURSOR_ADDR + 1 CALL VLDIR ;MOVE CHARACTERS STO ' ',[HL] ;LAST CHR BECOMES BLANK DI ! ENADIM ; ;A = ADDR(25TH LINE) MOV D,A LK E,0 RR D ! RR E ;SHIFT RIGHT DE DEC DE ;DE = ADDR(LST_CHR_ON_LST_LINE) MOV A,B ;A = #LINES TO MOVE LK HL,-VLL ADD HL,DE ;HL = ADDR(LINE ABOVE DE) ;DE := DE OR F000H; HL := HL OR F000H JR :ISTRT :ICONT: CALL VLDDR ;MOVE 1 LINE DOWN :ISTRT: CALL :VMOD JRNZ :ICONT ;IF MUST MOVE MORE LINES INC HL ;HL => 1ST CHR OF NEW LINE ; JR :EXIT SPACE 3,3 :EXIT: CALL CLRLN POP HL ;RECOVER CURSOR JMP VOUT90 ;MAIN EXIT SPACE 3,11 :DELT: POP DE ;RECOVER NEW CURSOR PUSH DE LK HL,VLL ADD HL,DE ;HL = LINE_BELOW_CURSOR JR :DSTRT :DCONT: CALL VLDIR ;MOVE 1 LINE UP :DSTRT: CALL :VMOD JRNZ :DCONT EX HL,DE ;GET ADDR OF LINE TO CLEAR JR :EXIT SPACE 3,13 ;HL := HL OR F000H; DE := DE OR F000H; ;SIMPLE MOD-4096 ARITHMETIC TO KEEP POINTERS INSIDE VIDEO MEMORY :VMOD: PUSH AF ;SAVE A = #LINES TO MOVE LK A,0F0H OR H MOV H,A ;SET UPPER NYBL OF H LK A,0F0H OR D MOV D,A ;MODULO 4096 LK BC,VLL POP AF DEC A ;DECREMENT LINE_P DE ! POP BC DI ENADIM LDDR ;9TH BIT MEMORY DISDIM EI RET SPACE 4,12 VLDIR: ;VIDEO BLOCK MOVE ; ENTRY BC, DE, HL SET ; EXIT LDIR ON MAIN & 9TH BIT MEMORY ; USES BC, DE, HL PUSH BC ! PUSH DE ! PUSH HL LDIR ;MAIN MEMORY POP HL ! POP DE ! POP BC DI ENADIM LDIR ;9TH BIT MEMORY DISDIM EI RET SPACE 4,10 UN_CUR: ;UNDO/INVERT CURSOR ; ENTRY HL = CURSOR_ADDR ; EXIT CURSOR INVERTED ; USES A, CY. LD A,[HL] ;GET THE CHR RAL ;CURSOR_BIT => CY CMC ;INVERT IT RAR STO A,[HL] ;... RET ; ENDX BMKEY.ASM ***************** Title 'bmSCAN - Keyboard scanning & decode' GKEY: ;Keyboard Interrupt processor ; Entry None ; Exit keyboard processing done, result in LKEY. ; system clock updated by UPTIM. Proc DI STO SP,IESTK ;save INTerrupted process stk LK SP,ISTK ;set to RAM int stk PUSHAL CALL UPTIM ;update system clock LD A,KEYLCK OR A JRZ GKEYX ;if locked keyboard :SCAN: CALL RDKEY ;scan keyboard CMP -2 JRZ GKEYAB ;ENABLE 9TH BIT MEMORY DEC HL ;HL = LAST CHR ON THIS LINE STO BRTBIT,[HL] ;SET CHR BRIGHT DISDIM ! EI ;MAIN MEMORY POP HL ;RESTORE CURSOR_ADDR JR VOUT90 ;NEXT SPACE 4,14 EINSRT: ;INSERT CHARACTER CALL UN_CUR PUSH HL ;SAVE CURSOR_ADDR CALL :CALC ;CALCULATE BC LK A,7FH OR L MOV L,A ;HL = LAST_CHR ON THIS LINE MOV E,A MOV D,H ;DE = HL DEC HL CALL VLDDR ;DO MOVE POP HL ;RESTORE CURSOR LD A,[HL] ;GET UNDERLINE BIT OF THIS CHR. RAL ;INTO CY LK A,' ' SHL 1 ;CHANGE THIS CHR TO ' ' JR VOUT96 ;EXIT PAGE ; ESC-SEQUENCE PROCESSING. PROC ESCSGR: LDK A,EF_GR ;ESC-G JR :125 ;SET GRAPHICS MODE. ESCSHA: LDK A,EF_HA ;ESC-) SET HALF INTENSITY JR :125 ;GO SET FLAG BIT ESCSUN: LDK A,EF_UN ;ESC-L SET UNDERLINE :125: OR B ;REG B IS ESCH BYTE VALUE :130: STO A,ESCH ;STORE DESIRED VALUE. JR VOUT97 ;EXIT ESCCGR: LDK A,NOT EF_GR ;ESC-G CLEAR GRAPHICS MODE JR :140 ;GO CLEAR ESCH BIT ESCCHA: LDK A,NOT EF_HA ;ESC-( CLEAR HALF INTENSITY JR :140 ECOUNT RET SPACE 4,30 CLRLN: ;CLEAR TO END OF LINE ; ENTRY HL= CURSOR ; EXIT CLEAR TO EOL ; USES ALL. PROC STO ' ',[HL] ;CLEAR CURSOR... DI ENADIM STO BRTBIT,[HL] ;SET CURSOR BRIGHT DISDIM EI LD A,LLIMIT DEC A ;MAX_#COLS => MAXIMUM_COL_# MOV E,L CBIT 7,E SUB E ;A = COL(EOL) - COL(CURSOR) RZ ;IF @EOL, DONE JRNC :2 ;IF INSIDE LOGICAL_VIDEO_LINE LK A,VLL SUB E ;...ELSE CLR TO END OF 128-CHR LINE RZ ;IF CURSOR @ COLUMN #127 :2: MOV C,A LK B,0 ;BC = CHRS TO MOVE MOV E,L MOV D,H INC DE ;DE = HL + 1 JR VLDIR PAGE DO_LF: ;DO LINE FEED PROCESSING ; ENTRY HL = CURSOR_ADDR ; EXIT CURSOR CLEARED ; HL UPDATED FOR CURRENT CURSOR POS ; WINDOW MOVED IF NECESSARY PROC CALL UN_CUR ;CLEAR CURSOR DO_LF2: PUSH HL ;SAVE ORIGINAL CURSOR LK BC,VLL ;LINE LENGTH ADD HL,BC JRNC :NOWAP ;IF NOT WRAPPING FROM LWAVM TO FWAVM LK BC,FWAVM ADD HL,BC ;HL = NEW CURSOR @ TOP OF VM :NOWAP: XTHL ;SAVE NEW CURSOR, GET OLD ADD HL,HL ;SHIFT HL LEFT LD  if no key being pressed ;Debounce the Keyboard: LK HL,TKEY CMP [hl] ;same as last time? (set Z flag) STO A,[hl] ;set TKEY to current value MOV B,A ;save chr LK HL,HKCNT JRNZ :1st ;if this is first such keypress MOV A,[HL] CMP 0 JZ :2ND ;SECOND TIME FOR THIS KEY :AUTO: DEC [HL] JRNZ GKEYX ;IF STILL WAITING FOR REPD/REPK STO REPK,[HL] ;...ELSE SET REPK FOR NEXT CHR, JR :DCODE ;AND RETURN CHR :1ST: LD A,KBDLY ;GET # OF INTERRUPTS TO DEBOUNCE CALL DELAY XRA A ;ZERO "HKCNT" STO A,HKCNT JR :SCAN :2ND: STO REPD,[HL] ;SET "REPD" DELAY :dcode: MOV A,B ;restore chr CALL SHIFT ;shift processing LK HL,CKEY BIT 2,[hl] ;ck for CNTL key JRZ :fin ;if CNTL-key is NOT pressed CALL SLIDE ;ck for screen slide keys CALL CNTRL ;cntrl key processing :fin: OR 80h ;set parity bit for CI STO A,LKEY ;make chr available to CI GKEYX: JMP EXITI ;exit interrupt GKEYAB: ;Abort Processing: set TKEY := -2 and return. LK A,-2 STO A,TKEY JR GKEYX  '`' , ('}'), 7Fh SLIDE: ;process ^1, ^2, ^3, ^(larrow), ^(rarrow) ; Entry A = chr, CNTL key pressed ; Exit 1) RET if chr not a special SLIDING chr ; 2) to GKEYX after acting on SLIDING chr Proc LK C,+2 CMP MCLEFT ;left arrow JRZ :slide LK C,-2 CMP MCRIGH ;right arrow JRZ :slide CMP '1' RC ;if not a SLIDING chr LK C, VFLO + 2*00 ;set screen to 0th column JRZ :set CMP '4' RNC ;if >3, not a SLIDING chr LK C, VFLO + 2*52 ;set 52nd col CMP '2' JRZ :set LK C, VFLO + 2*104 ;set 104th col JR :set :slide: LD A,PIAAD ;old screen offset value ADD A,C MOV C,A :set: CALL OPAD ;move the screen LK A,1 STO A,HKCNT ;short-circuit debounce/auto-repeat ;delay logic POP DE ;CLEAR STACK JMP GKEYX ;ignore RET-addr on stk: ;stk will be reset on next irupt. page RDKEY: ;Scan keyboard ; Entry none ; Exit A = chr (if available) ; -2 (if no key pressed) Proc LD A, H.KEY + 0FFh ;read ALL keyboard ports XOR 0FFh ;invert all  LF, '-', '/', ';', '\', 'l', '=' ; ENDX BMSCAN.ASM e (0..7) RAL ! RAL ! RAL ;A := A * 8 MOV C,A LK B,0 ;BC = offset into table LK HL,T5KEY ;HL = FWA(table) ADD HL,BC ;HL => rank(key) page MOV A,D ;restore data from keyboard LK BC, 0800h ;B := 8, C := 0 :loop2: RRC ;shift corresponding bit into CY JRNC :3 ;if didn't find bit this time thru DEC C ;...else record that a key was pressed ; MOV E,B ;don't need to save loop-index LD D,[hl] ;get chr from table :3: INC HL ;...else try next chr & bit DJNZ :loop2 INC C JZ :EXIT LDK A,-2 RET :exit: MOV A,D ;return chr in A RET space 4,10 T5KEY: T6KEY: DB ESC, TAB, ERC, ERC, ERC, CR, '''', '[' DB '1', '2', '3', '4', '5', '6', '7', '8' DB 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i' DB 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k' DB 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',' DB MCUP, BKS, '0', ' ', '.', 'p', 'o', '9' DB MCRIGH,  page SHIFT: ;Shift key processing ; Entry A = chr from RDKEY ; Exit A = shifted value from SHIFT and ALPHA LOCK keys Proc CMP ' ' + 1 RC ;if cntl-chr (<=space), unshiftable LK HL,CKEY BIT 4,[hl] ;shift key bit JRNZ :shift ;if shift key pressed BIT 3,[hl] ;alpha lock key bit JRNZ :alpha ;if alpha key pressed RET ;if no shifting necessary :shift: CMP 'a' JRNC :alpha ;if 'a'..'z' CMP '[' JRC :tblsf ;if chr < '[', use shift table ;must be '[' or '\' JRNZ :alphx ;if '\', shift as alpha LK A,']' RET ;...else '[' shifted is ']' :tblsf: MOV E,A LK D,0 ;DE = chr LK HL, :stbl - '''' ;table FWA - apostrophe ADD HL,DE ;HL => shifted character LD A,[hl] ;A = shifted chr RET :alpha: CMP 'a' RC ;if <'a', ignored by ALPHA lock :alphx: XOR 20h ;UPPER/lower case bit RET ;shifted "comma" becomes "less than", ;shifted "hyphen" becomes "underbar", (etc.) ; ''', ...these 4 are unused :stbl: DB '"', '{', '}', '|', '~' ; ',', '-',bits, set flags LK A,-2 RZ ;if no key is pressed LDK HL, H.KEY + 001h ;control key rank MOV A,L ;ADDR BYTE TO A MOV R,A LD A,[hl] ;read control rank CMA ;complement the 1s STO A,CKEY ;save for shift & ctrl procs AND 1110_0011b ;clear SHIFT, CNTRL, & ALPHA bits LK BC,0700h ;loop 7 times, C := 0 JR :midle ;jump into middle of :loop1 :loop1: SLA L ;shift rank-select bit left MOV A,L ;ADDR BYTE TO A MOV R,A LD A,[hl] ;read rank XOR 0FFh ;invert 1s, set flags :midle: JRZ :2 ;if no key pressed in this rank DEC C ;record that a key was pressed MOV E,B ;record 7-rank# of key pressed MOV D,A ;save the data read :2: DJNZ :loop1 ;if not finished reading all ranks INC C ;ck for C = -1 JRZ :fbit ;if found EXACTLY ONE key press ;here if found 1) no keys pressed ; 2) many (more than 1) keys pressed LK A,-2 ;return NO keys pressed RET ;here to find the key pressed in a particular rank: ;load up the appropriate table entry & re '.', '/', '0', '1', '2', '3', '4', '5' DB '<', '_', '>', '?', ')', '!', '@', '#', '$', '%' ; '6', '7', '8', '9', (:), ';', (<), '=', (>) DB '^', '&', '*', '(', ' ', ':', ' ', '+', ' ' page CNTRL: ;Control key processing ; Entry A = chr, CNTL key pressed simultaneously ; Exit A = ^chr Proc CMP ' ' + 1 RC ;if space, TAB, ESC, RET, etc. CMP '@' JRC :cheat ;IF <'@', CK FOR CHEATED CHR CMP 'z'+1 JRNC GKEYAB ;if greater than 'z', no cntl-chr AND ' ' - 1 ;kill cntl & lowercase bits RET :cheat: MOV B,A ;save chr AND ',' CMP ',' JRNZ GKEYAB ;if not a legal cheated chr MOV A,B ;restore chr LK HL,:tbl1-',' CMP '/'+1 ;ck for 1st group JRC :look ;if in :tbl1 LK HL,:tbl2-'<' ;...else in :tbl2 :look: ADD L ;do indexed load from base in HL MOV L,A JRNC :get INC H ;if carry, propagate into H :get: LD A,[hl] RET space 3 ; , - . / :tbl1: DB '{' , '_'-40h, '}' , '~' ; < = > ? :tbl2: DB ('{'),turn. ; Entry D = data read from keyboard ; E = 7-rank# of above data :fbit: LK A,7 ;#ranks SUB E ;A = table row to use (0..7) RAL ! RAL ! RAL ;A := A * 8 MOV C,A LK B,0 ;BC = offset into table LK HL,T5KEY ;HL = FWA(table) ADD HL,BC ;HL => rank(key) page MOV A,D ;restore data from keyboard LK BC, 0800h ;B := 8, C := 0 :loop2: RRC ;shift corresponding bit into CY JRNC :3 ;if didn't find bit this time thru DEC C ;...else record that a key was pressed ; MOV E,B ;don't need to save loop-index LD D,[hl] ;get chr from table :3: INC HL ;...else try next chr & bit DJNZ :loop2 INC C JZ :EXIT LDK A,-2 RET :exit: MOV A,D ;return chr in A RET space 4,10 T5KEY: T6KEY: DB ESC, TAB, ERC, ERC, ERC, CR, '''', '[' DB '1', '2', '3', '4', '5', '6', '7', '8' DB 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i' DB 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k' DB 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',' DB MCUP, BKS, '0', ' ', '.', 'p', 'o', '9' DB MCRIGH,   TITLE 'MONITOR MAIN LOOP.' DISDIM ;DISABLE DIM JMP BMON ;RESET/RESTART USER: ;EXIT TO USER PROGRAM FROM 'G' COMMAND EI ! RET ;EXIT FROM G COMMAND .MAC IF RSIZE = 48 LIST G ; LEVEL 1 = BREAKPOINT ORG 1*8 IBKP: DI JMP PBKP ;PROCESS BREAKPOINT NULINT 2 NULINT 3 ; LEVEL 4 = KEYBOARD INT4: DI ;KEYBOARD INTERRUPT JMP GKEY NULINT 5 ; LEVEL 6 = SERIAL INTERRUPT NULINT 6 DI ; JMP ILINT LIST * .MAC ELSE .PBKP IF DEF PBKP ORG 1*8 IBKP: DI JMP PBKP ;PROCESS BREAKPOINT .PBKP ENDIF .MAC ENDIF ILINT: ;HERE ON UNKNOWN INTERRUPT .MAC IF RSIZE = 64 DI .MAC ENDIF DISDIM STO SP,IESTK ;SAVE INTERRUPTED PROC STACK LDK SP,ISTK ;INSURE STACK IN RAM PUSHAL ;SAVE ALL REGISTERS LDK A,'I' STO A,MPCHR ;SET PROMPT TO INTER LEVEL EXITI: ;EXIT INTERRUPT CODE VIA EXITING TO RAM AND ; THEN ENABLE OR DISABLE ROM CODE DEPENDING ON ; THE VALUE CONTAINED IN ROMRAM CELL. LD A,H.VIO ;CLEAR INTERRUPT LD A,ROMRAM OR A JNZ RORAME ;IF RETURN TO RAM, CPM  CMP [HL] INC HL JRZ :4 ;IF COMMAND MATCH INC HL ! INC HL DJNZ :3 ;IF NOT END JMP ERROR ;IF ILLEGAL ; HERE ON COMMAND MATCH :4: LD A,[HL] INC HL LD H,[HL] MOV L,A LDK C,2 JMP [HL] ;PROCESS COMMAND .MAC ENDIF PAGE HINT: ;INITIALIZE ALL DEPENDENT HARDWARE. ; ENTRY NONE. ; EXIT ALL HARDWARE INITIALIZED. ; SET FLAG INDICATING IN ROM ENAROM DISDIM ;DISABLE DIM BIT .MAC IF RSIZE = 48 IM0 ;MODE 0 MACHINE .MAC ELSE LDK HL,GKEY STO HL,INTBL+(4*2) ;SET KEYBOARD INTERRUPT IM2 LDK A,HIGH INTBL MOV I,A ;SET INTERRUPT PAGE .MAC ENDIF ; INITIALIZE KEYBOARD XRA A STO A,BELCNT ;CLEAR BELL TIMER CELL STO A,LKEY ;CLEAR LAST KEY CELL STO A,HKCNT ;CLEAR DEBOUNCE STO A,ECHOP ;CLEAR ECHO TO LIST DEV STO A,ESCH ;CLEAR ESC HOLD FLAG CMA STO A,IDAY ;SET DATE INVALID FOR SETUP.COM STO A,TKEY ;CLEAR HOLDING KEY STO A,KEYLCK ;INDICATE NOT LOCKED ; LDK HL,FWAVM ; STO HL,CURS ;SET CURSOR LDK A,VLL STO A,LLIMIT ;SET MAX LINE LIMIT ; SET KEYBO CALL CO ;PROMPT :2: CALL GETCH ;GET NEXT CHAR CMP ' ' JRZ :2 ;IF LEADING BLANK LDK B,NCMDS LDK HL,CTAB :3: CMP [HL] INC HL JRZ :4 ;IF COMMAND MATCH INC HL ! INC HL DJNZ :3 ;IF NOT END JMP ERROR ;IF ILLEGAL ; HERE ON COMMAND MATCH :4: LD A,[HL] INC HL LD H,[HL] MOV L,A LDK C,2 JMP [HL] ;PROCESS COMMAND .MAC ENDIF ; ENDX BMLOP TITLE 'MROMD - Debug Monitor ROM data and constants.' ; ROM storage and constants IMMSG: ;Sign-on message to user, Version is current date for ; this assembly. DB cr DC lf ; DB 'OCC-1 ' ; DB ' SORCIM Monitor ' ; VFD 16\VER,8\'.',16\LEVEL ; DC ' ' IBMSG: DB 'Z'-40h,lf,lf,lf,lf DB ESC,VSGH DB 'Q'-40h DB 07Fh, 24, 'W'-40h DB 'E'-40h DB ESC,VEGH DB cr,lf DB ESC,VSGH,1, ESC,VEGH DB ' ' DB ESC,'l' DB 'Osborne System ONE.' DB ESC,'m' DB ' ' DB ESC,VSGH,4, ESC,VEGH DB cr,lf DB ESC,VSGH DB 'A'-40h DB 07Fh,24,' ' DB 'D'-40h DB ESC,VEGH DB cr,lf DB ESC,VSGH DB 'A'-40h DB '  .MAC IF RSIZE = 48 JR RESREG .MAC ELSE POPALL LD SP,IESTK ;GET USERS STACK BACK EI ! RET .MAC ENDIF .MAC IF RSIZE = 64 BMON: DI LDK SP,ROMSTK LDK A,0 STO A,SEC6 STO A,SDISK ;SET DISK TO DRIVE 0 CALL HINT ;INITIALIZE HARDWARE LDK HL,(HIGH MRAM)*100H STO HL,SSAVE ;INITIALIZE USER STACK IN RAM LDK HL,0 STO HL,LDSEL ;CLEAR SELECT AND LAST TRACK LDK DE,IBMSG CALL OSTR ;OUTPUT INITIAL MESSAGE JR BMON1 ;CONTINUE .MAC ENDIF IF * > NMIA MSG 'ILINT CODE IS TOO LARGE ', * ERROR ENDIF SPACE 4,10 ORG NMIA DI JMP BMON ;NMI PAGE ; MAIN START UP FOR MONITOR. IF RSIZE = 48 BMON: DI LDK SP,ROMSTK LDK A,0 STO A,SEC6 STO A,SDISK ;SET DISK TO DRIVE 0 LDK C,' ' ;FILL WITH BLANKS CALL FVIO ;CLEAR VIDEO MEMORY CALL HINT ;INITIALIZE HARDWARE LDK HL,(HIGH MRAM)*100H STO HL,SSAVE ;INITIALIZE USER STACK IN RAM LDK HL,0 STO HL,LDSEL ;CLEAR SELECT AND LAST TRACK LDK DE,IBMSG CALL OSTR ;OUTPUT INITIAL MESSAGE ENDIF ; GET 1ST USER RESPONARD DEBOUNCE DELAY CELL LK A,KBDTM ;DEBOUNCE CONSTANT STO A,KBDLY ;SET DEBOUNCE-DELAY CELL ; NOW FUNCTION PIA TO SET STARTING ADDRESS ; AND CONTINUE TO MOVE DISPLAY WINDOW OVER ; THE FIRST DISPLAY LINE. ; SET CURSOR AS 1-40 ON 1ST LINE. CALL SPAO ;SET UP FOR OUTPUT LDK C,VFLO CALL OPAD ;SET FOR -10 CHAR POSITIONS ; SET BEGINNING LINE TO 0 LDK A,0 STO A,PIABD ;SET DATA REG MOV C,A CALL OPBD ;SET LINE ; RESET-MASTER CLEAR THE SIO (ACIA) LK C,SI.S16 ;SELECT 16X CLOCK FOR 1200 BAUD CALL SIRST ;RESET ; SET DEFAULT SEEK TO AS DEFINED BY SYSTEXT LDK A,SEEKTM ;DEFINED FROM SYSTEXT STO A,SEKDEL ;SET SEEK STEP RATE ; SET DEFAULT PROMPT CHAR LDK A,PMCHR STO A,MPCHR ;SET UP DEFAULT EI ! RET PAGE IF * > 100H MSG 'BMON IS TOO LONG > 100H ',* ERROR ENDIF ORG 100H ; JUMP VECTOR FOR DEBUGGER AND CP/M RVEC: JMP CBOOT ;COLD BOOT JMP WBOOT ;WARM BOOT JMP SKEY ;KEYBOARD STATUS JMP CI ;KEYBOARD INPUT JMP COUT ;CONSOLE OUTPUT JMP LIST ;LIS ' DB ESC,')' DB ' Rev A 180 ' DB ESC,'(' DB ' ' DB 'D'-40h DB ESC,VEGH DB cr,lf DB ESC,VSGH DB 'Z'-40h DB 07Fh, 24, 'X'-40h DB 'C'-40h DB ESC,VEGH DB cr,lf,lf,lf DB 'Insert disk in Drive ' DB ESC,'l' DB 'A' DB ESC,'m' DB ' and type RETURN' DC '.' BKPTA: DB CR DC 'Bkp' XCMDA: DB CR DC 'X ' ZCMDA: DB CR DC 'Zrg' ; Table of all valid Monitor command Characters COMAND MACRO CHR,ADR .incmd IF IN_%1_CMD DB '%1' IF ' %2' <> ' ' DW %2 ELSE DW %1_CMD ENDIF .incmd ENDIF ENDM CTAB: COMAND A ;Ascii core entry COMAND B,CBOOT ;Boot up system COMAND D ;Display memory COMAND F ;Fill memory COMAND G ;Go execute/breakpoint COMAND H ;Hex sum & difference COMAND M ;Move data COMAND R ;Read Intel-format hex COMAND S ;Substitute data into memory COMAND X ;eXamine register(s) COMAND T,DIAG ;Tests diagnostic section COMAND Z ;examine Z80 regs NCMDS EQU (*-CTAB)/3 ;NUMBER OF VALID COMMANDS space 4,10 ; Table of ALL 8SE. BMON1: CALL CI ;GET NEXT CHARACTER CMP CR LK HL,DSKSWP ;DISK SWAP CELL LK C,0 ;BOOT FROM A: STO C,[HL] ;SET TO A=A, B=B JZ CBOOT ;IF COLD BOOT IF INDIA INC [HL] ;SWAP DRIVES: A=B, B=A CMP '"' JZ CBOOT ;IF COLD BOOT OFF OF B CMP 'D'-40H JZ DIAG ;IF ENTER DEBUGGER JR BMON ELSE JR BMON1 ENDIF ; HERE ON NMI AND RESET ;BMNI: LDK SP,ROMSTK ;STACK MUST BE IN RAM (NOT 0,1 PAGE) ; CALL HINT ;INITIALIZE HARDWARE ; JMP DMON ;ENTER LOOP .MAC IF RSIZE = 48 RESREG: ;RESTORE REGISTERS AND EXIT INTERRUPT POPALL LD SP,IESTK ;GET USERS STACK BACK EI ! RET .MAC ENDIF PAGE .MAC IF INDMON ; MAIN LOOP FOR OSB DEBUG MONITOR. ; ENTRY NONE. ; EXIT TO COMMAND PROCESSOR. ; C= 2. DMON: LDK DE,IMMSG CALL OSTR ;OUTPUT SIGNON MESSAGE ; COMMAND PROCESSOR NEXTC: EI LDK SP,ROMSTK ;RESET ALWAYS CALL OCRLF ;NEW LINE LD A,MPCHR MOV C,A CALL CO ;PROMPT :2: CALL GETCH ;GET NEXT CHAR CMP ' ' JRZ :2 ;IF LEADING BLANK LDK B,NCMDS LDK HL,CTAB :3:T OUTPUT JMP PUNCH ;PUNCH OUTPUT JMP READER ;READER INPUT ; DISK I/O JMP HOME JMP SELDSK ;SELECT DISK JMP SETTRK ;SET TRACK JMP SETSEC ;SET SECTOR JMP SETDMA ;SET DMA JMP DREAD ;DISK READ JMP DWRT ;DISK WRITE JMP SLST ;LIST DEVICE STATUS RET ! NOP ! NOP ;SECTOR TRANSLATE ; END OF STANDARD CP/M FUNCTIONS RORAME: JMP BIOS+BRRXT JMP BIOS+BROMJP JMP FORMT ;FORMAT ONE TRACK JMP SIRST ;SIO RESET ; JMP BIOS+BRDXY ; JMP BIOS+BWTXY JMP IE.CO ;IEEE CONTROL OUT JMP IE.SI ; STATUS IN JMP IE.GTS ; GO TO STANDBY JMP IE.TC ; TAKE CONTROL JMP IE.OIM ; OUTPUT INTERFACE MESSAGE JMP IE.ODM ; OUTPUT DEVICE MESSAGE JMP IE.IDM ; INPUT DEVICE MESSAGE JMP IE.PP ; PARALLEL POLL PAGE .MAC IF RSIZE = 48 ; MAIN LOOP FOR OSB DEBUG MONITOR. ; ENTRY NONE. ; EXIT TO COMMAND PROCESSOR. ; C= 2. DMON: LDK DE,IMMSG CALL OSTR ;OUTPUT SIGNON MESSAGE ; COMMAND PROCESSOR NEXTC: EI LDK SP,ROMSTK ;RESET ALWAYS CALL OCRLF ;NEW LINE LD A,MPCHR MOV C,A  080 Registers. ; Each entry in the RTAB consists of: ; DB ASCII name ; DB Address ; DB flag, where flag is ; 0= 8 bit register ; 1= 16 bit ; 8x=8 bit but do not display in X command RTABS EQU 3 ;Length of each register entry RTAB: DB 'A', low ASAVE ,0 DB 'B', low BSAVE ,1 DB 'C'+80h, low CSAVE ,0 DB 'D', low DSAVE ,1 DB 'E'+80h, low ESAVE ,0 DB 'H', low HSAVE ,1 DB 'L'+80h, low LSAVE ,0 DB 'F', low FSAVE ,0 DB 'S', low SSAVE+1 ,1 DB 'P', low PSAVE+1 ,1 DB 0 ;Indicate end of table ; Z80 register control table. RTAX: DB 'A', low AFSAX+1 ,0 DB 'B', low BCSAX+1 ,1 DB 'C'+80h, low BCSAX ,0 DB 'D', low DESAX+1 ,1 DB 'E'+80h, low DESAX ,0 DB 'H', low HLSAX+1 ,1 DB 'L'+80h, low HLSAX ,0 DB 'F', low AFSAX ,0 DB 'I'+80h, low IVSAX+1 ,0 DB 'X', low IXSAX+1 ,1 DB 'Y', low IYSAX+1 ,1 DB 0 ; endx bmromd.asm diagnostic section COMAND Z ;examine Z80 regs NCMDS EQU (*-CTAB)/3 ;NUMBER OF VALID COMMANDS space 4,10 ; Table of ALL 8:wait: LD A,H.SSTS AND SI.TRDY ;wait for CTS go-ahead JRZ :wait ;if CTS high, wait again MOV A,C STO A,H.SXMT ;send chr ; NOP ! NOP ! NOP ;...wait... ; LD A,ACIAD ;get last command ; STO A,H.SCTRL ;set RTS high (no request) RET ; Endx BMSIO.asm atus AND SI.RRDY ; LD A,H.SREC ;clear ~DCD JRZ READER ;if not ready LD A,H.SREC ;get data MOV C,A ;A=C ; LK A,SI.RERR ;error check ; AND B ;...with status ; MOV A,C ;recover data ; RZ ;if OK ; STC ;...else error RET space 4,10 SLST: ;Get list device status ; Exit A= 0, if NOT ready LD A,H.SSTS AND SI.TRDY ;ck for Xmit buf empty RET ;set status space 4,10 LIST: ;Output one byte to list port PUNCH: ;Output one byte to punch port ; Entry C= character to output ; Exit C=C. ; LD A,ACIAD ;get last command byte ; CBIT 6,A ;...invert RTS status ; STO A,H.SCTRL ;make request (~RTS := low) BIT LD A,[DE] RRC ;NORMALIZE CHAR PUSH AF AND 07FH MOV C,A CALL CO ;OUTPUT IT INC DE POP AF JRNC ESTR ;IF NOT DONE RET PAGE .OLD IF FALSE FVIO: ;FILL VIDEO MEMORY WITH FIXED DATA ; ENTRY C= DATA TO BROADCAST ; NOTE: INTERRUPTS MUST BE DISABLED.. PROC LDK HL,FWAVM LDK DE,LVMEM PUSH HL ! PUSH DE CALL FILLC ;CLEAR MAIN VIO POP DE ! POP HL .MAC IF RSIZE = 64 ENADIM LDK C,0 ;CLEAR 9TH BIT :2: MOV A,D ;FILL 9TH BIT MEMORY OR E JRZ :4 ;IF DONE STO C,[HL] INC HL DEC DE JR :2 ;LOOP :4: DISDIM .MAC ENDIF RET .OLD ENDIF SPACE 4,10 SPAO: ;SET PIA FOR OUTPUT LDK A,03H ;CRA1-0, INTERRUPT INPUTS CA1 STO A,H.VIO+1 ;SET DATA DIRECTION LDK A,0FFH STO A,H.VIO ;SET ALL A LINES AS OUTPUT LDK A,0 STO A,H.VIO+3 LDK A,0FFH STO A,H.VIO+2 ;SET ALL B LINES AS OUTPUT RET SPACE 4,10 OPAD: ;OUTPUT DATA TO PIA A REGISTER ; ENTRY C= DATA ; EXIT PIAAD = NEW VALUE LDK A,4+3 STO A,H.VIO+1 MOV A,C STO A,PIAAD STO A,H.VIO ;SEND DA TITLE 'HARDWARE PIO FUNCTION PROCESSORS.' CDEHL: ;COMPARE DE TO HL AS UNSIGNED INTEGERS. ; ENTRY DE,HL SET TO VALUES TO COMPARE ; EXIT ZBIT SET IF DE = HL ; CBIT SET IF DE < HL. ; USES AF. MOV A,D CMP H RNZ ;IF D .NE. H MOV A,E CMP L RNZ ;IF DE .NE. HL STC RET SPACE 4,10 CNVBN: ;CONVERT ASCII TO BINARY ; ENTRY C= ASCII CHAR ; EXIT A = CHAR MOV A,C SUI '0' CPI 9+1 RM SUI 7 RET SPACE 4,10 DELAY: ;'N' MILLISECONDS ; ENTRY A=NUMBER OF MILLISECONDS TO DELAY ; SCLFRE= (FREQ/1000)/25 ; EXIT TIME PASSED. PROC PUSH BC MOV C,A :1: LDK A,SCLFRE :2: DEC A ;(4 TICS) MOV B,B ;(4 TICS) MOV C,C ;(4 TICS) JNZ :2 ;(10 TICS) IF 1 MS NOT ELAPSED DEC C JNZ :1 ;IF REQUESTED MSEC NOT DONE POP BC ;RESTORE REGISTERS RET ;SCLFRE: = 2000/22 ;Z80, 2MHZ ;...DEFINED IN OCCTXT.AST SPACE 4,32 FILLZ: ;FILL BLOCK OF MEMORY WITH BYTE VALUE. ; ENTRY DE=LENGTH TO BROADCAST CHARACTER ; C =CHARACTER TO BROADCAST ; HL=FWA TO START BROADCAST ; EXIT FILL DONE LTA RET SPACE 4,10 OPBD: ;OUTPUT DATA TO PIA B REGISTER ; PIA DEFINITION. ; 7 6 5 4 3 2 1 0 ; +--+--+--+--+--+--+--+--+ ; |D1|D0|^G| VERT OFFSET | ; +--+--+--+--+--+--+--+--+ ; ; ENTRY C= DATA ; EXIT PIABD = NEW VALUE LDK A,4 STO A,H.VIO+3 MOV A,C STO A,PIABD STO A,H.VIO+2 ;SEND DATA RET ; ENDX BMPIO TITLE 'bmIEEE.asm - IEEE-488 interface.' ; +---------------------------------------+ ; | Entered 05/01/81 from TNW xerox, seh. | ; +---------------------------------------+ ; ;Last edited at 09:29 on 11 NOV 80 ; ;There are four commands to the 6821 ; ; 00 Peripheral/direction register A CPDRA ; 01 Control register A CCRA ; 10 Peripheral/direction register B CPDRB ; 11 Control register B CCRB ; ;Bit 2 of the control register (A and B) allows selection of either ;a peripheral interface register or a data direction register. ;A "1" in bit 2 selects the peripheral register. ; ;The two data direction registers allow control of the directi TITLE 'SIO - Serial I/O Processors.' SIRST: ;Master reset SIO ; Entry C= SI.S16 or SI.S64 for 1200/300 baud LDK A,SI.MRST STO A,H.SCTRL ;master reset NOP ! NOP ! NOP MOV A,C STO A,ACIAD ;last-command cell STO A,H.SCTRL ;select SIO RET space 4,10 READER: ;Input one byte from reader port ; Entry None ; Exit A=C= character read LD A,H.SSTS ; MOV B,A ;save status AND SI.RRDY ; LD A,H.SREC ;clear ~DCD JRZ READER ;if not ready LD A,H.SREC ;get data MOV C,A ;A=C ; LK A,SI.RERR ;error check ; AND B ;...with status ; MOV A,C ;recover data ; RZ ;if OK ; STC ;...else error RET space 4,10 SLST: ;Get list device status ; Exit A= 0, if NOT ready LD A,H.SSTS AND SI.TRDY ;ck for Xmit buf empty RET ;set status space 4,10 LIST: ;Output one byte to list port PUNCH: ;Output one byte to punch port ; Entry C= character to output ; Exit C=C. ; LD A,ACIAD ;get last command byte ; CBIT 6,A ;...invert RTS status ; STO A,H.SCTRL ;make request (~RTS := low) K C,0 ;FILL WITH ZERO .OLD IF FALSE ; 8080 VERSION MOV A,D OR E RZ ;IF ALL DONE STO C,[HL] INC HL DEC DE JR FILLC ;CONTINUE .OLD ENDIF FILLC: MOV A,E OR D RZ ; RETURN HERE IF BROADCAST 0 BYTES STO C,[HL] ; 1ST BYTE DEC DE MOV A,E OR D RZ ; RETURN HERE IF BROADCAST 1 BYTE MOV B,D MOV C,E ; BC := (COUNT) MOV D,H MOV E,L INC DE ; DE := HL + 1 LDIR ; OVERLAPPING MOVE RET SPACE 4,10 OSTR: ;OUTPUT STRING TO CONSOLE ; ENTRY DE=FWA OF SOURCE ; NOTE : OSTR RECOGNIZES 7F AS AN ESCAPE SEQUENCE ; TO REPEAT CHAR N TIMES. FORMAT IS: ; 7F, REPEAT COUNT, CHAR PROC LD A,[DE] OR A PUSH AF AND 07FH CMP 07FH MOV C,A JRNZ :4 ;IF NOT REPEAT INC DE ! LD A,[DE] ! DEC A MOV B,A ;REPEAT COUNT INC DE ! LD A,[DE] ;GET REPEAT CHAR MOV C,A :2: CALL CO ;OUTPUT CHAR DJNZ :2 ;IF NOT DONE :4: CALL CO ;OUTPUT IT INC DE POP AF JP OSTR ;IF NOT DONE RET SPACE 4,13 ESTR: ;OUTPUT ENCODED STRING TO CONSOLE ; ENTRY DE=FWA OF SOURCE OR A ;CLEAR C on ;of data through each corresponding peripheral data line. ;A data direction register bit set at "0" configures ;the corresponding peripheral data line as an input. ; ;A reset at power up has the effect of zeroing all PIA registers. ;This will set PA0-PA7, PB0-PB7, CA2, and CB2 as inputs, ;and all interrupts disabled. ;Signals ATN, REN, and IFC will be driven low ;until initialized by software. ; ;Data direction is always set for output for the data register. ;Data must be set to all ones when inputting. ;The interface is in source handshake mode if data enable (PB0) ;is set to "0", and in acceptor handshake mode if set to "1". ;When switching from source to acceptor handshake, ;ATN will always be low. ;TAKE CONTROL can only be called following a GO TO STANDBY. ;After a fatal error, perform an IFC reset. ; ;Standard values used: ; ;CCRA 0011(IFC)(DIR)10 ; ;CCRB 0011(REN)(DIR)00 ; ;CPDRA Source Direction 1111_1111 ; Data DATA ; ;CPDRA Acceptor Direction 1111_1111 ; Data 1 source handshake STO A,CPDRB ;Leave IFC low for 100 micro-sec LK A,25 ;delay 100 micro-sec :b1c10: DEC A JRNZ :b1c10 LK A,0011_0110b ;set IFC high STO A,CCRA :b1c20: BIT 2,C ;check REN sub-command JRZ :b1c40 ;set/clear REN LK A,0011_0000b BIT 1,C JRZ :b1c30 LK A,0011_1000b :b1c30: STO A,CCRB :b1c40: POP HL POP AF RET Page ;Bios call 2: STATUS IN ; ; Can be called only while in source handshake mode. ; ;Bit 0 of register A set if SRQ is low ; IE.SI: Proc PUSH HL LD A,CPDRA ;clear IRQA1 LK HL,CPDRB ;pulse enable DAV/EOI CBIT 2,[hl] SBIT 2,[hl] LD A,CCRA ;set SRQ value in A AND 1000_0000b RLC A POP HL RET space 4,14 ;Bios call 3: GO TO STANDBY ; ; Can be called only while in source handshake mode ; ;No parameters passed ; IE.GTS: Proc PUSH AF LK A,0000_0010b ;set ATN high STO A,CPDRB XOR A ;float data bus STO A,CPDRA POP AF RET Page ;Bios call 4: TAKE CONTROL ; ; Can be called only while in the controller standby sta;DAC timeout re-entry MOV A,C ;place data on bus STO A,CPDRA LK A,10 :b6c20: BIT 7,[hl] JRZ :b6c30 ;ready for data DEC A JRNZ :b6c20 ;wait for 100 micro-sec LK A,1000_0010b ;set RFD timeout error JR :b6c80 :b6c30: BIT 6,[hl] JRNZ :b6c40 ;data accepted low LK A,1000_0001b ;set device not present error JR :b6c80 :b6c40: SBIT 5,[hl] ;set DAV low :b6c50: LK A,255 :b6c60: BIT 6,[hl] JRZ :b6c70 ;data accepted DEC A JRNZ :b6c60 ;wait 1000 micro-sec LK A,1000_0100b ;set DAC timeout error JR :b6c80 :b6c70: CBIT 5,[hl] ;set DAV high CBIT 3,[hl] ;set EOI high XOR A ;remove data from bus STO A,CPDRA :b6c80: POP HL RET Page ;Bios call 7: INPUT DEVICE MESSAGE ; ; Can be called while in any mode or state ; ; Exits in the acceptor handshake mode with ATN high. ; ;Device message returned in both registers A and H ;Error code returned in register L ; IE.IDM: Proc PUSH DE EX DE,HL ;save re-entry data LK HL,CPDRB BIT 0,[hl] JRNZ :b7c10 ;set-111_1111 ; ;CPDRB Source Direction 0011_1111 ; Data 000A_0010 ;A = ATN ; ;CPDRB Acceptor Direction 1101_0111 ; Data 0100_0101 Page ;PIA signal definitions: ;All signals are low on the IEEE bus when PIA register contains "1". ; ; PA0 DIO 1 ; PA1 DIO 2 ; PA2 DIO 3 ; PA3 DIO 4 ; PA4 DIO 5 ; PA5 DIO 6 ; PA6 DIO 7 ; PA7 DIO 8 ; ; CA1 SRQ ; CA2 IFC ; ; PB0 Enable data out (enabled when "0") ; PB1 Enable NDAC/NRFD (enabled when "0") ; PB2 Enable EOI/DAV (enabled when "0") ; PB3 EOI ; PB4 ATN ; PB5 DAV ; PB6 NDAC ; PB7 NRFD ; ; CB1 Not Used ; CB2 REN ; ;Control Word format ; ;[ 7 ][ 6 ][ 5 ][ 4 ][ 3 ][ 2 ][ 1 ][ 0 ] ; ;[IRQA1][IRQA2][ CA2 Control ][ DDRA][ CA1 Control] ;[IRQB1][IRQB2][ CB2 Control ][ DDRB][ CB1 Control] ; ; IRQA1 0 Interrupt flag set by fall of SRQ ; IRQA2 0 Not Used ; CA2 110 Set IFC high ; 111 Set IFC low ; DDRA 0 R/W data direction register A ; 1 R/W peripheral register A ; CA1 10 Set IRQA1 high on rise of SRQ te ; (ATN high). ; ; Exits in the controller active state (ATN low), ; source handshake mode. ; ;Bit 0 of register C set to take control asynchronous ; ;Error code returned in register A. ; IE.TC: Proc PUSH HL LK HL,CPDRB BIT 0,C JRNZ :b4c30 ;take control synchronously STO 0000_0111b,[hl] ;disable drivers LD A,CCRB CBIT 2,A STO A,CCRB STO 1101_0111b,[hl] ;direction register SBIT 2,A STO A,CCRB STO 1000_0101b,[hl] ;set NRFD low LK A,25 :b4c10: BIT 5,[hl] JRZ :b4c20 ;data valid has dropped DEC A JRNZ :b4c10 ;wait 100 micro-sec LK A,1000_0001b ;set data valid timeout error JR :b4c40 :b4c20: STO 1100_0101b,[hl] ;set NDAC low :b4c30: SBIT 4,[hl] ;set ATN low ;set-up for source handshake LD A,CCRB CBIT 2,A STO A,CCRB STO 0011_1111b,[hl] ;direction register SBIT 2,A STO A,CCRB STO 0001_0010b,[hl] ;control signal initial value XOR A ;clear error code :b4c40: POP HL RET Page ;Bios call 5: OUTPUT INTERFACE MESSAGE ; ; Can be called whup for acceptor handshake STO 0001_0111b,[hl] ;disable drivers LD A,CCRB CBIT 2,A STO A,CCRB STO 1101_0111b,[hl] ;direction register SBIT 2,A STO A,CCRB LK A,1111_1111b ;float internal data bus STO A,CPDRA STO 0101_0101b,[hl] ;control signals initial value STO 0100_0101b,[hl] ;set ATN high ;Perform acceptor handshake :b7c10: BIT 6,[hl] JRZ :b7c50 ;data invalid timeout error re-entry CBIT 7,[hl] ;set NRFD high LK A,10 :b7c20: BIT 5,[hl] JRNZ :b7c30 ;data valid DEC A JRNZ :b7c20 ;wait 100 micro-sec LK DE,1000_0010b ;set data valid timeout error JR :b7c80 :b7c30: SBIT 7,[hl] ;set NRFD low LD A,CPDRA ;read data MOV D,A LK E,0 ;read EOI BIT 3,[hl] JRZ :b7c40 LK E,1 :b7c40: CBIT 6,[hl] ;set NDAC high :b7c50: LK A,255 :b7c60: BIT 5,[hl] JRZ :b7c70 ;data valid dropped DEC A JRNZ :b7c60 ;wait 1000 micro-sec SBIT 2,E ;set data invalid timeout error SBIT 7,E JR :b7c80 :b7c70: SBIT 6,[hl] ;set NDAC low :b7c80: EX DE,HL ;move results ; ; IRQB1 0 Not Used ; IRQB2 0 Not Used ; CB2 110 Set REN high ; 111 Set REN low ; DDRB 0 R/W data direction register B ; 1 R/W peripheral register B ; CB1 00 Not Used Page ;Bios call 1: CONTROL OUT ; ; Can be called while in any state. ; ; Exits in the controller standby state (ATN high), ; source handshake mode ; ;Parameter passed in register C: ; ; Bit 0 If "1", the IFC signal is set low for 101 micro-sec ; and all pia signals are initialized ; ; Bit 2 1 ; 0 X No action ; 1 0 Sets REN high ; 1 1 Sets REN low ; IE.CO: Proc PUSH AF PUSH HL BIT 0,C ;check IFC sub-command JRZ :b1c20 ;Initialize all IEEE-488 signals LK HL,CCRA STO 0011_1010b,[hl] ;enable SRQ and set IFC-out low LK A,1111_1111b ;direct data out STO A,CPDRA STO 0011_1110b,[hl] XOR A ;set data to zero STO A,CPDRA LK HL,CCRB STO 0011_0000b,[hl] ;set REN-out high LK A,0011_1111b ;direction for source handshake STO A,CPDRB STO 0011_0100b,[hl] LK A,0000_0010b ;values forile in any mode or state ; ; Exits in the source handshake mode with ATN low. ; ;Multi-line message in register C ; ;Error!code returned in register A ; IE.OIM: Proc PUSH HL LK HL,CPDRB SBIT 4,[hl] ;set ATN low BIT 0,[hl] JRZ IE.shk ;set-up for source handshake STO 0001_0111b,[hl] ;disable drivers LD A,CCRB CBIT 2,A STO A,CCRB STO 0011_1111b,[hl] ;direction register SBIT 2,A STO A,CCRB XOR A ;float external data bus STO A,CPDRA STO 0001_0010b,[hl] ;control signal initial value JR IE.shk Page ;Bios call 6: OUTPUT DEVICE MESSAGE ; ; Can be called only while in the source handshake mode ; with ATN high or low. ; ; Exits in the source handshake mode with ATN high. ; ;Multi-line message in register C ;EOI request in register B ; ;Error code returned in register A ; IE.ODM: Proc PUSH HL LK HL,CPDRB CBIT 4,[hl] ;set ATN high BIT 0,B ;check if EOI requested JRZ IE.shk SBIT 3,[hl] ;Perform source handshake IE.shk: BIT 5,[hl] ; JRNZ :b6c50  to registers A and HL MOV A,H POP DE RET space 4,21 ;Bios call 8: PARALLEL POLL ; ; Can be called only while in the source handshake mode ; with ATN high or low. ; ; Exits in the source handshake mode with ATN low. ; ;Parallel poll value returned in A. ; IE.PP: Proc PUSH HL LK HL,CPDRA LK A,0001_1011b ;form parallel poll STO A,CPDRB STO 1111_1111b,[hl] ;float internal data bus LD A,[hl] ;read parallel poll data STO 0,[hl] ;re-store source handshake mode LK HL,CPDRB STO 0001_0010b,[hl] POP HL RET ; Endx bmIEEE.asm low LD A,CPDRA ;read data MOV D,A LK E,0 ;read EOI BIT 3,[hl] JRZ :b7c40 LK E,1 :b7c40: CBIT 6,[hl] ;set NDAC high :b7c50: LK A,255 :b7c60: BIT 5,[hl] JRZ :b7c70 ;data valid dropped DEC A JRNZ :b7c60 ;wait 1000 micro-sec SBIT 2,E ;set data invalid timeout error SBIT 7,E JR :b7c80 :b7c70: SBIT 6,[hl] ;set NDAC low :b7c80: EX DE,HL ;move resultsF JMP COUT O2SP: ;Output 2 spaces on console CALL OSP OSP: LK C,' ' JMP COUT RLWA = * ;LWA OF ROM RESIDENT CODE MSG 'LENGTH OF THIS ROM IS = ',RLWA IF RLWA > 0FFFH .9 ERROR CODE TOO LARGE.. ENDIF ; endx BMUTIL2.asm PUSH AF ;Save argument RRC RRC RRC RRC ;Get upper 4 bits to LOW 4 bit positions CALL PRVAL ;Convert lower 4 bits to ASCII CALL CO ;SEND to terminal POP AF ;Get back argument CALL PRVAL JMP CO space 4,10 PRVAL: ;Converts a number in the range 0 to F HEX to ; the corresponding ASCII character, 0-9,A-F. PRVAL ; does not check the validity of its input argument. ; Entry A= integer, range 0 to F ; Exit A= ASCII character. ; C= A ; Calls NONE. ; DESTROYS: AF AND 0Fh ADD A,90h ;Set UP a so that A-F CAUSE a Carry DAA ;adjust contents of a register ADC A,40h ;ADD in Carry and adjust upper 4 bits DAA ;adjust contents of a register again MOV C,A RET OCRLF: ;Output CR,LF on console screen LK C,CR CALL COUT LK C,L PIA-A data PIABD: DS 1 ;Holds last PIA-B data ; Calendar month, day year IDAY DS 3 IMONTH = IDAY+1 IYR = IDAY+2 ; Wall clock time cells and disk active ; see UPTIM: in BMKEY.asm HOURS: DS 6 MINS: = HOURS+1 SECS: = HOURS+2 SEC6: = HOURS+3 ; Used to deselect drive when there is NO activity ; on drive for n seconds. See FDSK routine DACTVE: = HOURS+4 ;=0 by FDSK, Used by UPTIM BELCNT: = HOURS+5 ;^G bell timer cell LLIMIT DS 1 ;max #columns in a logical line ; MSG 'LLIMIT = ',LLIMIT,'h.' ; Disk drive current positions LDSEL: DS 2 ;Last selected drive LDTRK = LDSEL+1 ;Last track used for non-selected drive IESTK: DS 2 ;save current stk ptr ; Interrupt stack DS 20*2 ISTK: DS 0 ; Stack entry DS 20*2 BIOSTK: ROMSTK: DS 0 ACIAD: DS 1 ;last command byte written to ACIA R179x: DS 4 ;179x register save area KBDLY: DS 1 ;keyboard debounce-delay cell ;since CP/M CANNOT boot off B:, this cell is used ;to invert the names of the 2 drives: ; =0, all normal, A= TITLE 'BMRAM - Debug Monitor RAM Storage.' ;MRAM - Debug Monitor RAM Storage. ; Used to assembly ROM resident and CBIOS ORG MRAM ; Host disk xfer buffer and... ; Format track template holding buffer HSTBUF: IF DEF FMTDAT RMTDAT DS 0 DS (FMTSD-FMTDAT) RFMTSD DS 0 DS (FTRKN-FMTSD) RFTRKN DS 0 DS (FSECN-FTRKN) RFSECN DS 0 DS (FDAM-FSECN) RDAM DS 0 DS LSECB+1 RCRC2 DS 0 DS FMTEND-FCRC2 DS (256+128)-(*-HSTBUF) ELSE DS 256+128 ENDIF ; Directory Buffer DIRBUF: = HSTBUF+256 TEM DS 6 RNDV = TEM+1 ;random number seed ERCNT = RNDV+1 ;DW ERCNT RTRC = ERCNT+2 ;retry count RTRY = RTRC+1 MPCHR DS 1 ;prompt character ECHOP DS 1 ;=0, list ehco off ROMRAM DS 1 ;0= RAM, 1= ROM DSTSB DS 6 ;Disk status bytes ; Disk operation temps and control DMADR DS 2 ;Address for read/write Disk DMAADR DS 2 ;CBIOS, users DMA ; Note order of xxxSEC,xxxTRK,xxxDSK must be maintained ; along with length (1,2,1). SEKDEL: DS 1 ;Set for seek-restore command in ROM ;depends oA:, B=B: ; =1, all inverted, A=B:, B=A: DSKSWP DS 1 ; Z80 Alternate Register Set ALIGN 10h RAGS: DESAX: DS 2 ;DE` BCSAX: DS 2 ;BC` AFSAX: DS 2 ;AF` HLSAX: DS 2 ;HL` IXSAX: DS 2 ;IX IYSAX: DS 2 ;IY IVSAX: DS 2 ;Interrupt page register ; 8080 Register Save Area. ALIGN 10h REGS: ESAVE: DS 1 ;E Register save location DSAVE: DS 1 ;D Register save location CSAVE: DS 1 ;C Register save location BSAVE: DS 1 ;B Register save location FSAVE: DS 1 ;FLAGS save location ASAVE: DS 1 ;A Register save location LSAVE: DS 1 ;L Register save location HSAVE: DS 1 ;H Register save location PSAVE: DS 2 ;PGM COUNTER save location SSAVE: DS 2 ;USER STACK pointer save location IF (high *) <> (high ROMSTK) .9 DW *, STK, must be equal ENDIF ;TEMP: DS 1 ;TEMPORARY MONITOR CELL BKPA: DS 2 ;last breakpoint address BKPC: DS 1 ;Contents of bkp IF * >= LWAMEM MSG 'RAM temporary area too large ',* .9 ERROR ENDIF IF * > INTBL .9 ERROR MSG 'RAM overflow into Int Vector ' TITLE 'BMUTIL2 - Osborne 1 Utility routines.' NMOUT: PBBH: ;Print Binary Byte in Hex. ; Converts the 8 BIT, unsigned integer in the ; A register into 2 ASCII characters. ; Entry A= 8 bit integer ; Exit NONE ; Calls CO,PRVAL ; DESTROYS: AF, C. PUSH AF ;Save argument RRC RRC RRC RRC ;Get upper 4 bits to LOW 4 bit positions CALL PRVAL ;Convert lower 4 bits to ASCII CALL CO ;SEND to terminal POP AF ;Get back argument CALL PRVAL JMP CO space 4,10 PRVAL: ;Converts a number in the range 0 to F HEX to ; the corresponding ASCII character, 0-9,A-F. PRVAL ; does not check the validity of its input argument. ; Entry A= integer, range 0 to F ; Exit A= ASCII character. ; C= A ; Calls NONE. ; DESTROYS: AF AND 0Fh ADD A,90h ;Set UP a so that A-F CAUSE a Carry DAA ;adjust contents of a register ADC A,40h ;ADD in Carry and adjust upper 4 bits DAA ;adjust contents of a register again MOV C,A RET OCRLF: ;Output CR,LF on console screen LK C,CR CALL COUT LK C,Ln disk type. Siemens = 3h, MPI = 0h SAVSEC DS 1 ;last sector requested SAVTRK DS 2 ;last track requested SDISK DS 1 ;Selected disk drive (0,1) ACTSEC = SAVSEC ACTTRK = SAVTRK ACTDSK = SDISK SEKSEC DS 1 SEKTRK DS 2 SEKDSK DS 1 HSTSEC DS 1 HSTTRK DS 2 HSTDSK DS 1 TEMSEC DS 1 ;Used in bios only RDFLAG DS 1 ;Read flag ERFLAG DS 1 ;Error reporting WRTYPE DS 1 ;Write operation type ALV: DS ALVS CSV: DS CSVS ; BIOS blocking-deblocking flags HSTACT: DS 1 ;host active flag HSTWRT: DS 1 ;Host written flag UNACNT: DS 1 ;Unalloc rec count UNATRK: DS 2 ;Track UNASEC: DS 1 ;Sector LOGSEC: DS 1 ;Logical sector LDADR DS 2 KEYLCK DS 1 ;Zero if locked keyboard CURS DS 2 ;current cursor position ; Keyboard scan temporaries TKEY DS 1 ;Tem holding key HKCNT DS 1 ;Debounce key LKEY DS 1 ;Last valid keystroke CKEY DS 1 ;Last control key ESCH DS 1 ;ESC holding flag ;PIAAD and PIABD must be kept sequential, PIAAD first ;dependency in VC_HOME of BMKEY.asm PIAAD: DS 1 ;Holds last, * ENDIF ; Interrupt Jump Vector is between EFFO, EFFF. PAGE ; Endx MRAM SAX: DS 2 ;BC` AFSAX: DS 2 ;AF` HLSAX: DS 2 ;HL` IXSAX: DS 2 ;IX IYSAX: DS 2 ;IY IVSAX: DS 2 ;Interrupt page register ; 8080 Register Save Area. ALIGN 10h REGS: ESAVE: DS 1 ;E Register save location DSAVE: DS 1 ;D Register save location CSAVE: DS 1 ;C Register save location BSAVE: DS 1 ;B Register save location FSAVE: DS 1 ;FLAGS save location ASAVE: DS 1 ;A Register save location LSAVE: DS 1 ;L Register save location HSAVE: DS 1 ;H Register save location PSAVE: DS 2 ;PGM COUNTER save location SSAVE: DS 2 ;USER STACK pointer save location IF (high *) <> (high ROMSTK) .9 DW *, STK, must be equal ENDIF ;TEMP: DS 1 ;TEMPORARY MONITOR CELL BKPA: DS 2 ;last breakpoint address BKPC: DS 1 ;Contents of bkp IF * >= LWAMEM MSG 'RAM temporary area too large ',* .9 ERROR ENDIF IF * > INTBL .9 ERROR MSG 'RAM overflow into Int Vector 'ms then 2 ; Keyboard debounce KBDTM = 1 ;WAIT 1 MILLISECOND FOR DEBOUNCE ; Assembly Constants ; Port definitions (Memory mapped) H.FDC = 2100h ;Floppy disk H.KEY = 2200h ;Keyboard H.SIO = 2A00h ;Serial I/O H.VIO = 2C00h ;Video memory controls SEKTMO = 0FEh ;Seek Time Out error status ; SIO Interface and definitions H.SXMT = H.SIO+1 ;Transmit address H.SREC = H.SIO+1 ;Receive (read from address) H.SCTRL = H.SIO ;Set control reg (write) H.SSTS = H.SIO ;Status reg (read) ; Defined function codes SI.MRST = 0_10_101_11b ;Master reset SI.S16 = 0_10_101_01b ;Select 16x clock, xmit/rec ;8 data, 1 stop bit ;RTS high (no request) SI.S64 = 0_10_101_10b ;Select 64x clock ;...all else identical to SI.S16 SI.1200 = SI.S16 SI.300 = SI.S64 SI.RRDY = 01 ;Receiver ready SI.TRDY = 02 ;Transmit ready SI.NCTS = 0000_1000b ; ~CTS SI.RERR = 0111_0000b ;Rcvr err: PE, OVRN, FE H.IEEE = 2900h ;IEEE interface CPDRA EQU H.IEEE+0 ;Peripheral/Direction register A  ;Eof character (same as cpm) TAB = 09h INVV = 80h ;Inverse video bit GESC = 'a' ;Graphics escape toggle char ; CP/m definitions CVER = 22 ;CPM version number CBIOSV = SVER ;cbios version NDSKS = 2 K = 1024 MSIZE = RSIZE-(LVMEM/K) BIOS = MSIZE*k-0600h ;Start of CPM jump table BDOS = BIOS-0E00h+6 ;BDOS entry pt CCP = BIOS-1600h ;CCP entry ABTC = 'C'-40h ;Abort character ALVS: = 0Ch ;*** must be validated with CBIOS *** CSVS: = 20h ;*** --------------------------- *** LSECB = 256 ;Length of a sector MTRK = 40 ;Maximum tracks MSEC = 10 ;Maximum Sectors FMTCHR = 0E5h ;Data format char space 4,10 ; Set CP/M symbols. IOBYTE = 3 CDISK = 4 ;Current logged-in CPM disk SYS = 5 ;CPM Monitor call address SYSL = SYS+1 ;(lwa of CP/m) TIMPTR = 40h ;points to where time kept DBUF = 80h ;Default disk buffer OM#LRAM = SYSL SYSR = 0 ;return to system SYSDSK = CDISK ;Contains current system disk # SYSDAT = 10h ;Date in ddmmyy SYSTIM = SYSDAT+3 ;Time in hhmm CCRA EQU H.IEEE+1 ;Control register A CPDRB EQU H.IEEE+2 ;Peripheral/Direction register B CCRB EQU H.IEEE+3 ;Control register B ROMVEC = 100h ;Start of rom vector BKPI = 0CFh ;Breakpoint interrupt = 1 NMIA = 66h ;NMI address LCMDP = 4*1024 ;L command prom .siz IF RSIZE = 48 MSG 'Assembly for 48 k Mode 1 system' MRAM = 0AD80h ;FWA for Monitor ram FWAVM = 0B000h ;FWA of video memory NVDL = 24 .siz ELSE MSG 'Assembly for 64k Mode 2 system' MRAM = 0ED80h FWAVM = 0F000h NVDL = 24 INTBL = 0EFF0h ;interrupt vector table .siz ENDIF LVMEM = 128*32 ;Length of video memory LVDIS = 128*NVDL ;Length of Display memory VFLO = -22 ;First line video offset VLL = 128 ;Length of one video line VLDL = 52 ;Length of displayed char/line FWASM = FWAVM+VLDL ;Status info LWAMEM = FWAVM+LVMEM-1 @FREQ = 4000 ;freq of processor SCLFRE = @FREQ/25 ;for DELAY routine ; Define Ascii Control Codes. ; Value ;^Control Meaning in Phoenix EOS = 0 ;^@, NUL = End of String TBFCHR =ss ORGP = 100h ;Transient program origin ;EOL does not exist in CP/M EOM = '$' ;End of Message (for system function) EOF = 'Z'-40h ;End of File L$PRU = 128 ;Bytes per floppy sector FCB = 5Ch ;SYSTEM DEFAULT FILE CONTROL BLOCK FCB_NR = FCB+32 ;Next Record = LRN F_EX = 12 ;Extend field F_S2 = 14 ;CPM system usage **used with 2.0 SIZ funct** F_RC = 15 ;Record count (0 to 128) F_NR = 32 ;Next record ordinal in FCB F_RRF = 33 ;r0,r1,r2 (random field) in FCB L_FILEN = 8 ;length of File name L_FILEX = 3 ;length of filename suffix L_FCB = 36 ;length of entire FCB (comp with 2.0) DMA = 80h ;WHERE SECTORS ARE READ TBUFF = DMA ;where CCP puts command line OS#RCO = 1 ;Read character from CRT: OS#WCO = 2 ;Write character to CRT: device OS#RRO = 3 ;Read from reader OS#WPO = 4 ;Write to punch OS#WLO = 5 ;Write character to LST: device OS#OST = 9 ;Write string on CRT: OS#RCB = 10 ;Read Console Buffer OS#CABT = 11 ;Get Console status OS#VER = 12 ;Return version in HL ;H= 0, L=0 if 1.4  TITLE 'OCCTXT.AST - Osborne Computer Corp System Text.' SVER = 1 ; Legal values for RSIZE are 48 and 64 ; entered from command line IF *o = 0 ; user forgot 'o=64' parameter RSIZE = 64 ; default = 64k version ELSE RSIZE = *o ;get machine size ENDIF ;SYSTEXT.AST - Installation Parameter Configuration. ; This Systext provides definitions of system configuration, ; and Ascii control characters for the DigiCon Phoenix ; product set. ; ; This text is configured for CP/m. Another text must be ; used to assemble routines for Phoenix. Both are derived ; from IPARAMS.ACD. space 4,10 ; True/False definitions FALSE = 0 TRUE = not FALSE space 4,10 ODEBUG = FALSE ;True for activating debug code SYcpm20 = 4 ;=cpm 2.0 SYcpm14 = 0 SYmpm10 = 5 SYcdos = 3 @CPM SET TRUE space 4,10 ; List output page/line/column definitions MLPP = 66 ;Number of lines per physical page LLP = 60 ;NUMBER OF LINES TO PRINT PER PAGN ; Disk type and speed constants SEEKTM = 2 ;if MPI, 0 ;if Sieme 'A'-40h ;^A, SOH = Tab with fill BTBCHR = 02h ;^B, STX = BACK TAB CHARACTER ABTCHR = 03h ;^C, ETX = ABORT CHARACTER BELCHR = 07h ;^G, BEL = Audible Alarm BKSCHR = 08h ;^H, BS = PHYSICAL BACKSPACE CHARACTER TABCHR = 09h ;^I, HT = Tab LF = 0Ah ;^J, LF = Line Feed VTAB = 0Bh ;^K, VT = Vertical Tab FMFD = 0Ch ;^L, FF = Form Feed CR = 0Dh ;^M, CR = Carriage Return LITCHR = 0Eh ;^N, SO = Literal next character SUSCHR = 0Fh ;^O, SI = SUSPEND CHARACTER RTYCHR = 12h ;^R, DC2 = RE-TYPE LINE CHARACTER CTRU = 15h ;^U, NAK = Cancel Line char BWDCHR = 17h ;^W, ETB = Backspace ONE word CANCHR = 18h ;^X, CAN = CANCEL LINE CHARACTER ESC = 1Bh ;^[, ESC = Escape RUBOUT = 7Fh ; DEL = Rubout (accepted as Backspace) ERC = 7Fh ;illegal key REP = 02 ;repeat key CAPS = 03 ;repeat SHTK = 04 ;Shift key CTRL = 05 ;Control key CLRSRN = 'Z'-40h ;Clear screen MCR = 'L'-40h ;Form Feed (move cursor right) PMCHR = '>' ;Prompt character ERCHR = '?' ;Error character BKS = 08h EOFC = 'Z'-40h  ;H= 0, L=xx if 2.0 or > ;H= 1, L=0 if MPM 1.0 OS#IND = 13 ;Initialize/Reset Disk system OS#DSEL = 14 ;Select disk unit OS#OPEN = 15 ;Open file OS#CLOS = 16 ;Close file OS#SDIR = 17 ;Search directory OS#NDIR = 18 ;next entry in directory OS#DEL = 19 ;Delete a file OS#READ = 20 ;READ next pru from file OS#WRT = 21 ;Write one PRU to file OS#CRE = 22 ;Create a file OS#REN = 23 ;rename a file OS#RLV = 24 ;Return login vector OS#RCD = 25 ;Return current disk OS#SDMA = 26 ;Set DMA address ; CPM 2.x functions OS#DIO = 6 ;Console direct I/O OS#GAA = 27 ;Get adr (alloc) OS#SWP = 28 ;Set write protect for disk OS#GRO = 29 ;Get r/o vector OS#SFA = 30 ;Set File attributes OS#GAD = 31 ;Get disk parms address OS#USC = 32 ;Get/set user code OS#RRD = 33 ;Read random OS#WRD = 34 ;Write random OS#FIZ = 35 ;Get file size in records OS#SRD = 36 ;Set random record OS#RDRV = 37 ;Reset drive OS#ADR = 38 ;Access drive OS#FDR = 39 ;Free drive OS#WRZ = 40 ;Write random with zero fill ; DirectOUT 3 ENDM ; Endx SYSTEXT eck ; SYS.ACD is used to make file action ; requests. SYSCAL MACRO NAME,ARG .1 IF ' %2' <> ' ' LXI DE,%2 .1 ENDIF CALL %1 ENDM space 4,10 ; SYSTEM This macro provides a mechanism to call the ; system directly. SYSTEM MACRO FUN,ARG .2 IF DEF OS#%1 MVI C,OS#%1 .1 IF ' %2' <> ' ' LXI DE,%2 .1 ENDIF CALL SYS .2 ELSE CALL %1 .2 ENDIF ENDM ; ALIGN Set origin to even boundary. ALIGN MACRO SIZ,O DS (*%2+(%1)-1)/(%1)*(%1)-*%2 ENDM ; DI and EI are macros so all usages can be accounted ; for in the cr. DI MACRO DB 0F3h ENDM EI MACRO DB 0FBh ENDM ; Macros to enable ROM, RAM and DIM code ENAROM MACRO OUT 0 LDK A,0 STO A,ROMRAM ENDM DISROM MACRO OUT 1 LDK A,1 STO A,ROMRAM ENDM BRTBIT: = 80h ;set brt/dim memory BRIGHT DIMBIT: = 00h ;set brt/dim memory DIM ENADIM MACRO OUT 2 ENDM DISDIM MACRO ;OCCROM0B.ASM TITLE 'Osborne-One Monitor for Model 1 system.' * 4D2008-00 MASTER .ASM * 2D2008-00 ASSY .ASM * 1D2008-00 LISTING .PRN * 4D1008-00 MASTER .COM * 2D1008-00 ASSY .COM LIST -F ;4-25, Do not list opted out code ; Initial Monitor for Osborne-One System. ; +-------------------------------+ ; | | ; | Osborne-One Monitor | ; | | ; +-------------------------------+ ;VER = REV B ;DATE = 227 ;DEB ; Assembly Constants ORG 0 ;FWA of memory @XFRMT = TRUE ;FALSE IF FORMAT IS IN ROM INACMD = FALSE INBCMD = TRUE INDCMD = FALSE INFCMD = FALSE INGCMD = FALSE INHCMD = FALSE INMCMD = FALSE INRCMD = FALSE INSCMD = FALSE INTCMD = FALSE INXCMD = FALSE INZCMD = FALSE INDIA = TRUE ;INTERNAL DIAGNOSTICS INDMON = FALSE INUTIL = FALSE NULINT MACRO NUMB ORG %1*8 DI JMP ILINT NOP ! NOP ! NOP ! NOP ENDM PUSHAL MACRO PUSH AF PUSH BC PUSH DE PUSH HL PUSH IX PUSH IY ENDM POPALL MACRO POP IY POP IX POP HL POP DE POP BC POP AF BIO call definitions BCONST = 2*3 ;Console status BCONIN SET 3*3 BCOUT = 4*3 ;Console output BLIST = 5*3 ;List output BPUNCH = 6*3 ;Punch output BRDR = 7*3 ;Reader input BHOME = 8*3 ;Home disk drive BSDSK = 9*3 ;Select Disk drive BSTTRK = 10*3 ;Set track BSTSEC = 11*3 ;Set sector BSTDMA = 12*3 ;Set DMA BREAD = 13*3 ;READ disk pru BWRITE = 14*3 ;WRITE disk pru BLSTS = 15*3 ;List LST: device status BSECTR = 16*3 ;Sector translate routine ; Extensions added by SORCIM BRRXT = 17*3 ;Ram-Rom exit BROMJP = 18*3 ;Rom jump entry BFMTJP = 19*3 ;Format Track BSBAUD = 20*3 ;Set Serial Port Baud Rate ;BRDXY = 21*3 ;Read XY ;BWTXY = 22*3 ;Write XY ; IEEE-488 calls BIECO = 21*3 ;Control Out BIESI = 22*3 ;Status In BIEGTS = 23*3 ;Go To Standby BIETC = 24*3 ;Take Control BIEOIM = 25*3 ;Output Interface Message BIEODM = 26*3 ;Output Device Message BIEIDM = 27*3 ;Input Device Message BIEPP = 28*3 ;Parallel Poll ;BIOCAL Used to make calls directly to BIO BIOCAL MACRO NAME LXI HL,L%K  TITLE 'BMUTIL2 - OSBORNE 1 UTILITY ROUTINES.' NMOUT: PBBH: ;PRINT BINARY BYTE IN HEX. ; CONVERTS THE 8 BIT, UNSIGNED INTEGER IN THE ; A REGISTER INTO 2 ASCII CHARACTERS. ; ENTRY A= 8 BIT INTEGER ; EXIT NONE ; CALLS CO,PRVAL ; DESTROYS: AF, C. PUSH AF ;SAVE ARGUMENT RRC RRC RRC RRC ;GET UPPER 4 BITS TO LOW 4 BIT POSITIONS CALL PRVAL ;CONVERT LOWER 4 BITS TO ASCII CALL CO ;SEND TO TERMINAL POP AF ;GET BACK ARGUMENT CALL PRVAL JMP CO SPACE 4,10 PRVAL: ;CONVERTS A NUMBER IN THE RANGE 0 TO F HEX TO ; THE CORRESPONDING ASCII CHARACTER, 0-9,A-F. PRVAL ; DOES NOT CHECK THE VALIDITY OF ITS INPUT ARGUMENT. ; ENTRY A= INTEGER, RANGE 0 TO F ; EXIT A= ASCII CHARACTER. ; C= A ; CALLS NONE. ; DESTROYS: AF AND 0FH ADD A,90H ;SET UP A SO THAT A-F CAUSE A CARRY DAA ;ADJUST CONTENTS OF A REGISTER ADC A,40H ;ADD IN CARRY AND ADJUST UPPER 4 BITS DAA ;ADJUST CONTENTS OF A REGISTER AGAIN MOV C,A RET OCRLF: ;OUTPUT CR,LF ON CONSOLE SCREEN LK C,CR CALL COUT LK C,L ENDM PAGE LINK OCCROM1B.ASM ;ROM STANDARDS ;LOP,ROMD LINK OCCROM2B.ASM ;CPM BOOT ;BOOT LINK OCCROM3B.ASM ;CONSOL ROUTINES ;KEY LINK OCCROM4B.ASM ;PIA ROUTINES ;PIO,IEEE LINK OCCROM5B.ASM ;SIA ROUTINES ;SIO LINK OCCROM6B.ASM ;DISK ROUTINES ;DSK LINK OCCROM7B.ASM ;DIAGNOSIC ROUTINES ;DIA LINK OCCROM8B.ASM ;FORMAT ROUTINE ;XFMT LINK OCCROM9B.ASM ;UTILITES ;UTIL2 LINK OCCRAMA.ASM ;RAM LOCATIONS ; Endx F FORMAT IS IN ROM INACMD = FALSE INBCMD = TRUE INDCMD = FALSE INFCMD = FALSE INGCMD = FALSE INHCMD = FALSE INMCMD = FALSE INRCMD = FALSE INSCMD = FALSE INTCMD = FALSE INXCMD = FALSE INZCMD = FALSE INDIA = TRUE ;INTERNAL DIAGNOSTICS INDMON = FALSE INUTIL = FALSE NULINT MACRO NUMB ORG %1*8 DI JMP ILINT NOP ! NOP ! NOP ! NOP ENDM PUSHAL MACRO PUSH AF PUSH BC PUSH DE PUSH HL PUSH IX PUSH IY ENDM POPALL MACRO POP IY POP IX POP HL POP DE POP BC POP AFPUSH HL ;return LHLD SYSR+1 MVI L,%1 PCHL L%K: ENDM space 4,10 ;SYSCAL ; This macro is to be used when the common deck ; SYS.ACD is used to make file action ; requests. SYSCAL MACRO NAME,ARG .1 IF ' %2' <> ' ' LXI DE,%2 .1 ENDIF CALL %1 ENDM space 4,10 ; SYSTEM This macro provides a mechanism to call the ; system directly. SYSTEM MACRO FUN,ARG .2 IF DEF OS#%1 MVI C,OS#%1 .1 IF ' %2' <> ' ' LXI DE,%2 .1 ENDIF CALL SYS .2 ELSE CALL %1 .2 ENDIF ENDM ; ALIGN Set origin to even boundary. ALIGN MACRO SIZ,O DS (*%2+(%1)-1)/(%1)*(%1)-*%2 ENDM ; DI and EI are macros so all usages can be accounted ; for in the cr. DI MACRO DB 0F3h ENDM EI MACRO DB 0FBh ENDM ; Macros to enable ROM, RAM and DIM code ENAROM MACRO OUT 0 LDK A,0 STO A,ROMRAM ENDM DISROM MACRO OUT 1 LDK A,1 STO A,ROMRAM ENDM BRTBIT: = 80h ;set brt/dim memory BRIGHT DIMBIT: = 00h ;set brt/dim memory DIM ENADIM MACRO OUT 2 ENDM DISDIM MACRO F JMP COUT O2SP: ;OUTPUT 2 SPACES ON CONSOLE CALL OSP OSP: LK C,' ' JMP COUT RLWA = * ;LWA OF ROM RESIDENT CODE MSG 'LENGTH OF THIS ROM IS = ',RLWA IF RLWA > 0FFFH .9 ERROR CODE TOO LARGE.. ENDIF ; endx BMUTIL2.asm PUSH AF ;SAVE ARGUMENT RRC RRC RRC RRC ;GET UPPER 4 BITS TO LOW 4 BIT POSITIONS CALL PRVAL ;CONVERT LOWER 4 BITS TO ASCII CALL CO ;SEND TO TERMINAL POP AF ;GET BACK ARGUMENT CALL PRVAL JMP CO SPACE 4,10 PRVAL: ;CONVERTS A NUMBER IN THE RANGE 0 TO F HEX TO ; THE CORRESPONDING ASCII CHARACTER, 0-9,A-F. PRVAL ; DOES NOT CHECK THE VALIDITY OF ITS INPUT ARGUMENT. ; ENTRY A= INTEGER, RANGE 0 TO F ; EXIT A= ASCII CHARACTER. ; C= A ; CALLS NONE. ; DESTROYS: AF AND 0FH ADD A,90H ;SET UP A SO THAT A-F CAUSE A CARRY DAA ;ADJUST CONTENTS OF A REGISTER ADC A,40H ;ADD IN CARRY AND ADJUST UPPER 4 BITS DAA ;ADJUST CONTENTS OF A REGISTER AGAIN MOV C,A RET OCRLF: ;OUTPUT CR,LF ON CONSOLE SCREEN LK C,CR CALL COUT LK C,L:10000000D303C33600FBC9F3D303ED736FEF31990C :10001000EFF5C5D5E5DDE5FDE53E493206EF3A00F1 :100020002C3A08EFB7C23301FDE1DDE1E1D1C1F1C6 :10003000ED7B6FEFFBC9F331C1EF3E003269EF3268 :1000400017EFCD85002100ED22EAEF210000226D9F :09005000EF115701CD82081811CF :10006600F3C33600CDAC02FE0D21C7EF0E0071CAF8 :10007600FA0134FE22CAFA01FE04CAF20C18B1D300 :10008600003E003208EFD303216C0622F8EFED5E46 :100096003EEFED47AF326BEF325EEF325DEF320788 :1000A600EF3260EF2F3263EF325CEF3259EF3E8072 :1000B600326CEF3E0132C6EFCDB0080EEACDC50870 :1000C6003E003262EF4FCDD2080E55CD570A3E02A2 :0A00D6003213EF3E3E3206EFFBC985 :10010000C3FA01C30902C3A102C3AC02C38603C37D :10011000790AC3790AC3670AC3940AC3FC0AC38A6B :100120000AC38F0AC3850AC39A0BC3E00BC3730AC1 :10013000C90000C333EAC336EAC3620FC3570AC318 :10014000DF08C32209C33509C34109C38109C3A418 :1001500009C3E609C3420A1A0A0A0A0A1B67117F81 :100160001817051B470D0A1B67011B4720201B4C56 :100170004F53424F524E452053595354454D204FF3 :100180004E452E1B4D2020201B67041B470D0A1BCC :1001900067017FFA5F6 :1004700028032B1872E5017FFF093A6CEF4F060045 :1004800009E3293A62EFF6E0BCE1200401000C091F :100490003EF0B46718513A62EFF6204FCDD2083ED5 :1004A0001E326BEF18492100F0CDE40501800FCD1D :1004B00055063A62EFE6E04FCDD2082100F018274A :1004C000CD66063E80A56F181ECD05061819CD66AF :1004D000067E775DCBBB3A6CEF3D9320093E80A54D :1004E0006FCD08061801237E173F1F77225AEFC1F0 :1004F000D1E179C9AF18023EFF3259EF18F1E5CDCD :10050000E405E118E23E07A0F6183260EF18E03E7D :1005100007A0F63818F43E7F4DCBB99128044F065A :1005200000C9E1E118C1E5CD1605545D23CD55069E :100530003620F3D3022B3680D303FBE118A9CD6616 :1005400006E5CD16053E7FB56F5F542BCD4406E121 :100550007E173E4018933E0118063E0218023E04E4 :10056000B03260EF18893EFE18063EFD18023EFBD1 :10057000A018EE0E0218020EFEF33A61EF814FCD85 :10058000C508FBC3EF040EEA18F5CD66063E80A54C :100590006FE5293A62EFC61894E61F473E52B978D4 :1005A000282084571E00CB1ACB1B1B782180FF19F3 :1005B0001803CD4406CDD50520F823CDE405E1C3CD :1005C000E704D1D5218000191803CD5506CDD505F6 :1005D00020F8EB18E6F53EF0B4B0003E0332012C3EFF32002C3E0032032C3E20 :1008C000FF32022CC93E0732012C793261EF32002F :1008D0002CC93E0432032C793262EF32022CC9F566 :1008E000E5CB41282B210129363A3EFF320029363B :1008F0003EAF32002921032936303E3F32022936ED :10090000343E023202293E193D20FD3E3632012995 :10091000CB51280B3E30CB4928023E38320329E127 :10092000F1C9E53A0029210229CB96CBD63A012913 :10093000E68007E1C9F53E02320229AF320029F113 :10094000C9E5210229CB41202236073A0329CB975A :1009500032032936D7CBD732032936853E19CB6EE1 :1009600028073D20F93E81181636C5CBE63A032903 :10097000CB97320329363FCBD73203293612AFE16A :10098000C9E5210229CBE6CB46282536173A0329AB :10099000CB97320329363FCBD7320329AF32002918 :1009A0003612180CE5210229CBA6CB402802CBDE5B :1009B000CB6E201B793200293E0ACB7E28073D20D2 :1009C000F93E82181FCB7620043E811817CBEE3EED :1009D000FFCB7628073D20F93E841808CBAECB9E8E :1009E000AF320029E1C9D5EB210229CB46201A36C6 :1009F000173A0329CB9732032936D7CBD7320329AD :100A00003EFF32002936553645CB762820CBBE3EF8 :100A10000ACB6E20083D20F91182001821CBFE1820041B470D0A1B6701202020E0 :1001A00020201B2920524556204220202032323761 :1001B00020201B282020202020041B470D0A1B671D :1001C0001A7F1818031B470D0A0A0A494E53455255 :1001D00054204449534B20494E204452495645200F :1001E0001B4C411B4D20414E44205052455353203F :1001F00052455455524EAE42FA013E063200EF7956 :10020000CD11023A17EFC300EA3E023200EF3A0482 :10021000003217EFCD020BB720530100D4CD850A71 :100220002100002215EF3E013214EF0602C5060A36 :10023000CD9A0BC12046220FEF2A15EF232215EF8E :1002400010EB3A00EF47C50601CD9A0BC1202D22D5 :100250000FEF2114EF3410EE2150EF110700CD7095 :10026000083EFF3255EF3E7F326EEFAFC91181027B :10027000D53E00CD6008D1CD6F0C189811910218B1 :10028000EF88E4D2ECCA409C9EA840E4CAC2C8F2FF :100290005D84DEDEE840A48A828840CAE4E4DEE4CD :1002A0005D3A59EFB7C83A5EEFCB7FC9CDA10228BE :1002B000FBF34FAF325EEF79E67F4FFBC9FE61D8AB :1002C000FE7BD0D620C9216BEFAFB6280C352009B4 :1002D0003A62EFE6DF4FCDD2082B7EB7280435CC4B :1002E000E80A2B35C0363BAF2B7E3C2777FE60D823 :1002F00036002B7E3C2777FE60D836002B7E3C27CD :100673EF0B257018024 :1005E00000F13DC93620F3D3023680D303FB3A6CC9 :1005F000EF3D5DCBBB93C830043E8093C84F0600EF :100600005D54131850CD6606E501800009300401E1 :1006100000F009E3293A62EFC61794E61F2802E1C9 :10062000C93A6CEFCB3D9538F6E1E53E80A56FCD3C :10063000E4053A62EF47E6E04F3E1F04A0B14FCD1C :10064000D208E1C9C5D5E5EDB8E1D1C1F3D302EDDA :10065000B8D303FBC9C5D5E5EDB0E1D1C1F3D302F1 :10066000EDB0D303FBC97E173F1F77C9F3ED736F5E :10067000EF3199EFF5C5D5E5DDE5FDE5CDC6023AEB :1006800059EFB72843CDC607FEFE283F215CEFBED9 :100690007747215DEF200D7EFE00CAB00635202889 :1006A0003605180E3AC6EFCD6008AF325DEF18D5AB :1006B000362D78CDD206215FEFCB562806CD4407E4 :1006C000CD1507F680325EEFC31E003EFE325CEFB2 :1006D00018F6FE21D8215FEFCB662005CB5E2017F0 :1006E000C9FE413012FE5B3805200F3E5DC95F1622 :1006F0000021D606197EC9FE41D8EE20C9227B7D95 :100700007C7E3C5F3E3F2921402324255E262A280B :10071000203A202B20FE21D8FE403807FE5B30AB6C :10072000E61FC947E62CFE2C20A178211007FE30D9 :100730003803210407856F3001247EC97B1F7D7E2D :100740007B607D73A46 :100A20000029571E00CB5E28021E01CBB63EFFCB2D :100A30006E28093D20F9CBD3CBFB1802CBF6EB7C1B :100A4000D1C9E52100293E1B32022936FF7E36003E :100A50002102293612E1C93E5732002A00000079EE :100A600032C1EF32002AC93A002AE60128F93A01D8 :100A70002A4FC93A002AE602C93A002AE60228F9B2 :100A80007932012AC9ED430FEFC9ED4315EFC9795A :100A90003214EFC9010000C38A0A3A17EF21C7EFE9 :100AA000AEE601FE0120023E40C6404F3A62EF47EB :100AB000E6C0B9CA600C3A6DEFB9281279326DEF11 :100AC000C5216EEF4E3A01217779320121C1CD6007 :100AD0000C06053EFACD60083EFACD60083A0021CA :100AE000E602C810EEF682C93A62EFE61F4FC3D2A3 :100AF000082113EFB6CD200CC0C3470C79CD9D0A59 :100B00001803CD9A0A3E0CCDF10AFEFF2809CB67E7 :100B10002005CB57280CAFF53EFF326AEFCDE00C35 :100B2000F1C9E68018F1CD9A0A3A15EF3203214F48 :100B30003A0121B928283E053205EF3E18CDF10AC9 :100B40004FE6182014CD6C0B200F2109EF3A15EF5A :100B5000BE280B3A05EF3D20DF79F68018B9CD4766 :100B60000C3A14EF320221AFC9CD9A0A3EC4CD200F :100B70000C2109EF0606F3D511A00F3A0021CB474F :100B8000284ECB4F20091B7AB323000077FE25D83601C979FE1020093A07EF2F6C :100310003207EF79C9CD86033A07EFB728F5C379DD :100320000AC903D204F703FB03E903ED03F103F564 :10033000033D0505530F05675605476605295A0510 :10034000286A056C5E056D6E051AA604513E0557B8 :100350002605458A05528A0554FE0423F40422F733 :1003600004AC030DC0040AC904086A040CCE040BD3 :1003700061040173050277050386050796041AA632 :10038000041E5304EF04E5D5C52A5AEF3A60EF473F :10039000E608202379FE1B782815E5212103E607CE :1003A000875F1600197E23666FE379C97818EBF62C :1003B000083260EFC3EF04CB60206BA8473260EFD8 :1003C000E52131031E10791815FE20380BF3D302F6 :1003D0003680D303FBC3D204E52163031E0BBE2387 :1003E00028C323231D20F718BCFE2038DCF6801814 :1003F000DCFE2038D4F680FE2038CEF3D30236005F :10040000D303FBC3D204CB70200FE61F4F3A62EF39 :10041000E6E0B14FCDD208182787C6EAE6FE4FCDF9 :10042000C508CBA81824CD66063EE081CB6820D64F :1004300029CB702010673A62EF841FCB1DF6F0675E :100440003E40B0180817CB2C1F6F3E07A03260EF5C :10045000C3E704CD66063A62EF1F2E00CB1D671876 :100460002FCD6606E50180FF1816CD66063E7FF53A62EF47F10E02FE08285F7D :100750000EFEFE0C2859F53A61EF4FF10601FE0B33 :10076000283A06FFFE0A2834FE31D8F53A62EFE651 :10077000E047F10EEA283DFE37D00E52FE32283413 :100780000EBAFE33282EF578F60847F10EEAFE344D :1007900028220E52FE35281C0EBA18183A62EFE6CF :1007A0001F80E61F473A62EFE6E0B047C3B4073A5E :1007B00061EF814FC5CDC508C148CDD2083E013299 :1007C0005DEFD1C3C8063AFF22EEFF3EFEC821010D :1007D000227DED4F7E2F325FEFE6E3010007180820 :1007E000CB257DED4F7EEEFF28030D585710F10C01 :1007F00028033EFEC93E07931717174F060021171F :1008000008097A0100080F30020D562310F80CCAAF :1008100015083EFEC97AC91B097F7F7F0D275B3112 :10082000323334353637385157455254595549418A :1008300053444647484A4B5A584356424E4D2C0B58 :100840000830202E504F390C0A2D2F3B5C4C3D7A3E :10085000BCC07BBDC037C979D630FE0AF8D607C9FF :10086000C54F3EA03D4049C264080DC26208C1C9DF :100870000E007BB2C8711B7BB2C8424B545D13EDB6 :10088000B0C91AB7F5E67FFE7F4F200C131A3D471B :10089000131A4FCD070310FBCD070313F1F28208A3 :1008A000C9B71A0FF5E67F4FCD070313F130F2C930 :10080F00EFE18413AB5 :100B90000321772310E2D1AFFBC950CD260B2036BD :100BA00042C53E80152802F610CD200CC1FEFF285C :100BB00025F32A0FEFC506003A0021CB472811CBB9 :100BC0004F28F53A0321772310EEC110E8AF18063D :100BD000CDE00CD1F680B7F53EFF326AEFF1FBC9EC :100BE00050CD260B20F042C53EA4152802F610CDAC :100BF000200CC1F32A0FEFC5010001CD060C20D057 :100C0000C110F4AF18D03A0021CB472810CB4F28A1 :100C1000F57E320321230B78B120EBAFC9F680C9F2 :100C2000473A62EFE6C02005C5CD9A0AC1CD470C10 :100C3000F8783200210E003A00211F38050D20F708 :100C40001814AF326AEFC9C50100003A00211F3005 :100C50000A0B78B120F53EFFC1B7C917C1E67FC9BD :100C600078E61FB14FCDD2083ED0320021AFC9D5B2 :100C7000CDB40F3A17EFC6414FCD0703CDBE0FD10C :100C8000C3A108D5E5C5F511C70CCDA108F1CD98D4 :100C90000FCDBE0F3A15EFCD980F0E2CCD86033A2F :100CA0000121CD980FCDBE0F3A14EFCD980F0E2C29 :100CB000CD86033A0221CD980F2A02EF232202EFBC :100CC000CD680CC1E1D1C91A1488E6D6408AA4A423 :100CD0004050E6E8E640E8E4D640E6CAC6525A414B :100CE000C5D5E521002111C2EF010400EDB0E1D12D :100CF000C1C931C1ow) seek to trk 12, sec 0 ; ;:fastr: LK HL,SAVTRK ; LK A,-4 ;seek 4 tracks out ; ADD [hl] ; STO A,[hl] ; LK HL,SEKDEL ; DEC [hl] ;speed up step rate ; CALL SEEK ;seek 4 track outwards, faster ; JRNZ :err ;if stepping too fast ; LD A,SEKDEL ; OR A ;stepping fastest possible? ; JRNZ :fastr ;try a faster seek ;; JR :end ;..else seeking fastest already ; ;:end: CALL BCPM1 ;read in cpm ; JMP BIOS ;cold start ; ;:err: LK HL,SEKDEL ; INC [hl] ;seek at previous (slower) speed ; LK A,0000_0011b ; AND [hl] ;limit seek to (slowest) 3 ; STO A,[hl] ; JR :end WBOOT: Proc LDK A,6-4 ;don't read CBIOS STO A,TEM ;save sectors LD A,CDISK ;Current logged in drive ; JR BCPM ;Boot CP/M space 4,10 BCPM: ;Boot CPM from disk ; Entry A = Drive to boot from. ; TEM = Number of sectors to read from ; track 3. ; A = Drive to boot or warm-boot from ; Exit A = 0, load sucessful. ; Z bit = 1, load successful. proc STO A,SDISK ;Set drive to boot from BCPM1: CALL HOMEF113A0DCD380E21C7EF0E0039 :100D000071FE41CAFA0134FE42CAFA0135FE4BCAED :100D1000440EFE4DCA690EFE52CACD0EFE4420D2CC :100D2000119C0DCD380ED64128043D20C53C32170C :100D3000EFCDAC0DCDD40DC3F20C34404040A49E99 :100D40009A408892828E9C9EA6A89286E61A14A645 :100D5000CAD8CAC6E840A8CAE6E8741A14825884F9 :100D60004084DEDEE840A6F2E61A14408840D2E66F :100D7000D61A14409640CAF25AECC8E81A14409A9F :100D800040CADADEE4F21A1440A440CAC2C840D213 :100D9000DC40E8CAE6E8141A144074411A14A6CAE2 :100DA000D8CAC6E84050825884527441CD100E3ED5 :100DB000003215EF3E013214EF0601CD9A0BB7C495 :100DC000830C3A14EF3CFE0B20EC3A15EF3CFE2866 :100DD00020DF1825CD100E3E643200EFCD1E0F32FD :100DE00015EF0601CD9A0BB7C4830CCD1E0FCD6055 :100DF000083A00EF3D20E2180011050ECDA1082AA7 :100E000002EFC3450F1A148AA4A440C6DCE85A4175 :100E10003A69EF3201EFCDE80A110000ED5302EF1D :100E20004BCD020B280BCD680C118102CD6F0C1835 :100E3000E80180EDCD850AC9CDA108CD590FFE1B73 :100E4000CAF20CC911500ECDA108210040C32E0FCB :100E50001A148ADCE8CAE440D6CAF2E64050E8D266 :100E6 TITLE 'B o o t C P / M f r o m d i s k.' ; ; The CBOOT entry point gets control from the cold start ; loader and is responsible for the basic system initial- ; ization. This includes outputting a sign-on message and ; initializing the following page zero locations: ; ; 0,1,2: Set to the warmstart jump vector. ; 3: Set to the initial IOBYTE value. ; 4: Default and logged on drive. ; 5,6,7: Set to a jump to BDOS. ; ; Before any data is read in, the maximum drive step rate ; must be determined: ; 1. set slowest seek ; 2. home drive A: ; 3. seek track #12 ; 4. speed up step rate ; 5. seek 4 tracks outward (12=>8,8=>4,4=>0) ; 6. if error, slow down step rate by 1, ; load in CP/M, boot, exit, etc. ; 7. else try faster step rate ; (if not fastest, GOTO #4 above) ; 8. if stepping fastest rate, boot CP/M. ; The exit address is to the CCP routine. ; ; ; The WBOOT entry point gets control when a warm start ; occurs, a ^C from the console, a jump to BDED ;home drive OR A JRNZ BCPME ;if drive NOT ready LDK BC,CCP ;Set buffer address CALL SETDMA LDK HL,0 STO HL,SAVTRK ;set track LDK A,1 STO A,SAVSEC ;set sector=1 ; Read in 1st two track LDK B,2 :4: PUSH BC LDK B,MSEC CALL DREAD ;read 1st track POP BC JRNZ BRDE ;if read error STO HL,DMADR ;update DMA LD HL,SAVTRK INC HL STO HL,SAVTRK ;update track to read DJNZ :4 ;if not all tracks ; Now read in requested number of sectors ; from track 3. LD A,TEM MOV B,A ;sectors to read :8: PUSH BC LDK B,1 CALL DREAD ;read one sector POP BC JRNZ BRDE ;if read error STO HL,DMADR ;update DMA LDK HL,SAVSEC INC [hl] ;update sector number DJNZ :8 ;if not all secs LDK HL,HSTACT LDK DE,(LOGSEC-HSTACT)+1 CALL FILLZ ;clear Host BIOS cells LDK A,0FFh STO A,UNASEC LDK A,VLL-1 STO A,LDTRK ;set other drive NOT int XRA A ;Clear error indicator RET ; Here on Drive NOT ready BCPME: LDK DE,DNRMSG ; Output error message and return to BCP000D8D840BCB45240744111C00ECDA1081175 :100E700000EF2100400EA5F3D5E57123CD4F0820EA :100E8000F9E1E5F37EB9281FFB47C5CDB40FCD4589 :100E90000FCDC10FC1C579CD980F0E3DCD8603781A :100EA000CD980FC1CD4C0F23CD4F0820D6FB790F25 :100EB0004F2128F034E1D1CD4C0F28BB4FC3770E22 :100EC0001A149ACADADEE4F240E8CAE6E911FA0E28 :100ED000CDA108CD670A69CD670A61CD450FEB2129 :100EE00000407AB3280BCD670A773228F0231B180D :100EF000F1110D0FCDA108C300401A14A6E8C2E4F9 :100F0000E840D2DCE0EAE8744098CADC7B1A14A01E :100F1000E4DECEE4C2DA40C4CACED2DCE675ED5FD0 :100F2000AEE63FC611FE28DA2C0FD62877C9CDAC25 :100F300002FE1ACAF20C7723FE0D2003360A234F55 :100F4000CD860318E97CCD980F7D184CCDA102C841 :100F5000CDAC02FE1BCAF20CC9CDAC02CD0703C357 :100F6000BD02C53A15EF210121B6CA720F3E40CD30 :100F7000F10A3EF4F3CD200CE1FBC0F34E234623EF :100F8000CD060C20113A0021B7280BE60228F63EC8 :100F9000FF32032118EFFBC9F50F0F0F0FCDAA0F7A :100FA000CD0703F1CDAA0FC30703E60FC69027CEE6 :100FB00040274FC90E0DCD86030E0AC38603CDC14F :060FC0000F0E20C38603A2 :00010010 OS (function ; 0), or a jump to location zero. The WBOOT routine reads ; the CCP and BDOS from the appropriate disk sectors. ; WBOOT must also re-initialize locations 0,1,2 and 5,6,7. ; The WBOOT routines exits with the C register set to the ; appropriate drive selection value. The exit address ; is to the CCP routine. ; ; Disk layout Definition ; --Note: Tracks 0, 1, and 2 are reserved for CPM.-- ; Track 0----------- ; 1 thru 8 CCP 2k ; 9 thru 10 BDOS ; Track 1----------- ; 1 thru 10 BDOS ; Track 2----------- ; 1 thru 2 BDOS 3.5k ; 3 thru 10 CBIOS 2k ; Sectors 3,4,5,6 are currently used. page CBOOT: ;Entry C= drive to boot from ; Exit A= drive Proc LDK A,6 ;read 5 sectors of trk 3 STO A,TEM MOV A,C CALL BCPM ;boot system LD A,SDISK ;use requested drive JMP BIOS ;enter CPM ; LK A,3 ; STO A,SEKDEL ;set step rate =3 (slowest) ; CALL HOMED ;send A: home ; ; LK BC,12 ; CALL SETTRK ;track 12 ; LK C,0 ; CALL SETSEC ;sector 0 ; CALL SEEK ;do (slM BCPME1: PUSH DE LDK A,low(256) CALL DELAY ;Delay 256 milli-seconds POP DE ;FWA of message CALL ODER ;indicate drive NOT ready JR BCPM1 ;try again ; Here on Boot READ error BRDE: LDK DE,BRDEMG JR BCPME1 ;delay output error DNRMSG: DCE 'Drive NOT ready.' BRDEMG: DCE 'Boot READ error.' ; Endx BMboot.asm date track to read DJNZ :4 ;if not all tracks ; Now read in requested number of sectors ; from track 3. LD A,TEM MOV B,A ;sectors to read :8: PUSH BC LDK B,1 CALL DREAD ;read one sector POP BC JRNZ BRDE ;if read error STO HL,DMADR ;update DMA LDK HL,SAVSEC INC [hl] ;update sector number DJNZ :8 ;if not all secs LDK HL,HSTACT LDK DE,(LOGSEC-HSTACT)+1 CALL FILLZ ;clear Host BIOS cells LDK A,0FFh STO A,UNASEC LDK A,VLL-1 STO A,LDTRK ;set other drive NOT int XRA A ;Clear error indicator RET ; Here on Drive NOT ready BCPME: LDK DE,DNRMSG ; Output error message and return to BCPY ;if NO data DI MOV C,A XRA A STO A,LKEY ;clear key from hold MOV A,C AND 7Fh MOV C,A ;A=C EI RET space 4,10 NORM: ;Normalize to UPPER case ; Entry A= char ; Exit A= CHAR CMP 'a' RC ;if upper CMP 'z'+1 RNC ;if not lower SUI 'a'-'A' RET REPD = 45 ;initial rep delay REPK = 5 ;repeat constant .nkbd IF @KEY = 0 ;if not new keyboard, use old code GKEY: ;Keyboard interrupt processor. ; Scans both sets of data lines to see if any key ; pressed. If so then determines key and ; Sets TKEY to value. ; If TKEY and next key same then HKCNT set. ; If HKCNT set and no key on this entry, then ; LKEY is set and we have found a valid key closure. ; Entry None ; Exit Cbit set if key RNK5: = 21h ;rank 5 RNK6: = 01h ;rank 6 RNKCTL: = 0A0h ;Control rank proc .mac IF RSIZE = 64 DI .mac ENDIF STO SP,IESTK ;save int process stack LDK SP,ISTK ;set to RAM int stk PUSHAL ; Update and display current time CALL UPTIM ;update time ; Perform Scan JRZ :20 ;if [, shifted = ']' CMP '1' JRC :19 ;if not shiftable CMP 'A' JRNC :18 ;if possible alpha SUB 10h JR :19 :18: CALL NORM :19: MOV C,A ; Here to actual set key ; Entry C= current keystroke value :20: SBIT 7,C ;set bit 2**7 LD A,TKEY CMP C JRZ :16 ;if last = current MOV A,C STO A,TKEY ;confirm key (debounce) STO A,LKEY LDK A,REPD STO A,HKCNT ;set to surface next time ; JR GKEYX ;exit ; restore regs, clear interrupt and return GKEYX: JMP EXITI ;Exit interrupt ; Here if debounced key, process SHIFT, Control and ; REpeat functions ; Entry C= current character :16: LDK HL,HKCNT DEC [hl] ;reset hold count JRNZ GKEYX ;if keep holding MOV A,C :16A: STO A,LKEY ;show keep to user MOV C,A ;save current key LDK A,REPK STO A,HKCNT ;reset hold for repeat JR GKEYX ;exit page RDKEY: ;Read keyboard for valid key pressure ; Exit A= current key ; if A = -1, exit to GKEYX ; = -2, NO key pressure proc .rdkey IF @KEY = 0 L of Keyboard LD A,KEYLCK ;locked keyboard? OR A JZ GKEYX ;if locked keyboard, can't read chrs CALL RDKEY ;read keyboard CMP -2 JRNZ :4 ;if key depressed ; Here if no key press, check for holding ; debounced key, if so surface key. :2: LD A,TKEY BIT 7,A JRZ :3 ;if no key holding LD A,LKEY STO A,TKEY ;clear-set hold :3: JMP GKEYX ;exit :4: PUSH AF CALL RDKEY ;Try again POP DE ;last A CMP D JRNZ :2 ;if not match, error CMP -1 JZ GKEYX ;if null control key ; A= current key pressed ; TKEY = last scan key found GKEY10: MOV C,A ;save current key LD A,CKEY ;control key value OR A JRZ :20 ;if no special function keys ; If special, check type BIT 6,A ;40h JRZ :17 ;if NOT contrl key ; Process Control key ; Check for ^1, 2, or 3 for fixed alignment MOV A,C CMP '1' LDK C,VFLO JRZ :10B ;if ^0, align to 0 offset CMP '2' LDK C,VFLO+2*52 ;2*52 compensates for 1/2 chr shift JRZ :10B ;if ^1, align to 52 CMP '3' LDK C,VFLO+4*52 ;4D A,H.KEY+0DFh CMA MOV B,A LD A,H.KEY+07Fh ;everything but cntrl rank CMA OR B LDK A,-2 RZ ;if NO key pressure ; save any contrl keys LD A,H.KEY+RNKCTL CMA STO A,CKEY ;save control key ; B <> 0 means Bit 5 table MOV A,B OR A JRZ :5 ;if bit 5 table :3: LDK HL,H.KEY+1 LDK DE,T6KEY-1 JR :5A ;process ; Here if Bit 5 set :5: LDK HL,H.KEY+21h LDK DE,T5KEY-1 :5A: LDK BC,0 :5B: LD A,[hl] ;get next scan line CMA OR A JRNZ :6 ;if key active PUSH BC LDK IX,SCANI ADD IX,BC LD C,[ix+0] ADD HL,BC ;next line POP BC INC BC JR :5B ;loop to next SCANI: DB 1,2,4,8,30h,40h ; Here with C = address line ; A= key down bit :6: PUSH AF ; Check for control key rank MOV A,L CMP RNKCTL JRNZ :6A ;if not control rank LD A,H.KEY+0DFh CMA OR A JRNZ :3 ;if key active in other rank STO A,TKEY ;clear key POP AF ;restore stack LDK A,-1 ;indicate exit RET ; Process active key :6A: MOV A,C ANI 7 ;get relative to 0 RAL ! RAL ! TITLE 'Keyboard and Console Routines.' @KEY = 1 ; Control keys CBELL = 'G'-40h ;Ring the Bell MCUP = 'K'-40h ;Move cursor up MCDOWN = LF ;Move cursor down MCLEFT = BKS ;Move cursor left MCRIGH = 'L'-40h ;Move cursor right VCLRS = 'Z'-40h ;Clear and home cursor VHOME = '^'-40h ;Home Cursor ; Escape keys VLOCK: = '#' ;Lock Keyboard VUNLK = '"' ;Unlock Keyboard VCAD: = '=' ;Cursor Addressing VSAD: = 'S' ;Screen Addressing VINC: = 'Q' ;Insert Char VDELC: = 'W' ;Delete char VINL: = 'E' ;Insert line VDELL: = 'R' ;Delete line VCEOL: = 'T' ;Clear to end of line VSHI: = ')' ;Start half intensity VEHI: = '(' ;end VSUL: = 'l' ;Start underline VEUL: = 'm' ;end VSGH: = 'g' ;Start graphics VEGH: = 'G' ;End SKEY: ;Get status of keyboard ; Exit Cbit set if no data ready LD A,KEYLCK OR A RZ ;if locked keyboard LD A,LKEY BIT 7,A RET ;=0 if NO DATA space 4,10 CI: RKEY: ;Read next key from keyboard ; Exit A=C= last key proc CALL SKEY JRZ RKE*52 = 208 shifts = 104 characters JRZ :10B ;if ^2, align to 104 ; Check for special control code sceen movement codes ; if so process local and return LDK E,2 CMP MCLEFT JRZ :10A ;if move screen LDK E,-2 CMP MCRIGH JRNZ :10C ;if not screen right :10A: LD A,PIAAD ;current horz offset ADD A,E MOV C,A :10B: CALL OPAD ;reset offset hardware XRA A ;clear entry key JR GKEYX ;exit :10C: CMP ' ' JC :20 ;if literal CMP '@' LDK C,0 JC :20 ;if illegal code CALL NORM SUB '@' CMP ' ' JNC :20 ;if illegal JR :19 ;converted control code ; Check for SHIFT key ; A= shift status ; C= current character :17: BIT 5,A ;20h JRZ :20 ;if NOT shifted MOV A,C ;get actual char ; Check for legal SHIFTED code :17B: CMP ',' JRC :19 ;if impossible shift CMP '/'+1 JRNC :17C ;if not ascii reverse pairing ADD A,10h JR :19 :17C: CMP '0' LDK C,'^' JRZ :20 ;if O, shifted = '^' CMP '@' LDK C,'\' JRZ :20 ;if @, shifted = '\' CMP '[' LDK C,']'  RAL ;*8 MOV C,A LDK B,0 EX DE,HL ;base to HL ADD HL,BC LDK BC,0 POP AF ;get bit back OR A ;clear carry ; Now convert bit value to binary :7: INC C RRC JRNC :7 ;if not bit ADD HL,BC ;add in value ; Get Actual Key pressure value into A. LD A,[hl] ;get table value RET .rdkey ELSE LD A,H.KEY+0FFh XOR 0FFh ;1s complement, set flags MOV B,A LDK A,-2 RZ ;if no key ; Read CNTRL rank and save LD A,H.KEY+01 CMA STO A,CKEY ;save it ; Key depressed, check for which rank, make ; sure its legal, ie. not just CNTRL key. LDK DE,2 ;ignore contrl rank LDK B,6 ;number of ranks-CNTRL rank :3: LDK HL,H.KEY ;base ADD HL,DE ;address of next rank LD A,[hl] ;get possible entry XOR 0FFh JRNZ :7 ;if found key pressure DEC B JRZ :5 ;if all done with scan EX DE,HL ;power of 2 to DE ADD HL,HL ;*2 EX DE,HL ;next rank to DE JR :3 ;continue ; Here if suppose to be key down, but none ; found in non-CNTRL key ranks. Check for TAB, ; eF, ':', '/', ';', '\', '1', '-' ENDIF .nkbd ENDIF page UPTIM: ;Update time via 60hz interrupt ; Time is kept in video memory as ; hhmmss (3 locations) ; Routine also checks to see if the disk drive motor ; should be turned off by updating DACTIVE ; ...Routine ALSO checks to see if bell is currently ; ringing: if so, decrement counter. ; if counter turns zero, shut off bell. Proc LK HL,BELCNT XOR A OR [hl] ;cell=zero ? JRZ :2 ;if bell now off DEC [hl] ;...bell is on. decrement counter JRNZ :2 ;if bell should stay on awhile yet LD A,PIABD AND 1101_1111b ;clear bell bit MOV C,A CALL OPBD :2: DEC HL ;HL => DACTVE LD A,[hl] OR A JRZ :3 ;if inactive DEC [hl] ;reset delay CZ DDRV ;if deselect drive :3: DEC HL ;HL => SEC6 DEC [hl] RNZ ;if not 1 sec transition STO 59,[hl] ;60th tick is NOW XOR A ;A:=0, CY:=0 for DAA DEC HL ;HL => SECS LD A,[hl] ! INC A ! DAA ! STO A,[hl] CMP 60h RC ;if not 60 secs STO 0,[hl] ;reset seconds DEC HL Lelete line DB VCEOL ! DW EEOL ;Clear to end of line DB VLOCK ! DW ESCLCK ;Lock Keyboard DB VUNLK ! DW ESCULK ;Unlock Keyboard :end: DW COUT2 ;No Match exit ; Ignore char upon undefined ESC-Sequence ; (to treat undefined char after ESC as a regular ; data char, should go to COUT2). VALETS: = (:end-VALIDE)/3 ;# of entries in table space 4,10 VALIDC: ;Valid control character table ; 3 bytes per entry: Ascii char , "DW"- Vector ; no. of entries is VALCTS ; Following body of table is 2 byte No-Match adrs DB CR ! DW VC_CR ;carriage return routine DB LF ! DW VC_LF ;line feed DB BKS ! DW VC_BKS ;back space DB MCRIGH ! DW VC_MCRT ;move cursor right DB MCUP ! DW VC_MCUP ;move cursor up DB 'A'-40H ! DW VSHFT_L ;shift screen left DB 'B'-40H ! DW VSHFT_R ;shift right DB 'C'-40H ! DW VSHFT_0 ;left column (^1) DB CBELL ! DW VC_BEL ;Ring bell DB VCLRS ! DW VC_CLRS ;clear screen DB VHOME ! DW VC_HOME ;Cursor Home ; DW VOUT97 ;No match--ignore undef control char ; lse key down is to be ignored. :5: LDK HL,T5KEY LD A,CKEY OR A JRZ :nokey ;if no CNTL-key sensed either CALL DRNK ;check for tab CMP TAB RZ ;if tab :nokey: LDK A,-2 ;indicate NO key, just CNTRL RET ; Here if found key down i non-CNTRL ranks ; HL = rank address ; A = value ; B = 7..1, 7-(ordinal of rank) :7: PUSH AF ;save value LK A,8 SUB B ;A = ordinal of rank RLC ! RLC ! RLC ;*8 to get address MOV E,A LDK HL,T5KEY ;base for decode LDK D,0 ADD HL,DE ;get key decode base POP AF DRNK: ;Decode rank value ; Entry A= rank value read ; HL=fwa of rank entry ; Exit A= key value in ASCII LDK BC,-1 OR A ;clear carry :8: INC BC ;update base adder RRC JRNC :8 ADD HL,BC LD A,[hl] ;get actual key RET .rdkey ENDIF page ; Character input translation table IF @KEY = 0 T5KEY: DB ESC, ESC, ERC, ERC, ERC, ERC, ERC, ERC ;5KEY: DB TAB, ESC, ERC, ERC, ERC, ERC, ERC, ERC DB '1', '2', '3', '4', '9', '0', ':', '-' ; DB '1',D A,[hl] ! INC A ! DAA ! STO A,[hl] CMP 60h RC ;if not 60 minutes STO 0,[hl] DEC HL LD A,[hl] ! INC A ! DAA ! STO A,[hl] CMP 25h RC ;if time <= 24:59:59 STO 1,[hl] RET page CO: ;Output routine for monitor ; Entry C= char ; CO will process ^p to toggle ; echo to list device ala cpm. ; Exit C=C=A. proc MOV A,C CMP 'P'-40h JRNZ :5 ;if not toggle echo list LD A,ECHOP CMA STO A,ECHOP ;toggle list echo :2: MOV A,C ;perserve A RET :5: CALL COUT ;output char LD A,ECHOP OR A JRZ :2 ;if no echo to list JMP LIST ;echo it page ; Bit definitions for ESCH flag byte ; Note Bit 7 is currently free. EF_X: = 64 ;B6= extegting X-coordinate EF_SCR: = 32 ;B5= Screen/Cursor Addressing EF_ADR: = 16 ;B4= expegting address-chr EF_ESC: = 8 ;B3=$last char was ESC EF_UN: = 4 ;B2= Underline mode EF_HA: = 2 ;B1= Half Intensity mode EF_GR: = 1 ;B0= Graphics mode EF_MSK: = EF_UN+EF_HA+EF_GR ;Mask to get mode. space 4,10 ; Vector (branch) table for v VALCTS: = ((*-2)-VALIDC)/3 ;Number of valid entries page COUT: ;General output routine to Video Screen ; ENTRY C=Character, CURS=Cursor, ESCH=Flag+Mode ; EXIT CURS & ESCH updated, A=Character ; (bc, de, hl preserved) ; ; ESCH is flag + mode byte as follows ; =00 Normal mode & Last chr Esc flag false ; =08 Normal mode & Last chr Esc flag True ; =01,02,04 Mode is Graphics, Half, or Under, respectively ; , and Last chr Esc flag is False. ; =3,5,6,7 As above, but mode is combination ; =9-15 Last chr Esc flag True;otherwise like 1-7. proc PUSH HL PUSH DE PUSH BC LD HL,CURS ;HL will usually be cursor. LD A,ESCH MOV B,A ;B will be ESCH for a while AND EF_ESC ;test flag bit JRNZ PSTESC ;IF last chr was ESC ;Current chr is NOT ESCaped. Is this chr ESC? MOV A,C ;Chr CMP ESC MOV A,B ;(A=ESCH) JRZ :ESC ;if this chr = ESC space 4,10 ;Here with A=B= ESCH :out: PUSH HL LK HL,ESCHTB AND EF_MSK ;Mode bits only ADD A,A ;Times two MOV E, '2', '3', '4', '9', '0', '-', '~' DB 'q', 'w', 'e', 'r', 'o', 'p', '@', 7Fh ; DB 'q', 'w', 'e', 'r', 'o', 'p', '{', '}' DB 'a', 's', 'd', 'f', 'l', ';', BKS, FMFD ; DB 'a', 's', 'd', 'f', 'l', ';', ':', '\' DB 'z', 'x', 'c', 'v', ERC, '.', '/', ERC DB ' ', ERC, ERC, ERC, ERC, ERC, ERC, ERC DB ERC, ERC, ERC, REP, CAPS, SHTK, CTRL, ERC T6KEY: DB ERC, ERC, ERC, BKS, VTAB, ERC, ERC, ERC DB '6', '5', '7', '8', '[', ERC, ERC, ERC DB 'y', 't', 'u', 'i', '-', ERC, ERC, ERC DB 'h', 'g', 'j', 'k', CR, ERC, ERC, ERC Db 'n', 'b', 'm', ',', LF, ERC, ERC, ERC ELSE T5KEY: T6KEY: DB ESC, CTRL, CAPS, SHTK, CR, TAB, TAB, '_' DB '1', '2', '3', '4', '5', '6', '7', '8' DB 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i' DB 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k' DB 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',' DB MCUP, BKS, '0', ' ', '.', 'p', 'o', 'p' DB MCRIGH DB Lideo output mode selection ; controlled by ESCH mode ESCHTB: DW VNORM ;0 Normal mode DW VGRAPH ;1 Graphics mode DW VHALF ;2 Half intensity mode DW VHA_GR ;3 Half and graphics DW VUNDER ;4 Underline mode DW VUN_GR ;5 Under and graphics DW VUN_HA ;6 Under and half intensity DW VUN_HA_GR ;7 Under and half and graphics space 4,10 VALIDE: ;Valid ESC-Sequence Table ; 3 bytes per entry:ascii char , "DW"-Vector. ; no. of entries is VALETS ; Following body of table is 2 byte No-Match adrs DB VCAD ! DW ESCCAD ;Cursor Addressing DB VSAD ! DW ESCSAD ;Screen Addressing DB VSGH ! DW ESCSGR ;Set graphics mode DB VEGH ! DW ESCCGR ;Clr graphics mode DB VSHI ! DW ESCSHA ;Set half int. mode DB VEHI ! DW ESCCHA ;Clr half int. mode DB VSUL ! DW ESCSUN ;Set underline mode DB VEUL ! DW ESCCUN ;Clr underline mode DB VCLRS ! DW ESCZZ ;Clear screen to blanks DB VINC ! DW EINSRT ;Insert char DB VDELC ! DW EDELC ;Delete char DB VINL ! DW ESCEE ;Insert line DB VDELL ! DW ESCRR ;DA LK D,0 ;DE = offset ADD HL,DE ;HL = tbl addrs VECTOR: ;entry point. note hl on stack. LD A,[HL] ;1st byte (low order adrs) INC HL LD H,[HL] ;2nd byte (hi order adrs) MOV L,A ;HL=adrs from table XTHL ;Restore hl from stack ;stack=tbl adrs MOV A,C ;Chr. note B=ESCH byte value RET ;enter routine per table adrs. COUT2: MOV A,B ;recall ESCH value JR :out ;output chr per current settings :ESC: ;Current chr is ESC. Set flag and exit OR EF_ESC ;indicate last char= ESC STO A,ESCH JMP VOUT97 ;Exit space 4,17 PSTESC: ;Last chr was ESC ; Entry A= EF_ESC ; B= ESCH ; C= Char to output ; HL=curs Proc BIT 4,B ;is this chr really an address? JRNZ SETXY ;...if chr is part of an addr ;no cursor/screen addressing in effect: XOR B ;Clr EF_ESC bit (for next time) MOV B,A ;Set up B = ESCH byte value. STO A,ESCH PUSH HL ;save Curs LDK HL,VALIDE ;Branch table adrs LDK E,VALETS ;Table size MOV A,C ;Chr to A JR LOOKUPB ;Go to routine to bran :sY: AND 0001_1111b ;mod 32 MOV C,A LD A,PIABD AND 1110_0000b OR C MOV C,A CALL OPBD ;set Y coordinate JR :exitY :sX: ADD A,A ;double A ADD A,VFLO ;PIA A-reg magic offset constant AND 1111_1110b ;clear bit 0 => no 1/2 chr shift MOV C,A CALL OPAD ;set X coordinate CBIT 5,B ;finished screen-addressing JR :exitX space 4,10 SETXY: ;Set X-Y value for Cursor/Screen Addressing ; Entry HL= cursor_addr ; B = ESCH ; C = chr ; Exit to VOUT90; ESCH updated CALL UN_CUR LK A,-(' ') ADD C ;remove cursor bias BIT 5,B ;cursor/screen addressing? JRNZ SCREEN ;if screen addressing ;cursor addressing: ADD HL,HL ;shift HL left BIT 6,B ;X/Y coordinate? JRNZ :cX ;if X coordinate :cY: MOV H,A ;save LD A,PIABD ADD H ;offset by start-Y co-ord of video RAR ;bit0(A) -> CY, shift A right RR L ;CY -> bit7(L) OR 0F0h ;turn on upper nybl MOV H,A ;HL= new cursor addr ; JR :exitY :exitY: LK A,0100_0000b ;next addr-chr will be X-coord OR B JR :exit2 :cX: page ; Exit points for COUT ; Here to store new data and to update cursor VGRAPH: VOUT80: STO A,[hl] ;This exit path stores A (new char) MOV E,L CBIT 7,E ;E = col(cursor) LD A,LLIMIT DEC A ;A = last_legal_col SUB E ;A = last_legal_col - col(cur) JRNZ VOUT85 ;if not @LLIMIT LK A,80h AND L MOV L,A ;do CR... CALL DO_LF2 ;...and LF. JR VOUT90 VOUT85: INC HL ;move cursor ; Here if NO cursor update VOUT90: LD A,[HL] ;This exit path turns on 80h bit ; Here if new data already in A VOUT95: RAL ;Make this chr cursor VOUT96: CMC ;invert cursor bit RAR STO A,[hl] STO HL,CURS ;update cursor ; Here if no change to cursor, restore reg and exit VOUT97: POP BC POP DE POP HL MOV A,C ;Exit with A=chr RET ;return, end of cout subr. space 4 :First = VOUT97 - (127 + 2) ;earliest possible JR :Last = VOUT80 + (128 - 2) ;latest possible JR page ESC_LCK: ;Lock Keyboard Proc XOR A JR :2 ESC_ULK: ;Unlock Keyboard LK A,0FFh :2: STO A,KEYLCK ch per tbl space 4,15 VNORM: ;NORMAL mode character processing. ; Entry A= char to output ; HL=curs CMP ' ' JRC :2 ;IF control chr VBRIGH: DI ! ENADIM ;9th bit memory STO BRTBIT,[hl] ;set this chr BRIGHT DISDIM ! EI JMP VOUT80 :2: PUSH HL ;Save Curs LDK HL,VALIDC ;Branch table adrs LDK E,VALCTS ;Table size ; JMP LOOKUPB ;Scan table of valid control chrs ; ;and branch to appropriate routine. space 4,20 LOOKUPB: ;Logic to scan 3 byte branch table ; NOT a subroutine---do not CALL. ; Entry HL =1st byte of table (match code) ; (2nd,3rd bytes = branch adrs) ; (table repeats [3 byte entries]) ; E is table size (no. of entries) ; (table body is followed with ; 2 byte "No-Match" adrs) ; Stack has HL saved as top entry. ; C = char ; A = value to scan for possible match CMP [HL] INC HL ;(2nd byte of this 3 byte entry) JRZ VECTOR ;If match process INC HL ;(3rd byte of this entry) INC HL ;1st byte of next entry DEC E ;Dec count of entries remaining JRAL ;trash 7th bit SRA H ;bit0(H) -> CY, bit7 stays 1 RAR ;... CY -> bit7(A) MOV L,A ; JR :exitX :exitX: LK A,EF_MSK AND B ;finished addressing: reset addr bits :exit2: STO A,ESCH JMP VOUT90 page ; Control Code character processing VC_HOME: ;Home Cursor Proc CALL UN_CUR LD A,PIABD RAR ;bit0 => CY LK L,0 RR L ;CY => bit7, trash bit0 MOV H,A JR :fixhl ;HL := HL or F000h space 4,7 VC_MCUP: ;Move Cursor Up. ; A=C=Chr=MCUP. HL=Curs. CALL UN_CUR PUSH HL ;old cursor must be on stack LK BC,(-VLL) JR :fwa ;...at this entry point space 4,28 VC_BKS: ;HL=Curs=current (old) char CALL UN_CUR ;clear 80h bit LK A,7Fh AND L JRZ :wrap ;if must wrap from col 0 to LLIMIT DEC HL JR VOUT90 ;Exit :wrap: PUSH HL ;save old cursor LK BC,-(VLL+1) ADD HL,BC ;HL = prev_line, (-1)st column LD A,LLIMIT ;LLIMIT = #columns on screen MOV C,A LK B,0 :fwa: ADD HL,BC XTHL ;get old cursor, save new ADD HL,HL ;shift line# into H reg. LD A,PIA JR VOUT97 space 4,5 EEOL: ;Erase to end of line PUSH HL ;save cursor CALL CLRLN POP HL JR VOUT90 space 4,12 ESC_CAD: ;Cursor Addressing LK A,EF_MSK AND B OR EF_ESC or EF_ADR ;next chr will be Y-coord :exit3: STO A,ESCH JR VOUT97 ESC_SAD: ;Screen Addressing LK A,EF_MSK AND B OR EF_ESC or EF_ADR or EF_SCR JR :exit3 page ;Subroutine for use with EDELC and EINSRT: ;Calculate #chrs to move; if move zero chrs, never return. Proc :calc: LK A,VLL-1 ;A= max #chrs to be moved MOV C,L CBIT 7,C ;C = col(cursor) SUB C ;A = #chrs to move JRZ :end ;if move zero characters MOV C,A LK B,0 ;BC = #chrs to move RET :end: POP HL ;trash return_addr POP HL ;cursor_addr JR VOUT90 space 4,14 EDELC: ;Delete Character PUSH HL ;save cursor_addr CALL :calc ;calculate BC MOV D,H MOV E,L ;DE = cursor_addr INC HL ;HL = cursor_addr + 1 CALL VLDIR ;move characters STO ' ',[hl] ;last chr becomes blank DI ! ENADIM ;enable 9th bit memory DEC HL ;HL = last RNZ LOOKUPB ;Continue thru body of table JR VECTOR ;No-Match. hl=points to vector page ; Processing for modes other than normal. ; -------------------------------------- ;VGRAPH = VOUT80 ;Normal mode EXCEPT: cntl chrs are printed VUNDER: ;Underline only CMP ' ' JRC VNORM ;if cntl-chr, process as normal ; JR VUN_GR ;continue VUN_GR: ;Underlined Graphics OR 80h ;underline bit JR VBRIGH ;set this chr BRIGHT VUN_HA: ;Underline and Half intensity CMP ' ' JRC VNORM ;if cntl-chr, process as normal ; JR VUN_HA_GR VUN_HA_GR: ;Underline, Half Intensity, Graphics OR 80h ;set underline bit ; JR VHA_GR VHALF: ;Half Intensity CMP ' ' JRC VNORM ;if cntl-chr, process as normal ; JR VHA_GR VHA_GR: ;C=Chr, HL=Curs DI ENADIM STO DIMBIT,[hl] ;set dim field bit ; LD E,[hl] ;diagnostic DISDIM EI JMP VOUT80 ;continue space 4,22 SCREEN: ;SetXY for Screen movement ; Entry B= ESCH ; A= new co-ord val, NO OFFSET Proc BIT 6,B JRNZ :sX ;if X-coordinate BD OR 1110_0000b ;A = line# of UL corner CMP H ;set Zflag: @home? POP HL ;get new cursor... JRNZ :fixhl ;if NOT @video home LK BC,(24*VLL) ;wrap constant ADD HL,BC :fixhl: LK A,0F0h OR H ;modulo result: keep cursor MOV H,A ;inside video memory. JR VOUT90 space 4,8 VC_BEL: ;Ring the bell via setting PIAB 2**5 bit LD A,PIABD OR 0010_0000b ;bell bit MOV C,A CALL OPBD ;function PIAB LK A,30 ;ring bell for 30 ticks STO A,BELCNT ;... = 1/2 second JR VOUT97 ;exit no change space 4,10 VC_CLRS: LK HL,FWAVM CALL CLRLN ;clear 1st line LK BC,LVMEM-VLL CALL VLDIR ;clear remaining lines LD A,PIABD ;Reset for 1st line of display mem AND not(1_1111b) MOV C,A CALL OPBD LK HL,FWAVM ;new cursor JR VOUT90 ;Exit space 4,8 VC_CR: CALL UN_CUR ;erase cursor LK A,80h ;Carriage Return AND L MOV L,A JR VOUT90 VC_LF: CALL DO_LF ;Line Feed JR VOUT90 space 4,3 VC_MCRT ;Move Cursor Right CALL UN_CUR LD A,[hl] ; JR VOUT80 ;re-echo current chr chr on this line STO BRTBIT,[hl] ;set chr BRIGHT DISDIM ! EI ;main memory POP HL ;restore cursor_addr JR VOUT90 ;next space 4,14 EINSRT: ;Insert Character CALL UN_CUR PUSH HL ;save cursor_addr CALL :calc ;calculate BC LK A,7Fh OR L MOV L,A ;HL = last_chr on this line MOV E,A MOV D,H ;DE = HL DEC HL CALL VLDDR ;do move POP HL ;restore cursor LD A,[hl] ;get underline bit of this chr. RAL ;into CY LK A,' ' shl 1 ;change this chr to ' ' JR VOUT96 ;exit page ; ESC-Sequence processing. Proc ESCSGR: LDK A,EF_GR ;ESC-g JR :125 ;set graphics mode. ESCSHA: LDK A,EF_HA ;ESC-) set half intensity JR :125 ;go set flag bit ESCSUN: LDK A,EF_UN ;ESC-l set underline :125: OR B ;Reg B is ESCH Byte value :130: STO A,ESCH ;store desired value. JR VOUT97 ;Exit ESCCGR: LDK A,NOT EF_GR ;ESC-G Clear graphics mode JR :140 ;go clear ESCH bit ESCCHA: LDK A,NOT EF_HA ;ESC-( Clear half intensity JR :140 ESCCUN: LDK A,NOT EF_UN ;ESC-m Clear underlend of line ; Entry HL= Cursor ; Exit clear to EOL ; Uses All. proc STO ' ',[hl] ;clear cursor... DI ENADIM STO BRTBIT,[hl] ;set cursor BRIGHT DISDIM EI LD A,LLIMIT DEC A ;max_#cols => maximum_col_# MOV E,L CBIT 7,E SUB E ;A = col(EOL) - col(cursor) RZ ;if @EOL, done JRNC :2 ;if inside logical_video_line LK A,VLL SUB E ;...else clr to end of 128-chr line RZ ;if cursor @ column #127 :2: MOV C,A LK B,0 ;BC = chrs to move MOV E,L MOV D,H INC DE ;DE = HL + 1 JR VLDIR page DO_LF: ;Do Line Feed processing ; Entry HL = cursor_addr ; Exit Cursor cleared ; HL updated for current cursor pos ; window moved if necessary proc CALL UN_CUR ;clear cursor DO_LF2: PUSH HL ;save original cursor LK BC,VLL ;line length ADD HL,BC JRNC :nowap ;if not wrapping from LWAVM to FWAVM LK BC,FWAVM ADD HL,BC ;HL = new cursor @ top of VM :nowap: XTHL ;save new cursor, get old ADD HL,HL ;shift HL left LD A,PIABD ADD A,23 ;start + 23 = last_videoYBOARD: LK HL,TKEY CMP [HL] ;SAME AS LAST TIME? (SET Z FLAG) STO A,[HL] ;SET TKEY TO CURRENT VALUE MOV B,A ;SAVE CHR LK HL,HKCNT JRNZ :1ST ;IF THIS IS FIRST SUCH KEYPRESS MOV A,[HL] CMP 0 JZ :2ND ;SECOND TIME FOR THIS KEY :AUTO: DEC [HL] JRNZ GKEYX ;IF STILL WAITING FOR REPD/REPK STO REPK,[HL] ;...ELSE SET REPK FOR NEXT CHR, JR :DCODE ;AND RETURN CHR :1ST: LD A,KBDLY ;GET # OF INTERRUPTS TO DEBOUNCE CALL DELAY XRA A ;ZERO "HKCNT" STO A,HKCNT JR :SCAN :2ND: STO REPD,[HL] ;SET "REPD" DELAY :DCODE: MOV A,B ;RESTORE CHR CALL SHIFT ;SHIFT PROCESSING LK HL,CKEY BIT 2,[HL] ;CK FOR CNTL KEY JRZ :FIN ;IF CNTL-KEY IS NOT PRESSED CALL SLIDE ;CK FOR SCREEN SLIDE KEYS CALL CNTRL ;CNTRL KEY PROCESSING :FIN: OR 80H ;SET PARITY BIT FOR CI STO A,LKEY ;MAKE CHR AVAILABLE TO CI GKEYX: JMP EXITI ;EXIT INTERRUPT GKEYAB: ;ABORT PROCESSING: SET TKEY := -2 AND RETURN. LK A,-2 STO A,TKEY JR GKEYX PAGE SHIFT: ;SHIFT KEY PROCESSING ; ENTRine :140: AND B ;Clear bit JR :130 ;Go store ESCH byte ESCZZ: = VC_CLRS ;ESC-Z Clear screen -same as ; ;Control-Z routine. page Proc VSHFT_L: ;shift screen left LK C,+2 JR :slide VSHFT_R: ;shift screen right LK C,-2 :slide: DI LD A,PIAAD ;get old offset ADD C ;modify... MOV C,A :1: CALL OPAD ;new setting for video offset EI JMP VOUT97 VSHFT_0: ;shift to column #0 (like ^1) LK C,VFLO ;constant for column #0 JR :1 ;set video offset page ESCRR: ;Delete Line ESCEE: ;Insert Line ; Entry HL = cursor ; C = chr ; Exit screen updated ; HL = new cursor ; ...to VOUT90 Proc CALL UN_CUR LK A,1000_0000b AND L MOV L,A ;do CR PUSH HL ;save new cursor ADD HL,HL LD A,PIABD ADD A,24 ;A = addr(25th line) SUB H ;A = lines_to_move + 1 AND 0001_1111b ;mod 32 MOV B,A LK A,VDELL CMP C MOV A,B ;recall #lines to move JRZ :delt ;if deleting a line space 3,17 :insrt: ;Insert a line ADD H ;A = addr(25th line) MOV D,A LK E,0 _line SUB H ;A = l_line - curr_line AND 0001_1111b ;modulo 32 JRZ :vmov ;if cursor is on 24th line of screen :end: POP HL ;get new cursor RET :vmov: LD A,LLIMIT SRL L ;unshift L register SUB L ;A = LLIMIT - col(cursor) JRC :end ;if cursor is outside logical line ;cursor is on last line of screen, inside of logical line. ;must move screen to follow cursor down through video memory. POP HL PUSH HL LK A,80h AND L MOV L,A ;HL = beginning of line CALL CLRLN ;erase to EOL LD A,PIABD MOV B,A AND not 31 ;A = line zero MOV C,A ;C = housekeeping bits 5..7 LK A,31 INC B ;increment line# AND B ;A = line# OR C ;A = new line# OR housekeeping_bits MOV C,A ;C = new value for OPBD CALL OPBD ;move video screen down 1 line in memory POP HL RET space 4,12 VLDDR: ;Video Block Move ; Entry BC, DE, HL set ; Exit LDDR on main & 9th bit memory ; Uses BC, DE, HL PUSH BC ! PUSH DE ! PUSH HL LDDR ;main memory POP HL ! POP DE ! POP BC DI ENADIM LDDR ;9thY A = CHR FROM RDKEY ; EXIT A = SHIFTED VALUE FROM SHIFT AND ALPHA LOCK KEYS PROC CMP ' ' + 1 RC ;IF CNTL-CHR (<=SPACE), UNSHIFTABLE LK HL,CKEY BIT 4,[HL] ;SHIFT KEY BIT JRNZ :SHIFT ;IF SHIFT KEY PRESSED BIT 3,[HL] ;ALPHA LOCK KEY BIT JRNZ :ALPHA ;IF ALPHA KEY PRESSED RET ;IF NO SHIFTING NECESSARY :SHIFT: CMP 'A' JRNC :ALPHA ;IF 'A'..'Z' CMP '[' JRC :TBLSF ;IF CHR < '[', USE SHIFT TABLE ;MUST BE '[' OR '\' JRNZ :ALPHX ;IF '\', SHIFT AS ALPHA LK A,']' RET ;...ELSE '[' SHIFTED IS ']' :TBLSF: MOV E,A LK D,0 ;DE = CHR LK HL, :STBL - '''' ;TABLE FWA - APOSTROPHE ADD HL,DE ;HL => SHIFTED CHARACTER LD A,[HL] ;A = SHIFTED CHR RET :ALPHA: CMP 'A' RC ;IF <'A', IGNORED BY ALPHA LOCK :ALPHX: XOR 20H ;UPPER/LOWER CASE BIT RET ;SHIFTED "COMMA" BECOMES "LESS THAN", ;SHIFTED "HYPHEN" BECOMES "UNDERBAR", (ETC.) ; ''', ...THESE 4 ARE UNUSED :STBL: DB '"', '{', '}', '|', '~' ; ',', '-', '.', '/', '0', '1', '2', '3', '4', '5' D RR D ! RR E ;shift right DE DEC DE ;DE = addr(lst_chr_on_lst_line) MOV A,B ;A = #lines to move LK HL,-VLL ADD HL,DE ;HL = addr(line above DE) ;DE := DE or F000h; HL := HL or F000h JR :istrt :icont: CALL VLDDR ;move 1 line down :istrt: CALL :vmod JRNZ :icont ;if must move more lines INC HL ;HL => 1st chr of new line ; JR :exit space 3,3 :exit: CALL CLRLN POP HL ;recover cursor JMP VOUT90 ;Main Exit space 3,11 :delt: POP DE ;recover new cursor PUSH DE LK HL,VLL ADD HL,DE ;HL = line_below_cursor JR :dstrt :dcont: CALL VLDIR ;move 1 line up :dstrt: CALL :vmod JRNZ :dcont EX HL,DE ;get addr of line to clear JR :exit space 3,13 ;HL := HL or F000h; DE := DE or F000h; ;simple mod-4096 arithmetic to keep pointers INSIDE video memory :vmod: PUSH AF ;save A = #lines to move LK A,0F0h OR H MOV H,A ;set upper nybl of H LK A,0F0h OR D MOV D,A ;modulo 4096 LK BC,VLL POP AF DEC A ;decrement line_count RET space 4,30 CLRLN: ;Clear to  bit memory DISDIM EI RET space 4,12 VLDIR: ;Video Block Move ; Entry BC, DE, HL set ; Exit LDIR on main & 9th bit memory ; Uses BC, DE, HL PUSH BC ! PUSH DE ! PUSH HL LDIR ;main memory POP HL ! POP DE ! POP BC DI ENADIM LDIR ;9th bit memory DISDIM EI RET space 4,10 UN_CUR: ;Undo/Invert Cursor ; Entry HL = cursor_addr ; Exit cursor inverted ; Uses A, CY. LD A,[hl] ;get the chr RAL ;cursor_bit => CY CMC ;invert it RAR STO A,[hl] ;... RET ; endx BMKEY.asm ***************** TITLE 'BMSCAN - KEYBOARD SCANNING & DECODE' GKEY: ;KEYBOARD INTERRUPT PROCESSOR ; ENTRY NONE ; EXIT KEYBOARD PROCESSING DONE, RESULT IN LKEY. ; SYSTEM CLOCK UPDATED BY UPTIM. PROC DI STO SP,IESTK ;SAVE INTERRUPTED PROCESS STK LK SP,ISTK ;SET TO RAM INT STK PUSHAL CALL UPTIM ;UPDATE SYSTEM CLOCK LD A,KEYLCK OR A JRZ GKEYX ;IF LOCKED KEYBOARD :SCAN: CALL RDKEY ;SCAN KEYBOARD CMP -2 JRZ GKEYAB ;IF NO KEY BEING PRESSED ;DEBOUNCE THE KEB '<', '_', '>', '?', ')', '!', '@', '#', '$', '%' ; '6', '7', '8', '9', (:), ';', (<), '=', (>) DB '^', '&', '*', '(', ' ', ':', ' ', '+', ' ' PAGE CNTRL: ;CONTROL KEY PROCESSING ; ENTRY A = CHR, CNTL KEY PRESSED SIMULTANEOUSLY ; EXIT A = ^CHR PROC CMP ' ' + 1 RC ;IF SPACE, TAB, ESC, RET, ETC. CMP '@' JRC :CHEAT ;IF <'@', CK FOR CHEATED CHR CMP 'Z'+1 JRNC GKEYAB ;IF GREATER THAN 'Z', NO CNTL-CHR AND ' ' - 1 ;KILL CNTL & LOWERCASE BITS RET :CHEAT: MOV B,A ;SAVE CHR AND ',' CMP ',' JRNZ GKEYAB ;IF NOT A LEGAL CHEATED CHR MOV A,B ;RESTORE CHR LK HL,:TBL1-',' CMP '/'+1 ;CK FOR 1ST GROUP JRC :LOOK ;IF IN :TBL1 LK HL,:TBL2-'<' ;...ELSE IN :TBL2 :LOOK: ADD L ;DO INDEXED LOAD FROM BASE IN HL MOV L,A JRNC :GET INC H ;IF CARRY, PROPAGATE INTO H :GET: LD A,[HL] RET SPACE 3 ; , - . / :TBL1: DB '{' , '_'-40H, '}' , '~' ; < = > ? :TBL2: DB ('{'), '`' , ('}'), 7FH SLIDE: ;PROCESS ^1, CMA ;COMPLEMENT THE 1S STO A,CKEY ;SAVE FOR SHIFT & CTRL PROCS AND 1110_0011B ;CLEAR SHIFT, CNTRL, & ALPHA BITS LK BC,0700H ;LOOP 7 TIMES, C := 0 JR :MIDLE ;JUMP INTO MIDDLE OF :LOOP1 :LOOP1: SLA L ;SHIFT RANK-SELECT BIT LEFT MOV A,L ;ADDR BYTE TO A MOV R,A LD A,[HL] ;READ RANK XOR 0FFH ;INVERT 1S, SET FLAGS :MIDLE: JRZ :2 ;IF NO KEY PRESSED IN THIS RANK DEC C ;RECORD THAT A KEY WAS PRESSED MOV E,B ;RECORD 7-RANK# OF KEY PRESSED MOV D,A ;SAVE THE DATA READ :2: DJNZ :LOOP1 ;IF NOT FINISHED READING ALL RANKS INC C ;CK FOR C = -1 JRZ :FBIT ;IF FOUND EXACTLY ONE KEY PRESS ;HERE IF FOUND 1) NO KEYS PRESSED ; 2) MANY (MORE THAN 1) KEYS PRESSED LK A,-2 ;RETURN NO KEYS PRESSED RET ;HERE TO FIND THE KEY PRESSED IN A PARTICULAR RANK: ;LOAD UP THE APPROPRIATE TABLE ENTRY & RETURN. ; ENTRY D = DATA READ FROM KEYBOARD ; E = 7-RANK# OF ABOVE DATA :FBIT: LK A,7 ;#RANKS SUB E ;A = TABLE ROW TO USE )0..7) RAL ! RAL ! RAL ;A := A * 8 M TITLE 'Disk I/O routines.' ; Disk interface definitions and functions. ; 1792 functions. DML = 4 ;= 15 ms delay on function LTRKB = 3125 ;length of a track ; Note: Shugart says LTRKB = 3125... NRTRYS = 4 ;Number of retries MSECB = 10h ;Multi-sector r/w bit ; Function codes D.RES = 00h+0Ch ;restore D.SEK = 10h+08h ;seek D.STP = 20h ;step D.STPI = 40h ;Step IN D.STPO = 60h ;Step out D.RDS = 80h ;Read sector D.WRTS = 0A0h+DML ;Write sector D.RDA = 0C0h+DML ;read address D.RDT = 0E0h+DML ;read track D.WRTT = 0F0h+DML ;write track D.FINT = 0D0h ;Force interrupt ; Disk status and command registers D.CMDR = H.FDC ;Disk command reg (write) D.STSR = H.FDC ;Status reg (read) D.TRKR = D.CMDR+1 ;track reg D.SECR = D.CMDR+2 ;Sector reg D.DATR = D.CMDR+3 ;Data reg (r/w) ; Status definitions BS.BSY = 0 ;Busy DS.BSY = 1 shl BS.BSY BS.DRQ = 1 DS.INX = 1 shl BS.DRQ ;Index mark detected DS.DRQ = DS.INX ;DR is full on read, empty on write BS.TK0 = 2 DS.TK0 = 1 shl  ^2, ^3, ^(LARROW), ^(RARROW) ; ENTRY A = CHR, CNTL KEY PRESSED ; EXIT 1) RET IF CHR NOT A SPECIAL SLIDING CHR ; 2) TO GKEYX AFTER ACTING ON SLIDING CHR PROC PUSH AF LD A,PIABD ;B=Y MOV B,A POP AF LK C,+2 CMP MCLEFT ;LEFT ARROW JRZ :SLIDH LK C,-2 CMP MCRIGH ;RIGHT ARROW JRZ :SLIDH PUSH AF LD A,PIAAD ;C=X MOV C,A POP AF LK B,+1 CMP MCUP ;UP ARROW JRZ :SLIDV LK B,-1 CMP MCDOWN ;DOWN ARROW JRZ :SLIDV ;1,2,3,4,5,6 CMP '1' RC ;IF NOT A SLIDING CHR PUSH AF ;SAVE VALUE LD A,PIABD ;OLD Y VALUE AND 11100000B ;SET Y TO ZERO MOV B,A ;VALUE TO B POP AF ;RESTORE VALUE LK C, VFLO + 2*00 ;SET SCREEN TO 0TH COLUMN JRZ :SET CMP '7' RNC ;IF >3, NOT A SLIDING CHR LK C, VFLO + 2*52 ;SET 52ND COL CMP '2' JRZ :SET LK C, VFLO + 2*104 ;SET 104TH COL CMP '3' JRZ :SET PUSH AF ;SAVE IT MOV A,B OR 00001000B ;Y VALUE OF 8 MOV B,A POP AF LK C, VFLO + 2*00 ;SET SCREEN TO 0TH COLUMN CMP '4' JRZ :SET LK C,OV C,A LK B,0 ;BC = OFFSET INTO TABLE LK HL,T5KEY ;HL = FWA(TABLE) ADD HL,BC ;HL => RANK(KEY) PAGE MOV A,D ;RESTORE DATA FROM KEYBOARD LK BC, 0800H ;B := 8, C := 0 :LOOP2: RRC ;SHIFT CORRESPONDING BIT INTO CY JRNC :3 ;IF DIDN'T FIND BIT THIS TIME THRU DEC C ;...ELSE RECORD THAT A KEY WAS PRESSED ; MOV E,B ;DON'T NEED TO SAVE LOOP-INDEX LD D,[HL] ;GET CHR FROM TABLE :3: INC HL ;...ELSE TRY NEXT CHR & BIT DJNZ :LOOP2 INC C JZ :EXIT LDK A,-2 RET :EXIT: MOV A,D ;RETURN CHR IN A RET SPACE 4,10 T5KEY: T6KEY: DB ESC, TAB, ERC, ERC, ERC, CR, '''', '[' DB '1', '2', '3', '4', '5', '6', '7', '8' DB 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I' DB 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K' DB 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',' DB MCUP, BKS, '0', ' ', '.', 'P', 'O', '9' DB MCRIGH, LF, '-', '/', ';', '\', 'L', '=' ; ENDX BMSCAN.ASM BS.TK0 DS.LSD = DS.TK0 ;lost data DS.CRC = 08h ;CRC error in ID field BS.SEK = 4 DS.SEK = 1 shl BS.SEK ;Seek error DS.RNF = DS.SEK ;Record NOT found DS.HDL = 20h ;Head loaded DS.WTF = DS.HDL ;Write fault DS.WTP = 40h ;Write protected DS.NRY = 80h ;Drive NOT ready ; Disk timing counts D.DEL = 20 ;Delay after function page SDMA: ;Set DMA SETDMA: ; Entry BC = DMA address STO BC,DMADR RET space 4,10 SETTRK: ;Set track ; Entry BC = track STO BC,SAVTRK RET space 4,10 SETSEC: ;Set Sector ; Entry C= sector number (1 to MSEC) MOV A,C STO A,SAVSEC RET space 4,10 HOME: ;Home selected disk drive LDK BC,0 JMP SETTRK ;reset track to 0 PAGE SDRV: ;Select Drive ; Entry SDISK= drive ; Exit A= 0, if drive is ready ; Calls OPBD, DELAY ; Uses A,B proc LD A,SDISK SDRV1: LK HL,DSKSWP ;disk drive swap cell XOR [hl] ;swap A for B if DSKSWP=1 AND 1 ;Can only be 0 or 1 CMP 1 JRNZ :2 ;if not drive 1 LDK A,40h :2: ADI 40h MOV C,A LD A,PIABD M VFLO + 2*52 ;SET 52ND COL CMP '5' JRZ :SET LK C, VFLO + 2*104 ;SET 104TH COL JR :SET :SLIDV: LD A,PIABD ;ADD TO VIDEO BITS AND 00011111B ADD A,B ;ADD NEW TO OLD AND 00011111B MOV B,A LD A,PIABD ;LAST VALUE AND 11100000B ;CLEAR VIDIO BITS OR B ;ADD NEW VIDIO OFFSET MOV B,A JMP :SET :SLIDH: LD A,PIAAD ;OLD SCREEN OFFSET VALUE ADD A,C MOV C,A :SET: PUSH BC ;SAVE Y CALL OPAD ;MOVE THE SCREEN POP BC MOV C,B CALL OPBD ;SET Y LK A,1 STO A,HKCNT ;SHORT-CIRCUIT DEBOUNCE/AUTO-REPEAT ;DELAY LOGIC POP DE ;CLEAR STACK JMP GKEYX ;IGNORE RET-ADDR ON STK: ;STK WILL BE RESET ON NEXT IRUPT. PAGE RDKEY: ;SCAN KEYBOARD ; ENTRY NONE ; EXIT A = CHR (IF AVAILABLE) ; -2 (IF NO KEY PRESSED) PROC LD A, H.KEY + 0FFH ;READ ALL KEYBOARD PORTS XOR 0FFH ;INVERT ALL BITS, SET FLAGS LK A,-2 RZ ;IF NO KEY IS PRESSED LDK HL, H.KEY + 001H ;CONTROL KEY RANK MOV A,L ;ADDR BYTE TO A MOV R,A LD A,[HL] ;READ CONTROL RANK OV B,A AND 1100_0000b ;get drive bits only CMP C JZ RDSKD ;if drive already selected ; Check to see if this drive is the same as the last ; one selected. ; IF true, go to 3 ; else ; Save current trk register in LDSEL and ; set trk reg to last track used for newly selected ; drive ; end LD A,LDSEL ;last selected disk CMP C JRZ :3 ;if same drive MOV A,C STO A,LDSEL ;set to new drive PUSH BC LDK HL,LDTRK LD C,[hl] ;get last accessed track for new drive LD A,D.TRKR ;get current track STO A,[hl] ;save in table MOV A,C STO A,D.TRKR ;set trk register to last selected POP BC ; Set drive select perserving vio offset values :3: CALL RDSKD ;reset Controller LDK B,5 ;number of tries :5: LDK A,250 CALL DELAY LK A,250 ;2nd delay CALL DELAY LD A,D.STSR AND DS.INX RZ ;if index DJNZ :5 ;keep trying OR 80h or DS.INX ;indicate NOT ready RET space 4,10 DDRV: ;Deselect drive ; Entry SDISK = current disk drive LD A,PIABD AND 1_1111b MOV  for FDC quiescence LD A,SAVSEC STO A,D.SECR ;set sector register XRA A ;indicate good RET space 4,10 DRDA: ;Read Address info. ; Entry SDISK= drive ; Exit D.STSB = data bytes ; MUST NOT destroy DE pair proc CALL SDRV ;select drive DRDAS: LDK A,D.RDA CALL FDSK ;function disk ; Get status bytes LDK HL,DSTSB LDK B,6 DI PUSH DE ;save DE :2: LDK DE,4000 ;time out :3: LD A,D.STSR BIT BS.BSY,A JRZ RWEX ;if possible error BIT BS.DRQ,A JRNZ :4 ;if data ready DEC DE MOV A,D OR E JRNZ :3 ;if NOT time out LK C,SEKTMO ;seek time out JR RWEX ;error exit :4: LD A,D.DATR STO A,[hl] ;save byte INC HL DJNZ :2 ;if not done POP DE XRA A ;indicate good EI ! RET space 4,10 DREAD: DRSECS: ;Read disk sectors. ; Entry SDISK= drive ; B = number of sectors to read ; Number from 1 to MSEC ; DMADR= FWA for data. ; Exit DSTSB= A= 0, if no error ; HL = next DMA ; Uses All registers proc MOV D,B ;save sectors CALL SEEK ;seek to trry A= function code ; Exit A= 0, if chip accepted function ; else, A=-1, indicating time-out, See WBUSY ; Uses A, B, C proc MOV B,A ;save function code LD A,PIABD AND 1100_0000b JRNZ :1 ;if drive active PUSH BC CALL SDRV ;reselect drive POP BC :1: CALL WBUSY ;Wait for busy to clear RM ;if will NOT clear busy ; Controller NOT busy, issue command MOV A,B STO A,D.CMDR ;function drive ; Wait for busy to be set LDK C,0 :2: LD A,D.STSR RAR ;DS.BSY JRC :3 ;if chip went busy DEC C JRNZ :2 ;if not time-out JR WBUSYX ;exit, error ; Set DACTVE indicating activity on drive :3: XRA A STO A,DACTVE RET space 4,10 WBUSY: ;Wait for Busy to clear ; Exit A= -1, if time out occurred, ; else ; A= last status and is positive. ; Uses A, C proc PUSH BC LDK BC,0 :1: LD A,D.STSR RAR ;DS.BSY JRNC :1A ;if NOT busy, proceed DEC BC MOV A,B OR C JRNZ :1 ;if not time-out WBUSYX: LDK A,-1 ;indicate error, drive NOT ready POP BC OR A ;set fC,A JMP OPBD ;deselect last drive page PSEKC: ;Perform seek type command ; Entry A= command to perform without r1, and r0. ; PSEKC will or in the low two bits as defined ; by SEKDEL. ; Exit A= last value of D.STSr LDK HL,SEKDEL OR [hl] ;or in delay time for seek CALL FDSK ;function disk RNZ ;if Drive NOT ready JMP WBUSY space 4,10 SELDSK: ;Select disk in register C MOV A,C ;drive to home CALL SDRV1 ;C= drive JR HOMED1 HOMED: ;Home disk drive ; Entry SDISK= drive ; Exit A=0 if drive on home. proc CALL SDRV ;select drive HOMED1: LDK A,D.RES CALL PSEKC ;perform seek command CMP -1 JRZ SKEX1 ;if error BIT BS.SEK,A JRNZ SKEX1 ;if error BIT BS.TK0,A JRZ :4 ;if NOT home IF ODEBUG CALL LDSKS1 ;list status **** ENDIF XRA A ;clear A SKEX1: PUSH AF LDK A,-1 STO A,DACTVE ;start counter CALL STAT17 ;save disk controller regs POP AF RET ; Here if drive NOT homed, possible NOT ready :4: AND 80h JR SKEX1 space 4,10 SEEK: ;Seek toack, set sector JRNZ RWEX1 ;if seek error MOV B,D PUSH BC LDK A,D.RDS DEC D JRZ :3 ;if NOT multi-sectors OR MSECB ;add 'm' bit :3: CALL FDSK POP BC CMP -1 JRZ RWEX1 ;if drive NOT ready ; Now xfer bytes from controller to DMA. DI LD HL,DMADR :5: PUSH BC LDK B,low LSECB :6: LD A,D.STSR BIT BS.BSY,A JRZ RWEX ;if possible error BIT BS.DRQ,A JRZ :6 ;if no data LD A,D.DATR STO A,[hl] INC HL DJNZ :6 ;if not all data ; Now check if multi sector POP BC DJNZ :5 ;continue XRA A JR RWEX1 ; here on error RWEX: CALL STAT17 ;save disk controller regs POP DE ;restore stack OR 80h ;if busy cleared, indicate with 80h RWEX1: OR A ;set status PUSH AF LDK A,-1 STO A,DACTVE POP AF EI ! RET space 4,10 DWRT: ;Write to disk ; Entry SDISK= drive ; B= Number of sectors to xmit. ; DMADR= FWA of data ; Exit same as DREAD ; Uses All registers proc MOV D,B CALL SEEK JRNZ RWEX1 ;if seek error MOV B,D PUSH BC LDK A,D.WRTS DEC lags RET :1A: RAL ;restore A POP BC ;restore BC AND 7Fh ;make sure its positive RET space 4,8 RDSKD: ;Reset PIA and disk controller ; selecting drive specified by C ; Entry C= drive ; B= PIABD MOV A,B AND 0001_1111b ;get vio offset only OR C MOV C,A CALL OPBD ;function PIO-b ; JMP RDSKC RDSKC: ;reset disk controller ; Entry None ; Exit Busy cleared. ; A= 0. LDK A,D.FINT STO A,D.STSR ;clear controller XRA A ;clear A and flags RET ODER: ;Output disk error to console ; Entry DE= FWA of message ; SDISK = drive with error PUSH DE CALL OCRLF ;new line LD A,SDISK ADD A,'A' MOV C,A CALL CO ;output drive name CALL O2SP POP DE ;get message JMP ESTR DERR: ;Output disk system error ; Entry A= status from controller ; Exit error output PUSH DE PUSH HL PUSH BC PUSH AF LDK DE,DERMSG CALL ESTR ;output error POP AF ;get status value CALL PBBH ;output status CALL O2SP LD A,SAVTRK CALL PBBH ;output track LDK C,',' CAL track defined by SAVTRK ; Entry SAVTRK set to track ; SAVSEC set to sector number ; Exit A= 0, if no error, else status ; MUST NOT destroy DE, HL pair proc CALL SDRV ;select drive ; Here if drive already selected ; Check to see if SEEK is necessary by ; comparing SAVTRK to controller track ; register SEEKN: LD A,SAVTRK STO A,D.DATR ;set track wanted MOV C,A LD A,D.TRKR CMP C JRZ :8 ;if on track ; Disk seek required, function controller ; with SEEK command LDK A,5 SEEKA: STO A,RTRY ;update retry count LDK A,D.SEK CALL PSEKC ;perform seek command MOV C,A AND DS.CRC or DS.SEK JRNZ :10 ;if error ; Now read-address and verify on-track CALL DRDAS ;read address JRNZ :10 ;if error LDK HL,DSTSB LD A,SAVTRK CMP [hl] JRZ :8 ;if ON track LD A,RTRY DEC A JRNZ SEEKA ;if not max retrys ; here if seek error :10: MOV A,C ORI 80h ;indicate movement error JR SKEX1 ; Now set the sector register to requested ; Sector :8: CALL WBUSY ;waitD JRZ :3 ;if NOT multi-sectors OR MSECB ;add 'm' bit :3: CALL FDSK POP BC ; Now xfer bytes to controller from DMA. DI LD HL,DMADR :5: PUSH BC LDK BC,LSECB ;length of std sector :6: CALL XDD ;xfer to disk JRNZ RWEX ;if error ; Now check if multi sector POP BC DJNZ :5 ;continue XRA A :8: JR RWEX1 page XDD: ;Xfer data from memory to disk ; Entry BC = length ; HL = FWA ; Exit HL = next address ; A=0 if no error, else status ; Uses A,BC,E, HL proc LD A,D.STSR BIT BS.BSY,A JRZ :5 ;if possible error BIT BS.DRQ,A JRZ XDD ;if no data LD A,[hl] STO A,D.DATR ;send to controller INC HL DEC BC MOV A,B OR C JRNZ XDD ;if not done XRA A ;indicate good xfer RET ; here if error :5: OR 80h ;indicate busy dropped RET page FDSK: ;Function disk routine ; All functions for DSK controller SHALL do so by using ; this routine. FDSK sets DACTVE to 0 indicating activity ; UPTIM uses this cell to turn off select if one sec has ; occurred. ; EntL COUT ;output comma LD A,D.TRKR CALL PBBH ;output controller track CALL O2SP LD A,SAVSEC CALL PBBH ;output sector LDK C,',' CALL COUT ;output comma LD A,D.SECR CALL PBBH ;output controller sector ; Update error counter LD HL,ERCNT INC HL STO HL,ERCNT ;update error count ; Clear controller CALL RDSKC ;reset disk controller ; Restore regs POP BC POP HL POP DE RET DERMSG: DBE cr,lf DCE 'Dsk ERR (sts trk sec)- ' space 4,10 STAT17: ;save 179x status ;called when disk error discovered: ;...saves 179x regs in high RAM. PUSH BC ! PUSH DE ! PUSH HL LK HL,D.STSR ;1st (lowest) 179x register LK DE,R179x ;register save area LK BC,4 ;move 4 bytes LDIR POP HL ! POP DE ! POP BC RET ; endx BMDSK r POP AF ;get status value CALL PBBH ;output status CALL O2SP LD A,SAVTRK CALL PBBH ;output track LDK C,',' CALU ;Ask user for input SUB 'A' JRZ :2 ;if 'A' DEC A JRNZ DIAG ;if not A or B INC A :2: STO A,SDISK ;set drive CALL DRDT ;test reading entire disk CALL DSEKT ;test random seeks JMP NEXTC ;next DIAMSG: DBE 'Z'-40h DBE ' ROM DIAGNOSTICs' DBE cr,lf,'Select Test:' DBE cr,lf,'A,B Boot Sys' DBE cr,lf,' D isk' DBE cr,lf,' K ey-vdt' DBE cr,lf,' M emory' DBE cr,lf,' R ead in test' DBE lf,cr,lf,' :' DCE ' ' DSKMSG: DBE cr,lf DCE 'Select (A,B): ' ; Disk diagnostic section. DRDT: ;Disk read test ; reads each sector on disk and reports any errors proc CALL DSKDI ;initialize disk LDK A,0 :2: STO A,SAVTRK LDK A,1 :3: STO A,SAVSEC LDK B,1 CALL DREAD ;read sector OR A CNZ DERR ;if error LD A,SAVSEC INC A CMP MSEC+1 JRNZ :3 ;if not full track LD A,SAVTRK INC A CMP MTRK JRNZ :2 ;if not full disk JR DERC ;display error count space 4,10 DSEKT: ;Disk seek test ; Routine performs random seeks followed by reads validating ; drive correctly. ; Fixed limits on memory test are 4000h to EF00h ; (TEM = EF00h) ; Entry none. ; Exit To error if any errors occurred during ; the testing ; Calls GETNM proc LDK DE,TSMSG CALL ESTR ;prompt user about mem test LDK DE,TEM LDK HL,4000h LDK C,0A5h ;initial test pattern ; Loop thu testing memory within limits ; HL= FWA ; DE= LWA :2: DI PUSH DE ;save LWA PUSH HL ;save FWA :3: STO C,[hl] ;data to memory INC HL ;update address CALL CDEHL JRNZ :3 ;if not all done ; Now perform test on memory reading ; what was just written and comparing ; with pattern C. POP HL ;restore FWA PUSH H :5: DI LD A,[hl] CMP C ;validate good write JRZ :7 ;If GOOD compare EI MOV B,A ;save BAD data PUSH BC CALL OCRLF ;output new line CALL ADRD ;Output Location in error CALL OSP ;Output space char POP BC PUSH BC MOV A,C CALL NMOUT ;Output good data LDK C,'=' CALL COUT MOV A,B CALL NMOUT ;Output BAD data POP BC ;restore pattern CALL BREAK :7:  is aligned and data path is valid. ; Entry None. ; Exit Back to diag main loop. proc CALL DSKDI ;initialize LDK A,100 :2: STO A,TEM CALL GNRN ;get next track STO A,SAVTRK LDK B,1 CALL DREAD ;read sector OR A CNZ DERR ;if disk error CALL GNRN ;get random CALL DELAY ;delay LD A,TEM DEC A JRNZ :2 ;if not done JR DERC ;display error count space 4,8 ;DDAM: ;Test data address marks ;; Entry None ;; Exit After 1000 tries and displays ; proc ; CALL DSKDI ;initialize disk ; LDK BC,1000 ;:2: PUSH BC ; CALL DRDA ;read address mark ; LDK C,' ' ; JRZ :4 ;if good xfer ; LD HL,ERCNT ; INC HL ; STO HL,ERCNT ;update error count ; LDK C,80h ;pure white space ;:4: CALL COUT ;output indicator ; POP BC ; DEC BC ; MOV A,B ; OR C ; JRNZ :2 ;if not done ; JR DERC ;display error count space 4,8 DERC: ;Display error counter. ; Entry ERCNT = current error count LDK DE,DERCMG CALL ESTR ;output error prompt LD HL,ERCNT JMP ADRD ;output number DERCMG: INC HL CALL CDEHL JRNZ :5 ;If not all done EI ;allow key entry MOV A,C RRC ;shift one position MOV C,A LDK HL,FWAVM+40 INC [hl] ;indicate running POP HL POP DE CALL BREAK JRZ :2 ;if not data MOV C,A ;next test pattern JMP :2 ;keep on looping TSMSG: DBE cr,lf,'Memory tes' DCE 't' page TSERI: ;Input test routine through serial port ; Format of input: ; 8 bit binary data, no parity ; 1st two bytes are DW (length) ; (length) following bytes are placed ; at 4000h in memory; ; Exit: JMP 4000h Proc LK DE,:lmsg ;length msg CALL ESTR CALL READER ;get chr MOV L,C ;low byte of length CALL READER MOV H,C CALL PBWH ;print out length of test routine EX HL,DE ;DE = length LK HL,4000h ;FWA of test program :loop: MOV A,D OR E JRZ :xit ;if finished with input, run prgm CALL READER STO A,[hl] ;get & deposit next byte STO A,FWAVM+40 ;indicate recieved data INC HL DEC DE JR :loop :xit: LK DE,:xmsg ;exit message CALL ESTR JMP TITLE 'Diagnostic section.' ; This section of code is entered either via the 1st prompt ; level by entering ^d, or by using the monitor command of ; 'T' if DEBUG is assembled on. ; ; This section of code contains all of the rom resident ; diagnostics to assist production and distributors. ; ; The diagnostic section uses a menu and contain test ; for major hardware pieces. These diagnostics are NOT ; considered to be all-encompassing...... ; Entry from monitor loop DIAG: proc IF ~INDMON NEXTC = DIAG ENDIF LK SP,ROMSTK LDK DE,DIAMSG CALL ASKU ;ask user for input LDK HL,DSKSWP ;disk swap cell LDK C,0 STO C,[HL] ;SET A=A,B=B CMP 'A' JZ CBOOT ;IF BOOT A DRIVE INC [HL] ;SWAP DRIVES A=B,B=A CMP 'B' JZ CBOOT ;IF BOOT B DRIVE DEC [HL] ;A=A, B=B CMP 'K' JZ KEYBT ;if Keyboard test CMP 'M' JZ TSTMEM ;if memory test CMP 'R' JZ TSERI ;if input test program CMP 'D' JRNZ DIAG ;if illegal DSKD: ;Here to run disk diagnostic LDK DE,DSKMSG CALL ASK DBE cr,lf DCE 'ERR cnt- ' page DSKDI: ;Disk diagnostic initialize ; Entry SDISK set to disk to test(0 or 1) proc LD A,SEC6 STO A,RNDV ;set random seed CALL DDRV ;deselect drive :2: LDK DE,0 STO DE,ERCNT ;clear error count MOV C,E CALL HOMED ;select drive 0, home. JRZ :3 ;if drive ready CALL RDSKC ;reset disk controller LDK DE,DNRMSG CALL ODER ;output disk error JR :2 :3: LDK BC,HSTBUF CALL SETDMA ;set to default dma RET page ASKU: ;Ask user for input, first displaying prompt ; Entry DE= FWA of prompt message ; Exit A= normalized input from user CALL ESTR ;prompt user CALL GETCH ;get next char CMP ESC JZ NEXTC ;if abort RET page KEYBT: ;Perform reading of keyboard and echoing to screen ; Keeps running till user types in ^Z. LDK DE,KEYTM CALL ESTR ;output prompt LDK HL,4000h JMP ACMDD ;enter A command KEYTM: DBE cr,lf DCE 'Enter keys (till ^Z) : ' page TSTMEM: ;performs a test of memory validating that the ; memory is working 4000h ;...to user program :lmsg: DBE cr,lf,'Start input: Len' ! DCE '=' :xmsg: DBE cr,lf,'Program begins' ! DCE ':' space 4,10 GNRN: ;Get next random number ; Exit A= new number to use (0 to MTRK-1) proc MOV A,R ;refresh register XOR [hl] AND 3Fh ;cannot exceed 28h=40d ADD A,17 CMP MTRK JC :4 ;if in range SUB MTRK :4: STO A,[hl] ;update RET space 4,10 IF ~INDMON ACMDD: ;Entry here from Diagnostic loop HL = 4000h proc :3: CALL CI ;read char CPI EOFC JZ DIAG ;if request to quit STO A,[hl] ;into memory INC HL ;update pointer CPI CR JRNZ :5 ;If not carriage return STO LF,[hl] INC HL :5: MOV C,A CALL COUT ;back to user JR :3 ;next character space 4,10 ADRD: PBWH: ;Print Binary Word in Hex. ; PBWH outputs to the console the address ; contained in the H,L registers. ; Entry HL= address to be displayed ; Exit NONE ; Calls PBBH ; DESTROYS: AF, C. MOV A,H ;display First half of address CALL PBBH MOV A,L ;display second half of address:wait: LD A,H.SSTS AND SI.TRDY ;wait for CTS go-ahead JRZ :wait ;if CTS high, wait again MOV A,C STO A,H.SXMT ;send chr ; NOP ! NOP ! NOP ;...wait... ; LD A,ACIAD ;get last command ; STO A,H.SCTRL ;set RTS high (no request) RET ; Endx BMSIO.asm atus AND SI.RRDY ; LD A,H.SREC ;clear ~DCD JRZ READER ;if not ready LD A,H.SREC ;get data MOV C,A ;A=C ; LK A,SI.RERR ;error check ; AND B ;...with status ; MOV A,C ;recover data ; RZ ;if OK ; STC ;...else error RET space 4,10 SLST: ;Get list device status ; Exit A= 0, if NOT ready LD A,H.SSTS AND SI.TRDY ;ck for Xmit buf empty RET ;set status space 4,10 LIST: ;Output one byte to list port PUNCH: ;Output one byte to punch port ; Entry C= character to output ; Exit C=C. ; LD A,ACIAD ;get last command byte ; CBIT 6,A ;...invert RTS status ; STO A,H.SCTRL ;make request (~RTS := low) 6so1>I2:,:3{o1>2i2ͅ!"!"mW͂e ~#X6ͬ !q4" >2!l"^>G2k2^2]22`/2c2\2Y>2l>2Ͱ>2bOUW >2>>2!np+q*m2_!ppJ´ áìÆy y g Ô Ê Ï Å Ú s 36bW " 5 A Á ä B  gG gG LOSBORNE SYSTEM ONE.M gG g G g ) REV B 227 ( G gG INSERT DISK IN DRIVE LAM AND PRESS RETURNB>2y:>2:2 Sͅ !">2 ͚ F"*#":G͚ -"!4!Pp>2U>2n>`o @@]@@]:Y:^͡(O2^yOa{ !kﯶ( 5 :bO+~(5 +56;+~<'w`6+~<'w`6+~<'w%6y :/2y͆:(y =SgVGf)Z(jl^mnQ>W&ERT#"  j  aswS*Z:`G #yx(!!_~#foyx2`` kG2`!1y 8 6!c #(##  8 8 86 JR PBBH space 4,10 BREAK: ;Check for break key. ; Entry NONE ; Exit To DIAG if char entered is ESC, else ; return to caller A= char or 0 if none ; Calls SKEY, CI ; DESTROYS: A,F/F'S CALL SKEY ;get console status RZ ;If not ready CALL CI ;get char CMP ESC JZ DIAG ;if ESC, abort RET space 4,10 GETCH: ;returns the next character in the input stream ; TO the calling program. ; Entry NONE ; Exit C - next character normalized to UPPER case. ; Calls CI,CO,NORM ; DESTROYS: A,C,F/F'S CALL CI ;Get character from terminal CALL CO ;output it JMP NORM ENDIF ; Endx BMDIA.asm INC HL :5: MOV C,A CALL COUT ;back to user JR :3 ;next character space 4,10 ADRD: PBWH: ;Print Binary Word in Hex. ; PBWH outputs to the console the address ; contained in the H,L registers. ; Entry HL= address to be displayed ; Exit NONE ; Calls PBBH ; DESTROYS: AF, C. MOV A,H ;display First half of address CALL PBBH MOV A,L ;display second half of address page FORMT: ;Format one track ; in IBM 3740 format consisting of 40 tracks, with each ; track containing 10 sectors. ; Drive already selected and ready ; Entry BC = FWA of buffer ; BUF+0= DW length ; BUF+2= beginning of data ; SAVTRK = next track to format ; SAVSEC = 1 ; Exit track formatted proc PUSH BC ;save address LD A,SAVTRK LDK HL,D.TRKR ;PRESENT TRACK OR [HL] JZ :2 ;if already on track LDK A,D.STPI CALL PSEKC ;perform step IN :2: LDK A,D.WRTT ;request write track DI CALL FDSK ;request write POP HL ;FWA of buffer EI RNZ ;if error DI ; Load BC with length and set ; HL = FWA of data to xmit to disk LD C,[hl] ! INC HL LD B,[hl] ! INC HL ;BC = length of xfer ; Now write out data :4: CALL XDD ;xfer to disk JRNZ :11 ;if error ; Pad rest of track with FFh :10: LD A,D.STSR OR A JRZ :11 ;if all done AND DS.DRQ JRZ :10 LDK A,0FFh STO A,D.DATR ;pad JR :10 ;continue ; Exit A=0, if no error :11: EI RET ; endx BMXFMTp O:bO'O˨$f>h )p g:bg>@,o>2`f:b.g/ff>(+r :lO ):b  >gQ:b O>2kI!U:bO!'f>of~w]˻:l= >o#~?w"Zyɯ>2Y>2`>8>M˹(OT]#U6 +6f>o_T+D~>@>>>2`>>>:aOf>o):bG>Rx( Wx!D #!U >g>W=6 6:l=]˻0>O]TPf 0 ):b(:l=8>o:bGO>O~?wso1:Y(C(?!\wG!] ~ʰ5 (6:`2]6-x!_V(D2^>2\!!_f ^ A0[8 >]_!~A "{}|~<_>?)!@#$%^&*( : + !@8[0G,, x!08!o0$~{}~{`}:bG(_ (Y:aO (: (41:bG(=7R2(43(.xG4("R5(:bG:bGô:aOH>2]:">!"}O~/2_%}O~( XW (>>O! TITLE 'SIO - Serial I/O Processors.' SIRST: ;Master reset SIO ; Entry C= SI.S16 or SI.S64 for 1200/300 baud LDK A,SI.MRST STO A,H.SCTRL ;master reset NOP ! NOP ! NOP MOV A,C STO A,ACIAD ;last-command cell STO A,H.SCTRL ;select SIO RET space 4,10 READER: ;Input one byte from reader port ; Entry None ; Exit A=C= character read LD A,H.SSTS ; MOV B,A ;save status AND SI.RRDY ; LD A,H.SREC ;clear ~DCD JRZ READER ;if not ready LD A,H.SREC ;get data MOV C,A ;A=C ; LK A,SI.RERR ;error check ; AND B ;...with status ; MOV A,C ;recover data ; RZ ;if OK ; STC ;...else error RET space 4,10 SLST: ;Get list device status ; Exit A= 0, if NOT ready LD A,H.SSTS AND SI.TRDY ;ck for Xmit buf empty RET ;set status space 4,10 LIST: ;Output one byte to list port PUNCH: ;Output one byte to punch port ; Entry C= character to output ; Exit C=C. ; LD A,ACIAD ;get last command byte ; CBIT 6,A ;...invert RTS status ; STO A,H.SCTRL ;make request (~RTS := low) .asm e already selected and ready ; Entry BC = FWA of buffer ; BUF+0= DW length ; BUF+2= beginning of data ; SAVTRK = next track to format ; SAVSEC = 1 ; Exit track formatted proc PUSH BC ;save address LD A,SAVTRK LDK HL,D.TRKR ;PRESENT TRACK OR [HL] JZ :2 ;if already on track LDK A,D.STPI CALL PSEKC ;perform step IN :2: LDK A,D.WRTT ;request write track DI CALL FDSK ;request write POP HL ;FWA of buffer EI RNZ ;if error DI ; Load BC with length and set ; HL = FWA of data to xmit to disk LD C,[hl] ! INC HL LD B,[hl] ! INC HL ;BC = length of xfer ; Now write out data :4: CALL XDD ;xfer to disk JRNZ :11 ;if error ; Pad rest of track with FFh :10: LD A,D.STSR OR A JRZ :11 ;if all done AND DS.DRQ JRZ :10 LDK A,0FFh STO A,D.DATR ;pad JR :10 ;continue ; Exit A=0, if no error :11: EI RET ; endx BMXFMT z0 V# >z  '[12345678QWERTYUIASDFGHJKZXCVBNM, 0 .PO9 -/;\L=z{7y0 O>=@Id b{q{BKT]O =GOɷO0>2,>2,>2,>2,>2,y2a2,>2,y2b2,A(+!)6:>2)6>2)!)60>?2)64>2)>= >62)Q( >0I(>82):)!)˖:)>2)2)!)A "6:)˗2)62)6>n(= >6:)˗2)6?2)6!)F(%6:)˗2)6?2)2)6 !)˦@(n y2)> ~(= >v >>v(= >ˮ˞2)!)F 6:)˗2)62)>2)6U6Ev( ˾> n = !:)W^(˶>n( = |!)>2)6~6!)6>W2*y22*:*(:*O:*:*(y2*CCy2Ê :! >@@O:bG` :m(y2m!nN:!wy2!` >`>`:!:bO! G y͝ ͚ > ( g W( >2j ͚ :2!O:!((>2> O l ! :( := yG :2!͚ > ! :!G(NO z A:!w#ѯP& 6B>( (%*:!G(O(:!w# >2jP& B>( *  ;VER = REV B ;DATE = 227 ;DEB ; Assembly Constants 0000 = 0000 ORG 0 ;FWA of memory = FFFF @XFRMT = TRUE ;FALSE IF FORMAT IS IN ROM = 0000 INACMD = FALSE = FFFF INBCMD = TRUE = 0000 INDCMD = FALSE = 0000 INFCMD = FALSE = 0000 INGCMD = FALSE = 0000 INHCMD = FALSE = 0000 INMCMD = FALSE = 0000 INRCMD = FALSE = 0000 INSCMD = FALSE = 0000 INTCMD = FALSE = 0000 INXCMD = FALSE = 0000 INZCMD = FALSE = FFFF INDIA = TRUE ;INTERNAL DIAGNOSTICS = 0000 INDMON = FALSE = 0000 INUTIL = FALSE NULINT MACRO NUMB ORG %1*8 DI JMP Ix Assembler ver 3.5E 1=/10/91 1<:0; Page 4 Monitor Main Loop. E:OCCROM1B.ASM 0000 DISDIM ;disable DIM 0002 C33600 JMP BMON ;reset/restart 0005 USER: ;Exit to user program from 'G' command 0005 EI ! RET ;Exit from G command = 0000 .mac IF RSIZE = 48 .mac ELSE = 0000 .pbkp IF def PBKP .pbkp ENDIF .mac ENDIF 0007 ILINT: ;Here on unknown interrupt = FFFF .mac IF RSIZE = 64 0007 DI .mac ENDIF 0008 DISDIM 000A ED736FEF $ STO SP,IESTK ;save interrupted proc stack 000E 3199EF LDK SP,ISTK ;insure stack in RAM 0011 PUSHAL ;save all registers 0019 3E49 LDK A,'I' 001B 3206EF STO A,MPCHR ;set prompt to inter level 001E :!G(O(~2!# x G:b ͚ G x2!:!8 2j:!0 x >xO>2!ʹ:AO;á ͘͡;:͘,͆:!͘;:͘,͆:!͘*#"h @@P@@RZA!!1: 8!qA4B5KDMiRD  8A(= <2ͬ 4@@@@@tX@@@@@@Z@@@@@@@tA@PXRtA>2>2͚ ă :< :<( %>d22͚ ă `:= ͡*E@ZA:i2 SK ( h o ͅ ͡Y P͡!@.@@P@R@tA͡!@q#O ~(GʹEy͘=͆x͘L#O yO!(4L(Ow@͡g ig aE!@z( g w2(# ͡@@t@{@u_?(,(wͬ w# 6 #O͆|͘}Lͬ͡ ͬý:!!r>@ > N#F# :!( (>2!ͪͪƐ'@'O ͆ Æ Æ:^#V#*^#V>+)x-8_LINT NOP ! NOP ! NOP ! NOP ENDM PUSHAL MACRO PUSH AF PUSH BC PUSH DE SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 2 Osborne-One Monitor for Model 1 system. E:OCCROM0B.ASM PUSH HL PUSH IX PUSH IY ENDM POPALL MACRO POP IY POP IX POP HL POP DE POP BC POP AF ENDM SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 3 Osborne-One Monitor for Model 1 system. E:OCCROM0B.ASM LINK OCCROM1B.ASM ;ROM STANDARDS  EXITI: ;Exit interrupt code via exiting to RAM and ; then enable or disable ROM code depending on ; the value contained in ROMRAM cell. 001E 3A002C LD A,H.VIO ;clear interrupt 0021 3A08EF LD A,ROMRAM 0024 B7 OR A 0025 C23301 JNZ RORAME ;if return to RAM, CPM = 0000 .mac IF RSIZE = 48 .mac ELSE 0028 POPALL 0030 ED7B6FEF $ LD SP,IESTK ;get users stack back 0034 EI ! RET .mac ENDIF = FFFF .mac IF RSIZE = 64 0036 BMON: DI 0037 31C1EF LDK SP,ROMSTK 003A 3E00 LDK A,0 003C 3269EF STO A,SEC6 003F 3217EF STO A,SDISK ;set disk to drive 0 0042 CD8500 CALL HINT ;Initialize hardware 0045 2100ED LDK HL,(high MRAM)*100h 0048 22EAEF STO HL,SSAVE ;Initialize User stack in ram 004B 210000 LDK HL,0 004E 22 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 1 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM *ABS 0000 EFEF *CODE EFEF 0000 *DATA EFEF 0000 ;OCCROM0B.ASM * 4D2008-00 MASTER .ASM * 2D2008-00 ASSY .ASM * 1D2008-00 LISTING .PRN * 4D1008-00 MASTER .COM * 2D1008-00 ASSY .COM LIST -F ;4-25, Do not list opted out code ; Initial Monitor for Osborne-One System. ; +-------------------------------+ ; | | ; | Osborne-One Monitor | ; | | ; +-------------------------------+  ;LOP,ROMD LINK OCCROM2B.ASM ;CPM BOOT ;BOOT LINK OCCROM3B.ASM ;CONSOL ROUTINES ;KEY LINK OCCROM4B.ASM ;PIA ROUTINES ;PIO,IEEE LINK OCCROM5B.ASM ;SIA ROUTINES ;SIO LINK OCCROM6B.ASM ;DISK ROUTINES ;DSK LINK OCCROM7B.ASM ;DIAGNOSIC ROUTINES ;DIA LINK OCCROM8B.ASM ;FORMAT ROUTINE ;XFMT LINK OCCROM9B.ASM ;UTILITES ;UTIL2 LINK OCCRAMA.ASM ;RAM LOCATIONS ; Endx SORCIM 8086DEF STO HL,LDSEL ;clear select and last track 0051 115701 LDK DE,IBMSG 0054 CD8208 CALL OSTR ;Output initial message 0057 1811 ^006A$ JR BMON1 ;continue .mac ENDIF = 0000 IF * > NMIA ENDIF SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 5 Monitor Main Loop. E:OCCROM1B.ASM 0059 = 0066 ORG NMIA 0066 DI 0067 C33600 JMP BMON ;NMI SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 6 Monitor Main Loop. E:OCCROM1B.ASM ; Main start up for Monitor. = 0000 IF RSIZE = 48 ENDIF ; Get 1st user response. 006A CDAC02 BMON1: CALL CI ;Get next character 006D FE0D CMP CR 006F 21C7EF LK HL,clear last key cell 00A1 325DEF STO A,HKCNT ;clear debounce 00A4 3207EF STO A,ECHOP ;clear echo to list dev 00A7 3260EF STO A,ESCH ;clear ESC hold flag 00AA 2F CMA 00AB 3263EF STO A,IDAY ;set date invalid for SETUP.COM 00AE 325CEF STO A,TKEY ;clear holding key 00B1 3259EF STO A,KEYLCK ;indicate NOT locked ; LDK HL,FWAVM ; STO HL,CURS ;set cursor 00B4 3E80 LDK A,VLL 00B6 326CEF STO A,LLIMIT ;set max line limit ; Set keyboard debounce delay cell 00B9 3E01 LK A,KBDTM ;debounce constant 00BB 32C6EF STO A,KBDLY ;set debounce-delay cell ; Now function PIA to set starting address ; and continue to move display window over ; the first display line. ; Set cursor as 1-40 on 1st line. 00BE CDB008 CA;set sector 0124 C3850A JMP SETDMA ;set DMA 0127 C39A0B JMP DREAD ;Disk read 012A C3E00B JMP DWRT ;Disk write 012D C3730A JMP SLST ;List device status 0130 C9 RET ! NOP ! NOP ;Sector translate ; End of standard CP/m functions 0133 C333EA RORAME: JMP BIOS+BRRXT 0136 C336EA JMP BIOS+BROMJP 0139 C3620F JMP FORMT ;Format one track 013C C3570A JMP SIRST ;SIO reset ; JMP BIOS+BRDXY ; JMP BIOS+BWTXY 013F C3DF08 JMP IE.CO ;IEEE Control Out 0142 C32209 JMP IE.SI ; Status In 0145 C33509 JMP IE.GTS ; Go To Standby 0148 C34109 JMP IE.TC ; Take Control 014B C38109 JMP IE.OIM ; Output Interface Message 014E C3A409 JMP IE.ODM ; Output Device Message 0151 C3E609 JMP IE.IDM ; Input Device Message 0154 C3420A JMP IE.PP ; Parallel Poll DSKSWP ;disk swap cell 0072 0E00 LK C,0 ;boot from A: 0074 71 STO C,[hl] ;set to A=A, B=B 0075 CAFA01 JZ CBOOT ;if cold boot = FFFF IF INDIA 0078 34 INC [hl] ;swap drives: A=B, B=A 0079 FE22 CMP '"' 007B CAFA01 JZ CBOOT ;if cold boot off of B 007E FE04 CMP 'D'-40h 0080 CAF20C JZ DIAG ;if enter debugger 0083 18B1 ^0036$ JR BMON ELSE ENDIF ; Here on NMI and RESET ;BMNI: LDK SP,ROMSTK ;Stack must be in RAM (not 0,1 page) ; CALL HINT ;Initialize hardware ; JMP DMON ;enter loop = 0000 .mac IF RSIZE = 48 .mac ENDIF SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 7 Monitor Main Loop. E:OCCROM1B.ASM = 0000LL SPAO ;set up for output 00C1 0EEA LDK C,VFLO 00C3 CDC508 CALL OPAD ;set for -10 char positions ; Set beginning line to 0 00C6 3E00 LDK A,0 00C8 3262EF STO A,PIABD ;set data reg 00CB 4F MOV C,A 00CC CDD208 CALL OPBD ;set line ; Reset-Master clear the SIO (ACIA) 00CF 0E55 LK C,SI.S16 ;select 16x clock for 1200 baud 00D1 CD570A CALL SIRST ;reset ; Set default seek to as defined by systext 00D4 3E02 LDK A,SEEKTM ;defined from systext 00D6 3213EF STO A,SEKDEL ;set seek step rate SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 9 Monitor Main Loop. E:OCCROM1B.ASM ; Set default prompt char 00D9 3E3E LDK A,PMCHR 00DB 3206EF STO ASORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 11 Monitor Main Loop. E:OCCROM1B.ASM = 0000 .mac IF RSIZE = 48 .mac ENDIF ; Endx BMLOP SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 12 MROMD - DEBUG MONITOR ROM DATA AND CONSTANTS. E:OCCROM1B.ASM ; ROM STORAGE AND CONSTANTS 0157 IBMSG: 0157 1A0A0A0A0A DB 'Z'-40H,LF,LF,LF,LF 015C 1B67 DB ESC,VSGH 015E 11 DB 'Q'-40H 015F 7F1817 DB 07FH, 24, 'W'-40H 0162 05 DB 'E'-40H 0163 1B47 DB ESC,VEGH 0165 0D0A DB CR,LF 0167 1B67011B47 DB ESC,VSGH,1, ESC,VEGH 016C 2020 DB ' ' 016E 1B4C DB ESC,'L' 0170 4F53424F52 DB 'OSBORNE SYSTEM ONE.' 0183 1B4D DB ESC,'M' 0185 202020 DB  .mac IF INDMON .mac ENDIF SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 8 Monitor Main Loop. E:OCCROM1B.ASM 0085 HINT: ;Initialize all dependent hardware. ; Entry None. ; Exit All hardware initialized. ; Set flag indicating in ROM 0085 ENAROM 008C DISDIM ;disable DIM bit = 0000 .mac IF RSIZE = 48 .mac ELSE 008E 216C06 LDK HL,GKEY 0091 22F8EF STO HL,INTBL+(4*2) ;set keyboard interrupt 0094 ED5E $ IM2 0096 3EEF LDK A,high INTBL 0098 ED47 $ MOV I,A ;set interrupt page .mac ENDIF ; Initialize keyboard 009A AF XRA A 009B 326BEF STO A,BELCNT ;clear bell timer cell 009E 325EEF STO A,LKEY ;,MPCHR ;set up default 00DE EI ! RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 10 Monitor Main Loop. E:OCCROM1B.ASM = 0000 IF * > 100h ENDIF 00E0 = 0100 ORG 100h ; Jump vector for debugger and CP/M 0100 C3FA01 RVEC: JMP CBOOT ;cold boot 0103 C30902 JMP WBOOT ;warm boot 0106 C3A102 JMP SKEY ;keyboard status 0109 C3AC02 JMP CI ;keyboard input 010C C38603 JMP COUT ;console output 010F C3790A JMP LIST ;list output 0112 C3790A JMP PUNCH ;punch output 0115 C3670A JMP READER ;reader input ; Disk I/O 0118 C3940A JMP HOME 011B C3FC0A JMP SELDSK ;select disk 011E C38A0A JMP SETTRK ;set track 0121 C38F0A JMP SETSEC ' ' 0188 1B67041B47 DB ESC,VSGH,4, ESC,VEGH 018D 0D0A DB CR,LF 018F 1B67 DB ESC,VSGH 0191 01 DB 'A'-40H 0192 7F1820 DB 07FH,24,' ' 0195 04 DB 'D'-40H 0196 1B47 DB ESC,VEGH 0198 0D0A DB CR,LF 019A 1B67 DB ESC,VSGH 019C 01 DB 'A'-40H 019D 2020202020 DB ' ' 01A2 1B29 DB ESC,')' 01A4 2052455620 DB ' REV B 227 ' 01B2 1B28 DB ESC,'(' 01B4 2020202020 DB ' ' 01B9 04 DB 'D'-40H 01BA 1B47 DB ESC,VEGH 01BC 0D0A DB CR,LF 01BE 1B67 DB ESC,VSGH 01C0 1A DB 'Z'-40H 01C1 7F1818 DB 07FH, 24, 'X'-40H 01C4 03 DB 'C'-40H 01C5 1B47 DB ESC,VEGH 01C7 0D0A0A0A DB CR,LF,LF,LF 01CB 494E534552 DB 'INSERT DISK IN DRIVE ' 01E0 1B4C DB ESC,'L' 01E2 41  SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 14 B o o t C P / M f r o m d i s k. E:OCCROM2B.ASM ; ; The CBOOT entry point gets control from the cold start ; loader and is responsible for the basic system initial- ; ization. This includes outputting a sign-on message and ; initializing the following page zero locations: ; ; 0,1,2: Set to the warmstart jump vector. ; 3: Set to the initial IOBYTE value. ; 4: Default and logged on drive. ; 5,6,7: Set to a jump to BDOS. ; ; Before any data is read in, the maximum drive step rate ; must be determined: ; 1. set slowest seek ; 2. home drive A: ; 3. seek track #1 01FF 79 MOV A,C 0200 CD1102 CALL BCPM ;boot system 0203 3A17EF LD A,SDISK ;use requested drive 0206 C300EA JMP BIOS ;enter CPM ; LK A,3 ; STO A,SEKDEL ;set step rate =3 (slowest) ; CALL HOMED ;send A: home ; ; LK BC,12 ; CALL SETTRK ;track 12 ; LK C,0 ; CALL SETSEC ;sector 0 ; CALL SEEK ;do (slow) seek to trk 12, sec 0 ; ;:fastr: LK HL,SAVTRK ; LK A,-4 ;seek 4 tracks out ; ADD [hl] ; STO A,[hl] ; LK HL,SEKDEL ; DEC [hl] ;speed up step rate ; CALL SEEK ;seek 4 track outwards, faster ; JRNZ :err ;if stepping too fast ; LD A,SEKDEL  DB 'A' 01E3 1B4D DB ESC,'M' 01E5 20414E4420 DB ' AND PRESS RETURN' 01F6 AE DC '.' ; TABLE OF ALL VALID MONITOR COMMAND CHARACTERS COMAND MACRO CHR,ADR .INCMD IF IN_%1_CMD DB '%1' SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 13 MROMD - DEBUG MONITOR ROM DATA AND CONSTANTS. E:OCCROM1B.ASM IF ' %2' <> ' ' DW %2 ELSE DW %1_CMD ENDIF .INCMD ENDIF ENDM 01F7 CTAB: 01F7 COMAND A ;ASCII CORE ENTRY 01F7 COMAND B,CBOOT ;BOOT UP SYSTEM 01FA COMAND D ;DISPLAY MEMORY 01FA COMAND F ;FILL MEMORY 01FA COMAND G ;GO EXECUTE/BREAKPOINT 2 ; 4. speed up step rate ; 5. seek 4 tracks outward (12=>8,8=>4,4=>0) ; 6. if error, slow down step rate by 1, ; load in CP/M, boot, exit, etc. ; 7. else try faster step rate ; (if not fastest, GOTO #4 above) ; 8. if stepping fastest rate, boot CP/M. ; The exit address is to the CCP routine. ; ; ; The WBOOT entry point gets control when a warm start ; occurs, a ^C from the console, a jump to BDOS (function ; 0), or a jump to location zero. The WBOOT routine reads ; the CCP and BDOS from the appropriate disk sectors. ; WBOOT must also re-initialize locations 0,1,2 and 5,6,7. ; The WBOOT routines exits with the C register set to the  ; OR A ;stepping fastest possible? ; JRNZ :fastr ;try a faster seek ;; JR :end ;..else seeking fastest already ; ;:end: CALL BCPM1 ;read in cpm ; JMP BIOS ;cold start ; ;:err: LK HL,SEKDEL ; INC [hl] ;seek at previous (slower) speed ; LK A,0000_0011b ; AND [hl] ;limit seek to (slowest) 3 ; STO A,[hl] ; JR :end 0209 WBOOT: Proc 0209 3E02 LDK A,6-4 ;don't read CBIOS 020B 3200EF STO A,TEM ;save sectors 020E 3A0400 LD A,CDISK ;Current logged in drive ; JR BCPM ;Boot CP/M SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 16 B o o t C P / M f r o m d i s k.  01FA COMAND H ;HEX SUM & DIFFERENCE 01FA COMAND M ;MOVE DATA 01FA COMAND R ;READ INTEL-FORMAT HEX 01FA COMAND S ;SUBSTITUTE DATA INTO MEMORY 01FA COMAND X ;EXAMINE REGISTER(S) 01FA COMAND T,DIAG ;TESTS DIAGNOSTIC SECTION 01FA COMAND Z ;EXAMINE Z80 REGS = 0001 NCMDS EQU (*-CTAB)/3 ;NUMBER OF VALID COMMANDS ; TABLE OF ALL 8080 REGISTERS. ; EACH ENTRY IN THE RTAB CONSISTS OF: ; DB ASCII NAME ; DB ADDRESS ; DB FLAG, WHERE FLAG IS ; 0= 8 BIT REGISTER ; 1= 16 BIT ; 8X=8 BIT BUT DO NOT DISPLAY IN X COMMAND = 0003 RTABS EQU 3 ;LENGTH OF EACH REGISTER ENTRY ; ENDX BMROMD.ASM  ; appropriate drive selection value. The exit address ; is to the CCP routine. ; ; Disk layout Definition ; --Note: Tracks 0, 1, and 2 are reserved for CPM.-- ; Track 0----------- ; 1 thru 8 CCP 2k ; 9 thru 10 BDOS ; Track 1----------- ; 1 thru 10 BDOS ; Track 2----------- ; 1 thru 2 BDOS 3.5k ; 3 thru 10 CBIOS 2k ; Sectors 3,4,5,6 are currently used. SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 15 B o o t C P / M f r o m d i s k. E:OCCROM2B.ASM 01FA CBOOT: ;Entry C= drive to boot from ; Exit A= drive 01FA Proc 01FA 3E06 LDK A,6 ;read 5 sectors of trk 3 01FC 3200EF STO A,TEM  E:OCCROM2B.ASM 0211 BCPM: ;Boot CPM from disk ; Entry A = Drive to boot from. ; TEM = Number of sectors to read from ; track 3. ; A = Drive to boot or warm-boot from ; Exit A = 0, load sucessful. ; Z bit = 1, load successful. 0211 proc 0211 3217EF STO A,SDISK ;Set drive to boot from 0214 CD020B BCPM1: CALL HOMED ;home drive 0217 B7 OR A 0218 2053 ^026D$ JRNZ BCPME ;if drive NOT ready 021A 0100D4 LDK BC,CCP ;Set buffer address 021D CD850A CALL SETDMA 0220 210000 LDK HL,0 0223 2215EF STO HL,SAVTRK ;set track 0226 3E01 LDK A,1 0228 3214EF STO A,SAVSEC ;set sector=1 ; Read in 1st two track 022B 0602 LDK B,2 022D C5 :4: PUSH BC 027C 119102 BRDE: LDK DE,BRDEMG 027F 18EF ^0270$ JR BCPME1 ;delay output error 0281 88E4D2ECCA DNRMSG: DCE 'Drive NOT ready.' 0291 84DEDEE840 BRDEMG: DCE 'Boot READ error.' ; Endx BMboot.asm SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 18 Keyboard and Console Routines. E:OCCROM3B.ASM = 0001 @KEY = 1 ; Control keys = 0007 CBELL = 'G'-40h ;Ring the Bell = 000B MCUP = 'K'-40h ;Move cursor up = 000A MCDOWN = LF ;Move cursor down = 0008 MCLEFT = BKS ;Move cursor left = 000C MCRIGH = 'L'-40h ;Move cursor right = 001A VCLRS = 'Z'-40h ;Clear and home cursor = 001E VHOME = '^'-40h ;Home Cursor ; Es not lower 02C3 D620 SUI 'a'-'A' 02C5 C9 RET = 002D REPD = 45 ;initial rep delay = 0005 REPK = 5 ;repeat constant = 0000 .nkbd IF @KEY = 0 ;if not new keyboard, use old code .nkbd ENDIF SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 20 Keyboard and Console Routines. E:OCCROM3B.ASM 02C6 UPTIM: ;Update time via 60hz interrupt ; Time is kept in video memory as ; hhmmss (3 locations) ; Routine also checks to see if the disk drive motor ; should be turned off by updating DACTIVE ; ...Routine ALSO checks to see if bell is currently ; ringing: if so, decrement counter. ; if counter turns zero, shut off bell. 02C6 Proc 02C6 216BEF 2E 060A LDK B,MSEC 0230 CD9A0B CALL DREAD ;read 1st track 0233 C1 POP BC 0234 2046 ^027C$ JRNZ BRDE ;if read error 0236 220FEF STO HL,DMADR ;update DMA 0239 2A15EF LD HL,SAVTRK 023C 23 INC HL 023D 2215EF STO HL,SAVTRK ;update track to read 0240 10EB ^022D$ DJNZ :4 ;if not all tracks ; Now read in requested number of sectors ; from track 3. 0242 3A00EF LD A,TEM 0245 47 MOV B,A ;sectors to read 0246 C5 :8: PUSH BC 0247 0601 LDK B,1 0249 CD9A0B CALL DREAD ;read one sector 024C C1 POP BC 024D 202D ^027C$ JRNZ BRDE ;if read error 024F 220FEF STO HL,DMADR ;update DMA 0252 2114EF LDK HL,SAVSEC 0255 34 INC [hl] ;update sector number 0256 10EE ^0246$ DJNZ :8 ;if not all secs 0258 2150EF LDK HL,HSTACT 025B 110700cape keys = 0023 VLOCK: = '#' ;Lock Keyboard = 0022 VUNLK = '"' ;Unlock Keyboard = 003D VCAD: = '=' ;Cursor Addressing = 0053 VSAD: = 'S' ;Screen Addressing = 0051 VINC: = 'Q' ;Insert Char = 0057 VDELC: = 'W' ;Delete char = 0045 VINL: = 'E' ;Insert line = 0052 VDELL: = 'R' ;Delete line = 0054 VCEOL: = 'T' ;Clear to end of line = 0029 VSHI: = ')' ;Start half intensity = 0028 VEHI: = '(' ;end = 006C VSUL: = 'l' ;Start underline = 006D VEUL: = 'm' ;end = 0067 VSGH: = 'g' ;Start graphics = 0047 VEGH: = 'G' ;End 02A1 SKEY: ;Get status of keyboard ; Exit Cbit set if no data ready 02A1 3A59EF LD A,KEYLCK 02A4 B7 OR A 02A5 C8 RZ ;if locked keyboard 02A6 3A5EEF LD A,LK LK HL,BELCNT 02C9 AF XOR A 02CA B6 OR [hl] ;cell=zero ? 02CB 280C ^02D9$ JRZ :2 ;if bell now off 02CD 35 DEC [hl] ;...bell is on. decrement counter 02CE 2009 ^02D9$ JRNZ :2 ;if bell should stay on awhile yet 02D0 3A62EF LD A,PIABD 02D3 E6DF AND 1101_1111b ;clear bell bit 02D5 4F MOV C,A 02D6 CDD208 CALL OPBD 02D9 2B :2: DEC HL ;HL => DACTVE 02DA 7E LD A,[hl] 02DB B7 OR A 02DC 2804 ^02E2$ JRZ :3 ;if inactive 02DE 35 DEC [hl] ;reset delay 02DF CCE80A CZ DDRV ;if deselect drive 02E2 2B :3: DEC HL ;HL => SEC6 02E3 35 DEC [hl] 02E4 C0 RNZ ;if not 1 sec transition 02E5 363B STO 59,[hl] ;60th tick is NOW 02E7 AF XOR A ;A:=0, CY:=0 for DAA 02E8 2B DEC HL ;HL => SECS 02E9 7E LD A,[hl] ! INC A ! DAA ! STO A,[hl] 02ED FE60 CMP 60h 02EF LDK DE,(LOGSEC-HSTACT)+1 025E CD7008 CALL FILLZ ;clear Host BIOS cells 0261 3EFF LDK A,0FFh 0263 3255EF STO A,UNASEC 0266 3E7F LDK A,VLL-1 0268 326EEF STO A,LDTRK ;set other drive NOT int 026B AF XRA A ;Clear error indicator 026C C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 17 B o o t C P / M f r o m d i s k. E:OCCROM2B.ASM ; Here on Drive NOT ready 026D 118102 BCPME: LDK DE,DNRMSG ; Output error message and return to BCPM 0270 D5 BCPME1: PUSH DE 0271 3E00 LDK A,low(256) 0273 CD6008 CALL DELAY ;Delay 256 milli-seconds 0276 D1 POP DE ;FWA of message 0277 CD6F0C CALL ODER ;indicate drive NOT ready 027A 1898 ^0214$ JR BCPM1 ;try again ; Here on Boot READ error 02EY 02A9 CB7F $ BIT 7,A 02AB C9 RET ;=0 if NO DATA 02AC CI: 02AC RKEY: ;Read next key from keyboard ; Exit A=C= last key 02AC proc 02AC CDA102 CALL SKEY 02AF 28FB ^02AC$ JRZ RKEY ;if NO data 02B1 DI 02B2 4F MOV C,A 02B3 AF XRA A 02B4 325EEF STO A,LKEY ;clear key from hold 02B7 79 MOV A,C 02B8 E67F AND 7Fh 02BA 4F MOV C,A ;A=C 02BB EI SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 19 Keyboard and Console Routines. E:OCCROM3B.ASM 02BC C9 RET 02BD NORM: ;Normalize to UPPER case ; Entry A= char ; Exit A= CHAR 02BD FE61 CMP 'a' 02BF D8 RC ;if upper 02C0 FE7B CMP 'z'+1 02C2 D0 RNC ;if D8 RC ;if not 60 secs 02F0 3600 STO 0,[hl] ;reset seconds 02F2 2B DEC HL 02F3 7E LD A,[hl] ! INC A ! DAA ! STO A,[hl] 02F7 FE60 CMP 60h 02F9 D8 RC ;if not 60 minutes 02FA 3600 STO 0,[hl] 02FC 2B DEC HL 02FD 7E LD A,[hl] ! INC A ! DAA ! STO A,[hl] 0301 FE25 CMP 25h 0303 D8 RC ;if time <= 24:59:59 0304 3601 STO 1,[hl] 0306 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 21 Keyboard and Console Routines. E:OCCROM3B.ASM 0307 CO: ;Output routine for monitor ; Entry C= char ; CO will process ^p to toggle ; echo to list device ala cpm. ; Exit C=C=A. 0307 proc 0307 79 MOV A,C 0308 FE10 CMP 'P'-40h 030A 2009 ^0315$ JRNZ :53D DB VCAD ! DW ESCCAD ;Cursor Addressing 0334 53 DB VSAD ! DW ESCSAD ;Screen Addressing 0337 67 DB VSGH ! DW ESCSGR ;Set graphics mode 033A 47 DB VEGH ! DW ESCCGR ;Clr graphics mode 033D 29 DB VSHI ! DW ESCSHA ;Set half int. mode 0340 28 DB VEHI ! DW ESCCHA ;Clr half int. mode 0343 6C DB VSUL ! DW ESCSUN ;Set underline mode 0346 6D DB VEUL ! DW ESCCUN ;Clr underline mode 0349 1A DB VCLRS ! DW ESCZZ ;Clear screen to blanks 034C 51 DB VINC ! DW EINSRT ;Insert char 034F 57 DB VDELC ! DW EDELC ;Delete char 0352 45 DB VINL ! DW ESCEE ;Insert line 0355 52 DB VDELL ! DW ESCRR ;Delete line 0358 54 DB VCEOL ! DW EEOL ;Clear to end of line 035B 23 DB VLOCK ! DW ESCLCK ;Lock Keyboard 035E 22 DB VUNLK ! DW ESCULK ;Unlock Keyboard 0361 :end: 0361 AC03 DW ; =00 Normal mode & Last chr Esc flag false ; =08 Normal mode & Last chr Esc flag True ; =01,02,04 Mode is Graphics, Half, or Under, respectively ; , and Last chr Esc flag is False. ; =3,5,6,7 As above, but mode is combination ; =9-15 Last chr Esc flag True;otherwise like 1-7. 0386 proc 0386 E5 PUSH HL 0387 D5 PUSH DE 0388 C5 PUSH BC 0389 2A5AEF LD HL,CURS ;HL will usually be cursor. 038C 3A60EF LD A,ESCH 038F 47 MOV B,A ;B will be ESCH for a while 0390 E608 AND EF_ESC ;test flag bit 0392 2023 ^03B7$ JRNZ PSTESC ;IF last chr was ESC ;Current chr is NOT ESCaped. Is this chr ESC? 0394 79 MOV A,C ;Chr 0395 FE1B CMP ESC 0397 78 MOV A,B ;(A=ESCH) 0398 2815 ^03AF$ JRZ :ESC  ;if not toggle echo list 030C 3A07EF LD A,ECHOP 030F 2F CMA 0310 3207EF STO A,ECHOP ;toggle list echo 0313 79 :2: MOV A,C ;perserve A 0314 C9 RET 0315 CD8603 :5: CALL COUT ;output char 0318 3A07EF LD A,ECHOP 031B B7 OR A 031C 28F5 ^0313$ JRZ :2 ;if no echo to list 031E C3790A JMP LIST ;echo it SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 22 Keyboard and Console Routines. E:OCCROM3B.ASM ; Bit definitions for ESCH flag byte ; Note Bit 7 is currently free. = 0040 EF_X: = 64 ;B6= extegting X-coordinate = 0020 EF_SCR: = 32 ;B5= Screen/Cursor Addressing = 0010 EF_ADR: = 16 ;B4= expegting address-chr = 0008 EF_ESC: = 8 ;B3=$last char was ESC = 0004 EF_UN: = 4 ;B2= Underlin COUT2 ;No Match exit ; Ignore char upon undefined ESC-Sequence ; (to treat undefined char after ESC as a regular ; data char, should go to COUT2). = 0010 VALETS: = (:end-VALIDE)/3 ;# of entries in table SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 23 Keyboard and Console Routines. E:OCCROM3B.ASM 0363 VALIDC: ;Valid control character table ; 3 bytes per entry: Ascii char , "DW"- Vector ; no. of entries is VALCTS ; Following body of table is 2 byte No-Match adrs 0363 0D DB CR ! DW VC_CR ;carriage return routine 0366 0A DB LF ! DW VC_LF ;line feed 0369 08 DB BKS ! DW VC_BKS ;back space 036C 0C DB MCRIGH ! DW VC_MCRT ;move cursor right 036F 0B DB MCUP ! DW VC_MCUP ;move cursor up 0372 01 DB 'A'-40H  ;if this chr = ESC ;Here with A=B= ESCH 039A E5 :out: PUSH HL 039B 212103 LK HL,ESCHTB 039E E607 AND EF_MSK ;Mode bits only 03A0 87 ADD A,A ;Times two 03A1 5F MOV E,A 03A2 1600 LK D,0 ;DE = offset 03A4 19 ADD HL,DE ;HL = tbl addrs 03A5 VECTOR: ;entry point. note hl on stack. 03A5 7E LD A,[HL] ;1st byte (low order adrs) 03A6 23 INC HL 03A7 66 LD H,[HL] ;2nd byte (hi order adrs) 03A8 6F MOV L,A ;HL=adrs from table 03A9 E3 XTHL ;Restore hl from stack ;stack=tbl adrs 03AA 79 MOV A,C ;Chr. note B=ESCH byte value 03AB C9 RET ;enter routine per table adrs. 03AC 78 COUT2: MOV A,B ;recall ESCH value 03AD 18EB ^039A$ JR :out ;output chr per current settings 03AF :ESC: ;Current chr is ESC. Set fle mode = 0002 EF_HA: = 2 ;B1= Half Intensity mode = 0001 EF_GR: = 1 ;B0= Graphics mode = 0007 EF_MSK: = EF_UN+EF_HA+EF_GR ;Mask to get mode. ; Vector (branch) table for video output mode selection ; controlled by ESCH mode 0321 C903 ESCHTB: DW VNORM ;0 Normal mode 0323 D204 DW VGRAPH ;1 Graphics mode 0325 F703 DW VHALF ;2 Half intensity mode 0327 FB03 DW VHA_GR ;3 Half and graphics 0329 E903 DW VUNDER ;4 Underline mode 032B ED03 DW VUN_GR ;5 Under and graphics 032D F103 DW VUN_HA ;6 Under and half intensity 032F F503 DW VUN_HA_GR ;7 Under and half and graphics 0331 VALIDE: ;Valid ESC-Sequence Table ; 3 bytes per entry:ascii char , "DW"-Vector. ; no. of entries is VALETS ; Following body of table is 2 byte No-Match adrs 0331 ! DW VSHFT_L ;shift screen left 0375 02 DB 'B'-40H ! DW VSHFT_R ;shift right 0378 03 DB 'C'-40H ! DW VSHFT_0 ;left column (^1) 037B 07 DB CBELL ! DW VC_BEL ;Ring bell 037E 1A DB VCLRS ! DW VC_CLRS ;clear screen 0381 1E DB VHOME ! DW VC_HOME ;Cursor Home ; 0384 EF04 DW VOUT97 ;No match--ignore undef control char ; = 000B VALCTS: = ((*-2)-VALIDC)/3 ;Number of valid entries SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 24 Keyboard and Console Routines. E:OCCROM3B.ASM 0386 COUT: ;General output routine to Video Screen ; ENTRY C=Character, CURS=Cursor, ESCH=Flag+Mode ; EXIT CURS & ESCH updated, A=Character ; (bc, de, hl preserved) ; ; ESCH is flag + mode byte as follows  ag and exit 03AF F608 OR EF_ESC ;indicate last char= ESC 03B1 3260EF STO A,ESCH 03B4 C3EF04 JMP VOUT97 ;Exit SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 25 Keyboard and Console Routines. E:OCCROM3B.ASM 03B7 PSTESC: ;Last chr was ESC ; Entry A= EF_ESC ; B= ESCH ; C= Char to output ; HL=curs 03B7 Proc 03B7 CB60 $ BIT 4,B ;is this chr really an address? 03B9 206B ^0426$ JRNZ SETXY ;...if chr is part of an addr ;no cursor/screen addressing in effect: 03BB A8 XOR B ;Clr EF_ESC bit (for next time) 03BC 47 MOV B,A ;Set up B = ESCH byte value. 03BD 3260EF STO A,ESCH 03C0 E5 PUSH HL ;save Curs 03C1 213103 LDK HL,VALIDE ;Branch table adrs 03C4 1E10 LDK E,VALETS  SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 27 Keyboard and Console Routines. E:OCCROM3B.ASM ; Processing for modes other than normal. ; -------------------------------------- ;VGRAPH = VOUT80 ;Normal mode EXCEPT: cntl chrs are printed 03E9 VUNDER: ;Underline only 03E9 FE20 CMP ' ' 03EB 38DC ^03C9$ JRC VNORM ;if cntl-chr, process as normal ; JR VUN_GR ;continue 03ED VUN_GR: ;Underlined Graphics 03ED F680 OR 80h ;underline bit 03EF 18DC ^03CD$ JR VBRIGH ;set this chr BRIGHT 03F1 VUN_HA: ;Underline and Half intensity 03F1 FE20 CMP ' ' 03F3 38D4 ^03C9$ JRC VNORM ;if cntl-chr, process as normal ; JR VUN_HA_GR 03F5  LK A,-(' ') 042B 81 ADD C ;remove cursor bias 042C CB68 $ BIT 5,B ;cursor/screen addressing? 042E 20D6 ^0406$ JRNZ SCREEN ;if screen addressing ;cursor addressing: 0430 29 ADD HL,HL ;shift HL left 0431 CB70 $ BIT 6,B ;X/Y coordinate? 0433 2010 ^0445$ JRNZ :cX ;if X coordinate 0435 67 :cY: MOV H,A ;save 0436 3A62EF LD A,PIABD 0439 84 ADD H ;offset by start-Y co-ord of video 043A 1F RAR ;bit0(A) -> CY, shift A right 043B CB1D $ RR L ;CY -> bit7(L) 043D F6F0 OR 0F0h ;turn on upper nybl 043F 67 MOV H,A ;HL= new cursor addr ; JR :exitY 0440 3E40 :exitY: LK A,0100_0000b ;next addr-chr will be X-coord 0442 B0 OR B 0443 1808 ^044D$ JR :exit2 0445 17 :cX: RAL ;trash 7th bit SORC;Table size 03C6 79 MOV A,C ;Chr to A 03C7 1815 ^03DE$ JR LOOKUPB ;Go to routine to branch per tbl 03C9 VNORM: ;NORMAL mode character processing. ; Entry A= char to output ; HL=curs 03C9 FE20 CMP ' ' 03CB 380B ^03D8$ JRC :2 ;IF control chr 03CD VBRIGH: DI ! ENADIM ;9th bit memory 03D0 3680 STO BRTBIT,[hl] ;set this chr BRIGHT 03D2 DISDIM ! EI 03D5 C3D204 JMP VOUT80 03D8 E5 :2: PUSH HL ;Save Curs 03D9 216303 LDK HL,VALIDC ;Branch table adrs 03DC 1E0B LDK E,VALCTS ;Table size ; JMP LOOKUPB ;Scan table of valid control chrs ; ;and branch to appropriate routine. SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 26 Keyboard and Console Routines. E:OCCROM3B.ASM 03DE LOOKUVUN_HA_GR: ;Underline, Half Intensity, Graphics 03F5 F680 OR 80h ;set underline bit ; JR VHA_GR 03F7 VHALF: ;Half Intensity 03F7 FE20 CMP ' ' 03F9 38CE ^03C9$ JRC VNORM ;if cntl-chr, process as normal ; JR VHA_GR 03FB VHA_GR: ;C=Chr, HL=Curs 03FB DI 03FC ENADIM 03FE 3600 STO DIMBIT,[hl] ;set dim field bit ; LD E,[hl] ;diagnostic 0400 DISDIM 0402 EI 0403 C3D204 JMP VOUT80 ;continue SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 28 Keyboard and Console Routines. E:OCCROM3B.ASM 0406 SCREEN: ;SetXY for Screen movement ; Entry B= ESCH ; A= new co-ord val, NO OFFSET 0406 Proc 0406 CB70 $ BIT 6,B 0408 IM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 29 Keyboard and Console Routines. E:OCCROM3B.ASM 0446 CB2C $ SRA H ;bit0(H) -> CY, bit7 stays 1 0448 1F RAR ;... CY -> bit7(A) 0449 6F MOV L,A ; JR :exitX 044A 3E07 :exitX: LK A,EF_MSK 044C A0 AND B ;finished addressing: reset addr bits 044D 3260EF :exit2: STO A,ESCH 0450 C3E704 JMP VOUT90 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 30 Keyboard and Console Routines. E:OCCROM3B.ASM ; Control Code character processing 0453 VC_HOME: ;Home Cursor 0453 Proc 0453 CD6606 CALL UN_CUR 0456 3A62EF LD A,PIABD 0459 1F RAR ;bit0 => CY 045A 2E00 LK L,0 045C CB1D $ RR L ;CY => bit7, trash bit0 045E 67 PB: ;Logic to scan 3 byte branch table ; NOT a subroutine---do not CALL. ; Entry HL =1st byte of table (match code) ; (2nd,3rd bytes = branch adrs) ; (table repeats [3 byte entries]) ; E is table size (no. of entries) ; (table body is followed with ; 2 byte "No-Match" adrs) ; Stack has HL saved as top entry. ; C = char ; A = value to scan for possible match 03DE BE CMP [HL] 03DF 23 INC HL ;(2nd byte of this 3 byte entry) 03E0 28C3 ^03A5$ JRZ VECTOR ;If match process 03E2 23 INC HL ;(3rd byte of this entry) 03E3 23 INC HL ;1st byte of next entry 03E4 1D DEC E ;Dec count of entries remaining 03E5 20F7 ^03DE$ JRNZ LOOKUPB ;Continue thru body of table 03E7 18BC ^03A5$ JR VECTOR ;No-Match. hl=points to vector  200F ^0419$ JRNZ :sX ;if X-coordinate 040A E61F :sY: AND 0001_1111b ;mod 32 040C 4F MOV C,A 040D 3A62EF LD A,PIABD 0410 E6E0 AND 1110_0000b 0412 B1 OR C 0413 4F MOV C,A 0414 CDD208 CALL OPBD ;set Y coordinate 0417 1827 ^0440$ JR :exitY 0419 87 :sX: ADD A,A ;double A 041A C6EA ADD A,VFLO ;PIA A-reg magic offset constant 041C E6FE AND 1111_1110b ;clear bit 0 => no 1/2 chr shift 041E 4F MOV C,A 041F CDC508 CALL OPAD ;set X coordinate 0422 CBA8 $ CBIT 5,B ;finished screen-addressing 0424 1824 ^044A$ JR :exitX 0426 SETXY: ;Set X-Y value for Cursor/Screen Addressing ; Entry HL= cursor_addr ; B = ESCH ; C = chr ; Exit to VOUT90; ESCH updated 0426 CD6606 CALL UN_CUR 0429 3EE0 ! MOV H,A 045F 182F ^0490$ JR :fixhl ;HL := HL or F000h 0461 VC_MCUP: ;Move Cursor Up. ; A=C=Chr=MCUP. HL=Curs. 0461 CD6606 CALL UN_CUR 0464 E5 PUSH HL ;old cursor must be on stack 0465 0180FF LK BC,(-VLL) 0468 1816 ^0480$ JR :fwa ;...at this entry point 046A VC_BKS: ;HL=Curs=current (old) char 046A CD6606 CALL UN_CUR ;clear 80h bit 046D 3E7F LK A,7Fh 046F A5 AND L 0470 2803 ^0475$ JRZ :wrap ;if must wrap from col 0 to LLIMIT 0472 2B DEC HL 0473 1872 ^04E7$ JR VOUT90 ;Exit 0475 E5 :wrap: PUSH HL ;save old cursor 0476 017FFF LK BC,-(VLL+1) 0479 09 ADD HL,BC ;HL = prev_line, (-1)st column 047A 3A6CEF LD A,LLIMIT ;LLIMIT = #columns on screen 047D 4F MOV C,A 047E 0600 LK B,0 0480 09 :fwa: ADD HL,BC 0481 E3  ; JR VOUT80 ;re-echo current chr SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 32 Keyboard and Console Routines. E:OCCROM3B.ASM ; Exit points for COUT ; Here to store new data and to update cursor 04D2 VGRAPH: 04D2 77 VOUT80: STO A,[hl] ;This exit path stores A (new char) 04D3 5D MOV E,L 04D4 CBBB $ CBIT 7,E ;E = col(cursor) 04D6 3A6CEF LD A,LLIMIT 04D9 3D DEC A ;A = last_legal_col 04DA 93 SUB E ;A = last_legal_col - col(cur) 04DB 2009 ^04E6$ JRNZ VOUT85 ;if not @LLIMIT 04DD 3E80 LK A,80h 04DF A5 AND L 04E0 6F MOV L,A ;do CR... 04E1 CD0806 CALL DO_LF2 ;...and LF. 04E4 1801 ^04E7$ JR VOUT90 04E6 23 VOUT85: INC HL ;move cursor ; Here if NO ; Page 34 Keyboard and Console Routines. E:OCCROM3B.ASM ;Subroutine for use with EDELC and EINSRT: ;Calculate #chrs to move; if move zero chrs, never return. 0516 Proc 0516 3E7F :calc: LK A,VLL-1 ;A= max #chrs to be moved 0518 4D MOV C,L 0519 CBB9 $ CBIT 7,C ;C = col(cursor) 051B 91 SUB C ;A = #chrs to move 051C 2804 ^0522$ JRZ :end ;if move zero characters 051E 4F MOV C,A 051F 0600 LK B,0 ;BC = #chrs to move 0521 C9 RET 0522 E1 :end: POP HL ;trash return_addr 0523 E1 POP HL ;cursor_addr 0524 18C1 ^04E7$ JR VOUT90 0526 EDELC: ;Delete Character 0526 E5 PUSH HL ;save cursor_addr 0527 CD1605 CALL :calc ;calculate BC 052A 54 MOV D,H 052B 5D MOV E,L ;DE = cursor_addr 052C 23 INC H XTHL ;get old cursor, save new 0482 29 ADD HL,HL ;shift line# into H reg. 0483 3A62EF LD A,PIABD 0486 F6E0 OR 1110_0000b ;A = line# of UL corner 0488 BC CMP H ;set Zflag: @home? 0489 E1 POP HL ;get new cursor... 048A 2004 ^0490$ JRNZ :fixhl ;if NOT @video home 048C 01000C LK BC,(24*VLL) ;wrap constant 048F 09 ADD HL,BC 0490 3EF0 :fixhl: LK A,0F0h 0492 B4 OR H ;modulo result: keep cursor 0493 67 MOV H,A ;inside video memory. 0494 1851 ^04E7$ JR VOUT90 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 31 Keyboard and Console Routines. E:OCCROM3B.ASM 0496 VC_BEL: ;Ring the bell via setting PIAB 2**5 bit 0496 3A62EF LD A,PIABD 0499 F620 OR 0010_0000b ;bell bit 049B 4F MOV C,A 049C CDD208 CALL OPBD ;function PIAB 049F 3E1E LK A,3cursor update 04E7 7E VOUT90: LD A,[HL] ;This exit path turns on 80h bit ; Here if new data already in A 04E8 17 VOUT95: RAL ;Make this chr cursor 04E9 3F VOUT96: CMC ;invert cursor bit 04EA 1F RAR 04EB 77 STO A,[hl] 04EC 225AEF STO HL,CURS ;update cursor ; Here if no change to cursor, restore reg and exit 04EF C1 VOUT97: POP BC 04F0 D1 POP DE 04F1 E1 POP HL 04F2 79 MOV A,C ;Exit with A=chr 04F3 C9 RET ;return, end of cout subr. = 046E :First = VOUT97 - (127 + 2) ;earliest possible JR = 0550 :Last = VOUT80 + (128 - 2) ;latest possible JR SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 33 Keyboard and Console Routines. E:OCCROM3B.ASM 04F4 L ;HL = cursor_addr + 1 052D CD5506 CALL VLDIR ;move characters 0530 3620 STO ' ',[hl] ;last chr becomes blank 0532 DI ! ENADIM ;enable 9th bit memory 0535 2B DEC HL ;HL = last chr on this line 0536 3680 STO BRTBIT,[hl] ;set chr BRIGHT 0538 DISDIM ! EI ;main memory 053B E1 POP HL ;restore cursor_addr 053C 18A9 ^04E7$ JR VOUT90 ;next 053E EINSRT: ;Insert Character 053E CD6606 CALL UN_CUR 0541 E5 PUSH HL ;save cursor_addr 0542 CD1605 CALL :calc ;calculate BC 0545 3E7F LK A,7Fh 0547 B5 OR L 0548 6F MOV L,A ;HL = last_chr on this line 0549 5F MOV E,A 054A 54 MOV D,H ;DE = HL 054B 2B DEC HL 054C CD4406 CALL VLDDR ;do move 054F E1 POP HL ;restore cursor 0550 7E LD A,[hl] ;get underline bit of this chr. 0551 17 RAL ;int0 ;ring bell for 30 ticks 04A1 326BEF STO A,BELCNT ;... = 1/2 second 04A4 1849 ^04EF$ JR VOUT97 ;exit no change 04A6 2100F0 VC_CLRS: LK HL,FWAVM 04A9 CDE405 CALL CLRLN ;clear 1st line 04AC 01800F LK BC,LVMEM-VLL 04AF CD5506 CALL VLDIR ;clear remaining lines 04B2 3A62EF LD A,PIABD ;Reset for 1st line of display mem 04B5 E6E0 AND not(1_1111b) 04B7 4F MOV C,A 04B8 CDD208 CALL OPBD 04BB 2100F0 LK HL,FWAVM ;new cursor 04BE 1827 ^04E7$ JR VOUT90 ;Exit 04C0 CD6606 VC_CR: CALL UN_CUR ;erase cursor 04C3 3E80 LK A,80h ;Carriage Return 04C5 A5 AND L 04C6 6F MOV L,A 04C7 181E ^04E7$ JR VOUT90 04C9 CD0506 VC_LF: CALL DO_LF ;Line Feed 04CC 1819 ^04E7$ JR VOUT90 04CE VC_MCRT ;Move Cursor Right 04CE CD6606 CALL UN_CUR 04D1 7E LD A,[hl]  ESC_LCK: ;Lock Keyboard 04F4 Proc 04F4 AF XOR A 04F5 1802 ^04F9$ JR :2 04F7 ESC_ULK: ;Unlock Keyboard 04F7 3EFF LK A,0FFh 04F9 3259EF :2: STO A,KEYLCK 04FC 18F1 ^04EF$ JR VOUT97 04FE EEOL: ;Erase to end of line 04FE E5 PUSH HL ;save cursor 04FF CDE405 CALL CLRLN 0502 E1 POP HL 0503 18E2 ^04E7$ JR VOUT90 0505 ESC_CAD: ;Cursor Addressing 0505 3E07 LK A,EF_MSK 0507 A0 AND B 0508 F618 OR EF_ESC or EF_ADR ;next chr will be Y-coord 050A 3260EF :exit3: STO A,ESCH 050D 18E0 ^04EF$ JR VOUT97 050F ESC_SAD: ;Screen Addressing 050F 3E07 LK A,EF_MSK 0511 A0 AND B 0512 F638 OR EF_ESC or EF_ADR or EF_SCR 0514 18F4 ^050A$ JR :exit3 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0"o CY 0552 3E40 LK A,' ' shl 1 ;change this chr to ' ' 0554 1893 ^04E9$ JR VOUT96 ;exit SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 35 Keyboard and Console Routines. E:OCCROM3B.ASM ; ESC-Sequence processing. 0556 Proc 0556 3E01 ESCSGR: LDK A,EF_GR ;ESC-g 0558 1806 ^0560$ JR :125 ;set graphics mode. 055A 3E02 ESCSHA: LDK A,EF_HA ;ESC-) set half intensity 055C 1802 ^0560$ JR :125 ;go set flag bit 055E 3E04 ESCSUN: LDK A,EF_UN ;ESC-l set underline 0560 B0 :125: OR B ;Reg B is ESCH Byte value 0561 3260EF :130: STO A,ESCH ;store desired value. 0564 1889 ^04EF$ JR VOUT97 ;Exit 0566 3EFE ESCCGR: LDK A,NOT EF_GR ;ESC-G Clear graphics mode 0568 1806 ^0570$ JR :140 ;go clear ESCH bit 056A 3EFD ESCCHAddr(25th line) 0598 94 SUB H ;A = lines_to_move + 1 0599 E61F AND 0001_1111b ;mod 32 059B 47 MOV B,A 059C 3E52 LK A,VDELL 059E B9 CMP C 059F 78 MOV A,B ;recall #lines to move 05A0 2820 ^05C2$ JRZ :delt ;if deleting a line 05A2 :insrt: ;Insert a line 05A2 84 ADD H ;A = addr(25th line) 05A3 57 MOV D,A 05A4 1E00 LK E,0 05A6 CB1A $ RR D ! RR E ;shift right DE 05AA 1B DEC DE ;DE = addr(lst_chr_on_lst_line) 05AB 78 MOV A,B ;A = #lines to move 05AC 2180FF LK HL,-VLL 05AF 19 ADD HL,DE ;HL = addr(line above DE) ;DE := DE or F000h; HL := HL or F000h 05B0 1803 ^05B5$ JR :istrt 05B2 CD4406 :icont: CALL VLDDR ;move 1 line down 05B5 CDD505 :istrt: CALL :vmod 05B8 20F8 ^05B2$ JRNZ :icont ;if must move more lines 05BA 23 INC  05F2 5D MOV E,L 05F3 CBBB $ CBIT 7,E 05F5 93 SUB E ;A = col(EOL) - col(cursor) 05F6 C8 RZ ;if @EOL, done 05F7 3004 ^05FD$ JRNC :2 ;if inside logical_video_line 05F9 3E80 LK A,VLL 05FB 93 SUB E ;...else clr to end of 128-chr line 05FC C8 RZ ;if cursor @ column #127 05FD 4F :2: MOV C,A 05FE 0600 LK B,0 ;BC = chrs to move 0600 5D MOV E,L 0601 54 MOV D,H 0602 13 INC DE ;DE = HL + 1 0603 1850 ^0655$ JR VLDIR SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 40 Keyboard and Console Routines. E:OCCROM3B.ASM 0605 DO_LF: ;Do Line Feed processing ; Entry HL = cursor_addr ; Exit Cursor cleared ; HL updated for current cursor pos : LDK A,NOT EF_HA ;ESC-( Clear half intensity 056C 1802 ^0570$ JR :140 056E 3EFB ESCCUN: LDK A,NOT EF_UN ;ESC-m Clear underline 0570 A0 :140: AND B ;Clear bit 0571 18EE ^0561$ JR :130 ;Go store ESCH byte = 04A6 ESCZZ: = VC_CLRS ;ESC-Z Clear screen -same as ; ;Control-Z routine. SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 36 Keyboard and Console Routines. E:OCCROM3B.ASM 0573 Proc 0573 VSHFT_L: ;shift screen left 0573 0E02 LK C,+2 0575 1802 ^0579$ JR :slide 0577 VSHFT_R: ;shift screen right 0577 0EFE LK C,-2 0579 :slide: DI 057A 3A61EF LD A,PIAAD ;get old offset 057D 81 ADD C ;modify... 057E 4F MOV C,A 057F CDC508 :1: CALL OPAD ;new setHL ;HL => 1st chr of new line ; JR :exit 05BB CDE405 :exit: CALL CLRLN 05BE E1 POP HL ;recover cursor 05BF C3E704 JMP VOUT90 ;Main Exit SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 38 Keyboard and Console Routines. E:OCCROM3B.ASM 05C2 D1 :delt: POP DE ;recover new cursor 05C3 D5 PUSH DE 05C4 218000 LK HL,VLL 05C7 19 ADD HL,DE ;HL = line_below_cursor 05C8 1803 ^05CD$ JR :dstrt 05CA CD5506 :dcont: CALL VLDIR ;move 1 line up 05CD CDD505 :dstrt: CALL :vmod 05D0 20F8 ^05CA$ JRNZ :dcont 05D2 EB EX HL,DE ;get addr of line to clear 05D3 18E6 ^05BB$ JR :exit ;HL := HL or F000h; DE := DE or F000h; ;simple mod-4096 arithmetic to keep pointers INSIDE video memory 05D5 F5 :vmod: PUSH AF ;save A = #lines to m ; window moved if necessary 0605 proc 0605 CD6606 CALL UN_CUR ;clear cursor 0608 E5 DO_LF2: PUSH HL ;save original cursor 0609 018000 LK BC,VLL ;line length 060C 09 ADD HL,BC 060D 3004 ^0613$ JRNC :nowap ;if not wrapping from LWAVM to FWAVM 060F 0100F0 LK BC,FWAVM 0612 09 ADD HL,BC ;HL = new cursor @ top of VM 0613 E3 :nowap: XTHL ;save new cursor, get old 0614 29 ADD HL,HL ;shift HL left 0615 3A62EF LD A,PIABD 0618 C617 ADD A,23 ;start + 23 = last_video_line 061A 94 SUB H ;A = l_line - curr_line 061B E61F AND 0001_1111b ;modulo 32 061D 2802 ^0621$ JRZ :vmov ;if cursor is on 24th line of screen 061F E1 :end: POP HL ;get new cursor 0620 C9 RET 0621 3A6CEF :vmov: LD A,LLIMIT 0624 CB3D $ SRL L ;unshift L register 0626 95 SUB L ;A = LLIMIT - col(cuting for video offset 0582 EI 0583 C3EF04 JMP VOUT97 0586 VSHFT_0: ;shift to column #0 (like ^1) 0586 0EEA LK C,VFLO ;constant for column #0 0588 18F5 ^057F$ JR :1 ;set video offset SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 37 Keyboard and Console Routines. E:OCCROM3B.ASM 058A ESCRR: ;Delete Line 058A ESCEE: ;Insert Line ; Entry HL = cursor ; C = chr ; Exit screen updated ; HL = new cursor ; ...to VOUT90 058A Proc 058A CD6606 CALL UN_CUR 058D 3E80 LK A,1000_0000b 058F A5 AND L 0590 6F MOV L,A ;do CR 0591 E5 PUSH HL ;save new cursor 0592 29 ADD HL,HL 0593 3A62EF LD A,PIABD 0596 C618 ADD A,24 ;A = aove 05D6 3EF0 LK A,0F0h 05D8 B4 OR H 05D9 67 MOV H,A ;set upper nybl of H 05DA 3EF0 LK A,0F0h 05DC B2 OR D 05DD 57 MOV D,A ;modulo 4096 05DE 018000 LK BC,VLL 05E1 F1 POP AF 05E2 3D DEC A ;decrement line_count 05E3 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 39 Keyboard and Console Routines. E:OCCROM3B.ASM 05E4 CLRLN: ;Clear to end of line ; Entry HL= Cursor ; Exit clear to EOL ; Uses All. 05E4 proc 05E4 3620 STO ' ',[hl] ;clear cursor... 05E6 DI 05E7 ENADIM 05E9 3680 STO BRTBIT,[hl] ;set cursor BRIGHT 05EB DISDIM 05ED EI 05EE 3A6CEF LD A,LLIMIT 05F1 3D DEC A ;max_#cols => maximum_col_# #rsor) 0627 38F6 ^061F$ JRC :end ;if cursor is outside logical line ;cursor is on last line of screen, inside of logical line. ;must move screen to follow cursor down through video memory. 0629 E1 POP HL 062A E5 PUSH HL 062B 3E80 LK A,80h 062D A5 AND L 062E 6F MOV L,A ;HL = beginning of line 062F CDE405 CALL CLRLN ;erase to EOL 0632 3A62EF LD A,PIABD 0635 47 MOV B,A 0636 E6E0 AND not 31 ;A = line zero 0638 4F MOV C,A ;C = housekeeping bits 5..7 0639 3E1F LK A,31 063B 04 INC B ;increment line# 063C A0 AND B ;A = line# 063D B1 OR C ;A = new line# OR housekeeping_bits 063E 4F MOV C,A ;C = new value for OPBD 063F CDD208 CALL OPBD ;move video screen down 1 line in memory 0642 E1 POP HL 0643 C9 RET  ; SYSTEM CLOCK UPDATED BY UPTIM. 066C PROC 066C DI 066D ED736FEF $ STO SP,IESTK ;SAVE INTERRUPTED PROCESS STK 0671 3199EF LK SP,ISTK ;SET TO RAM INT STK 0674 PUSHAL 067C CDC602 CALL UPTIM ;UPDATE SYSTEM CLOCK 067F 3A59EF LD A,KEYLCK 0682 B7 OR A 0683 2843 ^06C8$ JRZ GKEYX ;IF LOCKED KEYBOARD 0685 CDC607 :SCAN: CALL RDKEY ;SCAN KEYBOARD 0688 FEFE CMP -2 068A 283F ^06CB$ JRZ GKEYAB ;IF NO KEY BEING PRESSED ;DEBOUNCE THE KEYBOARD: 068C 215CEF LK HL,TKEY 068F BE CMP [HL] ;SAME AS LAST TIME? (SET Z FLAG) 0690 77 STO A,[HL] ;SET TKEY TO CURRENT VALUE 0691 47 MOV B,A ;SAVE CHR 0692 215DEF LK HL,HKCNT 0695 200D ^06A4$ JRNZ :1ST ;IF THIS IS FIRST SUCH KEYPRESS  06D2 FE21 CMP ' ' + 1 06D4 D8 RC ;IF CNTL-CHR (<=SPACE), UNSHIFTABLE 06D5 215FEF LK HL,CKEY 06D8 CB66 $ BIT 4,[HL] ;SHIFT KEY BIT 06DA 2005 ^06E1$ JRNZ :SHIFT ;IF SHIFT KEY PRESSED 06DC CB5E $ BIT 3,[HL] ;ALPHA LOCK KEY BIT 06DE 2017 ^06F7$ JRNZ :ALPHA ;IF ALPHA KEY PRESSED 06E0 C9 RET ;IF NO SHIFTING NECESSARY 06E1 FE41 :SHIFT: CMP 'A' 06E3 3012 ^06F7$ JRNC :ALPHA ;IF 'A'..'Z' 06E5 FE5B CMP '[' 06E7 3805 ^06EE$ JRC :TBLSF ;IF CHR < '[', USE SHIFT TABLE ;MUST BE '[' OR '\' 06E9 200F ^06FA$ JRNZ :ALPHX ;IF '\', SHIFT AS ALPHA 06EB 3E5D LK A,']' 06ED C9 RET ;...ELSE '[' SHIFTED IS ']' 06EE 5F :TBLSF: MOV E,A 06EF 1600 LK D,0  SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 41 Keyboard and Console Routines. E:OCCROM3B.ASM 0644 VLDDR: ;Video Block Move ; Entry BC, DE, HL set ; Exit LDDR on main & 9th bit memory ; Uses BC, DE, HL 0644 C5 PUSH BC ! PUSH DE ! PUSH HL 0647 EDB8 $ LDDR ;main memory 0649 E1 POP HL ! POP DE ! POP BC 064C DI 064D ENADIM 064F EDB8 $ LDDR ;9th bit memory 0651 DISDIM 0653 EI 0654 C9 RET 0655 VLDIR: ;Video Block Move ; Entry BC, DE, HL set ; Exit LDIR on main & 9th bit memory ; Uses BC, DE, HL 0655 C5 PUSH BC ! PUSH DE ! PUSH HL 0658 EDB0 $ LDIR ;main memory 065A E1 POP HL ! POP DE ! POP BC 065D  0697 7E MOV A,[HL] 0698 FE00 CMP 0 069A CAB006 JZ :2ND ;SECOND TIME FOR THIS KEY 069D 35 :AUTO: DEC [HL] 069E 2028 ^06C8$ JRNZ GKEYX ;IF STILL WAITING FOR REPD/REPK 06A0 3605 STO REPK,[HL] ;...ELSE SET REPK FOR NEXT CHR, 06A2 180E ^06B2$ JR :DCODE ;AND RETURN CHR 06A4 3AC6EF :1ST: LD A,KBDLY ;GET # OF INTERRUPTS TO DEBOUNCE 06A7 CD6008 CALL DELAY 06AA AF XRA A ;ZERO "HKCNT" 06AB 325DEF STO A,HKCNT 06AE 18D5 ^0685$ JR :SCAN 06B0 362D :2ND: STO REPD,[HL] ;SET "REPD" DELAY 06B2 78 :DCODE: MOV A,B ;RESTORE CHR 06B3 CDD206 CALL SHIFT ;SHIFT PROCESSING 06B6 215FEF LK HL,CKEY 06B9 CB56 $ BIT 2,[HL] ;CK FOR CNTL KEY 06BB 2806 ^06C3$ JRZ :FIN ;IF CNTL-KEY IS NOT PRESSED 06BD CD4407 CALL SLIDE ;CK FOR ;DE = CHR 06F1 21D606 LK HL, :STBL - '''' ;TABLE FWA - APOSTROPHE 06F4 19 ADD HL,DE ;HL => SHIFTED CHARACTER 06F5 7E LD A,[HL] ;A = SHIFTED CHR 06F6 C9 RET 06F7 FE41 :ALPHA: CMP 'A' 06F9 D8 RC ;IF <'A', IGNORED BY ALPHA LOCK 06FA EE20 :ALPHX: XOR 20H ;UPPER/LOWER CASE BIT 06FC C9 RET ;SHIFTED "COMMA" BECOMES "LESS THAN", ;SHIFTED "HYPHEN" BECOMES "UNDERBAR", (ETC.) ; ''', ...THESE 4 ARE UNUSED 06FD 227B7D7C7E :STBL: DB '"', '{', '}', '|', '~' ; ',', '-', '.', '/', '0', '1', '2', '3', '4', '5' 0702 3C5F3E3F29 DB '<', '_', '>', '?', ')', '!', '@', '#', '$', '%' ; '6', '7', '8', '9', (:), ';', (<), '=', (>) 070C 5E262A2820 DB '^', '&', '*', '(', ' ', ':', ' ', '+', ' '  DI 065E ENADIM 0660 EDB0 $ LDIR ;9th bit memory 0662 DISDIM 0664 EI 0665 C9 RET 0666 UN_CUR: ;Undo/Invert Cursor ; Entry HL = cursor_addr ; Exit cursor inverted ; Uses A, CY. 0666 7E LD A,[hl] ;get the chr 0667 17 RAL ;cursor_bit => CY 0668 3F CMC ;invert it 0669 1F RAR 066A 77 STO A,[hl] ;... 066B C9 RET ; endx BMKEY.asm ***************** SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 42 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 066C GKEY: ;KEYBOARD INTERRUPT PROCESSOR ; ENTRY NONE ; EXIT KEYBOARD PROCESSING DONE, RESULT IN LKEY. SCREEN SLIDE KEYS 06C0 CD1507 CALL CNTRL ;CNTRL KEY PROCESSING 06C3 F680 :FIN: OR 80H ;SET PARITY BIT FOR CI SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 43 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 06C5 325EEF STO A,LKEY ;MAKE CHR AVAILABLE TO CI 06C8 C31E00 GKEYX: JMP EXITI ;EXIT INTERRUPT 06CB GKEYAB: ;ABORT PROCESSING: SET TKEY := -2 AND RETURN. 06CB 3EFE LK A,-2 06CD 325CEF STO A,TKEY 06D0 18F6 ^06C8$ JR GKEYX SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 44 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 06D2 SHIFT: ;SHIFT KEY PROCESSING ; ENTRY A = CHR FROM RDKEY ; EXIT A = SHIFTED VALUE FROM SHIFT AND ALPHA LOCK KEYS 06D2 PROC $ SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 45 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 0715 CNTRL: ;CONTROL KEY PROCESSING ; ENTRY A = CHR, CNTL KEY PRESSED SIMULTANEOUSLY ; EXIT A = ^CHR 0715 PROC 0715 FE21 CMP ' ' + 1 0717 D8 RC ;IF SPACE, TAB, ESC, RET, ETC. 0718 FE40 CMP '@' 071A 3807 ^0723$ JRC :CHEAT ;IF <'@', CK FOR CHEATED CHR 071C FE5B CMP 'Z'+1 071E 30AB ^06CB$ JRNC GKEYAB ;IF GREATER THAN 'Z', NO CNTL-CHR 0720 E61F AND ' ' - 1 ;KILL CNTL & LOWERCASE BITS 0722 C9 RET 0723 47 :CHEAT: MOV B,A ;SAVE CHR 0724 E62C AND ',' 0726 FE2C CMP ',' 0728 20A1 ^06CB$ JRNZ GKEYAB ;IF NOT A LEGAL CHEATED CHR 79C$ JRZ :SLIDV ;1,2,3,4,5,6 0768 FE31 CMP '1' 076A D8 RC ;IF NOT A SLIDING CHR 076B F5 PUSH AF ;SAVE VALUE 076C 3A62EF LD A,PIABD ;OLD Y VALUE 076F E6E0 AND 11100000B ;SET Y TO ZERO 0771 47 MOV B,A ;VALUE TO B 0772 F1 POP AF ;RESTORE VALUE 0773 0EEA LK C, VFLO + 2*00 ;SET SCREEN TO 0TH COLUMN 0775 283D ^07B4$ JRZ :SET 0777 FE37 CMP '7' 0779 D0 RNC ;IF >3, NOT A SLIDING CHR 077A 0E52 LK C, VFLO + 2*52 ;SET 52ND COL 077C FE32 CMP '2' 077E 2834 ^07B4$ JRZ :SET 0780 0EBA LK C, VFLO + 2*104 ;SET 104TH COL 0782 FE33 CMP '3' 0784 282E ^07B4$ JRZ :SET 0786 F5 PUSH AF ;SAVE IT 0787 78 MOV A,B 0788 F608 OR 00001000B ;Y VALUE OF 8 ONE ; EXIT A = CHR (IF AVAILABLE) ; -2 (IF NO KEY PRESSED) 07C6 PROC 07C6 3AFF22 LD A, H.KEY + 0FFH ;READ ALL KEYBOARD PORTS 07C9 EEFF XOR 0FFH ;INVERT ALL BITS, SET FLAGS 07CB 3EFE LK A,-2 07CD C8 RZ ;IF NO KEY IS PRESSED 07CE 210122 LDK HL, H.KEY + 001H ;CONTROL KEY RANK 07D1 7D MOV A,L ;ADDR BYTE TO A 07D2 ED4F $ MOV R,A 07D4 7E LD A,[HL] ;READ CONTROL RANK 07D5 2F CMA ;COMPLEMENT THE 1S 07D6 325FEF STO A,CKEY ;SAVE FOR SHIFT & CTRL PROCS 07D9 E6E3 AND 1110_0011B ;CLEAR SHIFT, CNTRL, & ALPHA BITS 07DB 010007 LK BC,0700H ;LOOP 7 TIMES, C := 0 07DE 1808 ^07E8$ JR :MIDLE ;JUMP INTO MIDDLE OF :LOOP1 07E0 CB25 $ :LOOP1: SLA L ;SHIFT  072A 78 MOV A,B ;RESTORE CHR 072B 211007 LK HL,:TBL1-',' 072E FE30 CMP '/'+1 ;CK FOR 1ST GROUP 0730 3803 ^0735$ JRC :LOOK ;IF IN :TBL1 0732 210407 LK HL,:TBL2-'<' ;...ELSE IN :TBL2 0735 85 :LOOK: ADD L ;DO INDEXED LOAD FROM BASE IN HL 0736 6F MOV L,A 0737 3001 ^073A$ JRNC :GET 0739 24 INC H ;IF CARRY, PROPAGATE INTO H 073A 7E :GET: LD A,[HL] 073B C9 RET ; , - . / 073C 7B1F7D7E :TBL1: DB '{' , '_'-40H, '}' , '~' ; < = > ? 0740 7B607D7F :TBL2: DB ('{'), '`' , ('}'), 7FH 0744 SLIDE: ;PROCESS ^1, ^2, ^3, ^(LARROW), ^(RARROW) ; ENTRY A = CHR, CNTL KEY PRESSED ; EXIT 1) RET IF CHR NOT A SPECIAL SLIDI 078A 47 MOV B,A 078B F1 POP AF 078C 0EEA LK C, VFLO + 2*00 ;SET SCREEN TO 0TH COLUMN 078E FE34 CMP '4' 0790 2822 ^07B4$ JRZ :SET 0792 0E52 LK C, VFLO + 2*52 ;SET 52ND COL 0794 FE35 CMP '5' 0796 281C ^07B4$ JRZ :SET 0798 0EBA LK C, VFLO + 2*104 ;SET 104TH COL 079A 1818 ^07B4$ JR :SET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 47 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 079C :SLIDV: 079C 3A62EF LD A,PIABD ;ADD TO VIDEO BITS 079F E61F AND 00011111B 07A1 80 ADD A,B ;ADD NEW TO OLD 07A2 E61F AND 00011111B 07A4 47 MOV B,A 07A5 3A62EF LD A,PIABD ;LAST VALUE 07A8 E6E0 AND 11100000B ;CLEAR VIDIO BITS 07AA B0 OR B ;ADD NEW VIDIO OFFSET RANK-SELECT BIT LEFT 07E2 7D MOV A,L ;ADDR BYTE TO A 07E3 ED4F $ MOV R,A 07E5 7E LD A,[HL] ;READ RANK 07E6 EEFF XOR 0FFH ;INVERT 1S, SET FLAGS 07E8 2803 ^07ED$ :MIDLE: JRZ :2 ;IF NO KEY PRESSED IN THIS RANK 07EA 0D DEC C ;RECORD THAT A KEY WAS PRESSED 07EB 58 MOV E,B ;RECORD 7-RANK# OF KEY PRESSED 07EC 57 MOV D,A ;SAVE THE DATA READ 07ED 10F1 ^07E0$ :2: DJNZ :LOOP1 ;IF NOT FINISHED READING ALL RANKS 07EF 0C INC C ;CK FOR C = -1 07F0 2803 ^07F5$ JRZ :FBIT ;IF FOUND EXACTLY ONE KEY PRESS ;HERE IF FOUND 1) NO KEYS PRESSED ; 2) MANY (MORE THAN 1) KEYS PRESSED 07F2 3EFE LK A,-2 ;RETURN NO KEYS PRESSED 07F4 C9 RET ;HERE TO FINNG CHR ; 2) TO GKEYX AFTER ACTING ON SLIDING CHR 0744 PROC 0744 F5 PUSH AF 0745 3A62EF LD A,PIABD ;B=Y 0748 47 MOV B,A 0749 F1 POP AF SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 46 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 074A 0E02 LK C,+2 074C FE08 CMP MCLEFT ;LEFT ARROW 074E 285F ^07AF$ JRZ :SLIDH 0750 0EFE LK C,-2 0752 FE0C CMP MCRIGH ;RIGHT ARROW 0754 2859 ^07AF$ JRZ :SLIDH 0756 F5 PUSH AF 0757 3A61EF LD A,PIAAD ;C=X 075A 4F MOV C,A 075B F1 POP AF 075C 0601 LK B,+1 075E FE0B CMP MCUP ;UP ARROW 0760 283A ^079C$ JRZ :SLIDV 0762 06FF LK B,-1 0764 FE0A CMP MCDOWN ;DOWN ARROW 0766 2834 ^007AB 47 MOV B,A 07AC C3B407 JMP :SET 07AF 3A61EF :SLIDH: LD A,PIAAD ;OLD SCREEN OFFSET VALUE 07B2 81 ADD A,C 07B3 4F MOV C,A 07B4 :SET: 07B4 C5 PUSH BC ;SAVE Y 07B5 CDC508 CALL OPAD ;MOVE THE SCREEN 07B8 C1 POP BC 07B9 48 MOV C,B 07BA CDD208 CALL OPBD ;SET Y 07BD 3E01 LK A,1 07BF 325DEF STO A,HKCNT ;SHORT-CIRCUIT DEBOUNCE/AUTO-REPEAT ;DELAY LOGIC 07C2 D1 POP DE ;CLEAR STACK 07C3 C3C806 JMP GKEYX ;IGNORE RET-ADDR ON STK: ;STK WILL BE RESET ON NEXT IRUPT. SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 48 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 07C6 RDKEY: ;SCAN KEYBOARD ; ENTRY N%D THE KEY PRESSED IN A PARTICULAR RANK: ;LOAD UP THE APPROPRIATE TABLE ENTRY & RETURN. ; ENTRY D = DATA READ FROM KEYBOARD ; E = 7-RANK# OF ABOVE DATA 07F5 3E07 :FBIT: LK A,7 ;#RANKS 07F7 93 SUB E ;A = TABLE ROW TO USE )0..7) 07F8 17 RAL ! RAL ! RAL ;A := A * 8 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 49 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 07FB 4F MOV C,A 07FC 0600 LK B,0 ;BC = OFFSET INTO TABLE 07FE 211708 LK HL,T5KEY ;HL = FWA(TABLE) 0801 09 ADD HL,BC ;HL => RANK(KEY) SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 50 BMSCAN - KEYBOARD SCANNING & DECODE E:OCCROM3B.ASM 0802 7A MOV A,D ;RESTORE DATA FROM KEYBOARD 0803 010008 LK BC, 0800H ;B := 8, C := 0  ; Entry C= ascii char ; Exit A = char 0857 79 MOV A,C 0858 D630 SUI '0' 085A FE0A CPI 9+1 085C F8 RM 085D D607 SUI 7 085F C9 RET 0860 DELAY: ;'N' Milliseconds ; Entry A=Number of Milliseconds to delay ; SCLFRE= (Freq/1000)/25 ; Exit Time passed. 0860 Proc 0860 C5 PUSH BC 0861 4F MOV C,A 0862 3EA0 :1: LDK A,SCLFRE 0864 3D :2: DEC A ;(4 tics) 0865 40 MOV B,B ;(4 tics) 0866 49 MOV C,C ;(4 tics) 0867 C26408 JNZ :2 ;(10 tics) If 1 ms not elapsed 086A 0D DEC C 086B C26208 JNZ :1 ;If requested msec not done 086E C1 POP BC ;restore registers 086F C9 RET ;SCLFRE: = 2000/22B 13 INC DE 089C F1 POP AF 089D F28208 JP OSTR ;if not done 08A0 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 53 Hardware PIO function processors. E:OCCROM4B.ASM 08A1 ESTR: ;Output ENCODED string to console ; Entry DE=FWA of source 08A1 B7 OR A ;clear cbit 08A2 1A LD A,[de] 08A3 0F RRC ;normalize char 08A4 F5 PUSH AF 08A5 E67F AND 07Fh 08A7 4F MOV C,A 08A8 CD0703 CALL CO ;output it 08AB 13 INC DE 08AC F1 POP AF 08AD 30F2 ^08A1$ JRNC ESTR ;if not done 08AF C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 54 Hardware PIO function processors. E:OCCROM4B.ASM = 0000 .old IF FALSE .old ENDIF 08B0  0806 0F :LOOP2: RRC ;SHIFT CORRESPONDING BIT INTO CY 0807 3002 ^080B$ JRNC :3 ;IF DIDN'T FIND BIT THIS TIME THRU 0809 0D DEC C ;...ELSE RECORD THAT A KEY WAS PRESSED ; MOV E,B ;DON'T NEED TO SAVE LOOP-INDEX 080A 56 LD D,[HL] ;GET CHR FROM TABLE 080B 23 :3: INC HL ;...ELSE TRY NEXT CHR & BIT 080C 10F8 ^0806$ DJNZ :LOOP2 080E 0C INC C 080F CA1508 JZ :EXIT 0812 3EFE LDK A,-2 0814 C9 RET 0815 7A :EXIT: MOV A,D ;RETURN CHR IN A 0816 C9 RET 0817 T5KEY: 0817 1B097F7F7F T6KEY: DB ESC, TAB, ERC, ERC, ERC, CR, '''', '[' 081F 3132333435 DB '1', '2', '3', '4', '5', '6', '7', '8' 0827 5157455254 DB 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I' 082F 4153444647 DB 'A', 'S', ;Z80, 2mhz ;...defined in OCCTXT.ast SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 52 Hardware PIO function processors. E:OCCROM4B.ASM 0870 FILLZ: ;Fill block of memory with byte value. ; Entry DE=LENGTH TO broadcast character ; C =character TO broadcast ; HL=FWA TO START broadcast ; EXIT FILL DONE 0870 0E00 LK C,0 ;FILL WITH ZERO = 0000 .old IF FALSE ; 8080 version .old ENDIF 0872 7B FILLC: MOV A,E 0873 B2 OR D 0874 C8 RZ ; return here if broadcast 0 bytes 0875 71 STO C,[hl] ; 1st byte 0876 1B DEC DE 0877 7B MOV A,E 0878 B2 OR D 0879 C8 RZ ; return here if broadcast 1 byte 087A 42 MOV B,D 087B 4B MOV C,E ; BC := (count) 087C 54  SPAO: ;Set PIA for output 08B0 3E03 LDK A,03h ;CRA1-0, Interrupt inputs CA1 08B2 32012C STO A,H.VIO+1 ;set data direction 08B5 3EFF LDK A,0FFh 08B7 32002C STO A,H.VIO ;set all A lines as output 08BA 3E00 LDK A,0 08BC 32032C STO A,H.VIO+3 08BF 3EFF LDK A,0FFh 08C1 32022C STO A,H.VIO+2 ;set all B lines as output 08C4 C9 RET 08C5 OPAD: ;Output data to pia A register ; Entry C= data ; Exit PIAAD = new value 08C5 3E07 LDK A,4+3 08C7 32012C STO A,H.VIO+1 08CA 79 MOV A,C 08CB 3261EF STO A,PIAAD 08CE 32002C STO A,H.VIO ;send data 08D1 C9 RET 08D2 OPBD: ;Output data to pia B register ; PIA definition. ; 7 6 5 4 3 2 1 0 ; +--+--+--+--+--+--+--+--+ ; |D1|D0 'D', 'F', 'G', 'H', 'J', 'K' 0837 5A58435642 DB 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',' 083F 0B0830202E DB MCUP, BKS, '0', ' ', '.', 'P', 'O', '9' 0847 0C0A2D2F3B DB MCRIGH, LF, '-', '/', ';', '\', 'L', '=' ; ENDX BMSCAN.ASM SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 51 Hardware PIO function processors. E:OCCROM4B.ASM 084F CDEHL: ;Compare DE to HL as unsigned integers. ; Entry DE,HL set to values to compare ; Exit Zbit set if DE = HL ; Cbit set if DE < HL. ; Uses AF. 084F 7A MOV A,D 0850 BC CMP H 0851 C0 RNZ ;If D .ne. H 0852 7B MOV A,E 0853 BD CMP L 0854 C0 RNZ ;if DE .ne. HL 0855 37 STC 0856 C9 RET 0857 CNVBN: ;Convert Ascii to binary  MOV D,H 087D 5D MOV E,L 087E 13 INC DE ; DE := HL + 1 087F EDB0 $ LDIR ; overlapping move 0881 C9 RET 0882 OSTR: ;Output string to console ; Entry DE=FWA of source ; Note : OSTR recognizes 7F as an escape sequence ; to repeat char N times. Format is: ; 7F, Repeat count, Char 0882 proc 0882 1A LD A,[de] 0883 B7 OR A 0884 F5 PUSH AF 0885 E67F AND 07Fh 0887 FE7F CMP 07Fh 0889 4F MOV C,A 088A 200C ^0898$ JRNZ :4 ;if not repeat 088C 13 INC DE ! LD A,[de] ! DEC A 088F 47 MOV B,A ;repeat count 0890 13 INC DE ! LD A,[de] ;get repeat char 0892 4F MOV C,A 0893 CD0703 :2: CALL CO ;output char 0896 10FB ^0893$ DJNZ :2 ;if not done 0898 CD0703 :4: CALL CO ;output it 089&|^G| vert offset | ; +--+--+--+--+--+--+--+--+ ; ; Entry C= data ; Exit PIABD = new value 08D2 3E04 LDK A,4 08D4 32032C STO A,H.VIO+3 08D7 79 MOV A,C 08D8 3262EF STO A,PIABD 08DB 32022C STO A,H.VIO+2 ;send data 08DE C9 RET ; endx BMpio SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 55 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ; +---------------------------------------+ ; | ENTERED 05/01/81 FROM TNW XEROX, SEH. | ; +---------------------------------------+ ; ;LAST EDITED AT 09:29 ON 11 NOV 80 ; ;THERE ARE FOUR COMMANDS TO THE 6821  ;CPDRA SOURCE DIRECTION 1111_1111 ; DATA DATA ; ;CPDRA ACCEPTOR DIRECTION 1111_1111 ; DATA 1111_1111 ; ;CPDRB SOURCE DIRECTION 0011_1111 ; DATA 000A_0010 ;A = ATN ; ;CPDRB ACCEPTOR DIRECTION 1101_0111 ; DATA 0100_0101 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 56 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;PIA SIGNAL DEFINITIONS: ;ALL SIGNALS ARE LOW ON THE IEEE BUS WHEN PIA REGISTER CONTAINS "1". ; ; PA0 DIO 1 ; PA1 DIO 2 ; PA2 DIO 3 ; PA3 DIO 4 ; PA4 DIO 5 ; PA5 DIO 6 ; PA6 DIO 7 HANDSHAKE MODE ; ;PARAMETER PASSED IN REGISTER C: ; ; BIT 0 IF "1", THE IFC SIGNAL IS SET LOW FOR 101 MICRO-SEC ; AND ALL PIA SIGNALS ARE INITIALIZED ; ; BIT 2 1 ; 0 X NO ACTION ; 1 0 SETS REN HIGH ; 1 1 SETS REN LOW ; 08DF IE.CO: PROC 08DF F5 PUSH AF 08E0 E5 PUSH HL 08E1 CB41 $ BIT 0,C ;CHECK IFC SUB-COMMAND 08E3 282B ^0910$ JRZ :B1C20 ;INITIALIZE ALL IEEE-488 SIGNALS 08E5 210129 LK HL,CCRA 08E8 363A STO 0011_1010B,[HL] ;ENABLE SRQ AND SET IFC-OUT LOW 08EA 3EFF LK A,1111_1111B ;DIRECT DATA OUT 08EC 320029 STO A,CPDRA 08EF 363E STO 0011_1110B,[HL] 08F1 AF XOR A ;SET DATA TO ZERO 08F2 320029  ; ; 00 PERIPHERAL/DIRECTION REGISTER A CPDRA ; 01 CONTROL REGISTER A CCRA ; 10 PERIPHERAL/DIRECTION REGISTER B CPDRB ; 11 CONTROL REGISTER B CCRB ; ;BIT 2 OF THE CONTROL REGISTER (A AND B) ALLOWS SELECTION OF EITHER ;A PERIPHERAL INTERFACE REGISTER OR A DATA DIRECTION REGISTER. ;A "1" IN BIT 2 SELECTS THE PERIPHERAL REGISTER. ; ;THE TWO DATA DIRECTION REGISTERS ALLOW CONTROL OF THE DIRECTION ;OF DATA THROUGH EACH CORRESPONDING PERIPHERAL DATA LINE. ;A DATA DIRECTION REGISTER BIT SET AT "0" CONFIGURES ;THE CORRESPONDING PERIPHERAL DATA LINE AS AN INPUT. ; ;A RESET AT POWER UP HAS THE EFFECT OF ZEROING ALL PIA REGISTERS. ;THIS WILL SET PA0-PA7, PB0-PB7, CA2, AND CB2 A ; PA7 DIO 8 ; ; CA1 SRQ ; CA2 IFC ; ; PB0 ENABLE DATA OUT (ENABLED WHEN "0") ; PB1 ENABLE NDAC/NRFD (ENABLED WHEN "0") ; PB2 ENABLE EOI/DAV (ENABLED WHEN "0") ; PB3 EOI ; PB4 ATN ; PB5 DAV ; PB6 NDAC ; PB7 NRFD ; ; CB1 NOT USED ; CB2 REN ; ;CONTROL WORD FORMAT ; ;[ 7 ][ 6 ][ 5 ][ 4 ][ 3 ][ 2 ][ 1 ][ 0 ] ; ;[IRQA1][IRQA2][ CA2 CONTROL ][ DDRA][ CA1 CONTROL] ;[IRQB1][IRQB2][ CB2 CONTROL ][ DDRB][ CB1 CONTROL] ; ; IRQA1 0 INTERRUPT FLAG SET BY FALL OF SRQ ; IRQA2  STO A,CPDRA 08F5 210329 LK HL,CCRB 08F8 3630 STO 0011_0000B,[HL] ;SET REN-OUT HIGH 08FA 3E3F LK A,0011_1111B ;DIRECTION FOR SOURCE HANDSHAKE 08FC 320229 STO A,CPDRB 08FF 3634 STO 0011_0100B,[HL] 0901 3E02 LK A,0000_0010B ;VALUES FOR SOURCE HANDSHAKE 0903 320229 STO A,CPDRB ;LEAVE IFC LOW FOR 100 MICRO-SEC 0906 3E19 LK A,25 ;DELAY 100 MICRO-SEC 0908 3D :B1C10: DEC A 0909 20FD ^0908$ JRNZ :B1C10 090B 3E36 LK A,0011_0110B ;SET IFC HIGH 090D 320129 STO A,CCRA 0910 CB51 $ :B1C20: BIT 2,C ;CHECK REN SUB-COMMAND 0912 280B ^091F$ JRZ :B1C40 ;SET/CLEAR REN 0914 3E30 LK A,0011_0000B 0916 CB49 $ BIT 1,C 0918 2802 ^091C$ JRZ :B1C30 091A 3E38 LK A,0011_1000B 091C 320329 :B1C30: STO A,CCRB 091F E1 :B1C40: POP HL 0920 F1 S INPUTS, ;AND ALL INTERRUPTS DISABLED. ;SIGNALS ATN, REN, AND IFC WILL BE DRIVEN LOW ;UNTIL INITIALIZED BY SOFTWARE. ; ;DATA DIRECTION IS ALWAYS SET FOR OUTPUT FOR THE DATA REGISTER. ;DATA MUST BE SET TO ALL ONES WHEN INPUTTING. ;THE INTERFACE IS IN SOURCE HANDSHAKE MODE IF DATA ENABLE (PB0) ;IS SET TO "0", AND IN ACCEPTOR HANDSHAKE MODE IF SET TO "1". ;WHEN SWITCHING FROM SOURCE TO ACCEPTOR HANDSHAKE, ;ATN WILL ALWAYS BE LOW. ;TAKE CONTROL CAN ONLY BE CALLED FOLLOWING A GO TO STANDBY. ;AFTER A FATAL ERROR, PERFORM AN IFC RESET. ; ;STANDARD VALUES USED: ; ;CCRA 0011(IFC)(DIR)10 ; ;CCRB 0011(REN)(DIR)00 ; 0 NOT USED ; CA2 110 SET IFC HIGH ; 111 SET IFC LOW ; DDRA 0 R/W DATA DIRECTION REGISTER A ; 1 R/W PERIPHERAL REGISTER A ; CA1 10 SET IRQA1 HIGH ON RISE OF SRQ ; ; IRQB1 0 NOT USED ; IRQB2 0 NOT USED ; CB2 110 SET REN HIGH ; 111 SET REN LOW ; DDRB 0 R/W DATA DIRECTION REGISTER B ; 1 R/W PERIPHERAL REGISTER B ; CB1 00 NOT USED SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 57 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;BIOS CALL 1: CONTROL OUT ; ; CAN BE CALLED WHILE IN ANY STATE. ; ; EXITS IN THE CONTROLLER STANDBY STATE (ATN HIGH), ; SOURCE ' POP AF 0921 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 58 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;BIOS CALL 2: STATUS IN ; ; CAN BE CALLED ONLY WHILE IN SOURCE HANDSHAKE MODE. ; ;BIT 0 OF REGISTER A SET IF SRQ IS LOW ; 0922 IE.SI: PROC 0922 E5 PUSH HL 0923 3A0029 LD A,CPDRA ;CLEAR IRQA1 0926 210229 LK HL,CPDRB ;PULSE ENABLE DAV/EOI 0929 CB96 $ CBIT 2,[HL] 092B CBD6 $ SBIT 2,[HL] 092D 3A0129 LD A,CCRA ;SET SRQ VALUE IN A 0930 E680 AND 1000_0000B 0932 07 RLC A 0933 E1 POP HL 0934 C9 RET ;BIOS CALL 3: GO TO STANDBY ; ; CAN BE CALLED ONLY WHILE IN SOURCE HANDSHAKE MODE T 4,[HL] ;SET ATN LOW ;SET-UP FOR SOURCE HANDSHAKE 096D 3A0329 LD A,CCRB 0970 CB97 $ CBIT 2,A 0972 320329 STO A,CCRB 0975 363F STO 0011_1111B,[HL] ;DIRECTION REGISTER 0977 CBD7 $ SBIT 2,A 0979 320329 STO A,CCRB 097C 3612 STO 0001_0010B,[HL] ;CONTROL SIGNAL INITIAL VALUE 097E AF XOR A ;CLEAR ERROR CODE 097F E1 :B4C40: POP HL 0980 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 60 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;BIOS CALL 5: OUTPUT INTERFACE MESSAGE ; ; CAN BE CALLED WHILE IN ANY MODE OR STATE ; ; EXITS IN THE SOURCE HANDSHAKE MODE WITH ATN LOW. ; ;MULTI-LINE MESSAGE IN REGISTER C ;  CB7E $ :B6C20: BIT 7,[HL] 09BC 2807 ^09C5$ JRZ :B6C30 ;READY FOR DATA 09BE 3D DEC A 09BF 20F9 ^09BA$ JRNZ :B6C20 ;WAIT FOR 100 MICRO-SEC 09C1 3E82 LK A,1000_0010B ;SET RFD TIMEOUT ERROR 09C3 181F ^09E4$ JR :B6C80 09C5 CB76 $ :B6C30: BIT 6,[HL] 09C7 2004 ^09CD$ JRNZ :B6C40 ;DATA ACCEPTED LOW 09C9 3E81 LK A,1000_0001B ;SET DEVICE NOT PRESENT ERROR 09CB 1817 ^09E4$ JR :B6C80 09CD CBEE $ :B6C40: SBIT 5,[HL] ;SET DAV LOW 09CF 3EFF :B6C50: LK A,255 09D1 CB76 $ :B6C60: BIT 6,[HL] 09D3 2807 ^09DC$ JRZ :B6C70 ;DATA ACCEPTED 09D5 3D DEC A 09D6 20F9 ^09D1$ JRNZ :B6C60 ;WAIT 1000 MICRO-SEC 09D8 3E84 LK A,1000_0100B ;SET DAC TIMEOUT ERROR 09DA 1808 ^09E4$ JR :B6C80 09DC CBAE $ :B6C70: CBIT 5,[HL] ;SET DAV HIGH 09DE CB9E $ CBIT 3,[HL] ;SET EOI HIGH 09E0 AF XOR A ;REMOVE  ; ;NO PARAMETERS PASSED ; 0935 IE.GTS: PROC 0935 F5 PUSH AF 0936 3E02 LK A,0000_0010B ;SET ATN HIGH 0938 320229 STO A,CPDRB 093B AF XOR A ;FLOAT DATA BUS 093C 320029 STO A,CPDRA 093F F1 POP AF 0940 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 59 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;BIOS CALL 4: TAKE CONTROL ; ; CAN BE CALLED ONLY WHILE IN THE CONTROLLER STANDBY STATE ; (ATN HIGH). ; ; EXITS IN THE CONTROLLER ACTIVE STATE (ATN LOW), ; SOURCE HANDSHAKE MODE. ; ;BIT 0 OF REGISTER C SET TO TAKE CONTROL ASYNCHRONOUS ; ;ERROR CODE RETURNED IN REGISTER ;ERROR CODE RETURNED IN REGISTER A ; 0981 IE.OIM: PROC 0981 E5 PUSH HL 0982 210229 LK HL,CPDRB 0985 CBE6 $ SBIT 4,[HL] ;SET ATN LOW 0987 CB46 $ BIT 0,[HL] 0989 2825 ^09B0$ JRZ IE.SHK ;SET-UP FOR SOURCE HANDSHAKE 098B 3617 STO 0001_0111B,[HL] ;DISABLE DRIVERS 098D 3A0329 LD A,CCRB 0990 CB97 $ CBIT 2,A 0992 320329 STO A,CCRB 0995 363F STO 0011_1111B,[HL] ;DIRECTION REGISTER 0997 CBD7 $ SBIT 2,A 0999 320329 STO A,CCRB 099C AF XOR A ;FLOAT EXTERNAL DATA BUS 099D 320029 STO A,CPDRA 09A0 3612 STO 0001_0010B,[HL] ;CONTROL SIGNAL INITIAL VALUE 09A2 180C ^09B0$ JR IE.SHK SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 61 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;BIOS CALL 6: OUTPDATA FROM BUS 09E1 320029 STO A,CPDRA 09E4 E1 :B6C80: POP HL 09E5 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 62 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM ;BIOS CALL 7: INPUT DEVICE MESSAGE ; ; CAN BE CALLED WHILE IN ANY MODE OR STATE ; ; EXITS IN THE ACCEPTOR HANDSHAKE MODE WITH ATN HIGH. ; ;DEVICE MESSAGE RETURNED IN BOTH REGISTERS A AND H ;ERROR CODE RETURNED IN REGISTER L ; 09E6 IE.IDM: PROC 09E6 D5 PUSH DE 09E7 EB EX DE,HL ;SAVE RE-ENTRY DATA 09E8 210229 LK HL,CPDRB 09EB CB46 $ BIT 0,[HL] 09ED 201A ^0A09$ JRNZ :B7C10 ;SET-UP FOR ACCEPTOR HANDSHAKE 09EF 3617 STO 0001_0111B,[HL]  A. ; 0941 IE.TC: PROC 0941 E5 PUSH HL 0942 210229 LK HL,CPDRB 0945 CB41 $ BIT 0,C 0947 2022 ^096B$ JRNZ :B4C30 ;TAKE CONTROL SYNCHRONOUSLY 0949 3607 STO 0000_0111B,[HL] ;DISABLE DRIVERS 094B 3A0329 LD A,CCRB 094E CB97 $ CBIT 2,A 0950 320329 STO A,CCRB 0953 36D7 STO 1101_0111B,[HL] ;DIRECTION REGISTER 0955 CBD7 $ SBIT 2,A 0957 320329 STO A,CCRB 095A 3685 STO 1000_0101B,[HL] ;SET NRFD LOW 095C 3E19 LK A,25 095E CB6E $ :B4C10: BIT 5,[HL] 0960 2807 ^0969$ JRZ :B4C20 ;DATA VALID HAS DROPPED 0962 3D DEC A 0963 20F9 ^095E$ JRNZ :B4C10 ;WAIT 100 MICRO-SEC 0965 3E81 LK A,1000_0001B ;SET DATA VALID TIMEOUT ERROR 0967 1816 ^097F$ JR :B4C40 0969 36C5 :B4C20: STO 1100_0101B,[HL] ;SET NDAC LOW 096B CBE6 $ :B4C30: SBIUT DEVICE MESSAGE ; ; CAN BE CALLED ONLY WHILE IN THE SOURCE HANDSHAKE MODE ; WITH ATN HIGH OR LOW. ; ; EXITS IN THE SOURCE HANDSHAKE MODE WITH ATN HIGH. ; ;MULTI-LINE MESSAGE IN REGISTER C ;EOI REQUEST IN REGISTER B ; ;ERROR CODE RETURNED IN REGISTER A ; 09A4 IE.ODM: PROC 09A4 E5 PUSH HL 09A5 210229 LK HL,CPDRB 09A8 CBA6 $ CBIT 4,[HL] ;SET ATN HIGH 09AA CB40 $ BIT 0,B ;CHECK IF EOI REQUESTED 09AC 2802 ^09B0$ JRZ IE.SHK 09AE CBDE $ SBIT 3,[HL] ;PERFORM SOURCE HANDSHAKE 09B0 CB6E $ IE.SHK: BIT 5,[HL] ; 09B2 201B ^09CF$ JRNZ :B6C50 ;DAC TIMEOUT RE-ENTRY 09B4 79 MOV A,C ;PLACE DATA ON BUS 09B5 320029 STO A,CPDRA 09B8 3E0A LK A,10 09BA(;DISABLE DRIVERS 09F1 3A0329 LD A,CCRB 09F4 CB97 $ CBIT 2,A 09F6 320329 STO A,CCRB 09F9 36D7 STO 1101_0111B,[HL] ;DIRECTION REGISTER 09FB CBD7 $ SBIT 2,A 09FD 320329 STO A,CCRB 0A00 3EFF LK A,1111_1111B ;FLOAT INTERNAL DATA BUS 0A02 320029 STO A,CPDRA 0A05 3655 STO 0101_0101B,[HL] ;CONTROL SIGNALS INITIAL VALUE 0A07 3645 STO 0100_0101B,[HL] ;SET ATN HIGH ;PERFORM ACCEPTOR HANDSHAKE 0A09 CB76 $ :B7C10: BIT 6,[HL] 0A0B 2820 ^0A2D$ JRZ :B7C50 ;DATA INVALID TIMEOUT ERROR RE-ENTRY 0A0D CBBE $ CBIT 7,[HL] ;SET NRFD HIGH 0A0F 3E0A LK A,10 0A11 CB6E $ :B7C20: BIT 5,[HL] 0A13 2008 ^0A1D$ JRNZ :B7C30 ;DATA VALID 0A15 3D DEC A 0A16 20F9 ^0A11$ JRNZ :B7C20 ;WAIT 100 MICRO-SEC 0A18 118200 LK DE,1000_0010B ;SET DATA VALID TIMEOUT ERROR 0A1B 1821 ^0A3E$ JR :B7C80 0 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 64 SIO - Serial I/O Processors. E:OCCROM5B.ASM 0A57 SIRST: ;Master reset SIO ; Entry C= SI.S16 or SI.S64 for 1200/300 baud 0A57 3E57 LDK A,SI.MRST 0A59 32002A STO A,H.SCTRL ;master reset 0A5C 00 NOP ! NOP ! NOP 0A5F 79 MOV A,C 0A60 32C1EF STO A,ACIAD ;last-command cell 0A63 32002A STO A,H.SCTRL ;select SIO 0A66 C9 RET 0A67 READER: ;Input one byte from reader port ; Entry None ; Exit A=C= character read 0A67 3A002A LD A,H.SSTS ; MOV B,A ;save status 0A6A E601 AND SI.RRDY ; LD A,H.SREC ;clear ~DCD 0A6C 28F9 ^0A67$ JRZ READER ;if not ready 0A6E 3A012A LD A,H.SREC ;get data 0A71 4F MOV C,A ;A=C KB = 3125... = 0004 NRTRYS = 4 ;Number of retries = 0010 MSECB = 10h ;Multi-sector r/w bit ; Function codes = 000C D.RES = 00h+0Ch ;restore = 0018 D.SEK = 10h+08h ;seek = 0020 D.STP = 20h ;step = 0040 D.STPI = 40h ;Step IN = 0060 D.STPO = 60h ;Step out = 0080 D.RDS = 80h ;Read sector = 00A4 D.WRTS = 0A0h+DML ;Write sector = 00C4 D.RDA = 0C0h+DML ;read address = 00E4 D.RDT = 0E0h+DML ;read track = 00F4 D.WRTT = 0F0h+DML ;write track = 00D0 D.FINT = 0D0h ;Force interrupt ; Disk status and command registers = 2100 D.CMDR = H.FDC ;Disk command reg (write) = 2100 D.STSR = H.FDC ;Status reg (read) = 2101 D.TRKR = D.CMDR+1 ;track reg = 2102 D.SECR = D.CMDR+2 ;Sector reg = 2103 A1D CBFE $ :B7C30: SBIT 7,[HL] ;SET NRFD LOW 0A1F 3A0029 LD A,CPDRA ;READ DATA 0A22 57 MOV D,A 0A23 1E00 LK E,0 ;READ EOI 0A25 CB5E $ BIT 3,[HL] 0A27 2802 ^0A2B$ JRZ :B7C40 0A29 1E01 LK E,1 0A2B CBB6 $ :B7C40: CBIT 6,[HL] ;SET NDAC HIGH 0A2D 3EFF :B7C50: LK A,255 0A2F CB6E $ :B7C60: BIT 5,[HL] 0A31 2809 ^0A3C$ JRZ :B7C70 ;DATA VALID DROPPED 0A33 3D DEC A 0A34 20F9 ^0A2F$ JRNZ :B7C60 ;WAIT 1000 MICRO-SEC 0A36 CBD3 $ SBIT 2,E ;SET DATA INVALID TIMEOUT ERROR 0A38 CBFB $ SBIT 7,E 0A3A 1802 ^0A3E$ JR :B7C80 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 63 BMIEEE.ASM - IEEE-488 INTERFACE. E:OCCROM4B.ASM 0A3C CBF6 $ :B7C70: SBIT 6,[HL] ;SET NDAC LOW 0A3E EB :B7C80: EX DE,HL ;MOVE RESULTS TO REGISTERS A AND HL 0A3F 7C MOV A,H 0A40 D1  ; LK A,SI.RERR ;error check ; AND B ;...with status ; MOV A,C ;recover data ; RZ ;if OK ; STC ;...else error 0A72 C9 RET 0A73 SLST: ;Get list device status ; Exit A= 0, if NOT ready 0A73 3A002A LD A,H.SSTS 0A76 E602 AND SI.TRDY ;ck for Xmit buf empty 0A78 C9 RET ;set status 0A79 LIST: ;Output one byte to list port 0A79 PUNCH: ;Output one byte to punch port ; Entry C= character to output ; Exit C=C. ; LD A,ACIAD ;get last command byte ; CBIT 6,A ;...invert RTS status ; STO A,H.SCTRL ;make request (~RTS := low) 0A79 3A002A :wait: LD A,H.SSTS 0A7C E602 AND SI.TRDY ;wait for CTS go-ahead 0A7E 28F9 ^0A79$ JRZ :wait ;if CTS hig D.DATR = D.CMDR+3 ;Data reg (r/w) ; Status definitions = 0000 BS.BSY = 0 ;Busy = 0001 DS.BSY = 1 shl BS.BSY = 0001 BS.DRQ = 1 = 0002 DS.INX = 1 shl BS.DRQ ;Index mark detected = 0002 DS.DRQ = DS.INX ;DR is full on read, empty on write = 0002 BS.TK0 = 2 = 0004 DS.TK0 = 1 shl BS.TK0 = 0004 DS.LSD = DS.TK0 ;lost data = 0008 DS.CRC = 08h ;CRC error in ID field = 0004 BS.SEK = 4 = 0010 DS.SEK = 1 shl BS.SEK ;Seek error = 0010 DS.RNF = DS.SEK ;Record NOT found = 0020 DS.HDL = 20h ;Head loaded = 0020 DS.WTF = DS.HDL ;Write fault = 0040 DS.WTP = 40h ;Write protected = 0080 DS.NRY = 80h ;Drive NOT ready  POP DE 0A41 C9 RET ;BIOS CALL 8: PARALLEL POLL ; ; CAN BE CALLED ONLY WHILE IN THE SOURCE HANDSHAKE MODE ; WITH ATN HIGH OR LOW. ; ; EXITS IN THE SOURCE HANDSHAKE MODE WITH ATN LOW. ; ;PARALLEL POLL VALUE RETURNED IN A. ; 0A42 IE.PP: PROC 0A42 E5 PUSH HL 0A43 210029 LK HL,CPDRA 0A46 3E1B LK A,0001_1011B ;FORM PARALLEL POLL 0A48 320229 STO A,CPDRB 0A4B 36FF STO 1111_1111B,[HL] ;FLOAT INTERNAL DATA BUS 0A4D 7E LD A,[HL] ;READ PARALLEL POLL DATA 0A4E 3600 STO 0,[HL] ;RE-STORE SOURCE HANDSHAKE MODE 0A50 210229 LK HL,CPDRB 0A53 3612 STO 0001_0010B,[HL] 0A55 E1 POP HL 0A56 C9 RET ; ENDX BMIEEE.ASM h, wait again 0A80 79 MOV A,C 0A81 32012A STO A,H.SXMT ;send chr SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 65 SIO - Serial I/O Processors. E:OCCROM5B.ASM ; NOP ! NOP ! NOP ;...wait... ; LD A,ACIAD ;get last command ; STO A,H.SCTRL ;set RTS high (no request) 0A84 C9 RET ; Endx BMSIO.asm SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 66 Disk I/O routines. E:OCCROM6B.ASM ; Disk interface definitions and functions. ; 1792 functions. = 0004 DML = 4 ;= 15 ms delay on function = 0C35 LTRKB = 3125 ;length of a track ; Note: Shugart says LTR) ; Disk timing counts = 0014 D.DEL = 20 ;Delay after function SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 67 Disk I/O routines. E:OCCROM6B.ASM 0A85 SDMA: ;Set DMA 0A85 SETDMA: ; Entry BC = DMA address 0A85 ED430FEF $ STO BC,DMADR 0A89 C9 RET 0A8A SETTRK: ;Set track ; Entry BC = track 0A8A ED4315EF $ STO BC,SAVTRK 0A8E C9 RET 0A8F SETSEC: ;Set Sector ; Entry C= sector number (1 to MSEC) 0A8F 79 MOV A,C 0A90 3214EF STO A,SAVSEC 0A93 C9 RET 0A94 HOME: ;Home selected disk drive 0A94 010000 LDK BC,0 0A97 C38A0A JMP SETTRK ;reset track to 0 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 68 ,5 ;number of tries 0AD3 3EFA :5: LDK A,250 0AD5 CD6008 CALL DELAY 0AD8 3EFA LK A,250 ;2nd delay 0ADA CD6008 CALL DELAY 0ADD 3A0021 LD A,D.STSR 0AE0 E602 AND DS.INX 0AE2 C8 RZ ;if index 0AE3 10EE ^0AD3$ DJNZ :5 ;keep trying 0AE5 F682 OR 80h or DS.INX ;indicate NOT ready 0AE7 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 69 Disk I/O routines. E:OCCROM6B.ASM 0AE8 DDRV: ;Deselect drive ; Entry SDISK = current disk drive 0AE8 3A62EF LD A,PIABD 0AEB E61F AND 1_1111b 0AED 4F MOV C,A 0AEE C3D208 JMP OPBD ;deselect last drive SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 70 Disk I/O routines. E:OCCROM6B.ASM 0AF1 PSEKC: ;Perform seek typ, if no error, else status ; MUST NOT destroy DE, HL pair 0B26 proc 0B26 CD9A0A CALL SDRV ;select drive ; Here if drive already selected ; Check to see if SEEK is necessary by ; comparing SAVTRK to controller track ; register 0B29 3A15EF SEEKN: LD A,SAVTRK 0B2C 320321 STO A,D.DATR ;set track wanted 0B2F 4F MOV C,A 0B30 3A0121 LD A,D.TRKR 0B33 B9 CMP C 0B34 2828 ^0B5E$ JRZ :8 ;if on track ; Disk seek required, function controller ; with SEEK command 0B36 3E05 LDK A,5 0B38 3205EF SEEKA: STO A,RTRY ;update retry count 0B3B 3E18 LDK A,D.SEK 0B3D CDF10A CALL PSEKC ;perform seek command 0B40 4F MOV C,A 0B41 E618 AND DS.CRC or DS.SEK 0B43 2014 Disk I/O routines. E:OCCROM6B.ASM 0A9A SDRV: ;Select Drive ; Entry SDISK= drive ; Exit A= 0, if drive is ready ; Calls OPBD, DELAY ; Uses A,B 0A9A proc 0A9A 3A17EF LD A,SDISK 0A9D 21C7EF SDRV1: LK HL,DSKSWP ;disk drive swap cell 0AA0 AE XOR [hl] ;swap A for B if DSKSWP=1 0AA1 E601 AND 1 ;Can only be 0 or 1 0AA3 FE01 CMP 1 0AA5 2002 ^0AA9$ JRNZ :2 ;if not drive 1 0AA7 3E40 LDK A,40h 0AA9 C640 :2: ADI 40h 0AAB 4F MOV C,A 0AAC 3A62EF LD A,PIABD 0AAF 47 MOV B,A 0AB0 E6C0 AND 1100_0000b ;get drive bits only 0AB2 B9 CMP C 0AB3 CA600C JZ RDSKD ;if drive already selected ; Check to see if this drive is the same as the last ; one see command ; Entry A= command to perform without r1, and r0. ; PSEKC will or in the low two bits as defined ; by SEKDEL. ; Exit A= last value of D.STSr 0AF1 2113EF LDK HL,SEKDEL 0AF4 B6 OR [hl] ;or in delay time for seek 0AF5 CD200C CALL FDSK ;function disk 0AF8 C0 RNZ ;if Drive NOT ready 0AF9 C3470C JMP WBUSY 0AFC SELDSK: ;Select disk in register C 0AFC 79 MOV A,C ;drive to home 0AFD CD9D0A CALL SDRV1 ;C= drive 0B00 1803 ^0B05$ JR HOMED1 0B02 HOMED: ;Home disk drive ; Entry SDISK= drive ; Exit A=0 if drive on home. 0B02 proc 0B02 CD9A0A CALL SDRV ;select drive 0B05 3E0C HOMED1: LDK A,D.RES 0B07 CDF10A CALL PSEKC ;perform seek command 0B0A FEFF CMP -1 0B0C 2809 ^0B17$ ^0B59$ JRNZ :10 ;if error ; Now read-address and verify on-track 0B45 CD6C0B CALL DRDAS ;read address 0B48 200F ^0B59$ JRNZ :10 ;if error 0B4A 2109EF LDK HL,DSTSB 0B4D 3A15EF LD A,SAVTRK 0B50 BE CMP [hl] 0B51 280B ^0B5E$ JRZ :8 ;if ON track 0B53 3A05EF LD A,RTRY 0B56 3D DEC A 0B57 20DF ^0B38$ JRNZ SEEKA ;if not max retrys ; here if seek error 0B59 79 :10: MOV A,C 0B5A F680 ORI 80h ;indicate movement error 0B5C 18B9 ^0B17$ JR SKEX1 ; Now set the sector register to requested ; Sector 0B5E CD470C :8: CALL WBUSY ;wait for FDC quiescence 0B61 3A14EF LD A,SAVSEC 0B64 320221 STO A,D.SECR ;set sector register 0B67 AF XRA A ;indicate good 0B68 C9 RET lected. ; IF true, go to 3 ; else ; Save current trk register in LDSEL and ; set trk reg to last track used for newly selected ; drive ; end 0AB6 3A6DEF LD A,LDSEL ;last selected disk 0AB9 B9 CMP C 0ABA 2812 ^0ACE$ JRZ :3 ;if same drive 0ABC 79 MOV A,C 0ABD 326DEF STO A,LDSEL ;set to new drive 0AC0 C5 PUSH BC 0AC1 216EEF LDK HL,LDTRK 0AC4 4E LD C,[hl] ;get last accessed track for new drive 0AC5 3A0121 LD A,D.TRKR ;get current track 0AC8 77 STO A,[hl] ;save in table 0AC9 79 MOV A,C 0ACA 320121 STO A,D.TRKR ;set trk register to last selected 0ACD C1 POP BC ; Set drive select perserving vio offset values 0ACE CD600C :3: CALL RDSKD ;reset Controller 0AD1 0605 LDK B JRZ SKEX1 ;if error 0B0E CB67 $ BIT BS.SEK,A 0B10 2005 ^0B17$ JRNZ SKEX1 ;if error 0B12 CB57 $ BIT BS.TK0,A 0B14 280C ^0B22$ JRZ :4 ;if NOT home = 0000 IF ODEBUG ENDIF 0B16 AF XRA A ;clear A 0B17 F5 SKEX1: PUSH AF 0B18 3EFF LDK A,-1 0B1A 326AEF STO A,DACTVE ;start counter 0B1D CDE00C CALL STAT17 ;save disk controller regs 0B20 F1 POP AF 0B21 C9 RET ; Here if drive NOT homed, possible NOT ready 0B22 E680 :4: AND 80h 0B24 18F1 ^0B17$ JR SKEX1 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 71 Disk I/O routines. E:OCCROM6B.ASM 0B26 SEEK: ;Seek to track defined by SAVTRK ; Entry SAVTRK set to track ; SAVSEC set to sector number ; Exit A= 0* SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 72 Disk I/O routines. E:OCCROM6B.ASM 0B69 DRDA: ;Read Address info. ; Entry SDISK= drive ; Exit D.STSB = data bytes ; MUST NOT destroy DE pair 0B69 proc 0B69 CD9A0A CALL SDRV ;select drive 0B6C 3EC4 DRDAS: LDK A,D.RDA 0B6E CD200C CALL FDSK ;function disk ; Get status bytes 0B71 2109EF LDK HL,DSTSB 0B74 0606 LDK B,6 0B76 DI 0B77 D5 PUSH DE ;save DE 0B78 11A00F :2: LDK DE,4000 ;time out 0B7B 3A0021 :3: LD A,D.STSR 0B7E CB47 $ BIT BS.BSY,A 0B80 284E ^0BD0$ JRZ RWEX ;if possible error 0B82 CB4F $ BIT BS.DRQ,A 0B84 2009 ^0B8F$ JRNZ :4 ;if data ready 0B86 1B DEC DE 0B87 7A MOV A,D 0B88C7 23 INC HL 0BC8 10EE ^0BB8$ DJNZ :6 ;if not all data ; Now check if multi sector 0BCA C1 POP BC 0BCB 10E8 ^0BB5$ DJNZ :5 ;continue 0BCD AF XRA A 0BCE 1806 ^0BD6$ JR RWEX1 ; here on error 0BD0 CDE00C RWEX: CALL STAT17 ;save disk controller regs 0BD3 D1 POP DE ;restore stack 0BD4 F680 OR 80h ;if busy cleared, indicate with 80h 0BD6 B7 RWEX1: OR A ;set status 0BD7 F5 PUSH AF 0BD8 3EFF LDK A,-1 0BDA 326AEF STO A,DACTVE 0BDD F1 POP AF 0BDE EI ! RET 0BE0 DWRT: ;Write to disk ; Entry SDISK= drive ; B= Number of sectors to xmit. ; DMADR= FWA of data ; Exit same as DREAD ; Uses All registers 0BE0 proc 0BE0 50  RET ; here if error 0C1D F680 :5: OR 80h ;indicate busy dropped 0C1F C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 76 Disk I/O routines. E:OCCROM6B.ASM 0C20 FDSK: ;Function disk routine ; All functions for DSK controller SHALL do so by using ; this routine. FDSK sets DACTVE to 0 indicating activity ; UPTIM uses this cell to turn off select if one sec has ; occurred. ; Entry A= function code ; Exit A= 0, if chip accepted function ; else, A=-1, indicating time-out, See WBUSY ; Uses A, B, C 0C20 proc 0C20 47 MOV B,A ;save function code 0C21 3A62EF LD A,PIABD 0C24 E6C0 AND 1100_0000b 0C26 2005 ^0C2D$ JRNZ :1 ;if B3 OR E 0B89 20F0 ^0B7B$ JRNZ :3 ;if NOT time out 0B8B 0EFE LK C,SEKTMO ;seek time out 0B8D 1841 ^0BD0$ JR RWEX ;error exit 0B8F 3A0321 :4: LD A,D.DATR 0B92 77 STO A,[hl] ;save byte 0B93 23 INC HL 0B94 10E2 ^0B78$ DJNZ :2 ;if not done 0B96 D1 POP DE 0B97 AF XRA A ;indicate good 0B98 EI ! RET 0B9A DREAD: 0B9A DRSECS: ;Read disk sectors. ; Entry SDISK= drive ; B = number of sectors to read ; Number from 1 to MSEC ; DMADR= FWA for data. ; Exit DSTSB= A= 0, if no error ; HL = next DMA ; Uses All registers 0B9A proc 0B9A 50 MOV D,B ;save sectors 0B9B CD260B CALL SEEK ;seek to track, set sector 0B9E 2036 ^0BD6$ JRNZ RWEX1 ;if seek MOV D,B 0BE1 CD260B CALL SEEK 0BE4 20F0 ^0BD6$ JRNZ RWEX1 ;if seek error 0BE6 42 MOV B,D 0BE7 C5 PUSH BC 0BE8 3EA4 LDK A,D.WRTS 0BEA 15 DEC D 0BEB 2802 ^0BEF$ JRZ :3 ;if NOT multi-sectors 0BED F610 OR MSECB ;add 'm' bit SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 74 Disk I/O routines. E:OCCROM6B.ASM 0BEF CD200C :3: CALL FDSK 0BF2 C1 POP BC ; Now xfer bytes to controller from DMA. 0BF3 DI 0BF4 2A0FEF LD HL,DMADR 0BF7 C5 :5: PUSH BC 0BF8 010001 LDK BC,LSECB ;length of std sector 0BFB CD060C :6: CALL XDD ;xfer to disk 0BFE 20D0 ^0BD0$ JRNZ RWEX ;if error ; Now check if multi sector 0C00 C1 POP BC 0C01 10F4 ^0BF7$ DJNZ :5 ;continue 0C03 A drive active 0C28 C5 PUSH BC 0C29 CD9A0A CALL SDRV ;reselect drive 0C2C C1 POP BC 0C2D CD470C :1: CALL WBUSY ;Wait for busy to clear 0C30 F8 RM ;if will NOT clear busy ; Controller NOT busy, issue command 0C31 78 MOV A,B 0C32 320021 STO A,D.CMDR ;function drive ; Wait for busy to be set 0C35 0E00 LDK C,0 0C37 3A0021 :2: LD A,D.STSR 0C3A 1F RAR ;DS.BSY 0C3B 3805 ^0C42$ JRC :3 ;if chip went busy 0C3D 0D DEC C 0C3E 20F7 ^0C37$ JRNZ :2 ;if not time-out 0C40 1814 ^0C56$ JR WBUSYX ;exit, error ; Set DACTVE indicating activity on drive 0C42 AF :3: XRA A 0C43 326AEF STO A,DACTVE 0C46 C9 RET 0C47 WBUSY: ;Wait for Busy to clear ; Exit A= -1, if time out oc error 0BA0 42 MOV B,D 0BA1 C5 PUSH BC 0BA2 3E80 LDK A,D.RDS 0BA4 15 DEC D 0BA5 2802 ^0BA9$ JRZ :3 ;if NOT multi-sectors SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 73 Disk I/O routines. E:OCCROM6B.ASM 0BA7 F610 OR MSECB ;add 'm' bit 0BA9 CD200C :3: CALL FDSK 0BAC C1 POP BC 0BAD FEFF CMP -1 0BAF 2825 ^0BD6$ JRZ RWEX1 ;if drive NOT ready ; Now xfer bytes from controller to DMA. 0BB1 DI 0BB2 2A0FEF LD HL,DMADR 0BB5 C5 :5: PUSH BC 0BB6 0600 LDK B,low LSECB 0BB8 3A0021 :6: LD A,D.STSR 0BBB CB47 $ BIT BS.BSY,A 0BBD 2811 ^0BD0$ JRZ RWEX ;if possible error 0BBF CB4F $ BIT BS.DRQ,A 0BC1 28F5 ^0BB8$ JRZ :6 ;if no data 0BC3 3A0321 LD A,D.DATR 0BC6 77 STO A,[hl] 0BF XRA A 0C04 18D0 ^0BD6$ :8: JR RWEX1 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 75 Disk I/O routines. E:OCCROM6B.ASM 0C06 XDD: ;Xfer data from memory to disk ; Entry BC = length ; HL = FWA ; Exit HL = next address ; A=0 if no error, else status ; Uses A,BC,E, HL 0C06 proc 0C06 3A0021 LD A,D.STSR 0C09 CB47 $ BIT BS.BSY,A 0C0B 2810 ^0C1D$ JRZ :5 ;if possible error 0C0D CB4F $ BIT BS.DRQ,A 0C0F 28F5 ^0C06$ JRZ XDD ;if no data 0C11 7E LD A,[hl] 0C12 320321 STO A,D.DATR ;send to controller 0C15 23 INC HL 0C16 0B DEC BC 0C17 78 MOV A,B 0C18 B1 OR C 0C19 20EB ^0C06$ JRNZ XDD ;if not done 0C1B AF XRA A ;indicate good xfer 0C1C C9 +curred, ; else ; A= last status and is positive. ; Uses A, C 0C47 proc 0C47 C5 PUSH BC 0C48 010000 LDK BC,0 0C4B 3A0021 :1: LD A,D.STSR 0C4E 1F RAR ;DS.BSY 0C4F 300A ^0C5B$ JRNC :1A ;if NOT busy, proceed 0C51 0B DEC BC 0C52 78 MOV A,B 0C53 B1 OR C 0C54 20F5 ^0C4B$ JRNZ :1 ;if not time-out 0C56 3EFF WBUSYX: LDK A,-1 ;indicate error, drive NOT ready SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 77 Disk I/O routines. E:OCCROM6B.ASM 0C58 C1 POP BC 0C59 B7 OR A ;set flags 0C5A C9 RET 0C5B 17 :1A: RAL ;restore A 0C5C C1 POP BC ;restore BC 0C5D E67F AND 7Fh ;make sure its positive 0C5F C9 RET 0C60 utput comma 0C9F 3A0121 LD A,D.TRKR 0CA2 CD980F CALL PBBH ;output controller track 0CA5 CDBE0F CALL O2SP 0CA8 3A14EF LD A,SAVSEC 0CAB CD980F CALL PBBH ;output sector 0CAE 0E2C LDK C,',' 0CB0 CD8603 CALL COUT ;output comma 0CB3 3A0221 LD A,D.SECR 0CB6 CD980F CALL PBBH ;output controller sector ; Update error counter 0CB9 2A02EF LD HL,ERCNT 0CBC 23 INC HL 0CBD 2202EF STO HL,ERCNT ;update error count ; Clear controller 0CC0 CD680C CALL RDSKC ;reset disk controller ; Restore regs 0CC3 C1 POP BC 0CC4 E1 POP HL 0CC5 D1 POP DE 0CC6 C9 RET 0CC7 1A14 DERMSG: DBE cr,lf 0CC9 88E6D6408A DCE 'Dsk ERR (sts trk sec)- ' 0CE0  CMP 'K' 0D0F CA440E JZ KEYBT ;if Keyboard test 0D12 FE4D CMP 'M' 0D14 CA690E JZ TSTMEM ;if memory test 0D17 FE52 CMP 'R' 0D19 CACD0E JZ TSERI ;if input test program 0D1C FE44 CMP 'D' 0D1E 20D2 ^0CF2$ JRNZ DIAG ;if illegal 0D20 DSKD: ;Here to run disk diagnostic 0D20 119C0D LDK DE,DSKMSG 0D23 CD380E CALL ASKU ;Ask user for input 0D26 D641 SUB 'A' 0D28 2804 ^0D2E$ JRZ :2 ;if 'A' 0D2A 3D DEC A 0D2B 20C5 ^0CF2$ JRNZ DIAG ;if not A or B 0D2D 3C INC A 0D2E 3217EF :2: STO A,SDISK ;set drive 0D31 CDAC0D CALL DRDT ;test reading entire disk 0D34 CDD40D CALL DSEKT ;test random seeks 0D37 C3F20C JMP NEXTC ;next 0D3A 34 DIAMSG: DBE 'Z'-40h 0D3B 404040A49E DBE ' ROM DIAGNOSTICs' 0D4D 1A14A6CAD8 DBE cr,lf,'Select Test:' 0RDSKD: ;Reset PIA and disk controller ; selecting drive specified by C ; Entry C= drive ; B= PIABD 0C60 78 MOV A,B 0C61 E61F AND 0001_1111b ;get vio offset only 0C63 B1 OR C 0C64 4F MOV C,A 0C65 CDD208 CALL OPBD ;function PIO-b ; JMP RDSKC 0C68 RDSKC: ;reset disk controller ; Entry None ; Exit Busy cleared. ; A= 0. 0C68 3ED0 LDK A,D.FINT 0C6A 320021 STO A,D.STSR ;clear controller 0C6D AF XRA A ;clear A and flags 0C6E C9 RET 0C6F ODER: ;Output disk error to console ; Entry DE= FWA of message ; SDISK = drive with error 0C6F D5 PUSH DE 0C70 CDB40F CALL OCRLF ;new line 0C73 3A17EF LD A,SDISK 0C76 C STAT17: ;save 179x status ;called when disk error discovered: ;...saves 179x regs in high RAM. 0CE0 C5 PUSH BC ! PUSH DE ! PUSH HL 0CE3 210021 LK HL,D.STSR ;1st (lowest) 179x register 0CE6 11C2EF LK DE,R179x ;register save area 0CE9 010400 LK BC,4 ;move 4 bytes 0CEC EDB0 $ LDIR 0CEE E1 POP HL ! POP DE ! POP BC 0CF1 C9 RET ; endx BMDSK SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 79 Diagnostic section. E:OCCROM7B.ASM ; This section of code is entered either via the 1st prompt ; level by entering ^d, or by using the monitor command of ; 'T' if DEBUG is assembled on. ; ; This section of code contains all of the rom resident ; diagnostics to assist producD5B 1A14825884 DBE cr,lf,'A,B Boot Sys' SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 80 Diagnostic section. E:OCCROM7B.ASM 0D69 1A14408840 DBE cr,lf,' D isk' 0D71 1A14409640 DBE cr,lf,' K ey-vdt' 0D7C 1A14409A40 DBE cr,lf,' M emory' 0D86 1A1440A440 DBE cr,lf,' R ead in test' 0D96 141A144074 DBE lf,cr,lf,' :' 0D9B 41 DCE ' ' 0D9C 1A14 DSKMSG: DBE cr,lf 0D9E A6CAD8CAC6 DCE 'Select (A,B): ' ; Disk diagnostic section. 0DAC DRDT: ;Disk read test ; reads each sector on disk and reports any errors 0DAC proc 0DAC CD100E CALL DSKDI ;initialize disk 0DAF 3E00 LDK A,0 0DB1 3215EF :2: STO A,SAVTRK 0DB4 3E01 LDK A,1 0DB6 3214EF :3: STO A,SAVSEC 0DB9 0601 LDK B,1 0DBB CD9A0B CALL DREAD 641 ADD A,'A' 0C78 4F MOV C,A 0C79 CD0703 CALL CO ;output drive name 0C7C CDBE0F CALL O2SP 0C7F D1 POP DE ;get message 0C80 C3A108 JMP ESTR 0C83 DERR: ;Output disk system error ; Entry A= status from controller ; Exit error output 0C83 D5 PUSH DE 0C84 E5 PUSH HL 0C85 C5 PUSH BC 0C86 F5 PUSH AF 0C87 11C70C LDK DE,DERMSG 0C8A CDA108 CALL ESTR ;output error 0C8D F1 POP AF ;get status value 0C8E CD980F CALL PBBH ;output status 0C91 CDBE0F CALL O2SP SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 78 Disk I/O routines. E:OCCROM6B.ASM 0C94 3A15EF LD A,SAVTRK 0C97 CD980F CALL PBBH ;output track 0C9A 0E2C LDK C,',' 0C9C CD8603 CALL COUT ;otion and distributors. ; ; The diagnostic section uses a menu and contain test ; for major hardware pieces. These diagnostics are NOT ; considered to be all-encompassing...... ; Entry from monitor loop 0CF2 DIAG: proc = FFFF IF ~INDMON = 0CF2 NEXTC = DIAG ENDIF 0CF2 31C1EF LK SP,ROMSTK 0CF5 113A0D LDK DE,DIAMSG 0CF8 CD380E CALL ASKU ;ask user for input 0CFB 21C7EF LDK HL,DSKSWP ;disk swap cell 0CFE 0E00 LDK C,0 0D00 71 STO C,[HL] ;SET A=A,B=B 0D01 FE41 CMP 'A' 0D03 CAFA01 JZ CBOOT ;IF BOOT A DRIVE 0D06 34 INC [HL] ;SWAP DRIVES A=B,B=A 0D07 FE42 CMP 'B' 0D09 CAFA01 JZ CBOOT ;IF BOOT B DRIVE 0D0C 35 DEC [HL] ;A=A, B=B 0D0D FE4B ,;read sector 0DBE B7 OR A 0DBF C4830C CNZ DERR ;if error 0DC2 3A14EF LD A,SAVSEC 0DC5 3C INC A 0DC6 FE0B CMP MSEC+1 0DC8 20EC ^0DB6$ JRNZ :3 ;if not full track 0DCA 3A15EF LD A,SAVTRK 0DCD 3C INC A 0DCE FE28 CMP MTRK 0DD0 20DF ^0DB1$ JRNZ :2 ;if not full disk 0DD2 1825 ^0DF9$ JR DERC ;display error count 0DD4 DSEKT: ;Disk seek test ; Routine performs random seeks followed by reads validating ; drive is aligned and data path is valid. ; Entry None. ; Exit Back to diag main loop. 0DD4 proc 0DD4 CD100E CALL DSKDI ;initialize 0DD7 3E64 LDK A,100 0DD9 3200EF :2: STO A,TEM 0DDC CD1E0F CALL GNRN ;get next track 0DDF 3215EF STO A,SAVTRK 0DE2 0601 LDK B,1 0DE4 CD9A0B CALL DREAD ;read sector 0DE7 B7 F LD A,SEC6 0E13 3201EF STO A,RNDV ;set random seed 0E16 CDE80A CALL DDRV ;deselect drive 0E19 110000 :2: LDK DE,0 0E1C ED5302EF $ STO DE,ERCNT ;clear error count 0E20 4B MOV C,E 0E21 CD020B CALL HOMED ;select drive 0, home. 0E24 280B ^0E31$ JRZ :3 ;if drive ready 0E26 CD680C CALL RDSKC ;reset disk controller 0E29 118102 LDK DE,DNRMSG 0E2C CD6F0C CALL ODER ;output disk error 0E2F 18E8 ^0E19$ JR :2 0E31 0180ED :3: LDK BC,HSTBUF 0E34 CD850A CALL SETDMA ;set to default dma 0E37 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 83 Diagnostic section. E:OCCROM7B.ASM 0E38 ASKU: ;Ask user for input, first displaying prompt ; Entry DE= FWA of prompt message ; Exit A= normalized input from user 0E38 CDA108  JRNZ :3 ;if not all done ; Now perform test on memory reading ; what was just written and comparing ; with pattern C. 0E81 E1 POP HL ;restore FWA 0E82 E5 PUSH H 0E83 :5: DI 0E84 7E LD A,[hl] 0E85 B9 CMP C ;validate good write 0E86 281F ^0EA7$ JRZ :7 ;If GOOD compare 0E88 EI 0E89 47 MOV B,A ;save BAD data 0E8A C5 PUSH BC 0E8B CDB40F CALL OCRLF ;output new line 0E8E CD450F CALL ADRD ;Output Location in error 0E91 CDC10F CALL OSP ;Output space char 0E94 C1 POP BC 0E95 C5 PUSH BC 0E96 79 MOV A,C 0E97 CD980F CALL NMOUT ;Output good data 0E9A 0E3D LDK C,'=' 0E9C CD8603 CALL COUT 0E9F 78 MOV A,B 0EA0 CD980F CALL NMOUT ;Output BAD data 0EA3 C1 POP BC ;restore pattern 0EA OR A 0DE8 C4830C CNZ DERR ;if disk error 0DEB CD1E0F CALL GNRN ;get random 0DEE CD6008 CALL DELAY ;delay 0DF1 3A00EF LD A,TEM 0DF4 3D DEC A 0DF5 20E2 ^0DD9$ JRNZ :2 ;if not done 0DF7 1800 ^0DF9$ JR DERC ;display error count SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 81 Diagnostic section. E:OCCROM7B.ASM ;DDAM: ;Test data address marks ;; Entry None ;; Exit After 1000 tries and displays ; proc ; CALL DSKDI ;initialize disk ; LDK BC,1000 ;:2: PUSH BC ; CALL DRDA ;read address mark ; LDK C,' ' ; JRZ :4 ;if good xfer ; LD HL,ERCNT ; INC HL ; STO HL,ERCNT ;update error count  CALL ESTR ;prompt user 0E3B CD590F CALL GETCH ;get next char 0E3E FE1B CMP ESC 0E40 CAF20C JZ NEXTC ;if abort 0E43 C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 84 Diagnostic section. E:OCCROM7B.ASM 0E44 KEYBT: ;Perform reading of keyboard and echoing to screen ; Keeps running till user types in ^Z. 0E44 11500E LDK DE,KEYTM 0E47 CDA108 CALL ESTR ;output prompt 0E4A 210040 LDK HL,4000h 0E4D C32E0F JMP ACMDD ;enter A command 0E50 1A14 KEYTM: DBE cr,lf 0E52 8ADCE8CAE4 DCE 'Enter keys (till ^Z) : ' SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 85 Diagnostic section. E:OCCROM7B.ASM 0E69 TSTMEM: ;performs a test of memory validating that the ; 4 CD4C0F CALL BREAK 0EA7 :7: 0EA7 23 INC HL 0EA8 CD4F08 CALL CDEHL SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 86 Diagnostic section. E:OCCROM7B.ASM 0EAB 20D6 ^0E83$ JRNZ :5 ;If not all done 0EAD EI ;allow key entry 0EAE 79 MOV A,C 0EAF 0F RRC ;shift one position 0EB0 4F MOV C,A 0EB1 2128F0 LDK HL,FWAVM+40 0EB4 34 INC [hl] ;indicate running 0EB5 E1 POP HL 0EB6 D1 POP DE 0EB7 CD4C0F CALL BREAK 0EBA 28BB ^0E77$ JRZ :2 ;if not data 0EBC 4F MOV C,A ;next test pattern 0EBD C3770E JMP :2 ;keep on looping 0EC0 1A149ACADA TSMSG: DBE cr,lf,'Memory tes' 0ECC E9 DCE 't' SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 87 Diagnostic section.  ; LDK C,80h ;pure white space ;:4: CALL COUT ;output indicator ; POP BC ; DEC BC ; MOV A,B ; OR C ; JRNZ :2 ;if not done ; JR DERC ;display error count 0DF9 DERC: ;Display error counter. ; Entry ERCNT = current error count 0DF9 11050E LDK DE,DERCMG 0DFC CDA108 CALL ESTR ;output error prompt 0DFF 2A02EF LD HL,ERCNT 0E02 C3450F JMP ADRD ;output number 0E05 1A14 DERCMG: DBE cr,lf 0E07 8AA4A440C6 DCE 'ERR cnt- ' SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 82 Diagnostic section. E:OCCROM7B.ASM 0E10 DSKDI: ;Disk diagnostic initialize ; Entry SDISK set to disk to test(0 or 1) 0E10 proc 0E10 3A69Ememory is working correctly. ; Fixed limits on memory test are 4000h to EF00h ; (TEM = EF00h) ; Entry none. ; Exit To error if any errors occurred during ; the testing ; Calls GETNM 0E69 proc 0E69 11C00E LDK DE,TSMSG 0E6C CDA108 CALL ESTR ;prompt user about mem test 0E6F 1100EF LDK DE,TEM 0E72 210040 LDK HL,4000h 0E75 0EA5 LDK C,0A5h ;initial test pattern ; Loop thu testing memory within limits ; HL= FWA ; DE= LWA 0E77 :2: DI 0E78 D5 PUSH DE ;save LWA 0E79 E5 PUSH HL ;save FWA 0E7A :3: 0E7A 71 STO C,[hl] ;data to memory 0E7B 23 INC HL ;update address 0E7C CD4F08 CALL CDEHL 0E7F 20F9 ^0E7A$ - E:OCCROM7B.ASM 0ECD TSERI: ;Input test routine through serial port ; Format of input: ; 8 bit binary data, no parity ; 1st two bytes are DW (length) ; (length) following bytes are placed ; at 4000h in memory; ; Exit: JMP 4000h 0ECD Proc 0ECD 11FA0E LK DE,:lmsg ;length msg 0ED0 CDA108 CALL ESTR 0ED3 CD670A CALL READER ;get chr 0ED6 69 MOV L,C ;low byte of length 0ED7 CD670A CALL READER 0EDA 61 MOV H,C 0EDB CD450F CALL PBWH ;print out length of test routine 0EDE EB EX HL,DE ;DE = length 0EDF 210040 LK HL,4000h ;FWA of test program 0EE2 7A :loop: MOV A,D 0EE3 B3 OR E 0EE4 280B ^0EF1$ JRZ :xit ;if finished wi ; contained in the H,L registers. ; Entry HL= address to be displayed ; Exit NONE ; Calls PBBH ; DESTROYS: AF, C. 0F45 7C MOV A,H ;display First half of address 0F46 CD980F CALL PBBH 0F49 7D MOV A,L ;display second half of address 0F4A 184C ^0F98$ JR PBBH 0F4C BREAK: ;Check for break key. ; Entry NONE ; Exit To DIAG if char entered is ESC, else ; return to caller A= char or 0 if none ; Calls SKEY, CI ; DESTROYS: A,F/F'S 0F4C CDA102 CALL SKEY ;get console status 0F4F C8 RZ ;If not ready 0F50 CDAC02 CALL CI ;get char 0F53 FE1B CMP ESC 0F55 CAF20C JZ DIAG ;if ESC, abort 0F58 C9 RET SORCIM 808x Assembler v ; Load BC with length and set ; HL = FWA of data to xmit to disk 0F7C 4E LD C,[hl] ! INC HL 0F7E 46 LD B,[hl] ! INC HL ;BC = length of xfer ; Now write out data 0F80 CD060C :4: CALL XDD ;xfer to disk 0F83 2011 ^0F96$ JRNZ :11 ;if error ; Pad rest of track with FFh 0F85 3A0021 :10: LD A,D.STSR 0F88 B7 OR A 0F89 280B ^0F96$ JRZ :11 ;if all done 0F8B E602 AND DS.DRQ 0F8D 28F6 ^0F85$ JRZ :10 0F8F 3EFF LDK A,0FFh 0F91 320321 STO A,D.DATR ;pad 0F94 18EF ^0F85$ JR :10 ;continue ; Exit A=0, if no error 0F96 :11: EI 0F97 C9 RET ; endx BMXFMT.asm SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 91 th input, run prgm 0EE6 CD670A CALL READER 0EE9 77 STO A,[hl] ;get & deposit next byte 0EEA 3228F0 STO A,FWAVM+40 ;indicate recieved data 0EED 23 INC HL 0EEE 1B DEC DE 0EEF 18F1 ^0EE2$ JR :loop 0EF1 110D0F :xit: LK DE,:xmsg ;exit message 0EF4 CDA108 CALL ESTR 0EF7 C30040 JMP 4000h ;...to user program 0EFA 1A14A6E8C2 :lmsg: DBE cr,lf,'Start input: Len' ! DCE '=' 0F0D 1A14A0E4DE :xmsg: DBE cr,lf,'Program begins' ! DCE ':' 0F1E GNRN: ;Get next random number ; Exit A= new number to use (0 to MTRK-1) 0F1E proc 0F1E ED5F $ MOV A,R ;refresh register 0F20 AE XOR [hl] 0F21 E63F AND 3Fh ;cannot exceed 28h=40d 0F23 C611 ADD A,17 0F25 FE28 CMP MTRK 0F27 DA2C0F JC :4 ;if in range 0F2A D628 SUB MTRK 0F2er 3.5E 1=/10/91 1<:0; Page 89 Diagnostic section. E:OCCROM7B.ASM 0F59 GETCH: ;returns the next character in the input stream ; TO the calling program. ; Entry NONE ; Exit C - next character normalized to UPPER case. ; Calls CI,CO,NORM ; DESTROYS: A,C,F/F'S 0F59 CDAC02 CALL CI ;Get character from terminal 0F5C CD0703 CALL CO ;output it 0F5F C3BD02 JMP NORM ENDIF ; Endx BMDIA.asm SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 90 Diagnostic section. E:OCCROM8B.ASM 0F62 FORMT: ;Format one track ; in IBM 3740 format consisting of 40 tracks, with e BMUTIL2 - OSBORNE 1 UTILITY ROUTINES. E:OCCROM9B.ASM 0F98 NMOUT: 0F98 PBBH: ;PRINT BINARY BYTE IN HEX. ; CONVERTS THE 8 BIT, UNSIGNED INTEGER IN THE ; A REGISTER INTO 2 ASCII CHARACTERS. ; ENTRY A= 8 BIT INTEGER ; EXIT NONE ; CALLS CO,PRVAL ; DESTROYS: AF, C. 0F98 F5 PUSH AF ;SAVE ARGUMENT 0F99 0F RRC 0F9A 0F RRC 0F9B 0F RRC 0F9C 0F RRC ;GET UPPER 4 BITS TO LOW 4 BIT POSITIONS 0F9D CDAA0F CALL PRVAL ;CONVERT LOWER 4 BITS TO ASCII 0FA0 CD0703 CALL CO ;SEND TO TERMINAL 0FA3 F1 POP AF ;GET BACK ARGUMENT 0FA4 CDAA0F CALL PRVAL 0FA7 C30703 JMP CO 0FAA PRVAL: ;CONVERTS A NUMBER IN THE RANGE 0 TO F HEX TO ; THE CORRESPONDING ASCII CHARACTER, 0-C 77 :4: STO A,[hl] ;update 0F2D C9 RET SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 88 Diagnostic section. E:OCCROM7B.ASM = FFFF IF ~INDMON 0F2E ACMDD: ;Entry here from Diagnostic loop HL = 4000h 0F2E proc 0F2E CDAC02 :3: CALL CI ;read char 0F31 FE1A CPI EOFC 0F33 CAF20C JZ DIAG ;if request to quit 0F36 77 STO A,[hl] ;into memory 0F37 23 INC HL ;update pointer 0F38 FE0D CPI CR 0F3A 2003 ^0F3F$ JRNZ :5 ;If not carriage return 0F3C 360A STO LF,[hl] 0F3E 23 INC HL 0F3F :5: 0F3F 4F MOV C,A 0F40 CD8603 CALL COUT ;back to user 0F43 18E9 ^0F2E$ JR :3 ;next character 0F45 ADRD: 0F45 PBWH: ;Print Binary Word in Hex. ; PBWH outputs to the console the address ach ; track containing 10 sectors. ; Drive already selected and ready ; Entry BC = FWA of buffer ; BUF+0= DW length ; BUF+2= beginning of data ; SAVTRK = next track to format ; SAVSEC = 1 ; Exit track formatted 0F62 proc 0F62 C5 PUSH BC ;save address 0F63 3A15EF LD A,SAVTRK 0F66 210121 LDK HL,D.TRKR ;PRESENT TRACK 0F69 B6 OR [HL] 0F6A CA720F JZ :2 ;if already on track 0F6D 3E40 LDK A,D.STPI 0F6F CDF10A CALL PSEKC ;perform step IN 0F72 3EF4 :2: LDK A,D.WRTT ;request write track 0F74 DI 0F75 CD200C CALL FDSK ;request write 0F78 E1 POP HL ;FWA of buffer 0F79 EI 0F7A C0 RNZ ;if error 0F7B DI .9,A-F. PRVAL ; DOES NOT CHECK THE VALIDITY OF ITS INPUT ARGUMENT. ; ENTRY A= INTEGER, RANGE 0 TO F ; EXIT A= ASCII CHARACTER. ; C= A ; CALLS NONE. ; DESTROYS: AF 0FAA E60F AND 0FH 0FAC C690 ADD A,90H ;SET UP A SO THAT A-F CAUSE A CARRY 0FAE 27 DAA ;ADJUST CONTENTS OF A REGISTER 0FAF CE40 ADC A,40H ;ADD IN CARRY AND ADJUST UPPER 4 BITS 0FB1 27 DAA ;ADJUST CONTENTS OF A REGISTER AGAIN 0FB2 4F MOV C,A 0FB3 C9 RET 0FB4 OCRLF: ;OUTPUT CR,LF ON CONSOLE SCREEN 0FB4 0E0D LK C,CR 0FB6 CD8603 CALL COUT 0FB9 0E0A LK C,LF 0FBB C38603 JMP COUT 0FBE O2SP: ;OUTPUT 2 SPACES ON CONSOLE 0FBE CDC10F CALL OSP 0FC1 0E20 OSP: LK C,' ' 0FC3 C38603  along with length (1,2,1). EF13 = 0001 SEKDEL: DS 1 ;Set for seek-restore command in ROM ;depends on disk type. Siemens = 3h, MPI = 0h EF14 = 0001 SAVSEC DS 1 ;last sector requested EF15 = 0002 SAVTRK DS 2 ;last track requested EF17 = 0001 SDISK DS 1 ;Selected disk drive (0,1) = EF14 ACTSEC = SAVSEC = EF15 ACTTRK = SAVTRK = EF17 ACTDSK = SDISK EF18 = 0001 SEKSEC DS 1 EF19 = 0002 SEKTRK DS 2 EF1B = 0001 SEKDSK DS 1 EF1C = 0001 HSTSEC DS 1 EF1D = 0002 HSTTRK DS 2 EF1F = 0001 HSTDSK DS 1 EF20 = 0001 TEMSEC DS 1 ;Used in bios only EF21 = 0001 RDFLAG DS 1 ;Read flag EF22 = 0001 ERFLAG DS 1 ;Error reporting SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 94 BMRAM - Debug Monitor RAM Storage. timer cell EF6C = 0001 LLIMIT DS 1 ;max #columns in a logical line ; MSG 'LLIMIT = ',LLIMIT,'h.' ; Disk drive current positions EF6D = 0002 LDSEL: DS 2 ;Last selected drive = EF6E LDTRK = LDSEL+1 ;Last track used for non-selected drive EF6F = 0002 IESTK: DS 2 ;save current stk ptr SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 95 BMRAM - Debug Monitor RAM Storage. E:OCCRAMA .ASM ; Interrupt stack EF71 = 0028 DS 20*2 EF99 = 0000 ISTK: DS 0 ; Stack entry EF99 = 0028 DS 20*2 EFC1 BIOSTK: EFC1 = 0000 ROMSTK: DS 0 EFC1 = 0001 ACIAD: DS 1 ;last command byte written to ACIA  JMP COUT = 0FC6 RLWA = * ;LWA OF ROM RESIDENT CODE MSG 'LENGTH OF THIS ROM IS = ',RLWA 'LENGTH OF THIS ROM IS = 0FC6' = 0000 IF RLWA > 0FFFH ENDIF SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 92 BMUTIL2 - OSBORNE 1 UTILITY ROUTINES. E:OCCROM9B.ASM ; endx BMUTIL2.asm SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 93 BMRAM - Debug Monitor RAM Storage. E:OCCRAMA .ASM ;MRAM - Debug Monitor RAM Storage. ; Used to assembly ROM resident and CBIOS 0FC6 = ED80 ORG MRAM ; Host disk xfer buffer and... ; Format track templ E:OCCRAMA .ASM EF23 = 0001 WRTYPE DS 1 ;Write operation type EF24 = 000C ALV: DS ALVS EF30 = 0020 CSV: DS CSVS ; BIOS blocking-deblocking flags EF50 = 0001 HSTACT: DS 1 ;host active flag EF51 = 0001 HSTWRT: DS 1 ;Host written flag EF52 = 0001 UNACNT: DS 1 ;Unalloc rec count EF53 = 0002 UNATRK: DS 2 ;Track EF55 = 0001 UNASEC: DS 1 ;Sector EF56 = 0001 LOGSEC: DS 1 ;Logical sector EF57 = 0002 LDADR DS 2 EF59 = 0001 KEYLCK DS 1 ;Zero if locked keyboard EF5A = 0002 CURS DS 2 ;current cursor position ; Keyboard scan temporaries EF5C = 0001 TKEY DS 1 ;Tem holding key EF5D = 0001 HKCNT DS 1 ;Debounce key EF5E = 0001 LKEY DS 1 ;Last valid keystroke EF5F = 0001 CKEY DS 1 ;Last control key EF60 = 0001 ESCH DS 1 ; EFC2 = 0004 R179x: DS 4 ;179x register save area EFC6 = 0001 KBDLY: DS 1 ;keyboard debounce-delay cell ;since CP/M CANNOT boot off B:, this cell is used ;to invert the names of the 2 drives: ; =0, all normal, A=A:, B=B: ; =1, all inverted, A=B:, B=A: EFC7 = 0001 DSKSWP DS 1 ; Z80 Alternate Register Set EFC8 ALIGN 10h EFD0 RAGS: EFD0 = 0002 DESAX: DS 2 ;DE` EFD2 = 0002 BCSAX: DS 2 ;BC` EFD4 = 0002 AFSAX: DS 2 ;AF` EFD6 = 0002 HLSAX: DS 2 ;HL` EFD8 = 0002 IXSAX: DS 2 ;IX EFDA = 0002 IYSAX: DS 2 ;IY EFDC = 0002 IVSAX: DS 2 ;Interrupt page register ; 8080 Register Save Area. EFDE ALIGN 10h EFE0 REGS: ate holding buffer ED80 HSTBUF: = 0000 IF DEF FMTDAT ELSE ED80 = 0180 DS 256+128 ENDIF ; Directory Buffer = EE80 DIRBUF: = HSTBUF+256 EF00 = 0006 TEM DS 6 = EF01 RNDV = TEM+1 ;random number seed = EF02 ERCNT = RNDV+1 ;DW ERCNT = EF04 RTRC = ERCNT+2 ;retry count = EF05 RTRY = RTRC+1 EF06 = 0001 MPCHR DS 1 ;prompt character EF07 = 0001 ECHOP DS 1 ;=0, list ehco off EF08 = 0001 ROMRAM DS 1 ;0= RAM, 1= ROM EF09 = 0006 DSTSB DS 6 ;Disk status bytes ; Disk operation temps and control EF0F = 0002 DMADR DS 2 ;Address for read/write Disk EF11 = 0002 DMAADR DS 2 ;CBIOS, users DMA ; Note order of xxxSEC,xxxTRK,xxxDSK must be maintained ;ESC holding flag ;PIAAD and PIABD must be kept sequential, PIAAD first ;dependency in VC_HOME of BMKEY.asm EF61 = 0001 PIAAD: DS 1 ;Holds last PIA-A data EF62 = 0001 PIABD: DS 1 ;Holds last PIA-B data ; Calendar month, day year EF63 = 0003 IDAY DS 3 = EF64 IMONTH = IDAY+1 = EF65 IYR = IDAY+2 ; Wall clock time cells and disk active ; see UPTIM: in BMKEY.asm EF66 = 0006 HOURS: DS 6 = EF67 MINS: = HOURS+1 = EF68 SECS: = HOURS+2 = EF69 SEC6: = HOURS+3 ; Used to deselect drive when there is NO activity ; on drive for n seconds. See FDSK routine = EF6A DACTVE: = HOURS+4 ;=0 by FDSK, Used by UPTIM = EF6B BELCNT: = HOURS+5 ;^G bell /EFE0 = 0001 ESAVE: DS 1 ;E Register save location EFE1 = 0001 DSAVE: DS 1 ;D Register save location EFE2 = 0001 CSAVE: DS 1 ;C Register save location EFE3 = 0001 BSAVE: DS 1 ;B Register save location EFE4 = 0001 FSAVE: DS 1 ;FLAGS save location EFE5 = 0001 ASAVE: DS 1 ;A Register save location EFE6 = 0001 LSAVE: DS 1 ;L Register save location EFE7 = 0001 HSAVE: DS 1 ;H Register save location EFE8 = 0002 PSAVE: DS 2 ;PGM COUNTER save location EFEA = 0002 SSAVE: DS 2 ;USER STACK pointer save location = 0000 IF (high *) <> (high ROMSTK) ENDIF ;TEMP: DS 1 ;TEMPORARY MONITOR CELL EFEC = 0002 BKPA: DS 2 ;last breakpoint address EFEE = 0001 BKPC: DS 1 ;Contents of bkp SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 96 BMRAM - Debug Monitor RAM StorTK0 0002 66#39 66/40 70/31 n BSAVE EFE3 95#43 CBELL 0007 18# 5 23/13 CBOOT 01FA 6/11 6/15 10/ 6 13/12 14#48 79/26 79/29 s CCP D400 16/15 s CCRA 2901 57/25 57/45 58/13 s CCRB 2903 57/32 57/54 59/21 59/23 59/26 59/40 59/42 59/45 60/20 60/22 60/25 62/19 62/21 62/24 CDEHL 084F 50#37 85/27 85/57 s CDISK 0004 15/48 CI 02AC 6/ 6 10/ 9 18#44 88/ 4 88/47 89/ 8 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 98 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM CKEY EF5F 42/50 44/ 9 48/19 94#23 CLRLN 05E4 31/14 33/16 37/47 38#28 40/36 CNTRL 0715 42/55 44#53 n CNVBN 0857 51#18 CO 0307 20#47 52/45 52/47 53/ 9 77/41 89/ 9 91/16 91/19  81#33 DERMSG 0CC7 77/53 78#29 DERR 0C83 77#46 80/23 80/51 n DESAX EFD0 95#27 sD DI mac 4/14 4/38 5/ 3 18/51 25/29 27/31 34/29 39/ 8 41/ 9 41/26 42/ 9 72/15 73/ 9 74/ 6 90/22 90/27 DIAG 0CF2 6/17 79#15 79/17 79/38 79/46 88/ 6 88/49 DIAMSG 0D3A 79/20 79#54 s DIMBIT 0000 27/32 n DIRBUF EE80 93#19 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 99 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM s DISDIM mac 4/ 2 4/16 8/ 8 25/31 27/35 34/32 39/11 41/12 41/29 s DMA 0080 n DMAADR EF11 93#33 DMADR EF0F 16/29 16/44 67/ 4 73/ 9 74/ 6 93#32 DML 0004 66# 5 66/18 66/19 66/20 66/21 DNRMSG 0281 17/ 3 17#16 82/13 DOLF 0605 age. E:OCCRAMA .ASM = 0000 IF * >= LWAMEM ENDIF = 0000 IF * > INTBL ENDIF ; Interrupt Jump Vector is between EFFO, EFFF. SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 97 BMRAM - Debug Monitor RAM Storage. E:OCCRAMA .ASM ; Endx MRAM no ERRORs, 696 Labels, 5572h bytes not used. Program LWA = EFEFh.  s @FREQ 0FA0 @KEY 0001 18# 2 19/19 n @XFRMT FFFF 1#29 ACIAD EFC1 64/ 7 95#12 ACMDD 0F2E 84/ 6 88# 2 n ACTDSK EF17 93#45 n ACTSEC EF14 93#43 n ACTTRK EF15 93#44 ADRD 0F45 81/31 85/43 88#21 n AFSAX EFD4 95#29 s ALIGN mac 95/26 95/39 n ALV EF24 94# 3 s A COMAND mac 12#55 13/11 13/12 13/13 13/14 13/15 13/16 13/17 13/18 13/19 13/20 13/21 13/22 COUT 0386 10/10 21/16 23#20 78/ 4 78/11 85/50 88/15 91/43 91/45 91/50 COUT2 03AC 22/52 24#49 s CPDRA 2900 57/28 57/31 58/ 9 58/33 60/27 61/24 61/50 62/26 62/43 63/22 s CPDRB 2902 57/35 57/38 58/10 58/31 59/15 60/13 61/15 62/13 63/24 63/28 s CR 000D 6/ 7 12/11 12/20 12/27 12/38 12/45 23/ 5 50/28 78/29 79/56 79/57 79/58 80/ 2 80/ 3 80/ 4 80/ 5 80/ 8 81/33 84/ 8 86/15 87/36 87/37 88/ 9 91/42 n CSAVE EFE2 95#42 n CSV EF30 94# 4 s CSVS 0020 94/ 4 CTAB 01F7 13# 9 13/23 CURS EF5A 24/17 32/28 94#17 D.CMDR 2100 31/33 39#31 DOLF2 0608 32/15 40# 8 n DRDA 0B69 71#55 DRDAS 0B6C 71/33 72# 7 DRDT 0DAC 79/50 80#12 DREAD 0B9A 10/21 16/26 16/41 72#40 80/21 80/49 n DRSECS 0B9A 72#41 n DS.BSY 0001 66#33 DS.CRC 0008 66#43 71/28 DS.DRQ 0002 66#37 90/42 DS.HDL 0020 66#49 66/50 DS.INX 0002 66#36 66/37 68/52 68/55 n DS.LSD 0004 66#41 n DS.NRY 0080 66#53 n DS.RNF 0010 66#47 DS.SEK 0010 66#46 66/47 71/28 DS.TK0 0004 66#40 66/41 n DS.WTF 0020 66#50 n DS.WTP 0040 66#52 n DSAVE EFE1 95#41 DSEKT 0DD4 79/51 80#37 n DSKD 0D20 79#40 DSKDI 0E10 80/15 80/43 81#35 DSKMSG 0D9C 79/41 80# 8 DSKSWP EFC7 6/ 8 68/ 8 79/22 95#21 DSTSB EF09 71/35 72/11 93#29 DWRT 0BE0 10/22 73#42 ECHLVS 000C 94/ 3 n ASAVE EFE5 95#45 ASKU 0E38 79/21 79/42 82#20 BCPM 0211 15/ 7 15#51 BCPM1 0214 16#11 17/10 BCPME 026D 16/13 17# 3 BCPME1 0270 17# 5 17/14 n BCSAX EFD2 95#28 BELCNT EF6B 8/19 20/10 31/ 7 94#47 s BIOS EA00 10/27 10/28 15/ 9 n BIOSTK EFC1 95# 9 n BKPA EFEC 95#55 n BKPC EFEE 95#56 s BKS 0008 18/ 8 23/ 7 50/33 BMON 0036 4/ 2 4#37 5/ 3 6/18 BMON1 006A 4/49 6# 6 BRDE 027C 16/28 16/43 17#13 BRDEMG 0291 17/13 17#17 BREAK 0F4C 85/54 86/10 88#38 s BROMJP 0036 10/28 s BRRXT 0033 10/27 s BRTBIT 0080 25/29 34/30 39/ 9 BS.BSY 0000 66#32 66/33 72/18 73/13 75/ 9 BS.DRQ 0001 66#35 66/36 72/20 73/15 75/11 BS.SEK 0004 66#45 66/46 70/29 BS. 66#25 66/27 66/28 66/29 76/23 D.DATR 2103 66#29 71/14 72/29 73/17 75/14 90/45 n D.DEL 0014 66#56 D.FINT 00D0 66#22 77/28 D.RDA 00C4 66#19 72/ 7 D.RDS 0080 66#17 72/55 n D.RDT 00E4 66#20 D.RES 000C 66#12 70/25 D.SECR 2102 66#28 71/52 78/12 D.SEK 0018 66#13 71/25 n D.STP 0020 66#14 D.STPI 0040 66#15 90/18 n D.STPO 0060 66#16 D.STSR 2100 66#26 68/51 72/17 73/12 75/ 8 76/27 76/50 77/29 78/40 90/39 D.TRKR 2101 66#27 68/38 68/41 71/16 78/ 5 90/15 D.WRTS 00A4 66#18 73/54 D.WRTT 00F4 66#21 90/20 DACTVE EF6A 70/38 73/35 76/36 94#45 DDRV 0AE8 20/25 68#57 82/ 6 DELAY 0860 17/ 7 42/41 51#31 68/48 68/50 80/53 DERC 0DF9 80/32 80/57 81#26 DERCMG 0E05 81/28 0OP EF07 8/22 21/10 21/12 21/17 93#27 EDELC 0526 22/46 34#20 EEOL 04FE 22/49 33#14 EFADR 0010 22# 6 33/26 33/33 EFESC 0008 22# 7 24/20 24/53 33/26 33/33 EFGR 0001 22#10 22/11 35/ 3 35/14 EFHA 0002 22# 9 22/11 35/ 6 35/17 EFMSK 0007 22#11 24/35 29/ 6 33/24 33/31 EFSCR 0020 22# 5 33/33 EFUN 0004 22# 8 22/11 35/ 9 35/20 n EFX 0040 22# 4 sD EI mac 4/ 6 4/34 9/ 8 18/58 25/31 27/36 34/32 36/15 39/12 41/13 41/30 72/36 73/38 85/40 86/ 3 90/25 EINSRT 053E 22/45 34#38 s ENADIM mac 25/29 27/32 34/29 39/ 9 41/10 41/27 s ENAROM mac 8/ 7 s EOFC 001A 88/ 5 s ERC 007F 50/28 50/28 50/28 ERCNT EF02 78/16 78/18 81/30 82/ 8 93#23 93/24 n ERFLAG EF22 66/26 s H.IEEE 2900 s H.KEY 2200 48/ 7 48/12 s H.SCTR 2A00 64/ 4 64/ 8 s H.SIO 2A00 s H.SREC 2A01 64/23 s H.SSTS 2A00 64/17 64/37 64/52 s H.SXMT 2A01 64/57 s H.VIO 2C00 4/25 54/ 9 54/11 54/13 54/15 54/25 54/28 54/44 54/47 HINT 0085 4/42 7# 3 HKCNT EF5D 8/21 42/28 42/43 47/28 94#21 n HLSAX EFD6 95#30 HOME 0A94 10/16 67#27 HOMED 0B02 16/11 70#20 82/10 HOMED1 0B05 70/18 70#25 HOURS EF66 94#38 94/39 94/40 94/41 94/45 94/47 n HSAVE EFE7 95#47 HSTACT EF50 16/49 16/50 94# 7 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 101 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM HSTBUF ED80 82/17 93#12 93/19 n HSTDSK EF1F 93#53 n HSTSEC EF1C 93#51  80/ 5 80/ 8 81/33 84/ 8 86/15 87/36 87/37 88/11 91/44 LIST 0A79 10/11 21/20 64#44 LKEY EF5E 8/20 18/37 18/53 42/58 94#22 LLIMIT EF6C 8/31 30/37 32/ 8 39/12 40/24 94#50 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 102 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM LOGSEC EF56 16/50 94#12 LOOKUP 03DE 25/18 25#38 26/18 n LSAVE EFE6 95#46 s LSECB 0100 73/11 74/ 8 n LTRKB 0C35 66# 6 s LVMEM 1000 31/15 s LWAMEM FFFF 95/58 MCDOWN 000A 18# 7 46/17 MCLEFT 0008 18# 8 46/ 2 MCRIGH 000C 18# 9 23/ 8 46/ 5 50/34 MCUP 000B 18# 6 23/ 9 46/14 50/33 n MINS EF67 94#39 MPCHR EF06 4/20 9/ 4 93#26 s MRAM ED80 4/43 93/ 4 s MSEC 000A 16/25 80/26 M 93#57 n ESAVE EFE0 95#40 s ESC 001B 12/ 5 12/ 9 12/12 12/12 12/14 12/16 12/18 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 100 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM 12/18 12/21 12/25 12/28 12/31 12/33 12/36 12/39 12/43 12/47 12/49 24/25 50/28 83/ 6 88/48 ESCCAD 0505 22/35 33#23 ESCCGR 0566 22/38 35#14 ESCCHA 056A 22/40 35#17 ESCCUN 056E 22/42 35#20 ESCEE 058A 22/47 37# 2 ESCH EF60 8/23 24/18 24/54 25/13 29/ 8 33/27 35/11 94#24 ESCHTB 0321 22#18 24/34 ESCLCK 04F4 22/50 32#43 ESCRR 058A 22/48 36#20 ESCSAD 050F 22/36 33#30 ESCSGR 0556 22/37 35# 3 ESCSHA 055A 22/39 35# 6 ESCSUN 055E 22/ n HSTTRK EF1D 93#52 n HSTWRT EF51 94# 8 IBMSG 0157 4/47 12# 3 IDAY EF63 8/25 94#32 94/33 94/34 IE.CO 08DF 10/33 57#18 IE.GTS 0935 10/35 58#28 IE.IDM 09E6 10/39 62#10 IE.ODM 09A4 10/38 61#13 IE.OIM 0981 10/37 60#11 IE.PP 0A42 10/40 63#20 IE.SHK 09B0 60/16 60/29 61/18 61#21 IE.SI 0922 10/34 58# 7 IE.TC 0941 10/36 59#13 IESTK EF6F 4/16 4/32 42/ 9 94#57 n ILINT 0007 4#11 n IMONTH EF64 94#33 INACMD 0000 1#30 13/11 INBCMD FFFF 1#31 13/12 INDCMD 0000 1#32 13/13 INDIA FFFF 1#43 6/12 INDMON 0000 1#44 6/29 79/16 87/55 INFCMD 0000 1#33 13/14 INGCMD 0000 1#34 13/15 INHCMD 0000 1#35 13/16 INMCMD 0000 1#36 13/17 INRCMD 0000 1#37 13/18 ISECB 0010 66# 9 72/58 73/57 s MSIZE 003C s MTRK 0028 80/30 87/50 87/52 n NCMDS 0001 13#23 NEXTC 0CF2 79#17 79/52 83/ 7 s NMIA 0066 4/52 4/54 NMOUT 0F98 85/48 85/52 90#54 NORM 02BD 19# 6 89/10 n NRTRYS 0004 66# 8 n NULINT mac 1#47 s NVDL 0018 O2SP 0FBE 77/42 77/57 78/ 7 91#47 OCRLF 0FB4 77/37 85/42 91#41 s ODEBUG 0000 70/33 ODER 0C6F 17/ 9 77#33 82/14 OPAD 08C5 8/43 28/21 36/13 47/20 54#21 OPBD 08D2 8/49 20/19 28/14 31/ 5 31/20 40/46 47/24 54#34 69/ 6 77/21 OSP 0FC1 85/44 91/48 91#49 OSTR 0882 4/48 52#28 52/50 PBBH 0F98 77/56 78/ 2 78/ 6 78/ 9 78/13 88/31 88/33 91# 2 U PBKP 0006 4/ 8 PBWH 0F45 87/18 88#22 P41 35# 9 ESCULK 04F7 22/51 33# 6 ESCZZ 04A6 22/44 35#24 ESTR 08A1 52#52 53/12 77/44 77/54 81/29 83/ 4 84/ 4 85/12 87/11 87/33 EXITI 001E 4#22 43/ 3 s FALSE 0000 1/30 1/32 1/33 1/34 1/35 1/36 1/37 1/38 1/39 1/40 1/41 1/44 1/45 52/ 7 53/14 s FCB 005C FDSK 0C20 70/ 8 72/ 8 73/ 2 73/58 75#26 90/22 n FILLC 0872 52# 9 FILLZ 0870 16/51 51#52 U FMTDAT ED80 93/13 FORMT 0F62 10/29 89#17 n FSAVE EFE4 95#44 s FWAVM F000 31/13 31/21 40/12 86/ 6 87/27 GETCH 0F59 83/ 5 88#51 GKEY 066C 8/10 42# 2 GKEYAB 06CB 42/21 43# 5 45/13 45/21 GKEYX 06C8 42/17 42/36 43# 3 43/ 8 47/31 GNRN 0F1E 80/46 80/52 87#43 s H.FDC 2100 66/25 NSCMD 0000 1#38 13/19 s INTBL EFF0 8/11 8/13 96/ 4 INTCMD 0000 1#39 13/21 n INUTIL 0000 1#45 INXCMD 0000 1#40 13/20 INZCMD 0000 1#41 13/22 ISTK EF99 4/17 42/10 95# 5 n IVSAX EFDC 95#34 n IXSAX EFD8 95#32 n IYR EF65 94#34 n IYSAX EFDA 95#33 s K 0400 KBDLY EFC6 8/35 42/40 95#15 s KBDTM 0001 8/34 KEYBT 0E44 79/32 83# 9 KEYLCK EF59 8/27 18/34 33/ 8 42/15 94#16 KEYTM 0E50 84/ 3 84# 8 n LDADR EF57 94#15 LDSEL EF6D 4/46 68/30 68/34 94#54 94/55 LDTRK EF6E 16/55 68/36 94#55 s LF 000A 12/ 4 12/ 4 12/ 4 12/ 4 12/11 12/20 12/27 12/38 12/45 12/45 12/45 18/ 7 23/ 6 50/34 78/29 79/56 79/57 79/58 80/ 2 80/ 3 80/ 4 80/ 5 1IAAD EF61 36/10 46/ 9 47/15 54/27 94#28 PIABD EF62 8/47 20/16 28/10 28/45 30/ 6 30/43 31/ 2 31/17 37/15 40/16 40/37 45/54 46/26 47/ 4 47/ 9 54/46 68/16 69/ 3 76/12 94#29 s PMCHR 003E 9/ 3 POPALL mac 2# 6 4/32 PRVAL 0FAA 91/15 91/18 91#24 n PSAVE EFE8 95#48 PSEKC 0AF1 69# 7 70/26 71/26 90/19 PSTESC 03B7 24/21 24#56 PUNCH 0A79 10/12 64#45 PUSHAL mac 1#54 4/19 42/12 R179X EFC2 78/41 95#14 n RAGS EFD0 95#26 n RDFLAG EF21 93#56 RDKEY 07C6 42/19 47#33 RDSKC 0C68 77#24 78/21 82/12 RDSKD 0C60 68/20 68/45 77#13 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 103 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM READER 0A67 10/13 D 0001 64/19 s SI.S16 0055 8/52 s SI.S64 0056 s SI.TRD 0002 64/38 64/53 SIRST 0A57 8/53 10/30 63#34 SKEX1 0B17 70/28 70/30 70#36 70/45 71/46 SKEY 02A1 10/ 8 18#32 18/48 88/45 SLIDE 0744 42/54 45#47 SLST 0A73 10/23 64#35 SPAO 08B0 8/41 54# 7 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 104 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM SSAVE EFEA 4/44 95#49 STAT17 0CE0 70/39 73/29 78#36 s SVER 0001 s SYS 0005 s SYSDAT 0010 s SYSL 0006 T5KEY 0817 49/ 3 50#27 n T6KEY 0817 50#28 s TAB 0009 50/28 TEM EF00 15/ 5 15/47 16/37 80/45 80/54 85/13 93#21 93/22 n TEMSEC EF20 93#55 TKEY EF5C 8/26 42/24 43/ 7 94#20 s TRUE 80 8/30 16/54 30/20 30/35 30/48 31/15 34/ 4 37/34 38/ 3 38/24 39/21 40/ 9 VLOCK 0023 18#15 22/49 VNORM 03C9 22/18 25#23 27/ 8 27/17 27/26 VOUT80 04D2 25/31 27/36 32# 5 32/42 VOUT85 04E6 32/11 32#18 VOUT90 04E7 29/ 9 30/32 30/53 31/22 31/31 31/34 32/16 32#21 33/18 34/15 34/33 37/49 n VOUT95 04E8 32#24 VOUT96 04E9 32#25 34/53 VOUT97 04EF 23/17 24/55 31/ 8 32#31 32/40 33/ 9 33/28 35/12 36/15 VSAD 0053 18#18 22/35 VSGH 0067 12/ 5 12/12 12/18 12/21 12/28 12/39 18#29 22/36 VSHFT0 0586 23/13 36#17 VSHFTL 0573 23/11 36# 2 VSHFTR 0577 23/12 36# 6 VSHI 0029 18#24 22/38 VSUL 006C 18#26 22/40 VUNDER 03E9 22/22 27# 6 VUN 64#14 64/21 87/13 87/15 87/25 n REGS EFE0 95#39 REPD 002D 19#16 42/46 REPK 0005 19#17 42/37 RKEY 02AC 18#45 18/49 RLWA 0FC6 91#52 91/54 91/55 RNDV EF01 82/ 5 93#22 93/23 ROMRAM EF08 4/26 8/ 7 93#28 ROMSTK EFC1 4/38 79/19 95#10 95/51 RORAME 0133 4/28 10#27 s RSIZE 0040 4/ 6 4/12 4/29 4/36 6/ 2 6/27 8/ 8 10/41 n RTABS 0003 13#38 RTRC EF04 93#24 93/25 RTRY EF05 71/24 71/39 93#25 n RVEC 0100 10# 6 RWEX 0BD0 72/19 72/27 73/14 73#29 74/10 RWEX1 0BD6 72/52 73/ 5 73/26 73#32 73/51 74/16 SAVSEC EF14 16/20 16/45 67/21 71/51 78/ 8 80/19 80/24 93#39 93/43 SAVTRK EF15 16/18 16/30 16/32 67/12 71/13 71/36 77/58 80/17 8 FFFF 1/29 1/31 1/43 TSERI 0ECD 79/36 86#17 TSMSG 0EC0 85/11 86#15 TSTMEM 0E69 79/34 84#10 n UNACNT EF52 94# 9 UNASEC EF55 16/53 94#11 n UNATRK EF53 94#10 UNCUR 0666 28/33 30/ 5 30/18 30/27 31/27 31/40 34/39 37/ 9 40/ 7 41#35 UPTIM 02C6 19#21 42/13 n USER 0005 4# 4 VALCTS 000B 23#19 25/35 VALETS 0010 22#56 25/16 VALIDC 0363 22#57 23/19 25/34 VALIDE 0331 22#30 22/56 25/15 VBRIGH 03CD 25#28 27/13 VCAD 003D 18#17 22/34 VCBEL 0496 23/14 30#54 VCBKS 046A 23/ 8 30#26 VCCLRS 04A6 23/15 31#13 35/24 VCCR 04C0 23/ 6 31#27 VCEOL 0054 18#23 22/48 VCHOME 0453 23/16 30# 3 VCLF 04C9 23/ 7 31#33 VCLRS 001A 18#10 22/43 23/14 VCMCRT 04CE GR 03ED 22/23 27#11 VUNHA 03F1 22/24 27#15 VUNHAG 03F5 22/25 27#20 VUNLK 0022 18#16 22/50 WBOOT 0209 10/ 7 15#45 WBUSY 0C47 70/10 71/50 76/18 76#42 WBUSYX 0C56 76/32 76#57 n WRTYPE EF23 93#58 XDD 0C06 74/ 9 74#17 75/12 75/19 90/34  WBUSYX 0C56 32/16 32#21 33/18 34/15 34/33 37/49 n VOUT95 04E8 32#24 VOUT96 04E9 32#25 34/53 VOUT97 04EF 23/17 24/55 31/ 8 32#31 32/40 33/ 9 33/28 35/12 36/15 VSAD 0053 18#18 22/35 VSGH 0067 12/ 5 12/12 12/18 12/21 12/28 12/39 18#29 22/36 VSHFT0 0586 23/13 36#17 VSHFTL 0573 23/11 36# 2 VSHFTR 0577 23/12 36# 6 VSHI 0029 18#24 22/38 VSUL 006C 18#26 22/40 VUNDER 03E9 22/22 27# 6 VUN0/28 80/47 90/14 93#40 93/44 s SCLFRE 00A0 51/39 SCREEN 0406 27#37 28/37 SDISK EF17 4/41 15/ 8 16/10 68/ 7 77/38 79/48 93#41 93/45 n SDMA 0A85 66#57 SDRV 0A9A 67#30 70/24 71/ 7 72/ 6 76/16 SDRV1 0A9D 68# 8 70/17 SEC6 EF69 4/40 82/ 4 94#41 n SECS EF68 94#40 SEEK 0B26 70#46 72/51 73/50 SEEKA 0B38 71#24 71/41 n SEEKN 0B29 71#13 s SEEKTM 0002 8/56 SEKDEL EF13 8/57 70/ 6 93#37 n SEKDSK EF1B 93#49 n SEKSEC EF18 93#47 s SEKTMO 00FE 72/26 n SEKTRK EF19 93#48 SELDSK 0AFC 10/17 70#15 SETDMA 0A85 10/20 16/16 67# 2 82/18 SETSEC 0A8F 10/19 67#18 SETTRK 0A8A 10/18 67#10 67/29 SETXY 0426 25/ 8 28#28 SHIFT 06D2 42/49 43# 9 s SI.MRS 0057 64/ 3 s SI.RR 23/ 9 31#39 VCMCUP 0461 23/10 30#16 VDELC 0057 18#20 22/45 VDELL 0052 18#22 22/47 37/20 VECTOR 03A5 24#40 26/14 26/19 VEGH 0047 12/ 9 12/12 12/18 12/25 12/36 12/43 18#30 22/37 VEHI 0028 18#25 22/39 VEUL 006D 18#27 22/41 s VFLO FFEA 8/42 28/18 36/18 46/31 46/36 46/39 46/49 46/53 46/56 VGRAPH 04D2 22/19 32# 4 VHAGR 03FB 22/21 27#29 VHALF 03F7 22/20 27#24 VHOME 001E 18#11 23/15 VINC 0051 18#19 22/44 VINL 0045 18#21 22/46 VLDDR 0644 34/48 37/39 40#50 VLDIR 0655 31/16 34/26 38/ 7 39/30 41#18 SORCIM 808x Assembler ver 3.5E 1=/10/91 1<:0; Page 105 Osborne-One Monitor for Model 1 system. E:OCCRAMA .ASM s VLDL 0034 s VLL 002 TITLE 'Monitor Main Loop.' DISDIM ;disable DIM JMP BMON ;reset/restart USER: ;Exit to user program from 'G' command EI ! RET ;Exit from G command .mac IF RSIZE = 48 LIST G ; Level 1 = breakpoint ORG 1*8 IBKP: DI JMP PBKP ;process breakpoint NULINT 2 NULINT 3 ; Level 4 = Keyboard INT4: DI ;Keyboard Interrupt JMP GKEY NULINT 5 ; Level 6 = Serial interrupt NULINT 6 DI ; JMP ILINT LIST * .mac ELSE .pbkp IF def PBKP ORG 1*8 IBKP: DI JMP PBKP ;process breakpoint .pbkp ENDIF .mac ENDIF ILINT: ;Here on unknown interrupt .mac IF RSIZE = 64 DI .mac ENDIF DISDIM STO SP,IESTK ;save interrupted proc stack LDK SP,ISTK ;insure stack in RAM PUSHAL ;save all registers LDK A,'I' STO A,MPCHR ;set prompt to inter level EXITI: ;Exit interrupt code via exiting to RAM and ; then enable or disable ROM code depending on ; the value contained in ROMRAM cell. LD A,H.VIO ;clear interrupt LD A,ROMRAM OR A JNZ RORAME ;if return to RAM, CPM  CMP [hl] INC HL JRZ :4 ;if command match INC HL ! INC HL DJNZ :3 ;if not end JMP ERROR ;if illegal ; Here on command match :4: LD A,[hl] INC HL LD H,[hl] MOV L,A LDK C,2 JMP [hl] ;process command .mac ENDIF page HINT: ;Initialize all dependent hardware. ; Entry None. ; Exit All hardware initialized. ; Set flag indicating in ROM ENAROM DISDIM ;disable DIM bit .mac IF RSIZE = 48 IM0 ;mode 0 machine .mac ELSE LDK HL,GKEY STO HL,INTBL+(4*2) ;set keyboard interrupt IM2 LDK A,high INTBL MOV I,A ;set interrupt page .mac ENDIF ; Initialize keyboard XRA A STO A,BELCNT ;clear bell timer cell STO A,LKEY ;clear last key cell STO A,HKCNT ;clear debounce STO A,ECHOP ;clear echo to list dev STO A,ESCH ;clear ESC hold flag CMA STO A,IDAY ;set date invalid for SETUP.COM STO A,TKEY ;clear holding key STO A,KEYLCK ;indicate NOT locked ; LDK HL,FWAVM ; STO HL,CURS ;set cursor LDK A,VLL STO A,LLIMIT ;set max line limit ; Set keybo CALL CO ;prompt :2: CALL GETCH ;get next char CMP ' ' JRZ :2 ;if leading blank LDK B,NCMDS LDK HL,CTAB :3: CMP [hl] INC HL JRZ :4 ;if command match INC HL ! INC HL DJNZ :3 ;if not end JMP ERROR ;if illegal ; Here on command match :4: LD A,[hl] INC HL LD H,[hl] MOV L,A LDK C,2 JMP [hl] ;process command .mac ENDIF ; Endx BMLOP TITLE 'MROMD - DEBUG MONITOR ROM DATA AND CONSTANTS.' ; ROM STORAGE AND CONSTANTS IBMSG: DB 'Z'-40H,LF,LF,LF,LF DB ESC,VSGH DB 'Q'-40H DB 07FH, 24, 'W'-40H DB 'E'-40H DB ESC,VEGH DB CR,LF DB ESC,VSGH,1, ESC,VEGH DB ' ' DB ESC,'L' DB 'OSBORNE SYSTEM ONE.' DB ESC,'M' DB ' ' DB ESC,VSGH,4, ESC,VEGH DB CR,LF DB ESC,VSGH DB 'A'-40H DB 07FH,24,' ' DB 'D'-40H DB ESC,VEGH DB CR,LF DB ESC,VSGH DB 'A'-40H DB ' ' DB ESC,')' DB ' REV B 227 ' DB ESC,'(' DB ' ' DB 'D'-40H DB ESC,VEGH DB CR,LF DB ESC,VSGH DB 'Z'-40H DB 07FH, 24, 'X'-40H DB 'C'-40H DB ESC,V .mac IF RSIZE = 48 JR RESREG .mac ELSE POPALL LD SP,IESTK ;get users stack back EI ! RET .mac ENDIF .mac IF RSIZE = 64 BMON: DI LDK SP,ROMSTK LDK A,0 STO A,SEC6 STO A,SDISK ;set disk to drive 0 CALL HINT ;Initialize hardware LDK HL,(high MRAM)*100h STO HL,SSAVE ;Initialize User stack in ram LDK HL,0 STO HL,LDSEL ;clear select and last track LDK DE,IBMSG CALL OSTR ;Output initial message JR BMON1 ;continue .mac ENDIF IF * > NMIA MSG 'ILINT code is too large ', * ERROR ENDIF space 4,10 ORG NMIA DI JMP BMON ;NMI page ; Main start up for Monitor. IF RSIZE = 48 BMON: DI LDK SP,ROMSTK LDK A,0 STO A,SEC6 STO A,SDISK ;set disk to drive 0 LDK C,' ' ;fill with blanks CALL FVIO ;clear video memory CALL HINT ;Initialize hardware LDK HL,(high MRAM)*100h STO HL,SSAVE ;Initialize User stack in ram LDK HL,0 STO HL,LDSEL ;clear select and last track LDK DE,IBMSG CALL OSTR ;Output initial message ENDIF ; Get 1st user responard debounce delay cell LK A,KBDTM ;debounce constant STO A,KBDLY ;set debounce-delay cell ; Now function PIA to set starting address ; and continue to move display window over ; the first display line. ; Set cursor as 1-40 on 1st line. CALL SPAO ;set up for output LDK C,VFLO CALL OPAD ;set for -10 char positions ; Set beginning line to 0 LDK A,0 STO A,PIABD ;set data reg MOV C,A CALL OPBD ;set line ; Reset-Master clear the SIO (ACIA) LK C,SI.S16 ;select 16x clock for 1200 baud CALL SIRST ;reset ; Set default seek to as defined by systext LDK A,SEEKTM ;defined from systext STO A,SEKDEL ;set seek step rate ; Set default prompt char LDK A,PMCHR STO A,MPCHR ;set up default EI ! RET page IF * > 100h MSG 'BMON is too long > 100h ',* ERROR ENDIF ORG 100h ; Jump vector for debugger and CP/M RVEC: JMP CBOOT ;cold boot JMP WBOOT ;warm boot JMP SKEY ;keyboard status JMP CI ;keyboard input JMP COUT ;console output JMP LIST ;lisEGH DB CR,LF,LF,LF DB 'INSERT DISK IN DRIVE ' DB ESC,'L' DB 'A' DB ESC,'M' DB ' AND PRESS RETURN' DC '.' ; TABLE OF ALL VALID MONITOR COMMAND CHARACTERS COMAND MACRO CHR,ADR .INCMD IF IN_%1_CMD DB '%1' IF ' %2' <> ' ' DW %2 ELSE DW %1_CMD ENDIF .INCMD ENDIF ENDM CTAB: COMAND A ;ASCII CORE ENTRY COMAND B,CBOOT ;BOOT UP SYSTEM COMAND D ;DISPLAY MEMORY COMAND F ;FILL MEMORY COMAND G ;GO EXECUTE/BREAKPOINT COMAND H ;HEX SUM & DIFFERENCE COMAND M ;MOVE DATA COMAND R ;READ INTEL-FORMAT HEX COMAND S ;SUBSTITUTE DATA INTO MEMORY COMAND X ;EXAMINE REGISTER(S) COMAND T,DIAG ;TESTS DIAGNOSTIC SECTION COMAND Z ;EXAMINE Z80 REGS NCMDS EQU (*-CTAB)/3 ;NUMBER OF VALID COMMANDS SPACE 4,10 ; TABLE OF ALL 8080 REGISTERS. ; EACH ENTRY IN THE RTAB CONSISTS OF: ; DB ASCII NAME ; DB ADDRESS ; DB FLAG, WHERE FLAG IS ; 0= 8 BIT REGISTER ; 1= 16 BIT ; 8X=8 BIT BUT DO NOT DISPLAY IN X COMMAND RTABS EQU 3 ;LENGTH OF EACH REGISTER ENTRY ; ENDX BMROse. BMON1: CALL CI ;Get next character CMP CR LK HL,DSKSWP ;disk swap cell LK C,0 ;boot from A: STO C,[hl] ;set to A=A, B=B JZ CBOOT ;if cold boot IF INDIA INC [hl] ;swap drives: A=B, B=A CMP '"' JZ CBOOT ;if cold boot off of B CMP 'D'-40h JZ DIAG ;if enter debugger JR BMON ELSE JR BMON1 ENDIF ; Here on NMI and RESET ;BMNI: LDK SP,ROMSTK ;Stack must be in RAM (not 0,1 page) ; CALL HINT ;Initialize hardware ; JMP DMON ;enter loop .mac IF RSIZE = 48 RESREG: ;Restore registers and exit interrupt POPALL LD SP,IESTK ;get users stack back EI ! RET .mac ENDIF page .mac IF INDMON ; Main loop for OSB Debug Monitor. ; Entry None. ; Exit To command processor. ; C= 2. DMON: LDK DE,IMMSG CALL OSTR ;output signon message ; Command processor NEXTC: EI LDK SP,ROMSTK ;reset always CALL OCRLF ;new line LD A,MPCHR MOV C,A CALL CO ;prompt :2: CALL GETCH ;get next char CMP ' ' JRZ :2 ;if leading blank LDK B,NCMDS LDK HL,CTAB :3:t output JMP PUNCH ;punch output JMP READER ;reader input ; Disk I/O JMP HOME JMP SELDSK ;select disk JMP SETTRK ;set track JMP SETSEC ;set sector JMP SETDMA ;set DMA JMP DREAD ;Disk read JMP DWRT ;Disk write JMP SLST ;List device status RET ! NOP ! NOP ;Sector translate ; End of standard CP/m functions RORAME: JMP BIOS+BRRXT JMP BIOS+BROMJP JMP FORMT ;Format one track JMP SIRST ;SIO reset ; JMP BIOS+BRDXY ; JMP BIOS+BWTXY JMP IE.CO ;IEEE Control Out JMP IE.SI ; Status In JMP IE.GTS ; Go To Standby JMP IE.TC ; Take Control JMP IE.OIM ; Output Interface Message JMP IE.ODM ; Output Device Message JMP IE.IDM ; Input Device Message JMP IE.PP ; Parallel Poll page .mac IF RSIZE = 48 ; Main loop for OSB Debug Monitor. ; Entry None. ; Exit To command processor. ; C= 2. DMON: LDK DE,IMMSG CALL OSTR ;output signon message ; Command processor NEXTC: EI LDK SP,ROMSTK ;reset always CALL OCRLF ;new line LD A,MPCHR MOV C,A 3MD.ASM BLE OF ALL VALID MONITOR COMMAND CHARACTERS COMAND MACRO CHR,ADR .INCMD IF IN_%1_CMD DB '%1' IF ' %2' <> ' ' DW %2 ELSE DW %1_CMD ENDIF .INCMD ENDIF ENDM CTAB: COMAND A ;ASCII CORE ENTRY COMAND B,CBOOT ;BOOT UP SYSTEM COMAND D ;DISPLAY MEMORY COMAND F ;FILL MEMORY COMAND G ;GO EXECUTE/BREAKPOINT COMAND H ;HEX SUM & DIFFERENCE COMAND M ;MOVE DATA COMAND R ;READ INTEL-FORMAT HEX COMAND S ;SUBSTITUTE DATA INTO MEMORY COMAND X ;EXAMINE REGISTER(S) COMAND T,DIAG ;TESTS DIAGNOSTIC SECTION COMAND Z ;EXAMINE Z80 REGS NCMDS EQU (*-CTAB)/3 ;NUMBER OF VALID COMMANDS SPACE 4,10 ; TABLE OF ALL 8080 REGISTERS. ; EACH ENTRY IN THE RTAB CONSISTS OF: ; DB ASCII NAME ; DB ADDRESS ; DB FLAG, WHERE FLAG IS ; 0= 8 BIT REGISTER ; 1= 16 BIT ; 8X=8 BIT BUT DO NOT DISPLAY IN X COMMAND RTABS EQU 3 ;LENGTH OF EACH REGISTER ENTRY ; ENDX BMROK C,0 ;FILL WITH ZERO .old IF FALSE ; 8080 version MOV A,D OR E RZ ;IF ALL DONE STO C,[hl] INC HL DEC DE JR FILLC ;CONTINUE .old ENDIF FILLC: MOV A,E OR D RZ ; return here if broadcast 0 bytes STO C,[hl] ; 1st byte DEC DE MOV A,E OR D RZ ; return here if broadcast 1 byte MOV B,D MOV C,E ; BC := (count) MOV D,H MOV E,L INC DE ; DE := HL + 1 LDIR ; overlapping move RET space 4,10 OSTR: ;Output string to console ; Entry DE=FWA of source ; Note : OSTR recognizes 7F as an escape sequence ; to repeat char N times. Format is: ; 7F, Repeat count, Char proc LD A,[de] OR A PUSH AF AND 07Fh CMP 07Fh MOV C,A JRNZ :4 ;if not repeat INC DE ! LD A,[de] ! DEC A MOV B,A ;repeat count INC DE ! LD A,[de] ;get repeat char MOV C,A :2: CALL CO ;output char DJNZ :2 ;if not done :4: CALL CO ;output it INC DE POP AF JP OSTR ;if not done RET space 4,13 ESTR: ;Output ENCODED string to console ; Entry DE=FWA of source OR A ;clear cON ;OF DATA THROUGH EACH CORRESPONDING PERIPHERAL DATA LINE. ;A DATA DIRECTION REGISTER BIT SET AT "0" CONFIGURES ;THE CORRESPONDING PERIPHERAL DATA LINE AS AN INPUT. ; ;A RESET AT POWER UP HAS THE EFFECT OF ZEROING ALL PIA REGISTERS. ;THIS WILL SET PA0-PA7, PB0-PB7, CA2, AND CB2 AS INPUTS, ;AND ALL INTERRUPTS DISABLED. ;SIGNALS ATN, REN, AND IFC WILL BE DRIVEN LOW ;UNTIL INITIALIZED BY SOFTWARE. ; ;DATA DIRECTION IS ALWAYS SET FOR OUTPUT FOR THE DATA REGISTER. ;DATA MUST BE SET TO ALL ONES WHEN INPUTTING. ;THE INTERFACE IS IN SOURCE HANDSHAKE MODE IF DATA ENABLE (PB0) ;IS SET TO "0", AND IN ACCEPTOR HANDSHAKE MODE IF SET TO "1". ;WHEN SWITCHING FROM SOURCE TO ACCEPTOR HANDSHAKE, ;ATN WILL ALWAYS BE LOW. ;TAKE CONTROL CAN ONLY BE CALLED FOLLOWING A GO TO STANDBY. ;AFTER A FATAL ERROR, PERFORM AN IFC RESET. ; ;STANDARD VALUES USED: ; ;CCRA 0011(IFC)(DIR)10 ; ;CCRB 0011(REN)(DIR)00 ; ;CPDRA SOURCE DIRECTION 1111_1111 ; DATA DATA ; ;CPDRA ACCEPTOR DIRECTION 1111_1111 ; DATA 1bit LD A,[de] RRC ;normalize char PUSH AF AND 07Fh MOV C,A CALL CO ;output it INC DE POP AF JRNC ESTR ;if not done RET page .old IF FALSE FVIO: ;Fill video memory with fixed data ; Entry C= data to broadcast ; NOTE: Interrupts MUST be disabled.. proc LDK HL,FWAVM LDK DE,LVMEM PUSH HL ! PUSH DE CALL FILLC ;clear main vio POP DE ! POP HL .mac IF RSIZE = 64 ENADIM LDK C,0 ;clear 9th bit :2: MOV A,D ;fill 9th bit memory OR E JRZ :4 ;if done STO C,[hl] INC HL DEC DE JR :2 ;loop :4: DISDIM .mac ENDIF RET .old ENDIF space 4,10 SPAO: ;Set PIA for output LDK A,03h ;CRA1-0, Interrupt inputs CA1 STO A,H.VIO+1 ;set data direction LDK A,0FFh STO A,H.VIO ;set all A lines as output LDK A,0 STO A,H.VIO+3 LDK A,0FFh STO A,H.VIO+2 ;set all B lines as output RET space 4,10 OPAD: ;Output data to pia A register ; Entry C= data ; Exit PIAAD = new value LDK A,4+3 STO A,H.VIO+1 MOV A,C STO A,PIAAD STO A,H.VIO ;send da111_1111 ; ;CPDRB SOURCE DIRECTION 0011_1111 ; DATA 000A_0010 ;A = ATN ; ;CPDRB ACCEPTOR DIRECTION 1101_0111 ; DATA 0100_0101 PAGE ;PIA SIGNAL DEFINITIONS: ;ALL SIGNALS ARE LOW ON THE IEEE BUS WHEN PIA REGISTER CONTAINS "1". ; ; PA0 DIO 1 ; PA1 DIO 2 ; PA2 DIO 3 ; PA3 DIO 4 ; PA4 DIO 5 ; PA5 DIO 6 ; PA6 DIO 7 ; PA7 DIO 8 ; ; CA1 SRQ ; CA2 IFC ; ; PB0 ENABLE DATA OUT (ENABLED WHEN "0") ; PB1 ENABLE NDAC/NRFD (ENABLED WHEN "0") ; PB2 ENABLE EOI/DAV (ENABLED WHEN "0") ; PB3 EOI ; PB4 ATN ; PB5 DAV ; PB6 NDAC ; PB7 NRFD ; ; CB1 NOT USED ; CB2 REN ; ;CONTROL WORD FORMAT ; ;[ 7 ][ 6 ][ 5 ][ 4 ][ 3 ][ 2 ][ 1 ][ 0 ] ; ;[IRQA1][IRQA2][ CA2 CONTROL ][ DDRA][ CA1 CONTROL] ;[IRQB1][IRQB2][ CB2 CONTROL ][ DDRB][ CB1 CONTROL] ; ; IRQA1 0 INTERRUPT FLAG SET BY FALL OF SRQ ; IRQA2 0 NOT USED ; CA2 110 SET IFC HIGH ; 111 SET IFC LOW ; DDRA 0 R/W DATA DIRECTION REGISTER A ; 1 R/W PERIPHERAL REGISTER A ; CA1 10 SET IRQA1 HIGH ON RISE OF SRQ  TITLE 'Hardware PIO function processors.' CDEHL: ;Compare DE to HL as unsigned integers. ; Entry DE,HL set to values to compare ; Exit Zbit set if DE = HL ; Cbit set if DE < HL. ; Uses AF. MOV A,D CMP H RNZ ;If D .ne. H MOV A,E CMP L RNZ ;if DE .ne. HL STC RET space 4,10 CNVBN: ;Convert Ascii to binary ; Entry C= ascii char ; Exit A = char MOV A,C SUI '0' CPI 9+1 RM SUI 7 RET space 4,10 DELAY: ;'N' Milliseconds ; Entry A=Number of Milliseconds to delay ; SCLFRE= (Freq/1000)/25 ; Exit Time passed. Proc PUSH BC MOV C,A :1: LDK A,SCLFRE :2: DEC A ;(4 tics) MOV B,B ;(4 tics) MOV C,C ;(4 tics) JNZ :2 ;(10 tics) If 1 ms not elapsed DEC C JNZ :1 ;If requested msec not done POP BC ;restore registers RET ;SCLFRE: = 2000/22 ;Z80, 2mhz ;...defined in OCCTXT.ast space 4,32 FILLZ: ;Fill block of memory with byte value. ; Entry DE=LENGTH TO broadcast character ; C =character TO broadcast ; HL=FWA TO START broadcast ; EXIT FILL DONE Lta RET space 4,10 OPBD: ;Output data to pia B register ; PIA definition. ; 7 6 5 4 3 2 1 0 ; +--+--+--+--+--+--+--+--+ ; |D1|D0|^G| vert offset | ; +--+--+--+--+--+--+--+--+ ; ; Entry C= data ; Exit PIABD = new value LDK A,4 STO A,H.VIO+3 MOV A,C STO A,PIABD STO A,H.VIO+2 ;send data RET ; endx BMpio TITLE 'BMIEEE.ASM - IEEE-488 INTERFACE.' ; +---------------------------------------+ ; | ENTERED 05/01/81 FROM TNW XEROX, SEH. | ; +---------------------------------------+ ; ;LAST EDITED AT 09:29 ON 11 NOV 80 ; ;THERE ARE FOUR COMMANDS TO THE 6821 ; ; 00 PERIPHERAL/DIRECTION REGISTER A CPDRA ; 01 CONTROL REGISTER A CCRA ; 10 PERIPHERAL/DIRECTION REGISTER B CPDRB ; 11 CONTROL REGISTER B CCRB ; ;BIT 2 OF THE CONTROL REGISTER (A AND B) ALLOWS SELECTION OF EITHER ;A PERIPHERAL INTERFACE REGISTER OR A DATA DIRECTION REGISTER. ;A "1" IN BIT 2 SELECTS THE PERIPHERAL REGISTER. ; ;THE TWO DATA DIRECTION REGISTERS ALLOW CONTROL OF THE DIRECTI4 ; ; IRQB1 0 NOT USED ; IRQB2 0 NOT USED ; CB2 110 SET REN HIGH ; 111 SET REN LOW ; DDRB 0 R/W DATA DIRECTION REGISTER B ; 1 R/W PERIPHERAL REGISTER B ; CB1 00 NOT USED PAGE ;BIOS CALL 1: CONTROL OUT ; ; CAN BE CALLED WHILE IN ANY STATE. ; ; EXITS IN THE CONTROLLER STANDBY STATE (ATN HIGH), ; SOURCE HANDSHAKE MODE ; ;PARAMETER PASSED IN REGISTER C: ; ; BIT 0 IF "1", THE IFC SIGNAL IS SET LOW FOR 101 MICRO-SEC ; AND ALL PIA SIGNALS ARE INITIALIZED ; ; BIT 2 1 ; 0 X NO ACTION ; 1 0 SETS REN HIGH ; 1 1 SETS REN LOW ; IE.CO: PROC PUSH AF PUSH HL BIT 0,C ;CHECK IFC SUB-COMMAND JRZ :B1C20 ;INITIALIZE ALL IEEE-488 SIGNALS LK HL,CCRA STO 0011_1010B,[HL] ;ENABLE SRQ AND SET IFC-OUT LOW LK A,1111_1111B ;DIRECT DATA OUT STO A,CPDRA STO 0011_1110B,[HL] XOR A ;SET DATA TO ZERO STO A,CPDRA LK HL,CCRB STO 0011_0000B,[HL] ;SET REN-OUT HIGH LK A,0011_1111B ;DIRECTION FOR SOURCE HANDSHAKE STO A,CPDRB STO 0011_0100B,[HL] LK A,0000_0010B ;VALUES FORILE IN ANY MODE OR STATE ; ; EXITS IN THE SOURCE HANDSHAKE MODE WITH ATN LOW. ; ;MULTI-LINE MESSAGE IN REGISTER C ; ;ERROR CODE RETURNED IN REGISTER A ; IE.OIM: PROC PUSH HL LK HL,CPDRB SBIT 4,[HL] ;SET ATN LOW BIT 0,[HL] JRZ IE.SHK ;SET-UP FOR SOURCE HANDSHAKE STO 0001_0111B,[HL] ;DISABLE DRIVERS LD A,CCRB CBIT 2,A STO A,CCRB STO 0011_1111B,[HL] ;DIRECTION REGISTER SBIT 2,A STO A,CCRB XOR A ;FLOAT EXTERNAL DATA BUS STO A,CPDRA STO 0001_0010B,[HL] ;CONTROL SIGNAL INITIAL VALUE JR IE.SHK PAGE ;BIOS CALL 6: OUTPUT DEVICE MESSAGE ; ; CAN BE CALLED ONLY WHILE IN THE SOURCE HANDSHAKE MODE ; WITH ATN HIGH OR LOW. ; ; EXITS IN THE SOURCE HANDSHAKE MODE WITH ATN HIGH. ; ;MULTI-LINE MESSAGE IN REGISTER C ;EOI REQUEST IN REGISTER B ; ;ERROR CODE RETURNED IN REGISTER A ; IE.ODM: PROC PUSH HL LK HL,CPDRB CBIT 4,[HL] ;SET ATN HIGH BIT 0,B ;CHECK IF EOI REQUESTED JRZ IE.SHK SBIT 3,[HL] ;PERFORM SOURCE HANDSHAKE IE.SHK: BIT 5,[HL] ; JRNZ :B6C50  TO REGISTERS A AND HL MOV A,H POP DE RET SPACE 4,21 ;BIOS CALL 8: PARALLEL POLL ; ; CAN BE CALLED ONLY WHILE IN THE SOURCE HANDSHAKE MODE ; WITH ATN HIGH OR LOW. ; ; EXITS IN THE SOURCE HANDSHAKE MODE WITH ATN LOW. ; ;PARALLEL POLL VALUE RETURNED IN A. ; IE.PP: PROC PUSH HL LK HL,CPDRA LK A,0001_1011B ;FORM PARALLEL POLL STO A,CPDRB STO 1111_1111B,[HL] ;FLOAT INTERNAL DATA BUS LD A,[HL] ;READ PARALLEL POLL DATA STO 0,[HL] ;RE-STORE SOURCE HANDSHAKE MODE LK HL,CPDRB STO 0001_0010B,[HL] POP HL RET ; ENDX BMIEEE.ASM LOW LD A,CPDRA ;READ DATA MOV D,A LK E,0 ;READ EOI BIT 3,[HL] JRZ :B7C40 LK E,1 :B7C40: CBIT 6,[HL] ;SET NDAC HIGH :B7C50: LK A,255 :B7C60: BIT 5,[HL] JRZ :B7C70 ;DATA VALID DROPPED DEC A JRNZ :B7C60 ;WAIT 1000 MICRO-SEC SBIT 2,E ;SET DATA INVALID TIMEOUT ERROR SBIT 7,E JR :B7C80 :B7C70: SBIT 6,[HL] ;SET NDAC LOW :B7C80: EX DE,HL ;MOVE RESULTS SOURCE HANDSHAKE STO A,CPDRB ;LEAVE IFC LOW FOR 100 MICRO-SEC LK A,25 ;DELAY 100 MICRO-SEC :B1C10: DEC A JRNZ :B1C10 LK A,0011_0110B ;SET IFC HIGH STO A,CCRA :B1C20: BIT 2,C ;CHECK REN SUB-COMMAND JRZ :B1C40 ;SET/CLEAR REN LK A,0011_0000B BIT 1,C JRZ :B1C30 LK A,0011_1000B :B1C30: STO A,CCRB :B1C40: POP HL POP AF RET PAGE ;BIOS CALL 2: STATUS IN ; ; CAN BE CALLED ONLY WHILE IN SOURCE HANDSHAKE MODE. ; ;BIT 0 OF REGISTER A SET IF SRQ IS LOW ; IE.SI: PROC PUSH HL LD A,CPDRA ;CLEAR IRQA1 LK HL,CPDRB ;PULSE ENABLE DAV/EOI CBIT 2,[HL] SBIT 2,[HL] LD A,CCRA ;SET SRQ VALUE IN A AND 1000_0000B RLC A POP HL RET SPACE 4,14 ;BIOS CALL 3: GO TO STANDBY ; ; CAN BE CALLED ONLY WHILE IN SOURCE HANDSHAKE MODE ; ;NO PARAMETERS PASSED ; IE.GTS: PROC PUSH AF LK A,0000_0010B ;SET ATN HIGH STO A,CPDRB XOR A ;FLOAT DATA BUS STO A,CPDRA POP AF RET PAGE ;BIOS CALL 4: TAKE CONTROL ; ; CAN BE CALLED ONLY WHILE IN THE CONTROLLER STANDBY STA;DAC TIMEOUT RE-ENTRY MOV A,C ;PLACE DATA ON BUS STO A,CPDRA LK A,10 :B6C20: BIT 7,[HL] JRZ :B6C30 ;READY FOR DATA DEC A JRNZ :B6C20 ;WAIT FOR 100 MICRO-SEC LK A,1000_0010B ;SET RFD TIMEOUT ERROR JR :B6C80 :B6C30: BIT 6,[HL] JRNZ :B6C40 ;DATA ACCEPTED LOW LK A,1000_0001B ;SET DEVICE NOT PRESENT ERROR JR :B6C80 :B6C40: SBIT 5,[HL] ;SET DAV LOW :B6C50: LK A,255 :B6C60: BIT 6,[HL] JRZ :B6C70 ;DATA ACCEPTED DEC A JRNZ :B6C60 ;WAIT 1000 MICRO-SEC LK A,1000_0100B ;SET DAC TIMEOUT ERROR JR :B6C80 :B6C70: CBIT 5,[HL] ;SET DAV HIGH CBIT 3,[HL] ;SET EOI HIGH XOR A ;REMOVE DATA FROM BUS STO A,CPDRA :B6C80: POP HL RET PAGE ;BIOS CALL 7: INPUT DEVICE MESSAGE ; ; CAN BE CALLED WHILE IN ANY MODE OR STATE ; ; EXITS IN THE ACCEPTOR HANDSHAKE MODE WITH ATN HIGH. ; ;DEVICE MESSAGE RETURNED IN BOTH REGISTERS A AND H ;ERROR CODE RETURNED IN REGISTER L ; IE.IDM: PROC PUSH DE EX DE,HL ;SAVE RE-ENTRY DATA LK HL,CPDRB BIT 0,[HL] JRNZ :B7C10 ;SET-TE ; (ATN HIGH). ; ; EXITS IN THE CONTROLLER ACTIVE STATE (ATN LOW), ; SOURCE HANDSHAKE MODE. ; ;BIT 0 OF REGISTER C SET TO TAKE CONTROL ASYNCHRONOUS ; ;ERROR CODE RETURNED IN REGISTER A. ; IE.TC: PROC PUSH HL LK HL,CPDRB BIT 0,C JRNZ :B4C30 ;TAKE CONTROL SYNCHRONOUSLY STO 0000_0111B,[HL] ;DISABLE DRIVERS LD A,CCRB CBIT 2,A STO A,CCRB STO 1101_0111B,[HL] ;DIRECTION REGISTER SBIT 2,A STO A,CCRB STO 1000_0101B,[HL] ;SET NRFD LOW LK A,25 :B4C10: BIT 5,[HL] JRZ :B4C20 ;DATA VALID HAS DROPPED DEC A JRNZ :B4C10 ;WAIT 100 MICRO-SEC LK A,1000_0001B ;SET DATA VALID TIMEOUT ERROR JR :B4C40 :B4C20: STO 1100_0101B,[HL] ;SET NDAC LOW :B4C30: SBIT 4,[HL] ;SET ATN LOW ;SET-UP FOR SOURCE HANDSHAKE LD A,CCRB CBIT 2,A STO A,CCRB STO 0011_1111B,[HL] ;DIRECTION REGISTER SBIT 2,A STO A,CCRB STO 0001_0010B,[HL] ;CONTROL SIGNAL INITIAL VALUE XOR A ;CLEAR ERROR CODE :B4C40: POP HL RET PAGE ;BIOS CALL 5: OUTPUT INTERFACE MESSAGE ; ; CAN BE CALLED WHUP FOR ACCEPTOR HANDSHAKE STO 0001_0111B,[HL] ;DISABLE DRIVERS LD A,CCRB CBIT 2,A STO A,CCRB STO 1101_0111B,[HL] ;DIRECTION REGISTER SBIT 2,A STO A,CCRB LK A,1111_1111B ;FLOAT INTERNAL DATA BUS STO A,CPDRA STO 0101_0101B,[HL] ;CONTROL SIGNALS INITIAL VALUE STO 0100_0101B,[HL] ;SET ATN HIGH ;PERFORM ACCEPTOR HANDSHAKE :B7C10: BIT 6,[HL] JRZ :B7C50 ;DATA INVALID TIMEOUT ERROR RE-ENTRY CBIT 7,[HL] ;SET NRFD HIGH LK A,10 :B7C20: BIT 5,[HL] JRNZ :B7C30 ;DATA VALID DEC A JRNZ :B7C20 ;WAIT 100 MICRO-SEC LK DE,1000_0010B ;SET DATA VALID TIMEOUT ERROR JR :B7C80 :B7C30: SBIT 7,[HL] ;SET NRFD LOW LD A,CPDRA ;READ DATA MOV D,A LK E,0 ;READ EOI BIT 3,[HL] JRZ :B7C40 LK E,1 :B7C40: CBIT 6,[HL] ;SET NDAC HIGH :B7C50: LK A,255 :B7C60: BIT 5,[HL] JRZ :B7C70 ;DATA VALID DROPPED DEC A JRNZ :B7C60 ;WAIT 1000 MICRO-SEC SBIT 2,E ;SET DATA INVALID TIMEOUT ERROR SBIT 7,E JR :B7C80 :B7C70: SBIT 6,[HL] ;SET NDAC LOW :B7C80: EX DE,HL ;MOVE RESULTS56789:;<=>?@ABCDEFGHIJKL