和製MESSでPC-6001 その7

ここら辺を参考にVDG周りを動作確認。全然色が違います。

http://p6ers.net/mm/pc-6001/dev/p6color_chk/

f:id:tanam:20130731044005p:image:w360

f:id:tanam:20130731044004p:image:w360

mc6847.cpp

/*
	Skelton for retropc emulator

	Author : Takeda.Toshiya
	Date   : 2010.08.03-

	[ mc6847 ]
*/

#include "mc6847.h"
#include "../fileio.h"

#ifndef MC6847_VRAM_OFS
#define MC6847_VRAM_OFS	0
#endif

#define LIGHTGREEN	0
#define YELLOW		1
#define BLUE		2
#define RED		3
#define WHITE		4
#define CYAN		5
#define MAGENTA		6
#define ORANGE		7
#define BLACK		8
// text
#define GREEN		9
#define BEIGE		10
// phc20
#define GRAY		11

// from mess m6847.c
static const uint8 intfont[64 * 12] = {
	0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
	0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00
};

void MC6847::initialize()
{
	// external font
	FILEIO* fio = new FILEIO();
#ifdef _PC6001
	if(fio->Fopen(emu->bios_path(_T("ROM/CGROM60.60")), FILEIO_READ_BINARY)) {
#else
	if(fio->Fopen(emu->bios_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
#endif
		fio->Fread(extfont, sizeof(extfont), 1);
		fio->Fclose();
	}
	delete fio;
	
	// semigraphics pattern
	for(int i = 0; i < 16; i++) {
		for(int j = 0; j < 6; j++) {
			sg4[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
		}
		for(int j = 6; j < 12; j++) {
			sg4[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
		}
	}
	for(int i = 0; i < 64; i++) {
		for(int j = 0; j < 4; j++) {
			sg6[i * 12 + j] = ((i & 0x20) ? 0xf0 : 0) | ((i & 0x10) ? 0x0f : 0);
		}
		for(int j = 4; j < 8; j++) {
			sg6[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
		}
		for(int j = 8; j < 12; j++) {
			sg6[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
		}
	}
	
	// pc pallete
	palette_pc[LIGHTGREEN] = RGB_COLOR(184,255,181);
	palette_pc[RED       ] = RGB_COLOR(254, 65,105);
	palette_pc[YELLOW    ] = RGB_COLOR(252,253,153);
	palette_pc[BLUE      ] = RGB_COLOR(116, 41,255);
	palette_pc[WHITE     ] = RGB_COLOR(241,229,232);
	palette_pc[CYAN      ] = RGB_COLOR(124,210,213);
	palette_pc[MAGENTA   ] = RGB_COLOR(254,113,255);
	palette_pc[ORANGE    ] = RGB_COLOR(254,112, 35);
	palette_pc[BLACK     ] = RGB_COLOR(  0,  0,  0);
	palette_pc[GREEN     ] = RGB_COLOR( 22,134, 10);
	palette_pc[BEIGE     ] = RGB_COLOR(255,198,170);
	palette_pc[GRAY      ] = RGB_COLOR( 32, 32, 32);
	
	// register event
	register_vline_event(this);
}

void MC6847::reset()
{
	vsync = hsync = true;
}

void MC6847::write_signal(int id, uint32 data, uint32 mask)
{
	switch(id) {
	case SIG_MC6847_AG:
		ag = ((data & mask) != 0);
		break;
	case SIG_MC6847_AS:
		as = ((data & mask) != 0);
		break;
	case SIG_MC6847_INTEXT:
		intext = ((data & mask) != 0);
		break;
	case SIG_MC6847_GM:
		gm = (gm & ~mask) | (data & mask);
		break;
	case SIG_MC6847_CSS:
		css = ((data & mask) != 0);
		break;
	case SIG_MC6847_INV:
		inv = ((data & mask) != 0);
		break;
	}
}

void MC6847::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
{
	// this should be called before vline event
	tWHS = (int)((double)new_clocks / new_frames_per_sec / (double)new_lines_per_frame * 16.5 / 227.5 + 0.5);
}

void MC6847::event_vline(int v, int clock)
{
	// vsync
	set_vsync(v > 32);	// 32/262
	
	// hsync
	if(outputs_hsync.count) {
		set_hsync(false);
		register_event_by_clock(this, 0, tWHS, false, NULL);
	}
#ifdef _PC6001
		if (counter++ > 30) {
		counter=0;
		d_cpu->write_signal(SIG_CPU_IRQ, 0x06, 0xff);
	}
#endif
}

void MC6847::event_callback(int event_id, int err)
{
	set_hsync(true);
}

void MC6847::set_vsync(bool val)
{
	if(vsync != val) {
		write_signals(&outputs_vsync, val ? 0xffffffff : 0);
		vsync = val;
	}
}

void MC6847::set_hsync(bool val)
{
	if(hsync != val) {
		write_signals(&outputs_hsync, val ? 0xffffffff : 0);
		hsync = val;
	}
}

void MC6847::draw_screen()
{
// render screen
#ifdef _PC6001
	if (*vram_ptr&0x80) {
		// graphics mode
		byte b=*vram_ptr;
		css = (b&0x02) ? true : false;
		vram_ptr+=0x200;
		switch(b&0x1C) {
		case 0x00: draw_cg(4, 3); break;	//  64x 64
		case 0x10: draw_rg(2, 3); break;	// 128x 64
		case 0x08: draw_cg(2, 3); break;	// 128x 64
		case 0x18: draw_rg(2, 2); break;	// 128x 96
		case 0x04: draw_cg(2, 2); break;	// 128x 96
		case 0x14: draw_rg(2, 1); break;	// 128x192
		case 0x0C: draw_cg(2, 1); break;	// 128x192
		case 0x1C: draw_rg(1, 1); break;	// 256x192
		}
		vram_ptr-=0x200;
#else
	// render screen
	if(ag) {
		// graphics mode
		switch(gm) {
		case 0: draw_cg(4, 3); break;	//  64x 64
		case 1: draw_rg(2, 3); break;	// 128x 64
		case 2: draw_cg(2, 3); break;	// 128x 64
		case 3: draw_rg(2, 2); break;	// 128x 96
		case 4: draw_cg(2, 2); break;	// 128x 96
		case 5: draw_rg(2, 1); break;	// 128x192
		case 6: draw_cg(2, 1); break;	// 128x192
		case 7: draw_rg(1, 1); break;	// 256x192
		}
#endif
	} else {
		// alphanumerics / semigraphics
		draw_alpha();
	}
	
	// copy to screen
	for(int y = 0; y < 192; y++) {
		scrntype* dest = emu->screen_buffer(y);
		for(int x = 0; x < 256; x++) {
			dest[x] = palette_pc[screen[y][x]];
		}
	}
}

void MC6847::draw_cg(int xofs, int yofs)
{
	uint8 color = css ? 4 : 0;
	int ofs = 0;
	
	for(int y = 0; y < 192; y += yofs) {
		for(int x = 0; x < 256; x += xofs * 4) {
			uint8 data = vram_ptr[ofs];
			if(++ofs >= vram_size) {
				ofs = 0;
			}
			uint8* dest = &screen[y][x];
			
			if(xofs == 4) {
				dest[ 0] = dest[ 1] = dest[ 2] = dest[ 3] = color | ((data >> 6) & 3);
				dest[ 4] = dest[ 5] = dest[ 6] = dest[ 7] = color | ((data >> 4) & 3);
				dest[ 8] = dest[ 9] = dest[10] = dest[11] = color | ((data >> 2) & 3);
				dest[12] = dest[13] = dest[14] = dest[15] = color | ((data >> 0) & 3);
			} else {
				dest[0] = dest[1] = color | ((data >> 6) & 3);
				dest[2] = dest[3] = color | ((data >> 4) & 3);
				dest[4] = dest[5] = color | ((data >> 2) & 3);
				dest[6] = dest[7] = color | ((data >> 0) & 3);
			}
		}
		if(yofs >= 2) {
			memcpy(screen[y + 1], screen[y], 256);
			if(yofs >= 3) {
				memcpy(screen[y + 2], screen[y], 256);
			}
		}
	}
}

void MC6847::draw_rg(int xofs, int yofs)
{
	static const uint8 color_table[4] = {
		GREEN, LIGHTGREEN, BLACK, WHITE
	};
#ifdef _PC6001
	static const uint8 color_table2[4] = {
		BLACK, BLACK, CYAN, WHITE
	};
	static const uint8 color_table3[4] = {
		BLACK, ORANGE, BLACK, WHITE
	};
	uint8 color = css ? 2 : 0;
	int ofs = 0;
	
	for(int y = 0; y < 192; y += yofs) {
		for(int x = 0; x < 256; x += xofs * 8) {
			uint8 data = vram_ptr[ofs];
			if(++ofs >= vram_size) {
				ofs = 0;
			}
			uint8* dest = &screen[y][x];
			
			if(xofs == 2) {
				dest[ 0] = dest[ 1] = color_table[color | ((data >> 7) & 1)];
				dest[ 2] = dest[ 3] = color_table[color | ((data >> 6) & 1)];
				dest[ 4] = dest[ 5] = color_table[color | ((data >> 5) & 1)];
				dest[ 6] = dest[ 7] = color_table[color | ((data >> 4) & 1)];
				dest[ 8] = dest[ 9] = color_table[color | ((data >> 3) & 1)];
				dest[10] = dest[11] = color_table[color | ((data >> 2) & 1)];
				dest[12] = dest[13] = color_table[color | ((data >> 1) & 1)];
				dest[14] = dest[15] = color_table[color | ((data >> 0) & 1)];
			} else if (color) {
				dest[0] = color_table2[((data >> 6) & 3)];
				dest[1] = color_table3[((data >> 6) & 3)];
				dest[2] = color_table2[((data >> 4) & 3)];
				dest[3] = color_table3[((data >> 4) & 3)];
				dest[4] = color_table2[((data >> 2) & 3)];
				dest[5] = color_table3[((data >> 2) & 3)];
				dest[6] = color_table2[((data >> 0) & 3)];
				dest[7] = color_table3[((data >> 0) & 3)];
#else
	uint8 color = css ? 2 : 0;
	int ofs = 0;
	
	for(int y = 0; y < 192; y += yofs) {
		for(int x = 0; x < 256; x += xofs * 8) {
			uint8 data = vram_ptr[ofs];
			if(++ofs >= vram_size) {
				ofs = 0;
			}
			uint8* dest = &screen[y][x];
			
			if(xofs == 2) {
				dest[ 0] = dest[ 1] = color_table[color | ((data >> 7) & 1)];
				dest[ 2] = dest[ 3] = color_table[color | ((data >> 6) & 1)];
				dest[ 4] = dest[ 5] = color_table[color | ((data >> 5) & 1)];
				dest[ 6] = dest[ 7] = color_table[color | ((data >> 4) & 1)];
				dest[ 8] = dest[ 9] = color_table[color | ((data >> 3) & 1)];
				dest[10] = dest[11] = color_table[color | ((data >> 2) & 1)];
				dest[12] = dest[13] = color_table[color | ((data >> 1) & 1)];
				dest[14] = dest[15] = color_table[color | ((data >> 0) & 1)];
#endif
			} else {
				dest[0] = color_table[color | ((data >> 7) & 1)];
				dest[1] = color_table[color | ((data >> 6) & 1)];
				dest[2] = color_table[color | ((data >> 5) & 1)];
				dest[3] = color_table[color | ((data >> 4) & 1)];
				dest[4] = color_table[color | ((data >> 3) & 1)];
				dest[5] = color_table[color | ((data >> 2) & 1)];
				dest[6] = color_table[color | ((data >> 1) & 1)];
				dest[7] = color_table[color | ((data >> 0) & 1)];
			}
		}
		if(yofs >= 2) {
			memcpy(screen[y + 1], screen[y], 256);
			if(yofs >= 3) {
				memcpy(screen[y + 2], screen[y], 256);
			}
		}
	}
}

void MC6847::draw_alpha()
{
	
	int ofs = 0;
	
	for(int y = 0; y < 192; y += 12) {
		for(int x = 0; x < 256; x += 8) {
			uint8 data = vram_ptr[ofs + MC6847_VRAM_OFS];
#ifdef MC6847_ATTR_OFS
			uint8 attr = vram_ptr[ofs + MC6847_ATTR_OFS];
#endif
			if(++ofs >= vram_size) {
				ofs = 0;
			}
			// vram data bits may be connected to mode signals
			bool as2 = as;
			bool intext2 = intext;
			bool css2 = css;
			bool inv2 = inv;
#ifdef MC6847_VRAM_AS
			as2 = ((data & MC6847_VRAM_AS) != 0);
#endif
#ifdef MC6847_VRAM_INTEXT
			intext2 = ((data & MC6847_VRAM_INTEXT) != 0);
#endif
#ifdef MC6847_VRAM_CSS
			css2 = ((data & MC6847_VRAM_CSS) != 0);
#endif
#ifdef MC6847_VRAM_INV
			inv2 = ((data & MC6847_VRAM_INV) != 0);
#endif
#ifdef MC6847_ATTR_OFS
#ifdef MC6847_ATTR_AS
			as2 = ((attr & MC6847_ATTR_AS) != 0);
#endif
#ifdef MC6847_ATTR_INTEXT
			intext2 = ((attr & MC6847_ATTR_INTEXT) != 0);
#endif
#ifdef MC6847_ATTR_CSS
			css2 = ((attr & MC6847_ATTR_CSS) != 0);
#endif
#ifdef MC6847_ATTR_INV
			inv2 = ((attr & MC6847_ATTR_INV) != 0);
#endif
#endif
			uint8 *pattern;
			uint8 col_fore, col_back;
			if(!as2) {
				if(intext2) {
					// external alphanumerics
					pattern = &extfont[16 * data];
				} else {
					// internal alphanumerics
					pattern = (uint8 *)(&intfont[12 * (data & 0x3f)]);
				}
				// note: we need to overwrite the color table by each driver
				static const uint8 color_table[6] = {
#ifdef _PHC20
					WHITE, GRAY, WHITE, GRAY, WHITE, GRAY
#else
					LIGHTGREEN, GREEN, BEIGE, RED, GREEN, BLACK
#endif
				};
				int col = (css2 ? 2 : 0) | (inv2 ? 1 : 0);
				col_fore = color_table[col];
				col_back = color_table[col ^ 1];
			}
			else {
				if(intext2) {
					// semiggraphics 6
					pattern = &sg6[12 * (data & 0x3f)];
					col_fore = (css2 ? 4 : 0) | ((data >> 6) & 3);
				} else {
					// semiggraphics 4
					pattern = &sg4[12 * (data & 0x0f)];
					col_fore = (data >> 4) & 7;
				}
				col_back = BLACK;
			}
			for(int l = 0; l < 12; l++) {
				uint8 pat = pattern[l];
				uint8* dest = &screen[y + l][x];
				
				dest[0] = (pat & 0x80) ? col_fore : col_back;
				dest[1] = (pat & 0x40) ? col_fore : col_back;
				dest[2] = (pat & 0x20) ? col_fore : col_back;
				dest[3] = (pat & 0x10) ? col_fore : col_back;
				dest[4] = (pat & 0x08) ? col_fore : col_back;
				dest[5] = (pat & 0x04) ? col_fore : col_back;
				dest[6] = (pat & 0x02) ? col_fore : col_back;
				dest[7] = (pat & 0x01) ? col_fore : col_back;
			}
		}
	}
}

#ifdef _PC6001
void MC6847::write_io8(uint32 addr, uint32 data)
{
	unsigned int VRAMHead[4] = { 0xc000, 0xe000, 0x8000, 0xa000 };

	if ((addr & 0xff)==0xB0) {
		vram_ptr=(ram_ptr+VRAMHead[(data&0x06)>>1]);
	}
}
#endif

mc6847.h

/*
	Skelton for retropc emulator

	Author : Takeda.Toshiya
	Date   : 2010.08.03-

	[ mc6847 ]
*/

#ifndef _MC6847_H_
#define _MC6847_H_

#include "vm.h"
#include "../emu.h"
#include "device.h"

#define SIG_MC6847_AG		0
#define SIG_MC6847_AS		1
#define SIG_MC6847_INTEXT	2
#define SIG_MC6847_GM		3
#define SIG_MC6847_CSS		4
#define SIG_MC6847_INV		5

class MC6847 : public DEVICE
{
private:
	// output signals
	outputs_t outputs_vsync;
	outputs_t outputs_hsync;
	
	uint8 extfont[256 * 16];
	uint8 sg4[16 * 12];
	uint8 sg6[64 * 12];
	uint8 screen[192][256];
#ifdef _PC6001
	DEVICE *d_cpu;
	uint8 *ram_ptr;
	uint8 counter;
#endif
	uint8 *vram_ptr;
	int vram_size;
	scrntype palette_pc[16];
	
	bool ag, as;
	bool intext;
	uint8 gm;
	bool css, inv;
	
	bool vsync, hsync;
	int tWHS;
	
	void set_vsync(bool val);
	void set_hsync(bool val);
	void draw_cg(int xofs, int yofs);
	void draw_rg(int xofs, int yofs);
	void draw_alpha();
	
public:
	MC6847(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
		ag = as = intext = css = inv = false;
		gm = 0;
		init_output_signals(&outputs_vsync);
		init_output_signals(&outputs_hsync);
	}
	~MC6847() {}
	
	// common functions
	void initialize();
	void reset();
	void write_signal(int id, uint32 data, uint32 mask);
	void event_vline(int v, int clock);
	void event_callback(int event_id, int err);
	void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame);
	
	// unique functions
	void set_context_vsync(DEVICE* device, int id, uint32 mask) {
		register_output_signal(&outputs_vsync, device, id, mask);
	}
	void set_context_hsync(DEVICE* device, int id, uint32 mask) {
		register_output_signal(&outputs_hsync, device, id, mask);
	}
#ifdef _PC6001
	void set_context_cpu(DEVICE* device) {
		d_cpu = device;
	}

	void set_vram_ptr(uint8* ptr, int size) {
		ram_ptr = vram_ptr = ptr; vram_size = size;
	}

	void write_io8(uint32 addr, uint32 data);
#else
	void set_vram_ptr(uint8* ptr, int size) {
		vram_ptr = ptr; vram_size = size;
	}
#endif
	void draw_screen();
};

#endif