#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define _USE_MATH_DEFINES
#include <math.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#define DEGRAD 57.295779513
#define K 1024
#define MAXTICKS 60
typedef struct viewer {
GLfloat x, y, z;
GLfloat theta, phi;
GLfloat vx, vy, vz;
} VIEWER;
typedef struct monstertype {
GLfloat x, y, z;
GLfloat heading;
GLfloat leftleg, rightleg;
} MONSTER;
typedef struct actiontype {
GLfloat startangle;
GLfloat angle[MAXTICKS];
GLfloat slope[MAXTICKS];
int currentphase;
} ACTION;
ACTION kick;
int automode = 0;
GLfloat pos1[] = { 1.0, 3.0, 4.0, 1.0 };
GLfloat pos2[] = { -1.0, 3.0, 4.0, 1.0 };
GLfloat amb[] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat dif[] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat spe[] = { 0.9, 0.9, 0.9, 1.0 };
GLfloat matamb[] = { 0.30, 0.30, 0.30, 1.0 };
GLfloat matdif[] = { 0.50, 0.50, 0.50, 1.0 };
GLfloat matspe[] = { 0.10, 0.10, 0.10, 1.0 };
GLfloat objamb[] = { 0.60, 0.10, 0.10, 1.0 };
GLfloat objdif[] = { 0.10, 0.10, 0.10, 1.0 };
GLfloat objspe[] = { 0.10, 0.10, 0.80, 1.0 };
GLUquadric *body;
MONSTER bob;
double pov;
VIEWER moi;
int xOrigin = 0;
int yOrigin = 0;
int lastx = 400;
int lasty = 300;
void display();
void animate();
void reshape(int w, int h);
void arrows(int c, int x, int y);
void keyboard(unsigned char c, int x, int y);
void blocks(int x, int y, int z);
void move_viewer(int dir);
//non-functional
void mouseMove(int x, int y);
void init();
void update_viewer();
void monster(MONSTER *p);
int main(int argc, char *argv[])
{
pov
= (argc
== 1) ? 60.0 : atof(argv
[1]); glutInit(&argc, argv);
glutInitWindowSize(800, 600);
glutInitWindowPosition(400, 100);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("V0.1");
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutSpecialFunc(arrows);
glutReshapeFunc(reshape);
glutIdleFunc(animate);
// mouse func's
glutSetCursor(GLUT_CURSOR_CROSSHAIR);
glutPassiveMotionFunc(mouseMove);
init();
display();
glutMainLoop();
}
void move_viewer(int dir)
{
GLfloat tx, tz, tt;
int k;
/* for forward and backward movement */
switch (dir){
case 1:
//tx = moi.x + moi.vx;
//tz = moi.z + moi.vz;
moi.x += moi.vx;
moi.z += moi.vz;
break;
case 2:
tt = moi.theta;
moi.theta -= 90.0;
moi.x += moi.vx;
moi.z += moi.vz;
moi.theta = tt;
break;
case 3:
tt = moi.theta;
moi.theta += 90.0;
moi.x += moi.vx*1.0;
moi.z += moi.vz*1.0;
moi.theta = tt;
break;
case 4:
//tx = moi.x - moi.vx;
//tz = moi.z - moi.vz;
moi.x -= moi.vx;
moi.z -= moi.vz;
break;
}
pos1[0] = moi.x;
pos1[1] = moi.y;
pos1[2] = moi.z;
glLightfv(GL_LIGHT0, GL_POSITION, pos1);
}
void keyboard(unsigned char c, int x, int y)
{
switch (c){
case 27: /* escape key */
case 'w':
move_viewer(1);
break;
case 's':
move_viewer(4);
break;
case 'a':
move_viewer(2);
break;
case 'd':
move_viewer(3);
break;
case 'r':
if (!automode){
automode = 1;
kick.currentphase = 0;
}
break;
}
update_viewer();
glutPostRedisplay();
}
void mouseMove(int x, int y)
{
// update the angles
int diffx = x - lastx;
int diffy = y - lasty;
lastx = x;
lasty = y;
moi.phi = ((diffy *2) - y) * 0.001f;
moi.theta = ((diffx*2) - x) * 0.001f;
/*moi.phi += diffx;
moi.theta += diffy;*/
// update camera's direction
update_viewer();
glutPostRedisplay();
// put new directions back into the origins
yOrigin = moi.phi;
xOrigin = moi.theta;
}
void arrows(int c, int x, int y)
{
switch (c){
case GLUT_KEY_LEFT:
break;
case GLUT_KEY_UP:
moi.phi += 0.1;
break;
case GLUT_KEY_DOWN:
moi.phi -= 0.1;
break;
case GLUT_KEY_RIGHT:
bob.heading -= 5.0;
break;
}
update_viewer();
glutPostRedisplay();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(pov, (GLdouble)w / (GLdouble)h, 0.001, 50.0);
glMatrixMode(GL_MODELVIEW);
}
void init_action(ACTION *p)
{
int i;
p->startangle = 0.0;
for (i = 0; i<MAXTICKS; i++)
p->slope[i] = (i < MAXTICKS / 3) ? 4.0 : -2.0;
p->angle[0] = p->startangle;
for (i = 1; i<MAXTICKS; i++)
p->angle[i] = p->angle[i - 1] + p->slope[i];
p->currentphase = 0;
}
void init_monster(MONSTER *p)
{
memset(p
, 0, sizeof(MONSTER
)); }
void init()
{
moi.x = 0.0;
moi.y = 2.5;
moi.z = 5.0;
pos1[0] = moi.x;
pos1[1] = moi.y;
pos1[2] = moi.z;
moi.theta = -M_PI / 2.0;
moi.phi = 0.0;
automode = 0;
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
update_viewer();
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT0, GL_POSITION, pos1);
glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
glLightfv(GL_LIGHT0, GL_SPECULAR, spe);
glLightfv(GL_LIGHT0, GL_POSITION, pos2);
glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
glLightfv(GL_LIGHT0, GL_SPECULAR, spe);
body = gluNewQuadric();
gluQuadricDrawStyle(body, GLU_LINE);
init_monster(&bob);
init_action(&kick);
}
void animate()
{
int n;
if (!automode)
return;
fprintf(stderr
, "made it to animate!\n"); n = kick.currentphase++;
if (n >= MAXTICKS){
automode = 0;
bob.rightleg = kick.startangle;
}
else {
bob.rightleg = kick.angle[n];
}
update_viewer();
glutPostRedisplay();
}
void update_viewer()
{
}
void display()
{
int i, j, k, u, v;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLineWidth(2.0);
glLoadIdentity();
gluLookAt(moi.x, moi.y, moi.z,
moi.x + moi.vx, moi.y + moi.vy, moi.z + moi.vz,
0.0, 1.0, 0.0);
/* blocks(x,y,z) */
for (i = -10; i < 20; i++){
for (k = -10; k < 20; k++){
if (v % 2 == 0){
glColor3f(1.0f, 1.0f, 1.0f);
}
else{
glColor3f(0.1f, 0.9f, 0.2f);
}
blocks(i, 0, k);
}
}
//monster(&bob);
glutSwapBuffers();
}
void blocks(int x, int y, int z)
{
/* floor blocks */
// glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matamb);
// glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matdif);
// glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matspe);
// glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
glBegin(GL_LINE_STRIP);
/* top of block */
glVertex3f(x, y+1.0, z);
glVertex3f(x+1.0, y+1.0, z);
glVertex3f(x+1.0, y+1.0, z+1.0);
glVertex3f(x, y+1.0, z+1.0);
glEnd();
/* left of block */
glBegin(GL_LINE_STRIP);
glVertex3f(x, y+1.0, z);
glVertex3f(x, y, z);
glVertex3f(x, y, z+1.0);
glVertex3f(x, y + 1.0, z + 1.0);
glEnd();
/* right of block */
glBegin(GL_LINE_STRIP);
glVertex3f(x+1.0, y+1.0, z);
glVertex3f(x+1.0, y, z);
glVertex3f(x+1.0, y, z+1.0);
glVertex3f(x+1.0, y+1.0, z+1.0);
glEnd();
/* front of block */
glBegin(GL_LINE_STRIP);
glVertex3f(x, y+1.0, z);
glVertex3f(x, y, z);
glVertex3f(x+1.0, y, z);
glVertex3f(x+1.0, y+1.0, z);
glEnd();
/* back of block */
glBegin(GL_LINE_STRIP);
glVertex3f(x, y+1.0, z+1.0);
glVertex3f(x, y, z+1.0);
glVertex3f(x+1.0, y, z+1.0);
glVertex3f(x+1.0, y+1.0, z+1.0);
glEnd();
/* bottom of block */
glBegin(GL_LINE_STRIP);
glVertex3f(x, y, z);
glVertex3f(x+1.0, y, z);
glVertex3f(x+1.0, y, z+1.0);
glVertex3f(x, y, z+1.0);
glEnd();
}
void monster(MONSTER *p)
{
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, objamb);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, objdif);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, objspe);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0);
glRotatef(bob.heading, 0.0, 1.0, 0.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
/* torso and head*/
glPushMatrix();
glTranslatef(0.0, 0.0, 2.5);
gluSphere(body, 0.5, 12, 12);
glTranslatef(0.0, 0.0, -1.5);
glScalef(0.5, 1.0, 1.0);
gluCylinder(body, 0.2, 0.3, 1.0, 12, 12);
glPopMatrix();
/* legs */
glPushMatrix();
glTranslatef(0.0, 0.1, 1.0);
glRotatef(p->rightleg, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -1.0);
gluCylinder(body, 0.05, 0.05, 1.0, 12, 12);
glPopMatrix();
glTranslatef(0.0, -0.1, 0.0);
gluCylinder(body, 0.05, 0.05, 1.0, 12, 12);
glPopMatrix();
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8dGltZS5oPgojZGVmaW5lIF9VU0VfTUFUSF9ERUZJTkVTCiNpbmNsdWRlIDxtYXRoLmg+CgojaWZkZWYgX19BUFBMRV9fCiNpbmNsdWRlIDxHTFVUL2dsdXQuaD4KI2Vsc2UKI2luY2x1ZGUgPEdML2dsdXQuaD4KI2VuZGlmCgojZGVmaW5lIERFR1JBRCAgICAgICAgNTcuMjk1Nzc5NTEzCiNkZWZpbmUgSyAgICAgICAgICAgMTAyNAoKI2RlZmluZSBNQVhUSUNLUyAgICAgIDYwCgp0eXBlZGVmIHN0cnVjdCB2aWV3ZXIgewoJR0xmbG9hdCB4LCB5LCB6OwoJR0xmbG9hdCB0aGV0YSwgcGhpOwoJR0xmbG9hdCB2eCwgdnksIHZ6Owp9IFZJRVdFUjsKCnR5cGVkZWYgc3RydWN0IG1vbnN0ZXJ0eXBlIHsKCUdMZmxvYXQgeCwgeSwgejsKCUdMZmxvYXQgaGVhZGluZzsKCUdMZmxvYXQgbGVmdGxlZywgcmlnaHRsZWc7Cn0gTU9OU1RFUjsKCnR5cGVkZWYgc3RydWN0IGFjdGlvbnR5cGUgewoJR0xmbG9hdCBzdGFydGFuZ2xlOwoJR0xmbG9hdCBhbmdsZVtNQVhUSUNLU107CglHTGZsb2F0IHNsb3BlW01BWFRJQ0tTXTsKCWludCBjdXJyZW50cGhhc2U7Cn0gQUNUSU9OOwoKQUNUSU9OIGtpY2s7CgppbnQgYXV0b21vZGUgPSAwOwoKR0xmbG9hdCBwb3MxW10gPSB7IDEuMCwgMy4wLCA0LjAsIDEuMCB9OwpHTGZsb2F0IHBvczJbXSA9IHsgLTEuMCwgMy4wLCA0LjAsIDEuMCB9OwpHTGZsb2F0IGFtYltdID0geyAwLjUsIDAuNSwgMC41LCAxLjAgfTsKR0xmbG9hdCBkaWZbXSA9IHsgMC41LCAwLjUsIDAuNSwgMS4wIH07CkdMZmxvYXQgc3BlW10gPSB7IDAuOSwgMC45LCAwLjksIDEuMCB9OwoKR0xmbG9hdCBtYXRhbWJbXSA9IHsgMC4zMCwgMC4zMCwgMC4zMCwgMS4wIH07CkdMZmxvYXQgbWF0ZGlmW10gPSB7IDAuNTAsIDAuNTAsIDAuNTAsIDEuMCB9OwpHTGZsb2F0IG1hdHNwZVtdID0geyAwLjEwLCAwLjEwLCAwLjEwLCAxLjAgfTsKCkdMZmxvYXQgb2JqYW1iW10gPSB7IDAuNjAsIDAuMTAsIDAuMTAsIDEuMCB9OwpHTGZsb2F0IG9iamRpZltdID0geyAwLjEwLCAwLjEwLCAwLjEwLCAxLjAgfTsKR0xmbG9hdCBvYmpzcGVbXSA9IHsgMC4xMCwgMC4xMCwgMC44MCwgMS4wIH07CgpHTFVxdWFkcmljICpib2R5OwpNT05TVEVSIGJvYjsKCmRvdWJsZSBwb3Y7ClZJRVdFUiBtb2k7CmludCB4T3JpZ2luID0gMDsKaW50IHlPcmlnaW4gPSAwOwppbnQgbGFzdHggPSA0MDA7CmludCBsYXN0eSA9IDMwMDsKCnZvaWQgZGlzcGxheSgpOwp2b2lkIGFuaW1hdGUoKTsKdm9pZCByZXNoYXBlKGludCB3LCBpbnQgaCk7CnZvaWQgYXJyb3dzKGludCBjLCBpbnQgeCwgaW50IHkpOwp2b2lkIGtleWJvYXJkKHVuc2lnbmVkIGNoYXIgYywgaW50IHgsIGludCB5KTsKdm9pZCBibG9ja3MoaW50IHgsIGludCB5LCBpbnQgeik7CnZvaWQgbW92ZV92aWV3ZXIoaW50IGRpcik7Ci8vbm9uLWZ1bmN0aW9uYWwKdm9pZCBtb3VzZU1vdmUoaW50IHgsIGludCB5KTsKCnZvaWQgaW5pdCgpOwp2b2lkIHVwZGF0ZV92aWV3ZXIoKTsKdm9pZCBtb25zdGVyKE1PTlNURVIgKnApOwoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkKewoJc3JhbmQodGltZShOVUxMKSk7Cglwb3YgPSAoYXJnYyA9PSAxKSA/IDYwLjAgOiBhdG9mKGFyZ3ZbMV0pOwoJZ2x1dEluaXQoJmFyZ2MsIGFyZ3YpOwoJZ2x1dEluaXRXaW5kb3dTaXplKDgwMCwgNjAwKTsKCWdsdXRJbml0V2luZG93UG9zaXRpb24oNDAwLCAxMDApOwoKCWdsdXRJbml0RGlzcGxheU1vZGUoR0xVVF9ET1VCTEUgfCBHTFVUX1JHQkEgfCBHTFVUX0RFUFRIKTsKCWdsdXRDcmVhdGVXaW5kb3coIlYwLjEiKTsKCglnbHV0S2V5Ym9hcmRGdW5jKGtleWJvYXJkKTsKCWdsdXREaXNwbGF5RnVuYyhkaXNwbGF5KTsKCWdsdXRTcGVjaWFsRnVuYyhhcnJvd3MpOwoJZ2x1dFJlc2hhcGVGdW5jKHJlc2hhcGUpOwoJZ2x1dElkbGVGdW5jKGFuaW1hdGUpOwoKCS8vIG1vdXNlIGZ1bmMncwoJZ2x1dFNldEN1cnNvcihHTFVUX0NVUlNPUl9DUk9TU0hBSVIpOwoJZ2x1dFBhc3NpdmVNb3Rpb25GdW5jKG1vdXNlTW92ZSk7CgoJaW5pdCgpOwoJZGlzcGxheSgpOwoKCWdsdXRNYWluTG9vcCgpOwp9CnZvaWQgbW92ZV92aWV3ZXIoaW50IGRpcikKewoJR0xmbG9hdCB0eCwgdHosIHR0OwoJaW50IGs7CgoJLyogZm9yIGZvcndhcmQgYW5kIGJhY2t3YXJkIG1vdmVtZW50ICovCglzd2l0Y2ggKGRpcil7CgljYXNlIDE6CgkJLy90eCA9IG1vaS54ICsgbW9pLnZ4OwoJCS8vdHogPSBtb2kueiArIG1vaS52ejsKCQltb2kueCArPSBtb2kudng7CgkJbW9pLnogKz0gbW9pLnZ6OwoJCWJyZWFrOwoJY2FzZSAyOgoJCXR0ID0gbW9pLnRoZXRhOwoJCW1vaS50aGV0YSAtPSA5MC4wOwoJCW1vaS52eCA9IGNvcyhtb2kudGhldGEpOwoJCW1vaS52eiA9IHNpbihtb2kudGhldGEpOwoJCW1vaS54ICs9IG1vaS52eDsKCQltb2kueiArPSBtb2kudno7CgkJbW9pLnRoZXRhID0gdHQ7CgkJYnJlYWs7CgljYXNlIDM6CgkJdHQgPSBtb2kudGhldGE7CgkJbW9pLnRoZXRhICs9IDkwLjA7CgkJbW9pLnZ4ID0gY29zKG1vaS50aGV0YSk7CgkJbW9pLnZ6ID0gc2luKG1vaS50aGV0YSk7CgkJbW9pLnggKz0gbW9pLnZ4KjEuMDsKCQltb2kueiArPSBtb2kudnoqMS4wOwoJCW1vaS50aGV0YSA9IHR0OwoJCWJyZWFrOwoJY2FzZSA0OgoJCS8vdHggPSBtb2kueCAtIG1vaS52eDsKCQkvL3R6ID0gbW9pLnogLSBtb2kudno7CgkJbW9pLnggLT0gbW9pLnZ4OwoJCW1vaS56IC09IG1vaS52ejsKCQlicmVhazsKCX0KCglwb3MxWzBdID0gbW9pLng7Cglwb3MxWzFdID0gbW9pLnk7Cglwb3MxWzJdID0gbW9pLno7CglnbExpZ2h0ZnYoR0xfTElHSFQwLCBHTF9QT1NJVElPTiwgcG9zMSk7Cn0Kdm9pZCBrZXlib2FyZCh1bnNpZ25lZCBjaGFyIGMsIGludCB4LCBpbnQgeSkKewoJc3dpdGNoIChjKXsKCWNhc2UgMjc6ICAvKiBlc2NhcGUga2V5ICovCgkJZXhpdCgwKTsKCWNhc2UgJ3cnOgoJCW1vdmVfdmlld2VyKDEpOwoJCWJyZWFrOwoJY2FzZSAncyc6CgkJbW92ZV92aWV3ZXIoNCk7CgkJYnJlYWs7CgljYXNlICdhJzoKCQltb3ZlX3ZpZXdlcigyKTsKCQlicmVhazsKCWNhc2UgJ2QnOgoJCW1vdmVfdmlld2VyKDMpOwoJCWJyZWFrOwoJY2FzZSAncic6CgkJaWYgKCFhdXRvbW9kZSl7CgkJCWF1dG9tb2RlID0gMTsKCQkJa2ljay5jdXJyZW50cGhhc2UgPSAwOwoJCX0KCQlicmVhazsKCX0KCXVwZGF0ZV92aWV3ZXIoKTsKCWdsdXRQb3N0UmVkaXNwbGF5KCk7Cn0Kdm9pZCBtb3VzZU1vdmUoaW50IHgsIGludCB5KSAKewoKCgkvLyB1cGRhdGUgdGhlIGFuZ2xlcwoJaW50IGRpZmZ4ID0geCAtIGxhc3R4OwoJaW50IGRpZmZ5ID0geSAtIGxhc3R5OwoJbGFzdHggPSB4OwoJbGFzdHkgPSB5OwoJCgkKCW1vaS5waGkgPSAoKGRpZmZ5ICoyKSAtIHkpICogMC4wMDFmOwoJbW9pLnRoZXRhID0gKChkaWZmeCoyKSAtIHgpICogMC4wMDFmOwoKCS8qbW9pLnBoaSArPSBkaWZmeDsKCW1vaS50aGV0YSArPSBkaWZmeTsqLwoJLy8gdXBkYXRlIGNhbWVyYSdzIGRpcmVjdGlvbgoJdXBkYXRlX3ZpZXdlcigpOwoJZ2x1dFBvc3RSZWRpc3BsYXkoKTsKCS8vIHB1dCBuZXcgZGlyZWN0aW9ucyBiYWNrIGludG8gdGhlIG9yaWdpbnMKCXlPcmlnaW4gPSBtb2kucGhpOwoJeE9yaWdpbiA9IG1vaS50aGV0YTsKCn0Kdm9pZCBhcnJvd3MoaW50IGMsIGludCB4LCBpbnQgeSkKewoJc3dpdGNoIChjKXsKCWNhc2UgR0xVVF9LRVlfTEVGVDoKCQlicmVhazsKCWNhc2UgR0xVVF9LRVlfVVA6CgkJbW9pLnBoaSArPSAwLjE7CgkJYnJlYWs7CgljYXNlIEdMVVRfS0VZX0RPV046CgkJbW9pLnBoaSAtPSAwLjE7CgkJYnJlYWs7CgljYXNlIEdMVVRfS0VZX1JJR0hUOgoJCWJvYi5oZWFkaW5nIC09IDUuMDsKCQlicmVhazsKCX0KCXVwZGF0ZV92aWV3ZXIoKTsKCWdsdXRQb3N0UmVkaXNwbGF5KCk7Cn0Kdm9pZCByZXNoYXBlKGludCB3LCBpbnQgaCkKewoJZ2xWaWV3cG9ydCgwLCAwLCB3LCBoKTsKCWdsTWF0cml4TW9kZShHTF9QUk9KRUNUSU9OKTsKCWdsTG9hZElkZW50aXR5KCk7CglnbHVQZXJzcGVjdGl2ZShwb3YsIChHTGRvdWJsZSl3IC8gKEdMZG91YmxlKWgsIDAuMDAxLCA1MC4wKTsKCWdsTWF0cml4TW9kZShHTF9NT0RFTFZJRVcpOwp9CnZvaWQgaW5pdF9hY3Rpb24oQUNUSU9OICpwKQp7CglpbnQgaTsKCglwLT5zdGFydGFuZ2xlID0gMC4wOwoJZm9yIChpID0gMDsgaTxNQVhUSUNLUzsgaSsrKQoJCXAtPnNsb3BlW2ldID0gKGkgPCBNQVhUSUNLUyAvIDMpID8gNC4wIDogLTIuMDsKCXAtPmFuZ2xlWzBdID0gcC0+c3RhcnRhbmdsZTsKCWZvciAoaSA9IDE7IGk8TUFYVElDS1M7IGkrKykKCQlwLT5hbmdsZVtpXSA9IHAtPmFuZ2xlW2kgLSAxXSArIHAtPnNsb3BlW2ldOwoJcC0+Y3VycmVudHBoYXNlID0gMDsKfQp2b2lkIGluaXRfbW9uc3RlcihNT05TVEVSICpwKQp7CgltZW1zZXQocCwgMCwgc2l6ZW9mKE1PTlNURVIpKTsKfQp2b2lkIGluaXQoKQp7Cgltb2kueCA9IDAuMDsKCW1vaS55ID0gMi41OwoJbW9pLnogPSA1LjA7Cglwb3MxWzBdID0gbW9pLng7Cglwb3MxWzFdID0gbW9pLnk7IAoJcG9zMVsyXSA9IG1vaS56OwoJbW9pLnRoZXRhID0gLU1fUEkgLyAyLjA7Cgltb2kucGhpID0gMC4wOwoKCWF1dG9tb2RlID0gMDsKCWdsdXRJbml0RGlzcGxheU1vZGUoR0xVVF9ET1VCTEUgfCBHTFVUX1JHQiB8IEdMVVRfREVQVEgpOwoJdXBkYXRlX3ZpZXdlcigpOwoKCWdsRW5hYmxlKEdMX0xJR0hUSU5HKTsKCWdsRW5hYmxlKEdMX0RFUFRIX1RFU1QpOwoJZ2xFbmFibGUoR0xfVEVYVFVSRV8yRCk7CglnbEVuYWJsZShHTF9MSUdIVDApOwoJZ2xFbmFibGUoR0xfTElHSFQxKTsKCglnbExpZ2h0ZnYoR0xfTElHSFQwLCBHTF9QT1NJVElPTiwgcG9zMSk7CglnbExpZ2h0ZnYoR0xfTElHSFQwLCBHTF9BTUJJRU5ULCBhbWIpOwoJZ2xMaWdodGZ2KEdMX0xJR0hUMCwgR0xfRElGRlVTRSwgZGlmKTsKCWdsTGlnaHRmdihHTF9MSUdIVDAsIEdMX1NQRUNVTEFSLCBzcGUpOwoKCWdsTGlnaHRmdihHTF9MSUdIVDAsIEdMX1BPU0lUSU9OLCBwb3MyKTsKCWdsTGlnaHRmdihHTF9MSUdIVDAsIEdMX0FNQklFTlQsIGFtYik7CglnbExpZ2h0ZnYoR0xfTElHSFQwLCBHTF9ESUZGVVNFLCBkaWYpOwoJZ2xMaWdodGZ2KEdMX0xJR0hUMCwgR0xfU1BFQ1VMQVIsIHNwZSk7CgoJYm9keSA9IGdsdU5ld1F1YWRyaWMoKTsKCWdsdVF1YWRyaWNEcmF3U3R5bGUoYm9keSwgR0xVX0xJTkUpOwoKCWluaXRfbW9uc3RlcigmYm9iKTsKCWluaXRfYWN0aW9uKCZraWNrKTsKfQp2b2lkIGFuaW1hdGUoKQp7CglpbnQgbjsKCglpZiAoIWF1dG9tb2RlKQoJCXJldHVybjsKCWZwcmludGYoc3RkZXJyLCAibWFkZSBpdCB0byBhbmltYXRlIVxuIik7CgluID0ga2ljay5jdXJyZW50cGhhc2UrKzsKCWlmIChuID49IE1BWFRJQ0tTKXsKCQlhdXRvbW9kZSA9IDA7CgkJYm9iLnJpZ2h0bGVnID0ga2ljay5zdGFydGFuZ2xlOwoJfQoJZWxzZSB7CgkJYm9iLnJpZ2h0bGVnID0ga2ljay5hbmdsZVtuXTsKCX0KCXVwZGF0ZV92aWV3ZXIoKTsKCWdsdXRQb3N0UmVkaXNwbGF5KCk7Cn0Kdm9pZCB1cGRhdGVfdmlld2VyKCkKewoJbW9pLnZ4ID0gY29zKG1vaS50aGV0YSk7Cgltb2kudnkgPSBzaW4obW9pLnBoaSk7Cgltb2kudnogPSBzaW4obW9pLnRoZXRhKTsKfQp2b2lkIGRpc3BsYXkoKQp7CglpbnQgaSwgaiwgaywgdSwgdjsKCgkKCWdsQ2xlYXIoR0xfQ09MT1JfQlVGRkVSX0JJVCB8IEdMX0RFUFRIX0JVRkZFUl9CSVQpOwoJZ2xMaW5lV2lkdGgoMi4wKTsKCWdsTG9hZElkZW50aXR5KCk7CgoJZ2x1TG9va0F0KG1vaS54LCBtb2kueSwgbW9pLnosCgkJbW9pLnggKyBtb2kudngsIG1vaS55ICsgbW9pLnZ5LCBtb2kueiArIG1vaS52eiwKCQkwLjAsIDEuMCwgMC4wKTsKCgkvKiBibG9ja3MoeCx5LHopICovCglmb3IgKGkgPSAtMTA7IGkgPCAyMDsgaSsrKXsKCQlmb3IgKGsgPSAtMTA7IGsgPCAyMDsgaysrKXsKCQkJdiA9IHJhbmQoKTsKCQkJaWYgKHYgJSAyID09IDApewoJCQkJZ2xDb2xvcjNmKDEuMGYsIDEuMGYsIDEuMGYpOwoJCQl9CgkJCWVsc2V7CgkJCQlnbENvbG9yM2YoMC4xZiwgMC45ZiwgMC4yZik7CgkJCX0KCQkJCgkJCWJsb2NrcyhpLCAwLCBrKTsKCQl9Cgl9CgoJLy9tb25zdGVyKCZib2IpOwoKCWdsdXRTd2FwQnVmZmVycygpOwp9CnZvaWQgYmxvY2tzKGludCB4LCBpbnQgeSwgaW50IHopCnsKCS8qIGZsb29yIGJsb2NrcyAqLwoKLy8JZ2xNYXRlcmlhbGZ2KEdMX0ZST05UX0FORF9CQUNLLCBHTF9BTUJJRU5ULCBtYXRhbWIpOwovLwlnbE1hdGVyaWFsZnYoR0xfRlJPTlRfQU5EX0JBQ0ssIEdMX0RJRkZVU0UsIG1hdGRpZik7Ci8vCWdsTWF0ZXJpYWxmdihHTF9GUk9OVF9BTkRfQkFDSywgR0xfU1BFQ1VMQVIsIG1hdHNwZSk7Ci8vCWdsTWF0ZXJpYWxmKEdMX0ZST05UX0FORF9CQUNLLCBHTF9TSElOSU5FU1MsIDUwLjApOwoJZ2xCZWdpbihHTF9MSU5FX1NUUklQKTsKCS8qIHRvcCBvZiBibG9jayAqLwoJZ2xWZXJ0ZXgzZih4LCAgICAgeSsxLjAsIHopOwoJZ2xWZXJ0ZXgzZih4KzEuMCwgeSsxLjAsIHopOwoJZ2xWZXJ0ZXgzZih4KzEuMCwgeSsxLjAsIHorMS4wKTsKCWdsVmVydGV4M2YoeCwgICAgIHkrMS4wLCB6KzEuMCk7CglnbEVuZCgpOwoJLyogbGVmdCBvZiBibG9jayAqLwoJZ2xCZWdpbihHTF9MSU5FX1NUUklQKTsKCWdsVmVydGV4M2YoeCwgeSsxLjAsIHopOwoJZ2xWZXJ0ZXgzZih4LCB5LCAgICAgeik7CglnbFZlcnRleDNmKHgsIHksICAgICB6KzEuMCk7CglnbFZlcnRleDNmKHgsIHkgKyAxLjAsIHogKyAxLjApOwoJZ2xFbmQoKTsKCS8qIHJpZ2h0IG9mIGJsb2NrICovCglnbEJlZ2luKEdMX0xJTkVfU1RSSVApOwoJZ2xWZXJ0ZXgzZih4KzEuMCwgeSsxLjAsIHopOwoJZ2xWZXJ0ZXgzZih4KzEuMCwgeSwgICAgIHopOwoJZ2xWZXJ0ZXgzZih4KzEuMCwgeSwgICAgIHorMS4wKTsKCWdsVmVydGV4M2YoeCsxLjAsIHkrMS4wLCB6KzEuMCk7CglnbEVuZCgpOwoJLyogZnJvbnQgb2YgYmxvY2sgKi8KCWdsQmVnaW4oR0xfTElORV9TVFJJUCk7CglnbFZlcnRleDNmKHgsICAgICB5KzEuMCwgeik7CglnbFZlcnRleDNmKHgsICAgICB5LCAgICAgeik7CglnbFZlcnRleDNmKHgrMS4wLCB5LCAgICAgeik7CglnbFZlcnRleDNmKHgrMS4wLCB5KzEuMCwgeik7CglnbEVuZCgpOwoJLyogYmFjayBvZiBibG9jayAqLwoJZ2xCZWdpbihHTF9MSU5FX1NUUklQKTsKCWdsVmVydGV4M2YoeCwgICAgIHkrMS4wLCB6KzEuMCk7CglnbFZlcnRleDNmKHgsICAgICB5LCAgICAgeisxLjApOwoJZ2xWZXJ0ZXgzZih4KzEuMCwgeSwgICAgIHorMS4wKTsKCWdsVmVydGV4M2YoeCsxLjAsIHkrMS4wLCB6KzEuMCk7CglnbEVuZCgpOwoJLyogYm90dG9tIG9mIGJsb2NrICovCglnbEJlZ2luKEdMX0xJTkVfU1RSSVApOwoJZ2xWZXJ0ZXgzZih4LCAgICAgeSwgeik7CglnbFZlcnRleDNmKHgrMS4wLCB5LCB6KTsKCWdsVmVydGV4M2YoeCsxLjAsIHksIHorMS4wKTsKCWdsVmVydGV4M2YoeCwgICAgIHksIHorMS4wKTsKCWdsRW5kKCk7Cn0Kdm9pZCBtb25zdGVyKE1PTlNURVIgKnApCnsKCWdsUHVzaE1hdHJpeCgpOwoKCWdsTWF0ZXJpYWxmdihHTF9GUk9OVF9BTkRfQkFDSywgR0xfQU1CSUVOVCwgb2JqYW1iKTsKCWdsTWF0ZXJpYWxmdihHTF9GUk9OVF9BTkRfQkFDSywgR0xfRElGRlVTRSwgb2JqZGlmKTsKCWdsTWF0ZXJpYWxmdihHTF9GUk9OVF9BTkRfQkFDSywgR0xfU1BFQ1VMQVIsIG9ianNwZSk7CglnbE1hdGVyaWFsZihHTF9GUk9OVF9BTkRfQkFDSywgR0xfU0hJTklORVNTLCAxMC4wKTsKCglnbFJvdGF0ZWYoYm9iLmhlYWRpbmcsIDAuMCwgMS4wLCAwLjApOwoKCWdsUm90YXRlZigtOTAuMCwgMS4wLCAwLjAsIDAuMCk7CgoJLyogdG9yc28gYW5kIGhlYWQqLwoKCWdsUHVzaE1hdHJpeCgpOwoKCWdsVHJhbnNsYXRlZigwLjAsIDAuMCwgMi41KTsKCWdsdVNwaGVyZShib2R5LCAwLjUsIDEyLCAxMik7CgoJZ2xUcmFuc2xhdGVmKDAuMCwgMC4wLCAtMS41KTsKCWdsU2NhbGVmKDAuNSwgMS4wLCAxLjApOwoJZ2x1Q3lsaW5kZXIoYm9keSwgMC4yLCAwLjMsIDEuMCwgMTIsIDEyKTsKCWdsUG9wTWF0cml4KCk7CgoJLyogbGVncyAqLwoJZ2xQdXNoTWF0cml4KCk7CglnbFRyYW5zbGF0ZWYoMC4wLCAwLjEsIDEuMCk7CglnbFJvdGF0ZWYocC0+cmlnaHRsZWcsIDAuMCwgMS4wLCAwLjApOwoJZ2xUcmFuc2xhdGVmKDAuMCwgMC4wLCAtMS4wKTsKCWdsdUN5bGluZGVyKGJvZHksIDAuMDUsIDAuMDUsIDEuMCwgMTIsIDEyKTsKCWdsUG9wTWF0cml4KCk7CgoJZ2xUcmFuc2xhdGVmKDAuMCwgLTAuMSwgMC4wKTsKCWdsdUN5bGluZGVyKGJvZHksIDAuMDUsIDAuMDUsIDEuMCwgMTIsIDEyKTsKCglnbFBvcE1hdHJpeCgpOwp9