summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/dmv.cpp
blob: 5b0d48dc7f36c9aeb6eb3545fe97de126145614a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12

                                 









                                                                             
 
                            
                        
                            
                             


                            
                          
                   


                           
                         

                         
                         
                         
                         


                         
                   
                     


                            
                              
 




                                      
                                                                                   
























                                                   
                                            
           
 


                                         
                                

                                      
                                                   



                                              
                                            

                                           
                                        
                                          

                                       




                                              


                                         

                                             
                                            










                                                                            









                                                                          
                                                 
                                           
 

                                                                                       
 






                                                                                                                  




                                                                            


                                                             
 



                                           


                                              
























                                                        
                                
 

                                
                             


                                 



                                    
                                
                              

  



                                  
 





                                    


                                











                                                      

                              
                                           

 











                                 
                                  
 
                            

 
                                  
 





                                   

 

                                     

                              
 


                                                       




                                     









                                                       
                            
 


                             


                                                         
 


                                                
                             

                             








                                        


                    
                                                               
 


                                                                    


                                                                                  
 
                                          
                 


                                                              









                                                                              
                                                                    
 
                                        

                                                                  
                                                                                                      

                 

 
                                                          
 

                                        

                                                                                 









                                                                                                        

                                                         
                 


                                               
                                                                                    








                                                                        
                                                   
                                               
 
                                                                                    

                                                 

                                                         
                                                                           




                         












                                                             
                                                                 

                                                                     




                                                            
                                                     
         


                                                       


                                              

                                                                                 
                                                                 
                                                                                                          
 


                                       




                                                       
 
 
                                                                                      

                                                                                                                    

                                                          

 
                                                                                     

                                                                                                                    

                                                           

 









                                                                  

                                   







                                                       








                                        
                                                  
 


                                   

                                       




                                                

                                      
                                                

 





                                                



                                        
                          

                                         









                                        





                                        



                      
                                                                                         
 






                                                                                                                    






                                                                       
                                                                             
 
                            












                                                                                                                            









                                                                              


                                         
                                                                                       





                                        





                                                                                 




                                                                                                                          







                                                                                 
 
 













                                                             

                                         
 
 




                                                       


                        



                                                  

               

                               
                         

 

                               



                                                       



                            
                       
                     
                      
                                              
                                          

                           

 
                                  
 





                                                                                                                     




                                        



                                                       



                                   
                                                               

  
                                 
                                                                


             
                                                                                      
          



                                                                                      

                           

                      
                              

 

























                                                                     

                                        

                                  

 

                                       

                                   
 



                                   
 




                                                  





                                                                              
 










                                                                                           
 





                                                                                                             

 

                                                     
 
 
 




                                                                                                             
 
                                    
                                    


                                                            
 



                                                                                               
 


                                           
 
                            
                                         
                                    
                                                                           

                                                    
 
                                                                   
                                            
                                              

                  



                                                                                        
 













                                                                                
 


                                                                            

                                                                                          
 




                                                               

                            
                                               
                                                 
                                                   

                                                 
                                                             
                                                 
                                                               

                                                                            
                                                  
                                                              

                                                                             
                                                 
                                                               

                                                                            
                                                 
                                                               

                                                                            
                                                 
                                                               

                                                                            
                                                 
                                                               

                                                                            

                                                 
                                                             



                                                                                                                               

                                                             



                                                                                                                               
 
                                                  
 
                                                                     
 



                    

                                                                                                                                                                        



                                                                                                  
 




                                                                                                                                              
 
                                           
                                                                                                                                                  


                                                                                                                                                  
                                                                                                                                                  




                                                                                                                                                                 



            

                                                                                                                                            
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
/***************************************************************************

        NCR Decision Mate V

        04/01/2012 Skeleton driver.

****************************************************************************/


#include "emu.h"

#include "cpu/mcs48/mcs48.h"
#include "cpu/z80/z80.h"
#include "machine/am9517a.h"
#include "machine/dmv_keyb.h"
#include "machine/pit8253.h"
#include "machine/upd765.h"
#include "sound/spkrdev.h"
#include "video/upd7220.h"
#include "emupal.h"

// expansion slots
#include "bus/dmv/dmvbus.h"
#include "bus/dmv/k210.h"
#include "bus/dmv/k220.h"
#include "bus/dmv/k230.h"
#include "bus/dmv/k233.h"
#include "bus/dmv/k801.h"
#include "bus/dmv/k803.h"
#include "bus/dmv/k806.h"
#include "bus/dmv/ram.h"

#include "screen.h"
#include "softlist.h"
#include "speaker.h"

#include "formats/dmv_dsk.h"
#include "imagedev/snapquik.h"

#include "dmv.lh"

class dmv_state : public driver_device
{
public:
	dmv_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag)
		, m_maincpu(*this, "maincpu")
		, m_screen(*this, "screen")
		, m_hgdc(*this, "upd7220")
		, m_dmac(*this, "dma8237")
		, m_pit(*this, "pit8253")
		, m_fdc(*this, "i8272")
		, m_floppy0(*this, "i8272:0")
		, m_floppy1(*this, "i8272:1")
		, m_keyboard(*this, "keyboard")
		, m_speaker(*this, "speaker")
		, m_video_ram(*this, "video_ram")
		, m_palette(*this, "palette")
		, m_ram(*this, "ram")
		, m_bootrom(*this, "boot")
		, m_chargen(*this, "chargen")
		, m_slot1(*this, "slot1")
		, m_slot2(*this, "slot2")
		, m_slot2a(*this, "slot2a")
		, m_slot3(*this, "slot3")
		, m_slot4(*this, "slot4")
		, m_slot5(*this, "slot5")
		, m_slot6(*this, "slot6")
		, m_slot7(*this, "slot7")
		, m_slot7a(*this, "slot7a")
		, m_leds(*this, "led%u", 1U)
	{ }

	void dmv(machine_config &config);

