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;
6769static retro_input_state_t input_state_cb ;
6870static retro_environment_t environ_cb ;
6971retro_audio_sample_batch_t audio_batch_cb ;
72+ retro_log_printf_t vj_log_cb = NULL ;
7073
7174static bool libretro_supports_bitmasks = false;
7275static 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 {
0 commit comments