OSDN Git Service

[VM][FM7][FM77AV] Set sub clock.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mc6847.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2010.08.03-
6
7         [ mc6847 ]
8 */
9
10 #include "mc6847.h"
11
12 #ifndef MC6847_VRAM_OFS
13 #define MC6847_VRAM_OFS 0
14 #endif
15
16 #define LIGHTGREEN      0
17 #define YELLOW          1
18 #define BLUE            2
19 #define RED             3
20 #define WHITE           4
21 #define CYAN            5
22 #define MAGENTA         6
23 #define ORANGE          7
24 #define BLACK           8
25 // text
26 #define GREEN           9
27 #define BEIGE           10
28 // phc20
29 #define GRAY            11
30
31 // from mess m6847.c
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
97 };
98
99 void MC6847::initialize()
100 {
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);
105                 }
106                 for(int j = 6; j < 12; j++) {
107                         sg4[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
108                 }
109         }
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);
113                 }
114                 for(int j = 4; j < 8; j++) {
115                         sg6[i * 12 + j] = ((i & 0x08) ? 0xf0 : 0) | ((i & 0x04) ? 0x0f : 0);
116                 }
117                 for(int j = 8; j < 12; j++) {
118                         sg6[i * 12 + j] = ((i & 0x02) ? 0xf0 : 0) | ((i & 0x01) ? 0x0f : 0);
119                 }
120         }
121         
122         // pc pallete
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);
135         
136         disabled = false;
137         
138         // register event
139         register_vline_event(this);
140         update_timing(CPU_CLOCKS, FRAMES_PER_SEC, LINES_PER_FRAME);
141 }
142
143 void MC6847::reset()
144 {
145         vsync = hsync = disp = true;
146 }
147
148 void MC6847::write_signal(int id, uint32 data, uint32 mask)
149 {
150         switch(id) {
151         case SIG_MC6847_AG:
152                 ag = ((data & mask) != 0);
153                 break;
154         case SIG_MC6847_AS:
155                 as = ((data & mask) != 0);
156                 break;
157         case SIG_MC6847_INTEXT:
158                 intext = ((data & mask) != 0);
159                 break;
160         case SIG_MC6847_GM:
161                 gm = (gm & ~mask) | (data & mask);
162                 break;
163         case SIG_MC6847_CSS:
164                 css = ((data & mask) != 0);
165                 break;
166         case SIG_MC6847_INV:
167                 inv = ((data & mask) != 0);
168                 break;
169         case SIG_MC6847_ENABLE:
170                 disabled = ((data & mask) == 0);
171                 break;
172         case SIG_MC6847_DISABLE:
173                 disabled = ((data & mask) != 0);
174                 break;
175         }
176 }
177
178 void MC6847::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
179 {
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);
182 }
183
184 void MC6847::event_vline(int v, int clock)
185 {
186         // vsync
187         set_vsync(v > 32);      // 32/262
188         
189         // hsync
190         set_hsync(false);
191         register_event_by_clock(this, 0, tWHS, false, NULL);
192 }
193
194 void MC6847::event_callback(int event_id, int err)
195 {
196         set_hsync(true);
197 }
198
199 void MC6847::set_vsync(bool val)
200 {
201         if(vsync != val) {
202                 write_signals(&outputs_vsync, val ? 0xffffffff : 0);
203                 vsync = val;
204                 set_disp(vsync && hsync);
205         }
206 }
207
208 void MC6847::set_hsync(bool val)
209 {
210         if(hsync != val) {
211                 write_signals(&outputs_hsync, val ? 0xffffffff : 0);
212                 hsync = val;
213                 set_disp(vsync && hsync);
214         }
215 }
216
217 void MC6847::set_disp(bool val)
218 {
219         if(disp != val) {
220                 if(d_cpu != NULL && !disabled) {
221                         d_cpu->write_signal(SIG_CPU_BUSREQ, val ? 1 : 0, 1);
222                 }
223                 disp = val;
224         }
225 }
226
227 void MC6847::load_font_image(_TCHAR *path)
228 {
229         // external font
230         FILEIO* fio = new FILEIO();
231         if(fio->Fopen(path, FILEIO_READ_BINARY)) {
232                 fio->Fread(extfont, sizeof(extfont), 1);
233                 fio->Fclose();
234         }
235         delete fio;
236 }
237
238 void MC6847::draw_screen()
239 {
240         // render screen
241         if(disabled) {
242                 memset(screen, 0, sizeof(screen));
243         } else if(ag) {
244                 // graphics mode
245                 switch(gm) {
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
254                 }
255         } else {
256                 // alphanumerics / semigraphics
257                 draw_alpha();
258         }
259         
260         // copy to screen
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]];
265                 }
266         }
267 }
268
269 void MC6847::draw_cg(int xofs, int yofs)
270 {
271         uint8 color = css ? 4 : 0;
272         int ofs = 0;
273         
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) {
278                                 ofs = 0;
279                         }
280                         uint8* dest = &screen[y][x];
281                         
282                         if(xofs == 4) {
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);
287                         } else {
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);
292                         }
293                 }
294                 if(yofs >= 2) {
295                         memcpy(screen[y + 1], screen[y], 256);
296                         if(yofs >= 3) {
297                                 memcpy(screen[y + 2], screen[y], 256);
298                         }
299                 }
300         }
301 }
302
303 void MC6847::draw_rg(int xofs, int yofs)
304 {
305         static const uint8 color_table[4] = {
306                 GREEN, LIGHTGREEN, BLACK, WHITE
307         };
308         static const uint8 color_table2[4] = {
309                 BLACK, BLACK, CYAN, WHITE
310         };
311         static const uint8 color_table3[4] = {
312                 BLACK, ORANGE, BLACK, WHITE
313         };
314         uint8 color = css ? 2 : 0;
315         int ofs = 0;
316         
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) {
321                                 ofs = 0;
322                         }
323                         uint8* dest = &screen[y][x];
324                         
325                         if(xofs == 2) {
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)];
334                         } else if(css) {
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];
344                         } else {
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];
353                         }
354                 }
355                 if(yofs >= 2) {
356                         memcpy(screen[y + 1], screen[y], 256);
357                         if(yofs >= 3) {
358                                 memcpy(screen[y + 2], screen[y], 256);
359                         }
360                 }
361         }
362 }
363
364 void MC6847::draw_alpha()
365 {
366         
367         int ofs = 0;
368         
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];
374 #endif
375                         if(++ofs >= vram_size) {
376                                 ofs = 0;
377                         }
378                         // vram data bits may be connected to mode signals
379                         bool as2 = as;
380                         bool intext2 = intext;
381                         bool css2 = css;
382                         bool inv2 = inv;
383 #ifdef MC6847_VRAM_AS
384                         as2 = ((data & MC6847_VRAM_AS) != 0);
385 #endif
386 #ifdef MC6847_VRAM_INTEXT
387                         intext2 = ((data & MC6847_VRAM_INTEXT) != 0);
388 #endif
389 #ifdef MC6847_VRAM_CSS
390                         css2 = ((data & MC6847_VRAM_CSS) != 0);
391 #endif
392 #ifdef MC6847_VRAM_INV
393                         inv2 = ((data & MC6847_VRAM_INV) != 0);
394 #endif
395 #ifdef MC6847_ATTR_OFS
396 #ifdef MC6847_ATTR_AS
397                         as2 = ((attr & MC6847_ATTR_AS) != 0);
398 #endif
399 #ifdef MC6847_ATTR_INTEXT
400                         intext2 = ((attr & MC6847_ATTR_INTEXT) != 0);
401 #endif
402 #ifdef MC6847_ATTR_CSS
403                         css2 = ((attr & MC6847_ATTR_CSS) != 0);
404 #endif
405 #ifdef MC6847_ATTR_INV
406                         inv2 = ((attr & MC6847_ATTR_INV) != 0);
407 #endif
408 #endif
409                         uint8 *pattern;
410                         uint8 col_fore, col_back;
411                         if(!as2) {
412                                 if(intext2) {
413                                         // external alphanumerics
414                                         pattern = &extfont[16 * data];
415                                 } else {
416                                         // internal alphanumerics
417                                         pattern = (uint8 *)(&intfont[12 * (data & 0x3f)]);
418                                 }
419                                 // note: we need to overwrite the color table by each driver
420                                 static const uint8 color_table[6] = {
421 #ifdef _PHC20
422                                         WHITE, GRAY, WHITE, GRAY, WHITE, GRAY
423 #else
424                                         LIGHTGREEN, GREEN, BEIGE, RED, GREEN, BLACK
425 #endif
426                                 };
427                                 int col = (css2 ? 2 : 0) | (inv2 ? 1 : 0);
428                                 col_fore = color_table[col];
429                                 col_back = color_table[col ^ 1];
430                         } else {
431                                 if(intext2) {
432                                         // semiggraphics 6
433                                         pattern = &sg6[12 * (data & 0x3f)];
434                                         col_fore = (css2 ? 4 : 0) | ((data >> 6) & 3);
435                                 } else {
436                                         // semiggraphics 4
437                                         pattern = &sg4[12 * (data & 0x0f)];
438                                         col_fore = (data >> 4) & 7;
439                                 }
440                                 col_back = BLACK;
441                         }
442                         for(int l = 0; l < 12; l++) {
443                                 uint8 pat = pattern[l];
444                                 uint8* dest = &screen[y + l][x];
445                                 
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;
454                         }
455                 }
456         }
457 }
458
459 #define STATE_VERSION   1
460
461 void MC6847::save_state(FILEIO* state_fio)
462 {
463         state_fio->FputUint32(STATE_VERSION);
464         state_fio->FputInt32(this_device_id);
465         
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);
479 }
480
481 bool MC6847::load_state(FILEIO* state_fio)
482 {
483         if(state_fio->FgetUint32() != STATE_VERSION) {
484                 return false;
485         }
486         if(state_fio->FgetInt32() != this_device_id) {
487                 return false;
488         }
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();
502         return true;
503 }
504