private:
	void update_halt_line();

	DECLARE_WRITE8_MEMBER(leds_w);
	DECLARE_WRITE_LINE_MEMBER(dma_hrq_changed);
	DECLARE_WRITE_LINE_MEMBER(dmac_eop);
	DECLARE_WRITE_LINE_MEMBER(dmac_dack3);
	DECLARE_WRITE_LINE_MEMBER(fdc_irq);
	DECLARE_WRITE_LINE_MEMBER(pit_out0);
	DECLARE_WRITE_LINE_MEMBER(timint_w);
	DECLARE_WRITE8_MEMBER(fdd_motor_w);
	DECLARE_READ8_MEMBER(sys_status_r);
	DECLARE_WRITE8_MEMBER(tc_set_w);
	DECLARE_WRITE8_MEMBER(switch16_w);
	DECLARE_READ8_MEMBER(ramsel_r);
	DECLARE_READ8_MEMBER(romsel_r);
	DECLARE_WRITE8_MEMBER(ramsel_w);
	DECLARE_WRITE8_MEMBER(romsel_w);
	DECLARE_READ8_MEMBER(kb_mcu_port1_r);
	DECLARE_WRITE8_MEMBER(kb_mcu_port1_w);
	DECLARE_WRITE8_MEMBER(kb_mcu_port2_w);
	DECLARE_WRITE8_MEMBER(rambank_w);
	DECLARE_READ8_MEMBER(program_r);
	DECLARE_WRITE8_MEMBER(program_w);
	DECLARE_READ8_MEMBER(exp_program_r);
	DECLARE_WRITE8_MEMBER(exp_program_w);
	DECLARE_WRITE_LINE_MEMBER(thold7_w);

	void update_busint(int slot, int state);
	DECLARE_WRITE_LINE_MEMBER(busint2_w)    { update_busint(0, state); }
	DECLARE_WRITE_LINE_MEMBER(busint2a_w)   { update_busint(1, state); }
	DECLARE_WRITE_LINE_MEMBER(busint3_w)    { update_busint(2, state); }
	DECLARE_WRITE_LINE_MEMBER(busint4_w)    { update_busint(3, state); }
	DECLARE_WRITE_LINE_MEMBER(busint5_w)    { update_busint(4, state); }
	DECLARE_WRITE_LINE_MEMBER(busint6_w)    { update_busint(5, state); }
	DECLARE_WRITE_LINE_MEMBER(busint7_w)    { update_busint(6, state); }
	DECLARE_WRITE_LINE_MEMBER(busint7a_w)   { update_busint(7, state); }

	void update_irqs(int slot, int state);
	DECLARE_WRITE_LINE_MEMBER(irq2_w)       { update_irqs(0, state); }
	DECLARE_WRITE_LINE_MEMBER(irq2a_w)      { update_irqs(1, state); }
	DECLARE_WRITE_LINE_MEMBER(irq3_w)       { update_irqs(2, state); }
	DECLARE_WRITE_LINE_MEMBER(irq4_w)       { update_irqs(3, state); }
	DECLARE_WRITE_LINE_MEMBER(irq5_w)       { update_irqs(4, state); }
	DECLARE_WRITE_LINE_MEMBER(irq6_w)       { update_irqs(5, state); }
	DECLARE_WRITE_LINE_MEMBER(irq7_w)       { update_irqs(6, state); }
	DECLARE_WRITE_LINE_MEMBER(irq7a_w)      { update_irqs(7, state); }

	DECLARE_FLOPPY_FORMATS( floppy_formats );
	DECLARE_QUICKLOAD_LOAD_MEMBER(dmv);

	uint8_t program_read(address_space &space, int cas, offs_t offset);
	void program_write(address_space &space, int cas, offs_t offset, uint8_t data);

	void ifsel_r(address_space &space, int ifsel, offs_t offset, uint8_t &data);
	void ifsel_w(address_space &space, int ifsel, offs_t offset, uint8_t data);
	DECLARE_READ8_MEMBER(ifsel0_r)  { uint8_t data = 0xff;   ifsel_r(space, 0, offset, data);   return data; }
	DECLARE_READ8_MEMBER(ifsel1_r)  { uint8_t data = 0xff;   ifsel_r(space, 1, offset, data);   return data; }
	DECLARE_READ8_MEMBER(ifsel2_r)  { uint8_t data = 0xff;   ifsel_r(space, 2, offset, data);   return data; }
	DECLARE_READ8_MEMBER(ifsel3_r)  { uint8_t data = 0xff;   ifsel_r(space, 3, offset, data);   return data; }
	DECLARE_READ8_MEMBER(ifsel4_r)  { uint8_t data = 0xff;   ifsel_r(space, 4, offset, data);   return data; }
	DECLARE_WRITE8_MEMBER(ifsel0_w) { ifsel_w(space, 0, offset, data); }
	DECLARE_WRITE8_MEMBER(ifsel1_w) { ifsel_w(space, 1, offset, data); }
	DECLARE_WRITE8_MEMBER(ifsel2_w) { ifsel_w(space, 2, offset, data); }
	DECLARE_WRITE8_MEMBER(ifsel3_w) { ifsel_w(space, 3, offset, data); }
	DECLARE_WRITE8_MEMBER(ifsel4_w) { ifsel_w(space, 4, offset, data); }

	UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
	UPD7220_DRAW_TEXT_LINE_MEMBER( hgdc_draw_text );

	void dmv_io(address_map &map);
	void dmv_mem(address_map &map);
	void upd7220_map(address_map &map);

	virtual void machine_start() override;
	virtual void machine_reset() override;

	required_device<cpu_device> m_maincpu;
	required_device<screen_device> m_screen;
	required_device<upd7220_device> m_hgdc;
	required_device<am9517a_device> m_dmac;
	required_device<pit8253_device> m_pit;
	required_device<i8272a_device> m_fdc;
	required_device<floppy_connector> m_floppy0;
	required_device<floppy_connector> m_floppy1;
	required_device<dmv_keyboard_device> m_keyboard;
	required_device<speaker_sound_device> m_speaker;
	required_shared_ptr<uint16_t> m_video_ram;
	required_device<palette_device> m_palette;
	required_memory_region m_ram;
	required_memory_region m_bootrom;
	required_memory_region m_chargen;

	required_device<dmvcart_slot_device> m_slot1;
	required_device<dmvcart_slot_device> m_slot2;
	required_device<dmvcart_slot_device> m_slot2a;
	required_device<dmvcart_slot_device> m_slot3;
	required_device<dmvcart_slot_device> m_slot4;
	required_device<dmvcart_slot_device> m_slot5;
	required_device<dmvcart_slot_device> m_slot6;
	required_device<dmvcart_slot_device> m_slot7;
	required_device<dmvcart_slot_device> m_slot7a;
	output_finder<8> m_leds;

	bool        m_ramoutdis;
	int         m_switch16;
	int         m_thold7;
	int         m_dma_hrq;
	int         m_ram_bank;
	bool        m_color_mode;
	int         m_eop_line;
	int         m_dack3_line;
	int         m_sd_poll_state;
	int         m_floppy_motor;
	int         m_busint[8];
	int         m_irqs[8];
};

