OSDN Git Service

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