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:
zeromus 2010-03-24 23:13:36 +00:00
parent c9f278e00d
commit e068592d6b
4 changed files with 42 additions and 23 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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); }

View File

@ -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