WRITE8_MEMBER(dmv_state::tc_set_w)
{
	m_fdc->tc_w(true);
}

WRITE8_MEMBER(dmv_state::switch16_w)
{
	m_switch16 = !m_switch16;
	update_halt_line();
}

WRITE8_MEMBER(dmv_state::leds_w)
{
	/*
	    LEDs    Value       Significance
	    ---------------------------------------
	    None    0xFF        Check complete
	    1+8     0x7E        Sumcheck error
	    2+8     0xBE        GDC error
	    3+8     0xDE        Disk drive error
	    4+8     0xEE        16-bit processor error
	    5+8     0xF6        Keyboard error
	    6+8     0xFA        DMA error
	    7+8     0xFC        Memory error
	    All     0x00        Processor error
	*/

	for(int i=0; i<8; i++)
		m_leds[7-i] = BIT(data, i);
}

READ8_MEMBER(dmv_state::ramsel_r)
{
	m_ramoutdis = false;
	return 0;
}

READ8_MEMBER(dmv_state::romsel_r)
{
	m_ramoutdis = true;
	return 0;
}

WRITE8_MEMBER(dmv_state::ramsel_w)
{
	m_ramoutdis = false;
}

WRITE8_MEMBER(dmv_state::romsel_w)
{
	m_ramoutdis = true;
}

WRITE8_MEMBER(dmv_state::rambank_w)
{
	m_ram_bank = offset;
}

WRITE8_MEMBER(dmv_state::fdd_motor_w)
{
	m_pit->write_gate0(1);
	m_pit->write_gate0(0);

	m_floppy_motor = 0;
	m_floppy0->get_device()->mon_w(m_floppy_motor);
	m_floppy1->get_device()->mon_w(m_floppy_motor);
}

READ8_MEMBER(dmv_state::sys_status_r)
{
	/*
	    Main system status
	    x--- ---- FDD index
	    -x--- --- IRQ 2
	    --x--- -- IRQ 3
	    ---x--- - IRQ 4
	    ---- x--- FDC interrupt
	    ---- -x-- FDD ready
	    ---- --x- 16-bit CPU available (active low)
	    ---- ---x FDD motor (active low)
	*/
	uint8_t data = 0x00;

	if (m_floppy_motor)
		data |= 0x01;

	// 16-bit CPU
	if (!(m_slot7->av16bit() || m_slot7a->av16bit()))
		data |= 0x02;

	if (!m_floppy0->get_device()->ready_r())
		data |= 0x04;

	if (m_fdc->get_irq())
		data |= 0x08;

	if (m_irqs[3])
		data |= 0x10;   // IRQ 4

	if (m_irqs[2])
		data |= 0x20;   // IRQ 3

	if (m_irqs[0])
		data |= 0x40;   // IRQ 2

	return data;
}

UPD7220_DISPLAY_PIXELS_MEMBER( dmv_state::hgdc_display_pixels )
{
	if (m_color_mode)
	{
		// 96KB videoram (32KB green + 32KB red + 32KB blue)
		uint16_t green = m_video_ram[(0x00000 + (address & 0x7fff)) >> 1];
		uint16_t red   = m_video_ram[(0x08000 + (address & 0x7fff)) >> 1];
		uint16_t blue  = m_video_ram[(0x10000 + (address & 0x7fff)) >> 1];

		for(int xi=0; xi<16; xi++)
		{
			int r = ((red   >> xi) & 1) ? 255 : 0;
			int g = ((green >> xi) & 1) ? 255 : 0;
			int b = ((blue  >> xi) & 1) ? 255 : 0;

			if (bitmap.cliprect().contains(x + xi, y))
				bitmap.pix32(y, x + xi) = rgb_t(r, g, b);
		}
	}
	else
	{
		const rgb_t *palette = m_palette->palette()->entry_list_raw();

		// 32KB videoram
		uint16_t gfx = m_video_ram[(address & 0xffff) >> 1];

		for(int xi=0;xi<16;xi++)
		{
			if (bitmap.cliprect().contains(x + xi, y))
				bitmap.pix32(y, x + xi) = ((gfx >> xi) & 1) ? palette[2] : palette[0];
		}
	}
}

UPD7220_DRAW_TEXT_LINE_MEMBER( dmv_state::hgdc_draw_text )
{
	for( int x = 0; x < pitch; x++ )
	{
		uint8_t tile = m_video_ram[(((addr+x)*2) & 0x1ffff) >> 1] & 0xff;
		uint8_t attr = m_video_ram[(((addr+x)*2) & 0x1ffff) >> 1] >> 8;

		rgb_t bg, fg;
		if (m_color_mode)
		{
			bg = rgb_t(attr & 0x20 ? 0 : 255, attr & 0x40 ? 0 : 255, attr & 0x80 ? 0 : 255);
			fg = rgb_t(attr & 0x04 ? 255 : 0, attr & 0x08 ? 255 : 0, attr & 0x10 ? 255 : 0);
		}
		else
		{
			const rgb_t *palette = m_palette->palette()->entry_list_raw();
			bg = palette[(attr & 1) ? 2 : 0];
			fg = palette[(attr & 1) ? 0 : 2];
		}

		for( int yi = 0; yi < lr; yi++)
		{
			uint8_t tile_data = m_chargen->base()[(tile*16+yi) & 0x7ff];

			if(cursor_on && cursor_addr == addr+x) //TODO
				tile_data^=0xff;

			for( int xi = 0; xi < 8; xi++)
			{
				int res_x,res_y;
				int pen = (tile_data >> xi) & 1 ? 1 : 0;

				res_x = x * 8 + xi;
				res_y = y + yi;

				if(!m_screen->visible_area().contains(res_x, res_y))
					continue;

				if(yi >= 16) { pen = 0; }

				bitmap.pix32(res_y, res_x) = pen ? fg : bg;
			}
		}
	}
}

/***********************************************************

    Quickload

    This loads a .COM file to address 0x100 then jumps
    there. Sometimes .COM has been renamed to .CPM to
    prevent windows going ballistic. These can be loaded
    as well.

************************************************************/

QUICKLOAD_LOAD_MEMBER( dmv_state, dmv )
{
	/* Avoid loading a program if CP/M-80 is not in memory */
	if ((m_ram->base()[0] != 0xc3) || (m_ram->base()[5] != 0xc3))
		return image_init_result::FAIL;

	if (quickload_size >= 0xfd00)
		return image_init_result::FAIL;

	/* Load image to the TPA (Transient Program Area) */
	for (uint16_t i = 0; i < quickload_size; i++)
	{
		uint8_t data;
		if (image.fread( &data, 1) != 1)
			return image_init_result::FAIL;
		m_ram->base()[i+0x100] = data;
	}

	m_ram->base()[0x80] = m_ram->base()[0x81] = 0;  // clear out command tail

	m_maincpu->set_pc(0x100);                // start program
	m_maincpu->set_state_int(Z80_SP, 256 * m_ram->base()[7] - 300); // put the stack a bit before BDOS

	return image_init_result::PASS;
}

static void dmv_floppies(device_slot_interface &device)
{
	device.option_add("525dd", FLOPPY_525_DD);
	device.option_add("525qd", FLOPPY_525_QD);
}


void dmv_state::ifsel_r(address_space &space, int ifsel, offs_t offset, uint8_t &data)
{
	dmvcart_slot_device *slots[] = { m_slot2, m_slot2a, m_slot3, m_slot4, m_slot5, m_slot6, m_slot7, m_slot7a };
	for(auto & slot : slots)
		slot->io_read(space, ifsel, offset, data);
}

void dmv_state::ifsel_w(address_space &space, int ifsel, offs_t offset, uint8_t data)
{
	dmvcart_slot_device *slots[] = { m_slot2, m_slot2a, m_slot3, m_slot4, m_slot5, m_slot6, m_slot7, m_slot7a };
	for(auto & slot : slots)
		slot->io_write(space, ifsel, offset, data);
}

WRITE8_MEMBER(dmv_state::exp_program_w)
{
	program_write(space, (offset >> 16) & 0x07, offset, data);
}

READ8_MEMBER(dmv_state::exp_program_r)
{
	return program_read(space, (offset >> 16) & 0x07, offset);
}

WRITE8_MEMBER(dmv_state::program_w)
{
	program_write(space, m_ram_bank, offset, data);
}

