This commit is contained in:
2025-10-06 04:18:49 +08:00
commit df2cacdb92
2784 changed files with 1280840 additions and 0 deletions

View File

@@ -0,0 +1,397 @@
#include "Asset/AnimationStruct.h"
#include "Asset/ScriptData.h"
namespace AniScriptParser
{
std::string Get_Ani_Flag(int data)
{
switch (data)
{
case 0:
return "LOOP";
case 1:
return "SHADOW";
case 3:
return "COORD";
case 7:
return "IMAGE_RATE";
case 8:
return "IMAGE_ROTATE";
case 9:
return "RGBA";
case 10:
return "INTERPOLATION";
case 11:
return "GRAPHIC_EFFECT";
case 12:
return "DELAY";
case 13:
return "DAMAGE_TYPE";
case 14:
return "DAMAGE_BOX";
case 15:
return "ATTACK_BOX";
case 16:
return "PLAY_SOUND";
case 17:
return "PRELOAD";
case 18:
return "SPECTRUM";
case 23:
return "SET_FLAG";
case 24:
return "FLIP_TYPE";
case 25:
return "LOOP_START";
case 26:
return "LOOP_END";
case 27:
return "CLIP";
case 28:
return "OPERATION";
default:
return "";
}
}
std::string Get_Ani_Effect_Type(int data)
{
switch (data)
{
case 0:
return "NONE";
case 1:
return "DODGE";
case 2:
return "LINEARDODGE";
case 3:
return "DARK";
case 4:
return "XOR";
case 5:
return "MONOCHROME";
case 6:
return "SPACEDISTORT";
default:
return "";
}
};
std::string Get_Ani_Flip_Type(int data)
{
switch (data)
{
case 1:
return "HORIZON";
case 2:
return "VERTICAL";
case 3:
return "ALL";
default:
return "";
}
};
std::string Get_Ani_Damage_Type(int data)
{
switch (data)
{
case 0:
return "NORMAL";
case 1:
return "SUPERARMOR";
case 2:
return "UNBREAKABLE";
default:
return "";
}
};
AlsInfo StructAlsInfo(ScriptData &Data)
{
AlsInfo Info;
while (!Data.IsEnd())
{
std::string Segment = Data.Get();
if (Segment == "[use animation]")
{
std::string AniPath = Data.Get();
std::string AniKey = Data.Get();
Info.AniList[AniKey].path = Tool_toLowerCase(AniPath);
}
else if (Segment == "[none effect add]")
{
std::vector<int> AniLayer = {std::stoi(Data.Get()), std::stoi(Data.Get())};
std::string AniKey = Data.Get();
Info.AniList[AniKey].layer = AniLayer;
}
else if (Segment == "[add]")
{
std::vector<int> AniLayer = {std::stoi(Data.Get()), std::stoi(Data.Get())};
std::string AniKey = Data.Get();
Info.AniList[AniKey].layer = AniLayer;
}
}
return Info;
};
AniInfo StructAniInfo(ScriptData &Data)
{
AniInfo Info;
while (!Data.IsEnd())
{
std::string Segment = Data.Get();
if (Segment == "[image]")
{
}
}
return Info;
};
/////////以下是读取逻辑
AniInfo StructAniInfo(Blob blob)
{
AniInfo Info;
int Frame_Max = blob.getUShort();
int Img_Count = blob.getUShort();
// Img的路径读取 存入数组
for (int i = 0; i < Img_Count; i++)
{
int Buf = blob.getInt();
std::string ImgPath = "sprite/" + blob.getString(Buf);
Info.Img_List.push_back(ImgPath);
}
// Ani头部标签数量
int Ani_H_Item_Count = blob.getUShort();
// 处理标签
for (int i = 0; i < Ani_H_Item_Count; i++)
{
int Type = blob.getUShort();
switch (Type)
{
case 0:
case 1:
{
std::string Key = AniScriptParser::Get_Ani_Flag(Type);
int Value = blob.getByte();
Info.Flag.emplace(Key, Value);
break;
}
case 3:
case 28:
{
std::string Key = AniScriptParser::Get_Ani_Flag(Type);
int Value = blob.getUShort();
Info.Flag.emplace(Key, Value);
break;
}
case 18:
{
blob.getByte();
blob.getInt();
blob.getInt();
blob.getInt();
blob.get256();
blob.get256();
blob.get256();
blob.get256();
blob.getUShort();
}
default:
break;
}
}
// 读取每一个Img
for (int i = 0; i < Frame_Max; i++)
{
AniFrame FrameObject;
// 碰撞框项目数量
int Ani_Box_Item_Count = blob.getUShort();
for (int j = 0; j < Ani_Box_Item_Count; j++)
{
int Box_Type = blob.getUShort();
std::vector<int> D_Box_b;
for (int k = 0; k < 6; k++)
{
D_Box_b.push_back(blob.getInt());
}
if (Box_Type == 15)
FrameObject.AttackBox.push_back(D_Box_b);
else
FrameObject.DamageBox.push_back(D_Box_b);
}
// 调用的第几个Img
int Index_Buf = blob.getShort();
if (Index_Buf != -1)
{
FrameObject.Img_Path = Tool_toLowerCase(Info.Img_List[Index_Buf]);
FrameObject.Img_Index = blob.getUShort();
}
else
{
FrameObject.Img_Path = "";
FrameObject.Img_Index = 0;
}
// 坐标
FrameObject.Img_Pos = VecPos{blob.getInt(), blob.getInt()};
// Img中的项目数量
int Img_Flag_Count = blob.getUShort();
for (int j = 0; j < Img_Flag_Count; j++)
{
int Img_Flag_Type = blob.getUShort();
std::string Key;
int Value;
switch (Img_Flag_Type)
{
case 0:
case 1:
case 10:
{
Key = AniScriptParser::Get_Ani_Flag(Img_Flag_Type);
Value = blob.getByte();
FrameObject.Flag.emplace(Key, Value);
break;
}
case 3:
{
Key = "COORD";
Value = blob.getUShort();
FrameObject.Flag.emplace(Key, Value);
break;
}
case 17:
{
Key = "PRELOAD";
Value = 1;
FrameObject.Flag.emplace(Key, Value);
break;
}
case 7:
{
Key = "IMAGE_RATE";
VecFPos pos{
blob.getFloat(),
blob.getFloat()};
FrameObject.Flag.emplace(Key, pos);
break;
}
case 8:
{
Key = "IMAGE_ROTATE";
float RateBuffer = blob.getFloat();
FrameObject.Flag.emplace(Key, RateBuffer);
break;
}
case 9:
{
Key = "RGBA";
std::vector<int> RGBA = {
(int)blob.get256(),
(int)blob.get256(),
(int)blob.get256(),
(int)blob.get256()};
FrameObject.Flag.emplace(Key, RGBA);
break;
}
case 11:
{
int Effect_Type = blob.getUShort();
Key = "GRAPHIC_EFFECT_" + AniScriptParser::Get_Ani_Effect_Type(Effect_Type);
std::vector<float> effect;
switch (Effect_Type)
{
case 5:
{
effect.push_back(blob.get256());
effect.push_back(blob.get256());
effect.push_back(blob.get256());
break;
}
case 6:
{
effect.push_back(blob.get256());
effect.push_back(blob.get256());
break;
}
}
FrameObject.Flag.emplace(Key, effect);
break;
}
case 12:
{
Value = blob.getInt();
FrameObject.Delay = Value;
break;
}
case 13:
{
Key = "DAMAGE_TYPE";
std::string DTYPE = AniScriptParser::Get_Ani_Damage_Type(blob.getUShort());
FrameObject.Flag.emplace(Key, DTYPE);
break;
}
case 16:
{
int SoundTempSize = blob.getInt();
Key = "PLAY_SOUND";
std::string sound = blob.getString(SoundTempSize);
FrameObject.Flag.emplace(Key, sound);
break;
}
case 23:
{
Key = "SET_FLAG";
Value = blob.getInt();
FrameObject.Flag.emplace(Key, Value);
break;
}
case 24:
{
Key = "FLIP_TYPE";
std::string FTYPEValue = AniScriptParser::Get_Ani_Flip_Type(blob.getUShort());
FrameObject.Flag.emplace(Key, FTYPEValue);
break;
}
case 25:
{
Key = "LOOP_START";
FrameObject.Flag.emplace(Key, 1);
break;
}
case 26:
{
Key = "LOOP_END";
Value = blob.getInt();
FrameObject.Flag.emplace(Key, Value);
break;
}
case 27:
{
Key = "CLIP";
std::vector<int> ClipArr{
blob.getShort(),
blob.getShort(),
blob.getShort(),
blob.getShort(),
};
FrameObject.Flag.emplace(Key, ClipArr);
break;
}
default:
break;
}
}
Info.Frame.push_back(FrameObject);
}
return Info;
}
};

