Skip to content

Commit 9e6af37

Browse files
JoeMattclaude
andcommitted
Route all logging through libretro log interface for UI-toggleable verbosity
Add src/log.h with LOG_DBG/LOG_INF/LOG_WRN/LOG_ERR macros that use the retro_log_printf_t callback (falls back to stderr for test harnesses). Convert ~107 fprintf(stderr) calls across 7 source files to use log levels: - Debug: hex dumps, per-sector traces, sentinel matches, GPU loop traces - Info: boot progress, CD loading, auth bypass - Warn: missing BIOS, fallback paths - Error: hard failures (rfopen, magic mismatch, bad lengths) Also: increase boot stub buffer from 12 to 32 sectors (fixes Space Ace $FA00 boot stub), use register-based TOM resolution (HDB1/HDE/VDB/VDE), fix JERRY_TRACE_DEBUG and GPU trace guards for audio regression. Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent d4864a2 commit 9e6af37

11 files changed

Lines changed: 1034 additions & 1091 deletions

File tree

libretro.c

Lines changed: 110 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#define HLE_DIAG 1
12
#include <stdio.h>
23
#include <stdlib.h>
34
#include <string.h>
@@ -31,6 +32,7 @@ int64_t rfread(void* buffer, size_t elem_size, size_t elem_count, RFILE* stream)
3132
#include "tom.h"
3233
#include "state.h"
3334
#include "m68000/m68kinterface.h"
35+
#include "log.h"
3436

3537
#define SAMPLERATE 48000
3638
#define BUFPAL 1920
@@ -67,6 +69,7 @@ static retro_input_poll_t input_poll_cb;
6769
static retro_input_state_t input_state_cb;
6870
static retro_environment_t environ_cb;
6971
retro_audio_sample_batch_t audio_batch_cb;
72+
retro_log_printf_t vj_log_cb = NULL;
7073

7174
static bool libretro_supports_bitmasks = false;
7275
static bool save_data_needs_unpack = false;
@@ -313,6 +316,12 @@ void retro_set_environment(retro_environment_t cb)
313316
bool option_categories = false;
314317
environ_cb = cb;
315318

319+
{
320+
struct retro_log_callback log_iface;
321+
if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log_iface))
322+
vj_log_cb = log_iface.log;
323+
}
324+
316325
libretro_set_core_options(environ_cb, &option_categories);
317326
update_display_cb.callback = update_option_visibility;
318327
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK, &update_display_cb);
@@ -819,7 +828,7 @@ void retro_get_system_info(struct retro_system_info *info)
819828
#ifndef GIT_VERSION
820829
#define GIT_VERSION ""
821830
#endif
822-
info->library_version = "v2.1.0" GIT_VERSION;
831+
info->library_version = "v2.2.0" GIT_VERSION;
823832
info->need_fullpath = true;
824833
info->valid_extensions = "j64|jag|cue|cdi|iso";
825834
}
@@ -1128,16 +1137,16 @@ bool retro_load_game(const struct retro_game_info *info)
11281137

11291138
if (vjs.cdBootMode == CDBOOT_HLE)
11301139
{
1131-
fprintf(stderr, "[CD] Boot mode: HLE (skipping BIOS search)\n");
1140+
LOG_INF("[CD] Boot mode: HLE (skipping BIOS search)\n");
11321141
}
11331142
else
11341143
{
11351144
if (!load_external_cd_bios())
11361145
{
11371146
if (vjs.cdBootMode == CDBOOT_BIOS)
1138-
fprintf(stderr, "[CD] WARNING: Boot mode is BIOS but no external BIOS found\n");
1147+
LOG_WRN("[CD] WARNING: Boot mode is BIOS but no external BIOS found\n");
11391148
else
1140-
fprintf(stderr, "[CD] No external BIOS found — will use HLE boot path\n");
1149+
LOG_WRN("[CD] No external BIOS found — will use HLE boot path\n");
11411150
}
11421151
}
11431152
}
@@ -1174,9 +1183,9 @@ bool retro_load_game(const struct retro_game_info *info)
11741183
JaguarSetScreenPitch(videoWidth);
11751184
JaguarSetScreenBuffer(videoBuffer);
11761185

