|
|
|
/**
|
|
|
|
* \defgroup unixsimulator Simulation of the Borg API for UNIX like platforms.
|
|
|
|
*/
|
|
|
|
/*@{*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file main.c
|
|
|
|
* @brief Simulator for Unix like platforms.
|
|
|
|
* @author Martin Ongsiek, Peter Fuhrmann, Christian Kroll
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef OSX_
|
|
|
|
#include <GLUT/glut.h>
|
|
|
|
#else
|
|
|
|
#include <GL/glut.h>
|
|
|
|
#endif
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
|
|
|
#include "../config.h"
|
|
|
|
#include "../display_loop.h"
|
|
|
|
#include "trackball.h"
|
|
|
|
|
|
|
|
/** Number of bytes per row. */
|
|
|
|
#define LINEBYTES ((NUM_COLS + 1) / 8)
|
|
|
|
|
|
|
|
/** Fake port for simulating joystick input. */
|
|
|
|
volatile unsigned char fakeport;
|
|
|
|
/** Flag which indicates if wait should jump to the menu if fire is pressed. */
|
|
|
|
volatile unsigned char waitForFire;
|
|
|
|
/** The simulated frame buffer of the borg. */
|
|
|
|
volatile unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
|
|
|
|
/** Jump buffer which leads directly the menu. */
|
|
|
|
extern jmp_buf newmode_jmpbuf;
|
|
|
|
|
|
|
|
/** Width of the window. */
|
|
|
|
int WindWidth;
|
|
|
|
/** Height of the window. */
|
|
|
|
int WindHeight;
|
|
|
|
|
|
|
|
/** Rotation of the x-axis of the scene. */
|
|
|
|
float view_rotx = 0;
|
|
|
|
/** Rotation of the y-axis of the scene. */
|
|
|
|
float view_roty = 0;
|
|
|
|
/** Rotation of the z-axis of the scene. */
|
|
|
|
float view_rotz = 0;
|
|
|
|
|
|
|
|
/** GLUT window handle. */
|
|
|
|
int win;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Simple wait function.
|
|
|
|
* @param ms The requested delay in milliseconds.
|
|
|
|
*/
|
|
|
|
void wait(unsigned int ms) {
|
|
|
|
if (waitForFire) {
|
|
|
|
if (fakeport & 0x01) {
|
|
|
|
longjmp(newmode_jmpbuf, 43);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
usleep(ms * 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Draw a LED in the given color (which is a list).
|
|
|
|
* @param color List which contains a sphere.
|
|
|
|
* @param pos_x x-coordinate
|
|
|
|
* @param pos_y y-coordinate
|
|
|
|
* @param pos_z z-coordinate
|
|
|
|
*/
|
|
|
|
void drawLED(int color, float pos_x, float pos_y, float pos_z) {
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(pos_x, pos_y, pos_z);
|
|
|
|
glCallList(color);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Draws the LED matrix.
|
|
|
|
*/
|
|
|
|
void display(void) {
|
|
|
|
int x, y, z, level, color;
|
|
|
|
tbReshape(WindWidth, WindHeight);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(NUM_COLS * 2., 0., NUM_ROWS * 2.);
|
|
|
|
tbMatrix();
|
|
|
|
glRotatef(view_rotx, 1.0, 0.0, 0.0);
|
|
|
|
glRotatef(view_roty, 0.0, 1.0, 0.0);
|
|
|
|
glRotatef(view_rotz, 0.0, 0.0, 1.0);
|
|
|
|
glTranslatef(-NUM_COLS * 2, 0., -NUM_ROWS * 2.);
|
|
|
|
for (x = 0; x < 1; x++) {
|
|
|
|
for (y = 0; y < NUM_COLS; y++) {
|
|
|
|
for (z = 0; z < NUM_ROWS; z++) {
|
|
|
|
color = 0;
|
|
|
|
for (level = 0; level < NUMPLANE; level++) {
|
|
|
|
if (pixmap[level][z % NUM_ROWS][y / 8] & (1 << y % 8)) {
|
|
|
|
color = level + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
drawLED(color, (float) y * 4.0, (float) x * 4.0,
|
|
|
|
(float) (NUM_ROWS - 1 - z) * 4.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glPopMatrix();
|
|
|
|
glutSwapBuffers();
|
|
|
|
|
|
|
|
usleep(20000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for processing key presses.
|
|
|
|
* @param key The pressed key encoded in ASCII.
|
|
|
|
* @param x X-position of the mouse pointer.
|
|
|
|
* @param y Y-position of the mouse pointer.
|
|
|
|
*/
|
|
|
|
void keyboard(unsigned char key, int x, int y) {
|
|
|
|
switch (key) {
|
|
|
|
case 'q':
|
|
|
|
printf("Quit\n");
|
|
|
|
glutDestroyWindow(win);
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
fakeport |= 0x01;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
fakeport |= 0x02;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
fakeport |= 0x04;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
fakeport |= 0x08;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
fakeport |= 0x10;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for processing key releases.
|
|
|
|
* @param key The released key encoded in ASCII.
|
|
|
|
* @param x X-position of the mouse pointer.
|
|
|
|
* @param y Y-position of the mouse pointer.
|
|
|
|
*/
|
|
|
|
void keyboardup(unsigned char key, int x, int y) {
|
|
|
|
switch (key) {
|
|
|
|
case ' ':
|
|
|
|
fakeport &= ~0x01;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
fakeport &= ~0x02;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
fakeport &= ~0x04;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
fakeport &= ~0x08;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
fakeport &= ~0x10;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Relays mouse position and button state to the trackball implementation.
|
|
|
|
* @param button Currently monitored button.
|
|
|
|
* @param state State of that button.
|
|
|
|
* @param x X-position of the mouse pointer.
|
|
|
|
* @param y Y-position of the mouse pointer.
|
|
|
|
*/
|
|
|
|
void mouse(int button, int state, int x, int y) {
|
|
|
|
tbMouse(button, state, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Relays motion request to the trackball implementation.
|
|
|
|
* @param x X-position for the motion direction.
|
|
|
|
* @param y Y-position for the motion direction.
|
|
|
|
*/
|
|
|
|
void motion(int x, int y) {
|
|
|
|
tbMotion(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updating the window size.
|
|
|
|
* @param width Width of the window.
|
|
|
|
* @param height Height of the window.
|
|
|
|
*/
|
|
|
|
void reshape(int width, int height) {
|
|
|
|
|
|
|
|
tbReshape(width, height);
|
|
|
|
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.);
|
|
|
|
gluLookAt(NUM_ROWS * 2., NUM_ROWS * 2. + 50., NUM_COLS * 2., NUM_ROWS * 2.,
|
|
|
|
NUM_ROWS * 2., NUM_COLS * 2., 0.0, 0.0, 1.0);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
WindWidth = width;
|
|
|
|
WindHeight = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for special keys (the arrow keys in particular) for adjusting the
|
|
|
|
* view angle of the scene.
|
|
|
|
* @param k The pressed special key using GLUT's nomenclature.
|
|
|
|
* @param x X-position of the mouse pointer.
|
|
|
|
* @param y Y-position of the mouse pointer.
|
|
|
|
*/
|
|
|
|
static void special(int k, int x, int y) {
|
|
|
|
switch (k) {
|
|
|
|
case GLUT_KEY_UP:
|
|
|
|
view_rotx += 5.0;
|
|
|
|
break;
|
|
|
|
case GLUT_KEY_DOWN:
|
|
|
|
view_rotx -= 5.0;
|
|
|
|
break;
|
|
|
|
case GLUT_KEY_LEFT:
|
|
|
|
view_rotz += 5.0;
|
|
|
|
break;
|
|
|
|
case GLUT_KEY_RIGHT:
|
|
|
|
view_rotz -= 5.0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
glutPostRedisplay();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Entry point for starting the display loop thread.
|
|
|
|
* @param unused Not used. Only here to satisfy signature constraints.
|
|
|
|
*/
|
|
|
|
void *display_loop_run(void * unused) {
|
|
|
|
display_loop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Main function for the simulator.
|
|
|
|
* @param argc The argument count.
|
|
|
|
* @param argv Command line arguments.
|
|
|
|
* @return Exit codem, always zero.
|
|
|
|
*/
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
WindHeight = 700;
|
|
|
|
WindWidth = 700;
|
|
|
|
glutInit(&argc, argv);
|
|
|
|
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
|
|
|
glutInitWindowSize(WindHeight, WindWidth);
|
|
|
|
win = glutCreateWindow("16x16 Borg Simulator");
|
|
|
|
|
|
|
|
// callback
|
|
|
|
glutDisplayFunc(display);
|
|
|
|
glutIdleFunc(display);
|
|
|
|
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
|
|
|
|
glutKeyboardFunc(keyboard);
|
|
|
|
glutKeyboardUpFunc(keyboardup);
|
|
|
|
glutSpecialFunc(special);
|
|
|
|
glutMouseFunc(mouse);
|
|
|
|
glutMotionFunc(motion);
|
|
|
|
|
|
|
|
// clearcolor & main loop
|
|
|
|
glClearColor(0, 0, 0, 1.0);
|
|
|
|
gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.);
|
|
|
|
gluLookAt(NUM_COLS * 2., NUM_COLS * 2. + 50., NUM_ROWS * 2., NUM_COLS * 2.,
|
|
|
|
NUM_COLS * 2., NUM_ROWS * 2., 0.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
// init Call List for LED
|
|
|
|
GLUquadric* quad = gluNewQuadric();
|
|
|
|
glNewList(0, GL_COMPILE);
|
|
|
|
glColor4f(0.8, 0.0, 0.0, 1.);
|
|
|
|
gluSphere(quad, 1.0, 12, 12);
|
|
|
|
glEndList();
|
|
|
|
glNewList(1, GL_COMPILE);
|
|
|
|
glColor4f(0.5, 0.0, 0.0, 1.);
|
|
|
|
gluSphere(quad, 1.4, 12, 12);
|
|
|
|
glEndList();
|
|
|
|
glNewList(2, GL_COMPILE);
|
|
|
|
glColor4f(0.7, 0.0, 0.0, 1.);
|
|
|
|
gluSphere(quad, 1.55, 12, 12);
|
|
|
|
glEndList();
|
|
|
|
glNewList(3, GL_COMPILE);
|
|
|
|
glColor4f(1.00, 0.0, 0.0, 1.);
|
|
|
|
gluSphere(quad, 1.7, 12, 12);
|
|
|
|
glEndList();
|
|
|
|
|
|
|
|
tbInit(GLUT_LEFT_BUTTON);
|
|
|
|
tbAnimate(GL_FALSE);
|
|
|
|
|
|
|
|
pthread_t simthread;
|
|
|
|
pthread_create(&simthread, NULL, display_loop_run, NULL);
|
|
|
|
|
|
|
|
glutMainLoop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*@}*/
|