Files
neinterm/NeinTerm.HC
2025-10-07 10:51:07 -04:00

254 lines
6.5 KiB
HolyC

#define @nt_process_debug Print
Bool @nt_window_is_hovered(CTask* task)
{
return (task == sys_focus_task && ms.pos.x >= task->pix_left && ms.pos.x <= task->pix_right && ms.pos.y >= task->pix_top && ms.pos.y <= task->pix_bottom);
}
U0 @nt_draw_it(CTask* task, CDC* dc)
{
GrBlot(dc, 0, 0, task->user_data(@nt*)->screen);
@nt* nt = task->user_data;
if (@nt_window_is_hovered(task)) {
gr.fp_draw_ms = NULL;
GrBlot(dc, ms.pos.x - task->pix_left, ms.pos.y - task->pix_top, nt->cursor);
} else {
gr.fp_draw_ms = &DrawStdMs;
}
}
U0 @nt_rx_loop(@nt* nt)
{
// Make tcp connection to cpu server and send the connect script
nt->s = @tcp_socket_create(nt->host, nt->port);
while (nt->s->state != TCP_SOCKET_STATE_ESTABLISHED) {
Sleep(1);
}
nt->s->send(nt->connect_script, StrLen(nt->connect_script));
U8* request = NULL;
@9p_msg * msg = NULL;
U8* buf = CAlloc(NT_BUF_SIZE, nt->main_task);
I64 len = 0;
I64 pos = 0;
I64 base = 0;
U32 request_length = 0;
// Export 9P filesystem, loop and receive Trequests
while (1) {
pos = 0;
base = 0;
len = nt->s->receive(buf + base, 1024);
nt_rx_queue_next_request:
msg = buf + base;
// If request length > data received length, keep receiving
while (msg->length > len) {
pos = len;
len += nt->s->receive(buf + base + pos, 1024);
}
// Insert request into rx_fifo
request = CAlloc(msg->length, nt->main_task);
// @nt_rx_dbg(nt, "fifo ins: len: %04d\ttype: %s\ttag: 0x%04x", msg->length, @nt_msg_type_string(msg->type), msg->tag);
MemCpy(request, buf + base, msg->length);
FifoI64Ins(nt->rx_fifo, request);
// If we have more data, queue next request
if (msg->length < len) {
base += msg->length;
len -= msg->length;
pos = 0;
goto nt_rx_queue_next_request;
}
Sleep(1);
}
}
U0 @nt_dbg_loop(@nt* nt)
{
@nt_dbg_msg* msg = NULL;
while (1) {
while (FifoI64Cnt(nt->rx_dbg_fifo)) {
FifoI64Rem(nt->rx_dbg_fifo, &msg);
@nt_dbg_out(msg);
}
while (FifoI64Cnt(nt->tx_dbg_fifo)) {
FifoI64Rem(nt->tx_dbg_fifo, &msg);
@nt_dbg_out(msg);
}
Sleep(1);
}
}
U0 @nt_process_one(@nt* nt)
{
if (!FifoI64Cnt(nt->rx_fifo))
return;
U8* request = NULL;
FifoI64Rem(nt->rx_fifo, &request);
@9p_msg * msg = request;
@9p_debug_dump(msg, msg->length, 0);
//@nt_tx_dbg(nt, "fifo rem: len: %04d\ttype: %s\ttag: 0x%04x", msg->length, @nt_msg_type_string(msg->type), msg->tag);
switch (msg->type) {
case TVERSION:
@nt_Tversion(nt, msg);
break;
case TATTACH:
@nt_Tattach(nt, msg);
break;
case TWALK:
@nt_Twalk(nt, msg);
break;
case TOPEN:
@nt_Topen(nt, msg);
break;
case TCLUNK:
@nt_Tclunk(nt, msg);
break;
case TREAD:
@nt_Tread(nt, msg);
break;
case TWRITE:
@nt_Twrite(nt, msg);
break;
case TFLUSH:
@nt_Tflush(nt, msg);
break;
case TSTAT:
@nt_Tstat(nt, msg);
break;
default:
@nt_tx_dbg(nt, "unimplemented request -");
PressAKey;
break;
}
Free(request);
}
U0 @nt_process_kbd(@nt* nt)
{
// Process keyboard events
if (!nt->kbd_read_tag)
return;
if (cnts.jiffies < nt->kbd_last_jiffies + 80)
return;
if (!FifoI64Cnt(nt->kbd_fifo))
return;
U8* ev = NULL;
FifoI64Rem(nt->kbd_fifo, &ev);
@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_tx_loop(@nt* nt)
{
while (1) {
@nt_process_one(nt);
@nt_process_kbd(nt);
Sleep(1);
}
}
U0 @nt_create_qids(@nt* nt)
{
@nt_qid_create(nt, "/", NT_IS_DIR);
@nt_qid_create(nt, "/dev", NT_IS_DIR);
@nt_qid_create(nt, "/dev/cons", NT_IS_FILE);
@nt_qid_create(nt, "/dev/draw", NT_IS_DIR);
@nt_qid_create(nt, "/dev/draw/new", NT_IS_FILE);
@nt_qid_create(nt, "/dev/kbd", NT_IS_FILE);
@nt_qid_create(nt, "/dev/cursor", NT_IS_FILE);
@nt_qid_create(nt, "/dev/mouse", NT_IS_FILE);
//@nt_qid_create(nt, "/dev/mousectl", NT_IS_FILE);
//@nt_qid_create(nt, "/dev/mousein", NT_IS_FILE);
}
@nt* @nt_new(U8* host, I64 port)
{
@nt* nt = CAlloc(sizeof(@nt));
nt->cursor = @nt_cursor;
nt->screen = DCNew(GR_WIDTH, GR_HEIGHT);
DCFill(nt->screen, TRANSPARENT);
nt->main_task = Fs;
nt->main_task->user_data = nt;
nt->host = StrNew(host);
nt->out = CAlloc(NT_BUF_SIZE);
nt->rx_fifo = FifoI64New(NT_FIFO_SIZE);
nt->rx_dbg_fifo = FifoI64New(NT_FIFO_SIZE);
nt->tx_dbg_fifo = FifoI64New(NT_FIFO_SIZE);
nt->kbd_fifo = FifoI64New(NT_FIFO_SIZE);
nt->port = port;
nt->drawobjs = Json.CreateObject(nt->main_task);
nt->fids = Json.CreateObject(nt->main_task);
nt->qids = Json.CreateObject(nt->main_task);
nt->connect_script = FileRead("M:/script.rc");
StrCpy(nt->main_task->task_title, "NeinTerm");
nt->dbg_task = Spawn(&@nt_dbg_loop, nt, "NeinTerm DbgTask");
nt->rx_task = Spawn(&@nt_rx_loop, nt, "NeinTerm RxTask");
nt->tx_task = Spawn(&@nt_tx_loop, nt, "NeinTerm TxTask");
nt->main_task->draw_it = &@nt_draw_it;
@nt_create_qids(nt);
return nt;
}
U0 NeinTerm(U8* host, I64 port)
{
@nt* nt = @nt_new(host, port);
I64 ch, sc, code;
U8* ev;
while (1) {
code = ScanMsg(&ch, &sc);
if (!ch) {
switch (sc & 0xff) {
case SC_DELETE:
ch = 0x7f;
break;
default:
break;
}
}
if (ch) {
switch (code) {
case MSG_KEY_DOWN:
ev = CAlloc(8, nt->main_task);
ev[0] = 3;
ev[4] = 0x72;
ev[5] = ch;
FifoI64Ins(nt->kbd_fifo, ev);
break;
case MSG_KEY_UP:
ev = CAlloc(8, nt->main_task);
ev[0] = 3;
ev[4] = 0x52;
ev[5] = ch;
FifoI64Ins(nt->kbd_fifo, ev);
break;
}
}
Sleep(10);
}
}