/*
 * 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 <graphics.h>
#include <stdint.h>

/* Габариты спрайта-источника. Из них же считаем и рект, и буфер —
 * так 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 (;;) { }
}
