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

125 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_text_16.c — bitmap-font text rendering for mode 0x82
* (640×256×16, 4 bits per pixel).
*
* Per glyph row (8 pixels): emit 4 bytes — each byte packs two
* adjacent pixels as (LEFT<<4) | RIGHT. A precomputed 4-entry pair
* table maps the 2-bit source pattern (LEFT*2 + RIGHT) directly to
* the output byte, avoiding per-pixel mask/OR.
*
* Currently requires byte-aligned x (x must be even); odd x is
* silently ignored. Text grids are typically aligned.
*/
#include <gfx.h>
#include <stdint.h>
extern uint16_t _gfx_addr_base;
extern const uint8_t *_gfx_font_ptr;
extern void _gfx_font_ensure(void);
static uint8_t txt_y;
static uint8_t txt_row;
static uint16_t txt_addr;
/* 4-byte lookup: index = LEFT*2 + RIGHT, value = (LEFT<<4)|RIGHT. */
static uint8_t txt_pair[4];
/* Render one 8-pixel row using the pair table — 4 byte writes. */
static void render_row_16(void) __naked
{
__asm
di
in a, (#0xE2)
push af
ld a, #0x50
out (#0xE2), a
ld a, (_txt_y)
out (#0x89), a
ld hl, (_txt_addr)
ld a, (_txt_row)
ld c, a ; C = rotating source bits
ld b, #4 ; 4 output bytes
rr16_loop:
;; Extract two top bits of C as index A = LEFT*2 + RIGHT.
sla c ; CY = LEFT bit; C <<= 1
ld a, #0
adc a, a ; A = LEFT
sla c ; CY = RIGHT bit; C <<= 1
adc a, a ; A = LEFT*2 + RIGHT (0..3)
;; A = txt_pair[A]; preserve HL across the lookup.
push hl
ld e, a
ld d, #0
ld hl, #_txt_pair
add hl, de
ld a, (hl)
pop hl
ld (hl), a
inc hl
djnz rr16_loop
pop af
out (#0xE2), a
ei
ret
__endasm;
}
static void build_pair_table(uint8_t fg, uint8_t bg)
{
uint8_t f = fg & 0x0F;
uint8_t b = bg & 0x0F;
/* HIGH nibble = LEFT, LOW nibble = RIGHT (sprinter_graphics convention). */
txt_pair[0] = (uint8_t)((b << 4) | b); /* 00 BG BG */
txt_pair[1] = (uint8_t)((b << 4) | f); /* 01 BG FG */
txt_pair[2] = (uint8_t)((f << 4) | b); /* 10 FG BG */
txt_pair[3] = (uint8_t)((f << 4) | f); /* 11 FG FG */
}
void gfx_putchar16(int x, int y, char c, uint8_t fg, uint8_t bg)
{
_gfx_font_ensure();
if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return;
if (x & 1) return;
build_pair_table(fg, bg);
uint8_t cc = (uint8_t)c;
uint16_t base = (uint16_t)(_gfx_addr_base + ((unsigned)x >> 1));
for (int r = 0; r < 8; r++) {
int yy = y + r;
if ((unsigned)yy >= GFX_HEIGHT_16) break;
txt_y = (uint8_t)yy;
txt_addr = base;
txt_row = _gfx_font_ptr[r * 256 + cc];
render_row_16();
}
}
void gfx_text16(int x, int y, const char *s, uint8_t fg, uint8_t bg)
{
/* Build pair table once for the whole string (FG/BG don't change). */
_gfx_font_ensure();
if (x & 1) return;
build_pair_table(fg, bg);
for (; *s; s++) {
if (x >= GFX_WIDTH_16) break;
if ((unsigned)y >= GFX_HEIGHT_16) break;
uint8_t cc = (uint8_t)*s;
uint16_t base = (uint16_t)(_gfx_addr_base + ((unsigned)x >> 1));
for (int r = 0; r < 8; r++) {
int yy = y + r;
if ((unsigned)yy >= GFX_HEIGHT_16) break;
txt_y = (uint8_t)yy;
txt_addr = base;
txt_row = _gfx_font_ptr[r * 256 + cc];
render_row_16();
}
x += 8;
}
}