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 / BDSC / BDSC-4 / UCSDTRAN.C < prev    next >
Text File  |  2000-06-30  |  15KB  |  577 lines

  1. /*********************************************************************
  2. *             ucsdtran  -- ucsd to cp/m transfer                     *
  3. **********************************************************************
  4. *     Copyright (c) 1983     Ben Goldfarb, Orlando, FL               *
  5. *            All rights reserved                     *
  6. *                                     *
  7. *     Permission is hereby granted to copy and distribute all parts  *
  8. *     of this software program and associated documents for any      *
  9. *     non-commercial purpose.  Any use of this material for          *
  10. *     commercial advantage without prior written consent of          *
  11. *     the author is prohibited.                                      *
  12. **********************************************************************
  13. *     This program is designed to read files from a 8" (3740) floppy *
  14. *     disk that has been formatted and written by a UCSD Pascal      *
  15. *     System and write them to files on the CP/M system.  Following  *
  16. *     is the sequence of actions:                     *
  17. *         o  Get drive designation for UCSD disk & set up drives     *
  18. *         o  Read and print UCSD disk directory                      *
  19. *         o  Get filename of file to transfer and target file        *
  20. *         o  Do the transfer                         *
  21. *         o  Repeat the above til done                     *
  22. *                                     *
  23. *     UCSDTRAN properly handles UCSD Textfiles, converting them      *
  24. *     to CP/M-compatible ascii files.  Compressed blanks are         *
  25. *     expanded and the editor formatting is undone.  No conversion   *
  26. *     is done to UCSD Codefiles, Datafiles, etc.             *
  27. *                                     *
  28. *                                     *
  29. *     Installation requires BDS C Version 1.42 or later.  If         *
  30. *     a version prior to 1.50 is used, delete '#include <hardware.h>'*
  31. *                                          *
  32. *                                     *
  33. *     UCSDTRAN makes use of the alloc() function for dynamic memory  *
  34. *     allocation, so be certain this feature is enabled in your      *
  35. *     BDS C compiler before you attempt to compile the program.         *
  36. *     (See the BDS C compiler documentation.)                 *
  37. *                                     *
  38. *     Customization:  The only #define that may be necessary to      *
  39. *     change is SECT0.  If your disk system calls the first sector   *
  40. *     on each track '0', rather than '1', you must leave SECT0       *
  41. *     defined.  Otherwise, comment it out or delete the #define.     *
  42. *     This is necessary because the program directly addresses the   *
  43. *     appropriate track and sector on the UCSD disk; all mapping is  *
  44. *     done by the program.  The Godbout DISK 1 controller numbers    *
  45. *     sectors from 0; most others we've seen in CP/M systems start   *
  46. *     with 1.                                 *
  47. *                                     *
  48. **********************************************************************
  49. *     UCSD is a registered trademark of the Regents of the           *
  50. *          University of California.                     *
  51. *     CP/M is a trademark of Digital Research, Inc.                 *
  52. *     BDS is a trademark of BD Software, Inc.                 *
  53. *                                     *
  54. **********************************************************************
  55. *                                                                    *
  56. *              Author:  Ben Goldfarb                                 *
  57. *                       Orlando, FL                                  *
  58. *                                                                    *
  59. *              Date:    02/11/83                                     *
  60. *                                                                    *
  61. *   Bug reports, comments, and suggestions for improvements to:      *
  62. *                 USENET:  ...!duke!ucf-cs!goldfarb             *
  63. *                 ARPANET: goldfarb.ucf-cs@Rand-Relay                 *
  64. *                                                                    *
  65. **********************************************************************/
  66.  
  67. /*
  68.  *          Revision Log
  69.  *
  70.  *   $Log:    /usr1/grad/goldfarb/cpm/src/ucsdtran.c,v $
  71.  * Revision 1.2  83/04/06  14:31:51  goldfarb
  72.  * Added facility for transferring non-Textfiles.  Previously, only
  73.  * Textfiles were handled, so code was added to circumvent reformatting
  74.  * of editor text 'pages.'  Type of file is detected by examining the
  75.  * 'kind' field in the UCSD directory entry for the file in question.
  76.  * 
  77.  * Revision 1.1  83/04/06  13:54:34  goldfarb
  78.  * Initial revision
  79.  * 
  80.  */
  81.  
  82.  
  83. #include <bdscio.h>
  84. #include <hardware.h>
  85.  
  86. #define VERSION 12
  87.  
  88. /* 
  89.  *  Godbout controller kludge (see title page)
  90.  */
  91.  
  92. #define SECT0
  93.  
  94.  
  95. /*  for versions with no screen handling  */
  96. #ifdef VANILLA
  97. #undef CLEARS
  98. #undef INTOREV
  99. #undef OUTAREV
  100. #define CLEARS ""
  101. #define INTOREV ""
  102. #define OUTAREV ""
  103. #endif
  104.  
  105. /*  Misc. ASCII defines */
  106. #define DLE 0x10
  107. #define CR  0x0d
  108. #define LF  0x0a
  109.  
  110. /*
  111.  *    Definitions for various CP/M 2.2 data structures.
  112.  */
  113.  
  114. /*  Absolute memory loocations  */
  115. #define BIOS_LOC 0x0001
  116. #define IOBYTE   0x0003
  117. #define LOGDRV   0x0004
  118. #define BDOS_LOC 0x0006
  119. #define FCB_1    0x005c
  120. #define TBUFF    0x0080
  121.  
  122.  
  123. /*   Disk Parameter Block  */
  124.  
  125. struct dpb {
  126.     unsigned spt;
  127.     char bsf;
  128.     char bm;
  129.     char nm;
  130.     unsigned dsk_siz;
  131.     unsigned dir_max;
  132.     char al0;
  133.     char al1;
  134.     unsigned chk_siz;
  135.     unsigned trk_ofs;
  136. };
  137.  
  138.  
  139. /*   Disk Parameter Header  */
  140.  
  141. struct dph {
  142.     char *pst_tab;
  143.     int scratch[3];
  144.     char *pdir_buf;
  145.     struct dpb *pdpb;
  146.     char *pchk;
  147.     char *ppalv;
  148. };
  149.  
  150.  
  151. /*  BIOS calls */
  152. #define SEL_DSK 9
  153. #define SET_TRK 10
  154. #define SET_SEC 11
  155. #define READ 13
  156. #define WRITE 14
  157.  
  158. /*  BDOS calls  */
  159. #define INIT_BDOS 13
  160. #define SEL_BDOS 14
  161. #define SET_DMA 26
  162.  
  163. /*  Miscellaneous CP/M constants  */
  164. #define LOG 0
  165. #define NO_LOG 255
  166.  
  167. /*  Miscellaneous UCSD constants  */
  168. #define PAGESIZE 1024
  169. #define DIRENTRIES 77
  170. #define DIRENTSIZE 26
  171.  
  172. /*  UCSD directory structures  */
  173. struct direntry {
  174.     int firstblk, lastblk, kind;
  175.     char title[16];
  176.     int bytesinlast;
  177.     char moddate[2];
  178. };
  179.  
  180. struct dirhdr {
  181.     int dfirstblk, dlastblk, dkind;
  182.     char dtitle[8];
  183.     int lastblkvol, filesindir, loadtime, access;
  184.     char pad[4];
  185. };
  186.  
  187. /*
  188.  *  Global Variables 
  189.  */
  190.  
  191. int ucsddrive, cpmdrive;        /*  Disk drive codes          */
  192. int Godbout;                /*  Kludge for Disk 1        */
  193. char string[16];            /*  Misc. string space        */
  194. int dirp;                    /*  Ptr. to current dir. entry  */
  195. struct dph *pdph;            /*  Ptr. to disk parm header    */
  196. char buff[PAGESIZE];               /*  Input buffer        */
  197. char cpmbuff[BUFSIZ];            /*  Output buffer        */
  198. struct direntry dir[DIRENTRIES - 1];    /*  Directory buffer        */
  199. struct dirhdr volid;            /*  Directory header        */
  200.  
  201. main()
  202. {
  203.     char c, error, morefiles;
  204.  
  205.     
  206.     /*  Print program ident  */
  207.     printf(CLEARS);
  208.     printf("\n\nUCSDtran version %d.%d\n",VERSION/10,VERSION%10);
  209.     printf("\n\nUCSD Pascal to CP/M transfer utility.\n\n");
  210.     printf("Copyright (c) 1983, Ben Goldfarb, Orlando, FL.\n\n");
  211.  
  212. #ifdef SECT0
  213.     Godbout = TRUE;
  214. #else
  215.     Godbout = FALSE;
  216. #endif
  217.  
  218.     /*  Initialize alligator  */
  219.     _allocp = 0;
  220.  
  221.     /*  Input drive names  */
  222.     ucsddrive = getdrive("UCSD");
  223.     cpmdrive = getdrive("CP/M");
  224.  
  225.     /*  Tell user where to go and reset system  */
  226.     do {
  227.         error = FALSE;
  228.         printf("\n\nPut UCSD disk in Drive %c: ", ucsddrive + 'A');
  229.         printf("and CP/M disk in Drive %c:", cpmdrive + 'A');
  230.         printf("\nHit <CR> when ready: ");
  231.         while((c = getchar()) != '\n');
  232.         if ((pdph = seldsk(ucsddrive, LOG)) == NULL) { 
  233.             printf("Message from drive %c:  ", ucsddrive + 'A');
  234.             eprint("You better put it in!");
  235.             error = TRUE;
  236.         }
  237.         else {
  238.                 if (pdph->pdpb->spt != 26 || pdph->pdpb->dsk_siz > 243 ) {
  239.                     eprint("UCSD disk must be standard 3740.");
  240.                     error = TRUE;
  241.                 continue;
  242.                 }
  243.          }
  244.     } while (error);
  245.  
  246.     readdir();  /*  get UCSD directory  */
  247.  
  248.     morefiles = TRUE;
  249.         do {
  250.         error = FALSE;
  251.        do {
  252.         printf(CLEARS);
  253.             printdir();  /*   print directory  */
  254.         printf("Transfer what file: ");
  255.         if ((dirp = getucsd()) == -1) {
  256.             printf("\007No such file\n");    
  257.             error = TRUE;
  258.         }
  259.        } while (error);
  260.        tocpm();
  261.        printf("Transfer more files? ");
  262.        morefiles = yesno();
  263.     } while (morefiles);
  264. }
  265.  
  266. tocpm()    /*  Transfer UCSD file to CP/M file  */
  267. {
  268.     char name[30], istext;
  269.     int fd, i, n;
  270.     unsigned track, sect, nsects;
  271.  
  272.     /*  note: skip first 1024 byte "page" of text file  */
  273.     nsects = ((dir[dirp].lastblk - dir[dirp].firstblk ) * 4);
  274.         if (istext = (dir[dirp].kind == 3)) 
  275.         /*  skip editor page for Textfile  */
  276.         nsects -= 8;
  277.     block(dir[dirp].firstblk + (istext ? 2 : 0), &track, §);
  278.  
  279.     /*  Get filename and set up file  */
  280.     printf("\nEnter CP/M file name: ");
  281.     gets(name);
  282.     printf("Creating %s...",name);
  283.     if ((fd = fcreat(name, cpmbuff)) < 0) {
  284.         printf("\n\007Can't create %s.\n",name);
  285.         return(eprint(""));
  286.     }
  287.  
  288.     /*  Perform the transfer  */
  289.     while (nsects > 0) {
  290.         if (rwfor(&track, §, buff, (istext ? 8 : 4), READ) < 0) 
  291.             return(eprint("Read error on UCSD disk."));
  292.         if (istext)  /* do textfile conversion */
  293.             cpmconvert();
  294.         else   /*  copy raw data  */
  295.             for (i = 0; i < 512; i++) putc(buff[i], cpmbuff);
  296.  
  297.         nsects -= (istext? 8 : 4);
  298.     }
  299.  
  300.      if (istext) putc(CPMEOF, cpmbuff);
  301.     fflush(cpmbuff);
  302.     printf("\nTransfer complete\n");
  303.     fclose(cpmbuff);
  304. }
  305.  
  306. cpmconvert()  /*  output translated UCSD 1024 byte buffer to cp/m file */
  307. {
  308.     int i, nospaces, bufptr;
  309.     char c;
  310.  
  311.     bufptr = 0;
  312.     while (bufptr < 1024) {
  313.         
  314.         switch(c = buff[bufptr++]) {
  315.            case DLE: 
  316.             nospaces = buff[bufptr++] - 32;
  317.             for (i = 0; i < nospaces; i++)
  318.                 putc(' ', cpmbuff);
  319.             break;
  320.            case CR:
  321.             putc(c, cpmbuff);
  322.             putc(LF, cpmbuff);
  323.                 break;
  324.            case '\0':
  325.             break;  /* ignore  */
  326.            default:
  327.             putc(c, cpmbuff);
  328.             break;
  329.         }
  330.     }
  331. }
  332.  
  333.             
  334. rwfor(t,s,buff,n,rw)   /*  Read or write a sector from UCSD disk  */
  335. unsigned *t,*s,n,rw;
  336. char *buff;
  337. {
  338.     char *buffa;
  339.  
  340.     /*  Reset buffer  */
  341.     buffa = buff;
  342.     
  343.     /*  Select UCSD Disk  */
  344.     seldsk(ucsddrive, NO_LOG);
  345.  
  346.     /*  Now read or write n sectors  */
  347.     while (n-- > 0) {
  348.         register unsigned ps;
  349.  
  350.         bios(SET_TRK, *t);
  351.         ps = map(*s, *t);
  352.         /*  Set sector (note Godbout kludge)  */
  353.         bios(SET_SEC, ps + ((Godbout) ? 0 : 1)); 
  354.         bdos(SET_DMA, buffa);
  355.         if ((bios(rw, 0) & 1) == 1)
  356.             return(ERROR);
  357.  
  358.         /*  Bump track, if necessary  */
  359.         if (++(*s) > 25) {
  360.              *s = 0;
  361.             (*t)++;
  362.         }
  363.         buffa += 128;
  364.     }
  365.     bdos(SET_DMA, buff);
  366.     seldsk(cpmdrive, NO_LOG);
  367.     return(OK);
  368. }
  369.  
  370. getdrive(s)  /*  get disk drive designation and validate  */
  371. char *s;
  372. {
  373.     char c;
  374.  
  375.     for (;;) {  /*  until the dummy gets it right!  */
  376.           printf("\n\nDrive for %s disk: (A - P) ", s);
  377.         if ((c = toupper(getchar())) > 'P' || c < 'A')  
  378.             eprint("Drive value out of range!");
  379.         else
  380.             return(c - 'A');
  381.     }
  382. }
  383.  
  384. yesno()   /*  ask for a response and return true for 'yes'  */
  385. {
  386.     char c;
  387.  
  388.     return(((c = toupper(getchar())) == 'Y') ? TRUE : FALSE);
  389. }
  390.  
  391. eprint(s)  /*  Print error message, hold screen, and return error  */
  392. char *s;
  393. {
  394.     printf("\n\007");
  395.     rprintf(s);
  396.     printf("\nHit <CR> to continue: ");
  397.     getchar();
  398.     bdos(INIT_BDOS);
  399.     return(ERROR);
  400. }
  401.  
  402.  
  403. rprintf(s)   /*  Print in reverse video  */
  404. char *s;
  405. {
  406.     printf(INTOREV);
  407.     printf(s);
  408.     printf(OUTAREV);
  409. }
  410.  
  411. struct dph
  412. *seldsk(dn, log)   /*  BIOS function to select drive and return dph */
  413. char dn, log;
  414. {
  415.     unsigned *pbios;
  416.     unsigned *psel_dsk;
  417.  
  418.     pbios = BIOS_LOC;
  419.     psel_dsk = *pbios + 0x0019;
  420.     return(call(*psel_dsk, dn, 0, dn, log));
  421. }
  422.  
  423. block(blk, track, sect)   /*  translates UCSD block to logical track/sector  */
  424. int blk, *track, *sect;
  425. {
  426.     int abssector;
  427.     
  428.     abssector = blk * 4;
  429.     *track = (abssector / 26) + 1;
  430.     *sect = abssector % 26;
  431. }
  432.  
  433.     
  434.     
  435. map(secno, trkno)   /*  maps logical to physical sector  */
  436. int secno, trkno;
  437. {
  438.     int s;
  439.     
  440.     if (secno > 12)
  441.         s = ((secno * 2) + 1 + ((trkno-1) * 6 )) % 26;
  442.     else 
  443.         s = ((secno * 2) + ((trkno-1) * 6)) % 26;
  444.     return(s);
  445. }
  446.  
  447. readdir()   /*  read the directory on the UCSD disk   */
  448. {
  449.     int track, sect;
  450.     char *alloc(), *dirbuf; 
  451.  
  452.     if ((dirbuf = alloc(DIRENTRIES * DIRENTSIZE)) == 0) {
  453.         printf("Not enough memory -- aborting.\n");
  454.         exit(ERROR);
  455.     } 
  456.  
  457.     block(2, &track, §);   /*  2 is the directory block  */
  458.     rwfor(&track, §, dirbuf, 4*4, READ);
  459.  
  460.     /* big kludge because no casts in BDS  */
  461.     movmem(dirbuf, &volid, DIRENTSIZE);
  462.     movmem(dirbuf + DIRENTSIZE, &dir[0], (DIRENTRIES - 1) * DIRENTSIZE);
  463.     free(dirbuf);
  464. }
  465.  
  466. printdir()  /*  print UCSD disk's directory  */
  467. {
  468.     int i;
  469.     char *s;
  470.  
  471.     printf("Volume ID: %s\n", makestr(volid.dtitle));
  472.  
  473.     for (i = 0; i < volid.filesindir; i++) {
  474.        printf("%-14s\t%3d", makestr(dir[i].title),
  475.         dir[i].lastblk - dir[i].firstblk);
  476.        printf("\t");
  477.        printdate(dir[i].moddate);
  478.        printf("\t");
  479.        switch(dir[i].kind) {  /*  Ain't BDS nice ? */
  480.         case 0:  printf("Datafile"); break;
  481.         case 1:  printf("Xdskfile"); break;
  482.         case 2:  printf("Codefile"); break;
  483.         case 3:  printf("Textfile"); break;
  484.         case 4:  printf("Infofile"); break;
  485.         case 5:  printf("Datafile"); break;
  486.         case 6:  printf("Graffile"); break;
  487.         case 7:  printf("Fotofile"); break;
  488.         default: printf("Foofile"); break;
  489.        }
  490.        printf("\n");
  491.     }
  492.     printf("\n");    
  493. }
  494.  
  495. char *
  496. makestr(s)  /*  make a C string from UCSD variable string  */
  497. char *s;
  498. {
  499.     int i;
  500.     char *t;
  501.  
  502.     t = &string[0];
  503.     for (i = 0;  i < s[0]; i++)
  504.         t[i] = s[i+1];
  505.     t[i] = '\0';
  506.     return(&string[0]);
  507. }
  508.  
  509. printdate(d) /*  prints a UCSD date record  */
  510. char d[];
  511. {
  512.  
  513.     int t1;
  514.  
  515.     /*
  516.          *  The UCSD format is:
  517.       *  
  518.      *  DATEREC = PACKED RECORD
  519.      *       MONTH: 0..12;
  520.      *       DAY:   0..31;
  521.      *       YEAR:  0..100
  522.      *  END;
  523.      *
  524.      *  This routine expects a char[2] array with the
  525.      *  information stored as above.
  526.      */
  527.  
  528.     t1 = (d[0] >> 4) | ((d[1] & 1) << 4);
  529.     printf("%2d", t1);
  530.     t1 = d[0] & 0x0f;
  531.     printf("-");
  532.     switch (t1) {  /*  because of no init in BDS  */
  533.        case 1:  printf("Jan"); break;
  534.        case 2:  printf("Feb"); break;
  535.        case 3:  printf("Mar"); break;
  536.        case 4:  printf("Apr"); break;
  537.        case 5:  printf("May"); break;
  538.        case 6:  printf("Jun"); break;
  539.        case 7:  printf("Jul"); break;
  540.        case 8:  printf("Aug"); break;
  541.        case 9:  printf("Sep"); break;
  542.        case 10: printf("Oct"); break;
  543.        case 11: printf("Nov"); break;
  544.        case 12: printf("Dec"); break;
  545.        default: printf("Foo"); break;
  546.     }
  547.     printf("-");
  548.     t1 = d[1] >> 1;
  549.     printf("%02d", t1);
  550. }
  551.  
  552. getucsd()   /*  returns a ptr to dir entry if valid, else -1 */
  553. {
  554.     char temp[81];
  555.     int i, j, l, found;
  556.  
  557.  
  558.     gets(temp);
  559.     
  560.     /*  see if we can find it in dir  */
  561.     for (i = 0; i < volid.filesindir; i++) {
  562.         if ((l = strlen(temp)) != dir[i].title[0])
  563.             continue;
  564.         else {
  565.             found = TRUE;
  566.             for (j = 1; j <= l; j++) {
  567.                 if (toupper(temp[j-1]) != dir[i].title[j]){
  568.                     found = FALSE;
  569.                     break;
  570.                 }
  571.             }
  572.             if (found) return(i);
  573.         }
  574.     }
  575.     return(-1);
  576. }
  577.