From 3eede898a3ad31ebfd844a136f4adf96464c69e1 Mon Sep 17 00:00:00 2001 From: ketmar Date: Wed, 25 May 2022 07:38:39 +0000 Subject: [PATCH] added "vid_scale" command FossilOrigin-Name: e4bfae1f6716623d3e4e6bc36bac34bb6d6e76df96561c91a62cfe913e2d68a9 --- dox/zxemut_console.txt | 9 ++++ src/ZXEmuT/jimapi.c | 42 +++++++++++++++++ src/ZXEmuT/libvideo/video.c | 109 ++++++++++++++++++++++++++++++++++++++++++-- src/ZXEmuT/libvideo/video.h | 2 + tcl/init/concmd.tcl | 1 + 5 files changed, 159 insertions(+), 4 deletions(-) diff --git a/dox/zxemut_console.txt b/dox/zxemut_console.txt index 79a090e..28e2966 100644 --- a/dox/zxemut_console.txt +++ b/dox/zxemut_console.txt @@ -746,6 +746,15 @@ second one. returns number of t-states +vid_scale +========= +set window scale. +usage: + vid_scale [1..4] + +returns old scale. + + ZX Spectrum Key Names ===================== diff --git a/src/ZXEmuT/jimapi.c b/src/ZXEmuT/jimapi.c index 51d6e63..2ec4071 100644 --- a/src/ZXEmuT/jimapi.c +++ b/src/ZXEmuT/jimapi.c @@ -117,6 +117,46 @@ JIMAPI_FN(softload) { } +//////////////////////////////////////////////////////////////////////////////// +// vid_scale num +JIMAPI_FN(vid_scale) { + if (jimapiWantsCompletion(interp, argc, argv)) { + Jim_Obj *res = Jim_NewStringObj(interp, Jim_String(argv[0]), -1); + //char *a0 = completeAbbrev((argc > 1 ? Jim_String(argv[1]) : ""), "keep", NULL); + jimapiStrAppendAbbrev(interp, res, ""); + //free(a0); + jimapiAppendRestArgs(res, 2); + Jim_SetResult(interp, res); + return JIM_OK; + } + + if (argc > 2) { + jim_SetResStrf(interp, "%s: wut?!", Jim_String(argv[0])); + return JIM_ERR; + } + + // return old value + Jim_SetResultInt(interp, vidScale); + + // set new value + if (argc > 1) { + int newval = jimGetIntVal(interp, argv[1]); + if (newval == JIM_INVALID_INTVAL) { + jim_SetResStrf(interp, "%s: invalid numeric value: '%s'", Jim_String(argv[0]), Jim_String(argv[1])); + return JIM_ERR; + } + if (newval < 1 || newval > 4) { + jim_SetResStrf(interp, "%s: scale value out of bounds: '%s'", Jim_String(argv[0]), Jim_String(argv[1])); + return JIM_ERR; + } + vidScale = newval; + updateScale(); + } + + return JIM_OK; +} + + // quit JIMAPI_FN(quit) { if (jimapiDisableCompletion(interp, argc, argv)) return JIM_OK; @@ -2468,6 +2508,8 @@ void jimInit (void) { jimEvalFile("jimstd/0init.tcl", 0); #endif + JIMAPI_REGISTER(vid_scale); + JIMAPI_REGISTER(quit); JIMAPI_REGISTER(zxbind); JIMAPI_REGISTER(zxunbind); diff --git a/src/ZXEmuT/libvideo/video.c b/src/ZXEmuT/libvideo/video.c index 6b8c11d..1b099f0 100644 --- a/src/ZXEmuT/libvideo/video.c +++ b/src/ZXEmuT/libvideo/video.c @@ -37,7 +37,8 @@ KeyCB keyCB = NULL; MouseCB mouseCB = NULL; MouseButtonCB mouseButtonCB = NULL; WindowActivationCB windowActivationCB = NULL; - +int vidScale = 3; // 1, 2, 3, 4; default is 3 +static int actualScale; static void screenFlip (void); @@ -314,9 +315,12 @@ void rebuildPalette (void) { static void lvCreateSurfaces (void) { if (optFullscreen) { screenReal = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE | SDL_FULLSCREEN); + actualScale = 2; screen = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 240, screenReal->format->BitsPerPixel, screenReal->format->Rmask, screenReal->format->Gmask, screenReal->format->Bmask, 0); } else { - screenReal = SDL_SetVideoMode(320*3, 240*3, 32, SDL_SWSURFACE/*|SDL_DOUBLEBUF*/); + actualScale = vidScale; + if (actualScale < 1) actualScale = 1; else if (actualScale > 4) actualScale = 4; + screenReal = SDL_SetVideoMode(320*actualScale, 240*actualScale, 32, SDL_SWSURFACE/*|SDL_DOUBLEBUF*/); screen = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 240, screenReal->format->BitsPerPixel, screenReal->format->Rmask, screenReal->format->Gmask, screenReal->format->Bmask, 0); } if (screen == NULL) { @@ -348,6 +352,7 @@ void initVideo (void) { void switchFullScreen (void) { + const int needInit = !!screen; #if 0 if (optFullscreen) { screenReal = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE/*|SDL_DOUBLEBUF*/); @@ -362,9 +367,19 @@ void switchFullScreen (void) { #else if (screen) { SDL_FreeSurface(screen); screen = NULL; } optFullscreen = !optFullscreen; - lvCreateSurfaces(); + if (needInit) lvCreateSurfaces(); #endif - screenFlip(); + if (needInit) screenFlip(); +} + + +void updateScale (void) { + const int needInit = !!screen; + if (screen) { SDL_FreeSurface(screen); screen = NULL; } + if (needInit) { + lvCreateSurfaces(); + screenFlip(); + } } @@ -598,6 +613,64 @@ static inline Uint32 fixColor (Uint32 clr) { //////////////////////////////////////////////////////////////////////////////// +static void Blit4xInternal (void) { + const Uint32 *scrB = screen->pixels; // 320x240 + Uint32 *scrR = screenReal->pixels; // 1280x960 + for (int y = 0; y < screen->h; ++y) { + const Uint32 *s = scrB; + Uint32 *d0 = scrR; + Uint32 *d1 = (Uint32 *)((Uint8 *)d0+screenReal->pitch); + Uint32 *d2 = (Uint32 *)((Uint8 *)d1+screenReal->pitch); + Uint32 *d3 = (Uint32 *)((Uint8 *)d2+screenReal->pitch); + for (int x = 0; x < screen->w; ++x) { + const Uint32 clr = fixColor(*s++); + d0[0] = d0[1] = d0[2] = d0[3] = clr; + d1[0] = d1[1] = d1[2] = d1[3] = clr; + d2[0] = d2[1] = d2[2] = d2[3] = clr; + d3[0] = d3[1] = d3[2] = d3[3] = clr; + d0 += 4; + d1 += 4; + d2 += 4; + d3 += 4; + } + scrB = (Uint32 *)((Uint8 *)scrB+screen->pitch); + scrR = (Uint32 *)((Uint8 *)scrR+screenReal->pitch*4); + } +} + + +static void TV4xInternal (void) { + Uint32 *scrR = screenReal->pixels; // 1280x960 + scrR = (Uint32 *)((Uint8 *)scrR+screenReal->pitch); + for (int y = screenReal->h/2; y--; scrR = (Uint32 *)((Uint8 *)scrR+screenReal->pitch*2)) { + Uint32 *d0 = scrR; + for (int x = 0; x < screen->w; ++x) { + const Uint32 c0 = *d0; + Uint32 c1 = (((c0&0x00ff00ff)*7)>>3)&0x00ff00ff; + c1 |= (((c0&0x0000ff00)*7)>>3)&0x0000ff00; + d0[0] = d0[1] = d0[2] = d0[3] = c1; + d0 += 4; + } + } +} + + +static void Blit4x (void) { + int needUnlock = (SDL_MUSTLOCK(screenReal)) ? SDL_LockSurface(screenReal) == 0 : 0; + Blit4xInternal(); + if (needUnlock) SDL_UnlockSurface(screenReal); +} + + +static void Blit4xTV (void) { + const int needUnlock = (SDL_MUSTLOCK(screenReal)) ? SDL_LockSurface(screenReal) == 0 : 0; + /*FIXME: make this faster!*/ + Blit4xInternal(); + TV4xInternal(); + if (needUnlock) SDL_UnlockSurface(screenReal); +} + + static void Blit3xInternal (void) { const Uint32 *scrB = screen->pixels; // 320x240 Uint32 *scrR = screenReal->pixels; // 960x720 @@ -697,6 +770,25 @@ static void Blit2xTV (void) { } +static void Blit1x (void) { + const int needUnlock = (SDL_MUSTLOCK(screenReal)) ? SDL_LockSurface(screenReal) == 0 : 0; + const Uint32 *scrB = screen->pixels; // 320x240 + Uint32 *scrR = screenReal->pixels; // 320x240 + for (int y = 0; y < screen->h; ++y) { + const Uint32 *s = scrB; + Uint32 *d = scrR; + for (int x = 0; x < screen->w; ++x) { + const Uint32 clr = fixColor(*s++); + d[0] = clr; + d += 1; + } + scrB = (Uint32 *)((Uint8 *)scrB+screen->pitch); + scrR = (Uint32 *)((Uint8 *)scrR+screenReal->pitch); + } + if (needUnlock) SDL_UnlockSurface(screenReal); +} + + static void screenFlip (void) { /* lockSurface(&frameSfcLock, screen); @@ -705,11 +797,20 @@ static void screenFlip (void) { */ // if (screenReal != NULL) { + /* if (!optFullscreen) { if (optTVScaler) Blit3xTV(); else Blit3x(); } else { if (optTVScaler > 1 || (optTVScaler && !optFullscreen)) Blit2xTV(); else Blit2x(); } + */ + switch (actualScale) { + case 1: Blit1x(); break; + case 2: if (optTVScaler) Blit2xTV(); else Blit2x(); break; + case 3: if (optTVScaler) Blit3xTV(); else Blit3x(); break; + case 4: if (optTVScaler) Blit4xTV(); else Blit4x(); break; + default: __builtin_trap(); + } SDL_Flip(screenReal); } else { SDL_Flip(screen); diff --git a/src/ZXEmuT/libvideo/video.h b/src/ZXEmuT/libvideo/video.h index 9d5320d..1612d32 100644 --- a/src/ZXEmuT/libvideo/video.h +++ b/src/ZXEmuT/libvideo/video.h @@ -71,6 +71,7 @@ extern int msAutoTresholdX, msAutoTresholdY; //////////////////////////////////////////////////////////////////////////////// extern int optFullscreen; extern int optTVScaler; +extern int vidScale; // 1, 2, 3, 4; default is 3 extern SDL_Surface *screen; // always 32bpp extern SDL_Surface *screenReal; // always 32bpp extern Uint32 palette[256]; // converted for frameSfc @@ -102,6 +103,7 @@ extern int64_t timerGetMicroSeconds (void); // microseconds extern void sdlInit (void); extern void initVideo (void); extern void switchFullScreen (void); +extern void updateScale (void); extern void rebuildPalette (void); diff --git a/tcl/init/concmd.tcl b/tcl/init/concmd.tcl index 390d97b..2f7f95e 100644 --- a/tcl/init/concmd.tcl +++ b/tcl/init/concmd.tcl @@ -215,6 +215,7 @@ concmdlist-register concmd_simple_command { memcontention useplus3 scrattrfill + vid_scale } # result is always printed -- 2.11.4.GIT