#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); } }