1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 // thanks-to:Kevin Horton
4 /******************************************************************************
5 
6 Parker Brothers Starting Lineup Talking Baseball
7 
8 Hardware notes:
9 - PCB label KPT-349 REV 6C<1>
10 - 80C31 MCU @ 12MHz
11 - 2KB RAM, 128KB ROM, 2 cartridge slots
12 - 12 leds, 2 16-button keypads
13 
14 ROM chip has (C) 1987 Tonka (Kenner Parker Toys was acquired by Tonka in 1987, Parker
15 Brothers itself was acquired by Kenner in 1985)
16 
17 The speech driver is by Forrest S. Mozer's company.
18 
19 The cartridge slots are for extra teams. There are around 8 cartridges, each one
20 included 3 or 4 baseball teams, with exception to the "Hall of Fame" cartridge.
21 Players enter a 3-digit code to select the team.
22 
23 TODO:
24 - add cartridge slots
25 - Buttons are unresponsive at initial game setup, you need to hold the yes/no button
26   until it responds. The keypad reading routine is at $1A5D, it gets skipped for several
27   seconds at a time. Once in-game, everything is fine though. BTANB or different cause?
28 
29 *******************************************************************************
30 
31 Field positions (used when substituting):
32 
33 1: Pitcher
34 2: Catcher
35 3: First Base
36 4: Second Base
37 5: Third Base
38 6: Shortstop
39 7: Left Field
40 8: Center Field
41 9: Right Field
42 
43 The game includes baseball cards with player stats. At the very least, the roster
44 cards are needed to play the game properly. See below for the default teams.
45 
46 American Team:
47 --------------
48 
49 Starting lineup batting order:
50 
51 1: #23  Rickey Henderson, CF
52 2: #14  Don Mattingly, 1B
53 3: #18  Wade Boggs, 3B
54 4: #22  George Bell, LF
55 5: #24  Dave Winfield, RF
56 6: #16  Cal Ripken, SS
57 7: #11  Terry Kennedy, C
58 8: #15  Willie Randolph, 2B
59 9: #20  Alan Trammell, SS & DH
60 10:#27  Roger Clemens, P
61 
62 Substitutes:
63 
64 #19: George Brett, 3B
65 #12: Carlton Fisk, C
66 #25: Jack Morris, P
67 #13: Eddie Murray, 1B
68 #21: Kirby Puckett, OF
69 #30: Dan Quisenberry, P
70 #29: Dave Righetti, P
71 #28: Bret Saberhagen, P
72 #17: Lou Whitaker, 2B
73 #26: Robin Yount, SS
74 
75 National Team:
76 --------------
77 
78 Starting lineup batting order:
79 
80 1: #23: Tim Raines, LF
81 2: #16: Ryne Sandberg, 2B
82 3: #22: Darryl Strawberry, RF
83 4: #19: Mike Schmidt, 3B
84 5: #13: Jack Clark, 1B
85 6: #20: Eric Davis, CF
86 7: #11: Gary Carter, C
87 8: #17: Ozzie Smith, SS
88 9: #18: Dale Murphy, OF & DH
89 10:#25: Mike Scott, P
90 
91 Substitutes:
92 
93 #15: Buddy Bell, 3B
94 #26: Jody Davis, C
95 #24: Andre Dawson, CF
96 #29: Dwight Gooden, P
97 #21: Tony Gwynn, OF
98 #14: Keith Hernandez, 1B
99 #30: Nolan Ryan, P
100 #12: Steve Sax, 2B
101 #28: Fernando Valenzuela, P
102 #27: Todd Worrell, P
103 
104 ******************************************************************************/
105 
106 #include "emu.h"
107 #include "cpu/mcs51/mcs51.h"
108 #include "video/pwm.h"
109 #include "sound/dac.h"
110 #include "speaker.h"
111 
112 // internal artwork
113 #include "talkingbb.lh"
114 
115 
116 namespace {
117 
118 class talkingbb_state : public driver_device
119 {
120 public:
talkingbb_state(const machine_config & mconfig,device_type type,const char * tag)121 	talkingbb_state(const machine_config &mconfig, device_type type, const char *tag) :
122 		driver_device(mconfig, type, tag),
123 		m_maincpu(*this, "maincpu"),
124 		m_rom(*this, "maincpu"),
125 		m_display(*this, "display"),
126 		m_inputs(*this, "IN.%u", 0)
127 	{ }
128 
129 	void talkingbb(machine_config &config);
130 
131 protected:
132 	virtual void machine_start() override;
133 
134 private:
135 	// devices/pointers
136 	required_device<mcs51_cpu_device> m_maincpu;
137 	required_region_ptr<u8> m_rom;
138 	required_device<pwm_display_device> m_display;
139 	required_ioport_array<5> m_inputs;
140 
141 	void main_map(address_map &map);
142 	void main_io(address_map &map);
143 
144 	u8 m_bank;
145 	u8 m_inp_mux;
146 
147 	// I/O handlers
148 	void bank_w(u8 data);
149 	u8 bank_r(offs_t offset);
150 	void input_w(u8 data);
151 	u8 input_r();
152 	u8 switch_r();
153 };
154 
machine_start()155 void talkingbb_state::machine_start()
156 {
157 	// zerofill
158 	m_bank = 0;
159 	m_inp_mux = 0;
160 
161 	// register for savestates
162 	save_item(NAME(m_bank));
163 	save_item(NAME(m_inp_mux));
164 }
165 
166 
167 
168 /******************************************************************************
169     I/O
170 ******************************************************************************/
171 
bank_w(u8 data)172 void talkingbb_state::bank_w(u8 data)
173 {
174 	// d0-d1: upper rom bank
175 	// d2-d4: upper rom enable (bus conflict possible)
176 	// d2: internal rom, d3: cart slot 1, d4: cart slot 2
177 	m_bank = data;
178 }
179 
bank_r(offs_t offset)180 u8 talkingbb_state::bank_r(offs_t offset)
181 {
182 	u32 hi = (~m_bank & 3) << 15;
183 	u8 data = (m_bank & 4) ? 0xff : m_rom[offset | hi];
184 
185 	// TODO: cartridge
186 
187 	return data;
188 }
189 
input_w(u8 data)190 void talkingbb_state::input_w(u8 data)
191 {
192 	// no effect if P30 is low (never happens though)
193 	if (~m_bank & 1)
194 		return;
195 
196 	// d4-d7: led select (also input mux)
197 	// d0-d2: led data
198 	m_inp_mux = data >> 4;
199 	m_display->matrix(m_inp_mux, ~data & 7);
200 }
201 
input_r()202 u8 talkingbb_state::input_r()
203 {
204 	// open bus if P30 is low (never happens though)
205 	if (~m_bank & 1)
206 		return 0xff;
207 
208 	u8 data = 0;
209 
210 	// multiplexed inputs
211 	for (int i = 0; i < 4; i++)
212 		if (BIT(m_inp_mux, i))
213 			data |= m_inputs[i]->read();
214 
215 	return ~data;
216 }
217 
switch_r()218 u8 talkingbb_state::switch_r()
219 {
220 	// d5: mode switch
221 	return ~m_inputs[4]->read();
222 }
223 
224 
225 
226 /******************************************************************************
227     Address Maps
228 ******************************************************************************/
229 
main_map(address_map & map)230 void talkingbb_state::main_map(address_map &map)
231 {
232 	map(0x0000, 0x7fff).rom().region("maincpu", 0x18000);
233 	map(0x8000, 0xffff).r(FUNC(talkingbb_state::bank_r));
234 }
235 
main_io(address_map & map)236 void talkingbb_state::main_io(address_map &map)
237 {
238 	map(0x0000, 0x07ff).mirror(0x7800).ram();
239 	map(0x8000, 0x8000).mirror(0x7fff).rw(FUNC(talkingbb_state::input_r), FUNC(talkingbb_state::input_w));
240 }
241 
242 
243 
244 /******************************************************************************
245     Input Ports
246 ******************************************************************************/
247 
248 /* keypad layout:        **** P1 = Batter ****  |  **** P2 = Pitcher ****
249                                                 |
250 [PINCH   [1       [2]       [3       [TIME OUT] |   [INFIELD  [1        [2        [3        [TIME OUT]
251  HITTER]  BUNT]              POWER]             |    IN]       FAST]     CURVE]    CHANGE]
252                                                 |
253 [SCORE]  [4]      [5        [6]      [NO        |   [SCORE]   [4        [5        [6        [NO
254                    SQUEEZE]           CANCEL]   |              PTCHOUT]  PICKOFF]  INTWALK]  CANCEL]
255                                                 |
256 [PINCH   [7       [8]       [9       [YES       |   [INSTANT  [7        [8]       [9        [YES
257  RUNNER]  STEAL]             X-BASE]  ENTER]    |    REPLAY]   RELIEF]             SUB]      ENTER]
258                                                 |
259                   [0                            |                       [0
260                    SWING]                       |                        BALL]
261 */
262 
263 static INPUT_PORTS_START( talkingbb )
264 	PORT_START("IN.0")
PORT_CODE(KEYCODE_3)265 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_R) PORT_NAME("P1 3 / Power")
266 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_F) PORT_NAME("P1 6")
267 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_V) PORT_NAME("P1 9 / Extra Base")
268 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_MINUS) PORT_NAME("P1 Time Out")
269 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_O) PORT_NAME("P2 3 / Change")
270 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_L) PORT_NAME("P2 6 / Intentional Walk")
271 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9_PAD) PORT_CODE(KEYCODE_STOP) PORT_NAME("P2 9 / Sub")
272 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("P2 Time Out")
273 
274 	PORT_START("IN.1")
275 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_E) PORT_NAME("P1 2")
276 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_D) PORT_NAME("P1 5 / Squeeze")
277 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_C) PORT_NAME("P1 8")
278 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_LALT) PORT_NAME("P1 0 / Swing")
279 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_I) PORT_NAME("P2 2 / Curve")
280 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5_PAD) PORT_CODE(KEYCODE_K) PORT_NAME("P2 5 / Pickoff")
281 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_COMMA) PORT_NAME("P2 8")
282 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(KEYCODE_RALT) PORT_NAME("P2 0 / Ball")
283 
284 	PORT_START("IN.2")
285 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_W) PORT_NAME("P1 1 / Bunt")
286 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_S) PORT_NAME("P1 4")
287 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_X) PORT_NAME("P1 7 / Steal")
288 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("P1 No / Cancel")
289 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1_PAD) PORT_CODE(KEYCODE_U) PORT_NAME("P2 1 / Fast")
290 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_J) PORT_NAME("P2 4 / Pitchout")
291 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_M) PORT_NAME("P2 7 / Relief")
292 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL_PAD) PORT_NAME("P2 No / Cancel")
293 
294 	PORT_START("IN.3")
295 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q) PORT_NAME("P1 Pinch Hitter")
296 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A) PORT_NAME("P1 Score")
297 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Z) PORT_NAME("P1 Pinch Runner")
298 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("P1 Yes / Enter")
299 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y) PORT_NAME("P2 Infield In")
300 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H) PORT_NAME("P2 Score")
301 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_NAME("P2 Instant Replay")
302 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("P2 Yes / Enter")
303 
304 	PORT_START("IN.4")
305 	PORT_CONFNAME( 0x20, 0x00, "Mode" )
306 	PORT_CONFSETTING(    0x00, "Player" )
307 	PORT_CONFSETTING(    0x20, "Coach" )
308 INPUT_PORTS_END
309 
310 
311 
312 /******************************************************************************
313     Machine Configs
314 ******************************************************************************/
315 
316 void talkingbb_state::talkingbb(machine_config &config)
317 {
318 	/* basic machine hardware */
319 	I80C31(config, m_maincpu, 12_MHz_XTAL);
320 	m_maincpu->set_addrmap(AS_PROGRAM, &talkingbb_state::main_map);
321 	m_maincpu->set_addrmap(AS_IO, &talkingbb_state::main_io);
322 	m_maincpu->port_out_cb<1>().set("dac", FUNC(dac_8bit_r2r_device::write));
323 	m_maincpu->port_out_cb<3>().set(FUNC(talkingbb_state::bank_w));
324 	m_maincpu->port_in_cb<3>().set(FUNC(talkingbb_state::switch_r));
325 
326 	/* video hardware */
327 	PWM_DISPLAY(config, m_display).set_size(4, 3);
328 	config.set_default_layout(layout_talkingbb);
329 
330 	/* sound hardware */
331 	SPEAKER(config, "speaker").front_center();
332 	DAC_8BIT_R2R(config, "dac").add_route(ALL_OUTPUTS, "speaker", 0.5);
333 }
334 
335 
336 
337 /******************************************************************************
338     ROM Definitions
339 ******************************************************************************/
340 
341 ROM_START( talkingbb )
342 	ROM_REGION( 0x20000, "maincpu", 0 )
343 	ROM_LOAD("sp17208-002", 0x0000, 0x20000, CRC(e0e56217) SHA1(24a06b5c94a5c750799f61e3eb865e02d6cea68a) ) // GM231000-110
344 ROM_END
345 
346 } // anonymous namespace
347 
348 
349 
350 /******************************************************************************
351     Drivers
352 ******************************************************************************/
353 
354 //    YEAR  NAME        PARENT CMP MACHINE    INPUT      CLASS            INIT        COMPANY, FULLNAME, FLAGS
355 CONS( 1988, talkingbb,  0,      0, talkingbb, talkingbb, talkingbb_state, empty_init, "Parker Brothers", "Starting Lineup Talking Baseball", MACHINE_SUPPORTS_SAVE )
356