view draw_outputs.pde @ 232:ea6eb6541607

Cleanups.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 06 Sep 2018 12:58:41 +0300
parents 1c9deae71fb1
children
line wrap: on
line source

// Collect all that "writes" the virtual image in some way or other
// plus other active manipulations

int clampv(int v, int vmin, int vmax)
{
    return (v < vmin) ? vmin : (v > vmax ? vmax : v);
}

int chop2(int v)
{
    return int(v / 2) * 2;
}

int chop8(int v)
{
    return int(v / 8) * 8;
}

int chopv(int v, int qv)
{
    return int(v / qv) * qv;
}


void createpoint(int x, int y, int mo)
{
    if (mo == LEFT) makepoint(x, y);
    else
    if (mo == RIGHT) clearpoint(x, y);
}


void doborx(int xf, int yf, int xt, int yt)
{
    //rectangle for brush drawing
    for (int ii = xf; ii <= xt; ii++)
    for (int jj = yf; jj <= yt; jj++)
        createpoint(ii, jj, g_button);
}


void docircx(int xf, int yf, int hh, int vv)
{
    //circle for brush drawing
    float prop, fh = hh, fv = vv;

    if (vv > 0)
    {
        prop = fh / fv;
    }
    else
    {
        prop = 1;
    }
    hh++;

    for (int ii = -hh; ii <= hh; ii++)
    for (int jj = -vv; jj <= vv; jj++)
    {
        if (dist(xf + ii, yf + jj * prop, xf, yf) <= hh - 1)
            createpoint(xf + ii, yf + jj, g_button);
    }
}


