/* * NRJ (NOR and Reference Jump) OISC ANSI C emulator by Luxferre * Public domain * Build with: cc -Os -o nrj nrj.c */ #include #include #include #include #include #ifndef NRJWORD #define NRJWORD unsigned short #endif #define NRJWSIZE (sizeof(NRJWORD)) #define NRJSIZE (1 << NRJWSIZE) #define MAXADDR ((NRJWORD) (NRJSIZE - 1)) int kbhit() { struct timeval tv = { 0L, 0L }; fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); return select(1, &fds, NULL, NULL, &tv) > 0; } struct termios tty_opts_backup, tty_opts_raw; void restore_term() { tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_backup); } void nrj_in(NRJWORD *ctxid, NRJWORD *val) { unsigned char c; if(*ctxid == (NRJWORD) 0) { /* for now, only emulate standard context id */ *val = (NRJWORD) 0; if(kbhit()) { if(read(0, &c, 1) > -1) *val = (NRJWORD) c; } } } void nrj_out(NRJWORD *ctxid, NRJWORD *val) { if(*ctxid == (NRJWORD) 0) /* for now, only emulate standard context id */ putchar((unsigned char) *val); } void nrj_run(NRJWORD *mem, NRJWORD pc) { /* 0 - input, 1 - output, 2 - I/O context, 3 - program start */ while(pc != MAXADDR) { if(mem[0]) nrj_in(&mem[2], &mem[mem[0]]); mem[mem[pc]] = (~(mem[mem[pc]] | mem[mem[pc+1]])) & MAXADDR; pc = mem[mem[pc+2]]; mem[0] = (NRJWORD) 0; if(mem[1]) { nrj_out(&mem[2], &mem[mem[1]]); mem[1] = (NRJWORD) 0; } } } int main(int argc, char* argv[]) { if(argc > 1) { NRJWORD mem[NRJSIZE]; FILE *prog = fopen(argv[1], "rb"); if(prog) { /* load the program */ fseek(prog, 0, SEEK_END); int flen = ftell(prog); fseek(prog, 0, SEEK_SET); fread(mem, NRJWSIZE, (flen/NRJWSIZE) & MAXADDR, prog); fclose(prog); /* prepare the terminal */ tcgetattr(STDIN_FILENO, &tty_opts_backup); atexit(&restore_term); cfmakeraw(&tty_opts_raw); tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw); /* start the engine */ nrj_run(mem, 3); } else { printf("NRJ16: could not open the input file %s\r\n", argv[1]); return 1; } } else { puts("NRJ16: no binary specified\r"); return 1; } return 0; }