Sixty-four column rays per frame, 22.10 fixed point, no floating point unit.
The last set of games to add were the ones that test the machine hardest: real-time 3D in software, and a virtual machine from 1977.
The raycaster. Written in C against the 64x32 framebuffer, the first prototype ran at about 3 FPS for two separate reasons.
Floating point was the first. Sine and cosine through soft float choked the dual-issue core, so all math moved to 22.10 fixed point with FP_SHIFT at 10 and FP_ONE at 1024, and the trigonometry became a 256-entry lookup table generated at startup from a Bhaskara rational approximation.
Fisheye distortion was the second. Measuring Euclidean distance straight from the player to the wall intersection bends the image along wall edges. The fix is to use the perpendicular distance to the camera plane:
int32_t perp_wall_dist = (side == 0) ?
(side_dist_x - delta_dist_x) : (side_dist_y - delta_dist_y);
int line_height = (int)(((SCREEN_H) << FP_SHIFT) / perp_wall_dist);
The column step is a DDA over the map grid, accumulating side distance per axis and stepping the smaller one each iteration:
while (!hit) {
if (side_dist_x < side_dist_y) {
side_dist_x += delta_dist_x; map_x += step_x; side = 0;
} else {
side_dist_y += delta_dist_y; map_y += step_y; side = 1;
}
if (world_map[map_y][map_x] > 0) hit = 1;
}
The division budget is where this game meets the hardware. Each frame casts 64 column rays and wall heights need one division per column. The FPGA's iterative divider takes 33 cycles, so the column pass costs under 4,000 divider cycles in total. The whole pass, raycasting plus texture mapping plus sprite sorting, runs in under 400,000 cycles per frame, which fits the 45 FPS budget at 50 MHz with headroom to spare.
Chip-8. The interpreter implements all 35 opcodes: 16 8-bit registers, a 16-bit index register, a 16-level call stack, 60 Hz delay and sound timers tied to the millisecond tick, and XOR sprite drawing with collision detection.
Two Chip-8 ROMs from the active list were moved to the reserve vault for a reason worth recording. Guess the Number and Kaleidoscope were written for the 1977 COSMAC VIP hex keypad, a 4x4 matrix of keys 0 through F. With a modern keyboard and no on-screen instructions, pressing keys produced zero reaction, which reads as a broken emulator rather than a period-correct input scheme. Duplicate variants such as Pong 2 and vertical Brix, and system test ROMs, went the same way, making room for native titles with clear keyboard layouts.
The vault (games/vault/) holds those ROMs along with extra CP/M adventures such as ELIZA and Oregon Trail, plus a document describing the swap. Swapping a title in is one table entry and one build. A slightly shorter catalog in which every game responds to the keyboard is a better console than a longer one where some titles look broken.
Native games. Snake (circular-buffer tail management with an attract-mode AI), 2048 (matrix shifting, merging, pseudo-random spawn), Tetris (4x4 tetromino rotation, line clear, wall kicks), Minesweeper and Flappy Bird, all drawing directly into the framebuffer and polling the hardware key register.
That completes the catalog: 7 native and 3D titles, 6 CP/M 2.2 titles and 19 Chip-8 games, 32 in total, all behind one launcher on a board that fits in a hand, running on a CPU designed for this project. The next work is about cutting the last cord to the laptop: booting the bitstream and image from the on-board configuration flash, a VGA output on the GPIO header, and a local controller.
M_Jagadeesh97
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.