OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [gui.c] - Diff between revs 3 and 5

Show entire file | Details | Blame | View Log

Rev 3 Rev 5
Line 1... Line 1...
/**@file      gui.c
/**@file      gui.c
 * @brief     GUI Simulator for the H2 SoC
 * @brief     GUI Simulator for the H2 SoC
 * @copyright Richard James Howe (2017)
 * @copyright Richard James Howe (2017-2019)
 * @license   MIT
 * @license   MIT
 *
 * @note It would have been better to make this in SDL, se
 * @todo Implement reset/reload, and save/load state */
 * <https://www.libsdl.org/>.  */
 
 
 
 
#include "h2.h"
#include "h2.h"
#include <assert.h>
#include <assert.h>
#include <errno.h>
#include <errno.h>
#include <ctype.h>
#include <ctype.h>
Line 20... Line 19...
#include <GL/gl.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glut.h>
#include <GL/freeglut_ext.h> /* for glutStrokeHeight */
#include <GL/freeglut_ext.h> /* for glutStrokeHeight */
#include <stdarg.h>
#include <stdarg.h>
 
 
 
#define TRON (0)
 
 
/* ====================================== Utility Functions ==================================== */
/* ====================================== Utility Functions ==================================== */
 
 
#define PI               (3.1415926535897932384626433832795)
#define PI               (3.1415926535897932384626433832795)
#define MAX(X, Y)        ((X) > (Y) ? (X) : (Y))
#define MAX(X, Y)        ((X) > (Y) ? (X) : (Y))
#define MIN(X, Y)        ((X) < (Y) ? (X) : (Y))
#define MIN(X, Y)        ((X) < (Y) ? (X) : (Y))
Line 40... Line 41...
#define CYCLE_MINIMUM    (10000)
#define CYCLE_MINIMUM    (10000)
#define CYCLE_HYSTERESIS (2.0)
#define CYCLE_HYSTERESIS (2.0)
#define TARGET_FPS       (30.0)
#define TARGET_FPS       (30.0)
#define BACKGROUND_ON    (false)
#define BACKGROUND_ON    (false)
#define SIM_HACKS        (true)
#define SIM_HACKS        (true)
 
#define TRACE_FILE       ("trace.csv")
 
#define TRACE_BUFFER_LEN (16*4096)
 
 
typedef struct {
typedef struct {
        double window_height;
        double window_height;
        double window_width;
        double window_width;
        double window_x_starting_position;
        double window_x_starting_position;
        double window_y_starting_position;
        double window_y_starting_position;
        double window_scale_x;
        double window_scale_x;
        double window_scale_y;
        double window_scale_y;
 
        void *font_scaled;
 
        uint64_t cycle_count;
 
        uint64_t cycles;
        volatile unsigned tick;
        volatile unsigned tick;
        volatile bool     halt_simulation;
 
        unsigned arena_tick_ms;
        unsigned arena_tick_ms;
 
        volatile bool halt_simulation;
        bool use_uart_input;
        bool use_uart_input;
        bool debug_extra;
        bool debug_extra;
        bool step;
        bool step;
        bool debug_mode;
        bool debug_mode;
        uint64_t cycle_count;
 
        uint64_t cycles;
 
        void *font_scaled;
 
} world_t;
} world_t;
 
 
static world_t world = {
static world_t world = {
        .window_height               = 800.0,
        .window_height               = 800.0,
        .window_width                = 800.0,
        .window_width                = 800.0,
Line 79... Line 82...
        .cycle_count                 = 0,
        .cycle_count                 = 0,
        .cycles                      = CYCLE_INITIAL,
        .cycles                      = CYCLE_INITIAL,
        .font_scaled                 = GLUT_STROKE_MONO_ROMAN
        .font_scaled                 = GLUT_STROKE_MONO_ROMAN
};
};
 
 
 
static FILE *trace_file = NULL; /* NB. !NULL turns tracing on */
 
