Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,508 @@
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