From 52636a5d6e97e6d235227579534778bf0dbfb49d Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Thu, 9 Jul 2026 14:18:33 +0300 Subject: [PATCH] =?UTF-8?q?libbgi:=20=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA=D1=83=20BGI?= =?UTF-8?q?=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=83?= =?UTF-8?q?=D1=8E=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=83=20+=20=D1=82=D0=B5=D1=81=D1=82=20=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B9=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Графика вынесена из libc/ в новую библиотеку libbgi/: - common/ — mode-agnostic математика и состояние (один исходник, .rel попадает в оба driver-архива); - bgi256/ + bgi16/ — mode-specific leaf'ы (raw-плот/чтение/спаны); - include/ — graphics.h + gfx.h; _bgi.h — внутренний заголовок. Собираются lib/bgi256.lib (и bgi16.lib в Фазе 2); выбор режима линковкой через sprinter-cc --gfx 256|16. libc/ теперь без графики. tests/bgi_img — тест спрайтов getimage/putimage/imagesize (5 операций COPY/XOR/OR/AND/NOT + XOR-round-trip + self-check imagesize). Проверен автотестом в MAME. Примечание: make size-check пока красный (gfx_dbuf/gfx_demo выросли после реорга) — закрыть по завершении миграции libbgi. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 4 +- CLAUDE.md | 23 +- Makefile | 13 +- app.mk | 7 +- bin/sprinter-cc | 5 +- docs/libc-headers.md | 14 +- docs/libc-reference.md | 33 ++- docs/libc-roadmap.md | 2 +- docs/size_baseline.tsv | 1 + lib/Makefile | 104 --------- libbgi/Makefile | 79 +++++++ libbgi/_bgi.h | 197 ++++++++++++++++++ .../bgi16/_bgi_clear_raw.c | 6 +- .../bgi16/_bgi_hspan_raw.c | 6 +- .../bgi16/_bgi_plot_raw.c | 6 +- .../bgi16/_bgi_vspan_raw.c | 6 +- {libc/gfx => libbgi/bgi16}/_gfx_g16_state.c | 2 +- {libc/gfx => libbgi/bgi16}/_gfx_hfill16.c | 2 +- {libc/gfx => libbgi/bgi16}/_gfx_rmw16.c | 2 +- .../bgi256/_bgi_clear_raw.c | 6 +- .../bgi256/_bgi_hspan_raw.c | 6 +- .../drv256 => libbgi/bgi256}/_bgi_mode_set.c | 6 +- .../bgi256/_bgi_plot_raw.c | 6 +- .../bgi256/_bgi_read_raw.c | 6 +- .../bgi256/_bgi_vspan_raw.c | 6 +- {libc/gfx => libbgi/bgi256}/_gfx_acc256.c | 2 +- {libc/gfx => libbgi/bgi256}/_gfx_hfill256.c | 2 +- libbgi/bgi256/getpixel.c | 33 +++ libbgi/bgi256/putpixel.c | 39 ++++ {libc/bgi => libbgi/common}/_bgi_arc_draw.c | 2 +- libbgi/common/_bgi_begin.c | 24 +++ libbgi/common/_bgi_clearall.c | 13 ++ .../bgi => libbgi/common}/_bgi_draw_scaled.c | 2 +- libbgi/common/_bgi_end.c | 15 ++ {libc/bgi => libbgi/common}/_bgi_fill_span.c | 2 +- {libc/bgi => libbgi/common}/_bgi_fill_state.c | 2 +- libbgi/common/_bgi_font_rows.c | 20 ++ libbgi/common/_bgi_hspan.c | 13 ++ {libc/bgi => libbgi/common}/_bgi_isqrt.c | 2 +- {libc/bgi => libbgi/common}/_bgi_line_state.c | 2 +- libbgi/common/_bgi_lineseg.c | 49 +++++ {libc/bgi => libbgi/common}/_bgi_poly_edge.c | 2 +- {libc/bgi => libbgi/common}/_bgi_poly_state.c | 2 +- libbgi/common/_bgi_read.c | 16 ++ {libc/bgi => libbgi/common}/_bgi_state.c | 2 +- .../bgi => libbgi/common}/_bgi_styled_line.c | 2 +- {libc/bgi => libbgi/common}/_bgi_text_state.c | 2 +- {libc/bgi => libbgi/common}/_bgi_trig.c | 2 +- .../gfx => libbgi/common}/_gfx_font_ensure.c | 2 +- {libc/gfx => libbgi/common}/_gfx_font_state.c | 2 +- {libc/gfx => libbgi/common}/_gfx_state.c | 4 +- {libc/gfx => libbgi/common}/_gfx_w3_state.c | 2 +- {libc/bgi => libbgi/common}/arc.c | 2 +- {libc/bgi => libbgi/common}/bar.c | 2 +- {libc/bgi => libbgi/common}/bar3d.c | 2 +- {libc/bgi => libbgi/common}/circle.c | 2 +- {libc/bgi => libbgi/common}/cleardevice.c | 2 +- libbgi/common/closegraph.c | 8 + {libc/bgi => libbgi/common}/drawpoly.c | 2 +- {libc/bgi => libbgi/common}/ellipse.c | 2 +- {libc/bgi => libbgi/common}/fillellipse.c | 2 +- {libc/bgi => libbgi/common}/fillpoly.c | 2 +- {libc/bgi => libbgi/common}/floodfill.c | 2 +- {libc/bgi => libbgi/common}/getbkcolor.c | 2 +- {libc/bgi => libbgi/common}/getcolor.c | 2 +- {libc/bgi => libbgi/common}/getfillsettings.c | 2 +- {libc/bgi => libbgi/common}/getimage.c | 2 +- {libc/bgi => libbgi/common}/getlinesettings.c | 2 +- {libc/bgi => libbgi/common}/getmaxcolor.c | 2 +- {libc/bgi => libbgi/common}/getmaxx.c | 2 +- {libc/bgi => libbgi/common}/getmaxy.c | 2 +- {libc/bgi => libbgi/common}/gettextsettings.c | 2 +- {libc/bgi => libbgi/common}/getx.c | 2 +- {libc/bgi => libbgi/common}/gety.c | 2 +- {libc/gfx => libbgi/common}/gfx_get_bank.c | 2 +- .../gfx => libbgi/common}/gfx_get_draw_page.c | 2 +- .../common}/gfx_get_visible_page.c | 2 +- .../common}/gfx_load_default_font.c | 2 +- {libc/gfx => libbgi/common}/gfx_pal_get.c | 2 +- .../gfx => libbgi/common}/gfx_pal_get_color.c | 2 +- {libc/gfx => libbgi/common}/gfx_pal_load.c | 2 +- {libc/gfx => libbgi/common}/gfx_pal_reset.c | 2 +- {libc/gfx => libbgi/common}/gfx_pal_set.c | 2 +- {libc/gfx => libbgi/common}/gfx_set_bank.c | 2 +- .../gfx => libbgi/common}/gfx_set_draw_page.c | 2 +- {libc/gfx => libbgi/common}/gfx_set_font.c | 2 +- .../common}/gfx_set_visible_page.c | 2 +- {libc/gfx => libbgi/common}/gfx_wait_vsync.c | 3 +- {libc/bgi => libbgi/common}/graphresult.c | 2 +- {libc/bgi => libbgi/common}/imagesize.c | 2 +- {libc/bgi => libbgi/common}/initgraph.c | 2 +- {libc/bgi => libbgi/common}/line.c | 2 +- {libc/bgi => libbgi/common}/linerel.c | 2 +- {libc/bgi => libbgi/common}/lineto.c | 2 +- {libc/bgi => libbgi/common}/moverel.c | 2 +- {libc/bgi => libbgi/common}/moveto.c | 2 +- {libc/bgi => libbgi/common}/outtext.c | 2 +- {libc/bgi => libbgi/common}/outtextxy.c | 2 +- {libc/bgi => libbgi/common}/pieslice.c | 2 +- {libc/bgi => libbgi/common}/putimage.c | 2 +- {libc/bgi => libbgi/common}/rectangle.c | 2 +- {libc/bgi => libbgi/common}/sector.c | 2 +- {libc/bgi => libbgi/common}/setbkcolor.c | 2 +- {libc/bgi => libbgi/common}/setcolor.c | 2 +- {libc/bgi => libbgi/common}/setfillstyle.c | 2 +- {libc/bgi => libbgi/common}/setlinestyle.c | 2 +- {libc/bgi => libbgi/common}/settextstyle.c | 2 +- {libc/bgi => libbgi/common}/textheight.c | 2 +- {libc/bgi => libbgi/common}/textwidth.c | 2 +- libbgi/include/gfx.h | 74 +++++++ {libc => libbgi}/include/graphics.h | 0 libc/Makefile | 89 ++++++++ libc/bgi/_bgi.h | 107 ---------- libc/bgi/closegraph.c | 7 - libc/bgi/drv256/_bgi_begin.c | 8 - libc/bgi/drv256/_bgi_clearall.c | 8 - libc/bgi/drv256/_bgi_drawtext.c | 8 - libc/bgi/drv256/_bgi_end.c | 8 - libc/bgi/drv256/_bgi_fillrect.c | 8 - libc/bgi/drv256/_bgi_font_rows.c | 17 -- libc/bgi/drv256/_bgi_hspan.c | 8 - libc/bgi/drv256/_bgi_hspan_raw.c | 11 - libc/bgi/drv256/_bgi_lineseg.c | 8 - libc/bgi/drv256/_bgi_mode_done.c | 8 - libc/bgi/drv256/_bgi_plot.c | 8 - libc/bgi/drv256/_bgi_plot_raw.c | 11 - libc/bgi/drv256/_bgi_read.c | 8 - libc/bgi/drv256/_bgi_read_raw.c | 11 - libc/bgi/getpixel.c | 7 - libc/bgi/putpixel.c | 7 - libc/gfx/_gfx.h | 110 ---------- libc/gfx/_gfx_render_row16.c | 53 ----- libc/gfx/_gfx_t16_pair_build.c | 17 -- libc/gfx/_gfx_t16_state.c | 14 -- libc/gfx/_gfx_w3_video_begin.c | 20 -- libc/gfx/_gfx_w3_video_end.c | 15 -- libc/gfx/gfx_clear16.c | 12 -- libc/gfx/gfx_clear256.c | 12 -- libc/gfx/gfx_done.c | 10 - libc/gfx/gfx_fill_rect16.c | 16 -- libc/gfx/gfx_fill_rect256.c | 28 --- libc/gfx/gfx_getpixel256.c | 30 --- libc/gfx/gfx_hline16.c | 12 -- libc/gfx/gfx_hline256.c | 12 -- libc/gfx/gfx_init.c | 19 -- libc/gfx/gfx_line16.c | 35 ---- libc/gfx/gfx_line256.c | 37 ---- libc/gfx/gfx_putchar16.c | 27 --- libc/gfx/gfx_putchar256.c | 72 ------- libc/gfx/gfx_putpixel16.c | 14 -- libc/gfx/gfx_putpixel256.c | 14 -- libc/gfx/gfx_rect16.c | 19 -- libc/gfx/gfx_rect256.c | 19 -- libc/gfx/gfx_text16.c | 29 --- libc/gfx/gfx_text256.c | 15 -- libc/gfx/gfx_vline16.c | 12 -- libc/gfx/gfx_vline256.c | 12 -- libc/include/gfx.h | 160 -------------- tests/bgi_img/Makefile | 4 + tests/bgi_img/bgi_img.c | 114 ++++++++++ tests/gfx_dbuf/Makefile | 3 +- tests/gfx_dbuf/gfx_dbuf.c | 82 ++++---- tests/gfx_demo/Makefile | 3 +- tests/gfx_demo/gfx_demo.c | 111 +++++----- 164 files changed, 1072 insertions(+), 1440 deletions(-) delete mode 100644 lib/Makefile create mode 100644 libbgi/Makefile create mode 100644 libbgi/_bgi.h rename libc/gfx/_gfx_clear16_raw.c => libbgi/bgi16/_bgi_clear_raw.c (76%) rename libc/gfx/_gfx_hline16_raw.c => libbgi/bgi16/_bgi_hspan_raw.c (90%) rename libc/gfx/_gfx_putpixel16_raw.c => libbgi/bgi16/_bgi_plot_raw.c (80%) rename libc/gfx/_gfx_vline16_raw.c => libbgi/bgi16/_bgi_vspan_raw.c (84%) rename {libc/gfx => libbgi/bgi16}/_gfx_g16_state.c (96%) rename {libc/gfx => libbgi/bgi16}/_gfx_hfill16.c (98%) rename {libc/gfx => libbgi/bgi16}/_gfx_rmw16.c (98%) rename libc/gfx/_gfx_clear256_raw.c => libbgi/bgi256/_bgi_clear_raw.c (78%) rename libc/gfx/_gfx_hline256_raw.c => libbgi/bgi256/_bgi_hspan_raw.c (80%) rename {libc/bgi/drv256 => libbgi/bgi256}/_bgi_mode_set.c (90%) rename libc/gfx/_gfx_putpixel256_raw.c => libbgi/bgi256/_bgi_plot_raw.c (84%) rename libc/gfx/_gfx_getpixel256_raw.c => libbgi/bgi256/_bgi_read_raw.c (81%) rename libc/gfx/_gfx_vline256_raw.c => libbgi/bgi256/_bgi_vspan_raw.c (90%) rename {libc/gfx => libbgi/bgi256}/_gfx_acc256.c (95%) rename {libc/gfx => libbgi/bgi256}/_gfx_hfill256.c (99%) create mode 100644 libbgi/bgi256/getpixel.c create mode 100644 libbgi/bgi256/putpixel.c rename {libc/bgi => libbgi/common}/_bgi_arc_draw.c (98%) create mode 100644 libbgi/common/_bgi_begin.c create mode 100644 libbgi/common/_bgi_clearall.c rename {libc/bgi => libbgi/common}/_bgi_draw_scaled.c (98%) create mode 100644 libbgi/common/_bgi_end.c rename {libc/bgi => libbgi/common}/_bgi_fill_span.c (98%) rename {libc/bgi => libbgi/common}/_bgi_fill_state.c (93%) create mode 100644 libbgi/common/_bgi_font_rows.c create mode 100644 libbgi/common/_bgi_hspan.c rename {libc/bgi => libbgi/common}/_bgi_isqrt.c (94%) rename {libc/bgi => libbgi/common}/_bgi_line_state.c (92%) create mode 100644 libbgi/common/_bgi_lineseg.c rename {libc/bgi => libbgi/common}/_bgi_poly_edge.c (97%) rename {libc/bgi => libbgi/common}/_bgi_poly_state.c (95%) create mode 100644 libbgi/common/_bgi_read.c rename {libc/bgi => libbgi/common}/_bgi_state.c (95%) rename {libc/bgi => libbgi/common}/_bgi_styled_line.c (98%) rename {libc/bgi => libbgi/common}/_bgi_text_state.c (91%) rename {libc/bgi => libbgi/common}/_bgi_trig.c (98%) rename {libc/gfx => libbgi/common}/_gfx_font_ensure.c (95%) rename {libc/gfx => libbgi/common}/_gfx_font_state.c (97%) rename {libc/gfx => libbgi/common}/_gfx_state.c (89%) rename {libc/gfx => libbgi/common}/_gfx_w3_state.c (94%) rename {libc/bgi => libbgi/common}/arc.c (92%) rename {libc/bgi => libbgi/common}/bar.c (96%) rename {libc/bgi => libbgi/common}/bar3d.c (98%) rename {libc/bgi => libbgi/common}/circle.c (98%) rename {libc/bgi => libbgi/common}/cleardevice.c (90%) create mode 100644 libbgi/common/closegraph.c rename {libc/bgi => libbgi/common}/drawpoly.c (96%) rename {libc/bgi => libbgi/common}/ellipse.c (94%) rename {libc/bgi => libbgi/common}/fillellipse.c (97%) rename {libc/bgi => libbgi/common}/fillpoly.c (98%) rename {libc/bgi => libbgi/common}/floodfill.c (99%) rename {libc/bgi => libbgi/common}/getbkcolor.c (83%) rename {libc/bgi => libbgi/common}/getcolor.c (83%) rename {libc/bgi => libbgi/common}/getfillsettings.c (92%) rename {libc/bgi => libbgi/common}/getimage.c (97%) rename {libc/bgi => libbgi/common}/getlinesettings.c (93%) rename {libc/bgi => libbgi/common}/getmaxcolor.c (88%) rename {libc/bgi => libbgi/common}/getmaxx.c (86%) rename {libc/bgi => libbgi/common}/getmaxy.c (86%) rename {libc/bgi => libbgi/common}/gettextsettings.c (94%) rename {libc/bgi => libbgi/common}/getx.c (80%) rename {libc/bgi => libbgi/common}/gety.c (80%) rename {libc/gfx => libbgi/common}/gfx_get_bank.c (86%) rename {libc/gfx => libbgi/common}/gfx_get_draw_page.c (89%) rename {libc/gfx => libbgi/common}/gfx_get_visible_page.c (89%) rename {libc/gfx => libbgi/common}/gfx_load_default_font.c (97%) rename {libc/gfx => libbgi/common}/gfx_pal_get.c (94%) rename {libc/gfx => libbgi/common}/gfx_pal_get_color.c (95%) rename {libc/gfx => libbgi/common}/gfx_pal_load.c (98%) rename {libc/gfx => libbgi/common}/gfx_pal_reset.c (91%) rename {libc/gfx => libbgi/common}/gfx_pal_set.c (95%) rename {libc/gfx => libbgi/common}/gfx_set_bank.c (88%) rename {libc/gfx => libbgi/common}/gfx_set_draw_page.c (96%) rename {libc/gfx => libbgi/common}/gfx_set_font.c (93%) rename {libc/gfx => libbgi/common}/gfx_set_visible_page.c (97%) rename {libc/gfx => libbgi/common}/gfx_wait_vsync.c (98%) rename {libc/bgi => libbgi/common}/graphresult.c (90%) rename {libc/bgi => libbgi/common}/imagesize.c (97%) rename {libc/bgi => libbgi/common}/initgraph.c (97%) rename {libc/bgi => libbgi/common}/line.c (90%) rename {libc/bgi => libbgi/common}/linerel.c (92%) rename {libc/bgi => libbgi/common}/lineto.c (90%) rename {libc/bgi => libbgi/common}/moverel.c (88%) rename {libc/bgi => libbgi/common}/moveto.c (86%) rename {libc/bgi => libbgi/common}/outtext.c (95%) rename {libc/bgi => libbgi/common}/outtextxy.c (92%) rename {libc/bgi => libbgi/common}/pieslice.c (91%) rename {libc/bgi => libbgi/common}/putimage.c (98%) rename {libc/bgi => libbgi/common}/rectangle.c (95%) rename {libc/bgi => libbgi/common}/sector.c (98%) rename {libc/bgi => libbgi/common}/setbkcolor.c (88%) rename {libc/bgi => libbgi/common}/setcolor.c (86%) rename {libc/bgi => libbgi/common}/setfillstyle.c (91%) rename {libc/bgi => libbgi/common}/setlinestyle.c (94%) rename {libc/bgi => libbgi/common}/settextstyle.c (95%) rename {libc/bgi => libbgi/common}/textheight.c (93%) rename {libc/bgi => libbgi/common}/textwidth.c (94%) create mode 100644 libbgi/include/gfx.h rename {libc => libbgi}/include/graphics.h (100%) create mode 100644 libc/Makefile delete mode 100644 libc/bgi/_bgi.h delete mode 100644 libc/bgi/closegraph.c delete mode 100644 libc/bgi/drv256/_bgi_begin.c delete mode 100644 libc/bgi/drv256/_bgi_clearall.c delete mode 100644 libc/bgi/drv256/_bgi_drawtext.c delete mode 100644 libc/bgi/drv256/_bgi_end.c delete mode 100644 libc/bgi/drv256/_bgi_fillrect.c delete mode 100644 libc/bgi/drv256/_bgi_font_rows.c delete mode 100644 libc/bgi/drv256/_bgi_hspan.c delete mode 100644 libc/bgi/drv256/_bgi_hspan_raw.c delete mode 100644 libc/bgi/drv256/_bgi_lineseg.c delete mode 100644 libc/bgi/drv256/_bgi_mode_done.c delete mode 100644 libc/bgi/drv256/_bgi_plot.c delete mode 100644 libc/bgi/drv256/_bgi_plot_raw.c delete mode 100644 libc/bgi/drv256/_bgi_read.c delete mode 100644 libc/bgi/drv256/_bgi_read_raw.c delete mode 100644 libc/bgi/getpixel.c delete mode 100644 libc/bgi/putpixel.c delete mode 100644 libc/gfx/_gfx.h delete mode 100644 libc/gfx/_gfx_render_row16.c delete mode 100644 libc/gfx/_gfx_t16_pair_build.c delete mode 100644 libc/gfx/_gfx_t16_state.c delete mode 100644 libc/gfx/_gfx_w3_video_begin.c delete mode 100644 libc/gfx/_gfx_w3_video_end.c delete mode 100644 libc/gfx/gfx_clear16.c delete mode 100644 libc/gfx/gfx_clear256.c delete mode 100644 libc/gfx/gfx_done.c delete mode 100644 libc/gfx/gfx_fill_rect16.c delete mode 100644 libc/gfx/gfx_fill_rect256.c delete mode 100644 libc/gfx/gfx_getpixel256.c delete mode 100644 libc/gfx/gfx_hline16.c delete mode 100644 libc/gfx/gfx_hline256.c delete mode 100644 libc/gfx/gfx_init.c delete mode 100644 libc/gfx/gfx_line16.c delete mode 100644 libc/gfx/gfx_line256.c delete mode 100644 libc/gfx/gfx_putchar16.c delete mode 100644 libc/gfx/gfx_putchar256.c delete mode 100644 libc/gfx/gfx_putpixel16.c delete mode 100644 libc/gfx/gfx_putpixel256.c delete mode 100644 libc/gfx/gfx_rect16.c delete mode 100644 libc/gfx/gfx_rect256.c delete mode 100644 libc/gfx/gfx_text16.c delete mode 100644 libc/gfx/gfx_text256.c delete mode 100644 libc/gfx/gfx_vline16.c delete mode 100644 libc/gfx/gfx_vline256.c delete mode 100644 libc/include/gfx.h create mode 100644 tests/bgi_img/Makefile create mode 100644 tests/bgi_img/bgi_img.c diff --git a/.gitignore b/.gitignore index fa15163..651e592 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # =========================================================================== # `build/` directories anywhere in the tree -# (top-level build/, lib/build/, toolchain/*/build/, ...) +# (top-level build/, libc/build/, libbgi/build/, toolchain/*/build/, ...) build/ # sprinter-cc per-example intermediate directory @@ -40,7 +40,7 @@ tests/*/*.cdb tests/*/*.mem tests/*/*.rst -# libc archive (built from libc/, see lib/Makefile) +# libc + libbgi archives (built by libc/Makefile + libbgi/Makefile) lib/*.lib # Host-built mkexe binary + test outputs (input fixtures *.bin/*.ihx kept) diff --git a/CLAUDE.md b/CLAUDE.md index bbdc742..baec71d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,20 +6,26 @@ Target-слой SDCC 4.5 (z80) для компьютера Sprinter Sp2000: crt0 ## Сборка и проверка ``` -make # tools + lib + все тесты (43) + examples -make -C lib # только libc → lib/sprinter.lib +make # tools + lib + libbgi + все тесты (45) + examples +make -C libc # только libc → lib/sprinter.lib +make -C libbgi # только BGI → lib/bgi256.lib (и bgi16.lib в Фазе 2) make floppy # упаковать все .exe в mame/v306/IMG/mc.img make size-check # размерный регресс: _CODE vs docs/size_baseline.tsv make size-baseline # принять текущие размеры эталоном ``` +Графика (BGI) — отдельная библиотека libbgi/ (см. ниже). Программа, +использующая graphics.h, собирается с `--gfx 256` (или `--gfx 16` в +Фазе 2): sprinter-cc подлинкует lib/bgi256.lib и добавит -I libbgi/include. + Одиночный тест: `cd tests/<имя> && make run` (пакует ТОЛЬКО этот exe + EXTRA_DATA на дискету и запускает MAME). Тесты в MAME гоняет пользователь — готовь дискету и проси прогнать. -После правок libc: пересборка от чистого листа (`make -C lib clean`) -не обязательна — stale .rel чистятся автоматически; `make size-check` -обязателен (рост _CODE без причины — регрессия). +После правок libc/libbgi: пересборка от чистого листа (`make -C libc clean` +/ `make -C libbgi clean`) не обязательна — stale .rel чистятся +автоматически; `make size-check` обязателен (рост _CODE без причины — +регрессия). ## Правила libc @@ -29,7 +35,7 @@ make size-baseline # принять текущие размеры эталон (`_`-префикс); общие статики — в отдельные data-модули (`_xxx_state.c`); internal-заголовки (`_file.h`, `_gfx.h`, …) — рядом с исходниками, НЕ в libc/include. -- Имя файла = имя функции. lib/Makefile собирает wildcard'ом — +- Имя файла = имя функции. libc/Makefile собирает wildcard'ом — ничего регистрировать не надо. - Комментарии — на русском; шапка модуля объясняет что/зачем + ABI. - File-scope переменные НЕ инициализировать `= 0` (crt0 зануляет @@ -54,12 +60,13 @@ make size-baseline # принять текущие размеры эталон лимит 8 файловых манипуляторов, 9-й OPEN ВЕШАЕТ DSS (_fd_guard); ENV $46: A=0 = NOT FOUND. - Перед обвинением компилятора/железа — подтвердить артефактом - (сгенерированный .asm в lib/build/, дамп, репро) — см. + (сгенерированный .asm в libc/build/ или libbgi/build/, дамп, репро) — см. memory/defer_unexplained_quirks. ## Структура -- `libc//*.c` — модули libc; `libc/include/` — публичные заголовки +- `libc//*.c` — модули libc (ядро, БЕЗ графики); `libc/include/` — публичные заголовки libc +- `libbgi/` — графика BGI (отдельная библиотека): `common/` — mode-agnostic (один исходник, .rel в обеих driver-библиотеках), `bgi256/` + `bgi16/` — mode-specific leaf'ы (реальные реализации, без обёрток); `include/` — graphics.h + gfx.h; `_bgi.h` — внутренний заголовок. Собирает `lib/bgi256.lib` (и `bgi16.lib` в Фазе 2). Выбор режима линковкой: `--gfx 256` / `--gfx 16`. - `runtime/` — crt0-семейство, heap, bank (bank.s собирается per-build) - `bin/sprinter-cc` — обёртка компилятора; `toolchain/mkexe` — упаковщик - `tests/` — по одному API/фиче; `examples/` — реальные приложения diff --git a/Makefile b/Makefile index d243ba7..6ef56cf 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # # 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 lib build lib/sprinter.lib (libc) + lib/bgi256.lib (libbgi) # 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 @@ -18,8 +18,9 @@ TESTS := hello hello2 simple banked bankedbg banktest strtest cat seek \ attrprob timedir mouse banklocl stdlib assrtest ptime stattest \ filetest fdmax fbench solidt irqtest cbltest cblwav dec_test gets stest2 winrest \ bios_text text_palette \ - gfx_demo gfx_d16 gfx_text gfx_mous gfx_dbuf - + gfx_demo gfx_dbuf +# gfx_d16 / gfx_text / gfx_mous — 16-цветные; убраны до Фазы 2 (bgi16.lib +# ещё не собирается). Вернуть мигрированными на BGI --gfx 16. # Larger end-user applications under examples/. APPS := mdview mdview2 @@ -46,7 +47,8 @@ tools: $(MAKE) -C toolchain/mkexe lib: - $(MAKE) -C lib + $(MAKE) -C libc + $(MAKE) -C libbgi check: tools $(MAKE) -C toolchain/mkexe check @@ -81,7 +83,8 @@ size-baseline: clean: $(MAKE) -C toolchain/mkexe clean - $(MAKE) -C lib clean + $(MAKE) -C libc clean + $(MAKE) -C libbgi clean @for t in $(TESTS); do $(MAKE) -C tests/$$t clean; done @for a in $(APPS); do $(MAKE) -C examples/$$a clean; done diff --git a/app.mk b/app.mk index 3b59957..f65e918 100644 --- a/app.mk +++ b/app.mk @@ -62,8 +62,13 @@ $(EXAMPLE).exe: $(SOURCES) $(MKEXE) $(LIB) $(RUNTIME_DEPS) $(MKEXE): $(MAKE) -C $(PROJ_ROOT)/toolchain/mkexe +# $(LIB) = lib/sprinter.lib (libc). Графика (bgi256.lib) собирает +# libbgi/Makefile; гоним и его — иначе standalone `make` в тесте с +# --gfx 256 не найдёт bgi256.lib при линковке. Оба инкрементальные, +# на повторном запуске ничего не пересобирают. $(LIB): - $(MAKE) -C $(PROJ_ROOT)/lib + $(MAKE) -C $(PROJ_ROOT)/libc + $(MAKE) -C $(PROJ_ROOT)/libbgi clean: rm -rf .sprinter-cc-* $(EXAMPLE).exe diff --git a/bin/sprinter-cc b/bin/sprinter-cc index b8a46a0..51e102f 100755 --- a/bin/sprinter-cc +++ b/bin/sprinter-cc @@ -64,6 +64,7 @@ CHECK_BANKS="$PROJ_ROOT/toolchain/check_banks.py" RUNTIME="$PROJ_ROOT/runtime" LIB_DIR="$PROJ_ROOT/lib" INC_DIR="$PROJ_ROOT/libc/include" +BGI_INC_DIR="$PROJ_ROOT/libbgi/include" # gfx.h, graphics.h (BGI) # ------- Defaults ------------------------------------------------------------ OUT="" @@ -129,7 +130,7 @@ done GFX_LD=() case "$GFX_MODE" in "") ;; # graphics.h не используется - 256) GFX_LD=("-lsprinter_gfx256");; + 256) GFX_LD=("-lbgi256");; # libbgi/bgi256 → lib/bgi256.lib 16) echo "sprinter-cc: --gfx 16 ещё не реализован (пока только 256)" >&2; exit 1;; *) echo "sprinter-cc: --gfx: ожидается 256 (или 16), дано: $GFX_MODE" >&2; exit 1;; esac @@ -288,7 +289,7 @@ run "$SDASZ80" -o "$HEAP_TOP_REL" "$HEAP_TOP_SRC" # 2. user sources → .rel (HOME) USER_RELS=() -CC_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size -I "$INC_DIR" "${USER_INCS[@]}") +CC_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size -I "$INC_DIR" -I "$BGI_INC_DIR" "${USER_INCS[@]}") [[ $DEBUG_RT -eq 1 ]] && CC_FLAGS+=(-DDEBUG_RT) [[ -n "$MAX_ALLOCS" ]] && CC_FLAGS+=(--max-allocs-per-node "$MAX_ALLOCS") for src in "${SOURCES[@]}"; do diff --git a/docs/libc-headers.md b/docs/libc-headers.md index 49ccf2b..60a20aa 100644 --- a/docs/libc-headers.md +++ b/docs/libc-headers.md @@ -32,9 +32,15 @@ SDCC-версию) и дальше только добавляет Sprinter-ра ## 3. Свои заголовки (SDCC-аналога нет — затенения нет) -conio.h, dir.h, dos.h, errno.h, fcntl.h, gfx.h, mouse.h, palette.h, +conio.h, dir.h, dos.h, errno.h, fcntl.h, mouse.h, palette.h, sprinter*.h, unistd.h, bios/*. +Графика вынесена из libc в отдельную библиотеку libbgi/: её публичные +заголовки gfx.h (mode-agnostic BGI_GFX) и graphics.h (BGI API) живут в +libbgi/include/ и пробрасываются через -I libbgi/include (sprinter-cc +добавляет его автоматически). Внутренний заголовок графики — +libbgi/_bgi.h (слияние старых libc/gfx/_gfx.h и libc/bgi/_bgi.h). + ## Правила - новый стандартный заголовок — сначала пробовать паттерн 1 @@ -42,5 +48,7 @@ sprinter*.h, unistd.h, bios/*. реализацию (как puts/putchar на ESTEX); - в заголовках паттерна 2 — комментарий, какие декларации обслуживают z80.lib; -- internal-заголовки libc (`_conio.h`, `_file.h`, `_gfx.h`, …) живут - РЯДОМ с исходниками в libc//, не в libc/include. +- internal-заголовки libc (`_conio.h`, `_file.h`, …) живут + РЯДОМ с исходниками в libc//, не в libc/include. Internal + графики — в libbgi/_bgi.h (корень libbgi/, подключается из common/ и + bgi256/bgi16/ как `#include "../_bgi.h"`). diff --git a/docs/libc-reference.md b/docs/libc-reference.md index 47b88f6..6bf493f 100644 --- a/docs/libc-reference.md +++ b/docs/libc-reference.md @@ -180,7 +180,13 @@ wrchar rdchar`; режимы `gettextmode/settextmode` (0x02=40×32, `bios_fillchar/fillattr/fillcharattr`, `bios_clearwin[_ch]`, `bios_scrollwin`. Строка s — в #4000–#BFFF; place продвигается. -## — графика (0x81: 320×256×256; 0x82: 640×256×16) +## — графика, mode-agnostic API (BGI_GFX); живёт в libbgi/include + +Рисование (putpixel/line/bar/circle/…) вынесено в BGI — см. `` +и driver-библиотеки lib/bgi256.lib / lib/bgi16.lib (выбор режима линковкой: +`sprinter-cc --gfx 256` / `--gfx 16`). В gfx.h остались только функции +БЕЗ BGI-аналога (mode-agnostic, живут в libbgi/common/, .rel в обеих + driver-библиотеках): Setup: `gfx_init(mode,page)→prev`, `gfx_done(prev)`. Страницы/банк: `gfx_set/get_visible_page`, `gfx_set/get_draw_page` @@ -199,14 +205,13 @@ Setup: `gfx_init(mode,page)→prev`, `gfx_done(prev)`. использования с реальным CBL-звуком. Фолбэк на одно кадровое прерывание (`halt`), если бит не ведёт себя как ожидается за разумное число попыток. -Примитивы (суффикс _256 / _16): `clear putpixel hline vline line -rect fill_rect` — через акселератор (hline/vline burst до 256 байт; -в 0x82 vline через RMW). Координаты int, клиппинг по краям. -Текст: `gfx_putchar256/16, gfx_text256/16` (8×8, fg/bg; в 0x82 x — -чётный), `gfx_load_default_font`, `gfx_set_font(ptr)` (interleaved -font[row*256+char]). +Шрифт: `gfx_load_default_font`, `gfx_set_font(ptr)` (interleaved +font[row*256+char]) — грузится лениво при первом использовании BGI-текста. Палитра: `gfx_pal_load/set/get/get_color/reset` (страницы 0..3). -`gfx_getpixel256(x,y)→color` — чтение пикселя (0x81). + +Константы режимов: `GFX_MODE_320x256x256` (0x81), `GFX_MODE_640x256x16` +(0x82); размеры `GFX_WIDTH/HEIGHT` (320/256), `GFX_WIDTH_16/HEIGHT_16` +(640/256). Рисование через `` (BGI). ## — Turbo-C BGI (функц. совместимость), Фаза 1, режим 256 @@ -237,9 +242,15 @@ drawpoly. Стиль текста (Ф2d): `settextstyle(font,dir,size)`/`gettextsettings`, `textwidth`/`textheight` — масштаб 1..10, HORIZ/VERT, прозрачный фон (только DEFAULT_FONT 8×8). -Реализация: libc/bgi/*.c (math) + libc/bgi/drv256/*.c (leaf → -sprinter_gfx256.lib). Пакетные примитивы — одна W3-скобка на примитив; -тригонометрия/эллипсы целочисленные (Q7/isqrt, БЕЗ 32-бит). +Реализация: libbgi/common/*.c (mode-agnostic math + BGI public API + +BGI_GFX) + libbgi/bgi256/*.c (256-цветные leaf'ы) → lib/bgi256.lib +(Фаза 2 добавит libbgi/bgi16/*.c → lib/bgi16.lib; common .rel одни и +те же в обоих архивах). Leaf'ы — реальные реализации (БЕЗ обёрток: +putpixel/getpixel полностью inline, _bgi_plot_raw/_bgi_hspan_raw/... +поглощают акселераторный asm). Пакетные примитивы — одна W3-скобка +на примитив; тригонометрия/эллипсы целочисленные (Q7/isqrt, БЕЗ 32-бит). +Cross-lib: libbgi всегда линкуется с libc; _cbl_port_ref/unref +объявлены extern в libbgi/_bgi.h (сверять с libc/cbl/_cbl.h). Ф2d (осталось): setviewport/клиппинг, settextjustify, setaspectratio — см. docs/TODO.md. diff --git a/docs/libc-roadmap.md b/docs/libc-roadmap.md index 3e33cff..205f074 100644 --- a/docs/libc-roadmap.md +++ b/docs/libc-roadmap.md @@ -75,7 +75,7 @@ fgetpos/fsetpos (хвост П2). bdos/brk/ioctl — отказ решение (stdio.h, time.h — обязаны дублировать сигнатуры z80.lib); из sprinter_compat.h убраны макросы min/max (конфликтовали с функциями из stdlib.h; в Solid-C это тоже функции) -- [x] lib/Makefile: stale .rel чистятся сверкой списка перед упаковкой; +- [x] libc/Makefile: stale .rel чистятся сверкой списка перед упаковкой; штамп .modules триггерит перелинковку при смене состава (и сносит архив — mtime на exFAT грубый) - [x] Все extra-тесты в top-level TESTS (43 программы: + hello2, simple, diff --git a/docs/size_baseline.tsv b/docs/size_baseline.tsv index b016a5c..3a26e4b 100644 --- a/docs/size_baseline.tsv +++ b/docs/size_baseline.tsv @@ -6,6 +6,7 @@ banked 1056 bankedbg 1067 banklocl 4832 banktest 3767 +bgi_img 6218 bgitest 4196 bios_text 4470 cat 915 diff --git a/lib/Makefile b/lib/Makefile deleted file mode 100644 index eace06d..0000000 --- a/lib/Makefile +++ /dev/null @@ -1,104 +0,0 @@ -# Build lib/libsprinter.lib — the Sprinter target libc archive. -# -# Includes all libc/*.c modules plus the runtime helpers that get -# auto-pulled by SDCC's codegen (heap for malloc, bank trampolines for -# __banked). The crt0 family is NOT in the lib — they are always -# explicitly linked, never DCE-eligible. -# -# Each .c file becomes its own .rel inside the archive. The linker -# pulls only those .rel files whose exported symbols are referenced, -# giving free dead-code elimination at module granularity. - -PROJ_ROOT := $(abspath $(CURDIR)/..) -SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin -SDCC := $(SDCC_BIN)/sdcc -SDAR := $(SDCC_BIN)/sdar -SDASZ80 := $(SDCC_BIN)/sdasz80 - -INC := -I$(PROJ_ROOT)/libc/include -CC_FLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC) - -BUILD := $(PROJ_ROOT)/lib/build - -# All libc C modules — every .c under libc// becomes its own .rel. -# One PUBLIC function per file (see docs/libc-split-asm-cases.md): the -# linker pulls whole .rel modules, so file granularity == DCE granularity. -# Внимание: `libc/*/*.c` — ровно ОДИН уровень вложенности, поэтому -# ловит mode-agnostic BGI-математику libc/bgi/*.c (идёт в sprinter.lib), -# но НЕ ловит driver-leaf'ы libc/bgi/drv256/*.c (два уровня) — они -# собираются в ОТДЕЛЬНЫЙ архив sprinter_gfx256.lib (выбор режима -# линковкой; см. memory/bgi_two_lib_design). -LIBC_C := $(patsubst $(PROJ_ROOT)/%,%,$(wildcard $(PROJ_ROOT)/libc/*/*.c)) - -# Driver-leaf'ы 256-цветного BGI → sprinter_gfx256.lib. -GFX256_C := $(patsubst $(PROJ_ROOT)/%,%,$(wildcard $(PROJ_ROOT)/libc/bgi/drv256/*.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 -# window (W1 for BIG, W3 for HUGE) which is decided per-build by sprinter-cc. -# That tool assembles bank.s on each banked build with the right BANK_W1 flag. -RUNTIME_S := runtime/heap.s - -LIBC_RELS := $(patsubst libc/%.c,$(BUILD)/%.rel,$(LIBC_C)) -GFX256_RELS := $(patsubst libc/%.c,$(BUILD)/%.rel,$(GFX256_C)) -RUNTIME_RELS := $(patsubst runtime/%.s,$(BUILD)/%.rel,$(RUNTIME_S)) - -# Члены основной sprinter.lib. -ALL_RELS := $(LIBC_RELS) $(RUNTIME_RELS) -# Всё, что вообще собираем (для штампа и чистки stale — иначе .rel'ы -# драйвера сочтутся «осиротевшими» и будут удалены). -KNOWN_RELS := $(ALL_RELS) $(GFX256_RELS) - -# Штамп списка модулей: обновляется при любом изменении состава -# (добавление/удаление/переименование исходника) — иначе удаление -# исходника не триггерит перелинковку и stale .rel остаётся в архиве. -# Сразу сносим и архив: на exFAT (SAM8) гранулярность mtime грубая, -# и «список изменился» через сравнение времён можно проглядеть. -MODLIST := $(BUILD)/.modules -ifneq ($(shell cat $(MODLIST) 2>/dev/null),$(KNOWN_RELS)) -_ := $(shell mkdir -p $(BUILD); echo "$(KNOWN_RELS)" > $(MODLIST); rm -f sprinter.lib sprinter_gfx256.lib) -endif - -LIB := sprinter.lib -GFX256_LIB := sprinter_gfx256.lib - -all: $(LIB) $(GFX256_LIB) - -# Pattern rule for C modules — preserves the libc/io|mem|stdio path -# so .rel members keep their natural names inside the archive. -$(BUILD)/%.rel: $(PROJ_ROOT)/libc/%.c - @mkdir -p $(dir $@) - $(SDCC) $(CC_FLAGS) -c -o $@ $< - -# Runtime .s → .rel -$(BUILD)/%.rel: $(PROJ_ROOT)/runtime/%.s - @mkdir -p $(dir $@) - $(SDASZ80) -o $@ $< - -# Archive — sdar with `rcs` = replace/create/symtab. -# Перед упаковкой удаляем stale .rel: wildcard не знает об удалённых/ -# переименованных исходниках, и осиротевший .rel из build/ иначе жил бы -# вечно (уже кусало: старый file.rel после сплита). -$(LIB): $(ALL_RELS) $(MODLIST) - @find $(BUILD) -name '*.rel' -print | sort > $(BUILD)/.have - @printf '%s\n' $(KNOWN_RELS) | sort > $(BUILD)/.want - @comm -23 $(BUILD)/.have $(BUILD)/.want | while read f; do \ - echo " stale: $$f (исходник удалён) — rm"; \ - rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \ - done - rm -f $@ - $(SDAR) -rcs $@ $(ALL_RELS) - @echo - @echo " Built $@ with $(words $(ALL_RELS)) modules:" - @$(SDAR) -t $@ | sed 's/^/ /' - -# Driver-архив 256-цветного BGI: только leaf'ы drv256/. -$(GFX256_LIB): $(GFX256_RELS) $(MODLIST) - rm -f $@ - $(SDAR) -rcs $@ $(GFX256_RELS) - @echo " Built $@ with $(words $(GFX256_RELS)) modules." - -clean: - rm -rf $(BUILD) $(LIB) $(GFX256_LIB) - -.PHONY: all clean diff --git a/libbgi/Makefile b/libbgi/Makefile new file mode 100644 index 0000000..8513c83 --- /dev/null +++ b/libbgi/Makefile @@ -0,0 +1,79 @@ +# Build lib/bgi256.lib — Sprinter BGI graphics driver (320×256×256). +# +# libbgi/ — самостоятельная графическая библиотека, отделённая от libc. +# Две driver-библиотеки собираются из одной исходной базы: +# bgi256.lib = common/*.rel + bgi256/*.rel (эта — Фаза 1) +# bgi16.lib = common/*.rel + bgi16/*.rel (Фаза 2; пока не собирается) +# common/ — mode-agnostic: .rel компилируется ОДИН раз и кладётся в ОБА +# архива (один исходник для функций, общих 256- и 16-цветной версиям). +# bgi256/ — mode-specific leaf'ы (реальные реализации, без обёрток). +# +# Каждый .c — отдельный .rel в архиве (1 публичная функция = 1 модуль); +# линкер тянет только нужные .rel → DCE на уровне файлов. См. план +# «Рефакторинг GFX → BGI» и memory/bgi_two_lib_design. +# +# make build lib/bgi256.lib +# make clean remove build/ + lib/bgi256.lib +# +# (Фаза 2 добавит bgi16.lib = common + bgi16; common .rel переиспользуются.) + +PROJ_ROOT := $(abspath $(CURDIR)/..) +SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin +SDCC := $(SDCC_BIN)/sdcc +SDAR := $(SDCC_BIN)/sdar + +# -I libbgi/include (gfx.h, graphics.h) + -I libc/include (palette.h, +# sprinter_exit.h — публичные заголовки libc; libbgi всегда линкуется с +# libc). SDCC stdint и пр. — из собственного include-пути SDCC. +INC := -I$(CURDIR)/include -I$(PROJ_ROOT)/libc/include +CC_FLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC) + +BUILD := $(CURDIR)/build + +COMMON_C := $(wildcard $(CURDIR)/common/*.c) +BGI256_C := $(wildcard $(CURDIR)/bgi256/*.c) +# BGI16_C := $(wildcard $(CURDIR)/bgi16/*.c) # Фаза 2 + +COMMON_RELS := $(patsubst $(CURDIR)/common/%.c,$(BUILD)/common/%.rel,$(COMMON_C)) +BGI256_RELS := $(patsubst $(CURDIR)/bgi256/%.c,$(BUILD)/bgi256/%.rel,$(BGI256_C)) +KNOWN_RELS := $(COMMON_RELS) $(BGI256_RELS) + +LIB_DIR := $(PROJ_ROOT)/lib +LIB256 := $(LIB_DIR)/bgi256.lib + +# Штамп списка модулей — иначе удаление/переименование исходника не +# триггерит перелинковку и stale .rel остаётся в архиве. На exFAT +# грубая mtime — сравниваем по списку, не по времени. +MODLIST := $(BUILD)/.modules +ifneq ($(shell cat $(MODLIST) 2>/dev/null),$(KNOWN_RELS)) +_ := $(shell mkdir -p $(BUILD); echo "$(KNOWN_RELS)" > $(MODLIST); rm -f $(LIB256)) +endif + +all: $(LIB256) + +# Pattern rule для common/ и bgi256/ (один уровень под build/). +$(BUILD)/common/%.rel: $(CURDIR)/common/%.c + @mkdir -p $(dir $@) + $(SDCC) $(CC_FLAGS) -c -o $@ $< + +$(BUILD)/bgi256/%.rel: $(CURDIR)/bgi256/%.c + @mkdir -p $(dir $@) + $(SDCC) $(CC_FLAGS) -c -o $@ $< + +# Archive — sdar rcs = replace/create/symtab. Перед упаковкой удаляем +# stale .rel (wildcard не знает об удалённых исходниках). +$(LIB256): $(COMMON_RELS) $(BGI256_RELS) $(MODLIST) + @find $(BUILD) -name '*.rel' -print | sort > $(BUILD)/.have + @printf '%s\n' $(KNOWN_RELS) | sort > $(BUILD)/.want + @comm -23 $(BUILD)/.have $(BUILD)/.want | while read f; do \ + echo " stale: $$f (исходник удалён) — rm"; \ + rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \ + done + rm -f $@ + $(SDAR) -rcs $@ $(COMMON_RELS) $(BGI256_RELS) + @echo " Built $@ with $(words $(COMMON_RELS)) common + $(words $(BGI256_RELS)) bgi256 modules." + +clean: + rm -rf $(BUILD) $(LIB256) + +.PHONY: all clean diff --git a/libbgi/_bgi.h b/libbgi/_bgi.h new file mode 100644 index 0000000..554bbb5 --- /dev/null +++ b/libbgi/_bgi.h @@ -0,0 +1,197 @@ +/* + * _bgi.h — внутренности графической подсистемы BGI (НЕ публичный заголовок). + * + * Слияние старых libc/bgi/_bgi.h и libc/gfx/_gfx.h. Графика вынесена из + * libc в самостоятельную библиотеку libbgi/ (см. docs + memory + * bgi_two_lib_design). Из libbgi собираются две driver-библиотеки + * (каждый .c → отдельный .rel): + * bgi256.lib ← common/ + bgi256/ (320×256×256, mode 0x81) + * bgi16.lib ← common/ + bgi16/ (640×256×16, mode 0x82) + * common/ — mode-agnostic: .rel компилируется ОДИН раз и кладётся в + * ОБА архива (один исходник для функций, общих 256- и 16-цветной + * версиям). bgi256/ и bgi16/ — mode-specific leaf'ы (реальные + * реализации, БЕЗ обёрток-делегатов). Режим выбирается линковкой + * (--gfx 256 / --gfx 16), одновременно один. + * + * Публичные leaf-символы (_bgi_plot_raw, _bgi_hspan_raw, _bgi_read_raw, + * _bgi_vspan_raw, _bgi_clear_raw, _bgi_mode_set) одинаково объявлены в + * обоих driver-каталогах, поэтому common-математика не знает режима — + * нужный .rel тянет линкер из выбранной библиотеки. + */ +#ifndef _BGI_INTERNAL_H +#define _BGI_INTERNAL_H + +#include +#include +#include /* GFX_MODE_*, размеры — для внутренних таблиц */ + +/* ---- Состояние BGI (_bgi_state.c) -------------------------------- */ +extern uint8_t _bgi_fg; /* текущий цвет рисования */ +extern uint8_t _bgi_bg; /* фоновый цвет */ +extern int _bgi_cx; /* текущая позиция X (CP) */ +extern int _bgi_cy; /* текущая позиция Y */ +extern int _bgi_maxx; /* правая граница (319 / 639) */ +extern int _bgi_maxy; /* нижняя граница (255) */ +extern int _bgi_maxcolor; /* макс. индекс цвета (255 / 15) */ +extern uint8_t _bgi_prevmode; /* видеорежим до initgraph */ +extern int _bgi_result; /* код graphresult */ + +/* ---- Общее gfx-состояние (common/_gfx_state.c) ------------------ * + * Пишут gfx_set_visible_page / gfx_set_draw_page / + * gfx_set_bank; читают все mode-специфичные примитивы. */ + +extern uint8_t _gfx_visible_page; +extern uint8_t _gfx_draw_page; + +/* Байт страницы W3 (0x50..0x5F) — какой видеобанк мапится при записи. + * См. memory/sprinter_vram_transparency.md (0x50 normal, 0x54 temp, + * 0x58 transparent, 0x5C оба). */ +extern uint8_t _gfx_bank; + +/* CPU-адрес колонки 0 текущей draw-страницы: 0xC000 (page 0) или + * 0xC140 (page 1); каждый примитив использует его вместо константы. */ +extern uint16_t _gfx_addr_base; + +/* ---- Низкоуровневый видеорежим (libc/video) ---------------------- */ +uint8_t _videomode_raw_get(void); +int _videomode_raw_set(uint8_t mode); + +/* ---- W3-скобки (common/_bgi_begin.c, _bgi_end.c) ----------------- * + * begin: DI + сохранить текущий W3 и замапить _gfx_bank; + * end: восстановить W3 + EI. Не реентерабельно (сейв в статике). */ + +extern uint8_t _gfx_saved_w3; + +void _bgi_begin(void); +void _bgi_end(void); + +/* ---- LEAF-операции драйвера (bgi256/ или bgi16/) ----------------- * + * Каждая self-contained: raw-варианты НЕ ставят свою W3-скобку + * (вызывающий обязан обернуть в _bgi_begin/_bgi_end); self-bracket + * (_bgi_read/_bgi_hspan/_bgi_clearall) ставят скобку сами. */ + +uint8_t _bgi_mode_set(void); /* войти в режим + палитра + границы */ + +void _bgi_plot_raw (int x, int y, uint8_t color); /* точка, без скобки */ +uint8_t _bgi_read_raw (int x, int y); /* чтение, без скобки */ +void _bgi_hspan_raw(int x, int y, int len, uint8_t color); /* H-отрезок, без скобки */ +void _bgi_vspan_raw(int x, int y, int len, uint8_t color); /* V-отрезок, без скобки */ +void _bgi_clear_raw(uint8_t color); /* заливка экрана, без скобки */ + +/* Self-bracket версии (begin + raw + end) — для разовых вызовов из + * математики, которой не нужен пакетный режим (floodfill, cleardevice). + * _bgi_read возвращает цвет пикселя как unsigned (в SDCC __sdcccall(1) + * 8-битный возврат идёт в A, расширяется до int). */ +unsigned _bgi_read (int x, int y); +void _bgi_hspan (int x, int y, int len, uint8_t color); +void _bgi_clearall(uint8_t color); + +/* ---- Скретч акселератора 256 (bgi256/_gfx_acc256.c) -------------- * + * Общий для hspan/vspan/clear; однопоточно, IRQ выключены между + * _bgi_begin/_bgi_end. */ +extern uint8_t _gfx_acc_color; +extern uint8_t _gfx_acc_y; +extern uint8_t _gfx_acc_len; /* 0 = 256 — конвенция акселератора */ +extern uint16_t _gfx_acc_addr; + +/* Горизонтальный Fill-burst: _gfx_acc_len байт с _gfx_acc_addr на + * строке _gfx_acc_y (W3 замаплен, DI активен). */ +void _gfx_hfill256_chunk(void); + +/* ---- Скретч 16-цветных примитивов (bgi16/_gfx_g16_state.c) ------- */ +extern uint8_t _gfx_g16_y; +extern uint8_t _gfx_g16_byte; /* nibble | (nibble<<4) */ +extern uint8_t _gfx_g16_nibble; /* цвет в нужной половине байта */ +extern uint8_t _gfx_g16_mask; /* маска, сохраняющая ДРУГУЮ половину */ +extern uint8_t _gfx_g16_len; /* размер accel-блока (0 = 256) */ +extern uint16_t _gfx_g16_addr; + +/* Горизонтальный Fill-burst байтами _gfx_g16_byte (bgi16/_gfx_hfill16.c). */ +void _gfx_hfill16_chunk(void); + +/* RMW одного нибла по (_gfx_g16_addr, _gfx_g16_y) (bgi16/_gfx_rmw16.c). */ +void _gfx_rmw16_pixel(void); + +/* ---- Шрифт (common/_gfx_font_state.c, _gfx_font_ensure.c) -------- * + * Формат: 256 глифов × 8 рядов, INTERLEAVED — offset = row*256 + char; + * биты MSB-first. См. memory/sprinter_font_format. */ + +#define _GFX_FONT_BYTES 2048 + +extern uint8_t _gfx_font_buf[_GFX_FONT_BYTES]; +extern const uint8_t *_gfx_font_ptr; +extern uint8_t _gfx_font_loaded; + +/* Ленивая инициализация: грузит системный шрифт при первом использовании. */ +void _gfx_font_ensure(void); + +/* 8 байт строк глифа c (грузит шрифт при первом использовании) — + * mode-agnostic, просто читает _gfx_font_ptr. common/_bgi_font_rows.c. */ +void _bgi_font_rows(unsigned char c, uint8_t *rows8); + +/* ---- Тригонометрия для дуг (common/_bgi_trig.c) ------------------ * + * Угол в градусах; результат sin/cos × 128 (Q7 — чтобы радиус×значение + * влезало в int без 32-бит арифметики). */ +int _bgi_sin128(int deg); +int _bgi_cos128(int deg); + +/* Общий рисователь дуги/контура эллипса (common/_bgi_arc_draw.c): + * полилиния по точкам от stangle до endangle с полуосями xr,yr вокруг + * (cx,cy). */ +void _bgi_ellipse_arc(int cx, int cy, int stangle, int endangle, + int xr, int yr, uint8_t color); + +/* Целочисленный sqrt (0..~32767) для fillellipse (common/_bgi_isqrt.c). */ +int _bgi_isqrt(int n); + +/* ---- Состояние линий (common/_bgi_line_state.c) ------------------ */ +extern uint8_t _bgi_line_style; /* SOLID_LINE..USERBIT_LINE */ +extern uint8_t _bgi_line_thick; /* 1 (NORM) или 3 (THICK) */ +extern uint16_t _bgi_line_pattern; /* маска для USERBIT_LINE */ + +/* Отрезок текущим стилем/толщиной линии (common/_bgi_styled_line.c). */ +void _bgi_styled_line(int x0, int y0, int x1, int y1, uint8_t color); + +/* Отрезок (x0,y0)->(x1,y1) БЕЗ стиля: ортогонал → hspan/vspan, + * диагональ → Брезенхэм over _bgi_plot_raw, своя W3-скобка + * (common/_bgi_lineseg.c). Реальная логика, не обёртка. */ +void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color); + +/* ---- Состояние заливки (common/_bgi_fill_state.c) ---------------- */ +extern uint8_t _bgi_fill_pattern; /* *_FILL */ +extern uint8_t _bgi_fill_color; + +/* Залить строку [x0..x1] на y ТЕКУЩИМ стилем заливки (паттерн+цвет), + * с клипом по экрану. Вызывать между _bgi_begin/_bgi_end. */ +void _bgi_fill_span(int x0, int x1, int y); + +/* ---- Стиль текста (common/_bgi_text_state.c) --------------------- */ +extern uint8_t _bgi_text_dir; /* HORIZ_DIR / VERT_DIR */ +extern uint8_t _bgi_text_size; /* масштаб 1..10 */ + +/* Нарисовать строку s в (x,y) текущим стилем текста (масштаб/направление, + * цвет _bgi_fg, прозрачный фон) — common/_bgi_draw_scaled.c. */ +void _bgi_draw_scaled(int x, int y, const char *s); + +/* ---- Скан-таблицы min/max X по строкам для fillpoly -------------- * + * (common/_bgi_poly_state.c). GFX_HEIGHT — высота экрана (256 в обоих + * режимах), см. . */ +extern int _bgi_span_min[GFX_HEIGHT]; +extern int _bgi_span_max[GFX_HEIGHT]; + +/* Прогнать ребро (Брезенхэм) обновляя _bgi_span_min/max + * (common/_bgi_poly_edge.c). */ +void _bgi_poly_edge(int x0, int y0, int x1, int y1); + +/* ---- Cross-library: внутренние символы libc/cbl ------------------ * + * libbgi ВСЕГДА линкуется вместе с libc (sprinter.lib), поэтому + * зависимость от внутренних символов libc допустима. gfx_wait_vsync + * держит bit7 порта 0x004E через рефкаунт _cbl_port_ref/unref, чтобы + * бит 5 порта 0xFE (позиция луча) был доступен. + * ВНИМАНИЕ: это ВНУТРЕННИЕ символы libc/cbl — при изменении сигнатур + * СВЕРЯТЬ с libc/cbl/_cbl.h и синхронизировать. (По тому же паттерну, + * каким здесь живут _videomode_raw_* из libc/video.) */ +extern void _cbl_port_ref(void); +extern void _cbl_port_unref(void); + +#endif diff --git a/libc/gfx/_gfx_clear16_raw.c b/libbgi/bgi16/_bgi_clear_raw.c similarity index 76% rename from libc/gfx/_gfx_clear16_raw.c rename to libbgi/bgi16/_bgi_clear_raw.c index 94ddf97..c561091 100644 --- a/libc/gfx/_gfx_clear16_raw.c +++ b/libbgi/bgi16/_bgi_clear_raw.c @@ -1,11 +1,11 @@ /* - * _gfx_clear16_raw — залить всё поле 640×256 цветом color, mode 0x82. + * _bgi_clear_raw — залить всё поле 640×256 цветом color, mode 0x82. * Построчный hfill: 256 строк × 2 burst'а (256 + 64 байта). W3-naive. */ -#include "_gfx.h" +#include "../_bgi.h" -void _gfx_clear16_raw(uint8_t color) +void _bgi_clear_raw(uint8_t color) { _gfx_g16_byte = (uint8_t)((color & 0x0F) | ((color & 0x0F) << 4)); for (int y = 0; y < GFX_HEIGHT_16; y++) { diff --git a/libc/gfx/_gfx_hline16_raw.c b/libbgi/bgi16/_bgi_hspan_raw.c similarity index 90% rename from libc/gfx/_gfx_hline16_raw.c rename to libbgi/bgi16/_bgi_hspan_raw.c index 83b95dd..12811df 100644 --- a/libc/gfx/_gfx_hline16_raw.c +++ b/libbgi/bgi16/_bgi_hspan_raw.c @@ -1,12 +1,12 @@ /* - * _gfx_hline16_raw — горизонтальная линия len пикселей от (x,y), + * _bgi_hspan_raw — горизонтальная линия len пикселей от (x,y), * mode 0x82: невыровненные крайние ниблы через RMW, середина — * Fill-burst'ами акселератора по целым байтам. W3-naive. */ -#include "_gfx.h" +#include "../_bgi.h" -void _gfx_hline16_raw(int x, int y, int len, uint8_t color) +void _bgi_hspan_raw(int x, int y, int len, uint8_t color) { if ((unsigned)y >= GFX_HEIGHT_16) return; if (x < 0) { len += x; x = 0; } diff --git a/libc/gfx/_gfx_putpixel16_raw.c b/libbgi/bgi16/_bgi_plot_raw.c similarity index 80% rename from libc/gfx/_gfx_putpixel16_raw.c rename to libbgi/bgi16/_bgi_plot_raw.c index 46a84b4..cfe2c99 100644 --- a/libc/gfx/_gfx_putpixel16_raw.c +++ b/libbgi/bgi16/_bgi_plot_raw.c @@ -1,12 +1,12 @@ /* - * _gfx_putpixel16_raw — пиксель (x,y) цветом 0..15, mode 0x82. + * _bgi_plot_raw — пиксель (x,y) цветом 0..15, mode 0x82. * Байт по адресу _gfx_addr_base + x/2 держит два пикселя: high nibble = * ЛЕВЫЙ (чётный x), low = ПРАВЫЙ (нечётный). W3-naive. */ -#include "_gfx.h" +#include "../_bgi.h" -void _gfx_putpixel16_raw(int x, int y, uint8_t color) +void _bgi_plot_raw(int x, int y, uint8_t color) { if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return; _gfx_g16_y = (uint8_t)y; diff --git a/libc/gfx/_gfx_vline16_raw.c b/libbgi/bgi16/_bgi_vspan_raw.c similarity index 84% rename from libc/gfx/_gfx_vline16_raw.c rename to libbgi/bgi16/_bgi_vspan_raw.c index ea61ba6..edd96be 100644 --- a/libc/gfx/_gfx_vline16_raw.c +++ b/libbgi/bgi16/_bgi_vspan_raw.c @@ -1,13 +1,13 @@ /* - * _gfx_vline16_raw — вертикальная линия len пикселей от (x,y), + * _bgi_vspan_raw — вертикальная линия len пикселей от (x,y), * mode 0x82. Вертикального accel-пути нет: байт покрывает два * горизонтальных пикселя, Fill затёр бы соседний нибл — поэтому * RMW на каждую строку. W3-naive. */ -#include "_gfx.h" +#include "../_bgi.h" -void _gfx_vline16_raw(int x, int y, int len, uint8_t color) +void _bgi_vspan_raw(int x, int y, int len, uint8_t color) { if ((unsigned)x >= GFX_WIDTH_16) return; if (y < 0) { len += y; y = 0; } diff --git a/libc/gfx/_gfx_g16_state.c b/libbgi/bgi16/_gfx_g16_state.c similarity index 96% rename from libc/gfx/_gfx_g16_state.c rename to libbgi/bgi16/_gfx_g16_state.c index 008191b..6a7155a 100644 --- a/libc/gfx/_gfx_g16_state.c +++ b/libbgi/bgi16/_gfx_g16_state.c @@ -4,7 +4,7 @@ * между W3-begin/end. */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t _gfx_g16_y; uint8_t _gfx_g16_byte; /* nibble | (nibble<<4) — цвет в обе половины */ diff --git a/libc/gfx/_gfx_hfill16.c b/libbgi/bgi16/_gfx_hfill16.c similarity index 98% rename from libc/gfx/_gfx_hfill16.c rename to libbgi/bgi16/_gfx_hfill16.c index dfa3162..f00ab1d 100644 --- a/libc/gfx/_gfx_hfill16.c +++ b/libbgi/bgi16/_gfx_hfill16.c @@ -10,7 +10,7 @@ * как новый размер блока. */ -#include "_gfx.h" +#include "../_bgi.h" void _gfx_hfill16_chunk(void) __naked { diff --git a/libc/gfx/_gfx_rmw16.c b/libbgi/bgi16/_gfx_rmw16.c similarity index 98% rename from libc/gfx/_gfx_rmw16.c rename to libbgi/bgi16/_gfx_rmw16.c index f3a179c..1ce7102 100644 --- a/libc/gfx/_gfx_rmw16.c +++ b/libbgi/bgi16/_gfx_rmw16.c @@ -6,7 +6,7 @@ * Pre: W3 замаплен, DI активен. */ -#include "_gfx.h" +#include "../_bgi.h" void _gfx_rmw16_pixel(void) __naked { diff --git a/libc/gfx/_gfx_clear256_raw.c b/libbgi/bgi256/_bgi_clear_raw.c similarity index 78% rename from libc/gfx/_gfx_clear256_raw.c rename to libbgi/bgi256/_bgi_clear_raw.c index f15b442..5d557a7 100644 --- a/libc/gfx/_gfx_clear256_raw.c +++ b/libbgi/bgi256/_bgi_clear_raw.c @@ -1,12 +1,12 @@ /* - * _gfx_clear256_raw — залить всё поле 320×256 цветом color, mode 0x81. + * _bgi_clear_raw — залить всё поле 320×256 цветом color, mode 0x81. * Построчный hfill: 256 строк × 2 burst'а (256 + 64 байта) = 512. * W3-naive: вызывающий обрамляет begin/end. */ -#include "_gfx.h" +#include "../_bgi.h" -void _gfx_clear256_raw(uint8_t color) +void _bgi_clear_raw(uint8_t color) { _gfx_acc_color = color; for (int y = 0; y < GFX_HEIGHT; y++) { diff --git a/libc/gfx/_gfx_hline256_raw.c b/libbgi/bgi256/_bgi_hspan_raw.c similarity index 80% rename from libc/gfx/_gfx_hline256_raw.c rename to libbgi/bgi256/_bgi_hspan_raw.c index 87e852f..8b702ac 100644 --- a/libc/gfx/_gfx_hline256_raw.c +++ b/libbgi/bgi256/_bgi_hspan_raw.c @@ -1,12 +1,12 @@ /* - * _gfx_hline256_raw — горизонтальная линия len пикселей от (x,y), + * _bgi_hspan_raw — горизонтальная линия len пикселей от (x,y), * mode 0x81, через Fill-burst'ы акселератора (до 256 байт за выстрел). * W3-naive: вызывающий обрамляет begin/end. */ -#include "_gfx.h" +#include "../_bgi.h" -void _gfx_hline256_raw(int x, int y, int len, uint8_t color) +void _bgi_hspan_raw(int x, int y, int len, uint8_t color) { if ((unsigned)y >= GFX_HEIGHT) return; if (x < 0) { len += x; x = 0; } diff --git a/libc/bgi/drv256/_bgi_mode_set.c b/libbgi/bgi256/_bgi_mode_set.c similarity index 90% rename from libc/bgi/drv256/_bgi_mode_set.c rename to libbgi/bgi256/_bgi_mode_set.c index 8dfd0fc..597e938 100644 --- a/libc/bgi/drv256/_bgi_mode_set.c +++ b/libbgi/bgi256/_bgi_mode_set.c @@ -31,7 +31,11 @@ static const uint8_t _bgi_ega_pal[16 * 4] = { uint8_t _bgi_mode_set(void) { - uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0); + uint8_t prev = _videomode_raw_get(); + _videomode_raw_set(GFX_MODE_320x256x256); + _gfx_bank = 0x50; + gfx_set_visible_page(0); + gfx_set_draw_page(0); gfx_pal_load(0, 0, 16, _bgi_ega_pal); _bgi_maxx = GFX_WIDTH - 1; _bgi_maxy = GFX_HEIGHT - 1; diff --git a/libc/gfx/_gfx_putpixel256_raw.c b/libbgi/bgi256/_bgi_plot_raw.c similarity index 84% rename from libc/gfx/_gfx_putpixel256_raw.c rename to libbgi/bgi256/_bgi_plot_raw.c index 6c60d61..83ee5fe 100644 --- a/libc/gfx/_gfx_putpixel256_raw.c +++ b/libbgi/bgi256/_bgi_plot_raw.c @@ -1,5 +1,5 @@ /* - * _gfx_putpixel256_raw — пиксель (x,y) цветом color, mode 0x81. + * _bgi_plot_raw — пиксель (x,y) цветом color, mode 0x81. * * "Raw" = W3-naive: вызывающий уже сделал _gfx_w3_video_begin (W3 на * видеобанке, DI). Адресация: CPU _gfx_addr_base + x, Port_Y (0x89) = y. @@ -8,13 +8,13 @@ * Брезенхэма не топтал внешнее состояние акселератора. */ -#include "_gfx.h" +#include "../_bgi.h" static uint8_t _gfx_pp_y; static uint16_t _gfx_pp_addr; static uint8_t _gfx_pp_color; -void _gfx_putpixel256_raw(int x, int y, uint8_t color) +void _bgi_plot_raw(int x, int y, uint8_t color) { if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return; _gfx_pp_y = (uint8_t)y; diff --git a/libc/gfx/_gfx_getpixel256_raw.c b/libbgi/bgi256/_bgi_read_raw.c similarity index 81% rename from libc/gfx/_gfx_getpixel256_raw.c rename to libbgi/bgi256/_bgi_read_raw.c index 172bc0d..bffc51a 100644 --- a/libc/gfx/_gfx_getpixel256_raw.c +++ b/libbgi/bgi256/_bgi_read_raw.c @@ -1,17 +1,17 @@ /* - * _gfx_getpixel256_raw — прочитать пиксель (x,y) БЕЗ своей W3-скобки + * _bgi_read_raw — прочитать пиксель (x,y) БЕЗ своей W3-скобки * (вызывающий уже сделал _gfx_w3_video_begin). Для блиттинга image: * getimage/putimage читают тысячи пикселей в одной скобке. * За пределами экрана возвращает 0. */ -#include "_gfx.h" +#include "../_bgi.h" static uint8_t _gfx_gpr_y; static uint16_t _gfx_gpr_addr; static uint8_t _gfx_gpr_color; -uint8_t _gfx_getpixel256_raw(int x, int y) +uint8_t _bgi_read_raw(int x, int y) { if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return 0; _gfx_gpr_y = (uint8_t)y; diff --git a/libc/gfx/_gfx_vline256_raw.c b/libbgi/bgi256/_bgi_vspan_raw.c similarity index 90% rename from libc/gfx/_gfx_vline256_raw.c rename to libbgi/bgi256/_bgi_vspan_raw.c index 9c71cb0..ed5a64e 100644 --- a/libc/gfx/_gfx_vline256_raw.c +++ b/libbgi/bgi256/_bgi_vspan_raw.c @@ -1,10 +1,10 @@ /* - * _gfx_vline256_raw — вертикальная линия len пикселей от (x,y), + * _bgi_vspan_raw — вертикальная линия len пикселей от (x,y), * mode 0x81. Вертикальный Fill акселератора сам инкрементирует Port_Y, * так что вся колонка (высота 256) — один burst. W3-naive. */ -#include "_gfx.h" +#include "../_bgi.h" /* Вертикальный Fill: _gfx_acc_len пикселей в колонке _gfx_acc_addr, * верхняя строка _gfx_acc_y. Про SMC и правила FSM акселератора — @@ -33,7 +33,7 @@ static void vfill_chunk(void) __naked __endasm; } -void _gfx_vline256_raw(int x, int y, int len, uint8_t color) +void _bgi_vspan_raw(int x, int y, int len, uint8_t color) { if ((unsigned)x >= GFX_WIDTH) return; if (y < 0) { len += y; y = 0; } diff --git a/libc/gfx/_gfx_acc256.c b/libbgi/bgi256/_gfx_acc256.c similarity index 95% rename from libc/gfx/_gfx_acc256.c rename to libbgi/bgi256/_gfx_acc256.c index 5c1ad77..f7a9e80 100644 --- a/libc/gfx/_gfx_acc256.c +++ b/libbgi/bgi256/_gfx_acc256.c @@ -4,7 +4,7 @@ * GFX работает с выключенными прерываниями между W3-begin/end. */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t _gfx_acc_color; uint8_t _gfx_acc_y; diff --git a/libc/gfx/_gfx_hfill256.c b/libbgi/bgi256/_gfx_hfill256.c similarity index 99% rename from libc/gfx/_gfx_hfill256.c rename to libbgi/bgi256/_gfx_hfill256.c index 09a0a29..d8a108b 100644 --- a/libc/gfx/_gfx_hfill256.c +++ b/libbgi/bgi256/_gfx_hfill256.c @@ -15,7 +15,7 @@ * как новый размер блока. */ -#include "_gfx.h" +#include "../_bgi.h" void _gfx_hfill256_chunk(void) __naked { diff --git a/libbgi/bgi256/getpixel.c b/libbgi/bgi256/getpixel.c new file mode 100644 index 0000000..f1c52fb --- /dev/null +++ b/libbgi/bgi256/getpixel.c @@ -0,0 +1,33 @@ +/* + * getpixel (bgi256) — цвет пикселя (x,y), mode 0x81. Полностью inline + * (bounds + W3-скобка + чтение пикселя), без вызовов _bgi_read/raw. + * Возвращает 0 вне экрана. + */ +#include "../_bgi.h" + +static uint8_t _gp_y; +static uint16_t _gp_addr; +static uint8_t _gp_color; + +unsigned getpixel(int x, int y) +{ + if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return 0; + _gp_y = (uint8_t)y; + _gp_addr = (uint16_t)(_gfx_addr_base + (unsigned)x); + __asm + di + in a, (#0xE2) + ld (__gfx_saved_w3), a + ld a, (__gfx_bank) + out (#0xE2), a + ld a, (_gp_y) + out (#0x89), a + ld hl, (_gp_addr) + ld a, (hl) + ld (_gp_color), a + ld a, (__gfx_saved_w3) + out (#0xE2), a + ei + __endasm; + return _gp_color; +} diff --git a/libbgi/bgi256/putpixel.c b/libbgi/bgi256/putpixel.c new file mode 100644 index 0000000..414e648 --- /dev/null +++ b/libbgi/bgi256/putpixel.c @@ -0,0 +1,39 @@ +/* + * putpixel (bgi256) — точка (x,y) цветом color, mode 0x81. + * ПОЛНОСТЬЬЮ inline: bounds + W3-скобка + запись пикселя в теле, БЕЗ + * вызовов _bgi_plot / gfx_putpixel256 / _bgi_plot_raw (устранены + * прокладки старой цепочки putpixel→_bgi_plot→gfx_putpixel256→raw). + * Адресация: CPU _gfx_addr_base + x, Port_Y (0x89) = y; W3 мапится на + * _gfx_bank, сейв восстанавливается. Bounds — compile-time GFX_WIDTH/ + * HEIGHT (меньше/быстрее, ≡ runtime _bgi_maxx/_bgi_maxy). + */ +#include "../_bgi.h" + +/* File-static скретч (как в _bgi_plot_raw, но свой — putpixel не должен + * топтать скретч акселератора/plot_raw, если звать вперемешку). */ +static uint8_t _pp_y; +static uint16_t _pp_addr; +static uint8_t _pp_color; + +void putpixel(int x, int y, int color) +{ + if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return; + _pp_y = (uint8_t)y; + _pp_addr = (uint16_t)(_gfx_addr_base + (unsigned)x); + _pp_color = (uint8_t)color; + __asm + di + in a, (#0xE2) + ld (__gfx_saved_w3), a + ld a, (__gfx_bank) + out (#0xE2), a + ld a, (_pp_y) + out (#0x89), a + ld hl, (_pp_addr) + ld a, (_pp_color) + ld (hl), a + ld a, (__gfx_saved_w3) + out (#0xE2), a + ei + __endasm; +} diff --git a/libc/bgi/_bgi_arc_draw.c b/libbgi/common/_bgi_arc_draw.c similarity index 98% rename from libc/bgi/_bgi_arc_draw.c rename to libbgi/common/_bgi_arc_draw.c index 5b2754d..123bf95 100644 --- a/libc/bgi/_bgi_arc_draw.c +++ b/libbgi/common/_bgi_arc_draw.c @@ -10,7 +10,7 @@ * эллипс через (long)…>>8 рисовался прямоугольником). */ -#include "_bgi.h" +#include "../_bgi.h" void _bgi_ellipse_arc(int cx, int cy, int stangle, int endangle, int xr, int yr, uint8_t color) diff --git a/libbgi/common/_bgi_begin.c b/libbgi/common/_bgi_begin.c new file mode 100644 index 0000000..e138f6a --- /dev/null +++ b/libbgi/common/_bgi_begin.c @@ -0,0 +1,24 @@ +/* + * _bgi_begin — открыть W3-сессию для пакетного рисования: DI, сохранить + * текущую страницу W3 и замапить _gfx_bank (видеобанк 0x50..0x5F). + * Композитные примитивы обрамляют одной парой _bgi_begin/_bgi_end весь + * внутренний цикл — W3-танец оплачивается один раз на операцию, а не + * на пиксель. НЕ реентерабельно (сейв в _gfx_saved_w3): между begin и + * end IRQ выключены. + * + * Real код (поглощён из старого libc/gfx/_gfx_w3_video_begin.c) — не + * обёртка. Mode-agnostic: использует только _gfx_bank/_gfx_saved_w3. + */ +#include "../_bgi.h" + +void _bgi_begin(void) __naked +{ + __asm + di + in a, (#0xE2) + ld (__gfx_saved_w3), a + ld a, (__gfx_bank) + out (#0xE2), a + ret + __endasm; +} diff --git a/libbgi/common/_bgi_clearall.c b/libbgi/common/_bgi_clearall.c new file mode 100644 index 0000000..59fc151 --- /dev/null +++ b/libbgi/common/_bgi_clearall.c @@ -0,0 +1,13 @@ +/* + * _bgi_clearall — залить весь экран цветом, self-bracket (своя W3-скобка). + * cleardevice зовёт это фоновым цветом. Реальная композиция + * _bgi_begin + _bgi_clear_raw + _bgi_end. + */ +#include "../_bgi.h" + +void _bgi_clearall(uint8_t color) +{ + _bgi_begin(); + _bgi_clear_raw(color); + _bgi_end(); +} diff --git a/libc/bgi/_bgi_draw_scaled.c b/libbgi/common/_bgi_draw_scaled.c similarity index 98% rename from libc/bgi/_bgi_draw_scaled.c rename to libbgi/common/_bgi_draw_scaled.c index 10c703c..e9ae53d 100644 --- a/libc/bgi/_bgi_draw_scaled.c +++ b/libbgi/common/_bgi_draw_scaled.c @@ -7,7 +7,7 @@ * Каждый «пиксель» глифа — блок size×size из raw-плотов, всё в одной * W3-скобке. */ -#include "_bgi.h" +#include "../_bgi.h" void _bgi_draw_scaled(int x, int y, const char *s) { diff --git a/libbgi/common/_bgi_end.c b/libbgi/common/_bgi_end.c new file mode 100644 index 0000000..25b1adb --- /dev/null +++ b/libbgi/common/_bgi_end.c @@ -0,0 +1,15 @@ +/* + * _bgi_end — закрыть W3-сессию: восстановить сохранённую страницу W3 и + * EI. Real код (поглощён из старого libc/gfx/_gfx_w3_video_end.c). + */ +#include "../_bgi.h" + +void _bgi_end(void) __naked +{ + __asm + ld a, (__gfx_saved_w3) + out (#0xE2), a + ei + ret + __endasm; +} diff --git a/libc/bgi/_bgi_fill_span.c b/libbgi/common/_bgi_fill_span.c similarity index 98% rename from libc/bgi/_bgi_fill_span.c rename to libbgi/common/_bgi_fill_span.c index 6f051cd..b58868a 100644 --- a/libc/bgi/_bgi_fill_span.c +++ b/libbgi/common/_bgi_fill_span.c @@ -6,7 +6,7 @@ * Клип по экрану внутри. ВЫЗЫВАТЬ между _bgi_begin/_bgi_end. */ -#include "_bgi.h" +#include "../_bgi.h" /* Стандартные 8×8-паттерны Borland, индексы LINE_FILL..CLOSE_DOT_FILL. */ static const uint8_t _bgi_pat[10][8] = { diff --git a/libc/bgi/_bgi_fill_state.c b/libbgi/common/_bgi_fill_state.c similarity index 93% rename from libc/bgi/_bgi_fill_state.c rename to libbgi/common/_bgi_fill_state.c index 6bc8589..81055fa 100644 --- a/libc/bgi/_bgi_fill_state.c +++ b/libbgi/common/_bgi_fill_state.c @@ -4,7 +4,7 @@ * Без инициализации (crt0 зануляет _DATA). */ -#include "_bgi.h" +#include "../_bgi.h" uint8_t _bgi_fill_pattern; uint8_t _bgi_fill_color; diff --git a/libbgi/common/_bgi_font_rows.c b/libbgi/common/_bgi_font_rows.c new file mode 100644 index 0000000..0775afb --- /dev/null +++ b/libbgi/common/_bgi_font_rows.c @@ -0,0 +1,20 @@ +/* + * _bgi_font_rows — 8 байт строк глифа символа c (mode-agnostic: просто + * читает шрифт через _gfx_font_ptr). Шрифт системный, interleaved: + * offset = row*256 + char (MSB-first), см. memory/sprinter_font_format. + * Грузится лениво (_gfx_font_ensure) при первом использовании. + * + * Раньше жил в drv256/ по недосмотру — перенесён в common/, т.к. логика + * не зависит от видеорежима (один и тот же .rel в bgi256.lib и bgi16.lib). + */ +#include "../_bgi.h" + +void _bgi_font_rows(unsigned char c, uint8_t *rows8) +{ + const uint8_t *f; + int r; + _gfx_font_ensure(); + f = _gfx_font_ptr; + for (r = 0; r < 8; r++) + rows8[r] = f[r * 256 + c]; +} diff --git a/libbgi/common/_bgi_hspan.c b/libbgi/common/_bgi_hspan.c new file mode 100644 index 0000000..01f3b33 --- /dev/null +++ b/libbgi/common/_bgi_hspan.c @@ -0,0 +1,13 @@ +/* + * _bgi_hspan — горизонтальный отрезок len пикселей от (x,y), self-bracket + * (своя W3-скобка). Для floodfill (заливка строки вне пакетной сессии). + * Реальная композиция _bgi_begin + _bgi_hspan_raw + _bgi_end. + */ +#include "../_bgi.h" + +void _bgi_hspan(int x, int y, int len, uint8_t color) +{ + _bgi_begin(); + _bgi_hspan_raw(x, y, len, color); + _bgi_end(); +} diff --git a/libc/bgi/_bgi_isqrt.c b/libbgi/common/_bgi_isqrt.c similarity index 94% rename from libc/bgi/_bgi_isqrt.c rename to libbgi/common/_bgi_isqrt.c index e58a6bf..666bb44 100644 --- a/libc/bgi/_bgi_isqrt.c +++ b/libbgi/common/_bgi_isqrt.c @@ -4,7 +4,7 @@ * без float и 32-бит. */ -#include "_bgi.h" +#include "../_bgi.h" int _bgi_isqrt(int n) { diff --git a/libc/bgi/_bgi_line_state.c b/libbgi/common/_bgi_line_state.c similarity index 92% rename from libc/bgi/_bgi_line_state.c rename to libbgi/common/_bgi_line_state.c index f66ad51..f8e44b4 100644 --- a/libc/bgi/_bgi_line_state.c +++ b/libbgi/common/_bgi_line_state.c @@ -2,7 +2,7 @@ * _bgi_line_state — текущий стиль/толщина/маска линий BGI. * initgraph ставит SOLID_LINE / NORM / 0xFFFF. Без инициализации. */ -#include "_bgi.h" +#include "../_bgi.h" uint8_t _bgi_line_style; uint8_t _bgi_line_thick; diff --git a/libbgi/common/_bgi_lineseg.c b/libbgi/common/_bgi_lineseg.c new file mode 100644 index 0000000..222fb05 --- /dev/null +++ b/libbgi/common/_bgi_lineseg.c @@ -0,0 +1,49 @@ +/* + * _bgi_lineseg — отрезок (x0,y0)->(x1,y1) БЕЗ стиля/толщины (SOLID+NORM). + * Real логика (поглощена из старого libc/gfx/gfx_line256.c), не обёртка. + * + * Ортогональные отрезки уходят на driver-leaf'ы _bgi_hspan_raw / + * _bgi_vspan_raw (акселератор); наклонные — Брезенхэм поточечно через + * _bgi_plot_raw. Каждый путь ставит свою W3-скобку (_bgi_begin/_bgi_end) + * — вызывать _bgi_lineseg ВНЕ чужой скобки (W3-сейв не реентерабелен). + * Вызывают: _bgi_styled_line (SOLID+NORM), _bgi_arc_draw, fillpoly, + * sector — все вне скобки. + */ +#include "../_bgi.h" + +void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color) +{ + /* Горизонталь — один H-burst. */ + if (y0 == y1) { + int x = x0 <= x1 ? x0 : x1; + int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1; + _bgi_begin(); + _bgi_hspan_raw(x, y0, w, color); + _bgi_end(); + return; + } + /* Вертикаль — один V-burst (256) или RMW-цикл (16). */ + if (x0 == x1) { + int y = y0 <= y1 ? y0 : y1; + int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1; + _bgi_begin(); + _bgi_vspan_raw(x0, y, h, color); + _bgi_end(); + return; + } + + /* Наклонный — Брезенхэм в одной W3-скобке. */ + int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx; + int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy; + int err = (dx > dy ? dx : -dy) / 2; + int x = x0, y = y0; + _bgi_begin(); + for (;;) { + _bgi_plot_raw(x, y, color); + if (x == x1 && y == y1) break; + int e2 = err; + if (e2 > -dx) { err -= dy; x += sx; } + if (e2 < dy) { err += dx; y += sy; } + } + _bgi_end(); +} diff --git a/libc/bgi/_bgi_poly_edge.c b/libbgi/common/_bgi_poly_edge.c similarity index 97% rename from libc/bgi/_bgi_poly_edge.c rename to libbgi/common/_bgi_poly_edge.c index e382773..63f8455 100644 --- a/libc/bgi/_bgi_poly_edge.c +++ b/libbgi/common/_bgi_poly_edge.c @@ -5,7 +5,7 @@ * пропускаются. Заливка потом идёт от min до max по строке. */ -#include "_bgi.h" +#include "../_bgi.h" void _bgi_poly_edge(int x0, int y0, int x1, int y1) { diff --git a/libc/bgi/_bgi_poly_state.c b/libbgi/common/_bgi_poly_state.c similarity index 95% rename from libc/bgi/_bgi_poly_state.c rename to libbgi/common/_bgi_poly_state.c index d1044fe..a3e70d3 100644 --- a/libc/bgi/_bgi_poly_state.c +++ b/libbgi/common/_bgi_poly_state.c @@ -5,7 +5,7 @@ * однопоточно (рисование не реентерабельно). */ -#include "_bgi.h" +#include "../_bgi.h" int _bgi_span_min[GFX_HEIGHT]; int _bgi_span_max[GFX_HEIGHT]; diff --git a/libbgi/common/_bgi_read.c b/libbgi/common/_bgi_read.c new file mode 100644 index 0000000..d29ebe1 --- /dev/null +++ b/libbgi/common/_bgi_read.c @@ -0,0 +1,16 @@ +/* + * _bgi_read — цвет пикселя (x,y), self-bracket (своя W3-скобка). + * Для разовых чтений из математики, которой не нужен пакетный режим + * (floodfill). getpixel тоже зовёт это. Реальная композиция + * _bgi_begin + _bgi_read_raw + _bgi_end — не обёртка над обёрткой. + */ +#include "../_bgi.h" + +unsigned _bgi_read(int x, int y) +{ + unsigned c; + _bgi_begin(); + c = _bgi_read_raw(x, y); + _bgi_end(); + return c; +} diff --git a/libc/bgi/_bgi_state.c b/libbgi/common/_bgi_state.c similarity index 95% rename from libc/bgi/_bgi_state.c rename to libbgi/common/_bgi_state.c index a5e9ffc..4d25fd1 100644 --- a/libc/bgi/_bgi_state.c +++ b/libbgi/common/_bgi_state.c @@ -6,7 +6,7 @@ * выставляет initgraph(). */ -#include "_bgi.h" +#include "../_bgi.h" uint8_t _bgi_fg; uint8_t _bgi_bg; diff --git a/libc/bgi/_bgi_styled_line.c b/libbgi/common/_bgi_styled_line.c similarity index 98% rename from libc/bgi/_bgi_styled_line.c rename to libbgi/common/_bgi_styled_line.c index 415f649..8c2b812 100644 --- a/libc/bgi/_bgi_styled_line.c +++ b/libbgi/common/_bgi_styled_line.c @@ -6,7 +6,7 @@ * дублированием перпендикулярно основной оси (±1). Всё raw в одной * W3-скобке. */ -#include "_bgi.h" +#include "../_bgi.h" /* Маски стандартных стилей (SOLID/DOTTED/CENTER/DASHED). */ static const uint16_t _bgi_line_pat[4] = { 0xFFFF, 0xCCCC, 0xFF18, 0xF8F8 }; diff --git a/libc/bgi/_bgi_text_state.c b/libbgi/common/_bgi_text_state.c similarity index 91% rename from libc/bgi/_bgi_text_state.c rename to libbgi/common/_bgi_text_state.c index 5c4e664..fa7c1d8 100644 --- a/libc/bgi/_bgi_text_state.c +++ b/libbgi/common/_bgi_text_state.c @@ -2,7 +2,7 @@ * _bgi_text_state — направление и масштаб текста BGI. * initgraph ставит HORIZ_DIR / size 1. Без инициализации. */ -#include "_bgi.h" +#include "../_bgi.h" uint8_t _bgi_text_dir; uint8_t _bgi_text_size; diff --git a/libc/bgi/_bgi_trig.c b/libbgi/common/_bgi_trig.c similarity index 98% rename from libc/bgi/_bgi_trig.c rename to libbgi/common/_bgi_trig.c index 6b84c47..5ac287d 100644 --- a/libc/bgi/_bgi_trig.c +++ b/libbgi/common/_bgi_trig.c @@ -9,7 +9,7 @@ * (см. memory/avoid_32bit_arith_z80; ловили эллипс-в-прямоугольник). */ -#include "_bgi.h" +#include "../_bgi.h" /* sin(0°..90°) × 128. */ static const int _bgi_sintab[91] = { diff --git a/libc/gfx/_gfx_font_ensure.c b/libbgi/common/_gfx_font_ensure.c similarity index 95% rename from libc/gfx/_gfx_font_ensure.c rename to libbgi/common/_gfx_font_ensure.c index 26863e8..e48e61d 100644 --- a/libc/gfx/_gfx_font_ensure.c +++ b/libbgi/common/_gfx_font_ensure.c @@ -4,7 +4,7 @@ * использовании (чисто графическая программа BIOS-вызов не платит). */ -#include "_gfx.h" +#include "../_bgi.h" void _gfx_font_ensure(void) { diff --git a/libc/gfx/_gfx_font_state.c b/libbgi/common/_gfx_font_state.c similarity index 97% rename from libc/gfx/_gfx_font_state.c rename to libbgi/common/_gfx_font_state.c index 4225c0a..3c23f84 100644 --- a/libc/gfx/_gfx_font_state.c +++ b/libbgi/common/_gfx_font_state.c @@ -9,7 +9,7 @@ * _gfx_font_ensure(); программы могут подменить шрифт gfx_set_font(). */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t _gfx_font_buf[_GFX_FONT_BYTES]; const uint8_t *_gfx_font_ptr = _gfx_font_buf; diff --git a/libc/gfx/_gfx_state.c b/libbgi/common/_gfx_state.c similarity index 89% rename from libc/gfx/_gfx_state.c rename to libbgi/common/_gfx_state.c index b98d68f..60ec462 100644 --- a/libc/gfx/_gfx_state.c +++ b/libbgi/common/_gfx_state.c @@ -1,11 +1,11 @@ /* * _gfx_state — общее состояние графики (модуль только с данными). * - * Пишут gfx_init / gfx_set_visible_page / gfx_set_draw_page / + * Пишут gfx_set_visible_page / gfx_set_draw_page / * gfx_set_bank; читают все mode-специфичные примитивы. */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t _gfx_visible_page; uint8_t _gfx_draw_page; diff --git a/libc/gfx/_gfx_w3_state.c b/libbgi/common/_gfx_w3_state.c similarity index 94% rename from libc/gfx/_gfx_w3_state.c rename to libbgi/common/_gfx_w3_state.c index 7ff33a6..650cdd9 100644 --- a/libc/gfx/_gfx_w3_state.c +++ b/libbgi/common/_gfx_w3_state.c @@ -5,6 +5,6 @@ * прерывания выключенными между _gfx_w3_video_begin и _end. */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t _gfx_saved_w3; diff --git a/libc/bgi/arc.c b/libbgi/common/arc.c similarity index 92% rename from libc/bgi/arc.c rename to libbgi/common/arc.c index f07840c..b7fd122 100644 --- a/libc/bgi/arc.c +++ b/libbgi/common/arc.c @@ -1,5 +1,5 @@ /* arc — дуга окружности радиуса r от stangle до endangle (градусы). */ -#include "_bgi.h" +#include "../_bgi.h" void arc(int x, int y, int stangle, int endangle, int radius) { diff --git a/libc/bgi/bar.c b/libbgi/common/bar.c similarity index 96% rename from libc/bgi/bar.c rename to libbgi/common/bar.c index d1b8601..72595ed 100644 --- a/libc/bgi/bar.c +++ b/libbgi/common/bar.c @@ -2,7 +2,7 @@ * bar — залитый прямоугольник (left,top)-(right,bottom) включительно * ТЕКУЩИМ стилем заливки (setfillstyle), без рамки — как в Turbo-C. */ -#include "_bgi.h" +#include "../_bgi.h" void bar(int left, int top, int right, int bottom) { diff --git a/libc/bgi/bar3d.c b/libbgi/common/bar3d.c similarity index 98% rename from libc/bgi/bar3d.c rename to libbgi/common/bar3d.c index 2e9128c..0209533 100644 --- a/libc/bgi/bar3d.c +++ b/libbgi/common/bar3d.c @@ -3,7 +3,7 @@ * заливки, рёбра — текущим цветом рисования. depth — глубина (вправо- * вверх), topflag != 0 рисует верхнюю грань. */ -#include "_bgi.h" +#include "../_bgi.h" void bar3d(int left, int top, int right, int bottom, int depth, int topflag) { diff --git a/libc/bgi/circle.c b/libbgi/common/circle.c similarity index 98% rename from libc/bgi/circle.c rename to libbgi/common/circle.c index 3318b16..21db215 100644 --- a/libc/bgi/circle.c +++ b/libbgi/common/circle.c @@ -6,7 +6,7 @@ * raw-плот — иначе скобка на каждый пиксель делает большие окружности * мучительно медленными (тысячи DI/EI). */ -#include "_bgi.h" +#include "../_bgi.h" void circle(int cx, int cy, int r) { diff --git a/libc/bgi/cleardevice.c b/libbgi/common/cleardevice.c similarity index 90% rename from libc/bgi/cleardevice.c rename to libbgi/common/cleardevice.c index 4724dbf..a218b8c 100644 --- a/libc/bgi/cleardevice.c +++ b/libbgi/common/cleardevice.c @@ -1,5 +1,5 @@ /* cleardevice — очистить экран фоновым цветом, вернуть CP в (0,0). */ -#include "_bgi.h" +#include "../_bgi.h" void cleardevice(void) { diff --git a/libbgi/common/closegraph.c b/libbgi/common/closegraph.c new file mode 100644 index 0000000..56b637d --- /dev/null +++ b/libbgi/common/closegraph.c @@ -0,0 +1,8 @@ +/* closegraph — вернуть текстовый режим, действовавший до initgraph. + * _bgi_mode_done удалён — _videomode_raw_set (mode-agnostic) */ +#include "../_bgi.h" + +void closegraph(void) +{ + _videomode_raw_set(_bgi_prevmode); +} diff --git a/libc/bgi/drawpoly.c b/libbgi/common/drawpoly.c similarity index 96% rename from libc/bgi/drawpoly.c rename to libbgi/common/drawpoly.c index 9f0ec46..f29e12d 100644 --- a/libc/bgi/drawpoly.c +++ b/libbgi/common/drawpoly.c @@ -3,7 +3,7 @@ * текущим цветом. Как в Turbo-C, контур НЕ замыкается автоматически: * чтобы получить замкнутый полигон, повторите первую точку последней. */ -#include "_bgi.h" +#include "../_bgi.h" void drawpoly(int numpoints, const int *polypoints) { diff --git a/libc/bgi/ellipse.c b/libbgi/common/ellipse.c similarity index 94% rename from libc/bgi/ellipse.c rename to libbgi/common/ellipse.c index f6fbdc9..3f9fa3b 100644 --- a/libc/bgi/ellipse.c +++ b/libbgi/common/ellipse.c @@ -2,7 +2,7 @@ * ellipse — контур эллипса/эллиптической дуги с полуосями xradius, * yradius от stangle до endangle. Полный эллипс: stangle=0,endangle=360. */ -#include "_bgi.h" +#include "../_bgi.h" void ellipse(int x, int y, int stangle, int endangle, int xradius, int yradius) diff --git a/libc/bgi/fillellipse.c b/libbgi/common/fillellipse.c similarity index 97% rename from libc/bgi/fillellipse.c rename to libbgi/common/fillellipse.c index ae7b4d1..a9b1ac4 100644 --- a/libc/bgi/fillellipse.c +++ b/libbgi/common/fillellipse.c @@ -6,7 +6,7 @@ * _bgi_isqrt). ry²,dy² ≤ ~180² < 32767, rx*s ≤ rx*ry < 32767 — без * 32-бит (см. memory/avoid_32bit_arith_z80). */ -#include "_bgi.h" +#include "../_bgi.h" void fillellipse(int cx, int cy, int rx, int ry) { diff --git a/libc/bgi/fillpoly.c b/libbgi/common/fillpoly.c similarity index 98% rename from libc/bgi/fillpoly.c rename to libbgi/common/fillpoly.c index d17372d..d7bc3ea 100644 --- a/libc/bgi/fillpoly.c +++ b/libbgi/common/fillpoly.c @@ -8,7 +8,7 @@ * оболочка по строкам (упрощение). Крайние X даёт брезенхэмовский * проход рёбер (_bgi_poly_edge) — без 32-бит арифметики. */ -#include "_bgi.h" +#include "../_bgi.h" void fillpoly(int numpoints, const int *polypoints) { diff --git a/libc/bgi/floodfill.c b/libbgi/common/floodfill.c similarity index 99% rename from libc/bgi/floodfill.c rename to libbgi/common/floodfill.c index df1bec1..96aa892 100644 --- a/libc/bgi/floodfill.c +++ b/libbgi/common/floodfill.c @@ -15,7 +15,7 @@ * фигурах) — компромисс по памяти. */ -#include "_bgi.h" +#include "../_bgi.h" #define FF_STACK 300 static int ff_sx[FF_STACK]; diff --git a/libc/bgi/getbkcolor.c b/libbgi/common/getbkcolor.c similarity index 83% rename from libc/bgi/getbkcolor.c rename to libbgi/common/getbkcolor.c index c907e85..67e74cb 100644 --- a/libc/bgi/getbkcolor.c +++ b/libbgi/common/getbkcolor.c @@ -1,5 +1,5 @@ /* getbkcolor — текущий фоновый цвет. */ -#include "_bgi.h" +#include "../_bgi.h" int getbkcolor(void) { diff --git a/libc/bgi/getcolor.c b/libbgi/common/getcolor.c similarity index 83% rename from libc/bgi/getcolor.c rename to libbgi/common/getcolor.c index e0c2b0d..65cf2c7 100644 --- a/libc/bgi/getcolor.c +++ b/libbgi/common/getcolor.c @@ -1,5 +1,5 @@ /* getcolor — текущий цвет рисования. */ -#include "_bgi.h" +#include "../_bgi.h" int getcolor(void) { diff --git a/libc/bgi/getfillsettings.c b/libbgi/common/getfillsettings.c similarity index 92% rename from libc/bgi/getfillsettings.c rename to libbgi/common/getfillsettings.c index f7eda81..2c39883 100644 --- a/libc/bgi/getfillsettings.c +++ b/libbgi/common/getfillsettings.c @@ -1,5 +1,5 @@ /* getfillsettings — прочитать текущий паттерн и цвет заливки. */ -#include "_bgi.h" +#include "../_bgi.h" void getfillsettings(struct fillsettingstype *fillinfo) { diff --git a/libc/bgi/getimage.c b/libbgi/common/getimage.c similarity index 97% rename from libc/bgi/getimage.c rename to libbgi/common/getimage.c index 982dd31..176c71d 100644 --- a/libc/bgi/getimage.c +++ b/libbgi/common/getimage.c @@ -3,7 +3,7 @@ * Формат: uint16 width, uint16 height, затем w*h байт (по строкам). * Чтение raw в одной W3-скобке. */ -#include "_bgi.h" +#include "../_bgi.h" void getimage(int left, int top, int right, int bottom, void *bitmap) { diff --git a/libc/bgi/getlinesettings.c b/libbgi/common/getlinesettings.c similarity index 93% rename from libc/bgi/getlinesettings.c rename to libbgi/common/getlinesettings.c index 7a5b74c..8d428f2 100644 --- a/libc/bgi/getlinesettings.c +++ b/libbgi/common/getlinesettings.c @@ -1,5 +1,5 @@ /* getlinesettings — прочитать текущий стиль/маску/толщину линий. */ -#include "_bgi.h" +#include "../_bgi.h" void getlinesettings(struct linesettingstype *lineinfo) { diff --git a/libc/bgi/getmaxcolor.c b/libbgi/common/getmaxcolor.c similarity index 88% rename from libc/bgi/getmaxcolor.c rename to libbgi/common/getmaxcolor.c index d862c74..f011be4 100644 --- a/libc/bgi/getmaxcolor.c +++ b/libbgi/common/getmaxcolor.c @@ -1,5 +1,5 @@ /* getmaxcolor — максимальный индекс цвета (255 в 256-цветном режиме). */ -#include "_bgi.h" +#include "../_bgi.h" int getmaxcolor(void) { diff --git a/libc/bgi/getmaxx.c b/libbgi/common/getmaxx.c similarity index 86% rename from libc/bgi/getmaxx.c rename to libbgi/common/getmaxx.c index 0e326e5..830042e 100644 --- a/libc/bgi/getmaxx.c +++ b/libbgi/common/getmaxx.c @@ -1,5 +1,5 @@ /* getmaxx — максимальная координата X (ширина-1). */ -#include "_bgi.h" +#include "../_bgi.h" int getmaxx(void) { diff --git a/libc/bgi/getmaxy.c b/libbgi/common/getmaxy.c similarity index 86% rename from libc/bgi/getmaxy.c rename to libbgi/common/getmaxy.c index b7f63c0..a018431 100644 --- a/libc/bgi/getmaxy.c +++ b/libbgi/common/getmaxy.c @@ -1,5 +1,5 @@ /* getmaxy — максимальная координата Y (высота-1). */ -#include "_bgi.h" +#include "../_bgi.h" int getmaxy(void) { diff --git a/libc/bgi/gettextsettings.c b/libbgi/common/gettextsettings.c similarity index 94% rename from libc/bgi/gettextsettings.c rename to libbgi/common/gettextsettings.c index 1d0217b..d0ad6fe 100644 --- a/libc/bgi/gettextsettings.c +++ b/libbgi/common/gettextsettings.c @@ -1,5 +1,5 @@ /* gettextsettings — текущий стиль текста (justify не реализован → 0). */ -#include "_bgi.h" +#include "../_bgi.h" void gettextsettings(struct textsettingstype *textinfo) { diff --git a/libc/bgi/getx.c b/libbgi/common/getx.c similarity index 80% rename from libc/bgi/getx.c rename to libbgi/common/getx.c index b1cf7a3..5635ae3 100644 --- a/libc/bgi/getx.c +++ b/libbgi/common/getx.c @@ -1,5 +1,5 @@ /* getx — текущая позиция X. */ -#include "_bgi.h" +#include "../_bgi.h" int getx(void) { diff --git a/libc/bgi/gety.c b/libbgi/common/gety.c similarity index 80% rename from libc/bgi/gety.c rename to libbgi/common/gety.c index 35dc83d..7a17b14 100644 --- a/libc/bgi/gety.c +++ b/libbgi/common/gety.c @@ -1,5 +1,5 @@ /* gety — текущая позиция Y. */ -#include "_bgi.h" +#include "../_bgi.h" int gety(void) { diff --git a/libc/gfx/gfx_get_bank.c b/libbgi/common/gfx_get_bank.c similarity index 86% rename from libc/gfx/gfx_get_bank.c rename to libbgi/common/gfx_get_bank.c index a7cbc79..8ce444f 100644 --- a/libc/gfx/gfx_get_bank.c +++ b/libbgi/common/gfx_get_bank.c @@ -2,7 +2,7 @@ * gfx_get_bank — текущий байт страницы W3 (0x50..0x5F). */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t gfx_get_bank(void) { diff --git a/libc/gfx/gfx_get_draw_page.c b/libbgi/common/gfx_get_draw_page.c similarity index 89% rename from libc/gfx/gfx_get_draw_page.c rename to libbgi/common/gfx_get_draw_page.c index a67e9a8..c5340e6 100644 --- a/libc/gfx/gfx_get_draw_page.c +++ b/libbgi/common/gfx_get_draw_page.c @@ -2,7 +2,7 @@ * gfx_get_draw_page — кэшированный номер рисуемой страницы (0/1). */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t gfx_get_draw_page(void) { diff --git a/libc/gfx/gfx_get_visible_page.c b/libbgi/common/gfx_get_visible_page.c similarity index 89% rename from libc/gfx/gfx_get_visible_page.c rename to libbgi/common/gfx_get_visible_page.c index e54fd4b..46d0a14 100644 --- a/libc/gfx/gfx_get_visible_page.c +++ b/libbgi/common/gfx_get_visible_page.c @@ -2,7 +2,7 @@ * gfx_get_visible_page — кэшированный номер видимой страницы (0/1). */ -#include "_gfx.h" +#include "../_bgi.h" uint8_t gfx_get_visible_page(void) { diff --git a/libc/gfx/gfx_load_default_font.c b/libbgi/common/gfx_load_default_font.c similarity index 97% rename from libc/gfx/gfx_load_default_font.c rename to libbgi/common/gfx_load_default_font.c index 5e28f3d..0799cf8 100644 --- a/libc/gfx/gfx_load_default_font.c +++ b/libbgi/common/gfx_load_default_font.c @@ -3,7 +3,7 @@ * через BIOS WIN_GET_ZG (fn 0xB8) в _gfx_font_buf и включить его. */ -#include "_gfx.h" +#include "../_bgi.h" /* BIOS WIN_GET_ZG (0xB8): DE = приёмник, возвращает 2 КБ. */ static void bios_get_zg(uint8_t *dest) __naked diff --git a/libc/gfx/gfx_pal_get.c b/libbgi/common/gfx_pal_get.c similarity index 94% rename from libc/gfx/gfx_pal_get.c rename to libbgi/common/gfx_pal_get.c index d9419e9..883cabe 100644 --- a/libc/gfx/gfx_pal_get.c +++ b/libbgi/common/gfx_pal_get.c @@ -3,7 +3,7 @@ * обёртка над pal_get (libc/video) — не на горячем пути. */ -#include "_gfx.h" +#include "../_bgi.h" #include void gfx_pal_get(uint8_t pal_num, uint8_t start, uint8_t count, diff --git a/libc/gfx/gfx_pal_get_color.c b/libbgi/common/gfx_pal_get_color.c similarity index 95% rename from libc/gfx/gfx_pal_get_color.c rename to libbgi/common/gfx_pal_get_color.c index b958794..99888a1 100644 --- a/libc/gfx/gfx_pal_get_color.c +++ b/libbgi/common/gfx_pal_get_color.c @@ -3,7 +3,7 @@ * R/G/B (любой указатель может быть NULL); обёртка над pal_get_color. */ -#include "_gfx.h" +#include "../_bgi.h" #include void gfx_pal_get_color(uint8_t pal_num, uint8_t idx, diff --git a/libc/gfx/gfx_pal_load.c b/libbgi/common/gfx_pal_load.c similarity index 98% rename from libc/gfx/gfx_pal_load.c rename to libbgi/common/gfx_pal_load.c index d7e32d7..c25eedc 100644 --- a/libc/gfx/gfx_pal_load.c +++ b/libbgi/common/gfx_pal_load.c @@ -8,7 +8,7 @@ * палитру (следующая печать в текстовом режиме вешалась). */ -#include "_gfx.h" +#include "../_bgi.h" #include static uint8_t gpl_num_; diff --git a/libc/gfx/gfx_pal_reset.c b/libbgi/common/gfx_pal_reset.c similarity index 91% rename from libc/gfx/gfx_pal_reset.c rename to libbgi/common/gfx_pal_reset.c index 67a52f0..27b5624 100644 --- a/libc/gfx/gfx_pal_reset.c +++ b/libbgi/common/gfx_pal_reset.c @@ -3,7 +3,7 @@ * (BIOS $A6, type = PAL_GRAPH). */ -#include "_gfx.h" +#include "../_bgi.h" #include void gfx_pal_reset(void) diff --git a/libc/gfx/gfx_pal_set.c b/libbgi/common/gfx_pal_set.c similarity index 95% rename from libc/gfx/gfx_pal_set.c rename to libbgi/common/gfx_pal_set.c index 7546b3d..036945c 100644 --- a/libc/gfx/gfx_pal_set.c +++ b/libbgi/common/gfx_pal_set.c @@ -3,7 +3,7 @@ * четвёрку (B, G, R, 0) и зовёт gfx_pal_load(pal_num, idx, 1, ...). */ -#include "_gfx.h" +#include "../_bgi.h" void gfx_pal_set(uint8_t pal_num, uint8_t idx, uint8_t r, uint8_t g, uint8_t b) diff --git a/libc/gfx/gfx_set_bank.c b/libbgi/common/gfx_set_bank.c similarity index 88% rename from libc/gfx/gfx_set_bank.c rename to libbgi/common/gfx_set_bank.c index 5c0ae44..914af9f 100644 --- a/libc/gfx/gfx_set_bank.c +++ b/libbgi/common/gfx_set_bank.c @@ -2,7 +2,7 @@ * gfx_set_bank — задать байт страницы W3 (0x50..0x5F) для gfx-записей. */ -#include "_gfx.h" +#include "../_bgi.h" void gfx_set_bank(uint8_t bank) { diff --git a/libc/gfx/gfx_set_draw_page.c b/libbgi/common/gfx_set_draw_page.c similarity index 96% rename from libc/gfx/gfx_set_draw_page.c rename to libbgi/common/gfx_set_draw_page.c index c7e10be..04d9b30 100644 --- a/libc/gfx/gfx_set_draw_page.c +++ b/libbgi/common/gfx_set_draw_page.c @@ -3,7 +3,7 @@ * _gfx_addr_base, который читают все примитивы. */ -#include "_gfx.h" +#include "../_bgi.h" void gfx_set_draw_page(uint8_t page) { diff --git a/libc/gfx/gfx_set_font.c b/libbgi/common/gfx_set_font.c similarity index 93% rename from libc/gfx/gfx_set_font.c rename to libbgi/common/gfx_set_font.c index f665bab..19fe523 100644 --- a/libc/gfx/gfx_set_font.c +++ b/libbgi/common/gfx_set_font.c @@ -3,7 +3,7 @@ * storage должен жить, пока шрифт активен). Формат см. _gfx.h. */ -#include "_gfx.h" +#include "../_bgi.h" void gfx_set_font(const uint8_t *font) { diff --git a/libc/gfx/gfx_set_visible_page.c b/libbgi/common/gfx_set_visible_page.c similarity index 97% rename from libc/gfx/gfx_set_visible_page.c rename to libbgi/common/gfx_set_visible_page.c index c29c88a..5434e86 100644 --- a/libc/gfx/gfx_set_visible_page.c +++ b/libbgi/common/gfx_set_visible_page.c @@ -6,7 +6,7 @@ * (один из свопов показывается чёрным). Через syscall DSS доволен. */ -#include "_gfx.h" +#include "../_bgi.h" void gfx_set_visible_page(uint8_t page) { diff --git a/libc/gfx/gfx_wait_vsync.c b/libbgi/common/gfx_wait_vsync.c similarity index 98% rename from libc/gfx/gfx_wait_vsync.c rename to libbgi/common/gfx_wait_vsync.c index 469d8df..400ed5a 100644 --- a/libc/gfx/gfx_wait_vsync.c +++ b/libbgi/common/gfx_wait_vsync.c @@ -19,8 +19,7 @@ * зависнуть намертво. */ -#include "_gfx.h" -#include "../cbl/_cbl.h" +#include "../_bgi.h" #include static uint8_t vsync_ready; diff --git a/libc/bgi/graphresult.c b/libbgi/common/graphresult.c similarity index 90% rename from libc/bgi/graphresult.c rename to libbgi/common/graphresult.c index c7f4511..4975dad 100644 --- a/libc/bgi/graphresult.c +++ b/libbgi/common/graphresult.c @@ -1,5 +1,5 @@ /* graphresult — код последней ошибки; вызов сбрасывает его в grOk. */ -#include "_bgi.h" +#include "../_bgi.h" int graphresult(void) { diff --git a/libc/bgi/imagesize.c b/libbgi/common/imagesize.c similarity index 97% rename from libc/bgi/imagesize.c rename to libbgi/common/imagesize.c index 81635e8..56ff444 100644 --- a/libc/bgi/imagesize.c +++ b/libbgi/common/imagesize.c @@ -6,7 +6,7 @@ * Произведение w*h считаем в unsigned — для валидных (<64 КБ) образов * умещается точно; без 32-бит. */ -#include "_bgi.h" +#include "../_bgi.h" unsigned imagesize(int left, int top, int right, int bottom) { diff --git a/libc/bgi/initgraph.c b/libbgi/common/initgraph.c similarity index 97% rename from libc/bgi/initgraph.c rename to libbgi/common/initgraph.c index 27b6bd0..c884129 100644 --- a/libc/bgi/initgraph.c +++ b/libbgi/common/initgraph.c @@ -5,7 +5,7 @@ * 320×256×256). По умолчанию: цвет WHITE, фон BLACK, позиция (0,0). */ -#include "_bgi.h" +#include "../_bgi.h" void initgraph(void) { diff --git a/libc/bgi/line.c b/libbgi/common/line.c similarity index 90% rename from libc/bgi/line.c rename to libbgi/common/line.c index c9a0b42..45313a6 100644 --- a/libc/bgi/line.c +++ b/libbgi/common/line.c @@ -1,5 +1,5 @@ /* line — отрезок (x1,y1)->(x2,y2) текущим цветом; CP не меняется. */ -#include "_bgi.h" +#include "../_bgi.h" void line(int x1, int y1, int x2, int y2) { diff --git a/libc/bgi/linerel.c b/libbgi/common/linerel.c similarity index 92% rename from libc/bgi/linerel.c rename to libbgi/common/linerel.c index bbb0c27..9cb1f70 100644 --- a/libc/bgi/linerel.c +++ b/libbgi/common/linerel.c @@ -1,5 +1,5 @@ /* linerel — линия от CP до CP+(dx,dy); CP сдвигается в конец. */ -#include "_bgi.h" +#include "../_bgi.h" void linerel(int dx, int dy) { diff --git a/libc/bgi/lineto.c b/libbgi/common/lineto.c similarity index 90% rename from libc/bgi/lineto.c rename to libbgi/common/lineto.c index 7fe6291..ad7295e 100644 --- a/libc/bgi/lineto.c +++ b/libbgi/common/lineto.c @@ -1,5 +1,5 @@ /* lineto — линия от CP до (x,y) текущим цветом; CP := (x,y). */ -#include "_bgi.h" +#include "../_bgi.h" void lineto(int x, int y) { diff --git a/libc/bgi/moverel.c b/libbgi/common/moverel.c similarity index 88% rename from libc/bgi/moverel.c rename to libbgi/common/moverel.c index b3dd510..273236b 100644 --- a/libc/bgi/moverel.c +++ b/libbgi/common/moverel.c @@ -1,5 +1,5 @@ /* moverel — сдвинуть текущую позицию относительно. */ -#include "_bgi.h" +#include "../_bgi.h" void moverel(int dx, int dy) { diff --git a/libc/bgi/moveto.c b/libbgi/common/moveto.c similarity index 86% rename from libc/bgi/moveto.c rename to libbgi/common/moveto.c index 8a3b7fa..8c592da 100644 --- a/libc/bgi/moveto.c +++ b/libbgi/common/moveto.c @@ -1,5 +1,5 @@ /* moveto — задать текущую позицию (CP). */ -#include "_bgi.h" +#include "../_bgi.h" void moveto(int x, int y) { diff --git a/libc/bgi/outtext.c b/libbgi/common/outtext.c similarity index 95% rename from libc/bgi/outtext.c rename to libbgi/common/outtext.c index 9d433b4..0b43aa5 100644 --- a/libc/bgi/outtext.c +++ b/libbgi/common/outtext.c @@ -2,7 +2,7 @@ * outtext — строка в текущей позиции (CP) текущим стилем текста; CP * сдвигается на textwidth (гориз.) или вверх на textheight (верт.). */ -#include "_bgi.h" +#include "../_bgi.h" void outtext(const char *text) { diff --git a/libc/bgi/outtextxy.c b/libbgi/common/outtextxy.c similarity index 92% rename from libc/bgi/outtextxy.c rename to libbgi/common/outtextxy.c index e87f11e..d7df3af 100644 --- a/libc/bgi/outtextxy.c +++ b/libbgi/common/outtextxy.c @@ -1,6 +1,6 @@ /* outtextxy — строка в (x,y) текущим стилем текста (масштаб/направление, * прозрачный фон); CP не меняет. */ -#include "_bgi.h" +#include "../_bgi.h" void outtextxy(int x, int y, const char *text) { diff --git a/libc/bgi/pieslice.c b/libbgi/common/pieslice.c similarity index 91% rename from libc/bgi/pieslice.c rename to libbgi/common/pieslice.c index f150b41..a900af1 100644 --- a/libc/bgi/pieslice.c +++ b/libbgi/common/pieslice.c @@ -1,5 +1,5 @@ /* pieslice — залитый сектор круга радиуса r (частный случай sector). */ -#include "_bgi.h" +#include "../_bgi.h" void pieslice(int x, int y, int stangle, int endangle, int radius) { diff --git a/libc/bgi/putimage.c b/libbgi/common/putimage.c similarity index 98% rename from libc/bgi/putimage.c rename to libbgi/common/putimage.c index fb31b57..37d8a58 100644 --- a/libc/bgi/putimage.c +++ b/libbgi/common/putimage.c @@ -5,7 +5,7 @@ * COPY — пишем src; XOR/OR/AND — комбинируем с экраном (нужно raw- * чтение); NOT — пишем ~src. Всё в одной W3-скобке (raw-плот/чтение). */ -#include "_bgi.h" +#include "../_bgi.h" void putimage(int left, int top, const void *bitmap, int op) { diff --git a/libc/bgi/rectangle.c b/libbgi/common/rectangle.c similarity index 95% rename from libc/bgi/rectangle.c rename to libbgi/common/rectangle.c index 96523bb..e8de20d 100644 --- a/libc/bgi/rectangle.c +++ b/libbgi/common/rectangle.c @@ -1,5 +1,5 @@ /* rectangle — контур прямоугольника по углам (left,top)-(right,bottom). */ -#include "_bgi.h" +#include "../_bgi.h" void rectangle(int left, int top, int right, int bottom) { diff --git a/libc/bgi/sector.c b/libbgi/common/sector.c similarity index 98% rename from libc/bgi/sector.c rename to libbgi/common/sector.c index 9819d74..df55d53 100644 --- a/libc/bgi/sector.c +++ b/libbgi/common/sector.c @@ -9,7 +9,7 @@ * «выемку» (min/max по строке не различает 4 пересечения). */ -#include "_bgi.h" +#include "../_bgi.h" /* точка на эллипсе под углом a (Q7-тригонометрия). */ static int se_x(int cx, int xr, int a) { return cx + ((xr * _bgi_cos128(a)) >> 7); } diff --git a/libc/bgi/setbkcolor.c b/libbgi/common/setbkcolor.c similarity index 88% rename from libc/bgi/setbkcolor.c rename to libbgi/common/setbkcolor.c index 05a26be..7c54f07 100644 --- a/libc/bgi/setbkcolor.c +++ b/libbgi/common/setbkcolor.c @@ -1,5 +1,5 @@ /* setbkcolor — задать фоновый цвет (cleardevice, фон текста). */ -#include "_bgi.h" +#include "../_bgi.h" void setbkcolor(int color) { diff --git a/libc/bgi/setcolor.c b/libbgi/common/setcolor.c similarity index 86% rename from libc/bgi/setcolor.c rename to libbgi/common/setcolor.c index d416ae5..61c3100 100644 --- a/libc/bgi/setcolor.c +++ b/libbgi/common/setcolor.c @@ -1,5 +1,5 @@ /* setcolor — задать текущий цвет рисования. */ -#include "_bgi.h" +#include "../_bgi.h" void setcolor(int color) { diff --git a/libc/bgi/setfillstyle.c b/libbgi/common/setfillstyle.c similarity index 91% rename from libc/bgi/setfillstyle.c rename to libbgi/common/setfillstyle.c index 14d4fd6..3e9b1fa 100644 --- a/libc/bgi/setfillstyle.c +++ b/libbgi/common/setfillstyle.c @@ -1,5 +1,5 @@ /* setfillstyle — задать паттерн и цвет заливки (bar/fillpoly/…). */ -#include "_bgi.h" +#include "../_bgi.h" void setfillstyle(int pattern, int color) { diff --git a/libc/bgi/setlinestyle.c b/libbgi/common/setlinestyle.c similarity index 94% rename from libc/bgi/setlinestyle.c rename to libbgi/common/setlinestyle.c index 9fc98e0..47e7a3d 100644 --- a/libc/bgi/setlinestyle.c +++ b/libbgi/common/setlinestyle.c @@ -1,5 +1,5 @@ /* setlinestyle — задать стиль, пользовательскую маску и толщину линий. */ -#include "_bgi.h" +#include "../_bgi.h" void setlinestyle(int linestyle, unsigned upattern, int thickness) { diff --git a/libc/bgi/settextstyle.c b/libbgi/common/settextstyle.c similarity index 95% rename from libc/bgi/settextstyle.c rename to libbgi/common/settextstyle.c index f105a0f..9b932b4 100644 --- a/libc/bgi/settextstyle.c +++ b/libbgi/common/settextstyle.c @@ -2,7 +2,7 @@ * settextstyle — шрифт (поддержан только DEFAULT_FONT), направление и * масштаб текста. font игнорируется (всегда растровый 8×8). */ -#include "_bgi.h" +#include "../_bgi.h" void settextstyle(int font, int direction, int charsize) { diff --git a/libc/bgi/textheight.c b/libbgi/common/textheight.c similarity index 93% rename from libc/bgi/textheight.c rename to libbgi/common/textheight.c index 55b6376..d87dceb 100644 --- a/libc/bgi/textheight.c +++ b/libbgi/common/textheight.c @@ -1,5 +1,5 @@ /* textheight — высота строки как она будет нарисована (масштаб/направление). */ -#include "_bgi.h" +#include "../_bgi.h" #include int textheight(const char *text) diff --git a/libc/bgi/textwidth.c b/libbgi/common/textwidth.c similarity index 94% rename from libc/bgi/textwidth.c rename to libbgi/common/textwidth.c index b24a1d3..e2ad879 100644 --- a/libc/bgi/textwidth.c +++ b/libbgi/common/textwidth.c @@ -1,6 +1,6 @@ /* textwidth — ширина строки как она будет нарисована (с учётом * масштаба и направления). */ -#include "_bgi.h" +#include "../_bgi.h" #include int textwidth(const char *text) diff --git a/libbgi/include/gfx.h b/libbgi/include/gfx.h new file mode 100644 index 0000000..d8ffa55 --- /dev/null +++ b/libbgi/include/gfx.h @@ -0,0 +1,74 @@ +/* + * gfx.h — Sprinter graphics: mode-agnostic API (BGI_GFX). + * + * Рисование (putpixel/line/bar/circle/…) вынесено в BGI — см. + * и driver-библиотеки bgi256.lib / bgi16.lib (выбор режима + * линковкой: sprinter-cc --gfx 256 | --gfx 16). Здесь остались только + * функции БЕЗ BGI-аналога: вход/выход в режим, страницы, банк, vsync, + * палитра, шрифт. Они mode-agnostic и живут в libbgi/common/ (один + * исходник, .rel в обеих driver-библиотеках). + * + * Адресация (для не-BGI программ, использующих эти примитивы напрямую: + * пиксель (x,y) — CPU 0xC000 + (x или x/2) с Port_Y (0x89) = y; + * gfx-код мапит 16 КБ VRAM-страницу в W3 при записи. + * Для double-buffering страница 1 начинается на 320 байт дальше (0xC140). + * + * Палитра: BIOS $A4 (RST 8); 4 байта на запись — B, G, R, pad. + */ +#ifndef GFX_H +#define GFX_H + +#include + +/* ESTEX SETVMOD codes — same values as the SETVMOD `A` register. */ +#define GFX_MODE_TEXT_40x32 0x02 +#define GFX_MODE_TEXT_80x32 0x03 +#define GFX_MODE_320x256x256 0x81 +#define GFX_MODE_640x256x16 0x82 + +/* Pixel dimensions of mode 0x81 (320×256, 256 colours). */ +#define GFX_WIDTH 320 +#define GFX_HEIGHT 256 + +/* Pixel dimensions of mode 0x82 (640×256, 16 colours). Each byte at + * 0xC000+x_byte holds two pixels: high nibble = LEFT (even-x), low + * nibble = RIGHT (odd-x) — see memory/sprinter_graphics.md. */ +#define GFX_WIDTH_16 640 +#define GFX_HEIGHT_16 256 +#define GFX_COLORS_16 16 + +/* ---- Page selection (double-buffering) and bank control ---------- */ +void gfx_set_visible_page(uint8_t page); /* 0 or 1 */ +uint8_t gfx_get_visible_page(void); +void gfx_set_draw_page(uint8_t page); /* 0 or 1 */ +uint8_t gfx_get_draw_page(void); +void gfx_set_bank(uint8_t bank); /* 0x50..0x5F */ +uint8_t gfx_get_bank(void); + +/* Block until the next frame (50 Hz). Типичный double-buffer: + * gfx_set_draw_page(hidden); draw_frame(); gfx_wait_vsync(); + * gfx_set_visible_page(hidden); // tear-free flip */ +void gfx_wait_vsync(void); + +/* ---- Bitmap-font text -------------------------------------------- * + * Шрифт 256 глифов × 8 рядов × 1 байт (ZX-Spectrum формат), 2 КБ. + * Грузится лениво при первом использовании BGI-текста; gfx_set_font + * подменяет указатель (storage должен жить, пока шрифт активен). */ +void gfx_load_default_font(void); +void gfx_set_font(const uint8_t *font); + +/* ---- Palette ----------------------------------------------------- * + * Каждая графическая страница имеет свою палитру (page 0 → palette 0, + * page 1 → palette 1). Для seamless double-buffering грузить одну + * палитру в обе. */ +void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count, + const uint8_t *data); +void gfx_pal_set (uint8_t pal_num, uint8_t idx, + uint8_t r, uint8_t g, uint8_t b); +void gfx_pal_get (uint8_t pal_num, uint8_t start, uint8_t count, + uint8_t *data); +void gfx_pal_get_color(uint8_t pal_num, uint8_t idx, + uint8_t *r, uint8_t *g, uint8_t *b); +void gfx_pal_reset(void); + +#endif diff --git a/libc/include/graphics.h b/libbgi/include/graphics.h similarity index 100% rename from libc/include/graphics.h rename to libbgi/include/graphics.h diff --git a/libc/Makefile b/libc/Makefile new file mode 100644 index 0000000..501beec --- /dev/null +++ b/libc/Makefile @@ -0,0 +1,89 @@ +# Build lib/sprinter.lib — the Sprinter target libc archive. +# +# libc/ — ядро библиотеки (БЕЗ графики; графика вынесена в libbgi/). +# Каждый .c под libc// — отдельный .rel в архиве (1 публичная +# функция = 1 модуль); линкер тянет только нужные .rel → DCE на уровне +# файлов. Плюс runtime-хелперы, которые автотянутся кодогеном SDCC +# (heap для malloc). crt0-семейство НЕ в архиве — оно всегда явно +# линкуется, не DCE-eligible. См. docs/libc-split-asm-cases.md. +# +# make build lib/sprinter.lib +# make clean remove build/ + lib/sprinter.lib +# +# Симметрично libbgi/Makefile: исходники и build/ рядом, результат +# ложится в общий каталог lib/ (откуда его линкует sprinter-cc). + +PROJ_ROOT := $(abspath $(CURDIR)/..) +SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin +SDCC := $(SDCC_BIN)/sdcc +SDAR := $(SDCC_BIN)/sdar +SDASZ80 := $(SDCC_BIN)/sdasz80 + +INC := -I$(CURDIR)/include +CC_FLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC) + +BUILD := $(CURDIR)/build + +# All libc C modules — every .c under libc// becomes its own .rel. +# `libc/*/*.c` — ровно ОДИН уровень вложенности; графика (gfx/bgi) сюда +# не попадает (вынесена в libbgi/). Один PUBLIC-символ на файл. +LIBC_C := $(wildcard $(CURDIR)/*/*.c) + +# Runtime modules to bundle (pulled by symbol references from libc-using +# code). bank.s НЕ bundled — его трамплин зависит от banking-окна (W1 +# для BIG, W3 для HUGE), что решается per-build в sprinter-cc; он +# ассемблирует bank.s с нужным BANK_W1 флагом на каждый banked-build. +RUNTIME_S := $(PROJ_ROOT)/runtime/heap.s + +LIBC_RELS := $(patsubst $(CURDIR)/%.c,$(BUILD)/%.rel,$(LIBC_C)) +RUNTIME_RELS := $(patsubst $(PROJ_ROOT)/runtime/%.s,$(BUILD)/%.rel,$(RUNTIME_S)) + +ALL_RELS := $(LIBC_RELS) $(RUNTIME_RELS) +KNOWN_RELS := $(ALL_RELS) + +# Штамп списка модулей: обновляется при любом изменении состава +# (добавление/удаление/переименование исходника) — иначе удаление +# исходника не триггерит перелинковку и stale .rel остаётся в архиве. +# Сразу сносим и архив: на exFAT (SAM8) гранулярность mtime грубая, +# и «список изменился» через сравнение времён можно проглядеть. +MODLIST := $(BUILD)/.modules +ifneq ($(shell cat $(MODLIST) 2>/dev/null),$(KNOWN_RELS)) +_ := $(shell mkdir -p $(BUILD); echo "$(KNOWN_RELS)" > $(MODLIST); rm -f $(LIB)) +endif + +LIB_DIR := $(PROJ_ROOT)/lib +LIB := $(LIB_DIR)/sprinter.lib + +all: $(LIB) + +# Pattern rule для C-модулей libc//file.c → build//file.rel +# (сохраняет путь io|mem|stdio внутри архива). +$(BUILD)/%.rel: $(CURDIR)/%.c + @mkdir -p $(dir $@) + $(SDCC) $(CC_FLAGS) -c -o $@ $< + +# Runtime .s → .rel (runtime/ вне libc/, но heap.s бандлится в архив). +$(BUILD)/%.rel: $(PROJ_ROOT)/runtime/%.s + @mkdir -p $(dir $@) + $(SDASZ80) -o $@ $< + +# Archive — sdar rcs = replace/create/symtab. Перед упаковкой удаляем +# stale .rel: wildcard не знает об удалённых/переименованных исходниках, +# и осиротевший .rel из build/ иначе жил бы вечно. +$(LIB): $(ALL_RELS) $(MODLIST) + @find $(BUILD) -name '*.rel' -print | sort > $(BUILD)/.have + @printf '%s\n' $(KNOWN_RELS) | sort > $(BUILD)/.want + @comm -23 $(BUILD)/.have $(BUILD)/.want | while read f; do \ + echo " stale: $$f (исходник удалён) — rm"; \ + rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \ + done + rm -f $@ + $(SDAR) -rcs $@ $(ALL_RELS) + @echo + @echo " Built $@ with $(words $(ALL_RELS)) modules:" + @$(SDAR) -t $@ | sed 's/^/ /' + +clean: + rm -rf $(BUILD) $(LIB) + +.PHONY: all clean diff --git a/libc/bgi/_bgi.h b/libc/bgi/_bgi.h deleted file mode 100644 index c735fee..0000000 --- a/libc/bgi/_bgi.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * _bgi.h — внутренности BGI-слоя (НЕ публичный заголовок). - * - * Математика примитивов (circle/line/bar/…) — mode-agnostic, лежит в - * каталоге libc/bgi (файлы .c) и попадает в основную sprinter.lib. - * Различающиеся по видеорежиму LEAF-операции (`_bgi_*`) реализованы в - * отдельных driver-каталогах libc/bgi/drv256 и drv16 (каждый — свой архив, выбирается - * линковкой; см. memory/bgi_two_lib_design). Публичные символы leaf'ов - * одинаковы в обоих драйверах, поэтому math не знает режима. - */ -#ifndef _BGI_INTERNAL_H -#define _BGI_INTERNAL_H - -#include -#include -#include /* GFX_WIDTH/HEIGHT для внутренних таблиц */ - -/* ---- Состояние (_bgi_state.c) ------------------------------------ */ -extern uint8_t _bgi_fg; /* текущий цвет рисования */ -extern uint8_t _bgi_bg; /* фоновый цвет */ -extern int _bgi_cx; /* текущая позиция X (CP) */ -extern int _bgi_cy; /* текущая позиция Y */ -extern int _bgi_maxx; /* правая граница (319) */ -extern int _bgi_maxy; /* нижняя граница (255) */ -extern int _bgi_maxcolor; /* макс. индекс цвета (255) */ -extern uint8_t _bgi_prevmode; /* видеорежим до initgraph */ -extern int _bgi_result; /* код graphresult */ - -/* ---- LEAF-операции драйвера (каталоги drv256 или drv16) ----------- * - * Каждая self-contained (сама оборачивает W3-скобку через gfx_*). - * mode_set: войти в граф.режим, загрузить палитру, заполнить - * _bgi_maxx/_bgi_maxy/_bgi_maxcolor; вернуть предыдущий видеорежим. */ -uint8_t _bgi_mode_set(void); -void _bgi_mode_done(uint8_t prev_mode); - -void _bgi_plot(int x, int y, uint8_t color); -unsigned _bgi_read(int x, int y); - -/* Пакетное рисование: одна W3-скобка на весь примитив вместо скобки на - * каждый пиксель (для circle/ellipse/fill — тысячи точек). Между - * _bgi_begin и _bgi_end IRQ выключены; плот делать только _bgi_plot_raw - * (без своей скобки, с клипом по краю экрана). */ -void _bgi_begin(void); -void _bgi_end(void); -void _bgi_plot_raw(int x, int y, uint8_t color); - -/* ---- Тригонометрия для дуг (_bgi_trig.c) ------------------------- * - * Угол в градусах; результат sin/cos × 128 (Q7 — чтобы радиус×значение - * влезало в int без 32-бит арифметики). */ -int _bgi_sin128(int deg); -int _bgi_cos128(int deg); - -/* Общий рисователь дуги/контура эллипса (_bgi_arc_draw.c): полилиния - * по точкам от stangle до endangle с полуосями xr,yr вокруг (cx,cy). */ -void _bgi_ellipse_arc(int cx, int cy, int stangle, int endangle, - int xr, int yr, uint8_t color); - -/* Целочисленный sqrt (0..~32767) для fillellipse (_bgi_isqrt.c). */ -int _bgi_isqrt(int n); - -/* ---- Состояние линий (_bgi_line_state.c) ------------------------- */ -extern uint8_t _bgi_line_style; /* SOLID_LINE..USERBIT_LINE */ -extern uint8_t _bgi_line_thick; /* 1 (NORM) или 3 (THICK) */ -extern uint16_t _bgi_line_pattern; /* маска для USERBIT_LINE */ - -/* Отрезок текущим стилем/толщиной линии (_bgi_styled_line.c). */ -void _bgi_styled_line(int x0, int y0, int x1, int y1, uint8_t color); - -/* ---- Состояние заливки (_bgi_fill_state.c) ----------------------- */ -extern uint8_t _bgi_fill_pattern; /* *_FILL */ -extern uint8_t _bgi_fill_color; - -/* Raw horizontal span (без своей W3-скобки; клип делает сам gfx-raw). */ -void _bgi_hspan_raw(int x, int y, int len, uint8_t color); - -/* Raw чтение пикселя (без своей W3-скобки) — для getimage/putimage. */ -unsigned _bgi_read_raw(int x, int y); - -/* ---- Стиль текста (_bgi_text_state.c) ---------------------------- */ -extern uint8_t _bgi_text_dir; /* HORIZ_DIR / VERT_DIR */ -extern uint8_t _bgi_text_size; /* масштаб 1..10 */ - -/* Заполнить 8 байт строк глифа символа c (грузит шрифт при первом - * использовании) — drv256/_bgi_font_rows.c. */ -void _bgi_font_rows(unsigned char c, uint8_t *rows8); - -/* Нарисовать строку s в (x,y) текущим стилем текста (масштаб/направление, - * цвет _bgi_fg, прозрачный фон) — _bgi_draw_scaled.c. */ -void _bgi_draw_scaled(int x, int y, const char *s); - -/* Залить строку [x0..x1] на y ТЕКУЩИМ стилем заливки (паттерн+цвет), - * с клипом по экрану. Вызывать между _bgi_begin/_bgi_end. */ -void _bgi_fill_span(int x0, int x1, int y); - -/* Скан-таблицы min/max X по строкам для fillpoly (_bgi_poly_state.c). */ -extern int _bgi_span_min[GFX_HEIGHT]; -extern int _bgi_span_max[GFX_HEIGHT]; - -/* Прогнать ребро (Брезенхэм) обновляя _bgi_span_min/max (_bgi_poly_edge.c). */ -void _bgi_poly_edge(int x0, int y0, int x1, int y1); -void _bgi_hspan(int x, int y, int len, uint8_t color); -void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color); -void _bgi_fillrect(int x, int y, int w, int h, uint8_t color); -void _bgi_clearall(uint8_t color); -void _bgi_drawtext(int x, int y, const char *s, uint8_t fg, uint8_t bg); - -#endif diff --git a/libc/bgi/closegraph.c b/libc/bgi/closegraph.c deleted file mode 100644 index 7e155d4..0000000 --- a/libc/bgi/closegraph.c +++ /dev/null @@ -1,7 +0,0 @@ -/* closegraph — вернуть текстовый режим, действовавший до initgraph. */ -#include "_bgi.h" - -void closegraph(void) -{ - _bgi_mode_done(_bgi_prevmode); -} diff --git a/libc/bgi/drv256/_bgi_begin.c b/libc/bgi/drv256/_bgi_begin.c deleted file mode 100644 index b4c2346..0000000 --- a/libc/bgi/drv256/_bgi_begin.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_begin (drv256) — открыть W3-сессию для пакетного рисования. */ -#include "../_bgi.h" -#include "../../gfx/_gfx.h" - -void _bgi_begin(void) -{ - _gfx_w3_video_begin(); -} diff --git a/libc/bgi/drv256/_bgi_clearall.c b/libc/bgi/drv256/_bgi_clearall.c deleted file mode 100644 index 2aea0d9..0000000 --- a/libc/bgi/drv256/_bgi_clearall.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_clearall (drv256) — залить весь экран цветом. */ -#include "../_bgi.h" -#include - -void _bgi_clearall(uint8_t color) -{ - gfx_clear256(color); -} diff --git a/libc/bgi/drv256/_bgi_drawtext.c b/libc/bgi/drv256/_bgi_drawtext.c deleted file mode 100644 index 1608977..0000000 --- a/libc/bgi/drv256/_bgi_drawtext.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_drawtext (drv256) — строка шрифтом 8×8 цветами fg/bg в (x,y). */ -#include "../_bgi.h" -#include - -void _bgi_drawtext(int x, int y, const char *s, uint8_t fg, uint8_t bg) -{ - gfx_text256(x, y, s, fg, bg); -} diff --git a/libc/bgi/drv256/_bgi_end.c b/libc/bgi/drv256/_bgi_end.c deleted file mode 100644 index eb43be2..0000000 --- a/libc/bgi/drv256/_bgi_end.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_end (drv256) — закрыть W3-сессию пакетного рисования. */ -#include "../_bgi.h" -#include "../../gfx/_gfx.h" - -void _bgi_end(void) -{ - _gfx_w3_video_end(); -} diff --git a/libc/bgi/drv256/_bgi_fillrect.c b/libc/bgi/drv256/_bgi_fillrect.c deleted file mode 100644 index b94f704..0000000 --- a/libc/bgi/drv256/_bgi_fillrect.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_fillrect (drv256) — залитый прямоугольник w×h из (x,y). */ -#include "../_bgi.h" -#include - -void _bgi_fillrect(int x, int y, int w, int h, uint8_t color) -{ - gfx_fill_rect256(x, y, w, h, color); -} diff --git a/libc/bgi/drv256/_bgi_font_rows.c b/libc/bgi/drv256/_bgi_font_rows.c deleted file mode 100644 index bd9e627..0000000 --- a/libc/bgi/drv256/_bgi_font_rows.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * _bgi_font_rows (drv256) — 8 байт строк глифа символа c. - * Шрифт системный, interleaved: offset = row*256 + char (MSB-first), - * см. memory/sprinter_font_format. Грузится лениво (_gfx_font_ensure). - */ -#include "../_bgi.h" -#include "../../gfx/_gfx.h" - -void _bgi_font_rows(unsigned char c, uint8_t *rows8) -{ - const uint8_t *f; - int r; - _gfx_font_ensure(); - f = _gfx_font_ptr; - for (r = 0; r < 8; r++) - rows8[r] = f[r * 256 + c]; -} diff --git a/libc/bgi/drv256/_bgi_hspan.c b/libc/bgi/drv256/_bgi_hspan.c deleted file mode 100644 index ad8bbd2..0000000 --- a/libc/bgi/drv256/_bgi_hspan.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_hspan (drv256) — горизонтальный отрезок len пикселей. */ -#include "../_bgi.h" -#include - -void _bgi_hspan(int x, int y, int len, uint8_t color) -{ - gfx_hline256(x, y, len, color); -} diff --git a/libc/bgi/drv256/_bgi_hspan_raw.c b/libc/bgi/drv256/_bgi_hspan_raw.c deleted file mode 100644 index 3dcb6ae..0000000 --- a/libc/bgi/drv256/_bgi_hspan_raw.c +++ /dev/null @@ -1,11 +0,0 @@ -/* - * _bgi_hspan_raw (drv256) — горизонтальный отрезок без своей W3-скобки - * (вызывать между _bgi_begin/_bgi_end). Клип делает сам raw-примитив. - */ -#include "../_bgi.h" -#include "../../gfx/_gfx.h" - -void _bgi_hspan_raw(int x, int y, int len, uint8_t color) -{ - _gfx_hline256_raw(x, y, len, color); -} diff --git a/libc/bgi/drv256/_bgi_lineseg.c b/libc/bgi/drv256/_bgi_lineseg.c deleted file mode 100644 index 02c7e17..0000000 --- a/libc/bgi/drv256/_bgi_lineseg.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_lineseg (drv256) — отрезок (x0,y0)->(x1,y1) (использует accel-line). */ -#include "../_bgi.h" -#include - -void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color) -{ - gfx_line256(x0, y0, x1, y1, color); -} diff --git a/libc/bgi/drv256/_bgi_mode_done.c b/libc/bgi/drv256/_bgi_mode_done.c deleted file mode 100644 index 0b6c74b..0000000 --- a/libc/bgi/drv256/_bgi_mode_done.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_mode_done (drv256) — вернуть видеорежим, бывший до initgraph. */ -#include "../_bgi.h" -#include - -void _bgi_mode_done(uint8_t prev_mode) -{ - gfx_done(prev_mode); -} diff --git a/libc/bgi/drv256/_bgi_plot.c b/libc/bgi/drv256/_bgi_plot.c deleted file mode 100644 index 6041ba7..0000000 --- a/libc/bgi/drv256/_bgi_plot.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_plot (drv256) — одиночный пиксель текущим цветом. */ -#include "../_bgi.h" -#include - -void _bgi_plot(int x, int y, uint8_t color) -{ - gfx_putpixel256(x, y, color); -} diff --git a/libc/bgi/drv256/_bgi_plot_raw.c b/libc/bgi/drv256/_bgi_plot_raw.c deleted file mode 100644 index 0ce530f..0000000 --- a/libc/bgi/drv256/_bgi_plot_raw.c +++ /dev/null @@ -1,11 +0,0 @@ -/* - * _bgi_plot_raw (drv256) — пиксель без своей W3-скобки (вызывать между - * _bgi_begin/_bgi_end). Клип по краю экрана делает сам raw-примитив. - */ -#include "../_bgi.h" -#include "../../gfx/_gfx.h" - -void _bgi_plot_raw(int x, int y, uint8_t color) -{ - _gfx_putpixel256_raw(x, y, color); -} diff --git a/libc/bgi/drv256/_bgi_read.c b/libc/bgi/drv256/_bgi_read.c deleted file mode 100644 index 8303807..0000000 --- a/libc/bgi/drv256/_bgi_read.c +++ /dev/null @@ -1,8 +0,0 @@ -/* _bgi_read (drv256) — цвет пикселя (x,y). */ -#include "../_bgi.h" -#include - -unsigned _bgi_read(int x, int y) -{ - return gfx_getpixel256(x, y); -} diff --git a/libc/bgi/drv256/_bgi_read_raw.c b/libc/bgi/drv256/_bgi_read_raw.c deleted file mode 100644 index f667e17..0000000 --- a/libc/bgi/drv256/_bgi_read_raw.c +++ /dev/null @@ -1,11 +0,0 @@ -/* - * _bgi_read_raw (drv256) — чтение пикселя без своей W3-скобки - * (между _bgi_begin/_bgi_end). Для getimage/putimage. - */ -#include "../_bgi.h" -#include "../../gfx/_gfx.h" - -unsigned _bgi_read_raw(int x, int y) -{ - return _gfx_getpixel256_raw(x, y); -} diff --git a/libc/bgi/getpixel.c b/libc/bgi/getpixel.c deleted file mode 100644 index 1a56540..0000000 --- a/libc/bgi/getpixel.c +++ /dev/null @@ -1,7 +0,0 @@ -/* getpixel — цвет пикселя (x,y). */ -#include "_bgi.h" - -unsigned getpixel(int x, int y) -{ - return _bgi_read(x, y); -} diff --git a/libc/bgi/putpixel.c b/libc/bgi/putpixel.c deleted file mode 100644 index f1d6996..0000000 --- a/libc/bgi/putpixel.c +++ /dev/null @@ -1,7 +0,0 @@ -/* putpixel — точка (x,y) заданным цветом (не трогает текущий цвет/CP). */ -#include "_bgi.h" - -void putpixel(int x, int y, int color) -{ - _bgi_plot(x, y, (uint8_t)color); -} diff --git a/libc/gfx/_gfx.h b/libc/gfx/_gfx.h deleted file mode 100644 index 4d85a85..0000000 --- a/libc/gfx/_gfx.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * _gfx.h — внутренности графической подсистемы (НЕ публичный заголовок). - * - * Общее состояние лежит в data-модулях (_gfx_state.c, _gfx_w3_state.c, - * _gfx_acc256.c, _gfx_g16_state.c, _gfx_font_state.c), helpers — в - * отдельных internal-модулях; см. docs/libc-split-asm-cases.md. - */ -#ifndef _GFX_INTERNAL_H -#define _GFX_INTERNAL_H - -#include - -/* ---- Общее состояние (_gfx_state.c) ------------------------------ */ - -/* Кэш SELPAGE: видимая и рисуемая страницы (0/1). */ -extern uint8_t _gfx_visible_page; -extern uint8_t _gfx_draw_page; - -/* Байт страницы W3 (0x50..0x5F) — какой видеобанк мапится при записи. */ -extern uint8_t _gfx_bank; - -/* CPU-адрес колонки 0 текущей draw-страницы: 0xC000 (page 0) или - * 0xC140 (page 1); каждый примитив использует его вместо константы. */ -extern uint16_t _gfx_addr_base; - -/* ---- Низкоуровневый видеорежим (video/videomode_raw.c) ----------- */ - -uint8_t _videomode_raw_get(void); -int _videomode_raw_set(uint8_t mode); - -/* ---- W3-скобки (_gfx_w3_video_begin/end.c, _gfx_w3_state.c) ------ * - * begin: DI + сохранить текущий W3 и замапить _gfx_bank; - * end: восстановить W3 + EI. Не реентерабельно (сейв в статике). */ - -extern uint8_t _gfx_saved_w3; - -void _gfx_w3_video_begin(void); -void _gfx_w3_video_end(void); - -/* ---- Raw-примитивы 256 цветов (mode 0x81) ------------------------- * - * "Raw" = W3-naive: вызывающий обязан обернуть последовательность в - * одну пару _gfx_w3_video_begin/_gfx_w3_video_end. */ - -void _gfx_putpixel256_raw(int x, int y, uint8_t color); -uint8_t _gfx_getpixel256_raw(int x, int y); -void _gfx_hline256_raw (int x, int y, int len, uint8_t color); -void _gfx_vline256_raw (int x, int y, int len, uint8_t color); -void _gfx_clear256_raw (uint8_t color); - -/* Скретч акселератора (_gfx_acc256.c) — общий для hline/vline/clear; - * однопоточно, IRQ выключены между begin/end. */ -extern uint8_t _gfx_acc_color; -extern uint8_t _gfx_acc_y; -extern uint8_t _gfx_acc_len; /* 0 = 256 — конвенция акселератора */ -extern uint16_t _gfx_acc_addr; - -/* Горизонтальный Fill-burst: _gfx_acc_len байт с _gfx_acc_addr на - * строке _gfx_acc_y (W3 замаплен, DI активен). */ -void _gfx_hfill256_chunk(void); - -/* ---- Raw-примитивы 16 цветов (mode 0x82) -------------------------- */ - -void _gfx_putpixel16_raw(int x, int y, uint8_t color); -void _gfx_hline16_raw (int x, int y, int len, uint8_t color); -void _gfx_vline16_raw (int x, int y, int len, uint8_t color); -void _gfx_clear16_raw (uint8_t color); - -/* Скретч 16-цветных примитивов (_gfx_g16_state.c). */ -extern uint8_t _gfx_g16_y; -extern uint8_t _gfx_g16_byte; /* nibble | (nibble<<4) */ -extern uint8_t _gfx_g16_nibble; /* цвет в нужной половине байта */ -extern uint8_t _gfx_g16_mask; /* маска, сохраняющая ДРУГУЮ половину */ -extern uint8_t _gfx_g16_len; /* размер accel-блока (0 = 256) */ -extern uint16_t _gfx_g16_addr; - -/* Горизонтальный Fill-burst байтами _gfx_g16_byte (_gfx_hfill16.c). */ -void _gfx_hfill16_chunk(void); - -/* RMW одного нибла по (_gfx_g16_addr, _gfx_g16_y) (_gfx_rmw16.c). */ -void _gfx_rmw16_pixel(void); - -/* ---- Шрифт (_gfx_font_state.c, _gfx_font_ensure.c) ---------------- * - * Формат: 256 глифов × 8 рядов, INTERLEAVED — offset = row*256 + char; - * биты MSB-first. См. memory/sprinter_font_format. */ - -#define _GFX_FONT_BYTES 2048 - -extern uint8_t _gfx_font_buf[_GFX_FONT_BYTES]; -extern const uint8_t *_gfx_font_ptr; -extern uint8_t _gfx_font_loaded; - -/* Ленивая инициализация: грузит системный шрифт при первом использовании. */ -void _gfx_font_ensure(void); - -/* ---- Текст 16 цветов: общая машинерия ----------------------------- * - * Данные в _gfx_t16_state.c, рендер ряда в _gfx_render_row16.c, - * pair-таблица в _gfx_t16_pair_build.c. */ - -extern uint8_t _gfx_t16_y; -extern uint8_t _gfx_t16_row; /* битовый паттерн ряда глифа */ -extern uint16_t _gfx_t16_addr; /* VRAM-адрес ряда */ -extern uint8_t _gfx_t16_pair[4]; /* LEFT*2+RIGHT → (LEFT<<4)|RIGHT */ - -/* Отрисовать один 8-пиксельный ряд по pair-таблице (4 записи байт). */ -void _gfx_render_row16(void); - -/* Заполнить pair-таблицу для пары цветов fg/bg. */ -void _gfx_t16_pair_build(uint8_t fg, uint8_t bg); - -#endif diff --git a/libc/gfx/_gfx_render_row16.c b/libc/gfx/_gfx_render_row16.c deleted file mode 100644 index 257a1cd..0000000 --- a/libc/gfx/_gfx_render_row16.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * _gfx_render_row16 — один 8-пиксельный ряд глифа в mode 0x82 - * (640×256×16): 4 выходных байта, каждый пакует два соседних пикселя - * как (LEFT<<4) | RIGHT через прекомпилированную _gfx_t16_pair — - * 2-битный паттерн источника (LEFT*2 + RIGHT) сразу даёт выходной - * байт, без mask/OR на пиксель. Сам делает DI / W3 save+restore — - * вызывать можно из любого контекста без скобок. - */ - -#include "_gfx.h" - -void _gfx_render_row16(void) __naked -{ - __asm - di - in a, (#0xE2) - push af - ld a, #0x50 - out (#0xE2), a - ld a, (__gfx_t16_y) - out (#0x89), a - - ld hl, (__gfx_t16_addr) - ld a, (__gfx_t16_row) - ld c, a ; C = сдвигаемые биты источника - ld b, #4 ; 4 выходных байта - rr16_loop: - ;; Два верхних бита C в индекс A = LEFT*2 + RIGHT. - sla c ; CY = бит LEFT; C <<= 1 - ld a, #0 - adc a, a ; A = LEFT - sla c ; CY = бит RIGHT; C <<= 1 - adc a, a ; A = LEFT*2 + RIGHT (0..3) - - ;; A = _gfx_t16_pair[A]; HL сохраняем через стек. - push hl - ld e, a - ld d, #0 - ld hl, #__gfx_t16_pair - add hl, de - ld a, (hl) - pop hl - - ld (hl), a - inc hl - djnz rr16_loop - - pop af - out (#0xE2), a - ei - ret - __endasm; -} diff --git a/libc/gfx/_gfx_t16_pair_build.c b/libc/gfx/_gfx_t16_pair_build.c deleted file mode 100644 index 31726a2..0000000 --- a/libc/gfx/_gfx_t16_pair_build.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * _gfx_t16_pair_build — заполнить pair-таблицу текстового рендера - * mode 0x82 для пары цветов fg/bg. - */ - -#include "_gfx.h" - -void _gfx_t16_pair_build(uint8_t fg, uint8_t bg) -{ - uint8_t f = fg & 0x0F; - uint8_t b = bg & 0x0F; - /* HIGH nibble = LEFT, LOW = RIGHT (конвенция sprinter_graphics). */ - _gfx_t16_pair[0] = (uint8_t)((b << 4) | b); /* 00 BG BG */ - _gfx_t16_pair[1] = (uint8_t)((b << 4) | f); /* 01 BG FG */ - _gfx_t16_pair[2] = (uint8_t)((f << 4) | b); /* 10 FG BG */ - _gfx_t16_pair[3] = (uint8_t)((f << 4) | f); /* 11 FG FG */ -} diff --git a/libc/gfx/_gfx_t16_state.c b/libc/gfx/_gfx_t16_state.c deleted file mode 100644 index 3c9d80d..0000000 --- a/libc/gfx/_gfx_t16_state.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * _gfx_t16_state — скретч текстового рендера mode 0x82 (только данные). - * Пишут gfx_putchar16/gfx_text16 и _gfx_t16_pair_build, читает - * _gfx_render_row16. - */ - -#include "_gfx.h" - -uint8_t _gfx_t16_y; -uint8_t _gfx_t16_row; -uint16_t _gfx_t16_addr; - -/* index = LEFT*2 + RIGHT, value = (LEFT<<4)|RIGHT. */ -uint8_t _gfx_t16_pair[4]; diff --git a/libc/gfx/_gfx_w3_video_begin.c b/libc/gfx/_gfx_w3_video_begin.c deleted file mode 100644 index 4a6e271..0000000 --- a/libc/gfx/_gfx_w3_video_begin.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * _gfx_w3_video_begin — DI, сохранить текущую страницу W3 и замапить - * _gfx_bank (видеобанк 0x50..0x5F). Композитные примитивы обрамляют - * одной парой begin/end весь внутренний цикл — W3-танец оплачивается - * один раз на операцию, а не на пиксель. - */ - -#include "_gfx.h" - -void _gfx_w3_video_begin(void) __naked -{ - __asm - di - in a, (#0xE2) - ld (__gfx_saved_w3), a - ld a, (__gfx_bank) - out (#0xE2), a - ret - __endasm; -} diff --git a/libc/gfx/_gfx_w3_video_end.c b/libc/gfx/_gfx_w3_video_end.c deleted file mode 100644 index 2cf90ac..0000000 --- a/libc/gfx/_gfx_w3_video_end.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * _gfx_w3_video_end — восстановить сохранённую страницу W3 и EI. - */ - -#include "_gfx.h" - -void _gfx_w3_video_end(void) __naked -{ - __asm - ld a, (__gfx_saved_w3) - out (#0xE2), a - ei - ret - __endasm; -} diff --git a/libc/gfx/gfx_clear16.c b/libc/gfx/gfx_clear16.c deleted file mode 100644 index 62925b5..0000000 --- a/libc/gfx/gfx_clear16.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * gfx_clear16 — залить экран цветом (mode 0x82); одна W3-скобка. - */ - -#include "_gfx.h" - -void gfx_clear16(uint8_t color) -{ - _gfx_w3_video_begin(); - _gfx_clear16_raw(color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_clear256.c b/libc/gfx/gfx_clear256.c deleted file mode 100644 index 4c00ab8..0000000 --- a/libc/gfx/gfx_clear256.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * gfx_clear256 — залить экран цветом (mode 0x81); одна W3-скобка. - */ - -#include "_gfx.h" - -void gfx_clear256(uint8_t color) -{ - _gfx_w3_video_begin(); - _gfx_clear256_raw(color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_done.c b/libc/gfx/gfx_done.c deleted file mode 100644 index 953c453..0000000 --- a/libc/gfx/gfx_done.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * gfx_done — восстановить ранее сохранённый видеорежим (из gfx_init). - */ - -#include "_gfx.h" - -void gfx_done(uint8_t mode) -{ - _videomode_raw_set(mode); -} diff --git a/libc/gfx/gfx_fill_rect16.c b/libc/gfx/gfx_fill_rect16.c deleted file mode 100644 index 93a3ee2..0000000 --- a/libc/gfx/gfx_fill_rect16.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * gfx_fill_rect16 — залитый прямоугольник w×h от (x,y) (mode 0x82). - * Поколоночные vlines (per-row RMW в каждой колонке); внешняя - * begin/end-скобка мапит W3 один раз на весь прямоугольник. - */ - -#include "_gfx.h" - -void gfx_fill_rect16(int x, int y, int w, int h, uint8_t color) -{ - if (w <= 0 || h <= 0) return; - _gfx_w3_video_begin(); - for (int xx = 0; xx < w; xx++) - _gfx_vline16_raw(x + xx, y, h, color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_fill_rect256.c b/libc/gfx/gfx_fill_rect256.c deleted file mode 100644 index fdbd849..0000000 --- a/libc/gfx/gfx_fill_rect256.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * gfx_fill_rect256 — залитый прямоугольник w×h от (x,y) (mode 0x81). - */ - -#include "_gfx.h" - -void gfx_fill_rect256(int x, int y, int w, int h, uint8_t color) -{ - if (w <= 0 || h <= 0) return; - - /* Ориентация с меньшим числом accel-burst'ов. Один burst красит - * до 256 смежных байт (горизонталь) или до 256 пикселей колонки. - * построчно (hlines): h × ceil(w/256) burst'ов - * поколоночно (vlines): w × ceil(h/256) — при h ≤ 256 это w - * Вертикаль выигрывает на высоких узких, горизонталь — на низких - * широких. */ - int h_bursts = h * ((w + 255) >> 8); - int v_bursts = w * ((h + 255) >> 8); - _gfx_w3_video_begin(); - if (h_bursts <= v_bursts) { - for (int yy = 0; yy < h; yy++) - _gfx_hline256_raw(x, y + yy, w, color); - } else { - for (int xx = 0; xx < w; xx++) - _gfx_vline256_raw(x + xx, y, h, color); - } - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_getpixel256.c b/libc/gfx/gfx_getpixel256.c deleted file mode 100644 index 8ea4137..0000000 --- a/libc/gfx/gfx_getpixel256.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * gfx_getpixel256 — прочитать цвет пикселя (x,y) в режиме 0x81. - * - * Одиночный вызов в собственной W3-скобке. Адресация та же, что у - * _gfx_putpixel256_raw: CPU _gfx_addr_base + x, Port_Y (0x89) = y. - * За пределами экрана возвращает 0. - */ - -#include "_gfx.h" - -static uint8_t _gfx_gp_y; -static uint16_t _gfx_gp_addr; -static uint8_t _gfx_gp_color; - -uint8_t gfx_getpixel256(int x, int y) -{ - if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return 0; - _gfx_gp_y = (uint8_t)y; - _gfx_gp_addr = (uint16_t)(_gfx_addr_base + (unsigned)x); - _gfx_w3_video_begin(); - __asm - ld a, (__gfx_gp_y) - out (#0x89), a - ld hl, (__gfx_gp_addr) - ld a, (hl) - ld (__gfx_gp_color), a - __endasm; - _gfx_w3_video_end(); - return _gfx_gp_color; -} diff --git a/libc/gfx/gfx_hline16.c b/libc/gfx/gfx_hline16.c deleted file mode 100644 index 0e16f91..0000000 --- a/libc/gfx/gfx_hline16.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * gfx_hline16 — горизонтальная линия (mode 0x82) в W3-скобке. - */ - -#include "_gfx.h" - -void gfx_hline16(int x, int y, int len, uint8_t color) -{ - _gfx_w3_video_begin(); - _gfx_hline16_raw(x, y, len, color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_hline256.c b/libc/gfx/gfx_hline256.c deleted file mode 100644 index 36d9e20..0000000 --- a/libc/gfx/gfx_hline256.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * gfx_hline256 — горизонтальная линия (mode 0x81) в W3-скобке. - */ - -#include "_gfx.h" - -void gfx_hline256(int x, int y, int len, uint8_t color) -{ - _gfx_w3_video_begin(); - _gfx_hline256_raw(x, y, len, color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_init.c b/libc/gfx/gfx_init.c deleted file mode 100644 index ad76c7c..0000000 --- a/libc/gfx/gfx_init.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * gfx_init — переключиться в графический режим `mode`, вернуть прежний. - * - * `page` (0/1) — стартовая страница: и видимая, и рисуемая; банк W3 - * сбрасывается в 0x50 (канонический видимый видеобанк). Идёт через - * _videomode_raw_set — минуя text-only валидацию conio. - */ - -#include "_gfx.h" - -uint8_t gfx_init(uint8_t mode, uint8_t page) -{ - uint8_t prev = _videomode_raw_get(); - _videomode_raw_set(mode); - _gfx_bank = 0x50; - gfx_set_visible_page(page); - gfx_set_draw_page(page); - return prev; -} diff --git a/libc/gfx/gfx_line16.c b/libc/gfx/gfx_line16.c deleted file mode 100644 index 8620af2..0000000 --- a/libc/gfx/gfx_line16.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * gfx_line16 — линия (x0,y0)-(x1,y1) (mode 0x82). Ортогональные — - * через hline/vline; наклонные — Брезенхэм с одной W3-скобкой. - */ - -#include "_gfx.h" - -void gfx_line16(int x0, int y0, int x1, int y1, uint8_t color) -{ - if (y0 == y1) { - int x = x0 <= x1 ? x0 : x1; - int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1; - gfx_hline16(x, y0, w, color); - return; - } - if (x0 == x1) { - int y = y0 <= y1 ? y0 : y1; - int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1; - gfx_vline16(x0, y, h, color); - return; - } - int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx; - int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy; - int err = (dx > dy ? dx : -dy) / 2; - int x = x0, y = y0; - _gfx_w3_video_begin(); - for (;;) { - _gfx_putpixel16_raw(x, y, color); - if (x == x1 && y == y1) break; - int e2 = err; - if (e2 > -dx) { err -= dy; x += sx; } - if (e2 < dy) { err += dx; y += sy; } - } - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_line256.c b/libc/gfx/gfx_line256.c deleted file mode 100644 index b3e0e1c..0000000 --- a/libc/gfx/gfx_line256.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * gfx_line256 — линия (x0,y0)-(x1,y1) (mode 0x81). Ортогональные - * уходят на акселератор; наклонные — Брезенхэм с одной W3-скобкой - * вокруг всего цикла. - */ - -#include "_gfx.h" - -void gfx_line256(int x0, int y0, int x1, int y1, uint8_t color) -{ - if (y0 == y1) { - int x = x0 <= x1 ? x0 : x1; - int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1; - gfx_hline256(x, y0, w, color); - return; - } - if (x0 == x1) { - int y = y0 <= y1 ? y0 : y1; - int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1; - gfx_vline256(x0, y, h, color); - return; - } - - int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx; - int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy; - int err = (dx > dy ? dx : -dy) / 2; - int x = x0, y = y0; - _gfx_w3_video_begin(); - for (;;) { - _gfx_putpixel256_raw(x, y, color); - if (x == x1 && y == y1) break; - int e2 = err; - if (e2 > -dx) { err -= dy; x += sx; } - if (e2 < dy) { err += dx; y += sy; } - } - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_putchar16.c b/libc/gfx/gfx_putchar16.c deleted file mode 100644 index fb78947..0000000 --- a/libc/gfx/gfx_putchar16.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * gfx_putchar16 — символ шрифтом 8×8 в (x,y), mode 0x82. - * x должен быть ЧЁТНЫМ (байтовое выравнивание); нечётный молча - * игнорируется — текстовые сетки обычно выровнены. - */ - -#include "_gfx.h" - -void gfx_putchar16(int x, int y, char c, uint8_t fg, uint8_t bg) -{ - _gfx_font_ensure(); - if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return; - if (x & 1) return; - - _gfx_t16_pair_build(fg, bg); - uint8_t cc = (uint8_t)c; - uint16_t base = (uint16_t)(_gfx_addr_base + ((unsigned)x >> 1)); - - for (int r = 0; r < 8; r++) { - int yy = y + r; - if ((unsigned)yy >= GFX_HEIGHT_16) break; - _gfx_t16_y = (uint8_t)yy; - _gfx_t16_addr = base; - _gfx_t16_row = _gfx_font_ptr[r * 256 + cc]; - _gfx_render_row16(); - } -} diff --git a/libc/gfx/gfx_putchar256.c b/libc/gfx/gfx_putchar256.c deleted file mode 100644 index dc53d14..0000000 --- a/libc/gfx/gfx_putchar256.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * gfx_putchar256 — символ шрифтом 8×8 в (x,y), mode 0x81 (байт на - * пиксель). На ряд глифа (8 пикселей) пишем 8 байт: FG где бит 1, - * BG где 0. Рендер ряда сам делает DI / W3 save+restore — вызывать - * можно из любого контекста без скобок. - */ - -#include "_gfx.h" - -/* Скретч рендера ряда — только этого модуля. */ -static uint8_t txt_y; -static uint8_t txt_row; /* битовый паттерн текущего ряда глифа */ -static uint8_t txt_fg; -static uint8_t txt_bg; -static uint16_t txt_addr; /* VRAM-адрес ряда */ - -static void render_row_256(void) __naked -{ - __asm - di - in a, (#0xE2) - push af - ld a, #0x50 - out (#0xE2), a - ld a, (_txt_y) - out (#0x89), a - - ld hl, (_txt_addr) - ld a, (_txt_fg) - ld d, a - ld a, (_txt_bg) - ld e, a - ld a, (_txt_row) - ld b, #8 ; 8 пикселей в ряду - rr256_loop: - rla ; CY = старший бит, A <<= 1 - jr nc, rr256_bg - ld (hl), d ; FG - jr rr256_next - rr256_bg: - ld (hl), e ; BG - rr256_next: - inc hl - djnz rr256_loop - - pop af - out (#0xE2), a - ei - ret - __endasm; -} - -void gfx_putchar256(int x, int y, char c, uint8_t fg, uint8_t bg) -{ - _gfx_font_ensure(); - if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return; - - txt_fg = fg; - txt_bg = bg; - uint8_t cc = (uint8_t)c; - uint16_t base = (uint16_t)(_gfx_addr_base + (unsigned)x); - - for (int r = 0; r < 8; r++) { - int yy = y + r; - if ((unsigned)yy >= GFX_HEIGHT) break; - txt_y = (uint8_t)yy; - txt_addr = base; - /* Interleaved-раскладка: ряд r глифа cc — font[r*256 + cc]. */ - txt_row = _gfx_font_ptr[r * 256 + cc]; - render_row_256(); - } -} diff --git a/libc/gfx/gfx_putpixel16.c b/libc/gfx/gfx_putpixel16.c deleted file mode 100644 index 47294ef..0000000 --- a/libc/gfx/gfx_putpixel16.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * gfx_putpixel16 — пиксель (x,y) цветом 0..15 (mode 0x82); - * одиночный вызов в собственной W3-скобке. - */ - -#include "_gfx.h" - -void gfx_putpixel16(int x, int y, uint8_t color) -{ - if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return; - _gfx_w3_video_begin(); - _gfx_putpixel16_raw(x, y, color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_putpixel256.c b/libc/gfx/gfx_putpixel256.c deleted file mode 100644 index 34e64b9..0000000 --- a/libc/gfx/gfx_putpixel256.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * gfx_putpixel256 — пиксель (x,y) цветом color (mode 0x81); - * одиночный вызов в собственной W3-скобке. - */ - -#include "_gfx.h" - -void gfx_putpixel256(int x, int y, uint8_t color) -{ - if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return; - _gfx_w3_video_begin(); - _gfx_putpixel256_raw(x, y, color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_rect16.c b/libc/gfx/gfx_rect16.c deleted file mode 100644 index 7de60c7..0000000 --- a/libc/gfx/gfx_rect16.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * gfx_rect16 — рамка w×h от (x,y) (mode 0x82); все четыре стороны - * в одной W3-скобке. - */ - -#include "_gfx.h" - -void gfx_rect16(int x, int y, int w, int h, uint8_t color) -{ - if (w <= 0 || h <= 0) return; - _gfx_w3_video_begin(); - _gfx_hline16_raw(x, y, w, color); - _gfx_hline16_raw(x, y + h - 1, w, color); - if (h > 2) { - _gfx_vline16_raw(x, y + 1, h - 2, color); - _gfx_vline16_raw(x + w - 1, y + 1, h - 2, color); - } - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_rect256.c b/libc/gfx/gfx_rect256.c deleted file mode 100644 index c2e3d47..0000000 --- a/libc/gfx/gfx_rect256.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * gfx_rect256 — рамка w×h от (x,y) (mode 0x81); все четыре стороны - * в одной W3-скобке. - */ - -#include "_gfx.h" - -void gfx_rect256(int x, int y, int w, int h, uint8_t color) -{ - if (w <= 0 || h <= 0) return; - _gfx_w3_video_begin(); - _gfx_hline256_raw(x, y, w, color); - _gfx_hline256_raw(x, y + h - 1, w, color); - if (h > 2) { - _gfx_vline256_raw(x, y + 1, h - 2, color); - _gfx_vline256_raw(x + w - 1, y + 1, h - 2, color); - } - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_text16.c b/libc/gfx/gfx_text16.c deleted file mode 100644 index 6f14666..0000000 --- a/libc/gfx/gfx_text16.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * gfx_text16 — строка шрифтом 8×8 от (x,y), mode 0x82; x чётный, - * растёт на 8 на символ. Pair-таблица строится один раз на всю - * строку (FG/BG не меняются) — поэтому не через gfx_putchar16. - */ - -#include "_gfx.h" - -void gfx_text16(int x, int y, const char *s, uint8_t fg, uint8_t bg) -{ - _gfx_font_ensure(); - if (x & 1) return; - _gfx_t16_pair_build(fg, bg); - for (; *s; s++) { - if (x >= GFX_WIDTH_16) break; - if ((unsigned)y >= GFX_HEIGHT_16) break; - uint8_t cc = (uint8_t)*s; - uint16_t base = (uint16_t)(_gfx_addr_base + ((unsigned)x >> 1)); - for (int r = 0; r < 8; r++) { - int yy = y + r; - if ((unsigned)yy >= GFX_HEIGHT_16) break; - _gfx_t16_y = (uint8_t)yy; - _gfx_t16_addr = base; - _gfx_t16_row = _gfx_font_ptr[r * 256 + cc]; - _gfx_render_row16(); - } - x += 8; - } -} diff --git a/libc/gfx/gfx_text256.c b/libc/gfx/gfx_text256.c deleted file mode 100644 index 4ba8ee5..0000000 --- a/libc/gfx/gfx_text256.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * gfx_text256 — строка шрифтом 8×8 от (x,y), mode 0x81; x растёт - * на 8 на символ. - */ - -#include "_gfx.h" - -void gfx_text256(int x, int y, const char *s, uint8_t fg, uint8_t bg) -{ - for (; *s; s++) { - if (x >= GFX_WIDTH) break; - gfx_putchar256(x, y, *s, fg, bg); - x += 8; - } -} diff --git a/libc/gfx/gfx_vline16.c b/libc/gfx/gfx_vline16.c deleted file mode 100644 index 34406e8..0000000 --- a/libc/gfx/gfx_vline16.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * gfx_vline16 — вертикальная линия (mode 0x82) в W3-скобке. - */ - -#include "_gfx.h" - -void gfx_vline16(int x, int y, int len, uint8_t color) -{ - _gfx_w3_video_begin(); - _gfx_vline16_raw(x, y, len, color); - _gfx_w3_video_end(); -} diff --git a/libc/gfx/gfx_vline256.c b/libc/gfx/gfx_vline256.c deleted file mode 100644 index 594f00b..0000000 --- a/libc/gfx/gfx_vline256.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * gfx_vline256 — вертикальная линия (mode 0x81) в W3-скобке. - */ - -#include "_gfx.h" - -void gfx_vline256(int x, int y, int len, uint8_t color) -{ - _gfx_w3_video_begin(); - _gfx_vline256_raw(x, y, len, color); - _gfx_w3_video_end(); -} diff --git a/libc/include/gfx.h b/libc/include/gfx.h deleted file mode 100644 index 197a004..0000000 --- a/libc/include/gfx.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * gfx.h — Sprinter graphics primitives. - * - * Two main modes: - * GFX_MODE_320x256x256 (0x81) — one byte per pixel, palette of 256 - * entries. API functions suffixed _256. - * GFX_MODE_640x256x16 (0x82) — 4 bits per pixel, palette of 16. - * API functions suffixed _16. - * - * Common API (no suffix) covers things that are mode-agnostic: - * gfx_init / gfx_done - * gfx_set_visible_page / gfx_set_draw_page / gfx_set_bank - * gfx_wait_vsync - * gfx_pal_load / gfx_pal_set - * gfx_load_default_font / gfx_set_font - * - * Addressing reminder: - * pixel (x, y) lives at CPU 0xC000 + (x or x/2) with Port_Y (0x89) = y; - * the gfx code maps a 16 KB VRAM page into W3 around every write. - * For double-buffering, page 1 starts 320 bytes later (0xC140). - * - * Palette: BIOS $A4 (RST 8); 4 bytes per entry — B, G, R, pad. - */ - -#ifndef GFX_H -#define GFX_H - -#include - -/* ESTEX SETVMOD codes — same values as the SETVMOD `A` register. */ -#define GFX_MODE_TEXT_40x32 0x02 -#define GFX_MODE_TEXT_80x32 0x03 -#define GFX_MODE_320x256x256 0x81 -#define GFX_MODE_640x256x16 0x82 - -/* Pixel dimensions of mode 0x81 (320×256, 256 colours). */ -#define GFX_WIDTH 320 -#define GFX_HEIGHT 256 - -/* Pixel dimensions of mode 0x82 (640×256, 16 colours). Each byte at - * 0xC000+x_byte holds two pixels: high nibble = LEFT (even-x), low - * nibble = RIGHT (odd-x) — see memory/sprinter_graphics.md. */ -#define GFX_WIDTH_16 640 -#define GFX_HEIGHT_16 256 -#define GFX_COLORS_16 16 - -/* ---- Setup / teardown -------------------------------------------- * - * - * Switch to `mode`, returning the previous mode for restore. `page` - * (0 or 1) selects the initial graphics screen — both the visible and - * the draw page are set to it, and the W3 bank is reset to 0x50 (the - * canonical visible video page). Programs that don't double-buffer - * just pass 0. */ -uint8_t gfx_init(uint8_t mode, uint8_t page); - -/* Restore a previously-saved video mode. */ -void gfx_done(uint8_t mode); - -/* ---- Page selection (double-buffering) and bank control ---------- * - * - * The Sprinter hardware holds two graphics screens. The VISIBLE page - * is what's shown on screen; the DRAW page is where the gfx_* writes - * land. Render the next frame into the hidden page and flip when ready. - * - * "Bank" is the W3 page byte (0x50..0x5F) — bits 2,3 select - * normal/temp/transparent display modes. All gfx_* primitives map - * THIS bank into W3 before touching 0xC000+. Default is 0x50. */ - -void gfx_set_visible_page(uint8_t page); /* 0 or 1 */ -uint8_t gfx_get_visible_page(void); - -void gfx_set_draw_page(uint8_t page); /* 0 or 1 */ -uint8_t gfx_get_draw_page(void); - -void gfx_set_bank(uint8_t bank); /* 0x50..0x5F */ -uint8_t gfx_get_bank(void); - -/* Block until the next frame interrupt (50 Hz on Sprinter). Uses - * `EI; HALT` — the Z80 sleeps until the next IM2 tick that DSS programs - * for keyboard / cursor handling. Typical use: - * - * gfx_set_draw_page(hidden); - * draw_frame(...); - * gfx_wait_vsync(); // wait for vretrace - * gfx_set_visible_page(hidden); // tear-free flip - */ -void gfx_wait_vsync(void); - -/* ---- 320×256×256 (mode 0x81) drawing API -------------------------- * - * Colour args are palette indices 0..255. */ - -void gfx_clear256 (uint8_t color); -void gfx_putpixel256 (int x, int y, uint8_t color); -uint8_t gfx_getpixel256 (int x, int y); -void gfx_hline256 (int x, int y, int len, uint8_t color); -void gfx_vline256 (int x, int y, int len, uint8_t color); -void gfx_line256 (int x0, int y0, int x1, int y1, uint8_t color); -void gfx_rect256 (int x, int y, int w, int h, uint8_t color); -void gfx_fill_rect256(int x, int y, int w, int h, uint8_t color); - -/* ---- 640×256×16 (mode 0x82) drawing API --------------------------- * - * Colour args are palette indices 0..15. The accelerator works - * byte-wise so vline16 falls back to per-row RMW (a byte spans two - * horizontal pixels). */ - -void gfx_clear16 (uint8_t color); -void gfx_putpixel16 (int x, int y, uint8_t color); -void gfx_hline16 (int x, int y, int len, uint8_t color); -void gfx_vline16 (int x, int y, int len, uint8_t color); -void gfx_line16 (int x0, int y0, int x1, int y1, uint8_t color); -void gfx_rect16 (int x, int y, int w, int h, uint8_t color); -void gfx_fill_rect16(int x, int y, int w, int h, uint8_t color); - -/* ---- Bitmap-font text -------------------------------------------- * - * Font is 256 glyphs × 8 rows × 1 byte (ZX-Spectrum format), 2 KB. - * On first use the default system font is fetched via BIOS WIN_GET_ZG - * (fn 0xB8). gfx_set_font() lets you swap in a custom font (the - * pointer is held — keep the storage alive). */ - -void gfx_load_default_font(void); -void gfx_set_font(const uint8_t *font); - -/* 320×256×256 text: one byte per pixel; advances x by 8 per char. */ -void gfx_putchar256(int x, int y, char c, uint8_t fg, uint8_t bg); -void gfx_text256 (int x, int y, const char *s, uint8_t fg, uint8_t bg); - -/* 640×256×16 text: 4 bits per pixel; x must be EVEN (byte-aligned). */ -void gfx_putchar16 (int x, int y, char c, uint8_t fg, uint8_t bg); -void gfx_text16 (int x, int y, const char *s, uint8_t fg, uint8_t bg); - -/* ---- Palette ----------------------------------------------------- * - * Each graphics page has its own palette page (page 0 → palette 0, - * page 1 → palette 1). For seamless double-buffering, load the same - * palette into both. */ - -/* Load a contiguous block of palette entries. - * pal_num: 0..3 (graphics palettes) - * start: first colour slot (0..255) - * count: number of slots (0 → 256) - * data: pointer to count entries, each formatted (B, G, R, 0). */ -void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count, - const uint8_t *data); - -/* Convenience: set one palette entry from RGB. Internally builds the - * BGR+pad triple and calls gfx_pal_load(pal_num, idx, 1, ...). */ -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 diff --git a/tests/bgi_img/Makefile b/tests/bgi_img/Makefile new file mode 100644 index 0000000..bc36d30 --- /dev/null +++ b/tests/bgi_img/Makefile @@ -0,0 +1,4 @@ +PROJ_ROOT := $(abspath $(CURDIR)/../..) +EXAMPLE := bgi_img +EXTRA_FLAGS := --gfx 256 +include $(PROJ_ROOT)/app.mk diff --git a/tests/bgi_img/bgi_img.c b/tests/bgi_img/bgi_img.c new file mode 100644 index 0000000..07ff492 --- /dev/null +++ b/tests/bgi_img/bgi_img.c @@ -0,0 +1,114 @@ +/* + * bgi_img — тест спрайтов BGI: getimage / putimage / imagesize + * (режим 320×256×256, --gfx 256). + * + * Что проверяем: + * 1. imagesize() совпадает с реальным размером буфера (self-check — + * при расхождении рисуется красная плашка "SIZE MISMATCH"). + * 2. getimage() снимает прямоугольник экрана в буфер (заголовок + * w,h + w*h байт). + * 3. putimage() кладёт образ всеми пятью операциями COPY/XOR/OR/AND/ + * NOT поверх серого фона — визуально видно разницу операций. + * 4. XOR дважды по одному месту восстанавливает фон (классический + * признак корректного спрайтового XOR). + * + * Прогон в MAME визуальный: см. что источник и его COPY-копия + * идентичны (в т.ч. красный маркер в левом-верхнем углу — ловит + * зеркалирование), а XOR-дважды не оставляет следа на фоне. + */ + +#include +#include + +/* Габариты спрайта-источника. Из них же считаем и рект, и буфер — + * так imagesize() и sizeof(buf) обязаны сойтись. */ +#define SPR_L 16 +#define SPR_T 28 +#define SPR_W 40 +#define SPR_H 32 + +/* Буфер образа: 4 байта заголовка (w,h) + по байту на пиксель. */ +static uint8_t sprite[4 + SPR_W * SPR_H]; + +/* Нарисовать узнаваемый ассиметричный образ в (SPR_L,SPR_T). */ +static void draw_source(void) +{ + int l = SPR_L, t = SPR_T; + int r = l + SPR_W - 1, b = t + SPR_H - 1; + + setfillstyle(SOLID_FILL, LIGHTBLUE); + bar(l, t, r, b); /* фон образа */ + + setcolor(YELLOW); + circle(l + SPR_W / 2, t + SPR_H / 2, 10); + + setcolor(WHITE); + line(l, t, r, b); /* диагональ */ + + /* Красный маркер в левом-верхнем углу — детектор ориентации. */ + setfillstyle(SOLID_FILL, LIGHTRED); + bar(l, t, l + 5, t + 5); + + setcolor(WHITE); + rectangle(l - 1, t - 1, r + 1, b + 1); /* рамка вокруг источника */ +} + +int main(void) +{ + static const int ops[5] = { COPY_PUT, XOR_PUT, OR_PUT, AND_PUT, NOT_PUT }; + static const char *names[5] = { "COPY", "XOR", "OR", "AND", "NOT" }; + int i, x; + int sl = SPR_L, st = SPR_T; + int sr = SPR_L + SPR_W - 1, sb = SPR_T + SPR_H - 1; + + initgraph(); + cleardevice(); + + setcolor(WHITE); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 1); + outtextxy(80, 6, "getimage/putimage test"); + + /* --- источник --- */ + outtextxy(SPR_L, 18, "src"); + draw_source(); + + /* --- imagesize() self-check --- */ + if (imagesize(sl, st, sr, sb) != (unsigned)sizeof(sprite)) { + setfillstyle(SOLID_FILL, LIGHTRED); + bar(80, 90, 240, 100); + setcolor(WHITE); + outtextxy(84, 92, "SIZE MISMATCH"); + } + + /* --- снимаем образ --- */ + getimage(sl, st, sr, sb, sprite); + + /* --- пять операций putimage поверх серого фона --- */ + for (i = 0; i < 5; i++) { + x = 16 + i * 60; + setcolor(WHITE); + outtextxy(x, 108, names[i]); + + setfillstyle(SOLID_FILL, LIGHTGRAY); /* общий фон под все ops */ + bar(x, 120, x + SPR_W - 1, 120 + SPR_H - 1); + + putimage(x, 120, sprite, ops[i]); + } + + /* --- XOR дважды = восстановление фона --- */ + setcolor(WHITE); + outtextxy(16, 176, "XOR x2 -> restores bg (patch stays clean):"); + + setfillstyle(SOLID_FILL, GREEN); + bar(16, 190, 16 + SPR_W - 1, 190 + SPR_H - 1); + putimage(16, 190, sprite, XOR_PUT); /* наложили */ + putimage(16, 190, sprite, XOR_PUT); /* сняли */ + + /* Рядом — тот же зелёный фон нетронутым, для сравнения. */ + setfillstyle(SOLID_FILL, GREEN); + bar(80, 190, 80 + SPR_W - 1, 190 + SPR_H - 1); + setcolor(WHITE); + outtextxy(130, 202, "<- these two must match ->"); + + for (;;) { } +} diff --git a/tests/gfx_dbuf/Makefile b/tests/gfx_dbuf/Makefile index c6c92f4..3702dd4 100644 --- a/tests/gfx_dbuf/Makefile +++ b/tests/gfx_dbuf/Makefile @@ -1,3 +1,4 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..) -EXAMPLE := gfx_dbuf +EXAMPLE := gfx_dbuf +EXTRA_FLAGS := --gfx 256 include $(PROJ_ROOT)/app.mk diff --git a/tests/gfx_dbuf/gfx_dbuf.c b/tests/gfx_dbuf/gfx_dbuf.c index 0a092ff..80341e6 100644 --- a/tests/gfx_dbuf/gfx_dbuf.c +++ b/tests/gfx_dbuf/gfx_dbuf.c @@ -1,29 +1,26 @@ /* - * gfx_dbuf — double-buffering demo. + * gfx_dbuf — double-buffering demo (BGI, bgi256.lib). * - * 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). + * Рендерит движущийся прямоугольник, чередуя страницу 0 и 1: + * - Каждый кадр: рисуем на СКРЫТОЙ странице, затем делаем её видимой. + * - Видимая страница никогда не пишется → пользователь видит только + * целые кадры (без артефактов, без мерцания от 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. + * Переключение страниц и vsync — через mode-agnostic gfx_* (gfx.h, + * остались в BGI_GFX): gfx_set_draw_page / gfx_set_visible_page / + * gfx_get_visible_page / gfx_wait_vsync. Рисование — через BGI + * (graphics.h): cleardevice / bar / rectangle / outtextxy. Режим + * 0x81 выбирается линковкой: EXTRA_FLAGS=--gfx 256. * - * 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. + * Индикатор страницы (маленький swatch сверху-справа) меняет оттенок + * каждый кадр — если бокс движется плавно, а swatch мигает между двумя + * оттенками, своп работает. Press any key to exit. */ #include #include -#include +#include +#include /* double-buffering + vsync (mode-agnostic) */ #include static uint8_t palette[256 * 4]; @@ -48,42 +45,44 @@ static void make_palette(void) static void draw_frame(int box_x, int box_y, uint8_t page_indicator) { - gfx_clear256(COL_BG); + setbkcolor(COL_BG); cleardevice(); /* 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); + setfillstyle(SOLID_FILL, COL_STRIPE); + bar(0, 0, GFX_WIDTH - 1, 7); + bar(0, GFX_HEIGHT - 8, GFX_WIDTH - 1, GFX_HEIGHT - 1); - 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); + setcolor(COL_TEXT); + outtextxy(8, 16, "double-buffering demo"); + outtextxy(8, GFX_HEIGHT - 24, "press a key to exit"); - /* 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); + /* Page indicator — different shade per page: flicker here proves + * the swap is happening. */ + setfillstyle(SOLID_FILL, page_indicator ? COL_PAGE1 : COL_PAGE0); + bar(GFX_WIDTH - 24, 16, GFX_WIDTH - 24 + 11, 16 + 11); /* The animated box. */ - gfx_fill_rect256(box_x, box_y, 40, 30, COL_BOX); - gfx_rect256 (box_x, box_y, 40, 30, COL_BLACK); + setfillstyle(SOLID_FILL, COL_BOX); + bar(box_x, box_y, box_x + 39, box_y + 29); + setcolor(COL_BLACK); + rectangle(box_x, box_y, box_x + 39, box_y + 29); } int main(void) { make_palette(); - uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0); + initgraph(); - /* 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. */ + /* Каждая графическая страница имеет свою палитру (0→pal 0, 1→pal 1). + * Грузим одну и ту же в обе — визуальный своп бесшовный. */ 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); + /* Очистить обе страницы, чтобы первый флип не вскрыл мусор. */ + setbkcolor(COL_BG); + gfx_set_draw_page(0); cleardevice(); + gfx_set_draw_page(1); cleardevice(); /* Bouncing rect state. */ int box_x = 10; @@ -98,9 +97,8 @@ int main(void) 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. */ + /* Ждать следующий кадр перед флипом — своп падает в vblank, + * пользователь не видит полунарисованный кадр. */ gfx_wait_vsync(); gfx_set_visible_page(hidden); @@ -114,7 +112,7 @@ int main(void) } (void)getch(); - gfx_done(prev); + closegraph(); puts("done"); return 0; } diff --git a/tests/gfx_demo/Makefile b/tests/gfx_demo/Makefile index 7324b8d..3352578 100644 --- a/tests/gfx_demo/Makefile +++ b/tests/gfx_demo/Makefile @@ -1,3 +1,4 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..) -EXAMPLE := gfx_demo +EXAMPLE := gfx_demo +EXTRA_FLAGS := --gfx 256 include $(PROJ_ROOT)/app.mk diff --git a/tests/gfx_demo/gfx_demo.c b/tests/gfx_demo/gfx_demo.c index 0a88638..aa1945d 100644 --- a/tests/gfx_demo/gfx_demo.c +++ b/tests/gfx_demo/gfx_demo.c @@ -1,15 +1,23 @@ /* - * 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 + * gfx_demo — exercises the BGI primitives (bgi256.lib). Shows: + * 1. cleardevice / line (orthogonal frame via horizontal/vertical lines) + * 2. rectangle outlines, line diagonals (Bresenham) + * 3. bar filled-rect colour bars (accelerator-backed) + * 4. a grey-ramp palette + * + * Migrated с низкоуровневого gfx.h drawing-API на BGI (graphics.h). + * Режим 0x81 (320×256×256) выбирается линковкой: EXTRA_FLAGS=--gfx 256 + * (см. Makefile). Палитура грузится через gfx_pal_load (mode-agnostic, + * остался в gfx.h) — BGI initgraph уже загрузил EGA-палитру, мы её + * подменяем серым клином. * * Press a key to advance through each stage. */ #include #include -#include +#include +#include /* GFX_WIDTH/HEIGHT, gfx_pal_load (mode-agnostic) */ #include static uint8_t palette_data[256 * 4]; @@ -32,69 +40,74 @@ int main(void) palette_data[i * 4 + 3] = 0; } - uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0); + initgraph(); 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); + /* --- Stage 1: orthogonal frame via horizontal/vertical lines ------ */ + setbkcolor(0x40); cleardevice(); + setcolor(0xFF); + line(1, 1, GFX_WIDTH - 2, 1); /* top */ + line(1, GFX_HEIGHT - 2, GFX_WIDTH - 2, GFX_HEIGHT - 2); /* bottom */ + line(1, 2, 1, GFX_HEIGHT - 4); /* left */ + line(GFX_WIDTH - 2, 2, GFX_WIDTH - 2, GFX_HEIGHT - 4); /* right */ 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. */ + /* --- Stage 2: nested rectangles --------------------------------- */ + setbkcolor(0x20); cleardevice(); 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)); + setcolor((uint8_t)(0x40 + i * 8)); + rectangle(i * 10, i * 8, + GFX_WIDTH - i * 20, + GFX_HEIGHT - 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)); + /* --- Stage 3: filled-rect colour bars (bar = залитый прямоугольник) */ + setbkcolor(0); cleardevice(); + for (int i = 0; i < 16; i++) { + setfillstyle(SOLID_FILL, (uint8_t)(i * 16)); + bar(i * 20, 0, i * 20 + 19, 127); + setfillstyle(SOLID_FILL, (uint8_t)(255 - i * 16)); + bar(i * 20, 128, i * 20 + 19, 255); + } wait_key(); - /* --- Stage 4: diagonal lines via Bresenham ---------------------- */ - gfx_clear256(0x18); - /* "Star" of lines from centre to a circle of endpoints. */ + /* --- Stage 3b: wide-short stripes + a grid of small squares ------ */ + setbkcolor(0x08); cleardevice(); + for (int i = 0; i < 8; i++) { + setfillstyle(SOLID_FILL, (uint8_t)(0x40 + i * 24)); + bar(0, i * 32, GFX_WIDTH - 1, i * 32 + 15); + } + for (int row = 0; row < 4; row++) + for (int col = 0; col < 16; col++) { + setfillstyle(SOLID_FILL, (uint8_t)((row * 16 + col) * 4)); + bar(col * 20 + 4, 256 - 80 + row * 20, + col * 20 + 4 + 11, 256 - 80 + row * 20 + 11); + } + wait_key(); + + /* --- Stage 4: diagonal lines via Bresenham ----------------------- */ + setbkcolor(0x18); cleardevice(); 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); + setcolor(0xFF); line(cx, cy, ex, 0); + setcolor(0xC0); line(cx, cy, ex, GFX_HEIGHT - 1); } 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); + setcolor(0x80); line(cx, cy, 0, ey); + setcolor(0x40); line(cx, cy, GFX_WIDTH - 1, ey); } - /* 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); + /* Box outline. */ + setcolor(0xFF); + line(0, 0, GFX_WIDTH - 1, 0); + line(0, GFX_HEIGHT - 1, GFX_WIDTH - 1, GFX_HEIGHT - 1); + line(0, 0, 0, GFX_HEIGHT - 1); + line(GFX_WIDTH - 1, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); wait_key(); - gfx_done(prev); + closegraph(); puts("done"); return 0; }