diff --git a/include/PR/ultratypes.h b/include/PR/ultratypes.h index ddff2827..1ebde775 100644 --- a/include/PR/ultratypes.h +++ b/include/PR/ultratypes.h @@ -31,6 +31,8 @@ typedef double f64; #include #include +#include + #if defined(__MINGW32__) #include <_mingw.h> #if !defined(__MINGW64_VERSION_MAJOR) @@ -39,4 +41,5 @@ typedef long ssize_t; typedef ptrdiff_t ssize_t; #endif #endif -#endif + +#endif // _ULTRA64_TYPES_H_ diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index db8c04f8..1dbe2f3b 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -74,9 +74,9 @@ struct newcam_hardpos newcam_fixedcam[] = #endif // noaccel s16 newcam_yaw; //Z axis rotation -s8 newcam_yaw_acc; +f32 newcam_yaw_acc; s16 newcam_tilt = 1500; //Y axis rotation -s8 newcam_tilt_acc; +f32 newcam_tilt_acc; u16 newcam_distance = 750; //The distance the camera stays from the player u16 newcam_distance_target = 750; //The distance the player camera tries to reach. f32 newcam_pos_target[3]; //The position the camera is basing calculations off. *usually* Mario. @@ -187,14 +187,20 @@ void newcam_diagnostics(void) print_text_fmt_int(32,32,"DISTANCE %d",newcam_distance); } -static s16 newcam_adjust_value(s16 var, s16 val) +static s16 newcam_adjust_value(s16 var, s16 val, s8 max) { - var += val; - if (var > 100) - var = 100; - if (var < -100) - var = -100; - + if (val > 0) + { + var += val; + if (var > max) + var = max; + } + else if (val < 0) + { + var += val; + if (var < max) + var = max; + } return var; } @@ -234,6 +240,8 @@ static int ivrt(u8 axis) static void newcam_rotate_button(void) { + f32 intendedXMag; + f32 intendedYMag; if ((newcam_modeflags & NC_FLAG_8D || newcam_modeflags & NC_FLAG_4D) && newcam_modeflags & NC_FLAG_XTURN) //8 directional camera rotation input for buttons. { if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_analogue == 0) @@ -264,27 +272,33 @@ static void newcam_rotate_button(void) if (newcam_modeflags & NC_FLAG_XTURN) { if ((gPlayer1Controller->buttonDown & L_CBUTTONS) && newcam_analogue == 0) - newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,accel); + newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,accel, 100); else if ((gPlayer1Controller->buttonDown & R_CBUTTONS) && newcam_analogue == 0) - newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,-accel); + newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,-accel, -100); else + if (!newcam_analogue) + { #ifdef noaccel newcam_yaw_acc = 0; #else newcam_yaw_acc -= (newcam_yaw_acc*newcam_degrade); #endif + } } if (gPlayer1Controller->buttonDown & U_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0) - newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,accel); + newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,accel, 100); else if (gPlayer1Controller->buttonDown & D_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0) - newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,-accel); + newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,-accel, -100); else + if (!newcam_analogue) + { #ifdef noaccel newcam_tilt_acc = 0; #else newcam_tilt_acc -= (newcam_tilt_acc*newcam_degrade); #endif + } newcam_framessincec[0] += 1; newcam_framessincec[1] += 1; @@ -316,12 +330,14 @@ static void newcam_rotate_button(void) if (newcam_analogue == 1) //There's not much point in keeping this behind a check, but it wouldn't hurt, just incase any 2player shenanigans ever happen, it makes it easy to disable. { //The joystick values cap at 80, so divide by 8 to get the same net result at maximum turn as the button + intendedXMag = gPlayer2Controller->stickX*1.25; + intendedYMag = gPlayer2Controller->stickY*1.25; if (ABS(gPlayer2Controller->stickX) > 20 && newcam_modeflags & NC_FLAG_XTURN) { if (newcam_modeflags & NC_FLAG_8D) { if (newcam_cstick_down == 0) - { + { newcam_cstick_down = 1; newcam_centering = 1; #ifndef nosound @@ -344,18 +360,24 @@ static void newcam_rotate_button(void) } } else - newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,(-gPlayer2Controller->stickX/4)); + { + newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,-gPlayer2Controller->stickX/8, intendedXMag); + } } else + if (newcam_analogue) { newcam_cstick_down = 0; newcam_yaw_acc -= (newcam_yaw_acc*newcam_degrade); } if (ABS(gPlayer2Controller->stickY) > 20 && newcam_modeflags & NC_FLAG_YTURN) - newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,(-gPlayer2Controller->stickY/4)); + newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,-gPlayer2Controller->stickY/8, intendedYMag); else + if (newcam_analogue) + { newcam_tilt_acc -= (newcam_tilt_acc*newcam_degrade); + } } if (newcam_mouse == 1) @@ -417,9 +439,9 @@ static void newcam_update_values(void) {//For tilt, this just limits it so it doesn't go further than 90 degrees either way. 90 degrees is actually 16384, but can sometimes lead to issues, so I just leave it shy of 90. u8 waterflag = 0; if (newcam_modeflags & NC_FLAG_XTURN) - newcam_yaw += (ivrt(0)*(newcam_yaw_acc*(newcam_sensitivityX/10))); + newcam_yaw += ((ivrt(0)*(newcam_yaw_acc*(newcam_sensitivityX/10)))); if (((newcam_tilt < 12000 && newcam_tilt_acc*ivrt(1) > 0) || (newcam_tilt > -12000 && newcam_tilt_acc*ivrt(1) < 0)) && newcam_modeflags & NC_FLAG_YTURN) - newcam_tilt += (ivrt(1)*(newcam_tilt_acc*(newcam_sensitivityY/10))); + newcam_tilt += ((ivrt(1)*(newcam_tilt_acc*(newcam_sensitivityY/10)))); else { if (newcam_tilt > 12000) diff --git a/src/game/camera.c b/src/game/camera.c index deddc6d5..5ae68805 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -3080,6 +3080,12 @@ void update_camera(struct Camera *c) { sCButtonsPressed = find_c_buttons_pressed(sCButtonsPressed, gPlayer1Controller->buttonPressed,gPlayer1Controller->buttonDown); #ifdef BETTERCAMERA } + + if (gMarioState->action == ACT_SHOT_FROM_CANNON && newcam_active) + { + gMarioState->area->camera->mode = CAMERA_MODE_NEWCAM; + gLakituState.mode = CAMERA_MODE_NEWCAM; + } #endif if (c->cutscene != 0) { diff --git a/src/game/object_list_processor.h b/src/game/object_list_processor.h index 1bb5cb61..fde29d65 100644 --- a/src/game/object_list_processor.h +++ b/src/game/object_list_processor.h @@ -21,7 +21,12 @@ struct SpawnInfo; /** * The maximum number of objects that can be loaded at once. */ + +#ifdef NODRAWINGDISTANCE +#define OBJECT_POOL_CAPACITY 960 +#else #define OBJECT_POOL_CAPACITY 240 +#endif /** * Every object is categorized into an object list, which controls the order diff --git a/src/goddard/renderer.c b/src/goddard/renderer.c index 821f9aff..4fa77986 100644 --- a/src/goddard/renderer.c +++ b/src/goddard/renderer.c @@ -493,6 +493,7 @@ ALIGNED8 static u8 gd_texture_sparkle_4[] = { //! No reference to this texture. Two DL's uses the same previous texture // instead of using this texture. +// Fixed via setting TEXTURE_FIX to 1. ALIGNED8 static u8 gd_texture_sparkle_5[] = { #include "textures/intro_raw/sparkle_5.rgba16.inc.c" }; @@ -569,6 +570,7 @@ static Gfx gd_dl_red_sparkle_4[] = { gsSPBranchList(gd_dl_sparkle), }; +#ifndef TEXTURE_FIX static Gfx gd_dl_red_sparkle_4_dup[] ={ gsDPPipeSync(), gsSPDisplayList(gd_dl_sparkle_red_color), @@ -576,6 +578,15 @@ static Gfx gd_dl_red_sparkle_4_dup[] ={ gsSPBranchList(gd_dl_sparkle), }; +#else +static Gfx gd_dl_red_sparkle_5[] ={ + gsDPPipeSync(), + gsSPDisplayList(gd_dl_sparkle_red_color), + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, gd_texture_sparkle_5), + gsSPBranchList(gd_dl_sparkle), +}; +#endif + static Gfx gd_dl_silver_sparkle_0[] = { gsDPPipeSync(), gsSPDisplayList(gd_dl_sparkle_white_color), @@ -611,6 +622,7 @@ static Gfx gd_dl_silver_sparkle_4[] = { gsSPBranchList(gd_dl_sparkle), }; +#ifndef TEXTURE_FIX static Gfx gd_dl_silver_sparkle_4_dup[] = { gsDPPipeSync(), gsSPDisplayList(gd_dl_sparkle_white_color), @@ -618,6 +630,15 @@ static Gfx gd_dl_silver_sparkle_4_dup[] = { gsSPBranchList(gd_dl_sparkle), }; +#else +static Gfx gd_dl_silver_sparkle_5[] = { + gsDPPipeSync(), + gsSPDisplayList(gd_dl_sparkle_white_color), + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, gd_texture_sparkle_5), + gsSPBranchList(gd_dl_sparkle), +}; +#endif + static Gfx *gd_red_sparkle_dl_array[] = { gd_dl_red_sparkle_4, gd_dl_red_sparkle_4, @@ -629,8 +650,13 @@ static Gfx *gd_red_sparkle_dl_array[] = { gd_dl_red_sparkle_1, gd_dl_red_sparkle_0, gd_dl_red_sparkle_0, +#ifndef TEXTURE_FIX gd_dl_red_sparkle_4_dup, gd_dl_red_sparkle_4_dup, +#else + gd_dl_red_sparkle_5, + gd_dl_red_sparkle_5, +#endif }; static Gfx *gd_silver_sparkle_dl_array[] = { @@ -644,8 +670,13 @@ static Gfx *gd_silver_sparkle_dl_array[] = { gd_dl_silver_sparkle_1, gd_dl_silver_sparkle_0, gd_dl_silver_sparkle_0, +#ifndef TEXTURE_FIX gd_dl_silver_sparkle_4_dup, gd_dl_silver_sparkle_4_dup, +#else + gd_dl_silver_sparkle_5, + gd_dl_silver_sparkle_5, +#endif }; static Gfx gd_texture3_dummy_aligner1[] = { diff --git a/src/pc/gfx/gfx_opengl_legacy.c b/src/pc/gfx/gfx_opengl_legacy.c index aebe91b0..21dc4a00 100644 --- a/src/pc/gfx/gfx_opengl_legacy.c +++ b/src/pc/gfx/gfx_opengl_legacy.c @@ -25,6 +25,21 @@ #define GL_GLEXT_PROTOTYPES 1 #include +// redefine this if using a different GL loader +#define mglGetProcAddress(name) SDL_GL_GetProcAddress(name) + +// we'll define and load it manually in init, just in case +typedef void (*PFNMGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer); +static PFNMGLFOGCOORDPOINTERPROC mglFogCoordPointer = NULL; + +// since these can have different names, might as well redefine them to a single one +#undef GL_FOG_COORD_SRC +#undef GL_FOG_COORD +#undef GL_FOG_COORD_ARRAY +#define GL_FOG_COORD_SRC 0x8450 +#define GL_FOG_COORD 0x8451 +#define GL_FOG_COORD_ARRAY 0x8457 + #include "gfx_cc.h" #include "gfx_rendering_api.h" #include "macros.h" @@ -65,9 +80,12 @@ static uint8_t shader_program_pool_size; static struct ShaderProgram *cur_shader = NULL; static const float *cur_buf = NULL; +static const float *cur_fog_ofs = NULL; static size_t cur_buf_size = 0; static size_t cur_buf_num_tris = 0; static size_t cur_buf_stride = 0; +static bool gl_blend = false; +static bool gl_adv_fog = false; static const float c_white[] = { 1.f, 1.f, 1.f, 1.f }; @@ -186,13 +204,18 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) { } if (prg->shader_id & SHADER_OPT_FOG) { - // have fog, but fog colors are the same for every vertex - // TODO: alpha ain't the same, maybe use glSecondaryColorPointer? - // TODO: or pass start and end from gsSPFogPosition somehow or calculate them from z0, w0 and a0? - // TODO: or alpha blend solid triangles on top, using the fog factor as alpha - // glEnable(GL_FOG); - // glFogi(GL_FOG_MODE, GL_LINEAR); - // glFogfv(GL_FOG_COLOR, ofs); + // fog requested, we can deal with it in one of two ways + if (gl_adv_fog) { + // if GL_EXT_fog_coord is available, use the provided fog factor as scaled depth for GL fog + const float fogrgb[] = { ofs[0], ofs[1], ofs[2] }; + glEnable(GL_FOG); + glFogfv(GL_FOG_COLOR, fogrgb); // color is the same for all verts, only intensity is different + glEnableClientState(GL_FOG_COORD_ARRAY); + mglFogCoordPointer(GL_FLOAT, cur_buf_stride, ofs + 3); // point it to alpha, which is fog factor + } else { + // if there's no fog coords available, blend it on top of normal tris later + cur_fog_ofs = ofs; + } ofs += 4; } @@ -251,8 +274,11 @@ static void gfx_opengl_unload_shader(struct ShaderProgram *old_prg) { glDisable(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); + glDisable(GL_FOG); + cur_fog_ofs = NULL; // clear fog colors glDisableClientState(GL_COLOR_ARRAY); + if (gl_adv_fog) glDisableClientState(GL_FOG_COORD_ARRAY); } static void gfx_opengl_load_shader(struct ShaderProgram *new_prg) { @@ -401,6 +427,7 @@ static void gfx_opengl_set_scissor(int x, int y, int width, int height) { } static void gfx_opengl_set_use_alpha(bool use_alpha) { + gl_blend = use_alpha; if (use_alpha) { glEnable(GL_BLEND); } else { @@ -408,6 +435,32 @@ static void gfx_opengl_set_use_alpha(bool use_alpha) { } } +// draws the same triangles as plain fog color + fog intensity as alpha +// on top of the normal tris and blends them to achieve sort of the same effect +// as fog would +static inline void gfx_opengl_blend_fog_tris(void) { + // if a texture was used, replace it with fog color instead, but still keep the alpha + if (cur_shader->texture_used[0]) { + glActiveTexture(GL_TEXTURE0); + TEXENV_COMBINE_ON(); + // out.rgb = input0.rgb + TEXENV_COMBINE_SET1(RGB, GL_REPLACE, GL_PRIMARY_COLOR); + // out.a = texel0.a * input0.a + TEXENV_COMBINE_SET2(ALPHA, GL_MODULATE, GL_TEXTURE, GL_PRIMARY_COLOR); + } + + glEnableClientState(GL_COLOR_ARRAY); // enable color array temporarily + glColorPointer(4, GL_FLOAT, cur_buf_stride, cur_fog_ofs); // set fog colors as primary colors + if (!gl_blend) glEnable(GL_BLEND); // enable blending temporarily + glDepthFunc(GL_LEQUAL); // Z is the same as the base triangles + + glDrawArrays(GL_TRIANGLES, 0, 3 * cur_buf_num_tris); + + glDepthFunc(GL_LESS); // set back to default + if (!gl_blend) glDisable(GL_BLEND); // disable blending if it was disabled + glDisableClientState(GL_COLOR_ARRAY); // will get reenabled later anyway +} + 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); @@ -418,7 +471,10 @@ static void gfx_opengl_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_ gfx_opengl_apply_shader(cur_shader); - glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris); + glDrawArrays(GL_TRIANGLES, 0, 3 * cur_buf_num_tris); + + // cur_fog_ofs is only set if GL_EXT_fog_coord isn't used + if (cur_fog_ofs) gfx_opengl_blend_fog_tris(); } static inline bool gl_check_ext(const char *name) { @@ -428,10 +484,11 @@ static inline bool gl_check_ext(const char *name) { extstr = (const char *)glGetString(GL_EXTENSIONS); if (!strstr(extstr, name)) { - fprintf(stderr, "Required GL extension not supported: %s\n", name); + fprintf(stderr, "GL extension not supported: %s\n", name); return false; } + printf("GL extension detected: %s\n", name); return true; } @@ -465,16 +522,44 @@ static void gfx_opengl_init(void) { } // check extensions that we need - bool supported = + const bool supported = gl_check_ext("GL_ARB_multitexture") && gl_check_ext("GL_ARB_texture_env_combine"); if (!supported) abort(); + gl_adv_fog = false; + + // check whether we can use advanced fog shit + const bool fog_ext = + vmajor > 1 || vminor > 3 || + gl_check_ext("GL_EXT_fog_coord") || + gl_check_ext("GL_ARB_fog_coord"); + + if (fog_ext) { + // try to load manually, as this might be an extension, and even then the ext list may lie + mglFogCoordPointer = mglGetProcAddress("glFogCoordPointer"); + if (!mglFogCoordPointer) mglFogCoordPointer = mglGetProcAddress("glFogCoordPointerEXT"); + if (!mglFogCoordPointer) mglFogCoordPointer = mglGetProcAddress("glFogCoordPointerARB"); + if (!mglFogCoordPointer) + printf("glFogCoordPointer is not actually available, it won't be used.\n"); + else + gl_adv_fog = true; // appears to be all good + } + printf("GL_VERSION = %s\n", glGetString(GL_VERSION)); printf("GL_EXTENSIONS =\n%s\n", glGetString(GL_EXTENSIONS)); - // these never change + if (gl_adv_fog) { + // set fog params, they never change + printf("GL_EXT_fog_coord available, using that for fog\n"); + glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD); + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_START, 0.0f); + glFogf(GL_FOG_END, 1.0f); + } + + // these also never change glEnableClientState(GL_VERTEX_ARRAY); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, c_white); diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 01bea71f..e2aadfa1 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -155,24 +155,37 @@ static size_t buf_vbo_num_tris; static struct GfxWindowManagerAPI *gfx_wapi; static struct GfxRenderingAPI *gfx_rapi; -#if defined(__MINGW32__) -#include <_mingw.h> -#if !defined(__MINGW64_VERSION_MAJOR) +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && !defined(__APPLE__) +// old mingw +# include <_mingw.h> +# define NO_CLOCK_GETTIME +#endif + +#ifdef NO_CLOCK_GETTIME + +#if defined(_WIN32) #include #define CLOCK_MONOTONIC 0 -//https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows -struct timespec { long tv_sec; long tv_nsec; }; //header part -int clock_gettime(int arg, struct timespec *spec) //C-file part -{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); - wintime -=116444736000000000LL; //1jan1601 to 1jan1970 - spec->tv_sec =wintime / 10000000LL; //seconds - spec->tv_nsec =wintime % 10000000LL*100; //nano-seconds - return 0; +// https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows +struct timespec { long tv_sec; long tv_nsec; }; +int clock_gettime(int arg, struct timespec *spec) { + __int64 wintime; + GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -= 116444736000000000LL; //1jan1601 to 1jan1970 + spec->tv_sec = wintime / 10000000LL; //seconds + spec->tv_nsec = wintime % 10000000LL*100; //nano-seconds + return 0; } -#else +#else // _WIN32 +#error "Add a clock_gettime() impl for your platform!" +#endif // _WIN32 + +#else // NO_CLOCK_GETTIME + #include -#endif -#endif + +#endif // NO_CLOCK_GETTIME + static unsigned long get_time(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);