title BIOSMMR -- KAYPRO 10 BIOS ; copyright 1984-5 Michael M Rubenstein ; version 1.1 18 May 1985 ; ; version 1.2 September 15, 1985 John Smith, Pepperell, MA ; ; Incorporated conditional assembly equates as follows: ; ; fload - deletes code to initialize PATH, ENV, NDR via the ; graphics overlay loader from the drive B system tracks. ; zsys - Changes the BDOS patch points, save buffer space and ; fast reset structure to be compatible with ZRDOS+ ; as distributed by Echelon, Inc. Due to the size of the ; buffer space that must be saved, part of it is saved ; in the BIOS area and the rest at bsave1. ; ; These equates are added to BIOS.LIB and the new patch locations are ; added to BIOSLOC.LIB. Also, removed all "private" conditionals. ; .z80 maclib BIOS.LIB ifndef redir redir equ 0 endif ;redir ifndef freset freset equ 0 endif ;freset ifndef fboot fboot equ 0 endif ;fboot ifndef fsub fsub equ 0 endif ;fsub ifndef expht expht equ 0 endif ;expht ifndef escgrph escgrph equ 0 endif ;escgrph ifndef setcur setcur equ 0 endif ;setcur ifndef bigdsk bigdsk equ 0 endif ;bigdsk ifndef mdmsup mdmsup equ 0 endif ;mdmsup ifndef xonsup xonsup equ 0 endif ;xonsup ifndef minibye minibye equ 0 endif ;minibye ifndef fload fload equ 0 endif ;fload ifndef zsys zsys equ 0 endif ;zsys ; zcpr equates (mmr) if zcpr3 maclib Z3BASE.LIB endif ;zcpr3 if zcpr2 expath equ 0f300h ;base address external path z3cl equ 0f380h ;base address of multiple command buffer z3cls equ 248 ;size of buffer z3ndir equ 0f100h ;base address of named directory z3ndirs equ 50 ;number of entries endif ;zcpr2 maclib BIOSLOC.LIB if bigdsk newdsm equ 04edh ;high allocation block number endif ;bigdsk mdmctl equ 06h ;modem rs232 control port mdmdat equ 04h ;modem rs232 data port mdmrst equ 10h ;modem rs232 reset command mdmrcv equ 01h ;bit for receive char ready mdmsnd equ 04h ;bit for send char ready vers equ 22 ;CP/M version number trksec equ 68 ;sectors/track bitport equ 14H ;status/control bit maped port bauda equ 0 ;baud rate port (modem) baudb equ 8 ;baud rate port (printer) baud30 equ 05H ;300 baud rate baud12 equ 07H ;1200 baud rate iobyte equ 3 ;logical to physical map time equ 8000H ;time out rate siokb0 equ 07H ;keyboard channel command/status siosp0 equ 0EH ;serial printer command/status channel siom0 equ 06H ;modem channel command/status reset equ 18H ;channel reset wr1 equ 01H ;interrupt enable and wait/ready modes tid equ 00H ;transmitter interrupt disable rid equ 00H ;recieve interrupt disable wr3 equ 03H ;receiver logic control parameters re equ 01H ;receiver enable autoe equ 20H ;auto enable (use dcd and cts to enable recv ;and xmt rbits8 equ 0c0h ;8 bits/character wr4 equ 04h ;control bits that affect both xmt and recv sbits1 equ 04h ;1 stop bit cr16 equ 40h ;x16 wr5 equ 05h ;control bits that affect xmt rts equ 02h ;RTS output te equ 08h ;transmit enable tbits8 equ 60h ;8 bits/character dtr equ 80h ;DTR output pfdat equ 24 ;cent out data port (8 bit latch) pstrob equ 8 ; bit in bit port numstr macro n db '&n' endm tpastr macro numstr %tpasze endm if zcpr3 if zcpr2 .printx | *** Cannot specify both ZCPR2 and ZCPR3 | db 256 endif ;zcpr2 endif ;zcpr3 if minibye if not zcpr3 .printx | *** Cannot specify MINIBYE without ZCPR3 | db 256 endif ;not zcpr3 endif ;minibye aseg org 0902h ;length of system (for cold boot) dw ccp dw bios db (endbios-ccp)/128+1 org 1f80h ;location in putsys .phase bios jp boot ;arrive here from cold start jp wboot ;arrive here for warm start jp const ;console status return in A FF=ready, 00=not jp conin ;console char in jp conout ;console char out jp list ;listing char out jp punch ;punch char out jp reader ;reader char in hom: jp home ;move to track 0 on selected disk drive seld: jp seldsk ;select disk drive sett: jp settrk ;set track # sets: jp setsec ;set sector # setd: jp setdma ;set DMA address rd: jp read ;read selected sector jp write ;write selected sector jp listst ;list status (Ready to print a char) sect: jp sectran ;sector translate iob: db 81h ;initial value for i/o byte wrtsaf: db 0 ;write safe flag 0=false vtab: db 05h,18h,13h,04h ;vector pad xlate table ^k ^j ^h ^l db '0', '1', '2', '3' ; u d l r db '4', '5', '6', '7' ; 09 0a 08 0b db '8', '9',0,0 ; '8', '9', '-', ',' db 0DH, 0ffh ; cr '.' baudrt: db baud12 ;baud rate (modem) db baud12 ;baud rate (printer) db (sndtab-vtab) sioint: ;i/o device initialization table ;first byte is number of bytes to send ;second byte is port to send out to ;third byte is data ;init sio channel for serial printer db 09H db siosp0 db reset ;reset sio channel db wr4 db sbits1 or cr16 ;one stop bit 16x clock db wr3 db re or rbits8 or autoe ;recv enable, 8bits/char (v1.1 chg) db wr5 db te or tbits8 or dtr or rts ;xmt enable, 8bits/char,assert dtr & rts db wr1 db tid or rid ;xmt & recv interrupts disabled ;init sio channel for modem db 09H db siom0 db reset ;reset sio channel db wr4 db sbits1 or cr16 ;one stop bit 16x clock db wr3 db re or rbits8 ;recv enable, 8bits/char db wr5 db te or tbits8 or dtr or rts ;xmt enable, 8bits/char,assert dtr & rts db wr1 db tid or rid ;xmt & recv interrupts disabled siotbnd:db 0 ;end of table sndtab: db 0,0,0,0 ;up arrow key db 0,0,0,0 ;down arrow key db 0,0,0,0 ;left arrow key db 0,0,0,0 ;right arrow key db 0,0,0,0 ;0 key on numeric pad db 0,0,0,0 ;1 key on numeric pad db 0,0,0,0 ;2 key on numeric pad db 0,0,0,0 ;3 key on numeric pad db 0,0,0,0 ;4 key on numeric pad db 0,0,0,0 ;5 key on numeric pad db 0,0,0,0 ;6 key on numeric pad db 0,0,0,0 ;7 key on numeric pad db 0,0,0,0 ;8 key on numeric pad db 0,0,0,0 ;9 key on numeric pad db 'dir',0dh ;- key on numeric pad db 'flr',0dh ;, key on numeric pad db 0,0,0,0 ; " " db 0,0,0,0 ;. key on numeric pad featur defl (8000h and redir)+(4000h and freset)+(2000h and fboot) featur defl featur+(1000h and fsub)+(0800h and expht)+(0400h and escgrph) featur defl featur+(0200h and setcur)+(0100h and bigdsk) featur defl featur+(0080h and mdmsup)+(0040h and xonsup) featur defl featur+(0020h and minibye) db 'MMR',0 dw featur+1 ; Cold boot entry point, set up system pointers and pass control to the CCP boot: call diskint sub a ;clear system disk number ld (4),a if setcur ;set up for setable cursor ld hl,0f60h ;slow blink block ld (cur1),hl endif ;setcur ld hl,flags ;clear flags ld de,flags+1 ld bc,lflags-1 ld (hl),a ldir if minibye ld hl,mbflag ld (hl),a ;set minibye not active inc hl ld (hl),a ;set noctl not active endif ;minibye ld a,3+1 ;set max disk ld (maxdisk),a ld a,(iob) ;init value for i/o byte ld (iobyte),a ld hl,sioint ;initialize i/o devices iolp: ld b,(hl) ;number of bytes to send inc hl ld c,(hl) ;port to send inc hl ;address of byte being sent otir ld a,(hl) ;get this byte or a ;clean test jr nz,iolp ;if more tables then do ld hl,baudrt ld a,(hl) ;set baud rates out (bauda),a inc hl ld a,(hl) out (baudb),a if tight prtid: call print db 1ah tpastr db 'K TPA',0dh,0ah,0 else prtid: call print db 1AH if zsys db 'KAYPRO 10 Z-System ' else db 'KAYPRO 10 CP/M ' db vers/10+'0', '.', vers mod 10+'0',' MMR ' endif ;zsys tpastr db 'K TPA' db 0dh,0ah,0 endif ; tight ; zcpr initialization ld hl,cmdset ;initialization for multiple command buffer ld de,z3cl ld bc,lcmdset ldir if not fload if zcpr3 push hl ld hl,z3ndir ;Named directory buffer call zero128 pop hl else ld de,z3ndir ld bc,lndvals ldir endif ;zcpr3 ld de,expath ld bc,lpath ldir endif ;not fload if zcpr3 if rcp ne 0 ld hl,rcp ;clear RCP buffer call zero128 endif ;rcp if fcp ne 0 ld hl,fcp ;clear FCP buffer call zero128 endif ;fcp if not fload if z3env ne 0 ld hl,z3env ;clear environment ld b,128+16 call zerom endif ;z3env endif ;not fload if shstk ne 0 sub a ;clear shell stack ld (shstk),a endif if z3msg ne 0 ld hl,z3msg ;clear message buffer ld b,80 call zerom endif ;z3msg endif ;zcpr3 if bigdsk jp wboot ;cheap way to force setting of DSM else if fboot ;must set jumps here in case they some filter call setpg1 ;will change them on disk operations endif ;fboot endif ;bigdsk goccp: if redir or freset or fsub ld hl,(bdos+1) ;must repatch the bdos ld (obdos+1),hl ld hl,nbdos ld (bdos+1),hl if redir ld a,(rflag) ;are we redirecting? or a jr z,goccp1 ld hl,selptc ;check if bios vector has been patched yet ld a,(hl) ld (hl),0ffh ;mark patched or a jr nz,goccp1 ld hl,seld ld de,oseld ld bc,lseld ldir ld hl,nseld ld de,seld ld bc,lseld ldir endif ;redir endif ;redir or freset or fsub goccp1: ld hl,time ;reset disk time out ld (count),hl if not fboot ld a,0C3H ;set up CP/M jumps to bdos and wboot ld hl,bios+3 ;wboot entry point ld (0),a ld (1),hl ld hl,bdos ;entry point to bdos ld (5),a ld (6),hl endif ;not fboot ld a,(4) ;last logical disk unit used ld c,a and 0FH ;valid disk? inc a ;maxdisk has max + 1 ld hl,maxdisk cp (hl) jr c,goccp2 ld a,c ;no, so go to drive 0 and 0F0H ld c,a ;pass to ccp to select goccp2: jp ccp ;pass control to ccp if fboot setpg1: ld a,0C3H ;set up CP/M jumps to bdos and wboot ld hl,bios+3 ;wboot entry point ld (0),a ld (1),hl ld hl,bdos ;entry point to bdos ld (5),a ld (6),hl ret endif ;fboot if zcpr3 zero128: ld b,128 zerom: sub a zerom1: ld (hl),a inc hl djnz zerom1 ret endif ;zcpr3 ; zcpr buffer initial values (mmr) cmdset: dw z3cl+4 ;point to first char db z3cls ;size of buffer db 0 if zcpr3 and not fload db 'LDR SYS' tpastr db '.ENV;' endif ;zcpr3 and not fload db 'START' tpastr db 0 lcmdset equ $-cmdset if not zcpr3 ndvals: db z3ndirs ;number of entries db 0 ;none yet db 0 ;dummy for no disk db 0 ;dummy for no user db 0 ;dummy for no name lndvals equ $-ndvals endif ;not zcpr3 if not fload path: db 'A'-'@' ;Drive A db 15 ;User 15 db 'A'-'@' ;Drive A db '$' ;Curent user db 0,0,0,0 db 0 lpath equ $-path ;length of path data endif ;not fload wberr: if fboot sub a ;on error in fast boot, abandon it ld (fbdriv),a endif ;fboot ; Warm boot entry point, re-load the CCP and BDOS wboot: ld sp,0100h ;reset stack if fboot ;must set jumps here in case some filter call setpg1 ;will change them on disk operations endif ;fboot if redir ld a,(rflag) ;do we have a redirection? or a call nz,rclose ;if so, must reset it. endif ;redir if freset if zsys ld a,0ffh ;prepare warm boot flag ld (wbflag),a ; for bdos fcn 13 patch endif ;zsys ld a,(frflag) ;enabled? ld hl,frdrty ;need real reset? or (hl) jr z,wboot1 call diskint ;reset the disk system sub a ;clear all drives jr wboot2 wboot1: ld a,(dlog) and 03h ;only keep a & b wboot2: push af endif ;freset if bigdsk ;increase disk capacity? ld c,0 ;select disk A ld e,a call seldsk ;get DPH ld de,000ah ;point to DPB add hl,de ld e,(hl) ;get DPH inc hl ld d,(hl) ld hl,0005h ;point to dsm add hl,de ld (hl),low newdsm endif ;bigdsk if fboot ld a,(fbdriv) ld c,a ;select fast boot drive ld e,0 call seld ld a,h ;is it a valid drive? or l jr z,wberr ;error if not call hom ld hl,stdtrs ld a,(fbdriv) ;fast boot? or a jr z,wb1 ld hl,fbtrs1 ;point to track/sector descriptor wb1: ld (fbtrsp),hl ;save pointer ld b,nsects ld hl,ccp ;first memory location to load ld (dmaadr),hl wb2: ld hl,(fbtrsp) ;get pointer ld e,(hl) ;get track inc hl ld d,(hl) ld (fbt),de ;save track inc hl ld e,(hl) ;get sector inc hl ld d,(hl) ld (fbs),de ;save sector inc hl ld (fbtrsp),hl ;save pointer ld a,(fbdriv) or a jr z,wb3 ld a,(fbspg) ;get sectors/group ld c,a jr wb4 wb3: ld c,68 wb4: push bc ;save counters wb5: ld bc,(fbt) call sett ;set track wb6: ld hl,(fbs) ld de,(fbtran) ld b,h ld c,l ld a,(fbdriv) or a call nz,sect ;translate sector ld b,h ld c,l call sets ;set sector ld bc,(dmaadr) call setd call rd pop bc or a jp nz,wberr ;oops, error on warm boot, don't fast boot dec b ;count sector read if freset jp z,ptchbd ;done loading? else jp z,goccp endif ;freset ld hl,(dmaadr) ;advance load address ld de,128 add hl,de ld (dmaadr),hl dec c ;done with this group? jr z,wb2 ld hl,(fbs) inc hl ;advance sector ld (fbs),hl push bc ld a,(fbdriv) ;from a? or a jr z,wb6 ld de,(fbspt) ;done with track? or a sbc hl,de jr c,wb6 ;still more sectors on track ld hl,0 ;go to next track ld (fbs),hl ld hl,(fbt) inc hl ld (fbt),hl jr wb5 fbt: dw 0 ;track fbs: dw 0 ;sector fbtrsp: dw 0 ;point to start of group track/sector stdtrs: dw 0,1 else ;fboot ld c,0 call seldsk call home ld bc,0 ;set track call settrk ld bc,ccp ;first memory location to load ld (dmaadr),bc call setdma ld bc,nsects*256+1 wb1: push bc ;save sector count and current sector call setsec ;select sector call read pop bc or a jr nz,wboot ;oops, error on warm boot push bc ld hl,(dmaadr) ;update dma address for next sector ld de,128 ;new dma address add hl,de ld b,h ld c,l ld (dmaadr),hl call setdma pop bc dec b if freset jp z,ptchbd ;done loading? else jp z,goccp endif ;freset inc c ;bump sector count jr wb1 endif ;fboot if freset ptchbd: pop af ld (dlog),a ;restore logged status of a & b call bdp1 ;clear if dirty ld a,0cdh ;call if zsys ld (breset+10),a ld hl,bdp1 ld (breset+11),hl sub a ld (wbflag),a else ld (breset+6),a ld hl,bdp1 ld (breset+7),hl ld (resdrv),a ld hl,bdp2 ld (resdrv+1),hl endif ;zsys jp goccp ; hot patch bdos to prevent reset of drives a and b bdp1: ld a,(frflag) ;enabled? ld hl,frdrty ;dirty? or (hl) ld (hl),0 add a,0ffh ;convert any nz to 0ffh sbc a,a ;if dirty then 0ffh else 0 cpl ;if dirty then 0 else 0ffh and 03h ;if dirty then 0 else 3 ld hl,dlog ;unlog all drives but a & b and (hl) if zsys push af ;save drive log ld a,(wbflag) ;get warm boot flag or a ;zero flag reset if warm boot ld (hl),0 ;0 in low byte of dlog pop af ;new dlog value jr z,bdp11 ;skip low byte dlog if not warm boot endif ;zsys ld (hl),a bdp11: inc hl ld (hl),0 ret if not zsys bdp2: ld hl,(bfcb) ;don't reset a or b ld a,l and 0fch ld l,a ld (bfcb),hl ret endif ;not zsys endif ;freset ; logical devices are con: rdr: pun: and lst: ; physical devices are: ; con: ; tty: printer rs232 ; crt: video and keyboard ; bat: rdr:/pun: ; uc1: modem rs232 ; rdr: ; tty: printer rs232 ; rdr: keyboard ; ur1: printer rs232 (same as tty:) ; ur2: modem rs232 ; pun: ; tty: printer rs232 ; ptp: video ; up1: centronics ; up2: modem rs232 ; lst: ; tty: printer rs232 ; crt: video ; lpt: centronics ; ul1: modem rs232 ; ; Device tables. Addresses less than 0100h are in ROM. cstbl: dw 0033h ;console status dw kbdcs dw batcs if mdmsup dw mdmist else dw 0033h endif ;mdmsup citbl: dw 0036h ;console input dw kbdci dw reader if mdmsup dw mdmin else dw 0036h endif ;mdmsup cotbl: dw 0039h ;console output if expht ;expand tabs dw crtout else dw 0045h endif ;expht dw punch if mdmsup dw mdmout else dw 0039h endif ;mdmsup potbl: dw 0039h ;list or punch output dw 0045h dw lstdev if mdmsup dw mdmout else dw 0039h endif ;mdmsup ritbl: dw 0036h ;reader input dw kbdci dw 0 ;impossible if mdmsup dw mdmin else dw 0036h endif ;mdmsup lstbl: dw 0042h ;list status dw chrrdy dw 003ch if mdmsup dw mdmost else dw 0042h endif ;mdmsup if xonsup x1tbl: dw 0033h ;status for xon/xoff dw nochar dw nochar if mdmsup dw mdmist else dw 0033h endif ;mdmsup x2tbl: dw 0036h ;get char for xon/xoff dw 0 ;impossible dw 0 ;impossible if mdmsup dw mdmin else dw 0036h endif ;mdmsup endif ;xonsup ; Corresponding to the 2 bit fields in the iobyte, the ioflag is divided ; into two bit fields. For the corresponding device, the low order bit ; indicates that bit 7 should be cleared. The high order bit indicates ; xon/xoff (pun: and lst: only) const: if minibye call mbchk ;check carrier jr z,const0 call const0 ;check char from console or a ret nz jp mdmist endif ;minibye const0: ld hl,(count) ;time out motors? dec hl ld (count),hl ld a,h or l ld l,27h ;turn off disks if time up call z,callrom ld a,(iobyte) ;get i/o byte const1: ld hl,cstbl ; jump to routine from table switch: and 03H ;strip to device bits add a,a ;* 2 ld e,a ld d,0 add hl,de ld e,(hl) ;get address inc hl ld d,(hl) ex de,hl ld a,h ;in rom? or a jp z,callrom jphl: jp (hl) ;no, just jump to routine if expht ;expand tabs? crtout: ld a,c ld l,45h cp 09h ;is it a tab? jp nz,callrom ;just do it if not pop hl ;cut down on stack use ld (crtot2+1),hl crtot1: ld c,' ' ld l,45h call callrom ld a,(ccol) and 07h ;at tab col? jr nz,crtot1 crtot2: jp 0 ;return (set at run time) endif ;expht batcs: ld a,(iobyte) ;console status for bat: rra ;move reader to low bits rra and 3 cp 2 ;convert ur1: to tty: jr nz,const1 sub a jr const1 kbdcs: ld a,(cnt) ;load function counter or a ;clean test ld l,2ah ;get from keyboard jp z,callrom chrrdy: or 0ffh ;clean nz ret conin: if minibye call mbchk ;check carrier jr z,conin0 ld hl,mbtcon ld de,mbtwk ld bc,lmbt ldir ld a,(mbflag) ld (mbtwk+lmbt),a mbcnin: call mbchk ;check carrier call const0 ;check char from terminal or a jr nz,conin1 call mdmist ;check char from modem jr z,mbcni1 in a,(mdmdat) ;get character from modem and 7fh ;always clear bit 7 cp 03h ;is it ^C? ret nz ld c,a ;save the char ld a,(noctlc) ;allow ^C? or a ld a,0 ;change to 0 if not allowing ret nz ld a,c ret mbcni1: ld hl,mbtwk ;check for time out ld b,lmbt+1 mbclp: dec (hl) jr nz,mbcnin inc hl djnz mbclp jp mbexit mbtcon: db 0,164,7 lmbt equ $-mbtcon mbtwk: db 0,0,0,0 endif ;minibye conin0: call const ;key press? or a jr z,conin0 conin1: ld a,(iobyte) ;go get character ld hl,citbl call switch conin2: ld b,a ;save char ld a,(ioflag) ;should i clear bit 7? rra ld a,b ret c and 7fh ;clear bit 7 ret kbdci: pop hl ;get rid of return ld a,(cnt) ;get counter value or a ;clean test jr nz,frjp ;do function if not 0 ld l,02dh ;get char call callrom or a ret p ;msb not set and 01fh ;form table index to vtab ld hl,vtab ld c,a ld b,0 add hl,bc ld a,(hl) ;pick up xlated character or a ;clean test ret nz ;if valid character value return sectab: ld hl,sndtab ;set to new table value add hl,bc ;set hl to character position add hl,bc ;size of entry = 4 add hl,bc add hl,bc ld (pntr),hl ;store position in pointer ld a,4 ;set to this value ld (cnt),a ;initialize counter to 4 ;continue process of function frjp: ld hl,cnt ;decrement count dec (hl) ex de,hl ;save pointer to count in case we need it ld hl,(pntr) ;get pointer value ld a,(hl) ;load character into c reg inc hl ;increment pointer ld (pntr),hl ;save this value off ret z ;return if zero ld c,a ;save char ld a,(hl) ;get next byte value or a ;compare to 0 ld a,c ;move value in c to a ret nz ;return if not zero sub a ;clear accumulator ld (de),a ;clear counter value ld a,c ;move value in c to a ret conout: ld (savebc),bc ;console output if minibye call mbchk ;check carrier call nz,mdmout endif ;minibye if redir ld hl,rflag ;redirecting? ld a,(hl) or a jp z,conot5 dec hl ld a,(hl) or a ;ignore redirection? jp nz,conot5 dec hl ld a,(hl) ;get buffer count inc (hl) ;advance buffer count ld e,a ld d,0 ld hl,rbuff add hl,de ld a,c cp 1ah ;don't put an eof in file jr nz,conot1 sub a ;change it to NUL conot1: ld (hl),a ;store char ld a,e inc e ;advance counter to match memory jp nz,conot5 ;buffer full? call rsave ;save bdos & stack ld c,32 ;set user ld a,(ruser) ld e,a call bdos call ropen ;open the file if necessary ld de,rbuff ld b,2 conot2: push bc ;save count push de ;save buffer address ld c,26 ;setdma call bdos ld c,34 ;random write ld de,rfcb call bdos or a ;error? jr nz,conot3 ld hl,(rfcb+33) ;increment record inc hl ld (rfcb+33),hl pop de pop bc ld hl,128 ;advance buffer add hl,de ex de,hl djnz conot2 jr conot4 conot3: call rerr ;report error conot4: call rrest ;restore environment endif conot5: if escgrph or setcur ;allow graphics in escape sequences? ld a,(iobyte) and 03h ;isolate console field cp 01h ;crt? jr nz,cono5b ;no ld hl,leadflg ld a,(hl) ;in escape sequence? endif ;escgrph or setcur if setcur ;is cursor setable? cp 2 jr nz,cono5a ld a,(esccmd) ;attribute on? cp 'B' jr nz,conot6 ld a,c ;cursor on? and 7fh sub '4' jr nz,conot6 ld (hl),0 ;clear lead in flag ld hl,cur1 ld c,1dh ;port address for video controller ld a,10 out (1ch),a outi ld a,11 out (1ch),a outi ret endif ;setcur cono5a: if escgrph or a jr nz,conot6 endif ;escgrph cono5b: ld a,(ioflag) ;clear bit 7? rra jr c,conot6 ld a,c and 7fh ;clear bit ld c,a conot6: ld a,(iobyte) ld hl,cotbl call switch ld bc,(savebc) ;get character again ld a,(prflag) ;print also? or a ret z list: if minibye call mbchk ;check carrier ret nz ;no printer under minibye endif ld a,(ioflag) ;get flags ld b,a ld a,(iobyte) rlca ;get it in low bits rlca jp plout if redir rsave: ex (sp),hl ;get return ld (rsret+1),hl ;save it pop hl ld (rstack),sp ;save environment of bdos ld sp,rstack ;local stack push hl ;save regs push de push bc ;save char ld hl,nredir ;don't redirect bdos error messages now inc (hl) if zsys ld hl,bdos+5 ;save bdos variables ld de,0dd6ch ld bc,93h ldir ld hl,bdos+0dc9h ld de,bsave1 ld bc,30h ldir else ;zsys ld hl,bdos+bsoff1 ;save bdos variables ld de,bsave1 ld bc,lbsav1 ldir ld hl,bdos+bsoff2 ld de,bsave2 ld bc,lbsav2 ldir endif ;zsys ld hl,(hlddma) ;save disk settings push hl ld hl,(hldsec) push hl ld hl,(hldtrk) push hl ld hl,(hlddsk) push hl rsret: jp 0 ;address inserted at run time rrest: pop hl ;restore bdos environment ld (rrret+1),hl ;save return address pop bc ;restore disk settings ld e,1 ;not first time call seld pop bc call sett pop bc call sets pop bc call setd if zsys ld hl,0dd6ch ;restore bdos variables ld de,bdos+5 ld bc,93h ldir ld hl,bsave1 ld de,bdos+0dc9h ld bc,30h ldir else ;zsys ld hl,bsave1 ;restore bdos variables ld de,bdos+bsoff1 ld bc,lbsav1 ldir ld hl,bsave2 ld de,bdos+bsoff2 ld bc,lbsav2 ldir endif ;zsys ld hl,nredir ;clear ignore redirection (unless error) dec (hl) pop bc ;restore regs pop de pop hl ld sp,(rstack) ;restore stack rrret: jp 0 ;address computed at run time rerr: call print ;error on write db 0dh,0ah,07h,'ERROR: Cannot write CON: redir file' db 0dh,0ah,0 pop de ;restore stack pop bc ;get char ld hl,nredir ;ignore from now on inc (hl) ret ropen: ld a,(ropflg) ;is it open or a ret nz ;done if so ld c,15 ;open int ld de,rfcb call bdos inc a ;error? ld (ropflg),a call z,rerr ;report if error ret rclose: ld hl,ropflg ;is it open? ld a,(hl) ld (hl),0 or a ret z ;done if not call rsave ;reset redirection file ld c,32 ;set user ld a,(ruser) ld e,a call bdos ld c,16 ;close it ld de,rfcb call bdos inc a ;error? call z,rerr ;error in reset call rrest ;restore environment ret selptc: db 0 ;not patched yet hlddsk: defs 2 hldtrk: defs 2 hldsec: defs 2 hlddma: defs 2 endif ;redir nbdos: if redir ld a,(rflag) ;are we redirecting? or a jr z,nbdos2 ld a,c ;must close if resetting any drives cp 13 ;reset all jr z,nbdos1 cp 37 ;reset selected nbdos1: call z,rclose endif ;redir nbdos2: if freset ld a,c cp 13 ;reset all? jr nz,nbdos3 ;jump, if not fcn 13 pop hl ;get return ld (nb2ret+1),hl ;don't use too much of stack call obdos1 or 0ffh ;always return $$$.sub hint nb2ret: jp 0 ;computed at run time endif nbdos3: if fsub ld a,c ;check the function cp maxcfn+1 jr nc,obdos1 ld a,(fsdriv) ;fast submit drive given? or a jr z,obdos1 ld b,0 ;is this one we have to check? ld hl,ckbfil add hl,bc ld a,(hl) or a jr z,obdos1 push de ;save the fcb inc de ;point to the name ld hl,fsnam ld b,11 ;length filename + file type nbdos4: ld a,(de) ;get char and 7fh ;clear attribute cp (hl) jr nz,nbdos5 inc de ;advance inc hl djnz nbdos4 pop de ;it's $$$.sub ld a,(fsdriv) ;set the drive ld (de),a push de nbdos5: pop de endif ;fsub obdos1: ld (30h),a ld (32h),bc ld (34h),de ld (36h),hl ld (38h),sp obdos: jp 0 ;address set at run time if fsub fsnam: db '$$$ SUB' ;sub file name ; check vector for bdos functions ; if nz, function uses an fcb ckbfil: db 0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0,1,1,1,0,1 db 1,1,1,1,0,0,0,0,0,0 db 1,0,0,1,1,1,1,0,0,0 db 1 maxcfn equ $-ckbfil-1 endif ;fsub reader: ld a,(iobyte) ld hl,ritbl rra ;get reader field in low bits rra and 3 ;convert ur1: to tty: cp 2 jr nz,readr1 sub a readr1: call switch ld b,a ld a,(ioflag) and 04h ;clear bit 7? ld a,b ret nz and 7fh ;clear it ret punch: ld a,(ioflag) ;get io flag rla ;move to hi bits rla ld b,a ld a,(iobyte) ;get iobyte rra ;move to low bits rra rra rra plout: ;output for both list and punch ld (savebc),bc ;save bc regs bit 6,b ;clear bit 7? jr nz,plout1 res 7,c plout1: if xonsup bit 7,b ;xon/xoff? jr z,plout9 ld (savebc1),bc ld (savea1),a ld hl,x1tbl ;check if char ready call switch or a jr z,plout8 ;no character, continue ld a,(savea1) ld hl,x2tbl ;get the char call switch and 7fh ;turn off bit 7 cp 'S' and 1fh ;is it xoff (control S)? jr nz,plout8 plout2: ld a,(savea1) ;wait for xon (control Q) ld hl,x1tbl call switch or a jr z,plout2 ld a,(savea1) ld hl,x2tbl call switch and 7fh ;turn off bit 7 cp 'Q' and 1fh jr nz,plout2 plout8: ld bc,(savebc1) ld a,(savea1) endif ;xonsup plout9: ld hl,potbl call switch ld bc,(savebc) ;restore bc reg ret listst: ld a,(iobyte) rlca ;get it in low bits rlca ld hl,lstbl jp switch lstdev: call listst ;is printer busy jr nz,lstdev ;if not return ld a,c ;move character into a out (pfdat),a ;output character to printer in a,(bitport) ;strb. printer and 0ffh-pstrob out (bitport),a or pstrob out (bitport),a ret nochar: sub a ;no character ready ret if minibye mbchk: ld a,(mbflag) ;is minibye active? or a ret z ;just return if not ld a,mdmrst out (mdmctl),a in a,(mdmctl) and 08 ;check CD ret nz mbexit: ld (mbflag),a ;set minibye not active ld hl,mbcmd ;set multiple to MBYE command ld de,z3cl ld bc,lmbcmd ldir jp 0 ;warm boot mbcmd: dw z3cl+4 ;point to first char db z3cls ;size of buffer db 0 db "MBYE",0 lmbcmd equ $-mbcmd endif ;minibye if mdmsup or minibye mdmist: ld a,mdmrst ;return nz if modem has char out (mdmctl),a in a,(mdmctl) rra ;set nonzero if bit 0 is 1 sbc a,a ret mdmost: ld a,mdmrst ;return nz if mdm ready to send out (mdmctl),a in a,(mdmctl) rra ;set nonzero if bit 3 is 1 rra rra sbc a,a ret if mdmsup mdmin: call mdmist ;get char from modem jr z,mdmin in a,(mdmdat) ret endif ;mdmsup mdmout: call mdmost ;put char in c to modem rs232 jr z,mdmout ld a,c out (mdmdat),a ret endif ;mdmsup or minibye diskint:ld l,03H ;re-set disk software sub-system jr callrom home: ld l,0CH ;home disk drive rom routine jr callrom if redir ; patch routines to keep track of the disk settings seldn: ld (hlddsk),bc jr oseld settn: ld (hldtrk),bc jr osett setsn: ld (hldsec),bc jr osets setdn: ld (hlddma),bc ;save dma address jr osetd oseld: jp 0 ;patched at run time osett: jp 0 osets: jp 0 osetd: jp 0 nseld: jp seldn nsett: jp settn nsets: jp setsn nsetd: jp setdn lseld equ $-nseld endif ;redir seldsk: ld hl,0 ;error if drive > 2 ; ld a,c ;deleted per rev 1.1 to allow ; cp 3 ; more disk drives - N/A for ; ret nc ; this Kaypro 10. ld a,(maxdisk) ;check if we're allowing this dec a dec a cp c ret c ld l,0FH ;select disk drive jr callrom settrk: ld l,12H ;seek track jr callrom setsec: ld l,15H ;set sector number jr callrom setdma: ld l,18H ;set dma address jr callrom read: ld hl,time ;reset time out ld (count),hl ld l,1BH ;read a logical sector callrom:in a,(bitport) ;turn rom on or 80h out (bitport),a ld (savsp),sp ;save current stack (may be under rom) ld sp,stack ;set a local stack ld h,0 call jphl biosret:push af ;save a in a,(bitport) ;off the rom and 7fh out (bitport),a pop af ;restore a ld sp,(savsp) ;restore stack ret ;done with rom routine write: if freset pop hl ;who called? push hl ld de,bdos or 0ffh ;clear carry, set a to nz sbc hl,de ;set carry if not bdos jr nc,write0 ld (frdrty),a ;set dirty if nonbdos write endif ;freset write0: ld hl,time ;reset time out ld (count),hl ld l,1eh ;write a logical sector if redir ld a,(ropflg) ;write safe if redirection open or a jr nz,write1 endif ;redir ld a,(wrtsaf) ;write safe flag or a ;true or false jr z,callrom ;normal operation write1: ld c,1 ;directory write code (forces write op) jr callrom sectran:ld l,21H ;xlate logical to physical sector jr callrom print: ex (sp),hl ;pop return address, points to text to print ld a,(hl) ;get a byte of text, stop on zero byte inc hl ex (sp),hl ;save new return address or a ;is it a zero byte? ret z ld c,a ;no, so print it call conout jr print pntr: dw 0 ;pointer for function key routine cnt: db 0 ;character counter for function routine count: dw 0 ;disk time out counter dmaadr: dw 0 ;dma address for warm boot savsp: dw 0 ;current stack pointer during rom call savebc: db 0 savea1: db 0 savebc1: dw 0 wbflag: db 0 db 'END' endbios equ $-1 stack equ 0f380h ;a local stack toobig macro n .printx | *** BIOS too big by n bytes *** | db 256 endm if endbios ge maxbios bigsz equ endbios-maxbios+1 toobig %bigsz endif ;endbios ge maxbios info macro n,sccp,sbdos,sbios,ebios .printx |Kaypro 10 Bios (MMR) n K TPA | .printx |Start CCP = sccp | .printx |Start BDOS = sbdos | .printx |Start BIOS = sbios | .printx |End BIOS = ebios | endm info %tpasze,%ccp,%bdos,%bios,%endbios if redir .printx |Redirection available | endif ;redir if freset .printx |Fast reset available | endif ;freset if fboot .printx |Fast boot available | endif ;fboot if fsub .printx |Fast submit available | endif ;fsub if expht .printx |Tabs expanded in BIOS | endif ;expht if escgrph .printx |Escape graphics always allowed | endif ;escgrph if setcur .printx |Settable cursor | endif ;setcur if bigdsk .printx |Increased hard disk capacity | endif ;bigdsk if mdmsup .printx |Modem RS232 supported | endif ;mdmsup if xonsup .printx |XON/XOFF supported | endif ;xonsup if minibye .printx |Minibye supported | endif ;minibye .dephase end