void craft(int x, int y, int c)
{
    //foundational brush control
    //whether hard coded, circular or bitmap brush
    int calc, mb;
    int a1, b1, s1, x0, y0, midx, midy, passes, ofx, ofy;
    ofx = x;
    ofy = y;
    mb = g_button;
    if (g_btype == 1)
    {
        if (g_bsize < 4)
        {
            //some hardcoded brushes
            switch (g_bsize)
            {
                case 0:
                    doborx(ofx, ofy, ofx + 1, ofy + 1);
                    break;
                case 1:
                    if (g_data[int('c')] == 1 || g_shift == true)
                    {
                        ofx = ofx + 1;
                        ofy = ofy + 1;
                    }
                    doborx(ofx - 1, ofy - 1, ofx + 1, ofy + 1);
                    break;
                case 2:
                    if (g_data[int('c')] == 1 || g_shift == true)
                    {
                        ofx = ofx + 2;
                        ofy = ofy + 2;
                    }
                    doborx(ofx - 2, ofy - 2, ofx + 1, ofy + 1);
                    break;
                case 3:
                    if (g_data[int('c')] == 1 || g_shift == true)
                    {
                        ofx = ofx + 3;
                        ofy = ofy + 3;
                    }
                    doborx(ofx - 3, ofy - 3, ofx + 4, ofy + 4);
                    break;
            }
        }
        else
        { //larger size brushes
            calc = g_bsize - 3;
            calc = calc * calc;
            calc = calc + 4;
            doborx(x - calc, y - calc, x + calc, y + calc);
        }
        return;
    }

    if (g_btype == 9)
    { //bitmap brush
        passes = 2;
        int tempox, tempoy, tempx, tempy, moloy;
        moloy = 1;
        tempox = g_bsourcex;
        tempoy = g_bsourcey;
        tempx = g_bsourcex2;
        tempy = g_bsourcey2;
        if (g_data[int('t')] == 1)
        {
            if (tempx > g_bsourcex + 16) tempx = g_bsourcex + 16;
            if (tempy > g_bsourcey + 16) tempy = g_bsourcey + 16;
        }
        midx = int((g_bsourcex2 - g_bsourcex) / 2);
        midy = int((g_bsourcey2 - g_bsourcey) / 2);
        if (g_data[int('c')] == 1 || g_shift == true)
        {
            if (g_data[int('q')] == 1)
            {
                // XXX is this g_gridx an error?
                midy = chopv(midy, g_gridx);
                midx = chopv(midx, g_gridx);
            }
        }
        int orient = g_data[int('x')] * 100 + g_data[int('y')] * 10 + g_data[int('q')];
        if (g_pixelw == 2)
        {
            x = chop2(x);
            passes = 1;
        }

        for (int pp = 1; pp <= passes; pp++)
        {
            for (int yy = tempoy; yy <= tempy; yy = yy + moloy)
            {
                for (int xx = tempox; xx <= tempx; xx = xx + g_pixelw)
                {
                    s1 = int(g_brush[1024 + xx + yy * X]);
                    if (g_multic == 0) s1 = getabsa(xx, yy, 1);
                    if (g_multic > 0) s1 = getmultibrush(xx, yy);
                    if (s1 != g_backg)
                    {
                        x0 = x + xx - g_bsourcex;
                        y0 = y + yy - g_bsourcey;

                        if (g_data[int('q')] == 1)
                        {
                            x0 = x - (yy - g_bsourcey2);
                            y0 = y + (xx - g_bsourcex);
                            x0 = x0 + midx;
                            x0 = x0 - midy;
                            y0 = y0 + midy;
                            y0 = y0 - midx;
                        }

                        if (g_data[int('x')] == 1)
                        {
                            x0 = x0 - (x + midx);
                            x0 = -x0;
                            x0 = x0 + (x + midx);
                        }

                        if (g_data[int('y')] == 1)
                        {
                            y0 = y0 - (y + midy);
                            y0 = -y0;
                            y0 = y0 + (y + midy);
                        }

                        if (g_data[int('c')] == 1 || g_shift)
                        {
                            if (orient == 10) y0 = y0 + 1;
                            if (orient == 11) y0 = y0 + g_gridy - g_pixelw;
                            if (orient == 100) x0 = x0 + 1;
                            if (orient == 101) x0 = x0 + g_gridx - 1;
                            if (orient == 110)
                            {
                                x0 = x0 + 1;
                                y0 = y0 + 1;
                            }
                            if (orient == 111)
                            {
                                x0 = x0 + g_gridx - 1;
                                y0 = y0 + g_gridy - g_pixelw;
                            }
                        }

                        if (mb == LEFT)
                        {
                            if (g_multic > 0)
                            {
                                g_farge = s1;
                                if (g_data[int('p')] == 1) g_farge = g_ofarge;
                                if (g_pixelw == 2)
                                {
                                    if (g_data[int('q')] == 0) makepoint(x0, y0);
                                    if (g_data[int('q')] == 1)
                                    {
                                        makepoint(x0 - x + x0, y + (y0 - y));
                                        makepoint(x0 - x + x0, y + (y0 - y) + 1);
                                    }
                                }
                                else
                                {
                                    makepoint(x0, y0);
                                }
                            }
                            else
                            {
                                g_farge = s1;
                                if (zxcolor(g_farge) != zxcolor(g_backg))
                                {
                                    if (g_data[int('p')] == 1) g_farge = g_ofarge;
                                    makepoint(x0, y0);
                                }
                            }
                        }

                        if (mb == RIGHT)
                        {
                            if (g_multic > 0)
                            {
                                if (g_pixelw == 2)
                                {
                                    if (g_data[int('q')] == 0) clearpoint(x0, y0);
                                    if (g_data[int('q')] == 1)
                                    {
                                        clearpoint(x0 - x + x0, y + (y0 - y));
                                        clearpoint(x0 - x + x0, y + (y0 - y) + 1);
                                    }
                                }
                                else
                                {
                                    clearpoint(x0, y0);
                                }
                            }
                            else
                            {
                                clearpoint(x0, y0);
                            }
                        }
                    }
                }
            }
        }
        g_farge = g_ofarge;
        return;
    }

    if (g_bsize < 4)
    {
        switch (g_bsize)
        {
            case 0:
                createpoint(x, y, g_button);
                break;
            case 1:
                createpoint(x, y + 1, g_button);
                createpoint(x, y - 1, g_button);
                createpoint(x, y, g_button);
                createpoint(x - 1, y, g_button);
                createpoint(x + 1, y, g_button);
                break;
            case 2:
                doborx(x - 1, y - 2, x + 1, y + 2);
                doborx(x - 2, y - 1, x + 2, y + 1);
                break;
            case 3:
                doborx(x - 3, y - 1, x + 3, y + 1);
                doborx(x - 1, y - 3, x + 1, y + 3);
                doborx(x - 2, y - 2, x + 2, y + 2);
                break;
        }
    }
    else
    {
        calc = g_bsize - 3;
        calc = calc * calc;
        calc = calc + 4;
        docircx(x, y, calc, calc);
    }
}


void do_line(int xfrom, int yfrom, int xto, int yto, int prevent)
{
    //bresenham almost exactly from Wikipedia
    int swap, pex, pey;
    boolean steep;
    //multicolor 160 pixel reso
    if (g_pixelw == 2)
    {
        xfrom = chop2(xfrom);
        xto = chop2(xto);
    }

    craft(xfrom, yfrom, 0);
    pex = xfrom;
    pey = yfrom;

    if (prevent == 0) craft(xto, yto, 0);

    if (g_pixelw == 2)
    {
        xfrom = int(xfrom / 2);
        xto = int(xto / 2);
    }

    int x0 = xfrom;
    int y0 = yfrom;
    int x1 = xto;
    int y1 = yto;

    steep = abs(y1 - y0) > abs(x1 - x0);

    if (steep)
    {
        swap = x0;
        x0 = y0;
        y0 = swap;
        swap = x1;
        x1 = y1;
        y1 = swap;
    }

    float deltax = abs(x1 - x0);
    float deltay = abs(y1 - y0);
    float error = deltax / 2;
    int ystep;

    if (deltax == 0) return;

    int y = y0;
    int inc;

    if (x0 < x1)
    {
        inc = 1;
    }
    else
    {
        inc = -1;
    }
    if (y0 < y1)
    {
        ystep = 1;
    }
    else
    {
        ystep = -1;
    }
    int x;
    x = x0;
    while (x != x1)
    {
        if (steep)
        {
            if (y * g_pixelw != pex || x != pey)
            {
                craft(y * g_pixelw, x, 0);
                pex = y * g_pixelw;
                pey = x;
            }
        }
        else
        {
            if (x * g_pixelw != pex || y != pey)
            {
                craft(x * g_pixelw, y, 0);
                pex = x * g_pixelw;
                pey = y;
            }
        }

        error = error - deltay;
        if (error < 0)
        {
            y = y + ystep;
            error = error + deltax;
        }
        x = x + inc;
    }
}

