mirror of
https://github.com/libretro/libretro-prboom.git
synced 2024-11-26 17:50:36 +00:00
Prevent segfault when applying cheats before a level has loaded (#161)
This commit is contained in:
parent
e8ebfe780f
commit
ee17bf3632
120
libretro/libretro-common/include/array/rbuf.h
Normal file
120
libretro/libretro-common/include/array/rbuf.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (rbuf.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_ARRAY_RBUF_H__
|
||||
#define __LIBRETRO_SDK_ARRAY_RBUF_H__
|
||||
|
||||
/*
|
||||
* This file implements stretchy buffers as invented (?) by Sean Barrett.
|
||||
* Based on the implementation from the public domain Bitwise project
|
||||
* by Per Vognsen - https://github.com/pervognsen/bitwise
|
||||
*
|
||||
* It's a super simple type safe dynamic array for C with no need
|
||||
* to predeclare any type or anything.
|
||||
* The first time an element is added, memory for 16 elements are allocated.
|
||||
* Then every time length is about to exceed capacity, capacity is doubled.
|
||||
*
|
||||
* Be careful not to supply modifying statements to the macro arguments.
|
||||
* Something like RBUF_REMOVE(buf, i--); would have unintended results.
|
||||
*
|
||||
* Sample usage:
|
||||
*
|
||||
* mytype_t* buf = NULL;
|
||||
* RBUF_PUSH(buf, some_element);
|
||||
* RBUF_PUSH(buf, other_element);
|
||||
* -- now RBUF_LEN(buf) == 2, buf[0] == some_element, buf[1] == other_element
|
||||
*
|
||||
* -- Free allocated memory:
|
||||
* RBUF_FREE(buf);
|
||||
* -- now buf == NULL, RBUF_LEN(buf) == 0, RBUF_CAP(buf) == 0
|
||||
*
|
||||
* -- Explicitly increase allocated memory and set capacity:
|
||||
* RBUF_FIT(buf, 100);
|
||||
* -- now RBUF_LEN(buf) == 0, RBUF_CAP(buf) == 100
|
||||
*
|
||||
* -- Resize buffer (does not initialize or zero memory!)
|
||||
* RBUF_RESIZE(buf, 200);
|
||||
* -- now RBUF_LEN(buf) == 200, RBUF_CAP(buf) == 200
|
||||
*
|
||||
* -- To handle running out of memory:
|
||||
* bool ran_out_of_memory = !RBUF_TRYFIT(buf, 1000);
|
||||
* -- before RESIZE or PUSH. When out of memory, buf will stay unmodified.
|
||||
*/
|
||||
|
||||
#include <retro_math.h> /* for MAX */
|
||||
#include <stdlib.h> /* for malloc, realloc */
|
||||
|
||||
#define RBUF__HDR(b) (((struct rbuf__hdr *)(b))-1)
|
||||
|
||||
#define RBUF_LEN(b) ((b) ? RBUF__HDR(b)->len : 0)
|
||||
#define RBUF_CAP(b) ((b) ? RBUF__HDR(b)->cap : 0)
|
||||
#define RBUF_END(b) ((b) + RBUF_LEN(b))
|
||||
#define RBUF_SIZEOF(b) ((b) ? RBUF_LEN(b)*sizeof(*b) : 0)
|
||||
|
||||
#define RBUF_FREE(b) ((b) ? (free(RBUF__HDR(b)), (b) = NULL) : 0)
|
||||
#define RBUF_FIT(b, n) ((size_t)(n) <= RBUF_CAP(b) ? 0 : (*(void**)(&(b)) = rbuf__grow((b), (n), sizeof(*(b)))))
|
||||
#define RBUF_PUSH(b, val) (RBUF_FIT((b), 1 + RBUF_LEN(b)), (b)[RBUF__HDR(b)->len++] = (val))
|
||||
#define RBUF_POP(b) (b)[--RBUF__HDR(b)->len]
|
||||
#define RBUF_RESIZE(b, sz) (RBUF_FIT((b), (sz)), ((b) ? RBUF__HDR(b)->len = (sz) : 0))
|
||||
#define RBUF_CLEAR(b) ((b) ? RBUF__HDR(b)->len = 0 : 0)
|
||||
#define RBUF_TRYFIT(b, n) (RBUF_FIT((b), (n)), (((b) && RBUF_CAP(b) >= (size_t)(n)) || !(n)))
|
||||
#define RBUF_REMOVE(b, idx) memmove((b) + (idx), (b) + (idx) + 1, (--RBUF__HDR(b)->len - (idx)) * sizeof(*(b)))
|
||||
|
||||
struct rbuf__hdr
|
||||
{
|
||||
size_t len;
|
||||
size_t cap;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
__attribute__((__unused__))
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4505) //unreferenced local function has been removed
|
||||
#endif
|
||||
static void *rbuf__grow(void *buf,
|
||||
size_t new_len, size_t elem_size)
|
||||
{
|
||||
struct rbuf__hdr *new_hdr;
|
||||
size_t new_cap = MAX(2 * RBUF_CAP(buf), MAX(new_len, 16));
|
||||
size_t new_size = sizeof(struct rbuf__hdr) + new_cap*elem_size;
|
||||
if (buf)
|
||||
{
|
||||
new_hdr = (struct rbuf__hdr *)realloc(RBUF__HDR(buf), new_size);
|
||||
if (!new_hdr)
|
||||
return buf; /* out of memory, return unchanged */
|
||||
}
|
||||
else
|
||||
{
|
||||
new_hdr = (struct rbuf__hdr *)malloc(new_size);
|
||||
if (!new_hdr)
|
||||
return NULL; /* out of memory */
|
||||
new_hdr->len = 0;
|
||||
}
|
||||
new_hdr->cap = new_cap;
|
||||
return new_hdr + 1;
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
190
libretro/libretro-common/include/retro_math.h
Normal file
190
libretro/libretro-common/include/retro_math.h
Normal file
@ -0,0 +1,190 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_math.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRETRO_COMMON_MATH_H
|
||||
#define _LIBRETRO_COMMON_MATH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#elif defined(_WIN32) && defined(_XBOX)
|
||||
#include <Xtl.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
#include <retro_inline.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#if !defined(USE_MATH_DEFINES)
|
||||
#define M_PI 3.14159265358979323846264338327
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* next_pow2:
|
||||
* @v : initial value
|
||||
*
|
||||
* Get next power of 2 value based on initial value.
|
||||
*
|
||||
* Returns: next power of 2 value (derived from @v).
|
||||
**/
|
||||
static INLINE uint32_t next_pow2(uint32_t v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* prev_pow2:
|
||||
* @v : initial value
|
||||
*
|
||||
* Get previous power of 2 value based on initial value.
|
||||
*
|
||||
* Returns: previous power of 2 value (derived from @v).
|
||||
**/
|
||||
static INLINE uint32_t prev_pow2(uint32_t v)
|
||||
{
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
return v - (v >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clamp:
|
||||
* @v : initial value
|
||||
*
|
||||
* Get the clamped value based on initial value.
|
||||
*
|
||||
* Returns: clamped value (derived from @v).
|
||||
**/
|
||||
static INLINE float clamp_value(float v, float min, float max)
|
||||
{
|
||||
return v <= min ? min : v >= max ? max : v;
|
||||
}
|
||||
|
||||
/**
|
||||
* saturate_value:
|
||||
* @v : initial value
|
||||
*
|
||||
* Get the clamped 0.0-1.0 value based on initial value.
|
||||
*
|
||||
* Returns: clamped 0.0-1.0 value (derived from @v).
|
||||
**/
|
||||
static INLINE float saturate_value(float v)
|
||||
{
|
||||
return clamp_value(v, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* dot_product:
|
||||
* @a : left hand vector value
|
||||
* @b : right hand vector value
|
||||
*
|
||||
* Get the dot product of the two passed in vectors.
|
||||
*
|
||||
* Returns: dot product value (derived from @a and @b).
|
||||
**/
|
||||
static INLINE float dot_product(const float* a, const float* b)
|
||||
{
|
||||
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert_rgb_to_yxy:
|
||||
* @rgb : in RGB colour space value
|
||||
* @Yxy : out Yxy colour space value
|
||||
*
|
||||
* Convert from RGB colour space to Yxy colour space.
|
||||
*
|
||||
* Returns: Yxy colour space value (derived from @rgb).
|
||||
**/
|
||||
static INLINE void convert_rgb_to_yxy(const float* rgb, float* Yxy)
|
||||
{
|
||||
float inv;
|
||||
float xyz[3];
|
||||
float one[3] = {1.0, 1.0, 1.0};
|
||||
float rgb_xyz[3][3] = {
|
||||
{0.4124564, 0.3575761, 0.1804375},
|
||||
{0.2126729, 0.7151522, 0.0721750},
|
||||
{0.0193339, 0.1191920, 0.9503041}
|
||||
};
|
||||
|
||||
xyz[0] = dot_product(rgb_xyz[0], rgb);
|
||||
xyz[1] = dot_product(rgb_xyz[1], rgb);
|
||||
xyz[2] = dot_product(rgb_xyz[2], rgb);
|
||||
|
||||
inv = 1.0f / dot_product(xyz, one);
|
||||
Yxy[0] = xyz[1];
|
||||
Yxy[1] = xyz[0] * inv;
|
||||
Yxy[2] = xyz[1] * inv;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert_yxy_to_rgb:
|
||||
* @rgb : in Yxy colour space value
|
||||
* @Yxy : out rgb colour space value
|
||||
*
|
||||
* Convert from Yxy colour space to rgb colour space.
|
||||
*
|
||||
* Returns: rgb colour space value (derived from @Yxy).
|
||||
**/
|
||||
static INLINE void convert_yxy_to_rgb(const float* Yxy, float* rgb)
|
||||
{
|
||||
float xyz[3];
|
||||
float xyz_rgb[3][3] = {
|
||||
{3.2404542, -1.5371385, -0.4985314},
|
||||
{-0.9692660, 1.8760108, 0.0415560},
|
||||
{0.0556434, -0.2040259, 1.0572252}
|
||||
};
|
||||
xyz[0] = Yxy[0] * Yxy[1] / Yxy[2];
|
||||
xyz[1] = Yxy[0];
|
||||
xyz[2] = Yxy[0] * (1.0 - Yxy[1] - Yxy[2]) / Yxy[2];
|
||||
|
||||
rgb[0] = dot_product(xyz_rgb[0], xyz);
|
||||
rgb[1] = dot_product(xyz_rgb[1], xyz);
|
||||
rgb[2] = dot_product(xyz_rgb[2], xyz);
|
||||
}
|
||||
|
||||
#endif
|
@ -10,6 +10,7 @@
|
||||
#include <libretro.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <array/rbuf.h>
|
||||
|
||||
#if _MSC_VER
|
||||
#include <compat/msvc.h>
|
||||
@ -41,6 +42,7 @@
|
||||
#include "../src/g_game.h"
|
||||
#include "../src/wi_stuff.h"
|
||||
#include "../src/p_tick.h"
|
||||
#include "../src/z_zone.h"
|
||||
|
||||
/* Don't include file_stream_transforms.h but instead
|
||||
just forward declare the prototype */
|
||||
@ -55,13 +57,18 @@ int SCREENWIDTH = 320;
|
||||
int SCREENHEIGHT = 200;
|
||||
|
||||
//i_video
|
||||
static unsigned char *screen_buf;
|
||||
static unsigned char *screen_buf = NULL;
|
||||
|
||||
/* libretro */
|
||||
static char g_wad_dir[1024];
|
||||
static char g_basename[1024];
|
||||
static char g_save_dir[1024];
|
||||
|
||||
/* Cheat handling */
|
||||
static bool cheats_enabled = false;
|
||||
static bool cheats_pending = false;
|
||||
static char **cheats_pending_list = NULL;
|
||||
|
||||
//forward decls
|
||||
bool D_DoomMainSetup(void);
|
||||
void D_DoomLoop(void);
|
||||
@ -277,6 +284,8 @@ void retro_init(void)
|
||||
enum retro_pixel_format rgb565;
|
||||
struct retro_log_callback log;
|
||||
|
||||
Z_Init(); /* 1/18/98 killough: start up memory stuff first */
|
||||
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
|
||||
log_cb = log.log;
|
||||
else
|
||||
@ -296,6 +305,24 @@ void retro_deinit(void)
|
||||
{
|
||||
D_DoomDeinit();
|
||||
|
||||
if (screen_buf)
|
||||
free(screen_buf);
|
||||
screen_buf = NULL;
|
||||
|
||||
cheats_enabled = false;
|
||||
cheats_pending = false;
|
||||
if (cheats_pending_list)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < RBUF_LEN(cheats_pending_list); i++)
|
||||
{
|
||||
if (cheats_pending_list[i])
|
||||
free(cheats_pending_list[i]);
|
||||
cheats_pending_list[i] = NULL;
|
||||
}
|
||||
RBUF_FREE(cheats_pending_list);
|
||||
}
|
||||
|
||||
libretro_supports_bitmasks = false;
|
||||
|
||||
retro_set_rumble_damage(0, 0.0f);
|
||||
@ -307,6 +334,13 @@ void retro_deinit(void)
|
||||
rumble_damage_counter = -1;
|
||||
rumble_touch_strength = 0;
|
||||
rumble_touch_counter = -1;
|
||||
|
||||
/* Z_Close() must be the very last
|
||||
* function that is called, since
|
||||
* z_zone.h overrides malloc()/free()/etc.
|
||||
* (i.e. anything that calls free()
|
||||
* after Z_Close() will likely segfault) */
|
||||
Z_Close();
|
||||
}
|
||||
|
||||
unsigned retro_api_version(void)
|
||||
@ -561,6 +595,27 @@ void retro_run(void)
|
||||
bool updated = false;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
|
||||
update_variables(false);
|
||||
|
||||
/* Check for pending cheats */
|
||||
if (cheats_pending && (gamestate == GS_LEVEL) && !demoplayback)
|
||||
{
|
||||
unsigned i, j;
|
||||
for (i = 0; i < RBUF_LEN(cheats_pending_list); i++)
|
||||
{
|
||||
const char *cheat_code = cheats_pending_list[i];
|
||||
if (cheat_code)
|
||||
{
|
||||
for (j = 0; cheat_code[j] != '\0'; j++)
|
||||
M_FindCheats(cheat_code[j]);
|
||||
|
||||
free(cheats_pending_list[i]);
|
||||
cheats_pending_list[i] = NULL;
|
||||
}
|
||||
}
|
||||
RBUF_FREE(cheats_pending_list);
|
||||
cheats_pending = false;
|
||||
}
|
||||
|
||||
if (quit_pressed)
|
||||
{
|
||||
environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
|
||||
@ -765,9 +820,6 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
myargc = argc;
|
||||
myargv = (const char **) argv;
|
||||
|
||||
if (!Z_Init()) /* 1/18/98 killough: start up memory stuff first */
|
||||
goto failed;
|
||||
|
||||
/* cphipps - call to video specific startup code */
|
||||
if (!I_PreInitGraphics())
|
||||
goto failed;
|
||||
@ -779,6 +831,10 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
for (i = 0; i < 3; i++)
|
||||
D_DoomLoop();
|
||||
|
||||
cheats_enabled = true;
|
||||
cheats_pending = false;
|
||||
cheats_pending_list = NULL;
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
@ -804,9 +860,6 @@ failed:
|
||||
|
||||
void retro_unload_game(void)
|
||||
{
|
||||
if (screen_buf)
|
||||
free(screen_buf);
|
||||
screen_buf = NULL;
|
||||
}
|
||||
|
||||
unsigned retro_get_region(void)
|
||||
@ -1020,11 +1073,43 @@ void retro_cheat_reset(void)
|
||||
|
||||
void retro_cheat_set(unsigned index, bool enabled, const char *code)
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
(void)index;(void)enabled;
|
||||
if(code)
|
||||
for (i=0; code[i] != '\0'; i++)
|
||||
|
||||
if (!code || !cheats_enabled)
|
||||
return;
|
||||
|
||||
/* Note: it is not currently possible to disable
|
||||
* cheats once active... */
|
||||
|
||||
/* Check if cheat can be applied now */
|
||||
if ((gamestate == GS_LEVEL) && !demoplayback)
|
||||
{
|
||||
for (i = 0; code[i] != '\0'; i++)
|
||||
M_FindCheats(code[i]);
|
||||
}
|
||||
/* Current game state does not support cheat
|
||||
* activation - add code to pending list */
|
||||
else
|
||||
{
|
||||
bool code_found = false;
|
||||
|
||||
for (i = 0; i < RBUF_LEN(cheats_pending_list); i++)
|
||||
{
|
||||
const char *existing_code = cheats_pending_list[i];
|
||||
if (existing_code && !strcmp(existing_code, code))
|
||||
{
|
||||
code_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!code_found)
|
||||
{
|
||||
RBUF_PUSH(cheats_pending_list, strdup(code));
|
||||
cheats_pending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static action_lut_t left_analog_lut[] = {
|
||||
|
@ -1494,7 +1494,6 @@ void D_DoomDeinit(void)
|
||||
V_DestroyUnusedTrueColorPalettes();
|
||||
R_FlushAllPatches();
|
||||
P_Deinit();
|
||||
Z_Close();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -112,6 +112,10 @@ void Z_Close(void)
|
||||
|
||||
bool Z_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < PU_MAX; i++)
|
||||
blockbytag[i] = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user