EasyRPG / Player

RPG Maker 2000/2003 and EasyRPG games interpreter
https://easyrpg.org/player/
GNU General Public License v3.0
983 stars 186 forks source link

Compile time toggling of features like fonts #2345

Open Ghabry opened 4 years ago

Ghabry commented 4 years ago

The Player bundles many Fonts. I see use cases where font packs can be disabled (e.g. to reduce the memory footprint on devices where the entire ELF is copied into memory - homebrew stuff) Also useful for commercial releases: An English game only needs English glyphs.

TODO: Make a list of all the fonts

Ghabry commented 12 months ago

This semi fits here as the fonts are large: I analyzed the Player using bloaty.

tl;dr: Disabling everything and removing built in fonts and encoding support will bring us down from 12 MB to around ~5-6 MB. Everything includes audio making the barely pretty useless. Removing encoding support will break Chinese/Japanese/Korean games. Afterwards there is no simple way to get even smaller. We just have too much functionality in it.

A saving of 1 MB means that the game can load ~3.4 pictures of size 320x240 more. So this can help a bit in low memory conditions.

Note that bloaty requires debug symbols for certain features which increase the size of the binary. Debug symbols are not part of the final binary but part of the calculation.

symbols is for specific functions. compileunits lists the size per file (though this can be inaccurate). This is just a different way to represent the information. I output 10 entries per section (different locations in the executable where stuff is stored).

I couldn't get .eh_frame (exception handling) disabled. Was even generated with -fno-exceptions. This is usually disabled to save space (around 0.5 MB).