View File

@@ -0,0 +1,58 @@
#pragma once
#include <vector>
#include <string>
#include <variant>
#include <unordered_map>
#include <SDL.h>
#include "Tool/Blob.hpp"
#include "Tool/Tool_String.h"
#include "Tool/Common.h"
class ScriptData;
namespace AniScriptParser
{
using AniFlag = std::variant<
int,
float,
VecPos,
VecFPos,
std::string,
std::vector<int>,
std::vector<float>>;
struct AniFrame
{
std::string Img_Path; // img路径
int Img_Index; // img索引
VecPos Img_Pos; // img位置
std::vector<std::vector<int>> AttackBox; // 攻击框
std::vector<std::vector<int>> DamageBox; // 受击框
std::unordered_map<std::string, AniFlag> Flag; // Frame特效数据
int Delay; // 延迟
};
struct AniInfo
{
std::vector<std::string> Img_List; // img列表
std::vector<AniFrame> Frame; // ani列表
std::unordered_map<std::string, AniFlag> Flag; // ani特效数据
};
struct AlsAniInfo
{
std::string path;
std::vector<int> layer;
};
struct AlsInfo
{
std::unordered_map<std::string, AlsAniInfo> AniList; // Ani列表
};
// 工具函数
std::string Get_Ani_Flag(int data);
std::string Get_Ani_Effect_Type(int data);
std::string Get_Ani_Flip_Type(int data);
std::string Get_Ani_Damage_Type(int data);
// Ani脚本的读取逻辑
AniInfo StructAniInfo(Blob blob);
AlsInfo StructAlsInfo(ScriptData &blob);
};

