4 #include "new_dynarec/new_dynarec.h"
5 #include "lightrec/plugin.h"
7 /* It's duplicated from emu_if.c */
8 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
10 /* Corresponds to LIGHTREC_OPT_INV_DMA_ONLY of lightrec.h */
11 #define LIGHTREC_HACK_INV_DMA_ONLY (1 << 0)
15 static const char * const MemorycardHack_db[] =
17 /* Lifeforce Tenka, also known as Codename Tenka */
18 "SLES00613", "SLED00690", "SLES00614", "SLES00615",
19 "SLES00616", "SLES00617", "SCUS94409"
22 static const char * const cdr_read_hack_db[] =
24 /* T'ai Fu - Wrath of the Tiger */
28 static const char * const gpu_slow_llist_db[] =
30 /* Bomberman Fantasy Race */
31 "SLES01712", "SLPS01525", "SLPS91138", "SLPM87102", "SLUS00823",
33 "SCES02834", "SCUS94570", "SCUS94616", "SCUS94654",
34 /* Final Fantasy IV */
35 "SCES03840", "SLPM86028", "SLUS01360",
36 /* Point Blank - calibration cursor */
37 "SCED00287", "SCES00886", "SLUS00481",
38 /* Simple 1500 Series Vol. 57: The Meiro */
40 /* Spot Goes to Hollywood */
41 "SLES00330", "SLPS00394", "SLUS00014",
43 "SCES01338", "SCES02072", "SCES02072", "SCES02072", "SCES02072", "SCUS94427",
44 /* Vampire Hunter D */
45 "SLES02731", "SLPS02477", "SLPS03198", "SLUS01138",
48 static const char * const gpu_centering_hack_db[] =
51 "SLPM86042", "SLPM86103", "SLPM87323",
56 static const char * const dualshock_timing1024_hack_db[] =
58 /* Judge Dredd - could also be poor cdrom+mdec+dma timing */
59 "SLUS00630", "SLES00755",
62 static const char * const dualshock_init_analog_hack_db[] =
64 /* Formula 1 Championship Edition */
68 static const char * const fractional_Framerate_hack_db[] =
70 /* Dance Dance Revolution */
71 "SLPM86503", // 3rd Mix
72 "SLPM86752", // 4th Mix
73 "SLPM86266", // 4thMix: The Beat Goes On
74 "SLPM86831", // Extra Mix
75 "SLUS01446", // Konamix
76 /* Dancing Stage Fever */
78 /* Dancing Stage Fusion */
81 "SCUS94425", "SCES02104",
84 #define HACK_ENTRY(var, list) \
85 { #var, &Config.hacks.var, list, ARRAY_SIZE(list) }
91 const char * const * id_list;
96 HACK_ENTRY(cdr_read_timing, cdr_read_hack_db),
97 HACK_ENTRY(gpu_slow_list_walking, gpu_slow_llist_db),
98 HACK_ENTRY(gpu_centering, gpu_centering_hack_db),
99 HACK_ENTRY(gpu_timing1024, dualshock_timing1024_hack_db),
100 HACK_ENTRY(dualshock_init_analog, dualshock_init_analog_hack_db),
101 HACK_ENTRY(fractional_Framerate, fractional_Framerate_hack_db),
107 const char * const id[4];
109 cycle_multiplier_overrides[] =
111 /* note: values are = (10000 / gui_option) */
112 /* Internal Section - fussy about timings */
113 { 202, { "SLPS01868" } },
114 /* Super Robot Taisen Alpha - on the edge with 175,
115 * changing memcard settings is enough to break/unbreak it */
116 { 190, { "SLPS02528", "SLPS02636" } },
117 /* Colin McRae Rally - language selection menu does not work with 175 */
118 { 174, { "SLES00477" } },
119 /* Brave Fencer Musashi - cd sectors arrive too fast */
120 { 170, { "SLUS00726", "SLPS01490" } },
121 #if defined(DRC_DISABLE) || defined(LIGHTREC) /* new_dynarec has a hack for this game */
122 /* Parasite Eve II - internal timer checks */
123 { 125, { "SLUS01042", "SLUS01055", "SLES02558", "SLES12558" } },
125 /* Discworld Noir - audio skips if CPU runs too fast */
126 { 222, { "SLES01549", "SLES02063", "SLES02064" } },
128 { 153, { "SLUS01032", "SLES02914" } },
129 /* Syphon Filter - reportedly hangs under unknown conditions */
130 { 169, { "SCUS94240" } },
131 /* Psychic Detective - some weird race condition in the game's cdrom code */
132 { 222, { "SLUS00165", "SLUS00166", "SLUS00167" } },
133 { 222, { "SLES00070", "SLES10070", "SLES20070" } },
134 /* Vib-Ribbon - cd timing issues (PAL+ari64drc only?) */
135 { 200, { "SCES02873" } },
136 /* Zero Divide - sometimes too fast */
137 { 200, { "SLUS00183", "SLES00159", "SLPS00083", "SLPM80008" } },
142 const char * const id;
145 lightrec_hacks_db[] =
147 /* Formula One Arcade */
148 { "SCES03886", LIGHTREC_HACK_INV_DMA_ONLY },
150 /* Formula One '99 */
151 { "SLUS00870", LIGHTREC_HACK_INV_DMA_ONLY },
152 { "SCPS10101", LIGHTREC_HACK_INV_DMA_ONLY },
153 { "SCES01979", LIGHTREC_HACK_INV_DMA_ONLY },
154 { "SLES01979", LIGHTREC_HACK_INV_DMA_ONLY },
156 /* Formula One 2000 */
157 { "SLUS01134", LIGHTREC_HACK_INV_DMA_ONLY },
158 { "SCES02777", LIGHTREC_HACK_INV_DMA_ONLY },
159 { "SCES02778", LIGHTREC_HACK_INV_DMA_ONLY },
160 { "SCES02779", LIGHTREC_HACK_INV_DMA_ONLY },
162 /* Formula One 2001 */
163 { "SCES03404", LIGHTREC_HACK_INV_DMA_ONLY },
164 { "SCES03423", LIGHTREC_HACK_INV_DMA_ONLY },
165 { "SCES03424", LIGHTREC_HACK_INV_DMA_ONLY },
166 { "SCES03524", LIGHTREC_HACK_INV_DMA_ONLY },
169 /* Function for automatic patching according to GameID. */
170 void Apply_Hacks_Cdrom(void)
174 memset(&Config.hacks, 0, sizeof(Config.hacks));
176 for (i = 0; i < ARRAY_SIZE(hack_db); i++)
178 for (j = 0; j < hack_db[i].id_list_len; j++)
180 if (strncmp(CdromId, hack_db[i].id_list[j], 9))
183 SysPrintf("using hack: %s\n", hack_db[i].name);
188 if (Config.hacks.dualshock_init_analog) {
189 // assume the default is off, see LoadPAD1plugin()
190 for (i = 0; i < 8; i++)
194 /* Apply Memory card hack for Codename Tenka. (The game needs one of the memory card slots to be empty) */
195 for (i = 0; i < ARRAY_SIZE(MemorycardHack_db); i++)
197 if (strncmp(CdromId, MemorycardHack_db[i], 9) == 0)
199 /* Disable the second memory card slot for the game */
201 /* This also needs to be done because in sio.c, they don't use Config.Mcd2 for that purpose */
207 /* Dynarec game-specific hacks */
208 new_dynarec_hacks_pergame = 0;
209 Config.cycle_multiplier_override = 0;
211 for (i = 0; i < ARRAY_SIZE(cycle_multiplier_overrides); i++)
213 const char * const * const ids = cycle_multiplier_overrides[i].id;
214 for (j = 0; j < ARRAY_SIZE(cycle_multiplier_overrides[i].id); j++)
215 if (ids[j] && strcmp(ids[j], CdromId) == 0)
217 if (j < ARRAY_SIZE(cycle_multiplier_overrides[i].id))
219 Config.cycle_multiplier_override = cycle_multiplier_overrides[i].mult;
220 new_dynarec_hacks_pergame |= NDHACK_OVERRIDE_CYCLE_M;
221 SysPrintf("using cycle_multiplier_override: %d\n",
222 Config.cycle_multiplier_override);
229 for (i = 0; drc_is_lightrec() && i < ARRAY_SIZE(lightrec_hacks_db); i++) {
230 if (strcmp(CdromId, lightrec_hacks_db[i].id) == 0)
232 lightrec_hacks = lightrec_hacks_db[i].hacks;
233 SysPrintf("using lightrec_hacks: 0x%x\n", lightrec_hacks);
239 // from duckstation's gamedb.json
240 static const u16 libcrypt_ids[] = {
241 17, 311, 995, 1041, 1226, 1241, 1301, 1362, 1431, 1444,
242 1492, 1493, 1494, 1495, 1516, 1517, 1518, 1519, 1545, 1564,
243 1695, 1700, 1701, 1702, 1703, 1704, 1715, 1733, 1763, 1882,
244 1906, 1907, 1909, 1943, 1979, 2004, 2005, 2006, 2007, 2024,
245 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2061, 2071, 2080,
246 2081, 2082, 2083, 2084, 2086, 2104, 2105, 2112, 2113, 2118,
247 2181, 2182, 2184, 2185, 2207, 2208, 2209, 2210, 2211, 2222,
248 2264, 2290, 2292, 2293, 2328, 2329, 2330, 2354, 2355, 2365,
249 2366, 2367, 2368, 2369, 2395, 2396, 2402, 2430, 2431, 2432,
250 2433, 2487, 2488, 2489, 2490, 2491, 2529, 2530, 2531, 2532,
251 2533, 2538, 2544, 2545, 2546, 2558, 2559, 2560, 2561, 2562,
252 2563, 2572, 2573, 2681, 2688, 2689, 2698, 2700, 2704, 2705,
253 2706, 2707, 2708, 2722, 2723, 2724, 2733, 2754, 2755, 2756,
254 2763, 2766, 2767, 2768, 2769, 2824, 2830, 2831, 2834, 2835,
255 2839, 2857, 2858, 2859, 2860, 2861, 2862, 2965, 2966, 2967,
256 2968, 2969, 2975, 2976, 2977, 2978, 2979, 3061, 3062, 3189,
257 3190, 3191, 3241, 3242, 3243, 3244, 3245, 3324, 3489, 3519,
258 3520, 3521, 3522, 3523, 3530, 3603, 3604, 3605, 3606, 3607,
259 3626, 3648, 12080, 12081, 12082, 12083, 12084, 12328, 12329, 12330,
260 12558, 12559, 12560, 12561, 12562, 12965, 12966, 12967, 12968, 12969,
261 22080, 22081, 22082, 22083, 22084, 22328, 22329, 22330, 22965, 22966,
262 22967, 22968, 22969, 32080, 32081, 32082, 32083, 32084, 32965, 32966,
266 // as documented by nocash
267 static const u16 libcrypt_sectors[16] = {
268 14105, 14231, 14485, 14579, 14649, 14899, 15056, 15130,
269 15242, 15312, 15378, 15628, 15919, 16031, 16101, 16167
272 int check_unsatisfied_libcrypt(void)
274 const char *p = CdromId + 4;
278 if (strncmp(CdromId, "SCE", 3) && strncmp(CdromId, "SLE", 3))
283 for (i = 0; i < ARRAY_SIZE(libcrypt_ids); i++)
284 if (id == libcrypt_ids[i])
286 if (i == ARRAY_SIZE(libcrypt_ids))
289 // detected a protected game
290 if (!CDR_getBufferSub(libcrypt_sectors[0]) && !sbi_sectors) {
291 SysPrintf("==================================================\n");
292 SysPrintf("LibCrypt game detected with missing SBI/subchannel\n");
293 SysPrintf("==================================================\n");
298 // calculate key just for fun (we don't really need it)
299 for (i = 0; i < 16; i++)
300 if (CheckSBI(libcrypt_sectors[i] - 2*75))
301 key |= 1u << (15 - i);
304 SysPrintf("%s, possible key=%04X\n", "LibCrypt detected", key);
306 SysPrintf("%s\n", "LibCrypt detected");