Player build that has all features enabled and compiled static against the libraries ``` cmake --preset linux-relwithdebinfo -DPLAYER_BUILD_LIBLCF=ON -DCMAKE_CXX_FLAGS="-Os -g" ``` ``` bloaty -n 10 -d sections,symbols easyrpg-player-all --debug-file=easyrpg-player-all.debug FILE SIZE VM SIZE -------------- -------------- 52.4% 5.94Mi 49.2% 5.94Mi .text 94.6% 5.62Mi 94.6% 5.62Mi [17585 Others] 0.8% 48.3Ki 0.8% 48.3Ki lcf::TypedField<>::WriteXml() 0.6% 39.5Ki 0.6% 39.5Ki __static_initialization_and_destruction_0() 0.6% 39.4Ki 0.6% 39.4Ki lcf::Struct<>::ReadLcf() 0.6% 38.4Ki 0.6% 38.4Ki std::vector<>::_M_default_append() 0.5% 31.6Ki 0.5% 31.6Ki FmMidiDecoder::load_programs() 0.5% 31.0Ki 0.5% 31.0Ki lcf::Struct<>::WriteLcf() 0.4% 27.1Ki 0.4% 27.1Ki std::_Rb_tree<>::_M_get_insert_hint_unique_pos() 0.4% 25.2Ki 0.4% 25.2Ki std::vector<>::_M_realloc_insert<>() 0.4% 24.1Ki 0.4% 24.1Ki lcf::rpg::ForEachString<>() 0.4% 23.2Ki 0.4% 23.2Ki lcf::Struct<>::LcfSize() 26.2% 2.98Mi 24.7% 2.98Mi .rodata 23.3% 710Ki 23.3% 710Ki [1741 Others] 20.6% 628Ki 20.6% 628Ki icudt69_dat 18.8% 572Ki 18.8% 572Ki BITMAPFONT_WQY 16.2% 494Ki 16.2% 494Ki [section .rodata] 9.9% 302Ki 9.9% 302Ki SHINONOME_GOTHIC 2.8% 84.1Ki 2.8% 84.1Ki BITMAPFONT_TTYP0 2.1% 64.0Ki 2.1% 64.0Ki hard_light 2.0% 61.0Ki 2.0% 61.0Ki propsVectorsTrie_index 1.8% 54.7Ki 1.8% 54.7Ki ft_adobe_glyph_list 1.4% 43.5Ki 1.4% 43.5Ki propsTrie_index 1.1% 32.1Ki 1.1% 32.1Ki ispow 9.0% 1.02Mi 8.5% 1.02Mi .eh_frame 91.8% 962Ki 91.8% 962Ki [17585 Others] 1.5% 15.6Ki 1.5% 15.6Ki lcf::TypedField<>::WriteXml() 0.9% 9.25Ki 0.9% 9.25Ki lcf::TypedField<>::ReadLcf() 0.9% 9.13Ki 0.9% 9.13Ki lcf::Struct<>::ReadLcf() 0.8% 8.70Ki 0.8% 8.70Ki lcf::Struct<>::LcfSize() 0.8% 8.48Ki 0.8% 8.48Ki std::_Rb_tree<>::_M_get_insert_hint_unique_pos() 0.8% 8.20Ki 0.8% 8.20Ki lcf::Struct<>::WriteLcf() 0.7% 7.09Ki 0.7% 7.09Ki lcf::Struct<>::WriteXml() 0.7% 6.85Ki 0.7% 6.85Ki lcf::TypedField<>::LcfSize() 0.6% 6.43Ki 0.6% 6.43Ki std::_Rb_tree<>::_M_get_insert_unique_pos() 0.6% 6.36Ki 0.6% 6.36Ki lcf::TypedField<>::IsDefault() 0.0% 0 6.0% 744Ki .bss NAN% 0 50.3% 375Ki rand_table NAN% 0 18.3% 136Ki midisynth::(anonymous namespace)::envelope_table NAN% 0 8.6% 64.0Ki midisynth::(anonymous namespace)::vibrato_table NAN% 0 6.1% 45.1Ki [862 Others] NAN% 0 4.4% 33.0Ki palette NAN% 0 4.2% 31.3Ki Window_Keyboard::layouts NAN% 0 3.5% 26.3Ki newt_coeffs NAN% 0 1.3% 9.65Ki old_sigaction NAN% 0 1.1% 8.00Ki midisynth::(anonymous namespace)::log_table NAN% 0 1.1% 8.00Ki midisynth::(anonymous namespace)::sine_table NAN% 0 1.1% 8.00Ki sf_parselog 6.1% 710Ki 5.8% 710Ki .rela.dyn 49.0% 348Ki 49.0% 348Ki [1105 Others] 16.5% 117Ki 16.5% 117Ki RTP::rtp_table_2k3 9.7% 68.9Ki 9.7% 68.9Ki RTP::rtp_table_2k 8.6% 61.2Ki 8.6% 61.2Ki lcf::TypedField<> 4.0% 28.5Ki 4.0% 28.5Ki lcf::Struct<>::fields 2.8% 19.6Ki 2.8% 19.6Ki jump_table 2.0% 14.1Ki 2.0% 14.1Ki LANGUAGES 2.0% 14.1Ki 2.0% 14.1Ki LANGUAGES_3 1.8% 12.9Ki 1.8% 12.9Ki lcf::StructFieldXmlHandler<> 1.8% 12.9Ki 1.8% 12.9Ki lcf::StructVectorXmlHandler<> 1.8% 12.9Ki 1.8% 12.9Ki lcf::StructXmlHandler<> 2.7% 313Ki 2.5% 313Ki .data.rel.ro 53.2% 166Ki 53.2% 166Ki [1029 Others] 13.5% 42.3Ki 13.5% 42.3Ki RTP::rtp_table_2k3 12.6% 39.3Ki 12.6% 39.3Ki RTP::rtp_table_2k 7.1% 22.2Ki 7.1% 22.2Ki lcf::TypedField<> 2.6% 8.08Ki 2.6% 8.08Ki arrControllers 2.4% 7.62Ki 2.4% 7.62Ki sse2_fast_paths 2.0% 6.14Ki 2.0% 6.14Ki mmx_fast_paths 1.9% 6.06Ki 1.9% 6.06Ki c_fast_paths 1.7% 5.36Ki 1.7% 5.36Ki accessors 1.5% 4.77Ki 1.5% 4.77Ki lcf::StructFieldXmlHandler<> 1.5% 4.77Ki 1.5% 4.77Ki lcf::StructVectorXmlHandler<> 1.7% 195Ki 1.6% 195Ki .eh_frame_hdr 91.7% 179Ki 91.7% 179Ki [17585 Others] 1.0% 1.86Ki 1.0% 1.86Ki lcf::TypedField<>::BeginXml() 1.0% 1.86Ki 1.0% 1.86Ki lcf::TypedField<>::ParseXml() 1.0% 1.86Ki 1.0% 1.86Ki lcf::TypedField<>::ReadLcf() 1.0% 1.86Ki 1.0% 1.86Ki lcf::TypedField<>::WriteLcf() 1.0% 1.86Ki 1.0% 1.86Ki lcf::TypedField<>::WriteXml() 0.9% 1.85Ki 0.9% 1.85Ki lcf::TypedField<>::IsDefault() 0.9% 1.85Ki 0.9% 1.85Ki lcf::TypedField<>::LcfSize() 0.6% 1.09Ki 0.6% 1.09Ki std::_Rb_tree<>::_M_erase() 0.5% 1.02Ki 0.5% 1.02Ki std::_Rb_tree<>::_M_get_insert_hint_unique_pos() 0.5% 1.02Ki 0.5% 1.02Ki std::_Rb_tree<>::_M_get_insert_unique_pos() 0.7% 86.8Ki 0.7% 86.8Ki .data 55.0% 47.7Ki 55.0% 47.7Ki [1043 Others] 11.9% 10.3Ki 11.9% 10.3Ki lcf::Struct<>::fields 7.5% 6.52Ki 7.5% 6.52Ki jump_table 5.4% 4.69Ki 5.4% 4.69Ki _WM_freq_table 4.6% 4.00Ki 4.6% 4.00Ki SDL_scancode_names 4.6% 4.00Ki 4.6% 4.00Ki icon32 3.4% 2.98Ki 3.4% 2.98Ki SDL_GeneratedBlitFuncTable 2.4% 2.07Ki 2.4% 2.07Ki [section .data] 2.3% 2.00Ki 2.3% 2.00Ki default_key_maps 2.0% 1.72Ki 2.0% 1.72Ki system_h 0.9% 772 0.9% 772 default_accents 0.7% 75.8Ki 0.6% 75.8Ki .gcc_except_table 0.4% 42.3Ki 0.3% 35.4Ki [27 Others] 0.1% 11.3Ki 0.1% 11.3Ki .dynstr 97.3% 11.0Ki 97.3% 11.0Ki [section .dynstr] 1.3% 156 1.3% 156 std::operator+<>() 0.4% 42 0.4% 42 std::bad_weak_ptr@GLIBCXX_3.4.15 0.3% 32 0.3% 32 std::char_traits<>::eq() 0.2% 23 0.2% 23 __libc_single_threaded@GLIBC_2.32 0.1% 14 0.1% 14 [2 Others] 0.1% 13 0.1% 13 std::nothrow@GLIBCXX_3.4 0.1% 10 0.1% 10 std::cerr@GLIBCXX_3.4 0.1% 10 0.1% 10 std::clog@GLIBCXX_3.4 0.1% 10 0.1% 10 std::cout@GLIBCXX_3.4 0.1% 9 0.1% 9 std::cin@GLIBCXX_3.4 100.0% 11.3Mi 100.0% 12.1Mi TOTAL ``` ``` bloaty -n 10 -d sections,compileunits easyrpg-player-all --debug-file=easyrpg-player-all.debug FILE SIZE VM SIZE -------------- -------------- 52.4% 5.94Mi 49.2% 5.94Mi .text 74.5% 4.43Mi 74.5% 4.43Mi [881 Others] 13.3% 811Ki 13.3% 811Ki easyrpg-buildscripts/linux-static/freetype-2.13.0/src/lzw/ftlzw.c 2.0% 120Ki 2.0% 120Ki pixman-mmx.c 1.7% 102Ki 1.7% 102Ki player/lib/liblcf/src/generated/ldb_database.cpp 1.7% 101Ki 1.7% 101Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_yuv.c 1.4% 82.7Ki 1.4% 82.7Ki pixman-ppc.c 1.3% 78.3Ki 1.3% 78.3Ki inffast.c 1.2% 71.9Ki 1.2% 71.9Ki easyrpg-buildscripts/linux-static/freetype-2.13.0/src/svg/svg.c 1.0% 63.2Ki 1.0% 63.2Ki pixman-combine32.c 1.0% 59.6Ki 1.0% 59.6Ki player/lib/liblcf/src/generated/lsd_save.cpp 1.0% 59.3Ki 1.0% 59.3Ki easyrpg-buildscripts/linux-static/freetype-2.13.0/src/sdf/sdf.c 26.2% 2.98Mi 24.7% 2.98Mi .rodata 64.7% 1.93Mi 64.7% 1.93Mi [section .rodata] 32.3% 985Ki 32.3% 985Ki player/src/font.cpp 2.1% 64.3Ki 2.1% 64.3Ki player/src/bitmap.cpp 0.7% 20.5Ki 0.7% 20.5Ki player/src/scene_logo.cpp 0.1% 2.00Ki 0.1% 2.00Ki player/src/game_battle.cpp 0.1% 1.61Ki 0.1% 1.61Ki player/src/decoder_drwav.cpp 0.0% 799 0.0% 799 player/src/cache.cpp 0.0% 604 0.0% 604 player/src/tilemap_layer.cpp 0.0% 456 0.0% 456 [12 Others] 0.0% 132 0.0% 132 player/src/platform/sdl/sdl2_ui.cpp 0.0% 124 0.0% 124 player/src/rtp_table.cpp 9.0% 1.02Mi 8.5% 1.02Mi .eh_frame 76.3% 800Ki 76.3% 800Ki [880 Others] 9.5% 99.6Ki 9.5% 99.6Ki easyrpg-buildscripts/linux-static/freetype-2.13.0/src/lzw/ftlzw.c 4.4% 45.8Ki 4.4% 45.8Ki 6vectorIN3lcf3rpg4ItemESaIS2_EE7reserveEm 2.9% 30.1Ki 2.9% 30.1Ki player/lib/liblcf/src/generated/ldb_database.cpp 1.9% 19.8Ki 1.9% 19.8Ki player/lib/liblcf/src/generated/lsd_save.cpp 0.9% 9.95Ki 0.9% 9.95Ki pixman-gradient-walker.c 0.9% 9.88Ki 0.9% 9.88Ki player/src/game_interpreter.cpp 0.8% 8.91Ki 0.8% 8.91Ki easyrpg-buildscripts/linux-static/fluidsynth-2.3.2/src/synth/fluid_mod.c 0.8% 8.76Ki 0.8% 8.76Ki inffast.c 0.8% 7.90Ki 0.8% 7.90Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_blit_N.c 0.7% 7.74Ki 0.7% 7.74Ki pixman-ppc.c 0.0% 0 6.0% 744Ki .bss NAN% 0 59.1% 439Ki [section .bss] NAN% 0 29.1% 216Ki player/src/midisynth.cpp NAN% 0 4.5% 33.2Ki player/src/bitmap.cpp NAN% 0 4.2% 31.3Ki player/src/window_keyboard.cpp NAN% 0 1.1% 8.27Ki [64 Others] NAN% 0 0.7% 4.90Ki player/src/rand.cpp NAN% 0 0.4% 3.04Ki player/src/lcf_data.cpp NAN% 0 0.3% 2.50Ki player/lib/liblcf/src/generated/ldb_database.cpp NAN% 0 0.3% 2.37Ki player/src/player.cpp NAN% 0 0.3% 1.88Ki player/lib/liblcf/src/generated/lsd_save.cpp NAN% 0 0.1% 913 player/src/audio_generic.cpp 6.1% 710Ki 5.8% 710Ki .rela.dyn 66.2% 470Ki 66.2% 470Ki [section .rela.dyn] 25.8% 183Ki 25.8% 183Ki player/src/rtp_table.cpp 4.2% 30.0Ki 4.2% 30.0Ki [79 Others] 0.9% 6.33Ki 0.9% 6.33Ki player/src/window_settings.cpp 0.7% 5.30Ki 0.7% 5.30Ki player/src/game_config.cpp 0.6% 4.27Ki 0.6% 4.27Ki player/src/window_input_settings.cpp 0.5% 3.47Ki 0.5% 3.47Ki player/lib/liblcf/src/generated/ldb_terms.cpp 0.3% 2.25Ki 0.3% 2.25Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_blit_copy.c 0.3% 1.83Ki 0.3% 1.83Ki player/lib/liblcf/src/generated/ldb_system.cpp 0.2% 1.48Ki 0.2% 1.48Ki player/lib/liblcf/src/generated/lsd_savesystem.cpp 0.2% 1.43Ki 0.2% 1.43Ki player/src/game_ineluki.cpp 2.7% 313Ki 2.5% 313Ki .data.rel.ro 71.1% 222Ki 71.1% 222Ki [section .data.rel.ro] 26.2% 81.9Ki 26.2% 81.9Ki player/src/rtp_table.cpp 0.7% 2.12Ki 0.7% 2.12Ki player/src/window_settings.cpp 0.6% 1.81Ki 0.6% 1.81Ki player/src/game_config.cpp 0.5% 1.42Ki 0.5% 1.42Ki player/src/window_input_settings.cpp 0.3% 976 0.3% 976 player/src/game_ineluki.cpp 0.3% 864 0.3% 864 [69 Others] 0.1% 400 0.1% 400 player/src/filefinder.cpp 0.1% 344 0.1% 344 player/src/input_source.cpp 0.1% 344 0.1% 344 player/src/scene_settings.cpp 0.1% 328 0.1% 328 player/lib/liblcf/src/reader_flags.cpp 1.7% 195Ki 1.6% 195Ki .eh_frame_hdr 76.4% 149Ki 76.4% 149Ki [880 Others] 7.8% 15.3Ki 7.8% 15.3Ki easyrpg-buildscripts/linux-static/freetype-2.13.0/src/lzw/ftlzw.c 6.7% 13.1Ki 6.7% 13.1Ki 6vectorIN3lcf3rpg4ItemESaIS2_EE7reserveEm 2.6% 5.09Ki 2.6% 5.09Ki player/lib/liblcf/src/generated/ldb_database.cpp 1.8% 3.57Ki 1.8% 3.57Ki player/lib/liblcf/src/generated/lsd_save.cpp 0.9% 1.80Ki 0.9% 1.80Ki pixman-gradient-walker.c 0.8% 1.64Ki 0.8% 1.64Ki player/src/game_interpreter.cpp 0.7% 1.42Ki 0.7% 1.42Ki player/src/game_actor.cpp 0.7% 1.42Ki 0.7% 1.42Ki player/src/game_map.cpp 0.7% 1.40Ki 0.7% 1.40Ki easyrpg-buildscripts/linux-static/fluidsynth-2.3.2/src/synth/fluid_mod.c 0.7% 1.30Ki 0.7% 1.30Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_surface.c 0.7% 86.8Ki 0.7% 86.8Ki .data 37.8% 32.8Ki 37.8% 32.8Ki [section .data] 33.4% 29.0Ki 33.4% 29.0Ki [65 Others] 6.6% 5.75Ki 6.6% 5.75Ki player/lib/liblcf/src/generated/ldb_terms.cpp 4.6% 4.00Ki 4.6% 4.00Ki player/src/platform/sdl/sdl2_ui.cpp 3.4% 2.97Ki 3.4% 2.97Ki player/lib/liblcf/src/generated/ldb_system.cpp 2.7% 2.38Ki 2.7% 2.38Ki player/lib/liblcf/src/generated/lsd_savesystem.cpp 2.6% 2.28Ki 2.6% 2.28Ki player/lib/liblcf/src/generated/ldb_item.cpp 2.5% 2.16Ki 2.5% 2.16Ki player/lib/liblcf/src/generated/lsd_savepartylocation.cpp 2.2% 1.94Ki 2.2% 1.94Ki player/lib/liblcf/src/generated/ldb_skill.cpp 2.1% 1.81Ki 2.1% 1.81Ki player/lib/liblcf/src/generated/ldb_actor.cpp 2.0% 1.73Ki 2.0% 1.73Ki player/lib/liblcf/src/generated/ldb_state.cpp 0.7% 75.8Ki 0.6% 75.8Ki .gcc_except_table 0.4% 42.3Ki 0.3% 35.4Ki [27 Others] 0.1% 11.3Ki 0.1% 11.3Ki .dynstr 98.4% 11.2Ki 98.4% 11.2Ki [section .dynstr] 0.7% 79 0.7% 79 player/src/filefinder_rtp.cpp 0.7% 77 0.7% 77 player/src/graphics.cpp 0.3% 32 0.3% 32 player/src/filefinder.cpp 100.0% 11.3Mi 100.0% 12.1Mi TOTAL ```

