Skip to content

Commit ff21085

Browse files
committed
[JK2SP] save files have screenshots again
Breaks save compatibility with earlier OpenJO versions.
1 parent a3c29cd commit ff21085

File tree

17 files changed

+328
-128
lines changed

17 files changed

+328
-128
lines changed

code/client/cl_scrn.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,9 +584,10 @@ void SCR_SetScreenshot(const byte *pbData, int w, int h)
584584
}
585585

586586

587+
#ifdef JK2_MODE
587588
// This is just a client-side wrapper for the function RE_TempRawImage_ReadFromFile() in the renderer code...
588589
//
589-
/*
590+
590591
byte* SCR_TempRawImage_ReadFromFile(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip)
591592
{
592593
return re.TempRawImage_ReadFromFile(psLocalFilename, piWidth, piHeight, pbReSampleBuffer, qbVertFlip);
@@ -598,5 +599,6 @@ void SCR_TempRawImage_CleanUp()
598599
{
599600
re.TempRawImage_CleanUp();
600601
}
601-
*/
602+
#endif
603+
602604

code/client/cl_ui.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ int PC_ReadTokenHandle(int handle, struct pc_token_s *pc_token);
3131
intptr_t CL_UISystemCalls( intptr_t *args );
3232

3333
//prototypes
34+
#ifdef JK2_MODE
35+
extern qboolean SG_GetSaveImage( const char *psPathlessBaseName, void *pvAddress );
36+
#endif
3437
extern int SG_GetSaveGameComment(const char *psPathlessBaseName, char *sComment, char *sMapName);
3538
extern qboolean SG_GameAllowedToSaveHere(qboolean inCamera);
3639
extern void SG_StoreSaveGameComment(const char *sComment);
@@ -241,14 +244,18 @@ void CL_InitUI( void ) {
241244
uii.Language_UsesSpaces = re.Language_UsesSpaces;
242245
uii.AnyLanguage_ReadCharFromString = re.AnyLanguage_ReadCharFromString;
243246

244-
//uii.SG_GetSaveImage = SG_GetSaveImage;
247+
#ifdef JK2_MODE
248+
uii.SG_GetSaveImage = SG_GetSaveImage;
249+
#endif
245250
uii.SG_GetSaveGameComment = SG_GetSaveGameComment;
246251
uii.SG_StoreSaveGameComment = SG_StoreSaveGameComment;
247252
uii.SG_GameAllowedToSaveHere= SG_GameAllowedToSaveHere;
248253

249254
//uii.SCR_GetScreenshot = SCR_GetScreenshot;
250255

251-
//uii.DrawStretchRaw = re.DrawStretchRaw;
256+
#ifdef JK2_MODE
257+
uii.DrawStretchRaw = re.DrawStretchRaw;
258+
#endif
252259
uii.R_ClearScene = re.ClearScene;
253260
uii.R_AddRefEntityToScene = re.AddRefEntityToScene;
254261
uii.R_AddPolyToScene = re.AddPolyToScene;
@@ -261,6 +268,10 @@ void CL_InitUI( void ) {
261268
uii.R_DrawStretchPic = re.DrawStretchPic;
262269
uii.UpdateScreen = SCR_UpdateScreen;
263270

271+
#ifdef JK2_MODE
272+
uii.PrecacheScreenshot = SCR_PrecacheScreenshot;
273+
#endif
274+
264275
uii.R_LerpTag = re.LerpTag;
265276

266277
uii.S_StartLocalLoopingSound= S_StartLocalLoopingSound;

code/client/client.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor,
371371
void SCR_DrawBigChar( int x, int y, int ch );
372372
void SCR_DrawSmallChar( int x, int y, int ch );
373373

374+
#ifdef JK2_MODE
375+
void SCR_PrecacheScreenshot();
376+
#endif
377+
374378
//
375379
// cl_cin.c
376380
//

code/qcommon/common.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ do the apropriate things.
239239
=============
240240
*/
241241
void SG_Shutdown();
242+
#ifdef JK2_MODE
243+
extern void SCR_UnprecacheScreenshot();
244+
#endif
242245
void QDECL Com_Error( int code, const char *fmt, ... ) {
243246
va_list argptr;
244247
static int lastErrorTime;
@@ -267,6 +270,10 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
267270
}
268271
lastErrorTime = currentTime;
269272

273+
#ifdef JK2_MODE
274+
SCR_UnprecacheScreenshot();
275+
#endif
276+
270277
va_start (argptr,fmt);
271278
Q_vsnprintf (com_errorMessage, sizeof(com_errorMessage), fmt, argptr);
272279
va_end (argptr);

code/qcommon/qcommon.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,11 @@ qboolean Sys_CopyFile(const char *lpExistingFileName, const char *lpNewFileName,
850850

851851

852852
byte* SCR_GetScreenshot(qboolean *qValid);
853+
#ifdef JK2_MODE
854+
void SCR_SetScreenshot(const byte *pbData, int w, int h);
855+
byte* SCR_TempRawImage_ReadFromFile(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip);
856+
void SCR_TempRawImage_CleanUp();
857+
#endif
853858

854859
inline int Round(float value)
855860
{

code/rd-common/tr_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ void LoadJPG( const char *filename, byte **pic, int *width, int *height );
4545
// Load raw image data from PNG image.
4646
void LoadPNG( const char *filename, byte **data, int *width, int *height );
4747

48+
#ifdef JK2_MODE
49+
//Load raw image data from JPEG input.
50+
void LoadJPGFromBuffer( byte *inputBuffer, size_t len, byte **pic, int *width, int *height );
51+
#endif
4852

4953
/*
5054
================================================================================

code/rd-common/tr_image_jpg.cpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,157 @@ void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height
204204
/* And we're done! */
205205
}
206206

207+
#ifdef JK2_MODE
208+
void LoadJPGFromBuffer( byte *inputBuffer, size_t len, unsigned char **pic, int *width, int *height ) {
209+
/* This struct contains the JPEG decompression parameters and pointers to
210+
* working space (which is allocated as needed by the JPEG library).
211+
*/
212+
struct jpeg_decompress_struct cinfo = { NULL };
213+
/* We use our private extension JPEG error handler.
214+
* Note that this struct must live as long as the main JPEG parameter
215+
* struct, to avoid dangling-pointer problems.
216+
*/
217+
/* This struct represents a JPEG error handler. It is declared separately
218+
* because applications often want to supply a specialized error handler
219+
* (see the second half of this file for an example). But here we just
220+
* take the easy way out and use the standard error handler, which will
221+
* print a message on stderr and call exit() if compression fails.
222+
* Note that this struct must live as long as the main JPEG parameter
223+
* struct, to avoid dangling-pointer problems.
224+
*/
225+
struct jpeg_error_mgr jerr;
226+
/* More stuff */
227+
JSAMPARRAY buffer; /* Output row buffer */
228+
unsigned int row_stride; /* physical row width in output buffer */
229+
unsigned int pixelcount, memcount;
230+
unsigned int sindex, dindex;
231+
byte *out;
232+
byte *buf;
233+
234+
if (!inputBuffer) {
235+
return;
236+
}
237+
238+
/* Step 1: allocate and initialize JPEG decompression object */
239+
240+
/* We have to set up the error handler first, in case the initialization
241+
* step fails. (Unlikely, but it could happen if you are out of memory.)
242+
* This routine fills in the contents of struct jerr, and returns jerr's
243+
* address which we place into the link field in cinfo.
244+
*/
245+
cinfo.err = jpeg_std_error(&jerr);
246+
cinfo.err->error_exit = R_JPGErrorExit;
247+
cinfo.err->output_message = R_JPGOutputMessage;
248+
249+
/* Now we can initialize the JPEG decompression object. */
250+
jpeg_create_decompress(&cinfo);
251+
252+
/* Step 2: specify data source (eg, a file) */
253+
254+
jpeg_mem_src(&cinfo, inputBuffer, len);
255+
256+
/* Step 3: read file parameters with jpeg_read_header() */
257+
258+
(void) jpeg_read_header(&cinfo, TRUE);
259+
/* We can ignore the return value from jpeg_read_header since
260+
* (a) suspension is not possible with the stdio data source, and
261+
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
262+
* See libjpeg.doc for more info.
263+
*/
264+
265+
/* Step 4: set parameters for decompression */
266+
267+
268+
/* Make sure it always converts images to RGB color space. This will
269+
* automatically convert 8-bit greyscale images to RGB as well. */
270+
cinfo.out_color_space = JCS_RGB;
271+
272+
/* Step 5: Start decompressor */
273+
274+
(void) jpeg_start_decompress(&cinfo);
275+
/* We can ignore the return value since suspension is not possible
276+
* with the stdio data source.
277+
*/
278+
279+
/* We may need to do some setup of our own at this point before reading
280+
* the data. After jpeg_start_decompress() we have the correct scaled
281+
* output image dimensions available, as well as the output colormap
282+
* if we asked for color quantization.
283+
* In this example, we need to make an output work buffer of the right size.
284+
*/
285+
/* JSAMPLEs per row in output buffer */
286+
pixelcount = cinfo.output_width * cinfo.output_height;
287+
288+
if(!cinfo.output_width || !cinfo.output_height
289+
|| ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height
290+
|| pixelcount > 0x1FFFFFFF || cinfo.output_components != 3
291+
)
292+
{
293+
// Free the memory to make sure we don't leak memory
294+
jpeg_destroy_decompress(&cinfo);
295+
296+
ri.Printf( PRINT_ALL, "LoadJPG: invalid image format: %dx%d*4=%d, components: %d",
297+
cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components);
298+
return;
299+
}
300+
301+
memcount = pixelcount * 4;
302+
row_stride = cinfo.output_width * cinfo.output_components;
303+
304+
out = (byte *)Z_Malloc(memcount, TAG_TEMP_WORKSPACE, qfalse);
305+
306+
*width = cinfo.output_width;
307+
*height = cinfo.output_height;
308+
309+
/* Step 6: while (scan lines remain to be read) */
310+
/* jpeg_read_scanlines(...); */
311+
312+
/* Here we use the library's state variable cinfo.output_scanline as the
313+
* loop counter, so that we don't have to keep track ourselves.
314+
*/
315+
while (cinfo.output_scanline < cinfo.output_height) {
316+
/* jpeg_read_scanlines expects an array of pointers to scanlines.
317+
* Here the array is only one element long, but you could ask for
318+
* more than one scanline at a time if that's more convenient.
319+
*/
320+
buf = ((out+(row_stride*cinfo.output_scanline)));
321+
buffer = &buf;
322+
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
323+
}
324+
325+
buf = out;
326+
// Expand from RGB to RGBA
327+
sindex = pixelcount * cinfo.output_components;
328+
dindex = memcount;
329+
330+
do {
331+
buf[--dindex] = 255;
332+
buf[--dindex] = buf[--sindex];
333+
buf[--dindex] = buf[--sindex];
334+
buf[--dindex] = buf[--sindex];
335+
} while(sindex);
336+
337+
*pic = out;
338+
339+
/* Step 7: Finish decompression */
340+
341+
(void) jpeg_finish_decompress(&cinfo);
342+
/* We can ignore the return value since suspension is not possible
343+
* with the stdio data source.
344+
*/
345+
346+
/* Step 8: Release JPEG decompression object */
347+
348+
/* This is an important step since it will release a good deal of memory. */
349+
jpeg_destroy_decompress(&cinfo);
350+
351+
/* At this point you may want to check to see whether any corrupt-data
352+
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
353+
*/
354+
355+
/* And we're done! */
356+
}
357+
#endif
207358

208359
/* Expanded data destination object for stdio output */
209360

code/rd-common/tr_public.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ typedef struct {
206206

207207
// for use with save-games mainly...
208208
void (*GetScreenShot)(byte *data, int w, int h);
209+
210+
#ifdef JK2_MODE
211+
size_t (*SaveJPGToBuffer)(byte *buffer, size_t bufSize, int quality, int image_width, int image_height, byte *image_buffer, int padding );
212+
void (*LoadJPGFromBuffer)( byte *inputBuffer, size_t len, byte **pic, int *width, int *height );
213+
#endif
209214

210215
// this is so you can get access to raw pixels from a graphics format (TGA/JPG/BMP etc),
211216
// currently only the save game uses it (to make raw shots for the autosaves)

0 commit comments

Comments
 (0)