; move comments over 1 tab	C/;/	;/
; move back 1 tab        	C/	;/;/
; find leading spaces and convert to tabs	4y5y6y
; get 24 leading	1,$c/^                        /			/4p
;      16        	1,$c/^                /		/5p
;       8         	1,$c/^        /	/6p
;
$MACRO moveb from to nbytes
?? 4
        mov #@1,r0
        mov #@2,r1
        mov #@3,r2
#@4=.
        movb (r0)+,(r1)+
        sob r2,#@4
$ENDM
/
        PROGRAM REC
        .title rec
        .enabl lc
        .psect rec
        .enabl ama
	.nlist sym
        .mcall qiow$,dir$,fdop$r,finit$,fsrsz$,nmblk$,fdbk$r
        .mcall fdat$r,fdrc$r,write$,wait$,close$,exst$s,mrkt$s
        .mcall cmkt$s,alun$

        flun=2 
        fev=20. 
        bad=4
        good=1

begin:   
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
puic:   .word 0                         ;owner uic
uic:    .word 0                         ;uic of file
len:    .word 0                         ;length of file name
name:   .blkb 16.*3+20                  ;file name is input here
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buf:    .blkb 16.                       ;get packet buffer
code:   .word                           ; is 16 bytes,2 bytes=code,2bytes=cksum
sum:    .word 0                         ; this is the checksum
        .blkb 6.                        ;safety - so we don't clobber anything
ack:    .byte 'A,'A                     ;ack/nack buffer (goes back)

        .byte 0                         ;abort code (odd alligned)
