|
40 | 40 | #include "unpatched_funcs.h" |
41 | 41 | #include "debug_file.h" |
42 | 42 | #include "cardengine.h" |
| 43 | +#include "fpsAdjust.h" |
43 | 44 | #include "nds_header.h" |
44 | 45 | #include "igm_text.h" |
45 | 46 |
|
@@ -182,6 +183,10 @@ static int noI2CVolLevel = 127; // Volume workaround for bricked I2C chips |
182 | 183 | static int volumeAdjustDelay = 0; |
183 | 184 | static bool volumeAdjustActivated = false; |
184 | 185 |
|
| 186 | +#ifndef TWLSDK |
| 187 | +fpsa_t sActiveFpsa; |
| 188 | +#endif |
| 189 | + |
185 | 190 | //static bool ndmaUsed = false; |
186 | 191 |
|
187 | 192 | // static int cardEgnineCommandMutex = 0; |
@@ -1172,6 +1177,142 @@ void unloadInGameMenu(void) { |
1172 | 1177 | sharedAddr[5] = 0; |
1173 | 1178 | } |
1174 | 1179 |
|
| 1180 | +#ifndef TWLSDK |
| 1181 | +static void vcountIrqLower() |
| 1182 | +{ |
| 1183 | + while (1) |
| 1184 | + { |
| 1185 | + if (sActiveFpsa.initial) |
| 1186 | + { |
| 1187 | + sActiveFpsa.initial = FALSE; |
| 1188 | + break; |
| 1189 | + } |
| 1190 | + |
| 1191 | + if (!sActiveFpsa.backJump) |
| 1192 | + sActiveFpsa.cycleDelta += sActiveFpsa.targetCycles - ((u64)FPSA_CYCLES_PER_FRAME << 24); |
| 1193 | + u32 linesToAdd = 0; |
| 1194 | + while (sActiveFpsa.cycleDelta >= (s64)((u64)FPSA_CYCLES_PER_LINE << 23)) |
| 1195 | + { |
| 1196 | + sActiveFpsa.cycleDelta -= (u64)FPSA_CYCLES_PER_LINE << 24; |
| 1197 | + if (++linesToAdd == 5) |
| 1198 | + break; |
| 1199 | + } |
| 1200 | + if (linesToAdd == 0) |
| 1201 | + { |
| 1202 | + sActiveFpsa.backJump = FALSE; |
| 1203 | + break; |
| 1204 | + } |
| 1205 | + if (linesToAdd > 1) |
| 1206 | + { |
| 1207 | + sActiveFpsa.backJump = TRUE; |
| 1208 | + } |
| 1209 | + else |
| 1210 | + { |
| 1211 | + // don't set the backJump flag because the irq is not retriggered if the new vcount |
| 1212 | + // is the same as the previous line |
| 1213 | + sActiveFpsa.backJump = FALSE; |
| 1214 | + } |
| 1215 | + // ensure we won't accidentally run out of line time |
| 1216 | + while (REG_DISPSTAT & DISP_IN_HBLANK) |
| 1217 | + ; |
| 1218 | + int curVCount = REG_VCOUNT; |
| 1219 | + REG_VCOUNT = curVCount - (linesToAdd - 1); |
| 1220 | + if (linesToAdd == 1) |
| 1221 | + break; |
| 1222 | + |
| 1223 | + while (REG_VCOUNT >= curVCount)//FPSA_ADJUST_MAX_VCOUNT - 5) |
| 1224 | + ; |
| 1225 | + while (REG_VCOUNT < curVCount)//FPSA_ADJUST_MAX_VCOUNT - 5) |
| 1226 | + ; |
| 1227 | + } |
| 1228 | + REG_IF = IRQ_VCOUNT; |
| 1229 | +} |
| 1230 | + |
| 1231 | +static void vcountIrqHigher() |
| 1232 | +{ |
| 1233 | + if (sActiveFpsa.initial) |
| 1234 | + { |
| 1235 | + sActiveFpsa.initial = FALSE; |
| 1236 | + return; |
| 1237 | + } |
| 1238 | + sActiveFpsa.cycleDelta += ((u64)FPSA_CYCLES_PER_FRAME << 24) - sActiveFpsa.targetCycles; |
| 1239 | + u32 linesToSkip = 0; |
| 1240 | + while (sActiveFpsa.cycleDelta >= (s64)((u64)FPSA_CYCLES_PER_LINE << 23)) |
| 1241 | + { |
| 1242 | + sActiveFpsa.cycleDelta -= (u64)FPSA_CYCLES_PER_LINE << 24; |
| 1243 | + if (++linesToSkip == 55) |
| 1244 | + break; |
| 1245 | + } |
| 1246 | + if (linesToSkip == 0) |
| 1247 | + return; |
| 1248 | + // ensure we won't accidentally run out of line time |
| 1249 | + while (REG_DISPSTAT & DISP_IN_HBLANK) |
| 1250 | + ; |
| 1251 | + REG_VCOUNT = REG_VCOUNT + (linesToSkip + 1); |
| 1252 | +} |
| 1253 | + |
| 1254 | +void fpsa_init(fpsa_t* fpsa) |
| 1255 | +{ |
| 1256 | + toncset(fpsa, 0, sizeof(fpsa_t)); |
| 1257 | + fpsa->isStarted = FALSE; |
| 1258 | + fpsa_setTargetFrameCycles(fpsa, (u64)FPSA_CYCLES_PER_FRAME << 24); // default to no adjustment |
| 1259 | +} |
| 1260 | + |
| 1261 | +void fpsa_start(fpsa_t* fpsa) |
| 1262 | +{ |
| 1263 | + // int irq = enterCriticalSection(); |
| 1264 | + do |
| 1265 | + { |
| 1266 | + if (fpsa->isStarted) |
| 1267 | + break; |
| 1268 | + if (fpsa->targetCycles == ((u64)FPSA_CYCLES_PER_FRAME << 24)) |
| 1269 | + break; |
| 1270 | + fpsa->backJump = FALSE; |
| 1271 | + fpsa->cycleDelta = 0; |
| 1272 | + fpsa->initial = TRUE; |
| 1273 | + fpsa->isFpsLower = fpsa->targetCycles >= ((u64)FPSA_CYCLES_PER_FRAME << 24); |
| 1274 | + // prevent the irq from immediately happening |
| 1275 | + while (REG_VCOUNT != FPSA_ADJUST_MAX_VCOUNT + 2) |
| 1276 | + ; |
| 1277 | + fpsa->isStarted = TRUE; |
| 1278 | + if (fpsa->isFpsLower) |
| 1279 | + { |
| 1280 | + SetYtrigger(FPSA_ADJUST_MAX_VCOUNT - 5); |
| 1281 | + } |
| 1282 | + else |
| 1283 | + { |
| 1284 | + SetYtrigger(FPSA_ADJUST_MIN_VCOUNT); |
| 1285 | + } |
| 1286 | + } while (0); |
| 1287 | + // leaveCriticalSection(irq); |
| 1288 | +} |
| 1289 | + |
| 1290 | +void fpsa_stop(fpsa_t* fpsa) |
| 1291 | +{ |
| 1292 | + if (!fpsa->isStarted) |
| 1293 | + return; |
| 1294 | + fpsa->isStarted = FALSE; |
| 1295 | +} |
| 1296 | + |
| 1297 | +void fpsa_setTargetFrameCycles(fpsa_t* fpsa, u64 cycles) |
| 1298 | +{ |
| 1299 | + fpsa->targetCycles = cycles; |
| 1300 | +} |
| 1301 | + |
| 1302 | +void fpsa_setTargetFpsFraction(fpsa_t* fpsa, u32 num, u32 den) |
| 1303 | +{ |
| 1304 | + u64 cycles = (((double)FPSA_SYS_CLOCK * den * (1 << 24)) / num) + 0.5; |
| 1305 | + fpsa_setTargetFrameCycles(fpsa, cycles);//((((u64)FPSA_SYS_CLOCK * (u64)den) << 24) + ((num + 1) >> 1)) / num); |
| 1306 | +} |
| 1307 | + |
| 1308 | +void fpsa_run(void) { |
| 1309 | + if (!sActiveFpsa.isStarted) { |
| 1310 | + return; |
| 1311 | + } |
| 1312 | + sActiveFpsa.isFpsLower ? vcountIrqLower() : vcountIrqHigher(); |
| 1313 | +} |
| 1314 | +#endif |
| 1315 | + |
1175 | 1316 | #ifdef DEBUG |
1176 | 1317 | static void log_arm9(void) { |
1177 | 1318 | //driveInitialize(); |
@@ -2007,6 +2148,10 @@ void myIrqHandlerVBlank(void) { |
2007 | 2148 | IPC_SendSync(screenIpc); |
2008 | 2149 | } |
2009 | 2150 |
|
| 2151 | + #ifndef TWLSDK |
| 2152 | + fpsa_run(); |
| 2153 | + #endif |
| 2154 | + |
2010 | 2155 | if (sharedAddr[0] == 0x524F5245) { // 'EROR' |
2011 | 2156 | REG_MASTER_VOLUME = 0; |
2012 | 2157 | while (REG_VCOUNT != 191) swiDelay(100); |
|
0 commit comments