Files
snark13 c71e249a4e Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.

What's in here:
  bin/sprinter-cc        — driver script invoking SDCC + linker + mkexe
  libc/                  — Sprinter-specific libc layer over ESTEX/BIOS
                           (conio, gfx, io, mem, stdio + headers)
  runtime/               — crt0 variants (default/small/banked/minimal)
                           + heap + bank trampolines
  toolchain/             — mkexe (SprintEXE packer, C + tests)
  examples/              — 30 demo programs (gfx, file I/O, env, time, …)
  lib/Makefile           — builds the libc archive (sprinter.lib)
  docs/                  — converted Sprinter manuals + asm reference samples
  third_party/           — solid-c reference compiler dump + sdcc setup script
  release_docs/          — packaging / release notes

gitignore overhaul:
  • Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
    and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
    on macOS APFS).  Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
  • Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
    INPUT fixtures, not build outputs.
  • Collapse the duplicated SDCC/C/Sdcc sections into one section per
    concern (build outputs / vendored / OS-junk).
  • Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 16:13:21 +03:00

119 lines
3.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* gfx_256.c — 256-colour (mode 0x81) public drawing API.
*
* Single-shot wrappers do one W3-begin / one W3-end around their raw
* call. Composites (rect, fill_rect, line) wrap a single begin/end
* around many raw calls so the W3 dance is paid once per operation,
* not once per pixel/byte.
*/
#include <gfx.h>
#include <stdint.h>
/* From gfx_raw_common.c — DI + map _gfx_bank into W3, save previous. */
extern void _gfx_w3_video_begin(void);
extern void _gfx_w3_video_end(void);
/* From gfx_raw_256.c — W3-naive primitives. */
extern void _gfx_putpixel256_raw(int x, int y, uint8_t color);
extern void _gfx_hline256_raw (int x, int y, int len, uint8_t color);
extern void _gfx_vline256_raw (int x, int y, int len, uint8_t color);
extern void _gfx_clear256_raw (uint8_t color);
void gfx_clear256(uint8_t color)
{
_gfx_w3_video_begin();
_gfx_clear256_raw(color);
_gfx_w3_video_end();
}
void gfx_putpixel256(int x, int y, uint8_t color)
{
if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return;
_gfx_w3_video_begin();
_gfx_putpixel256_raw(x, y, color);
_gfx_w3_video_end();
}
void gfx_hline256(int x, int y, int len, uint8_t color)
{
_gfx_w3_video_begin();
_gfx_hline256_raw(x, y, len, color);
_gfx_w3_video_end();
}
void gfx_vline256(int x, int y, int len, uint8_t color)
{
_gfx_w3_video_begin();
_gfx_vline256_raw(x, y, len, color);
_gfx_w3_video_end();
}
void gfx_rect256(int x, int y, int w, int h, uint8_t color)
{
if (w <= 0 || h <= 0) return;
_gfx_w3_video_begin();
_gfx_hline256_raw(x, y, w, color);
_gfx_hline256_raw(x, y + h - 1, w, color);
if (h > 2) {
_gfx_vline256_raw(x, y + 1, h - 2, color);
_gfx_vline256_raw(x + w - 1, y + 1, h - 2, color);
}
_gfx_w3_video_end();
}
void gfx_fill_rect256(int x, int y, int w, int h, uint8_t color)
{
if (w <= 0 || h <= 0) return;
/* Pick the orientation with fewer accelerator bursts. Each burst
* paints up to 256 contiguous bytes (horizontal) or up to 256
* vertical pixels in one column.
* row-major (hlines): h × ceil(w/256) bursts
* col-major (vlines): w × ceil(h/256) bursts — for h ≤ 256 = w
* Vertical wins for tall-narrow rects; horizontal for short-wide. */
int h_bursts = h * ((w + 255) >> 8);
int v_bursts = w * ((h + 255) >> 8);
_gfx_w3_video_begin();
if (h_bursts <= v_bursts) {
for (int yy = 0; yy < h; yy++)
_gfx_hline256_raw(x, y + yy, w, color);
} else {
for (int xx = 0; xx < w; xx++)
_gfx_vline256_raw(x + xx, y, h, color);
}
_gfx_w3_video_end();
}
void gfx_line256(int x0, int y0, int x1, int y1, uint8_t color)
{
/* Orthogonal lines route to the accelerator. */
if (y0 == y1) {
int x = x0 <= x1 ? x0 : x1;
int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1;
gfx_hline256(x, y0, w, color);
return;
}
if (x0 == x1) {
int y = y0 <= y1 ? y0 : y1;
int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1;
gfx_vline256(x0, y, h, color);
return;
}
/* Bresenham — single W3-setup around the whole loop. */
int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx;
int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy;
int err = (dx > dy ? dx : -dy) / 2;
int x = x0, y = y0;
_gfx_w3_video_begin();
for (;;) {
_gfx_putpixel256_raw(x, y, color);
if (x == x1 && y == y1) break;
int e2 = err;
if (e2 > -dx) { err -= dy; x += sx; }
if (e2 < dy) { err += dx; y += sy; }
}
_gfx_w3_video_end();
}