Annotation of frontvm/src/screen.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari - screen.c
        !             3: 
        !             4:   This file is distributed under the GNU Public License, version 2 or at your
        !             5:   option any later version. Read the file gpl.txt for details.
        !             6: */
        !             7: 
        !             8: #include <SDL.h>
        !             9: #include <GL/gl.h>
        !            10: #include <GL/glu.h>
        !            11: 
        !            12: #include "main.h"
        !            13: #include "../m68000.h"
        !            14: #include "screen.h"
        !            15: 
        !            16: unsigned long VideoBase;                        /* Base address in ST Ram for screen(read on each VBL) */
        !            17: unsigned char *VideoRaster;                      /* Pointer to Video raster, after VideoBase in PC address space. Use to copy data on HBL */
        !            18: 
        !            19: int len_main_palette;
        !            20: unsigned short MainPalette[256];
        !            21: unsigned short CtrlPalette[16];
        !            22: int fe2_bgcol;
        !            23: 
        !            24: unsigned int MainRGBPalette[256];
        !            25: unsigned int CtrlRGBPalette[16];
        !            26: 
        !            27: unsigned long logscreen, logscreen2, physcreen, physcreen2;
        !            28: 
        !            29: SDL_Surface *sdlscrn;                             /* The SDL screen surface */
        !            30: BOOL bGrabMouse = FALSE;                          /* Grab the mouse cursor in the window */
        !            31: BOOL bInFullScreen = FALSE;
        !            32: 
        !            33: /* new stuff */
        !            34: enum RENDERERS use_renderer = R_GL;
        !            35: /* mouse shown this frame? */
        !            36: int mouse_shown = 0;
        !            37: /* fe2 UI blits are done to old screen memory and copied to this texture. */
        !            38: static unsigned int screen_tex;
        !            39: 
        !            40: static GLUquadricObj *qobj;
        !            41: static GLUtesselator *tobj;
        !            42: 
        !            43: float hack;
        !            44: 
        !            45: #define SCR_TEX_W      512
        !            46: #define SCR_TEX_H      256
        !            47: 
        !            48: #define RAD_2_DEG      57.295779513082323f
        !            49: 
        !            50: /*-----------------------------------------------------------------------*/
        !            51: /*
        !            52:   Set window size
        !            53: */
        !            54: int screen_w = 640;
        !            55: int screen_h = 480;
        !            56: #define GLERR { printf ("GL: %s\n", gluErrorString (glGetError ()));}
        !            57: 
        !            58: #ifndef CALLBACK
        !            59: # ifdef WIN32
        !            60: #  define CALLBACK __attribute__ ((__stdcall__))
        !            61: # else
        !            62: #  define CALLBACK
        !            63: # endif
        !            64: #endif /* CALLBACK */
        !            65: 
        !            66: void CALLBACK beginCallback(GLenum which);
        !            67: void CALLBACK errorCallback(GLenum errorCode);
        !            68: void CALLBACK endCallback(void);
        !            69: void CALLBACK vertexCallback(GLvoid *vertex, GLvoid *poly_data);
        !            70: void CALLBACK combineCallback(GLdouble coords[3], 
        !            71:                      GLdouble *vertex_data[4],
        !            72:                      GLfloat weight[4], GLdouble **dataOut );
        !            73: 
        !            74: static void set_main_viewport ()
        !            75: {
        !            76:        int ctrl_h = 32*screen_h/200;
        !            77:        glViewport (0, ctrl_h, screen_w, screen_h - ctrl_h);
        !            78: }
        !            79: 
        !            80: static void set_ctrl_viewport ()
        !            81: {
        !            82:        glViewport (0, 0, screen_w, screen_h);
        !            83: }
        !            84: 
        !            85: static void change_vidmode ()
        !            86: {
        !            87:        const SDL_VideoInfo *info = NULL;
        !            88:        int modes;
        !            89: 
        !            90:        info = SDL_GetVideoInfo ();
        !            91: 
        !            92:        assert (info != NULL);
        !            93: 
        !            94:        SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
        !            95:        
        !            96:        modes = SDL_OPENGL | SDL_ANYFORMAT | (bInFullScreen ? SDL_FULLSCREEN : 0);
        !            97:        
        !            98:        if ((sdlscrn = SDL_SetVideoMode (screen_w, screen_h,
        !            99:                                info->vfmt->BitsPerPixel, modes)) == 0) {
        !           100:                fprintf (stderr, "Video mode set failed: %s\n", SDL_GetError ());
        !           101:                SDL_Quit ();
        !           102:                exit (-1);
        !           103:        }
        !           104: 
        !           105:        glDisable (GL_CULL_FACE);
        !           106:        glShadeModel (GL_FLAT);
        !           107:        glDisable (GL_DEPTH_TEST);
        !           108:        glClearColor (0, 0, 0, 0);
        !           109: 
        !           110:        glMatrixMode (GL_PROJECTION);
        !           111:        glLoadIdentity ();
        !           112:        /* aspect ratio of frontier's 3d view is 320/168 = 1.90 */
        !           113:        gluPerspective (36.5f, 1.9f, 1.0f, 10000000000.0f);
        !           114: 
        !           115:        glEnable (GL_TEXTURE_2D);
        !           116:        glGenTextures (1, &screen_tex);
        !           117:        glBindTexture (GL_TEXTURE_2D, screen_tex);
        !           118:        glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, SCR_TEX_W, SCR_TEX_H, 0, GL_RGBA, GL_INT, 0);
        !           119:        glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        !           120:        glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        !           121:        glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        !           122:        glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        !           123:        
        !           124:        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        !           125:        glDisable (GL_TEXTURE_2D);
        !           126:        
        !           127:        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        !           128:        glMatrixMode (GL_MODELVIEW);
        !           129:        glLoadIdentity ();
        !           130:        glDisable (GL_DEPTH_TEST);
        !           131: }
        !           132: 
        !           133: void Screen_Init(void)
        !           134: {
        !           135:        change_vidmode ();
        !           136:        
        !           137:        qobj = gluNewQuadric ();
        !           138: 
        !           139:        tobj = gluNewTess ();
        !           140:                
        !           141:        gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (_GLUfuncptr) vertexCallback);
        !           142:        gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr) beginCallback);
        !           143:        gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr) endCallback);
        !           144:        gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr) errorCallback);
        !           145:        gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr) combineCallback);
        !           146:        
        !           147:        /* Configure some SDL stuff: */
        !           148:        SDL_WM_SetCaption(PROG_NAME, "Frontier");
        !           149:        SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
        !           150:        SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
        !           151:        SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
        !           152:        SDL_ShowCursor(SDL_ENABLE);
        !           153: }
        !           154: 
        !           155: void Screen_UnInit(void)
        !           156: {
        !           157: }
        !           158: 
        !           159: void Screen_ToggleFullScreen ()
        !           160: {
        !           161:        bInFullScreen = !bInFullScreen;
        !           162:        change_vidmode ();
        !           163:        //SDL_WM_ToggleFullScreen (sdlscrn);
        !           164: }
        !           165: 
        !           166: static const unsigned char font_bmp[] = {
        !           167:        0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x80,0x80,0x80,0x80,0x80,0x0,
        !           168:        0x80,0x0,0x0,0x2,0xa0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x50,
        !           169:        0xf8,0x50,0x50,0xf8,0x50,0x0,0x0,0x6,0x20,0xf0,0xa0,0xa0,0xa0,0xa0,0xf0,0x20,
        !           170:        0x0,0x5,0x0,0xc8,0xd8,0x30,0x60,0xd8,0x98,0x0,0x0,0x6,0xa0,0x0,0xe0,0xa0,
        !           171:        0xa0,0xa0,0xe0,0x0,0x0,0x4,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,
        !           172:        0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0x0,0x3,0xc0,0x40,0x40,0x40,0x40,0x40,
        !           173:        0x40,0xc0,0x0,0x3,0x0,0x0,0x20,0xf8,0x50,0xf8,0x20,0x0,0x0,0x6,0x0,0x0,
        !           174:        0x40,0xe0,0x40,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x80,
        !           175:        0x0,0x2,0x0,0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x0,
        !           176:        0x0,0x0,0x80,0x0,0x0,0x2,0x0,0x8,0x18,0x30,0x60,0xc0,0x80,0x0,0x0,0x6,
        !           177:        0xe0,0xa0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x40,0xc0,0x40,0x40,0x40,0x40,
        !           178:        0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0xe0,0x80,0x80,0xe0,0x0,0x0,0x4,0xe0,0x20,
        !           179:        0x20,0xe0,0x20,0x20,0xe0,0x0,0x0,0x4,0x80,0x80,0xa0,0xa0,0xe0,0x20,0x20,0x0,
        !           180:        0x0,0x4,0xe0,0x80,0x80,0xe0,0x20,0x20,0xe0,0x0,0x0,0x4,0xe0,0x80,0x80,0xe0,
        !           181:        0xa0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x4,
        !           182:        0xe0,0xa0,0xa0,0xe0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0xa0,0xa0,0xe0,0x20,0x20,
        !           183:        0xe0,0x0,0x0,0x4,0x0,0x0,0x0,0x80,0x0,0x80,0x0,0x0,0x0,0x2,0x0,0x0,
        !           184:        0x0,0x80,0x0,0x0,0x80,0x80,0x0,0x2,0xe0,0x0,0xe0,0xa0,0xa0,0xa0,0xa0,0x0,
        !           185:        0x0,0x4,0x0,0x0,0xe0,0x0,0xe0,0x0,0x0,0x0,0x0,0x4,0xc0,0x0,0xe0,0xa0,
        !           186:        0xe0,0x80,0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0xe0,0x80,0x0,0x80,0x0,0x0,0x4,
        !           187:        0xfe,0x82,0xba,0xa2,0xba,0x82,0xfe,0x0,0x0,0x8,0xf0,0x90,0x90,0x90,0xf0,0x90,
        !           188:        0x90,0x0,0x0,0x5,0xf0,0x90,0x90,0xf8,0x88,0x88,0xf8,0x0,0x0,0x6,0xe0,0x80,
        !           189:        0x80,0x80,0x80,0x80,0xe0,0x0,0x0,0x4,0xf8,0x48,0x48,0x48,0x48,0x48,0xf8,0x0,
        !           190:        0x0,0x6,0xf0,0x80,0x80,0xe0,0x80,0x80,0xf0,0x0,0x0,0x5,0xf0,0x80,0x80,0xe0,
        !           191:        0x80,0x80,0x80,0x0,0x0,0x4,0xf0,0x80,0x80,0x80,0xb0,0x90,0xf0,0x0,0x0,0x5,
        !           192:        0x90,0x90,0x90,0xf0,0x90,0x90,0x90,0x0,0x0,0x5,0xe0,0x40,0x40,0x40,0x40,0x40,
        !           193:        0xe0,0x0,0x0,0x4,0xf0,0x20,0x20,0x20,0x20,0x20,0xe0,0x0,0x0,0x4,0x90,0xb0,
        !           194:        0xe0,0xc0,0xe0,0xb0,0x90,0x0,0x0,0x5,0x80,0x80,0x80,0x80,0x80,0x80,0xe0,0x0,
        !           195:        0x0,0x4,0x88,0xd8,0xf8,0xa8,0x88,0x88,0x88,0x0,0x0,0x6,0x90,0xd0,0xf0,0xb0,
        !           196:        0x90,0x90,0x90,0x0,0x0,0x5,0xf0,0x90,0x90,0x90,0x90,0x90,0xf0,0x0,0x0,0x5,
        !           197:        0xf0,0x90,0x90,0xf0,0x80,0x80,0x80,0x0,0x0,0x5,0xf0,0x90,0x90,0x90,0x90,0xb0,
        !           198:        0xf0,0x18,0x0,0x5,0xf0,0x90,0x90,0xf0,0xe0,0xb0,0x90,0x0,0x0,0x5,0xf0,0x80,
        !           199:        0x80,0xf0,0x10,0x10,0xf0,0x0,0x0,0x5,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,0x0,
        !           200:        0x0,0x3,0x90,0x90,0x90,0x90,0x90,0x90,0xf0,0x0,0x0,0x5,0x90,0x90,0x90,0xb0,
        !           201:        0xe0,0xc0,0x80,0x0,0x0,0x5,0x88,0x88,0x88,0xa8,0xf8,0xd8,0x88,0x0,0x0,0x6,
        !           202:        0x88,0xd8,0x70,0x20,0x70,0xd8,0x88,0x0,0x0,0x6,0x90,0x90,0x90,0xf0,0x20,0x20,
        !           203:        0x20,0x0,0x0,0x5,0xf0,0x10,0x30,0x60,0xc0,0x80,0xf0,0x0,0x0,0x5,0xa0,0x0,
        !           204:        0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x80,0xc0,0x60,0x30,0x18,0x8,0x0,
        !           205:        0x0,0x6,0xe0,0xa0,0xa0,0xe0,0xa0,0xa0,0xe0,0x80,0x80,0x4,0xe0,0xa0,0xe0,0x0,
        !           206:        0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8,0x0,0x6,
        !           207:        0xa0,0x0,0xe0,0x20,0xe0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,0xe0,0x20,0xe0,0xa0,
        !           208:        0xe0,0x0,0x0,0x4,0x80,0x80,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,
        !           209:        0xc0,0x80,0x80,0x80,0xc0,0x0,0x0,0x3,0x20,0x20,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,
        !           210:        0x0,0x4,0x0,0x0,0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xc0,0x80,0x80,0xc0,
        !           211:        0x80,0x80,0x80,0x0,0x0,0x3,0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x20,0xe0,0x4,
        !           212:        0x80,0x80,0xe0,0xa0,0xa0,0xa0,0xa0,0x0,0x0,0x4,0x80,0x0,0x80,0x80,0x80,0x80,
        !           213:        0x80,0x0,0x0,0x2,0x40,0x0,0x40,0x40,0x40,0x40,0x40,0xc0,0x0,0x3,0x80,0x80,
        !           214:        0xb0,0xe0,0xe0,0xb0,0x90,0x0,0x0,0x5,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x0,
        !           215:        0x0,0x2,0x0,0x0,0xf8,0xa8,0xa8,0xa8,0xa8,0x0,0x0,0x6,0x0,0x0,0xe0,0xa0,
        !           216:        0xa0,0xa0,0xa0,0x0,0x0,0x4,0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,
        !           217:        0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x80,0x80,0x4,0x0,0x0,0xe0,0xa0,0xa0,0xa0,
        !           218:        0xe0,0x20,0x30,0x4,0x0,0x0,0xc0,0x80,0x80,0x80,0x80,0x0,0x0,0x3,0x0,0x0,
        !           219:        0xc0,0x80,0xc0,0x40,0xc0,0x0,0x0,0x3,0x80,0x80,0xc0,0x80,0x80,0x80,0xc0,0x0,
        !           220:        0x0,0x3,0x0,0x0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,0xa0,0xa0,
        !           221:        0xe0,0xc0,0x80,0x0,0x0,0x4,0x0,0x0,0x88,0xa8,0xf8,0xd8,0x88,0x0,0x0,0x6,
        !           222:        0x0,0x0,0xa0,0xe0,0x40,0xe0,0xa0,0x0,0x0,0x4,0x0,0x0,0xa0,0xa0,0xa0,0xa0,
        !           223:        0xe0,0x20,0xe0,0x4,0x0,0x0,0xf0,0x30,0x60,0xc0,0xf0,0x0,0x0,0x5,0x81,0x8d,
        !           224:        0xe1,0xa0,0xa0,0xa0,0xa0,0x0,0x0,0x9,0x2,0x1a,0xc2,0x80,0xc0,0x40,0xc0,0x0,
        !           225:        0x0,0x8,0xfe,0xfc,0xf8,0xfc,0xfe,0xdf,0x8e,0x4,0x0,0x7,0x7f,0x3f,0x1f,0x3f,
        !           226:        0x7f,0xfb,0x71,0x20,0x0,0x8,0x4,0x8e,0xdf,0xfe,0xfc,0xf8,0xfc,0xfe,0x0,0x8,
        !           227:        0x20,0x71,0xfb,0x7f,0x3f,0x1f,0x3f,0x7f,0x0,0x7,0xff,0x81,0x81,0x81,0x81,0x81,
        !           228:        0x81,0xff,0x0,0x9,0x0,0x0,0xe0,0x80,0x80,0x80,0xe0,0x40,0xc0,0x4,0x60,0x0,
        !           229:        0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xc0,0x0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,
        !           230:        0x0,0x4,0x40,0xa0,0x40,0x40,0x40,0x40,0x40,0x0,0x0,0x4,0x40,0xa0,0xe0,0x20,
        !           231:        0xe0,0xa0,0xe0,0x0,0x0,0x4,0x40,0xa0,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,
        !           232:        0x40,0xa0,0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xe0,0x0,0xa0,0xa0,0xa0,0xa0,
        !           233:        0xe0,0x0,0x0,0x4,0xc0,0x0,0xe0,0x20,0xe0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0xa0,
        !           234:        0xa0,0xa0,0xe0,0xa0,0xa0,0x0,0x0,0x4,0xc0,0xa0,0xa0,0xc0,0xa0,0xa0,0xc0,0x0,
        !           235:        0x0,0x4,0xe0,0x80,0x80,0x80,0x80,0x80,0xe0,0x0,0x0,0x4,0xc0,0xa0,0xa0,0xa0,
        !           236:        0xa0,0xa0,0xc0,0x0,0x0,0x4,0xe0,0x80,0x80,0xe0,0x80,0x80,0xe0,0x0,0x0,0x4,
        !           237:        0xe0,0x80,0x80,0xe0,0x80,0x80,0x80,0x0,0x0,0x4
        !           238: };
        !           239: 
        !           240: static int DrawChar (int col, int xoffset, char *scrline, int chr)
        !           241: {
        !           242:        const char *font_pos;
        !           243:        char *pix;
        !           244:        int i;
        !           245:        
        !           246:        font_pos = font_bmp;
        !           247:        font_pos += (chr&0xff)*10;
        !           248:        scrline += xoffset;
        !           249:        
        !           250:        if (xoffset < 0) {
        !           251:                font_pos += 9;
        !           252:                return xoffset + *font_pos;
        !           253:        }
        !           254:        
        !           255:        for (i=0; i<8; i++, font_pos++, scrline += SCREENBYTES_LINE) {
        !           256:                pix = scrline;
        !           257:                if (xoffset > 319) continue;
        !           258:                if (*font_pos & 0x80) *pix = col;
        !           259:                pix++;
        !           260:                if (xoffset+1 > 319) continue;
        !           261:                if (*font_pos & 0x40) *pix = col;
        !           262:                pix++;
        !           263:                if (xoffset+2 > 319) continue;
        !           264:                if (*font_pos & 0x20) *pix = col;
        !           265:                pix++;
        !           266:                if (xoffset+3 > 319) continue;
        !           267:                if (*font_pos & 0x10) *pix = col;
        !           268:                pix++;
        !           269:                if (xoffset+4 > 319) continue;
        !           270:                if (*font_pos & 0x8) *pix = col;
        !           271:                pix++;
        !           272:                if (xoffset+5 > 319) continue;
        !           273:                if (*font_pos & 0x4) *pix = col;
        !           274:                pix++;
        !           275:                if (xoffset+6 > 319) continue;
        !           276:                if (*font_pos & 0x2) *pix = col;
        !           277:                pix++;
        !           278:                if (xoffset+7 > 319) continue;
        !           279:                if (*font_pos & 0x1) *pix = col;
        !           280:        }
        !           281:        /* width of character */
        !           282:        font_pos++;
        !           283:        i = *font_pos;
        !           284:        return xoffset + i;
        !           285: }
        !           286: 
        !           287: #define MAX_QUEUED_STRINGS     200
        !           288: struct QueuedString {
        !           289:        int x, y, col;
        !           290:        unsigned char str[64];
        !           291: } queued_strings[MAX_QUEUED_STRINGS];
        !           292: int queued_string_pos;
        !           293: 
        !           294: void Nu_QueueDrawStr ()
        !           295: {
        !           296:        assert (queued_string_pos < MAX_QUEUED_STRINGS);
        !           297:        strncpy (queued_strings[queued_string_pos].str, GetReg (REG_A0) + STRam, 64);
        !           298:        queued_strings[queued_string_pos].x = GetReg (REG_D1);
        !           299:        queued_strings[queued_string_pos].y = GetReg (REG_D2);
        !           300:        queued_strings[queued_string_pos++].col = GetReg (REG_D0);
        !           301: }
        !           302: 
        !           303: int DrawStr (int xpos, int ypos, int col, unsigned char *str, bool shadowed)
        !           304: {
        !           305:        int x, y, chr;
        !           306:        char *screen;
        !           307: 
        !           308:        x = xpos;
        !           309:        y = ypos;
        !           310:        
        !           311:        if ((y > 192) || (y<0)) return x;
        !           312: set_line:
        !           313:        screen = LOGSCREEN2;
        !           314:        screen += SCREENBYTES_LINE * y;
        !           315: 
        !           316:        while (*str) {
        !           317:                chr = *(str++);
        !           318:                
        !           319:                if (chr < 0x1e) {
        !           320:                        if (chr == '\r') {
        !           321:                                y += 10;
        !           322:                                x = xpos;
        !           323:                                goto set_line;
        !           324:                        }
        !           325:                        else if (chr == 1) col = *(str++);
        !           326:                        continue;
        !           327:                } else if (chr == 0x1e) {
        !           328:                        /* read new xpos */
        !           329:                        x = *(str++);
        !           330:                        x *= 2;
        !           331:                        continue;
        !           332:                } else if (chr < 0x20) {
        !           333:                        /* Read new position */
        !           334:                        x = *(str++);
        !           335:                        x *= 2;
        !           336:                        y = *(str++);
        !           337:                        goto set_line;
        !           338:                }
        !           339:                
        !           340:                //if (x > 316) continue;
        !           341: 
        !           342:                if (shadowed) {
        !           343:                        DrawChar (0, x+1, screen+SCREENBYTES_LINE, chr-0x20);
        !           344:                }
        !           345:                x = DrawChar (col, x, screen, chr-0x20);
        !           346:        }
        !           347: 
        !           348:        return x;
        !           349: }
        !           350: 
        !           351: static void push_ortho ()
        !           352: {
        !           353:        glDisable (GL_DEPTH_TEST);
        !           354:        glMatrixMode (GL_PROJECTION);
        !           355:        glPushMatrix ();
        !           356:        glLoadIdentity ();
        !           357:        glOrtho (0, 320, 0, 200, -1, 1);
        !           358: 
        !           359:        glMatrixMode (GL_MODELVIEW);
        !           360:        glPushMatrix ();
        !           361:        glLoadIdentity ();
        !           362: }
        !           363: 
        !           364: static void pop_ortho ()
        !           365: {
        !           366:        glMatrixMode (GL_PROJECTION);
        !           367:        glPopMatrix ();
        !           368:        glMatrixMode (GL_MODELVIEW);
        !           369:        glPopMatrix ();
        !           370: }
        !           371: 
        !           372: void Screen_ToggleRenderer ()
        !           373: {
        !           374:        use_renderer++;
        !           375:        if (use_renderer >= R_MAX) use_renderer = 0;
        !           376: }
        !           377: 
        !           378: static void draw_control_panel ()
        !           379: {
        !           380:        int x, y;
        !           381:        unsigned char *scr;
        !           382:        unsigned int line[320];
        !           383:        unsigned int *pal;
        !           384: 
        !           385:        set_ctrl_viewport ();
        !           386:        
        !           387:        /* this is a big fucking hack to make starsystem names
        !           388:         * in the starmap show up. they are the only bitmap text
        !           389:         * things drawn within the fe2 3d renderer, which makes
        !           390:         * them fucking annoying. */
        !           391:        y = logscreen2;
        !           392:        logscreen2 = physcreen;
        !           393:        for (x=0; x<queued_string_pos; x++) {
        !           394:                DrawStr (       queued_strings[x].x,
        !           395:                                queued_strings[x].y,
        !           396:                                queued_strings[x].col,
        !           397:                                queued_strings[x].str,
        !           398:                                FALSE);
        !           399:        }
        !           400:        logscreen2 = y;
        !           401:        /****************************************************/
        !           402:        
        !           403:        scr = VideoRaster;
        !           404:        
        !           405:        /* intro likes black at the bottom */
        !           406:        /* hack hack hack what a pile of shite this is */
        !           407:        push_ortho ();
        !           408:        glColor3f (0.0f, 0.0f, 0.0f);
        !           409:        glBegin (GL_TRIANGLE_STRIP);
        !           410:                glVertex3f (0, 32, 0);
        !           411:                glVertex3f (319, 32, 0);
        !           412:                glVertex3f (0, 0, 0);
        !           413:                glVertex3f (319, 0, 0);
        !           414:        glEnd ();
        !           415:        
        !           416:        glEnable (GL_TEXTURE_2D);
        !           417:        
        !           418:        glBindTexture (GL_TEXTURE_2D, screen_tex);
        !           419: 
        !           420:        pal = MainRGBPalette;
        !           421:        
        !           422:        /* copy whole 320x200 screen to texture */
        !           423:        for (y=0; y<200; y++) {
        !           424:                /* the control panel at the bottom has its own palette */
        !           425:                if (y >= 168) pal = CtrlRGBPalette;
        !           426:                
        !           427:                for (x=0; x<320; x++) {
        !           428:                        /* in gl mode the ui texture has transparent crap where no shit is */
        !           429:                        if ((*(scr)) == 255) {
        !           430:                                scr++;
        !           431:                                line[x] = 0;
        !           432:                        } else {
        !           433:                                line[x] = pal[*(scr++)];
        !           434:                        }
        !           435:                }
        !           436:                glTexSubImage2D (GL_TEXTURE_2D, 0, 0, y, 320, 2, GL_RGBA, GL_UNSIGNED_BYTE, line);
        !           437:        }
        !           438:        glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        !           439:        
        !           440:        if (use_renderer == R_OLD) {
        !           441:                glBegin (GL_TRIANGLE_STRIP);
        !           442:                        glTexCoord2f (0.0f, 200.0f/SCR_TEX_H);
        !           443:                        glVertex2i (0, 0);
        !           444:                        glTexCoord2f (320.0f/SCR_TEX_W, 200.0f/SCR_TEX_H);
        !           445:                        glVertex2i (320, 0);
        !           446:                        glTexCoord2f (0.0f, 0.0f);
        !           447:                        glVertex2i (0, 200);
        !           448:                        glTexCoord2f (320.0f/SCR_TEX_W, 0.0f);
        !           449:                        glVertex2i (320, 200);
        !           450:                glEnd ();
        !           451:        } else {
        !           452:                glEnable (GL_BLEND);
        !           453:                glBegin (GL_TRIANGLE_STRIP);
        !           454:                        glTexCoord2f (0.0f, 200.0f/SCR_TEX_H);
        !           455:                        glVertex2i (0, 0);
        !           456:                        glTexCoord2f (320.0f/SCR_TEX_W, 200.0f/SCR_TEX_H);
        !           457:                        glVertex2i (320, 0);
        !           458:                        glTexCoord2f (0.0f, 0.0f);
        !           459:                        glVertex2i (0, 200);
        !           460:                        glTexCoord2f (320.0f/SCR_TEX_W, 0.0f);
        !           461:                        glVertex2i (320, 200);
        !           462:                glEnd ();
        !           463:                glDisable (GL_BLEND);
        !           464:        }
        !           465:        
        !           466:        glDisable (GL_TEXTURE_2D);
        !           467:        
        !           468:        pop_ortho ();
        !           469: }
        !           470: 
        !           471: static void _BuildRGBPalette (unsigned int *rgb, unsigned short *st, int len)
        !           472: {
        !           473:        int i;
        !           474:        int st_col, r, g, b;
        !           475: 
        !           476:        for (i=0; i<len; i++, st++) {
        !           477:                st_col = *st;
        !           478:                b = (st_col & 0xf)<<4;
        !           479:                g = (st_col & 0xf0);
        !           480:                r = (st_col & 0xf00)>>4;
        !           481:                rgb[i] = 0xff000000 | (b<<16) | (g<<8) | (r);
        !           482:        }
        !           483: }
        !           484: 
        !           485: static inline void split_rgb444b (int rgb, int *r, int *g, int *b)
        !           486: {
        !           487:        *r = (rgb & 0xf00) >> 4;
        !           488:        *g = (rgb & 0xf0);
        !           489:        *b = (rgb & 0xf) << 4;
        !           490: }
        !           491: 
        !           492: static inline void split_rgb444i (unsigned int rgb, unsigned int *r, unsigned int *g, unsigned int *b)
        !           493: {
        !           494:        *r = (rgb & 0xf00) << 20;
        !           495:        *g = (rgb & 0xf0) << 24;
        !           496:        *b = (rgb & 0xf) << 28;
        !           497: }
        !           498: 
        !           499: static inline void read_m68k_vertex (int st_vptr, int output[3])
        !           500: {
        !           501:        output[0] = STMemory_ReadLong (st_vptr);
        !           502:        output[1] = STMemory_ReadLong (st_vptr+4);
        !           503:        output[2] = -STMemory_ReadLong (st_vptr+8);
        !           504: }
        !           505: 
        !           506: struct ZNode {
        !           507:        unsigned int z;
        !           508:        struct ZNode *less, *more;
        !           509:        void *data;
        !           510: };
        !           511: 
        !           512: #define MAX_OBJ_DATA   (2<<17)
        !           513: static unsigned char obj_data_area[MAX_OBJ_DATA];
        !           514: static int obj_data_pos;
        !           515: #define MAX_ZNODES     1000
        !           516: static struct ZNode znode_buf[MAX_ZNODES];
        !           517: static int znode_buf_pos;
        !           518: static struct ZNode *znode_start;
        !           519: static struct ZNode *znode_cur;
        !           520: 
        !           521: static inline void znode_databegin ()
        !           522: {
        !           523:        znode_cur->data = &obj_data_area[obj_data_pos];
        !           524: }
        !           525: 
        !           526: static inline void znode_wrlong (int val)
        !           527: {
        !           528:        *((int*)(obj_data_area+obj_data_pos)) = val;
        !           529:        obj_data_pos+=4;
        !           530: }
        !           531: static inline void znode_wrword (short val)
        !           532: {
        !           533:        *((short*)(obj_data_area+obj_data_pos)) = val;
        !           534:        obj_data_pos+=2;
        !           535: }
        !           536: static inline void znode_wrbyte (char val)
        !           537: {
        !           538:        *((char*)(obj_data_area+obj_data_pos)) = val;
        !           539:        obj_data_pos++;
        !           540: }
        !           541: 
        !           542: static inline void znode_wrnormal (p68K loc)
        !           543: {
        !           544:        znode_wrword (STMemory_ReadWord (loc));
        !           545:        znode_wrword (STMemory_ReadWord (loc+2));
        !           546:        znode_wrword (STMemory_ReadWord (loc+4));
        !           547: }
        !           548: 
        !           549: static void znode_wrmatrix (p68K loc)
        !           550: {
        !           551:        znode_wrword (STMemory_ReadWord (loc));
        !           552:        znode_wrword (STMemory_ReadWord (loc+2));
        !           553:        znode_wrword (STMemory_ReadWord (loc+4));
        !           554:        znode_wrword (STMemory_ReadWord (loc+6));
        !           555:        znode_wrword (STMemory_ReadWord (loc+8));
        !           556:        znode_wrword (STMemory_ReadWord (loc+10));
        !           557:        znode_wrword (STMemory_ReadWord (loc+12));
        !           558:        znode_wrword (STMemory_ReadWord (loc+14));
        !           559:        znode_wrword (STMemory_ReadWord (loc+16));
        !           560: }
        !           561: 
        !           562: static inline void znode_wrvertex (p68K loc)
        !           563: {
        !           564:        znode_wrlong (STMemory_ReadLong (loc));
        !           565:        znode_wrlong (STMemory_ReadLong (loc+4));
        !           566:        znode_wrlong (-STMemory_ReadLong (loc+8));
        !           567: }
        !           568: 
        !           569: static inline void znode_wrlightsource (p68K loc)
        !           570: {
        !           571:        znode_wrlong (-STMemory_ReadWord (loc));
        !           572:        znode_wrlong (-STMemory_ReadWord (loc+2));
        !           573:        znode_wrlong (STMemory_ReadWord (loc+4));
        !           574: }
        !           575: 
        !           576: static inline void znode_wrcolor (int rgb444col)
        !           577: {
        !           578:        int r,g,b;
        !           579:        split_rgb444b (rgb444col, &r, &g, &b);
        !           580:        znode_wrbyte (r);
        !           581:        znode_wrbyte (g);
        !           582:        znode_wrbyte (b);
        !           583:        znode_wrbyte (0);
        !           584: }
        !           585: 
        !           586: static inline int znode_rdlong (void **data)
        !           587: {
        !           588:        int val = *((int*)(*data));
        !           589:        (*data) += 4;
        !           590:        return val;
        !           591: }
        !           592: static inline short znode_rdword (void **data)
        !           593: {
        !           594:        short val = *((short*)(*data));
        !           595:        (*data) += 2;
        !           596:        return val;
        !           597: }
        !           598: static inline char znode_rdbyte (void **data)
        !           599: {
        !           600:        char val = *((char*)(*data));
        !           601:        (*data)++;
        !           602:        return val;
        !           603: }
        !           604: 
        !           605: static void znode_rdmatrix (void **data, GLfloat m[16])
        !           606: {
        !           607:        short val;
        !           608: 
        !           609: #define rdmatrixval(idx)       \
        !           610:        {       \
        !           611:                val = znode_rdword (data);      \
        !           612:                m[idx] = ((float)val)/-32768.0; \
        !           613:        }
        !           614:        
        !           615:        rdmatrixval (0);
        !           616:        rdmatrixval (1);
        !           617:        rdmatrixval (2);
        !           618:        m[3] = 0.0f;
        !           619:        rdmatrixval (4);
        !           620:        rdmatrixval (5);
        !           621:        rdmatrixval (6);
        !           622:        m[7] = 0.0f;
        !           623:        rdmatrixval (8);
        !           624:        rdmatrixval (9);
        !           625:        rdmatrixval (10);
        !           626:        m[11] = 0.0f;
        !           627:        m[12] = 0.0f;
        !           628:        m[13] = 0.0f;
        !           629:        m[14] = 0.0f;
        !           630:        m[15] = 1.0f;
        !           631: 
        !           632:        //m[0] = -m[0];
        !           633:        //m[5] = -m[5];
        !           634:        //m[10] = -m[10];
        !           635: }
        !           636: 
        !           637: static inline void znode_rdnormal (void **data, short normal[3])
        !           638: {
        !           639:        normal[0] = znode_rdword (data);
        !           640:        normal[1] = znode_rdword (data);
        !           641:        normal[2] = znode_rdword (data);
        !           642: }
        !           643: 
        !           644: static inline void znode_rdvertex (void **data, int vertex[3])
        !           645: {
        !           646:        vertex[0] = znode_rdlong (data);
        !           647:        vertex[1] = znode_rdlong (data);
        !           648:        vertex[2] = znode_rdlong (data);
        !           649: }
        !           650: 
        !           651: static inline void znode_rdvertexf (void **data, float vertex[3])
        !           652: {
        !           653:        vertex[0] = znode_rdlong (data);
        !           654:        vertex[1] = znode_rdlong (data);
        !           655:        vertex[2] = znode_rdlong (data);
        !           656: }
        !           657: 
        !           658: static inline void znode_rdvertexd (void **data, GLdouble vertex[3])
        !           659: {
        !           660:        vertex[0] = znode_rdlong (data);
        !           661:        vertex[1] = znode_rdlong (data);
        !           662:        vertex[2] = znode_rdlong (data);
        !           663: }
        !           664: 
        !           665: static inline void znode_rdcolorv (void **data, int *rgb)
        !           666: {
        !           667:        rgb[0] = (unsigned char) znode_rdbyte (data);
        !           668:        rgb[1] = (unsigned char) znode_rdbyte (data);
        !           669:        rgb[2] = (unsigned char) znode_rdbyte (data);
        !           670:        (*data)++;
        !           671: }
        !           672: 
        !           673: static inline void znode_rdcolor (void **data, int *r, int *g, int *b)
        !           674: {
        !           675:        *r = znode_rdbyte (data);
        !           676:        *g = znode_rdbyte (data);
        !           677:        *b = znode_rdbyte (data);
        !           678:        (*data)++;
        !           679: }
        !           680: 
        !           681: enum NuPrimitive {
        !           682:        NU_END,
        !           683:        NU_TRIANGLE,
        !           684:        NU_QUAD,
        !           685:        NU_LINE,
        !           686:        NU_BEZIER_LINE,
        !           687:        NU_TEARDROP,
        !           688:        NU_COMPLEX_SNEXT,
        !           689:        NU_COMPLEX_START,
        !           690:        NU_COMPLEX_END,
        !           691:        NU_COMPLEX_INNER,
        !           692:        NU_COMPLEX_BEZIER,
        !           693:        NU_TWINKLYCIRCLE,
        !           694:        NU_PLANET,
        !           695:        NU_CIRCLE,
        !           696:        NU_CYLINDER,
        !           697:        NU_BLOB,
        !           698:        NU_OVALTHINGY,
        !           699:        NU_POINT,
        !           700:        NU_MAX
        !           701: };
        !           702: 
        !           703: static inline void end_node ()
        !           704: {
        !           705:        znode_wrlong (0);
        !           706: }
        !           707: 
        !           708: static void add_node (struct ZNode **node, unsigned int zval)
        !           709: {
        !           710:        assert (znode_buf_pos < MAX_ZNODES);
        !           711:        /* end previous znode display list!!!!!!! */
        !           712:        if (znode_cur) end_node ();
        !           713:        
        !           714:        *node = znode_cur = &znode_buf[znode_buf_pos++];
        !           715:        znode_cur->z = zval;
        !           716:        znode_cur->less = NULL;
        !           717:        znode_cur->more = NULL;
        !           718:        znode_databegin ();
        !           719: }
        !           720: 
        !           721: static void znode_insert (struct ZNode *node, unsigned int zval)
        !           722: {
        !           723:        if (zval > node->z) {
        !           724:                if (node->more) {
        !           725:                        znode_insert (node->more, zval);
        !           726:                } else {
        !           727:                        add_node (&node->more, zval);
        !           728:                }
        !           729:        } else {
        !           730:                if (node->less) {
        !           731:                        znode_insert (node->less, zval);
        !           732:                } else {
        !           733:                        add_node (&node->less, zval);
        !           734:                }
        !           735:        }
        !           736: }
        !           737: 
        !           738: static bool no_znodes_kthx;
        !           739: 
        !           740: void Nu_InsertZNode ()
        !           741: {
        !           742:        unsigned int zval = GetReg (4);
        !           743:        if (use_renderer == R_OLD) return;
        !           744:        if (no_znodes_kthx) return;
        !           745:        if (znode_start == NULL) {
        !           746:                add_node (&znode_start, zval);
        !           747:        } else {
        !           748:                znode_insert (znode_start, zval);
        !           749:        }
        !           750: }
        !           751: 
        !           752: void Nu_3DViewInit ()
        !           753: {
        !           754:        queued_string_pos = 0;
        !           755:        //printf ("3dviewinit()\n");
        !           756:        znode_buf_pos = 0;
        !           757:        //printf ("%d bytes object data\n", obj_data_pos);
        !           758:        obj_data_pos = 0;
        !           759: 
        !           760:        //add_node (&znode_start, 0);
        !           761:        znode_start = NULL;
        !           762:        znode_cur = NULL;
        !           763: }
        !           764: 
        !           765: static void lighting_on (float light_vec[4], int rgb444_light_col, int rgb444_extra_col, int rgb444_obj_col)
        !           766: {
        !           767:        bool do_not_light;
        !           768:        unsigned int extra_col[4], obj_col[4], light_col[4];
        !           769: 
        !           770:        do_not_light = rgb444_obj_col & (1<<8);
        !           771:        
        !           772:        /* object color bit 0x8 set means DO NOT LIGHT */
        !           773:        if (do_not_light) {
        !           774:                rgb444_obj_col ^= (1<<8);
        !           775:        } else {
        !           776:                split_rgb444i (rgb444_light_col, &light_col[0], &light_col[1], &light_col[2]);
        !           777:                light_col[3] = 0;
        !           778:                light_vec[3] = 0.0f;
        !           779:        }
        !           780: 
        !           781:        if (rgb444_obj_col & (1<<4)) {
        !           782:                rgb444_obj_col ^= (1<<4);
        !           783:                split_rgb444i (rgb444_obj_col, &obj_col[0], &obj_col[1], &obj_col[2]);
        !           784:                split_rgb444i (rgb444_extra_col, &extra_col[0], &extra_col[1], &extra_col[2]);
        !           785:                obj_col[0] += extra_col[0];
        !           786:                obj_col[1] += extra_col[1];
        !           787:                obj_col[2] += extra_col[2];
        !           788:        } else {
        !           789:                split_rgb444i (rgb444_obj_col, &obj_col[0], &obj_col[1], &obj_col[2]);
        !           790:        }
        !           791:        obj_col[3] = 0;
        !           792: 
        !           793:        if (do_not_light) {
        !           794:                glDisable (GL_LIGHTING);
        !           795:                glDisable (GL_LIGHT0);
        !           796:                glColor3ui (obj_col[0], obj_col[1], obj_col[2]);
        !           797:        } else {
        !           798:                glLightfv (GL_LIGHT0, GL_POSITION, light_vec);
        !           799:                glLightiv (GL_LIGHT0, GL_DIFFUSE, light_col);
        !           800:                glLightiv (GL_LIGHT0, GL_AMBIENT, obj_col);
        !           801:                glEnable (GL_LIGHTING);
        !           802:                glEnable (GL_LIGHT0);
        !           803:        }
        !           804: }
        !           805: 
        !           806: static void lighting_off ()
        !           807: {
        !           808:        glDisable (GL_LIGHTING);
        !           809:        glDisable (GL_LIGHT0);
        !           810: }
        !           811: 
        !           812: void CALLBACK beginCallback(GLenum which)
        !           813: {
        !           814:    glBegin(which);
        !           815: }
        !           816: 
        !           817: void CALLBACK errorCallback(GLenum errorCode)
        !           818: {
        !           819:    const GLubyte *estring;
        !           820: 
        !           821:    estring = gluErrorString(errorCode);
        !           822:    fprintf(stderr, "Tessellation Error: %s\n", estring);
        !           823: }
        !           824: 
        !           825: void CALLBACK endCallback(void)
        !           826: {
        !           827:    glEnd();
        !           828: }
        !           829: 
        !           830: static int complex_col[3];
        !           831: void CALLBACK vertexCallback(GLvoid *vertex, GLvoid *poly_data)
        !           832: {
        !           833:    const GLdouble *pointer;
        !           834: 
        !           835:    pointer = (GLdouble *) vertex;
        !           836:    glColor3ub (complex_col[0], complex_col[1], complex_col[2]);
        !           837:    glVertex3dv(pointer);
        !           838: }
        !           839: /*  combineCallback is used to create a new vertex when edges
        !           840:  *  intersect.  coordinate location is trivial to calculate,
        !           841:  *  but weight[4] may be used to average color, normal, or texture
        !           842:  *  coordinate data.  In this program, color is weighted.
        !           843:  */
        !           844: void CALLBACK combineCallback(GLdouble coords[3], 
        !           845:                      GLdouble *vertex_data[4],
        !           846:                      GLfloat weight[4], GLdouble **dataOut )
        !           847: {
        !           848:    GLdouble vertex[6];
        !           849: 
        !           850:    //vertex = (GLdouble *) malloc(6 * sizeof(GLdouble));
        !           851: 
        !           852:    vertex[0] = coords[0];
        !           853:    vertex[1] = coords[1];
        !           854:    vertex[2] = coords[2];
        !           855:    *dataOut = vertex;
        !           856: }
        !           857: #define MAX_TESS_VERTICES      400
        !           858: static GLdouble tess_vertices[MAX_TESS_VERTICES][3];
        !           859: static int tess_vpos;
        !           860: 
        !           861: static bool do_start_complex;
        !           862: static int complex_col_rgb444;
        !           863: 
        !           864: static void put_complex_start_4real ()
        !           865: {
        !           866:        znode_wrlong (NU_COMPLEX_START);
        !           867:        znode_wrcolor (complex_col_rgb444);
        !           868:        no_znodes_kthx = TRUE;
        !           869: }
        !           870: 
        !           871: void Nu_ComplexSNext ()
        !           872: {
        !           873:        if (use_renderer == R_OLD) return;
        !           874:        if (do_start_complex) { put_complex_start_4real (); do_start_complex = FALSE; }
        !           875:        znode_wrlong (NU_COMPLEX_SNEXT);
        !           876:        znode_wrvertex (GetReg (REG_A0)+4);
        !           877: }
        !           878: void Nu_DrawComplexSNext (void **data)
        !           879: {
        !           880:        if (use_renderer == R_GLWIRE) {
        !           881:                znode_rdvertexd (data, tess_vertices[tess_vpos]);
        !           882:                glVertex3dv (tess_vertices[tess_vpos++]);
        !           883:        } else {
        !           884:                assert (tess_vpos < MAX_TESS_VERTICES);
        !           885:                znode_rdvertexd (data, tess_vertices[tess_vpos]);
        !           886:                gluTessVertex (tobj, tess_vertices[tess_vpos], tess_vertices[tess_vpos]);
        !           887:                tess_vpos++;
        !           888:        }
        !           889: }
        !           890: void Nu_ComplexSBegin ()
        !           891: {
        !           892:        Nu_ComplexSNext ();
        !           893: }
        !           894: 
        !           895: void Nu_ComplexStart ()
        !           896: {
        !           897:        if (use_renderer == R_OLD) return;
        !           898:        do_start_complex = TRUE;
        !           899:        complex_col_rgb444 = GetReg (REG_D6);
        !           900: }
        !           901: void Nu_DrawComplexStart (void **data)
        !           902: {
        !           903:        tess_vpos = 0;
        !           904:        
        !           905:        if (use_renderer == R_GL) {
        !           906:                gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
        !           907:                gluTessBeginPolygon (tobj, NULL);
        !           908:                gluTessBeginContour (tobj);
        !           909:        } else {
        !           910:                glBegin (GL_LINE_STRIP);
        !           911:        }
        !           912:        znode_rdcolor (data, &complex_col[0], &complex_col[1], &complex_col[2]);
        !           913:        glColor3ub (complex_col[0], complex_col[1], complex_col[2]);
        !           914: }
        !           915: 
        !           916: 
        !           917: void Nu_ComplexEnd ()
        !           918: {
        !           919:        if (use_renderer == R_OLD) return;
        !           920:        if (do_start_complex) { put_complex_start_4real (); do_start_complex = FALSE; }
        !           921:        znode_wrlong (NU_COMPLEX_END);
        !           922:        do_start_complex = FALSE;
        !           923:        no_znodes_kthx = FALSE;
        !           924: }
        !           925: void Nu_DrawComplexEnd (void **data)
        !           926: {
        !           927:        if (use_renderer == R_GL) {
        !           928:                gluTessEndContour (tobj);
        !           929:                gluTessEndPolygon (tobj);
        !           930:        } else if (use_renderer == R_GLWIRE) {
        !           931:                glVertex3dv (tess_vertices[0]);
        !           932:                glEnd ();
        !           933:        }
        !           934: }
        !           935: 
        !           936: void Nu_ComplexStartInner ()
        !           937: {
        !           938:        if (use_renderer == R_OLD) return;
        !           939:        if (do_start_complex) { put_complex_start_4real (); do_start_complex = FALSE; }
        !           940:        znode_wrlong (NU_COMPLEX_INNER);
        !           941: }
        !           942: void Nu_DrawComplexStartInner (void **data)
        !           943: {
        !           944:        if (use_renderer == R_GL) {
        !           945:                gluTessEndContour (tobj);
        !           946:                gluTessBeginContour (tobj);
        !           947:        } else if (use_renderer == R_GLWIRE) {
        !           948:                glEnd ();
        !           949:                glBegin (GL_LINE_STRIP);
        !           950:                tess_vpos = 0;
        !           951:        }
        !           952: }
        !           953: 
        !           954: #define BEZIER_STEPS   10
        !           955: static void eval_bezier (GLdouble *out, float _t, float ctrlpoints[4][3])
        !           956: {
        !           957:        float a,b,c,d,t2;
        !           958:        t2 = _t*_t;
        !           959:        c = 1.0f-_t;
        !           960:        d = t2*_t;
        !           961:        b = c*c;
        !           962:        a = b*c;
        !           963:        b = b*_t*3.0f;
        !           964:        c = c*3.0f*t2;
        !           965:        /* x */ 
        !           966:        out[0] =
        !           967:            ctrlpoints[0][0] * a +
        !           968:            ctrlpoints[1][0] * b +
        !           969:            ctrlpoints[2][0] * c +
        !           970:            ctrlpoints[3][0] * d;
        !           971:        /* y */ 
        !           972:        out[1] =
        !           973:            ctrlpoints[0][1] * a +
        !           974:            ctrlpoints[1][1] * b +
        !           975:            ctrlpoints[2][1] * c +
        !           976:            ctrlpoints[3][1] * d;
        !           977:        /* y */ 
        !           978:        out[2] =
        !           979:            ctrlpoints[0][2] * a +
        !           980:            ctrlpoints[1][2] * b +
        !           981:            ctrlpoints[2][2] * c +
        !           982:            ctrlpoints[3][2] * d;
        !           983: }
        !           984: 
        !           985: void Nu_ComplexBezier ()
        !           986: {
        !           987:        if (use_renderer == R_OLD) return;
        !           988:        if (do_start_complex) { put_complex_start_4real (); do_start_complex = FALSE; }
        !           989:        znode_wrlong (NU_COMPLEX_BEZIER);
        !           990:        znode_wrvertex (GetReg (REG_A0)+4);
        !           991:        znode_wrvertex (GetReg (REG_A1)+4);
        !           992:        znode_wrvertex (GetReg (REG_A2)+4);
        !           993:        znode_wrvertex (GetReg (REG_A3)+4);
        !           994: }
        !           995: void Nu_DrawComplexBezier (void **data)
        !           996: {
        !           997:        int i, bezier_steps;
        !           998:        float delta;
        !           999:        double v[3];
        !          1000:        GLfloat ctrlpoints[4][3];
        !          1001:        
        !          1002:        znode_rdvertexf (data, ctrlpoints[0]);
        !          1003:        znode_rdvertexf (data, ctrlpoints[1]);
        !          1004:        znode_rdvertexf (data, ctrlpoints[2]);
        !          1005:        znode_rdvertexf (data, ctrlpoints[3]);
        !          1006:        
        !          1007:        /*float poo = MAX (abs (ctrlpoints[0][0]-ctrlpoints[3][0]),
        !          1008:                         abs (ctrlpoints[0][1]-ctrlpoints[3][1]));
        !          1009:        poo /= MIN (ctrlpoints[0][2], ctrlpoints[3][2]);
        !          1010:        bezier_steps = MIN (6 - 20*poo, 16);*/
        !          1011:        //printf ("%d ", bezier_steps);
        !          1012:        bezier_steps = 10;
        !          1013:        
        !          1014:        assert (tess_vpos + bezier_steps < MAX_TESS_VERTICES);
        !          1015:        delta = 1.0f/bezier_steps;
        !          1016: 
        !          1017:        if (use_renderer == R_GLWIRE) {
        !          1018:                tess_vertices[tess_vpos][0] = ctrlpoints[0][0];
        !          1019:                tess_vertices[tess_vpos][1] = ctrlpoints[0][1];
        !          1020:                tess_vertices[tess_vpos++][2] = ctrlpoints[0][2];
        !          1021:                for (i=0; i<=bezier_steps; i++) {
        !          1022:                        eval_bezier (v, i*delta, ctrlpoints);
        !          1023:                        glVertex3dv (v);
        !          1024:                }
        !          1025:                return;
        !          1026:        }
        !          1027:        /* the tessellator prefers it :-) */
        !          1028:        eval_bezier (&tess_vertices[tess_vpos][0], 0.001, ctrlpoints);
        !          1029:        gluTessVertex (tobj, tess_vertices[tess_vpos], tess_vertices[tess_vpos]);
        !          1030:        tess_vpos++;
        !          1031:        
        !          1032:        for (i=1; i<bezier_steps; i++) {
        !          1033:                eval_bezier (&tess_vertices[tess_vpos][0], i*delta, ctrlpoints);
        !          1034:                gluTessVertex (tobj, tess_vertices[tess_vpos], tess_vertices[tess_vpos]);
        !          1035:                tess_vpos++;
        !          1036:        }
        !          1037:        eval_bezier (&tess_vertices[tess_vpos][0], 0.999, ctrlpoints);
        !          1038:        gluTessVertex (tobj, tess_vertices[tess_vpos], tess_vertices[tess_vpos]);
        !          1039:        tess_vpos++;
        !          1040: }
        !          1041: 
        !          1042: 
        !          1043: /* For engines and industry chimney flares.
        !          1044:  * This is a bit crap, as you will see by panning around the effect. */
        !          1045: void Nu_PutTeardrop ()
        !          1046: {
        !          1047:        if (use_renderer == R_OLD) return;
        !          1048:        znode_wrlong (NU_TEARDROP);
        !          1049:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1050:        znode_wrvertex (GetReg (REG_A1)+4);
        !          1051:        znode_wrcolor (GetReg (REG_D6));
        !          1052: }
        !          1053: void Nu_DrawTeardrop (void **data)
        !          1054: {
        !          1055:        int i;
        !          1056:        float delta;
        !          1057:        GLfloat ctrlpoints[4][3];
        !          1058:        GLfloat dir[3], ppd[3];
        !          1059:        GLdouble out[3];
        !          1060:        int r, g, b;
        !          1061: 
        !          1062: #define TD_STRETCH     1.3333333333
        !          1063: #define TD_BROADEN     0.33
        !          1064: #define TD_BEZIER_STEPS        40
        !          1065:        
        !          1066:        if (use_renderer == R_OLD) return;
        !          1067:        znode_rdvertexf (data, dir);
        !          1068:        znode_rdvertexf (data, ctrlpoints[0]);
        !          1069:        znode_rdcolor (data, &r, &g, &b);
        !          1070:        
        !          1071:        dir[0] -= ctrlpoints[0][0];
        !          1072:        dir[1] -= ctrlpoints[0][1];
        !          1073:        dir[2] -= ctrlpoints[0][2];
        !          1074:        
        !          1075:        ppd[0] = -dir[1];
        !          1076:        ppd[1] = dir[0];
        !          1077:        ppd[2] = dir[2];
        !          1078: 
        !          1079:        //h = sqrt (dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
        !          1080:        
        !          1081:        ctrlpoints[1][0] = ctrlpoints[0][0] + TD_STRETCH*dir[0] + TD_BROADEN*ppd[0];
        !          1082:        ctrlpoints[1][1] = ctrlpoints[0][1] + TD_STRETCH*dir[1] + TD_BROADEN*ppd[1];
        !          1083:        ctrlpoints[1][2] = ctrlpoints[0][2] + dir[2];
        !          1084:        
        !          1085:        ctrlpoints[2][0] = ctrlpoints[0][0] + TD_STRETCH*dir[0] - TD_BROADEN*ppd[0];
        !          1086:        ctrlpoints[2][1] = ctrlpoints[0][1] + TD_STRETCH*dir[1] - TD_BROADEN*ppd[1];
        !          1087:        ctrlpoints[2][2] = ctrlpoints[0][2] + dir[2];
        !          1088:        
        !          1089:        ctrlpoints[3][0] = ctrlpoints[0][0];
        !          1090:        ctrlpoints[3][1] = ctrlpoints[0][1];
        !          1091:        ctrlpoints[3][2] = ctrlpoints[0][2];
        !          1092: 
        !          1093:        delta = 1.0f/TD_BEZIER_STEPS;
        !          1094:        glColor3ub (r, g, b);
        !          1095:        glBegin (GL_TRIANGLE_FAN);
        !          1096:        /* the tessellator prefers it :-) */
        !          1097:        for (i=0; i<=TD_BEZIER_STEPS; i++) {
        !          1098:                eval_bezier (out, i*delta, ctrlpoints);
        !          1099:                glVertex3dv (out);
        !          1100:        }
        !          1101:        glEnd ();
        !          1102: }
        !          1103: 
        !          1104: 
        !          1105: void Nu_PutBezierLine ()
        !          1106: {
        !          1107:        if (use_renderer == R_OLD) return;
        !          1108:        znode_wrlong (NU_BEZIER_LINE);
        !          1109:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1110:        znode_wrvertex (GetReg (REG_A1)+4);
        !          1111:        znode_wrvertex (GetReg (REG_A2)+4);
        !          1112:        znode_wrvertex (GetReg (REG_A3)+4);
        !          1113:        znode_wrcolor (GetReg (REG_D6));
        !          1114: }
        !          1115: void Nu_DrawBezierLine (void **data)
        !          1116: {
        !          1117:        int i, r, g, b;
        !          1118:        GLfloat ctrlpoints[4][3];
        !          1119:        GLfloat delta;
        !          1120:        GLdouble out[3];
        !          1121: 
        !          1122:        znode_rdvertexf (data, ctrlpoints[0]);
        !          1123:        znode_rdvertexf (data, ctrlpoints[1]);
        !          1124:        znode_rdvertexf (data, ctrlpoints[2]);
        !          1125:        znode_rdvertexf (data, ctrlpoints[3]);
        !          1126:        znode_rdcolor (data, &r, &g, &b);
        !          1127:        
        !          1128:        delta = 1.0f/20;
        !          1129:        glColor3ub (r, g, b);
        !          1130:        glBegin (GL_LINE_STRIP);
        !          1131:        for (i=0; i<=20; i++) {
        !          1132:                eval_bezier (out, i*delta, ctrlpoints);
        !          1133:                glVertex3dv (out);
        !          1134:        }
        !          1135:        glEnd ();
        !          1136: }
        !          1137: 
        !          1138: void Nu_PutTriangle ()
        !          1139: {
        !          1140:        if (use_renderer == R_OLD) return;
        !          1141:        znode_wrlong (NU_TRIANGLE);
        !          1142:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1143:        znode_wrvertex (GetReg (REG_A1)+4);
        !          1144:        znode_wrvertex (GetReg (REG_A2)+4);
        !          1145:        znode_wrcolor (GetReg (REG_D6));
        !          1146: }
        !          1147: void Nu_DrawTriangle (void **data)
        !          1148: {
        !          1149:        float v1[3], v2[3], v3[3];
        !          1150:        int rgb[3];
        !          1151:        
        !          1152:        znode_rdvertexf (data, v1);
        !          1153:        znode_rdvertexf (data, v2);
        !          1154:        znode_rdvertexf (data, v3);
        !          1155:        znode_rdcolorv (data, rgb);
        !          1156:        glColor3ub (rgb[0], rgb[1], rgb[2]);
        !          1157:        if (use_renderer == R_GLWIRE) {
        !          1158:                glBegin (GL_LINE_STRIP);
        !          1159:                        glVertex3fv (v1);
        !          1160:                        glVertex3fv (v2);
        !          1161:                        glVertex3fv (v3);
        !          1162:                        glVertex3fv (v1);
        !          1163:                glEnd ();
        !          1164:        } else {
        !          1165:                glBegin (GL_TRIANGLES);
        !          1166:                        glVertex3fv (v1);
        !          1167:                        glVertex3fv (v2);
        !          1168:                        glVertex3fv (v3);
        !          1169:                glEnd ();
        !          1170:        }
        !          1171: }
        !          1172: 
        !          1173: void Nu_PutQuad ()
        !          1174: {
        !          1175:        if (use_renderer == R_OLD) return;
        !          1176:        znode_wrlong (NU_QUAD);
        !          1177:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1178:        znode_wrvertex (GetReg (REG_A1)+4);
        !          1179:        znode_wrvertex (GetReg (REG_A2)+4);
        !          1180:        znode_wrvertex (GetReg (REG_A3)+4);
        !          1181:        znode_wrcolor (GetReg (REG_D6));
        !          1182: }
        !          1183: void Nu_DrawQuad (void **data)
        !          1184: {
        !          1185:        int v1[3], v2[3], v3[3], v4[3];
        !          1186:        int r, g, b;
        !          1187:        
        !          1188:        znode_rdvertex (data, v1);
        !          1189:        znode_rdvertex (data, v2);
        !          1190:        znode_rdvertex (data, v3);
        !          1191:        znode_rdvertex (data, v4);
        !          1192:        znode_rdcolor (data, &r, &g, &b);
        !          1193:        
        !          1194:        glColor3ub (r, g, b);
        !          1195:        if (use_renderer == R_GLWIRE) {
        !          1196:                glBegin (GL_LINE_STRIP);
        !          1197:                        glVertex3iv (v1);
        !          1198:                        glVertex3iv (v2);
        !          1199:                        glVertex3iv (v3);
        !          1200:                        glVertex3iv (v4);
        !          1201:                        glVertex3iv (v1);
        !          1202:                glEnd ();
        !          1203:        } else {
        !          1204:                glBegin (GL_TRIANGLE_STRIP);
        !          1205:                        glVertex3iv (v1);
        !          1206:                        glVertex3iv (v2);
        !          1207:                        glVertex3iv (v4);
        !          1208:                        glVertex3iv (v3);
        !          1209:                glEnd ();
        !          1210:        }
        !          1211: }
        !          1212: void Nu_PutTwinklyCircle ()
        !          1213: {
        !          1214:        if (use_renderer == R_OLD) return;
        !          1215:        znode_wrlong (NU_TWINKLYCIRCLE);
        !          1216:        znode_wrlong (GetReg (REG_D2));
        !          1217:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1218:        znode_wrcolor (GetReg (REG_D6));
        !          1219: }
        !          1220: void Nu_DrawTwinklyCircle (void **data)
        !          1221: {
        !          1222:        int v1[3];
        !          1223:        unsigned int dreg2, isize;
        !          1224:        float size;
        !          1225:        int r, g, b;
        !          1226: 
        !          1227:        dreg2 = znode_rdlong (data);
        !          1228:        znode_rdvertex (data, v1);
        !          1229:        znode_rdcolor (data, &r, &g, &b);
        !          1230:        
        !          1231:        glColor3ub (r, g, b);
        !          1232: 
        !          1233:        isize = (dreg2 << 16) | (dreg2 >> 16);
        !          1234:        //printf ("%x (%x)\n", GetReg (2), isize);
        !          1235:        
        !          1236:        size = -0.002*((short)dreg2)*v1[2];
        !          1237:        
        !          1238:        glPushMatrix ();
        !          1239:        glTranslatef (v1[0], v1[1], v1[2]);
        !          1240:        
        !          1241:        if (size > 0.0f) gluDisk (qobj, 0.0, size, 32, 1);
        !          1242:        
        !          1243:        size = -0.002*((short) dreg2)*v1[2] - 0.016*v1[2];
        !          1244:        
        !          1245:        //printf ("Size %.2f\n", size);
        !          1246:        if (size > 0.0f) {
        !          1247:                glBegin (GL_LINES);
        !          1248:                        glVertex3f (-size, 0.0f, 0.0f);
        !          1249:                        glVertex3f (+size, 0.0f, 0.0f);
        !          1250:                        glVertex3f (0.0f, -size, 0.0f);
        !          1251:                        glVertex3f (0.0f, +size, 0.0f);
        !          1252:                glEnd ();
        !          1253:        }
        !          1254:        glPopMatrix ();
        !          1255: }
        !          1256: 
        !          1257: #define NUS_X  0.525731112119133606
        !          1258: #define NUS_Z  0.850650808352039932
        !          1259: 
        !          1260: static float nus_vdata[12][3] = {
        !          1261:        {-NUS_X, 0.0, NUS_Z}, {NUS_X, 0.0, NUS_Z}, {-NUS_X, 0.0, -NUS_Z}, {NUS_X, 0.0, -NUS_Z},
        !          1262:        {0.0, NUS_Z, NUS_X}, {0.0, NUS_Z, -NUS_X}, {0.0, -NUS_Z, NUS_X}, {0.0, -NUS_Z, -NUS_X},
        !          1263:        {NUS_Z, NUS_X, 0.0}, {-NUS_Z, NUS_X, 0.0}, {NUS_Z, -NUS_X, 0.0}, {-NUS_Z, -NUS_X, 0.0}
        !          1264: };
        !          1265: 
        !          1266: static int nus_tindices[20][3] = {
        !          1267:        {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
        !          1268:        {8,10,1}, {8,3,10},{5,3,8}, {5,2,3}, {2,7,3},
        !          1269:        {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
        !          1270:        {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
        !          1271: };
        !          1272: 
        !          1273: static void Normalise (float v[3])
        !          1274: {
        !          1275:        float d = sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
        !          1276:        d = 1.0f / d;
        !          1277:        v[0] *= d;
        !          1278:        v[1] *= d;
        !          1279:        v[2] *= d;
        !          1280: }
        !          1281: 
        !          1282: static void nuSubdivide (float v1[3], float v2[3], float v3[3], int depth)
        !          1283: {
        !          1284:        float v12[3], v23[3], v31[3];
        !          1285:        int i;
        !          1286: 
        !          1287:        if (depth == 0) {
        !          1288:                glBegin (GL_POLYGON);
        !          1289:                        glNormal3fv (v1); glVertex3fv (v1);
        !          1290:                        glNormal3fv (v2); glVertex3fv (v2);
        !          1291:                        glNormal3fv (v3); glVertex3fv (v3);
        !          1292:                glEnd ();
        !          1293:                return;
        !          1294:        }
        !          1295: 
        !          1296:        for (i=0; i<3; i++) {
        !          1297:                v12[i] = v1[i]+v2[i];
        !          1298:                v23[i] = v2[i]+v3[i];
        !          1299:                v31[i] = v3[i]+v1[i];
        !          1300:        }
        !          1301:        Normalise (v12);
        !          1302:        Normalise (v23);
        !          1303:        Normalise (v31);
        !          1304:        nuSubdivide(v1, v12, v31, depth-1);
        !          1305:        nuSubdivide(v2, v23, v12, depth-1);
        !          1306:        nuSubdivide(v3, v31, v23, depth-1);
        !          1307:        nuSubdivide(v12, v23, v31, depth-1);
        !          1308: }
        !          1309: 
        !          1310: /*
        !          1311: static void NormCrossProd (float v1[3], float v2[3], float vout[3])
        !          1312: {
        !          1313:        vout[0] = v1[1]*v2[2] - v1[2]*v2[1];
        !          1314:        vout[1] = v1[2]*v2[0] - v1[0]*v2[2];
        !          1315:        vout[2] = v1[0]*v2[1] - v1[1]*v2[0];
        !          1316:        Normalise (vout);
        !          1317: }*/
        !          1318: 
        !          1319: #define NUSPHERE_SUBDIVS       4
        !          1320: 
        !          1321: void nuSphere (float size)
        !          1322: {
        !          1323:        int i;
        !          1324:        glScalef (size, size, size);
        !          1325:        for (i=0; i<20; i++) {
        !          1326:                nuSubdivide (nus_vdata[nus_tindices[i][0]],
        !          1327:                                nus_vdata[nus_tindices[i][1]],
        !          1328:                                nus_vdata[nus_tindices[i][2]],
        !          1329:                                NUSPHERE_SUBDIVS);
        !          1330:        }
        !          1331: }
        !          1332: 
        !          1333: /* not finished by a long shot */
        !          1334: void Nu_PutPlanet ()
        !          1335: {
        !          1336:        if (use_renderer == R_OLD) return;
        !          1337:        
        !          1338:        /*{
        !          1339:                int cunt, i;
        !          1340:                cunt = GetReg (REG_A6);
        !          1341:                cunt -= 36;
        !          1342:                printf ("Cuntrix:");
        !          1343:                for (i=0; i<9; i++) {
        !          1344:                        if (((i)%3) == 0) printf ("\n");
        !          1345:                        printf ("%04hx ", STMemory_ReadWord (cunt));
        !          1346:                        cunt += 2;
        !          1347:                }
        !          1348:                printf ("\n");
        !          1349:        }*/
        !          1350:        
        !          1351:        znode_wrlong (NU_PLANET);
        !          1352:        znode_wrlong (GetReg (REG_D6));
        !          1353:        znode_wrlong (GetReg (REG_D1));
        !          1354:        znode_wrlong (GetReg (REG_D0));
        !          1355:        /* lighting vector */
        !          1356:        znode_wrlightsource (GetReg (REG_A1));
        !          1357:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1358:        znode_wrmatrix (GetReg (REG_A6)-36);
        !          1359: }
        !          1360: void Nu_DrawPlanet (void **data)
        !          1361: {
        !          1362:        int v1[3];
        !          1363:        int size;
        !          1364:        float light_vec[4];
        !          1365:        GLfloat rot_matrix[16];
        !          1366:        unsigned int obj_col[4], light_col[4];
        !          1367: 
        !          1368:        /*obj_col[0] = 1000000000;
        !          1369:        obj_col[1] = 1000000000;
        !          1370:        obj_col[2] = 1000000000;
        !          1371:        obj_col[3] = 0;*/
        !          1372:        split_rgb444i (znode_rdlong (data), &obj_col[0], &obj_col[1], &obj_col[2]);
        !          1373:        obj_col[3] = 0;
        !          1374:        split_rgb444i (znode_rdlong (data), &light_col[0], &light_col[1], &light_col[2]);
        !          1375:        light_col[3] = 0;
        !          1376: 
        !          1377:        size = znode_rdlong (data);
        !          1378:        
        !          1379:        znode_rdvertexf (data, light_vec);
        !          1380:        light_vec[3] = 0.0f;
        !          1381:        
        !          1382:        glLightfv (GL_LIGHT1, GL_POSITION, light_vec);
        !          1383: 
        !          1384:        glLightiv (GL_LIGHT1, GL_DIFFUSE, light_col);
        !          1385:        glLightiv (GL_LIGHT1, GL_AMBIENT, obj_col);
        !          1386: 
        !          1387: //     glMaterialiv (GL_FRONT, GL_AMBIENT, obj_col);
        !          1388:        glEnable (GL_LIGHTING);
        !          1389:        glEnable (GL_LIGHT1);
        !          1390:        glEnable (GL_NORMALIZE);
        !          1391:        
        !          1392:        glShadeModel (GL_SMOOTH);
        !          1393: //     glColor3uiv (obj_col);
        !          1394:        znode_rdvertex (data, v1);
        !          1395:        znode_rdmatrix (data, rot_matrix);
        !          1396: 
        !          1397:        //printf ("planet size %d, pos (%d,%d,%d)\n", size,v1[0],v1[1],v1[2]);
        !          1398:        
        !          1399:        glPushMatrix ();
        !          1400:        glTranslatef (v1[0], v1[1], v1[2]);
        !          1401:        glRotatef (180.0f, 1, 0, 0);
        !          1402:        glRotatef (180.0f, 0, 1, 0);
        !          1403:        glMultMatrixf (rot_matrix);
        !          1404:        glCullFace (GL_BACK);
        !          1405:        glEnable (GL_CULL_FACE);
        !          1406:        /* why the fucking fudge factor?? */
        !          1407:        nuSphere (size*1.0080);
        !          1408:        //gluSphere (qobj, size, 100, 100);
        !          1409:        glDisable (GL_CULL_FACE);
        !          1410:        glPopMatrix ();
        !          1411:        
        !          1412:        glDisable (GL_NORMALIZE);
        !          1413:        glDisable (GL_LIGHTING);
        !          1414:        glDisable (GL_LIGHT1);
        !          1415: }
        !          1416: 
        !          1417: void Nu_PutCircle ()
        !          1418: {
        !          1419:        if (use_renderer == R_OLD) return;
        !          1420:        znode_wrlong (NU_CIRCLE);
        !          1421:        znode_wrlong (GetReg (REG_D2));
        !          1422:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1423:        znode_wrcolor (GetReg (REG_D6));
        !          1424: }
        !          1425: void Nu_DrawCircle (void **data)
        !          1426: {
        !          1427:        int v1[3];
        !          1428:        unsigned int dreg2, isize;
        !          1429:        float size;
        !          1430:        int r, g, b;
        !          1431: 
        !          1432:        dreg2 = znode_rdlong (data);
        !          1433:        znode_rdvertex (data, v1);
        !          1434:        znode_rdcolor (data, &r, &g, &b);
        !          1435:        
        !          1436:        glColor3ub (r, g, b);
        !          1437: 
        !          1438:        isize = (dreg2 << 16) | (dreg2 >> 16);
        !          1439:        //printf ("%x (%x)\n", GetReg (2), isize);
        !          1440:        
        !          1441:        size = -0.002*((short)dreg2)*v1[2];
        !          1442:        
        !          1443:        glPushMatrix ();
        !          1444:        glTranslatef (v1[0], v1[1], v1[2]);
        !          1445:        gluDisk (qobj, 0.0, size, 32, 1);
        !          1446:        glPopMatrix ();
        !          1447: }
        !          1448: 
        !          1449: /* life is so strange */
        !          1450: void Nu_PutCylinder ()
        !          1451: {
        !          1452:        if (use_renderer == R_OLD) return;
        !          1453:        znode_wrlong (NU_CYLINDER);
        !          1454:        znode_wrlightsource (GetReg (REG_A4));
        !          1455:        znode_wrlong (GetReg (REG_D3));
        !          1456:        znode_wrlong (GetReg (REG_D2));
        !          1457:        znode_wrlong (GetReg (REG_D6));
        !          1458:        znode_wrvertex (GetReg (REG_A2)+4);
        !          1459:        znode_wrvertex (GetReg (REG_A3)+4);
        !          1460:        znode_wrlong (GetReg (REG_D0));
        !          1461:        znode_wrlong (GetReg (REG_D1));
        !          1462:        znode_wrlong (GetReg (REG_D5));
        !          1463:        znode_wrlong (GetReg (REG_D4));
        !          1464: }
        !          1465: void Nu_DrawCylinder (void **data)
        !          1466: {
        !          1467:        float light_vec[4];
        !          1468:        int v1[3], v2[3];
        !          1469:        float vdiff[3];
        !          1470:        int rad1, rad2;
        !          1471:        int light_col, obj_col, extra_col;
        !          1472:        float h;
        !          1473: 
        !          1474:        znode_rdvertexf (data, light_vec);
        !          1475:        light_col = znode_rdlong (data);
        !          1476:        obj_col = znode_rdlong (data);
        !          1477:        extra_col = znode_rdlong (data);
        !          1478: 
        !          1479:        znode_rdvertex (data, v1);
        !          1480:        znode_rdvertex (data, v2);
        !          1481: 
        !          1482:        vdiff[0] = v2[0] - v1[0];
        !          1483:        vdiff[1] = v2[1] - v1[1];
        !          1484:        vdiff[2] = v2[2] - v1[2];
        !          1485:        
        !          1486:        h = sqrt (vdiff[0]*vdiff[0] + vdiff[1]*vdiff[1] + vdiff[2]*vdiff[2]);
        !          1487:        
        !          1488:        rad1 = znode_rdlong (data) & 0xffff;
        !          1489:        rad2 = znode_rdlong (data) & 0xffff;
        !          1490:        
        !          1491:        glShadeModel (GL_SMOOTH);
        !          1492:        
        !          1493:        glPushMatrix ();
        !          1494:        glTranslatef (v1[0], v1[1], v1[2]);
        !          1495:        glRotatef (-RAD_2_DEG * (atan2 (vdiff[2], vdiff[0]) - M_PI/2), 0.0f, 1.0f, 0.0f);
        !          1496:        glRotatef (-RAD_2_DEG * asin (vdiff[1]/h), 1.0f, 0.0f, 0.0f);
        !          1497: #define CYLINDER_POOP  20
        !          1498:        
        !          1499:        lighting_on (light_vec, light_col, extra_col, znode_rdlong (data));
        !          1500:        gluDisk (qobj, 0.0, rad1, CYLINDER_POOP, 1);
        !          1501:        glTranslatef (0, 0, h);
        !          1502:        
        !          1503:        lighting_on (light_vec, light_col, extra_col, znode_rdlong (data));
        !          1504:        gluDisk (qobj, 0.0, rad2, CYLINDER_POOP, 1);
        !          1505:        glTranslatef (0, 0, -h);
        !          1506:        
        !          1507:        glEnable (GL_CULL_FACE);
        !          1508:        lighting_on (light_vec, light_col, extra_col, obj_col);
        !          1509:        gluCylinder (qobj, rad1, rad2, h, CYLINDER_POOP, 1);
        !          1510:        glDisable (GL_CULL_FACE);
        !          1511:                
        !          1512:        glPopMatrix ();
        !          1513:        lighting_off ();
        !          1514: }
        !          1515: 
        !          1516: /*
        !          1517:  * this primitive is WRONG.
        !          1518:  */
        !          1519: void Nu_PutOval ()
        !          1520: {
        !          1521:        if (use_renderer == R_OLD) return;
        !          1522:        znode_wrlong (NU_OVALTHINGY);
        !          1523:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1524:        
        !          1525:        znode_wrlong (GetReg (REG_D3));
        !          1526:        znode_wrlong (GetReg (REG_D4));
        !          1527:        znode_wrlong (GetReg (REG_D5));
        !          1528: 
        !          1529:        znode_wrlong (GetReg (REG_D6));
        !          1530: }
        !          1531: void Nu_DrawOval (void **data)
        !          1532: {
        !          1533:        int v1[3];
        !          1534:        int rad, r, g, b;
        !          1535:        unsigned short d,e,f;
        !          1536: 
        !          1537:        znode_rdvertex (data, v1);
        !          1538: 
        !          1539:        r = 0;
        !          1540:        g = 0;
        !          1541:        b = 0;
        !          1542:        
        !          1543:        d = (short) znode_rdlong (data);
        !          1544:        e = (short) znode_rdlong (data);
        !          1545:        f = (short) znode_rdlong (data);
        !          1546:        rad = (short) znode_rdlong (data);
        !          1547:        
        !          1548:        glColor3ub (r, g, b);
        !          1549:        glPushMatrix ();
        !          1550:        glTranslatef (v1[0], v1[1], v1[2]);
        !          1551:        //printf ("%d,%d,%d\n", d,e,f);
        !          1552:        //glRotatef (RAD_2_DEG*M_PI*(d/32768.0f), 0.0f, 1.0f, 0.0f);
        !          1553:        //glRotatef (RAD_2_DEG*M_PI*(e/32768.0f), 1.0f, 0.0f, 0.0f);
        !          1554:        //glRotatef (-RAD_2_DEG*M_PI*(f/65536.0f), 0.0f, 1.0f, 0.0f);
        !          1555:        gluDisk (qobj, 0.0, rad, 32, 1);
        !          1556:        glPopMatrix ();
        !          1557: }
        !          1558: 
        !          1559: void Nu_PutBlob ()
        !          1560: {
        !          1561:        if (use_renderer == R_OLD) return;
        !          1562:        znode_wrlong (NU_BLOB);
        !          1563:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1564:        znode_wrlong (GetReg (REG_D0));
        !          1565:        znode_wrlong (GetReg (REG_D1));
        !          1566: }
        !          1567: void Nu_DrawBlob (void **data)
        !          1568: {
        !          1569:        int v1[3];
        !          1570:        unsigned int r, g, b;
        !          1571:        int rad;
        !          1572:        int edges;
        !          1573:        
        !          1574:        znode_rdvertex (data, v1);
        !          1575:        split_rgb444i (znode_rdlong (data), &r, &g, &b);
        !          1576:        rad = znode_rdlong (data) & 0xffff;
        !          1577:        edges = rad+4;
        !          1578: 
        !          1579:        glColor3ui (r, g, b);
        !          1580:        if (rad < 3) {
        !          1581:                glPointSize ((rad/2)+1);
        !          1582:                glBegin (GL_POINTS);
        !          1583:                        glVertex3iv (v1);
        !          1584:                glEnd ();
        !          1585:        } else {
        !          1586:                glPushMatrix ();
        !          1587:                glTranslatef (v1[0], v1[1], v1[2]);
        !          1588:                gluDisk (qobj, 0.0, -0.002*(rad)*v1[2], edges, 1);
        !          1589:                glPopMatrix ();
        !          1590:        }
        !          1591: }
        !          1592: void Nu_PutColoredPoint ()
        !          1593: {
        !          1594:        if (use_renderer == R_OLD) return;
        !          1595:        znode_wrlong (NU_POINT);
        !          1596:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1597:        znode_wrcolor (GetReg (REG_D0));
        !          1598:        znode_wrlong (2);
        !          1599: }
        !          1600: 
        !          1601: void Nu_PutPoint ()
        !          1602: {
        !          1603:        if (use_renderer == R_OLD) return;
        !          1604:        znode_wrlong (NU_POINT);
        !          1605:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1606:        znode_wrcolor (0xfff);
        !          1607:        znode_wrlong (1);
        !          1608: }
        !          1609: void Nu_DrawPoint (void **data)
        !          1610: {
        !          1611:        int v1[3];
        !          1612:        int point_size, r, g, b;
        !          1613: 
        !          1614:        if (use_renderer == R_OLD) return;
        !          1615:        znode_rdvertex (data, v1);
        !          1616:        znode_rdcolor (data, &r, &g, &b);
        !          1617:        point_size = znode_rdlong (data);
        !          1618: 
        !          1619:        glPointSize (point_size);
        !          1620:        glColor3ub (r, g, b);
        !          1621:        glBegin (GL_POINTS);
        !          1622:                glVertex3iv (v1);
        !          1623:        glEnd ();
        !          1624: }
        !          1625: 
        !          1626: void Nu_PutLine ()
        !          1627: {
        !          1628:        if (use_renderer == R_OLD) return;
        !          1629:        znode_wrlong (NU_LINE);
        !          1630:        znode_wrvertex (GetReg (REG_A0)+4);
        !          1631:        znode_wrvertex (GetReg (REG_A1)+4);
        !          1632:        znode_wrcolor (GetReg (REG_D6));
        !          1633: }
        !          1634: void Nu_DrawLine (void **data)
        !          1635: {
        !          1636:        int v1[3], v2[3];
        !          1637:        int r, g, b;
        !          1638:        
        !          1639:        znode_rdvertex (data, v1);
        !          1640:        znode_rdvertex (data, v2);
        !          1641:        znode_rdcolor (data, &r, &g, &b);
        !          1642:        
        !          1643:        glColor3ub (r, g, b);
        !          1644:        glBegin (GL_LINES);
        !          1645:                glVertex3iv (v1);
        !          1646:                glVertex3iv (v2);
        !          1647:        glEnd ();
        !          1648: }
        !          1649: 
        !          1650: void Nu_IsGLRenderer ()
        !          1651: {
        !          1652:        if (use_renderer == R_OLD) {
        !          1653:                SetReg (0, 0);
        !          1654:        } else {
        !          1655:                SetReg (0, 1);
        !          1656:        }
        !          1657: }
        !          1658: 
        !          1659: void Nu_GLClearArea ()
        !          1660: {
        !          1661:        unsigned char *screen, *screen2;
        !          1662:        int x,y,x1,x2,y1,y2;
        !          1663: 
        !          1664:        if (use_renderer == R_OLD) return;
        !          1665:        x1 = GetReg (0)&0xffff;
        !          1666:        y1 = GetReg (1)&0xffff;
        !          1667:        x2 = GetReg (2)&0xffff;
        !          1668:        y2 = GetReg (3)&0xffff;
        !          1669:        
        !          1670:        push_ortho ();
        !          1671:        set_ctrl_viewport ();
        !          1672:        glColor3f (0.0f, 0.0f, 0.0f);
        !          1673:        glBegin (GL_TRIANGLE_STRIP);
        !          1674:                glVertex3f (x1, 200-y1, 0);
        !          1675:                glVertex3f (x2, 200-y1, 0);
        !          1676:                glVertex3f (x1, 200-y2, 0);
        !          1677:                glVertex3f (x2, 200-y2, 0);
        !          1678:        glEnd ();
        !          1679:        set_main_viewport ();
        !          1680:        pop_ortho ();
        !          1681: 
        !          1682:        /* and then we wipe the bit of the ST framebuffer (on both buffers)
        !          1683:         * to transparent/unset */
        !          1684:        screen = (unsigned char *)PHYSCREEN;
        !          1685:        screen += SCREENBYTES_LINE * y1;
        !          1686:        screen2 = (unsigned char *)LOGSCREEN;
        !          1687:        screen2 += SCREENBYTES_LINE * y1;
        !          1688: 
        !          1689:        for (y=y1; y<y2; y++) {
        !          1690:                for (x=x1; x<x2; x++) {
        !          1691:                        *(screen+x) = 255;
        !          1692:                        *(screen2+x) = 255;
        !          1693:                }
        !          1694:                screen += SCREENBYTES_LINE;
        !          1695:                screen2 += SCREENBYTES_LINE;
        !          1696:        }
        !          1697: }
        !          1698: 
        !          1699: typedef void (*NU_DRAWFUNC) (void **);
        !          1700: NU_DRAWFUNC nu_drawfuncs[NU_MAX] = {
        !          1701:        NULL,
        !          1702:        &Nu_DrawTriangle,
        !          1703:        &Nu_DrawQuad,
        !          1704:        &Nu_DrawLine,
        !          1705:        &Nu_DrawBezierLine,
        !          1706:        &Nu_DrawTeardrop,
        !          1707:        &Nu_DrawComplexSNext, // 6
        !          1708:        &Nu_DrawComplexStart,
        !          1709:        &Nu_DrawComplexEnd,
        !          1710:        &Nu_DrawComplexStartInner, // 9
        !          1711:        &Nu_DrawComplexBezier,
        !          1712:        &Nu_DrawTwinklyCircle,
        !          1713:        &Nu_DrawPlanet,
        !          1714:        &Nu_DrawCircle,
        !          1715:        &Nu_DrawCylinder,
        !          1716:        &Nu_DrawBlob,
        !          1717:        &Nu_DrawOval,
        !          1718:        &Nu_DrawPoint
        !          1719: };
        !          1720: 
        !          1721: static void Nu_DrawPrimitive (void *data)
        !          1722: {
        !          1723:        int fnum;
        !          1724:        
        !          1725:        for (;;) {
        !          1726:                fnum = znode_rdlong (&data);
        !          1727:                //fprintf (stderr, "%d ", fnum);
        !          1728:                if (!fnum) return;
        !          1729:                nu_drawfuncs[fnum] (&data);
        !          1730:        }
        !          1731: }
        !          1732: 
        !          1733: /*
        !          1734:  * znode_start is the head of a btree of znodes, each with a linked list
        !          1735:  * of GL display lists to draw (in list order).
        !          1736:  *
        !          1737:  * Draw this crap starting from biggest value znodes.
        !          1738:  */
        !          1739: static void draw_3dview (struct ZNode *node)
        !          1740: {
        !          1741:        if (node == NULL) return;
        !          1742:        if (node->more) draw_3dview (node->more);
        !          1743:        
        !          1744:        if (use_renderer) {
        !          1745:                //fprintf (stderr, "Z=%d ", node->z);
        !          1746:                Nu_DrawPrimitive (node->data);
        !          1747:        }
        !          1748: 
        !          1749:        if (node->less) draw_3dview (node->less);
        !          1750: }
        !          1751: 
        !          1752: static void set_gl_clear_col (int rgb)
        !          1753: {
        !          1754:        float r,g,b;
        !          1755:        r = (rgb&0xff)/255.0f;
        !          1756:        g = (rgb&0xff00)/65280.0f;
        !          1757:        b = (rgb&0xff0000)/16711680.0f;
        !          1758:        glClearColor (r,g,b,0);
        !          1759: }
        !          1760: 
        !          1761: void Nu_DrawScreen ()
        !          1762: {
        !          1763:        //fprintf (stderr, "Render: ");
        !          1764:        if (znode_cur) end_node ();
        !          1765:        //printf ("Frame: %d znodes.\n", znode_buf_pos);
        !          1766:        draw_3dview (znode_start);
        !          1767:        //fprintf (stderr, "\n");
        !          1768: 
        !          1769:        if (mouse_shown) {
        !          1770:                SDL_ShowCursor (SDL_ENABLE);
        !          1771:                mouse_shown = 0;
        !          1772:        } else {
        !          1773:                SDL_ShowCursor (SDL_DISABLE);
        !          1774:        }
        !          1775:        /* build RGB palettes */
        !          1776:        _BuildRGBPalette (MainRGBPalette, MainPalette, len_main_palette);
        !          1777:        _BuildRGBPalette (CtrlRGBPalette, CtrlPalette, 16);
        !          1778:        
        !          1779:        draw_control_panel ();
        !          1780:        glFlush ();
        !          1781:        
        !          1782:        SDL_GL_SwapBuffers ();
        !          1783: 
        !          1784:        /* frontier background color... */
        !          1785:        set_gl_clear_col (MainRGBPalette[fe2_bgcol]);
        !          1786:        
        !          1787:        glMatrixMode (GL_MODELVIEW);
        !          1788:        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        !          1789:        glLoadIdentity ();
        !          1790:        
        !          1791:        set_main_viewport ();
        !          1792: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.