home *** CD-ROM | disk | FTP | other *** search
- 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
- ;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
- ;M I S C E L L A N E O U S U S E F U L U T I L I T I E S
- ;"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
- 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
-