tl;dr 12.1 MB


Disable all audio and freetype font rendering ``` cmake --preset linux-relwithdebinfo -DPLAYER_BUILD_LIBLCF=ON -DCMAKE_CXX_FLAGS="-Os -g" -DPLAYER_AUDIO_BACKEND=OFF -DPLAYER_WITH_FREETYPE=OFF ``` ``` bloaty -n 10 -d sections,symbols easyrpg-player --debug-file=easyrpg-player.debug FILE SIZE VM SIZE -------------- -------------- 49.1% 3.53Mi 48.4% 3.53Mi .text 92.5% 3.27Mi 92.5% 3.27Mi [11844 Others] 1.1% 39.5Ki 1.1% 39.5Ki lcf::Struct<>::ReadLcf() 1.1% 39.2Ki 1.1% 39.2Ki lcf::TypedField<>::WriteXml() 1.0% 37.8Ki 1.0% 37.8Ki std::vector<>::_M_default_append() 0.8% 28.5Ki 0.8% 28.5Ki lcf::Struct<>::WriteLcf() 0.7% 26.7Ki 0.7% 26.7Ki std::_Rb_tree<>::_M_get_insert_hint_unique_pos() 0.7% 24.1Ki 0.7% 24.1Ki lcf::rpg::ForEachString<>() 0.6% 21.6Ki 0.6% 21.6Ki lcf::Struct<>::LcfSize() 0.5% 19.7Ki 0.5% 19.7Ki std::vector<>::_M_realloc_insert<>() 0.5% 18.1Ki 0.5% 18.1Ki _GLOBAL__sub_I__ZN15Window_Keyboard4DONEE 0.4% 15.2Ki 0.4% 15.2Ki lcf::Struct<>::MakeFieldMap() 32.8% 2.36Mi 32.3% 2.36Mi .rodata 26.0% 628Ki 26.0% 628Ki icudt69_dat 23.7% 572Ki 23.7% 572Ki BITMAPFONT_WQY 14.8% 358Ki 14.8% 358Ki [section .rodata] 12.5% 302Ki 12.5% 302Ki SHINONOME_GOTHIC 10.3% 249Ki 10.3% 249Ki [632 Others] 3.5% 84.1Ki 3.5% 84.1Ki BITMAPFONT_TTYP0 2.6% 64.0Ki 2.6% 64.0Ki hard_light 2.5% 61.0Ki 2.5% 61.0Ki propsVectorsTrie_index 1.8% 43.5Ki 1.8% 43.5Ki propsTrie_index 1.1% 27.3Ki 1.1% 27.3Ki propsVectors 1.0% 24.1Ki 1.0% 24.1Ki ucase_props_trieIndex 7.5% 554Ki 7.4% 554Ki .rela.dyn 39.5% 219Ki 39.5% 219Ki [690 Others] 21.1% 117Ki 21.1% 117Ki RTP::rtp_table_2k3 12.4% 68.9Ki 12.4% 68.9Ki RTP::rtp_table_2k 7.0% 38.9Ki 7.0% 38.9Ki lcf::TypedField<> 5.1% 28.5Ki 5.1% 28.5Ki lcf::Struct<>::fields 3.5% 19.6Ki 3.5% 19.6Ki jump_table 2.5% 14.1Ki 2.5% 14.1Ki LANGUAGES 2.5% 14.1Ki 2.5% 14.1Ki LANGUAGES_3 2.3% 12.8Ki 2.3% 12.8Ki accessors 2.3% 12.8Ki 2.3% 12.8Ki Input::Keys::kNames 1.5% 8.23Ki 1.5% 8.23Ki s_ControllerMappings 4.5% 331Ki 4.4% 331Ki .eh_frame 97.9% 324Ki 97.9% 324Ki [7826 Others] 0.4% 1.23Ki 0.4% 1.23Ki fmt::v9::detail::write_padded<>() 0.3% 904 0.3% 904 SDL_ConvertPixels_YUV_to_RGB 0.3% 880 0.3% 880 icu_69::(anonymous namespace)::canonicalizeLocale() 0.3% 876 0.3% 876 fmt::v9::detail::write<>() 0.2% 776 0.2% 776 icu_69::UnicodeString::UnicodeString() 0.2% 772 0.2% 772 icu_69::MemoryPool<>::create<>() 0.1% 496 0.1% 496 fmt::v9::detail::write_significand<>() 0.1% 456 0.1% 456 ulocimp_minimizeSubtags_69 0.1% 408 0.1% 408 createLikelySubtagsString() 0.1% 376 0.1% 376 doOpenChoice() 3.4% 247Ki 3.3% 247Ki .data.rel.ro 43.1% 106Ki 43.1% 106Ki [633 Others] 17.1% 42.3Ki 17.1% 42.3Ki RTP::rtp_table_2k3 15.9% 39.3Ki 15.9% 39.3Ki RTP::rtp_table_2k 6.7% 16.7Ki 6.7% 16.7Ki lcf::TypedField<> 3.3% 8.08Ki 3.3% 8.08Ki arrControllers 3.1% 7.62Ki 3.1% 7.62Ki sse2_fast_paths 2.5% 6.14Ki 2.5% 6.14Ki mmx_fast_paths 2.4% 6.06Ki 2.4% 6.06Ki c_fast_paths 2.2% 5.36Ki 2.2% 5.36Ki accessors 1.9% 4.72Ki 1.9% 4.72Ki LANGUAGES 1.9% 4.72Ki 1.9% 4.72Ki LANGUAGES_3 0.0% 0 1.6% 116Ki .bss NAN% 0 28.4% 33.0Ki palette NAN% 0 26.9% 31.3Ki Window_Keyboard::layouts NAN% 0 14.9% 17.3Ki [789 Others] NAN% 0 8.3% 9.65Ki old_sigaction NAN% 0 4.2% 4.89Ki (anonymous namespace)::rng NAN% 0 3.7% 4.29Ki lcf::Struct<>::tag_map NAN% 0 3.5% 4.04Ki lcf::Struct<>::field_map NAN% 0 3.4% 4.00Ki gTimeZoneBuffer NAN% 0 2.6% 3.02Ki SDL_keyboard NAN% 0 2.5% 2.91Ki lcf::Data::data NAN% 0 1.7% 2.00Ki SDL_disabled_events 1.1% 78.7Ki 1.1% 78.7Ki .data 55.4% 43.6Ki 55.4% 43.6Ki [992 Others] 13.1% 10.3Ki 13.1% 10.3Ki lcf::Struct<>::fields 8.3% 6.52Ki 8.3% 6.52Ki jump_table 5.1% 4.00Ki 5.1% 4.00Ki SDL_scancode_names 5.1% 4.00Ki 5.1% 4.00Ki icon32 3.8% 2.98Ki 3.8% 2.98Ki SDL_GeneratedBlitFuncTable 2.6% 2.04Ki 2.6% 2.04Ki [section .data] 2.5% 2.00Ki 2.5% 2.00Ki default_key_maps 2.2% 1.71Ki 2.2% 1.71Ki system_h 1.0% 772 1.0% 772 default_accents 1.0% 768 1.0% 768 lcf::static_name 0.9% 64.5Ki 0.9% 64.5Ki .eh_frame_hdr 98.9% 63.8Ki 98.9% 63.8Ki [7826 Others] 0.2% 136 0.2% 136 icu_69::UnicodeString::UnicodeString() 0.2% 120 0.2% 120 fmt::v9::detail::write<>() 0.2% 112 0.2% 112 fmt::v9::detail::write_padded<>() 0.1% 88 0.1% 88 icu_69::MemoryPool<>::create<>() 0.1% 64 0.1% 64 fmt::v9::detail::do_parse_arg_id<>() 0.1% 64 0.1% 64 icu_69::MaybeStackArray<>::~MaybeStackArray() 0.1% 48 0.1% 48 fmt::v9::detail::write_significand<>() 0.1% 40 0.1% 40 icu_69::Locale::Locale() 0.1% 40 0.1% 40 icu_69::MemoryPool<>::~MemoryPool() 0.1% 40 0.1% 40 icu_69::UnicodeSet::UnicodeSet() 0.5% 37.8Ki 0.4% 31.2Ki [27 Others] 0.1% 10.7Ki 0.1% 10.7Ki .dynstr 97.5% 10.4Ki 97.5% 10.4Ki [section .dynstr] 1.4% 156 1.4% 156 std::operator+<>() 0.3% 32 0.3% 32 std::char_traits<>::eq() 0.2% 23 0.2% 23 __libc_single_threaded@GLIBC_2.32 0.1% 13 0.1% 13 std::nothrow@GLIBCXX_3.4 0.1% 10 0.1% 10 std::cerr@GLIBCXX_3.4 0.1% 10 0.1% 10 std::clog@GLIBCXX_3.4 0.1% 10 0.1% 10 std::cout@GLIBCXX_3.4 0.1% 9 0.1% 9 std::cin@GLIBCXX_3.4 0.1% 7 0.1% 7 [1 Others] 0.1% 7 0.1% 7 stderr@GLIBC_2.2.5 0.1% 10.3Ki 0.1% 10.3Ki .dynsym 97.5% 10.0Ki 97.5% 10.0Ki [section .dynsym] 0.5% 48 0.5% 48 std::operator+<>() 0.2% 24 0.2% 24 [1 Others] 0.2% 24 0.2% 24 __libc_single_threaded@GLIBC_2.32 0.2% 24 0.2% 24 std::cerr@GLIBCXX_3.4 0.2% 24 0.2% 24 std::char_traits<>::eq() 0.2% 24 0.2% 24 std::cin@GLIBCXX_3.4 0.2% 24 0.2% 24 std::clog@GLIBCXX_3.4 0.2% 24 0.2% 24 std::cout@GLIBCXX_3.4 0.2% 24 0.2% 24 std::nothrow@GLIBCXX_3.4 0.2% 24 0.2% 24 stderr@GLIBC_2.2.5 100.0% 7.20Mi 100.0% 7.30Mi TOTAL ``` ``` bloaty -n 10 -d sections,compileunits easyrpg-player --debug-file=easyrpg-player.debug FILE SIZE VM SIZE -------------- -------------- 49.1% 3.53Mi 48.4% 3.53Mi .text 78.8% 2.78Mi 78.8% 2.78Mi [582 Others] 3.3% 120Ki 3.3% 120Ki pixman-mmx.c 2.8% 101Ki 2.8% 101Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_yuv.c 2.7% 98.0Ki 2.7% 98.0Ki player/lib/liblcf/src/generated/ldb_database.cpp 2.3% 82.7Ki 2.3% 82.7Ki pixman-ppc.c 2.2% 78.3Ki 2.2% 78.3Ki inffast.c 1.7% 63.2Ki 1.7% 63.2Ki pixman-combine32.c 1.6% 58.3Ki 1.6% 58.3Ki player/lib/liblcf/src/generated/lsd_save.cpp 1.6% 58.3Ki 1.6% 58.3Ki utrie2.cpp 1.6% 57.9Ki 1.6% 57.9Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_blit_N.c 1.4% 49.0Ki 1.4% 49.0Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/render/software/SDL_blendfillrect.c 32.8% 2.36Mi 32.3% 2.36Mi .rodata 55.5% 1.31Mi 55.5% 1.31Mi [section .rodata] 40.8% 985Ki 40.8% 985Ki player/src/font.cpp 2.7% 64.3Ki 2.7% 64.3Ki player/src/bitmap.cpp 0.8% 20.5Ki 0.8% 20.5Ki player/src/scene_logo.cpp 0.1% 2.00Ki 0.1% 2.00Ki player/src/game_battle.cpp 0.0% 799 0.0% 799 player/src/cache.cpp 0.0% 604 0.0% 604 player/src/tilemap_layer.cpp 0.0% 270 0.0% 270 [9 Others] 0.0% 132 0.0% 132 player/src/platform/sdl/sdl2_ui.cpp 0.0% 124 0.0% 124 player/src/rtp_table.cpp 0.0% 124 0.0% 124 player/src/weather.cpp 7.5% 554Ki 7.4% 554Ki .rela.dyn 56.8% 314Ki 56.8% 314Ki [section .rela.dyn] 33.1% 183Ki 33.1% 183Ki player/src/rtp_table.cpp 5.4% 29.7Ki 5.4% 29.7Ki [74 Others] 1.1% 6.33Ki 1.1% 6.33Ki player/src/window_settings.cpp 1.0% 5.30Ki 1.0% 5.30Ki player/src/game_config.cpp 0.8% 4.27Ki 0.8% 4.27Ki player/src/window_input_settings.cpp 0.6% 3.47Ki 0.6% 3.47Ki player/lib/liblcf/src/generated/ldb_terms.cpp 0.4% 2.25Ki 0.4% 2.25Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_blit_copy.c 0.3% 1.83Ki 0.3% 1.83Ki player/lib/liblcf/src/generated/ldb_system.cpp 0.3% 1.48Ki 0.3% 1.48Ki player/lib/liblcf/src/generated/lsd_savesystem.cpp 0.3% 1.43Ki 0.3% 1.43Ki player/src/game_ineluki.cpp 4.5% 331Ki 4.4% 331Ki .eh_frame 67.8% 224Ki 67.8% 224Ki [308 Others] 13.8% 45.8Ki 13.8% 45.8Ki 6vectorIN3lcf3rpg4ItemESaIS2_EE7reserveEm 2.6% 8.76Ki 2.6% 8.76Ki inffast.c 2.4% 7.90Ki 2.4% 7.90Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_blit_N.c 2.3% 7.74Ki 2.3% 7.74Ki pixman-ppc.c 2.2% 7.41Ki 2.2% 7.41Ki pixman-access.c 1.9% 6.35Ki 1.9% 6.35Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_surface.c 1.8% 5.86Ki 1.8% 5.86Ki utrie2.cpp 1.8% 5.85Ki 1.8% 5.85Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/power/SDL_power.c 1.7% 5.73Ki 1.7% 5.73Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_yuv.c 1.7% 5.62Ki 1.7% 5.62Ki loadednormalizer2impl.cpp 3.4% 247Ki 3.3% 247Ki .data.rel.ro 63.5% 157Ki 63.5% 157Ki [section .data.rel.ro] 33.0% 81.9Ki 33.0% 81.9Ki player/src/rtp_table.cpp 0.9% 2.12Ki 0.9% 2.12Ki player/src/window_settings.cpp 0.7% 1.81Ki 0.7% 1.81Ki player/src/game_config.cpp 0.6% 1.42Ki 0.6% 1.42Ki player/src/window_input_settings.cpp 0.4% 976 0.4% 976 player/src/game_ineluki.cpp 0.3% 832 0.3% 832 [68 Others] 0.2% 400 0.2% 400 player/src/filefinder.cpp 0.1% 344 0.1% 344 player/src/input_source.cpp 0.1% 344 0.1% 344 player/src/scene_settings.cpp 0.1% 328 0.1% 328 player/lib/liblcf/src/reader_flags.cpp 0.0% 0 1.6% 116Ki .bss NAN% 0 28.5% 33.2Ki player/src/bitmap.cpp NAN% 0 26.9% 31.3Ki player/src/window_keyboard.cpp NAN% 0 24.2% 28.2Ki [section .bss] NAN% 0 6.6% 7.64Ki [58 Others] NAN% 0 4.2% 4.90Ki player/src/rand.cpp NAN% 0 2.6% 3.04Ki player/src/lcf_data.cpp NAN% 0 2.1% 2.50Ki player/lib/liblcf/src/generated/ldb_database.cpp NAN% 0 2.0% 2.37Ki player/src/player.cpp NAN% 0 1.6% 1.88Ki player/lib/liblcf/src/generated/lsd_save.cpp NAN% 0 0.8% 913 player/src/audio_generic.cpp NAN% 0 0.4% 532 player/src/game_map.cpp 1.1% 78.7Ki 1.1% 78.7Ki .data 36.6% 28.8Ki 36.6% 28.8Ki [59 Others] 31.6% 24.9Ki 31.6% 24.9Ki [section .data] 7.3% 5.75Ki 7.3% 5.75Ki player/lib/liblcf/src/generated/ldb_terms.cpp 5.1% 4.00Ki 5.1% 4.00Ki player/src/platform/sdl/sdl2_ui.cpp 3.8% 2.97Ki 3.8% 2.97Ki player/lib/liblcf/src/generated/ldb_system.cpp 3.0% 2.38Ki 3.0% 2.38Ki player/lib/liblcf/src/generated/lsd_savesystem.cpp 2.9% 2.28Ki 2.9% 2.28Ki player/lib/liblcf/src/generated/ldb_item.cpp 2.7% 2.16Ki 2.7% 2.16Ki player/lib/liblcf/src/generated/lsd_savepartylocation.cpp 2.5% 1.94Ki 2.5% 1.94Ki player/lib/liblcf/src/generated/ldb_skill.cpp 2.3% 1.81Ki 2.3% 1.81Ki player/lib/liblcf/src/generated/ldb_actor.cpp 2.2% 1.73Ki 2.2% 1.73Ki player/lib/liblcf/src/generated/ldb_state.cpp 0.9% 64.5Ki 0.9% 64.5Ki .eh_frame_hdr 65.1% 42.0Ki 65.1% 42.0Ki [308 Others] 20.3% 13.1Ki 20.3% 13.1Ki 6vectorIN3lcf3rpg4ItemESaIS2_EE7reserveEm 2.0% 1.30Ki 2.0% 1.30Ki easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_surface.c 1.8% 1.16Ki 1.8% 1.16Ki pixman-utils.c 1.7% 1.12Ki 1.7% 1.12Ki inffast.c 1.7% 1.11Ki 1.7% 1.11Ki pixman-access.c 1.6% 1.01Ki 1.6% 1.01Ki loadednormalizer2impl.cpp 1.5% 1008 1.5% 1008 easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/video/SDL_blit_N.c 1.5% 960 1.5% 960 utrie2.cpp 1.4% 944 1.4% 944 easyrpg-buildscripts/linux-static/expat-2.5.0/lib/xmlrole.c 1.4% 920 1.4% 920 easyrpg-buildscripts/linux-static/SDL2-2.26.5/src/joystick/SDL_gamecontroller.c 0.5% 37.8Ki 0.4% 31.2Ki [27 Others] 0.1% 10.7Ki 0.1% 10.7Ki .dynstr 98.3% 10.5Ki 98.3% 10.5Ki [section .dynstr] 0.7% 79 0.7% 79 player/src/filefinder_rtp.cpp 0.7% 77 0.7% 77 player/src/graphics.cpp 0.3% 32 0.3% 32 player/src/filefinder.cpp 0.1% 10.3Ki 0.1% 10.3Ki .dynsym 99.3% 10.2Ki 99.3% 10.2Ki [section .dynsym] 0.2% 24 0.2% 24 player/src/filefinder.cpp 0.2% 24 0.2% 24 player/src/filefinder_rtp.cpp 0.2% 24 0.2% 24 player/src/graphics.cpp 100.0% 7.20Mi 100.0% 7.30Mi TOTAL ```

