summaryrefslogblamecommitdiffstatshomepage
path: root/src/mess/machine/cgenie.c
blob: 193754b0cb381dfad29450fcd376c225bfad0ba1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                            




                                     

                                              





                                                      

                            


 
                                                          
 
                                                                  
 
                                        
         

                                         



         
                                  
 
                                                            
                                                  



















                                                                         
                                           








                                                                   
                                           
         
                                                    
                 

                                                                          
                                                                   




                                                                    
                                                            




                                                                                  
                                                    
                                                  
                                                                             


                                                                   
                                           
         
                                                                                  
                                                 

                                                                                


            
                                                    
                                                  
                                                                             

         

                         

 
                                  
 
                                                            
                                               


                                         




                          

          



                                                             
                                              





                                                                       



                                                                                                                                     
                                                                                                                                            








                                       








                                                                              
 
                                               
 
                                               
 
                                                      













                                       
                                            































                                                                    
                                                     




                                      

                                                                  




                                      
                                                  

         
                         


 
                                              
 
                                         
 
                           



                    
                                                










                                       
                                                 
 
                           

 
                                                 
 
                                

                                      
                                   
 

                                                          
 

                                                          
 

                                                          
 

                                                          



                                        
                                   
 

                                                              
 

                                                              
 

                                                              
 

                                                              
 

                                                              
 

                                                              
         
                           

 
                                                  
 
                           

 
                                                  
 
                           

 
                                             
 
                                                                       
                                                    
                                                  
                         
                                            

 
                                            
 
                                                                       
                                                       
                                                  
                            
                                           

 
                                             
 
                                                                       
                                                       
                                                  
                            
                                            

 
                                           
 
                                                                       
                                                       
                                                  
                            
                                          

 
                                               
 
                                                                       
                                                              
                                                  
                       
                                            

 
                                             
 
                                                                       
                                                            
                                                  
                       
                                          

 
                                              
 
                                                                       
                                                            
                                                  
                       
                                           

 
                                            
 
                                                                       
                                                            
                                                  
                       
                                         

 
                                                 
 
                                  
 
                                               


                      
                                                          
 
                                             
         
                                          
                                                        


         
                                                   
 
                                                                  
                                               



                       
                                                   
                 
                                                
                                                                



                 
                                         





                                                
                                                                  



                                                
                                             
 
                                                                       
















                                                 
                                         

                                      
                              
 

                              




                                       
                                               



                           
                                                 

                           
                                                 

                           
                                                 

                           
                                                 

                           
                                                 

                           
                                                 

                           
                                                 

                           
                                                 







                                       
                                                 
 
                                     


                                
                                                
 
                                     

                                      
                                                      


                                
                                               
 
                                         

 
                                                
 


                               
                                        


                           
                                  
                                                               
                                                                                             

 
                                              
 
                                 

 
                                               
 

                  
                                       
                                                      

                        
                                 

                                  
                                                                                                                              















                                       
                                                          
 
                                                          
         
                                                          
                                                       
                                     
                                                                                       



         
                                                    
 
                              

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

  machine.c

  Functions to emulate general aspects of the machine
  (RAM, ROM, interrupts, I/O ports)

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

#include "emu.h"
#include "cpu/z80/z80.h"
#include "includes/cgenie.h"
#include "machine/wd17xx.h"
#include "imagedev/cartslot.h"
#include "imagedev/cassette.h"
#include "sound/dac.h"
#include "imagedev/flopdrv.h"
#include "machine/ram.h"

#define AYWriteReg(chip,port,value) \
	m_ay8910->address_w(space, 0,port);  \
	m_ay8910->data_w(space, 0,value)

#define TAPE_HEADER "Colour Genie - Virtual Tape File"




#define IRQ_TIMER       0x80
#define IRQ_FDC         0x40



TIMER_CALLBACK_MEMBER(cgenie_state::handle_cassette_input)
{
	UINT8 new_level = ( (m_cassette->input()) > 0.0 ) ? 1 : 0;

	if ( new_level != m_cass_level )
	{
		m_cass_level = new_level;
		m_cass_bit ^= 1;
	}
}


void cgenie_state::machine_reset()
{
	address_space &space = m_maincpu->space(AS_PROGRAM);
	UINT8 *ROM = memregion("maincpu")->base();

	/* reset the AY8910 to be quiet, since the cgenie BIOS doesn't */
	AYWriteReg(0, 0, 0);
	AYWriteReg(0, 1, 0);
	AYWriteReg(0, 2, 0);
	AYWriteReg(0, 3, 0);
	AYWriteReg(0, 4, 0);
	AYWriteReg(0, 5, 0);
	AYWriteReg(0, 6, 0);
	AYWriteReg(0, 7, 0x3f);
	AYWriteReg(0, 8, 0);
	AYWriteReg(0, 9, 0);
	AYWriteReg(0, 10, 0);

	/* wipe out color RAM */
	memset(&ROM[0x0f000], 0x00, 0x0400);

	/* wipe out font RAM */
	memset(&ROM[0x0f400], 0xff, 0x0400);

	if( ioport("DSW0")->read() & 0x80 )
	{
		logerror("cgenie floppy discs enabled\n");
	}
	else
	{
		logerror("cgenie floppy discs disabled\n");
	}

	/* copy DOS ROM, if enabled or wipe out that memory area */
	if( ioport("DSW0")->read() & 0x40 )
	{
		if ( ioport("DSW0")->read() & 0x80 )
		{
			space.install_read_bank(0xc000, 0xdfff, "bank10");
			space.nop_write(0xc000, 0xdfff);
			membank("bank10")->set_base(&ROM[0x0c000]);
			logerror("cgenie DOS enabled\n");
			memcpy(&ROM[0x0c000],&ROM[0x10000], 0x2000);
		}
		else
		{
			space.nop_readwrite(0xc000, 0xdfff);
			logerror("cgenie DOS disabled (no floppy image given)\n");
		}
	}
	else
	{
		space.nop_readwrite(0xc000, 0xdfff);
		logerror("cgenie DOS disabled\n");
		memset(&memregion("maincpu")->base()[0x0c000], 0x00, 0x2000);
	}

	/* copy EXT ROM, if enabled or wipe out that memory area */
	if( ioport("DSW0")->read() & 0x20 )
	{
		space.install_rom(0xe000, 0xefff, 0); // mess 0135u3 need to check
		logerror("cgenie EXT enabled\n");
		memcpy(&memregion("maincpu")->base()[0x0e000],
				&memregion("maincpu")->base()[0x12000], 0x1000);
	}
	else
	{
		space.nop_readwrite(0xe000, 0xefff);
		logerror("cgenie EXT disabled\n");
		memset(&memregion("maincpu")->base()[0x0e000], 0x00, 0x1000);
	}

	m_cass_level = 0;
	m_cass_bit = 1;
}

void cgenie_state::machine_start()
{
	address_space &space = m_maincpu->space(AS_PROGRAM);
	UINT8 *gfx = memregion("gfx2")->base();
	int i;

	/* initialize static variables */
	m_irq_status = 0;
	m_motor_drive = 0;
	m_head = 0;
	m_tv_mode = -1;
	m_port_ff = 0xff;

	/*
	 * Every fifth cycle is a wait cycle, so I reduced
	 * the overlocking by one fitfth
	 * Underclocking causes the tape loading to not work.
	 */
//  cpunum_set_clockscale(machine(), 0, 0.80);

	/* Initialize some patterns to be displayed in graphics mode */
	for( i = 0; i < 256; i++ )
		memset(gfx + i * 8, i, 8);

	/* set up RAM */
	space.install_read_bank(0x4000, 0x4000 + m_ram->size() - 1, "bank1");
	space.install_write_handler(0x4000, 0x4000 + m_ram->size() - 1, write8_delegate(FUNC(cgenie_state::cgenie_videoram_w),this));
	m_videoram = m_ram->pointer();
	membank("bank1")->set_base(m_ram->pointer());
	machine().scheduler().timer_pulse(attotime::from_hz(11025), timer_expired_delegate(FUNC(cgenie_state::handle_cassette_input),this));
}

/*************************************
 *
 *              Port handlers.
 *
 *************************************/

/* used bits on port FF */
#define FF_CAS  0x01           /* tape output signal */
#define FF_BGD0 0x04           /* background color enable */
#define FF_CHR1 0x08           /* charset 0xc0 - 0xff 1:fixed 0:defined */
#define FF_CHR0 0x10           /* charset 0x80 - 0xbf 1:fixed 0:defined */
#define FF_CHR  (FF_CHR0 | FF_CHR1)
#define FF_FGR  0x20           /* 1: "hi" resolution graphics, 0: text mode */
#define FF_BGD1 0x40           /* background color select 1 */
#define FF_BGD2 0x80           /* background color select 2 */
#define FF_BGD  (FF_BGD0 | FF_BGD1 | FF_BGD2)

WRITE8_MEMBER( cgenie_state::cgenie_port_ff_w )
{
	int port_ff_changed = m_port_ff ^ data;

	m_cassette->output(data & 0x01 ? -1.0 : 1.0 );

	/* background bits changed ? */
	if( port_ff_changed & FF_BGD )
	{
		unsigned char r, g, b;

		if( data & FF_BGD0 )
		{
			r = 112;
			g = 0;
			b = 112;
		}
		else
		{
			if( m_tv_mode == 0 )
			{
				switch( data & (FF_BGD1 + FF_BGD2) )
				{
				case FF_BGD1:
					r = 112;
					g = 40;
					b = 32;
					break;
				case FF_BGD2:
					r = 40;
					g = 112;
					b = 32;
					break;
				case FF_BGD1 + FF_BGD2:
					r = 72;
					g = 72;
					b = 72;
					break;
				default:
					r = 0;
					g = 0;
					b = 0;
					break;
				}
			}
			else
			{
				r = 15;
				g = 15;
				b = 15;
			}
		}
		m_palette->set_pen_color(0, r, g, b);
	}

	/* character mode changed ? */
	if( port_ff_changed & FF_CHR )
	{
		m_font_offset[2] = (data & FF_CHR0) ? 0x00 : 0x80;
		m_font_offset[3] = (data & FF_CHR1) ? 0x00 : 0x80;
	}

	/* graphics mode changed ? */
	if( port_ff_changed & FF_FGR )
	{
		cgenie_mode_select(data & FF_FGR);
	}

	m_port_ff = data;
}


READ8_MEMBER( cgenie_state::cgenie_port_ff_r )
{
	UINT8   data = m_port_ff & ~0x01;

	data |= m_cass_bit;

	return data;
}

int cgenie_state::cgenie_port_xx_r( int offset )
{
	return 0xff;
}

/*************************************
 *                                   *
 *      Memory handlers              *
 *                                   *
 *************************************/


READ8_MEMBER( cgenie_state::cgenie_psg_port_a_r )
{
	return m_psg_a_inp;
}

READ8_MEMBER( cgenie_state::cgenie_psg_port_b_r )
{
	if( m_psg_a_out < 0xd0 )
	{
		/* comparator value */
		m_psg_b_inp = 0x00;

		if( ioport("JOY0")->read() > m_psg_a_out )
			m_psg_b_inp |= 0x80;

		if( ioport("JOY1")->read() > m_psg_a_out )
			m_psg_b_inp |= 0x40;

		if( ioport("JOY2")->read() > m_psg_a_out )
			m_psg_b_inp |= 0x20;

		if( ioport("JOY3")->read() > m_psg_a_out )
			m_psg_b_inp |= 0x10;
	}
	else
	{
		/* read keypad matrix */
		m_psg_b_inp = 0xFF;

		if( !(m_psg_a_out & 0x01) )
			m_psg_b_inp &= ~ioport("KP0")->read();

		if( !(m_psg_a_out & 0x02) )
			m_psg_b_inp &= ~ioport("KP1")->read();

		if( !(m_psg_a_out & 0x04) )
			m_psg_b_inp &= ~ioport("KP2")->read();

		if( !(m_psg_a_out & 0x08) )
			m_psg_b_inp &= ~ioport("KP3")->read();

		if( !(m_psg_a_out & 0x10) )
			m_psg_b_inp &= ~ioport("KP4")->read();

		if( !(m_psg_a_out & 0x20) )
			m_psg_b_inp &= ~ioport("KP5")->read();
	}
	return m_psg_b_inp;
}

