cd: switch to CD controller code from genplus
[picodrive.git] / pico / cd / cd_sys.c
index 6b92d56..f7cd7b5 100644 (file)
 #define FAST_REV       0x10300         // FAST REVERSE track CDD status\r
 #define PLAYING                0x0100          // PLAYING audio track CDD status\r
 \r
+//#undef cdprintf\r
+//#define cdprintf(x, ...) elprintf(EL_STATUS, x, ##__VA_ARGS__)\r
+\r
+#define CDC_Update_Header()\r
 \r
 static int CD_Present = 0;\r
 \r
@@ -139,15 +143,32 @@ PICO_INTERNAL void Check_CD_Command(void)
                cdprintf("Got a read command");\r
 \r
                // DATA ?\r
-               if (Pico_mcd->scd.Cur_Track == 1)\r
+               if (Pico_mcd->scd.Cur_Track == 1) {\r
                     Pico_mcd->s68k_regs[0x36] |=  0x01;\r
-               else Pico_mcd->s68k_regs[0x36] &= ~0x01;                        // AUDIO\r
 \r
-               if (Pico_mcd->scd.File_Add_Delay == 0)\r
-               {\r
-                       FILE_Read_One_LBA_CDC();\r
+                 if (Pico_mcd->scd.File_Add_Delay == 0)\r
+                 {\r
+                       unsigned char header[4];\r
+                       _msf MSF;\r
+\r
+                       LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);\r
+\r
+                       header[0] = INT_TO_BCDB(MSF.M);\r
+                       header[1] = INT_TO_BCDB(MSF.S);\r
+                       header[2] = INT_TO_BCDB(MSF.F);\r
+                       header[3] = 0x01;\r
+\r
+                       //FILE_Read_One_LBA_CDC();\r
+                       Pico_mcd->scd.Cur_LBA +=\r
+                         cdc_decoder_update(header);\r
+                 }\r
+                 else Pico_mcd->scd.File_Add_Delay--;\r
+               }\r
+               else {\r
+                       Pico_mcd->s68k_regs[0x36] &= ~0x01;                     // AUDIO\r
+                       unsigned char header[4] = { 0, };\r
+                       cdc_decoder_update(header);\r
                }\r
-               else Pico_mcd->scd.File_Add_Delay--;\r
        }\r
 \r
        // Check CDD\r
@@ -190,7 +211,8 @@ PICO_INTERNAL void Reset_CD(void)
        Pico_mcd->scd.Cur_Track = 0;\r
        Pico_mcd->scd.Cur_LBA = -150;\r
        Pico_mcd->scd.Status_CDC &= ~1;\r
-       Pico_mcd->scd.Status_CDD = CD_Present ? READY : NOCD;\r
+       if (Pico_mcd->scd.Status_CDD != TRAY_OPEN)\r
+               Pico_mcd->scd.Status_CDD = CD_Present ? READY : NOCD;\r
        Pico_mcd->scd.CDD_Complete = 0;\r
        Pico_mcd->scd.File_Add_Delay = 0;\r
 }\r
@@ -201,27 +223,41 @@ int Insert_CD(const char *cdimg_name, int type)
        int ret = 1;\r
 \r
        CD_Present = 0;\r
-       Pico_mcd->scd.Status_CDD = NOCD;\r
 \r
        if (cdimg_name != NULL && type != CIT_NOT_CD)\r
        {\r
                ret = Load_CD_Image(cdimg_name, type);\r
                if (ret == 0) {\r
                        CD_Present = 1;\r
-                       /* for open tray close command will handle Status_CDD */\r
-                       if (Pico_mcd->scd.Status_CDD != TRAY_OPEN)\r
+\r
+                       if (Pico_mcd->scd.Status_CDD == TRAY_OPEN)\r
+                       {\r
+                               if (Pico_mcd->bios[0x122 ^ 1] == '2')\r
+                                       Close_Tray_CDD_cC();\r
+                               // else bios will issue it\r
+                       }\r
+                       else\r
+                       {\r
                                Pico_mcd->scd.Status_CDD = READY;\r
+                       }\r
                }\r
        }\r
 \r
