#include #include #include #include struct idxentry { DWORD offset; DWORD size; BYTE unk; char filename[15]; }; struct idxFile { DWORD filecount; idxentry entries[0]; }; // Get filename with replaced extension // e.g. samifilename = ChangeFileExt(filename, '.smi'); char* ChangeFileExt(const char* filename, const char* new_ext) { char* p = strrchr(filename,'.'); size_t n=strlen(filename); if (p) n=p-filename; char *result = (char*)malloc(n+strlen(new_ext)); strncpy(result, filename ,n); strcpy(result+n, new_ext); return result; } void ListLb5(const char* lb5Filename) { char* idxFilename = ChangeFileExt(lb5Filename,".idx"); FILE* hIdxFile=fopen(idxFilename,"rb"); if (hIdxFile) { fseek(hIdxFile,0,SEEK_END); size_t fsize=ftell(hIdxFile); fseek(hIdxFile,0,SEEK_SET); idxFile* idx = (idxFile*)malloc(fsize); fread(idx,fsize,1,hIdxFile); printf("file count: %d\n",idx->filecount); for (int i=0; ifilecount; i++) printf("0x%08.8x %02.2x %-8d %s\n",idx->entries[i].offset,idx->entries[i].unk,idx->entries[i].size,idx->entries[i].filename); free(idx); fclose(hIdxFile); } else { printf("Couldn't open file '%s'\n",idxFilename); } free(idxFilename); } void decrypt(char* buf, size_t size) { char c; while(size--) { c=*buf; if ((unsigned char)c>0xf) c=0xe-c; *buf=c; buf++; } } void ExtractLb5(const char* filename, const char* toExtract) { char* idxFilename = ChangeFileExt(filename,".idx"); char* lb5Filename = ChangeFileExt(filename,".lb5"); FILE* hIdxFile=fopen(idxFilename,"rb"); FILE* hLb5File=fopen(lb5Filename,"rb"); char buffer[1024]; if (!hLb5File) { printf("Couldn't open file '%s'\n",lb5Filename); } else if (hIdxFile) { fseek(hIdxFile,0,SEEK_END); size_t fsize=ftell(hIdxFile); fseek(hIdxFile,0,SEEK_SET); idxFile* idx = (idxFile*)malloc(fsize); fread(idx,fsize,1,hIdxFile); printf("file count: %d\n",idx->filecount); for (int i=0; ifilecount; i++) { if (toExtract && strcmp(toExtract, idx->entries[i].filename)) continue; printf("Extracting %s\n",idx->entries[i].filename); fseek(hLb5File,idx->entries[i].offset,SEEK_SET); FILE* curFile=fopen(idx->entries[i].filename,"wb"); if (!curFile) { printf("Couldn't create file!\n"); break; } size_t k=idx->entries[i].size,n=sizeof(buffer); while (k>0) { if (n>k) n=k; if (1!=fread(buffer,n,1,hLb5File)) { printf("Read file error!\n"); i=idx->filecount; break; }; if (strstr(idx->entries[i].filename,".txt") || strstr(idx->entries[i].filename,".TXT")) decrypt(buffer,n); if (1!=fwrite(buffer,n,1,curFile)) { printf("Write file error!\n"); i=idx->filecount; break; }; k-=n; } fclose(curFile); if (toExtract) break; } if (toExtract && i>=idx->filecount) printf("Couldn't find file '%s' in archive\n",toExtract); free(idx); } else { printf("Couldn't open file '%s'\n",idxFilename); } if(hIdxFile) fclose(hIdxFile); if(hLb5File)fclose(hLb5File); free(idxFilename); free(lb5Filename); } idxFile* genIdxFile(const char* filemask) { long hFile; struct _finddata_t c_file; int total = 0; if( (hFile = _findfirst( filemask, &c_file )) != -1L ) { do { total++; } while( _findnext( hFile, &c_file ) == 0 ); } _findclose( hFile ); if (total==0) return NULL; size_t fsize = total*sizeof(idxentry)+sizeof(idxFile); int i=0; idxFile* idx = (idxFile*)malloc(fsize); idx->filecount = total; if( (hFile = _findfirst( filemask, &c_file )) != -1L ) { do { strncpy(idx->entries[i].filename, c_file.name, 15); idx->entries[i].filename[14]=0; idx->entries[i].size = c_file.size; idx->entries[i].unk = 0; i++; } while( _findnext( hFile, &c_file ) == 0 ); } _findclose( hFile ); return idx; } void CreateLb5(const char* filename, const char* filemask) { char* idxFilename = ChangeFileExt(filename,".idx"); char* lb5Filename = ChangeFileExt(filename,".lb5"); char buffer[1024]; idxFile* idx = genIdxFile(filemask); if (idx==NULL) printf("No files matching '%s' found.\n",filemask); FILE* hLb5File=fopen(lb5Filename,"wb"); if (!hLb5File) { printf("Couldn't create file '%s'\n",lb5Filename); } else { printf("file count: %d\n",idx->filecount); size_t offset = 0; for (int i=0; ifilecount; i++) { printf("Adding %s\n",idx->entries[i].filename); FILE* curFile=fopen(idx->entries[i].filename,"rb"); if (!curFile) { printf("Couldn't open source file!\n"); break; } idx->entries[i].offset = offset; size_t k=idx->entries[i].size,n=sizeof(buffer); offset += k; while (k>0) { if (n>k) n=k; if (1!=fread(buffer,n,1,curFile)) { printf("Read file error!\n"); i=idx->filecount; break; }; if (strstr(idx->entries[i].filename,".txt") || strstr(idx->entries[i].filename,".TXT")) decrypt(buffer,n); if (1!=fwrite(buffer,n,1,hLb5File)) { printf("Write file error!\n"); i=idx->filecount; break; }; k-=n; } fclose(curFile); } FILE* hIdxFile=fopen(idxFilename,"wb"); if (!hIdxFile) printf("Couldn't create file '%s'\n",idxFilename); else { size_t fsize=idx->filecount*sizeof(idxentry)+sizeof(idxFile); if (1!=fwrite(idx,fsize,1,hIdxFile)) printf("Error writing to file '%s'\n",idxFilename); fclose(hIdxFile); } } free(idx); if (hLb5File) fclose(hLb5File); free(idxFilename); free(lb5Filename); } #define STR_TEST(test, result, expected) if (strcmp(result,expected)) \ printf("%s FAILED! (result: '%s', expected: '%s')\n", #test, result,expected);\ else printf("%s PASSED (result: '%s', expected: '%s')\n", #test,result,expected); void Test() { printf("Testing...\n"); char* tmp; tmp = ChangeFileExt("test.bmp",".ddwerwd"); STR_TEST(ChangeFileExt("test.bmp",".ddwerwd"), tmp, "test.ddwerwd"); free(tmp); tmp = ChangeFileExt("test2",".ddaa"); STR_TEST(ChangeFileExt("test2",".ddaa"), tmp, "test2.ddaa"); free(tmp); tmp = ChangeFileExt("test2.",".d"); STR_TEST(ChangeFileExt("test2.",".d"), tmp, "test2.d"); free(tmp); }; int main(int argc, const char* argv[]) { //Test(); if (argc<3) { printf("Usage: lb5 {l|x|c} file.lb5 [file (x)|filemask (c)]\n"); return 1; } if (!strcmp(argv[1],"x")) { if (argc>2) ExtractLb5(argv[2],argv[3]); else ExtractLb5(argv[2],NULL); } else if (!strcmp(argv[1],"l")) { ListLb5(argv[2]); } else if (!strcmp(argv[1],"c")) { CreateLb5(argv[2], argv[3]); } return 0; }