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:
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := assrtest
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := dec_test
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := filetest
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_dbuf
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_demo
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_mous
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := ptime
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 .....................................................................................................................................................................................................................................
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := stattest
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := stdlib
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := stest2
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user