#include "compiler.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "gdc_sub.h"
#include "lio.h"
typedef struct {
UINT8 x1[2];
UINT8 y1[2];
UINT8 x2[2];
UINT8 y2[2];
UINT8 pal;
UINT8 type;
UINT8 sw;
UINT8 style[2];
UINT8 patleng;
UINT8 off[2];
UINT8 seg[2];
} GLINE;
typedef struct {
int x1;
int y1;
int x2;
int y2;
UINT8 pal;
} LINEPT;
static void gline(const _GLIO *lio, const LINEPT *lp, UINT16 pat) {
int x1;
int y1;
int x2;
int y2;
int swap;
int tmp;
int width;
int height;
int d1;
int d2;
UINT32 csrw;
GDCVECT vect;
x1 = lp->x1;
y1 = lp->y1;
x2 = lp->x2;
y2 = lp->y2;
// びゅーぽいんと
swap = 0;
if (x1 > x2) {
tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
swap = 1;
}
if ((x1 > lio->draw.x2) || (x2 < lio->draw.x1)) {
return;
}
width = x2 - x1;
height = y2 - y1;
d1 = lio->draw.x1 - x1;
d2 = x2 - lio->draw.x2;
if (d1 > 0) {
x1 = lio->draw.x1;
y1 += (((height * d1 * 2) / width) + 1) >> 1;
}
if (d2 > 0) {
x2 = lio->draw.x2;
y2 -= (((height * d2 * 2) / width) + 1) >> 1;
}
if (swap) {
tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
swap = 0;
if (y1 > y2) {
tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
if ((y1 > lio->draw.y2) || (y2 < lio->draw.y1)) {
return;
}
width = x2 - x1;
height = y2 - y1;
d1 = lio->draw.y1 - y1;
d2 = y2 - lio->draw.y2;
if (d1 > 0) {
y1 = lio->draw.y1;
x1 += (((width * d1 * 2) / height) + 1) >> 1;
}
if (d2 > 0) {
y2 = lio->draw.y2;
x2 -= (((width * d2 * 2) / height) + 1) >> 1;
}
if (swap) {
tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
// 進んだ距離計算
d1 = x1 - lp->x1;
if (d1 < 0) {
d1 = 0 - d1;
}
d2 = y1 - lp->y1;
if (d2 < 0) {
d2 = 0 - d2;
}
d1 = max(d1, d2) & 15;
pat = (UINT16)((pat >> d1) | (pat << (16 - d1)));
csrw = (y1 * 40) + (x1 >> 4) + ((x1 & 0xf) << 20);
if (lio->draw.flag & LIODRAW_UPPER) {
csrw += 16000 >> 1;
}
gdcsub_setvectl(&vect, x1, y1, x2, y2);
if (!(lio->draw.flag & LIODRAW_MONO)) {
gdcsub_vectl(csrw + 0x4000, &vect, pat,
(REG8)((lp->pal & 1)?GDCOPE_SET:GDCOPE_CLEAR));
gdcsub_vectl(csrw + 0x8000, &vect, pat,
(REG8)((lp->pal & 2)?GDCOPE_SET:GDCOPE_CLEAR));
gdcsub_vectl(csrw + 0xc000, &vect, pat,
(REG8)((lp->pal & 4)?GDCOPE_SET:GDCOPE_CLEAR));
if (lio->draw.flag & LIODRAW_4BPP) {
gdcsub_vectl(csrw, &vect, pat,
(REG8)((lp->pal & 8)?GDCOPE_SET:GDCOPE_CLEAR));
}
}
else {
csrw += ((lio->draw.flag + 1) & LIODRAW_PMASK) << 12;
gdcsub_vectl(csrw, &vect, pat,
(REG8)((lp->pal)?GDCOPE_SET:GDCOPE_CLEAR));
}
}
static void glineb(const _GLIO *lio, const LINEPT *lp, UINT16 pat) {
LINEPT lpt;
lpt = *lp;
lpt.y2 = lp->y1;
gline(lio, &lpt, pat);
lpt.y2 = lp->y2;
lpt.x2 = lp->x1;
gline(lio, &lpt, pat);
lpt.x2 = lp->x2;
lpt.x1 = lp->x2;
gline(lio, &lpt, pat);
lpt.x1 = lp->x1;
lpt.y1 = lp->y2;
gline(lio, &lpt, pat);
lpt.y1 = lp->y1;
}
// ----
static void gbox(const _GLIO *lio, const LINEPT *lp, UINT8 *tile, UINT leng) {
int x1;
int y1;
int x2;
int y2;
int tmp;
UINT32 csrw;
GDCVECT vect;
UINT planes;
UINT adrs[4];
UINT8 ope[4];
UINT16 pat;
UINT8 *tterm;
UINT r;
x1 = lp->x1;
y1 = lp->y1;
x2 = lp->x2;
y2 = lp->y2;
if (x1 > x2) {
tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 > y2) {
tmp = y1;
y1 = y2;
y2 = tmp;
}
if ((x1 > lio->draw.x2) || (x2 < lio->draw.x1) ||
(y1 > lio->draw.y2) || (y2 < lio->draw.y1)) {
return;
}
x1 = max(x1, lio->draw.x1);
y1 = max(y1, lio->draw.y1);
x2 = min(x2, lio->draw.x2);
y2 = min(y2, lio->draw.y2);
csrw = 0;
if (lio->draw.flag & LIODRAW_UPPER) {
csrw += 16000 >> 1;
}
if (!(lio->draw.flag & LIODRAW_MONO)) {
planes = (lio->draw.flag & LIODRAW_4BPP)?4:3;
adrs[0] = csrw + 0x4000;
adrs[1] = csrw + 0x8000;
adrs[2] = csrw + 0xc000;
adrs[3] = csrw + 0x0000;
ope[0] = (lp->pal & 1)?GDCOPE_SET:GDCOPE_CLEAR;
ope[1] = (lp->pal & 2)?GDCOPE_SET:GDCOPE_CLEAR;
ope[2] = (lp->pal & 4)?GDCOPE_SET:GDCOPE_CLEAR;
ope[3] = (lp->pal & 8)?GDCOPE_SET:GDCOPE_CLEAR;
}
else {
planes = 1;
adrs[0] = csrw + (((lio->draw.flag + 1) & LIODRAW_PMASK) << 12);
ope[0] = (lp->pal)?GDCOPE_SET:GDCOPE_CLEAR;
}
if (leng == 0) {
tile = NULL;
tterm = NULL;
}
else {
tterm = tile + leng;
tmp = (x1 - lio->draw.x1) & 7;
do {
r = GDCPATREVERSE(*tile);
*tile = (UINT8)((r << tmp) | (r >> (8 - tmp)));
} while(++tile < tterm);
tile -= leng;
tmp = (y1 - lio->draw.y1) * planes;
tile += tmp % leng;
}
pat = 0xffff;
while(y1 <= y2) {
gdcsub_setvectl(&vect, x1, y1, x2, y1);
csrw = (y1 * 40) + (x1 >> 4) + ((x1 & 0xf) << 20);
r = 0;
do {
if (tile) {
pat = (*tile << 8) | *tile;
if (++tile >= tterm) {
tile -= leng;
}
}
gdcsub_vectl(csrw + adrs[r], &vect, pat, ope[r]);
} while(++r < planes);
y1++;
}
}
// ---- CLS
REG8 lio_gcls(GLIO lio) {
LINEPT lp;
lio_updatedraw(lio);
lp.x1 = lio->draw.x1;
lp.y1 = lio->draw.y1;
lp.x2 = lio->draw.x2;
lp.y2 = lio->draw.y2;
lp.pal = lio->work.bgcolor;
gbox(lio, &lp, NULL, 0);
return(LIO_SUCCESS);
}
// ----
REG8 lio_gline(GLIO lio) {
GLINE dat;
LINEPT lp;
UINT16 pat;
UINT leng;
// UINT lengmin;
UINT8 tile[256];
lio_updatedraw(lio);
MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat));
lp.x1 = (SINT16)LOADINTELWORD(dat.x1);
lp.y1 = (SINT16)LOADINTELWORD(dat.y1);
lp.x2 = (SINT16)LOADINTELWORD(dat.x2);
lp.y2 = (SINT16)LOADINTELWORD(dat.y2);
TRACEOUT(("lio_gline %d,%d-%d,%d [%d]", lp.x1, lp.y1, lp.x2, lp.y2, dat.type));
if (dat.pal == 0xff) {
dat.pal = lio->work.fgcolor;
}
if (dat.pal >= lio->draw.palmax) {
goto gline_err;
}
pat = 0xffff;
if (dat.type < 2) {
if (dat.sw) {
pat = (GDCPATREVERSE(dat.style[0]) << 8) +
GDCPATREVERSE(dat.style[1]);
}
lp.pal = dat.pal;
if (dat.type == 0) {
gline(lio, &lp, pat);
}
else {
glineb(lio, &lp, pat);
}
}
else if (dat.type == 2) {
leng = 0;
if (dat.sw == 2) {
leng = dat.patleng;
if (leng == 0) {
goto gline_err;
}
MEMR_READS(LOADINTELWORD(dat.seg), LOADINTELWORD(dat.off),
tile, leng);
}
if (dat.sw != 1) {
lp.pal = dat.pal;
gbox(lio, &lp, tile, leng);
}
else {
lp.pal = dat.style[0];
gbox(lio, &lp, tile, leng);
lp.pal = dat.pal;
glineb(lio, &lp, 0xffff);
}
}
else {
goto gline_err;
}
return(LIO_SUCCESS);
gline_err:
return(LIO_ILLEGALFUNC);
}
RetroPC.NET-CVS <cvs@retropc.net>