From 889ae950fef08ec468ce10e05733be56f4ed2606 Mon Sep 17 00:00:00 2001 From: GreaseMonkey Date: Tue, 29 Aug 2023 10:16:52 +1200 Subject: [PATCH 01/18] Fix a few cases of UB incl. OoB Behaviour should be mostly the same but there are some OoB accesses in the menu code where I've had to assume things. Tests for each OoB case: - Accessing of layer -1: Select a game file in the "Choose Your Reality" screen. - Accessing of menu for the 5th player: Die in a mission. --- src/game/camera.c | 9 +++++++++ src/game/gfxreplace.c | 4 ++++ src/game/menu.c | 21 +++++++++++++++++++++ src/lib/mp3/decoder.c | 4 ++-- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/game/camera.c b/src/game/camera.c index 92996ae26..c47490563 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -1,4 +1,5 @@ #include +#include #include "constants.h" #include "game/atan2f.h" #include "game/camera.h" @@ -600,6 +601,9 @@ bool camIsPosInFovAndVisibleRoom(RoomNum *rooms, struct coord *pos, f32 arg2) RoomNum room; bool hasdata = false; struct drawslot *thisthing; +#ifdef AVOID_UB + static struct drawslot dslot; +#endif struct screenbox box; for (i = 0, room = rooms[i]; room != -1; i++, room = rooms[i]) { @@ -637,5 +641,10 @@ bool camIsPosInFovAndVisibleRoom(RoomNum *rooms, struct coord *pos, f32 arg2) return false; } +#ifdef AVOID_UB + memcpy(&dslot.box, &box, sizeof(box)); + return camIsPosInScreenBox(pos, arg2, &dslot); +#else return camIsPosInScreenBox(pos, arg2, (struct drawslot *) &(((u8 *) &box)[-((uintptr_t) &(((struct drawslot *)0)->box))])); +#endif } diff --git a/src/game/gfxreplace.c b/src/game/gfxreplace.c index 73174e085..2d03b8b4b 100644 --- a/src/game/gfxreplace.c +++ b/src/game/gfxreplace.c @@ -329,7 +329,11 @@ void gfxReplaceGbiCommands(Gfx *startgdl, Gfx *endgdl, s32 type) void gfxReplaceGbiCommandsRecursively(struct roomblock *block, s32 type) { +#ifndef AVOID_UB + // Sometimes block is NULL when this is called. + // If UBSan is being used, this will crash in this instance. if (block->type == ROOMBLOCKTYPE_PARENT); +#endif while (true) { if (!block) { diff --git a/src/game/menu.c b/src/game/menu.c index cee8361a4..464def658 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -3413,8 +3413,14 @@ void menuClose(void) void func0f0f8120(void) { +#ifdef AVOID_UB + u32 mpindex = g_MpPlayerNum % MAX_PLAYERS; + struct menudialog *prev = g_Menus[mpindex].curdialog; + s32 i; +#else struct menudialog *prev = g_Menus[g_MpPlayerNum].curdialog; s32 i; +#endif if (g_MenuData.unk66e > 0) { for (i = g_MenuData.unk66e; i >= 0; i--) { @@ -3422,11 +3428,22 @@ void func0f0f8120(void) } } +#ifdef AVOID_UB + mpindex = g_MpPlayerNum; + if (mpindex >= MAX_PLAYERS) + mpindex -= MAX_PLAYERS; + if (g_Menus[mpindex].curdialog == prev) { + while (g_Menus[mpindex].depth > 0) { + menuPopDialog(); + } + } +#else if (g_Menus[g_MpPlayerNum].curdialog == prev) { while (g_Menus[g_MpPlayerNum].depth > 0) { menuPopDialog(); } } +#endif } void func0f0f820c(struct menudialogdef *dialogdef, s32 root) @@ -4340,7 +4357,11 @@ void dialogTick(struct menudialog *dialog, struct menuinputs *inputs, u32 tickfl } // Apply default navigational behaviour if requested +#ifdef AVOID_UB + if (usedefaultbehaviour && (tickflags & MENUTICKFLAG_DIALOGISCURRENT) && !dialog->dimmed && g_Menus[g_MpPlayerNum].depth >= 1) { +#else if (usedefaultbehaviour && (tickflags & MENUTICKFLAG_DIALOGISCURRENT) && !dialog->dimmed) { +#endif struct menulayer *layer = &g_Menus[g_MpPlayerNum].layers[g_Menus[g_MpPlayerNum].depth - 1]; if (layer->numsiblings <= 1) { diff --git a/src/lib/mp3/decoder.c b/src/lib/mp3/decoder.c index 5751abbb0..11383b68d 100644 --- a/src/lib/mp3/decoder.c +++ b/src/lib/mp3/decoder.c @@ -2736,8 +2736,8 @@ bool mp3dec000427d8(struct asistream *stream, u32 gr) f32 *sp0c = stream->unk4664[0][0].unk00; s32 i = 0; - if (stream->window_switching[gr][0] && stream->window_switching[gr][2] == 2) { - if (stream->window_switching[gr][4]) { + if (stream->window_switching[gr][0] && stream->block_type[gr][0] == 2) { + if (stream->mixed_block_flag[gr][0]) { while (i++ < 36) { *(sp10++) = *(sp0c++); } From 43a91b2b4b5147291e2108ce0e62fbaa5617601c Mon Sep 17 00:00:00 2001 From: GreaseMonkey Date: Tue, 29 Aug 2023 13:11:58 +1200 Subject: [PATCH 02/18] Fix "mpindex=4" UB cases for various view gadgets --- src/game/bondview.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/game/bondview.c b/src/game/bondview.c index 2b24a6516..2ced8b44f 100644 --- a/src/game/bondview.c +++ b/src/game/bondview.c @@ -1952,6 +1952,9 @@ Gfx *bviewDrawNvLens(Gfx *gdl) s32 viewbottom = viewtop + viewheight; s32 brightness; s32 y; +#ifdef AVOID_UB + u32 mpindex = g_Vars.currentplayerstats->mpindex % MAX_PLAYERS; +#endif var8007f840++; @@ -1973,9 +1976,15 @@ Gfx *bviewDrawNvLens(Gfx *gdl) skySetOverexposure(brightness, brightness, brightness); } +#ifdef AVOID_UB + if (g_Menus[mpindex].curdialog == NULL) { + gdl = bviewDrawMotionBlur(gdl, 0x00ff0000, 0x60); + } +#else if (g_Menus[g_Vars.currentplayerstats->mpindex].curdialog == NULL) { gdl = bviewDrawMotionBlur(gdl, 0x00ff0000, 0x60); } +#endif gDPPipeSync(gdl++); @@ -2034,6 +2043,9 @@ Gfx *bviewDrawIrLens(Gfx *gdl) s32 viewcentrey; f32 viewheightf; s32 a0; +#ifdef AVOID_UB + u32 mpindex = g_Vars.currentplayerstats->mpindex % MAX_PLAYERS; +#endif #if VERSION < VERSION_NTSC_1_0 static s32 fsscanline = 0; @@ -2198,9 +2210,15 @@ Gfx *bviewDrawIrLens(Gfx *gdl) #endif } +#ifdef AVOID_UB + if (g_Menus[mpindex].curdialog == NULL) { + gdl = bviewDrawMotionBlur(gdl, 0xff000000, 0x40); + } +#else if (g_Menus[g_Vars.currentplayerstats->mpindex].curdialog == NULL) { gdl = bviewDrawMotionBlur(gdl, 0xff000000, 0x40); } +#endif return gdl; } From 9eb3ffcc30184c67bb8873ef39d9ffbfc1831dc6 Mon Sep 17 00:00:00 2001 From: Phnod Date: Fri, 1 Sep 2023 00:02:47 -0400 Subject: [PATCH 03/18] port: add a config option to disable texture filtering on fonts --- port/include/video.h | 1 + port/src/video.c | 8 ++++++++ src/game/game_1531a0.c | 7 ++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/port/include/video.h b/port/include/video.h index 81738a76e..e5c82e576 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -19,6 +19,7 @@ s32 videoGetNativeHeight(void); s32 videoGetWidth(void); s32 videoGetHeight(void); f32 videoGetAspect(void); +u32 videoGetFontTextureFilter(void); s32 videoCreateFramebuffer(u32 w, u32 h); void videoSetFramebuffer(s32 target); diff --git a/port/src/video.c b/port/src/video.c index 17674ac80..e2928f338 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -20,6 +20,7 @@ static u32 dlcount = 0; static u32 frames = 0; static u32 framesPerSec = 0; static f64 startTime, endTime, fpsTime; +static u32 fontTextureFilter = 1; s32 videoInit(void) { @@ -46,6 +47,8 @@ s32 videoInit(void) if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT; renderingAPI->set_texture_filter((enum FilteringMode)filter); + fontTextureFilter = configGetInt("Video.FontTextureFilter", 1); + initDone = true; return 0; } @@ -134,6 +137,11 @@ f32 videoGetAspect(void) return gfx_current_dimensions.aspect_ratio; } +u32 videoGetFontTextureFilter(void) +{ + return fontTextureFilter; +} + s32 videoCreateFramebuffer(u32 w, u32 h) { return gfx_create_framebuffer(w, h); diff --git a/src/game/game_1531a0.c b/src/game/game_1531a0.c index 24fd38485..743d46c6a 100644 --- a/src/game/game_1531a0.c +++ b/src/game/game_1531a0.c @@ -394,7 +394,12 @@ Gfx *text0f153628(Gfx *gdl) } #endif else { - gDPSetTextureFilter(gdl++, G_TF_BILERP); + if (videoGetFontTextureFilter() == 0) { + gDPSetTextureFilter(gdl++, G_TF_POINT); + } + else { + gDPSetTextureFilter(gdl++, G_TF_BILERP); + } } return gdl; From 9744b2266f117044f89d9619919124a3a9085cec Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 09:22:09 +0200 Subject: [PATCH 04/18] port: dummy out hi-res and screen ratio options --- src/game/mainmenu.c | 2 ++ src/game/options.c | 4 ++++ src/game/player.c | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/src/game/mainmenu.c b/src/game/mainmenu.c index cff845e97..fd09690dc 100644 --- a/src/game/mainmenu.c +++ b/src/game/mainmenu.c @@ -2525,6 +2525,7 @@ struct menuitem g_VideoOptionsMenuItems[] = { 0, menuhandlerScreenSize, }, +#ifdef PLATFORM_N64 { MENUITEMTYPE_DROPDOWN, 0, @@ -2541,6 +2542,7 @@ struct menuitem g_VideoOptionsMenuItems[] = { 0, menuhandlerHiRes, }, +#endif #if PAL { MENUITEMTYPE_DROPDOWN, diff --git a/src/game/options.c b/src/game/options.c index 9a38dbe18..d8ff82093 100644 --- a/src/game/options.c +++ b/src/game/options.c @@ -296,7 +296,11 @@ s32 optionsGetScreenRatio(void) void optionsSetScreenRatio(s32 ratio) { +#ifdef PLATFORM_N64 g_ScreenRatio = ratio; +#else + g_ScreenRatio = SCREENRATIO_NORMAL; +#endif } u8 optionsGetScreenSplit(void) diff --git a/src/game/player.c b/src/game/player.c index e68aede10..905ac95e5 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -2792,7 +2792,11 @@ void playerResetLoResIf4Mb(void) void playerSetHiResEnabled(bool enable) { +#ifdef PLATFORM_N64 g_HiResEnabled = enable; +#else + g_HiResEnabled = false; +#endif } s16 playerGetFbWidth(void) From 29dae044cc057a1e141a41ccf4c1de53bf8dbdc2 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 12:45:05 +0200 Subject: [PATCH 05/18] port: also disable hi-res and aspect options in 2p pause menu --- src/game/mainmenu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/mainmenu.c b/src/game/mainmenu.c index fd09690dc..5a0710ca9 100644 --- a/src/game/mainmenu.c +++ b/src/game/mainmenu.c @@ -2589,6 +2589,7 @@ struct menuitem g_VideoOptionsMenuItems[] = { }; struct menuitem g_2PMissionVideoOptionsMenuItems[] = { +#ifdef PLATFORM_N64 { MENUITEMTYPE_DROPDOWN, 0, @@ -2605,6 +2606,7 @@ struct menuitem g_2PMissionVideoOptionsMenuItems[] = { 0, menuhandlerHiRes, }, +#endif #if PAL { MENUITEMTYPE_DROPDOWN, From b0d97bde89426615010b253bcf0583070e47e114 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 17:55:07 +0200 Subject: [PATCH 06/18] port: possibly fixed a bunch of textures at the cost of about 22kb extra memory, how horrifying --- port/fast3d/gfx_pc.cpp | 255 +++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 135 deletions(-) diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index ae454dc5c..ff93f9163 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -145,6 +145,19 @@ struct RawTexMetadata { float h_byte_scale = 1, v_pixel_scale = 1; }; +struct LoadedTexture { + const uint8_t* addr; + uint32_t orig_size_bytes; + uint32_t full_size_bytes; // full_image_line_size_bytes * height + uint32_t size_bytes; // line_size_bytes * height + uint32_t full_image_line_size_bytes; + uint32_t line_size_bytes; + uint32_t tex_flags; + struct RawTexMetadata raw_tex_metadata; + bool masked; + bool blended; +}; + static struct RDP { uint16_t palette[256]; const uint8_t* palette_addrs[2]; @@ -156,18 +169,6 @@ static struct RDP { uint32_t tex_flags; struct RawTexMetadata raw_tex_metadata; } texture_to_load; - struct { - const uint8_t* addr; - uint32_t orig_size_bytes; - uint32_t full_size_bytes; // full_image_line_size_bytes * height - uint32_t size_bytes; // line_size_bytes * height - uint32_t full_image_line_size_bytes; - uint32_t line_size_bytes; - uint32_t tex_flags; - struct RawTexMetadata raw_tex_metadata; - bool masked; - bool blended; - } loaded_texture[8]; struct { uint8_t fmt; uint8_t siz; @@ -178,8 +179,8 @@ static struct RDP { uint16_t tmem; // 0-511, in 64-bit word units uint32_t line_size_bytes; uint8_t palette; - uint8_t tmem_index; // 0 or 1 for offset 0 kB or offset 2 kB, respectively } texture_tile[8]; + LoadedTexture loaded_texture[512]; // for each tmem location bool textures_changed[2]; uint8_t first_tile_index; @@ -579,13 +580,13 @@ static void gfx_texture_cache_delete(const uint8_t* orig_addr) { } } -static void import_texture_rgba16(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; // SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); // TODO: this trips in some places with a garbage size in full_image_line_size_bytes // probably wherever framebuffer effects are used @@ -607,16 +608,16 @@ static void import_texture_rgba16(int tile, bool importReplacement) { const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } -static void import_texture_rgba32(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); uint32_t *dest = (uint32_t *)tex_upload_buffer; @@ -628,16 +629,16 @@ static void import_texture_rgba32(int tile, bool importReplacement) { const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2; const uint32_t height = (size_bytes / 2) / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, addr, width, height); + // DumpTexture(loaded_texture.otr_path, addr, width, height); } -static void import_texture_ia4(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); uint8_t *dest = tex_upload_buffer; @@ -657,16 +658,16 @@ static void import_texture_ia4(int tile, bool importReplacement) { const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } -static void import_texture_ia8(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); uint8_t *dest = tex_upload_buffer; @@ -683,16 +684,16 @@ static void import_texture_ia8(int tile, bool importReplacement) { const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } -static void import_texture_ia16(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); uint8_t *dest = tex_upload_buffer; @@ -709,16 +710,16 @@ static void import_texture_ia16(int tile, bool importReplacement) { const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } -static void import_texture_i4(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); uint8_t *dest = tex_upload_buffer; @@ -736,16 +737,16 @@ static void import_texture_i4(int tile, bool importReplacement) { const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } -static void import_texture_i8(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); uint8_t *dest = tex_upload_buffer; @@ -761,7 +762,7 @@ static void import_texture_i8(int tile, bool importReplacement) { const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } static inline void palette_to_rgba32(const uint16_t palentry, uint8_t *rgba32_buf) { @@ -785,13 +786,13 @@ static inline void palette_to_rgba32(const uint16_t palentry, uint8_t *rgba32_bu } } -static void import_texture_ci4(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; const uint32_t pal_idx = rdp.texture_tile[tile].palette; // 0-15 const uint16_t* palette = (const uint16_t *)(rdp.palette + pal_idx * 16); // 16 pixel entries, 16 bits each SUPPORT_CHECK(full_image_line_size_bytes == line_size_bytes); @@ -813,13 +814,13 @@ static void import_texture_ci4(int tile, bool importReplacement) { gfx_rapi->upload_texture(tex_upload_buffer, width, height); } -static void import_texture_ci8(int tile, bool importReplacement) { - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* addr = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr; - const uint32_t size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes; +static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) { + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* addr = loaded_texture.addr; + const uint32_t size_bytes = loaded_texture.size_bytes; const uint32_t full_image_line_size_bytes = - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes; - const uint32_t line_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes; + loaded_texture.full_image_line_size_bytes; + const uint32_t line_size_bytes = loaded_texture.line_size_bytes; for (uint32_t i = 0, j = 0; i < size_bytes; j += full_image_line_size_bytes - line_size_bytes) { for (uint32_t k = 0; k < line_size_bytes; i++, k++, j++) { @@ -837,28 +838,28 @@ static void import_texture_ci8(int tile, bool importReplacement) { const uint32_t height = size_bytes / result_line_size; gfx_rapi->upload_texture(tex_upload_buffer, width, height); - // DumpTexture(rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].otr_path, rgba32_buf, width, height); + // DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height); } static void import_texture(int i, int tile, bool importReplacement) { + LoadedTexture& loaded_texture = rdp.loaded_texture[rdp.texture_tile[tile].tmem]; const uint8_t fmt = rdp.texture_tile[tile].fmt; const uint8_t siz = rdp.texture_tile[tile].siz; - const uint32_t texFlags = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].tex_flags; - const uint32_t tmem_index = rdp.texture_tile[tile].tmem_index; + const uint32_t tex_flags = loaded_texture.tex_flags; const uint8_t palette_index = rdp.texture_tile[tile].palette; - if (rdp.tex_lod || !rdp.loaded_texture[tmem_index].addr) { + if (rdp.tex_lod || !loaded_texture.addr) { // set up miplevel 0; also acts as a catch-all for when .addr is NULL because my texture loader sucks - rdp.loaded_texture[tmem_index].line_size_bytes = rdp.texture_tile[tile].line_size_bytes; - rdp.loaded_texture[tmem_index].full_image_line_size_bytes = rdp.texture_tile[tile].line_size_bytes; - rdp.loaded_texture[tmem_index].full_size_bytes = rdp.loaded_texture[tmem_index].full_image_line_size_bytes * rdp.texture_tile[tile].height; - rdp.loaded_texture[tmem_index].size_bytes = rdp.loaded_texture[tmem_index].line_size_bytes * rdp.texture_tile[tile].height; - rdp.loaded_texture[tmem_index].orig_size_bytes = rdp.loaded_texture[tmem_index].size_bytes; - rdp.loaded_texture[tmem_index].addr = rdp.texture_to_load.addr; + loaded_texture.line_size_bytes = rdp.texture_tile[tile].line_size_bytes; + loaded_texture.full_image_line_size_bytes = rdp.texture_tile[tile].line_size_bytes; + loaded_texture.full_size_bytes = loaded_texture.full_image_line_size_bytes * rdp.texture_tile[tile].height; + loaded_texture.size_bytes = loaded_texture.line_size_bytes * rdp.texture_tile[tile].height; + loaded_texture.orig_size_bytes = loaded_texture.size_bytes; + loaded_texture.addr = rdp.texture_to_load.addr; } - const RawTexMetadata* metadata = &rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata; - const uint8_t* orig_addr = rdp.loaded_texture[tmem_index].addr; + const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata; + const uint8_t* orig_addr = loaded_texture.addr; SUPPORT_CHECK(orig_addr); TextureCacheKey key; @@ -874,35 +875,35 @@ static void import_texture(int i, int tile, bool importReplacement) { if (fmt == G_IM_FMT_RGBA) { if (siz == G_IM_SIZ_16b) { - import_texture_rgba16(tile, importReplacement); + import_texture_rgba16(tile, loaded_texture, importReplacement); } else if (siz == G_IM_SIZ_32b) { - import_texture_rgba32(tile, importReplacement); + import_texture_rgba32(tile, loaded_texture, importReplacement); } else { sysFatalError("Bad size for RGBA texture in tile %d: %02x", tile, siz); } } else if (fmt == G_IM_FMT_IA) { if (siz == G_IM_SIZ_4b) { - import_texture_ia4(tile, importReplacement); + import_texture_ia4(tile, loaded_texture, importReplacement); } else if (siz == G_IM_SIZ_8b) { - import_texture_ia8(tile, importReplacement); + import_texture_ia8(tile, loaded_texture, importReplacement); } else if (siz == G_IM_SIZ_16b) { - import_texture_ia16(tile, importReplacement); + import_texture_ia16(tile, loaded_texture, importReplacement); } else { sysFatalError("Bad size for IA texture in tile %d: %02x", tile, siz); } } else if (fmt == G_IM_FMT_CI) { if (siz == G_IM_SIZ_4b) { - import_texture_ci4(tile, importReplacement); + import_texture_ci4(tile, loaded_texture, importReplacement); } else if (siz == G_IM_SIZ_8b) { - import_texture_ci8(tile, importReplacement); + import_texture_ci8(tile, loaded_texture, importReplacement); } else { sysFatalError("Bad size for CI texture in tile %d: %02x", tile, siz); } } else if (fmt == G_IM_FMT_I) { if (siz == G_IM_SIZ_4b) { - import_texture_i4(tile, importReplacement); + import_texture_i4(tile, loaded_texture, importReplacement); } else if (siz == G_IM_SIZ_8b) { - import_texture_i8(tile, importReplacement); + import_texture_i8(tile, loaded_texture, importReplacement); } else { sysFatalError("Bad size for I texture in tile %d: %02x", tile, siz); } @@ -1298,18 +1299,6 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo if (use_grayscale) { cc_options |= (uint64_t)SHADER_OPT_GRAYSCALE; } - if (rdp.loaded_texture[0].masked) { - cc_options |= (uint64_t)SHADER_OPT_TEXEL0_MASK; - } - if (rdp.loaded_texture[1].masked) { - cc_options |= (uint64_t)SHADER_OPT_TEXEL1_MASK; - } - if (rdp.loaded_texture[0].blended) { - cc_options |= (uint64_t)SHADER_OPT_TEXEL0_BLEND; - } - if (rdp.loaded_texture[1].blended) { - cc_options |= (uint64_t)SHADER_OPT_TEXEL1_BLEND; - } // If we are not using alpha, clear the alpha components of the combiner as they have no effect if (!use_alpha) { @@ -1338,7 +1327,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo uint8_t cms = rdp.texture_tile[tile].cms; uint8_t cmt = rdp.texture_tile[tile].cmt; - uint32_t tex_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].orig_size_bytes; + uint32_t tex_size_bytes = rdp.loaded_texture[rdp.texture_tile[tile].tmem].orig_size_bytes; uint32_t line_size = rdp.texture_tile[tile].line_size_bytes; if (line_size == 0) { @@ -1837,10 +1826,8 @@ static void gfx_dp_set_tile(uint8_t fmt, uint32_t siz, uint32_t line, uint32_t t rdp.texture_tile[tile].shifts = shifts; rdp.texture_tile[tile].shiftt = shiftt; rdp.texture_tile[tile].line_size_bytes = line * 8; - - // assume one texture is loaded at address 0 and another texture at any other address rdp.texture_tile[tile].tmem = tmem; - rdp.texture_tile[tile].tmem_index = (rdp.tex_lod && tile < 6) ? tile : 6 + (tmem > 0); + rdp.textures_changed[0] = true; rdp.textures_changed[1] = true; } @@ -1906,18 +1893,18 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t size_bytes *= rdp.texture_to_load.raw_tex_metadata.h_byte_scale; size_bytes *= rdp.texture_to_load.raw_tex_metadata.v_pixel_scale; } - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].orig_size_bytes = orig_size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes = size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_size_bytes = size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes = size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes = size_bytes; - // assert(size_bytes <= 4096 && "bug: too big texture"); - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].tex_flags = rdp.texture_to_load.tex_flags; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata = rdp.texture_to_load.raw_tex_metadata; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr = rdp.texture_to_load.addr; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].masked = false; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].blended = false; + LoadedTexture& loaded_texture = rdp.loaded_texture[rdp.texture_tile[tile].tmem]; + loaded_texture.orig_size_bytes = orig_size_bytes; + loaded_texture.size_bytes = size_bytes; + loaded_texture.full_size_bytes = size_bytes; + loaded_texture.line_size_bytes = size_bytes; + loaded_texture.full_image_line_size_bytes = size_bytes; + loaded_texture.tex_flags = rdp.texture_to_load.tex_flags; + loaded_texture.raw_tex_metadata = rdp.texture_to_load.raw_tex_metadata; + loaded_texture.addr = rdp.texture_to_load.addr; + loaded_texture.masked = false; + loaded_texture.blended = false; rdp.textures_changed[0] = rdp.textures_changed[1] = true; } @@ -1949,19 +1936,17 @@ static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t tile_line_size_bytes *= h_byte_scale; } - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].orig_size_bytes = orig_size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].size_bytes = size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_size_bytes = full_image_line_size_bytes * tile_height; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].full_image_line_size_bytes = full_image_line_size_bytes; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].line_size_bytes = tile_line_size_bytes; - - // assert(size_bytes <= 4096 && "bug: too big texture"); - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].tex_flags = rdp.texture_to_load.tex_flags; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].raw_tex_metadata = rdp.texture_to_load.raw_tex_metadata; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].addr = rdp.texture_to_load.addr + start_offset_bytes; - - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].masked = false; - rdp.loaded_texture[rdp.texture_tile[tile].tmem_index].blended = false; + LoadedTexture& loaded_texture = rdp.loaded_texture[rdp.texture_tile[tile].tmem]; + loaded_texture.orig_size_bytes = orig_size_bytes; + loaded_texture.size_bytes = size_bytes; + loaded_texture.full_size_bytes = full_image_line_size_bytes * tile_height; + loaded_texture.full_image_line_size_bytes = full_image_line_size_bytes; + loaded_texture.line_size_bytes = tile_line_size_bytes; + loaded_texture.tex_flags = rdp.texture_to_load.tex_flags; + loaded_texture.raw_tex_metadata = rdp.texture_to_load.raw_tex_metadata; + loaded_texture.addr = rdp.texture_to_load.addr + start_offset_bytes; + loaded_texture.masked = false; + loaded_texture.blended = false; rdp.texture_tile[tile].uls = uls; rdp.texture_tile[tile].ult = ult; From e5e685902cae57c1aee303592149e56345aef7b2 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 17:55:41 +0200 Subject: [PATCH 07/18] port: don't use G_RM_NOOP2 with non-noop 1cyc modes this ALMOST fixes sparks and blood splatter --- src/game/bondview.c | 4 ++-- src/game/sparks.c | 2 +- src/game/weather.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/bondview.c b/src/game/bondview.c index 2ced8b44f..6c794a2c5 100644 --- a/src/game/bondview.c +++ b/src/game/bondview.c @@ -211,7 +211,7 @@ Gfx *bviewPrepareStaticRgba16(Gfx *gdl, u32 colour, u32 alpha) gDPSetTexturePersp(gdl++, G_TP_NONE); gDPSetColorDither(gdl++, G_CD_DISABLE); gDPSetAlphaDither(gdl++, G_AD_NOISE); - gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_NOOP2); + gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_CLD_SURF2); return gdl; } @@ -245,7 +245,7 @@ Gfx *bviewPrepareStaticI8(Gfx *gdl, u32 colour, u32 alpha) gDPSetTexturePersp(gdl++, G_TP_NONE); gDPSetColorDither(gdl++, G_CD_DISABLE); gDPSetAlphaDither(gdl++, G_AD_NOISE); - gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_NOOP2); + gDPSetRenderMode(gdl++, G_RM_CLD_SURF, G_RM_CLD_SURF2); return gdl; } diff --git a/src/game/sparks.c b/src/game/sparks.c index 56c8c842b..993232b1e 100644 --- a/src/game/sparks.c +++ b/src/game/sparks.c @@ -335,7 +335,7 @@ Gfx *sparksRender(Gfx *gdl) gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetColorDither(gdl++, G_CD_DISABLE); - gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_NOOP2); + gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_AA_ZB_XLU_SURF2); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureConvert(gdl++, G_TC_FILT); diff --git a/src/game/weather.c b/src/game/weather.c index 917e4d436..800d1d090 100644 --- a/src/game/weather.c +++ b/src/game/weather.c @@ -823,7 +823,7 @@ Gfx *weatherRenderRain(Gfx *gdl, struct weatherdata *weather, s32 arg2) gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetColorDither(gdl++, G_CD_DISABLE); - gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_NOOP2); + gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_AA_ZB_XLU_SURF2); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureConvert(gdl++, G_TC_FILT); @@ -2902,7 +2902,7 @@ Gfx *weatherRenderSnow(Gfx *gdl, struct weatherdata *weather, s32 arg2) gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetColorDither(gdl++, G_CD_DISABLE); - gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_NOOP2); + gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_AA_ZB_XLU_SURF2); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureConvert(gdl++, G_TC_FILT); From 5235581e33888ebc94ab94f858098408a80c6282 Mon Sep 17 00:00:00 2001 From: Phnod Date: Fri, 1 Sep 2023 13:49:22 -0400 Subject: [PATCH 08/18] fix: remove height trim on rotated text --- src/game/game_1531a0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/game_1531a0.c b/src/game/game_1531a0.c index 24fd38485..d1bc4f4da 100644 --- a/src/game/game_1531a0.c +++ b/src/game/game_1531a0.c @@ -1790,7 +1790,7 @@ Gfx *text0f15568c(Gfx *gdl, s32 *x, s32 *y, struct fontchar *curchar, struct fon (*x + curchar->width) * 4 + var8007fadc, G_TX_RENDERTILE, var8007fae8 + 32, - ((curchar->height - 1) << 5) + var8007fae4 + 32, + ((curchar->height) << 5) + var8007fae4 + 32, 1024, 65536 - 1024 / var8007fad0); } else { From eff475c4980d14365f1250fbe55789a5fe62e63e Mon Sep 17 00:00:00 2001 From: Phnod Date: Fri, 1 Sep 2023 14:38:17 -0400 Subject: [PATCH 09/18] fix: nudge menu left side text a pixel to the left to counteract extra pixel column --- src/game/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/menu.c b/src/game/menu.c index 7f11faf3d..3a13a2f0e 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -3011,7 +3011,7 @@ Gfx *dialogRender(Gfx *gdl, struct menudialog *dialog, struct menu *menu, bool l textMeasure(&textheight, &textwidth, title, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); - x = dialogleft - 1; + x = dialogleft - 2; y = (dialogtop + dialogbottom) / 2 - textwidth - 3; if (y < dialogtop) { From 701193e71ad57d62453a553318853df7da8fdb00 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 22:42:23 +0200 Subject: [PATCH 10/18] port: add crash handler you probably won't get symbol names, but you can still use addr2line --- Makefile.port | 2 +- port/include/system.h | 3 + port/src/crash.c | 313 ++++++++++++++++++++++++++++++++++++++++-- port/src/main.c | 2 + port/src/system.c | 8 ++ 5 files changed, 312 insertions(+), 16 deletions(-) diff --git a/Makefile.port b/Makefile.port index ecf4e9bed..0ca2bd254 100644 --- a/Makefile.port +++ b/Makefile.port @@ -130,7 +130,7 @@ G_DIR := src/generated/$(ROMID) ifneq (,$(findstring windows,$(TARGET_PLATFORM))) TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) - TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -static-libstdc++ + TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -static-libstdc++ -ldbghelp # on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs TOOLCHAIN ?= i686-w64-mingw32- else # assume *nix diff --git a/port/include/system.h b/port/include/system.h index b744122a7..cc9d4277e 100644 --- a/port/include/system.h +++ b/port/include/system.h @@ -31,6 +31,9 @@ void *sysMemAlloc(const u32 size); void *sysMemZeroAlloc(const u32 size); void sysMemFree(void *ptr); +void crashInit(void); +void crashShutdown(void); + #ifdef __cplusplus } #endif diff --git a/port/src/crash.c b/port/src/crash.c index abe1c3e25..d41baa4a0 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -1,40 +1,323 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + #include #include #include +#include #include #include "system.h" +#include "platform.h" + +#define CRASH_MAX_MSG 4096 +#define CRASH_MAX_SYM 256 +#define CRASH_MAX_FRAMES 32 +#define CRASH_MSG(...) \ + if (msglen < CRASH_MAX_MSG) msglen += snprintf(msg + msglen, CRASH_MAX_MSG - msglen, __VA_ARGS__) + +#if defined(PLATFORM_WIN32) + +#include +#include +#include +#include + +// NOTE: game builds with gcc, which means we have no PDBs for the windows version +// this means that you generally won't get any symbol names in the main executable + +static LPTOP_LEVEL_EXCEPTION_FILTER prevExFilter; + +static void crashStackTrace(char *msg, PEXCEPTION_POINTERS exinfo) +{ + CONTEXT context = *exinfo->ContextRecord; + HANDLE process = GetCurrentProcess(); + HANDLE thread = GetCurrentThread(); + + SymSetOptions(SymGetOptions() | SYMOPT_DEBUG | SYMOPT_LOAD_LINES); + SymInitialize(process, NULL, TRUE); + + STACKFRAME64 stackframe; + memset(&stackframe, 0, sizeof(stackframe)); + + DWORD image; +#ifdef PLATFORM_X86 + image = IMAGE_FILE_MACHINE_I386; + stackframe.AddrPC.Offset = context.Eip; + stackframe.AddrPC.Mode = AddrModeFlat; + stackframe.AddrFrame.Offset = context.Ebp; + stackframe.AddrFrame.Mode = AddrModeFlat; + stackframe.AddrStack.Offset = context.Esp; + stackframe.AddrStack.Mode = AddrModeFlat; +#elif defined(PLATFORM_X86_64) + image = IMAGE_FILE_MACHINE_AMD64; + stackframe.AddrPC.Offset = context.Rip; + stackframe.AddrPC.Mode = AddrModeFlat; + stackframe.AddrFrame.Offset = context.Rsp; + stackframe.AddrFrame.Mode = AddrModeFlat; + stackframe.AddrStack.Offset = context.Rsp; + stackframe.AddrStack.Mode = AddrModeFlat; +#else + sysLogPrintf(LOG_ERROR, "no stack trace available on this arch"); + return; +#endif + + DWORD disp = 0; + DWORD64 disp64 = 0; + IMAGEHLP_LINE64 line; + DWORD msglen = 0; + + CRASH_MSG("EXCEPTION: 0x%08lx\n", exinfo->ExceptionRecord->ExceptionCode); + CRASH_MSG("PC: %p", exinfo->ExceptionRecord->ExceptionAddress); + if (SymGetLineFromAddr64(process, (uintptr_t)exinfo->ExceptionRecord->ExceptionAddress, &disp, &line)) { + CRASH_MSG(": %s:%lu+%lu", line.FileName, line.LineNumber, disp); + } + CRASH_MSG("\n\nBACKTRACE:\n"); + + char symbuf[sizeof(SYMBOL_INFO) + CRASH_MAX_SYM * sizeof(TCHAR)]; + PSYMBOL_INFO sym = (PSYMBOL_INFO)symbuf; + sym->SizeOfStruct = sizeof(*sym); + sym->MaxNameLen = CRASH_MAX_SYM; + + s32 i; + for (i = 0; i < CRASH_MAX_FRAMES; ++i) { + const BOOL res = StackWalk64(image, process, thread, &stackframe, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL); + if (!res) { + break; + } + + CRASH_MSG("#%02d: %p", i, (void *)(uintptr_t)stackframe.AddrPC.Offset); + + if (SymFromAddr(process, stackframe.AddrPC.Offset, &disp64, sym)) { + CRASH_MSG(": %s+%llu", sym->Name, disp64); + } + + if(SymGetLineFromAddr64(process, stackframe.AddrPC.Offset, &disp, &line)) { + CRASH_MSG(" (%s:%lu+%lu)", line.FileName, line.LineNumber, disp); + } + + CRASH_MSG("\n"); + } + + if (i <= 1) { + CRASH_MSG("no information\n"); + } else if (i == CRASH_MAX_FRAMES) { + CRASH_MSG("...\n"); + } + + SymCleanup(process); +} + +static long __stdcall crashHandler(PEXCEPTION_POINTERS exinfo) +{ + char msg[CRASH_MAX_MSG + 1] = { 0 }; + + if (IsDebuggerPresent()) { + if (prevExFilter) { + return prevExFilter(exinfo); + } + return EXCEPTION_CONTINUE_EXECUTION; + } + + sysLogPrintf(LOG_ERROR, "FATAL: Crashed: PC=%p CODE=0x%08lx", exinfo->ExceptionRecord->ExceptionAddress, exinfo->ExceptionRecord->ExceptionCode); + + fflush(stderr); + fflush(stdout); + + crashStackTrace(msg, exinfo); + + sysFatalError("Crash!\n\n%s", msg); + + return EXCEPTION_CONTINUE_EXECUTION; +} + +#elif defined(PLATFORM_LINUX) + +#include +#include +#include +#include +#include +#include + +static struct sigaction prevSigAction; + +static s32 crashIsDebuggerPresent(void) +{ + static s32 result = -1; + + if (result >= 0) { + return result; + } + + char buf[4096] = { 0 }; + + int fd = open("/proc/self/status", O_RDONLY); + if (fd < 0) { + result = 0; + return 0; + } + + int rx = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (rx <= 0) { + result = 0; + return 0; + } + + buf[rx] = 0; + + char *str = strstr(buf, "TracerPid:"); + if (!str) { + result = 0; + return 0; + } + + str += 10; + + while (*str && !isdigit(*str)) { + if (*str == '\n') { + result = 0; + return 0; + } + ++str; + } + + result = (atoi(str) != 0); + return result; +} + +static void crashStackTrace(char *msg, s32 sig, void *pc) +{ + u32 msglen = 0; + void *frames[CRASH_MAX_FRAMES] = { NULL }; + + const s32 nframes = backtrace(frames, CRASH_MAX_FRAMES); + if (nframes <= 0) { + CRASH_MSG("no information\n"); + return; + } + + char **strings = backtrace_symbols(frames, nframes); + + CRASH_MSG("SIGNAL: %d\n", sig); + CRASH_MSG("PC: "); + if (pc) { + CRASH_MSG("%p\n", pc); + } if (strings) { + CRASH_MSG("%s\n", strings[0]); + } else { + CRASH_MSG("%p\n", frames[0]); + } + + CRASH_MSG("\nBACKTRACE:\n"); + + s32 i; + for (i = 0; i < nframes; ++i) { + CRASH_MSG("#%02d: ", i); + if (strings && strings[i]) { + CRASH_MSG("%s\n", strings[i]); + } else { + CRASH_MSG("%p\n", frames[i]); + } + } + + if (i == CRASH_MAX_FRAMES) { + CRASH_MSG("...\n"); + } else if (i <= 1) { + CRASH_MSG("no information\n"); + } + + free(strings); +} + +static void crashHandler(s32 sig, siginfo_t *siginfo, void *ctx) +{ + char msg[CRASH_MAX_MSG + 1] = { 0 }; + + if (crashIsDebuggerPresent()) { + return; + } + + void *pc = NULL; + if (ctx) { + ucontext_t *ucontext = (ucontext_t *)ctx; +#ifdef PLATFORM_X86 + pc = (void *)ucontext->uc_mcontext.gregs[REG_EIP]; +#elif defined(PLATFORM_X86_64) + pc = (void *)ucontext->uc_mcontext.gregs[REG_RIP]; +#elif defined(PLATFORM_ARM) && defined(PLATFORM_64BIT) + pc = (void *)ucontext->uc_mcontext.pc; +#elif defined(PLATFORM_ARM) + pc = (void *)ucontext->uc_mcontext.arm_pc; +#endif + } + + sysLogPrintf(LOG_ERROR, "FATAL: Crashed: PC=%p SIGNAL=%d", pc, sig); + + fflush(stderr); + fflush(stdout); + + crashStackTrace(msg, sig, pc); + + sysFatalError("Crash!\n\n%s", msg); +} + +#endif -u8 g_CrashHasMessage = 0; s32 g_CrashEnabled = 0; static char crashMsg[1024]; +void crashInit(void) +{ +#ifdef PLATFORM_WIN32 + SetErrorMode(SEM_FAILCRITICALERRORS); + prevExFilter = SetUnhandledExceptionFilter(crashHandler); + g_CrashEnabled = 1; +#elif defined(PLATFORM_LINUX) + struct sigaction sigact = { 0 }; + sigact.sa_flags = SA_SIGINFO | SA_ONSTACK; + sigact.sa_sigaction = crashHandler; + sigaction(SIGSEGV, &sigact, &prevSigAction); + sigaction(SIGABRT, &sigact, &prevSigAction); + sigaction(SIGBUS, &sigact, &prevSigAction); + sigaction(SIGILL, &sigact, &prevSigAction); + g_CrashEnabled = 1; +#endif +} + +void crashShutdown(void) +{ +#ifdef PLATFORM_WIN32 + if (prevExFilter) { + SetUnhandledExceptionFilter(prevExFilter); + } +#elif defined(PLATFORM_LINUX) + sigaction(SIGSEGV, &prevSigAction, NULL); + sigaction(SIGABRT, &prevSigAction, NULL); + sigaction(SIGBUS, &prevSigAction, NULL); + sigaction(SIGILL, &prevSigAction, NULL); +#endif + g_CrashEnabled = 0; +} + void crashCreateThread(void) { - // TODO: install a crash handler of some sort + } void crashSetMessage(char *string) { - strncpy(crashMsg, string, sizeof(crashMsg) - 1); - sysLogPrintf(LOG_ERROR, "crashSetMessage: %s", crashMsg); - g_CrashHasMessage = 1; + } void crashReset(void) { - crashMsg[0] = 0; - g_CrashHasMessage = 0; + } void crashAppendChar(char c) { - g_CrashHasMessage = 1; - for (u32 i = 0; i < sizeof(crashMsg) - 1; ++i) { - if (crashMsg[i] == '\0') { - crashMsg[i] = c; - crashMsg[i + 1] = '\0'; - break; - } - } + } diff --git a/port/src/main.c b/port/src/main.c index ae6abc84f..6e7d04dd4 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -60,6 +60,7 @@ static void cleanup(void) sysLogPrintf(LOG_NOTE, "shutdown"); inputSaveConfig(); configSave(CONFIG_FNAME); + crashShutdown(); // TODO: actually shut down all subsystems } @@ -75,6 +76,7 @@ static void gameLoadConfig(void) int main(int argc, const char **argv) { + crashInit(); sysInit(argc, argv); fsInit(); configInit(); diff --git a/port/src/system.c b/port/src/system.c index df874b8a7..73cd1727c 100644 --- a/port/src/system.c +++ b/port/src/system.c @@ -112,8 +112,16 @@ void sysLogPrintf(s32 level, const char *fmt, ...) void sysFatalError(const char *fmt, ...) { + static s32 alreadyCrashed = 0; + + if (alreadyCrashed) { + abort(); + } + char errmsg[2048] = { 0 }; + alreadyCrashed = 1; + va_list ap; va_start(ap, fmt); vsnprintf(errmsg, sizeof(errmsg), fmt, ap); From 37907dccfc2ed8dd34a14a099eb78e406cb274f8 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 22:49:45 +0200 Subject: [PATCH 11/18] port: small crashhandler fix --- port/src/crash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/src/crash.c b/port/src/crash.c index d41baa4a0..fec0a9793 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -58,7 +58,7 @@ static void crashStackTrace(char *msg, PEXCEPTION_POINTERS exinfo) stackframe.AddrStack.Offset = context.Rsp; stackframe.AddrStack.Mode = AddrModeFlat; #else - sysLogPrintf(LOG_ERROR, "no stack trace available on this arch"); + snprintf(msg, CRASH_MAX_MSG, "no stack trace available on this arch\n"); return; #endif From cc079e842bac9bb2f0ff8345dd0791261e9b4476 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 22:58:45 +0200 Subject: [PATCH 12/18] port: small crashhandler fix 2 --- port/src/crash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/src/crash.c b/port/src/crash.c index fec0a9793..c87a2b05c 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -204,7 +204,7 @@ static void crashStackTrace(char *msg, s32 sig, void *pc) CRASH_MSG("PC: "); if (pc) { CRASH_MSG("%p\n", pc); - } if (strings) { + } else if (strings) { CRASH_MSG("%s\n", strings[0]); } else { CRASH_MSG("%p\n", frames[0]); From 56df5b4054f93dc5e849621a8ddc6fb463b3e84a Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 1 Sep 2023 23:08:52 +0200 Subject: [PATCH 13/18] port: ignore invert pitch setting when mouse aiming --- src/game/bondmove.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/game/bondmove.c b/src/game/bondmove.c index 62d42ee54..949dcecbd 100644 --- a/src/game/bondmove.c +++ b/src/game/bondmove.c @@ -1295,12 +1295,19 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i movedata.aimturnleftspeed = (g_Vars.currentplayer->swivelpos[0] - -0.9f) / -0.1f; movedata.aimturnrightspeed = 0.f; } + f32 vertaup = 0.f, vertadown = 0.f; if (g_Vars.currentplayer->swivelpos[1] > 0.9f) { - movedata.speedvertaup = (g_Vars.currentplayer->swivelpos[1] - 0.9f) / 0.1f; - movedata.speedvertadown = 0.f; + vertaup = (g_Vars.currentplayer->swivelpos[1] - 0.9f) / 0.1f; } else if (g_Vars.currentplayer->swivelpos[1] < -0.9f) { - movedata.speedvertadown = (g_Vars.currentplayer->swivelpos[1] - -0.9f) / -0.1f; - movedata.speedvertaup = 0.f; + vertadown = (g_Vars.currentplayer->swivelpos[1] - -0.9f) / -0.1f; + } + // Uninvert pitch if needed + if (movedata.invertpitch) { + movedata.speedvertaup = vertadown; + movedata.speedvertadown = vertaup; + } else { + movedata.speedvertaup = vertaup; + movedata.speedvertadown = vertadown; } } else { // Reset mouse aim position when not mouse aiming From 0942f61affc6fe19a3cc45a81ac29f73fc778a06 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 2 Sep 2023 16:18:06 +0200 Subject: [PATCH 14/18] port: possibly fix skyboxes by just rendering them with normal triangles --- src/game/sky.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/game/sky.c b/src/game/sky.c index 77f443941..588c7209c 100644 --- a/src/game/sky.c +++ b/src/game/sky.c @@ -15,6 +15,7 @@ #include "data.h" #include "types.h" #ifndef PLATFORM_N64 +#include "game/gfxmemory.h" #include "game/game_13c510.h" #include "game/player.h" #endif @@ -826,6 +827,7 @@ Gfx *skyRender(Gfx *gdl) gDPSetRenderMode(gdl++, G_RM_OPA_SURF, G_RM_OPA_SURF2); +#ifdef PLATFORM_N64 if (numvertices == 4) { gdl = skyRenderTri(gdl, &watervertices2d[0], &watervertices2d[1], &watervertices2d[3], 130.0f, true); @@ -846,6 +848,40 @@ Gfx *skyRender(Gfx *gdl) // 1 corner is on the ground gdl = skyRenderTri(gdl, &watervertices2d[0], &watervertices2d[1], &watervertices2d[2], 130.0f, true); } +#else + Vtx *verts = gfxAllocateVertices(5); + Col *cols = gfxAllocateColours(5); + Mtxf *mtx = gfxAllocateMatrix(); + mtx4MultMtx4(camGetWorldToScreenMtxf(), &g_SkyMtx, mtx); + mtxF2L(mtx, mtx); + + gSPMatrix(gdl++, osVirtualToPhysical(mtx), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH); + gSPColor(gdl++, osVirtualToPhysical(cols), numvertices); + gSPVertex(gdl++, osVirtualToPhysical(verts), numvertices, 0); + + for (s32 i = 0; i < numvertices; ++i) { + verts[i].x = watervertices3d[i].x; + verts[i].y = watervertices3d[i].y; + verts[i].z = watervertices3d[i].z; + verts[i].s = watervertices3d[i].s; + verts[i].t = watervertices3d[i].t; + verts[i].colour = i * 4; + cols[i].r = watervertices3d[i].r; + cols[i].g = watervertices3d[i].g; + cols[i].b = watervertices3d[i].b; + cols[i].a = watervertices3d[i].a; + } + + if (numvertices == 4) { + gSPTri2(gdl++, 0, 1, 3, 3, 2, 0); + } else if (numvertices == 5) { + gSPTri3(gdl++, 0, 1, 2, 0, 2, 3, 0, 3, 4); + } else if (numvertices == 3) { + gSPTri1(gdl++, 0, 1, 2); + } + + gSPPopMatrix(gdl++, G_MTX_MODELVIEW); +#endif } } @@ -1252,6 +1288,7 @@ Gfx *skyRender(Gfx *gdl) skyvertices2d[i].y = skyClamp(skyvertices2d[i].y, camGetScreenTop() * 4.0f, (camGetScreenTop() + camGetScreenHeight()) * 4.0f - 1.0f); } +#ifdef PLATFORM_N64 if (numvertices == 4) { if (cornerstate == CORNERSTATE_TOP) { if (sp548 < sp54c) { @@ -1292,6 +1329,41 @@ Gfx *skyRender(Gfx *gdl) // One corner is in the sky gdl = skyRenderTri(gdl, &skyvertices2d[0], &skyvertices2d[1], &skyvertices2d[2], 130.0f, true); } +#else + Vtx *verts = gfxAllocateVertices(5); + Col *cols = gfxAllocateColours(5); + Mtxf *mtx = gfxAllocateMatrix(); + mtx4MultMtx4(camGetWorldToScreenMtxf(), &g_SkyMtx, mtx); + mtxF2L(mtx, mtx); + + gSPMatrix(gdl++, osVirtualToPhysical(mtx), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH); + gSPColor(gdl++, osVirtualToPhysical(cols), numvertices); + gSPVertex(gdl++, osVirtualToPhysical(verts), numvertices, 0); + + const f32 iscale = 1.f / scale; + for (s32 i = 0; i < numvertices; ++i) { + verts[i].x = skyvertices3d[i].x; + verts[i].y = skyvertices3d[i].y; + verts[i].z = skyvertices3d[i].z; + verts[i].s = skyvertices3d[i].s; + verts[i].t = skyvertices3d[i].t; + verts[i].colour = i * 4; + cols[i].r = skyvertices3d[i].r; + cols[i].g = skyvertices3d[i].g; + cols[i].b = skyvertices3d[i].b; + cols[i].a = skyvertices3d[i].a; + } + + if (numvertices == 4) { + gSPTri2(gdl++, 0, 1, 3, 3, 2, 0); + } else if (numvertices == 5) { + gSPTri3(gdl++, 0, 1, 2, 0, 2, 3, 0, 3, 4); + } else if (numvertices == 3) { + gSPTri1(gdl++, 0, 1, 2); + } + + gSPPopMatrix(gdl++, G_MTX_MODELVIEW); +#endif } return gdl; From 702db43590c6335e446a325c31e951b38664d47a Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 2 Sep 2023 19:35:04 +0200 Subject: [PATCH 15/18] port: workarounds for some sky issues --- port/fast3d/gfx_pc.cpp | 8 +++++--- src/game/sky.c | 13 ++++++++----- src/include/gbiex.h | 1 + 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index ff93f9163..a1ebe4ec1 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -1183,9 +1183,11 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo // if (rand()%2) return; - if (v1->clip_rej & v2->clip_rej & v3->clip_rej) { - // The whole triangle lies outside the visible area - return; + if ((rsp.extra_geometry_mode & G_NO_CLIPPING_EXT) == 0) { + if (v1->clip_rej & v2->clip_rej & v3->clip_rej) { + // The whole triangle lies outside the visible area + return; + } } if ((rsp.geometry_mode & G_CULL_BOTH) != 0) { diff --git a/src/game/sky.c b/src/game/sky.c index 588c7209c..e65e9eccc 100644 --- a/src/game/sky.c +++ b/src/game/sky.c @@ -855,6 +855,7 @@ Gfx *skyRender(Gfx *gdl) mtx4MultMtx4(camGetWorldToScreenMtxf(), &g_SkyMtx, mtx); mtxF2L(mtx, mtx); + gSPSetExtraGeometryModeEXT(gdl++, G_NO_CLIPPING_EXT); gSPMatrix(gdl++, osVirtualToPhysical(mtx), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH); gSPColor(gdl++, osVirtualToPhysical(cols), numvertices); gSPVertex(gdl++, osVirtualToPhysical(verts), numvertices, 0); @@ -863,8 +864,8 @@ Gfx *skyRender(Gfx *gdl) verts[i].x = watervertices3d[i].x; verts[i].y = watervertices3d[i].y; verts[i].z = watervertices3d[i].z; - verts[i].s = watervertices3d[i].s; - verts[i].t = watervertices3d[i].t; + verts[i].s = skyClamp(watervertices3d[i].s, -32768.f, 32767.f); + verts[i].t = skyClamp(watervertices3d[i].t, -32768.f, 32767.f); verts[i].colour = i * 4; cols[i].r = watervertices3d[i].r; cols[i].g = watervertices3d[i].g; @@ -881,6 +882,7 @@ Gfx *skyRender(Gfx *gdl) } gSPPopMatrix(gdl++, G_MTX_MODELVIEW); + gSPClearExtraGeometryModeEXT(gdl++, G_NO_CLIPPING_EXT); #endif } } @@ -1336,17 +1338,17 @@ Gfx *skyRender(Gfx *gdl) mtx4MultMtx4(camGetWorldToScreenMtxf(), &g_SkyMtx, mtx); mtxF2L(mtx, mtx); + gSPSetExtraGeometryModeEXT(gdl++, G_NO_CLIPPING_EXT); gSPMatrix(gdl++, osVirtualToPhysical(mtx), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH); gSPColor(gdl++, osVirtualToPhysical(cols), numvertices); gSPVertex(gdl++, osVirtualToPhysical(verts), numvertices, 0); - const f32 iscale = 1.f / scale; for (s32 i = 0; i < numvertices; ++i) { verts[i].x = skyvertices3d[i].x; verts[i].y = skyvertices3d[i].y; verts[i].z = skyvertices3d[i].z; - verts[i].s = skyvertices3d[i].s; - verts[i].t = skyvertices3d[i].t; + verts[i].s = skyClamp(skyvertices3d[i].s, -32768.f, 32767.f); + verts[i].t = skyClamp(skyvertices3d[i].t, -32768.f, 32767.f); verts[i].colour = i * 4; cols[i].r = skyvertices3d[i].r; cols[i].g = skyvertices3d[i].g; @@ -1363,6 +1365,7 @@ Gfx *skyRender(Gfx *gdl) } gSPPopMatrix(gdl++, G_MTX_MODELVIEW); + gSPClearExtraGeometryModeEXT(gdl++, G_NO_CLIPPING_EXT); #endif } diff --git a/src/include/gbiex.h b/src/include/gbiex.h index 1bbef5a8b..574850299 100644 --- a/src/include/gbiex.h +++ b/src/include/gbiex.h @@ -201,6 +201,7 @@ #define G_ASPECT_RIGHT_EXT 0x00000020 #define G_ASPECT_CENTER_EXT (G_ASPECT_LEFT_EXT | G_ASPECT_RIGHT_EXT) #define G_ASPECT_MODE_EXT G_ASPECT_CENTER_EXT +#define G_NO_CLIPPING_EXT 0x00000040 /* Extended command macros */ From 721c27c3292a2cb25989d5e920303742cdfbabb8 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 2 Sep 2023 22:05:33 +0200 Subject: [PATCH 16/18] port: add exit option to 4mb menu --- src/game/fmb.c | 10 ++++++++++ src/include/game/mainmenu.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/game/fmb.c b/src/game/fmb.c index 2fe4c2c05..f6de5aadd 100644 --- a/src/game/fmb.c +++ b/src/game/fmb.c @@ -585,6 +585,16 @@ struct menuitem g_MainMenu4MbMenuItems[] = { 0, (void *)&g_ChangeAgentMenuDialog, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, + L_OPTIONS_110, // "Exit Game" + 0x00000007, + (void *)&g_ExitGameMenuDialog, + }, +#endif { MENUITEMTYPE_END }, }; diff --git a/src/include/game/mainmenu.h b/src/include/game/mainmenu.h index 349d7458c..c44cd7c7d 100644 --- a/src/include/game/mainmenu.h +++ b/src/include/game/mainmenu.h @@ -10,6 +10,9 @@ extern struct menudialogdef g_AcceptMissionMenuDialog; extern struct menudialogdef g_PreAndPostMissionBriefingMenuDialog; extern struct menudialogdef g_RetryMissionMenuDialog; extern struct menudialogdef g_NextMissionMenuDialog; +#ifndef PLATFORM_N64 +extern struct menudialogdef g_ExitGameMenuDialog; +#endif char *menuTextCurrentStageName(struct menuitem *item); char *soloMenuTextDifficulty(struct menuitem *item); From 0d6a62ada0358e6f525bc38b8078205f0d440b4a Mon Sep 17 00:00:00 2001 From: Catherine Reprobate Date: Sat, 2 Sep 2023 13:28:21 -0700 Subject: [PATCH 17/18] Use XBox / PC Menu A/B semantics Fixes #110 --- port/src/input.c | 2 +- src/game/menu.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/port/src/input.c b/port/src/input.c index 743042aea..021d0e61f 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -156,7 +156,7 @@ void inputSetDefaultKeyBinds(void) }; static const u32 joybinds[][2] = { - { CK_B, SDL_CONTROLLER_BUTTON_A }, + { CK_A, SDL_CONTROLLER_BUTTON_A }, { CK_X, SDL_CONTROLLER_BUTTON_X }, { CK_Y, SDL_CONTROLLER_BUTTON_Y }, { CK_DPAD_L, SDL_CONTROLLER_BUTTON_B, }, diff --git a/src/game/menu.c b/src/game/menu.c index 7f11faf3d..57e9f222b 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -4624,11 +4624,11 @@ void menuProcessInput(void) if (buttonsnow & BUTTON_RADIAL) { inputs.select = 1; } - // this will naturally feel nice w/ a switch layout - // with the default mapping for weapon-back + if (buttonsnow & BUTTON_WPNBACK) { - inputs.select = 1; + inputs.back = 1; } + #endif if (buttonsnow & B_BUTTON) { inputs.back = 1; From 07c3a513ef02cdbaa2ec08ae11ed1b4f07d4a860 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 3 Sep 2023 00:36:27 +0200 Subject: [PATCH 18/18] port: generalize the texture font filter a bit now called TextureFilter2D; although for now I couldn't find anything other than fonts to use it on --- port/include/video.h | 2 +- port/src/video.c | 8 ++++---- src/game/game_1531a0.c | 7 +------ src/game/tex.c | 3 +++ src/game/texreset.c | 3 +++ src/include/data.h | 10 ++++++++++ 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/port/include/video.h b/port/include/video.h index e5c82e576..c0f676ec4 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -19,7 +19,7 @@ s32 videoGetNativeHeight(void); s32 videoGetWidth(void); s32 videoGetHeight(void); f32 videoGetAspect(void); -u32 videoGetFontTextureFilter(void); +u32 videoGetTextureFilter2D(void); s32 videoCreateFramebuffer(u32 w, u32 h); void videoSetFramebuffer(s32 target); diff --git a/port/src/video.c b/port/src/video.c index e2928f338..ccac1972f 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -20,7 +20,7 @@ static u32 dlcount = 0; static u32 frames = 0; static u32 framesPerSec = 0; static f64 startTime, endTime, fpsTime; -static u32 fontTextureFilter = 1; +static u32 texFilter2D = 1; s32 videoInit(void) { @@ -47,7 +47,7 @@ s32 videoInit(void) if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT; renderingAPI->set_texture_filter((enum FilteringMode)filter); - fontTextureFilter = configGetInt("Video.FontTextureFilter", 1); + texFilter2D = configGetIntClamped("Video.TextureFilter2D", 1, 0, 1); initDone = true; return 0; @@ -137,9 +137,9 @@ f32 videoGetAspect(void) return gfx_current_dimensions.aspect_ratio; } -u32 videoGetFontTextureFilter(void) +u32 videoGetTextureFilter2D(void) { - return fontTextureFilter; + return texFilter2D; } s32 videoCreateFramebuffer(u32 w, u32 h) diff --git a/src/game/game_1531a0.c b/src/game/game_1531a0.c index 52434cfc3..33a443e37 100644 --- a/src/game/game_1531a0.c +++ b/src/game/game_1531a0.c @@ -394,12 +394,7 @@ Gfx *text0f153628(Gfx *gdl) } #endif else { - if (videoGetFontTextureFilter() == 0) { - gDPSetTextureFilter(gdl++, G_TF_POINT); - } - else { - gDPSetTextureFilter(gdl++, G_TF_BILERP); - } + gDPSetTextureFilter(gdl++, TEX_FILTER_2D); } return gdl; diff --git a/src/game/tex.c b/src/game/tex.c index 82f29b5ea..953b5a464 100644 --- a/src/game/tex.c +++ b/src/game/tex.c @@ -39,6 +39,9 @@ s32 g_TexLutMode; u32 var800ab5b4; struct tilestate g_TexTileStates[8]; struct tilesize g_TexTileSizes[8]; +#ifndef PLATFORM_N64 +u32 g_TexFilter2D = G_TF_BILERP; +#endif // Default u16 g_SurfaceTypeDefaultSounds[] = { SFX_HIT_STONE_8087, SFX_HIT_STONE_8088 }; diff --git a/src/game/texreset.c b/src/game/texreset.c index 30251c2ff..4bf444113 100644 --- a/src/game/texreset.c +++ b/src/game/texreset.c @@ -136,6 +136,9 @@ void texReset(void) // reset backend texture cache videoResetTextureCache(); + + // get backend texture settings + g_TexFilter2D = videoGetTextureFilter2D() ? G_TF_BILERP : G_TF_POINT; #endif g_TexWords = mempAlloc(ALIGN16(g_TexNumConfigs * 4), MEMPOOL_STAGE); diff --git a/src/include/data.h b/src/include/data.h index c70056c8c..c6c84d346 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -528,12 +528,22 @@ extern struct menudialogdef g_HtDetailsMenuDialog; extern struct menudialogdef g_HtFailedMenuDialog; extern struct menudialogdef g_HtCompletedMenuDialog; extern struct menudialogdef g_HangarListMenuDialog; + #ifndef PLATFORM_N64 + extern f32 g_PlayerCrosshairSway; extern f32 g_PlayerDefaultFovY; extern s32 g_PlayerMouseAimMode; extern f32 g_PlayerMouseAimSpeedX; extern f32 g_PlayerMouseAimSpeedY; +extern u32 g_TexFilter2D; + +#define TEX_FILTER_2D g_TexFilter2D + +#else + +#define TEX_FILTER_2D G_TF_BILERP + #endif #endif