home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / amiga / splitter / loader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-10  |  9.4 KB  |  422 lines

  1. /*     SCCS Id: @(#)loader.c 3.1    93/01/08
  2. /*    Copyright (c) Kenneth Lorber, Bethesda, Maryland 1992, 1993 */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * Amiga split binary runtime system
  7.  */
  8.  
  9. /*#define LDEBUG         /* turn on debugging I/O */
  10. #define SDEBUG        /* static primary array allocation */
  11. /*#define NOCLEAN        /* turn off $ovl_memchain code */
  12. /*#define NOSPLIT        /* debug: load an unsplit binary(run ONCE!)*/
  13. #define MULTI            /* real file reading code */
  14. /*#define PARANOID        /* check for refs off end that might be OK */
  15. #define CACHE            /* deal with cache flushing */
  16.  
  17. unsigned long xx;
  18. long *yy;
  19.  
  20. #include "split.h"
  21.  
  22. #ifdef SPLIT
  23.  
  24. #include <stdio.h>        /* for spanic - should change */
  25. #include <exec/types.h>
  26. #include <exec/memory.h>
  27. #include <libraries/dosextens.h>
  28. #include <proto/dos.h>
  29. #include <proto/exec.h>
  30. #include <dos.h>            /* NOT libraries/dos.h! */
  31. #include "amiout.h"
  32.  
  33. #include "multi.h"
  34.  
  35. #define F_LOAD 0
  36. #define F_RELOAD 1
  37.  
  38. #define HT(x)    ((x) & ~MEM_OBJ_EXTEND)
  39.  
  40. void *$ovl_AllocMem(unsigned int);
  41. void spanic(char *);            /* think about this!!!! */
  42. void exit(int);
  43.  
  44. #ifdef SDEBUG
  45. unsigned long *$ovl_hunktable[500];    /* 223 as of 10/21/92 */
  46. #else
  47. unsigned long *(*$ovl_hunktable)[];
  48. int $ovl_hunktablesize;
  49. #endif
  50.  
  51. #ifndef NOCLEAN
  52. BPTR $ovlmemchain=0;
  53. #endif
  54. BPTR ovlfile=0;
  55. BPTR fh;
  56. ULONG database;
  57.  
  58. BPTR s_LoadSeg(char *);
  59. void s_UnLoadSeg(void);
  60. BPTR load_code(int,char *);
  61. void load_data(int,char *);
  62. unsigned long *load_hunk(BPTR,int,ULONG *);
  63.  
  64. #ifdef MULTI
  65. union multiopts mo;
  66.     /* dump these after testing */
  67. #define Read MultiRead
  68. #define Close MultiClose
  69. #endif
  70.  
  71. BPTR
  72. s_LoadSeg(dir)
  73.     char *dir;
  74.     {
  75.     static BPTR base;
  76.     static char never=1;
  77.     if(never){
  78. #ifdef LDEBUG
  79.         fprintf(stderr,"s_LoadSeg waiting\n");
  80.         Delay(100);
  81.         fprintf(stderr,"going\n");
  82. #endif
  83.         base=load_code(F_LOAD,dir);
  84. #ifndef NOSPLIT
  85.         load_data(F_LOAD,dir);
  86.         never=0;
  87. #endif
  88.     }else{
  89.         load_data(F_RELOAD,dir);
  90.     }
  91. #ifdef LDEBUG
  92.     fprintf(stderr,"loadseg done! (waiting)\n");
  93.     getchar();
  94. #endif
  95. #ifdef CACHE
  96.     {
  97.     struct Library *eb=OpenLibrary("exec.library",36);
  98.     if(eb){
  99.         CacheClearU();
  100.         CloseLibrary(eb);
  101.     } else {
  102.         /* force a context switch and hope for the best */
  103.         Delay(1);
  104.     }
  105.     }
  106. #endif
  107.     return(base);
  108. }
  109.  
  110. BPTR
  111. load_code(dummy,dir)
  112.     int dummy;    /* always F_LOAD */
  113.     char *dir;    /* direction file */
  114. {
  115.     ULONG x;
  116.     ULONG *xp;
  117.     ULONG c,hc;
  118.     ULONG r;
  119. #ifdef MULTI
  120.     mo.r.mor_tag='C';
  121.     fh=MultiOpen(dir,MODE_OLDFILE,&mo);
  122. #else
  123.     fh=Open("s_NetHack.c00",MODE_OLDFILE);
  124. #endif
  125.     if(fh==0){
  126.         fprintf(stderr,"open failed %d\n",IoErr());
  127.         spanic("missing code file");
  128.     }
  129.     Read(fh,&x,4);    /* HUNK_HEADER */
  130.     Read(fh,&x,4);    /* 0 */
  131.     Read(fh,&hc,4);    /* table size */
  132. #ifdef LDEBUG
  133.     fprintf(stderr,"hunk count=%d\n",hc);
  134. #endif
  135. #ifndef SDEBUG
  136.     $ovl_hunktable= (long*(*)[])$ovl_AllocMem(hc*4);
  137.     $ovl_hunktablesize=hc*4;
  138. #endif
  139. #ifdef LDEBUG
  140.     fprintf(stderr,"table at %08x\n",$ovl_hunktable);
  141. #endif
  142.     Read(fh,&x,4);    /* F==0 */
  143.     Read(fh,&x,4);    /* L==size-1 */
  144.     for(c=0;c<hc;c++){
  145.         Read(fh,&x,4);
  146. #ifdef SDEBUG
  147.         xx=$ovl_hunktable[c]=$ovl_AllocMem(x*4);
  148. #else
  149.         xx=(*$ovl_hunktable)[c]=$ovl_AllocMem(x*4);
  150. #endif
  151. #ifdef LDEBUG
  152.         fprintf(stderr,"t[%d]=%08x, len=%08x\n",c,xx,((long*)xx)[-2]);
  153. #endif
  154.     }
  155. #ifdef LDEBUG
  156.     fprintf(stderr,"TABLE LOADED\n");Delay(50);
  157. #endif
  158.     for(c=0,xp=(unsigned long*)1;xp;c++){
  159. #ifdef LDEBUG
  160. # ifdef SDEBUG
  161.         yy=$ovl_hunktable[c];
  162. # else
  163.         yy=(*$ovl_hunktable)[c];
  164. # endif
  165.         fprintf(stderr,"loading hunk %d@%08x len=%08x\n",c,yy,yy[-2]);
  166. #endif
  167. #ifdef SDEBUG
  168.         xp=load_hunk(fh,dummy,$ovl_hunktable[c]);
  169. #else
  170.         xp=load_hunk(fh,dummy,(*$ovl_hunktable)[c]);
  171. #endif
  172.     }
  173.     database=c-1;    /* first hunk for use for data on each load */
  174.     Close(fh);
  175. #ifdef LDEBUG
  176. # ifdef SDEBUG
  177.     fprintf(stderr,"retval=%08x\n",$ovl_hunktable[0]);
  178. # else
  179.     fprintf(stderr,"retval=%08x\n",(*$ovl_hunktable)[0]);
  180. # endif
  181. #endif
  182. #ifdef SDEBUG
  183.     r= (unsigned long) $ovl_hunktable[0];        /* BPTR to seglist */
  184. #else
  185.     r= (unsigned long) (*$ovl_hunktable)[0];    /* BPTR to seglist */
  186. #endif
  187.     return (BPTR)(r>>2)-1;
  188. }
  189.  
  190. void
  191. load_data(fl,dir)
  192.     int fl;
  193.     char *dir;
  194. {
  195.     int c;
  196.     unsigned long *x;
  197. #ifdef MULTI
  198.     mo.r.mor_tag='D';
  199.     fh=MultiOpen(dir,MODE_OLDFILE,&mo);
  200. #else
  201.     fh=Open("s_NetHack.d00",MODE_OLDFILE);
  202. #endif
  203.             /* doing it this way we don't need the hunk count */
  204.     for(c=database,x=(unsigned long*)1;x;c++){
  205. #ifdef SDEBUG
  206.         x=load_hunk(fh,fl,$ovl_hunktable[c]);
  207. #else
  208.         x=load_hunk(fh,fl,(*$ovl_hunktable)[c]);
  209. #endif
  210.     }
  211. #ifdef LDEBUG
  212.     fprintf(stderr,"end of load_data (waiting)\n");
  213.     getchar();
  214. #endif
  215.     Close(fh);
  216. }
  217.  
  218. unsigned long *
  219. load_hunk(ovlfile,fl,lbase)
  220.     BPTR ovlfile;        /* AmigaDOS file handle */
  221.     int fl;
  222.     ULONG *lbase;
  223. {
  224.     unsigned long data[2];
  225.     unsigned long *where;
  226.     unsigned long reloc_type;
  227.  
  228. #ifdef LDEBUG
  229.     {
  230.     int pos=Seek(ovlfile,0,0);
  231.     fprintf(stderr,"load_hunk (fpos=%08x) @%08x len=%08x(%08x)\n",pos,
  232.     lbase,lbase[-2],lbase[-2]/4);
  233.     }
  234. #endif
  235.     if(0==Read(ovlfile,data,sizeof(data))){
  236. #ifdef LDEBUG
  237.         fprintf(stderr,"getchar EOF\n");
  238.         getchar();
  239. #endif
  240.         return(0);    /* EOF */
  241.     }
  242. #ifdef LDEBUG
  243.     fprintf(stderr,"read type=%08x len=%08x(longs)\n",data[0],data[1]);
  244. #endif
  245.     if( HT(data[0])!=HUNK_CODE &&
  246.         HT(data[0])!=HUNK_DATA &&
  247.         HT(data[0])!=HUNK_BSS){
  248.         fprintf(stderr,"bad data=%08x\n",data[0]);
  249.         spanic("ovlfile cookie botch");
  250.     }
  251.     where=lbase;
  252. #if 0
  253.                 /* clear memory if:
  254.                  * 1. not the first time (MEMF_CLEAR'd already)
  255.                  * 2. data or bss (just in case)
  256.                  * This is just a sanity check since these are
  257.                  * the only hunks we should be seeing on reload.
  258.                  */
  259.     if(fl==F_RELOAD && (HT(data[0])==HUNK_DATA || HT(data[0])==HUNK_BSS)
  260. #endif
  261.     {
  262.         ULONG *p=where;        /* clear memory block */
  263.         ULONG c=(where[-2]/4)-1;    /* (len includes ptr) */
  264.         if(!TypeOfMem(p))spanic("clearing bogus memory");
  265.         while(c--)*p++=0;    /* not memset - use longs for speed */
  266.     }
  267.  
  268.     if(HT(data[0])==HUNK_DATA || HT(data[0])==HUNK_CODE){
  269.         xx=Read(ovlfile,where,data[1]*4);    /* load the block */
  270.         if(xx!=data[1]*4){
  271.             fprintf(stderr,"Read(%08x,%08x)->%08x\n",where,
  272.               data[1]*4,xx);
  273.             spanic("out of data");
  274.         }
  275.     } else {
  276. #ifdef LDEBUG
  277.         fprintf(stderr,"BSS - no load\n");
  278. #endif
  279.     }
  280.             /* link/relocate as needed */
  281.             /* NB this could be done faster if we keep a buffer of
  282.              * relocation information (instead of issuing 4 byte
  283.              * Reads)
  284.              */
  285.     xx=Read(ovlfile,&reloc_type,sizeof(reloc_type));
  286.     if(xx!=sizeof(reloc_type))spanic("lost reloc_type");
  287.     while(reloc_type!=HUNK_END){
  288.         unsigned long reloc_count;
  289.         unsigned long reloc_hunk;
  290.         unsigned long *base;
  291.         unsigned long reloc_offset;
  292.         if(reloc_type!=HUNK_RELOC32){
  293.             if(reloc_type==HUNK_END)continue;    /* and quit */
  294.             fprintf(stderr,"bad data %08x\n",reloc_type);
  295.             spanic("ovlfile reloc cookie botch");
  296.         }
  297.         xx=Read(ovlfile,&reloc_count,sizeof(reloc_count));
  298.         if(xx!=sizeof(reloc_count))spanic("lost reloc_count");
  299.         while(reloc_count){
  300.             xx=Read(ovlfile,&reloc_hunk,sizeof(reloc_hunk));
  301.             if(xx!=sizeof(reloc_count))spanic("lost reloc_hunk");
  302. #ifdef SDEBUG
  303.             base=$ovl_hunktable[reloc_hunk];
  304. #else
  305.             base=(*$ovl_hunktable)[reloc_hunk];
  306. #endif
  307. #ifdef LDEBUG
  308.             fprintf(stderr,"reloc #%d: hunk #%d@%08x\n",
  309.               reloc_count,reloc_hunk,base);
  310. #endif
  311.             while(reloc_count--){
  312.                 xx=Read(ovlfile,&reloc_offset,sizeof(long));
  313.                 if(xx!=sizeof(reloc_count))
  314.                     spanic("lost offset");
  315.                 if(reloc_offset<0 || reloc_offset>where[-2]){
  316.                     fprintf(stderr,"where[-2]==%08x\n",
  317.                       where[-2]);
  318.                     spanic("offset out of hunk");
  319.                 }
  320.                 {
  321.                 ULONG *p=(ULONG*)(((ULONG)where)+reloc_offset);
  322. #ifdef PARANOID
  323. /* NB - nasty violation of signed/unsigned here */
  324.                 {
  325.                 if(*p > base[-2])
  326.                   fprintf(stderr,
  327.                   "WARNING: offset points outside block\n");
  328.                 }
  329. #endif
  330. #ifdef LDEBUG
  331.                 fprintf(stderr,
  332.                   "reloc_offset=%08x where=%08x p=%08x\n",
  333.                   reloc_offset,where,p);
  334.                 fprintf(stderr," current *p=%08x\n",*p);
  335. #endif
  336.                 (*p)+=(unsigned long)base;
  337. #ifdef LDEBUG
  338.                 fprintf(stderr," new *p=%08x\n",*p);
  339. #endif
  340.                 }
  341.             }
  342.             xx=Read(ovlfile,&reloc_count,sizeof(reloc_count));
  343.             if(xx!=sizeof(reloc_count))spanic("lost reloc_count2");
  344.         }
  345.         xx=Read(ovlfile,&reloc_type,sizeof(reloc_type));
  346.         if(xx!=sizeof(reloc_count))spanic("lost reloc_type2");
  347.     }
  348.     return(where);            /* return execute start point */
  349. }
  350.  
  351. /*
  352.     -2    len (bytes)
  353.     -1    next block
  354.      0    data
  355.  */
  356. void *
  357. $ovl_AllocMem(len)
  358.     unsigned int len;
  359.     {
  360.     unsigned long *adr;
  361.     ULONG length=(len&0x0fffffff);
  362.                 /* Always clear the memory.  On reload of
  363.                  * bss or data we have to do it manually */
  364.     adr=AllocMem(length+8,(6&(len>>29))|MEMF_CLEAR);
  365.     {
  366.         int type=6&(len>>29);
  367.         if(    type!=MEMF_CHIP &&
  368.             type!=MEMF_FAST &&
  369.             type!=MEMF_PUBLIC &&
  370.             type != 0
  371.         ){
  372.             printf("%08x %08x* ",len,type);
  373.             spanic("bad memory type");
  374.         }
  375.     }
  376.     if(!adr)spanic("allocation failure");
  377.     adr[0]=length;
  378. #ifndef NOCLEAN
  379.     adr[1]=(unsigned long)$ovlmemchain;    /* list for freeing at end */
  380.     $ovlmemchain=((long)adr>>2)+1;    /* BPTR to next ptr */
  381. # ifdef LDEBUG
  382.     fprintf(stderr,"Alloc: adr[0]=%08x adr[1]=%08x\n",adr[0],adr[1]);
  383. # endif
  384. #endif
  385.     return adr+2;
  386. }
  387.  
  388. void
  389. s_UnLoadSeg()
  390. {
  391. #ifndef NOCLEAN
  392.     BPTR p,p1;
  393.  
  394. # ifdef LDEBUG
  395.     fprintf(stderr,"starting Free loop: ovlmemchain=%x\n",$ovlmemchain);
  396. # endif
  397.     for(p=$ovlmemchain;p;p=p1){
  398.         p1=*(BPTR *)BADDR(p);
  399. # ifdef LDEBUG
  400.         fprintf(stderr,"Free(%x,%x)\n",BADDR(p-1),
  401.           (*(long *)BADDR(p-1))+8);
  402. # endif
  403.         FreeMem(BADDR(p-1),(*(long *)BADDR(p-1))+8);
  404.     }
  405. #endif
  406. #ifndef SDEBUG
  407.     FreeMem($ovl_hunktable,$ovl_hunktablesize);
  408. #endif
  409.     return;
  410. }
  411.  
  412. /* this needs to be improved and integrated with wb.c */
  413. void
  414. spanic(s)
  415.     char *s;
  416. {
  417.     fprintf(stderr,"s_LoadSeg failed: %s\n",s);
  418.     getchar();
  419.     exit(1);
  420. }
  421. #endif /* SPLIT */
  422.