IMD 1.16: 13/08/2007 18:22:12 cbios 4d2007-00 occbi00a.asm 4d2007-00 occbi001.asm 1d2007-00 occbi00a.prn 1d2007-00 occbi001.prn 4d2007-00 occbi00a.com 4d2007-00 occbi001.com 9/4/81  OCCBIO2AASMOCCBIO1AASMOCCBIO4AASMOCCBIO6AASM OCCBIO7AASM OCCBIO8AASM OCCBIO5AASM OCCBIO3AASM OCCBIO0AASMOCCBIO0ACOMOCCBIO0ACOMOCCBIO0ACOM !"#$%&OCCBIO0ACOMY'()*+,OCCBIO0APRN-./01234OCCBIO0APRN56789:;<OCCBIO0APRN=>?@ABCDOCCBIO0APRN*EFGOCCBIO21ASMHOCCBIO11ASMIJOCCBIO51ASMKLOCCBIO01ASMMOCCBIO41ASMNOOCCBIO61ASM PQOCCBIO71ASMROCCBIO81ASMSTUVWXYZOCCBIO31ASM [OCCTXTA ASTI\]^_OCCTXT3 ASTHOCCBIO01PRN`abcdefgOCCBIO01PRNhijklmnoOCCBIO01PRNpqrstuvwOCCBIO01PRNxyz{|}~ page MRTRY: = 5 ;Maximum number of retries. MSG 'Assemblying BIOS for LWA of ', LWAMEM,'h.' ; CP/M to host disk constants HSTSIZ: = 256 ;Blocking/Deblocking buffer size FPYSIB: = 2048/128 ;Sectors in floppy disk block ; CP/M disk control block equates which define the ; disk types and maximum storage capability of each ; disk type. DSKS1: = 0 ;Single density, single sided. S1DSM: = ((40-3)*2*10)/FPYSIB ; BDOS constants on entry to write WRALL: = 0 ;write to allocated WRDIR: = 1 ;write to directory WRUAL: = 2 ;write to unallocated space 4,10 ; ROM equates. ENROM: = 0 ;Port to enable ROM DIROM: = 1 ;Port to disable ROM page ; Macro for generating Control Blocks for disk drives ; The format of these disk control blocks are as follows: ; 16 bits = -> translation table. ; 48 bits = Work area for CP/M. ; 16 bits = -> DIRBUF. ; 16 bits = -> Parameter block. ; 16 bits = -> check vector. ; 16 bits = -> allocation vector. NDSK: SET 0 ;Number of disk drivesOCCBIO01PRNOCCBIO01PRN`OCCBIO01COMOCCBIO01COMOCCBIO01COMOCCBIO01COMVOCCRAMA ASM"OCCRAM1 ASM page ; Sector Translation Tables. XLTS: ;Translation table 2 to 1 DB 0, 1, 4, 5, 8, 9, 12,13, 16,17 DB 2, 3, 6, 7, 10,11, 14,15, 18,19 ; Translation 3 to 1 ; DB 0, 1, 6, 7, 12,13, 18,19 ; DB 2, 3, 8, 9, 14,15 ; DB 4, 5, 10,11, 16,17 ; Translation 4 to 1 ; DB 0, 1, 8, 9, 16,17 ; DB 2, 3, 10, 11, 18,19 ; DB 4, 5, 12, 13 ; DB 6, 7, 14, 15 IF (*-XLTS) <> (MSEC*2) MSG 'Translation table error',ERROR ENDIF space 4,10 ; Control Blocks for disk drives DPBASE: DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive A: DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive B: space 4,10 ; Disk type definition blocks for each particular mode. DPBS1: ;Single density, single sided. DPBGEN DSKS1,2*MSEC,4,15,1,S1DSM,64,1000000000000000b,3 .AL IF ALVSZ <> ALVS MSG 'Allocation problems ALVS<> ALVSZ, ALVSZ= ',ALVSZ .9 ERROR .AL ENDIF ; endx OSBBIOS2  NOFDD: SET 0 ;Number of floppy disk drives ALVSZ: SET 0 ;Allocation vector size CSVSZ: SET 0 ;Check vector size LIST D,G,M DPHGEN MACRO TYPE,XLATE,DIRBUF,DPBADR NDSK: SET NDSK+1 DW %2 DW 0,0,0 DW %3 DW %4 DW CSV+CSVSZ DW ALV+ALVSZ NOFDD: SET NOFDD+1 CSVSZ: SET CSVSZ+(64/4) ALVSZ: SET ALVSZ+((S1DSM+7)/8) ENDM ; Make sure Systext agrees with assembled size space 4,10 ; Macro for generating the Disk Parameter Blocks. ; ; Disk type definition blocks for each particular mode. ; The format of these areas are as follow: ; 8 bit = disk type code ; 16 bit = Sectors per track ; 8 bit = Block shift ; 8 bit = BS mask ; 8 bit = Extent mask ; 16 bit = Disk size/1024 - 1. ; 16 bit = Directory size. ; 16 bit = Allocation for directory. ; 16 bit = check area size. ; 16 bit = offset to first track. DPBGEN MACRO TYPE,SPT,BSH,BSM,EXM,DSM,DIRSIZ,ALVMSK,OFFSET DB %1 DW %2 DB %3,%4,%5 DW %6-1,%7-1,REV (%8) DW (%7+3)/4 DW %9 ENDM page ; The following jump table defines the entry points ; into the CBIOS for use by CP/M and other external ; routines; therfore the order of these jump cannot ; be modified. The location of these jumps can only ; be modified by 400h locations, which is a restriction ; of MOVCPM. ORG BIOS CALL CBOOT ;Cold boot CALL WBOOT ;Warm boot JMP CONST ;Console status (input) CONIN: CALL ROMCDE ;Console input CONOUT: CALL ROMCDE ;Console output LIST: CALL ROMCDE ;List output PUNCH: CALL ROMCDE ;Punch output READER: CALL ROMCDE ;Reader input JMP HOME ;Set track to zero RSELDK: JMP SELDSK ;Select disk unit JMP SETTRK ;Set track JMP SETSEC ;Set sector JMP SETDMA ;Set Disk Memory Address RRDK: JMP READ ;Read from disk RWDK: JMP WRITE ;Write onto disk CALL ROMCDE ;Return LST: device status JMP SECTRN ;Sector translation routine ; Extensions RRI: JMP ROMRI JMP ROMJMP FMTJ: CALL ROMCDE ;Rom resident call SBAUD: CALL ROMCDE ; IEEE-488 vectors CALL ROMCDE ;Control Out CALL ROMCDE ;Stat T R A C K. ; ; Set track number. The track number is saved for later ; use during a disk transfer operation. ; ; ENTRY BC = track number. SETTRK: STO BC,SEKTRK ;Set track LHLD UNATRK MOV A,L XRA C MOV C,A MOV A,H XRA B ORA C RZ ;If same track ; JMP CUNACT space 4,10 ; Clear Unallocated block count (force pre-reads). CUNACT: XRA A ;A = 0 STO A,UNACNT ;Clear unallocated block count RET space 4,10 ; Set the sector for later use in the disk transfer. No ; actual disk operations are perfomed. ; ; Entry BC = sector number. SETSEC: MOV A,C STO A,TEMSEC ;sector to seek RET space 4,10 ; Set Disk memory address for subsequent disk read or ; write routines. This address is saved in DMAADR until ; the disk transfer is performed. ; ; ENTRY BC = Disk memory address. ; ; EXIT DMAADR = BC. SETDMA: STO BC,DMAADR RET space 4,15 ; Translate sector number from logical to physical. ; ; ENTRY DE = 0, no translation required. ; DE = translation table a page READ: ;a CP/M 128 byte sector. ; ; EXIT A = 0, successful read operation. ; A = 1, unsucessful read operation. ; Z bit = 1, successful read operation. ; Z bit = 0, unsuccessful read operation. CALL MVINFO ;Move information for transfer XRA A ;Set flag to force a read STO A,UNACNT ;Clear sector counter CALL FILL ;Fill buffer with data POP HL POP DE LDK BC,128 ;Move 128 bytes LDIR LD A,ERFLAG ORA A RZ ;If no error XRA A STO A,HSTACT ;Clear host active ORI 001h ;Set error flag RET space 4,20 WRITE: ;the selected 128 byte CP/M sector. ; ; ENTRY C = 0, write to a previously allocated block. ; C = 1, write to the directory. ; C = 2, write to the first sector of unallocated ; data block. ; ; EXIT A = 0, write was successful. ; A = 1, write was unsucessful. ; Z bit = 1, write was successful. ; Z bit = 0, write was unsucessful. CALL MVINFO ;Move information for transfer MOV A,C ;Write type in c STO A,WRTYPE CPI WRUAL JRNZ WRIT2 ;Ius In CALL ROMCDE ;Go To Standby CALL ROMCDE ;Take Control CALL ROMCDE ;Output Interface Message CALL ROMCDE ;Output Device Message CALL ROMCDE ;Input Device Message CALL ROMCDE ;Parallel Poll . ORG BIOS CALL CBOOT ;Cold boot CALL WBOOT ;Warm boot JMP CONST ;Console status (input) CONIN: CALL ROMCDE ;Console input CONOUT: CALL ROMCDE ;Console output LIST: CALL ROMCDE ;List output PUNCH: CALL ROMCDE ;Punch output READER: CALL ROMCDE ;Reader input JMP HOME ;Set track to zero RSELDK: JMP SELDSK ;Select disk unit JMP SETTRK ;Set track JMP SETSEC ;Set sector JMP SETDMA ;Set Disk Memory Address RRDK: JMP READ ;Read from disk RWDK: JMP WRITE ;Write onto disk CALL ROMCDE ;Return LST: device status JMP SECTRN ;Sector translation routine ; Extensions RRI: JMP ROMRI JMP ROMJMP FMTJ: CALL ROMCDE ;Rom resident call SBAUD: CALL ROMCDE ; IEEE-488 vectors CALL ROMCDE ;Control Out CALL ROMCDE ;Statddress. ; BC = sector number to translate. ; ; EXIT HL = translated sector. SECTRN: LDA UNASEC CMP C CNZ CUNACT ;If sectors do not match MOV A,C STO A,LOGSEC MOV L,C MOV H,B ADD HL,DE MOV L,M MVI H,0 RET  ;If same track ; JMP CUNACT space 4,10 ; Clear Unallocated block count (force pre-reads). CUNACT: XRA A ;A = 0 STO A,UNACNT ;Clear unallocated block count RET space 4,10 ; Set the sector for later use in the disk transfer. No ; actual disk operations are perfomed. ; ; Entry BC = sector number. SETSEC: MOV A,C STO A,TEMSEC ;sector to seek RET space 4,10 ; Set Disk memory address for subsequent disk read or ; write routines. This address is saved in DMAADR until ; the disk transfer is performed. ; ; ENTRY BC = Disk memory address. ; ; EXIT DMAADR = BC. SETDMA: STO BC,DMAADR RET space 4,15 ; Translate sector number from logical to physical. ; ; ENTRY DE = 0, no translation required. ; DE = translation table af write to allocated LDK A,2048/128 STO A,UNACNT LD HL,SEKTRK STO HL,UNATRK ;UNATRK = SEKTRK LD A,LOGSEC INC A JR WRIT3 WRIT2: LDK HL,UNACNT LD A,[hl] ORA A JZ WRIT4 ;If no unallocated records DEC [hl] ;dec unalloc record count LD A,UNASEC ;Increment logical sector INC A CPI 2*10 JRNZ WRIT3 ;If not end of track LD HL,UNATRK INC HL STO HL,UNATRK XRA A WRIT3: STO A,UNASEC LDK A,0FFh WRIT4: CALL FILL POP DE POP HL LDK BC,128 LDIR LDK A,1 STO A,HSTWRT ;HSTWRT = 1 LD A,ERFLAG ORA A RNZ ;If any errors occurred LD A,WRTYPE ;write type CPI WRDIR ;to directory? CZ FLUSH ;Force write of directory LD A,ERFLAG ORA A RET page ; FILL - fill host buffer with approprite host sector. ; ; ENTRY A = 0, Read required if not in buffer. ; 0therwise read not required. ; ; EXIT On exit the stack will contain the following ; values: ; POP x ;x = host record address. ; POP y ;y = caller's buffer address.  page ; H O M E ; ; Return disk to home. This routine sets the track number ; to zero. The current host disk buffer is flushed to the ; disk. HOME: CALL FLUSH ;Flush host buffer XRA A STO A,HSTACT ;Clear host active flag STO A,UNACNT ;Clear sector count STO A,SEKTRK STO A,SEKTRK+1 RET space 4,10 SELDSK: ;Select disk drive for next transfer. ; ; ENTRY C = disk selection value (0..15). ; DE and 1 = 0, first call for this disk. ; ; EXIT HL = 0, if drive not selectable. ; HL = DPH address if drive is selected. MOV A,C CPI NDSK JNC SELD1 ;If invalid drive number STO A,SEKDSK MOV L,C MVI H,0 ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 MOV B,E ;save initial bit LDK DE,DPBASE ADD HL,DE ;HL = DPH address PUSH HL LDK DE,100h + (low RSELDK) MOV A,B AND 1 CZ ROMJMP ;Select the disk in reg C POP HL RET SELD1: LDK HL,0 LDA CDISK SUB C RNZ ;If default drive not in error STO A,CDISK RET space 4,10 ; S E T  FILL: STO A,RDFLAG ;Save read flag LDK DE,HSTBUF ;initial offset LDK HL,128 ;128 byte records LD A,SEKSEC ;Get logical sector EX DE,HL RRC JRNC FILL3 ;If low bit not set ADD HL,DE ;Add bias to offset FILL3: EX DE,HL ADD HL,HL ANI 07Fh ;Mask sector STO A,SEKSEC LD HL,DMAADR XTHL ;Set return parameters PUSH DE PUSH HL ;Set return address LDK HL,HSTACT ;host active flag LD A,[hl] STO 1,[hl] ;always becomes 1 ORA A JRZ FILL6 ;If host buffer inactive LDK HL,HSTSEC LDK DE,SEKSEC LDK B,SEKDSK-SEKSEC+1 FILL4: LD A,[de] CMP [hl] JRNZ FILL5 ;If mis-match INC HL INC DE DJNZ FILL4 ;If all bytes not checked RET FILL5: CALL FLUSH ;Flush host buffer FILL6: LD A,SEKDSK ;Move disk and type STO A,HSTDSK STO A,ACTDSK LD HL,SEKTRK STO HL,HSTTRK STO HL,ACTTRK LD A,SEKSEC STO A,HSTSEC STO A,ACTSEC LD A,RDFLAG ORA A RNZ ;If no read required LDK A,0 ;Read JR FINAL space 4,10 ; FLUSH - Write out active host buffer onto dis page ; 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. ; 40-41: Points to where Date and Time are kept ; ; Register C must contain the selected drive, which is ; zero to select the A drive. 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 ; appropriate drive selectionk. FLUSH: LDK HL,HSTWRT LD A,[hl] ORA A RZ ;If host buffer already on disk STO 0,[hl] LD A,HSTDSK ;Move disk and type STO A,ACTDSK LD HL,HSTTRK STO HL,ACTTRK LD A,HSTSEC STO A,ACTSEC LDK A,3 ;Write flag ; JMP FINAL space 4,10 FINAL: ;Preform final transfer processing. ; ; ENTRY A = 0 .. read disk. ; = 3 .. write disk. ; Calls: Rom resident routine to read/write ONE ; sector only. MOV E,A LDK D,0 LDK HL,ROMVEC+3*13 ADD HL,DE STO HL,SAVADR LDK HL,ACTSEC INC [hl] ;update sector+1 LDK A,MRTRY ;Set retry count FNL1: STO A,RTRY ;Clear retry count LD HL,SAVADR EX DE,HL LDK B,1 ;indicate one sector xfer CALL ROMJMP ;process read or write STO A,ERFLAG ;set possible error flag RZ ;If no errors LD A,RTRY ;Get retry counter DEC A JRNZ FNL1 ;If not permanent error ORI 01h STO A,ERFLAG ;Set error flag RET ; endx OSBBIOS6.asm  page ; Physical data buffer address ((DMAADR) or HSTBUF) ; User data buffer address DMAADR: DW 0 ;Lower 16 bits (least, middle) space 4,10 ; BIOS blocking / deblocking flags. HSTACT: DB 0 ;host active flag HSTWRT: DB 0 ;host written flag UNACNT: DB 0 ;unalloc rec CNT UNATRK: DW 0 ;Track UNASEC: DB 255 ;Sector LOGSEC DB 0 ;Logical sector space 4,10 ; CP/M disk work space. ALV: DS ALVS CSV: DS CSVS page ; Disk access information. ; This area is organized into the following groups ; sector number ; track number ; disk drive ; Each of these groups has three cells for the ; current disk request, ACTual disk transfer, ; and active host disk. SEKSEC: DS 1 ;Current request's sector SEKTRK: DS 2 ;Current request's track SEKDSK: DS 1 ;Current request's disk ACTSEC: DS 1 ;Sector to use in transfer operation ACTTRK: DS 2 ;Track to use in transfer operation ACTDSK: DS 1 ;Disk to use in transfer operation HSTSEC: DS 1 ;Active host sector HSTTRK: DS 2 ;Acti value. The exit address ; is to the CCP routine. ; CBOOT: ;Entry A= drive to boot off of. MOV B,A ;save requested drive DISROM MOV A,B ;restore requested drive STO A,CDISK ;force requested drive LDK SP,CCP .autos IF ~ AUTOST LDK HL,SIGNON CALL PRINT ;Output Banner .autos ENDIF XRA A STO A,IOBYTE ;Clear I/O byte .autos IF AUTOST ORI 1 ;indicate cold boot .autos ENDIF JR BCCP ;Do CP/M WBOOT: ;Warm boot LDK SP,CCP CALL HOME ;flush any buffer BCPM: LDK DE,ROMVEC+3*1 ;Set ROM vector address LDK BC,CCP CALL ROMJMP ORA A JRNZ BCPM ;If error in read ORI 0FFh BCCP: ;Entry A = 01, if cold boot ; A = ff, if warm boot PUSH AF ;Save flags LDK BC,DBUF ;Set default data transfer address CALL SETDMA LDK HL,HSTBUF STO HL,DMADR ;set ROM DMA address ; Clear console control ESC cell XRA A STO A,ESCH ;clear ESC ; Set-up low core pointer cells LDK A,0C3h ;Store jumps in low memory STO A,0 STO A,5 LDK HL,BIOS+3 STO HL,1 LDK HL page ; MVINFO Move information necessary for transfer. MVINFO: XRA A STO A,ERFLAG ;Clear error flag LD A,TEMSEC STO A,SEKSEC RET space 4,10 ; Print message terminated by zero byte. ; ; ENTRY HL -> message buffer, terminated by zero. ; ; EXIT HL -> zero byte + 1. ; A = 0. ; Z bit set. ; ; Destroys only HL, Flags, and A registers. PRINT: LD A,[hl] ;Get a character ORA A INC HL RZ ;If zero the terminate PUSH HL MOV C,A CALL CONOUT ;Output to the console POP HL JR PRINT SAVADR: DS 2 ;Disk transfer routine vector IF * > (MRAM-1) MSG 'CBIOS is too long, lwa= ',* .9 ERROR ENDIF ; Endx OSBBIOS8.asm ve host track HSTDSK: DS 1 ;Active host disk space 4,10 ; Disk transfer flags and counters. RTRY: DS 1 ;Retry counter RDFLAG: DS 1 ;Read flag ERFLAG: DS 1 ;Error reporting WRTYPE: DS 1 ;Write operation type SAVSEC: DS 1 ;Save sector ESPACE: ORG LWAMEM-HSTSIZ-128 BIOSTK: LKEY: DB 0 DIRBUF: DS 128 ;Directory buffer HSTBUF: DS HSTSIZ-1 ;Host buffer MSG 'Available exspansion = $',DIRBUF-ESPACE,' bytes.' TITLE 'Cross Reference Listing.'  groups ; sector number ; track number ; disk drive ; Each of these groups has three cells for the ; current disk request, ACTual disk transfer, ; and active host disk. SEKSEC: DS 1 ;Current request's sector SEKTRK: DS 2 ;Current request's track SEKDSK: DS 1 ;Current request's disk ACTSEC: DS 1 ;Sector to use in transfer operation ACTTRK: DS 2 ;Track to use in transfer operation ACTDSK: DS 1 ;Disk to use in transfer operation HSTSEC: DS 1 ;Active host sector HSTTRK: DS 2 ;Acti,BDOS STO HL,6 LDK HL,IDAY STO HL,TIMPTR ;set date-time pointer LDK HL,CAUTO ;Digital Research has informed SORCIM that CP/M 2.2 ;CANNOT be booted off B:. ;Manipulation of CDISK is kept here to avoid the bugs ;which would appear with its disappearance. ;Booting off B: is accomplished with the RAM cell DSKSWP. LD A,CDISK ;use requested drive ; AND 0Fh ;force user #0 ; STO A,BDOS+0336h ;set CP/M internal ; ;'CURDSK' static variable MOV C,A POP AF CMP 1 JRZ GCOLD ;If cold boot LDK HL,WAUTO GCOLD: LD A,[hl] ORA A JZ CCP+3 ;If no auto start line PUSH BC ;Save current drive LDK DE,CCP+7 LDK B,0 MOV C,A LDIR ;Move command line to buffer POP BC JMP CCP ;Go to CPM .autos IF ~ AUTOST SIGNON: DB 'Z'-40h DB 'Osborne Computer System' DB CR,LF,MSIZE/10+'0',MSIZE mod 10 + '0' DB 'K CP/M ',VERS/10+'0','.',VERS mod 10 + '0' DB CBIOSV+'@',CR,LF,0 .autos ENDIF CAUTO: DB CAUTOL DB 'AUTOST ' CAUTOL = *-CAUTO-1 WAUTO: DB WAUTOL DB ' ' WAUTOL =pt entry stk EI ! RET space 4,10 ROMCDE: ;Call ROM resident processor ; Entry DE = resident processor to call biased ; by CBIOS jump vector. ; NOTE: ROM jump vector must match CBIOS vector POP DE ;Get calling address MOV A,E SUI 3 MOV E,A LDK D,high (ROMVEC) LD A,IOBYTE ROMJMP: ;Entry here to jump to ROM function code directly ; Entry DE = ROM jump address ; BC = any parameters DI LDK HL,0 ADD HL,SP ;Old stack to HL LDK SP,BIOSTK PUSH HL ;Save old stack pointer ENAROM EX DE,HL ;ROM jump address to HL CALL GOROM DI PUSH AF ;save status returned DISROM POP AF POP HL ;Restore old stack pointer MOV SP,HL EI ! RET GOROM: EI JMP [hl] ,A OT,C A STO A,ROMRAM POP BC EI ! RET space 4,10 ROMRI: ;Exit ROM resident Interrupt routine. LD A,ROMRAM MOV C,A ;port OT,C A ;set ROM or RAM enabled POP IY POP IX POP HL POP DE POP BC POP AF LD SP,IESTK ;reset to interru ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c *-WAUTO-2 ; Endx OSBBIOS5.asm at CP/M 2.2 ;CANNOT be booted off B:. ;Manipulation of CDISK is kept here to avoid the bugs ;which would appear with its disappearance. ;Booting off B: is accomplished with the RAM cell DSKSWP. LD A,CDISK ;use requested drive ; AND 0Fh ;force user #0 ; STO A,BDOS+0336h ;set CP/M internal ; ;'CURDSK' static variable MOV C,A POP AF CMP 1 JRZ GCOLD ;If cold boot LDK HL,WAUTO GCOLD: LD A,[hl] ORA A JZ CCP+3 ;If no auto start line PUSH BC ;Save current drive LDK DE,CCP+7 LDK B,0 MOV C,A LDIR ;Move command line to buffer POP BC JMP CCP ;Go to CPM .autos IF ~ AUTOST SIGNON: DB 'Z'-40h DB 'Osborne Computer System' DB CR,LF,MSIZE/10+'0',MSIZE mod 10 + '0' DB 'K CP/M ',VERS/10+'0','.',VERS mod 10 + '0' DB CBIOSV+'@',CR,LF,0 .autos ENDIF CAUTO: DB CAUTOL DB 'AUTOST ' CAUTOL = *-CAUTO-1 WAUTO: DB WAUTOL DB ' ' WAUTOL =;OCCBIO0A.ASM TITLE 'Osborne CP/M 2.2 CBIOS.' ;CBIOS - Osborne CP/M 2.2 CBIOS. * 4D2007-00 MASTER .ASM * 2D2007-00 ASSY .ASM * 1D2007-00 LISTING .PRN * 4D1007-00 MASTER .COM * 2D1007-00 ASSY .C0M ; +-----------------------+ ; | | ; | C B I O S | ; | | ; +-----------------------+ ;REV = A ;DATE = 247 AUTOST = TRUE ;If autostart program VERS: EQU 22 space 4,10 ; Link files. link OCCbio1A ;Jump Table link OCCbio2A ;CP/M disk definitions link OCCbio3A ;Unit record I/O link OCCbio4A ;Non data transfer disk link OCCbio5A ;Cold and Warm boot link OCCbio6A ;Disk data transfer I/O link OCCbio7A ;Utility routines link bmram.asm ;Commom ram definitions  ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c page ; C O N S O L S T A T U S ; ; This routine samples the Console status and returns the ; following values in the A register. ; ; EXIT A = 0 (zero), means no character ; currently ready to read. ; ; A = FFh (255), means character ; currently ready to read. CONST: LD A,LKEY ;Get Key hit flag BIT 7,A RZ ;If data not available ORI 0FFh RET space 4,10 ; L i s t S t a t u s. ; ; Return the ready status for the list device. ; ; EXIT A = 0 (zero), list device is not ready to ; accept another character. ; A = FFh (255), list device is ready to accept ; a character. ; See rom code... page SETRRM: ;Set ROM-RAM flag ; Entry A= port to output (setting ROM or RAM enable) ; Exit none. ; Uses A DI PUSH BC MOV C,A OT,C A STO A,ROMRAM POP BC EI ! RET space 4,10 ROMRI: ;Exit ROM resident Interrupt routine. LD A,ROMRAM MOV C,A ;port OT,C A ;set ROM or RAM enabled POP IY POP IX POP HL POP DE POP BC POP AF LD SP,IESTK ;reset to interru ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c  ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c  ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c  ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c  ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!c  ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!cb{Û3FKPï  W0$W@*-?:^Oy2:Oy{o{_:!91>2>2ͼ2P2R22y'2i&))))Ckx!:2C*S}O|ȯ2Ry2 C:UAy2Vi`n&G>2x21ԯ21 K!"2`>22!"!"!c"@!:O(!~OAUTOST 2R]:"ȯ2Py2# >2R*"S:V<!R~<5:U< *S#"S2U>]>2Q:":#̼:"2!!:0)2*!P~6(! #ͼ:22*"":22:!>!Q~6:2*":2>_!'"!4>2*2":= rt program = 0016 VERS: EQU 22 ; Link files. link OCCbio1A ;Jump Table link OCCbio2A ;CP/M disk definitions link OCCbio3A ;Unit record I/O link OCCbio4A ;Non data transfer disk link OCCbio5A ;Cold and Warm boot link OCCbio6A ;Disk data transfer I/O link OCCbio7A ;Utility routines link bmram.asm ;Commom ram definitions SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 2 Osborne CP/M 2.2 CBIOS. D:OCCBIO1A.ASM = 0005 MRTRY: = 5 ;Maximum number of retries. MSG 'Assemblying BIOS for LWA of ', LWAMEM,'h.' 'Assemblying BIOS for LWA of FFFFh.' ; CP/M to host disk constants  DW 0,0,0 DW %3 DW %4 DW CSV+CSVSZ DW ALV+ALVSZ NOFDD: SET NOFDD+1 CSVSZ: SET CSVSZ+(64/4) ALVSZ: SET ALVSZ+((S1DSM+7)/8) ENDM ; Make sure Systext agrees with assembled size ; Macro for generating the Disk Parameter Blocks. ; ; Disk type definition blocks for each particular mode. ; The format of these areas are as follow: ; 8 bit = disk type code ; 16 bit = Sectors per track ; 8 bit = Block shift ; 8 bit = BS mask ; 8 bit = Extent mask ; 16 bit = Disk size/1024 - 1. ; 16 bit = Directory size. ; 16 bit = 2"ɯ2": 2~#O 6  !6  *& . 1 4 7 : = F P [ f q  :2!q: " *M n :c4 *M n :2!cb{Û3FKPï  W0$W@*-?:^Oy2:Oy{o{_:!91>2>2ͼ2P2R22y'2i&))))Ckx!:2C*S}O|ȯ2Ry2 C:UAy2Vi`n&G>2x21ԯ21 K!"2`>22!"!"!c"@!:O(!~OAUTOST 2R]:"ȯ2Py2# >2R*"S:V<!R~<5:U< *S#"S2U>]>2Q:":#̼:"2!!:0)2*!P~6(! #ͼ:22*"":22:!>!Q~6:2*":2>_!'"!4>2*2":=  = 0100 HSTSIZ: = 256 ;Blocking/Deblocking buffer size = 0010 FPYSIB: = 2048/128 ;Sectors in floppy disk block ; CP/M disk control block equates which define the ; disk types and maximum storage capability of each ; disk type. = 0000 DSKS1: = 0 ;Single density, single sided. = 002E S1DSM: = ((40-3)*2*10)/FPYSIB ; BDOS constants on entry to write = 0000 WRALL: = 0 ;write to allocated = 0001 WRDIR: = 1 ;write to directory = 0002 WRUAL: = 2 ;write to unallocated ; ROM equates. = 0000 ENROM: = 0 ;Port to enable ROM = 0001 DIROM: = 1 ;Port to disable ROM SORCIM 808x Assembler ver Allocation for directory. ; 16 bit = check area size. ; 16 bit = offset to first track. DPBGEN MACRO TYPE,SPT,BSH,BSM,EXM,DSM,DIRSIZ,ALVMSK,OFFSET DB %1 DW %2 DB %3,%4,%5 DW %6-1,%7-1,REV (%8) DW (%7+3)/4 DW %9 ENDM SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 4 Osborne CP/M 2.2 CBIOS. D:OCCBIO1A.ASM ; The following jump table defines the entry points ; into the CBIOS for use by CP/M and other external ; routines; therfore the order of these jump cannot ; be modified. The location of these jumps can only ; be modified by 400h locations, which is a restriction ; of MOVCPM. SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 1 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM *ABS 0000 EFEF *CODE EFEF 0000 *DATA EFEF 0000 ;OCCBIO0A.ASM ;CBIOS - Osborne CP/M 2.2 CBIOS. * 4D2007-00 MASTER .ASM * 2D2007-00 ASSY .ASM * 1D2007-00 LISTING .PRN * 4D1007-00 MASTER .COM * 2D1007-00 ASSY .C0M ; +-----------------------+ ; | | ; | C B I O S | ; | | ; +-----------------------+ ;REV = A ;DATE = 247 = FFFF AUTOST = TRUE ;If autosta3.5E 5=/00/;1 1<:03 Page 3 Osborne CP/M 2.2 CBIOS. D:OCCBIO1A.ASM ; Macro for generating Control Blocks for disk drives ; The format of these disk control blocks are as follows: ; 16 bits = -> translation table. ; 48 bits = Work area for CP/M. ; 16 bits = -> DIRBUF. ; 16 bits = -> Parameter block. ; 16 bits = -> check vector. ; 16 bits = -> allocation vector. = 0000 NDSK: SET 0 ;Number of disk drives = 0000 NOFDD: SET 0 ;Number of floppy disk drives = 0000 ALVSZ: SET 0 ;Allocation vector size = 0000 CSVSZ: SET 0 ;Check vector size LIST D,G,M DPHGEN MACRO TYPE,XLATE,DIRBUF,DPBADR NDSK: SET NDSK+1 DW %2  0000 = EA00 ORG BIOS EA00 CD62EB CALL CBOOT ;Cold boot EA03 CD7BEB CALL WBOOT ;Warm boot EA06 C39BEA JMP CONST ;Console status (input) EA09 CDC3EA CONIN: CALL ROMCDE ;Console input EA0C CDC3EA CONOUT: CALL ROMCDE ;Console output EA0F CDC3EA LIST: CALL ROMCDE ;List output EA12 CDC3EA PUNCH: CALL ROMCDE ;Punch output EA15 CDC3EA READER: CALL ROMCDE ;Reader input EA18 C3F5EA JMP HOME ;Set track to zero EA1B C306EB RSELDK: JMP SELDSK ;Select disk unit EA1E C333EB JMP SETTRK ;Set track EA21 C346EB JMP SETSEC ;Set sector EA24 C34BEB JMP SETDMA ;Set Disk Memory Address EA27 C3E5EB RRDK: JMP READ ;Read from disk EA2A C302EC RWDK: JMP WRITE ;Write onto disk EA2D CDC3EA CALL ROMCDE ;Return LST: device status EA30 C350EB JMP SECTRN ;Sector translation routine  DW DPBS1+1 EA77 +30EF DW CSV+CSVSZ EA79 +24EF DW ALV+ALVSZ += 0001 NOFDD: SET NOFDD+1 += 0010 CSVSZ: SET CSVSZ+(64/4) += 0006 ALVSZ: SET ALVSZ+((S1DSM+7)/8) EA7B DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive B: += 0002 NDSK: SET NDSK+1 EA7B +57EA DW XLTS EA7D +0000000000 DW 0,0,0 00 EA83 +80EE DW DIRBUF EA85 +8CEA DW DPBS1+1 EA87 +40EF DW CSV+CSVSZ EA89 +2AEF DW ALV+ALVSZ += 0002 NOFDD: SET NOFDD+1 += 0020 CSVSZ: SET CSVSZ+(64/4) += 000C ALVSZ: SET ALVSZ+((S1DSM+7)/8) SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 6 Osborne CP/M 2.2 CBIOS. D:OCCBIO2A.ASM ; Disk type definition blocks for each particular mode. EA8B DPBS1: ;Single density, single si D:OCCBIO3A.ASM EAA4 SETRRM: ;Set ROM-RAM flag ; Entry A= port to output (setting ROM or RAM enable) ; Exit none. ; Uses A EAA4 DI EAA4 +F3 DB 0F3h EAA5 C5 PUSH BC EAA6 4F MOV C,A EAA7 ED79 $ OT,C A EAA9 3208EF STO A,ROMRAM EAAC C1 POP BC EAAD EI ! RET EAAD +FB DB 0FBh EAAE +C9 RET EAAF ROMRI: ;Exit ROM resident Interrupt routine. EAAF 3A08EF LD A,ROMRAM EAB2 4F MOV C,A ;port EAB3 ED79 $ OT,C A ;set ROM or RAM enabled EAB5 FDE1 $ POP IY EAB7 DDE1 $ POP IX EAB9 E1 POP HL EABA D1 POP DE EABB C1 POP BC EABC F1 POP AF EABD ED7B6FEF $ LD SP,IESTK ;reset to interrupt entry stk EAC1 EI ! RET EAC1 +FB  ; Extensions EA33 C3AFEA RRI: JMP ROMRI EA36 C3CDEA JMP ROMJMP EA39 CDC3EA FMTJ: CALL ROMCDE ;Rom resident call EA3C CDC3EA SBAUD: CALL ROMCDE ; IEEE-488 vectors EA3F CDC3EA CALL ROMCDE ;Control Out EA42 CDC3EA CALL ROMCDE ;Status In EA45 CDC3EA CALL ROMCDE ;Go To Standby EA48 CDC3EA CALL ROMCDE ;Take Control EA4B CDC3EA CALL ROMCDE ;Output Interface Message EA4E CDC3EA CALL ROMCDE ;Output Device Message EA51 CDC3EA CALL ROMCDE ;Input Device Message EA54 CDC3EA CALL ROMCDE ;Parallel Poll SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 5 Osborne CP/M 2.2 CBIOS. D:OCCBIO2A.ASM ; Sector Translation Tables. EA57 XLTS: ;Translation table 2 to 1 EA57 0001040508 DB 0, 1, 4, ded. EA8B DPBGEN DSKS1,2*MSEC,4,15,1,S1DSM,64,1000000000000000b,3 EA8B +00 DB DSKS1 EA8C +1400 DW 2*MSEC EA8E +040F01 DB 4,15,1 EA91 +2D003F0080 DW S1DSM-1,64-1,REV (1000000000000000B) 00 EA97 +1000 DW (64+3)/4 EA99 +0300 DW 3 = 0000 .AL IF ALVSZ <> ALVS - MSG 'Allocation problems ALVS<> ALVSZ, ALVSZ= ',ALVSZ - .9 ERROR .AL ENDIF ; endx OSBBIOS2 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 7 Osborne CP/M 2.2 CBIOS. D:OCCBIO3A.ASM ; C O N S O L S T A T U S ; ; This routine samples the Console status and returns the ; following values in the A register. DB 0FBh EAC2 +C9 RET EAC3 ROMCDE: ;Call ROM resident processor ; Entry DE = resident processor to call biased ; by CBIOS jump vector. ; NOTE: ROM jump vector must match CBIOS vector EAC3 D1 POP DE ;Get calling address EAC4 7B MOV A,E EAC5 D603 SUI 3 EAC7 5F MOV E,A EAC8 1601 LDK D,high (ROMVEC) EACA 3A0300 LD A,IOBYTE EACD ROMJMP: ;Entry here to jump to ROM function code directly ; Entry DE = ROM jump address ; BC = any parameters EACD DI EACD +F3 DB 0F3h EACE 210000 LDK HL,0 EAD1 39 ADD HL,SP ;Old stack to HL EAD2 31C1EF LDK SP,BIOSTK EAD5 E5 PUSH HL ;Save old stack pointer EAD6 ENAROM SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 P5, 8, 9, 12,13, 16,17 090C0D1011 EA61 020306070A DB 2, 3, 6, 7, 10,11, 14,15, 18,19 0B0E0F1213 ; Translation 3 to 1 ; DB 0, 1, 6, 7, 12,13, 18,19 ; DB 2, 3, 8, 9, 14,15 ; DB 4, 5, 10,11, 16,17 ; Translation 4 to 1 ; DB 0, 1, 8, 9, 16,17 ; DB 2, 3, 10, 11, 18,19 ; DB 4, 5, 12, 13 ; DB 6, 7, 14, 15 = 0000 IF (*-XLTS) <> (MSEC*2) - MSG 'Translation table error',ERROR ENDIF ; Control Blocks for disk drives EA6B DPBASE: EA6B DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive A: += 0001 NDSK: SET NDSK+1 EA6B +57EA DW XLTS EA6D +0000000000 DW 0,0,0 00 EA73 +80EE DW DIRBUF EA75 +8CEA ; ; EXIT A = 0 (zero), means no character ; currently ready to read. ; ; A = FFh (255), means character ; currently ready to read. EA9B 3A5EEF CONST: LD A,LKEY ;Get Key hit flag EA9E CB7F $ BIT 7,A EAA0 C8 RZ ;If data not available EAA1 F6FF ORI 0FFh EAA3 C9 RET ; L i s t S t a t u s. ; ; Return the ready status for the list device. ; ; EXIT A = 0 (zero), list device is not ready to ; accept another character. ; A = FFh (255), list device is ready to accept ; a character. ; See rom code... SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 8 Osborne CP/M 2.2 CBIOS. age 9 Osborne CP/M 2.2 CBIOS. D:OCCBIO3A.ASM EAD6 + DI EAD6 +F3 DB 0F3h EAD7 +D300 OUT 0 EAD9 +3E00 LDK A,0 EADB +3208EF STO A,ROMRAM EADE + EI EADE +FB DB 0FBh EADF EB EX DE,HL ;ROM jump address to HL EAE0 CDF3EA CALL GOROM EAE3 DI EAE3 +F3 DB 0F3h EAE4 F5 PUSH AF ;save status returned EAE5 DISROM EAE5 + DI EAE5 +F3 DB 0F3h EAE6 +D301 OUT 1 EAE8 +3E01 LDK A,1 EAEA +3208EF STO A,ROMRAM EAED + EI EAED +FB DB 0FBh EAEE F1 POP AF EAEF E1 POP HL ;Restore old stack pointer EAF0 F9 MOV SP,HL EAF1 EI ! RET EAF1 +FB DB 0FBh EAF2 +C9 RET EAF3 GOROM: EI EAF3 +FB DB 0FBh EAF4 E9  RNZ ;If default drive not in error EB2F 320400 STO A,CDISK EB32 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 11 Osborne CP/M 2.2 CBIOS. D:OCCBIO4A.ASM ; S E T T R A C K. ; ; Set track number. The track number is saved for later ; use during a disk transfer operation. ; ; ENTRY BC = track number. EB33 SETTRK: EB33 ED4319EF $ STO BC,SEKTRK ;Set track EB37 2A53EF LHLD UNATRK EB3A 7D MOV A,L EB3B A9 XRA C EB3C 4F MOV C,A EB3D 7C MOV A,H EB3E A8 XRA B EB3F B1 ORA C EB40 C8 RZ ;If same track ; JMP CUNACT ; Clear Unallocated block count (force pre-reads). BIO5A.ASM ; 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. ; 40-41: Points to where Date and Time are kept ; ; Register C must contain the selected drive, which is ; zero to select the A drive. The exit address is to ; the CCP routine. ; ;  JMP [hl] SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 10 Osborne CP/M 2.2 CBIOS. D:OCCBIO4A.ASM ; H O M E ; ; Return disk to home. This routine sets the track number ; to zero. The current host disk buffer is flushed to the ; disk. EAF5 HOME: EAF5 CDBCEC CALL FLUSH ;Flush host buffer EAF8 AF XRA A EAF9 3250EF STO A,HSTACT ;Clear host active flag EAFC 3252EF STO A,UNACNT ;Clear sector count EAFF 3219EF STO A,SEKTRK EB02 321AEF STO A,SEKTRK+1 EB05 C9 RET EB06 SELDSK: ;Select disk drive for next transfer. ; ; ENTRY C = disk selection value (0..15). ; DE and 1 = 0, first call for this disk. ;  EB41 AF CUNACT: XRA A ;A = 0 EB42 3252EF STO A,UNACNT ;Clear unallocated block count EB45 C9 RET ; Set the sector for later use in the disk transfer. No ; actual disk operations are perfomed. ; ; Entry BC = sector number. EB46 79 SETSEC: MOV A,C EB47 3220EF STO A,TEMSEC ;sector to seek EB4A C9 RET ; Set Disk memory address for subsequent disk read or ; write routines. This address is saved in DMAADR until ; the disk transfer is performed. ; ; ENTRY BC = Disk memory address. ; ; EXIT DMAADR = BC. EB4B SETDMA: EB4B ED4311EF $ STO BC,DMAADR EB4F C9 RET SORCIM 808x Assembler ver 3.5E ; 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 ; appropriate drive selection value. The exit address ; is to the CCP routine. ; EB62 CBOOT: ;Entry A= drive to boot off of. EB62 47 MOV B,A ;save requested drive EB63 DISROM EB63 + DI EB63 +F3 DB 0F3h EB64 +D301 OUT 1 EB66 +3E01 LDK A,1 EB68 +3208EF STO A,ROMRAM EB6B + EI EB6B +FB DB 0FBh EB6C 78 MOV A,B ;restore requested drive ; EXIT HL = 0, if drive not selectable. ; HL = DPH address if drive is selected. EB06 79 MOV A,C EB07 FE02 CPI NDSK EB09 D227EB JNC SELD1 ;If invalid drive number EB0C 321BEF STO A,SEKDSK EB0F 69 MOV L,C EB10 2600 MVI H,0 EB12 29 ADD HL,HL ;*2 EB13 29 ADD HL,HL ;*4 EB14 29 ADD HL,HL ;*8 EB15 29 ADD HL,HL ;*16 EB16 43 MOV B,E ;save initial bit EB17 116BEA LDK DE,DPBASE EB1A 19 ADD HL,DE ;HL = DPH address EB1B E5 PUSH HL EB1C 111B01 LDK DE,100h + (low RSELDK) EB1F 78 MOV A,B EB20 E601 AND 1 EB22 CCCDEA CZ ROMJMP ;Select the disk in reg C EB25 E1 POP HL EB26 C9 RET EB27 210000 SELD1: LDK HL,0 EB2A 3A0400 LDA CDISK EB2D 91 SUB C EB2E C0  5=/00/;1 1<:03 Page 12 Osborne CP/M 2.2 CBIOS. D:OCCBIO4A.ASM ; Translate sector number from logical to physical. ; ; ENTRY DE = 0, no translation required. ; DE = translation table address. ; BC = sector number to translate. ; ; EXIT HL = translated sector. EB50 SECTRN: EB50 3A55EF LDA UNASEC EB53 B9 CMP C EB54 C441EB CNZ CUNACT ;If sectors do not match EB57 79 MOV A,C EB58 3256EF STO A,LOGSEC EB5B 69 MOV L,C EB5C 60 MOV H,B EB5D 19 ADD HL,DE EB5E 6E MOV L,M EB5F 2600 MVI H,0 EB61 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 13 Osborne CP/M 2.2 CBIOS. D:OCC EB6D 320400 STO A,CDISK ;force requested drive EB70 3100D4 LDK SP,CCP = 0000 .autos IF ~ AUTOST - LDK HL,SIGNON - CALL PRINT ;Output Banner .autos ENDIF EB73 AF XRA A EB74 320300 STO A,IOBYTE ;Clear I/O byte = FFFF .autos IF AUTOST EB77 F601 ORI 1 ;indicate cold boot .autos ENDIF EB79 1814 ^EB8F$ JR BCCP ;Do CP/M EB7B WBOOT: ;Warm boot EB7B 3100D4 LDK SP,CCP EB7E CDF5EA CALL HOME ;flush any buffer EB81 110301 BCPM: LDK DE,ROMVEC+3*1 ;Set ROM vector address SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 14 Osborne CP/M 2.2 CBIOS. D:OCCBIO5A.ASM EB84 0100D4 LDK BC,CCP EB87 CDCDEA CALL ROMJMP EB8A B7 ORA A EB8B 20F4 ^EB81$ JRNZ BCPM 4F MOV C,A EBD5 EDB0 $ LDIR ;Move command line to buffer EBD7 C1 POP BC EBD8 C300D4 JMP CCP ;Go to CPM SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 15 Osborne CP/M 2.2 CBIOS. D:OCCBIO5A.ASM = 0000 .autos IF ~ AUTOST - SIGNON: - DB 'Z'-40h - DB 'Osborne Computer System' - DB CR,LF,MSIZE/10+'0',MSIZE mod 10 + '0' - DB 'K CP/M ',VERS/10+'0','.',VERS mod 10 + '0' - DB CBIOSV+'@',CR,LF,0 .autos ENDIF EBDB 07 CAUTO: DB CAUTOL EBDC 4155544F53 DB 'AUTOST ' 5420 = 0007 CAUTOL = *-CAUTO-1 EBE3 00 WAUTO: DB WAUTOL EBE4 20 DB ' ' = 0000 WAUTOL = *-WAUTO-2  LDK A,2048/128 EC0F 3252EF STO A,UNACNT EC12 2A19EF LD HL,SEKTRK EC15 2253EF STO HL,UNATRK ;UNATRK = SEKTRK EC18 3A56EF LD A,LOGSEC EC1B 3C INC A EC1C 1819 ^EC37$ JR WRIT3 EC1E 2152EF WRIT2: LDK HL,UNACNT EC21 7E LD A,[hl] EC22 B7 ORA A EC23 CA3CEC JZ WRIT4 ;If no unallocated records EC26 35 DEC [hl] ;dec unalloc record count EC27 3A55EF LD A,UNASEC ;Increment logical sector SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 17 Osborne CP/M 2.2 CBIOS. D:OCCBIO6A.ASM EC2A 3C INC A EC2B FE14 CPI 2*10 EC2D 2008 ^EC37$ JRNZ WRIT3 ;If not end of track EC2F 2A53EF LD HL,UNATRK EC32 23 INC HL EC33 2253EF STO HL,UNATRK EC36 AF XRA A EC37 3255EF WRIT3: STO A,UNASEC EC3A 3EFF ;If error in read EB8D F6FF ORI 0FFh EB8F BCCP: ;Entry A = 01, if cold boot ; A = ff, if warm boot EB8F F5 PUSH AF ;Save flags EB90 018000 LDK BC,DBUF ;Set default data transfer address EB93 CD4BEB CALL SETDMA EB96 2180ED LDK HL,HSTBUF EB99 220FEF STO HL,DMADR ;set ROM DMA address ; Clear console control ESC cell EB9C AF XRA A EB9D 3260EF STO A,ESCH ;clear ESC ; Set-up low core pointer cells EBA0 3EC3 LDK A,0C3h ;Store jumps in low memory EBA2 320000 STO A,0 EBA5 320500 STO A,5 EBA8 2103EA LDK HL,BIOS+3 EBAB 220100 STO HL,1 EBAE 2106DC LDK HL,BDOS EBB1 220600 STO HL,6 EBB4 2163EF LDK HL,IDAY EBB7 224000 STO HL,TIMPTR ;set date-time pointer EBBA 21DBEB  ; Endx OSBBIOS5.asm SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 16 Osborne CP/M 2.2 CBIOS. D:OCCBIO6A.ASM EBE5 READ: ;a CP/M 128 byte sector. ; ; EXIT A = 0, successful read operation. ; A = 1, unsucessful read operation. ; Z bit = 1, successful read operation. ; Z bit = 0, unsuccessful read operation. EBE5 CD04ED CALL MVINFO ;Move information for transfer EBE8 AF XRA A ;Set flag to force a read EBE9 3252EF STO A,UNACNT ;Clear sector counter EBEC CD5DEC CALL FILL ;Fill buffer with data EBEF E1 POP HL EBF0 D1 POP DE EBF1 018000 LDK BC,128 ;Move 128 bytes EBF4 EDB0 $ LDIR EBF6 3A22EF LD A,ERFLAG EBF9 B7 ORA A EBFA C8 RZ ;If no  LDK A,0FFh EC3C CD5DEC WRIT4: CALL FILL EC3F D1 POP DE EC40 E1 POP HL EC41 018000 LDK BC,128 EC44 EDB0 $ LDIR EC46 3E01 LDK A,1 EC48 3251EF STO A,HSTWRT ;HSTWRT = 1 EC4B 3A22EF LD A,ERFLAG EC4E B7 ORA A EC4F C0 RNZ ;If any errors occurred EC50 3A23EF LD A,WRTYPE ;write type EC53 FE01 CPI WRDIR ;to directory? EC55 CCBCEC CZ FLUSH ;Force write of directory EC58 3A22EF LD A,ERFLAG EC5B B7 ORA A EC5C C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 18 Osborne CP/M 2.2 CBIOS. D:OCCBIO6A.ASM ; FILL - fill host buffer with approprite host sector. ; ; ENTRY A = 0, Read required if not in buffer. ; 0therwise read not reqLDK HL,CAUTO ;Digital Research has informed SORCIM that CP/M 2.2 ;CANNOT be booted off B:. ;Manipulation of CDISK is kept here to avoid the bugs ;which would appear with its disappearance. ;Booting off B: is accomplished with the RAM cell DSKSWP. EBBD 3A0400 LD A,CDISK ;use requested drive ; AND 0Fh ;force user #0 ; STO A,BDOS+0336h ;set CP/M internal ; ;'CURDSK' static variable EBC0 4F MOV C,A EBC1 F1 POP AF EBC2 FE01 CMP 1 EBC4 2803 ^EBC9$ JRZ GCOLD ;If cold boot EBC6 21E3EB LDK HL,WAUTO EBC9 7E GCOLD: LD A,[hl] EBCA B7 ORA A EBCB CA03D4 JZ CCP+3 ;If no auto start line EBCE C5 PUSH BC ;Save current drive EBCF 1107D4 LDK DE,CCP+7 EBD2 0600 LDK B,0 EBD4 error EBFB AF XRA A EBFC 3250EF STO A,HSTACT ;Clear host active EBFF F601 ORI 001h ;Set error flag EC01 C9 RET EC02 WRITE: ;the selected 128 byte CP/M sector. ; ; ENTRY C = 0, write to a previously allocated block. ; C = 1, write to the directory. ; C = 2, write to the first sector of unallocated ; data block. ; ; EXIT A = 0, write was successful. ; A = 1, write was unsucessful. ; Z bit = 1, write was successful. ; Z bit = 0, write was unsucessful. EC02 CD04ED CALL MVINFO ;Move information for transfer EC05 79 MOV A,C ;Write type in c EC06 3223EF STO A,WRTYPE EC09 FE02 CPI WRUAL EC0B 2011 ^EC1E$ JRNZ WRIT2 ;If write to allocated EC0D 3E10 uired. ; ; EXIT On exit the stack will contain the following ; values: ; POP x ;x = host record address. ; POP y ;y = caller's buffer address. EC5D 3221EF FILL: STO A,RDFLAG ;Save read flag EC60 1180ED LDK DE,HSTBUF ;initial offset EC63 218000 LDK HL,128 ;128 byte records EC66 3A18EF LD A,SEKSEC ;Get logical sector EC69 EB EX DE,HL EC6A 0F RRC EC6B 3001 ^EC6E$ JRNC FILL3 ;If low bit not set EC6D 19 ADD HL,DE ;Add bias to offset EC6E EB FILL3: EX DE,HL EC6F 29 ADD HL,HL EC70 E67F ANI 07Fh ;Mask sector EC72 3218EF STO A,SEKSEC EC75 2A11EF LD HL,DMAADR EC78 E3 XTHL ;Set return parameters EC79 D5 PUSH DE EC7A E5 PUSH HL ;Set return address EC7B FINAL: ;Preform final transfer processing. ; ; ENTRY A = 0 .. read disk. ; = 3 .. write disk. ; Calls: Rom resident routine to read/write ONE ; sector only. ECD8 5F MOV E,A ECD9 1600 LDK D,0 ECDB 212701 LDK HL,ROMVEC+3*13 ECDE 19 ADD HL,DE ECDF 221BED STO HL,SAVADR ECE2 2114EF LDK HL,ACTSEC ECE5 34 INC [hl] ;update sector+1 ECE6 3E05 LDK A,MRTRY ;Set retry count ECE8 3205EF FNL1: STO A,RTRY ;Clear retry count ECEB 2A1BED LD HL,SAVADR ECEE EB EX DE,HL ECEF 0601 LDK B,1 ;indicate one sector xfer ECF1 CDCDEA CALL ROMJMP ;process read or write ECF4 3222EF STO A,ERFLAG ;set possible error flag ECF7 C8 RZ ;If no errors ECF8 3A05EF LD A,RTRY ;Get retry counter ECFB 3.5E 5=/00/;1 1<:03 Page 22 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM ;MRAM - Debug Monitor RAM Storage. ; Used to assembly ROM resident and CBIOS ED1D = ED80 ORG MRAM ; Host disk xfer buffer and... ; Format track template holding buffer ED80 HSTBUF: = 0000 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 ( 2150EF LDK HL,HSTACT ;host active flag EC7E 7E LD A,[hl] EC7F 3601 STO 1,[hl] ;always becomes 1 EC81 B7 ORA A EC82 2814 ^EC98$ JRZ FILL6 ;If host buffer inactive EC84 211CEF LDK HL,HSTSEC EC87 1118EF LDK DE,SEKSEC EC8A 0604 LDK B,SEKDSK-SEKSEC+1 EC8C 1A FILL4: LD A,[de] EC8D BE CMP [hl] EC8E 2005 ^EC95$ JRNZ FILL5 ;If mis-match EC90 23 INC HL EC91 13 INC DE EC92 10F8 ^EC8C$ DJNZ FILL4 ;If all bytes not checked EC94 C9 RET EC95 CDBCEC FILL5: CALL FLUSH ;Flush host buffer EC98 3A1BEF FILL6: LD A,SEKDSK ;Move disk and type EC9B 321FEF STO A,HSTDSK EC9E 3217EF STO A,ACTDSK ECA1 2A19EF LD HL,SEKTRK ECA4 221DEF STO HL,HSTTRK ECA7 2215EF STO HL,ACTTRK ECAA 3A18EF LD A,SEKSEC ECAD 321CEF STO A,HSTSEC ECB0 3214EF  3D DEC A ECFC 20EA ^ECE8$ JRNZ FNL1 ;If not permanent error ECFE F601 ORI 01h ED00 3222EF STO A,ERFLAG ;Set error flag ED03 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 20 Osborne CP/M 2.2 CBIOS. D:OCCBIO6A.ASM ; endx OSBBIOS6.asm SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 21 Osborne CP/M 2.2 CBIOS. D:OCCBIO7A.ASM ; MVINFO Move information necessary for transfer. ED04 MVINFO: ED04 AF XRA A ED05 3222EF STO A,ERFLAG ;Clear error flag ED08 3A20EF LD A,TEMSEC ED0B 3218EF STO A,SEKSEC ED0E C9 RET ; Print message terminated by zero byte. ; ; ENTRY H256+128)-(*-HSTBUF) 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 *********REDEFINED************* EF09 = 0000 MSECB DS 0 ;MULTI SECTOR BYTES FOR R/W **********not used************* 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  STO A,ACTSEC ECB3 3A21EF LD A,RDFLAG ECB6 B7 ORA A ECB7 C0 RNZ ;If no read required SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 19 Osborne CP/M 2.2 CBIOS. D:OCCBIO6A.ASM ECB8 3E00 LDK A,0 ;Read ECBA 181C ^ECD8$ JR FINAL ; FLUSH - Write out active host buffer onto disk. ECBC FLUSH: ECBC 2151EF LDK HL,HSTWRT ECBF 7E LD A,[hl] ECC0 B7 ORA A ECC1 C8 RZ ;If host buffer already on disk ECC2 3600 STO 0,[hl] ECC4 3A1FEF LD A,HSTDSK ;Move disk and type ECC7 3217EF STO A,ACTDSK ECCA 2A1DEF LD HL,HSTTRK ECCD 2215EF STO HL,ACTTRK ECD0 3A1CEF LD A,HSTSEC ECD3 3214EF STO A,ACTSEC ECD6 3E03 LDK A,3 ;Write flag ; JMP FINAL ECD8 L -> message buffer, terminated by zero. ; ; EXIT HL -> zero byte + 1. ; A = 0. ; Z bit set. ; ; Destroys only HL, Flags, and A registers. ED0F 7E PRINT: LD A,[hl] ;Get a character ED10 B7 ORA A ED11 23 INC HL ED12 C8 RZ ;If zero the terminate ED13 E5 PUSH HL ED14 4F MOV C,A ED15 CD0CEA CALL CONOUT ;Output to the console ED18 E1 POP HL ED19 18F4 ^ED0F$ JR PRINT ED1B = 0002 SAVADR: DS 2 ;Disk transfer routine vector = 0000 IF * > (MRAM-1) - MSG 'CBIOS is too long, lwa= ',* - .9 ERROR ENDIF ; Endx OSBBIOS8.asm SORCIM 808x Assembler ver ; Note order of xxxSEC,xxxTRK,xxxDSK must be maintained ; 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) SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 23 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM = 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  ; 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 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 ; 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 *) <> (high ROMSTK) - .9 DW *, STK, must be equal ENDIF ;TEMP: DS 1 ;TEMPORARY MONITOR CELL EFEC = 0002 BKPA: DS 2 ;last breakpoint address EFEE = 0001 BKPC: DS 1 ;Contents of bkp = 0000 IF * >= LWAMEM - MSG 'RAM temporary area too large ',* - .9 ERROR ENDIF = 0000 IF * > INTBL - .9 ERROR - MSG 'RAM overflow into Int Vector ', * ENDIF ; Interrupt Jump Vector is between EFFO, EFFF. SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 26 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM ; Endx MRAM no ERRORs, 356 Labels, 72D7h bytes not used. ProTEMSEC DS 1 ;Used in bios only EF21 = 0001 RDFLAG DS 1 ;Read flag EF22 = 0001 ERFLAG DS 1 ;Error reporting 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 ; EFC1 = 0001 ACIAD: DS 1 ;last command byte written to ACIA 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 EFC8 += 0008 DS (*+(10H)-1)/(10H)*(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 gram LWA = EFEFh.  s @FREQ 0FA0 n ACIAD EFC1 24#28 ACTDSK EF17 18/48 19/17 23# 4 ACTSEC EF14 18/54 19/21 19/40 23# 2 ACTTRK EF15 18/51 19/19 23# 3 n AFSAX EFD4 24#46 s ALIGN mac 24/42 24/56 ALV EF24 5/36 5/49 23#19 s ALVS 000C 6/14 23/19 ALVSZ 000C 3#12 5/36 5/39 5#39 5/49 5/52 5#52 6/14 n ASAVE EFE5 25# 6 AUTOST FFFF 1#22 13/42 13/48 14/58 BCCP EB8F 13/51 14# 8 BCPM EB81 13#57 14/ 4 n BCSAX EFD2 24#45 s BDOS DC06 14/26 n BELCNT EF6B 24# 6 s BIOS EA00 4/ 8 14/24 BIOSTK EFC1 8/55 24#25 n BKPA EFEC 25#17 n BKPC EFEE 25#18 n BSAVE EFE3 25# 4 CAUTO EBDB 14/30 15#10 15/13 CAUTOL 0007 15/10 15#13 CBOOT EB62 4/10 13#29 Last valid keystroke EF5F = 0001 CKEY DS 1 ;Last control key EF60 = 0001 ESCH DS 1 ;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 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 24 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM  ; 8080 Register Save Area. EFDE ALIGN 10h EFDE += 0002 DS (*+(10H)-1)/(10H)*(10H)-* EFE0 REGS: SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 25 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM 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  s CCP D400 13/41 13/54 13/58 14/49 14/51 14/56 s CDISK 0004 10/49 10/52 13/40 14/37 n CKEY EF5F 23#39 n CONIN EA09 4#13 CONOUT EA0C 4#14 21/29 CONST EA9B 4/12 7#12 n CSAVE EFE2 25# 3 CSV EF30 5/35 5/48 23#20 s CSVS 0020 23/20 CSVSZ 0020 3#13 5/35 5/38 5#38 5/48 5/51 5#51 CUNACT EB41 11#25 12/12 n CURS EF5A 23#33 n DACTVE EF6A 24# 4 s DBUF 0080 14/11 n DESAX EFD0 24#44 sD DI mac 8/ 6 8/52 9/ 2 9/11 9/15 13/33 DIRBUF EE80 5/33 5/46 22#32 n DIROM 0001 2#32 s DISROM mac 9/14 13/32 s DMA 0080 DMAADR EF11 11/53 18/23 22#49 DMADR EF0F 14/14 22#48 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 27 Osborne CP/M 2.2 CBIOS.  n ISTK EF99 24#21 n IVSAX EFDC 24#51 n IXSAX EFD8 24#49 n IYR EF65 23#50 n IYSAX EFDA 24#50 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 28 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM s K 0400 n KBDLY EFC6 24#31 n KEYLCK EF59 23#32 n LDADR EF57 23#31 LDSEL EF6D 24#13 24/14 n LDTRK EF6E 24#14 n LIST EA0F 4#15 LKEY EF5E 7/12 23#38 n LLIMIT EF6C 24# 9 LOGSEC EF56 12/14 16/48 23#28 n LSAVE EFE6 25# 7 s LVMEM 1000 s LWAMEM FFFF 2/ 5 25/20 n MINS EF67 23#55 n MPCHR EF06 22#39 s MRAM ED80 21/35 22/ 4 MRTRY 0005 1#38 19/42 s MSEC 000A 5/18 6/ 7 n MSECB EF09 22#43 s MSIZE 003C MVINFO ED04 16/ 8 16/39 21# 3 NDSK 0002 DMA EB4B 4/22 11#52 14/12 n SETRRM EAA4 7#31 SETSEC EB46 4/21 11#37 SETTRK EB33 4/20 11# 8 s SI.S16 0055 s SI.S64 0056 n SSAVE EFEA 25#10 s SVER 0001 s SYS 0005 s SYSDAT 0010 s SYSL 0006 TEM EF00 22#34 22/35 TEMSEC EF20 11/38 21/ 6 23#14 s TIMPTR 0040 14/29 n TKEY EF5C 23#36 s TRUE FFFF 1/22 UNACNT EF52 10/11 11/26 16/10 16/45 16/52 23#25 UNASEC EF55 12/10 16/57 17/ 9 23#27 UNATRK EF53 11/10 16/47 17/ 4 17/ 6 23#26 n VERS 0016 1#23 s VLDL 0034 WAUTO EBE3 14/45 15#15 15/17 WAUTOL 0000 15/15 15#17 WBOOT EB7B 4/11 13#53 n WRALL 0000 2#22 WRDIR 0001 2#23 17/24 WRIT2 EC1E 16/43 16#52 WRIT3 EC37 16/50 17/ 3 17# 9 WRIT4 EC3C 16/55 17# D:BMRAM .ASM DPBASE EA6B 5#27 10/38 DPBGEN mac 3#50 6/ 6 DPBS1 EA8B 5/34 5/47 6# 3 DPHGEN mac 3#16 5/29 5/42 n DSAVE EFE1 25# 2 DSKS1 0000 2#16 6/ 6 n DSKSWP EFC7 24#37 n DSTSB EF09 22#45 n ECHOP EF07 22#40 sD EI mac 8/13 8/31 9/ 7 9/20 9/25 9/29 13/38 s ENAROM mac 8/58 n ENROM 0000 2#31 ERCNT EF02 22#36 22/37 ERFLAG EF22 16/16 17/19 17/26 19/48 19/55 21/ 5 23#16 n ESAVE EFE0 24#58 ESCH EF60 14/18 23#40 s FALSE 0000 s FCB 005C FILL EC5D 16/11 17/12 18#11 FILL3 EC6E 18/17 18#19 FILL4 EC8C 18#36 18/41 FILL5 EC95 18/38 18#44 FILL6 EC98 18/32 18#46 FINAL ECD8 19/ 3 19#28 FLUSH ECBC 10/ 8 17/25 18/44 19#10 U FMT 3#10 5/29 5#29 5/42 5#42 10/28 NOFDD 0002 3#11 5/37 5#37 5/50 5#50 s NVDL 0018 n PIAAD EF61 23#44 n PIABD EF62 23#45 PRINT ED0F 21#23 21/31 n PSAVE EFE8 25# 9 n PUNCH EA12 4#16 n R179X EFC2 24#30 n RAGS EFD0 24#43 RDFLAG EF21 18/11 18/55 23#15 READ EBE5 4/23 15#21 n READER EA15 4#17 n REGS EFE0 24#57 RNDV EF01 22#35 22/36 ROMCDE EAC3 4/13 4/14 4/15 4/16 4/17 4/25 4/31 4/32 4/35 4/36 4/37 4/38 4/39 4/40 4/41 4/42 8#37 ROMJMP EACD 4/30 8#48 10/44 14/ 2 19/47 ROMRAM EF08 8/10 8/20 9/ 5 9/18 13/36 22#41 ROMRI EAAF 4/29 8#19 ROMSTK EFC1 24#26 25/12 s ROMVEC 0100 8/45 13/57 19/37 n RRDK EA27 4#23 n12 WRITE EC02 4/24 16#27 WRTYPE EF23 16/41 17/23 23#17 WRUAL 0002 2#24 16/42 XLTS EA57 5# 4 5/18 5/30 5/43  EF23 16/41 17/23 23#17 WRUAL 0002 2#24 16/42 s SYSDAT 0010 s SYSL 0006 TEM EF00 22#34 22/35 TEMSEC EF20 11/38 21/ 6 23#14 s TIMPTR 0040 14/29 n TKEY EF5C 23#36 s TRUE FFFF 1/22 UNACNT EF52 10/11 11/26 16/10 16/45 16/52 23#25 UNASEC EF55 12/10 16/57 17/ 9 23#27 UNATRK EF53 11/10 16/47 17/ 4 17/ 6 23#26 n VERS 0016 1#23 s VLDL 0034 WAUTO EBE3 14/45 15#15 15/17 WAUTOL 0000 15/15 15#17 WBOOT EB7B 4/11 13#53 n WRALL 0000 2#22 WRDIR 0001 2#23 17/24 WRIT2 EC1E 16/43 16#52 WRIT3 EC37 16/50 17/ 3 17# 9 WRIT4 EC3C 16/55 17#DAT ED80 22/13 n FMTJ EA39 4#31 FNL1 ECE8 19#43 19/53 FPYSIB 0010 2#10 2/18 n FSAVE EFE4 25# 5 s FWAVM F000 GCOLD EBC9 14/44 14#47 GOROM EAF3 9/ 9 9#28 s H.IEEE 2900 s H.SIO 2A00 n HKCNT EF5D 23#37 n HLSAX EFD6 24#47 HOME EAF5 4/18 10# 7 13/55 HOURS EF66 23#54 23/55 23/56 23/57 24/ 4 24/ 6 n HSAVE EFE7 25# 8 HSTACT EF50 10/10 16/20 18/28 23#23 HSTBUF ED80 14/13 18/12 22#12 22/32 HSTDSK EF1F 18/47 19/16 23#12 HSTSEC EF1C 18/33 18/53 19/20 23#10 n HSTSIZ 0100 2# 9 HSTTRK EF1D 18/50 19/18 23#11 HSTWRT EF51 17/18 19/11 23#24 IDAY EF63 14/28 23#48 23/49 23/50 IESTK EF6F 8/29 24#16 n IMONTH EF64 23#49 s INTBL EFF0 25/25 s IOBYTE 0003 8/46 13/47  RRI EA33 4#29 RSELDK EA1B 4#19 10/41 s RSIZE 0040 RTRC EF04 22#37 22/38 RTRY EF05 19/43 19/51 22#38 n RWDK EA2A 4#24 S1DSM 002E 2#18 5/39 5/52 6/ 9 SAVADR ED1B 19/39 19/44 21#33 SAVSEC EF14 22#55 23/ 2 SAVTRK EF15 22#56 23/ 3 n SBAUD EA3C 4#32 SDISK EF17 22#57 23/ 4 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 29 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM n SEC6 EF69 23#57 n SECS EF68 23#56 SECTRN EB50 4/26 12# 9 n SEKDEL EF13 22#53 SEKDSK EF1B 10/30 18/35 18/46 23# 8 SEKSEC EF18 18/14 18/22 18/34 18/35 18/52 21/ 7 23# 6 SEKTRK EF19 10/12 10/13 11/ 9 16/46 18/49 23# 7 SELD1 EB27 10/29 10#48 SELDSK EB06 4/19 10#19 SET page ; Sector Translation Tables. XLTS: ;Translation table 2 to 1 DB 0, 1, 4, 5, 8, 9, 12,13, 16,17 DB 2, 3, 6, 7, 10,11, 14,15, 18,19 ; Translation 3 to 1 ; DB 0, 1, 6, 7, 12,13, 18,19 ; DB 2, 3, 8, 9, 14,15 ; DB 4, 5, 10,11, 16,17 ; Translation 4 to 1 ; DB 0, 1, 8, 9, 16,17 ; DB 2, 3, 10, 11, 18,19 ; DB 4, 5, 12, 13 ; DB 6, 7, 14, 15 IF (*-XLTS) <> (MSEC*2) MSG 'Translation table error',ERROR ENDIF space 4,10 ; Control Blocks for disk drives DPBASE: DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive A: DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive B: space 4,10 ; Disk type definition blocks for each particular mode. DPBS1: ;Single density, single sided. DPBGEN DSKS1,2*MSEC,4,15,1,S1DSM,64,1000000000000000b,3 .AL IF ALVSZ <> ALVS MSG 'Allocation problems ALVS<> ALVSZ, ALVSZ= ',ALVSZ .9 ERROR .AL ENDIF ; endx OSBBIOS2  16 bits = -> check vector. ; 16 bits = -> allocation vector. NDSK: SET 0 ;Number of disk drives NOFDD: SET 0 ;Number of floppy disk drives ALVSZ: SET 0 ;Allocation vector size CSVSZ: SET 0 ;Check vector size LIST D,G,M DPHGEN MACRO TYPE,XLATE,DIRBUF,DPBADR NDSK: SET NDSK+1 DW %2 DW 0,0,0 DW %3 DW %4 DW CSV+CSVSZ DW ALV+ALVSZ NOFDD: SET NOFDD+1 CSVSZ: SET CSVSZ+(64/4) ALVSZ: SET ALVSZ+((S1DSM+7)/8) ENDM ; Make sure Systext agrees with assembled size space 4,10 ; Macro for generating the Disk Parameter Blocks. ; ; Disk type definition blocks for each particular mode. ; The format of these areas are as follow: ; 8 bit = disk type code ; 16 bit = Sectors per track ; 8 bit = Block shift ; 8 bit = BS mask ; 8 bit = Extent mask ; 16 bit = Disk size/1024 - 1. ; 16 bit = Directory size. ; 16 bit = Allocation for directory. ; 16 bit = check area size. ; 16 bit = offset to first track. DPBGEN MACRO TYPE,SPT,BSH,BSM,EXM,DSM,DIRSIZ,ALVMSK,OFFSET DB %1 DW %2 page ;***** ; Revisions: ; YNS 20AUG81 change iobyte defaults ; ;***** ; 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. ; 40-41: Points to where Date and Time are kept ; ; Register C must contain the selected drive, which is ; zero to select the A drive. 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  DB %3,%4,%5 DW %6-1,%7-1,REV (%8) DW (%7+3)/4 DW %9 ENDM page ; The following jump table defines the entry points ; into the CBIOS for use by CP/M and other external ; routines; therfore the order of these jump cannot ; be modified. The location of these jumps can only ; be modified by 400h locations, which is a restriction ; of MOVCPM. ORG BIOS CALL CBOOT ;Cold boot CALL WBOOT ;Warm boot jmp cnsta ;Console status (input) CONIN: jmp cnin ;Console input CONOUT: jmp cnout ;Console output LIST: jmp lst ;List output PUNCH: jmp pnch ;Punch output READER: jmp rdr ;Reader input JMP HOME ;Set track to zero RSELDK: JMP SELDSK ;Select disk unit JMP SETTRK ;Set track JMP SETSEC ;Set sector JMP SETDMA ;Set Disk Memory Address RRDK: JMP READ ;Read from disk RWDK: JMP WRITE ;Write onto disk LISTST: jmp lstst ;Return LST: device status JMP SECTRN ;Sector translation routine ; Extensions RRI: JMP ROMRI JMP ROMJMP FMTJ: CALL ROMCDE ;Rom resident callroutines exits with the C register set to the ; appropriate drive selection value. The exit address ; is to the CCP routine. ; CBOOT: ;Entry A= drive to boot off of. MOV B,A ;save requested drive DISROM MOV A,B ;restore requested drive STO A,CDISK ;force requested drive LDK SP,CCP .autos IF ~ AUTOST LDK HL,SIGNON CALL PRINT ;Output Banner .autos ENDIF ldk a,iob_default STO A,IOBYTE ;Clear I/O byte .autos IF AUTOST ORI 1 ;indicate cold boot .autos ENDIF JR BCCP ;Do CP/M WBOOT: ;Warm boot LDK SP,CCP CALL HOME ;flush any buffer BCPM: LDK DE,ROMVEC+3*1 ;Set ROM vector address LDK BC,CCP CALL ROMJMP ORA A JRNZ BCPM ;If error in read ORI 0FFh BCCP: ;Entry A = 01, if cold boot ; A = ff, if warm boot PUSH AF ;Save flags LDK BC,DBUF ;Set default data transfer address CALL SETDMA LDK HL,HSTBUF STO HL,DMADR ;set ROM DMA address ; Clear console control ESC cell XRA A STO A,ESCH ;clear ESC ; Set-up low core pointer cells LDK A, page ;***** ; Revisions: ; YNS 18AUG81 change bios jump vector to call new routines ; ; ;***** MRTRY: = 5 ;Maximum number of retries. MSG 'Assemblying BIOS for LWA of ', LWAMEM,'h.' ; CP/M to host disk constants HSTSIZ: = 256 ;Blocking/Deblocking buffer size FPYSIB: = 2048/128 ;Sectors in floppy disk block ; CP/M disk control block equates which define the ; disk types and maximum storage capability of each ; disk type. DSKS1: = 0 ;Single density, single sided. S1DSM: = ((40-3)*2*10)/FPYSIB ; BDOS constants on entry to write WRALL: = 0 ;write to allocated WRDIR: = 1 ;write to directory WRUAL: = 2 ;write to unallocated space 4,10 ; ROM equates. ENROM: = 0 ;Port to enable ROM DIROM: = 1 ;Port to disable ROM page ; Macro for generating Control Blocks for disk drives ; The format of these disk control blocks are as follows: ; 16 bits = -> translation table. ; 48 bits = Work area for CP/M. ; 16 bits = -> DIRBUF. ; 16 bits = -> Parameter block. ; SBAUD: CALL ROMCDE ; IEEE-488 vectors ieb1c: CALL ROMCDE ;Control Out ieb2c: CALL ROMCDE ;Status In ieb3c: CALL ROMCDE ;Go To Standby ieb4c: CALL ROMCDE ;Take Control ieb5c: CALL ROMCDE ;Output Interface Message ieb6c: CALL ROMCDE ;Output Device Message ieb7c: CALL ROMCDE ;Input Device Message ieb8c: CALL ROMCDE ;Parallel Poll OT ;Cold boot CALL WBOOT ;Warm boot jmp cnsta ;Console status (input) CONIN: jmp cnin ;Console input CONOUT: jmp cnout ;Console output LIST: jmp lst ;List output PUNCH: jmp pnch ;Punch output READER: jmp rdr ;Reader input JMP HOME ;Set track to zero RSELDK: JMP SELDSK ;Select disk unit JMP SETTRK ;Set track JMP SETSEC ;Set sector JMP SETDMA ;Set Disk Memory Address RRDK: JMP READ ;Read from disk RWDK: JMP WRITE ;Write onto disk LISTST: jmp lstst ;Return LST: device status JMP SECTRN ;Sector translation routine ; Extensions RRI: JMP ROMRI JMP ROMJMP FMTJ: CALL ROMCDE ;Rom resident call0C3h ;Store jumps in low memory STO A,0 STO A,5 LDK HL,BIOS+3 STO HL,1 LDK HL,BDOS STO HL,6 LDK HL,IDAY STO HL,TIMPTR ;set date-time pointer LDK HL,CAUTO ;Digital Research has informed SORCIM that CP/M 2.2 ;CANNOT be booted off B:. ;Manipulation of CDISK is kept here to avoid the bugs ;which would appear with its disappearance. ;Booting off B: is accomplished with the RAM cell DSKSWP. LD A,CDISK ;use requested drive ; AND 0Fh ;force user #0 ; STO A,BDOS+0336h ;set CP/M internal ; ;'CURDSK' static variable MOV C,A POP AF CMP 1 JRZ GCOLD ;If cold boot LDK HL,WAUTO GCOLD: LD A,[hl] ORA A JZ CCP+3 ;If no auto start line PUSH BC ;Save current drive LDK DE,CCP+7 LDK B,0 MOV C,A LDIR ;Move command line to buffer POP BC JMP CCP ;Go to CPM .autos IF ~ AUTOST SIGNON: DB 'Z'-40h DB 'Osborne Computer System' DB CR,LF,MSIZE/10+'0',MSIZE mod 10 + '0' DB 'K CP/M ',VERS/10+'0','.',VERS mod 10 + '0' DB CBIOSV+'@',CR,LF,0 .autos ENDIF CAddress. ; BC = sector number to translate. ; ; EXIT HL = translated sector. SECTRN: LDA UNASEC CMP C CNZ CUNACT ;If sectors do not match MOV A,C STO A,LOGSEC MOV L,C MOV H,B ADD HL,DE MOV L,M MVI H,0 RET  ;If same track ; JMP CUNACT space 4,10 ; Clear Unallocated block count (force pre-reads). CUNACT: XRA A ;A = 0 STO A,UNACNT ;Clear unallocated block count RET space 4,10 ; Set the sector for later use in the disk transfer. No ; actual disk operations are perfomed. ; ; Entry BC = sector number. SETSEC: MOV A,C STO A,TEMSEC ;sector to seek RET space 4,10 ; Set Disk memory address for subsequent disk read or ; write routines. This address is saved in DMAADR until ; the disk transfer is performed. ; ; ENTRY BC = Disk memory address. ; ; EXIT DMAADR = BC. SETDMA: STO BC,DMAADR RET space 4,15 ; Translate sector number from logical to physical. ; ; ENTRY DE = 0, no translation required. ; DE = translation table aUTO: DB CAUTOL DB 'AUTOST ' CAUTOL = *-CAUTO-1 WAUTO: DB WAUTOL DB ' ' WAUTOL = *-WAUTO-2 ; Endx OSBBIOS5.asm TIMPTR ;set date-time pointer LDK HL,CAUTO ;Digital Research has informed SORCIM that CP/M 2.2 ;CANNOT be booted off B:. ;Manipulation of CDISK is kept here to avoid the bugs ;which would appear with its disappearance. ;Booting off B: is accomplished with the RAM cell DSKSWP. LD A,CDISK ;use requested drive ; AND 0Fh ;force user #0 ; STO A,BDOS+0336h ;set CP/M internal ; ;'CURDSK' static variable MOV C,A POP AF CMP 1 JRZ GCOLD ;If cold boot LDK HL,WAUTO GCOLD: LD A,[hl] ORA A JZ CCP+3 ;If no auto start line PUSH BC ;Save current drive LDK DE,CCP+7 LDK B,0 MOV C,A LDIR ;Move command line to buffer POP BC JMP CCP ;Go to CPM .autos IF ~ AUTOST SIGNON: DB 'Z'-40h DB 'Osborne Computer System' DB CR,LF,MSIZE/10+'0',MSIZE mod 10 + '0' DB 'K CP/M ',VERS/10+'0','.',VERS mod 10 + '0' DB CBIOSV+'@',CR,LF,0 .autos ENDIF CA page ; H O M E ; ; Return disk to home. This routine sets the track number ; to zero. The current host disk buffer is flushed to the ; disk. HOME: CALL FLUSH ;Flush host buffer XRA A STO A,HSTACT ;Clear host active flag STO A,UNACNT ;Clear sector count STO A,SEKTRK STO A,SEKTRK+1 RET space 4,10 SELDSK: ;Select disk drive for next transfer. ; ; ENTRY C = disk selection value (0..15). ; DE and 1 = 0, first call for this disk. ; ; EXIT HL = 0, if drive not selectable. ; HL = DPH address if drive is selected. MOV A,C CPI NDSK JNC SELD1 ;If invalid drive number STO A,SEKDSK MOV L,C MVI H,0 ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 MOV B,E ;save initial bit LDK DE,DPBASE ADD HL,DE ;HL = DPH address PUSH HL LDK DE,100h + (low RSELDK) MOV A,B AND 1 CZ ROMJMP ;Select the disk in reg C POP HL RET SELD1: LDK HL,0 LDA CDISK SUB C RNZ ;If default drive not in error STO A,CDISK RET space 4,10 ; S E T ;OCCBIO01.ASM TITLE 'Osborne CP/M 2.2 CBIOS.' ;CBIOS - Osborne CP/M 2.2 CBIOS. * 4D2007-00 MASTER .ASM * 2D2007-00 ASSY .ASM * 1D2007-00 LISTING .PRN * 4D1007-00 MASTER .COM * 2D1007-00 ASSY .C0M ; +-----------------------+ ; | | ; | C B I O S | ; | | ; +-----------------------+ ; Copyright 1981, Osborne. ; This product is a copyright program product of ; Osborne and is supplied for use with the Osborne. ;REV = A1 ;DATE = 247 AUTOST = TRUE ;If autostart program VERS: EQU 22 space 4,10 ; Link files. link OCCbio11 ;Jump Table link OCCbio21 ;CP/M disk definitions link OCCbio31 ;Unit record I/O link OCCbio41 ;Non data transfer disk link OCCbio51 ;Cold and Warm boot link OCCbio61 ;Disk data transfer I/O link OCCbio71 ;Utility routines link OCCbio81 ;Utility routines link bmram.asm ;Commom ram definitions  T R A C K. ; ; Set track number. The track number is saved for later ; use during a disk transfer operation. ; ; ENTRY BC = track number. SETTRK: STO BC,SEKTRK ;Set track LHLD UNATRK MOV A,L XRA C MOV C,A MOV A,H XRA B ORA C RZ ;If same track ; JMP CUNACT space 4,10 ; Clear Unallocated block count (force pre-reads). CUNACT: XRA A ;A = 0 STO A,UNACNT ;Clear unallocated block count RET space 4,10 ; Set the sector for later use in the disk transfer. No ; actual disk operations are perfomed. ; ; Entry BC = sector number. SETSEC: MOV A,C STO A,TEMSEC ;sector to seek RET space 4,10 ; Set Disk memory address for subsequent disk read or ; write routines. This address is saved in DMAADR until ; the disk transfer is performed. ; ; ENTRY BC = Disk memory address. ; ; EXIT DMAADR = BC. SETDMA: STO BC,DMAADR RET space 4,15 ; Translate sector number from logical to physical. ; ; ENTRY DE = 0, no translation required. ; DE = translation table a page READ: ;a CP/M 128 byte sector. ; ; EXIT A = 0, successful read operation. ; A = 1, unsucessful read operation. ; Z bit = 1, successful read operation. ; Z bit = 0, unsuccessful read operation. CALL MVINFO ;Move information for transfer XRA A ;Set flag to force a read STO A,UNACNT ;Clear sector counter CALL FILL ;Fill buffer with data POP HL POP DE LDK BC,128 ;Move 128 bytes LDIR LD A,ERFLAG ORA A RZ ;If no error XRA A STO A,HSTACT ;Clear host active ORI 001h ;Set error flag RET space 4,20 WRITE: ;the selected 128 byte CP/M sector. ; ; ENTRY C = 0, write to a previously allocated block. ; C = 1, write to the directory. ; C = 2, write to the first sector of unallocated ; data block. ; ; EXIT A = 0, write was successful. ; A = 1, write was unsucessful. ; Z bit = 1, write was successful. ; Z bit = 0, write was unsucessful. CALL MVINFO ;Move information for transfer MOV A,C ;Write type in c STO A,WRTYPE CPI WRUAL JRNZ WRIT2 ;Ik. FLUSH: LDK HL,HSTWRT LD A,[hl] ORA A RZ ;If host buffer already on disk STO 0,[hl] LD A,HSTDSK ;Move disk and type STO A,ACTDSK LD HL,HSTTRK STO HL,ACTTRK LD A,HSTSEC STO A,ACTSEC LDK A,3 ;Write flag ; JMP FINAL space 4,10 FINAL: ;Preform final transfer processing. ; ; ENTRY A = 0 .. read disk. ; = 3 .. write disk. ; Calls: Rom resident routine to read/write ONE ; sector only. MOV E,A LDK D,0 LDK HL,ROMVEC+3*13 ADD HL,DE STO HL,SAVADR LDK HL,ACTSEC INC [hl] ;update sector+1 LDK A,MRTRY ;Set retry count FNL1: STO A,RTRY ;Clear retry count LD HL,SAVADR EX DE,HL LDK B,1 ;indicate one sector xfer CALL ROMJMP ;process read or write STO A,ERFLAG ;set possible error flag RZ ;If no errors LD A,RTRY ;Get retry counter DEC A JRNZ FNL1 ;If not permanent error ORI 01h STO A,ERFLAG ;Set error flag RET ; endx OSBBIOS6.asm  page ;***** ; file: OSBbios9.asm ; This file contains CP/M extensions to the OSBORNE CBIOS ; added by MICOROCDE CORPORATION. ; ; Revisions: ; YNS 20AUG81 Initial release ; YNS 29AUG81 Expanded trans. table to include ctl/numerics ; Translate keys to 1/2 or three char seq. ; Iobyte assignements redone. ; YNS 01SEP81 Added parallel port support ; ;***** ; ; the following routines will use the IOBYTE to transfer ; control to the appropriate device driver ; ;-------------- ; return console status ; CNSTA: ldk hl,ptr_cstat ; status table jr godispch ; call appropriate rtn ;------------ ; read input character from device ; CNIN: ldk hl,ptr_cinp ; table of input rtns jr godispch ;------------- ; put output character to device ; c contains output character ; CNOUT: ldk hl,ptr_cout ; table of output rtns godispch: mvi b,1 ;number of shifts required to align ;CONSOLE field jmp dispch ;--------------- ; list device character output ; LST: mvif write to allocated LDK A,2048/128 STO A,UNACNT LD HL,SEKTRK STO HL,UNATRK ;UNATRK = SEKTRK LD A,LOGSEC INC A JR WRIT3 WRIT2: LDK HL,UNACNT LD A,[hl] ORA A JZ WRIT4 ;If no unallocated records DEC [hl] ;dec unalloc record count LD A,UNASEC ;Increment logical sector INC A CPI 2*10 JRNZ WRIT3 ;If not end of track LD HL,UNATRK INC HL STO HL,UNATRK XRA A WRIT3: STO A,UNASEC LDK A,0FFh WRIT4: CALL FILL POP DE POP HL LDK BC,128 LDIR LDK A,1 STO A,HSTWRT ;HSTWRT = 1 LD A,ERFLAG ORA A RNZ ;If any errors occurred LD A,WRTYPE ;write type CPI WRDIR ;to directory? CZ FLUSH ;Force write of directory LD A,ERFLAG ORA A RET page ; FILL - fill host buffer with approprite host sector. ; ; ENTRY A = 0, Read required if not in buffer. ; 0therwise read not required. ; ; EXIT On exit the stack will contain the following ; values: ; POP x ;x = host record address. ; POP y ;y = caller's buffer address.  page ; MVINFO Move information necessary for transfer. MVINFO: XRA A STO A,ERFLAG ;Clear error flag LD A,TEMSEC STO A,SEKSEC RET space 4,10 ; Print message terminated by zero byte. ; ; ENTRY HL -> message buffer, terminated by zero. ; ; EXIT HL -> zero byte + 1. ; A = 0. ; Z bit set. ; ; Destroys only HL, Flags, and A registers. PRINT: LD A,[hl] ;Get a character ORA A INC HL RZ ;If zero the terminate PUSH HL MOV C,A CALL CONOUT ;Output to the console POP HL JR PRINT SAVADR: DS 2 ;Disk transfer routine vector IF * > (MRAM-1) MSG 'CBIOS is too long, lwa= ',* .9 ERROR ENDIF ; Endx OSBBIOS8.asm  b,4 ldk hl,ptr_list ;table of list routines jmp dispch ;--------------- ; output to punch ; PNCH: mvi b,6 ldk hl,ptr_pnch ; punch routines jmp dispch ;---------------- ; reader input ; RDR: mvi b,8 ldk hl,ptr_rdr ; reader routines jmp dispch space 4,10 ; L i s t S t a t u s. ; ; Return the ready status for the list device. ; ; EXIT A = 0 (zero), list device is not ready to ; accept another character. ; A = FFh (255), list device is ready to accept ; a character. ; The list status is returned depending upon the iobyte fields ; LIST field (bits 6,7) ; =0: status of crt. (always ready) ; =1: status of parallel port printer ; =2: status of serial printer ; =3: complete status of serial port ; LSTST: mvi b,4 ;number of left shifts thru carry ;to align LIST field of IOBYTE ldk hl,ptr_lst ;list status routines jmp dispch page dispch: ; on entry here reg B contains the left shift count ; required to align the iobyte field to bit 1 positio FILL: STO A,RDFLAG ;Save read flag LDK DE,HSTBUF ;initial offset LDK HL,128 ;128 byte records LD A,SEKSEC ;Get logical sector EX DE,HL RRC JRNC FILL3 ;If low bit not set ADD HL,DE ;Add bias to offset FILL3: EX DE,HL ADD HL,HL ANI 07Fh ;Mask sector STO A,SEKSEC LD HL,DMAADR XTHL ;Set return parameters PUSH DE PUSH HL ;Set return address LDK HL,HSTACT ;host active flag LD A,[hl] STO 1,[hl] ;always becomes 1 ORA A JRZ FILL6 ;If host buffer inactive LDK HL,HSTSEC LDK DE,SEKSEC LDK B,SEKDSK-SEKSEC+1 FILL4: LD A,[de] CMP [hl] JRNZ FILL5 ;If mis-match INC HL INC DE DJNZ FILL4 ;If all bytes not checked RET FILL5: CALL FLUSH ;Flush host buffer FILL6: LD A,SEKDSK ;Move disk and type STO A,HSTDSK STO A,ACTDSK LD HL,SEKTRK STO HL,HSTTRK STO HL,ACTTRK LD A,SEKSEC STO A,HSTSEC STO A,ACTSEC LD A,RDFLAG ORA A RNZ ;If no read required LDK A,0 ;Read JR FINAL space 4,10 ; FLUSH - Write out active host buffer onto disn. ; and reg HL contains address of select table lda iobyte dspch1: ral djnz dspch1 ani 6 ;get select field*2 mov e,a ldk d,0 ; de = iobyte field * 2 dad de mov e,m inx hl mov h,m ; get the routine address mov l,e ; into hl and xchange with pc pchl ; ; addresses of routines ; ptr_cstat: dw const ; keyboard status dw pistat ; parallel input stat dw sistat ; serial port input status dw ieinstat ; status of input device on IEEE port ptr_cinp: dw keyinp ; get input from keyboard dw parinp ; parallel input dw spinp ; serial port input dw ieinp ; ieee port input ptr_cout: dw crtout ; output character to crt dw parout ; parallel output dw spout ; serial port output dw ieout ; ieee port output ptr_list: dw crtout ; list assigned to crt dw parout ; parallel port output dw spout ; serial port dw ACICTL ; serial port usart ctl ptr_pnch: dw crtout ; punch assigned to crt dw ieout ; ieee port dw spout ; serial port dw part ;return ;endif kin30: ;else ; get next key from keyboard driver and translate if reqd. ldk e,low(conin) call romcd1 ; ; when control is returned here, A has the input code for ; console character. If code is between 80h and 8fh, it is ; translated. ; cpi basvl0 rc ;return when code is not tobe xlated cpi basvl0+tbllen rnc sui basvl0 ;subtract base val ral ;mult remainder by 2 mov e,a ;build ptr to table entry mvi d,0 ldk hl,xltbl dad de ld a,[hl] ;get byte 0 inx hl ;point to byte 1 ora a jrnz kin40 ;if first byte is 0 then ld a,[hl] ret ;return with byte1 as xlated val. kin40: ; if msb of byte 0 is 0 then the xlated val is byte0 and byte 1 bit 7,a jrnz kin50 ;elseif bit7 is 0 then push af ;save byte 0 ld a,[hl] ;get byte1 from table sto a,xltvl1 ;save translated value lk a,1 sto a,xltkey ;set xlated keys to 1 pop af ret ;return with the first char of t after dc4 mov a,c sui '0' ; do a range check on code jc crt40 ;exit when char .lt. '0' cpi tbllen jnc crt40 ;or .gt. entries in table rlc ; multiply index by 2 mov c,a ldk b,0 ; set up bc for a dbl add ldk hl,xltbl dad bc ; add bc to hl shld tblptr ; save the ptr ldk a,2 ; set dc4 flg to indicate crt25: sto a,dc4flg ;next state ret ; ; store input character in xlate table crt30: lhld tblptr mov m,c sui 3 jrz crt25 ;clear dc4 flag and return when last ;char of dc4 seq received. inc hl ;increment table ptr for next byte shld tblptr ldk a,3 jr crt25 ; ; Illegal sequence. Char following dc4 is not valid. This ; outputs a dc4 and the invalid char to the crt. crt40: push bc ;save current char ldk c,dc4cod call crt10 ;***note*** pop bc jr crt10 ; dc4flg db 0 tblptr dw 0 dc4cod equ 14h page ;** ; routine: SOSTAT ; gets status of output device attached to serial port out ; parallel port out ptr_rdr: dw keyinp ; reader assigned to keyboard dw ieinp ; ieee port dw spinp ; serial port dw parinp ; parallel port input ptr_lst: dw crstat dw postat ;parallel port output stat dw sostat ;serial port output stat dw acistat ;serial port usart status page ; C O N S O L S T A T U S ; ; This routine samples the Console status and returns the ; following values in the A register. ; ; EXIT A = 0 (zero), means no character ; currently ready to read. ; ; A = FFh (255), means character ; currently ready to read. nokey equ 00h ;indicates key not present CONST: ; check if any translated keys are pending ld a,xltkey ora a jrnz const5 ; if no xlated keys pending, check keyhit flag LD A,LKEY ;Get Key hit flag xri nokey RZ ;If data not available const5: ORI 0FFh RET page ;** ; Routine name: KEYINP - gets keystroke from rom kbd driver. Translates ; the codes 80h to 8fh as per table. ; ; Outputs: A = translhe ;sequence kin50: ;else ; the key is translated to a three char seq. esc byte0-80h byte1 ani 07fh ;get lower seven bits sto a,xltvl2 ;save byte0-80h ld a,[hl] sto a,xltvl1 ;save byte1 lk a,2 sto a,xltkey lk a,1bh ;a = esc code ret xltvl1: db 0 xltvl2: db 0 xltkey: db 0 xltbl: ;default table ; ctl numerics produce and escape seq. Esc n ; cursor keys produce ctl/l, ctl/h, ctl/k and ctl/j db 1bh,'0' db 1bh,'1' db 1bh,'2' db 1bh,'3' db 1bh,'4' db 1bh,'5' db 1bh,'6' db 1bh,'7' db 1bh,'8' db 1bh,'9' db 0,'K'-40h db 0,'L'-40h db 0,'J'-40h db 0,'H'-40h tbllen equ (*-xltbl)/2 page ;** ; routine: CRSTAT ; returns status of crt. ; crt is always ready CRSTAT: ori 0FFh ret ;** ; routine name: CRTOUT ; ; inputs: C: output character ; outputs: update translate table when the dc4 sequence found provided ; we are not in an escape seq. or in graphic mode. ; otherwise outputs the character to c SOSTAT: call acistat ;get 6850 status ani si.trdy rz ;return with not ready status ori true ret ;** ; routine: SISTAT ; gets status of input device attached to serial port SISTAT: call acistat ani si.rrdy rz ;return with not ready status ori true ret ;** ; routine: SPINP ; Inputs a character from the serial port ; Uses the reader (sp) driver in ROM ; SPINP: ldk e,low(reader) jmp romcd1 ret ;** ; routine: SPOUT ; Outputs character in reg c to the serial port (list device) ; calls the list (sp) driver in ROM ; SPOUT: ldk e,low(list) jmp romcd1 ;** ; routine: ACICTL ; outputs character in c to the ACIA CTL port. ; ACICTL: call sw2rom mov a,c sta h.sctrl jmp sw2ram ;** ; routine: acistat ; returns usart status in A acistat: call sw2rom lda h.ssts jmp sw2ram page ; ie device mod values ie_talk equ 0 ;device is a talker ie_lstn equ 1 ;device is a listener ie_ad0 db 0 ;device address ie_ad1 db 0 iated code in ASCII ; All registers are destroyed ; ; Translation scheme: ; the translation table has a two byte entry for each code between ; 80h and 8fh. The incoming keystroke from the keyboard is translated ; to one, two or three character sequence as follows: ; if byte 0 is all zeros, the translated value is byte 1. ; if byte 0 is less than 80h, the key is translated to a ; 2 byte sequence: byte0 byte1 ; if byte 0 is 80h to ffh, the key is translated to a 3 byte ; sequence: Escape byte0-80h byte1 basvl0 equ 80h ;lowest code of the codes that ;are translated. KEYINP: ; if there are no xlated keys waiting then ; call the keyboard driver in rom ldk hl,xltkey ld a,[hl] ;get number of xlated keys ora a jrz kin30 ;if keys pending then dec [hl] ;reduce pending count cpi 1 jrnz kin20 ;if only one key then ld a,xltvl1 ;get translated value ret ;return kin20: ;else if two keys are waiting then ld a,xltvl2 ;get first val reonsole ; all registers destroyed ; The dc4 sequence is as follows: ; dc4 k b0 b1 ; where: ; dc4 is the ascii device control char code 14h ; k is the table entry number + 30h. ; b0 is byte 0 of the table. ; b1 is byte 1 of the table. ; esch flag bit definitions (also check in file bmkey.asm) ef_esc: equ 8 ef_gr: equ 1 CRTOUT: lda esch and ef_esc+ef_gr jnz crt10 ;check for dc4 seq only when neither esc seq ; nor graphic lda dc4flg ; ora a ; jnz crt20 ; if not in dc4 sequence then mov a,c cpi dc4cod jnz crt10 ;if start of dc seq then ldk a,1 ;set dc4 flag sto a,dc4flg ret crt10: ;else (*this is called as a sbrt*) xra a sto a,dc4flg ;reset dc4 found flag ldk e,low(conout) ;output to crt jmp romcd1 ; ; following ensures that the character following the dc4 ; is between 30h and 30h+tbllen. In case of error the characters ; are displayed. crt20: cpi 1 jnz crt30 ;exit when it is not second charemode db 0 ;mode of IEEE device ;** ; routine: IEINSTAT ; gets status of the input device attached to ieee port ; Uses ROM resident primitives IEINSTAT: ;************* ret ;** ; routine: IEINP ; Reads a character from IEEE port ; Uses ROM resident primitives. IEINP: lda ie_mode bit ie_talk,a jrz iei20 ;if device is not a talker then ;make talker iei05: lda ie_ad0 adi 40h ;get primary address mov c,a ldk e,low(ieb5c) jmp romcd1 ;output interface message ora a jrnz iei05 ;try again if error iei10: lda ie_ad1 adi 60h mov c,a ldk e,low(ieb5c) jmp romcd1 ;output secondary address ora a jrnz iei10 lk hl,ie_mode sbit ie_talk,[hl] ;set mode to talker iei20: ; ldk e,low(ieb7c) jmp romcd1 bit 7,l jrnz iei20 ;try again if error ret ;** ; routine: IEOUT ; Outputs the character in reg C to IEEE port ; Uses ROM resident primitives. ; IEOUT: lda ie_mode bit ie_lstn,a jrz ieo20 ;if device is  rdy bit in pia ctl reg strb equ 00100000b ;strobe bit in port b ; port modes pp.undef equ 0 pp.out equ 1 pp.in equ 2 pp.mode db pp.undef ;*** ; sbrt: CV2OP. initializes the port to a parallel output ; port. cv2op: lda pp.mode cpi pp.out rz ;return when in output mode ; set port a to output on all lines lk a,pa.cdr sta pa.ctl ;select direction reg lk a,pa.dro sta pa.dir ;output constant to dir. reg to put ; a port in output mode lk a,pa.cdt sta pa.ctl ;select port a data reg. lk a,pb.cdr sta pb.ct ;selec por b direction lk a,pb.dr sta pb.dir ;all lines are output except the output ;busy signal on bit 6 lk a,pb.cdt sta pb.ctl ;select data register lk a,pb.dto sta pb.dta ;initialize port b data lk a,pp.out sta pp.mode ret ;*** ; sbrt: CV2IP. initializes the port to a parallel input ; port. cv2ip: lda pp.mode cpi pp.in rz ;return when in input mode ; set port a to input on all lines lk a,pa.cdr sta page ;***** ; Revisions: ; YNS 18AUG81 added iobyte function to listst ; modified romcde routine ; YNS 30AUG81 moved const and listst to osbbios9.asm ;***** SETRRM: ;Set ROM-RAM flag ; Entry A= port to output (setting ROM or RAM enable) ; Exit none. ; Uses A DI PUSH BC MOV C,A OT,C A STO A,ROMRAM POP BC EI ! RET space 4,10 ROMRI: ;Exit ROM resident Interrupt routine. LD A,ROMRAM MOV C,A ;port OT,C A ;set ROM or RAM enabled POP IY POP IX POP HL POP DE POP BC POP AF LD SP,IESTK ;reset to interrupt entry stk EI ! RET space 4,10 ROMCDE: ;Call ROM resident processor ; Entry DE = resident processor to call biased ; by CBIOS jump vector. ; NOTE: ROM jump vector must match CBIOS vector ; ; Entry at ROMCD1 with low digit of CBIOS vector in reg E POP DE ;Get calling address MOV A,E SUI 3 MOV E,A ROMCD1: LDK D,high (ROMVEC) LD A,IOBYTE ROMJMP: ;Entry here to jump to ROM function code directly ; Entry DE = ROM jump address ; BC = not a listener then ;make listener ieo05: lda ie_ad0 adi 20h ;get primary address mov c,a ldk e,low(ieb5c) jmp romcd1 ;output interface message ora a jrnz ieo05 ;try again if error ieo10: lda ie_ad1 adi 60h mov c,a ldk e,low(ieb5c) jmp romcd1 ;output secondary address ora a jrnz ieo10 lk hl,ie_mode sbit ie_lstn,[hl] ;set mode to listener ieo20: ; ldk e,low(ieb6c) jmp romcd1 ora a jrnz ieo20 ;try again if error ret page ;** The Parallel port is actually the IEEE port driven with the centronix ; protocol. The bit assignements of the PIA and PIB are as follows: ; PIA0-7 = data bus ; PIB0 = 0, data bus is output. 1, data bus is input ; PIB1 = set to 1. ; PIB2 = set to 0. ; PIB3 = 0 output, 1 Input ; PIB4 = not used ; PIB5 = output strobe. Active = 1. ; PIB6 = 0, printer busy. 1, printer is ready. ; PIB7 = not used. ; ; CA2 = going low indicates to device that we are busy. ; CA1 = low to high transition gates input pa.ctl ;select direction reg lk a,pa.dri sta pa.dir ;output constant to dir. reg to put ; a port in input mode lk a,pa.cdt sta pa.ctl ;select port a data reg. lk a,pb.cdr sta pb.ct ;selec por b direction lk a,pb.dr sta pb.dir ;all lines are output except the output ;busy signal on bit 6 lk a,pb.cdt sta pb.ctl ;select data register lk a,pb.dti sta pb.dta ;initialize port b data lk a,pp.in sta pp.mode ret ;** ; routine: POSTAT ; gets status of the parallel (centronix) printer ; attached to the ieee port ; POSTAT: call sw2rom call cv2op ;convert to output lda pb.dta ;get port b data ani pp.ordy jrz pos10 ori true pos10: jmp sw2ram ;** ; routine: PISTAT ; gets status of the input device attached to the ; parallel port ; piactl db 0 PISTAT: call sw2rom call cv2ip lda piactl ani pp.irdy jrnz pis20 ;if saved status indicates there is a char ;in the PIA lda pa.ctl sta piactl ;this is saved as any parameters DI LDK HL,0 ADD HL,SP ;Old stack to HL LDK SP,BIOSTK PUSH HL ;Save old stack pointer ENAROM EX DE,HL ;ROM jump address to HL CALL GOROM DI PUSH AF ;save status returned DISROM POP AF POP HL ;Restore old stack pointer MOV SP,HL EI ! RET GOROM: EI JMP [hl] ent Interrupt routine. LD A,ROMRAM MOV C,A ;port OT,C A ;set ROM or RAM enabled POP IY POP IX POP HL POP DE POP BC POP AF LD SP,IESTK ;reset to interrupt entry stk EI ! RET space 4,10 ROMCDE: ;Call ROM resident processor ; Entry DE = resident processor to call biased ; by CBIOS jump vector. ; NOTE: ROM jump vector must match CBIOS vector ; ; Entry at ROMCD1 with low digit of CBIOS vector in reg E POP DE ;Get calling address MOV A,E SUI 3 MOV E,A ROMCD1: LDK D,high (ROMVEC) LD A,IOBYTE ROMJMP: ;Entry here to jump to ROM function code directly ; Entry DE = ROM jump address ; BC =  data to port a. ; ; The port is bidirectional but only one direction ; can be active at any time. The direction of port is determined ; by which routines are called. If postat or parout are ; called, it is made an output port and an input port if ; pistat or parinp are called. ; port registers pa.dta equ h.ieee+0 pa.dir equ pa.dta pa.ctl equ h.ieee+1 pb.dta equ h.ieee+2 pb.dir equ pb.dta pb.ctl equ h.ieee+3 ; port ctl register constants. pa.cdr equ 00101010b ;to address port a direction pa.cdt equ 00101110b ;to address port a data and set ;port a in input program handshake mode. pb.cdr equ 00000000b ;to address port b direction pb.cdt equ 00000100b ;to address port b data ; direction register constants pa.dro equ 0ffh ;port a output mode pa.dri equ 00h ;port a input mode pb.dr equ 0bfh ;port b direction pb.dto equ 00000010b ;port b data for output pb.dti equ 00001011b ;port b data for input pp.ordy equ 01000000b ;output rdy bit in pib pp.irdy equ 10000000b ;inputreading the ;pia clears the status ani pp.irdy jrz pis30 pis20: ori true pis30: jmp sw2ram ;** ; routine: PARINP ; inputs a character from parallel port. PARINP: call pistat jrz parinp ;wait till char in pia call sw2rom xra a sta piactl ;clear saved status lda pa.dta jmp sw2ram ;** ; routine: PAROUT ; outputs the character in c to the IEEE port treating the ; port as a parallel port. PAROUT: call postat jrz parout call sw2rom mov a,c sta pa.dta lk a,pb.dto+strb sta pb.dta ;set strobe lk a,pb.dto sta pb.dta ;clear strobe jmp sw2ram page ;*** ; sbrt: SW2ROM ; switches to rom ; saves all registers SW2ROM: di push af enarom pop af ei ret ;*** ; sbrt: SW2RAM ; switches to ram ; preserves all registers SW2RAM: di push af disrom pop af ei ret pp.irdy jrnz pis20 ;if saved status indicates there is a char ;in the PIA lda pa.ctl sta piactl ;this is saved as  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 ; Directms 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 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  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  SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 1 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM *ABS 0000 EFEF *CODE EFEF 0000 *DATA EFEF 0000 ;OCCBIO01.ASM ;CBIOS - Osborne CP/M 2.2 CBIOS. * 4D2007-00 MASTER .ASM * 2D2007-00 ASSY .ASM * 1D2007-00 LISTING .PRN * 4D1007-00 MASTER .COM * 2D1007-00 ASSY .C0M ; +-----------------------+ ; | | ; | C B I O S | ; | | ; +-----------------------+ ; Copyright 1981, Osborne. ; This product is a copyright program product of  = 002E S1DSM: = ((40-3)*2*10)/FPYSIB ; BDOS constants on entry to write = 0000 WRALL: = 0 ;write to allocated = 0001 WRDIR: = 1 ;write to directory = 0002 WRUAL: = 2 ;write to unallocated ; ROM equates. = 0000 ENROM: = 0 ;Port to enable ROM = 0001 DIROM: = 1 ;Port to disable ROM SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 3 Osborne CP/M 2.2 CBIOS. D:OCCBIO11.ASM ; Macro for generating Control Blocks for disk drives ; The format of these disk control blocks are as follows: ; 16 bits = -> translation table. ; 48 bits = Work area for CP/M. ; 16 bits = -> DIRBUF. ; 16 bits = -> Parameter block. SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 4 Osborne CP/M 2.2 CBIOS. D:OCCBIO11.ASM ; The following jump table defines the entry points ; into the CBIOS for use by CP/M and other external ; routines; therfore the order of these jump cannot ; be modified. The location of these jumps can only ; be modified by 400h locations, which is a restriction ; of MOVCPM. 0000 = E600 ORG BIOS E600 CD59E7 CALL CBOOT ;Cold boot E603 CD73E7 CALL WBOOT ;Warm boot E606 C315E9 jmp cnsta ;Console status (input) E609 C31AE9 CONIN: jmp cnin ;Console input E60C C31FE9 CONOUT: jmp cnout ;Console output E60F C327E9 LIST: jmp lst ;List output E612 C32FE9 PUNCH: jmp pnch ;Punch output E615 C337E9 READER: jmp rdr ; ; Osborne and is supplied for use with the Osborne. ;REV = A1 ;DATE = 247 = FFFF AUTOST = TRUE ;If autostart program = 0016 VERS: EQU 22 ; Link files. link OCCbio11 ;Jump Table link OCCbio21 ;CP/M disk definitions link OCCbio31 ;Unit record I/O link OCCbio41 ;Non data transfer disk link OCCbio51 ;Cold and Warm boot link OCCbio61 ;Disk data transfer I/O link OCCbio71 ;Utility routines link OCCbio81 ;Utility routines link bmram.asm ;Commom ram definitions SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 2 Osborne CP/M 2.2 CBIOS. D:OCCBIO11.ASM  ; 16 bits = -> check vector. ; 16 bits = -> allocation vector. = 0000 NDSK: SET 0 ;Number of disk drives = 0000 NOFDD: SET 0 ;Number of floppy disk drives = 0000 ALVSZ: SET 0 ;Allocation vector size = 0000 CSVSZ: SET 0 ;Check vector size LIST D,G,M DPHGEN MACRO TYPE,XLATE,DIRBUF,DPBADR NDSK: SET NDSK+1 DW %2 DW 0,0,0 DW %3 DW %4 DW CSV+CSVSZ DW ALV+ALVSZ NOFDD: SET NOFDD+1 CSVSZ: SET CSVSZ+(64/4) ALVSZ: SET ALVSZ+((S1DSM+7)/8) ENDM ; Make sure Systext agrees with assembled size ; Macro for generatReader input E618 C3ECE6 JMP HOME ;Set track to zero E61B C3FDE6 RSELDK: JMP SELDSK ;Select disk unit E61E C32AE7 JMP SETTRK ;Set track E621 C33DE7 JMP SETSEC ;Set sector E624 C342E7 JMP SETDMA ;Set Disk Memory Address E627 C3DDE7 RRDK: JMP READ ;Read from disk E62A C3FAE7 RWDK: JMP WRITE ;Write onto disk E62D C33FE9 LISTST: jmp lstst ;Return LST: device status E630 C347E7 JMP SECTRN ;Sector translation routine ; Extensions E633 C3A6E6 RRI: JMP ROMRI E636 C3C4E6 JMP ROMJMP E639 CDBAE6 FMTJ: CALL ROMCDE ;Rom resident call E63C CDBAE6 SBAUD: CALL ROMCDE ; IEEE-488 vectors E63F CDBAE6 ieb1c: CALL ROMCDE ;Control Out E642 CDBAE6 ieb2c: CALL ROMCDE ;Status In E645 CDBAE6 ieb3c: CALL ROMCDE ;Go To Standby E648 CDBAE6 ieb4c: CALL ROMCDE ;Take Control E64B CD ;***** ; Revisions: ; YNS 18AUG81 change bios jump vector to call new routines ; ; ;***** = 0005 MRTRY: = 5 ;Maximum number of retries. MSG 'Assemblying BIOS for LWA of ', LWAMEM,'h.' 'Assemblying BIOS for LWA of FFFFh.' ; CP/M to host disk constants = 0100 HSTSIZ: = 256 ;Blocking/Deblocking buffer size = 0010 FPYSIB: = 2048/128 ;Sectors in floppy disk block ; CP/M disk control block equates which define the ; disk types and maximum storage capability of each ; disk type. = 0000 DSKS1: = 0 ;Single density, single sided. ing the Disk Parameter Blocks. ; ; Disk type definition blocks for each particular mode. ; The format of these areas are as follow: ; 8 bit = disk type code ; 16 bit = Sectors per track ; 8 bit = Block shift ; 8 bit = BS mask ; 8 bit = Extent mask ; 16 bit = Disk size/1024 - 1. ; 16 bit = Directory size. ; 16 bit = Allocation for directory. ; 16 bit = check area size. ; 16 bit = offset to first track. DPBGEN MACRO TYPE,SPT,BSH,BSM,EXM,DSM,DIRSIZ,ALVMSK,OFFSET DB %1 DW %2 DB %3,%4,%5 DW %6-1,%7-1,REV (%8) DW (%7+3)/4 DW %9 ENDM BAE6 ieb5c: CALL ROMCDE ;Output Interface Message E64E CDBAE6 ieb6c: CALL ROMCDE ;Output Device Message E651 CDBAE6 ieb7c: CALL ROMCDE ;Input Device Message E654 CDBAE6 ieb8c: CALL ROMCDE ;Parallel Poll SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 5 Osborne CP/M 2.2 CBIOS. D:OCCBIO21.ASM ; Sector Translation Tables. E657 XLTS: ;Translation table 2 to 1 E657 0001040508 DB 0, 1, 4, 5, 8, 9, 12,13, 16,17 090C0D1011 E661 020306070A DB 2, 3, 6, 7, 10,11, 14,15, 18,19 0B0E0F1213 ; Translation 3 to 1 ; DB 0, 1, 6, 7, 12,13, 18,19 ; DB 2, 3, 8, 9, 14,15 ; DB 4, 5, 10,11, 16,17 ; Translation 4 to 1 ; DB 0, 1, 8, 9, 16,17 'Allocation problems ALVS<> ALVSZ, ALVSZ= ',ALVSZ - .9 ERROR .AL ENDIF ; endx OSBBIOS2 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 7 Osborne CP/M 2.2 CBIOS. D:OCCBIO31.ASM ;***** ; Revisions: ; YNS 18AUG81 added iobyte function to listst ; modified romcde routine ; YNS 30AUG81 moved const and listst to osbbios9.asm ;***** E69B SETRRM: ;Set ROM-RAM flag ; Entry A= port to output (setting ROM or RAM enable) ; Exit none. ; Uses A E69B DI E69B +F3 DB 0F3h E69C C5 PUSH BC E69D 4F MOV C,A E69E ED79 $ OT,C A E6A0  E6D5 + EI E6D5 +FB DB 0FBh E6D6 EB EX DE,HL ;ROM jump address to HL E6D7 CDEAE6 CALL GOROM E6DA DI E6DA +F3 DB 0F3h E6DB F5 PUSH AF ;save status returned E6DC DISROM E6DC + DI E6DC +F3 DB 0F3h E6DD +D301 OUT 1 E6DF +3E01 LDK A,1 E6E1 +3208EF STO A,ROMRAM E6E4 + EI E6E4 +FB DB 0FBh E6E5 F1 POP AF E6E6 E1 POP HL ;Restore old stack pointer E6E7 F9 MOV SP,HL E6E8 EI ! RET E6E8 +FB DB 0FBh E6E9 +C9 RET E6EA GOROM: EI E6EA +FB DB 0FBh E6EB E9 JMP [hl] SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 9 Osborne CP/M 2.2 CBIOS. D:OCCBIO41.ASM ; H O M E ;  ; DB 2, 3, 10, 11, 18,19 ; DB 4, 5, 12, 13 ; DB 6, 7, 14, 15 = 0000 IF (*-XLTS) <> (MSEC*2) - MSG 'Translation table error',ERROR ENDIF ; Control Blocks for disk drives E66B DPBASE: E66B DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive A: += 0001 NDSK: SET NDSK+1 E66B +57E6 DW XLTS E66D +0000000000 DW 0,0,0 00 E673 +80EE DW DIRBUF E675 +8CE6 DW DPBS1+1 E677 +30EF DW CSV+CSVSZ E679 +24EF DW ALV+ALVSZ += 0001 NOFDD: SET NOFDD+1 += 0010 CSVSZ: SET CSVSZ+(64/4) += 0006 ALVSZ: SET ALVSZ+((S1DSM+7)/8) E67B DPHGEN DSKS1,XLTS,DIRBUF,DPBS1+1 ;Drive B: += 0002 NDSK: SET NDSK+1 E67B +57E6 DW XLTS E67D +0000000000 DW 0,0,0 00 3208EF STO A,ROMRAM E6A3 C1 POP BC E6A4 EI ! RET E6A4 +FB DB 0FBh E6A5 +C9 RET E6A6 ROMRI: ;Exit ROM resident Interrupt routine. E6A6 3A08EF LD A,ROMRAM E6A9 4F MOV C,A ;port E6AA ED79 $ OT,C A ;set ROM or RAM enabled E6AC FDE1 $ POP IY E6AE DDE1 $ POP IX E6B0 E1 POP HL E6B1 D1 POP DE E6B2 C1 POP BC E6B3 F1 POP AF E6B4 ED7B6FEF $ LD SP,IESTK ;reset to interrupt entry stk E6B8 EI ! RET E6B8 +FB DB 0FBh E6B9 +C9 RET E6BA ROMCDE: ;Call ROM resident processor ; Entry DE = resident processor to call biased ; by CBIOS jump vector. ; NOTE: ROM jump vector must match CBIOS vector ; ; Entry at ROMCD1 with low digit of CBIOS vector in reg E  ; Return disk to home. This routine sets the track number ; to zero. The current host disk buffer is flushed to the ; disk. E6EC HOME: E6EC CDB4E8 CALL FLUSH ;Flush host buffer E6EF AF XRA A E6F0 3250EF STO A,HSTACT ;Clear host active flag E6F3 3252EF STO A,UNACNT ;Clear sector count E6F6 3219EF STO A,SEKTRK E6F9 321AEF STO A,SEKTRK+1 E6FC C9 RET E6FD SELDSK: ;Select disk drive for next transfer. ; ; ENTRY C = disk selection value (0..15). ; DE and 1 = 0, first call for this disk. ; ; EXIT HL = 0, if drive not selectable. ; HL = DPH address if drive is selected. E6FD 79 MOV A,C E6FE FE02 CPI NDSK E700 D21EE7 JNC SELD1 ;IE683 +80EE DW DIRBUF E685 +8CE6 DW DPBS1+1 E687 +40EF DW CSV+CSVSZ E689 +2AEF DW ALV+ALVSZ += 0002 NOFDD: SET NOFDD+1 += 0020 CSVSZ: SET CSVSZ+(64/4) += 000C ALVSZ: SET ALVSZ+((S1DSM+7)/8) SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 6 Osborne CP/M 2.2 CBIOS. D:OCCBIO21.ASM ; Disk type definition blocks for each particular mode. E68B DPBS1: ;Single density, single sided. E68B DPBGEN DSKS1,2*MSEC,4,15,1,S1DSM,64,1000000000000000b,3 E68B +00 DB DSKS1 E68C +1400 DW 2*MSEC E68E +040F01 DB 4,15,1 E691 +2D003F0080 DW S1DSM-1,64-1,REV (1000000000000000B) 00 E697 +1000 DW (64+3)/4 E699 +0300 DW 3 = 0000 .AL IF ALVSZ <> ALVS - MSG  E6BA D1 POP DE ;Get calling address E6BB 7B MOV A,E E6BC D603 SUI 3 E6BE 5F MOV E,A E6BF ROMCD1: E6BF 1601 LDK D,high (ROMVEC) SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 8 Osborne CP/M 2.2 CBIOS. D:OCCBIO31.ASM E6C1 3A0300 LD A,IOBYTE E6C4 ROMJMP: ;Entry here to jump to ROM function code directly ; Entry DE = ROM jump address ; BC = any parameters E6C4 DI E6C4 +F3 DB 0F3h E6C5 210000 LDK HL,0 E6C8 39 ADD HL,SP ;Old stack to HL E6C9 31C1EF LDK SP,BIOSTK E6CC E5 PUSH HL ;Save old stack pointer E6CD ENAROM E6CD + DI E6CD +F3 DB 0F3h E6CE +D300 OUT 0 E6D0 +3E00 LDK A,0 E6D2 +3208EF STO A,ROMRAMf invalid drive number E703 321BEF STO A,SEKDSK E706 69 MOV L,C E707 2600 MVI H,0 E709 29 ADD HL,HL ;*2 E70A 29 ADD HL,HL ;*4 E70B 29 ADD HL,HL ;*8 E70C 29 ADD HL,HL ;*16 E70D 43 MOV B,E ;save initial bit E70E 116BE6 LDK DE,DPBASE E711 19 ADD HL,DE ;HL = DPH address E712 E5 PUSH HL E713 111B01 LDK DE,100h + (low RSELDK) E716 78 MOV A,B E717 E601 AND 1 E719 CCC4E6 CZ ROMJMP ;Select the disk in reg C E71C E1 POP HL E71D C9 RET E71E 210000 SELD1: LDK HL,0 E721 3A0400 LDA CDISK E724 91 SUB C E725 C0 RNZ ;If default drive not in error E726 320400 STO A,CDISK E729 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 10 Osborne CP/M 2.2 CBIOS. = 0, no translation required. ; DE = translation table address. ; BC = sector number to translate. ; ; EXIT HL = translated sector. E747 SECTRN: E747 3A55EF LDA UNASEC E74A B9 CMP C E74B C438E7 CNZ CUNACT ;If sectors do not match E74E 79 MOV A,C E74F 3256EF STO A,LOGSEC E752 69 MOV L,C E753 60 MOV H,B E754 19 ADD HL,DE E755 6E MOV L,M E756 2600 MVI H,0 E758 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 12 Osborne CP/M 2.2 CBIOS. D:OCCBIO51.ASM ;***** ; Revisions: ; YNS 20AUG81 change iobyte defaults ; ;***** ; B o o trequested drive E767 3100D0 LDK SP,CCP = 0000 .autos IF ~ AUTOST - LDK HL,SIGNON - CALL PRINT ;Output Banner .autos ENDIF E76A 3E80 ldk a,iob_default E76C 320300 STO A,IOBYTE ;Clear I/O byte = FFFF .autos IF AUTOST E76F F601 ORI 1 ;indicate cold boot .autos ENDIF E771 1814 ^E787$ JR BCCP ;Do CP/M SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 13 Osborne CP/M 2.2 CBIOS. D:OCCBIO51.ASM E773 WBOOT: ;Warm boot E773 3100D0 LDK SP,CCP E776 CDECE6 CALL HOME ;flush any buffer E779 110301 BCPM: LDK DE,ROMVEC+3*1 ;Set ROM vector address E77C 0100D0 LDK BC,CCP E77F CDC4E6 CALL ROMJMP E782 B7 ORA A E783 20F4 ^E779$ JRNZ BCPM ;If error in read  D:OCCBIO41.ASM ; S E T T R A C K. ; ; Set track number. The track number is saved for later ; use during a disk transfer operation. ; ; ENTRY BC = track number. E72A SETTRK: E72A ED4319EF $ STO BC,SEKTRK ;Set track E72E 2A53EF LHLD UNATRK E731 7D MOV A,L E732 A9 XRA C E733 4F MOV C,A E734 7C MOV A,H E735 A8 XRA B E736 B1 ORA C E737 C8 RZ ;If same track ; JMP CUNACT ; Clear Unallocated block count (force pre-reads). E738 AF CUNACT: XRA A ;A = 0 E739 3252EF STO A,UNACNT ;Clear unallocated block count E73C C9 RET ; Set the sector for later use in the disk transfer. No  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. ; 40-41: Points to where Date and Time are kept ; ; Register C must contain the selected drive, which is ; zero to select the A drive. The exit address is to ; the CCP routine. ; ; ; The WBOOT entry point gets contr E785 F6FF ORI 0FFh E787 BCCP: ;Entry A = 01, if cold boot ; A = ff, if warm boot E787 F5 PUSH AF ;Save flags E788 018000 LDK BC,DBUF ;Set default data transfer address E78B CD42E7 CALL SETDMA E78E 2180ED LDK HL,HSTBUF E791 220FEF STO HL,DMADR ;set ROM DMA address ; Clear console control ESC cell E794 AF XRA A E795 3260EF STO A,ESCH ;clear ESC ; Set-up low core pointer cells E798 3EC3 LDK A,0C3h ;Store jumps in low memory E79A 320000 STO A,0 E79D 320500 STO A,5 E7A0 2103E6 LDK HL,BIOS+3 E7A3 220100 STO HL,1 E7A6 2106D8 LDK HL,BDOS E7A9 220600 STO HL,6 E7AC 2163EF LDK HL,IDAY E7AF 224000 STO HL,TIMPTR ;set date-time pointer E7B2 21D3E7 LDK HL,CAUTO  ; actual disk operations are perfomed. ; ; Entry BC = sector number. E73D 79 SETSEC: MOV A,C E73E 3220EF STO A,TEMSEC ;sector to seek E741 C9 RET ; Set Disk memory address for subsequent disk read or ; write routines. This address is saved in DMAADR until ; the disk transfer is performed. ; ; ENTRY BC = Disk memory address. ; ; EXIT DMAADR = BC. E742 SETDMA: E742 ED4311EF $ STO BC,DMAADR E746 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 11 Osborne CP/M 2.2 CBIOS. D:OCCBIO41.ASM ; Translate sector number from logical to physical. ; ; ENTRY DE ol 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 ; appropriate drive selection value. The exit address ; is to the CCP routine. ; E759 CBOOT: ;Entry A= drive to boot off of. E759 47 MOV B,A ;save requested drive E75A DISROM E75A + DI E75A +F3 DB 0F3h E75B +D301 OUT 1 E75D +3E01 LDK A,1 E75F +3208EF STO A,ROMRAM E762 + EI E762 +FB DB 0FBh E763 78 MOV A,B ;restore requested drive E764 320400 STO A,CDISK ;force  ;Digital Research has informed SORCIM that CP/M 2.2 ;CANNOT be booted off B:. ;Manipulation of CDISK is kept here to avoid the bugs ;which would appear with its disappearance. ;Booting off B: is accomplished with the RAM cell DSKSWP. E7B5 3A0400 LD A,CDISK ;use requested drive ; AND 0Fh ;force user #0 ; STO A,BDOS+0336h ;set CP/M internal ; ;'CURDSK' static variable E7B8 4F MOV C,A E7B9 F1 POP AF E7BA FE01 CMP 1 E7BC 2803 ^E7C1$ JRZ GCOLD ;If cold boot E7BE 21DBE7 LDK HL,WAUTO E7C1 7E GCOLD: LD A,[hl] E7C2 B7 ORA A E7C3 CA03D0 JZ CCP+3 ;If no auto start line E7C6 C5 PUSH BC ;Save current drive E7C7 1107D0 LDK DE,CCP+7 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:0 A E7F4 3250EF STO A,HSTACT ;Clear host active E7F7 F601 ORI 001h ;Set error flag E7F9 C9 RET E7FA WRITE: ;the selected 128 byte CP/M sector. ; ; ENTRY C = 0, write to a previously allocated block. ; C = 1, write to the directory. ; C = 2, write to the first sector of unallocated ; data block. ; ; EXIT A = 0, write was successful. ; A = 1, write was unsucessful. ; Z bit = 1, write was successful. ; Z bit = 0, write was unsucessful. E7FA CDFCE8 CALL MVINFO ;Move information for transfer E7FD 79 MOV A,C ;Write type in c E7FE 3223EF STO A,WRTYPE E801 FE02 CPI WRUAL E803 2011 ^E816$ JRNZ WRIT2 ;If write to allocated E805 3E10 LDK A,2048/128 E807 3252E ; EXIT On exit the stack will contain the following ; values: ; POP x ;x = host record address. ; POP y ;y = caller's buffer address. E855 3221EF FILL: STO A,RDFLAG ;Save read flag E858 1180ED LDK DE,HSTBUF ;initial offset E85B 218000 LDK HL,128 ;128 byte records E85E 3A18EF LD A,SEKSEC ;Get logical sector E861 EB EX DE,HL E862 0F RRC E863 3001 ^E866$ JRNC FILL3 ;If low bit not set E865 19 ADD HL,DE ;Add bias to offset E866 EB FILL3: EX DE,HL E867 29 ADD HL,HL E868 E67F ANI 07Fh ;Mask sector E86A 3218EF STO A,SEKSEC E86D 2A11EF LD HL,DMAADR E870 E3 XTHL ;Set return parameters E871 D5 PUSH DE E872 E5 PUSH HL ;Set return address E873 2150EF LDK HL,HSTACT ;h3 Page 14 Osborne CP/M 2.2 CBIOS. D:OCCBIO51.ASM E7CA 0600 LDK B,0 E7CC 4F MOV C,A E7CD EDB0 $ LDIR ;Move command line to buffer E7CF C1 POP BC E7D0 C300D0 JMP CCP ;Go to CPM = 0000 .autos IF ~ AUTOST - SIGNON: - DB 'Z'-40h - DB 'Osborne Computer System' - DB CR,LF,MSIZE/10+'0',MSIZE mod 10 + '0' - DB 'K CP/M ',VERS/10+'0','.',VERS mod 10 + '0' - DB CBIOSV+'@',CR,LF,0 .autos ENDIF E7D3 07 CAUTO: DB CAUTOL E7D4 4155544F53 DB 'AUTOST ' 5420 = 0007 CAUTOL = *-CAUTO-1 E7DB 00 WAUTO: DB WAUTOL E7DC 20 DB ' ' = 0000 WAUTOL = *-WAUTO-2 ; EF STO A,UNACNT E80A 2A19EF LD HL,SEKTRK E80D 2253EF STO HL,UNATRK ;UNATRK = SEKTRK E810 3A56EF LD A,LOGSEC E813 3C INC A E814 1819 ^E82F$ JR WRIT3 E816 2152EF WRIT2: LDK HL,UNACNT E819 7E LD A,[hl] E81A B7 ORA A E81B CA34E8 JZ WRIT4 ;If no unallocated records E81E 35 DEC [hl] ;dec unalloc record count E81F 3A55EF LD A,UNASEC ;Increment logical sector SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 16 Osborne CP/M 2.2 CBIOS. D:OCCBIO61.ASM E822 3C INC A E823 FE14 CPI 2*10 E825 2008 ^E82F$ JRNZ WRIT3 ;If not end of track E827 2A53EF LD HL,UNATRK E82A 23 INC HL E82B 2253EF STO HL,UNATRK E82E AF XRA A E82F 3255EF WRIT3: STO A,UNASEC E832 3EFF LDK A,0FFh ost active flag E876 7E LD A,[hl] E877 3601 STO 1,[hl] ;always becomes 1 E879 B7 ORA A E87A 2814 ^E890$ JRZ FILL6 ;If host buffer inactive E87C 211CEF LDK HL,HSTSEC E87F 1118EF LDK DE,SEKSEC E882 0604 LDK B,SEKDSK-SEKSEC+1 E884 1A FILL4: LD A,[de] E885 BE CMP [hl] E886 2005 ^E88D$ JRNZ FILL5 ;If mis-match E888 23 INC HL E889 13 INC DE E88A 10F8 ^E884$ DJNZ FILL4 ;If all bytes not checked E88C C9 RET E88D CDB4E8 FILL5: CALL FLUSH ;Flush host buffer E890 3A1BEF FILL6: LD A,SEKDSK ;Move disk and type E893 321FEF STO A,HSTDSK E896 3217EF STO A,ACTDSK E899 2A19EF LD HL,SEKTRK E89C 221DEF STO HL,HSTTRK E89F 2215EF STO HL,ACTTRK E8A2 3A18EF LD A,SEKSEC E8A5 321CEF STO A,HSTSEC E8A8 3214EF STO A,ACTSEC E8AB 3A21EF ndx OSBBIOS5.asm SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 15 Osborne CP/M 2.2 CBIOS. D:OCCBIO61.ASM E7DD READ: ;a CP/M 128 byte sector. ; ; EXIT A = 0, successful read operation. ; A = 1, unsucessful read operation. ; Z bit = 1, successful read operation. ; Z bit = 0, unsuccessful read operation. E7DD CDFCE8 CALL MVINFO ;Move information for transfer E7E0 AF XRA A ;Set flag to force a read E7E1 3252EF STO A,UNACNT ;Clear sector counter E7E4 CD55E8 CALL FILL ;Fill buffer with data E7E7 E1 POP HL E7E8 D1 POP DE E7E9 018000 LDK BC,128 ;Move 128 bytes E7EC EDB0 $ LDIR E7EE 3A22EF LD A,ERFLAG E7F1 B7 ORA A E7F2 C8 RZ ;If no error E7F3 AF XRA E834 CD55E8 WRIT4: CALL FILL E837 D1 POP DE E838 E1 POP HL E839 018000 LDK BC,128 E83C EDB0 $ LDIR E83E 3E01 LDK A,1 E840 3251EF STO A,HSTWRT ;HSTWRT = 1 E843 3A22EF LD A,ERFLAG E846 B7 ORA A E847 C0 RNZ ;If any errors occurred E848 3A23EF LD A,WRTYPE ;write type E84B FE01 CPI WRDIR ;to directory? E84D CCB4E8 CZ FLUSH ;Force write of directory E850 3A22EF LD A,ERFLAG E853 B7 ORA A E854 C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 17 Osborne CP/M 2.2 CBIOS. D:OCCBIO61.ASM ; FILL - fill host buffer with approprite host sector. ; ; ENTRY A = 0, Read required if not in buffer. ; 0therwise read not required. ;  LD A,RDFLAG E8AE B7 ORA A E8AF C0 RNZ ;If no read required SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 18 Osborne CP/M 2.2 CBIOS. D:OCCBIO61.ASM E8B0 3E00 LDK A,0 ;Read E8B2 181C ^E8D0$ JR FINAL ; FLUSH - Write out active host buffer onto disk. E8B4 FLUSH: E8B4 2151EF LDK HL,HSTWRT E8B7 7E LD A,[hl] E8B8 B7 ORA A E8B9 C8 RZ ;If host buffer already on disk E8BA 3600 STO 0,[hl] E8BC 3A1FEF LD A,HSTDSK ;Move disk and type E8BF 3217EF STO A,ACTDSK E8C2 2A1DEF LD HL,HSTTRK E8C5 2215EF STO HL,ACTTRK E8C8 3A1CEF LD A,HSTSEC E8CB 3214EF STO A,ACTSEC E8CE 3E03 LDK A,3 ;Write flag ; JMP FINAL E8D0 FINAL: ;Preform final  by zero. ; ; EXIT HL -> zero byte + 1. ; A = 0. ; Z bit set. ; ; Destroys only HL, Flags, and A registers. E907 7E PRINT: LD A,[hl] ;Get a character E908 B7 ORA A E909 23 INC HL E90A C8 RZ ;If zero the terminate E90B E5 PUSH HL E90C 4F MOV C,A E90D CD0CE6 CALL CONOUT ;Output to the console E910 E1 POP HL E911 18F4 ^E907$ JR PRINT E913 = 0002 SAVADR: DS 2 ;Disk transfer routine vector = 0000 IF * > (MRAM-1) - MSG 'CBIOS is too long, lwa= ',* - .9 ERROR ENDIF ; Endx OSBBIOS8.asm SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 2 ldk hl,ptr_list ;table of list routines E92C C347E9 jmp dispch ;--------------- ; output to punch ; E92F PNCH: E92F 0606 mvi b,6 E931 2178E9 ldk hl,ptr_pnch ; punch routines E934 C347E9 jmp dispch ;---------------- ; reader input SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 22 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ; E937 RDR: E937 0608 mvi b,8 E939 2180E9 ldk hl,ptr_rdr ; reader routines E93C C347E9 jmp dispch ; L i s t S t a t u s. ; ; Return the ready status for the list device. ; ; EXIT A = 0 (zero), list device is not ready to ; accept another character. transfer processing. ; ; ENTRY A = 0 .. read disk. ; = 3 .. write disk. ; Calls: Rom resident routine to read/write ONE ; sector only. E8D0 5F MOV E,A E8D1 1600 LDK D,0 E8D3 212701 LDK HL,ROMVEC+3*13 E8D6 19 ADD HL,DE E8D7 2213E9 STO HL,SAVADR E8DA 2114EF LDK HL,ACTSEC E8DD 34 INC [hl] ;update sector+1 E8DE 3E05 LDK A,MRTRY ;Set retry count E8E0 3205EF FNL1: STO A,RTRY ;Clear retry count E8E3 2A13E9 LD HL,SAVADR E8E6 EB EX DE,HL E8E7 0601 LDK B,1 ;indicate one sector xfer E8E9 CDC4E6 CALL ROMJMP ;process read or write E8EC 3222EF STO A,ERFLAG ;set possible error flag E8EF C8 RZ ;If no errors E8F0 3A05EF LD A,RTRY ;Get retry counter E8F3 3D DEC A E8F4 21 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ;***** ; file: OSBbios9.asm ; This file contains CP/M extensions to the OSBORNE CBIOS ; added by MICOROCDE CORPORATION. ; ; Revisions: ; YNS 20AUG81 Initial release ; YNS 29AUG81 Expanded trans. table to include ctl/numerics ; Translate keys to 1/2 or three char seq. ; Iobyte assignements redone. ; YNS 01SEP81 Added parallel port support ; ;***** ; ; the following routines will use the IOBYTE to transfer ; control to the appropriate device driver ; ;-------------- ; return con ; A = FFh (255), list device is ready to accept ; a character. ; The list status is returned depending upon the iobyte fields ; LIST field (bits 6,7) ; =0: status of crt. (always ready) ; =1: status of parallel port printer ; =2: status of serial printer ; =3: complete status of serial port ; E93F LSTST: E93F 0604 mvi b,4 ;number of left shifts thru carry ;to align LIST field of IOBYTE E941 2188E9 ldk hl,ptr_lst ;list status routines E944 C347E9 jmp dispch SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 23 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM E947 dispch: ; on entry her0EA ^E8E0$ JRNZ FNL1 ;If not permanent error E8F6 F601 ORI 01h E8F8 3222EF STO A,ERFLAG ;Set error flag E8FB C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 19 Osborne CP/M 2.2 CBIOS. D:OCCBIO61.ASM ; endx OSBBIOS6.asm SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 20 Osborne CP/M 2.2 CBIOS. D:OCCBIO71.ASM ; MVINFO Move information necessary for transfer. E8FC MVINFO: E8FC AF XRA A E8FD 3222EF STO A,ERFLAG ;Clear error flag E900 3A20EF LD A,TEMSEC E903 3218EF STO A,SEKSEC E906 C9 RET ; Print message terminated by zero byte. ; ; ENTRY HL -> message buffer, terminatedsole status ; E915 CNSTA: E915 2158E9 ldk hl,ptr_cstat ; status table E918 1808 ^E922$ jr godispch ; call appropriate rtn ;------------ ; read input character from device ; E91A CNIN: E91A 2160E9 ldk hl,ptr_cinp ; table of input rtns E91D 1803 ^E922$ jr godispch ;------------- ; put output character to device ; c contains output character ; E91F CNOUT: E91F 2168E9 ldk hl,ptr_cout ; table of output rtns E922 godispch: E922 0601 mvi b,1 ;number of shifts required to align ;CONSOLE field E924 C347E9 jmp dispch ;--------------- ; list device character output ; E927 LST: E927 0604 mvi b,4 E929 2170E9 e reg B contains the left shift count ; required to align the iobyte field to bit 1 position. ; and reg HL contains address of select table E947 3A0300 lda iobyte E94A dspch1: E94A 17 ral E94B 10FD ^E94A$ djnz dspch1 E94D E606 ani 6 ;get select field*2 E94F 5F mov e,a E950 1600 ldk d,0 ; de = iobyte field * 2 E952 19 dad de E953 5E mov e,m E954 23 inx hl E955 66 mov h,m ; get the routine address E956 6B mov l,e ; into hl and xchange with pc E957 E9 pchl ; ; addresses of routines ; E958 ptr_cstat: E958 90E9 dw const ; keyboard status E95A 7BEB dw pistat ; parallel input stat E95C 7CEA dw sistat ; serial port input status E95E A6EA dw ieinstat ; status A register. ; ; EXIT A = 0 (zero), means no character ; currently ready to read. ; ; A = FFh (255), means character ; currently ready to read. = 0000 nokey equ 00h ;indicates key not present E990 CONST: ; check if any translated keys are pending E990 3AF2E9 ld a,xltkey E993 B7 ora a E994 2006 ^E99C$ jrnz const5 ; if no xlated keys pending, check keyhit flag E996 3A5EEF LD A,LKEY ;Get Key hit flag E999 EE00 xri nokey E99B C8 RZ ;If data not available E99C const5: E99C F6FF ORI 0FFh E99E C9 RET SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 26 Osborne CP/M 2.2 CBIOS.  E9B3 1E09 ldk e,low(conin) E9B5 CDBFE6 call romcd1 ; ; when control is returned here, A has the input code for ; console character. If code is between 80h and 8fh, it is ; translated. ; E9B8 FE80 cpi basvl0 E9BA D8 rc ;return when code is not tobe xlated E9BB FE8E cpi basvl0+tbllen E9BD D0 rnc E9BE D680 sui basvl0 ;subtract base val E9C0 17 ral ;mult remainder by 2 E9C1 5F mov e,a ;build ptr to table entry E9C2 1600 mvi d,0 E9C4 21F3E9 ldk hl,xltbl E9C7 19 dad de E9C8 7E ld a,[hl] ;get byte 0 E9C9 23 inx hl ;point to byte 1 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 27 Osborne CP/M 2.2 CBIOS. D of input device on IEEE port E960 ptr_cinp: E960 9FE9 dw keyinp ; get input from keyboard E962 97EB dw parinp ; parallel input E964 85EA dw spinp ; serial port input E966 A7EA dw ieinp ; ieee port input E968 ptr_cout: E968 12EA dw crtout ; output character to crt E96A A9EB dw parout ; parallel output E96C 8BEA dw spout ; serial port output E96E D9EA dw ieout ; ieee port output E970 ptr_list: E970 12EA dw crtout ; list assigned to crt E972 A9EB dw parout ; parallel port output E974 8BEA dw spout ; serial port E976 90EA dw ACICTL ; serial port usart ctl E978 ptr_pnch: E978 12EA dw crtout ; punch assigned to crt E97A D9EA dw ieout ; ieee port E97C 8BEA dw spout ; serial port E97E A9EB dw parout ; parallel port out E980 ptr_rd D:OCCBIO81.ASM ;** ; Routine name: KEYINP - gets keystroke from rom kbd driver. Translates ; the codes 80h to 8fh as per table. ; ; Outputs: A = translated code in ASCII ; All registers are destroyed ; ; Translation scheme: ; the translation table has a two byte entry for each code between ; 80h and 8fh. The incoming keystroke from the keyboard is translated ; to one, two or three character sequence as follows: ; if byte 0 is all zeros, the translated value is byte 1. ; if byte 0 is less than 80h, the key is translated to a ; 2 byte sequence: byte0 byte1 ; if byte 0 is 80h to ffh, the key is translated to a 3 byte ; sequence: Escape byte0-80h byte1 :OCCBIO81.ASM E9CA B7 ora a E9CB 2002 ^E9CF$ jrnz kin40 ;if first byte is 0 then E9CD 7E ld a,[hl] E9CE C9 ret ;return with byte1 as xlated val. E9CF kin40: ; if msb of byte 0 is 0 then the xlated val is byte0 and byte 1 E9CF CB7F $ bit 7,a E9D1 200C ^E9DF$ jrnz kin50 ;elseif bit7 is 0 then E9D3 F5 push af ;save byte 0 E9D4 7E ld a,[hl] ;get byte1 from table E9D5 32F0E9 sto a,xltvl1 ;save translated value E9D8 3E01 lk a,1 E9DA 32F2E9 sto a,xltkey ;set xlated keys to 1 E9DD F1 pop af E9DE C9 ret ;return with the first char of the ;sequence E9DF kin50: ;else ; the key is translated to a three char seq. esc byte0-80h byte1 E9DF E67F ani 07fh ;get lower seven bits E9E1 32F1E9 sto a,xltvl2 ;save byte0-80h E9E4 7E r: E980 9FE9 dw keyinp ; reader assigned to keyboard E982 A7EA dw ieinp ; ieee port E984 85EA dw spinp ; serial port E986 97EB dw parinp ; parallel port input E988 ptr_lst: E988 0FEA dw crstat E98A 68EB dw postat ;parallel port output stat E98C 73EA dw sostat ;serial port output stat E98E 9AEA dw acistat ;serial port usart status SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 24 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 25 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ; C O N S O L S T A T U S ; ; This routine samples the Console status and returns the ; following values in the = 0080 basvl0 equ 80h ;lowest code of the codes that ;are translated. E99F KEYINP: ; if there are no xlated keys waiting then ; call the keyboard driver in rom E99F 21F2E9 ldk hl,xltkey E9A2 7E ld a,[hl] ;get number of xlated keys E9A3 B7 ora a E9A4 280D ^E9B3$ jrz kin30 ;if keys pending then E9A6 35 dec [hl] ;reduce pending count E9A7 FE01 cpi 1 E9A9 2004 ^E9AF$ jrnz kin20 ;if only one key then E9AB 3AF0E9 ld a,xltvl1 ;get translated value E9AE C9 ret ;return E9AF kin20: ;else if two keys are waiting then E9AF 3AF1E9 ld a,xltvl2 ;get first val E9B2 C9 ret ;return ;endif E9B3 kin30: ;else ; get next key from keyboard driver and translate if reqd.   ld a,[hl] E9E5 32F0E9 sto a,xltvl1 ;save byte1 E9E8 3E02 lk a,2 E9EA 32F2E9 sto a,xltkey E9ED 3E1B lk a,1bh ;a = esc code E9EF C9 ret E9F0 00 xltvl1: db 0 E9F1 00 xltvl2: db 0 E9F2 00 xltkey: db 0 E9F3 xltbl: ;default table ; ctl numerics produce and escape seq. Esc n ; cursor keys produce ctl/l, ctl/h, ctl/k and ctl/j E9F3 1B30 db 1bh,'0' E9F5 1B31 db 1bh,'1' E9F7 1B32 db 1bh,'2' E9F9 1B33 db 1bh,'3' E9FB 1B34 db 1bh,'4' E9FD 1B35 db 1bh,'5' E9FF 1B36 db 1bh,'6' EA01 1B37 db 1bh,'7' EA03 1B38 db 1bh,'8' EA05 1B39 db 1bh,'9' EA07 000B db 0,'K'-40h EA09 000C db 0,'L'-40h EA0B 000A db 0,'J'-40h EA0D 0008 db 0,'7 3E01 ldk a,1 ;set dc4 flag EA29 3270EA sto a,dc4flg EA2C C9 ret EA2D crt10: ;else (*this is called as a sbrt*) EA2D AF xra a EA2E 3270EA sto a,dc4flg ;reset dc4 found flag EA31 1E0C ldk e,low(conout) ;output to crt EA33 C3BFE6 jmp romcd1 ; ; following ensures that the character following the dc4 ; is between 30h and 30h+tbllen. In case of error the characters ; are displayed. EA36 crt20: EA36 FE01 cpi 1 EA38 C257EA jnz crt30 ;exit when it is not second char after dc4 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 29 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM EA3B 79 mov a,c EA3C D630 sui '0' ; do a range check on code EA3E DA67EA jc crt40 ;exit when char .lt. '0' EA4 rz ;return with not ready status EA79 F6FF ori true EA7B C9 ret ;** ; routine: SISTAT ; gets status of input device attached to serial port EA7C SISTAT: EA7C CD9AEA call acistat EA7F E601 ani si.rrdy EA81 C8 rz ;return with not ready status EA82 F6FF ori true EA84 C9 ret ;** ; routine: SPINP ; Inputs a character from the serial port ; Uses the reader (sp) driver in ROM ; EA85 SPINP: EA85 1E15 ldk e,low(reader) EA87 C3BFE6 jmp romcd1 EA8A C9 ret ;** ; routine: SPOUT ; Outputs character in reg c to the serial port (list device) H'-40h = 000E tbllen equ (*-xltbl)/2 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 28 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ;** ; routine: CRSTAT ; returns status of crt. ; crt is always ready EA0F CRSTAT: EA0F F6FF ori 0FFh EA11 C9 ret ;** ; routine name: CRTOUT ; ; inputs: C: output character ; outputs: update translate table when the dc4 sequence found provided ; we are not in an escape seq. or in graphic mode. ; otherwise outputs the character to console ; all registers destroyed ; The dc4 sequence is as follows: 1 FE0E cpi tbllen EA43 D267EA jnc crt40 ;or .gt. entries in table EA46 07 rlc ; multiply index by 2 EA47 4F mov c,a EA48 0600 ldk b,0 ; set up bc for a dbl add EA4A 21F3E9 ldk hl,xltbl EA4D 09 dad bc ; add bc to hl EA4E 2271EA shld tblptr ; save the ptr EA51 3E02 ldk a,2 ; set dc4 flg to indicate EA53 crt25: EA53 3270EA sto a,dc4flg ;next state EA56 C9 ret ; ; store input character in xlate table EA57 crt30: EA57 2A71EA lhld tblptr EA5A 71 mov m,c EA5B D603 sui 3 EA5D 28F4 ^EA53$ jrz crt25 ;clear dc4 flag and return when last ;char of dc4 seq received. EA5F 23 inc hl ;increment table ptr for next byte EA60 2271EA shld tblptr EA63 3E03 ldk a,3 EA65 18EC; calls the list (sp) driver in ROM ; EA8B SPOUT: EA8B 1E0F ldk e,low(list) EA8D C3BFE6 jmp romcd1 ;** ; routine: ACICTL ; outputs character in c to the ACIA CTL port. ; EA90 ACICTL: EA90 CDC2EB call sw2rom EA93 79 mov a,c EA94 32002A sta h.sctrl EA97 C3D0EB jmp sw2ram ;** ; routine: acistat ; returns usart status in A EA9A acistat: EA9A CDC2EB call sw2rom EA9D 3A002A lda h.ssts EAA0 C3D0EB jmp sw2ram SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 31 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ; ie device mod values = 0000 ie_ta ; dc4 k b0 b1 ; where: ; dc4 is the ascii device control char code 14h ; k is the table entry number + 30h. ; b0 is byte 0 of the table. ; b1 is byte 1 of the table. ; esch flag bit definitions (also check in file bmkey.asm) = 0008 ef_esc: equ 8 = 0001 ef_gr: equ 1 EA12 CRTOUT: EA12 3A60EF lda esch EA15 E609 and ef_esc+ef_gr EA17 C22DEA jnz crt10 ;check for dc4 seq only when neither esc seq ; nor graphic EA1A 3A70EA lda dc4flg ; EA1D B7 ora a ; EA1E C236EA jnz crt20 ; if not in dc4 sequence then EA21 79 mov a,c EA22 FE14 cpi dc4cod EA24 C22DEA jnz crt10 ;if start of dc seq then EA2 ^EA53$ jr crt25 ; ; Illegal sequence. Char following dc4 is not valid. This ; outputs a dc4 and the invalid char to the crt. EA67 crt40: EA67 C5 push bc ;save current char EA68 0E14 ldk c,dc4cod EA6A CD2DEA call crt10 ;***note*** EA6D C1 pop bc EA6E 18BD ^EA2D$ jr crt10 ; EA70 00 dc4flg db 0 EA71 0000 tblptr dw 0 = 0014 dc4cod equ 14h SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 30 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ;** ; routine: SOSTAT ; gets status of output device attached to serial port EA73 SOSTAT: EA73 CD9AEA call acistat ;get 6850 status EA76 E602 ani si.trdy EA78 C8 !lk equ 0 ;device is a talker = 0001 ie_lstn equ 1 ;device is a listener EAA3 00 ie_ad0 db 0 ;device address EAA4 00 ie_ad1 db 0 EAA5 00 iemode db 0 ;mode of IEEE device ;** ; routine: IEINSTAT ; gets status of the input device attached to ieee port ; Uses ROM resident primitives EAA6 IEINSTAT: ;************* EAA6 C9 ret ;** ; routine: IEINP ; Reads a character from IEEE port ; Uses ROM resident primitives. EAA7 IEINP: EAA7 3AA5EA lda ie_mode EAAA CB47 $ bit ie_talk,a EAAC 2821 ^EACF$ jrz iei20 ;if device is not a talker then ;make talker EAAE iei05:  jmp romcd1 ;output secondary address EAF8 B7 ora a EAF9 20F2 ^EAED$ jrnz ieo10 EAFB 21A5EA lk hl,ie_mode EAFE CBCE $ sbit ie_lstn,[hl] ;set mode to listener EB00 ieo20: ; EB00 1E4E ldk e,low(ieb6c) EB02 C3BFE6 jmp romcd1 EB05 B7 ora a EB06 20F8 ^EB00$ jrnz ieo20 ;try again if error EB08 C9 ret SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 33 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ;** The Parallel port is actually the IEEE port driven with the centronix ; protocol. The bit assignements of the PIA and PIB are as follows: ; PIA0-7 = data bus ; PIB0 = 0, data bus is output. 1, data bus is input ; PIB1 = set to 1. ; PIB2 = set to 0. rdy bit in pia ctl reg = 0020 strb equ 00100000b ;strobe bit in port b ; port modes = 0000 pp.undef equ 0 = 0001 pp.out equ 1 = 0002 pp.in equ 2 EB09 00 pp.mode db pp.undef ;*** ; sbrt: CV2OP. initializes the port to a parallel output ; port. SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 34 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM EB0A cv2op: EB0A 3A09EB lda pp.mode EB0D FE01 cpi pp.out EB0F C8 rz ;return when in output mode ; set port a to output on all lines EB10 3E2A lk a,pa.cdr EB12 320129 sta pa.ctl ;select direction reg EB15 3EFF lk a,pa.dro EB17 320029 sta pa.dir ;output constant to dir EAAE 3AA3EA lda ie_ad0 EAB1 C640 adi 40h ;get primary address EAB3 4F mov c,a EAB4 1E4B ldk e,low(ieb5c) EAB6 C3BFE6 jmp romcd1 ;output interface message EAB9 B7 ora a EABA 20F2 ^EAAE$ jrnz iei05 ;try again if error EABC iei10: EABC 3AA4EA lda ie_ad1 EABF C660 adi 60h EAC1 4F mov c,a EAC2 1E4B ldk e,low(ieb5c) EAC4 C3BFE6 jmp romcd1 ;output secondary address EAC7 B7 ora a EAC8 20F2 ^EABC$ jrnz iei10 EACA 21A5EA lk hl,ie_mode EACD CBC6 $ sbit ie_talk,[hl] ;set mode to talker EACF iei20: ; EACF 1E51 ldk e,low(ieb7c) EAD1 C3BFE6 jmp romcd1 EAD4 CB7D $ bit 7,l EAD6 20F7 ^EACF$ jrnz iei20 ;try again if error EAD8 C9 ret ;** ; rout ; PIB3 = 0 output, 1 Input ; PIB4 = not used ; PIB5 = output strobe. Active = 1. ; PIB6 = 0, printer busy. 1, printer is ready. ; PIB7 = not used. ; ; CA2 = going low indicates to device that we are busy. ; CA1 = low to high transition gates input data to port a. ; ; The port is bidirectional but only one direction ; can be active at any time. The direction of port is determined ; by which routines are called. If postat or parout are ; called, it is made an output port and an input port if ; pistat or parinp are called. ; port registers = 2900 pa.dta equ h.ieee+0 = 2900 pa.dir equ pa.dta = 2901 pa.ctl equ h.ieee+1 = 2902 pb.dta equ h.. reg to put ; a port in output mode EB1A 3E2E lk a,pa.cdt EB1C 320129 sta pa.ctl ;select port a data reg. EB1F 3E00 lk a,pb.cdr EB21 320329 sta pb.ctl ;select port b direction EB24 3EBF lk a,pb.dr EB26 320229 sta pb.dir ;all lines are output except the output ;busy signal on bit 6 EB29 3E04 lk a,pb.cdt EB2B 320329 sta pb.ctl ;select data register EB2E 3E02 lk a,pb.dto EB30 320229 sta pb.dta ;initialize port b data EB33 3E01 lk a,pp.out EB35 3209EB sta pp.mode EB38 C9 ret ;*** ; sbrt: CV2IP. initializes the port to a parallel input ; port. EB39 cv2ip: EB39 3A09EB lda pp.mode EB3C FE02 cpi pp.in EB3E C8 rz ;return when in input mode ine: IEOUT ; Outputs the character in reg C to IEEE port ; Uses ROM resident primitives. SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 32 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ; EAD9 IEOUT: EAD9 3AA5EA lda ie_mode EADC CB4F $ bit ie_lstn,a EADE 2820 ^EB00$ jrz ieo20 ;if device is not a listener then ;make listener EAE0 ieo05: EAE0 3AA3EA lda ie_ad0 EAE3 C620 adi 20h ;get primary address EAE5 4F mov c,a EAE6 1E4B ldk e,low(ieb5c) EAE8 C3BFE6 jmp romcd1 ;output interface message ora a EAEB 20F3 ^EAE0$ jrnz ieo05 ;try again if error EAED ieo10: EAED 3AA4EA lda ie_ad1 EAF0 C660 adi 60h EAF2 4F mov c,a EAF3 1E4B ldk e,low(ieb5c) EAF5 C3BFE6 ieee+2 = 2902 pb.dir equ pb.dta = 2903 pb.ctl equ h.ieee+3 ; port ctl register constants. = 002A pa.cdr equ 00101010b ;to address port a direction = 002E pa.cdt equ 00101110b ;to address port a data and set ;port a in input program handshake mode. = 0000 pb.cdr equ 00000000b ;to address port b direction = 0004 pb.cdt equ 00000100b ;to address port b data ; direction register constants = 00FF pa.dro equ 0ffh ;port a output mode = 0000 pa.dri equ 00h ;port a input mode = 00BF pb.dr equ 0bfh ;port b direction = 0002 pb.dto equ 00000010b ;port b data for output = 000B pb.dti equ 00001011b ;port b data for input = 0040 pp.ordy equ 01000000b ;output rdy bit in pib = 0080 pp.irdy equ 10000000b ;input " ; set port a to input on all lines EB3F 3E2A lk a,pa.cdr EB41 320129 sta pa.ctl ;select direction reg EB44 3E00 lk a,pa.dri EB46 320029 sta pa.dir ;output constant to dir. reg to put ; a port in input mode EB49 3E2E lk a,pa.cdt EB4B 320129 sta pa.ctl ;select port a data reg. EB4E 3E00 lk a,pb.cdr EB50 320329 sta pb.ctl ;select port b direction EB53 3EBF lk a,pb.dr EB55 320229 sta pb.dir ;all lines are output except the output ;busy signal on bit 6 EB58 3E04 lk a,pb.cdt EB5A 320329 sta pb.ctl ;select data register EB5D 3E0B lk a,pb.dti EB5F 320229 sta pb.dta ;initialize port b data EB62 3E02 lk a,pp.in EB64 3209EB sta pp.mode EB67 C9 ret SORCIM 808 ;** SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 36 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ; routine: PAROUT ; outputs the character in c to the IEEE port treating the ; port as a parallel port. EBA9 PAROUT: EBA9 CD68EB call postat EBAC 28FB ^EBA9$ jrz parout EBAE CDC2EB call sw2rom EBB1 79 mov a,c EBB2 320029 sta pa.dta EBB5 3E22 lk a,pb.dto+strb EBB7 320229 sta pb.dta ;set strobe EBBA 3E02 lk a,pb.dto EBBC 320229 sta pb.dta ;clear strobe EBBF C3D0EB jmp sw2ram SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 37 Osborne CP/M 2.2 CBIOS.  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 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 *********REDEFINED************* EF09 = 0000 MSECB DS 0 ;MULTI SECx Assembler ver 3.5E 5=/00/;1 1<:03 Page 35 Osborne CP/M 2.2 CBIOS. D:OCCBIO81.ASM ;** ; routine: POSTAT ; gets status of the parallel (centronix) printer ; attached to the ieee port ; EB68 POSTAT: EB68 CDC2EB call sw2rom EB6B CD0AEB call cv2op ;convert to output EB6E 3A0229 lda pb.dta ;get port b data EB71 E640 ani pp.ordy EB73 2802 ^EB77$ jrz pos10 EB75 F6FF ori true EB77 pos10: EB77 C3D0EB jmp sw2ram ;** ; routine: PISTAT ; gets status of the input device attached to the ; parallel port ; EB7A 00 piactl db 0 EB7B PISTAT: EB7B CDC2EB call sw2r D:OCCBIO81.ASM ;*** ; sbrt: SW2ROM ; switches to rom ; saves all registers EBC2 SW2ROM: EBC2 di EBC2 +F3 DB 0F3h EBC3 F5 push af EBC4 enarom EBC4 + DI EBC4 +F3 DB 0F3h EBC5 +D300 OUT 0 EBC7 +3E00 LDK A,0 EBC9 +3208EF STO A,ROMRAM EBCC + EI EBCC +FB DB 0FBh EBCD F1 pop af EBCE ei EBCE +FB DB 0FBh EBCF C9 ret ;*** ; sbrt: SW2RAM ; switches to ram ; preserves all registers EBD0 SW2RAM: EBD0 di EBD0 +F3 DB 0F3h EBD1 F5 push af EBD2 disrom EBD2 + DI EBD2 +F3 DB 0F3TOR BYTES FOR R/W **********not used************* 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 ; 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) SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 39 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM = EF14 ACTSEC = SAVSEC = EF15 ACTTRKom EB7E CD39EB call cv2ip EB81 3A7AEB lda piactl EB84 E680 ani pp.irdy EB86 200A ^EB92$ jrnz pis20 ;if saved status indicates there is a char ;in the PIA EB88 3A0129 lda pa.ctl EB8B 327AEB sta piactl ;this is saved as reading the ;pia clears the status EB8E E680 ani pp.irdy EB90 2802 ^EB94$ jrz pis30 EB92 pis20: EB92 F6FF ori true EB94 pis30: EB94 C3D0EB jmp sw2ram ;** ; routine: PARINP ; inputs a character from parallel port. EB97 PARINP: EB97 CD7BEB call pistat EB9A 28FB ^EB97$ jrz parinp ;wait till char in pia EB9C CDC2EB call sw2rom EB9F AF xra a EBA0 327AEB sta piactl ;clear saved status EBA3 3A0029 lda pa.dta EBA6 C3D0EB jmp sw2ram h EBD3 +D301 OUT 1 EBD5 +3E01 LDK A,1 EBD7 +3208EF STO A,ROMRAM EBDA + EI EBDA +FB DB 0FBh EBDB F1 pop af EBDC ei EBDC +FB DB 0FBh EBDD C9 ret SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 38 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM ;MRAM - Debug Monitor RAM Storage. ; Used to assembly ROM resident and CBIOS EBDE = ED80 ORG MRAM ; Host disk xfer buffer and... ; Format track template holding buffer ED80 HSTBUF: = 0000 IF DEF FMTDAT - RMTDAT DS 0 - DS (FMTSD-FMTDAT) - RFMTSD DS 0 - # = 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 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 = 0 DS 2 ;save current stk ptr ; 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 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 EFC8 += 0008 DS (*+(10H)-1)/(10H)*(10H)-* p Vector is between EFFO, EFFF. SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 42 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM ; Endx MRAM no ERRORs, 463 Labels, 688Fh bytes not used. Program LWA = EFEFh.  s @FREQ 0FA0 n ACIAD EFC1 40#28 ACICTL EA90 23/41 30#44 ACISTA EA9A 23/56 30/ 5 30/15 30#53 ACTDSK EF17 17/48 18/17 39# 4 ACTSEC EF14 17/54 18/21 18/40 39# 2 ACTTRK EF15 17/51 18/19 39# 3 n AFSAX EFD4 40#46 s ALIGN mac 40/42 40/56 ALV EF24 5/36 5/49 39#19 s ALVS 000C 6/14 39/19 ALVSZ 000C 3#12 5/36 5/39 5#39 5/49 5/52 5#52 6/14 n ASAVE EFE5 41# 6 AUTOST FFFF 1#27 12/48 12/54 14/ 7 BASVL0 0080 26#18 26002 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 ;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 EF6EFD0 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 EFDE += 0002 DS (*+(10H)-1)/(10H)*(10H)-* EFE0 REGS: SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 41 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM 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/46 26/48 26/50 BCCP E787 12/57 13#14 BCPM E779 13# 6 13/10 n BCSAX EFD2 40#45 s BDOS D806 13/32 n BELCNT EF6B 40# 6 s BIOS E600 4/ 8 13/30 BIOSTK EFC1 8/10 40#25 n BKPA EFEC 41#17 n BKPC EFEE 41#18 n BSAVE EFE3 41# 4 CAUTO E7D3 13/36 14#16 14/19 CAUTOL 0007 14/16 14#19 CBOOT E759 4/10 12#35 s CCP D000 12/47 13/ 3 13/ 7 13/55 13/57 14/ 5 s CDISK 0004 9/49 9/52 12/46 13/43 n CKEY EF5F 39#39 CNIN E91A 4/13 21#29 CNOUT E91F 4/14 21#36 CNSTA E915 4/12 21#23 CONIN E609 4#13 26/39 CONOUT E60C 4#14 20/29 28/49 CONST E990 23/23 25#14 CONST5 E99C 25/18 25#24 CRSTAT EA0F 23/53 28# 5 CRT10 EA2D 28/35 28/42 28#46 29/35 29/37 CRT20 EA36 6 = 0006 HOURS: DS 6 = EF67 MINS: = HOURS+1 = EF68 SECS: = HOURS+2 = EF69 SEC6: = HOURS+3 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 40 BMRAM - Debug Monitor RAM Storage. D:BMRAM .ASM ; 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 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: 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) - .9 DW *, STK, must be equal ENDIF ;TEMP: DS 1 ;TEMPORARY MONITOR CELL EFEC = 0002 BKPA: DS 2 ;last breakpoint address EFEE = 0001 BKPC: DS 1 ;Contents of bkp = 0000 IF * >= LWAMEM - MSG 'RAM temporary area too large ',* - .9 ERROR ENDIF = 0000 IF * > INTBL - .9 ERROR - MSG 'RAM overflow into Int Vector ', * ENDIF ; Interrupt Jum$ 28/39 28#55 CRT25 EA53 29#13 29/22 29/27 CRT30 EA57 28/57 29#18 CRT40 EA67 29/ 3 29/ 5 29#32 CRTOUT EA12 23/33 23/38 23/43 28#32 n CSAVE EFE2 41# 3 CSV EF30 5/35 5/48 39#20 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 43 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM s CSVS 0020 39/20 CSVSZ 0020 3#13 5/35 5/38 5#38 5/48 5/51 5#51 CUNACT E738 10#25 11/12 n CURS EF5A 39#33 CV2IP EB39 34#30 35/26 CV2OP EB0A 33#58 35/ 8 n DACTVE EF6A 40# 4 s DBUF 0080 13/17 DC4COD 0014 28/41 29/34 29#42 DC4FLG EA70 28/37 28/44 28/48 29/14 29#39 n DESAX EFD0 40#44 sD DI mac 7/14 8/ 7 8/14 8/23 8/27 12/39 37/ 7 37/11 37/28 37/32 SSTS 2A00 30/55 n HKCNT EF5D 39#37 n HLSAX EFD6 40#47 HOME E6EC 4/18 9# 7 13/ 4 HOURS EF66 39#54 39/55 39/56 39/57 40/ 4 40/ 6 n HSAVE EFE7 41# 8 HSTACT EF50 9/10 15/20 17/28 39#23 HSTBUF ED80 13/19 17/12 38#12 38/32 HSTDSK EF1F 17/47 18/16 39#12 HSTSEC EF1C 17/33 17/53 18/20 39#10 n HSTSIZ 0100 2#17 HSTTRK EF1D 17/50 18/18 39#11 HSTWRT EF51 16/18 18/11 39#24 IDAY EF63 13/34 39#48 39/49 39/50 IEAD0 EAA3 31# 5 31/28 32/ 8 IEAD1 EAA4 31# 6 31/36 32/15 n IEB1C E63F 4#35 n IEB2C E642 4#36 n IEB3C E645 4#37 n IEB4C E648 4#38 IEB5C E64B 4#39 31/31 31/39 32/11 32/18 IEB6C E64E 4#40 32/27 IEB7C E651 4#41 31/48 n IEB8C E654 4#42 IEI05 EAAE 31#27 31/28 NOFDD 0002 3#11 5/37 5#37 5/50 5#50 NOKEY 0000 25#12 25/22 s NVDL 0018 PA.CDR 002A 33#31 34/ 6 34/35 PA.CDT 002E 33#32 34/11 34/40 PA.CTL 2901 33#25 34/ 7 34/12 34/36 34/41 35/31 PA.DIR 2900 33#24 34/ 9 34/38 PA.DRI 0000 33#39 34/37 PA.DRO 00FF 33#38 34/ 8 PA.DTA 2900 33#23 33/24 35/51 36/ 9 PARINP EB97 23/29 23/51 35#45 35/47 PAROUT EBA9 23/34 23/39 23/46 36# 4 36/ 6 PB.CDR 0000 33#34 34/14 34/43 PB.CDT 0004 33#35 34/19 34/48 PB.CTL 2903 33#28 34/15 34/20 34/44 34/49 PB.DIR 2902 33#27 34/17 34/46 PB.DR 00BF 33#40 34/16 34/45 PB.DTA 2902 33#26 33/27 34/22 34/51 35/ 9 36/11 36/13 PB.DTI 000B 33#42 34/50 PB.DTO 0002 33#41 34/21 36/10 36/12 n PIAAD EF61 39#4DIRBUF EE80 5/33 5/46 38#32 n DIROM 0001 2#40 DISPCH E947 21/41 21/48 21/55 22/ 5 22/29 22#33 s DISROM mac 8/26 12/38 37/31 s DMA 0080 DMAADR EF11 10/53 17/23 38#49 DMADR EF0F 13/20 38#48 DPBASE E66B 5#27 9/38 DPBGEN mac 3#50 6/ 6 DPBS1 E68B 5/34 5/47 6# 3 DPHGEN mac 3#16 5/29 5/42 n DSAVE EFE1 41# 2 DSKS1 0000 2#24 6/ 6 n DSKSWP EFC7 40#37 DSPCH1 E94A 23# 7 23/ 9 n DSTSB EF09 38#45 n ECHOP EF07 38#40 EFESC 0008 28#28 28/34 EFGR 0001 28#29 28/34 sD EI mac 7/21 7/39 8/19 8/32 8/37 8/41 12/44 37/16 37/19 37/37 37/40 s ENAROM mac 8/13 37/10 n ENROM 0000 2#39 ERCNT EF02 38#36 38/37 ERFLAG EF22 15/16 16/19 16/26 18/48 /34 IEI10 EABC 31#35 31/42 IEI20 EACF 31/25 31#47 31/51 IEINP EAA7 23/31 23/49 31#22 IEINST EAA6 23/26 31#14 IELSTN 0001 31# 3 32/ 4 32/24 IEMODE EAA5 31# 8 31/23 31/44 32/ 3 32/23 IEO05 EAE0 32# 7 32/13 IEO10 EAED 32#14 32/21 IEO20 EB00 32/ 5 32#26 32/30 IEOUT EAD9 23/36 23/44 32# 2 IESTK EF6F 7/37 40#16 IETALK 0000 31# 2 31/24 31/45 n IMONTH EF64 39#49 s INTBL EFF0 41/25 s IOBDEF 0080 12/52 s IOBYTE 0003 7/58 12/53 23/ 6 n ISTK EF99 40#21 n IVSAX EFDC 40#51 n IXSAX EFD8 40#49 n IYR EF65 39#50 n IYSAX EFDA 40#50 s K 0400 n KBDLY EFC6 40#31 KEYINP E99F 23/28 23/48 26#20 n KEYLCK EF59 39#32 KIN20 E9AF 26/29 26#32 KIN30 E9B3 26/26 26#36 4 n PIABD EF62 39#45 PIACTL EB7A 35#22 35/27 35/32 35/50 PIS20 EB92 35/29 35#36 PIS30 EB94 35/35 35#38 PISTAT EB7B 23/24 35#24 35/46 PNCH E92F 4/16 21#52 POS10 EB77 35/11 35#13 POSTAT EB68 23/54 35# 6 36/ 5 PP.IN 0002 33#51 34/32 34/53 PP.IRD 0080 33#45 35/28 35/34 PP.MOD EB09 33#53 34/ 2 34/25 34/31 34/54 PP.ORD 0040 33#44 35/10 PP.OUT 0001 33#50 34/ 3 34/24 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 46 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM PP.UND 0000 33#49 33/53 PRINT E907 20#23 20/31 n PSAVE EFE8 41# 9 PTRCIN E960 21/30 23#27 PTRCOU E968 21/37 23#32 PTRCST E958 21/24 23#22 PTRLIS E970 21/47 23#37 PTRLST E988 22/28 18/55 20/ 5 39#16 n ESAVE EFE0 40#58 ESCH EF60 13/24 28/33 39#40 s FALSE 0000 s FCB 005C FILL E855 15/11 16/12 17#11 FILL3 E866 17/17 17#19 FILL4 E884 17#36 17/41 FILL5 E88D 17/38 17#44 FILL6 E890 17/32 17#46 FINAL E8D0 18/ 3 18#28 FLUSH E8B4 9/ 8 16/25 17/44 18#10 U FMTDAT ED80 38/13 n FMTJ E639 4#31 FNL1 E8E0 18#43 18/53 FPYSIB 0010 2#18 2/26 n FSAVE EFE4 41# 5 s FWAVM F000 GCOLD E7C1 13/50 13#53 GODISP E922 21/25 21/31 21#38 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 44 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM GOROM E6EA 8/21 8#40 s H.IEEE 2900 33/23 33/25 33/26 33/28 s H.SCTR 2A00 30/47 s H.SIO 2A00 s H. KIN40 E9CF 27/ 2 27# 5 SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 45 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM KIN50 E9DF 27/ 8 27#16 n LDADR EF57 39#31 LDSEL EF6D 40#13 40/14 n LDTRK EF6E 40#14 LIST E60F 4#15 30/37 n LISTST E62D 4#25 LKEY EF5E 25/21 39#38 n LLIMIT EF6C 40# 9 LOGSEC EF56 11/14 15/48 39#28 n LSAVE EFE6 41# 7 LST E927 4/15 21#45 LSTST E93F 4/25 22#25 s LVMEM 1000 s LWAMEM FFFF 2/13 41/20 n MINS EF67 39#55 n MPCHR EF06 38#39 s MRAM ED80 20/35 38/ 4 MRTRY 0005 2# 9 18/42 s MSEC 000A 5/18 6/ 7 n MSECB EF09 38#43 s MSIZE 003C MVINFO E8FC 15/ 8 15/39 20# 3 NDSK 0002 3#10 5/29 5#29 5/42 5#42 9%23#52 PTRPNC E978 21/54 23#42 PTRRDR E980 22/ 4 23#47 n PUNCH E612 4#16 n R179X EFC2 40#30 n RAGS EFD0 40#43 RDFLAG EF21 17/11 17/55 39#15 RDR E937 4/17 22# 2 READ E7DD 4/23 14#27 READER E615 4#17 30/27 n REGS EFE0 40#57 RNDV EF01 38#35 38/36 ROMCD1 E6BF 7#56 26/40 28/50 30/28 30/38 31/32 31/40 31/49 32/12 32/19 32/28 ROMCDE E6BA 4/31 4/32 4/35 4/36 4/37 4/38 4/39 4/40 4/41 4/42 7#45 ROMJMP E6C4 4/30 8# 3 9/44 13/ 8 18/47 ROMRAM EF08 7/18 7/28 8/17 8/30 12/42 37/14 37/35 38#41 ROMRI E6A6 4/29 7#27 ROMSTK EFC1 40#26 41/12 s ROMVEC 0100 7/57 13/ 6 18/37 n RRDK E627 4#23 n RRI E633 4#29 F52 9/11 10/26 15/10 15/45 15/52 39#25 UNASEC EF55 11/10 15/57 16/ 9 39#27 UNATRK EF53 10/10 15/47 16/ 4 16/ 6 39#26 n VERS 0016 1#28 s VLDL 0034 WAUTO E7DB 13/51 14#21 14/23 WAUTOL 0000 14/21 14#23 WBOOT E773 4/11 13# 2 n WRALL 0000 2#30 WRDIR 0001 2#31 16/24 WRIT2 E816 15/43 15#52 WRIT3 E82F 15/50 16/ 3 16# 9 WRIT4 E834 15/55 16#12 WRITE E7FA 4/24 15#27 WRTYPE EF23 15/41 16/23 39#17 WRUAL 0002 2#32 15/42 XLTBL E9F3 26/54 27#31 27/49 29/ 9 XLTKEY E9F2 25/16 26/23 27/13 27/23 27#29 XLTS E657 5# 4 5/18 5/30 5/43 XLTVL1 E9F0 26/30 27/11 27/21 27#27 XLTVL2 E9F1 26/33 27/19 27#28  5/18 5/30 5/43 XLTVL1 E9F0 26/30 27/11 27/21 27#27 XLTVL2 E~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#RSELDK E61B 4#19 9/41 s RSIZE 0040 RTRC EF04 38#37 38/38 RTRY EF05 18/43 18/51 38#38 n RWDK E62A 4#24 S1DSM 002E 2#26 5/39 5/52 6/ 9 SAVADR E913 18/39 18/44 20#33 SAVSEC EF14 38#55 39/ 2 SAVTRK EF15 38#56 39/ 3 n SBAUD E63C 4#32 SDISK EF17 38#57 39/ 4 n SEC6 EF69 39#57 n SECS EF68 39#56 SECTRN E747 4/26 11# 9 n SEKDEL EF13 38#53 SEKDSK EF1B 9/30 17/35 17/46 39# 8 SEKSEC EF18 17/14 17/22 17/34 17/35 17/52 20/ 7 39# 6 SEKTRK EF19 9/12 9/13 10/ 9 15/46 17/49 39# 7 SELD1 E71E 9/29 9#48 SELDSK E6FD 4/19 9#19 SETDMA E742 4/22 10#52 13/18 n SETRRM E69B 7# 9 SETSEC E73D 4/21 10#37 SETTRK E72A 4/20 10# 8 s SI.RRD 0001 30/16 s SI.S16 0055 ~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r# SORCIM 808x Assembler ver 3.5E 5=/00/;1 1<:03 Page 47 Osborne CP/M 2.2 CBIOS. D:BMRAM .ASM s SI.S64 0056 s SI.TRD 0002 30/ 6 SISTAT EA7C 23/25 30#14 SOSTAT EA73 23/55 30# 4 SPINP EA85 23/30 23/50 30#26 SPOUT EA8B 23/35 23/40 23/45 30#36 n SSAVE EFEA 41#10 STRB 0020 33#46 36/10 s SVER 0001 SW2RAM EBD0 30/48 30/56 35/14 35/39 35/52 36/14 37#26 SW2ROM EBC2 30/45 30/54 35/ 7 35/25 35/48 36/ 7 37# 5 s SYS 0005 s SYSDAT 0010 s SYSL 0006 TBLLEN 000E 26/48 27#49 29/ 4 TBLPTR EA71 29/11 29/19 29/25 29#40 TEM EF00 38#34 38/35 TEMSEC EF20 10/38 20/ 6 39#14 s TIMPTR 0040 13/35 n TKEY EF5C 39#36 s TRUE FFFF 1/27 30/ 8 30/18 35/12 35/37 UNACNT E~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#&~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#'~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#(~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#)~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#*~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#+~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#,~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#: 2~#O <!X!`!hG!pG!xG!G!G:_^#fk{|hs: :^!~( 5 :: Ϳր_!~# ~ ~2>22~2>2>0123456789 :` -:p6y->2pɯ2p ÿWy0ggO! "q>2p*qq(#"q>-͚͚ÿÿy2*:*:G(!:@OKÿ :`OKÿ !Qÿ} :O( : OKÿ :`OKÿ !Nÿ : >*2)>2)>.2)>2)>2)>2)>2)>2 : >*2)>2)>.2)>2)>2)>2)> 2)>2 :)@(9:z :)2z({(2z:)h(y2)>"2)>2)>2>2 >2R*"S:V<!R~45:U< *S#"S2U>U>2Q:":#̴:"2!!:0)2*!P~6(! #ʹ:22*"":22:!>!Q~6:2*":2>_!'"!4>2*2":= 2"ɯ2"~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#~ G >@w!:͆>w :9ē*9#"9 *c3 ~ ʪ(~w##^#V*9ʠ w#Ò ͤO:9= y*9#%N#Fx w# Ò *9"9|~ : # !"96!"9*9"9!9"9*9;'*9!9f'*9zV  6 s#r#Ys'/7*=B?Gæͺͺͺͺͺͺͺͺͺͺ  W0$W@*-?Oy2:Oy{o{_:!91>2>2ʹ2P2R22y2i&))))Ckx!:2C*S}O|ȯ2Ry2 C:U8y2Vi`n&G>2x21>21 B!"2`>22!"!"!c"@!:O(!~OAUTOST 2RU:"ȯ2Py2# >2R*"S:V<!R~45:U< *S#"S2U>U>2Q:":#̴:"2!!:0)2*!P~6(! #ʹ:22*"":22:!>!Q~6:2*":2>_!'"!4>2*2":= 2"ɯ2"-PUSH 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 y 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 = H.IEEE+0 ;Peripheral/Direction register A CCRA = H.IEEE+1 ;Control register A CPDRB = H.IEEE+2 ;Peripheral/Direction register B CCh ;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 iob_default = 80h ;default value for iobyte 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 hhmmss 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 FILOUT 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 RB = 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 MSG 'Assembly for 64k Mode 2 system' MRAM = 0ED80h FWAVM = 0F000h NVDL = 24 INTBL = 0EFF0h ;interrupt vector table 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/22 ;for DELAY routine ; Define Ascii Control Codes. ; Value ;^Control Meaning in Phoenix EOS = 0 ;^@, NUL = End of String TBFCHR = '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 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 ;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 TITLE 'OCCTXT.AST - Osborne Computer Corp System Text.' SVER = 1 ; Legal values for RSIZE are 48 and 64 ; entered from command line RSIZE = 64 ; default = 64k version ;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 Siemems then 2 ; Keyboard debounce KBDTM = 5 ;WAIT 1 MILLISECOND FOR DEBOUNCE ; Assemble 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 ;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-0A00. = 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 ; Direct 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 ;d PIABD must be kept sequential, PIAAD first ;dependency in VC_HOME of BMKEY.asm PIAAD: DS 1 ;Holds last 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 ;sinSelect 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 PUSH 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 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 *********REDEFINED************* MSECB DS 0 ;MULTI SECTOR BYTES FOR R/W **********not used************* 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 ce 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: 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 tempo ' %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 DI OUT 0 LDK A,0 STO A,ROMRAM EI ENDM DISROM MACRO DI OUT 1 LDK A,1 STO A,ROMRAM EI ENDM BRTBIT: = 80h ;set brt/dim memory BRIGHT DIMBIT: = 00h ;set brt/dim memory DIM ENADIM MACRO OUT 2 ENDM DISDIM MACRO OUT 3 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 ENDM ; Endx SYSTEXT maintained ; along with length (1,2,1). SEKDEL: DS 1 ;Set for seek-restore command in ROM ;depends on 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 an/rary area too large ',* .9 ERROR ENDIF IF * > INTBL .9 ERROR MSG 'RAM overflow into Int Vector ', * ENDIF ; Interrupt Jump Vector is between EFFO, EFFF. PAGE ; Endx MRAM  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 tempo 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 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=A:, 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  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: DS 256+128 ; 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 on 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 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 BKPA: DS 2 ;last breakpoint address BKPC: DS 1 ;Contents of bkp ; Interrupt Jump Vector is between EFFO, EFFF. VRTOFF DS 1 ;LAST VERTICAL OFFSET TAKEN FROM COUT PAGE ; Endx MRAM 0, all normal, A=A:, 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 0123456789:;<=>?@ABCDEFGHIJKL