READ8_MEMBER(dmv_state::program_r)
{
	return program_read(space, m_ram_bank, offset);
}

WRITE_LINE_MEMBER( dmv_state::thold7_w )
{
	if (m_thold7 != state)
	{
		m_thold7 = state;
		update_halt_line();
	}
}

void dmv_state::update_busint(int slot, int state)
{
	m_busint[slot] = state;

	int new_state = CLEAR_LINE;
	for (auto & elem : m_busint)
		if (elem != CLEAR_LINE)
		{
			new_state = ASSERT_LINE;
			break;
		}

	m_slot7a->busint_w(new_state);
	m_slot7->busint_w(new_state);
	m_maincpu->set_input_line(0, new_state);
}

void dmv_state::update_irqs(int slot, int state)
{
	m_irqs[slot] = state;

	switch(slot)
	{
	case 0: // slot 2
		m_slot7->irq2_w(state);
		m_slot7a->irq2_w(state);
		break;
	case 1: // slot 2a
		m_slot7->irq2a_w(state);
		m_slot7a->irq2a_w(state);
		break;
	case 2: // slot 3
		m_slot7->irq3_w(state);
		m_slot7a->irq3_w(state);
		break;
	case 3: // slot 4
		m_slot7->irq4_w(state);
		m_slot7a->irq4_w(state);
		break;
	case 4: // slot 5
		m_slot7->irq5_w(state);
		m_slot7a->irq5_w(state);
		break;
	case 5: // slot 6
		m_slot7->irq6_w(state);
		m_slot7a->irq6_w(state);
		break;
	}
}

void dmv_state::program_write(address_space &space, int cas, offs_t offset, uint8_t data)
{
	bool tramd = false;
	dmvcart_slot_device *slots[] = { m_slot2, m_slot2a, m_slot3, m_slot4, m_slot5, m_slot6, m_slot7, m_slot7a };
	for(int i=0; i<8 && !tramd; i++)
		tramd = slots[i]->write(offset, data);

	if (!tramd)
	{
		if (cas == 0)
			m_ram->base()[offset & 0xffff] = data;
		else
			m_slot1->ram_write(cas, offset & 0xffff, data);
	}
}

uint8_t dmv_state::program_read(address_space &space, int cas, offs_t offset)
{
	uint8_t data = 0xff;
	if (m_ramoutdis && offset < 0x2000)
	{
		data = m_bootrom->base()[offset];
	}
	else
	{
		bool tramd = false;
		dmvcart_slot_device *slots[] = { m_slot2, m_slot2a, m_slot3, m_slot4, m_slot5, m_slot6, m_slot7, m_slot7a };
		for(int i=0; i<8 && !tramd; i++)
			tramd = slots[i]->read(offset, data);

		if (!tramd)
		{
			if (cas == 0)
				data = m_ram->base()[offset & 0xffff];
			else
				m_slot1->ram_read(cas, offset & 0xffff, data);
		}
	}

	return data;
}

void dmv_state::dmv_mem(address_map &map)
{
	map.unmap_value_high();
	map(0x0000, 0xffff).rw(FUNC(dmv_state::program_r), FUNC(dmv_state::program_w));
}

