2019-01-04 02:50:49 +01:00
|
|
|
/* RETRO ------------------------------------------------------
|
2018-10-01 16:56:49 +02:00
|
|
|
A personal, minimalistic forth
|
2020-11-02 14:25:54 +01:00
|
|
|
Copyright (c) 2016 - 2020 Charles Childers
|
|
|
|
|
|
|
|
This is a minimalist implementation of an interactive
|
|
|
|
RETRO system with an embedded image and the listerner loop
|
|
|
|
being written in RETRO.
|
|
|
|
|
|
|
|
Building:
|
|
|
|
|
|
|
|
cp ngaImage barebones.image
|
|
|
|
retro-extend barebones.image interface/barebones.retro
|
|
|
|
retro-embedimage barebones.image >vm/nga-c/barebones_image.c
|
|
|
|
cd vm/nga-c
|
|
|
|
make barebones
|
2019-01-04 02:50:49 +01:00
|
|
|
---------------------------------------------------------- */
|
2018-10-01 16:56:49 +02:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
2019-09-23 17:11:56 +02:00
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
#define CELL int32_t
|
|
|
|
#define CELL_MIN INT_MIN + 1
|
|
|
|
#define CELL_MAX INT_MAX - 1
|
2018-10-01 16:56:49 +02:00
|
|
|
|
2019-03-26 20:55:06 +01:00
|
|
|
#define IMAGE_SIZE 242000 /* Amount of RAM. 968kB by default. */
|
|
|
|
#define ADDRESSES 256 /* Depth of address stack */
|
2018-10-01 16:56:49 +02:00
|
|
|
#define STACK_DEPTH 128 /* Depth of data stack */
|
|
|
|
|
|
|
|
CELL memory[IMAGE_SIZE + 1]; /* The memory for the image */
|
|
|
|
|
2021-02-15 19:45:48 +01:00
|
|
|
#define TOS cpu.data[cpu.sp] /* Shortcut for top item on stack */
|
|
|
|
#define NOS cpu.data[cpu.sp-1] /* Shortcut for second item on stack */
|
|
|
|
#define TORS cpu.address[cpu.rp] /* Shortcut for top item on address stack */
|
|
|
|
|
|
|
|
struct NgaCore {
|
|
|
|
CELL sp, rp, ip; /* Stack & instruction pointers */
|
|
|
|
CELL data[STACK_DEPTH]; /* The data stack */
|
|
|
|
CELL address[ADDRESSES]; /* The address stack */
|
|
|
|
} cpu;
|
2018-10-01 16:56:49 +02:00
|
|
|
|
2018-11-22 03:16:41 +01:00
|
|
|
#define NUM_DEVICES 2
|
|
|
|
|
|
|
|
typedef void (*Handler)(void);
|
|
|
|
|
|
|
|
Handler IO_deviceHandlers[NUM_DEVICES + 1];
|
|
|
|
Handler IO_queryHandlers[NUM_DEVICES + 1];
|
|
|
|
|
2018-10-01 16:56:49 +02:00
|
|
|
#include "barebones_image.c"
|
|
|
|
|
|
|
|
CELL stack_pop();
|
|
|
|
void stack_push(CELL value);
|
|
|
|
void execute(CELL cell);
|
2020-11-02 14:25:54 +01:00
|
|
|
CELL load_image();
|
|
|
|
void prepare_vm();
|
|
|
|
void process_opcode(CELL opcode);
|
|
|
|
void process_opcode_bundle(CELL opcode);
|
|
|
|
int validate_opcode_bundle(CELL opcode);
|
2018-10-01 16:56:49 +02:00
|
|
|
|
|
|
|
CELL stack_pop() {
|
2021-02-15 19:45:48 +01:00
|
|
|
cpu.sp--;
|
|
|
|
return cpu.data[cpu.sp + 1];
|
2018-10-01 16:56:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void stack_push(CELL value) {
|
2021-02-15 19:45:48 +01:00
|
|
|
cpu.sp++;
|
|
|
|
cpu.data[cpu.sp] = value;
|
2018-10-01 16:56:49 +02:00
|
|
|
}
|
|
|
|
|
2018-11-22 03:16:41 +01:00
|
|
|
void generic_output() {
|
|
|
|
putc(stack_pop(), stdout);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void generic_output_query() {
|
|
|
|
stack_push(0);
|
|
|
|
stack_push(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void generic_input() {
|
|
|
|
stack_push(getc(stdin));
|
|
|
|
if (TOS == 127) TOS = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
void generic_input_query() {
|
|
|
|
stack_push(0);
|
|
|
|
stack_push(1);
|
|
|
|
}
|
2018-10-01 16:56:49 +02:00
|
|
|
|
|
|
|
void execute(CELL cell) {
|
|
|
|
CELL opcode;
|
2021-02-15 19:45:48 +01:00
|
|
|
cpu.rp = 1;
|
|
|
|
cpu.ip = cell;
|
|
|
|
while (cpu.ip < IMAGE_SIZE) {
|
|
|
|
opcode = memory[cpu.ip];
|
2020-11-02 14:25:54 +01:00
|
|
|
if (validate_opcode_bundle(opcode) != 0) {
|
|
|
|
process_opcode_bundle(opcode);
|
2018-10-01 16:56:49 +02:00
|
|
|
} else {
|
2018-11-22 03:16:41 +01:00
|
|
|
printf("Invalid instruction!\n");
|
|
|
|
exit(1);
|
2018-10-01 16:56:49 +02:00
|
|
|
}
|
2021-02-15 19:45:48 +01:00
|
|
|
cpu.ip++;
|
|
|
|
if (cpu.rp == 0)
|
|
|
|
cpu.ip = IMAGE_SIZE;
|
2018-10-01 16:56:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
2018-11-22 03:16:41 +01:00
|
|
|
IO_deviceHandlers[0] = generic_output;
|
|
|
|
IO_deviceHandlers[1] = generic_input;
|
|
|
|
IO_queryHandlers[0] = generic_output_query;
|
|
|
|
IO_queryHandlers[1] = generic_input_query;
|
2020-11-02 14:25:54 +01:00
|
|
|
prepare_vm();
|
|
|
|
load_image();
|
2018-10-01 16:56:49 +02:00
|
|
|
execute(0);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2020-11-02 14:44:56 +01:00
|
|
|
#include "nga.c"
|