summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/littlerb.c
blob: 419352c85d4b19b31ac1af92876f986ef875022d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11






                  



                                    

  
      
 

                                                                                                   
 

                                                                                               
 


                                                                                                    
                                                                                                
                                                                   
 




                                                                                            
 


                                                                                       


      
 









































                                                           
                
                              
                         
                      
 

                                                            


                                           
                                                                                        
                                                    


                                                    
                                           
         

                                
 



                                              



                                  



                                         
                                 



                             
                                              
                                                   
 

                                                 
 

                                             





                                                   
                                                           






























                                                                    
                                                                                   
                 
                 
                    

                                                        
                                                                                                            

                 
 


























                                                                                                          
                                   
                                                                                                              
                                                        
  

 
                                         
 
                                         

 
                                              



                 










                                                      
                                                        
                                                                       
                                                                                 

                                                                                  
 
                                                                                  


                                                                                                






                                                                                                                       
 
                                                         
                                                                                                                
               
 
                                                               
                                                                                                   
               
 



                                      
 

                                              
 

                                            
                                                                                      
 
       
                                                                                                           

                                       
                                                                                                       
         
                                                                
         
 
                                                   

  
                                                                     
 

                                                                                                                       

                                                                                                                       


 




                                                  
                                                          
 
                                                                      

                                                                        


 



                                                                                                           
                                                                                               
 
                                                   
 
 
                                                                                       
 
                                                                      
                                                                                                           
                                                                                               
                                          



                                                                                                                             
                                                                                      
         


            
                                                           

                                                                                             

                                                                                                       

                                              
 

 





 
                                                             
 
                                                                      
                                                                                          

 
                                             
 
                                                                                                                                          
                       
 
                           
         



                                                                             

         
                   

 
                 
                                              
 

                      
                                   
                 
                                             
                         
                                                                                                                                                          
                         
 

                                                                                                                                                                                                               

                                                                                                                           
                 
 
                                                                                                                                               




                                     
                                              
                         
                                                                                                                                                              
                         


                                                                                           
                                                                 


                    
                                                                                                                                                           



                 


                       

                                                           


                       

                                                           



                       
                                                               


                       

                                                       
                                                                                                             





                      






                                                                                                                                            
                                                  
 


                                                                       

 
                                                  
 


                                                                       

 
                                                                         





                                                        


                                                                                     
                                                                   


                                                        

               
                                                                                      
                                                          
 
                                                              


                         

                                    
                                       








































                                                          
                                             



                                                          
                                       














                                                                                      
                                                                                                                                   
 
                                       










                                                                                      
 

                                                                                                                   
                                                                                                                     
 

                                 

                                                                                       



                 
                                                               
 




                               









                                                                                  


                      
                           
         
                                                        


         
                                  
 

                                                                                 
 

                                                                                

 
                                                                                   





 
                                                                                                                                                             
 
                
                       
                                                                                               
 




                                               
                                                                                               
                                                                   
 

                                          
 









                                                                                                     
                                                                 
                         
                                                                                    
                         
 
                                   



                 
                                                           
 
                                                                      
                     
                        

                                                   

                      
                        






                                                                                                                     


                                    
                                                
         
                                                                                         
 
                                                           
 




                                                                                                
 



                                                                                                                                                                                                                                                    
 

                                                                                     
 












                                                                                                                                  
                            


                                                                                                                                                    
 
 
 




                                                                                                                                                        
 
 




                                                                                                                                                                                                                                                                                                                                            
 



                                                         
 
 






                                                    



                                                  
                                         
                                                                                                                                                                                                                                                                                                                                            
 



                                                         
 






                                                    















                                                                                               

                                    



                                                                                                                             








                                                                                                                 
 
 





























                                                                                                                                                                                                                   
 
 

                                  
         

 

 
                                                       

                                                 
                                                                                                      
 
                                         
                                                                               
                                                          
                                     
                                                        
                                                                         
 
 
                                  
 
                                                      
                                                          
 
                                                       

                                                           
                            

                                                       
                            
                                                       
                  

                     
                                                             


                                                                                                                     
                                                               

                                                                                                              


       
                                                                                                                                          
/* Little Robin */

/* driver by
Pierpaolo Prazzoli
David Haywood
*/


#define littlerb_printf logerror
#define littlerb_alt_printf logerror