void dmv_state::dmv_io(address_map &map)
{
	map.unmap_value_high();
	map.global_mask(0xff);
	map(0x00, 0x00).w(FUNC(dmv_state::leds_w));
	map(0x10, 0x10).rw(FUNC(dmv_state::ramsel_r), FUNC(dmv_state::ramsel_w));
	map(0x11, 0x11).rw(FUNC(dmv_state::romsel_r), FUNC(dmv_state::romsel_w));
	map(0x12, 0x12).w(FUNC(dmv_state::tc_set_w));
	map(0x13, 0x13).r(FUNC(dmv_state::sys_status_r));
	map(0x14, 0x14).w(FUNC(dmv_state::fdd_motor_w));
	map(0x20, 0x2f).rw(m_dmac, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
	map(0x40, 0x41).rw("kb_ctrl_mcu", FUNC(upi41_cpu_device::upi41_master_r), FUNC(upi41_cpu_device::upi41_master_w));
	map(0x50, 0x51).m(m_fdc, FUNC(i8272a_device::map));
	map(0x80, 0x83).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
	map(0xa0, 0xa1).rw(m_hgdc, FUNC(upd7220_device::read), FUNC(upd7220_device::write));
	map(0xd0, 0xd7).w(FUNC(dmv_state::switch16_w));
	map(0xe0, 0xe7).w(FUNC(dmv_state::rambank_w));

	map(0x60, 0x6f).rw(FUNC(dmv_state::ifsel0_r), FUNC(dmv_state::ifsel0_w));
	map(0x70, 0x7f).rw(FUNC(dmv_state::ifsel1_r), FUNC(dmv_state::ifsel1_w));
	map(0x30, 0x3f).rw(FUNC(dmv_state::ifsel2_r), FUNC(dmv_state::ifsel2_w));
	map(0xb0, 0xbf).rw(FUNC(dmv_state::ifsel3_r), FUNC(dmv_state::ifsel3_w));
	map(0xc0, 0xcf).rw(FUNC(dmv_state::ifsel4_r), FUNC(dmv_state::ifsel4_w));
}

READ8_MEMBER(dmv_state::kb_mcu_port1_r)
{
	return !(m_keyboard->sd_poll_r() & !m_sd_poll_state);
}

WRITE8_MEMBER(dmv_state::kb_mcu_port1_w)
{
	m_sd_poll_state = BIT(data, 1);
	m_keyboard->sd_poll_w(!m_sd_poll_state);
}

WRITE8_MEMBER(dmv_state::kb_mcu_port2_w)
{
	m_speaker->level_w(BIT(data, 0));
	m_slot7a->keyint_w(BIT(data, 4));
	m_slot7->keyint_w(BIT(data, 4));
}

void dmv_state::upd7220_map(address_map &map)
{
	map.global_mask(0x1ffff);
	map(0x00000, 0x1ffff).ram().share("video_ram");
}

/* Input ports */
INPUT_PORTS_START( dmv )
	PORT_START("CONFIG")
	PORT_CONFNAME( 0x01, 0x00, "Video Board" )
	PORT_CONFSETTING( 0x00, "Monochrome" )
	PORT_CONFSETTING( 0x01, "Color" )
INPUT_PORTS_END

void dmv_state::machine_start()
{
	m_leds.resolve();
}

void dmv_state::machine_reset()
{
	m_color_mode = ioport("CONFIG")->read() & 0x01;

	m_ramoutdis = true;
	m_ram_bank = 0;
	m_eop_line = 0;
	m_dack3_line = 0;
	m_sd_poll_state = 0;
	m_floppy_motor = 1;
	m_switch16 = 0;
	m_thold7 = 0;
	m_dma_hrq = 0;
	memset(m_busint, 0, sizeof(m_busint));
	memset(m_irqs, 0, sizeof(m_irqs));

	update_halt_line();
}

void dmv_state::update_halt_line()
{
	m_slot7->hold_w(m_dma_hrq);
	m_slot7->switch16_w(m_switch16);
	m_slot7a->hold_w(m_dma_hrq);
	m_slot7a->switch16_w(m_switch16);

	m_maincpu->set_input_line(INPUT_LINE_HALT, (m_thold7 || m_switch16 || m_dma_hrq) ? ASSERT_LINE : CLEAR_LINE);
}

/* F4 Character Displayer */
static const gfx_layout dmv_charlayout =
{
	8, 16,                  /* 8 x 16 characters */
	128,                    /* 128 characters */
	1,                  /* 1 bits per pixel */
	{ 0 },                  /* no bitplanes */
	/* x offsets */
	{ 7, 6, 5, 4, 3, 2, 1, 0 },
	/* y offsets */
	{ STEP16(0,8) },
	8*16                    /* every char takes 16 bytes */
};

static GFXDECODE_START( gfx_dmv )
	GFXDECODE_ENTRY("chargen", 0x0000, dmv_charlayout, 0, 1)
GFXDECODE_END


//------------------------------------------------------------------------------------
//   I8237
//------------------------------------------------------------------------------------

WRITE_LINE_MEMBER( dmv_state::dma_hrq_changed )
{
	m_dma_hrq = state;
	update_halt_line();

	// Assert HLDA
	m_dmac->hack_w(state);
}

WRITE_LINE_MEMBER( dmv_state::dmac_eop )
{
	if (!(m_dack3_line || m_eop_line) && (m_dack3_line || state))
		m_fdc->tc_w(true);

	m_eop_line = state;
}

WRITE_LINE_MEMBER( dmv_state::dmac_dack3 )
{
	if (!(m_dack3_line || m_eop_line) && (state || m_eop_line))
		m_fdc->tc_w(true);

	m_dack3_line = state;
}

WRITE_LINE_MEMBER( dmv_state::pit_out0 )
{
	if (!state)
	{
		m_floppy_motor = 1;
		m_floppy0->get_device()->mon_w(m_floppy_motor);
		m_floppy1->get_device()->mon_w(m_floppy_motor);
	}
}

WRITE_LINE_MEMBER( dmv_state::timint_w )
{
	m_slot7a->timint_w(state);
	m_slot7->timint_w(state);
}

WRITE_LINE_MEMBER( dmv_state::fdc_irq )
{
	m_slot7a->flexint_w(state);
	m_slot7->flexint_w(state);

	if (state)
		m_fdc->tc_w(false);
}


FLOPPY_FORMATS_MEMBER( dmv_state::floppy_formats )
	FLOPPY_DMV_FORMAT
FLOPPY_FORMATS_END


static void dmv_slot1(device_slot_interface &device)
{
	device.option_add("k200", DMV_K200);        // K200 64K RAM expansion
	device.option_add("k202", DMV_K202);        // K202 192K RAM expansion
	device.option_add("k208", DMV_K208);        // K208 448K RAM expansion
}

static void dmv_slot2_6(device_slot_interface &device)
{
	device.option_add("k210", DMV_K210);        // K210 Centronics
	device.option_add("k211", DMV_K211);        // K211 RS-232 Communications Interface
	device.option_add("k212", DMV_K212);        // K212 RS-232 Printer Interface
	device.option_add("k213", DMV_K213);        // K213 RS-232 Plotter Interface
	device.option_add("k233", DMV_K233);        // K233 16K Shared RAM
	device.option_add("k801", DMV_K801);        // K801 RS-232 Switchable Interface
	device.option_add("k803", DMV_K803);        // K803 RTC module
	device.option_add("k806", DMV_K806);        // K806 Mouse module
}

static void dmv_slot7(device_slot_interface &device)
{
	device.option_add("k220", DMV_K220);        // K220 Diagnostic Module
	device.option_add("k231", DMV_K231);        // K231 External 8088 module without interrupt controller
	device.option_add("k234", DMV_K234);        // K234 External 68008 module
}


static void dmv_slot2a(device_slot_interface &device)
{

}

static void dmv_slot7a(device_slot_interface &device)
{
	device.option_add("k230", DMV_K230);        // K230 Internal 8088 module without interrupt controller
	device.option_add("k235", DMV_K235);        // K235 Internal 8088 module with interrupt controller
}

MACHINE_CONFIG_START(dmv_state::dmv)
	/* basic machine hardware */
	MCFG_DEVICE_ADD("maincpu",Z80, XTAL(24'000'000) / 6)
	MCFG_DEVICE_PROGRAM_MAP(dmv_mem)
	MCFG_DEVICE_IO_MAP(dmv_io)

	MCFG_DEVICE_ADD("kb_ctrl_mcu", I8741, XTAL(6'000'000))
	MCFG_MCS48_PORT_P1_IN_CB(READ8(*this, dmv_state, kb_mcu_port1_r)) // bit 0 data from kb
	MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(*this, dmv_state, kb_mcu_port1_w)) // bit 1 data to kb
	MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, dmv_state, kb_mcu_port2_w))

	MCFG_QUANTUM_PERFECT_CPU("maincpu")

	MCFG_DMV_KEYBOARD_ADD("keyboard")

	/* video hardware */
	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(50)
	MCFG_SCREEN_UPDATE_DEVICE("upd7220", upd7220_device, screen_update)
	MCFG_SCREEN_SIZE(640, 400)
	MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 400-1)

	MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_dmv)
	MCFG_PALETTE_ADD_3BIT_RGB("palette")
	config.set_default_layout(layout_dmv);

	// devices
	UPD7220(config, m_hgdc, XTAL(5'000'000)/2); // unk clock
	m_hgdc->set_addrmap(0, &dmv_state::upd7220_map);
	m_hgdc->set_display_pixels_callback(FUNC(dmv_state::hgdc_display_pixels), this);
	m_hgdc->set_draw_text_callback(FUNC(dmv_state::hgdc_draw_text), this);

	AM9517A(config, m_dmac, 4_MHz_XTAL);
	m_dmac->out_hreq_callback().set(FUNC(dmv_state::dma_hrq_changed));
	m_dmac->out_eop_callback().set(FUNC(dmv_state::dmac_eop));
	m_dmac->in_memr_callback().set(FUNC(dmv_state::program_r));
	m_dmac->out_memw_callback().set(FUNC(dmv_state::program_w));
	m_dmac->in_ior_callback<0>().set_log("Read DMA CH1");
	m_dmac->out_iow_callback<0>().set_log("Write DMA CH1");
	m_dmac->in_ior_callback<1>().set_log("Read DMA CH2");
	m_dmac->out_iow_callback<1>().set_log("Write DMA CH2");
	m_dmac->in_ior_callback<2>().set(m_hgdc, FUNC(upd7220_device::dack_r));
	m_dmac->out_iow_callback<2>().set(m_hgdc, FUNC(upd7220_device::dack_w));
	m_dmac->in_ior_callback<3>().set(m_fdc, FUNC(i8272a_device::mdma_r));
	m_dmac->out_iow_callback<3>().set(m_fdc, FUNC(i8272a_device::mdma_w));
	m_dmac->out_dack_callback<3>().set(FUNC(dmv_state::dmac_dack3));

	I8272A(config, m_fdc, true);
	m_fdc->intrq_wr_callback().set(FUNC(dmv_state::fdc_irq));
	m_fdc->drq_wr_callback().set(m_dmac, FUNC(am9517a_device::dreq3_w));
	MCFG_FLOPPY_DRIVE_ADD("i8272:0", dmv_floppies, "525dd", dmv_state::floppy_formats)
	MCFG_FLOPPY_DRIVE_ADD("i8272:1", dmv_floppies, "525dd", dmv_state::floppy_formats)

	PIT8253(config, m_pit, 0);
	m_pit->set_clk<0>(50);
	m_pit->out_handler<0>().set(FUNC(dmv_state::pit_out0));
	m_pit->set_clk<2>(XTAL(24'000'000) / 3 / 16);
	m_pit->out_handler<2>().set(FUNC(dmv_state::timint_w));

	/* sound hardware */
	SPEAKER(config, "mono").front_center();
	MCFG_DEVICE_ADD("speaker", SPEAKER_SOUND)
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)

	MCFG_DEVICE_ADD("slot1", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot1, nullptr, false)
	MCFG_DEVICE_ADD("slot2", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot2_6, nullptr, false)
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint2_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq2_w))
	MCFG_DEVICE_ADD("slot2a", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot2a, nullptr, false)
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint2a_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq2a_w))
	MCFG_DEVICE_ADD("slot3", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot2_6, nullptr, false)
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint3_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq3_w))
	MCFG_DEVICE_ADD("slot4", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot2_6, nullptr, false)
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint4_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq4_w))
	MCFG_DEVICE_ADD("slot5", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot2_6, nullptr, false)
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint5_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq5_w))
	MCFG_DEVICE_ADD("slot6", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot2_6, nullptr, false)
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint6_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq6_w))

	MCFG_DEVICE_ADD("slot7", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot7, nullptr, false)
	MCFG_DMVCART_SLOT_PROGRAM_READWRITE_CB(READ8(*this, dmv_state, exp_program_r), WRITE8(*this, dmv_state, exp_program_w))
	MCFG_DMVCART_SLOT_OUT_THOLD_CB(WRITELINE(*this, dmv_state, thold7_w))
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint7_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq7_w))
	MCFG_DEVICE_ADD("slot7a", DMVCART_SLOT, 0)
	MCFG_DEVICE_SLOT_INTERFACE(dmv_slot7a, "k230", false)
	MCFG_DMVCART_SLOT_PROGRAM_READWRITE_CB(READ8(*this, dmv_state, exp_program_r), WRITE8(*this, dmv_state, exp_program_w))
	MCFG_DMVCART_SLOT_OUT_THOLD_CB(WRITELINE(*this, dmv_state, thold7_w))
	MCFG_DMVCART_SLOT_OUT_INT_CB(WRITELINE(*this, dmv_state, busint7a_w))
	MCFG_DMVCART_SLOT_OUT_IRQ_CB(WRITELINE(*this, dmv_state, irq7a_w))

	MCFG_SOFTWARE_LIST_ADD("flop_list", "dmv")

	MCFG_QUICKLOAD_ADD("quickload", dmv_state, dmv, "com,cpm", 3)

