C************************************************
C*                                              *
C*  CPMD2--CP/M TO DEC DISK TRANSLATER          *
C*                                              *
C*  NOTE:  MUST BE COMPILED '/NOSWAP'           *
C*                                              *
C*  THIS IS A SHORT VERSION OF CPMDEC, FOR USE  *
C*    WHERE THE PROGRAM MUST BE HAND ENTERED.   *
C*    TYPE THIS FILE INTO YOUR DEC SYSTEM,      *
C*    OMITTING THE COMMENTS.  THEN COMPILE IT,  *
C*    THE RESULT WILL BE A SHORT VERSION WHICH  *
C*    WILL ONLY READ CPMDEC FROM THE DISK.      *
C*    YOU MAY THEN COMPILE CPMDEC FOR LATER USE.*
C*                                              *
C*  RUSS BAKKE                02-18-83          *
C*                                              *
C************************************************
C
	PROGRAM CPMD2
C
	BYTE DIR(32,64),CNAME(12),DNAME(12)
	COMMON DIR
	DATA DNAME/ 'D','K','0','C','P','M','D','E','C',
     +	'F','O','R'/
	DATA CNAME/ 'C','P','M','D','E','C',' ',' ','F','O','R',0/
C
	TYPE 100
  100	FORMAT (1X,'CP/M TRANSLATER BOOTSTRAP, V1.0'//
     +	1X,'INSERT CP/M DISK IN DY1: AND PRESS RETURN'/)
	ACCEPT 104,IWANT
  104	FORMAT (1A1)
C
C OPEN CP/M DISK AS NON-FILE STRUCTURED DEVICE:
	CALL DSKOPN(ICHAN)
	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 90
C
C  GET DEC NAME & OPEN
   32	CALL DECOPN(DNAME,IDCHAN)
C  READ FILE AND WRITE TO DEC
	CALL CPYFIL(IENTRY,CNAME,ICHAN,IDCHAN)
C
C  CLOSE
   90	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(2,ISECTR,DIR(1,4*(ISECTR-1)+1),ICHAN)
   80	C O N T I N U E
	RETURN
	END
C
	SUBROUTINE DOSEC(ITRK,ISEC,BUFF,ICHAN)
C****************************************************
C*                                                  *
C*  READ LOGICAL SECTOR 'ISEC', TRACK 'ITRK', TO    *
C*   'BUFF' (128 BYTES), FROM CHANNEL 'ICHAN'.      *
C*                                                  *
C*  RUSS BAKKE                   02-18-83           *
C*                                                  *
C****************************************************
C
	BYTE BUFF(128),MYBUFF(130)
	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
	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
	END
C
	SUBROUTINE DECOPN(FNAME,IDCHAN)
C**************************************************
C*                                                *
C*  OPEN A DEC FILE FNAME, RETURNING CHANNEL      *
C*  NUMBER IN IDCHAN.                             *
C*                                                *
C*  RUSS BAKKE               02-18-83             *
C*                                                *
C**************************************************
C
	BYTE FNAME(12)
	REAL*8 FSPEC
C
C  GET A CHANNEL
	IDCHAN=IGETC()
	IF(IDCHAN .LT. 0) STOP' NO CHANNEL AVAILABLE'
C
C  CONVERT FNAME TO RADIX 50
	IDUM=IRAD50(12,FNAME,FSPEC)
C
	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)
C*************************************************
C*                                               *
C*  COPY CP/M FILE (ICHAN) TO DEC FILE (IDCHAN). *
C*  CP/M DIRECTORY ENTRY IS 'IENTRY'.            *
C*  CLOSE DEC CHANNEL (IDCHAN) WHEN FINISHED.    *
C*                                               *
C*  RUSS BAKKE                      02-18-83     *
C*                                               *
C*************************************************
C
	BYTE DIR(32,64),DBUFF(1024),CNAME(12)
	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(ITRK,ITEMP,DBUFF(128*ISECTR+1),ICHAN)
	ISIZE=ISIZE-1
	IF (ISIZE .LE. 0) GOTO 62
   60	C O N T I N U E
C
C  NOW WRITE BUFF TO IDCHAN
C  SEARCH BUFFER FOR CTL-Z (EOF)
   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
   78	C O N T I N U E
	IF (INDEX .GT. 512) GOTO 84
C
C  HAVE PARTIAL BUFFER--WRITE IT OUT.
   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
