/*
 * _putch_wrchar — воркер вывода mode-0: пишет символ в (pc_place)
 * через ESTEX WRCHAR ($58) атрибутом attr, интерпретируя управляющие:
 *
 *     0x08 BS  → pc_col-- (если не 0)
 *     0x09 TAB → pc_col к следующему кратному 8 (потолок 80)
 *     0x0A LF  → pc_row++ (потолок 32; без глифа)
 *     0x0D CR  → pc_col = 0
 *     прочее   → WRCHAR + pc_col++
 *
 * WRCHAR подавляется при pc_col ≥ 80 или pc_row ≥ 32 (вне экрана) —
 * координаты только [0..79] × [0..31].
 *
 * Курсор BIOS НЕ трогает — вызывающий читает его один раз до серии
 * вызовов и записывает один раз после: плата BIOS за ОПЕРАЦИЮ,
 * а не за символ.
 */

#include "_conio.h"

void _putch_wrchar(char ch, uint8_t attr) __naked
{
    (void)ch; (void)attr;
    __asm
        ;; __sdcccall(1): ch в A, attr в L.
        ;; Диспетчеризация по управляющим, пока A держит ch (cp не
        ;; трогает A).  B/C грузятся только на пути вывода, поэтому
        ;; ветки управляющих символов дешевле.
        cp    #0x08
        jr    z, _rp0_bs
        cp    #0x09
        jr    z, _rp0_tab
        cp    #0x0A
        jr    z, _rp0_lf
        cp    #0x0D
        jr    z, _rp0_cr
        ;; Всё остальное (печатное или незнакомый ctrl) → глиф.

    _rp0_pri:

        ld    c, a                  ; C = ch (сохранить до порчи A)
        ld    a, (_pc_place + 1)
        cp    #32
        ret   nc                    ; за нижним краем — молча пропустить
        ld    d, a                  ; D = row (конвенция ESTEX WRCHAR)
        ld    a, (_pc_place)
        cp    #80
        ret   nc                    ; за правым краем — молча пропустить
        ld    e, a                  ; E = col
        inc   a
        ld    (_pc_place), a        ; pc_col++

    _rp0_wr:
        ld    b, l                  ; B = attr
        ld    a, c                  ; A = ch
        push  ix
        ld    c, #0x58              ; ESTEX WRCHAR
        rst   #0x10
        pop   ix
        ret

    _rp0_bs:
        ld    a, (_pc_place)
        or    a, a
        ret   z                     ; уже в колонке 0 — без изменений
        dec   a
        ld    (_pc_place), a
        ld    e, a                  ; E = col
        ld    a, (_pc_place + 1)
        ld    d, a                  ; D = row (конвенция ESTEX WRCHAR)
        ld    c, #0x20
        jr    _rp0_wr

    _rp0_tab:
        ld    a, (_pc_place)
        or    #0x07                 ; округлить вниз к кратному 8
        inc   a                     ; → следующее кратное 8
        cp    #81                   ; сравнить A с 81 (0x51)
        jr    c, _rp0_tab_skip      ; если A < 81 (т.е. A ≤ 80), пропустить загрузку
        ld    a, #80                ; иначе A > 80 → установить A = 80
    _rp0_tab_skip:
        ld    (_pc_place), a
        ret

    _rp0_lf:
        ld    a, (_pc_place + 1)
        cp    #32
        ret   nc                    ; уже у нижнего края
        inc   a
        ld    (_pc_place + 1), a
        ret

    _rp0_cr:
        xor   a, a
        ld    (_pc_place), a
        ret
    __endasm;
}
