home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume15 / upm / part01 / upm.c < prev    next >
C/C++ Source or Header  |  1990-12-17  |  7KB  |  321 lines

  1. /*
  2.  
  3. up/m - unix CP/M.
  4.  
  5. (C) MCMXC - Nick Sayer - All rights reserved.
  6.  
  7. See COPYRIGHT file for more details.
  8.  
  9.  
  10. Configuration section.
  11.  
  12.  
  13. CPM_FILE - default file with CP/M HEX images.
  14.  
  15. Addresses 0-2K are CCP, 2K-5.5K - BDOS. 5.5K-16K - BIOS. Address 65535
  16. will have the length (in pages) of CP/M.
  17.  
  18. Addresses 16K-? - relocation bitmap. Each bit in the bitmap represents
  19. a BYTE in 0-16K. If the bit is 1, the high byte of the first address of
  20. the destination address for the CCP should be added to the byte in 0-16K
  21. image. That image is then moved to the proper location. The PC is set to
  22. 32K and the Z-80 starts running. The high byte of the first byte of the
  23. CCP destination address is gotten from address 65535. This value is
  24. then adjusted if CP/M is to be relocated lower than the default
  25. top of memory. The CP/M image to load should have a resident run address
  26. before relocation of 0.
  27.  
  28. */
  29. #define CPM_FILE "CPM"
  30.  
  31. #include <strings.h>
  32. #include <ctype.h>
  33. #include <sgtty.h>
  34. #include <signal.h>
  35.  
  36. #include "upm.h"
  37.  
  38. WORD topmem=256;       /* These may be changed by arguments */
  39. char *cpm_file=CPM_FILE;
  40.  
  41. struct sgttyb tty_sgtty_data;
  42.  
  43. static BYTE dph[32]={
  44.  
  45. /* Disk Paramater Header (diskbufs[]) */
  46.  
  47. 0x00,0x00,    /* TRANSTABLE unused */
  48. 0x00,0x00,    /* unused */
  49. 0x00,0x00,
  50. 0x00,0x00,
  51. 0x80,0xff,    /* DIRBUF - patch with topmem-1 later */
  52. 0x10,0xff,    /* DPB - patch with OUR page no. */
  53. 0x00,0x00,    /* CHKVEC - not used */
  54. 0x20,0xff,    /* ALLOCVEC - patch with OUR page no. */
  55.  
  56. /* Disk Paramater Block */
  57.  
  58. 0x40,0x00,    /* Sectors per track */
  59. 0x04,        /* Block Shift */
  60. 0x0f,        /* Block Mask */
  61. 0x00,        /* Extent Mask */
  62. 0x00,0x10,    /* Blocks on device - patch if variable size implemented */
  63. 0xff,0x01,    /* Directory entries -1 */
  64. 0xff,0x00,    /* Allocation masks for directory */
  65. 0x00,0x00,    /* Check vector size - patch if checkvecs implemented */
  66. 0x00,0x00,    /* offset to first user-track */
  67. 0x00        /* spare */
  68. };
  69.  
  70. /* These are externs in upm.h, but they have to be declared somewhere. */
  71.  
  72. FILE *disks[16],*devices[5];
  73. WORD diskbufs[16];
  74. BYTE ccp_image[SIZE_CCP_IMAGE];
  75. WORD ccp_start;
  76.  
  77. /*
  78.  
  79. relocade(address);
  80. BYTE address;
  81.  
  82. Relocate CP/M image at 0000-4000 using bitmap at 4000-4800.
  83. Copy image to new location, and copy first 5.5K to ccp_image[];
  84. Stop if we get to the top of RAM.
  85.  
  86. */
  87.  
  88. relocate(add,len)
  89. BYTE add;
  90. {
  91.   WORD i;
  92.  
  93.   for (i=0;i!=(256*len);i++)
  94.   {
  95.     if ( real_z80_mem[16384+(i>>3)]&(1<<(i&7)) )
  96.       real_z80_mem[i]=real_z80_mem[i]+add;
  97.     real_z80_mem[i+(add<<8)]=real_z80_mem[i];
  98.     if (i<SIZE_CCP_IMAGE)
  99.       ccp_image[i]=real_z80_mem[i];
  100.   }
  101. }
  102. int debugflag = 0;
  103. int dlogflag = 0;
  104.  
  105. debugit();
  106.  
  107. main(argc,argv)
  108. int argc;
  109. char **argv;
  110. {
  111.   FILE *cpm;
  112.   char line[80];
  113.   int i;
  114.  
  115.   signal(SIGINT,debugit);
  116.  
  117.   for(i=0;i<16;i++)
  118.   {
  119.     disks[i]=NULL;
  120.     devices[i%5]=NULL; /* hack: only do 0-4 */
  121.   }
  122.  
  123. /* OPEN ~/.upmrc, send each line to process_args(line); */
  124.  
  125.   argc--; argv++;
  126.   for(;argc--;argv++)
  127.     process_args(*argv);
  128.  
  129.   if (disks[0]==NULL)
  130.   {
  131.     printf("A: must be assigned.\n");
  132.     exit(0);
  133.   }
  134.  
  135. /*
  136.  
  137. For each non-null pointer in disks[], lower topmem, and save the pointer
  138. to diskbufs[]. This assigns space for the allocation vector, and the
  139. DPH/DPB. Then copy in a "standard" DPH/DPB into the bottom. We'll
  140. patch it later.
  141.  
  142. We really should allow disks to be sized at runtime, but for now
  143. they're fixed at 8MB, so we lower topmem 3 for each one. 2 pages
  144. for the alloc table, another page (actually 32 bytes)
  145. for the miscelany.
  146.  
  147. */
  148.  
  149.   for(i=0;i!=16;i++)
  150.   {
  151.     char j;
  152.  
  153.     if (disks[i]==NULL)
  154.       continue;
  155.     topmem-=3;
  156.     diskbufs[i]=topmem<<8;
  157.     for(j=0;j!=32;j++)
  158.       real_z80_mem[diskbufs[i]+j]=dph[j];
  159.     real_z80_mem[diskbufs[i]+0x0b]=real_z80_mem[diskbufs[i]+0x0f]=topmem;
  160.   }
  161.  
  162. /*
  163.  
  164. Now for each non-null disk[] readjust the dirbuf pointer.
  165. We couldn't do it before because we didn't have a final
  166. location for dirbuf. topmem-1 is the high-byte of the
  167. final location for dirbuf. the low byte is 0x80.
  168. This page of memory is shared with the BIOS "jump" table.
  169.  
  170. */
  171.  
  172.   for(i=0;i!=16;i++)
  173.   {
  174.     if (disks[i]==NULL)
  175.       continue;
  176.     real_z80_mem[diskbufs[i]+9]=topmem-1;
  177.   }
  178.  
  179.   cpm=fopen(cpm_file,"r");
  180.   if (cpm==NULL)
  181.   {
  182.     printf("Can't open CP/M binaries: %s\n",sys_errlist[errno]);
  183.     exit(1);
  184.   }
  185.   loadhex(cpm);
  186.  
  187.   ccp_start=(topmem-real_z80_mem[65535])<<8;
  188.   relocate(topmem-real_z80_mem[65535],real_z80_mem[65535]);
  189.  
  190.   PC=0x8000;
  191.  
  192. /*
  193.  
  194. Now set up the terminal. Just toggling RAW should be enough.
  195.  
  196. */
  197.  
  198.   gtty(fileno(stdin),&tty_sgtty_data);
  199.   tty_sgtty_data.sg_flags|=RAW;
  200.   tty_sgtty_data.sg_flags&=~ECHO;
  201.   stty(fileno(stdin),&tty_sgtty_data);
  202.  
  203.   do
  204.   { z80_run();
  205.     if(debugflag>1 && debugit()) PC++;
  206.     else if(bios()) break;
  207.   } while(1); /*  }  while(!bios()); */
  208.  
  209.   gtty(fileno(stdin),&tty_sgtty_data);
  210.   tty_sgtty_data.sg_flags&=~RAW;
  211.   tty_sgtty_data.sg_flags|=ECHO;
  212.   stty(fileno(stdin),&tty_sgtty_data);
  213. }
  214.  
  215. /*
  216.  
  217. The arguments can include A:file-O:file, {TY, LP, PT, U1, U2}:file,
  218. mem:0-128.
  219.  
  220. Disk files are fopen()ed "r+", and are assigned to disks[].
  221. Device files are fopen()ed "r+" and are assigned to devices[], except
  222. for LP:, which is fopen()ed "w".
  223.  
  224. The value after mem: lowers the top of memory by that many pages (256
  225. bytes) to save space for things like BYE, etc.
  226.  
  227. The arguments MUST be stripped of white-spaces.
  228.  
  229. */
  230.  
  231. process_args(arg)
  232. char *arg;
  233. {
  234.   char i,left[80],*right;
  235.  
  236.     if (index(arg,':')==NULL)
  237.     {
  238.       printf("Missing ':' in argument.\n");
  239.       return;
  240.     }
  241.  
  242.     strcpy(left,arg);
  243.     right=index(left,':')+1;
  244.     *index(left,':')='\0';
  245.     for(i=0;i!=strlen(left);i++)
  246.       if (islower(left[i]))
  247.         left[i]=toupper(left[i]);
  248.  
  249.     if (strlen(left)==1 && (*left<='O') && (*left>='A'))
  250.     {
  251.       disks[*left-'A']=fopen(right,"r+");
  252.       return;
  253.     }
  254.     if (!strcmp(left,"MEM"))
  255.     {
  256.       topmem-=atoi(right);
  257.       return;
  258.     }
  259.     if (!strcmp(left,"TY"))
  260.     {
  261.       devices[F_TY]=fopen(right,"r+");
  262.       return;
  263.     }
  264.     if (!strcmp(left,"PT"))
  265.     {
  266.       devices[F_PT]=fopen(right,"r+");
  267.       return;
  268.     }
  269.     if (!strcmp(left,"LP"))
  270.     {
  271.       devices[F_LP]=fopen(right,"w");
  272.       return;
  273.     }
  274.     if (!strcmp(left,"U1"))
  275.     {
  276.       devices[F_U1]=fopen(right,"r+");
  277.       return;
  278.     }
  279.     if (!strcmp(left,"U2"))
  280.     {
  281.       devices[F_U2]=fopen(right,"r+");
  282.       return;
  283.     }
  284.     if (!strcmp(left,"DEBUG"))
  285.     {
  286.       debugflag=atoi(right);
  287.       return;
  288.     }
  289.     if (!strcmp(left,"DLOG"))
  290.     {
  291.       dlogflag=atoi(right);
  292.       return;
  293.     }
  294.     if (!strcmp(left,"BIOS"))
  295.     {
  296.       biosflag=atoi(right);
  297.       return;
  298.     }
  299.     if (!strcmp(left,"TRAP"))
  300.     {
  301.       sscanf(right,"%4x",&TRAPval);
  302.       return;
  303.     }
  304.     if (!strcmp(left,"TWRT"))
  305.     {
  306.       sscanf(right,"%4x",&TWRTval);
  307.       return;
  308.     }
  309. }
  310.  
  311. coredump()
  312. {
  313.   FILE *qb;
  314.   int i;
  315.  
  316.   qb=fopen("mem","w");
  317.   for(i=0;i!=65536;i++)
  318.     putc(real_z80_mem[i],qb);
  319.   fclose(qb);
  320. }
  321.