1 // license:BSD-3-Clause
2 // copyright-holders:Uki
3 /*****************************************************************************
4 
5 Dr. Micro (c) 1983 Sanritsu
6 
7         driver by Uki
8 
9 Quite similar to Appoooh
10 
11 *****************************************************************************/
12 
13 #include "emu.h"
14 #include "includes/drmicro.h"
15 
16 #include "cpu/z80/z80.h"
17 #include "sound/msm5205.h"
18 #include "sound/sn76496.h"
19 #include "screen.h"
20 #include "speaker.h"
21 
22 #define MCLK 18432000
23 
24 
25 /*************************************
26  *
27  *  Memory handlers
28  *
29  *************************************/
30 
INTERRUPT_GEN_MEMBER(drmicro_state::drmicro_interrupt)31 INTERRUPT_GEN_MEMBER(drmicro_state::drmicro_interrupt)
32 {
33 	if (m_nmi_enable)
34 		device.execute().pulse_input_line(INPUT_LINE_NMI, attotime::zero);
35 }
36 
nmi_enable_w(uint8_t data)37 void drmicro_state::nmi_enable_w(uint8_t data)
38 {
39 	m_nmi_enable = data & 1;
40 	m_flipscreen = (data & 2) ? 1 : 0;
41 	flip_screen_set(data & 2);
42 
43 	// bit2,3 unknown
44 }
45 
46 
WRITE_LINE_MEMBER(drmicro_state::pcm_w)47 WRITE_LINE_MEMBER(drmicro_state::pcm_w)
48 {
49 	uint8_t *PCM = memregion("adpcm")->base();
50 
51 	int data = PCM[m_pcm_adr / 2];
52 
53 	if (data != 0x70) // ??
54 	{
55 		if (~m_pcm_adr & 1)
56 			data >>= 4;
57 
58 		m_msm->data_w(data & 0x0f);
59 		m_msm->reset_w(0);
60 
61 		m_pcm_adr = (m_pcm_adr + 1) & 0x7fff;
62 	}
63 	else
64 		m_msm->reset_w(1);
65 }
66 
pcm_set_w(uint8_t data)67 void drmicro_state::pcm_set_w(uint8_t data)
68 {
69 	m_pcm_adr = ((data & 0x3f) << 9);
70 	pcm_w(1);
71 }
72 
73 /*************************************
74  *
75  *  Address maps
76  *
77  *************************************/
78 
drmicro_map(address_map & map)79 void drmicro_state::drmicro_map(address_map &map)
80 {
81 	map(0x0000, 0xbfff).rom();
82 	map(0xc000, 0xdfff).ram();
83 	map(0xe000, 0xefff).ram().w(FUNC(drmicro_state::drmicro_videoram_w));
84 	map(0xf000, 0xffff).ram();
85 }
86 
io_map(address_map & map)87 void drmicro_state::io_map(address_map &map)
88 {
89 	map.global_mask(0xff);
90 	map(0x00, 0x00).portr("P1").w("sn1", FUNC(sn76496_device::write));
91 	map(0x01, 0x01).portr("P2").w("sn2", FUNC(sn76496_device::write));
92 	map(0x02, 0x02).w("sn3", FUNC(sn76496_device::write));
93 	map(0x03, 0x03).portr("DSW1").w(FUNC(drmicro_state::pcm_set_w));
94 	map(0x04, 0x04).portr("DSW2").w(FUNC(drmicro_state::nmi_enable_w));
95 	map(0x05, 0x05).noprw(); // unused? / watchdog?
96 }
97 
98 /*************************************
99  *
100  *  Input ports
101  *
102  *************************************/
103 
104 static INPUT_PORTS_START( drmicro )
105 	PORT_START("P1")
106 	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
107 	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SERVICE1 )
108 	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN1 )
109 	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 )
110 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_4WAY
111 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_4WAY
112 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_4WAY
113 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_4WAY
114 
115 	PORT_START("P2")
116 	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
117 	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_START2 )
118 	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 )
119 	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
120 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_PLAYER(2)
121 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(2)
122 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_PLAYER(2)
123 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(2)
124 
125 	PORT_START("DSW1")
126 	PORT_DIPNAME( 0x03, 0x01, DEF_STR( Lives ) )        PORT_DIPLOCATION("SW1:!1,!2")
127 	PORT_DIPSETTING(    0x00, "2" )
128 	PORT_DIPSETTING(    0x01, "3" )
129 	PORT_DIPSETTING(    0x02, "4" )
130 	PORT_DIPSETTING(    0x03, "5" )
131 	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Demo_Sounds ) )  PORT_DIPLOCATION("SW1:!3")
132 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
133 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
134 	PORT_DIPNAME( 0x18, 0x08, DEF_STR( Bonus_Life ) )   PORT_DIPLOCATION("SW1:!4,!5")
135 	PORT_DIPSETTING(    0x00, "30000 100000" )
136 	PORT_DIPSETTING(    0x08, "50000 150000" )
137 	PORT_DIPSETTING(    0x10, "70000 200000" )
138 	PORT_DIPSETTING(    0x18, "100000 300000" )
139 	PORT_SERVICE_DIPLOC(  0x20, IP_ACTIVE_HIGH, "SW1:!6" )  /* Service Mode shows as "X" */
140 	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Cabinet ) )      PORT_DIPLOCATION("SW1:!7")
141 	PORT_DIPSETTING(    0x40, DEF_STR( Upright ) )
142 	PORT_DIPSETTING(    0x00, DEF_STR( Cocktail ) )
143 	PORT_DIPNAME( 0x80, 0x00, DEF_STR( Flip_Screen ) )  PORT_DIPLOCATION("SW1:!8")
144 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
145 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
146 
147 	PORT_START("DSW2")
148 	PORT_DIPNAME( 0x07, 0x00, DEF_STR( Coinage ) )      PORT_DIPLOCATION("SW2:!1,!2,!3")
149 	PORT_DIPSETTING(    0x07, DEF_STR( 4C_1C ) )
150 	PORT_DIPSETTING(    0x06, DEF_STR( 3C_1C ) )
151 	PORT_DIPSETTING(    0x05, DEF_STR( 2C_1C ) )
152 	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ) )
153 	PORT_DIPSETTING(    0x01, DEF_STR( 1C_2C ) )
154 	PORT_DIPSETTING(    0x02, DEF_STR( 1C_3C ) )
155 	PORT_DIPSETTING(    0x03, DEF_STR( 1C_4C ) )
156 	PORT_DIPSETTING(    0x04, DEF_STR( 1C_5C ) )
157 	PORT_DIPUNUSED_DIPLOC( 0x08, IP_ACTIVE_HIGH, "SW2:!4" ) /* Service Mode shows as "X" */
158 	PORT_DIPUNUSED_DIPLOC( 0x10, IP_ACTIVE_HIGH, "SW2:!5" ) /* Service Mode shows as "X" */
159 	PORT_DIPUNUSED_DIPLOC( 0x20, IP_ACTIVE_HIGH, "SW2:!6" ) /* Service Mode shows as "X" */
160 	PORT_DIPUNUSED_DIPLOC( 0x40, IP_ACTIVE_HIGH, "SW2:!7" ) /* Service Mode shows as "X" */
161 	PORT_DIPUNUSED_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SW2:!8" ) /* Service Mode shows as "X" */
162 INPUT_PORTS_END
163 
164 /*************************************
165  *
166  *  Graphics definitions
167  *
168  *************************************/
169 
170 static const gfx_layout spritelayout4 =
171 {
172 	16,16,
173 	0x100,
174 	2,
175 	{0,0x2000*8},
176 	{STEP8(7,-1),STEP8(71,-1)},
177 	{STEP8(0,8),STEP8(128,8)},
178 	8*8*4
179 };
180 
181 static const gfx_layout spritelayout8 =
182 {
183 	16,16,
184 	0x100,
185 	3,
186 	{0x2000*16,0x2000*8,0},
187 	{STEP8(7,-1),STEP8(71,-1)},
188 	{STEP8(0,8),STEP8(128,8)},
189 	8*8*4
190 };
191 
192 static const gfx_layout charlayout4 =
193 {
194 	8,8,
195 	0x400,
196 	2,
197 	{0,0x2000*8},
198 	{STEP8(7,-1)},
199 	{STEP8(0,8)},
200 	8*8*1
201 };
202 
203 static const gfx_layout charlayout8 =
204 {
205 	8,8,
206 	0x400,
207 	3,
208 	{0x2000*16,0x2000*8,0},
209 	{STEP8(7,-1)},
210 	{STEP8(0,8)},
211 	8*8*1
212 };
213 
214 static GFXDECODE_START( gfx_drmicro )
215 	GFXDECODE_ENTRY( "gfx1", 0x0000, charlayout4,     0, 64 ) /* tiles */
216 	GFXDECODE_ENTRY( "gfx2", 0x0000, charlayout8,   256, 32 ) /* tiles */
217 	GFXDECODE_ENTRY( "gfx1", 0x0000, spritelayout4,   0, 64 ) /* sprites */
218 	GFXDECODE_ENTRY( "gfx2", 0x0000, spritelayout8, 256, 32 ) /* sprites */
219 GFXDECODE_END
220 
221 
222 /*************************************
223  *
224  *  Machine driver
225  *
226  *************************************/
227 
machine_start()228 void drmicro_state::machine_start()
229 {
230 	save_item(NAME(m_nmi_enable));
231 	save_item(NAME(m_pcm_adr));
232 	save_item(NAME(m_flipscreen));
233 }
234 
machine_reset()235 void drmicro_state::machine_reset()
236 {
237 	m_nmi_enable = 0;
238 	m_pcm_adr = 0;
239 	m_flipscreen = 0;
240 }
241 
242 
drmicro(machine_config & config)243 void drmicro_state::drmicro(machine_config &config)
244 {
245 	/* basic machine hardware */
246 	Z80(config, m_maincpu, MCLK/6); /* 3.072MHz? */
247 	m_maincpu->set_addrmap(AS_PROGRAM, &drmicro_state::drmicro_map);
248 	m_maincpu->set_addrmap(AS_IO, &drmicro_state::io_map);
249 	m_maincpu->set_vblank_int("screen", FUNC(drmicro_state::drmicro_interrupt));
250 
251 	config.set_maximum_quantum(attotime::from_hz(60));
252 
253 	/* video hardware */
254 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
255 	screen.set_refresh_hz(60);
256 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
257 	screen.set_size(32*8, 32*8);
258 	screen.set_visarea(0*8, 32*8-1, 2*8, 30*8-1);
259 	screen.set_screen_update(FUNC(drmicro_state::screen_update_drmicro));
260 	screen.set_palette(m_palette);
261 
262 	GFXDECODE(config, m_gfxdecode, m_palette, gfx_drmicro);
263 	PALETTE(config, m_palette, FUNC(drmicro_state::drmicro_palette), 512, 32);
264 
265 	/* sound hardware */
266 	SPEAKER(config, "mono").front_center();
267 
268 	SN76496(config, "sn1", MCLK/4).add_route(ALL_OUTPUTS, "mono", 0.50);
269 	SN76496(config, "sn2", MCLK/4).add_route(ALL_OUTPUTS, "mono", 0.50);
270 	SN76496(config, "sn3", MCLK/4).add_route(ALL_OUTPUTS, "mono", 0.50);
271 
272 	MSM5205(config, m_msm, 384000);
273 	m_msm->vck_legacy_callback().set(FUNC(drmicro_state::pcm_w));   /* IRQ handler */
274 	m_msm->set_prescaler_selector(msm5205_device::S64_4B);  /* 6 KHz */
275 	m_msm->add_route(ALL_OUTPUTS, "mono", 0.75);
276 }
277 
278 /*************************************
279  *
280  *  ROM definition(s)
281  *
282  *************************************/
283 
284 ROM_START( drmicro )
285 	ROM_REGION( 0x10000, "maincpu", 0 ) // CPU
286 	ROM_LOAD( "dm-00.13b", 0x0000,  0x2000, CRC(270f2145) SHA1(1557428387e2c0f711c676a13a763c8d48aa497b) )
287 	ROM_LOAD( "dm-01.14b", 0x2000,  0x2000, CRC(bba30c80) SHA1(a084429fad58fa6348936084652235d5f55e3b89) )
288 	ROM_LOAD( "dm-02.15b", 0x4000,  0x2000, CRC(d9e4ca6b) SHA1(9fb6d1d6b45628891deae389cf1d142332b110ba) )
289 	ROM_LOAD( "dm-03.13d", 0x6000,  0x2000, CRC(b7bcb45b) SHA1(61035afc642bac2e1c56c36c188bed4e1949523f) )
290 	ROM_LOAD( "dm-04.14d", 0x8000,  0x2000, CRC(071db054) SHA1(75929b7692bebf2246fa84581b6d1eedb02c9aba) )
291 	ROM_LOAD( "dm-05.15d", 0xa000,  0x2000, CRC(f41b8d8a) SHA1(802830f3f0362ec3df257f31dc22390e8ae4207c) )
292 
293 	ROM_REGION( 0x04000, "gfx1", 0 ) // gfx 1
294 	ROM_LOAD( "dm-23.5l",  0x0000,  0x2000, CRC(279a76b8) SHA1(635650621bdce5873bb5faf64f8352149314e784) )
295 	ROM_LOAD( "dm-24.5n",  0x2000,  0x2000, CRC(ee8ed1ec) SHA1(7afc05c73186af9fe3d3f3ce13412c8ee560b146) )
296 
297 	ROM_REGION( 0x06000, "gfx2", 0 ) // gfx 2
298 	ROM_LOAD( "dm-20.4a",  0x0000,  0x2000, CRC(6f5dbf22) SHA1(41ef084336e2ebb1016b28505dcb43483e37a0de) )
299 	ROM_LOAD( "dm-21.4c",  0x2000,  0x2000, CRC(8b17ff47) SHA1(5bcc14489ea1d4f1fe8e51c24a72a8e787ab8159) )
300 	ROM_LOAD( "dm-22.4d",  0x4000,  0x2000, CRC(84daf771) SHA1(d187debcca59ceab6cd696be246370120ee575c6) )
301 
302 	ROM_REGION( 0x04000, "adpcm", 0 ) // samples
303 	ROM_LOAD( "dm-40.12m",  0x0000,  0x2000, CRC(3d080af9) SHA1(f9527fae69fe3ca0762024ac4a44b1f02fbee66a) )
304 	ROM_LOAD( "dm-41.13m",  0x2000,  0x2000, CRC(ddd7bda2) SHA1(bbe9276cb47fa3e82081d592522640e04b4a9223) )
305 
306 	ROM_REGION( 0x00220, "proms", 0 ) // PROMs
307 	ROM_LOAD( "dm-62.9h", 0x0000,  0x0020, CRC(e3e36eaf) SHA1(5954400190e587a20cad60f5829f4bddc85ea526) )
308 	ROM_LOAD( "dm-61.4m", 0x0020,  0x0100, CRC(0dd8e365) SHA1(cbd43a2d4af053860932af32ca5e13bef728e38a) )
309 	ROM_LOAD( "dm-60.6e", 0x0120,  0x0100, CRC(540a3953) SHA1(bc65388a1019dadf8c71705e234763f5c735e282) )
310 ROM_END
311 
312 
313 /*************************************
314  *
315  *  Game driver(s)
316  *
317  *************************************/
318 
319 GAME( 1983, drmicro, 0, drmicro, drmicro, drmicro_state, empty_init, ROT270, "Sanritsu", "Dr. Micro", MACHINE_SUPPORTS_SAVE )
320