#include "sux.h" #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) #define DEFAULT(a, b) (a) = (a) ? (a) : (b) char *key = NULL; uint8_t key_idx = 0; uint8_t esc = 0; uint8_t iscsi = 0; typedef struct escape escape; struct escape { char buf[128]; /* Buffer. */ size_t len; /* Buffer length. */ int arg[16]; /* Arguments. */ int narg; /* Number of arguments. */ char mode[2]; /* Mode type. */ }; escape escseq; static inline char *get_keyseq(int keycode) { switch (keycode) { case KEY_BACKSPACE: return "\b"; case KEY_UP : return "\x1B[A"; case KEY_DOWN : return "\x1B[B"; case KEY_RIGHT : return "\x1B[C"; case KEY_LEFT : return "\x1B[D"; case KEY_F( 1) : return "\x1BOP"; case KEY_F( 2) : return "\x1BOQ"; case KEY_F( 3) : return "\x1BOR"; case KEY_F( 4) : return "\x1BOS"; case KEY_F( 5) : return "\x1B[15~"; case KEY_F( 6) : return "\x1B[17~"; case KEY_F( 7) : return "\x1B[18~"; case KEY_F( 8) : return "\x1B[19~"; case KEY_F( 9) : return "\x1B[20~"; case KEY_F(10) : return "\x1B[21~"; case KEY_F(11) : return "\x1B[23~"; case KEY_F(12) : return "\x1B[24~"; default : return NULL; } } int get_key(WINDOW *scr) { int x, y; int c; int keycode = 0; int tmp_flag = dbg_print_per_inst; curs_set(1); if ((key == NULL) || (key && key[key_idx] == '\0') || !kbd_rdy) { c = wgetch(scr); if (c == 19) { if (kbd_rdy) { c = wgetch(scr); } step = 1; } else if (c == 0x11) { end = 1; } if (kbd_rdy) { key_idx = 0; key = get_keyseq(c); } keycode = c; } if (kbd_rdy) { c = (key != NULL) ? key[key_idx++] : c; } if (step) { if (keycode != 19 && keycode != 18 && keycode != 0x11 && !isalnum(keycode)) { /*WINDOW *w; int maxcol = getmaxx(scr)/2; int maxrow = getmaxy(scr)/2;*/ switch (keycode) { case KEY_F(1): /*w = newwin(maxrow, maxcol, maxrow, maxcol); emumon(w); delwin(w);*/ endwin(); puts("Starting asmmon()"); asmmon("stdin"); puts("Reinitializing screen."); init_scr(); wrefresh(scr); #if debug wrefresh(regs); #endif break; case KEY_F(3): dbg_print_per_inst = !dbg_print_per_inst; } #if debug && !bench getyx(scr, y, x); wmove(scr, getmaxy(scr)-1, 0); wclrtoeol(scr); wprintw(scr, "keycode: %i", keycode); if (tmp_flag != dbg_print_per_inst) { wprintw(scr, ", Disassemble per instruction %s", (dbg_print_per_inst) ? "enabled" : "disabled"); } wmove(scr, y, x); #endif } } if (kbd_rdy) { switch (c) { case ERR: addr[CTRL_ADDR] = 0; break; case '\0': break; default: if (kbd_rdy && c < 0x100) { addr[CTRL_ADDR] = 1; #if debug && !bench wmove(scr, getmaxy(scr)-1, 0); wclrtoeol(scr); wprintw(scr, "c: %i ", c); wprintw(scr, "key: "); for (int i = 0; key && key[i] != '\0'; i++) { wprintw(scr, "$%02X%s", key[i], (key[i+1] != '\0') ? ", " : ""); } wmove(scr, y, x); #endif } break; } } else { if (step) { step = !(c == 18); } } addr[STEP_ADDR] = step; curs_set(0); return c; } void parse_esc() { char *str = escseq.buf, *nstr; long int value; escseq.narg = 0; escseq.buf[escseq.len] = '\0'; for (;str < escseq.buf + escseq.len; str++) { nstr = NULL; value = strtol(str, &nstr, 10); if (nstr == str) { value = 0; } if (value == LONG_MAX || value == LONG_MIN) { value = -1; } escseq.arg[escseq.narg++] = value; str = nstr; if (*str != ';' || escseq.narg == 16) { break; } } escseq.mode[0] = *str++; escseq.mode[1] = (str < (escseq.buf + escseq.len)) ? *str : '\0'; } void handle_esc() { int x, y; getyx(scr, y, x); switch (escseq.mode[0]) { case 'A': DEFAULT(escseq.arg[0], 1); if (y-escseq.arg[0] >= 0) { y -= escseq.arg[0]; #if !debug wmove(scr, y, x); #endif } break; case 'B': case 'e': DEFAULT(escseq.arg[0], 1); if (y+escseq.arg[0] <= getmaxy(scr)) { y += escseq.arg[0]; #if !debug wmove(scr, y, x); #endif } break; case 'C': case 'a': DEFAULT(escseq.arg[0], 1); if (x+escseq.arg[0] <= getmaxx(scr)) { x += escseq.arg[0]; #if !debug wmove(scr, y, x); #endif } break; case 'D': DEFAULT(escseq.arg[0], 1); if (x-escseq.arg[0] >= 0) { x -= escseq.arg[0]; #if !debug wmove(scr, y, x); #endif } break; case 'H': case 'f': DEFAULT(escseq.arg[0], 1); DEFAULT(escseq.arg[1], 1); #if !debug wmove(scr, escseq.arg[0]-1, escseq.arg[1]-1); #else wmove(scr, 31, 0); wclrtoeol(scr); wprintw(scr, "escseq.arg[0]: %i, escseq.arg[1]: %i", escseq.arg[0], escseq.arg[1]); #endif break; case 'S': DEFAULT(escseq.arg[0], 1); #if !debug wscrl(scr, -escseq.arg[0]); #else #endif break; case 'T': DEFAULT(escseq.arg[0], 1); #if !debug wscrl(scr, escseq.arg[0]); #else #endif break; } } void reset_esc() { memset(&escseq, 0, sizeof(escseq)); } void handle_ctrlcode(int c) { int x, y; uint16_t scr_col = 0; int tmp_flag = 0; #if debug if (subdbg) { tmp_flag = (addr[TX_ADDR] != 0x0C && addr[TX_ADDR] != '\n' && scr_col < 160); if (!tmp_flag) { wmove(scr, 30, 0); wclrtoeol(scr); } scr_col = (tmp_flag) ? (addr[1] << 1)-2 : 0; wmove(scr, 30, scr_col); } #endif getyx(scr, y, x); switch (c) { case 0xC: x=0,y=0; #if !debug wclear(scr); wmove(scr, y, x); #endif break; case CURSES_BACKSPACE: case '\b': if (x > 0) { x--; #if !debug wmove(scr, y, x); #endif } #if !debug wdelch(scr); #else if (subdbg) { scr_col++; wmove(scr, 30, scr_col--); wdelch(scr); wmove(scr, 30, scr_col); wdelch(scr); } #endif break; case '\033': reset_esc(); esc = 1; break; case '\n': x = 0; y+=1; #if !debug wmove(scr, y, x); #endif break; default: #if !debug /*wmove(scr, y, x);*/ waddch(scr, c); #else if (subdbg && scr_col < 160) { if (c != ' ') { wprintw(scr, "%02X", c); } else { wprintw(scr, " "); } } #endif x+=1; break; } } void io(uint64_t address, uint8_t rw) { /*step |= (!rw) ? (cpu->pc[thread] == CTRL_ADDR) : step;*/ switch (address) { case STEP_ADDR: step = (!rw) ? addr[STEP_ADDR] : step; break; case CTRL_ADDR: if (!rw) { break; } kbd_rdy = 1; wrefresh(scr); #if debug wrefresh(regs); wrefresh(inst_win); wrefresh(dbg_win); #endif addr[RX_ADDR] = get_key(scr); kbd_rdy = 0; break; case TX_ADDR: if (rw) { break; } if (esc) { #if debug if (!subdbg && addr[RX_ADDR] == '\n') { wclrtoeol(scr); } #endif int c = addr[TX_ADDR]; if (iscsi) { escseq.buf[escseq.len++] = c; if (BETWEEN(c, 0x40, 0x7E) || escseq.len >= sizeof(escseq.buf)-1) { esc = 0; iscsi = 0; parse_esc(); handle_esc(); } } if (c == '[') { iscsi = 1; } } else { handle_ctrlcode(addr[TX_ADDR]); } break; } }