#include <SDL.h>
#include "main.h"
#include "../m68000.h"
#include "screen.h"

/* new stuff */
enum RENDERERS use_renderer = R_OLD;
int len_main_palette;
unsigned short MainPalette[256];
unsigned short CtrlPalette[16];
int fe2_bgcol;
int mouse_shown = 0;
unsigned long logscreen, logscreen2, physcreen, physcreen2;
unsigned long VideoBase;
unsigned char *VideoRaster;
unsigned int MainRGBPalette[256];
unsigned int CtrlRGBPalette[16];
int screen_w=320;
int screen_h=200;
BOOL bGrabMouse = FALSE;
BOOL bInFullScreen = FALSE;
SDL_Surface *sdlscrn;




static const unsigned char font_bmp[] = {
	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x80,0x80,0x80,0x80,0x80,0x0,
	0x80,0x0,0x0,0x2,0xa0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x50,
	0xf8,0x50,0x50,0xf8,0x50,0x0,0x0,0x6,0x20,0xf0,0xa0,0xa0,0xa0,0xa0,0xf0,0x20,
	0x0,0x5,0x0,0xc8,0xd8,0x30,0x60,0xd8,0x98,0x0,0x0,0x6,0xa0,0x0,0xe0,0xa0,
	0xa0,0xa0,0xe0,0x0,0x0,0x4,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,
	0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0x0,0x3,0xc0,0x40,0x40,0x40,0x40,0x40,
	0x40,0xc0,0x0,0x3,0x0,0x0,0x20,0xf8,0x50,0xf8,0x20,0x0,0x0,0x6,0x0,0x0,
	0x40,0xe0,0x40,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x80,
	0x0,0x2,0x0,0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x0,
	0x0,0x0,0x80,0x0,0x0,0x2,0x0,0x8,0x18,0x30,0x60,0xc0,0x80,0x0,0x0,0x6,
	0xe0,0xa0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x40,0xc0,0x40,0x40,0x40,0x40,
	0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0xe0,0x80,0x80,0xe0,0x0,0x0,0x4,0xe0,0x20,
	0x20,0xe0,0x20,0x20,0xe0,0x0,0x0,0x4,0x80,0x80,0xa0,0xa0,0xe0,0x20,0x20,0x0,
	0x0,0x4,0xe0,0x80,0x80,0xe0,0x20,0x20,0xe0,0x0,0x0,0x4,0xe0,0x80,0x80,0xe0,
	0xa0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x4,
	0xe0,0xa0,0xa0,0xe0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0xa0,0xa0,0xe0,0x20,0x20,
	0xe0,0x0,0x0,0x4,0x0,0x0,0x0,0x80,0x0,0x80,0x0,0x0,0x0,0x2,0x0,0x0,
	0x0,0x80,0x0,0x0,0x80,0x80,0x0,0x2,0xe0,0x0,0xe0,0xa0,0xa0,0xa0,0xa0,0x0,
	0x0,0x4,0x0,0x0,0xe0,0x0,0xe0,0x0,0x0,0x0,0x0,0x4,0xc0,0x0,0xe0,0xa0,
	0xe0,0x80,0xe0,0x0,0x0,0x4,0xe0,0x20,0x20,0xe0,0x80,0x0,0x80,0x0,0x0,0x4,
	0xfe,0x82,0xba,0xa2,0xba,0x82,0xfe,0x0,0x0,0x8,0xf0,0x90,0x90,0x90,0xf0,0x90,
	0x90,0x0,0x0,0x5,0xf0,0x90,0x90,0xf8,0x88,0x88,0xf8,0x0,0x0,0x6,0xe0,0x80,
	0x80,0x80,0x80,0x80,0xe0,0x0,0x0,0x4,0xf8,0x48,0x48,0x48,0x48,0x48,0xf8,0x0,
	0x0,0x6,0xf0,0x80,0x80,0xe0,0x80,0x80,0xf0,0x0,0x0,0x5,0xf0,0x80,0x80,0xe0,
	0x80,0x80,0x80,0x0,0x0,0x4,0xf0,0x80,0x80,0x80,0xb0,0x90,0xf0,0x0,0x0,0x5,
	0x90,0x90,0x90,0xf0,0x90,0x90,0x90,0x0,0x0,0x5,0xe0,0x40,0x40,0x40,0x40,0x40,
	0xe0,0x0,0x0,0x4,0xf0,0x20,0x20,0x20,0x20,0x20,0xe0,0x0,0x0,0x4,0x90,0xb0,
	0xe0,0xc0,0xe0,0xb0,0x90,0x0,0x0,0x5,0x80,0x80,0x80,0x80,0x80,0x80,0xe0,0x0,
	0x0,0x4,0x88,0xd8,0xf8,0xa8,0x88,0x88,0x88,0x0,0x0,0x6,0x90,0xd0,0xf0,0xb0,
	0x90,0x90,0x90,0x0,0x0,0x5,0xf0,0x90,0x90,0x90,0x90,0x90,0xf0,0x0,0x0,0x5,
	0xf0,0x90,0x90,0xf0,0x80,0x80,0x80,0x0,0x0,0x5,0xf0,0x90,0x90,0x90,0x90,0xb0,
	0xf0,0x18,0x0,0x5,0xf0,0x90,0x90,0xf0,0xe0,0xb0,0x90,0x0,0x0,0x5,0xf0,0x80,
	0x80,0xf0,0x10,0x10,0xf0,0x0,0x0,0x5,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,0x0,
	0x0,0x3,0x90,0x90,0x90,0x90,0x90,0x90,0xf0,0x0,0x0,0x5,0x90,0x90,0x90,0xb0,
	0xe0,0xc0,0x80,0x0,0x0,0x5,0x88,0x88,0x88,0xa8,0xf8,0xd8,0x88,0x0,0x0,0x6,
	0x88,0xd8,0x70,0x20,0x70,0xd8,0x88,0x0,0x0,0x6,0x90,0x90,0x90,0xf0,0x20,0x20,
	0x20,0x0,0x0,0x5,0xf0,0x10,0x30,0x60,0xc0,0x80,0xf0,0x0,0x0,0x5,0xa0,0x0,
	0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x80,0xc0,0x60,0x30,0x18,0x8,0x0,
	0x0,0x6,0xe0,0xa0,0xa0,0xe0,0xa0,0xa0,0xe0,0x80,0x80,0x4,0xe0,0xa0,0xe0,0x0,
	0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8,0x0,0x6,
	0xa0,0x0,0xe0,0x20,0xe0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,0xe0,0x20,0xe0,0xa0,
	0xe0,0x0,0x0,0x4,0x80,0x80,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,
	0xc0,0x80,0x80,0x80,0xc0,0x0,0x0,0x3,0x20,0x20,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,
	0x0,0x4,0x0,0x0,0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xc0,0x80,0x80,0xc0,
	0x80,0x80,0x80,0x0,0x0,0x3,0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x20,0xe0,0x4,
	0x80,0x80,0xe0,0xa0,0xa0,0xa0,0xa0,0x0,0x0,0x4,0x80,0x0,0x80,0x80,0x80,0x80,
	0x80,0x0,0x0,0x2,0x40,0x0,0x40,0x40,0x40,0x40,0x40,0xc0,0x0,0x3,0x80,0x80,
	0xb0,0xe0,0xe0,0xb0,0x90,0x0,0x0,0x5,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x0,
	0x0,0x2,0x0,0x0,0xf8,0xa8,0xa8,0xa8,0xa8,0x0,0x0,0x6,0x0,0x0,0xe0,0xa0,
	0xa0,0xa0,0xa0,0x0,0x0,0x4,0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,
	0x0,0x0,0xe0,0xa0,0xa0,0xa0,0xe0,0x80,0x80,0x4,0x0,0x0,0xe0,0xa0,0xa0,0xa0,
	0xe0,0x20,0x30,0x4,0x0,0x0,0xc0,0x80,0x80,0x80,0x80,0x0,0x0,0x3,0x0,0x0,
	0xc0,0x80,0xc0,0x40,0xc0,0x0,0x0,0x3,0x80,0x80,0xc0,0x80,0x80,0x80,0xc0,0x0,
	0x0,0x3,0x0,0x0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,0x0,0x0,0xa0,0xa0,
	0xe0,0xc0,0x80,0x0,0x0,0x4,0x0,0x0,0x88,0xa8,0xf8,0xd8,0x88,0x0,0x0,0x6,
	0x0,0x0,0xa0,0xe0,0x40,0xe0,0xa0,0x0,0x0,0x4,0x0,0x0,0xa0,0xa0,0xa0,0xa0,
	0xe0,0x20,0xe0,0x4,0x0,0x0,0xf0,0x30,0x60,0xc0,0xf0,0x0,0x0,0x5,0x81,0x8d,
	0xe1,0xa0,0xa0,0xa0,0xa0,0x0,0x0,0x9,0x2,0x1a,0xc2,0x80,0xc0,0x40,0xc0,0x0,
	0x0,0x8,0xfe,0xfc,0xf8,0xfc,0xfe,0xdf,0x8e,0x4,0x0,0x7,0x7f,0x3f,0x1f,0x3f,
	0x7f,0xfb,0x71,0x20,0x0,0x8,0x4,0x8e,0xdf,0xfe,0xfc,0xf8,0xfc,0xfe,0x0,0x8,
	0x20,0x71,0xfb,0x7f,0x3f,0x1f,0x3f,0x7f,0x0,0x7,0xff,0x81,0x81,0x81,0x81,0x81,
	0x81,0xff,0x0,0x9,0x0,0x0,0xe0,0x80,0x80,0x80,0xe0,0x40,0xc0,0x4,0x60,0x0,
	0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xc0,0x0,0xa0,0xa0,0xa0,0xa0,0xe0,0x0,
	0x0,0x4,0x40,0xa0,0x40,0x40,0x40,0x40,0x40,0x0,0x0,0x4,0x40,0xa0,0xe0,0x20,
	0xe0,0xa0,0xe0,0x0,0x0,0x4,0x40,0xa0,0xe0,0xa0,0xa0,0xa0,0xe0,0x0,0x0,0x4,
	0x40,0xa0,0xe0,0xa0,0xe0,0x80,0xe0,0x0,0x0,0x4,0xe0,0x0,0xa0,0xa0,0xa0,0xa0,
	0xe0,0x0,0x0,0x4,0xc0,0x0,0xe0,0x20,0xe0,0xa0,0xe0,0x0,0x0,0x4,0xe0,0xa0,
	0xa0,0xa0,0xe0,0xa0,0xa0,0x0,0x0,0x4,0xc0,0xa0,0xa0,0xc0,0xa0,0xa0,0xc0,0x0,
	0x0,0x4,0xe0,0x80,0x80,0x80,0x80,0x80,0xe0,0x0,0x0,0x4,0xc0,0xa0,0xa0,0xa0,
	0xa0,0xa0,0xc0,0x0,0x0,0x4,0xe0,0x80,0x80,0xe0,0x80,0x80,0xe0,0x0,0x0,0x4,
	0xe0,0x80,0x80,0xe0,0x80,0x80,0x80,0x0,0x0,0x4
};