void do_circle_new(int x1, int y1, int x2, int y2)
{
    int hh, vv;
    float prop;
    int xf, yf;
    float fh, fv;

    if (x2 < x1) x2 = x1 - (x2 - x1);
    if (y2 < y1) y2 = y1 - (y2 - y1);

    xf = x1;
    yf = y1;
    hh = x2 - x1;
    vv = y2 - y1;
    fh = hh;
    fv = vv;
    if (vv > 0)
    {
        prop = fh / fv;
    }
    else
    {
        prop = 1;
    }
    hh++;
    for (int ii = -hh; ii <= hh; ii++)
    for (int jj = -vv; jj <= vv; jj++)
    {
        if (dist(xf + ii, yf + jj * prop, xf, yf) <= hh - 1)
            createpoint(xf + ii, yf + jj, g_button);
    }
}


void do_circle(int x1, int y1, int x2, int y2)
{
    float dds, a, t, sx, sy, gear1, gear2, x0, y0;
    int prex, prey;

    dds = dist(x1, y1, x2, y2);
    gear1 = int(dds);
    if (gear1 <= 12) gear1 = 12;
    if (gear1 > 120) gear1 = 120;
    gear2 = int(gear1 * 2);

    if (x2 < x1) x2 = x1 - (x2 - x1);
    if (y2 < y1) y2 = y1 - (y2 - y1);

    if (g_data[int('t')] == 1 && x2 > x1 + 15) x2 = x1 + 16;
    if (g_data[int('t')] == 1 && y2 > y1 + 15) y2 = y1 + 16;

    if (g_data[int('f')] == 1 && g_btype != 9)
    {
        if (g_multic == 1 && g_data[int('d')] == 0)
        {
            g_farge = g_map[1];
            docircx(x1, y1, abs(x2 - int(x1)), abs(y2 - int(y1)));
            g_farge = g_ofarge;
        }
        docircx(x1, y1, abs(x2 - int(x1)), abs(y2 - int(y1)));
    }

    prex = 0;
    prey = 0;
    for (t = 0; t <= (gear2); t++)
    {
        a = t / (gear1) * PI;
        sx = (x2 - x1) * sin(a);
        sy = (y1 - y2) * cos(a);
        if (t > 0) do_line(prex, prey, x1 + int(sx), y1 + int(sy), 1);
        prex = (x1 + int(sx));
        prey = (y1 + int(sy));
    }
}


void do_rectangle(int x1, int y1, int x2, int y2)
{
    int x0, y0, yt, xt, xf, yf;

    xf = chop8(x1);
    xt = chop8(x2);

    yf = chop8(y1);
    yt = chop8(y2);

    yt = yt + 7;
    xt = xt + 6;

    if (x2 < x1)
    {
        x0 = x2;
        x2 = x1;
        x1 = x0;
    }
    if (y2 < y1)
    {
        y0 = y2;
        y2 = y1;
        y1 = y0;
    }

    if (g_data[int('t')] == 1 && x2 > x1 + 15) x2 = x1 + 16;
    if (g_data[int('t')] == 1 && y2 > y1 + 15) y2 = y1 + 16;

    if (g_btype != 9)
    {
        if (g_data[int('c')] == 1 || g_shift)
        {
            if (x2 > x1) x2--;
            if (y2 > y1) y2--;
        }
    }

    if (g_data[int('f')] == 1 && g_btype != 9)
    {
        if (g_multic == 1 && g_data[int('d')] == 0)
        {
            g_farge = g_map[1];
            for (int y = y1; y <= y2; y++)
            {
                for (int x = x1; x <= x2; x = x + g_pixelw)
                {
                    if (x >= xf && y >= yf && x <= xt && y <= yt)
                    {
                        makepoint(x, y);
                    }
                }
            }
        }
        g_farge = g_ofarge;
        if (g_button == RIGHT) g_farge = g_backg;
        for (int y = y1; y <= y2; y++)
        {
            for (int x = x1; x <= x2; x = x + g_pixelw)
            {
                makepoint(x, y);
            }
        }
    }
    if (g_data[int('f')] == 0 || g_btype == 9)
    {
        if (g_data[int('c')] == 1 && g_btype == 1)
        {
            if (x2 > x1)
            {
                if (g_bsize == 0) x2--;
                if (g_bsize == 1) x2 = x2 - 2;
                if (g_bsize == 2) x2 = x2 - 3;
                if (g_bsize == 3) x2++;
            }
            if (y2 > y1)
            {
                if (g_bsize == 0) y2--;
                if (g_bsize == 1) y2 = y2 - 2;
                if (g_bsize == 2) y2 = y2 - 3;
                if (g_bsize == 3) y2++;
            }
        }
        do_line(x1, y1, x2, y1, 0);
        do_line(x1, y1, x1, y2, 0);
        do_line(x1, y2, x2, y2, 0);
        do_line(x2, y2, x2, y1, 0);
    }
    g_farge = g_ofarge;
}


