1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /******************************************************************************
4 
5     V-Tech V.Smile Baby console emulation
6 
7 *******************************************************************************/
8 
9 #include "emu.h"
10 
11 #include "includes/vsmile.h"
12 
13 #include "softlist.h"
14 #include "speaker.h"
15 
16 
17 /************************************
18  *
19  *  V.Smile Baby
20  *
21  ************************************/
22 
machine_start()23 void vsmileb_state::machine_start()
24 {
25 	vsmile_base_state::machine_start();
26 
27 	save_item(NAME(m_mode));
28 }
29 
machine_reset()30 void vsmileb_state::machine_reset()
31 {
32 	m_mode = 0x0400;
33 }
34 
porta_r()35 uint16_t vsmileb_state::porta_r()
36 {
37 	return 0x0302 | (m_io_logo->read() ? 0x0080 : 0x0000);
38 }
39 
portb_r()40 uint16_t vsmileb_state::portb_r()
41 {
42 	return 0x0080;
43 }
44 
INPUT_CHANGED_MEMBER(vsmileb_state::pad_button_changed)45 INPUT_CHANGED_MEMBER(vsmileb_state::pad_button_changed)
46 {
47 	uint16_t value = m_mode;
48 	if (newval == 0)
49 	{
50 		value |= 0x0080;
51 	}
52 	else
53 	{
54 		value |= (uint16_t)param;
55 	}
56 	m_maincpu->uart_rx((uint8_t)(value >> 8));
57 	m_maincpu->uart_rx((uint8_t)value);
58 }
59 
INPUT_CHANGED_MEMBER(vsmileb_state::sw_mode)60 template <uint16_t V> INPUT_CHANGED_MEMBER(vsmileb_state::sw_mode)
61 {
62 	if (!newval && oldval)
63 	{
64 		m_mode = V;
65 		const uint16_t value = m_mode | 0x0080;
66 		m_maincpu->uart_rx((uint8_t)(value >> 8));
67 		m_maincpu->uart_rx((uint8_t)value);
68 	}
69 }
70 
banked_map(address_map & map)71 void vsmileb_state::banked_map(address_map &map)
72 {
73 	map(0x0000000, 0x03fffff).rom().region("sysrom", 0);
74 	map(0x0400000, 0x07fffff).rom().region("sysrom", 0);
75 	map(0x0800000, 0x0bfffff).rom().region("sysrom", 0);
76 
77 	map(0x1000000, 0x13fffff).rw(m_cart, FUNC(vsmile_cart_slot_device::bank0_r), FUNC(vsmile_cart_slot_device::bank0_w));
78 
79 	map(0x1400000, 0x15fffff).rw(m_cart, FUNC(vsmile_cart_slot_device::bank0_r), FUNC(vsmile_cart_slot_device::bank0_w));
80 	map(0x1600000, 0x17fffff).rw(m_cart, FUNC(vsmile_cart_slot_device::bank2_r), FUNC(vsmile_cart_slot_device::bank2_w));
81 
82 	map(0x1800000, 0x18fffff).rw(m_cart, FUNC(vsmile_cart_slot_device::bank0_r), FUNC(vsmile_cart_slot_device::bank0_w));
83 	map(0x1900000, 0x19fffff).rw(m_cart, FUNC(vsmile_cart_slot_device::bank1_r), FUNC(vsmile_cart_slot_device::bank1_w));
84 	map(0x1a00000, 0x1afffff).rw(m_cart, FUNC(vsmile_cart_slot_device::bank2_r), FUNC(vsmile_cart_slot_device::bank2_w));
85 	map(0x1b00000, 0x1bfffff).r(FUNC(vsmileb_state::bank3_r));
86 }
87 
88 /************************************
89  *
90  *  Inputs
91  *
92  ************************************/
93 
94 static INPUT_PORTS_START( vsmileb )
95 	PORT_START("BUTTONS")
PORT_CHANGED_MEMBER(DEVICE_SELF,vsmileb_state,pad_button_changed,vsmileb_state::BUTTON_YELLOW)96 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_YELLOW) PORT_NAME("Yellow")
97 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_BLUE)   PORT_NAME("Blue")
98 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_ORANGE) PORT_NAME("Orange")
99 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_GREEN)  PORT_NAME("Green")
100 	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_RED)    PORT_NAME("Red")
101 	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_CLOUD)  PORT_NAME("Cloud")
102 	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_BALL)   PORT_NAME("Ball")
103 	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, pad_button_changed, vsmileb_state::BUTTON_EXIT)   PORT_NAME("Exit")
104 
105 	PORT_START("MODE")
106 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Play Time")       PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, sw_mode<0x0400>, 0) // three-position function switch
107 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Watch & Learn")   PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, sw_mode<0x0800>, 0)
108 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Learn & Explore") PORT_CHANGED_MEMBER(DEVICE_SELF, vsmileb_state, sw_mode<0x0c00>, 0)
109 
110 	PORT_START("LOGO")
111 	PORT_DIPNAME( 0x10, 0x10, "VTech Intro" )
112 	PORT_DIPSETTING(    0x00, DEF_STR(Off) )
113 	PORT_DIPSETTING(    0x10, DEF_STR(On) )
114 	PORT_BIT( 0xef, 0x00, IPT_UNUSED )
115 INPUT_PORTS_END
116 
117 /************************************
118  *
119  *  Machine Configs
120  *
121  ************************************/
122 
123 void vsmileb_state::vsmileb(machine_config &config)
124 {
125 	SPG28X(config, m_maincpu, XTAL(27'000'000), m_screen);
126 	m_maincpu->set_addrmap(AS_PROGRAM, &vsmileb_state::mem_map);
127 	m_maincpu->set_force_no_drc(true);
128 	m_maincpu->chip_select().set(FUNC(vsmileb_state::chip_sel_w));
129 	m_maincpu->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
130 	m_maincpu->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
131 	m_maincpu->porta_in().set(FUNC(vsmileb_state::porta_r));
132 	m_maincpu->portb_in().set(FUNC(vsmileb_state::portb_r));
133 
134 	vsmile_base(config);
135 
136 	m_bankdev->set_addrmap(AS_PROGRAM, &vsmileb_state::banked_map);
137 
138 	SOFTWARE_LIST(config, "cart_list").set_original("vsmileb_cart");
139 }
140 
vsmilebp(machine_config & config)141 void vsmileb_state::vsmilebp(machine_config &config)
142 {
143 	vsmileb(config);
144 	m_maincpu->set_pal(true);
145 }
146 
147 /************************************
148  *
149  *  ROM Loading
150  *
151  ************************************/
152 
153 ROM_START( vsmileb )
154 	ROM_REGION16_BE( 0x800000, "sysrom", ROMREGION_ERASEFF )
155 	ROM_LOAD16_WORD_SWAP( "vsmilebabybios.bin",                0x000000, 0x800000, CRC(58d4caa0) SHA1(0b636ff80fd7fc429d753a8beab2957f1e59cbde) )
156 ROM_END
157 
158 ROM_START( vsmilebs )
159 	ROM_REGION16_BE( 0x800000, "sysrom", ROMREGION_ERASEFF )
160 	ROM_LOAD16_WORD_SWAP( "vsmilebabybios_spain_pooh.bin",     0x000000, 0x800000, CRC(a1926654) SHA1(a8ccbe29235bb44faef77b1e7d73a20221b005c2) )
161 ROM_END
162 
163 ROM_START( vsmilebsw )
164 	ROM_REGION16_BE( 0x800000, "sysrom", ROMREGION_ERASEFF )
165 	ROM_LOAD16_WORD_SWAP( "vsmilebabybios_sweden.bin",         0x000000, 0x800000, CRC(8b464b19) SHA1(cea304ba886c39e86906aad3dce17d5fff7cfcbe) )
166 ROM_END
167 
168 ROM_START( vsmilebg )
169 	ROM_REGION16_BE( 0x800000, "sysrom", ROMREGION_ERASEFF )
170 	ROM_LOAD16_WORD_SWAP( "vsmilebabybios_germany_pooh.bin",   0x000000, 0x800000, CRC(22261569) SHA1(8918a905af4bb186beb5577b1d295d9c037584f7) )
171 ROM_END
172 
173 ROM_START( vsmilebf )
174 	ROM_REGION16_BE( 0x800000, "sysrom", ROMREGION_ERASEFF )
175 	ROM_LOAD16_WORD_SWAP( "vsmilebabybios_france_pooh.bin",    0x000000, 0x800000, CRC(3dfa2acb) SHA1(9b3a34dae5475f0c82187cb0c62183b46344b7ad) )
176 ROM_END
177 
178 ROM_START( vsmilebfp )
179 	ROM_REGION16_BE( 0x800000, "sysrom", ROMREGION_ERASEFF )
180 	ROM_LOAD16_WORD_SWAP( "vsmilebabybios_france_patoune.bin", 0x000000, 0x800000, CRC(57757602) SHA1(a7495e1c6b2edaeb63bf1c658575689304f15804) )
181 ROM_END
182 
183 //    year, name,      parent,  compat, machine, input,   class,         init,       company, fullname,                                                                         flags
184 CONS( 2005, vsmileb,   0,       0,      vsmileb, vsmileb, vsmileb_state, empty_init, "VTech", "V.Smile Baby (USA)",                                                             MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
185 CONS( 2005, vsmilebsw ,vsmileb, 0,      vsmilebp,vsmileb, vsmileb_state, empty_init, "VTech", "V.Smile Baby (Sweden)",                                                          MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
186 
187 // These have a game in the BIOS ROM, supplied as a 'Romless cart' with the device, so probably triggers a switch. Currently always banked in.
188 CONS( 2005, vsmilebs,  vsmileb, 0,      vsmileb, vsmileb, vsmileb_state, empty_init, "VTech", "V.Smile Baby (Spain, with 'Aventuras en el Bosque de los Cien Acres')",          MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
189 CONS( 2005, vsmilebg,  vsmileb, 0,      vsmileb, vsmileb, vsmileb_state, empty_init, "VTech", "V.Smile Baby (Germany, with 'Puuhs Hundert-Morgen-Wald')",                       MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
190 CONS( 2005, vsmilebf,  vsmileb, 0,      vsmileb, vsmileb, vsmileb_state, empty_init, "VTech", "V.Smile Baby (France, with 'Winnie et ses amis dans la Foret des Reves Bleus')", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
191 CONS( 2005, vsmilebfp, vsmileb, 0,      vsmileb, vsmileb, vsmileb_state, empty_init, "VTech", "V.Smile Baby (France, with 'En Ville avec l'ourson Patoune')",                   MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
192