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>
86 lines
2.5 KiB
C
86 lines
2.5 KiB
C
/*
|
|
* bank1.c — code, const tables AND writable static data all live in the
|
|
* BANK1 page mapped into window 3 while these functions run.
|
|
*
|
|
* Compile flags (see Makefile):
|
|
* --codeseg BANK1 functions go to _BANK1 area
|
|
* --constseg BANK1 `static const` tables go to _BANK1
|
|
* --dataseg BANK1 uninitialized data (BSS) goes to _BANK1
|
|
*
|
|
* mkexe -p 0 zero-pads the bank's image, so any BSS bytes that don't
|
|
* appear in the IHX file are 0x00 when the bank is loaded — free zero
|
|
* init for `uint8_t buf[N];`.
|
|
*
|
|
* Note: a CRITICAL trampoline fix is required (see memory/sdcc_banking)
|
|
* — the old bcall used `pop af; out (n), a` which clobbered the uint8_t
|
|
* return value. Without that fix, banked functions returning a byte
|
|
* would silently return the saved page number instead.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
|
|
uint8_t bank1_buf[16];
|
|
|
|
static const uint16_t bank1_tab[5] = { 100, 200, 300, 400, 500 };
|
|
|
|
|
|
void bank1_fill(int seed) __banked
|
|
{
|
|
uint8_t *p = bank1_buf;
|
|
for (int i = 0; i < 16; i++)
|
|
p[i] = (uint8_t)(seed + i);
|
|
}
|
|
|
|
uint8_t bank1_peek(int idx) __banked
|
|
{
|
|
uint8_t *p = bank1_buf;
|
|
if (idx < 0 || idx >= 16) return 0xFF;
|
|
return p[idx];
|
|
}
|
|
|
|
uint16_t bank1_sumtab(void) __banked
|
|
{
|
|
uint16_t s = 0;
|
|
for (int i = 0; i < 5; i++) s += bank1_tab[i];
|
|
return s;
|
|
}
|
|
|
|
void bank1_map_print(void) __banked
|
|
{
|
|
printf( "bank1_buf = %p\n", bank1_buf);
|
|
printf( "bank1_tab = %p\n", bank1_tab);
|
|
printf( "bank1_fill = %p\n", bank1_fill);
|
|
printf( "bank1_peek = %p\n", bank1_peek);
|
|
printf( "bank1_sumtab = %p\n", bank1_sumtab);
|
|
}
|
|
|
|
/*
|
|
* malloc-from-banked test.
|
|
*
|
|
* SDCC's heap lives in HOME RAM (W2 = 0x8000-0xBFFF, see runtime/heap.s).
|
|
* Window 2 is fixed and stays mapped regardless of W3 page swaps. So
|
|
* malloc() called from a banked function should:
|
|
* 1. Return a pointer somewhere in 0x80xx..0xBFxx (W2 heap)
|
|
* 2. The pointer is usable both inside the bank (W2 still mapped) and
|
|
* after returning to HOME (W2 unchanged across trampoline).
|
|
*
|
|
* The function allocates N bytes, fills them with a known pattern, and
|
|
* returns the pointer to the caller for verification.
|
|
*/
|
|
uint8_t *bank1_alloc_and_fill(int n, uint8_t pattern) __banked
|
|
{
|
|
uint8_t *p = (uint8_t *)malloc(n);
|
|
if (p == NULL) return NULL;
|
|
for (int i = 0; i < n; i++)
|
|
p[i] = (uint8_t)(pattern + i);
|
|
printf(" bank1_alloc_and_fill: malloc(%d) -> %p\n", n, p);
|
|
return p;
|
|
}
|
|
|
|
void bank1_free(void *p) __banked
|
|
{
|
|
free(p);
|
|
}
|