some more
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* NRJ (NOR and Reference Jump) OISC ANSI C emulator
|
* NRJ (NOR and Reference Jump) OISC ANSI C emulator
|
||||||
* Created by Luxferre, 2022, public domain
|
* Created by Luxferre, 2022, public domain
|
||||||
* Build with: cc -Os -o nrj nrj.c
|
* Build with: cc -Os -std=c89 -o nrj nrj.c
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#ifndef NRJWORD /* we emulate NRJ16 by default */
|
#ifndef NRJWORD /* we emulate NRJ16 by default but this can be overridden */
|
||||||
#define NRJWORD unsigned short
|
#define NRJWORD unsigned short
|
||||||
#endif
|
#endif
|
||||||
#define NRJWSIZE (sizeof(NRJWORD) << 3)
|
#define NRJWSIZE (sizeof(NRJWORD) << 3)
|
||||||
@@ -25,11 +25,8 @@ int kbhit() { /* our best attempt to detect a keypress on a POSIX system */
|
|||||||
|
|
||||||
void nrj_in(NRJWORD *ctxid, NRJWORD *val) { /* context-dependent input handler */
|
void nrj_in(NRJWORD *ctxid, NRJWORD *val) { /* context-dependent input handler */
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
if(*ctxid == (NRJWORD) 0) { /* for now, only emulate standard context id */
|
if(*ctxid == (NRJWORD) 0) /* for now, only emulate standard context id */
|
||||||
*val = (NRJWORD) 0;
|
*val = (NRJWORD) ((kbhit() && read(0, &c, 1) > -1) ? c : 0);
|
||||||
if(kbhit() && read(0, &c, 1) > -1)
|
|
||||||
*val = (NRJWORD) c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nrj_out(NRJWORD *ctxid, NRJWORD *val) { /* context-dependent output handler */
|
void nrj_out(NRJWORD *ctxid, NRJWORD *val) { /* context-dependent output handler */
|
||||||
@@ -39,42 +36,38 @@ void nrj_out(NRJWORD *ctxid, NRJWORD *val) { /* context-dependent output handler
|
|||||||
|
|
||||||
void nrj_run(NRJWORD *mem, NRJWORD pc) { /* Main NRJ engine - just 12 lines of C within this function */
|
void nrj_run(NRJWORD *mem, NRJWORD pc) { /* Main NRJ engine - just 12 lines of C within this function */
|
||||||
while(pc != MAXADDR) { /* halt if jumped to the last word */
|
while(pc != MAXADDR) { /* halt if jumped to the last word */
|
||||||
if(mem[0]) { /* handle input if the first word is set, and clear it */
|
if(mem[0]) { /* handle input if word 0 is set */
|
||||||
nrj_in(&mem[2], &mem[mem[0]]);
|
nrj_in(&mem[2], &mem[mem[0]]); /* input a value to the location specified in word 0 */
|
||||||
mem[0] = (NRJWORD) 0;
|
mem[0] = (NRJWORD) 0; /* clear word 0 */
|
||||||
}
|
}
|
||||||
mem[mem[pc]] = (~(mem[mem[pc]] | mem[mem[pc+1]])) & MAXADDR; /* then perform the NOR operation */
|
mem[mem[pc]] = (~(mem[mem[pc]] | mem[mem[pc+1]])) & MAXADDR; /* then perform the NOR operation */
|
||||||
pc = mem[mem[pc+2]]; /* then perform the reference jump operation */
|
pc = mem[mem[pc+2]]; /* then perform the reference jump operation */
|
||||||
if(mem[1]) { /* then handle output if the second word is set, and clear it */
|
if(mem[1]) { /* then handle output if word 1 is set */
|
||||||
nrj_out(&mem[2], &mem[mem[1]]);
|
nrj_out(&mem[2], &mem[mem[1]]); /* output the value from the location specified in word 1 */
|
||||||
mem[1] = (NRJWORD) 0;
|
mem[1] = (NRJWORD) 0; /* clear word 1 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* terminal helper definitions */
|
||||||
struct termios tty_opts_backup, tty_opts_raw;
|
struct termios tty_opts_backup, tty_opts_raw;
|
||||||
void restore_term() {
|
void restore_term() {tcsetattr(0, TCSANOW, &tty_opts_backup);}
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_backup);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) { /* emulator entry point: nrj program.bin */
|
||||||
if(argc > 1) {
|
if(argc > 1) {
|
||||||
NRJWORD mem[NRJSIZE]; /* NRJ memory: word 0 - input, 1 - output, 2 - I/O context, 3 - program start */
|
NRJWORD mem[NRJSIZE]; /* NRJ memory: word 0 - input, 1 - output, 2 - I/O context, 3 - program start */
|
||||||
FILE *prog = fopen(argv[1], "rb");
|
FILE *prog = fopen(argv[1], "rb");
|
||||||
if(prog) {
|
if(prog) { /* load the program and prepare the terminal */
|
||||||
/* load the program */
|
|
||||||
fseek(prog, 0, SEEK_END);
|
fseek(prog, 0, SEEK_END);
|
||||||
int flen = ftell(prog);
|
int flen = ftell(prog);
|
||||||
fseek(prog, 0, SEEK_SET);
|
fseek(prog, 0, SEEK_SET);
|
||||||
fread(mem, sizeof(NRJWORD), (flen/sizeof(NRJWORD)) & MAXADDR, prog);
|
fread(mem, sizeof(NRJWORD), (flen/sizeof(NRJWORD)) & MAXADDR, prog);
|
||||||
fclose(prog);
|
fclose(prog);
|
||||||
/* prepare the terminal */
|
tcgetattr(0, &tty_opts_backup);
|
||||||
tcgetattr(STDIN_FILENO, &tty_opts_backup);
|
|
||||||
atexit(&restore_term);
|
atexit(&restore_term);
|
||||||
cfmakeraw(&tty_opts_raw);
|
cfmakeraw(&tty_opts_raw);
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw);
|
tcsetattr(0, TCSANOW, &tty_opts_raw);
|
||||||
/* start the engine */
|
nrj_run(mem, 3); /* now, start the engine */
|
||||||
nrj_run(mem, 3);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("NRJ%u: could not open the input file %s\r\n", (unsigned int) NRJWSIZE, argv[1]);
|
printf("NRJ%u: could not open the input file %s\r\n", (unsigned int) NRJWSIZE, argv[1]);
|
||||||
|
|||||||
Reference in New Issue
Block a user