c71e249a4e
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>
70 lines
1.7 KiB
C
70 lines
1.7 KiB
C
/*
|
|
* puts — C99 fputs(s, stdout) + '\n'.
|
|
*
|
|
* Turbo-C convention: stdio's `puts` is the FAST path with NO attribute
|
|
* control — backed by ESTEX PCHARS ($5C). Cursor cell attributes are
|
|
* whatever ESTEX has cached (usually the shell's default).
|
|
*
|
|
* For coloured output use cputs() / cprintf() from <conio.h>.
|
|
*
|
|
* Implementation notes:
|
|
* - PCHARS does NOT translate '\n' to CR LF, so we copy the string
|
|
* into a static buffer expanding each '\n' to CR LF, then append
|
|
* the trailing CR LF before the NUL.
|
|
* - Avoid trailing PUTCHAR after PCHARS — empirically that sometimes
|
|
* drops the next char. Embed the line ending inside the PCHARS
|
|
* buffer instead.
|
|
* - Strings longer than the buffer fall back to per-char putchar so
|
|
* we never silently truncate.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#define PUTS_BUF_SIZE 256 /* body bytes before CR expansion */
|
|
|
|
static char puts_buf[PUTS_BUF_SIZE + 3]; /* +3 for trailing CR LF NUL */
|
|
|
|
static void pchars(const char *s) __naked
|
|
{
|
|
(void)s;
|
|
__asm
|
|
push ix
|
|
ld c, #0x5C
|
|
rst #0x10
|
|
pop ix
|
|
ret
|
|
__endasm;
|
|
}
|
|
|
|
int puts(const char *s)
|
|
{
|
|
uint16_t n = 0;
|
|
uint16_t i = 0;
|
|
|
|
while (s[i] && n < PUTS_BUF_SIZE - 1) {
|
|
char c = s[i++];
|
|
if (c == '\n') {
|
|
puts_buf[n++] = '\r';
|
|
puts_buf[n++] = '\n';
|
|
} else {
|
|
puts_buf[n++] = c;
|
|
}
|
|
}
|
|
|
|
if (s[i]) {
|
|
/* Overflow — char-by-char fallback so we never truncate. */
|
|
for (uint16_t k = 0; s[k]; k++)
|
|
putchar((unsigned char)s[k]);
|
|
putchar('\n');
|
|
return 0;
|
|
}
|
|
|
|
puts_buf[n++] = '\r';
|
|
puts_buf[n++] = '\n';
|
|
puts_buf[n] = 0;
|
|
|
|
pchars(puts_buf);
|
|
return 0;
|
|
}
|