Add mdview markdown viewer, reorganize tests/examples and libc layout

- Split tests/ (libc feature tests) and examples/ (real apps); shared
  app.mk in repo root, was examples/example.mk
- libc/io/* split into libc/{conio,env,errno,file,mouse,string,sys,
  time,video}/ — clearer module boundaries
- New examples/mdview/: markdown viewer (Phases 1-5 + light nested
  lists). Headers (H1-H4), HR, ulist/olist/quote with nesting via
  leading spaces, fenced code blocks, inline emphasis (bold/italic/
  underscore/code), wrap/unwrap mode with soft wrap (F2), horizontal
  pan (← →) with '>' truncation indicator
- libc additions: scroll() in conio (ESTEX SCROLL), strlwr/strupr,
  gets() test
- Makefile updates across tests/ for the new shared app.mk path

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 22:23:36 +03:00
parent b851e22fa6
commit 737c974400
104 changed files with 2485 additions and 223 deletions
+5
View File
@@ -0,0 +1,5 @@
# Build argv_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := argv
include $(PROJ_ROOT)/app.mk
+22
View File
@@ -0,0 +1,22 @@
#include <stdio.h>
/*
* Prints every command-line argument, then exits.
*
* Try in MAME / ESTEX shell:
* ARGV_TES -> argc=1, argv[0] = ""
* ARGV_TES one two three -> argc=4, argv[1..3] = "one","two","three"
* ARGV_TES spaced args -> multiple spaces are squashed
*/
int main(int argc, char **argv)
{
printf("argc = %d\n", argc);
for (int i = 0; i < argc; i++) {
printf("argv[%d] = \"%s\"\n", i, argv[i]);
}
puts("");
puts("Press any key to exit...");
(void)getchar();
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := assrtest
include $(PROJ_ROOT)/app.mk
+43
View File
@@ -0,0 +1,43 @@
/*
* assrtest — exercise <assert.h> from SDCC's z80.lib.
*
* Tests both the disabled-debug (NDEBUG) form and the active form.
* The failing assert at the end prints an error message via printf
* (which routes through our putchar) and then halts.
*/
#include <stdio.h>
#include <assert.h>
static int divide(int a, int b)
{
assert(b != 0); /* must succeed for the test cases */
return a / b;
}
int main(int argc, char **argv)
{
(void)argc; (void)argv;
puts("assrtest: exercising <assert.h>");
/* These pass. */
int q = divide(10, 2);
printf(" divide(10, 2) = %d\n", q);
assert(q == 5);
q = divide(-9, 3);
printf(" divide(-9, 3) = %d\n", q);
assert(q == -3);
puts(" all passing asserts OK");
/* Final, failing assert. Prints "Assert(...) failed in function ..."
* then enters an infinite loop (SDCC __assert convention). */
puts(" triggering deliberate failing assert (system will hang)...");
int zero = 0;
(void)divide(1, zero);
/* unreachable */
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build attr_probe.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := attrprob
include $(PROJ_ROOT)/app.mk
+79
View File
@@ -0,0 +1,79 @@
#include <stdio.h>
#include <conio.h>
#include <stdint.h>
/*
* attr_probe — visualise every value of the ESTEX attribute byte.
*
* Layout:
* row 2 16 cells: low nibble 0..F, high nibble 0 (varying fg)
* row 4 16 cells: low nibble 7, high nibble 0..F (varying bg)
* row 6 bit-7 toggle test: 8 pairs comparing N with N|0x80
* row 8 full 16x16 grid: bg outer, fg inner — every attribute byte
* row 26 RDCHAR readback of a known cell
*
* Each cell is drawn with wrchar() so the attribute is set exactly,
* independent of ESTEX's hidden "current" attribute used by PCHARS.
*/
int main(void)
{
clrscr();
gotoxy(20, 0); cputs("== attr probe ==");
/* Row 2: vary fg (low nibble), bg = 0 (black). */
gotoxy(0, 2); cputs("fg 0..F /bg0:");
for (int i = 0; i < 16; i++) {
wrchar(15 + i, 2, 'A' + i, (uint8_t)i);
}
/* Row 4: vary bg (high nibble), fg = 7 (light gray). */
gotoxy(0, 4); cputs("bg 0..F /fg7:");
for (int i = 0; i < 16; i++) {
wrchar(15 + i, 4, 'A' + i, (uint8_t)((i << 4) | 0x07));
}
/* Row 6: compare attr N with N|0x80 — bit 7 may be blink or extra bg. */
gotoxy(0, 6); cputs("bit7: N|N|0x80 pairs (1F,2E,3D,4C,5B,6A,79,F0):");
{
static const uint8_t probes[] = { 0x1F, 0x2E, 0x3D, 0x4C,
0x5B, 0x6A, 0x79, 0xF0 };
for (int i = 0; i < 8; i++) {
wrchar(2 + i*4, 7, '*', probes[i]);
wrchar(2 + i*4 + 1, 7, '*', probes[i] | 0x80);
/* hex labels under each pair */
gotoxy(2 + i*4, 8);
printf("%02X", probes[i]);
}
}
/* Row 10..25: full 16x16 grid of every attr byte 0x00..0xFF.
* Cell (col, row) = (col_idx + offset, row_idx + 10) holds char '#'
* with attr = (row_idx << 4) | col_idx. */
gotoxy(0, 10); cputs("Full 16x16 grid (row=bg, col=fg):");
for (int row = 0; row < 16; row++) {
for (int col = 0; col < 16; col++) {
uint8_t attr = (uint8_t)((row << 4) | col);
wrchar(20 + col, 11 + row, '#', attr);
}
/* label rows */
gotoxy(15, 11 + row);
printf("%X:", row);
}
gotoxy(20, 27);
cputs("0123456789ABCDEF (fg)");
/* RDCHAR readback test. */
{
uint16_t got = rdchar(15, 2);
gotoxy(0, 29);
printf("rdchar(15,2) -> ch=0x%02X attr=0x%02X (expected 'A'=0x41 attr=0x00)",
got & 0xFF, (got >> 8) & 0xFF);
}
gotoxy(0, 31);
cputs("press any key");
getch();
return 0;
}
+11
View File
@@ -0,0 +1,11 @@
# Build banked.exe — HUGE memory mode (small + banked code in W3).
#
# Layout:
# CODE/HOME at 0x4100 (W1), DATA at 0x8000 (W2), banks at 0x{N}C000 (W3).
# crt0_banked.s loads N banks from the .EXE before calling main.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := banked
MEMORY := huge
EXTRA_FLAGS := --bank 1=bank1.c --bank 2=bank2.c
include $(PROJ_ROOT)/app.mk
+17
View File
@@ -0,0 +1,17 @@
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>
void bank1_func(int x) __banked
{
(void)x;
puts("BANK1: hello from a banked function!");
puts("BANK1: window 3 phys page = ");
hex8(_io_page_w3); /* should be BANK1's phys page */
putchar('\n');
putchar('1');
putchar('=');
putchar('0' + (x / 10) % 10);
putchar('0' + x % 10);
putchar('\n');
}
+18
View File
@@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>
void bank2_func(int x) __banked
{
(void)x;
puts("BANK2: hello from the second bank!");
puts("BANK2: window 3 phys page = ");
hex8(_io_page_w3); /* should be BANK2's phys page */
putchar('\n');
putchar('2');
putchar('=');
putchar('0' + (x / 100) % 10);
putchar('0' + (x / 10) % 10);
putchar('0' + x % 10);
putchar('\n');
}
+47
View File
@@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>
/* crt0_banked.s reads this constant to know how many banks to load. */
const uint8_t n_banks = 2;
void bank1_func(int x) __banked;
void bank2_func(int x) __banked;
extern uint8_t bank_pages[]; /* filled by crt0_banked.s */
static void show_w3(const char *who)
{
puts(who);
hex8(_io_page_w3); /* current physical page mapped in window 3 */
putchar('\n');
}
int main(void)
{
puts("HOME: program start.");
#ifdef DEBUG_RT
printf("HOME: w2_self_allocated = %u\n", w2_self_allocated);
#endif
show_w3("HOME: window 3 phys page = ");
puts("HOME: bank_pages[1] (BANK1 phys) = ");
hex8(bank_pages[1]);
putchar('\n');
puts("HOME: bank_pages[2] (BANK2 phys) = ");
hex8(bank_pages[2]);
putchar('\n');
puts("HOME: calling bank1_func(42)...");
bank1_func(42);
show_w3("HOME: back, window 3 phys = ");
puts("HOME: calling bank2_func(123)...");
bank2_func(123);
show_w3("HOME: back, window 3 phys = ");
puts("HOME: done.");
puts("Press any key to exit...");
(void)getchar();
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
# Build banked_big.exe — BIG memory mode (tiny + banked code in W1).
#
# Layout:
# CODE/HOME at 0x8100 (W2), DATA chained after CODE (W2)
# Banks at virtual 0x{N}4000 — physical pages mapped into W1
# crt0_banked.s + bank.s built with BANK_W1=1 by sprinter-cc
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := bankedbg
MEMORY := big
EXTRA_FLAGS := --bank 1=bank1.c --bank 2=bank2.c
include $(PROJ_ROOT)/app.mk
+17
View File
@@ -0,0 +1,17 @@
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>
void bank1_func(int x) __banked
{
(void)x;
puts("BANK1: hello from a banked function (W1)!");
puts("BANK1: window 1 phys page = ");
hex8(_io_page_w1); /* should be BANK1's phys page */
putchar('\n');
putchar('1');
putchar('=');
putchar('0' + (x / 10) % 10);
putchar('0' + x % 10);
putchar('\n');
}
+18
View File
@@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>
void bank2_func(int x) __banked
{
(void)x;
puts("BANK2: hello from the second bank (W1)!");
puts("BANK2: window 1 phys page = ");
hex8(_io_page_w1); /* should be BANK2's phys page */
putchar('\n');
putchar('2');
putchar('=');
putchar('0' + (x / 100) % 10);
putchar('0' + (x / 10) % 10);
putchar('0' + x % 10);
putchar('\n');
}
+58
View File
@@ -0,0 +1,58 @@
/*
* banked_big — BIG memory mode: base CODE+DATA in W2, banked code in W1.
*
* Layout:
* _CODE at 0x8100 (W2), DATA chained after CODE (W2)
* _BANK1 / _BANK2 at virtual 0x{N}4000 — physical page mapped into W1
* trampoline ___sdcc_bcall_ehl swaps port 0xA2 (W1) to call bank funcs
*
* Mirrors examples/banked (HUGE mode) for direct comparison.
*/
#include <stdio.h>
#include <stdint.h>
#include <sprinter.h>
/* crt0_banked.s reads this constant to know how many banks to load. */
const uint8_t n_banks = 2;
void bank1_func(int x) __banked;
void bank2_func(int x) __banked;
extern uint8_t bank_pages[]; /* filled by crt0_banked.s */
static void show_w1(const char *who)
{
puts(who);
hex8(_io_page_w1); /* current physical page mapped in window 1 */
putchar('\n');
}
int main(void)
{
puts("HOME: program start (BIG mode).");
#ifdef DEBUG_RT
printf("HOME: w2_self_allocated = %u\n", w2_self_allocated);
#endif
show_w1("HOME: window 1 phys page = ");
puts("HOME: bank_pages[1] (BANK1 phys) = ");
hex8(bank_pages[1]);
putchar('\n');
puts("HOME: bank_pages[2] (BANK2 phys) = ");
hex8(bank_pages[2]);
putchar('\n');
puts("HOME: calling bank1_func(42)...");
bank1_func(42);
show_w1("HOME: back, window 1 phys = ");
puts("HOME: calling bank2_func(123)...");
bank2_func(123);
show_w1("HOME: back, window 1 phys = ");
puts("HOME: done.");
puts("Press any key to exit...");
(void)getchar();
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
# bank_local_data — code AND static data live in BANK1.
#
# HUGE mode: HOME at 0x4100 (W1), DATA at 0x8000 (W2), BANK1 in W3.
# sprinter-cc compiles bank1.c with --codeseg/--constseg/--dataseg BANK1
# automatically (via --bank 1=bank1.c). mkexe gets `-p 0` so BSS pages
# in the bank land as zero-filled — no runtime zeroing needed.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := banklocl
MEMORY := huge
EXTRA_FLAGS := --bank 1=bank1.c --mkexe -p --mkexe 0
include $(PROJ_ROOT)/app.mk
+85
View File
@@ -0,0 +1,85 @@
/*
* 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);
}
+87
View File
@@ -0,0 +1,87 @@
/*
* bank_local_data — demonstrates that a banked function can own its own
* static (BSS) array and a const lookup table without burning HOME
* memory. When the function executes, BANK1 is mapped into window 3
* and both code and data are directly addressable.
*
* No bank_read / bank_write needed — the trampoline maps the bank for
* us and the C code touches the arrays normally.
*/
#include <stdio.h>
#include <stdint.h>
extern void bank1_fill (int seed) __banked;
extern uint16_t bank1_sumtab (void) __banked;
extern uint8_t bank1_peek (int idx) __banked;
extern void bank1_map_print(void) __banked;
extern uint8_t *bank1_alloc_and_fill(int n, uint8_t pattern) __banked;
extern void bank1_free (void *p) __banked;
/* MUST be `const`: crt0_banked reads _n_banks BEFORE gsinit, so
* non-const initialized variables haven't been copied yet and would
* read 0 → bank loading is skipped → garbage in window 3. */
const uint8_t n_banks = 1;
uint8_t local0_buf[16];
int main(int argc, char **argv)
{
puts("bank_local_data: testing static data in BANK1");
bank1_map_print();
/* Verify crt0_banked parsed argv correctly. */
printf("argc=%d, argv[0]=\"%s\"\n", argc, argv[0]);
printf("local0_buf = %p\n", local0_buf);
for (int i = 1; i < argc; i++)
printf(" argv[%d]=\"%s\"\n", i, argv[i]);
/* Seed the BSS array in BANK1. */
bank1_fill(0x10);
/* Read it back through another banked function — verifies the data
* survived after the trampoline returned to HOME and re-entered. */
int ok = 1;
for (int i = 0; i < 8; i++) {
uint8_t v = bank1_peek(i);
uint8_t expected = (uint8_t)(0x10 + i);
if (v != expected) {
printf(" bank1_buf[%d] = 0x%02X, expected 0x%02X\n",
i, v, expected);
ok = 0;
}
}
if (ok)
puts(" buf[0..7] OK");
/* Use the const lookup table that lives in BANK1. */
uint16_t sum = bank1_sumtab();
printf(" bank1_sumtab() = %u (expected 1500)\n", sum);
/* malloc from a banked function — the heap lives in W2 (HOME),
* which stays mapped across W3 page swaps. Returned pointer
* should be usable both inside the bank AND from HOME afterwards. */
uint8_t *heap_p = bank1_alloc_and_fill(32, 0xA0);
if (heap_p == NULL) {
puts(" malloc from bank FAILED");
} else {
printf(" caller sees pointer = %p\n", heap_p);
int ok = 1;
for (int i = 0; i < 32; i++) {
uint8_t expected = (uint8_t)(0xA0 + i);
if (heap_p[i] != expected) {
printf(" heap_p[%d] = 0x%02X, expected 0x%02X\n",
i, heap_p[i], expected);
ok = 0;
}
}
if (ok) puts(" bank-allocated heap [0..31] OK from HOME");
bank1_free(heap_p);
}
puts("done");
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
# Build cat.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := cat
EXTRA_DATA := test.txt
include $(PROJ_ROOT)/app.mk
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
int fd = open("TEST.TXT", O_RDONLY);
if (fd < 0) {
puts("cat: cannot open TEST.TXT");
puts("Press any key to exit...");
(void)getchar();
return 1;
}
puts("--- TEST.TXT ---");
char buf[64];
int n;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
for (int i = 0; i < n; i++) {
putchar((unsigned char)buf[i]);
}
}
close(fd);
puts("");
puts("--- end of file. Press any key to exit. ---");
(void)getchar();
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
Hello from a file on disk!
This text was read by cat.exe through
the ESTEX file I/O syscalls:
open ($11)
read ($13)
close ($12)
The whole loop hits real DSS code on
the Sprinter (in MAME, just an image).
Line 9.
Line 10.
Final line.
+5
View File
@@ -0,0 +1,5 @@
# Build conio_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := conio
include $(PROJ_ROOT)/app.mk
+128
View File
@@ -0,0 +1,128 @@
#include <stdio.h>
#include <conio.h>
#include <unistd.h> /* sleep */
/*
* Exercises every conio function:
* clrscr — clear the screen
* gotoxy — move cursor to (x, y), 0-based
* putch — single character
* cputs — string without auto-newline
* kbhit — non-blocking key probe
* getch — blocking, no echo
* getche — blocking, with echo
*
* Sprinter native text mode is 80×32, so we anchor corners at
* (0,0), (79,0), (0,31), (79,31).
*/
int main(void)
{
/* 1. clrscr + diagnostic probes + a centered banner.
*
* Row-0 probe: figure out why [NW]/[NE] don't paint.
* '0','1','2','3' — single putch at row 0, cols 0/5/40/79
* "R0" — cputs at row 0, col 10
* 'a','b','c','R1'— same pattern on row 1 (control)
*/
clrscr();
gotoxy(0, 0); putch('0');
gotoxy(5, 0); putch('1');
gotoxy(40, 0); putch('2');
gotoxy(79, 0); putch('3');
gotoxy(10, 0); cputs("R0");
gotoxy(0, 1); putch('a');
gotoxy(5, 1); putch('b');
gotoxy(79, 1); putch('c');
gotoxy(10, 1); cputs("R1");
/* Bottom corners moved to row 30 to avoid the auto-wrap-scroll issue —
* cputs("[SE]") at (76, 31) ends with cursor at col 80 on the last row,
* which scrolls the screen up by one and eats everything we wrote at
* row 0. By staying on row 30, no wraparound is triggered. */
gotoxy(0, 30); cputs("[SW]");
gotoxy(76, 30); cputs("[SE]");
/* Row 31 single-char probes (col 0 + col 78, no col-80 reach). */
gotoxy(0, 31); putch('L');
gotoxy(78, 31); putch('R');
gotoxy(30, 4);
cputs("== conio test ==");
/* wherex/wherey probe — place cursor at a known spot, read it back. */
gotoxy(15, 5);
int cx = wherex();
int cy = wherey();
gotoxy(0, 6);
printf("wherex/wherey after gotoxy(15,5) -> x=%d y=%d", cx, cy);
/* 2. putch — single chars in a diagonal. */
for (int i = 0; i < 16; i++) {
gotoxy(10 + i, 8 + i);
putch('*');
}
/* 3. kbhit polling loop with a spinning indicator. */
gotoxy(0, 14);
cputs("kbhit polling - press any key to interrupt");
static const char spin[] = "|/-\\";
int frame = 0;
while (!kbhit()) {
gotoxy(50, 14);
putch(spin[frame & 3]);
frame++;
/* small delay so the spin is visible (sleep is in 1-sec units;
* we want ~10 fps — implemented with a busy "halts" later, but
* here we just rely on kbhit being slow enough to be visible). */
}
int probed = kbhit(); /* re-read to clear / display */
gotoxy(0, 16);
printf("kbhit captured 0x%02X ('%c')", probed,
(probed >= 0x20 && probed < 0x7F) ? probed : '?');
/* 4. getch — drain the key + ask for one with no echo. */
gotoxy(0, 18);
cputs("getch (no echo) — press a key: ");
int k1 = getch();
gotoxy(0, 19);
printf("you pressed 0x%02X ('%c')", k1,
(k1 >= 0x20 && k1 < 0x7F) ? k1 : '?');
/* 5. getche — same but the keypress should appear on screen. */
gotoxy(0, 21);
cputs("getche (with echo) — press a key: ");
gotoxy(36, 21);
int k2 = getche();
gotoxy(0, 22);
printf("you pressed 0x%02X (echoed above)", k2);
/* 6. Finish at the bottom; do NOT scroll. */
gotoxy(0, 28);
cputs("All conio functions exercised. Press any key to exit.");
set_videotextmode(TEXT_MODE_40x32);
for (int i = 0; i < 16; i++) {
wrchar(4 + i * 2, 3, i < 10 ? '0' + i : 'A' - 10 + i, 0x1F);
wrchar(4 + i * 2 + 1, 3, ' ', 0x1F);
}
for (int j = 0; j < 16; j++) {
wrchar(2, 4 + j, j < 10 ? '0' + j : 'A' - 10 + j, 0x1F);
wrchar(2 + 1, 4 + j, ' ', 0x1F);
for (int i = 0; i < 16; i++) {
wrchar(4 + i * 2, 4 + j, j * 16 + i, 0x2F);
wrchar(4 + i * 2 + 1, 4 + j, ' ', 0x2F);
}
}
(void)getch();
set_videotextmode(TEXT_MODE_80x32);
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
Задача -
меняем алгоритм работы putch (и соответственно остальных ф-ий работающих через putch - cputs/cprintf и т.д.) -
вводится еще одна глобальная переменная (с сеттером и геттером) - char -
как обрабатываются управляющие символы ф-иями вывода в conio - выводятся через wrchar или отрабатываются как управляющие
если она 0 - то отрабатваются как управляющие -
это символы
0x08 - BS - уменьшаем pc_col на 1 если она еще не равна 0 (если 0 - не меняется)
0x09 - TAB - увеличиваем pc_col до ближайшего кратного 8-ми
0x0A - LF - увеличиваем pc_row на 1 кроме случая когда pc_row = 32 - тогда уже не увеличиваем
0x0D - CR - сбрасываем pc_col до 0
в остальных случаях после вывода символа увеличиваем pc_col на 1 (но не более чем до 80)
если же глобальная переменная 1 - то выводим ВСЕ символы as is через wrchar так же увеличивая pc_col на 1 (но не более чем до 80)
Замечание - если pc_col == 80 или pc_row == 32 - можем просто не выводить символ
(символы выводятся только если координаты X / Y = [0..79]/[0..31])
такой режим только если attr <= 0x00FF, в противном случае - вывод через быстрый вывод без управления координат и цветом
для ускорения предлагается создать raw putch который будет принимать в параметрах только символ и аттрибут.
этой функции уже не надо будет проверять старший байт аттрибутов (а в аттрибуты будет принимать младший байт)
этот raw putch всегда будет выводить через WRCHAR (но будет отрабатывать новый параметр - как отрабатывать управляющие сигналы)
обычный putch вначале будет проверять attr что бы понять выводить через PUTCHAR (5B) или WRCHAR (58 - raw putch).
аналогично cputs - вначале будет проверять attr что бы понять - выводить через PCHARS (5C - _cputs_pchars) или через WRCHAR (58 - raw putch)
так же перед выводом и cputs и putcg будут получать текущие координаты для вывода и сохрнять их (если вывод идет через WRCHAR)
то есть еще один пункт для оптимизации - мы должны только один раз получить кооринаты для вывода и один раз их сохранить
(если вывод через WRCHAR, если же через PUTCHAR/PCHARS - то за координаты отвечает уже сам ESTEX).
+5
View File
@@ -0,0 +1,5 @@
# Build conio_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := conio2
include $(PROJ_ROOT)/app.mk
+63
View File
@@ -0,0 +1,63 @@
#include <stdio.h>
#include <conio.h>
#include <unistd.h> /* sleep */
/*
* Exercises every conio function:
* clrscr — clear the screen
* gotoxy — move cursor to (x, y), 0-based
* putch — single character
* cputs — string without auto-newline
* kbhit — non-blocking key probe
* getch — blocking, no echo
* getche — blocking, with echo
*
* Sprinter native text mode is 80×32, so we anchor corners at
* (0,0), (79,0), (0,31), (79,31).
*/
int main(void)
{
/* 1. clrscr + diagnostic probes + a centered banner.
*
* Row-0 probe: figure out why [NW]/[NE] don't paint.
* '0','1','2','3' — single putch at row 0, cols 0/5/40/79
* "R0" — cputs at row 0, col 10
* 'a','b','c','R1'— same pattern on row 1 (control)
*/
clrscr();
gotoxy(0, 0); putch('0');
textattr(0x70);
gotoxy(1, 0); putch('1');
set_putch_raw_mode(1);
textattr(0x0F);
gotoxy(4, 3);
for (int i = 0; i < 16; i++) {
putch(i < 10 ? '0' + i : 'A' - 10 + i);
putch(' ');
}
for (int j = 0; j < 16; j++) {
gotoxy(2, 4 + j);
textattr(0x0F);
putch(j < 10 ? '0' + j : 'A' - 10 + j);
putch(' ');
for (int i = 0; i < 16; i++) {
textattr((j << 4) + i);
putch((j << 4) + i); putch(' ');
}
}
set_putch_raw_mode(0);
gotoxy(0,22);
set_text_attr(0x000E);
// cputs("Test message line");
cputs("Test message line 1\nTest message line2\rline3\n\r\n\r1234\t5678\b90");
(void)getch();
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := dec_test
include $(PROJ_ROOT)/app.mk
+39
View File
@@ -0,0 +1,39 @@
#include <stdio.h>
extern void dec8 (unsigned char);
extern void dec16(unsigned int);
extern void dec32(unsigned long);
extern void hex8 (unsigned char);
extern void hex16(unsigned int);
extern void hex32(unsigned long);
int main(void) {
puts("hex8:");
hex8(0x00); puts("");
hex8(0x5A); puts("");
hex8(0xFF); puts("");
puts("hex16:");
hex16(0x0000); puts("");
hex16(0xCAFE); puts("");
hex16(0xFFFF); puts("");
puts("hex32:");
hex32(0x00000000UL); puts("");
hex32(0xDEADBEEFUL); puts("");
hex32(0xFFFFFFFFUL); puts("");
puts("dec8:");
dec8(0); puts("");
dec8(42); puts("");
dec8(255); puts("");
puts("dec16:");
dec16(0); puts("");
dec16(1234); puts("");
dec16(65535); puts("");
puts("dec32:");
dec32(0UL); puts("");
dec32(98765UL); puts("");
dec32(123456UL); puts("");
dec32(123456789UL); puts("");
dec32(4294967295UL); puts("");
puts("done — any key");
(void)getchar();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build errno_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := errno
include $(PROJ_ROOT)/app.mk
+50
View File
@@ -0,0 +1,50 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
/*
* Exercises errno + strerror + perror by triggering each failure path.
* No file system mutations are required — every call here is expected
* to fail by design.
*/
int main(void)
{
puts("errno test:");
puts("");
/* 1. Open a file that does not exist. */
errno = 0;
int fd = open("NOSUCH.TXT", O_RDONLY);
printf(" open(\"NOSUCH.TXT\"): fd=%d errno=%d %s\n",
fd, errno, strerror(errno));
/* 2. Close a bogus file descriptor. */
errno = 0;
int r = close(0x7F);
printf(" close(0x7F): ret=%d errno=%d %s\n", r, errno, strerror(errno));
/* 3. perror() — convenience wrapper. */
errno = 0;
fd = open("ANOTHER.MIS", O_RDONLY);
perror(" open(\"ANOTHER.MIS\")");
/* 4. Delete something that isn't there. */
errno = 0;
r = unlink("PHANTOM.TMP");
perror(" unlink(\"PHANTOM.TMP\")");
/* 5. A few raw codes for the table. */
puts("");
puts(" raw codes:");
for (int i = 0; i <= 5; i++) {
printf(" %2d → %s\n", i, strerror(i));
}
printf(" %2d → %s (out of range)\n", 99, strerror(99));
puts("");
puts("Press any key to exit.");
(void)getchar();
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := filetest
include $(PROJ_ROOT)/app.mk
+74
View File
@@ -0,0 +1,74 @@
/*
* filetest — exercise minimal FILE * stream API (fopen/fclose/fputs/
* fgets/fread/fwrite/fseek/ftell/feof + stdin/stdout/stderr).
*
* Steps:
* 1. fopen("FILE.TXT","w"), fputs+fputc lines, fclose.
* 2. fopen("FILE.TXT","r"), fgets each line, fclose.
* 3. fopen("r"), fread block, fseek, ftell, feof, fread again.
* 4. fputs to stdout (sanity check console pseudo-stream).
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
const char *path = "FILE.TXT";
/* ----- 1. Write via fputs + fputc ----- */
{
FILE *fp = fopen(path, "w");
if (!fp) {
printf("fopen(w) failed: errno=%d (%s)\n", errno, strerror(errno));
return 1;
}
fputs("Hello from FILE*\n", fp);
fputs("Second line via fputs\n", fp);
for (int i = '0'; i <= '9'; i++) fputc(i, fp);
fputc('\n', fp);
if (fclose(fp) != 0) puts("fclose: error");
}
/* ----- 2. Read via fgets ----- */
{
FILE *fp = fopen(path, "r");
if (!fp) {
printf("fopen(r) failed: errno=%d\n", errno);
return 1;
}
char buf[128];
int n = 0;
while (fgets(buf, sizeof buf, fp)) {
printf(" line %d: %s", ++n, buf);
if (buf[strlen(buf)-1] != '\n') putchar('\n');
}
printf(" total lines: %d, feof=%d\n", n, feof(fp));
fclose(fp);
}
/* ----- 3. fread / fseek / ftell ----- */
{
FILE *fp = fopen(path, "r");
if (!fp) return 1;
char buf[16];
size_t got = fread(buf, 1, 16, fp);
printf(" fread(16) -> %u bytes, ftell=%ld\n",
(unsigned)got, ftell(fp));
if (fseek(fp, 0L, SEEK_END) == 0) {
printf(" file size via fseek(END)+ftell = %ld\n", ftell(fp));
}
rewind(fp);
printf(" rewind: ftell=%ld, feof=%d\n", ftell(fp), feof(fp));
fclose(fp);
}
/* ----- 4. Console pseudo-streams ----- */
fputs(" fputs to stdout works\n", stdout);
fputs(" fputs to stderr works\n", stderr);
fputc('!', stdout); fputc('\n', stdout);
puts("filetest done.");
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build cat.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := gets
include $(PROJ_ROOT)/app.mk
+19
View File
@@ -0,0 +1,19 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
char buff [256];
puts("--- gets test ---");
gets(buff);
puts("");
puts("loaded string:");
puts(buff);
puts("done");
(void)getchar();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build gfx_demo16.exe — exercises libc/gfx 640x256x16 primitives.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := gfx_d16
include $(PROJ_ROOT)/app.mk
+116
View File
@@ -0,0 +1,116 @@
/*
* gfx_demo16 — exercises the 640×256×16 (mode 0x82) primitives.
*
* Stages (press a key to advance):
* 1. 1-pixel frame via hline/vline16 — verifies edge alignment
* (odd-x and odd-(x+len) RMW paths)
* 2. Nested rectangles in cycled colours
* 3. Colour bars — 16 vertical stripes, each colour 0..15
* (palette readability test)
* 4. Diagonal star + axis-aligned cross via line16
*/
#include <stdio.h>
#include <conio.h>
#include <gfx.h>
#include <stdint.h>
static uint8_t palette[16 * 4];
static void wait_key(void)
{
__asm
ld c, #0x30
rst #0x10
__endasm;
}
static void build_palette(void)
{
/* 16-color palette: index 0 = black, 1..7 = primary ramp,
* 8..15 = mid/light variants. Order chosen so neighbouring
* indices contrast in the colour-bars test. */
static const uint8_t bgr[16][3] = {
{0x00, 0x00, 0x00}, /* 0 black */
{0x00, 0x00, 0xFF}, /* 1 red */
{0x00, 0xFF, 0x00}, /* 2 green */
{0xFF, 0x00, 0x00}, /* 3 blue */
{0x00, 0xFF, 0xFF}, /* 4 yellow */
{0xFF, 0x00, 0xFF}, /* 5 magenta */
{0xFF, 0xFF, 0x00}, /* 6 cyan */
{0xFF, 0xFF, 0xFF}, /* 7 white */
{0x40, 0x40, 0x40}, /* 8 dim grey */
{0x40, 0x40, 0xFF}, /* 9 light red */
{0x40, 0xFF, 0x40}, /* A light green */
{0xFF, 0x40, 0x40}, /* B light blue */
{0x40, 0xFF, 0xFF}, /* C light yellow */
{0xFF, 0x40, 0xFF}, /* D light magenta */
{0xFF, 0xFF, 0x40}, /* E light cyan */
{0xA0, 0xA0, 0xA0}, /* F grey */
};
for (int i = 0; i < 16; i++) {
palette[i * 4 + 0] = bgr[i][0];
palette[i * 4 + 1] = bgr[i][1];
palette[i * 4 + 2] = bgr[i][2];
palette[i * 4 + 3] = 0;
}
}
int main(void)
{
build_palette();
uint8_t prev = gfx_init(GFX_MODE_640x256x16, 0);
gfx_pal_load(0, 0, 16, palette);
/* --- Stage 1: 1-px frame at edges -------------------------------- */
gfx_clear16(8); /* dim grey */
gfx_hline16(0, 0, GFX_WIDTH_16, 7); /* white top */
gfx_hline16(0, GFX_HEIGHT_16 - 1, GFX_WIDTH_16, 7); /* white bottom */
gfx_vline16(0, 0, GFX_HEIGHT_16, 7);
gfx_vline16(GFX_WIDTH_16 - 1, 0, GFX_HEIGHT_16, 7);
/* 1-px inset purple frame — exercises odd-x edges. */
gfx_hline16(1, 1, GFX_WIDTH_16 - 2, 5);
gfx_hline16(1, GFX_HEIGHT_16 - 2, GFX_WIDTH_16 - 2, 5);
gfx_vline16(1, 2, GFX_HEIGHT_16 - 4, 5);
gfx_vline16(GFX_WIDTH_16 - 2, 2, GFX_HEIGHT_16 - 4, 5);
wait_key();
/* --- Stage 2: nested rectangles --------------------------------- */
gfx_clear16(0);
for (int i = 0; i < 16; i++)
gfx_rect16(i * 20, i * 8,
GFX_WIDTH_16 - i * 40,
GFX_HEIGHT_16 - i * 16,
(uint8_t)((i + 1) & 0x0F));
wait_key();
/* --- Stage 3: vertical color bars ------------------------------- */
gfx_clear16(0);
/* 16 bars × 40 px wide = 640 px exactly. */
for (int i = 0; i < 16; i++)
gfx_fill_rect16(i * 40, 0, 40, GFX_HEIGHT_16, (uint8_t)i);
wait_key();
/* --- Stage 4: diagonal star + cross ----------------------------- */
gfx_clear16(0);
int cx = GFX_WIDTH_16 / 2, cy = GFX_HEIGHT_16 / 2;
for (int i = 0; i < 16; i++) {
int ex = i * (GFX_WIDTH_16 - 1) / 15;
gfx_line16(cx, cy, ex, 0, 7);
gfx_line16(cx, cy, ex, GFX_HEIGHT_16 - 1, 3);
}
for (int i = 0; i < 16; i++) {
int ey = i * (GFX_HEIGHT_16 - 1) / 15;
gfx_line16(cx, cy, 0, ey, 1);
gfx_line16(cx, cy, GFX_WIDTH_16 - 1, ey, 2);
}
/* axis-aligned cross to verify hline/vline alignment at runtime. */
gfx_hline16(0, cy, GFX_WIDTH_16, 6);
gfx_vline16(cx, 0, GFX_HEIGHT_16, 6);
wait_key();
gfx_done(prev);
puts("done");
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := gfx_dbuf
include $(PROJ_ROOT)/app.mk
+120
View File
@@ -0,0 +1,120 @@
/*
* gfx_dbuf — double-buffering demo.
*
* Renders a moving rectangle by alternating between page 0 and page 1:
* - Each frame: draw to the HIDDEN page, then flip visible to it.
* - The page currently being displayed is never written to, so the
* user only sees fully-rendered frames (no half-drawn artefacts,
* no flicker from the per-frame clear).
*
* Indicators help verify the swap is actually happening:
* - A small colour swatch in the top-right alternates each frame:
* one shade when page 0 is shown, another when page 1. If the
* box motion looks smooth and the swatch flickers between the two
* shades at the animation rate, the swap is working.
*
* NOTE: each graphics screen has its OWN palette page (screen 0 →
* palette 0, screen 1 → palette 1). We load the same palette into
* both so the colours look identical regardless of which page is
* currently visible. See memory/sprinter_graphics.md.
*
* Press any key to exit.
*/
#include <stdio.h>
#include <conio.h>
#include <gfx.h>
#include <stdint.h>
static uint8_t palette[256 * 4];
#define COL_BLACK 0x00
#define COL_BG 0x20
#define COL_STRIPE 0x60
#define COL_TEXT 0xC0
#define COL_BOX 0xFF
#define COL_PAGE0 0x40
#define COL_PAGE1 0xE0
static void make_palette(void)
{
for (int i = 0; i < 256; i++) {
palette[i*4+0] = (uint8_t)i;
palette[i*4+1] = (uint8_t)i;
palette[i*4+2] = (uint8_t)i;
palette[i*4+3] = 0;
}
}
static void draw_frame(int box_x, int box_y, uint8_t page_indicator)
{
gfx_clear256(COL_BG);
/* Static decoration — identical on both pages so the swap doesn't
* flicker the chrome. */
gfx_fill_rect256(0, 0, GFX_WIDTH, 8, COL_STRIPE);
gfx_fill_rect256(0, GFX_HEIGHT - 8, GFX_WIDTH, 8, COL_STRIPE);
gfx_text256(8, 16, "double-buffering demo", COL_TEXT, COL_BG);
gfx_text256(8, GFX_HEIGHT - 24,
"press a key to exit", COL_TEXT, COL_BG);
/* Page indicator — different shade for each page so a flickering
* box here proves the swap is happening. */
gfx_fill_rect256(GFX_WIDTH - 24, 16, 12, 12,
page_indicator ? COL_PAGE1 : COL_PAGE0);
/* The animated box. */
gfx_fill_rect256(box_x, box_y, 40, 30, COL_BOX);
gfx_rect256 (box_x, box_y, 40, 30, COL_BLACK);
}
int main(void)
{
make_palette();
uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
/* Each graphics screen has its own palette page (0→pal 0, 1→pal 1).
* Load the same data into both so the visual swap is seamless. */
gfx_pal_load(0, 0, 0, palette);
gfx_pal_load(1, 0, 0, palette);
/* Clear both pages so the very first flip doesn't reveal garbage. */
gfx_set_draw_page(0);
gfx_clear256(COL_BG);
gfx_set_draw_page(1);
gfx_clear256(COL_BG);
/* Bouncing rect state. */
int box_x = 10;
int box_y = 100;
int dx = 3;
int dy = 2;
const int box_w = 40, box_h = 30;
while (!kbhit()) {
uint8_t hidden = 1 - gfx_get_visible_page();
gfx_set_draw_page(hidden);
draw_frame(box_x, box_y, hidden);
/* Wait for the next frame interrupt before flipping, so the
* page swap lands during vertical retrace and the user never
* sees a half-drawn frame. */
gfx_wait_vsync();
gfx_set_visible_page(hidden);
/* Step the box; bounce off all four walls. */
box_x += dx;
if (box_x < 0) { box_x = 0; dx = -dx; }
if (box_x + box_w > GFX_WIDTH) { box_x = GFX_WIDTH - box_w; dx = -dx; }
box_y += dy;
if (box_y < 8) { box_y = 8; dy = -dy; }
if (box_y + box_h > GFX_HEIGHT-8) { box_y = GFX_HEIGHT-8 - box_h; dy = -dy; }
}
(void)getch();
gfx_done(prev);
puts("done");
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := gfx_demo
include $(PROJ_ROOT)/app.mk
+100
View File
@@ -0,0 +1,100 @@
/*
* gfx_demo — exercises the libc/gfx primitives. Shows:
* 1. accelerator-backed gfx_clear256 / gfx_hline256 / gfx_vline256 / gfx_fill_rect256
* 2. gfx_rect256 outline, gfx_line256 diagonals (Bresenham via putpixel)
* 3. a grey-ramp palette
*
* Press a key to advance through each stage.
*/
#include <stdio.h>
#include <conio.h>
#include <gfx.h>
#include <stdint.h>
static uint8_t palette_data[256 * 4];
static void wait_key(void)
{
__asm
ld c, #0x30
rst #0x10
__endasm;
}
int main(void)
{
/* Grey ramp: (B=i, G=i, R=i, 0). */
for (int i = 0; i < 256; i++) {
palette_data[i * 4 + 0] = (uint8_t)i;
palette_data[i * 4 + 1] = (uint8_t)i;
palette_data[i * 4 + 2] = (uint8_t)i;
palette_data[i * 4 + 3] = 0;
}
uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
gfx_pal_load(0, 0, 0, palette_data);
/* --- Stage 1: orthogonal frame via hline / vline ----------------- */
gfx_clear256(0x40);
gfx_hline256(1, 1, GFX_WIDTH - 2, 0xFF);
gfx_hline256(1, GFX_HEIGHT - 2, GFX_WIDTH - 2, 0xFF);
gfx_vline256(1, 2, GFX_HEIGHT - 4, 0xFF);
gfx_vline256(GFX_WIDTH - 2, 2, GFX_HEIGHT - 4, 0xFF);
wait_key();
/* --- Stage 2: nested rectangles -------------------------------- */
gfx_clear256(0x20);
for (int i = 0; i < 16; i++)
gfx_rect256(i * 10, i * 8,
GFX_WIDTH - i * 20,
GFX_HEIGHT - i * 16,
(uint8_t)(0x40 + i * 8));
wait_key();
/* --- Stage 3: filled-rect colour bars --------------------------- */
gfx_clear256(0);
/* Tall-narrow rects (w=20, h=128) — heuristic picks vertical orient. */
for (int i = 0; i < 16; i++) {
gfx_fill_rect256(i * 20, 0, 20, 128, (uint8_t)(i * 16));
gfx_fill_rect256(i * 20 + 0, 128, 20, 128, (uint8_t)(255 - i * 16));
}
wait_key();
/* --- Stage 3b: wide-short rects + a grid of small squares -------- */
gfx_clear256(0x08);
/* Wide-short stripes (w=320, h=16) — heuristic picks horizontal. */
for (int i = 0; i < 8; i++)
gfx_fill_rect256(0, i * 32, GFX_WIDTH, 16, (uint8_t)(0x40 + i * 24));
/* 8×8 small squares grid (w=h, heuristic picks either — same cost). */
for (int row = 0; row < 4; row++)
for (int col = 0; col < 16; col++)
gfx_fill_rect256(col * 20 + 4, 256 - 80 + row * 20, 12, 12,
(uint8_t)((row * 16 + col) * 4));
wait_key();
/* --- Stage 4: diagonal lines via Bresenham ---------------------- */
gfx_clear256(0x18);
/* "Star" of lines from centre to a circle of endpoints. */
int cx = GFX_WIDTH / 2, cy = GFX_HEIGHT / 2;
for (int i = 0; i < 16; i++) {
int ex = i * (GFX_WIDTH - 1) / 15;
gfx_line256(cx, cy, ex, 0, 0xFF);
gfx_line256(cx, cy, ex, GFX_HEIGHT - 1, 0xC0);
}
for (int i = 0; i < 16; i++) {
int ey = i * (GFX_HEIGHT - 1) / 15;
gfx_line256(cx, cy, 0, ey, 0x80);
gfx_line256(cx, cy, GFX_WIDTH - 1, ey, 0x40);
}
/* Box outline using gfx_line256. */
gfx_line256(0, 0, GFX_WIDTH - 1, 0, 0xFF);
gfx_line256(0, GFX_HEIGHT - 1, GFX_WIDTH - 1, GFX_HEIGHT - 1, 0xFF);
gfx_line256(0, 0, 0, GFX_HEIGHT - 1, 0xFF);
gfx_line256(GFX_WIDTH - 1, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1, 0xFF);
wait_key();
gfx_done(prev);
puts("done");
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := gfx_mous
include $(PROJ_ROOT)/app.mk
+169
View File
@@ -0,0 +1,169 @@
/*
* gfx_mouse_test — exercises the graphics-mode mouse cursor API:
* $09 LOAD CURSOR — install a custom cursor bitmap
* $81 CHANGE VIDEO MODE — let the driver re-sync after switching modes
* $0B RETURN CURSOR — read the cursor back (may be a stub in MAME)
*
* Flow:
* 1. Init the mouse driver in text mode.
* 2. Switch to 320x256x256, notify the driver.
* 3. Build an 8x8 cursor — solid white border + transparent middle —
* and load it. Show it. Move the mouse to verify it tracks.
* 4. Press a key: query the driver's view of the cursor and dump the
* result so we can compare against what we loaded.
* 5. Hide cursor, return to text mode, print the round-trip dump.
*
* The driver's bitmap format is undocumented — best guess is one byte
* per pixel (palette index, with 0 meaning transparent). We load 0xFF
* for opaque cells and 0 for transparent so the cursor stands out
* against any background.
*/
#include <stdio.h>
#include <conio.h>
#include <mouse.h>
#include <gfx.h>
#include <stdint.h>
#define CURSOR_W 12
#define CURSOR_H 12
#define CURSOR_BUF_BYTES (CURSOR_W * CURSOR_H)
/* Cursor format (verified empirically 2026-05-31):
* ONE BYTE per pixel — row-major, width*height bytes total.
* 0xFF = transparent (background shows through)
* any other byte = palette index (drawn opaque)
*
* Cursor bitmap lives in a dedicated video bank, not the 0x50 page used
* by gfx_clear256 / gfx_putpixel256 — that's why 0xFF reads as transparent
* even though in the main visible page 0xFF is a regular colour.
*/
static uint8_t cursor_bitmap[CURSOR_BUF_BYTES];
static uint8_t roundtrip_buf[CURSOR_BUF_BYTES];
static uint8_t palette[256 * 4];
/* Arrow shape, 1 byte per pixel. Each cell is either:
* _ transparent (0xFF, lets the background through)
* O black solid pixel (0x00)
* W white solid pixel (0xFF would mean transparent, so use 0xFF
* palette entry by hand if you want a white pixel — for the
* default greyscale palette in this demo, W = bright grey 0xE0)
*
* Feel free to edit the 12×12 grid below to draw a nicer cursor. */
#define _ 0xFF
#define O 0x00
#define W 0xE0
static const uint8_t cursor_arrow[CURSOR_BUF_BYTES] = {
O,_,_,_,_,_,_,_,_,_,_,_,
O,O,_,_,_,_,_,_,_,_,_,_,
O,W,O,_,_,_,_,_,_,_,_,_,
O,W,W,O,_,_,_,_,_,_,_,_,
O,W,W,W,O,_,_,_,_,_,_,_,
O,W,W,W,W,O,_,_,_,_,_,_,
O,W,W,W,W,W,O,_,_,_,_,_,
O,W,W,W,O,O,O,O,_,_,_,_,
O,O,O,W,O,_,_,_,_,_,_,_,
O,_,_,O,W,O,_,_,_,_,_,_,
_,_,_,O,W,O,_,_,_,_,_,_,
_,_,_,_,O,O,_,_,_,_,_,_,
};
#undef _
#undef O
#undef W
static void make_palette(void)
{
for (int i = 0; i < 256; i++) {
palette[i*4+0] = (uint8_t)i;
palette[i*4+1] = (uint8_t)i;
palette[i*4+2] = (uint8_t)i;
palette[i*4+3] = 0;
}
}
/* Copy the arrow pattern into our scratch (one place for the driver
* to point IX at). */
static void build_cursor(void)
{
for (int i = 0; i < CURSOR_BUF_BYTES; i++)
cursor_bitmap[i] = cursor_arrow[i];
}
static void wait_key(void)
{
while (!kbhit()) { /* spin */ }
(void)getch();
}
int main(void)
{
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
clrscr();
cputs("gfx_mouse_test\r\n");
if (mouse_init() < 0) {
cputs("mouse_init failed - no driver\r\n");
return 1;
}
mouse_set_sensitivity(2, 2);
/* --- enter graphics, load custom cursor, then show -------------- */
make_palette();
build_cursor();
uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
gfx_pal_load(0, 0, 0, palette);
gfx_clear256(0x40); /* dim grey background */
/* Coordinate grid every 32 px so the cursor position reads easily. */
for (int x = 0; x < GFX_WIDTH; x += 32) gfx_vline256(x, 0, GFX_HEIGHT, 0x80);
for (int y = 0; y < GFX_HEIGHT; y += 32) gfx_hline256(0, y, GFX_WIDTH, 0x80);
mouse_video_mode_changed(GFX_MODE_320x256x256);
mouse_bounds_x(0, GFX_WIDTH - 1);
mouse_bounds_y(0, GFX_HEIGHT - 1);
mouse_cursor_t custom = {
.image = cursor_bitmap,
.width = CURSOR_W,
.height = CURSOR_H,
.hot_x = 0,
.hot_y = 0,
};
mouse_load_cursor(&custom);
mouse_show();
wait_key();
/* --- query driver to see what it has now ------------------------ */
mouse_cursor_t readback = {
.image = roundtrip_buf,
.width = 0, .height = 0, .hot_x = 0, .hot_y = 0,
};
mouse_get_cursor(&readback);
mouse_hide();
gfx_done(prev);
mouse_video_mode_changed(prev); /* tell driver we're back */
/* --- back in text mode: report what the driver returned --------- */
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
clrscr();
cprintf("loaded : %ux%u hot (%u,%u)\r\n",
CURSOR_W, CURSOR_H, 0, 0);
cprintf("read back: %ux%u hot (%u,%u)\r\n",
readback.width, readback.height, readback.hot_x, readback.hot_y);
uint16_t n = (uint16_t)readback.width * (uint16_t)readback.height;
if (n > CURSOR_BUF_BYTES) n = CURSOR_BUF_BYTES;
cprintf("bitmap (%u bytes):\r\n", n);
for (uint16_t i = 0; i < n; i++) {
cprintf("%02X ", roundtrip_buf[i]);
if ((i % readback.width) == readback.width - 1) cputs("\r\n");
}
cputs("\r\n");
cputs("press any key to exit");
wait_key();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build gfx_text_demo.exe — bitmap-font text in both graphics modes.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := gfx_text
include $(PROJ_ROOT)/app.mk
+113
View File
@@ -0,0 +1,113 @@
/*
* gfx_text_demo — bitmap-font text rendering test.
*
* Stages (press a key to advance):
* 1. 320×256×256 mode — text in multiple colors using BIOS default font.
* 2. 640×256×16 mode — same text with the 16-color palette.
* Verifies the same font renders correctly in both pixel formats.
*/
#include <stdio.h>
#include <conio.h>
#include <gfx.h>
#include <stdint.h>
static uint8_t pal256[256 * 4];
static uint8_t pal16[16 * 4];
static void wait_key(void)
{
__asm
ld c, #0x30
rst #0x10
__endasm;
}
int main(void)
{
/* Grey ramp for 256-color mode. */
for (int i = 0; i < 256; i++) {
pal256[i * 4 + 0] = (uint8_t)i;
pal256[i * 4 + 1] = (uint8_t)i;
pal256[i * 4 + 2] = (uint8_t)i;
pal256[i * 4 + 3] = 0;
}
/* Simple 16-color palette: 0=black, 1=red, 2=green, ..., 7=white,
* 8..15 = dimmed variants. */
static const uint8_t bgr16[16][3] = {
{0x00,0x00,0x00}, {0x00,0x00,0xFF}, {0x00,0xFF,0x00}, {0xFF,0x00,0x00},
{0x00,0xFF,0xFF}, {0xFF,0x00,0xFF}, {0xFF,0xFF,0x00}, {0xFF,0xFF,0xFF},
{0x40,0x40,0x40}, {0x40,0x40,0xFF}, {0x40,0xFF,0x40}, {0xFF,0x40,0x40},
{0x40,0xFF,0xFF}, {0xFF,0x40,0xFF}, {0xFF,0xFF,0x40}, {0xA0,0xA0,0xA0},
};
for (int i = 0; i < 16; i++) {
pal16[i*4+0] = bgr16[i][0];
pal16[i*4+1] = bgr16[i][1];
pal16[i*4+2] = bgr16[i][2];
pal16[i*4+3] = 0;
}
/* --- Stage 1: text in 320×256×256 ----------------------------- */
uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
gfx_pal_load(0, 0, 0, pal256);
gfx_clear256(0x20);
gfx_text256(8, 8, "Hello from Sprinter!", 0xFF, 0x20);
gfx_text256(8, 24, "320x256x256 mode", 0xC0, 0x20);
gfx_text256(8, 40, "Bitmap font from BIOS WIN_GET_ZG", 0x80, 0x20);
/* Color showcase — same string in 8 different greys. */
for (int i = 0; i < 8; i++) {
char buf[16] = "Color ramp test";
gfx_text256(8, 64 + i * 12, buf, (uint8_t)(0x40 + i * 24), 0x20);
}
/* Adjacent FG/BG variants. */
gfx_text256(8, 176, "FG=white BG=red", 0xFF, 0x30);
gfx_text256(8, 192, "FG=black BG=white", 0x00, 0xFF);
gfx_text256(8, 208, "Negative space:", 0xFF, 0x20);
/* Large block to test grid-aligned text. */
for (int row = 0; row < 3; row++)
for (int col = 0; col < 8; col++) {
char ch[2] = { (char)('A' + row * 8 + col), 0 };
gfx_text256(176 + col * 16, 176 + row * 16, ch, 0xFF, 0x20);
}
wait_key();
/* --- Stage 2: text in 640×256×16 ------------------------------ */
gfx_done(prev);
prev = gfx_init(GFX_MODE_640x256x16, 0);
gfx_pal_load(0, 0, 16, pal16);
gfx_clear16(0);
gfx_text16(8, 8, "Hello from Sprinter!", 7, 0);
gfx_text16(8, 24, "640x256x16 mode (16 colours)", 6, 0);
gfx_text16(8, 40, "Same font, packed two pixels/byte", 4, 0);
/* Color demo: each line in a different palette index. */
for (int i = 1; i < 16; i++) {
char buf[20];
/* Simple manual itoa to avoid stdio bloat. */
buf[0] = 'C'; buf[1] = 'o'; buf[2] = 'l'; buf[3] = 'o'; buf[4] = 'r';
buf[5] = ' '; buf[6] = (char)('0' + (i / 10));
buf[7] = (char)('0' + (i % 10));
buf[8] = 0;
gfx_text16(8, 64 + (i - 1) * 12, buf, (uint8_t)i, 0);
}
/* Show on right side — paragraph in white-on-black, then inverted. */
gfx_text16(280, 64, "ABCDEFGHIJKLMNOP", 7, 0);
gfx_text16(280, 76, "QRSTUVWXYZ", 7, 0);
gfx_text16(280, 92, "abcdefghijklmnop", 7, 0);
gfx_text16(280, 104, "qrstuvwxyz", 7, 0);
gfx_text16(280, 120, "0123456789", 7, 0);
gfx_text16(280, 132, "!@#$%^&*()_+-=", 7, 0);
gfx_text16(280, 148, "Inverted text", 0, 7);
gfx_text16(280, 164, "FG=red BG=cyan", 1, 6);
wait_key();
gfx_done(prev);
puts("done");
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build hello.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := hello
include $(PROJ_ROOT)/app.mk
+65
View File
@@ -0,0 +1,65 @@
/*
* hello — smoke test for the two output APIs:
*
* stdio (printf/puts/putchar) — FAST, no attribute (ambient colour)
* conio (cprintf/cputs/putch) — SLOWER, applies textcolor/textbackground
*
* Demonstrates textcolor/textbackground (Turbo-C-compatible names).
*/
#include <stdio.h>
#include <conio.h>
#include <gfx.h>
#include <sprinter.h>
#include <sprinter_exit.h>
#include <errno.h>
int main(void)
{
errno = -1;
int16_t a0 = 0, a1 = 0;
a0 = get_text_attr();
uint8_t vMode = get_videotextmode();
set_videotextmode(TEXT_MODE_80x32);
/* Wipe the screen with a known attribute so stdio printf/puts inherit
* a clean colour for the cursor. */
clrscr_attr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
/* --- stdio set: fast, no attribute ------------------------------- */
puts("hello (stdio) - fast PCHARS, ambient colour");
printf("printf: a0=%d (initial attr)\n", a0);
/* --- conio set: applies textcolor / textbackground --------------- */
textcolor(COLOR_YELLOW);
textbackground(COLOR_BLUE);
cputs("conio: yellow on blue\r\n");
textcolor(COLOR_LIGHTRED);
textbackground(COLOR_BLACK);
cprintf("cprintf %d %d %s\r\n", 42, -7, "args");
/* set_text_attr / textattr replace the whole byte. */
textattr(COLOR(COLOR_LIGHTGREEN, COLOR_BLACK));
cputs("conio: light-green via textattr\r\n");
/* Opting out of attribute control — conio falls back to fast path. */
set_text_attr(KEEP_EXIST_ATTR);
cputs("conio with KEEP_EXIST_ATTR (fast path)\r\n");
a1 = get_text_attr();
/* Back to a normal attribute so the goodbye reads cleanly. */
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
printf("a0=%d a1=%d now=%d errno=%d\n",
a0, a1, get_text_attr(), errno);
#ifdef DEBUG_RT
printf("w2_self_allocated = %u\n", w2_self_allocated);
#endif
cputs("Press any key to exit...");
(void)getchar();
set_videotextmode(vMode);
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build ls.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := ls
include $(PROJ_ROOT)/app.mk
+96
View File
@@ -0,0 +1,96 @@
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <dir.h>
#include <errno.h>
/*
* ls — list files on the current drive that match the given pattern.
*
* LS -> "*.*" (everything in current dir)
* LS *.TXT -> just .TXT files
* LS C: -> auto-rewritten to "C:*.*"
* LS C:\BIN -> "C:\BIN\*.*"
* LS C:\BIN\ -> "C:\BIN\*.*"
* LS /A -> include hidden / system / label entries
*
* ESTEX F_FIRST itself returns errno 16 (EINAME) when given a bare path
* with no wildcard, so we patch the pattern up before calling it.
*/
/*
* Sprinter ESTEX F_FIRST refuses bare path components — it needs a real
* wildcard. We do the minimum that DOS-style shells do for the user:
* - "C:" → "C:\*.*" (drive without slash)
* - "C:\" → "C:\*.*" (root-like, just append the wildcard)
* - anything else: pass through. A more correct implementation would
* stat the path and decide between "single file" / "directory" — out
* of scope for this example.
*/
static char *normalize_pattern(const char *src, char *dst, int cap)
{
int len = (int)strlen(src);
if (len == 0) {
strcpy(dst, "*.*");
return dst;
}
char last = src[len - 1];
const char *suffix = NULL;
if (last == ':') suffix = "\\*.*";
else if (last == '\\' || last == '/') suffix = "*.*";
if (suffix && len + (int)strlen(suffix) + 1 <= cap) {
strcpy(dst, src);
strcat(dst, suffix);
} else {
strcpy(dst, src);
}
return dst;
}
int main(int argc, char **argv)
{
const char *pattern_in = "*.*";
uint8_t attr = FA_NORMAL | FA_DIREC | FA_RDONLY | FA_ARCH;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '/' && (argv[i][1] | 0x20) == 'a') {
attr |= FA_HIDDEN | FA_SYSTEM | FA_LABEL;
} else {
pattern_in = argv[i];
}
}
char pattern[80];
normalize_pattern(pattern_in, pattern, sizeof(pattern));
printf("ls: pattern=\"%s\" attr=0x%02X\n\n", pattern, attr);
ffblk_t blk;
int r = ffirst(pattern, &blk, attr);
if (r < 0) {
printf("no match (errno=%d %s)\n", errno, strerror(errno));
cputs("\nPress any key to exit.\n");
(void)getch();
return 1;
}
int count = 0;
do {
const char *kind;
if (blk.found_attr & FA_DIREC) kind = "<DIR>";
else if (blk.found_attr & FA_LABEL) kind = "<VOL>";
else if (blk.found_attr & FA_SYSTEM) kind = "[SYS]";
else if (blk.found_attr & FA_HIDDEN) kind = "[HID]";
else kind = " ";
printf(" %s %-14s %8lu\n", kind, blk.found_name, blk.size);
count++;
} while (fnext(&blk) == 0);
printf("\n%d entries\n\n", count);
cputs("Press any key to exit.\n");
(void)getch();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build malloc_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := malloc
include $(PROJ_ROOT)/app.mk
+63
View File
@@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Exercises SDCC's malloc / free. The library pulls in heap.rel + malloc.rel
* from z80.lib automatically and inits the heap from crt0's _GSINIT chain.
* Default heap size is 1023 bytes — see docs/TODO.md for plans to grow it.
*/
int main(void)
{
puts("malloc test:");
/* small allocations */
char *a = (char *)malloc(20);
char *b = (char *)malloc(40);
char *c = (char *)malloc(60);
printf(" a = %p\n", a);
printf(" b = %p\n", b);
printf(" c = %p\n", c);
if (a && b && c) {
strcpy(a, "first");
strcpy(b, "second-medium-length");
strcpy(c, "third-and-the-longest-of-them-all");
printf(" a: \"%s\"\n", a);
printf(" b: \"%s\"\n", b);
printf(" c: \"%s\"\n", c);
} else {
puts(" one of the allocations FAILED");
}
/* free b, alloc smaller — should fit in the b-shaped hole */
free(b);
char *d = (char *)malloc(15);
printf(" after free(b), d = %p (expected near b)\n", d);
if (d) {
strcpy(d, "reused");
printf(" d: \"%s\"\n", d);
}
/* drain a larger allocation to see when malloc actually says no */
int total = 0;
int count = 0;
for (;;) {
void *p = malloc(64);
if (!p) break;
total += 64;
count++;
}
printf(" alloc'd %d x 64-byte blocks before failure (total %d bytes)\n",
count, total);
free(a);
free(c);
free(d);
puts("");
puts("Press any key to exit.");
(void)getchar();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build mem_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := mem_test
include $(PROJ_ROOT)/app.mk
+87
View File
@@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sprinter.h>
#include <sprinter_mem.h>
/*
* Exercises the ESTEX EMM page allocator + bank_read/bank_write helpers.
*
* Plan:
* 1. Show free-page count via mem_info.
* 2. Allocate 3 pages → block id.
* 3. For each page in the block, write a recognizable pattern via
* bank_write, then read it back via bank_read into a near buffer.
* 4. Cross-check the readback to prove pages are independent.
* 5. Free the block, show the free-page count again.
*/
static void show_mem(const char *label)
{
uint16_t total, free_pages;
mem_info(&total, &free_pages);
printf(" %s total=%u free=%u (each page = 16 KB)\n",
label, total, free_pages);
}
int main(void)
{
puts("Sprinter page allocator demo");
puts("");
show_mem("before:");
uint8_t blk = mem_alloc_pages(3);
if (blk == 0) {
puts(" mem_alloc_pages(3) failed");
(void)getchar();
return 1;
}
printf(" allocated block id = %u (3 pages)\n", blk);
show_mem("after alloc:");
/* Show the physical page numbers we got. */
for (uint8_t i = 0; i < 3; i++) {
uint8_t phys = mem_get_page(blk, i);
printf(" page %u of block = phys 0x%02X\n", i, phys);
}
/* Write a 32-byte pattern at offset 0 of each page; pattern depends
* on page index so we can distinguish them. */
char buf[33];
for (uint8_t i = 0; i < 3; i++) {
uint8_t phys = mem_get_page(blk, i);
for (int j = 0; j < 32; j++) {
buf[j] = 'A' + (char)i; /* page 0 -> 'A', page 1 -> 'B', page 2 -> 'C' */
}
buf[32] = 0;
bank_write(phys, 0, buf, 32);
printf(" wrote 32 x '%c' to page %u (phys 0x%02X)\n",
'A' + i, i, phys);
}
/* Read back and verify each page has its own pattern. */
puts("");
puts("readback:");
for (uint8_t i = 0; i < 3; i++) {
uint8_t phys = mem_get_page(blk, i);
memset(buf, 0, sizeof(buf));
bank_read(phys, 0, buf, 32);
buf[32] = 0;
printf(" page %u (phys 0x%02X) first 32 bytes: \"%s\"\n",
i, phys, buf);
}
/* Single-byte API spot check. */
bank_store_byte(mem_get_page(blk, 1), 100, 0x42);
uint8_t got = bank_load_byte(mem_get_page(blk, 1), 100);
printf("\n store/load single byte at page1[100]: 0x%02X (expect 0x42)\n", got);
mem_free_block(blk);
show_mem("after free:");
puts("");
puts("Press any key to exit.");
(void)getchar();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build mouse_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := mouse
include $(PROJ_ROOT)/app.mk
+80
View File
@@ -0,0 +1,80 @@
/*
* mouse_test — exercises the libc/io/mouse driver wrappers.
*
* Loop: shows live cursor state (pixel + char coordinates + buttons)
* and the current sensitivity values. Press +/- to change horizontal
* sensitivity, [/] to change vertical. ESC quits.
*/
#include <stdio.h>
#include <conio.h>
#include <mouse.h>
int main(void)
{
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
clrscr();
cputs("Mouse test - move mouse and click.\r\n"
" 1 / 2 : decrease / increase horizontal sensitivity\r\n"
" 3 / 4 : decrease / increase vertical sensitivity\r\n"
" ESC : exit\r\n");
if (mouse_init() < 0) {
cputs("mouse_init failed - no driver installed\r\n");
return 1;
}
/* Text mode 03h: 80 chars * 8 = 640 px wide, 32 * 8 = 256 px tall. */
mouse_bounds_x(0, 639);
mouse_bounds_y(0, 255);
mouse_show();
mouse_state_t st;
int last_x = -1, last_y = -1;
uint8_t last_btn = 0xFF;
/* Sensitivity is a "raw steps per cursor pixel" divider: smaller =
* faster cursor. Force a known starting value so the display
* matches what's active in the driver even when GET returns 0
* (some drivers / MAME stub). */
uint8_t sens_x = 2;
uint8_t sens_y = 2;
mouse_set_sensitivity(sens_x, sens_y);
int sens_dirty = 1;
while (1) {
mouse_read(&st);
if (st.x != last_x || st.y != last_y || st.buttons != last_btn) {
gotoxy(0, 6);
cprintf("x=%4u y=%4u text(%2u,%2u) buttons=0x%02X L%c R%c ",
st.x, st.y,
st.x / 8, st.y / 8,
st.buttons,
(st.buttons & 1) ? '*' : '.',
(st.buttons & 2) ? '*' : '.');
last_x = st.x;
last_y = st.y;
last_btn = st.buttons;
}
if (sens_dirty) {
gotoxy(0, 8);
cprintf("sensitivity horz=%3u vert=%3u ", sens_x, sens_y);
sens_dirty = 0;
}
if (!kbhit()) continue;
int k = getch();
if (k == 27) break; /* ESC */
if (k == '1' && sens_x > 1) { sens_x -= 1; sens_dirty = 1; }
if (k == '2' && sens_x < 254) { sens_x += 1; sens_dirty = 1; }
if (k == '3' && sens_y > 1) { sens_y -= 1; sens_dirty = 1; }
if (k == '4' && sens_y < 254) { sens_y += 1; sens_dirty = 1; }
if (sens_dirty)
mouse_set_sensitivity(sens_x, sens_y);
}
mouse_hide();
gotoxy(0, 10);
cputs("press any key to exit");
(void)getch();
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
# Build open_env_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := openenv
MEMORY := big
EXTRA_FLAGS :=
include $(PROJ_ROOT)/app.mk
+153
View File
@@ -0,0 +1,153 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sprinter.h>
/*
* Exercises the new open() state machine + ESTEX env API.
*
* Touches the floppy: creates TMP1.TXT and TMP2.TXT, writes a few bytes,
* verifies O_CREAT / O_EXCL / O_TRUNC / O_APPEND behaviour, then deletes.
*/
extern uint8_t estex_file_handle;
static void show_errno(const char *label)
{
printf(" %s: errno=%d \"%s\"\n", label, errno, strerror(errno));
}
int main(void)
{
puts("Sprinter open() + env API test");
puts("");
printf("estex_file_handle: fd=%u\n", estex_file_handle);
/* --- open() state machine ------------------------------------- */
/* 1. O_CREAT|O_EXCL: must succeed first time, must fail on retry. */
unlink("TMP1.TXT"); /* clean slate */
errno = 0;
int fd = open("TMP1.TXT", O_WRONLY | O_CREAT | O_EXCL);
printf("create-new TMP1.TXT (1st): fd=%d\n", fd);
show_errno(" after 1st");
if (fd >= 0) {
write(fd, "abcdef", 6);
close(fd);
}
errno = 0;
fd = open("TMP1.TXT", O_WRONLY | O_CREAT | O_EXCL);
printf("create-new TMP1.TXT (2nd, should fail with EEXIST): fd=%d\n", fd);
show_errno(" after 2nd");
/* 2. O_CREAT|O_TRUNC: file is reset. */
errno = 0;
fd = open("TMP1.TXT", O_WRONLY | O_CREAT | O_TRUNC);
printf("create-trunc TMP1.TXT: fd=%d\n", fd);
if (fd >= 0) {
write(fd, "XYZ", 3);
close(fd);
}
/* Read back to confirm truncation overwrote "abcdef". */
char buf[16];
fd = open("TMP1.TXT", O_RDONLY);
int n = read(fd, buf, sizeof(buf) - 1);
if (n < 0) n = 0;
buf[n] = 0;
close(fd);
printf("contents after trunc+write: \"%s\" (expect \"XYZ\")\n", buf);
/* 3. O_APPEND: writes go to end. */
fd = open("TMP1.TXT", O_WRONLY | O_APPEND);
if (fd >= 0) {
write(fd, "+APP", 4);
close(fd);
}
fd = open("TMP1.TXT", O_RDONLY);
n = read(fd, buf, sizeof(buf) - 1);
if (n < 0) n = 0;
buf[n] = 0;
close(fd);
printf("contents after append: \"%s\" (expect \"XYZ+APP\")\n", buf);
/* 4. O_CREAT alone (no EXCL/TRUNC): existing file opens, new file is
* created. We open TMP1 (must succeed without truncating) then
* TMP2 (must be created fresh). */
fd = open("TMP1.TXT", O_RDONLY | O_CREAT);
n = read(fd, buf, sizeof(buf) - 1);
if (n < 0) n = 0;
buf[n] = 0;
close(fd);
printf("O_CREAT on existing TMP1: \"%s\" (expect \"XYZ+APP\")\n", buf);
unlink("TMP2.TXT");
fd = open("TMP2.TXT", O_WRONLY | O_CREAT);
printf("O_CREAT on missing TMP2: fd=%d\n", fd);
if (fd >= 0) {
write(fd, "fresh", 5);
close(fd);
}
/* cleanup */
unlink("TMP1.TXT");
unlink("TMP2.TXT");
/* --- env API -------------------------------------------------- */
puts("");
puts("env API:");
errno = 0;
char *v = getenv("PATH");
printf(" getenv(\"PATH\") = %p", v);
if (v) {
printf(" -> \"%s\"", v);
} else {
printf(" (NULL, errno=%d)", errno);
}
putchar('\n');
errno = 0;
int rc = putenv("SPRINTER_HELLO=world");
printf(" putenv(\"SPRINTER_HELLO=world\"): rc=%d\n", rc);
if (rc != 0) show_errno(" after putenv");
errno = 0;
v = getenv("SPRINTER_HELLO");
printf(" getenv(\"SPRINTER_HELLO\") = %p", v);
if (v) {
printf(" -> \"%s\"", v);
} else {
printf(" (NULL, errno=%d)", errno);
}
putchar('\n');
/* --- sysenv: dump the whole environment block ----------------- */
puts("");
puts("sysenv:");
{
static char envbuf[512];
errno = 0;
char *r = sysenv(envbuf);
if (r == (char *)-1) {
show_errno(" sysenv failed");
} else {
printf(" sysenv(%p) returned %p\n", envbuf, r);
int n = 0;
for (char *p = r; *p; p += strlen(p) + 1) {
printf(" [%d] %s\n", n++, p);
}
printf(" total: %d variable(s)\n", n);
}
}
puts("");
puts("Press any key to exit.");
(void)getchar();
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := ptime
include $(PROJ_ROOT)/app.mk
+44
View File
@@ -0,0 +1,44 @@
/*
* ptime — exercise POSIX <time.h>. All wired through SDCC's z80.lib
* time.rel which calls our RtcRead() (bridged to ESTEX SYSTIME).
*/
#include <stdio.h>
#include <time.h>
int main(void)
{
/* time() returns seconds since 1970-01-01 (Unix epoch). */
time_t now;
time(&now);
printf("time() = %lu epoch seconds\n", now);
/* localtime() decomposes into struct tm. */
struct tm *lt = localtime(&now);
printf("localtime() = %04d-%02d-%02d %02d:%02d:%02d (wday=%u)\n",
lt->tm_year + 1900,
lt->tm_mon + 1,
lt->tm_mday,
lt->tm_hour,
lt->tm_min,
lt->tm_sec,
(unsigned)lt->tm_wday);
/* asctime() formats it as a 25-char string. */
printf("asctime() = %s", asctime(lt)); /* asctime adds \n */
/* mktime() round-trip — should recover the same epoch. */
time_t round = mktime(lt);
printf("mktime() = %lu (round-trip %s original)\n",
round, (round == now ? "==" : "!="));
/* Native datetime_t API still works alongside. */
datetime_t dt;
getdatetime(&dt);
printf("native = %04u-%02u-%02u %02u:%02u:%02u (dow=%u)\n",
dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
(unsigned)dt.dow);
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build rt_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := rt_test
include $(PROJ_ROOT)/app.mk
+63
View File
@@ -0,0 +1,63 @@
#include <stdio.h>
#include <unistd.h>
#include <setjmp.h>
#include <sprinter_exit.h>
static void bye1(void) { puts("[atexit] bye1 (registered first, runs last)"); }
static void bye2(void) { puts("[atexit] bye2 (registered second)"); }
static void bye3(void) { puts("[atexit] bye3 (registered third, runs first)"); }
static jmp_buf env;
static int attempt;
static void might_fail(int n)
{
printf(" might_fail(%d) running...\n", n);
if (n == 2) {
puts(" -> longjmp(env, 42)");
longjmp(env, 42);
/* not reached */
}
printf(" might_fail(%d) returned normally\n", n);
}
int main(void)
{
puts("Sprinter runtime features test:");
puts("");
/* --- atexit registration --- */
atexit(bye1);
atexit(bye2);
atexit(bye3);
/* --- setjmp / longjmp --- */
puts("setjmp/longjmp:");
int r = setjmp(env);
if (r == 0) {
attempt = 1;
puts(" first arrival from setjmp (r=0)");
might_fail(attempt);
attempt = 2;
might_fail(attempt);
puts(" -- this line is NOT reached");
} else {
printf(" resumed via longjmp, setjmp returned %d (attempt=%d)\n",
r, attempt);
}
/* --- sleep --- */
puts("");
puts("sleep(5): pausing 5 seconds...");
sleep(5);
puts(" done.");
puts("");
puts("Press any key, atexit chain will run after.");
(void)getchar();
/* Use exit() to drive the atexit chain (vs returning from main, which
* doesn't necessarily go through exit() under SDCC). */
exit(0);
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
# Build seek_demo.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := seek
EXTRA_DATA := big.txt
include $(PROJ_ROOT)/app.mk
+400
View File
@@ -0,0 +1,400 @@
[off=0000000] block #0000 .....................................................................................................................................................................................................................................
[off=0000256] block #0001 .....................................................................................................................................................................................................................................
[off=0000512] block #0002 .....................................................................................................................................................................................................................................
[off=0000768] block #0003 .....................................................................................................................................................................................................................................
[off=0001024] block #0004 .....................................................................................................................................................................................................................................
[off=0001280] block #0005 .....................................................................................................................................................................................................................................
[off=0001536] block #0006 .....................................................................................................................................................................................................................................
[off=0001792] block #0007 .....................................................................................................................................................................................................................................
[off=0002048] block #0008 .....................................................................................................................................................................................................................................
[off=0002304] block #0009 .....................................................................................................................................................................................................................................
[off=0002560] block #0010 .....................................................................................................................................................................................................................................
[off=0002816] block #0011 .....................................................................................................................................................................................................................................
[off=0003072] block #0012 .....................................................................................................................................................................................................................................
[off=0003328] block #0013 .....................................................................................................................................................................................................................................
[off=0003584] block #0014 .....................................................................................................................................................................................................................................
[off=0003840] block #0015 .....................................................................................................................................................................................................................................
[off=0004096] block #0016 .....................................................................................................................................................................................................................................
[off=0004352] block #0017 .....................................................................................................................................................................................................................................
[off=0004608] block #0018 .....................................................................................................................................................................................................................................
[off=0004864] block #0019 .....................................................................................................................................................................................................................................
[off=0005120] block #0020 .....................................................................................................................................................................................................................................
[off=0005376] block #0021 .....................................................................................................................................................................................................................................
[off=0005632] block #0022 .....................................................................................................................................................................................................................................
[off=0005888] block #0023 .....................................................................................................................................................................................................................................
[off=0006144] block #0024 .....................................................................................................................................................................................................................................
[off=0006400] block #0025 .....................................................................................................................................................................................................................................
[off=0006656] block #0026 .....................................................................................................................................................................................................................................
[off=0006912] block #0027 .....................................................................................................................................................................................................................................
[off=0007168] block #0028 .....................................................................................................................................................................................................................................
[off=0007424] block #0029 .....................................................................................................................................................................................................................................
[off=0007680] block #0030 .....................................................................................................................................................................................................................................
[off=0007936] block #0031 .....................................................................................................................................................................................................................................
[off=0008192] block #0032 .....................................................................................................................................................................................................................................
[off=0008448] block #0033 .....................................................................................................................................................................................................................................
[off=0008704] block #0034 .....................................................................................................................................................................................................................................
[off=0008960] block #0035 .....................................................................................................................................................................................................................................
[off=0009216] block #0036 .....................................................................................................................................................................................................................................
[off=0009472] block #0037 .....................................................................................................................................................................................................................................
[off=0009728] block #0038 .....................................................................................................................................................................................................................................
[off=0009984] block #0039 .....................................................................................................................................................................................................................................
[off=0010240] block #0040 .....................................................................................................................................................................................................................................
[off=0010496] block #0041 .....................................................................................................................................................................................................................................
[off=0010752] block #0042 .....................................................................................................................................................................................................................................
[off=0011008] block #0043 .....................................................................................................................................................................................................................................
[off=0011264] block #0044 .....................................................................................................................................................................................................................................
[off=0011520] block #0045 .....................................................................................................................................................................................................................................
[off=0011776] block #0046 .....................................................................................................................................................................................................................................
[off=0012032] block #0047 .....................................................................................................................................................................................................................................
[off=0012288] block #0048 .....................................................................................................................................................................................................................................
[off=0012544] block #0049 .....................................................................................................................................................................................................................................
[off=0012800] block #0050 .....................................................................................................................................................................................................................................
[off=0013056] block #0051 .....................................................................................................................................................................................................................................
[off=0013312] block #0052 .....................................................................................................................................................................................................................................
[off=0013568] block #0053 .....................................................................................................................................................................................................................................
[off=0013824] block #0054 .....................................................................................................................................................................................................................................
[off=0014080] block #0055 .....................................................................................................................................................................................................................................
[off=0014336] block #0056 .....................................................................................................................................................................................................................................
[off=0014592] block #0057 .....................................................................................................................................................................................................................................
[off=0014848] block #0058 .....................................................................................................................................................................................................................................
[off=0015104] block #0059 .....................................................................................................................................................................................................................................
[off=0015360] block #0060 .....................................................................................................................................................................................................................................
[off=0015616] block #0061 .....................................................................................................................................................................................................................................
[off=0015872] block #0062 .....................................................................................................................................................................................................................................
[off=0016128] block #0063 .....................................................................................................................................................................................................................................
[off=0016384] block #0064 .....................................................................................................................................................................................................................................
[off=0016640] block #0065 .....................................................................................................................................................................................................................................
[off=0016896] block #0066 .....................................................................................................................................................................................................................................
[off=0017152] block #0067 .....................................................................................................................................................................................................................................
[off=0017408] block #0068 .....................................................................................................................................................................................................................................
[off=0017664] block #0069 .....................................................................................................................................................................................................................................
[off=0017920] block #0070 .....................................................................................................................................................................................................................................
[off=0018176] block #0071 .....................................................................................................................................................................................................................................
[off=0018432] block #0072 .....................................................................................................................................................................................................................................
[off=0018688] block #0073 .....................................................................................................................................................................................................................................
[off=0018944] block #0074 .....................................................................................................................................................................................................................................
[off=0019200] block #0075 .....................................................................................................................................................................................................................................
[off=0019456] block #0076 .....................................................................................................................................................................................................................................
[off=0019712] block #0077 .....................................................................................................................................................................................................................................
[off=0019968] block #0078 .....................................................................................................................................................................................................................................
[off=0020224] block #0079 .....................................................................................................................................................................................................................................
[off=0020480] block #0080 .....................................................................................................................................................................................................................................
[off=0020736] block #0081 .....................................................................................................................................................................................................................................
[off=0020992] block #0082 .....................................................................................................................................................................................................................................
[off=0021248] block #0083 .....................................................................................................................................................................................................................................
[off=0021504] block #0084 .....................................................................................................................................................................................................................................
[off=0021760] block #0085 .....................................................................................................................................................................................................................................
[off=0022016] block #0086 .....................................................................................................................................................................................................................................
[off=0022272] block #0087 .....................................................................................................................................................................................................................................
[off=0022528] block #0088 .....................................................................................................................................................................................................................................
[off=0022784] block #0089 .....................................................................................................................................................................................................................................
[off=0023040] block #0090 .....................................................................................................................................................................................................................................
[off=0023296] block #0091 .....................................................................................................................................................................................................................................
[off=0023552] block #0092 .....................................................................................................................................................................................................................................
[off=0023808] block #0093 .....................................................................................................................................................................................................................................
[off=0024064] block #0094 .....................................................................................................................................................................................................................................
[off=0024320] block #0095 .....................................................................................................................................................................................................................................
[off=0024576] block #0096 .....................................................................................................................................................................................................................................
[off=0024832] block #0097 .....................................................................................................................................................................................................................................
[off=0025088] block #0098 .....................................................................................................................................................................................................................................
[off=0025344] block #0099 .....................................................................................................................................................................................................................................
[off=0025600] block #0100 .....................................................................................................................................................................................................................................
[off=0025856] block #0101 .....................................................................................................................................................................................................................................
[off=0026112] block #0102 .....................................................................................................................................................................................................................................
[off=0026368] block #0103 .....................................................................................................................................................................................................................................
[off=0026624] block #0104 .....................................................................................................................................................................................................................................
[off=0026880] block #0105 .....................................................................................................................................................................................................................................
[off=0027136] block #0106 .....................................................................................................................................................................................................................................
[off=0027392] block #0107 .....................................................................................................................................................................................................................................
[off=0027648] block #0108 .....................................................................................................................................................................................................................................
[off=0027904] block #0109 .....................................................................................................................................................................................................................................
[off=0028160] block #0110 .....................................................................................................................................................................................................................................
[off=0028416] block #0111 .....................................................................................................................................................................................................................................
[off=0028672] block #0112 .....................................................................................................................................................................................................................................
[off=0028928] block #0113 .....................................................................................................................................................................................................................................
[off=0029184] block #0114 .....................................................................................................................................................................................................................................
[off=0029440] block #0115 .....................................................................................................................................................................................................................................
[off=0029696] block #0116 .....................................................................................................................................................................................................................................
[off=0029952] block #0117 .....................................................................................................................................................................................................................................
[off=0030208] block #0118 .....................................................................................................................................................................................................................................
[off=0030464] block #0119 .....................................................................................................................................................................................................................................
[off=0030720] block #0120 .....................................................................................................................................................................................................................................
[off=0030976] block #0121 .....................................................................................................................................................................................................................................
[off=0031232] block #0122 .....................................................................................................................................................................................................................................
[off=0031488] block #0123 .....................................................................................................................................................................................................................................
[off=0031744] block #0124 .....................................................................................................................................................................................................................................
[off=0032000] block #0125 .....................................................................................................................................................................................................................................
[off=0032256] block #0126 .....................................................................................................................................................................................................................................
[off=0032512] block #0127 .....................................................................................................................................................................................................................................
[off=0032768] block #0128 .....................................................................................................................................................................................................................................
[off=0033024] block #0129 .....................................................................................................................................................................................................................................
[off=0033280] block #0130 .....................................................................................................................................................................................................................................
[off=0033536] block #0131 .....................................................................................................................................................................................................................................
[off=0033792] block #0132 .....................................................................................................................................................................................................................................
[off=0034048] block #0133 .....................................................................................................................................................................................................................................
[off=0034304] block #0134 .....................................................................................................................................................................................................................................
[off=0034560] block #0135 .....................................................................................................................................................................................................................................
[off=0034816] block #0136 .....................................................................................................................................................................................................................................
[off=0035072] block #0137 .....................................................................................................................................................................................................................................
[off=0035328] block #0138 .....................................................................................................................................................................................................................................
[off=0035584] block #0139 .....................................................................................................................................................................................................................................
[off=0035840] block #0140 .....................................................................................................................................................................................................................................
[off=0036096] block #0141 .....................................................................................................................................................................................................................................
[off=0036352] block #0142 .....................................................................................................................................................................................................................................
[off=0036608] block #0143 .....................................................................................................................................................................................................................................
[off=0036864] block #0144 .....................................................................................................................................................................................................................................
[off=0037120] block #0145 .....................................................................................................................................................................................................................................
[off=0037376] block #0146 .....................................................................................................................................................................................................................................
[off=0037632] block #0147 .....................................................................................................................................................................................................................................
[off=0037888] block #0148 .....................................................................................................................................................................................................................................
[off=0038144] block #0149 .....................................................................................................................................................................................................................................
[off=0038400] block #0150 .....................................................................................................................................................................................................................................
[off=0038656] block #0151 .....................................................................................................................................................................................................................................
[off=0038912] block #0152 .....................................................................................................................................................................................................................................
[off=0039168] block #0153 .....................................................................................................................................................................................................................................
[off=0039424] block #0154 .....................................................................................................................................................................................................................................
[off=0039680] block #0155 .....................................................................................................................................................................................................................................
[off=0039936] block #0156 .....................................................................................................................................................................................................................................
[off=0040192] block #0157 .....................................................................................................................................................................................................................................
[off=0040448] block #0158 .....................................................................................................................................................................................................................................
[off=0040704] block #0159 .....................................................................................................................................................................................................................................
[off=0040960] block #0160 .....................................................................................................................................................................................................................................
[off=0041216] block #0161 .....................................................................................................................................................................................................................................
[off=0041472] block #0162 .....................................................................................................................................................................................................................................
[off=0041728] block #0163 .....................................................................................................................................................................................................................................
[off=0041984] block #0164 .....................................................................................................................................................................................................................................
[off=0042240] block #0165 .....................................................................................................................................................................................................................................
[off=0042496] block #0166 .....................................................................................................................................................................................................................................
[off=0042752] block #0167 .....................................................................................................................................................................................................................................
[off=0043008] block #0168 .....................................................................................................................................................................................................................................
[off=0043264] block #0169 .....................................................................................................................................................................................................................................
[off=0043520] block #0170 .....................................................................................................................................................................................................................................
[off=0043776] block #0171 .....................................................................................................................................................................................................................................
[off=0044032] block #0172 .....................................................................................................................................................................................................................................
[off=0044288] block #0173 .....................................................................................................................................................................................................................................
[off=0044544] block #0174 .....................................................................................................................................................................................................................................
[off=0044800] block #0175 .....................................................................................................................................................................................................................................
[off=0045056] block #0176 .....................................................................................................................................................................................................................................
[off=0045312] block #0177 .....................................................................................................................................................................................................................................
[off=0045568] block #0178 .....................................................................................................................................................................................................................................
[off=0045824] block #0179 .....................................................................................................................................................................................................................................
[off=0046080] block #0180 .....................................................................................................................................................................................................................................
[off=0046336] block #0181 .....................................................................................................................................................................................................................................
[off=0046592] block #0182 .....................................................................................................................................................................................................................................
[off=0046848] block #0183 .....................................................................................................................................................................................................................................
[off=0047104] block #0184 .....................................................................................................................................................................................................................................
[off=0047360] block #0185 .....................................................................................................................................................................................................................................
[off=0047616] block #0186 .....................................................................................................................................................................................................................................
[off=0047872] block #0187 .....................................................................................................................................................................................................................................
[off=0048128] block #0188 .....................................................................................................................................................................................................................................
[off=0048384] block #0189 .....................................................................................................................................................................................................................................
[off=0048640] block #0190 .....................................................................................................................................................................................................................................
[off=0048896] block #0191 .....................................................................................................................................................................................................................................
[off=0049152] block #0192 .....................................................................................................................................................................................................................................
[off=0049408] block #0193 .....................................................................................................................................................................................................................................
[off=0049664] block #0194 .....................................................................................................................................................................................................................................
[off=0049920] block #0195 .....................................................................................................................................................................................................................................
[off=0050176] block #0196 .....................................................................................................................................................................................................................................
[off=0050432] block #0197 .....................................................................................................................................................................................................................................
[off=0050688] block #0198 .....................................................................................................................................................................................................................................
[off=0050944] block #0199 .....................................................................................................................................................................................................................................
[off=0051200] block #0200 .....................................................................................................................................................................................................................................
[off=0051456] block #0201 .....................................................................................................................................................................................................................................
[off=0051712] block #0202 .....................................................................................................................................................................................................................................
[off=0051968] block #0203 .....................................................................................................................................................................................................................................
[off=0052224] block #0204 .....................................................................................................................................................................................................................................
[off=0052480] block #0205 .....................................................................................................................................................................................................................................
[off=0052736] block #0206 .....................................................................................................................................................................................................................................
[off=0052992] block #0207 .....................................................................................................................................................................................................................................
[off=0053248] block #0208 .....................................................................................................................................................................................................................................
[off=0053504] block #0209 .....................................................................................................................................................................................................................................
[off=0053760] block #0210 .....................................................................................................................................................................................................................................
[off=0054016] block #0211 .....................................................................................................................................................................................................................................
[off=0054272] block #0212 .....................................................................................................................................................................................................................................
[off=0054528] block #0213 .....................................................................................................................................................................................................................................
[off=0054784] block #0214 .....................................................................................................................................................................................................................................
[off=0055040] block #0215 .....................................................................................................................................................................................................................................
[off=0055296] block #0216 .....................................................................................................................................................................................................................................
[off=0055552] block #0217 .....................................................................................................................................................................................................................................
[off=0055808] block #0218 .....................................................................................................................................................................................................................................
[off=0056064] block #0219 .....................................................................................................................................................................................................................................
[off=0056320] block #0220 .....................................................................................................................................................................................................................................
[off=0056576] block #0221 .....................................................................................................................................................................................................................................
[off=0056832] block #0222 .....................................................................................................................................................................................................................................
[off=0057088] block #0223 .....................................................................................................................................................................................................................................
[off=0057344] block #0224 .....................................................................................................................................................................................................................................
[off=0057600] block #0225 .....................................................................................................................................................................................................................................
[off=0057856] block #0226 .....................................................................................................................................................................................................................................
[off=0058112] block #0227 .....................................................................................................................................................................................................................................
[off=0058368] block #0228 .....................................................................................................................................................................................................................................
[off=0058624] block #0229 .....................................................................................................................................................................................................................................
[off=0058880] block #0230 .....................................................................................................................................................................................................................................
[off=0059136] block #0231 .....................................................................................................................................................................................................................................
[off=0059392] block #0232 .....................................................................................................................................................................................................................................
[off=0059648] block #0233 .....................................................................................................................................................................................................................................
[off=0059904] block #0234 .....................................................................................................................................................................................................................................
[off=0060160] block #0235 .....................................................................................................................................................................................................................................
[off=0060416] block #0236 .....................................................................................................................................................................................................................................
[off=0060672] block #0237 .....................................................................................................................................................................................................................................
[off=0060928] block #0238 .....................................................................................................................................................................................................................................
[off=0061184] block #0239 .....................................................................................................................................................................................................................................
[off=0061440] block #0240 .....................................................................................................................................................................................................................................
[off=0061696] block #0241 .....................................................................................................................................................................................................................................
[off=0061952] block #0242 .....................................................................................................................................................................................................................................
[off=0062208] block #0243 .....................................................................................................................................................................................................................................
[off=0062464] block #0244 .....................................................................................................................................................................................................................................
[off=0062720] block #0245 .....................................................................................................................................................................................................................................
[off=0062976] block #0246 .....................................................................................................................................................................................................................................
[off=0063232] block #0247 .....................................................................................................................................................................................................................................
[off=0063488] block #0248 .....................................................................................................................................................................................................................................
[off=0063744] block #0249 .....................................................................................................................................................................................................................................
[off=0064000] block #0250 .....................................................................................................................................................................................................................................
[off=0064256] block #0251 .....................................................................................................................................................................................................................................
[off=0064512] block #0252 .....................................................................................................................................................................................................................................
[off=0064768] block #0253 .....................................................................................................................................................................................................................................
[off=0065024] block #0254 .....................................................................................................................................................................................................................................
[off=0065280] block #0255 .....................................................................................................................................................................................................................................
[off=0065536] block #0256 .....................................................................................................................................................................................................................................
[off=0065792] block #0257 .....................................................................................................................................................................................................................................
[off=0066048] block #0258 .....................................................................................................................................................................................................................................
[off=0066304] block #0259 .....................................................................................................................................................................................................................................
[off=0066560] block #0260 .....................................................................................................................................................................................................................................
[off=0066816] block #0261 .....................................................................................................................................................................................................................................
[off=0067072] block #0262 .....................................................................................................................................................................................................................................
[off=0067328] block #0263 .....................................................................................................................................................................................................................................
[off=0067584] block #0264 .....................................................................................................................................................................................................................................
[off=0067840] block #0265 .....................................................................................................................................................................................................................................
[off=0068096] block #0266 .....................................................................................................................................................................................................................................
[off=0068352] block #0267 .....................................................................................................................................................................................................................................
[off=0068608] block #0268 .....................................................................................................................................................................................................................................
[off=0068864] block #0269 .....................................................................................................................................................................................................................................
[off=0069120] block #0270 .....................................................................................................................................................................................................................................
[off=0069376] block #0271 .....................................................................................................................................................................................................................................
[off=0069632] block #0272 .....................................................................................................................................................................................................................................
[off=0069888] block #0273 .....................................................................................................................................................................................................................................
[off=0070144] block #0274 .....................................................................................................................................................................................................................................
[off=0070400] block #0275 .....................................................................................................................................................................................................................................
[off=0070656] block #0276 .....................................................................................................................................................................................................................................
[off=0070912] block #0277 .....................................................................................................................................................................................................................................
[off=0071168] block #0278 .....................................................................................................................................................................................................................................
[off=0071424] block #0279 .....................................................................................................................................................................................................................................
[off=0071680] block #0280 .....................................................................................................................................................................................................................................
[off=0071936] block #0281 .....................................................................................................................................................................................................................................
[off=0072192] block #0282 .....................................................................................................................................................................................................................................
[off=0072448] block #0283 .....................................................................................................................................................................................................................................
[off=0072704] block #0284 .....................................................................................................................................................................................................................................
[off=0072960] block #0285 .....................................................................................................................................................................................................................................
[off=0073216] block #0286 .....................................................................................................................................................................................................................................
[off=0073472] block #0287 .....................................................................................................................................................................................................................................
[off=0073728] block #0288 .....................................................................................................................................................................................................................................
[off=0073984] block #0289 .....................................................................................................................................................................................................................................
[off=0074240] block #0290 .....................................................................................................................................................................................................................................
[off=0074496] block #0291 .....................................................................................................................................................................................................................................
[off=0074752] block #0292 .....................................................................................................................................................................................................................................
[off=0075008] block #0293 .....................................................................................................................................................................................................................................
[off=0075264] block #0294 .....................................................................................................................................................................................................................................
[off=0075520] block #0295 .....................................................................................................................................................................................................................................
[off=0075776] block #0296 .....................................................................................................................................................................................................................................
[off=0076032] block #0297 .....................................................................................................................................................................................................................................
[off=0076288] block #0298 .....................................................................................................................................................................................................................................
[off=0076544] block #0299 .....................................................................................................................................................................................................................................
[off=0076800] block #0300 .....................................................................................................................................................................................................................................
[off=0077056] block #0301 .....................................................................................................................................................................................................................................
[off=0077312] block #0302 .....................................................................................................................................................................................................................................
[off=0077568] block #0303 .....................................................................................................................................................................................................................................
[off=0077824] block #0304 .....................................................................................................................................................................................................................................
[off=0078080] block #0305 .....................................................................................................................................................................................................................................
[off=0078336] block #0306 .....................................................................................................................................................................................................................................
[off=0078592] block #0307 .....................................................................................................................................................................................................................................
[off=0078848] block #0308 .....................................................................................................................................................................................................................................
[off=0079104] block #0309 .....................................................................................................................................................................................................................................
[off=0079360] block #0310 .....................................................................................................................................................................................................................................
[off=0079616] block #0311 .....................................................................................................................................................................................................................................
[off=0079872] block #0312 .....................................................................................................................................................................................................................................
[off=0080128] block #0313 .....................................................................................................................................................................................................................................
[off=0080384] block #0314 .....................................................................................................................................................................................................................................
[off=0080640] block #0315 .....................................................................................................................................................................................................................................
[off=0080896] block #0316 .....................................................................................................................................................................................................................................
[off=0081152] block #0317 .....................................................................................................................................................................................................................................
[off=0081408] block #0318 .....................................................................................................................................................................................................................................
[off=0081664] block #0319 .....................................................................................................................................................................................................................................
[off=0081920] block #0320 .....................................................................................................................................................................................................................................
[off=0082176] block #0321 .....................................................................................................................................................................................................................................
[off=0082432] block #0322 .....................................................................................................................................................................................................................................
[off=0082688] block #0323 .....................................................................................................................................................................................................................................
[off=0082944] block #0324 .....................................................................................................................................................................................................................................
[off=0083200] block #0325 .....................................................................................................................................................................................................................................
[off=0083456] block #0326 .....................................................................................................................................................................................................................................
[off=0083712] block #0327 .....................................................................................................................................................................................................................................
[off=0083968] block #0328 .....................................................................................................................................................................................................................................
[off=0084224] block #0329 .....................................................................................................................................................................................................................................
[off=0084480] block #0330 .....................................................................................................................................................................................................................................
[off=0084736] block #0331 .....................................................................................................................................................................................................................................
[off=0084992] block #0332 .....................................................................................................................................................................................................................................
[off=0085248] block #0333 .....................................................................................................................................................................................................................................
[off=0085504] block #0334 .....................................................................................................................................................................................................................................
[off=0085760] block #0335 .....................................................................................................................................................................................................................................
[off=0086016] block #0336 .....................................................................................................................................................................................................................................
[off=0086272] block #0337 .....................................................................................................................................................................................................................................
[off=0086528] block #0338 .....................................................................................................................................................................................................................................
[off=0086784] block #0339 .....................................................................................................................................................................................................................................
[off=0087040] block #0340 .....................................................................................................................................................................................................................................
[off=0087296] block #0341 .....................................................................................................................................................................................................................................
[off=0087552] block #0342 .....................................................................................................................................................................................................................................
[off=0087808] block #0343 .....................................................................................................................................................................................................................................
[off=0088064] block #0344 .....................................................................................................................................................................................................................................
[off=0088320] block #0345 .....................................................................................................................................................................................................................................
[off=0088576] block #0346 .....................................................................................................................................................................................................................................
[off=0088832] block #0347 .....................................................................................................................................................................................................................................
[off=0089088] block #0348 .....................................................................................................................................................................................................................................
[off=0089344] block #0349 .....................................................................................................................................................................................................................................
[off=0089600] block #0350 .....................................................................................................................................................................................................................................
[off=0089856] block #0351 .....................................................................................................................................................................................................................................
[off=0090112] block #0352 .....................................................................................................................................................................................................................................
[off=0090368] block #0353 .....................................................................................................................................................................................................................................
[off=0090624] block #0354 .....................................................................................................................................................................................................................................
[off=0090880] block #0355 .....................................................................................................................................................................................................................................
[off=0091136] block #0356 .....................................................................................................................................................................................................................................
[off=0091392] block #0357 .....................................................................................................................................................................................................................................
[off=0091648] block #0358 .....................................................................................................................................................................................................................................
[off=0091904] block #0359 .....................................................................................................................................................................................................................................
[off=0092160] block #0360 .....................................................................................................................................................................................................................................
[off=0092416] block #0361 .....................................................................................................................................................................................................................................
[off=0092672] block #0362 .....................................................................................................................................................................................................................................
[off=0092928] block #0363 .....................................................................................................................................................................................................................................
[off=0093184] block #0364 .....................................................................................................................................................................................................................................
[off=0093440] block #0365 .....................................................................................................................................................................................................................................
[off=0093696] block #0366 .....................................................................................................................................................................................................................................
[off=0093952] block #0367 .....................................................................................................................................................................................................................................
[off=0094208] block #0368 .....................................................................................................................................................................................................................................
[off=0094464] block #0369 .....................................................................................................................................................................................................................................
[off=0094720] block #0370 .....................................................................................................................................................................................................................................
[off=0094976] block #0371 .....................................................................................................................................................................................................................................
[off=0095232] block #0372 .....................................................................................................................................................................................................................................
[off=0095488] block #0373 .....................................................................................................................................................................................................................................
[off=0095744] block #0374 .....................................................................................................................................................................................................................................
[off=0096000] block #0375 .....................................................................................................................................................................................................................................
[off=0096256] block #0376 .....................................................................................................................................................................................................................................
[off=0096512] block #0377 .....................................................................................................................................................................................................................................
[off=0096768] block #0378 .....................................................................................................................................................................................................................................
[off=0097024] block #0379 .....................................................................................................................................................................................................................................
[off=0097280] block #0380 .....................................................................................................................................................................................................................................
[off=0097536] block #0381 .....................................................................................................................................................................................................................................
[off=0097792] block #0382 .....................................................................................................................................................................................................................................
[off=0098048] block #0383 .....................................................................................................................................................................................................................................
[off=0098304] block #0384 .....................................................................................................................................................................................................................................
[off=0098560] block #0385 .....................................................................................................................................................................................................................................
[off=0098816] block #0386 .....................................................................................................................................................................................................................................
[off=0099072] block #0387 .....................................................................................................................................................................................................................................
[off=0099328] block #0388 .....................................................................................................................................................................................................................................
[off=0099584] block #0389 .....................................................................................................................................................................................................................................
[off=0099840] block #0390 .....................................................................................................................................................................................................................................
[off=0100096] block #0391 .....................................................................................................................................................................................................................................
[off=0100352] block #0392 .....................................................................................................................................................................................................................................
[off=0100608] block #0393 .....................................................................................................................................................................................................................................
[off=0100864] block #0394 .....................................................................................................................................................................................................................................
[off=0101120] block #0395 .....................................................................................................................................................................................................................................
[off=0101376] block #0396 .....................................................................................................................................................................................................................................
[off=0101632] block #0397 .....................................................................................................................................................................................................................................
[off=0101888] block #0398 .....................................................................................................................................................................................................................................
[off=0102144] block #0399 .....................................................................................................................................................................................................................................
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env python3
"""
Generate a >64 KB test file with predictable position-encoded content.
Every 256-byte block starts with a 32-character ASCII line
"[off=NNNNNNN] block #BBBB filler...\n"
where NNNNNNN is the absolute byte offset of the block start (padded to 7
decimal digits) and BBBB is the 4-digit block index. The line is padded
to 256 bytes with '.' so that seeking to any 256-aligned offset gives an
immediately-readable label.
"""
import sys
import os
def main():
path = sys.argv[1] if len(sys.argv) > 1 else "big.txt"
target_size = int(sys.argv[2]) if len(sys.argv) > 2 else 100 * 1024
block_size = 256
nblocks = (target_size + block_size - 1) // block_size
with open(path, "wb") as f:
for b in range(nblocks):
offset = b * block_size
header = f"[off={offset:07d}] block #{b:04d} "
body = header + ("." * (block_size - len(header) - 1)) + "\n"
assert len(body) == block_size, len(body)
f.write(body.encode("ascii"))
actual = os.path.getsize(path)
print(f"wrote {path}: {actual} bytes ({nblocks} blocks of {block_size} each)")
if __name__ == "__main__":
main()
+66
View File
@@ -0,0 +1,66 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
/*
* Exercises lseek() with offsets that span the 16-bit boundary.
* big.txt is 102400 bytes (100 KB); every 256-byte block opens with a
* "[off=NNNNNNN] block #BBBB " label, so any seek aligned to 256 lands
* on a self-identifying marker.
*/
static void show_marker(int fd, long off)
{
long pos = lseek(fd, off, SEEK_SET);
printf("\nseek %ld -> pos=%ld\n", off, pos);
char buf[28];
int n = read(fd, buf, 27);
if (n <= 0) {
printf(" read failed: %d\n", n);
return;
}
buf[n] = 0;
printf(" bytes: \"%s\"\n", buf);
}
int main(void)
{
int fd = open("BIG.TXT", O_RDONLY);
if (fd < 0) {
printf("open failed: %d\n", fd);
(void)getchar();
return 1;
}
/* Total file size. */
long size = lseek(fd, 0L, SEEK_END);
printf("file size = %ld bytes\n", size);
/* Seek inside the first 64 KB (high16 = 0). */
show_marker(fd, 0L);
show_marker(fd, 256L);
show_marker(fd, 32768L);
/* Right at the 64 KB boundary (offset 0x00010000, high16 = 1). */
show_marker(fd, 65536L);
/* Past 64 KB (high16 still 1, low16 != 0). */
show_marker(fd, 65536L + 256L);
show_marker(fd, 81920L);
/* Near end of file (size = 102400 = 0x19000, high16 = 1). */
show_marker(fd, 102400L - 256L);
/* SEEK_CUR: from current position, +256. After the previous SEEK_SET
* to 102144, then read of 27 bytes, pos is 102171. +256 -> 102427,
* which is past EOF — ESTEX should clamp or error. */
long after_cur = lseek(fd, 256L, SEEK_CUR);
printf("\nSEEK_CUR +256 -> pos=%ld (past EOF)\n", after_cur);
close(fd);
puts("");
puts("Press any key to exit...");
(void)getchar();
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := stattest
include $(PROJ_ROOT)/app.mk
+89
View File
@@ -0,0 +1,89 @@
/*
* stattest — exercise POSIX stat() and fstat() over ESTEX file metadata.
*
* Calls:
* stat() on a file by path
* stat() on a directory (current dir)
* stat() on a non-existent file (expects errno=ENOENT)
* fstat() on a freshly opened file
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
static const char *mode_str(uint16_t m)
{
if (S_ISDIR(m)) return "DIR";
if (S_ISREG(m)) return "REG";
return "???";
}
static void print_stat(const char *what, const struct stat *st)
{
char buf[32];
/* Reuse asctime by converting epoch → struct tm. */
time_t t = st->st_mtime;
struct tm *tm = localtime(&t);
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
printf(" %s: mode=%s perm=0%o size=%lu mtime=%s\n",
what,
mode_str(st->st_mode),
(unsigned)(st->st_mode & 0777),
(unsigned long)st->st_size,
buf);
}
int main(int argc, char **argv)
{
struct stat st;
puts("stattest: stat() / fstat() smoke test");
/* stat on this very file (the .exe). */
if (stat(argv[0], &st) == 0)
print_stat("self.exe", &st);
else
printf(" stat(\"%s\") failed: errno=%d (%s)\n",
argv[0], errno, strerror(errno));
/* stat on a definitely-missing file. */
errno = 0;
if (stat("NOSUCH.XXX", &st) == 0)
puts(" stat(NOSUCH.XXX) unexpectedly succeeded?!");
else
printf(" stat(NOSUCH.XXX) -> errno=%d (%s) [expected ENOENT]\n",
errno, strerror(errno));
/* fstat on a fresh handle (open the running exe read-only). */
int fd = open(argv[0], O_RDONLY);
if (fd < 0) {
printf(" open(\"%s\") failed: errno=%d (%s)\n",
argv[0], errno, strerror(errno));
} else {
if (fstat(fd, &st) == 0)
print_stat("fstat(self)", &st);
else
printf(" fstat failed: errno=%d (%s)\n",
errno, strerror(errno));
close(fd);
}
/* Extra argv-passed path. */
if (argc > 1) {
if (stat(argv[1], &st) == 0)
print_stat(argv[1], &st);
else
printf(" stat(\"%s\") failed: errno=%d (%s)\n",
argv[1], errno, strerror(errno));
}
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := stdlib
include $(PROJ_ROOT)/app.mk
+63
View File
@@ -0,0 +1,63 @@
/*
* stdlib_test — verifies that SDCC's z80.lib stdlib functions (atoi,
* strtol, rand, qsort, bsearch, abs, ldiv) work in our environment.
* If they all behave correctly, we can save ourselves the labour of
* reimplementing them in libc/stdlib.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmp_int(const void *a, const void *b)
{
int ia = *(const int *)a;
int ib = *(const int *)b;
return (ia > ib) - (ia < ib);
}
int main(int argc, char **argv)
{
/* atoi / strtol */
int v_atoi = atoi("12345");
long v_strtol = strtol("-9876", NULL, 10);
long v_hex = strtol("ff", NULL, 16);
printf("atoi(\"12345\") = %d (expected 12345)\n", v_atoi);
printf("strtol(\"-9876\",,10) = %ld (expected -9876)\n", v_strtol);
printf("strtol(\"ff\",,16) = %ld (expected 255)\n", v_hex);
/* abs / ldiv */
printf("abs(-7) = %d (expected 7)\n", abs(-7));
{
ldiv_t q = ldiv(100L, 7L);
printf("ldiv(100,7) = {q=%ld, r=%ld} (expected {14, 2})\n",
q.quot, q.rem);
}
/* rand / srand — deterministic with fixed seed */
srand(42);
printf("rand x3 (seed 42): %d %d %d\n", rand(), rand(), rand());
/* qsort */
{
int arr[] = { 5, 1, 4, 2, 8, 3, 7, 6, 0, 9 };
qsort(arr, 10, sizeof(int), cmp_int);
printf("qsort:");
for (int i = 0; i < 10; i++) printf(" %d", arr[i]);
printf(" (expected 0..9 sorted)\n");
/* bsearch */
int key = 7;
int *p = (int *)bsearch(&key, arr, 10, sizeof(int), cmp_int);
printf("bsearch(7) -> %s (expected found)\n",
(p && *p == 7) ? "found" : "MISS");
}
/* argv-as-int: typical CLI use */
if (argc > 1) {
printf("argv[1] as int: %d\n", atoi(argv[1]));
}
puts("\nall SDCC stdlib functions reachable.");
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := stest2
include $(PROJ_ROOT)/app.mk
+43
View File
@@ -0,0 +1,43 @@
/*
* stattest — exercise POSIX stat() and fstat() over ESTEX file metadata.
*
* Calls:
* stat() on a file by path
* stat() on a directory (current dir)
* stat() on a non-existent file (expects errno=ENOENT)
* fstat() on a freshly opened file
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <dir.h>
int main(int argc, char **argv)
{
struct stat st;
puts("stattest: stat() / fstat() smoke test");
ffblk_t ffb;
if (ffirst(argv[0], &ffb, FA_DIREC) == 0) {
printf("File %s, size = %d\n", argv[0], ffb.size);
} else {
printf("File %s, error\n", argv[0]);
}
if (argc > 1) {
if (ffirst(argv[1], &ffb, FA_DIREC) == 0) {
printf("File %s, size = %d\n", argv[1], ffb.size);
} else {
printf("File %s, error\n", argv[1]);
}
}
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build strtest.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := strtest
include $(PROJ_ROOT)/app.mk
+53
View File
@@ -0,0 +1,53 @@
#include <stdio.h>
#include <string.h>
static void check(const char *label, int ok)
{
puts(label);
puts(ok ? " OK" : " FAIL");
}
int main(void)
{
char buf[32];
/* strlen */
check("strlen(\"\") == 0", strlen("") == 0);
check("strlen(\"hello\") == 5", strlen("hello") == 5);
/* strcpy + strlen */
strcpy(buf, "Sprinter");
check("strcpy + strlen == 8", strlen(buf) == 8);
/* strcmp */
check("strcmp(\"a\",\"a\") == 0", strcmp("a", "a") == 0);
check("strcmp(\"a\",\"b\") < 0", strcmp("a", "b") < 0);
check("strcmp(\"b\",\"a\") > 0", strcmp("b", "a") > 0);
check("strcmp(buf,\"Sprinter\")", strcmp(buf, "Sprinter") == 0);
/* strcat */
strcpy(buf, "Hello ");
strcat(buf, "Sprinter!");
check("strcat -> \"Hello Sprinter!\"", strcmp(buf, "Hello Sprinter!") == 0);
/* memcpy */
memset(buf, 'X', 16);
memcpy(buf + 4, "ABCD", 4);
buf[16] = 0;
check("memset+memcpy -> \"XXXXABCDXXXXXXXX\"",
strcmp(buf, "XXXXABCDXXXXXXXX") == 0);
/* memset */
memset(buf, 'q', 5);
buf[5] = 0;
check("memset(buf,'q',5) -> \"qqqqq\"", strcmp(buf, "qqqqq") == 0);
/* memcmp */
check("memcmp equal", memcmp("abcd", "abcd", 4) == 0);
check("memcmp diff", memcmp("abcd", "abxd", 4) != 0);
puts("");
puts("All checks done. Press any key to exit.");
(void)getchar();
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
# Build time_dir_test.exe — uses lib/sprinter.lib in TINY memory mode.
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := timedir
include $(PROJ_ROOT)/app.mk
+108
View File
@@ -0,0 +1,108 @@
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <conio.h>
static const char *dow_name(uint8_t d)
{
/* Sprinter SYSTIME returns dow 1-based: 1=Sun..7=Sat. */
static const char *names[] = { "?", "Sun", "Mon", "Tue",
"Wed", "Thu", "Fri", "Sat" };
return (d >= 1 && d <= 7) ? names[d] : names[0];
}
int main(void)
{
/* --- time ----------------------------------------------------------- */
datetime_t dt;
getdatetime(&dt);
printf("getdatetime: %04u-%02u-%02u %02u:%02u:%02u (dow=%u %s)\n",
dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.dow, dow_name(dt.dow));
/* dow convention probe — set to known dates, read back.
* Discriminating test: today (Thu) gave dow=5, which fits either
* (a) Sun=1, Mon=2, ..., Sat=7 (DOS 1-based starting Sun)
* (b) Sat=0, Sun=1, ..., Fri=6 (week starts Saturday)
* Saturday's number tells us which one. */
datetime_t saved = dt;
datetime_t probe;
probe = dt; probe.year = 2026; probe.month = 5; probe.day = 30; /* Sat */
if (setdatetime(&probe) == 0) {
getdatetime(&probe);
printf("probe 2026-05-30 (Sat expected): dow=%u %s\n",
probe.dow, dow_name(probe.dow));
}
probe = dt; probe.year = 2026; probe.month = 5; probe.day = 31; /* Sun */
if (setdatetime(&probe) == 0) {
getdatetime(&probe);
printf("probe 2026-05-31 (Sun expected): dow=%u %s\n",
probe.dow, dow_name(probe.dow));
}
probe = dt; probe.year = 2026; probe.month = 6; probe.day = 1; /* Mon */
if (setdatetime(&probe) == 0) {
getdatetime(&probe);
printf("probe 2026-06-01 (Mon expected): dow=%u %s\n",
probe.dow, dow_name(probe.dow));
}
/* Restore original. */
if (setdatetime(&saved) == 0)
printf("restored original date\n");
else
printf("setdatetime(restore) failed: errno=%d\n", errno);
/* --- getcwd --------------------------------------------------------- */
char cwd[256];
if (getcwd(cwd, sizeof cwd) == NULL) {
printf("getcwd failed: errno=%d (%s)\n", errno, strerror(errno));
} else {
printf("cwd before: \"%s\"\n", cwd);
}
/* --- mkdir / chdir / getcwd / rmdir --------------------------------- */
const char *test_dir = "TMPTEST";
/* If a previous run left it behind, ignore the mkdir failure. */
if (mkdir(test_dir) < 0) {
printf("mkdir(%s) -> errno=%d (%s) [continuing]\n",
test_dir, errno, strerror(errno));
} else {
printf("mkdir(%s) OK\n", test_dir);
}
if (chdir(test_dir) < 0) {
printf("chdir(%s) failed: errno=%d (%s)\n",
test_dir, errno, strerror(errno));
return 1;
}
printf("chdir(%s) OK\n", test_dir);
if (getcwd(cwd, sizeof cwd) != NULL)
printf("cwd after: \"%s\"\n", cwd);
/* Back out, then remove. */
if (chdir("\\") < 0)
printf("chdir(\\) failed: errno=%d\n", errno);
else
printf("chdir(\\) OK\n");
if (rmdir(test_dir) < 0)
printf("rmdir(%s) failed: errno=%d (%s)\n",
test_dir, errno, strerror(errno));
else
printf("rmdir(%s) OK\n", test_dir);
if (getcwd(cwd, sizeof cwd) != NULL)
printf("cwd final: \"%s\"\n", cwd);
puts("\npress any key to exit");
(void)getch();
return 0;
}