Skip to content

Commit

Permalink
tr2/screenshots: improve screenshots support
Browse files Browse the repository at this point in the history
Resolves #1766.
Resolves #1773.
  • Loading branch information
rr- committed Oct 28, 2024
1 parent 535a502 commit da94642
Show file tree
Hide file tree
Showing 36 changed files with 357 additions and 402 deletions.
3 changes: 3 additions & 0 deletions docs/tr2/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr2-0.5...develop) - ××××-××-××
- improved FMV mode appearance - removed black scanlines (#1729)
- improved FMV mode behavior - stopped switching screen resolutions (#1729)
- improved screenshots: now saved in the screenshots/ directory with level titles and timestamps as JPG or PNG, similar to TR1X (#1773)
- improved switch object names
- Switch Type 1 renamed to "Airlock Switch"
- Switch Type 2 renamed to "Small Switch"
- Switch Type 3 renamed to "Switch Button"
- Switch Type 4 renamed to "Lever/Switch"
- Switch Type 5 renamed to "Underwater Lever/Switch"
- fixed screenshots not working in windowed mode (#1766)
- fixed screenshots key not getting debounced (#1773)
- fixed `/give` not working with weapons (regression from 0.5)
- fixed the camera being cut off after using the gong hammer in Ice Palace (#1580)
- fixed the audio not being in sync when Lara strikes the gong in Ice Palace (#1725)
Expand Down
15 changes: 15 additions & 0 deletions src/libtrx/game/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "game/clock.h"

#include <stdio.h>
#include <time.h>

size_t Clock_GetDateTime(char *const buffer, const size_t size)
{
time_t lt = time(0);
struct tm *tptr = localtime(&lt);

return snprintf(
buffer, size, "%04d%02d%02d_%02d%02d%02d", tptr->tm_year + 1900,
tptr->tm_mon + 1, tptr->tm_mday, tptr->tm_hour, tptr->tm_min,
tptr->tm_sec);
}
3 changes: 3 additions & 0 deletions src/libtrx/include/libtrx/game/clock.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#pragma once

#include <stddef.h>

size_t Clock_GetDateTime(char *buffer, size_t size);
extern double Clock_GetHighPrecisionCounter(void);
1 change: 1 addition & 0 deletions src/libtrx/include/libtrx/game/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@

extern bool Game_IsPlayable(void);
extern GAMEFLOW_LEVEL_TYPE Game_GetCurrentLevelType(void);
extern int32_t Game_GetCurrentLevelNum(void);
3 changes: 3 additions & 0 deletions src/libtrx/include/libtrx/game/output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

extern bool Output_MakeScreenshot(const char *path);
1 change: 1 addition & 0 deletions src/libtrx/include/libtrx/output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern Output_MakeScreenshot(const char *const path);
10 changes: 10 additions & 0 deletions src/libtrx/include/libtrx/screenshot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <stdbool.h>

typedef enum {
SCREENSHOT_FORMAT_JPEG,
SCREENSHOT_FORMAT_PNG,
} SCREENSHOT_FORMAT;

bool Screenshot_Make(SCREENSHOT_FORMAT format);
2 changes: 2 additions & 0 deletions src/libtrx/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ sources = [
'event_manager.c',
'filesystem.c',
'game/backpack.c',
'game/clock.c',
'game/console/cmd/config.c',
'game/console/cmd/die.c',
'game/console/cmd/end_level.c',
Expand Down Expand Up @@ -122,6 +123,7 @@ sources = [
'json/json_write.c',
'log.c',
'memory.c',
'screenshot.c',
'strings/common.c',
'strings/fuzzy_match.c',
'vector.c',
Expand Down
123 changes: 123 additions & 0 deletions src/libtrx/screenshot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include "screenshot.h"

#include "filesystem.h"
#include "game/game.h"
#include "game/gameflow/common.h"
#include "game/output.h"
#include "memory.h"

#include <stdio.h>
#include <string.h>

#define SCREENSHOTS_DIR "screenshots"

static char *M_GetScreenshotName(void);

static char *M_GetScreenshotName(void)
{
const int32_t level_num = Game_GetCurrentLevelNum();
char *level_title = NULL;
if (level_num < 0) {
level_title = Memory_DupStr("Intro");
} else {
level_title = Memory_DupStr(Gameflow_GetLevelTitle(level_num));
}

// Prepare level title for screenshot
char *check = level_title;
bool prev_us = true; // '_' after timestamp before title
int idx = 0;

while (*check != '\0') {
if (*check == ' ') {
// Replace spaces with a single underscore
if (prev_us) {
memmove(
&level_title[idx], &level_title[idx + 1],
strlen(level_title) - idx);
} else {
*check++ = '_';
idx++;
prev_us = true;
}
} else if (((*check < 'A' || *check > 'Z')
&& (*check < 'a' || *check > 'z')
&& (*check < '0' || *check > '9'))) {
// Strip non alphanumeric chars
memmove(
&level_title[idx], &level_title[idx + 1],
strlen(level_title) - idx);
} else {
check++;
idx++;
prev_us = false;
}
}

// If title totally invalid, name it based on level number
if (strlen(level_title) == 0) {
sprintf(level_title, "Level_%d", level_num);
prev_us = false;
}

// Strip trailing underscores
if (prev_us) {
check--;
idx--;
memmove(
&level_title[idx], &level_title[idx + 1], strlen(level_title) - 1);
prev_us = false;
}

// Get timestamp
char date_time[30];
Clock_GetDateTime(date_time);

// Full screenshot name
size_t out_size = snprintf(NULL, 0, "%s_%s", date_time, level_title) + 1;
char *out = Memory_Alloc(out_size);
snprintf(out, out_size, "%s_%s", date_time, level_title);
return out;
}

bool Screenshot_Make(const SCREENSHOT_FORMAT format)
{
File_CreateDirectory(SCREENSHOTS_DIR);

char *const filename = M_GetScreenshotName();

const char *ext;
switch (format) {
case SCREENSHOT_FORMAT_JPEG:
ext = "jpg";
break;
case SCREENSHOT_FORMAT_PNG:
ext = "png";
break;
default:
ext = "jpg";
break;
}

bool result = false;
char *full_path = Memory_Alloc(
strlen(SCREENSHOTS_DIR) + strlen(filename) + strlen(ext) + 6);
sprintf(full_path, "%s/%s.%s", SCREENSHOTS_DIR, filename, ext);
if (!File_Exists(full_path)) {
result = Output_MakeScreenshot(full_path);
} else {
// name already exists, so add a number to name
for (int i = 2; i < 100; i++) {
sprintf(
full_path, "%s/%s_%d.%s", SCREENSHOTS_DIR, filename, i, ext);
if (!File_Exists(full_path)) {
result = Output_MakeScreenshot(full_path);
break;
}
}
}

Memory_FreePointer(&filename);
Memory_FreePointer(&full_path);
return result;
}
1 change: 1 addition & 0 deletions src/tr1/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <libtrx/config.h>
#include <libtrx/gfx/common.h>
#include <libtrx/screenshot.h>

#include <stdbool.h>
#include <stdint.h>
Expand Down
12 changes: 0 additions & 12 deletions src/tr1/game/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <time.h>

static double M_GetElapsedUnit(CLOCK_TIMER *const timer, const double unit);
static bool M_CheckElapsedUnit(
Expand Down Expand Up @@ -76,17 +75,6 @@ double Clock_GetSpeedMultiplier(void)
}
}

void Clock_GetDateTime(char *date_time)
{
time_t lt = time(0);
struct tm *tptr = localtime(&lt);

sprintf(
date_time, "%04d%02d%02d_%02d%02d%02d", tptr->tm_year + 1900,
tptr->tm_mon + 1, tptr->tm_mday, tptr->tm_hour, tptr->tm_min,
tptr->tm_sec);
}

int32_t Clock_GetFrameAdvance(void)
{
return g_Config.rendering.fps == 30 ? 2 : 1;
Expand Down
4 changes: 2 additions & 2 deletions src/tr1/game/clock.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <libtrx/game/clock.h>

#include <stdbool.h>
#include <stdint.h>

Expand Down Expand Up @@ -44,6 +46,4 @@ bool Clock_CheckElapsedMilliseconds(CLOCK_TIMER *timer, int32_t wait);
// by the turbo cheat multiplier.
bool Clock_CheckElapsedRawMilliseconds(CLOCK_TIMER *timer, int32_t how_often);

void Clock_GetDateTime(char *date_time);

int32_t Clock_GetFrameAdvance(void);
5 changes: 5 additions & 0 deletions src/tr1/game/game/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ GAMEFLOW_LEVEL_TYPE Game_GetCurrentLevelType(void)
return g_GameInfo.current_level_type;
}

extern int32_t Game_GetCurrentLevelNum(void)
{
return g_CurrentLevel;
}

bool Game_IsPlayable(void)
{
if (g_GameInfo.current_level_type == GFL_TITLE
Expand Down
6 changes: 4 additions & 2 deletions src/tr1/game/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <libtrx/engine/image.h>
#include <libtrx/filesystem.h>
#include <libtrx/game/console/common.h>
#include <libtrx/gfx/context.h>
#include <libtrx/memory.h>
#include <libtrx/utils.h>

Expand Down Expand Up @@ -1364,9 +1365,10 @@ void Output_ApplyTint(float *r, float *g, float *b)
}
}

bool Output_MakeScreenshot(const char *path)
bool Output_MakeScreenshot(const char *const path)
{
return S_Output_MakeScreenshot(path);
GFX_Context_ScheduleScreenshot(path);
return true;
}

int Output_GetObjectBounds(const BOUNDS_16 *const bounds)
Expand Down
2 changes: 1 addition & 1 deletion src/tr1/game/phase/phase_photo_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static void M_End(void)
static PHASE_CONTROL M_Control(int32_t nframes)
{
if (m_Status == PS_ACTIVE) {
Shell_MakeScreenshot();
Screenshot_Make(g_Config.screenshot_format);
Sound_Effect(SFX_MENU_CHOOSE, NULL, SPM_ALWAYS);
m_Status = PS_COOLDOWN;
} else if (m_Status == PS_COOLDOWN) {
Expand Down
2 changes: 1 addition & 1 deletion src/tr1/game/savegame/savegame_bson.c
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,7 @@ static JSON_OBJECT *M_DumpCurrentMusic(void)
{
JSON_OBJECT *current_music_obj = JSON_ObjectNew();
JSON_ObjectAppendInt(
current_music_obj, "current_track", Music_GetCurrentTrack());
current_music_obj, "current_track", Music_GetCurrentPlayingTrack());
JSON_ObjectAppendDouble(
current_music_obj, "timestamp", Music_GetTimestamp());

Expand Down
Loading

0 comments on commit da94642

Please sign in to comment.