abrt:   .byte 'F                        ;the code is followed by 2 byte error
acode:  .word 0                         ;word (word alligned for mov instr)
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
ios:    .word 0,0                       ;2 word qio status block
i:      .word 0                         ;index
j:      .word 0                         ;index
chk:    .word 0                         ;for computing checksum
p:      .word ffdb                      ;pointer into fdb/block buffer
fsize:  .word 0				;size of the file in blocks
bnum:   .word 0,0                       ;block number double prec
bios:   .word 0,0                       ;block i/o status block
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
alunb:  alun$ 1,CM,0
kill:   qiow$ io.kil ,1                   ;kill i/o
in:     qiow$ io.ral ,1,7,,ios,,<buf,20.> ;input qio
insy:   qiow$ io.ral ,1,7,,ios,,<buf,1>   ;input qio (sync)
out:    qiow$ io.wal ,1,7,,ios,,<ack,1,0> ;output qio
aout:   qiow$ io.wal ,1,7,,ios,,<abrt,3,0>;output qio for abort
osync:  qiow$ io.wal ,1,7,,ios,,<osy,4,0>   ;output qio
osy:    .ascii /RRRR/
;;;;f1:     qiow$  sf.smc,1,7,,ios,,<p1,s1>   ;flush input (not used now)
;;;;
;;;;p1:     .byte tc.tbf,1
;;;;	s1=.-p1
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
        CSI                             ;init csi buffers ([222,7]file.mac
ffdb:   FDB flun                        ;fdb allocated, pointing to csi dsdp
ffdb1:  FDB flun			;where we read it into
        .blkw 20.                       ;safety
block:  .blkb   512.                    ;block buffer
dfnb:   nmblk$ ,,,sy                    ;defaults to current uic, and sy
         
;     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
start:     
        finit$ 

        dir$ #alunb                     ;assign lun to communications line

        mov #begin,r0                   ;for debugging
        mov #ffdb,r1
        mov #p,r2
        mov #ios,r3
        mov #in-buf,r4
;	iot 
         
         
         
;        nop 
        nop 
;        dir$ #f1                        ;flush typeahead
        call sync
        dir$ #osync
        call getfdb                     ;receive the fdb part
        call getnam                     ;receive the file name
         
        mov #ffdb,r0                    ;now prepare the fdb
        mov #ffdb1,r1                   ;from the orig file
        mov f.efbk+2(r1),fsize          ;get file size
        IF f.ffby(r1) = #0 AND fsize GT #0      ;eof might be at end of block
	        dec fsize
        FI
        mov fsize,f.cntg(r0)            ;set size to create
         
        IF len LT #0                   ;store contigous flag in sign bit
            neg len                     ; of the length
        ELSE 
            neg f.cntg(r0)              ;and make this non contigous
        FI 
         
        fdat$r #ffdb,#r.fix,,#512.      ;set up for
        fdrc$r #ffdb,#fd.rwm            ;block i/o
        fdbk$r #ffdb,#block,#512.       ;until we've coppied in everything
         
         
        mov uic,r1
;       call .wdfui                     ;set default uic to what came in
        mov @#.fsrpt,r0                 ;do this ourselves so we can use
        mov r1,102(r0)                  ;fcs res
        clr 24(r0)                      ;this is what module rwfsr2 does
                                        ;disassembled it.

        FILE #name,len                  ;len contains file length (set csi blk)
        IF CS
	        mov #-54.,acode
	        clrb acode
	        jmp abort
        FI


        OPEN #ffdb,wrt                  ;open for write
        IF CS
	        mov f.err(r0),acode
	        jmp abort
        FI

        call getfil
        call closeit
         
         
;        iot
        exst$s  #good
         
         
;+
; closeit - close file, restoring the original attributes
;
;-
closeit: 
        moveb #ffdb1,#ffdb,#7*2		;restore first 7 words of fdb
        mov fsize,ffdb+f.hibk+2         ;but correctly set size
        mov puic,r1                     ;get owner uic
        call .wfown                     ;and set fsr owner word
        close$ #ffdb                    ;
        rts pc
         
;+
; getfil - get the file block at a time
;
;          calls getblk repeatedly until the last block
;          which we know the length of since it was in the fdb we
;          received.
;-
getfil:  
        LOOP for bnum+2 = #1 TO fsize
            call getblk
            write$ #ffdb,#block,#512.,#bnum,#fev,#bios
            wait$ 
            IF bios NE #1
            mov bios,acode
            jmp abort
            FI

            IF ffdb+f.err NE #1
            mov ffdb+f.err,acode
            jmp abort
            FI

        NEXT bnum+2
        rts pc
;+
; getfdb - get the fdb in 7 packets into name:
;          when all done ffdb has 7*16 bytes = 112 bytes (at least enough)
;          more than an entire fdb is probably transfered (100 is all of it)
;-
getfdb:  
        mov #ffdb1,p                    ;point at output
        LOOP FOR j = #1 TO #7
            call getp                   ;get a packet in
            moveb #buf,p,#16.           ;move in the 16 data bytes
            add #16.,p                  ;update to next area coming in
        NEXT j
        rts pc
;+
; getnam - get the file name in 3 packets into name:
;
;
;-
getnam:  
         
        mov #puic,p                 ;point at output
        LOOP FOR j = #1 TO #3
            call getp               ;get a packet in
            moveb #buf,p,#16.       ;move in the 16 data bytes
            add #16.,p              ;update to next area coming in
        NEXT j
        rts pc
         
;+
; getblk - get a block of data
;          does it in 32 packets
;
;-
getblk:  
         
        mov #block,p                ;point at output
        LOOP FOR j = #1 TO #32.
            call getp               ;get a packet in
            moveb #buf,p,#16.       ;move in the 16 data bytes
            add #16.,p              ;update to next area coming in
        NEXT j
        rts pc
         
         
         
getp:        
        DO FOREVER
            dir$ #in
l1:         clr chk
            LOOP for i  = #buf THRU #buf+17. STEP #2
                add @i,chk
            NEXT i
                 
            IF chk =  sum
                movb #'A,ack
                BREAK                   ;its ok, so done
            ELSE 
                clrb ack
	        dir$ #out
            FI 
        OD 
        dir$ #out
l2:      
        return 
         
;+
; abort - send abort code and abort error word back and exit
; user sets acode to a number then jumps here.
;-
abort:  dir$ #aout
        close$ #ffdb
        exst$s #bad

;+
; sync  -  monitor the line until 4 'S s come in
;          don't have to be priv'd this way
;-
sync:
        mrkt$s ,#5,#2,#timout            ;marktime for ast
        clr r2
        DO FOREVER
	        clrb buf
	        dir$ #insy
                IFB buf = #'S
		        inc r2
	        ELSE
		        clr r2
	        FI
	        BREAK IF r2 GE #4
        OD
        cmkt$s
        rts pc


timout:
        dir$ #kill
        exst$s #bad



        fsrsz$   1

        .end start
