1 #include "xbox_ref_log.h"
17 static FILE *g_xbox_ref_log = NULL;
18 static char g_xbox_ref_log_path[MAX_PATH * 2] = {0};
19 static char g_xbox_ref_temp_path[MAX_PATH * 2] = {0};
20 static int g_xbox_ref_using_temp = 0;
22 static void xbox_ref_build_log_path(const char *target_filename, char drive_letter, char *out, size_t out_size, int *is_temp)
24 if (!out || out_size == 0)
31 if (target_filename && target_filename[0]) {
32 snprintf(out, out_size, "%s.log", target_filename);
36 if (drive_letter && isalpha((unsigned char)drive_letter))
37 snprintf(out, out_size, "friidump_%c.log", (char)tolower((unsigned char)drive_letter));
39 snprintf(out, out_size, "friidump.log");
45 static int xbox_ref_open_path(const char *path, int append)
47 if (!path || !path[0])
50 g_xbox_ref_log = fopen(path, append ? "ab" : "wb");
54 strncpy(g_xbox_ref_log_path, path, sizeof(g_xbox_ref_log_path) - 1);
55 g_xbox_ref_log_path[sizeof(g_xbox_ref_log_path) - 1] = '\0';
59 int xbox_ref_log_open_for_target(const char *target_filename, char drive_letter)
61 char path[MAX_PATH * 2];
64 xbox_ref_build_log_path(target_filename, drive_letter, path, sizeof(path), &is_temp);
66 if (g_xbox_ref_log && strcmp(g_xbox_ref_log_path, path) == 0)
71 if (!xbox_ref_open_path(path, 0)) {
72 fprintf(stderr, "[FRIIDUMP][WARN] Could not create log file '%s'. Continuing without file logging.\n", path[0] ? path : "(none)");
76 g_xbox_ref_using_temp = is_temp;
78 strncpy(g_xbox_ref_temp_path, path, sizeof(g_xbox_ref_temp_path) - 1);
79 g_xbox_ref_temp_path[sizeof(g_xbox_ref_temp_path) - 1] = '\0';
81 g_xbox_ref_temp_path[0] = '\0';
84 xbox_ref_printf("[FRIIDUMP] Log file: %s\n", g_xbox_ref_log_path);
88 int xbox_ref_log_retarget(const char *target_filename)
90 char final_path[MAX_PATH * 2];
93 if (!target_filename || !target_filename[0])
96 xbox_ref_build_log_path(target_filename, 0, final_path, sizeof(final_path), &dummy);
100 if (strcmp(g_xbox_ref_log_path, final_path) == 0)
103 if (!g_xbox_ref_log) {
104 return xbox_ref_open_path(final_path, 0);
107 xbox_ref_printf("[FRIIDUMP] Retargeting log file to: %s\n", final_path);
108 fclose(g_xbox_ref_log);
109 g_xbox_ref_log = NULL;
111 if (g_xbox_ref_using_temp && g_xbox_ref_temp_path[0]) {
113 if (rename(g_xbox_ref_temp_path, final_path) == 0) {
114 g_xbox_ref_using_temp = 0;
115 g_xbox_ref_temp_path[0] = '\0';
116 return xbox_ref_open_path(final_path, 1);
120 g_xbox_ref_using_temp = 0;
121 g_xbox_ref_temp_path[0] = '\0';
122 return xbox_ref_open_path(final_path, 1);
125 void xbox_ref_log_close(void)
127 if (g_xbox_ref_log) {
128 fflush(g_xbox_ref_log);
129 fclose(g_xbox_ref_log);
131 g_xbox_ref_log = NULL;
132 g_xbox_ref_log_path[0] = '\0';
133 g_xbox_ref_temp_path[0] = '\0';
134 g_xbox_ref_using_temp = 0;
137 int xbox_ref_log_is_open(void)
139 return g_xbox_ref_log != NULL;
142 const char *xbox_ref_log_path(void)
144 return g_xbox_ref_log_path[0] ? g_xbox_ref_log_path : NULL;
147 int xbox_ref_printf(const char *fmt, ...)
155 out = vprintf(fmt, ap);
157 if (g_xbox_ref_log) {
158 vfprintf(g_xbox_ref_log, fmt, ap2);
159 fflush(g_xbox_ref_log);
166 int xbox_ref_log_fprintf(FILE *stream, const char *fmt, ...)
177 out = vfprintf(stream, fmt, ap);
179 if (g_xbox_ref_log) {
180 vfprintf(g_xbox_ref_log, fmt, ap2);
181 fflush(g_xbox_ref_log);
188 int xbox_ref_console_printf(const char *fmt, ...)
194 out = vprintf(fmt, ap);
200 static void xbox_ref_hexdump_to_file(FILE *stream, const char *prefix, const uint8_t *data, size_t length, size_t limit, int truncated)
203 size_t shown = (limit && limit < length) ? limit : length;
205 if (!stream || !prefix)
209 fprintf(stream, "\n--- %s (%lu bytes; console showing first %lu bytes, full data in log) ---\n",
210 prefix, (unsigned long)length, (unsigned long)shown);
212 fprintf(stream, "\n--- %s (%lu bytes) ---\n", prefix, (unsigned long)length);
214 for (i = 0; i < shown; i++) {
215 fprintf(stream, "%02X ", data ? data[i] : 0);
216 if ((i + 1) % 16 == 0)
217 fprintf(stream, "\n");
220 fprintf(stream, "\n");
222 fprintf(stream, "... [truncated on console; full %lu bytes written to log]\n", (unsigned long)length);
223 fprintf(stream, "---------------------------\n");
227 void xbox_ref_log_hexdump(const char *prefix, const uint8_t *data, size_t length, size_t console_limit)
229 int console_truncated = (console_limit > 0 && console_limit < length);
231 xbox_ref_hexdump_to_file(stdout, prefix, data, length, console_limit, console_truncated);
233 if (g_xbox_ref_log) {
234 /* The log is intentionally never truncated. */
235 xbox_ref_hexdump_to_file(g_xbox_ref_log, prefix, data, length, 0, 0);