diff options
| author | Nicolas Pomarède <npomarede@corp.free.fr> | 2024-01-16 22:12:29 (GMT) |
|---|---|---|
| committer | Nicolas Pomarède <npomarede@corp.free.fr> | 2024-01-16 22:12:29 (GMT) |
| commit | dd0c3b993ad068a9323ebf3c735bf5935febad68 (patch) | |
| tree | f583ef3f154842b7287d9a663505c822d371be4e | |
| parent | 3f6874f39896a9fe0b4f0c95ba70fee5d5abb61f (diff) | |
| download | hatari-dd0c3b993ad068a9323ebf3c735bf5935febad68.zip hatari-dd0c3b993ad068a9323ebf3c735bf5935febad68.tar.gz | |
NEO direct video memory dump option for screen snapshot (patch by Brad Smith)
This needs to be enabled via Config.bNEOScreenSnapShot=TRUE (no UI added for it)
Notes from Brad Smith (https://github.com/hatari/hatari/pull/31 for more details) :
This creates a NEO file format screenshot, out of the data in FrameBuffer (screen.c).
This works for ST low, medium, and high resolutions. The palette is taken
from the centre line of the FrameBuffer for Low and Medium resolutions.
For High resolution don't seem to store per-line palette, but I instead extracted
the GenConvert palette for it.
| -rw-r--r-- | src/configuration.c | 2 | ||||
| -rw-r--r-- | src/includes/configuration.h | 1 | ||||
| -rw-r--r-- | src/includes/screen.h | 1 | ||||
| -rw-r--r-- | src/includes/screenConvert.h | 1 | ||||
| -rw-r--r-- | src/screen.c | 4 | ||||
| -rw-r--r-- | src/screenConvert.c | 5 | ||||
| -rw-r--r-- | src/screenSnapShot.c | 78 |
7 files changed, 91 insertions, 1 deletions
diff --git a/src/configuration.c b/src/configuration.c index 390ca2c..5bce1c5 100644 --- a/src/configuration.c +++ b/src/configuration.c @@ -97,6 +97,7 @@ static const struct Config_Tag configs_Screen[] = { "nMaxHeight", Int_Tag, &ConfigureParams.Screen.nMaxHeight }, { "nZoomFactor", Float_Tag, &ConfigureParams.Screen.nZoomFactor }, { "bUseSdlRenderer", Bool_Tag, &ConfigureParams.Screen.bUseSdlRenderer }, + { "bNEOScreenSnapShot", Bool_Tag, &ConfigureParams.Screen.bNEOScreenSnapShot }, { "bUseVsync", Bool_Tag, &ConfigureParams.Screen.bUseVsync }, { NULL , Error_Tag, NULL } }; @@ -753,6 +754,7 @@ void Configuration_SetDefault(void) ConfigureParams.Screen.nZoomFactor = 1.0; ConfigureParams.Screen.bUseSdlRenderer = true; ConfigureParams.Screen.bUseVsync = false; + ConfigureParams.Screen.bNEOScreenSnapShot = false; /* Set defaults for Sound */ ConfigureParams.Sound.bEnableMicrophone = true; diff --git a/src/includes/configuration.h b/src/includes/configuration.h index 3fc25c4..55289bc 100644 --- a/src/includes/configuration.h +++ b/src/includes/configuration.h @@ -310,6 +310,7 @@ typedef struct bool bResizable; bool bUseVsync; bool bUseSdlRenderer; + bool bNEOScreenSnapShot; float nZoomFactor; int nSpec512Threshold; int nVdiColors; diff --git a/src/includes/screen.h b/src/includes/screen.h index 85bad0e..8066185 100644 --- a/src/includes/screen.h +++ b/src/includes/screen.h @@ -100,6 +100,7 @@ extern uint16_t HBLPalettes[HBL_PALETTE_LINES]; extern uint16_t *pHBLPalettes; extern uint32_t HBLPaletteMasks[HBL_PALETTE_MASKS]; extern uint32_t *pHBLPaletteMasks; +extern int STScreenLineOffset[NUM_VISIBLE_LINES]; extern void Screen_Init(void); extern void Screen_UnInit(void); diff --git a/src/includes/screenConvert.h b/src/includes/screenConvert.h index 04b7c45..33df05a 100644 --- a/src/includes/screenConvert.h +++ b/src/includes/screenConvert.h @@ -7,6 +7,7 @@ void Screen_RemapPalette(void); void Screen_SetPaletteColor(Uint8 idx, Uint8 red, Uint8 green, Uint8 blue); +SDL_Color Screen_GetPaletteColor(Uint8 idx); void ScreenConv_MemorySnapShot_Capture(bool bSave); void Screen_GenConvert(uint32_t vaddr, void *fvram, int vw, int vh, diff --git a/src/screen.c b/src/screen.c index 90664a1..4f90a6e 100644 --- a/src/screen.c +++ b/src/screen.c @@ -96,7 +96,7 @@ static int PCScreenOffsetX; /* how many pixels to skip from left when dr static int PCScreenOffsetY; /* how many pixels to skip from top when drawing */ static SDL_Rect STScreenRect; /* screen size without statusbar */ -static int STScreenLineOffset[NUM_VISIBLE_LINES]; /* Offsets for ST screen lines eg, 0,160,320... */ +int STScreenLineOffset[NUM_VISIBLE_LINES]; /* Offsets for ST screen lines eg, 0,160,320... */ static Uint16 HBLPalette[16], PrevHBLPalette[16]; /* Current palette for line, also copy of first line */ static void (*ScreenDrawFunctionsNormal[3])(void); /* Screen draw functions */ @@ -752,6 +752,8 @@ void Screen_UnInit(void) /* Free memory used for copies */ free(FrameBuffer.pSTScreen); free(FrameBuffer.pSTScreenCopy); + FrameBuffer.pSTScreen = NULL; + FrameBuffer.pSTScreenCopy = NULL; Screen_FreeSDL2Resources(); if (sdlWindow) diff --git a/src/screenConvert.c b/src/screenConvert.c index 84f2e32..a6d23fe 100644 --- a/src/screenConvert.c +++ b/src/screenConvert.c @@ -50,6 +50,11 @@ void Screen_SetPaletteColor(Uint8 idx, Uint8 red, Uint8 green, Uint8 blue) palette.native[idx] = SDL_MapRGB(sdlscrn->format, red, green, blue); } +SDL_Color Screen_GetPaletteColor(Uint8 idx) +{ + return palette.standard[idx]; +} + void Screen_RemapPalette(void) { int i; diff --git a/src/screenSnapShot.c b/src/screenSnapShot.c index 92dde48..6858583 100644 --- a/src/screenSnapShot.c +++ b/src/screenSnapShot.c @@ -17,6 +17,7 @@ const char ScreenSnapShot_fileid[] = "Hatari screenSnapShot.c"; #include "log.h" #include "paths.h" #include "screen.h" +#include "screenConvert.h" #include "screenSnapShot.h" #include "statusbar.h" #include "video.h" @@ -29,6 +30,7 @@ const char ScreenSnapShot_fileid[] = "Hatari screenSnapShot.c"; static int nScreenShots = 0; /* Number of screen shots saved */ +static Uint8 NEOHeader[128]; /*-----------------------------------------------------------------------*/ @@ -293,6 +295,66 @@ png_cleanup: } #endif +/** + * Helper for writing NEO file header + */ +static void StoreU16NEO(Uint16 val, int offset) +{ + NEOHeader[offset+0] = (val >> 8) & 0xFF; + NEOHeader[offset+1] = (val >> 0) & 0xFF; +} + +/** + * Save direct video memory dump to NEO file + */ +static int ScreenSnapShot_SaveNEO(const char *filename) +{ + FILE *fp = NULL; + int i, res, sw, sh, stride, offset; + + if (pFrameBuffer == NULL || pFrameBuffer->pSTScreen == NULL) + return -1; + + fp = fopen(filename, "wb"); + if (!fp) + return -1; + + res = (STRes == ST_HIGH_RES) ? 2 : + (STRes == ST_MEDIUM_RES) ? 1 : + 0; + sw = (res > 0) ? 640 : 320; + sh = (res > 1) ? 400 : 200; + stride = (res > 1) ? 80 : 160; + + memset(NEOHeader, 0, sizeof(NEOHeader)); + StoreU16NEO(res, 2); + if (res != 2) /* Low/Medium resolution: use middle line's palette for whole image. */ + { + for (i=0; i<16; i++) + StoreU16NEO(pFrameBuffer->HBLPalettes[i+((OVERSCAN_TOP+sh/2)<<4)], 4+(2*i)); + } + else /* High resolution: use stored GenConvert RGB palette. */ + { + for (i=0; i<2;i++) + StoreU16NEO((Screen_GetPaletteColor(i).r >= 128) ? 0x777 : 0x000, 4+(2*i)); + } + memcpy(NEOHeader+36," . ",12); + StoreU16NEO(sw, 58); + StoreU16NEO(sh, 60); + + fwrite(NEOHeader, 1, 128, fp); + for (i = 0; i < sh; i++) + { + offset = (res > 1) ? + (SCREENBYTES_MONOLINE * i) : + (STScreenLineOffset[i+OVERSCAN_TOP] + SCREENBYTES_LEFT); + fwrite(pFrameBuffer->pSTScreen + offset, 1, stride, fp); + } + + fclose (fp); + return 1; /* >0 if OK, -1 if error */ +} + /*-----------------------------------------------------------------------*/ /** @@ -309,6 +371,17 @@ void ScreenSnapShot_SaveScreen(void) ScreenSnapShot_GetNum(); /* Create our filename */ nScreenShots++; + /* NEO memory dump */ + if (ConfigureParams.Screen.bNEOScreenSnapShot) + { + sprintf(szFileName,"%s/grab%4.4d.neo", Paths_GetScreenShotDir(), nScreenShots); + if (ScreenSnapShot_SaveNEO(szFileName) > 0) + fprintf(stderr, "Screen dump saved to: %s\n", szFileName); + else + fprintf(stderr, "NEO screen dump failed!\n"); + free(szFileName); + return; + } #if HAVE_LIBPNG /* try first PNG */ sprintf(szFileName,"%s/grab%4.4d.png", Paths_GetScreenShotDir(), nScreenShots); @@ -352,6 +425,11 @@ void ScreenSnapShot_SaveToFile(const char *szFileName) success = SDL_SaveBMP(sdlscrn, szFileName) == 0; } else + if (File_DoesFileExtensionMatch(szFileName, ".neo")) + { + success = ScreenSnapShot_SaveNEO(szFileName) == 0; + } + else { fprintf(stderr, "ERROR: unknown screen dump file name extension: %s\n", szFileName); return; |