1177-
/* Init video */
1178-
for (i = 0; i < videoWidth * videoHeight; ++i)
1179-
videoBuffer[i] = 0xFF00FFFF;
1186+
/* Init video to opaque black */
1187+
for (i = 0; i < 1024 * 512; ++i)
1188+
videoBuffer[i] = 0xFF000000;
11801189

11811190
if (jaguar_cd_mode && cd_bios_loaded_externally)
11821191
{
@@ -1195,7 +1204,7 @@ bool retro_load_game(const struct retro_game_info *info)
11951204
* forever in emulation (the GPU security code at $F032EC never
11961205
* converges). Skip the GPU wait by clearing bit 0. */
11971206
jagMemSpace[0x80040B] &= 0xFE;
1198-
fprintf(stderr, "[CD-TRACE] Boot ROM wait bypass applied at $80040B (value now $%02X)\n",
1207+
LOG_DBG("[CD-TRACE] Boot ROM wait bypass applied at $80040B (value now $%02X)\n",
11991208
jagMemSpace[0x80040B]);
12001209

12011210
JaguarReset();
@@ -1248,7 +1257,7 @@ bool retro_load_game(const struct retro_game_info *info)
12481257
{
12491258
if (!JaguarCDHLEBoot())
12501259
{
1251-
fprintf(stderr, "[CD-HLE] HLE boot failed — falling back to diagnostic screen\n");
1260+
LOG_ERR("[CD-HLE] HLE boot failed — falling back to diagnostic screen\n");
12521261
}
12531262
}
12541263

@@ -1395,6 +1404,98 @@ void retro_run(void)
13951404
JaguarExecuteNew();
13961405
SoundCallback(NULL, sampleBuffer, vjs.hardwareTypeNTSC==1?BUFNTSC:BUFPAL);
13971406

1407+
#ifdef HLE_DIAG
1408+
{
1409+
static uint32_t hle_frame = 0;
1410+
hle_frame++;
1411+
if (JaguarCDHLEActive() &&
1412+
(hle_frame == 50 || hle_frame == 100 || hle_frame == 200 ||
1413+
hle_frame == 300 || hle_frame == 400 || hle_frame == 500 ||
1414+
hle_frame == 600 || hle_frame == 800 || hle_frame == 1000 ||
1415+
hle_frame == 2000 || hle_frame == 3000))
1416+
{
1417+
uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC);
1418+
uint16_t vmode = TOMReadWord(0xF00028, 0);
1419+
uint16_t vdb = TOMReadWord(0xF00046, 0);
1420+
uint16_t vde = TOMReadWord(0xF00048, 0);
1421+
uint16_t hdb1 = TOMReadWord(0xF00038, 0);
1422+
uint16_t hde = TOMReadWord(0xF0003C, 0);
1423+
uint16_t bg = TOMReadWord(0xF00058, 0);
1424+
uint32_t olp = ((uint32_t)TOMReadWord(0xF00020, 0) << 16)
1425+
| (uint32_t)TOMReadWord(0xF00022, 0);
1426+
uint32_t nzpix = 0;
1427+
if (videoBuffer)
1428+
for (uint32_t i = 0; i < (uint32_t)(game_width * game_height); i++)
1429+
if (videoBuffer[i] != 0) nzpix++;
1430+
1431+
LOG_DBG("[HLE-DIAG] frame=%u PC=$%06X tomW=%u tomH=%u gameW=%d gameH=%d\n",
1432+
hle_frame, pc, tomWidth, tomHeight, game_width, game_height);
1433+
LOG_DBG("[HLE-DIAG] VMODE=$%04X VDB=$%04X VDE=$%04X HDB1=$%04X HDE=$%04X BG=$%04X OLP=$%08X\n",
1434+
vmode, vdb, vde, hdb1, hde, bg, olp);
1435+
LOG_DBG("[HLE-DIAG] non-zero pixels=%u/%u\n",
1436+
nzpix, (uint32_t)(game_width * game_height));
1437+
/* Sample a few pixel values */
1438+
if (videoBuffer && game_width > 0 && game_height > 0)
1439+
{
1440+
int cy = game_height / 2, cx = game_width / 2;
1441+
LOG_DBG("[HLE-DIAG] pixel[0,0]=$%08X pixel[%d,%d]=$%08X pixel[last]=$%08X\n",
1442+
videoBuffer[0], cx, cy, videoBuffer[cy * game_width + cx],
1443+
videoBuffer[game_width * game_height - 1]);
1444+
}
1445+
/* Dump PPM directly from videoBuffer at specific frames */
1446+
if ((hle_frame == 50 || hle_frame == 100 || hle_frame == 200 ||
1447+
hle_frame == 300 || hle_frame == 400 || hle_frame == 500 ||
1448+
hle_frame == 600 || hle_frame == 800 || hle_frame == 1000 ||
1449+
hle_frame == 2000 || hle_frame == 3000) &&
1450+
videoBuffer && game_width > 0 && game_height > 0)
1451+
{
1452+
char ppm_path[64];
1453+
snprintf(ppm_path, sizeof(ppm_path), "/tmp/hle_f%04u.ppm", hle_frame);
1454+
FILE *pf = fopen(ppm_path, "wb");
1455+
if (pf)
1456+
{
1457+
int w = game_width, h = game_height;
1458+
fprintf(pf, "P6\n%d %d\n255\n", w, h);
1459+
for (int y = 0; y < h; y++)
1460+
for (int x = 0; x < w; x++)
1461+
{
1462+
uint32_t px = videoBuffer[y * w + x]; /* XRGB8888 */
1463+
uint8_t rgb[3] = {
1464+
(px >> 16) & 0xFF, /* R */
1465+
(px >> 8) & 0xFF, /* G */
1466+
px & 0xFF /* B */
1467+
};
1468+
fwrite(rgb, 1, 3, pf);
1469+
}
1470+
fclose(pf);
1471+
LOG_DBG("[HLE-DIAG] Saved direct PPM: %s\n", ppm_path);
1472+
}
1473+
}
1474+
LOG_DBG("[HLE-DIAG] D0=$%08X D1=$%08X A0=$%08X A7=$%08X SR=$%04X\n",
1475+
m68k_get_reg(NULL, M68K_REG_D0),
1476+
m68k_get_reg(NULL, M68K_REG_D1),
1477+
m68k_get_reg(NULL, M68K_REG_A0),
1478+
m68k_get_reg(NULL, M68K_REG_A7),
1479+
m68k_get_reg(NULL, M68K_REG_SR));
1480+
/* OLP target: dump first 16 bytes of the Object Processor list */
1481+
if (olp >= 0x4000 && olp < 0x200000 - 16)
1482+
{
1483+
extern uint8_t * jaguarMainRAM;
1484+
LOG_DBG("[HLE-DIAG] OP list @$%06X: %02X%02X%02X%02X %02X%02X%02X%02X "
1485+
"%02X%02X%02X%02X %02X%02X%02X%02X\n", olp,
1486+
jaguarMainRAM[olp+0], jaguarMainRAM[olp+1],
1487+
jaguarMainRAM[olp+2], jaguarMainRAM[olp+3],
1488+
jaguarMainRAM[olp+4], jaguarMainRAM[olp+5],
1489+
jaguarMainRAM[olp+6], jaguarMainRAM[olp+7],
1490+
jaguarMainRAM[olp+8], jaguarMainRAM[olp+9],
1491+
jaguarMainRAM[olp+10], jaguarMainRAM[olp+11],
1492+
jaguarMainRAM[olp+12], jaguarMainRAM[olp+13],
1493+
jaguarMainRAM[olp+14], jaguarMainRAM[olp+15]);
1494+
}
1495+
}
1496+
}
1497+
#endif
1498+
13981499
// Resolution changed
13991500
if ((tomWidth != videoWidth || tomHeight != videoHeight) && tomWidth > 0 && tomHeight > 0)
14001501
{

src/cdintf.c

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@
1818
#include <streams/file_stream_transforms.h>
1919
#include "cdintf.h"
2020
#include "jaguar.h"
21-
22-
/* file_stream_transforms.h does `#define fprintf rfprintf`, which silently
23-
* eats fprintf(stderr, ...) calls. Restore real stdio fprintf for debug logs. */
24-
#undef fprintf
21+
#include "log.h"
2522

2623
// CDI (DiscJuggler) format support
2724
static RFILE *cdi_file = NULL;
@@ -530,6 +527,21 @@ static bool ParseCueSheet(const char *cuePath)
530527
}
531528
}
532529

