1 #include <cstring>
2 
3 #include "Common/Log.h"
4 #include "Common/Data/Format/RIFF.h"
5 
flipID(uint32_t id)6 inline uint32_t flipID(uint32_t id) {
7 	return ((id >> 24) & 0xFF) | ((id >> 8) & 0xFF00) | ((id << 8) & 0xFF0000) | ((id << 24) & 0xFF000000);
8 }
9 
RIFFReader(const uint8_t * data,int dataSize)10 RIFFReader::RIFFReader(const uint8_t *data, int dataSize) {
11 	data_ = new uint8_t[dataSize];
12 	memcpy(data_, data, dataSize);
13 	depth_ = 0;
14 	pos_ = 0;
15 	eof_ = dataSize;
16 	fileSize_ = dataSize;
17 }
18 
~RIFFReader()19 RIFFReader::~RIFFReader() {
20 	delete[] data_;
21 }
22 
ReadInt()23 int RIFFReader::ReadInt() {
24 	if (data_ && pos_ < eof_ - 3) {
25 		pos_ += 4;
26 		return *(int *)(data_ + pos_ - 4);
27 	}
28 	return 0;
29 }
30 
Descend(uint32_t intoId)31 bool RIFFReader::Descend(uint32_t intoId) {
32 	if (depth_ > 30)
33 		return false;
34 
35 	intoId = flipID(intoId);
36 	bool found = false;
37 
38 	// save information to restore after the next Ascend
39 	stack[depth_].parentStartLocation = pos_;
40 	stack[depth_].parentEOF = eof_;
41 
42 	// let's search through children..
43 	while (pos_ < eof_) {
44 		int id = ReadInt();
45 		int length = ReadInt();
46 		int startLocation = pos_;
47 
48 		if (pos_ + length > fileSize_) {
49 			ERROR_LOG(IO, "Block extends outside of RIFF file - failing descend");
50 			pos_ = stack[depth_].parentStartLocation;
51 			return false;
52 		}
53 
54 		if (id == intoId) {
55 			stack[depth_].ID = intoId;
56 			stack[depth_].length = length;
57 			stack[depth_].startLocation = startLocation;
58 			found = true;
59 			break;
60 		} else {
61 			if (length > 0) {
62 				pos_ += length; // try next block
63 			} else {
64 				ERROR_LOG(IO, "Bad data in RIFF file : block length %d. Not descending.", length);
65 				pos_ = stack[depth_].parentStartLocation;
66 				return false;
67 			}
68 		}
69 	}
70 
71 	// if we found nothing, return false so the caller can skip this
72 	if (!found) {
73 		pos_ = stack[depth_].parentStartLocation;
74 		return false;
75 	}
76 
77 	// descend into it
78 	// pos was set inside the loop above
79 	eof_ = stack[depth_].startLocation + stack[depth_].length;
80 	depth_++;
81 	return true;
82 }
83 
Ascend()84 void RIFFReader::Ascend() {
85 	// ascend, and restore information
86 	depth_--;
87 	pos_ = stack[depth_].parentStartLocation;
88 	eof_ = stack[depth_].parentEOF;
89 }
90 
ReadData(void * what,int count)91 void RIFFReader::ReadData(void *what, int count) {
92 	memcpy(what, data_ + pos_, count);
93 	pos_ += count;
94 	count &= 3;
95 	if (count) {
96 		count = 4 - count;
97 		pos_ += count;
98 	}
99 }
100 
GetCurrentChunkSize()101 int RIFFReader::GetCurrentChunkSize() {
102 	if (depth_)
103 		return stack[depth_ - 1].length;
104 	else
105 		return 0;
106 }
107 
108