/*

Notes:

VDP (Blitter) handling is not 100% correct
A brief original video (recorded by Dox) can be seen at https://www.youtube.com/watch?v=8THpeogarUk

Overall addressing / auto-increment etc. of the VDP device is not fully understood, but for now
appears to be good enough for the game.

How we distinguish between mode setting (clear, copy, cliprect etc.) VDP commands and actual sprite
commands is not yet understood.  All 'sprite' sections of the blit list seem to be terminated with
a 0x0000 word, but it isn't clear how the blocks are started, the current method relies on some bits
of the sprite data offset to determine if we're sprite data, or a command.  Maybe this is just a
quirk of the hardware, and you can't have sprites at those offsets?

Copy / Scroll are not yet implemented, see the Smileys between scenes in the original video.
 (Clipping is implemented, but might be per layer, so you do see the sprites vanish, but no
   smileys are drawn)

How big are the actual framebuffers?  Are both also double buffered?

Sound pitch is directly correlated with irqs, scanline timings and pixel clock,
so it's surely not 100% correct. Sound sample playbacks looks fine at current time tho.

------



Dip sw.1
--------
             | Coin 1 | Coin 2  |
              1  2  3   4  5  6   7  8   Coin  Play
---------------------------------------------------
 Coins        -  -  -   -  -  -           1     4
              +  -  -   +  -  -           1     3
              -  +  -   -  +  -           1     2
              +  +  -   +  +  -           1     1
              -  -  +   -  -  +           2     1
              +  -  +   +  -  +           3     1
              -  +  +   -  +  +           4     1
              +  +  +   +  +  +           5     1
 Player                           -  -    2
                                  +  -    3
                                  -  +    4
                                  +  +    5


Dip sw.2
--------          1  2  3  4  5  6  7  8
-----------------------------------------------------------
 Demo Sound       -                        Yes
                  +                        No
 Mode                -                     Test Mode
                     +                     Game Mode
 Difficulty             -  -  -            0 (Easy)
                        +  -  -            1
                        -  +  -            2 (Normal)
                        +  +  -            3
                        -  -  +            4
                        +  -  +            5
                        -  +  +            6
                        +  +  +            7 (Hardest)
 Bonus                           -  -      Every 150000
                                 +  -      Every 200000
                                 -  +      Every 300000
                                 +  +      No Bonus


*/

#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "video/ramdac.h"
#include "sound/dac.h"

static void littlerb_draw_sprites(running_machine &machine);

class littlerb_state : public driver_device
{
public:
	littlerb_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag),
			m_maincpu(*this, "maincpu"),
			m_dacl(*this, "dacl"),
			m_dacr(*this, "dacr"),
		m_region4(*this, "region4")
	{
		m_1ff80804 = -1;
	}

	required_device<cpu_device> m_maincpu;
	required_device<dac_device> m_dacl;
	required_device<dac_device> m_dacr;
	required_shared_ptr<UINT16> m_region4;
	UINT16 m_vdp_address_low;
	UINT16 m_vdp_address_high;
	UINT16 m_vdp_writemode;
	UINT32 m_write_address;

	UINT32 m_write_address_laststart;
	UINT32 m_write_address_lastend;

	UINT8 m_paldac[3][0x100];
	int m_paldac_select;
	int m_paldac_offset;
	int m_type2_writes;
	UINT32 m_lasttype2pc;
	UINT8 m_sound_index_l,m_sound_index_r;
	UINT16 m_sound_pointer_l,m_sound_pointer_r;

	bitmap_ind16 *m_temp_bitmap_sprites;
	bitmap_ind16 *m_temp_bitmap_sprites_back;


	DECLARE_WRITE16_MEMBER(spritelist_w);
	DECLARE_WRITE16_MEMBER(region4_w);
	DECLARE_READ16_MEMBER(buffer_status_r);
	DECLARE_READ16_MEMBER(littlerb_vdp_r);
	DECLARE_WRITE16_MEMBER(littlerb_vdp_w);
	DECLARE_WRITE16_MEMBER(littlerb_l_sound_w);
	DECLARE_WRITE16_MEMBER(littlerb_r_sound_w);
	DECLARE_CUSTOM_INPUT_MEMBER(littlerb_frame_step_r);

	int m_1ff80804;
	int m_listoffset;
	UINT16* m_spritelist;

	DECLARE_READ16_MEMBER( littlerb_1ff80800_r )
	{
		littlerb_printf("littlerb_1ff80800_r\n");
		return 0x0000;
	}

	DECLARE_WRITE16_MEMBER( littlerb_1ff80800_w )
	{
		littlerb_printf("littlerb_1ff80800_w %04x\n", data);
	}

	DECLARE_READ16_MEMBER( littlerb_1ff80802_r )
	{
		littlerb_printf("littlerb_1ff80802_r\n");
		return 0x0000;
	}

	DECLARE_WRITE16_MEMBER( littlerb_1ff80802_w )
	{
		littlerb_printf("littlerb_1ff80802_w %04x\n", data);
	}

	DECLARE_WRITE16_MEMBER( littlerb_1ff80804_w )
	{
		littlerb_printf("littlerb_1ff80804_w %04x\n", data);

		if ((!(m_spritelist[2] & 0x1000)) && (!(m_spritelist[1] & 0x1000)))
		{
		}
		else
		{
			if (!(m_spritelist[2] & 0x1000))
				m_temp_bitmap_sprites_back->fill(0, m_temp_bitmap_sprites_back->cliprect());

		}

		littlerb_draw_sprites(space.machine());


		m_listoffset = 0;
		memset(m_spritelist, 0x00, 0x20000); // clear out the list.. I think it's commands anyway?

	}

	DECLARE_WRITE16_MEMBER( littlerb_18000012_w )
	{
		littlerb_printf("littlerb_18000012_w %04x\n", data);
		// edfc / fffc alternating (select double buffering?)
	}

	DECLARE_WRITE16_MEMBER( littlerb_18000014_w )
	{
		littlerb_printf("littlerb_18000014_w %04x\n", data);
		// dosen't seem to be the draw trigger, or you get broken platforms..


	}

	DECLARE_WRITE16_MEMBER( littlerb_1800003c_w )
	{
		littlerb_printf("littlerb_1800003c_w %04x\n", data);
		// edfc / fffc alternating (display double buffering?)
	}
	virtual void video_start();
	UINT32 screen_update_littlerb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
	TIMER_DEVICE_CALLBACK_MEMBER(littlerb_scanline);
};


