#include "System.h" #include "User.h" /* * BSX.c: Manager for BSX graphics objects. At the moment this is simply a case of tagging the items in memory * and keeping a linked list of them. * * * 1.00 AGC Added BSX support to AberMUD 5.21 * 1.01 AGC -1 can be used to specify remove this object * 1.02 AGC Extra newlines between commands removed. Purge done on * object loads. * 1.03 AGC ANSIfication * */ Module "BSX"; Author "Alan Cox"; Version "1.03"; extern USER UserList[]; extern char CmdBuffer[]; static BSXImage *BSXImageList=NULL; BSXImage *BSXAllocate(char *name, int size) { BSXImage *image=Allocate(BSXImage); strncpy(image->bsx_Identifier,name,8); image->bsx_Identifier[8]=0; image->bsx_Data=(unsigned char *)malloc(size); if(image->bsx_Data==NULL) Error("Out of memory"); image->bsx_DataSize=size; image->bsx_Next=BSXImageList; BSXImageList=image; return(image); } BSXImage *BSXFindFirst(void) { return(BSXImageList); } BSXImage *BSXFindNext(BSXImage *image) { return(image->bsx_Next); } BSXImage *BSXFind(char *name) { BSXImage *image=BSXFindFirst(); while(image!=NULL) { if(strcmp(name,image->bsx_Identifier)==0) return(image); image=BSXFindNext(image); } return(NULL); } void BSXDelete(BSXImage *i) { if(i==BSXImageList) { BSXImageList=i->bsx_Next; } else { BSXImage *walk=BSXFindFirst(); while(walk->bsx_Next!=NULL) { if(walk->bsx_Next==i) { walk->bsx_Next=i->bsx_Next; break; } } if(walk->bsx_Next==NULL) Error("Invalid BSXImage pointer"); walk=walk->bsx_Next; } free(i->bsx_Data); free(i); } static int HexDecode(char x) { if(x>='0'&&x<='9') return(x-'0'); if(x>='A'&&x<='F') return(x-'A'+10); if(x>='a'&&x<='f') return(x-'a'+10); return(-1); } int BSXEncodePair(char *buf) { int result; int v; v=HexDecode(*buf++); if(v==-1) return(-1); result=v*16; v=HexDecode(*buf); if(v==-1) return(-1); result=result+v; return(result); } void BSXDecodePair(unsigned char in, char *out) { static char hexify[]="0123456789ABCDEF"; *out++=hexify[in/16]; *out=hexify[in&0x0F]; } /* * Load and encode a BSX image from a path */ BSXImage *BSXLoadImage(char *name, char *path) { FILE *f=fopen(path,"r"); BSXImage *image; unsigned char *data; int size; int code; char buf[2]; if(f==NULL) return(NULL); if(fseek(f,0L,2)==-1) { fclose(f); return(NULL); } size=(int)ftell(f); rewind(f); size/=2; /* Hex cost */ image=BSXAllocate(name,size); if(image==NULL) { fclose(f); return(NULL); } data=image->bsx_Data; while(fread(buf,2,1,f)==1) { code=BSXEncodePair(buf); if(code==-1) { BSXDelete(image); fclose(f); return(NULL); } *data++=code; } fclose(f); return(image); } void Cmd_DeleteBSX(ITEM *i) { BSXImage *image; if(!ArchWizard(i)) { SendItem(i,"Pardon ?\n"); return; } if(GetWord()==(WLIST *)(-1)) { SendItem(i,"Yes, but which BSX object ?\n"); return; } image=BSXFind(WordBuffer); if(image==NULL) { SendItem(i,"Unknown BSX object.\n"); return; } BSXDelete(image); SendItem(i,"Ok.\n"); } void Cmd_LoadBSX(ITEM *i) { BSXImage *image; int u=0; if(!ArchWizard(i)) { SendItem(i,"Pardon ?\n"); return; } if(GetWord()==(WLIST *)(-1)) { SendItem(i,"Yes, but what shall I call it.\n"); return; } if(BSXFind(WordBuffer)!=NULL) { SendItem(i,"BSX item already exists.\n"); return; } strcpy(CmdBuffer,WordBuffer); GetAll(); if(*WordBuffer==0) { SendItem(i,"Load which file.\n"); return; } image=BSXLoadImage(CmdBuffer,WordBuffer); if(image==NULL) { SendItem(i,"Load failed.\n"); return; } SendItem(i,"Ok.\n"); /* Invalidate user caches */ while(u<MAXUSER) { if(UserList[u].us_Port!=NULL) { SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,"@PUR"); SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,CmdBuffer); SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,"."); } u++; } } void Cmd_ListBSX(ITEM *i) { BSXImage *image; if(!ArchWizard(i)) { SendItem(i,"Pardon ?\n"); return; } image=BSXFindFirst(); while(image!=NULL) { SendItem(i,"%s\n",image->bsx_Identifier); image=BSXFindNext(image); } } void Cmd_ShowBSX(ITEM *i) { BSXImage *image; if(!ArchWizard(i)) { SendItem(i,"Pardon ?\n"); return; } if(GetWord()==(WLIST *)(-1)) { SendItem(i,"Yes, but which BSX object ?\n"); return; } image=BSXFind(WordBuffer); if(image==NULL) { SendItem(i,"Unknown BSX object.\n"); return; } if(!IsUser(i)) return; SendTPacket(UserList[UserOf(i)].us_Port,PACKET_BSXSCENE,"@SCE"); SendTPacket(UserList[UserOf(i)].us_Port,PACKET_BSXSCENE,image->bsx_Identifier); SendTPacket(UserList[UserOf(i)].us_Port,PACKET_BSXSCENE,".@RFS"); SendItem(i,"Ok.\n"); } /* * Client callback processor */ void BSXDecompSend(int user, BSXImage *image) { /* Use the CmdBuffer again for this - 512 bytes of work space */ int ct=0; int cto=0; unsigned char *ptr=image->bsx_Data; while(ct<image->bsx_DataSize) { BSXDecodePair(*ptr++,&CmdBuffer[cto]); cto+=2; if(cto==510) { CmdBuffer[cto]=0; SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,CmdBuffer); cto=0; } ct++; } if(cto!=0) { CmdBuffer[cto]=0; SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,CmdBuffer); } /* SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,"\n");*/ } void Handle_BSXPacket(int user, char *data) { BSXImage *i; if(strlen(data)<4) return; if(strncmp(data,"#RQS",4)==0||strncmp(data,"#RQO",4)==0) { char *t=data+5; while(*t!='.'&&*t) t++; *t=0; i=BSXFind(data+5); if(i==NULL) { /* Whoops it doesn't exist.. that shouldn't happen. */ return; } if(strncmp(data,"#RQS",4)==0) SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,"@DFS"); else SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,"@DFO"); SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,i->bsx_Identifier); SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,"."); BSXDecompSend(user,i); SendTPacket(UserList[user].us_Port,PACKET_BSXSCENE,"@RFS"); return; } /* Nothing else really matters */ } /* * BSX Database actions */ void Act_BSXScene(void) { ITEM *m=Me(); int u; char *t; if(!IsUser(m)) { ArgText(); return; } u=UserOf(m); t=TextOf(ArgText()); if(!IsBSX(u)) return; if(BSXFind(t)==NULL) SendUser(u,"BSXError - unknown '%s'.\n",t); SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,"@SCE"); SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,t); SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,".@RFS"); } void Act_BSXObject(void) { ITEM *m=Me(); int u; char buf[128]; int p,d; char *t; if(!IsUser(m)) { ArgNum(); ArgNum(); ArgText(); return; } u=UserOf(m); p=ArgNum(); d=ArgNum(); t=TextOf(ArgText()); if(!IsBSX(u)) return; if(BSXFind(t)==NULL) SendUser(u,"BSXError - unknown '%s'.\n",t); if(p==-1) /* RMO */ { sprintf(buf,"@RMO%s.@RFS",t); } else { /* Purge fixes bug in older BSX clients */ sprintf(buf,"@PUR%s.@VIO%s.",t,t); t=buf+strlen(buf); BSXDecodePair((unsigned char)p,t); BSXDecodePair((unsigned char)p,t+2); strcat(buf,"@RFS"); t[4]=0; } SendTPacket(UserList[u].us_Port,PACKET_BSXSCENE,buf); }