#include "compiler.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "bios.h"
#include "lio.h"
#include "vram.h"
typedef struct {
UINT8 x1[2];
UINT8 y1[2];
UINT8 x2[2];
UINT8 y2[2];
UINT8 off[2];
UINT8 seg[2];
UINT8 leng[2];
} GGET;
typedef struct {
UINT8 x[2];
UINT8 y[2];
UINT8 off[2];
UINT8 seg[2];
UINT8 leng[2];
UINT8 mode;
UINT8 colorsw;
UINT8 fg;
UINT8 bg;
} GPUT1;
typedef struct {
UINT8 x[2];
UINT8 y[2];
UINT8 chr[2];
UINT8 mode;
UINT8 colorsw;
UINT8 fg;
UINT8 bg;
} GPUT2;
typedef struct {
SINT16 x;
SINT16 y;
UINT16 width;
UINT16 height;
UINT16 off;
UINT16 seg;
UINT8 mode;
UINT8 sw;
UINT8 fg;
UINT8 bg;
} LIOPUT;
typedef struct {
UINT8 *baseptr;
UINT addr;
UINT sft;
UINT width;
UINT8 mask;
} GETCNTX;
typedef struct {
UINT8 *baseptr;
UINT addr;
UINT sft;
UINT width;
UINT8 maskl;
UINT8 maskr;
UINT8 masklr;
UINT8 mask;
UINT8 pat[84];
} PUTCNTX;
static void getvram(const GETCNTX *gt, UINT8 *dst) {
UINT8 *baseptr;
UINT addr;
UINT width;
UINT dat;
UINT sft;
baseptr = gt->baseptr;
addr = gt->addr;
width = gt->width;
sft = 8 - gt->sft;
dat = baseptr[LOW15(addr)];
addr++;
while(width > 8) {
width -= 8;
dat = (dat << 8) + baseptr[LOW15(addr)];
addr++;
*dst = (UINT8)(dat >> sft);
dst++;
}
dat = (dat << 8) + baseptr[LOW15(addr)];
*dst = (UINT8)((dat >> sft) & gt->mask);
}
static void setdirty(UINT addr, UINT width, UINT height, REG8 bit) {
UINT r;
gdcs.grphdisp |= bit;
width = (width + 7) >> 3;
while(height--) {
r = 0;
while(r < width) {
vramupdate[LOW15(addr + r)] |= bit;
r++;
}
addr += 80;
}
}
static void putor(const PUTCNTX *pt) {
UINT8 *baseptr;
UINT addr;
const UINT8 *src;
UINT width;
UINT dat;
baseptr = pt->baseptr;
addr = pt->addr;
src = pt->pat;
width = pt->width;
dat = *src++;
if ((pt->sft + width) < 8) {
baseptr[LOW15(addr)] |= (UINT8)((dat >> pt->sft) & pt->masklr);
}
else {
baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft) & pt->maskl;
addr++;
width -= (8 - pt->sft);
while(width > 8) {
width -= 8;
dat = (dat << 8) + (*src);
src++;
baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft);
addr++;
}
if (width) {
dat = (dat << 8) + (*src);
baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft) & pt->maskr;
}
}
}
static void putorn(const PUTCNTX *pt) {
UINT8 *baseptr;
UINT addr;
const UINT8 *src;
UINT width;
UINT dat;
baseptr = pt->baseptr;
addr = pt->addr;
src = pt->pat;
width = pt->width;
dat = *src++;
if ((pt->sft + width) < 8) {
baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->masklr);
}
else {
baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->maskl);
addr++;
width -= (8 - pt->sft);
while(width > 8) {
width -= 8;
dat = (dat << 8) + (*src);
src++;
baseptr[LOW15(addr)] |= (UINT8)((~dat) >> pt->sft);
addr++;
}
if (width) {
dat = (dat << 8) + (*src);
baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->maskr);
}
}
}
static void putand(const PUTCNTX *pt) {
UINT8 *baseptr;
UINT addr;
const UINT8 *src;
UINT width;
UINT dat;
baseptr = pt->baseptr;
addr = pt->addr;
src = pt->pat;
width = pt->width;
dat = *src++;
if ((pt->sft + width) < 8) {
baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->masklr));
}
else {
baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->maskl));
addr++;
width -= (8 - pt->sft);
while(width > 8) {
width -= 8;
dat = (dat << 8) + (*src);
src++;
baseptr[LOW15(addr)] &= (UINT8)(dat >> pt->sft);
addr++;
}
if (width) {
dat = (dat << 8) + (*src);
baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->maskr));
}
}
}
static void putandn(const PUTCNTX *pt) {
UINT8 *baseptr;
UINT addr;
const UINT8 *src;
UINT width;
UINT dat;
baseptr = pt->baseptr;
addr = pt->addr;
src = pt->pat;
width = pt->width;
dat = *src++;
if ((pt->sft + width) < 8) {
baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->masklr));
}
else {
baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->maskl));
addr++;
width -= (8 - pt->sft);
while(width > 8) {
width -= 8;
dat = (dat << 8) + (*src);
src++;
baseptr[LOW15(addr)] &= (UINT8)((~dat) >> pt->sft);
addr++;
}
if (width) {
dat = (dat << 8) + (*src);
baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->maskr));
}
}
}
static void putxor(const PUTCNTX *pt) {
UINT8 *baseptr;
UINT addr;
const UINT8 *src;
UINT width;
UINT dat;
baseptr = pt->baseptr;
addr = pt->addr;
src = pt->pat;
width = pt->width;
dat = *src++;
if ((pt->sft + width) < 8) {
baseptr[LOW15(addr)] ^= (UINT8)((dat >> pt->sft) & pt->masklr);
}
else {
baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft) & pt->maskl;
addr++;
width -= (8 - pt->sft);
while(width > 8) {
width -= 8;
dat = (dat << 8) + (*src);
src++;
baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft);
addr++;
}
if (width) {
dat = (dat << 8) + (*src);
baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft) & pt->maskr;
}
}
}
static void putxorn(const PUTCNTX *pt) {
UINT8 *baseptr;
UINT addr;
const UINT8 *src;
UINT width;
UINT dat;
baseptr = pt->baseptr;
addr = pt->addr;
src = pt->pat;
width = pt->width;
dat = *src++;
if ((pt->sft + width) < 8) {
baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->masklr);
}
else {
baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->maskl);
addr++;
width -= (8 - pt->sft);
while(width > 8) {
width -= 8;
dat = (dat << 8) + (*src);
src++;
baseptr[LOW15(addr)] ^= (UINT8)((~dat) >> pt->sft);
addr++;
}
if (width) {
dat = (dat << 8) + (*src);
baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->maskr);
}
}
}
// ----
static REG8 putsub(GLIO lio, const LIOPUT *lput) {
UINT addr;
PUTCNTX pt;
UINT datacnt;
UINT off;
UINT height;
UINT flag;
UINT pl;
UINT writecnt;
if ((lput->x < lio->draw.x1) ||
(lput->y < lio->draw.y1) ||
((lput->x + lput->width - 1) > lio->draw.x2) ||
((lput->y + lput->height - 1) > lio->draw.y2)) {
return(LIO_ILLEGALFUNC);
}
if ((lput->width <= 0) || (lput->height <= 0)) {
return(LIO_SUCCESS);
}
addr = (lput->x >> 3) + (lput->y * 80);
if (lio->draw.flag & LIODRAW_UPPER) {
addr += 16000;
}
setdirty(addr, (lput->x & 7) + lput->width, lput->height, lio->draw.sbit);
pt.addr = addr;
pt.sft = lput->x & 7;
pt.width = lput->width;
pt.maskl = (UINT8)(0xff >> pt.sft);
pt.maskr = (UINT8)((~0x7f) >> ((pt.width + pt.sft - 1) & 7));
pt.masklr = (UINT8)(pt.maskl >> pt.sft);
datacnt = (lput->width + 7) >> 3;
off = lput->off;
flag = (lio->draw.flag & LIODRAW_4BPP)?0x0f:0x07;
flag |= (lput->fg & 15) << 4;
flag |= (lput->bg & 15) << 8;
// さて表示。
writecnt = 0;
height = lput->height;
do {
flag <<= 4;
for (pl=0; pl<4; pl++) {
flag >>= 1;
if (flag & 8) {
pt.baseptr = mem + lio->draw.base + lioplaneadrs[pl];
MEMR_READS(lput->seg, off, pt.pat, datacnt);
if (lput->sw) {
off += datacnt;
}
switch(lput->mode) {
case 0: // PSET
if (flag & (8 << 4)) {
putor(&pt);
}
else {
putandn(&pt);
}
if (flag & (8 << 8)) {
putorn(&pt);
}
else {
putand(&pt);
}
writecnt += 2;
break;
case 1: // NOT
if (!(flag & (8 << 4))) {
putor(&pt);
}
else {
putandn(&pt);
}
if (!(flag & (8 << 8))) {
putorn(&pt);
}
else {
putand(&pt);
}
writecnt += 2;
break;
case 2: // OR
if (flag & (8 << 4)) {
putor(&pt);
writecnt++;
}
if (flag & (8 << 8)) {
putorn(&pt);
writecnt++;
}
break;
case 3: // AND
if (!(flag & (8 << 4))) {
putandn(&pt);
writecnt++;
}
if (!(flag & (8 << 8))) {
putand(&pt);
writecnt++;
}
break;
case 4: // XOR
if (flag & (8 << 4)) {
putxor(&pt);
writecnt++;
}
if (flag & (8 << 8)) {
putxorn(&pt);
writecnt++;
}
break;
}
}
}
pt.addr += 80;
if (!lput->sw) {
off += datacnt;
}
} while(--height);
lio->wait += writecnt * datacnt * (10 + 10 + 10);
return(LIO_SUCCESS);
}
// ---- GGET
REG8 lio_gget(GLIO lio) {
GGET dat;
SINT32 x;
SINT32 y;
int x2;
int y2;
UINT off;
UINT seg;
UINT32 leng;
UINT32 size;
UINT datacnt;
UINT mask;
GETCNTX gt;
UINT8 pat[84];
UINT pl;
lio_updatedraw(lio);
MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat));
x = (SINT16)LOADINTELWORD(dat.x1);
y = (SINT16)LOADINTELWORD(dat.y1);
x2 = (SINT16)LOADINTELWORD(dat.x2);
y2 = (SINT16)LOADINTELWORD(dat.y2);
if ((x < lio->draw.x1) || (y < lio->draw.y1) ||
(x2 > lio->draw.x2) || (y2 > lio->draw.y2)) {
return(LIO_ILLEGALFUNC);
}
x2 = x2 - x + 1;
y2 = y2 - y + 1;
if ((x2 <= 0) || (y2 <= 0)) {
return(LIO_ILLEGALFUNC);
}
off = LOADINTELWORD(dat.off);
seg = (SINT16)LOADINTELWORD(dat.seg);
datacnt = (x2 + 7) >> 3;
size = datacnt * y2;
leng = LOADINTELWORD(dat.leng);
if (!(lio->draw.flag & LIODRAW_MONO)) {
if (lio->draw.flag & LIODRAW_4BPP) {
size *= 4;
mask = 0x0f;
}
else {
size *= 3;
mask = 0x07;
}
}
else {
mask = 1 << (lio->draw.flag & LIODRAW_PMASK);
}
if (leng < (size + 4)) {
return(LIO_ILLEGALFUNC);
}
MEMR_WRITE16(seg, off, (REG16)x2);
MEMR_WRITE16(seg, off+2, (REG16)y2);
off += 4;
gt.addr = (x >> 3) + (y * 80);
if (lio->draw.flag & LIODRAW_UPPER) {
gt.addr += 16000;
}
gt.sft = x & 7;
gt.width = x2;
gt.mask = (UINT8)((~0x7f) >> ((x2 - 1) & 7));
do {
mask <<= 4;
for (pl=0; pl<4; pl++) {
mask >>= 1;
if (mask & 8) {
gt.baseptr = mem + lio->draw.base + lioplaneadrs[pl];
getvram(>, pat);
MEMR_WRITES(seg, off, pat, datacnt);
off += datacnt;
}
}
gt.addr += 80;
} while(--y2);
lio->wait = size * 12;
return(LIO_SUCCESS);
}
// ---- GPUT1
REG8 lio_gput1(GLIO lio) {
GPUT1 dat;
LIOPUT lput;
UINT leng;
UINT size;
lio_updatedraw(lio);
MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat));
lput.x = (SINT16)LOADINTELWORD(dat.x);
lput.y = (SINT16)LOADINTELWORD(dat.y);
lput.off = (UINT16)(LOADINTELWORD(dat.off) + 4);
lput.seg = LOADINTELWORD(dat.seg);
lput.mode = dat.mode;
leng = LOADINTELWORD(dat.leng);
lput.width = MEMR_READ16(lput.seg, lput.off - 4);
lput.height = MEMR_READ16(lput.seg, lput.off - 2);
size = ((lput.width + 7) >> 3) * lput.height;
if (leng < (size + 4)) {
return(LIO_ILLEGALFUNC);
}
if (leng < ((size * 3) + 4)) {
lput.sw = 0;
if (dat.colorsw) {
lput.fg = dat.fg;
lput.bg = dat.bg;
}
else {
lput.fg = lio->work.fgcolor;
lput.bg = lio->work.bgcolor;
}
}
else {
if (dat.colorsw) {
lput.sw = 0;
lput.fg = dat.fg;
lput.bg = dat.bg;
}
else {
lput.sw = 1;
lput.fg = 0x0f;
lput.bg = 0;
}
}
return(putsub(lio, &lput));
}
// ---- GPUT2
REG8 lio_gput2(GLIO lio) {
GPUT2 dat;
LIOPUT lput;
UINT16 jis;
int pat;
REG16 size;
lio_updatedraw(lio);
MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat));
lput.x = (SINT16)LOADINTELWORD(dat.x);
lput.y = (SINT16)LOADINTELWORD(dat.y);
lput.off = 0x104e;
lput.seg = CPU_DS;
jis = LOADINTELWORD(dat.chr);
pat = 0;
if (jis < 0x200) {
if (jis < 0x80) {
if (jis == 0x7c) {
pat = 1;
}
else if (jis == 0x7e) {
pat = 2;
}
else {
jis += 0x2900;
}
}
else if (jis < 0x100) {
if ((jis - 0x20) & 0x40) {
pat = (jis & 0x3f) + 3;
}
else {
jis += 0x2980;
}
}
else {
jis &= 0xff;
}
}
if (!pat) {
size = bios0x18_14(lput.seg, 0x104c, jis);
}
else {
MEMR_WRITES(lput.seg, lput.off, mem + (LIO_SEGMENT << 4) +
LIO_FONT + ((pat - 1) << 4), 0x10);
size = 0x0102;
}
lput.width = (size & 0xff00) >> (8 - 3);
lput.height = (size & 0xff) << 3;
lput.mode = dat.mode;
lput.sw = 0;
if (dat.colorsw) {
lput.fg = dat.fg;
lput.bg = dat.bg;
}
else {
lput.fg = lio->work.fgcolor;
lput.bg = lio->work.bgcolor;
}
return(putsub(lio, &lput));
}
RetroPC.NET-CVS <cvs@retropc.net>