mcd, revisit track handling in cdd
authorkub <derkub@gmail.com>
Fri, 19 Apr 2024 18:53:52 +0000 (20:53 +0200)
committerkub <derkub@gmail.com>
Fri, 19 Apr 2024 22:41:57 +0000 (00:41 +0200)
pico/cd/cdd.c

index 78fae75..9715c67 100644 (file)
@@ -196,67 +196,52 @@ static void cdd_change_track(int index, int lba)
   cdda_start_play(base, lba_offset, lb_len);
 }
 
-int cdd_context_save(uint8 *state)
-{
-  int bufferptr = 0;
-
-  save_param(&cdd.cycles, sizeof(cdd.cycles));
-  save_param(&cdd.latency, sizeof(cdd.latency));
-  save_param(&cdd.index, sizeof(cdd.index));
-  save_param(&cdd.lba, sizeof(cdd.lba));
-  save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
-  save_param(&cdd.volume, sizeof(cdd.volume));
-  save_param(&cdd.status, sizeof(cdd.status));
-
-  return bufferptr;
-}
+static off_t read_pos = -1;
 
-int cdd_context_load(uint8 *state)
+void cdd_seek(int index, int lba)
 {
-  int lba;
-  int bufferptr = 0;
+  int aindex = (index < 0 ? -index : index);
 
 #ifdef USE_LIBTREMOR
 #ifdef DISABLE_MANY_OGG_OPEN_FILES
-  /* close previous track VORBIS file structure to save memory */
-  if (cdd.toc.tracks[cdd.index].vf.datasource)
+  /* check if track index has changed */
+  if (index != cdd.index)
   {
-    ogg_free(cdd.index);
+    /* close previous track VORBIS file structure to save memory */
+    if (cdd.index >= 0 && cdd.toc.tracks[cdd.index].vf.datasource)
+    {
+      ogg_free(cdd.index);
+    }
+
+    /* open current track VORBIS file */
+    if (cdd.toc.tracks[aindex].vf.seekable)
+    {
+      ov_open(cdd.toc.tracks[aindex].fd,&cdd.toc.tracks[aindex].vf,0,0);
+    }
   }
 #endif
 #endif
 
-  load_param(&cdd.cycles, sizeof(cdd.cycles));
-  load_param(&cdd.latency, sizeof(cdd.latency));
-  load_param(&cdd.index, sizeof(cdd.index));
-  load_param(&cdd.lba, sizeof(cdd.lba));
-  load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
-  load_param(&cdd.volume, sizeof(cdd.volume));
-  load_param(&cdd.status, sizeof(cdd.status));
+  /* update current track index and LBA */
+  cdd.index = aindex;
+  cdd.lba = lba;
 
-  /* adjust current LBA within track limit */
-  lba = cdd.lba;
+  /* stay within track limits when seeking files */
   if (lba < cdd.toc.tracks[cdd.index].start)
   {
     lba = cdd.toc.tracks[cdd.index].start;
   }
 
-  /* seek to current track position */
+  /* seek to current block */
   if (!is_audio(cdd.index))
   {
     /* DATA track */
-    if (cdd.toc.tracks[cdd.index].fd)
-    {
-      pm_seek(cdd.toc.tracks[cdd.index].fd, lba * cdd.sectorSize, SEEK_SET);
-    }
+    read_pos = lba * cdd.sectorSize;
+    pm_seek(cdd.toc.tracks[cdd.index].fd, read_pos, SEEK_SET);
   }
 #ifdef USE_LIBTREMOR
   else if (cdd.toc.tracks[cdd.index].vf.seekable)
   {
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-    /* VORBIS file need to be opened first */
-    ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
-#endif
     /* VORBIS AUDIO track */
     ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
   }
@@ -273,6 +258,37 @@ int cdd_context_load(uint8 *state)
     cdd_change_track(cdd.index, lba);
   }
 #endif
