Example #1
0
bool CDIF_ReadRawSector(uint8 *buf, uint32 lba)
{
 bool found = FALSE;

 // This shouldn't happen, the emulated-system-specific CDROM emulation code should make sure the emulated program doesn't try
 // to read past the last "real" sector of the disc.
 if(lba >= toc.tracks[100].lba)
 {
  printf("Attempt to read LBA %d, >= LBA %d\n", lba, toc.tracks[100].lba);
  return(FALSE);
 }

 ReadThreadQueue->Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba, 0, 0, 0, NULL));

 do
 {
  MDFND_LockMutex(SBMutex);

  for(int i = 0; i < SBSize; i++)
  {
   if(SectorBuffers[i].valid && SectorBuffers[i].lba == lba)
   {
    memcpy(buf, SectorBuffers[i].data, 2352 + 96);
    found = TRUE;
   }
  }

  MDFND_UnlockMutex(SBMutex);

  if(!found)
   MDFND_Sleep(1);
 } while(!found);

 return(TRUE);
}
void CDIF_MT::HintReadSector(uint32 lba)
{
   if(UnrecoverableError)
      return;

   ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba));
}
Example #3
0
bool CDIF_Close(void)
{
 ReadThreadQueue->Write(CDIF_Message(CDIF_MSG_DIEDIEDIE, 0, 0, 0, 0, NULL));
 MDFND_WaitThread(CDReadThread, NULL);

 if(SectorBuffers)
 {
  free(SectorBuffers);
  SectorBuffers = NULL;
 }

 if(ReadThreadQueue)
 {
  delete ReadThreadQueue;
  ReadThreadQueue = NULL;
 }

 if(EmuThreadQueue)
 {
  delete EmuThreadQueue;
  EmuThreadQueue = NULL;
 }

 if(SBMutex)
 {
  MDFND_DestroyMutex(SBMutex);
  SBMutex = NULL;
 }

 return(1);
}
CDIF_MT::~CDIF_MT()
{
   bool thread_deaded_failed = false;

   try
   {
      ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_DIEDIEDIE));
   }
   catch(std::exception &e)
   {
      log_cb(RETRO_LOG_ERROR, "%s.\n", e.what());
      thread_deaded_failed = true;
   }

   if(!thread_deaded_failed)
      sthread_join((sthread_t*)CDReadThread);

   if(SBMutex)
   {
      slock_free((slock_t*)SBMutex);
      SBMutex = NULL;
   }

   if(disc_cdaccess)
   {
      delete disc_cdaccess;
      disc_cdaccess = NULL;
   }
}
bool CDIF_MT::ReadRawSector(uint8 *buf, uint32 lba)
{
   bool found = FALSE;
   bool error_condition = false;

   if(UnrecoverableError)
   {
      memset(buf, 0, 2352 + 96);
      return(false);
   }

   // This shouldn't happen, the emulated-system-specific CDROM emulation code should make sure the emulated program doesn't try
   // to read past the last "real" sector of the disc.
   if(lba >= disc_toc.tracks[100].lba)
   {
      printf("Attempt to read LBA %d, >= LBA %d\n", lba, disc_toc.tracks[100].lba);
      return(FALSE);
   }

   ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba));

   slock_lock((slock_t*)SBMutex);

   do
   {
      int i;
      for(i = 0; i < SBSize; i++)
      {
         if(SectorBuffers[i].valid && SectorBuffers[i].lba == lba)
         {
            error_condition = SectorBuffers[i].error;
            memcpy(buf, SectorBuffers[i].data, 2352 + 96);
            found = TRUE;
         }
      }

      if(!found)
         scond_wait((scond_t*)SBCond, (slock_t*)SBMutex);
   } while(!found);

   slock_unlock((slock_t*)SBMutex);

   return(!error_condition);
}
bool CDIF_MT::Eject(bool eject_status)
{
   if(UnrecoverableError)
      return(false);

   try
   {
      CDIF_Message msg;

      ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_EJECT, eject_status));
      EmuThreadQueue.Read(&msg);
   }
   catch(std::exception &e)
   {
      log_cb(RETRO_LOG_ERROR, "Error on eject/insert attempt: %s\n", e.what());
      return(false);
   }

   return(true);
}
Example #7
0
bool CDIF_HintReadSector(uint32 lba)
{
 ReadThreadQueue->Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba, 0, 0, 0, NULL));

 return(1);
}
Example #8
0
static int ReadThreadStart(void *arg)
{
 char *device_name = (char *)arg;
 bool Running = TRUE;

 MDFN_printf(_("Loading %s...\n\n"), device_name ? device_name : _("PHYSICAL CDROM DISC"));
 MDFN_indent(1);

 if(!(p_cdrfile = cdrfile_open(device_name)))
 {
  MDFN_indent(-1);
  EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, FALSE, 0, 0, 0, NULL));
  return(0);
 }

 if(!cdrfile_read_toc(p_cdrfile, &toc))
 {
  puts("Error reading TOC");
  MDFN_indent(-1);
  EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, FALSE, 0, 0, 0, NULL));
  return(0);
 }

 if(toc.first_track < 1 || toc.last_track > 99 || toc.first_track > toc.last_track)
 {
  puts("First/Last track numbers bad");
  MDFN_indent(-1);
  EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, FALSE, 0, 0, 0, NULL));
  return(0);
 }

 for(int32 track = toc.first_track; track <= toc.last_track; track++)
 {
  MDFN_printf(_("Track %2d, LBA: %6d  %s\n"), track, toc.tracks[track].lba, (toc.tracks[track].control & 0x4) ? "DATA" : "AUDIO");
 }

 MDFN_printf("Leadout: %6d\n", toc.tracks[100].lba);
 MDFN_indent(-1);

 EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, TRUE, 0, 0, 0, NULL));

 while(Running)
 {
  CDIF_Message msg;

  // Only do a blocking-wait for a message if we don't have any sectors to read-ahead.
  // MDFN_DispMessage("%d %d %d\n", last_read_lba, ra_lba, ra_count);
  if(ReadThreadQueue->Read(&msg, ra_count ? FALSE : TRUE))
  {
   switch(msg.message)
   {
    case CDIF_MSG_DIEDIEDIE: Running = FALSE;
 		 	 break;

    case CDIF_MSG_READ_SECTOR:
			 {
                          static const int max_ra = 16;
			  static const int initial_ra = 1;
			  static const int speedmult_ra = 2;
			  uint32 new_lba = msg.args[0];

			  assert((unsigned int)max_ra < (SBSize / 4));

			  if(new_lba == (last_read_lba + 1))
			  {
			   int how_far_ahead = ra_lba - new_lba;

			   assert(how_far_ahead >= 0);

			   if(how_far_ahead <= max_ra)
			    ra_count = std::min(speedmult_ra, 1 + max_ra - how_far_ahead);
			   else
			    ra_count++;
			  }
			  else
			  {
                           ra_lba = new_lba;
			   ra_count = initial_ra;
			  }
			  last_read_lba = new_lba;
			 }
			 break;
   }
  }

  // Don't read >= the "end" of the disc, silly snake.  Slither.
  if(ra_count && ra_lba == toc.tracks[100].lba)
  {
   ra_count = 0;
   //printf("Ephemeral scarabs: %d!\n", ra_lba);
  }

  if(ra_count)
  {
   uint8 tmpbuf[2352 + 96];

   if(!cdrfile_read_raw_sector(p_cdrfile, tmpbuf, ra_lba))
   {
    printf("Sector %d read error!  Abandon ship!", ra_lba);
    memset(tmpbuf, 0, sizeof(tmpbuf));
   }
   MDFND_LockMutex(SBMutex);

   SectorBuffers[SBWritePos].lba = ra_lba;
   memcpy(SectorBuffers[SBWritePos].data, tmpbuf, 2352 + 96);
   SectorBuffers[SBWritePos].valid = TRUE;
   SBWritePos = (SBWritePos + 1) % SBSize;

   MDFND_UnlockMutex(SBMutex);

   ra_lba++;
   ra_count--;
  }
 }

 if(p_cdrfile)
 {
  cdrfile_destroy(p_cdrfile);
  p_cdrfile = NULL;
 }

 return(1);
}
int CDIF_MT::ReadThreadStart()
{
   bool Running = TRUE;

   DiscEjected = true;
   SBWritePos = 0;
   ra_lba = 0;
   ra_count = 0;
   last_read_lba = ~0U;

   try
   {
      RT_EjectDisc(false, true);
   }
   catch(std::exception &e)
   {
      EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_FATAL_ERROR, std::string(e.what())));
      return(0);
   }

   EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_DONE));

   while(Running)
   {
      CDIF_Message msg;

      // Only do a blocking-wait for a message if we don't have any sectors to read-ahead.
      // MDFN_DispMessage("%d %d %d\n", last_read_lba, ra_lba, ra_count);
      if(ReadThreadQueue.Read(&msg, ra_count ? FALSE : TRUE))
      {
         switch(msg.message)
         {
            case CDIF_MSG_DIEDIEDIE:
               Running = FALSE;
               break;

            case CDIF_MSG_EJECT:
               try
               {
                  RT_EjectDisc(msg.args[0]);
                  EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_DONE));
               }
               catch(std::exception &e)
               {
                  EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_FATAL_ERROR, std::string(e.what())));
               }
               break;

            case CDIF_MSG_READ_SECTOR:
               {
                  static const int       max_ra = 16;
                  static const int   initial_ra = 1;
                  static const int speedmult_ra = 2;
                  uint32_t              new_lba = msg.args[0];

                  assert((unsigned int)max_ra < (SBSize / 4));

                  if(last_read_lba != ~0U && new_lba == (last_read_lba + 1))
                  {
                     int how_far_ahead = ra_lba - new_lba;

                     if(how_far_ahead <= max_ra)
                        ra_count = MIN(speedmult_ra, 1 + max_ra - how_far_ahead);
                     else
                        ra_count++;
                  }
                  else if(new_lba != last_read_lba)
                  {
                     ra_lba = new_lba;
                     ra_count = initial_ra;
                  }

                  last_read_lba = new_lba;
               }
               break;
         }
      }

      // Don't read >= the "end" of the disc, silly snake.  Slither.
      if(ra_count && ra_lba == disc_toc.tracks[100].lba)
      {
         ra_count = 0;
         //printf("Ephemeral scarabs: %d!\n", ra_lba);
      }

      if(ra_count)
      {
         uint8_t tmpbuf[2352 + 96];
         bool error_condition = false;

         try
         {
            disc_cdaccess->Read_Raw_Sector(tmpbuf, ra_lba);
         }
         catch(std::exception &e)
         {
            log_cb(RETRO_LOG_ERROR, "Sector %u read error: %s\n", ra_lba, e.what());
            memset(tmpbuf, 0, sizeof(tmpbuf));
            error_condition = true;
         }

         slock_lock((slock_t*)SBMutex);

         SectorBuffers[SBWritePos].lba = ra_lba;
         memcpy(SectorBuffers[SBWritePos].data, tmpbuf, 2352 + 96);
         SectorBuffers[SBWritePos].valid = TRUE;
         SectorBuffers[SBWritePos].error = error_condition;
         SBWritePos = (SBWritePos + 1) % SBSize;

         scond_signal((scond_t*)SBCond);
         slock_unlock((slock_t*)SBMutex);

         ra_lba++;
         ra_count--;
      }
   }

   return(1);
}