forked from Ports/perfect_dark
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d63e12034 | ||
|
|
23ce248dce | ||
|
|
fa7ef3df64 | ||
|
|
0fd290c8c3 | ||
|
|
b20abed21e | ||
|
|
c4f12ad0a5 | ||
|
|
60989596d5 | ||
|
|
256323a109 | ||
|
|
1e46e68933 |
No files matched your search
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"clang-format.enable": false,
|
||||
"C_Cpp.clang_format_style": "none",
|
||||
"[c]": {
|
||||
"editor.formatOnSave": false,
|
||||
"editor.formatOnPaste": false,
|
||||
"editor.formatOnType": false
|
||||
},
|
||||
"[cpp]": {
|
||||
"editor.formatOnSave": false,
|
||||
"editor.formatOnPaste": false,
|
||||
"editor.formatOnType": false
|
||||
}
|
||||
}
|
||||
+160
-2
@@ -33,6 +33,10 @@ struct ShaderProgram {
|
||||
GLint frame_count_location;
|
||||
GLint noise_scale_location;
|
||||
GLint three_point_filter_locations[2];
|
||||
GLint decal_mode_location;
|
||||
GLint decal_scale_location;
|
||||
int decal_mode;
|
||||
float decal_scale;
|
||||
};
|
||||
|
||||
struct Framebuffer {
|
||||
@@ -40,6 +44,8 @@ struct Framebuffer {
|
||||
bool has_depth_buffer;
|
||||
uint32_t msaa_level;
|
||||
bool invert_y;
|
||||
bool depth_copy_checked;
|
||||
bool depth_copy_failed;
|
||||
|
||||
GLuint fbo, clrbuf, clrbuf_msaa, rbo;
|
||||
};
|
||||
@@ -58,6 +64,19 @@ static int current_anisotropy_level;
|
||||
static FilteringMode current_filter_mode = FILTER_LINEAR;
|
||||
static MipmapFilteringMode current_mipmap_filter_mode = MIPMAP_LINEAR;
|
||||
static bool current_textures_linear_filter[2] = {false, false};
|
||||
static struct ShaderProgram* current_shader_program;
|
||||
|
||||
// N64 decal depth mode: pixels only pass when close to the stored depth, using a copy of the depth buffer
|
||||
#define DECAL_DEPTH_TEXTURE_UNIT 2
|
||||
// Height of the N64 frame; the RDP's depth slope tolerance is measured in N64 pixels
|
||||
#define DECAL_N64_SCREEN_HEIGHT 240.0f
|
||||
static bool depth_copy_supported;
|
||||
static bool depth_copy_dirty = true;
|
||||
static size_t depth_copy_source;
|
||||
static GLuint depth_copy_fbo, depth_copy_tex;
|
||||
static uint32_t depth_copy_width, depth_copy_height;
|
||||
static bool current_depth_test;
|
||||
static bool current_depth_decal;
|
||||
|
||||
static int gl_glsl_version = 130;
|
||||
static char gl_glsl_version_str[16] = "130";
|
||||
@@ -120,6 +139,7 @@ static void gfx_opengl_unload_shader(struct ShaderProgram* old_prg) {
|
||||
|
||||
static void gfx_opengl_load_shader(struct ShaderProgram* new_prg) {
|
||||
// if (!new_prg) return;
|
||||
current_shader_program = new_prg;
|
||||
glUseProgram(new_prg->opengl_program_id);
|
||||
gfx_opengl_vertex_array_set_attribs(new_prg);
|
||||
gfx_opengl_set_uniforms(new_prg);
|
||||
@@ -382,6 +402,9 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
|
||||
append_line(fs_buf, &fs_len, "uniform int frame_count;");
|
||||
append_line(fs_buf, &fs_len, "uniform float noise_scale;");
|
||||
append_line(fs_buf, &fs_len, "uniform int uDecalMode;");
|
||||
append_line(fs_buf, &fs_len, "uniform highp float uDecalPixelScale;");
|
||||
append_line(fs_buf, &fs_len, "uniform highp sampler2D uDepthTex;");
|
||||
|
||||
append_line(fs_buf, &fs_len, "float random(in vec3 value) {");
|
||||
append_line(fs_buf, &fs_len, " float random = dot(sin(value), vec3(12.9898, 78.233, 37.719));");
|
||||
@@ -442,6 +465,15 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
|
||||
append_line(fs_buf, &fs_len, "void main() {");
|
||||
|
||||
// RDP decal Z mode: pass only if |z - stored z| <= dz (the per-pixel depth slope), and never over cleared depth.
|
||||
// The slope is computed before anything can discard, since derivatives are undefined after a neighbor discards.
|
||||
append_line(fs_buf, &fs_len, " highp float decalSlope = fwidth(gl_FragCoord.z);");
|
||||
append_line(fs_buf, &fs_len, " if (uDecalMode != 0) {");
|
||||
append_line(fs_buf, &fs_len, " highp float storedZ = texelFetch(uDepthTex, ivec2(gl_FragCoord.xy), 0).r;");
|
||||
append_line(fs_buf, &fs_len, " highp float dz = max(decalSlope * uDecalPixelScale, 1.0 / 262144.0);");
|
||||
append_line(fs_buf, &fs_len, " if (storedZ >= 1.0 || abs(gl_FragCoord.z - storedZ) > dz) discard;");
|
||||
append_line(fs_buf, &fs_len, " }");
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (cc_features.used_textures[i]) {
|
||||
bool s = cc_features.clamp[i][0], t = cc_features.clamp[i][1];
|
||||
@@ -652,6 +684,14 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
prg->noise_scale_location = glGetUniformLocation(shader_program, "noise_scale");
|
||||
prg->three_point_filter_locations[0] = glGetUniformLocation(shader_program, "three_point_filter0");
|
||||
prg->three_point_filter_locations[1] = glGetUniformLocation(shader_program, "three_point_filter1");
|
||||
prg->decal_mode_location = glGetUniformLocation(shader_program, "uDecalMode");
|
||||
prg->decal_scale_location = glGetUniformLocation(shader_program, "uDecalPixelScale");
|
||||
prg->decal_mode = 0;
|
||||
prg->decal_scale = 0.0f;
|
||||
if (prg->decal_mode_location >= 0) {
|
||||
glUniform1i(prg->decal_mode_location, 0);
|
||||
glUniform1i(glGetUniformLocation(shader_program, "uDepthTex"), DECAL_DEPTH_TEXTURE_UNIT);
|
||||
}
|
||||
|
||||
gfx_opengl_load_shader(prg);
|
||||
|
||||
@@ -671,6 +711,7 @@ static void gfx_opengl_shader_get_info(struct ShaderProgram* prg, uint8_t* num_i
|
||||
|
||||
static void gfx_opengl_clear_shaders(void) {
|
||||
glUseProgram(0);
|
||||
current_shader_program = nullptr;
|
||||
for (auto& pair : shader_program_pool) {
|
||||
glDeleteProgram(pair.second.opengl_program_id);
|
||||
}
|
||||
@@ -725,8 +766,8 @@ static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint
|
||||
|
||||
mipmaps = mipmaps && (current_mipmap_filter_mode != MIPMAP_DISABLED);
|
||||
const int mip_idx = mipmaps ? current_mipmap_filter_mode : 0;
|
||||
const GLint min_filter = linear_filter ? min_filters[current_filter_mode][mip_idx] : GL_NEAREST;
|
||||
const GLint max_filter = linear_filter && (current_filter_mode == FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST;
|
||||
const GLint min_filter = linear_filter ? min_filters[current_filter_mode][mip_idx] : GL_LINEAR;
|
||||
const GLint max_filter = linear_filter && (current_filter_mode == FILTER_LINEAR) ? GL_LINEAR : GL_LINEAR;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + tile);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
@@ -741,6 +782,9 @@ static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode) {
|
||||
current_depth_test = depth_test;
|
||||
current_depth_decal = depth_test && depth_compare && zmode == ZMODE_DEC;
|
||||
|
||||
if (depth_test) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(depth_update ? GL_TRUE : GL_FALSE);
|
||||
@@ -810,10 +854,116 @@ static void gfx_opengl_set_use_alpha(bool use_alpha, bool modulate) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool gfx_opengl_update_depth_copy(void) {
|
||||
if (!depth_copy_supported) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Framebuffer& fb = framebuffers[current_framebuffer];
|
||||
if ((current_framebuffer != 0 && !fb.has_depth_buffer) || fb.depth_copy_failed) {
|
||||
return false;
|
||||
}
|
||||
if (!depth_copy_dirty && depth_copy_source == current_framebuffer && depth_copy_width == fb.width &&
|
||||
depth_copy_height == fb.height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (depth_copy_tex == 0 || depth_copy_width != fb.width || depth_copy_height != fb.height) {
|
||||
if (depth_copy_tex == 0) {
|
||||
glGenTextures(1, &depth_copy_tex);
|
||||
glGenFramebuffers(1, &depth_copy_fbo);
|
||||
}
|
||||
|
||||
GLint active_texture;
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
|
||||
glActiveTexture(GL_TEXTURE0 + DECAL_DEPTH_TEXTURE_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, depth_copy_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, fb.width, fb.height, 0, GL_DEPTH_STENCIL,
|
||||
GL_UNSIGNED_INT_24_8, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glActiveTexture(active_texture);
|
||||
|
||||
const GLenum no_draw_buffer = GL_NONE;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, depth_copy_fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth_copy_tex, 0);
|
||||
glDrawBuffers(1, &no_draw_buffer);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
depth_copy_width = fb.width;
|
||||
depth_copy_height = fb.height;
|
||||
}
|
||||
|
||||
const bool check_errors = !fb.depth_copy_checked;
|
||||
if (check_errors) {
|
||||
for (int i = 0; i < 16 && glGetError() != GL_NO_ERROR; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, depth_copy_fbo);
|
||||
glBlitFramebuffer(0, 0, fb.width, fb.height, 0, 0, fb.width, fb.height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.fbo);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
if (check_errors) {
|
||||
fb.depth_copy_checked = true;
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
fb.depth_copy_failed = true;
|
||||
sysLogPrintf(LOG_WARNING, "GL: could not copy depth buffer of framebuffer %u, decal edges will not be clipped",
|
||||
(unsigned)current_framebuffer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
depth_copy_dirty = false;
|
||||
depth_copy_source = current_framebuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_decal_uniforms(struct ShaderProgram* prg, bool enabled) {
|
||||
if (prg == nullptr || prg->decal_mode_location < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int mode = enabled ? 1 : 0;
|
||||
if (prg->decal_mode != mode) {
|
||||
glUniform1i(prg->decal_mode_location, mode);
|
||||
prg->decal_mode = mode;
|
||||
}
|
||||
|
||||
const float scale = framebuffers[current_framebuffer].height / DECAL_N64_SCREEN_HEIGHT;
|
||||
if (enabled && prg->decal_scale != scale) {
|
||||
glUniform1f(prg->decal_scale_location, scale);
|
||||
prg->decal_scale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_opengl_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) {
|
||||
// printf("flushing %d tris\n", buf_vbo_num_tris);
|
||||
if (current_depth_decal) {
|
||||
// The shader replaces the depth test like the RDP does; fall back to polygon offset if depth can't be copied
|
||||
const bool decal = gfx_opengl_update_depth_copy();
|
||||
glDepthFunc(decal ? GL_ALWAYS : GL_LEQUAL);
|
||||
if (decal) {
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
} else {
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
}
|
||||
gfx_opengl_set_decal_uniforms(current_shader_program, decal);
|
||||
} else {
|
||||
gfx_opengl_set_decal_uniforms(current_shader_program, false);
|
||||
}
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * buf_vbo_len, buf_vbo, GL_STREAM_DRAW);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris);
|
||||
|
||||
if (current_depth_test && current_depth_mask) {
|
||||
depth_copy_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (APIENTRY *DEBUGPROC)(GLenum source,
|
||||
@@ -990,6 +1140,11 @@ static void gfx_opengl_init(void) {
|
||||
gfx_framebuffers_enabled = false;
|
||||
}
|
||||
|
||||
depth_copy_supported = GLVersion.major >= 3 && gfx_opengl_supports_framebuffers() && glDrawBuffers && glReadBuffer;
|
||||
if (!depth_copy_supported) {
|
||||
sysLogPrintf(LOG_WARNING, "GL: depth buffer copies unsupported, decal edges will not be clipped");
|
||||
}
|
||||
|
||||
if ((GLVersion.major < 4 || GLVersion.minor < 4) && !GLAD_GL_ARB_texture_mirror_clamp_to_edge) {
|
||||
// GL_MIRROR_CLAMP_TO_EDGE unsupported
|
||||
gl_mirror_clamp = GL_MIRRORED_REPEAT;
|
||||
@@ -1138,6 +1293,7 @@ static void gfx_opengl_update_framebuffer_parameters(int fb_id, uint32_t width,
|
||||
fb.has_depth_buffer = has_depth_buffer;
|
||||
fb.msaa_level = msaa_level;
|
||||
fb.invert_y = opengl_invert_y;
|
||||
depth_copy_dirty = true;
|
||||
}
|
||||
|
||||
bool gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) {
|
||||
@@ -1148,6 +1304,7 @@ bool gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) {
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.fbo);
|
||||
current_framebuffer = fb_id;
|
||||
depth_copy_dirty = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -1165,6 +1322,7 @@ void gfx_opengl_clear_framebuffer(bool clear_color, bool clear_depth) {
|
||||
if (clear_depth) {
|
||||
glDepthMask(GL_TRUE);
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
depth_copy_dirty = true;
|
||||
}
|
||||
glClear(mask);
|
||||
if (clear_depth) {
|
||||
|
||||
@@ -170,6 +170,8 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
|
||||
configRegisterInt("Game.DisableMpDeathMusic", &g_MusicDisableMpDeath, 0, 1);
|
||||
configRegisterInt("Game.GEMuzzleFlashes", &g_BgunGeMuzzleFlashes, 0, 1);
|
||||
configRegisterInt("Game.MaxExplosions", &g_MaxExplosions, 6, 96);
|
||||
configRegisterInt("Game.DecalLimitMultiplier", &g_DecalLimitMultiplier, 1, MAX_DECAL_LIMIT_MULTIPLIER);
|
||||
configRegisterInt("Game.MaxCorpses", &g_MaxCorpses, -1, MAX_CORPSES_LIMIT); // -1 = never fade
|
||||
for (s32 j = 0; j < MAX_PLAYERS; ++j) {
|
||||
const s32 i = j + 1;
|
||||
configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f);
|
||||
|
||||
@@ -1833,7 +1833,12 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if (controlmode == CONTROLMODE_12 || controlmode == CONTROLMODE_14 || controlmode == CONTROLMODE_PC) {
|
||||
#else
|
||||
// The PC controls walk with an analog stick like 1.1, so look ahead works there (see below)
|
||||
if (controlmode == CONTROLMODE_12 || controlmode == CONTROLMODE_14) {
|
||||
#endif
|
||||
movedata.disablelookahead = true;
|
||||
}
|
||||
} // end 1.x
|
||||
@@ -1992,6 +1997,22 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
lookahead = g_Vars.currentplayer->cachedlookahead;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// PC controls pitch with the right stick or mouse (natural pitch), which the N64 code never
|
||||
// treats as manual pitch. Do what C-up/C-down does: stop the centring until the next walk,
|
||||
// or until the walk stops if already walking.
|
||||
// A deliberate stick deflection only: a resting stick can drift past the small dead zone
|
||||
if (controlmode == CONTROLMODE_PC
|
||||
&& (movedata.analogpitch > 15 || movedata.analogpitch < -15 || movedata.freelookdy != 0.0f)) {
|
||||
g_Vars.currentplayer->docentreupdown = false;
|
||||
g_Vars.currentplayer->automovecentre = false;
|
||||
|
||||
if (movedata.canlookahead && (movedata.analogwalk > 60 || movedata.analogwalk < -60)) {
|
||||
g_Vars.currentplayer->movecentrerelease = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (g_Vars.currentplayer->movecentrerelease
|
||||
&& movedata.analogwalk < 40 && movedata.analogwalk > -40) {
|
||||
g_Vars.currentplayer->movecentrerelease = false;
|
||||
@@ -2241,6 +2262,13 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
y = (y < -1.f) ? -1.f : ((y > 1.f) ? 1.f : y);
|
||||
g_Vars.currentplayer->swivelpos[0] = x;
|
||||
g_Vars.currentplayer->swivelpos[1] = y;
|
||||
|
||||
// The stick still offsets the crosshair, as in the stick-only path below, so gyro (sent as mouse)
|
||||
// and stick aiming combine
|
||||
x += (movedata.c1stickxraw * 0.65f) / 80.0f;
|
||||
y += (movedata.c1stickyraw * 0.65f) / 80.0f;
|
||||
x = (x < -1.f) ? -1.f : ((x > 1.f) ? 1.f : x);
|
||||
y = (y < -1.f) ? -1.f : ((y > 1.f) ? 1.f : y);
|
||||
bgunSwivelWithDamp(x, y, 0.01f);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2633,6 +2633,19 @@ s32 chrTick(struct prop *prop)
|
||||
}
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_MaxCorpses != 0 && !g_Vars.normmplayerisrunning && needsupdate) {
|
||||
// Kept corpses are drawn rather than deleted, and don't count towards the visible chr budget
|
||||
if (chr->actiontype != ACT_DEAD
|
||||
&& (chr->actiontype != ACT_DRUGGEDKO || (chr->chrflags & CHRCFLAG_KEEPCORPSEKO))) {
|
||||
var8009cdb0++;
|
||||
|
||||
if (var8009cdb0 > 30) {
|
||||
needsupdate = false;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (!g_Vars.normmplayerisrunning && needsupdate) {
|
||||
if (chr->actiontype == ACT_DEAD
|
||||
|| (chr->actiontype == ACT_DRUGGEDKO && (chr->chrflags & CHRCFLAG_KEEPCORPSEKO) == 0)) {
|
||||
|
||||
+35
-8
@@ -7199,7 +7199,14 @@ bool chrTrySurrender(struct chrdata *chr)
|
||||
bool chrFadeOut(struct chrdata *chr)
|
||||
{
|
||||
chrBeginDead(chr);
|
||||
#ifndef PLATFORM_N64
|
||||
// Scripted removals still fade when corpses are kept forever
|
||||
if (chr->actiontype == ACT_DEAD || chr->actiontype == ACT_DRUGGEDKO) {
|
||||
chr->act_dead.fadenow = true;
|
||||
}
|
||||
#else
|
||||
chrFadeCorpse(chr);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -8197,6 +8204,12 @@ void chrTickSurrender(struct chrdata *chr)
|
||||
|
||||
void chrFadeCorpse(struct chrdata *chr)
|
||||
{
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_MaxCorpses < 0 && chr->aibot == NULL) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (chr->actiontype == ACT_DEAD || chr->actiontype == ACT_DRUGGEDKO) {
|
||||
chr->act_dead.fadenow = true;
|
||||
}
|
||||
@@ -8204,6 +8217,12 @@ void chrFadeCorpse(struct chrdata *chr)
|
||||
|
||||
void chrFadeCorpseWhenOffScreen(struct chrdata *chr)
|
||||
{
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_MaxCorpses < 0 && chr->aibot == NULL) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (chr->actiontype == ACT_DEAD) {
|
||||
chr->act_dead.fadewheninvis = true;
|
||||
}
|
||||
@@ -13459,6 +13478,10 @@ void cutsceneStart(u32 ailistid)
|
||||
* - Run BG scripts
|
||||
* - Choose which corpses to fade
|
||||
*/
|
||||
// 0 keeps the original corpse limits, -1 never fades corpses, otherwise the number of corpses kept on screen,
|
||||
// off screen and spawned
|
||||
s32 g_MaxCorpses = 0;
|
||||
|
||||
void chraTickBg(void)
|
||||
{
|
||||
s32 i;
|
||||
@@ -13470,10 +13493,10 @@ void chraTickBg(void)
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
s32 spawnslen;
|
||||
#endif
|
||||
struct chrdata *onscreen[5];
|
||||
struct chrdata *offscreen[5];
|
||||
struct chrdata *onscreen[MAX_CORPSES_LIMIT];
|
||||
struct chrdata *offscreen[MAX_CORPSES_LIMIT];
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
struct chrdata *spawns[10];
|
||||
struct chrdata *spawns[MAX_CORPSES_LIMIT];
|
||||
#endif
|
||||
s32 writeindex;
|
||||
s32 maxdeadonscreen;
|
||||
@@ -13599,7 +13622,7 @@ void chraTickBg(void)
|
||||
spawns[spawnslen] = chr;
|
||||
spawnslen++;
|
||||
|
||||
if (spawnslen >= 10) {
|
||||
if (spawnslen >= (g_MaxCorpses > 0 ? g_MaxCorpses : 10)) {
|
||||
writeindex = rngRandom() % spawnslen;
|
||||
chrFadeCorpse(spawns[writeindex]);
|
||||
spawns[writeindex] = spawns[spawnslen - 1];
|
||||
@@ -13620,12 +13643,16 @@ void chraTickBg(void)
|
||||
// 5 chrs (alive or dead) to keep the number of polygons low.
|
||||
maxdeadonscreen = 5 - numaliveonscreen;
|
||||
|
||||
if (g_MaxCorpses > 0) {
|
||||
maxdeadonscreen = g_MaxCorpses;
|
||||
}
|
||||
|
||||
// If the game is lagging, take the number of 60ths over 6 since the
|
||||
// previous frame and reduce the limit by that amount. So if it's been, say,
|
||||
// 8 60ths since the last frame then the max corpses will be reduced by 2.
|
||||
// This is why corpses are more likely to fade on screen when you change
|
||||
// weapons - the lag spike from changing guns triggers a lower corpse limit.
|
||||
if (g_Vars.lvupdate60 > 6) {
|
||||
if (g_Vars.lvupdate60 > 6 && g_MaxCorpses == 0) {
|
||||
maxdeadonscreen = maxdeadonscreen - g_Vars.lvupdate60 + 6;
|
||||
}
|
||||
|
||||
@@ -13651,7 +13678,7 @@ void chraTickBg(void)
|
||||
#else
|
||||
// Decide which corpses to fade.
|
||||
// NTSC Beta implements its engagement counter here.
|
||||
if (numdeadonscreen) {
|
||||
if (numdeadonscreen && g_MaxCorpses >= 0) {
|
||||
numdeadonscreen = 0;
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
onscreenlen = 0;
|
||||
@@ -13690,7 +13717,7 @@ void chraTickBg(void)
|
||||
onscreen[onscreenlen] = chr;
|
||||
onscreenlen++;
|
||||
|
||||
if (onscreenlen >= (VERSION >= VERSION_NTSC_1_0 ? 2 : 3)) {
|
||||
if (onscreenlen >= (g_MaxCorpses > 0 ? g_MaxCorpses : (VERSION >= VERSION_NTSC_1_0 ? 2 : 3))) {
|
||||
writeindex = rngRandom() % onscreenlen;
|
||||
chrFadeCorpseWhenOffScreen(onscreen[writeindex]);
|
||||
onscreen[writeindex] = onscreen[onscreenlen - 1];
|
||||
@@ -13705,7 +13732,7 @@ void chraTickBg(void)
|
||||
offscreenlen++;
|
||||
|
||||
// Allow up to 5 corpses off-screen
|
||||
if (offscreenlen >= (VERSION >= VERSION_NTSC_1_0 ? 5 : 6)) {
|
||||
if (offscreenlen >= (g_MaxCorpses > 0 ? g_MaxCorpses : (VERSION >= VERSION_NTSC_1_0 ? 5 : 6))) {
|
||||
writeindex = rngRandom() % offscreenlen;
|
||||
|
||||
if (offscreen[writeindex]->actiontype != ACT_DEAD) {
|
||||
|
||||
+22
-8
@@ -111,15 +111,29 @@ void gfxReset(void)
|
||||
g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1] = strtol(argFindByPrefix(1, "-mvtx"), NULL, 0) * 1024;
|
||||
}
|
||||
|
||||
// %d Players : Allocating %d bytes for master dl's\n
|
||||
g_GfxBuffers[0] = mempAlloc(g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1] * NUM_GFXTASKS, MEMPOOL_STAGE);
|
||||
g_GfxBuffers[1] = g_GfxBuffers[0] + g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1];
|
||||
g_GfxBuffers[2] = g_GfxBuffers[1] + g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1];
|
||||
{
|
||||
u32 gfxsize = g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1];
|
||||
u32 vtxsize = g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1];
|
||||
|
||||
// Allocating %d bytes for mtxvtx space\n
|
||||
g_VtxBuffers[0] = mempAlloc(g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1] * NUM_GFXTASKS, MEMPOOL_STAGE);
|
||||
g_VtxBuffers[1] = g_VtxBuffers[0] + g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1];
|
||||
g_VtxBuffers[2] = g_VtxBuffers[1] + g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1];
|
||||
#ifndef PLATFORM_N64
|
||||
// Each extra rendered decal needs display list commands and per-frame colours
|
||||
if (g_DecalLimitMultiplier > 1) {
|
||||
u32 extradecals = 360 * (g_DecalLimitMultiplier - 1);
|
||||
gfxsize = ALIGN16(gfxsize + extradecals * 6 * sizeof(Gfx));
|
||||
vtxsize = ALIGN16(vtxsize + extradecals * 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
// %d Players : Allocating %d bytes for master dl's\n
|
||||
g_GfxBuffers[0] = mempAlloc(gfxsize * NUM_GFXTASKS, MEMPOOL_STAGE);
|
||||
g_GfxBuffers[1] = g_GfxBuffers[0] + gfxsize;
|
||||
g_GfxBuffers[2] = g_GfxBuffers[1] + gfxsize;
|
||||
|
||||
// Allocating %d bytes for mtxvtx space\n
|
||||
g_VtxBuffers[0] = mempAlloc(vtxsize * NUM_GFXTASKS, MEMPOOL_STAGE);
|
||||
g_VtxBuffers[1] = g_VtxBuffers[0] + vtxsize;
|
||||
g_VtxBuffers[2] = g_VtxBuffers[1] + vtxsize;
|
||||
}
|
||||
|
||||
g_GfxActiveBufferIndex = 0;
|
||||
g_GfxRequestedDisplayList = false;
|
||||
|
||||
+1
-1
@@ -1996,7 +1996,7 @@ MenuItemHandlerResult menuhandlerMissionList(s32 operation, struct menuitem *ite
|
||||
texSelect(&gdl, g_TexGeneralConfigs + 13 + stageindex, 2, 0, 2, true, NULL);
|
||||
gDPSetCycleType(gdl++, G_CYC_1CYCLE);
|
||||
gDPSetCombineMode(gdl++, G_CC_CUSTOM_00, G_CC_CUSTOM_00);
|
||||
gDPSetTextureFilter(gdl++, G_TF_POINT);
|
||||
gDPSetTextureFilter(gdl++, G_TF_AVERAGE);
|
||||
gDPSetEnvColorViaWord(gdl++, 0xffffff00 | ((renderdata->colour & 0xff) * 255 / 256));
|
||||
#else
|
||||
texSelect(&gdl, g_TexGeneralConfigs + 13 + stageindex, 1, 0, 2, true, NULL);
|
||||
|
||||
@@ -1400,6 +1400,14 @@ void setupLoadFiles(s32 stagenum)
|
||||
numobjs += g_Vars.numaibuddies; // the buddy's weapon
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// Kept corpses hold on to their slots, so reserve extra ones for spawned chrs and their weapons
|
||||
if (!g_Vars.normmplayerisrunning) {
|
||||
numchrs += g_MaxCorpses < 0 ? MAX_CORPSES_LIMIT : g_MaxCorpses;
|
||||
numobjs += g_MaxCorpses < 0 ? MAX_CORPSES_LIMIT : g_MaxCorpses;
|
||||
}
|
||||
#endif
|
||||
|
||||
numobjs += setupCountCommandType(OBJTYPE_WEAPON);
|
||||
numobjs += setupCountCommandType(OBJTYPE_KEY);
|
||||
numobjs += setupCountCommandType(OBJTYPE_HAT);
|
||||
@@ -1531,6 +1539,12 @@ void setupCreateProps(s32 stagenum)
|
||||
numchrs += g_Vars.numaibuddies;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (!g_Vars.normmplayerisrunning) {
|
||||
numchrs += g_MaxCorpses < 0 ? MAX_CORPSES_LIMIT : g_MaxCorpses;
|
||||
}
|
||||
#endif
|
||||
|
||||
chrmgrConfigure(numchrs);
|
||||
} else {
|
||||
chrmgrConfigure(0);
|
||||
|
||||
@@ -20,6 +20,7 @@ u32 var8009cc6c;
|
||||
s32 g_WallhitsCriticalSpareLimit;
|
||||
s32 g_WallhitsGoalSpareLimit;
|
||||
f32 g_WallhitTargetBloodRatio;
|
||||
s32 g_DecalLimitMultiplier = 1;
|
||||
|
||||
/**
|
||||
* Initialises an array of room numbers and a linked list of structs.
|
||||
@@ -81,6 +82,19 @@ void wallhitReset(void)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_DecalLimitMultiplier > 1) {
|
||||
g_WallhitsMax *= g_DecalLimitMultiplier;
|
||||
g_MinPropWallhits *= g_DecalLimitMultiplier;
|
||||
g_MaxPropWallhits *= g_DecalLimitMultiplier;
|
||||
g_MinBgWallhitsPerRoom *= g_DecalLimitMultiplier;
|
||||
g_MaxBgWallhitsPerRoom *= g_DecalLimitMultiplier;
|
||||
var8009cc6c *= g_DecalLimitMultiplier;
|
||||
g_WallhitsCriticalSpareLimit *= g_DecalLimitMultiplier;
|
||||
g_WallhitsGoalSpareLimit *= g_DecalLimitMultiplier;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_WallhitCountsPerRoom = NULL;
|
||||
g_WallhitsNumSettled = 0;
|
||||
g_WallhitsNumFree = 0;
|
||||
|
||||
@@ -201,6 +201,8 @@ extern u32 g_SkyStageNum;
|
||||
extern bool g_SkyLightningActive;
|
||||
extern struct explosion *g_Explosions;
|
||||
extern s32 g_MaxExplosions;
|
||||
extern s32 g_DecalLimitMultiplier;
|
||||
extern s32 g_MaxCorpses;
|
||||
extern struct smoke *g_Smokes;
|
||||
extern s32 g_MaxSmokes;
|
||||
extern Mtx var800a3448;
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#define MAX_SQUADRONS 16
|
||||
#define MAX_TEAMS 8
|
||||
#define MAX_EXPLOSIONS_DEFAULT 6
|
||||
#define MAX_DECAL_LIMIT_MULTIPLIER 10
|
||||
#define MAX_CORPSES_LIMIT 64
|
||||
|
||||
#define NUM_BOTDIFFS 6
|
||||
#define NUM_CYCLEABLE_WEAPONS 45
|
||||
|
||||
Reference in new issue
Block a user