pkgextract tool : added already working code from gui version
This commit is contained in:
parent
dc8fc09ad8
commit
bfb60e4c84
|
@ -0,0 +1,90 @@
|
||||||
|
#include "FsFile.h"
|
||||||
|
|
||||||
|
FsFile::FsFile()
|
||||||
|
{
|
||||||
|
m_file = nullptr;
|
||||||
|
}
|
||||||
|
FsFile::FsFile(const std::string& path, fsOpenMode mode)
|
||||||
|
{
|
||||||
|
Open(path, mode);
|
||||||
|
}
|
||||||
|
bool FsFile::Open(const std::string& path, fsOpenMode mode)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
fopen_s(&m_file, path.c_str(), getOpenMode(mode));
|
||||||
|
return IsOpen();
|
||||||
|
}
|
||||||
|
bool FsFile::Close()
|
||||||
|
{
|
||||||
|
if (!IsOpen() || std::fclose(m_file) != 0) {
|
||||||
|
m_file = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_file = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
FsFile::~FsFile()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FsFile::Write(const void* src, U64 size)
|
||||||
|
{
|
||||||
|
if (!IsOpen() || std::fwrite(src, 1, size, m_file) != size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FsFile::Read(void* dst, U64 size)
|
||||||
|
{
|
||||||
|
if (!IsOpen() || std::fread(dst, 1, size, m_file) != size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 FsFile::ReadBytes(void* dst, U64 size)
|
||||||
|
{
|
||||||
|
return std::fread(dst, 1, size, m_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FsFile::Seek(S64 offset, fsSeekMode mode)
|
||||||
|
{
|
||||||
|
if (!IsOpen() || _fseeki64(m_file, offset, getSeekMode(mode)) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
U64 FsFile::Tell() const
|
||||||
|
{
|
||||||
|
if (IsOpen()) {
|
||||||
|
return _ftelli64(m_file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
U64 FsFile::getFileSize()
|
||||||
|
{
|
||||||
|
U64 pos = _ftelli64(m_file);
|
||||||
|
if (_fseeki64(m_file, 0, SEEK_END) != 0) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U64 size = _ftelli64(m_file);
|
||||||
|
if (_fseeki64(m_file, pos, SEEK_SET) != 0) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FsFile::IsOpen() const
|
||||||
|
{
|
||||||
|
return m_file != nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
enum fsOpenMode
|
||||||
|
{
|
||||||
|
fsRead = 0x1,
|
||||||
|
fsWrite = 0x2,
|
||||||
|
fsReadWrite = fsRead | fsWrite
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fsSeekMode
|
||||||
|
{
|
||||||
|
fsSeekSet,
|
||||||
|
fsSeekCur,
|
||||||
|
fsSeekEnd,
|
||||||
|
};
|
||||||
|
|
||||||
|
class FsFile
|
||||||
|
{
|
||||||
|
std::FILE* m_file;
|
||||||
|
public:
|
||||||
|
FsFile();
|
||||||
|
FsFile(const std::string& path, fsOpenMode mode = fsRead);
|
||||||
|
bool Open(const std::string& path, fsOpenMode mode = fsRead);
|
||||||
|
bool IsOpen() const;
|
||||||
|
bool Close();
|
||||||
|
bool Read(void* dst, U64 size);
|
||||||
|
U32 ReadBytes(void* dst, U64 size);
|
||||||
|
bool Write(const void* src, U64 size);
|
||||||
|
bool Seek(S64 offset, fsSeekMode mode);
|
||||||
|
U64 getFileSize();
|
||||||
|
U64 Tell() const;
|
||||||
|
~FsFile();
|
||||||
|
|
||||||
|
template< typename T > bool ReadBE(T& dst)
|
||||||
|
{
|
||||||
|
if (!Read(&dst, sizeof(T))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
::ReadBE(dst);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* getOpenMode(fsOpenMode mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case fsRead: return "rb";
|
||||||
|
case fsWrite: return "wb";
|
||||||
|
case fsReadWrite: return "r+b";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "r";
|
||||||
|
}
|
||||||
|
|
||||||
|
const int getSeekMode(fsSeekMode mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case fsSeekSet: return SEEK_SET;
|
||||||
|
case fsSeekCur: return SEEK_CUR;
|
||||||
|
case fsSeekEnd: return SEEK_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SEEK_SET;
|
||||||
|
}
|
||||||
|
std::FILE* fileDescr()
|
||||||
|
{
|
||||||
|
return m_file;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include "PKG.h"
|
||||||
|
#include "FsFile.h"
|
||||||
|
#include <direct.h>
|
||||||
|
|
||||||
|
PKG::PKG()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PKG::~PKG()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PKG::open(const std::string& filepath) {
|
||||||
|
FsFile file;
|
||||||
|
if (!file.Open(filepath, fsRead))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pkgSize = file.getFileSize();
|
||||||
|
PKGHeader pkgheader;
|
||||||
|
file.ReadBE(pkgheader);
|
||||||
|
//we have already checked magic should be ok
|
||||||
|
|
||||||
|
//find title id it is part of pkg_content_id starting at offset 0x40
|
||||||
|
file.Seek(0x47, fsSeekSet);//skip first 7 characters of content_id
|
||||||
|
file.Read(&pkgTitleID, sizeof(pkgTitleID));
|
||||||
|
|
||||||
|
file.Close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool PKG::extract(const std::string& filepath, const std::string& extractPath, std::string& failreason)
|
||||||
|
{
|
||||||
|
this->extractPath = extractPath;
|
||||||
|
FsFile file;
|
||||||
|
if (!file.Open(filepath, fsRead))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pkgSize = file.getFileSize();
|
||||||
|
PKGHeader pkgheader;
|
||||||
|
file.ReadBE(pkgheader);
|
||||||
|
|
||||||
|
if (pkgheader.pkg_size > pkgSize)
|
||||||
|
{
|
||||||
|
failreason = "PKG file size is different";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((pkgheader.pkg_content_size + pkgheader.pkg_content_offset) > pkgheader.pkg_size)
|
||||||
|
{
|
||||||
|
failreason = "Content size is bigger than pkg size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
file.Seek(0, fsSeekSet);
|
||||||
|
pkg = (U08*)mmap(pkgSize, file.fileDescr());
|
||||||
|
if (pkg == nullptr)
|
||||||
|
{
|
||||||
|
failreason = "Can't allocate size for image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Read(pkg, pkgSize);
|
||||||
|
|
||||||
|
U32 offset = pkgheader.pkg_table_entry_offset;
|
||||||
|
U32 n_files = pkgheader.pkg_table_entry_count;
|
||||||
|
|
||||||
|
|
||||||
|
for (U32 i = 0; i < n_files; i++) {
|
||||||
|
PKGEntry entry = (PKGEntry&)pkg[offset + i * 0x20];
|
||||||
|
ReadBE(entry);
|
||||||
|
//try to figure out the name
|
||||||
|
std::string name = getEntryNameByType(entry.id);
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
std::size_t pos = name.find("/");//check if we have a directory (assuming we only have 1 level of subdirectories)
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
//directory found
|
||||||
|
std::string dir = name.substr(0, pos+1);//include '/' as well
|
||||||
|
std::string path = extractPath + dir;
|
||||||
|
_mkdir(path.c_str());//make dir
|
||||||
|
std::string file = name.substr(pos + 1);//read filename
|
||||||
|
FsFile out;
|
||||||
|
out.Open(path + file, fsWrite);
|
||||||
|
out.Write(pkg + entry.offset, entry.size);
|
||||||
|
out.Close();
|
||||||
|
|
||||||
|
}
|
||||||
|
//found an name use it
|
||||||
|
FsFile out;
|
||||||
|
out.Open(extractPath + name, fsWrite);
|
||||||
|
out.Write(pkg + entry.offset, entry.size);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//just print with id
|
||||||
|
FsFile out;
|
||||||
|
out.Open(extractPath + std::to_string(entry.id), fsWrite);
|
||||||
|
out.Write(pkg + entry.offset, entry.size);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//extract pfs_image.dat
|
||||||
|
FsFile out;
|
||||||
|
out.Open(extractPath + "pfs_image.dat", fsWrite);
|
||||||
|
out.Write(pkg + pkgheader.pfs_image_offset, pkgheader.pfs_image_size);
|
||||||
|
out.Close();
|
||||||
|
munmap(pkg);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include "Types.h"
|
||||||
|
#include <io.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct PKGHeader {
|
||||||
|
/*BE*/U32 magic;// Magic
|
||||||
|
/*BE*/U32 pkg_type;
|
||||||
|
/*BE*/U32 pkg_0x8; //unknown field
|
||||||
|
/*BE*/U32 pkg_file_count;
|
||||||
|
/*BE*/U32 pkg_table_entry_count;
|
||||||
|
/*BE*/U16 pkg_sc_entry_count;
|
||||||
|
/*BE*/U16 pkg_table_entry_count_2;// same as pkg_entry_count
|
||||||
|
/*BE*/U32 pkg_table_entry_offset;//file table offset
|
||||||
|
/*BE*/U32 pkg_sc_entry_data_size;
|
||||||
|
/*BE*/U64 pkg_body_offset;//offset of PKG entries
|
||||||
|
/*BE*/U64 pkg_body_size;//length of all PKG entries
|
||||||
|
/*BE*/U64 pkg_content_offset;
|
||||||
|
/*BE*/U64 pkg_content_size;
|
||||||
|
U08 pkg_content_id[0x24];//packages' content ID as a 36-byte string
|
||||||
|
U08 pkg_padding[0xC];//padding
|
||||||
|
/*BE*/U32 pkg_drm_type;//DRM type
|
||||||
|
/*BE*/U32 pkg_content_type;//Content type
|
||||||
|
/*BE*/U32 pkg_content_flags;//Content flags
|
||||||
|
/*BE*/U32 pkg_promote_size;
|
||||||
|
/*BE*/U32 pkg_version_date;
|
||||||
|
/*BE*/U32 pkg_version_hash;
|
||||||
|
/*BE*/U32 pkg_0x088;
|
||||||
|
/*BE*/U32 pkg_0x08C;
|
||||||
|
/*BE*/U32 pkg_0x090;
|
||||||
|
/*BE*/U32 pkg_0x094;
|
||||||
|
/*BE*/U32 pkg_iro_tag;
|
||||||
|
/*BE*/U32 pkg_drm_type_version;
|
||||||
|
|
||||||
|
U08 pkg_zeroes_1[0x60];
|
||||||
|
|
||||||
|
/* Digest table */
|
||||||
|
U08 digest_entries1[0x20]; // sha256 digest for main entry 1
|
||||||
|
U08 digest_entries2[0x20]; // sha256 digest for main entry 2
|
||||||
|
U08 digest_table_digest[0x20]; // sha256 digest for digest table
|
||||||
|
U08 digest_body_digest[0x20]; // sha256 digest for main table
|
||||||
|
|
||||||
|
U08 pkg_zeroes_2[0x280];
|
||||||
|
|
||||||
|
U32 pkg_0x400;
|
||||||
|
|
||||||
|
U32 pfs_image_count; // count of PFS images
|
||||||
|
U64 pfs_image_flags; // PFS flags
|
||||||
|
U64 pfs_image_offset; // offset to start of external PFS image
|
||||||
|
U64 pfs_image_size; // size of external PFS image
|
||||||
|
U64 mount_image_offset;
|
||||||
|
U64 mount_image_size;
|
||||||
|
U64 pkg_size;
|
||||||
|
U32 pfs_signed_size;
|
||||||
|
U32 pfs_cache_size;
|
||||||
|
U08 pfs_image_digest[0x20];
|
||||||
|
U08 pfs_signed_digest[0x20];
|
||||||
|
U64 pfs_split_size_nth_0;
|
||||||
|
U64 pfs_split_size_nth_1;
|
||||||
|
|
||||||
|
U08 pkg_zeroes_3[0xB50];
|
||||||
|
|
||||||
|
U08 pkg_digest[0x20];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void ReadBE(PKGHeader& s)
|
||||||
|
{
|
||||||
|
ReadBE(s.magic);
|
||||||
|
ReadBE(s.pkg_table_entry_offset);
|
||||||
|
ReadBE(s.pkg_table_entry_count);
|
||||||
|
ReadBE(s.pkg_content_offset);
|
||||||
|
ReadBE(s.pkg_content_size);
|
||||||
|
ReadBE(s.pfs_image_offset);
|
||||||
|
ReadBE(s.pfs_image_size);
|
||||||
|
ReadBE(s.pkg_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PKGEntry {
|
||||||
|
U32 id; // File ID, useful for files without a filename entry
|
||||||
|
U32 filename_offset; // Offset into the filenames table (ID 0x200) where this file's name is located
|
||||||
|
U32 flags1; // Flags including encrypted flag, etc
|
||||||
|
U32 flags2; // Flags including encryption key index, etc
|
||||||
|
U32 offset; // Offset into PKG to find the file
|
||||||
|
U32 size; // Size of the file
|
||||||
|
U64 padding; // blank padding
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void ReadBE(PKGEntry& s)
|
||||||
|
{
|
||||||
|
ReadBE(s.id);
|
||||||
|
ReadBE(s.filename_offset);
|
||||||
|
ReadBE(s.flags1);
|
||||||
|
ReadBE(s.flags2);
|
||||||
|
ReadBE(s.offset);
|
||||||
|
ReadBE(s.size);
|
||||||
|
ReadBE(s.padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PKG
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
U08* pkg;
|
||||||
|
U64 pkgSize = 0;
|
||||||
|
S08 pkgTitleID[9];
|
||||||
|
std::string extractPath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PKG();
|
||||||
|
~PKG();
|
||||||
|
bool open(const std::string& filepath);
|
||||||
|
U64 getPkgSize()
|
||||||
|
{
|
||||||
|
return pkgSize;
|
||||||
|
}
|
||||||
|
std::string getTitleID()
|
||||||
|
{
|
||||||
|
return std::string(pkgTitleID,9);
|
||||||
|
}
|
||||||
|
bool extract(const std::string& filepath, const std::string& extractPath, std::string& failreason);
|
||||||
|
|
||||||
|
void* mmap(size_t sLength, std::FILE* nFd) {
|
||||||
|
HANDLE hHandle;
|
||||||
|
void* pStart=nullptr;
|
||||||
|
hHandle = CreateFileMapping(
|
||||||
|
(HANDLE)_get_osfhandle(_fileno((nFd))),
|
||||||
|
NULL, // default security
|
||||||
|
PAGE_WRITECOPY, // read/write access
|
||||||
|
0, // maximum object size (high-order DWORD)
|
||||||
|
0, // maximum object size (low-order DWORD)
|
||||||
|
NULL); // name of mapping object
|
||||||
|
|
||||||
|
if (hHandle != NULL) {
|
||||||
|
pStart = MapViewOfFile(hHandle, FILE_MAP_COPY, 0, 0, sLength);
|
||||||
|
}
|
||||||
|
if(pStart == NULL)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return pStart;
|
||||||
|
}
|
||||||
|
int munmap(void* pStart) {
|
||||||
|
if (UnmapViewOfFile(pStart) != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
typedef struct {
|
||||||
|
U32 type;
|
||||||
|
std::string name;
|
||||||
|
} pkg_entry_value;
|
||||||
|
|
||||||
|
std::string getEntryNameByType(U32 type)
|
||||||
|
{
|
||||||
|
pkg_entry_value entries[] = {
|
||||||
|
{ 0x0001, "digests" },
|
||||||
|
{ 0x0010, "entry_keys" },
|
||||||
|
{ 0x0020, "image_key" },
|
||||||
|
{ 0x0080, "general_digests" },
|
||||||
|
{ 0x0100, "metas" },
|
||||||
|
{ 0x0200, "entry_names" },
|
||||||
|
{ 0x0400, "license.dat" },
|
||||||
|
{ 0x0401, "license.info" },
|
||||||
|
{ 0x0402, "nptitle.dat" },
|
||||||
|
{ 0x0403, "npbind.dat" },
|
||||||
|
{ 0x0409, "psreserved.dat" },
|
||||||
|
{ 0x1000, "param.sfo" },
|
||||||
|
{ 0x1001, "playgo-chunk.dat" },
|
||||||
|
{ 0x1002, "playgo-chunk.sha" },
|
||||||
|
{ 0x1003, "playgo-manifest.xml" },
|
||||||
|
{ 0x1004, "pronunciation.xml" },
|
||||||
|
{ 0x1005, "pronunciation.sig" },
|
||||||
|
{ 0x1006, "pic1.png" },
|
||||||
|
{ 0x1007, "pubtoolinfo.dat" },
|
||||||
|
{ 0x100B, "shareparam.json" },
|
||||||
|
{ 0x100C, "shareoverlayimage.png" },
|
||||||
|
{ 0x100E, "shareprivacyguardimage.png"},
|
||||||
|
{ 0x1200, "icon0.png" },
|
||||||
|
{ 0x1220, "pic0.png" },
|
||||||
|
{ 0x1240, "snd0.at9" },
|
||||||
|
{ 0x1280, "icon0.dds" },
|
||||||
|
{ 0x12A0, "pic0.dds" },
|
||||||
|
{ 0x12C0, "pic1.dds" },
|
||||||
|
{ 0x1400, "trophy/trophy00.trp" }
|
||||||
|
};
|
||||||
|
std::string entry_name="";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof entries / sizeof entries[0]; i++) {
|
||||||
|
if (type == entries[i].type) {
|
||||||
|
entry_name = entries[i].name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
using S08 = char;
|
||||||
|
using S16 = short;
|
||||||
|
using S32 = int;
|
||||||
|
using S64 = long long;
|
||||||
|
|
||||||
|
using U08 = unsigned char;
|
||||||
|
using U16 = unsigned short;
|
||||||
|
using U32 = unsigned int;
|
||||||
|
using U64 = unsigned long long;
|
||||||
|
|
||||||
|
using F32 = float;
|
||||||
|
using F64 = double;
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T > T inline LoadBE(T* src) { return *src; };
|
||||||
|
template< typename T > inline void StoreBE(T* dst, T src) { *dst = src; };
|
||||||
|
|
||||||
|
inline S16 LoadBE(S16* src) { return _loadbe_i16(src); };
|
||||||
|
inline S32 LoadBE(S32* src) { return _loadbe_i32(src); };
|
||||||
|
inline S64 LoadBE(S64* src) { return _loadbe_i64(src); };
|
||||||
|
|
||||||
|
inline U16 LoadBE(U16* src) { return _load_be_u16(src); };
|
||||||
|
inline U32 LoadBE(U32* src) { return _load_be_u32(src); };
|
||||||
|
inline U64 LoadBE(U64* src) { return _load_be_u64(src); };
|
||||||
|
|
||||||
|
inline void StoreBE(S16* dst, S16 const src) { _storebe_i16(dst, src); };
|
||||||
|
inline void StoreBE(S32* dst, S32 const src) { _storebe_i32(dst, src); };
|
||||||
|
inline void StoreBE(S64* dst, S64 const src) { _storebe_i64(dst, src); };
|
||||||
|
|
||||||
|
inline void StoreBE(U16* dst, U16 const src) { _store_be_u16(dst, src); };
|
||||||
|
inline void StoreBE(U32* dst, U32 const src) { _store_be_u32(dst, src); };
|
||||||
|
inline void StoreBE(U64* dst, U64 const src) { _store_be_u64(dst, src); };
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T > inline void ReadBE(T& val)
|
||||||
|
{
|
||||||
|
val = LoadBE(&val); // swap inplace
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T > inline void WriteBE(T& val)
|
||||||
|
{
|
||||||
|
StoreBE(&val, val); // swap inplace
|
||||||
|
}
|
|
@ -127,8 +127,15 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="FsFile.cpp" />
|
||||||
|
<ClCompile Include="PKG.cpp" />
|
||||||
<ClCompile Include="pkgextract.cpp" />
|
<ClCompile Include="pkgextract.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="FsFile.h" />
|
||||||
|
<ClInclude Include="PKG.h" />
|
||||||
|
<ClInclude Include="Types.h" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|
|
@ -18,5 +18,22 @@
|
||||||
<ClCompile Include="pkgextract.cpp">
|
<ClCompile Include="pkgextract.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="PKG.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="FsFile.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="PKG.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="FsFile.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Types.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue