summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/galgame.cpp
blob: f8bb996747adee039c9e6535a2e05a13ec63874b (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                                       

  
               
 
                                
 
                                











                                             
                                                                                          
                                                    

                                                

















                                                                          






                                      
                                        
                                              
                                                                                                                
                                             
                                                     
                                              
                                                  







                                       
                                     
 



                        
                              


                                
                                   

                              
                                   











                                                                      
                                      
 





                                                


                                                                                                                


                                    

                                                 



                                 
                                           

                              

                                           
                         
                                          


                            
                                         



                              


                                                                              




                                           
                                                                                                   







                                                                 

                                                            




                                           
                                                                                                   







                                                                 

                                                            














                                                                      
                                                                                                                         
 
                                                      
                                                             
         
                                                                                                 



                 
                                    
 
                   

 
                                     
 
                   

 
                                    
 
                   

 
                                     
 
                   



                                                                        
                                  
                 
                                                                            
                         

                                                                                   
                         


                                                                             



                 
                                                            




                                                         


                                                                           











                                       



                                                                       







                                                               


                                                                                





                                                                                       
                                                          


                                                                      

                                                                      









                                                                                       
                                       
 
                     

 
                                                                            
                                       

                                                                   
                                                                        


                                                                                           


               
                                                              
 
                                                       


                    
                                                      
 
                           
         
                                                                
                                


         
                                      
 



                                       

 



                                                           
                                      
                                                                          
                                                                                 




                                                       

                                                
                                                                             
                                      
 
                                              
 


                  

                                                                                                      
                                                        
                                                                                                              











































                                                                               
                                               
 
                                                           
                                                



























                                                                                     
                                                                      




                                                                             
                                                                              





                                                                             
                                                                              








                                                                             
                                                                       






                                                     
                           




                                                    

 
                                                                                                                                                      
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek
/*

    Galaxy Game

    Driver by Mariusz Wojcieszek

    First commercial video game.

*/

#include "emu.h"
#include "cpu/t11/t11.h"


#define MAX_POINTS 2048

class galaxygame_state : public driver_device
{
public:
	galaxygame_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag),
		m_maincpu(*this, "maincpu"),
		m_palette(*this, "palette")  { }

	UINT16 m_clk;

	UINT16 m_x;
	UINT16 m_y;

	INT16 m_mq;
	INT16 m_ac;

	struct
	{
		UINT16 x;
		UINT16 y;
	} m_point_work_list[MAX_POINTS], m_point_display_list[MAX_POINTS];

	int m_point_work_list_index;
	int m_point_display_list_index;
	int m_interrupt;
	DECLARE_READ16_MEMBER(ke_r);
	DECLARE_WRITE16_MEMBER(ke_w);
	DECLARE_READ16_MEMBER(x_r);
	DECLARE_WRITE16_MEMBER(x_w);
	DECLARE_READ16_MEMBER(y_r);
	DECLARE_WRITE16_MEMBER(y_w);
	DECLARE_WRITE16_MEMBER(clk_w);
	DECLARE_DRIVER_INIT(galaxygame);
	virtual void machine_reset() override;
	UINT32 screen_update_galaxygame(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
	INTERRUPT_GEN_MEMBER(galaxygame_irq);
	IRQ_CALLBACK_MEMBER(galaxygame_irq_callback);
	required_device<cpu_device> m_maincpu;
	required_device<palette_device> m_palette;
};

/*************************************
 *
 *  KE11 Extended Artithmetic Element
 *
 *************************************/

READ16_MEMBER(galaxygame_state::ke_r)
{
	UINT16 ret;

	switch( offset )
	{
		case 0: // DIV
			ret = 0;
			break;
		case 1: // AC
			ret = m_ac;
			break;
		case 2: // MQ
			ret = m_mq;
			break;
		case 7: // ASH
			ret = 0;
			break;
		default:
			ret = 0;
			logerror("Unhandled KE read (%d)\n", offset );
			break;
	}
	return ret;
}

WRITE16_MEMBER(galaxygame_state::ke_w)
{
	switch( offset )
	{
		case 0: // DIV
			{
				if ( data != 0 )
				{
					INT32 dividend = (INT32)((UINT32)((UINT16)m_ac << 16) | (UINT16)(m_mq));
					m_mq = dividend / (INT16)data;
					m_ac = dividend % (INT16)data;
				}
				else
				{
					m_mq = 0;
					m_ac = 0;
				}
			}
			break;
		case 1: // AC
			m_ac = (INT16)data;
			break;
		case 2: // MQ
			m_mq = (INT16)data;
			if (m_mq < 0)
			{
				m_ac = -1;
			}
			else
			{
				m_ac = 0;
			}
			break;
		case 3: // X
			{
				INT32 mulres = (INT32)m_mq*(INT32)(INT16)data;
				m_ac = mulres >> 16;
				m_mq = mulres & 0xffff;
			}
			break;
		case 6: // LSH
			{
				data &= 63;
				INT32 val = (INT32)((UINT32)((UINT16)m_ac << 16) | (UINT16)(m_mq));
				if ( data < 32 )
				{
					val = val << data;
				}
				else
				{
					val = val >> (64 - data);
				}
				m_mq = val & 0xffff;
				m_ac = (val >> 16) & 0xffff;
			}
			break;
		case 7: // ASH
			{
				data &= 63;
				INT32 val = (INT32)((UINT32)((UINT16)m_ac << 16) | (UINT16)(m_mq));
				if ( data < 32 )
				{
					val = val << data;
				}
				else
				{
					val = val >> (64 - data);
				}
				m_mq = val & 0xffff;
				m_ac = (val >> 16) & 0xffff;
			}
			break;
		default:
			logerror("Unhandled KE write (%d)\n", offset);
			break;
	}

}

/*************************************
 *
 *  Video
 *
 *************************************/

UINT32 galaxygame_state::screen_update_galaxygame(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	bitmap.fill(m_palette->black_pen(), cliprect);
	for (int i = 0; i < m_point_display_list_index; i++ )
	{
		bitmap.pix16(m_point_display_list[i].x >> 7, m_point_display_list[i].y >> 7) = 1;
	}
	return 0;
}

READ16_MEMBER(galaxygame_state::x_r)
{
	return m_x;
}

WRITE16_MEMBER(galaxygame_state::x_w)
{
	m_x = data;
}

READ16_MEMBER(galaxygame_state::y_r)
{
	return m_y;
}

WRITE16_MEMBER(galaxygame_state::y_w)
{
	m_y = data;
	if ( data == 0x0101 )
	{
		// send points list to display device
		// seems to happen on first 0x0101 write after interrupt
		if ( m_interrupt )
		{
			for ( int i = 0; i < m_point_work_list_index ; i++ )
			{
				m_point_display_list[i].x = m_point_work_list[i].x;
				m_point_display_list[i].y = m_point_work_list[i].y;
			}
			m_point_display_list_index = m_point_work_list_index;
			m_point_work_list_index = 0;
			m_interrupt = 0;
		}
	}
	else
	{
		if ( m_point_work_list_index >= MAX_POINTS )
		{
			logerror("Work list overflow\n");
		}
		else
		{
			m_point_work_list[m_point_work_list_index].x = m_x;
			m_point_work_list[m_point_work_list_index].y = m_y;
			m_point_work_list_index++;
		}
	}
}

/*************************************
 *
 *  Inputs
 *
 *************************************/

static INPUT_PORTS_START( galaxygame )
	PORT_START("COINAC")
	PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_COIN3 ) // 25 cents, left
	PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_COIN1 ) // 10 cents, left
	PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_COIN4 ) // 25 cents, right
	PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_COIN2 ) // 10 cents, right

	PORT_START("SR")
	PORT_DIPNAME( 0x8000, 0x0000, "Gravity" )
	PORT_DIPSETTING(      0x0000, "Positive Gravity" )
	PORT_DIPSETTING(      0x8000, "Negative Gravity" )
	PORT_DIPNAME( 0x4000, 0x0000, "Sun" )
	PORT_DIPSETTING(      0x0000, "Sun (& Gravity)" )
	PORT_DIPSETTING(      0x4000, "No Sun (& No Gravity)" )
	PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) // fire
	PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) // hyper
	PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) // thrust
	PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY PORT_PLAYER(1)
	PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY PORT_PLAYER(1)

	PORT_DIPNAME( 0x0080, 0x0000, "Speed" )
	PORT_DIPSETTING(      0x0000, "Slow Speed" )
	PORT_DIPSETTING(      0x0080, "Fast Speed" )
	PORT_DIPNAME( 0x0040, 0x0000, DEF_STR( Players ) )
	PORT_DIPSETTING(      0x0000, "Two Players" )
	PORT_DIPSETTING(      0x0040, "One Player" )
	PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
	PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2)
	PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2)
	PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY PORT_PLAYER(2)
	PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY PORT_PLAYER(2)
INPUT_PORTS_END

/*************************************
 *
 *  Machine
 *
 *************************************/

WRITE16_MEMBER(galaxygame_state::clk_w)
{
	m_clk = data;
}

static ADDRESS_MAP_START( galaxygame_map, AS_PROGRAM, 16, galaxygame_state )
	AM_RANGE(0x0000, 0x1fff) AM_RAM
	AM_RANGE(0xfec0, 0xfecf) AM_READWRITE(ke_r, ke_w)
	AM_RANGE(0xff52, 0xff53) AM_READWRITE(y_r, y_w) // 177522 Y
	AM_RANGE(0xff54, 0xff55) AM_READ_PORT("COINAC") // 177524 COINAC
	AM_RANGE(0xff5a, 0xff5b) AM_READWRITE(x_r, x_w) // 177532 X
	AM_RANGE(0xff5c, 0xff5d) AM_READ_PORT("SR")     // 177534 SR
	AM_RANGE(0xff66, 0xff67) AM_WRITE(clk_w)        // 177546 KW11 line frequency clock
ADDRESS_MAP_END


IRQ_CALLBACK_MEMBER(galaxygame_state::galaxygame_irq_callback)
{
	device.execute().set_input_line(1, CLEAR_LINE);
	return 0x40;
}

INTERRUPT_GEN_MEMBER(galaxygame_state::galaxygame_irq)
{
	if ( m_clk & 0x40 )
	{
		device.execute().set_input_line(1, ASSERT_LINE);
		m_interrupt = 1;
	}
}

void galaxygame_state::machine_reset()
{
	m_clk = 0x00;
	m_point_work_list_index = 0;
	m_point_display_list_index = 0;
	m_interrupt = 0;
}

static MACHINE_CONFIG_START( galaxygame, galaxygame_state )

	MCFG_CPU_ADD("maincpu", T11, 3000000 )
	MCFG_CPU_PROGRAM_MAP(galaxygame_map)
	MCFG_T11_INITIAL_MODE(5 << 13)
	MCFG_CPU_PERIODIC_INT_DRIVER(galaxygame_state, galaxygame_irq, 60)
	MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(galaxygame_state,galaxygame_irq_callback)

	/* video hardware */
	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(60)
	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
	MCFG_SCREEN_SIZE(512, 512)
	MCFG_SCREEN_VISIBLE_AREA(0, 511, 0, 511)
	MCFG_SCREEN_UPDATE_DRIVER(galaxygame_state, screen_update_galaxygame)
	MCFG_SCREEN_PALETTE("palette")

	MCFG_PALETTE_ADD_MONOCHROME("palette")

MACHINE_CONFIG_END

ROM_START(galgame)
	// Original Galaxy Game listing, the one used in the 2nd hardware revision (blue dual cabinet)
	// PALX11 V413R 19-NOV-71 8:46
	ROM_REGION( 0x20000, "code", ROMREGION_ERASE00 )
	ROM_LOAD( "sw97.lst", 0x00000, 0x1f062, CRC(838018a5) SHA1(e3c47c5cf78299650b031ec49fde7d9e4024a759) )
ROM_END

/*************************************
 *
 *  Code loading
 *
 *************************************/

static UINT8 read_uint16(UINT16 *pval, int pos, const UINT8* line, int linelen)
{
	int i;

	*pval = 0;
	if ( linelen < (pos + 6) )
	{
		return 0;
	}

	for ( i = 0; i < 6; i++ )
	{
		*pval <<= 3;
		*pval |= line[pos + i] - 0x30;
	}
	return 1;
}

static UINT8 read_uint8(UINT8 *pval, int pos, const UINT8* line, int linelen)
{
	int i;

	*pval = 0;
	if ( linelen < (pos + 3) )
	{
		return 0;
	}

	for ( i = 0; i < 3; i++ )
	{
		*pval <<= 3;
		*pval |= line[pos + i] - 0x30;
	}
	return 1;
}

DRIVER_INIT_MEMBER(galaxygame_state,galaxygame)
{
	address_space &main = m_maincpu->space(AS_PROGRAM);
	UINT8 *code = memregion("code")->base();

	int filepos = 0, linepos, linelen;
	UINT8 line[256];
	UINT16 address;
	UINT16 val;
	UINT8 val8;

	//load lst file
	while( code[filepos] != 0 )
	{
		linepos = 0;
		while( code[filepos] != 0x0d )
		{
			line[linepos++] = code[filepos++];
		}
		line[linepos] = 0;
		filepos += 2;
		linelen = linepos;

		if ( linelen == 0 )
		{
			continue;
		}
		if ( ( line[8] != ' ' ) && read_uint16(&address, 7, line, linelen ) )
		{
			if ( (linelen >= 15+6) && (line[15] != ' ') )
			{
				read_uint16(&val, 15, line, linelen);
				main.write_word(address, val, 0xffff);
				address += 2;

				if ( (linelen >= 22+6) && (line[22] != ' ') )
				{
					read_uint16(&val, 22, line, linelen);
					main.write_word(address, val, 0xffff);
					address += 2;
				}

				if ( (linelen >= 29+6) && (line[29] != ' ') )
				{
					read_uint16(&val, 29, line, linelen);
					main.write_word(address, val, 0xffff);
					address += 2;
				}

			}
			else
			{
				if ( (linelen >= 18+3) && (line[18] != ' ') )
				{
					read_uint8(&val8, 18, line, linelen);
					main.write_byte(address, val8);
					address += 1;
				}
			}

		}
	}

	// set startup code
	main.write_word(0, 012700); /* MOV #0, R0 */
	main.write_word(2, 0);
	main.write_word(4, 0x8d00); /* MTPS R0 */
	main.write_word(6, 000167); /* JMP 0500*/
	main.write_word(8, 000500 - 10);
}

GAME(1971, galgame, 0, galaxygame, galaxygame, galaxygame_state, galaxygame, ROT270, "Computer Recreations, Inc", "Galaxy Game", MACHINE_NO_SOUND_HW )