1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     Seiko-Epson SED1330 LCD Controller emulation
6 
7 **********************************************************************/
8 
9 #include "emu.h"
10 #include "sed1330.h"
11 #include "screen.h"
12 
13 //#define VERBOSE 1
14 #include "logmacro.h"
15 
16 
17 
18 //**************************************************************************
19 //  MACROS / CONSTANTS
20 //**************************************************************************
21 
22 
23 #define INSTRUCTION_SYSTEM_SET      0x40
24 #define INSTRUCTION_SLEEP_IN        0x53    // unimplemented
25 #define INSTRUCTION_DISP_ON         0x59
26 #define INSTRUCTION_DISP_OFF        0x58
27 #define INSTRUCTION_SCROLL          0x44
28 #define INSTRUCTION_CSRFORM         0x5d
29 #define INSTRUCTION_CGRAM_ADR       0x5c
30 #define INSTRUCTION_CSRDIR_RIGHT    0x4c
31 #define INSTRUCTION_CSRDIR_LEFT     0x4d
32 #define INSTRUCTION_CSRDIR_UP       0x4e
33 #define INSTRUCTION_CSRDIR_DOWN     0x4f
34 #define INSTRUCTION_HDOT_SCR        0x5a
35 #define INSTRUCTION_OVLAY           0x5b
36 #define INSTRUCTION_CSRW            0x46
37 #define INSTRUCTION_CSRR            0x47
38 #define INSTRUCTION_MWRITE          0x42
39 #define INSTRUCTION_MREAD           0x43
40 
41 
42 #define CSRDIR_RIGHT                0x00
43 #define CSRDIR_LEFT                 0x01
44 #define CSRDIR_UP                   0x02
45 #define CSRDIR_DOWN                 0x03
46 
47 
48 #define MX_OR                       0x00
49 #define MX_XOR                      0x01    // unimplemented
50 #define MX_AND                      0x02    // unimplemented
51 #define MX_PRIORITY_OR              0x03    // unimplemented
52 
53 
54 #define FC_OFF                      0x00
55 #define FC_SOLID                    0x01
56 #define FC_FLASH_32                 0x02    // unimplemented
57 #define FC_FLASH_64                 0x03    // unimplemented
58 
59 
60 #define FP_OFF                      0x00
61 #define FP_SOLID                    0x01
62 #define FP_FLASH_32                 0x02    // unimplemented
63 #define FP_FLASH_4                  0x03    // unimplemented
64 
65 
66 
67 //**************************************************************************
68 //  GLOBAL VARIABLES
69 //**************************************************************************
70 
71 // device type definition
72 DEFINE_DEVICE_TYPE(SED1330, sed1330_device, "sed1330", "Epson SED1330")
73 
74 
75 // default address map
sed1330(address_map & map)76 void sed1330_device::sed1330(address_map &map)
77 {
78 	if (!has_configured_map(0))
79 		map(0x0000, 0xffff).ram();
80 }
81 
82 
83 // internal character generator ROM
84 ROM_START( sed1330 )
85 	ROM_REGION( 0x5c0, "gfx1", 0 ) // internal chargen ROM
86 	ROM_LOAD( "sed1330.bin", 0x000, 0x5c0, NO_DUMP )
87 ROM_END
88 
89 
90 
91 //**************************************************************************
92 //  INLINE HELPERS
93 //**************************************************************************
94 
95 //-------------------------------------------------
96 //  readbyte - read a byte at the given address
97 //-------------------------------------------------
98 
readbyte(offs_t address)99 inline uint8_t sed1330_device::readbyte(offs_t address)
100 {
101 	return space().read_byte(address);
102 }
103 
104 
105 //-------------------------------------------------
106 //  writebyte - write a byte at the given address
107 //-------------------------------------------------
108 
writebyte(offs_t address,uint8_t data)109 inline void sed1330_device::writebyte(offs_t address, uint8_t data)
110 {
111 	space().write_byte(address, data);
112 }
113 
114 
115 //-------------------------------------------------
116 //  increment_csr - increment cursor address
117 //-------------------------------------------------
118 
increment_csr()119 inline void sed1330_device::increment_csr()
120 {
121 	switch (m_cd)
122 	{
123 	case CSRDIR_RIGHT:
124 		m_csr++;
125 		break;
126 
127 	case CSRDIR_LEFT:
128 		m_csr--;
129 		break;
130 
131 	case CSRDIR_UP:
132 		m_csr -= m_ap;
133 		break;
134 
135 	case CSRDIR_DOWN:
136 		m_csr += m_ap;
137 		break;
138 	}
139 }
140 
141 
142 
143 //**************************************************************************
144 //  LIVE DEVICE
145 //**************************************************************************
146 
147 //-------------------------------------------------
148 //  sed1330_device - constructor
149 //-------------------------------------------------
150 
sed1330_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)151 sed1330_device::sed1330_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
152 	: device_t(mconfig, SED1330, tag, owner, clock),
153 		device_memory_interface(mconfig, *this),
154 		device_video_interface(mconfig, *this),
155 		m_bf(0),
156 		m_space_config("videoram", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(sed1330_device::sed1330), this))
157 {
158 }
159 
160 
161 //-------------------------------------------------
162 //  rom_region - device-specific ROM region
163 //-------------------------------------------------
164 
device_rom_region() const165 const tiny_rom_entry *sed1330_device::device_rom_region() const
166 {
167 	return ROM_NAME( sed1330 );
168 }
169 
170 
171 //-------------------------------------------------
172 //  device_start - device-specific startup
173 //-------------------------------------------------
174 
device_start()175 void sed1330_device::device_start()
176 {
177 	space().cache(m_cache);
178 
179 	// register for state saving
180 	save_item(NAME(m_bf));
181 	save_item(NAME(m_ir));
182 	save_item(NAME(m_dor));
183 	save_item(NAME(m_pbc));
184 	save_item(NAME(m_d));
185 	save_item(NAME(m_sleep));
186 	save_item(NAME(m_sag));
187 	save_item(NAME(m_m0));
188 	save_item(NAME(m_m1));
189 	save_item(NAME(m_m2));
190 	save_item(NAME(m_ws));
191 	save_item(NAME(m_iv));
192 	save_item(NAME(m_wf));
193 	save_item(NAME(m_fx));
194 	save_item(NAME(m_fy));
195 	save_item(NAME(m_cr));
196 	save_item(NAME(m_tcr));
197 	save_item(NAME(m_lf));
198 	save_item(NAME(m_ap));
199 	save_item(NAME(m_sad1));
200 	save_item(NAME(m_sad2));
201 	save_item(NAME(m_sad3));
202 	save_item(NAME(m_sad4));
203 	save_item(NAME(m_sl1));
204 	save_item(NAME(m_sl2));
205 	save_item(NAME(m_hdotscr));
206 	save_item(NAME(m_csr));
207 	save_item(NAME(m_cd));
208 	save_item(NAME(m_crx));
209 	save_item(NAME(m_cry));
210 	save_item(NAME(m_cm));
211 	save_item(NAME(m_fc));
212 	save_item(NAME(m_fp));
213 	save_item(NAME(m_mx));
214 	save_item(NAME(m_dm));
215 	save_item(NAME(m_ov));
216 }
217 
218 
219 //-------------------------------------------------
220 //  device_reset - device-specific reset
221 //-------------------------------------------------
222 
device_reset()223 void sed1330_device::device_reset()
224 {
225 }
226 
227 
228 //-------------------------------------------------
229 //  memory_space_config - return a description of
230 //  any address spaces owned by this device
231 //-------------------------------------------------
232 
memory_space_config() const233 device_memory_interface::space_config_vector sed1330_device::memory_space_config() const
234 {
235 	return space_config_vector {
236 		std::make_pair(0, &m_space_config)
237 	};
238 }
239 
240 
241 //-------------------------------------------------
242 //  status_r -
243 //-------------------------------------------------
244 
status_r()245 uint8_t sed1330_device::status_r()
246 {
247 	if (!machine().side_effects_disabled())
248 		LOG("SED1330 Status Read: %s\n", m_bf ? "busy" : "ready");
249 
250 	return m_bf << 6;
251 }
252 
253 
254 //-------------------------------------------------
255 //  command_w -
256 //-------------------------------------------------
257 
command_w(uint8_t data)258 void sed1330_device::command_w(uint8_t data)
259 {
260 	m_ir = data;
261 	m_pbc = 0;
262 
263 	switch (m_ir)
264 	{
265 #if 0
266 	case INSTRUCTION_SLEEP_IN:
267 		break;
268 #endif
269 	case INSTRUCTION_CSRDIR_RIGHT:
270 	case INSTRUCTION_CSRDIR_LEFT:
271 	case INSTRUCTION_CSRDIR_UP:
272 	case INSTRUCTION_CSRDIR_DOWN:
273 		m_cd = data & 0x03;
274 
275 		switch (m_cd)
276 		{
277 		case CSRDIR_RIGHT:  LOG("SED1330 Cursor Direction: Right\n");  break;
278 		case CSRDIR_LEFT:   LOG("SED1330 Cursor Direction: Left\n");   break;
279 		case CSRDIR_UP:     LOG("SED1330 Cursor Direction: Up\n");     break;
280 		case CSRDIR_DOWN:   LOG("SED1330 Cursor Direction: Down\n");   break;
281 		}
282 		break;
283 	}
284 }
285 
286 
287 //-------------------------------------------------
288 //  data_r -
289 //-------------------------------------------------
290 
data_r()291 uint8_t sed1330_device::data_r()
292 {
293 	uint8_t data = 0;
294 
295 	switch (m_ir)
296 	{
297 	case INSTRUCTION_MREAD:
298 		data = readbyte(m_csr);
299 		if (!machine().side_effects_disabled())
300 		{
301 			LOG("SED1330 Memory Read %02x from %04x\n", data, m_csr);
302 			increment_csr();
303 		}
304 		break;
305 
306 	case INSTRUCTION_CSRR:
307 		switch (m_pbc)
308 		{
309 		case 0:
310 			data = m_csr & 0xff;
311 			break;
312 
313 		case 1:
314 			data = (m_csr & 0xff00) >> 8;
315 			break;
316 
317 		default:
318 			logerror("SED1330 Invalid parameter byte %02x\n", data);
319 		}
320 		if (!machine().side_effects_disabled())
321 		{
322 			LOG("SED1330 Cursor Byte %d Read %02x\n", m_pbc, data);
323 			m_pbc++;
324 		}
325 		break;
326 
327 	default:
328 		logerror("SED1330 Unsupported instruction %02x\n", m_ir);
329 		break;
330 	}
331 
332 	return data;
333 }
334 
335 
336 //-------------------------------------------------
337 //  data_w -
338 //-------------------------------------------------
339 
data_w(uint8_t data)340 void sed1330_device::data_w(uint8_t data)
341 {
342 	switch (m_ir)
343 	{
344 	case INSTRUCTION_SYSTEM_SET:
345 		switch (m_pbc)
346 		{
347 		case 0:
348 			m_m0 = BIT(data, 0);
349 			m_m1 = BIT(data, 1);
350 			m_m2 = BIT(data, 2);
351 			m_ws = BIT(data, 3);
352 			m_iv = BIT(data, 5);
353 
354 			LOG("SED1330 %s CG ROM\n", BIT(data, 0) ? "External" : "Internal");
355 			LOG("SED1330 D6 Correction: %s\n", BIT(data, 1) ? "enabled" : "disabled");
356 			LOG("SED1330 Character Height: %u\n", BIT(data, 2) ? 16 : 8);
357 			LOG("SED1330 %s Panel Drive\n", BIT(data, 3) ? "Dual" : "Single");
358 			LOG("SED1330 Screen Top-Line Correction: %s\n", BIT(data, 5) ? "disabled" : "enabled");
359 			break;
360 
361 		case 1:
362 			m_fx = (data & 0x07) + 1;
363 			m_wf = BIT(data, 7);
364 
365 			LOG("SED1330 Horizontal Character Size: %u\n", m_fx);
366 			LOG("SED1330 %s AC Drive\n", BIT(data, 7) ? "2-frame" : "16-line");
367 			break;
368 
369 		case 2:
370 			m_fy = (data & 0x0f) + 1;
371 			LOG("SED1330 Vertical Character Size: %u\n", m_fy);
372 			break;
373 
374 		case 3:
375 			m_cr = data + 1;
376 			LOG("SED1330 Visible Characters Per Line: %u\n", m_cr);
377 			break;
378 
379 		case 4:
380 			m_tcr = data + 1;
381 			LOG("SED1330 Total Characters Per Line: %u\n", m_tcr);
382 			break;
383 
384 		case 5:
385 			m_lf = data + 1;
386 			LOG("SED1330 Frame Height: %u\n", m_lf);
387 			if (clock() != 0)
388 			{
389 				attotime fr = clocks_to_attotime(m_tcr * m_lf * 9);
390 				screen().configure(m_tcr * m_fx, m_lf, screen().visible_area(), fr.as_attoseconds());
391 				LOG("SED1330 Frame Rate: %.1f Hz\n", fr.as_hz());
392 			}
393 			break;
394 
395 		case 6:
396 			m_ap = (m_ap & 0xff00) | data;
397 			break;
398 
399 		case 7:
400 			m_ap = (data << 8) | (m_ap & 0xff);
401 			LOG("SED1330 Virtual Screen Width: %u\n", m_ap);
402 			break;
403 
404 		default:
405 			logerror("SED1330 Invalid parameter byte %02x\n", data);
406 		}
407 		break;
408 
409 	case INSTRUCTION_DISP_ON:
410 	case INSTRUCTION_DISP_OFF:
411 		m_d = BIT(m_ir, 0);
412 		m_fc = data & 0x03;
413 		m_fp = data >> 2;
414 		LOG("SED1330 Display: %s\n", BIT(m_ir, 0) ? "enabled" : "disabled");
415 
416 		switch (m_fc)
417 		{
418 		case FC_OFF:        LOG("SED1330 Cursor: disabled\n"); break;
419 		case FC_SOLID:      LOG("SED1330 Cursor: solid\n");    break;
420 		case FC_FLASH_32:   LOG("SED1330 Cursor: fFR/32\n");   break;
421 		case FC_FLASH_64:   LOG("SED1330 Cursor: fFR/64\n");   break;
422 		}
423 
424 		switch (m_fp & 0x03)
425 		{
426 		case FP_OFF:        LOG("SED1330 Display Page 1: disabled\n");     break;
427 		case FP_SOLID:      LOG("SED1330 Display Page 1: enabled\n");      break;
428 		case FP_FLASH_32:   LOG("SED1330 Display Page 1: flash fFR/32\n"); break;
429 		case FP_FLASH_4:    LOG("SED1330 Display Page 1: flash fFR/4\n");  break;
430 		}
431 
432 		switch ((m_fp >> 2) & 0x03)
433 		{
434 		case FP_OFF:        LOG("SED1330 Display Page 2/4: disabled\n");       break;
435 		case FP_SOLID:      LOG("SED1330 Display Page 2/4: enabled\n");        break;
436 		case FP_FLASH_32:   LOG("SED1330 Display Page 2/4: flash fFR/32\n");   break;
437 		case FP_FLASH_4:    LOG("SED1330 Display Page 2/4: flash fFR/4\n");    break;
438 		}
439 
440 		switch ((m_fp >> 4) & 0x03)
441 		{
442 		case FP_OFF:        LOG("SED1330 Display Page 3: disabled\n");     break;
443 		case FP_SOLID:      LOG("SED1330 Display Page 3: enabled\n");      break;
444 		case FP_FLASH_32:   LOG("SED1330 Display Page 3: flash fFR/32\n"); break;
445 		case FP_FLASH_4:    LOG("SED1330 Display Page 3: flash fFR/4\n");  break;
446 		}
447 		break;
448 
449 	case INSTRUCTION_SCROLL:
450 		switch (m_pbc)
451 		{
452 		case 0:
453 			m_sad1 = (m_sad1 & 0xff00) | data;
454 			break;
455 
456 		case 1:
457 			m_sad1 = (data << 8) | (m_sad1 & 0xff);
458 			LOG("SED1330 Display Page 1 Start Address: %04x\n", m_sad1);
459 			break;
460 
461 		case 2:
462 			m_sl1 = data + 1;
463 			LOG("SED1330 Display Block 1 Screen Lines: %u\n", m_sl1);
464 			break;
465 
466 		case 3:
467 			m_sad2 = (m_sad2 & 0xff00) | data;
468 			break;
469 
470 		case 4:
471 			m_sad2 = (data << 8) | (m_sad2 & 0xff);
472 			LOG("SED1330 Display Page 2 Start Address: %04x\n", m_sad2);
473 			break;
474 
475 		case 5:
476 			m_sl2 = data + 1;
477 			LOG("SED1330 Display Block 2 Screen Lines: %u\n", m_sl2);
478 			break;
479 
480 		case 6:
481 			m_sad3 = (m_sad3 & 0xff00) | data;
482 			break;
483 
484 		case 7:
485 			m_sad3 = (data << 8) | (m_sad3 & 0xff);
486 			LOG("SED1330 Display Page 3 Start Address: %04x\n", m_sad3);
487 			break;
488 
489 		case 8:
490 			m_sad4 = (m_sad4 & 0xff00) | data;
491 			break;
492 
493 		case 9:
494 			m_sad4 = (data << 8) | (m_sad4 & 0xff);
495 			LOG("SED1330 Display Page 4 Start Address: %04x\n", m_sad4);
496 			break;
497 
498 		default:
499 			logerror("SED1330 Invalid parameter byte %02x\n", data);
500 		}
501 		break;
502 
503 	case INSTRUCTION_CSRFORM:
504 		switch (m_pbc)
505 		{
506 		case 0:
507 			m_crx = (data & 0x0f) + 1;
508 			LOG("SED1330 Horizontal Cursor Size: %u\n", m_crx);
509 			break;
510 
511 		case 1:
512 			m_cry = (data & 0x0f) + 1;
513 			m_cm = BIT(data, 7);
514 			LOG("SED1330 Vertical Cursor Location: %u\n", m_cry);
515 			LOG("SED1330 Cursor Shape: %s\n", BIT(data, 7) ? "Block" : "Underscore");
516 			break;
517 
518 		default:
519 			logerror("SED1330 Invalid parameter byte %02x\n", data);
520 		}
521 		break;
522 
523 	case INSTRUCTION_CGRAM_ADR:
524 		switch (m_pbc)
525 		{
526 		case 0:
527 			m_sag = (m_sag & 0xff00) | data;
528 			break;
529 
530 		case 1:
531 			m_sag = (data << 8) | (m_sag & 0xff);
532 			LOG("SED1330 Character Generator RAM Start Address: %04x\n", m_sag);
533 			break;
534 
535 		default:
536 			logerror("SED1330 Invalid parameter byte %02x\n", data);
537 		}
538 		break;
539 
540 	case INSTRUCTION_HDOT_SCR:
541 		m_hdotscr = data & 0x07;
542 		LOG("SED1330 Horizontal Dot Scroll: %u\n", m_hdotscr);
543 		break;
544 
545 	case INSTRUCTION_OVLAY:
546 		m_mx = data & 0x03;
547 		m_dm = (data >> 2) & 0x03;
548 		m_ov = BIT(data, 4);
549 
550 		switch (m_mx)
551 		{
552 		case MX_OR:             LOG("SED1330 Display Composition Method: OR\n");           break;
553 		case MX_XOR:            LOG("SED1330 Display Composition Method: Exclusive-OR\n"); break;
554 		case MX_AND:            LOG("SED1330 Display Composition Method: AND\n");          break;
555 		case MX_PRIORITY_OR:    LOG("SED1330 Display Composition Method: Priority-OR\n");  break;
556 		}
557 
558 		LOG("SED1330 Display Page 1 Mode: %s\n", BIT(data, 2) ? "Graphics" : "Text");
559 		LOG("SED1330 Display Page 3 Mode: %s\n", BIT(data, 3) ? "Graphics" : "Text");
560 		LOG("SED1330 Display Composition Layers: %u\n", BIT(data, 4) ? 3 : 2);
561 		break;
562 
563 	case INSTRUCTION_CSRW:
564 		switch (m_pbc)
565 		{
566 		case 0:
567 			m_csr = (m_csr & 0xff00) | data;
568 			break;
569 
570 		case 1:
571 			m_csr = (data << 8) | (m_csr & 0xff);
572 			LOG("SED1330 Cursor Address %04x\n", m_csr);
573 			break;
574 
575 		default:
576 			logerror("SED1330 Invalid parameter byte %02x\n", data);
577 		}
578 		break;
579 #if 0
580 	case INSTRUCTION_CSRR:
581 		break;
582 #endif
583 	case INSTRUCTION_MWRITE:
584 		LOG("SED1330 Memory Write %02x to %04x (row %u col %u line %u)\n", data, m_csr, m_csr/80/8, m_csr%80, m_csr/80);
585 
586 		writebyte(m_csr, data);
587 
588 		increment_csr();
589 		break;
590 #if 0
591 	case INSTRUCTION_MREAD:
592 		break;
593 #endif
594 	default:
595 		logerror("SED1330 Unsupported instruction %02x\n", m_ir);
596 	}
597 
598 	m_pbc++;
599 }
600 
601 
602 //-------------------------------------------------
603 //  draw_text_scanline -
604 //-------------------------------------------------
605 
draw_text_scanline(bitmap_ind16 & bitmap,const rectangle & cliprect,int y,int r,uint16_t va,bool cursor)606 void sed1330_device::draw_text_scanline(bitmap_ind16 &bitmap, const rectangle &cliprect, int y, int r, uint16_t va, bool cursor)
607 {
608 	uint16_t *p = &bitmap.pix(y);
609 
610 	for (int sx = 0; sx < m_cr; sx++, p += m_fx)
611 	{
612 		if (m_m0 && !m_m1)
613 		{
614 			uint8_t c = m_cache.read_byte(va + sx);
615 			uint8_t data = m_cache.read_byte(0xf000 | (m_m2 ? u16(c) << 4 | r : u16(c) << 3 | (r & 7)));
616 			for (int x = 0; x < m_fx; x++, data <<= 1)
617 				if (BIT(data, 7))
618 					p[x] = 1;
619 		}
620 
621 		if (cursor && (va + sx) == m_csr)
622 		{
623 			if (m_cm)
624 			{
625 				// block cursor
626 				if (r < m_cry)
627 				{
628 					std::fill_n(p, m_crx, 1);
629 				}
630 			}
631 			else
632 			{
633 				// underscore cursor
634 				if (r == m_cry)
635 				{
636 					std::fill_n(p, m_crx, 1);
637 				}
638 			}
639 		}
640 	}
641 }
642 
643 
644 //-------------------------------------------------
645 //  draw_graphics_scanline -
646 //-------------------------------------------------
647 
draw_graphics_scanline(bitmap_ind16 & bitmap,const rectangle & cliprect,int y,uint16_t va)648 void sed1330_device::draw_graphics_scanline(bitmap_ind16 &bitmap, const rectangle &cliprect, int y, uint16_t va)
649 {
650 	for (int sx = 0; sx < m_cr; sx++)
651 	{
652 		uint8_t data = readbyte(va++);
653 
654 		for (int x = 0; x < m_fx; x++)
655 		{
656 			bitmap.pix(y, (sx * m_fx) + x) = BIT(data, 7);
657 			data <<= 1;
658 		}
659 	}
660 }
661 
662 
663 //-------------------------------------------------
664 //  update_graphics -
665 //-------------------------------------------------
666 
update_graphics(bitmap_ind16 & bitmap,const rectangle & cliprect)667 void sed1330_device::update_graphics(bitmap_ind16 &bitmap, const rectangle &cliprect)
668 {
669 }
670 
671 
672 //-------------------------------------------------
673 //  update_text -
674 //-------------------------------------------------
675 
update_text(bitmap_ind16 & bitmap,const rectangle & cliprect)676 void sed1330_device::update_text(bitmap_ind16 &bitmap, const rectangle &cliprect)
677 {
678 	uint8_t attr1 = m_fp & 0x03;
679 	uint8_t attr2 = (m_fp >> 2) & 0x03;
680 	uint8_t attr3 = (m_fp >> 4) & 0x03;
681 
682 	for (int y = 0; y < m_lf; y++)
683 	{
684 		if (y >= m_sl1)
685 		{
686 			if (attr3 != FP_OFF)
687 			{
688 				uint16_t sad3 = m_sad3 + (((y - m_sl1) / m_fy) * m_ap);
689 
690 				// draw text display page 3 scanline
691 				draw_text_scanline(bitmap, cliprect, y, (y - m_sl1) % m_fy, sad3, m_ov && m_fc != FC_OFF);
692 			}
693 		}
694 		else
695 		{
696 			if (attr1 != FP_OFF)
697 			{
698 				uint16_t sad1 = m_sad1 + ((y / m_fy) * m_ap);
699 
700 				// draw text display page 1 scanline
701 				draw_text_scanline(bitmap, cliprect, y, y % m_fy, sad1, !m_ov && m_fc != FC_OFF);
702 			}
703 		}
704 
705 		if (attr2 != FP_OFF)
706 		{
707 			if (m_ws && y >= m_sl2)
708 			{
709 				uint16_t sad4 = m_sad4 + ((y - m_sl2) * m_ap);
710 
711 				// draw graphics display page 4 scanline
712 				draw_graphics_scanline(bitmap, cliprect, y, sad4);
713 			}
714 			else
715 			{
716 				uint16_t sad2 = m_sad2 + (y * m_ap);
717 
718 				// draw graphics display page 2 scanline
719 				draw_graphics_scanline(bitmap, cliprect, y, sad2);
720 			}
721 		}
722 	}
723 }
724 
725 
726 //-------------------------------------------------
727 //  screen_update -
728 //-------------------------------------------------
729 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)730 uint32_t sed1330_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
731 {
732 	bitmap.fill(0, cliprect);
733 	if (m_d)
734 	{
735 		if (m_dm)
736 		{
737 			update_graphics(bitmap, cliprect);
738 		}
739 		else
740 		{
741 			update_text(bitmap, cliprect);
742 		}
743 	}
744 	return 0;
745 }
746