This document provides information about some of the software associated with the Tarpeeksi Hyvae Soft brand!
For auxiliary information, visit:
Ever wanted a cloud physics simulator and renderer? Maybe not, but this software provides.
The program simulates the rising of moist air and the subsequent condensation of cloud-forming droplets as the air cools; then renders the resulting 3D droplet grid into a realistic (thereabouts) image of clouds!
Further info is available via these links:
A low-level retro-oriented 3D software renderer for the HTML <canvas>!
The renderer's features include:
<canvas id='canvas' style='width: 200px; height: 200px;'></canvas> <script src='rngon.js'></script> <script> const quad = Rngon.ngon([ Rngon.vertex(-1, -1, 3), Rngon.vertex( 1, -1, 3), Rngon.vertex( 1, 1, 3), Rngon.vertex(-1, 1, 3)], { color: Rngon.color_rgba(0, 150, 255) }); Rngon.render('canvas', [Rngon.mesh([quad])]); </script>
Further info is available via these links:
Looks like an old browser, acts like an old browser. Serlain is a Windows 95-themed web front-end for Internet Archive's Wayback Machine, displaying archived pages inside a period-correct-looking mock browser!
Serlain uses the work-in-progress w95 framework for rendering the entire UI in a <canvas> (apart from displaying the archived sites in an <iframe>)!
Due to the nature of cross-domain <iframe> elements, there are various limitations to Serlain's browsing functionality. Treat it as a toy rather than a serious tool!
Further info is available via these links:
A well-featured, open-source Linux control application for Datapath's VisionRGB capture cards, with a feature-set targeted especially at retro enthusiasts!
VCS's features include:
Further info is available via these links:
A project to replace Doxygen's aging HTML output with a more modern XML-to-HTML re-theming for VCS's developer documentation!
Compared to Doxygen's standard HTML output, this version comes with a mobile-friendlier responsive layout, a cleaner look, the option of light and dark mode, and a less cluttered output directory structure!
Further info is available via these links:
A vanilla multi-threaded path tracer written originally in JavaScript and later converted into TypeScript.
Wray's features include:
These interactive render samples may not work on iOS.
Further info is available via these links:
A drop-in extension for the HTMLCanvasElement API to provide native indexed-color pixel plotting!
// Create a paletted canvas. const canvasEl = document.createElement("canvas", {is: "paletted-canvas"}); const context = canvasEl.getContext(); const indexedImage = context.createImageData(); // Fill the canvas with red (palette color #0). indexedImage.palette = [[255, 0, 0]]; indexedImage.data.fill(0); context.putImageData(indexedImage); // Change all pixels to blue by altering the palette. indexedImage.palette[0] = [0, 0, 255]; context.putImageData(indexedImage);
The overall render performance is on par with the standard API! Pure rasterization is faster due to the naturally smaller footprint of indexed pixels compared to full-color ones.
Further info is available via these links:
A modding toolset for the 1990s DOS racing game Rally-Sport! Lets you build tracks, edit textures, etc.
Over the years, the toolset has been available for a variety of platforms from MS-DOS to Linux and web browsers! In its current incarnation, it consists of a browser-based track editor and a few DOS-native applications to inject the modded content into the game!
With an integrated DOSBox, the track editor lets you run the game directly in your browser and one-click playtest your tracks as you're making them. The editor's custom software 3D renderer accurately replicates the visual quirks of the game's renderer.
Further info is available via these links:
A front-end framework for building web apps in the image of Windows 95!
This leisurely work-in-progress framework aims to replicate relevant aspects of the look and feel of Windows 95 to give the end-user a genuine retro experience!
A custom software rasterizer is used to render UI widgets inside a <canvas> for full control over the output! Conditional rendering ensures that only stale widgets are re-rendered! A React-like API is provided for developers.
Further info is available via these links:
A 3D front-end for the PC emulator PCem!
PCbi's features include:
PCbi is implemented as an independent process that communicates with PCem via shared memory. PCem's framebuffer is passed in real-time to PCbi and shown on the virtual PC's screen!
PCbi is currently pending release as open source, which may or may not happen at some point in 2023!
Further info is available via these links:
A web app for playing and corrupting the 1990s DOS game Rally-Sport in your browser! Comes with 60 pre-defined corruptions.
Further info is available via these links:
An app for hobbyist birdwatchers to keep list of their sightings in a visually engaging way!
Lintulista's features include:
This software started its life in 2019 as a full-stack JavaScript/Reach/PHP web app! Its PHP server code was converted into Node.js in 2021, and the entire thing into a desktop application in 2022 using Electron!
Further info is available via these links:
A web front-end for DOSBox – i.e. for js-dos, which is a browser wrapper for DOSBox!
Provides a simple URL hash interface for users to run DOS programs in their browser, and a JavaScript API for defining a set of containerized DOS programs to be run! For example, the following configuration defines a container for Tomb Raider:
"^/?tomb-raider/?$": { title: "Tomb Raider", zip: "./tombraid.zip", run: ["cls", "tomb"] }
With the above configuration, when the user browses to /dosbox/#/tomb-raider, the app will load the contents of tombraid.zip into js-dos, and, once the emulator has started, execute the commands cls and tomb.
Further info is available via these links:
A minimalist 3D wireframe visualizer that lets you easily display n-gonal meshes in a HTML document. Based on the Luujanko project, which renders wireframes using <svg>.
<mesh-preview> <wireframe-mesh id='triangle' name='Triangle' src-array='[ [{x:-1, y:-1, z:0}, {x: 0, y: 1, z:0}, {x: 1, y:-1, z:0}] ]'> </wireframe-mesh> <wireframe-mesh id='two-squares' name='Two squares' src-array='[ [{x:-2, y:-1, z: 0}, {x:-2, y: 1, z: 0}, {x:-1, y: 1, z: 0}, {x:-1, y:-1, z: 0}], [{x: 1, y:-1, z: 0}, {x: 1, y: 1, z: 0}, {x: 2, y: 1, z: 0}, {x: 2, y:-1, z: 0}] ]'> </wireframe-mesh> </mesh-preview>
Meshes can be imported from OBJ files or defined as plain JavaScript vertex arrays, either directly in the HTML or as a return value from a custom function. Async loading is also supported.
Possible use cases for this visualizer include debug rendering in the workflow of writing a mesh file importer.
Further info is available via these links:
A minimalist HTML wireframe renderer of n-sided polygons into an <svg> element.
Luujanko's features include:
A normal pixel rasterizer first clears the framebuffer and then draws in new pixels. Luujanko works much the same way, except rather than clearing the framebuffer, it empties the target <svg> element of its <polygon> child elements; and rather than drawing pixels, it re-populates the <svg> with <polygon> elements that have been assigned with updated screen-space vertex coordinates.
<svg id='rendering' width='200' height='200'></svg> <script type='module'> import {Luu} from 'luujanko.js'; const targetSVG = document.getElementById('rendering'); const triangle = Luu.ngon([ Luu.vertex(-1, -1, 0), Luu.vertex( 1, -1, 0), Luu.vertex( 1, 1, 0) ]); Luu.render([Luu.mesh([triangle])], targetSVG, { viewRotation: Luu.rotation(0, 0, 0), viewPosition: Luu.translation(0, 0, -3) }); </script>
Further info is available via these links:
A handy app for monitoring retail prices at Kesko's grocery stores! You give it a list of products and it'll log their prices over time, with a web interface to view the logged trends!
Further info is available via these links:
A hybrid voxel/polygon 3D software renderer that draws its inspiration from retro voxel/polygon games like Delta Force and Outcast!
The voxel renderer makes 2D heightmaps into 3D landscapes. It's effectively a ray tracer, tracing a ray through each pixel on the screen and sampling height values from the heightmap along the ray's path! The renderer has full six degrees of freedom, multi-threading, and bilinear interpolation!
The polygon renderer supports single-threaded scanline and barycentric rasterization. It uses the depth map generated by the voxel renderer to discard pixels occluded by the terrain, and draws the rest over the voxel renderer's pixel buffer.
// This function will be called by the voxel renderer for each sky pixel, with // a direction vector from the viewer to the pixel's sky patch as an argument. const auto hosekWilkieSkySampler = [&](const vond::vector3<double> &direction)->vond::color<uint8_t, 4> { const double thetaSky = std::acos(skyZenith.dot(direction)); const double phiSky = std::acos(sunPos.dot(direction)); vond::color<double, 3> result; for (unsigned int i = 0; i < 3; i++) { result.channel_at(i) = (5 * arhosek_tristim_skymodel_radiance(skyModelState[i], thetaSky, phiSky, i)); } return { uint8_t(std::min(255.0, std::max(0.0, result.channel_at(0)))), uint8_t(std::min(255.0, std::max(0.0, result.channel_at(1)))), uint8_t(std::min(255.0, std::max(0.0, result.channel_at(2)))), 255u }; };
Further info is available via these links:
A unifying C89 interface for various 3D rasterizer APIs on the Win32 platform.
Kelpo's features include:
The 1990s saw the proliferation of consumer 3D hardware along with non-standard rendering APIs and diverging hardware feature-sets (see e.g. vintage3d.org for more info)! If you wanted your 3D application to capture the home market, you had to write several variations of your rendering code – for example, the renderer for Tomb Raider came in at least six versions: one for software rendering and the rest for the various 3D hardware offerings from ATi, Matrox, S3, and others!
The goal for Kelpo is to create an easy-to-use generic render API that exposes a minimal feature-set shared across the various 3D implementations of this time period (Glide, S3D, Direct3D, and others), such that the client application only needs to write its rendering code once and can be fairly certain that the output will be the same regardless of the end-user's hardware, while in the background the application still takes advantage of that hardware via its native API.
/* Initialize Kelpo for OpenGL 1.1. */ const struct kelpo_interface_s *kelpo = NULL; kelpo_create_interface(&kelpo, "opengl_1_1"); /* Open a 640 x 480 (16-bit) render window on video device #0. */ kelpo->window.open(0, 640, 480, 16); /* Run the render loop. */ while (kelpo->window.process_messages(), !kelpo->window.is_closing()) { kelpo->rasterizer.clear_frame(); kelpo->rasterizer.draw_triangles(&triangle, 1); kelpo->window.flip_surface(); }
Kelpo is work in progress, and there's no hurry to complete it – it's a casual project being done for the sake of doing it! It currently supports Glide 3, Direct3D 5, Direct3D 7, OpenGL 1.1, and OpenGL 3.0; planned support includes the proprietary rendering APIs of Matrox, S3, and ATi, among others!
Further info is available via these links:
A HTML5 video player whose seek bar shows a spectrogram of the video's audio.
To generate the spectrogram, the app samples the output of a <video> element using an AnalyserNode to get a time-variant spectrum, then paints the spectral values into a <canvas> element overlaid on the video's seek bar.
This app was originally made for a friend who had a need for it, but it turned out their iPad was overly paranoid about letting the browser access videos on the system, and so they couldn't use this. Further info is available via these links:
A framework for constructing single-page HTML documentation using Markdown.
Work in progress.
Dokki's feature's include:
The first version of dokki was essentially a HTML framework, providing an extended set of HTML tags designed for marking-up documentation (e.g. code snippets with syntax highlighting) which were then rendered client-side using Vue.js with responsive styling, automatically-generated table of contents, and a light/dark color theme, among others. Documentation was authored directly as HTML.
Since then, dokki has been in the process of moving away from direct HTML and toward Markdown, with documentation authored in Markdown (with optional Markdown-like syntax extensions) and an in-between compilation step translating the Markdown into distributable HTML.
Further info is available via these links:
Patches a bug in Ultima 7 that forces the CPU cache on at game launch!
Like many games of its time, Ultima 7 lacks hardware-agnostic game cycle timing, meaning that its gameplay will run too fast on hardware that's much newer than the early Pentium-class machines the game was originally developed for.
The usual workaround for this problem is to disable the CPU's cache, making it run much slower and so more in line with what the game was written for! Unfortunately, this workaround doesn't work for Ultima 7, as the game will always force the CPU cache back on at launch.
This patch modifies the game executables so that they no longer touch the CPU cache flag (which controls whether the cache is disabled), and so the cache can remain disabled during gameplay. With the patched executable, I've seen a cache-disabled Athlon 64 CPU run the game absolutely fine!
; The game wants to enable protected mode as the first step in entering ; unreal mode. Normally, it assigns 1 to EBX, which sets the relevant ; first bit but also resets all the other bits (importantly, bit #30, ; for cache disable). Instead, we want to set only the first bit and ; leave the others untouched. mov ebx, cr0 or bl, 1 mov cr0, ebx ; ... ; The game has entered unreal mode and is ready to disable protected ; mode. Again, we want to manipulate only the relevant first bit. and bl, 0feh mov cr0, ebx
It seems that the (unpatched) game resets the CPU cache flag as part of its logic to enter unreal mode. But given that this process shouldn't require the cache flag to be modified, it's likely a programming oversight! The patch simply prevents the game code from modifying the cache flag bit, while retaining the relevant functionality to enter unreal mode.
Further info is available via these links:
A set of command-line tools for converting data from the DAT files of Grand Prix Legends into more standard formats! The tools can extract files from DATs (container files), convert MIPs and SRBs (images) into PNG, and turn 3DOs (3D meshes) into OBJs.
The game's assets are stored in DAT container files, which are collections of straightforward binary blobs represented as a data header and a stream of bytes. Of the types of assets, the most notable is the 3DO mesh: its data are stored in a tree format, with nodes defining properties of the mesh (visibility, texture, color, polygons, etc.) and branches joining multiple nodes together (resulting in e.g. visibility culling based on which branch path is taken). This seems to be a pre-compiled format for consumption by the game's renderer rather than a format for storing meshes in general.
I used PHP to write the DAT and MIP/SRB converters, but chose C++ for the 3DO-to-OBJ converter for better binary-parsing performance (I recall the speed-up was about an order of magnitude going from a PHP implementation to C++)!
I wrote this toolset to help generate scenes for testing the retro n-gon renderer! There didn't appear to be existing tools that ran natively on Linux!
Further info is available via these links:
A utility to parse hard drive SMART data dumps from smartctl into customizable graphs!
The app provides the ability define individual graphs (e.g. temperature per time) and to compose these graphs into an image! The graphs' data can be either directly from the SMART dumps or transformed using simple mathematical expressions!
The app uses Qt to draw the graphs and for exporting them into PNG images.
A browser adaptation of SMART log grapher!
The app parses SMART attribute data from smartctl log dumps via a Node.js back-end, then converts the data using client-side JavaScript into SVG plots for display.
The fundamental output of the app is a single plot of a SMART attribute's values over a period of time. The user is then free to style and compose these plots onto a HTML page as they see fit!
A simple 16-bit real-mode 3D rasterizer benchmark for recreational perf-testing of DOS-capable C compilers, compatible with a number of legacy C and C++ toolchains!
The benchmark renders a spinning 3D model in VGA mode 13h, then provides basic characteristics of its runtime performance!
Further info is available via these links:
An early web development effort of mine, a front-end for the venerable DOS video chip compatibility matrix. This front-end offers much improved readability and glanceability of the matrix's data!
I harvested the matrix's data, converted it into JSON format, and wrote front-end code for displaying the data as a list. The list gives each video chip an overall score based on its individual test results, and sorts the chips by that score! If you want to dig deeper, clicking on an element in the list reveals its individual test results. There's also a handy search feature to filter the list.
Test your retro CPU's floating-point performance with this DOS path tracer that renders a few samples per pixel of a scene of spheres and counts the number of seconds it took.
The program runs in VGA mode 13h (320 × 200, 256 colors) and renders its test image in 120 × 80 resolution (upscaled to 240 × 160 for display)! The scene to be rendered is made of eight spheres (five diffuse Lambertian and three reflective) and a large triangle for the ground plane; the background is a light source approximating the CIE Standard Overcast Sky.
Requires a math coprocessor.
A tool to make impulse response recordings into waterfall graphs.
The app reads WAV files representing impulse responses, uses the Kiss FFT library to extract the audio's frequencies in the time-domain, and renders the resulting spectrogram.
The method of rendering varied from ray-tracing a 3D mesh of the spectrogram to drawing slices of the spectrogram as polygons using Qt's QPainter.
Further info is available via these links:
A platform for users of RallySportED to share and download custom-made content for the game.
Rally-Sport Content's features include:
Further info is available via these links:
By default, Rally-Sport doesn't allow key re-mapping, forcing you to stick with its default A Z , . control scheme. But with this little DOS app, you can modify the game's hard-coded keymap to have your own custom controls.
Written using the 1990s Turbo C++ IDE.
Further info is available via these links:
Allows you to customize Rally-Sport's hard-coded VGA palettes. The program is a self-modifying DOS application that stores the palette within itself and can then patch it on command into Rally-Sport's game files.
Written using the 1980s Turbo C IDE.
Further info is available via these links:
The the first path-tracing renderer I made, serving as a personal messing-around testbed for offline rendering.
The renderer featured BVH-accelerated ray–triangle path tracing on the CPU and GPU, photon mapping, spectral and volumetric rendering, HDR environment mapping, and various other similar things. Its render performance wasn't stellar, but as with path tracing in general, it was able to generate fairly realistic images.
The renderer was later used in my cloud simulator to produce its cloud images, in which rays were traced through moisture volumes representing cloud bodies.
Further info is available via these links:
My first ray caster, from 2003. Its initial incarnation was based heavily on Permadi's historic ray-casting tutorial, but evolved from that original Wolfenstein-style 90-degree-walled caster into a heightmap-based 2.5D voxel renderer as I kept tinkering with it.
This project is included here as a historical curio. Vond is a more recent heightmapped voxel renderer of mine, and I continued my ray-tracing experiments with another project.
An early game I was working on while learning C++ and OpenGL.
Further info is available via these links: