Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

508 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'LDCOPY Ver 1.1 Oct 81'
vers equ 10
; Copyright, (C) 1981
; Digital Research, Inc.
; P.O. Box 579
; Pacific Grove, CA 93950
; LDCOPY is used to generate and propagate bootable CP/M-86 systems.
; It copies a CP/M-86 Loader image (either from a disk file, or from
; the system tracks of an existing CP/M-86 system diskette) to a new
; diskette.
; The following equates will require modification for different
; diskette formats. For convienence, they are only referenced
; by a pair of data bytes near the end of the data segment.
; In addition, the skew table in the data area will need modification.
sdspt equ 26 ; number of sectors per track
sdlt equ 2 ; " of tracks for loader
; **************************
; *
; * global equates
; *
; **************************
bdosint equ 224 ;BDOS interrupt number
false equ 0
true equ not false
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
sdndisks equ 16 ; maximum number of drives
sdsecsiz equ 128 ; size of each sector
tpa equ 100h
fcbaddr equ 5ch
fcbname equ fcbaddr + 1 ;1st char of file name
fcbtype equ fcbaddr + 9 ;file type
fcbcr equ fcbaddr + 32 ;current record
cseg
jmp start
db ' COPYRIGHT (C) 1981, DIGITAL RESEARCH '
Rs 100H ; Emergency patch area
; ***********************
; *
; * program begins here
; *
; ***********************
start:
mov ax,ds
mov es,ax
mov dx,offset signon
call outmsg
cmp byte ptr .fcbname,' '
jz gl ;check for file given on command line
call getfile ;read ldr from file
jmp ps
gl: call getldr ;read ldr from 1st 2 tracks
ps: call putldr ;put ldr on " " "
jmp reboot
; ***************************
; *
; * getfile: get the file specified in command tail into ram
; *
; ***************************
getfile:
cmp byte ptr .fcbtype,' '
jnz opn
mov byte ptr .fcbtype, 'C'
mov byte ptr .fcbtype + 1,'M'
mov byte ptr .fcbtype + 2,'D'
opn:
mov dx,fcbaddr ;try to open it
call open
inc al ;255 becomes 00
jnz rdok ;ok to read if not 255
mov dx,offset nofile
call crmsg ;file not present, error and reboot
jmp reboot
rdok:
mov byte ptr .fcbcr,0 ;current record = 0
mov dx,offset loadp ;base of buffer
mov cx,maxsecs ;sector count
rdinp:
push cx
push dx ;ready for dma
call bdma ;bdos dma function
mov dx,fcbaddr ;ready for read
call dread
pop dx ;recall dma address
pop cx ;recall sector count
cmp al,1 ;check for eof
jz don
dec cx ;don't read to far
jz don
or al,al ;0 if read ok
jnz badrd
add dx,secsiz ;inc dma by sector size
jmp rdinp
don:
ret
badrd: ;read error encountered in input file
mov dx,offset badfile
call crmsg
jmp reboot
; **************************
; *
; * getldr: get CP/M loader from 1st N tracks
; *
; **************************
getldr:
mov dx,offset askget
call crmsg ;which drive is source on ?
call getchar ;must get from disk - not from memory
mov ah,al ;save ascii char
sub al,'A' ;normalize drive number
cmp al,ndisks ;valid drive?
jb getc ;skip to getc if so
call baddisk ;invalid drive number
jmp getldr ;to try again
getc:
mov gdisk,ah ;ascii drive letter for message
call sel ;to select the drive in al
call crlf
mov dx,offset getmsg
call outmsg ;make sure right drive
call getchar
cmp al,cr ;user mistake, no cr
jnz gboot
call crlf
mov rewr,0 ;set to read for getput
call getput
mov dx,offset done
call outmsg
ret
gboot: jmp reboot ;back to cp/m
; *******************************
; *
; * putldr: put CP/M loader on 1st N tracks
; *
; *******************************
putldr:
mov dx,offset askput
call crmsg ;what drive to put ldr
call getchar
cmp al,cr ;all done if cr
jz pboot ;this is normal program exit point
mov ah,al ;save ascii drive letter
sub al,'A' ;make it a number
cmp al,ndisks
jb putc
call baddisk ;invalid drive name
jmp putldr ;to try again
putc:
mov pdisk,ah ;drive letter in message
call sel ;select dest drive in al
mov dx,offset putmsg
call crmsg ;check with user for ok
call getchar
cmp al,cr ;user mistake if not cr, reboot
jnz pboot
call crlf
mov rewr,1 ;set to write for getput
call getput ;to put loader back on diskette
mov dx,offset done
call outmsg
jmp putldr ;for another put operation
pboot: jmp reboot ;back to cp/m
; ***********************
; *
; * getput: get or put loader (rewr=0 for read, 1 for write)
; * disk is already selected
; *
; ***********************
getput:
mov bx,offset loadp ;load point in ram for cp/m during LDCOPY
mov dmaddr,bx
;clear track to 00
mov track,-1 ;start with track equal -1
rwtrk: ;read or write next track
inc track ;track = track + 1
mov cx,track
cmp cx,nlt ;number of loader tracks = current track ?
jnz nxttrk ;end of this routine > 128 bytes
jmp endrw ;end of read or write
;otherwise notdone, go to next track
nxttrk:
mov cx,track
call trk ;to set track
mov sector,-1 ;counts 0, 1, 2, . . . 25
;sector incremented before read or write
rwsec: ;read or write sector
inc sector ;to next sector
mov bx,sector ;current sector
cmp bx,spt ;sectors per track
jz endtrk
;read or write sector to or from
l_5: ;current dma address
mov si,offset tran
add bx,bx ; double sector number
mov cx,[bx+si] ;xlate to physical sector
push si
push cx
call sec ;set up sector number
pop cx
pop si
mov bx,[si]
sub cx,bx ;tran(sector)-tran(0)
call multsec ;cx * sector size
add cx,dmaddr ;base of dma for this track
;+(tran(sector)-tran(0))*secsiz
call dma ;dma address set from cx
;dma address set, clear retry count
trysec: ;try to read or write current sector
Mov Cl, 00
Mov Ax, Track
Inc Ax
Cmp Ax, Nlt
Jne Normal_Write
Mov Ax, Sector
Inc Ax
Cmp Ax, Spt
Jne Normal_Write
Mov Cl, 01
Normal_Write:
or rewr,0 ;read or write?
jz tryread
;must be write
call write
jmp chkrw ;check for error returns
tryread:
call read
chkrw:
or al,al
jz rwsec
mov dx,offset errmsg
call outmsg
call getchar
cmp al,cr
jne reboot1 ;local jmp then to reboot, >128
;typed a cr, ok to ignore
call crlf
jmp rwsec
endtrk: ;end of track
mov cx,spt ;sectors per track
call multsec ;*secsiz
mov bx,dmaddr ;base dma for this track
add bx,cx
;+ spt * secsiz
mov dmaddr,bx ;ready for next track
jmp rwtrk ;for another track
endrw: ;end of read or write, return to caller
ret
reboot1:jmp reboot ;farther than 128 bytes
; *****************************************
; *
; * utility subroutines
; *
; ****************************************
;
;*****
multsec: ;cx * sector size
push dx ;return value in cx
mov ax,secsiz
mul cx
mov cx,ax
pop dx
ret
;*****
baddisk:
mov dx,offset qdisk ;bad disk name
call crmsg
ret
; **********************
; *
; * bdos subroutines
; *
; **********************
bdos: int bdosint
ret
;function numbers in cl
reset equ 0 ;warm boot
coni equ 1 ;console input
cono equ 2 ;console output
prstr equ 9 ;print string
rconb equ 10 ;read console buffer
self equ 14 ;select disk
openf equ 15 ;disk open
setdmaf equ 26 ;where data will go
dreadf equ 20 ;disk read
biosf equ 50 ;bios call
reboot:
mov al,0
call sel
call crlf
mov cl,reset
mov dl,0 ; release memory
jmp bdos
;****
getchar: ;get an upper case char into al
call getbuf ;use buffered console read
cmp conbuf+1,0 ;just a crlf?
mov al,cr
jz ex
mov al,conbuf+2 ;first char read
cmp al,'a' ;translate to upper case if lower
jb ex
cmp al,'z'
ja ex
and al,5fh ;it is lower, make upper
ex: ret
;****
getbuf:
;read console buffer
mov cl,rconb
mov dx,offset conbuf
jmp bdos
;****
putchar:
;write character from al to console
mov dl,al
mov cl,cono
jmp bdos
;****
crlf: ;send carriage return, line feed
mov al,cr
call putchar
mov al,lf
call putchar
ret
;****
crmsg: ;print message addressed by dx til zero
;with leading crlf
push dx
call crlf
pop dx ;drop thru to outmsg0
;****
outmsg:
mov cl,prstr
jmp bdos ;dx has string addr
;****
bdma: ;dx has address
mov cl,setdmaf
jmp bdos
;****
dread: ;disk read function
mov cl,dreadf
jmp bdos
;****
open: ;file open function
mov cl,openf
jmp bdos
;****
bios:
mov fnum,al ;bios function number
mov bcx,cx
mov bdx,dx
mov dx,offset(bds)
mov cl,biosf
jmp bdos
; ****************************
; *
; * bios utilities
; *
; ****************************
seldsk equ 9 ;wboot+24 for disk select
settrk equ 10 ;wboot+27 for set track function
setsec equ 11 ;wboot+30 for set sector function
setdma equ 12 ;wboot+33 for set dma address
readf equ 13 ;wboot+36 for read function
writf equ 14 ;wboot+39 for write function
sel:
;select disk given by register a
mov cl,al
mov al,seldsk
jmp bios
;****
trk: ;set up track
mov al,settrk ;offset for settrk entry
jmp bios ;gone to settrk
;****
sec: ;set up sector number
mov al,setsec
jmp bios
;****
dma: ;set dma address to value of cx
mov al,setdma
jmp bios
;****
read: ;perform read operation
mov al,readf
jmp bios
;****
write: ;perform write operaton
mov al,writf
jmp bios
; **************************
; *
; * data areas
; *
; **************************
dseg
org 0100h ; skip past page zero
;messages
signon db 'LDCOPY VERS '
db vers/10+'0','.',vers mod 10+'0','$'
askget db 'Source Drive Name $'
getmsg db 'Source On '
gdisk rs 1 ;filled in at get function
db ', Then Type Return$'
askput db 'Destination Drive Name (Or Return To Reboot) $'
putmsg db 'Destination On '
pdisk rs 1 ;filled in at put function
db ', Then Type Return$'
errmsg db 'Permanent Error, Type Return To Ignore$'
done db 'Function Complete$'
qdisk db 'Invalid Drive Name$'
nofile db 'No Source File On Disk$'
badfile db 'Source File Read Error$'
;translate table
tran dw 1,3,5,7,9,11,13,15,17,19,21,23,25
dw 2,4,6,8,10,12,14,16,18,20,22,24,26
;leave room for double density
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0 ; (64 extra bytes reserved)
; *************************
; *
; * variables
; *
; ************************
bds: ;bios data structure
fnum rb 1 ;storage for bios parameters
bcx rw 1 ;the bdos bios func puts these
bdx rw 1 ;in registers before jumping to bios
nlt dw sdlt ;number of loader tracks
spt dw sdspt ;sectors per track
ndisks db sdndisks ;number of disks
secsiz dw sdsecsiz ;sector size
maxsecs dw sdlt * sdspt ;maximum sectors to read from file
sdisk rb 1 ;selected disk for current operation
track rw 1 ;current track
rewr rb 1 ;read if 0,write if 1
sector rw 1 ;current sector
dmaddr dw 0 ;current dma address
retry rb 1 ;number of tries on this sector
conbuf db 30
rb 32 ;console buffer
;make stack on even address
loadp rs sdsecsiz*sdspt*sdlt
db 0 ; force out last data segement byte
end