View File

@@ -0,0 +1,48 @@
#include "AssetManager.h"
#include "Asset/Asset_Script.h"
AssetManager::AssetManager()
{
}
AssetManager::~AssetManager()
{
}
AniScriptParser::AniInfo AssetManager::StructAniInfo(std::string path)
{
std::vector<BYTE> Data = Asset_Script::GetInstance().GetFileContentByte(path);
if (Data.size() > 0)
{
Blob blob(Data);
return AniScriptParser::StructAniInfo(blob);
}
SDL_LogError(0, "Ani加载失败 Error : %s", path.c_str());
return AniScriptParser::AniInfo();
}
AniScriptParser::AlsInfo AssetManager::StructAlsInfo(std::string path)
{
std::vector<BYTE> Data = Asset_Script::GetInstance().GetFileContentByte(path);
if (Data.size() > 0)
{
ScriptData Pvf;
Pvf.Init(Data, path);
AniScriptParser::AlsInfo Info = AniScriptParser::StructAlsInfo(Pvf);
return Info;
}
SDL_LogError(0, "Als加载失败 Error : %s", path.c_str());
return AniScriptParser::AlsInfo();
}
ScriptData AssetManager::GetScriptInfo(std::string path)
{
std::vector<BYTE> Data = Asset_Script::GetInstance().GetFileContentByte(path);
if (Data.size() > 0)
{
ScriptData Pvf;
Pvf.Init(Data, path);
return Pvf;
}
SDL_LogError(0, "Script加载失败 Error : %s", path.c_str());
return ScriptData();
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include "Asset/AnimationStruct.h" //Ani结构
#include "Asset/ScriptData.h"
class AssetManager
{
public:
AssetManager(const AssetManager &) = delete;
AssetManager &operator=(const AssetManager &) = delete;
AssetManager(AssetManager &&) = delete;
AssetManager &operator=(AssetManager &&) = delete;
// 全局访问点
static AssetManager &GetInstance()
{
static AssetManager instance; // 局部静态变量,保证只初始化一次
return instance;
}
private:
AssetManager(/* args */);
~AssetManager();
public:
// 构造Ani结构体
AniScriptParser::AniInfo StructAniInfo(std::string path);
AniScriptParser::AlsInfo StructAlsInfo(std::string path);
// Script读取体
ScriptData GetScriptInfo(std::string path);
};

View File

@@ -0,0 +1,246 @@
#include "Asset_ImagePack.h"
Asset_ImagePack::Asset_ImagePack()
{
}
Asset_ImagePack::~Asset_ImagePack()
{
}
void Asset_ImagePack::Init()
{
DIR *dir;
struct dirent *ent;
std::string path = "ImagePacks2/";
dir = opendir(path.c_str());
while ((ent = readdir(dir)))
{
// 跳过.和..目录
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
std::string RealPath = path + ent->d_name;
Ifstream_NPK Fs;
Fs.open(RealPath.c_str(), std::ios::in | std::ios::binary);
if (Fs.is_open())
{
std::string Header = Fs.ReadString();
// 如果是NPK
if (Header.find("NeoplePack_Bill") != std::string::npos)
{
// 读取img数量
int ImageCount = Fs.ReadInt();
// 读取头
NpkInfo *ImgList = new NpkInfo[ImageCount];
for (int i = 0; i < ImageCount; i++)
{
ImgList[i].Offset = Fs.ReadInt();
ImgList[i].Length = Fs.ReadInt();
ImgList[i].Path = Fs.ReadInfo();
}
for (int i = 0; i < ImageCount; i++)
{
IMG img;
img.imgOffset = ImgList[i].Offset;
img.imgSize = ImgList[i].Length;
img.img_index = i;
img.lpBelongsFile = ent->d_name;
img.lpImgName = ImgList[i].Path;
img.lp_lplist = NULL;
img.png_sum = 0;
map_npk.insert(make_pair(img.lpImgName, img));
}
// 销毁
delete[] ImgList;
}
}
Fs.close();
}
closedir(dir);
}
void Asset_ImagePack::ParseColor(BYTE *Tab, int Type, BYTE *SaveByte, int Offset)
{
BYTE a = 0;
BYTE r = 0;
BYTE g = 0;
BYTE b = 0;
switch (Type)
{
case 0x0e:
a = (BYTE)(Tab[1] >> 7);
r = (BYTE)((Tab[1] >> 2) & 0x1f);
g = (BYTE)((Tab[0] >> 5) | ((Tab[1] & 3) << 3));
b = (BYTE)(Tab[0] & 0x1f);
a = (BYTE)(a * 0xff);
r = (BYTE)((r << 3) | (r >> 2));
g = (BYTE)((g << 3) | (g >> 2));
b = (BYTE)((b << 3) | (b >> 2));
break;
case 0x0f:
a = (BYTE)(Tab[1] & 0xf0);
r = (BYTE)((Tab[1] & 0xf) << 4);
g = (BYTE)(Tab[0] & 0xf0);
b = (BYTE)((Tab[0] & 0xf) << 4);
break;
}
SaveByte[Offset + 0] = b;
SaveByte[Offset + 1] = g;
SaveByte[Offset + 2] = r;
SaveByte[Offset + 3] = a;
}
void Asset_ImagePack::LoadImgToMem(IMG *p)
{
std::string Path = "ImagePacks2/" + p->lpBelongsFile;
// SDL_Log("LoadImgToMem : %s", Path.c_str());
Ifstream_NPK Fs;
Fs.open(Path.c_str(), std::ios::in | std::ios::binary);
if (Fs.is_open())
{
Fs.seekg(p->imgOffset);
std::string Flag = Fs.ReadString(); // 读取Flag
if (Flag.find("Neople Img File") != std::string::npos)
{
// 索引表大小
long TableLength = Fs.ReadLong();
// img 版本 4字节
Fs.ReadInt(); // 读取版本
// img 帧数
int IndexCount = Fs.ReadInt();
// 图片数量赋值
p->png_sum = IndexCount;
// new出 Png数量的 结构体
ImgInfo *PngList = new ImgInfo[IndexCount];
for (int i = 0; i < IndexCount; i++)
{
PngList[i].Type = Fs.ReadInt();
if (PngList[i].Type == 17)
{
// 引用贴图
int frbuf = Fs.ReadInt();
// 压缩类型 用来临时存一下引用编号
PngList[i].CmpType = frbuf;
////大小
PngList[i].Size = 0;
PngList[i].Offset = PngList[i - 1].Offset + PngList[i - 1].Size;
continue;
}
// 压缩类型
PngList[i].CmpType = Fs.ReadInt();
// 宽度
PngList[i].Width = Fs.ReadInt();
// 高度
PngList[i].Height = Fs.ReadInt();
// 大小
PngList[i].Size = Fs.ReadInt();
// Xpos
PngList[i].Xpos = Fs.ReadInt();
// Ypos
PngList[i].Ypos = Fs.ReadInt();
// 帧域X
PngList[i].FrameXpos = Fs.ReadInt();
// 帧域Y
PngList[i].FrameYpos = Fs.ReadInt();
// 计算偏移
if (i == 0)
PngList[i].Offset = 0 + p->imgOffset + TableLength + 32;
else
PngList[i].Offset = PngList[i - 1].Offset + PngList[i - 1].Size;
}
for (int i = 0; i < IndexCount; i++)
{
// 引用
if (PngList[i].Type == 17)
{
// 引用编号
int YYIndex = PngList[i].CmpType;
int sizebuf = PngList[YYIndex].Width * PngList[YYIndex].Height * 4;
BYTE *bByte = new BYTE[sizebuf];
memcpy(bByte, PngList[PngList[i].CmpType].PNGdata, sizebuf);
PngList[i].PNGdata = PngList[YYIndex].PNGdata;
// 压缩类型 用来临时存一下引用编号
PngList[i].CmpType = PngList[YYIndex].CmpType;
// 宽度
PngList[i].Width = PngList[YYIndex].Width;
// 高度
PngList[i].Height = PngList[YYIndex].Height;
// 大小
PngList[i].Size = 0;
// Xpos
PngList[i].Xpos = PngList[YYIndex].Xpos;
// Ypos
PngList[i].Ypos = PngList[YYIndex].Ypos;
// 帧域X
PngList[i].FrameXpos = PngList[YYIndex].FrameXpos;
// 帧域Y
PngList[i].FrameYpos = PngList[YYIndex].FrameYpos;
continue;
}
Fs.seekg(PngList[i].Offset);
BYTE *PngData = Fs.ReadCustomSize(PngList[i].Size);
int DeSize = PngList[i].Width * PngList[i].Height * 4;
BYTE *bByte = new BYTE[DeSize];
unsigned long RealSize = DeSize;
uncompress(bByte, &RealSize, PngData, (unsigned long)PngList[i].Size);
delete[] PngData;
if (PngList[i].Type != 16)
{
int PngByteSize = DeSize * 2;
PngList[i].PNGdata = new BYTE[PngByteSize];
for (int e = 0; e < PngByteSize; e += 4)
{
BYTE NeedData[2];
memset(NeedData, 0, 2);
memcpy(NeedData, bByte + (e / 4) * 2, 2);
ParseColor(NeedData, PngList[i].Type, PngList[i].PNGdata, e);
}
delete[] bByte;
}
else
{
PngList[i].PNGdata = bByte;
}
}
p->lp_lplist = PngList;
}
else if (Flag.find("Neople Image File") != std::string::npos)
{
// LoadImgToMem2(p);
}
Fs.close();
}
}
Asset_ImagePack::IMG *Asset_ImagePack::GetIMG(std::string imgName)
{
IMG *img = NULL;
std::map<std::string, IMG>::iterator itr;
itr = map_npk.find(imgName);
if (itr == map_npk.end())
{
std::string mes = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!调用了不存在的Img : " + imgName;
SDL_Log(mes.c_str());
img = &map_npk["sprite/interface/base.img"];
}
else
{
img = &itr->second;
}
// 如果图片数组不存在 或者 图片数据不存在都要重读
if (!img->lp_lplist)
{
LoadImgToMem(img);
}
img->UseTime = SDL_GetTicks();
return img;
}

View File

@@ -0,0 +1,86 @@
#pragma once
#ifdef _SWITCH_
#include <switch.h>
#endif
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <SDL.h>
#include <map>
#include "Tool/Ifstream_NPK.h"
#include <zlib.h>
class Asset_ImagePack
{
public:
struct NpkInfo
{
int Offset;
int Length;
std::string Path;
};
// PNG结构体
struct ImgInfo
{
// 图片格式
int Type;
// 压缩类型
int CmpType;
// 宽度
int Width;
// 高度
int Height;
// 大小
int Size;
// Xpos
int Xpos;
// Ypos
int Ypos;
// 帧域X
int FrameXpos;
// 帧域Y
int FrameYpos;
// 偏移
int Offset;
// Png位图数据
BYTE *PNGdata;
};
struct IMG // npk的img的结构体
{
std::string lpImgName; // img文件的路径
int img_index; // img文件在npk文件里的序号
unsigned imgOffset;
unsigned imgSize;
std::string lpBelongsFile; // 这个img属于哪个npk文件
int png_sum; // 这个img文件有多少个 图片
ImgInfo *lp_lplist; // 图片的数组..
Uint32 UseTime = 0;
};
public:
Asset_ImagePack(const Asset_ImagePack &) = delete;
Asset_ImagePack &operator=(const Asset_ImagePack &) = delete;
Asset_ImagePack(Asset_ImagePack &&) = delete;
Asset_ImagePack &operator=(Asset_ImagePack &&) = delete;
// 全局访问点
static Asset_ImagePack &GetInstance()
{
static Asset_ImagePack instance; // 局部静态变量,保证只初始化一次
return instance;
}
public:
void Init();
void ParseColor(BYTE *Tab, int Type, BYTE *SaveByte, int Offset);
void LoadImgToMem(IMG *p);
IMG *GetIMG(std::string imgName);
private:
Asset_ImagePack(/* args */);
~Asset_ImagePack();
std::map<std::string, IMG> map_npk;
};

View File

@@ -0,0 +1,227 @@
#include "Asset/Asset_Script.h"
#include "Asset_Script.h"
void Asset_Script::Init()
{
// 读取头建立树
InitHeader();
// 读取bin文件
InitBin();
// 读取LoadString
InitLoadString();
}
void Asset_Script::Clear()
{
FileInfo.clear();
BinStringM.clear();
LoadStringM.clear();
_Data.clear();
_Data.shrink_to_fit();
}
void Asset_Script::InitHeader()
{
// 读取UUID的长度
int UUID_LENGTH = GetInt();
// UUID 读 1 - 36位 构造 UTF8 string
std::string UUID = GetString(UUID_LENGTH);
// 版本号
int Version = GetInt();
(void)Version;
// 文件路径数据的大小
int AlignedIndexHeaderSize = GetInt();
// 解密密钥
int IndexHeaderCrc = GetInt();
// 文件数量
int IndexSize = GetInt();
// 文件起始位置
int FristPos = tellg();
CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc);
int CurrPos = 0;
StartPos = AlignedIndexHeaderSize + 56;
// 建立pvf文件索引表
for (int i = 0; i < IndexSize; i++)
{
seek(FristPos + CurrPos);
int FileNumber = GetInt();
(void)FileNumber;
int FilePathLength = GetInt();
std::string FileName = tolower(GetString(FilePathLength));
int FileLength = GetInt();
int Cre32 = GetInt();
int RelativeOffset = GetInt();
if (FileLength > 0)
{
int RealFileLength = (FileLength + 3) & 4294967292;
PvfFileInfo Info;
Info.ROffset = RelativeOffset;
Info.Cr32 = Cre32;
Info.Length = RealFileLength;
Info.DecodeFlag = false;
FileInfo[FileName] = Info;
}
CurrPos += 20;
CurrPos += FilePathLength;
}
}
void Asset_Script::InitBin()
{
if (FileInfo.count("stringtable.bin") == 0)
{
SDL_LogError(0, "stringtable.bin文件不存在");
return;
}
PvfFileInfo BinInfo = FileInfo["stringtable.bin"];
seek(StartPos + BinInfo.ROffset);
CrcDecode(BinInfo.Length, BinInfo.Cr32);
seek(StartPos + BinInfo.ROffset);
int FileHPos = tellg();
int Count = GetInt();
int CurrentIndex = 0;
for (int i = 0; i < Count; i++)
{
seek(FileHPos + CurrentIndex * 4 + 4);
int StartPos = GetInt();
int EndPos = GetInt();
int Len = EndPos - StartPos;
seek(FileHPos + StartPos + 4);
std::string Str = GetString(Len);
BinStringM[CurrentIndex] = Str;
CurrentIndex++;
}
}
void Asset_Script::InitLoadString()
{
if (FileInfo.count("n_string.lst") == 0)
{
SDL_LogError(0, "n_string.lst文件不存在");
}
PvfFileInfo Info = FileInfo["n_string.lst"];
seek(StartPos + Info.ROffset);
CrcDecode(Info.Length, Info.Cr32);
seek(StartPos + Info.ROffset);
int FileHPos = tellg();
int Flag = GetShort();
(void)Flag;
int i = 2;
while (i < Info.Length)
{
if ((Info.Length - i) >= 10)
{
seek(FileHPos + i + 6);
int FindKey = GetInt();
std::string Key = GetBinString(FindKey);
std::string Type = tolower(Key.substr(0, Key.find("/")));
if (Key.length() > 0)
{
PvfFileInfo *FileInfo = GetFileInfo(Key);
if (FileInfo == nullptr)
continue;
seek(StartPos + FileInfo->ROffset);
CrcDecode(FileInfo->Length, FileInfo->Cr32);
seek(StartPos + FileInfo->ROffset);
std::string Str = GetStringNormal(FileInfo->Length);
std::vector<std::string> StrArr = split(Str, "\n");
for (auto it = StrArr.begin(); it != StrArr.end(); ++it)
{
std::string strobj = *it;
if (strobj.find(">") != std::string::npos)
{
std::vector<std::string> strobjarr = split(strobj, ">");
if (strobjarr.size() > 1)
{
LoadStringM[Type][strobjarr[0]] = strobjarr[1];
}
}
}
}
}
else
break;
i += 10;
}
}
std::string Asset_Script::GetBinString(int Key)
{
if (BinStringM.count(Key))
return BinStringM[Key];
return "";
}
std::string Asset_Script::GetLoadString(std::string Type, std::string Key)
{
if (LoadStringM.count(Type) && LoadStringM[Type].count(Key))
return LoadStringM[Type][Key];
return "";
}
Asset_Script::PvfFileInfo *Asset_Script::GetFileInfo(std::string path)
{
path = tolower(path);
if (FileInfo.count(path))
return &FileInfo[path];
return nullptr;
}
std::string Asset_Script::GetFileContent(std::string path)
{
if (FileInfo.count(path))
{
seek(StartPos + FileInfo[path].ROffset);
if (FileInfo[path].DecodeFlag == false)
{
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
seek(StartPos + FileInfo[path].ROffset);
FileInfo[path].DecodeFlag = true;
}
char *blobp = new char[FileInfo[path].Length];
read((char *)blobp, FileInfo[path].Length);
std::string Str(blobp, FileInfo[path].Length);
delete[] blobp;
return Str;
}
return std::string();
}
char *Asset_Script::GetFileContentChar(std::string path)
{
if (FileInfo.count(path))
{
seek(StartPos + FileInfo[path].ROffset);
if (FileInfo[path].DecodeFlag == false)
{
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
seek(StartPos + FileInfo[path].ROffset);
FileInfo[path].DecodeFlag = true;
}
char *blobp = new char[FileInfo[path].Length];
read((char *)blobp, FileInfo[path].Length);
return blobp;
}
return nullptr;
}
std::vector<BYTE> Asset_Script::GetFileContentByte(std::string path)
{
if (FileInfo.count(path))
{
seek(StartPos + FileInfo[path].ROffset);
if (FileInfo[path].DecodeFlag == false)
{
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
seek(StartPos + FileInfo[path].ROffset);
FileInfo[path].DecodeFlag = true;
}
std::vector<BYTE> blobp(FileInfo[path].Length);
read((char *)blobp.data(), FileInfo[path].Length);
return blobp;
}
return std::vector<BYTE>();
}