static inline void read_m68k_vertex (int st_vptr, int output[3])
{
        output[0] = STMemory_ReadLong (st_vptr);
        output[1] = STMemory_ReadLong (st_vptr+4);
        output[2] = -STMemory_ReadLong (st_vptr+8);
}

struct ZNode {
        unsigned int z;
        struct ZNode *less, *more;
        void *data;
};

#define MAX_OBJ_DATA    (2<<17)
static unsigned char obj_data_area[MAX_OBJ_DATA];
static int obj_data_pos;
#define MAX_ZNODES      1000
static struct ZNode znode_buf[MAX_ZNODES];
static int znode_buf_pos;
static struct ZNode *znode_start;
static struct ZNode *znode_cur;

enum NuPrimitive {
        NU_END,
        NU_TRIANGLE,
        NU_QUAD,
        NU_LINE,
        NU_BEZIER_LINE,
        NU_TEARDROP,
        NU_COMPLEX_SNEXT,
        NU_COMPLEX_START,
        NU_COMPLEX_END,
        NU_COMPLEX_INNER,
        NU_COMPLEX_BEZIER,
        NU_TWINKLYCIRCLE,
        NU_PLANET,
        NU_CIRCLE,
        NU_CYLINDER,
        NU_BLOB,
        NU_OVALTHINGY,
        NU_POINT,
        NU_2DLINE,
        NU_MAX
};


