# HG changeset patch
# User John Tsiombikas <nuclear@member.fsf.org>
# Date 1403403370 -10800
# Node ID b0ed38f13261ce6da063c0100fd90d0586101d04
# Parent  fb0a0d6a8b5271c28e58f7a4918bf95f444ff26f
working on the rasterizer

diff -r fb0a0d6a8b52 -r b0ed38f13261 Makefile.sdl
--- a/Makefile.sdl	Thu Jun 19 05:53:46 2014 +0300
+++ b/Makefile.sdl	Sun Jun 22 05:16:10 2014 +0300
@@ -4,7 +4,9 @@
 dep = $(obj:.o=.d)
 bin = trycatch
 
-CFLAGS = -pedantic -Wall -g `pkg-config sdl --cflags` -Isrc -Isrc/sdlsys
+warn = -Wall -Wno-unused-function
+
+CFLAGS = -pedantic $(warn) -g `pkg-config sdl --cflags` -Isrc -Isrc/sdlsys
 LDFLAGS = `pkg-config sdl --libs` -lm
 
 $(bin): $(obj)
@@ -13,6 +15,11 @@
 %.x86.o: %.c
 	$(CC) $(CFLAGS) -o $@ -c $<
 
+-include $(dep)
+
+%.x86.d: %.c
+	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
+
 .PHONY: clean
 clean:
 	rm -f $(obj) $(bin)
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/config.h
--- a/src/config.h	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/config.h	Sun Jun 22 05:16:10 2014 +0300
@@ -1,8 +1,24 @@
 #ifndef CONFIG_H_
 #define CONFIG_H_
 
-#define GFX_MODE	VMODE_LFB_160x128_16
+#include "gbasys.h"
+
+/* 3: 240x160:16
+ * 4: 240x160:8
+ * 5: 160x128:16
+ */
+#define GFX_MODE	5
+
+#if (GFX_MODE == 3) || (GFX_MODE == 4)
+#define WIDTH		240
+#define HEIGHT		160
+#else
 #define WIDTH		160
 #define HEIGHT		128
+#endif
+
+#if (GFX_MODE == 4)
+#define PALMODE
+#endif
 
 #endif	/* CONFIG_H_ */
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/game.c
--- a/src/game.c	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/game.c	Sun Jun 22 05:16:10 2014 +0300
@@ -4,23 +4,32 @@
 #include "x3d.h"
 #include "sincos.h"
 #include "fixed.h"
+#include "palman.h"
+
+static void draw_rect(int x, int y, int w, int h, uint16_t color);
 
 #define X16INT(x)	((x) << 16)
 
 static const int32_t poly[] = {
-	X16INT(80), X16INT(10), 0,
-	X16INT(140), X16INT(100), 0,
-	X16INT(40), X16INT(80), 0
+	X16INT(120), X16INT(20), 0,
+	X16INT(200), X16INT(130), 0,
+	X16INT(40), X16INT(100), 0
 };
 static const short vcount = sizeof poly / sizeof *poly / 3;
 
 int game_init(void)
 {
 	sincos_init();
+#ifdef PALMODE
+	palman_init();
+#endif
 
 	return 0;
 }
 
+static short keyrot;
+static int autorot = 1;
+
 void game_draw(void)
 {
 	unsigned long msec = get_millisec();
@@ -29,22 +38,119 @@
 
 	x3d_load_identity();
 	x3d_translate(-itox16(WIDTH / 2), -itox16(HEIGHT / 2), 0);
-	x3d_rotate((msec / 64) << 16, 0, 0, 65536);
+	if(autorot) {
+		x3d_rotate((msec / 64) << 16, 0, 0, 65536);
+	} else {
+		x3d_rotate(keyrot << 16, 0, 0, 65536);
+	}
 	x3d_translate(itox16(WIDTH / 2), itox16(HEIGHT / 2), 0);
 
 	x3d_vertex_array(vcount, poly);
 
+#ifdef PALMODE
+	x3d_color_index(255);
+#else
 	x3d_color(65536, 65536, 65536);
+#endif
 	x3d_draw_arrays(X3D_TRIANGLES, vcount);
 
+#ifdef PALMODE
+	x3d_color_index(RGBPAL(0, 255, 0));
+#else
 	x3d_color(0, 65536, 0);
+#endif
 	x3d_draw_arrays(X3D_POINTS, vcount);
+	x3d_vertex_array(0, 0);
 
-	x3d_vertex_array(0, 0);
+	draw_rect(0, 0, WIDTH, HEIGHT, RGBPAL(255, 0, 0));
+	draw_rect(1, 1, WIDTH - 2, HEIGHT - 2, RGBPAL(0, 255, 0));
+	draw_rect(2, 2, WIDTH - 4, HEIGHT - 4, RGBPAL(32, 64, 255));
 
 	flip();
 }
 
 void game_keyb(int key, int pressed)
 {
+	if(!pressed) return;
+
+	switch(key) {
+	case KEY_LEFT:
+		keyrot--;
+		break;
+
+	case KEY_RIGHT:
+		keyrot++;
+		break;
+
+	case KEY_A:
+		autorot = !autorot;
+		break;
+
+	default:
+		break;
+	}
 }
