summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Michael Smith <mikesmiffy128@gmail.com> 2025-12-18 23:33:26 +0000
committerGravatar Michael Smith <mikesmiffy128@gmail.com> 2026-02-16 19:11:24 +0000
commitf386f2a1fcae885967278710fe997c56e2183476 (patch)
treea00d8854a055640952c48890b452ac5ae1bf9ced
parent7a07c08abe46f97f2412f06c77204e9015f97a47 (diff)
downloadsst-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.c4
-rw-r--r--src/chunklets/x86.c7
-rw-r--r--src/fixes.c12
-rw-r--r--src/hud.c6
-rw-r--r--src/hud.h4
-rw-r--r--src/inputhud.c86
-rw-r--r--src/langext.h8
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();
diff --git a/src/hud.c b/src/hud.c
index 0c7c142..ef86c4d 100644
--- a/src/hud.c
+++ b/src/hud.c
@@ -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);
diff --git a/src/hud.h b/src/hud.h
index a966ef0..5fbf5ad 100644
--- a/src/hud.h
+++ b/src/hud.h
@@ -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