void makepoint(int xx, int yy)
{
    //central pixelmaking function
    //has become very messy but what are you gonna do
    int uses[] = new int[8];
    int fars[] = new int[8];
    int mirrix = 0;
    int mirriy = 0;
    int tiler = 0;
    int ignore = 0;
    int fari;

    //for the X/Y mirrors & tiler, the function calls itself with x+10000 or y+10000
    //resolved here
    if (xx >= 20000)
    {
        xx = xx - 20000;
        mirrix = 0;
        mirriy = 0;
        tiler = 1;
    }
    if (xx >= 10000)
    {
        xx = xx - 10000;
        mirrix = 1;
        mirriy = 1;
    }
    if (yy >= 10000)
    {
        yy = yy - 10000;
        mirriy = 1;
        mirrix = 1;
    }

    if (xx < 0 || yy < 0 || xx >= X || yy >= Y) return;

    // adaptive color unless with floodfill (which has its own system)
    if (int(g_map[12]) != 5)
    {
        if (g_multic == 2)
        {
            skaveri(xx, yy, g_farge, 0);
        }
        else
        {
            if (g_data[int('b')] == 0)
            {
                if (g_multic == 1)
                    mkaveri(xx, yy, g_farge, 0);
                else
                    kaveri(xx, yy, g_farge, 0);
            }
            else
            {
                //old iq
                kaveri_iq(xx, yy, g_farge, 0);
            }
        }
    }

    if (g_pixelw == 2)
    {
        xx = chop2(xx);
    }

    if (g_data[int('r')] == 1)
    { //simple raster
        if (get_raster(xx, yy) == 0) ignore = 1;
    }

    if (g_data[int('R')] == 1)
    { //user defined raster
        if (g_bsourcex2 > g_bsourcex && g_bsourcey2 > g_bsourcey)
        {

            int x0 = int(xx / ((g_bsourcex2 + 1) - g_bsourcex));
            int y0 = int(yy / ((g_bsourcey2 + 1) - g_bsourcey));
            int x1 = xx - x0 * ((g_bsourcex2 + 1) - g_bsourcex);
            int y1 = yy - y0 * ((g_bsourcey2 + 1) - g_bsourcey);
            int xr = g_bsourcex + x1;
            int yr = g_bsourcey + y1;
            if (g_pixelw == 2)
            {
                x0 = int(xx / ((g_bsourcex2 + 2) - g_bsourcex));
                y0 = int(yy / ((g_bsourcey2 + 1) - g_bsourcey));
                x1 = xx - x0 * ((g_bsourcex2 + 2) - g_bsourcex);
                x1 = chop2(x1);
                y1 = yy - y0 * ((g_bsourcey2 + 1) - g_bsourcey);
                xr = g_bsourcex + x1;
                xr = chop2(xr);
                yr = g_bsourcey + y1;
                if (getmultic(xr, yr, 1) == g_backg) ignore = 1;
            }
            else
            {
                if (getabsa(xr, yr, 1) == g_backg) ignore = 1;
            }
            //    if(g_brush[1024+xr+yr*X]==0){ignore=1;}
        }
    }

    int xc, yc;

    if (ignore == 0 && g_data[int('d')] == 1 && g_attrimode <= 1)
    {
        int aba, baba, ii, jj, miny, maxy, ojox, ojoy;
        aba = getattra(xx, yy, 0);
        baba = getattra(xx, yy, 1);
        if (g_multic == 0)
        {
            ojox = chop8(xx);
            ojoy = chop8(yy);
            miny = yy - ojoy;
            maxy = miny;

            if (g_attrimode == 1)
            {
                miny = 0;
                maxy = 7;
            }

            if (baba == g_backg) simplepaint(xx, yy, 1, g_farge);
            if (aba == g_backg) simplepaint(xx, yy, 0, g_farge);
            ignore = 1;
            if (g_farge == baba && g_farge == aba)
            {
                for (jj = miny; jj <= maxy; jj++)
                {
                    for (ii = 0; ii < 8; ii++)
                    {
                        g_map[1024 + ojox + ojoy * X + ii + jj * X] = 0;
                    }
                }
            }
        }
        else
        {
            if (aba == g_backg)
            {
                ignore = 0;
            }
            else
            {
                ignore = 1;
            }
        }
        xc = int(xx / 8);
        yc = int(yy / 8);
        g_redo[xc + yc * MX] = byte(0); //block update
        g_remdo[xc + yc * MX] = byte(1); //block update
    }

    if (ignore == 0)
    {
        xc = int(xx / 8);
        yc = int(yy / 8);
        g_redo[xc + yc * MX] = byte(0); //block update
        g_remdo[xc + yc * MX] = byte(1); //block update

        switch (g_multic)
        {
            case 0: //1-bit + attribute i.e. spectrum
                fari = g_farge;
                if (g_machine == MSX && fari == int(g_map[1])) fari = 0;
                if (g_britemode == 1 && fari == 8) fari = 0;

                if (getattra(xx, yy, 1) == 0 && fari == g_map[1])
                {
                    g_map[1024 + xx + yy * X] = byte(0);
                }
                else
                {
                    if (getattra(xx, yy, 1) == fari)
                    {
                        g_map[1024 + xx + yy * X] = byte(0);
                    }
                    else
                    {
                        int ojox = chop8(xx);
                        int ojoy = chop8(yy);
                        int mac, macpre, maxos;
                        int maxoy, miny, maxy;
                        mac = 0;
                        macpre = 0;
                        miny = 0;
                        maxy = 7;
                        maxos = 64;
                        if (g_attrimode == 0)
                        {
                            miny = (yy - ojoy);
                            maxy = miny;
                            maxos = 8;
                        } //MSX
                        for (int j = miny; j <= maxy; j++)
                        {
                            for (int i = 0; i < 8; i++)
                            {
                                if (g_map[1024 + ojox + ojoy * X + j * X] == 1) macpre++;
                            }
                        }
                        g_map[1024 + xx + yy * X] = byte(1);
                        for (int j = miny; j <= maxy; j++)
                        {
                            for (int i = 0; i < 8; i++)
                            {
                                if (g_map[1024 + ojox + ojoy * X + i + j * X] == 1) mac++;
                            }
                        }
                        if (mac == maxos)
                        {
                            for (int j = miny; j <= maxy; j++)
                            {
                                int vad = 1024 + ojox + (ojoy + j) * X;
                                for (int i = 0; i < 8; i++)
                                {
                                    g_map[vad] = 0;
                                    vad++;
                                }
                            }
                            simplepaint(xx, yy, 1, fari);
                        }
                        else
                        {
                            simplepaint(xx, yy, 0, fari);
                        }
                    }
                }
                break;

            case 1: //c64 style zoomed multicolour
                //foreg
                int looks, skippo;
                byte bit1, bit2, valu1, valu2;
                int metax, metay, mex, mey, metamax;
                fari = g_farge;
                int zeroc = int(g_map[1]);
                int zeroc2 = int(g_map[2]);
                boolean cut = false;
                if (fari == zeroc)
                { //shortcut
                    g_map[1024 + xx + yy * X] = byte(0);
                    g_map[1024 + xx + yy * X + 1] = byte(0);
                    cut = true;
                }
                if (g_machine == PLUS4M && fari == zeroc2)
                { //shortcut
                    g_map[1024 + xx + yy * X] = byte(1);
                    g_map[1024 + xx + yy * X + 1] = byte(1);
                    cut = true;
                }
                if (cut)
                {
                    // X Y mirrors
                    if (g_data[int('t')] == 1)
                    {
                        if (tiler == 0)
                        {
                            int ex = int(X / g_gridx);
                            int ey = int(Y / g_gridy);
                            for (int tilx = -ex; tilx <= ex; tilx++)
                            {
                                for (int tily = -ey; tily <= ey; tily++)
                                {
                                    makepoint(20000 + xx + int(X / ex) * tilx, yy + int(Y / ey) * tily);
                                }
                            }
                        }
                        return;
                    }
                    if (g_data[int('X')] == 1 && mirrix == 0) makepoint(10000 + (X - 1) - xx, yy);
                    if (g_data[int('Y')] == 1 && mirriy == 0) makepoint(xx, 10000 + (Y - 1) - yy);
                    if (g_data[int('X')] == 1 && g_data[int('Y')] == 1)
                    {
                        if (mirrix == 0)
                        {
                            makepoint(10000 + (X - 1) - xx, 10000 + (Y - 1) - yy);
                        }
                    }
                    return;
                }

                uses[0] = 0;
                uses[1] = 0;
                uses[2] = 0;
                uses[3] = 0;
                fars[0] = zeroc;
                fars[1] = zeroc;
                fars[2] = zeroc;
                fars[3] = zeroc;
                mex = int(xx / 8);
                mey = int(yy / 8);
                looks = 65536 + mex + mey * MX;
                mex = int(mex * 8);
                mey = int(mey * 8);
                int saps = 1024 + mex + mey * X;

                for (metay = 0; metay <= 7; metay++)
                {
                    for (metax = 0; metax <= 3; metax++)
                    {
                        int pars = g_map[saps] + g_map[saps + 1] * 2;
                        uses[pars] = 1;
                        if (pars == 0) fars[0] = zeroc;
                        if (pars == 1) fars[1] = int(g_map[looks]);
                        if (pars == 2) fars[2] = int(g_map[looks + 1000]);
                        if (pars == 3)
                        {
                            if (g_machine == C64M) fars[3] = int(g_map[looks + 2000]);
                            if (g_machine == PLUS4M) fars[3] = zeroc2;
                        }
                        saps = saps + 2;
                    }
                    saps = saps - 8 + X;
                }

                bit1 = 0;
                bit2 = 0;
                skippo = 0;

                // mega-escape, if it's not possible to draw at all don't bother
                if (uses[0] == 1 && uses[1] == 1 && uses[2] == 1 && uses[3] == 1)
                {
                    if (fari != fars[0] && fari != fars[1] && fari != fars[2] && fari != fars[3]) skippo = 100;
                }

                if (skippo == 0)
                {
                    int okay = 0;
                    metamax = 3;
                    if (g_machine == PLUS4M) metamax = 2;

                    // if the color is already in the 4x8 area?

                    for (metay = 0; metay <= metamax; metay++)
                    {
                        if (uses[metay] == 1)
                        {
                            if (fars[metay] == fari)
                            {
                                if (metay == 1)
                                {
                                    bit1 = 1;
                                    bit2 = 0;
                                    g_map[looks] = byte(fari);
                                }
                                if (metay == 2)
                                {
                                    bit1 = 0;
                                    bit2 = 1;
                                    g_map[looks + 1000] = byte(fari);
                                }
                                if (metay == 3)
                                {
                                    bit1 = 1;
                                    bit2 = 1;
                                    if (g_machine == C64M) g_map[looks + 2000] = byte(fari);
                                    if (g_machine == PLUS4M) g_map[looks + 2000] = byte(zeroc2);
                                }
                                g_map[1024 + xx + yy * X] = bit1;
                                g_map[1024 + xx + yy * X + 1] = bit2;
                                okay = 1;
                            }
                        }
                    }

                    //if the color is not in the 4x8 area

                    if (okay == 0)
                    {
                        for (metay = 1; metay <= metamax; metay++)
                        {
                            if (uses[metay] == 0)
                            {
                                uses[metay] = 1;
                                if (metay == 1)
                                {
                                    bit1 = 1;
                                    bit2 = 0;
                                    g_map[looks] = byte(fari);
                                    uses[2] = 1;
                                }
                                if (metay == 2)
                                {
                                    bit1 = 0;
                                    bit2 = 1;
                                    g_map[looks + 1000] = byte(fari);
                                    uses[3] = 1;
                                }
                                if (metay == 3)
                                {
                                    bit1 = 1;
                                    bit2 = 1;
                                    if (g_machine == C64M) g_map[looks + 2000] = byte(fari);
                                    if (g_machine == PLUS4M) g_map[looks + 2000] = byte(zeroc2);
                                }
                                g_map[1024 + xx + yy * X] = bit1;
                                g_map[1024 + xx + yy * X + 1] = bit2;
                            }
                        }
                    }

                } //skippo0

                break;

            case 2: // VGA style i.e. Amiga, CPC
                fari = g_farge;

                if (g_data[int('d')] == 1)
                {
                    if (g_map[1024 + xx + yy * X] == byte(g_backg))
                    {
                        g_map[1024 + xx + yy * X] = byte(g_farge);
                        if (g_hzoomer == 2) g_map[1024 + xx + yy * X + 1] = byte(g_farge);
                    }
                }
                else
                {
                    g_map[1024 + xx + yy * X] = byte(g_farge);
                    if (g_hzoomer == 2) g_map[1024 + xx + yy * X + 1] = byte(g_farge);
                }
                break;
        }
    }

    // end ignore

    // X Y mirrors & tiler

    if (g_data[int('t')] == 1)
    {
        if (tiler == 0)
        {
            int ex = int(X / g_gridx);
            int ey = int(Y / g_gridy);
            for (int tilx = -(ex); tilx <= ex; tilx++)
            {
                for (int tily = -(ey); tily <= ey; tily++)
                {
                    makepoint(20000 + xx + int(X / ex) * tilx, yy + int(Y / ey) * tily);
                }
            }
        }
        return;
    }
    if (g_data[int('X')] == 1 && mirrix == 0) makepoint(10000 + (X - 1) - xx, yy);
    if (g_data[int('Y')] == 1 && mirriy == 0) makepoint(xx, 10000 + (Y - 1) - yy);
    if (g_data[int('X')] == 1 && g_data[int('Y')] == 1)
    {
        if (mirrix == 0)
        {
            makepoint(10000 + (X - 1) - xx, 10000 + (Y - 1) - yy);
        }
    }
}


