if (check_unsatisfied_libcrypt())
       show_notification("LibCrypt protected game with missing SBI detected", 3000, 3);
+   if (Config.TurboCD)
+      show_notification("TurboCD is ON", 700, 2);
 
    return true;
 }
          display_internal_fps = true;
    }
 
+   var.value = NULL;
+   var.key = "pcsx_rearmed_cd_turbo";
+   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+   {
+      if (strcmp(var.value, "enabled") == 0)
+         Config.TurboCD = true;
+      else
+         Config.TurboCD = false;
+   }
+
 #ifdef HAVE_CDROM
    var.value = NULL;
    var.key = "pcsx_rearmed_phys_cd_readahead";
 
       "Compatibility Fixes",
       "Configure settings/workarounds required for correct operation of specific games."
    },
-#if !defined(DRC_DISABLE) && !defined(LIGHTREC)
    {
       "speed_hack",
       "Speed Hacks (Advanced)",
       "Configure hacks that may improve performance at the expense of decreased accuracy/stability."
    },
-#endif
    { NULL, NULL, NULL },
 };
 
       },
       "disabled",
    },
+   {
+      "pcsx_rearmed_cd_turbo",
+      "Turbo CD",
+      NULL,
+      "This makes the emulated CD-ROM extremely fast and can reduce loading times in some cases. Warning: many games were not programmed to handle such a speed. The game (or even the emulator) MAY CRASH at ANY TIME if this is enabled.",
+      NULL,
+      "speed_hack",
+      {
+         { "disabled", NULL },
+         { "enabled",  NULL },
+         { NULL, NULL },
+      },
+      "disabled",
+   },
 #if !defined(DRC_DISABLE) && !defined(LIGHTREC)
    {
       "pcsx_rearmed_nocompathacks",
       "pcsx_rearmed_nostalls",
       "Disable CPU/GTE Stalls",
       NULL,
-      "Will cause some games to run too quickly."
+      "Will cause some games to run too quickly. Should be disabled in almost all cases."
 #if defined(LIGHTREC)
       " Interpreter only."
 #endif
       ,
       NULL,
-      "compat_hack",
+      "speed_hack",
       {
          { "disabled", NULL },
          { "enabled",  NULL },
 
                SysPrintf("note: running with HLE BIOS, expect compatibility problems\n");
                SysPrintf("----------------------------------------------------------\n");
        }
+       if (Config.TurboCD)
+               SysPrintf("note: TurboCD is enabled, this breaks games\n");
 
        if (show_hud_msg) {
                if (check_unsatisfied_libcrypt())
 
        CE_CONFIG_VAL(GpuListWalking),
        CE_CONFIG_VAL(FractionalFramerate),
        CE_CONFIG_VAL(PreciseExceptions),
+       CE_CONFIG_VAL(TurboCD),
        CE_INTVAL(region),
        CE_INTVAL_V(g_scaler, 3),
        CE_INTVAL(g_gamma),
                                   "causes a performance hit";
 static const char h_cfg_ffps[]   = "Instead of 50/60fps for PAL/NTSC use ~49.75/59.81\n"
                                   "Closer to real hw but doesn't match modern displays.";
+static const char h_cfg_tcd[]    = "Greatly reduce CD load times. Breaks some games.";
 static const char h_cfg_psxclk[]  = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n"
                                    "(adjust this if the game is too slow/too fast/hangs)";
 
-enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU, AMO_GPUL, AMO_FFPS };
+enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU, AMO_GPUL, AMO_FFPS, AMO_TCD };
 
 static menu_entry e_menu_adv_options[] =
 {
        mee_onoff_h   ("BP exception emulation", 0, menu_iopts[AMO_BP],   1, h_cfg_exc),
        mee_enum_h    ("GPU l-list slow walking",0, menu_iopts[AMO_GPUL], men_autooo, h_cfg_gpul),
        mee_enum_h    ("Fractional framerate",   0, menu_iopts[AMO_FFPS], men_autooo, h_cfg_ffps),
+       mee_onoff_h   ("Turbo CD-ROM ",          0, menu_iopts[AMO_TCD], 1, h_cfg_tcd),
 #if !defined(DRC_DISABLE) || defined(LIGHTREC)
        mee_onoff_h   ("Disable dynarec (slow!)",0, menu_iopts[AMO_CPU],  1, h_cfg_nodrc),
 #endif
                { &Config.icache_emulation, &menu_iopts[AMO_IC] },
                { &Config.PreciseExceptions, &menu_iopts[AMO_BP] },
                { &Config.Cpu,     &menu_iopts[AMO_CPU] },
+               { &Config.TurboCD, &menu_iopts[AMO_TCD] },
        };
        int i;
        for (i = 0; i < ARRAY_SIZE(opts); i++)
 
        u8 AdpcmActive;
        u32 LastReadSeekCycles;
 