#define MAX_QUEUED_STRINGS      200
struct QueuedString {
        int x, y, col;
        unsigned char str[64];
} queued_strings[MAX_QUEUED_STRINGS];
int queued_string_pos;
static bool no_znodes_kthx;


/*********PROTOTYPES****************/
static void _BuildRGBPalette (unsigned int *rgb, unsigned short *st, int len);
static void draw_3dview (struct ZNode *node);
static int DrawChar (int col, int xoffset, char *scrline, int chr);
static void Nu_DrawPrimitive (void *data);
static inline int znode_rdlong (void **data);
static void add_node (struct ZNode **node, unsigned int zval);
static void znode_insert (struct ZNode *node, unsigned int zval);
static inline void end_node ();
static inline void znode_databegin ();
static inline void znode_wrlong (int val);

int DrawStr (int xpos, int ypos, int col, unsigned char *str, bool shadowed)
{
        int x, y, chr;
        char *screen;

        x = xpos;
        y = ypos;

        if ((y > 192) || (y<0)) return x;
set_line:
        screen = LOGSCREEN2;
        screen += SCREENBYTES_LINE * y;

        while (*str) {
                chr = *(str++);

                if (chr < 0x1e) {
                        if (chr == '\r') {
                                y += 10;
                                x = xpos;
                                goto set_line;
                        }
                        else if (chr == 1) col = *(str++);
                        continue;
                } else if (chr == 0x1e) {
                        /* read new xpos */
                        x = *(str++);
                        x *= 2;
                        continue;
                } else if (chr < 0x20) {
                        /* Read new position */
                        x = *(str++);
                        x *= 2;
                        y = *(str++);
                        goto set_line;
                }

                //if (x > 316) continue;

                if (shadowed) {
                        DrawChar (0, x+1, screen+SCREENBYTES_LINE, chr-0x20);
                }
                x = DrawChar (col, x, screen, chr-0x20);
        }

        return x;
printf ("DrawStr [%s]\n",str);
return 0;
}

