Skip to content

Getting Started

Markdown

SH4ZAM is a hand-optimized, general-purpose math and linear algebra library for harnessing the floating-point power of the SH4 processor in the Sega Dreamcast. Install it, include one header, link libsh4zam.a, and make some gainz.

Pick one:

  • KallistiOS (Dreamcast). SH4ZAM is an official part of kos-ports. If you followed the standard KallistiOS setup, it is already installed. Otherwise run make install from kos-ports/sh4zam. Details: Install with KallistiOS.
  • CMake (any platform). mkdir build && cd build && cmake .. && make && make install from the repo root. On anything that is not a Dreamcast this builds the portable software back-end. Details: Install with CMake.

In order to use SH4ZAM within your project, you must do two things:

  1. Include the header file(s) within your code.
    • #include <sh4zam/shz_sh4zam.h> globally includes the whole SH4ZAM C API.
    • #include <sh4zam/shz_sh4zam.hpp> globally includes the whole SH4ZAM C++ API.
  2. Link to the statically linked library, libsh4zam.a, within your build system.

Unless you link to SH4ZAM, your project will compile correctly, yet fail to link. With a KallistiOS Makefile, add -lsh4zam:

$(TARGET): $(OBJS)
kos-cc -o $(TARGET) $(OBJS) -lsh4zam

With CMake:

target_link_libraries(MyProject PUBLIC -lsh4zam)

More on this in Using Within a Project.

These are the usage samples from the upstream README. Both build an XMTRX transform, store it, and transform a vector by it.

#include <sh4zam/shz_sh4zam.h>
int main(int argc, const char *argv[]) {
shz_vec4_t vec1 = shz_vec4_init(2.0f, 3.0f, 4.0f, 1.0f);
shz_vec4_t vec2 = shz_vec4_normalize(shz_vec4_scale(vec1, shz_sinf(SHZ_F_PI)));
shz_mat4x4_t mat = {};
shz_xmtrx_init_diagonal(vec2.x, vec2.y, vec2.z, vec2.w);
shz_xmtrx_apply_rotation_x(shz_vec4_dot(vec1, vec2));
shz_xmtrx_apply_translation(vec1.x, vec1.y, vec1.z);
shz_xmtrx_store_4x4(&mat);
shz_vec4_t vec3 = shz_xmtrx_transform_vec4(vec2);
return 0;
}

Where applicable, the C API also includes type-generic routines which resolve to the proper function based on argument type. For example, shz_vec_dot() forwards to shz_vec2_dot(), shz_vec3_dot() or shz_vec4_dot() depending on the vectors passed to it.

#include <sh4zam/shz_sh4zam.hpp>
int main(int argc, const char* argv[]) {
shz::vec4 vec1(2.0f, 3.0f, 4.0f, 1.0f);
shz::vec4 vec2 = shz::vec4(vec1 * shz::sinf(shz::pi_f)).direction();
shz::mat4x4 mat {};
shz::xmtrx::init_diagonal(vec2.x, vec2.y, vec2.z, vec2.w);
shz::xmtrx::apply_rotation_x(vec1.dot(vec2));
shz::xmtrx::apply_translation(vec1.x, vec1.y, vec1.z);
shz::xmtrx::store(&mat);
shz::vec4 vec3 = shz::xmtrx::transform(vec2);
return 0;
}

Upstream's README passes vec2.y, vec2.z to apply_translation() in the C++ version; it is fixed to match the C version here. C++ can still use the C API by design, and every C++ type is also compatible with its corresponding C type and the C API, so you can mix and match.

The C sample uses {} empty initialization, which is C23. With an older C standard, write shz_mat4x4_t mat = {0};.

At this point it is advised that you check out and attempt to run the examples provided with SH4ZAM. If you installed through kos-ports they live in kos-ports/examples/sh4zam; type make in an example's folder to build it. You can quickly verify the integrity of your SH4ZAM install by playing with Bruce's Balls, which renders 93 high-polygon spheres and reports polygons per second. See Examples for a walkthrough of what it does.