530+
{
531+
int i;
532+
for (i = 0; i < (int)disc.numTracks; i++)
533+
{
534+
if (disc.tracks[i].session >= 2 || i >= (int)disc.numTracks - 5)
535+
LOG_DBG("[CD-LAYOUT] track %2u sess=%u startLBA=%u dataLBA=%u "
536+
"len=%u MSF=%02u:%02u:%02u BIN=%s\n",
537+
disc.tracks[i].number, disc.tracks[i].session,
538+
disc.tracks[i].startLBA, disc.tracks[i].dataLBA,
539+
disc.tracks[i].lengthLBA,
540+
disc.tracks[i].startM, disc.tracks[i].startS, disc.tracks[i].startF,
541+
disc.tracks[i].binFilePath[0] ? "yes" : "no");
542+
}
543+
}
544+
533545
disc.loaded = true;
534546
return true;
535547
}
@@ -932,15 +944,6 @@ bool CDIntfReadBlock(uint32_t sector, uint8_t *buffer)
932944
struct CDIntfTrack *track = NULL;
933945
uint32_t sectorSize;
934946

935-
{
936-
static uint32_t entryCount = 0;
937-
if (entryCount < 20 || (sector >= 139600 && sector < 140000))
938-
fprintf(stderr, "[CD-RB-ENTRY] sector=%u loaded=%d numSessions=%u s2Leadout=%u (call #%u)\n",
939-
sector, disc.loaded, disc.numSessions,
940-
disc.numSessions >= 2 ? disc.sessions[1].leadOutLBA : 0,
941-
++entryCount);
942-
}
943-
944947
if (!disc.loaded || !buffer)
945948
return false;
946949

