Saving shn files now implemented.

master
sigonasr2 1 year ago
parent 89ce51cd6f
commit d5f7cf205d
  1. BIN
      SHNFileDecryptor/AbState.shn
  2. BIN
      SHNFileDecryptor/AbState.shn.bak
  3. BIN
      SHNFileDecryptor/AbState.shn_decoded.bak
  4. 209
      SHNFileDecryptor/SHNFileDecryptor.cpp
  5. BIN
      SHNFileDecryptor/save_AbState.shn

Binary file not shown.

Binary file not shown.

@ -9,6 +9,13 @@ 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++){
@ -20,11 +27,19 @@ class SHNFile{
}
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--){
@ -58,26 +73,44 @@ class SHNFile{
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;
@ -93,13 +126,33 @@ class SHNFile{
}
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,sizeof(float));
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]);
}
@ -115,6 +168,13 @@ class SHNFile{
}
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;
@ -238,6 +298,8 @@ public:
//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);
@ -269,40 +331,40 @@ public:
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;
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);
@ -316,8 +378,82 @@ public:
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("save_"+filename,std::ios::binary);
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.GetByte());
}break;
case 2:{
WriteUInt16(f,col.GetUInt16());
}break;
case 3:
case 11:
case 0x12:
case 0x1b:{
WriteUInt32(f,col.GetUInt32());
}break;
case 5:{
WriteSingle(f,col.GetFloat());
}break;
case 9:
case 0x18:{
WriteString(f,col.GetString(),columns[colNum].length);
}break;
case 13:
case 0x15:{
WriteInt16(f,col.GetInt16());
}break;
case 20:{
WriteSByte(f,col.GetSByte());
}break;
case 0x16:{
WriteInt32(f,col.GetInt32());
}break;
case 0x1a:{
WriteString(f,col.GetString(),-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(){}
};
@ -325,6 +461,5 @@ public:
int main(){
SHNFile shn;
shn.Load("AbState.shn");
shn.Load("AbState.shn");
shn.Save();
}

Binary file not shown.
Loading…
Cancel
Save