WRITE16_MEMBER(littlerb_state::region4_w)
{
	COMBINE_DATA(&m_region4[offset]);
}

READ16_MEMBER(littlerb_state::buffer_status_r)
{
	return 0;
}


WRITE16_MEMBER(littlerb_state::spritelist_w)
{
	littlerb_printf("spritelist_w %04x\n",  data);

	COMBINE_DATA(&m_spritelist[m_listoffset]);
	m_listoffset++;
}



/* this map is wrong because our VDP access is wrong! */
static ADDRESS_MAP_START( littlerb_vdp_map8, AS_0, 16, littlerb_state )
	// it ends up writing some gfx here (the bubbles when you shoot an enemy)
	AM_RANGE(0x00000000, 0x0007ffff) AM_RAM
	AM_RANGE(0x00080000, 0x003fffff) AM_RAM // temp so it doesn't fill the log

	/* these are definitely written by a non-incrementing access to the VDP */
	AM_RANGE(0x00800000, 0x00800001) AM_DEVWRITE8("^ramdac", ramdac_device, index_w, 0x00ff)
	AM_RANGE(0x00800002 ,0x00800003) AM_DEVWRITE8("^ramdac", ramdac_device, pal_w,   0x00ff)
	AM_RANGE(0x00800004 ,0x00800005) AM_DEVWRITE8("^ramdac", ramdac_device, mask_w,  0x00ff)
	AM_RANGE(0x18000012, 0x18000013) AM_DEVWRITE("^", littlerb_state, littlerb_18000012_w)
	AM_RANGE(0x18000014, 0x18000015) AM_DEVWRITE("^", littlerb_state, littlerb_18000014_w)
	AM_RANGE(0x1800003c, 0x1800003d) AM_DEVWRITE("^", littlerb_state, littlerb_1800003c_w)
	AM_RANGE(0x1ff80800, 0x1ff80801) AM_DEVREADWRITE("^", littlerb_state, littlerb_1ff80800_r, littlerb_1ff80800_w)
	AM_RANGE(0x1ff80802, 0x1ff80803) AM_DEVREADWRITE("^", littlerb_state, littlerb_1ff80802_r, littlerb_1ff80802_w)
	AM_RANGE(0x1ff80804, 0x1ff80805) AM_DEVREADWRITE("^", littlerb_state, buffer_status_r, littlerb_1ff80804_w)
	AM_RANGE(0x1ff80806, 0x1ff80807) AM_RAM AM_DEVWRITE("^", littlerb_state, spritelist_w)

	// most gfx end up here including the sprite list
	AM_RANGE(0x1ff80000, 0x1fffffff) AM_RAM AM_DEVWRITE("^", littlerb_state, region4_w)  AM_SHARE("region4")
ADDRESS_MAP_END

static ADDRESS_MAP_START( ramdac_map, AS_0, 8, littlerb_state )
	AM_RANGE(0x000, 0x3ff) AM_DEVREADWRITE("ramdac",ramdac_device,ramdac_pal_r,ramdac_rgb888_w)
