mirror of
https://git.checksum.fail/alec/neinterm.git
synced 2025-12-10 13:09:54 +02:00
503 lines
12 KiB
HolyC
503 lines
12 KiB
HolyC
class @Rect
|
|
{
|
|
U32 x0;
|
|
U32 y0;
|
|
U32 x1;
|
|
U32 y1;
|
|
};
|
|
|
|
class @Point
|
|
{
|
|
U32 x;
|
|
U32 y;
|
|
}
|
|
|
|
class @draw_A
|
|
{
|
|
U32 id;
|
|
U32 imageid;
|
|
U32 fillid;
|
|
U8 public;
|
|
};
|
|
|
|
class @draw_P
|
|
{
|
|
U32 dstid;
|
|
U16 n;
|
|
U32 wind;
|
|
@Point ignore;
|
|
U32 srcid;
|
|
@Point sp;
|
|
// U16 sp[4];
|
|
// dp[2*2*(n+1)];
|
|
};
|
|
|
|
class @draw_b
|
|
{
|
|
U32 id;
|
|
U32 screenid;
|
|
U8 refresh;
|
|
U32 chan;
|
|
U8 repl;
|
|
@Rect r;
|
|
@Rect clipr;
|
|
U32 color;
|
|
};
|
|
|
|
class @draw_d
|
|
{
|
|
U32 dstid;
|
|
U32 srcid;
|
|
U32 maskid;
|
|
@Rect dstr;
|
|
@Point srcp;
|
|
@Point maskp;
|
|
};
|
|
|
|
class @draw_y
|
|
{
|
|
U32 id;
|
|
@Rect r;
|
|
};
|
|
|
|
I64 @image_cbgr24_to_4_bit(CBGR24* ptr, Bool dither_probability)
|
|
{
|
|
I64 res, k;
|
|
if (dither_probability) {
|
|
k = RandU32;
|
|
if (SqrI64(ptr->r) + SqrI64(ptr->g) + SqrI64(ptr->b) >= 3 * SqrI64(k.u8[0]))
|
|
res = 8;
|
|
else
|
|
res = 0;
|
|
if (ptr->r >= k.u8[1])
|
|
res |= RED;
|
|
if (ptr->g >= k.u8[2])
|
|
res |= GREEN;
|
|
if (ptr->b >= k.u8[3])
|
|
res |= BLUE;
|
|
} else {
|
|
if (SqrI64(ptr->r) + SqrI64(ptr->g) + SqrI64(ptr->b) >= SqrI64(0x80)) {
|
|
res = 8;
|
|
if (ptr->r >= 0x80)
|
|
res |= RED;
|
|
if (ptr->g >= 0x80)
|
|
res |= GREEN;
|
|
if (ptr->b >= 0x80)
|
|
res |= BLUE;
|
|
} else {
|
|
res = 0;
|
|
if (ptr->r >= 0x40)
|
|
res |= RED;
|
|
if (ptr->g >= 0x40)
|
|
res |= GREEN;
|
|
if (ptr->b >= 0x40)
|
|
res |= BLUE;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
I64 @nt_draw_A(@nt* nt, @draw_A* d, JsonObject* dobj)
|
|
{
|
|
// FIXME: Implement this.
|
|
@nt_tx_dbg(nt, "id: %d, imageid: %d, fillid: %d, public: %d",
|
|
d->id, d->imageid, d->fillid, d->public);
|
|
// PressAKey;
|
|
return sizeof(@draw_A);
|
|
}
|
|
|
|
I64 @nt_draw_b(@nt* nt, @draw_b* d, JsonObject* dobj)
|
|
{
|
|
// Allocate an image with a given id on the screen named by screenid.
|
|
// b id[4] screenid[4] refresh[1] chan[4] repl[1] r[4 * 4] clipr[4 * 4] color[4]
|
|
|
|
@nt_tx_dbg(nt, "id: %d, screenid: %d, refresh: %d, chan: %d, repl: %d",
|
|
d->id, d->screenid, d->refresh, d->chan, d->repl);
|
|
@nt_tx_dbg(nt, "rect: x0: %d, y0: %d, x1: %d, y1: %d",
|
|
d->r.x0, d->r.y0, d->r.x1, d->r.y1);
|
|
@nt_tx_dbg(nt, "clip rect: x0: %d, y0: %d, x1: %d, y1: %d",
|
|
d->clipr.x0, d->clipr.y0, d->clipr.x1, d->clipr.y1);
|
|
@nt_tx_dbg(nt, "color: %08x",
|
|
d->color);
|
|
|
|
U8 intbuf[16];
|
|
StrPrint(intbuf, "%d", d->id);
|
|
|
|
if (dobj->o("imgs")->@(intbuf)) {
|
|
@nt_tx_dbg(nt, "error: image id already exists");
|
|
PressAKey;
|
|
}
|
|
|
|
CDC* dc = NULL;
|
|
if (!d->repl) {
|
|
dc = DCNew(d->r.x1 - d->r.x0, d->r.y1 - d->r.y0);
|
|
}
|
|
|
|
JsonObject* iobj = Json.CreateObject(nt->main_task);
|
|
JsonObject* tmpr = NULL;
|
|
|
|
iobj->set("id", d->id, JSON_NUMBER);
|
|
iobj->set("screenid", d->screenid, JSON_NUMBER);
|
|
iobj->set("refresh", d->refresh, JSON_NUMBER);
|
|
iobj->set("chan", d->chan, JSON_NUMBER);
|
|
iobj->set("repl", d->repl, JSON_NUMBER);
|
|
iobj->set("dc", dc, JSON_NUMBER);
|
|
iobj->set("r", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
|
iobj->set("clipr", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
|
|
|
tmpr = iobj->o("r");
|
|
tmpr->set("x0", d->r.x0, JSON_NUMBER);
|
|
tmpr->set("y0", d->r.x1, JSON_NUMBER);
|
|
tmpr->set("x1", d->r.y0, JSON_NUMBER);
|
|
tmpr->set("y1", d->r.y1, JSON_NUMBER);
|
|
|
|
tmpr = iobj->o("clipr");
|
|
tmpr->set("x0", d->clipr.x0, JSON_NUMBER);
|
|
tmpr->set("y0", d->clipr.x1, JSON_NUMBER);
|
|
tmpr->set("x1", d->clipr.y0, JSON_NUMBER);
|
|
tmpr->set("y1", d->clipr.y1, JSON_NUMBER);
|
|
|
|
if (dc) {
|
|
CBGR24 bgr;
|
|
bgr.b = d->color.u8[0];
|
|
bgr.g = d->color.u8[1];
|
|
bgr.r = d->color.u8[2];
|
|
DCFill(dc, @image_cbgr24_to_4_bit(&bgr, 0));
|
|
}
|
|
|
|
StrPrint(intbuf, "%d", d->id);
|
|
dobj->o("imgs")->set(intbuf, iobj, JSON_OBJECT);
|
|
|
|
return sizeof(@draw_b);
|
|
}
|
|
|
|
U0 @nt_draw_y_mono_1bit(CDC* dc, @draw_y* d)
|
|
{
|
|
U8* _c = d;
|
|
I64 x = 0;
|
|
I64 y = 0;
|
|
I64 sx = 0;
|
|
_c += sizeof(@draw_y);
|
|
for (y = 0; y < d->r.y1; y++) {
|
|
for (x = 0; x < d->r.x1; x++) {
|
|
dc->color = @t((reverse_bits(*_c) >> sx) & 1, 15, 0);
|
|
GrPlot(dc, x, y);
|
|
sx++;
|
|
if (sx > 7) {
|
|
sx = 0;
|
|
_c++;
|
|
}
|
|
}
|
|
if (sx) {
|
|
sx = 0;
|
|
_c++;
|
|
}
|
|
}
|
|
}
|
|
|
|
I64 @nt_draw_y(@nt* nt, @draw_y* d, JsonObject* dobj)
|
|
{
|
|
// y id[4] r[4*4] buf[x*1]
|
|
|
|
// Replace the rectangle r of pixels in image id with the pixel data in buf.
|
|
|
|
@nt_tx_dbg(nt, "id: %d", d->id);
|
|
@nt_tx_dbg(nt, "rect: x0: %d, y0: %d, x1: %d, y1: %d",
|
|
d->r.x0, d->r.y0, d->r.x1, d->r.y1);
|
|
|
|
U32 int_w;
|
|
U8 intbuf[16];
|
|
StrPrint(intbuf, "%d", d->id);
|
|
|
|
JsonObject* iobj = dobj->o("imgs")->@(intbuf);
|
|
|
|
if (!iobj) {
|
|
@nt_tx_dbg(nt, "imageid %d does not exist\n", d->id);
|
|
PressAKey;
|
|
}
|
|
|
|
CDC* dc = iobj->@("dc");
|
|
|
|
if (!dc) {
|
|
@nt_tx_dbg(nt, "no device context for imageid %d\n", d->id);
|
|
PressAKey;
|
|
}
|
|
|
|
switch (iobj->@("chan")) {
|
|
case 0x31:
|
|
@nt_draw_y_mono_1bit(dc, d);
|
|
int_w = d->r.x1;
|
|
while (int_w % 8) {
|
|
int_w++;
|
|
}
|
|
return sizeof(@draw_y) + ((int_w * d->r.y1) / 8);
|
|
default:
|
|
@nt_tx_dbg(nt, "unsupported chan value: 0x%04x", iobj->@("chan"));
|
|
PressAKey;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
|
|
U8* @nt_drawcoord(@nt* nt, U8* p, U8* maxp, U32 oldx, U32* newx)
|
|
{
|
|
U32 b, x;
|
|
|
|
if (p >= maxp) {
|
|
@nt_tx_dbg(nt, "error: Eshortdraw1: p = 0x%08x, maxp = 0x%08x", p, maxp);
|
|
PressAKey;
|
|
}
|
|
b = *p++;
|
|
x = b & 0x7F;
|
|
if (b & 0x80) {
|
|
if (p + 1 >= maxp) {
|
|
@nt_tx_dbg(nt, "error: Eshortdraw2: p = 0x%08x", p);
|
|
PressAKey;
|
|
}
|
|
x |= *p++ << 7;
|
|
x |= *p++ << 15;
|
|
if (x & (1 << 22))
|
|
x |= ~0 << 23;
|
|
} else {
|
|
if (b & 0x40)
|
|
x |= ~0 << 7;
|
|
x += oldx;
|
|
}
|
|
*newx = x;
|
|
return p;
|
|
}
|
|
|
|
I64 @nt_draw_P(@nt* nt, @draw_P* d, JsonObject* dobj)
|
|
{
|
|
// P dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] dp[2*2*(n+1)]
|
|
|
|
// Draw a polygon as the p message, but fill it rather than outlining it.
|
|
|
|
@nt_tx_dbg(nt, "dstid: %d, n: %d, srcid: %d",
|
|
d->dstid, d->n, d->srcid);
|
|
|
|
// FIXME: Implement this.
|
|
|
|
JsonObject* iobj;
|
|
U8 idbuf[16];
|
|
I64 dx, dy;
|
|
CDC* dst = NULL;
|
|
CDC* src = NULL;
|
|
|
|
StrPrint(idbuf, "%d", d->dstid);
|
|
iobj = dobj->o("imgs")->o(idbuf);
|
|
if (iobj) {
|
|
dst = iobj->@("dc");
|
|
}
|
|
|
|
// StrPrint(idbuf, "%d", d->srcid);
|
|
// iobj = dobj->o("imgs")->o(idbuf);
|
|
// if (iobj) {
|
|
// src = iobj->@("dc");
|
|
// }
|
|
|
|
if (dst) {
|
|
dx = 0 + d->sp.x;
|
|
dy = 0 + d->sp.y;
|
|
|
|
// dy = d->sp.y;
|
|
|
|
// dst->color = BLUE;
|
|
//@nt_tx_dbg(nt, "plot dst pixel: dx: %d, dy: %d", dx, dy);
|
|
// GrPlot(dst, dx, dy);
|
|
}
|
|
|
|
I64 i; //, j;
|
|
I64 dp_length = 0;
|
|
U8* dp_ptr = d;
|
|
U8* maxp = 0x80000000000000;
|
|
dp_ptr += 4 + 2 + 4 + 4 + 4 + 4 + 2 * 4;
|
|
// d += sizeof(@draw_P);
|
|
I64 b = 0;
|
|
|
|
// m = 1+4+2+4 +4+4 +4 +2*4
|
|
|
|
// U32 ox = 0;
|
|
// U32 oy = 0;
|
|
// p.x = d->sp.x;
|
|
// p.y = d->sp.y;
|
|
|
|
U64 __p = d;
|
|
__p += sizeof(@draw_P);
|
|
|
|
@Point p;
|
|
p.x = (__p)(U32*)[0];
|
|
p.y = (__p)(U32*)[1];
|
|
|
|
U32 ox = p.x;
|
|
U32 oy = p.y;
|
|
|
|
for (i = 0; i < d->n + 1; i++) {
|
|
dp_ptr = @nt_drawcoord(nt, dp_ptr, maxp, ox, &p.x);
|
|
dp_ptr = @nt_drawcoord(nt, dp_ptr, maxp, oy, &p.y);
|
|
|
|
if (dst) {
|
|
dst->color = BLACK;
|
|
@nt_tx_dbg(nt, "plot line: x0: %d, y0: %d, x1: %d, y1: %d", ox, oy, p.x, p.y);
|
|
if (!(ox > dst->width || oy > dst->height || p.x > dst->width || p.y > dst->height)) {
|
|
GrLine(dst, ox, oy, p.x, p.y);
|
|
}
|
|
// GrPlot(dst, dx + p.x, dy + p.y);
|
|
}
|
|
|
|
ox = p.x;
|
|
oy = p.y;
|
|
// for (j = 0; j < 2; j++) {
|
|
// b = dp_ptr[dp_length++];
|
|
// if (b & 0x80) {
|
|
// dp_length += 2;
|
|
// }
|
|
// }
|
|
}
|
|
// Sleep(5000);
|
|
// PressAKey;
|
|
return sizeof(@draw_P) + dp_length - d(U8*);
|
|
}
|
|
|
|
I64 @nt_draw_d(@nt* nt, @draw_d* d, JsonObject* dobj)
|
|
{
|
|
// m = 1+4+4+4+4*4+2*4+2*4;
|
|
// d dstid[4] srcid[4] maskid[4] dstr[4*4] srcp[2*4] maskp[2*4]
|
|
// Use the draw operator to combine the rectangle dstr of image dstid with a rectangle of image srcid ...
|
|
// res = 4 + 4 + 4 + sizeof(@Rect) + sizeof(@Point) + sizeof(@Point);
|
|
|
|
I64 res = 4 + 4 + 4 + sizeof(@Rect) + sizeof(@Point) + sizeof(@Point);
|
|
|
|
@nt_tx_dbg(nt, "dstid: %d, srcid: %d, maskid: %d, dstr: (%d,%d, %d,%d), srcp: (%d,%d) maskp: (%d,%d)",
|
|
d->dstid, d->srcid, d->maskid, d->dstr.x0, d->dstr.y0, d->dstr.x1, d->dstr.y1,
|
|
d->srcp.x, d->srcp.y, d->maskp.x, d->maskp.y);
|
|
|
|
JsonObject* iobj;
|
|
U8 idbuf[16];
|
|
I64 dx, dy;
|
|
CDC* dst;
|
|
CDC* src;
|
|
|
|
StrPrint(idbuf, "%d", d->dstid);
|
|
iobj = dobj->o("imgs")->o(idbuf);
|
|
if (!iobj) {
|
|
return res;
|
|
}
|
|
dst = iobj->@("dc");
|
|
if (!dst) {
|
|
return res;
|
|
}
|
|
|
|
StrPrint(idbuf, "%d", d->srcid);
|
|
iobj = dobj->o("imgs")->o(idbuf);
|
|
if (!iobj) {
|
|
return res;
|
|
}
|
|
src = iobj->@("dc");
|
|
if (!src) {
|
|
return res;
|
|
}
|
|
|
|
dx = U32_MAX - d->srcp.x;
|
|
dy = U32_MAX - d->srcp.y;
|
|
|
|
GrBlot(dst, dx, dy, src);
|
|
|
|
return res;
|
|
|
|
// if (dobj->o("imgs")->o(idbuf)) {
|
|
// @nt_tx_dbg(nt, "image id %d exists for srcid", d->srcid);
|
|
// src = dobj->o("imgs")->o(idbuf)->@("dc");
|
|
//
|
|
// if (src) {
|
|
// @nt_tx_dbg(nt, "src dc: width: %d, height: %d", src->width, src->height);
|
|
// if (d->dstr.x1 == 640 && d->dstr.y1 == 480 && src->width != 640) {
|
|
// dx = U32_MAX - d->srcp.x;
|
|
// dy = U32_MAX - d->srcp.y;
|
|
// GrBlot(gr.dc, dx, dy, src);
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// return 4 + 4 + 4 + sizeof(@Rect) + sizeof(@Point) + sizeof(@Point);
|
|
}
|
|
I64 @nt_draw_cmd(@nt* nt, U8* data, JsonObject* dobj, U8* data_ptr, I64 i)
|
|
{
|
|
I64 cmd = data_ptr[i++];
|
|
I64 res = 0;
|
|
// size[4] Twrite tag[2] fid[4] offset[8] count[4]
|
|
@nt_tx_dbg(nt, "draw cmd: %c, offset: 0x%04x", cmd, i - 1 + (4 + 1 + 2 + 4 + 8 + 4));
|
|
|
|
JsonKey* k;
|
|
JsonObject* o;
|
|
CDC* dc;
|
|
|
|
switch (cmd) {
|
|
case 0:
|
|
@nt_tx_dbg(nt, "ERROR: draw cmd is NULL, i: 0x%04x", i - 1 + (4 + 1 + 2 + 4 + 8 + 4));
|
|
PressAKey;
|
|
break;
|
|
case 'A':
|
|
res = @nt_draw_A(nt, data_ptr + i, dobj);
|
|
break;
|
|
case 'p':
|
|
case 'P':
|
|
res = @nt_draw_P(nt, data_ptr + i, dobj);
|
|
break;
|
|
case 'b':
|
|
res = @nt_draw_b(nt, data_ptr + i, dobj);
|
|
break;
|
|
case 'v':
|
|
k = dobj->o("imgs")->keys;
|
|
while (k) {
|
|
o = k->value;
|
|
if (o && o->@("dc")) {
|
|
dc = o->@("dc");
|
|
if (dc->width == 640 && dc->height == 480) {
|
|
GrBlot(nt->screen, 0, 0, dc);
|
|
}
|
|
}
|
|
k = k->next;
|
|
}
|
|
// FIXME: update display buffer
|
|
break;
|
|
case 'y':
|
|
res = @nt_draw_y(nt, data_ptr + i, dobj);
|
|
break;
|
|
case 'c':
|
|
// c dstid[4] repl[1] clipr[4*4]
|
|
// Change the replicate bit and clipping rectangle of the image dstid.
|
|
res = 4 + 1 + sizeof(@Rect);
|
|
break;
|
|
case 'd':
|
|
res = @nt_draw_d(nt, data_ptr + i, dobj);
|
|
break;
|
|
default:
|
|
// Sleep(5000);
|
|
@nt_tx_dbg(nt, "ERROR: unimplemented draw cmd: %c, offset: 0x%04x", cmd, i - 1 + (4 + 1 + 2 + 4 + 8 + 4));
|
|
// Sleep(5000);
|
|
PressAKey;
|
|
break;
|
|
}
|
|
return ++res;
|
|
}
|
|
|
|
U0 @nt_draw(@nt* nt, U8* data, @9p_qid * qid)
|
|
{
|
|
SET_MSGS
|
|
|
|
// size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count]
|
|
|
|
U8 dobjbuf[32];
|
|
StrCpy(dobjbuf, StrFind("/dev/draw/", qid->path) + 10);
|
|
StrFind("/data", dobjbuf)[0] = NULL;
|
|
JsonObject* dobj = nt->drawobjs->@(dobjbuf);
|
|
|
|
U64 draw_ptr = data + (4 + 1 + 2 + 4 + 8 + 4);
|
|
U32 length = *(data + (4 + 1 + 2 + 4 + 8))(U32*);
|
|
|
|
I64 i = 0;
|
|
while (i < length) {
|
|
i += @nt_draw_cmd(nt, data, dobj, draw_ptr, i);
|
|
}
|
|
} |