Ejemplo n.º 1
0
Archivo: lcdc.c Proyecto: Jakz/ohboy
void stat_write(byte b)
{
	R_STAT = (R_STAT & 0x07) | (b & 0x78);
	if (!hw.cgb && !(R_STAT & 2)) /* DMG STAT write bug => interrupt */
		hw_interrupt(IF_STAT, IF_STAT);
	stat_trigger();
}
Ejemplo n.º 2
0
Archivo: lcdc.c Proyecto: Jakz/ohboy
 /* FIXME: function now will only lower vblank interrupt, description
does not match anymore */
static void stat_change(int stat)
{
	stat &= 3;
	R_STAT = (R_STAT & 0x7C) | stat;

	if (stat != 1) hw_interrupt(0, IF_VBLANK);
	/* hw_interrupt((stat == 1) ? IF_VBLANK : 0, IF_VBLANK); */
	stat_trigger();
}
Ejemplo n.º 3
0
Archivo: lcdc.c Proyecto: Jakz/ohboy
void stat_trigger()
{
	static const int condbits[4] = { 0x08, 0x10, 0x20, 0x00 };
	int flag = 0;

	if (R_LY == R_LYC)
	{
		R_STAT |= 0x04;
		if (R_STAT & 0x40) flag = IF_STAT;
	}
	else R_STAT &= ~0x04;

	if (R_STAT & condbits[R_STAT&3]) flag = IF_STAT;

	if (!(R_LCDC & 0x80)) flag = 0;
	
	hw_interrupt(flag, IF_STAT);
}
Ejemplo n.º 4
0
Archivo: lcdc.c Proyecto: Jakz/ohboy
/* lcdc_trans()
	Main LCDC emulation routine
*/
void lcdc_trans()
{
	if (R_LCDC & 0x80)
	{
		/* LCDC operation enabled */
		while (C <= 0)
		{
			/* Update current state */
			switch ((byte)(R_STAT & 3))
			{
				case 0: /* after hblank */
					/* FIXME: first line of first frame will be skipped
					each time LCDC is started */
					if (++R_LY <= 143)
					{
						stat_change(2); /* -> search */
					}
					else
					{
						stat_change(1); /* -> vblank */
						/* See "NOTE A" above */
						/*if (cpu.halt)
						{
							hw_interrupt(IF_VBLANK, IF_VBLANK);
							C += 228;
						}
						else
						{
							C += 10;
							continue;
						}*/
						break;
					}
					break;
				case 2:  /* after search */
					stat_change(3); /* -> transfer */
					break;
				case 3:  /* after transfer */
					stat_change(0); /* -> hblank */
					break;
				case 1: /* after (in) vblank */
					if (R_LY == 0)
					{
						stat_change(2); /* -> search */
					}
					break;
			}
			
			/* Handle current state */
			switch ((byte)(R_STAT & 3))
			{
				case 2:  /* search */
					if (R_LY == 0)
					{
						lcd_begin();
					}
					C += 40;
					break;
				case 3:  /* transfer */
					lcd_refreshline();
					C += 86;
					break;
				case 0: /* hblank */
					if (hw.hdma & 0x80) {
						hw_hdma();
					}
					C += 102;
					break;
				case 1: /* vblank */
					if (!(hw.ilines & IF_VBLANK))
					{
						C += 228; /*C += 218; See "NOTE A" above */
						hw_interrupt(IF_VBLANK, IF_VBLANK);
					}
					else
					{
						R_LY++;
						if (R_LY < 153)
						{
							C += 228;
						}
						else if (R_LY == 153)
						{
							/* Handling special case on the last line
							part 1; see docs/HACKING */
							C += 28;
						}
						else
						{
							/* Handling special case on the last line
							part 2; see docs/HACKING */
							R_LY = 0;
							C += 200;
						}
						stat_trigger();
					}
					break;
			} /* switch(state) */
		} /* while (C <= 0) */
	} /* if (R_LCDC & 0x80) */
	else
	{
		/* LCDC operation disabled (short route) */
		if (C <= 0) /* Original code does in fact return after each pass, there is no loop here */
		{
			switch ((byte)(R_STAT & 3))
			{
			case 2: /* after search */
				stat_change(3);
				C += 86;
				break;
			case 3: /* after transfer */
				stat_change(0);
				C += 102;
				break;
			case 0: /* after hblank */
				stat_change(2);
				R_LY++;
				C += 40;
				break;
			case 1: /* after (in) vblank */
				stat_change(2);
				C += 40;
				break;
			}
		}
	}
}
Ejemplo n.º 5
0
void ioreg_write(byte r, byte b)
{
	if (!hw.cgb)
	{
		switch (r)
		{
		case RI_VBK:
		case RI_BCPS:
		case RI_OCPS:
		case RI_BCPD:
		case RI_OCPD:
		case RI_SVBK:
		case RI_KEY1:
		case RI_HDMA1:
		case RI_HDMA2:
		case RI_HDMA3:
		case RI_HDMA4:
		case RI_HDMA5:
			return;
		}
	}
	
	switch(r)
	{
	case RI_TIMA:
	case RI_TMA:
	case RI_TAC:
	case RI_SCY:
	case RI_SCX:
	case RI_WY:
	case RI_WX:
		REG(r) = b;
		break;
	case RI_BGP:
		if (R_BGP == b) break;
		pal_write_dmg(0, 0, b);
		pal_write_dmg(8, 1, b);
		R_BGP = b;
		break;
	case RI_OBP0:
		if (R_OBP0 == b) break;
		pal_write_dmg(64, 2, b);
		R_OBP0 = b;
		break;
	case RI_OBP1:
		if (R_OBP1 == b) break;
		pal_write_dmg(72, 3, b);
		R_OBP1 = b;
		break;
	case RI_IF:
	case RI_IE:
		REG(r) = b & 0x1F;
		break;
	case RI_P1:
		REG(r) = b;
		pad_refresh();
		break;
	case RI_SC:
		/* FIXME - this is a hack for stupid roms that probe serial */
		if ((b & 0x81) == 0x81)
		{
			R_SB = 0xff;
			hw_interrupt(IF_SERIAL, IF_SERIAL);
			hw_interrupt(0, IF_SERIAL);
		}
		R_SC = b; /* & 0x7f; */
		break;
	case RI_DIV:
		REG(r) = 0;
		break;
	case RI_LCDC:
		lcdc_change(b);
		break;
	case RI_STAT:
		stat_write(b);
		break;
	case RI_LYC:
		REG(r) = b;
		stat_trigger();
		break;
	case RI_VBK:
		REG(r) = b | 0xFE;
		mem_updatemap();
		break;
	case RI_BCPS:
		R_BCPS = b & 0xBF;
		R_BCPD = lcd.pal[b & 0x3F];
		break;
	case RI_OCPS:
		R_OCPS = b & 0xBF;
		R_OCPD = lcd.pal[64 + (b & 0x3F)];
		break;
	case RI_BCPD:
		R_BCPD = b;
		pal_write(R_BCPS & 0x3F, b);
		if (R_BCPS & 0x80) R_BCPS = (R_BCPS+1) & 0xBF;
		break;
	case RI_OCPD:
		R_OCPD = b;
		pal_write(64 + (R_OCPS & 0x3F), b);
		if (R_OCPS & 0x80) R_OCPS = (R_OCPS+1) & 0xBF;
		break;
	case RI_SVBK:
		REG(r) = b & 0x07;
		mem_updatemap();
		break;
	case RI_DMA:
		hw_dma(b);
		break;
	case RI_KEY1:
		REG(r) = (REG(r) & 0x80) | (b & 0x01);
		break;
	case RI_HDMA1:
		REG(r) = b;
		break;
	case RI_HDMA2:
		REG(r) = b & 0xF0;
		break;
	case RI_HDMA3:
		REG(r) = b & 0x1F;
		break;
	case RI_HDMA4:
		REG(r) = b & 0xF0;
		break;
	case RI_HDMA5:
		hw_hdma_cmd(b);
		break;
	}
	switch (r)
	{
	case RI_BGP:
	case RI_OBP0:
	case RI_OBP1:
		/* printf("palette reg %02X write %02X at LY=%02X\n", r, b, R_LY); */
	case RI_HDMA1:
	case RI_HDMA2:
	case RI_HDMA3:
	case RI_HDMA4:
	case RI_HDMA5:
		/* printf("HDMA %d: %02X\n", r - RI_HDMA1 + 1, b); */
		break;
	}
	/* printf("reg %02X => %02X (%02X)\n", r, REG(r), b); */
}
Ejemplo n.º 6
0
void lcdc_trans()
{
	if (!(R_LCDC & 0x80))
	{
		while (C <= 0)
		{
			switch ((byte)(R_STAT & 3))
			{
			case 0:
			case 1:
				stat_change(2);
				C += 40;
				break;
			case 2:
				stat_change(3);
				C += 86;
				break;
			case 3:
				stat_change(0);
				if (hw.hdma & 0x80)
					hw_hdma();
				else
					C += 102;
				break;
			}
			return;
		}
	}
	while (C <= 0)
	{
		switch ((byte)(R_STAT & 3))
		{
		case 1:
			if (!(hw.ilines & IF_VBLANK))
			{
				C += 218;
				hw_interrupt(IF_VBLANK, IF_VBLANK);
				break;
			}
			if (R_LY == 0)
			{
				lcd_begin();
				stat_change(2);
				C += 40;
				break;
			}
			else if (R_LY < 152)
				C += 228;
			else if (R_LY == 152)
				C += 28;
			else
			{
				R_LY = -1;
				C += 200;
			}
			R_LY++;
			stat_trigger();
			break;
		case 2:
			lcd_refreshline();
			stat_change(3);
			C += 86;
			break;
		case 3:
			stat_change(0);
			if (hw.hdma & 0x80)
				hw_hdma();
			/* FIXME -- how much of the hblank does hdma use?? */
			/* else */
			C += 102;
			break;
		case 0:
			if (++R_LY >= 144)
			{
				if (cpu.halt)
				{
					hw_interrupt(IF_VBLANK, IF_VBLANK);
					C += 228;
				}
				else C += 10;
				stat_change(1);
				break;
			}
			stat_change(2);
			C += 40;
			break;
		}
	}
}