OSDN Git Service

[VM][FMTOWNS][MEMORY] Fix setup around memory banks by I/O 0404h and 0480h.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pasopia / display.cpp
1 /*
2         TOSHIBA PASOPIA Emulator 'EmuPIA'
3
4         Author : Takeda.Toshiya
5         Date   : 2007.02.08 -
6
7         [ display ]
8 */
9
10 #include "display.h"
11
12 namespace PASOPIA {
13
14 void DISPLAY::initialize()
15 {
16         // load rom image
17         FILEIO* fio = new FILEIO();
18         if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
19                 fio->Fread(font, sizeof(font), 1);
20                 fio->Fclose();
21         }
22         delete fio;
23         
24         // create pc palette
25 #ifdef _LCD
26         for(int i = 1; i < 8; i++) {
27                 palette_pc[i] = RGB_COLOR(48, 56, 16);
28         }
29         palette_pc[0] = RGB_COLOR(160, 168, 160);
30 #else
31         for(int i = 0; i < 8; i++) {
32                 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
33         }
34 #endif
35         
36         // init pasopia own
37         mode = 0;
38         cblink = 0;
39         
40         // register event
41         register_frame_event(this);
42 }
43
44 void DISPLAY::write_io8(uint32_t addr, uint32_t data)
45 {
46         switch(addr & 0xff) {
47         case 0x10:
48                 d_crtc->write_io8(addr, data);
49                 break;
50         case 0x11:
51                 d_crtc->write_io8(addr, data);
52                 break;
53         }
54 }
55
56 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
57 {
58         // from 8255-1 port.a
59         mode = data;
60 }
61
62 void DISPLAY::event_frame()
63 {
64         cblink = (cblink + 1) & 0x1f;
65 }
66
67 void DISPLAY::draw_screen()
68 {
69         if((regs[8] & 0x30) != 0x30) {
70                 uint16_t src = ((regs[12] << 8) | regs[13]) & 0x7ff;
71                 if((regs[8] & 0xc0) == 0xc0) {
72                         cursor = -1;
73                 } else {
74                         cursor = ((regs[14] << 8) | regs[15]) & 0x7ff;
75                 }
76                 
77                 // render screen
78                 memset(screen, mode & 7, sizeof(screen));
79                 
80                 switch(mode & 0xe0) {
81                 case 0x00:      // screen 0, wide
82                         draw_screen0_wide(src);
83                         break;
84                 case 0x20:      // screen 0, normal
85                         draw_screen0_normal(src);
86                         break;
87                 case 0x40:      // screen 1, wide
88                         draw_screen1_wide(src);
89                         break;
90                 case 0x60:      // screen 1, normal
91                         draw_screen1_normal(src);
92                         break;
93                 case 0x80:      // screen 2, wide
94                         draw_screen2_wide(src);
95                         break;
96                 case 0xa0:      // screen 2, normal
97                         draw_screen2_normal(src);
98                         break;
99                 case 0xc0:      // screen 1.5, wide
100                         draw_screen15_wide(src);
101                         break;
102                 case 0xe0:      // screen 1.5, normal
103                         draw_screen15_normal(src);
104                         break;
105                 }
106         } else {
107                 memset(screen, 0, sizeof(screen));
108         }
109         
110         // copy to real screen
111         emu->set_vm_screen_lines(200);
112         
113         uint16_t bcol = palette_pc[mode & 7];
114         emu->set_vm_screen_lines(200);
115         for(int y = 0; y < 200; y++) {
116                 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
117                 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
118                 uint8_t* src = screen[y];
119                 
120                 for(int x = 0; x < 640; x++) {
121                         dest0[x] = palette_pc[src[x] & 7];
122                 }
123                 if(config.scan_line) {
124                         memset(dest1, 0, 640 * sizeof(scrntype_t));
125                 } else {
126                         memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
127                 }
128         }
129         emu->screen_skip_line(true);
130 }
131
132 #define IS_ATTRIB(d) (((d) & 0xf8) == 0xf8)
133
134 void DISPLAY::draw_screen0_normal(uint16_t src)
135 {
136         // screen 0, normal char (80chars)
137         uint16_t src_t = src & 0x7ff;
138         uint8_t c_b = mode & 7;
139         int width = regs[1] - 1;
140         
141         for(int y = 0; y < 200; y += 8) {
142                 uint8_t c_t = IS_ATTRIB(vram[src_t]) ? (vram[src_t] & 7) : 7;
143                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
144                 
145                 for(int x = 0; x < width; x++) {
146                         uint8_t code = vram[src_t];
147                         if(IS_ATTRIB(code)) {
148                                 c_t = code & 7;
149                         }
150                         uint8_t* font_base = &font[code << 3];
151                         
152                         for(int l = 0; l < 8; l++) {
153                                 uint8_t p = font_base[l];
154                                 uint8_t* d = &screen[y + l][x << 3];
155                                 
156                                 d[0] = (p & 0x80) ? c_t : c_b;
157                                 d[1] = (p & 0x40) ? c_t : c_b;
158                                 d[2] = (p & 0x20) ? c_t : c_b;
159                                 d[3] = (p & 0x10) ? c_t : c_b;
160                                 d[4] = (p & 0x08) ? c_t : c_b;
161                                 d[5] = (p & 0x04) ? c_t : c_b;
162                                 d[6] = (p & 0x02) ? c_t : c_b;
163                                 d[7] = (p & 0x01) ? c_t : c_b;
164                         }
165                         if(src_t == cursor) {
166                                 int bp = regs[10] & 0x60;
167                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
168                                         for(int i = (regs[10] & 7); i < 8; i++) {
169                                                 memset(&screen[y + i][x << 3], 7, 8);
170                                         }
171                                 }
172                         }
173                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
174                 }
175         }
176 }
177
178 void DISPLAY::draw_screen0_wide(uint16_t src)
179 {
180         // screen 0, wide char (36chars)
181         uint16_t src_t = src & 0x7ff;
182         uint8_t c_b = mode & 7;
183         int width = regs[1] - 1;
184         
185         for(int y = 0; y < 192; y += 8) {
186                 uint8_t c_t = IS_ATTRIB(vram[src_t]) ? (vram[src_t] & 7) : 7;
187                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
188                 
189                 for(int x = 0; x < width; x++) {
190                         uint8_t code = vram[src_t];
191                         if(IS_ATTRIB(code)) {
192                                 c_t = code & 7;
193                         }
194                         uint8_t* font_base = &font[code << 3];
195                         
196                         for(int l = 0; l < 8; l++) {
197                                 uint8_t p = font_base[l];
198                                 uint8_t* d = &screen[y + l][x << 4];
199                                 
200                                 d[ 0] = d[ 1] = (p & 0x80) ? c_t : c_b;
201                                 d[ 2] = d[ 3] = (p & 0x40) ? c_t : c_b;
202                                 d[ 4] = d[ 5] = (p & 0x20) ? c_t : c_b;
203                                 d[ 6] = d[ 7] = (p & 0x10) ? c_t : c_b;
204                                 d[ 8] = d[ 9] = (p & 0x08) ? c_t : c_b;
205                                 d[10] = d[11] = (p & 0x04) ? c_t : c_b;
206                                 d[12] = d[13] = (p & 0x02) ? c_t : c_b;
207                                 d[14] = d[15] = (p & 0x01) ? c_t : c_b;
208                         }
209                         if(src_t == cursor) {
210                                 int bp = regs[10] & 0x60;
211                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
212                                         for(int i = (regs[10] & 7); i < 8; i++) {
213                                                 memset(&screen[y + i][x << 4], 7, 16);
214                                         }
215                                 }
216                         }
217                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
218                 }
219         }
220 }
221
222 void DISPLAY::draw_screen1_normal(uint16_t src)
223 {
224         // screen 1, normal char (80chars)
225         uint16_t src_t = src & 0x7ff;
226         uint8_t c_b = mode & 7;
227         int width = regs[1] - 1;
228         uint8_t c_t[8] = {7, 7, 7, 7, 7, 7, 7, 7};
229         
230         for(int y = 0; y < 200; y += 8) {
231                 // character data is set for every other line in scren 1
232                 for(int i = 0; i < 8; i += 2) {
233                         uint8_t t = vram[src_t + (i * 0x800)];
234                         if(IS_ATTRIB(t)) {
235                                 c_t[i] = c_t[i + 1] = t & 7;
236                         }
237                 }
238                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
239                 
240                 for(int x = 0; x < width; x++) {
241                         bool is_graph[8];
242                         uint8_t attr_t[8];
243                         uint8_t code[8];
244                         for(int i = 0; i < 8; i += 2) {
245                                 uint16_t t = (src_t + (i * 0x800)) & 0x3fff;
246                                 is_graph[i] = is_graph[i + 1] = (attr[t] != 0);
247                                 attr_t[i] = attr_t[i + 1] = attr[t];
248                                 code[i] = code[i + 1] = vram[t];
249                         }
250                         
251                         for(int l = 0; l < 8; l++) {
252                                 // change line color if vram data is text and is attribute character
253                                 // note: check only first line
254                                 uint8_t code_t = code[l];
255                                 if(!is_graph[l] && IS_ATTRIB(code_t)) {
256                                         c_t[l] = code_t & 7;
257                                 }
258                                 uint8_t* font_base = &font[code_t << 3];
259                                 uint8_t c_l = c_t[l], c_r = c_t[l], p = font_base[l];
260                                 if(is_graph[l]) {
261                                         if(attr_t[l]) {
262                                                 p = code_t;
263                                                 c_l = (p >> 4) & 7;
264                                                 c_r = p & 7;
265                                                 p = (p & 0xf0 ? 0xf0 : 0) | (p & 0x0f ? 0x0f : 0);
266                                         } else {
267                                                 p = 0;
268                                         }
269                                 }
270                                 uint8_t* d = &screen[y + l][x << 3];
271                                 
272                                 d[0] = (p & 0x80) ? c_l : c_b;
273                                 d[1] = (p & 0x40) ? c_l : c_b;
274                                 d[2] = (p & 0x20) ? c_l : c_b;
275                                 d[3] = (p & 0x10) ? c_l : c_b;
276                                 d[4] = (p & 0x08) ? c_r : c_b;
277                                 d[5] = (p & 0x04) ? c_r : c_b;
278                                 d[6] = (p & 0x02) ? c_r : c_b;
279                                 d[7] = (p & 0x01) ? c_r : c_b;
280                         }
281                         if(src_t == cursor) {
282                                 int bp = regs[10] & 0x60;
283                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
284                                         for(int i = (regs[10] & 7); i < 8; i++) {
285                                                 memset(&screen[y + i][x << 3], 7, 8);
286                                         }
287                                 }
288                         }
289                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
290                 }
291         }
292 }
293
294 void DISPLAY::draw_screen1_wide(uint16_t src)
295 {
296         // screen 1, wide char (36chars)
297         uint16_t src_t = src & 0x7ff;
298         uint8_t c_b = mode & 7;
299         int width = regs[1] - 1;
300         uint8_t c_t[8] = {7, 7, 7, 7, 7, 7, 7, 7};
301         
302         for(int y = 0; y < 192; y += 8) {
303                 // character data is set for every other line in scren 1
304                 for(int i = 0; i < 8; i += 2) {
305                         uint8_t t = vram[src_t + (i * 0x800)];
306                         if(IS_ATTRIB(t)) {
307                                 c_t[i] = c_t[i + 1] = t & 7;
308                         }
309                 }
310                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
311                 
312                 for(int x = 0; x < width; x++) {
313                         bool is_graph[8];
314                         uint8_t attr_t[8];
315                         uint8_t code[8];
316                         for(int i = 0; i < 8; i += 2) {
317                                 uint16_t t = (src_t + (i * 0x800)) & 0x3fff;
318                                 is_graph[i] = is_graph[i + 1] = (attr[t] != 0);
319                                 attr_t[i] = attr_t[i + 1] = attr[t];
320                                 code[i] = code[i + 1] = vram[t];
321                         }
322                         
323                         for(int l = 0; l < 8; l++) {
324                                 // change line color if vram data is text and is attribute character
325                                 // note: check only first line
326                                 uint8_t code_t = code[l];
327                                 if(!is_graph[l] && IS_ATTRIB(code_t)) {
328                                         c_t[l] = code_t & 7;
329                                 }
330                                 uint8_t* font_base = &font[code_t << 3];
331                                 uint8_t c_l = c_t[l], c_r = c_t[l], p = font_base[l];
332                                 if(is_graph[l]) {
333                                         if(attr_t[l]) {
334                                                 p = code_t;
335                                                 c_l = (p >> 4) & 7;
336                                                 c_r = p & 7;
337                                                 p = (p & 0xf0 ? 0xf0 : 0) | (p & 0x0f ? 0x0f : 0);
338                                         } else {
339                                                 p = 0;
340                                         }
341                                 }
342                                 uint8_t* d = &screen[y + l][x << 4];
343                                 
344                                 d[ 0] = d[ 1] = (p & 0x80) ? c_l : c_b;
345                                 d[ 2] = d[ 3] = (p & 0x40) ? c_l : c_b;
346                                 d[ 4] = d[ 5] = (p & 0x20) ? c_l : c_b;
347                                 d[ 6] = d[ 7] = (p & 0x10) ? c_l : c_b;
348                                 d[ 8] = d[ 9] = (p & 0x08) ? c_r : c_b;
349                                 d[10] = d[11] = (p & 0x04) ? c_r : c_b;
350                                 d[12] = d[13] = (p & 0x02) ? c_r : c_b;
351                                 d[14] = d[15] = (p & 0x01) ? c_r : c_b;
352                         }
353                         if(src_t == cursor) {
354                                 int bp = regs[10] & 0x60;
355                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
356                                         for(int i = (regs[10] & 7); i < 8; i++) {
357                                                 memset(&screen[y + i][x << 4], 7, 16);
358                                         }
359                                 }
360                         }
361                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
362                 }
363         }
364 }
365
366 void DISPLAY::draw_screen2_normal(uint16_t src)
367 {
368         // screen 2, normal char (80chars)
369         uint16_t src_t = src & 0x7ff;
370         uint8_t c_b = mode & 7;
371         int width = regs[1] - 1;
372         uint8_t c_t[8] = {7, 7, 7, 7, 7, 7, 7, 7};
373         
374         for(int y = 0; y < 200; y += 8) {
375                 // character data is set for every line in scren 2
376                 for(int i = 0; i < 8; i++) {
377                         uint8_t t = vram[src_t + (i * 0x800)];
378                         if(IS_ATTRIB(t)) {
379                                 c_t[i] = t & 7;
380                         }
381                 }
382                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
383                 
384                 for(int x = 0; x < width; x++) {
385                         uint16_t src_g = src_t;
386                         bool is_graph[8];
387                         uint8_t code[8];
388                         for(int i = 0; i < 8; i++) {
389                                 uint16_t t = (src_t + (i * 0x800)) & 0x3fff;
390                                 is_graph[i] = (attr[t] != 0);
391                                 code[i] = vram[t];
392                         }
393                         
394                         for(int l = 0; l < 8; l++) {
395                                 // change line color if vram data is text and is attribute character
396                                 uint8_t code_t = code[l];
397                                 if(!is_graph[l] && (0xf8 <= code_t) && (code_t <= 0xff)) {
398                                         c_t[l] = code_t & 7;
399                                 }
400                                 uint8_t c_l = c_t[l], c_r = c_t[l];
401                                 
402                                 uint8_t* font_base = &font[code_t << 3];
403                                 uint8_t p = is_graph[l] ? (attr[src_g] ? vram[src_g] : 0) : font_base[l];
404                                 src_g = (src_g + 0x800) & 0x3fff;
405                                 uint8_t c_p = /*is_graph[l] ? 7 : */c_t[l];
406                                 uint8_t* d = &screen[y + l][x << 3];
407                                 
408                                 d[0] = (p & 0x80) ? c_p : c_b;
409                                 d[1] = (p & 0x40) ? c_p : c_b;
410                                 d[2] = (p & 0x20) ? c_p : c_b;
411                                 d[3] = (p & 0x10) ? c_p : c_b;
412                                 d[4] = (p & 0x08) ? c_p : c_b;
413                                 d[5] = (p & 0x04) ? c_p : c_b;
414                                 d[6] = (p & 0x02) ? c_p : c_b;
415                                 d[7] = (p & 0x01) ? c_p : c_b;
416                         }
417                         if(src_t == cursor) {
418                                 int bp = regs[10] & 0x60;
419                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
420                                         for(int i = (regs[10] & 7); i < 8; i++) {
421                                                 memset(&screen[y + i][x << 3], 7, 8);
422                                         }
423                                 }
424                         }
425                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
426                 }
427         }
428 }
429
430 void DISPLAY::draw_screen2_wide(uint16_t src)
431 {
432         // screen 0, wide char (36chars)
433         uint16_t src_t = src & 0x7ff;
434         uint8_t c_b = mode & 7;
435         int width = regs[1] - 1;
436         uint8_t c_t[8] = {7, 7, 7, 7, 7, 7, 7, 7};
437         
438         for(int y = 0; y < 192; y += 8) {
439                 // character data is set for every line in scren 2
440                 for(int i = 0; i < 8; i++) {
441                         uint8_t t = vram[src_t + (i * 0x800)];
442                         if(IS_ATTRIB(t)) {
443                                 c_t[i] = t & 7;
444                         }
445                 }
446                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
447                 
448                 for(int x = 0; x < width; x++) {
449                         uint16_t src_g = src_t;
450                         bool is_graph[8];
451                         uint8_t code[8];
452                         for(int i = 0; i < 8; i++) {
453                                 uint16_t t = (src_t + (i * 0x800)) & 0x3fff;
454                                 is_graph[i] = (attr[t] != 0);
455                                 code[i] = vram[t];
456                         }
457                         for(int l = 0; l < 8; l++) {
458                                 // change line color if vram data is text and is attribute character
459                                 uint8_t code_t = code[l];
460                                 if(!is_graph[l] && IS_ATTRIB(code_t)) {
461                                         c_t[l] = code_t & 7;
462                                 }
463                                 uint8_t c_l = c_t[l], c_r = c_t[l];
464                                 
465                                 uint8_t* font_base = &font[code_t << 3];
466                                 uint8_t p = is_graph[l] ? (attr[src_g] ? vram[src_g] : 0) : font_base[l];
467                                 src_g = (src_g + 0x800) & 0x3fff;
468                                 uint8_t c_p = /*is_graph[l] ? 7 : */c_t[l];
469                                 uint8_t* d = &screen[y + l][x << 4];
470                                 
471                                 d[ 0] = d[ 1] = (p & 0x80) ? c_p : c_b;
472                                 d[ 2] = d[ 3] = (p & 0x40) ? c_p : c_b;
473                                 d[ 4] = d[ 5] = (p & 0x20) ? c_p : c_b;
474                                 d[ 6] = d[ 7] = (p & 0x10) ? c_p : c_b;
475                                 d[ 8] = d[ 9] = (p & 0x08) ? c_p : c_b;
476                                 d[10] = d[11] = (p & 0x04) ? c_p : c_b;
477                                 d[12] = d[13] = (p & 0x02) ? c_p : c_b;
478                                 d[14] = d[15] = (p & 0x01) ? c_p : c_b;
479                         }
480                         if(src_t == cursor) {
481                                 int bp = regs[10] & 0x60;
482                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
483                                         for(int i = (regs[10] & 7); i < 8; i++) {
484                                                 memset(&screen[y + i][x << 4], 7, 16);
485                                         }
486                                 }
487                         }
488                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
489                 }
490         }
491 }
492
493 void DISPLAY::draw_screen15_normal(uint16_t src)
494 {
495         // screen 2, normal char (80chars)
496         uint16_t src_t = src & 0x7ff;
497         uint8_t c_b = mode & 7;
498         int width = regs[1] - 1;
499         uint8_t c_t[8] = {7, 7, 7, 7, 7, 7, 7, 7};
500         
501         for(int y = 0; y < 200; y += 8) {
502                 // character data is set for every line in scren 1.5
503                 for(int i = 0; i < 8; i++) {
504                         uint8_t t = vram[src_t + (i * 0x800)];
505                         if(IS_ATTRIB(t)) {
506                                 c_t[i] = t & 7;
507                         }
508                 }
509                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
510                 
511                 for(int x = 0; x < width; x++) {
512                         bool is_graph[8];
513                         uint8_t attr_t[8];
514                         uint8_t code[8];
515                         for(int i = 0; i < 8; i++) {
516                                 uint16_t t = (src_t + (i * 0x800)) & 0x3fff;
517                                 is_graph[i] = (attr[t] != 0);
518                                 attr_t[i] = attr[t];
519                                 code[i] = vram[t];
520                         }
521                         for(int l = 0; l < 8; l++) {
522                                 // change line color if vram data is text and is attribute character
523                                 uint8_t code_t = code[l];
524                                 if(!is_graph[l] && IS_ATTRIB(code_t)) {
525                                         c_t[l] = code_t & 7;
526                                 }
527                                 uint8_t* font_base = &font[code_t << 3];
528                                 uint8_t c_l = c_t[l], c_r = c_t[l], p = font_base[l];
529                                 if(is_graph[l]) {
530                                         if(attr_t[l]) {
531                                                 p = code_t;
532                                                 c_l = (p >> 4) & 7;
533                                                 c_r = p & 7;
534                                                 p = (p & 0xf0 ? 0xf0 : 0) | (p & 0x0f ? 0x0f : 0);
535                                         } else {
536                                                 p = 0;
537                                         }
538                                 }
539                                 uint8_t* d = &screen[y + l][x << 3];
540                                 
541                                 d[0] = (p & 0x80) ? c_l : c_b;
542                                 d[1] = (p & 0x40) ? c_l : c_b;
543                                 d[2] = (p & 0x20) ? c_l : c_b;
544                                 d[3] = (p & 0x10) ? c_l : c_b;
545                                 d[4] = (p & 0x08) ? c_r : c_b;
546                                 d[5] = (p & 0x04) ? c_r : c_b;
547                                 d[6] = (p & 0x02) ? c_r : c_b;
548                                 d[7] = (p & 0x01) ? c_r : c_b;
549                         }
550                         if(src_t == cursor) {
551                                 int bp = regs[10] & 0x60;
552                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
553                                         for(int i = (regs[10] & 7); i < 8; i++) {
554                                                 memset(&screen[y + i][x << 3], 7, 8);
555                                         }
556                                 }
557                         }
558                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
559                 }
560         }
561 }
562
563 void DISPLAY::draw_screen15_wide(uint16_t src)
564 {
565         // screen 0, normal char (80chars)
566         uint16_t src_t = src & 0x7ff;
567         uint8_t c_b = mode & 7;
568         int width = regs[1] - 1;
569         uint8_t c_t[8] = {7, 7, 7, 7, 7, 7, 7, 7};
570         
571         for(int y = 0; y < 192; y += 8) {
572                 // character data is set for every line in scren 1.5
573                 for(int i = 0; i < 8; i++) {
574                         uint8_t t = vram[src_t + (i * 0x800)];
575                         if(IS_ATTRIB(t)) {
576                                 c_t[i] = t & 7;
577                         }
578                 }
579                 src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
580                 
581                 for(int x = 0; x < width; x++) {
582                         bool is_graph[8];
583                         uint8_t attr_t[8];
584                         uint8_t code[8];
585                         for(int i = 0; i < 8; i++) {
586                                 uint16_t t = (src_t + (i * 0x800)) & 0x3fff;
587                                 is_graph[i] = (attr[t] != 0);
588                                 attr_t[i] = attr[t];
589                                 code[i] = vram[t];
590                         }
591                         
592                         for(int l = 0; l < 8; l++) {
593                                 // change line color if vram data is text and is attribute character
594                                 uint8_t code_t = code[l];
595                                 if(!is_graph[l] && IS_ATTRIB(code_t)) {
596                                         c_t[l] = code_t & 7;
597                                 }
598                                 uint8_t* font_base = &font[code_t << 3];
599                                 uint8_t c_l = c_t[l], c_r = c_t[l], p = font_base[l];
600                                 if(is_graph[l]) {
601                                         if(attr_t[l]) {
602                                                 p = code_t;
603                                                 c_l = (p >> 4) & 7;
604                                                 c_r = p & 7;
605                                                 p = (p & 0xf0 ? 0xf0 : 0) | (p & 0x0f ? 0x0f : 0);
606                                         } else {
607                                                 p = 0;
608                                         }
609                                 }
610                                 uint8_t* d = &screen[y + l][x << 4];
611                                 
612                                 d[ 0] = d[ 1] = (p & 0x80) ? c_l : c_b;
613                                 d[ 2] = d[ 3] = (p & 0x40) ? c_l : c_b;
614                                 d[ 4] = d[ 5] = (p & 0x20) ? c_l : c_b;
615                                 d[ 6] = d[ 7] = (p & 0x10) ? c_l : c_b;
616                                 d[ 8] = d[ 9] = (p & 0x08) ? c_r : c_b;
617                                 d[10] = d[11] = (p & 0x04) ? c_r : c_b;
618                                 d[12] = d[13] = (p & 0x02) ? c_r : c_b;
619                                 d[14] = d[15] = (p & 0x01) ? c_r : c_b;
620                         }
621                         if(src_t == cursor) {
622                                 int bp = regs[10] & 0x60;
623                                 if((bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
624                                         for(int i = (regs[10] & 7); i < 8; i++) {
625                                                 memset(&screen[y + i][x << 4], 7, 16);
626                                         }
627                                 }
628                         }
629                         src_t = (src_t & 0x3800) | ((src_t + 1) & 0x7ff);
630                 }
631         }
632 }
633
634 #define STATE_VERSION   1
635
636 bool DISPLAY::process_state(FILEIO* state_fio, bool loading)
637 {
638         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
639                 return false;
640         }
641         if(!state_fio->StateCheckInt32(this_device_id)) {
642                 return false;
643         }
644         state_fio->StateValue(mode);
645         state_fio->StateValue(cursor);
646         state_fio->StateValue(cblink);
647         return true;
648 }
649
650 }