home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_07_04 / v7n4041a.txt < prev    next >
Text File  |  1988-10-10  |  19KB  |  470 lines

  1. /*----------------------------------------------------------------*/
  2. /*    MODULE: AUDIR.C                                             */
  3. /*  CONTENTS: main()...                                           */
  4. /*    AUTHOR: John T. Bell                                        */
  5. /*   HISTORY: Last modified on 9/14/88                            */
  6. /*                                                                */
  7. /*  Copyright 1988, by John T. Bell, All Rights Reserved.         */
  8. /*----------------------------------------------------------------*/
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #include "bios.h"
  12.  
  13. typedef unsigned char byte;
  14. typedef unsigned short word;
  15. /* turn off redefinitions in header files */
  16. #define BYTE_DEF
  17.  
  18. #include "prodir.h"
  19. #include "ados33.h"
  20. #include "cpmdir.h"
  21.  
  22. /*---------------------------------------------------*/
  23. /* Note: Slot 6, Drive 1, is the C: CP/M drive on my */
  24. /*       system. Drive C: is is referenced by the    */
  25. /*       Number 2 to the CP/M BIOS.                  */
  26. /*       A: == Drive 0                               */
  27. /*       B: == Drive 1                               */
  28. /*       C: == Drive 2                               */
  29. /*       Etc...                                      */
  30. /* Change as appropiate for your system.             */
  31. /*---------------------------------------------------*/
  32. #define DRIVE 2
  33.  
  34. /*----------------------------------------------------------*/
  35. /* This is a table of the first 4 bytes which should        */
  36. /* appear at track 0 sector 0 of each disk format           */
  37. /* expected. This is used to determine which                */
  38. /* operating system the disk was written with. The          */
  39. /* fifth byte in each row should identify the OS in         */
  40. /* the following manner;                                    */
  41. /*                                                          */
  42. /* CP/M  is 0x00                                            */
  43. /* AppleDOS is 0x01                                         */
  44. /* and ProDOS is 0x02                                       */
  45. /*                                                          */
  46. /* Note: The second CP/M entry is for a disk which has      */
  47. /* formatted but the CP/M boot tracks were not written.     */
  48. /*----------------------------------------------------------*/
  49. #define MAX_TYPE 4
  50. byte disk_id[ MAX_TYPE ][5] = {
  51.     { 0x01, 0xea, 0xa6, 0x2b, 0x00}, /* CP/M format */
  52.     { 0xe5, 0xe5, 0xe5, 0xe5, 0x00}, /* CP/M Disk w/o system */
  53.     { 0x01, 0xa5, 0x27, 0xc9, 0x01}, /* Apple Dos 3.3 Disk */
  54.     { 0x01, 0x38, 0xb0, 0x03, 0x02}  /* ProDOS 1.1.1 Disk  */
  55. };
  56.  
  57. /*---------------------------------------------------*/
  58. /* The following is the sector conversion table      */
  59. /* for converting DOS sectors to CP/M sectors.       */
  60. /*---------------------------------------------------*/
  61. int dos2cpm[] = {0,15,9,3, 13,7,1,11, 10,4,14,8, 2,12,6,5};
  62. int pro2cpm[] = {0,6,12,2, 8,14,4,10, 11,1,7,13, 3,9,15,5};
  63.  
  64. main()
  65. {
  66.     int type;
  67.     int err;
  68.  
  69.     type = disktype();
  70.     switch(type){
  71.     case 0: /* CP/M disk */
  72.         printf("*** CP/M Directory ***\n\n");
  73.         cpmdir();
  74.         break;
  75.  
  76.     case 1:
  77.         printf("*** Apple DOS 3.3 Directory ***\n\n");
  78.         dosdir();
  79.         break;
  80.  
  81.     case 2:
  82.         printf("*** ProDOS Directory ***\n\n");
  83.         prodir();
  84.         break;
  85.  
  86.     default:
  87.         printf("udir: Can't identify disk type\n");
  88.         break;
  89.     }
  90. /*--------------------------------------------------------*/
  91. /* The following, skips the Aztec CP/M exit code.         */
  92. /*--------------------------------------------------------*/
  93. #asm
  94.     .z80
  95.     jp 0
  96.     .8080
  97. #endasm
  98. }
  99.  
  100. /*--------------------------------------------------------------------------*/
  101. /*   Function: int disktype();                                              */
  102. /*    Purpose: Identify a diskette as being CP/M, AppleDOS, or ProDOS.      */
  103. /*    Returns: 0 for CP/M, 1 for AppleDOS, 2 for ProDOS,                    */
  104. /*             -1 for unidentified, and -2 for error.                       */
  105. /*    Globals: Uses the disk_id[][] table to compare the first four         */
  106. /*             bytes of the disk and make an identification.                */
  107. /*      Notes: Disk idents were determined by trial and error. There may    */
  108. /*             be others (ie; NON-Bootable AppleDOS) which have not been    */
  109. /*             included in the table.                                       */
  110. /*--------------------------------------------------------------------------*/
  111. int disktype()
  112. {
  113.     byte buff[128]; /* buffer for first track and sector */
  114.     byte *bptr;
  115.     int i,j;
  116.     int err;
  117.  
  118.     if((err = readsect(DRIVE,0,0,buff)) != 0){ /* disk error */
  119.         errno = err;
  120.         return(-2);
  121.     }
  122.  
  123.     for(i = 0; i < MAX_TYPE; i++){
  124.         bptr = buff;
  125.         for(j = 0; j < 4; j++){
  126.             if(disk_id[i][j] != *bptr++)
  127.                 break;
  128.         }
  129.         if(j >= 4)
  130.             return(disk_id[i][4] & 0x00ff);
  131.     }
  132.     return(-1);
  133. }
  134.  
  135. /*--------------------------------------------------------------------------*/
  136. /*   Function: cpmdir()                                                     */
  137. /*    Purpose: Do a low level (without CP/M BDOS assistance) read of the    */
  138. /*             CP/M directory. A low level directory read is needed here    */
  139. /*             to enable future porting to other Apple Operating Systems.   */
  140. /*    Returns: NONE                                                         */
  141. /*      Notes: Disk is currently hard coded and should be given as an arg   */
  142. /*             in the future.                                               */
  143. /*                                                                          */
  144. /*--------------------------------------------------------------------------*/
  145. cpmdir()
  146. {
  147.     char buff[128];  /* disk sector buffer */
  148.     int i,err;
  149.     int disk;
  150.     int track,sect;
  151.     struct cpm_entry *dir;
  152.     int user,j;
  153.  
  154.     track = 3; /* track for apple cp/m directory */
  155.  
  156.     for(sect = 0; sect < 12; sect++){
  157.         err = readsect(DRIVE,track,sect,buff);
  158.         if(!err){
  159.             dir = (struct cpm_entry *)buff;
  160.             for(j = 0; j < 4; j++){
  161.                 if((dir->user_no != 0xe5) /* skip erased file */
  162.                   &&(dir->extent == 0)){   /* and extra extents */
  163.                     user = dir->user_no & 0x1f;
  164.                     printf("C%d:%8.8s.%3.3s\n",user,dir->name,dir->ext);
  165.                 }
  166.                 dir++;
  167.             }
  168.         }
  169.     }
  170. }
  171.  
  172. /*--------------------------------------------------------------------------*/
  173. /*   Function: prodir()                                                     */
  174. /*    Purpose: This routine reads the Apple DOS directory from              */
  175. /*             a Pro Dos disk and prints it to the display.                 */
  176. /*    Returns: 0 if no error, -1 otherwise.                                 */
  177. /*      Notes: Requires PRODIR.H to define the structures.                  */
  178. /*                                                                          */
  179. /*--------------------------------------------------------------------------*/
  180. prodir()
  181. {
  182.     byte buff[513];  /* disk sector buffer */
  183.     byte fname[32];  /* space for filename */
  184.     int i,err;
  185.     int block;
  186.     struct pro_block *dir;
  187.     int entry_type;
  188.     int name_len;
  189.  
  190.     dir = (struct pro_block *)buff;
  191.     block = 2;
  192. /*---------------------------------------------------*/
  193. /* read sectors until no further catalog links       */
  194. /*---------------------------------------------------*/
  195.     do{
  196.         err = getproblock(block,buff); 
  197.         if(err){
  198.             fprintf(stderr,"error %d reading block %d\n",err,block);
  199.             return(-1);
  200.         }
  201.  
  202. /*---------------------------------------------------*/
  203. /* Print the directory entries                       */
  204. /*---------------------------------------------------*/
  205.         for(i = 0; i < 13; i++){
  206.             entry_type = (dir->dir[i].typ_len & 0x00f0) / 16;
  207.             name_len = (dir->dir[i].typ_len & 0x000f);
  208.             setmem(fname,32,'\0'); /* clear the filename space */
  209.             strncpy(fname, dir->dir[i].fname, name_len);
  210.             fixstr(fname);
  211.  
  212. #ifdef xyzzy
  213.             printf("INFO:%d entry %d len %d name %15.15s\n",
  214.               i,entry_type,name_len,fname);
  215. #endif
  216.  
  217.             switch(entry_type){
  218.             case 0x0f:      /* Volume entry */
  219.                 printf("VOLUME NAME: %s\n\n", fname);
  220.                 break;
  221.  
  222.             case 0x0e:      /* Subdirectory header */
  223.                 break;
  224.  
  225.             case 0x0d:      /* Subdirectory */
  226.                 printf("\nSUB-DIRECTORY: %s\n\n", fname);
  227.                 break;
  228.  
  229.             case 0:         /* Deleted entry */
  230.                 break;
  231.  
  232.             case 1:
  233.             case 2:
  234.             case 3:
  235.                 printf("%s\n", fname);
  236.                 break;
  237.  
  238.             default:
  239.                 printf("Unknown entry type %d\n",entry_type);
  240.                 break;
  241.             }
  242.         }
  243. /*---------------------------------------------------*/
  244. /* Get the next Catalog Block                        */
  245. /*---------------------------------------------------*/
  246.         block = dir->next;
  247.     }while(block > 2);
  248.     return(0);
  249. }
  250.  
  251. /*--------------------------------------------------------------------------*/
  252. /*   Function: getproblk( block, buff)                                      */
  253. /*             unsigned int block; - ProDOS block number to read.           */
  254. /*             byte *buff; - Location to store the data read.               */
  255. /*                           Must be 512 bytes long or greater.             */
  256. /*    Purpose: Read a ProDOS disk block.                                    */
  257. /*    Returns: -1 for error, 0 otherwise.                                   */
  258. /*    Globals: Uses the pro2cpm[] sector translation table.                 */
  259. /*      Notes: Calculates CP/M tracks and sectors and does all              */
  260. /*             ProDOS to CP/M sector translation. Reads 4 CP/M sectors.     */
  261. /*                                                                          */
  262. /*--------------------------------------------------------------------------*/
  263. int getproblock(block,buff)
  264. int block;
  265. byte *buff;
  266. {
  267.     int cpmsect;
  268.     int err;
  269.     int track;
  270.     int sect;
  271.     int i,j;
  272.  
  273. /*---------------------------------------------------*/
  274. /* Do ProDOS to CP/M sector translation              */
  275. /*---------------------------------------------------*/
  276.     track = block/8;
  277.     sect = (block % 8) * 2;
  278.     cpmsect = pro2cpm[sect] * 2;
  279.  
  280. /*---------------------------------------------------*/
  281. /* Read 4 CP/M sectors and copy into buff            */
  282. /*---------------------------------------------------*/
  283.     for(i = 0; i < 2; i++){
  284.         for(j = 0; j < 2; j++){
  285.             err = readsect(DRIVE,track,cpmsect,buff);
  286.             if(err < 0)
  287.                 return(err);
  288.             cpmsect++;
  289.             buff+=128;
  290.         }
  291.         sect++;
  292.         cpmsect = pro2cpm[sect] * 2;
  293.     }
  294.     return(0);
  295. }
  296.  
  297. /*--------------------------------------------------------------------------*/
  298. /*   Function: dosdir()                                                     */
  299. /*    Purpose: This routine reads the Apple DOS directory from              */
  300. /*             a DOS 3.3 disk and prints it to the display.                 */
  301. /*    Returns: -1 if error, 0 otherwise.                                    */
  302. /*      Notes: Requires ADOS33.H.                                           */
  303. /*                                                                          */
  304. /*--------------------------------------------------------------------------*/
  305. dosdir()
  306. {
  307.     char buff[257];  /* disk sector buffer */
  308.     char fname[32];  /* space for filename */
  309.     int i,err;
  310.     int disk;
  311.     int track,sect;
  312.     struct dir_blk *dblk; /* pointer to directory block */
  313.  
  314.     dblk = (struct dir_blk *)&buff[0];
  315.     setmem(fname,32,'\0'); /* clear the filename space */
  316.  
  317. /*---------------------------------------------------*/
  318. /* get VTOC sector                                   */
  319. /*---------------------------------------------------*/
  320.     track = 17; /* VTOC begins at track 17  sector 0 */
  321.     sect = 0;
  322.     err = rd_dos_blk(track,sect,buff); /* read the VTOC sector */
  323.     if(err){
  324.         fprintf(stderr,"error %d track %d sector %d\n",err,track,sect);
  325.         return(-1);
  326.     }
  327.  
  328. /*---------------------------------------------------*/
  329. /* get catalog track, sector links                   */
  330. /*---------------------------------------------------*/
  331.     track = dblk->track_lnk;
  332.     sect = dblk->sect_lnk;
  333.  
  334. /*---------------------------------------------------*/
  335. /* read sectors until no further catalog links       */
  336. /*---------------------------------------------------*/
  337.     while(track && sect){
  338.         err = rd_dos_blk(track,sect,buff);
  339.         if(err){
  340.             fprintf(stderr,"error %d track %d sector %d\n",err,track,sect);
  341.             return(-1);
  342.         }
  343.  
  344. /*---------------------------------------------------*/
  345. /* Print the directory entries                       */
  346. /*---------------------------------------------------*/
  347.         for(i=0;i<7;i++){
  348.             if((dblk->dir[i].track != (char)0xff)&&
  349.               (dblk->dir[i].track != (char)0)){
  350.                 movmem(&dblk->dir[i].fname,fname,30);
  351.                 fixstr(fname);
  352.                 printf("%s\n",fname);
  353.             }
  354.         }
  355. /*---------------------------------------------------*/
  356. /* Get the next Catalog track and sector             */
  357. /*---------------------------------------------------*/
  358.         if(track||sect){
  359.             track = dblk->track_lnk;
  360.             sect = dblk->sect_lnk;
  361.         }
  362.     }
  363.     return(0);
  364. }
  365.  
  366. /*--------------------------------------------------------------------------*/
  367. /*   Function: rd_dos_blk(track, sect, buff);                               */
  368. /*             int track; - track of block to be read;                      */
  369. /*             int sect;  - AppleDOS sector to be read;                     */
  370. /*             byte *buff; - Destination for block data, must be at least   */
  371. /*                           256 bytes long.                                */
  372. /*                                                                          */
  373. /*    Purpose: read an AppleDOS disk block.                                 */
  374. /*    Returns: readsect() error value if error, 0 if no errors occurs.      */
  375. /*    Globals: Uses the dos2cpm[] sector translation table.                 */
  376. /*      Notes: Does sector translation and reads 2 CP/M sectors.            */
  377. /*             (DOS sectors are 256 bytes CP/M sectors are 128 bytes.)      */
  378. /*                                                                          */
  379. /*--------------------------------------------------------------------------*/
  380. int rd_dos_blk(track,sect,buff)
  381. int track;
  382. int sect;
  383. char *buff;
  384. {
  385.     int dsect;
  386.     int err;
  387.     int i;
  388.  
  389. /*---------------------------------------------------*/
  390. /* Do DOS 2 CP/M sector translation                  */
  391. /*---------------------------------------------------*/
  392.     dsect = dos2cpm[sect]*2;
  393.  
  394. /*---------------------------------------------------*/
  395. /* Read 2 CP/M sectors and copy into buff            */
  396. /*---------------------------------------------------*/
  397.     for(i = 0; i < 2; i++){
  398.         err = readsect(DRIVE,track,dsect,buff);
  399.         if(err < 0)
  400.             return(err);
  401.         dsect++;
  402.         buff+=128;
  403.     }
  404.     return(0);
  405. }
  406.  
  407. /*--------------------------------------------------------------------------*/
  408. /*   Function: readsect(drive, track, sect, buff)                           */
  409. /*             int drive; - disk drive indentifier. A:=0, B:=1, ..., P:=15  */
  410. /*             int track; - track of sector to be read.                     */
  411. /*             int sect;  - sector number of sector to be read.             */
  412. /*             byte *buff; - where to put the data read.                    */
  413. /*                                                                          */
  414. /*    Purpose: To read a sector from a disk using the low level BIOS calls. */
  415. /*    Returns:  0 if everything is AOK.                                     */
  416. /*             -1 if a select disk error occurs.                            */
  417. /*             -2 if a sector read error occurs.                            */
  418. /*      Setup: NONE                                                         */
  419. /*    Globals: NONE                                                         */
  420. /*      Notes: Use BIOS.H to compile.                                       */
  421. /*                                                                          */
  422. /*--------------------------------------------------------------------------*/
  423. int readsect(drive,track,sect,buff)
  424. int drive;
  425. int track;
  426. int sect;
  427. byte *buff;
  428. {
  429.     int skew;           /* internal CP/M skew table */
  430.     int tru_sect;       /* translated physical sector value  */
  431.     int err;
  432. /*---------------------------------------------------*/
  433. /* Get address of disk parameter block.              */
  434. /*---------------------------------------------------*/
  435.     skew = bioshl(SELDSK,drive,0);
  436.     if(skew == 0){
  437.         return(-1);
  438.     }
  439. /*---------------------------------------------------*/
  440. /* Select the track                                  */
  441. /*---------------------------------------------------*/
  442.     bios(SETTRK,track,0);
  443. /*---------------------------------------------------*/
  444. /* Select the sector                                 */
  445. /*---------------------------------------------------*/
  446.     tru_sect = bioshl(SECTRAN,sect,skew);
  447.     bios(SETSEC,tru_sect,0);    
  448. /*---------------------------------------------------*/
  449. /* Assign destination address (DMA Address)          */
  450. /*---------------------------------------------------*/
  451.     bios(SETDMA,buff,0);
  452. /*---------------------------------------------------*/
  453. /* Read the sector                                   */
  454. /*---------------------------------------------------*/
  455.     err = bios(READ,0,0);
  456.     if(err)
  457.         return(-2);
  458.     else
  459.         return(0);
  460. }
  461. /*---------------------------------------------------*/
  462. /* Fixes Apple strings for display under CP/M        */
  463. /*---------------------------------------------------*/
  464. fixstr(s)
  465. byte *s;
  466. {
  467.     while(*s)
  468.         *s++ &= 0x7f;
  469. }
  470.