mirror of
https://git.checksum.fail/alec/neinterm.git
synced 2025-12-10 13:09:54 +02:00
Add files to repository
This commit is contained in:
133
System/9P/Debug.HC
Normal file
133
System/9P/Debug.HC
Normal file
@@ -0,0 +1,133 @@
|
||||
// debugging drawterm
|
||||
|
||||
#define _TVERSION 100
|
||||
#define _TAUTH 102
|
||||
#define _TATTACH 104
|
||||
#define _TERROR 106
|
||||
#define _TFLUSH 108
|
||||
#define _TWALK 110
|
||||
#define _TOPEN 112
|
||||
#define _TCREATE 114
|
||||
#define _TREAD 116
|
||||
#define _TWRITE 118
|
||||
#define _TCLUNK 120
|
||||
#define _TREMOVE 122
|
||||
#define _TSTAT 124
|
||||
#define _TWSTAT 126
|
||||
|
||||
U0 @9p_debug_printf(U8* fmt, ...)
|
||||
{
|
||||
U8* buf;
|
||||
if (argc) {
|
||||
buf = StrPrintJoin(NULL, fmt, argc, argv);
|
||||
} else {
|
||||
buf = StrNew(fmt);
|
||||
}
|
||||
U8* s = buf;
|
||||
while (*s) {
|
||||
OutU8(0xe9, *s++);
|
||||
}
|
||||
Free(buf);
|
||||
}
|
||||
|
||||
U8* @9p_debug_get_code_str(I64 code)
|
||||
{
|
||||
switch (code) {
|
||||
case _TVERSION:
|
||||
return "Tversion";
|
||||
case _TAUTH:
|
||||
return "Tauth";
|
||||
case _TATTACH:
|
||||
return "Tattach";
|
||||
case _TERROR:
|
||||
return "Terror";
|
||||
case _TFLUSH:
|
||||
return "Tflush";
|
||||
case _TWALK:
|
||||
return "Twalk";
|
||||
case _TOPEN:
|
||||
return "Topen";
|
||||
case _TCREATE:
|
||||
return "Tcreate";
|
||||
case _TREAD:
|
||||
return "Tread";
|
||||
case _TWRITE:
|
||||
return "Twrite";
|
||||
case _TCLUNK:
|
||||
return "Tclunk";
|
||||
case _TREMOVE:
|
||||
return "Tremove";
|
||||
case _TSTAT:
|
||||
return "Tstat";
|
||||
case _TWSTAT:
|
||||
return "Twstat";
|
||||
case 1 + _TVERSION:
|
||||
return "Rversion";
|
||||
case 1 + _TAUTH:
|
||||
return "Rauth";
|
||||
case 1 + _TATTACH:
|
||||
return "Rattach";
|
||||
case 1 + _TERROR:
|
||||
return "Rerror";
|
||||
case 1 + _TFLUSH:
|
||||
return "Rflush";
|
||||
case 1 + _TWALK:
|
||||
return "Rwalk";
|
||||
case 1 + _TOPEN:
|
||||
return "Ropen";
|
||||
case 1 + _TCREATE:
|
||||
return "Rcreate";
|
||||
case 1 + _TREAD:
|
||||
return "Rread";
|
||||
case 1 + _TWRITE:
|
||||
return "Rwrite";
|
||||
case 1 + _TCLUNK:
|
||||
return "Rclunk";
|
||||
case 1 + _TREMOVE:
|
||||
return "Rremove";
|
||||
case 1 + _TSTAT:
|
||||
return "Rstat";
|
||||
case 1 + _TWSTAT:
|
||||
return "Rwstat";
|
||||
default:
|
||||
return "(unimplemented)";
|
||||
}
|
||||
}
|
||||
|
||||
U0 @9p_debug_dump(U8* dat, U64 ndat, I64 mode)
|
||||
{
|
||||
I64 i, j, step;
|
||||
U8 buf[17];
|
||||
buf[16] = 0;
|
||||
|
||||
@9p_debug_printf("dump: ptr=%p, length=%d, code: %s, mode=%s\n", dat, ndat, @9p_debug_get_code_str(dat[4]), @t(mode == 1, "tx", "rx"));
|
||||
for (i = 0; i < 32; i++)
|
||||
@9p_debug_printf("=");
|
||||
@9p_debug_printf("\n");
|
||||
|
||||
i = 0;
|
||||
|
||||
while (i < ndat) {
|
||||
@9p_debug_printf("%08x: ", i);
|
||||
step = @t(ndat - i > 16, 16, ndat - i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (j > step - 1) {
|
||||
@9p_debug_printf(" ");
|
||||
buf[j] = 0;
|
||||
} else {
|
||||
@9p_debug_printf("%02x ", dat[i + j]);
|
||||
switch (dat[i + j]) {
|
||||
case ' ' ... 'z':
|
||||
buf[j] = dat[i + j];
|
||||
break;
|
||||
default:
|
||||
buf[j] = '.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@9p_debug_printf("%s\n", buf);
|
||||
i += step;
|
||||
}
|
||||
@9p_debug_printf("\n");
|
||||
}
|
||||
293
System/9P/Defs.HC
Normal file
293
System/9P/Defs.HC
Normal file
@@ -0,0 +1,293 @@
|
||||
#define TVERSION 100
|
||||
#define TAUTH 102
|
||||
#define TATTACH 104
|
||||
#define TERROR 106
|
||||
#define TFLUSH 108
|
||||
#define TWALK 110
|
||||
#define TOPEN 112
|
||||
#define TCREATE 114
|
||||
#define TREAD 116
|
||||
#define TWRITE 118
|
||||
#define TCLUNK 120
|
||||
#define TREMOVE 122
|
||||
#define TSTAT 124
|
||||
#define TWSTAT 126
|
||||
|
||||
#define NT_BUF_SIZE 65536
|
||||
#define NT_FIFO_SIZE 128
|
||||
#define SET_REQUEST_SIZE U32 request_size = *(data)(U32*);
|
||||
|
||||
#define NT_IS_DIR 0x80
|
||||
#define NT_IS_FILE 0x0
|
||||
|
||||
// #define SET_RESPONSE_SIZE *(nt->out)(U32*) = response_size;
|
||||
// #define CLEAR_RESPONSE_BUFFER MemSet(nt->out, NULL, response_size);
|
||||
// #define SEND_RESPONSE_BUFFER nt->s->send(nt->out, response_size);
|
||||
#define SET_RESPONSE_CMD nt->out[4] = data[4] + 1;
|
||||
#define SET_RESPONSE_TAG \
|
||||
nt->out[5] = data[5]; \
|
||||
nt->out[6] = data[6];
|
||||
|
||||
#define SET_MSGS \
|
||||
@9p_msg * Tmsg = data; \
|
||||
@9p_msg * Rmsg = nt->out;
|
||||
#define SEND_RMSG \
|
||||
SET_RESPONSE_CMD SET_RESPONSE_TAG @9p_debug_dump(Rmsg, Rmsg->length, 1); \
|
||||
nt->s->send(Rmsg, Rmsg->length);
|
||||
#define CLEAR_RMSG MemSet(Rmsg(U64) + 4, NULL, Rmsg->length - 4);
|
||||
|
||||
U8* @nt_msg_type_string(I64 req)
|
||||
{
|
||||
switch (req) {
|
||||
case TVERSION:
|
||||
return "Tversion";
|
||||
case TAUTH:
|
||||
return "Tauth";
|
||||
case TATTACH:
|
||||
return "Tattach";
|
||||
case TERROR:
|
||||
return "Terror";
|
||||
case TFLUSH:
|
||||
return "Tflush";
|
||||
case TWALK:
|
||||
return "Twalk";
|
||||
case TOPEN:
|
||||
return "Topen";
|
||||
case TCREATE:
|
||||
return "Tcreate";
|
||||
case TREAD:
|
||||
return "Tread";
|
||||
case TWRITE:
|
||||
return "Twrite";
|
||||
case TCLUNK:
|
||||
return "Tclunk";
|
||||
case TREMOVE:
|
||||
return "Tremove";
|
||||
case TSTAT:
|
||||
return "Tstat";
|
||||
case TWSTAT:
|
||||
return "Twstat";
|
||||
default:
|
||||
return "(unimplemented)";
|
||||
}
|
||||
}
|
||||
|
||||
class @9p_qid
|
||||
{
|
||||
U8 type;
|
||||
U32 version;
|
||||
U64 path;
|
||||
};
|
||||
|
||||
class @9p_str
|
||||
{
|
||||
U8 length;
|
||||
U8 data;
|
||||
};
|
||||
|
||||
class @9p_msg
|
||||
{
|
||||
U32 length;
|
||||
U8 type;
|
||||
U16 tag;
|
||||
U32 fid;
|
||||
};
|
||||
|
||||
class @9p_twalk : @9p_msg
|
||||
{
|
||||
U32 newfid;
|
||||
U16 nwname;
|
||||
U8 wname; // mem location for nwname*(wname[s])
|
||||
};
|
||||
|
||||
class @9p_stat
|
||||
{
|
||||
U16 size;
|
||||
U16 type;
|
||||
U32 dev;
|
||||
@9p_qid qid;
|
||||
U32 mode;
|
||||
U32 atime;
|
||||
U32 mtime;
|
||||
U64 length;
|
||||
U8 name;
|
||||
};
|
||||
|
||||
class @9p_direntry
|
||||
{
|
||||
U16 type;
|
||||
U32 dev;
|
||||
@9p_qid qid;
|
||||
U32 mode;
|
||||
U32 atime;
|
||||
U32 mtime;
|
||||
U64 length;
|
||||
U8 name;
|
||||
};
|
||||
|
||||
// The reply will contain a machine-independent directory entry, stat, laid out as follows:
|
||||
// size[2]total byte count of the following data
|
||||
// type[2]for kernel use
|
||||
// dev[4]for kernel use
|
||||
// qid.type[1]
|
||||
// the type of the file (directory, etc.), represented as a bit vector corresponding to the high 8 bits of the file’s mode word.
|
||||
// qid.vers[4]
|
||||
// version number for given path
|
||||
// qid.path[8]
|
||||
// the file server’s unique identification for the file
|
||||
// mode[4]
|
||||
// permissions and flags
|
||||
// atime[4]
|
||||
// last access time
|
||||
// mtime[4]
|
||||
// last modification time
|
||||
// length[8]
|
||||
// length of file in bytes
|
||||
// name[ s ]
|
||||
// file name; must be / if the file is the root directory of the server
|
||||
// uid[ s ]owner name
|
||||
// gid[ s ]group name
|
||||
// muid[ s ]
|
||||
// name of the user who last modified the file
|
||||
|
||||
U64 EndianU64(U64 s)
|
||||
{
|
||||
U64 d;
|
||||
d.u8[0] = s.u8[7];
|
||||
d.u8[1] = s.u8[6];
|
||||
d.u8[2] = s.u8[5];
|
||||
d.u8[3] = s.u8[4];
|
||||
d.u8[4] = s.u8[3];
|
||||
d.u8[5] = s.u8[2];
|
||||
d.u8[6] = s.u8[1];
|
||||
d.u8[7] = s.u8[0];
|
||||
return d;
|
||||
}
|
||||
|
||||
// Mouse Cursor
|
||||
CDC* @nt_cursor = DCNew(16, 16);
|
||||
Free(@nt_cursor->body);
|
||||
U8 @nt_cursor_data[16 * 16] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
@nt_cursor->body = @nt_cursor_data;
|
||||
|
||||
class @nt
|
||||
{
|
||||
CDC* cursor;
|
||||
CTask* dbg_task;
|
||||
CTask* main_task;
|
||||
CTask* rx_task;
|
||||
CTask* tx_task;
|
||||
TcpSocket* s;
|
||||
U8* host;
|
||||
I64 port;
|
||||
U8* out;
|
||||
CFifoI64* rx_fifo;
|
||||
CFifoI64* rx_dbg_fifo;
|
||||
CFifoI64* tx_dbg_fifo;
|
||||
CFifoI64* kbd_fifo;
|
||||
I64 kbd_last_jiffies;
|
||||
U8* connect_script;
|
||||
U16 kbd_read_tag;
|
||||
// U8 last_kbd_read_request[23];
|
||||
JsonObject* fids;
|
||||
JsonObject* qids;
|
||||
JsonObject* drawobjs;
|
||||
CDC* screen;
|
||||
I64 attach_fid;
|
||||
};
|
||||
|
||||
class @nt_dbg_msg
|
||||
{
|
||||
I64 ts;
|
||||
U8* s;
|
||||
I64 dir;
|
||||
};
|
||||
|
||||
U0 @nt_dbg_out(@nt_dbg_msg* msg)
|
||||
{
|
||||
U8 ts[16];
|
||||
StrPrint(ts, "[%8d] %c ", msg->ts, @t(msg->dir, 'TX', 'RX'));
|
||||
U8* s = ts;
|
||||
while (*s) {
|
||||
OutU8(0xe9, *s++);
|
||||
}
|
||||
s = msg->s;
|
||||
while (*s) {
|
||||
OutU8(0xe9, *s++);
|
||||
}
|
||||
OutU8(0xe9, '\n');
|
||||
// Free(msg->s);
|
||||
// Free(msg);
|
||||
}
|
||||
|
||||
@9p_qid * @nt_qid_create(@nt* nt, U8* path, I64 type)
|
||||
{
|
||||
@9p_qid * qid = CAlloc(sizeof(@9p_qid), nt->main_task);
|
||||
qid->type = type;
|
||||
qid->path = StrNew(path, nt->main_task);
|
||||
nt->qids->set(path, qid, JSON_NUMBER);
|
||||
return qid;
|
||||
}
|
||||
|
||||
@9p_qid * @nt_lookup_qid_by_path(@nt* nt, U8* path)
|
||||
{
|
||||
return nt->qids->@(path);
|
||||
}
|
||||
|
||||
U0 @nt_pascal_to_c_strings(@nt* nt, U8** wname, U8* data, I64 nwname)
|
||||
{
|
||||
I64 i, j = 0;
|
||||
I64 len = 0;
|
||||
for (i = 0; i < nwname; i++) {
|
||||
len = *(data + j)(U16*);
|
||||
j += 2;
|
||||
wname[i] = CAlloc(len + 1, nt->main_task);
|
||||
MemCpy(wname[i], data + j, len);
|
||||
j += len;
|
||||
}
|
||||
}
|
||||
|
||||
U0 @nt_rx_dbg(@nt* nt, U8* fmt, ...)
|
||||
{
|
||||
U8* buf;
|
||||
if (argc) {
|
||||
buf = StrPrintJoin(NULL, fmt, argc, argv);
|
||||
} else {
|
||||
buf = StrNew(fmt);
|
||||
}
|
||||
@nt_dbg_msg* msg = CAlloc(sizeof(@nt_dbg_msg), nt->main_task);
|
||||
msg->ts = cnts.jiffies;
|
||||
msg->s = buf;
|
||||
msg->dir = 0;
|
||||
FifoI64Ins(nt->rx_dbg_fifo, msg);
|
||||
}
|
||||
|
||||
U0 @nt_tx_dbg(@nt* nt, U8* fmt, ...)
|
||||
{
|
||||
U8* buf;
|
||||
if (argc) {
|
||||
buf = StrPrintJoin(NULL, fmt, argc, argv);
|
||||
} else {
|
||||
buf = StrNew(fmt);
|
||||
}
|
||||
@nt_dbg_msg* msg = CAlloc(sizeof(@nt_dbg_msg), nt->main_task);
|
||||
msg->ts = cnts.jiffies;
|
||||
msg->s = buf;
|
||||
msg->dir = 1;
|
||||
FifoI64Ins(nt->tx_dbg_fifo, msg);
|
||||
}
|
||||
|
||||
U0 @nt_zrmsg(@nt* nt, I64 length)
|
||||
{
|
||||
// Zero Rmsg to length and set length
|
||||
@9p_msg * Rmsg = nt->out;
|
||||
MemSet(Rmsg, NULL, length);
|
||||
Rmsg->length = length;
|
||||
}
|
||||
|
||||
U0 @nt_fid_set(@nt* nt, U8* fidbuf, @9p_qid * qid)
|
||||
{
|
||||
JsonObject* fid = Json.CreateObject(nt->main_task);
|
||||
fid->set("qid", qid, JSON_NUMBER);
|
||||
nt->fids->set(fidbuf, fid, JSON_OBJECT);
|
||||
}
|
||||
503
System/9P/Draw.HC
Normal file
503
System/9P/Draw.HC
Normal file
@@ -0,0 +1,503 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
557
System/9P/Requests.HC
Normal file
557
System/9P/Requests.HC
Normal file
@@ -0,0 +1,557 @@
|
||||
U0 @nt_Rerror(@nt* nt, U8* data, U8* errormsg)
|
||||
{
|
||||
// size[4] Rerror tag[2] ename[s]
|
||||
|
||||
SET_MSGS
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + 2);
|
||||
nt->out[4] = TERROR + 1; // RERROR
|
||||
|
||||
MemCpy(nt->out + (4 + 1 + 2 + 2), errormsg, StrLen(errormsg));
|
||||
*(nt->out + (4 + 1 + 2))(U16*) = StrLen(errormsg);
|
||||
|
||||
SET_RESPONSE_TAG
|
||||
Rmsg->length += StrLen(errormsg);
|
||||
|
||||
@9p_debug_dump(Rmsg, Rmsg->length, 1);
|
||||
nt->s->send(Rmsg, Rmsg->length);
|
||||
}
|
||||
|
||||
U0 @nt_Tversion(@nt* nt, U8* data)
|
||||
{
|
||||
SET_MSGS
|
||||
|
||||
// Special case; just increment Tmsg tag to Rmsg and echo back to client
|
||||
data[4]++;
|
||||
@9p_debug_dump(data, Tmsg->length, 1);
|
||||
nt->s->send(data, Tmsg->length);
|
||||
}
|
||||
|
||||
U0 @nt_Tattach(@nt* nt, U8* data)
|
||||
{
|
||||
SET_MSGS
|
||||
@nt_zrmsg(nt, 20);
|
||||
//@nt_tx_dbg(nt, "Tattach fid: %d", Tmsg->fid);
|
||||
nt->attach_fid = Tmsg->fid;
|
||||
|
||||
// Map fid to qid
|
||||
U8 fidbuf[16];
|
||||
@9p_qid * qid = @nt_lookup_qid_by_path(nt, "/");
|
||||
StrPrint(fidbuf, "%d", Tmsg->fid);
|
||||
// nt->fids->set(fidbuf, qid, JSON_NUMBER);
|
||||
@nt_fid_set(nt, fidbuf, qid);
|
||||
|
||||
MemCpy(nt->out + 7, qid, sizeof(@9p_qid));
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
U0 @nt_Twalk(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/walk.html
|
||||
|
||||
// size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s])
|
||||
// size[4] Rwalk tag[2] nwqid[2] nwqid*(qid[13])
|
||||
|
||||
// The fid must be valid in the current session and must not have been opened for I/O by an open or create message.
|
||||
// If the full sequence of nwname elements is walked successfully, newfid will represent the file that results.
|
||||
// If not, newfid (and fid) will be unaffected. However, if newfid is in use or otherwise illegal, an Rerror is returned.
|
||||
|
||||
// If the first element cannot be walked for any reason, Rerror is returned.
|
||||
// Otherwise, the walk will return an Rwalk message containing:
|
||||
// nwqid qids corresponding, in order, to the files that are visited by the nwqid successful elementwise walks;
|
||||
// nwqid is therefore either nwname or the index of the first elementwise walk that failed.
|
||||
|
||||
// size[4] Rwalk tag[2] nwqid[2] nwqid*(qid[13])
|
||||
|
||||
// The value of nwqid cannot be zero unless nwname is zero.
|
||||
// Also, nwqid will always be less than or equal to nwname.
|
||||
// Only if it is equal, however, will newfid be affected, in which case newfid will represent:
|
||||
// the file reached by the final elementwise walk requested in the message.
|
||||
|
||||
SET_MSGS
|
||||
@9p_twalk * Twalk = data;
|
||||
U8** wname = NULL;
|
||||
|
||||
I64 i, j;
|
||||
U16 fid = Twalk->fid;
|
||||
U16 newfid = Twalk->newfid;
|
||||
U16 nwname = Twalk->nwname;
|
||||
U16 nwqid = 0;
|
||||
@9p_qid * qid = NULL;
|
||||
|
||||
U8 basepath[512];
|
||||
U8 pathbuf[512];
|
||||
U8 fidbuf[16];
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + 2);
|
||||
//@nt_tx_dbg(nt, "Twalk fid: %d, newfid: %d, nwname: %d", fid, newfid, nwname);
|
||||
|
||||
if (fid != nt->attach_fid) {
|
||||
// FIXME: Lookup base path from fid
|
||||
StrPrint(fidbuf, "%d", fid);
|
||||
qid = nt->fids->o(fidbuf)->@("qid");
|
||||
if (!qid) {
|
||||
@nt_tx_dbg(nt, "ERROR: !qid");
|
||||
PressAKey;
|
||||
}
|
||||
StrCpy(basepath, qid->path);
|
||||
if (qid->type != NT_IS_DIR) {
|
||||
StrLastOcc(basepath, "/")[0] = NULL;
|
||||
}
|
||||
} else {
|
||||
StrCpy(basepath, "");
|
||||
}
|
||||
|
||||
if (nwname) {
|
||||
wname = CAlloc(sizeof(U8*) * nwname, nt->main_task);
|
||||
@nt_pascal_to_c_strings(nt, wname, &Twalk->wname, nwname);
|
||||
|
||||
for (i = 0; i < nwname; i++) {
|
||||
StrCpy(pathbuf, basepath);
|
||||
for (j = 0; j <= i; j++) {
|
||||
StrPrint(pathbuf + StrLen(pathbuf), "/%s", wname[j]);
|
||||
}
|
||||
qid = @nt_lookup_qid_by_path(nt, pathbuf);
|
||||
if (qid) {
|
||||
// Copy the qid to Rwalk and increment nwqid, Rwalk length
|
||||
MemCpy(nt->out + (4 + 1 + 2 + 2 + (nwqid * sizeof(@9p_qid))), qid, sizeof(@9p_qid));
|
||||
nwqid++;
|
||||
Rmsg->length += sizeof(@9p_qid);
|
||||
} else {
|
||||
|
||||
// Rerror
|
||||
Rmsg->length = (4 + 1 + 2 + 2);
|
||||
Rmsg->type = 0x6b; // Rerror
|
||||
SET_RESPONSE_TAG
|
||||
StrPrint(nt->out + (4 + 1 + 2 + 2), "file does not exist: '.%s'", pathbuf);
|
||||
//@nt_tx_dbg(nt, "newfid: %d, %s", newfid, nt->out + (4 + 1 + 2 + 2));
|
||||
*(nt->out + (4 + 1 + 2))(U16*) = StrLen(nt->out + (4 + 1 + 2 + 2));
|
||||
Rmsg->length += StrLen(nt->out + (4 + 1 + 2 + 2));
|
||||
@9p_debug_dump(Rmsg, Rmsg->length, 1);
|
||||
nt->s->send(Rmsg, Rmsg->length);
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map newfid to qid
|
||||
StrPrint(fidbuf, "%d", newfid);
|
||||
// nt->fids->set(fidbuf, qid, JSON_NUMBER);
|
||||
@nt_fid_set(nt, fidbuf, qid);
|
||||
|
||||
// Set nwqid
|
||||
*(nt->out + (4 + 1 + 2))(U16*) = nwqid;
|
||||
|
||||
//@nt_tx_dbg(nt, "newfid: %d, walked: %s", newfid, pathbuf);
|
||||
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
U0 @nt_Topen(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/open.html
|
||||
|
||||
// size[4] Topen tag[2] fid[4] mode[1]
|
||||
// size[4] Ropen tag[2] qid[13] iounit[4]
|
||||
|
||||
SET_MSGS
|
||||
|
||||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||||
I64 mode = data[4 + 1 + 2 + 4];
|
||||
|
||||
U8 fidbuf[16];
|
||||
StrPrint(fidbuf, "%d", fid);
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + 13 + 4);
|
||||
//@nt_tx_dbg(nt, "Topen fid: %d, mode: %d", fid, mode);
|
||||
|
||||
@9p_qid * qid = nt->fids->o(fidbuf)->@("qid");
|
||||
|
||||
if (!qid) {
|
||||
@nt_tx_dbg("ERROR: no qid for fid %d", fid);
|
||||
PressAKey;
|
||||
}
|
||||
|
||||
MemCpy(nt->out + 7, qid, sizeof(@9p_qid));
|
||||
*(nt->out + (4 + 1 + 2 + 13))(U32*) = NULL; // set iounit to NULL for now
|
||||
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
U0 @nt_Tclunk(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/clunk.html
|
||||
|
||||
// size[4] Tclunk tag[2] fid[4]
|
||||
// size[4] Rclunk tag[2]
|
||||
|
||||
SET_MSGS
|
||||
|
||||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||||
|
||||
U8 fidbuf[16];
|
||||
StrPrint(fidbuf, "%d", fid);
|
||||
|
||||
Rmsg->length = (4 + 1 + 2);
|
||||
//@nt_tx_dbg(nt, "Tclunk fid: %d", fid);
|
||||
|
||||
nt->fids->unset(fidbuf);
|
||||
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
// I64 test_read_cnt = 0;
|
||||
|
||||
I64 test_read_cnt = 0;
|
||||
// I64 test_entry_size = 0x45;
|
||||
I64 test_entry_size = 0x41;
|
||||
|
||||
// U8 test_entry[test_entry_size] = { 0x3e, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x27, 0xab, 0xe2, 0x68, 0x1b, 0xab, 0xe2, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x72, 0x61, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63 };
|
||||
U8 test_entry[test_entry_size] = { 0x3f, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x80, 0x27, 0xab, 0xe2, 0x68, 0x1b, 0xab, 0xe2, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x64, 0x72, 0x61, 0x77, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63 };
|
||||
// U8 test_entry[test_entry_size] = { 0x3f, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x80, 0x4d, 0xb2, 0xe2, 0x68, 0x47, 0xb2, 0xe2, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x64, 0x72, 0x61, 0x77, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x04, 0x00, 0x61, 0x6c, 0x65, 0x63, 0x42, 0x00, 0x69, 0x00 };
|
||||
|
||||
U0 @dev_draw_new_read(@nt* nt, U8* data)
|
||||
{
|
||||
SET_MSGS
|
||||
|
||||
U32 read_size = 144;
|
||||
|
||||
I64 i;
|
||||
U8 newbuf[144];
|
||||
U8 intbuf[16];
|
||||
U8 pathbuf[128];
|
||||
U8* chanstr = "x8r8g8b8";
|
||||
JsonObject* tmpr;
|
||||
I64 conn = nt->drawobjs->length + 1;
|
||||
|
||||
JsonObject* dobj = Json.CreateObject(nt->main_task);
|
||||
dobj->set("conn", conn, JSON_NUMBER);
|
||||
dobj->set("imageid", 0, JSON_NUMBER);
|
||||
dobj->set("chan", chanstr, JSON_STRING);
|
||||
dobj->set("r", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
||||
dobj->set("clipr", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
||||
|
||||
tmpr = dobj->o("r");
|
||||
tmpr->set("x0", 0, JSON_NUMBER);
|
||||
tmpr->set("y0", 0, JSON_NUMBER);
|
||||
tmpr->set("x1", GR_WIDTH, JSON_NUMBER);
|
||||
tmpr->set("y1", GR_HEIGHT, JSON_NUMBER);
|
||||
|
||||
tmpr = dobj->o("clipr");
|
||||
tmpr->set("x0", 0, JSON_NUMBER);
|
||||
tmpr->set("y0", 0, JSON_NUMBER);
|
||||
tmpr->set("x1", GR_WIDTH, JSON_NUMBER);
|
||||
tmpr->set("y1", GR_HEIGHT, JSON_NUMBER);
|
||||
|
||||
dobj->set("imgs", Json.CreateObject(nt->main_task), JSON_OBJECT);
|
||||
|
||||
// Insert new draw object [/dev/draw/[conn#] to nt->drawobjs]
|
||||
StrPrint(intbuf, "%d", conn);
|
||||
nt->drawobjs->set(intbuf, dobj, JSON_OBJECT);
|
||||
|
||||
// Create path objects
|
||||
StrPrint(pathbuf, "/dev/draw/%d", conn);
|
||||
@nt_qid_create(nt, pathbuf, NT_IS_DIR);
|
||||
StrPrint(pathbuf, "/dev/draw/%d/data", conn);
|
||||
@nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||||
StrPrint(pathbuf, "/dev/draw/%d/refresh", conn);
|
||||
@nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||||
|
||||
// ** not yet implemented
|
||||
// StrPrint(pathbuf, "/dev/draw/%d/colormap", conn);
|
||||
// @nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||||
// StrPrint(pathbuf, "/dev/draw/%d/ctl", conn);
|
||||
// @nt_qid_create(nt, pathbuf, NT_IS_FILE);
|
||||
|
||||
// *** Build payload for Rread
|
||||
|
||||
// Default; set all fields to 0
|
||||
MemSet(newbuf, ' ', read_size);
|
||||
for (i = 0; i < 12; i++) {
|
||||
newbuf[10 + (12 * i)] = '0';
|
||||
}
|
||||
|
||||
// Set connection number
|
||||
StrPrint(intbuf, "%d", conn);
|
||||
MemCpy(newbuf + 11 - StrLen(intbuf), intbuf, StrLen(intbuf));
|
||||
|
||||
// Set chan string
|
||||
MemCpy(newbuf + 11 - StrLen(chanstr) + (12 * 2), chanstr, StrLen(chanstr));
|
||||
|
||||
// Set max.x of display image and clipping rect
|
||||
StrPrint(intbuf, "%d", GR_WIDTH);
|
||||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 6), intbuf, StrLen(intbuf));
|
||||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 10), intbuf, StrLen(intbuf));
|
||||
|
||||
// Set max.y of display image and clipping rect
|
||||
StrPrint(intbuf, "%d", GR_HEIGHT);
|
||||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 7), intbuf, StrLen(intbuf));
|
||||
MemCpy(newbuf + 11 - StrLen(intbuf) + (12 * 11), intbuf, StrLen(intbuf));
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + 4);
|
||||
MemCpy(nt->out + (4 + 1 + 2 + 4), newbuf, read_size);
|
||||
*(nt->out + (4 + 1 + 2))(U32*) = read_size;
|
||||
Rmsg->length += read_size;
|
||||
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
U0 @nt_Rread_dir(@nt* nt, U8* data, @9p_qid * qid)
|
||||
{
|
||||
SET_MSGS
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + 4);
|
||||
|
||||
if (test_read_cnt) {
|
||||
*(nt->out + (4 + 1 + 2))(U32*) = 0;
|
||||
SEND_RMSG
|
||||
return;
|
||||
}
|
||||
|
||||
U32 read_size = test_entry_size;
|
||||
MemCpy(nt->out + (4 + 1 + 2 + 4), test_entry, read_size);
|
||||
|
||||
*(nt->out + (4 + 1 + 2))(U32*) = read_size;
|
||||
Rmsg->length += read_size;
|
||||
SEND_RMSG
|
||||
|
||||
test_read_cnt++;
|
||||
}
|
||||
|
||||
// @9p_msg * Rmsg = nt->out;
|
||||
//
|
||||
// if (ev) {
|
||||
// Rmsg->length = 0x0e;
|
||||
// Rmsg->type = TREAD + 1; // RREAD
|
||||
// Rmsg->tag = nt->kbd_read_tag;
|
||||
// MemCpy(nt->out + (4 + 1 + 2), ev, 7);
|
||||
// // nt->kbd_read_tag = NULL;
|
||||
// nt->kbd_last_jiffies = cnts.jiffies;
|
||||
// nt->s->send(Rmsg, Rmsg->length);
|
||||
// Free(ev);
|
||||
// }
|
||||
|
||||
U0 @nt_Tread(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/read.html
|
||||
|
||||
// size[4] Tread tag[2] fid[4] offset[8] count[4]
|
||||
// size[4] Rread tag[2] count[4] data[count]
|
||||
|
||||
SET_MSGS
|
||||
|
||||
U32 _fid = *(data + (4 + 1 + 2))(U32*);
|
||||
U64 offset = *(data + (4 + 1 + 2 + 4))(U64*);
|
||||
U32 count = *(data + (4 + 1 + 2 + 4 + 8))(U32*);
|
||||
|
||||
//@nt_tx_dbg(nt, "Tread fid: %d, offset: %d, count: %d", fid, offset, count);
|
||||
|
||||
U8 fidbuf[16];
|
||||
StrPrint(fidbuf, "%d", _fid);
|
||||
|
||||
JsonObject* fid = nt->fids->o(fidbuf);
|
||||
|
||||
if (!fid)
|
||||
return;
|
||||
|
||||
@9p_qid * qid = fid->@("qid");
|
||||
|
||||
if (!qid)
|
||||
return;
|
||||
|
||||
I64 read_count = fid->@("read_count");
|
||||
|
||||
if (qid) {
|
||||
switch (qid->type) {
|
||||
case NT_IS_DIR:
|
||||
if (!StrCmp(qid->path, "/dev")) {
|
||||
@nt_Rread_dir(nt, data, qid);
|
||||
return;
|
||||
}
|
||||
//@nt_tx_dbg(nt, "got read on dir: %s", qid->path);
|
||||
break;
|
||||
default:
|
||||
if (!StrCmp(qid->path, "/dev/kbd")) {
|
||||
nt->kbd_read_tag = Tmsg->tag;
|
||||
//@nt_tx_dbg(nt, "Set nt->kbd_read_tag: 0x%04x", Tmsg->tag);
|
||||
}
|
||||
if (!StrCmp(qid->path, "/dev/draw/new")) {
|
||||
if (read_count) {
|
||||
@nt_Rerror(nt, data, "unknown id for draw image");
|
||||
} else {
|
||||
@dev_draw_new_read(nt, data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
read_count++;
|
||||
fid->set("read_count", read_count, JSON_NUMBER);
|
||||
}
|
||||
|
||||
U0 @nt_Twrite(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/read.html
|
||||
|
||||
// size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count]
|
||||
// size[4] Rwrite tag[2] count[4]
|
||||
|
||||
SET_MSGS
|
||||
|
||||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||||
U64 offset = *(data + (4 + 1 + 2 + 4))(U64*);
|
||||
U32 count = *(data + (4 + 1 + 2 + 4 + 8))(U32*);
|
||||
U8* p = data + (4 + 1 + 2 + 4 + 8 + 4);
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + 4);
|
||||
//@nt_tx_dbg(nt, "Twrite fid: %d, offset: %d, count: %d", fid, offset, count);
|
||||
|
||||
U8 fidbuf[16];
|
||||
U8 errmsgbuf[256];
|
||||
StrPrint(fidbuf, "%d", fid);
|
||||
@9p_qid * qid = nt->fids->o(fidbuf)->@("qid");
|
||||
|
||||
I64 i;
|
||||
|
||||
if (qid) {
|
||||
if (String.BeginsWith("/dev/draw", qid->path) && String.EndsWith("/data", qid->path)) {
|
||||
}
|
||||
if (!StrCmp(qid->path, "/dev/draw/1/data")) {
|
||||
@nt_draw(nt, data, qid);
|
||||
}
|
||||
if (!StrCmp(qid->path, "/dev/cons")) {
|
||||
for (i = 0; i < count; i++) {
|
||||
DocPrint(nt->main_task->put_doc, "%c", p[i]);
|
||||
}
|
||||
}
|
||||
if (!StrCmp(qid->path, "/dev/mousectl")) {
|
||||
p[count] = NULL;
|
||||
StrPrint(errmsgbuf, "unknown control message \"%s\"", p);
|
||||
@nt_Rerror(nt, data, errmsgbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
//@nt_tx_dbg(nt, "got write for path: %s", qid->path);
|
||||
}
|
||||
|
||||
*(nt->out + (4 + 1 + 2))(U32*) = count;
|
||||
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
U0 @nt_Tflush(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/flush.html
|
||||
|
||||
// size[4] Tflush tag[2] oldtag[2]
|
||||
// size[4] Rflush tag[2]
|
||||
|
||||
SET_MSGS
|
||||
|
||||
Rmsg->length = (4 + 1 + 2);
|
||||
SEND_RMSG
|
||||
}
|
||||
|
||||
U0 @nt_Tstat(@nt* nt, U8* data)
|
||||
{
|
||||
// https://9fans.github.io/plan9port/man/man9/stat.html
|
||||
|
||||
// size[4] Tstat tag[2] fid[4]
|
||||
// size[4] Rstat tag[2] stat[n]
|
||||
|
||||
// The reply will contain a machine-independent directory entry, stat, laid out as follows:
|
||||
// size[2]total byte count of the following data
|
||||
// type[2]for kernel use
|
||||
// dev[4]for kernel use
|
||||
// qid.type[1]
|
||||
// the type of the file (directory, etc.), represented as a bit vector corresponding to the high 8 bits of the file’s mode word.
|
||||
// qid.vers[4]
|
||||
// version number for given path
|
||||
// qid.path[8]
|
||||
// the file server’s unique identification for the file
|
||||
// mode[4]
|
||||
// permissions and flags
|
||||
// atime[4]
|
||||
// last access time
|
||||
// mtime[4]
|
||||
// last modification time
|
||||
// length[8]
|
||||
// length of file in bytes
|
||||
// name[ s ]
|
||||
// file name; must be / if the file is the root directory of the server
|
||||
// uid[ s ]owner name
|
||||
// gid[ s ]group name
|
||||
// muid[ s ]
|
||||
// name of the user who last modified the file
|
||||
|
||||
SET_MSGS
|
||||
|
||||
U32 fid = *(data + (4 + 1 + 2))(U32*);
|
||||
|
||||
Rmsg->length = (4 + 1 + 2 + sizeof(@9p_stat)); // set initial Rmsg length
|
||||
//@nt_tx_dbg(nt, "Tstat fid: %d", fid);
|
||||
// PressAKey;
|
||||
|
||||
U8 fidbuf[16];
|
||||
StrPrint(fidbuf, "%d", fid);
|
||||
|
||||
@9p_qid * qid = nt->fids->o(fidbuf)->@("qid");
|
||||
|
||||
@9p_stat * stat = nt->out + (4 + 1 + 2);
|
||||
stat->size = sizeof(@9p_stat) - 2;
|
||||
stat->type = 0;
|
||||
stat->dev = 0;
|
||||
MemCpy(&stat->qid, qid, sizeof(@9p_qid));
|
||||
stat->atime = 0;
|
||||
stat->mtime = 0;
|
||||
stat->length = 1024;
|
||||
|
||||
// add strings
|
||||
U8* p = NULL;
|
||||
U8* user = "alec";
|
||||
|
||||
// name[ s ]
|
||||
p = nt->out + Rmsg->length;
|
||||
U8* path = qid->path;
|
||||
if (StrCmp(path, "/")) {
|
||||
path = StrLastOcc(path, "/") + 1;
|
||||
}
|
||||
*(p)(U16*) = StrLen(path);
|
||||
p += 2;
|
||||
MemCpy(p, path, StrLen(path));
|
||||
p += StrLen(path);
|
||||
stat->size += StrLen(path) + 2;
|
||||
Rmsg->length += StrLen(path) + 2;
|
||||
|
||||
// uid[ s ]owner name
|
||||
p = nt->out + Rmsg->length;
|
||||
*(p)(U16*) = StrLen(user);
|
||||
p += 2;
|
||||
MemCpy(p, user, StrLen(user));
|
||||
p += StrLen(user);
|
||||
stat->size += StrLen(user) + 2;
|
||||
Rmsg->length += StrLen(user) + 2;
|
||||
|
||||
// uid[ s ]group name
|
||||
p = nt->out + Rmsg->length;
|
||||
*(p)(U16*) = StrLen(user);
|
||||
p += 2;
|
||||
MemCpy(p, user, StrLen(user));
|
||||
p += StrLen(user);
|
||||
stat->size += StrLen(user) + 2;
|
||||
Rmsg->length += StrLen(user) + 2;
|
||||
|
||||
// muid[ s ]
|
||||
p = nt->out + Rmsg->length;
|
||||
*(p)(U16*) = StrLen(user);
|
||||
p += 2;
|
||||
MemCpy(p, user, StrLen(user));
|
||||
p += StrLen(user);
|
||||
stat->size += StrLen(user) + 2;
|
||||
Rmsg->length += StrLen(user) + 2;
|
||||
|
||||
SEND_RMSG
|
||||
}
|
||||
Reference in New Issue
Block a user