tl;dr 7.30MB


What you can see is that disabling audio and freetype reduces the executable size from 12.1MB to 7.30MB. Is of course not desired to have all the audio disabled but just so you can see what the "base size" of a minimal Player is. Still pretty large.

The largest offenders when having everything enabled appear to be fluidsynth with this weird rand_table. rand_table is some dithering table in fluidsynth. No idea what the purpose is but this is very large. Maybe can be patched out without impacting quality too much?

   0.0%       0   6.0%   744Ki    .bss
     NAN%       0  50.3%   375Ki    rand_table
     NAN%       0  18.3%   136Ki    midisynth::(anonymous namespace)::envelope_table
     NAN%       0   8.6%  64.0Ki    midisynth::(anonymous namespace)::vibrato_table
     NAN%       0   6.1%  45.1Ki    [862 Others]
     NAN%       0   4.4%  33.0Ki    palette
     NAN%       0   4.2%  31.3Ki    Window_Keyboard::layouts

compile units:

  52.4%  5.94Mi  49.2%  5.94Mi    .text
    74.5%  4.43Mi  74.5%  4.43Mi    [881 Others]
    13.3%   811Ki  13.3%   811Ki    easyrpg-buildscripts/linux-static/freetype-2.13.0/src/lzw/ftlzw.c
     2.0%   120Ki   2.0%   120Ki    pixman-mmx.c