+}
+
+int cdd_context_save(uint8 *state)
+{
+  int bufferptr = 0;
+
+  save_param(&cdd.cycles, sizeof(cdd.cycles));
+  save_param(&cdd.latency, sizeof(cdd.latency));
+  save_param(&cdd.index, sizeof(cdd.index));
+  save_param(&cdd.lba, sizeof(cdd.lba));
+  save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
+  save_param(&cdd.volume, sizeof(cdd.volume));
+  save_param(&cdd.status, sizeof(cdd.status));
+
+  return bufferptr;
+}
+
+int cdd_context_load(uint8 *state)
+{
+  int bufferptr = 0;
+
+  load_param(&cdd.cycles, sizeof(cdd.cycles));
+  load_param(&cdd.latency, sizeof(cdd.latency));
+  load_param(&cdd.index, sizeof(cdd.index));
+  load_param(&cdd.lba, sizeof(cdd.lba));
+  load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
+  load_param(&cdd.volume, sizeof(cdd.volume));
+  load_param(&cdd.status, sizeof(cdd.status));
+
+  /* seek to current track position */
+  cdd_seek(-cdd.index, cdd.lba);
 
   return bufferptr;
 }
@@ -280,6 +296,8 @@ int cdd_context_load(uint8 *state)
 int cdd_context_load_old(uint8 *state)
 {
   memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
+  cdd_seek(-cdd.index, cdd.lba);
+
   return 12 * 4;
 }
 
@@ -510,17 +528,29 @@ int cdd_unload(void)
 void cdd_read_data(uint8 *dst)
 {
   /* only read DATA track sectors */
-  if (!is_audio(cdd.index) && (cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[cdd.index].end))
+  if (!is_audio(cdd.index) && (cdd.lba >= cdd.toc.tracks[cdd.index].start) &&
+                              (cdd.lba < cdd.toc.tracks[cdd.index].end))
   {
+    off_t pos;
+
     /* BIN format ? */
     if (cdd.sectorSize == 2352)
     {
       /* skip 16-byte header */
-      pm_seek(cdd.toc.tracks[cdd.index].fd, cdd.lba * 2352 + 16, SEEK_SET);
+      pos = cdd.lba * 2352 + 16;
+    }
+    else
+    {
+      pos = cdd.lba * cdd.sectorSize;
+    }
+
+    if (pos != read_pos) {
+      pm_seek(cdd.toc.tracks[cdd.index].fd, pos, SEEK_SET);
+      read_pos = pos;
     }
 
     /* read sector data (Mode 1 = 2048 bytes) */
-    pm_read(dst, 2048, cdd.toc.tracks[cdd.index].fd);
+    read_pos += pm_read(dst, 2048, cdd.toc.tracks[cdd.index].fd);
   }
 }
 
@@ -719,7 +749,7 @@ void cdd_update(void)
       header[3] = 0x01;
 
       /* data track sector read is controlled by CDC */
-      cdd.lba += cdc_decoder_update(header);
+      cdc_decoder_update(header);
     }
     else
     {
@@ -734,51 +764,19 @@ void cdd_update(void)
 
       /* audio blocks are still sent to CDC as well as CD DAC/Fader */
       cdc_decoder_update(header);
-      /* next audio block is automatically read */
-      cdd.lba++;
     }
+    /* next block is automatically read */
+    cdd.lba++;
 
     /* check end of current track */
     if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
     {
-#ifdef USE_LIBTREMOR
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-      /* close previous track VORBIS file structure to save memory */
-      if (cdd.toc.tracks[cdd.index].vf.datasource)
-      {
-        ogg_free(cdd.index);
-      }
-#endif
-#endif
-      /* play next track */
-      cdd.index++;
-
       /* PAUSE between tracks */
       Pico_mcd->s68k_regs[0x36+0] = 0x01;
 
       /* seek to next audio track start */
-#ifdef USE_LIBTREMOR
-      if (cdd.toc.tracks[cdd.index].vf.seekable)
-      {
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-        /* VORBIS file need to be opened first */
-        ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
-#endif
-        ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
-      }
-      else
-#endif 
-#if 0
-      if (cdd.toc.tracks[cdd.index].fd)
-      {
-        fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
-      }
-#else
-      {
-        cdd_change_track(cdd.index, cdd.lba);
-      }
-#endif
+      cdd_seek(cdd.index + 1, cdd.lba);
     }
   }
 
