|
40 | 40 | #include "emu.h" |
41 | 41 | #include "config.h" |
42 | 42 |
|
| 43 | +static const char* GLDEBUG_MAGIC = "GLDEBUG2"; |
| 44 | +static const int GLDEBUG_MAGIC_LEN = 8; |
| 45 | +static const int GLDEBUG_MAX_RECORDS = 0x10000; |
| 46 | + |
| 47 | +static bool read_settings_data(std::istream& stream, void* data, size_t size); |
| 48 | +static bool read_settings_bool(std::istream& stream, bool& value); |
| 49 | +static bool read_settings_count(std::istream& stream, int& count, size_t record_size); |
| 50 | + |
43 | 51 | void gui_debug_init(void) |
44 | 52 | { |
45 | 53 | gui_debug_trace_logger_init(); |
@@ -131,9 +139,6 @@ void gui_debug_windows(void) |
131 | 139 | } |
132 | 140 | } |
133 | 141 |
|
134 | | -static const char* GLDEBUG_MAGIC = "GLDEBUG2"; |
135 | | -static const int GLDEBUG_MAGIC_LEN = 8; |
136 | | - |
137 | 142 | void gui_debug_save_settings(const char* file_path) |
138 | 143 | { |
139 | 144 | std::ofstream file(file_path, std::ios::binary); |
@@ -196,49 +201,93 @@ void gui_debug_load_settings(const char* file_path) |
196 | 201 | } |
197 | 202 |
|
198 | 203 | char magic[8] = {}; |
199 | | - file.read(magic, GLDEBUG_MAGIC_LEN); |
200 | | - if (file.gcount() != GLDEBUG_MAGIC_LEN || memcmp(magic, GLDEBUG_MAGIC, GLDEBUG_MAGIC_LEN) != 0) |
| 204 | + if (!read_settings_data(file, magic, GLDEBUG_MAGIC_LEN) || |
| 205 | + memcmp(magic, GLDEBUG_MAGIC, GLDEBUG_MAGIC_LEN) != 0) |
201 | 206 | { |
202 | 207 | Log("Invalid debug settings file: %s", file_path); |
203 | | - file.close(); |
204 | 208 | return; |
205 | 209 | } |
206 | 210 |
|
207 | 211 | GearlynxCore* core = emu_get_core(); |
208 | 212 | M6502* processor = core->GetM6502(); |
209 | 213 |
|
210 | | - processor->ResetBreakpoints(); |
| 214 | + M6502::GLYNX_Breakpoint breakpoint = {}; |
| 215 | + size_t breakpoint_size = sizeof(breakpoint.enabled) + sizeof(breakpoint.address1) + |
| 216 | + sizeof(breakpoint.address2) + sizeof(breakpoint.read) + sizeof(breakpoint.write) + |
| 217 | + sizeof(breakpoint.execute) + sizeof(breakpoint.range); |
211 | 218 | int bp_count = 0; |
212 | | - file.read((char*)&bp_count, sizeof(int)); |
213 | | - std::vector<M6502::GLYNX_Breakpoint>* breakpoints = processor->GetBreakpoints(); |
| 219 | + if (!read_settings_count(file, bp_count, breakpoint_size)) |
| 220 | + { |
| 221 | + Log("Invalid debug settings file: %s", file_path); |
| 222 | + return; |
| 223 | + } |
| 224 | + |
| 225 | + std::vector<M6502::GLYNX_Breakpoint> breakpoints; |
| 226 | + breakpoints.reserve((size_t)bp_count); |
214 | 227 | for (int i = 0; i < bp_count; i++) |
215 | 228 | { |
216 | | - M6502::GLYNX_Breakpoint bp; |
217 | | - file.read((char*)&bp.enabled, sizeof(bool)); |
218 | | - file.read((char*)&bp.address1, sizeof(u16)); |
219 | | - file.read((char*)&bp.address2, sizeof(u16)); |
220 | | - file.read((char*)&bp.read, sizeof(bool)); |
221 | | - file.read((char*)&bp.write, sizeof(bool)); |
222 | | - file.read((char*)&bp.execute, sizeof(bool)); |
223 | | - file.read((char*)&bp.range, sizeof(bool)); |
224 | | - breakpoints->push_back(bp); |
| 229 | + M6502::GLYNX_Breakpoint bp = {}; |
| 230 | + if (!read_settings_bool(file, bp.enabled) || |
| 231 | + !read_settings_data(file, &bp.address1, sizeof(bp.address1)) || |
| 232 | + !read_settings_data(file, &bp.address2, sizeof(bp.address2)) || |
| 233 | + !read_settings_bool(file, bp.read) || |
| 234 | + !read_settings_bool(file, bp.write) || |
| 235 | + !read_settings_bool(file, bp.execute) || |
| 236 | + !read_settings_bool(file, bp.range)) |
| 237 | + { |
| 238 | + Log("Invalid debug settings file: %s", file_path); |
| 239 | + return; |
| 240 | + } |
| 241 | + breakpoints.push_back(bp); |
225 | 242 | } |
226 | 243 |
|
227 | | - file.read((char*)emu_debug_irq_breakpoints, sizeof(bool) * 8); |
| 244 | + bool irq_breakpoints[8] = {}; |
| 245 | + for (int i = 0; i < 8; i++) |
| 246 | + { |
| 247 | + if (!read_settings_bool(file, irq_breakpoints[i])) |
| 248 | + { |
| 249 | + Log("Invalid debug settings file: %s", file_path); |
| 250 | + return; |
| 251 | + } |
| 252 | + } |
228 | 253 |
|
229 | | - gui_debug_reset_disassembler_bookmarks(); |
| 254 | + struct DasmBookmark { u16 address; char name[32]; }; |
| 255 | + DasmBookmark bookmark = {}; |
| 256 | + size_t bookmark_size = sizeof(bookmark.address) + sizeof(bookmark.name); |
230 | 257 | int bookmark_count = 0; |
231 | | - file.read((char*)&bookmark_count, sizeof(int)); |
| 258 | + if (!read_settings_count(file, bookmark_count, bookmark_size)) |
| 259 | + { |
| 260 | + Log("Invalid debug settings file: %s", file_path); |
| 261 | + return; |
| 262 | + } |
| 263 | + |
| 264 | + std::vector<DasmBookmark> bookmarks; |
| 265 | + bookmarks.reserve((size_t)bookmark_count); |
232 | 266 | for (int i = 0; i < bookmark_count; i++) |
233 | 267 | { |
234 | | - u16 address; |
235 | | - char name[32]; |
236 | | - file.read((char*)&address, sizeof(u16)); |
237 | | - file.read(name, 32); |
238 | | - gui_debug_add_disassembler_bookmark(address, name); |
| 268 | + DasmBookmark item = {}; |
| 269 | + if (!read_settings_data(file, &item.address, sizeof(item.address)) || |
| 270 | + !read_settings_data(file, item.name, sizeof(item.name))) |
| 271 | + { |
| 272 | + Log("Invalid debug settings file: %s", file_path); |
| 273 | + return; |
| 274 | + } |
| 275 | + item.name[sizeof(item.name) - 1] = 0; |
| 276 | + bookmarks.push_back(item); |
| 277 | + } |
| 278 | + |
| 279 | + if (!gui_debug_memory_load_settings(file)) |
| 280 | + { |
| 281 | + Log("Invalid debug settings file: %s", file_path); |
| 282 | + return; |
239 | 283 | } |
240 | 284 |
|
241 | | - gui_debug_memory_load_settings(file); |
| 285 | + processor->GetBreakpoints()->swap(breakpoints); |
| 286 | + memcpy(emu_debug_irq_breakpoints, irq_breakpoints, sizeof(irq_breakpoints)); |
| 287 | + |
| 288 | + gui_debug_reset_disassembler_bookmarks(); |
| 289 | + for (int i = 0; i < bookmark_count; i++) |
| 290 | + gui_debug_add_disassembler_bookmark(bookmarks[i].address, bookmarks[i].name); |
242 | 291 |
|
243 | 292 | file.close(); |
244 | 293 |
|
@@ -290,3 +339,55 @@ void gui_debug_auto_load_settings(void) |
290 | 339 |
|
291 | 340 | gui_debug_load_settings(path.c_str()); |
292 | 341 | } |
| 342 | + |
| 343 | +static bool read_settings_data(std::istream& stream, void* data, size_t size) |
| 344 | +{ |
| 345 | + stream.read((char*)data, (std::streamsize)size); |
| 346 | + return !stream.fail() && stream.gcount() == (std::streamsize)size; |
| 347 | +} |
| 348 | + |
| 349 | +static bool read_settings_bool(std::istream& stream, bool& value) |
| 350 | +{ |
| 351 | + u8 data[sizeof(bool)] = {}; |
| 352 | + bool false_value = false; |
| 353 | + bool true_value = true; |
| 354 | + |
| 355 | + if (!read_settings_data(stream, data, sizeof(data))) |
| 356 | + return false; |
| 357 | + if (memcmp(data, &false_value, sizeof(data)) == 0) |
| 358 | + { |
| 359 | + value = false; |
| 360 | + return true; |
| 361 | + } |
| 362 | + if (memcmp(data, &true_value, sizeof(data)) == 0) |
| 363 | + { |
| 364 | + value = true; |
| 365 | + return true; |
| 366 | + } |
| 367 | + |
| 368 | + return false; |
| 369 | +} |
| 370 | + |
| 371 | +static bool read_settings_count(std::istream& stream, int& count, size_t record_size) |
| 372 | +{ |
| 373 | + if (!read_settings_data(stream, &count, sizeof(count))) |
| 374 | + return false; |
| 375 | + if (count < 0 || count > GLDEBUG_MAX_RECORDS || record_size == 0) |
| 376 | + return false; |
| 377 | + |
| 378 | + std::streampos position = stream.tellg(); |
| 379 | + if (position == std::streampos(-1)) |
| 380 | + return false; |
| 381 | + |
| 382 | + stream.seekg(0, std::ios::end); |
| 383 | + std::streampos end = stream.tellg(); |
| 384 | + if (end == std::streampos(-1)) |
| 385 | + return false; |
| 386 | + |
| 387 | + stream.seekg(position); |
| 388 | + if (stream.fail() || end < position) |
| 389 | + return false; |
| 390 | + |
| 391 | + u64 remaining = (u64)(end - position); |
| 392 | + return (u64)count <= remaining / record_size; |
| 393 | +} |
0 commit comments