2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
11 #include "../fileio.h"
13 #ifndef MC6847_VRAM_OFS
14 #define MC6847_VRAM_OFS 0
33 static const uint8 intfont[64 * 12] = {
34 0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
94 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00
100 void MC6847::initialize()
102 // semigraphics pattern
103 for(int i = 0; i < 16; i++) {
104 for(int j = 0; j < 6; j++) {
105 sg4[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
107 for(int j = 6; j < 12; j++) {
108 sg4[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
111 for(int i = 0; i < 64; i++) {
112 for(int j = 0; j < 4; j++) {
113 sg6[i * 12 + j] = ((i & 0x20) ? 0xf0 : 0) | ((i & 0x10) ? 0x0f : 0);
115 for(int j = 4; j < 8; j++) {
116 sg6[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
118 for(int j = 8; j < 12; j++) {
119 sg6[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
124 palette_pc[LIGHTGREEN] = RGB_COLOR(184,255,181);
125 palette_pc[RED ] = RGB_COLOR(254, 65,105);
126 palette_pc[YELLOW ] = RGB_COLOR(252,253,153);
127 palette_pc[BLUE ] = RGB_COLOR(116, 41,255);
128 palette_pc[WHITE ] = RGB_COLOR(241,229,232);
129 palette_pc[CYAN ] = RGB_COLOR(124,210,213);
130 palette_pc[MAGENTA ] = RGB_COLOR(254,113,255);
131 palette_pc[ORANGE ] = RGB_COLOR(254,112, 35);
132 palette_pc[BLACK ] = RGB_COLOR( 0, 0, 0);
133 palette_pc[GREEN ] = RGB_COLOR( 22,134, 10);
134 palette_pc[BEIGE ] = RGB_COLOR(255,198,170);
135 palette_pc[GRAY ] = RGB_COLOR( 32, 32, 32);
140 register_vline_event(this);
141 update_timing(CPU_CLOCKS, FRAMES_PER_SEC, LINES_PER_FRAME);
146 vsync = hsync = disp = true;
149 void MC6847::write_signal(int id, uint32 data, uint32 mask)
153 ag = ((data & mask) != 0);
156 as = ((data & mask) != 0);
158 case SIG_MC6847_INTEXT:
159 intext = ((data & mask) != 0);
162 gm = (gm & ~mask) | (data & mask);
165 css = ((data & mask) != 0);
168 inv = ((data & mask) != 0);
170 case SIG_MC6847_ENABLE:
171 disabled = ((data & mask) == 0);
173 case SIG_MC6847_DISABLE:
174 disabled = ((data & mask) != 0);
179 void MC6847::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
181 // this should be called before vline event
182 tWHS = (int)((double)new_clocks / new_frames_per_sec / (double)new_lines_per_frame * 16.5 / 227.5 + 0.5);
185 void MC6847::event_vline(int v, int clock)
188 set_vsync(v > 32); // 32/262
192 register_event_by_clock(this, 0, tWHS, false, NULL);
195 void MC6847::event_callback(int event_id, int err)
200 void MC6847::set_vsync(bool val)
203 write_signals(&outputs_vsync, val ? 0xffffffff : 0);
205 set_disp(vsync && hsync);
209 void MC6847::set_hsync(bool val)
212 write_signals(&outputs_hsync, val ? 0xffffffff : 0);
214 set_disp(vsync && hsync);
218 void MC6847::set_disp(bool val)
221 if(d_cpu != NULL && !disabled) {
222 d_cpu->write_signal(SIG_CPU_BUSREQ, val ? 1 : 0, 1);
228 void MC6847::load_font_image(_TCHAR *path)
231 FILEIO* fio = new FILEIO();
232 if(fio->Fopen(path, FILEIO_READ_BINARY)) {
233 fio->Fread(extfont, sizeof(extfont), 1);
239 void MC6847::draw_screen()
243 memset(screen, 0, sizeof(screen));
247 case 0: draw_cg(4, 3); break; // 64x 64
248 case 1: draw_rg(2, 3); break; // 128x 64
249 case 2: draw_cg(2, 3); break; // 128x 64
250 case 3: draw_rg(2, 2); break; // 128x 96
251 case 4: draw_cg(2, 2); break; // 128x 96
252 case 5: draw_rg(2, 1); break; // 128x192
253 case 6: draw_cg(2, 1); break; // 128x192
254 case 7: draw_rg(1, 1); break; // 256x192
257 // alphanumerics / semigraphics
262 for(int y = 0; y < 192; y++) {
263 scrntype* dest = emu->screen_buffer(y);
264 for(int x = 0; x < 256; x++) {
265 dest[x] = palette_pc[screen[y][x]];
270 void MC6847::draw_cg(int xofs, int yofs)
272 uint8 color = css ? 4 : 0;
275 for(int y = 0; y < 192; y += yofs) {
276 for(int x = 0; x < 256; x += xofs * 4) {
277 uint8 data = vram_ptr[ofs];
278 if(++ofs >= vram_size) {
281 uint8* dest = &screen[y][x];
284 dest[ 0] = dest[ 1] = dest[ 2] = dest[ 3] = color | ((data >> 6) & 3);
285 dest[ 4] = dest[ 5] = dest[ 6] = dest[ 7] = color | ((data >> 4) & 3);
286 dest[ 8] = dest[ 9] = dest[10] = dest[11] = color | ((data >> 2) & 3);
287 dest[12] = dest[13] = dest[14] = dest[15] = color | ((data >> 0) & 3);
289 dest[0] = dest[1] = color | ((data >> 6) & 3);
290 dest[2] = dest[3] = color | ((data >> 4) & 3);
291 dest[4] = dest[5] = color | ((data >> 2) & 3);
292 dest[6] = dest[7] = color | ((data >> 0) & 3);
296 memcpy(screen[y + 1], screen[y], 256);
298 memcpy(screen[y + 2], screen[y], 256);
304 void MC6847::draw_rg(int xofs, int yofs)
306 static const uint8 color_table[4] = {
307 GREEN, LIGHTGREEN, BLACK, WHITE
309 static const uint8 color_table2[4] = {
310 BLACK, BLACK, CYAN, WHITE
312 static const uint8 color_table3[4] = {
313 BLACK, ORANGE, BLACK, WHITE
315 uint8 color = css ? 2 : 0;
318 for(int y = 0; y < 192; y += yofs) {
319 for(int x = 0; x < 256; x += xofs * 8) {
320 uint8 data = vram_ptr[ofs];
321 if(++ofs >= vram_size) {
324 uint8* dest = &screen[y][x];
327 dest[ 0] = dest[ 1] = color_table[color | ((data >> 7) & 1)];
328 dest[ 2] = dest[ 3] = color_table[color | ((data >> 6) & 1)];
329 dest[ 4] = dest[ 5] = color_table[color | ((data >> 5) & 1)];
330 dest[ 6] = dest[ 7] = color_table[color | ((data >> 4) & 1)];
331 dest[ 8] = dest[ 9] = color_table[color | ((data >> 3) & 1)];
332 dest[10] = dest[11] = color_table[color | ((data >> 2) & 1)];
333 dest[12] = dest[13] = color_table[color | ((data >> 1) & 1)];
334 dest[14] = dest[15] = color_table[color | ((data >> 0) & 1)];
336 // color bleed in black/white pattern
337 dest[0] = color_table2[(data >> 6) & 3];
338 dest[1] = color_table3[(data >> 6) & 3];
339 dest[2] = color_table2[(data >> 4) & 3];
340 dest[3] = color_table3[(data >> 4) & 3];
341 dest[4] = color_table2[(data >> 2) & 3];
342 dest[5] = color_table3[(data >> 2) & 3];
343 dest[6] = color_table2[(data >> 0) & 3];
344 dest[7] = color_table3[(data >> 0) & 3];
346 dest[0] = color_table[(data >> 7) & 1];
347 dest[1] = color_table[(data >> 6) & 1];
348 dest[2] = color_table[(data >> 5) & 1];
349 dest[3] = color_table[(data >> 4) & 1];
350 dest[4] = color_table[(data >> 3) & 1];
351 dest[5] = color_table[(data >> 2) & 1];
352 dest[6] = color_table[(data >> 1) & 1];
353 dest[7] = color_table[(data >> 0) & 1];
357 memcpy(screen[y + 1], screen[y], 256);
359 memcpy(screen[y + 2], screen[y], 256);
365 void MC6847::draw_alpha()
370 for(int y = 0; y < 192; y += 12) {
371 for(int x = 0; x < 256; x += 8) {
372 uint8 data = vram_ptr[ofs + MC6847_VRAM_OFS];
373 #ifdef MC6847_ATTR_OFS
374 uint8 attr = vram_ptr[ofs + MC6847_ATTR_OFS];
376 if(++ofs >= vram_size) {
379 // vram data bits may be connected to mode signals
381 bool intext2 = intext;
384 #ifdef MC6847_VRAM_AS
385 as2 = ((data & MC6847_VRAM_AS) != 0);
387 #ifdef MC6847_VRAM_INTEXT
388 intext2 = ((data & MC6847_VRAM_INTEXT) != 0);
390 #ifdef MC6847_VRAM_CSS
391 css2 = ((data & MC6847_VRAM_CSS) != 0);
393 #ifdef MC6847_VRAM_INV
394 inv2 = ((data & MC6847_VRAM_INV) != 0);
396 #ifdef MC6847_ATTR_OFS
397 #ifdef MC6847_ATTR_AS
398 as2 = ((attr & MC6847_ATTR_AS) != 0);
400 #ifdef MC6847_ATTR_INTEXT
401 intext2 = ((attr & MC6847_ATTR_INTEXT) != 0);
403 #ifdef MC6847_ATTR_CSS
404 css2 = ((attr & MC6847_ATTR_CSS) != 0);
406 #ifdef MC6847_ATTR_INV
407 inv2 = ((attr & MC6847_ATTR_INV) != 0);
411 uint8 col_fore, col_back;
414 // external alphanumerics
415 pattern = &extfont[16 * data];
417 // internal alphanumerics
418 pattern = (uint8 *)(&intfont[12 * (data & 0x3f)]);
420 // note: we need to overwrite the color table by each driver
421 static const uint8 color_table[6] = {
423 WHITE, GRAY, WHITE, GRAY, WHITE, GRAY
425 LIGHTGREEN, GREEN, BEIGE, RED, GREEN, BLACK
428 int col = (css2 ? 2 : 0) | (inv2 ? 1 : 0);
429 col_fore = color_table[col];
430 col_back = color_table[col ^ 1];
434 pattern = &sg6[12 * (data & 0x3f)];
435 col_fore = (css2 ? 4 : 0) | ((data >> 6) & 3);
438 pattern = &sg4[12 * (data & 0x0f)];
439 col_fore = (data >> 4) & 7;
443 for(int l = 0; l < 12; l++) {
444 uint8 pat = pattern[l];
445 uint8* dest = &screen[y + l][x];
447 dest[0] = (pat & 0x80) ? col_fore : col_back;
448 dest[1] = (pat & 0x40) ? col_fore : col_back;
449 dest[2] = (pat & 0x20) ? col_fore : col_back;
450 dest[3] = (pat & 0x10) ? col_fore : col_back;
451 dest[4] = (pat & 0x08) ? col_fore : col_back;
452 dest[5] = (pat & 0x04) ? col_fore : col_back;
453 dest[6] = (pat & 0x02) ? col_fore : col_back;
454 dest[7] = (pat & 0x01) ? col_fore : col_back;
460 #define STATE_VERSION 1
462 void MC6847::save_state(FILEIO* state_fio)
464 state_fio->FputUint32(STATE_VERSION);
465 state_fio->FputInt32(this_device_id);
467 state_fio->Fwrite(sg4, sizeof(sg4), 1);
468 state_fio->Fwrite(sg6, sizeof(sg6), 1);
469 state_fio->FputBool(ag);
470 state_fio->FputBool(as);
471 state_fio->FputBool(intext);
472 state_fio->FputUint8(gm);
473 state_fio->FputBool(css);
474 state_fio->FputBool(inv);
475 state_fio->FputBool(vsync);
476 state_fio->FputBool(hsync);
477 state_fio->FputBool(disp);
478 state_fio->FputInt32(tWHS);
479 state_fio->FputBool(disabled);
482 bool MC6847::load_state(FILEIO* state_fio)
484 if(state_fio->FgetUint32() != STATE_VERSION) {
487 if(state_fio->FgetInt32() != this_device_id) {
490 state_fio->Fread(sg4, sizeof(sg4), 1);
491 state_fio->Fread(sg6, sizeof(sg6), 1);
492 ag = state_fio->FgetBool();
493 as = state_fio->FgetBool();
494 intext = state_fio->FgetBool();
495 gm = state_fio->FgetUint8();
496 css = state_fio->FgetBool();
497 inv = state_fio->FgetBool();
498 vsync = state_fio->FgetBool();
499 hsync = state_fio->FgetBool();
500 disp = state_fio->FgetBool();
501 tWHS = state_fio->FgetInt32();
502 disabled = state_fio->FgetBool();