Freetype takes up almost an MB. pixman-mmx is x86 cpu specific so this will differ depending on the platform.

  26.2%  2.98Mi  24.7%  2.98Mi    .rodata
    64.7%  1.93Mi  64.7%  1.93Mi    [section .rodata]
    32.3%   985Ki  32.3%   985Ki    player/src/font.cpp
     2.1%  64.3Ki   2.1%  64.3Ki    player/src/bitmap.cpp
     0.7%  20.5Ki   0.7%  20.5Ki    player/src/scene_logo.cpp

After disabling all optional dependencies

  32.8%  2.36Mi  32.3%  2.36Mi    .rodata
    26.0%   628Ki  26.0%   628Ki    icudt69_dat
    23.7%   572Ki  23.7%   572Ki    BITMAPFONT_WQY
    14.8%   358Ki  14.8%   358Ki    [section .rodata]
    12.5%   302Ki  12.5%   302Ki    SHINONOME_GOTHIC
     4.7%   114Ki   4.7%   114Ki    [622 Others]
     3.5%  84.1Ki   3.5%  84.1Ki    BITMAPFONT_TTYP0
     2.6%  64.0Ki   2.6%  64.0Ki    hard_light

Getting rid of some fonts and breaking many games around the world will likely save 1.2 MB. Problem is that we cannot say "use a TTF font" here because enabling Freetype takes 1 MB...

   7.5%   554Ki   7.4%   554Ki    .rela.dyn
    28.9%   160Ki  28.9%   160Ki    [680 Others]
    21.1%   117Ki  21.1%   117Ki    RTP::rtp_table_2k3
    12.4%  68.9Ki  12.4%  68.9Ki    RTP::rtp_table_2k
     7.0%  38.9Ki   7.0%  38.9Ki    lcf::TypedField<>
     5.1%  28.5Ki   5.1%  28.5Ki    lcf::Struct<>::fields
   3.4%   247Ki   3.3%   247Ki    .data.rel.ro
    31.6%  78.4Ki  31.6%  78.4Ki    [623 Others]
    17.1%  42.3Ki  17.1%  42.3Ki    RTP::rtp_table_2k3
    15.9%  39.3Ki  15.9%  39.3Ki    RTP::rtp_table_2k

