OSDN Git Service

[VM][FM77AV][MB61VH010] More accurate lines.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / mb61vh010.cpp
1 /*
2  * FM77AV/FM16β ALU [mb61vh010.cpp]
3  *  of Fujitsu MB61VH010/011
4  *
5  * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
6  * License: GPLv2
7  * History:
8  *   Mar 28, 2015 : Initial
9  *
10  */
11
12 #include "mb61vh010.h"
13
14
15 MB61VH010::MB61VH010(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
16 {
17         p_emu = parent_emu;
18         p_vm = parent_vm;
19 }
20
21 MB61VH010::~MB61VH010()
22 {
23 }
24
25 uint8 MB61VH010::do_read(uint32 addr, uint32 bank)
26 {
27         uint32 raddr;
28         uint32 offset;
29         
30         if(((1 << bank) & read_signal(SIG_DISPLAY_MULTIPAGE)) != 0) return 0xff;
31         //if(is_400line) offset = 0x8000;
32         
33         if(is_400line) {
34                 if((addr & 0xffff) < 0x8000) {
35                         //raddr = ((addr + (line_addr_offset.w.l << 1)) & 0x7fff) | (0x8000 * bank);
36                         raddr = (addr  & 0x7fff) | (0x8000 * bank);
37                         return target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
38                 }
39                 return 0xff;
40         } else {
41                 //raddr = ((addr + (line_addr_offset.w.l << 1)) & 0x3fff) | (0x4000 * bank);
42                 raddr = (addr & 0x3fff) | (0x4000 * bank);
43                 return target->read_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS);
44         }
45         return 0xff;
46 }
47
48 uint8 MB61VH010::do_write(uint32 addr, uint32 bank, uint8 data)
49 {
50         uint32 raddr;
51         uint8 readdata;
52
53         if(((1 << bank) & read_signal(SIG_DISPLAY_MULTIPAGE)) != 0) return 0xff;
54         if((command_reg & 0x40) != 0) { // Calculate before writing
55                 readdata = do_read(addr, bank);
56                 //readdata = data;
57                 if((command_reg & 0x20) != 0) { // NAND
58                         readdata = readdata & cmp_status_reg;
59                         data = data & ~cmp_status_reg;
60                         readdata = readdata | data;
61                 } else { // AND
62                         readdata = readdata & ~cmp_status_reg;
63                         data = data & cmp_status_reg;
64                         readdata = readdata | data;
65                 }
66         } else {
67                 readdata = data;
68         }
69         if(is_400line) {
70                 if((addr & 0xffff) < 0x8000) {
71                         //raddr = ((addr + (line_addr_offset.w.l << 1)) & 0x7fff) | (0x8000 * bank);
72                         raddr = (addr & 0x7fff) | (0x8000 * bank);
73                         target->write_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS, readdata);
74                 }
75         } else {
76                 //raddr = ((addr + (line_addr_offset.w.l << 1)) & 0x3fff) | (0x4000 * bank);
77                 raddr = (addr & 0x3fff) | (0x4000 * bank);
78                 target->write_data8(raddr + DISPLAY_VRAM_DIRECT_ACCESS, readdata);
79         }
80         return readdata;
81 }
82
83
84 uint8 MB61VH010::do_pset(uint32 addr)
85 {
86         uint32 i;
87         uint32 raddr = addr;  // Use banked ram.
88         uint8 bitmask;
89         uint8 srcdata;
90         int planes_b = planes;
91
92         if(planes_b >= 4) planes_b = 4;
93         for(i = 0; i < planes_b; i++) {
94                 if((bank_disable_reg & (1 << i)) != 0) {
95                                 continue;
96                 }
97                 if((color_reg & (1 << i)) == 0) {
98                         bitmask = 0x00;
99                 } else {
100                         bitmask = 0xff;
101                 }
102                 
103                 srcdata = do_read(addr, i);
104                 bitmask = bitmask & ~mask_reg;
105                 srcdata = srcdata & mask_reg;
106                 srcdata = srcdata | bitmask;
107                 do_write(addr, i, srcdata);
108         }
109         return 0xff;
110 }
111
112 uint8 MB61VH010::do_blank(uint32 addr)
113 {
114         uint32 i;
115         uint8 srcdata;
116
117         if(planes >= 4) planes = 4;
118         for(i = 0; i < planes; i++) {
119                 if((bank_disable_reg & (1 << i)) != 0) {
120                         continue;
121                 }
122                 srcdata = do_read(addr, i);
123                 srcdata = srcdata & mask_reg;
124                 do_write(addr, i, srcdata);
125         }
126         return 0xff;
127 }
128
129 uint8 MB61VH010::do_or(uint32 addr)
130 {
131         uint32 i;
132         uint8 bitmask;
133         uint8 srcdata;
134         
135         if(planes >= 4) planes = 4;
136         for(i = 0; i < planes; i++) {
137                 if((bank_disable_reg & (1 << i)) != 0) {
138                         continue;
139                 }
140                 srcdata = do_read(addr, i);
141                 if((color_reg & (1 << i)) == 0) {
142                         bitmask = srcdata; // srcdata | 0x00
143                 } else {
144                         bitmask = 0xff; // srcdata | 0xff
145                 }
146                 bitmask = bitmask & ~mask_reg;
147                 srcdata = (srcdata & mask_reg) | bitmask;
148                 do_write(addr, i, srcdata);
149         }
150         return 0xff;
151 }
152
153 uint8 MB61VH010::do_and(uint32 addr)
154 {
155         uint32 i;
156         uint8 bitmask;
157         uint8 srcdata;
158
159         if(planes >= 4) planes = 4;
160         for(i = 0; i < planes; i++) {
161                 if((bank_disable_reg & (1 << i)) != 0) {
162                         continue;
163                 }
164                 srcdata = do_read(addr, i);
165                 if((color_reg & (1 << i)) == 0) {
166                         bitmask = 0x00; // srcdata & 0x00
167                 } else {
168                         bitmask = srcdata; // srcdata & 0xff;
169                 }
170                 bitmask = bitmask & ~mask_reg;
171                 srcdata = (srcdata & mask_reg) | bitmask;
172                 do_write(addr, i, srcdata);
173         }
174         return 0xff;
175 }
176
177 uint8 MB61VH010::do_xor(uint32 addr)
178 {
179         uint32 i;
180         uint8 bitmask;
181         uint8 srcdata;
182
183         if(planes >= 4) planes = 4;
184         for(i = 0; i < planes; i++) {
185                 if((bank_disable_reg & (1 << i)) != 0) {
186                         continue;
187                 }
188                 srcdata = do_read(addr, i);
189                 if((color_reg & (1 << i)) == 0) {
190                         bitmask = srcdata ^ 0x00;
191                 } else {
192                         bitmask = srcdata ^ 0xff;
193                 }
194                 bitmask = bitmask & ~mask_reg;
195                 srcdata = (srcdata & mask_reg) | bitmask;
196                 do_write(addr, i, srcdata);
197         }
198         return 0xff;
199 }
200
201 uint8 MB61VH010::do_not(uint32 addr)
202 {
203         uint32 i;
204         uint8 bitmask;
205         uint8 srcdata;
206
207         if(planes >= 4) planes = 4;
208         for(i = 0; i < planes; i++) {
209                 if((bank_disable_reg & (1 << i)) != 0) {
210                         continue;
211                 }
212                 srcdata = do_read(addr, i);
213                 bitmask = ~srcdata;
214                 
215                 bitmask = bitmask & ~mask_reg;
216                 srcdata = (srcdata & mask_reg) | bitmask;
217                 do_write(addr, i, srcdata);
218         }
219         return 0xff;
220 }
221
222
223 uint8 MB61VH010::do_tilepaint(uint32 addr)
224 {
225         uint32 i;
226         uint8 bitmask;
227         uint8 srcdata;
228         //printf("Tilepaint CMD=%02x, ADDR=%04x Planes=%d, tile_reg=(%02x %02x %02x %02x)\n",
229         //       command_reg, addr, planes, tile_reg[0], tile_reg[1], tile_reg[2], tile_reg[3]);
230         if(planes >= 4) planes = 4;
231         for(i = 0; i < planes; i++) {
232                 if((bank_disable_reg & (1 << i)) != 0) {
233                         continue;
234                 }
235                 srcdata = do_read(addr, i);
236                 bitmask = tile_reg[i] & ~mask_reg;
237                 srcdata = (srcdata & mask_reg) | bitmask;
238                 do_write(addr, i, srcdata);
239         }
240         return 0xff;
241 }
242
243 uint8 MB61VH010::do_compare(uint32 addr)
244 {
245         uint32 offset = 0x4000;
246         uint8 r, g, b, t;
247         uint8 disables = ~bank_disable_reg;
248         uint8 tmpcol;
249         uint8 tmp_stat = 0;
250         int i;
251         int j;
252         //printf("Compare CMD=%02x, ADDR=%04x\n", command_reg, addr);
253         b = do_read(addr, 0);
254         r = do_read(addr, 1);
255         g = do_read(addr, 2);
256         if(planes >= 4) {
257                 t = do_read(addr, 3);
258                 disables = disables & 0x0f;
259         } else {
260                 t = 0;
261                 disables = disables & 0x07;
262         }
263         for(i = 7; i >= 0; i--) {
264                 tmpcol  = ((b & 0x80) != 0) ? 1 : 0;
265                 tmpcol |= ((r & 0x80) != 0) ? 2 : 0;
266                 tmpcol |= ((g & 0x80) != 0) ? 4 : 0;
267                 tmpcol |= ((t & 0x80) != 0) ? 8 : 0;
268                 tmpcol = tmpcol & disables;
269                 for(j = 0; j < 8; j++) {
270                         if((cmp_color_data[j] & 0x80) == 0) {
271                                 if((cmp_color_data[j] & disables) == tmpcol) {
272                                         tmp_stat = tmp_stat | (1 << i);
273                                         break;
274                                 }
275                         }
276                 }
277                 b <<= 1;
278                 r <<= 1;
279                 g <<= 1;
280                 t <<= 1;
281         }
282         cmp_status_reg = tmp_stat;
283         return 0xff;
284 }
285
286 void MB61VH010::do_alucmds_dmyread(uint32 addr)
287 {
288         int i;
289         if(!is_400line) {
290                 addr = addr & 0x3fff;
291         } else {
292                 if(addr >= 0x8000) {
293                         mask_reg = 0xff;
294                         return;
295                 }
296                 addr = addr & 0x7fff;
297         }
298         //printf("ALU DMYREAD: CMD %02x ADDR=%04x CMP[]=", command_reg, addr);
299         //for(i = 0; i < 8; i++) printf("[%02x]", cmp_color_data[i]);
300         if((command_reg & 0x80) == 0) {
301           //printf("\n");
302                 return;
303         }
304         if(((command_reg & 0x40) != 0) && ((command_reg & 0x07) != 7)) do_compare(addr);
305         switch(command_reg & 0x07) {
306                 case 0:
307                         do_pset(addr);
308                         break;
309                 case 1:
310                         do_blank(addr);
311                         break;
312                 case 2:
313                         do_or(addr);
314                         break;
315                 case 3:
316                         do_and(addr);
317                         break;
318                 case 4:
319                         do_xor(addr);
320                         break;
321                 case 5:
322                         do_not(addr);
323                         break;
324                 case 6:
325                         do_tilepaint(addr);
326                         break;
327                 case 7:
328                         do_compare(addr);
329                         break;
330         }
331         //printf(" CMP STATUS=%02x\n", cmp_status_reg);
332 }  
333
334 uint8 MB61VH010::do_alucmds(uint32 addr)
335 {
336         if(!is_400line) {
337                 addr = addr & 0x3fff;
338         } else {
339                 if(addr >= 0x8000) {
340                         mask_reg = 0xff;
341                         return 0xff;
342                 }
343                 addr = addr & 0x7fff;
344         }
345         //if((command_reg & 0x07) != 0x00) printf("ALU: CMD %02x ADDR=%08x\n", command_reg, addr);
346         if(((command_reg & 0x40) != 0) && ((command_reg & 0x07) != 7)) do_compare(addr);
347         switch(command_reg & 0x07) {
348                 case 0:
349                         return do_pset(addr);
350                         break;
351                 case 1:
352                         return do_blank(addr);
353                         break;
354                 case 2:
355                         return do_or(addr);
356                         break;
357                 case 3:
358                         return do_and(addr);
359                         break;
360                 case 4:
361                         return do_xor(addr);
362                         break;
363                 case 5:
364                         return do_not(addr);
365                         break;
366                 case 6:
367                         return do_tilepaint(addr);
368                         break;
369                 case 7:
370                         return do_compare(addr);
371                         break;
372         }
373         return 0xff;
374 }
375
376 void MB61VH010::do_line(void)
377 {
378         int x_begin = line_xbegin.w.l;
379         int x_end = line_xend.w.l;
380         int y_begin = line_ybegin.w.l;
381         int y_end = line_yend.w.l;
382         int cpx_t = x_begin;
383         int cpy_t = y_begin;
384         int ax = x_end - x_begin;
385         int ay = y_end - y_begin;
386         int diff = 0;
387         int count = 0;
388         int xcount;
389         int ycount;
390         uint8 mask_bak = mask_reg;
391         uint8 vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
392         //printf("Line: (%d,%d) - (%d,%d) CMD=%02x\n", x_begin, y_begin, x_end, y_end, command_reg);  
393         double usec;
394         bool lastflag = false;
395         
396         is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
397         planes = target->read_signal(SIG_DISPLAY_PLANES) & 0x07;
398         screen_width = target->read_signal(SIG_DISPLAY_X_WIDTH) * 8;
399         screen_height = target->read_signal(SIG_DISPLAY_Y_HEIGHT);
400
401         //if((command_reg & 0x80) == 0) return;
402         oldaddr = 0xffffffff;
403         alu_addr = 0xffffffff;
404
405         
406         line_style = line_pattern;
407         oldaddr = 0xffff;
408         busy_flag = true;
409         total_bytes = 1;
410         
411         //mask_reg = 0xff & ~vmask[x_begin & 7];
412         mask_reg = 0xff;
413         // Got from HD63484.cpp.
414         xcount = abs(ax);
415         ycount = abs(ay);
416         if(xcount >= ycount) {
417                 if(xcount != 0) {
418                         if(ycount != 0) {
419                                 diff = ((abs(ay)  + 1) * 1024) / abs(ax);
420                         }
421                         for(; cpx_t != x_end; ) {
422                                 lastflag = put_dot(cpx_t, cpy_t);
423                                 count += diff;
424                                 if(count >= 1024) {
425                                         if(ax > 0) {
426                                                 lastflag = put_dot(cpx_t + 1, cpy_t);
427                                         } else if(ax < 0) {
428                                                 lastflag = put_dot(cpx_t - 1, cpy_t);
429                                         }
430                                         if(ay < 0) {
431                                                 cpy_t--;
432                                         } else {
433                                                 cpy_t++;
434                                         }
435                                         count -= 1024;
436                                 }
437                                 if(ax > 0) {
438                                         cpx_t++;
439                                 } else if(ax < 0) {
440                                         cpx_t--;
441                                 }
442                         }
443                 } else { // ax = ay = 0
444                         lastflag = put_dot(cpx_t, cpy_t);
445                         total_bytes++;
446                 }
447         } else { // (abs(ax) < abs(ay)
448                 if(xcount != 0) {
449                         diff = ((xcount + 1) * 1024) / abs(ay);
450                 }
451                 for(; cpy_t != y_end; ) {
452                         lastflag = put_dot(cpx_t, cpy_t);
453                         count += diff;
454                         if(count >= 1024) {
455                                 if(ay > 0) {
456                                         lastflag = put_dot(cpx_t, cpy_t + 1);
457                                 } else if(ay < 0) {
458                                         lastflag = put_dot(cpx_t, cpy_t - 1);
459                                 }                                 
460                                 if(ax < 0) {
461                                         cpx_t--;
462                                 } else if(ax > 0) {
463                                         cpx_t++;
464                                 }
465                                 count -= 1024;
466                                 total_bytes++;
467                         }
468                         if(ay > 0) {
469                                 cpy_t++;
470                         } else {
471                                 cpy_t--;
472                         }
473                         total_bytes++;
474                 }
475         }
476
477         if(!lastflag) total_bytes++;
478         do_alucmds(alu_addr);
479
480         if(total_bytes > 8) { // Over 0.5us
481                 usec = (double)total_bytes / 16.0;
482                 register_event(this, EVENT_MB61VH010_BUSY_OFF, usec, false, &eventid_busy) ;
483         } else {
484                 busy_flag = false;
485         }
486         //mask_reg = mask_bak;
487         line_pattern = line_style;
488 }
489
490 bool MB61VH010::put_dot(int x, int y)
491 {
492         uint8 vmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
493         uint16 tmp8a;
494         uint8 mask;
495         bool flag = false;
496         
497         if((x < 0) || (y < 0)) return flag;
498         if((x >= screen_width) || (y >= screen_height)) return flag;
499         if((command_reg & 0x80) == 0) return flag;
500         
501         alu_addr = ((y * screen_width) >> 3) + (x >> 3);
502         alu_addr = alu_addr + (line_addr_offset.w.l << 1);
503         alu_addr = alu_addr & 0x7fff;
504         if(!is_400line) alu_addr = alu_addr & 0x3fff;
505         if(oldaddr == 0xffffffff) oldaddr = alu_addr;
506         
507         if(oldaddr != alu_addr) {
508                 do_alucmds(oldaddr);
509                 mask_reg = 0xff;
510                 oldaddr = alu_addr;
511                 flag = true;
512                 total_bytes++;
513         }
514         
515         if((line_style.b.h & 0x80) != 0) {
516                 mask_reg &= ~vmask[x & 7];
517         }
518         tmp8a = (line_style.w.l & 0x8000) >> 15;
519         line_style.w.l = (line_style.w.l << 1) | tmp8a;
520         return flag;
521 }
522
523 void MB61VH010::write_data8(uint32 id, uint32 data)
524 {
525         //printf("ALU: ADDR=%02x DATA=%02x\n", id, data);
526         if(id == ALU_CMDREG) {
527                 command_reg = data;
528                 return;
529         }
530         //if((command_reg & 0x80) == 0) return;
531         switch(id) {
532                 case ALU_LOGICAL_COLOR:
533                         color_reg = data;
534                         break;
535                 case ALU_WRITE_MASKREG:
536                         mask_reg = data;
537                         break;
538                 case ALU_BANK_DISABLE:
539                         bank_disable_reg = data;
540                         break;
541                 case ALU_TILEPAINT_B:
542                         tile_reg[0] = data;
543                         break;
544                 case ALU_TILEPAINT_R:
545                         tile_reg[1] = data;
546                         break;
547                 case ALU_TILEPAINT_G:
548                         tile_reg[2] = data;
549                         break;
550                 case ALU_TILEPAINT_L:
551                         tile_reg[3] = data;
552                         break;
553                 case ALU_OFFSET_REG_HIGH:
554                         line_addr_offset.b.h = data;
555                         break;
556                 case ALU_OFFSET_REG_LO:
557                         line_addr_offset.b.l = data;
558                         break;
559                 case ALU_LINEPATTERN_REG_HIGH:
560                         line_pattern.b.h = data;
561                         break;
562                 case ALU_LINEPATTERN_REG_LO:
563                         line_pattern.b.l = data;
564                         break;
565                 case ALU_LINEPOS_START_X_HIGH:
566                         line_xbegin.b.h = data;
567                         break;
568                 case ALU_LINEPOS_START_X_LOW:  
569                         line_xbegin.b.l = data;
570                         break;
571                 case ALU_LINEPOS_START_Y_HIGH:
572                         line_ybegin.b.h = data;
573                         break;
574                 case ALU_LINEPOS_START_Y_LOW:  
575                         line_ybegin.b.l = data;
576                         break;
577                 case ALU_LINEPOS_END_X_HIGH:
578                         line_xend.b.h = data;
579                         break;
580                 case ALU_LINEPOS_END_X_LOW:  
581                         line_xend.b.l = data;
582                         break;
583                 case ALU_LINEPOS_END_Y_HIGH:
584                         line_yend.b.h = data;
585                         break;
586                 case ALU_LINEPOS_END_Y_LOW:
587                         line_yend.b.l = data;
588                         do_line();
589                         break;
590                 default:
591                         if((id >= (ALU_CMPDATA_REG + 0)) && (id < (ALU_CMPDATA_REG + 8))) {
592                                 cmp_color_data[id - ALU_CMPDATA_REG] = data;
593                         } else  if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0x18000))) {
594                                 is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
595                                 do_alucmds_dmyread(id - ALU_WRITE_PROXY);
596                         }
597                         break;
598         }
599 }
600
601 uint32 MB61VH010::read_data8(uint32 id)
602 {
603   
604         switch(id) {
605                 case ALU_CMDREG:
606                         return (uint32)command_reg;
607                         break;
608                 case ALU_LOGICAL_COLOR:
609                         return (uint32)color_reg;
610                         break;
611                 case ALU_WRITE_MASKREG:
612                         return (uint32)mask_reg;
613                         break;
614                 case ALU_CMP_STATUS_REG:
615                         return (uint32)cmp_status_reg;
616                         break;
617                 case ALU_BANK_DISABLE:
618                         return (uint32)bank_disable_reg;
619                         break;
620                 default:
621                         if((id >= ALU_WRITE_PROXY) && (id < (ALU_WRITE_PROXY + 0x18000))) {
622                                 is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
623                                 do_alucmds_dmyread(id - ALU_WRITE_PROXY);
624                         }
625                         return 0xffffffff;
626                         break;
627         }
628 }
629
630 uint32 MB61VH010::read_signal(int id)
631 {
632         uint32 val = 0x00000000;
633         switch(id) {
634                 case SIG_ALU_BUSYSTAT:
635                         if(busy_flag) val = 0xffffffff;
636                         break;
637         }
638         return val;
639 }
640
641 void MB61VH010::event_callback(int event_id, int err)
642 {
643         switch(event_id) {
644                 case EVENT_MB61VH010_BUSY_ON:
645                         busy_flag = true;
646                         if(eventid_busy >= 0) cancel_event(this, eventid_busy);
647                         eventid_busy = -1;
648                         break;
649                 case EVENT_MB61VH010_BUSY_OFF:
650                         busy_flag = false;
651                         eventid_busy = -1;
652                         break;
653         }
654 }
655
656 void MB61VH010::initialize(void)
657 {
658         busy_flag = false;
659         eventid_busy = -1;
660 }
661
662 void MB61VH010::reset(void)
663 {
664         int i;
665         busy_flag = false;
666         if(eventid_busy >= 0) cancel_event(this, eventid_busy);
667         eventid_busy = -1;
668         
669         command_reg = 0;        // D410 (RW)
670         color_reg = 0;          // D411 (RW)
671         mask_reg = 0;           // D412 (RW)
672         cmp_status_reg = 0;     // D413 (RO)
673         for(i = 0; i < 8; i++) cmp_color_data[i] = 0x80; // D413-D41A (WO)
674         bank_disable_reg = 0;   // D41B (RW)
675         for(i = 0; i < 4; i++) tile_reg[i] = 0;        // D41C-D41F (WO)
676         
677         line_addr_offset.d = 0; // D420-D421 (WO)
678         line_pattern.d = 0;     // D422-D423 (WO)
679         line_xbegin.d = 0;      // D424-D425 (WO)
680         line_ybegin.d = 0;      // D426-D427 (WO)
681         line_xend.d = 0;        // D428-D429 (WO)
682         line_yend.d = 0;        // D42A-D42B (WO)
683
684         oldaddr = 0xffffffff;
685         
686         planes = target->read_signal(SIG_DISPLAY_PLANES) & 0x07;
687         is_400line = (target->read_signal(SIG_DISPLAY_MODE_IS_400LINE) != 0) ? true : false;
688         
689         screen_width = target->read_signal(SIG_DISPLAY_X_WIDTH) * 8;
690         screen_height = target->read_signal(SIG_DISPLAY_Y_HEIGHT);
691 }