1 // license:BSD-3-Clause
2 // copyright-holders:Phill Harvey-Smith, Carl
3 /*
4     machine/rmnimbus.c
5 
6     Machine driver for the Research Machines Nimbus.
7 
8     Phill Harvey-Smith
9     2009-11-29.
10 
11 */
12 
13 /*
14 
15     SCSI/SASI drives supported by RM Nimbus machines
16 
17 Native SCSI - format with HDFORM.EXE
18 
19 Drive           Capacity    Tracks  Heads   Sec/Track       Blocks
20 RO652-20        20MB        306     4       34              41616
21 ST225N          20MB        615     4       17              41721
22 ST125N          20MB        407     4       26              41921
23 8425S-30        20MB                                        41004
24 CP3020          20MB        623     2       33              41118
25 ST225NP         20MB        615     4       17              41720
26 CP3040          40MB        1026    2       40              82080
27 
28 Via Xebec S1410 SASI to MFM bridge board - format with WINFORM.EXE
29 NP05-10S         8MB        160     6       17              16320
30 NP04-20T        16MB        320     6       17              32640
31 NP03-20         15MB        306     6       17              31212
32 R352-10         10MB        306     4       17              20808
33 NP04-50         40MB        699     7       17              83181
34 NP04-55         44MB        754     7       17              89726
35 
36 Via Adaptec ACB4070 SCSI to RLL bridge board - format with ADAPT.EXE
37 NEC D5147       60MB        615     8       26              127920
38 ST227R          60MB        820     6       26              127920
39 
40 After formating, the drives need to have a partition table put on them with
41 STAMP.EXE and then formatted in the normal way for a dos system drive with
42 Format /s.
43 
44 The tracks, heads and sectors/track can be used with chdman createhd
45 to create a blank hard disk which can then be formatted with the RM tools.
46 The important thing when doing this is to make sure that if using the Native
47 SCSI tools, that the disk has the  same number of blocks as specified above,
48 even if you have to use unusual geometry to do so !
49 Currently, only the ST225N and ST125N can be formatted as the other native
50 drives and Xebec board expect the WRITE BUFFER (0x3B) and READ BUFFER (0x3C)
51 with mode 0 commands to be implemented and the Adaptec board uses unknown
52 command 0xE4.
53 
54 
55 for example:
56 
57 chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
58 (the actual geometry can't be used because the block count won't match)
59 
60 */
61 
62 #include "emu.h"
63 #include <functional>
64 
65 #include "includes/rmnimbus.h"
66 #include "debugger.h"
67 #include "debug/debugcon.h"
68 #include "debug/debugcpu.h"
69 #include "imagedev/floppy.h"
70 
71 
72 
73 /*-------------------------------------------------------------------------*/
74 /* Defines, constants, and global variables                                */
75 /*-------------------------------------------------------------------------*/
76 
77 /* External int vectors for chained interrupts */
78 #define EXTERNAL_INT_DISK       0x80
79 #define EXTERNAL_INT_MSM5205    0x84
80 #define EXTERNAL_INT_MOUSE_YU   0x88
81 #define EXTERNAL_INT_MOUSE_YD   0x89
82 #define EXTERNAL_INT_MOUSE_XL   0x8A
83 #define EXTERNAL_INT_MOUSE_XR   0x8B
84 #define EXTERNAL_INT_PC8031_8C  0x8c
85 #define EXTERNAL_INT_PC8031_8E  0x8E
86 #define EXTERNAL_INT_PC8031_8F  0x8F
87 
88 #define HDC_DRQ_MASK        0x40
89 #define FDC_SIDE()          ((m_nimbus_drives.reg400 & 0x10) >> 4)
90 #define FDC_MOTOR()         ((m_nimbus_drives.reg400 & 0x20) >> 5)
91 #define FDC_DRIVE()         (fdc_driveno(m_nimbus_drives.reg400 & 0x0f))
92 #define HDC_DRQ_ENABLED()   ((m_nimbus_drives.reg400 & 0x40) ? 1 : 0)
93 #define FDC_DRQ_ENABLED()   ((m_nimbus_drives.reg400 & 0x80) ? 1 : 0)
94 
95 /* 8031/8051 Peripheral controller */
96 
97 #define IPC_OUT_ADDR        0x01
98 #define IPC_OUT_READ_PEND   0x02
99 #define IPC_OUT_BYTE_AVAIL  0x04
100 
101 #define IPC_IN_ADDR         0x01
102 #define IPC_IN_BYTE_AVAIL   0x02
103 #define IPC_IN_READ_PEND    0x04
104 
105 /* IO unit */
106 
107 #define DISK_INT_ENABLE         0x01
108 #define MSM5205_INT_ENABLE      0x04
109 #define MOUSE_INT_ENABLE        0x08
110 #define PC8031_INT_ENABLE       0x10
111 
112 enum
113 {
114 	MOUSE_PHASE_STATIC = 0,
115 	MOUSE_PHASE_POSITIVE,
116 	MOUSE_PHASE_NEGATIVE
117 };
118 
119 #define MOUSE_INT_ENABLED(state)     (((state)->m_iou_reg092 & MOUSE_INT_ENABLE) ? 1 : 0)
120 
121 #define LINEAR_ADDR(seg,ofs)    ((seg<<4)+ofs)
122 
123 #define OUTPUT_SEGOFS(mess,seg,ofs)  logerror("%s=%04X:%04X [%08X]\n",mess,seg,ofs,((seg<<4)+ofs))
124 
125 #define LOG_SIO             0
126 #define LOG_DISK_HDD        0
127 #define LOG_DISK            0
128 #define LOG_PC8031          0
129 #define LOG_PC8031_186      0
130 #define LOG_PC8031_PORT     0
131 #define LOG_IOU             0
132 #define LOG_RAM             0
133 
134 /* Debugging */
135 
136 #define DEBUG_SET(flags)    ((m_debug_machine & (flags))==(flags))
137 #define DEBUG_SET_STATE(flags)    ((state->m_debug_machine & (flags))==(flags))
138 
139 #define DEBUG_NONE          0x0000000
140 #define DECODE_BIOS         0x0000002
141 #define DECODE_BIOS_RAW     0x0000004
142 #define DECODE_DOS21        0x0000008
143 
144 /* Nimbus sub-bios structures for debugging */
145 
146 struct t_area_params
147 {
148 	uint16_t  ofs_brush;
149 	uint16_t  seg_brush;
150 	uint16_t  ofs_data;
151 	uint16_t  seg_data;
152 	uint16_t  count;
153 };
154 
155 struct t_plot_string_params
156 {
157 	uint16_t  ofs_font;
158 	uint16_t  seg_font;
159 	uint16_t  ofs_data;
160 	uint16_t  seg_data;
161 	uint16_t  x;
162 	uint16_t  y;
163 	uint16_t  length;
164 };
165 
166 struct t_nimbus_brush
167 {
168 	uint16_t  style;
169 	uint16_t  style_index;
170 	uint16_t  colour1;
171 	uint16_t  colour2;
172 	uint16_t  transparency;
173 	uint16_t  boundary_spec;
174 	uint16_t  boundary_colour;
175 	uint16_t  save_colour;
176 };
177 
178 
179 static int instruction_hook(device_t &device, offs_t curpc);
180 
external_int(uint8_t vector,bool state)181 void rmnimbus_state::external_int(uint8_t vector, bool state)
182 {
183 	if(!state && (vector != m_vector))
184 		return;
185 
186 	m_vector = vector;
187 
188 	m_maincpu->int0_w(state);
189 }
190 
cascade_callback()191 uint8_t rmnimbus_state::cascade_callback()
192 {
193 	m_maincpu->int0_w(0);
194 	return !m_vector ? m_z80sio->m1_r() : m_vector;
195 }
196 
machine_reset()197 void rmnimbus_state::machine_reset()
198 {
199 	/* CPU */
200 	iou_reset();
201 	fdc_reset();
202 	hdc_reset();
203 	pc8031_reset();
204 	rmni_sound_reset();
205 	memory_reset();
206 	mouse_js_reset();
207 
208 	/* USER VIA 6522 port B is connected to the BBC user port */
209 	m_via->write_pb(0xff);
210 }
211 
machine_start()212 void rmnimbus_state::machine_start()
213 {
214 	m_nimbus_mouse.m_mouse_timer=timer_alloc(TIMER_MOUSE);
215 
216 	/* setup debug commands */
217 	if (machine().debug_flags & DEBUG_FLAG_ENABLED)
218 	{
219 		using namespace std::placeholders;
220 		machine().debugger().console().register_command("nimbus_debug", CMDFLAG_NONE, 0, 0, 1, std::bind(&rmnimbus_state::debug_command, this, _1, _2));
221 
222 		/* set up the instruction hook */
223 		m_maincpu->debug()->set_instruction_hook(instruction_hook);
224 	}
225 
226 	m_debug_machine=DEBUG_NONE;
227 	m_fdc->dden_w(0);
228 }
229 
debug_command(int ref,const std::vector<std::string> & params)230 void rmnimbus_state::debug_command(int ref, const std::vector<std::string> &params)
231 {
232 	if (params.size() > 0)
233 	{
234 		int temp;
235 		sscanf(params[0].c_str(), "%d", &temp);
236 		m_debug_machine = temp;
237 	}
238 	else
239 	{
240 		machine().debugger().console().printf("Error usage : nimbus_debug <debuglevel>\n");
241 		machine().debugger().console().printf("Current debuglevel=%02X\n", m_debug_machine);
242 	}
243 }
244 
245 /*-----------------------------------------------
246     instruction_hook - per-instruction hook
247 -----------------------------------------------*/
248 
instruction_hook(device_t & device,offs_t curpc)249 static int instruction_hook(device_t &device, offs_t curpc)
250 {
251 	rmnimbus_state  *state = device.machine().driver_data<rmnimbus_state>();
252 	address_space   &space = device.memory().space(AS_PROGRAM);
253 	uint8_t           *addr_ptr;
254 
255 	addr_ptr = (uint8_t*)space.get_read_ptr(curpc);
256 
257 	if ((addr_ptr !=nullptr) && (addr_ptr[0]==0xCD))
258 	{
259 		if(DEBUG_SET_STATE(DECODE_BIOS) && (addr_ptr[1]==0xF0))
260 		{
261 			if(DEBUG_SET_STATE(DECODE_BIOS_RAW))
262 				state->decode_subbios(&device,curpc,1);
263 			else
264 				state->decode_subbios(&device,curpc,0);
265 		}
266 
267 		if(DEBUG_SET_STATE(DECODE_DOS21) && (addr_ptr[1]==0x21))
268 			state->decode_dos21(&device,curpc);
269 	}
270 
271 	return 0;
272 }
273 
274 #define set_type(type_name)     sprintf(type_str,type_name)
275 #define set_drv(drv_name)       sprintf(drv_str,drv_name)
276 #define set_func(func_name)     sprintf(func_str,func_name)
277 
decode_subbios(device_t * device,offs_t pc,uint8_t raw_flag)278 void rmnimbus_state::decode_subbios(device_t *device,offs_t pc, uint8_t raw_flag)
279 {
280 	char    type_str[80];
281 	char    drv_str[80];
282 	char    func_str[80];
283 
284 	void (rmnimbus_state::*dump_dssi)(uint16_t, uint16_t, uint8_t) = &rmnimbus_state::decode_dssi_none;
285 
286 	uint16_t  ax = m_maincpu->state_int(I8086_AX);
287 	uint16_t  bx = m_maincpu->state_int(I8086_BX);
288 	uint16_t  cx = m_maincpu->state_int(I8086_CX);
289 	uint16_t  ds = m_maincpu->state_int(I8086_DS);
290 	uint16_t  si = m_maincpu->state_int(I8086_SI);
291 
292 	// *** TEMP Don't show f_enquire_display_line calls !
293 	if((cx==6) && (ax==43))
294 		return;
295 	// *** END TEMP
296 
297 	if(!raw_flag)
298 	{
299 		logerror("=======================================================================\n");
300 		logerror("Sub-bios call at %08X, AX=%04X, BX=%04X, CX=%04X, DS:SI=%04X:%04X\n",pc,ax,bx,cx,ds,si);
301 	}
302 
303 	set_type("invalid");
304 	set_drv("invalid");
305 	set_func("invalid");
306 
307 	switch (cx)
308 	{
309 		case 0   :
310 		{
311 			set_type("t_mummu");
312 			set_drv("d_mummu");
313 
314 			switch (ax)
315 			{
316 				case 0  : set_func("f_get_version_number"); break;
317 				case 1  : set_func("f_add_type_code"); break;
318 				case 2  : set_func("f_del_typc_code"); break;
319 				case 3  : set_func("f_get_TCB"); break;
320 				case 4  : set_func("f_add_driver_code"); break;
321 				case 5  : set_func("f_del_driver_code"); break;
322 				case 6  : set_func("f_get_DCB"); break;
323 				case 7  : set_func("f_get_copyright"); break;
324 			}
325 		}; break;
326 
327 		case 1   :
328 		{
329 			set_type("t_character");
330 			set_drv("d_printer");
331 
332 			switch(ax)
333 			{
334 				case 0  : set_func("f_get_version_number"); break;
335 				case 1  : set_func("f_get_output_status"); break;
336 				case 2  : set_func("f_output_character"); break;
337 				case 3  : set_func("f_get_input_status"); break;
338 				case 4  : set_func("f_get_and_remove"); break;
339 				case 5  : set_func("f_get_no_remove"); break;
340 				case 6  : set_func("f_get_last_and_remove"); break;
341 				case 7  : set_func("f_get_last_no_remove"); break;
342 				case 8  : set_func("f_set_IO_parameters"); break;
343 			}
344 		}; break;
345 
346 		case 2   :
347 		{
348 			set_type("t_disk");
349 
350 			switch(bx)
351 			{
352 				case 0  : set_drv("d_floppy"); break;
353 				case 1  : set_drv("d_winchester"); break;
354 				case 2  : set_drv("d_tape"); break;
355 				case 3  : set_drv("d_rompack"); break;
356 				case 4  : set_drv("d_eeprom"); break;
357 			}
358 
359 			switch(ax)
360 			{
361 				case 0  : set_func("f_get_version_number"); break;
362 				case 1  : set_func("f_initialise_unit"); break;
363 				case 2  : set_func("f_pseudo_init_unit"); break;
364 				case 3  : set_func("f_get_device_status"); break;
365 				case 4  : set_func("f_read_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
366 				case 5  : set_func("f_write_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
367 				case 6  : set_func("f_verify_n_sectors"); break;
368 				case 7  : set_func("f_media_check"); break;
369 				case 8  : set_func("f_recalibrate"); break;
370 				case 9  : set_func("f_motors_off"); break;
371 			}
372 			dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors;
373 
374 		}; break;
375 
376 		case 3   :
377 		{
378 			set_type("t_piconet");
379 			set_drv("d_piconet");
380 
381 			switch(ax)
382 			{
383 				case 0  : set_func("f_get_version_number"); break;
384 				case 1  : set_func("f_get_slave_status"); break;
385 				case 2  : set_func("f_get_slave_map"); break;
386 				case 3  : set_func("f_change_slave_addr"); break;
387 				case 4  : set_func("f_read_slave_control"); break;
388 				case 5  : set_func("f_write_slave_control"); break;
389 				case 6  : set_func("f_send_data_byte"); break;
390 				case 7  : set_func("f_request_data_byte"); break;
391 				case 8  : set_func("f_send_data_block"); break;
392 				case 9  : set_func("f_request_data_block"); break;
393 				case 10 : set_func("f_reset_slave"); break;
394 
395 			}
396 		}; break;
397 
398 		case 4   :
399 		{
400 			set_type("t_tick");
401 			set_drv("d_tick");
402 
403 			switch(ax)
404 			{
405 				case 0  : set_func("f_get_version_number"); break;
406 				case 1  : set_func("f_ticks_per_second"); break;
407 				case 2  : set_func("f_link_tick_routine"); break;
408 				case 3  : set_func("f_unlink_tick_routine"); break;
409 			}
410 		}; break;
411 
412 		case 5   :
413 		{
414 			set_type("t_graphics_input");
415 
416 			switch(bx)
417 			{
418 				case 0  : set_drv("d_mouse"); break;
419 				case 1  : set_drv("d_joystick_1"); break;
420 				case 2  : set_drv("d_joystick_2"); break;
421 			}
422 
423 
424 			switch(ax)
425 			{
426 				case 0  : set_func("f_get_version_number"); break;
427 				case 1  : set_func("f_graphics_input_cold_start"); break;
428 				case 2  : set_func("f_graphics_input_device_off"); break;
429 				case 3  : set_func("f_return_button_status"); break;
430 				case 4  : set_func("f_return_switch_and_button_stat"); break;
431 				case 5  : set_func("f_start_tracking"); break;
432 				case 6  : set_func("f_stop_tracking"); break;
433 				case 7  : set_func("f_enquire_position"); break;
434 				case 8  : set_func("f_set_position"); break;
435 
436 				case 10 : set_func("f_return_button_press_info"); break;
437 				case 11 : set_func("f_return_button_release_info"); break;
438 				case 12 : set_func("f_set_gain/f_set_squeaks_per_pixel_ratio"); break;
439 				case 13 : set_func("f_enquire_graphics_in_misc_data"); break;
440 			}
441 		}; break;
442 
443 		case 6   :
444 		{
445 			set_type("t_graphics_output");
446 			set_drv("d_ngc_screen");
447 
448 			switch(ax)
449 			{
450 				case 0  : set_func("f_get_version_number");                 break;
451 				case 1  : set_func("f_graphics_output_cold_start");         break;
452 				case 2  : set_func("f_graphics_output_warm_start");         break;
453 				case 3  : set_func("f_graphics_output_off");                break;
454 				case 4  : set_func("f_reinit_graphics_output");             break;
455 				case 5  : set_func("f_polymarker");                         break;
456 				case 6  : set_func("f_polyline"); dump_dssi = &rmnimbus_state::decode_dssi_f_fill_area; break;
457 				case 7  : set_func("f_fill_area"); dump_dssi = &rmnimbus_state::decode_dssi_f_fill_area; break;
458 				case 8  : set_func("f_flood_fill_area"); break;
459 				case 9  : set_func("f_plot_character_string"); dump_dssi = &rmnimbus_state::decode_dssi_f_plot_character_string; break;
460 				case 10 : set_func("f_define_graphics_clipping_area"); break;
461 				case 11 : set_func("f_enquire_clipping_area_limits"); break;
462 				case 12 : set_func("f_select_graphics_clipping_area"); break;
463 				case 13 : set_func("f_enq_selctd_graphics_clip_area"); break;
464 				case 14 : set_func("f_set_clt_element"); break;
465 				case 15 : set_func("f_enquire_clt_element"); break;
466 				case 16 : set_func("f_set_new_clt"); dump_dssi = &rmnimbus_state::decode_dssi_f_set_new_clt; break;
467 				case 17 : set_func("f_enquire_clt_contents"); break;
468 				case 18 : set_func("f_define_dithering_pattern"); break;
469 				case 19 : set_func("f_enquire_dithering_pattern"); break;
470 				case 20 : set_func("f_draw_sprite"); break;
471 				case 21 : set_func("f_move_sprite"); break;
472 				case 22 : set_func("f_erase_sprite"); break;
473 				case 23 : set_func("f_read_pixel"); break;
474 				case 24 : set_func("f_read_to_limit"); break;
475 				case 25 : set_func("f_read_area_pixel"); break;
476 				case 26 : set_func("f_write_area_pixel"); break;
477 				case 27 : set_func("f_copy_area_pixel"); break;
478 
479 				case 29 : set_func("f_read_area_word"); break;
480 				case 30 : set_func("f_write_area_word"); break;
481 				case 31 : set_func("f_copy_area_word"); break;
482 				case 32 : set_func("f_swap_area_word"); break;
483 				case 33 : set_func("f_set_border_colour"); break;
484 				case 34 : set_func("f_enquire_border_colour"); break;
485 				case 35 : set_func("f_enquire_miscellaneous_data"); break;
486 				case 36  : set_func("f_circle"); break;
487 
488 				case 38 : set_func("f_arc_of_ellipse"); break;
489 				case 39 : set_func("f_isin"); break;
490 				case 40 : set_func("f_icos"); break;
491 				case 41 : set_func("f_define_hatching_pattern"); break;
492 				case 42 : set_func("f_enquire_hatching_pattern"); break;
493 				case 43 : set_func("f_enquire_display_line"); break;
494 				case 44 : set_func("f_plonk_logo"); break;
495 			}
496 		}; break;
497 
498 		case 7   :
499 		{
500 			set_type("t_zend");
501 			switch(ax)
502 			{
503 				case 0  : set_func("f_get_version_number"); break;
504 			}
505 		}; break;
506 
507 		case 8   :
508 		{
509 			set_type("t_zep");
510 			switch(ax)
511 			{
512 				case 0  : set_func("f_get_version_number"); break;
513 			}
514 		}; break;
515 
516 		case 9   :
517 		{
518 			set_type("t_raw_console");
519 
520 			switch(bx)
521 			{
522 				case 0  :
523 				{
524 					set_drv("d_screen");
525 
526 					switch(ax)
527 					{
528 						case 0  : set_func("f_get_version_number"); break;
529 						case 1  : set_func("f_plonk_char"); dump_dssi = &rmnimbus_state::decode_dssi_f_plonk_char; break;
530 						case 2  : set_func("f_plonk_cursor"); break;
531 						case 3  : set_func("f_kill_cursor"); break;
532 						case 4  : set_func("f_scroll"); break;
533 						case 5  : set_func("f_width"); dump_dssi = &rmnimbus_state::decode_dssi_generic; break;
534 						case 6  : set_func("f_get_char_set"); break;
535 						case 7  : set_func("f_set_char_set"); break;
536 						case 8  : set_func("f_reset_char_set"); break;
537 						case 9  : set_func("f_set_plonk_parameters"); break;
538 						case 10 : set_func("f_set_cursor_flash_rate"); break;
539 					}
540 				}; break;
541 
542 				case 1  :
543 				{
544 					set_drv("d_keyboard");
545 
546 					switch(ax)
547 					{
548 						case 0  : set_func("f_get_version_number"); break;
549 						case 1  : set_func("f_init_keyboard"); break;
550 						case 2  : set_func("f_get_last_key_code"); break;
551 						case 3  : set_func("f_get_bitmap"); break;
552 					}
553 				}; break;
554 			}
555 		}; break;
556 
557 		case 10   :
558 		{
559 			set_type("t_acoustics");
560 
561 			switch(bx)
562 			{
563 				case 0  :
564 				{
565 					set_drv("d_sound");
566 
567 					switch(ax)
568 					{
569 						case 0  : set_func("f_get_version_number"); break;
570 						case 1  : set_func("f_sound_enable"); break;
571 						case 2  : set_func("f_play_note"); break;
572 						case 3  : set_func("f_get_queue_status"); break;
573 					}
574 				}; break;
575 
576 				case 1  :
577 				{
578 					set_drv("d_voice");
579 
580 					switch(ax)
581 					{
582 						case 0  : set_func("f_get_version_number"); break;
583 						case 1  : set_func("f_talk"); break;
584 						case 2  : set_func("f_wait_and_talk"); break;
585 						case 3  : set_func("f_test_talking"); break;
586 					}
587 				}
588 			}
589 		}; break;
590 
591 		case 11   :
592 		{
593 			set_type("t_hard_sums");
594 			switch(ax)
595 			{
596 				case 0  : set_func("f_get_version_number"); break;
597 			}
598 		}; break;
599 	}
600 
601 	if(raw_flag)
602 	{
603 		(this->*dump_dssi)(ds, si, raw_flag);
604 	}
605 	else
606 	{
607 		logerror("Type=%s, Driver=%s, Function=%s\n",type_str,drv_str,func_str);
608 
609 		(this->*dump_dssi)(ds, si, raw_flag);
610 		logerror("=======================================================================\n");
611 	}
612 }
613 
get_dssi_ptr(address_space & space,uint16_t ds,uint16_t si)614 static inline void *get_dssi_ptr(address_space &space, uint16_t   ds, uint16_t si)
615 {
616 	int             addr;
617 
618 	addr=((ds<<4)+si);
619 //    OUTPUT_SEGOFS("DS:SI",ds,si);
620 
621 	return space.get_read_ptr(addr);
622 }
623 
decode_dssi_none(uint16_t ds,uint16_t si,uint8_t raw_flag)624 void rmnimbus_state::decode_dssi_none(uint16_t ds, uint16_t si, uint8_t raw_flag)
625 {
626 }
627 
decode_dssi_generic(uint16_t ds,uint16_t si,uint8_t raw_flag)628 void rmnimbus_state::decode_dssi_generic(uint16_t ds, uint16_t si, uint8_t raw_flag)
629 {
630 	address_space &space = m_maincpu->space(AS_PROGRAM);
631 	uint16_t  *params;
632 	int     count;
633 
634 	if(raw_flag)
635 		return;
636 
637 	params=(uint16_t  *)get_dssi_ptr(space,ds,si);
638 
639 	for(count=0; count<10; count++)
640 		logerror("%04X ",params[count]);
641 
642 	logerror("\n");
643 }
644 
645 
decode_dssi_f_fill_area(uint16_t ds,uint16_t si,uint8_t raw_flag)646 void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si, uint8_t raw_flag)
647 {
648 	address_space &space = m_maincpu->space(AS_PROGRAM);
649 
650 	uint16_t          *addr_ptr;
651 	t_area_params   *area_params;
652 	t_nimbus_brush  *brush;
653 	int             cocount;
654 
655 	area_params = (t_area_params   *)get_dssi_ptr(space,ds,si);
656 
657 	if (!raw_flag)
658 		OUTPUT_SEGOFS("SegBrush:OfsBrush",area_params->seg_brush,area_params->ofs_brush);
659 
660 	brush=(t_nimbus_brush  *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_brush,area_params->ofs_brush));
661 
662 	if(raw_flag)
663 	{
664 		logerror("\tdw\t%04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, ",
665 					brush->style,brush->style_index,brush->colour1,brush->colour2,
666 					brush->transparency,brush->boundary_spec,brush->boundary_colour,brush->save_colour,
667 					area_params->count);
668 	}
669 	else
670 	{
671 		logerror("Brush params\n");
672 		logerror("Style=%04X,          StyleIndex=%04X\n",brush->style,brush->style_index);
673 		logerror("Colour1=%04X,        Colour2=%04X\n",brush->colour1,brush->colour2);
674 		logerror("transparency=%04X,   boundary_spec=%04X\n",brush->transparency,brush->boundary_spec);
675 		logerror("boundary colour=%04X, save colour=%04X\n",brush->boundary_colour,brush->save_colour);
676 
677 
678 		OUTPUT_SEGOFS("SegData:OfsData",area_params->seg_data,area_params->ofs_data);
679 	}
680 
681 	addr_ptr = (uint16_t *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_data,area_params->ofs_data));
682 	for(cocount=0; cocount < area_params->count; cocount++)
683 	{
684 		if(raw_flag)
685 		{
686 			if(cocount!=(area_params->count-1))
687 				logerror("%04X, %04X, ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
688 			else
689 				logerror("%04X, %04X ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
690 		}
691 		else
692 			logerror("x=%d y=%d\n",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
693 	}
694 
695 	if(raw_flag)
696 		logerror("\n");
697 }
698 
decode_dssi_f_plot_character_string(uint16_t ds,uint16_t si,uint8_t raw_flag)699 void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si, uint8_t raw_flag)
700 {
701 	address_space &space = m_maincpu->space(AS_PROGRAM);
702 
703 	uint8_t                   *char_ptr;
704 	t_plot_string_params    *plot_string_params;
705 	int                     charno;
706 
707 	if(raw_flag)
708 		return;
709 
710 	plot_string_params=(t_plot_string_params   *)get_dssi_ptr(space,ds,si);
711 
712 	OUTPUT_SEGOFS("SegFont:OfsFont",plot_string_params->seg_font,plot_string_params->ofs_font);
713 	OUTPUT_SEGOFS("SegData:OfsData",plot_string_params->seg_data,plot_string_params->ofs_data);
714 
715 	logerror("x=%d, y=%d, length=%d\n",plot_string_params->x,plot_string_params->y,plot_string_params->length);
716 
717 	char_ptr=(uint8_t*)space.get_read_ptr(LINEAR_ADDR(plot_string_params->seg_data,plot_string_params->ofs_data));
718 
719 	if (plot_string_params->length==0xFFFF)
720 		logerror("%s",char_ptr);
721 	else
722 		for(charno=0;charno<plot_string_params->length;charno++)
723 			logerror("%c",char_ptr[charno]);
724 
725 	logerror("\n");
726 }
727 
decode_dssi_f_set_new_clt(uint16_t ds,uint16_t si,uint8_t raw_flag)728 void rmnimbus_state::decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si, uint8_t raw_flag)
729 {
730 	address_space &space = m_maincpu->space(AS_PROGRAM);
731 	uint16_t  *new_colours;
732 	int     colour;
733 	new_colours=(uint16_t  *)get_dssi_ptr(space,ds,si);
734 
735 	if(raw_flag)
736 		return;
737 
738 	OUTPUT_SEGOFS("SegColours:OfsColours",ds,si);
739 
740 	for(colour=0;colour<16;colour++)
741 		logerror("colour #%02X=%04X\n",colour,new_colours[colour]);
742 
743 }
744 
decode_dssi_f_plonk_char(uint16_t ds,uint16_t si,uint8_t raw_flag)745 void rmnimbus_state::decode_dssi_f_plonk_char(uint16_t ds, uint16_t si, uint8_t raw_flag)
746 {
747 	address_space &space = m_maincpu->space(AS_PROGRAM);
748 	uint16_t  *params;
749 	params=(uint16_t  *)get_dssi_ptr(space,ds,si);
750 
751 	if(raw_flag)
752 		return;
753 
754 	OUTPUT_SEGOFS("SegParams:OfsParams",ds,si);
755 
756 	logerror("plonked_char=%c\n",params[0]);
757 }
758 
decode_dssi_f_rw_sectors(uint16_t ds,uint16_t si,uint8_t raw_flag)759 void rmnimbus_state::decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si, uint8_t raw_flag)
760 {
761 	address_space &space = m_maincpu->space(AS_PROGRAM);
762 	uint16_t  *params;
763 	int     param_no;
764 
765 	if(raw_flag)
766 		return;
767 
768 	params=(uint16_t  *)get_dssi_ptr(space,ds,si);
769 
770 	for(param_no=0;param_no<16;param_no++)
771 		logerror("%04X ",params[param_no]);
772 
773 	logerror("\n");
774 }
775 
decode_dos21(device_t * device,offs_t pc)776 void rmnimbus_state::decode_dos21(device_t *device,offs_t pc)
777 {
778 	uint16_t  ax = m_maincpu->state_int(I8086_AX);
779 	uint16_t  bx = m_maincpu->state_int(I8086_BX);
780 	uint16_t  cx = m_maincpu->state_int(I8086_CX);
781 	uint16_t  dx = m_maincpu->state_int(I8086_DX);
782 	uint16_t  cs = m_maincpu->state_int(I8086_CS);
783 	uint16_t  ds = m_maincpu->state_int(I8086_DS);
784 	uint16_t  es = m_maincpu->state_int(I8086_ES);
785 	uint16_t  ss = m_maincpu->state_int(I8086_SS);
786 
787 	uint16_t  si = m_maincpu->state_int(I8086_SI);
788 	uint16_t  di = m_maincpu->state_int(I8086_DI);
789 	uint16_t  bp = m_maincpu->state_int(I8086_BP);
790 
791 	logerror("=======================================================================\n");
792 	logerror("DOS Int 0x21 call at %05X\n",pc);
793 	logerror("AX=%04X, BX=%04X, CX=%04X, DX=%04X\n",ax,bx,cx,dx);
794 	logerror("CS=%04X, DS=%04X, ES=%04X, SS=%04X\n",cs,ds,es,ss);
795 	logerror("SI=%04X, DI=%04X, BP=%04X\n",si,di,bp);
796 	logerror("=======================================================================\n");
797 }
798 
799 
800 /*
801     The Nimbus has 3 banks of memory each of which can be either 16x4164 or 16x41256 giving
802     128K or 512K per bank. These banks are as follows :
803 
804     bank0   on nimbus motherboard.
805     bank1   first half of expansion card.
806     bank2   second half of expansion card.
807 
808     The valid combinations are :
809 
810     bank0       bank1       bank2       total
811     128K                                128K
812     128K        128K                    256K
813     128K        128K        128K        384K
814     128K        512K                    640K (1)
815     512K        128K                    640K (2)
816     512K        512K                    1024K
817     512K        512K        512K        1536K
818 
819     It will be noted that there are two possible ways of getting 640K, we emulate method 2
820     (above).
821 
822     To allow for the greatest flexibility, the Nimbus allows 4 methods of mapping the
823     banks of ram into the 1M addressable by the 81086.
824 
825     With only 128K banks present, they are mapped into the first 3 blocks of 128K in
826     the memory map giving a total of up to 384K.
827 
828     If any of the blocks are 512K, then the block size is set to 512K and the map arranged
829     so that the bottom block is a 512K block (if both 512K and 128K blocks are available).
830 
831     This is all determined by the value written to port 80 :-
832 
833     port80 = 0x07   start       end
834         block0      0x00000     0x1FFFF
835         block1      0x20000     0x3FFFF
836         block2      0x40000     0x5FFFF
837 
838     port80 = 0x1F
839         block0      0x00000     0x7FFFF
840         block1      0x80000     0xEFFFF (0x9FFFF if 128K (2))
841 
842     port80 = 0x0F
843         block1      0x00000     0x7FFFF
844         block0      0x80000     0xEFFFF (0x9FFFF if 128K (1))
845 
846     port80 = 0x17
847         block1      0x00000     0x7FFFF
848         block2      0x80000     0xEFFFF
849 
850 */
851 
852 struct nimbus_meminfo
853 {
854 	offs_t  start;      /* start address of bank */
855 	offs_t  end;        /* End address of bank */
856 };
857 
858 static const struct nimbus_meminfo memmap[] =
859 {
860 	{ 0x00000, 0x1FFFF },
861 	{ 0x20000, 0x3FFFF },
862 	{ 0x40000, 0x5FFFF },
863 	{ 0x60000, 0x7FFFF },
864 	{ 0x80000, 0x9FFFF },
865 	{ 0xA0000, 0xBFFFF },
866 	{ 0xC0000, 0xDFFFF },
867 	{ 0xE0000, 0xEFFFF }
868 };
869 
870 struct nimbus_block
871 {
872 	int     blockbase;
873 	int     blocksize;
874 };
875 
876 typedef nimbus_block nimbus_blocks[3];
877 
878 static const nimbus_blocks ramblocks[] =
879 {
880 	{{ 0, 128 },    { 000, 000 },   { 000, 000 }} ,
881 	{{ 0, 128 },    { 128, 128 },   { 000, 000 }} ,
882 	{{ 0, 128 },    { 128, 128 },   { 256, 128 }} ,
883 	{{ 0, 512 },    { 000, 000 },   { 000, 000 }} ,
884 	{{ 0, 512 },    { 512, 128 },   { 000, 000 }} ,
885 	{{ 0, 512 },    { 512, 512 },   { 000, 000 }} ,
886 	{{ 0, 512 },    { 512, 512 },   { 1024, 512 } }
887 };
888 
nimbus_bank_memory()889 void rmnimbus_state::nimbus_bank_memory()
890 {
891 	address_space &space = m_maincpu->space(AS_PROGRAM);
892 	int     ramsize = m_ram->size();
893 	int     ramblock = 0;
894 	int     blockno;
895 	char    bank[10];
896 	uint8_t   *ram    = &m_ram->pointer()[0];
897 	uint8_t   *map_blocks[3];
898 	uint8_t   *map_base;
899 	int     map_blockno;
900 	int     block_ofs;
901 
902 	uint8_t   ramsel = (m_mcu_reg080 & 0x1F);
903 
904 	// Invalid ramsel, return.
905 	if((ramsel & 0x07)!=0x07)
906 		return;
907 
908 	switch (ramsize / 1024)
909 	{
910 		case 128    : ramblock=0; break;
911 		case 256    : ramblock=1; break;
912 		case 384    : ramblock=2; break;
913 		case 512    : ramblock=3; break;
914 		case 640    : ramblock=4; break;
915 		case 1024   : ramblock=5; break;
916 		case 1536   : ramblock=6; break;
917 	}
918 
919 	map_blocks[0]  = ram;
920 	map_blocks[1]  = (ramblocks[ramblock][1].blocksize==0) ? nullptr : &ram[ramblocks[ramblock][1].blockbase*1024];
921 	map_blocks[2]  = (ramblocks[ramblock][2].blocksize==0) ? nullptr : &ram[ramblocks[ramblock][2].blockbase*1024];
922 
923 	//if(LOG_RAM) logerror("\n\nmcu_reg080=%02X, ramblock=%d, map_blocks[0]=%X, map_blocks[1]=%X, map_blocks[2]=%X\n",m_mcu_reg080,ramblock,(int)map_blocks[0],(int)map_blocks[1],(int)map_blocks[2]);
924 
925 	for(blockno=0;blockno<8;blockno++)
926 	{
927 		sprintf(bank,"bank%d",blockno);
928 
929 		switch (ramsel)
930 		{
931 			case 0x07   : (blockno<3) ? map_blockno=blockno : map_blockno=-1; break;
932 			case 0x1F   : (blockno<4) ? map_blockno=0 : map_blockno=1; break;
933 			case 0x0F   : (blockno<4) ? map_blockno=1 : map_blockno=0; break;
934 			case 0x17   : (blockno<4) ? map_blockno=1 : map_blockno=2; break;
935 			default     : map_blockno=-1;
936 		}
937 		block_ofs=(ramsel==0x07) ? 0 : ((blockno % 4)*128);
938 
939 
940 		if(LOG_RAM) logerror("mapped %s",bank);
941 
942 		if((map_blockno>-1) && (block_ofs < ramblocks[ramblock][map_blockno].blocksize) &&
943 			(map_blocks[map_blockno]!=nullptr))
944 		{
945 			map_base=(ramsel==0x07) ? map_blocks[map_blockno] : &map_blocks[map_blockno][block_ofs*1024];
946 
947 			membank(bank)->set_base(map_base);
948 			space.install_readwrite_bank(memmap[blockno].start, memmap[blockno].end, bank);
949 			//if(LOG_RAM) logerror(", base=%X\n",(int)map_base);
950 		}
951 		else
952 		{
953 			space.nop_readwrite(memmap[blockno].start, memmap[blockno].end);
954 			if(LOG_RAM) logerror("NOP\n");
955 		}
956 	}
957 }
958 
nimbus_mcu_r()959 uint8_t rmnimbus_state::nimbus_mcu_r()
960 {
961 	return m_mcu_reg080;
962 }
963 
nimbus_mcu_w(uint8_t data)964 void rmnimbus_state::nimbus_mcu_w(uint8_t data)
965 {
966 	m_mcu_reg080=data;
967 
968 	nimbus_bank_memory();
969 }
970 
memory_reset()971 void rmnimbus_state::memory_reset()
972 {
973 	m_mcu_reg080=0x07;
974 	nimbus_bank_memory();
975 }
976 
977 /*
978 
979 Z80SIO, used for the keyboard interface
980 
981 */
982 
983 /* Z80 SIO/2 */
984 
WRITE_LINE_MEMBER(rmnimbus_state::sio_interrupt)985 WRITE_LINE_MEMBER(rmnimbus_state::sio_interrupt)
986 {
987 	if(LOG_SIO)
988 		logerror("SIO Interrupt state=%02X\n",state);
989 
990 	external_int(0, state);
991 }
992 
993 /* Floppy disk */
994 
fdc_reset()995 void rmnimbus_state::fdc_reset()
996 {
997 	m_nimbus_drives.reg400=0;
998 	m_scsi_ctrl_out->write(0);
999 }
1000 
WRITE_LINE_MEMBER(rmnimbus_state::nimbus_fdc_intrq_w)1001 WRITE_LINE_MEMBER(rmnimbus_state::nimbus_fdc_intrq_w)
1002 {
1003 	if(LOG_DISK)
1004 		logerror("nimbus_drives_intrq = %d\n",state);
1005 
1006 	if(m_iou_reg092 & DISK_INT_ENABLE)
1007 	{
1008 		external_int(EXTERNAL_INT_DISK,state);
1009 	}
1010 }
1011 
WRITE_LINE_MEMBER(rmnimbus_state::nimbus_fdc_drq_w)1012 WRITE_LINE_MEMBER(rmnimbus_state::nimbus_fdc_drq_w)
1013 {
1014 	if(LOG_DISK)
1015 		logerror("nimbus_drives_drq_w(%d)\n", state);
1016 
1017 	m_maincpu->drq1_w(state && FDC_DRQ_ENABLED());
1018 }
1019 
fdc_driveno(uint8_t drivesel)1020 uint8_t rmnimbus_state::fdc_driveno(uint8_t drivesel)
1021 {
1022 	switch (drivesel)
1023 	{
1024 		case 0x01: return 0;
1025 		case 0x02: return 1;
1026 		case 0x04: return 2;
1027 		case 0x08: return 3;
1028 		case 0x10: return 4;
1029 		case 0x20: return 5;
1030 		case 0x40: return 6;
1031 		case 0x80: return 7;
1032 		default: return 0;
1033 	}
1034 }
1035 
1036 /*
1037     0x410 read bits
1038 
1039     0   Ready from floppy
1040     1   Index pulse from floppy
1041     2   Motor on from floppy
1042     3   MSG from HDD
1043     4   !BSY from HDD
1044     5   !I/O from HDD
1045     6   !C/D
1046     7   !REQ from HDD
1047 */
1048 
scsi_r(offs_t offset)1049 uint8_t rmnimbus_state::scsi_r(offs_t offset)
1050 {
1051 	int result = 0;
1052 
1053 	int pc=m_maincpu->pc();
1054 	char drive[5];
1055 	floppy_image_device *floppy;
1056 
1057 	sprintf(drive, "%d", FDC_DRIVE());
1058 	floppy = m_fdc->subdevice<floppy_connector>(drive)->get_device();
1059 
1060 	switch(offset*2)
1061 	{
1062 		case 0x00 :
1063 			result |= m_scsi_req << 7;
1064 			result |= m_scsi_cd << 6;
1065 			result |= m_scsi_io << 5;
1066 			result |= m_scsi_bsy << 4;
1067 			result |= !m_scsi_msg << 3;
1068 			if(floppy)
1069 			{
1070 				result |= FDC_MOTOR() << 2;
1071 				result |= (!floppy->idx_r()) << 1;
1072 				result |= floppy->ready_r() << 0;
1073 			}
1074 			break;
1075 		case 0x08 :
1076 			result = m_scsi_data_in->read();
1077 			hdc_post_rw();
1078 		default:
1079 			break;
1080 	}
1081 
1082 	if(LOG_DISK_HDD)
1083 		logerror("Nimbus HDCR at pc=%08X from %04X data=%02X\n",pc,(offset*2)+0x410,result);
1084 
1085 	return result;
1086 }
1087 
1088 /*
1089     0x400 write bits
1090 
1091     0   drive 0 select
1092     1   drive 1 select
1093     2   drive 2 select
1094     3   drive 3 select
1095     4   side select
1096     5   fdc motor on
1097     6   hdc drq enabled
1098     7   fdc drq enabled
1099 */
fdc_ctl_w(uint8_t data)1100 void rmnimbus_state::fdc_ctl_w(uint8_t data)
1101 {
1102 	uint8_t reg400_old = m_nimbus_drives.reg400;
1103 	char drive[5];
1104 	floppy_image_device *floppy;
1105 
1106 	m_nimbus_drives.reg400 = data;
1107 
1108 	sprintf(drive, "%d", FDC_DRIVE());
1109 	floppy = m_fdc->subdevice<floppy_connector>(drive)->get_device();
1110 
1111 	m_fdc->set_floppy(floppy);
1112 	if(floppy)
1113 	{
1114 		floppy->ss_w(FDC_SIDE());
1115 		floppy->mon_w(!FDC_MOTOR());
1116 	}
1117 
1118 	// if we enable hdc drq with a pending condition, act on it
1119 	if((data & HDC_DRQ_MASK) && (~reg400_old & HDC_DRQ_MASK))
1120 		hdc_drq(true);
1121 }
1122 
1123 /*
1124     0x410 write bits
1125 
1126     0   SCSI reset
1127     1   SCSI SEL
1128     2   SCSI IRQ Enable
1129 */
1130 
scsi_w(offs_t offset,uint8_t data)1131 void rmnimbus_state::scsi_w(offs_t offset, uint8_t data)
1132 {
1133 	int pc=m_maincpu->pc();
1134 
1135 	if(LOG_DISK_HDD)
1136 		logerror("Nimbus HDCW at %05X write of %02X to %04X\n",pc,data,(offset*2)+0x410);
1137 
1138 	switch(offset*2)
1139 	{
1140 		case 0x00 :
1141 			m_scsi_ctrl_out->write(data);
1142 			break;
1143 
1144 		case 0x08 :
1145 			m_scsi_data_out->write(data);
1146 			hdc_post_rw();
1147 			break;
1148 	}
1149 }
1150 
hdc_reset()1151 void rmnimbus_state::hdc_reset()
1152 {
1153 	m_scsi_iena = 0;
1154 	m_scsi_msg = 0;
1155 	m_scsi_bsy = 0;
1156 	m_scsi_io = 0;
1157 	m_scsi_cd = 0;
1158 	m_scsi_req = 0;
1159 }
1160 
check_scsi_irq()1161 void rmnimbus_state::check_scsi_irq()
1162 {
1163 	nimbus_fdc_intrq_w(m_scsi_io && m_scsi_cd && m_scsi_req && m_scsi_iena);
1164 }
1165 
WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_iena)1166 WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_iena)
1167 {
1168 	m_scsi_iena = state;
1169 	check_scsi_irq();
1170 }
1171 
hdc_post_rw()1172 void rmnimbus_state::hdc_post_rw()
1173 {
1174 	if(m_scsi_req)
1175 		m_scsibus->write_ack(1);
1176 }
1177 
hdc_drq(bool state)1178 void rmnimbus_state::hdc_drq(bool state)
1179 {
1180 	m_maincpu->drq1_w(HDC_DRQ_ENABLED() && !m_scsi_cd && state);
1181 }
1182 
WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_bsy)1183 WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_bsy )
1184 {
1185 	m_scsi_bsy = state;
1186 }
1187 
WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_cd)1188 WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_cd )
1189 {
1190 	m_scsi_cd = state;
1191 	check_scsi_irq();
1192 }
1193 
WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_io)1194 WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_io )
1195 {
1196 	m_scsi_io = state;
1197 
1198 	if (m_scsi_io)
1199 	{
1200 		m_scsi_data_out->write(0);
1201 	}
1202 	check_scsi_irq();
1203 }
1204 
WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_msg)1205 WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_msg )
1206 {
1207 	m_scsi_msg = state;
1208 }
1209 
WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_req)1210 WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_req )
1211 {
1212 	int last = m_scsi_req;
1213 	m_scsi_req = state;
1214 
1215 	if (state)
1216 	{
1217 		if (!m_scsi_cd && !last)
1218 		{
1219 			hdc_drq(true);
1220 		}
1221 	}
1222 	else
1223 	{
1224 		hdc_drq(false);
1225 		m_scsibus->write_ack(0);
1226 	}
1227 	check_scsi_irq();
1228 }
1229 
1230 /* 8031/8051 Peripheral controller 80186 side */
1231 
pc8031_reset()1232 void rmnimbus_state::pc8031_reset()
1233 {
1234 	logerror("peripheral controller reset\n");
1235 
1236 	memset(&m_ipc_interface,0,sizeof(m_ipc_interface));
1237 }
1238 
1239 
1240 #if 0
1241 void rmnimbus_state::ipc_dumpregs()
1242 {
1243 	logerror("in_data=%02X, in_status=%02X, out_data=%02X, out_status=%02X\n",
1244 				m_ipc_interface.ipc_in, m_ipc_interface.status_in,
1245 				m_ipc_interface.ipc_out, m_ipc_interface.status_out);
1246 
1247 }
1248 #endif
1249 
nimbus_pc8031_r(offs_t offset)1250 uint8_t rmnimbus_state::nimbus_pc8031_r(offs_t offset)
1251 {
1252 	int pc=m_maincpu->pc();
1253 	uint8_t   result;
1254 
1255 	switch(offset*2)
1256 	{
1257 		case 0x00   : result=m_ipc_interface.ipc_out;
1258 						m_ipc_interface.status_in   &= ~IPC_IN_READ_PEND;
1259 						m_ipc_interface.status_out  &= ~IPC_OUT_BYTE_AVAIL;
1260 						break;
1261 
1262 		case 0x02   : result=m_ipc_interface.status_out;
1263 						break;
1264 
1265 		default : result=0; break;
1266 	}
1267 
1268 	if(LOG_PC8031_186)
1269 		logerror("Nimbus PCIOR %08X read of %04X returns %02X\n",pc,(offset*2)+0xC0,result);
1270 
1271 	return result;
1272 }
1273 
nimbus_pc8031_w(offs_t offset,uint8_t data)1274 void rmnimbus_state::nimbus_pc8031_w(offs_t offset, uint8_t data)
1275 {
1276 	int pc=m_maincpu->pc();
1277 
1278 	switch(offset*2)
1279 	{
1280 		case 0x00   : m_ipc_interface.ipc_in=data;
1281 						m_ipc_interface.status_in   |= IPC_IN_BYTE_AVAIL;
1282 						m_ipc_interface.status_in   &= ~IPC_IN_ADDR;
1283 						m_ipc_interface.status_out  |= IPC_OUT_READ_PEND;
1284 						break;
1285 
1286 		case 0x02   : m_ipc_interface.ipc_in=data;
1287 						m_ipc_interface.status_in   |= IPC_IN_BYTE_AVAIL;
1288 						m_ipc_interface.status_in   |= IPC_IN_ADDR;
1289 						m_ipc_interface.status_out  |= IPC_OUT_READ_PEND;
1290 						break;
1291 	}
1292 
1293 	if(LOG_PC8031_186)
1294 		logerror("Nimbus PCIOW %08X write of %02X to %04X\n",pc,data,(offset*2)+0xC0);
1295 
1296 }
1297 
1298 /* 8031/8051 Peripheral controller 8031/8051 side */
1299 
nimbus_pc8031_iou_r(offs_t offset)1300 uint8_t rmnimbus_state::nimbus_pc8031_iou_r(offs_t offset)
1301 {
1302 	int pc=m_iocpu->pc();
1303 	uint8_t   result = 0;
1304 
1305 	switch (offset & 0x01)
1306 	{
1307 		case 0x00   : result=m_ipc_interface.ipc_in;
1308 						m_ipc_interface.status_out  &= ~IPC_OUT_READ_PEND;
1309 						m_ipc_interface.status_in   &= ~IPC_IN_BYTE_AVAIL;
1310 						break;
1311 
1312 		case 0x01   : result=m_ipc_interface.status_in;
1313 						break;
1314 	}
1315 
1316 	if(((offset==2) || (offset==3)) && (m_iou_reg092 & PC8031_INT_ENABLE))
1317 		external_int(EXTERNAL_INT_PC8031_8C, true);
1318 
1319 	if(LOG_PC8031)
1320 		logerror("8031: PCIOR %04X read of %04X returns %02X\n",pc,offset,result);
1321 
1322 	return result;
1323 }
1324 
nimbus_pc8031_iou_w(offs_t offset,uint8_t data)1325 void rmnimbus_state::nimbus_pc8031_iou_w(offs_t offset, uint8_t data)
1326 {
1327 	int pc=m_iocpu->pc();
1328 
1329 	if(LOG_PC8031)
1330 		logerror("8031 PCIOW %04X write of %02X to %04X\n",pc,data,offset);
1331 
1332 	switch(offset & 0x03)
1333 	{
1334 		case 0x00   : m_ipc_interface.ipc_out=data;
1335 						m_ipc_interface.status_out  |= IPC_OUT_BYTE_AVAIL;
1336 						m_ipc_interface.status_out  &= ~IPC_OUT_ADDR;
1337 						m_ipc_interface.status_in   |= IPC_IN_READ_PEND;
1338 						break;
1339 
1340 		case 0x01   : m_ipc_interface.ipc_out=data;
1341 						m_ipc_interface.status_out   |= IPC_OUT_BYTE_AVAIL;
1342 						m_ipc_interface.status_out   |= IPC_OUT_ADDR;
1343 						m_ipc_interface.status_in    |= IPC_IN_READ_PEND;
1344 						break;
1345 
1346 		case 0x02   : m_ipc_interface.ipc_out=data;
1347 						m_ipc_interface.status_out  |= IPC_OUT_BYTE_AVAIL;
1348 						m_ipc_interface.status_out  &= ~IPC_OUT_ADDR;
1349 						m_ipc_interface.status_in   |= IPC_IN_READ_PEND;
1350 						if(m_iou_reg092 & PC8031_INT_ENABLE)
1351 							external_int(EXTERNAL_INT_PC8031_8F, true);
1352 						break;
1353 
1354 		case 0x03   : m_ipc_interface.ipc_out=data;
1355 						//m_ipc_interface.status_out   |= IPC_OUT_BYTE_AVAIL;
1356 						m_ipc_interface.status_out   |= IPC_OUT_ADDR;
1357 						m_ipc_interface.status_in    |= IPC_IN_READ_PEND;
1358 						if(m_iou_reg092 & PC8031_INT_ENABLE)
1359 							external_int(EXTERNAL_INT_PC8031_8E, true);
1360 						break;
1361 	}
1362 }
1363 
nimbus_pc8031_port1_r()1364 uint8_t rmnimbus_state::nimbus_pc8031_port1_r()
1365 {
1366 	int pc=m_iocpu->pc();
1367 	uint8_t   result = (m_eeprom_bits & ~4) | (m_eeprom->do_read() << 2);
1368 
1369 	if(LOG_PC8031_PORT)
1370 		logerror("8031: PCPORTR %04X read of P1 returns %02X\n",pc,result);
1371 
1372 	return result;
1373 }
1374 
nimbus_pc8031_port3_r()1375 uint8_t rmnimbus_state::nimbus_pc8031_port3_r()
1376 {
1377 	int pc=m_iocpu->pc();
1378 	uint8_t   result = 0;
1379 
1380 	if(LOG_PC8031_PORT)
1381 		logerror("8031: PCPORTR %04X read of P3 returns %02X\n",pc,result);
1382 
1383 	return result;
1384 }
1385 
nimbus_pc8031_port1_w(uint8_t data)1386 void rmnimbus_state::nimbus_pc8031_port1_w(uint8_t data)
1387 {
1388 	int pc=m_iocpu->pc();
1389 
1390 	m_eeprom->cs_write((data & 8) ? 1 : 0);
1391 
1392 	if(!(data & 8))
1393 		m_eeprom_state = 0;
1394 	else if(!(data & 2) || (m_eeprom_state == 2))
1395 		m_eeprom_state = 2;
1396 	else if((data & 8) && (!(m_eeprom_bits & 8)))
1397 		m_eeprom_state = 1;
1398 	else if((!(data & 1)) && (m_eeprom_bits & 1) && (m_eeprom_state == 1))
1399 		m_eeprom_state = 2; //wait until 1 clk after cs rises to set di else it's seen as a start bit
1400 
1401 	m_eeprom->di_write(((data & 2) && (m_eeprom_state == 2)) ? 1 : 0);
1402 	m_eeprom->clk_write((data & 1) ? 1 : 0);
1403 	m_eeprom_bits = data;
1404 
1405 	if(LOG_PC8031_PORT)
1406 		logerror("8031 PCPORTW %04X write of %02X to P1\n",pc,data);
1407 }
1408 
nimbus_pc8031_port3_w(uint8_t data)1409 void rmnimbus_state::nimbus_pc8031_port3_w(uint8_t data)
1410 {
1411 	int pc=m_iocpu->pc();
1412 
1413 	if(LOG_PC8031_PORT)
1414 		logerror("8031 PCPORTW %04X write of %02X to P3\n",pc,data);
1415 }
1416 
1417 
1418 /* IO Unit */
nimbus_iou_r(offs_t offset)1419 uint8_t rmnimbus_state::nimbus_iou_r(offs_t offset)
1420 {
1421 	int pc=m_maincpu->pc();
1422 	uint8_t   result=0;
1423 
1424 	if(offset==0)
1425 	{
1426 		result=m_iou_reg092;
1427 	}
1428 
1429 	if(LOG_IOU)
1430 		logerror("Nimbus IOUR %08X read of %04X returns %02X\n",pc,(offset*2)+0x92,result);
1431 
1432 	return result;
1433 }
1434 
nimbus_iou_w(offs_t offset,uint8_t data)1435 void rmnimbus_state::nimbus_iou_w(offs_t offset, uint8_t data)
1436 {
1437 	int pc=m_maincpu->pc();
1438 
1439 	if(LOG_IOU)
1440 		logerror("Nimbus IOUW %08X write of %02X to %04X\n",pc,data,(offset*2)+0x92);
1441 
1442 	if(offset==0)
1443 	{
1444 		m_iou_reg092=data;
1445 		m_msm->reset_w((data & MSM5205_INT_ENABLE) ? 0 : 1);
1446 	}
1447 }
1448 
iou_reset()1449 void rmnimbus_state::iou_reset()
1450 {
1451 	m_iou_reg092=0x00;
1452 	m_eeprom_state = 0;
1453 }
1454 
1455 /*
1456     Sound hardware : AY8910
1457 
1458     I believe that the IO ports of the 8910 are used to control the ROMPack ports, however
1459     this is currently un-implemented (and may never be as I don't have any rompacks!).
1460 
1461     The registers are mapped as so :
1462 
1463     Address     0xE0                0xE2
1464     Read        Data                ????
1465     Write       Register Address    Data
1466 
1467 */
1468 
rmni_sound_reset()1469 void rmnimbus_state::rmni_sound_reset()
1470 {
1471 	m_msm->reset_w(1);
1472 
1473 	m_last_playmode = msm5205_device::S48_4B;
1474 	m_msm->playmode_w(m_last_playmode);
1475 
1476 	m_ay8910_a=0;
1477 }
1478 
nimbus_sound_ay8910_porta_w(uint8_t data)1479 void rmnimbus_state::nimbus_sound_ay8910_porta_w(uint8_t data)
1480 {
1481 	m_msm->data_w(data);
1482 
1483 	// Mouse code needs a copy of this.
1484 	m_ay8910_a=data;
1485 }
1486 
nimbus_sound_ay8910_portb_w(uint8_t data)1487 void rmnimbus_state::nimbus_sound_ay8910_portb_w(uint8_t data)
1488 {
1489 	if ((data & 0x07) != m_last_playmode)
1490 	{
1491 		m_last_playmode = (data & 0x07);
1492 		m_msm->playmode_w(m_last_playmode);
1493 	}
1494 }
1495 
WRITE_LINE_MEMBER(rmnimbus_state::nimbus_msm5205_vck)1496 WRITE_LINE_MEMBER(rmnimbus_state::nimbus_msm5205_vck)
1497 {
1498 	if(m_iou_reg092 & MSM5205_INT_ENABLE)
1499 		external_int(EXTERNAL_INT_MSM5205,state);
1500 }
1501 
1502 static const int MOUSE_XYA[3][4] = { { 0, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 1, 0 } };
1503 static const int MOUSE_XYB[3][4] = { { 0, 0, 0, 0 }, { 0, 1, 1, 0 }, { 1, 1, 0, 0 } };
1504 //static const int MOUSE_XYA[4] = { 1, 1, 0, 0 };
1505 //static const int MOUSE_XYB[4] = { 0, 1, 1, 0 };
1506 
mouse_js_reset()1507 void rmnimbus_state::mouse_js_reset()
1508 {
1509 	m_nimbus_mouse.m_mouse_px=0;
1510 	m_nimbus_mouse.m_mouse_py=0;
1511 	m_nimbus_mouse.m_mouse_x=128;
1512 	m_nimbus_mouse.m_mouse_y=128;
1513 	m_nimbus_mouse.m_mouse_pc=0;
1514 	m_nimbus_mouse.m_mouse_pcx=0;
1515 	m_nimbus_mouse.m_mouse_pcy=0;
1516 	m_nimbus_mouse.m_intstate_x=0;
1517 	m_nimbus_mouse.m_intstate_y=0;
1518 	m_nimbus_mouse.m_reg0a4=0xC0;
1519 
1520 	// Setup timer to poll the mouse
1521 	m_nimbus_mouse.m_mouse_timer->adjust(attotime::zero, 0, attotime::from_hz(1000));
1522 }
1523 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)1524 void rmnimbus_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
1525 {
1526 	uint8_t   x = 0;
1527 	uint8_t   y = 0;
1528 //  int     pc=m_maincpu->pc();
1529 
1530 	uint8_t   intstate_x;
1531 	uint8_t   intstate_y;
1532 	int     xint;
1533 	int     yint;
1534 
1535 	m_nimbus_mouse.m_reg0a4 = m_io_mouse_button->read() | 0xC0;
1536 	x = m_io_mousex->read();
1537 	y = m_io_mousey->read();
1538 
1539 	uint8_t   mxa;
1540 	uint8_t   mxb;
1541 	uint8_t   mya;
1542 	uint8_t   myb;
1543 
1544 	//logerror("poll_mouse()\n");
1545 
1546 	if (x == m_nimbus_mouse.m_mouse_x)
1547 	{
1548 		m_nimbus_mouse.m_mouse_px = MOUSE_PHASE_STATIC;
1549 	}
1550 	else if (x > m_nimbus_mouse.m_mouse_x)
1551 	{
1552 		m_nimbus_mouse.m_mouse_px = MOUSE_PHASE_POSITIVE;
1553 	}
1554 	else if (x < m_nimbus_mouse.m_mouse_x)
1555 	{
1556 		m_nimbus_mouse.m_mouse_px = MOUSE_PHASE_NEGATIVE;
1557 	}
1558 
1559 	if (y == m_nimbus_mouse.m_mouse_y)
1560 	{
1561 		m_nimbus_mouse.m_mouse_py = MOUSE_PHASE_STATIC;
1562 	}
1563 	else if (y > m_nimbus_mouse.m_mouse_y)
1564 	{
1565 		m_nimbus_mouse.m_mouse_py = MOUSE_PHASE_POSITIVE;
1566 	}
1567 	else if (y < m_nimbus_mouse.m_mouse_y)
1568 	{
1569 		m_nimbus_mouse.m_mouse_py = MOUSE_PHASE_NEGATIVE;
1570 	}
1571 
1572 	switch (m_nimbus_mouse.m_mouse_px)
1573 	{
1574 		case MOUSE_PHASE_STATIC     : break;
1575 		case MOUSE_PHASE_POSITIVE   : m_nimbus_mouse.m_mouse_pcx++; break;
1576 		case MOUSE_PHASE_NEGATIVE   : m_nimbus_mouse.m_mouse_pcx--; break;
1577 	}
1578 	m_nimbus_mouse.m_mouse_pcx &= 0x03;
1579 
1580 	switch (m_nimbus_mouse.m_mouse_py)
1581 	{
1582 		case MOUSE_PHASE_STATIC     : break;
1583 		case MOUSE_PHASE_POSITIVE   : m_nimbus_mouse.m_mouse_pcy++; break;
1584 		case MOUSE_PHASE_NEGATIVE   : m_nimbus_mouse.m_mouse_pcy--; break;
1585 	}
1586 	m_nimbus_mouse.m_mouse_pcy &= 0x03;
1587 
1588 //  mxb = MOUSE_XYB[state.m_mouse_px][state->m_mouse_pcx]; // XB
1589 //  mxa = MOUSE_XYA[state.m_mouse_px][state->m_mouse_pcx]; // XA
1590 //  mya = MOUSE_XYA[state.m_mouse_py][state->m_mouse_pcy]; // YA
1591 //  myb = MOUSE_XYB[state.m_mouse_py][state->m_mouse_pcy]; // YB
1592 
1593 	mxb = MOUSE_XYB[1][m_nimbus_mouse.m_mouse_pcx]; // XB
1594 	mxa = MOUSE_XYA[1][m_nimbus_mouse.m_mouse_pcx]; // XA
1595 	mya = MOUSE_XYA[1][m_nimbus_mouse.m_mouse_pcy]; // YA
1596 	myb = MOUSE_XYB[1][m_nimbus_mouse.m_mouse_pcy]; // YB
1597 
1598 	if ((m_nimbus_mouse.m_mouse_py!=MOUSE_PHASE_STATIC) || (m_nimbus_mouse.m_mouse_px!=MOUSE_PHASE_STATIC))
1599 	{
1600 //        logerror("mouse_px=%02X, mouse_py=%02X, mouse_pcx=%02X, mouse_pcy=%02X\n",
1601 //              state.m_mouse_px,state->m_mouse_py,state->m_mouse_pcx,state->m_mouse_pcy);
1602 
1603 //        logerror("mxb=%02x, mxa=%02X (mxb ^ mxa)=%02X, (ay8910_a & 0xC0)=%02X, (mxb ^ mxa) ^ ((ay8910_a & 0x80) >> 7)=%02X\n",
1604 //              mxb,mxa, (mxb ^ mxa) , (state.m_ay8910_a & 0xC0), (mxb ^ mxa) ^ ((state->m_ay8910_a & 0x40) >> 6));
1605 	}
1606 
1607 	intstate_x = (mxb ^ mxa) ^ ((m_ay8910_a & 0x40) >> 6);
1608 	intstate_y = (myb ^ mya) ^ ((m_ay8910_a & 0x80) >> 7);
1609 
1610 	if (MOUSE_INT_ENABLED(this))
1611 	{
1612 		if ((intstate_x==1) && (m_nimbus_mouse.m_intstate_x==0))
1613 //        if (intstate_x!=state.m_intstate_x)
1614 		{
1615 			xint=mxa ? EXTERNAL_INT_MOUSE_XR : EXTERNAL_INT_MOUSE_XL;
1616 
1617 			external_int(xint, true);
1618 
1619 //            logerror("Xint:%02X, mxb=%02X\n",xint,mxb);
1620 		}
1621 
1622 		if ((intstate_y==1) && (m_nimbus_mouse.m_intstate_y==0))
1623 //        if (intstate_y!=state.m_intstate_y)
1624 		{
1625 			yint=myb ? EXTERNAL_INT_MOUSE_YU : EXTERNAL_INT_MOUSE_YD;
1626 
1627 			external_int(yint, true);
1628 //            logerror("Yint:%02X, myb=%02X\n",yint,myb);
1629 		}
1630 	}
1631 	else
1632 	{
1633 		m_nimbus_mouse.m_reg0a4 &= 0xF0;
1634 		m_nimbus_mouse.m_reg0a4 |= ( mxb & 0x01) << 3; // XB
1635 		m_nimbus_mouse.m_reg0a4 |= (~mxb & 0x01) << 2; // XA
1636 		m_nimbus_mouse.m_reg0a4 |= (~myb & 0x01) << 1; // YA
1637 		m_nimbus_mouse.m_reg0a4 |= ( myb & 0x01) << 0; // YB
1638 	}
1639 
1640 	m_nimbus_mouse.m_mouse_x = x;
1641 	m_nimbus_mouse.m_mouse_y = y;
1642 
1643 	if ((m_nimbus_mouse.m_mouse_py!=MOUSE_PHASE_STATIC) || (m_nimbus_mouse.m_mouse_px!=MOUSE_PHASE_STATIC))
1644 	{
1645 //        logerror("pc=%05X, reg0a4=%02X, reg092=%02X, ay_a=%02X, x=%02X, y=%02X, px=%02X, py=%02X, intstate_x=%02X, intstate_y=%02X\n",
1646 //                 pc,state.m_reg0a4,state->m_iou_reg092,state->m_ay8910_a,state->m_mouse_x,state->m_mouse_y,state->m_mouse_px,state->m_mouse_py,intstate_x,intstate_y);
1647 	}
1648 
1649 	m_nimbus_mouse.m_intstate_x=intstate_x;
1650 	m_nimbus_mouse.m_intstate_y=intstate_y;
1651 }
1652 
nimbus_mouse_js_r()1653 uint8_t rmnimbus_state::nimbus_mouse_js_r()
1654 {
1655 	/*
1656 
1657 	    bit     description
1658 
1659 	    0       JOY 0-Up    or mouse XB
1660 	    1       JOY 0-Down  or mouse XA
1661 	    2       JOY 0-Left  or mouse YA
1662 	    3       JOY 0-Right or mouse YB
1663 	    4       JOY 0-b0    or mouse rbutton
1664 	    5       JOY 0-b1    or mouse lbutton
1665 	    6       ?? always reads 1
1666 	    7       ?? always reads 1
1667 
1668 	*/
1669 	uint8_t result;
1670 	//int pc=m_maincpu->_pc();
1671 
1672 	if (m_io_config->read() & 0x01)
1673 	{
1674 		result=m_nimbus_mouse.m_reg0a4;
1675 		//logerror("mouse_js_r: pc=%05X, result=%02X\n",pc,result);
1676 	}
1677 	else
1678 	{
1679 		result = m_io_joystick0->read();
1680 	}
1681 
1682 	return result;
1683 }
1684 
nimbus_mouse_js_w(uint8_t data)1685 void rmnimbus_state::nimbus_mouse_js_w(uint8_t data)
1686 {
1687 }
1688 
1689 /**********************************************************************
1690 Parallel printer / User port.
1691 The Nimbus parallel printer port card is almost identical to the circuit
1692 in the BBC micro, so I have borrowed the driver code from the BBC :)
1693 
1694 Port A output is buffered before being connected to the printer connector.
1695 This means that they can only be operated as output lines.
1696 CA1 is pulled high by a 4K7 resistor. CA1 normally acts as an acknowledge
1697 line when a printer is used. CA2 is buffered so that it has become an open
1698 collector output only. It usually acts as the printer strobe line.
1699 ***********************************************************************/
1700 
1701 /* USER VIA 6522 port B is connected to the BBC user port */
nimbus_via_write_portb(uint8_t data)1702 void rmnimbus_state::nimbus_via_write_portb(uint8_t data)
1703 {
1704 }
1705