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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
#include "egg/core/eggDvdRipper.h"
#include "rvl/VI.h" // IWYU pragma: export
namespace EGG {
bool DvdRipper::sErrorRetry = true;
DvdRipper::UnkCallback DvdRipper::sCallback;
u8 *DvdRipper::loadToMainRAM(
s32 entryNum, u8 *dst, Heap *heap, EAllocDirection allocDir, u32 offset, u32 *amountRead, u32 *fileSize
) {
DvdFile file = DvdFile();
if (!file.open(entryNum)) {
return nullptr;
}
return loadToMainRAM(&file, dst, heap, allocDir, offset, amountRead, fileSize);
}
u8 *DvdRipper::loadToMainRAM(
const char *path, u8 *dst, Heap *heap, EAllocDirection allocDir, u32 offset, u32 *amountRead, u32 *fileSize
) {
DvdFile file = DvdFile();
if (!file.open(path)) {
return nullptr;
}
return loadToMainRAM(&file, dst, heap, allocDir, offset, amountRead, fileSize);
}
u8 *DvdRipper::loadToMainRAM(
DvdFile *pFile, u8 *pOut, Heap *pHeap, EAllocDirection allocDir, u32 offset, u32 *pRead, u32 *pSize
) {
u32 size;
bool memAllocated = false;
u32 alignedSize;
s32 result;
u8 buf[0x40];
// msg could be a buffer, it could be a completely different structure,
// there is no good way to know. (callback is never set D: )
// Issue with the callback argument not being placed on the stack properly
if (sCallback) {
UnkCallback_Arg cb_arg;
cb_arg.UNK_0x04 = 0;
cb_arg.UNK_0x08 = 0;
cb_arg.UNK_0x0C = 1;
cb_arg.UNK_0x10 = 0;
cb_arg.buf = &buf;
sCallback(&cb_arg);
}
size = pFile->getFileSize();
if (pSize) {
*pSize = size;
}
alignedSize = nw4r::ut::RoundUp(size, 0x20);
if (!pOut) {
u32 size = alignedSize - offset;
pOut = (u8 *)Heap::alloc(size, allocDir == ALLOC_DIR_TOP ? 0x20 : -0x20, pHeap);
memAllocated = true;
}
if (pOut == nullptr) {
return nullptr;
}
if (offset != 0) {
// Fakematch???? This just feels weird
void *ptr = ROUND_UP_PTR(&buf[8], 0x20);
while (true) {
result = DVDReadPrio(&pFile->mFileInfo, ptr, 0x20, offset, DVD_PRIO_MEDIUM);
if (result >= DVD_RESULT_OK) {
break;
}
if (result == DVD_RESULT_CANCELED || !sErrorRetry) {
if (memAllocated) {
Heap::free(pOut, nullptr);
}
return nullptr;
}
VIWaitForRetrace();
}
DCInvalidateRange(ptr, 0x20);
}
while (true) {
result = DVDReadPrio(&pFile->mFileInfo, pOut, alignedSize - offset, offset, DVD_PRIO_MEDIUM);
if (result >= DVD_RESULT_OK) {
break;
}
if (result == DVD_RESULT_CANCELED || !sErrorRetry) {
if (memAllocated) {
Heap::free(pOut, nullptr);
}
return nullptr;
}
VIWaitForRetrace();
}
if (pRead) {
*pRead = alignedSize - offset;
}
return pOut;
}
void *DvdRipper::loadToMainRAMDecomp(
DvdFile *file, StreamDecomp *decompressor, u8 *pOut, Heap *heap, EAllocDirection allocDir, s32 offset, u32 size,
u32 chunkSize, u32 *pRead, u32 *pSize
) {
s32 uncomp_align = allocDir == ALLOC_DIR_TOP ? 0x20 : -0x20;
s32 align = allocDir == ALLOC_DIR_TOP ? -0x20 : 0x20;
// Ouput size of file
s32 file_size = file->getFileSize();
if (pSize) {
*pSize = file_size;
}
// Setup amount to read
s32 max_read = ROUND_UP(file->getFileSize(), 0x20) - offset;
if (size != 0) {
max_read = size;
}
void *read_buffer = heap->alloc(decompressor->getHeaderSize(), align);
if (!read_buffer) {
return nullptr;
}
s32 result = DVDReadPrio(&file->mFileInfo, read_buffer, decompressor->getHeaderSize(), offset, DVD_PRIO_MEDIUM);
file_size = decompressor->getHeaderSize();
if (result == file_size) {
file_size = decompressor->getUncompressedSize(read_buffer);
} else {
// BUG? - Read buffer never freed
return nullptr;
}
heap->free(read_buffer);
read_buffer = nullptr;
// Already Read header to get size
if (pRead) {
*pRead = decompressor->getHeaderSize();
}
// Ensure decompression space
if (!pOut) {
pOut = (u8 *)heap->alloc(file_size, uncomp_align);
}
if (!pOut) {
return nullptr;
}
// Read and decompress the chunks
void *chunk_buffer = heap->alloc(chunkSize, align);
if (chunk_buffer) {
s32 file_size = 0;
decompressor->init(pOut, max_read);
while (true) {
u32 chunk_size = MIN(max_read - file_size, chunkSize);
u32 chunk_offset = offset + file_size;
s32 result =
DVDReadPrio(&file->mFileInfo, chunk_buffer, ROUND_UP(chunk_size, 0x20), chunk_offset, DVD_PRIO_MEDIUM);
if (result < DVD_RESULT_OK || decompressor->decomp(chunk_buffer, result)) {
break;
}
file_size += result;
}
heap->free(chunk_buffer);
if (pRead) {
*pRead = file_size + decompressor->getHeaderSize();
}
}
return pOut;
}
} // namespace EGG
|