home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / emulation / qlsource / src / l_qdos.c next >
Encoding:
C/C++ Source or Header  |  1997-03-24  |  10.1 KB  |  550 lines

  1. ;/*
  2. A68k sub.asm
  3. dcc -o L_QDOS L_QDOS.c -l hardware SUB.o
  4. quit
  5. */
  6. /* L_QDOS loads and runs QDOS */
  7.  
  8. #include <exec/exec.h>
  9. #include <exec/libraries.h>
  10. #include <dos/dos.h>
  11. #include <intuition/intuition.h>
  12. #include <workbench/workbench.h>
  13. #include <stdio.h>
  14. #include <hardware/cia.h>
  15.  
  16. #define MAXROMS 16
  17.  
  18. extern struct ExecBase *SysBase;
  19. extern __far struct CIA ciaa, ciab;
  20.  
  21. typedef struct List         LIST;
  22. typedef struct Node         NODE;
  23. typedef struct MemHeader MEMHEADER;
  24. typedef struct MemChunk  MEMCHUNK;
  25.  
  26. extern int sub(),dummy();
  27. extern int subtoclear();
  28.  
  29. long ql_lomem,ql_himem,ql_ssp,ql_var,rom_lomem;
  30. int sflag,mflag,cflag,ccount,rflag,rcount,dflag;
  31. long qldate;
  32.  
  33. struct
  34. {
  35.   long day;
  36.   long min;
  37.   long tick;
  38. } date;
  39.  
  40. struct rominfo
  41. {
  42.   char *name;
  43.   VOID *fp;
  44.   long len;
  45.   long rlen;
  46. };
  47.  
  48. struct memrange
  49. {
  50.   long lomem;
  51.   long himem;
  52. };
  53.  
  54. struct memrange *toclear;
  55. struct rominfo rom[MAXROMS];
  56.  
  57. typedef struct CommandLineInterface CLI;
  58. typedef struct Process PROCESS;
  59.  
  60. CLI      *cli;
  61. PROCESS *proc;
  62.  
  63. extern int    _start_();
  64. extern int    _realstart_();
  65.  
  66. extern long _Detached_,   /* are we detached?    */
  67.                 _WorkBench_,  /* are we on the WB?    */
  68.                 _CLI_,          /* are we on the CLI? */
  69.                 _Process_;      /* are we a process?    */
  70. #if 1
  71. /* how to change the default console (if it's used) */
  72. char _DefaultConsole[] =
  73.          "CON:0/12/320/72/L_QDOS 2.04, loading QDOS...";
  74. #endif
  75.  
  76. char VERSTAG[] = "\0$VER: L_QDOS 2.04";
  77.  
  78. shutdown(s) char *s;
  79. {
  80.   printf("%ls\n",s);
  81.   if(_WorkBench_ || _Detached_)
  82.   {
  83.      Delay(500);
  84.   }
  85.   exit(0);
  86. }
  87.  
  88. usage()
  89. {
  90.   shutdown("L_QDOS v2.04\n\n"
  91.               "usage:\tL_QDOS [-r]\n"
  92.                       "\t       [-q<QDOS rom>]\n"
  93.                       "\t       [-p<MAIN rom>]\n"
  94.                       "\t       [-m<lomem><+len|-himem>]\n"
  95.                       "\t       [<OTHER roms>...]\n");
  96. }
  97.  
  98. warning(s) char *s;
  99. {
  100.   printf("%ls\n",s);
  101. }
  102.  
  103. char *
  104. getnum(p,np) char *p; long *np;
  105. { long n,h;
  106.   char c;
  107.   c=*p++;
  108.   n=0;
  109.   if(c!='$')
  110.   {
  111.      while(isdigit(c))
  112.      {
  113.         h=c-48;
  114.         n=n*10+h;
  115.         c=*p++;
  116.      }
  117.   }
  118.   else
  119.   {
  120.      c=*p++;
  121.      while(isxdigit(c))
  122.      {
  123.         h=(c<58?c-48:(c<96?c-55:c-87));
  124.         n=n*16+h;
  125.         c=*p++;
  126.      }
  127.   }
  128.   *np=n;
  129.   return --p;
  130. }
  131.  
  132. doflags(p) char *p;
  133. {
  134.   long num;
  135.   while(*p!=0)
  136.   { switch(toupper(*p++))
  137.      {
  138.      case 'D':
  139.         dflag=1;
  140.         break;
  141.      case 'R':
  142.         rflag=1;
  143.         break;
  144.      case 'Q':
  145.         rom[0].name=p;
  146.         while (*p!=0)
  147.           p++;
  148.         break;
  149.      case 'P':
  150.         rom[1].name=p;
  151.         while (*p!=0)
  152.           p++;
  153.         break;
  154.      case 'M':
  155.         while(*p!=0)
  156.         { p=getnum(p,&num);
  157.           switch(*p)
  158.           {
  159.           case '+':
  160.              mflag=1;
  161.              ql_var=num;
  162.              break;
  163.           case '-':
  164.              mflag=2;
  165.              ql_var=num;
  166.              break;
  167.           case 0:
  168.              switch(mflag)
  169.              {
  170.              case 1:
  171.                 ql_himem=ql_var+num;
  172.                 break;
  173.              case 2:
  174.                 ql_himem=num;
  175.                 break;
  176.              default:
  177.                 usage();
  178.              }
  179.              break;
  180.           default:
  181.              usage();
  182.           }
  183.           if(*p!=0)
  184.              p++;
  185.         }
  186.         break;
  187.      default:
  188.         usage();
  189.      }
  190.   }
  191. }
  192.  
  193. int
  194. findrom(rom) struct rominfo *rom;
  195. {
  196.   long len;
  197.   VOID *f;
  198.   char temp[80];
  199.   f = fopen(rom->name,"r");
  200.   if(f == 0)
  201.   { strcpy(temp,rom->name);
  202.      strcat(temp," not available");
  203.      warning(temp);
  204.      len=0;
  205.   }
  206.   else
  207.   { fseek(f,0,2);
  208.      len=ftell(f);
  209.      fseek(f,0,0);
  210.   }
  211.   rom->fp = f;
  212.   rom->len=len;
  213.   len+=255;
  214.   len&=-256;
  215.   rom->rlen=len;
  216.   return len;
  217. }
  218.  
  219. main(argc,argv)
  220. int argc;
  221. char **argv;
  222. {
  223.   int i,j,n;
  224.   long olddir;
  225.   long rom_tot,rom_len,len,rom_dst,sub_len,sub_dst;
  226.   char *p,*qp,*cp,**av;
  227.   long GfxBase;
  228.  
  229.   MEMHEADER *mh;
  230.   long mh_lower, mh_upper;
  231.  
  232.   _DetachFromCLI();         /* Does just that. (Or nothing if */
  233.                                  /* run from the WorkBench).          */
  234.  
  235.   _RunOnWorkBench();      /* Indicates this program should  */
  236.                                  /* continue and will run properly */
  237.                                  /* if started from the WorkBench. */
  238.                                  /* Well, you say it will.           */
  239.  
  240.   _ToolTypeArgs();         /* Means move tooltype array from */
  241.                                  /* .info file to argc,argv.          */
  242.  
  243.   _OpenDefaultConsole(); /* Need this to use printf's etc  */
  244.                                  /* when starting from WorkBench   */
  245.                                  /* or if you've detached.         */
  246.                                  /* (You won't need it if you're   */
  247.                                  /* only using intuition stuff).   */
  248.                                  /* Does nothing if you're running */
  249.                                  /* on the CLI/Shell.                  */
  250.  
  251.   toclear=(struct memrange *)subtoclear;
  252.  
  253.   mflag=sflag=cflag=ccount=rflag=dflag=0;
  254.   rcount=2;
  255.   ql_lomem=rom_lomem=0;
  256.   ql_himem=0x10000000;
  257.   ql_ssp=0x28480;
  258.   ql_var=0x28000;
  259.  
  260.   for(i=1;i<argc;i++)
  261.   {
  262. /*  printf("arg %ld = %ls\n",i,argv[i]); */
  263.      if(argv[i][0]=='?')
  264.         usage();
  265.      if(argv[i][0]=='-')
  266.         doflags(argv[i]+1);
  267.      else
  268.      {
  269.         if(rcount<MAXROMS)
  270.         { rom[rcount].name=argv[i];
  271.           rcount++;
  272.         }
  273.         else
  274.           shutdown("too many roms");
  275.      }
  276.   }
  277.   if(dflag!=0)
  278.      warning("...now in debug mode");
  279.  
  280.   if(dflag!=0)
  281.      printf("to clear structure=$%lx $%lx\n\n",(long)toclear,(long)subtoclear);
  282.  
  283.   ccount=0;
  284.   for (mh  = (MEMHEADER *)GetHead((LIST *)&SysBase->MemList);
  285.          mh != 0;
  286.          mh  = (MEMHEADER *)GetSucc((NODE *)mh))
  287.   {
  288.      mh_lower=mh->mh_Lower;
  289.      mh_upper=mh->mh_Upper;
  290.      if (((long)mh+sizeof(MEMHEADER))=mh_lower)
  291.         mh_lower=(long)mh;
  292.  
  293.      if (ccount!=0)
  294.         for (i=0;i<ccount;i++)
  295.           if (mh_lower<toclear[i].lomem)
  296.           {
  297.              n=mh_lower;mh_lower=toclear[i].lomem;toclear[i].lomem=n;
  298.              n=mh_upper;mh_upper=toclear[i].himem;toclear[i].himem=n;
  299.           }
  300.  
  301.      toclear[ccount].lomem=mh_lower;
  302.      toclear[ccount].himem=mh_upper;
  303.      ccount++;
  304.  
  305.   }
  306.  
  307.   i=0;
  308.   while ((i<ccount)&(ql_var>toclear[i].himem))
  309.      i++;
  310.  
  311.   if (i<ccount)
  312.      if (ql_var<toclear[i].lomem)
  313.         ql_var=toclear[i].lomem;
  314.  
  315.   i=ccount-1;
  316.   while ((i>=0)&(ql_himem<toclear[i].lomem))
  317.      i--;
  318.  
  319.   if (i>=0)
  320.      if (ql_himem>toclear[i].himem)
  321.         ql_himem=toclear[i].himem;
  322.  
  323.   if (ql_himem>0x1000000)
  324.      if (ql_var<toclear[ccount-1].lomem)
  325.         ql_var=toclear[ccount-1].lomem;
  326.  
  327.   if(dflag!=0)
  328.   {
  329.      for (i=0;i<ccount;i++)
  330.         printf("$%08lX $%08lX \n",toclear[i].lomem,toclear[i].himem);
  331.   }
  332.  
  333.   if(rom[0].name==0)
  334.      rom[0].name="QLboot:ROMs/SYS_cde";
  335.   if(rom[1].name==0)
  336.      rom[1].name="QLboot:ROMs/MAIN_cde";
  337.   rom_tot=0;
  338.   for(i=0;i==0 || i<rcount;i++)
  339.   { len=findrom(&rom[i]);
  340.      if((len==0)&&(i<2))
  341.         shutdown("sorry but I can't load QDOS");
  342.      if(dflag!=0)
  343.         printf("%ls\n",rom[i].name);
  344.  
  345.      rom_tot+=len;
  346.   }
  347.  
  348.   if(dflag!=0)
  349.      printf("total space req=$%lx/%ld\n",rom_tot,rom_tot);
  350.  
  351.   if(rom_tot!=0)
  352.   {
  353.      p = (char *)malloc(rom_tot);
  354.      if(p==0)
  355.         shutdown("no memory");
  356.      qp=p;
  357.      for(i=0;i<rcount;i++)
  358.      { if(rom[i].len!=0)
  359.         { fread(p,rom[i].len,1,rom[i].fp);
  360.           p+=rom[i].rlen;
  361.         }
  362.      }
  363.   }
  364.  
  365.   rom_len=rom_tot-rom[0].rlen-rom[1].rlen;
  366.  
  367.   if(dflag!=0)
  368.   { printf("QDOS and ROMS source=$%lx\n",qp);
  369.      printf("QDOS len=$%lx\n",rom[0].rlen);
  370.      printf("MAIN len=$%lx\n",rom[1].rlen);
  371.      printf("ROMs len=$%lx\n\n",rom_len);
  372.   }
  373.  
  374.   DateStamp(&date);
  375.   qldate=date.day+365*17+4;
  376.   qldate=qldate*(24*60*60/8);
  377.   qldate<<=3;
  378.   qldate+=(date.min*60);
  379.   qldate+=(date.tick/50);
  380.   if(dflag!=0)
  381.   { printf("days=%ld mins=%ld ticks=%ld\n",date.day,date.min,date.tick);
  382.      printf("qldate=$%08lx\n",qldate);
  383.   }
  384.  
  385.   ql_var=(ql_var+0x7FFF)&(-0x8000);
  386.   ql_himem=ql_himem&(-0x200);
  387.  
  388.   rom_dst=(ql_himem-rom_len)&(-0x200);
  389.   sub_len=(long)dummy-(long)sub;
  390.   sub_dst=((ql_himem-rom_tot)&(-0x200))-sub_len;
  391.  
  392.   ql_himem=rom_dst;
  393.   if(rflag!=0)
  394.      if(ql_himem>0x200000)
  395.         ql_himem=ql_himem-rom[0].rlen+0x600;
  396.  
  397.   if(dflag!=0)
  398.      printf("rom_dst=$%lx\n",rom_dst);
  399.  
  400.   if(ql_var<0x28000)
  401.      ql_var=0x28000;
  402.  
  403.   ql_ssp=ql_var+0x480;
  404.   ql_lomem=ql_ssp;
  405.  
  406.   if(dflag!=0)
  407.      printf("lomem=$%lx himem=$%lx\n\n",ql_lomem,ql_himem);
  408.  
  409.  
  410.   if(ql_lomem>=ql_himem)
  411.      shutdown("bad value for memory range\n...might be out of memory\n ");
  412.  
  413. check_dst:
  414.   if(((long)qp <= sub_dst) && ((long)qp + rom_tot > sub_dst))
  415.      sub_dst=qp-sub_len;
  416.   if(((long)sub<=sub_dst)&&((long)sub+sub_len>sub_dst))
  417.   { sub_dst=(long)sub-sub_len;
  418.      goto check_dst;
  419.   }
  420.   if(dflag!=0)
  421.      printf("sub src=$%lx sub dst=$%lx sub len=$%lx\n\n"
  422.               ,(long)sub,sub_dst,sub_len);
  423.  
  424.   i=0;
  425.   while(i<ccount)
  426.   {
  427.      if(toclear[i].lomem<rom[0].rlen)
  428.      { if(toclear[i].himem>rom[0].rlen)
  429.           toclear[i].lomem=rom[0].rlen;
  430.         else
  431.           goto removerange;
  432.      }
  433.  
  434.      if(toclear[i].lomem<0x1F400)
  435.      { if(toclear[i].himem>0x1F400)
  436.         { if(toclear[i].himem>(0x1F400+rom[1].rlen))
  437.           { if(ccount<8)
  438.              { toclear[ccount].lomem=0x1F400+rom[1].rlen;
  439.                 toclear[ccount].himem=toclear[i].himem;
  440.                 ccount++;
  441.              }
  442.              else
  443.                 shutdown("range too complex");
  444.              }
  445.  
  446.           toclear[i].himem=0x1F400;
  447.         }
  448.      }
  449.  
  450.      if(toclear[i].lomem<sub_dst)
  451.      { if(toclear[i].himem>sub_dst)
  452.         { if(toclear[i].himem>(sub_dst+sub_len))
  453.           { if(ccount<8)
  454.              { toclear[ccount].lomem=sub_dst+sub_len;
  455.                 toclear[ccount].himem=toclear[i].himem;
  456.                 ccount++;
  457.              }
  458.              else
  459.                 shutdown("range too complex");
  460.              }
  461.  
  462.           toclear[i].himem=sub_dst;
  463.         }
  464.      }
  465.  
  466.      if(toclear[i].lomem<rom_dst)
  467.      { if(toclear[i].himem>rom_dst)
  468.         { if(toclear[i].himem>(rom_dst+rom_len))
  469.           { if(ccount<8)
  470.              { toclear[ccount].lomem=rom_dst+rom_len;
  471.                 toclear[ccount].himem=toclear[i].himem;
  472.                 ccount++;
  473.              }
  474.              else
  475.                 shutdown("range too complex");
  476.              }
  477.  
  478.           toclear[i].himem=rom_dst;
  479.         }
  480.      }
  481.  
  482.      if(toclear[i].lomem<ql_himem)
  483.      { if(toclear[i].himem>ql_himem)
  484.           toclear[i].himem=ql_himem;
  485.      }
  486.      else
  487.         goto removerange;
  488.  
  489.      if(toclear[i].lomem==toclear[i].himem)
  490.         goto removerange;
  491.  
  492.      i++;
  493.      goto endwhile;
  494.  
  495.      removerange:
  496.      ccount--;
  497.      toclear[i].lomem=toclear[ccount].lomem;
  498.      toclear[i].himem=toclear[ccount].himem;
  499.      endwhile:
  500.   }
  501.   toclear[ccount].lomem=0;
  502.   toclear[ccount].himem=0;
  503.  
  504.   if(dflag!=0)
  505.   { i=0;
  506.      while(i<ccount)
  507.      { printf("range: lomem=$%lx himem=%lx\n"
  508.                  ,toclear[i].lomem,toclear[i].himem);
  509.         i++;
  510.      }
  511.   }
  512.  
  513.   if(dflag!=0)
  514.   { printf("vars=$%lx ssp=$%lx\n\n",ql_var,ql_ssp);
  515.      shutdown("quitting L_QDOS...\n");
  516.   }
  517.  
  518.   GfxBase=0;
  519.   if (!(GfxBase =
  520.         OpenLibrary("graphics.library",0)))
  521.      goto die;
  522.  
  523.   LoadView(NULL);
  524.  
  525.   if (GfxBase)
  526.      CloseLibrary(GfxBase);
  527.  
  528. die:
  529.   Forbid();
  530.   Disable();
  531.   OwnBlitter();
  532.   while(WaitBlit());
  533.  
  534.   if(((struct Library *)SysBase)->lib_Version>=37)
  535.     CacheControl(0,CACRF_EnableI|CACRF_EnableD|CACRF_IBE|CACRF_DBE);
  536.  
  537. /* deselect all drives                                */
  538.   ciab.ciaprb|=CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
  539. /* motor signal (off)                                */
  540.   ciab.ciaprb|=CIAF_DSKMOTOR;
  541. /* select all drives (thus, switch them off) */
  542.   ciab.ciaprb&=~(CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3);
  543. /* deselect drives again (well, why not?)     */
  544.   ciab.ciaprb|=CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
  545.  
  546.   sub(sub_dst,ql_lomem,ql_himem,rom_dst,qp,
  547.         rom[0].rlen,rom_len,rom[1].rlen,ql_ssp,qldate);
  548. }
  549.  
  550.