void clearpoint(int xx, int yy)
{
    if (g_multic == 1)
        xx = chop2(xx);

    g_farge = g_backg;
    makepoint(xx, yy);
    g_farge = g_ofarge;
}


void absolute_clearpoint(int xx, int yy)
{
    int mirrix = 0;
    int mirriy = 0;
    int ignore = 0;
    if (xx >= 10000)
    {
        xx = xx - 10000;
        mirrix = 1;
        mirriy = 1;
    }
    if (yy >= 10000)
    {
        yy = yy - 10000;
        mirriy = 1;
        mirrix = 1;
    }

    if (xx < 0 || yy < 0 || xx >= X || yy >= Y)
        return;

    if (g_multic == 2 && g_hzoomer != 2)
    {
        g_farge = g_backg;
        makepoint(xx, yy);
        g_farge = g_ofarge;
        return;
    }
    if (g_pixelw == 2)
    {
        xx = chop2(xx);
    }
    if (g_data[int('b')] == 1) return;

    if (g_data[int('r')] == 1)
    { //raster
        if (get_raster(xx, yy) == 0) ignore = 1;
    }

    if (g_data[int('R')] == 1)
    { //user defined raster
        if (g_bsourcex2 > g_bsourcex && g_bsourcey2 > g_bsourcey)
        {
            int x0 = int(xx / ((g_bsourcex2 + 1) - g_bsourcex));
            int y0 = int(yy / ((g_bsourcey2 + 1) - g_bsourcey));
            int x1 = xx - x0 * ((g_bsourcex2 + 1) - g_bsourcex);
            int y1 = yy - y0 * ((g_bsourcey2 + 1) - g_bsourcey);
            int xr = g_bsourcex + x1;
            int yr = g_bsourcey + y1;
            if (g_brush[1024 + xr + yr * X] == 0) ignore = 1;
        }
    }

    if (ignore == 0)
    {
        g_map[1024 + xx + yy * X] = byte(0);
        if (g_pixelw == 2) g_map[1024 + xx + yy * X + 1] = byte(0);
        int xc = int(xx / 8);
        int yc = int(yy / 8);
        g_redo[xc + yc * MX] = byte(0); //block update
        g_remdo[xc + yc * MX] = byte(1); //block update
    }

    if (g_data[int('X')] == 1 && mirrix == 0) clearpoint(10000 + (X - 1) - xx, yy);
    if (g_data[int('Y')] == 1 && mirriy == 0) clearpoint(xx, 10000 + (Y - 1) - yy);
    if (g_data[int('X')] == 1 && g_data[int('Y')] == 1)
    {
        if (mirrix == 0) clearpoint(10000 + (X - 1) - xx, 10000 + (Y - 1) - yy);
    }
}


