home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
NSTAR
/
PUTUSR.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
7KB
|
315 lines
;PUTUSR.ASM v1.00 as of 12-15-83
;Written by S. Kluger and placed into the public domain.
;Please see PUTUSR.DOC for description
;
dcomof equ 16*3 ;offset to BIOS DCOM routine
bios equ 1 ;BIOS vector location
bdos equ 5 ;BDOS entry point
usero equ 700h ;user offset from BIOS
dbuf equ 80h ;default buffer
conin equ 1 ;BDOS console in
print equ 9 ;BDOS print string
fopen equ 15 ;BDOS open file
fread equ 20 ;BDOS read sequential
stdma equ 26 ;BDOS set DMA
;
cr equ 0dh
lf equ 0ah
;
org 100h
;
; Program entry point. Set up local stack.
;
start: lxi sp,stack
call banner ;say who we are
call ckcpm ;check CP/M, ret only if ok
call getidr ;ask for input drive
call loadhx ;load hex file
call xlhex ;translate HEX to binary
next: call savusr ;write user to disk
jz next ;yes, more
rst 0 ;fast way out
;
; BANNER routine. Announce our presence.
;
banner: lxi d,baner
string: mvi c,print
jmp bdos
;
; CKCPM routine. Set up pointers and check for N* CP/M
;
ckcpm: lhld bdos+1 ;get BDOS pointer
mvi l,0 ;point to OEM code
mov a,m ;get first byte
cpi 0e3h
jnz barfc ;complain if not N*
inx h
mov a,m
cpi 16h
jz cpmok ;continue if ok
barfc: lxi d,mbarfc
call string
rst 0 ;warm boot
;
cpmok: lhld bios ;get BIOS vector
lxi d,dcomof ;DCOM vector offset
dad d ;DCOM addr now in HL
shld dcom+1 ;set address
mov a,m ;let's see if the...
cpi 0c3h ;...BIOS is still ok
jnz barfc ;no, complain
ret
;
; GETIDR routine - get input drive letter A..P
;
getidr: lxi d,mindr ;display prompt
call getdr ;get A..P
ani 0fh ;make 1..16
sta fcb ;save drive in FCB
ret
;
; LOADHX routine. Does the following:
; 1. open USER.HEX
; 2. load file into RAM, translate to binary
;
loadhx: call ack ;acknowledge
lxi d,fcb ;let's open the file
push d ;save fcb
mvi c,fopen
call bdos
inr a
jz nofile ;complain of error
lxi h,hbuf ;set dma buffer
shld hptr ;save buffer ptr
xchg
mvi c,stdma
call bdos
pop d ;get fcb
push d
mvi c,fread
call bdos ;read a sector
ora a
jnz inerr ;initial read error
lloop: lxi d,80h ;increment hex buffer
lhld hptr
dad d
shld hptr
xchg
mvi c,stdma
call bdos
pop d ;get fcb
push d ;save it
mvi c,fread
call bdos ;read next
ora a ;if no error...
jz lloop ;...then decode and load next
pop d ;clean up stack
ret ;else done (hopefully)
;
; XLHEX - translate ASCII chars into binary
;
xlhex: lxi h,buffer ;hl=binary buffer
push h ;save it
lxi b,200h ;512 bytes to zero
zerbuf: mvi m,0
inx h
dcx b
mov a,b
ora c
jnz zerbuf
xchg
pop h
newln: ldax d ;get next byte
cpi ':' ;separator?
inx d ;point ot next
jnz newln ;loop until : found
push d
lxi d,hbuf
mov a,h
cmp d
jnc toobig
pop d
mvi c,0 ;zero checksum
call get2 ;get 2 nybbles
ora a ;if zero
rz ;then done.
mov b,a ;save count
push h ;save buffer
mvi h,3 ;6 bytes to skip
adsk: call get2 ;get byte
dcr h
jnz adsk
pop h ;now we get serious...
code: call get2 ;get next
mov m,a
inx h
dcr b
jnz code
call get2 ;get checksum
mov a,c
ora a
jz newln ;loop if ok
lxi d,mcksm ;checksum error
call string
rst 0
;
; SAVUSR routine - save user to disk and
; ask for more saves.
;
savusr: lxi d,modrv ;display prompt
call getdr ;get A..P
ani 0fh
ori 80h ;specify double density
push psw
call ack
pop psw
;
; The following is register preparation for the DCOM
; routine. I call it DCOM because it is very similar to
; the N* DOS DCOM routine. the parameters are:
; B=track C=density/drive
; D=sector E=command
; A=# of sect HL=buffer addr
; For more info, read the comments in DIRDUMP.ASM
;
mov c,a ;place drive/density in C
mvi a,1 ;1 (one) N* sector
mvi e,0 ;write command
mvi d,8 ;sector
mvi b,0 ;track
lxi h,buffer ;binary code buffer
dcom: call 0 ;filled at startup
lxi d,mfcom ;say finished
call string
mvi c,conin ;get response
call bdos
ani 5fh ;make caps
cpi 'Y'
ret
;
; UTILITY SUBROUTINES
;
; GETDR - get drive letter in A, complain if invalid.
;
getdr: call string
agn: mvi c,conin
call bdos ;get response character
ani 5fh ;make caps
cpi 'A'
jc invdr ;invalid drive
cpi 'P'
rc ;return if ok
invdr: lxi d,minvdr
call string
jmp agn
;
; GET2 - get 2 nybbles into A
; DE=pointer, save all reg
; ret with DE advanced and cksum updated
;
get2: push b ;save checksum & count
ldax d ;get hi nybble
cpi 'A'
jc nhx1
sui 7
nhx1: ani 0fh
ral
ral
ral
ral
mov b,a
inx d
ldax d
cpi 'A'
jc nhx2
sui 7
nhx2: ani 0fh
ora b
inx d
pop b
push psw
add c
mov c,a
pop psw
ret
;
; ACK routine - wait for RETURN
;
ack: lxi d,mack
call string
ackl: mvi c,conin
call bdos
cpi cr
jnz ackl
ret
;
; NOFILE - file not found
;
nofile: lxi d,mnofil
call string
rst 0
;
; INERR - empty file maybe?
;
inerr: lxi d,minerr
call string
rst 0
;
; TOOBIG - USER area is over 512 bytes
;
toobig: lxi d,mbig
call string
rst 0
;
; MESSAGES FOLLOW
;
baner: db cr,lf
db 'PUTUSR v1.00 by S. Kluger',cr,lf
db 'Any response of CONTROL-C aborts.',cr,lf,lf,'$'
;
mbarfc: db cr,lf,7
db 'ERROR - CP/M cannot be identified as '
db 'North Star CP/M - ABORTING',cr,lf,lf,'$'
;
mindr: db cr,lf
db 'Please enter drive letter of the drive containing',cr,lf
db 'the file USER.HEX (A..P) :$'
;
modrv: db cr,lf
db 'USER file in RAM now, please enter drive letter',cr,lf
db 'of the output drive (A..P):$'
;
mfcom: db cr,lf,lf
db 'SAVE COMPLETED.',cr,lf
db 'Do you wish to save USER to another disk (Y/N) ? $'
;
minvdr: db cr,lf,lf,7
db 'Invalid drive. Drive letter must be A..P.',cr,lf
db 'Please try again (A..P) :$'
;
mnofil: db cr,lf,lf,7
db 'ERROR - file USER.HEX not found on disk!',cr,lf,lf,'$'
;
minerr: db cr,lf,lf,7
db 'ERROR while reading USER.HEX - file empty?',cr,lf,lf,'$'
;
mcksm: db cr,lf,lf,7
db 'CHECKSUM error in USER.HEX',cr,lf,lf,'$'
;
mbig: db cr,lf,lf,7
db 'ERROR - USER area > 512 bytes!',cr,lf,lf,'$'
;
mack: db cr,lf
db 'MOUNT DISK AND PRESS RETURN WHEN READY$'
;
hptr: dw 0
;
fcb: db 0,'USER HEX',0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0
;
ds 48 ;some stack space
stack equ $
buffer equ $
hbuf equ $+512
end