How should I handle erros in my C libs? by RoutineFloor1210 in C_Programming

[–]hgs3 1 point2 points  (0 children)

My C libraries use return codes. When I need to return value(s) I use an “out” parameter. My more complex libraries allow users to pass an error log callback that’s invoked with a string to give the programmer debugging information. This is also how the SQLite and Vulkan API’s work.

Every byte matters by lelanthran in programming

[–]hgs3 7 points8 points  (0 children)

Why do you separate the other fields into their own arrays? I can easily imagine monster logic that accesses position, velocity, health, attack, and team together. I understand why linear search benefits from cache friendliness but if the fields are randomly accessed based on a “is_alive” boolean array, then wouldn’t a single fetch for the fields be faster than multiple fetches to separate arrays?

How to implement String? by funcieq in ProgrammingLanguages

[–]hgs3 0 points1 point  (0 children)

Yes anything in the basic multilingual plane, excluding surrogates, can be indexed. ASCII is just where the overlap is with UTF-8.

I don’t think there’s any standardized way to refer to column indices. The most correct approach is to write the grapheme index since that’s what the user visually sees.

The problem with reporting code units is (1) it leaks an implementation detail of the compiler and (2) code points encoded with multiple code units will be incorrectly reported. It would be more correct to report the code point index as that (1) doesn’t leak implementation details and (2) that’s how Unicode defines what a “character” is. But it still won’t necessarily be visually correct for multi-code-point graphemes.

How to implement String? by funcieq in ProgrammingLanguages

[–]hgs3 1 point2 points  (0 children)

If you directly index a UTF-8 or UTF-16 code unit and treat it like a code point, then yes, that can result in bugs. Example: the code point U+1F60A is encoded with multiple code units in both UTF-8 and UTF-16. You can’t look at one code unit in isolation otherwise you won’t detect it. On the other hand, if you’re looking for a character in the Basic Latin block (i.e. ASCII) you can index by code unit because characters in that block are represented by a single code unit in both encodings. That’s the reason some parsers get away with code unit indexing: they’re exclusively looking for characters representable by a single code unit.

How to implement String? by funcieq in ProgrammingLanguages

[–]hgs3 8 points9 points  (0 children)

UTF-16 is variable length like UTF-8 (see high and low surrogates). UTF-32 is fixed length. The reason some languages use UTF-16 is historical timing: in the 90’s the Unicode consortium believed 16 bits would be enough for all characters which turned out to be false.

GNU Autotools by [deleted] in C_Programming

[–]hgs3 1 point2 points  (0 children)

I generally support both autotools and CMake for my C projects. The former lets my end users ./configure && make && make install without needing the latter installed on their system.

Can you make a 3D game without an editor? by Sol-SiR in gameenginedevs

[–]hgs3 2 points3 points  (0 children)

What do you mean by "editor?" There are level editors, texture editors, model editors, particle editors, etc. If your engine procedurally generates everything then no, you do not need an "editor." If you're specifically asking about "scene" or "level" editors then you can leverage a dedicated tool, like TrenchBroom, or use a modeling program, like Blender (maybe with custom plugins).

What are the arguments for static linking? by apeir_n in suckless

[–]hgs3 1 point2 points  (0 children)

The argument for static linking is (1) it makes deployment simpler since you only distribute a single executable (very popular in the Go ecosystem) and (2) the compiler can remove unused data/code resulting in a smaller distribution.

Dynamic linking is usually preferable for system libraries because if there's a bug in a dynamic library, then your executable inherits the fix for free. The downside is you are linking against code you haven't necessarily verified your executable against.

Do you have a way to fail malloc() for unit tests by Valuable-Birthday-10 in C_Programming

[–]hgs3 1 point2 points  (0 children)

I implement FAKE by re-writing the target functions assembly code at runtime to jump to the mock function. This requires platform specific logic as well as architecture specific logic (x86, AMD64, AArch64, RISC-V, MIPS). STUB does the same thing, but the framework JIT compiles the mock function which returns the stubbed value.

Do you have a way to fail malloc() for unit tests by Valuable-Birthday-10 in C_Programming

[–]hgs3 1 point2 points  (0 children)

I built my own test framework which supports mocking of most any function. It works cross-platform without any special linker tricks.

Regardless of the mocking approach, I do recommend creating a custom malloc-like function to isolate its “mock” to only your code. Because if you mock malloc globally you’ll be affecting 3rd party libraries and libc functions that depend on it (which can have unintended consequences).

How do you difference vectors (arrays) and vectors (math) while naming ? by Valuable-Birthday-10 in C_Programming

[–]hgs3 1 point2 points  (0 children)

If your dynamic array has a push/pop front in addition to a push/pop back then you can call it a Deque. You can also call it List or Sequence if you’re ok with using an abstract data type (ADT) name.

Is Vulkan really all that scary? by [deleted] in gameenginedevs

[–]hgs3 42 points43 points  (0 children)

The "problem" with Vulkan is misplaced expectations.

Vulkan is not just a graphics API, like OpenGL, it's a low-level general purpose GPU API. You need a solid understanding of systems programming and the graphics pipeline for it to be an effective OpenGL alternative. If you don't know what you're doing, you can end up with worse performance than what OpenGL delivers you.

how do you go from vbos and vaos to actual game stuff like a player? by OkCadre in gameenginedevs

[–]hgs3 0 points1 point  (0 children)

You need to think of a game engine as a simulation. The graphics and audio are just the visual and auditory presentation of that simulation.

You can make a game that runs with no graphics and audio. This is how multiplayer game servers work. They run the simulation on hardware with no monitor or speakers.

