Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tr2/decomp: fix windowed screenshots not working #1767

Merged
merged 6 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 1 addition & 1 deletion docs/tr2/progress.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4471,7 +4471,7 @@ typedef enum {
0x0051B928 - int32_t g_HiRes;
0x0051B930 - RGB_888 g_GamePalette8[256];
0x0051BCC0 - APP_SETTINGS g_SavedAppSettings;
0x0051BD20 - char g_ErrorMessage[128];
0x0051BD20 + char g_ErrorMessage[128];
0x0051BDA8 - int32_t g_MasterVolume;
0x0051BDAC - MCIDEVICEID g_MciDeviceID;
0x0051BDB0 - int32_t g_CD_LoopTrack;
Expand Down
1 change: 0 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ _docker_build dockerfile tag force="0":

echo "Building Docker image: {{dockerfile}} → {{tag}}"
docker build \
--progress plain \
. \
-f {{dockerfile}} \
-t {{tag}}
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);
}
8 changes: 4 additions & 4 deletions src/libtrx/include/libtrx/engine/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ void Video_SetSurfaceDeallocatorFunc(
void *user_data);
void Video_SetSurfaceClearFunc(
VIDEO *video, void (*func)(void *surface, void *user_data),
void *const user_data);
void *user_data);
void Video_SetSurfaceLockFunc(
VIDEO *video, void *(*func)(void *surface, void *user_data),
void *const user_data);
void *user_data);
void Video_SetSurfaceUnlockFunc(
VIDEO *video, void (*func)(void *surface, void *user_data),
void *const user_data);
void *user_data);
void Video_SetSurfaceUploadFunc(
VIDEO *video, void (*func)(void *surface, void *user_data),
void *const user_data);
void *user_data);
void Video_SetRenderBeginFunc(
VIDEO *video, void (*func)(void *surface, void *user_data),
void *user_data);
Expand Down
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);
3 changes: 1 addition & 2 deletions src/libtrx/include/libtrx/game/rooms/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ extern void Room_FlipMap(void);
extern bool Room_GetFlipStatus(void);

int32_t Room_GetAdjoiningRooms(
int16_t init_room_num, int16_t out_room_nums[],
const int32_t max_room_num_count);
int16_t init_room_num, int16_t out_room_nums[], int32_t max_room_num_count);
3 changes: 3 additions & 0 deletions src/libtrx/include/libtrx/output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

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
141 changes: 141 additions & 0 deletions src/libtrx/screenshot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "screenshot.h"

#include "filesystem.h"
#include "game/clock.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_GetScreenshotTitle(void);
static char *M_CleanScreenshotTitle(const char *source);
static char *M_GetScreenshotBaseName(void);
static const char *M_GetScreenshotFileExt(SCREENSHOT_FORMAT format);
static char *M_GetScreenshotPath(SCREENSHOT_FORMAT format);

static char *M_CleanScreenshotTitle(const char *const source)
{
// Sanitize screenshot title.
// - Replace spaces with underscores
// - Remove all non-alphanumeric characters
// - Merge consecutive underscores together
// - Remove leading underscores
// - Remove trailing underscores
char *result = Memory_Alloc(strlen(source) + 1);

bool last_was_underscore = false;
char *out = result;
for (size_t i = 0; i < strlen(source); i++) {
if (source[i] == ' ' || source[i] == '_') {
if (!last_was_underscore && out > result) {
*out++ = '_';
last_was_underscore = true;
}
} else if (((source[i] >= 'A' && source[i] <= 'Z')
|| (source[i] >= 'a' && source[i] <= 'z')
|| (source[i] >= '0' && source[i] <= '9'))) {
*out++ = source[i];
last_was_underscore = false;
}
}
*out++ = '\0';

// Strip trailing underscores
while (out[-1] == '_' && out >= result) {
out--;
}
*out = '\0';

return result;
}

static char *M_GetScreenshotTitle(void)
{
const int32_t level_num = Game_GetCurrentLevelNum();
if (level_num < 0) {
return Memory_DupStr("Intro");
}

const char *const level_title = Gameflow_GetLevelTitle(level_num);
if (level_title != NULL && strlen(level_title) > 0) {
char *clean_level_title = M_CleanScreenshotTitle(level_title);
if (clean_level_title != NULL && strlen(clean_level_title) > 0) {
return clean_level_title;
}
Memory_FreePointer(clean_level_title);
}

// If title totally invalid, name it based on level number
const char *const fmt = "Level_%d";
const size_t result_size = snprintf(NULL, 0, fmt, level_num) + 1;
char *result = Memory_Alloc(result_size);
snprintf(result, result_size, fmt, level_num);
return result;
}

static char *M_GetScreenshotBaseName(void)
{
char *screenshot_title = M_GetScreenshotTitle();

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

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

static const char *M_GetScreenshotFileExt(const SCREENSHOT_FORMAT format)
{
switch (format) {
case SCREENSHOT_FORMAT_JPEG:
return "jpg";
case SCREENSHOT_FORMAT_PNG:
return "png";
default:
return "jpg";
}
}

static char *M_GetScreenshotPath(const SCREENSHOT_FORMAT format)
{
char *base_name = M_GetScreenshotBaseName();
const char *const ext = M_GetScreenshotFileExt(format);

char *full_path = Memory_Alloc(
strlen(SCREENSHOTS_DIR) + strlen(base_name) + strlen(ext) + 6);
sprintf(full_path, "%s/%s.%s", SCREENSHOTS_DIR, base_name, ext);
if (File_Exists(full_path)) {
for (int i = 2; i < 100; i++) {
sprintf(
full_path, "%s/%s_%d.%s", SCREENSHOTS_DIR, base_name, i, ext);
if (!File_Exists(full_path)) {
break;
}
}
}

Memory_FreePointer(&base_name);
return full_path;
}

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

char *full_path = M_GetScreenshotPath(format);
const bool result = Output_MakeScreenshot(full_path);
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