+
+#ifdef PALMODE
+#define ROWADV	(WIDTH / 2)
+#else
+#define ROWADV	WIDTH
+#endif
+
+static void draw_rect(int x, int y, int w, int h, uint16_t color)
+{
+	int i, xsz = w, ysz = h;
+	uint16_t *pixels = back_buffer->pixels;
+	uint16_t *topleft, *topright, *botleft;
+
+#ifdef PALMODE
+	pixels += (y * WIDTH + x) / 2;
+	topleft = pixels;
+	topright = (uint16_t*)back_buffer->pixels + (y * WIDTH + x + w - 1) / 2;
+
+	color |= color << 8;
+	xsz /= 2;
+#else
+	pixels += y * WIDTH + x;
+	topleft = pixels;
+	topright = topleft + w - 1;
+#endif
+	botleft = topleft + (ysz - 1) * ROWADV;
+
+#ifdef PALMODE
+	if(x & 1) {
+		*topleft = (*topleft & 0xff) | (color & 0xff00);
+		*botleft = (*topleft & 0xff) | (color & 0xff00);
+		++topleft;
+		++botleft;
+		xsz -= 1;
+	}
+#endif
+	for(i=0; i<xsz; i++) {
+		*topleft++ = color;
+		*botleft++ = color;
+	}
+
+	topleft = pixels;
+	for(i=0; i<ysz; i++) {
+#ifdef PALMODE
+		if(x & 1) {
+			*topleft = (*topleft & 0xff) | (color & 0xff00);
+		} else {
+			*topleft = (*topleft & 0xff00) | (color & 0xff);
+		}
+
+		if((x + w - 1) & 1) {
+			*topright = (*topright & 0xff) | (color & 0xff00);
+		} else {
+			*topright = (*topright & 0xff00) | (color & 0xff);
+		}
+#else
+		*topleft = color;
+		*topright = color;
+#endif
+
+		topleft += ROWADV;
+		topright += ROWADV;
+	}
+}
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/main.c
--- a/src/main.c	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/main.c	Sun Jun 22 05:16:10 2014 +0300
@@ -20,7 +20,7 @@
 
 	interrupt(INTR_KEY, keyb_intr);
 
-	set_video_mode(VMODE_LFB_160x128_16, 1);
+	set_video_mode(GFX_MODE, 1);
 
 	clear_buffer(front_buffer, 0);
 	set_text_writebg(1);
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/main_sdl.c
--- a/src/main_sdl.c	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/main_sdl.c	Sun Jun 22 05:16:10 2014 +0300
@@ -5,6 +5,14 @@
 #include "gbasys.h"
 #include "game.h"
 
+#ifdef PALMODE
+#define BPP		8
+#define PIXSZ	1
+#else
+#define BPP		16
+#define PIXSZ	2
+#endif
+
 static int proc_events(SDL_Event *ev);
 static void handle_keyboard(int key, int state);
 
@@ -29,7 +37,7 @@
 
 	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
 