void simplepaint(int xx, int yy, int mode, int attr)
{
    int ojyx = chop8(yy),
        miny = yy - ojyx,
        maxy = miny;

    xx = int(xx / 8);

    if (g_attrimode == 1)
    {
        miny = 0;
        maxy = 7;
    }

    for (int j = miny; j <= maxy; j++)
    {
        int ad, swad;
        if (mode == 0)
        {
            ad = 65536 + xx + (ojyx + j) * MX;
            swad = 65536 + xx + (ojyx + j) * MX + (MX * MY) * 8;
        }
        if (mode == 1)
        {
            swad = 65536 + xx + (ojyx + j) * MX;
            ad = 65536 + xx + (ojyx + j) * MX + (MX * MY) * 8;
        }
        if (g_britemode == 1)
        {
            if (attr == 8) attr = 0;
            if (attr > 0)
            {
                if (attr >= 8 && g_map[swad] <= 7) g_map[swad] = byte(g_map[swad] + 8);
                if (attr <= 7 && g_map[swad] >= 8) g_map[swad] = byte(g_map[swad] - 8);
            }
        }
        g_map[ad] = byte(attr);
    }
}


void storecoords(int qqx, int qqy)
{
    int psizex = g_magpix[magmode()],
        psizey = g_magpiy[magmode()];

    if (g_data[int('m')] == 0 && g_data[int('M')] == 0)
    {
        g_storedcoordx = int(qqx / psizex);
        g_storedcoordy = int(qqy / psizey);
    }
    else
    if (g_data[int('m')] == 1 || g_data[int('M')] == 1)
    {
        g_storedcoordx = int(qqx / psizex) + g_ofx * 8;
        g_storedcoordy = int(qqy / psizey) + g_ofy * 8;
    }
    else
    {
        g_storedcoordx = int(qqx);
        g_storedcoordy = int(qqy);
    }
}


