1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     Luxor ABC 1600 Mover emulation
6 
7 **********************************************************************/
8 
9 #include "emu.h"
10 #include "includes/abc1600.h"
11 #include "abc1600.lh"
12 #include "render.h"
13 
14 //#define VERBOSE 1
15 #include "logmacro.h"
16 
17 
18 //**************************************************************************
19 //  CONSTANTS / MACROS
20 //**************************************************************************
21 
22 // video RAM
23 #define VIDEORAM_SIZE       0x40000
24 #define VIDEORAM16_MASK     0x3ffff
25 #define VIDEORAM8_MASK      0x7fffe
26 
27 
28 // flag register
29 #define L_P         BIT(m_flag, 0)
30 #define BLANK       BIT(m_flag, 1)
31 #define PIX_POL     BIT(m_flag, 2)
32 #define FRAME_POL   BIT(m_flag, 3)
33 #define HOLD_FY     BIT(m_flag, 4)
34 #define HOLD_FX     BIT(m_flag, 5)
35 #define COMP_MOVE   BIT(m_flag, 6)
36 #define REPLACE     BIT(m_flag, 7)
37 
38 
39 
40 //**************************************************************************
41 //  DEVICE DEFINITIONS
42 //**************************************************************************
43 
44 DEFINE_DEVICE_TYPE(ABC1600_MOVER, abc1600_mover_device, "abc1600mover", "ABC 1600 Mover")
45 
46 
vram_map(address_map & map)47 void abc1600_mover_device::vram_map(address_map &map)
48 {
49 	map(0x00000, 0x7ffff).rw(FUNC(abc1600_mover_device::video_ram_r), FUNC(abc1600_mover_device::video_ram_w));
50 }
51 
crtc_map(address_map & map)52 void abc1600_mover_device::crtc_map(address_map &map)
53 {
54 	map(0x00, 0x00).mirror(0xfe).rw(m_crtc, FUNC(mc6845_device::status_r), FUNC(mc6845_device::address_w));
55 	map(0x01, 0x01).mirror(0xfe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
56 }
57 
iowr0_map(address_map & map)58 void abc1600_mover_device::iowr0_map(address_map &map)
59 {
60 	map(0x00, 0x00).mirror(0xff).r(FUNC(abc1600_mover_device::iord0_r));
61 	map(0x00, 0x00).mirror(0xf8).w(FUNC(abc1600_mover_device::ldsx_hb_w));
62 	map(0x01, 0x01).mirror(0xf8).w(FUNC(abc1600_mover_device::ldsx_lb_w));
63 	map(0x02, 0x02).mirror(0xf8).w(FUNC(abc1600_mover_device::ldsy_hb_w));
64 	map(0x03, 0x03).mirror(0xf8).w(FUNC(abc1600_mover_device::ldsy_lb_w));
65 	map(0x04, 0x04).mirror(0xf8).w(FUNC(abc1600_mover_device::ldtx_hb_w));
66 	map(0x05, 0x05).mirror(0xf8).w(FUNC(abc1600_mover_device::ldtx_lb_w));
67 	map(0x06, 0x06).mirror(0xf8).w(FUNC(abc1600_mover_device::ldty_hb_w));
68 	map(0x07, 0x07).mirror(0xf8).w(FUNC(abc1600_mover_device::ldty_lb_w));
69 }
70 
iowr1_map(address_map & map)71 void abc1600_mover_device::iowr1_map(address_map &map)
72 {
73 	map(0x00, 0x00).mirror(0xff).nopr();
74 	map(0x00, 0x00).mirror(0xf8).w(FUNC(abc1600_mover_device::ldfx_hb_w));
75 	map(0x01, 0x01).mirror(0xf8).w(FUNC(abc1600_mover_device::ldfx_lb_w));
76 	map(0x02, 0x02).mirror(0xf8).w(FUNC(abc1600_mover_device::ldfy_hb_w));
77 	map(0x03, 0x03).mirror(0xf8).w(FUNC(abc1600_mover_device::ldfy_lb_w));
78 	map(0x05, 0x05).mirror(0xf8).w(FUNC(abc1600_mover_device::wrml_w));
79 	map(0x07, 0x07).mirror(0xf8).w(FUNC(abc1600_mover_device::wrdl_w));
80 }
81 
iowr2_map(address_map & map)82 void abc1600_mover_device::iowr2_map(address_map &map)
83 {
84 	map(0x00, 0x00).mirror(0xff).nopr();
85 	map(0x00, 0x00).mirror(0xf8).w(FUNC(abc1600_mover_device::wrmask_strobe_hb_w));
86 	map(0x01, 0x01).mirror(0xf8).w(FUNC(abc1600_mover_device::wrmask_strobe_lb_w));
87 	map(0x02, 0x02).mirror(0xf8).w(FUNC(abc1600_mover_device::enable_clocks_w));
88 	map(0x03, 0x03).mirror(0xf8).w(FUNC(abc1600_mover_device::flag_strobe_w));
89 	map(0x04, 0x04).mirror(0xf8).w(FUNC(abc1600_mover_device::endisp_w));
90 }
91 
92 
mover_map(address_map & map)93 void abc1600_mover_device::mover_map(address_map &map)
94 {
95 	map(0x00000, 0x3ffff).ram();
96 }
97 
98 
99 //-------------------------------------------------
100 //  ROM( abc1600_mover )
101 //-------------------------------------------------
102 
103 ROM_START( abc1600_mover )
104 	ROM_REGION16_BE( 0x2000, "wrmsk", 0 )
CRC(bc737538)105 	ROM_LOAD16_BYTE( "wrmskl 6490362-01.1g", 0x0001, 0x1000, CRC(bc737538) SHA1(80e2c3757eb7f713018808d6e41ebef612425028) )
106 	ROM_LOAD16_BYTE( "wrmskh 6490363-01.1j", 0x0000, 0x1000, CRC(6b7c9f0b) SHA1(7155a993adcf08a5a8a2f22becf9fd66fda698be) )
107 
108 	ROM_REGION( 0x200, "shinf", 0 )
109 	ROM_LOAD( "shinf 6490361-01.1f", 0x000, 0x200, CRC(20260f8f) SHA1(29bf49c64e7cc7592e88cde2768ac57c7ce5e085) )
110 
111 	ROM_REGION16_BE( 0x40, "drmsk", 0 )
112 	ROM_LOAD16_BYTE( "drmskl 6490359-01.1k", 0x01, 0x20, CRC(6e71087c) SHA1(0acf67700d6227f4b315cf8fb0fb31c0e7fb9496) )
113 	ROM_LOAD16_BYTE( "drmskh 6490358-01.1l", 0x00, 0x20, CRC(a4a9a9dc) SHA1(d8575c0335d6021cbb5f7bcd298b41c35294a80a) )
114 
115 	ROM_REGION( 0x104, "plds", 0 )
116 	ROM_LOAD( "drmsk 6490360-01.1m", 0x000, 0x104, CRC(5f7143c1) SHA1(1129917845f8e505998b15288f02bf907487e4ac) ) // PAL16L8 mover word mixer @ 1m,1n,1t,2t
117 ROM_END
118 
119 
120 //-------------------------------------------------
121 //  rom_region - device-specific ROM region
122 //-------------------------------------------------
123 
124 const tiny_rom_entry *abc1600_mover_device::device_rom_region() const
125 {
126 	return ROM_NAME( abc1600_mover );
127 }
128 
129 
130 //-------------------------------------------------
131 //  mc6845
132 //-------------------------------------------------
133 
get_crtca(uint16_t ma,uint8_t ra,uint8_t column)134 inline uint16_t abc1600_mover_device::get_crtca(uint16_t ma, uint8_t ra, uint8_t column)
135 {
136 	/*
137 
138 	    bit         description
139 
140 	    CRTCA0      0
141 	    CRTCA1      0
142 	    CRTCA2      CC1/MA1
143 	    CRTCA3      CC2/MA2
144 	    CRTCA4      CC3/MA3
145 	    CRTCA5      CC4/MA4
146 	    CRTCA6      RA0
147 	    CRTCA7      RA1
148 	    CRTCA8      RA2
149 	    CRTCA9      RA3
150 	    CRTCA10     CR0/MA8
151 	    CRTCA11     CR1/MA9
152 	    CRTCA12     CR2/MA10
153 	    CRTCA13     CR3/MA11
154 	    CRTCA14     CR4/MA12
155 	    CRTCA15     CR5/MA13
156 
157 	*/
158 
159 	uint8_t cc = (ma & 0xff) + column;
160 	uint8_t cr = ma >> 8;
161 
162 	return (cr << 10) | ((ra & 0x0f) << 6) | ((cc << 1) & 0x3c);
163 }
164 
MC6845_UPDATE_ROW(abc1600_mover_device::crtc_update_row)165 MC6845_UPDATE_ROW(abc1600_mover_device::crtc_update_row)
166 {
167 	int x = 0;
168 	const pen_t *pen = m_palette->pens();
169 
170 	for (int column = 0; column < x_count; column += 2)
171 	{
172 		uint16_t dma = get_crtca(ma, ra, column);
173 
174 		// data is read out of video RAM in nibble mode by strobing CAS 4 times
175 		for (int cas = 0; cas < 4; cas++)
176 		{
177 			uint16_t data = read_videoram(dma + cas);
178 
179 			for (int bit = 0; bit < 16; bit++)
180 			{
181 				int color = ((BIT(data, 15) ^ PIX_POL) && !BLANK) && de;
182 
183 				bitmap.pix(vbp + y, hbp + x++) = pen[color];
184 
185 				data <<= 1;
186 			}
187 		}
188 	}
189 }
190 
MC6845_ON_UPDATE_ADDR_CHANGED(abc1600_mover_device::crtc_update)191 MC6845_ON_UPDATE_ADDR_CHANGED( abc1600_mover_device::crtc_update )
192 {
193 }
194 
195 //-------------------------------------------------
196 //  device_add_mconfig - add device configuration
197 //-------------------------------------------------
198 
device_add_mconfig(machine_config & config)199 void abc1600_mover_device::device_add_mconfig(machine_config &config)
200 {
201 	config.set_default_layout(layout_abc1600);
202 
203 	screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER, rgb_t::green()));
204 	screen.set_screen_update(FUNC(abc1600_mover_device::screen_update));
205 	screen.set_raw(XTAL(64'000'000), 0x3e0, 0, 0x300, 0x433, 0, 0x400);
206 
207 	PALETTE(config, m_palette, palette_device::MONOCHROME);
208 
209 	SY6845E(config, m_crtc, XTAL(64'000'000)/32);
210 	m_crtc->set_screen(SCREEN_TAG);
211 	m_crtc->set_show_border_area(true);
212 	m_crtc->set_char_width(32);
213 	m_crtc->set_update_row_callback(FUNC(abc1600_mover_device::crtc_update_row));
214 	m_crtc->set_on_update_addr_change_callback(FUNC(abc1600_mover_device::crtc_update));
215 }
216 
217 
218 //**************************************************************************
219 //  LIVE DEVICE
220 //**************************************************************************
221 
222 //-------------------------------------------------
223 //  abc1600_mover_device - constructor
224 //-------------------------------------------------
225 
abc1600_mover_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)226 abc1600_mover_device::abc1600_mover_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
227 	device_t(mconfig, ABC1600_MOVER, tag, owner, clock),
228 	device_memory_interface(mconfig, *this),
229 	m_space_config("vram", ENDIANNESS_BIG, 16, 18, -1, address_map_constructor(FUNC(abc1600_mover_device::mover_map), this)),
230 	m_crtc(*this, "sy6845e"),
231 	m_palette(*this, "palette"),
232 	m_wrmsk_rom(*this, "wrmsk"),
233 	m_shinf_rom(*this, "shinf"),
234 	m_drmsk_rom(*this, "drmsk")
235 {
236 }
237 
238 
239 //-------------------------------------------------
240 //  device_start - device-specific startup
241 //-------------------------------------------------
242 
device_start()243 void abc1600_mover_device::device_start()
244 {
245 	// state saving
246 	save_item(NAME(m_endisp));
247 	save_item(NAME(m_clocks_disabled));
248 	save_item(NAME(m_gmdi));
249 	save_item(NAME(m_wrm));
250 	save_item(NAME(m_ms));
251 	save_item(NAME(m_ds));
252 	save_item(NAME(m_flag));
253 	save_item(NAME(m_xsize));
254 	save_item(NAME(m_ysize));
255 	save_item(NAME(m_udx));
256 	save_item(NAME(m_udy));
257 	save_item(NAME(m_xfrom));
258 	save_item(NAME(m_xto));
259 	save_item(NAME(m_yto));
260 	save_item(NAME(m_ty));
261 	save_item(NAME(m_mfa));
262 	save_item(NAME(m_mta));
263 	save_item(NAME(m_sh));
264 	save_item(NAME(m_mdor));
265 	save_item(NAME(m_hold_1w_cyk));
266 	save_item(NAME(m_wrms0));
267 	save_item(NAME(m_wrms1));
268 	save_item(NAME(m_rmc));
269 	save_item(NAME(m_cmc));
270 }
271 
272 
273 //-------------------------------------------------
274 //  device_reset - device-specific reset
275 //-------------------------------------------------
276 
device_reset()277 void abc1600_mover_device::device_reset()
278 {
279 	// disable display
280 	m_clocks_disabled = 1;
281 	m_endisp = 0;
282 }
283 
284 
285 //-------------------------------------------------
286 //  memory_space_config - return a description of
287 //  any address spaces owned by this device
288 //-------------------------------------------------
289 
memory_space_config() const290 device_memory_interface::space_config_vector abc1600_mover_device::memory_space_config() const
291 {
292 	return space_config_vector {
293 		std::make_pair(0, &m_space_config)
294 	};
295 }
296 
297 
298 //-------------------------------------------------
299 //  read_videoram -
300 //-------------------------------------------------
301 
read_videoram(offs_t offset)302 inline uint16_t abc1600_mover_device::read_videoram(offs_t offset)
303 {
304 	return space().read_word((offset & VIDEORAM16_MASK) << 1);
305 }
306 
307 
308 //-------------------------------------------------
309 //  write_videoram -
310 //-------------------------------------------------
311 
write_videoram(offs_t offset,uint16_t data,uint16_t mask)312 inline void abc1600_mover_device::write_videoram(offs_t offset, uint16_t data, uint16_t mask)
313 {
314 	uint16_t old_data = read_videoram(offset);
315 
316 	space().write_word((offset & VIDEORAM16_MASK) << 1, (data & mask) | (old_data & (mask ^ 0xffff)));
317 }
318 
319 
320 //-------------------------------------------------
321 //  video_ram_r -
322 //-------------------------------------------------
323 
video_ram_r(offs_t offset)324 uint8_t abc1600_mover_device::video_ram_r(offs_t offset)
325 {
326 	offs_t addr = (offset & VIDEORAM8_MASK) >> 1;
327 	uint8_t data = 0;
328 
329 	if (offset & 0x01)
330 	{
331 		data = read_videoram(addr) & 0xff;
332 	}
333 	else
334 	{
335 		data = read_videoram(addr) >> 8;
336 	}
337 
338 	return data;
339 }
340 
341 
342 //-------------------------------------------------
343 //  video_ram_w -
344 //-------------------------------------------------
345 
video_ram_w(offs_t offset,uint8_t data)346 void abc1600_mover_device::video_ram_w(offs_t offset, uint8_t data)
347 {
348 	offs_t addr = (offset & VIDEORAM8_MASK) >> 1;
349 
350 	if (offset & 0x01)
351 	{
352 		if (REPLACE)
353 		{
354 			// WRPORT_LB
355 			m_wrm = (m_wrm & 0xff00) | data;
356 			LOG("WRM LB %02x -> %04x\n", data, m_wrm);
357 		}
358 		else
359 		{
360 			// DATAPORT_LB
361 			m_gmdi = (m_gmdi & 0xff00) | data;
362 			LOG("GMDI LB %02x -> %04x\n", data, m_gmdi);
363 		}
364 
365 		write_videoram(addr, m_gmdi, m_wrm & 0x00ff);
366 
367 		LOG("Video RAM write LB to %05x : %04x\n", addr, read_videoram(addr));
368 	}
369 	else
370 	{
371 		if (REPLACE)
372 		{
373 			// WRPORT_HB
374 			m_wrm = (data << 8) | (m_wrm & 0xff);
375 			LOG("WRM HB %02x -> %04x\n", data, m_wrm);
376 		}
377 		else
378 		{
379 			// DATAPORT_HB
380 			m_gmdi = (data << 8) | (m_gmdi & 0xff);
381 			LOG("GMDI HB %02x -> %04x\n", data, m_gmdi);
382 		}
383 
384 		write_videoram(addr, m_gmdi, m_wrm & 0xff00);
385 
386 		LOG("Video RAM write HB to %05x : %04x\n", addr, read_videoram(addr));
387 	}
388 }
389 
390 
391 //-------------------------------------------------
392 //  iord0_r -
393 //-------------------------------------------------
394 
iord0_r()395 uint8_t abc1600_mover_device::iord0_r()
396 {
397 	/*
398 
399 	    bit     description
400 
401 	    0       0
402 	    1       SCREENPOS
403 	    2
404 	    3
405 	    4
406 	    5
407 	    6       VSYNC
408 	    7       BUSY
409 
410 	*/
411 
412 	uint8_t data = 0;
413 
414 	// monitor orientation (portrait/landscape)
415 	data |= machine().render().first_target()->view() << 1;
416 
417 	// vertical sync
418 	data |= m_crtc->vsync_r() << 6;
419 
420 	return data;
421 }
422 
423 
424 //-------------------------------------------------
425 //  ldsx_hb_w -
426 //-------------------------------------------------
427 
ldsx_hb_w(uint8_t data)428 void abc1600_mover_device::ldsx_hb_w(uint8_t data)
429 {
430 	/*
431 
432 	    bit     description
433 
434 	    0       XSIZE8
435 	    1       XSIZE9
436 	    2       U/D* Y
437 	    3       U/D* X
438 	    4
439 	    5
440 	    6
441 	    7
442 
443 	*/
444 
445 	LOG("%s LDSX HB: %02x\n", machine().describe_context(), data);
446 
447 	m_xsize = ((data & 0x03) << 8) | (m_xsize & 0xff);
448 	m_udy = BIT(data, 2);
449 	m_udx = BIT(data, 3);
450 }
451 
452 
453 //-------------------------------------------------
454 //  ldsx_lb_w -
455 //-------------------------------------------------
456 
ldsx_lb_w(uint8_t data)457 void abc1600_mover_device::ldsx_lb_w(uint8_t data)
458 {
459 	/*
460 
461 	    bit     description
462 
463 	    0       XSIZE0
464 	    1       XSIZE1
465 	    2       XSIZE2
466 	    3       XSIZE3
467 	    4       XSIZE4
468 	    5       XSIZE5
469 	    6       XSIZE6
470 	    7       XSIZE7
471 
472 	*/
473 
474 	LOG("%s LDSX LB: %02x\n", machine().describe_context(), data);
475 
476 	m_xsize = (m_xsize & 0x300) | data;
477 }
478 
479 
480 //-------------------------------------------------
481 //  ldsy_hb_w -
482 //-------------------------------------------------
483 
ldsy_hb_w(uint8_t data)484 void abc1600_mover_device::ldsy_hb_w(uint8_t data)
485 {
486 	/*
487 
488 	    bit     description
489 
490 	    0       YSIZE8
491 	    1       YSIZE9
492 	    2       YSIZE10
493 	    3       YSIZE11
494 	    4
495 	    5
496 	    6
497 	    7
498 
499 	*/
500 
501 	LOG("%s LDSY HB: %02x\n", machine().describe_context(), data);
502 
503 	m_ysize = ((data & 0x0f) << 8) | (m_ysize & 0xff);
504 }
505 
506 
507 //-------------------------------------------------
508 //  ldsy_lb_w -
509 //-------------------------------------------------
510 
ldsy_lb_w(uint8_t data)511 void abc1600_mover_device::ldsy_lb_w(uint8_t data)
512 {
513 	/*
514 
515 	    bit     description
516 
517 	    0       YSIZE0
518 	    1       YSIZE1
519 	    2       YSIZE2
520 	    3       YSIZE3
521 	    4       YSIZE4
522 	    5       YSIZE5
523 	    6       YSIZE6
524 	    7       YSIZE7
525 
526 	*/
527 
528 	LOG("%s LDSY LB: %02x\n", machine().describe_context(), data);
529 
530 	m_ysize = (m_ysize & 0xf00) | data;
531 }
532 
533 
534 //-------------------------------------------------
535 //  ldtx_hb_w -
536 //-------------------------------------------------
537 
ldtx_hb_w(uint8_t data)538 void abc1600_mover_device::ldtx_hb_w(uint8_t data)
539 {
540 	/*
541 
542 	    bit     description
543 
544 	    0       XTO8, MTA4
545 	    1       XTO9, MTA5
546 	    2
547 	    3
548 	    4
549 	    5
550 	    6
551 	    7
552 
553 	*/
554 
555 	LOG("%s LDTX HB: %02x\n", machine().describe_context(), data);
556 
557 	m_xto = ((data & 0x03) << 8) | (m_xto & 0xff);
558 	m_mta = (m_mta & 0x3ffcf) | ((data & 0x03) << 4);
559 }
560 
561 
562 //-------------------------------------------------
563 //  ldtx_lb_w -
564 //-------------------------------------------------
565 
ldtx_lb_w(uint8_t data)566 void abc1600_mover_device::ldtx_lb_w(uint8_t data)
567 {
568 	/*
569 
570 	    bit     description
571 
572 	    0       XTO0
573 	    1       XTO1
574 	    2       XTO2
575 	    3       XTO3
576 	    4       XTO4, MTA0
577 	    5       XTO5, MTA1
578 	    6       XTO6, MTA2
579 	    7       XTO7, MTA3
580 
581 	*/
582 
583 	LOG("%s LDTX LB: %02x\n", machine().describe_context(), data);
584 
585 	m_xto = (m_xto & 0x300) | data;
586 	m_mta = (m_mta & 0x3fff0) | (data >> 4);
587 }
588 
589 
590 //-------------------------------------------------
591 //  ldty_hb_w -
592 //-------------------------------------------------
593 
ldty_hb_w(uint8_t data)594 void abc1600_mover_device::ldty_hb_w(uint8_t data)
595 {
596 	/*
597 
598 	    bit     description
599 
600 	    0       YTO8, MTA14
601 	    1       YTO9, MTA15
602 	    2       YTO10, MTA16
603 	    3       YTO11, MTA17
604 	    4
605 	    5
606 	    6
607 	    7
608 
609 	*/
610 
611 	LOG("%s LDTY HB: %02x\n", machine().describe_context(), data);
612 
613 	if (L_P) return;
614 
615 	m_ty = ((data & 0x0f) << 8) | (m_yto & 0xff);
616 	m_yto = ((data & 0x0f) << 8) | (m_yto & 0xff);
617 	m_mta = ((data & 0x0f) << 14) | (m_mta & 0x3fff);
618 }
619 
620 
621 //-------------------------------------------------
622 //  ldty_lb_w -
623 //-------------------------------------------------
624 
ldty_lb_w(uint8_t data)625 void abc1600_mover_device::ldty_lb_w(uint8_t data)
626 {
627 	/*
628 
629 	    bit     description
630 
631 	    0       YTO0, MTA6
632 	    1       YTO1, MTA7
633 	    2       YTO2, MTA8
634 	    3       YTO3, MTA9
635 	    4       YTO4, MTA10
636 	    5       YTO5, MTA11
637 	    6       YTO6, MTA12
638 	    7       YTO7, MTA13
639 
640 	*/
641 
642 	LOG("%s LDTY LB: %02x\n", machine().describe_context(), data);
643 
644 	if (L_P) return;
645 
646 	m_ty = (m_ty & 0xf00) | data;
647 	m_yto = (m_yto & 0xf00) | data;
648 	m_mta = (m_mta & 0x3c03f) | (data << 6);
649 }
650 
651 
652 //-------------------------------------------------
653 //  ldfx_hb_w -
654 //-------------------------------------------------
655 
ldfx_hb_w(uint8_t data)656 void abc1600_mover_device::ldfx_hb_w(uint8_t data)
657 {
658 	/*
659 
660 	    bit     description
661 
662 	    0       XFROM8, MFA4
663 	    1       XFROM9, MFA5
664 	    2
665 	    3
666 	    4
667 	    5
668 	    6
669 	    7
670 
671 	*/
672 
673 	LOG("%s LDFX HB: %02x\n", machine().describe_context(), data);
674 
675 	m_xfrom = ((data & 0x03) << 8) | (m_xfrom & 0xff);
676 	m_mfa = (m_mfa & 0x3ffcf) | ((data & 0x03) << 4);
677 }
678 
679 
680 //-------------------------------------------------
681 //  ldfx_lb_w -
682 //-------------------------------------------------
683 
ldfx_lb_w(uint8_t data)684 void abc1600_mover_device::ldfx_lb_w(uint8_t data)
685 {
686 	/*
687 
688 	    bit     description
689 
690 	    0       XFROM0
691 	    1       XFROM1
692 	    2       XFROM2
693 	    3       XFROM3
694 	    4       XFROM4, MFA0
695 	    5       XFROM5, MFA1
696 	    6       XFROM6, MFA2
697 	    7       XFROM7, MFA3
698 
699 	*/
700 
701 	LOG("%s LDFX LB: %02x\n", machine().describe_context(), data);
702 
703 	m_xfrom = (m_xfrom & 0x300) | data;
704 	m_mfa = (m_mfa & 0x3fff0) | (data >> 4);
705 }
706 
707 
708 //-------------------------------------------------
709 //  ldfy_hb_w -
710 //-------------------------------------------------
711 
ldfy_hb_w(uint8_t data)712 void abc1600_mover_device::ldfy_hb_w(uint8_t data)
713 {
714 	/*
715 
716 	    bit     description
717 
718 	    0       MFA14
719 	    1       MFA15
720 	    2       MFA16
721 	    3       MFA17
722 	    4
723 	    5
724 	    6
725 	    7
726 
727 	*/
728 
729 	LOG("%s LDFY HB: %02x\n", machine().describe_context(), data);
730 
731 	m_mfa = ((data & 0x0f) << 14) | (m_mfa & 0x3fff);
732 }
733 
734 
735 //-------------------------------------------------
736 //  ldfy_lb_w -
737 //-------------------------------------------------
738 
ldfy_lb_w(uint8_t data)739 void abc1600_mover_device::ldfy_lb_w(uint8_t data)
740 {
741 	/*
742 
743 	    bit     description
744 
745 	    0       MFA6
746 	    1       MFA7
747 	    2       MFA8
748 	    3       MFA9
749 	    4       MFA10
750 	    5       MFA11
751 	    6       MFA12
752 	    7       MFA13
753 
754 	*/
755 
756 	LOG("%s LDFY LB: %02x\n", machine().describe_context(), data);
757 
758 	m_mfa = (m_mfa & 0x3c03f) | (data << 6);
759 
760 	mover();
761 }
762 
763 
764 //-------------------------------------------------
765 //  wrml_w -
766 //-------------------------------------------------
767 
wrml_w(offs_t offset,uint8_t data)768 void abc1600_mover_device::wrml_w(offs_t offset, uint8_t data)
769 {
770 	/*
771 
772 	    bit     description
773 
774 	    0       MOVE CYK CLK
775 	    1       DISP CYC SEL / DISP CYK PRE FETCH (+1 PIXCLK)
776 	    2       DATA CLK
777 	    3       _DISP MEM WE
778 	    4       _CAS HB
779 	    5       DTACK CLK / BLANK TEST (+2 PIXCLK)
780 	    6       DISPREC CLK
781 	    7       _RAS HB
782 
783 	*/
784 
785 	LOG("MS %u : %02x\n", (offset >> 4) & 0x0f, data);
786 
787 	if (m_clocks_disabled)
788 	{
789 		m_ms[(offset >> 4) & 0x0f] = data;
790 	}
791 }
792 
793 
794 //-------------------------------------------------
795 //  wrdl_w -
796 //-------------------------------------------------
797 
wrdl_w(offs_t offset,uint8_t data)798 void abc1600_mover_device::wrdl_w(offs_t offset, uint8_t data)
799 {
800 	/*
801 
802 	    bit     description
803 
804 	    0       MOVE CYK CLK
805 	    1       DISP CYC SEL / DISP CYK PRE FETCH (+1 PIXCLK)
806 	    2       DATA CLK
807 	    3       _DISP MEM WE
808 	    4       _CAS HB
809 	    5       DTACK CLK / BLANK TEST (+2 PIXCLK)
810 	    6       DISPREC CLK
811 	    7       _RAS HB
812 
813 	*/
814 
815 	LOG("WS %u : %02x\n", (offset >> 4) & 0x0f, data);
816 
817 	if (m_clocks_disabled)
818 	{
819 		m_ds[(offset >> 4) & 0x0f] = data;
820 	}
821 }
822 
823 
824 //-------------------------------------------------
825 //  wrmask_strobe_hb_w -
826 //-------------------------------------------------
827 
wrmask_strobe_hb_w(uint8_t data)828 void abc1600_mover_device::wrmask_strobe_hb_w(uint8_t data)
829 {
830 	if (REPLACE)
831 	{
832 		// DATAPORT_HB
833 		m_gmdi = (data << 8) | (m_gmdi & 0xff);
834 		LOG("GMDI HB %04x\n", m_gmdi);
835 	}
836 	else
837 	{
838 		// WRPORT_HB
839 		m_wrm = (data << 8) | (m_wrm & 0xff);
840 		LOG("WRM HB %04x\n", m_gmdi);
841 	}
842 }
843 
844 
845 //-------------------------------------------------
846 //  wrmask_strobe_lb_w -
847 //-------------------------------------------------
848 
wrmask_strobe_lb_w(uint8_t data)849 void abc1600_mover_device::wrmask_strobe_lb_w(uint8_t data)
850 {
851 	if (REPLACE)
852 	{
853 		// DATAPORT_LB
854 		m_gmdi = (m_gmdi & 0xff00) | data;
855 		LOG("GMDI LB %04x\n", m_gmdi);
856 	}
857 	else
858 	{
859 		// WRPORT_LB
860 		m_wrm = (m_wrm & 0xff00) | data;
861 		LOG("WRM LB %04x\n", m_gmdi);
862 	}
863 }
864 
865 
866 //-------------------------------------------------
867 //  enable_clocks_w -
868 //-------------------------------------------------
869 
enable_clocks_w(uint8_t data)870 void abc1600_mover_device::enable_clocks_w(uint8_t data)
871 {
872 	LOG("ENABLE CLOCKS\n");
873 	m_clocks_disabled = 0;
874 }
875 
876 
877 //-------------------------------------------------
878 //  flag_strobe_w -
879 //-------------------------------------------------
880 
flag_strobe_w(uint8_t data)881 void abc1600_mover_device::flag_strobe_w(uint8_t data)
882 {
883 	/*
884 
885 	    bit     description
886 
887 	    0       L/_P FLAG
888 	    1       BLANK FLAG
889 	    2       PIX POL
890 	    3       FRAME POL
891 	    4       HOLD FY
892 	    5       HOLD FX
893 	    6       COMP MOVE FLAG
894 	    7       REPLACE/SET & RESET
895 
896 	*/
897 
898 	m_flag = data;
899 	LOG("FLAG %02x\n", m_flag);
900 }
901 
902 
903 //-------------------------------------------------
904 //  endisp_w -
905 //-------------------------------------------------
906 
endisp_w(uint8_t data)907 void abc1600_mover_device::endisp_w(uint8_t data)
908 {
909 	m_endisp = 1;
910 	LOG("ENDISP\n");
911 }
912 
913 
914 
915 //**************************************************************************
916 //  MOVER
917 //**************************************************************************
918 
919 //-------------------------------------------------
920 //  clock_mfa_x -
921 //-------------------------------------------------
922 
clock_mfa_x()923 inline void abc1600_mover_device::clock_mfa_x()
924 {
925 	uint16_t mfa_y = m_mfa >> 6;
926 	uint8_t mfa_x = m_mfa & 0x3f;
927 
928 	if (!HOLD_FX)
929 	{
930 		mfa_x += m_udx ? 1 : -1;
931 		mfa_x &= 0x3f;
932 	}
933 
934 	m_mfa = (mfa_y << 6) | mfa_x;
935 }
936 
937 
938 //-------------------------------------------------
939 //  clock_mfa_y -
940 //-------------------------------------------------
941 
clock_mfa_y()942 inline void abc1600_mover_device::clock_mfa_y()
943 {
944 	uint16_t mfa_y = m_mfa >> 6;
945 	uint8_t mfa_x = m_mfa & 0x3f;
946 
947 	if (!HOLD_FY)
948 	{
949 		mfa_y += m_udy ? 1 : -1;
950 		mfa_y &= 0xfff;
951 	}
952 
953 	m_mfa = (mfa_y << 6) | mfa_x;
954 }
955 
956 
957 //-------------------------------------------------
958 //  clock_mta_x -
959 //-------------------------------------------------
960 
clock_mta_x()961 inline void abc1600_mover_device::clock_mta_x()
962 {
963 	uint16_t mta_y = m_mta >> 6;
964 	uint8_t mta_x = m_mta & 0x3f;
965 
966 	mta_x += m_udx ? 1 : -1;
967 	mta_x &= 0x3f;
968 
969 	m_mta = (mta_y << 6) | mta_x;
970 }
971 
972 
973 //-------------------------------------------------
974 //  clock_mta_y -
975 //-------------------------------------------------
976 
clock_mta_y()977 inline void abc1600_mover_device::clock_mta_y()
978 {
979 	uint16_t mta_y = m_mta >> 6;
980 	uint8_t mta_x = m_mta & 0x3f;
981 
982 	mta_y += m_udy ? 1 : -1;
983 	mta_y &= 0xfff;
984 
985 	m_mta = (mta_y << 6) | mta_x;
986 }
987 
988 
989 //-------------------------------------------------
990 //  load_mfa_x -
991 //-------------------------------------------------
992 
load_mfa_x()993 inline void abc1600_mover_device::load_mfa_x()
994 {
995 	uint16_t mfa_y = m_mfa >> 6;
996 	uint8_t mfa_x = m_xfrom >> 4;
997 
998 	m_mfa = (mfa_y << 6) | mfa_x;
999 }
1000 
1001 
1002 //-------------------------------------------------
1003 //  load_mta_x -
1004 //-------------------------------------------------
1005 
load_mta_x()1006 inline void abc1600_mover_device::load_mta_x()
1007 {
1008 	uint16_t mta_y = m_mta >> 6;
1009 	uint8_t mta_x = m_xto >> 4;
1010 
1011 	m_mta = (mta_y << 6) | mta_x;
1012 }
1013 
1014 
1015 //-------------------------------------------------
1016 //  load_xy_reg -
1017 //-------------------------------------------------
1018 
load_xy_reg()1019 inline void abc1600_mover_device::load_xy_reg()
1020 {
1021 	if (L_P) return;
1022 
1023 	uint16_t sum = m_xto + m_xsize;
1024 
1025 	m_xto = sum & 0x3ff;
1026 	m_yto = m_ty & 0xfff;
1027 	m_mta = (m_ty << 6) | (sum >> 4);
1028 }
1029 
1030 
1031 //-------------------------------------------------
1032 //  compare_mta_x -
1033 //-------------------------------------------------
1034 
compare_mta_x()1035 inline void abc1600_mover_device::compare_mta_x()
1036 {
1037 	uint8_t mta_x_end = ((m_xto + m_xsize) >> 4) & 0x3f;
1038 	uint8_t mta_x = m_mta & 0x3f;
1039 
1040 	if (mta_x == mta_x_end)
1041 	{
1042 		m_cmc = 0;
1043 	}
1044 
1045 	m_wrms1 = m_cmc & m_amm;
1046 }
1047 
1048 
1049 //-------------------------------------------------
1050 //  compare_mta_y -
1051 //-------------------------------------------------
1052 
compare_mta_y()1053 inline void abc1600_mover_device::compare_mta_y()
1054 {
1055 	int mta_y_end = (m_yto + m_ysize) & 0xfff;
1056 	uint16_t mta_y = m_mta >> 6;
1057 
1058 	if (mta_y == mta_y_end)
1059 	{
1060 		m_rmc = 0;
1061 	}
1062 }
1063 
1064 
1065 //-------------------------------------------------
1066 //  get_shinf -
1067 //-------------------------------------------------
1068 
get_shinf()1069 inline void abc1600_mover_device::get_shinf()
1070 {
1071 	/*
1072 
1073 	    bit     description
1074 
1075 	    A0      XFROM0
1076 	    A1      XFROM1
1077 	    A2      XFROM2
1078 	    A3      XFROM3
1079 	    A4      XTO0
1080 	    A5      XTO1
1081 	    A6      XTO2
1082 	    A7      XTO3
1083 	    A8      U/D* X
1084 
1085 	*/
1086 
1087 	uint16_t shinf_addr = (m_udx << 8) | ((m_xto & 0x0f) << 4) | (m_xfrom & 0x0f);
1088 	uint8_t shinf = m_shinf_rom[shinf_addr];
1089 
1090 	m_sh = shinf & 0x0f;
1091 	m_hold_1w_cyk = BIT(shinf, 5);
1092 }
1093 
1094 
1095 //-------------------------------------------------
1096 //  get_drmsk -
1097 //-------------------------------------------------
1098 
get_drmsk()1099 inline uint16_t abc1600_mover_device::get_drmsk()
1100 {
1101 	/*
1102 
1103 	    bit     description
1104 
1105 	    A0      SH0
1106 	    A1      SH1
1107 	    A2      SH2
1108 	    A3      SH3
1109 	    A4      U/D* X
1110 
1111 	*/
1112 
1113 	uint16_t drmsk_addr = (m_udx << 4) | (m_sh & 0x0f);
1114 	return m_drmsk_rom[drmsk_addr];
1115 }
1116 
1117 
1118 //-------------------------------------------------
1119 //  get_wrmsk - get mover write mask
1120 //-------------------------------------------------
1121 
get_wrmsk()1122 inline uint16_t abc1600_mover_device::get_wrmsk()
1123 {
1124 	/*
1125 
1126 	    bit     description
1127 
1128 	    A0      XTO0
1129 	    A1      XTO1
1130 	    A2      XTO2
1131 	    A3      XTO3
1132 	    A4      XSIZE0
1133 	    A5      XSIZE1
1134 	    A6      XSIZE2
1135 	    A7      XSIZE3
1136 	    A8      U/D* X
1137 	    A9      ANDED MASKS
1138 	    A10     WRMS0
1139 	    A11     WRMS1
1140 
1141 	*/
1142 
1143 	uint16_t wrmsk_addr = (m_wrms1 << 11) | (m_wrms0 << 10) | ((!m_wrms1 && !m_wrms0) << 9) | (m_udx << 8) | ((m_xsize & 0x0f) << 4) | (m_xto & 0x0f);
1144 	return m_wrmsk_rom[wrmsk_addr] ^ 0xffff;
1145 }
1146 
1147 
1148 //-------------------------------------------------
1149 //  barrel_shift -
1150 //-------------------------------------------------
1151 
barrel_shift(uint16_t gmdr)1152 inline uint16_t abc1600_mover_device::barrel_shift(uint16_t gmdr)
1153 {
1154 	uint16_t rot = gmdr;
1155 
1156 	for (int sh = 0; sh < m_sh; sh++)
1157 	{
1158 		int msb = BIT(rot, 15);
1159 		rot <<= 1;
1160 		rot |= msb;
1161 	}
1162 
1163 	return rot;
1164 }
1165 
1166 
1167 //-------------------------------------------------
1168 //  word_mixer -
1169 //-------------------------------------------------
1170 
word_mixer(uint16_t rot)1171 inline uint16_t abc1600_mover_device::word_mixer(uint16_t rot)
1172 {
1173 	uint16_t drmsk = get_drmsk();
1174 	uint16_t gmdi = (rot & drmsk) | (m_mdor & (drmsk ^ 0xffff));
1175 
1176 	if (COMP_MOVE)
1177 	{
1178 		gmdi ^= 0xffff;
1179 	}
1180 
1181 	m_mdor = rot;
1182 
1183 	return gmdi;
1184 }
1185 
1186 
1187 //-------------------------------------------------
1188 //  mover -
1189 //-------------------------------------------------
1190 
mover()1191 void abc1600_mover_device::mover()
1192 {
1193 	LOG("XFROM %u XSIZE %u YSIZE %u XTO %u YTO %u MFA %05x MTA %05x U/D*X %u U/D*Y %u\n", m_xfrom, m_xsize, m_ysize, m_xto, m_yto, m_mfa, m_mta, m_udx, m_udy);
1194 
1195 	m_amm = 1;
1196 
1197 	m_rmc = 1;
1198 	get_shinf();
1199 
1200 	do
1201 	{
1202 		compare_mta_y();
1203 
1204 		load_mfa_x();
1205 		load_mta_x();
1206 		m_cmc = 1;
1207 		m_wrms0 = 0;
1208 
1209 		if (m_hold_1w_cyk)
1210 		{
1211 			// read one word in advance
1212 			uint16_t gmdr = read_videoram(m_mfa);
1213 			uint16_t rot = barrel_shift(gmdr);
1214 			word_mixer(rot);
1215 
1216 			clock_mfa_x();
1217 		}
1218 
1219 		do
1220 		{
1221 			compare_mta_x();
1222 
1223 			uint16_t gmdr = read_videoram(m_mfa);
1224 			uint16_t rot = barrel_shift(gmdr);
1225 			uint16_t gmdi = word_mixer(rot);
1226 			uint16_t mask = get_wrmsk();
1227 
1228 			write_videoram(m_mta, gmdi, mask);
1229 
1230 			clock_mfa_x();
1231 			clock_mta_x();
1232 
1233 			m_wrms0 = 1;
1234 		}
1235 		while (m_cmc);
1236 
1237 		clock_mfa_y();
1238 		clock_mta_y();
1239 	}
1240 	while (m_rmc);
1241 
1242 	load_xy_reg();
1243 
1244 	m_amm = 0;
1245 }
1246 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)1247 uint32_t abc1600_mover_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
1248 {
1249 	if (m_endisp)
1250 	{
1251 		bitmap.fill(m_palette->pen(FRAME_POL), cliprect);
1252 		m_crtc->screen_update(screen, bitmap, cliprect);
1253 	}
1254 	else
1255 	{
1256 		bitmap.fill(rgb_t::black(), cliprect);
1257 	}
1258 
1259 	return 0;
1260 }
1261