WRITE8_MEMBER( cgenie_state::cgenie_psg_port_a_w )
{
	m_psg_a_out = data;
}

WRITE8_MEMBER( cgenie_state::cgenie_psg_port_b_w )
{
	m_psg_b_out = data;
}

READ8_MEMBER( cgenie_state::cgenie_status_r )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, return 0 */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return 0;
	return fdc->status_r(space, offset);
}

READ8_MEMBER( cgenie_state::cgenie_track_r )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, return 0xff */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return 0xff;
	return fdc->track_r(space, offset);
}

READ8_MEMBER( cgenie_state::cgenie_sector_r )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, return 0xff */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return 0xff;
	return fdc->sector_r(space, offset);
}

READ8_MEMBER( cgenie_state::cgenie_data_r )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, return 0xff */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return 0xff;
	return fdc->data_r(space, offset);
}

WRITE8_MEMBER( cgenie_state::cgenie_command_w )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, return immediately */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return;
	fdc->command_w(space, offset, data);
}

WRITE8_MEMBER( cgenie_state::cgenie_track_w )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, ignore the write */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return;
	fdc->track_w(space, offset, data);
}

WRITE8_MEMBER( cgenie_state::cgenie_sector_w )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, ignore the write */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return;
	fdc->sector_w(space, offset, data);
}

WRITE8_MEMBER( cgenie_state::cgenie_data_w )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	/* If the floppy isn't emulated, ignore the write */
	if( (ioport("DSW0")->read() & 0x80) == 0 )
		return;
	fdc->data_w(space, offset, data);
}

READ8_MEMBER( cgenie_state::cgenie_irq_status_r )
{
	int result = m_irq_status;

	m_irq_status &= ~(IRQ_TIMER | IRQ_FDC);
	return result;
}

INTERRUPT_GEN_MEMBER(cgenie_state::cgenie_timer_interrupt)
{
	if( (m_irq_status & IRQ_TIMER) == 0 )
	{
		m_irq_status |= IRQ_TIMER;
		m_maincpu->set_input_line(0, HOLD_LINE);
	}
}

WRITE_LINE_MEMBER(cgenie_state::cgenie_fdc_intrq_w)
{
	/* if disc hardware is not enabled, do not cause an int */
	if (!( ioport("DSW0")->read() & 0x80 ))
		return;

	if (state)
	{
		if( (m_irq_status & IRQ_FDC) == 0 )
		{
			m_irq_status |= IRQ_FDC;
			m_maincpu->set_input_line(0, HOLD_LINE);
		}
	}
	else
	{
		m_irq_status &= ~IRQ_FDC;
	}
}

