diff --git a/Documentation/modules.def b/Documentation/modules.def index 9f03c5c..08d8f57 100644 --- a/Documentation/modules.def +++ b/Documentation/modules.def @@ -1,4 +1,4 @@ -1.22.1 +1.22.1-emu4crt-A09 apple2 Apple II/II+ 250 diff --git a/configure b/configure index 6c76ae2..804a817 100755 --- a/configure +++ b/configure @@ -18071,7 +18071,8 @@ else fi - LIBS="-mconsole -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" +/* SLK - switch -mconsole */ + LIBS="-mwindows -lws2_32 -ldxguid -lwinmm -ldinput $LIBS -lwinmm" CPPFLAGS="-D_LFS64_LARGEFILE=1 $CPPFLAGS" elif expr x"$host" : 'x.*djgpp' > /dev/null; then diff --git a/src/drivers/main.cpp b/src/drivers/main.cpp index ff7d59a..1909b83 100644 --- a/src/drivers/main.cpp +++ b/src/drivers/main.cpp @@ -268,6 +268,7 @@ static std::string DrBaseDirectory; MDFNGI *CurGame=NULL; + #ifdef WIN32 static std::string GetModuleFileName_UTF8(HMODULE hModule) { @@ -282,6 +283,47 @@ static std::string GetModuleFileName_UTF8(HMODULE hModule) return UTF16_to_UTF8(&path[0], nullptr, true); } + +static bool HandleConsoleMadness(void) // SLK - enforce stdout.txt & stderr.txt out to files +{ + bool ret; + if(AllocConsole()) + { + HWND cwin = GetConsoleWindow(); + ShowWindow(cwin, SW_HIDE); + + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + + SetConsoleOutputCP(65001); // UTF-8 + + std::string path; + size_t catpos; // Meow meow. + path = GetModuleFileName_UTF8(NULL); + if((catpos = path.find_last_of('\\')) != std::string::npos) path.resize(catpos + 1); + const std::u16string stdout_path = UTF8_to_UTF16(path + "stdout.txt", nullptr, true); + const std::u16string stderr_path = UTF8_to_UTF16(path + "stderr.txt", nullptr, true); + int new_stdout = -1; + int new_stderr = -1; + new_stdout = _wopen((const wchar_t*)stdout_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); + new_stderr = _wopen((const wchar_t*)stderr_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); + + fflush(stdout); + fflush(stderr); + + dup2(new_stdout, fileno(stdout)); + dup2(new_stderr, fileno(stderr)); + + close(new_stdout); + close(new_stderr); + + } + ret = false; + return ret; +} + +/* // SLK - Disable native redirection functions due to switch back to windows application + // returns 1 if redirected, 0 if not redirected due to error, -1 if not redirected due to env variable static int RedirectSTDxxx(void) { @@ -393,6 +435,8 @@ static bool HandleConsoleMadness(void) return ret; } +*/ + #endif void Mednafen::MDFND_OutputNotice(MDFN_NoticeType t, const char* s) noexcept @@ -1143,56 +1187,79 @@ static int GameLoop(void *arg) { while(GameThreadRun) { - int16 *sound; - int32 ssize; - bool fskip; - + //SLK trap change resolution request + if(resolution_to_change) + { + if(use_native_resolution) + { + if((current_resolution_w != resolution_to_change_w) || (current_resolution_h != resolution_to_change_h)) + { + GT_ChangeVideoResolution(); + printf("MAIN - native resolution switched\n"); + } + else {printf("MAIN - resolution change bypassed\n");} + } + if(use_super_resolution) + { + if(resolution_to_change_h != current_resolution_h) + { + GT_ChangeVideoResolution(); + printf("MAIN - Super resolution switched\n"); + } + else {printf("MAIN - Super resolution change bypassed\n");} + } + resolution_to_change = false; + } + // SLK - end + int16 *sound; + int32 ssize; + bool fskip; + /* If we requested a new video mode, wait until it's set before calling the emulation code again. */ - while(NeedVideoSync) - { - if(!GameThreadRun) return(1); // Might happen if video initialization failed + while(NeedVideoSync) + { + if(!GameThreadRun) return(1); // Might happen if video initialization failed Time::SleepMS(2); - } - - if(Sound_NeedReInit()) - GT_ReinitSound(); + } + if(Sound_NeedReInit()) + GT_ReinitSound(); - if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. - ers.SetETtoRT(); - // - // - fskip = ers.NeedFrameSkip(); - fskip &= MDFN_GetSettingB("video.frameskip"); - fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); - fskip |= (bool)NoWaiting; + if(MDFNDnetplay && !(NoWaiting & 0x2)) // TODO: Hacky, clean up. + ers.SetETtoRT(); + // + // + fskip = ers.NeedFrameSkip(); + fskip &= MDFN_GetSettingB("video.frameskip"); + fskip &= !(pending_ssnapshot || pending_snapshot || pending_save_state || pending_save_movie || NeedFrameAdvance); + fskip |= (bool)NoWaiting; - //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); + //printf("fskip %d; NeedFrameAdvance=%d\n", fskip, NeedFrameAdvance); - NeedFrameAdvance = false; - // - // - SoftFB[SoftFB_BackBuffer].lw[0] = ~0; + NeedFrameAdvance = false; + // + // + SoftFB[SoftFB_BackBuffer].lw[0] = ~0; - // - // - // - EmulateSpecStruct espec; + // + // + // + EmulateSpecStruct espec; - espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); - espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); - espec.skip = fskip; - espec.soundmultiplier = CurGameSpeed; - espec.NeedRewind = DNeedRewind; + espec.surface = SoftFB[SoftFB_BackBuffer].surface.get(); + espec.LineWidths = SoftFB[SoftFB_BackBuffer].lw.get(); + espec.skip = fskip; + espec.soundmultiplier = CurGameSpeed; + espec.NeedRewind = DNeedRewind; - espec.SoundRate = Sound_GetRate(); - espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); - espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; + espec.SoundRate = Sound_GetRate(); + espec.SoundBuf = Sound_GetEmuModBuffer(&espec.SoundBufMaxSize); + espec.SoundVolume = (double)MDFN_GetSettingUI("sound.volume") / 100; - if(MDFN_UNLIKELY(StateRCTest)) - { - // Note: Won't work correctly with modules that do mid-sync. - EmulateSpecStruct estmp = espec; + if(MDFN_UNLIKELY(StateRCTest)) + { + // Note: Won't work correctly with modules that do mid-sync. + EmulateSpecStruct estmp = espec; MemoryStream state0(524288); MemoryStream state1(524288); @@ -1210,19 +1277,19 @@ static int GameLoop(void *arg) if(!(state1.map_size() == state2.map_size() && !memcmp(state1.map() + 32, state2.map() + 32, state1.map_size() - 32))) { - FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); - FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); - - sd0.write(state1.map(), state1.map_size()); - sd1.write(state2.map(), state2.map_size()); - sd0.close(); - sd1.close(); - //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); - abort(); + FileStream sd0("/tmp/sdump0", FileStream::MODE_WRITE); + FileStream sd1("/tmp/sdump1", FileStream::MODE_WRITE); + + sd0.write(state1.map(), state1.map_size()); + sd1.write(state2.map(), state2.map_size()); + sd0.close(); + sd1.close(); + //assert(orig_state.map_size() == new_state.map_size() && !memcmp(orig_state.map() + 32, new_state.map() + 32, orig_state.map_size() - 32)); + abort(); } - } - else - MDFNI_Emulate(&espec); + } + else + MDFNI_Emulate(&espec); if(MDFN_UNLIKELY(StateSLSTest)) { @@ -1467,6 +1534,22 @@ bool GT_ReinitVideo(void) return(true); // FIXME! } +//SLK - called to change resolution +void GT_ChangeVideoResolution(void) +{ + // assert(MDFN_ThreadID() == GameThreadID); + MThreading::LockMutex(VTMutex); + NeedVideoSync++; + MThreading::UnlockMutex(VTMutex); + + MThreading::PostSem(VTWakeupSem); + while(NeedVideoSync && GameThreadRun) + { + Time::SleepMS(2); + } +} +//SLK - end + bool GT_ReinitSound(void) { bool ret = true; @@ -2025,7 +2108,7 @@ int main(int argc, char *argv[]) } #ifdef WIN32 - HandleConsoleMadness(); + HandleConsoleMadness(); // SLK #endif //ThreadTest(); diff --git a/src/drivers/main.h b/src/drivers/main.h index 73cd5dc..a19ef68 100644 --- a/src/drivers/main.h +++ b/src/drivers/main.h @@ -67,7 +67,7 @@ void GT_SetWMInputBehavior(bool CursorNeeded, bool MouseAbsNeeded, bool MouseRel void GT_ToggleFS(void); bool GT_ReinitVideo(void); bool GT_ReinitSound(void); - +void GT_ChangeVideoResolution(void); //SLK void BuildSystemSetting(MDFNSetting *setting, const char *system_name, const char *name, const char *description, const char *description_extra, MDFNSettingType type, const char *default_value, const char *minimum = NULL, const char *maximum = NULL, diff --git a/src/drivers/video-state.cpp b/src/drivers/video-state.cpp index 3bec53a..8a5f433 100644 --- a/src/drivers/video-state.cpp +++ b/src/drivers/video-state.cpp @@ -161,7 +161,7 @@ void DrawSaveStates(int32 screen_w, int32 screen_h, double exs, double eys, int } // end if(StateStatus) if(PreviewSurface) - { +{ MDFN_Rect tdrect, drect; int meow = ((screen_w / CurGame->nominal_width) + 1) / 2; @@ -169,19 +169,51 @@ void DrawSaveStates(int32 screen_w, int32 screen_h, double exs, double eys, int tdrect.w = TextRect.w * meow; tdrect.h = TextRect.h * meow; - tdrect.x = (screen_w - tdrect.w) / 2; - tdrect.y = screen_h - tdrect.h; - - BlitRaw(TextSurface, &TextRect, &tdrect); + tdrect.x = (screen_w - tdrect.w) / 2; + // SLK - Custom savestate selection OSD + if(use_native_resolution || use_super_resolution) + { + switch(screen_h){ + case 240:tdrect.y = screen_h - tdrect.h - 18; + break; + case 288:tdrect.y = screen_h - tdrect.h - 32; + break; + case 480:tdrect.y = screen_h - tdrect.h - 32; + break; + case 576:tdrect.y = screen_h - tdrect.h - 64; + break; + default:tdrect.y = screen_h - tdrect.h; + } + if(use_super_resolution) + { + tdrect.w = tdrect.w * 8; + tdrect.x = (screen_w - tdrect.w) / 2; + } + + BlitRaw(TextSurface, &TextRect, &tdrect); + + drect.w = screen_w * 0.5 + 3; // TODO: Why 3 ??? + drect.h = screen_h * 0.5 + 3; + drect.x = (screen_w - drect.w) / 2; + drect.y = tdrect.y - drect.h; // SLK + + BlitRaw(PreviewSurface, &PreviewRect, &drect); + } + else // native OSD display + { + tdrect.y = screen_h - tdrect.h; - drect.w = PreviewRect.w * meow; - drect.h = PreviewRect.h * meow; - drect.x = (screen_w - drect.w) / 2; - drect.y = screen_h - drect.h - tdrect.h - 4; + BlitRaw(TextSurface, &TextRect, &tdrect); - BlitRaw(PreviewSurface, &PreviewRect, &drect); + drect.w = PreviewRect.w * meow; + drect.h = PreviewRect.h * meow; + drect.x = (screen_w - drect.w) / 2; + drect.y = screen_h - drect.h - tdrect.h - 4; - } + BlitRaw(PreviewSurface, &PreviewRect, &drect); + } + // SLK - end + } } diff --git a/src/drivers/video.cpp b/src/drivers/video.cpp index f8ce628..88287b2 100644 --- a/src/drivers/video.cpp +++ b/src/drivers/video.cpp @@ -105,6 +105,16 @@ enum VDRIVER__COUNT }; +// SLK +static int _resolution_switch; +enum +{ + RES_STATIC = 0, + RES_NATIVE = 1, + RES_SUPER = 2 +}; +// SLK - end + enum { NTVB_NONE = 0, @@ -146,6 +156,17 @@ static const MDFNSetting_EnumList VDriver_List[] = { NULL, 0 }, }; +// SLK - custom setting +static const MDFNSetting_EnumList Resolution_Switch[] = +{ + // Legacy: + { "0", RES_STATIC}, + { "native", RES_NATIVE, "Native resolution", gettext_noop("Use emulated system native resolution.") }, + { "super", RES_SUPER, "Super resolution", gettext_noop("Use super resolutions") }, + { NULL, 0 }, +}; +// SLK - end + static const MDFNSetting GlobalVideoSettings[] = { { "video.driver", MDFNSF_NOFLAGS, gettext_noop("Video output driver."), NULL, MDFNST_ENUM, "default", NULL, NULL, NULL, NULL, VDriver_List }, @@ -161,6 +182,11 @@ static const MDFNSetting GlobalVideoSettings[] = MDFNST_BOOL, "1" }, { "video.disable_composition", MDFNSF_NOFLAGS, gettext_noop("Attempt to disable desktop composition."), gettext_noop("Currently, this setting only has an effect on Windows Vista and Windows 7(and probably the equivalent server versions as well)."), MDFNST_BOOL, "1" }, + + // SLK - admit new parameter + { "video.resolution_switch", MDFNSF_NOFLAGS, gettext_noop("Video resolution switch (0, native or super)."), NULL, MDFNST_ENUM, "0", NULL, NULL, NULL, NULL, Resolution_Switch}, + // SLK - end + }; static const MDFNSetting_EnumList StretchMode_List[] = @@ -844,6 +870,41 @@ void Video_Sync(MDFNGI *gi) video_settings.shader = (ShaderType)MDFN_GetSettingI(snp + "shader"); video_settings.shader_str = MDFN_GetSettingS(snp + "shader"); + + // SLK - set video settings - disable some options in conflict with native resolution + _resolution_switch = MDFN_GetSettingI("video.resolution_switch"); + if(_resolution_switch) + { + if(_resolution_switch == RES_NATIVE) // Native Res + { + use_native_resolution = true; + printf("### VIDEO Native resolution init - set to %dx%d\n",resolution_to_change_w,resolution_to_change_h); + video_settings.xres = resolution_to_change_w; // for fullscreen mode + VideoGI->nominal_width = resolution_to_change_w; // for windowed mode + video_settings.xscale = 1; + video_settings.xscalefs = 1; + video_settings.yscalefs = 1; + video_settings.stretch = 0; + + } + if(_resolution_switch == RES_SUPER) + { + use_super_resolution = true; + printf("### VIDEO Super resolution init - set to 2560x%d\n",resolution_to_change_h); + video_settings.xres = current_resolution_w = 2560; // for fullscreen mode + VideoGI->nominal_width = 2560; // for windowed mode + video_settings.xscale = 1; + video_settings.xscalefs = 1; + video_settings.yscalefs = 1; + video_settings.stretch = 0; + } + video_settings.yres = current_resolution_h = resolution_to_change_h; // for fullscreen mode + VideoGI->nominal_height = resolution_to_change_h; // for windowed mode + video_settings.yscale = 1; + video_settings.videoip = 0; + video_settings.shader = SHADER_NONE; + } + // // if(0) @@ -1238,11 +1299,44 @@ void Video_Sync(MDFNGI *gi) SMRect.y = 0; SMRect.w = screen_w; - SMDRect.w = SMRect.w * xmu; + // SLK - Set OSD message rendering rect. + if(use_super_resolution) // enlarge OSD message in super resolution mode + { + SMDRect.w = SMRect.w * xmu; + printf("VIDEO - Init : SMRect.w: %d xmu: %d\n",SMRect.w,xmu); + } + else + { + SMDRect.w = SMRect.w * xmu; + } + // SLK - end + + //SMDRect.w = SMRect.w * xmu; SMDRect.h = SMRect.h * ymu; SMDRect.x = (screen_w - SMDRect.w) / 2; - SMDRect.y = screen_h - SMDRect.h; + // SMDRect.y = screen_h - SMDRect.h; + // SLK - Vertical offset for OSD messages + if(use_native_resolution || use_super_resolution) + { + switch(screen_h){ + case 240:SMDRect.y = screen_h - SMDRect.h - 18; + break; + case 288:SMDRect.y = screen_h - SMDRect.h - 32; + break; + case 480:SMDRect.y = screen_h - SMDRect.h - 32; + break; + case 576:SMDRect.y = screen_h - SMDRect.h - 64; + break; + default:SMDRect.y = screen_h - SMDRect.h * xmu; // TODO: ??? + } + } + else + { + SMDRect.y = screen_h - SMDRect.h; + } + // SLK - end + if(SMDRect.x < 0) { SMRect.w += SMDRect.x * 2 / xmu; @@ -1648,6 +1742,16 @@ void BlitScreen(MDFN_Surface *msurface, const MDFN_Rect *DisplayRect, const int3 if(LineWidths[0] == ~0) // Skip multi line widths code? { + // SLK - blit for: NES + //printf(" Src: %dx%d - %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); + //printf(" Dest: %dx%d - %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); + // src_rect.y = (resolution_to_change_h - src_rect.h) / 2 ; //SLK + if(use_native_resolution || use_super_resolution) + { + screen_dest_rect.y = (resolution_to_change_h - src_rect.h) / 2; + screen_dest_rect.h = src_rect.h; + } + // SLK end SubBlit(msurface, src_rect, screen_dest_rect, InterlaceField); } else @@ -1687,28 +1791,60 @@ void BlitScreen(MDFN_Surface *msurface, const MDFN_Rect *DisplayRect, const int3 } else { - sub_dest_rect.x = screen_dest_rect.x; - sub_dest_rect.w = screen_dest_rect.w; - sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; - sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; - } - - if(!sub_dest_rect.h) // May occur with small yscale values in certain cases, so prevent triggering an assert() - sub_dest_rect.h = 1; - - // Blit here! - SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); + if(use_native_resolution || use_super_resolution) + { + // SLK - (prevent) resizing and centering + //printf(" src_rect: %dx%d %d,%d\n",src_rect.w,src_rect.h,src_rect.x,src_rect.y); + sub_dest_rect.x = screen_dest_rect.x; + sub_dest_rect.w = screen_dest_rect.w; + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y); // * screen_dest_rect.h / src_rect.h; + //printf(" sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); + //printf(" sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); + //printf(" sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); + + if(sub_src_rect.w >= resolution_to_change_w) // horizontal crop to fit screen + { + sub_src_rect.x = sub_src_rect.x + ((sub_src_rect.w - resolution_to_change_w) / 2); + sub_src_rect.w = resolution_to_change_w; + } + + if(native_resolution_vcenter == true) // default vertical centering + { + sub_dest_rect.y = sub_dest_rect.y + (resolution_to_change_h - sub_src_rect.h) / 2 ; + sub_dest_rect.h = sub_src_rect.h; + } + else // fill screen (psx - half black screen fix) + { + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; + } + //printf(" SLK sub_src_rect: %dx%d %d,%d\n",sub_src_rect.w,sub_src_rect.h,sub_src_rect.x,sub_src_rect.y); + //printf(" SLK sub_dest_rect: %dx%d %d,%d\n",sub_dest_rect.w,sub_dest_rect.h,sub_dest_rect.x,sub_dest_rect.y); + //printf(" SLK sub_screen_rect: %dx%d %d,%d\n",screen_dest_rect.w,screen_dest_rect.h,screen_dest_rect.x,screen_dest_rect.y); + } + else + { + sub_dest_rect.x = screen_dest_rect.x; + sub_dest_rect.w = screen_dest_rect.w; + sub_dest_rect.y = screen_dest_rect.y + (last_y - src_rect.y) * screen_dest_rect.h / src_rect.h; + sub_dest_rect.h = sub_src_rect.h * screen_dest_rect.h / src_rect.h; + } + + if(!sub_dest_rect.h){sub_dest_rect.h = 1;} // May occur with small yscale values in certain cases, so prevent triggering an assert() + // SLK - end + + // Blit here! + SubBlit(msurface, sub_src_rect, sub_dest_rect, InterlaceField); - last_y = y; + last_y = y; - if(y != (src_rect.y + src_rect.h)) - { - last_width = LineWidths[y]; + if(y != (src_rect.y + src_rect.h)) + { + last_width = LineWidths[y]; + } } - - } } } + } if(take_ssnapshot) { diff --git a/src/mednafen.cpp b/src/mednafen.cpp index d3b18a3..308d698 100644 --- a/src/mednafen.cpp +++ b/src/mednafen.cpp @@ -51,6 +51,18 @@ #include "video/tblur.h" #include "qtrecord.h" +// SLK +bool use_native_resolution = false; +bool use_super_resolution = false; +bool resolution_to_change; +int resolution_to_change_w; +int resolution_to_change_h; +int current_resolution_w; +int current_resolution_h; +bool native_resolution_vcenter = true; +// SLK end + + namespace Mednafen { @@ -64,6 +76,17 @@ static const char *CSD_tblur = gettext_noop("Enable video temporal blur(50/50 pr static const char *CSD_tblur_accum = gettext_noop("Accumulate color data rather than discarding it."); static const char *CSD_tblur_accum_amount = gettext_noop("Blur amount in accumulation mode, specified in percentage of accumulation buffer to mix with the current frame."); +// SLK +bool use_native_resolution = false; +bool use_super_resolution = false; +bool resolution_to_change; +int resolution_to_change_w; +int resolution_to_change_h; +int current_resolution_w; +int current_resolution_h; +bool native_resolution_vcenter = true; +// SLK end + static const MDFNSetting_EnumList VCodec_List[] = { { "raw", (int)QTRecord::VCODEC_RAW, "Raw", diff --git a/src/mednafen.h b/src/mednafen.h index 9172509..d1562c7 100644 --- a/src/mednafen.h +++ b/src/mednafen.h @@ -21,6 +21,18 @@ #include "settings.h" #include "NativeVFS.h" +// SLK +extern bool use_native_resolution; +extern bool use_super_resolution; +extern bool native_resolution_vcenter; +extern bool resolution_to_change; +extern int resolution_to_change_w; +extern int resolution_to_change_h; +extern int current_resolution_w; +extern int current_resolution_h; +// SLK end + + namespace Mednafen { extern NativeVFS NVFS; diff --git a/src/nes/nes.cpp b/src/nes/nes.cpp index e5255aa..d2341ef 100644 --- a/src/nes/nes.cpp +++ b/src/nes/nes.cpp @@ -287,7 +287,21 @@ static MDFN_COLD void Load(GameFile* gf) MDFNGameInfo->fps = PAL? 838977920 : 1008307711; MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); } - + + //SLK + if(PAL) + { + resolution_to_change_h = 288; + } + else + { + resolution_to_change_h = 240; + } + resolution_to_change_w = 256; + resolution_to_change = true; + //SLK end + + X6502_Init(); MDFNPPU_Init(); MDFNSND_Init(PAL); diff --git a/src/pce/pce.cpp b/src/pce/pce.cpp index 69d451a..e3d3133 100644 --- a/src/pce/pce.cpp +++ b/src/pce/pce.cpp @@ -413,6 +413,16 @@ static MDFN_COLD void LoadCommonPre(void) for(unsigned ch = 0; ch < 2; ch++) HRBufs[ch] = new OwlBuffer(); + // SLK + if(MDFN_GetSettingB("pce.arcadecard")) + { + resolution_to_change_w = 256; + resolution_to_change_h = 240; + resolution_to_change = true; + } + // SLK + + // FIXME: Make these globals less global! PCE_ACEnabled = MDFN_GetSettingB("pce.arcadecard"); diff --git a/src/pce/vce.cpp b/src/pce/vce.cpp index 3e67570..23f7b83 100644 --- a/src/pce/vce.cpp +++ b/src/pce/vce.cpp @@ -35,6 +35,11 @@ namespace MDFN_IEN_PCE { +// SLK +static int prev_dot_clock = 0; // SLK - 4 to force resolution initializing a start +static const int width_list[4] = {256, 320, 512, 512 }; // SLK +// SLK end + static const int vce_ratios[4] = { 4, 3, 2, 2 }; static MDFN_FASTCALL NO_INLINE int32 Sync(const int32 timestamp); @@ -634,6 +639,18 @@ void VCE::SetVCECR(uint8 V) dot_clock_ratio = vce_ratios[dot_clock]; CR = V; + + // SLK + if(dot_clock != prev_dot_clock) + { + printf("PCE - VCE - dot_clock change to: %d\n",dot_clock); + prev_dot_clock = dot_clock; + resolution_to_change_w = width_list[dot_clock]; + resolution_to_change_h = 240; + resolution_to_change = true; + } + // SLK end + } void VCE::SetPixelFormat(const MDFN_PixelFormat &format, const uint8* CustomColorMap, const uint32 CustomColorMapLen) diff --git a/src/psx/gpu.cpp b/src/psx/gpu.cpp index 9e2f7fe..1f003a9 100644 --- a/src/psx/gpu.cpp +++ b/src/psx/gpu.cpp @@ -24,6 +24,7 @@ #include "psx.h" #include "timer.h" +#include // SLK /* FIXME: Respect horizontal timing register values in relation to hsync/hblank/hretrace/whatever signal sent to the timers */ /* @@ -74,6 +75,78 @@ namespace PS_GPU_INTERNAL } using namespace PS_GPU_INTERNAL; +// SLK +uint32 PreviousDisplayMode; +int prev_resolution_w; +int prev_resolution_h; +int res_change_count; + +void GPU_NewDisplayMode(int V) // SLK - identify GPU new resolution, set global variables used in MAIN & VIDEO +{ + // GP1(08h) - Display mode + // 0-1 Horizontal Resolution 1 (0=256, 1=320, 2=512, 3=640) ;GPUSTAT.17-18 + // 2 Vertical Resolution (0=240, 1=480, when Bit5=1) ;GPUSTAT.19 + // 3 Video Mode (0=NTSC/60Hz, 1=PAL/50Hz) ;GPUSTAT.20 + // 4 Display Area Color Depth (0=15bit, 1=24bit) ;GPUSTAT.21 + // 5 Vertical Interlace (0=Off, 1=On) ;GPUSTAT.22 + // 6 Horizontal Resolution 2 (0=256/320/512/640, 1=368) ;GPUSTAT.16 + // 7 "Reverseflag" (0=Normal, 1=Distorted) ;GPUSTAT.14 + // source: http://problemkaputt.de/psx-spx.txt + + // Width + if((V & 0x40) == 0x40) + { + resolution_to_change_w = 368; + } + else + { + switch(V & 0x3) + { + case 0x00: + resolution_to_change_w = 256; + break; + case 0x01: + resolution_to_change_w = 320; + break; + case 0x02: + resolution_to_change_w = 512; + break; + case 0x03: + resolution_to_change_w = 640; + break; + } + } + // Height + if ((V & 8) == 8) + { //PAL + if ((V & 32) == 32) {resolution_to_change_h = 576;} //5 + else {resolution_to_change_h = 288;} + } + else + { // NTSC + if ((V & 32) == 32){resolution_to_change_h = 480;} //5 + else {resolution_to_change_h = 240;} + } + + if(prev_resolution_w != resolution_to_change_w || prev_resolution_h != resolution_to_change_h) + { + if(res_change_count < 2) + { + res_change_count += 1; + printf("PSX GPU - Startup resolution change bypass (%d).\n",res_change_count); + native_resolution_vcenter = false; // No need Vertical centering for PSX module. + } + else{ + prev_resolution_w = resolution_to_change_w; // will be used in VIDEO.cpp + prev_resolution_h = resolution_to_change_h; + printf("PSX - GPU register - resolution change to: %dx%d (V=%d)\n",resolution_to_change_w,resolution_to_change_h,V); + resolution_to_change = true; // will be reset in VIDEO.cpp + + } + } +} +// SLK end + void GPU_Init(bool pal_clock_and_tv) { static const int8 dither_table[4][4] = @@ -110,11 +183,25 @@ void GPU_Init(bool pal_clock_and_tv) { GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) hmc_to_visible = 520; + + //SLK + resolution_to_change = true; + resolution_to_change_w = 640; + resolution_to_change_h = 480; + printf("PSX - GPU Init - NTSC mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); + } else // PAL clock { GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) hmc_to_visible = 560; + + //SLK + resolution_to_change = true; + resolution_to_change_w = 640; + resolution_to_change_h = 576; + printf("PSX - GPU Init - PAL mode - resolution set to: %dx%d\n",resolution_to_change_w,resolution_to_change_h); + } memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F)); @@ -879,6 +966,11 @@ MDFN_FASTCALL void GPU_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 case 0x08: //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); DisplayMode = V & 0xFF; + if(PreviousDisplayMode != DisplayMode) // SLK - Trap GPU resolution change + { + PreviousDisplayMode = DisplayMode; + GPU_NewDisplayMode(V); + } break; case 0x09: @@ -1093,8 +1185,13 @@ MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp { static const uint32 DotClockRatios[5] = { 10, 8, 5, 4, 7 }; const uint32 dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); - const uint32 dmw = 2800 / DotClockRatios[dmc]; // Must be <= (768 - 32) - const uint32 dmpa = (2800 - (hide_hoverscan ? 2640 : 2800)) / DotClockRatios[dmc] / 2; // Must be <= 32 + + // Hotdog mod + // const uint32 dmw = 2800 / DotClockRatios[dmc]; // Must be <= (768 - 32) + // const uint32 dmpa = (2800 - (hide_hoverscan ? 2640 : 2800)) / DotClockRatios[dmc] / 2; // Must be <= 32 + const uint32 dmw = 2560 / DotClockRatios[dmc]; // Must be <= (768 - 32) + const uint32 dmpa = 0; + // Hotdog mod - end const uint32 drxbo = 32; int32 sys_clocks = sys_timestamp - lastts; @@ -1342,6 +1439,16 @@ MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp int32 fb_x = DisplayFB_XStart * 2; int32 dx_start = HorizStart, dx_end = HorizEnd; + // Hotdog mod - 384 + int32 actualGameBufferWidth = (HorizEnd - HorizStart) / DotClockRatios[dmc]; + int32 ourBufferWidth = dmw; + + int32 leftOffset = (actualGameBufferWidth - ourBufferWidth) / 2; + //leftOffset *= DotClockRatios[dmc]; // Get back into PSX GPU co-ords. + leftOffset = std::max(leftOffset, 0); // Make sure not negative + dx_start += leftOffset; // Offset the PSX buffer to render relative to our frame. + // + dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; @@ -1351,10 +1458,16 @@ MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp dx_start = dx_start / DotClockRatios[dmc]; dx_end = dx_end / DotClockRatios[dmc]; - dx_start -= hmc_to_visible / DotClockRatios[dmc]; - dx_end -= hmc_to_visible / DotClockRatios[dmc]; - dx_start += 7; - dx_end += 7; + // Hotdogmod + dx_end -= dx_start; + dx_start = -leftOffset; + + // dx_start -= hmc_to_visible / DotClockRatios[dmc]; + // dx_end -= hmc_to_visible / DotClockRatios[dmc]; + // dx_start += 7; + // dx_end += 7; + // Hotdod mod - end + if(dx_start < 0) { diff --git a/src/snes/interface.cpp b/src/snes/interface.cpp index 342efb5..a5c0863 100644 --- a/src/snes/interface.cpp +++ b/src/snes/interface.cpp @@ -71,6 +71,11 @@ static const uint8 ScopeOSCounter_TriggerEndThresh = 2; static std::vector ColorMap; // [32768] +// SLK +int prev_resolution_w; +int prev_resolution_h; +// SLK - end + static void BuildColorMap(MDFN_PixelFormat &format, uint8* CustomColorMap) { for(int x = 0; x < 32768; x++) @@ -546,6 +551,23 @@ static void SetupMisc(bool PAL) MDFNGameInfo->fps = PAL ? 838977920 : 1008307711; MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(32040.5); + // SLK - init. dynamic display video resolution - progressive by default + printf("SNES Interface - Regional mode: %s \n",(PAL ? "PAL" : "NTSC")); + if(PAL) + { + resolution_to_change_h = 288; + } + else + { + printf(" Video mode set to 256 x 240\n"); + resolution_to_change_h = 240; + } + resolution_to_change_w = 256; + resolution_to_change = true; + prev_resolution_w = resolution_to_change_w; + prev_resolution_h = resolution_to_change_h; + // SLK - end + if(!snsf_loader) { EnableHBlend = MDFN_GetSettingB("snes.h_blend"); @@ -890,6 +912,32 @@ static void Emulate(EmulateSpecStruct *espec) bSNES_v059::system.run_mednafen_custom(); bSNES_v059::ppu.enable_renderer(true); + // SLK - guess SNES active resolution + //printf("SNES Interface - Emulate - %dx%d - %d,%d\n",tdr->w,tdr->h,tdr->x,tdr->y); + if(tdr->h > 10 && tdr->w > 10 && tdr->w != prev_resolution_w) + { + resolution_to_change = true; + resolution_to_change_w = tdr->w; + } + if(tdr->h > 10 && tdr->w > 10 && tdr->h != prev_resolution_h) + { + resolution_to_change = true; + if(tdr->h <= 400) + { + resolution_to_change_h = bSNES_v059::system.region() ? 288 : 240; + } + else + { + resolution_to_change_h = bSNES_v059::system.region() ? 576 : 480; + } + } + if(resolution_to_change) + { + //printf("SNES - Interface - Resolution change detected: %dx%d\n",resolution_to_change_w,resolution_to_change_h); + prev_resolution_w = resolution_to_change_w; + prev_resolution_h = tdr->h; + } + // SLK - end // // Blank out any missed lines(for e.g. display height change with PAL emulation) diff --git a/src/snes_faust/ppu.cpp b/src/snes_faust/ppu.cpp index 86ab640..9e59be1 100644 --- a/src/snes_faust/ppu.cpp +++ b/src/snes_faust/ppu.cpp @@ -36,6 +36,10 @@ namespace MDFN_IEN_SNES_FAUST { +// SLK +int prev_resolution_w = 256; +// + static uint32 lastts; static uint32 LineStartTS; @@ -1944,6 +1948,16 @@ static MDFN_HOT void RenderLine(void) uint32* const out_target = es->surface->pixels + (LineTarget * es->surface->pitchinpix); const uint32 w = ((BGMode & 0x7) == 0x5 || (BGMode & 0x7) == 0x6 || (ScreenMode & 0x08)) ? 512 : 256; +// SLK + if(w != prev_resolution_w) + { + resolution_to_change_w = w; + prev_resolution_w = w; + resolution_to_change = true; + } +// SLK - end + + es->LineWidths[LineTarget] = w; // LineTarget++; diff --git a/src/snes_faust/snes.cpp b/src/snes_faust/snes.cpp index 7be0281..d98d25f 100644 --- a/src/snes_faust/snes.cpp +++ b/src/snes_faust/snes.cpp @@ -494,6 +494,21 @@ static MDFN_COLD void Load(GameFile* gf) const bool IsPAL = CART_Init(snsf_loader ? &snsf_loader->ROM_Data : gf->stream, EmulatedSNES_Faust.MD5); CART_LoadNV(); +// SLK - init. dynamic display video resolution - progressive by default + printf("SNES FAUST snes - Regional mode: %s \n",(IsPAL ? "PAL" : "NTSC")); + if(IsPAL) + { + resolution_to_change_h = 288; + } + else + { + printf(" Video mode set to 256 x 240\n"); + resolution_to_change_h = 240; + } + resolution_to_change_w = 256; + resolution_to_change = true; + // SLK - end + DMA_Init(); INPUT_Init(); { diff --git a/src/snes_faust/snes.h b/src/snes_faust/snes.h index 86d6983..f36ed94 100644 --- a/src/snes_faust/snes.h +++ b/src/snes_faust/snes.h @@ -44,6 +44,7 @@ namespace MDFN_IEN_SNES_FAUST { + extern bool MemSelect; DEFREAD(OBRead_XSLOW); diff --git a/src/ss/vdp2_render.cpp b/src/ss/vdp2_render.cpp index f9f0ed4..4a32af4 100644 --- a/src/ss/vdp2_render.cpp +++ b/src/ss/vdp2_render.cpp @@ -145,6 +145,14 @@ static uint8 RBG0CCRatio; static uint8 LineColorCCRatio; static uint8 BackCCRatio; +//SLK +static uint8 prev_InterlaceMode = 0; +static uint8 prev_HRes = 0; +static uint8 prev_VRes = 0; +static bool prev_BorderMode = 0; +// SLK end + + // static struct { @@ -550,6 +558,39 @@ static INLINE void RegsWrite(uint32 A, uint16 V) InterlaceMode = (V >> 6) & 0x3; VRes = (V >> 4) & 0x3; HRes = (V >> 0) & 0x7; + // SLK + if(InterlaceMode != prev_InterlaceMode || HRes != prev_HRes) + { + printf("VDP2 Render - Television mode changed: %d\n",V); + printf(" BorderMode: %d\n",BorderMode); + printf(" PAL: %d\n",PAL); + printf(" InterlaceMode: %d\n",InterlaceMode); + printf(" VRes: %d\n",VRes); + printf(" HRes: %d\n",HRes); + prev_BorderMode = BorderMode; + prev_InterlaceMode = InterlaceMode; + prev_VRes = VRes; + prev_HRes = HRes; + // HRES + switch(HRes){ + case 0: + resolution_to_change_w = 320; + break; + case 1: + resolution_to_change_w = 352; + break; + case 2: + resolution_to_change_w = 640; + break; + case 3: + resolution_to_change_w = 704; + break; + } + if(InterlaceMode >= 2){resolution_to_change_h = PAL ? 576 : 480;} else {resolution_to_change_h = PAL ? 288 : 240;} + printf("SS - VDP2 Render - TV mode set to %dx%d",resolution_to_change_w,resolution_to_change_h); + resolution_to_change = true; // Flag for video resolution change by VIDEO.cpp/MAIN.cpp + } + // SLK - end break; case 0x02: @@ -3293,12 +3334,20 @@ void VDP2REND_SetGetVideoParams(MDFNGI* gi, const bool caspect, const int sls, c { gi->nominal_width = (ShowHOverscan ? 365 : 354); gi->fb_height = 576; + resolution_to_change_h = 288; // SLK - init crt mode } else { gi->nominal_width = (ShowHOverscan ? 302 : 292); gi->fb_height = 480; + resolution_to_change_h = 240; // SLK - init crt mode } + // SLK + resolution_to_change_w = 320; + resolution_to_change = true; // SLK - init crt mode + // SLK - end + + gi->nominal_height = LineVisLast + 1 - LineVisFirst; gi->lcm_width = (ShowHOverscan? 10560 : 10240); diff --git a/src/state.cpp b/src/state.cpp index f6104b8..fa4e533 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -469,6 +469,14 @@ void MDFNSS_SaveSM(Stream *st, bool data_only, const MDFN_Surface *surface, cons neowidth = MDFNGameInfo->nominal_width; neoheight = MDFNGameInfo->nominal_height; + // SLK - Approximation to prevent SaveState snapshot corruption + if(use_super_resolution) + { + neowidth = resolution_to_change_w; + neoheight = DisplayRect->h; + } + // SLK - end + if(LineWidths[0] != ~0) { int32 first_w = LineWidths[DisplayRect->y]; @@ -856,7 +864,9 @@ bool MDFNI_LoadState(const char *fname, const char *suffix) noexcept MDFN_Error* me = dynamic_cast(&e); if(!fname && !suffix) - MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); + // SLK + // MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d load error: %s"), CurrentState, e.what()); + MDFN_Notify(MDFN_NOTICE_ERROR, _("State %d not found."), CurrentState); // SLK - shorten message to fit low-res rendering else { // FIXME: Autosave kludgery, refactor interfaces in the future to make cleaner.