C************************************************ C* * C* CPMDEC--CP/M TO DEC DISK TRANSLATER * C* * C* NOTE: MUST BE COMPILED '/NOSWAP' * C* * C* PROCESSING SCHEME: * C* THE (SINGLE DENSITY) CP/M DISK IS PHYS- * C* ICALLY THE SAME AS AN RX-01 DISK. * C* THUS WE OPEN DY1: AS A NON-FILE STRUC- * C* TURED DEVICE AND READ IT WITH THE SYSTEM * C* CALL ISPFNW, DOING OUR OWN INTERLEAVING. * C* * C* RX-01 READS 64 WORD SECTORS (128 BYTES, * C* SAME AS IBM AND CP/M). THE ISPFNW CALL * C* ALLOWS READING AND WRITING ABSOLUTE * C* PHYSICAL SECTORS. * C* * C* MORE INFORMATION ON RX-01 FORMAT DISKS IS * C* IN THE DEC PERIPHERALS HANDBOOK. * C* * C* EACH DISK CONTAINS 77 TRACKS (0..76), OF * C* 26 SECTORS EACH. CP/M INTERLEAVES THE * C* SECTORS; THIS IS TAKEN CARE OF IN SUB * C* DOSEC. RX-01 USES A DIFFERENT INTERLEAVE * C* SCHEME; BUT THIS IS OF NO CONCERN TO US * C* BECAUSE ISPFNW READS ABSOLUTE PHYSICAL * C* SECTORS. * C* * C* CP/M GROUPS 8 LOGICAL SECTORS INTO A * C* CLUSTER (1K) NUMBERED 0..240. CLUSTERS * C* ARE NUMBERED SEQUENTIALLY STARTING ON * C* TRACK 2; THE DIRECTORY (2K) IS CLUSTERS * C* 0 AND 1. TRACKS 0 AND 1 ARE SYSTEM * C* TRACKS. * C* * C* EACH DIRECTORY ENTRY IS 32 BYTES: * C* 1: 0 IF ACTIVE, 0E5H ("345) INACTIVE * C* 2-9: FILE NAME * C* 10-12: FILE TYPE * C* 13: EXTENT # [0...] * C* 14-15: OF NO CONCERN TO US * C* 16: # OF SECTORS IN THIS EXTENT * C* (0..128) * C* 17-32: NUMBERS, IN ORDER USED, OF UP * C* TO 16 CLUSTERS. (IF FILE IS OVER 16K, * C* ANOTHER DIRECTORY ENTRY IS CREATED * C* WITH THE EXTENT # INCREMENTED; AND UP * C* TO 16 MORE CLUSTERS ASSIGNED). UNUSED * C* CLUSTER ENTRIES ARE 0. * C* * C* RUSS BAKKE 02-17-83 * C* * C************************************************ C PROGRAM CPMDEC C BYTE DIR(32,64),CNAME(12),DNAME(16),LBUFF(80) BYTE BITMAP(256),DBUFF(1024),MODE(6) COMMON DIR DATA DNAME/ 'D','Y','0',':',12*0/ DATA BITMAP/ 2*1,254*0/, MODE /'A','S','C','I','I',' '/ C TYPE 100 100 FORMAT (1X,'CP/M DISK READER, V1.0'// + 1X,'INSERT CP/M DISK IN DY1: AND PRESS RETURN'/) ACCEPT 104,IWANT C C OPEN CP/M DISK AS NON-FILE STRUCTURED DEVICE: CALL DSKOPN(ICHAN) C C 10 IPRINT=0 TYPE 102,MODE 102 FORMAT (/,1X,'COPY MODE IS ',6A1,/, + 1X,'ENTER NUMBER OF OPTION DESIRED:',/, + 1X,'1. DISPLAY CP/M DIRECTORY.',/, + 1X,'2. PRINT CP/M DIRECTORY.',/, + 1X,'3. COPY A FILE FROM CP/M DISK.',/, + 1X,'4. COPY ALL FILES FROM CP/M DISK TO DY0:',/, + 1X,'5. INITIALIZE A CP/M DISK.',/, + 1X,'6. DELETE A FILE FROM CP/M DISK.',/, + 1X,'7. COPY FILE TO CP/M DISK.',/, + 1X,'8. CHANGE COPY MODE.',/, + 1X,'9. QUIT.') ACCEPT 104,IWANT 104 FORMAT (I2) IF (IWANT .LT. 1 .OR. IWANT .GT. 9) GOTO 10 IF (IWANT .EQ. 1) GOTO 11 IF (IWANT .EQ. 3) GOTO 30 IF (IWANT .EQ. 4) GOTO 40 IF (IWANT .EQ. 5) GOTO 50 IF (IWANT .EQ. 6) GOTO 60 IF (IWANT .EQ. 7) GOTO 70 IF (IWANT .EQ. 8) GOTO 62 IF (IWANT .EQ. 9) GOTO 99 C C FALL THROUGH IS 2 (PRINT DIRECTORY OF CP/M DISK) IPRINT=1 C C DISPLAY DIRECTORY 11 CALL GETDIR(ICHAN) !READ DIRECTORY ITOTAL=0 C C DISPLAY DIRECTORY DO 12 I=1,80 !CLEAR LBUFF LBUFF(I) = ' ' 12 C O N T I N U E IBFPTR = 0 C DO 24 INDEX=1,64 IF (DIR(1,INDEX) .EQ. "345) GOTO 24 !EMPTY ENTRY IF (DIR(13,INDEX) .NE. 0) GOTO 24 !LATER EXTENT ISIZE = DIR(16,INDEX) IF (ISIZE .LT. 0) ISIZE=ISIZE+256 IF (ISIZE .EQ. 128) GOTO 14 !MULTIPLE EXTENTS ISIZE = (ISIZE+7)/8 GOTO 22 C C MULTIPLE EXTENT FILE; MUST GET SIZE FROM LATER EXTENTS 14 DO 16 IPTR=2,12 CNAME(IPTR-1)=DIR(IPTR,INDEX) 16 C O N T I N U E IEXT=1 18 ISIZE=0 CALL FIND (CNAME,IEXT,IENTRY) IF (IENTRY .EQ. -1) GOTO 20 !NO MORE EXTENTS ISIZE=DIR(16,IENTRY) IF (ISIZE .LT. 0) ISIZE=ISIZE+256 IF (ISIZE .NE. 128) GOTO 20 !NO MORE EXTENTS IEXT=IEXT+1 GOTO 18 C 20 ISIZE=(ISIZE+7)/8 + 16*IEXT C 22 ENCODE(16,120,LBUFF(18*IBFPTR+2)) + (DIR(J,INDEX),J=2,12),ISIZE 120 FORMAT (8A,'.',3A,I3,'K') ITOTAL=ITOTAL+ISIZE IBFPTR = IBFPTR+1 IF (IBFPTR .LE. 3) GOTO 24 C C NEED TO PRINT & CLEAR LBUFF IF (IPRINT .EQ. 0) TYPE 122,LBUFF IF (IPRINT .EQ. 1) PRINT 122,LBUFF 122 FORMAT (1X,80A1) DO 23 I=1,80 LBUFF(I) = ' ' 23 C O N T I N U E IBFPTR = 0 C 24 C O N T I N U E IF (IPRINT .EQ. 1) GOTO 25 TYPE 122,LBUFF TYPE *,'TOTAL BYTES = ',ITOTAL,'K' GOTO 10 C 25 PRINT 122,LBUFF PRINT *,'TOTAL BYTES = ',ITOTAL,'K' GOTO 10 C C COPY A FILE FROM CP/M DISK C C GET CP/M NAME 30 CALL GTCPMF(CNAME) CALL GETDIR(ICHAN) C C LOOKUP CNAME IN DISK DIR CALL FIND(CNAME,0,IENTRY) IF (IENTRY .NE. -1) GOTO 32 !OK 31 TYPE *,'FILE NOT FOUND' GOTO 10 C C GET DEC NAME & OPEN 32 CALL GETFN('OUTPUT',IDCHAN) C READ FILE AND WRITE TO DEC CALL CPYFIL(IENTRY,CNAME,ICHAN,IDCHAN,MODE(1)) C C CPYFIL CLOSES AND FREES THE CHANNEL 34 TYPE *,'COPY COMPLETED' GOTO 10 C C C COPY ALL FILES FROM CP/M DISK TO DY0: 40 TYPE *,'INSERT BLANK DEC DISK IN DY0: AND PRESS RETURN' ACCEPT 104,IWANT CALL GETDIR(ICHAN) DO 48 IENTRY=1,64 IF (DIR(1,IENTRY) .EQ. "345) GOTO 48 IF (DIR(13,IENTRY) .NE. 0) GOTO 48 DO 42 IPTR=2,12 CNAME(IPTR-1)=DIR(IPTR,IENTRY) !SAVE NAME 42 C O N T I N U E C NOW CONVERT CNAME INTO DEC NAME, IN DNAME DO 44 IPTR=1,6 IF (CNAME(IPTR) .EQ. ' ') GOTO 46 DNAME(IPTR+4) = CNAME(IPTR) 44 C O N T I N U E 46 DNAME(IPTR+4)='.' DNAME(IPTR+5) = CNAME(9) DNAME(IPTR+6) = CNAME(10) DNAME(IPTR+7) = CNAME(11) DNAME(IPTR+8) = 0 DNAME(4)=':' C TYPE 124,(CNAME(J),J=1,11),DNAME 124 FORMAT (1X,'COPYING CP/M FILE ',8A,'.',3A,' TO DEC FILE ',16A) C C NOW OPEN DEC FILE (AS CHANNEL IDCHAN) CALL DECOPN(DNAME,IDCHAN,'O') IFILE=IENTRY CALL CPYFIL(IFILE,CNAME,ICHAN,IDCHAN,MODE(1)) 48 C O N T I N U E GOTO 34 C C C INITIALIZE A CP/M DISK 50 TYPE *,'INITIALIZE--ARE YOU SURE?' ACCEPT 126,IWANT 126 FORMAT(A1) IF (IWANT .NE. 'Y') GOTO 10 C C (WRITE E5H THROUGHOUT DIRECTORY) DO 54 I=1,32 DO 52 J=1,64 DIR(I,J)="345 52 C O N T I N U E 54 C O N T I N U E 56 CALL PUTDIR(ICHAN) TYPE *,'COMPLETED' GOTO 10 C C C DELETE A CP/M FILE 60 CALL GTCPMF(CNAME) CALL ERASE(CNAME,ICHAN,ISTAT) IF (ISTAT .EQ. -1) GOTO 31 !UNSUCCESSFUL GOTO 56 !WRITE DIR & RET TO MENU C C C TOGGLE COPY MODE 62 IF (MODE(1) .EQ. 'A') GOTO 64 MODE(1) = 'A' MODE(2) = 'S' MODE(3) = 'C' MODE(4) = 'I' MODE(5) = 'I' MODE(6) = ' ' GOTO 10 C 64 MODE(1) = 'B' MODE(2) = 'I' MODE(3) = 'N' MODE(4) = 'A' MODE(5) = 'R' MODE(6) = 'Y' GOTO 10 C C C WRITE A CP/M FILE C GET DEC NAME & OPEN 70 CALL GETFN('INPUT ',IDCHAN) IDBLK=0 C GET CP/M FILE NAME CALL GTCPMF(CNAME) C C IF WE ALREADY HAVE A FILE BY THIS NAME, ERASE IT CALL ERASE(CNAME,ICHAN,ISTAT) C C NOW FOR THE HARD PART. C WE MUST READ THE CP/M DIRECTORY; MAKE A BIT MAP C (ACTUALLY BYTE MAP) OF CLUSTERS USED; CREATE A C CP/M DIRECTORY ENTRY; ASSIGN EACH CLUSTER, READ C 8*128 BYTES WITH IREADW AND WRITE THEM TO THE C CP/M DISK. C DO 72 I=1,64 IF (DIR(1,I) .EQ. "345) GOTO 72 !NOT ALLOCATED DO 71 J=17,32 IDIREN=DIR(J,I) IF (IDIREN .EQ. 0) GOTO 72 !NOT ALLOCATED IF (IDIREN .LT. 0) IDIREN = IDIREN+256 IF (IDIREN .LT.0 .OR. IDIREN .GT. 255) STOP 'MAP ERROR' BITMAP (IDIREN+1) = 1 71 C O N T I N U E 72 C O N T I N U E C C NOW FIND AN OPEN DIR ENTRY IEXT=0 73 DO 74 IENTRY=1,64 IF (DIR(1,IENTRY) .EQ. "345) GOTO 75 74 C O N T I N U E STOP 'DIRECTORY FULL' C C COPY IN FILE NAME 75 DIR(1,IENTRY)=0 DO 76 J=2,12 DIR(J,IENTRY)=CNAME(J-1) 76 C O N T I N U E DO 77 J=13,32 DIR(J,IENTRY)=0 77 C O N T I N U E IBLK=1 ISIZE=0 DIR(13,IENTRY)=IEXT C C ALLOCATE A CLUSTER 78 DO 79 ICLU=3,241 IF (BITMAP(ICLU) .EQ. 0) GOTO 80 !FOUND A FREE CLUSTER 79 C O N T I N U E STOP 'CP/M DISK FULL' C C WRITE CLUSTER NUMBER TO DIRECTORY 80 BITMAP(ICLU)=1 ICLU=ICLU-1 !0-255 NOT 1-256 DIR(IBLK+16,IENTRY)=ICLU C CONVERT CLUSTER # TO SECTOR AND TRACK ITEMP=8*ICLU ISTTRK=ITEMP/26 ISTART=ITEMP-26*ISTTRK+1 ISTTRK=ISTTRK+2 C C READ 8 SECTORS FROM DEC DISK IRET=IREADW(512,DBUFF,IDBLK,IDCHAN) IDBLK=IDBLK+2 C ERRORS ARE: C -1: EOF C -2: HARDWARE ERROR C -3: CHANNEL NOT OPEN C OR IF IRET = 256, ONLY 1 BLOCK READ IF (IRET .EQ. 256) GOTO 96 !1 BLOCK IF (IRET .GE. 0) GOTO 81 IF (IRET .EQ. -1) GOTO 97 !EOF TYPE *,'IREAD ERROR TYPE ',IRET STOP C C WRITE 8 SECTORS 81 ILIMIT=7 83 IF (MODE(1) .EQ. 'B') GOTO 93 C C FIND EOF, INSERT CTL-Z (CP/M EOF) DO 84 INDEX2=128*(ILIMIT+1),1,-1 IF (DBUFF(INDEX2) .NE. 0) GOTO 85 84 C O N T I N U E 85 IF (INDEX2 .LT. 128*(ILIMIT+1)) DBUFF(INDEX2+1) = 26 !CTL-Z C 93 DO 95 ISEC=0,ILIMIT ITEMP=ISTART+ISEC ITRK=ISTTRK IF (ITEMP .LE. 26) GOTO 94 ITEMP=ITEMP-26 ITRK=ITRK+1 94 CALL DOSEC('W',ITRK,ITEMP,DBUFF(128*ISEC+1),ICHAN) ISIZE=ISIZE+1 95 C O N T I N U E IF (IRET .EQ. 0) GOTO 97 C C NEED ANOTHER CLUSTER IBLK=IBLK+1 IF (IBLK .LE. 16) GOTO 78 C NEED A NEW EXTENT DIR(16,IENTRY)=128 !SET SECTOR COUNT IEXT=IEXT+1 TYPE *,'WORKING. . .' GOTO 73 C C ONLY 4 SECTORS READ FROM DEC FILE 96 ILIMIT=3 IRET=0 GOTO 83 C C THAT'S ALL 97 DIR(16,IENTRY)= ISIZE !SET SIZE C WRITE OUT DIRECTORY CALL PUTDIR(ICHAN) CALL ICLOSE(IDCHAN) CALL IFREEC(IDCHAN) GOTO 34 C C C CLOSE 99 CALL ICLOSE (ICHAN) CALL IFREEC (ICHAN) CALL EXIT END C SUBROUTINE DSKOPN (IDCH) C**************************************************** C* * C* OPEN FLOPPY DISK DRIVE 1 AS NON-FILE * C* STRUCTURED DEVICE; RETURN CHANNEL NO. IN IDCH. * C* * C* RUSS BAKKE 02-10-83 * C* * C**************************************************** C REAL*4 DISK1 DATA DISK1 /3RDY1 / C C FETCH HANDLER, OPEN A CHANNEL, LOOKUP DEVICE IF (IFETCH(DISK1) .NE. 0) STOP 'IFETCH ERROR + IN DSKOPN' IDCH=IGETC() IF(IDCH.LT.0) STOP' NO CHANNEL AVAILABLE' C IRET = LOOKUP(IDCH,DISK1) IF (IRET .GE. 0) GOTO 10 C C LOOKUP FAILURE TYPE *,'LOOKUP FAILURE TYPE ',IRET STOP C 10 RETURN END C SUBROUTINE GETDIR(ICHAN) C**************************************************** C* * C* READ DIRECTORY OF CP/M DISK. * C* * C* THE CP/M DISK USES TRACKS 0 AND 1 FOR SYSTEM * C* TRACKS; WE MAY IGNORE THEM. THE DIRECTORY IS * C* 2K OR 16 SECTORS, STARTING ON TRACK 2. * C* * C* RUSS BAKKE 05-06-82 * C* * C**************************************************** C BYTE DIR(32,64) COMMON DIR C DO 80 INDEX=1,16 ISECTR=INDEX CALL DOSEC('R',2,ISECTR,DIR(1,4*(ISECTR-1)+1),ICHAN) 80 C O N T I N U E RETURN END C SUBROUTINE PUTDIR(ICHAN) C**************************************************** C* * C* WRITE DIRECTORY OF CP/M DISK. * C* (SIMILAR TO GETDIR). * C* * C* RUSS BAKKE 05-25-82 * C* * C**************************************************** C BYTE DIR(32,64) COMMON DIR C DO 80 INDEX=1,16 ISECTR=INDEX CALL DOSEC('W',2,ISECTR,DIR(1,4*(ISECTR-1)+1),ICHAN) 80 C O N T I N U E RETURN END C SUBROUTINE DOSEC(RW,ITRK,ISEC,BUFF,ICHAN) C**************************************************** C* * C* READ/WRITE (RW IS DIRECTION) LOGICAL SECTOR * C* 'ISEC', TRACK 'ITRK', TO/FROM 'BUFF' (128 * C* BYTES), FROM/TO CHANNEL 'ICHAN'. * C* * C* RUSS BAKKE 05-12-82 * C* * C**************************************************** C BYTE BUFF(128),MYBUFF(130),RW INTEGER ITABLE(26) DATA ITABLE /1,7,13,19,25,5,11,17,23,3,9,15,21,2,8, + 14,20,26,6,12,18,24,4,10,16,22/ C ITABLE IS THE CP/M SECTOR INTERLEAVE TABLE (26 SECTORS PER TRACK) C PHYSICAL SECTOR # [1..26] = ITABLE(LOGICAL SECTOR # [1..26]) C IF (RW .EQ. 'W') GOTO 50 IRET=ISPFNW("377,ICHAN,ITRK,MYBUFF,ITABLE(ISEC)) C C THE ISPFNW CALL IS AS FOLLOWS: C IRET=ISPFNW(FUNC,ICHAN,ITRK,BUFF,SECTOR) C FUNC="377 FOR READ, "376 FOR WRITE C ICHAN=CHANNEL #, FROM LOOKUP C ITRK=ABSOLUTE PHYSICAL TRACK #, 0..76 C SECTOR=ABSOLUTE PHYSICAL SECTOR #, 1..26 C BUFF=128 BYTE BUFFER C IRET RETURNS: C 0 NORMAL C 1 EOF C 2 HARDWARE ERROR C 3 CHANNEL NOT OPEN C IF (IRET .EQ. 0) GOTO 40 30 TYPE 100,RW,ITRK,ISEC 100 FORMAT (1X,A,2X,'TRACK: ',I3,' LOG. SECTOR: ',I3) IF (IRET .EQ. 1) STOP 'CHANNEL EOF IN DOSEC' IF (IRET .EQ. 2) STOP 'HARDWARE ERROR IN DOSEC' IF (IRET .EQ. 3) STOP 'CHANNEL NOT OPEN IN DOSEC' STOP 'ERROR IN DOSEC' C C WE MUST READ INTO 130 BYTE BUFFER, BECAUSE ISPFNW READS C LEADING 0 WORD INTO BUFFER. (THIS IS DOCUMENTED IN THE C SOFTWARE SUPPORT MANUAL BUT NOT IN THE PROGRAMMER'S REFERENCE). 40 DO 45 I=1,128 BUFF(I) = MYBUFF(I+2) 45 C O N T I N U E RETURN C C WRITING 50 DO 55 I=1,128 MYBUFF(I+2)=BUFF(I) 55 C O N T I N U E MYBUFF(1)=0 MYBUFF(2)=0 C IRET=ISPFNW("376,ICHAN,ITRK,MYBUFF,ITABLE(ISEC)) IF (IRET .NE. 0) GOTO 30 RETURN END C SUBROUTINE GTCPMF(CNAME) C**************************************************** C* * C* GET CP/M NAME, AND FORMAT INTO CNAME. * C* * C* RUSS BAKKE 05-05-82 * C* * C**************************************************** C BYTE CNAME(12),TYPE(3) C TYPE *,'ENTER CP/M FILE NAME:' ACCEPT 110,CNAME 110 FORMAT(12A1) C C NOW REFORMAT TO 8 CHAR NAME & 3 CHAR TYPE C FIND '.' DO 10 INDEX=1,12 IF (CNAME(INDEX) .EQ. '.') GOTO 20 10 C O N T I N U E GOTO 90 !NO '.', PASS WHAT WE GOT C C EXTRACT FILE TYPE 20 DO 30 INDEX2=1,3 TYPE(INDEX2) = CNAME(INDEX+INDEX2) 30 C O N T I N U E C FILL CNAME FROM PERIOD THROUGH 12 WITH SPACES DO 40 INDEX2=INDEX,12 CNAME(INDEX2) = ' ' 40 C O N T I N U E C COPY TYPE INTO CNAME DO 50 INDEX2=1,3 IF (TYPE(INDEX2) .EQ. 0) GOTO 90 CNAME(8+INDEX2) = TYPE(INDEX2) 50 C O N T I N U E 90 RETURN END C SUBROUTINE GETFN(PROMPT,IDCHAN) C******************************************************** C* * C* INPUT A FILE NAME AND OPEN A DEC FILE. RETURN THE * C* CHANNEL NUMBER IN IDCHAN. * C* * C* RUSS BAKKE 05-11-82 * C* * C******************************************************** C LOGICAL*1 FNAME(16),PROMPT(6) C 5 WRITE (7,103) PROMPT 103 FORMAT (1X,6A1,' FILE SPECIFICATION?') C 8 READ (5,105) FNAME 105 FORMAT (16A1) FNAME(16)=0 C CHECK TO AVOID NULL FILE NAME IF (FNAME(1) .EQ. ' ') GOTO 70 IF (FNAME(3) .EQ. ':' .AND. FNAME(4) .EQ. ' ') GOTO 70 IF (FNAME(4) .EQ. ':' .AND. FNAME(5) .EQ. ' ') GOTO 70 C CALL DECOPN(FNAME,IDCHAN,PROMPT(1)) RETURN C 70 TYPE *,'ERROR IN FILE SPECIFICATION, TRY AGAIN' GOTO 5 END C SUBROUTINE DECOPN(FNAME,IDCHAN,RW) C************************************************** C* * C* OPEN A DEC FILE FNAME, RETURNING CHANNEL * C* NUMBER IN IDCHAN. RW IS READ/WRITE. * C* * C* RUSS BAKKE 05-25-82 * C* * C************************************************** C BYTE FNAME(16),RW REAL*8 FSPEC C C CONVERT FNAME TO RADIX 50 C C REFORMAT AS DL0FNAME_TYP C FIRST FIND ':' DO 20 I=1,16 IF (FNAME(I) .EQ. ':') GOTO 25 20 C O N T I N U E C NO ':' FOUND, INSERT 'DL0' DO 22 I=13,1,-1 FNAME(I+3)=FNAME(I) 22 C O N T I N U E FNAME(1)='D' FNAME(2)='L' FNAME(3)='0' GOTO 30 C C EAT THE ':' 25 DO 28 J=I,15 FNAME(J)=FNAME(J+1) 28 C O N T I N U E FNAME(16)=' ' C C NOW FIND '.' 30 DO 35 I=1,16 IF (FNAME(I) .EQ. '.') GOTO 36 35 C O N T I N U E C NO '.' FOUND GOTO 40 C C MOVE TYPE TO LAST 3 CHARS 36 FNAME(16)=FNAME(I+3) FNAME(15)=FNAME(I+2) FNAME(14)=FNAME(I+1) FNAME(10)=FNAME(14) FNAME(11)=FNAME(15) FNAME(12)=FNAME(16) C C BLANK FILL IF (I .GE. 10) GOTO 40 DO 38 J=I,9 FNAME(J)=' ' 38 C O N T I N U E C C CHANGE ALL ILLEGAL CHARACTERS TO '9' 40 DO 42 INDEX=4,12 IF (FNAME(INDEX) .GE. 'A' .AND. + FNAME(INDEX) .LE. 'Z') GOTO 42 !OK IF (FNAME(INDEX) .GE. '0' .AND. + FNAME(INDEX) .LE. '9') GOTO 42 !OK IF (FNAME(INDEX) .EQ. ' ' .OR. + FNAME(INDEX) .EQ. '.') GOTO 42 !OK FNAME(INDEX) = '9' 42 C O N T I N U E C C NOW CONVERT TO RADIX 50 IDUM=IRAD50(12,FNAME,FSPEC) C C GET A CHANNEL IDCHAN=IGETC() IF(IDCHAN .LT. 0) STOP' NO CHANNEL AVAILABLE' C IF (RW .EQ. 'O') GOTO 50 IRET = LOOKUP(IDCHAN,FSPEC) IF (IRET .GE. 0) GOTO 90 C C LOOKUP FAILURE--TYPES ARE: C -1: CHANNEL ALREADY OPEN C -2: SPECIFIED FILE NOT FOUND C -3: DEVICE IN USE C -4: TAPE ONLY IF (IRET .NE. -2) GOTO 45 STOP 'DEC FILE NOT FOUND' C 45 TYPE *,'LOOKUP FAILURE TYPE ',IRET STOP C C WRITE FILE MUST USE IENTER NOT LOOKUP 50 IRET=IENTER(IDCHAN,FSPEC,-1) IF (IRET .GE. 0) GOTO 90 C IENTER ERRORS ARE: C -1: CHANNEL ALREADY OPEN C -2: NO SPACE AVAILABLE C -3: DEVICE IN USE C -4: FILE EXISTS AND IS PROTECTED C -5: CASSETTE ONLY TYPE *,'IENTER FAILURE TYPE ',IRET STOP C 90 RETURN END C SUBROUTINE FIND(CNAME,EXT,IENTRY) C**************************************************** C* * C* FIND CP/M FILE NAMED CNAME IN DIRECTORY (IN * C* DIR, PASSED IN COMMON), EXTENT 'EXT'; RETURN * C* DIRECTORY ENTRY NUMBER IN IENTRY. * C* * C* RUSS BAKKE 05-11-82 * C* * C**************************************************** C BYTE DIR(32,64),CNAME(12) INTEGER EXT COMMON DIR C DO 44 IENTRY=1,64 IF (DIR(1,IENTRY) .EQ. "345) GOTO 44 !EMPTY, SKIP DO 42 ICHAR=2,12 IF (DIR(ICHAR,IENTRY) .NE. CNAME(ICHAR-1)) GOTO 44 42 C O N T I N U E C FALL THROUGH MEANS A MATCH IF (DIR(13,IENTRY) .EQ. EXT) GOTO 90 !FOUND IT C 44 C O N T I N U E C FALL THROUGH MEANS NO MATCH FOUND IENTRY=-1 90 RETURN END C SUBROUTINE CPYFIL(IENTRY,CNAME,ICHAN,IDCHAN,MODE) C************************************************* C* * C* COPY CP/M FILE (ICHAN) TO DEC FILE (IDCHAN). * C* CP/M DIRECTORY ENTRY IS 'IENTRY'. * C* MODE IS "BINARY" OR "ASCII ". * C* CLOSE DEC CHANNEL (IDCHAN) WHEN FINISHED. * C* * C* RUSS BAKKE 02-02-83 * C* * C************************************************* C BYTE DIR(32,64),DBUFF(1024),CNAME(12),MODE COMMON DIR C IDBLK=0 !DISK BLOCK TO WRITE IEXT=0 !FIRST EXTENT C 8 ICLU=1 !FIRST CLUSTER ISIZE=DIR(16,IENTRY) IF (ISIZE .LT. 0) ISIZE=ISIZE+256 IF (ISIZE .EQ. 128) ISIZE=129 !DON'T LET IT COUNT OUT 10 IF (ISIZE .EQ. 0) GOTO 90 IBLK=DIR(16+ICLU,IENTRY) IF (IBLK .LT. 0) IBLK=IBLK+256 C (PROBLEM HERE, IS WE GET SIGN EXTENSION ON READING BYTE C VALUE INTO INTEGER VARIABLE) IF (IBLK .EQ. 0) GOTO 90 !THAT'S ALL C C NEED TO READ 'IBLK' 1K CLUSTER (8 SECTORS) C C CONVERT IBLK TO STARTING SECTOR # AND TRACK # C MULTIPLY BY 8 AND REDUCE MODULO 26 ITEMP=8*IBLK ISTTRK=ITEMP/26 ISTART=ITEMP-26*ISTTRK+1 ISTTRK=ISTTRK+2 !SKIP SYSTEM TRACKS C DO 60 ISECTR=0,7 ITEMP=ISTART+ISECTR ITRK=ISTTRK IF (ITEMP .LE. 26) GOTO 30 ITEMP=ITEMP-26 ITRK=ITRK+1 30 CALL DOSEC('R',ITRK,ITEMP,DBUFF(128*ISECTR+1),ICHAN) ISIZE=ISIZE-1 IF (ISIZE .LE. 0) GOTO 80 60 C O N T I N U E C C NOW WRITE BUFF TO IDCHAN C SEARCH BUFFER FOR CTL-Z (EOF) UNLESS BINARY MODE. IF (MODE .EQ. 'B') GOTO 70 62 DO 65 INDEX=1,1024 IF (DBUFF(INDEX) .EQ. 26) GOTO 75 65 C O N T I N U E C 70 IRET=IWRITW(512,DBUFF,IDBLK,IDCHAN) IDBLK=IDBLK+2 C IWRITW RETURNS: C -1: EOF C -2: HARDWARE ERROR C -3: CHANNEL NOT OPEN C IF (IRET .LT. 0) GOTO 95 ICLU=ICLU+1 IF (ICLU .LT. 17) GOTO 10 !NEXT SEGMENT C C NOW SEE IF WE HAVE ANOTHER EXTENT IEXT=IEXT+1 CALL FIND(CNAME,IEXT,IENTRY) IF (IENTRY .NE. -1) GOTO 8 !NEXT EXTENT GOTO 90 C C HAVE EOF AT "INDEX" 75 DO 78 INDEX1=INDEX,1024 DBUFF(INDEX1)=0 !NULL FILL FOR DEC 78 C O N T I N U E IF (INDEX .LE. 512) GOTO 83 GOTO 84 C C HAVE PARTIAL BUFFER--WRITE IT OUT. 80 IF (MODE .EQ. 'A') GOTO 62 DO 82 IPTR=128*(ISECTR+1)+1,1024 DBUFF(IPTR)=0 82 C O N T I N U E IF (ISECTR .GT. 3) GOTO 84 83 IRET=IWRITW(256,DBUFF,IDBLK,IDCHAN) IDBLK=1 GOTO 86 C 84 IRET=IWRITW(512,DBUFF,IDBLK,IDCHAN) IDBLK=2 86 IF (IRET .LT. 0) GOTO 95 90 IF (IDBLK .EQ. 0) GOTO 94 CALL ICLOSE(IDCHAN) 92 CALL IFREEC(IDCHAN) RETURN C C FILE OF 0 LENGTH, EAT IT. 94 CALL PURGE(IDCHAN) GOTO 92 C 95 TYPE *,'WRITE ERROR IN CPYFIL, TYPE ',IRET STOP END C SUBROUTINE ERASE (CNAME,ICHAN,ISTAT) C**************************************************** C* * C* ERASE CP/M FILE 'CNAME' VIA CHANNEL ICHAN. * C* RET ISTAT=0 IF OK, ELSE -1. * C* * C* RUSS BAKKE 12-07-82 * C* * C**************************************************** C BYTE DIR(32,64),CNAME(12) COMMON DIR C CALL GETDIR(ICHAN) CALL FIND(CNAME,0,IENTRY) IF (IENTRY .EQ. -1) GOTO 50 !UNSUCCESSFUL IEXT=0 10 DIR (1,IENTRY)="345 !SET EMPTY IEXT=IEXT+1 CALL FIND(CNAME,IEXT,IENTRY) !MORE EXTENTS? IF (IENTRY .NE. -1) GOTO 10 !YES ISTAT=0 RETURN C 50 ISTAT=-1 !UNSUCCESSFUL RETURN END