ADDRESS_MAP_END

static RAMDAC_INTERFACE( ramdac_intf )
{
	0
};

/* VDP device to give us our own memory map */
class littlerb_vdp_device;


class littlerb_vdp_device : public device_t,
							public device_memory_interface
{
public:
	littlerb_vdp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
	virtual void device_start() { }
	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const
	{
		return (spacenum == 0) ? &m_space_config : NULL;
	}

	address_space_config        m_space_config;
};

const device_type LITTLERBVDP = &device_creator<littlerb_vdp_device>;

littlerb_vdp_device::littlerb_vdp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, LITTLERBVDP, "LITTLERBVDP", tag, owner, clock),
		device_memory_interface(mconfig, *this),
		m_space_config("littlerb_vdp", ENDIANNESS_LITTLE, 16,32, 0, NULL, *ADDRESS_MAP_NAME(littlerb_vdp_map8))
{
}



/* end VDP device to give us our own memory map */


static void littlerb_recalc_regs(running_machine &machine)
{
	littlerb_state *state = machine.driver_data<littlerb_state>();
	state->m_vdp_address_low = state->m_write_address&0xffff;
	state->m_vdp_address_high = (state->m_write_address>>16)&0xffff;
}


static UINT16 littlerb_data_read(running_machine &machine, UINT16 mem_mask)
{
	littlerb_state *state = machine.driver_data<littlerb_state>();
	UINT32 addr = state->m_write_address >> 3; // almost surely raw addresses are actually shifted by 3
	address_space &vdp_space = machine.device<littlerb_vdp_device>("littlerbvdp")->space();

	return vdp_space.read_word(addr, mem_mask);
}

static void littlerb_data_write(running_machine &machine, UINT16 data, UINT16 mem_mask)
{
	littlerb_state *state = machine.driver_data<littlerb_state>();
	UINT32 addr = state->m_write_address >> 3; // almost surely raw addresses are actually shifted by 3
	address_space &vdp_space = machine.device<littlerb_vdp_device>("littlerbvdp")->space();
	int mode = state->m_vdp_writemode;


	logerror("mode %04x, data %04x, mem_mask %04x (address %08x)\n", mode,  data, mem_mask, state->m_write_address >> 3);

	if ((mode!=0x3800) && (mode !=0x2000) && (mode != 0xe000) && (mode != 0xf800))
	{
	}
	else
	{
		vdp_space.write_word(addr, data, mem_mask);

		// 2000 is used for palette writes which appears to be a RAMDAC, no auto-inc.
		//  1ff80806 is our 'spritelist'
		if (mode!=0x2000 && mode != 0xe000 && addr != 0x1ff80806) state->m_write_address+=0x10;
		littlerb_recalc_regs(machine);
	}




}




static void littlerb_recalc_address(running_machine &machine)
{
	littlerb_state *state = machine.driver_data<littlerb_state>();
	state->m_write_address = state->m_vdp_address_low | state->m_vdp_address_high<<16;
}

READ16_MEMBER(littlerb_state::littlerb_vdp_r)
{
	logerror("%06x littlerb_vdp_r offs %04x mask %04x (address %08x)\n", space.device().safe_pc(), offset, mem_mask, m_write_address);
	UINT16 res = 0;

	switch (offset & 3)
	{
		case 0: res = m_vdp_address_low; break;
		case 1: res = m_vdp_address_high; break;
		case 2: res = littlerb_data_read(machine(), mem_mask); break;
		case 3: res = m_vdp_writemode; break;
	}

	return res;
}

