Annotation of frontvm/src/screen.c, revision 1.1.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.