-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathItem.cpp
129 lines (107 loc) · 4.46 KB
/
Item.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "Item.h"
#include <cstdlib>
#include <cstring>
#include "Errors.h"
#include "module/Module.h"
#define DUMP_DATA_TABLE false
#define DUMP_CONTENT_TABLE false
#define DUMP_STRING_TABLE false
Item::Item(uint8_t* data, uint32_t length, Logger* logger, std::string name, std::string path, ModuleItem* moduleItem){
this->moduleItem = moduleItem;
// copy the strings. Ideally, we don't want to depend on any data managed by another object
this->name = std::string(name);
this->path = std::string(path);
this->logger = logger;
this->tagManager = nullptr;
// create a copy of the file. By doing this I don't need to keep track of which extracted buffer is still needed and which one can be freed
// and it should only momentarily increase memory usage, unless an item gets opened multiple times without freeing it again first
this->data = (uint8_t*)malloc(length);
memcpy(this->data,data,length);
// read the header
int r = this->header.parseHeader(this->data);
if(r != ERROR_NONE){
checkedlog(logger, LOG_LEVEL_ERROR,"Could not parse Header!\n");
return;
}
r = dataTable.readTable(data + header.dataTableOffset, header.dataTableCount);
if(DUMP_DATA_TABLE){
checkedlog(logger, LOG_LEVEL_DEBUG,"\n\n\n");
checkedlog(logger, LOG_LEVEL_DEBUG,"Data Table:\nSize\tRegion\tOffset\n");
for(int i = 0; i < dataTable.entries.size(); i++){
checkedlog(logger, LOG_LEVEL_DEBUG,"0x%x\t0x%x\t0x%x\t\n",dataTable.entries[i].size,dataTable.entries[i].region,dataTable.entries[i].offset);
}
}
r = contentTable.readTable(data + header.contentTableOffset, header.contentTableCount);
for(int i = 0; i < contentTable.entries.size(); i++){
if(contentTable.entries[i].ref != -1){
dataTable.entries[contentTable.entries[i].ref].cte = &contentTable.entries[i];
}
if(contentTable.entries[i].parent != -1){
dataTable.entries[contentTable.entries[i].parent].cte->children.emplace_back(&contentTable.entries[i]);
contentTable.entries[i].parentEntry = dataTable.entries[contentTable.entries[i].parent].cte;
} else {
// no parent -> root entry
contentTable.rootEntries.emplace_back(&contentTable.entries[i]);
}
}
if(DUMP_CONTENT_TABLE){
checkedlog(logger, LOG_LEVEL_DEBUG,"Type\t\tRef\tParent\n");
for(int i = 0; i < contentTable.entries.size(); i++){
checkedlog(logger, LOG_LEVEL_DEBUG,"0x%llx %#llx\t%#x\t%#x\n",contentTable.entries[i].type.data[0],contentTable.entries[i].type.data[1],contentTable.entries[i].ref,contentTable.entries[i].parent);
}
}
bool stillHasPaths = moduleItem->module->version < 0x35;
r = tagRefFieldTable.readStrings(data + header.stringTableOffset, header.stringCount, header.stringLength, data + header.stringDataOffset,stillHasPaths);
if(DUMP_STRING_TABLE){
checkedlog(logger, LOG_LEVEL_DEBUG,"Valid Strings\n");
for(int i = 0; i < tagRefFieldTable.strings.size(); i++){
checkedlog(logger, LOG_LEVEL_DEBUG,"%s\n",tagRefFieldTable.strings[i].string.c_str());
}
checkedlog(logger, LOG_LEVEL_DEBUG,"Invalid Strings\n");
for(int i = 0; i < tagRefFieldTable.invalidStrings.size(); i++){
checkedlog(logger, LOG_LEVEL_DEBUG,"%s\n",tagRefFieldTable.invalidStrings[i].string.c_str());
}
}
r = tagRefTable.readTable(data + header.tagRefTableOffset, header.tagRefTableCount,(char*) data + header.stringDataOffset);
r = dataRefTable.readTable(data + header.dataReferenceTableOffset, header.dataReferenceTableCount);
//checkedlog(logger, LOG_LEVEL_DEBUG, "Data Offset: 0x%lx, Data2 Offset: 0x%lx\n",this->header.dataOffset,this->header.data2Offset);
}
Item::~Item(){
free(data);
//printf("deleting Item\n");
}
void* Item::getDataBlock(DataTableEntry* entry){
// get the full offset in the file. This depends on the region the data block is in
uint32_t offset = entry->offset;
if(entry->region == 1){
offset += header.dataOffset;
}
if(entry->region == 2){
offset += header.data2Offset;
}
if(entry->region == 3){
offset += header.data3Offset;
}
//uint32_t full_offset = entry->region == 1 ? header.dataOffset + entry->offset : header.data2Offset + entry->offset;
return data + offset;
}
void* Item::getRefDataBlock(ContentTableEntry* entry){
if(entry->ref == -1){
// no ref
return nullptr;
}
return getDataBlock(&dataTable.entries[entry->ref]);
}
uint32_t Item::getDataBlockOffset(DataTableEntry* entry){
uint32_t offset = entry->offset;
if(entry->region == 1){
offset += header.dataOffset;
}
if(entry->region == 2){
offset += header.data2Offset;
}
if(entry->region == 3){
offset += header.data3Offset;
}
return offset;
}