libbgi: скролл-примитивы + --w3 + отчёт раскладки памяти
Скролл региона video->video (неактивная страница -> активная, банк 0x50: копия = скролл + heal цели): - gfx_scroll_h / _bgi_scroll_rows_raw — горизонтальный, построчно без страйдов (~54Т/строку), DI/EI бандами по 16 строк, h=0=>256; - gfx_scroll_v / _bgi_scroll_cols_raw — верт. И/ИЛИ гориз. за один проход без буфера (колонка = accel-burst LD A,A, STOP между read/write делает промежуточный OUT Port_Y безопасным), банды по 16 колонок; - _gfx_addr_shadow_base (адрес неактивной страницы) + gfx_rect_t. Пример examples/scroll. check_banks.py + sprinter-cc: отчёт раскладки памяти для ЛЮБОЙ модели (W1/W2 код/данные, остаток кучи/стека, W3 при --w3, банки при --bank), не только при --bank. Док docs/memory-management.md §10. --w3 (резидентный код окна W3) + сопутствующее: crt0_banked W3_RESIDENT, mkexe -W, tests/w3probe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+71
-10
@@ -15,8 +15,8 @@
|
||||
# 0xA2 to auto-detect whether DSS already mapped W2
|
||||
# (program > 16 KB) or whether we need to allocate
|
||||
# it ourselves (program < 16 KB). Covers 0..30 KB.
|
||||
# big: tiny + banked code in W1 [TODO]
|
||||
# huge: small + banked code in W3 [TODO]
|
||||
# big: tiny + banked code in W1
|
||||
# huge: small + banked code in W3
|
||||
# manual: explicit via --memory-manual / --code-loc / --data-loc
|
||||
# --memory-manual SPEC placement spec, only with --memory manual.
|
||||
# SPEC = comma-separated KEY=VAL list:
|
||||
@@ -33,6 +33,18 @@
|
||||
# -Wl FLAG extra linker flag (repeatable)
|
||||
# --bank N=FILE.c compile FILE.c as bank N; repeatable; pulls crt0_banked
|
||||
# automatically and adds -Wl-b_BANKN=0x{N}C000
|
||||
# --w3 FILE.c place FILE.c resident in window 3 (0xC000), called
|
||||
# DIRECTLY (no trampoline). Repeatable. Defaults to
|
||||
# --memory small; works in tiny|small|big|huge. DSS maps
|
||||
# all image pages incl. W3. Compiled with --codeseg/
|
||||
# --constseg W3CODE (writable statics stay in W2). In huge
|
||||
# the resident page SHARES W3 with trampoline banks: crt0
|
||||
# captures/restores it (W3_RESIDENT), mkexe gets -W.
|
||||
# Rules: W3 code must NOT switch the W3 page; W1/W2 code that
|
||||
# swaps W3 to another page must restore it; no writable data
|
||||
# belongs in W3 (code + rodata only). From a __banked
|
||||
# context the resident W3 code is unreachable (but resident
|
||||
# -> __banked via the W1 trampoline is fine).
|
||||
# --mkexe FLAG extra mkexe flag (repeatable; e.g. --mkexe -p --mkexe 0)
|
||||
# --max-allocs N SDCC --max-allocs-per-node (default: 100000 — smaller/
|
||||
# faster code at the cost of compile time; pass a lower
|
||||
@@ -88,6 +100,11 @@ SOURCES=()
|
||||
LD_EXTRA=()
|
||||
MKEXE_EXTRA=()
|
||||
BANK_SPECS=() # entries like "1=engine.c"
|
||||
W3_SPECS=() # entries like "mod.c" — резидентные модули окна W3 (--w3)
|
||||
W3_RELS=() # заполняется при компиляции W3-модулей
|
||||
W3_LD_FLAGS=() # -Wl-b_W3CODE=0xC000, если есть --w3
|
||||
USER_SET_MEMORY="" # непусто, если --memory задан явно (для --w3 авто-small)
|
||||
W3_RESIDENT_HUGE=0 # 1, если --w3 в режиме huge (резидент делит W3 с банками)
|
||||
MAX_ALLOCS="100000" # sdcc --max-allocs-per-node; дефолт 100000 — агрессивная
|
||||
# регистровая аллокация (медленнее компиляция, меньше/
|
||||
# быстрее код; как fast-сборки библиотек). --max-allocs N
|
||||
@@ -112,8 +129,9 @@ while [[ $# -gt 0 ]]; do
|
||||
-S) STACK_ADDR="$2"; shift 2;;
|
||||
--code-loc) USER_CODE_LOC="$2"; shift 2;;
|
||||
--data-loc) USER_DATA_LOC="$2"; shift 2;;
|
||||
--memory) MEMORY_MODE="$2"; shift 2;;
|
||||
--memory) MEMORY_MODE="$2"; USER_SET_MEMORY=1; shift 2;;
|
||||
--memory-manual) MEMORY_MANUAL="$2"; shift 2;;
|
||||
--w3) W3_SPECS+=("$2"); shift 2;;
|
||||
--stack-size) STACK_SIZE="$2"; shift 2;;
|
||||
-Wl) LD_EXTRA+=("$2"); shift 2;;
|
||||
--bank) BANK_SPECS+=("$2"); shift 2;;
|
||||
@@ -132,6 +150,24 @@ done
|
||||
[[ -z "$OUT" ]] && { echo "sprinter-cc: -o NAME is required" >&2; exit 1; }
|
||||
[[ ${#SOURCES[@]} -eq 0 ]] && { echo "sprinter-cc: no input files" >&2; exit 1; }
|
||||
|
||||
# ------- --w3: резидентный код окна W3 (подход A) ----------------------------
|
||||
# W3-модули едут в область W3CODE @0xC000 и вызываются напрямую (без
|
||||
# трамплинов). Работает поверх small-лейаута: main-код с 0x4100 (W1/W2),
|
||||
# W3 свободно, DSS маппит все страницы образа сам (проверено tests/w3probe).
|
||||
# --w3 подразумевает small; с huge несовместим (там W3 занят банками).
|
||||
if [[ ${#W3_SPECS[@]} -gt 0 ]]; then
|
||||
[[ -z "$USER_SET_MEMORY" ]] && MEMORY_MODE="small" # --w3 → small по умолчанию
|
||||
case "$MEMORY_MODE" in
|
||||
tiny|small|big|huge) : ;; # поддержаны (huge — резидент делит W3 с банками)
|
||||
*) echo "sprinter-cc: --w3 поддержан для tiny|small|big|huge (дано: $MEMORY_MODE)" >&2; exit 1;;
|
||||
esac
|
||||
# huge: резидентный W3-код (0xC000, HOME) сосуществует с трамплин-банками
|
||||
# W3 — crt0_banked захватывает резидентную страницу и возвращает её
|
||||
# дефолтом после загрузки банков (см. crt0_banked.s, W3_RESIDENT).
|
||||
W3_RESIDENT_HUGE=0
|
||||
[[ "$MEMORY_MODE" == "huge" ]] && W3_RESIDENT_HUGE=1
|
||||
fi
|
||||
|
||||
# ------- BGI graphics driver selection (--gfx) -------------------------------
|
||||
# graphics.h — mode-agnostic слой; конкретный видеорежим задаёт driver-
|
||||
# архив. Одновременно только один. drv16 пока не реализован.
|
||||
@@ -186,7 +222,8 @@ case "$MEMORY_MODE" in
|
||||
huge)
|
||||
# small layout + banked code in W3. crt0_banked auto-detects W2
|
||||
# the same way crt0_small does, then loads banks from the .EXE.
|
||||
MODE_CODE_LOC="0x4100"; MODE_DATA_LOC="0x8000"
|
||||
# MODE_CODE_LOC="0x4100"; MODE_DATA_LOC="0x8000"
|
||||
MODE_CODE_LOC="0x4100"; MODE_DATA_LOC="0"
|
||||
;;
|
||||
manual)
|
||||
# Defaults if SPEC omits a key.
|
||||
@@ -280,6 +317,7 @@ asm_runtime() {
|
||||
local prefix=""
|
||||
[[ $DEBUG_RT -eq 1 ]] && prefix+="DEBUG_RT = 1"$'\n'
|
||||
[[ $BANK_W1 -eq 1 ]] && prefix+="BANK_W1 = 1"$'\n'
|
||||
[[ $W3_RESIDENT_HUGE -eq 1 ]] && prefix+="W3_RESIDENT = 1"$'\n'
|
||||
if [[ -n "$prefix" ]]; then
|
||||
local patched="$WORK/$(basename "$src" .s)_patched.s"
|
||||
{ printf "%s" "$prefix"; cat "$src"; } > "$patched"
|
||||
@@ -305,9 +343,14 @@ if [[ -n "$STACK_SIZE" ]]; then
|
||||
printf " .module sprinter_heap_top\n ___sdcc_heap_end = 0x%04X\n .globl ___sdcc_heap_end\n" \
|
||||
"$_heap_top" > "$WORK/heap_top.s"
|
||||
HEAP_TOP_SRC="$WORK/heap_top.s"
|
||||
[[ $VERBOSE -eq 1 ]] && echo " heap_top: custom HEAP_TOP=$(printf '0x%04X' $_heap_top) (stack reserve $_stack_sz bytes)"
|
||||
HEAP_TOP_VAL=$(printf '0x%04X' "$_heap_top")
|
||||
[[ $VERBOSE -eq 1 ]] && echo " heap_top: custom HEAP_TOP=$HEAP_TOP_VAL (stack reserve $_stack_sz bytes)"
|
||||
else
|
||||
HEAP_TOP_SRC="$RUNTIME/heap_top.s"
|
||||
# Дефолт из runtime/heap_top.s (для отчёта раскладки) — обычно 0xBB00.
|
||||
HEAP_TOP_VAL=$(grep -oiE '___sdcc_heap_end[[:space:]]*=[[:space:]]*0x[0-9A-Fa-f]+' "$RUNTIME/heap_top.s" \
|
||||
| grep -oiE '0x[0-9A-Fa-f]+' | head -1)
|
||||
HEAP_TOP_VAL="${HEAP_TOP_VAL:-0xBB00}"
|
||||
fi
|
||||
run "$SDASZ80" -o "$HEAP_TOP_REL" "$HEAP_TOP_SRC"
|
||||
|
||||
@@ -322,6 +365,20 @@ for src in "${SOURCES[@]}"; do
|
||||
USER_RELS+=("$rel")
|
||||
done
|
||||
|
||||
# 2b. --w3 resident modules → .rel. --codeseg/--constseg W3CODE кладёт код
|
||||
# и rodata в W3 (0xC000); --dataseg НЕ трогаем — писучие статики
|
||||
# остаются в обычном _DATA (W2). Прямые вызовы, без трамплинов.
|
||||
if [[ ${#W3_SPECS[@]} -gt 0 ]]; then
|
||||
for src in "${W3_SPECS[@]}"; do
|
||||
rel="$WORK/w3_$(basename "$src" .c).rel"
|
||||
run "$SDCC" "${CC_FLAGS[@]}" --codeseg W3CODE --constseg W3CODE \
|
||||
-c -o "$rel" "$src"
|
||||
W3_RELS+=("$rel")
|
||||
done
|
||||
W3_LD_FLAGS+=("-Wl-b_W3CODE=0xC000")
|
||||
[[ $VERBOSE -eq 1 ]] && echo " w3: ${#W3_SPECS[@]} module(s) resident @0xC000 (direct call)"
|
||||
fi
|
||||
|
||||
# 3. bank infrastructure — required whenever crt0_banked is in play.
|
||||
# Always assemble bank.s for _bank_pages + the bcall/bjump trampolines.
|
||||
# If the user did not pass any --bank, generate a tiny stub providing
|
||||
@@ -369,6 +426,7 @@ IHX="$WORK/$(basename "$OUT" .exe).ihx"
|
||||
LINK_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size
|
||||
--code-loc "$CODE_LOC" --data-loc "$DATA_LOC")
|
||||
LINK_FLAGS+=("${BANK_LD_FLAGS[@]}")
|
||||
LINK_FLAGS+=("${W3_LD_FLAGS[@]}")
|
||||
for f in "${LD_EXTRA[@]}"; do LINK_FLAGS+=("$f"); done
|
||||
# libsprinter.lib via -l/-L (sdcc passes -lsprinter through to sdldz80).
|
||||
#
|
||||
@@ -379,12 +437,12 @@ for f in "${LD_EXTRA[@]}"; do LINK_FLAGS+=("$f"); done
|
||||
# the warning is just noise. In verbose mode show everything.
|
||||
if [[ $VERBOSE -eq 1 ]]; then
|
||||
run "$SDCC" "${LINK_FLAGS[@]}" -o "$IHX" \
|
||||
"$CRT0_REL" "$HEAP_TOP_REL" "${USER_RELS[@]}" "${BANK_RELS[@]}" \
|
||||
"$CRT0_REL" "$HEAP_TOP_REL" "${USER_RELS[@]}" "${BANK_RELS[@]}" "${W3_RELS[@]}" \
|
||||
"-L$LIB_DIR" "${GFX_LD[@]}" "$LIBC_LD"
|
||||
else
|
||||
# Drop the warning line + its two follow-up "Library:" lines.
|
||||
run "$SDCC" "${LINK_FLAGS[@]}" -o "$IHX" \
|
||||
"$CRT0_REL" "$HEAP_TOP_REL" "${USER_RELS[@]}" "${BANK_RELS[@]}" \
|
||||
"$CRT0_REL" "$HEAP_TOP_REL" "${USER_RELS[@]}" "${BANK_RELS[@]}" "${W3_RELS[@]}" \
|
||||
"-L$LIB_DIR" "${GFX_LD[@]}" "$LIBC_LD" 2>&1 \
|
||||
| awk '
|
||||
/^\?ASlink-Warning-Definition of public symbol/ { skip = 3 }
|
||||
@@ -393,9 +451,11 @@ else
|
||||
'
|
||||
fi
|
||||
|
||||
# Quick bank-size check (only meaningful if there are banks).
|
||||
if [[ ${#BANK_SPECS[@]} -gt 0 ]] && [[ -f "${IHX%.ihx}.map" ]]; then
|
||||
python3 "$CHECK_BANKS" "${IHX%.ihx}.map" || true
|
||||
# Отчёт по раскладке памяти + проверка лимитов — для ЛЮБОЙ модели памяти
|
||||
# (сколько свободно в W1/W2, W3 при --w3, и в каждом банке при --bank).
|
||||
if [[ -f "${IHX%.ihx}.map" ]]; then
|
||||
python3 "$CHECK_BANKS" "${IHX%.ihx}.map" \
|
||||
--mode "$MEMORY_MODE" --heap-top "$HEAP_TOP_VAL" --stack "$STACK_ADDR" || true
|
||||
fi
|
||||
|
||||
# 5. mkexe → .exe. In BIG mode tell mkexe banks live at 0x4000 (W1).
|
||||
@@ -404,6 +464,7 @@ fi
|
||||
MK_PREFIX=()
|
||||
[[ $VERBOSE -eq 1 ]] && MK_PREFIX+=(-v)
|
||||
[[ $BANK_W1 -eq 1 ]] && MK_PREFIX+=(-B 0x4000)
|
||||
[[ $W3_RESIDENT_HUGE -eq 1 ]] && MK_PREFIX+=(-W)
|
||||
MK_PREFIX+=("${MKEXE_EXTRA[@]}")
|
||||
MK_PREFIX+=(-L "$LOAD_ADDR" -E "$ENTRY_ADDR" -S "$STACK_ADDR" -o "$OUT")
|
||||
run "$MKEXE" "${MK_PREFIX[@]}" "$IHX"
|
||||
|
||||
Reference in New Issue
Block a user