#define LOG_VDP 1
WRITE16_MEMBER(littlerb_state::littlerb_vdp_w)
{
	if (offset!=2)
	{
		if (m_type2_writes)
		{
			if (m_type2_writes>2)
			{
				if (LOG_VDP) logerror("******************************* BIG WRITE OCCURRED BEFORE THIS!!! ****************************\n");
			}

			littlerb_printf("~%06x big write occured with start %08x end %08x (size %04x bytes)\n", m_lasttype2pc, m_write_address_laststart >> 3, m_write_address_lastend >> 3, m_type2_writes*2);

			if (LOG_VDP) logerror("~%06x previously wrote %08x data bytes\n", m_lasttype2pc, m_type2_writes*2);
			m_type2_writes = 0;
		}

		if (LOG_VDP) logerror("%06x littlerb_vdp_w offs %04x data %04x mask %04x\n", space.device().safe_pc(), offset, data, mem_mask);
	}
	else
	{
		if (mem_mask==0xffff)
		{
			if (m_type2_writes==0)
			{
				if (LOG_VDP) logerror("data write started %06x %04x data %04x mask %04x\n", space.device().safe_pc(), offset, data, mem_mask);
			}
			if (m_type2_writes==0) m_write_address_laststart = m_write_address;
			m_write_address_lastend = m_write_address;
			m_type2_writes++;
			m_lasttype2pc = space.device().safe_pc();
		}
		else
		{
			if (LOG_VDP) logerror("xxx %06x littlerb_vdp_w offs %04x data %04x mask %04x\n", space.device().safe_pc(), offset, data, mem_mask);
		}
	}


	switch (offset)
	{
		case 0:
			COMBINE_DATA(&m_vdp_address_low);
			littlerb_recalc_address(machine());
		break;

		case 1:
			COMBINE_DATA(&m_vdp_address_high);
			littlerb_recalc_address(machine());
		break;


		case 2:
		littlerb_data_write(machine(), data, mem_mask);
		break;

		case 3:
			COMBINE_DATA(&m_vdp_writemode);
			int mode = m_vdp_writemode;
			if ((mode!=0x3800) && (mode !=0x2000)) logerror("WRITE MODE CHANGED TO %04x\n",mode);
		break;

	}

}

/* could be slightly different (timing wise, directly related to the irqs), but certainly they smoked some bad pot for this messy way ... */
static UINT8 sound_data_shift(running_machine &machine)
{
	return ((machine.primary_screen->frame_number() % 16) == 0) ? 8 : 0;
}

/* l is SFX, r is BGM (they doesn't seem to share the same data ROM) */
WRITE16_MEMBER(littlerb_state::littlerb_l_sound_w)
{
	m_sound_index_l = (data >> sound_data_shift(machine())) & 0xff;
	m_sound_pointer_l = 0;
	//popmessage("%04x %04x",m_sound_index_l,m_sound_index_r);
}

WRITE16_MEMBER(littlerb_state::littlerb_r_sound_w)
{
	m_sound_index_r = (data >> sound_data_shift(machine())) & 0xff;
	m_sound_pointer_r = 0;
	//popmessage("%04x %04x",m_sound_index_l,m_sound_index_r);
}

static ADDRESS_MAP_START( littlerb_main, AS_PROGRAM, 16, littlerb_state )
	AM_RANGE(0x000008, 0x000017) AM_WRITENOP
	AM_RANGE(0x000020, 0x00002f) AM_WRITENOP
	AM_RANGE(0x000070, 0x000073) AM_WRITENOP
	AM_RANGE(0x060004, 0x060007) AM_WRITENOP
	AM_RANGE(0x000000, 0x0fffff) AM_ROM
	AM_RANGE(0x200000, 0x203fff) AM_RAM // main ram?
	AM_RANGE(0x700000, 0x700007) AM_READ(littlerb_vdp_r) AM_WRITE(littlerb_vdp_w)
	AM_RANGE(0x740000, 0x740001) AM_WRITE(littlerb_l_sound_w)
	AM_RANGE(0x760000, 0x760001) AM_WRITE(littlerb_r_sound_w)
	AM_RANGE(0x780000, 0x780001) AM_WRITENOP // generic outputs
	AM_RANGE(0x7c0000, 0x7c0001) AM_READ_PORT("DSW")
	AM_RANGE(0x7e0000, 0x7e0001) AM_READ_PORT("P1")
	AM_RANGE(0x7e0002, 0x7e0003) AM_READ_PORT("P2")
ADDRESS_MAP_END

/* guess according to DASM code and checking the gameplay speed, could be different */
CUSTOM_INPUT_MEMBER(littlerb_state::littlerb_frame_step_r)
{
	UINT32 ret = machine().primary_screen->frame_number();

	return (ret) & 7;
}

