Compare commits
17 Commits
b851e22fa6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| bd116d7361 | |||
| 858e5755ad | |||
| f87b52bb7f | |||
| 07c4004bd9 | |||
| 6992c1436e | |||
| 07c398a560 | |||
| 4bed9d3f3f | |||
| 463a058f56 | |||
| 8abc1d6c16 | |||
| 982af12710 | |||
| 394ee3a2cd | |||
| 47c9cd326a | |||
| ca5f30b332 | |||
| 0ad0559fc8 | |||
| 035d93ab51 | |||
| 0dedc4dac8 | |||
| 737c974400 |
+18
-1
@@ -9,7 +9,8 @@ build/
|
||||
# sprinter-cc per-example intermediate directory
|
||||
.sprinter-cc-*/
|
||||
|
||||
# Per-example final/intermediate outputs landing alongside the source
|
||||
# Per-program final/intermediate outputs landing alongside the source
|
||||
# (real apps under examples/ and libc feature tests under tests/).
|
||||
examples/*/*.exe
|
||||
examples/*/*.asm
|
||||
examples/*/*.lst
|
||||
@@ -23,6 +24,22 @@ examples/*/*.cdb
|
||||
examples/*/*.mem
|
||||
examples/*/*.rst
|
||||
|
||||
# Temporary build directory for floppy disk image preparation
|
||||
examples/*/.disk_tmp/
|
||||
|
||||
tests/*/*.exe
|
||||
tests/*/*.asm
|
||||
tests/*/*.lst
|
||||
tests/*/*.lk
|
||||
tests/*/*.ihx
|
||||
tests/*/*.noi
|
||||
tests/*/*.sym
|
||||
tests/*/*.map
|
||||
tests/*/*.rel
|
||||
tests/*/*.cdb
|
||||
tests/*/*.mem
|
||||
tests/*/*.rst
|
||||
|
||||
# libc archive (built from libc/, see lib/Makefile)
|
||||
lib/*.lib
|
||||
|
||||
|
||||
@@ -1,58 +1,41 @@
|
||||
# Sprinter C Compiler — top-level Makefile
|
||||
#
|
||||
# make build host tools, libc archive, and all examples
|
||||
# make build host tools, libc archive, all tests, all apps
|
||||
# make tools build only host tools (mkexe)
|
||||
# make lib build lib/sprinter.lib (libc archive used by sprinter-cc)
|
||||
# make examples build all examples
|
||||
# make floppy package every example + test files into mame/v306/IMG/mc.img
|
||||
# make tests build all libc feature tests under tests/
|
||||
# make examples build all real applications under examples/
|
||||
# make floppy package every .exe + test fixtures into mame/v306/IMG/mc.img
|
||||
# make check run mkexe unit tests
|
||||
# make clean remove all build artefacts
|
||||
# make sdcc download/extract vendored SDCC
|
||||
#
|
||||
# Most heavy lifting is delegated to sub-Makefiles.
|
||||
|
||||
EXAMPLES := hello banked bankedbg strtest cat seek malloc mem_test argv errno rt_test openenv ls conio attrprob timedir mouse banklocl stdlib assrtest ptime stattest filetest gfx_demo gfx_d16 gfx_text gfx_mous
|
||||
# Small libc-feature tests (one program per .c-language feature or libc API).
|
||||
TESTS := hello banked bankedbg strtest cat seek malloc mem_test argv errno \
|
||||
rt_test openenv ls conio attrprob timedir mouse banklocl stdlib \
|
||||
assrtest ptime stattest filetest gfx_demo gfx_d16 gfx_text gfx_mous
|
||||
|
||||
# Larger end-user applications under examples/.
|
||||
APPS := mdview
|
||||
|
||||
MAME_DIR := mame/v306
|
||||
FLOPPY_IMG := $(MAME_DIR)/IMG/mc.img
|
||||
MAKE_DISK := $(MAME_DIR)/make_disk.py
|
||||
|
||||
EXE_FILES := \
|
||||
examples/hello/hello.exe \
|
||||
examples/banked/banked.exe \
|
||||
examples/bankedbg/bankedbg.exe \
|
||||
examples/strtest/strtest.exe \
|
||||
examples/cat/cat.exe \
|
||||
examples/seek/seek.exe \
|
||||
examples/malloc/malloc.exe \
|
||||
examples/mem_test/mem_test.exe \
|
||||
examples/argv/argv.exe \
|
||||
examples/errno/errno.exe \
|
||||
examples/rt_test/rt_test.exe \
|
||||
examples/openenv/openenv.exe \
|
||||
examples/ls/ls.exe \
|
||||
examples/conio/conio.exe \
|
||||
examples/attrprob/attrprob.exe \
|
||||
examples/timedir/timedir.exe \
|
||||
examples/mouse/mouse.exe \
|
||||
examples/banklocl/banklocl.exe \
|
||||
examples/stdlib/stdlib.exe \
|
||||
examples/assrtest/assrtest.exe \
|
||||
examples/ptime/ptime.exe \
|
||||
examples/stattest/stattest.exe \
|
||||
examples/filetest/filetest.exe \
|
||||
examples/gfx_demo/gfx_demo.exe \
|
||||
examples/gfx_d16/gfx_d16.exe \
|
||||
examples/gfx_text/gfx_text.exe \
|
||||
examples/gfx_mous/gfx_mous.exe
|
||||
TEST_EXES := $(foreach t,$(TESTS),tests/$(t)/$(t).exe)
|
||||
APP_EXES := $(foreach a,$(APPS),examples/$(a)/$(a).exe)
|
||||
ALL_EXES := $(TEST_EXES) $(APP_EXES)
|
||||
|
||||
DATA_FILES := \
|
||||
examples/cat/test.txt \
|
||||
examples/seek/big.txt
|
||||
tests/cat/test.txt \
|
||||
tests/seek/big.txt \
|
||||
examples/mdview/SAMPLE.MD
|
||||
|
||||
.PHONY: all tools lib examples check clean sdcc floppy $(EXAMPLES)
|
||||
.PHONY: all tools lib tests examples check clean sdcc floppy $(TESTS) $(APPS)
|
||||
|
||||
all: tools lib examples
|
||||
all: tools lib tests examples
|
||||
|
||||
tools:
|
||||
$(MAKE) -C toolchain/mkexe
|
||||
@@ -63,18 +46,22 @@ lib:
|
||||
check: tools
|
||||
$(MAKE) -C toolchain/mkexe check
|
||||
|
||||
examples: $(EXAMPLES)
|
||||
tests: $(TESTS)
|
||||
examples: $(APPS)
|
||||
|
||||
$(EXAMPLES): tools lib
|
||||
$(TESTS): tools lib
|
||||
$(MAKE) -C tests/$@
|
||||
|
||||
$(APPS): tools lib
|
||||
$(MAKE) -C examples/$@
|
||||
|
||||
# Generate big.txt if missing (gen_bigfile.py creates 100 KB marker file).
|
||||
examples/seek/big.txt:
|
||||
cd examples/seek && python3 gen_bigfile.py big.txt 102400
|
||||
tests/seek/big.txt:
|
||||
cd tests/seek && python3 gen_bigfile.py big.txt 102400
|
||||
|
||||
# Re-pack the MAME floppy image with every built example + needed data files.
|
||||
floppy: examples examples/seek/big.txt
|
||||
python3 $(MAKE_DISK) $(FLOPPY_IMG) $(EXE_FILES) $(DATA_FILES)
|
||||
# Re-pack the MAME floppy image with every built exe + needed data files.
|
||||
floppy: tests examples tests/seek/big.txt
|
||||
python3 $(MAKE_DISK) $(FLOPPY_IMG) $(ALL_EXES) $(DATA_FILES)
|
||||
@echo
|
||||
@echo "Floppy ready: $(FLOPPY_IMG)"
|
||||
@echo "Run: cd $(MAME_DIR) && ./run_mame.sh"
|
||||
@@ -82,7 +69,8 @@ floppy: examples examples/seek/big.txt
|
||||
clean:
|
||||
$(MAKE) -C toolchain/mkexe clean
|
||||
$(MAKE) -C lib clean
|
||||
@for e in $(EXAMPLES); do $(MAKE) -C examples/$$e clean; done
|
||||
@for t in $(TESTS); do $(MAKE) -C tests/$$t clean; done
|
||||
@for a in $(APPS); do $(MAKE) -C examples/$$a clean; done
|
||||
|
||||
sdcc:
|
||||
bash third_party/setup-sdcc.sh
|
||||
|
||||
@@ -52,7 +52,7 @@ pages by program size — small programs get only one page. Pick a memory mode
|
||||
on what your program needs:
|
||||
|
||||
| Mode | Code lives in | Banking | Use when | Note |
|
||||
|---|---|---|---|
|
||||
|---|---|---|---|---|
|
||||
| `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB | |
|
||||
| `small` | W1-W2 (0x4100+) | no | code+data < 30 KB | |
|
||||
| `big` | W2 + W1 banking | yes (W1) | tiny + extra code modules | |
|
||||
@@ -217,7 +217,6 @@ This repository contains:
|
||||
|
||||
* **Sprinter / Peters Plus** — Иван Мак, Дмитрий Паринов and the original team
|
||||
* **SDCC** — for the underlying Z80 compiler
|
||||
* **z88dk +pps** — Дмитрий M. for paving the way with the first Sprinter target
|
||||
* **MAME** — for the Sprinter Sp2000 emulation
|
||||
|
||||
---
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# example.mk — shared Makefile fragment for simple Sprinter ESTEX examples.
|
||||
# app.mk — shared Makefile fragment for any standalone Sprinter ESTEX
|
||||
# program — used both by libc feature tests under tests/ and by real
|
||||
# applications under examples/.
|
||||
#
|
||||
# Usage in an example's Makefile:
|
||||
# Usage in a per-program Makefile:
|
||||
#
|
||||
# PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
# EXAMPLE := my_example # base name (matches my_example.c)
|
||||
# EXAMPLE := my_program # base name (matches my_program.c)
|
||||
#
|
||||
# # Optional overrides (any combination):
|
||||
# # MEMORY := small # tiny | small | big | huge | manual
|
||||
@@ -12,7 +14,7 @@
|
||||
# # EXTRA_FLAGS := --crt0=minimal # passed through to sprinter-cc
|
||||
# # EXTRA_DATA := test.txt # extra files to add to `make floppy`
|
||||
#
|
||||
# include $(PROJ_ROOT)/examples/example.mk
|
||||
# include $(PROJ_ROOT)/app.mk
|
||||
#
|
||||
# Pipeline (all driven by sprinter-cc):
|
||||
# crt0 + EXAMPLE.c + EXTRA_SRCS --sdcc--> .ihx
|
||||
@@ -61,9 +63,9 @@ $(LIB):
|
||||
clean:
|
||||
rm -rf .sprinter-cc-* $(EXAMPLE).exe
|
||||
|
||||
# `make floppy` packs ONLY this example (+ optional EXTRA_DATA files) into
|
||||
# `make floppy` packs ONLY this program (+ optional EXTRA_DATA files) into
|
||||
# the MAME floppy image, replacing whatever was there. Handy for trying a
|
||||
# single program without rebuilding all 27 examples.
|
||||
# single program without rebuilding everything.
|
||||
floppy: $(EXAMPLE).exe
|
||||
python3 $(MAKE_DISK) $(FLOPPY_IMG) $(EXAMPLE).exe $(EXTRA_DATA)
|
||||
@echo
|
||||
@@ -0,0 +1,188 @@
|
||||
# MDView: описание работы и тестовые паттерны
|
||||
## Назначение
|
||||
`mdview` — консольный просмотрщик Markdown для текстового режима 80x32.
|
||||
Программа загружает `.MD`-файл, индексирует его на экранные сегменты и рендерит содержимое с учётом переносов, стилей и специальных блоков.
|
||||
|
||||
## Как работает программа
|
||||
### 1) Загрузка файла
|
||||
- На старте вызывается `load_file(path)`.
|
||||
- Если путь не передан, используется `SAMPLE.MD`.
|
||||
- При ошибках загрузки программа показывает причину и завершает работу после нажатия клавиши.
|
||||
|
||||
### 2) Индексация (`index_lines`)
|
||||
- Файл разбирается в массив сегментов для быстрого рендера.
|
||||
- Поддерживаются ключевые типы строк:
|
||||
- заголовки `#..####`,
|
||||
- маркированные/нумерованные списки,
|
||||
- цитаты `>`,
|
||||
- горизонтальные разделители,
|
||||
- fenced code-блоки,
|
||||
- таблицы (nowrap-режим),
|
||||
- обычные параграфы.
|
||||
- Для list/quote/plain используется общая логика сканирования с режимами склейки строк.
|
||||
|
||||
### 3) Рендер (`render_line`, `render_viewport`)
|
||||
- Для каждой видимой строки рисуется префикс (маркер списка, цитаты и т.д.) и текст.
|
||||
- Поддерживаются inline-стили:
|
||||
- `**жирный**`,
|
||||
- `*курсив*`,
|
||||
- `_подчёркнутый_`,
|
||||
- `~~зачёркнутый~~`,
|
||||
- `` `code` ``.
|
||||
- Табы расширяются до фиксированного шага.
|
||||
- Для длинных nowrap-строк применяется горизонтальный сдвиг и индикаторы `<`/`>`.
|
||||
|
||||
### 4) Навигация
|
||||
- `Up/Down` — прокрутка на 1 строку.
|
||||
- `PgUp/PgDn` — прокрутка на экран.
|
||||
- `Home/End` — начало/конец документа.
|
||||
- `Left/Right` — горизонтальная прокрутка nowrap-контента.
|
||||
- `Esc` или `F10` — выход.
|
||||
|
||||
## Сборка и запуск
|
||||
```bash
|
||||
make -C examples/mdview
|
||||
```
|
||||
|
||||
Запуск на целевой системе:
|
||||
```bash
|
||||
mdview.exe <путь_к_файлу.md>
|
||||
```
|
||||
|
||||
Если путь не указан, открывается `SAMPLE.MD`.
|
||||
|
||||
## Тестовые паттерны
|
||||
Ниже набор паттернов для ручной регрессии.
|
||||
|
||||
### P01 — Базовый smoke-тест открытия
|
||||
Вход:
|
||||
- валидный markdown-файл среднего размера.
|
||||
|
||||
Ожидается:
|
||||
- файл открывается без ошибок;
|
||||
- статус-бар и меню отображаются корректно;
|
||||
- прокрутка работает.
|
||||
|
||||
### P02 — Ошибка открытия файла
|
||||
Вход:
|
||||
- несуществующий путь к файлу.
|
||||
|
||||
Ожидается:
|
||||
- сообщение `mdview: cannot load file`;
|
||||
- корректный код причины (`open failed` и т.п.);
|
||||
- ожидание клавиши перед выходом.
|
||||
|
||||
### P03 — Пустой файл
|
||||
Вход:
|
||||
- пустой `.md`.
|
||||
|
||||
Ожидается:
|
||||
- сообщение `mdview: empty file`;
|
||||
- корректное завершение после нажатия клавиши.
|
||||
|
||||
### P04 — Обычный параграф и переносы
|
||||
Шаблон:
|
||||
```md
|
||||
Это длинный абзац для проверки переноса строк в обычном тексте.
|
||||
Вторая строка должна мягко склеиться с первой.
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- строки склеиваются как единый параграф;
|
||||
- переносы происходят по ширине экрана без потери символов.
|
||||
|
||||
### P05 — Hard break в параграфе
|
||||
Шаблон:
|
||||
```md
|
||||
Первая строка с двумя пробелами в конце.
|
||||
Вторая строка после hard break.
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- между строками сохраняется принудительный разрыв;
|
||||
- inline-стиль не ломается.
|
||||
|
||||
### P06 — Многострочный список с lazy continuation
|
||||
Шаблон:
|
||||
```md
|
||||
- Пункт списка, который продолжается
|
||||
на следующей строке с отступом.
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- continuation-строка склеивается с пунктом через один пробел;
|
||||
- лишние ведущие отступы continuation не попадают в итоговый текст;
|
||||
- переносы не ломают маркер списка.
|
||||
|
||||
### P07 — Многострочная цитата
|
||||
Шаблон:
|
||||
```md
|
||||
> Первая строка цитаты
|
||||
> Вторая строка цитаты
|
||||
> Третья строка цитаты
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- для продолжений корректно повторяется quote-префикс;
|
||||
- сырой символ `>` из исходника не «просачивается» в середину текста.
|
||||
|
||||
### P08 — Пустая quoted-строка как разделитель
|
||||
Шаблон:
|
||||
```md
|
||||
> Первый параграф цитаты
|
||||
>
|
||||
> Второй параграф цитаты
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- пустая quoted-строка разделяет два параграфа;
|
||||
- рендер не объединяет их в один поток.
|
||||
|
||||
### P09 — Таблица в nowrap-режиме
|
||||
Шаблон:
|
||||
```md
|
||||
| col1 | col2 | col3 |
|
||||
|------|------|------|
|
||||
| очень длинное значение | очень длинное значение | очень длинное значение |
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- строка таблицы не переносится по словам;
|
||||
- работает горизонтальный сдвиг `Left/Right`;
|
||||
- индикаторы `<`/`>` показывают скрытый контент.
|
||||
|
||||
### P10 — Fenced code-block
|
||||
Шаблон:
|
||||
~~~md
|
||||
```text
|
||||
**это не жирный**
|
||||
_это не подчёркнутый_
|
||||
```
|
||||
~~~
|
||||
|
||||
Ожидается:
|
||||
- внутри code-блока inline-разметка не применяется;
|
||||
- текст отображается как литерал.
|
||||
|
||||
### P11 — Inline-стили на обычном тексте
|
||||
Шаблон:
|
||||
```md
|
||||
Текст с **жирным**, *курсивом*, _подчёркнутым_, ~~зачёркнутым~~ и `code`.
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
- все перечисленные стили рендерятся корректно;
|
||||
- литеральные случаи вроде `2 * 3` не превращаются в стиль.
|
||||
|
||||
### P12 — Статус-бар и границы прокрутки
|
||||
Вход:
|
||||
- документ на несколько экранов.
|
||||
|
||||
Ожидается:
|
||||
- корректные `L x-y / total` и `%`;
|
||||
- `Home/End` приводят к ожидаемым позициям;
|
||||
- при выходе за границы документа top-line корректно clamp-ится.
|
||||
|
||||
## Рекомендация по регрессии
|
||||
После любых изменений в логике индексации/рендера прогонять минимум:
|
||||
- `P04`, `P05`, `P06`, `P07`, `P09`, `P10`, `P11`, `P12`.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Build mdview.exe — Markdown viewer for Sprinter.
|
||||
#
|
||||
# small memory mode: code in W1, data/stack/heap in W2 (32 KB total).
|
||||
# W3 stays free for the file buffer (EMM-mapped).
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := mdview
|
||||
MEMORY := small
|
||||
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Образ дискеты: только mdview.exe + README.MD (перекодированный
|
||||
# из UTF-8 в CP866 — рабочую кодировку Sprinter).
|
||||
#
|
||||
# README.MD хранится в репозитории в UTF-8; iconv -c конвертирует
|
||||
# его в CP866, отбрасывая символы без аналога в целевой кодировке.
|
||||
# Результат кладётся в .disk_tmp/README.MD, чтобы make_disk.py
|
||||
# использовал правильное имя файла на диске.
|
||||
# ------------------------------------------------------------------
|
||||
DISK_TMP := .disk_tmp
|
||||
README_DISK := $(DISK_TMP)/README.MD
|
||||
|
||||
$(DISK_TMP):
|
||||
mkdir -p $@
|
||||
|
||||
$(README_DISK): README.MD | $(DISK_TMP)
|
||||
iconv -c -f UTF-8 -t CP866 README.MD > $@
|
||||
|
||||
floppy: $(EXAMPLE).exe $(README_DISK)
|
||||
python3 $(MAKE_DISK) $(FLOPPY_IMG) $(EXAMPLE).exe $(README_DISK)
|
||||
@echo
|
||||
@echo "Floppy ready: $(FLOPPY_IMG)"
|
||||
@echo "Run: cd $(MAME_DIR) && ./run_mame.sh"
|
||||
|
||||
clean:
|
||||
rm -rf .sprinter-cc-* $(EXAMPLE).exe $(DISK_TMP)
|
||||
|
||||
.PHONY: all clean floppy run
|
||||
@@ -0,0 +1,133 @@
|
||||
# MDView — Просмотрщик Markdown для Sprinter
|
||||
|
||||
**MDView** — программа для просмотра документов в формате *Markdown* на компьютере
|
||||
Sprinter (процессор Z80). Документ хранится в отдельном W3 окне и не занимает
|
||||
основную RAM программы.
|
||||
|
||||
## Возможности
|
||||
|
||||
- Документы до **128 КБ** (8 страниц EMM по 16 КБ каждая)
|
||||
- До **16 384** экранных строк в индексе
|
||||
- Автоматический перенос слов по ширине экрана (80 столбцов)
|
||||
- Горизонтальный сдвиг для широких строк (блоки кода, таблицы)
|
||||
- Статус-бар: имя файла, диапазон строк, процент прокрутки
|
||||
- Спиннер в строке состояния во время загрузки и индексации
|
||||
- Поддержка «мягкого» склеивания строк в абзацах и цитатах
|
||||
|
||||
## Запуск
|
||||
|
||||
```
|
||||
mdview [имя_файла.md]
|
||||
```
|
||||
|
||||
Если имя файла не задано, загружается `README.MD`.
|
||||
|
||||
## Управление
|
||||
|
||||
```
|
||||
Клавиша Действие
|
||||
───────────── ────────────────────────────────────────
|
||||
Up Down Прокрутка на одну строку вверх / вниз
|
||||
PgUp PgDn Прокрутка на страницу (30 строк)
|
||||
Home Начало документа
|
||||
End Конец документа
|
||||
Left Right Горизонтальный сдвиг (только nowrap-строки)
|
||||
F1 Окно справки
|
||||
F10 / Esc Выход из программы
|
||||
```
|
||||
|
||||
## Синтаксис Markdown
|
||||
|
||||
### Заголовки
|
||||
|
||||
Поддерживаются уровни H1–H4. Уровни H5 и H6 отображаются как H4.
|
||||
|
||||
# Заголовок первого уровня
|
||||
## Заголовок второго уровня
|
||||
### Заголовок третьего уровня
|
||||
#### Заголовок четвёртого уровня
|
||||
|
||||
### Текстовое форматирование
|
||||
|
||||
**Жирный текст** выделяется двойными звёздочками: `**текст**`
|
||||
|
||||
*Курсив* выделяется одиночными звёздочками `*текст*` или знаком подчёркивания `_текст_`
|
||||
|
||||
`Встроенный код` обозначается обратными кавычками
|
||||
|
||||
~~Зачёркнутый текст~~ — двойные тильды: `~~текст~~`
|
||||
|
||||
### Ненумерованный список
|
||||
|
||||
Маркеры `-`, `*` или `+`:
|
||||
|
||||
- Первый пункт списка
|
||||
- Второй пункт списка
|
||||
- Третий пункт с достаточно длинным текстом, который при необходимости
|
||||
будет перенесён на следующую строку с сохранением отступа
|
||||
|
||||
### Нумерованный список
|
||||
|
||||
1. Первый элемент
|
||||
2. Второй элемент
|
||||
3. Третий элемент
|
||||
|
||||
### Цитата
|
||||
|
||||
> Блок цитаты начинается с символа `>`. Несколько последовательных
|
||||
> строк одной цитаты склеиваются в единый абзац с автоматическим
|
||||
> переносом слов.
|
||||
|
||||
### Блок кода (verbatim)
|
||||
|
||||
Блок кода заключается в тройные обратные кавычки. Внутри блока
|
||||
текст отображается «как есть» без разбора Markdown:
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
#include <sprinter.h>
|
||||
|
||||
int main(void) {
|
||||
puts("Hello, Sprinter!");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Горизонтальная линия
|
||||
|
||||
Три или более символов `---`, `***` или `___` на отдельной строке:
|
||||
|
||||
---
|
||||
|
||||
## Технические характеристики
|
||||
|
||||
- **Платформа:** Sprinter, процессор Z80 @ 21 МГц
|
||||
- **Кодировка:** CP866 (DOS Cyrillic)
|
||||
- **Максимальный размер файла:** 128 КБ
|
||||
- **Максимальное число строк в индексе:** 16 384
|
||||
- **Режим памяти:** small
|
||||
- Код программы, cтек, данные, куча — окнa W1-W2 (32 КБ, адреса 0x4000–0xBFFF).
|
||||
- Буфер файла — страницы EMM, отображаемые в W3 (0xC000–0xFFFF)
|
||||
|
||||
## TODO
|
||||
|
||||
1. **Увеличение размера документов.** Снять лимит 128 КБ: Достаточно
|
||||
разрешить работать с большим кол-вом страниц памяти, пока оттестированно
|
||||
на работе с 8-мю страницами по 16Кб.
|
||||
|
||||
2. **Форматированные таблицы.** Разбирать строки вида `| ячейка | ячейка |`
|
||||
с автоматическим выравниванием столбцов и отрисовкой разделительных
|
||||
линий (строки `|---|---|`). На текущий момент таблицы отображаются
|
||||
как обычные nowrap-строки без выравнивания.
|
||||
|
||||
3. **Поддержка кодировок CP1251 и UTF-8.** Автоопределение кодировки
|
||||
по BOM, явное указание через аргумент командной строки (`--encoding cp1251`),
|
||||
возможность переключения кодировки во время просмотра (`F8`).
|
||||
Нужно прежде всего для документов на русском языке; CP866 кодировака уже поддерживается.
|
||||
|
||||
4. **Ускорение рендеринга.** Кэш строк экрана. Оптимизация цикла вывода
|
||||
символов через BIOS WRCHAR (пакетный вывод, DMA).
|
||||
|
||||
---
|
||||
|
||||
*MDView v0.2 · (c) 2026 Петров А.Г.*
|
||||
File diff suppressed because it is too large
Load Diff
+39
-16
@@ -22,25 +22,48 @@ BUILD := $(PROJ_ROOT)/lib/build
|
||||
|
||||
# All libc C modules.
|
||||
LIBC_C := \
|
||||
libc/io/atexit.c libc/io/conio.c libc/io/cprintf.c libc/io/dir.c \
|
||||
libc/io/videomode_raw.c \
|
||||
libc/io/_errno_set.c \
|
||||
libc/io/env.c libc/io/errno.c libc/io/fsdir.c \
|
||||
libc/io/lseek.c libc/io/mouse.c libc/io/open.c \
|
||||
libc/io/read.c libc/io/sleep.c \
|
||||
libc/io/time.c libc/io/posix_time.c libc/io/unlink.c \
|
||||
libc/sys/atexit.c \
|
||||
libc/conio/conio.c \
|
||||
libc/conio/cprintf.c \
|
||||
libc/conio/text_palette.c \
|
||||
libc/io/dir.c \
|
||||
libc/video/videomode_raw.c \
|
||||
libc/video/palette.c \
|
||||
libc/errno/_errno_set.c \
|
||||
libc/env/env.c \
|
||||
libc/errno/errno.c \
|
||||
libc/io/fsdir.c \
|
||||
libc/io/lseek.c \
|
||||
libc/mouse/mouse.c \
|
||||
libc/io/open.c \
|
||||
libc/io/read.c \
|
||||
libc/time/sleep.c \
|
||||
libc/time/time.c \
|
||||
libc/time/posix_time.c \
|
||||
libc/io/unlink.c \
|
||||
libc/io/stat.c \
|
||||
libc/mem/bank_io_w3.c libc/mem/bank_io_w1.c libc/mem/mem_alloc.c \
|
||||
libc/gfx/gfx_core.c libc/gfx/gfx_raw_common.c \
|
||||
libc/gfx/gfx_raw_256.c libc/gfx/gfx_raw_16.c \
|
||||
libc/gfx/gfx_256.c libc/gfx/gfx_16.c \
|
||||
libc/gfx/gfx_font.c libc/gfx/gfx_text_256.c \
|
||||
libc/mem/bank_io_w3.c \
|
||||
libc/mem/bank_io_w1.c \
|
||||
libc/mem/mem_estex.c \
|
||||
libc/mem/mem_bios.c \
|
||||
libc/gfx/gfx_core.c \
|
||||
libc/gfx/gfx_palette.c \
|
||||
libc/gfx/gfx_raw_common.c \
|
||||
libc/gfx/gfx_raw_256.c \
|
||||
libc/gfx/gfx_raw_16.c \
|
||||
libc/gfx/gfx_256.c \
|
||||
libc/gfx/gfx_16.c \
|
||||
libc/gfx/gfx_font.c \
|
||||
libc/gfx/gfx_text_256.c \
|
||||
libc/gfx/gfx_text_16.c \
|
||||
libc/stdio/getchar.c \
|
||||
libc/stdio/putchar.c libc/stdio/puts.c libc/stdio/file.c \
|
||||
libc/stdio/hex_print.c libc/stdio/dec_print.c \
|
||||
libc/stdio/solid_helpers.c \
|
||||
libc/io/solid_compat.c
|
||||
libc/stdio/putchar.c \
|
||||
libc/stdio/puts.c \
|
||||
libc/file/file.c \
|
||||
libc/stdio/hex_print.c \
|
||||
libc/stdio/dec_print.c \
|
||||
libc/string/strlwr.c \
|
||||
libc/string/strupr.c
|
||||
|
||||
# Runtime modules to bundle (pulled by symbol references from libc-using code).
|
||||
# NOTE: runtime/bank.s is NOT bundled — its trampoline depends on the banking
|
||||
|
||||
@@ -58,6 +58,30 @@ char getche(void) __naked
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* getkey — like getch() but exposes BOTH the ASCII value and the
|
||||
* positional scan code, so callers can distinguish extended keys
|
||||
* (arrows, F1..F12, PgUp/PgDn, Home/End, Ins/Del — all of which carry
|
||||
* ASCII == 0 from ESTEX) from plain ASCII keys.
|
||||
*
|
||||
* return = (scan << 8) | ascii
|
||||
*
|
||||
* For plain keys: ascii holds the character, scan holds the positional
|
||||
* code (bit 7 set when Ctrl/Alt/Shift is held).
|
||||
* For extended keys: ascii == 0, scan identifies the key (see KEY_* in
|
||||
* <conio.h>).
|
||||
*/
|
||||
uint16_t getkey(void) __naked
|
||||
{
|
||||
__asm
|
||||
push ix
|
||||
ld c, #0x30 ; ESTEX WAITKEY: A=ASCII, D=scan, E=ASCII
|
||||
rst #0x10
|
||||
pop ix
|
||||
ld e, a ; E = ASCII (defensive: A is the canonical copy)
|
||||
ret ; __sdcccall(1) returns uint16_t in DE
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* ---- putch / cputs: Turbo-C conio convention ---------------------- *
|
||||
* Both APPLY the current text attribute (g_text_attr). When attr is
|
||||
* KEEP_EXIST_ATTR (>0xFF), they short-circuit to the FAST stdio path
|
||||
@@ -332,6 +356,11 @@ char cputs(const char *s) __naked
|
||||
or a, l
|
||||
ret z
|
||||
|
||||
;; IX is callee-saved under SDCC's z80 ABI. We use it as a
|
||||
;; function pointer below (ld ix, #__raw_putch_raw0/1) so save
|
||||
;; the caller's value up front and restore before every ret.
|
||||
push ix
|
||||
|
||||
;; KEEP_EXIST_ATTR? high byte of g_text_attr != 0
|
||||
ld a, (_g_text_attr + 1)
|
||||
or a, a
|
||||
@@ -374,11 +403,13 @@ char cputs(const char *s) __naked
|
||||
_cputs_loop_end:
|
||||
|
||||
call __set_cursor
|
||||
pop ix ; restore caller's IX
|
||||
xor a, a ; return 0
|
||||
ret
|
||||
|
||||
_cputs_fast:
|
||||
call __cputs_pchars
|
||||
pop ix ; restore caller's IX
|
||||
xor a, a ; return 0
|
||||
ret
|
||||
__endasm;
|
||||
@@ -462,6 +493,37 @@ uint16_t wherexy(void) __naked
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* wrchar(uint8_t x, uint8_t y, char ch, uint8_t attr)
|
||||
*
|
||||
* SDCC __sdcccall(1): x in A, y in L (2 uint8 → A, L); ch and attr
|
||||
* packed and pushed on the stack as a single 16-bit value (caller does
|
||||
* `ld hl, #(attr<<8)|ch; push hl`). Layout after CALL:
|
||||
* [SP+0..1] = return address
|
||||
* [SP+2] = ch (low half of pushed pair)
|
||||
* [SP+3] = attr (high half)
|
||||
* Void return → callee-pops the 2 stack-arg bytes via `pop bc` + jp (iy).
|
||||
*/
|
||||
void scroll(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t direction, uint8_t clear) __naked
|
||||
{
|
||||
(void)x; (void)y; (void)w; (void)h; (void)direction; (void)clear;
|
||||
__asm
|
||||
pop iy ; return address
|
||||
ld d, l ; D = row (y)
|
||||
ld e, a ; E = col (x)
|
||||
pop hl ; H = heigth(h), L = width(w)
|
||||
pop bc ; C = direction, B = clear
|
||||
ld a, b ; A = clear(B)
|
||||
ld b, c ; B = direction(C)
|
||||
push ix
|
||||
ld c, #0x55 ; ESTEX SCROLL
|
||||
rst #0x10
|
||||
pop ix
|
||||
jp (iy)
|
||||
__endasm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* wrchar(uint8_t x, uint8_t y, char ch, uint8_t attr)
|
||||
*
|
||||
Vendored
@@ -143,7 +143,8 @@ int fputc(int c, FILE *fp)
|
||||
{
|
||||
if (!fp) { errno = EBADF; return EOF; }
|
||||
if (fp->flags & _F_CONOUT) {
|
||||
return putchar(c);
|
||||
putchar(c);
|
||||
return (int)c;
|
||||
}
|
||||
if (!(fp->flags & _F_WRITE)) { errno = EBADF; return EOF; }
|
||||
uint8_t ch = (uint8_t)c;
|
||||
@@ -175,7 +176,7 @@ int fputs(const char *s, FILE *fp)
|
||||
if (!fp || !s) { errno = EBADF; return EOF; }
|
||||
if (fp->flags & _F_CONOUT) {
|
||||
while (*s) {
|
||||
if (putchar((unsigned char)*s++) == EOF) return EOF;
|
||||
putchar((unsigned char)*s++);;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -239,7 +240,7 @@ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)
|
||||
const char *p = (const char *)ptr;
|
||||
size_t total = size * nmemb;
|
||||
for (size_t i = 0; i < total; i++) {
|
||||
if (putchar((unsigned char)p[i]) == EOF) return i / size;
|
||||
putchar((unsigned char)p[i]);
|
||||
}
|
||||
return nmemb;
|
||||
}
|
||||
+4
-41
@@ -13,7 +13,7 @@
|
||||
* gfx_set_draw_page / get — updates _gfx_addr_base for the new page
|
||||
* gfx_set_bank / get — sets the W3 page byte (0x50..0x5F)
|
||||
* gfx_wait_vsync — EI; HALT until next frame interrupt
|
||||
* gfx_pal_load / gfx_pal_set — BIOS $A4 PIC_SET_PAL wrappers
|
||||
* (palette wrappers live in gfx_palette.c, backed by libc/video/palette.c)
|
||||
*
|
||||
* Shared state (extern from this file):
|
||||
* _gfx_addr_base — 0xC000 for page 0, 0xC140 for page 1. Every
|
||||
@@ -136,43 +136,6 @@ void gfx_wait_vsync(void) __naked
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/* ---- Palette (BIOS $A4 PIC_SET_PAL) ----------------------------- */
|
||||
|
||||
static uint8_t pal_num_;
|
||||
static uint8_t pal_start_;
|
||||
static uint8_t pal_count_;
|
||||
static uint16_t pal_data_;
|
||||
|
||||
void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count,
|
||||
const uint8_t *data)
|
||||
{
|
||||
pal_num_ = pal_num;
|
||||
pal_start_ = start;
|
||||
pal_count_ = count;
|
||||
pal_data_ = (uint16_t)(uintptr_t)data;
|
||||
|
||||
__asm
|
||||
push ix
|
||||
ld a, (_pal_start_)
|
||||
ld e, a ; E = start
|
||||
ld a, (_pal_count_)
|
||||
ld d, a ; D = count (0 → 256)
|
||||
ld hl, (_pal_data_) ; HL = data
|
||||
ld b, #0xFF ; mask
|
||||
ld a, (_pal_num_) ; A = palette number
|
||||
ld c, #0xA4 ; BIOS PIC_SET_PAL
|
||||
rst #0x08
|
||||
pop ix
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void gfx_pal_set(uint8_t pal_num, uint8_t idx,
|
||||
uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
uint8_t entry[4];
|
||||
entry[0] = b;
|
||||
entry[1] = g;
|
||||
entry[2] = r;
|
||||
entry[3] = 0;
|
||||
gfx_pal_load(pal_num, idx, 1, entry);
|
||||
}
|
||||
/* Palette wrappers (gfx_pal_load / gfx_pal_set / gfx_pal_get /
|
||||
* gfx_pal_get_color / gfx_pal_reset) moved to gfx_palette.c — see also
|
||||
* libc/video/palette.c for the shared low-level $A4 / $A6 implementation. */
|
||||
|
||||
+86
-4
@@ -38,6 +38,42 @@
|
||||
char kbhit (void);
|
||||
char getch (void);
|
||||
char getche(void);
|
||||
|
||||
/* Extended-key reader. Returns (scan << 8) | ascii. Plain ASCII keys
|
||||
* have ascii in the low byte; extended keys (arrows / F1..F12 /
|
||||
* PgUp/PgDn / Home / End / Ins / Del) carry ascii == 0 and the
|
||||
* KEY_* code in the high byte. */
|
||||
uint16_t getkey(void);
|
||||
|
||||
/* Scan codes returned in the high byte of getkey() when the low byte
|
||||
* (ASCII) is 0. Empirically verified in MAME — the ProgrammerManual.txt
|
||||
* "positional code" column is misleading; BIOS returns IBM-style codes
|
||||
* for the F-keys and a "5N + numpad-position" pattern for the cursor /
|
||||
* editing keys.
|
||||
*
|
||||
* Verified 2026-06-04 by reading raw getkey() output. */
|
||||
#define KEY_F1 0x3B
|
||||
#define KEY_F2 0x3C
|
||||
#define KEY_F3 0x3D
|
||||
#define KEY_F4 0x3E
|
||||
#define KEY_F5 0x3F
|
||||
#define KEY_F6 0x40
|
||||
#define KEY_F7 0x41
|
||||
#define KEY_F8 0x42
|
||||
#define KEY_F9 0x43
|
||||
#define KEY_F10 0x44
|
||||
#define KEY_F11 0x45 /* not verified */
|
||||
#define KEY_F12 0x46 /* not verified */
|
||||
#define KEY_END 0x51
|
||||
#define KEY_DOWN 0x52
|
||||
#define KEY_PGDN 0x53
|
||||
#define KEY_LEFT 0x54
|
||||
#define KEY_RIGHT 0x56
|
||||
#define KEY_HOME 0x57
|
||||
#define KEY_UP 0x58
|
||||
#define KEY_PGUP 0x59
|
||||
#define KEY_INS 0x50 /* numpad 0; not verified */
|
||||
#define KEY_DEL 0x55 /* numpad 5/.; not verified */
|
||||
char putch (char c);
|
||||
char cputs (const char *s);
|
||||
int cprintf(const char *fmt, ...);
|
||||
@@ -63,6 +99,8 @@ uint8_t wherex (void);
|
||||
uint8_t wherey (void);
|
||||
uint16_t wherexy(void); // high byte = Y, low byte = X coords.
|
||||
|
||||
void scroll(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);
|
||||
|
||||
/* Direct character/attribute screen access (ESTEX $57 / $58).
|
||||
* wrchar — write char + attribute at (x, y); does NOT advance the cursor
|
||||
* and does NOT interpret control characters. Useful for
|
||||
@@ -143,12 +181,56 @@ uint8_t get_putch_raw_mode(void);
|
||||
* Colour order is standard CGA / Borland-conio.h. Constants 0..7 are
|
||||
* usable for both fg and bg; 8..15 are foreground-only. */
|
||||
enum {
|
||||
COLOR_BLACK = 0, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
|
||||
COLOR_RED, COLOR_MAGENTA, COLOR_BROWN, COLOR_LIGHTGRAY,
|
||||
COLOR_DARKGRAY, COLOR_LIGHTBLUE, COLOR_LIGHTGREEN, COLOR_LIGHTCYAN,
|
||||
COLOR_LIGHTRED, COLOR_LIGHTMAGENTA, COLOR_YELLOW, COLOR_WHITE
|
||||
COLOR_BLACK = 0,
|
||||
COLOR_BLUE,
|
||||
COLOR_GREEN,
|
||||
COLOR_CYAN,
|
||||
COLOR_RED,
|
||||
COLOR_MAGENTA,
|
||||
COLOR_BROWN,
|
||||
COLOR_LIGHTGRAY,
|
||||
COLOR_DARKGRAY,
|
||||
COLOR_LIGHTBLUE,
|
||||
COLOR_LIGHTGREEN,
|
||||
COLOR_LIGHTCYAN,
|
||||
COLOR_LIGHTRED,
|
||||
COLOR_LIGHTMAGENTA,
|
||||
COLOR_YELLOW,
|
||||
COLOR_WHITE
|
||||
};
|
||||
#define COLOR_BLINK 0x80u
|
||||
#define COLOR(fg, bg) ((uint8_t)((((bg) & 0x07) << 4) | ((fg) & 0x0F)))
|
||||
|
||||
/* Text-mode palette. The 16 logical CGA colours seen by COLOR(fg, bg)
|
||||
* actually live in four 256-entry hardware palette planes indexed by the
|
||||
* full 8-bit attribute byte:
|
||||
*
|
||||
* TEXT_PAL_PAPER — background colour, non-blink phase
|
||||
* TEXT_PAL_INK — foreground colour, non-blink phase
|
||||
* TEXT_PAL_BLINK_PAPER — background colour during the blink half-cycle
|
||||
* TEXT_PAL_BLINK_INK — foreground colour during the blink half-cycle
|
||||
*
|
||||
* For non-blinking attributes (bit 7 = 0) all four planes display the
|
||||
* same colours, so writing to PAPER/INK is enough. For blinking attrs
|
||||
* (bit 7 = 1) the renderer alternates between the non-blink and blink
|
||||
* planes — that's how flash is implemented in hardware.
|
||||
*
|
||||
* These wrappers add 4 to the plane index and forward to the low-level
|
||||
* <palette.h> API (pal_load / pal_set_color / pal_get / pal_get_color).
|
||||
* Use text_pal_reset() to restore the system default CGA palette. */
|
||||
#define TEXT_PAL_PAPER 0
|
||||
#define TEXT_PAL_INK 1
|
||||
#define TEXT_PAL_BLINK_PAPER 2
|
||||
#define TEXT_PAL_BLINK_INK 3
|
||||
|
||||
void text_pal_load (uint8_t plane, uint8_t start, uint8_t count,
|
||||
const uint8_t *bgr0);
|
||||
void text_pal_set_color(uint8_t plane, uint8_t attr,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
void text_pal_get (uint8_t plane, uint8_t start, uint8_t count,
|
||||
uint8_t *bgr0);
|
||||
void text_pal_get_color(uint8_t plane, uint8_t attr,
|
||||
uint8_t *r, uint8_t *g, uint8_t *b);
|
||||
void text_pal_reset (void);
|
||||
|
||||
#endif
|
||||
|
||||
+15
-7
@@ -16,14 +16,22 @@
|
||||
#ifndef FCNTL_H
|
||||
#define FCNTL_H
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define O_WRONLY 1
|
||||
#define O_RDWR 2
|
||||
#ifndef _STD_SEEK_
|
||||
#define _STD_SEEK_
|
||||
/* constants to be used as 3rd argument for "fseek" function */
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#define O_CREAT 0x040
|
||||
#define O_EXCL 0x080
|
||||
#define O_TRUNC 0x200
|
||||
#define O_APPEND 0x400
|
||||
/* Definition "open flags" */
|
||||
#define O_WRONLY 0x01 /* 0 file write only */
|
||||
#define O_RDONLY 0x02 /* 1 file read only */
|
||||
#define O_RDWR 0x03 /* 1,0 file read/write */
|
||||
#define O_TRUNC 0x04 /* 2 open with truncation */
|
||||
#define O_CREAT 0x08 /* 3 create and open file */
|
||||
#define O_EXCL 0x10 /* 4 exclusive open */
|
||||
#define O_APPEND 0x20 /* 5 to end of file */
|
||||
|
||||
int open (const char *path, int flags);
|
||||
int creat(const char *path, int mode); /* mode arg ignored on Sprinter */
|
||||
|
||||
@@ -145,4 +145,15 @@ void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count,
|
||||
void gfx_pal_set (uint8_t pal_num, uint8_t idx,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
/* Read a contiguous block of entries back from a graphics palette. */
|
||||
void gfx_pal_get (uint8_t pal_num, uint8_t start, uint8_t count,
|
||||
uint8_t *data);
|
||||
|
||||
/* Read one entry into R, G, B pointers (any may be NULL). */
|
||||
void gfx_pal_get_color(uint8_t pal_num, uint8_t idx,
|
||||
uint8_t *r, uint8_t *g, uint8_t *b);
|
||||
|
||||
/* Restore the system default graphics palette (BIOS $A6, type=1). */
|
||||
void gfx_pal_reset(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,23 +47,47 @@
|
||||
* n : 1..255
|
||||
* ret : blk_id (1..255) on success; 0 on failure with errno set.
|
||||
* The id is opaque — pass it to mem_get_page() and mem_free_block(). */
|
||||
uint8_t mem_alloc_pages(uint8_t n);
|
||||
uint8_t mem_alloc_pages_estex(uint8_t n);
|
||||
uint8_t mem_alloc_pages_bios(uint8_t n);
|
||||
|
||||
/* Release a block previously returned by mem_alloc_pages().
|
||||
* On error errno is set (e.g. EINVAL for unknown id). Double-free is
|
||||
* NOT idempotent: the second call sets errno. */
|
||||
void mem_free_block(uint8_t blk_id);
|
||||
void mem_free_block_estex(uint8_t blk_id);
|
||||
void mem_free_block_bios(uint8_t blk_id);
|
||||
|
||||
/* Translate (block, page-index) into a physical page number suitable
|
||||
* for sprinter_page_w1/w2/w3() or the bank_*() helpers below.
|
||||
* blk_id: from mem_alloc_pages()
|
||||
* idx : 0..(n-1)
|
||||
* ret : physical page (1..255) on success; 0 on failure (errno set). */
|
||||
uint8_t mem_get_page(uint8_t blk_id, uint8_t idx);
|
||||
uint8_t mem_get_page_bios(uint8_t blk_id, uint8_t idx);
|
||||
|
||||
/* Query the EMM allocator state. Both pointers must be non-NULL.
|
||||
* Cannot fail (no error path). */
|
||||
void mem_info(uint16_t *total, uint16_t *free_pages);
|
||||
void mem_info_estex(uint16_t *total, uint16_t *free_pages);
|
||||
void mem_info_bios(uint16_t *total, uint16_t *free_pages);
|
||||
|
||||
#define MEM_MANAGE_MODE_BIOS
|
||||
|
||||
#ifdef MEM_MANAGE_MODE_ESTEX
|
||||
|
||||
#define mem_alloc_pages mem_alloc_pages_estex
|
||||
#define mem_free_block mem_free_block_estex
|
||||
#define mem_info mem_info_estex
|
||||
|
||||
#define mem_get_page mem_get_page_bios
|
||||
|
||||
#elif defined MEM_MANAGE_MODE_BIOS
|
||||
|
||||
#define mem_alloc_pages mem_alloc_pages_bios
|
||||
#define mem_free_block mem_free_block_bios
|
||||
#define mem_info mem_info_bios
|
||||
|
||||
#define mem_get_page mem_get_page_bios
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
* Far-page accessors via window 3 (base 0xC000, port 0xE2)
|
||||
|
||||
@@ -30,7 +30,7 @@ int vprintf(const char *, va_list);
|
||||
int vsprintf(char *, const char *, va_list);
|
||||
|
||||
/* puts / putchar / getchar — overridden by our libc to use ESTEX. */
|
||||
int puts (const char *);
|
||||
char puts (const char *);
|
||||
int putchar(int);
|
||||
int getchar(void);
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* solid_compat.c — Solid-C compatibility helpers that need real code
|
||||
* (rather than just header macros).
|
||||
*/
|
||||
|
||||
#include <sprinter_compat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
char *strlwr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
while (*p) {
|
||||
if (*p >= 'A' && *p <= 'Z') *p += 'a' - 'A';
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
char *strupr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
while (*p) {
|
||||
if (*p >= 'a' && *p <= 'z') *p -= 'a' - 'A';
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* div() comes from SDCC's z80.lib. */
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* mem_alloc_pages / mem_free_block / mem_get_page / mem_info — ESTEX EMM
|
||||
* wrappers for explicit 16 KB-page allocation.
|
||||
*
|
||||
* ESTEX $3C INFOMEM → HL=total pages, BC=free pages
|
||||
* ESTEX $3D GETMEM B=npages → A=block id, CF=err
|
||||
* ESTEX $3E FREEMEM A=block id → CF=err
|
||||
* BIOS $C4 EMM_GETPAGE A=blk, B=idx → A=physical page CF=err
|
||||
*
|
||||
* Pattern: every RST 10h / RST 8 is bracketed with push/pop IX because
|
||||
* ESTEX/BIOS clobber it and the C caller uses it as a frame pointer.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sprinter_mem.h>
|
||||
|
||||
/*
|
||||
* Allocate `n` contiguous 16-KB physical pages from the EMM pool.
|
||||
*
|
||||
* in: n — 1..255 (number of pages requested).
|
||||
* out: blk_id (1..255) on success; 0 on failure with errno set.
|
||||
*
|
||||
* The returned block id is opaque — pass it to mem_get_page() to obtain
|
||||
* each physical-page number, and to mem_free_block() when done. Block
|
||||
* ids start at 1; id 0 is reserved as the "allocation failed" sentinel.
|
||||
*/
|
||||
uint8_t mem_alloc_pages(uint8_t n) __naked
|
||||
{
|
||||
(void)n;
|
||||
__asm
|
||||
;; SDCC single-uint8 arg → A on entry; ESTEX GETMEM wants n in B.
|
||||
push ix
|
||||
ld b, a
|
||||
ld c, #0x3D ; ESTEX GETMEM
|
||||
rst #0x10
|
||||
pop ix
|
||||
jr c, _alloc_fail
|
||||
ret ; CF=0 → A = blk_id, return as uint8 in A
|
||||
_alloc_fail:
|
||||
call __errno_set ; CF=1 → A = ESTEX errcode
|
||||
xor a, a ; return 0 = failure sentinel
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a block previously returned by mem_alloc_pages().
|
||||
*
|
||||
* in: blk_id (1..255).
|
||||
* out: void; on ESTEX error errno is set (e.g. EINVAL for unknown id).
|
||||
*
|
||||
* Idempotent guarantees are NOT provided — freeing the same block twice
|
||||
* sets errno on the second call. Caller is responsible for tracking
|
||||
* ownership.
|
||||
*/
|
||||
void mem_free_block(uint8_t blk_id) __naked
|
||||
{
|
||||
(void)blk_id;
|
||||
__asm
|
||||
;; SDCC single-uint8 arg → A on entry.
|
||||
push ix
|
||||
ld c, #0x3E ; ESTEX FREEMEM
|
||||
rst #0x10
|
||||
pop ix
|
||||
ret nc ; CF=0 → success
|
||||
jp __errno_set ; CF=1 → A = ESTEX errcode; tail-call helper
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a (block, page-index) pair into a physical 16-KB page number,
|
||||
* suitable for OUT to PORT_PAGE_W1/W2/W3 or for bank_*() helpers.
|
||||
*
|
||||
* in: blk_id — id returned by mem_alloc_pages().
|
||||
* idx — 0..(n-1), where n was the count passed to alloc.
|
||||
* out: physical page number (1..255) on success;
|
||||
* 0 on failure with errno set (invalid block or idx out of range).
|
||||
*/
|
||||
uint8_t mem_get_page(uint8_t blk_id, uint8_t idx) __naked
|
||||
{
|
||||
(void)blk_id; (void)idx;
|
||||
__asm
|
||||
;; 2-arg uint8/uint8: blk_id → A, idx → L.
|
||||
push ix
|
||||
ld b, l ; BIOS wants idx in B
|
||||
;; A still has blk_id
|
||||
ld c, #0xC4 ; BIOS EMM_GETPAGE
|
||||
rst #0x08
|
||||
pop ix
|
||||
ret nc ; CF=0 → A = phys page (return value)
|
||||
;; CF=1 → A = errcode; set errno, return 0 as sentinel.
|
||||
call __errno_set
|
||||
xor a, a
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the EMM allocator about its current state.
|
||||
*
|
||||
* *total ← number of 16-KB physical pages installed in the system
|
||||
* *free_pages ← number currently available for allocation
|
||||
*
|
||||
* Both pointers must be non-NULL writeable uint16_t locations.
|
||||
* No error path: ESTEX INFOMEM always succeeds.
|
||||
*/
|
||||
void mem_info(uint16_t *total, uint16_t *free_pages) __naked
|
||||
{
|
||||
(void)total; (void)free_pages;
|
||||
__asm
|
||||
;; HL = total ptr, DE = free_pages ptr on entry.
|
||||
;; RST 10 clobbers both — stash on the stack across the call.
|
||||
push ix
|
||||
push hl ; later [SP+2] = total_ptr
|
||||
push de ; TOS [SP+0] = free_pages_ptr
|
||||
|
||||
ld c, #0x3C ; ESTEX INFOMEM → HL = total, BC = free
|
||||
rst #0x10
|
||||
|
||||
pop de ; DE = free_pages_ptr
|
||||
ld a, c
|
||||
ld (de), a
|
||||
inc de
|
||||
ld a, b
|
||||
ld (de), a ; *free_pages = BC
|
||||
|
||||
pop de ; DE = total_ptr
|
||||
ld a, l
|
||||
ld (de), a
|
||||
inc de
|
||||
ld a, h
|
||||
ld (de), a ; *total = HL
|
||||
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
@@ -17,13 +17,7 @@ int getchar(void) __naked
|
||||
ld c, #0x30 ; ESTEX WAITKEY
|
||||
rst #0x10
|
||||
pop ix
|
||||
ld a, e ; E = ASCII (already the low byte of our return DE)
|
||||
or a, a
|
||||
jr Z, no_ascii
|
||||
ld d, #0
|
||||
ret
|
||||
no_ascii:
|
||||
ld de, #-1
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
+6
-14
@@ -19,23 +19,15 @@ int putchar(int c) __naked
|
||||
{
|
||||
(void)c;
|
||||
__asm
|
||||
ld a, l ; SDCC __sdcccall(1) int → HL
|
||||
push ix
|
||||
ld a, l
|
||||
cp #0x0A
|
||||
jr nz, _pc_emit
|
||||
ld a, #0x0D ; CR before LF
|
||||
push af
|
||||
jr nz, cputc
|
||||
call cputc
|
||||
ld a, #0x0D
|
||||
cputc:
|
||||
ld c, #0x5B
|
||||
rst #0x10
|
||||
pop af
|
||||
ld a, #0x0A
|
||||
_pc_emit:
|
||||
push af
|
||||
ld c, #0x5B
|
||||
rst #0x10
|
||||
pop af
|
||||
pop ix
|
||||
ld e, a
|
||||
ld e, l
|
||||
ld d, #0
|
||||
ret
|
||||
__endasm;
|
||||
|
||||
+21
-34
@@ -14,17 +14,11 @@
|
||||
* - Avoid trailing PUTCHAR after PCHARS — empirically that sometimes
|
||||
* drops the next char. Embed the line ending inside the PCHARS
|
||||
* buffer instead.
|
||||
* - Strings longer than the buffer fall back to per-char putchar so
|
||||
* we never silently truncate.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PUTS_BUF_SIZE 256 /* body bytes before CR expansion */
|
||||
|
||||
static char puts_buf[PUTS_BUF_SIZE + 3]; /* +3 for trailing CR LF NUL */
|
||||
|
||||
static void pchars(const char *s) __naked
|
||||
{
|
||||
(void)s;
|
||||
@@ -37,33 +31,26 @@ static void pchars(const char *s) __naked
|
||||
__endasm;
|
||||
}
|
||||
|
||||
int puts(const char *s)
|
||||
char puts(const char *s) __naked
|
||||
{
|
||||
uint16_t n = 0;
|
||||
uint16_t i = 0;
|
||||
|
||||
while (s[i] && n < PUTS_BUF_SIZE - 1) {
|
||||
char c = s[i++];
|
||||
if (c == '\n') {
|
||||
puts_buf[n++] = '\r';
|
||||
puts_buf[n++] = '\n';
|
||||
} else {
|
||||
puts_buf[n++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (s[i]) {
|
||||
/* Overflow — char-by-char fallback so we never truncate. */
|
||||
for (uint16_t k = 0; s[k]; k++)
|
||||
putchar((unsigned char)s[k]);
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
puts_buf[n++] = '\r';
|
||||
puts_buf[n++] = '\n';
|
||||
puts_buf[n] = 0;
|
||||
|
||||
pchars(puts_buf);
|
||||
return 0;
|
||||
(void)s;
|
||||
__asm
|
||||
puts_:
|
||||
ld a, (hl)
|
||||
or a
|
||||
jr z, fin_
|
||||
push hl
|
||||
ld l, a
|
||||
ld h, #0
|
||||
call _putchar
|
||||
pop hl
|
||||
inc hl
|
||||
jp puts_
|
||||
;
|
||||
fin_:
|
||||
ld l, #0x0A
|
||||
ld h, #0
|
||||
call _putchar
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* solid_helpers.c — small Solid-C compatibility helpers.
|
||||
*
|
||||
* dec8 / dec16 / dec32 / hex8 / hex16 / hex32 are in dec_hex.c (compact
|
||||
* asm port from solid-c's STDLIB.ASM, ~150 bytes total — vs ~3-5 KB if
|
||||
* routed through printf). This file now only holds gets().
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* ---- gets — dangerous but Solid-C provides it ---------------------- */
|
||||
char *gets(char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
int c;
|
||||
for (;;) {
|
||||
c = getchar();
|
||||
if (c == EOF) {
|
||||
if (i == 0) return 0;
|
||||
break;
|
||||
}
|
||||
if (c == '\n' || c == '\r') break;
|
||||
buf[i++] = (char)c;
|
||||
}
|
||||
buf[i] = 0;
|
||||
return buf;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* solid_compat.c — Solid-C compatibility helpers that need real code
|
||||
* (rather than just header macros).
|
||||
*
|
||||
* CP866 Cyrillic support: strlwr/strupr handle uppercase/lowercase
|
||||
* conversion for both Latin and Cyrillic characters in CP866 code page
|
||||
* (bytes 0x80–0xFF).
|
||||
*/
|
||||
|
||||
#include <sprinter_compat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
char *strlwr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
while (*p) {
|
||||
if ((*p >= 'A' && *p <= 'Z') || (*p >= 0x80 && *p <= 0x8F)) *p += 'a' - 'A';
|
||||
else if ((*p >= 0x90 && *p <= 0x9F)) *p += 0x50;
|
||||
else if ((*p == 0xF0)) *p = 0xF1;
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* solid_compat.c — Solid-C compatibility helpers that need real code
|
||||
* (rather than just header macros).
|
||||
*
|
||||
* CP866 Cyrillic support: strlwr/strupr handle uppercase/lowercase
|
||||
* conversion for both Latin and Cyrillic characters in CP866 code page
|
||||
* (bytes 0x80–0xFF).
|
||||
*/
|
||||
|
||||
#include <sprinter_compat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
char *strupr(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
while (*p) {
|
||||
if ((*p >= 'a' && *p <= 'z') || (*p >= 0xA0 && *p <= 0xAF)) *p -= 'a' - 'A';
|
||||
else if ((*p >= 0xE0 && *p <= 0xEF)) *p -= 0x50;
|
||||
else if ((*p == 0xF1)) *p = 0xF0;
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := argv
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := assrtest
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := attrprob
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -8,4 +8,4 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := banked
|
||||
MEMORY := huge
|
||||
EXTRA_FLAGS := --bank 1=bank1.c --bank 2=bank2.c
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -9,4 +9,4 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := bankedbg
|
||||
MEMORY := big
|
||||
EXTRA_FLAGS := --bank 1=bank1.c --bank 2=bank2.c
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -15,3 +15,17 @@ void bank1_func(int x) __banked
|
||||
putchar('0' + x % 10);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void bank1_func2(int x) __banked
|
||||
{
|
||||
(void)x;
|
||||
puts("BANK1-2: hello from a banked function (W1)!");
|
||||
puts("BANK1-2: 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');
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <stdint.h>
|
||||
#include <sprinter.h>
|
||||
|
||||
void bank1_func2(int x) __banked;
|
||||
|
||||
void bank2_func(int x) __banked
|
||||
{
|
||||
(void)x;
|
||||
@@ -15,4 +17,6 @@ void bank2_func(int x) __banked
|
||||
putchar('0' + (x / 10) % 10);
|
||||
putchar('0' + x % 10);
|
||||
putchar('\n');
|
||||
|
||||
bank1_func2(10);
|
||||
}
|
||||
@@ -9,4 +9,4 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := banklocl
|
||||
MEMORY := huge
|
||||
EXTRA_FLAGS := --bank 1=bank1.c --mkexe -p --mkexe 0
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -3,4 +3,4 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := cat
|
||||
EXTRA_DATA := test.txt
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := conio
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := conio2
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := dec_test
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := errno
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := filetest
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -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;
|
||||
}
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_d16
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_dbuf
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_demo
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_mous
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := gfx_text
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := hello
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -18,7 +18,7 @@ int main(void)
|
||||
{
|
||||
errno = -1;
|
||||
int16_t a0 = 0, a1 = 0;
|
||||
a0 = get_text_attr();
|
||||
a0 = get_text_attr();
|
||||
|
||||
uint8_t vMode = get_videotextmode();
|
||||
set_videotextmode(TEXT_MODE_80x32);
|
||||
@@ -52,7 +52,7 @@ int main(void)
|
||||
|
||||
/* 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",
|
||||
cprintf("a0=%d a1=%d now=%d errno=%d\n\r",
|
||||
a0, a1, get_text_attr(), errno);
|
||||
#ifdef DEBUG_RT
|
||||
printf("w2_self_allocated = %u\n", w2_self_allocated);
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := ls
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := malloc
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := mem_test
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -16,6 +16,8 @@
|
||||
* 5. Free the block, show the free-page count again.
|
||||
*/
|
||||
|
||||
uint32_t buff[256];
|
||||
|
||||
static void show_mem(const char *label)
|
||||
{
|
||||
uint16_t total, free_pages;
|
||||
@@ -28,6 +30,13 @@ int main(void)
|
||||
{
|
||||
puts("Sprinter page allocator demo");
|
||||
puts("");
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
// printf("mem_io_ports_test() = 0x%02X\n", mem_io_ports_test());
|
||||
printf("buff size (sizeof) = %u\n", sizeof(buff));
|
||||
printf("buff size one element (sizeof) = %u\n", sizeof(buff[0]));
|
||||
printf("buff first element = %u\n", buff[0]);
|
||||
printf("buff last element = %u\n", buff[(sizeof(buff) / sizeof(buff[0])) - 1]);
|
||||
|
||||
show_mem("before:");
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := mouse
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <conio.h>
|
||||
#include <mouse.h>
|
||||
|
||||
mouse_state_t st;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
|
||||
@@ -29,7 +31,6 @@ int main(void)
|
||||
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 =
|
||||
@@ -41,11 +42,13 @@ int main(void)
|
||||
mouse_set_sensitivity(sens_x, sens_y);
|
||||
int sens_dirty = 1;
|
||||
|
||||
st.x = st.y = 0; st.buttons = 0;
|
||||
|
||||
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 ",
|
||||
printf("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,
|
||||
@@ -57,19 +60,19 @@ int main(void)
|
||||
}
|
||||
if (sens_dirty) {
|
||||
gotoxy(0, 8);
|
||||
cprintf("sensitivity horz=%3u vert=%3u ", sens_x, sens_y);
|
||||
printf("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);
|
||||
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();
|
||||
@@ -4,4 +4,4 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := openenv
|
||||
MEMORY := big
|
||||
EXTRA_FLAGS :=
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := ptime
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := rt_test
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -3,4 +3,4 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := seek
|
||||
EXTRA_DATA := big.txt
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -1,3 +1,3 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := stattest
|
||||
include $(PROJ_ROOT)/examples/example.mk
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user