gba-x3dtest

changeset 9:b0ed38f13261

working on the rasterizer
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Jun 2014 05:16:10 +0300
parents fb0a0d6a8b52
children 23f716fa7f10
files Makefile.sdl src/config.h src/game.c src/main.c src/main_sdl.c src/palman.c src/palman.h src/polyfill.c src/sdlsys/gbasys.h src/x3d.c src/x3d.h
diffstat 11 files changed, 326 insertions(+), 42 deletions(-) [+]
line diff
     1.1 --- a/Makefile.sdl	Thu Jun 19 05:53:46 2014 +0300
     1.2 +++ b/Makefile.sdl	Sun Jun 22 05:16:10 2014 +0300
     1.3 @@ -4,7 +4,9 @@
     1.4  dep = $(obj:.o=.d)
     1.5  bin = trycatch
     1.6  
     1.7 -CFLAGS = -pedantic -Wall -g `pkg-config sdl --cflags` -Isrc -Isrc/sdlsys
     1.8 +warn = -Wall -Wno-unused-function
     1.9 +
    1.10 +CFLAGS = -pedantic $(warn) -g `pkg-config sdl --cflags` -Isrc -Isrc/sdlsys
    1.11  LDFLAGS = `pkg-config sdl --libs` -lm
    1.12  
    1.13  $(bin): $(obj)
    1.14 @@ -13,6 +15,11 @@
    1.15  %.x86.o: %.c
    1.16  	$(CC) $(CFLAGS) -o $@ -c $<
    1.17  
    1.18 +-include $(dep)
    1.19 +
    1.20 +%.x86.d: %.c
    1.21 +	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    1.22 +
    1.23  .PHONY: clean
    1.24  clean:
    1.25  	rm -f $(obj) $(bin)
     2.1 --- a/src/config.h	Thu Jun 19 05:53:46 2014 +0300
     2.2 +++ b/src/config.h	Sun Jun 22 05:16:10 2014 +0300
     2.3 @@ -1,8 +1,24 @@
     2.4  #ifndef CONFIG_H_
     2.5  #define CONFIG_H_
     2.6  
     2.7 -#define GFX_MODE	VMODE_LFB_160x128_16
     2.8 +#include "gbasys.h"
     2.9 +
    2.10 +/* 3: 240x160:16
    2.11 + * 4: 240x160:8
    2.12 + * 5: 160x128:16
    2.13 + */
    2.14 +#define GFX_MODE	5
    2.15 +
    2.16 +#if (GFX_MODE == 3) || (GFX_MODE == 4)
    2.17 +#define WIDTH		240
    2.18 +#define HEIGHT		160
    2.19 +#else
    2.20  #define WIDTH		160
    2.21  #define HEIGHT		128
    2.22 +#endif
    2.23 +
    2.24 +#if (GFX_MODE == 4)
    2.25 +#define PALMODE
    2.26 +#endif
    2.27  
    2.28  #endif	/* CONFIG_H_ */
     3.1 --- a/src/game.c	Thu Jun 19 05:53:46 2014 +0300
     3.2 +++ b/src/game.c	Sun Jun 22 05:16:10 2014 +0300
     3.3 @@ -4,23 +4,32 @@
     3.4  #include "x3d.h"
     3.5  #include "sincos.h"
     3.6  #include "fixed.h"
     3.7 +#include "palman.h"
     3.8 +
     3.9 +static void draw_rect(int x, int y, int w, int h, uint16_t color);
    3.10  
    3.11  #define X16INT(x)	((x) << 16)
    3.12  
    3.13  static const int32_t poly[] = {
    3.14 -	X16INT(80), X16INT(10), 0,
    3.15 -	X16INT(140), X16INT(100), 0,
    3.16 -	X16INT(40), X16INT(80), 0
    3.17 +	X16INT(120), X16INT(20), 0,
    3.18 +	X16INT(200), X16INT(130), 0,
    3.19 +	X16INT(40), X16INT(100), 0
    3.20  };
    3.21  static const short vcount = sizeof poly / sizeof *poly / 3;
    3.22  
    3.23  int game_init(void)
    3.24  {
    3.25  	sincos_init();
    3.26 +#ifdef PALMODE
    3.27 +	palman_init();
    3.28 +#endif
    3.29  
    3.30  	return 0;
    3.31  }
    3.32  
    3.33 +static short keyrot;
    3.34 +static int autorot = 1;
    3.35 +
    3.36  void game_draw(void)
    3.37  {
    3.38  	unsigned long msec = get_millisec();
    3.39 @@ -29,22 +38,119 @@
    3.40  
    3.41  	x3d_load_identity();
    3.42  	x3d_translate(-itox16(WIDTH / 2), -itox16(HEIGHT / 2), 0);
    3.43 -	x3d_rotate((msec / 64) << 16, 0, 0, 65536);
    3.44 +	if(autorot) {
    3.45 +		x3d_rotate((msec / 64) << 16, 0, 0, 65536);
    3.46 +	} else {
    3.47 +		x3d_rotate(keyrot << 16, 0, 0, 65536);
    3.48 +	}
    3.49  	x3d_translate(itox16(WIDTH / 2), itox16(HEIGHT / 2), 0);
    3.50  
    3.51  	x3d_vertex_array(vcount, poly);
    3.52  
    3.53 +#ifdef PALMODE
    3.54 +	x3d_color_index(255);
    3.55 +#else
    3.56  	x3d_color(65536, 65536, 65536);
    3.57 +#endif
    3.58  	x3d_draw_arrays(X3D_TRIANGLES, vcount);
    3.59  
    3.60 +#ifdef PALMODE
    3.61 +	x3d_color_index(RGBPAL(0, 255, 0));
    3.62 +#else
    3.63  	x3d_color(0, 65536, 0);
    3.64 +#endif
    3.65  	x3d_draw_arrays(X3D_POINTS, vcount);
    3.66 +	x3d_vertex_array(0, 0);
    3.67  
    3.68 -	x3d_vertex_array(0, 0);
    3.69 +	draw_rect(0, 0, WIDTH, HEIGHT, RGBPAL(255, 0, 0));
    3.70 +	draw_rect(1, 1, WIDTH - 2, HEIGHT - 2, RGBPAL(0, 255, 0));
    3.71 +	draw_rect(2, 2, WIDTH - 4, HEIGHT - 4, RGBPAL(32, 64, 255));
    3.72  
    3.73  	flip();
    3.74  }
    3.75  
    3.76  void game_keyb(int key, int pressed)
    3.77  {
    3.78 +	if(!pressed) return;
    3.79 +
    3.80 +	switch(key) {
    3.81 +	case KEY_LEFT:
    3.82 +		keyrot--;
    3.83 +		break;
    3.84 +
    3.85 +	case KEY_RIGHT:
    3.86 +		keyrot++;
    3.87 +		break;
    3.88 +
    3.89 +	case KEY_A:
    3.90 +		autorot = !autorot;
    3.91 +		break;
    3.92 +
    3.93 +	default:
    3.94 +		break;
    3.95 +	}
    3.96  }
    3.97 +
    3.98 +#ifdef PALMODE
    3.99 +#define ROWADV	(WIDTH / 2)
   3.100 +#else
   3.101 +#define ROWADV	WIDTH
   3.102 +#endif
   3.103 +
   3.104 +static void draw_rect(int x, int y, int w, int h, uint16_t color)
   3.105 +{
   3.106 +	int i, xsz = w, ysz = h;
   3.107 +	uint16_t *pixels = back_buffer->pixels;
   3.108 +	uint16_t *topleft, *topright, *botleft;
   3.109 +
   3.110 +#ifdef PALMODE
   3.111 +	pixels += (y * WIDTH + x) / 2;
   3.112 +	topleft = pixels;
   3.113 +	topright = (uint16_t*)back_buffer->pixels + (y * WIDTH + x + w - 1) / 2;
   3.114 +
   3.115 +	color |= color << 8;
   3.116 +	xsz /= 2;
   3.117 +#else
   3.118 +	pixels += y * WIDTH + x;
   3.119 +	topleft = pixels;
   3.120 +	topright = topleft + w - 1;
   3.121 +#endif
   3.122 +	botleft = topleft + (ysz - 1) * ROWADV;
   3.123 +
   3.124 +#ifdef PALMODE
   3.125 +	if(x & 1) {
   3.126 +		*topleft = (*topleft & 0xff) | (color & 0xff00);
   3.127 +		*botleft = (*topleft & 0xff) | (color & 0xff00);
   3.128 +		++topleft;
   3.129 +		++botleft;
   3.130 +		xsz -= 1;
   3.131 +	}
   3.132 +#endif
   3.133 +	for(i=0; i<xsz; i++) {
   3.134 +		*topleft++ = color;
   3.135 +		*botleft++ = color;
   3.136 +	}
   3.137 +
   3.138 +	topleft = pixels;
   3.139 +	for(i=0; i<ysz; i++) {
   3.140 +#ifdef PALMODE
   3.141 +		if(x & 1) {
   3.142 +			*topleft = (*topleft & 0xff) | (color & 0xff00);
   3.143 +		} else {
   3.144 +			*topleft = (*topleft & 0xff00) | (color & 0xff);
   3.145 +		}
   3.146 +
   3.147 +		if((x + w - 1) & 1) {
   3.148 +			*topright = (*topright & 0xff) | (color & 0xff00);
   3.149 +		} else {
   3.150 +			*topright = (*topright & 0xff00) | (color & 0xff);
   3.151 +		}
   3.152 +#else
   3.153 +		*topleft = color;
   3.154 +		*topright = color;
   3.155 +#endif
   3.156 +
   3.157 +		topleft += ROWADV;
   3.158 +		topright += ROWADV;
   3.159 +	}
   3.160 +}
     4.1 --- a/src/main.c	Thu Jun 19 05:53:46 2014 +0300
     4.2 +++ b/src/main.c	Sun Jun 22 05:16:10 2014 +0300
     4.3 @@ -20,7 +20,7 @@
     4.4  
     4.5  	interrupt(INTR_KEY, keyb_intr);
     4.6  
     4.7 -	set_video_mode(VMODE_LFB_160x128_16, 1);
     4.8 +	set_video_mode(GFX_MODE, 1);
     4.9  
    4.10  	clear_buffer(front_buffer, 0);
    4.11  	set_text_writebg(1);
     5.1 --- a/src/main_sdl.c	Thu Jun 19 05:53:46 2014 +0300
     5.2 +++ b/src/main_sdl.c	Sun Jun 22 05:16:10 2014 +0300
     5.3 @@ -5,6 +5,14 @@
     5.4  #include "gbasys.h"
     5.5  #include "game.h"
     5.6  
     5.7 +#ifdef PALMODE
     5.8 +#define BPP		8
     5.9 +#define PIXSZ	1
    5.10 +#else
    5.11 +#define BPP		16
    5.12 +#define PIXSZ	2
    5.13 +#endif
    5.14 +
    5.15  static int proc_events(SDL_Event *ev);
    5.16  static void handle_keyboard(int key, int state);
    5.17  
    5.18 @@ -29,7 +37,7 @@
    5.19  
    5.20  	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
    5.21  
    5.22 -	if(!(surf = SDL_SetVideoMode(WIDTH * sdlscale, HEIGHT * sdlscale, 16, SDL_SWSURFACE))) {
    5.23 +	if(!(surf = SDL_SetVideoMode(WIDTH * sdlscale, HEIGHT * sdlscale, BPP, SDL_SWSURFACE))) {
    5.24  		fprintf(stderr, "failed to initialize graphics\n");
    5.25  		return 1;
    5.26  	}
    5.27 @@ -37,8 +45,8 @@
    5.28  
    5.29  	bbuf.x = WIDTH;
    5.30  	bbuf.y = HEIGHT;
    5.31 -	bbuf.bpp = 16;
    5.32 -	if(!(bbuf.pixels = malloc(WIDTH * HEIGHT * 2))) {
    5.33 +	bbuf.bpp = BPP;
    5.34 +	if(!(bbuf.pixels = malloc(WIDTH * HEIGHT * PIXSZ))) {
    5.35  		fprintf(stderr, "failed to allocate framebuffer (%dx%d)\n", WIDTH, HEIGHT);
    5.36  		SDL_Quit();
    5.37  		return 1;
    5.38 @@ -53,7 +61,11 @@
    5.39  
    5.40  	for(;;) {
    5.41  		SDL_Event ev;
    5.42 +#ifdef PALMODE
    5.43 +		uint8_t *dest, *src;
    5.44 +#else
    5.45  		uint16_t *dest, *src;
    5.46 +#endif
    5.47  
    5.48  		while(SDL_PollEvent(&ev)) {
    5.49  			if(proc_events(&ev) == -1) {
    5.50 @@ -102,14 +114,32 @@
    5.51  
    5.52  void clear_buffer(struct pixel_buffer *pbuf, unsigned short color)
    5.53  {
    5.54 -	int i;
    5.55 +	int i, sz = pbuf->x * pbuf->y;
    5.56  	unsigned short *pixels = pbuf->pixels;
    5.57  
    5.58 -	for(i=0; i<pbuf->x * pbuf->y; i++) {
    5.59 +#ifdef PALMODE
    5.60 +	color |= color << 8;
    5.61 +	sz /= 2;
    5.62 +#endif
    5.63 +
    5.64 +	for(i=0; i<sz; i++) {
    5.65  		*pixels++ = color;
    5.66  	}
    5.67  }
    5.68  
    5.69 +void set_palette(int idx, int r, int g, int b)
    5.70 +{
    5.71 +	SDL_Color col;
    5.72 +	col.r = r;
    5.73 +	col.g = g;
    5.74 +	col.b = b;
    5.75 +
    5.76 +	if(SDL_SetPalette(surf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) {
    5.77 +		fprintf(stderr, "set_palette failed to set the required color\n");
    5.78 +	}
    5.79 +}
    5.80 +
    5.81 +
    5.82  int get_key_state(int key)
    5.83  {
    5.84  	return keystate & key;
    5.85 @@ -125,7 +155,7 @@
    5.86  	switch(ev->type) {
    5.87  	case SDL_KEYDOWN:
    5.88  	case SDL_KEYUP:
    5.89 -		handle_keyboard(ev->key.keysym.sym, ev->key.state == SDL_KEYDOWN);
    5.90 +		handle_keyboard(ev->key.keysym.sym, ev->key.state);
    5.91  		break;
    5.92  
    5.93  	case SDL_QUIT:
    5.94 @@ -173,6 +203,7 @@
    5.95  		break;
    5.96  
    5.97  	case '\n':
    5.98 +	case '\r':
    5.99  		gba_key = KEY_A;
   5.100  		break;
   5.101  	case '\b':
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/palman.c	Sun Jun 22 05:16:10 2014 +0300
     6.3 @@ -0,0 +1,16 @@
     6.4 +#include "gbasys.h"
     6.5 +#include "palman.h"
     6.6 +
     6.7 +void palman_init(void)
     6.8 +{
     6.9 +	int i;
    6.10 +
    6.11 +	for(i=0; i<255; i++) {
    6.12 +		int r = GET_R_PAL(i);
    6.13 +		int g = GET_G_PAL(i);
    6.14 +		int b = GET_B_PAL(i);
    6.15 +
    6.16 +		set_palette(i, r, g, b);
    6.17 +	}
    6.18 +	set_palette(255, 255, 255, 255);
    6.19 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/palman.h	Sun Jun 22 05:16:10 2014 +0300
     7.3 @@ -0,0 +1,13 @@
     7.4 +#ifndef PALMAN_H_
     7.5 +#define PALMAN_H_
     7.6 +
     7.7 +#define RGBPAL(r, g, b)	\
     7.8 +	(((r) & 0xe0) | (((g) >> 3) & 0x1c) | (((b) >> 6) & 0x3))
     7.9 +
    7.10 +#define GET_R_PAL(c)	((c) & 0xe0)
    7.11 +#define GET_G_PAL(c)	(((c) & 0x1c) << 3)
    7.12 +#define GET_B_PAL(c)	(((c) & 0x3) << 6)
    7.13 +
    7.14 +void palman_init(void);
    7.15 +
    7.16 +#endif	/* PALMAN_H_ */
     8.1 --- a/src/polyfill.c	Thu Jun 19 05:53:46 2014 +0300
     8.2 +++ b/src/polyfill.c	Sun Jun 22 05:16:10 2014 +0300
     8.3 @@ -5,14 +5,18 @@
     8.4  #include "fixed.h"
     8.5  #include "gbasys.h"
     8.6  
     8.7 -static void fill_scanline(int y, int x0, int x1, uint16_t color);
     8.8 +#define VNEXT(x, n)		(((x) + 1) % (n))
     8.9 +#define VPREV(x, n)		((x) > 0 ? (x) - 1 : (n) - 1)
    8.10 +
    8.11 +static void fill_scanline_pal(int y, int x0, int x1, uint8_t color);
    8.12 +static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color);
    8.13  
    8.14  void draw_poly(int num, const pvec3 *verts, uint16_t color)
    8.15  {
    8.16  	int i, topidx = 0, botidx = 0;
    8.17 -	int lidx[2], ridx[2];
    8.18 +	int lidx[2] = {-1, -1}, ridx[2] = {-1, -1};
    8.19  	int32_t y, topy, boty;
    8.20 -	int32_t ldy, rdy, ldxdy, rdxdy;
    8.21 +	int32_t ldy = 0, rdy = 0, ldxdy, rdxdy;
    8.22  	int32_t lx, rx;
    8.23  	int start, end;
    8.24  
    8.25 @@ -30,22 +34,46 @@
    8.26  	}
    8.27  
    8.28  	lidx[0] = ridx[0] = topidx;
    8.29 -	lidx[1] = topidx ? topidx - 1 : num - 1;
    8.30 -	ridx[1] = (topidx + 1) % num;
    8.31 +
    8.32 +	/* find starting left edge */
    8.33 +	lidx[1] = VPREV(lidx[0], num);
    8.34 +	ldy = verts[lidx[1]].y - verts[lidx[0]].y;
    8.35 +
    8.36 +	while(ldy == 0) {
    8.37 +		lidx[0] = lidx[1];
    8.38 +		lidx[1] = VPREV(lidx[1], num);
    8.39 +
    8.40 +		if(lidx[1] == topidx) {
    8.41 +			return;	/* degenerate */
    8.42 +		}
    8.43 +
    8.44 +		ldy = verts[lidx[1]].y - verts[lidx[0]].y;
    8.45 +	}
    8.46 +	lx = verts[lidx[0]].x;
    8.47 +	ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
    8.48 +
    8.49 +	/* find starting right edge */
    8.50 +	ridx[1] = VNEXT(ridx[0], num);
    8.51 +	rdy = verts[ridx[1]].y - verts[ridx[0]].y;
    8.52 +
    8.53 +	while(rdy == 0) {
    8.54 +		ridx[0] = ridx[1];
    8.55 +		ridx[1] = VNEXT(ridx[1], num);
    8.56 +
    8.57 +		if(ridx[1] == topidx) {
    8.58 +			return; /* degenerate */
    8.59 +		}
    8.60 +
    8.61 +		rdy = verts[ridx[1]].y - verts[ridx[0]].y;
    8.62 +	}
    8.63 +	rx = verts[ridx[0]].x;
    8.64 +	rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
    8.65 +
    8.66  
    8.67  	if(verts[ridx[1]].x < verts[lidx[1]].x) {
    8.68 -		return;	/* backface (CCW) */
    8.69 +		return;	/*  backface (CCW) */
    8.70  	}
    8.71  
    8.72 -	lx = rx = verts[lidx[0]].x;
    8.73 -
    8.74 -	/* TODO handle ldy == 0 or rdy == 0 */
    8.75 -	ldy = verts[lidx[1]].y - verts[lidx[0]].y;
    8.76 -	ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
    8.77 -
    8.78 -	rdy = verts[ridx[1]].y - verts[ridx[0]].y;
    8.79 -	rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
    8.80 -
    8.81  	start = topy >> 16;
    8.82  	end = boty >> 16;
    8.83  
    8.84 @@ -53,18 +81,12 @@
    8.85  
    8.86  	y = topy;
    8.87  	for(i=start; i<end; i++) {
    8.88 -		unsigned short x0, x1;
    8.89 -
    8.90 -		x0 = lx < 0 ? 0 : (lx >> 16);
    8.91 -		x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
    8.92 -
    8.93 -		if(i >= 0 && x1 > x0) {
    8.94 -			fill_scanline(i, x0, x1, color);
    8.95 -		}
    8.96 +		short x0, x1;
    8.97  
    8.98  		if(y >= verts[lidx[1]].y) {
    8.99 +			lx = verts[lidx[1]].x;
   8.100  			lidx[0] = lidx[1];
   8.101 -			lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1;
   8.102 +			lidx[1] = VPREV(lidx[1], num);
   8.103  			ldy = verts[lidx[1]].y - verts[lidx[0]].y;
   8.104  			if(ldy < 0) {
   8.105  				break;
   8.106 @@ -72,8 +94,9 @@
   8.107  			ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
   8.108  		}
   8.109  		if(y >= verts[ridx[1]].y) {
   8.110 +			rx = verts[ridx[1]].x;
   8.111  			ridx[0] = ridx[1];
   8.112 -			ridx[1] = (ridx[1] + 1) % num;
   8.113 +			ridx[1] = VNEXT(ridx[1], num);
   8.114  			rdy = verts[ridx[1]].y - verts[ridx[0]].y;
   8.115  			if(rdy < 0) {
   8.116  				break;
   8.117 @@ -81,13 +104,58 @@
   8.118  			rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
   8.119  		}
   8.120  
   8.121 +		x0 = lx < 0 ? 0 : (lx >> 16);
   8.122 +		x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
   8.123 +
   8.124 +		if(i >= 0 && x1 > x0) {
   8.125 +#ifdef PALMODE
   8.126 +			fill_scanline_pal(i, x0, x1, (uint8_t)color);
   8.127 +#else
   8.128 +			fill_scanline_rgb(i, x0, x1, color);
   8.129 +#endif
   8.130 +		}
   8.131 +
   8.132  		lx += ldxdy;
   8.133  		rx += rdxdy;
   8.134  		y += 65536;
   8.135  	}
   8.136  }
   8.137  
   8.138 -static void fill_scanline(int y, int x0, int x1, uint16_t color)
   8.139 +
   8.140 +static void fill_scanline_pal(int y, int x0, int x1, uint8_t color)
   8.141 +{
   8.142 +#if 1
   8.143 +	int i, num_pairs, num_pix = x1 - x0;
   8.144 +	uint16_t *pixels = (uint16_t*)back_buffer->pixels + (y * WIDTH + x0) / 2;
   8.145 +	uint16_t colpair = (uint16_t)color | ((uint16_t)color << 8);
   8.146 +
   8.147 +	if(x0 & 1) {
   8.148 +		uint16_t pix = *pixels & 0xff;
   8.149 +		*pixels++ = pix | ((uint16_t)color << 8);
   8.150 +		--num_pix;
   8.151 +	}
   8.152 +
   8.153 +	num_pairs = (num_pix & 0xfffe) / 2;
   8.154 +
   8.155 +	for(i=0; i<num_pairs; i++) {
   8.156 +		*pixels++ = colpair;
   8.157 +	}
   8.158 +
   8.159 +	if(num_pix & 1) {
   8.160 +		uint16_t pix = *pixels & 0xff00;
   8.161 +		*pixels = pix | color;
   8.162 +	}
   8.163 +#else
   8.164 +	int i;
   8.165 +	uint8_t *pixels = (uint8_t*)back_buffer->pixels + y * WIDTH + x0;
   8.166 +
   8.167 +	for(i=x0; i<x1; i++) {
   8.168 +		*pixels++ = color;
   8.169 +	}
   8.170 +#endif
   8.171 +}
   8.172 +
   8.173 +static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color)
   8.174  {
   8.175  	int i;
   8.176  	uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0;
   8.177 @@ -108,5 +176,14 @@
   8.178  		return;
   8.179  	}
   8.180  
   8.181 +#ifdef PALMODE
   8.182 +	pixels += (y * WIDTH + x) / 2;
   8.183 +	if(x & 1) {
   8.184 +		*pixels = (*pixels & 0xff) | (color << 8);
   8.185 +	} else {
   8.186 +		*pixels = (*pixels & 0xff00) | color;
   8.187 +	}
   8.188 +#else
   8.189  	pixels[y * WIDTH + x] = color;
   8.190 +#endif
   8.191  }
     9.1 --- a/src/sdlsys/gbasys.h	Thu Jun 19 05:53:46 2014 +0300
     9.2 +++ b/src/sdlsys/gbasys.h	Sun Jun 22 05:16:10 2014 +0300
     9.3 @@ -22,6 +22,7 @@
     9.4  /* defined in main_sdl.c */
     9.5  void flip(void);
     9.6  void clear_buffer(struct pixel_buffer *pbuf, unsigned short color);
     9.7 +void set_palette(int idx, int r, int g, int b);
     9.8  
     9.9  /* ---- fake gbasys/input.h ---- */
    9.10  enum {
    10.1 --- a/src/x3d.c	Thu Jun 19 05:53:46 2014 +0300
    10.2 +++ b/src/x3d.c	Sun Jun 22 05:16:10 2014 +0300
    10.3 @@ -1,3 +1,4 @@
    10.4 +#include "config.h"
    10.5  #include <string.h>
    10.6  #include "x3d.h"
    10.7  #include "fixed.h"
    10.8 @@ -33,6 +34,7 @@
    10.9  static unsigned short color_count;
   10.10  
   10.11  static int32_t im_color[3];
   10.12 +static uint8_t im_color_index;
   10.13  
   10.14  void x3d_projection(int32_t fov, int32_t aspect, int32_t nearz, int32_t farz)
   10.15  {
   10.16 @@ -155,7 +157,10 @@
   10.17  	int i, j, pverts = prim;
   10.18  	const int32_t *vptr = vertex_array;
   10.19  	const int32_t *cptr = color_array;
   10.20 +#ifndef PALMODE
   10.21  	short cr, cg, cb;
   10.22 +#endif
   10.23 +	uint16_t color;
   10.24  
   10.25  	if(!vertex_array) return -1;
   10.26  
   10.27 @@ -181,6 +186,9 @@
   10.28  			if(cptr) cptr += 3;
   10.29  		}
   10.30  
   10.31 +#ifdef PALMODE
   10.32 +		color = im_color_index;
   10.33 +#else
   10.34  		cr = col[0].x >> 8;
   10.35  		cg = col[0].y >> 8;
   10.36  		cb = col[0].z >> 8;
   10.37 @@ -189,9 +197,12 @@
   10.38  		if(cg > 255) cg = 255;
   10.39  		if(cb > 255) cb = 255;
   10.40  
   10.41 +		color = RGB(cr, cg, cb);
   10.42 +#endif
   10.43 +
   10.44  		switch(pverts) {
   10.45  		case X3D_POINTS:
   10.46 -			draw_point(vpos, RGB(cr, cg, cb));
   10.47 +			draw_point(vpos, color);
   10.48  			break;
   10.49  
   10.50  		case X3D_LINES:
   10.51 @@ -199,7 +210,7 @@
   10.52  
   10.53  		case X3D_TRIANGLES:
   10.54  		case X3D_QUADS:
   10.55 -			draw_poly(pverts, vpos, RGB(cr, cg, cb));
   10.56 +			draw_poly(pverts, vpos, color);
   10.57  			break;
   10.58  		}
   10.59  	}
   10.60 @@ -239,6 +250,11 @@
   10.61  	}
   10.62  }
   10.63  
   10.64 +void x3d_color_index(int cidx)
   10.65 +{
   10.66 +	im_color_index = cidx;
   10.67 +}
   10.68 +
   10.69  void x3d_color(int32_t r, int32_t g, int32_t b)
   10.70  {
   10.71  	im_color[0] = r;
    11.1 --- a/src/x3d.h	Thu Jun 19 05:53:46 2014 +0300
    11.2 +++ b/src/x3d.h	Sun Jun 22 05:16:10 2014 +0300
    11.3 @@ -25,6 +25,7 @@
    11.4  void x3d_color_array(int count, const int32_t *ptr);
    11.5  int x3d_draw_arrays(int prim, int vnum);
    11.6  
    11.7 +void x3d_color_index(int cidx);
    11.8  void x3d_color(int32_t r, int32_t g, int32_t b);
    11.9  
   11.10  #endif	/* X3D_H_ */