summaryrefslogtreecommitdiff
path: root/src/core/tracer/recorder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/tracer/recorder.cpp')
-rw-r--r--src/core/tracer/recorder.cpp208
1 files changed, 0 insertions, 208 deletions
diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp
deleted file mode 100644
index 73cacb47f..000000000
--- a/src/core/tracer/recorder.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include "common/assert.h"
7#include "common/file_util.h"
8#include "common/logging/log.h"
9#include "core/tracer/recorder.h"
10
11namespace CiTrace {
12
13Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) {}
14
15void Recorder::Finish(const std::string& filename) {
16 // Setup CiTrace header
17 CTHeader header;
18 std::memcpy(header.magic, CTHeader::ExpectedMagicWord(), 4);
19 header.version = CTHeader::ExpectedVersion();
20 header.header_size = sizeof(CTHeader);
21
22 // Calculate file offsets
23 auto& initial = header.initial_state_offsets;
24
25 initial.gpu_registers_size = static_cast<u32>(initial_state.gpu_registers.size());
26 initial.lcd_registers_size = static_cast<u32>(initial_state.lcd_registers.size());
27 initial.pica_registers_size = static_cast<u32>(initial_state.pica_registers.size());
28 initial.default_attributes_size = static_cast<u32>(initial_state.default_attributes.size());
29 initial.vs_program_binary_size = static_cast<u32>(initial_state.vs_program_binary.size());
30 initial.vs_swizzle_data_size = static_cast<u32>(initial_state.vs_swizzle_data.size());
31 initial.vs_float_uniforms_size = static_cast<u32>(initial_state.vs_float_uniforms.size());
32 initial.gs_program_binary_size = static_cast<u32>(initial_state.gs_program_binary.size());
33 initial.gs_swizzle_data_size = static_cast<u32>(initial_state.gs_swizzle_data.size());
34 initial.gs_float_uniforms_size = static_cast<u32>(initial_state.gs_float_uniforms.size());
35 header.stream_size = static_cast<u32>(stream.size());
36
37 initial.gpu_registers = sizeof(header);
38 initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32);
39 initial.pica_registers = initial.lcd_registers + initial.lcd_registers_size * sizeof(u32);
40 ;
41 initial.default_attributes = initial.pica_registers + initial.pica_registers_size * sizeof(u32);
42 initial.vs_program_binary =
43 initial.default_attributes + initial.default_attributes_size * sizeof(u32);
44 initial.vs_swizzle_data =
45 initial.vs_program_binary + initial.vs_program_binary_size * sizeof(u32);
46 initial.vs_float_uniforms =
47 initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32);
48 initial.gs_program_binary =
49 initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32);
50 initial.gs_swizzle_data =
51 initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32);
52 initial.gs_float_uniforms =
53 initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32);
54 header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32);
55
56 // Iterate through stream elements, update relevant stream element data
57 for (auto& stream_element : stream) {
58 switch (stream_element.data.type) {
59 case MemoryLoad: {
60 auto& file_offset = memory_regions[stream_element.hash];
61 if (!stream_element.uses_existing_data) {
62 file_offset = header.stream_offset;
63 }
64 stream_element.data.memory_load.file_offset = file_offset;
65 break;
66 }
67
68 default:
69 // Other commands don't use any extra data
70 DEBUG_ASSERT(stream_element.extra_data.size() == 0);
71 break;
72 }
73 header.stream_offset += static_cast<u32>(stream_element.extra_data.size());
74 }
75
76 try {
77 // Open file and write header
78 FileUtil::IOFile file(filename, "wb");
79 std::size_t written = file.WriteObject(header);
80 if (written != 1 || file.Tell() != initial.gpu_registers)
81 throw "Failed to write header";
82
83 // Write initial state
84 written =
85 file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size());
86 if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers)
87 throw "Failed to write GPU registers";
88
89 written =
90 file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size());
91 if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers)
92 throw "Failed to write LCD registers";
93
94 written = file.WriteArray(initial_state.pica_registers.data(),
95 initial_state.pica_registers.size());
96 if (written != initial_state.pica_registers.size() ||
97 file.Tell() != initial.default_attributes)
98 throw "Failed to write Pica registers";
99
100 written = file.WriteArray(initial_state.default_attributes.data(),
101 initial_state.default_attributes.size());
102 if (written != initial_state.default_attributes.size() ||
103 file.Tell() != initial.vs_program_binary)
104 throw "Failed to write default vertex attributes";
105
106 written = file.WriteArray(initial_state.vs_program_binary.data(),
107 initial_state.vs_program_binary.size());
108 if (written != initial_state.vs_program_binary.size() ||
109 file.Tell() != initial.vs_swizzle_data)
110 throw "Failed to write vertex shader program binary";
111
112 written = file.WriteArray(initial_state.vs_swizzle_data.data(),
113 initial_state.vs_swizzle_data.size());
114 if (written != initial_state.vs_swizzle_data.size() ||
115 file.Tell() != initial.vs_float_uniforms)
116 throw "Failed to write vertex shader swizzle data";
117
118 written = file.WriteArray(initial_state.vs_float_uniforms.data(),
119 initial_state.vs_float_uniforms.size());
120 if (written != initial_state.vs_float_uniforms.size() ||
121 file.Tell() != initial.gs_program_binary)
122 throw "Failed to write vertex shader float uniforms";
123
124 written = file.WriteArray(initial_state.gs_program_binary.data(),
125 initial_state.gs_program_binary.size());
126 if (written != initial_state.gs_program_binary.size() ||
127 file.Tell() != initial.gs_swizzle_data)
128 throw "Failed to write geomtry shader program binary";
129
130 written = file.WriteArray(initial_state.gs_swizzle_data.data(),
131 initial_state.gs_swizzle_data.size());
132 if (written != initial_state.gs_swizzle_data.size() ||
133 file.Tell() != initial.gs_float_uniforms)
134 throw "Failed to write geometry shader swizzle data";
135
136 written = file.WriteArray(initial_state.gs_float_uniforms.data(),
137 initial_state.gs_float_uniforms.size());
138 if (written != initial_state.gs_float_uniforms.size() ||
139 file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size)
140 throw "Failed to write geometry shader float uniforms";
141
142 // Iterate through stream elements, write "extra data"
143 for (const auto& stream_element : stream) {
144 if (stream_element.extra_data.size() == 0)
145 continue;
146
147 written =
148 file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size());
149 if (written != stream_element.extra_data.size())
150 throw "Failed to write extra data";
151 }
152
153 if (file.Tell() != header.stream_offset)
154 throw "Unexpected end of extra data";
155
156 // Write actual stream elements
157 for (const auto& stream_element : stream) {
158 if (1 != file.WriteObject(stream_element.data))
159 throw "Failed to write stream element";
160 }
161 } catch (const char* str) {
162 LOG_ERROR(HW_GPU, "Writing CiTrace file failed: {}", str);
163 }
164}
165
166void Recorder::FrameFinished() {
167 stream.push_back({{FrameMarker}});
168}
169
170void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) {
171 StreamElement element = {{MemoryLoad}};
172 element.data.memory_load.size = size;
173 element.data.memory_load.physical_address = physical_address;
174
175 // Compute hash over given memory region to check if the contents are already stored internally
176 boost::crc_32_type result;
177 result.process_bytes(data, size);
178 element.hash = result.checksum();
179
180 element.uses_existing_data = (memory_regions.find(element.hash) != memory_regions.end());
181 if (!element.uses_existing_data) {
182 element.extra_data.resize(size);
183 memcpy(element.extra_data.data(), data, size);
184 memory_regions.insert({element.hash, 0}); // file offset will be initialized in Finish()
185 }
186
187 stream.push_back(element);
188}
189
190template <typename T>
191void Recorder::RegisterWritten(u32 physical_address, T value) {
192 StreamElement element = {{RegisterWrite}};
193 element.data.register_write.size =
194 (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8
195 : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16
196 : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32
197 : CTRegisterWrite::SIZE_64;
198 element.data.register_write.physical_address = physical_address;
199 element.data.register_write.value = value;
200
201 stream.push_back(element);
202}
203
204template void Recorder::RegisterWritten(u32, u8);
205template void Recorder::RegisterWritten(u32, u16);
206template void Recorder::RegisterWritten(u32, u32);
207template void Recorder::RegisterWritten(u32, u64);
208} // namespace CiTrace