View File

@@ -0,0 +1,60 @@
#pragma once
#ifdef _SWITCH_
#include <switch.h>
#endif
#include <stdio.h>
#include <string>
#include <dirent.h>
#include <SDL.h>
#include <map>
#include "Tool/Ifstream_PVF.h"
class Asset_Script : public Ifstream_PVF
{
public:
struct PvfFileInfo
{
int ROffset;
int Cr32;
int Length;
bool DecodeFlag = false;
};
private:
Asset_Script(const std::string filename = "Script.pvf") : Ifstream_PVF(filename) {};
~Asset_Script() = default;
int StartPos = 0;
std::map<std::string, PvfFileInfo> FileInfo;
std::map<int, std::string> BinStringM;
std::map<std::string, std::map<std::string, std::string>> LoadStringM;
public:
Asset_Script(const Asset_Script &) = delete;
Asset_Script &operator=(const Asset_Script &) = delete;
Asset_Script(Asset_Script &&) = delete;
Asset_Script &operator=(Asset_Script &&) = delete;
// 全局访问点
static Asset_Script &GetInstance()
{
static Asset_Script instance; // 局部静态变量,保证只初始化一次
return instance;
}
public:
void Init();
void InitHeader();
void InitBin();
void InitLoadString();
void Clear();
public:
std::string GetBinString(int Key);
std::string GetLoadString(std::string Type, std::string Key);
PvfFileInfo *GetFileInfo(std::string path);
std::string GetFileContent(std::string path); // 获取文件内容
char* GetFileContentChar(std::string path); // 获取文件内容
std::vector<BYTE> GetFileContentByte(std::string path); // 获取文件内容
};

