Turn file into a single header

master
sigonasr2 1 year ago
parent a8eb9356c4
commit 82682d6b34
  1. BIN
      SHNFileDecryptor/AbState.shn
  2. BIN
      SHNFileDecryptor/AbState.shn.bak
  3. 449
      SHNFileDecryptor/SHNFileDecryptor.cpp
  4. 492
      SHNFileDecryptor/SHNFileDecryptor.h
  5. 2
      SHNFileDecryptor/SHNFileDecryptor.vcxproj
  6. 2
      SHNFileDecryptor/SHNFileDecryptor.vcxproj.filters
  7. 8
      SHNFileDecryptor/SHNFile_example.cpp

Binary file not shown.

Binary file not shown.

@ -1,449 +0,0 @@
#include <vector>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <string>
#include <chrono>
typedef std::byte byte;
typedef char sbyte;
class SHNFile{
std::vector<byte>ReadBytes(std::ifstream&file){
std::vector<byte>byteArr;
while(!file.eof()){
byteArr.push_back(byte(file.get()));
}
return byteArr;
}
std::vector<byte>ReadBytes(std::ifstream&file,int bytes){
std::vector<byte>byteArr;
for(int i=0;i<bytes;i++){
if(!file.eof()){
byteArr.push_back(byte(file.get()));
} else {
break;
}
}
return byteArr;
}
void WriteBytes(std::ofstream&file,std::vector<byte>&data){
for(int i=0;i<data.size();i++){
file<<unsigned char(data[i]);
}
}
int ReadInt32(std::ifstream&file){
std::vector<byte>intBytes=ReadBytes(file,4);
int numb = int(intBytes[3])<<24|int(intBytes[2])<<16|int(intBytes[1])<<8|int(intBytes[0]);
return numb;
}
void Encrypt(){
Decrypt();
}
void Decrypt(){
byte num = byte(data.size());
for(int i=data.size()-1;i>=0;i--){
data[i] = byte(data[i]^num);
byte num3 = byte(i);
num3 = byte(num3&byte(15));
num3 = byte(int(num3)+0x55);
num3 = byte(num3 ^ (byte((int(byte(i))*11))));
num3 = byte(num3^num);
num3 = byte(int(num3)^170);
num = num3;
}
}
std::vector<byte>ReadBytes(int bytes){
std::vector<byte>byteArr={};
for(int i=0;i<bytes;i++){
if(marker<data.size()){
byteArr.push_back(data[marker]);
marker++;
} else {
break;
}
}
return byteArr;
}
byte ReadByte(){
std::vector<byte>b=ReadBytes(1);
if(b.size()>0){
return b[0];
} else {
return byte(0);
}
}
void WriteByte(std::ofstream&f,byte b){
f<<unsigned char(b);
}
void WriteSByte(std::ofstream&f,sbyte b){
f<<char(b);
}
uint16_t ReadUInt16(){
std::vector<byte>intBytes=ReadBytes(2);
uint16_t numb = uint16_t(intBytes[1])<<8|uint16_t(intBytes[0]);
return numb;
}
void WriteUInt16(std::ofstream&f,uint16_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF);
}
int16_t ReadInt16(){
std::vector<byte>intBytes=ReadBytes(2);
int16_t numb = int16_t(intBytes[1])<<8|int16_t(intBytes[0]);
return numb;
}
void WriteInt16(std::ofstream&f,int16_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF);
}
uint32_t ReadUInt32(){
std::vector<byte>intBytes=ReadBytes(4);
uint32_t numb = uint32_t(intBytes[3])<<24|uint32_t(intBytes[2])<<16|uint32_t(intBytes[1])<<8|uint32_t(intBytes[0]);
return numb;
}
void WriteUInt32(std::ofstream&f,uint32_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF)<<unsigned char((val>>16)&0xFF)<<unsigned char((val>>24)&0xFF);
}
int ReadInt32(){
std::vector<byte>intBytes=ReadBytes(4);
int numb = int(intBytes[3])<<24|int(intBytes[2])<<16|int(intBytes[1])<<8|int(intBytes[0]);
return numb;
}
void WriteInt32(std::ofstream&f,int32_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF)<<unsigned char((val>>16)&0xFF)<<unsigned char((val>>24)&0xFF);
}
struct Column{
std::string name;
uint32_t type=0;
int length=0;
};
std::string ReadString(int bytes){
std::vector<byte>strBytes=ReadBytes(bytes);
std::string str="";
for(int i=0;i<strBytes.size();i++){
if(strBytes[i]!=byte(0)){
str+=unsigned char(strBytes[i]);
}
}
return str;
}
void WriteString(std::ofstream&f,std::string str,int bytes){
for(int i=0;i<bytes;i++){
if(i<str.length()){
f<<unsigned char(str[i]);
} else {
f<<unsigned char(0x00);
}
}
if(bytes==-1){
//We use this to append a 0 for unknown length strings (of the shn file)
f<<unsigned char(0x00);
}
}
float ReadSingle(){
std::vector<byte>strBytes=ReadBytes(4);
byte bytes[]={strBytes[0],strBytes[1],strBytes[2],strBytes[3]};
float f;
memcpy(&f,&bytes,4);
return f;
}
void WriteSingle(std::ofstream&f,float n){
byte bytes[4];
memcpy(&n,&bytes,4);
for(int i=0;i<4;i++){
f<<unsigned char(bytes[i]);
}
}
sbyte ReadSByte(){
return sbyte(ReadBytes(1)[0]);
}
std::string ReadString(){
std::string str="";
while(true){
std::vector<byte>byteArr=ReadBytes(1);
if(byteArr.size()>0&&byteArr[0]!=byte(0)){
str+=unsigned char(byteArr[0]);
}else{
break;
}
}
return str;
}
uint32_t GetRecordLength(){
uint32_t start=2;
for(Column&col:columns){
start+=uint32_t(col.length);
}
return start;
}
public:
struct Data{
std::shared_ptr<void>data;
int type=0;
Data(byte b){
std::shared_ptr<byte>ptr=std::make_shared<byte>(byte(b));
data=ptr;
type=1;
}
Data(sbyte b){
std::shared_ptr<sbyte>ptr=std::make_shared<sbyte>(sbyte(b));
data=ptr;
type=7;
}
Data(uint16_t n){
std::shared_ptr<uint16_t>ptr=std::make_shared<uint16_t>(uint16_t(n));
data=ptr;
type=2;
}
Data(int16_t n){
std::shared_ptr<int16_t>ptr=std::make_shared<int16_t>(int16_t(n));
data=ptr;
type=6;
}
Data(uint32_t n){
std::shared_ptr<uint32_t>ptr=std::make_shared<uint32_t>(uint32_t(n));
data=ptr;
type=3;
}
Data(int32_t n){
std::shared_ptr<int32_t>ptr=std::make_shared<int32_t>(int32_t(n));
data=ptr;
type=8;
}
Data(float n){
std::shared_ptr<float>ptr=std::make_shared<float>(float(n));
data=ptr;
type=4;
}
Data(std::string str){
std::shared_ptr<std::string>ptr=std::make_shared<std::string>(str);
data=ptr;
type=5;
}
template <typename T>
T Get(){
return *std::static_pointer_cast<T>(data);
}
template<typename T>
void Set(T b){
data=std::make_shared<T>(T(b));
}
std::string GetDisplayText(){
switch(type){
case 1:{
return std::to_string(int(Get<byte>()));
}break;
case 7:{
return std::to_string(int(Get<sbyte>()));
}break;
case 2:{
return std::to_string(Get<uint16_t>());
}break;
case 6:{
return std::to_string(Get<int16_t>());
}break;
case 3:{
return std::to_string(Get<uint32_t>());
}break;
case 8:{
return std::to_string(Get<int32_t>());
}break;
case 4:{
return std::to_string(Get<float>());
}break;
case 5:{
return Get<std::string>();
}break;
}
}
};
private:
friend std::ostream&operator<<(std::ostream&out,SHNFile::Data&d){
out<<d.GetDisplayText();
return out;
}
int marker=0;
std::vector<byte>cryptHeader;
std::vector<byte>data,rawData;
uint32_t header=0,recordCount=0,defaultRecordLength=0,columnCount=0;
std::vector<Column>columns;
std::vector<std::vector<Data>>contents;
std::string filename;
public:
void Load(std::string file){
cryptHeader.clear();
data.clear();
header=recordCount=defaultRecordLength=columnCount=0;
columns.clear();
contents.clear();
rawData.clear();
marker=0;
std::chrono::time_point<std::chrono::high_resolution_clock>timer=std::chrono::high_resolution_clock::now();
filename=file;
//FILE OPERATIONS!
std::ifstream f(filename,std::ios::binary);
//Since we don't just read in the entire file raw, we have to do some additional work here as the header provides us with some basic info on how to decrypt this file.
//The backup itself needs all the data from the original file, so we're appending it to rawData as we continue reading it.
cryptHeader=ReadBytes(f,0x20);
std::copy(cryptHeader.begin(),cryptHeader.end(),std::back_inserter(rawData));
int readAmt=ReadInt32(f);
rawData.push_back(byte(readAmt&0xFF));
rawData.push_back(byte((readAmt>>8)&0xFF));
rawData.push_back(byte((readAmt>>16)&0xFF));
rawData.push_back(byte((readAmt>>24)&0xFF));
data=ReadBytes(f,readAmt-0x24);
std::copy(data.begin(),data.end(),std::back_inserter(rawData));
Decrypt();
header=ReadUInt32();
recordCount=ReadUInt32();
defaultRecordLength=ReadUInt32();
columnCount=ReadUInt32();
int num2=2;
for(int i=0;i<columnCount;i++){
Column columnData;
columnData.name=ReadString(0x30);
columnData.type=ReadUInt32();
columnData.length=ReadInt32();
num2+=columnData.length;
columns.push_back(columnData);
}
for(int i=0;i<recordCount;i++){
ReadUInt16();
std::vector<Data>row;
for(int j=0;j<columns.size();j++){
switch(columns[j].type){
case 1:
case 12:
case 0x10:{
row.push_back(ReadByte());
}break;
case 2:{
row.push_back(ReadUInt16());
}break;
case 3:
case 11:
case 0x12:
case 0x1b:{
row.push_back(ReadUInt32());
}break;
case 5:{
row.push_back(ReadSingle());
}break;
case 9:
case 0x18:{
row.push_back(ReadString(columns[j].length));
}break;
case 13:
case 0x15:{
row.push_back(ReadInt16());
}break;
case 20:{
row.push_back(ReadSByte());
}break;
case 0x16:{
row.push_back(ReadInt32());
}break;
case 0x1a:{
row.push_back(ReadString());
}break;
}
}
contents.push_back(row);
}
std::chrono::duration<float>dur=std::chrono::high_resolution_clock::now()-timer;
std::cout<<"Loaded "<<contents.size()<<" rows, "<<contents.size()*columnCount<<" columns, "<<dur.count()<<"s"<<std::endl;
}
void Save(){
std::ofstream fBackup(filename+".bak",std::ios::binary);
std::cout<<"Saving a backup to "<<filename+".bak"<<std::endl;
for(int i=0;i<rawData.size();i++){
fBackup<<unsigned char(rawData[i]);
}
/*//Decoded version only required for debugging.
std::ofstream fDecodedBackup(filename+"_decoded.bak",std::ios::binary);
std::cout<<"Saving a backup to "<<filename+"_decoded.bak"<<std::endl;
for(int i=0;i<data.size();i++){
fDecodedBackup<<unsigned char(data[i]);
}*/
std::cout<<"Saving new file..."<<std::endl;
std::ofstream f(filename,std::ios::binary);
WriteUInt32(f,header);
WriteUInt32(f,contents.size());
WriteUInt32(f,GetRecordLength());
WriteUInt32(f,columnCount);
for(int i=0;i<columnCount;i++){
WriteString(f,columns[i].name,0x30);
WriteUInt32(f,columns[i].type);
WriteInt32(f,columns[i].length);
}
for(std::vector<Data>&row:contents){
std::streampos marker = f.tellp();
WriteUInt16(f,uint16_t(0));
int colNum=0;
for(Data&col:row){
switch(columns[colNum].type){
case 1:
case 12:
case 0x10:{
WriteByte(f,col.Get<byte>());
}break;
case 2:{
WriteUInt16(f,col.Get<uint16_t>());
}break;
case 3:
case 11:
case 0x12:
case 0x1b:{
WriteUInt32(f,col.Get<uint32_t>());
}break;
case 5:{
WriteSingle(f,col.Get<float>());
}break;
case 9:
case 0x18:{
WriteString(f,col.Get<std::string>(),columns[colNum].length);
}break;
case 13:
case 0x15:{
WriteInt16(f,col.Get<uint16_t>());
}break;
case 20:{
WriteSByte(f,col.Get<sbyte>());
}break;
case 0x16:{
WriteInt32(f,col.Get<int32_t>());
}break;
case 0x1a:{
WriteString(f,col.Get<std::string>(),-1);
}break;
}
colNum++;
}
std::streampos offset = f.tellp() - marker;
std::streampos newMarker = f.tellp();
f.seekp(marker);
WriteUInt16(f,uint16_t(offset));
f.seekp(newMarker);
}
f.close();
std::ifstream finishedFile(filename,std::ios::binary);
data=ReadBytes(finishedFile);
std::ofstream encryptedFile(filename,std::ios::binary);
std::cout<<"Encrypting..."<<std::endl;
Encrypt();
WriteBytes(encryptedFile,cryptHeader);
WriteInt32(encryptedFile,int32_t(data.size()+0x24));
WriteBytes(encryptedFile,data);
std::cout<<"File "<<filename<<" Saved!"<<std::endl;
}
SHNFile(){}
};
int main(){
SHNFile shn;
shn.Load("AbState.shn");
shn.Save();
}

