OSDN Git Service

[VM][EMU] Add common function; my_memcpy() instead of memcpy() using SIMD.Recommend...
[csp-qt/common_source_project-fm7.git] / source / src / vm / mc6847_base.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 #define LIGHTGREEN      0
13 #define YELLOW          1
14 #define BLUE            2
15 #define RED             3
16 #define WHITE           4
17 #define CYAN            5
18 #define MAGENTA         6
19 #define ORANGE          7
20 #define BLACK           8
21 // text
22 #define GREEN           9
23 #define BEIGE           10
24 // phc20
25 #define GRAY            11
26
27 void MC6847_BASE::initialize()
28 {
29         DEVICE::initialize();
30 }
31
32 void MC6847_BASE::reset()
33 {
34         vsync = hsync = disp = true;
35 }
36
37 void MC6847_BASE::write_signal(int id, uint32_t data, uint32_t mask)
38 {
39         switch(id) {
40         case SIG_MC6847_AG:
41                 ag = ((data & mask) != 0);
42                 break;
43         case SIG_MC6847_AS:
44                 as = ((data & mask) != 0);
45                 break;
46         case SIG_MC6847_INTEXT:
47                 intext = ((data & mask) != 0);
48                 break;
49         case SIG_MC6847_GM:
50                 gm = (gm & ~mask) | (data & mask);
51                 break;
52         case SIG_MC6847_CSS:
53                 css = ((data & mask) != 0);
54                 break;
55         case SIG_MC6847_INV:
56                 inv = ((data & mask) != 0);
57                 break;
58         case SIG_MC6847_ENABLE:
59                 disabled = ((data & mask) == 0);
60                 break;
61         case SIG_MC6847_DISABLE:
62                 disabled = ((data & mask) != 0);
63                 break;
64         }
65 }
66
67 void MC6847_BASE::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
68 {
69         // this should be called before vline event
70         tWHS = (int)((double)new_clocks / new_frames_per_sec / (double)new_lines_per_frame * 16.5 / 227.5 + 0.5);
71 }
72
73 void MC6847_BASE::event_vline(int v, int clock)
74 {
75         // vsync
76         set_vsync(v > 32);      // 32/262
77         
78         // hsync
79         set_hsync(false);
80         register_event_by_clock(this, 0, tWHS, false, NULL);
81 }
82
83 void MC6847_BASE::event_callback(int event_id, int err)
84 {
85         set_hsync(true);
86 }
87
88 void MC6847_BASE::set_vsync(bool val)
89 {
90         if(vsync != val) {
91                 write_signals(&outputs_vsync, val ? 0xffffffff : 0);
92                 vsync = val;
93                 set_disp(vsync && hsync);
94         }
95 }
96
97 void MC6847_BASE::set_hsync(bool val)
98 {
99         if(hsync != val) {
100                 write_signals(&outputs_hsync, val ? 0xffffffff : 0);
101                 hsync = val;
102                 set_disp(vsync && hsync);
103         }
104 }
105
106 void MC6847_BASE::set_disp(bool val)
107 {
108         if(disp != val) {
109                 if(d_cpu != NULL && !disabled) {
110                         d_cpu->write_signal(SIG_CPU_BUSREQ, val ? 1 : 0, 1);
111                 }
112                 disp = val;
113         }
114 }
115
116 void MC6847_BASE::load_font_image(const _TCHAR *file_path)
117 {
118         // external font
119         FILEIO* fio = new FILEIO();
120         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
121                 fio->Fread(extfont, sizeof(extfont), 1);
122                 fio->Fclose();
123         }
124         delete fio;
125 }
126
127 void MC6847_BASE::draw_screen()
128 {
129         // render screen
130         if(disabled) {
131                 memset(screen, 0, sizeof(screen));
132         } else if(ag) {
133                 // graphics mode
134                 switch(gm) {
135                 case 0: draw_cg(4, 3); break;   //  64x 64
136                 case 1: draw_rg(2, 3); break;   // 128x 64
137                 case 2: draw_cg(2, 3); break;   // 128x 64
138                 case 3: draw_rg(2, 2); break;   // 128x 96
139                 case 4: draw_cg(2, 2); break;   // 128x 96
140                 case 5: draw_rg(2, 1); break;   // 128x192
141                 case 6: draw_cg(2, 1); break;   // 128x192
142                 case 7: draw_rg(1, 1); break;   // 256x192
143                 }
144         } else {
145                 // alphanumerics / semigraphics
146                 draw_alpha();
147         }
148         
149         // copy to screen
150         for(int y = 0; y < 192; y++) {
151                 scrntype_t* dest = osd->get_vm_screen_buffer(y);
152                 for(int x = 0; x < 256; x++) {
153                         dest[x] = palette_pc[screen[y][x]];
154                 }
155         }
156 }
157
158 void MC6847_BASE::draw_cg(int xofs, int yofs)
159 {
160         uint8_t color = css ? 4 : 0;
161         int ofs = 0;
162         
163         for(int y = 0; y < 192; y += yofs) {
164                 for(int x = 0; x < 256; x += xofs * 4) {
165                         uint8_t data = vram_ptr[ofs];
166                         if(++ofs >= vram_size) {
167                                 ofs = 0;
168                         }
169                         uint8_t* dest = &screen[y][x];
170                         
171                         if(xofs == 4) {
172                                 dest[ 0] = dest[ 1] = dest[ 2] = dest[ 3] = color | ((data >> 6) & 3);
173                                 dest[ 4] = dest[ 5] = dest[ 6] = dest[ 7] = color | ((data >> 4) & 3);
174                                 dest[ 8] = dest[ 9] = dest[10] = dest[11] = color | ((data >> 2) & 3);
175                                 dest[12] = dest[13] = dest[14] = dest[15] = color | ((data >> 0) & 3);
176                         } else {
177                                 dest[0] = dest[1] = color | ((data >> 6) & 3);
178                                 dest[2] = dest[3] = color | ((data >> 4) & 3);
179                                 dest[4] = dest[5] = color | ((data >> 2) & 3);
180                                 dest[6] = dest[7] = color | ((data >> 0) & 3);
181                         }
182                 }
183                 if(yofs >= 2) {
184                         my_memcpy(screen[y + 1], screen[y], 256);
185                         if(yofs >= 3) {
186                                 my_memcpy(screen[y + 2], screen[y], 256);
187                         }
188                 }
189         }
190 }
191
192 void MC6847_BASE::draw_rg(int xofs, int yofs)
193 {
194         static const uint8_t color_table[4] = {
195                 GREEN, LIGHTGREEN, BLACK, WHITE
196         };
197         static const uint8_t color_table2[4] = {
198                 BLACK, BLACK, CYAN, WHITE
199         };
200         static const uint8_t color_table3[4] = {
201                 BLACK, ORANGE, BLACK, WHITE
202         };
203         uint8_t color = css ? 2 : 0;
204         int ofs = 0;
205         
206         for(int y = 0; y < 192; y += yofs) {
207                 for(int x = 0; x < 256; x += xofs * 8) {
208                         uint8_t data = vram_ptr[ofs];
209                         if(++ofs >= vram_size) {
210                                 ofs = 0;
211                         }
212                         uint8_t* dest = &screen[y][x];
213                         
214                         if(xofs == 2) {
215                                 dest[ 0] = dest[ 1] = color_table[color | ((data >> 7) & 1)];
216                                 dest[ 2] = dest[ 3] = color_table[color | ((data >> 6) & 1)];
217                                 dest[ 4] = dest[ 5] = color_table[color | ((data >> 5) & 1)];
218                                 dest[ 6] = dest[ 7] = color_table[color | ((data >> 4) & 1)];
219                                 dest[ 8] = dest[ 9] = color_table[color | ((data >> 3) & 1)];
220                                 dest[10] = dest[11] = color_table[color | ((data >> 2) & 1)];
221                                 dest[12] = dest[13] = color_table[color | ((data >> 1) & 1)];
222                                 dest[14] = dest[15] = color_table[color | ((data >> 0) & 1)];
223                         } else if(css) {
224                                 // color bleed in black/white pattern
225                                 dest[0] = color_table2[(data >> 6) & 3];
226                                 dest[1] = color_table3[(data >> 6) & 3];
227                                 dest[2] = color_table2[(data >> 4) & 3];
228                                 dest[3] = color_table3[(data >> 4) & 3];
229                                 dest[4] = color_table2[(data >> 2) & 3];
230                                 dest[5] = color_table3[(data >> 2) & 3];
231                                 dest[6] = color_table2[(data >> 0) & 3];
232                                 dest[7] = color_table3[(data >> 0) & 3];
233                         } else {
234                                 dest[0] = color_table[(data >> 7) & 1];
235                                 dest[1] = color_table[(data >> 6) & 1];
236                                 dest[2] = color_table[(data >> 5) & 1];
237                                 dest[3] = color_table[(data >> 4) & 1];
238                                 dest[4] = color_table[(data >> 3) & 1];
239                                 dest[5] = color_table[(data >> 2) & 1];
240                                 dest[6] = color_table[(data >> 1) & 1];
241                                 dest[7] = color_table[(data >> 0) & 1];
242                         }
243                 }
244                 if(yofs >= 2) {
245                         my_memcpy(screen[y + 1], screen[y], 256);
246                         if(yofs >= 3) {
247                                 my_memcpy(screen[y + 2], screen[y], 256);
248                         }
249                 }
250         }
251 }
252
253 void MC6847_BASE::draw_alpha()
254 {
255 }
256
257 #define STATE_VERSION   1
258
259 void MC6847_BASE::save_state(FILEIO* state_fio)
260 {
261         state_fio->FputUint32(STATE_VERSION);
262         state_fio->FputInt32(this_device_id);
263         
264         state_fio->Fwrite(sg4, sizeof(sg4), 1);
265         state_fio->Fwrite(sg6, sizeof(sg6), 1);
266         state_fio->FputBool(ag);
267         state_fio->FputBool(as);
268         state_fio->FputBool(intext);
269         state_fio->FputUint8(gm);
270         state_fio->FputBool(css);
271         state_fio->FputBool(inv);
272         state_fio->FputBool(vsync);
273         state_fio->FputBool(hsync);
274         state_fio->FputBool(disp);
275         state_fio->FputInt32(tWHS);
276         state_fio->FputBool(disabled);
277 }
278
279 bool MC6847_BASE::load_state(FILEIO* state_fio)
280 {
281         if(state_fio->FgetUint32() != STATE_VERSION) {
282                 return false;
283         }
284         if(state_fio->FgetInt32() != this_device_id) {
285                 return false;
286         }
287         state_fio->Fread(sg4, sizeof(sg4), 1);
288         state_fio->Fread(sg6, sizeof(sg6), 1);
289         ag = state_fio->FgetBool();
290         as = state_fio->FgetBool();
291         intext = state_fio->FgetBool();
292         gm = state_fio->FgetUint8();
293         css = state_fio->FgetBool();
294         inv = state_fio->FgetBool();
295         vsync = state_fio->FgetBool();
296         hsync = state_fio->FgetBool();
297         disp = state_fio->FgetBool();
298         tWHS = state_fio->FgetInt32();
299         disabled = state_fio->FgetBool();
300         return true;
301 }
302