const wd17xx_interface cgenie_wd17xx_interface =
{
	DEVCB_NULL,
	DEVCB_DRIVER_LINE_MEMBER(cgenie_state,cgenie_fdc_intrq_w),
	DEVCB_NULL,
	{FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
};

WRITE8_MEMBER( cgenie_state::cgenie_motor_w )
{
	fd1793_device *fdc = machine().device<fd1793_device>("wd179x");
	UINT8 drive = 255;

	logerror("cgenie motor_w $%02X\n", data);

	if( data & 1 )
		drive = 0;
	if( data & 2 )
		drive = 1;
	if( data & 4 )
		drive = 2;
	if( data & 8 )
		drive = 3;

	if( drive > 3 )
		return;

	/* mask head select bit */
		m_head = (data >> 4) & 1;

	/* currently selected drive */
	m_motor_drive = drive;

	fdc->set_drive(drive);
	fdc->set_side(m_head);
}

/*************************************
 *      Keyboard                     *
 *************************************/
READ8_MEMBER( cgenie_state::cgenie_keyboard_r )
{
	int result = 0;

	if( offset & 0x01 )
		result |= ioport("ROW0")->read();

	if( offset & 0x02 )
		result |= ioport("ROW1")->read();

	if( offset & 0x04 )
		result |= ioport("ROW2")->read();

	if( offset & 0x08 )
		result |= ioport("ROW3")->read();

	if( offset & 0x10 )
		result |= ioport("ROW4")->read();

	if( offset & 0x20 )
		result |= ioport("ROW5")->read();

	if( offset & 0x40 )
		result |= ioport("ROW6")->read();

	if( offset & 0x80 )
		result |= ioport("ROW7")->read();

	return result;
}

/*************************************
 *      Video RAM                    *
 *************************************/

int cgenie_state::cgenie_videoram_r( int offset )
{
	UINT8 *videoram = m_videoram;
	return videoram[offset];
}

WRITE8_MEMBER( cgenie_state::cgenie_videoram_w )
{
	UINT8 *videoram = m_videoram;
	/* write to video RAM */
	if( data == videoram[offset] )
		return;                /* no change */
	videoram[offset] = data;
}

READ8_MEMBER( cgenie_state::cgenie_colorram_r )
{
	return m_colorram[offset] | 0xf0;
}

WRITE8_MEMBER( cgenie_state::cgenie_colorram_w )
{
	/* only bits 0 to 3 */
	data &= 15;
	/* nothing changed ? */
	if( data == m_colorram[offset] )
		return;

	/* set new value */
	m_colorram[offset] = data;
	/* make offset relative to video frame buffer offset */
	offset = (offset + (cgenie_get_register(12) << 8) + cgenie_get_register(13)) & 0x3ff;
}

READ8_MEMBER( cgenie_state::cgenie_fontram_r )
{
	return m_fontram[offset];
}

WRITE8_MEMBER( cgenie_state::cgenie_fontram_w )
{
	UINT8 *dp;

	if( data == m_fontram[offset] )
		return;                /* no change */

	/* store data */
	m_fontram[offset] = data;

	/* convert eight pixels */
	dp = const_cast<UINT8 *>(m_gfxdecode->gfx(0)->get_data(256 + offset/8) + (offset % 8) * m_gfxdecode->gfx(0)->width());
	dp[0] = (data & 0x80) ? 1 : 0;
	dp[1] = (data & 0x40) ? 1 : 0;
	dp[2] = (data & 0x20) ? 1 : 0;
	dp[3] = (data & 0x10) ? 1 : 0;
	dp[4] = (data & 0x08) ? 1 : 0;
	dp[5] = (data & 0x04) ? 1 : 0;
	dp[6] = (data & 0x02) ? 1 : 0;
	dp[7] = (data & 0x01) ? 1 : 0;
}

/*************************************
 *
 *      Interrupt handlers.
 *
 *************************************/

INTERRUPT_GEN_MEMBER(cgenie_state::cgenie_frame_interrupt)
{
	if( m_tv_mode != (ioport("DSW0")->read() & 0x10) )
	{
		m_tv_mode = ioport("DSW0")->read() & 0x10;
		/* force setting of background color */
		m_port_ff ^= FF_BGD0;
		cgenie_port_ff_w(m_maincpu->space(AS_PROGRAM), 0, m_port_ff ^ FF_BGD0);
	}
}


READ8_MEMBER(cgenie_state::cgenie_sh_control_port_r)
{
	return m_control_port;
}

WRITE8_MEMBER(cgenie_state::cgenie_sh_control_port_w)
{
	m_control_port = data;
	m_ay8910->address_w(space, offset, data);
}