-       u8 unused7;
+       u8 RetryDetected;
 
        u8 DriveState; // enum drive_state
        u8 FastForward;
                cdr.ReportDelay--;
 }
 
+static boolean canDoTurbo(void)
+{
+       u32 c = psxRegs.cycle;
+       return Config.TurboCD && !cdr.RetryDetected && !cdr.AdpcmActive
+               //&& c - psxRegs.intCycle[PSXINT_SPUDMA].sCycle > (u32)cdReadTime * 2
+               && c - psxRegs.intCycle[PSXINT_MDECOUTDMA].sCycle > (u32)cdReadTime * 16;
+}
+
 static int cdrSeekTime(unsigned char *target)
 {
        int diff = msf2sec(cdr.SetSectorPlay) - msf2sec(target);
        }
 }
 
+static int msfiEq(const u8 *a, const u8 *b)
+{
+       return a[0] == b[0] && a[1] == b[1] && a[2] == b[2];
+}
+
 void cdrPlayReadInterrupt(void)
 {
        int hit = CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]);
                        {
                                for (i = 0; i < 3; i++)
                                        set_loc[i] = btoi(cdr.Param[i]);
+                               cdr.RetryDetected = msfiEq(cdr.SetSector, set_loc)
+                                       && !cdr.SetlocPending;
+                               //cdr.RetryDetected |= msfiEq(cdr.Param, cdr.Transfer);
                                memcpy(cdr.SetSector, set_loc, 3);
                                cdr.SetSector[3] = 0;
                                cdr.SetlocPending = 1;
                        StopReading();
                        SetPlaySeekRead(cdr.StatP, STATUS_SEEK | STATUS_ROTATING);
 
-                       seekTime = cdrSeekTime(cdr.SetSector);
+                       if (!canDoTurbo())
+                               seekTime = cdrSeekTime(cdr.SetSector);
                        memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
                        cdr.DriveState = DRIVESTATE_SEEK;
                        CDR_prefetch(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1],
                        cycles += seekTime;
                        if (Config.hacks.cdr_read_timing)
                                cycles = cdrAlignTimingHack(cycles);
+                       else if (canDoTurbo())
+                               cycles = cdReadTime / 2;
                        CDRPLAYREAD_INT(cycles, 1);
 
                        SetPlaySeekRead(cdr.StatP, STATUS_SEEK);
        cdr.Ctrl |= cdr.AdpcmActive << 2;
        cdr.Ctrl |= cdr.ResultReady << 5;
 
+       //cdr.Ctrl &= ~0x40;
+       //if (cdr.FifoOffset != DATA_SIZE)
        cdr.Ctrl |= 0x40; // data fifo not empty
 
        // What means the 0x10 and the 0x08 bits? I only saw it used by the bios
 }
 
 void psxDma3(u32 madr, u32 bcr, u32 chcr) {
-       u32 cdsize, max_words;
+       u32 cdsize, max_words, cycles;
        int size;
        u8 *ptr;
 
                        }
                        psxCpu->Clear(madr, cdsize / 4);
 
-                       set_event(PSXINT_CDRDMA, (cdsize / 4) * 24);
+                       cycles = (cdsize / 4) * 24;
+                       set_event(PSXINT_CDRDMA, cycles);
 
                        HW_DMA3_CHCR &= SWAPu32(~0x10000000);
                        if (chcr & 0x100) {
                        }
                        else {
                                // halted
-                               psxRegs.cycle += (cdsize/4) * 24 - 20;
+                               psxRegs.cycle += cycles - 20;
                        }
+                       if (canDoTurbo() && cdr.Reading && cdr.FifoOffset >= 2048)
+                               CDRPLAYREAD_INT(cycles + 4096, 1);
                        return;
 
                default:
 
        time[2] = itob(0x10);
 
        if (!Config.HLE && Config.SlowBoot) {
-               // boot to BIOS in case of CDDA ir lid open
+               // boot to BIOS in case of CDDA or lid is open
                CDR_getStatus(&stat);
                if ((stat.Status & 0x10) || stat.Type == 2 || !CDR_readTrack(time))
                        return 0;
 
        boolean icache_emulation;
        boolean DisableStalls;
        boolean PreciseExceptions;
+       boolean TurboCD;
        int cycle_multiplier; // 100 for 1.0
        int cycle_multiplier_override;
        s8 GpuListWalking;