/* (c) 2021 Aaron Taylor <ataylor at subgeniuskitty dot com> */
/* See LICENSE.txt file for copyright and license details. */
-// TODO:
-// - Write a brief description of the machine being simulated. Only one thread, reduced RAM, no meaningful console when running as screensaver, etc.
-
-// CLI Flags:
-// -path-to-aout-binary
-// -path-to-font-file
-// -speed
-
-// Ideas for sample programs to include:
-// - Build list of integers on the stack (DUP, IM_1, ADD).
-// - Calculate prime numbers, placing them on the stack.
-// - Lights sliding back and forth, like PDP-11 front panel with some OSes.
-
#include "screenhack.h"
#include "simulator.h"
-/* Keep this source code C89 compliant per XScreensaver's instructions. */
-
/* -------------------------------------------------------------------------- */
/* Data Structures */
/* -------------------------------------------------------------------------- */
text;
};
-//static struct color_scheme color_list[] = {
-// // TODO: Explain all this.
-// // TODO: Add other color schemes, like purple PDP-11/70.
-// // TODO: http://www.chdickman.com/pdp8/DECcolors/
-// {
-// {63479,63479,63479}, // 092-XXXX-123
-// { 5140, 2056, 5654}, // 092-XXXX-152
-// {40092,11051,15677}, // 092-XXXX-139
-// {30326,13107,12850}, // 092-XXXX-154
-// {65535,13107,12850}, // homemade
-// {30326,13107,12850}, // 092-XXXX-154
-// { 4112,12850,20046}, // 092-XXXX-145
-// {12336,29555,37008}, // 092-XXXX-151
-// {30326,24158, 6425}, // 092-XXXX-157
-// {63479,63479,63479}, // 092-XXXX-123
-// {63479,63479,63479} // 092-XXXX-123
-// }
-//};
-
static struct color_scheme color_list[] = {
// TODO: Explain all this.
// TODO: Add other color schemes, like purple PDP-11/70.
y_origin += nedsim->origin_y_offset;
x_size *= nedsim->cell_size;
y_size *= nedsim->cell_size;
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, x_origin, y_origin, x_size, y_size);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, x_origin, y_origin, x_size, y_size);
set_color(nedsim, &color_list[nedsim->color_index].border);
if (bord_top) {
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, x_origin, y_origin, x_size, nedsim->border_size);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, x_origin, y_origin, x_size, nedsim->border_size);
}
if (bord_bottom) {
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, x_origin, (y_origin + y_size - nedsim->border_size), x_size, nedsim->border_size);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, x_origin, (y_origin + y_size - nedsim->border_size), x_size, nedsim->border_size);
}
if (bord_left) {
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, x_origin, y_origin, nedsim->border_size, y_size);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, x_origin, y_origin, nedsim->border_size, y_size);
}
if (bord_right) {
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, (x_origin + x_size - nedsim->border_size), y_origin, nedsim->border_size, y_size);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, (x_origin + x_size - nedsim->border_size), y_origin, nedsim->border_size, y_size);
}
}
y -= (0.5 * nedsim->border_size);
// Start angle 0 and ending angle 360*64 is one full circle in Xlib units.
- XFillArc(nedsim->dpy, nedsim->win, nedsim->gc, x, y, diameter, diameter, 0, 360*64);
+ XFillArc(nedsim->dpy, nedsim->panel, nedsim->gc, x, y, diameter, diameter, 0, 360*64);
}
// TODO: Explain
// Draw background color over entire window.
set_color(nedsim, &color_list[nedsim->color_index].panel_bg);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, 0, 0, nedsim->dpy_width, nedsim->dpy_height);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, 0, 0, nedsim->dpy_width, nedsim->dpy_height);
// Draw NED panel in foreground color.
set_color(nedsim, &color_list[nedsim->color_index].panel_fg);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset,
nedsim->origin_y_offset,
nedsim->cell_size * OVERALL_WIDTH_IN_CELLS,
// Give the panel rounded corners by first deleting the four right-angle corners...
set_color(nedsim, &color_list[nedsim->color_index].panel_bg);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset,
nedsim->origin_y_offset,
nedsim->cell_size,
nedsim->cell_size
);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset + (nedsim->cell_size * (OVERALL_WIDTH_IN_CELLS-1)),
nedsim->origin_y_offset,
nedsim->cell_size,
nedsim->cell_size
);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset,
nedsim->origin_y_offset + (nedsim->cell_size * (HEADER_HEIGHT_IN_CELLS + nedsim->num_data_rows + FOOTER_HEIGHT_IN_CELLS - 1)),
nedsim->cell_size,
nedsim->cell_size
);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset + (nedsim->cell_size * (OVERALL_WIDTH_IN_CELLS-1)),
nedsim->origin_y_offset + (nedsim->cell_size * (HEADER_HEIGHT_IN_CELLS + nedsim->num_data_rows + FOOTER_HEIGHT_IN_CELLS - 1)),
nedsim->cell_size,
);
// ...and then replacing them with filled arcs, forming rounded corners.
set_color(nedsim, &color_list[nedsim->color_index].panel_fg);
- XFillArc(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillArc(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset,
nedsim->origin_y_offset,
nedsim->cell_size * 2, nedsim->cell_size * 2,
180*64, -90*64
);
- XFillArc(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillArc(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset + (nedsim->cell_size * (OVERALL_WIDTH_IN_CELLS-2)),
nedsim->origin_y_offset,
nedsim->cell_size * 2, nedsim->cell_size * 2,
0, 90*64
);
- XFillArc(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillArc(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset,
nedsim->origin_y_offset + (nedsim->cell_size * (HEADER_HEIGHT_IN_CELLS + nedsim->num_data_rows + FOOTER_HEIGHT_IN_CELLS - 2)),
nedsim->cell_size * 2, nedsim->cell_size * 2,
180*64, 90*64
);
- XFillArc(nedsim->dpy, nedsim->win, nedsim->gc,
+ XFillArc(nedsim->dpy, nedsim->panel, nedsim->gc,
nedsim->origin_x_offset + (nedsim->cell_size * (OVERALL_WIDTH_IN_CELLS-2)),
nedsim->origin_y_offset + (nedsim->cell_size * (HEADER_HEIGHT_IN_CELLS + nedsim->num_data_rows + FOOTER_HEIGHT_IN_CELLS - 2)),
nedsim->cell_size * 2, nedsim->cell_size * 2,
get_text_size(nedsim, "NED", &text_x_size, &text_y_size);
int local_x_offset = ((LOGO_WIDTH * nedsim->cell_size) - text_x_size) / 2;
int local_y_offset = ((LOGO_NAME_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (LOGO_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (LOGO_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((LOGO_Y_OFFSET+LOGO_NAME_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "NED", 3);
// And draw the 'subgeniuskitty.com' text in the bottom box.
get_text_size(nedsim, "subgeniuskitty.com", &text_x_size, &text_y_size);
local_x_offset = ((LOGO_WIDTH * nedsim->cell_size) - text_x_size) / 2;
local_y_offset = ((LOGO_WEBSITE_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (LOGO_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (LOGO_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((LOGO_Y_OFFSET+LOGO_NAME_HEIGHT+LOGO_WEBSITE_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "subgeniuskitty.com", 18);
}
get_text_size(nedsim, "HALT", &text_x_size, &text_y_size);
int local_x_offset = ((HALT_WIDTH * nedsim->cell_size) - text_x_size) / 2;
int local_y_offset = ((HALT_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (HALT_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (HALT_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((HALT_Y_OFFSET+HALT_LIGHT_HEIGHT+HALT_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "HALT", 4);
}
get_text_size(nedsim, "PC", &text_x_size, &text_y_size);
int local_x_offset = ((PC_WIDTH * nedsim->cell_size) - text_x_size) / 2;
int local_y_offset = ((PC_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (PC_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (PC_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((PC_Y_OFFSET+PC_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "PC", 2);
}
get_text_size(nedsim, "SC", &text_x_size, &text_y_size);
int local_x_offset = ((SC_WIDTH * nedsim->cell_size) - text_x_size) / 2;
int local_y_offset = ((SC_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (SC_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (SC_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((SC_Y_OFFSET+SC_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "SC", 2);
}
get_text_size(nedsim, "N", &text_x_size, &text_y_size);
int local_x_offset = ((PSW_LABEL_WIDTH * nedsim->cell_size) - text_x_size) / 2;
int local_y_offset = ((PSW_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (PSW_N_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (PSW_N_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((PSW_Y_OFFSET+PSW_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "N", 1);
// Now draw the label text "Z".
get_text_size(nedsim, "Z", &text_x_size, &text_y_size);
local_x_offset = ((PSW_LABEL_WIDTH * nedsim->cell_size) - text_x_size) / 2;
local_y_offset = ((PSW_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, (PSW_Z_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, (PSW_Z_X_OFFSET * nedsim->cell_size + nedsim->origin_x_offset + local_x_offset),
((PSW_Y_OFFSET+PSW_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "Z", 1);
}
int text_x_size, text_y_size;
get_text_size(nedsim, "Stack Size:", &text_x_size, &text_y_size);
int local_y_offset = ((STACK_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, ((STACK_X_OFFSET + 1) * nedsim->cell_size + nedsim->origin_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, ((STACK_X_OFFSET + 1) * nedsim->cell_size + nedsim->origin_x_offset),
((STACK_Y_OFFSET+STACK_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "Stack Size:", 11);
}
int text_x_size, text_y_size;
get_text_size(nedsim, "RAM Base:", &text_x_size, &text_y_size);
int local_y_offset = ((HEAP_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, ((HEAP_X_OFFSET + 1) * nedsim->cell_size + nedsim->origin_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, ((HEAP_X_OFFSET + 1) * nedsim->cell_size + nedsim->origin_x_offset),
((HEAP_Y_OFFSET+HEAP_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), "RAM Base:", 9);
// Now draw the address text.
snprintf(address, sizeof(address), "0x%08X", HEAP_START_ADDRESS);
get_text_size(nedsim, address, &text_x_size, &text_y_size);
local_y_offset = ((HEAP_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, ((HEAP_X_OFFSET + 1 + (HEAP_WIDTH / 2)) * nedsim->cell_size + nedsim->origin_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, ((HEAP_X_OFFSET + 1 + (HEAP_WIDTH / 2)) * nedsim->cell_size + nedsim->origin_x_offset),
((HEAP_Y_OFFSET+HEAP_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), address, strlen(address));
}
int text_x_size, text_y_size;
get_text_size(nedsim, stack_size, &text_x_size, &text_y_size);
int local_y_offset = ((STACK_LABEL_HEIGHT * nedsim->cell_size) - text_y_size) / 2;
- XDrawString(nedsim->dpy, nedsim->win, nedsim->gc, ((STACK_X_OFFSET + 1 + (STACK_WIDTH / 2)) * nedsim->cell_size + nedsim->origin_x_offset),
+ XDrawString(nedsim->dpy, nedsim->panel, nedsim->gc, ((STACK_X_OFFSET + 1 + (STACK_WIDTH / 2)) * nedsim->cell_size + nedsim->origin_x_offset),
((STACK_Y_OFFSET+STACK_LABEL_HEIGHT) * nedsim->cell_size + nedsim->origin_y_offset - local_y_offset), stack_size, strlen(stack_size));
// Draw the heap lights.
static void
NEDsim_free(Display * dpy, Window win, void * closure)
{
- // TODO: Replace all this with proper code to free everything.
struct NEDsim * nedsim = closure;
+
+ if (nedsim->nedstate != NULL) {
+ free(nedsim->nedstate->active_thread->psw);
+ free(nedsim->nedstate->active_thread);
+ free(nedsim->nedstate->hack);
+ free(nedsim->nedstate);
+ }
+
+ // TODO: Replace all this with proper code to free everything related to the screensaver itself.
XFreeGC(nedsim->dpy, nedsim->gc);
+ XFreePixmap(nedsim->dpy, nedsim->panel);
free(nedsim);
}
nedsim->delay = get_integer_resource(nedsim->dpy, "delay", "Integer");
nedsim->delay *= 1000; /* Turn milliseconds into microseconds. */
- // TODO: Read in the a.out file. This should be done in the simulator's init function call?
- nedsim->nedstate = init_simulator();
+ // Load the program file specified by the user or, if none is specified,
+ // randomly select one of the included programs.
+ char * input_file = get_string_resource(nedsim->dpy, "binary", "String");
+ if (input_file == NULL) {
+ // TODO: Need to include some default programs and randomly select one to load into RAM.
+ nedsim->nedstate = init_simulator("./test.out");
+ } else {
+ nedsim->nedstate = init_simulator(input_file);
+ }
nedsim->gc = XCreateGC(nedsim->dpy, nedsim->win, GCForeground, &gcv);
+ nedsim->panel = XCreatePixmap(nedsim->dpy, nedsim->win, nedsim->dpy_width, nedsim->dpy_height, xgwa.depth);
// TODO: Do this properly.
nedsim->color_index = 0;
update_display(nedsim);
} else {
set_color(nedsim, &color_list[nedsim->color_index].error_on);
- XFillRectangle(nedsim->dpy, nedsim->win, nedsim->gc, 0, 0, nedsim->dpy_width, nedsim->dpy_height);
+ XFillRectangle(nedsim->dpy, nedsim->panel, nedsim->gc, 0, 0, nedsim->dpy_width, nedsim->dpy_height);
}
+ XCopyArea(nedsim->dpy, nedsim->panel, nedsim->win, nedsim->gc, 0, 0, nedsim->dpy_width, nedsim->dpy_height, 0, 0);
+
return nedsim->delay;
}
static XrmOptionDescRec NEDsim_options[] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-binary", ".binary", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};