static INPUT_PORTS_START( littlerb )
	PORT_START("DSW")   /* 16bit */
	PORT_DIPNAME( 0x0003, 0x0001, DEF_STR( Lives ) )
	PORT_DIPSETTING(      0x0003, "2" )
	PORT_DIPSETTING(      0x0001, "3" )
	PORT_DIPSETTING(      0x0002, "4" )
	PORT_DIPSETTING(      0x0000, "5" )
	PORT_DIPNAME( 0x001c, 0x0004, DEF_STR( Coin_B ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( 5C_1C ) )
	PORT_DIPSETTING(      0x0010, DEF_STR( 4C_1C ) )
	PORT_DIPSETTING(      0x0008, DEF_STR( 3C_1C ) )
	PORT_DIPSETTING(      0x0018, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(      0x0004, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(      0x0014, DEF_STR( 1C_2C ) )
	PORT_DIPSETTING(      0x000c, DEF_STR( 1C_3C ) )
	PORT_DIPSETTING(      0x001c, DEF_STR( 1C_4C ) )
	PORT_DIPNAME( 0x00e0, 0x0020, DEF_STR( Coin_A ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( 5C_1C ) )
	PORT_DIPSETTING(      0x0080, DEF_STR( 4C_1C ) )
	PORT_DIPSETTING(      0x0040, DEF_STR( 3C_1C ) )
	PORT_DIPSETTING(      0x00c0, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(      0x0020, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(      0x00a0, DEF_STR( 1C_2C ) )
	PORT_DIPSETTING(      0x0060, DEF_STR( 1C_3C ) )
	PORT_DIPSETTING(      0x00e0, DEF_STR( 1C_4C ) )
	PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0100, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0200, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0400, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0800, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x1000, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x2000, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_SERVICE( 0x4000, IP_ACTIVE_LOW )
	PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x8000, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )

	PORT_START("P1")    /* 16bit */
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_DIPNAME( 0x1000, 0x1000, "???"  )
	PORT_DIPSETTING(      0x1000, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_BIT( 0xe000, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, littlerb_state,littlerb_frame_step_r, NULL)

	PORT_START("P2")    /* 16bit */
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END



/* sprite format / offset could be completely wrong, this is just based on our (currently incorrect) vram access */
UINT32 littlerb_state::screen_update_littlerb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	bitmap.fill(0, cliprect);

	copybitmap_trans(bitmap, *m_temp_bitmap_sprites_back, 0, 0, 0, 0, cliprect, 0);
	copybitmap_trans(bitmap, *m_temp_bitmap_sprites, 0, 0, 0, 0, cliprect, 0);

	return 0;
}

TIMER_DEVICE_CALLBACK_MEMBER(littlerb_state::littlerb_scanline)
{
	int scanline = param;

	if((scanline % 2) == 0)
	{
		UINT8 res;
		UINT8 *sample_rom = memregion("samples")->base();

		res = sample_rom[m_sound_pointer_l|(m_sound_index_l<<10)|0x40000];
		m_dacl->write_signed8(res);
		res = sample_rom[m_sound_pointer_r|(m_sound_index_r<<10)|0x00000];
		m_dacr->write_signed8(res);
		m_sound_pointer_l++;
		m_sound_pointer_l&=0x3ff;
		m_sound_pointer_r++;
		m_sound_pointer_r&=0x3ff;
	}

//  logerror("IRQ\n");
	if(scanline == 288)
	{
		m_maincpu->set_input_line(4, HOLD_LINE);
	}
}

void littlerb_state::video_start()
{
//  machine().primary_screen->register_screen_bitmap(m_temp_bitmap_sprites_back);
//  machine().primary_screen->register_screen_bitmap(m_temp_bitmap_sprites);

	m_temp_bitmap_sprites_back = auto_bitmap_ind16_alloc(machine(),512,512);
	m_temp_bitmap_sprites = auto_bitmap_ind16_alloc(machine(),512,512);


	m_spritelist = (UINT16*)auto_alloc_array_clear(machine(), UINT16, 0x20000);

}




static void draw_sprite(running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect, int xsize,int ysize, UINT32 fulloffs, int xpos, int ypos )
{
	int x,y;
	fulloffs >>= 3;
	address_space &vdp_space = machine.device<littlerb_vdp_device>("littlerbvdp")->space();

	for (y=0;y<ysize;y++)
	{
		for (x=0;x<xsize;x++)
		{
			int drawxpos, drawypos;
			// the addresses provided are the same as the offsets as the vdp writes
			UINT16 pix = vdp_space.read_byte(fulloffs);

			drawxpos = xpos+x;
			drawypos = ypos+y;

			// odd clipping behavior, count is only increased for visible lines?
			// I suspect the sprite corruption if you're near the top of the screen
			// between level changes is related to this too, data offset values are
			// probably being adjusted as layer is scrolled (and the cliprect is changed)
			// even if they don't move.
			if(drawypos>=cliprect.min_y)
			{
				fulloffs++;
			}

			if(cliprect.contains(drawxpos, drawypos))
			{
				if(pix&0xff) bitmap.pix16(drawypos, drawxpos) = pix;
			}

			drawxpos++;
		}
	}
}

static void littlerb_draw_sprites(running_machine &machine)
{
	littlerb_state *state = machine.driver_data<littlerb_state>();
	int x,y,offs;
	int xsize,ysize;
	UINT16* spriteregion = state->m_spritelist;
	//littlerb_printf("frame\n");

	int layer = 0;
	int yoffset = 0;

	littlerb_printf("m_listoffset %04x\n", state->m_listoffset );

	littlerb_printf("%04x %04x %04x %04x\n", spriteregion[0], spriteregion[1], spriteregion[2], spriteregion[3]);

	littlerb_alt_printf("start\n");

	int minx = 0 , maxx = 0x14f;
	int miny = 0 , maxy = 0x11f;

	for (offs=0;offs<(state->m_listoffset);)
	{
		UINT32 read_dword = ((spriteregion[offs+1])<<16)+ (spriteregion[offs+0]);

		littlerb_printf("read %08x\n", read_dword);

		// some kind of control words?? (layer selection, layer scrolls?, layer clears?)
		// but the low bits are the sprite offset??? how can this work
		if (spriteregion[offs+0] == 0x0060)
		{
			offs += 6;

		}
		else if (spriteregion[offs+0] == 0x0040)
		{
			littlerb_alt_printf("Control Word %04x %04x %04x %04x %04x %04x ---- ---- ---- ----\n", spriteregion[offs+0], spriteregion[offs+1], spriteregion[offs+2], spriteregion[offs+3], spriteregion[offs+4], spriteregion[offs+5]);

			// some scroll stuff is here (title -> high score transition)
			// maybe also copy area operations?


			// this isn't understood ... note, we still have a hack before draw_sprites is called too

			// usual start of frame
			// Control Word 0040 0090 6000 0026 0000 0012 ---- ---- ---- ----

			// happens in the middle of list during boss death, causes sprites to vanish atm
			// Control Word 0040 ffd6 00aa 00f8 0088 0018 ---- ---- ---- ----
			if (spriteregion[offs+4]==0x6000)
			{
				if (spriteregion[offs+3] & 0x1000)
					state->m_temp_bitmap_sprites_back->fill(0, state->m_temp_bitmap_sprites_back->cliprect());
			}
			else
			{
				if (spriteregion[offs+1] != 0xffd6) state->m_temp_bitmap_sprites->fill(0, state->m_temp_bitmap_sprites->cliprect());
			}



			// this is some kind of scroll or copy area..
			// also some of the other values change
			// this is set AFTER the graphics which need to be scrolled are sent and causes the credit text to bounce up and down instead of
			// anything scrolling
			//yoffset = spriteregion[offs+1] - 0x90;


			offs += 6;
		}
		else if (read_dword == 0x00e40020)
		{
			littlerb_alt_printf("Control Word %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", spriteregion[offs+0], spriteregion[offs+1], spriteregion[offs+2], spriteregion[offs+3], spriteregion[offs+4], spriteregion[offs+5], spriteregion[offs+6], spriteregion[offs+7], spriteregion[offs+8], spriteregion[offs+9]);

			if (spriteregion[offs+4]==0x6000)
				layer = 1;
			else
				layer = 0;


			minx = spriteregion[offs+6];
			maxx = spriteregion[offs+8];

			miny = spriteregion[offs+7];
			maxy = spriteregion[offs+9];


			offs += 10;
		}
		else if (read_dword == 0x00e40000)
		{
			// same as above?
			littlerb_alt_printf("Control Word %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", spriteregion[offs+0], spriteregion[offs+1], spriteregion[offs+2], spriteregion[offs+3], spriteregion[offs+4], spriteregion[offs+5], spriteregion[offs+6], spriteregion[offs+7], spriteregion[offs+8], spriteregion[offs+9]);

			if (spriteregion[offs+4]==0x6000)
				layer = 1;
			else
				layer = 0;

			minx = spriteregion[offs+6];
			maxx = spriteregion[offs+8];

			miny = spriteregion[offs+7];
			maxy = spriteregion[offs+9];


			offs += 10;
		}
		else if (read_dword == 0x00000000)
		{
			offs += 1;
		}
		else
		{
			UINT32 fullcode = ((spriteregion[offs+1])<<16)+ (spriteregion[offs+0]);

			x = spriteregion[offs+2] & 0x07ff;
			y = (spriteregion[offs+3] & 0x03ff); // 1?

			if (x&0x400) x-=0x800;
			if (y&0x200) y-=0x400;

			y+= yoffset;

			xsize = (spriteregion[offs+4] & 0x01ff); // background gfx for many places at 0x1ff wide
			ysize = (spriteregion[offs+5] & 0x00ff); // player1/player2 texts in service mode sides are 0xff high


			rectangle clip;

			clip.min_x = minx;
			clip.max_x = maxx;

			clip.min_y = miny;
			clip.max_y = maxy;

			// used between levels, and on boss death to clip sprite at the ground for sinking effect


			if (clip.min_x > state->m_temp_bitmap_sprites->cliprect().max_x)
				clip.min_x =  state->m_temp_bitmap_sprites->cliprect().max_x;

			if (clip.min_x < state->m_temp_bitmap_sprites->cliprect().min_x)
				clip.min_x =  state->m_temp_bitmap_sprites->cliprect().min_x;

			if (clip.max_x > state->m_temp_bitmap_sprites->cliprect().max_x)
				clip.max_x =  state->m_temp_bitmap_sprites->cliprect().max_x;

			if (clip.max_x < state->m_temp_bitmap_sprites->cliprect().min_x)
				clip.max_x =  state->m_temp_bitmap_sprites->cliprect().min_x;


			if (clip.min_y > state->m_temp_bitmap_sprites->cliprect().max_y)
				clip.min_y =  state->m_temp_bitmap_sprites->cliprect().max_y;

			if (clip.min_y < state->m_temp_bitmap_sprites->cliprect().min_y)
				clip.min_y =  state->m_temp_bitmap_sprites->cliprect().min_y;

			if (clip.max_y > state->m_temp_bitmap_sprites->cliprect().max_y)
				clip.max_y =  state->m_temp_bitmap_sprites->cliprect().max_y;

			if (clip.max_y < state->m_temp_bitmap_sprites->cliprect().min_y)
				clip.max_y =  state->m_temp_bitmap_sprites->cliprect().min_y;


			littlerb_alt_printf("%04x %04x %04x %04x %04x %04x\n", spriteregion[offs+0], spriteregion[offs+1], spriteregion[offs+2], spriteregion[offs+3], spriteregion[offs+4], spriteregion[offs+5]);

			if (layer==0) draw_sprite(machine, *state->m_temp_bitmap_sprites, clip,xsize,ysize,fullcode,x,y);
			else draw_sprite(machine, *state->m_temp_bitmap_sprites_back, clip,xsize,ysize,fullcode,x,y);


			offs += 6;
		}
	}
}



static MACHINE_CONFIG_START( littlerb, littlerb_state )
	MCFG_CPU_ADD("maincpu", M68000, 12000000)
	MCFG_CPU_PROGRAM_MAP(littlerb_main)
	MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", littlerb_state, littlerb_scanline, "screen", 0, 1)

	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(50) // guess based on high vertical resolution
	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500))
	MCFG_SCREEN_SIZE(512+22, 312)
	MCFG_SCREEN_VISIBLE_AREA(0*8, 336-1, 0*8, 288-1)
	MCFG_SCREEN_UPDATE_DRIVER(littlerb_state, screen_update_littlerb)


	MCFG_PALETTE_LENGTH(0x100)

	MCFG_DEVICE_ADD("littlerbvdp", LITTLERBVDP, 0)
	MCFG_RAMDAC_ADD("ramdac", ramdac_intf, ramdac_map)

//  MCFG_PALETTE_INIT_OVERRIDE(littlerb_state,littlerb)
	MCFG_SPEAKER_STANDARD_STEREO("lspeaker","rspeaker")

	MCFG_DAC_ADD("dacl")
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)

	MCFG_DAC_ADD("dacr")
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
MACHINE_CONFIG_END

ROM_START( littlerb )
	ROM_REGION( 0x100000, "maincpu", 0 ) /* 68000 Code */
	ROM_LOAD16_BYTE( "roma.u53", 0x00001, 0x80000, CRC(172fbc13) SHA1(cd165ca0d0546e2634cf182dc98004cbfb02cf9f) )
	ROM_LOAD16_BYTE( "romb.u29", 0x00000, 0x80000, CRC(b2fb1d61) SHA1(9a9d7176c241928d07af651e5f7f21d4f019701d) )

	ROM_REGION( 0x80000, "samples", 0 ) /* sound samples */
	ROM_LOAD( "romc.u26", 0x40000, 0x40000, CRC(f193c5b6) SHA1(95548a40e2b5064c558b36cabbf507d23678b1b2) )
	ROM_LOAD( "romd.u32", 0x00000, 0x40000, CRC(d6b81583) SHA1(b7a63d18a41ccac4d3db9211de0b0cdbc914317a) )
ROM_END


GAME( 1994, littlerb, 0, littlerb, littlerb, driver_device, 0, ROT0, "TCH", "Little Robin", GAME_IMPERFECT_GRAPHICS|GAME_IMPERFECT_SOUND )