Normal quits ran the full static-destructor chain, where destruction order is
unspecified and something logs through spdlog after its statics are destroyed,
intermittently segfaulting on exit (same class as upstream issue #689). All
user-visible state (config, saves) is already persisted by GameEngine::Destroy,
so end the process with _Exit like the extraction error paths already do.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: MegaMech <MegaMech@users.noreply.github.com>
* Make the reset button reliable from any screen
Pressing reset repeatedly near app start could do nothing, fade the music
with no reset, or bounce the press-start screen back to itself. Three
defects in the old handler:
- It ran from the ImGui widget, racing the menu state machine; a press
landing mid-fade was re-advanced by the in-flight transition (the
press-start loop).
- It always wrote gGamestateNext = MAIN_MENU_FROM_QUIT; once the game was
already in that state a repeat write is swallowed by the != guard in
main.c, so nothing happened.
- CM_ResetAudio ran unconditionally, so the music faded even when the
reset was swallowed.
The widget now only sets an atomic request flag; ApplyPendingReset (top of
push_frame, on the game loop) performs the reset. It alternates between
the two identical FROM_QUIT gamestates so every press trips the gamestate
switch, and re-enters the menus through the intro's own transition
protocol (FADE_MODE_LOGO -> setup_menus rebuild + fresh fade-in), which
replaces any in-flight transition. Audio only fades when a reset actually
executes. The dead gSkipIntro switch in the old handler (an unconditional
override below it always won) is gone; behavior is unchanged: reset lands
on the logo intro, or the start menu in debug mode.
Play-verified: hammering reset during the splash screens restarts the
logo every press; reset mid-fade after press-start no longer loops back;
resets from the main menu and mid-race work as before.
* Honor gSkipIntro when picking the post-reset screen
Review feedback on #719: restore the gSkipIntro switch from the old
handler instead of hard-coding the logo intro, keeping the debug-mode
override on top (no else), matching the boot-time logic in main().
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: MegaMech <MegaMech@users.noreply.github.com>
* some start of refactor
* Update SetFlags.cmake
* Update SetCmakeVar.cmake
* Update SetFlags.cmake
* Fix error int-convertion
* more refactor
* clean up include and source file
* fix link of lib
* fix a warning
* fix include in src/actors
* fix include in src/debug
* fix include in src/ending
* fix include in src/engine/actors
* fix include in src/engine/cameras
* fix include in src/engine/editor
* fix include in src/engine/objects
* fix include in src/engine/tracks
* fix include in src/port/ui
* fix include in src/racing
* fix include in src/engine/vehicles
* fix include in subfolder of src/engine
* fix include in src/engine
* fix include in src/enhancements
* fix include in src
* fix switch
* invert common and findlib
* Update SetFlags.cmake
* clean up some workflow
* some splification
* Update build.sh
* Update Game.h
* add header back
* Delete test_check.cmake
* continue
* Update common.cmake
* Fix widescreen letterbox/divider left-edge clipping on ARM64
The race-intro letterbox bars (draw_box_fill_wide) and the splitscreen
divider lines fed the float OTRGetDimensionFromLeftEdge result into
gDPFillWideRectangle, whose _SHIFTL packing casts float->unsigned.
Converting a negative float to unsigned is UB: x86 wraps (and the
wide-rect handler's sign extension recovers the value, so the bug is
invisible there), but ARM64 fcvtzu saturates negatives to zero — so on
Apple Silicon the fills started at the 4:3 left edge instead of the
true left edge, leaving a strip of sky visible left of the intro bars
in widescreen. Use the integer OTRGetRectDimensionFrom*Edge getters,
matching the sibling draw_box_wide helpers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Shorten the fix comment
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* macOS: sharp ImGui menu text on Retina at every menu scale
On a HiDPI display the ImGui overlay renders into a 2x framebuffer, but
the glyph atlas is rasterized at the logical point size and stretched up
by DisplayFramebufferScale, so all menu text looks fuzzy.
Set ImFontConfig::RasterizerDensity on the game fonts and the merged
FontAwesome icons: glyphs rasterize at higher resolution without
changing logical size or layout. Baked at retinaScale (2.0) times the
Menu Scale slider's maximum (2.0) so the runtime FontGlobalScale only
ever downsamples a high-res atlas instead of stretching a low-res one,
keeping text crisp at every Menu Scale setting. Standard-DPI displays
just get a supersampled atlas (identical layout, slightly sharper).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Shorten the RasterizerDensity comment
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
InitModsSystem() runs before the game world is set up. Its bail-out paths (no
O2R + user declines generation, missing mods.toml, cyclic/outdated mod deps,
and GenAssetFile's no-ROM / unsupported-ROM cases) call exit(), which runs the
global `static World sWorldInstance` destructor -> World::CleanWorld() ->
dereferences Sky::Instance and other singletons that are still null this early,
segfaulting. The most visible case: declining the first-run "Generate one now?"
prompt pops a crash report instead of quitting cleanly.
Use _Exit() on these pre-initialization bail-outs so no static destructors run.
Co-authored-by: quarrel07 <paeans-toggle-2e@icloud.com>
Co-authored-by: coco875 <59367621+coco875@users.noreply.github.com>
* Remove duplicate Switch::Init(PostInit) call.
It was called multiple times, causing multiple applet hooks (that all point to the same callback address) to be registered. For some reason, the OS started spamming us with FocusUpdate events via that hook because of that.
* Hide fullscreen and app data directory button on Switch
* merge upstream commit to fix some bug
* fix merge
* add a local user for the merge
* Update main.yml
* revert main.yml
* fix windows CI
* fix switch build
* fix windows and try a fix for switch
* fix windows build
* Force type correctness when calculating collision hashes
* Fix more incorrect hash calculations.
* fix an error
---------
Co-authored-by: coco875 <59367621+coco875@users.noreply.github.com>
* Enable MK64 build option for torch
* Fix HMAS type error (present on arm64)
* Align memory pool and fix empty macro
* Experimental: Add 4096 memory alignment
* Add alignment for ALIGNED8 macro
* Use memset over deprecated bzero
* Ensure OPENGLES flag can be used in CMakeLists.txt
* Diagnostic: align ship2_window_i8 to rule out odd-alignment crash
---------
Co-authored-by: MegaMech <MegaMech@users.noreply.github.com>
macOS uses COREAUDIO as the default audio backend, but the
combobox display map in MenuTypes.h only contained SDL and
WASAPI. This causes an unordered_map::at crash on first
frame draw when the Audio API dropdown tries to render.
Fixes the menu crash portion of #681.
* Fix NON_PORTABLE build. Ship::Context needs to be initialized before resolving files. Move offending calls inside functions where they are used. Those will always be called after GameEngine() which runs Ship::Context::CreateUninitializedInstance() early.
* Replace hardcoded string mk64.o2r and spaghetti.o2r with variables game_asset_file and engine_asset_file.
* use more unique ptr and fix a shell crash
* remove useless mods folder
* add even more unique_ptr
* Update KoopaTroopaBeach.cpp
* restore a throw
* Update Game.cpp
* automatically create mods folder
* fix oob in external by assuming that all 8 player can make sound
* better texture loading
* add destructor for gameobject
* avoid out of bound in audio sample
* Update FrameInterpolation.cpp
* Update torch
* invert condition
* adjust interpolation