title 'C128 Format Program 08 June 1987' ; modified 08June87 by V.Ertwine & F.Bowen: add 1581 support ; modified 07May86 by V.Ertwine: add more MFM formats ; original 15May85 by V.Ertwine: original release maclib z80 maclib cxequ maclib x6502 format$1581 equ true $*MACRO boot$code$02 equ 00B00h boot$code$80 equ 0E000h ; ; RAM loader equates ; rownum macro row,col db row+80h,col endm sys$name equ 000EDh ; cmp$hl$de equ 000FAh ; read$sector equ 0044Fh ; ext$error equ 00480h ; tell$user equ 004FFh ; table$error equ 0051Bh ; prt$msg$both equ 00526h ; prt$HL$both equ 00534h ; install$ASCII equ 005BDh ; wait equ 00945h ; ;BIOS$65$code equ 00D22h ; ;BIOS$size equ 001C3h ; ;F$rd$count equ 031BDh ; swap$code equ 00EE5h ; swap$size equ 0001Fh ; MMU$init$data equ 00FAAh ; page ;""""""""""""" ;E Q U A T E S ;""""""""""""" cret: equ 01 ; matrix position of return key disk$ready$key: equ 11 ; matrix position of $ ctrlc: equ 20 ; matrix position of c key yes$key: equ 25 ; yes - matrix position of 'y' key no$key: equ 39 ; 'no' - matrix position of n key cursor$up$key: equ 53h ; matrix position of up arrow cursor$dn$key: equ 54h ; matrix position of down arrow top$line: equ 0 ; screen top row for signon message use$line: equ 2 ; screen row for "using source" message keynam$line: equ 4 ; screen row for showing keyname lots$line: equ 6 ; screen row for showing big messages prompt$line: equ 10 ; screen row for showing menus spec$line: equ 23 ; status line row for special messages crlf: equ 0ffh ; code to do cr,lf do$6502$fun: equ 4 scrsz40: equ 20h ; flag value that this is a 40 column screen scrsz80: equ 40h ; flag value that this is an 80 column screen both: equ scrsz40+scrsz80 ; both of the above user$offset: equ 3*(30-1) page ;""""""""""""""""""" ;CP/M function calls ;""""""""""""""""""" bdos: equ 05 ;bdos call entry point conin: equ 01 ;char returned in a conout: equ 02 ;char sent in e constat: equ 11 ;console status cur$dsk: equ 25 ;get current disk to A getscb: equ 49 ;get system control block ;""""""""""""""""""""""""" ; 1581 Drive equates ;""""""""""""""""""""""""" ; constants buf$alc equ 081h ; allocate buffer 0 (no buf 7) ; memory location jobs equ 002h ; list of jobs to be done hdrs equ 00Bh ; header info (track and sector) buf$use equ 06Dh ; bit X set allocates buffer X next$job equ 083h ; pointer to next job to be done hdrjob equ 099h vtrans$ts equ 1B8h ; sector x-lat vector drv$buf equ 300h ; buffer 0 start adr ;boot$ret equ 0d35Ah ; will change with next ROM boot$ret equ 0FF5Ah ; return from drive boot code page ; pointer equ 20h ; DMA pointer used by 8502 cmdchn equ 15 ; use comand channel #15 ; ; KERNAL EQUATES ; serial equ 00A1Ch D2PRA equ 0DD00h D1SDR equ 0DC0Ch D1ICR equ 0DC0Dh clk$bit equ 10h K$set$bnk equ 0FF68h ; K$setlfs equ 0FFBAh ; setup a logical file K$setnam equ 0FFBDh ; set up file name for OPEN K$open equ 0FFC0h ; open a logical file (after SETLFS & SETNAM) K$chkout equ 0FFC9h ; open a channel for output K$clrchn equ 0FFCCh ; clears ALL I/O channel K$chkin equ 0FFC6h ; open a channel for input K$chrin equ 0FFCFh ; get a character from input channel K$chrout equ 0FFD2h ; output a character to output channel K$clall equ 0FFE7h ; close all open files K$close equ 0FFC3h ; close a logical file K$readst equ 0FFB7h ; read status byte page ;"""""""""""""""""""""""""""""""""" ;m a c r o d e f i n i t i o n s ;"""""""""""""""""""""""""""""""""" define macro label,for org ramalc label equ $ ramalc set ramalc+for endm save$top$bottom macro toprow,number mvi a,toprow+number-1 sta bottom$choice mvi a,toprow sta top$choice endm skip$and$destroy$hl macro db 21h endm zero? macro r1,r2 mov a,r1 ora r2 endm fmt macro fmtdef1,fmtdef2 DW fmtdef1 IF NOT NUL fmtdef2 DW fmtdef2 ELSE DW 0 ENDIF ENDM wrdef macro ?trk,?sect,?pointer db ?trk,?sect dw ?pointer endm defstart macro fillbyte IF NOT NUL fillbyte db fillbyte ELSE db 0 ENDIF ENDM defbuf macro ?count,?offset,?pointer dw ?count dw ?offset dw ?pointer endm definline macro ?count,?offset db ?count,-1 dw ?offset endm defexec macro ?adr db 0,-1 dw ?adr endm defend macro dw -1 endm page ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" ;S T A R T H E R E ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" org 100h ;"""""""""""""" ;initialization ;"""""""""""""" lxi sp,stack ;set up stack lhld 0001 ;read jump vector for i/o lxi d,user$offset ;..add this dad d shld go$user$fun+1 ;install vector to user BIOS functions lxi d,scbpbrd ;point to my parameter block mvi c,getscb ;..CP/M function to determine screen size call bdos mov a,h ani both ;..save whether 40,80 or both sta scrsiz ;NOW we are ready to start ;""""""""" ;SAY$HELLO: ;""""""""" call clear$screen ;set up to call posit$top ;..print signon message call print$msg db 'C128 CP/M FORMAT PROGRAM' db crlf db ' 08 JUNE 1987' db eom page mvi c,cur$dsk ; RETURN CURRENT DISK call bdos ; ..in A cpi 4 jrc select$new xra a ; if not A,B,C or D set A page ;---------- select$new: ;---------- mov b,a ; save in B for later mov c,a ; A=B=C= selection # (0-3) inr c ; (1-4) mvi a,80h ; rlc will give 01 select$next: rlc ; drive byte 0000dcba binary dcr c jrnz select$next sta fmt$drv sta vic$drv mov a,b ; get current drive select (0-3) sta sel$drv adi 'A' sta dsp$drv$1 sta dsp$drv$2 sta dsp$drv$3 ; ;***** login requested drive ; call get$disk$info ani 0Eh cpi 0Eh jz select$drv page ;-------------- ;show$disk$type: ;-------------- lda fast ;first tell user what type disk lxi h,fmt$drv ;point to format drive ana m ;..drive a= lst bit lxi h,3134h ; 0=1541 jrz show$slow$fast ; ; ;***** test for 1581 or 1571 ; ; if format$1581 mvi l,'8' ;assume 1581 lda vic$data cpi 0A3h ;horrible hack for *blank* disks! jrz show$slow$fast ; it is an empty 3.5" drive cpi 0A9h jrz show$slow$fast ; it is a virgin 3.5" diskette ani 0B0h ; cpi 020h ;Resident fmt with 512 byte sectors? jrz show$slow$fast ; yes, gotta be a 1581 endif mvi l,'7' ;none of the above, set as a 1571 show$slow$fast: shld a$15xx ;..store the type in message call clear$lots ; call posit$using call print$msg db 'Drive ' dsp$drv$1: db 'A is a 15' a$15xx: db 'x1',eom mvi a,use$line call highlight$line re$start: lxi sp,stack ; set up stack lda a$15xx cpi '4' jz get$1541$choices if format$1581 cpi '7' jz get$1571$choices ; cpi '8' ; jz get$1581$choices ; page ;--------------- ;get$1581$choices: ;--------------- call show$prompt ; db 'Please select disk type to format' db crlf,'Commodore 1581 (Double Sided)' db crlf,'Write system track only' db crlf,'Select Different Drive' db eom save$top$bottom promptline+1,3 call menu$response dw c128$ds$81 dw c128$sys$81 dw select$drv endif page ;--------------- get$1571choices: ;--------------- call show$prompt db 'Please select disk type to format' db crlf,'C128 Double sided' db crlf,'C128 Single sided' db crlf,'C64 Single sided' db crlf,'IBM Single Sided' db crlf,'IBM Double Sided' db crlf,'KAYPRO II' db crlf,'KAYPRO IV' db crlf,'EPSON QX10' db crlf,'OSBORNE DD' db crlf,'Select Different Drive' db eom save$top$bottom promptline+1,10 call menu$response dw c128$ds dw c128$ss dw c64$ss ; dw c1571$ibm$ss ; dw c1571$ibm$ds ; dw c1571$kp$2 ; dw c1571$kp$4 ; dw c1571$epson ; dw c1571$osborne ; dw select$drv ; page ;---------------- get$1541$choices: ;---------------- call show$prompt ; db 'Please select disk type to format' db crlf,'C128 single sided' db crlf,'C64 single sided' db crlf,'Select Different Drive' db eom save$top$bottom promptline+1,3 call menu$response dw c128$ss dw c64$ss dw select$drv ;---------- select$drv: ;---------- call show$prompt ; db 'Please select drive you wish to format with' db crlf,'Drive A' db crlf,'Drive B' db crlf,'Drive C' db crlf,'Drive D' db eom save$top$bottom promptline+1,4 call menu$response dw 0 ; continue execute inline jmp select$new page ; ; if format$1581 c128$ds$81: lxi h,c1581$dsk$def jr format$str c128$sys$81: lxi h,c1581$sys$def jr format$str endif ; ; c128$ds: lxi h,c128$ds$dsk$def jr format$str ; ; c128$ss: lxi h,c128$ss$dsk$def jr format$str ; ; c64$ss: lxi h,c64$ss$dsk$def jr format$str ; ; c1571$epson: lxi h,epson$dsk$def jr format$str ; ; c1571$osborne: lxi h,osborne$dsk$def jr format$str ; ; c1571$kp$2: lxi h,kp$2$dsk$def jr format$str ; ; c1571$kp$4: lxi h,kp$4$dsk$def jr format$str ; ; c1571$ibm$ss: lxi h,ibm$dsk$def$ss jr format$str ; ; C1571$ibm$ds: lxi h,ibm$dsk$def$ds ; jr format$str page ; ; ; format$str: ; call print$msg ; db 'Formatting',crlf,eom call print$what shld fmt$tbl$ptr call clear$prompt call print$msg db 'Insert diskette TO BE FORMATTED' db crlf,'in drive ' dsp$drv$2: db 'A. Type $ when ready,' db crlf,'any other key to abort ',eom call scan$for$key mov a,b cpi disk$ready$key jnz user$panics call clear$prompt call print$msg db '..formatting diskette in drive ' dsp$drv$3: db 'A',crlf,eom lhld fmt$tbl$ptr ; do the format call get$DE$from$HL ; get format table pointer (side 1) cnz format$DE$tbl call get$DE$from$HL ; get format table pointer (side 2) cnz format$DE$tbl call set$dsk$type page ; ; ; format$1: call get$DE$from$HL ; get track & sect mov a,d ; DE=-1 ? ana e inr a jz format$another? mov a,e sta trk mov a,d sta sect call print$msg db '..writing sector',cr,eom call get$DE$from$HL ; get DEF pointer xchg ; HL=DEF pointer, DE=MAIN pointer push d ; save MAIN pointer ; ; ; mov a,m ; get fill byte inx h call init$buf$with$A ; (HL saved) next$fill: call get$DE$from$HL ; get word count to DE jm count$minus mov b,d ; save count in BC mov c,e call get$DE$from$HL ; get offset in buffer push d call get$DE$from$HL ; get pointer to data xthl ; save DEF pointer get offset push d ; save DATA pointer lxi d,sect$buf dad d ; HL= buffer+offset pop d ; DE= DATA pointer xchg ; HL= DATA ptr, DE= buffer+offset ldir ; move data to buffer pop h ; recover DEF pointer jr next$fill page ; ; ; count$minus: inr e ; test for -1 jrnz cnt$not$minus$1 call write$data pop h ; recover MAIN pointer jmp format$1 cnt$not$minus$1: dcr e ; test for 0 jrnz data$inline call get$DE$from$HL xchg ; HL=code adr, DE=DEF pointer push d ; save DEF pointer call ipchl pop h ; recover DEF pointer jmp next$fill data$inline: mvi b,0 mov c,e ; BC=number of bytes to move call get$DE$from$HL ; get offset push h ; save DEF pointer lxi h,sect$buf dad d ; HL=buffer+offset xchg ; DE=buffer+offset pop h ; recover DEF pointer ldir jmp next$fill page ; ; ; format$DE$tbl: push h ; save MAIN pointer xchg ; HL=format table pointer mov c,m ; get count mvi b,0 ; count will be 1 to 255 inr c ; move count also lxi d,@buffer ; point to command buffer area ldir ; move format data to buffer lda fmt$drv ;..bit 0==drive a, MSB=unit 0 sta vic$drv mvi a,do$6502$fun mvi l,vic$frmt call go$user$fun ;call,ret ora a jrnz format$error pop h ret page ;------------ format$error: ;------------ call print$msg db ' format error',cr,lf,eom user$panics: pop h ;--------------- format$another?: ;--------------- call print$msg db crlf,lf,lf db 'Do you want to format another disk?' db eom call get$yes$or$no jc re$start ;----------- exit$format: ;----------- call clear$screen call posit$prompt call print$msg db '.....exiting format program',cr,lf,lf,eom exit$clean: mvi c,13 call bdos ; reset disk system mvi c,constat call bdos ana a jz 0 mvi c,conin call bdos jmp 0 ;--------- quit$prog: ;--------- push psw push b push d push h call posit$spec ;for special messages call print$msg db 'Are you sure? [ ]',bs,bs,eom call get$yes$or$no jrc exit$clean call posit$spec call clear$eol pop h pop d pop b pop psw ret page ;-------------- get$DE$from$HL: ;-------------- mov e,m inx h mov d,m inx h mov a,d ora e rz mov a,d ana a ret ipchl: pchl ;--------------- init$buf$with$A: ;--------------- push h lxi h,sect$buf shld dma mov m,a lxi d,sect$buf+1 lxi b,1024 ldir pop h ret ; ; set disk type to TYPE 0 (GCR direct sector I/O) ;------------ set$dsk$type: ;------------ push h mvi c,13 call bdos ; reset disk system lxi d,sel$pb call BIOS$ind dcx h call get$disk$info bit a,7 ; MFM disk? jrnz size$ok ; yes, then size is ok ani 30h ; no, 1571 GCR reports jrnz size$ok ; ...128 byte sectors mvi a,10h ; set 256 byte sectors size$ok: ani 00110000b ; set disk type to DSK$none mov m,a ; this will allow direct sector access pop h ret ;------------- get$disk$info: ;------------- push h mvi a,do$6502$fun mvi l,vic$test call go$user$fun ;call,ret mov b,a ;save status from drive in B also pop h ret page ;---------- write$data: ;---------- lxi d,dma$bnk$pb call BIOS$ind lxi d,dma$pb call BIOS$ind lxi d,trk$pb call BIOS$ind lxi d,sect$pb call BIOS$ind lxi d,wr$pb call BIOS$ind ana a rz pop h call posit$spec call print$msg db 'Disk write error',crlf,eom jmp exit$format page ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" ;Í É Ó Ã Å Ì Ì Á Î Å Ï Õ Ó Õ Ó Å Æ Õ Ì Õ Ô É Ì É Ô É Å Ó ;""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" beep: mvi e,7 jr do$con$out do$cr$lf: mvi e,cr call do$con$out mvi e,lf do$con$out: mvi c,conout jmp bdos BIOS$ind: mvi c,50 jmp bdos print$what: push h call clear$lots pop h call print$hl push h mvi a,lots$line call highlight$line pop h ret show$prompt: call clear$lots ; call posit$prompt ;----------------------------------------------------- print$msg: ;print a message on the screen ;----------------------------------------------------- xthl call print$hl xthl ret print$hl: push h print$lp: pop h mov a,m ;..get the message mov e,a ;in a for call to bdos inx h ;..update pointer ana a ;if char was 0, pointer = return address rz ;..end message push h ;..restore pointer inr a ;..FF==cr,lf jrz char$eq$cr$lf call do$con$out jr print$lp ;..loop char$eq$cr$lf: call do$cr$lf jr print$lp clear$prompt: call posit$prompt call clear$eos posit$prompt: lxi d,prompt$line*256+0 ; B=row C=col jr set$fx$cp$cmd clear$edit: call posit$editing call clear$eos posit$editing: lxi d,keynam$line*256+0 jr set$fx$cp$cmd posit$top: lxi d,top$line*256 jr set$fx$cp$cmd posit$using: lxi d,use$line*256 ; B=row C=col jr set$fx$cp$cmd clear$lots: call posit$lots call clear$eos posit$lots: lxi d,lots$line*256 jr set$fx$cp$cmd posit$spec: lxi d,spec$line*256 set$fx$cp$cmd: ;set up to position cursor mvi l,FR$cursor$pos jr go$screen$fun clear$eos: mvi l,FR$CES jr go$screen$fun clear$eol: mvi l,FR$CEL go$screen$fun: push b lda scr$siz mvi c,FR$40 cpi scrsz40 jrnz set$fx$eighty set$fx$forty: mov a,l add c mov l,a set$fx$eighty: mvi a,3 ; direct to screen fun # pop b go$user$fun: jmp 0000 ; address filled in page ;""""""""""""""""""""""""""""""""""""""""""""""""" ;s c a n f o r y e s o r n o a n s w e r ;""""""""""""""""""""""""""""""""""""""""""""""""" get$yes$or$no: call scan$for$key mov a,b cpi yes$key stc rz sui no$key ana a ;clear carry for no rz call beep jr get$yes$or$no ;""""""""""""""""""""""""""""""""""""""""""""" ;s c a n f o r k e y b o a r d i n p u t ;""""""""""""""""""""""""""""""""""""""""""""" scan$for$key: mvi a,2 call go$user$fun inr b jrz scan$for$key dcr b ret page ;""""""""""""""""""""""""""""""" ;c l e a r t h e s c r e e n ;""""""""""""""""""""""""""""""" clear$screen: call print$msg db 1ah,eom ret ;""""""""""""""""""""""""""""""""""""""""" ;g e t r e s p o n s e t o m e n u ;""""""""""""""""""""""""""""""""""""""""" menu$response: sta current$choice call highlight$line wait$ans: call scan$for$key mov a,b cpi cret jz made$selection cpi ctrlc cz quit$prog call up$or$down? cz scroll$values jr wait$ans made$selection: lda top$choice mov b,a lda current$choice sub b ;a=0-x for choices mov b,a ;..save it pop d mov l,a mvi h,0 ;first test if de is pointing to a 00 dad h ;*2 xchg ;(00--> just return) mov a,m inx h ora m inx h jrz back$to$?? dcx h dcx h dad d ;+ beginning of jump table mov a,m inx h mov h,m mov l,a back$to$??: mov a,b ;a=0-x pchl page ;""""""""""""""""""""""""""""""""""""""""""""""""""""" ;s c r o l l u p & d o w n t h r o u g h m e n u ;""""""""""""""""""""""""""""""""""""""""""""""""""""" scroll$values: push psw lda current$choice ;unhighlight the current menu line mvi h,0 ;..dont set any additional attributes call write$hi$line ;..common routine for writing current line pop psw ;get flags back jrc scroll$up lda bottom$choice mov b,a lda current$choice cmp b ;current==bottom && scrolldown?? jrz force$top inr a sta current$choice jr highlight$line ;call,ret scroll$up: lda top$choice mov b,a lda current$choice cmp b ;current==top && scroll up?? jrz force$bottom dcr a sta current$choice jr highlight$line ;call,ret force$top: lda top$choice ;to scroll down from bottom==top sta current$choice jr highlight$line ;call,ret force$bottom: lda bottom$choice ;to scroll up from top==bottom sta current$choice highlight$line: ;a=row # to be highlighted call read$this$row ;to highlight, read current row and mvi h,40h ;..write it out with rev vid attribute jr write$hi$line page read$this$row: push psw ;save the row number for others mov d,a ;d=row mvi e,0 ;column (e) = 0 lxi h,save$buffer ;a place to read into shld temp$ptr ;save a pointer xra a ;..initialize count to 0 sta read$count read$row$lp: push d ;..save it to loop mvi l,FR$rd$chr$atr ;read char and attribute from (de) call go$screen$fun ;go read a character lhld temp$ptr ;get buffer pointer mov m,b ;buffer the character inx h mov m,c ;..and the attribute inx h ;to next character shld temp$ptr ;save the pointer pop d ;current row,column inx d ;next row,column mov a,e ;when count(column)=, we have read maximum cpi 40 jrnz read$row$lp dcx h ;point to last character written mov b,e ;# of characters to scan for trailing spaces mvi a,' ' ;..space character to scan for scan$space$lp: dcx h ;char, not attribute cmp m ;..is char a space?? jrnz end$scan ;if not, we are done dcx h ;..else decrement to previous attribute djnz scan$space$lp ;keep looking end$scan: mov a,b inr a sta read$count ;store # of non-white chars to restore pop psw ;restore a=row # ret page write$hi$line: mov d,a ;current row passed in a mvi e,0 ;..start at column 0 mov a,h ;..additional attribute bits passed in h sta temp ;save attribute value to be ored lxi h,save$buffer ;where the current line was read into shld temp$ptr ;..save pointer to it lda read$count ;number of bytes actually in line (no trailing spaces) mov b,a ;..count in b wr$hi$li$loop: push b ;save the counter push d ;save the cursor position lhld temp$ptr ;get pointer mov b,m ;get char in b inx h ;point to attribute mov a,m ;..get attribute inx h ;update to next character shld temp$ptr ;..save the pointer mov h,a ;..put attribute here for a moment lda temp ;get the attribute passed (either rev vid or none) ora h ;..set it mov c,a ;..attribute must be passed in c mvi l,FR$wr$chr$atr ;write character and attribute functions call go$screen$fun ;go do it pop d ;cursor position back inx d ;..next pop b ;get counter back djnz wr$hi$li$loop ;..loop ret ;...line is rewritten up$or$down?: mov a,b ;get matrix row in a cpi cursor$up$key ;is it cursor up? stc rz ;..return if cursor up sui cursor$dn$key ana a ;clear carry flag ret ;return something to caller page ;------------------------------- ;p a r a m e t e r b l o c k s ;------------------------------- scbpbrd: db 24h ;set offset for conout db 0 ;..get (read)scb (hl =returnedword,a=byte) dw 0 ;just for the hell of it wr$pb: ;write parameter block db 14 ;write sector db 0 dw 0 dw 0 dw 0 sel$pb: ;select parameter block db 9 ; select drive function db 0 ; a sel$drv: dw 0 ; bc drive # dw 1 ; de lsb=0 means 1st time select dw 0 ; hl trk$pb: ;track parameter block db 10 ; set track db 0 trk: dw 0001h ; track # dw 0 dw 0 sect$pb: ;sector parameter block db 11 ; set sector # db 0 sect: dw 0001h ; sector # dw 0 dw 0 dma$pb: ;dma parameter block db 12 db 0 dma: dw 4000h ; dma pointer dw 0 dw 0 dma$bnk$pb: ;dma bank parameter block db 28 db 1 ; dma bank 1 dw 0 dw 0 dw 0 page ; ; 39-1 | 39-2 | 39-3 | ;"""""""""""""""|"""""""""""""""|"""""""""""""""| ; disk | BAM | BAM | disk | DRV | SYS | ; lable | 1 | 2 | DIR | boot | boot | ;"""""""|"""""""|"""""""|"""""""|"""""""|"""""""| ; 40-0 | 40-1 | 40-2 | 40-3 | 40-4 | 40-5 | ; ; ; 39-4 | 39-5 | ;"""""""""""""""|"""""""""""""""| ; LDR | LDR | LDR | | ; #1 | #2 | #3 | | ;"""""""|"""""""|"""""""|"""""""| ; 40-6 | 40-7 | 40-8 | 40-9 | ; if format$1581 c1581$dsk$def: db 'Formatting C128 CP/M on C1581',eom fmt fmt$tbl$c1581 wrdef 39,1,ST$sect$39$1 wrdef 39,2,ST$sect$39$2 wrdef 39,3,ST$sect$39$3 wrdef 39,4,ST$loader$start$1 wrdef 39,5,ST$loader$start$2 defend c1581$sys$def: db 'Formatting C128 CP/M on C1581',eom fmt 0 wrdef 39,1,ST$sect$39$1 wrdef 39,2,ST$sect$39$2 wrdef 39,3,ST$sect$39$3 wrdef 39,4,ST$loader$start$1 wrdef 39,5,ST$loader$start$2 defend endif page ; ; ; c64$ss$dsk$def: db 'C64 single sided',eom fmt fmt$tbl$c64$ss wrdef 1,0,ST$c64$1$0 ; track, sector, DEF wrdef 3,0,ST$E5s ; track, sector, DEF wrdef 3,1,ST$E5s ; track, sector, DEF wrdef 3,2,ST$E5s ; track, sector, DEF wrdef 3,3,ST$E5s ; track, sector, DEF wrdef 3,4,ST$E5s ; track, sector, DEF wrdef 3,5,ST$E5s ; track, sector, DEF wrdef 3,6,ST$E5s ; track, sector, DEF wrdef 3,7,ST$E5s ; track, sector, DEF defend page ; ; ; c128$ss$dsk$def: db 'C128 Single Sided',eom fmt fmt$tbl$c64$ss wrdef 1,0,ST$c128$1$0$ss ; track, sector, DEF wrdef 1,3,ST$E5s wrdef 1,4,ST$E5s wrdef 1,9,ST$E5s wrdef 1,10,ST$E5s wrdef 1,14,ST$E5s wrdef 1,15,ST$E5s wrdef 1,19,ST$E5s wrdef 1,20,ST$E5s wrdef 18,0,ST$sect$18$0 defend page ; ; ; c128$ds$dsk$def: db 'C128 Double Sided',eom fmt fmt$tbl$c64$ss wrdef 1,0,ST$c128$1$0$ds ; track, sector, DEF wrdef 1,1,ST$E5s wrdef 1,2,ST$E5s wrdef 1,3,ST$E5s wrdef 1,4,ST$E5s wrdef 1,7,ST$E5s wrdef 1,8,ST$E5s wrdef 1,9,ST$E5s wrdef 1,10,ST$E5s wrdef 1,12,ST$E5s wrdef 1,13,ST$E5s wrdef 1,14,ST$E5s wrdef 1,15,ST$E5s wrdef 1,17,ST$E5s wrdef 1,18,ST$E5s wrdef 1,19,ST$E5s wrdef 1,20,ST$E5s wrdef 18,0,ST$sect$18$0 wrdef 53,0,ST$sect$18$0 defend page ; ; ; epson$dsk$def: db 'EPSON QX10 512 byte sectors',eom fmt fmt$tbl$epson defend ; ; no sector to be set-up ; osborne$dsk$def: db 'OSBORNE Double Density',eom fmt fmt$tbl$osborne defend ; ; ; kp$2$dsk$def: db 'KAYPRO II',eom fmt fmt$tbl$kp$2 defend kp$4$dsk$def: db 'KAYPRO IV',eom fmt fmt$tbl$kp$2,fmt$tbl$kp$4 defend page ; ; IBM -- single sided disk definition ; ibm$dsk$def$ss: db 'IBM SS',eom fmt fmt$tbl$ibm$ss wrdef 0,1,ST$ibm$ss ; track, sector, DEF defend ; ; ; ibm$dsk$def$ds: db 'IBM DS',eom fmt fmt$tbl$ibm$ds wrdef 0,1,ST$ibm$ds ; track, sector, DEF defend page ; ; ; if format$1581 fmt$tbl$c1581: db 1 db 10000110b ;parameter N (cmd 4) db 2 ; sector size =512 db 79 ; last track # 79 db 10 ; number sectors/track db 0 ; starting track # db 0E5h ; fill byte db 38 ; gap 3 endif ; ; GCR Format parameters ; fmt$tbl$c64$ss: table$ds: db 4 db 00000110b ;parameter N (cmd 4) db 00000000b ;parameter MD (Mode GCR) db '8' ;parameter ID low db '0' ;parameter ID high ; ; ; fmt$tbl$epson: db 6 db 01100110b ; N cmd 4 db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 10 ; NS 10 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) ; ; ; fmt$tbl$osborne: db 6 db 01000110b ; N cmd 4 db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 3 ; SZ 1024 byte sectors db 39 ; LT last track 39 db 5 ; NS 5 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) page ; ; KAYPRO II (single sided) ; -- uses this format data to format the top and ; -- bottom of KAYPRO II and KAYPRO IV disk ; fmt$tbl$kp$2: db 6 db 01000110b ; N cmd 4 db 10000000b ; MD Mode MFM (start sector 0) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 10 ; NS 10 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) ; ; KAYPRO IV (double sided) ; -- uses this format data to format the top of the disk (side 1) ; fmt$tbl$kp$4: db 6 db 01010110b ; N cmd 4 db 10001010b ; MD Mode MFM (start sector 10) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 10 ; NS 10 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) page ; ; ; fmt$tbl$ibm$ss: db 6 db 01000110b ; N cmd 4 db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 8 ; NS 8 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) ; ; ; fmt$tbl$ibm$ds: db 6 db 01100110b ; N cmd 4 format DS db 10000001b ; MD Mode MFM (start sector 1) db 0 ; CP interleave of 0 db 2 ; SZ 512 byte sectors db 39 ; LT last track 39 db 8 ; NS 8 sectors/track ; ST Starting track logical (def 0) ; S Starting Offset Physical (def 0) ; FL Fill byte (def E5) page ; ; ; if format$1581 ST$sect$39$1: defstart 0 defbuf 29,0,sect$39$1 definline 8,100h db 40,2 ; next BAM track and sector db 44h,not(44h) ; DISK version # db '80' ; Disk ID db 40h ; verify off, check header ID on db 80h ; enable auto load defend ; ; ; ST$sect$39$2: defstart 0 definline 7,1 db -1 ; mark end of BAM db 44h,not(44h) ; Disk Version # db '80' ; ID db 40h ; verify off, check header ID on db 80h ; enable auto load definline 20,101h db -1 ; next track sector (end) db 83h ; type USR db 40,4 ; logical trk 40 sector 4 db 'COPYRIGHT CBM 86' definline 1,11Eh db 1 defend page ; ; ; ST$sect$39$3: defstart 0 definline 5,0 db 0,lng$drv$cd+5 dw drv$buf ; exec adr in drv db lng$drv$cd defbuf lng$drv$cd,5,drv$code$1581 defexec boot$check$sum ; compute Check SUM defbuf 0c9h,100h,boot$1581$sector defend ; ; ; ST$loader$start$1: defstart 0 defbuf 512,0,loader$start defend ; ; ; ST$loader$start$2: defstart 0 defbuf loader$size-512,0,loader$start+512 defend endif page ; ; ; ST$c64$1$0: defstart 0E5h definline 4,0 db 'KMBE' defend ; ; ; ST$c128$1$0$ss: defstart 0 defbuf 24h,0,sect$1$0 defend ; ; ; ST$c128$1$0$ds: defstart 0 defbuf 24h,0,sect$1$0 definline 1,255 db -1 defend page ; ; ; ST$sect$18$0: defstart 0 definline 4,0 db 1,5,41h,80h definline 4,48h db 11h,0fch,-1,7 definline 27,90h db 'CP/M PLUS' db 0a0h,0a0h,0a0h db 0a0h,0a0h,0a0h db 0a0h,0a0h,0a0h db '65',0a0h,'2A' db 0a0h,0a0h db 0a0h,0a0h defend ; ; ; ST$E5s: defstart 0E5h defend ; ; IBM single sided ; -- Track 0, Sector 1 last byte =0 ; ST$ibm$ss: defstart 0E5h definline 1,512-1 ; last byte=0 for IBM single sided db 0 defend ; ; IBM double sided ; -- Track 0, Sector 1 last byte =1 ; ST$ibm$ds: defstart 0E5h definline 1,512-1 ; last byte=0 for IBM single sided db 1 defend page ; ; Computes and sets the check SUM for the 1581 Drive Boot sector ; if format$1581 boot$check$sum: lxi h,sect$buf+2 lxi d,sect$buf+2+lng$drv$cd+3 mvi b,0 ; start SUM =0 sum$next: mov a,m add b aci 0 ; add carry to LSB mov b,a ; return sum to B inx h mov a,l cmp e jrnz sum$next mov a,h cmp d jrnz sum$next mov m,b ; save sum to end of buffer ret endif page ; ; 1541 and 1571 BOOT sector ; track 1 sector 0 sector definition (256 bytes) ; sect$1$0: db 'CBM',0,0,0,0,0,0 ; bytes 0 to 8 @sei ; byte 9 @jsr 0ff84h @lda 3eh,# ; set MMU to bank 0 @sta 0ff00h ; .. RAM and IO only @lda 0c3h,# @sta 0FFEEh @lda 08,# @sta 0FFEFh @lda 0,# @sta 0FFF0h @jmp 0ffd0h ; swap to Z80 (RST1 location) page if format$1581 CV equ drv$buf-$ my$trans$hi set high(my$trans+CV) my$trans$low set low(my$trans+CV) ; ; drv$code$1581: @sei @lda VTRANS$TS ; get old vector and save it @sta CV+code$exit$2+1 @lda VTRANS$TS+1 @sta CV+code$exit$2+2 @lda my$trans$low,# ; install new vector @sta VTRANS$TS @lda my$trans$hi,# @sta VTRANS$TS+1 @lda buf$alc,# @sta buf$use ; protect this code @jmp boot$ret my$trans: @ldx next$job @lda jobs,x ; get current job @cmp 80h,# ; is it a READ @bne code$exit$1 @ldy hdrjob ; get index @ldx hdrs+1,y ; get logical sector @bne code$exit$1 @ldx hdrs,y ; get logical track @dex ; was it one @bne code$exit$1 @ldx 40,# @stx hdrs,y ; change to logical TRK=40 @ldx 5,# @stx hdrs+1,y ; change to logical SECT=5 code$exit$1: @lda CV+code$exit$2+1 @sta VTRANS$TS ; get old vector and save it @lda CV+code$exit$2+2 @sta VTRANS$TS+1 code$exit$2: @jmp 0000 lng$drv$cd equ $-drv$code$1581 page ; ; 1581 Directory Sector ; sect$39$1: db 40,3 ; directory track & sector (logical) db 44h,0 ; Disk versions and null flag db 'CP/M PLUS',0a0h,0a0h,0a0h db 0a0h,0a0h,0a0h,0a0h,0a0h,0a0h db '80',0a0h,'3D',0a0h,0a0h page ; 1581 Boot sector ; track 1 sector 0 sector definition (256 bytes) ; BB equ boot$code$02-$ ; boot$1581$sector: db 'CBM',0,0,0,0,0,0 ; bytes 0 to 8 @sei ; (9) @jsr 0ff84h ; (A-C) reset I/O ; ; Clear Bank 0 memory ; @lda 3Fh,# ; (D,E) Enable RAM 0 @sta 0FF00h ; (F-11) @lda 10h,# ; (12,13) high byte of page pointer @sta 21h ; (14,15) save hiagh byte of pointer @lda 0,# ; (16,17) low byte of page pointer @sta 20h ; (18,19) save low byte of pointer @ldx 0EFh,# ; (1A,1B) from 1000h to FEFFh @tay ; (1Ch) start at 0 era$loop: @sta (20h),y ; (1D,1E) @iny ; (1Fh) @bne era$loop ; (20,21) @inc 21h ; (22,23) point to next page @dex ; (24) @bne era$loop ; (25,26) @sta 0FF00h ; (27-29) re-enable kernal and I/O ; ; load sectors that contain CP/M boot code (RAM version) ; ; open command chanel to drive 8 ; @lda 15,# ; (2A,2B) @ldx 8,# ; (2C,2D) @tay ; (2Eh) @jsr 0FFBAh ; (2F-31) SETLFS @lda 0,# ; (32,33) @tax ; (34) @jsr 0FF68h ; (35-37) SETBNK @lda 4,# ; (38,39) @ldx low(u0point+BB),# ; (3A,3B) @ldy high(u0point+BB),# ; (3C,3D) ;;;*** @jsr 0FFBDh ; (3E-40) SETNAM @jsr 0FFC0h ; (41-43) OPEN ; ; read sector 39-4 ; dma0 equ high(boot$code$80) @lda 39,# @ldx 4,# @ldy dma0,# @jsr rd$sector+BB ; ; read sector 39-5 ; @lda 39,# @ldx 5,# @jsr rd$sect$buf+BB ; ; install JMP BOOT$CP/M ; low$start equ low(boot$code$80) hi$start equ high(boot$code$80) @lda 0c3h,# @sta 0FFEEh @lda low$start,# @sta 0FFEFh @lda hi$start,# @sta 0FFF0h @lda 3eh,# ; set MMU to bank 0 @sta 0ff00h ; .. RAM and IO only @jmp 0FFD0h ; swap to Z80 (RST1 location) rd$sector: @sty 21h ; hi byte of DMA adr rd$sect$buf: @sta trk02+BB @stx sect02+BB @ldx 15,# ; CMD chan # @jsr 0FFC9h ; CHKOUT @ldy 6,# sendf: @lda R$cmd+BB,y @jsr 0FFD2h ; CHROUT @dey @bne sendf @jsr 0FFCCh ; CLRCHN @bit 0DC0Dh ; D1ICR @jsr read$byte+BB ; read status @ldx 2,# ; 2 256 byte blocks/sector @ldy 0,# @sty 20h ; low byte of DMA adr rd$buff: @jsr read$byte+BB @sta (20h),y ; at dma adr @iny @bne rd$buff @inc 21h ; advance DMA pointer @dex @bne rd$buff @lda 0DD00h ; D2PRA @and 0EFh,# ; @sta 0DD00h ; set clk hi @rts ; read$byte: @sei ; disable interrupts @lda 0DD00h ; D2PRA @eor 10h,# ; clock bit @sta 0DD00h @lda 8,# in$1: @bit 0DC0Dh ; D1ICR @beq in$1 @lda 0DC0Ch ; D1SDR @rts R$cmd equ $-1 db 1 ; count sect02: db 0 ; sector # trk02: db 0 ; track # db 0,'0' ; read comand =00h u0point: db 'U0',4Ch,0 ; Inquire Status page ; ZZ equ boot$code$80-$ LOADER$START: ; ; setup the MMU for booting CP/M ; lxi sp,boot$stack mvi a,3Fh sta force$map ; ; move bios and swap code into ram ; lxi h,bios$65$code+ZZ lxi d,bios$02 lxi b,bios$size ldir lxi h,swap$code lxi d,enable$z80 lxi b,swap$size ldir mvi a,RET ; get z80 return adr sta return$6502 ; store the RET ; ; initilize the 8502 bios ; xra a ; cleared by memory fill sta vic$cmd call enable$6502 page ; ; set MMU registers to a known state (for CP/M to use) ; lxi h,mmu$init$data+11-1 ; start at the End lxi b,mmu$start+11-1 ; and work forward mvi d,11 ; for all 11 bytes INIT$MMU$CPM: mov a,m ; get table value outp a ; send to MMU dcx h dcr c dcr d jrnz INIT$MMU$CPM ; re-enabled RAM bank 0 (no I/O) ; ; set 80 column colors and set up Video memory with ASCII char set ; mvi a,26 call wait mvi a,90h ; foreground red background black outp a mvi a,85h ; set attr and color sta current$atr ; ..for 80 column display mvi a,green ; set color sta attr$40 ; ..for 40 column display call install$ASCII ; convert char set to true ASCII mvi a,25 ; number of lines on the 40 col display sta paint$size page ; ; Let the user know we are booting CP/M ; call prt$msg$both db -1 ; clear both screens rownum 1,10 db 'BOOTING CP/M PLUS',0 ; ; point 40 column screen to CP/M screen area ; lxi b,VIC+24 mvi a,vic$screen*4/256+6 ; upper and lower case set (+6) outp a ; ; ; mvi a,64 sta block$size ; 64 dir entries/2K allocation lxi h,DIR$PTRS+ZZ shld ld$blk$ptr call SCAN$DIR+ZZ ; check 1st block call SCAN$DIR+ZZ ; check 2nd block (1K or 2K) lhld block$ptrs ; 1st pointer <>0 if file mov a,h ; name exist ora l ; pointer = 0 jz tell$user ; yes, inform user there is a error ; no, file FOUND, process it page ;---------------------------- ; load 1st group to 1K buffer ;---------------------------- FILE$FOUND: lxi h,block$ptrs shld ld$blk$ptr call UPDATE$BUFFER+ZZ ;-------------- ;GET$BOOT$INFO: ;-------------- lxi h,block$buffer lxi d,info$buffer lxi b,12 ldir call prt$msg$both rownum 10,0 db 0 ; end of string marker lxi h,block$buffer+80h call prt$hl$both lxi h,block$buffer+256 ; set scan pointer shld blk$unld$ptr page ;--------------------------------- ; load keyboard data to system RAM ;--------------------------------- call prt$msg$both rownum 3,12 db 'DATA TABLES',0 lhld info$buffer+10 shld key$tbl ; install keyboard translation pointer lxi h,info$buffer+9 call GET$SIZE$ADR+ZZ ; HL=adr DE=# (128 btye) records shld fun$tbl LOAD$NEXT$FORWARD: call LOAD$RECORD+ZZ ; HL =load address (in and out) lxi d,128 ; move pointer back to buf start dad d jrnz LOAD$NEXT$FORWARD page ;----------------------------------- ; transfer CP/M code to load address ;----------------------------------- call prt$msg$both rownum 4,12 db 'COMMON CODE',0 lxi h,info$buffer+1 ; load common code call LOAD$REVERSE+ZZ call prt$msg$both rownum 5,12 db 'BANKED CODE',0 lxi h,info$buffer+3 ; load banked code call LOAD$REVERSE+ZZ page ;--------------------------- ; now load the bios8502 code ;--------------------------- call prt$msg$both rownum 6,12 db 'BIOS8502 CODE',0 lxi h,info$buffer+7 ; load banked code call LOAD$REVERSE+ZZ lda info$buffer+7 ; get code size (in 256 byte blocks) mov b,a lda info$buffer+6 ; get page pointer (pointer to end) sub b ; find the start ; install jmp adr to BIOS02 sta return$z80+2 ; (jmp) (low) (high) xra a sta return$z80+1 ; (jmp) (low) (high) ;------------------------------------ ; now let's start executing CP/M Plus ;------------------------------------ lhld info$buffer+4 ; get start address pchl ; transfer control to CP/M page ;-------------; ; SUBROUTINES ; ;-------------; ; scan buffer for CPM+.SYS file ; SCAN$DIR: call UPDATE$BUFFER+ZZ ; returns HL=block$buffer mvi a,64 ; 64 for 2K block ; ..number director entries/sector CHECK$NEXT: shld @dma lxi d,sys$name ; point to system name push psw call name$match+ZZ cz FOUND+ZZ pop psw lhld @dma ; get current buffer pointer lxi d,32 dad d dcr a jrnz CHECK$NEXT ret page ; ; ; name$match: mvi b,12 xchg match$next: ldax d ani 7fh cmp m rnz inx h inx d djnz match$next ldax d sta ext$num xra a ret page ;---------------------------- ; save CPM+.SYS group numbers ;---------------------------- ; found a dir entry that has the right name ; add block pointers to list ; FOUND: lxi d,block$ptrs ; point to start of block pointers lda ext$num ora a jrz EXT$NUM$0 lxi d,block$ptrs+16 dcr a jnz ext$error EXT$NUM$0: lhld @dma ; get current pointer lxi b,16 ; number of bytes to move dad b ; also advance to block pointers ldir lhld block$ptrs mov a,h ora l ; 1st block present ? rz ; no, read more dir. lhld block$ptrs+14 ; extent full? mov a,h ora l jrz GO$BOOT$IT ; no, this is it then lhld block$ptrs+16 ; 2nd block present ? mov a,h ora l rz ; no, read more dir. GO$BOOT$IT: jmp FILE$FOUND+ZZ ; two parms are still on the stack ; but at this point who cares page ; ; ; LOAD$REVERSE: call GET$SIZE$ADR+ZZ ; HL=adr DE=# records (128 byte) LOAD$NEXT: lxi d,-128 ; move pointer back to buf start dad d call LOAD$RECORD+ZZ jrnz LOAD$NEXT ret ; ; ; GET$SIZE$ADR: mov e,m mvi d,0 ; get buffer size (#256 byte) mov a,e ; get size to A ora a jz table$error ; exit if count=0 xchg dad h ; HL=#128 byte blocks shld load$count xchg dcx h mov h,m mvi l,0 ret page ; ; ; LOAD$RECORD: push h ; save to address lxi h,block$buffer+2048 xchg lhld blk$unld$ptr call cmp$hl$de cz UPDATE$BUFFER+ZZ xchg lxi h,128 dad d shld blk$unld$ptr pop h ; recover save address push h xchg ; HL=source DE=dest. lxi b,128 ; size of move ldir lhld load$count dcx h shld load$count mov a,l ora h pop h ret page ; ; ; UPDATE$BUFFER: lxi h,block$buffer shld @dma push h ; save block buffer adr for ret lhld ld$blk$ptr ; get the current block pointer mov e,m ; get LSB of block pointer inx h ; advance pointer mov d,m ; zero MSB of block pointer inx h shld ld$blk$ptr xchg ; get block number to HL ; ; read the block pointed to by the HL ; into the data buffer ; dad h ; 2X (1k blocks) dad h ; 4x (512 byte blocks) push h call read$1K+ZZ ; read 1st 1K block lda @dma+1 adi 4 sta @dma+1 pop h inx h inx h call read$1K+ZZ ; read 2nd 1K block pop h ; recover block buffer adr ret ; ; convert block number (in HL) to sector and track ; read$1K: mvi a,2 sta F$rd$count+BZ ; lxi d,10 ; 10 sectors per side lxi b,-1 compute$trk: inx b ora a ; clear the carry dsbc d ; negative if <10 jrnc compute$trk ; jump if still positive >=10 dad d ; add it back mov a,c ; get trk # (0 to 159) cpi 39*2 jrc bump$trk inr a inr c bump$trk: rrc ; move bit 0 to carry mvi a,1 ; sector numbers are 1 to 10 jrnc side$0 mvi a,11 ; or 11 to 20 side$0: add l ; get sector # (0-9) sta VIC$sect mov a,c ; get trk # (0 to 159) rar ; divide by 2 (carry was cleared) sta VIC$trk jmp read$sector ; read the sector to the buffer DIR$PTRS: dw 0,1 page ; ; ; **** THIS IS THE COMMAND LOOP **** ; BZ equ bios$02-$ ; BIOS BIAS ; bios$65$code: @sei @lda 0,# ;-K @sta vic$data ;-K @JSR VICIO+BZ ;-K go find and do requested operation CMDLP: @sei @lda 3eh,# ;?K set up Z80 memory map as required @sta force$map ;-K @jmp enable$z80 ;-K ; ; **** IO COMMAND DISPATCH ROUTINE **** ; VICIO: @CLD ;-K clear to binary mode @LDA vic$cmd ;-K get the command @bne read ;-K 0=initialize ; 1=read page ; ; ; initilize: ; initialize the 8502 @ldx 0,# ;-K @stx force$map ;-K enable the kernal @stx VIC+26 ;+K turn off VIC interrupts @ldx low(irqs+BZ),# @ldy high(irqs+BZ),# @stx 314h ;+K IRQ vector @sty 315h @stx 316h ;+K BRK vector @sty 317h @stx 318h ;+K NMI vector @sty 319h ; ; **** OPEN DISK COMMAND CHANNEL **** ; @LDA cmdchn,# ;+K @CLC ;+K @JSR K$close ;+K @LDA cmdchn,# ;+K @LDX 8,# ;+K @TAY ;+K @JSR K$setlfs ;+K @LDA 0,# ;+K @TAX ;+K @JSR K$set$bnk ;+K @LDA 4,# ;+K @LDX low(U0PT+BZ),# ;+K @LDY high(U0PT+BZ),# ;+K @JSR K$setnam ;+K @JSR K$open ;+K @bcs misdsk @jsr K$readst @ROL A ;+K GET MSB TO CARRY @BCS MISDSK ;+K DEVICE MISSING IF CARRY SET @rts ; ; * DEVICE MISSING, CLEAN UP ERROR * ; MISDSK: @LDA 00fh,# ;+K SET ERROR CODE @skip2 fst$error: @lda 0dh,# ;?K @skip2 DISK$CHANGED: @lda 0FFh,# ;?K @STA vic$data ;?K writes to RAM under ROM @JMP CMDLP+BZ ;?K PAGE ; ; **** DISK SECTOR READ **** ; READ: @ldx 0,# ;-K get read command (side 0) @lda VIC$sect @cmp 11,# @bmi on$side$0 @ldx 10h,# ; get read command (side 1) @sbc 10,# ; remove bias of 10 on$side$0: @stx F$cmd+BZ @sta F$rd$sect+BZ @lda VIC$trk @sta F$rd$trk+BZ @lda @dma ;-K @sta pointer ;-K @lda @dma+1 ;-K @sta pointer+1 ;-K @lda 0,# ;-K @sta force$map ;-K @ldx cmdchn,# ;+K @jsr K$chkout ;+K @bcs fst$error ;+K @ldy Fcmd$lng,# ;+K sendf$rd: @lda Fcmd$buf+BZ-1,y ;+K @jsr K$chrout ;+K @dey ;+K @bne sendf$rd ;+K @jsr K$clrchn ;+K @bit D1ICR ;+K @ldx F$rd$count+BZ ;+K rd$sect: @sei ;+K @jsr rd$byte+BZ ;+K @and 0eh,# ;+K mask off error bits @bne fst$error ;+K @ldy 0,# ;+K start index at buffer start @jsr read$256+BZ ;+K read 1st 256 byte block @jsr read$256+BZ ;+K read 2nd 256 byte block @dex ;+K @bne rd$sect ;+K clk$hi: @lda d2pra ;+K @and 0ffh-clk$bit,# ;+K @sta d2pra ;+K @rts ;+K PAGE ; ; read$256: @jsr rd$byte+BZ ;+K @sta (pointer),y ;+K @iny ;+K @bne read$256 ;+K @inc pointer+1 ;+K @rts ; rd$byte: @lda d2pra @eor clk$bit,# @sta d2pra @lda 8,# rd$1: @bit d1icr @beq rd$1 @lda d1sdr @rts page ; ; handle all interrupts in BIOS 8502 (throw them away) ; irqs: @lda CIA$1+int$ctrl @lda CIA$2+int$ctrl @lda 0fh,# @sta VIC+25 ; ; system saved memory config, Y, X and A before getting here ; @pla @sta force$map @pla @tay @pla @tax @pla @rti PAGE F$cmd$buf: F$rd$count: db 2 ; 5 F$rd$sect: db 0 ; 4 filled in F$rd$trk: db 0 ; 3 filled in F$cmd: db 0 ; 2 read=0 db '0' U0PT: db 'U' ; 1 Fcmd$lng equ $-F$cmd$buf db '0',4Ch,0 ; reset disk change status (open) bios$size equ $-bios$65$code loader$size equ $-loader$start if loader$size > 2048 ' loader size error' endif endif page endofcode: ramalc set endofcode define top$choice,1 ; top row of these choices define bottom$choice,1 ; bottom row of these choices define current$choice,1 ; current row of these choices define fmt$drv,1 ; drive to do format on define fmt$tbl$ptr,2 ; pointer to current format table define save$buffer,80*2 ; save a row here define scrsiz,1 ; current screen size flag define temp,1 ; miscellaneous define temp$ptr,2 ; temporary ptr for moving tables define read$count,1 ; # of characters in saved line define top$of$stack,300 define stack,0 define sect$buf,1024 ; largest sector is 1024 end