1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont
3 /****************************************************************************
4 
5     drivers/macquadra700.cpp
6     Mac Quadra 700 emulation.  (900/950 are IOP-based and closer to the IIfx)
7 
8     By R. Belmont
9 
10 ****************************************************************************/
11 
12 #include "emu.h"
13 
14 #include "machine/macrtc.h"
15 #include "cpu/m68000/m68000.h"
16 #include "machine/6522via.h"
17 #include "machine/applefdc.h"
18 #include "machine/ram.h"
19 #include "machine/sonydriv.h"
20 #include "machine/swim.h"
21 #include "machine/timer.h"
22 #include "machine/z80scc.h"
23 #include "machine/macadb.h"
24 #include "machine/dp83932c.h"
25 #include "machine/nscsi_bus.h"
26 #include "machine/ncr5390.h"
27 #include "sound/asc.h"
28 #include "formats/ap_dsk35.h"
29 
30 #include "bus/nscsi/cd.h"
31 #include "bus/nscsi/hd.h"
32 
33 #include "bus/nubus/nubus.h"
34 #include "bus/nubus/nubus_48gc.h"
35 #include "bus/nubus/nubus_cb264.h"
36 #include "bus/nubus/nubus_vikbw.h"
37 #include "bus/nubus/nubus_specpdq.h"
38 #include "bus/nubus/nubus_m2hires.h"
39 #include "bus/nubus/nubus_spec8.h"
40 #include "bus/nubus/nubus_radiustpd.h"
41 #include "bus/nubus/nubus_wsportrait.h"
42 #include "bus/nubus/nubus_asntmc3b.h"
43 #include "bus/nubus/nubus_image.h"
44 #include "bus/nubus/nubus_m2video.h"
45 #include "bus/nubus/bootbug.h"
46 #include "bus/nubus/quadralink.h"
47 #include "bus/nubus/laserview.h"
48 
49 #include "emupal.h"
50 #include "screen.h"
51 #include "softlist.h"
52 #include "speaker.h"
53 
54 #define C7M (7833600)
55 #define C15M (C7M*2)
56 #define C32M (C15M*2)
57 
58 class macquadra_state : public driver_device
59 {
60 public:
macquadra_state(const machine_config & mconfig,device_type type,const char * tag)61 	macquadra_state(const machine_config &mconfig, device_type type, const char *tag) :
62 		driver_device(mconfig, type, tag),
63 		m_maincpu(*this, "maincpu"),
64 		m_via1(*this, "via1"),
65 		m_via2(*this, "via2"),
66 		m_macadb(*this, "macadb"),
67 		m_ram(*this, RAM_TAG),
68 		m_iwm(*this, "fdc"),
69 		m_rtc(*this,"rtc"),
70 		m_scsibus1(*this, "scsi1"),
71 		m_ncr1(*this, "scsi1:7:ncr5394"),
72 		m_sonic(*this, "sonic"),
73 		m_screen(*this, "screen"),
74 		m_palette(*this, "palette"),
75 		m_easc(*this, "easc"),
76 		m_scc(*this, "scc"),
77 		m_vram(*this, "vram")
78 	{
79 	}
80 
81 	void macqd700(machine_config &config);
82 	void quadra700_map(address_map &map);
83 
84 	void init_macqd700();
85 
86 private:
87 	required_device<m68040_device> m_maincpu;
88 	required_device<via6522_device> m_via1, m_via2;
89 	optional_device<macadb_device> m_macadb;
90 	required_device<ram_device> m_ram;
91 	required_device<applefdc_base_device> m_iwm;
92 	required_device<rtc3430042_device> m_rtc;
93 	required_device<nscsi_bus_device> m_scsibus1;
94 	required_device<ncr53cf94_device> m_ncr1;
95 	required_device<dp83932c_device> m_sonic;
96 	required_device<screen_device> m_screen;
97 	required_device<palette_device> m_palette;
98 	required_device<asc_device> m_easc;
99 	required_device<z80scc_device> m_scc;
100 	required_shared_ptr<uint32_t> m_vram;
101 
102 	virtual void machine_start() override;
103 	virtual void machine_reset() override;
104 
105 	uint32_t screen_update_dafb(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
106 	uint32_t dafb_r(offs_t offset, uint32_t mem_mask = ~0);
107 	void dafb_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
108 	uint32_t dafb_dac_r(offs_t offset, uint32_t mem_mask = ~0);
109 	void dafb_dac_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
110 	void dafb_recalc_ints();
111 
112 	TIMER_CALLBACK_MEMBER(dafb_vbl_tick);
113 	TIMER_CALLBACK_MEMBER(dafb_cursor_tick);
114 	DECLARE_VIDEO_START(macdafb);
115 	DECLARE_VIDEO_RESET(macdafb);
116 
117 	u32 *m_ram_ptr, *m_rom_ptr;
118 	u32 m_ram_mask, m_ram_size, m_rom_size;
119 
120 	emu_timer *m_vbl_timer, *m_cursor_timer, *m_6015_timer;
121 
122 	uint16_t m_cursor_line;
123 	uint16_t m_dafb_int_status;
124 	int m_dafb_scsi1_drq, m_dafb_scsi2_drq;
125 	uint8_t m_dafb_mode;
126 	uint32_t m_dafb_base, m_dafb_stride;
127 	uint32_t m_dafb_colors[3], m_dafb_count, m_dafb_clutoffs, m_dafb_montype, m_dafb_vbltime;
128 	uint32_t m_dafb_palette[256];
129 
130 	DECLARE_WRITE_LINE_MEMBER(nubus_irq_9_w);
131 	DECLARE_WRITE_LINE_MEMBER(nubus_irq_a_w);
132 	DECLARE_WRITE_LINE_MEMBER(nubus_irq_b_w);
133 	DECLARE_WRITE_LINE_MEMBER(nubus_irq_c_w);
134 	DECLARE_WRITE_LINE_MEMBER(nubus_irq_d_w);
135 	DECLARE_WRITE_LINE_MEMBER(nubus_irq_e_w);
136 	void nubus_slot_interrupt(uint8_t slot, uint32_t state);
137 	int m_via2_ca1_hack, m_nubus_irq_state;
138 
WRITE_LINE_MEMBER(adb_irq_w)139 	WRITE_LINE_MEMBER(adb_irq_w) { m_adb_irq_pending = state; }
140 	int m_adb_irq_pending;
141 
142 	DECLARE_WRITE_LINE_MEMBER(irq_539x_1_w);
143 	DECLARE_WRITE_LINE_MEMBER(irq_539x_2_w);
144 	DECLARE_WRITE_LINE_MEMBER(drq_539x_1_w);
145 	DECLARE_WRITE_LINE_MEMBER(drq_539x_2_w);
146 
147 	uint16_t mac_via_r(offs_t offset);
148 	void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask);
149 	uint16_t mac_via2_r(offs_t offset);
150 	void mac_via2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
151 	uint8_t mac_via_in_a();
152 	uint8_t mac_via_in_b();
153 	void mac_via_out_a(uint8_t data);
154 	void mac_via_out_b(uint8_t data);
155 	uint8_t mac_via2_in_a();
156 	uint8_t mac_via2_in_b();
157 	void mac_via2_out_a(uint8_t data);
158 	void mac_via2_out_b(uint8_t data);
159 	void field_interrupts();
160 	DECLARE_WRITE_LINE_MEMBER(mac_via_irq);
161 	DECLARE_WRITE_LINE_MEMBER(mac_via2_irq);
162 	TIMER_CALLBACK_MEMBER(mac_6015_tick);
WRITE_LINE_MEMBER(via_cb2_w)163 	WRITE_LINE_MEMBER(via_cb2_w) { m_macadb->adb_data_w(state); }
164 	int m_via_cycles, m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt;
165 	int m_irq_count, m_ca2_data;
166 
167 	uint32_t rom_switch_r(offs_t offset);
168 	bool m_overlay;
169 
mac_scc_r(offs_t offset)170 	uint16_t mac_scc_r(offs_t offset)
171 	{
172 		uint16_t result = m_scc->dc_ab_r(offset);
173 		return (result << 8) | result;
174 	}
mac_scc_2_w(offs_t offset,uint16_t data)175 	void mac_scc_2_w(offs_t offset, uint16_t data) { m_scc->dc_ab_w(offset, data >> 8); }
176 
mac_iwm_r(offs_t offset,uint16_t mem_mask)177 	uint16_t mac_iwm_r(offs_t offset, uint16_t mem_mask)
178 	{
179 		uint16_t result = m_iwm->read(offset >> 8);
180 		return (result << 8) | result;
181 	}
mac_iwm_w(offs_t offset,uint16_t data,uint16_t mem_mask)182 	void mac_iwm_w(offs_t offset, uint16_t data, uint16_t mem_mask)
183 	{
184 		if (ACCESSING_BITS_0_7)
185 			m_iwm->write((offset >> 8), data & 0xff);
186 		else
187 			m_iwm->write((offset >> 8), data>>8);
188 	}
189 
190 	uint8_t mac_5396_r(offs_t offset);
191 	void mac_5396_w(offs_t offset, uint8_t data);
192 };
193 
field_interrupts()194 void macquadra_state::field_interrupts()
195 {
196 	int take_interrupt = -1;
197 
198 	if (m_scc_interrupt)
199 	{
200 		take_interrupt = 4;
201 	}
202 	else if (m_via2_interrupt)
203 	{
204 		take_interrupt = 2;
205 	}
206 	else if (m_via_interrupt)
207 	{
208 		take_interrupt = 1;
209 	}
210 
211 	if (m_last_taken_interrupt > -1)
212 	{
213 		m_maincpu->set_input_line(m_last_taken_interrupt, CLEAR_LINE);
214 		m_last_taken_interrupt = -1;
215 	}
216 
217 	if (take_interrupt > -1)
218 	{
219 		m_maincpu->set_input_line(take_interrupt, ASSERT_LINE);
220 		m_last_taken_interrupt = take_interrupt;
221 	}
222 }
223 
machine_start()224 void macquadra_state::machine_start()
225 {
226 	m_ram_ptr = (u32*)m_ram->pointer();
227 	m_ram_size = m_ram->size()>>1;
228 	m_ram_mask = m_ram_size - 1;
229 	m_rom_ptr = (u32*)memregion("bootrom")->base();
230 	m_rom_size = memregion("bootrom")->bytes();
231 	m_via_cycles = -50;
232 	m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
233 	m_last_taken_interrupt = -1;
234 	m_irq_count = m_ca2_data = 0;
235 
236 	m_6015_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(macquadra_state::mac_6015_tick),this));
237 	m_6015_timer->adjust(attotime::never);
238 }
239 
machine_reset()240 void macquadra_state::machine_reset()
241 {
242 	m_nubus_irq_state = 0xff;
243 	m_via2_ca1_hack = 1;
244 	m_via2->write_ca1(1);
245 	m_via2->write_cb1(1);
246 	m_overlay = true;
247 	m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
248 	m_last_taken_interrupt = -1;
249 	m_irq_count = m_ca2_data = 0;
250 
251 	// put ROM mirror at 0
252 	address_space& space = m_maincpu->space(AS_PROGRAM);
253 	const u32 memory_size = std::min((u32)0x3fffff, m_rom_size);
254 	const u32 memory_end = memory_size - 1;
255 	offs_t memory_mirror = memory_end & ~(memory_size - 1);
256 
257 	space.unmap_write(0x00000000, memory_end);
258 	space.install_read_bank(0x00000000, memory_end & ~memory_mirror, memory_mirror, "bank1");
259 	membank("bank1")->set_base(m_rom_ptr);
260 
261 	// start 60.15 Hz timer
262 	m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15));
263 }
264 
init_macqd700()265 void macquadra_state::init_macqd700()
266 {
267 }
268 
nubus_slot_interrupt(uint8_t slot,uint32_t state)269 void macquadra_state::nubus_slot_interrupt(uint8_t slot, uint32_t state)
270 {
271 	static const uint8_t masks[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
272 	uint8_t mask = 0xff;
273 
274 	slot -= 9;
275 
276 	if (state)
277 	{
278 		m_nubus_irq_state &= ~masks[slot];
279 	}
280 	else
281 	{
282 		m_nubus_irq_state |= masks[slot];
283 	}
284 
285 	if ((m_nubus_irq_state & mask) != mask)
286 	{
287 		// HACK: sometimes we miss an ack (possible misbehavior in the VIA?)
288 		if (m_via2_ca1_hack == 0)
289 		{
290 			m_via2->write_ca1(1);
291 		}
292 		m_via2_ca1_hack = 0;
293 		m_via2->write_ca1(0);
294 	}
295 	else
296 	{
297 		m_via2_ca1_hack = 1;
298 		m_via2->write_ca1(1);
299 	}
300 }
301 
WRITE_LINE_MEMBER(macquadra_state::nubus_irq_9_w)302 WRITE_LINE_MEMBER(macquadra_state::nubus_irq_9_w) { nubus_slot_interrupt(9, state); }
WRITE_LINE_MEMBER(macquadra_state::nubus_irq_a_w)303 WRITE_LINE_MEMBER(macquadra_state::nubus_irq_a_w) { nubus_slot_interrupt(0xa, state); }
WRITE_LINE_MEMBER(macquadra_state::nubus_irq_b_w)304 WRITE_LINE_MEMBER(macquadra_state::nubus_irq_b_w) { nubus_slot_interrupt(0xb, state); }
WRITE_LINE_MEMBER(macquadra_state::nubus_irq_c_w)305 WRITE_LINE_MEMBER(macquadra_state::nubus_irq_c_w) { nubus_slot_interrupt(0xc, state); }
WRITE_LINE_MEMBER(macquadra_state::nubus_irq_d_w)306 WRITE_LINE_MEMBER(macquadra_state::nubus_irq_d_w) { nubus_slot_interrupt(0xd, state); }
WRITE_LINE_MEMBER(macquadra_state::nubus_irq_e_w)307 WRITE_LINE_MEMBER(macquadra_state::nubus_irq_e_w) { nubus_slot_interrupt(0xe, state); }
308 
309 // DAFB: video for Quadra 700/900
310 
dafb_recalc_ints()311 void macquadra_state::dafb_recalc_ints()
312 {
313 	if (m_dafb_int_status != 0)
314 	{
315 		nubus_slot_interrupt(0xf, ASSERT_LINE);
316 	}
317 	else
318 	{
319 		nubus_slot_interrupt(0xf, CLEAR_LINE);
320 	}
321 }
322 
TIMER_CALLBACK_MEMBER(macquadra_state::dafb_vbl_tick)323 TIMER_CALLBACK_MEMBER(macquadra_state::dafb_vbl_tick)
324 {
325 	m_dafb_int_status |= 1;
326 	dafb_recalc_ints();
327 
328 	m_vbl_timer->adjust(m_screen->time_until_pos(480, 0), 0);
329 }
330 
TIMER_CALLBACK_MEMBER(macquadra_state::dafb_cursor_tick)331 TIMER_CALLBACK_MEMBER(macquadra_state::dafb_cursor_tick)
332 {
333 	m_dafb_int_status |= 4;
334 	dafb_recalc_ints();
335 
336 	m_cursor_timer->adjust(m_screen->time_until_pos(m_cursor_line, 0), 0);
337 }
338 
VIDEO_START_MEMBER(macquadra_state,macdafb)339 VIDEO_START_MEMBER(macquadra_state,macdafb)
340 {
341 	m_vbl_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(macquadra_state::dafb_vbl_tick),this));
342 	m_cursor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(macquadra_state::dafb_cursor_tick),this));
343 
344 	m_vbl_timer->adjust(attotime::never);
345 	m_cursor_timer->adjust(attotime::never);
346 }
347 
VIDEO_RESET_MEMBER(macquadra_state,macdafb)348 VIDEO_RESET_MEMBER(macquadra_state,macdafb)
349 {
350 	m_dafb_count = 0;
351 	m_dafb_clutoffs = 0;
352 	m_dafb_montype = 6;
353 	m_dafb_vbltime = 0;
354 	m_dafb_int_status = 0;
355 	m_dafb_mode = 0;
356 	m_dafb_base = 0x1000;
357 	m_dafb_stride = 256*4;
358 
359 	memset(m_dafb_palette, 0, sizeof(m_dafb_palette));
360 }
361 
dafb_r(offs_t offset,uint32_t mem_mask)362 uint32_t macquadra_state::dafb_r(offs_t offset, uint32_t mem_mask)
363 {
364 //  if (offset != 0x108/4) printf("DAFB: Read @ %x (mask %x PC=%x)\n", offset*4, mem_mask, m_maincpu->pc());
365 
366 	switch (offset<<2)
367 	{
368 		case 0x1c:  // inverse of monitor sense
369 			return 7;   // 21" color 2-page
370 
371 		case 0x24: // SCSI 539x #1 status
372 			return m_dafb_scsi1_drq<<9;
373 
374 		case 0x28: // SCSI 539x #2 status
375 			return m_dafb_scsi2_drq<<9;
376 
377 		case 0x108: // IRQ/VBL status
378 			return m_dafb_int_status;
379 
380 		case 0x10c: // clear cursor scanline int
381 			m_dafb_int_status &= ~4;
382 			dafb_recalc_ints();
383 			break;
384 
385 		case 0x114: // clear VBL int
386 			m_dafb_int_status &= ~1;
387 			dafb_recalc_ints();
388 			break;
389 	}
390 	return 0;
391 }
392 
dafb_w(offs_t offset,uint32_t data,uint32_t mem_mask)393 void macquadra_state::dafb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
394 {
395 //  if (offset != 0x10c/4) printf("DAFB: Write %08x @ %x (mask %x PC=%x)\n", data, offset*4, mem_mask, m_maincpu->pc());
396 
397 	switch (offset<<2)
398 	{
399 		case 0: // bits 20-9 of base
400 			m_dafb_base &= 0x1ff;
401 			m_dafb_base |= (data & 0xffff) << 9;
402 //          printf("DAFB baseH: %x\n", m_dafb_base);
403 			break;
404 
405 		case 4: // bits 8-5 of base
406 			m_dafb_base &= ~0x1ff;
407 			m_dafb_base |= (data & 0xf) << 5;
408 //          printf("DAFB baseL: %x\n", m_dafb_base);
409 			break;
410 
411 		case 8:
412 			m_dafb_stride = data<<2;    // stride in DWORDs
413 //          printf("DAFB stride: %x %x\n", m_dafb_stride, data);
414 			break;
415 
416 		case 0x104:
417 			if (data & 1)   // VBL enable
418 			{
419 				m_vbl_timer->adjust(m_screen->time_until_pos(480, 0), 0);
420 			}
421 			else
422 			{
423 				m_vbl_timer->adjust(attotime::never);
424 				m_dafb_int_status &= ~1;
425 				dafb_recalc_ints();
426 			}
427 
428 			if (data & 2)   // aux scanline interrupt enable
429 			{
430 				fatalerror("DAFB: Aux scanline interrupt enable not supported!\n");
431 			}
432 
433 			if (data & 4)   // cursor scanline interrupt enable
434 			{
435 				m_cursor_timer->adjust(m_screen->time_until_pos(m_cursor_line, 0), 0);
436 			}
437 			else
438 			{
439 				m_cursor_timer->adjust(attotime::never);
440 				m_dafb_int_status &= ~4;
441 				dafb_recalc_ints();
442 			}
443 			break;
444 
445 		case 0x10c: // clear cursor scanline int
446 			m_dafb_int_status &= ~4;
447 			dafb_recalc_ints();
448 			break;
449 
450 		case 0x114: // clear VBL int
451 			m_dafb_int_status &= ~1;
452 			dafb_recalc_ints();
453 			break;
454 	}
455 }
456 
dafb_dac_r(offs_t offset,uint32_t mem_mask)457 uint32_t macquadra_state::dafb_dac_r(offs_t offset, uint32_t mem_mask)
458 {
459 //  printf("DAFB: Read DAC @ %x (mask %x PC=%x)\n", offset*4, mem_mask, m_maincpu->pc());
460 	return 0;
461 }
462 
dafb_dac_w(offs_t offset,uint32_t data,uint32_t mem_mask)463 void macquadra_state::dafb_dac_w(offs_t offset, uint32_t data, uint32_t mem_mask)
464 {
465 //  if ((offset > 0) && (offset != 0x10/4)) printf("DAFB: Write %08x to DAC @ %x (mask %x PC=%x)\n", data, offset*4, mem_mask, m_maincpu->pc());
466 
467 	switch (offset<<2)
468 	{
469 		case 0:
470 			m_dafb_clutoffs = data & 0xff;
471 			m_dafb_count = 0;
472 			break;
473 
474 		case 0x10:
475 			m_dafb_colors[m_dafb_count++] = data&0xff;
476 
477 			if (m_dafb_count == 3)
478 			{
479 				m_palette->set_pen_color(m_dafb_clutoffs, rgb_t(m_dafb_colors[0], m_dafb_colors[1], m_dafb_colors[2]));
480 				m_dafb_palette[m_dafb_clutoffs] = rgb_t(m_dafb_colors[0], m_dafb_colors[1], m_dafb_colors[2]);
481 				m_dafb_clutoffs++;
482 				m_dafb_count = 0;
483 			}
484 			break;
485 
486 		case 0x20:
487 			switch (data & 0x9f)
488 			{
489 				case 0x80:
490 					m_dafb_mode = 0;    // 1bpp
491 					break;
492 
493 				case 0x88:
494 					m_dafb_mode = 1;    // 2bpp
495 					break;
496 
497 				case 0x90:
498 					m_dafb_mode = 2;    // 4bpp
499 					break;
500 
501 				case 0x98:
502 					m_dafb_mode = 3;    // 8bpp
503 					break;
504 
505 				case 0x9c:
506 					m_dafb_mode = 4;    // 24bpp
507 					break;
508 			}
509 			break;
510 	}
511 }
512 
screen_update_dafb(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)513 uint32_t macquadra_state::screen_update_dafb(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
514 {
515 	switch (m_dafb_mode)
516 	{
517 		case 0: // 1bpp
518 		{
519 			uint8_t const *vram8 = (uint8_t *)m_vram.target();
520 			vram8 += m_dafb_base;
521 
522 			for (int y = 0; y < 870; y++)
523 			{
524 				uint32_t *scanline = &bitmap.pix(y);
525 				for (int x = 0; x < 1152; x+=8)
526 				{
527 					uint8_t const pixels = vram8[(y * m_dafb_stride) + ((x/8)^3)];
528 
529 					*scanline++ = m_dafb_palette[(pixels>>7)&1];
530 					*scanline++ = m_dafb_palette[(pixels>>6)&1];
531 					*scanline++ = m_dafb_palette[(pixels>>5)&1];
532 					*scanline++ = m_dafb_palette[(pixels>>4)&1];
533 					*scanline++ = m_dafb_palette[(pixels>>3)&1];
534 					*scanline++ = m_dafb_palette[(pixels>>2)&1];
535 					*scanline++ = m_dafb_palette[(pixels>>1)&1];
536 					*scanline++ = m_dafb_palette[(pixels&1)];
537 				}
538 			}
539 		}
540 		break;
541 
542 		case 1: // 2bpp
543 		{
544 			uint8_t const *vram8 = (uint8_t *)m_vram.target();
545 			vram8 += m_dafb_base;
546 
547 			for (int y = 0; y < 870; y++)
548 			{
549 				uint32_t *scanline = &bitmap.pix(y);
550 				for (int x = 0; x < 1152/4; x++)
551 				{
552 					uint8_t const pixels = vram8[(y * m_dafb_stride) + (BYTE4_XOR_BE(x))];
553 
554 					*scanline++ = m_dafb_palette[((pixels>>6)&3)];
555 					*scanline++ = m_dafb_palette[((pixels>>4)&3)];
556 					*scanline++ = m_dafb_palette[((pixels>>2)&3)];
557 					*scanline++ = m_dafb_palette[(pixels&3)];
558 				}
559 			}
560 		}
561 		break;
562 
563 		case 2: // 4bpp
564 		{
565 			uint8_t const *vram8 = (uint8_t *)m_vram.target();
566 			vram8 += m_dafb_base;
567 
568 			for (int y = 0; y < 870; y++)
569 			{
570 				uint32_t *scanline = &bitmap.pix(y);
571 				for (int x = 0; x < 1152/2; x++)
572 				{
573 					uint8_t const pixels = vram8[(y * m_dafb_stride) + (BYTE4_XOR_BE(x))];
574 
575 					*scanline++ = m_dafb_palette[(pixels>>4)];
576 					*scanline++ = m_dafb_palette[(pixels&0xf)];
577 				}
578 			}
579 		}
580 		break;
581 
582 		case 3: // 8bpp
583 		{
584 			uint8_t const *vram8 = (uint8_t *)m_vram.target();
585 			vram8 += m_dafb_base;
586 
587 			for (int y = 0; y < 870; y++)
588 			{
589 				uint32_t *scanline = &bitmap.pix(y);
590 				for (int x = 0; x < 1152; x++)
591 				{
592 					uint8_t const pixels = vram8[(y * m_dafb_stride) + (BYTE4_XOR_BE(x))];
593 					*scanline++ = m_dafb_palette[pixels];
594 				}
595 			}
596 		}
597 		break;
598 
599 		case 4: // 24 bpp
600 			for (int y = 0; y < 480; y++)
601 			{
602 				uint32_t *scanline = &bitmap.pix(y);
603 				uint32_t const *base = (uint32_t *)&m_vram[(y * (m_dafb_stride/4)) + (m_dafb_base/4)];
604 				for (int x = 0; x < 640; x++)
605 				{
606 					*scanline++ = *base++;
607 				}
608 			}
609 			break;
610 	}
611 
612 	return 0;
613 }
614 
WRITE_LINE_MEMBER(macquadra_state::drq_539x_1_w)615 WRITE_LINE_MEMBER(macquadra_state::drq_539x_1_w)
616 {
617 }
618 
WRITE_LINE_MEMBER(macquadra_state::drq_539x_2_w)619 WRITE_LINE_MEMBER(macquadra_state::drq_539x_2_w)
620 {
621 }
622 
WRITE_LINE_MEMBER(macquadra_state::irq_539x_1_w)623 WRITE_LINE_MEMBER(macquadra_state::irq_539x_1_w)
624 {
625 	if (state)  // make sure a CB1 transition occurs
626 	{
627 		m_via2->write_cb2(0);
628 		m_via2->write_cb2(1);
629 	}
630 }
631 
WRITE_LINE_MEMBER(macquadra_state::irq_539x_2_w)632 WRITE_LINE_MEMBER(macquadra_state::irq_539x_2_w)
633 {
634 }
635 
mac_via_r(offs_t offset)636 uint16_t macquadra_state::mac_via_r(offs_t offset)
637 {
638 	uint16_t data;
639 
640 	offset >>= 8;
641 	offset &= 0x0f;
642 
643 	data = m_via1->read(offset);
644 
645 	m_maincpu->adjust_icount(m_via_cycles);
646 
647 	return (data & 0xff) | (data << 8);
648 }
649 
mac_via_w(offs_t offset,uint16_t data,uint16_t mem_mask)650 void macquadra_state::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask)
651 {
652 	offset >>= 8;
653 	offset &= 0x0f;
654 
655 	if (ACCESSING_BITS_0_7)
656 		m_via1->write(offset, data & 0xff);
657 	if (ACCESSING_BITS_8_15)
658 		m_via1->write(offset, (data >> 8) & 0xff);
659 
660 	m_maincpu->adjust_icount(m_via_cycles);
661 }
662 
WRITE_LINE_MEMBER(macquadra_state::mac_via_irq)663 WRITE_LINE_MEMBER(macquadra_state::mac_via_irq)
664 {
665 	m_via_interrupt = state;
666 	field_interrupts();
667 }
668 
WRITE_LINE_MEMBER(macquadra_state::mac_via2_irq)669 WRITE_LINE_MEMBER(macquadra_state::mac_via2_irq)
670 {
671 	m_via2_interrupt = state;
672 	field_interrupts();
673 }
674 
mac_via2_r(offs_t offset)675 uint16_t macquadra_state::mac_via2_r(offs_t offset)
676 {
677 	int data;
678 
679 	offset >>= 8;
680 	offset &= 0x0f;
681 
682 	data = m_via2->read(offset);
683 	return (data & 0xff) | (data << 8);
684 }
685 
mac_via2_w(offs_t offset,uint16_t data,uint16_t mem_mask)686 void macquadra_state::mac_via2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
687 {
688 	offset >>= 8;
689 	offset &= 0x0f;
690 
691 	if (ACCESSING_BITS_0_7)
692 		m_via2->write(offset, data & 0xff);
693 	if (ACCESSING_BITS_8_15)
694 		m_via2->write(offset, (data >> 8) & 0xff);
695 }
696 
rom_switch_r(offs_t offset)697 uint32_t macquadra_state::rom_switch_r(offs_t offset)
698 {
699 	// disable the overlay
700 	if (m_overlay)
701 	{
702 		address_space& space = m_maincpu->space(AS_PROGRAM);
703 		const u32 memory_end = m_ram->size() - 1;
704 		void *memory_data = m_ram->pointer();
705 		offs_t memory_mirror = memory_end & ~memory_end;
706 
707 		space.install_readwrite_bank(0x00000000, memory_end & ~memory_mirror, memory_mirror, "bank1");
708 		membank("bank1")->set_base(memory_data);
709 		m_overlay = false;
710 	}
711 
712 	//printf("rom_switch_r: offset %08x ROM_size -1 = %08x, masked = %08x\n", offset, m_rom_size-1, offset & ((m_rom_size - 1)>>2));
713 
714 	return m_rom_ptr[offset & ((m_rom_size - 1)>>2)];
715 }
716 
TIMER_CALLBACK_MEMBER(macquadra_state::mac_6015_tick)717 TIMER_CALLBACK_MEMBER(macquadra_state::mac_6015_tick)
718 {
719 	/* handle ADB keyboard/mouse */
720 	m_macadb->adb_vblank();
721 
722 	if (++m_irq_count == 60)
723 	{
724 		m_irq_count = 0;
725 
726 		m_ca2_data ^= 1;
727 		/* signal 1 Hz irq on CA2 input on the VIA */
728 		m_via1->write_ca2(m_ca2_data);
729 	}
730 }
731 
mac_5396_r(offs_t offset)732 uint8_t macquadra_state::mac_5396_r(offs_t offset)
733 {
734 	if (offset < 0x100)
735 	{
736 		return m_ncr1->read(offset>>4);
737 	}
738 	else    // pseudo-DMA: read from the FIFO
739 	{
740 //      return m_539x_1->read(2);
741 	}
742 
743 	// never executed
744 	return 0;
745 }
746 
mac_5396_w(offs_t offset,uint8_t data)747 void macquadra_state::mac_5396_w(offs_t offset, uint8_t data)
748 {
749 	if (offset < 0x100)
750 	{
751 		m_ncr1->write(offset>>4, data);
752 	}
753 	else    // pseudo-DMA: write to the FIFO
754 	{
755 //      m_539x_1->write(2, data);
756 	}
757 }
758 
759 /***************************************************************************
760     ADDRESS MAPS
761 ***************************************************************************/
quadra700_map(address_map & map)762 void macquadra_state::quadra700_map(address_map &map)
763 {
764 	map(0x40000000, 0x400fffff).r(FUNC(macquadra_state::rom_switch_r)).mirror(0x0ff00000);
765 
766 	map(0x50000000, 0x50001fff).rw(FUNC(macquadra_state::mac_via_r), FUNC(macquadra_state::mac_via_w)).mirror(0x00fc0000);
767 	map(0x50002000, 0x50003fff).rw(FUNC(macquadra_state::mac_via2_r), FUNC(macquadra_state::mac_via2_w)).mirror(0x00fc0000);
768 // 50008000 = Ethernet MAC ID PROM
769 // 5000a000 = Sonic (DP83932) ethernet
770 // 5000f000 = SCSI cf96, 5000f402 = SCSI #2 cf96
771 	map(0x5000f000, 0x5000f3ff).rw(FUNC(macquadra_state::mac_5396_r), FUNC(macquadra_state::mac_5396_w)).mirror(0x00fc0000);
772 	map(0x5000c000, 0x5000dfff).rw(FUNC(macquadra_state::mac_scc_r), FUNC(macquadra_state::mac_scc_2_w)).mirror(0x00fc0000);
773 	map(0x50014000, 0x50015fff).rw(m_easc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00fc0000);
774 	map(0x5001e000, 0x5001ffff).rw(FUNC(macquadra_state::mac_iwm_r), FUNC(macquadra_state::mac_iwm_w)).mirror(0x00fc0000);
775 
776 	// f9800000 = VDAC / DAFB
777 	map(0xf9000000, 0xf91fffff).ram().share("vram");
778 	map(0xf9800000, 0xf98001ff).rw(FUNC(macquadra_state::dafb_r), FUNC(macquadra_state::dafb_w));
779 	map(0xf9800200, 0xf980023f).rw(FUNC(macquadra_state::dafb_dac_r), FUNC(macquadra_state::dafb_dac_w));
780 }
781 
mac_via_in_a()782 uint8_t macquadra_state::mac_via_in_a()
783 {
784 	return 0xc1;
785 }
786 
mac_via_in_b()787 uint8_t macquadra_state::mac_via_in_b()
788 {
789 	int val = m_macadb->get_adb_state()<<4;
790 	val |= m_rtc->data_r();
791 
792 	if (!m_adb_irq_pending)
793 	{
794 		val |= 0x08;
795 	}
796 
797 //  printf("%s VIA1 IN_B = %02x\n", machine().describe_context().c_str(), val);
798 
799 	return val;
800 }
801 
mac_via_out_a(uint8_t data)802 void macquadra_state::mac_via_out_a(uint8_t data)
803 {
804 //  printf("%s VIA1 OUT A: %02x\n", machine().describe_context().c_str(), data);
805 	sony_set_sel_line(m_iwm.target(), (data & 0x20) >> 5);
806 }
807 
mac_via_out_b(uint8_t data)808 void macquadra_state::mac_via_out_b(uint8_t data)
809 {
810 //  printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data);
811 	m_macadb->mac_adb_newaction((data & 0x30) >> 4);
812 
813 	m_rtc->ce_w((data & 0x04)>>2);
814 	m_rtc->data_w(data & 0x01);
815 	m_rtc->clk_w((data >> 1) & 0x01);
816 }
817 
mac_via2_in_a()818 uint8_t macquadra_state::mac_via2_in_a()
819 {
820 	return 0x80 | m_nubus_irq_state;
821 }
822 
mac_via2_in_b()823 uint8_t macquadra_state::mac_via2_in_b()
824 {
825 	return 0xcf;        // indicate no NuBus transaction error
826 }
827 
mac_via2_out_a(uint8_t data)828 void macquadra_state::mac_via2_out_a(uint8_t data)
829 {
830 }
831 
mac_via2_out_b(uint8_t data)832 void macquadra_state::mac_via2_out_b(uint8_t data)
833 {
834 	// chain 60.15 Hz to VIA1
835 	m_via1->write_ca1(data>>7);
836 }
837 
838 /***************************************************************************
839     DEVICE CONFIG
840 ***************************************************************************/
841 
842 static const applefdc_interface mac_iwm_interface =
843 {
844 	sony_set_lines,
845 	sony_set_enable_lines,
846 
847 	sony_read_data,
848 	sony_write_data,
849 	sony_read_status
850 };
851 
852 static const floppy_interface mac_floppy_interface =
853 {
854 	FLOPPY_STANDARD_3_5_DSHD,
855 	LEGACY_FLOPPY_OPTIONS_NAME(apple35_mac),
856 	"floppy_3_5"
857 };
858 
INPUT_PORTS_START(macadb)859 static INPUT_PORTS_START( macadb )
860 INPUT_PORTS_END
861 
862 /***************************************************************************
863     MACHINE DRIVERS
864 ***************************************************************************/
865 
866 static void mac_nubus_cards(device_slot_interface &device)
867 {
868 	device.option_add("m2video", NUBUS_M2VIDEO);    /* Apple Macintosh II Video Card */
869 	device.option_add("48gc", NUBUS_48GC);      /* Apple 4*8 Graphics Card */
870 	device.option_add("824gc", NUBUS_824GC);    /* Apple 8*24 Graphics Card */
871 	device.option_add("cb264", NUBUS_CB264);    /* RasterOps ColorBoard 264 */
872 	device.option_add("vikbw", NUBUS_VIKBW);    /* Moniterm Viking board */
873 	device.option_add("image", NUBUS_IMAGE);    /* Disk Image Pseudo-Card */
874 	device.option_add("specpdq", NUBUS_SPECPDQ);    /* SuperMac Spectrum PDQ */
875 	device.option_add("m2hires", NUBUS_M2HIRES);    /* Apple Macintosh II Hi-Resolution Card */
876 	device.option_add("spec8s3", NUBUS_SPEC8S3);    /* SuperMac Spectrum/8 Series III */
877 //  device.option_add("thundergx", NUBUS_THUNDERGX);        /* Radius Thunder GX (not yet) */
878 	device.option_add("radiustpd", NUBUS_RADIUSTPD);        /* Radius Two Page Display */
879 	device.option_add("asmc3nb", NUBUS_ASNTMC3NB);  /* Asante MC3NB Ethernet card */
880 	device.option_add("portrait", NUBUS_WSPORTRAIT);    /* Apple Macintosh II Portrait video card */
881 	device.option_add("enetnb", NUBUS_APPLEENET);   /* Apple NuBus Ethernet */
882 	device.option_add("bootbug", NUBUS_BOOTBUG);    /* Brigent BootBug debugger card */
883 	device.option_add("quadralink", NUBUS_QUADRALINK);  /* AE Quadralink serial card */
884 	device.option_add("laserview", NUBUS_LASERVIEW);  /* Sigma Designs LaserView monochrome video card */
885 }
886 
mac_scsi_devices(device_slot_interface & device)887 static void mac_scsi_devices(device_slot_interface &device)
888 {
889 	device.option_add("harddisk", NSCSI_HARDDISK);
890 	device.option_add("cdrom", NSCSI_CDROM);
891 }
892 
macqd700(machine_config & config)893 void macquadra_state::macqd700(machine_config &config)
894 {
895 	/* basic machine hardware */
896 	M68040(config, m_maincpu, 25000000);
897 	m_maincpu->set_addrmap(AS_PROGRAM, &macquadra_state::quadra700_map);
898 
899 	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
900 	m_screen->set_refresh_hz(75.08);
901 	m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1260));
902 	m_screen->set_size(1152, 870);
903 	m_screen->set_visarea(0, 1152-1, 0, 870-1);
904 	m_screen->set_screen_update(FUNC(macquadra_state::screen_update_dafb));
905 
906 	MCFG_VIDEO_START_OVERRIDE(macquadra_state,macdafb)
907 	MCFG_VIDEO_RESET_OVERRIDE(macquadra_state,macdafb)
908 
909 	PALETTE(config, m_palette).set_entries(256);
910 
911 	RTC3430042(config, m_rtc, XTAL(32'768));
912 
913 	LEGACY_IWM(config, m_iwm, &mac_iwm_interface);
914 	sonydriv_floppy_image_device::legacy_2_drives_add(config, &mac_floppy_interface);
915 
916 	SCC85C30(config, m_scc, C7M);
917 //  m_scc->intrq_callback().set(FUNC(macquadra_state::set_scc_interrupt));
918 
919 	// SCSI bus and devices
920 	NSCSI_BUS(config, m_scsibus1);
921 	NSCSI_CONNECTOR(config, "scsi1:0", mac_scsi_devices, nullptr);
922 	NSCSI_CONNECTOR(config, "scsi1:1", mac_scsi_devices, nullptr);
923 	NSCSI_CONNECTOR(config, "scsi1:2", mac_scsi_devices, nullptr);
924 	NSCSI_CONNECTOR(config, "scsi1:3", mac_scsi_devices, nullptr);
925 	NSCSI_CONNECTOR(config, "scsi1:4", mac_scsi_devices, nullptr);
926 	NSCSI_CONNECTOR(config, "scsi1:5", mac_scsi_devices, nullptr);
927 	NSCSI_CONNECTOR(config, "scsi1:6", mac_scsi_devices, "harddisk");
928 	NSCSI_CONNECTOR(config, "scsi1:7").option_set("ncr5394", NCR53CF94).clock(24_MHz_XTAL).machine_config(
929 		[this] (device_t *device)
930 		{
931 			ncr53cf94_device &adapter = downcast<ncr53cf94_device &>(*device);
932 
933 			adapter.set_busmd(ncr53cf94_device::BUSMD_0);
934 			adapter.irq_handler_cb().set(*this, FUNC(macquadra_state::irq_539x_1_w));
935 			adapter.drq_handler_cb().set(*this, FUNC(macquadra_state::drq_539x_1_w));
936 		});
937 
938 	DP83932C(config, m_sonic, 20_MHz_XTAL);
939 	m_sonic->set_bus(m_maincpu, 0);
940 
941 	nubus_device &nubus(NUBUS(config, "nubus", 0));
942 	nubus.set_space(m_maincpu, AS_PROGRAM);
943 	nubus.out_irq9_callback().set(FUNC(macquadra_state::nubus_irq_9_w));
944 	nubus.out_irqa_callback().set(FUNC(macquadra_state::nubus_irq_a_w));
945 	nubus.out_irqb_callback().set(FUNC(macquadra_state::nubus_irq_b_w));
946 	nubus.out_irqc_callback().set(FUNC(macquadra_state::nubus_irq_c_w));
947 	nubus.out_irqd_callback().set(FUNC(macquadra_state::nubus_irq_d_w));
948 	nubus.out_irqe_callback().set(FUNC(macquadra_state::nubus_irq_e_w));
949 	NUBUS_SLOT(config, "nbd", "nubus", mac_nubus_cards, nullptr);
950 	NUBUS_SLOT(config, "nbe", "nubus", mac_nubus_cards, nullptr);
951 
952 	VIA6522(config, m_via1, C7M/10);
953 	m_via1->readpa_handler().set(FUNC(macquadra_state::mac_via_in_a));
954 	m_via1->readpb_handler().set(FUNC(macquadra_state::mac_via_in_b));
955 	m_via1->writepa_handler().set(FUNC(macquadra_state::mac_via_out_a));
956 	m_via1->writepb_handler().set(FUNC(macquadra_state::mac_via_out_b));
957 	m_via1->irq_handler().set(FUNC(macquadra_state::mac_via_irq));
958 	m_via1->cb2_handler().set(FUNC(macquadra_state::via_cb2_w));
959 
960 	VIA6522(config, m_via2, C7M/10);
961 	m_via2->readpa_handler().set(FUNC(macquadra_state::mac_via2_in_a));
962 	m_via2->readpb_handler().set(FUNC(macquadra_state::mac_via2_in_b));
963 	m_via2->writepa_handler().set(FUNC(macquadra_state::mac_via2_out_a));
964 	m_via2->writepb_handler().set(FUNC(macquadra_state::mac_via2_out_b));
965 	m_via2->irq_handler().set(FUNC(macquadra_state::mac_via2_irq));
966 
967 	MACADB(config, m_macadb, C15M);
968 	m_macadb->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1));
969 	m_macadb->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2));
970 	m_macadb->adb_irq_callback().set(FUNC(macquadra_state::adb_irq_w));
971 
972 	SPEAKER(config, "lspeaker").front_left();
973 	SPEAKER(config, "rspeaker").front_right();
974 	ASC(config, m_easc, C15M, asc_device::asc_type::EASC);
975 //  m_easc->irqf_callback().set(FUNC(macquadra_state::mac_asc_irq));
976 	m_easc->add_route(0, "lspeaker", 1.0);
977 	m_easc->add_route(1, "rspeaker", 1.0);
978 
979 	/* internal ram */
980 	RAM(config, m_ram);
981 	m_ram->set_default_size("4M");
982 	m_ram->set_extra_options("8M,16M,32M,64M,68M,72M,80M,96M,128M");
983 
984 	SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop");
985 }
986 
987 ROM_START( macqd700 )
988 	ROM_REGION32_BE(0x100000, "bootrom", 0)
989 	ROM_LOAD( "420dbff3.rom", 0x000000, 0x100000, CRC(88ea2081) SHA1(7a8ee468d16e64f2ad10cb8d1a45e6f07cc9e212) )
990 ROM_END
991 
992 COMP( 1991, macqd700, 0, 0, macqd700, macadb, macquadra_state, init_macqd700,  "Apple Computer", "Macintosh Quadra 700", MACHINE_NOT_WORKING )
993