@@ -791,100 +789,45 @@ void cdd_update(void)
     /* check current track limits */
     if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
     {
-#ifdef USE_LIBTREMOR
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-      /* close previous track VORBIS file structure to save memory */
-      if (cdd.toc.tracks[cdd.index].vf.datasource)
-      {
-        ogg_free(cdd.index);
-      }
-#endif
-#endif
       /* next track */
-      cdd.index++;
+      if (cdd.index >= cdd.toc.last)
+      {
+        /* no AUDIO track playing */
+        Pico_mcd->s68k_regs[0x36+0] = 0x01;
 
-      /* skip directly to track start position */
-      cdd.lba = cdd.toc.tracks[cdd.index].start;
-      
-      /* AUDIO track playing ? */
-      if (cdd.status == CD_PLAY)
+        /* end of disc */
+        cdd.lba = cdd.toc.end;
+        cdd.status = CD_END;
+      }
+      else
       {
-        Pico_mcd->s68k_regs[0x36+0] = 0x00;
+        cdd_seek(cdd.index + 1, cdd.toc.tracks[cdd.index+1].start);
+
+        /* AUDIO track playing ? */
+        if (cdd.status == CD_PLAY && is_audio(cdd.index))
+        {
+          Pico_mcd->s68k_regs[0x36+0] = 0x00;
+        }
       }
     }
     else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
     {
-#ifdef USE_LIBTREMOR
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-      /* close previous track VORBIS file structure to save memory */
-      if (cdd.toc.tracks[cdd.index].vf.datasource)
+      /* previous track */
+      if (cdd.index <= 0)
       {
-        ogg_free(cdd.index);
+        cdd_seek(0, 0);
+      }
+      else
+      {
+        cdd_seek(cdd.index - 1, cdd.toc.tracks[cdd.index-1].end);
       }
-#endif
-#endif
-
-      /* previous track */
-      cdd.index--;
-
-      /* skip directly to track end position */
-      cdd.lba = cdd.toc.tracks[cdd.index].end;
-    }
-
-    /* check disc limits */
-    if (cdd.index < 0)
-    {
-      cdd.index = 0;
-      cdd.lba = 0;
-    }
-    else if (cdd.index >= cdd.toc.last)
-    {
-      /* no AUDIO track playing */
-      Pico_mcd->s68k_regs[0x36+0] = 0x01;
-
-      /* end of disc */
-      cdd.index = cdd.toc.last;
-      cdd.lba = cdd.toc.end;
-      cdd.status = CD_END;
-      return;
     }
 
-    /* seek to current block */
     if (!is_audio(cdd.index))
     {
       /* no AUDIO track playing */
       Pico_mcd->s68k_regs[0x36+0] = 0x01;
-
-      /* DATA track */
-      pm_seek(cdd.toc.tracks[cdd.index].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
     }
-#ifdef USE_LIBTREMOR
-    else if (cdd.toc.tracks[cdd.index].vf.seekable)
-    {
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-      /* check if a new track is being played */
-      if (!cdd.toc.tracks[cdd.index].vf.datasource)
-      {
-        /* VORBIS file need to be opened first */
-        ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
-      }
-#endif
-      /* VORBIS AUDIO track */
-      ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
-    }
-#endif 
-#if 0
-    else if (cdd.toc.tracks[cdd.index].fd)
-    {
-      /* PCM AUDIO track */
-      fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
-    }
-#else
-    else
-    {
-      cdd_change_track(cdd.index, cdd.lba);
-    }
-#endif
   }
 }
 
