All pastes #222786 Raw Edit

Gnuboy2x

public c v1 · immutable
#222786 ·published 2006-10-26 15:13 UTC
rendered paste body
#include "defs.h"#include "regs.h"#include "hw.h"#include "mem.h"#include "lcd.h"#include "rc.h"#include "fb.h"#ifdef USE_ASM#include "asm.h"#endifstruct lcd lcd;struct scan scan;typedef struct{	int usapaleta;	int volumen;	int scaling;	int sound;	int framelimit;	} opciones;extern opciones optbuffer;#define BG (scan.bg)#define WND (scan.wnd)#define BUF (scan.buf)#define PRI (scan.pri)#define PAL1 (scan.pal1)#define PAL2 (scan.pal2)#define PAL4 (scan.pal4)#define VS (scan.vs) /* vissprites */#define NS (scan.ns)#define L (scan.l) /* line */#define X (scan.x) /* screen position */#define Y (scan.y)#define S (scan.s) /* tilemap position */#define T (scan.t)#define U (scan.u) /* position within tile */#define V (scan.v)#define WX (scan.wx)#define WY (scan.wy)#define WT (scan.wt)#define WV (scan.wv)byte patpix[4096][8][8];byte patdirty[1024];byte anydirty;static int scale = 1;static int density = 0;static int rgb332;static int sprsort = 1;static int sprdebug;/* Aqui esta la informacion de la paleta, si no lo entiendes (que lo dudo) me preguntaspero vamos, basicamente es definir 4 colores en cada define, de mas claro a mas oscuroy luego decirle que use el esquema de color que tu le digas para cada plano de la gameboy,que son cuatro, asi que tenemos por ejemplo def_pal, y luego hacemos una paleta con ese esquema poniendo el mismo en cada uno de los planos*/#define DEF_PAL { 0x98d0e0, 0x68a0b0, 0x60707C, 0x2C3C3C }// de mas claro a mas oscuro#define DEF_PAL1  { 0x9fbfa7, 0x7f9986, 0x6a8070, 0x556659 } //verdes#define DEF_PAL2  { 0xd9d9d9, 0xb2b2b2, 0x8c8c8c, 0x666666 } //grises#define DEF_PAL3 { 0xFFFFFF, 0xa6a6a6, 0x595959, 0x000000 }  //alto contraste/*Aqui estan descritos los 4 planos de la gameboy, puedes hacer esquemas de color definiendopaletas de 4 colores cada una (como arriba) y luego poniendo paletas distintas para cada uno de los planosLo que ves justo aqui debajo, es una paleta hecha a mano con colores distintos para cada paleta de cada plano.*/unsigned int custom_pal[4][4] = {{0xaadddd, 0xdd7777, 0x772222, 0x220000}, //fondo						{0xdddddd, 0xaaaaaa, 0x777777, 0x222222}, //overlay						{0xddaadd, 0xaa77aa, 0x772277, 0x220022}, //sprites1						{0xdddddd, 0xaaaaaa, 0x777777, 0x222222}}; //sprites2/*Y esto son paletas con los mismos colores para cada plano, es lo mismo de arriba, pero usando los defines*/int dmg_pal[4][4] = { DEF_PAL1, DEF_PAL1, DEF_PAL1, DEF_PAL1 };int dmg_pal1[4][4] = { DEF_PAL1, DEF_PAL1, DEF_PAL1, DEF_PAL1 };int dmg_pal2[4][4] = { DEF_PAL2, DEF_PAL2, DEF_PAL2, DEF_PAL2 };int dmg_pal3[4][4] = { DEF_PAL3, DEF_PAL3, DEF_PAL3, DEF_PAL3 };static int usefilter, filterdmg;static int filter[3][4] = {	{ 195,  25,   0,  35 },	{  25, 170,  25,  35 },	{  25,  60, 125,  40 }};rcvar_t lcd_exports[] ={	RCV_INT("scale", &scale),	RCV_INT("density", &density),	RCV_BOOL("rgb332", &rgb332),	RCV_VECTOR("dmg_bgp", dmg_pal[0], 4),	RCV_VECTOR("dmg_wndp", dmg_pal[1], 4),	RCV_VECTOR("dmg_obp0", dmg_pal[2], 4),	RCV_VECTOR("dmg_obp1", dmg_pal[3], 4),	RCV_BOOL("sprsort", &sprsort),	RCV_BOOL("sprdebug", &sprdebug),	RCV_BOOL("colorfilter", &usefilter),	RCV_BOOL("filterdmg", &filterdmg),	RCV_VECTOR("red", filter[0], 4),	RCV_VECTOR("green", filter[1], 4),	RCV_VECTOR("blue", filter[2], 4),	RCV_END};static byte *vdest;#ifdef ALLOW_UNALIGNED_IO /* long long is ok since this is i386-only anyway? */#define MEMCPY8(d, s) ((*(long long *)(d)) = (*(long long *)(s)))#else#define MEMCPY8(d, s) memcpy((d), (s), 8)#endif#ifndef ASM_UPDATEPATPIXvoid updatepatpix(){	int i, j, k;	int a, c;	byte *vram = lcd.vbank[0];		if (!anydirty) return;	for (i = 0; i < 1024; i++)	{		if (i == 384) i = 512;		if (i == 896) break;		if (!patdirty[i]) continue;		patdirty[i] = 0;		for (j = 0; j < 8; j++)		{			a = ((i<<4) | (j<<1));			for (k = 0; k < 8; k++)			{				c = vram[a] & (1<<k) ? 1 : 0;				c |= vram[a+1] & (1<<k) ? 2 : 0;				patpix[i+1024][j][k] = c;			}			for (k = 0; k < 8; k++)				patpix[i][j][k] =					patpix[i+1024][j][7-k];		}		for (j = 0; j < 8; j++)		{			for (k = 0; k < 8; k++)			{				patpix[i+2048][j][k] =					patpix[i][7-j][k];				patpix[i+3072][j][k] =					patpix[i+1024][7-j][k];			}		}	}	anydirty = 0;}#endif /* ASM_UPDATEPATPIX */void tilebuf(){	int i, cnt;	int base;	byte *tilemap, *attrmap;	int *tilebuf;	int *wrap;	static int wraptable[64] =	{		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,-32	};	base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;	tilemap = lcd.vbank[0] + base;	attrmap = lcd.vbank[1] + base;	tilebuf = BG;	wrap = wraptable + S;	cnt = ((WX + 7) >> 3) + 1;	if (hw.cgb)	{		if (R_LCDC & 0x10)			for (i = cnt; i > 0; i--)			{				*(tilebuf++) = *tilemap					| (((int)*attrmap & 0x08) << 6)					| (((int)*attrmap & 0x60) << 5);				*(tilebuf++) = (((int)*attrmap & 0x07) << 2);				attrmap += *wrap + 1;				tilemap += *(wrap++) + 1;			}		else			for (i = cnt; i > 0; i--)			{				*(tilebuf++) = (256 + ((n8)*tilemap))					| (((int)*attrmap & 0x08) << 6)					| (((int)*attrmap & 0x60) << 5);				*(tilebuf++) = (((int)*attrmap & 0x07) << 2);				attrmap += *wrap + 1;				tilemap += *(wrap++) + 1;			}	}	else	{		if (R_LCDC & 0x10)			for (i = cnt; i > 0; i--)			{				*(tilebuf++) = *(tilemap++);				tilemap += *(wrap++);			}		else			for (i = cnt; i > 0; i--)			{				*(tilebuf++) = (256 + ((n8)*(tilemap++)));				tilemap += *(wrap++);			}	}	if (WX >= 160) return;		base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);	tilemap = lcd.vbank[0] + base;	attrmap = lcd.vbank[1] + base;	tilebuf = WND;	cnt = ((160 - WX) >> 3) + 1;	if (hw.cgb)	{		if (R_LCDC & 0x10)			for (i = cnt; i > 0; i--)			{				*(tilebuf++) = *(tilemap++)					| (((int)*attrmap & 0x08) << 6)					| (((int)*attrmap & 0x60) << 5);				*(tilebuf++) = (((int)*(attrmap++)&7) << 2);			}		else			for (i = cnt; i > 0; i--)			{				*(tilebuf++) = (256 + ((n8)*(tilemap++)))					| (((int)*attrmap & 0x08) << 6)					| (((int)*attrmap & 0x60) << 5);				*(tilebuf++) = (((int)*(attrmap++)&7) << 2);			}	}	else	{		if (R_LCDC & 0x10)			for (i = cnt; i > 0; i--)				*(tilebuf++) = *(tilemap++);		else			for (i = cnt; i > 0; i--)				*(tilebuf++) = (256 + ((n8)*(tilemap++)));	}}void bg_scan(){	int cnt;	byte *src, *dest;	int *tile;	if (WX <= 0) return;	cnt = WX;	tile = BG;	dest = BUF;		src = patpix[*(tile++)][V] + U;	memcpy(dest, src, 8-U);	dest += 8-U;	cnt -= 8-U;	if (cnt <= 0) return;	while (cnt >= 8)	{		src = patpix[*(tile++)][V];		MEMCPY8(dest, src);		dest += 8;		cnt -= 8;	}	src = patpix[*tile][V];	while (cnt--)		*(dest++) = *(src++);}void wnd_scan(){	int cnt;	byte *src, *dest;	int *tile;	if (WX >= 160) return;	cnt = 160 - WX;	tile = WND;	dest = BUF + WX;		while (cnt >= 8)	{		src = patpix[*(tile++)][WV];		MEMCPY8(dest, src);		dest += 8;		cnt -= 8;	}	src = patpix[*tile][WV];	while (cnt--)		*(dest++) = *(src++);}static void blendcpy(byte *dest, byte *src, byte b, int cnt){	while (cnt--) *(dest++) = *(src++) | b;}static int priused(void *attr){	un32 *a = attr;	return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080);}void bg_scan_pri(){	int cnt, i;	byte *src, *dest;	if (WX <= 0) return;	i = S;	cnt = WX;	dest = PRI;	src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);	if (!priused(src))	{		memset(dest, 0, cnt);		return;	}		memset(dest, src[i++&31]&128, 8-U);	dest += 8-U;	cnt -= 8-U;	if (cnt <= 0) return;	while (cnt >= 8)	{		memset(dest, src[i++&31]&128, 8);		dest += 8;		cnt -= 8;	}	memset(dest, src[i&31]&128, cnt);}void wnd_scan_pri(){	int cnt, i;	byte *src, *dest;	if (WX >= 160) return;	i = 0;	cnt = 160 - WX;	dest = PRI + WX;	src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);		if (!priused(src))	{		memset(dest, 0, cnt);		return;	}		while (cnt >= 8)	{		memset(dest, src[i++]&128, 8);		dest += 8;		cnt -= 8;	}	memset(dest, src[i]&128, cnt);}#ifndef ASM_BG_SCAN_COLORvoid bg_scan_color(){	int cnt;	byte *src, *dest;	int *tile;	if (WX <= 0) return;	cnt = WX;	tile = BG;	dest = BUF;		src = patpix[*(tile++)][V] + U;	blendcpy(dest, src, *(tile++), 8-U);	dest += 8-U;	cnt -= 8-U;	if (cnt <= 0) return;	while (cnt >= 8)	{		src = patpix[*(tile++)][V];		blendcpy(dest, src, *(tile++), 8);		dest += 8;		cnt -= 8;	}	src = patpix[*(tile++)][V];	blendcpy(dest, src, *(tile++), cnt);}#endifvoid wnd_scan_color(){	int cnt;	byte *src, *dest;	int *tile;	if (WX >= 160) return;	cnt = 160 - WX;	tile = WND;	dest = BUF + WX;		while (cnt >= 8)	{		src = patpix[*(tile++)][WV];		blendcpy(dest, src, *(tile++), 8);		dest += 8;		cnt -= 8;	}	src = patpix[*(tile++)][WV];	blendcpy(dest, src, *(tile++), cnt);}static void recolor(byte *buf, byte fill, int cnt){	while (cnt--) *(buf++) |= fill;}void spr_count(){	int i;	struct obj *o;		NS = 0;	if (!(R_LCDC & 0x02)) return;		o = lcd.oam.obj;		for (i = 40; i; i--, o++)	{		if (L >= o->y || L + 16 < o->y)			continue;		if (L + 8 >= o->y && !(R_LCDC & 0x04))			continue;		if (++NS == 10) break;	}}void spr_enum(){	int i, j;	struct obj *o;	struct vissprite ts[10];	int v, pat;	int l, x;	NS = 0;	if (!(R_LCDC & 0x02)) return;	o = lcd.oam.obj;		for (i = 40; i; i--, o++)	{		if (L >= o->y || L + 16 < o->y)			continue;		if (L + 8 >= o->y && !(R_LCDC & 0x04))			continue;		VS[NS].x = (int)o->x - 8;		v = L - (int)o->y + 16;		if (hw.cgb)		{			pat = o->pat | (((int)o->flags & 0x60) << 5)				| (((int)o->flags & 0x08) << 6);			VS[NS].pal = 32 + ((o->flags & 0x07) << 2);		}		else		{			pat = o->pat | (((int)o->flags & 0x60) << 5);			VS[NS].pal = 32 + ((o->flags & 0x10) >> 2);		}		VS[NS].pri = (o->flags & 0x80) >> 7;		if ((R_LCDC & 0x04))		{			pat &= ~1;			if (v >= 8)			{				v -= 8;				pat++;			}			if (o->flags & 0x40) pat ^= 1;		}		VS[NS].buf = patpix[pat][v];		if (++NS == 10) break;	}	if (!sprsort || hw.cgb) return;	/* not quite optimal but it finally works! */	for (i = 0; i < NS; i++)	{		l = 0;		x = VS[0].x;		for (j = 1; j < NS; j++)		{			if (VS[j].x < x)			{				l = j;				x = VS[j].x;			}		}		ts[i] = VS[l];		VS[l].x = 160;	}	memcpy(VS, ts, sizeof VS);}void spr_scan(){	int i, x;	byte pal, b, ns = NS;	byte *src, *dest, *bg, *pri;	struct vissprite *vs;	static byte bgdup[256];	if (!ns) return;	memcpy(bgdup, BUF, 256);	vs = &VS[ns-1];		for (; ns; ns--, vs--)	{		x = vs->x;		if (x >= 160) continue;		if (x <= -8) continue;		if (x < 0)		{			src = vs->buf - x;			dest = BUF;			i = 8 + x;		}		else		{			src = vs->buf;			dest = BUF + x;			if (x > 152) i = 160 - x;			else i = 8;		}		pal = vs->pal;		if (vs->pri)		{			bg = bgdup + (dest - BUF);			while (i--)			{				b = src[i];				if (b && !(bg[i]&3)) dest[i] = pal|b;			}		}		else if (hw.cgb)		{			bg = bgdup + (dest - BUF);			pri = PRI + (dest - BUF);			while (i--)			{				b = src[i];				if (b && (!pri[i] || !(bg[i]&3)))					dest[i] = pal|b;			}		}		else while (i--) if (src[i]) dest[i] = pal|src[i];		/* else while (i--) if (src[i]) dest[i] = 31 + ns; */	}	if (sprdebug) for (i = 0; i < NS; i++) BUF[i<<1] = 36;}void lcd_begin(){	if (fb.indexed)	{		if (rgb332) pal_set332();		else pal_expire();	}	while (scale * 160 > fb.w || scale * 144 > fb.h) scale--;	vdest = fb.ptr + ((fb.w*fb.pelsize)>>1)		- (80*fb.pelsize) * scale		+ ((fb.h>>1) - 72*scale) * fb.pitch;	WY = R_WY;}void lcd_refreshline(){	int i;	byte scalebuf[160*4*4], *dest;		if (!fb.enabled) return;		if (!(R_LCDC & 0x80))		return; /* should not happen... */		updatepatpix();	L = R_LY;	X = R_SCX;	Y = (R_SCY + L) & 0xff;	S = X >> 3;	T = Y >> 3;	U = X & 7;	V = Y & 7;		WX = R_WX - 7;	if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20))		WX = 160;	WT = (L - WY) >> 3;	WV = (L - WY) & 7;	spr_enum();	tilebuf();	if (hw.cgb)	{		bg_scan_color();		wnd_scan_color();		if (NS)		{			bg_scan_pri();			wnd_scan_pri();		}	}	else	{		bg_scan();		wnd_scan();		recolor(BUF+WX, 0x04, 160-WX);	}	spr_scan();	if (fb.dirty) memset(fb.ptr, 0, fb.pitch * fb.h);	fb.dirty = 0;	if (density > scale) density = scale;	if (scale == 1) density = 1;	dest = (density != 1) ? scalebuf : vdest;		switch (scale)	{	case 0:	case 1:		switch (fb.pelsize)		{		case 1:			refresh_1(dest, BUF, PAL1, 160);			break;		case 2:			refresh_2(dest, BUF, PAL2, 160);			break;		case 3:			refresh_3(dest, BUF, PAL4, 160);			break;		case 4:			refresh_4(dest, BUF, PAL4, 160);			break;		}		break;	case 2:		switch (fb.pelsize)		{		case 1:			refresh_2(dest, BUF, PAL2, 160);			break;		case 2:			refresh_4(dest, BUF, PAL4, 160);			break;		case 3:			refresh_3_2x(dest, BUF, PAL4, 160);			break;		case 4:			refresh_4_2x(dest, BUF, PAL4, 160);			break;		}		break;	case 3:		switch (fb.pelsize)		{		case 1:			refresh_3(dest, BUF, PAL4, 160);			break;		case 2:			refresh_2_3x(dest, BUF, PAL2, 160);			break;		case 3:			refresh_3_3x(dest, BUF, PAL4, 160);			break;		case 4:			refresh_4_3x(dest, BUF, PAL4, 160);			break;		}		break;	case 4:		switch (fb.pelsize)		{		case 1:			refresh_4(dest, BUF, PAL4, 160);			break;		case 2:			refresh_4_2x(dest, BUF, PAL4, 160);			break;		case 3:			refresh_3_4x(dest, BUF, PAL4, 160);			break;		case 4:			refresh_4_4x(dest, BUF, PAL4, 160);			break;		}		break;	default:		break;	}	if (density != 1)	{		for (i = 0; i < scale; i++)		{			if ((i < density) || ((density <= 0) && !(i&1)))				memcpy(vdest, scalebuf, 160 * fb.pelsize * scale);			vdest += fb.pitch;		}	}	else vdest += fb.pitch * scale;}static void updatepalette(int i){	int c, r, g, b, y, u, v, rr, gg;	c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF;	r = (c & 0x001F) << 3;	g = (c & 0x03E0) >> 2;	b = (c & 0x7C00) >> 7;	r |= (r >> 5);	g |= (g >> 5);	b |= (b >> 5);	if (usefilter && (filterdmg || hw.cgb))	{		rr = ((r * filter[0][0] + g * filter[0][1] + b * filter[0][2]) >> 8) + filter[0][3];		gg = ((r * filter[1][0] + g * filter[1][1] + b * filter[1][2]) >> 8) + filter[1][3];		b = ((r * filter[2][0] + g * filter[2][1] + b * filter[2][2]) >> 8) + filter[2][3];		r = rr;		g = gg;	}		if (fb.yuv)	{		y = (((r *  263) + (g * 516) + (b * 100)) >> 10) + 16;		u = (((r *  450) - (g * 377) - (b *  73)) >> 10) + 128;		v = (((r * -152) - (g * 298) + (b * 450)) >> 10) + 128;		if (y < 0) y = 0; if (y > 255) y = 255;		if (u < 0) u = 0; if (u > 255) u = 255;		if (v < 0) v = 0; if (v > 255) v = 255;		PAL4[i] = (y<<fb.cc[0].l) | (y<<fb.cc[3].l)			| (u<<fb.cc[1].l) | (v<<fb.cc[2].l);		return;	}		if (fb.indexed)	{		pal_release(PAL1[i]);		c = pal_getcolor(c, r, g, b);		PAL1[i] = c;		PAL2[i] = (c<<8) | c;		PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c;		return;	}	r = (r >> fb.cc[0].r) << fb.cc[0].l;	g = (g >> fb.cc[1].r) << fb.cc[1].l;	b = (b >> fb.cc[2].r) << fb.cc[2].l;	c = r|g|b;		switch (fb.pelsize)	{	case 1:		PAL1[i] = c;		PAL2[i] = (c<<8) | c;		PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c;		break;	case 2:		PAL2[i] = c;		PAL4[i] = (c<<16) | c;		break;	case 3:	case 4:		PAL4[i] = c;		break;	}}void pal_write(int i, byte b){	if (lcd.pal[i] == b) return;	lcd.pal[i] = b;	updatepalette(i>>1);}/*Esta es la funcion que activa la paleta que le digamos, si la comparas con la original veras latonteria de cambio que tiene.MUY IMPORTANTE: Cada vez que cambiemos la paleta, tenemos que usar la funcion pal_dirty() para quela actualice, o si vas a hacer cambios en mas cosas, lcd_reset() que esta mas abajo*/void pal_write_dmg(int i, int mapnum, byte d){	int j;	int *cmap;// = dmg_pal[mapnum];	int c, r, g, b;	if (optbuffer.usapaleta==0) cmap = custom_pal[mapnum];	if (optbuffer.usapaleta==1) cmap = dmg_pal1[mapnum];	if (optbuffer.usapaleta==2) cmap = dmg_pal2[mapnum];	if (optbuffer.usapaleta==3) cmap = dmg_pal3[mapnum];		if (hw.cgb) return;	/* if (mapnum >= 2) d = 0xe4; */	for (j = 0; j < 8; j += 2)	{		c = cmap[(d >> j) & 3];		r = (c & 0xf8) >> 3;		g = (c & 0xf800) >> 6;		b = (c & 0xf80000) >> 9;		c = r|g|b;		/* FIXME - handle directly without faking cgb */		pal_write(i+j, c & 0xff);		pal_write(i+j+1, c >> 8);	}}void vram_write(int a, byte b){	lcd.vbank[R_VBK&1][a] = b;	if (a >= 0x1800) return;	patdirty[((R_VBK&1)<<9)+(a>>4)] = 1;	anydirty = 1;}void vram_dirty(){	anydirty = 1;	memset(patdirty, 1, sizeof patdirty);}void pal_dirty(){	int i;	if (!hw.cgb)	{		pal_write_dmg(0, 0, R_BGP);		pal_write_dmg(8, 1, R_BGP);		pal_write_dmg(64, 2, R_OBP0);		pal_write_dmg(72, 3, R_OBP1);	}	for (i = 0; i < 64; i++)		updatepalette(i);}void lcd_reset(){	memset(&lcd, 0, sizeof lcd);	lcd_begin();	vram_dirty();	pal_dirty();}