The RTP lookup table for RTP detection requires 280 KB.

gameblabla commented 2 weeks ago

I ported EasyRPG to the Dreamcast and there's quite a lot more that can be done. (Note that my observations were done with LTO enabled)

For your information, the Dreamcast has 16MB of RAM along with 8MB of VRAM and 2MB of SPU RAM. However, because EasyRPG only has a software renderer available, the VRAM only ends up being used for the framebuffer and the SPU RAM also sits unused.

First thing i did was to remove the spanlite dependency in liblcf (instead using std::span directly) and partially switch to std::format instead of libfmt. Doing both save an additional 600kb or so. (it may be possible to save more by keeping libfmt with https://vitaut.net/posts/2024/binary-size/ but using std::span but i didn't have much luck with that).

Disabling the RTP routines saved a bit but it was a minor improvement. Disabling most built-in fonts except rmg2000 yielded quite a big improvement, i believe it was 1Mb+ for the japanese fonts alone. (removing ttyp0 gave me a very small benefit by comparison)

Disabling translations yielded a similar improvement to disabling RTP stuff, nothing huge.

Enabling mp3 decoding with mpg123 only adds an additional ~100kb... I did have to use the following :

-disable-components --disable-libsyn123 --enable-libmpg123 --disable-32bit --disable-largefile --disable-feature_report --disable-messages --disable-moreinfo --disable-id3v2 --disable-debug --disable-icy --with-cpu=generic_float --disable-real --disable-int-quality --enable-lfs-alias

Note that on some platforms, you may need largefile support (or you may have to enable 32-bits output support) but the rest doesn't really matter in the context of EasyRPG. Enabling portable mode in mpg123 unfortunately leads to linking errors... i don't know if that can be avoided.

Pixman is a huge dependency, unfortunately there's no real alternative in EasyRPG right now. Previously it was super slow with 16-bits in particular but thanks to ghabry's 16bit, it's a lot better (more so than 32bpp was even) albeit still not perfect. 16-bits support (On Dremcast, it's done by having an internal A1R5G5B5 buffer that's then uploaded to VRAM with Store Queues and displayed with PVR) not only helps with performance but also saves on memory.

For audio, i wasn't able to do much but to use a stripped down version of SDL with only audio because i encountered issues trying to make it work with sndstream from KOS... If it weren't for MIDI support, i would have bypassed Drwav and stuff altogether and just used the native audio functions.... except that won't be possible either because there's a limit of 64kb on audio samples ! (i do believe it could be possible to stream them but then it becomes rather annoying) In any case, audio works mostly fine but i'm still not 100% happy. And because we use SDL, we cannot support hardware ADPCM support either.

KallistiOS on Dreamcast currently lacks multi-sector support for DMA from CD device (only per sector)... As a result, trying to load a file results in high CPU usage, which is quite bad. To be clear, that's not an issue with EasyRPG. I hope this will be addressed in the future.

I compared the midi implementations on Dreamcast and overall, FMMidi is still the best when it comes to CPU and memory usage. Fluidlite even with the smallest soundfont available (4.7kb) is still slower than FMMidi. That said a while back, it was not my experience on the RS-90, fluidlite was quite faster by a significant margin. But at least the Dreamcast, that's not the case anymore.

Disabling the built-in EasyRPG logo saves a few kbytes, which is not negliable in a low memory situation like the Dreamcast.

What EasyRPG could do :

These would be nice to have but obviously require a lot more work :

On my branch right now, with drwav/mpg123 and my custom dreamcast backend along with some modifications above that i did, -Oz brings it down to 3.1mb. However Oz has a significant performance penalty. -O3/Ofast increases this to 3.7mb but the games are much faster (3x times faster in fact). It appears that drawing/pixman is still a significant performance bottleneck in my experience.

Ghabry commented 2 weeks ago

The performance bottleneck is probably because the rendering code heavily relies on inlining.

On low optimisation fetching the rgb-bit-mask requires 3 function calls and 3 registers. On O2 the compiler replaces the calls with constants. So more free registers and less function call overhead.

Same likely happens with our getters/setter just not as bad in terms of perf

gameblabla commented 2 weeks ago

Yeah that's probably it altho O2 only addresses the issue with rendering, using O3 instead increases the performance further in some other cases that i can't exactly pinpoint out yet.

I did a test implementation of EasyRPG with no zlib, only Miniz and SPNG and the code size dropped by about 80 kb with LTO. (along with using miniz.h for stuff that do use crc32. XYZ also relied on zlib but i switched it to miniz as well) https://github.com/gameblabla/Player/blob/5fae74ee429991cf469fc938aff1de1ed7b2e8b3/src/image_png.cpp

Not a huge improvement but still enough to allow me to allocate a small image or charset. I can't think of much less. I may attempt minimp3 later but i don't expect huge savings either given that mpg123 is only about 100kb or so in final build. (according to github repo, i would save about 50-60kb or so)