Rewrote API simulator from scratch for Win32 since Cygwin ceased support for Win32's native OpenGL libraries.
This commit is contained in:
parent
3e7ee74414
commit
971901e453
12
defaults.mk
12
defaults.mk
|
@ -21,7 +21,7 @@ LIBS = -lm
|
||||||
|
|
||||||
# flags for the compiler
|
# flags for the compiler
|
||||||
CFLAGS ?= -Wall -W -Wno-unused-parameter -Wno-sign-compare
|
CFLAGS ?= -Wall -W -Wno-unused-parameter -Wno-sign-compare
|
||||||
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline -D_XOPEN_SOURCE=600 -DNDEBUG
|
CFLAGS += -g -Os -std=gnu99 -mstrict-X -fgnu89-inline -D_XOPEN_SOURCE=600 -DNDEBUG
|
||||||
|
|
||||||
# flags for the linker
|
# flags for the linker
|
||||||
LDFLAGS += -T ./avr5.x -Wl,-Map,image.map -mmcu=$(MCU)
|
LDFLAGS += -T ./avr5.x -Wl,-Map,image.map -mmcu=$(MCU)
|
||||||
|
@ -35,13 +35,13 @@ MACHINE = $(shell uname -m)
|
||||||
#$(info $(OSTYPE))
|
#$(info $(OSTYPE))
|
||||||
|
|
||||||
ifeq ($(OSTYPE),cygwin)
|
ifeq ($(OSTYPE),cygwin)
|
||||||
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_WIN32 -mno-cygwin -D_XOPEN_SOURCE=600
|
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_WIN32 -D_XOPEN_SOURCE=600
|
||||||
LDFLAGS_SIM = -Wl -mno-cygwin -T simulator/i386pe.x
|
LDFLAGS_SIM = -Wl -T simulator/i386pe.x
|
||||||
LIBS_SIM = -lglut32 -lglu32 -lopengl32 -lm
|
LIBS_SIM = -lgdi32 -lwinmm -lm
|
||||||
else
|
else
|
||||||
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600
|
CFLAGS_SIM = -g -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600
|
||||||
ifeq ($(MACHINE),x86_64)
|
ifeq ($(MACHINE),x86_64)
|
||||||
LDFLAGS_SIM = -Wl -T simulator/elf_x86_64.x
|
LDFLAGS_SIM = -g -Wl -T simulator/elf_x86_64.x
|
||||||
else
|
else
|
||||||
LDFLAGS_SIM = -Wl -T simulator/elf_i386.x
|
LDFLAGS_SIM = -Wl -T simulator/elf_i386.x
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -3,7 +3,10 @@ TOPDIR = ..
|
||||||
|
|
||||||
include $(TOPDIR)/defaults.mk
|
include $(TOPDIR)/defaults.mk
|
||||||
|
|
||||||
SRC_SIM = main.c trackball.c util.c eeprom.c
|
ifeq ($(OSTYPE),cygwin)
|
||||||
|
SRC_SIM = winmain.c trackball.c eeprom.c
|
||||||
|
else
|
||||||
|
SRC_SIM = main.c trackball.c eeprom.c
|
||||||
|
endif
|
||||||
|
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* Default linker script, for normal executables */
|
/* Default linker script, for normal executables */
|
||||||
OUTPUT_FORMAT(pei-i386)
|
OUTPUT_FORMAT(pei-i386)
|
||||||
SEARCH_DIR("/usr/i686-pc-cygwin/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib/w32api");
|
SEARCH_DIR("/usr/i686-cygwin/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib/w32api");
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
/* Make the virtual address and file offset synced if the alignment is
|
/* Make the virtual address and file offset synced if the alignment is
|
||||||
|
@ -12,6 +12,8 @@ SECTIONS
|
||||||
*(.init)
|
*(.init)
|
||||||
*(.text)
|
*(.text)
|
||||||
*(SORT(.text$*))
|
*(SORT(.text$*))
|
||||||
|
*(.text.*)
|
||||||
|
*(.gnu.linkonce.t.*)
|
||||||
*(.glue_7t)
|
*(.glue_7t)
|
||||||
*(.glue_7)
|
*(.glue_7)
|
||||||
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
|
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
|
||||||
|
@ -28,7 +30,7 @@ SECTIONS
|
||||||
on fork. This used to be named ".data". The linker used
|
on fork. This used to be named ".data". The linker used
|
||||||
to include this between __data_start__ and __data_end__, but that
|
to include this between __data_start__ and __data_end__, but that
|
||||||
breaks building the cygwin32 dll. Instead, we name the section
|
breaks building the cygwin32 dll. Instead, we name the section
|
||||||
".data_cygwin_nocopy" and explictly include it after __data_end__. */
|
".data_cygwin_nocopy" and explicitly include it after __data_end__. */
|
||||||
.data BLOCK(__section_alignment__) :
|
.data BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
__data_start__ = . ;
|
__data_start__ = . ;
|
||||||
|
@ -48,12 +50,18 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.rdata)
|
*(.rdata)
|
||||||
*(SORT(.rdata$*))
|
*(SORT(.rdata$*))
|
||||||
*(.eh_frame)
|
__rt_psrelocs_start = .;
|
||||||
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
|
||||||
__RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
|
||||||
*(.rdata_runtime_pseudo_reloc)
|
*(.rdata_runtime_pseudo_reloc)
|
||||||
|
__rt_psrelocs_end = .;
|
||||||
|
}
|
||||||
|
__rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start;
|
||||||
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
||||||
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
||||||
|
___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;
|
||||||
|
__RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;
|
||||||
|
.eh_frame BLOCK(__section_alignment__) :
|
||||||
|
{
|
||||||
|
*(.eh_frame*)
|
||||||
}
|
}
|
||||||
.pdata BLOCK(__section_alignment__) :
|
.pdata BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
|
@ -76,6 +84,8 @@ SECTIONS
|
||||||
*(.debug$T)
|
*(.debug$T)
|
||||||
*(.debug$F)
|
*(.debug$F)
|
||||||
*(.drectve)
|
*(.drectve)
|
||||||
|
*(.note.GNU-stack)
|
||||||
|
*(.gnu.lto_*)
|
||||||
}
|
}
|
||||||
.idata BLOCK(__section_alignment__) :
|
.idata BLOCK(__section_alignment__) :
|
||||||
{
|
{
|
||||||
|
@ -86,7 +96,9 @@ SECTIONS
|
||||||
/* These zeroes mark the end of the import list. */
|
/* These zeroes mark the end of the import list. */
|
||||||
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
||||||
SORT(*)(.idata$4)
|
SORT(*)(.idata$4)
|
||||||
|
__IAT_start__ = .;
|
||||||
SORT(*)(.idata$5)
|
SORT(*)(.idata$5)
|
||||||
|
__IAT_end__ = .;
|
||||||
SORT(*)(.idata$6)
|
SORT(*)(.idata$6)
|
||||||
SORT(*)(.idata$7)
|
SORT(*)(.idata$7)
|
||||||
}
|
}
|
||||||
|
@ -153,10 +165,14 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.debug_pubnames)
|
*(.debug_pubnames)
|
||||||
}
|
}
|
||||||
|
.debug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
|
{
|
||||||
|
*(.debug_pubtypes)
|
||||||
|
}
|
||||||
/* DWARF 2. */
|
/* DWARF 2. */
|
||||||
.debug_info BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_info BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
{
|
{
|
||||||
*(.debug_info) *(.gnu.linkonce.wi.*)
|
*(.debug_info .gnu.linkonce.wi.*)
|
||||||
}
|
}
|
||||||
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
{
|
{
|
||||||
|
@ -168,7 +184,7 @@ SECTIONS
|
||||||
}
|
}
|
||||||
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
{
|
{
|
||||||
*(.debug_frame)
|
*(.debug_frame*)
|
||||||
}
|
}
|
||||||
.debug_str BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_str BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
{
|
{
|
||||||
|
@ -199,9 +215,18 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.debug_varnames)
|
*(.debug_varnames)
|
||||||
}
|
}
|
||||||
|
.debug_macro BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
|
{
|
||||||
|
*(.debug_macro)
|
||||||
|
}
|
||||||
/* DWARF 3. */
|
/* DWARF 3. */
|
||||||
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
|
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
{
|
{
|
||||||
*(.debug_ranges)
|
*(.debug_ranges)
|
||||||
}
|
}
|
||||||
|
/* DWARF 4. */
|
||||||
|
.debug_types BLOCK(__section_alignment__) (NOLOAD) :
|
||||||
|
{
|
||||||
|
*(.debug_types .gnu.linkonce.wt.*)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#include "joystick.h"
|
|
||||||
|
|
||||||
unsigned char fakeport;
|
|
||||||
|
|
||||||
|
|
||||||
// fake function since our keybord doesn't need any initialisation
|
|
||||||
void joy_init()
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
#ifndef JOYSTICK_H_
|
|
||||||
#define JOYSTICK_H_
|
|
||||||
|
|
||||||
extern unsigned char fakeport;
|
|
||||||
|
|
||||||
#define JOYISFIRE (0x01 & fakeport)
|
|
||||||
#define JOYISLEFT (0x02 & fakeport)
|
|
||||||
#define JOYISRIGHT (0x04 & fakeport)
|
|
||||||
#define JOYISDOWN (0x08 & fakeport)
|
|
||||||
#define JOYISUP (0x10 & fakeport)
|
|
||||||
|
|
||||||
unsigned char waitForFire;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*JOYSTICK_H_*/
|
|
179
simulator/main.c
179
simulator/main.c
|
@ -1,46 +1,82 @@
|
||||||
#ifdef _WIN32
|
/**
|
||||||
#include <GL/glut.h>
|
* \defgroup unixsimulator Simulation of the Borg API for UNIX like platforms.
|
||||||
#include <windows.h>
|
*/
|
||||||
#include <process.h>
|
/*@{*/
|
||||||
#define pthread_t int
|
|
||||||
#else
|
/**
|
||||||
|
* @file main.c
|
||||||
|
* @brief Simulator for Unix like platforms.
|
||||||
|
* @author Martin Ongsiek, Peter Fuhrmann, Christian Kroll
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef OSX_
|
#ifdef OSX_
|
||||||
#include <GLUT/glut.h>
|
#include <GLUT/glut.h>
|
||||||
#else
|
#else
|
||||||
#include <GL/glut.h>
|
#include <GL/glut.h>
|
||||||
#endif
|
#endif
|
||||||
#include <pthread.h> // for threads in linux
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "../display_loop.h"
|
#include "../display_loop.h"
|
||||||
#include "../pixel.h"
|
|
||||||
#include "trackball.h"
|
#include "trackball.h"
|
||||||
|
|
||||||
unsigned char fakeport;
|
/** Number of bytes per row. */
|
||||||
volatile unsigned char oldMode, oldOldmode, mode;
|
#define LINEBYTES ((NUM_COLS + 1) / 8)
|
||||||
extern unsigned char waitForFire;
|
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
|
||||||
int WindWidth, WindHeight;
|
/** Width of the window. */
|
||||||
|
int WindWidth;
|
||||||
|
/** Height of the window. */
|
||||||
|
int WindHeight;
|
||||||
|
|
||||||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
|
/** Rotation of the x-axis of the scene. */
|
||||||
unsigned char joystick;
|
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;
|
||||||
|
|
||||||
float view_rotx = 0, view_roty = 0, view_rotz = 0;
|
/** GLUT window handle. */
|
||||||
int win;
|
int win;
|
||||||
|
|
||||||
|
|
||||||
pthread_t simthread;
|
/**
|
||||||
GLUquadric* quad;
|
* 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) {
|
void drawLED(int color, float pos_x, float pos_y, float pos_z) {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(pos_x, pos_y, pos_z);
|
glTranslatef(pos_x, pos_y, pos_z);
|
||||||
|
@ -48,6 +84,10 @@ void drawLED(int color, float pos_x, float pos_y, float pos_z) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the LED matrix.
|
||||||
|
*/
|
||||||
void display(void) {
|
void display(void) {
|
||||||
int x, y, z, level, color;
|
int x, y, z, level, color;
|
||||||
tbReshape(WindWidth, WindHeight);
|
tbReshape(WindWidth, WindHeight);
|
||||||
|
@ -68,25 +108,28 @@ void display(void){
|
||||||
color = level + 1;
|
color = level + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drawLED(color, (float)y*4.0,
|
drawLED(color, (float) y * 4.0, (float) x * 4.0,
|
||||||
(float)x*4.0,
|
|
||||||
(float) (NUM_ROWS - 1 - z) * 4.0);
|
(float) (NUM_ROWS - 1 - z) * 4.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glutSwapBuffers();
|
glutSwapBuffers();
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(10);
|
|
||||||
#else
|
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
#endif
|
|
||||||
joystick = 255;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
void keyboard(unsigned char key, int x, int y) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'q': printf("Quit\n");
|
case 'q':
|
||||||
|
printf("Quit\n");
|
||||||
glutDestroyWindow(win);
|
glutDestroyWindow(win);
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
@ -108,6 +151,13 @@ void keyboard(unsigned char key, int x, int y){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
void keyboardup(unsigned char key, int x, int y) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case ' ':
|
case ' ':
|
||||||
|
@ -128,18 +178,34 @@ void keyboardup(unsigned char key, int x, int y){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouse(int button, int state, int x, int y)
|
|
||||||
{
|
/**
|
||||||
|
* 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);
|
tbMouse(button, state, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void motion(int x, int 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);
|
tbMotion(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reshape(int width, int height)
|
/**
|
||||||
{
|
* 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);
|
tbReshape(width, height);
|
||||||
|
|
||||||
|
@ -148,9 +214,8 @@ void reshape(int width, int height)
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.);
|
gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.);
|
||||||
gluLookAt(NUM_ROWS*2., NUM_ROWS*2.+50., NUM_COLS*2.,
|
gluLookAt(NUM_ROWS * 2., NUM_ROWS * 2. + 50., NUM_COLS * 2., NUM_ROWS * 2.,
|
||||||
NUM_ROWS*2., NUM_ROWS*2., NUM_COLS*2.,
|
NUM_ROWS * 2., NUM_COLS * 2., 0.0, 0.0, 1.0);
|
||||||
0.0, 0.0, 1.0);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
|
@ -158,7 +223,14 @@ void reshape(int width, int height)
|
||||||
WindHeight = height;
|
WindHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change view angle */
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
static void special(int k, int x, int y) {
|
||||||
switch (k) {
|
switch (k) {
|
||||||
case GLUT_KEY_UP:
|
case GLUT_KEY_UP:
|
||||||
|
@ -178,17 +250,24 @@ static void special(int k, int x, int y) {
|
||||||
}
|
}
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void timf(int value) {
|
|
||||||
glutPostRedisplay();
|
|
||||||
glutTimerFunc(1, timf, 0);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for starting the display loop thread.
|
||||||
|
* @param unused Not used. Only here to satisfy signature constraints.
|
||||||
|
*/
|
||||||
void *display_loop_run(void * unused) {
|
void *display_loop_run(void * unused) {
|
||||||
display_loop();
|
display_loop();
|
||||||
return 0;
|
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) {
|
int main(int argc, char **argv) {
|
||||||
WindHeight = 700;
|
WindHeight = 700;
|
||||||
WindWidth = 700;
|
WindWidth = 700;
|
||||||
|
@ -198,7 +277,6 @@ int main(int argc, char **argv){
|
||||||
win = glutCreateWindow("16x16 Borg Simulator");
|
win = glutCreateWindow("16x16 Borg Simulator");
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
//glutReshapeFunc(reshape);
|
|
||||||
glutDisplayFunc(display);
|
glutDisplayFunc(display);
|
||||||
glutIdleFunc(display);
|
glutIdleFunc(display);
|
||||||
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
|
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
|
||||||
|
@ -211,12 +289,11 @@ int main(int argc, char **argv){
|
||||||
// clearcolor & main loop
|
// clearcolor & main loop
|
||||||
glClearColor(0, 0, 0, 1.0);
|
glClearColor(0, 0, 0, 1.0);
|
||||||
gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.);
|
gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.);
|
||||||
gluLookAt(NUM_COLS*2., NUM_COLS*2.+50., NUM_ROWS*2.,
|
gluLookAt(NUM_COLS * 2., NUM_COLS * 2. + 50., NUM_ROWS * 2., NUM_COLS * 2.,
|
||||||
NUM_COLS*2., NUM_COLS*2., NUM_ROWS*2.,
|
NUM_COLS * 2., NUM_ROWS * 2., 0.0, 0.0, 1.0);
|
||||||
0.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
// init Call List for LED
|
// init Call List for LED
|
||||||
quad = gluNewQuadric();
|
GLUquadric* quad = gluNewQuadric();
|
||||||
glNewList(0, GL_COMPILE);
|
glNewList(0, GL_COMPILE);
|
||||||
glColor4f(0.8, 0.0, 0.0, 1.);
|
glColor4f(0.8, 0.0, 0.0, 1.);
|
||||||
gluSphere(quad, 1.0, 12, 12);
|
gluSphere(quad, 1.0, 12, 12);
|
||||||
|
@ -237,13 +314,11 @@ int main(int argc, char **argv){
|
||||||
tbInit(GLUT_LEFT_BUTTON);
|
tbInit(GLUT_LEFT_BUTTON);
|
||||||
tbAnimate(GL_FALSE);
|
tbAnimate(GL_FALSE);
|
||||||
|
|
||||||
// start display_loop thread
|
pthread_t simthread;
|
||||||
#ifdef _WIN32
|
|
||||||
_beginthread((void (*)(void*))display_loop_run, 0, NULL);
|
|
||||||
#else
|
|
||||||
pthread_create(&simthread, NULL, display_loop_run, NULL);
|
pthread_create(&simthread, NULL, display_loop_run, NULL);
|
||||||
#endif
|
|
||||||
//glutTimerFunc(40, timf, 0); // Set up timer for 40ms, about 25 fps
|
|
||||||
glutMainLoop();
|
glutMainLoop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
/*
|
/**
|
||||||
|
* \addtogroup unixsimulator
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/**
|
||||||
* Simple trackball-like motion adapted (ripped off) from projtex.c
|
* Simple trackball-like motion adapted (ripped off) from projtex.c
|
||||||
* (written by David Yu and David Blythe). See the SIGGRAPH '96
|
* (written by David Yu and David Blythe). See the SIGGRAPH '96
|
||||||
* Advanced OpenGL course notes.
|
* Advanced OpenGL course notes.
|
||||||
|
@ -20,67 +25,68 @@
|
||||||
* Typical setup:
|
* Typical setup:
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
void
|
* void
|
||||||
init(void)
|
* init(void)
|
||||||
{
|
* {
|
||||||
tbInit(GLUT_MIDDLE_BUTTON);
|
* tbInit(GLUT_MIDDLE_BUTTON);
|
||||||
tbAnimate(GL_TRUE);
|
* tbAnimate(GL_TRUE);
|
||||||
. . .
|
* . . .
|
||||||
}
|
* }
|
||||||
|
|
||||||
void
|
|
||||||
reshape(int width, int height)
|
|
||||||
{
|
|
||||||
tbReshape(width, height);
|
|
||||||
. . .
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
display(void)
|
|
||||||
{
|
|
||||||
glPushMatrix();
|
|
||||||
|
|
||||||
tbMatrix();
|
|
||||||
. . . draw the scene . . .
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mouse(int button, int state, int x, int y)
|
|
||||||
{
|
|
||||||
tbMouse(button, state, x, y);
|
|
||||||
. . .
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
motion(int x, int y)
|
|
||||||
{
|
|
||||||
tbMotion(x, y);
|
|
||||||
. . .
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
. . .
|
|
||||||
init();
|
|
||||||
glutReshapeFunc(reshape);
|
|
||||||
glutDisplayFunc(display);
|
|
||||||
glutMouseFunc(mouse);
|
|
||||||
glutMotionFunc(motion);
|
|
||||||
. . .
|
|
||||||
}
|
|
||||||
*
|
*
|
||||||
* */
|
* void
|
||||||
|
* reshape(int width, int height)
|
||||||
|
* {
|
||||||
|
* tbReshape(width, height);
|
||||||
|
* . . .
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void
|
||||||
|
* display(void)
|
||||||
|
* {
|
||||||
|
* glPushMatrix();
|
||||||
|
*
|
||||||
|
* tbMatrix();
|
||||||
|
* . . . draw the scene . . .
|
||||||
|
*
|
||||||
|
* glPopMatrix();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void
|
||||||
|
* mouse(int button, int state, int x, int y)
|
||||||
|
* {
|
||||||
|
* tbMouse(button, state, x, y);
|
||||||
|
* . . .
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void
|
||||||
|
* motion(int x, int y)
|
||||||
|
* {
|
||||||
|
* tbMotion(x, y);
|
||||||
|
* . . .
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* int
|
||||||
|
* main(int argc, char** argv)
|
||||||
|
* {
|
||||||
|
* . . .
|
||||||
|
* init();
|
||||||
|
* glutReshapeFunc(reshape);
|
||||||
|
* glutDisplayFunc(display);
|
||||||
|
* glutMouseFunc(mouse);
|
||||||
|
* glutMotionFunc(motion);
|
||||||
|
* . . .
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @file trackball.c
|
||||||
|
* @brief Helper functions for the UNIX platform Borg simulator.
|
||||||
|
* @author Martin Ongsiek, David Yu, David Blythe
|
||||||
|
*/
|
||||||
|
|
||||||
/* includes */
|
/* includes */
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#ifdef OSX_
|
#ifdef OSX_
|
||||||
# include <GLUT/glut.h>
|
# include <GLUT/glut.h>
|
||||||
#elif _WIN32
|
|
||||||
# include <GL/glut.h>
|
|
||||||
#else
|
#else
|
||||||
# include <GL/glut.h>
|
# include <GL/glut.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -104,11 +110,19 @@ static GLboolean tb_animate = GL_TRUE;
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
static void _tbPointToVector(int x, int y, int width, int height, float v[3])
|
|
||||||
{
|
/**
|
||||||
|
* Project x and y onto a hemisphere centered within given width and height.
|
||||||
|
* @param x X-coordinate
|
||||||
|
* @param y Y-coordinate
|
||||||
|
* @param width Width of the hemisphere.
|
||||||
|
* @param height Width of the hemisphere.
|
||||||
|
* @param v Vector where the projection is performed on.
|
||||||
|
*/
|
||||||
|
static void _tbPointToVector(int x, int y, int width, int height, float v[3]) {
|
||||||
float d, a;
|
float d, a;
|
||||||
|
|
||||||
/* project x, y onto a hemi-sphere centered within width, height. */
|
/* project x, y onto a hemisphere centered within width, height. */
|
||||||
v[0] = (2.0 * x - width) / width;
|
v[0] = (2.0 * x - width) / width;
|
||||||
v[1] = (height - 2.0 * y) / height;
|
v[1] = (height - 2.0 * y) / height;
|
||||||
d = sqrt(v[0] * v[0] + v[1] * v[1]);
|
d = sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||||
|
@ -119,13 +133,23 @@ static void _tbPointToVector(int x, int y, int width, int height, float v[3])
|
||||||
v[2] *= a;
|
v[2] *= a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tbAnimate(void)
|
|
||||||
{
|
/**
|
||||||
|
* Redisplay current window contents.
|
||||||
|
*/
|
||||||
|
static void _tbAnimate(void) {
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _tbStartMotion(int x, int y, int button, int time)
|
|
||||||
{
|
/**
|
||||||
|
* Starts trackball movement depending on the mouse position.
|
||||||
|
* @param x X-position of the mouse pointer.
|
||||||
|
* @param y Y-position of the mouse pointer.
|
||||||
|
* @param button Not used.
|
||||||
|
* @param time Elapsed time.
|
||||||
|
*/
|
||||||
|
void _tbStartMotion(int x, int y, int button, int time) {
|
||||||
assert(tb_button != -1);
|
assert(tb_button != -1);
|
||||||
|
|
||||||
tb_tracking = GL_TRUE;
|
tb_tracking = GL_TRUE;
|
||||||
|
@ -133,8 +157,13 @@ void _tbStartMotion(int x, int y, int button, int time)
|
||||||
_tbPointToVector(x, y, tb_width, tb_height, tb_lastposition);
|
_tbPointToVector(x, y, tb_width, tb_height, tb_lastposition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _tbStopMotion(int button, unsigned time)
|
|
||||||
{
|
/**
|
||||||
|
* Stops trackball movement.
|
||||||
|
* @param button Not used
|
||||||
|
* @param time Not used.
|
||||||
|
*/
|
||||||
|
void _tbStopMotion(int button, unsigned time) {
|
||||||
assert(tb_button != -1);
|
assert(tb_button != -1);
|
||||||
|
|
||||||
tb_tracking = GL_FALSE;
|
tb_tracking = GL_FALSE;
|
||||||
|
@ -143,18 +172,28 @@ void _tbStopMotion(int button, unsigned time)
|
||||||
glutIdleFunc(_tbAnimate);
|
glutIdleFunc(_tbAnimate);
|
||||||
} else {
|
} else {
|
||||||
tb_angle = 0.0;
|
tb_angle = 0.0;
|
||||||
if (tb_animate)
|
if (tb_animate) {
|
||||||
glutIdleFunc(0);
|
glutIdleFunc(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tbAnimate(GLboolean animate)
|
|
||||||
{
|
|
||||||
|
/**
|
||||||
|
* Starts or stops the spinning movement of the trackball.
|
||||||
|
* @param animate GL_TRUE for starting and GL_FALSE for stopping the animation.
|
||||||
|
*/
|
||||||
|
void tbAnimate(GLboolean animate) {
|
||||||
tb_animate = animate;
|
tb_animate = animate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tbInit(GLuint button)
|
|
||||||
{
|
/**
|
||||||
|
* Has to be called before any other tb call.
|
||||||
|
* @param button Mouse button state.
|
||||||
|
*/
|
||||||
|
void tbInit(GLuint button) {
|
||||||
tb_button = button;
|
tb_button = button;
|
||||||
tb_angle = 0.0;
|
tb_angle = 0.0;
|
||||||
|
|
||||||
|
@ -165,8 +204,11 @@ void tbInit(GLuint button)
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tbMatrix()
|
|
||||||
{
|
/**
|
||||||
|
* Gets the tb matrix rotation.
|
||||||
|
*/
|
||||||
|
void tbMatrix() {
|
||||||
assert(tb_button != -1);
|
assert(tb_button != -1);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
@ -179,16 +221,28 @@ void tbMatrix()
|
||||||
glMultMatrixf((GLfloat *) tb_transform);
|
glMultMatrixf((GLfloat *) tb_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tbReshape(int width, int height)
|
|
||||||
{
|
/**
|
||||||
|
* Reshape callback function for determining the window size.
|
||||||
|
* @param width Width of the trackball.
|
||||||
|
* @param height Height of the trackball.
|
||||||
|
*/
|
||||||
|
void tbReshape(int width, int height) {
|
||||||
assert(tb_button != -1);
|
assert(tb_button != -1);
|
||||||
|
|
||||||
tb_width = width;
|
tb_width = width;
|
||||||
tb_height = height;
|
tb_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tbMouse(int button, int state, int x, int y)
|
|
||||||
{
|
/**
|
||||||
|
* Starts motion depending on mouse position and button state.
|
||||||
|
* @param button The button whose state has changed.
|
||||||
|
* @param state The state of that button.
|
||||||
|
* @param x X-position of the mouse pointer.
|
||||||
|
* @param y Y-position of the mouse pointer.
|
||||||
|
*/
|
||||||
|
void tbMouse(int button, int state, int x, int y) {
|
||||||
assert(tb_button != -1);
|
assert(tb_button != -1);
|
||||||
|
|
||||||
if (state == GLUT_DOWN && button == tb_button)
|
if (state == GLUT_DOWN && button == tb_button)
|
||||||
|
@ -197,8 +251,13 @@ void tbMouse(int button, int state, int x, int y)
|
||||||
_tbStopMotion(button, glutGet(GLUT_ELAPSED_TIME));
|
_tbStopMotion(button, glutGet(GLUT_ELAPSED_TIME));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tbMotion(int x, int y)
|
|
||||||
{
|
/**
|
||||||
|
* Starts a rotating scene motion to the given coordinates.
|
||||||
|
* @param x The x-coordinate.
|
||||||
|
* @param y The y-coordinate.
|
||||||
|
*/
|
||||||
|
void tbMotion(int x, int y) {
|
||||||
GLfloat current_position[3], dx, dy, dz;
|
GLfloat current_position[3], dx, dy, dz;
|
||||||
|
|
||||||
assert(tb_button != -1);
|
assert(tb_button != -1);
|
||||||
|
@ -216,12 +275,12 @@ void tbMotion(int x, int y)
|
||||||
tb_angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
|
tb_angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
|
|
||||||
/* calculate the axis of rotation (cross product) */
|
/* calculate the axis of rotation (cross product) */
|
||||||
tb_axis[0] = tb_lastposition[1] * current_position[2] -
|
tb_axis[0] = tb_lastposition[1] * current_position[2]
|
||||||
tb_lastposition[2] * current_position[1];
|
- tb_lastposition[2] * current_position[1];
|
||||||
tb_axis[1] = tb_lastposition[2] * current_position[0] -
|
tb_axis[1] = tb_lastposition[2] * current_position[0]
|
||||||
tb_lastposition[0] * current_position[2];
|
- tb_lastposition[0] * current_position[2];
|
||||||
tb_axis[2] = tb_lastposition[0] * current_position[1] -
|
tb_axis[2] = tb_lastposition[0] * current_position[1]
|
||||||
tb_lastposition[1] * current_position[0];
|
- tb_lastposition[1] * current_position[0];
|
||||||
|
|
||||||
/* reset for next time */
|
/* reset for next time */
|
||||||
tb_lasttime = glutGet(GLUT_ELAPSED_TIME);
|
tb_lasttime = glutGet(GLUT_ELAPSED_TIME);
|
||||||
|
@ -232,3 +291,5 @@ void tbMotion(int x, int y)
|
||||||
/* remember to draw new position */
|
/* remember to draw new position */
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
/*
|
/**
|
||||||
|
* \addtogroup unixsimulator
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/**
|
||||||
* Simple trackball-like motion adapted (ripped off) from projtex.c
|
* Simple trackball-like motion adapted (ripped off) from projtex.c
|
||||||
* (written by David Yu and David Blythe). See the SIGGRAPH '96
|
* (written by David Yu and David Blythe). See the SIGGRAPH '96
|
||||||
* Advanced OpenGL course notes.
|
* Advanced OpenGL course notes.
|
||||||
|
@ -6,72 +11,76 @@
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
*
|
*
|
||||||
* o call gltbInit() in before any other gltb call
|
* o call tbInit() in before any other tb call
|
||||||
* o call gltbReshape() from the reshape callback
|
* o call tbReshape() from the reshape callback
|
||||||
* o call gltbMatrix() to get the trackball matrix rotation
|
* o call tbMatrix() to get the trackball matrix rotation
|
||||||
* o call gltbStartMotion() to begin trackball movememt
|
* o call tbStartMotion() to begin trackball movememt
|
||||||
* o call gltbStopMotion() to stop trackball movememt
|
* o call tbStopMotion() to stop trackball movememt
|
||||||
* o call gltbMotion() from the motion callback
|
* o call tbMotion() from the motion callback
|
||||||
* o call gltbAnimate(GL_TRUE) if you want the trackball to continue
|
* o call tbAnimate(GL_TRUE) if you want the trackball to continue
|
||||||
* spinning after the mouse button has been released
|
* spinning after the mouse button has been released
|
||||||
* o call gltbAnimate(GL_FALSE) if you want the trackball to stop
|
* o call tbAnimate(GL_FALSE) if you want the trackball to stop
|
||||||
* spinning after the mouse button has been released
|
* spinning after the mouse button has been released
|
||||||
*
|
*
|
||||||
* Typical setup:
|
* Typical setup:
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
void
|
* void
|
||||||
init(void)
|
* init(void)
|
||||||
{
|
* {
|
||||||
gltbInit(GLUT_MIDDLE_BUTTON);
|
* tbInit(GLUT_MIDDLE_BUTTON);
|
||||||
gltbAnimate(GL_TRUE);
|
* tbAnimate(GL_TRUE);
|
||||||
. . .
|
* . . .
|
||||||
}
|
* }
|
||||||
|
*
|
||||||
void
|
* void
|
||||||
reshape(int width, int height)
|
* reshape(int width, int height)
|
||||||
{
|
* {
|
||||||
gltbReshape(width, height);
|
* tbReshape(width, height);
|
||||||
. . .
|
* . . .
|
||||||
}
|
* }
|
||||||
|
*
|
||||||
void
|
* void
|
||||||
display(void)
|
* display(void)
|
||||||
{
|
* {
|
||||||
glPushMatrix();
|
* glPushMatrix();
|
||||||
|
*
|
||||||
gltbMatrix();
|
* tbMatrix();
|
||||||
. . . draw the scene . . .
|
* . . . draw the scene . . .
|
||||||
|
*
|
||||||
glPopMatrix();
|
* glPopMatrix();
|
||||||
}
|
* }
|
||||||
|
*
|
||||||
void
|
* void
|
||||||
mouse(int button, int state, int x, int y)
|
* mouse(int button, int state, int x, int y)
|
||||||
{
|
* {
|
||||||
gltbMouse(button, state, x, y);
|
* tbMouse(button, state, x, y);
|
||||||
. . .
|
* . . .
|
||||||
}
|
* }
|
||||||
|
*
|
||||||
void
|
* void
|
||||||
motion(int x, int y)
|
* motion(int x, int y)
|
||||||
{
|
* {
|
||||||
gltbMotion(x, y);
|
* tbMotion(x, y);
|
||||||
. . .
|
* . . .
|
||||||
}
|
* }
|
||||||
|
*
|
||||||
int
|
* int
|
||||||
main(int argc, char** argv)
|
* main(int argc, char** argv)
|
||||||
{
|
* {
|
||||||
. . .
|
* . . .
|
||||||
init();
|
* init();
|
||||||
glutReshapeFunc(reshape);
|
* glutReshapeFunc(reshape);
|
||||||
glutDisplayFunc(display);
|
* glutDisplayFunc(display);
|
||||||
glutMouseFunc(mouse);
|
* glutMouseFunc(mouse);
|
||||||
glutMotionFunc(motion);
|
* glutMotionFunc(motion);
|
||||||
. . .
|
* . . .
|
||||||
}
|
* }
|
||||||
***/
|
*
|
||||||
|
* @file trackball.h
|
||||||
|
* @brief Header file for helper functions for the UNIX platform Borg simulator.
|
||||||
|
* @author Martin Ongsiek, David Yu, David Blythe
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
|
@ -87,3 +96,4 @@
|
||||||
|
|
||||||
void tbAnimate(GLboolean animate);
|
void tbAnimate(GLboolean animate);
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
#include "joystick.h"
|
|
||||||
|
|
||||||
extern jmp_buf newmode_jmpbuf;
|
|
||||||
|
|
||||||
void wait(unsigned int ms) {
|
|
||||||
if (waitForFire) {
|
|
||||||
if (JOYISFIRE) {
|
|
||||||
longjmp(newmode_jmpbuf, 43);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(ms);
|
|
||||||
#else
|
|
||||||
usleep(ms*1000);
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -0,0 +1,492 @@
|
||||||
|
/**
|
||||||
|
* \defgroup winsimulator Simulation of the Borg API for the Win32 platform.
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a native Win32 port of the Borgware-2D API simulator. Although the
|
||||||
|
* OpenGL based simulator is in fact platform independent, there are some
|
||||||
|
* obstacles regarding Cygwin's OpenGL support.
|
||||||
|
*
|
||||||
|
* Earlier versions of Cygwin used to ship bindings to Win32's native OpenGL
|
||||||
|
* libraries. Unfortunately some of those native components (GLUT in particular)
|
||||||
|
* weren't maintained for years so it was decided to cease support for them.
|
||||||
|
*
|
||||||
|
* The reasons are explained in more detail at
|
||||||
|
* http://cygwin.com/ml/cygwin/2012-05/msg00276.html
|
||||||
|
*
|
||||||
|
* The OpenGL bindings which are now shipped with Cygwin require a running
|
||||||
|
* X-Server which I consider clumsy to use on a Windows platform (especially for
|
||||||
|
* a small application like this simulator). So I decided to write a native
|
||||||
|
* Win32 application to free Windows developers from the hassles of rolling out
|
||||||
|
* a complete X11 setup.
|
||||||
|
*
|
||||||
|
* The native simulator feels like the OpenGL based one, with the exception that
|
||||||
|
* you can't rotate the matrix (I'm using the plain GDI32 API for the graphics).
|
||||||
|
*
|
||||||
|
* @file winmain.c
|
||||||
|
* @brief Simulator for the Win32 platform.
|
||||||
|
* @author Christian Kroll
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include "../config.h"
|
||||||
|
#include "../display_loop.h"
|
||||||
|
|
||||||
|
/** Number of bytes per row. */
|
||||||
|
#define LINEBYTES ((NUM_COLS + 1) / 8)
|
||||||
|
|
||||||
|
/** The width (in pixels) of the margin around a LED. */
|
||||||
|
#define LED_MARGIN 1
|
||||||
|
/** The diameter (in pixels) of a LED. */
|
||||||
|
#define LED_DIAMETER 14
|
||||||
|
/** The extend of the whole LED including its margin. */
|
||||||
|
#define LED_EXTENT (2 * LED_MARGIN + LED_DIAMETER)
|
||||||
|
|
||||||
|
/** Width of the canvas. */
|
||||||
|
#define WND_X_EXTENTS (NUM_COLS * LED_EXTENT)
|
||||||
|
/** Height of the canvas. */
|
||||||
|
#define WND_Y_EXTENTS (NUM_ROWS * LED_EXTENT)
|
||||||
|
|
||||||
|
|
||||||
|
/* string constants */
|
||||||
|
LPCSTR g_strWindowClass = "BorgSimulatorWindowClass";
|
||||||
|
LPCSTR g_strWindowTitle = "Borg Simulator";
|
||||||
|
|
||||||
|
LPCSTR g_strError = "Error";
|
||||||
|
LPCSTR g_strErrorRegisterWindow = "Error: Could not register window class.";
|
||||||
|
LPCSTR g_strErrorCreateWindow = "Error: Could not create window.";
|
||||||
|
|
||||||
|
|
||||||
|
/** Event object for the multimedia timer (wait() function). */
|
||||||
|
HANDLE g_hWaitEvent;
|
||||||
|
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
|
||||||
|
/* forward declarations */
|
||||||
|
LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
|
UINT msg,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a window class (necessary for creating a window).
|
||||||
|
* @param lpwc Pointer to WNDCLASS struct.
|
||||||
|
* @param hInstance Handle of the instance where this window class belongs to.
|
||||||
|
* @return TRUE if successful, otherwise FALSE.
|
||||||
|
*/
|
||||||
|
BOOL simRegisterWindowClass(WNDCLASSA *const lpwc,
|
||||||
|
HINSTANCE hInstance)
|
||||||
|
{
|
||||||
|
lpwc->style = 0;
|
||||||
|
lpwc->lpfnWndProc = simWndProc;
|
||||||
|
lpwc->cbClsExtra = 0;
|
||||||
|
lpwc->cbWndExtra = 0;
|
||||||
|
lpwc->hInstance = hInstance;
|
||||||
|
lpwc->hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
||||||
|
lpwc->hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
lpwc->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||||
|
lpwc->lpszMenuName = NULL;
|
||||||
|
lpwc->lpszClassName = g_strWindowClass;
|
||||||
|
|
||||||
|
return (RegisterClassA(lpwc) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new window and makes it visible.
|
||||||
|
* @param lphWnd Pointer to window handle.
|
||||||
|
* @param hInstance Handle of the instance where this window belongs to.
|
||||||
|
* @param nCmdShow Flag for showing the window minimized, maximized etc.
|
||||||
|
* @return TRUE if successful, otherwise FALSE.
|
||||||
|
*/
|
||||||
|
BOOL simCreateWindow(HWND *lphWnd,
|
||||||
|
HINSTANCE hInstance,
|
||||||
|
int nCmdShow)
|
||||||
|
{
|
||||||
|
/* create window and retrieve its handle */
|
||||||
|
*lphWnd = CreateWindow(g_strWindowClass, g_strWindowTitle,
|
||||||
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
WND_X_EXTENTS * 2, WND_Y_EXTENTS * 2, HWND_DESKTOP,
|
||||||
|
NULL, hInstance, NULL);
|
||||||
|
|
||||||
|
/* mske it visible */
|
||||||
|
if (*lphWnd != NULL)
|
||||||
|
{
|
||||||
|
ShowWindow(*lphWnd, nCmdShow);
|
||||||
|
UpdateWindow(*lphWnd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the LED matrix on the given device context.
|
||||||
|
* @param hdc The device context where the LED matrix should be drawn on.
|
||||||
|
*/
|
||||||
|
void simDrawMatrix(HDC hdc)
|
||||||
|
{
|
||||||
|
COLORREF colorLed;
|
||||||
|
HBRUSH hBrushLed;
|
||||||
|
HGDIOBJ hGdiOld;
|
||||||
|
unsigned int c, p, x, y, absX;
|
||||||
|
int left, right, top, bottom;
|
||||||
|
static unsigned char const shl_map[8] =
|
||||||
|
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
|
||||||
|
|
||||||
|
/* clear background */
|
||||||
|
FloodFill(hdc, 0, 0, RGB(0, 0, 0));
|
||||||
|
|
||||||
|
/* go through every plane */
|
||||||
|
for (p = 0; p < NUMPLANE; ++p)
|
||||||
|
{
|
||||||
|
/* create and select red brush into device context */
|
||||||
|
colorLed = RGB((255.0 / NUMPLANE) * (p + 1), 0, 0);
|
||||||
|
hBrushLed = CreateSolidBrush(colorLed);
|
||||||
|
hGdiOld = SelectObject(hdc, hBrushLed);
|
||||||
|
|
||||||
|
/* translate pixmap into LEDs */
|
||||||
|
for (y = 0; y < NUM_ROWS; ++y)
|
||||||
|
{
|
||||||
|
for (c = 0; c < LINEBYTES; ++c)
|
||||||
|
{
|
||||||
|
for (x = 0; x < 8; ++x)
|
||||||
|
{
|
||||||
|
if (pixmap[p][y][c] & shl_map[x])
|
||||||
|
{
|
||||||
|
// eventually draw a LED, mirroring its coordinates
|
||||||
|
absX = (c * 8 + x) * LED_EXTENT + LED_MARGIN;
|
||||||
|
left = WND_X_EXTENTS - absX;
|
||||||
|
right = WND_X_EXTENTS - absX - LED_DIAMETER + 1;
|
||||||
|
top = y * LED_EXTENT + LED_MARGIN;
|
||||||
|
bottom = top + LED_DIAMETER - 1;
|
||||||
|
Ellipse(hdc, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dispose that brush */
|
||||||
|
DeleteObject(SelectObject(hdc, hGdiOld));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves device context from given window, creates a compatible memory
|
||||||
|
* device context for double buffering and hands that thing over to
|
||||||
|
* simDrawMatrix().
|
||||||
|
* @param hWnd The window where the LED-Matrix should be displayed.
|
||||||
|
*/
|
||||||
|
void simDisplay(HWND hWnd)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
HDC hdc;
|
||||||
|
HDC hMemDc;
|
||||||
|
HBITMAP hBmp;
|
||||||
|
HBITMAP hOldBmp;
|
||||||
|
|
||||||
|
/* retrieve window dimensions */
|
||||||
|
if (GetClientRect(hWnd, &rect))
|
||||||
|
{
|
||||||
|
int const cx = rect.right - rect.left;
|
||||||
|
int const cy = rect.bottom - rect.top;
|
||||||
|
|
||||||
|
/* retrieve device context */
|
||||||
|
if ((hdc = GetDC(hWnd)) != NULL)
|
||||||
|
{
|
||||||
|
/* make window contents scalable */
|
||||||
|
SetMapMode(hdc, MM_ANISOTROPIC);
|
||||||
|
SetWindowExtEx(hdc, WND_X_EXTENTS, WND_Y_EXTENTS, NULL);
|
||||||
|
SetViewportExtEx(hdc, cx, cy, NULL);
|
||||||
|
|
||||||
|
/* create memory device context for double buffering */
|
||||||
|
hMemDc = CreateCompatibleDC(hdc);
|
||||||
|
if (hMemDc != NULL)
|
||||||
|
{
|
||||||
|
/* contents of the memory DC should be scaled as well */
|
||||||
|
SetMapMode(hMemDc, MM_ANISOTROPIC);
|
||||||
|
SetWindowExtEx(hMemDc, WND_X_EXTENTS, WND_Y_EXTENTS, NULL);
|
||||||
|
SetViewportExtEx(hMemDc, cx, cy, NULL);
|
||||||
|
|
||||||
|
/* create a bitmap to be associated with the memory DC... */
|
||||||
|
hBmp = CreateCompatibleBitmap(hdc, cx, cy);
|
||||||
|
if (hBmp != NULL)
|
||||||
|
{
|
||||||
|
/* ...and selct that into that DC */
|
||||||
|
hOldBmp = (HBITMAP)SelectObject(hMemDc, hBmp);
|
||||||
|
|
||||||
|
/* finally *sigh* draw the LED matrix */
|
||||||
|
simDrawMatrix(hMemDc);
|
||||||
|
|
||||||
|
/* and blit that into the window DC */
|
||||||
|
BitBlt(hdc, 0, 0, cx, cy, hMemDc, 0, 0, SRCCOPY);
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
DeleteObject(SelectObject(hMemDc, hOldBmp));
|
||||||
|
}
|
||||||
|
DeleteDC(hMemDc);
|
||||||
|
}
|
||||||
|
ReleaseDC(hWnd, hdc);
|
||||||
|
}
|
||||||
|
InvalidateRect(hWnd, &rect, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message handler for the main window.
|
||||||
|
* @param hWnd The window whose messages should be processed.
|
||||||
|
* @param msg The message fired from the operating system.
|
||||||
|
* @param wParam First message parameter.
|
||||||
|
* @param lParam Second message parameter.
|
||||||
|
*/
|
||||||
|
LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
|
UINT msg,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam)
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
HDC hdc;
|
||||||
|
LPMINMAXINFO lpminmax;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
/* enforce minimum window size */
|
||||||
|
case WM_GETMINMAXINFO:
|
||||||
|
lpminmax = (LPMINMAXINFO)lParam;
|
||||||
|
lpminmax->ptMinTrackSize.x = WND_X_EXTENTS * 2;
|
||||||
|
lpminmax->ptMinTrackSize.y = WND_Y_EXTENTS * 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* paint window contents */
|
||||||
|
case WM_PAINT:
|
||||||
|
hdc = BeginPaint(hWnd, &ps);
|
||||||
|
if (hdc != NULL)
|
||||||
|
{
|
||||||
|
simDisplay(hWnd);
|
||||||
|
EndPaint(hWnd, &ps);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* map key presses to fake joystick movements */
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case VK_ESCAPE:
|
||||||
|
case 'Q':
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VK_SPACE:
|
||||||
|
fakeport |= 0x01;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'A':
|
||||||
|
fakeport |= 0x02;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
fakeport |= 0x04;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
fakeport |= 0x08;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'W':
|
||||||
|
fakeport |= 0x10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* map key releases to fake joystick movements */
|
||||||
|
case WM_KEYUP:
|
||||||
|
switch(wParam)
|
||||||
|
{
|
||||||
|
case VK_SPACE:
|
||||||
|
fakeport &= ~0x01;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'A':
|
||||||
|
fakeport &= ~0x02;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
fakeport &= ~0x04;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
fakeport &= ~0x08;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'W':
|
||||||
|
fakeport &= ~0x10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* refresh the LED matrix every 40 ms */
|
||||||
|
case WM_TIMER:
|
||||||
|
simDisplay(hWnd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* quit application */
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Windows' default handler */
|
||||||
|
default:
|
||||||
|
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for starting the the display loop in a thread.
|
||||||
|
* @param lpParam Free style arguments for the thread function (not used here).
|
||||||
|
* @return Always zero.
|
||||||
|
*/
|
||||||
|
DWORD WINAPI simLoop(LPVOID lpParam)
|
||||||
|
{
|
||||||
|
display_loop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait function which utilizes multimedia timers and thread synchronization
|
||||||
|
* objects. Although this is much more complicated than calling the Sleep()
|
||||||
|
* function, it is also much more precise.
|
||||||
|
* @param ms The requested delay in milliseconds.
|
||||||
|
*/
|
||||||
|
void wait(int ms)
|
||||||
|
{
|
||||||
|
TIMECAPS tc;
|
||||||
|
MMRESULT mmresult;
|
||||||
|
MMRESULT mmTimerEventId;
|
||||||
|
UINT uResolution;
|
||||||
|
|
||||||
|
/* check if fire button is pressed (and if it is, jump to the menu) */
|
||||||
|
if (waitForFire) {
|
||||||
|
if (fakeport & 0x01) {
|
||||||
|
longjmp(newmode_jmpbuf, 43);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve timer resolution capabilities of the current system */
|
||||||
|
mmresult = timeGetDevCaps(&tc, sizeof(tc));
|
||||||
|
if (mmresult == TIMERR_NOERROR)
|
||||||
|
{
|
||||||
|
/* retrieve best resolution and configure timer services accordingly */
|
||||||
|
uResolution = min(max(tc.wPeriodMin, 0), tc.wPeriodMax);
|
||||||
|
mmresult = timeBeginPeriod(uResolution);
|
||||||
|
if (mmresult == TIMERR_NOERROR)
|
||||||
|
{
|
||||||
|
/* actually retrieve a multimedia timer */
|
||||||
|
mmTimerEventId = timeSetEvent(ms, uResolution, g_hWaitEvent, NULL,
|
||||||
|
TIME_ONESHOT | TIME_CALLBACK_EVENT_PULSE);
|
||||||
|
if (mmTimerEventId != NULL)
|
||||||
|
{
|
||||||
|
/* now halt until that timer pulses our wait event object */
|
||||||
|
WaitForSingleObject(g_hWaitEvent, INFINITE);
|
||||||
|
|
||||||
|
/* relieve the timer from its duties */
|
||||||
|
timeKillEvent(mmTimerEventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* relax timer service constraints */
|
||||||
|
timeEndPeriod (uResolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function of the windows simulator.
|
||||||
|
* @param hInstance Instance handle given by the operating system.
|
||||||
|
* @param hPrevInstance This parameter has no meaning in Win32.
|
||||||
|
* @param lpCmdLine Pointer to a null terminated command line string.
|
||||||
|
* @param nCmdShow Flags for showing the window minimized, maximized and so on.
|
||||||
|
* @return Exit code, always 0 here.
|
||||||
|
*/
|
||||||
|
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
|
HINSTANCE hPrevInstance,
|
||||||
|
LPSTR lpCmdLine,
|
||||||
|
int nCmdShow)
|
||||||
|
{
|
||||||
|
WNDCLASS wc;
|
||||||
|
HWND hWnd;
|
||||||
|
MSG msg;
|
||||||
|
HANDLE hThread;
|
||||||
|
|
||||||
|
/* regster window class (with nice black background!) */
|
||||||
|
if (simRegisterWindowClass(&wc, hInstance))
|
||||||
|
{
|
||||||
|
/* actually create the window and make it visible */
|
||||||
|
if (simCreateWindow(&hWnd, hInstance, nCmdShow))
|
||||||
|
{
|
||||||
|
/* event handle for multimedia timer (for the wait() function) */
|
||||||
|
g_hWaitEvent = CreateEventA(NULL, FALSE, FALSE, "Local\\WaitEvent");
|
||||||
|
if (g_hWaitEvent != NULL)
|
||||||
|
{
|
||||||
|
/* start the display loop thread */
|
||||||
|
hThread = CreateThread(NULL, 0, simLoop, NULL, 0, NULL);
|
||||||
|
if (hThread != NULL)
|
||||||
|
{
|
||||||
|
/* ensure that the display loop stays responsive */
|
||||||
|
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
||||||
|
|
||||||
|
/* issue a timer message every 40 ms (roughly 25 fps) */
|
||||||
|
/* NOTE: this has nothing to do with the multimedia timer */
|
||||||
|
SetTimer(hWnd, 23, 40, NULL);
|
||||||
|
|
||||||
|
/* standard Windows(R) message loop */
|
||||||
|
/* (runs as long as the window hasn't been closed) */
|
||||||
|
while (GetMessageA(&msg, NULL, 0, 0))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageA(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop the display loop */
|
||||||
|
TerminateThread(hThread, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* relieve wait event object from its duties */
|
||||||
|
CloseHandle(g_hWaitEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg.wParam;
|
||||||
|
}
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorCreateWindow, g_strError, MB_OK);
|
||||||
|
}
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorRegisterWindow, g_strError, MB_OK);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@}*/
|
Loading…
Reference in New Issue