@@ -30,7 +30,22 @@ uint32_t *videoBuffer = NULL;
3030int game_width = 0 ;
3131int game_height = 0 ;
3232
33- extern uint16_t eeprom_ram [];
33+ extern uint16_t eeprom_ram [64 ];
34+ extern uint8_t mtMem [0x20000 ];
35+ extern uint32_t jaguarMainROMCRC32 ;
36+ extern void (* eeprom_dirty_cb )(void );
37+
38+ /* Save buffer for RETRO_MEMORY_SAVE_RAM.
39+ * Regular carts: 128 bytes (64 x 16-bit EEPROM words, big-endian packed).
40+ * Memory Track cart (CRC 0xFDF37F47): mtMem is used directly (128K).
41+ *
42+ * The save buffer is kept in sync on every EEPROM write via eeprom_dirty_cb,
43+ * so frontends that cache the pointer always see current data. */
44+ #define EEPROM_SAVE_SIZE 128 /* 64 x 16-bit words, big-endian */
45+ #define MT_SAVE_SIZE 0x20000 /* 128K Memory Track */
46+ static uint8_t eeprom_save_buf [EEPROM_SAVE_SIZE ];
47+ static void eeprom_pack_save_buf (void );
48+ static void eeprom_unpack_save_buf (void );
3449
3550static retro_video_refresh_t video_cb ;
3651static retro_input_poll_t input_poll_cb ;
@@ -39,6 +54,7 @@ static retro_environment_t environ_cb;
3954retro_audio_sample_batch_t audio_batch_cb ;
4055
4156static bool libretro_supports_bitmasks = false;
57+ static bool save_data_needs_unpack = false;
4258
4359void retro_set_video_refresh (retro_video_refresh_t cb ) { video_cb = cb ; }
4460void retro_set_audio_sample (retro_audio_sample_t cb ) { (void )cb ; }
@@ -719,26 +735,6 @@ static void update_input(void)
719735 }
720736}
721737
722- static void extract_basename (char * buf , const char * path , size_t size )
723- {
724- char * ext = NULL ;
725- const char * base = strrchr (path , '/' );
726- if (!base )
727- base = strrchr (path , '\\' );
728- if (!base )
729- base = path ;
730-
731- if (* base == '\\' || * base == '/' )
732- base ++ ;
733-
734- strncpy (buf , base , size - 1 );
735- buf [size - 1 ] = '\0' ;
736-
737- ext = strrchr (buf , '.' );
738- if (ext )
739- * ext = '\0' ;
740- }
741-
742738/************************************
743739 * libretro implementation
744740 ************************************/
@@ -897,9 +893,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code)
897893
898894bool retro_load_game (const struct retro_game_info * info )
899895{
900- char slash ;
901896 unsigned i ;
902- const char * save_dir = NULL ;
903897 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888 ;
904898
905899 struct retro_input_descriptor desc [] = {
@@ -981,31 +975,8 @@ bool retro_load_game(const struct retro_game_info *info)
981975
982976 check_variables ();
983977
984- // Get eeprom path info
985- // > Handle Windows nonsense...
986- #if defined(_WIN32 )
987- slash = '\\' ;
988- #else
989- slash = '/' ;
990- #endif
991- // > Get save path
992- vjs .EEPROMPath [0 ] = '\0' ;
993- if (environ_cb (RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY , & save_dir ) && save_dir )
994- {
995- if (strlen (save_dir ) > 0 )
996- {
997- sprintf (vjs .EEPROMPath , "%s%c" , save_dir , slash );
998- }
999- }
1000- // > Get ROM name
1001- if (info -> path != NULL )
1002- {
1003- extract_basename (vjs .romName , info -> path , sizeof (vjs .romName ));
1004- }
1005- else
1006- {
1007- vjs .romName [0 ] = '\0' ;
1008- }
978+ /* Register EEPROM dirty callback so the save buffer stays in sync */
979+ eeprom_dirty_cb = eeprom_pack_save_buf ;
1009980
1010981 JaguarInit (); // set up hardware
1011982 memcpy (jagMemSpace + 0xE00000 ,
@@ -1023,6 +994,11 @@ bool retro_load_game(const struct retro_game_info *info)
1023994 JaguarLoadFile ((uint8_t * )info -> data , info -> size );
1024995 JaguarReset ();
1025996
997+ /* The frontend will load .srm data into our save buffer (returned by
998+ * retro_get_memory_data) after this function returns but before the
999+ * first retro_run(). We unpack it on the first frame. */
1000+ save_data_needs_unpack = true;
1001+
10261002 return true;
10271003}
10281004
@@ -1055,22 +1031,55 @@ unsigned retro_api_version(void)
10551031 return RETRO_API_VERSION ;
10561032}
10571033
1034+ /* Pack eeprom_ram[] into the save buffer (big-endian byte order).
1035+ * Called on every EEPROM write via eeprom_dirty_cb so the buffer
1036+ * is always up-to-date for frontends that cache the pointer. */
1037+ static void eeprom_pack_save_buf (void )
1038+ {
1039+ unsigned i ;
1040+ for (i = 0 ; i < 64 ; i ++ )
1041+ {
1042+ eeprom_save_buf [(i * 2 ) + 0 ] = eeprom_ram [i ] >> 8 ;
1043+ eeprom_save_buf [(i * 2 ) + 1 ] = eeprom_ram [i ] & 0xFF ;
1044+ }
1045+ }
1046+
1047+ /* Unpack the save buffer back into eeprom_ram[].
1048+ * Called once after the frontend loads .srm data. */
1049+ static void eeprom_unpack_save_buf (void )
1050+ {
1051+ unsigned i ;
1052+ for (i = 0 ; i < 64 ; i ++ )
1053+ eeprom_ram [i ] = ((uint16_t )eeprom_save_buf [(i * 2 ) + 0 ] << 8 )
1054+ | eeprom_save_buf [(i * 2 ) + 1 ];
1055+ }
1056+
10581057void * retro_get_memory_data (unsigned type )
10591058{
1060- if (type == RETRO_MEMORY_SYSTEM_RAM )
1059+ if (type == RETRO_MEMORY_SYSTEM_RAM )
10611060 return jaguarMainRAM ;
1062- else if (type == RETRO_MEMORY_SAVE_RAM )
1063- return eeprom_ram ;
1064- else return NULL ;
1061+ if (type == RETRO_MEMORY_SAVE_RAM )
1062+ {
1063+ /* Memory Track cart uses 128K NVRAM directly */
1064+ if (jaguarMainROMCRC32 == 0xFDF37F47 )
1065+ return mtMem ;
1066+ /* Regular carts: return the pre-packed save buffer */
1067+ return eeprom_save_buf ;
1068+ }
1069+ return NULL ;
10651070}
10661071
10671072size_t retro_get_memory_size (unsigned type )
10681073{
1069- if (type == RETRO_MEMORY_SYSTEM_RAM )
1074+ if (type == RETRO_MEMORY_SYSTEM_RAM )
10701075 return 0x200000 ;
1071- else if (type == RETRO_MEMORY_SAVE_RAM )
1072- return 128 ;
1073- else return 0 ;
1076+ if (type == RETRO_MEMORY_SAVE_RAM )
1077+ {
1078+ if (jaguarMainROMCRC32 == 0xFDF37F47 )
1079+ return MT_SAVE_SIZE ;
1080+ return EEPROM_SAVE_SIZE ;
1081+ }
1082+ return 0 ;
10741083}
10751084
10761085void retro_init (void )
@@ -1097,6 +1106,16 @@ void retro_run(void)
10971106{
10981107 bool updated = false;
10991108
1109+ /* On the first frame, unpack save data that the frontend loaded
1110+ * into our RETRO_MEMORY_SAVE_RAM buffer after retro_load_game(). */
1111+ if (save_data_needs_unpack )
1112+ {
1113+ save_data_needs_unpack = false;
1114+ if (jaguarMainROMCRC32 != 0xFDF37F47 )
1115+ eeprom_unpack_save_buf ();
1116+ /* Memory Track: mtMem was written directly, no unpack needed. */
1117+ }
1118+
11001119 if (environ_cb (RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE , & updated ) && updated )
11011120 check_variables ();
11021121
0 commit comments