1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol, Robbbert
3 /***************************************************************************
4
5 Driver file to handle emulation of the Tiger Game.com by Wilbert Pol.
6 Various improvements by Robbbert.
7
8 Todo:
9 - Fix cpu and system problems that prevent the games from working fully.
10 - RS232 port
11 - Sound ports 1,2 do not sound anything like the real thing
12 - Sound port 3 (noise channel)
13 - Sound dac port (mostly works but is the wrong speed in some places).
14 dac pitch is controlled by how often TIM1_INT occurs. This same
15 interrupt also controls the seconds countdown in some games, such as
16 Quiz Wiz and Scrabble. Currently this countdown goes twice as fast
17 as it should. If the INT is slowed down to compensate, the dac sound
18 is so slow as to be unintelligible. Need to find a way to keep both happy.
19 - System seems slower than it should. Probably wrong cycle count in the CPU.
20 What we have there is a guess as the real info has not been found.
21 -speed 1.2 makes the sound more natural
22 -speed 1.7 if TIM1_INT is slowed to fix the countdown.
23
24 Game Status:
25 - Inbuilt ROM and PDA functions all work
26 - Due to an irritating message, the NVRAM is commented out in the machine config
27 - All carts appear to work, from my limited testing.
28 -- indy500 skips some speech just before the trial race starts.
29
30 ***************************************************************************/
31
32 #include "emu.h"
33 #include "includes/gamecom.h"
34
35 #include "screen.h"
36 #include "softlist.h"
37 #include "speaker.h"
38
39 #include "gamecom.lh"
40
41
gamecom_mem_map(address_map & map)42 void gamecom_state::gamecom_mem_map(address_map &map)
43 {
44 map(0x0000, 0x0013).ram().region("maincpu", 0x00);
45 map(0x0014, 0x0017).rw(FUNC(gamecom_state::gamecom_pio_r), FUNC(gamecom_state::gamecom_pio_w)); // buttons
46 map(0x0018, 0x001F).ram().region("maincpu", 0x18);
47 map(0x0020, 0x007F).rw(FUNC(gamecom_state::gamecom_internal_r), FUNC(gamecom_state::gamecom_internal_w));/* CPU internal register file */
48 map(0x0080, 0x03FF).ram().region("maincpu", 0x80); /* RAM */
49 map(0x0400, 0x0FFF).noprw(); /* Nothing */
50 map(0x1000, 0x1FFF).rom(); /* Internal ROM (initially), or External ROM/Flash. Controlled by MMU0 (never swapped out in game.com) */
51 map(0x2000, 0x3FFF).bankr("bank1"); /* External ROM/Flash. Controlled by MMU1 */
52 map(0x4000, 0x5FFF).bankr("bank2"); /* External ROM/Flash. Controlled by MMU2 */
53 map(0x6000, 0x7FFF).bankr("bank3"); /* External ROM/Flash. Controlled by MMU3 */
54 map(0x8000, 0x9FFF).bankr("bank4"); /* External ROM/Flash. Controlled by MMU4 */
55 map(0xA000, 0xDFFF).writeonly().share("videoram").nopr(); /* VRAM - writeonly, returns 0 on read, as expected by lostwrld */
56 map(0xE000, 0xFFFF).ram().share("nvram"); /* Extended I/O, Extended RAM */
57 }
58
59 static INPUT_PORTS_START( gamecom )
60 PORT_START("IN0")
61 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME( "Up" )
62 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME( "Down" )
63 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME( "Left" )
64 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME( "Right" )
PORT_CODE(KEYCODE_M)65 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME( "Menu" ) PORT_CODE( KEYCODE_M )
66 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME( DEF_STR(Pause) ) PORT_CODE( KEYCODE_V )
67 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME( "Sound" ) PORT_CODE( KEYCODE_S )
68 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME( "Button A" ) PORT_CODE( KEYCODE_A ) PORT_CODE( KEYCODE_LCONTROL )
69
70 PORT_START("IN1")
71 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME( "Button B" ) PORT_CODE( KEYCODE_B ) PORT_CODE( KEYCODE_LALT )
72 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME( "Button C" ) PORT_CODE( KEYCODE_C ) PORT_CODE( KEYCODE_SPACE )
73
74 PORT_START("IN2")
75 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME( "Reset" ) PORT_CODE( KEYCODE_N )
76 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME( "Button D" ) PORT_CODE( KEYCODE_D ) PORT_CODE( KEYCODE_LSHIFT )
77 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME( "Stylus press" ) PORT_CODE( KEYCODE_Z ) PORT_CODE( MOUSECODE_BUTTON1 )
78
79 // These are used by the "Default Grid" artwork to detect mouse clicks
80 PORT_START("GRID.0")
81 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
82 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
83 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
84 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
85 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
86 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
87 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
88 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
89 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
90 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
91
92 PORT_START("GRID.1")
93 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
94 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
95 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
96 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
97 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
98 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
99 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
100 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
101 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
102 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
103
104 PORT_START("GRID.2")
105 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
106 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
107 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
108 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
109 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
110 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
111 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
112 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
113 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
114 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
115
116 PORT_START("GRID.3")
117 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
118 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
119 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
120 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
121 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
122 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
123 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
124 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
125 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
126 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
127
128 PORT_START("GRID.4")
129 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
130 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
131 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
132 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
133 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
134 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
135 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
136 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
137 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
138 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
139
140 PORT_START("GRID.5")
141 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
142 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
143 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
144 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
145 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
146 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
147 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
148 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
149 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
150 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
151
152 PORT_START("GRID.6")
153 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
154 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
155 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
156 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
157 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
158 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
159 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
160 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
161 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
162 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
163
164 PORT_START("GRID.7")
165 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
166 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
167 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
168 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
169 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
170 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
171 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
172 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
173 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
174 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
175
176 PORT_START("GRID.8")
177 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
178 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
179 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
180 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
181 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
182 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
183 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
184 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
185 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
186 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
187
188 PORT_START("GRID.9")
189 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
190 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
191 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
192 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
193 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
194 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
195 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
196 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
197 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
198 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
199
200 PORT_START("GRID.10")
201 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
202 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
203 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
204 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
205 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
206 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
207 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
208 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
209 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
210 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
211
212 PORT_START("GRID.11")
213 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
214 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
215 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
216 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
217 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
218 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
219 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
220 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
221 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
222 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
223
224 PORT_START("GRID.12")
225 PORT_BIT( 0x001, IP_ACTIVE_HIGH, IPT_OTHER)
226 PORT_BIT( 0x002, IP_ACTIVE_HIGH, IPT_OTHER)
227 PORT_BIT( 0x004, IP_ACTIVE_HIGH, IPT_OTHER)
228 PORT_BIT( 0x008, IP_ACTIVE_HIGH, IPT_OTHER)
229 PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_OTHER)
230 PORT_BIT( 0x020, IP_ACTIVE_HIGH, IPT_OTHER)
231 PORT_BIT( 0x040, IP_ACTIVE_HIGH, IPT_OTHER)
232 PORT_BIT( 0x080, IP_ACTIVE_HIGH, IPT_OTHER)
233 PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OTHER)
234 PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OTHER)
235 INPUT_PORTS_END
236
237 void gamecom_state::gamecom_palette(palette_device &palette) const
238 {
239 palette.set_pen_color(0, 0x00, 0x00, 0x00); // Black
240 palette.set_pen_color(1, 0x0f, 0x4f, 0x2f); // Gray 1
241 palette.set_pen_color(2, 0x6f, 0x8f, 0x4f); // Gray 2
242 palette.set_pen_color(3, 0x8f, 0xcf, 0x8f); // Grey 3
243 palette.set_pen_color(4, 0xdf, 0xff, 0x8f); // White
244 }
245
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)246 uint32_t gamecom_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
247 {
248 copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
249 return 0;
250 }
251
INTERRUPT_GEN_MEMBER(gamecom_state::gamecom_interrupt)252 INTERRUPT_GEN_MEMBER(gamecom_state::gamecom_interrupt)
253 {
254 m_maincpu->set_input_line(sm8500_cpu_device::LCDC_INT, ASSERT_LINE );
255 }
256
gamecom(machine_config & config)257 void gamecom_state::gamecom(machine_config &config)
258 {
259 /* basic machine hardware */
260 SM8500(config, m_maincpu, XTAL(11'059'200)/2); /* actually it's an sm8521 microcontroller containing an sm8500 cpu */
261 m_maincpu->set_addrmap(AS_PROGRAM, &gamecom_state::gamecom_mem_map);
262 m_maincpu->dma_cb().set(FUNC(gamecom_state::gamecom_handle_dma));
263 m_maincpu->timer_cb().set(FUNC(gamecom_state::gamecom_update_timers));
264 m_maincpu->set_vblank_int("screen", FUNC(gamecom_state::gamecom_interrupt));
265
266 config.set_maximum_quantum(attotime::from_hz(60));
267
268 //NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
269
270 /* video hardware */
271 SCREEN(config, m_screen, SCREEN_TYPE_LCD);
272 m_screen->set_refresh_hz(59.732155);
273 m_screen->set_vblank_time(500);
274 m_screen->set_screen_update(FUNC(gamecom_state::screen_update));
275 m_screen->set_size(200, 160);
276 m_screen->set_visarea_full();
277 m_screen->set_palette("palette");
278
279 config.set_default_layout(layout_gamecom);
280 PALETTE(config, "palette", FUNC(gamecom_state::gamecom_palette), 5);
281
282 /* sound hardware */
283 SPEAKER(config, "speaker").front_center();
284 /* TODO: much more complex than this */
285 DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC (Digital audio)
286 DAC_4BIT_R2R(config, m_dac0, 0).add_route(ALL_OUTPUTS, "speaker", 0.05); // unknown DAC (Frequency modulation)
287 DAC_4BIT_R2R(config, m_dac1, 0).add_route(ALL_OUTPUTS, "speaker", 0.05); // unknown DAC (Frequency modulation)
288
289 /* cartridge */
290 GENERIC_CARTSLOT(config, "cartslot1", generic_linear_slot, "gamecom_cart", "bin,tgc").set_device_load(FUNC(gamecom_state::cart1_load));
291 GENERIC_CARTSLOT(config, "cartslot2", generic_linear_slot, "gamecom_cart", "bin,tgc").set_device_load(FUNC(gamecom_state::cart2_load));
292 SOFTWARE_LIST(config, "cart_list").set_original("gamecom");
293 }
294
295 ROM_START( gamecom )
296 ROM_REGION( 0x2000, "maincpu", 0 )
297 ROM_LOAD( "internal.bin", 0x1000, 0x1000, CRC(a0cec361) SHA1(03368237e8fed4a8724f3b4a1596cf4b17c96d33) )
298
299 ROM_REGION( 0x40000, "kernel", 0 )
300 ROM_LOAD( "external.bin", 0x00000, 0x40000, CRC(e235a589) SHA1(97f782e72d738f4d7b861363266bf46b438d9b50) )
301 ROM_END
302
303 // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
304 CONS( 1997, gamecom, 0, 0, gamecom, gamecom, gamecom_state, init_gamecom, "Tiger", "Game.com", MACHINE_IMPERFECT_SOUND | MACHINE_CLICKABLE_ARTWORK)
305