@@ -955,7 +958,7 @@ bool CDIntfReadBlock(uint32_t sector, uint8_t *buffer)
955958
{
956959
static uint32_t authHits = 0;
957960
if (authHits < 5)
958-
fprintf(stderr, "[CD-AUTH-REDIRECT] sector=%u served from track-30 BIN (hit #%u)\n", sector, ++authHits);
961+
LOG_INF("[CD-AUTH-REDIRECT] sector=%u served from track-30 BIN (hit #%u)\n", sector, ++authHits);
959962
else
960963
authHits++;
961964
lastReadVirtualPregap = false;
@@ -1201,14 +1204,14 @@ bool CDIntfExtractBootStub(uint8_t *outBuf, uint32_t outBufSize,
12011204
uint32_t firstS2Idx = 0;
12021205
bool foundS2 = false;
12031206
RFILE *trackFile;
1204-
uint8_t raw[2352 * 12];
1205-
uint8_t swapped[sizeof(raw)];
1207+
static uint8_t raw[2352 * 32];
1208+
static uint8_t swapped[sizeof(raw)];
12061209
int64_t bytesRead;
12071210
uint32_t loadAddr, length;
12081211

12091212
if (!disc.loaded || disc.numSessions < 2)
12101213
{
1211-
fprintf(stderr, "[CD-BOOTSTUB] Early exit: loaded=%d numSessions=%u\n",
1214+
LOG_WRN("[CD-BOOTSTUB] Early exit: loaded=%d numSessions=%u\n",
12121215
disc.loaded, disc.numSessions);
12131216
return false;
12141217
}
@@ -1224,28 +1227,28 @@ bool CDIntfExtractBootStub(uint8_t *outBuf, uint32_t outBufSize,
12241227
}
12251228
if (!foundS2 || !disc.tracks[firstS2Idx].binFilePath[0])
12261229
{
1227-
fprintf(stderr, "[CD-BOOTSTUB] No session-2 track found (foundS2=%d, pathEmpty=%d)\n",
1230+
LOG_WRN("[CD-BOOTSTUB] No session-2 track found (foundS2=%d, pathEmpty=%d)\n",
12281231
foundS2, foundS2 ? !disc.tracks[firstS2Idx].binFilePath[0] : -1);
12291232
return false;
12301233
}
12311234

1232-
fprintf(stderr, "[CD-BOOTSTUB] Opening track %u BIN: %s\n",
1235+
LOG_INF("[CD-BOOTSTUB] Opening track %u BIN: %s\n",
12331236
disc.tracks[firstS2Idx].number, disc.tracks[firstS2Idx].binFilePath);
12341237
trackFile = rfopen(disc.tracks[firstS2Idx].binFilePath, "rb");
12351238
if (!trackFile)
12361239
{
1237-
fprintf(stderr, "[CD-BOOTSTUB] rfopen failed for %s\n",
1240+
LOG_ERR("[CD-BOOTSTUB] rfopen failed for %s\n",
12381241
disc.tracks[firstS2Idx].binFilePath);
12391242
return false;
12401243
}
12411244

12421245
rfseek(trackFile, 0, SEEK_SET);
12431246
bytesRead = rfread(raw, 1, sizeof(raw), trackFile);
12441247
rfclose(trackFile);
1245-
fprintf(stderr, "[CD-BOOTSTUB] Read %lld bytes from track BIN\n", (long long)bytesRead);
1248+
LOG_INF("[CD-BOOTSTUB] Read %lld bytes from track BIN\n", (long long)bytesRead);
12461249
if (bytesRead < 0x6A + 4)
12471250
{
1248-
fprintf(stderr, "[CD-BOOTSTUB] Too few bytes read (%lld < %d)\n",
1251+
LOG_ERR("[CD-BOOTSTUB] Too few bytes read (%lld < %d)\n",
12491252
(long long)bytesRead, 0x6A + 4);
12501253
return false;
12511254
}
@@ -1257,20 +1260,19 @@ bool CDIntfExtractBootStub(uint8_t *outBuf, uint32_t outBufSize,
12571260
swapped[i + 1] = raw[i];
12581261
}
12591262

1260-
fprintf(stderr, "[CD-BOOTSTUB] Raw bytes 0x40-0x6F (pre-swap): ");
1263+
LOG_DBG("[CD-BOOTSTUB] Raw bytes 0x40-0x6F (pre-swap): ");
12611264
for (i = 0x40; i < 0x70 && i < (uint32_t)bytesRead; i++)
1262-
fprintf(stderr, "%02X ", raw[i]);
1263-
fprintf(stderr, "\n");
1264-
fprintf(stderr, "[CD-BOOTSTUB] Swapped bytes 0x40-0x6F: ");
1265+
LOG_DBG("%02X ", raw[i]);
1266+
LOG_DBG("\n");
1267+
LOG_DBG("[CD-BOOTSTUB] Swapped bytes 0x40-0x6F: ");
12651268
for (i = 0x40; i < 0x70 && i < (uint32_t)bytesRead; i++)
1266-
fprintf(stderr, "%02X ", swapped[i]);
1267-
fprintf(stderr, "\n");
1268-
fprintf(stderr, "[CD-BOOTSTUB] Swapped as text: '%.32s'\n", swapped + 0x42);
1269+
LOG_DBG("%02X ", swapped[i]);
1270+
LOG_DBG("\n");
1271+
LOG_DBG("[CD-BOOTSTUB] Swapped as text: '%.32s'\n", swapped + 0x42);
12691272

12701273
if (memcmp(swapped + 0x42, MAGIC, sizeof(MAGIC)) != 0)
12711274
{
1272-
fprintf(stderr,
1273-
"[CD-BOOTSTUB] Magic mismatch at +0x42 of session-2 track BIN\n");
1275+
LOG_ERR("[CD-BOOTSTUB] Magic mismatch at +0x42 of session-2 track BIN\n");
12741276
return false;
12751277
}
12761278

@@ -1282,8 +1284,7 @@ bool CDIntfExtractBootStub(uint8_t *outBuf, uint32_t outBufSize,
12821284
if (length == 0 || length > outBufSize
12831285
|| (uint64_t)0x6A + length > (uint64_t)bytesRead)
12841286
{
1285-
fprintf(stderr,
1286-
"[CD-BOOTSTUB] Bad length $%X (loadAddr=$%06X, bufSize=%u, available=%lld)\n",
1287+
LOG_ERR("[CD-BOOTSTUB] Bad length $%X (loadAddr=$%06X, bufSize=%u, available=%lld)\n",
12871288
length, loadAddr, outBufSize, (long long)bytesRead - 0x6A);
12881289
return false;
12891290
}
@@ -1292,8 +1293,7 @@ bool CDIntfExtractBootStub(uint8_t *outBuf, uint32_t outBufSize,
12921293
*outLoadAddr = loadAddr;
12931294
*outLength = length;
12941295

1295-
fprintf(stderr,
1296-
"[CD-BOOTSTUB] Extracted $%X bytes for load addr $%06X (track %u BIN: %s)\n",
1296+
LOG_INF("[CD-BOOTSTUB] Extracted $%X bytes for load addr $%06X (track %u BIN: %s)\n",
12971297
length, loadAddr,
12981298
disc.tracks[firstS2Idx].number, disc.tracks[firstS2Idx].binFilePath);
12991299
return true;
@@ -1323,7 +1323,7 @@ uint32_t CDIntfGetSession2GameDataLBA(void)
13231323
{
13241324
if (disc.tracks[i].session >= 2)
13251325
{
1326-
fprintf(stderr, "[CD-S2TRACK] track %u: startLBA=%u dataLBA=%u len=%u sess=%u\n",
1326+
LOG_DBG("[CD-S2TRACK] track %u: startLBA=%u dataLBA=%u len=%u sess=%u\n",
13271327
disc.tracks[i].number, disc.tracks[i].startLBA,
13281328
disc.tracks[i].dataLBA, disc.tracks[i].lengthLBA,
13291329
disc.tracks[i].session);
@@ -1340,7 +1340,7 @@ uint32_t CDIntfGetSession2GameDataLBA(void)
13401340
uint32_t lba = disc.tracks[bestIdx].dataLBA
13411341
? disc.tracks[bestIdx].dataLBA
13421342
: disc.tracks[bestIdx].startLBA;
1343-
fprintf(stderr, "[CD-S2TRACK] Selected largest track %u (len=%u) dataLBA=%u\n",
1343+
LOG_INF("[CD-S2TRACK] Selected largest track %u (len=%u) dataLBA=%u\n",
13441344
disc.tracks[bestIdx].number, bestLen, lba);
13451345
return lba;
13461346
}

0 commit comments

Comments
 (0)