Index: mbtofhm.c ================================================================== --- mbtofhm.c +++ mbtofhm.c @@ -57,10 +57,11 @@ // Common static char*basename; static char*nam; static unsigned long haroffs; +static unsigned long puzzlesetnumber; static void*alloc(unsigned int s) { void*o=malloc(s); if(s && !o) fatal("Allocation failed\n"); return o; @@ -92,10 +93,11 @@ static inline void read_header(void) { unsigned char buf[30]; int i,s; fread(buf,1,30,stdin); if(memcmp("MESH",buf+2,4)) fatal("Unrecognized file format\n"); + puzzlesetnumber=buf[6]|(buf[7]<<8)|(buf[8]<<16)|(buf[9]<<24); for(i=0;inmsgs++; - Allocate(Reallocate(class[id]->msgscode,class[id]->nmsgs)[i],k<<1); + Reallocate(class[id]->msgscode,class[id]->nmsgs); + Allocate(class[id]->msgscode[i],k<<1); memcpy(class[id]->msgscode[i],buf,4); fread(class[id]->msgscode[i]+4,k-2,2,stdin); } } @@ -404,15 +407,373 @@ if(*txt=='"') fputc('\\',fp); fputc(*txt++,fp); } } } + +#define SubOpcode(...) do{ static const char*const ss[]={__VA_ARGS__}; if(*op>=sizeof(ss)/sizeof(*ss)) goto unknown; fprintf(fp," %s",ss[*op]); }while(0) +#define PushFlowControl() do{ flowblock[flowptr]=ofs+2+(op[1]<<1)+(op[2]<<9); if(++flowptr==64) fatal("Too many nested flow controls\n"); len+=2; ind+=2; }while(0) + +static int class_codes(FILE*fp,const unsigned char*op,int ofs,const unsigned char*lbl,int nlbl,const unsigned char*subs,int nsubs,unsigned char*vars) { + static const char*const stdvars[256]={ + [0]="Class","Temperature","Shape", + [4]="Xloc","Yloc","Dir","Image","Inertia","Misc1","Misc2","Misc3","Misc4","Misc5","Misc6","Misc7", + [16]="Arrived","Departed","Arrivals","Departures", + [32]="Busy","Invisible","UserSignal","UserState","KeyCleared","IsPlayer","Destroyed","Stealthy","VisualOnly", + [48]="Msg","From","Arg1","Arg2", + [64]="Density","Volume","Strength","Weight","Distance","Height","Climb", + [72]="Hard","Hard","Hard","Hard","Sharp","Sharp","Sharp","Sharp","ShapeDir","ShapeDir","ShapeDir","ShapeDir", + [84]="Shovable", + }; + static const char*const direction[16]={"E","NE","N","NW","W","SW","S","SE","F","LF","L","LB","B","RB","R","RF"}; + int flowblock[64]; + int flowptr=0; + //int end=ofs+(op[-2]<<1)+(op[-1]<<9); + int ind=3; + int st=0; + int lix=0; + int remlbl=nlbl; + int x,y,z,len; + for(;;) { + while(flowptr && flowblock[flowptr-1]==ofs) { + --flowptr; + fprintf(fp,"\n%*s then",ind-=2,""); + } + if(*op==102 && op[1]!=1) return ofs+2; + if(!st) st=fprintf(fp,"\n%*s",ind,""); + //if(ofs>=end) { + // fprintf(fp," (?\?\?)"); + // return ofs; + //} + while(remlbl && (lbl[lix+8]|(lbl[lix+9]<<8))==ofs>>1) { + fprintf(fp," :%s",lbl+lix); + remlbl--; + lix+=10; + } + len=1; + switch(*op++) { + case 1 ... 4: + if(!stdvars[*op]) goto unknown; + if(*op>=72 && *op<=83) fprintf(fp," %c","ENWSENWSENWS"[*op&3],stdvars[*op]); + fputc(' ',fp); + if(op[-1]>2) fputc('=',fp); + if(!(op[-1]&1)) fputc(',',fp); + fprintf(fp,"%s",stdvars[*op]); + if(op[-1]>2) st=0; + break; + case 5: + fprintf(fp," %%%s",vars+*op*8); + break; + case 6: + fprintf(fp," =%%%s",vars+*op*8); + st=0; break; + case 7: + fprintf(fp," %d",*op); + break; + case 8: + fprintf(fp," %u",op[1]|(op[2]<<8)|(op[3]<<16)|(op[4]<<24)); + len+=4; break; + case 9: + if(!class[*op]) goto unknown; + fprintf(fp," $%s",class[*op]->name); + break; + case 11: + if(*op<20) { + fprintf(fp," %s",standard_message_names[*op]); + } else { + if(*op-20>=nusermsg || !usermsg[*op-20]) goto unknown; + fprintf(fp," #%s",usermsg[*op-20]); + } + break; + case 13: + fprintf(fp," \""); + len+=x=op[1]|(op[2]<<8); + for(y=0;yname,op[y+6]|(op[y+7]<<8)); y+=4; break; + case 14: fprintf(fp,"\\i%d:%d\\",op[y+4]|(op[y+5]<<8),op[y+6]|(op[y+7]<<8)); y+=4; break; + case 15: fprintf(fp,"\\b"); break; + case 16: fprintf(fp,"\\q"); break; + case 9: case 13: case 17 ... 31: case 127 ... 255: fprintf(fp,"\\x%02X",z); break; + case '\\': fputc(z,fp); //fallthrough + default: fputc(z,fp); + } + fputc('"',fp); + len+=2; break; + case 14: + if(*op<16) fprintf(fp," %s",direction[*op]); + else fprintf(fp," %d",*op); + break; + case 15: + for(x=0;xname); + break; + case 67: + fprintf(fp," Broadcast"); + break; + case 68: + if(*op==255) fprintf(fp," Move"); + else fprintf(fp," (Move %s)",direction[*op]); + break; + case 69: + if(*op==255) fprintf(fp," ,Move"); + else fprintf(fp," %s ,Move",direction[*op]); + break; + case 70: + fprintf(fp," JumpTo"); + break; + case 71: + fprintf(fp," ,JumpTo"); + break; + case 72: + fprintf(fp," Create"); + break; + case 74: + fprintf(fp," Destroy"); + break; + case 75: + fprintf(fp," ,Destroy"); + break; + case 80: + fprintf(fp," Send ."); + st=0; break; + case 81: + fprintf(fp," ,Send ."); + st=0; break; + case 82: + fprintf(fp," (Broadcast $%s) .",class[*op]->name); + st=0; break; + case 83: + fprintf(fp," Broadcast ."); + st=0; break; + case 84: + if(*op==255) fprintf(fp," Move ."); + else fprintf(fp," (Move %s) .",direction[*op]); + st=0; break; + case 85: + if(*op==255) fprintf(fp," ,Move ."); + else fprintf(fp," %s ,Move .",direction[*op]); + st=0; break; + case 88: + fprintf(fp," Create ."); + st=0; break; + case 96: + fprintf(fp," ;"); + len+=x=op[1]|(op[2]<<8); + for(y=0;yattr[38]|(c->attr[39]<<8)); } } - //TODO: Class codes if(c->subscode[1] || c->subscode[0]>2) { - fprintf(fp," (SUBS\n ; Not implemented yet!\n )\n"); + fprintf(fp," (SUBS"); + class_codes(fp,c->subscode+2,2,c->subslbl,c->nsubslbl,c->subslbl,c->nsubslbl,c->vars); + fprintf(fp,"\n )\n"); } + o=0; for(i=0;inmsgs;i++) { fprintf(fp," ("); j=c->msgscode[i][0]|(c->msgscode[i][1]<<8); if(j<20) fprintf(fp,"%s",standard_message_names[j]); else if(j-20msgscode[i]+4,o+4,c->msgslbl,c->nmsgslbl,c->subslbl,c->nsubslbl,c->vars); + fprintf(fp,"\n )\n"); } fprintf(fp,")\n"); } fclose(fp); }