OSDN Git Service

5889a5d81b724a4ec9f04a7d7aea7b6a5a441695
[csp-qt/common_source_project-fm7.git] / source / src / vm / pasopia7 / display.cpp
1 /*
2         TOSHIBA PASOPIA 7 Emulator 'EmuPIA7'
3
4         Author : Takeda.Toshiya
5         Date   : 2007.02.08 -
6
7         [ display ]
8 */
9
10 #include "display.h"
11
12 void DISPLAY::initialize()
13 {
14         // load rom image
15         FILEIO* fio = new FILEIO();
16         if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
17                 fio->Fread(font, sizeof(font), 1);
18                 fio->Fclose();
19         }
20         delete fio;
21         
22         // create pc palette
23 #ifdef _LCD
24         for(int i = 1; i < 8; i++) {
25                 palette_pc[i] = RGB_COLOR(48, 56, 16);
26         }
27         palette_pc[0] = RGB_COLOR(160, 168, 160);
28 #else
29         for(int i = 0; i < 8; i++) {
30                 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
31         }
32 #endif
33         
34         // initialize
35         for(int i = 0; i < 16; i++) {
36                 pal[i] = i & 7;
37         }
38         mode = text_page = 0;
39         cblink = flash_cnt = 0;
40         blink = pal_dis = false;
41         
42         // register event
43         register_frame_event(this);
44 }
45
46 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
47 {
48         if(id == SIG_DISPLAY_I8255_0_A) {
49                 mode = data;
50         } else if(id == SIG_DISPLAY_I8255_1_B) {
51                 text_page = (data >> 4) & 7;
52         } else if(id == SIG_DISPLAY_I8255_1_C) {
53                 blink = ((data & 0x20) != 0);
54                 pal_dis = ((data & 8) != 0);
55         }
56 }
57
58 void DISPLAY::event_frame()
59 {
60         cblink = (cblink + 1) & 0x1f;
61 }
62
63 void DISPLAY::draw_screen()
64 {
65         // clear screen buffer
66         memset(screen, 0, sizeof(screen));
67         
68 #ifdef _LCD
69         if((regs[8] & 0x30) != 0x30) {
70                 // render screen
71                 uint16_t src = ((regs[12] << 11) | (regs[13] << 3)) & 0x3ff8;
72                 if((regs[8] & 0xc0) == 0xc0) {
73                         cursor = -1;
74                 } else {
75                         cursor = ((regs[14] << 11) | (regs[15] << 3)) & 0x3ff8;
76                 }
77                 
78                 switch(mode & 0xa0) {
79                 case 0x00:      // text, wide
80                 case 0x20:      // text, normal
81                         draw_text_lcd(src);
82                         break;
83                 case 0x80:      // fine graph, wide
84                 case 0xa0:      // fine graph, normal
85                         draw_fine_lcd(src);
86                         break;
87                 }
88         }
89         
90         // copy to real screen
91         emu->set_vm_screen_lines(64);
92         for(int y = 0; y < 64; y++) {
93                 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
94                 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
95                 uint8_t* src = screen[y];
96                 
97                 for(int x = 0; x < 320; x++) {
98                         dest0[x] = palette_pc[src[x] & 7];
99                 }
100                 if(config.scan_line) {
101                         for(int x = 0; x < 320; x++) {
102                                 dest1[x] = palette_pc[0];
103                         }
104                 } else {
105                         memcpy(dest1, dest0, 320 * sizeof(scrntype_t));
106                 }
107         }
108 #else
109         if((regs[8] & 0x30) != 0x30) {
110                 // sync check
111                 uint16_t flash = 0;
112                 if(mode & 0x20) {
113                         if(regs[0] < 106 || 118 < regs[0] || 113 < regs[2]) {
114                                 flash = 0xffff;
115                         }
116                         flash_cnt -= 320;
117                 } else {
118                         if(regs[0] < 53 || 58 < regs[0] || 56 < regs[2]) {
119                                 flash = 0xffff;
120                         }
121                         flash_cnt -= 160;
122                 }
123                 if(regs[4] < 27 || 32 < regs[4] || 16 < regs[5] || 32 < regs[7]) {
124                         flash = 0xffff;
125                 }
126                 if((regs[8] & 3) == 3 || (regs[9] != 7 && regs[9] != 6)) {
127                         flash = 0xffff;
128                 }
129                 uint16_t src = (((regs[12] << 11) | (regs[13] << 3)) + (flash_cnt & flash)) & 0x3ff8;
130                 if((regs[8] & 0xc0) == 0xc0) {
131                         cursor = -1;
132                 } else {
133                         cursor = ((regs[14] << 11) | (regs[15] << 3)) & 0x3ff8;
134                 }
135                 
136                 // render screen
137                 if((flash != 0) || (regs[8] & 0x30) != 0x30) {
138                         switch(mode & 0xa0) {
139                         case 0x00:
140                                 // text, wide
141                                 draw_text_wide(src);
142                                 flash_cnt += 40;
143                                 break;
144                         case 0x20:
145                                 // text, normal
146                                 draw_text_normal(src);
147                                 break;
148                         case 0x80:
149                                 // fine graph, wide
150                                 draw_fine_wide(src);
151                                 break;
152                         case 0xa0:
153                                 // fine graph, normal
154                                 draw_fine_normal(src);
155                                 break;
156                         }
157                 }
158         }
159         
160         // copy to real screen
161         emu->set_vm_screen_lines(200);
162         for(int y = 0; y < 200; y++) {
163                 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
164                 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
165                 uint8_t* src = screen[y];
166                 
167                 for(int x = 0; x < 640; x++) {
168                         dest0[x] = palette_pc[src[x] & 7];
169                 }
170                 if(config.scan_line) {
171 //                      for(int x = 0; x < 640; x++) {
172 //                              dest1[x] = palette_pc[0];
173 //                      }
174                         memset(dest1, 0, 640 * sizeof(scrntype_t));
175                 } else {
176                         memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
177                 }
178         }
179 #endif
180         emu->screen_skip_line(true);
181 }
182
183 void DISPLAY::draw_text_normal(uint16_t src)
184 {
185         // text mode, normal char (80chars)
186         uint16_t src_t = (src & 0x3ff8) + text_page;
187         int maxx = 79, maxy = 24, hsync_pos = 92, vsync_pos = 28;
188         int _maxx = maxx + 36, _minx = -36;
189         int homex = hsync_pos - regs[2], homey = vsync_pos - regs[7];
190         int endx = regs[1] + homex, endy = regs[6] + homey;
191         int _dstx, dstx = homex, dsty = homey;
192         
193         for(int y = 0; y < 200; y += 8) {
194                 for(int x = 0; x < 80; x++, dstx++, src = (src + 8) & 0x3ff8, src_t = (src_t + 8) & 0x3fff) {
195                         if(dstx >= endx) {
196                                 dstx = homex;
197                                 dsty++;
198                         }
199                         if(dsty >= endy) {
200                                 // exit x and y loop
201                                 y = 200;
202                                 break;
203                         }
204                         if((dsty < 0)||(dsty > maxy)) {
205                                 continue;
206                         }
207                         _dstx = dstx;
208                         if((regs[8] & 0x30) == 0x10) {
209                                 if(dstx == 0) {
210                                         _dstx = 1;
211                                 }
212                                 if(dstx == 1) {
213                                         continue;
214                                 }
215                         }
216                         if((regs[8] & 0x30) == 0x20) {
217                                 if((dstx == 0) || (dstx == 1)) {
218                                         continue;
219                                 }
220                         }
221                         if(dstx <= _minx) {
222                                 _dstx = maxx - (dstx - _minx);
223                         }
224                         if(dstx >= _maxx) {
225                                 _dstx = dstx - _maxx;
226                         }
227                         if((_dstx < 0)||(_dstx > maxx)) {
228                                 continue;
229                         }
230                         uint8_t code = vram_g[src_t];
231                         uint8_t attr = vram_a[src_t];
232                         uint8_t c, c_t = (mode & 8) ? (mode & 7) : (attr & 7);
233                         uint8_t* font_base = &font[code << 3];
234                         uint8_t p = pal_dis ? 0 : 0xff;
235                         
236                         for(int l = 0; l < 8; l++) {
237                                 uint8_t p1 = vram_b[src + l] & p;
238                                 uint8_t p2 = vram_r[src + l] & p;
239                                 uint8_t p3 = font_base[l];
240                                 // negative, blink
241                                 if(attr & 8) {
242                                         p3 = ~p3;
243                                 }
244                                 if((mode & 8) && !(attr & 4) && blink) {
245                                         p3 = 0;
246                                 }
247                                 uint8_t* d = &screen[(dsty << 3) + l][_dstx << 3];
248                                 
249                                 c = ((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | 0;
250                                 d[0] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x80) ? c_t : (pal[c] & 7);
251                                 c = ((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | 8;
252                                 d[1] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x40) ? c_t : (pal[c] & 7);
253                                 c = ((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | 0;
254                                 d[2] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x20) ? c_t : (pal[c] & 7);
255                                 c = ((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | 8;
256                                 d[3] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x10) ? c_t : (pal[c] & 7);
257                                 c = ((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | 0;
258                                 d[4] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x08) ? c_t : (pal[c] & 7);
259                                 c = ((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | 8;
260                                 d[5] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x04) ? c_t : (pal[c] & 7);
261                                 c = ((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | 0;
262                                 d[6] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x02) ? c_t : (pal[c] & 7);
263                                 c = ((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | 8;
264                                 d[7] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x01) ? c_t : (pal[c] & 7);
265                         }
266                         if(src == cursor) {
267                                 int bp = regs[10] & 0x60;
268                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
269                                         for(int i = (regs[10] & 7); i < 8; i++) {
270                                                 memset(&screen[(dsty << 3) + i][_dstx << 3], 7, 8);
271                                         }
272                                 }
273                         }
274                 }
275         }
276 }
277
278 void DISPLAY::draw_text_wide(uint16_t src)
279 {
280         // text mode, wide char (40chars)
281         uint16_t src_t = (src & 0x3ff8) + text_page;
282         int maxx = 39, maxy = 24, hsync_pos = 47, vsync_pos = 28;
283         int _maxx = maxx + 18, _minx = -18;
284         int homex = hsync_pos - regs[2], homey = vsync_pos - regs[7];
285         int endx = regs[1] + homex, endy = regs[6] + homey;
286         int _dstx, dstx = homex, dsty = homey;
287         
288         for(int y = 0; y < 200; y += 8) {
289                 for(int x = 0; x < 40; x++, dstx++, src = (src + 8) & 0x3ff8, src_t = (src_t + 8) & 0x3fff) {
290                         if(dstx >= endx) {
291                                 dstx = homex;
292                                 dsty++;
293                         }
294                         if(dsty >= endy) {
295                                 // exit x and y loop
296                                 y = 200;
297                                 break;
298                         }
299                         if((dsty < 0)||(dsty > maxy)) {
300                                 continue;
301                         }
302                         _dstx = dstx;
303                         if((regs[8] & 0x30) == 0x10) {
304                                 if(dstx == 0) {
305                                         _dstx = 1;
306                                 }
307                                 if(dstx == 1) {
308                                         continue;
309                                 }
310                         }
311                         if((regs[8] & 0x30) == 0x20) {
312                                 if((dstx == 0) || (dstx == 1)) {
313                                         continue;
314                                 }
315                         }
316                         if(dstx <= _minx) {
317                                 _dstx = maxx - (dstx - _minx);
318                         }
319                         if(dstx >= _maxx) {
320                                 _dstx = dstx - _maxx;
321                         }
322                         if((_dstx < 0)||(_dstx > maxx)) {
323                                 continue;
324                         }
325                         
326                         uint8_t code = vram_g[src_t];
327                         uint8_t attr = vram_a[src_t];
328                         uint8_t c, c_t = (mode & 8) ? (mode & 7) : (attr & 7);
329                         uint8_t* font_base = &font[code << 3];
330                         uint8_t p = pal_dis ? 0 : 0xff;
331                         
332                         for(int l = 0; l < 8; l++) {
333                                 uint8_t p1 = vram_b[src + l] & p;
334                                 uint8_t p2 = vram_r[src + l] & p;
335                                 uint8_t p3 = font_base[l];
336                                 // negative, blink
337                                 if(attr & 8) {
338                                         p3 = ~p3;
339                                 }
340                                 if((mode & 8) && !(attr & 4) && blink) {
341                                         p3 = 0;
342                                 }
343                                 uint8_t* d = &screen[(dsty << 3) + l][_dstx << 4];
344                                 
345                                 c = ((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6);
346                                 d[ 0] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x80) ? c_t : (pal[c | 0] & 7);
347                                 d[ 1] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x80) ? c_t : (pal[c | 8] & 7);
348                                 c = ((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5);
349                                 d[ 2] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x40) ? c_t : (pal[c | 0] & 7);
350                                 d[ 3] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x40) ? c_t : (pal[c | 8] & 7);
351                                 c = ((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4);
352                                 d[ 4] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x20) ? c_t : (pal[c | 0] & 7);
353                                 d[ 5] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x20) ? c_t : (pal[c | 8] & 7);
354                                 c = ((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3);
355                                 d[ 6] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x10) ? c_t : (pal[c | 0] & 7);
356                                 d[ 7] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x10) ? c_t : (pal[c | 8] & 7);
357                                 c = ((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2);
358                                 d[ 8] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x08) ? c_t : (pal[c | 0] & 7);
359                                 d[ 9] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x08) ? c_t : (pal[c | 8] & 7);
360                                 c = ((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1);
361                                 d[10] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x04) ? c_t : (pal[c | 0] & 7);
362                                 d[11] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x04) ? c_t : (pal[c | 8] & 7);
363                                 c = ((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0);
364                                 d[12] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x02) ? c_t : (pal[c | 0] & 7);
365                                 d[13] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x02) ? c_t : (pal[c | 8] & 7);
366                                 c = ((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1);
367                                 d[14] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x01) ? c_t : (pal[c | 0] & 7);
368                                 d[15] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x01) ? c_t : (pal[c | 8] & 7);
369                         }
370                         if(src == cursor) {
371                                 int bp = regs[10] & 0x60;
372                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
373                                         for(int i = (regs[10] & 7); i < 8; i++) {
374                                                 memset(&screen[(dsty << 3) + i][_dstx << 4], 7, 16);
375                                         }
376                                 }
377                         }
378                 }
379         }
380 }
381
382 void DISPLAY::draw_fine_normal(uint16_t src)
383 {
384         // fine graph mode, normal char (80chars)
385         int maxx = 79, maxy = 24, hsync_pos = 92, vsync_pos = 28;
386         int _maxx = maxx + 36, _minx = -36;
387         int homex = hsync_pos - regs[2], homey = vsync_pos - regs[7];
388         int endx = regs[1] + homex, endy = regs[6] + homey;
389         int _dstx, dstx = homex, dsty = homey;
390         
391         for(int y = 0; y < 200; y += 8) {
392                 for(int x = 0; x < 80; x++, dstx++, src = (src + 8) & 0x3ff8) {
393                         if(dstx >= endx) {
394                                 dstx = homex;
395                                 dsty++;
396                         }
397                         if(dsty >= endy) {
398                                 // exit x and y loop
399                                 y = 200;
400                                 break;
401                         }
402                         if((dsty < 0)||(dsty > maxy)) {
403                                 continue;
404                         }
405                         _dstx = dstx;
406                         if((regs[8] & 0x30) == 0x10) {
407                                 if(dstx == 0) {
408                                         _dstx = 1;
409                                 }
410                                 if(dstx == 1) {
411                                         continue;
412                                 }
413                         }
414                         if((regs[8] & 0x30) == 0x20) {
415                                 if((dstx == 0) || (dstx == 1)) {
416                                         continue;
417                                 }
418                         }
419                         if(dstx <= _minx) {
420                                 _dstx = maxx - (dstx - _minx);
421                         }
422                         if(dstx >= _maxx) {
423                                 _dstx = dstx - _maxx;
424                         }
425                         if((_dstx < 0)||(_dstx > maxx)) {
426                                 continue;
427                         }
428                         
429                         for(int l = 0; l < 8; l++) {
430                                 uint8_t code = vram_g[src + l];
431                                 uint8_t attr = vram_a[src + l];
432                                 uint8_t c, c_t = (mode & 8) ? (mode & 7) : (attr & 7);
433                                 uint8_t* font_base = &font[code << 3];
434                                 uint8_t p = pal_dis ? 0 : 0xff;
435                                 uint8_t* d = &screen[(dsty << 3) + l][_dstx << 3];
436                                 
437                                 if(attr & 8) {
438                                         // dot mode
439                                         uint8_t p1 = vram_b[src + l] & p;
440                                         uint8_t p2 = vram_r[src + l] & p;
441                                         uint8_t p3 = vram_g[src + l] & p;
442                                         
443                                         d[0] = pal[((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | ((p3 & 0x80) >> 5) | 0] & 7;
444                                         d[1] = pal[((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | ((p3 & 0x40) >> 4) | 8] & 7;
445                                         d[2] = pal[((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | ((p3 & 0x20) >> 3) | 0] & 7;
446                                         d[3] = pal[((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | ((p3 & 0x10) >> 2) | 8] & 7;
447                                         d[4] = pal[((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | ((p3 & 0x08) >> 1) | 0] & 7;
448                                         d[5] = pal[((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | ((p3 & 0x04) >> 0) | 8] & 7;
449                                         d[6] = pal[((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | ((p3 & 0x02) << 1) | 0] & 7;
450                                         d[7] = pal[((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | ((p3 & 0x01) << 2) | 8] & 7;
451                                 } else {
452                                         // text
453                                         uint8_t p1 = vram_b[src + l] & p;
454                                         uint8_t p2 = vram_r[src + l] & p;
455                                         uint8_t p3 = font_base[l];
456                                         if(mode & 8) {
457                                                 // negative, blink
458                                                 if(attr & 8) {
459                                                         p3 = ~p3;
460                                                 }
461                                                 if(!(attr & 4) && blink) {
462                                                         p3 = 0;
463                                                 }
464                                         }
465                                         c = ((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | 0;
466                                         d[0] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x80) ? c_t : (pal[c] & 7);
467                                         c = ((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | 8;
468                                         d[1] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x40) ? c_t : (pal[c] & 7);
469                                         c = ((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | 0;
470                                         d[2] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x20) ? c_t : (pal[c] & 7);
471                                         c = ((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | 8;
472                                         d[3] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x10) ? c_t : (pal[c] & 7);
473                                         c = ((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | 0;
474                                         d[4] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x08) ? c_t : (pal[c] & 7);
475                                         c = ((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | 8;
476                                         d[5] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x04) ? c_t : (pal[c] & 7);
477                                         c = ((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | 0;
478                                         d[6] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x02) ? c_t : (pal[c] & 7);
479                                         c = ((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | 8;
480                                         d[7] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x01) ? c_t : (pal[c] & 7);
481                                 }
482                         }
483                         if(src == cursor) {
484                                 int bp = regs[10] & 0x60;
485                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
486                                         for(int i = (regs[10] & 7); i < 8; i++) {
487                                                 memset(&screen[(dsty << 3) + i][_dstx << 3], 7, 8);
488                                         }
489                                 }
490                         }
491                 }
492         }
493 }
494
495 void DISPLAY::draw_fine_wide(uint16_t src)
496 {
497         // fine graph mode, wide char (40chars)
498         int maxx = 39, maxy = 24, hsync_pos = 47, vsync_pos = 28;       //WIDTH 40
499         int _maxx = maxx + 18, _minx = -18;     //WIDTH 40
500         int homex = hsync_pos - regs[2], homey = vsync_pos - regs[7];
501         int endx = regs[1] + homex, endy = regs[6] + homey;
502         int _dstx, dstx = homex, dsty = homey;
503         
504         for(int y = 0; y < 200; y += 8) {
505                 for(int x = 0; x < 40; x++, dstx++, src = (src + 8) & 0x3ff8) {
506                         if(dstx >= endx) {
507                                 dstx = homex;
508                                 dsty++;
509                         }
510                         if(dsty >= endy) {
511                                 // exit x and y loop
512                                 y = 200;
513                                 break;
514                         }
515                         if((dsty < 0)||(dsty > maxy)) {
516                                 continue;
517                         }
518                         _dstx = dstx;
519                         if((regs[8] & 0x30) == 0x10) {
520                                 if(dstx == 0) {
521                                         _dstx = 1;
522                                 }
523                                 if(dstx == 1) {
524                                         continue;
525                                 }
526                         }
527                         if((regs[8] & 0x30) == 0x20) {
528                                 if((dstx == 0) || (dstx == 1)) {
529                                         continue;
530                                 }
531                         }
532                         if(dstx <= _minx) {
533                                 _dstx = maxx - (dstx - _minx);
534                         }
535                         if(dstx >= _maxx) {
536                                 _dstx = dstx - _maxx;
537                         }
538                         if((_dstx < 0)||(_dstx > maxx)) {
539                                 continue;
540                         }
541                         
542                         for(int l = 0; l < 8; l++) {
543                                 uint8_t code = vram_g[src + l];
544                                 uint8_t attr = vram_a[src + l];
545                                 uint8_t c, c_t = (mode & 8) ? (mode & 7) : (attr & 7);
546                                 uint8_t* font_base = &font[code << 3];
547                                 uint8_t p = pal_dis ? 0 : 0xff;
548                                 uint8_t* d = &screen[(dsty << 3) + l][_dstx << 4];
549                                 
550                                 if(attr & 8) {
551                                         // dot mode
552                                         uint8_t p1 = vram_b[src + l] & p;
553                                         uint8_t p2 = vram_r[src + l] & p;
554                                         uint8_t p3 = vram_g[src + l] & p;
555                                         
556                                         d[ 0] = pal[((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | ((p3 & 0x80) >> 5) | 0] & 7;
557                                         d[ 1] = pal[((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | ((p3 & 0x80) >> 5) | 8] & 7;
558                                         d[ 2] = pal[((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | ((p3 & 0x40) >> 4) | 0] & 7;
559                                         d[ 3] = pal[((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | ((p3 & 0x40) >> 4) | 8] & 7;
560                                         d[ 4] = pal[((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | ((p3 & 0x20) >> 3) | 0] & 7;
561                                         d[ 5] = pal[((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | ((p3 & 0x20) >> 3) | 8] & 7;
562                                         d[ 6] = pal[((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | ((p3 & 0x10) >> 2) | 0] & 7;
563                                         d[ 7] = pal[((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | ((p3 & 0x10) >> 2) | 8] & 7;
564                                         d[ 8] = pal[((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | ((p3 & 0x08) >> 1) | 0] & 7;
565                                         d[ 9] = pal[((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | ((p3 & 0x08) >> 1) | 8] & 7;
566                                         d[10] = pal[((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | ((p3 & 0x04) >> 0) | 0] & 7;
567                                         d[11] = pal[((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | ((p3 & 0x04) >> 0) | 8] & 7;
568                                         d[12] = pal[((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | ((p3 & 0x02) << 1) | 0] & 7;
569                                         d[13] = pal[((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | ((p3 & 0x02) << 1) | 8] & 7;
570                                         d[14] = pal[((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | ((p3 & 0x01) << 2) | 0] & 7;
571                                         d[15] = pal[((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | ((p3 & 0x01) << 2) | 8] & 7;
572                                 } else {
573                                         // text
574                                         uint8_t p1 = vram_b[src + l] & p;
575                                         uint8_t p2 = vram_r[src + l] & p;
576                                         uint8_t p3 = font_base[l];
577                                         if(mode & 8) {
578                                                 // negative, blink
579                                                 if(attr & 8) {
580                                                         p3 = ~p3;
581                                                 }
582                                                 if(!(attr & 4) && blink) {
583                                                         p3 = 0;
584                                                 }
585                                         }
586                                         c = ((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6);
587                                         d[ 0] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x80) ? c_t : (pal[c | 0] & 7);
588                                         d[ 1] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x80) ? c_t : (pal[c | 8] & 7);
589                                         c = ((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5);
590                                         d[ 2] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x40) ? c_t : (pal[c | 0] & 7);
591                                         d[ 3] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x40) ? c_t : (pal[c | 8] & 7);
592                                         c = ((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4);
593                                         d[ 4] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x20) ? c_t : (pal[c | 0] & 7);
594                                         d[ 5] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x20) ? c_t : (pal[c | 8] & 7);
595                                         c = ((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3);
596                                         d[ 6] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x10) ? c_t : (pal[c | 0] & 7);
597                                         d[ 7] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x10) ? c_t : (pal[c | 8] & 7);
598                                         c = ((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2);
599                                         d[ 8] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x08) ? c_t : (pal[c | 0] & 7);
600                                         d[ 9] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x08) ? c_t : (pal[c | 8] & 7);
601                                         c = ((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1);
602                                         d[10] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x04) ? c_t : (pal[c | 0] & 7);
603                                         d[11] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x04) ? c_t : (pal[c | 8] & 7);
604                                         c = ((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0);
605                                         d[12] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x02) ? c_t : (pal[c | 0] & 7);
606                                         d[13] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x02) ? c_t : (pal[c | 8] & 7);
607                                         c = ((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1);
608                                         d[14] = (pal[c | 0] & 8) ? (pal[c | 0] & 7) : (p3 & 0x01) ? c_t : (pal[c | 0] & 7);
609                                         d[15] = (pal[c | 8] & 8) ? (pal[c | 8] & 7) : (p3 & 0x01) ? c_t : (pal[c | 8] & 7);
610                                 }
611                         }
612                         if(src == cursor) {
613                                 int bp = regs[10] & 0x60;
614                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
615                                         for(int i = (regs[10] & 7); i < 8; i++) {
616                                                 memset(&screen[(dsty << 3) + i][_dstx << 4], 7, 16);
617                                         }
618                                 }
619                         }
620                 }
621         }
622 }
623
624 void DISPLAY::draw_text_lcd(uint16_t src)
625 {
626         // text mode, nomarl char (80chars)
627         for(int y = 0, yy = 0; y < 64; y += 8, yy++) {
628                 int src_g = (src + 640 * (yy & 3) + (yy & 4 ? 8 : 0)) & 0x3ff8;
629                 int src_t = src_g;// + text_page;
630                 
631                 for(int x = 0; x < 40; x++) {
632                         uint8_t code = vram_g[src_t];
633                         uint8_t attr = vram_a[src_t];
634                         uint8_t c, c_t = (mode & 8) ? (mode & 7) : (attr & 7);
635                         uint8_t* font_base = &font[code << 3];
636                         
637                         for(int l = 0; l < 8; l++) {
638                                 uint8_t p1 = vram_b[src_g + l];
639                                 uint8_t p2 = vram_r[src_g + l];
640                                 uint8_t p3 = font_base[l];
641                                 // negative, blink
642                                 if(attr & 8) {
643                                         p3 = ~p3;
644                                 }
645                                 if((mode & 8) && !(attr & 4) && blink) {
646                                         p3 = 0;
647                                 }
648                                 uint8_t* d = &screen[y + l][x << 3];
649                                 
650                                 c = ((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | 0;
651                                 d[0] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x80) ? c_t : (pal[c] & 7);
652                                 c = ((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | 8;
653                                 d[1] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x40) ? c_t : (pal[c] & 7);
654                                 c = ((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | 0;
655                                 d[2] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x20) ? c_t : (pal[c] & 7);
656                                 c = ((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | 8;
657                                 d[3] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x10) ? c_t : (pal[c] & 7);
658                                 c = ((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | 0;
659                                 d[4] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x08) ? c_t : (pal[c] & 7);
660                                 c = ((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | 8;
661                                 d[5] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x04) ? c_t : (pal[c] & 7);
662                                 c = ((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | 0;
663                                 d[6] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x02) ? c_t : (pal[c] & 7);
664                                 c = ((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | 8;
665                                 d[7] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x01) ? c_t : (pal[c] & 7);
666                         }
667                         if(src_g == cursor) {
668                                 int bp = regs[10] & 0x60;
669                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
670                                         for(int i = (regs[10] & 7); i < 8; i++) {
671                                                 memset(&screen[y + i][x << 3], 7, 8);
672                                         }
673                                 }
674                         }
675                         src_g = (src_g + 16) & 0x3ff8;
676                         src_t = (src_t + 16) & 0x3fff;
677                 }
678         }
679 }
680
681 void DISPLAY::draw_fine_lcd(uint16_t src)
682 {
683         // fine graph mode, normal char (80chars)
684         for(int y = 0, yy = 0; y < 64; y += 8, yy++) {
685                 int src_g = (src + 640 * (yy & 3) + (yy & 4 ? 8 : 0)) & 0x3ff8;
686                 
687                 for(int x = 0; x < 80; x++) {
688                         uint8_t code = vram_g[src_g];
689                         uint8_t attr = vram_a[src_g];
690                         uint8_t c, c_t = (mode & 8) ? (mode & 7) : (attr & 7);
691                         uint8_t* font_base = &font[code << 3];
692                         
693                         if(attr & 8) {
694                                 // dot mode
695                                 for(int l = 0; l < 8; l++) {
696                                         uint8_t p1 = vram_b[src_g + l];
697                                         uint8_t p2 = vram_r[src_g + l];
698                                         uint8_t p3 = vram_g[src_g + l];
699                                         uint8_t* d = &screen[y + l][x << 3];
700                                         
701                                         d[0] = pal[((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | ((p3 & 0x80) >> 5) | 0] & 7;
702                                         d[1] = pal[((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | ((p3 & 0x40) >> 4) | 8] & 7;
703                                         d[2] = pal[((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | ((p3 & 0x20) >> 3) | 0] & 7;
704                                         d[3] = pal[((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | ((p3 & 0x10) >> 2) | 8] & 7;
705                                         d[4] = pal[((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | ((p3 & 0x08) >> 1) | 0] & 7;
706                                         d[5] = pal[((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | ((p3 & 0x04) >> 0) | 8] & 7;
707                                         d[6] = pal[((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | ((p3 & 0x02) << 1) | 0] & 7;
708                                         d[7] = pal[((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | ((p3 & 0x01) << 2) | 8] & 7;
709                                 }
710                         } else {
711                                 // text
712                                 for(int l = 0; l < 8; l++) {
713                                         uint8_t p1 = vram_b[src_g + l];
714                                         uint8_t p2 = vram_r[src_g + l];
715                                         uint8_t p3 = font_base[l];
716                                         if(mode & 8) {
717                                                 // negative, blink
718                                                 if(attr & 8) {
719                                                         p3 = ~p3;
720                                                 }
721                                                 if(!(attr & 4) && blink) {
722                                                         p3 = 0;
723                                                 }
724                                         }
725                                         uint8_t* d = &screen[y + l][x << 3];
726                                         
727                                         c = ((p1 & 0x80) >> 7) | ((p2 & 0x80) >> 6) | 0;
728                                         d[0] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x80) ? c_t : (pal[c] & 7);
729                                         c = ((p1 & 0x40) >> 6) | ((p2 & 0x40) >> 5) | 8;
730                                         d[1] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x40) ? c_t : (pal[c] & 7);
731                                         c = ((p1 & 0x20) >> 5) | ((p2 & 0x20) >> 4) | 0;
732                                         d[2] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x20) ? c_t : (pal[c] & 7);
733                                         c = ((p1 & 0x10) >> 4) | ((p2 & 0x10) >> 3) | 8;
734                                         d[3] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x10) ? c_t : (pal[c] & 7);
735                                         c = ((p1 & 0x08) >> 3) | ((p2 & 0x08) >> 2) | 0;
736                                         d[4] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x08) ? c_t : (pal[c] & 7);
737                                         c = ((p1 & 0x04) >> 2) | ((p2 & 0x04) >> 1) | 8;
738                                         d[5] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x04) ? c_t : (pal[c] & 7);
739                                         c = ((p1 & 0x02) >> 1) | ((p2 & 0x02) >> 0) | 0;
740                                         d[6] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x02) ? c_t : (pal[c] & 7);
741                                         c = ((p1 & 0x01) >> 0) | ((p2 & 0x01) << 1) | 8;
742                                         d[7] = (pal[c] & 8) ? (pal[c] & 7) : (p3 & 0x01) ? c_t : (pal[c] & 7);
743                                 }
744                         }
745                         if(src_g == cursor) {
746                                 int bp = regs[10] & 0x60;
747                                 if(bp == 0 || (bp == 0x40 && (cblink & 8)) || (bp == 0x60 && (cblink & 0x10))) {
748                                         for(int i = (regs[10] & 7); i < 8; i++) {
749                                                 memset(&screen[y + i][x << 3], 7, 8);
750                                         }
751                                 }
752                         }
753                         src_g = (src_g + 16) & 0x3ff8;
754                 }
755         }
756 }
757
758 #define STATE_VERSION   1
759
760 bool DISPLAY::process_state(FILEIO* state_fio, bool loading)
761 {
762         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
763                 return false;
764         }
765         if(!state_fio->StateCheckInt32(this_device_id)) {
766                 return false;
767         }
768         state_fio->StateUint8(mode);
769         state_fio->StateUint8(text_page);
770         state_fio->StateUint16(cursor);
771         state_fio->StateUint16(cblink);
772         state_fio->StateUint16(flash_cnt);
773         state_fio->StateBool(blink);
774         state_fio->StateBool(pal_dis);
775         return true;
776 }