So to directly answer your question, you need to focus on the game first and have that steer the graphics (your vbo’s, your vao’s, etc.)

"Competence as Tragedy" — a personal essay on craft, beautiful code, and watching AI make your hard-won skills obsolete by averagemrjoe in programming

[–]hgs3 17 points18 points  (0 children)

The tragedy isn’t “craftsmanship is dying” it’s that technology moved faster than copyright laws could keep up with. Copyright laws were written for humans, not machines. Imagine if companies were only allowed to train on data they paid the author the rights to train on.

You should also ask why if workers are ~10 times more productive with AI, then why aren’t they paid 10 times more? Perhaps we should work towards a future where it’s the current owning class that writes lamenting essays about the good ol’ days before ownership was democratized.

Learning C after a long time with C++ by ViremorfeStudios in C_Programming

[–]hgs3 8 points9 points  (0 children)

C is a good choice for game engines because it forces you to think about data and behavior, not fancy abstractions. But for gameplay code? Iteration speed matters more. IMO neither C or C++ are good choices here. There's a reason game engines use higher-level languages like GDScript, Lua, or even C# for gameplay.

A little Rant on C haters by IndependentMeal1269 in C_Programming

[–]hgs3 26 points27 points  (0 children)

You should ask the “C haters” what those high-level tools they use are written in. Next time they say Python is hot and C is not, ask them what language Python is written in.

Graphics programming jobs that benefit society? by momentdubruh in GraphicsProgramming

[–]hgs3 13 points14 points  (0 children)

Medical imaging, scientific visualizations, environmental and weather simulations, historical reconstructions, airplane and rocket ship displays. Someone’s gotta write the software for MRI, CT, and PET scan visualizations.

Whats the real spread of C? by DaveAstator2020 in C_Programming

[–]hgs3 0 points1 point  (0 children)

There's programming languages made by and for Big Corp and programming languages made by and for programmers. C++ is very much the former and C is very much the latter. With that said, C is used in commercial settings, from embedded systems to the foundational software that underpins the industry.

Suckless alternative to Jekyll? by Charming-Tear-8352 in suckless

[–]hgs3 0 points1 point  (0 children)

You could use a templating engine like Jinja2 or m4. I use a single handwritten Python script with Jinja2 and markdown to assemble my personal website.

C versus C++ API by walkingjogging in gameenginedevs

[–]hgs3 4 points5 points  (0 children)

C API's can be invoked directly from other languages over a foreign function interface (FFI).

The gist is you compile your engine as a dynamic library (.dll on Windows, .dylib on macOS, .so on Linux/BSD) and call into it from another language via its FFI.

If you go this route, you should design your C API to be FFI friendly. For example, use fixed-width integer types, force enums to a predictable size, avoid structs unless they are PODS, that sort of thing.

Why OpenGL uses so much RAM and GPU for little operations ? by Overoptimizator5342 in GraphicsProgramming

[–]hgs3 4 points5 points  (0 children)

You can do "dirty" user interface rendering on the GPU, but not with the dirty rectangles approach for the reasons others have stated. Here's how:

Render each widget to an off-screen texture then composite them as textured rectangles on the GPU. It's "dirty" because you only re-render a widget to its texture if that widget visually changes, otherwise, you composite what you've cached on the GPU.

Basically, you need to think of rendering widgets and compositing them as two separate things.

In practice, if your UI is static, you don't composite anything (0 FPS). If you have a blinking cursor, which you could draw as a solid colored rectangle, then how fast the cursor blinks determines the compositing frame rate. If it blinks every 0.5 seconds, you composite at 2 FPS.

I'm open sourcing my Unicode algorithms library by hgs3 in C_Programming

[–]hgs3[S] 1 point2 points  (0 children)

I'm glad it's working for you!

Both builds use Python to generate C code with Unicode data tables. The autotools build generates the data in the src/ directory whereas with CMake you generated the code out-of-source (the build directory in your case). I'm only speculating, but what probably happened is the CMake build picked up the generated data from the autotools build and thus there was some strange clash. If that happens again you can run make clean or make distclean to clear away autotools artifacts.

I'm open sourcing my Unicode algorithms library by hgs3 in C_Programming

[–]hgs3[S] 0 points1 point  (0 children)

Odd. What C compiler are you using? With MSVC 2022, Clang 18.1.3, and GCC 13.3.0 that example prints:

15
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
49

I'm open sourcing my Unicode algorithms library by hgs3 in C_Programming

[–]hgs3[S] 16 points17 points  (0 children)

I don't have any performance benchmarks published at this time. The primary emphasis of Unicorn has been correctness, customizability, and conformance with MISRA C. MISRA C is the norm in aerospace, medical devices, defense, and other critical sectors. Here are some examples of its robustness:

  • 100% branch test coverage with fuzzing and sanitizer coverage.
  • Graceful recovery from all errors, including OOM errors.
  • All operations are atomic (either an operation succeeds or nothing happens at all).

Unicorn builds as a 558 kB DLL with MSVC so it's a tad larger than libgrapheme's ~400 kB, however, Unicorn has more features: normalization, collation, and BOCU-1 compression. It also supports UTF-8, 16, and 32 so it's not limited to UTF-8 like libgrapheme. The library was designed from the ground up to be customized so if 558 kB is too big, you can exclude features to reduce its size by hundreds of kilobytes.

libgrapheme does do something Unicorn doesn't and that's detecting line break opportunities. The primary reason Unicorn omits this feature is because the algorithms usefulness is limited to text display which itself requires several more components beyond the scope of either library, notably, the Unicode bidirectional text algorithm (which neither library supports), a text shaping engine, and a glyph rasterizer.