diff options
| author | 2025-12-18 23:33:26 +0000 | |
|---|---|---|
| committer | 2026-02-16 19:11:24 +0000 | |
| commit | f386f2a1fcae885967278710fe997c56e2183476 (patch) | |
| tree | a00d8854a055640952c48890b452ac5ae1bf9ced | |
| parent | 7a07c08abe46f97f2412f06c77204e9015f97a47 (diff) | |
| download | sst-f386f2a1fcae885967278710fe997c56e2183476.tar.gz sst-f386f2a1fcae885967278710fe997c56e2183476.zip | |
Size-optimise a few things
Saves multiple kilobytes, somehow. Unlikely to make much of a
performance difference since it's mostly init/shutdown stuff.
| -rw-r--r-- | src/build/gluegen.c | 4 | ||||
| -rw-r--r-- | src/chunklets/x86.c | 7 | ||||
| -rw-r--r-- | src/fixes.c | 12 | ||||
| -rw-r--r-- | src/hud.c | 6 | ||||
| -rw-r--r-- | src/hud.h | 4 | ||||
| -rw-r--r-- | src/inputhud.c | 86 | ||||
| -rw-r--r-- | src/langext.h | 8 |
7 files changed, 79 insertions, 48 deletions
diff --git a/src/build/gluegen.c b/src/build/gluegen.c index 574aa92..a055241 100644 --- a/src/build/gluegen.c +++ b/src/build/gluegen.c @@ -748,7 +748,7 @@ F( " feats.preinit_%.*s = _feat_preinit_%.*s();", } _( "}") _( "") -_( "static inline void initfeatures() {") +_( "static inline opt_small void initfeatures() {") // note: hidden flag could be 0 on OE but it's useful to know which things // *would* be hidden. in particular, GetHelpText currently checks for both // CON_INIT_HIDDEN and _CON_NE_HIDDEN when deciding whether to prepend @@ -856,7 +856,7 @@ _( "#else") _( "#endif") _( "}") _( "") -_( "static inline void endfeatures() {") +_( "static inline opt_small void endfeatures() {") for (int i = nfeatures - 1; i >= 0; --i) { s16 mod = feat_initorder[i]; if (mod_flags[mod] & HAS_END) { diff --git a/src/chunklets/x86.c b/src/chunklets/x86.c index 012cbb0..23d52ae 100644 --- a/src/chunklets/x86.c +++ b/src/chunklets/x86.c @@ -41,6 +41,13 @@ static int mrmsib(const unsigned char *p, int addrlen) { return 1; // note: include the mrm itself in the byte count } +#ifndef X86_DISABLE_SIZE_OPT +#if defined(__clang__) +__attribute((minsize)) +#elif defined(__GNUC__) +__attribute((optimize("Os"))) +#endif +#endif int x86_len(const unsigned char *insn) { #define CASES(name, _) case name: int pfxlen = 0, addrlen = 4, operandlen = 4; diff --git a/src/fixes.c b/src/fixes.c index 6a34c43..ac21722 100644 --- a/src/fixes.c +++ b/src/fixes.c @@ -57,7 +57,7 @@ static inline void unhidecmd(const char *name) { // TOOD(opt): had to hack this up badly for OE compat. think of a nicer way? -static void generalfixes() { +static inline void generalfixes() { // Expose all the demo stuff, for games like L4D that hide it for some // reason. unhide("demo_debug"); @@ -94,7 +94,7 @@ static void generalfixes() { chflags("developer", 0, _CON_NE_HIDDEN | _CON_NE_DEVONLY, CON_DEMO); } -static void l4dspecific() { +static inline void l4dspecific() { // NOTE: using unconditional dev-only flags here since we know it's NE. chflags("director_afk_timeout", _CON_NE_HIDDEN | _CON_NE_DEVONLY, 0, CON_CHEAT); @@ -122,7 +122,7 @@ static void l4dspecific() { con_setvarf(v, con_getvarf(v)); // hack: reapply limit if we loaded late } -static void l4d1specific() { +static inline void l4d1specific() { // For some reason, L4D1 hides mat_monitorgamma and doesn't archive it. // This means on every startup it's necessary to manually set non-default // values via the menu. This change here brings it in line with pretty much @@ -146,7 +146,7 @@ static void l4d1specific() { chcmdflags("update_addon_paths", 0, 0, _CON_NE_CCMDEXEC); } -static void l4d2specific() { +static inline void l4d2specific() { // L4D2 doesn't let you set sv_cheats in lobbies, but turns out it skips all // the lobby checks if this random command is not developer-only, presumably // because that flag is compiled out in debug builds and devs want to be @@ -207,7 +207,7 @@ e: chcmdflags("cl_fullupdate", CON_CHEAT, 0, 0); } -static void portal1specific() { +static inline void portal1specific() { #ifdef _WIN32 // TODO(compat): this is an absolutely atrocious way to implement this. it // should only be temporary in the interests of getting 4104 working right @@ -231,7 +231,7 @@ static void portal1specific() { #endif } -void fixes_apply() { +opt_small void fixes_apply() { generalfixes(); if (GAMETYPE_MATCHES(L4Dx)) { l4dspecific(); @@ -81,7 +81,7 @@ DECL_VFUNC_DYN(struct ISurface, void, DrawPolyLine, int *, int *, int) DECL_VFUNC_DYN(struct ISurface, void, DrawSetTextFont, struct handlewrap) DECL_VFUNC_DYN(struct ISurface, void, DrawSetTextColor, struct rgba) DECL_VFUNC_DYN(struct ISurface, void, DrawSetTextPos, int, int) -DECL_VFUNC_DYN(struct ISurface, void, DrawPrintText, hud_wchar *, int, int) +DECL_VFUNC_DYN(struct ISurface, void, DrawPrintText, const hud_wchar *, int, int) DECL_VFUNC_DYN(struct ISurface, void, GetScreenSize, int *, int *) DECL_VFUNC_DYN(struct ISurface, int, GetFontTall, struct handlewrap) DECL_VFUNC_DYN(struct ISurface, int, GetCharacterWidth, struct handlewrap, int) @@ -127,8 +127,8 @@ void hud_drawpolyline(int *x, int *y, int npoints, struct rgba colour) { DrawPolyLine(matsurf, x, y, npoints); } -void hud_drawtext(ulong font, int x, int y, struct rgba colour, hud_wchar *str, - int len) { +void hud_drawtext(ulong font, int x, int y, struct rgba colour, + const hud_wchar *str, int len) { DrawSetTextFont(matsurf, (struct handlewrap){font}); DrawSetTextPos(matsurf, x, y); DrawSetTextColor(matsurf, colour); @@ -65,8 +65,8 @@ void hud_drawline(int x0, int y0, int x1, int y1, struct rgba colour); void hud_drawpolyline(int *xs, int *ys, int npoints, struct rgba colour); /* Draws text using a given font handle. */ -void hud_drawtext(ulong font, int x, int y, struct rgba colour, hud_wchar *str, - int len); +void hud_drawtext(ulong font, int x, int y, struct rgba colour, + const hud_wchar *str, int len); /* Gets the width and height of the game window in pixels. */ void hud_screensize(int *width, int *height); diff --git a/src/inputhud.c b/src/inputhud.c index ef7f9ac..b4b101f 100644 --- a/src/inputhud.c +++ b/src/inputhud.c @@ -160,42 +160,58 @@ static inline int bsf(uint x) { // IMPORTANT: these things must all match the button order in engineapi.h static const struct { - hud_wchar *s; - int len; -} text[] = { - /* IN_ATTACK */ {L"Pri", 3}, - /* IN_JUMP */ {L"Jump", 4}, - /* IN_DUCK */ {L"Duck", 4}, - /* IN_FORWARD */ {L"Fwd", 3}, - /* IN_BACK */ {L"Back", 4}, - /* IN_USE */ {L"Use", 3}, + hud_wchar len; + hud_wchar s[6]; +} text[] = { // 7 * 20 = 140B + /* IN_ATTACK */ {3, L"Pri"}, + /* IN_JUMP */ {4, L"Jump"}, + /* IN_DUCK */ {4, L"Duck"}, + /* IN_FORWARD */ {3, L"Fwd"}, + /* IN_BACK */ {4, L"Back"}, + /* IN_USE */ {3, L"Use"}, /* IN_CANCEL */ {0}, - /* IN_LEFT */ {L"LTurn", 5}, - /* IN_RIGHT */ {L"RTurn", 5}, - /* IN_MOVELEFT */ {L"Left", 4}, - /* IN_MOVERIGHT */ {L"Right", 5}, - /* IN_ATTACK2 */ {L"Sec", 3}, + /* IN_LEFT */ {5, L"LTurn"}, + /* IN_RIGHT */ {5, L"RTurn"}, + /* IN_MOVELEFT */ {4, L"Left"}, + /* IN_MOVERIGHT */ {5, L"Right"}, + /* IN_ATTACK2 */ {3, L"Sec"}, /* IN_RUN */ {0}, - /* IN_RELOAD */ {L"Rld", 3}, + /* IN_RELOAD */ {3, L"Rld"}, /* IN_ALT1 */ {0}, /* IN_ALT2 */ {0}, /* IN_SCORE */ {0}, - /* IN_SPEED */ {L"Speed", 5}, - /* IN_WALK */ {L"Walk", 4}, - /* IN_ZOOM */ {L"Zoom", 4} + /* IN_SPEED */ {5, L"Speed"}, + /* IN_WALK */ {4, L"Walk"}, + /* IN_ZOOM */ {4, L"Zoom"} // ignoring the rest }; +struct layout_header { + // current IN_* things go up to 25 bits (1 << 24) however we don't use + // anything past IN_ZOOM here (1 << 19) + u32 mask : 24; + // our max width is currently 15; max height is 7 but allow some room here + u32 w : 4, h : 4; +}; +struct layout_btn { u8 x : 4, y : 4; }; struct layout { - int mask; - schar w, h; - // TODO(opt): should make this flexible, but that's harder than it sounds - struct { schar x, y; } pos[20]; + struct layout_header hdr; + struct layout_btn btns[]; }; +#define LAYOUT_FLEX(n) union { \ + struct { \ + struct layout_header hdr; \ + struct layout_btn btns[n]; \ + }; \ + struct layout l; \ +} // input layouts (since some games don't use all input bits) {{{ -static const struct layout layout_hl2 = { +// XXX: just manually sizing these unions for flexible arrays right now. +// not ideal, but simple enough... I guess. + +static const LAYOUT_FLEX(20) layout_hl2 = { IN_ATTACK | IN_JUMP | IN_DUCK | IN_FORWARD | IN_BACK | IN_USE | IN_MOVELEFT | IN_MOVERIGHT | IN_ATTACK2 | IN_RELOAD | IN_SPEED | IN_WALK | IN_ZOOM, @@ -221,7 +237,7 @@ static const struct layout layout_hl2 = { } }; -static const struct layout layout_portal1 = { +static const LAYOUT_FLEX(12) layout_portal1 = { IN_ATTACK | IN_JUMP | IN_DUCK | IN_FORWARD | IN_BACK | IN_USE | IN_MOVELEFT | IN_MOVERIGHT | IN_ATTACK2, 11, 7, @@ -243,7 +259,7 @@ static const struct layout layout_portal1 = { }; // TODO(compat): add portal2 layout once there's hud gamedata for portal 2 -//static const struct layout layout_portal2 = { +//static const LAYOUT_FLEX(20) layout_portal2 = { // IN_ATTACK | IN_JUMP | IN_DUCK | IN_FORWARD | IN_BACK | IN_USE | // IN_MOVELEFT | IN_MOVERIGHT | IN_ATTACK2 | IN_ZOOM, // 11, 7, @@ -268,7 +284,7 @@ static const struct layout layout_portal1 = { // } //}; -static const struct layout layout_l4d = { +static const LAYOUT_FLEX(20) layout_l4d = { IN_ATTACK | IN_JUMP | IN_DUCK | IN_FORWARD | IN_BACK | IN_USE | IN_MOVELEFT | IN_MOVERIGHT | IN_ATTACK2 | IN_RELOAD | IN_SPEED | IN_ZOOM, 13, 7, @@ -295,7 +311,7 @@ static const struct layout layout_l4d = { // }}} -static const struct layout *layout = &layout_hl2; +static const struct layout *layout = &layout_hl2.l; static const char *const fontnames[] = { "DebugFixedSmall", @@ -340,16 +356,16 @@ HANDLE_EVENT(HudPaint, int screenw, int screenh) { //else break; // not sorted } int gap = (boxsz | 32) >> 5; // minimum 1 pixel gap - int w = (boxsz + gap) * layout->w / 2 - gap; - int h = (boxsz + gap) * layout->h / 2 - gap; + int w = (boxsz + gap) * layout->hdr.w / 2 - gap; + int h = (boxsz + gap) * layout->hdr.h / 2 - gap; int basex = roundf(con_getvarf(sst_inputhud_x) * (screenw - w)); int basey = roundf(con_getvarf(sst_inputhud_y) * (screenh - h)); int buttons = heldbuttons | tappedbuttons; - for (int mask = layout->mask, bitidx, bit; mask; mask ^= bit) { + for (int mask = layout->hdr.mask, bitidx, bit; mask; mask ^= bit) { bitidx = bsf(mask); bit = 1 << bitidx; // divide sizes by 2 here to allow in-between positioning - int x = basex + layout->pos[bitidx].x * (boxsz + gap) / 2; - int y = basey + layout->pos[bitidx].y * (boxsz + gap) / 2; + int x = basex + layout->btns[bitidx].x * (boxsz + gap) / 2; + int y = basey + layout->btns[bitidx].y * (boxsz + gap) / 2; hud_drawrect(x, y, x + boxsz, y + boxsz, colours[!!(buttons & bit)], true); if_hot (font) { @@ -415,9 +431,9 @@ INIT { (void *)&hook_DecodeUserCmdFromBuffer); } - if (GAMETYPE_MATCHES(Portal1)) layout = &layout_portal1; - //else if (GAMETYPE_MATCHES(Portal2)) layout = &layout_portal2; - else if (GAMETYPE_MATCHES(L4D)) layout = &layout_l4d; + if (GAMETYPE_MATCHES(Portal1)) layout = &layout_portal1.l; + //else if (GAMETYPE_MATCHES(Portal2)) layout = &layout_portal2.l; + else if (GAMETYPE_MATCHES(L4D)) layout = &layout_l4d.l; // TODO(compat): more game-specific layouts! sst_inputhud_bgcolour_normal->cb = &colourcb; diff --git a/src/langext.h b/src/langext.h index 0624b71..7e3cbdb 100644 --- a/src/langext.h +++ b/src/langext.h @@ -77,6 +77,14 @@ static inline _Noreturn void _invoke_ub() {} //#define tailcall // Can't use this without Clang. #endif +#if defined(__clang__) +#define opt_small __attribute((minsize)) +#elif defined(__GNUC__) +#define opt_small __attribute((optimize("Os"))) +#else +#define opt_small +#endif + #endif // vi: sw=4 ts=4 noet tw=80 cc=80 |
