tweak around lcd line timing: make 3d vblank more generous (is still unrealistically brutal since all the rendering happens instantaneously, unlike real HW); give scanlines more time to render (render at end of scanline instead of hblank begin); execute an additional hblank dma on vcount=262 (speculative; fixes jittery nsmb split-parallax clouds)
This commit is contained in:
parent
c9f278e00d
commit
e068592d6b
|
@ -1378,31 +1378,10 @@ static void execHardware_hblank()
|
||||||
SPU_Emulate_core();
|
SPU_Emulate_core();
|
||||||
driver->AVI_SoundUpdate(SPU_core->outbuf,spu_core_samples);
|
driver->AVI_SoundUpdate(SPU_core->outbuf,spu_core_samples);
|
||||||
WAV_WavSoundUpdate(SPU_core->outbuf,spu_core_samples);
|
WAV_WavSoundUpdate(SPU_core->outbuf,spu_core_samples);
|
||||||
|
|
||||||
//this logic was formerly at hblank time. it was moved to the beginning of the scanline on a whim
|
|
||||||
if(nds.VCount<192)
|
|
||||||
{
|
|
||||||
//so, we have chosen to do the line drawing at hblank time.
|
|
||||||
//this is the traditional time for it in desmume.
|
|
||||||
//while it may seem more ruthlessly accurate to do it at hstart,
|
|
||||||
//in practice we need to be more forgiving, in case things have overrun the scanline start.
|
|
||||||
//this should be safe since games cannot do anything timing dependent until this next
|
|
||||||
//scanline begins, anyway (as this scanline was in the middle of drawing)
|
|
||||||
//taskSubGpu.execute(renderSubScreen,NULL);
|
|
||||||
GPU_RenderLine(&MainScreen, nds.VCount, frameSkipper.ShouldSkip2D());
|
|
||||||
GPU_RenderLine(&SubScreen, nds.VCount, frameSkipper.ShouldSkip2D());
|
|
||||||
//taskSubGpu.finish();
|
|
||||||
|
|
||||||
//trigger hblank dmas
|
|
||||||
//but notice, we do that just after we finished drawing the line
|
|
||||||
//(values copied by this hdma should not be used until the next scanline)
|
|
||||||
triggerDma(EDMAMode_HBlank);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execHardware_hstart_vblankEnd()
|
static void execHardware_hstart_vblankEnd()
|
||||||
{
|
{
|
||||||
nds.VCount = 0;
|
|
||||||
sequencer.nds_vblankEnded = true;
|
sequencer.nds_vblankEnded = true;
|
||||||
sequencer.reschedule = true;
|
sequencer.reschedule = true;
|
||||||
|
|
||||||
|
@ -1469,9 +1448,41 @@ static void execHardware_hstart_vcount()
|
||||||
|
|
||||||
static void execHardware_hstart()
|
static void execHardware_hstart()
|
||||||
{
|
{
|
||||||
|
//this logic keeps moving around.
|
||||||
|
//now, we try and give the game as much time as possible to finish doing its work for the scanline,
|
||||||
|
//by drawing scanline N at the very, very end of scanline N (here at the beginning of scanline N+1)
|
||||||
|
if(nds.VCount<192)
|
||||||
|
{
|
||||||
|
//taskSubGpu.execute(renderSubScreen,NULL);
|
||||||
|
GPU_RenderLine(&MainScreen, nds.VCount, frameSkipper.ShouldSkip2D());
|
||||||
|
GPU_RenderLine(&SubScreen, nds.VCount, frameSkipper.ShouldSkip2D());
|
||||||
|
//taskSubGpu.finish();
|
||||||
|
|
||||||
|
//trigger hblank dmas
|
||||||
|
//but notice, we do that just after we finished drawing the line
|
||||||
|
//(values copied by this hdma should not be used until the next scanline)
|
||||||
|
triggerDma(EDMAMode_HBlank);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nds.VCount==192)
|
||||||
|
{
|
||||||
|
//we need to trigger one last hblank dma since
|
||||||
|
//a. we're sort of lagged behind by one scanline
|
||||||
|
//b. i think that 193 hblanks actually fire (one for the hblank in scanline 262)
|
||||||
|
//this is demonstrated by NSMB splot-parallaxing clouds
|
||||||
|
//for some reason the game will setup two hdma scroll register buffers
|
||||||
|
//to be run consecutively, and unless we do this, the second buffer will be offset by one scanline
|
||||||
|
//causing a glitch in the 0th scanline
|
||||||
|
triggerDma(EDMAMode_HBlank);
|
||||||
|
}
|
||||||
|
|
||||||
nds.VCount++;
|
nds.VCount++;
|
||||||
|
|
||||||
if(nds.VCount==263)
|
if(nds.VCount==263)
|
||||||
|
{
|
||||||
|
nds.VCount=0;
|
||||||
|
}
|
||||||
|
if(nds.VCount==262)
|
||||||
{
|
{
|
||||||
execHardware_hstart_vblankEnd();
|
execHardware_hstart_vblankEnd();
|
||||||
} else if(nds.VCount==192)
|
} else if(nds.VCount==192)
|
||||||
|
@ -1505,8 +1516,12 @@ static void execHardware_hstart()
|
||||||
triggerDma(EDMAMode_MemDisplay);
|
triggerDma(EDMAMode_MemDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//end of 3d vblank
|
//end of 3d vblank
|
||||||
if(nds.VCount==214)
|
//this should be 214, but we are going to be generous for games with tight timing
|
||||||
|
//they shouldnt be changing any textures at 262 but they might accidentally still be at 214
|
||||||
|
//so..
|
||||||
|
if(CommonSettings.rigorous_timing && nds.VCount==214 || !CommonSettings.rigorous_timing && nds.VCount==262)
|
||||||
{
|
{
|
||||||
gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D());
|
gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D());
|
||||||
}
|
}
|
||||||
|
@ -2151,7 +2166,6 @@ void NDS_Reset()
|
||||||
|
|
||||||
nds.wifiCycle = 0;
|
nds.wifiCycle = 0;
|
||||||
memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4);
|
memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4);
|
||||||
nds.VCount = 0;
|
|
||||||
nds.old = 0;
|
nds.old = 0;
|
||||||
nds.touchX = nds.touchY = 0;
|
nds.touchX = nds.touchY = 0;
|
||||||
nds.isTouch = 0;
|
nds.isTouch = 0;
|
||||||
|
|
|
@ -525,6 +525,7 @@ extern struct TCommonSettings {
|
||||||
|
|
||||||
int num_cores;
|
int num_cores;
|
||||||
bool single_core() { return num_cores==1; }
|
bool single_core() { return num_cores==1; }
|
||||||
|
bool rigorous_timing;
|
||||||
|
|
||||||
struct _Wifi {
|
struct _Wifi {
|
||||||
int mode;
|
int mode;
|
||||||
|
|
|
@ -37,6 +37,7 @@ CommandLine::CommandLine()
|
||||||
: is_cflash_configured(false)
|
: is_cflash_configured(false)
|
||||||
, error(NULL)
|
, error(NULL)
|
||||||
, ctx(g_option_context_new (""))
|
, ctx(g_option_context_new (""))
|
||||||
|
, _rigorous_timing(0)
|
||||||
, _play_movie_file(0)
|
, _play_movie_file(0)
|
||||||
, _record_movie_file(0)
|
, _record_movie_file(0)
|
||||||
, _cflash_image(0)
|
, _cflash_image(0)
|
||||||
|
@ -84,6 +85,7 @@ void CommandLine::loadCommonOptions()
|
||||||
{ "num-cores", 0, 0, G_OPTION_ARG_INT, &_num_cores, "Override numcores detection and use this many", "NUM_CORES"},
|
{ "num-cores", 0, 0, G_OPTION_ARG_INT, &_num_cores, "Override numcores detection and use this many", "NUM_CORES"},
|
||||||
{ "scanline-filter-a", 0, 0, G_OPTION_ARG_INT, &scanline_filter_a, "Intensity of fadeout for scanlines filter (edge) (default 2)", "SCANLINE_FILTER_A"},
|
{ "scanline-filter-a", 0, 0, G_OPTION_ARG_INT, &scanline_filter_a, "Intensity of fadeout for scanlines filter (edge) (default 2)", "SCANLINE_FILTER_A"},
|
||||||
{ "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &scanline_filter_b, "Intensity of fadeout for scanlines filter (corner) (default 4)", "SCANLINE_FILTER_B"},
|
{ "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &scanline_filter_b, "Intensity of fadeout for scanlines filter (corner) (default 4)", "SCANLINE_FILTER_B"},
|
||||||
|
{ "rigorous-timing", 0, 0, G_OPTION_ARG_INT, &_rigorous_timing, "Use some rigorous timings instead of unrealistically generous (default 0)", "RIGOROUS_TIMING"},
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
{ "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL},
|
{ "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL},
|
||||||
{ "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL},
|
{ "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL},
|
||||||
|
@ -115,6 +117,7 @@ bool CommandLine::parse(int argc,char **argv)
|
||||||
if(_gbaslot_rom) gbaslot_rom = _gbaslot_rom;
|
if(_gbaslot_rom) gbaslot_rom = _gbaslot_rom;
|
||||||
|
|
||||||
if(_num_cores != -1) CommonSettings.num_cores = _num_cores;
|
if(_num_cores != -1) CommonSettings.num_cores = _num_cores;
|
||||||
|
if(_rigorous_timing) CommonSettings.rigorous_timing = true;
|
||||||
|
|
||||||
//TODO MAX PRIORITY! change ARM9BIOS etc to be a std::string
|
//TODO MAX PRIORITY! change ARM9BIOS etc to be a std::string
|
||||||
if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); }
|
if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); }
|
||||||
|
|
|
@ -86,6 +86,7 @@ private:
|
||||||
int _bios_swi;
|
int _bios_swi;
|
||||||
int _spu_advanced;
|
int _spu_advanced;
|
||||||
int _num_cores;
|
int _num_cores;
|
||||||
|
int _rigorous_timing;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue