// PORT: isolated item-table extension. All non-biology records stay byte-identical. #include "GameLib/StdAfx.h" #include "GameLib/ItemData.h" #include "EterBase/lzo.h" #include #include #include #include #include #include #include #include using Item=CItemData::TItemTable; static constexpr std::array item_key{{173217,72619434,408587239,27973291}}; static std::vector read_file(const char* path){ std::ifstream stream(path,std::ios::binary); if(!stream)throw std::runtime_error("cannot read proto"); return {std::istreambuf_iterator(stream),std::istreambuf_iterator()}; } static DWORD word(const std::vector& data,size_t offset){ if(offset+4>data.size())throw std::runtime_error("truncated proto"); DWORD value;std::memcpy(&value,data.data()+offset,4);return value; } static void put_word(std::vector& data,size_t offset,DWORD value){std::memcpy(data.data()+offset,&value,4);} static void write_file(const char* path,const std::vector& data){ std::ofstream stream(path,std::ios::binary|std::ios::trunc); if(!stream.write(reinterpret_cast(data.data()),data.size()))throw std::runtime_error("cannot write proto"); } int main(int argc,char** argv) { if(argc!=4)return 2; try { static CLZO lzo; auto key=item_key; auto input=read_file(argv[1]); if(input.size()<20 || std::memcmp(input.data(),"MIPX",4) || word(input,4)!=1 || word(input,8)!=sizeof(Item))throw std::runtime_error("item proto stride"); CLZObject decoded; if(!CLZO::Instance().Decompress(decoded,input.data()+20,key.data()))throw std::runtime_error("item proto decode"); if(decoded.GetSize()!=size_t(word(input,12))*sizeof(Item))throw std::runtime_error("proto count/size mismatch"); std::map rows; for(DWORD i=0;i>v>>type>>sub>>size>>anti>>flags>>buy>>sell))throw std::runtime_error("biology item row"); std::array values{};for(auto& value:values)if(!(stream>>value))throw std::runtime_error("biology item values"); std::string name;std::getline(stream,name);if(!name.empty()&&name[0]=='\t')name.erase(0,1); if(name.size()>24)throw std::runtime_error("biology item name too long"); Item r{};r.dwVnum=v;r.bType=type;r.bSubType=sub;r.bSize=size;r.dwAntiFlags=anti;r.dwFlags=flags; r.dwIBuyItemPrice=buy;r.dwISellItemPrice=sell; for(int i=0;i<6;++i)r.alValues[i]=values[i]; std::memcpy(r.szName,name.data(),name.size());std::memcpy(r.szLocaleName,name.data(),name.size()); rows[v]=r;++changed; } std::vector plain;for(const auto& pair:rows){const BYTE* bytes=reinterpret_cast(&pair.second);plain.insert(plain.end(),bytes,bytes+sizeof(Item));} CLZObject encoded;if(!CLZO::Instance().CompressEncryptedMemory(encoded,plain.data(),plain.size(),key.data()))throw std::runtime_error("encode"); std::vector result(input.begin(),input.begin()+20);put_word(result,12,rows.size());put_word(result,16,encoded.GetSize()); result.insert(result.end(),encoded.GetBuffer(),encoded.GetBuffer()+encoded.GetSize()); CLZObject verified;if(!CLZO::Instance().Decompress(verified,result.data()+20,key.data()) || verified.GetSize()!=plain.size() || std::memcmp(verified.GetBuffer(),plain.data(),plain.size()))throw std::runtime_error("round-trip"); write_file(argv[3],result);std::printf("biology items=%zu total=%zu; verified round-trip\n",changed,rows.size());return 0; }catch(const std::exception& e){std::fprintf(stderr,"%s\n",e.what());return 1;} }