void Nu_PutColoredPoint()
{}

void Nu_ComplexSNext()
{}
void Nu_DrawComplexSNext()
{}

void Nu_DrawComplexStart()
{}
void Nu_DrawComplexEnd()
{}

void Nu_ComplexStartInner()
{}
void Nu_DrawComplexStartInner()
{}
void Nu_ComplexBezier()
{}
void Nu_DrawComplexBezier()
{}


void draw_control_panel()
{
 unsigned int *pal;
  // Lock surface if needed
  if (SDL_MUSTLOCK(sdlscrn)) 
    if (SDL_LockSurface(sdlscrn) < 0) 
      return;


//JASON
  // Declare a couple of variables
  int y, x, yofs, ofs;

  // Draw to screen
  yofs = 0;
  pal=MainRGBPalette;
  for (y = 0; y < screen_h; y++)
  {
	if(y==168)pal=CtrlRGBPalette; //bottom has differnet palette
    for (x = 0, ofs = yofs; x < screen_w; x++, ofs++)
    {
      //((unsigned int*)sdlscrn->pixels)[ofs] = pal[VideoRaster[ofs]];



switch (sdlscrn->format->BytesPerPixel) 
{ 
case 1: // 8-bpp 
{ 
Uint8 *bufp; 
bufp = (Uint8 *)sdlscrn->pixels + y*sdlscrn->pitch + x; 
*bufp =(Uint8*) pal[VideoRaster[ofs]]; 
} 
break; 
case 2: // 15-bpp or 16-bpp 
{ 
Uint16 *bufp; 
bufp = (Uint16 *)sdlscrn->pixels + y*sdlscrn->pitch/2 + x; 
*bufp = pal[VideoRaster[ofs]]; 
} 
break; 
case 3: // 24-bpp mode, usually not used 
{ 
Uint8 *bufp; 
bufp = (Uint8 *)sdlscrn->pixels + y*sdlscrn->pitch + x * 3; 
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) 
{ 
bufp[0] = pal[VideoRaster[ofs]]; 
bufp[1] = pal[VideoRaster[ofs]] >> 8; 
bufp[2] = pal[VideoRaster[ofs]] >> 16; 
} else { 
bufp[2] = pal[VideoRaster[ofs]]; 
bufp[1] = pal[VideoRaster[ofs]] >> 8; 
bufp[0] = pal[VideoRaster[ofs]] >> 16; 
} 
} 
break; 
case 4: // 32-bpp 
{ 
Uint32 *bufp; 
bufp = (Uint32 *)sdlscrn->pixels + y*sdlscrn->pitch/4 + x; 
*bufp = pal[VideoRaster[ofs]]; 
} 
break; 
} 




	
    }
    //yofs += sdlscrn->pitch / 4;
    yofs += sdlscrn->pitch / sdlscrn->format->BytesPerPixel;
  }

  // Unlock if needed
  if (SDL_MUSTLOCK(sdlscrn)) 
    SDL_UnlockSurface(sdlscrn);

  // Tell SDL to update the whole screen
  SDL_UpdateRect(sdlscrn, 0, 0, screen_w, screen_h); 

