mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-27 02:14:19 +00:00
Upload
Digital Research
This commit is contained in:
508
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCOPY.A86
Normal file
508
CPM OPERATING SYSTEMS/CPM 86/CPM 86 1.1 SOURCE/LDCOPY.A86
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user