home *** CD-ROM | disk | FTP | other *** search
- ;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