MACHINE_CONFIG_END

/* ROM definition */
ROM_START( dmv )
	ROM_REGION( 0x2000, "boot", 0 )
	ROM_SYSTEM_BIOS(0, "c07", "C.07.00")    // ROM bears the handwritten note "Color 7.0", this is from the machine that originally had Color, 68K and internal 8088
	ROM_SYSTEM_BIOS(1, "c06", "C.06.00")    // Color machine with older BIOS revision
	ROM_SYSTEM_BIOS(2, "m07", "M.07.00")    // Mono machine with internal 8088 and internal HD
	ROM_SYSTEM_BIOS(3, "m06", "M.06.00")    // Mono machine
	ROM_SYSTEM_BIOS(4, "m05", "M.05.00")    // Mono machine, marked "updated"

	ROMX_LOAD( "dmv_mb_rom_33610.bin", 0x00000,    0x02000,    CRC(bf25f3f0) SHA1(0c7dd37704db4799e340cc836f887cd543e5c964), ROM_BIOS(0) )
	ROMX_LOAD( "dmv_mb_rom_32838.bin", 0x00000,    0x02000,    CRC(d5ceb559) SHA1(e3a05e43aa1b09f0a857b8d54b00bcd321215bf6), ROM_BIOS(1) )
	ROMX_LOAD( "dmv_mb_rom_33609.bin", 0x00000,    0x02000,    CRC(120951b6) SHA1(57bef9cc6379dea5730bc1477e8896508e00a349), ROM_BIOS(2) )
	ROMX_LOAD( "dmv_mb_rom_32676.bin", 0x00000,    0x02000,    CRC(7796519e) SHA1(8d5dd9c1e66c96fcca271b6f673d6a0e784acb33), ROM_BIOS(3) )
	ROMX_LOAD( "dmv_mb_rom_32664.bin", 0x00000,    0x02000,    CRC(6624610e) SHA1(e9226be897d2c5f875784ab77dad8807f14c7714), ROM_BIOS(4) )

	ROM_REGION(0x400, "kb_ctrl_mcu", 0)
	ROMX_LOAD( "dmv_mb_8741_32678.bin",    0x00000,    0x00400,    CRC(50d1dc4c) SHA1(2c8251d6c8df9f507e11bf920869657f4d074db1), ROM_BIOS(0) )
	ROMX_LOAD( "dmv_mb_8741_32678.bin",    0x00000,    0x00400,    CRC(50d1dc4c) SHA1(2c8251d6c8df9f507e11bf920869657f4d074db1), ROM_BIOS(1) )
	ROMX_LOAD( "dmv_mb_8741_32678.bin",    0x00000,    0x00400,    CRC(50d1dc4c) SHA1(2c8251d6c8df9f507e11bf920869657f4d074db1), ROM_BIOS(2) )
	ROMX_LOAD( "dmv_mb_8741_32678.bin",    0x00000,    0x00400,    CRC(50d1dc4c) SHA1(2c8251d6c8df9f507e11bf920869657f4d074db1), ROM_BIOS(3) )
	ROMX_LOAD( "dmv_mb_8741_32121.bin",    0x00000,    0x00400,    CRC(a03af298) SHA1(144cba41294c46f5ca79b7ad8ced0e4408168775), ROM_BIOS(4) )

	ROM_REGION(0x800, "chargen", 0)
	ROM_LOAD( "76161.bin",    0x00000,    0x00800,  CRC(6e4df4f9) SHA1(20ff4fc48e55eaf5131f6573fff93e7f97d2f45d)) // same for both color and monochrome board

	ROM_REGION(0x10000, "ram", ROMREGION_ERASE) // 64K RAM on mainboard
ROM_END

/* Driver */

//    YEAR  NAME  PARENT  COMPAT  MACHINE  INPUT  CLASS      INIT        COMPANY  FULLNAME           FLAGS
COMP( 1984, dmv,  0,      0,      dmv,     dmv,   dmv_state, empty_init, "NCR",   "Decision Mate V", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)