//printf("draw_control_panel\n");
}

void Nu_DrawScreen()
{
_BuildRGBPalette (MainRGBPalette, MainPalette, len_main_palette);
_BuildRGBPalette (CtrlRGBPalette, CtrlPalette, 16);
//printf ("Frame: %d znodex.\n",znode_buf_pos);
//draw_3dview (znode_start);
if (mouse_shown) {
        SDL_ShowCursor (SDL_ENABLE);
        mouse_shown = 0;
} else {
        SDL_ShowCursor (SDL_DISABLE);
}
draw_control_panel();
//set_main_viewport();

//printf("Nu_DrawScreen\n");

}

void Nu_PutBezierLine()
{}
void Nu_DrawBezierLine()
{}

void Nu_3DViewInit()
{
        queued_string_pos = 0;
        //printf ("3dviewinit()\n");
        znode_buf_pos = 0;
        //printf ("%d bytes object data\n", obj_data_pos);
        obj_data_pos = 0;

        znode_start = NULL;
        znode_cur = NULL;
        no_znodes_kthx = FALSE;
}
void Nu_InsertZNode()
{
        unsigned int zval = GetReg (4);
        if (use_renderer == R_OLD) return;
        if (no_znodes_kthx) return;
        if (znode_start == NULL) {
                add_node (&znode_start, zval);
        } else {
                znode_insert (znode_start, zval);
        }
}

void Nu_PutCircle()
{}
void Nu_DrawCircle()
{}

void Nu_PutOval()
{}
void Nu_DrawOval()
{}

void Nu_PutCylinder()
{}
void Nu_DrawCylinder()
{}

void Nu_QueueDrawStr()
{}
void Nu_IsGLRenderer()
{
 SetReg(0,0);
}

void Nu_PutPlanet()
{}
void Nu_DrawPlanet()
{}

void Nu_Put2Line()
{}
void Nu_Draw2Line()
{}

void Nu_PutQuad()
{}
void Nu_DrawQuad()
{}

void Nu_GLClearArea()
{}
void Nu_PutBlob()
{use_renderer=R_OLD;}
void Nu_DrawBlob()
{}

void Nu_Put2DLine()
{}
void Nu_Draw2DLine()
{}

void Nu_PutLine()
{}
void Nu_DrawLine()
{}

void Nu_UnInit()
{}

void Nu_PutTeardrop()
{}
void Nu_DrawTeardrop()
{}

void Nu_PutPoint()
{
printf("Nu_PutPoint\n");
}
void Nu_DrawPoint()
{}

void Nu_PutTwinklyCircle()
{}
void Nu_DrawTwinklyCircle()
{}

void Nu_ComplexStart()
{}

void Nu_PutTriangle()
{}
void Nu_DrawTriangle()
{}

void Nu_ComplexSBegin()
{}

void Nu_ComplexEnd()
{}

void Nu_32ViewInit()
{}

void Screen_ToggleRenderer ()
{
use_renderer = R_OLD;
}

void change_vidmode(void);

void Screen_Init(void)
{
change_vidmode();
SDL_WM_SetCaption(PROG_NAME, "Frontier");
SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
SDL_ShowCursor(SDL_ENABLE);
use_renderer=R_OLD;
printf("Screen_Init\n");
}

void change_vidmode (void)
{
        const SDL_VideoInfo *info = NULL;
        int modes;

        info = SDL_GetVideoInfo ();

        assert (info != NULL);


        modes = SDL_SWSURFACE;// SDL_ANYFORMAT | (bInFullScreen ? SDL_FULLSCREEN : 0 );

        if ((sdlscrn = SDL_SetVideoMode (screen_w, screen_h,
                                info->vfmt->BitsPerPixel, modes)) == 0) {
               fprintf (stderr, "Video mode set failed: %s\n", SDL_GetError ());
                SDL_Quit ();
                exit (-1);
	}
printf("change_vidmode %d x %d %d deep\n",screen_w,screen_h,info->vfmt->BitsPerPixel);
}

void Screen_UnInit(void)
{}
void Screen_ToggleFullScreen()
{
}

static void _BuildRGBPalette (unsigned int *rgb, unsigned short *st, int len)
{
        int i;
        int st_col, r, g, b;

        for (i=0; i<len; i++, st++) {
                st_col = *st;
                b = (st_col & 0xf)<<4;
                g = (st_col & 0xf0);
                r = (st_col & 0xf00)>>4;
                rgb[i] = 0xff000000 | (b<<16) | (g<<8) | (r);
        }
}