@@ -910,7 +853,7 @@ void cdd_process(void)
             Pico_mcd->s68k_regs[0x38+1] == 0x00 ||
             Pico_mcd->s68k_regs[0x38+1] == 0x01)
         {
-          int lba = cdd.lba + 150;
+          int lba = cdd.lba + 150 - cdd.latency;
          if (Pico_mcd->s68k_regs[0x38+1] == 0x01)
             lba = abs(cdd.lba - cdd.toc.tracks[cdd.index].start);
          if (Pico_mcd->s68k_regs[0x38+1] == 0x0f)
@@ -1081,66 +1024,10 @@ void cdd_process(void)
         cdd.latency += (((cdd.lba - lba) * 120) / 270000);
       }
 
-      /* update current LBA */
-      cdd.lba = lba;
-
       /* get track index */
       while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
 
-#ifdef USE_LIBTREMOR
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-      /* check if track index has changed */
-      if (index != cdd.index)
-      {
-        /* close previous track VORBIS file structure to save memory */
-        if (cdd.toc.tracks[cdd.index].vf.datasource)
-        {
-          ogg_free(cdd.index);
-        }
-
-        /* open current track VORBIS file */
-        if (cdd.toc.tracks[index].vf.seekable)
-        {
-          ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
-        }
-      }
-#endif
-#endif
-
-      /* update current track index */
-      cdd.index = index;
-
-      /* stay within track limits when seeking files */
-      if (lba < cdd.toc.tracks[index].start) 
-      {
-        lba = cdd.toc.tracks[index].start;
-      }
-      
-      /* seek to current block */
-      if (!is_audio(cdd.index))
-      {
-        /* DATA track */
-        pm_seek(cdd.toc.tracks[cdd.index].fd, lba * cdd.sectorSize, SEEK_SET);
-      }
-#ifdef USE_LIBTREMOR
-      else if (cdd.toc.tracks[index].vf.seekable)
-      {
-        /* VORBIS AUDIO track */
-        ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
-      }
-#endif
-#if 0
-      else if (cdd.toc.tracks[index].fd)
-      {
-        /* PCM AUDIO track */
-        fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
-      }
-#else
-      else
-      {
-        cdd_change_track(index, lba);
-      }
-#endif
+      cdd_seek(index, lba);
 
       /* no audio track playing (yet) */
       Pico_mcd->s68k_regs[0x36+0] = 0x01;
@@ -1180,66 +1067,11 @@ void cdd_process(void)
         cdd.latency = ((cdd.lba - lba) * 120) / 270000;
       }
 
-      /* update current LBA */
-      cdd.lba = lba;
-
       /* get current track index */
       while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
 
-#ifdef USE_LIBTREMOR
-#ifdef DISABLE_MANY_OGG_OPEN_FILES
-      /* check if track index has changed */
-      if (index != cdd.index)
-      {
-        /* close previous track VORBIS file structure to save memory */
-        if (cdd.toc.tracks[cdd.index].vf.datasource)
-        {
-          ogg_free(cdd.index);
-        }
-
-        /* open current track VORBIS file */
-        if (cdd.toc.tracks[index].vf.seekable)
-        {
-          ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
-        }
-      }
-#endif
-#endif
-
-      /* update current track index */
-      cdd.index = index;
-
-      /* stay within track limits */
-      if (lba < cdd.toc.tracks[index].start) 
-      {
-        lba = cdd.toc.tracks[index].start;
-      }
-      
       /* seek to current block */
-      if (!is_audio(cdd.index))
-      {
-        /* DATA track */
-        pm_seek(cdd.toc.tracks[cdd.index].fd, lba * cdd.sectorSize, SEEK_SET);
-      }
-#ifdef USE_LIBTREMOR
-      else if (cdd.toc.tracks[index].vf.seekable)
-      {
-        /* VORBIS AUDIO track */
-        ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
-      }
-#endif
-#if 0
-      else if (cdd.toc.tracks[index].fd)
-      {
-        /* PCM AUDIO track */
-        fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
-      }
-#else
-      else
-      {
-        cdd_change_track(index, lba);
-      }
-#endif
+      cdd_seek(index, lba);
 
       /* no audio track playing */
       Pico_mcd->s68k_regs[0x36+0] = 0x01;