2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 #ifndef MC6847_VRAM_OFS
13 #define MC6847_VRAM_OFS 0
32 static const uint8 intfont[64 * 12] = {
33 0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
34 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
93 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00
99 void MC6847::initialize()
101 // semigraphics pattern
102 for(int i = 0; i < 16; i++) {
103 for(int j = 0; j < 6; j++) {
104 sg4[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
106 for(int j = 6; j < 12; j++) {
107 sg4[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
110 for(int i = 0; i < 64; i++) {
111 for(int j = 0; j < 4; j++) {
112 sg6[i * 12 + j] = ((i & 0x20) ? 0xf0 : 0) | ((i & 0x10) ? 0x0f : 0);
114 for(int j = 4; j < 8; j++) {
115 sg6[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
117 for(int j = 8; j < 12; j++) {
118 sg6[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
123 palette_pc[LIGHTGREEN] = RGB_COLOR(184,255,181);
124 palette_pc[RED ] = RGB_COLOR(254, 65,105);
125 palette_pc[YELLOW ] = RGB_COLOR(252,253,153);
126 palette_pc[BLUE ] = RGB_COLOR(116, 41,255);
127 palette_pc[WHITE ] = RGB_COLOR(241,229,232);
128 palette_pc[CYAN ] = RGB_COLOR(124,210,213);
129 palette_pc[MAGENTA ] = RGB_COLOR(254,113,255);
130 palette_pc[ORANGE ] = RGB_COLOR(254,112, 35);
131 palette_pc[BLACK ] = RGB_COLOR( 0, 0, 0);
132 palette_pc[GREEN ] = RGB_COLOR( 22,134, 10);
133 palette_pc[BEIGE ] = RGB_COLOR(255,198,170);
134 palette_pc[GRAY ] = RGB_COLOR( 32, 32, 32);
139 register_vline_event(this);
140 update_timing(CPU_CLOCKS, FRAMES_PER_SEC, LINES_PER_FRAME);
145 vsync = hsync = disp = true;
148 void MC6847::write_signal(int id, uint32 data, uint32 mask)
152 ag = ((data & mask) != 0);
155 as = ((data & mask) != 0);
157 case SIG_MC6847_INTEXT:
158 intext = ((data & mask) != 0);
161 gm = (gm & ~mask) | (data & mask);
164 css = ((data & mask) != 0);
167 inv = ((data & mask) != 0);
169 case SIG_MC6847_ENABLE:
170 disabled = ((data & mask) == 0);
172 case SIG_MC6847_DISABLE:
173 disabled = ((data & mask) != 0);
178 void MC6847::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
180 // this should be called before vline event
181 tWHS = (int)((double)new_clocks / new_frames_per_sec / (double)new_lines_per_frame * 16.5 / 227.5 + 0.5);
184 void MC6847::event_vline(int v, int clock)
187 set_vsync(v > 32); // 32/262
191 register_event_by_clock(this, 0, tWHS, false, NULL);
194 void MC6847::event_callback(int event_id, int err)
199 void MC6847::set_vsync(bool val)
202 write_signals(&outputs_vsync, val ? 0xffffffff : 0);
204 set_disp(vsync && hsync);
208 void MC6847::set_hsync(bool val)
211 write_signals(&outputs_hsync, val ? 0xffffffff : 0);
213 set_disp(vsync && hsync);
217 void MC6847::set_disp(bool val)
220 if(d_cpu != NULL && !disabled) {
221 d_cpu->write_signal(SIG_CPU_BUSREQ, val ? 1 : 0, 1);
227 void MC6847::load_font_image(_TCHAR *path)
230 FILEIO* fio = new FILEIO();
231 if(fio->Fopen(path, FILEIO_READ_BINARY)) {
232 fio->Fread(extfont, sizeof(extfont), 1);
238 void MC6847::draw_screen()
242 memset(screen, 0, sizeof(screen));
246 case 0: draw_cg(4, 3); break; // 64x 64
247 case 1: draw_rg(2, 3); break; // 128x 64
248 case 2: draw_cg(2, 3); break; // 128x 64
249 case 3: draw_rg(2, 2); break; // 128x 96
250 case 4: draw_cg(2, 2); break; // 128x 96
251 case 5: draw_rg(2, 1); break; // 128x192
252 case 6: draw_cg(2, 1); break; // 128x192
253 case 7: draw_rg(1, 1); break; // 256x192
256 // alphanumerics / semigraphics
261 for(int y = 0; y < 192; y++) {
262 scrntype* dest = emu->screen_buffer(y);
263 for(int x = 0; x < 256; x++) {
264 dest[x] = palette_pc[screen[y][x]];
269 void MC6847::draw_cg(int xofs, int yofs)
271 uint8 color = css ? 4 : 0;
274 for(int y = 0; y < 192; y += yofs) {
275 for(int x = 0; x < 256; x += xofs * 4) {
276 uint8 data = vram_ptr[ofs];
277 if(++ofs >= vram_size) {
280 uint8* dest = &screen[y][x];
283 dest[ 0] = dest[ 1] = dest[ 2] = dest[ 3] = color | ((data >> 6) & 3);
284 dest[ 4] = dest[ 5] = dest[ 6] = dest[ 7] = color | ((data >> 4) & 3);
285 dest[ 8] = dest[ 9] = dest[10] = dest[11] = color | ((data >> 2) & 3);
286 dest[12] = dest[13] = dest[14] = dest[15] = color | ((data >> 0) & 3);
288 dest[0] = dest[1] = color | ((data >> 6) & 3);
289 dest[2] = dest[3] = color | ((data >> 4) & 3);
290 dest[4] = dest[5] = color | ((data >> 2) & 3);
291 dest[6] = dest[7] = color | ((data >> 0) & 3);
295 memcpy(screen[y + 1], screen[y], 256);
297 memcpy(screen[y + 2], screen[y], 256);
303 void MC6847::draw_rg(int xofs, int yofs)
305 static const uint8 color_table[4] = {
306 GREEN, LIGHTGREEN, BLACK, WHITE
308 static const uint8 color_table2[4] = {
309 BLACK, BLACK, CYAN, WHITE
311 static const uint8 color_table3[4] = {
312 BLACK, ORANGE, BLACK, WHITE
314 uint8 color = css ? 2 : 0;
317 for(int y = 0; y < 192; y += yofs) {
318 for(int x = 0; x < 256; x += xofs * 8) {
319 uint8 data = vram_ptr[ofs];
320 if(++ofs >= vram_size) {
323 uint8* dest = &screen[y][x];
326 dest[ 0] = dest[ 1] = color_table[color | ((data >> 7) & 1)];
327 dest[ 2] = dest[ 3] = color_table[color | ((data >> 6) & 1)];
328 dest[ 4] = dest[ 5] = color_table[color | ((data >> 5) & 1)];
329 dest[ 6] = dest[ 7] = color_table[color | ((data >> 4) & 1)];
330 dest[ 8] = dest[ 9] = color_table[color | ((data >> 3) & 1)];
331 dest[10] = dest[11] = color_table[color | ((data >> 2) & 1)];
332 dest[12] = dest[13] = color_table[color | ((data >> 1) & 1)];
333 dest[14] = dest[15] = color_table[color | ((data >> 0) & 1)];
335 // color bleed in black/white pattern
336 dest[0] = color_table2[(data >> 6) & 3];
337 dest[1] = color_table3[(data >> 6) & 3];
338 dest[2] = color_table2[(data >> 4) & 3];
339 dest[3] = color_table3[(data >> 4) & 3];
340 dest[4] = color_table2[(data >> 2) & 3];
341 dest[5] = color_table3[(data >> 2) & 3];
342 dest[6] = color_table2[(data >> 0) & 3];
343 dest[7] = color_table3[(data >> 0) & 3];
345 dest[0] = color_table[(data >> 7) & 1];
346 dest[1] = color_table[(data >> 6) & 1];
347 dest[2] = color_table[(data >> 5) & 1];
348 dest[3] = color_table[(data >> 4) & 1];
349 dest[4] = color_table[(data >> 3) & 1];
350 dest[5] = color_table[(data >> 2) & 1];
351 dest[6] = color_table[(data >> 1) & 1];
352 dest[7] = color_table[(data >> 0) & 1];
356 memcpy(screen[y + 1], screen[y], 256);
358 memcpy(screen[y + 2], screen[y], 256);
364 void MC6847::draw_alpha()
369 for(int y = 0; y < 192; y += 12) {
370 for(int x = 0; x < 256; x += 8) {
371 uint8 data = vram_ptr[ofs + MC6847_VRAM_OFS];
372 #ifdef MC6847_ATTR_OFS
373 uint8 attr = vram_ptr[ofs + MC6847_ATTR_OFS];
375 if(++ofs >= vram_size) {
378 // vram data bits may be connected to mode signals
380 bool intext2 = intext;
383 #ifdef MC6847_VRAM_AS
384 as2 = ((data & MC6847_VRAM_AS) != 0);
386 #ifdef MC6847_VRAM_INTEXT
387 intext2 = ((data & MC6847_VRAM_INTEXT) != 0);
389 #ifdef MC6847_VRAM_CSS
390 css2 = ((data & MC6847_VRAM_CSS) != 0);
392 #ifdef MC6847_VRAM_INV
393 inv2 = ((data & MC6847_VRAM_INV) != 0);
395 #ifdef MC6847_ATTR_OFS
396 #ifdef MC6847_ATTR_AS
397 as2 = ((attr & MC6847_ATTR_AS) != 0);
399 #ifdef MC6847_ATTR_INTEXT
400 intext2 = ((attr & MC6847_ATTR_INTEXT) != 0);
402 #ifdef MC6847_ATTR_CSS
403 css2 = ((attr & MC6847_ATTR_CSS) != 0);
405 #ifdef MC6847_ATTR_INV
406 inv2 = ((attr & MC6847_ATTR_INV) != 0);
410 uint8 col_fore, col_back;
413 // external alphanumerics
414 pattern = &extfont[16 * data];
416 // internal alphanumerics
417 pattern = (uint8 *)(&intfont[12 * (data & 0x3f)]);
419 // note: we need to overwrite the color table by each driver
420 static const uint8 color_table[6] = {
422 WHITE, GRAY, WHITE, GRAY, WHITE, GRAY
424 LIGHTGREEN, GREEN, BEIGE, RED, GREEN, BLACK
427 int col = (css2 ? 2 : 0) | (inv2 ? 1 : 0);
428 col_fore = color_table[col];
429 col_back = color_table[col ^ 1];
433 pattern = &sg6[12 * (data & 0x3f)];
434 col_fore = (css2 ? 4 : 0) | ((data >> 6) & 3);
437 pattern = &sg4[12 * (data & 0x0f)];
438 col_fore = (data >> 4) & 7;
442 for(int l = 0; l < 12; l++) {
443 uint8 pat = pattern[l];
444 uint8* dest = &screen[y + l][x];
446 dest[0] = (pat & 0x80) ? col_fore : col_back;
447 dest[1] = (pat & 0x40) ? col_fore : col_back;
448 dest[2] = (pat & 0x20) ? col_fore : col_back;
449 dest[3] = (pat & 0x10) ? col_fore : col_back;
450 dest[4] = (pat & 0x08) ? col_fore : col_back;
451 dest[5] = (pat & 0x04) ? col_fore : col_back;
452 dest[6] = (pat & 0x02) ? col_fore : col_back;
453 dest[7] = (pat & 0x01) ? col_fore : col_back;
459 #define STATE_VERSION 1
461 void MC6847::save_state(FILEIO* state_fio)
463 state_fio->FputUint32(STATE_VERSION);
464 state_fio->FputInt32(this_device_id);
466 state_fio->Fwrite(sg4, sizeof(sg4), 1);
467 state_fio->Fwrite(sg6, sizeof(sg6), 1);
468 state_fio->FputBool(ag);
469 state_fio->FputBool(as);
470 state_fio->FputBool(intext);
471 state_fio->FputUint8(gm);
472 state_fio->FputBool(css);
473 state_fio->FputBool(inv);
474 state_fio->FputBool(vsync);
475 state_fio->FputBool(hsync);
476 state_fio->FputBool(disp);
477 state_fio->FputInt32(tWHS);
478 state_fio->FputBool(disabled);
481 bool MC6847::load_state(FILEIO* state_fio)
483 if(state_fio->FgetUint32() != STATE_VERSION) {
486 if(state_fio->FgetInt32() != this_device_id) {
489 state_fio->Fread(sg4, sizeof(sg4), 1);
490 state_fio->Fread(sg6, sizeof(sg6), 1);
491 ag = state_fio->FgetBool();
492 as = state_fio->FgetBool();
493 intext = state_fio->FgetBool();
494 gm = state_fio->FgetUint8();
495 css = state_fio->FgetBool();
496 inv = state_fio->FgetBool();
497 vsync = state_fio->FgetBool();
498 hsync = state_fio->FgetBool();
499 disp = state_fio->FgetBool();
500 tWHS = state_fio->FgetInt32();
501 disabled = state_fio->FgetBool();