static char trace_buffer[TRACE_BUFFER_LEN];
 
 
typedef enum {
typedef enum {
        TRIANGLE,
        TRIANGLE,
        SQUARE,
        SQUARE,
        PENTAGON,
        PENTAGON,
        HEXAGON,
        HEXAGON,
Line 109... Line 115...
 
 
typedef struct { /**@note it might be worth translating some functions to use points*/
typedef struct { /**@note it might be worth translating some functions to use points*/
        double x, y;
        double x, y;
} point_t;
} point_t;
 
 
static const char *nvram_file = FLASH_INIT_FILE;
 
 
 
/**@bug not quite correct, arena_tick_ms is what we request, not want the arena
/**@bug not quite correct, arena_tick_ms is what we request, not want the arena
 * tick actually is */
 * tick actually is */
static double seconds_to_ticks(const world_t *world, double s)
static double seconds_to_ticks(const world_t *world, double s) {
{
 
        assert(world);
        assert(world);
        return s * (1000. / (double)world->arena_tick_ms);
        return s * (1000. / (double)world->arena_tick_ms);
}
}
 
 
static double rad2deg(double rad)
static double rad2deg(const double rad) {
{
 
        return (rad / (2.0 * PI)) * 360.0;
        return (rad / (2.0 * PI)) * 360.0;
}
}
 
 
static void set_color(color_t color, bool light)
static void set_color(const color_t color, const bool light) {
{
 
        double ON = light ? 0.8 : 0.4;
        double ON = light ? 0.8 : 0.4;
        static const double OFF = 0.0;
        static const double OFF = 0.0;
        switch(color) {      /* RED  GRN  BLU */
        switch(color) {      /* RED  GRN  BLU */
        case WHITE:   glColor3f( ON,  ON,  ON);   break;
        case WHITE:   glColor3f( ON,  ON,  ON);   break;
        case RED:     glColor3f( ON, OFF, OFF);   break;
        case RED:     glColor3f( ON, OFF, OFF);   break;
Line 143... Line 145...
        }
        }
}
}
 
 
/* see: https://www.opengl.org/discussion_boards/showthread.php/160784-Drawing-Circles-in-OpenGL */
/* see: https://www.opengl.org/discussion_boards/showthread.php/160784-Drawing-Circles-in-OpenGL */
static void _draw_regular_polygon(
static void _draw_regular_polygon(
                double x, double y,
                const double x, const double y,
                double orientation,
                const double orientation,
                double radius, double sides,
                const double radius, const double sides,
                bool lines, double thickness,
                const bool lines, const double thickness,
                color_t color)
                const color_t color) {
{
 
        glMatrixMode(GL_MODELVIEW);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glPushMatrix();
                glLoadIdentity();
                glLoadIdentity();
                glTranslatef(x, y, 0.0);
                glTranslatef(x, y, 0.0);
                glRotated(rad2deg(orientation), 0, 0, 1);
                glRotated(rad2deg(orientation), 0, 0, 1);
Line 167... Line 168...
                                glVertex3d(cos(i) * radius, sin(i) * radius, 0.0);
                                glVertex3d(cos(i) * radius, sin(i) * radius, 0.0);
                glEnd();
                glEnd();
        glPopMatrix();
        glPopMatrix();
}
}
 
 
static void _draw_rectangle(double x, double y, double width, double height, bool lines, double thickness, color_t color)
static void _draw_rectangle(
{
                const double x, const double y,
 
                const double width, const double height,
 
                const bool lines, const double thickness,
 
                const color_t color) {
        glMatrixMode(GL_MODELVIEW);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glPushMatrix();
                glLoadIdentity();
                glLoadIdentity();
                glRasterPos2d(x, y);
                glRasterPos2d(x, y);
                set_color(color, true);
                set_color(color, true);
Line 188... Line 192...
                glVertex3d(x,       y+height, 0);
                glVertex3d(x,       y+height, 0);
                glEnd();
                glEnd();
        glPopMatrix();
        glPopMatrix();
}
}
 
 
static void draw_rectangle_filled(double x, double y, double width, double height, color_t color)
static void draw_rectangle_filled(const double x, const double y, const double width, const double height, const color_t color) {
{
        _draw_rectangle(x, y, width, height, false, 0, color);
        return _draw_rectangle(x, y, width, height, false, 0, color);
 
}
}
 
 
static void draw_rectangle_line(double x, double y, double width, double height, double thickness, color_t color)
static void draw_rectangle_line(const double x, const double y, const double width, const double height, const double thickness, const color_t color) {
{
        _draw_rectangle(x, y, width, height, true, thickness, color);
        return _draw_rectangle(x, y, width, height, true, thickness, color);
 
}
}
 
 
static double shape_to_sides(shape_t shape)
static double shape_to_sides(shape_t shape) {
{
 
        static const double sides[] =
        static const double sides[] =
        {
        {
                [TRIANGLE] = 1.5,
                [TRIANGLE] = 1.5,
                [SQUARE]   = 2,
                [SQUARE]   = 2,
                [PENTAGON] = 2.5,
                [PENTAGON] = 2.5,
Line 216... Line 217...
        if(shape >= INVALID_SHAPE)
        if(shape >= INVALID_SHAPE)
                fatal("invalid shape '%d'", shape);
                fatal("invalid shape '%d'", shape);
        return sides[shape % INVALID_SHAPE];
        return sides[shape % INVALID_SHAPE];
}
}
 
 
static void draw_regular_polygon_filled(double x, double y, double orientation, double radius, shape_t shape, color_t color)
static void draw_regular_polygon_filled(const double x, const double y, const double orientation, const double radius, const shape_t shape, const color_t color) {
{
        _draw_regular_polygon(x, y, orientation, radius, shape_to_sides(shape), false, 0, color);
        double sides = shape_to_sides(shape);
 
        _draw_regular_polygon(x, y, orientation, radius, sides, false, 0, color);
 
}
}
 
 
static void draw_regular_polygon_line(double x, double y, double orientation, double radius, shape_t shape, double thickness, color_t color)
static void draw_regular_polygon_line(const double x, const double y, const double orientation, const double radius, const shape_t shape, const double thickness, const color_t color) {
{
        _draw_regular_polygon(x, y, orientation, radius, shape_to_sides(shape), true, thickness, color);
        double sides = shape_to_sides(shape);
 
        _draw_regular_polygon(x, y, orientation, radius, sides, true, thickness, color);
 
}
}
 
 
static void draw_char(uint8_t c)
static void draw_char(uint8_t c) {
{
 
        c = c >= 32 && c <= 127 ? c : '?';
        c = c >= 32 && c <= 127 ? c : '?';
        glutStrokeCharacter(world.font_scaled, c);
        glutStrokeCharacter(world.font_scaled, c);
}
}
 
 
/* see: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01
/* see: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01
 *      https://stackoverflow.com/questions/538661/how-do-i-draw-text-with-glut-opengl-in-c
 *      https://stackoverflow.com/questions/538661/how-do-i-draw-text-with-glut-opengl-in-c
 *      https://stackoverflow.com/questions/20866508/using-glut-to-simply-print-text */
 *      https://stackoverflow.com/questions/20866508/using-glut-to-simply-print-text */
static int draw_block(const uint8_t *msg, size_t len)
static int draw_block(const uint8_t *msg, const size_t len) {
{
 
        assert(msg);
        assert(msg);
        for(size_t i = 0; i < len; i++)
        for(size_t i = 0; i < len; i++)
                draw_char(msg[i]);
                draw_char(msg[i]);
        return len;
        return len;
}
}
 
 
static int draw_string(const char *msg)
static int draw_string(const char *msg) {
{
 
        assert(msg);
        assert(msg);
        return draw_block((uint8_t*)msg, strlen(msg));
        return draw_block((uint8_t*)msg, strlen(msg));
}
}
 
 
static scale_t font_attributes(void)
static scale_t font_attributes(void) {
{
        static bool initialized = false;  // @warning static!
        static bool initialized = false;
        static scale_t scale = { 0., 0.}; // @warning static!
        static scale_t scale = { 0., 0.};
 
        if(initialized)
        if(initialized)
                return scale;
                return scale;
        scale.y = glutStrokeHeight(world.font_scaled);
        scale.y = glutStrokeHeight(world.font_scaled);
        scale.x = glutStrokeWidth(world.font_scaled, 'M');
        scale.x = glutStrokeWidth(world.font_scaled, 'M');
        initialized = true;
        initialized = true;
        return scale;
        return scale;
}
}
 
 
static void draw_vt100_char(double x, double y, double scale_x, double scale_y, double orientation, uint8_t c, vt100_attribute_t *attr, bool blink)
static void draw_vt100_char(
{
                const double x, const double y,
 
                const double scale_x, const double scale_y,
 
                const double orientation, const uint8_t c,
 
                const vt100_attribute_t *attr, const bool blink) {
 
        assert(attr);
        /*scale_t scale = font_attributes();
        /*scale_t scale = font_attributes();
        double char_width  = scale.x / X_MAX;
        double char_width  = scale.x / X_MAX;
        double char_height = scale.y / Y_MAX;*/
        double char_height = scale.y / Y_MAX;*/
 
 
        if(blink && attr->blink)
        if(blink && attr->blink)
Line 286... Line 283...
        glPopMatrix();
        glPopMatrix();
        if(BACKGROUND_ON)
        if(BACKGROUND_ON)
                draw_rectangle_filled(x, y, 1.20, 1.55, attr->background_color);
                draw_rectangle_filled(x, y, 1.20, 1.55, attr->background_color);
}
}
 
 
static int draw_vt100_block(double x, double y, double scale_x, double scale_y, double orientation, const uint8_t *msg, size_t len, vt100_attribute_t *attr, bool blink)
static int draw_vt100_block(
{
                const double x, const double y,
        scale_t scale = font_attributes();
                const double scale_x, const double scale_y,
        double char_width = (scale.x / X_MAX)*1.1;
                const double orientation, const uint8_t *msg,
 
                const size_t len, const vt100_attribute_t * const attr, const bool blink) {
 
        assert(attr);
 
        const scale_t scale = font_attributes();
 
        const double char_width = (scale.x / X_MAX)*1.1;
        for(size_t i = 0; i < len; i++)
        for(size_t i = 0; i < len; i++)
                draw_vt100_char(x+char_width*i, y, scale_x, scale_y, orientation, msg[i], &attr[i], blink);
                draw_vt100_char(x+char_width*i, y, scale_x, scale_y, orientation, msg[i], &attr[i], blink);
        return len;
        return len;
}
}
 
 
static int draw_block_scaled(double x, double y, double scale_x, double scale_y, double orientation, const uint8_t *msg, size_t len, color_t color)
static int draw_block_scaled(
{
                const double x, const double y,
 
                const double scale_x, const double scale_y,
 
                const double orientation, const uint8_t *msg, const size_t len, const color_t color) {
        assert(msg);
        assert(msg);
        glMatrixMode(GL_MODELVIEW);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glPushMatrix();
                glLoadIdentity();
                glLoadIdentity();
                glTranslatef(x, y, 0.0);
                glTranslatef(x, y, 0.0);
Line 315... Line 318...
                glEnd();
                glEnd();
        glPopMatrix();
        glPopMatrix();
        return len;
        return len;
}
}
 
 
static int draw_string_scaled(double x, double y, double scale_x, double scale_y, double orientation, const char *msg, color_t color)
static int draw_string_scaled(
{
                const double x, const double y,
 
                const double scale_x, const double scale_y,
 
                const double orientation, const char *msg, const color_t color) {
        assert(msg);
        assert(msg);
        return draw_block_scaled(x, y, scale_x, scale_y, orientation, (uint8_t*)msg, strlen(msg), color);
        return draw_block_scaled(x, y, scale_x, scale_y, orientation, (uint8_t*)msg, strlen(msg), color);
}
}
 
 
static int vdraw_text(color_t color, double x, double y, const char *fmt, va_list ap)
static int vdraw_text(const color_t color, const double x, const double y, const char *fmt, va_list ap) {
{
 
        char f;
 
        int r = 0;
        int r = 0;
        assert(fmt);
        assert(fmt);
        static const double scale_x = 0.011;
        static const double scale_x = 0.011;
        static const double scale_y = 0.011;
        static const double scale_y = 0.011;
 
 
Line 335... Line 338...
        glPushMatrix();
        glPushMatrix();
        set_color(color, true);
        set_color(color, true);
        glTranslatef(x, y, 0);
        glTranslatef(x, y, 0);
        glScaled(scale_x, scale_y, 1.0);
        glScaled(scale_x, scale_y, 1.0);
        while(*fmt) {
        while(*fmt) {
                if('%' != (f = *fmt++)) {
                char f = *fmt++;
 
                if ('%' != f) {
                        glutStrokeCharacter(world.font_scaled, f);
                        glutStrokeCharacter(world.font_scaled, f);
                        r++;
                        r++;
                        continue;
                        continue;
                }
                }
                switch(f = *fmt++) {
                switch ((f = *fmt++)) {
                case 'c':
                case 'c':
                {
                {
                        char x[2] = {0, 0};
                        char x[2] = {0, 0};
                        x[0] = va_arg(ap, int);
                        x[0] = va_arg(ap, int);
                        r += draw_string(x);
                        r += draw_string(x);
Line 356... Line 360...
                        r += draw_string(s);
                        r += draw_string(s);
                        break;
                        break;
                }
                }
                case 'x':
                case 'x':
                {
                {
                        unsigned d = va_arg(ap, unsigned);
                        const unsigned d = va_arg(ap, unsigned);
                        char s[64] = {0};
                        char s[64] = {0};
                        sprintf(s, "%04x", d);
                        sprintf(s, "%04x", d);
                        r += draw_string(s);
                        r += draw_string(s);
                        break;
                        break;
                }
                }
                case 'u':
                case 'u':
                case 'd':
                case 'd':
                {
                {
                        int d = va_arg(ap, int);
                        const int d = va_arg(ap, int);
                        char s[64] = {0};
                        char s[64] = {0};
                        sprintf(s, f == 'u' ? "%u": "%d", d);
                        sprintf(s, f == 'u' ? "%u": "%d", d);
                        r += draw_string(s);
                        r += draw_string(s);
                        break;
                        break;
                }
                }
                case 'f':
                case 'f':
                {
                {
                        double f = va_arg(ap, double);
                        const double f = va_arg(ap, double);
                        char s[512] = {0};
                        char s[512] = {0};
                        sprintf(s, "%.2f", f);
                        sprintf(s, "%.2f", f);
                        r += draw_string(s);
                        r += draw_string(s);
                        break;
                        break;
                }
                }
Line 389... Line 393...
        }
        }
        glPopMatrix();
        glPopMatrix();
        return r;
        return r;
}
}
 
 
static void fill_textbox(textbox_t *t, const char *fmt, ...)
static void fill_textbox(textbox_t *t, const char *fmt, ...) {
{
 
        double r;
 
        va_list ap;
        va_list ap;
        assert(t);
        assert(t);
        assert(fmt);
        assert(fmt);
 
 
        scale_t scale = font_attributes();
        scale_t scale = font_attributes();
        double char_width = scale.x / X_MAX;
        const double char_width = scale.x / X_MAX;
        double char_height = scale.y / Y_MAX;
        const double char_height = scale.y / Y_MAX;
        assert(t && fmt);
        assert(t && fmt);
        va_start(ap, fmt);
        va_start(ap, fmt);
        r = vdraw_text(t->color_text, t->x, t->y - t->height, fmt, ap);
        double r = vdraw_text(t->color_text, t->x, t->y - t->height, fmt, ap);
        r *= char_width * 1.11;
        r *= char_width * 1.11;
        r += 1;
        r += 1;
        va_end(ap);
        va_end(ap);
        t->width = MAX(t->width, r);
        t->width = MAX(t->width, r);
        t->height += (char_height); /*correct?*/
        t->height += (char_height); /*correct?*/
}
}
 
 
static void draw_textbox(textbox_t *t)
static void draw_textbox(textbox_t *t) {
{
 
        assert(t);
        assert(t);
        scale_t scale = font_attributes();
        scale_t scale = font_attributes();
        double char_height = scale.y / Y_MAX;
        const double char_height = scale.y / Y_MAX;
        if(!(t->draw_border))
        if(!(t->draw_border))
                return;
                return;
        draw_rectangle_line(t->x - LINE_WIDTH, t->y - t->height + char_height - 1, t->width, t->height + 1, LINE_WIDTH, t->color_box);
        draw_rectangle_line(t->x - LINE_WIDTH, t->y - t->height + char_height - 1, t->width, t->height + 1, LINE_WIDTH, t->color_box);
}
}
 
 
static bool detect_circle_circle_collision(
static bool detect_circle_circle_collision(
                double ax, double ay, double aradius,
                const double ax, const double ay, const double aradius,
                double bx, double by, double bradius)
                const double bx, const double by, const double bradius) {
{
        const double dx = ax - bx;
        double dx = ax - bx;
        const double dy = ay - by;
        double dy = ay - by;
        const double distance = hypot(dx, dy);
        double distance = hypot(dx, dy);
        return distance < (aradius + bradius);
        return (distance < (aradius + bradius));
 
}
}
 
 
/* ====================================== Utility Functions ==================================== */
/* ====================================== Utility Functions ==================================== */
 
 
/* ====================================== Simulator Objects ==================================== */
/* ====================================== Simulator Objects ==================================== */
Line 441... Line 441...
        double angle;
        double angle;
        double radius;
        double radius;
        bool on;
        bool on;
} led_t;
} led_t;
 
 
static void draw_led(led_t *l)
static void draw_led(const led_t * const l) {
{
 
        assert(l);
        assert(l);
        double msz = l->radius * 0.75;
        const double msz = l->radius * 0.75;
        double off = (l->radius - msz) / 2.0;
        const double off = (l->radius - msz) / 2.0;
        draw_rectangle_filled(l->x+off, l->y+off, msz, msz, l->on ? GREEN : RED);
        draw_rectangle_filled(l->x+off, l->y+off, msz, msz, l->on ? GREEN : RED);
        draw_rectangle_filled(l->x, l->y, l->radius, l->radius, BLUE);
        draw_rectangle_filled(l->x, l->y, l->radius, l->radius, BLUE);
}
}
 
 
typedef struct {
typedef struct {
Line 458... Line 457...
        double angle;
        double angle;
        double radius;
        double radius;
        bool on;
        bool on;
} switch_t;
} switch_t;
 
 
static void draw_switch(switch_t *s)
static void draw_switch(const switch_t * const s) {
{
 
        assert(s);
        assert(s);
        double msz = s->radius * 0.6;
        const double msz = s->radius * 0.6;
        double off = (s->radius - msz) / 2.0;
        const double off = (s->radius - msz) / 2.0;
        draw_rectangle_filled(s->x+off, s->on ? (s->y + s->radius) - off : s->y+off, msz, msz, s->on ? GREEN : RED);
        draw_rectangle_filled(s->x+off, s->on ? (s->y + s->radius) - off : s->y+off, msz, msz, s->on ? GREEN : RED);
        draw_rectangle_filled(s->x+off, s->y + off, msz, msz*2., BLACK);
        draw_rectangle_filled(s->x+off, s->y + off, msz, msz*2., BLACK);
        draw_rectangle_filled(s->x, s->y, s->radius, s->radius * 2, BLUE);
        draw_rectangle_filled(s->x, s->y, s->radius, s->radius * 2, BLUE);
}
}
 
 
Line 488... Line 486...
        double width;
        double width;
        double height;
        double height;
        uint8_t segment;
        uint8_t segment;
} led_8_segment_t;
} led_8_segment_t;
 
 
static uint8_t convert_to_segments(uint8_t segment) {
static uint8_t convert_to_segments(const uint8_t segment) {
        static const uint8_t c2s[16] = {
        static const uint8_t c2s[16] = {
                0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
                0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
                0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
                0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
        };
        };
        return c2s[segment & 0xf];
        return c2s[segment & 0xf];
}
}
 
 
#define SEG_CLR(SG,BIT) (((SG) & (1 << BIT)) ? RED : BLACK)
#define SEG_CLR(SG,BIT) (((SG) & (1 << BIT)) ? RED : BLACK)
 
 
static void draw_led_8_segment(led_8_segment_t *l)
static void draw_led_8_segment(const led_8_segment_t * const l) {
{
 
        assert(l);
        assert(l);
        uint8_t sgs = convert_to_segments(l->segment);
        const uint8_t sgs = convert_to_segments(l->segment);
 
 
        draw_rectangle_filled(l->x + l->width * 0.20, l->y + l->height * 0.45, l->width * 0.5, l->height * 0.1, SEG_CLR(sgs, LED_SEGMENT_G)); /* Center */
        draw_rectangle_filled(l->x + l->width * 0.20, l->y + l->height * 0.45, l->width * 0.5, l->height * 0.1, SEG_CLR(sgs, LED_SEGMENT_G)); /* Center */
        draw_rectangle_filled(l->x + l->width * 0.20, l->y + l->height * 0.1,  l->width * 0.5, l->height * 0.1, SEG_CLR(sgs, LED_SEGMENT_D)); /* Bottom */
        draw_rectangle_filled(l->x + l->width * 0.20, l->y + l->height * 0.1,  l->width * 0.5, l->height * 0.1, SEG_CLR(sgs, LED_SEGMENT_D)); /* Bottom */
        draw_rectangle_filled(l->x + l->width * 0.20, l->y + l->height * 0.8,  l->width * 0.5, l->height * 0.1, SEG_CLR(sgs, LED_SEGMENT_A)); /* Top */
        draw_rectangle_filled(l->x + l->width * 0.20, l->y + l->height * 0.8,  l->width * 0.5, l->height * 0.1, SEG_CLR(sgs, LED_SEGMENT_A)); /* Top */
 
 
Line 531... Line 528...
        bool left;
        bool left;
        bool right;
        bool right;
        bool center;
        bool center;
} dpad_t;
} dpad_t;
 
 
static void draw_dpad(dpad_t *d)
static void draw_dpad(const dpad_t * const d) {
{
        assert(d);
        draw_regular_polygon_filled(d->x + (d->radius*2.0), d->y,                   d->angle,            d->radius, TRIANGLE, d->right  ? GREEN : RED);
        draw_regular_polygon_filled(d->x + (d->radius*2.0), d->y,                   d->angle,            d->radius, TRIANGLE, d->right  ? GREEN : RED);
        draw_regular_polygon_filled(d->x - (d->radius*2.0), d->y,                   d->angle + (PI/3.0), d->radius, TRIANGLE, d->left   ? GREEN : RED);
        draw_regular_polygon_filled(d->x - (d->radius*2.0), d->y,                   d->angle + (PI/3.0), d->radius, TRIANGLE, d->left   ? GREEN : RED);
        draw_regular_polygon_filled(d->x,                   d->y - (d->radius*2.0), d->angle - (PI/2.0), d->radius, TRIANGLE, d->down   ? GREEN : RED);
        draw_regular_polygon_filled(d->x,                   d->y - (d->radius*2.0), d->angle - (PI/2.0), d->radius, TRIANGLE, d->down   ? GREEN : RED);
        draw_regular_polygon_filled(d->x,                   d->y + (d->radius*2.0), d->angle + (PI/2.0), d->radius, TRIANGLE, d->up     ? GREEN : RED);
        draw_regular_polygon_filled(d->x,                   d->y + (d->radius*2.0), d->angle + (PI/2.0), d->radius, TRIANGLE, d->up     ? GREEN : RED);
        draw_regular_polygon_filled(d->x,                   d->y,                   d->angle,            d->radius, CIRCLE,   d->center ? GREEN : RED);
        draw_regular_polygon_filled(d->x,                   d->y,                   d->angle,            d->radius, CIRCLE,   d->center ? GREEN : RED);
Line 551... Line 548...
        DPAN_COL_DOWN,
        DPAN_COL_DOWN,
        DPAN_COL_UP,
        DPAN_COL_UP,
        DPAN_COL_CENTER
        DPAN_COL_CENTER
} dpad_collision_e;
} dpad_collision_e;
 
 
static dpad_collision_e dpad_collision(dpad_t *d, double x, double y, double radius)
static dpad_collision_e dpad_collision(const dpad_t * const d, const double x, const double y, const double radius) {
{
        assert(d);
        if(detect_circle_circle_collision(x, y, radius, d->x + (d->radius*2.0), d->y,                   d->radius))
        if(detect_circle_circle_collision(x, y, radius, d->x + (d->radius*2.0), d->y,                   d->radius))
                return DPAN_COL_RIGHT;
                return DPAN_COL_RIGHT;
        if(detect_circle_circle_collision(x, y, radius, d->x - (d->radius*2.0), d->y,                   d->radius))
        if(detect_circle_circle_collision(x, y, radius, d->x - (d->radius*2.0), d->y,                   d->radius))
                return DPAN_COL_LEFT;
                return DPAN_COL_LEFT;
        if(detect_circle_circle_collision(x, y, radius, d->x,                   d->y + (d->radius*2.0), d->radius))
        if(detect_circle_circle_collision(x, y, radius, d->x,                   d->y + (d->radius*2.0), d->radius))
Line 587... Line 584...
        color_t color;
        color_t color;
        vt100_t vt100;
        vt100_t vt100;
        vt100_background_texture_t *texture;
        vt100_background_texture_t *texture;
} terminal_t;
} terminal_t;
 
 
static void texture_background(terminal_t *t)
static void texture_background(const terminal_t * const t) {
{
 
        assert(t);
        assert(t);
        vt100_background_texture_t *v = t->texture;
        const vt100_background_texture_t *v = t->texture;
        vt100_t *vt = &t->vt100;
        const vt100_t *vt = &t->vt100;
        unsigned i, j;
        uint8_t *const img = v->image;
        uint8_t *img = v->image;
 
        const unsigned h = v->height;
        const unsigned h = v->height;
        const unsigned w = v->width;
        const unsigned w = v->width;
 
 
        for (i = 0; i < h; i++) {
        for (unsigned i = 0; i < h; i++) {
                uint8_t *row = &img[i*4];
                uint8_t * const row = &img[i * 4];
                unsigned ii = ((h - i - 1)*vt->height) / h;
                const unsigned ii = ((h - i - 1) * vt->height) / h;
                for (j = 0; j < w; j++) {
                for (unsigned j = 0; j < w; j++) {
                        uint8_t *column = &row[j*h*4];
                        uint8_t * const column = &row[j * h * 4];
                        const unsigned jj = (vt->width*j) / w;
                        const unsigned jj = (vt->width*j) / w;
                        const unsigned idx = jj+(ii*vt->width);
                        const unsigned idx = jj+(ii*vt->width);
                        column[0] = 255 * (vt->attributes[idx].background_color & 1);
                        column[0] = 255 * (vt->attributes[idx].background_color & 1);
                        column[1] = 255 * (vt->attributes[idx].background_color & 2);
                        column[1] = 255 * (vt->attributes[idx].background_color & 2);
                        column[2] = 255 * (vt->attributes[idx].background_color & 4);
                        column[2] = 255 * (vt->attributes[idx].background_color & 4);
Line 613... Line 608...
                }
                }
        }
        }
}
}
 
 
/* See <http://www.glprogramming.com/red/chapter09.html> */
/* See <http://www.glprogramming.com/red/chapter09.html> */
static void draw_texture(terminal_t *t, bool update)
static void draw_texture(const terminal_t * const t, const bool update) {
{
        assert(t);
        vt100_background_texture_t *v = t->texture;
        vt100_background_texture_t *v = t->texture;
        if(!v)
        if(!v)
                return;
                return;
 
 
        scale_t scale = font_attributes();
        const scale_t scale = font_attributes();
        double char_width  = scale.x / X_MAX;
        const double char_width  = scale.x / X_MAX;
        double char_height = scale.y / Y_MAX;
        const double char_height = scale.y / Y_MAX;
        double x = t->x;
        const double x = t->x;
        double y = t->y - (char_height * (t->vt100.height-1.0));
        const double y = t->y - (char_height * (t->vt100.height-1.0));
        double width  = char_width  * t->vt100.width * 1.10;
        const double width  = char_width  * t->vt100.width * 1.10;
        double height = char_height * t->vt100.height;
        const double height = char_height * t->vt100.height;
 
 
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_TEXTURE_2D);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 
 
        if(update) {
        if(update) {
Line 659... Line 654...
                glTexCoord2f(0.0, 0.0); glVertex3f(x,       y,        0.0);
                glTexCoord2f(0.0, 0.0); glVertex3f(x,       y,        0.0);
        glEnd();
        glEnd();
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_TEXTURE_2D);
}
}
 
 
void draw_terminal(const world_t *world, terminal_t *t, char *name)
void draw_terminal(const world_t *world, terminal_t *t, const char * const name) {
{
 
        assert(world);
        assert(world);
        assert(t);
        assert(t);
        glMatrixMode(GL_MODELVIEW);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glPushMatrix();
 
 
        static const double scale_x = 0.011;
        static const double scale_x = 0.011;
        static const double scale_y = 0.011;
        static const double scale_y = 0.011;
        vt100_t *v = &t->vt100;
        const vt100_t * const v = &t->vt100;
        double now = world->tick - t->blink_count;
        const scale_t scale = font_attributes();
        scale_t scale = font_attributes();
        const double now = world->tick - t->blink_count;
        double char_width  = scale.x / X_MAX;
        const double char_width  = scale.x / X_MAX;
        double char_height = scale.y / Y_MAX;
        const double char_height = scale.y / Y_MAX;
        size_t cursor_x = v->cursor % v->width;
        const size_t cursor_x = v->cursor % v->width;
        size_t cursor_y = v->cursor / v->width;
        const size_t cursor_y = v->cursor / v->width;
 
 
        if(now > seconds_to_ticks(world, 1.0)) {
        if(now > seconds_to_ticks(world, 1.0)) {
                t->blink_on = !(t->blink_on);
                t->blink_on = !(t->blink_on);
                t->blink_count = world->tick;
                t->blink_count = world->tick;
        }
        }
Line 846... Line 840...
 
 
/* ====================================== Simulator Instances ================================== */
/* ====================================== Simulator Instances ================================== */
 
 
/* ====================================== H2 I/O Handling ====================================== */
/* ====================================== H2 I/O Handling ====================================== */
 
 
static uint16_t h2_io_get_gui(h2_soc_state_t *soc, uint16_t addr, bool *debug_on)
static uint16_t h2_io_get_gui(h2_soc_state_t * const soc, const uint16_t addr, bool *debug_on) {
{
 
        assert(soc);
        assert(soc);
        assert(ps2_rx_fifo);
        assert(ps2_rx_fifo);
        assert(uart_tx_fifo);
        assert(uart_tx_fifo);
        assert(uart_rx_fifo);
        assert(uart_rx_fifo);
 
 
        if(debug_on)
        if(debug_on)
                *debug_on = false;
                *debug_on = false;
        switch(addr) {
        switch(addr) {
        case iUart:
        case iUart:
                {
                return (fifo_is_empty(uart_tx_fifo) << UART_TX_FIFO_EMPTY_BIT)
                        uint16_t r = 0;
                        | (fifo_is_full(uart_tx_fifo)  << UART_TX_FIFO_FULL_BIT)
                        r |= fifo_is_empty(uart_tx_fifo) << UART_TX_FIFO_EMPTY_BIT;
                        | (fifo_is_empty(uart_rx_fifo) << UART_RX_FIFO_EMPTY_BIT)
                        r |= fifo_is_full(uart_tx_fifo)  << UART_TX_FIFO_FULL_BIT;
                        | (fifo_is_full(uart_rx_fifo)  << UART_RX_FIFO_FULL_BIT)
                        r |= fifo_is_empty(uart_rx_fifo) << UART_RX_FIFO_EMPTY_BIT;
                        | soc->uart_getchar_register;
                        r |= fifo_is_full(uart_rx_fifo)  << UART_RX_FIFO_FULL_BIT;
 
                        r |= soc->uart_getchar_register;
 
                        return r;
 
                }
 
        case iVT100:
        case iVT100:
                {
                return (1u << UART_TX_FIFO_EMPTY_BIT)
                        uint16_t r = 0;
                        | (0u << UART_TX_FIFO_FULL_BIT)
                        r |= 1u << UART_TX_FIFO_EMPTY_BIT;
                        | (fifo_is_empty(ps2_rx_fifo) << UART_RX_FIFO_EMPTY_BIT)
                        r |= 0u << UART_TX_FIFO_FULL_BIT;
                        | (fifo_is_full(ps2_rx_fifo)  << UART_RX_FIFO_FULL_BIT)
                        r |= fifo_is_empty(ps2_rx_fifo) << UART_RX_FIFO_EMPTY_BIT;
                        | soc->ps2_getchar_register;
                        r |= fifo_is_full(ps2_rx_fifo)  << UART_RX_FIFO_FULL_BIT;
 
                        r |= soc->uart_getchar_register;
 
                        return r;
 
                }
 
        case iSwitches:
        case iSwitches:
                return soc->switches;
                return soc->switches;
        case iTimerDin: return soc->timer;
        case iTimerDin: return soc->timer;
        case iMemDin:   return h2_io_memory_read_operation(soc);
        case iMemDin:   return h2_io_memory_read_operation(soc);
        default:
        default:
Line 887... Line 872...
                break;
                break;
        }
        }
        return 0;
        return 0;
}
}
 
 
/**@warning uses variables of static storage duration! */
static void h2_io_set_gui(h2_soc_state_t *soc, const uint16_t addr, const uint16_t value, bool *debug_on) {
static void h2_io_set_gui(h2_soc_state_t *soc, uint16_t addr, uint16_t value, bool *debug_on)
 
{
 
        assert(soc);
        assert(soc);
        assert(uart_tx_fifo);
        assert(uart_tx_fifo);
        assert(uart_rx_fifo);
        assert(uart_rx_fifo);
 
 
        if(debug_on)
        if(debug_on)
Line 936... Line 919...
                break;
                break;
        case oIrcMask:    soc->irc_mask     = value; break;
        case oIrcMask:    soc->irc_mask     = value; break;
        case oMemControl:
        case oMemControl:
                {
                {
                        soc->mem_control    = value;
                        soc->mem_control    = value;
 
                        const bool sram_cs  = soc->mem_control & SRAM_CHIP_SELECT;
                        bool sram_cs   = soc->mem_control & SRAM_CHIP_SELECT;
                        const bool oe       = soc->mem_control & FLASH_MEMORY_OE;
                        bool oe        = soc->mem_control & FLASH_MEMORY_OE;
                        const bool we       = soc->mem_control & FLASH_MEMORY_WE;
                        bool we        = soc->mem_control & FLASH_MEMORY_WE;
 
 
 
                        if(sram_cs && !oe && we)
                        if(sram_cs && !oe && we)
                                soc->vram[(((uint32_t)(soc->mem_control & FLASH_MASK_ADDR_UPPER_MASK) << 16) | soc->mem_addr_low) >> 1] = soc->mem_dout;
                                soc->vram[(((uint32_t)(soc->mem_control & FLASH_MASK_ADDR_UPPER_MASK) << 16) | soc->mem_addr_low) >> 1] = soc->mem_dout;
                        break;
                        break;
                }
                }
        case oMemAddrLow: soc->mem_addr_low   = value; break;
        case oMemAddrLow: soc->mem_addr_low   = value; break;
        case oMemDout:    soc->mem_dout       = value; break;
        case oMemDout:    soc->mem_dout       = value; break;
 
        case oUartTxBaud:  soc->uart_tx_baud = value; break;
 
        case oUartRxBaud:  soc->uart_rx_baud = value; break;
 
        case oUartControl: soc->uart_control = value; break;
        default:
        default:
                warning("invalid write to %04"PRIx16 ":%04"PRIx16, addr, value);
                warning("invalid write to %04"PRIx16 ":%04"PRIx16, addr, value);
                break;
                break;
        }
        }
}
}
 
 
/* ====================================== H2 I/O Handling ====================================== */
/* ====================================== H2 I/O Handling ====================================== */
 
 
/* ====================================== Main Loop ============================================ */
/* ====================================== Main Loop ============================================ */
 
 
static double fps(void)
static double fps(void) {
{
 
        static unsigned frame = 0, timebase = 0;
        static unsigned frame = 0, timebase = 0;
        static double fps = 0;
        static double fps = 0;
        int time = glutGet(GLUT_ELAPSED_TIME);
        const int time = glutGet(GLUT_ELAPSED_TIME);
        frame++;
        frame++;
        if(time - timebase > 1000) {
        if(time - timebase > 1000) {
                fps = frame*1000.0/(time-timebase);
                fps = frame*1000.0/(time-timebase);
                timebase = time;
                timebase = time;
                frame = 0;
                frame = 0;
        }
        }
        return fps;
        return fps;
}
}
 
 
static void draw_debug_info(const world_t *world, double fps, double x, double y)
static void draw_debug_info(const world_t *world, double fps, double x, double y) {
{
 
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        assert(world);
        assert(world);
        fifo_t *f = world->use_uart_input ? uart_rx_fifo : ps2_rx_fifo;
        fifo_t *f = world->use_uart_input ? uart_rx_fifo : ps2_rx_fifo;
        const char *fifo_str = world->use_uart_input ? "UART" : "PS/2";
        const char *fifo_str = world->use_uart_input ? "UART" : "PS/2";
        char buf[256] = { 0 };
 
 
 
        fill_textbox(&t, "tick:               %u", world->tick);
        fill_textbox(&t, "tick:               %u", world->tick);
        //fill_textbox(&t, "seconds:         %f", ticks_to_seconds(world->tick));
        //fill_textbox(&t, "seconds:         %f", ticks_to_seconds(world->tick));
        fill_textbox(&t, "fps:                %f", fps);
        fill_textbox(&t, "fps:                %f", fps);
 
 
        if(world->debug_extra) {
        if(world->debug_extra) {
 
                char buf[256] = { 0 };
                fill_textbox(&t, "Mode:               %s", world->debug_mode ? "step" : "continue");
                fill_textbox(&t, "Mode:               %s", world->debug_mode ? "step" : "continue");
                fill_textbox(&t, "%s RX fifo full:  %s", fifo_str, fifo_is_full(f)  ? "true" : "false");
                fill_textbox(&t, "%s RX FIFO full:  %s",   fifo_str, fifo_is_full(f)  ? "true" : "false");
                fill_textbox(&t, "%s RX fifo empty: %s", fifo_str, fifo_is_empty(f) ? "true" : "false");
                fill_textbox(&t, "%s RX FIFO empty: %s",   fifo_str, fifo_is_empty(f) ? "true" : "false");
                fill_textbox(&t, "%s RX fifo count: %u", fifo_str, (unsigned)fifo_count(f));
                fill_textbox(&t, "%s RX FIFO count: %u",   fifo_str, (unsigned)fifo_count(f));
                fill_textbox(&t, "UART TX fifo full:  %s", fifo_is_full(uart_tx_fifo)  ? "true" : "false");
                fill_textbox(&t, "UART TX FIFO full:  %s", fifo_is_full(uart_tx_fifo)  ? "true" : "false");
                fill_textbox(&t, "UART TX fifo empty: %s", fifo_is_empty(uart_tx_fifo) ? "true" : "false");
                fill_textbox(&t, "UART TX FIFO empty: %s", fifo_is_empty(uart_tx_fifo) ? "true" : "false");
                fill_textbox(&t, "UART TX fifo count: %u", (unsigned)fifo_count(uart_tx_fifo));
                fill_textbox(&t, "UART TX FIFO count: %u", (unsigned)fifo_count(uart_tx_fifo));
 
 
                sprintf(buf, "%08lu", (unsigned long)(world->cycle_count));
                sprintf(buf, "%08lu", (unsigned long)(world->cycle_count));
                fill_textbox(&t, "cycles:             %s", buf);
                fill_textbox(&t, "cycles:             %s", buf);
                fill_textbox(&t, "cycles/tick         %u", (unsigned)(world->cycles));
                fill_textbox(&t, "cycles/tick:        %u", (unsigned)(world->cycles));
        }
        }
        draw_textbox(&t);
        draw_textbox(&t);
}
}
 
 
static void fill_textbox_memory(textbox_t *t, uint16_t *m, size_t length)
static void fill_textbox_memory(textbox_t *t, const uint16_t * const m, const size_t length) {
{
 
        assert(t);
        assert(t);
        assert(m);
        assert(m);
        assert((length % 4) == 0);
        assert((length % 4) == 0);
        for(size_t i = 0; i < length; i+=4)
        for(size_t i = 0; i < length; i+=4)
                fill_textbox(t, "%s%u: %x %x %x %x", i < 10 ? " " : "", i, m[i], m[i+1], m[i+2], m[i+3]);
                fill_textbox(t, "%s%u: %x %x %x %x", i < 10 ? " " : "", i, m[i], m[i+1], m[i+2], m[i+3]);
}
}
 
 
static void draw_debug_h2_screen_1(h2_t *h, double x, double y)
static void draw_debug_h2_screen_1(h2_t *h, double x, double y) {
{
 
        assert(h);
        assert(h);
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        fill_textbox(&t, "H2 CPU State", h->tos);
        fill_textbox(&t, "H2 CPU State", h->tos);
        fill_textbox(&t, "tp: %u", h->tos);
        fill_textbox(&t, "tp: %u", h->tos);
        fill_textbox_memory(&t, h->dstk, STK_SIZE);
        fill_textbox_memory(&t, h->dstk, STK_SIZE);
Line 1022... Line 1002...
        fill_textbox(&t, "dp: %u (max %u)", h->sp, h->spm);
        fill_textbox(&t, "dp: %u (max %u)", h->sp, h->spm);
        fill_textbox(&t, "ie: %s", h->ie ? "true" : "false");
        fill_textbox(&t, "ie: %s", h->ie ? "true" : "false");
        draw_textbox(&t);
        draw_textbox(&t);
}
}
 
 
static void draw_debug_h2_screen_2(h2_t *h, double x, double y)
static void draw_debug_h2_screen_2(const h2_t * const h, const double x, const double y) {
{
 
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        assert(h);
        assert(h);
        fill_textbox(&t, "H2 CPU Return Stack");
        fill_textbox(&t, "H2 CPU Return Stack");
        fill_textbox_memory(&t, h->rstk, STK_SIZE);
        fill_textbox_memory(&t, h->rstk, STK_SIZE);
        draw_textbox(&t);
        draw_textbox(&t);
}
}
 
 
static void draw_debug_h2_screen_3(h2_io_t *io, double x, double y)
static void draw_debug_h2_screen_3(const h2_io_t * const io, const double x, const double y) {
{
 
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        textbox_t t = { .x = x, .y = y, .draw_border = true, .color_text = WHITE, .color_box = WHITE };
        assert(io);
        assert(io);
        assert(io->soc);
        assert(io->soc);
        h2_soc_state_t *s = io->soc;
        const h2_soc_state_t * const s = io->soc;
        fill_textbox(&t, "I/O");
        fill_textbox(&t, "I/O");
        fill_textbox(&t, "LED             %x", (unsigned)s->leds);
        fill_textbox(&t, "LED             %x", (unsigned)s->leds);
        /*fill_textbox(&t, "VGA Cursor:     %x", (unsigned)s->vga_cursor);*/
        /*fill_textbox(&t, "VGA Cursor:     %x", (unsigned)s->vga_cursor);*/
        fill_textbox(&t, "Timer Control:  %x", (unsigned)s->timer_control);
        fill_textbox(&t, "Timer Control:  %x", (unsigned)s->timer_control);
        fill_textbox(&t, "Timer Count:    %x", (unsigned)s->timer);
        fill_textbox(&t, "Timer Count:    %x", (unsigned)s->timer);
Line 1060... Line 1038...
        fill_textbox(&t, "mode:           %x", (unsigned)s->flash.mode);
        fill_textbox(&t, "mode:           %x", (unsigned)s->flash.mode);
        fill_textbox(&t, "status:         %x", (unsigned)s->flash.status);
        fill_textbox(&t, "status:         %x", (unsigned)s->flash.status);
        fill_textbox(&t, "address arg 1:  %x", (unsigned)s->flash.arg1_address);
        fill_textbox(&t, "address arg 1:  %x", (unsigned)s->flash.arg1_address);
        fill_textbox(&t, "data            %x", (unsigned)s->flash.data);
        fill_textbox(&t, "data            %x", (unsigned)s->flash.data);
        fill_textbox(&t, "cycle:          %x", (unsigned)s->flash.cycle);
        fill_textbox(&t, "cycle:          %x", (unsigned)s->flash.cycle);
 
        fill_textbox(&t, "UART Control");
 
        fill_textbox(&t, "UART TX Baud:   %x", (unsigned)s->uart_tx_baud);
 
        fill_textbox(&t, "UART RX Baud:   %x", (unsigned)s->uart_rx_baud);
 
        fill_textbox(&t, "UART Control:   %x", (unsigned)s->uart_control);
        draw_textbox(&t);
        draw_textbox(&t);
}
}
 
 
static void keyboard_handler(unsigned char key, int x, int y)
static void keyboard_handler(const unsigned char key, const int x, const int y) {
{
 
        UNUSED(x);
        UNUSED(x);
        UNUSED(y);
        UNUSED(y);
        assert(uart_tx_fifo);
        assert(uart_tx_fifo);
        assert(ps2_rx_fifo);
        assert(ps2_rx_fifo);
        if(key == ESCAPE) {
        if(key == ESCAPE) {
Line 1079... Line 1060...
                else
                else
                        fifo_push(ps2_rx_fifo, key);
                        fifo_push(ps2_rx_fifo, key);
        }
        }
}
}
 
 
static void keyboard_special_handler(int key, int x, int y)
static void keyboard_special_handler(const int key, const int x, const int y) {
{
 
        UNUSED(x);
        UNUSED(x);
        UNUSED(y);
        UNUSED(y);
        switch(key) {
        switch(key) {
        case GLUT_KEY_UP:    dpad.up    = true; break;
        case GLUT_KEY_UP:    dpad.up    = true; break;
        case GLUT_KEY_LEFT:  dpad.left  = true; break;
        case GLUT_KEY_LEFT:  dpad.left  = true; break;
Line 1107... Line 1087...
        default:
        default:
                break;
                break;
        }
        }
}
}
 
 
static void keyboard_special_up_handler(int key, int x, int y)
static void keyboard_special_up_handler(const int key, const int x, const int y) {
{
 
        UNUSED(x);
        UNUSED(x);
        UNUSED(y);
        UNUSED(y);
        switch(key) {
        switch(key) {
        case GLUT_KEY_UP:    dpad.up    = false; break;
        case GLUT_KEY_UP:    dpad.up    = false; break;
        case GLUT_KEY_LEFT:  dpad.left  = false; break;
        case GLUT_KEY_LEFT:  dpad.left  = false; break;
Line 1126... Line 1105...
typedef struct {
typedef struct {
        double x;
        double x;
        double y;
        double y;
} coordinate_t;
} coordinate_t;
 
 
static double abs_diff(double a, double b)
static double abs_diff(const double a, const double b) {
{
 
        return fabsl(fabsl(a) - fabsl(b));
        return fabsl(fabsl(a) - fabsl(b));
}
}
 
 
static void resize_window(int w, int h)
static void resize_window(int w, int h) {
{
 
        double window_x_min, window_x_max, window_y_min, window_y_max;
        double window_x_min, window_x_max, window_y_min, window_y_max;
        double scale, center;
        double scale, center;
        world.window_width  = w;
        world.window_width  = w;
        world.window_height = h;
        world.window_height = h;
 
 
Line 1165... Line 1142...
        glMatrixMode(GL_PROJECTION);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glLoadIdentity();
        glOrtho(window_x_min, window_x_max, window_y_min, window_y_max, -1, 1);
        glOrtho(window_x_min, window_x_max, window_y_min, window_y_max, -1, 1);
}
}
 
 
static coordinate_t pixels_to_coordinates(const world_t *world, int x, int y)
static coordinate_t pixels_to_coordinates(const world_t *world, const int x, const int y) {
{
 
        assert(world);
        assert(world);
        coordinate_t c = { .0, .0 };
        const double xd = abs_diff(X_MAX, X_MIN);
        double xd = abs_diff(X_MAX, X_MIN);
        const double yd = abs_diff(Y_MAX, Y_MIN);
        double yd = abs_diff(Y_MAX, Y_MIN);
        const double xs = world->window_width  / world->window_scale_x;
        double xs = world->window_width  / world->window_scale_x;
        const double ys = world->window_height / world->window_scale_y;
        double ys = world->window_height / world->window_scale_y;
        const coordinate_t c = {
        c.x = Y_MIN + (xd * ((x - (world->window_width  - xs)/2.) / xs));
                .x = Y_MIN + (xd * ((x - (world->window_width  - xs)/2.) / xs)),
        c.y = Y_MAX - (yd * ((y - (world->window_height - ys)/2.) / ys));
                .y = Y_MAX - (yd * ((y - (world->window_height - ys)/2.) / ys))
 
        };
        return c;
        return c;
}
}
 
 
static void mouse_handler(int button, int state, int x, int y)
static void mouse_handler(const int button, const int state, const int x, const int y) {
{
        const coordinate_t c = pixels_to_coordinates(&world, x, y);
        coordinate_t c = pixels_to_coordinates(&world, x, y);
 
 
 
        for(size_t i = 0; i < SWITCHES_COUNT; i++) {
        for(size_t i = 0; i < SWITCHES_COUNT; i++) {
                if(detect_circle_circle_collision(c.x, c.y, 0.1, switches[i].x, switches[i].y, switches[i].radius)) {
                if(detect_circle_circle_collision(c.x, c.y, 0.1, switches[i].x, switches[i].y, switches[i].radius)) {
                        if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
                        if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
                                switches[i].on = true;
                                switches[i].on = true;
Line 1210... Line 1186...
                dpad.up     = false;
                dpad.up     = false;
                dpad.center = false;
                dpad.center = false;
        }
        }
}
}
 
 
static void timer_callback(int value)
static void timer_callback(const int value) {
{
 
        world.tick++;
        world.tick++;
        glutTimerFunc(world.arena_tick_ms, timer_callback, value);
        glutTimerFunc(world.arena_tick_ms, timer_callback, value);
}
}
 
 
static void update_switches(void)
static void update_switches(void) {
{
 
        h2_io->soc->switches = 0;
        h2_io->soc->switches = 0;
        for(size_t i = 0; i < SWITCHES_COUNT; i++)
        for(size_t i = 0; i < SWITCHES_COUNT; i++)
                h2_io->soc->switches |= switches[i].on << i;
                h2_io->soc->switches |= switches[i].on << i;
        h2_io->soc->switches |= dpad.center << (SWITCHES_COUNT+0);
        h2_io->soc->switches |= dpad.center << (SWITCHES_COUNT+0);
        h2_io->soc->switches |= dpad.right  << (SWITCHES_COUNT+1);
        h2_io->soc->switches |= dpad.right  << (SWITCHES_COUNT+1);
        h2_io->soc->switches |= dpad.left   << (SWITCHES_COUNT+2);
        h2_io->soc->switches |= dpad.left   << (SWITCHES_COUNT+2);
        h2_io->soc->switches |= dpad.down   << (SWITCHES_COUNT+3);
        h2_io->soc->switches |= dpad.down   << (SWITCHES_COUNT+3);
        h2_io->soc->switches |= dpad.up     << (SWITCHES_COUNT+4);
        h2_io->soc->switches |= dpad.up     << (SWITCHES_COUNT+4);
}
}
 
 
static void draw_scene(void)
static void draw_scene(void) {
{
        static uint64_t next = 0;  // @warning static!
        static uint64_t next = 0;
        static uint64_t count = 0; // @warning static!
        static uint64_t count = 0;
 
        double f = fps();
        double f = fps();
        if(world.halt_simulation)
        if(world.halt_simulation)
                exit(EXIT_SUCCESS);
                exit(EXIT_SUCCESS);
 
 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Line 1267... Line 1240...
                                world.cycles = MAX(CYCLE_MINIMUM, n);
                                world.cycles = MAX(CYCLE_MINIMUM, n);
                        }
                        }
                }
                }
 
 
                if(increment)
                if(increment)
                        if(h2_run(h, h2_io, stderr, increment, NULL, false) < 0)
                        if (h2_run(h, h2_io, stderr, increment, NULL, false, trace_file) < 0)
                                world.halt_simulation = true;
                                world.halt_simulation = true;
 
 
                world.step = false;
                world.step = false;
                world.cycle_count += increment;
                world.cycle_count += increment;
        }
        }
Line 1317... Line 1290...
        glFlush();
        glFlush();
        glutSwapBuffers();
        glutSwapBuffers();
        glutPostRedisplay();
        glutPostRedisplay();
}
}
 
 
static void initialize_rendering(char *arg_0)
static void initialize_rendering(char *arg_0) {
{
 
        char *glut_argv[] = { arg_0, NULL };
        char *glut_argv[] = { arg_0, NULL };
        int glut_argc = 0;
        int glut_argc = 0;
        memset(uart_terminal.vt100.m, ' ', uart_terminal.vt100.size);
        memset(uart_terminal.vt100.m, ' ', uart_terminal.vt100.size);
        glutInit(&glut_argc, glut_argv);
        glutInit(&glut_argc, glut_argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
Line 1338... Line 1310...
        glutReshapeFunc(resize_window);
        glutReshapeFunc(resize_window);
        glutDisplayFunc(draw_scene);
        glutDisplayFunc(draw_scene);
        glutTimerFunc(world.arena_tick_ms, timer_callback, 0);
        glutTimerFunc(world.arena_tick_ms, timer_callback, 0);
}
}
 
 
static void vt100_initialize(vt100_t *v)
static void vt100_initialize(vt100_t * const v) {
{
 
        assert(v);
        assert(v);
        memset(&v->attribute, 0, sizeof(v->attribute));
        memset(&v->attribute, 0, sizeof(v->attribute));
        v->attribute.foreground_color = WHITE;
        v->attribute.foreground_color = WHITE;
        v->attribute.background_color = BLACK;
        v->attribute.background_color = BLACK;
        for(size_t i = 0; i < v->size; i++)
        for(size_t i = 0; i < v->size; i++)
                v->attributes[i] = v->attribute;
                v->attributes[i] = v->attribute;
}
}
 
 
static void finalize(void)
static void finalize(void) {
{
        nvram_save(h2_io, FLASH_INIT_FILE);
        nvram_save(h2_io, nvram_file);
 
        h2_free(h);
        h2_free(h);
        h2_io_free(h2_io);
        h2_io_free(h2_io);
        fifo_free(uart_tx_fifo);
        fifo_free(uart_tx_fifo);
        fifo_free(uart_rx_fifo);
        fifo_free(uart_rx_fifo);
        fifo_free(ps2_rx_fifo);
        fifo_free(ps2_rx_fifo);
 
        if (trace_file)
 
                fclose(trace_file);
}
}
 
 
int main(int argc, char **argv)
int main(int argc, char **argv) {
{
 
        FILE *hexfile = NULL;
        FILE *hexfile = NULL;
        int r = 0;
        int r = 0;
 
 
        assert(Y_MAX > 0. && Y_MIN < Y_MAX && Y_MIN >= 0.);
        assert(Y_MAX > 0. && Y_MIN < Y_MAX && Y_MIN >= 0.);
        assert(X_MAX > 0. && X_MIN < X_MAX && X_MIN >= 0.);
        assert(X_MAX > 0. && X_MIN < X_MAX && X_MIN >= 0.);
Line 1408... Line 1379...
 
 
        uart_rx_fifo = fifo_new(UART_FIFO_DEPTH);
        uart_rx_fifo = fifo_new(UART_FIFO_DEPTH);
        uart_tx_fifo = fifo_new(UART_FIFO_DEPTH * 100); /** @note x100 to speed things up */
        uart_tx_fifo = fifo_new(UART_FIFO_DEPTH * 100); /** @note x100 to speed things up */
        ps2_rx_fifo  = fifo_new(8 /** @bug should be 1 - but this does not work, FIFO implementation needs correcting */);
        ps2_rx_fifo  = fifo_new(8 /** @bug should be 1 - but this does not work, FIFO implementation needs correcting */);
 
 
        nvram_load_and_transfer(h2_io, nvram_file, true);
        nvram_load_and_transfer(h2_io, FLASH_INIT_FILE, true);
 
 
 
        if (TRON) {
 
                errno = 0;
 
                trace_file = fopen(TRACE_FILE, "wb");
 
                if (trace_file)
 
                        setvbuf(trace_file, trace_buffer, _IOFBF, TRACE_BUFFER_LEN);
 
                else
 
                        warning("could not open %s for writing: %s", TRACE_FILE, strerror(errno));
 
        }
 
 
        atexit(finalize);
        atexit(finalize);
        initialize_rendering(argv[0]);
        initialize_rendering(argv[0]);
        glutMainLoop();
        glutMainLoop();
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.