1 // license:BSD-3-Clause
2 // copyright-holders:Philip Bennett
3 /***************************************************************************
4 
5     3DO M2 Bulldog ASIC
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "3dom2.h"
11 
12 #include <algorithm> // std::min
13 
14 
15 //**************************************************************************
16 //  MACROS / CONSTANTS
17 //**************************************************************************
18 
19 // Device type definitions
20 DEFINE_DEVICE_TYPE(M2_BDA, m2_bda_device, "m2bda", "3DO M2 Bulldog ASIC")
21 DEFINE_DEVICE_TYPE(M2_POWERBUS, m2_powerbus_device, "m2powerbus", "BDA PowerBus Controller")
22 DEFINE_DEVICE_TYPE(M2_MEMCTL, m2_memctl_device, "m2memctl", "BDA Memory Controller")
23 DEFINE_DEVICE_TYPE(M2_VDU, m2_vdu_device, "m2vdu", "BDA VDU")
24 DEFINE_DEVICE_TYPE(M2_CTRLPORT, m2_ctrlport_device, "m2ctrlport", "BDA Control Ports")
25 DEFINE_DEVICE_TYPE(M2_MPEG, m2_mpeg_device, "m2mpeg", "3DO MPEG Decoder")
26 DEFINE_DEVICE_TYPE(M2_CDE, m2_cde_device, "m2cde", "3DO M2 CDE ASIC")
27 
28 
29 
30 //**************************************************************************
31 //  VDU REGISTER DEFINITIONS
32 //**************************************************************************
33 
34 #define VDU_VLOC                0x00
35 #define VDU_VINT                0x04
36 #define VDU_VDC0                0x08
37 #define VDU_VDC1                0x0c
38 #define VDU_FV0A                0x10
39 #define VDU_FV1A                0x14
40 #define VDU_AVDI                0x1c
41 #define VDU_VDLI                0x20
42 #define VDU_VCFG                0x24
43 #define VDU_DMT0                0x28
44 #define VDU_DMT1                0x2c
45 #define VDU_LFSR                0x30
46 #define VDU_VRST                0x34
47 
48 //-------------------------------------------------
49 //  VLOC
50 //-------------------------------------------------
51 #define VDU_VLOC_VCOUNT_MASK    0x00003FF8
52 #define VDU_VLOC_VCOUNT_SHIFT   3
53 #define VDU_VLOC_VIDEOFIELD     0x00004000
54 #define VDU_VLOC_RESERVED       0xFFFF8007
55 
56 //-------------------------------------------------
57 //  VINT
58 //-------------------------------------------------
59 #define VDU_VINT_VINT0          0x80000000
60 #define VDU_VINT_VLINE0_MASK    0x7FF00000
61 #define VDU_VINT_VLINE0_SHIFT   20
62 #define VDU_VINT_VINT1          0x00008000
63 #define VDU_VINT_VLINE1_MASK    0x00007FF0
64 #define VDU_VINT_VLINE1_SHIFT   4
65 #define VDU_VINT_RESERVED       0x000F000F
66 
67 //-------------------------------------------------
68 //  VDC0/VDC1
69 //-------------------------------------------------
70 #define VDU_VDC_HINT            0x02000000
71 #define VDU_VDC_VINT            0x01000000
72 #define VDU_VDC_DITHER          0x00400000
73 #define VDU_VDC_MTXBYP          0x00200000
74 #define VDU_VDC_RESERVED        0xFC9FFFFF
75 
76 //-------------------------------------------------
77 //  AVDI
78 //-------------------------------------------------
79 #define VDU_AVDI_HSTART_MASK    0xFFE00000
80 #define VDU_AVDI_HWIDTH_MASK    0x0003FF80
81 #define VDU_AVDI_HDOUBLE        0x00000008
82 #define VDU_AVDI_VDOUBLE        0x00000004
83 #define VDU_AVDI_RESERVED       0x001C0073
84 #define VDU_AVDI_HSTART_SHIFT   21
85 #define VDU_AVDI_HWIDTH_SHIFT   7
86 
87 //-------------------------------------------------
88 //  VDLI
89 //-------------------------------------------------
90 #define VDU_VDLI_BYPASSTYPE     0x10000000
91 #define VDU_VDLI_FBFORMAT       0x04000000
92 #define VDU_VDLI_ONEVINTDIS     0x00400000
93 #define VDU_VDLI_RANDOMDITHER   0x00200000
94 #define VDU_VDLI_RESERVED       0xEB9FFFFF
95 #define VDU_VDLI_BYPASSTYPE_MSB 0
96 #define VDU_VDLI_BYPASSTYPE_LSB 0x10000000
97 #define VDU_VDLI_FBFORMAT_16    0
98 #define VDU_VDLI_FBFORMAT_32    0x04000000
99 
100 //-------------------------------------------------
101 //  VCFG
102 //-------------------------------------------------
103 
104 //-------------------------------------------------
105 //  VRST
106 //-------------------------------------------------
107 #define VDU_VRST_DVERESET       0x00000002
108 #define VDU_VRST_VIDRESET       0x00000001
109 #define VDU_VRST_RESERVED       0xFFFFFFFC
110 
111 
112 //-------------------------------------------------
113 //  VDL DMA CONTROL WORD
114 //-------------------------------------------------
115 #define VDL_DMA_MOD_MASK        0xFF000000
116 #define VDL_DMA_ENABLE          0x00200000
117 #define VDL_DMA_NOBUCKET        0x00020000
118 #define VDL_DMA_LDLOWER         0x00010000
119 #define VDL_DMA_LDUPPER         0x00008000
120 #define VDL_DMA_NWORDS_MASK     0x00007E00
121 #define VDL_DMA_NLINES_MASK     0x000001FF
122 #define VDL_DMA_RESERVED        0x00DC0000
123 #define VDL_DMA_NWORDS_SHIFT    9
124 #define VDL_DMA_MOD_SHIFT       24
125 #define VDL_DMA_NLINES_SHIFT    0
126 
127 //-------------------------------------------------
128 //  VDL DC CONTROL WORD
129 //-------------------------------------------------
130 #define VDL_DC                  0x80000000
131 #define VDL_DC_0                0x00000000
132 #define VDL_DC_1                0x10000000
133 #define VDL_DC_HINTCTL_MASK     0x00060000
134 #define VDL_DC_HINTCTL_SHIFT    17
135 #define VDL_DC_VINTCTL_MASK     0x00018000
136 #define VDL_DC_VINTCTL_SHIFT    15
137 #define VDL_DC_DITHERCTL_MASK   0x00001800
138 #define VDL_DC_DITHERCTL_SHIFT  11
139 #define VDL_DC_MTXBYPCTL_MASK   0x00000600
140 #define VDL_DC_MTXBYPCTL_SHIFT  9
141 #define VDL_DC_RESERVED         0x0FF861FF
142 #define VDL_CTL_DISABLE         0
143 #define VDL_CTL_ENABLE          1
144 #define VDL_CTL_NOP             2
145 
146 //-------------------------------------------------
147 //  VDL AV CONTROL WORD
148 //-------------------------------------------------
149 #define VDL_AV                  0xA0000000
150 #define VDL_AV_HSTART_MASK      0x1FFC0000
151 #define VDL_AV_HSTART_SHIFT     18
152 #define VDL_AV_LD_HSTART        0x00020000
153 #define VDL_AV_HWIDTH_MASK      0x0001FFC0
154 #define VDL_AV_HWIDTH_SHIFT     6
155 #define VDL_AV_LD_HWIDTH        0x00000020
156 #define VDL_AV_HDOUBLE          0x00000010
157 #define VDL_AV_VDOUBLE          0x00000008
158 #define VDL_AV_LD_HDOUBLE       0x00000004
159 #define VDL_AV_LD_VDOUBLE       0x00000002
160 #define VDL_AV_RESERVED         0x00000001
161 
162 //-------------------------------------------------
163 //  VDL LC CONTROL WORD
164 //-------------------------------------------------
165 #define VDL_LC                  0xC0000000
166 #define VDL_LC_BYPASSTYPE       0x02000000
167 #define VDL_LC_FBFORMAT         0x00800000
168 #define VDL_LC_ONEVINTDIS       0x00080000
169 #define VDL_LC_RANDOMDITHER     0x00040000
170 #define VDL_LC_LD_BYPASSTYPE    0x00002000
171 #define VDL_LC_LD_FBFORMAT      0x00001000
172 #define VDL_LC_RESERVED         0x1D73CFFF
173 #define VDL_LC_BYPASSTYPE_MSB   0x00000000
174 #define VDL_LC_BYPASSTYPE_LSB   0x02000000
175 #define VDL_LC_FBFORMAT_16      0x00000000
176 #define VDL_LC_FBFORMAT_32      0x00800000
177 
178 //-------------------------------------------------
179 //  VDL DMA CONTROL WORD
180 //-------------------------------------------------
181 
182 #define VDL_NOP                 0xe1000000
183 
184 
185 
186 /***************************************************************************
187     SUPPORT FUNCTIONS
188 ***************************************************************************/
189 
write_m2_reg(uint32_t & reg,uint32_t data,m2_reg_wmode mode)190 static void write_m2_reg(uint32_t &reg, uint32_t data, m2_reg_wmode mode)
191 {
192 	switch (mode)
193 	{
194 		case REG_WRITE: reg = data;     break;
195 		case REG_SET:   reg |= data;    break;
196 		case REG_CLEAR: reg &= ~data;   break;
197 		default:
198 			throw emu_fatalerror("write_m2_reg: Bad register write mode");
199 	}
200 }
201 
202 
203 
204 //**************************************************************************
205 //  BDA DEVICE
206 //**************************************************************************
207 
208 //-------------------------------------------------
209 //  m2_bda_device - constructor
210 //-------------------------------------------------
211 
m2_bda_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)212 m2_bda_device::m2_bda_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
213 	device_t(mconfig, M2_BDA, tag, owner, clock),
214 	m_cpu1(*this, finder_base::DUMMY_TAG),
215 	m_cpu2(*this, finder_base::DUMMY_TAG),
216 	m_cde(*this, finder_base::DUMMY_TAG),
217 	m_videores_in(*this),
218 	m_memctl(*this, "memctl"),
219 	m_powerbus(*this, "powerbus"),
220 	m_vdu(*this, "vdu"),
221 	m_ctrlport(*this, "ctrlport"),
222 	m_dspp(*this, "dspp"),
223 	m_mpeg(*this, "mpeg"),
224 	m_te(*this, "te"),
225 	m_dac_l(*this),
226 	m_dac_r(*this)
227 {
228 }
229 
230 
231 //-------------------------------------------------
232 //  device_start - device-specific startup
233 //-------------------------------------------------
234 
device_start()235 void m2_bda_device::device_start()
236 {
237 	// Resolve callbacks
238 	m_videores_in.resolve_safe(0);
239 	m_dac_l.resolve_safe();
240 	m_dac_r.resolve_safe();
241 
242 	// Allocate RAM
243 	uint32_t ram_size = (m_rambank_size[0] + m_rambank_size[1]) * 1024 * 1024;
244 	m_ram = auto_alloc_array(machine(), uint32_t, ram_size / sizeof(uint32_t));
245 	m_ram_mask = ram_size - 1;
246 
247 	// Install RAM and handlers into the CPU address spaces
248 	configure_ppc_address_map(m_cpu1->space(AS_PROGRAM));
249 	configure_ppc_address_map(m_cpu2->space(AS_PROGRAM));
250 
251 	// Register state for saving
252 	save_pointer(NAME(m_ram), ram_size / sizeof(uint32_t));
253 
254 	// Set a timer to pull data from the DSPP FIFO into the DACs
255 	m_dac_timer = timer_alloc(0);
256 	m_dac_timer->adjust(attotime::from_hz(16.9345));
257 }
258 
259 
260 //-------------------------------------------------
261 //  device_reset - device-specific reset
262 //-------------------------------------------------
263 
device_reset()264 void m2_bda_device::device_reset()
265 {
266 
267 }
268 
269 
270 //-------------------------------------------------
271 //  device_post_load - device-specific post-load
272 //-------------------------------------------------
273 
device_post_load()274 void m2_bda_device::device_post_load()
275 {
276 
277 }
278 
279 
280 //-------------------------------------------------
281 //  machine_config_fragment - declare sub-devices
282 //-------------------------------------------------
283 
device_add_mconfig(machine_config & config)284 void m2_bda_device::device_add_mconfig(machine_config &config)
285 {
286 	M2_MEMCTL(config, m_memctl, DERIVED_CLOCK(1, 1));
287 
288 	M2_POWERBUS(config, m_powerbus, DERIVED_CLOCK(1, 1));
289 
290 	M2_VDU(config, m_vdu, DERIVED_CLOCK(1, 1));
291 	m_vdu->vint0_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_VINT0_LINE>));
292 	m_vdu->vint1_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_VINT1_LINE>));
293 
294 	M2_CTRLPORT(config, m_ctrlport, DERIVED_CLOCK(1, 1));
295 
296 	M2_MPEG(config, m_mpeg, DERIVED_CLOCK(1, 1));
297 //  m_mpeg->int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_MPEG_LINE>));
298 
299 	DSPP(config, m_dspp, DERIVED_CLOCK(1, 1));
300 	m_dspp->int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_DSP_LINE>));
301 	m_dspp->dma_read_handler().set(FUNC(m2_bda_device::read_bus8));
302 	m_dspp->dma_write_handler().set(FUNC(m2_bda_device::write_bus8));
303 
304 	M2_TE(config, m_te, DERIVED_CLOCK(1, 1));
305 	m_te->general_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_TRIGEN_LINE>));
306 	m_te->dfinstr_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_TRIDFINST_LINE>));
307 	m_te->iminstr_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_TRIDMINST_LINE>));
308 	m_te->listend_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_TRILISTEND_LINE>));
309 	m_te->winclip_int_handler().set(m_powerbus, FUNC(m2_powerbus_device::int_line<BDAINT_TRIWINCLIP_LINE>));
310 }
311 
312 
313 //-------------------------------------------------
314 //  device_timer - device-specific timers
315 //-------------------------------------------------
316 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)317 void m2_bda_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
318 {
319 	switch (id)
320 	{
321 		case 0:
322 		{
323 			m_dac_l(m_dspp->read_output_fifo());
324 			m_dac_r(m_dspp->read_output_fifo());
325 			m_dac_timer->adjust(attotime::from_hz(44100));
326 			break;
327 		}
328 	}
329 }
330 
331 
332 
333 /***************************************************************************
334     PUBLIC FUNCTIONS
335 ***************************************************************************/
336 
337 //-------------------------------------------------
338 //  cpu_id_r - read from CPU ID register
339 //-------------------------------------------------
340 
cpu_id_r(address_space & space)341 uint32_t m2_bda_device::cpu_id_r(address_space &space)
342 {
343 	uint32_t data = 0;
344 
345 	// .x...... ........ ........ ........ -  Video type (0 = Arcade, 1 = NTSC/PAL)
346 	// x....... ........ ........ ........ -  CPU ID     (0 = CPU1, 1 = CPU2)
347 
348 	if (&space.device() == m_cpu2)
349 		data |= 0x80000000;
350 
351 	if (m_videores_in() != 0)
352 		data |= 0x40000000;
353 
354 	return data;
355 }
356 
357 
358 //-------------------------------------------------
359 //  cpu_id_w - Write to CPU ID register
360 //-------------------------------------------------
361 
cpu_id_w(address_space & space,uint32_t data)362 void m2_bda_device::cpu_id_w(address_space &space, uint32_t data)
363 {
364 	// TODO: How should this work?
365 	logerror("%s: CPUID: %x\n", machine().describe_context(), data);
366 }
367 
368 
369 //-------------------------------------------------
370 //  read_bus8 - Read 8-bit data from the PowerBus
371 //-------------------------------------------------
372 
read_bus8(offs_t offset)373 uint8_t m2_bda_device::read_bus8(offs_t offset)
374 {
375 	assert(offset >= RAM_BASE && offset <= RAM_BASE + m_ram_mask);
376 
377 	offset &= m_ram_mask;
378 	uint8_t *ptr = reinterpret_cast<uint8_t *>(&m_ram[0]) + BYTE8_XOR_BE(offset);
379 	return *ptr;
380 }
381 
382 
383 //-------------------------------------------------
384 //  read_bus16 - Read 16-bit data from the PowerBus
385 //-------------------------------------------------
386 
read_bus16(offs_t offset)387 uint16_t m2_bda_device::read_bus16(offs_t offset)
388 {
389 	assert(offset >= RAM_BASE && offset <= RAM_BASE + m_ram_mask);
390 
391 	offset &= m_ram_mask;
392 	uint8_t *ptr = reinterpret_cast<uint8_t *>(&m_ram[0]) + WORD2_XOR_BE(offset);
393 	return *reinterpret_cast<uint16_t *>(ptr);
394 }
395 
396 
397 //-------------------------------------------------
398 //  read_bus32 - Read 32-bit data from the PowerBus
399 //-------------------------------------------------
400 
read_bus32(offs_t offset)401 uint32_t m2_bda_device::read_bus32(offs_t offset)
402 {
403 	assert(offset >= RAM_BASE && offset <= RAM_BASE + m_ram_mask);
404 
405 	offset &= m_ram_mask;
406 
407 	uint8_t *ptr = reinterpret_cast<uint8_t *>(&m_ram[0]) + DWORD_XOR_BE(offset);
408 	return *reinterpret_cast<uint32_t *>(ptr);
409 }
410 
411 
412 //-------------------------------------------------
413 //  write_bus8 - Write 8-bit data to the PowerBus
414 //-------------------------------------------------
415 
write_bus8(offs_t offset,uint8_t data)416 void m2_bda_device::write_bus8(offs_t offset, uint8_t data)
417 {
418 	assert(offset >= RAM_BASE && offset <= RAM_BASE + m_ram_mask);
419 
420 	offset &= m_ram_mask;
421 	uint8_t *ptr = reinterpret_cast<uint8_t *>(&m_ram[0]) + BYTE8_XOR_BE(offset);
422 	*ptr = data;
423 }
424 
425 
426 //-------------------------------------------------
427 //  write_bus16 - Write 16-bit data to the PowerBus
428 //-------------------------------------------------
429 
write_bus16(offs_t offset,uint16_t data)430 void m2_bda_device::write_bus16(offs_t offset, uint16_t data)
431 {
432 	assert(offset >= RAM_BASE && offset <= RAM_BASE + m_ram_mask);
433 
434 	offset &= m_ram_mask;
435 	uint8_t *ptr = reinterpret_cast<uint8_t *>(&m_ram[0]) + WORD2_XOR_BE(offset);
436 	*reinterpret_cast<uint16_t *>(ptr) = data;
437 }
438 
439 
440 //-------------------------------------------------
441 //  write_bus32 - Write 32-bit data to the PowerBus
442 //-------------------------------------------------
443 
write_bus32(offs_t offset,uint32_t data)444 void m2_bda_device::write_bus32(offs_t offset, uint32_t data)
445 {
446 	assert(offset >= RAM_BASE && offset <= RAM_BASE + m_ram_mask);
447 
448 	offset &= m_ram_mask;
449 	uint8_t *ptr = reinterpret_cast<uint8_t *>(&m_ram[0]) + DWORD_XOR_BE(offset);
450 	*reinterpret_cast<uint32_t *>(ptr) = data;
451 }
452 
453 
454 
455 /***************************************************************************
456     PRIVATE FUNCTIONS
457 ***************************************************************************/
458 
459 //-------------------------------------------------
460 //  configure_ppc_address_map -
461 //-------------------------------------------------
462 
configure_ppc_address_map(address_space & space)463 void m2_bda_device::configure_ppc_address_map(address_space &space)
464 {
465 	// Install shared RAM
466 	space.install_ram(RAM_BASE, RAM_BASE + m_ram_mask, m_ram);
467 
468 	// Install TE texture RAM window
469 	space.install_ram(TE_TRAM_BASE, TE_TRAM_BASE + TE_TRAM_MASK, m_te->tram_ptr());
470 
471 	// Install BDA sub-devices
472 	space.install_readwrite_handler(POWERBUS_BASE,  POWERBUS_BASE + DEVICE_MASK,read32sm_delegate(*m_powerbus, FUNC(m2_powerbus_device::read)),    write32sm_delegate(*m_powerbus, FUNC(m2_powerbus_device::write)),    0xffffffffffffffffULL);
473 	space.install_readwrite_handler(MEMCTL_BASE,    MEMCTL_BASE + DEVICE_MASK,  read32s_delegate(*m_memctl,    FUNC(m2_memctl_device::read)),      write32s_delegate(*m_memctl,    FUNC(m2_memctl_device::write)),      0xffffffffffffffffULL);
474 	space.install_readwrite_handler(VDU_BASE,       VDU_BASE + DEVICE_MASK,     read32s_delegate(*m_vdu,       FUNC(m2_vdu_device::read)),         write32s_delegate(*m_vdu,       FUNC(m2_vdu_device::write)),         0xffffffffffffffffULL);
475 	space.install_readwrite_handler(TE_BASE,        TE_BASE + DEVICE_MASK,      read32sm_delegate(*m_te,       FUNC(m2_te_device::read)),          write32sm_delegate(*m_te,       FUNC(m2_te_device::write)),          0xffffffffffffffffULL);
476 	space.install_readwrite_handler(DSP_BASE,       DSP_BASE + DEVICE_MASK,     read32sm_delegate(*m_dspp,     FUNC(dspp_device::read)),           write32sm_delegate(*m_dspp,     FUNC(dspp_device::write)),           0xffffffffffffffffULL);
477 	space.install_readwrite_handler(CTRLPORT_BASE,  CTRLPORT_BASE + DEVICE_MASK,read32sm_delegate(*m_ctrlport, FUNC(m2_ctrlport_device::read)),    write32sm_delegate(*m_ctrlport, FUNC(m2_ctrlport_device::write)),    0xffffffffffffffffULL);
478 	space.install_readwrite_handler(MPEG_BASE,      MPEG_BASE + DEVICE_MASK,    read32sm_delegate(*m_mpeg,     FUNC(m2_mpeg_device::read)),        write32sm_delegate(*m_mpeg,     FUNC(m2_mpeg_device::write)),        0xffffffffffffffffULL);
479 
480 	space.install_readwrite_handler(CPUID_BASE,     CPUID_BASE + DEVICE_MASK,   read32mo_delegate(*this,       FUNC(m2_bda_device::cpu_id_r)),     write32mo_delegate(*this,       FUNC(m2_bda_device::cpu_id_w)),      0xffffffffffffffffULL);
481 
482 	space.install_readwrite_handler(SLOT4_BASE,     SLOT4_BASE + SLOT_MASK,     read32_delegate(*m_cde,        FUNC(m2_cde_device::read)),         write32_delegate(*m_cde,        FUNC(m2_cde_device::write)), 0xffffffffffffffffULL);
483 }
484 
485 
486 
487 //**************************************************************************
488 //  POWERBUS DEVICE
489 //**************************************************************************
490 
491 
492 //-------------------------------------------------
493 //  m2_powerbus_device - constructor
494 //-------------------------------------------------
495 
m2_powerbus_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)496 m2_powerbus_device::m2_powerbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
497 	device_t(mconfig, M2_POWERBUS, tag, owner, clock),
498 	m_int_handler(*this)
499 {
500 
501 }
502 
503 
504 //-------------------------------------------------
505 //  device_start - device-specific startup
506 //-------------------------------------------------
507 
device_start()508 void m2_powerbus_device::device_start()
509 {
510 	// Resolve callbacks
511 	m_int_handler.resolve();
512 
513 	// Register state for saving
514 	save_item(NAME(m_ctrl));
515 	save_item(NAME(m_int_enable));
516 	save_item(NAME(m_int_status));
517 	save_item(NAME(m_err_status));
518 	save_item(NAME(m_err_address));
519 }
520 
521 
522 //-------------------------------------------------
523 //  device_reset - device-specific reset
524 //-------------------------------------------------
525 
device_reset()526 void m2_powerbus_device::device_reset()
527 {
528 	m_ctrl = 0;
529 	m_int_enable = 0;
530 	m_int_status = 0;
531 	m_err_status = 0;
532 	m_err_address = 0;
533 }
534 
535 
536 /***************************************************************************
537     PUBLIC FUNCTIONS
538 ***************************************************************************/
539 
540 //-------------------------------------------------
541 //  read -
542 //-------------------------------------------------
543 
read(offs_t offset)544 uint32_t m2_powerbus_device::read(offs_t offset)
545 {
546 	const uint32_t byte_offs = offset << 2;
547 	uint32_t data = 0;
548 
549 	switch (byte_offs)
550 	{
551 		case BDAPCTL_PBINTENSET:
552 		{
553 			data = m_int_enable;
554 			break;
555 		}
556 		case BDAPCTL_PBINTSTAT:
557 		{
558 			data = m_int_status;
559 			break;
560 		}
561 		default:
562 			logerror("%s: POWERBUS R: [%x] %x\n", machine().describe_context(), byte_offs, data);
563 	}
564 
565 	return data;
566 }
567 
568 
569 //-------------------------------------------------
570 //  write -
571 //-------------------------------------------------
572 
write(offs_t offset,uint32_t data)573 void m2_powerbus_device::write(offs_t offset, uint32_t data)
574 {
575 	uint32_t byte_offs = offset << 2;
576 
577 	switch (byte_offs & ~0x400)
578 	{
579 		case BDAPCTL_PBINTENSET:
580 		{
581 			write_m2_reg(m_int_enable, data, byte_offs & 0x400 ? REG_CLEAR : REG_SET);
582 			update_interrupts();
583 			break;
584 		}
585 		case BDAPCTL_ERRSTAT:
586 		{
587 #if 1 // TODO
588 			if (byte_offs & 0x400)
589 			{
590 				write_m2_reg(m_int_status, data, REG_CLEAR);
591 			}
592 			else
593 			{
594 				if (data == 1)
595 					write_m2_reg(m_int_status, data, REG_SET);
596 			}
597 			update_interrupts();
598 #endif
599 			break;
600 		}
601 		default:
602 			logerror("%s: POWERBUS W: [%x] %x (PC:%x)\n", machine().describe_context(), byte_offs, data);
603 	}
604 }
605 
606 
607 /***************************************************************************
608     PRIVATE FUNCTIONS
609 ***************************************************************************/
610 
611 //-------------------------------------------------
612 //  update_interrupts -
613 //-------------------------------------------------
614 
update_interrupts()615 void m2_powerbus_device::update_interrupts()
616 {
617 	m_int_handler(m_int_status & m_int_enable ? ASSERT_LINE : CLEAR_LINE);
618 }
619 
620 
621 
622 //**************************************************************************
623 //  MEMORY CONTROLLER DEVICE
624 //**************************************************************************
625 
626 
627 //-------------------------------------------------
628 //  m2_memctl_device - constructor
629 //-------------------------------------------------
630 
m2_memctl_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)631 m2_memctl_device::m2_memctl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
632 	: device_t(mconfig, M2_MEMCTL, tag, owner, clock),
633 		m_gpio_in(*this),
634 		m_gpio_out(*this)
635 {
636 }
637 
638 
639 //-------------------------------------------------
640 //  device_start - device-specific startup
641 //-------------------------------------------------
642 
device_start()643 void m2_memctl_device::device_start()
644 {
645 	// Resolve our callbacks
646 	m_gpio_in.resolve_all_safe(0);
647 	m_gpio_out.resolve_all_safe();
648 
649 	// TODO: DELETE ME
650 	m2_bda_device *m_bda = (m2_bda_device*)owner(); // TEMP
651 
652 	// Configure the memory configuration register
653 	uint32_t bank1 = m_bda->get_rambank_size(0);
654 	uint32_t bank2 = m_bda->get_rambank_size(1);
655 
656 	m_mcfg = (ramsize_to_mcfg_field(bank2) << MCFG_SS1_SHIFT) | (ramsize_to_mcfg_field(bank1) << MCFG_SS0_SHIFT);
657 
658 	// Register state for saving
659 	save_item(NAME(m_mcfg));
660 	save_item(NAME(m_mref));
661 	save_item(NAME(m_mcntl));
662 	save_item(NAME(m_reset));
663 }
664 
665 
666 //-------------------------------------------------
667 //  device_reset - device-specific reset
668 //-------------------------------------------------
669 
device_reset()670 void m2_memctl_device::device_reset()
671 {
672 	// TODO: Need postload to set GPIO also?
673 	m_mref = 0;
674 }
675 
676 
677 /***************************************************************************
678     PUBLIC FUNCTIONS
679 ***************************************************************************/
680 
681 //-------------------------------------------------
682 //  read -
683 //-------------------------------------------------
684 
read(offs_t offset,uint32_t mem_mask)685 uint32_t m2_memctl_device::read(offs_t offset, uint32_t mem_mask)
686 {
687 	uint32_t byte_offs = offset << 2;
688 	uint32_t data = 0;
689 
690 	switch (byte_offs)
691 	{
692 		case MCTL_MCONFIG:
693 		{
694 			data = m_mcfg;
695 			break;
696 		}
697 		case MCTL_MREF:
698 		{
699 			if ((m_mref & MREF_GPIO0_GP) && !(m_mref & MREF_GPIO0_OUT))
700 			{
701 				if (m_gpio_in[0]())
702 					m_mref |= MREF_GPIO0_VALUE;
703 				else
704 					m_mref &= ~MREF_GPIO0_VALUE;
705 			}
706 
707 			if ((m_mref & MREF_GPIO1_GP) && !(m_mref & MREF_GPIO1_OUT))
708 			{
709 				if (m_gpio_in[1]())
710 					m_mref |= MREF_GPIO1_VALUE;
711 				else
712 					m_mref &= ~MREF_GPIO1_VALUE;
713 			}
714 
715 			if ((m_mref & MREF_GPIO2_GP) && !(m_mref & MREF_GPIO2_OUT))
716 			{
717 				if (m_gpio_in[2]())
718 					m_mref |= MREF_GPIO2_VALUE;
719 				else
720 					m_mref &= ~MREF_GPIO2_VALUE;
721 			}
722 
723 			if ((m_mref & MREF_GPIO3_GP) && !(m_mref & MREF_GPIO3_OUT))
724 			{
725 				if (m_gpio_in[3]())
726 					m_mref |= MREF_GPIO3_VALUE;
727 				else
728 					m_mref &= ~MREF_GPIO3_VALUE;
729 			}
730 
731 			data = m_mref;
732 			break;
733 		}
734 		case MCTL_MCNTL:
735 		case MCTL_MRESET:
736 			//logerror("%s: MEMCTL READ: %x %x\n", machine().describe_context(), byte_offs, mem_mask);
737 			break;
738 	}
739 
740 	return data;
741 }
742 
743 
744 //-------------------------------------------------
745 //  write -
746 //-------------------------------------------------
747 
write(offs_t offset,uint32_t data,uint32_t mem_mask)748 void m2_memctl_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
749 {
750 	uint32_t byte_offs = offset << 2;
751 
752 	switch (byte_offs)
753 	{
754 		case MCTL_MCONFIG:
755 		{
756 			m_mcfg = data;
757 			break;
758 		}
759 		case MCTL_MREF:
760 		{
761 			// Set any general purpose outputs
762 			if (data & (MREF_GPIO0_GP | MREF_GPIO0_OUT))
763 				m_gpio_out[0](data & MREF_GPIO0_VALUE ? 1 : 0);
764 
765 			if (data & (MREF_GPIO1_GP | MREF_GPIO1_OUT))
766 				m_gpio_out[1](data & MREF_GPIO1_VALUE ? 1 : 0);
767 
768 			if (data & (MREF_GPIO2_GP | MREF_GPIO2_OUT))
769 				m_gpio_out[2](data & MREF_GPIO2_VALUE ? 1 : 0);
770 
771 			if (data & (MREF_GPIO3_GP | MREF_GPIO3_OUT))
772 				m_gpio_out[3](data & MREF_GPIO3_VALUE ? 1 : 0);
773 
774 			m_mref = data;
775 			break;
776 		}
777 		case MCTL_MCNTL:
778 		case MCTL_MRESET:
779 			//logerror("%s: MEMCTL WRITE: %x %x %x\n", machine().describe_context(), data, byte_offs);
780 			break;
781 	}
782 }
783 
784 
785 
786 //**************************************************************************
787 //  VDU DEVICE
788 //**************************************************************************
789 
790 
791 //-------------------------------------------------
792 //  m2_vdu_device - constructor
793 //-------------------------------------------------
794 
m2_vdu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)795 m2_vdu_device::m2_vdu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
796 	: device_t(mconfig, M2_VDU, tag, owner, clock),
797 	m_screen(*this, finder_base::DUMMY_TAG),
798 	m_vint0_int_handler(*this),
799 	m_vint1_int_handler(*this)
800 {
801 
802 }
803 
804 
805 //-------------------------------------------------
806 //  device_start - device-specific startup
807 //-------------------------------------------------
808 
device_start()809 void m2_vdu_device::device_start()
810 {
811 	// Resolve callbacks
812 	m_vint0_int_handler.resolve_safe();
813 	m_vint1_int_handler.resolve_safe();
814 
815 	// Initialize line interrupt timers
816 	m_vint0_timer = timer_alloc(TIMER_ID_VINT0);
817 	m_vint1_timer = timer_alloc(TIMER_ID_VINT1);
818 
819 	// Calculate H/V count bias values (1 = start of blanking)
820 	const rectangle visarea = m_screen->visible_area();
821 
822 	m_hstart = visarea.min_x;
823 	m_htotal = visarea.max_x + 1;
824 
825 	m_vstart = visarea.min_y;
826 	m_vtotal = visarea.max_y + 1;
827 
828 	// Register state for saving
829 	save_item(NAME(m_vint));
830 	save_item(NAME(m_vdc0));
831 	save_item(NAME(m_vdc1));
832 	save_item(NAME(m_fv0a));
833 	save_item(NAME(m_fv1a));
834 	save_item(NAME(m_avdi));
835 	save_item(NAME(m_vdli));
836 	save_item(NAME(m_vcfg));
837 	save_item(NAME(m_dmt0));
838 	save_item(NAME(m_dmt1));
839 	save_item(NAME(m_vrst));
840 }
841 
842 
843 //-------------------------------------------------
844 //  device_reset - device-specific reset
845 //-------------------------------------------------
846 
device_reset()847 void m2_vdu_device::device_reset()
848 {
849 	m_fv0a = 0;
850 	m_fv1a = 0;
851 	m_avdi = 0;
852 	m_vdli = 0;
853 	m_vint = 0;
854 	m_vcfg = 0;
855 	m_dmt0 = 0;
856 	m_dmt1 = 0;
857 
858 	m_vint0_timer->adjust(attotime::never);
859 	m_vint1_timer->adjust(attotime::never);
860 }
861 
862 
863 //-------------------------------------------------
864 //  device_timer - device-specific timers
865 //-------------------------------------------------
866 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)867 void m2_vdu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
868 {
869 	switch (id)
870 	{
871 		case TIMER_ID_VINT0:
872 		{
873 			m_vint |= VDU_VINT_VINT0;
874 			m_vint0_int_handler(ASSERT_LINE);
875 			set_vint_timer(0);
876 			break;
877 		}
878 		case TIMER_ID_VINT1:
879 		{
880 			m_vint |= VDU_VINT_VINT1;
881 			m_vint1_int_handler(ASSERT_LINE);
882 			set_vint_timer(1);
883 			break;
884 		}
885 	}
886 }
887 
888 
889 
890 /***************************************************************************
891     PUBLIC FUNCTIONS
892 ***************************************************************************/
893 
894 //-------------------------------------------------
895 //  read -
896 //-------------------------------------------------
897 
read(offs_t offset,uint32_t mem_mask)898 uint32_t m2_vdu_device::read(offs_t offset, uint32_t mem_mask)
899 {
900 	uint32_t byte_offs = offset << 2;
901 	uint32_t data = 0;
902 
903 	switch (byte_offs)
904 	{
905 		case VDU_VLOC:
906 		{
907 			// TODO: Check me
908 			uint32_t mpos = m_screen->vpos();
909 			uint32_t vpos = ((mpos + m_vstart) % m_vtotal) + 1;
910 			data = vpos << VDU_VLOC_VCOUNT_SHIFT;
911 			break;
912 		}
913 		case VDU_VINT:
914 		{
915 			data = m_vint;
916 			break;
917 		}
918 		case VDU_VDC0:
919 		case VDU_VDC1:
920 		case VDU_FV0A:
921 		case VDU_FV1A:
922 		case VDU_AVDI:
923 		case VDU_VDLI:
924 		case VDU_VCFG:
925 		case VDU_DMT0:
926 		case VDU_DMT1:
927 		case VDU_LFSR:
928 		{
929 			//logerror("%s: VDU READ: %x %x\n", machine().describe_context(), byte_offs, mem_mask);
930 			break;
931 		}
932 	}
933 
934 	return data;
935 }
936 
937 
938 //-------------------------------------------------
939 //  write -
940 //-------------------------------------------------
941 
write(offs_t offset,uint32_t data,uint32_t mem_mask)942 void m2_vdu_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
943 {
944 	uint32_t byte_offs = offset << 2;
945 	m2_reg_wmode wmode = byte_offs & 0x400 ? REG_CLEAR : REG_WRITE;
946 
947 //  logerror("%s: VDU WRITE: %03x %08x %x\n", machine().describe_context(), byte_offs, data, mem_mask);
948 	byte_offs &= ~0x400;
949 	switch (byte_offs)
950 	{
951 		case VDU_VINT:
952 		{
953 			uint32_t old = m_vint;
954 			write_m2_reg(m_vint, data, wmode);
955 
956 			// Update line interrupts if changed
957 			if ((m_vint & VDU_VINT_VLINE0_MASK) != (old & VDU_VINT_VLINE0_MASK))
958 				set_vint_timer(0);
959 
960 			if ((m_vint & VDU_VINT_VLINE1_MASK) != (old & VDU_VINT_VLINE1_MASK))
961 				set_vint_timer(1);
962 
963 			// Clear interrupt bits
964 			if ((old & VDU_VINT_VINT0) && !(m_vint & VDU_VINT_VINT0))
965 				m_vint0_int_handler(CLEAR_LINE);
966 
967 			if ((old & VDU_VINT_VINT1) && !(m_vint & VDU_VINT_VINT1))
968 				m_vint1_int_handler(CLEAR_LINE);
969 
970 			break;
971 		}
972 		case VDU_FV0A:
973 		{
974 			m_fv0a = data;
975 			break;
976 		}
977 		case VDU_FV1A:
978 		{
979 			m_fv1a = data;
980 			break;
981 		}
982 		case VDU_VCFG:
983 		{
984 			m_vcfg = data;
985 			break;
986 		}
987 		case VDU_VRST:
988 		{
989 			m_vrst = data;
990 			break;
991 		}
992 		default:
993 		{
994 			logerror("%s: VDU WRITE: %x %x %x\n", machine().describe_context(), byte_offs, data, mem_mask);
995 			break;
996 		}
997 	}
998 }
999 
1000 
1001 //-------------------------------------------------
1002 //  parse_dc_word -
1003 //-------------------------------------------------
1004 
parse_dc_word(uint32_t cmd)1005 void m2_vdu_device::parse_dc_word(uint32_t cmd)
1006 {
1007 	// Determine the control register
1008 	uint32_t &vdc = cmd & VDL_DC_1 ? m_vdc1 : m_vdc0;
1009 
1010 	// Horizontal interpolation
1011 	uint32_t hint = (cmd & VDL_DC_HINTCTL_MASK) >> VDL_DC_HINTCTL_SHIFT;
1012 
1013 	if (hint == VDL_CTL_ENABLE)
1014 		vdc |= VDU_VDC_HINT;
1015 	else if (hint == VDL_CTL_DISABLE)
1016 		vdc &= ~VDU_VDC_HINT;
1017 
1018 
1019 	// Vertical interpolation
1020 	uint32_t vint = (cmd & VDL_DC_VINTCTL_MASK) >> VDL_DC_VINTCTL_SHIFT;
1021 
1022 	if (vint == VDL_CTL_ENABLE)
1023 		vdc |= VDU_VDC_VINT;
1024 	else if (vint == VDL_CTL_DISABLE)
1025 		vdc &= ~VDU_VDC_VINT;
1026 
1027 
1028 	// Dithering
1029 	uint32_t dith = (cmd & VDL_DC_DITHERCTL_MASK) >> VDL_DC_DITHERCTL_SHIFT;
1030 
1031 	if (dith == VDL_CTL_ENABLE)
1032 		vdc |= VDU_VDC_DITHER;
1033 	else if (dith == VDL_CTL_DISABLE)
1034 		vdc &= ~VDU_VDC_DITHER;
1035 
1036 
1037 	// MTXBYP (?)
1038 	uint32_t mtxbyp = (cmd & VDL_DC_MTXBYPCTL_MASK) >> VDL_DC_MTXBYPCTL_SHIFT;
1039 
1040 	if (mtxbyp == VDL_CTL_ENABLE)
1041 		vdc |= VDU_VDC_MTXBYP;
1042 	else if (mtxbyp == VDL_CTL_DISABLE)
1043 		vdc &= ~VDU_VDC_MTXBYP;
1044 }
1045 
1046 
1047 //-------------------------------------------------
1048 //  parse_av_word -
1049 //-------------------------------------------------
1050 
parse_av_word(uint32_t cmd)1051 void m2_vdu_device::parse_av_word(uint32_t cmd)
1052 {
1053 	if (cmd & VDL_AV_LD_HSTART)
1054 	{
1055 		uint32_t hstart = (cmd & VDL_AV_HSTART_MASK) >> VDL_AV_HSTART_SHIFT;
1056 		m_avdi &= ~VDU_AVDI_HSTART_MASK;
1057 		m_avdi |= hstart << VDU_AVDI_HSTART_SHIFT;
1058 	}
1059 	if (cmd & VDL_AV_LD_HWIDTH)
1060 	{
1061 		uint32_t hwidth = (cmd & VDL_AV_HWIDTH_MASK) >> VDL_AV_HWIDTH_SHIFT;
1062 		m_avdi &= ~VDU_AVDI_HWIDTH_MASK;
1063 		m_avdi |= hwidth << VDU_AVDI_HWIDTH_SHIFT;
1064 	}
1065 	if (cmd & VDL_AV_LD_HDOUBLE)
1066 	{
1067 		if (cmd & VDL_AV_HDOUBLE)
1068 			m_avdi |= VDU_AVDI_HDOUBLE;
1069 		else
1070 			m_avdi &= ~VDU_AVDI_HDOUBLE;
1071 	}
1072 	if (cmd & VDL_AV_LD_VDOUBLE)
1073 	{
1074 		if (cmd & VDL_AV_VDOUBLE)
1075 			m_avdi |= VDU_AVDI_VDOUBLE;
1076 		else
1077 			m_avdi &= ~VDU_AVDI_VDOUBLE;
1078 	}
1079 }
1080 
1081 
1082 //-------------------------------------------------
1083 //  parse_lc_word -
1084 //-------------------------------------------------
1085 
parse_lc_word(uint32_t cmd)1086 void m2_vdu_device::parse_lc_word(uint32_t cmd)
1087 {
1088 	// TODO: This may not be used
1089 	if (cmd & VDL_LC_LD_BYPASSTYPE)
1090 	{
1091 		m_vdli &= ~VDU_VDLI_BYPASSTYPE;
1092 		m_vdli |= (cmd & VDU_VDLI_BYPASSTYPE) == VDU_VDLI_BYPASSTYPE_MSB ? VDU_VDLI_BYPASSTYPE_MSB : VDU_VDLI_BYPASSTYPE_LSB;
1093 	}
1094 	if (cmd & VDL_LC_LD_FBFORMAT)
1095 	{
1096 		m_vdli &= ~VDU_VDLI_FBFORMAT;
1097 		m_vdli |= (cmd & VDL_LC_FBFORMAT) == VDL_LC_FBFORMAT_32 ? VDU_VDLI_FBFORMAT_32 : VDU_VDLI_FBFORMAT_16;
1098 	}
1099 
1100 	// Seems these two are always set by the command word
1101 	if (cmd & VDL_LC_RANDOMDITHER)
1102 		m_vdli |= VDU_VDLI_RANDOMDITHER;
1103 	else
1104 		m_vdli &= ~VDU_VDLI_RANDOMDITHER;
1105 
1106 	if (cmd & VDL_LC_ONEVINTDIS)
1107 		m_vdli |= VDU_VDLI_ONEVINTDIS;
1108 	else
1109 		m_vdli &= ~VDU_VDLI_ONEVINTDIS;
1110 }
1111 
1112 
1113 //-------------------------------------------------
1114 //  draw_scanline - Draw a scanline
1115 //-------------------------------------------------
1116 
draw_scanline(uint32_t * dst,uint32_t srclower,uint32_t srcupper)1117 void m2_vdu_device::draw_scanline(uint32_t *dst, uint32_t srclower, uint32_t srcupper)
1118 {
1119 	m2_bda_device *m_bda = (m2_bda_device*)owner(); // TEMP
1120 
1121 	uint32_t hs = (m_avdi & VDU_AVDI_HSTART_MASK) >> VDU_AVDI_HSTART_SHIFT;
1122 	uint32_t hw = (m_avdi & VDU_AVDI_HWIDTH_MASK) >> VDU_AVDI_HWIDTH_SHIFT;
1123 
1124 	bool is32bpp = m_vdli & VDU_VDLI_FBFORMAT_32 ? true : false;
1125 //  bool bypassmsb = m_vdli & VDU_VDLI_BYPASSTYPE_MSB ? true : false;
1126 //  bool randomdith = m_vdli & VDU_VDLI_RANDOMDITHER ? true : false;
1127 
1128 	uint32_t h = 0;
1129 
1130 	// Left border
1131 	while (h < hs)
1132 	{
1133 		*dst++ = rgb_t::black();
1134 		++h;
1135 	}
1136 
1137 	// Active video area
1138 	uint32_t vismax = std::min<uint32_t>(h + hw, m_htotal);
1139 
1140 	if (is32bpp)
1141 	{
1142 		while (h < vismax)
1143 		{
1144 			*dst++ = m_bda->read_bus32(srclower);
1145 			srclower += 4;
1146 			++h;
1147 		}
1148 	}
1149 	else
1150 	{
1151 		while (h < vismax)
1152 		{
1153 			uint16_t srcdata = m_bda->read_bus16(srclower);
1154 			*dst++ = pal555(srcdata, 10, 5, 0);
1155 			srclower += 2;
1156 			++h;
1157 		}
1158 	}
1159 
1160 	// Right border
1161 	while (h < m_htotal)
1162 	{
1163 		*dst++ = rgb_t::black();
1164 		++h;
1165 	}
1166 }
1167 
1168 
1169 //-------------------------------------------------
1170 //  draw_scanline_double - Draw a pixel-doubled scanline
1171 //-------------------------------------------------
1172 
draw_scanline_double(uint32_t * dst,uint32_t srclower,uint32_t srcupper)1173 void m2_vdu_device::draw_scanline_double(uint32_t *dst, uint32_t srclower, uint32_t srcupper)
1174 {
1175 	m2_bda_device *m_bda = (m2_bda_device*)owner(); // TEMP
1176 
1177 	uint32_t hs = (m_avdi & VDU_AVDI_HSTART_MASK) >> VDU_AVDI_HSTART_SHIFT;
1178 	uint32_t hw = (m_avdi & VDU_AVDI_HWIDTH_MASK) >> VDU_AVDI_HWIDTH_SHIFT;
1179 
1180 	bool is32bpp = m_vdli & VDU_VDLI_FBFORMAT_32 ? true : false;
1181 //  bool bypassmsb = m_vdli & VDU_VDLI_BYPASSTYPE_MSB ? true : false;
1182 //  bool randomdith = m_vdli & VDU_VDLI_RANDOMDITHER ? true : false;
1183 
1184 	uint32_t h = 0;
1185 
1186 	// Left border
1187 	while (h < hs)
1188 	{
1189 		*dst++ = rgb_t::black();
1190 		++h;
1191 	}
1192 
1193 	// Active video area
1194 	uint32_t vismax = std::min<uint32_t>(h + hw, m_htotal);
1195 
1196 	if (is32bpp)
1197 	{
1198 		while (h < vismax)
1199 		{
1200 			uint32_t srcdata = m_bda->read_bus32(srclower);
1201 
1202 			srclower += 4;
1203 			*dst++ = srcdata;
1204 			*dst++ = srcdata;
1205 			++h;
1206 		}
1207 	}
1208 	else
1209 	{
1210 		while (h < vismax)
1211 		{
1212 			uint32_t srcdata = m_bda->read_bus16(srclower);
1213 			srcdata = pal555(srcdata, 10, 5, 0);
1214 
1215 			srclower += 2;
1216 			*dst++ = srcdata;
1217 			*dst++ = srcdata;
1218 			++h;
1219 		}
1220 	}
1221 
1222 	// Right border
1223 	while (h < m_htotal)
1224 	{
1225 		*dst++ = rgb_t::black();
1226 		++h;
1227 	}
1228 }
1229 
1230 
1231 //-------------------------------------------------
1232 //  core_update_screen -
1233 //-------------------------------------------------
1234 
1235 
1236 
1237 //-------------------------------------------------
1238 //  screen_update -
1239 //-------------------------------------------------
1240 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)1241 uint32_t m2_vdu_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
1242 {
1243 	m2_bda_device *m_bda = (m2_bda_device*)owner(); // TEMP
1244 
1245 	// TODO: Interlace mode
1246 	uint32_t addr = m_fv0a;//screen.frame_number() & 1 ? m_fv1a : m_fv0a;
1247 
1248 	// Fill entire screen with black if disabled
1249 	if ((m_vrst & (VDU_VRST_VIDRESET | VDU_VRST_DVERESET)) || addr == 0)
1250 	{
1251 		bitmap.fill(rgb_t::black());
1252 		return 0;
1253 	}
1254 
1255 	// Processing begins at VSYNC
1256 	uint32_t v = 0;
1257 
1258 	// Process VDLs until all lines are exhausted
1259 	while (v < m_vtotal)
1260 	{
1261 		// Fetch the 4 header words
1262 		uint32_t dmactl = m_bda->read_bus32(addr);
1263 		uint32_t lower = m_bda->read_bus32(addr + 4);
1264 		uint32_t upper = m_bda->read_bus32(addr + 8);
1265 		uint32_t next = m_bda->read_bus32(addr + 12);
1266 
1267 		addr += 16;
1268 
1269 		// Word count includes the header
1270 		uint32_t words = (dmactl & VDL_DMA_NWORDS_MASK) >> VDL_DMA_NWORDS_SHIFT;
1271 		words -= 4;
1272 
1273 		// Check and adjust the line count
1274 		uint32_t lines = (dmactl & VDL_DMA_NLINES_MASK) >> VDL_DMA_NLINES_SHIFT;
1275 
1276 		if (lines > 0)
1277 		{
1278 			uint32_t vend = v + lines;
1279 
1280 			if (vend > m_vtotal)
1281 				lines = vend - m_vtotal;
1282 		}
1283 		else
1284 		{
1285 			// A zero count denotes all of the remaining screen lines
1286 			lines = m_vtotal - v;
1287 		}
1288 
1289 		// Parse the command list and update video registers accordingly
1290 		while (words-- > 0)
1291 		{
1292 			uint32_t cmd = m_bda->read_bus32(addr);
1293 			addr += 4;
1294 
1295 			switch (cmd & 0xe0000000)
1296 			{
1297 				case VDL_DC:
1298 				{
1299 					parse_dc_word(cmd);
1300 					break;
1301 				}
1302 				case VDL_AV:
1303 				{
1304 					parse_av_word(cmd);
1305 					break;
1306 				}
1307 				case VDL_LC:
1308 				{
1309 					parse_lc_word(cmd);
1310 					break;
1311 				}
1312 				default:
1313 				{
1314 					if (cmd != VDL_NOP)
1315 						fatalerror("VDU: Unknown VDL command word\n");
1316 					break;
1317 				}
1318 			}
1319 		}
1320 
1321 		// DMA from RAM to the display
1322 		if (dmactl & VDL_DMA_ENABLE)
1323 		{
1324 			bool hdouble = m_avdi & VDU_AVDI_HDOUBLE ? true : false;
1325 			bool vdouble = m_avdi & VDU_AVDI_VDOUBLE ? true : false;
1326 //          bool onevintdis = m_vdli & VDU_VDLI_ONEVINTDIS ? true : false;
1327 
1328 			uint32_t srclower = lower;
1329 			uint32_t srcupper = upper;
1330 			uint32_t mod = ((dmactl & VDL_DMA_MOD_MASK) >> VDL_DMA_MOD_SHIFT) << 5;
1331 
1332 			// Draw these lines
1333 			while (lines--)
1334 			{
1335 				// Line doubling is easily handled
1336 				for (uint32_t ys = vdouble ? 2 : 1; ys > 0; --ys)
1337 				{
1338 					if (hdouble)
1339 						draw_scanline_double(&bitmap.pix(v, 0), srclower, srcupper);
1340 					else
1341 						draw_scanline(&bitmap.pix(v, 0), srclower, srcupper);
1342 
1343 					++v;
1344 				}
1345 				// Update the source addresses
1346 				srclower += mod;
1347 				srcupper += mod;
1348 			}
1349 		}
1350 		else
1351 		{
1352 			// Blank this block of lines if DMA is disabled
1353 			while (lines--)
1354 			{
1355 				uint32_t *dst = &bitmap.pix(v, cliprect.min_x);
1356 
1357 				for (uint32_t x = cliprect.min_x; x <= cliprect.max_x; ++x)
1358 					*dst++ = rgb_t::black();
1359 
1360 				++v;
1361 			}
1362 		}
1363 
1364 		// Jump to the next VDL
1365 		addr = next;
1366 	}
1367 
1368 	return 0;
1369 }
1370 
1371 
1372 //-------------------------------------------------
1373 //  set_vint_timer -
1374 //-------------------------------------------------
1375 
set_vint_timer(uint32_t id)1376 void m2_vdu_device::set_vint_timer(uint32_t id)
1377 {
1378 	uint32_t v;
1379 	emu_timer *timer = (id == 0) ? m_vint0_timer : m_vint1_timer;
1380 
1381 	if (id == 0)
1382 		v = (m_vint & VDU_VINT_VLINE0_MASK) >> VDU_VINT_VLINE0_SHIFT;
1383 	else
1384 		v = (m_vint & VDU_VINT_VLINE1_MASK) >> VDU_VINT_VLINE1_SHIFT;
1385 
1386 	if (v == 0)
1387 	{
1388 		// Apparently 0 is invalid
1389 		timer->adjust(attotime::never);
1390 	}
1391 	else
1392 	{
1393 		// Adjust the count to what the core expects
1394 		uint32_t vadj = (v - 1 + (m_vtotal - m_vstart)) % m_vtotal;
1395 		timer->adjust(m_screen->time_until_pos(vadj));
1396 	}
1397 }
1398 
1399 
1400 
1401 //**************************************************************************
1402 //  CONTROL PORTS DEVICE
1403 //**************************************************************************
1404 
1405 //-------------------------------------------------
1406 //  m2_ctrlport_device - constructor
1407 //-------------------------------------------------
1408 
m2_ctrlport_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1409 m2_ctrlport_device::m2_ctrlport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1410 	: device_t(mconfig, M2_CTRLPORT, tag, owner, clock)
1411 {
1412 
1413 }
1414 
1415 
1416 //-------------------------------------------------
1417 //  device_start - device-specific startup
1418 //-------------------------------------------------
1419 
device_start()1420 void m2_ctrlport_device::device_start()
1421 {
1422 
1423 }
1424 
1425 
1426 //-------------------------------------------------
1427 //  device_reset - device-specific reset
1428 //-------------------------------------------------
1429 
device_reset()1430 void m2_ctrlport_device::device_reset()
1431 {
1432 
1433 }
1434 
1435 
1436 /***************************************************************************
1437     PUBLIC FUNCTIONS
1438 ***************************************************************************/
1439 
1440 //-------------------------------------------------
1441 //  read -
1442 //-------------------------------------------------
1443 
read(offs_t offset)1444 uint32_t m2_ctrlport_device::read(offs_t offset)
1445 {
1446 	//const uint32_t byte_offs = offset << 2;
1447 	uint32_t data = machine().rand();
1448 
1449 	//switch (byte_offs)
1450 	//{
1451 		//default:
1452 			//logerror("%s: CTRLPORT R: [%x] %x\n", machine().describe_context(), byte_offs, data);
1453 	//}
1454 
1455 	return data;
1456 }
1457 
1458 
1459 //-------------------------------------------------
1460 //  write -
1461 //-------------------------------------------------
1462 
write(offs_t offset,uint32_t data)1463 void m2_ctrlport_device::write(offs_t offset, uint32_t data)
1464 {
1465 	//uint32_t byte_offs = offset << 2;
1466 
1467 	//switch (byte_offs)
1468 	//{
1469 		//default:
1470 			//logerror("%s: CTRLPORT W: [%x] %x\n", machine().describe_context(), byte_offs, data);
1471 	//}
1472 }
1473 
1474 
1475 /***************************************************************************
1476     PRIVATE FUNCTIONS
1477 ***************************************************************************/
1478 
1479 
1480 
1481 
1482 
1483 //**************************************************************************
1484 //  CDE DEVICE
1485 //**************************************************************************
1486 
1487 //-------------------------------------------------
1488 //  m2_cde_device - constructor
1489 //-------------------------------------------------
1490 
m2_cde_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1491 m2_cde_device::m2_cde_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1492 	: device_t(mconfig, M2_CDE, tag, owner, clock),
1493 	m_cpu1(*this, finder_base::DUMMY_TAG),
1494 	m_bda(*this, finder_base::DUMMY_TAG),
1495 	m_int_handler(*this),
1496 	m_sdbg_out_handler(*this)
1497 {
1498 }
1499 
1500 
1501 //-------------------------------------------------
1502 //  device_start - device-specific startup
1503 //-------------------------------------------------
1504 
device_start()1505 void m2_cde_device::device_start()
1506 {
1507 	// Resolve callbacks
1508 	m_int_handler.resolve_safe();
1509 	m_sdbg_out_handler.resolve_safe();
1510 
1511 	// Init DMA
1512 	m_dma[0].m_timer = timer_alloc(TIMER_ID_DMA1);
1513 	m_dma[1].m_timer = timer_alloc(TIMER_ID_DMA2);
1514 
1515 	// Register state for saving
1516 	save_item(NAME(m_sdbg_cntl));
1517 	save_item(NAME(m_int_status));
1518 	save_item(NAME(m_int_enable));
1519 	save_item(NAME(m_bblock_en));
1520 	save_item(NAME(m_visa_dis));
1521 
1522 	for (uint32_t i = 0; i < 8; ++i)
1523 	{
1524 		save_item(NAME(m_bio_device[i].m_setup), i);
1525 		save_item(NAME(m_bio_device[i].m_cycle_time), i);
1526 	}
1527 
1528 	for (uint32_t i = 0; i < 2; ++i)
1529 	{
1530 		save_item(NAME(m_dma[i].m_cntl), i);
1531 		save_item(NAME(m_dma[i].m_cbad), i);
1532 		save_item(NAME(m_dma[i].m_cpad), i);
1533 		save_item(NAME(m_dma[i].m_ccnt), i);
1534 		save_item(NAME(m_dma[i].m_nbad), i);
1535 		save_item(NAME(m_dma[i].m_npad), i);
1536 		save_item(NAME(m_dma[i].m_ncnt), i);
1537 		// timer
1538 	}
1539 }
1540 
1541 //-------------------------------------------------
1542 //  device_reset - device-specific reset
1543 //-------------------------------------------------
1544 
device_reset()1545 void m2_cde_device::device_reset()
1546 {
1547 	m_sdbg_cntl = 0;
1548 	m_int_status = 0;
1549 	m_int_enable = 0;
1550 
1551 	// TODO? Boot block is clear on reset
1552 	m_bblock_en = 1; // ?
1553 	m_visa_dis = 0;
1554 
1555 	reset_dma(0);
1556 	reset_dma(1);
1557 }
1558 
1559 
1560 //-------------------------------------------------
1561 //  device_post_load - device-specific post-load
1562 //-------------------------------------------------
1563 
device_post_load()1564 void m2_cde_device::device_post_load()
1565 {
1566 
1567 }
1568 
1569 
1570 //-------------------------------------------------
1571 //  device_timer - a timer
1572 //-------------------------------------------------
1573 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)1574 void m2_cde_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
1575 {
1576 	switch (id)
1577 	{
1578 		case TIMER_ID_READY:
1579 			// TODO ?
1580 			set_interrupt(CDE_ID_READY);
1581 			break;
1582 
1583 		case TIMER_ID_DMA1:
1584 			next_dma(0);
1585 			break;
1586 
1587 		case TIMER_ID_DMA2:
1588 			next_dma(1);
1589 			break;
1590 
1591 		default:
1592 			throw emu_fatalerror("m2_cde_device::device_timer: Unknown CDE timer ID");
1593 	}
1594 }
1595 
1596 
1597 //-------------------------------------------------
1598 //  set_interrupt -
1599 //-------------------------------------------------
1600 
set_interrupt(uint32_t intmask)1601 void m2_cde_device::set_interrupt(uint32_t intmask)
1602 {
1603 	m_int_status |= (uint32_t)intmask;
1604 	update_interrupts();
1605 }
1606 
1607 
1608 //-------------------------------------------------
1609 //  update_interrupts -
1610 //-------------------------------------------------
1611 
update_interrupts()1612 void m2_cde_device::update_interrupts()
1613 {
1614 	if (m_int_status & m_int_enable)
1615 		m_int_handler(ASSERT_LINE);
1616 	else
1617 		m_int_handler(CLEAR_LINE);
1618 }
1619 
1620 
1621 
1622 /***************************************************************************
1623     PUBLIC FUNCTIONS
1624 ***************************************************************************/
1625 
1626 //-------------------------------------------------
1627 //  read -
1628 //-------------------------------------------------
1629 
read(address_space & space,offs_t offset,uint32_t mem_mask)1630 uint32_t m2_cde_device::read(address_space &space, offs_t offset, uint32_t mem_mask)
1631 {
1632 	const uint32_t byte_offs = offset << 2;
1633 	uint32_t data = 0;
1634 
1635 	switch (byte_offs)
1636 	{
1637 		case CDE_DEVICE_ID:
1638 		{
1639 			data = 0x00010000;
1640 			break;
1641 		}
1642 		case CDE_VERSION:
1643 		{
1644 			data = 0; // TODO
1645 			break;
1646 		}
1647 		case CDE_SDBG_CNTL:
1648 		{
1649 			data = m_sdbg_cntl;
1650 			break;
1651 		}
1652 		case CDE_SDBG_RD:
1653 		{
1654 			data = m_sdbg_in;
1655 			break;
1656 		}
1657 		case CDE_INT_STS:
1658 		{
1659 			data = m_int_status;
1660 			break;
1661 		}
1662 		case CDE_CD_STS_RD:
1663 		{
1664 			data = 0x000; // Status ready = 0x100
1665 			break;
1666 		}
1667 		case CDE_INT_ENABLE:
1668 		{
1669 			data = m_int_enable;
1670 			break;
1671 		}
1672 		case CDE_DEV_DETECT:
1673 		{
1674 			data = 0x0; // ?
1675 			break;
1676 		};
1677 		case CDE_BBLOCK:
1678 		{
1679 			// 8, 80
1680 			data = 0x80; // Needs to be non-zero
1681 			break;
1682 		}
1683 		case CDE_UNIQ_ID_RD:
1684 		{
1685 			data = 0xffffffff; // ?
1686 			break;
1687 		}
1688 		case CDE_BBLOCK_EN:
1689 		{
1690 			data = m_bblock_en;
1691 			break;
1692 		}
1693 		case CDE_SYSTEM_CONF:
1694 		{
1695 			data = m_syscfg;
1696 			break;
1697 		}
1698 		case CDE_MICRO_STATUS:
1699 		{
1700 			data = 0x20; // TODO
1701 			break;
1702 		}
1703 		case CDE_MICRO_RWS:
1704 		{
1705 			break;
1706 		}
1707 		case CDE_VISA_DIS:
1708 		{
1709 			data = m_visa_dis;
1710 			break;
1711 		}
1712 		case CDE_DMA1_CNTL:
1713 		case CDE_DMA2_CNTL:
1714 		{
1715 			uint32_t ch = (byte_offs & 0x20) ? 1 : 0;
1716 			data = m_dma[ch].m_cntl;
1717 			break;
1718 		}
1719 		default:
1720 		{
1721 			//logerror("%s: CDE_R UNHANDLED: 0x%.8x 0x%.8x\n", machine().describe_context(), byte_offs, mem_mask));
1722 		}
1723 	}
1724 
1725 	return data;
1726 }
1727 
1728 
1729 //-------------------------------------------------
1730 //  write -
1731 //-------------------------------------------------
1732 
write(address_space & space,offs_t offset,uint32_t data,uint32_t mem_mask)1733 void m2_cde_device::write(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask)
1734 {
1735 	uint32_t byte_offs = offset << 2;
1736 	uint32_t dmach = byte_offs & 0x20 ? 1 : 0;
1737 
1738 	m2_reg_wmode wm_cw = byte_offs & 0x400 ? REG_CLEAR : REG_WRITE;
1739 	m2_reg_wmode wm_cs = byte_offs & 0x400 ? REG_CLEAR : REG_SET;
1740 
1741 	byte_offs &= ~0x400;
1742 
1743 	switch (byte_offs)
1744 	{
1745 		case CDE_SDBG_CNTL:
1746 		{
1747 			// ........ ........ xxxxxxxx xxxx....      Clock scaler (written with 33MHz/38400 = 868)
1748 			write_m2_reg(m_sdbg_cntl, data, wm_cw);
1749 			break;
1750 		}
1751 		case CDE_SDBG_WRT:
1752 		{
1753 			m_sdbg_out_handler(data);
1754 			set_interrupt(CDE_SDBG_WRT_DONE);
1755 			break;
1756 		}
1757 		case CDE_INT_STS:
1758 		{
1759 			write_m2_reg(m_int_status, data, wm_cw);
1760 			update_interrupts();
1761 			break;
1762 		}
1763 		case CDE_INT_ENABLE:
1764 		{
1765 			write_m2_reg(m_int_enable, data, wm_cs);
1766 			update_interrupts();
1767 			break;
1768 		}
1769 		case CDE_RESET_CNTL:
1770 		{
1771 			if (data & 1)
1772 			{
1773 				// TODO: Should we reset both CPUs?
1774 				downcast<cpu_device *>(&space.device())->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
1775 
1776 				// TODO: Is this correct?
1777 				m_bblock_en = 0;
1778 			}
1779 			else if (data & 2)
1780 			{
1781 				// TODO: Hard reset
1782 			}
1783 
1784 			break;
1785 		}
1786 		case CDE_CD_CMD_WRT:
1787 		{
1788 			//set_interrupt(CDE_CD_CMD_WRT_DONE); // ?
1789 			//set_interrupt(CDE_CD_STS_FL_DONE); // ?
1790 			break;
1791 		};
1792 		case CDE_UNIQ_ID_CMD:
1793 		{
1794 			// TODO: What is this?
1795 			timer_set(attotime::from_usec(250), TIMER_ID_READY);
1796 			break;
1797 		}
1798 		case CDE_BBLOCK:
1799 		{
1800 			break;
1801 		}
1802 
1803 		case CDE_DEV0_SETUP:
1804 		case CDE_DEV1_SETUP:
1805 		case CDE_DEV2_SETUP:
1806 		case CDE_DEV3_SETUP:
1807 		case CDE_DEV4_SETUP:
1808 		case CDE_DEV5_SETUP:
1809 		case CDE_DEV6_SETUP:
1810 		case CDE_DEV7_SETUP:
1811 		{
1812 			uint32_t id = (byte_offs - CDE_DEV0_SETUP) >> 3;
1813 			write_m2_reg(m_bio_device[id].m_setup, data, wm_cw);
1814 			break;
1815 		}
1816 
1817 		case CDE_DEV0_CYCLE_TIME:
1818 		case CDE_DEV1_CYCLE_TIME:
1819 		case CDE_DEV2_CYCLE_TIME:
1820 		case CDE_DEV3_CYCLE_TIME:
1821 		case CDE_DEV4_CYCLE_TIME:
1822 		case CDE_DEV5_CYCLE_TIME:
1823 		case CDE_DEV6_CYCLE_TIME:
1824 		case CDE_DEV7_CYCLE_TIME:
1825 		{
1826 			uint32_t id = (byte_offs - CDE_DEV0_CYCLE_TIME) >> 3;
1827 			write_m2_reg(m_bio_device[id].m_cycle_time, data, wm_cw);
1828 			break;
1829 		}
1830 
1831 //      case CDE_SYSTEM_CONF:
1832 		case CDE_VISA_DIS:
1833 		{
1834 			write_m2_reg(m_visa_dis, data, wm_cw);
1835 			break;
1836 		}
1837 		case CDE_MICRO_RWS:
1838 		case CDE_MICRO_WI:
1839 		case CDE_MICRO_WOB:
1840 		case CDE_MICRO_WO:
1841 		case CDE_MICRO_STATUS:
1842 		{
1843 			break;
1844 		}
1845 
1846 		case CDE_DMA1_CNTL:
1847 		case CDE_DMA2_CNTL:
1848 		{
1849 			uint32_t &ctrl = m_dma[dmach].m_cntl;
1850 			uint32_t old = ctrl;
1851 
1852 			write_m2_reg(ctrl, data, wm_cw);
1853 
1854 			if (!(old & CDE_DMA_RESET) && (ctrl & CDE_DMA_RESET))
1855 				reset_dma(dmach);
1856 
1857 			if (!(old & CDE_DMA_CURR_VALID) && (ctrl & CDE_DMA_CURR_VALID))
1858 				start_dma(dmach);
1859 
1860 			break;
1861 		}
1862 		case CDE_DMA1_CBAD:
1863 		case CDE_DMA2_CBAD:
1864 		{
1865 			write_m2_reg(m_dma[dmach].m_cbad, data, wm_cw);
1866 			break;
1867 		}
1868 		case CDE_DMA1_CPAD:
1869 		case CDE_DMA2_CPAD:
1870 		{
1871 			write_m2_reg(m_dma[dmach].m_cpad, data, wm_cw);
1872 			break;
1873 		}
1874 		case CDE_DMA1_CCNT:
1875 		case CDE_DMA2_CCNT:
1876 		{
1877 			write_m2_reg(m_dma[dmach].m_ccnt, data, wm_cw);
1878 			break;
1879 		}
1880 		default:
1881 		{
1882 			//logerror("%s: CDE_W UNHANDLED: 0x%.8x 0x%.8x 0x%.8x\n", machine().describe_context(), byte_offs, data, mem_mask);
1883 		}
1884 	}
1885 }
1886 
1887 
1888 //-------------------------------------------------
1889 //  sdbg_in -
1890 //-------------------------------------------------
1891 
sdbg_in(uint32_t data)1892 void m2_cde_device::sdbg_in(uint32_t data)
1893 {
1894 	m_sdbg_in = data;
1895 	set_interrupt(CDE_SDBG_RD_DONE);
1896 }
1897 
1898 
1899 
1900 
1901 /***************************************************************************
1902     PRIVATE FUNCTIONS
1903 ***************************************************************************/
1904 
1905 //-------------------------------------------------
1906 //  reset_dma - Reset a DMA channel
1907 //-------------------------------------------------
1908 
reset_dma(uint32_t ch)1909 void m2_cde_device::reset_dma(uint32_t ch)
1910 {
1911 	m_dma[ch].m_cntl = 0;
1912 	m_dma[ch].m_timer->adjust(attotime::never);
1913 }
1914 
1915 
1916 //-------------------------------------------------
1917 //  start_dma - DMA between the PowerBus and BioBus
1918 //-------------------------------------------------
1919 
start_dma(uint32_t ch)1920 void m2_cde_device::start_dma(uint32_t ch)
1921 {
1922 	dma_channel &dma_ch = m_dma[ch];
1923 	address_space *dma_space = &m_cpu1->space();
1924 
1925 	// TODO: DMA timing is probably inaccurate
1926 	attotime delay = attotime::from_nsec(10);// * dma_ch.m_ccnt;
1927 
1928 //  attotime delay = clocks_to_attotime(4 * dma_ch.m_ccnt);
1929 	dma_ch.m_timer->adjust(delay);
1930 
1931 	if (dma_ch.m_cntl & CDE_DMA_DIRECTION)
1932 	{
1933 		// PowerBus to BioBus
1934 		throw emu_fatalerror("m2_cde_device::start_dma: CDE PowerBus to BioBus DMA currently unsupported");
1935 	}
1936 	else
1937 	{
1938 		// BioBus to PowerBus
1939 #if 0
1940 		logerror("%s: CDE DMA %u: [%.8x] -> [%.8x], 0x%.8x bytes\n", machine().describe_context(), ch, dma_ch.m_cbad, dma_ch.m_cpad, dma_ch.m_ccnt);
1941 #endif
1942 		// Determine the BioBus device from the address
1943 		const uint32_t slot = address_to_biobus_slot(dma_ch.m_cbad);
1944 
1945 		// Get the device parameters
1946 		const uint32_t setup = m_bio_device[slot].m_setup;
1947 
1948 		if (setup & CDE_DATAWIDTH_16)
1949 		{
1950 			// 16-bit case
1951 			if (dma_ch.m_ccnt & 1)
1952 				throw emu_fatalerror("m2_cde_device::start_dma: 16-bit DMA: Byte count must be even?");
1953 			if (dma_ch.m_cpad & 1)
1954 				throw emu_fatalerror("m2_cde_device::start_dma: 16-bit DMA: DMA destination must be word aligned?");
1955 
1956 			const uint32_t srcinc = setup & CDE_READ_SETUP_IO ? 0 : 2;
1957 
1958 			while (dma_ch.m_ccnt > 0)
1959 			{
1960 				uint16_t data = dma_space->read_word_unaligned(dma_ch.m_cbad); // FIX ME
1961 				dma_space->write_word(dma_ch.m_cpad, data);
1962 
1963 				dma_ch.m_cbad += srcinc;
1964 				dma_ch.m_cpad += 2;
1965 				dma_ch.m_ccnt -= 2;
1966 			}
1967 		}
1968 		else
1969 		{
1970 			// 8-bit case
1971 			const uint32_t srcinc = setup & CDE_READ_SETUP_IO ? 0 : 1;
1972 
1973 			fatalerror("8-bit DMA untested\n");
1974 
1975 			while (dma_ch.m_ccnt > 0)
1976 			{
1977 				uint8_t data = dma_space->read_byte(dma_ch.m_cbad);
1978 				dma_space->write_byte(dma_ch.m_cpad, data);
1979 
1980 				dma_ch.m_cbad += srcinc;
1981 				dma_ch.m_cpad += 1;
1982 				dma_ch.m_ccnt -= 1;
1983 			}
1984 		}
1985 	}
1986 }
1987 
1988 //-------------------------------------------------
1989 //  next_dma - Start the next DMA if set
1990 //-------------------------------------------------
1991 
next_dma(uint32_t ch)1992 void m2_cde_device::next_dma(uint32_t ch)
1993 {
1994 	dma_channel &dma_ch = m_dma[ch];
1995 
1996 	// TODO: HACK!
1997 #if 1
1998 	m_cpu1->set_cache_dirty();
1999 #endif
2000 
2001 	if (dma_ch.m_ccnt != 0)
2002 		throw emu_fatalerror("m2_cde_device::next_dma: DMA count non-zero during next DMA");
2003 
2004 	if (dma_ch.m_cntl & CDE_DMA_NEXT_VALID)
2005 	{
2006 		logerror("NEXT DMA CODE UNTESTED");
2007 
2008 		// Update current address and count registers
2009 		dma_ch.m_cbad = dma_ch.m_nbad;
2010 		dma_ch.m_cpad = dma_ch.m_npad;
2011 		dma_ch.m_ccnt = dma_ch.m_ncnt;
2012 		dma_ch.m_cntl |= CDE_DMA_CURR_VALID;
2013 
2014 		// Disable looping
2015 		if (!(dma_ch.m_cntl & CDE_DMA_GO_FOREVER))
2016 			dma_ch.m_cntl &= ~CDE_DMA_NEXT_VALID;
2017 
2018 		start_dma(ch);
2019 	}
2020 	else
2021 	{
2022 		// DMA complete
2023 		dma_ch.m_cntl &= ~CDE_DMA_CURR_VALID;
2024 		set_interrupt(ch == 0 ? CDE_DMA1_DONE : CDE_DMA2_DONE);
2025 	}
2026 }
2027 
2028 
2029 /***************************************************************************
2030  MPEG DEVICE
2031  ***************************************************************************/
2032 
2033 //-------------------------------------------------
2034 //  m2_mpeg_device - constructor
2035 //-------------------------------------------------
2036 
m2_mpeg_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)2037 m2_mpeg_device::m2_mpeg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
2038 	device_t(mconfig, M2_MPEG, tag, owner, clock)
2039 {
2040 }
2041 
2042 
2043 //-------------------------------------------------
2044 //  device_start - device-specific startup
2045 //-------------------------------------------------
2046 
device_start()2047 void m2_mpeg_device::device_start()
2048 {
2049 
2050 }
2051 
2052 //-------------------------------------------------
2053 //  device_reset - device-specific reset
2054 //-------------------------------------------------
2055 
device_reset()2056 void m2_mpeg_device::device_reset()
2057 {
2058 
2059 }
2060 
2061 //-------------------------------------------------
2062 //  read
2063 //-------------------------------------------------
2064 
read(offs_t offset)2065 uint32_t m2_mpeg_device::read(offs_t offset)
2066 {
2067 	logerror("%s: MPEG READ: %08X\n", machine().describe_context(), offset);
2068 	return 0;
2069 }
2070 
2071 //-------------------------------------------------
2072 //  write
2073 //-------------------------------------------------
2074 
write(offs_t offset,uint32_t data)2075 void m2_mpeg_device::write(offs_t offset, uint32_t data)
2076 {
2077 	logerror("%s: MPEG WRITE: %08X %08X\n", machine().describe_context(), offset, data);
2078 }
2079