105
source/Asset/ScriptData.cpp Normal file
View File

@@ -0,0 +1,105 @@
#include "ScriptData.h"
#include "Tool/Tool_String.h"
#include "Asset/Asset_Script.h"
ScriptData::ScriptData()
{
}
ScriptData::~ScriptData()
{
}
void ScriptData::Init(std::vector<BYTE> Data, std::string FilePath)
{
std::string ASA = "";
for (size_t i = 0; i < Data.size(); i++)
{
ASA += std::to_string((int)Data[i]);
ASA += ",";
}
if (Data.size() < 7)
return;
IO = std::make_shared<Blob>(Data);
filepath = FilePath;
filetype = Tool_toLowerCase(FilePath.substr(0, FilePath.find_first_of("/")));
filesize = Data.size();
}
std::string ScriptData::Get()
{
if (!IO)
return "";
if (_CurI < filesize && filesize - _CurI >= 5)
{
std::string Ret = UnpackData();
_CurI += 5;
return Ret;
}
return "_nop_";
}
void ScriptData::Back()
{
if (_CurI >= 5)
_CurI -= 5;
}
bool ScriptData::IsEnd()
{
return (_CurI >= filesize || filesize - _CurI < 5);
}
std::string ScriptData::UnpackData()
{
IO->setOffset(_CurI);
int currentByte = (int)(IO->getByte());
int after = IO->getInt();
switch (currentByte)
{
case 9:
{
BYTE NewcurrentByte = IO->getByte(); // 内容指示位
(void)NewcurrentByte;
int Newafter = IO->getInt();
std::string Buf = Asset_Script::GetInstance().GetBinString(Newafter);
if (Buf.empty())
Buf = "";
else
Buf = Asset_Script::GetInstance().GetLoadString(filetype, Buf);
return Buf;
}
case 10:
{
std::string Buf = Asset_Script::GetInstance().GetBinString(after);
if (Buf.empty())
Buf = "";
else
Buf = Asset_Script::GetInstance().GetLoadString(filetype, Buf);
return Buf;
}
case 2:
{
IO->setOffset(IO->getOffset() - 4);
int ret = IO->getInt();
return std::to_string(ret);
}
case 4:
{
float Bbuf;
std::memcpy(&Bbuf, &after, sizeof(float));
return std::to_string(Bbuf);
}
case 6:
case 8:
case 7:
case 5:
{
return Asset_Script::GetInstance().GetBinString(after);
}
default:
return "";
}
}

25
source/Asset/ScriptData.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include "Tool/Blob.hpp"
#include <memory>
class ScriptData
{
using BYTE = unsigned char;
private:
std::shared_ptr<Blob> IO;
public:
ScriptData();
~ScriptData();
std::string filepath;
std::string filetype;
int filesize;
int _CurI = 2;
void Init(std::vector<BYTE> Data, std::string FilePath);
std::string Get();
void Back();
bool IsEnd();
std::string UnpackData();
};