#include #include "types.h" #include #include #include #include #include "memman.h" #include //#include #include "swaper.c" #include #include #include #define DPMI_INT 0x31 #define LOAD_BUFFER 4096 #undef malloc void bonz_table(); #define NON_GETMEM_RESERVED (4*1024) char **mman_pathlist=NULL; static char swap_status=0; static FILE *swap = NULL; char mman_patch=0; int memman_handle; static int max_handle=0; //static FILE *log; void (*mman_action)(int action)=NULL; int32_t last_load_size; void standard_mem_error(size_t size) { char buff[256]; SEND_LOG("(ERROR) Memory allocation error detected, %u bytes missing",size,0); DXCloseMode(); sprintf(buff,"Memory allocation error\n Application can't allocate %lu bytes of memory (%xh)\n",size,memman_handle); display_error(buff); exit(1); } void load_error(char *filename) { char buff[256]; SEND_LOG("(ERROR) Load error detected, system can't load file: %s",filename,0); #ifdef LOGFILE // bonz_table(); #endif DXCloseMode(); sprintf(buff,"Load error while loading file: %s", filename); display_error(buff); exit(1); } void standard_swap_error() { char buff[256]; DXCloseMode(); sprintf(buff,"Swap error. Maybe disk is full"); display_error(buff); exit(1); } void (*mem_error)(size_t)=standard_mem_error; void (*swap_error)()=standard_swap_error; void *getmem(int32_t size) { void *p,*res; if (!size) return NULL; do { res=malloc(NON_GETMEM_RESERVED); if (res!=NULL) { p=(void *)malloc(size); free(res); } else p=NULL; if (p==NULL) mem_error(size); } while (p==NULL); // SEND_LOG("(ALLOC) **** Alloc: %p size %d",p,*((int32_t *)p-1)); return p; } void *load_file(char *filename) { FILE *f; int32_t size,*p; if (mman_action!=NULL) mman_action(MMA_READ); SEND_LOG("(LOAD) Loading file '%s'",filename,0); f=fopen(filename, "rb"); if (f==NULL) { load_error(filename); return NULL; } fseek(f,0, SEEK_END); size=ftell(f); fseek(f,0, SEEK_SET); p=(void *)getmem(size); if (fread(p,1,size,f)!=size) load_error(filename); fclose(f); last_load_size=size; return p; } //--------------- BLOCK MASTER OPERATION SYSTEM -------------------------- //--------------- part: MEMORY MANAGER ----------------------------------- typedef struct tnametable { char name[12]; int32_t seek; }TNAMETABLE; static int32_t *grptable,grptabsiz; static TNAMETABLE *nametable; static int nmtab_size; static int next_name_read=0; static int last_group; char *main_file_name=NULL; handle_groups _handles; static FILE *bmf=NULL; static FILE *patch=NULL; uint32_t bk_global_counter=0; char *swap_path; #ifdef LOGFILE static void bonz_table() { int i; if (bmf==-1) return; for(i=0;i>3);i++) grptable[i*2+1]=(grptable[i*2+1]-grptabsiz)>>4; SEND_LOG("(LOAD) Group Table Loaded",0,0); } void load_file_table() { int strsize; void *p; SEND_LOG("(LOAD) Loading File Table",0,0); fseek(bmf,grptabsiz,SEEK_SET); fseek(bmf,12,SEEK_CUR); fread(&strsize,4,1,bmf); strsize-=grptabsiz; fseek(bmf,grptabsiz,SEEK_SET); p=getmem(strsize);memcpy(&nametable,&p,4); fread(nametable,1,strsize,bmf); nmtab_size=strsize/sizeof(*nametable); SEND_LOG("(LOAD) File Table Loaded",0,0); } int find_name(int group,char *name) { int i; for(i=0;i<(grptabsiz>>2);i+=2) { if (grptable[i]==group) break; } if ((grptabsiz>>2)<=i) return -1; for(i=grptable[i+1];iflags & BK_HSWAP) pos=h->seekpos; else pos=swap_add_block(h->size); fseek(swap,0,SEEK_END); wsize=ftell(swap); fseek(swap,pos,SEEK_SET); SEND_LOG("(SWAP) Swaping block '%-.12hs'",h->src_file,0); wsize=fwrite(h->blockdata,1,h->size,swap); swap_status=1; if ((unsigned)wsize==h->size) { h->seekpos=pos; if (h->flags & BK_PRELOAD) h->flags&=~BK_SWAPABLE; h->flags|=BK_HSWAP; return 0; } else { SEND_LOG("(SWAP) Swap failed!",0,0); swap_error(); } swap_free_block(pos,h->size); return -1; } THANDLE_DATA *get_handle(int handle) { int group,list; group=handle/BK_MINOR_HANDLES; list=handle % BK_MINOR_HANDLES; if (_handles[group]==NULL) { _handles[group]=(handle_list *)getmem(sizeof(handle_list)); memset(_handles[group],0,sizeof(handle_list)); } if (handle>max_handle) max_handle=handle; return ((THANDLE_DATA *)_handles[group])+list; } void heap_error(size_t size) //heap system { int i,j; char swaped=0; uint32_t maxcounter=0; THANDLE_DATA *sh; char repeat=0,did=0; THANDLE_DATA *lastblock=NULL; char *last_free=NULL; int num; do { maxcounter=0; sh=NULL; repeat=0;did=0; for(i=0;icounter; if (h->status==BK_PRESENT && ~h->flags & BK_LOCKED) if (last_free!=NULL) { d=(char *)h->blockdata-last_free; if (dmaxcounter) { maxcounter=c; sh=h; did=1; num=i*BK_MINOR_HANDLES+j; } } } if (lastblock==sh) { did=0;repeat=0; } if (did) { size-=sh->size; last_free=sh->blockdata; if (sh->flags & BK_SWAPABLE) { if (swap_block(sh)) //pri neuspechu o ulozeni je nalezen blok jiny { sh->counter=bk_global_counter; repeat=1; } else { free(sh->blockdata); sh->status=BK_SWAPED; swaped=1; } } else { if (sh->flags & BK_PRELOAD) sh->status=BK_SWAPED; else sh->status=BK_NOT_LOADED; free(sh->blockdata); if (mman_action!=NULL) mman_action(MMA_FREE); } } else standard_mem_error(size); lastblock=sh; } while (repeat || size>0); // if (swaped) _dos_commit(swap); } THANDLE_DATA *kill_block(int handle) { THANDLE_DATA *h; h=get_handle(handle);if (h->status==BK_NOT_USED) return h; if (h->flags & BK_LOCKED) { SEND_LOG("(ERROR) Unable to kill block! It is LOCKED! '%-.12hs' (%04X)",h->src_file,handle); return NULL; } SEND_LOG("(KILL) Killing block '%-.12hs' (%04X)",h->src_file,handle); if (h->status==BK_SAME_AS) return h; if (h->status==BK_PRESENT) free(h->blockdata); if (h->flags & BK_HSWAP) swap_free_block(h->seekpos,h->size); h->status=BK_NOT_LOADED; h->flags&=~BK_HSWAP; return h; } THANDLE_DATA *zneplatnit_block(int handle) { THANDLE_DATA *h; h=kill_block(handle); if (h->status==BK_SAME_AS) return zneplatnit_block(h->seekpos); if (h->src_file[0]) h->seekpos=get_file_entry(h->path,h->src_file); return h; } void init_manager(char *filename,char */*swap is not supported*/) // filename= Jmeno datoveho souboru nebo NULL pak // se pouzije DOS // swp je cesta do TEMP adresare { next_name_read=0; last_group=0; memset(_handles,0,sizeof(_handles)); if (filename!=NULL) { bmf=fopen(filename,"rb"); if (bmf) { main_file_name=(char *)getmem(strlen(filename)+1); strcpy(main_file_name,filename); load_grp_table(); load_file_table(); } else main_file_name=NULL; } else main_file_name=NULL; mem_error=heap_error; swap=NULL; } void *load_swaped_block(THANDLE_DATA *h) { void *i; if (mman_action!=NULL) mman_action(MMA_SWAP_READ); i=getmem(h->size); SEND_LOG("(LOAD)(SWAP) Loading block from swap named '%-.12hs'",h->src_file,0); fseek(swap,h->seekpos,SEEK_SET); fread(i,1,h->size,swap); h->status=BK_PRESENT; return i; } int find_same(char *name,void *decomp) { THANDLE_DATA *p; int i,j; decomp; if (name[0]==0) return -1; for(i=0;istatus=BK_SAME_AS; h->seekpos=i; return h; } memcpy(h->src_file,filename,12); h->seekpos=0; strupr(h->src_file); h->loadproc=decompress; if (filename[0]) h->seekpos=get_file_entry(path,h->src_file); SEND_LOG("(REGISTER) File/Block registred '%-.12hs' handle %04X",h->src_file,handle); SEND_LOG("(REGISTER) Seekpos=%d",h->seekpos,0); h->flags=0; h->path=path; if (h->status!=BK_DIRLIST) h->status=BK_NOT_LOADED; h->counter=bk_global_counter++; return h; } void *afile(char *filename,int group,int32_t *blocksize) { char *c,*d; int32_t entr; void *p; d=alloca(strlen(filename)+1); strcpy(d,filename); strupr(d); if (mman_patch && test_file_exist_DOS(group,d)) entr=0; else entr=get_file_entry(group,d); if (entr!=0) { FILE *hnd; SEND_LOG("(LOAD) Afile is loading file '%s' from group %d",d,group); if (entr<0) entr=-entr,hnd=patch;else hnd=bmf; fseek(hnd,entr,SEEK_SET); fread(blocksize,1,4,hnd); p=getmem(*blocksize); fread(p,1,*blocksize,hnd); } else if (mman_pathlist!=NULL) { SEND_LOG("(LOAD) Afile is loading file '%s' from disk",d,group); c=alloca(strlen(filename)+strlen(mman_pathlist[group])+2); c=strcat(strcpy(c,mman_pathlist[group]),filename); p=load_file(c); *blocksize=last_load_size; } else return NULL; return p; } void *ablock(int handle) { THANDLE_DATA *h; sem: h=get_handle(handle); if (memman_handle!=handle || h->status!=BK_PRESENT) h->counter=bk_global_counter++; memman_handle=handle; if (h->status==BK_SAME_AS) { handle=h->seekpos; goto sem; } if (h->status==BK_PRESENT) return h->blockdata; if (h->status==BK_DIRLIST) { free(h->blockdata);h->status=BK_NOT_LOADED; } if (h->status==BK_NOT_LOADED) { void *p;int32_t s; char c[200]; SEND_LOG("(LOAD) Loading file as block '%-.12hs' %04X",h->src_file,handle); if (h->seekpos==0) { if (h->src_file[0]!=0) { if (mman_action!=NULL) mman_action(MMA_READ); strcpy(c,mman_pathlist[h->path]);strcat(c,h->src_file); c[strlen(mman_pathlist[h->path])+12]='\0'; p=load_file(c); s=last_load_size; } else { p=NULL; s=0; } if (h->loadproc!=NULL) h->loadproc(&p,&s); h->blockdata=p; h->status=BK_PRESENT; h->size=s; return p; } else { int entr=h->seekpos; FILE *hnd; if (mman_action!=NULL) mman_action(MMA_READ); if (entr<0) entr=-entr,hnd=patch;else hnd=bmf; fseek(hnd,entr,SEEK_SET); fread(&s,1,4,hnd); p=getmem(s); fread(p,1,s,hnd); if (h->loadproc!=NULL) h->loadproc(&p,&s); h->blockdata=p; h->status=BK_PRESENT; h->size=s; return p; } } //tato cast programu bude jeste dodelana - else .... if (h->status==BK_SWAPED) { return h->blockdata=load_swaped_block(h); } return NULL; } void alock(int handle) { THANDLE_DATA *h; h=get_handle(handle); if (!h->lockcount) { h->flags|=BK_LOCKED; if (h->status==BK_SAME_AS) alock(h->seekpos); } h->lockcount++; //SEND_LOG("(LOCK) Handle locked %04X (count %d)",handle,h->lockcount); } void aunlock(int handle) { THANDLE_DATA *h; h=get_handle(handle); if (h->lockcount) h->lockcount--;else return; if (!h->lockcount) { h->flags&=~BK_LOCKED; if (h->status==BK_SAME_AS) aunlock(h->seekpos); } //SEND_LOG("(LOCK) Handle unlocked %04X (count %d)",handle,h->lockcount); } void aswap(int handle) { THANDLE_DATA *h; h=get_handle(handle); h->flags|=BK_SWAPABLE; if (h->status==BK_SAME_AS) aswap(h->seekpos); } void aunswap(int handle) { THANDLE_DATA *h; h=get_handle(handle); h->flags|=BK_SWAPABLE; if (h->status==BK_SAME_AS) aunswap(h->seekpos); } void apreload(int handle) { THANDLE_DATA *h; h=get_handle(handle); if (h->src_file[0] && h->status!=BK_SAME_AS) { if (!(h->flags & BK_PRELOAD) || !(h->flags & BK_HSWAP)) h->flags|=BK_SWAPABLE | BK_PRELOAD; ablock(handle); } } static int32_t *apr_sign=NULL; static int32_t max_sign; void apreload_sign(int handle,int max_handle) { THANDLE_DATA *h; if (apr_sign==NULL) { apr_sign=NewArr(int32_t,max_handle); memset(apr_sign,0x7f,sizeof(int32_t)*max_handle); max_sign=max_handle; } if (handle>=max_sign) { apreload(handle); return; } h=get_handle(handle); if (h->src_file[0] && h->status!=BK_SAME_AS && h->status!=BK_NOT_USED) if (!(h->flags & BK_PRELOAD) || !(h->flags & BK_HSWAP)) apr_sign[handle]=h->seekpos; } int apreload_sort(const void *val1,const void *val2) { int32_t vl1,vl2; vl1=apr_sign[*(word *)val1]; vl2=apr_sign[*(word *)val2]; return (vl1>vl2)-(vl1status==BK_PRESENT) swap_block(h); percent(c+i,c+max_sign); } // _dos_commit(swap); free(apr_sign); free(p); apr_sign=NULL; } void undef_handle(int handle) { THANDLE_DATA *h; h=get_handle(handle); if (h->status!=BK_NOT_USED) { if (kill_block(handle)==NULL) return; SEND_LOG("(REGISTER) File/Block unregistred %04X (%-.12hs)",handle,h->src_file); } h->src_file[0]=0; h->seekpos=0; h->flags=0; h->status=BK_NOT_USED; } void close_manager() { int i,j; for(i=0;istatus!=BK_NOT_USED && h->status!=BK_SAME_AS) { int k; for(k=0;k<5;k++) copys[k]=h->flags & (1<src_file[0]) strncpy(nname,h->src_file,12);else strcpy(nname,""); printf("%04Xh ... %12s %s %s %08lXh %6d %10d %6d \n",i*BK_MINOR_HANDLES+j, nname,names[h->status-1], copys,(uintptr_t)h->blockdata,h->size,h->counter,h->lockcount); ln++; total_data+=h->size; if(h->status==BK_PRESENT)total_mem+=h->size; if (ln%24==23) { char c; printf("Enter to continue, q-quit:"); c=getchar(); if (c=='q' || c=='Q') { while (getchar()!='\n'); return; } } } } } printf("Data: %7d KB, Loaded: %7d KB",total_data/1024,total_mem/1024); while (getchar()!='\n'); } void *grealloc(void *p,int32_t size) { void *q; int32_t scop; if (!size) { free(p); return NULL; } q=realloc(p,size); if (q!=NULL) { SEND_LOG("(ALLOC) **** Realloc: New %p size %d\n",q,*((int32_t *)q-1)); return q; } q=getmem(size); free(q); q=realloc(p,size); return q; } char *read_next_entry(char mode) { if (mode==MMR_FIRST) next_name_read=0; if (main_file_name==NULL) return NULL; if (next_name_read>=nmtab_size) return NULL; return nametable[next_name_read++].name; } int read_group(int index) { return grptable[index<<1]; } char add_patch_file(char *filename) { int32_t l; int32_t poc; int i,cc=0; TNAMETABLE p; SEND_LOG("Adding patch: %s",filename,0); if (!patch) return 2; if (!bmf) return 3; patch=fopen(filename,"rb"); if (!patch) return 1; fseek(patch,4,SEEK_SET); fread(&l,1,4,patch); fseek(patch,l,SEEK_SET); fread(&p,1,sizeof(p),patch); poc=(p.seek-l)/sizeof(p); fseek(patch,l,SEEK_SET); for(i=0;itm_hour,newtime->tm_min,newtime->tm_sec); return text; } #endif int32_t get_handle_size(int handle) { THANDLE_DATA *h; h=get_handle(handle); if (h->status==BK_NOT_USED) return -1; return h->size; } /*void *malloc(size_t size) { static char zavora=1; void *c; c=_nmalloc(size); if (log!=NULL && zavora) { zavora=0; fprintf(log,"Alloc: %p size %d\n",c,*((int32_t *)c-1)); zavora=1; } return c; } */ FILE *afiletemp(char *filename, int group) { int32_t size; void *p=afile(filename,group,&size); FILE *f; if (p==NULL) return NULL; f=tmpfile(); if (f==NULL) {free(p);return NULL;} fwrite(p,size,1,f); fseek(f,0,SEEK_SET); return f; }