void do_tool(int qqx, int qqy, int mbut)
{
    storecoords(qqx, qqy);

    int tt = tool(),
        ox = g_storedcoordx,
        oy = g_storedcoordy,
        x = g_storedcoordx,
        y = g_storedcoordy;

    if (g_btype == 9 && tt != 4 && tt != 0 && mbut != 255)
    {
        x -= int((g_bsourcex2 - g_bsourcex) / 2);
        y -= int((g_bsourcey2 - g_bsourcey) / 2);
    }

    if (g_data[int('c')] == 1 || g_shift)
    {
        x = chopv(x, g_gridx);
        y = chopv(y, g_gridy);
    }

    if (g_pixelw == 2)
    {
        x = chop2(x);
        ox = chop2(ox);
    }

    if (mbut == 254)
    {
        //block picker
        switcher(2);
        g_data[int('n')] = 0;
        g_data[int('x')] = 0;
        g_data[int('y')] = 0;
        g_data[int('q')] = 0;
        g_data[int('z')] = 0;

        x = chopv(ox, g_gridx);
        y = chopv(oy, g_gridy);

        g_bsourcex = x;
        g_bsourcey = y;
        g_bsourcex2 = x + g_gridx - 1;
        g_bsourcey2 = y + g_gridy - 1;

        g_btype = 9;
        return;
    }
    else
    if (mbut == 255)
    { // color picker
        if (g_multic == 2)
        {
            if (g_hzoomer == 2)
            {
                ox = chop2(ox);
            }
            selectcolor(0, getmultic(ox, oy, 0));
            return;
        }
        selectcolor(0, getabsa(ox, oy, 0));
        if (g_pixelw == 2)
        {
            ox = chop2(ox);
            selectcolor(0, getattra(ox, oy, 0));
        }
        g_ofarge = g_farge;
        if (g_btype == 9) g_data[int('p')] = 1;
        g_realfront = byte(g_farge);
        return;
    }

    if (x >= 0 && y >= 0 && x < X && y < Y && g_mx < width - g_hedge && g_my < height - g_vedge)
        help(1000, x, y);

    if (g_phase > 0)
        help(1000, x, y);

    if (tt == 1)
    {
        craft(x, y, 0); //pixeller
    }
    else
    if (tt == 2)
    {
        //spraycan
        //if(random(100)<50){fixed_raster_command(int('x'));}
        //if(random(100)<50){fixed_raster_command(int('y'));}
        for (int i = 0; i <= 12; i++)
        {
            int rx = x - 10 + int(random((10) * 2));
            int ry = y - 10 + int(random((10) * 2));
            if (mbut == LEFT)
            {
                if (dist(x, y, rx, ry) < 10) craft(rx, ry, 0);
            }
            else
            {
                if (dist(x, y, rx, ry) < 10) craft(rx, ry, 0);
            }
        }
    }
    else
    if (tt == 3)
    {
        //cont line
        if (g_phase == 0)
        {
            g_prex = x;
            g_prey = y;
            craft(x, y, 0);
        }
        do_line(x, y, g_prex, g_prey, 0);
        g_prex = x;
        g_prey = y;
    }
    else
    if (tt == 5)
    {
        //floodfill
        if (!g_klikkeri)
        {
            g_klikkeri = true;

            storeparameters();
            g_data[int('X')] = 0;
            g_data[int('Y')] = 0;
            g_data[int('c')] = 0;
            g_data[int('t')] = 0;

            if (ox >= 0 && ox < X && oy >= 0 & oy < Y)
            {
                store_undo(); // exceptional!
                if (g_multic)
                    floodfill_mc(ox, oy, mbut);
                else
                    floodfill_iq(ox, oy, mbut);
            }
            else
                changeborder(mbut);

            restoreparameters();
        }
    }
    else
    if (tt == 6 || tt == 7 || tt == 8)
    {
        //line,circle,rect
        if (g_phase == 0)
        {
            g_rx = g_rx2 = x;
            g_ry = g_ry2 = y;
            g_rubbermode = 0;
        }
        else
        if (g_phase == 1)
        {
            g_rx2 = x;
            g_ry2 = y;
        }
    }
    else
    if (tt == 0)
    {
        // magnifier graphic tool
        g_data[int('m')] = 1;
        g_orx = x;
        g_ory = y;
        g_rx  = x - int(magx() / 2) * 8;
        g_ry  = y - int(magy() / 2) * 8;
        g_rx2 = x + (int(magx() / 2) + odd(magx())) * 8;
        g_ry2 = y + (int(magy() / 2) + odd(magy())) * 8;
        g_data[int('m')] = 0;

        if (g_phase == 1)
        {
            g_rubbermode = 0;
            g_data[int('m')] = 1;
            set_tool(g_prevtool);
            g_phase = 0;

            g_ofx = int(x / 8) - int(magx() / 2);
            g_ofy = int(y / 8) - int(magy() / 2);
            refresh();
            g_repanel = -2;
        }
        else
            g_rubbermode = 1;
    }
    else
    if (tt == 4)
    {
        //brush grabber grab brush
        if (g_phase == 0)
        {
            g_rx = x;
            g_orx = x;
            g_ry = y;
            g_ory = y;
            g_rx2 = x;
            g_ry2 = y;
        }
        else
        if (g_phase == 1)
        {
            g_rx2 = x;
            g_rx = g_orx;
            g_ry2 = y;
            g_ry = g_ory;
            if (x < g_orx)
            {
                g_rx2 = g_orx;
                g_rx = x;
            }
            if (y < g_ory)
            {
                g_ry2 = g_ory;
                g_ry = y;
            }
            if (g_data[int('c')] == 1 || g_shift)
            {
                g_rx2--;
                g_ry2--;
                if (g_pixelw == 2) g_rx2--;
            }
        }
        g_rubbermode = 1;
    }

    if (tt == 0 || tt == 4)
    {
        if (g_rubbermode == 1)
        {
            for (int xx = g_rx; xx <= g_rx2 + 2; xx++)
            {
                updatepoint(xx, g_ry);
                updatepoint(xx, g_ry2);
            }
            for (int yy = g_ry; yy <= g_ry2; yy++)
            {
                updatepoint(g_rx, yy);
                updatepoint(g_rx2, yy);
            }
        }
    }
}