+       if (Pico_mcd->scd.Status_CDD != TRAY_OPEN && !CD_Present)\r
+               Pico_mcd->scd.Status_CDD = NOCD;\r
+\r
        return ret;\r
 }\r
 \r
 \r
-void Stop_CD(void)\r
+int Stop_CD(void)\r
 {\r
+       int ret = CD_Present;\r
+\r
        Unload_ISO();\r
        CD_Present = 0;\r
+\r
+       return ret;\r
 }\r
 \r
 \r
@@ -471,8 +507,8 @@ PICO_INTERNAL int Play_CDD_c3(void)
        if (delay < 0) delay = -delay;\r
        delay >>= 12;\r
 \r
-       // based on genplys GX\r
-       if (delay < 13)\r
+       if (Pico_mcd->scd.Cur_LBA > 0 && delay < 13)\r
+               // based on genplus GX\r
                delay = 13;\r
 \r
        Pico_mcd->scd.Cur_LBA = new_lba;\r
@@ -740,3 +776,158 @@ PICO_INTERNAL int CDD_Def(void)
 }\r
 \r
 \r
+static int bswapwrite(int a, unsigned short d)\r
+{\r
+       *(unsigned short *)(Pico_mcd->s68k_regs + a) = (d>>8)|(d<<8);\r
+       return d + (d >> 8);\r
+}\r
+\r
+PICO_INTERNAL void CDD_Export_Status(void)\r
+{\r
+       unsigned int csum;\r
+\r
+       csum  = bswapwrite( 0x38+0, Pico_mcd->cdd.Status);\r
+       csum += bswapwrite( 0x38+2, Pico_mcd->cdd.Minute);\r
+       csum += bswapwrite( 0x38+4, Pico_mcd->cdd.Seconde);\r
+       csum += bswapwrite( 0x38+6, Pico_mcd->cdd.Frame);\r
+       Pico_mcd->s68k_regs[0x38+8] = Pico_mcd->cdd.Ext;\r
+       csum += Pico_mcd->cdd.Ext;\r
+       Pico_mcd->s68k_regs[0x38+9] = ~csum & 0xf;\r
+\r
+       Pico_mcd->s68k_regs[0x37] &= 3; // CDD.Control\r
+\r
+       if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4)\r
+       {\r
+               elprintf(EL_INTS, "cdd export irq 4");\r
+               SekInterruptS68k(4);\r
+       }\r
+\r
+//     cdprintf("CDD exported status\n");\r
+       cdprintf("out:  Status=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X  Checksum=%.4X",\r
+               (Pico_mcd->s68k_regs[0x38+0] << 8) | Pico_mcd->s68k_regs[0x38+1],\r
+               (Pico_mcd->s68k_regs[0x38+2] << 8) | Pico_mcd->s68k_regs[0x38+3],\r
+               (Pico_mcd->s68k_regs[0x38+4] << 8) | Pico_mcd->s68k_regs[0x38+5],\r
+               (Pico_mcd->s68k_regs[0x38+6] << 8) | Pico_mcd->s68k_regs[0x38+7],\r
+               (Pico_mcd->s68k_regs[0x38+8] << 8) | Pico_mcd->s68k_regs[0x38+9]);\r
+}\r
+\r
+\r
+PICO_INTERNAL void CDD_Import_Command(void)\r
+{\r
+//     cdprintf("CDD importing command\n");\r
+       cdprintf("in:  Command=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X  Checksum=%.4X",\r
+               (Pico_mcd->s68k_regs[0x38+10+0] << 8) | Pico_mcd->s68k_regs[0x38+10+1],\r
+               (Pico_mcd->s68k_regs[0x38+10+2] << 8) | Pico_mcd->s68k_regs[0x38+10+3],\r
+               (Pico_mcd->s68k_regs[0x38+10+4] << 8) | Pico_mcd->s68k_regs[0x38+10+5],\r
+               (Pico_mcd->s68k_regs[0x38+10+6] << 8) | Pico_mcd->s68k_regs[0x38+10+7],\r
+               (Pico_mcd->s68k_regs[0x38+10+8] << 8) | Pico_mcd->s68k_regs[0x38+10+9]);\r
+\r
+       switch (Pico_mcd->s68k_regs[0x38+10+0])\r
+       {\r
+               case 0x0:       // STATUS (?)\r
+                       Get_Status_CDD_c0();\r
+                       break;\r
+\r
+               case 0x1:       // STOP ALL (?)\r
+                       Stop_CDD_c1();\r
+                       break;\r
+\r
+               case 0x2:       // GET TOC INFORMATIONS\r
+                       switch(Pico_mcd->s68k_regs[0x38+10+3])\r
+                       {\r
+                               case 0x0:       // get current position (MSF format)\r
+                                       Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00);\r
+                                       Get_Pos_CDD_c20();\r
+                                       break;\r
+\r
+                               case 0x1:       // get elapsed time of current track played/scanned (relative MSF format)\r
+                                       Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 1;\r
+                                       Get_Track_Pos_CDD_c21();\r
+                                       break;\r
+\r
+                               case 0x2:       // get current track in RS2-RS3\r
+                                       Pico_mcd->cdd.Status =  (Pico_mcd->cdd.Status & 0xFF00) | 2;\r
+                                       Get_Current_Track_CDD_c22();\r
+                                       break;\r
+\r
+                               case 0x3:       // get total length (MSF format)\r
+                                       Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 3;\r
+                                       Get_Total_Lenght_CDD_c23();\r
+                                       break;\r
+\r
+                               case 0x4:       // first & last track number\r
+                                       Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 4;\r
+                                       Get_First_Last_Track_CDD_c24();\r
+                                       break;\r
+\r
+                               case 0x5:       // get track addresse (MSF format)\r
+                                       Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 5;\r
+                                       Get_Track_Adr_CDD_c25();\r
+                                       break;\r
+\r
+                               default :       // invalid, then we return status\r
+                                       Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 0xF;\r
+                                       Get_Status_CDD_c0();\r
+                                       break;\r
+                       }\r
+                       break;\r
+\r
+               case 0x3:       // READ\r
+                       Play_CDD_c3();\r
+                       break;\r
+\r
+               case 0x4:       // SEEK\r
+                       Seek_CDD_c4();\r
+                       break;\r
+\r
+               case 0x6:       // PAUSE/STOP\r
+                       Pause_CDD_c6();\r
+                       break;\r
+\r
+               case 0x7:       // RESUME\r
+                       Resume_CDD_c7();\r
+                       break;\r
+\r
+               case 0x8:       // FAST FOWARD\r
+                       Fast_Foward_CDD_c8();\r
+                       break;\r
+\r
+               case 0x9:       // FAST REWIND\r
+                       Fast_Rewind_CDD_c9();\r
+                       break;\r
+\r
+               case 0xA:       // RECOVER INITIAL STATE (?)\r
+                       CDD_cA();\r
+                       break;\r
+\r
+               case 0xC:       // CLOSE TRAY\r
+                       Close_Tray_CDD_cC();\r
+                       break;\r
+\r
+               case 0xD:       // OPEN TRAY\r
+                       Open_Tray_CDD_cD();\r
+                       break;\r
+\r
+               default:        // UNKNOWN\r
+                       CDD_Def();\r
+                       break;\r
+       }\r
+}\r
+\r
+void CDD_Reset(void)\r
+{\r
+       // Reseting CDD\r
+\r
+       memset(Pico_mcd->s68k_regs+0x34, 0, 2*2); // CDD.Fader, CDD.Control\r
+       Pico_mcd->cdd.Status = 0;\r
+       Pico_mcd->cdd.Minute = 0;\r
+       Pico_mcd->cdd.Seconde = 0;\r
+       Pico_mcd->cdd.Frame = 0;\r
+       Pico_mcd->cdd.Ext = 0;\r
+\r
+       // clear receive status and transfer command\r
+       memset(Pico_mcd->s68k_regs+0x38, 0, 20);\r
+       Pico_mcd->s68k_regs[0x38+9] = 0xF;              // Default checksum\r
+}\r
+\r
+\r