/*
 * _bgi_blit_cols_raw — accel block-copy КОЛОНКАМИ (буфер column-major ->
 * экран).  Парный к _bgi_blit_rows_raw, но вертикальный проход: каждая
 * КОЛОНКА копируется одним accel-burst'ом вниз (Port_Y авто-шагает),
 * опкод LD A,A (0x7F — «копирование блока для вертикального прохода»,
 * см. docs/reference/accel_r.txt).  dst двигается на +1 (следующий x) на
 * колонку; Port_Y сбрасывается в y0 перед каждой колонкой (accel шагает
 * его внутри burst'а); src двигается на sstride на колонку.
 *
 * ЗАЧЕМ: бесплатный ГОРИЗОНТАЛЬНЫЙ флип персонажей — вызывающий подаёт
 * src с конца (src+(w-1)*h) и sstride=-h, тогда правая колонка источника
 * ложится в левый x экрана (зеркало).  Реверс без CPU и без удвоения
 * памяти.  Спрайты персонажей хранятся column-major.
 *
 * ВХОД (__sdcccall(1)): src→HL, dst→DE; стек: w 4(ix), h 5(ix),
 * sstride 6/7(ix), y0 8(ix).  w — число КОЛОНОК (1..256, 0=256); h —
 * высота колонки = размер accel-блока (1..256, 0=256); sstride — шаг
 * адреса src между колонками (±); y0 — стартовый Port_Y.  Callee-pop 5 Б.
 *
 * Raw: без клиппинга (вызывающий); W3 замаплен (_bgi_begin/end снаружи);
 * банк выставлен вызывающим (0x5C прозрачный / 0x50 обычный).  src ВНЕ W3.
 * ОДИН DI на весь блит.  Колонки > 256 строк режет вызывающий (h ≤ 256).
 * Клоббер: AF/BC/DE/HL; IX сохраняется.
 */

#include "../_bgi.h"

void _bgi_blit_cols_raw(const uint8_t *src, uint8_t *dst,
                        uint8_t w, uint8_t h,
                        int sstride, uint8_t y0) __naked
{
    (void)src; (void)dst; (void)w; (void)h; (void)sstride; (void)y0;
    __asm
        push  ix
        ld    ix, #0
        add   ix, sp
        ;; SMC: размер accel-блока <- h (высота колонки)
        ld    a, 5 (ix)
        ld    (bc_len_imm), a
        ;; SMC: src-страйд между колонками (8-бит adc-цепочка, ± на вызов)
        ld    a, 6 (ix)
        ld    (bc_slo_imm), a
        ld    a, 7 (ix)
        ld    (bc_shi_imm), a
        ld    b, 4 (ix)            ; B = число колонок (0 => 256: djnz)
        ld    c, 8 (ix)            ; C = y0 (Port_Y, константа)
        di                         ; один DI на весь блит
        ld    d, d                 ; 0x52 — режим размера блока
        ld    a, #0
    bc_len_imm = . - 1
        ld    b, b                 ; 0x40 — стоп (B=счётчик не тронут)
    bc_col:
        ld    a, c
        out   (#0x89), a           ; Port_Y = y0 (сброс на верх колонки)
        ;; ЧТЕНИЕ — ГОРИЗОНТАЛЬНОЙ копией (LD L,L): src-колонка лежит в ОЗУ
        ;; СМЕЖНО, адрес шагает (не port_y).  ЗАПИСЬ — ВЕРТИКАЛЬНОЙ (LD A,A):
        ;; port_y шагает вниз по видео-колонке.  Режим меняется между read и
        ;; write (do_accel_block применяет один режим на весь блок).
        ld    l, l                 ; 0x6D — гориз. копия (для ЧТЕНИЯ смежных)
        ld    a, (hl)              ; read-блок: h смежных байт src -> буфер accel
        ld    a, a                 ; 0x7F — верт. копия (для ЗАПИСИ колонки)
        ld    (de), a              ; write-блок: буфер -> видео-колонка (port_y++)
        ld    b, b                 ; 0x40 — стоп
        ;; src += sstride (следующая колонка источника)
        ld    a, l
        add   a, #0
    bc_slo_imm = . - 1
        ld    l, a
        ld    a, h
        adc   a, #0
    bc_shi_imm = . - 1
        ld    h, a
        inc   de                   ; dst += 1 (следующий x)
        djnz  bc_col
        ei                         ; закрыть DI-окно
        pop   ix
        ;; callee-pop 5 байт (w,h,sstride:2,y0)
        pop   hl                   ; ret-адрес
        pop   af
        pop   af
        inc   sp
        jp    (hl)
    __endasm;
}