@ -1 +1,493 @@
#pragma once #pragma once
#include <vector>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <string>
#include <chrono>
typedef std::byte byte;
typedef char sbyte;
class SHNFile{
std::vector<byte>ReadBytes(std::ifstream&file);
std::vector<byte>ReadBytes(std::ifstream&file,int bytes);
void WriteBytes(std::ofstream&file,std::vector<byte>&data);
int ReadInt32(std::ifstream&file);
void Encrypt();
void Decrypt();
std::vector<byte>ReadBytes(int bytes);
byte ReadByte();
void WriteByte(std::ofstream&f,byte b);
void WriteSByte(std::ofstream&f,sbyte b);
uint16_t ReadUInt16();
void WriteUInt16(std::ofstream&f,uint16_t val);
int16_t ReadInt16();
void WriteInt16(std::ofstream&f,int16_t val);
uint32_t ReadUInt32();
void WriteUInt32(std::ofstream&f,uint32_t val);
int Read();
int32_t ReadInt32();
void WriteInt32(std::ofstream&f,int32_t val);
std::string ReadString(int bytes);
void WriteString(std::ofstream&f,std::string str,int bytes);
float ReadSingle();
void WriteSingle(std::ofstream&f,float n);
sbyte ReadSByte();
std::string ReadString();
uint32_t GetRecordLength();
public:
struct Data{
std::shared_ptr<void>data;
int type=0;
Data(byte b);
Data(sbyte b);
Data(uint16_t n);
Data(int16_t n);
Data(uint32_t n);
Data(int32_t n);
Data(float n);
Data(std::string str);
template <typename T>
T Get();
template<typename T>
void Set(T b);
std::string GetDisplayText();
};
private:
friend std::ostream&operator<<(std::ostream&out,SHNFile::Data&d){
out<<d.GetDisplayText();
return out;
}
struct Column{
std::string name;
uint32_t type=0;
int length=0;
};
int marker=0;
std::vector<byte>cryptHeader;
std::vector<byte>data,rawData;
uint32_t header=0,recordCount=0,defaultRecordLength=0,columnCount=0;
std::vector<Column>columns;
std::vector<std::vector<Data>>contents;
std::string filename;
public:
void Load(std::string file);
void Save();
SHNFile();
};
#ifdef OLC_PGEX_SHNFile
std::vector<byte>SHNFile::ReadBytes(std::ifstream&file){
std::vector<byte>byteArr;
while(!file.eof()){
byteArr.push_back(byte(file.get()));
}
return byteArr;
}
std::vector<byte>SHNFile::ReadBytes(std::ifstream&file,int bytes){
std::vector<byte>byteArr;
for(int i=0;i<bytes;i++){
if(!file.eof()){
byteArr.push_back(byte(file.get()));
} else {
break;
}
}
return byteArr;
}
void SHNFile::WriteBytes(std::ofstream&file,std::vector<byte>&data){
for(int i=0;i<data.size();i++){
file<<unsigned char(data[i]);
}
}
int SHNFile::ReadInt32(std::ifstream&file){
std::vector<byte>intBytes=ReadBytes(file,4);
int numb = int(intBytes[3])<<24|int(intBytes[2])<<16|int(intBytes[1])<<8|int(intBytes[0]);
return numb;
}
void SHNFile::Encrypt(){
Decrypt();
}
void SHNFile::Decrypt(){
byte num = byte(data.size());
for(int i=data.size()-1;i>=0;i--){
data[i] = byte(data[i]^num);
byte num3 = byte(i);
num3 = byte(num3&byte(15));
num3 = byte(int(num3)+0x55);
num3 = byte(num3 ^ (byte((int(byte(i))*11))));
num3 = byte(num3^num);
num3 = byte(int(num3)^170);
num = num3;
}
}
std::vector<byte>SHNFile::ReadBytes(int bytes){
std::vector<byte>byteArr={};
for(int i=0;i<bytes;i++){
if(marker<data.size()){
byteArr.push_back(data[marker]);
marker++;
} else {
break;
}
}
return byteArr;
}
byte SHNFile::ReadByte(){
std::vector<byte>b=ReadBytes(1);
if(b.size()>0){
return b[0];
} else {
return byte(0);
}
}
void SHNFile::WriteByte(std::ofstream&f,byte b){
f<<unsigned char(b);
}
void SHNFile::WriteSByte(std::ofstream&f,sbyte b){
f<<char(b);
}
uint16_t SHNFile::ReadUInt16(){
std::vector<byte>intBytes=ReadBytes(2);
uint16_t numb = uint16_t(intBytes[1])<<8|uint16_t(intBytes[0]);
return numb;
}
void SHNFile::WriteUInt16(std::ofstream&f,uint16_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF);
}
int16_t SHNFile::ReadInt16(){
std::vector<byte>intBytes=ReadBytes(2);
int16_t numb = int16_t(intBytes[1])<<8|int16_t(intBytes[0]);
return numb;
}
void SHNFile::WriteInt16(std::ofstream&f,int16_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF);
}
uint32_t SHNFile::ReadUInt32(){
std::vector<byte>intBytes=ReadBytes(4);
uint32_t numb = uint32_t(intBytes[3])<<24|uint32_t(intBytes[2])<<16|uint32_t(intBytes[1])<<8|uint32_t(intBytes[0]);
return numb;
}
void SHNFile::WriteUInt32(std::ofstream&f,uint32_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF)<<unsigned char((val>>16)&0xFF)<<unsigned char((val>>24)&0xFF);
}
int SHNFile::Read(){
std::vector<byte>intBytes=ReadBytes(4);
int numb = int(intBytes[3])<<24|int(intBytes[2])<<16|int(intBytes[1])<<8|int(intBytes[0]);
return numb;
}
int32_t SHNFile::ReadInt32(){
std::vector<byte>intBytes=ReadBytes(4);
int32_t numb = int32_t(intBytes[3])<<24|int32_t(intBytes[2])<<16|int32_t(intBytes[1])<<8|uint32_t(intBytes[0]);
return numb;
}
void SHNFile::WriteInt32(std::ofstream&f,int32_t val){
f<<unsigned char(val&0xFF)<<unsigned char((val>>8)&0xFF)<<unsigned char((val>>16)&0xFF)<<unsigned char((val>>24)&0xFF);
}
std::string SHNFile::ReadString(int bytes){
std::vector<byte>strBytes=ReadBytes(bytes);
std::string str="";
for(int i=0;i<strBytes.size();i++){
if(strBytes[i]!=byte(0)){
str+=unsigned char(strBytes[i]);
}
}
return str;
}
void SHNFile::WriteString(std::ofstream&f,std::string str,int bytes){
for(int i=0;i<bytes;i++){
if(i<str.length()){
f<<unsigned char(str[i]);
} else {
f<<unsigned char(0x00);
}
}
if(bytes==-1){
//We use this to append a 0 for unknown length strings (of the shn file)
f<<unsigned char(0x00);
}
}
float SHNFile::ReadSingle(){
std::vector<byte>strBytes=ReadBytes(4);
byte bytes[]={strBytes[0],strBytes[1],strBytes[2],strBytes[3]};
float f;
memcpy(&f,&bytes,4);
return f;
}
void SHNFile::WriteSingle(std::ofstream&f,float n){
byte bytes[4];
memcpy(&n,&bytes,4);
for(int i=0;i<4;i++){
f<<unsigned char(bytes[i]);
}
}
sbyte SHNFile::ReadSByte(){
return sbyte(ReadBytes(1)[0]);
}
std::string SHNFile::ReadString(){
std::string str="";
while(true){
std::vector<byte>byteArr=ReadBytes(1);
if(byteArr.size()>0&&byteArr[0]!=byte(0)){
str+=unsigned char(byteArr[0]);
}else{
break;
}
}
return str;
}
uint32_t SHNFile::GetRecordLength(){
uint32_t start=2;
for(Column&col:columns){
start+=uint32_t(col.length);
}
return start;
}
SHNFile::Data::Data(byte b){
std::shared_ptr<byte>ptr=std::make_shared<byte>(byte(b));
data=ptr;
type=1;
}
SHNFile::Data::Data(sbyte b){
std::shared_ptr<sbyte>ptr=std::make_shared<sbyte>(sbyte(b));
data=ptr;
type=7;
}
SHNFile::Data::Data(uint16_t n){
std::shared_ptr<uint16_t>ptr=std::make_shared<uint16_t>(uint16_t(n));
data=ptr;
type=2;
}
SHNFile::Data::Data(int16_t n){
std::shared_ptr<int16_t>ptr=std::make_shared<int16_t>(int16_t(n));
data=ptr;
type=6;
}
SHNFile::Data::Data(uint32_t n){
std::shared_ptr<uint32_t>ptr=std::make_shared<uint32_t>(uint32_t(n));
data=ptr;
type=3;
}
SHNFile::Data::Data(int32_t n){
std::shared_ptr<int32_t>ptr=std::make_shared<int32_t>(int32_t(n));
data=ptr;
type=8;
}
SHNFile::Data::Data(float n){
std::shared_ptr<float>ptr=std::make_shared<float>(float(n));
data=ptr;
type=4;
}
SHNFile::Data::Data(std::string str){
std::shared_ptr<std::string>ptr=std::make_shared<std::string>(str);
data=ptr;
type=5;
}
template <typename T>
T SHNFile::Data::Get(){
return *std::static_pointer_cast<T>(data);
}
template<typename T>
void SHNFile::Data::Set(T b){
data=std::make_shared<T>(T(b));
}
std::string SHNFile::Data::GetDisplayText(){
switch(type){
case 1:{
return std::to_string(int(Get<byte>()));
}break;
case 7:{
return std::to_string(int(Get<sbyte>()));
}break;
case 2:{
return std::to_string(Get<uint16_t>());
}break;
case 6:{
return std::to_string(Get<int16_t>());
}break;
case 3:{
return std::to_string(Get<uint32_t>());
}break;
case 8:{
return std::to_string(Get<int32_t>());
}break;
case 4:{
return std::to_string(Get<float>());
}break;
case 5:{
return Get<std::string>();
}break;
}
}
void SHNFile::Load(std::string file){
cryptHeader.clear();
data.clear();
header=recordCount=defaultRecordLength=columnCount=0;
columns.clear();
contents.clear();
rawData.clear();
marker=0;
std::chrono::time_point<std::chrono::high_resolution_clock>timer=std::chrono::high_resolution_clock::now();
filename=file;
//FILE OPERATIONS!
std::ifstream f(filename,std::ios::binary);
//Since we don't just read in the entire file raw, we have to do some additional work here as the header provides us with some basic info on how to decrypt this file.
//The backup itself needs all the data from the original file, so we're appending it to rawData as we continue reading it.
cryptHeader=ReadBytes(f,0x20);
std::copy(cryptHeader.begin(),cryptHeader.end(),std::back_inserter(rawData));
int readAmt=ReadInt32(f);
rawData.push_back(byte(readAmt&0xFF));
rawData.push_back(byte((readAmt>>8)&0xFF));
rawData.push_back(byte((readAmt>>16)&0xFF));
rawData.push_back(byte((readAmt>>24)&0xFF));
data=ReadBytes(f,readAmt-0x24);
std::copy(data.begin(),data.end(),std::back_inserter(rawData));
Decrypt();
header=ReadUInt32();
recordCount=ReadUInt32();
defaultRecordLength=ReadUInt32();
columnCount=ReadUInt32();
int num2=2;
for(int i=0;i<columnCount;i++){
Column columnData;
columnData.name=ReadString(0x30);
columnData.type=ReadUInt32();
columnData.length=ReadInt32();
num2+=columnData.length;
columns.push_back(columnData);
}
for(int i=0;i<recordCount;i++){
ReadUInt16();
std::vector<Data>row;
for(int j=0;j<columns.size();j++){
switch(columns[j].type){
case 1:
case 12:
case 0x10:{
row.push_back(ReadByte());
}break;
case 2:{
row.push_back(ReadUInt16());
}break;
case 3:
case 11:
case 0x12:
case 0x1b:{
row.push_back(ReadUInt32());
}break;
case 5:{
row.push_back(ReadSingle());
}break;
case 9:
case 0x18:{
row.push_back(ReadString(columns[j].length));
}break;
case 13:
case 0x15:{
row.push_back(ReadInt16());
}break;
case 20:{
row.push_back(ReadSByte());
}break;
case 0x16:{
row.push_back(ReadInt32());
}break;
case 0x1a:{
row.push_back(ReadString());
}break;
}
}
contents.push_back(row);
}
std::chrono::duration<float>dur=std::chrono::high_resolution_clock::now()-timer;
std::cout<<"Loaded "<<contents.size()<<" rows, "<<contents.size()*columnCount<<" columns, "<<dur.count()<<"s"<<std::endl;
}
void SHNFile::Save(){
std::ofstream fBackup(filename+".bak",std::ios::binary);
std::cout<<"Saving a backup to "<<filename+".bak"<<std::endl;
for(int i=0;i<rawData.size();i++){
fBackup<<unsigned char(rawData[i]);
}
/*//Decoded version only required for debugging.
std::ofstream fDecodedBackup(filename+"_decoded.bak",std::ios::binary);
std::cout<<"Saving a backup to "<<filename+"_decoded.bak"<<std::endl;
for(int i=0;i<data.size();i++){
fDecodedBackup<<unsigned char(data[i]);
}*/
std::cout<<"Saving new file..."<<std::endl;
std::ofstream f(filename,std::ios::binary);
WriteUInt32(f,header);
WriteUInt32(f,contents.size());
WriteUInt32(f,GetRecordLength());
WriteUInt32(f,columnCount);
for(int i=0;i<columnCount;i++){
WriteString(f,columns[i].name,0x30);
WriteUInt32(f,columns[i].type);
WriteInt32(f,columns[i].length);
}
for(std::vector<Data>&row:contents){
std::streampos marker = f.tellp();
WriteUInt16(f,uint16_t(0));
int colNum=0;
for(Data&col:row){
switch(columns[colNum].type){
case 1:
case 12:
case 0x10:{
WriteByte(f,col.Get<byte>());
}break;
case 2:{
WriteUInt16(f,col.Get<uint16_t>());
}break;
case 3:
case 11:
case 0x12:
case 0x1b:{
WriteUInt32(f,col.Get<uint32_t>());
}break;
case 5:{
WriteSingle(f,col.Get<float>());
}break;
case 9:
case 0x18:{
WriteString(f,col.Get<std::string>(),columns[colNum].length);
}break;
case 13:
case 0x15:{
WriteInt16(f,col.Get<uint16_t>());
}break;
case 20:{
WriteSByte(f,col.Get<sbyte>());
}break;
case 0x16:{
WriteInt32(f,col.Get<int32_t>());
}break;
case 0x1a:{
WriteString(f,col.Get<std::string>(),-1);
}break;
}
colNum++;
}
std::streampos offset = f.tellp() - marker;
std::streampos newMarker = f.tellp();
f.seekp(marker);
WriteUInt16(f,uint16_t(offset));
f.seekp(newMarker);
}
f.close();
std::ifstream finishedFile(filename,std::ios::binary);
data=ReadBytes(finishedFile);
std::ofstream encryptedFile(filename,std::ios::binary);
std::cout<<"Encrypting..."<<std::endl;
Encrypt();
WriteBytes(encryptedFile,cryptHeader);
WriteInt32(encryptedFile,int32_t(data.size()+0x24));
WriteBytes(encryptedFile,data);
std::cout<<"File "<<filename<<" Saved!"<<std::endl;
}
SHNFile::SHNFile(){}
#endif

@ -131,7 +131,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="SHNFileDecryptor.cpp" /> <ClCompile Include="SHNFile_example.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="SHNFileDecryptor.h" /> <ClInclude Include="SHNFileDecryptor.h" />

@ -15,7 +15,7 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="SHNFileDecryptor.cpp"> <ClCompile Include="SHNFile_example.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>

@ -0,0 +1,8 @@
#define OLC_PGEX_SHNFile
#include "SHNFileDecryptor.h"
int main(){
SHNFile shn;
shn.Load("AbState.shn");
shn.Save();
}
Loading…
Cancel
Save