-	if(!(surf = SDL_SetVideoMode(WIDTH * sdlscale, HEIGHT * sdlscale, 16, SDL_SWSURFACE))) {
+	if(!(surf = SDL_SetVideoMode(WIDTH * sdlscale, HEIGHT * sdlscale, BPP, SDL_SWSURFACE))) {
 		fprintf(stderr, "failed to initialize graphics\n");
 		return 1;
 	}
@@ -37,8 +45,8 @@
 
 	bbuf.x = WIDTH;
 	bbuf.y = HEIGHT;
-	bbuf.bpp = 16;
-	if(!(bbuf.pixels = malloc(WIDTH * HEIGHT * 2))) {
+	bbuf.bpp = BPP;
+	if(!(bbuf.pixels = malloc(WIDTH * HEIGHT * PIXSZ))) {
 		fprintf(stderr, "failed to allocate framebuffer (%dx%d)\n", WIDTH, HEIGHT);
 		SDL_Quit();
 		return 1;
@@ -53,7 +61,11 @@
 
 	for(;;) {
 		SDL_Event ev;
+#ifdef PALMODE
+		uint8_t *dest, *src;
+#else
 		uint16_t *dest, *src;
+#endif
 
 		while(SDL_PollEvent(&ev)) {
 			if(proc_events(&ev) == -1) {
@@ -102,14 +114,32 @@
 
 void clear_buffer(struct pixel_buffer *pbuf, unsigned short color)
 {
-	int i;
+	int i, sz = pbuf->x * pbuf->y;
 	unsigned short *pixels = pbuf->pixels;
 
-	for(i=0; i<pbuf->x * pbuf->y; i++) {
+#ifdef PALMODE
+	color |= color << 8;
+	sz /= 2;
+#endif
+
+	for(i=0; i<sz; i++) {
 		*pixels++ = color;
 	}
 }
 
+void set_palette(int idx, int r, int g, int b)
+{
+	SDL_Color col;
+	col.r = r;
+	col.g = g;
+	col.b = b;
+
+	if(SDL_SetPalette(surf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) {
+		fprintf(stderr, "set_palette failed to set the required color\n");
+	}
+}
+
+
 int get_key_state(int key)
 {
 	return keystate & key;
@@ -125,7 +155,7 @@
 	switch(ev->type) {
 	case SDL_KEYDOWN:
 	case SDL_KEYUP:
-		handle_keyboard(ev->key.keysym.sym, ev->key.state == SDL_KEYDOWN);
+		handle_keyboard(ev->key.keysym.sym, ev->key.state);
 		break;
 
 	case SDL_QUIT:
@@ -173,6 +203,7 @@
 		break;
 
 	case '\n':
+	case '\r':
 		gba_key = KEY_A;
 		break;
 	case '\b':
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/palman.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/palman.c	Sun Jun 22 05:16:10 2014 +0300
@@ -0,0 +1,16 @@
+#include "gbasys.h"
+#include "palman.h"
+
+void palman_init(void)
+{
+	int i;
+
+	for(i=0; i<255; i++) {
+		int r = GET_R_PAL(i);
+		int g = GET_G_PAL(i);
+		int b = GET_B_PAL(i);
+
+		set_palette(i, r, g, b);
+	}
+	set_palette(255, 255, 255, 255);
+}
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/palman.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/palman.h	Sun Jun 22 05:16:10 2014 +0300
@@ -0,0 +1,13 @@
+#ifndef PALMAN_H_
+#define PALMAN_H_
+
+#define RGBPAL(r, g, b)	\
+	(((r) & 0xe0) | (((g) >> 3) & 0x1c) | (((b) >> 6) & 0x3))
+
+#define GET_R_PAL(c)	((c) & 0xe0)
+#define GET_G_PAL(c)	(((c) & 0x1c) << 3)
+#define GET_B_PAL(c)	(((c) & 0x3) << 6)
+
+void palman_init(void);
+
+#endif	/* PALMAN_H_ */
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/polyfill.c
--- a/src/polyfill.c	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/polyfill.c	Sun Jun 22 05:16:10 2014 +0300
@@ -5,14 +5,18 @@
 #include "fixed.h"
 #include "gbasys.h"
 
-static void fill_scanline(int y, int x0, int x1, uint16_t color);
+#define VNEXT(x, n)		(((x) + 1) % (n))
+#define VPREV(x, n)		((x) > 0 ? (x) - 1 : (n) - 1)
+
+static void fill_scanline_pal(int y, int x0, int x1, uint8_t color);
+static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color);
 
 void draw_poly(int num, const pvec3 *verts, uint16_t color)
 {
 	int i, topidx = 0, botidx = 0;
-	int lidx[2], ridx[2];
+	int lidx[2] = {-1, -1}, ridx[2] = {-1, -1};
 	int32_t y, topy, boty;
-	int32_t ldy, rdy, ldxdy, rdxdy;
+	int32_t ldy = 0, rdy = 0, ldxdy, rdxdy;
 	int32_t lx, rx;
 	int start, end;
 
@@ -30,22 +34,46 @@
 	}
 
 	lidx[0] = ridx[0] = topidx;
-	lidx[1] = topidx ? topidx - 1 : num - 1;
-	ridx[1] = (topidx + 1) % num;
+
+	/* find starting left edge */
+	lidx[1] = VPREV(lidx[0], num);
+	ldy = verts[lidx[1]].y - verts[lidx[0]].y;
+
+	while(ldy == 0) {
+		lidx[0] = lidx[1];
+		lidx[1] = VPREV(lidx[1], num);
+
+		if(lidx[1] == topidx) {
+			return;	/* degenerate */
+		}
+
+		ldy = verts[lidx[1]].y - verts[lidx[0]].y;
+	}
+	lx = verts[lidx[0]].x;
+	ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
+
+	/* find starting right edge */
+	ridx[1] = VNEXT(ridx[0], num);
+	rdy = verts[ridx[1]].y - verts[ridx[0]].y;
+
+	while(rdy == 0) {
+		ridx[0] = ridx[1];
+		ridx[1] = VNEXT(ridx[1], num);
+
+		if(ridx[1] == topidx) {
+			return; /* degenerate */
+		}
+
+		rdy = verts[ridx[1]].y - verts[ridx[0]].y;
+	}
+	rx = verts[ridx[0]].x;
+	rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
+
 
 	if(verts[ridx[1]].x < verts[lidx[1]].x) {
-		return;	/* backface (CCW) */
+		return;	/*  backface (CCW) */
 	}
 
-	lx = rx = verts[lidx[0]].x;
-
-	/* TODO handle ldy == 0 or rdy == 0 */
-	ldy = verts[lidx[1]].y - verts[lidx[0]].y;
-	ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
-
-	rdy = verts[ridx[1]].y - verts[ridx[0]].y;
-	rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
-
 	start = topy >> 16;
 	end = boty >> 16;
 
@@ -53,18 +81,12 @@
 
 	y = topy;
 	for(i=start; i<end; i++) {
-		unsigned short x0, x1;
-
-		x0 = lx < 0 ? 0 : (lx >> 16);
-		x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
-
-		if(i >= 0 && x1 > x0) {
-			fill_scanline(i, x0, x1, color);
-		}
+		short x0, x1;
 
 		if(y >= verts[lidx[1]].y) {
+			lx = verts[lidx[1]].x;
 			lidx[0] = lidx[1];
-			lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1;
+			lidx[1] = VPREV(lidx[1], num);
 			ldy = verts[lidx[1]].y - verts[lidx[0]].y;
 			if(ldy < 0) {
 				break;
@@ -72,8 +94,9 @@
 			ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
 		}
 		if(y >= verts[ridx[1]].y) {
+			rx = verts[ridx[1]].x;
 			ridx[0] = ridx[1];
-			ridx[1] = (ridx[1] + 1) % num;
+			ridx[1] = VNEXT(ridx[1], num);
 			rdy = verts[ridx[1]].y - verts[ridx[0]].y;
 			if(rdy < 0) {
 				break;
@@ -81,13 +104,58 @@
 			rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
 		}
 
+		x0 = lx < 0 ? 0 : (lx >> 16);
+		x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
+
+		if(i >= 0 && x1 > x0) {
+#ifdef PALMODE
+			fill_scanline_pal(i, x0, x1, (uint8_t)color);
+#else
+			fill_scanline_rgb(i, x0, x1, color);
+#endif
+		}
+
 		lx += ldxdy;
 		rx += rdxdy;
 		y += 65536;
 	}
 }
 
-static void fill_scanline(int y, int x0, int x1, uint16_t color)
+
+static void fill_scanline_pal(int y, int x0, int x1, uint8_t color)
+{
+#if 1
+	int i, num_pairs, num_pix = x1 - x0;
+	uint16_t *pixels = (uint16_t*)back_buffer->pixels + (y * WIDTH + x0) / 2;
+	uint16_t colpair = (uint16_t)color | ((uint16_t)color << 8);
+
+	if(x0 & 1) {
+		uint16_t pix = *pixels & 0xff;
+		*pixels++ = pix | ((uint16_t)color << 8);
+		--num_pix;
+	}
+
+	num_pairs = (num_pix & 0xfffe) / 2;
+
+	for(i=0; i<num_pairs; i++) {
+		*pixels++ = colpair;
+	}
+
+	if(num_pix & 1) {
+		uint16_t pix = *pixels & 0xff00;
+		*pixels = pix | color;
+	}
+#else
+	int i;
+	uint8_t *pixels = (uint8_t*)back_buffer->pixels + y * WIDTH + x0;
+
+	for(i=x0; i<x1; i++) {
+		*pixels++ = color;
+	}
+#endif
+}
+
+static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color)
 {
 	int i;
 	uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0;
@@ -108,5 +176,14 @@
 		return;
 	}
 
+#ifdef PALMODE
+	pixels += (y * WIDTH + x) / 2;
+	if(x & 1) {
+		*pixels = (*pixels & 0xff) | (color << 8);
+	} else {
+		*pixels = (*pixels & 0xff00) | color;
+	}
+#else
 	pixels[y * WIDTH + x] = color;
+#endif
 }
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/sdlsys/gbasys.h
--- a/src/sdlsys/gbasys.h	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/sdlsys/gbasys.h	Sun Jun 22 05:16:10 2014 +0300
@@ -22,6 +22,7 @@
 /* defined in main_sdl.c */
 void flip(void);
 void clear_buffer(struct pixel_buffer *pbuf, unsigned short color);
+void set_palette(int idx, int r, int g, int b);
 
 /* ---- fake gbasys/input.h ---- */
 enum {
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/x3d.c
--- a/src/x3d.c	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/x3d.c	Sun Jun 22 05:16:10 2014 +0300
@@ -1,3 +1,4 @@
+#include "config.h"
 #include <string.h>
 #include "x3d.h"
 #include "fixed.h"
@@ -33,6 +34,7 @@
 static unsigned short color_count;
 
 static int32_t im_color[3];
+static uint8_t im_color_index;
 
 void x3d_projection(int32_t fov, int32_t aspect, int32_t nearz, int32_t farz)
 {
@@ -155,7 +157,10 @@
 	int i, j, pverts = prim;
 	const int32_t *vptr = vertex_array;
 	const int32_t *cptr = color_array;
+#ifndef PALMODE
 	short cr, cg, cb;
+#endif
+	uint16_t color;
 
 	if(!vertex_array) return -1;
 
@@ -181,6 +186,9 @@
 			if(cptr) cptr += 3;
 		}
 
+#ifdef PALMODE
+		color = im_color_index;
+#else
 		cr = col[0].x >> 8;
 		cg = col[0].y >> 8;
 		cb = col[0].z >> 8;
@@ -189,9 +197,12 @@
 		if(cg > 255) cg = 255;
 		if(cb > 255) cb = 255;
 
+		color = RGB(cr, cg, cb);
+#endif
+
 		switch(pverts) {
 		case X3D_POINTS:
-			draw_point(vpos, RGB(cr, cg, cb));
+			draw_point(vpos, color);
 			break;
 
 		case X3D_LINES:
@@ -199,7 +210,7 @@
 
 		case X3D_TRIANGLES:
 		case X3D_QUADS:
-			draw_poly(pverts, vpos, RGB(cr, cg, cb));
+			draw_poly(pverts, vpos, color);
 			break;
 		}
 	}
@@ -239,6 +250,11 @@
 	}
 }
 
+void x3d_color_index(int cidx)
+{
+	im_color_index = cidx;
+}
+
 void x3d_color(int32_t r, int32_t g, int32_t b)
 {
 	im_color[0] = r;
diff -r fb0a0d6a8b52 -r b0ed38f13261 src/x3d.h
--- a/src/x3d.h	Thu Jun 19 05:53:46 2014 +0300
+++ b/src/x3d.h	Sun Jun 22 05:16:10 2014 +0300
@@ -25,6 +25,7 @@
 void x3d_color_array(int count, const int32_t *ptr);
 int x3d_draw_arrays(int prim, int vnum);
 
+void x3d_color_index(int cidx);
 void x3d_color(int32_t r, int32_t g, int32_t b);
 
 #endif	/* X3D_H_ */