WoW Model Viewer
Your premiere tool for viewing, equipping and animating World of Warcraft models.
Loading...
Searching...
No Matches
CASCFile.cpp
Go to the documentation of this file.
1#include "CASCFile.h"
2
3#ifndef __CASCLIB_SELF__
4#define __CASCLIB_SELF__
5#endif
6#include "CascLib.h"
7#include "CASCChunks.h"
8#include "ChunkReader.h"
9#include "Game.h"
10#include "Logger.h"
11// #define DEBUG_READ
12
13CASCFile::CASCFile(std::string path, int id) : GameFile(std::move(path), id), m_handle(nullptr)
14{
15}
16
18{
19 close();
20}
21
22size_t CASCFile::read(void* dest, size_t bytes)
23{
25 {
26 return GameFile::read(dest, bytes);
27 }
28 else
29 {
30 unsigned long result = 0;
31 if (!CascReadFile(m_handle, dest, static_cast<DWORD>(bytes), &result))
32 LOG_ERROR << "Reading" << filepath << "failed." << "Error" << GetLastError();
33
34 return result;
35 }
36}
37
38void CASCFile::seek(size_t offset)
39{
41 {
42 GameFile::seek(offset);
43 }
44 else
45 {
46 if (CascSetFilePointer(m_handle, static_cast<LONG>(offset), nullptr, FILE_BEGIN) == CASC_INVALID_POS)
47 LOG_ERROR << "Seek in file" << filepath << "to position" << offset << "failed. Error" << GetLastError();
48 }
49}
50
52{
53 if ((m_fileDataId > 0 && GAMEDIRECTORY.openFile(m_fileDataId, &m_handle))
54 || GAMEDIRECTORY.openFile(filepath, &m_handle))
55 {
56 return true;
57 }
58 LOG_ERROR << "Opening" << filepath << "(ID:" << m_fileDataId << ")" << "failed." << "Error" << GetLastError();
59 return false;
60}
61
63{
64 if (m_handle)
65 return true;
66 else
67 return false;
68}
69
70bool CASCFile::getFileSize(unsigned long long& s)
71{
72 bool result = false;
73
74 if (m_handle)
75 {
76 s = CascGetFileSize(m_handle, nullptr);
77
78 if (s == CASC_INVALID_SIZE)
79 LOG_ERROR << "Opening" << filepath << "failed." << "Error" << GetLastError();
80 else
81 result = true;
82 }
83
84 return result;
85}
86
87unsigned long CASCFile::readFile()
88{
89 unsigned long result = 0;
90
91 if (!CascReadFile(m_handle, buffer, size, &result))
92 LOG_ERROR << "Reading" << filepath << "failed." << "Error" << GetLastError();
93
94 return result;
95}
96
98{
100 return;
101
102 const auto parsed = ChunkReader::parse(buffer, size);
103 for (const auto& ci : parsed)
104 {
105 Chunk chunk;
106 chunk.magic = ci.magic;
107 chunk.start = ci.start;
108 chunk.size = ci.size;
109 chunk.pointer = 0;
110 chunks.push_back(std::move(chunk));
111 }
112
113 if (chunks.size() == 1)
114 setChunk(chunks[0].magic);
115}
116
118{
119#ifdef DEBUG_READ
120 LOG_INFO << this << __FUNCTION__ << "Closing" << filepath << "handle" << m_handle;
121#endif
122 if (m_handle)
123 {
124 HANDLE savedHandle = m_handle;
125 m_handle = nullptr;
126
127#ifdef DEBUG_READ
128 bool result = CascCloseFile(savedHandle);
129 LOG_INFO << __FUNCTION__ << result;
130 return result;
131#else
132 return CascCloseFile(savedHandle);
133#endif
134 }
135
136 return true;
137}
138
140{
141 LOG_INFO << "Structure for file" << filepath;
142 for (auto it : chunks)
143 {
144 if (it.magic == "AFID")
145 {
146 LOG_INFO << "Chunk :" << it.magic.c_str() << "nb anim file id" << it.size / sizeof(AFID);
147 setChunk("AFID");
148 while (!isEof())
149 {
150 AFID afid;
151 read(&afid, sizeof(AFID));
152 const GameFile* f = GAMEDIRECTORY.getFile(afid.fileId);
153 if (f)
154 LOG_INFO << f->fullname();
155 }
156 }
157 else if (it.magic == "SKS1")
158 {
159 setChunk("SKS1");
160 SKS1 sks1;
161 read(&sks1, sizeof(sks1));
162 LOG_INFO << "Chunk :" << it.magic.c_str() << "nGlobalSequences" << sks1.nGlobalSequences << "nAnimations" <<
163 sks1.nAnimations << "nAnimationLookup" << sks1.nAnimationLookup;
164 }
165 else if (it.magic == "SKA1")
166 {
167 setChunk("SKA1");
168 SKA1 ska1;
169 read(&ska1, sizeof(ska1));
170 LOG_INFO << "Chunk :" << it.magic.c_str() << "nAttachments" << ska1.nAttachments << "nAttachLookup" << ska1.
171 nAttachLookup;
172 }
173 else if (it.magic == "SKB1")
174 {
175 setChunk("SKB1");
176 SKB1 skb1;
177 read(&skb1, sizeof(skb1));
178 LOG_INFO << "Chunk :" << it.magic.c_str() << "nBones" << skb1.nBones << "nKeyBoneLookup" << skb1.
179 nKeyBoneLookup;
180 }
181 else if (it.magic == "SKPD")
182 {
183 setChunk("SKPD");
184 SKPD skpd;
185 read(&skpd, sizeof(skpd));
186 LOG_INFO << "Chunk :" << it.magic.c_str() << "parentFileId" << skpd.parentFileId;
187 }
188 else if (it.magic == "BFID")
189 {
190 LOG_INFO << "Chunk :" << it.magic.c_str() << "nb bone files id" << it.size / sizeof(uint32);
191 setChunk("BFID");
192 while (!isEof())
193 {
194 uint32 id;
195 read(&id, sizeof(uint32));
196 const GameFile* f = GAMEDIRECTORY.getFile(id);
197 if (f)
198 LOG_INFO << f->fullname();
199 }
200 }
201 else
202 {
203 LOG_INFO << "Chunk :" << it.magic.c_str() << it.start << it.size;
204 }
205 }
206}
#define GAMEDIRECTORY
Definition Game.h:9
#define LOG_ERROR
Definition Logger.h:11
#define LOG_INFO
Definition Logger.h:10
virtual void doPostOpenOperation()
Definition CASCFile.cpp:97
virtual unsigned long readFile()
Definition CASCFile.cpp:87
virtual bool isAlreadyOpened()
Definition CASCFile.cpp:62
virtual bool doPostCloseOperation()
Definition CASCFile.cpp:117
void dumpStructure()
Definition CASCFile.cpp:139
size_t read(void *dest, size_t bytes)
Read bytes from the file into dest.
Definition CASCFile.cpp:22
HANDLE m_handle
Definition CASCFile.h:39
virtual bool getFileSize(unsigned long long &s)
Definition CASCFile.cpp:70
CASCFile(std::string path, int id=-1)
Definition CASCFile.cpp:13
void seek(size_t offset)
Seek to an absolute byte offset.
Definition CASCFile.cpp:38
virtual bool openFile()
Definition CASCFile.cpp:51
Abstract base class representing a file within the game data archive.
Definition GameFile.h:12
bool m_useMemoryBuffer
Definition GameFile.h:96
std::string filepath
Definition GameFile.h:84
virtual void seek(size_t offset)
Seek to an absolute byte offset.
Definition GameFile.cpp:29
std::vector< Chunk > chunks
Definition GameFile.h:95
unsigned char * buffer
Definition GameFile.h:82
unsigned long long size
Definition GameFile.h:83
bool close()
Close the file and release the internal buffer.
Definition GameFile.cpp:74
virtual size_t read(void *dest, size_t bytes)
Read bytes from the file into dest.
Definition GameFile.cpp:5
int m_fileDataId
Definition GameFile.h:85
const std::string & fullname() const
Definition GameFile.h:56
bool setChunk(std::string chunkName, bool resetToStart=true)
Switch the active read window to the named chunk.
Definition GameFile.cpp:100
bool isEof()
True if the read pointer has reached the end of the file.
Definition GameFile.cpp:24
bool isChunked(const unsigned char *data, size_t dataSize)
Determine whether a buffer begins with a known chunked-file header.
Definition ChunkReader.h:61
std::vector< ChunkInfo > parse(const unsigned char *data, size_t dataSize)
Parse all top-level chunks from a buffer.
Definition ChunkReader.h:86
Animation file ID entry mapping anim/sub-anim to a CASC file ID (AFID chunk).
Definition CASCChunks.h:14
uint32 fileId
CASC file data ID.
Definition CASCChunks.h:17
unsigned int start
Definition GameFile.h:90
unsigned int size
Definition GameFile.h:91
std::string magic
Definition GameFile.h:89
unsigned int pointer
Definition GameFile.h:92
Skeleton attachment data header (SKA1 chunk).
Definition CASCChunks.h:33
uint32 nAttachments
Number of attachments.
Definition CASCChunks.h:34
Skeleton bone data header (SKB1 chunk).
Definition CASCChunks.h:42
uint32 nBones
Number of bones.
Definition CASCChunks.h:43
Skeleton parent data chunk (SKPD).
Definition CASCChunks.h:51
uint32 parentFileId
File data ID of the parent skeleton.
Definition CASCChunks.h:53
Skeleton sequence data header (SKS1 chunk).
Definition CASCChunks.h:22
uint32 nAnimationLookup
Number of animation lookup entries.
Definition CASCChunks.h:27
uint32 nAnimations
Number of animations.
Definition CASCChunks.h:25
uint32 nGlobalSequences
Number of global sequences.
Definition CASCChunks.h:23
uint32_t uint32
Definition types.h:34