X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fpolyfill.c;fp=src%2Fpolyfill.c;h=25954297d33ec742eb8440adfd228b1399603fe2;hb=5b98299a1aa716cc17cb5f70498c8e23cac945cb;hp=0000000000000000000000000000000000000000;hpb=ca3123df6cd875b1361533020c1f4eebfe9da295;p=gba_blender diff --git a/src/polyfill.c b/src/polyfill.c new file mode 100644 index 0000000..2595429 --- /dev/null +++ b/src/polyfill.c @@ -0,0 +1,99 @@ +/* +blender for the Gameboy Advance +Copyright (C) 2021 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include "polyfill.h" +#include "debug.h" + +static unsigned char *fb; +static int fbwidth, fbheight; +static short scantab[2][160] __attribute__((section(".iwram"))); + +void polyfill_framebuffer(unsigned char *ptr, int w, int h) +{ + fb = ptr; + fbwidth = w; + fbheight = h; +} + +#define VNEXT(p) (((p) == vlast) ? varr : (p) + 1) +#define VPREV(p) ((p) == varr ? vlast : (p) - 1) +#define VSUCC(p, side) ((side) == 0 ? VNEXT(p) : VPREV(p)) + +void polyfill_flat(struct pvertex *varr, int vnum, unsigned char col) +{ + int i, line, top, bot; + struct pvertex *vlast, *v, *vn; + int32_t x, y0, y1, dx, dy, slope, fx, fy; + short *tab, start, len; + unsigned char *fbptr; + + vlast = varr + vnum - 1; + top = fbheight; + bot = 0; + + for(i=0; iy == v->y) continue; + + if(vn->y > v->y) { + tab = scantab[0]; + } else { + tab = scantab[1]; + v = vn; + vn = varr + i; + } + + dx = vn->x - v->x; + dy = vn->y - v->y; + slope = (dx << 8) / dy; + + y0 = (v->y + 0x100) & 0xffffff00; /* start from the next scanline */ + fy = y0 - v->y; /* fractional part before the next scanline */ + fx = (fy * slope) >> 8; /* X adjust for the step to the next scanline */ + x = v->x + fx; /* adjust X */ + y1 = vn->y & 0xffffff00; /* last scanline of the edge <= vn->y */ + + line = y0 >> 8; + if(line < top) top = line; + if((y1 >> 8) > bot) bot = y1 >> 8; + + if(line > 0) tab += line; + + while(line < (y1 >> 8) && line < fbheight) { + if(line >= 0) { + int val = x < 0 ? 0 : x >> 8; + *tab++ = val < fbwidth ? val : fbwidth - 1; + } + x += slope; + line++; + } + } + + fbptr = fb + top * fbwidth; + for(i=top; i 0) { + memset(fbptr + start, col, len); + } + fbptr += fbwidth; + } +}