static int DrawChar (int col, int xoffset, char *scrline, int chr)
{
        const char *font_pos;
        char *pix;
        int i;

        font_pos = font_bmp;
        font_pos += (chr&0xff)*10;
        scrline += xoffset;

        if (xoffset < 0) {
                font_pos += 9;
                return xoffset + *font_pos;
        }

        for (i=0; i<8; i++, font_pos++, scrline += SCREENBYTES_LINE) {
                pix = scrline;
                if (xoffset > 319) continue;
                if (*font_pos & 0x80) *pix = col;
                pix++;
                if (xoffset+1 > 319) continue;
                if (*font_pos & 0x40) *pix = col;
                pix++;
                if (xoffset+2 > 319) continue;
                if (*font_pos & 0x20) *pix = col;
                pix++;
                if (xoffset+3 > 319) continue;
                if (*font_pos & 0x10) *pix = col;
                pix++;
                if (xoffset+4 > 319) continue;
                if (*font_pos & 0x8) *pix = col;
                pix++;
                if (xoffset+5 > 319) continue;
                if (*font_pos & 0x4) *pix = col;
                pix++;
                if (xoffset+6 > 319) continue;
                if (*font_pos & 0x2) *pix = col;
                pix++;
                if (xoffset+7 > 319) continue;
                if (*font_pos & 0x1) *pix = col;
        }
        /* width of character */
        font_pos++;
        i = *font_pos;
        return xoffset + i;
}
/*
 * znode_start is the head of a btree of znodes, each with a linked list
 * of GL display lists to draw (in list order).
 *
 * Draw this crap starting from biggest value znodes.
 */
static void draw_3dview (struct ZNode *node)
{
        if (node == NULL) return;
        if (node->more) draw_3dview (node->more);

        if (use_renderer) {
                printf ("Z=%d ", node->z);
                Nu_DrawPrimitive (node->data);
        }

        if (node->less) draw_3dview (node->less);
printf("draw_3dview\n");
}

typedef void (*NU_DRAWFUNC) (void **);
NU_DRAWFUNC nu_drawfuncs[NU_MAX] = {
        NULL,
        &Nu_DrawTriangle,
        &Nu_DrawQuad,
        &Nu_DrawLine,
        &Nu_DrawBezierLine,
        &Nu_DrawTeardrop,
        &Nu_DrawComplexSNext, // 6
        &Nu_DrawComplexStart,
        &Nu_DrawComplexEnd,
        &Nu_DrawComplexStartInner, // 9
        &Nu_DrawComplexBezier,
        &Nu_DrawTwinklyCircle,
        &Nu_DrawPlanet,
        &Nu_DrawCircle,
        &Nu_DrawCylinder,
        &Nu_DrawBlob,
        &Nu_DrawOval,
        &Nu_DrawPoint,
        &Nu_Draw2DLine
};


static void Nu_DrawPrimitive (void *data)
{
        int fnum;

        for (;;) {
                fnum = znode_rdlong (&data);
                //fprintf (stderr, "%d ", fnum);
                if (!fnum) return;
                nu_drawfuncs[fnum] (&data);
        }
}

static inline int znode_rdlong (void **data)
{
        int val = *((int*)(*data));
        (*data) += 4;
        return val;
}

static void add_node (struct ZNode **node, unsigned int zval)
{
        assert (znode_buf_pos < MAX_ZNODES);
        /* end previous znode display list!!!!!!! */
        if (znode_cur) end_node ();

        *node = znode_cur = &znode_buf[znode_buf_pos++];
        znode_cur->z = zval;
        znode_cur->less = NULL;
        znode_cur->more = NULL;
        znode_databegin ();
}

static inline void end_node ()
{
        znode_wrlong (0);
}

static void znode_insert (struct ZNode *node, unsigned int zval)
{
        if (zval > node->z) {
                if (node->more) {
                        znode_insert (node->more, zval);
                } else {
                        add_node (&node->more, zval);
                }
        } else {
                if (node->less) {
                        znode_insert (node->less, zval);
                } else {
                        add_node (&node->less, zval);
                }
        }
}

static inline void znode_databegin ()
{
        znode_cur->data = &obj_data_area[obj_data_pos];
}

static inline void znode_wrlong (int val)
{
        *((int*)(obj_data_area+obj_data_pos)) = val;
        obj_data_pos+=4;
}
