diff --git a/desmume/src/GPU_osd.cpp b/desmume/src/GPU_osd.cpp index 6e893fb74..5717b8ca1 100644 --- a/desmume/src/GPU_osd.cpp +++ b/desmume/src/GPU_osd.cpp @@ -528,7 +528,7 @@ void DrawHUD() if (CommonSettings.hud.FpsDisplay) { - osd->addFixed(Hud.FpsDisplay.x, Hud.FpsDisplay.y, "Fps:%02d/%02d (%02d%%)%s", Hud.fps, Hud.fps3d, Hud.arm9load, driver->EMU_IsEmulationPaused() ? " (paused)" : ""); + osd->addFixed(Hud.FpsDisplay.x, Hud.FpsDisplay.y, "Fps:%02d/%02d (%02d%%/%02d%%)%s", Hud.fps, Hud.fps3d, Hud.cpuload[0], Hud.cpuload[1], driver->EMU_IsEmulationPaused() ? " (paused)" : ""); } if (CommonSettings.hud.FrameCounterDisplay) diff --git a/desmume/src/GPU_osd.h b/desmume/src/GPU_osd.h index 999973bc0..5645c9b96 100644 --- a/desmume/src/GPU_osd.h +++ b/desmume/src/GPU_osd.h @@ -58,7 +58,7 @@ public: { fps = 0; fps3d = 0; - arm9load = 0; + cpuload[0] = cpuload[1] = 0; cpuloopIterationCount = 0; clicked = false; } @@ -76,7 +76,7 @@ public: HudCoordinates &hud(int i) { return ((HudCoordinates*)this)[i]; } void reset(); - int fps, fps3d, arm9load, cpuloopIterationCount; + int fps, fps3d, cpuload[2], cpuloopIterationCount; bool clicked; }; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 5959b9ba2..00df55b13 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -1522,10 +1522,12 @@ static void execHardware_hstart_vblankStart() triggerDma(EDMAMode_VBlank); //tracking for arm9 load average - nds.runCycleCollector[nds.idleFrameCounter] = 1120380-nds.idleCycles; + nds.runCycleCollector[0][nds.idleFrameCounter] = 1120380-nds.idleCycles[0]; + nds.runCycleCollector[1][nds.idleFrameCounter] = 1120380-nds.idleCycles[1]; nds.idleFrameCounter++; nds.idleFrameCounter &= 15; - nds.idleCycles = 0; + nds.idleCycles[0] = 0; + nds.idleCycles[1] = 0; } static void execHardware_hstart_vcount() @@ -1866,7 +1868,7 @@ static /*donotinline*/ std::pair armInnerLoop( { s32 temp = arm9; arm9 = min(s32next, arm9 + kIrqWait); - nds.idleCycles += arm9-temp; + nds.idleCycles[0] += arm9-temp; if (gxFIFO.size < 255) nds.freezeBus = FALSE; } } @@ -1882,7 +1884,9 @@ static /*donotinline*/ std::pair armInnerLoop( } else { + s32 temp = arm7; arm7 = min(s32next, arm7 + kIrqWait); + nds.idleCycles[1] += arm7-temp; if(arm7 == s32next) { nds_timer = nds_timer_base + minarmtime(arm9,arm7); @@ -2014,9 +2018,17 @@ void NDS_exec(s32 nb) #endif //if we were waiting for an irq, don't wait too long: - //let's re-analyze it after this hardware event - if(NDS_ARM9.waitIRQ) nds_arm9_timer = nds_timer; - if(NDS_ARM7.waitIRQ) nds_arm7_timer = nds_timer; + //let's re-analyze it after this hardware event (this rolls back a big burst of irq waiting which may have been interrupted by a resynch) + if(NDS_ARM9.waitIRQ) + { + nds.idleCycles[0] -= (s32)(nds_arm9_timer-nds_timer); + nds_arm9_timer = nds_timer; + } + if(NDS_ARM7.waitIRQ) + { + nds.idleCycles[1] -= (s32)(nds_arm7_timer-nds_timer); + nds_arm7_timer = nds_timer; + } } } diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 12b412581..2f334ab39 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -186,8 +186,8 @@ struct NDSSystem //it was perhaps a mistake to put it here. //it is far less important than the above. //maybe I should move it. - s32 idleCycles; - s32 runCycleCollector[16]; + s32 idleCycles[2]; + s32 runCycleCollector[2][16]; s32 idleFrameCounter; s32 cpuloopIterationCount; //counts the number of times during a frame that a reschedule happened diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 6c5c4d172..9c62b1066 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -1829,11 +1829,27 @@ static void StepRunLoop_User() if(nds.idleFrameCounter==0 || oneSecond) { //calculate a 16 frame arm9 load average - int load = 0; - for(int i=0;i<16;i++) - load = load/8 + nds.runCycleCollector[(i+nds.idleFrameCounter)&15]*7/8; - load = std::min(100,std::max(0,(int)(load*100/1120380))); - Hud.arm9load = load; + for(int cpu=0;cpu<2;cpu++) + { + int load = 0; + //printf("%d: ",cpu); + for(int i=0;i<16;i++) + { + //blend together a few frames to keep low-framerate games from having a jittering load average + //(they will tend to work 100% for a frame and then sleep for a while) + //4 frames should handle even the slowest of games + s32 sample = + nds.runCycleCollector[cpu][(i+0+nds.idleFrameCounter)&15] + + nds.runCycleCollector[cpu][(i+1+nds.idleFrameCounter)&15] + + nds.runCycleCollector[cpu][(i+2+nds.idleFrameCounter)&15] + + nds.runCycleCollector[cpu][(i+3+nds.idleFrameCounter)&15]; + sample /= 4; + load = load/8 + sample*7/8; + } + //printf("\n"); + load = std::min(100,std::max(0,(int)(load*100/1120380))); + Hud.cpuload[cpu] = load; + } } Hud.cpuloopIterationCount = nds.cpuloopIterationCount; @@ -3644,7 +3660,7 @@ void ScreenshotToClipboard(bool extraInfo) memcpy(&str[titlelen+1], &MMU.CART_ROM[12], 6); str[titlelen+1+6] = '\0'; TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 3:2), str, strlen(str)); - sprintf(str, "FPS: %i/%i (%02d%%) | %s", mainLoopData.fps, mainLoopData.fps3d, Hud.arm9load, paused ? "Paused":"Running"); + sprintf(str, "FPS: %i/%i (%02d%%/%02d%%) | %s", mainLoopData.fps, mainLoopData.fps3d, Hud.cpuload[0], Hud.cpuload[1], paused ? "Paused":"Running"); TextOut(hMemDC, 8, 384 + 14 * (twolinever ? 4:3), str, strlen(str)); sprintf(str, "3D Render: %s", core3DList[cur3DCore]->name);